AU: Don't allow stateful /etc/lsb-release override in normal boot mode...

... on official images except for the release track.

BUG=chromium-os:6244
TEST=unit tests, tested on device

Change-Id: I2d2a634c7b5ac7dd4619f52d1f79b6d88c359e46

Review URL: http://codereview.chromium.org/6225001
diff --git a/omaha_request_params.cc b/omaha_request_params.cc
index eaff3d3..ed80060 100644
--- a/omaha_request_params.cc
+++ b/omaha_request_params.cc
@@ -38,27 +38,29 @@
 static const char kHWIDPath[] = "/sys/devices/platform/chromeos_acpi/HWID";
 
 OmahaRequestDeviceParams::OmahaRequestDeviceParams() :
-    force_build_type_(false),
-    forced_official_build_(false) {}
+    force_lock_down_(false),
+    forced_lock_down_(false) {}
 
 bool OmahaRequestDeviceParams::Init(const std::string& in_app_version,
                                     const std::string& in_update_url) {
+  bool stateful_override = !ShouldLockDown();
   os_platform = OmahaRequestParams::kOsPlatform;
   os_version = OmahaRequestParams::kOsVersion;
   app_version = in_app_version.empty() ?
-      GetLsbValue("CHROMEOS_RELEASE_VERSION", "", NULL, true) : in_app_version;
+      GetLsbValue("CHROMEOS_RELEASE_VERSION", "", NULL, stateful_override) :
+      in_app_version;
   os_sp = app_version + "_" + GetMachineType();
-  os_board = GetLsbValue("CHROMEOS_RELEASE_BOARD", "", NULL, true);
+  os_board = GetLsbValue("CHROMEOS_RELEASE_BOARD", "", NULL, stateful_override);
   app_id = GetLsbValue("CHROMEOS_RELEASE_APPID",
                        OmahaRequestParams::kAppId,
                        NULL,
-                       true);
+                       stateful_override);
   app_lang = "en-US";
   app_track = GetLsbValue(
       kUpdateTrackKey,
       "",
       &chromeos_update_engine::OmahaRequestDeviceParams::IsValidTrack,
-      true);
+      true);  // stateful_override
   hardware_class = GetHardwareClass();
   struct stat stbuf;
 
@@ -81,15 +83,15 @@
   const string rootfs_track = GetLsbValue(
       kUpdateTrackKey,
       "",
-      &chromeos_update_engine::OmahaRequestDeviceParams::IsValidTrack,
-      false);
+      NULL,  // No need to validate the read-only rootfs track.
+      false);  // stateful_override
   delta_okay = delta_okay && rootfs_track == app_track;
 
   update_url = in_update_url.empty() ?
       GetLsbValue("CHROMEOS_AUSERVER",
                   OmahaRequestParams::kUpdateUrl,
                   NULL,
-                  true) :
+                  stateful_override) :
       in_update_url;
   return true;
 }
@@ -173,8 +175,11 @@
   return hwid;
 }
 
-bool OmahaRequestDeviceParams::IsOfficialBuild() const {
-  return force_build_type_ ? forced_official_build_ : utils::IsOfficialBuild();
+bool OmahaRequestDeviceParams::ShouldLockDown() const {
+  if (force_lock_down_) {
+    return forced_lock_down_;
+  }
+  return utils::IsOfficialBuild() && utils::IsNormalBootMode();
 }
 
 bool OmahaRequestDeviceParams::IsValidTrack(const std::string& track) const {
@@ -183,7 +188,7 @@
     "beta-channel",
     "dev-channel",
   };
-  if (!IsOfficialBuild()) {
+  if (!ShouldLockDown()) {
     return true;
   }
   for (size_t t = 0; t < arraysize(kValidTracks); ++t) {
@@ -194,9 +199,9 @@
   return false;
 }
 
-void OmahaRequestDeviceParams::SetBuildTypeOfficial(bool is_official) {
-  force_build_type_ = true;
-  forced_official_build_ = is_official;
+void OmahaRequestDeviceParams::SetLockDown(bool lock) {
+  force_lock_down_ = true;
+  forced_lock_down_ = lock;
 }
 
 }  // namespace chromeos_update_engine
diff --git a/omaha_request_params.h b/omaha_request_params.h
index 075ed3f..7864370 100644
--- a/omaha_request_params.h
+++ b/omaha_request_params.h
@@ -86,19 +86,23 @@
   // For unit-tests.
   void set_root(const std::string& root) { root_ = root; }
 
-  // Force build type for testing purposes.
-  void SetBuildTypeOfficial(bool is_official);
+  // Enforce security mode for testing purposes.
+  void SetLockDown(bool lock);
 
  private:
   FRIEND_TEST(OmahaRequestDeviceParamsTest, IsValidTrackTest);
+  FRIEND_TEST(OmahaRequestDeviceParamsTest, ShouldLockDownTest);
 
   // Use a validator that is a non-static member of this class so that its
   // inputs can be mocked in unit tests (e.g., build type for IsValidTrack).
   typedef bool(OmahaRequestDeviceParams::*ValueValidator)(
       const std::string&) const;
 
-  // Returns true if this is an official build, false otherwise.
-  bool IsOfficialBuild() const;
+  // Returns true if parameter values should be locked down for security
+  // reasons. If this is an official build running in normal boot mode, all
+  // values except the release track are parsed only from the read-only rootfs
+  // partition and the track values are restricted to a pre-approved set.
+  bool ShouldLockDown() const;
 
   // Returns true if |track| is a valid track, false otherwise. This method
   // restricts the track value only if the image is official (see
@@ -124,9 +128,9 @@
   // When reading files, prepend root_ to the paths. Useful for testing.
   std::string root_;
 
-  // Force build type for testing purposes.
-  bool force_build_type_;
-  bool forced_official_build_;
+  // Force security lock down for testing purposes.
+  bool force_lock_down_;
+  bool forced_lock_down_;
 
   DISALLOW_COPY_AND_ASSIGN(OmahaRequestDeviceParams);
 };
diff --git a/omaha_request_params_unittest.cc b/omaha_request_params_unittest.cc
index fdbf96e..8f2d7c8 100644
--- a/omaha_request_params_unittest.cc
+++ b/omaha_request_params_unittest.cc
@@ -29,7 +29,7 @@
     ASSERT_EQ(0, System(string("mkdir -p ") + kTestDir +
                         utils::kStatefulPartition + "/etc"));
     params_.set_root(string("./") + kTestDir);
-    params_.SetBuildTypeOfficial(false);
+    params_.SetLockDown(false);
   }
 
   virtual void TearDown() {
@@ -264,7 +264,7 @@
       kTestDir + utils::kStatefulPartition + "/etc/lsb-release",
       "CHROMEOS_RELEASE_BOARD=x86-generic\n"
       "CHROMEOS_RELEASE_TRACK=bartrack\n"
-      "CHROMEOS_AUSERVER=http://www.google.com"));
+      "CHROMEOS_AUSERVER=https://www.google.com"));
   OmahaRequestParams out;
   EXPECT_TRUE(DoTest(&out, "", ""));
   EXPECT_EQ("Chrome OS", out.os_platform);
@@ -276,7 +276,32 @@
   EXPECT_EQ("", out.hardware_class);
   EXPECT_FALSE(out.delta_okay);
   EXPECT_EQ("bartrack", out.app_track);
-  EXPECT_EQ("http://www.google.com", out.update_url);
+  EXPECT_EQ("https://www.google.com", out.update_url);
+}
+
+TEST_F(OmahaRequestDeviceParamsTest, OverrideLockDownTest) {
+  ASSERT_TRUE(WriteFileString(
+      kTestDir + "/etc/lsb-release",
+      "CHROMEOS_RELEASE_BOARD=arm-generic\n"
+      "CHROMEOS_RELEASE_FOO=bar\n"
+      "CHROMEOS_RELEASE_VERSION=0.2.2.3\n"
+      "CHROMEOS_RELEASE_TRACK=footrack\n"
+      "CHROMEOS_AUSERVER=https://www.google.com"));
+  ASSERT_TRUE(WriteFileString(
+      kTestDir + utils::kStatefulPartition + "/etc/lsb-release",
+      "CHROMEOS_RELEASE_BOARD=x86-generic\n"
+      "CHROMEOS_RELEASE_TRACK=dev-channel\n"
+      "CHROMEOS_AUSERVER=http://www.google.com"));
+  params_.SetLockDown(true);
+  OmahaRequestParams out;
+  EXPECT_TRUE(DoTest(&out, "", ""));
+  EXPECT_EQ("arm-generic", out.os_board);
+  EXPECT_EQ("{87efface-864d-49a5-9bb3-4b050a7c227a}", out.app_id);
+  EXPECT_EQ("0.2.2.3", out.app_version);
+  EXPECT_EQ("", out.hardware_class);
+  EXPECT_FALSE(out.delta_okay);
+  EXPECT_EQ("dev-channel", out.app_track);
+  EXPECT_EQ("https://www.google.com", out.update_url);
 }
 
 TEST_F(OmahaRequestDeviceParamsTest, OverrideSameTrackTest) {
@@ -293,12 +318,9 @@
       "CHROMEOS_RELEASE_TRACK=footrack"));
   OmahaRequestParams out;
   EXPECT_TRUE(DoTest(&out, "", ""));
-  EXPECT_EQ("Chrome OS", out.os_platform);
-  EXPECT_EQ(string("0.2.2.3_") + GetMachineType(), out.os_sp);
   EXPECT_EQ("x86-generic", out.os_board);
   EXPECT_EQ("{87efface-864d-49a5-9bb3-4b050a7c227a}", out.app_id);
   EXPECT_EQ("0.2.2.3", out.app_version);
-  EXPECT_EQ("en-US", out.app_lang);
   EXPECT_EQ("", out.hardware_class);
   EXPECT_TRUE(out.delta_okay);
   EXPECT_EQ("footrack", out.app_track);
@@ -316,7 +338,7 @@
   {
     OmahaRequestDeviceParams params;
     params.set_root(string("./") + kTestDir);
-    params.SetBuildTypeOfficial(false);
+    params.SetLockDown(false);
     EXPECT_TRUE(params.Init("", ""));
     params.SetTrack("zootrack");
   }
@@ -341,7 +363,7 @@
   {
     OmahaRequestDeviceParams params;
     params.set_root(string("./") + kTestDir);
-    params.SetBuildTypeOfficial(false);
+    params.SetLockDown(false);
     EXPECT_TRUE(params.Init("", ""));
     params.SetTrack("zootrack");
   }
@@ -362,7 +384,7 @@
   {
     OmahaRequestDeviceParams params;
     params.set_root(string("./") + kTestDir);
-    params.SetBuildTypeOfficial(true);
+    params.SetLockDown(true);
     EXPECT_TRUE(params.Init("", ""));
     params.SetTrack("zootrack");
   }
@@ -373,13 +395,13 @@
 }
 
 TEST_F(OmahaRequestDeviceParamsTest, IsValidTrackTest) {
-  params_.SetBuildTypeOfficial(true);
+  params_.SetLockDown(true);
   EXPECT_TRUE(params_.IsValidTrack("canary-channel"));
   EXPECT_TRUE(params_.IsValidTrack("beta-channel"));
   EXPECT_TRUE(params_.IsValidTrack("dev-channel"));
   EXPECT_FALSE(params_.IsValidTrack("some-channel"));
   EXPECT_FALSE(params_.IsValidTrack(""));
-  params_.SetBuildTypeOfficial(false);
+  params_.SetLockDown(false);
   EXPECT_TRUE(params_.IsValidTrack("canary-channel"));
   EXPECT_TRUE(params_.IsValidTrack("beta-channel"));
   EXPECT_TRUE(params_.IsValidTrack("dev-channel"));
@@ -387,29 +409,6 @@
   EXPECT_TRUE(params_.IsValidTrack(""));
 }
 
-TEST_F(OmahaRequestDeviceParamsTest, InvalidTrackTest) {
-  ASSERT_TRUE(WriteFileString(
-      kTestDir + "/etc/lsb-release",
-      "CHROMEOS_RELEASE_BOARD=arm-generic\n"
-      "CHROMEOS_RELEASE_FOO=bar\n"
-      "CHROMEOS_RELEASE_VERSION=0.2.2.3\n"
-      "CHROMEOS_RELEASE_TRACK=footrack\n"
-      "CHROMEOS_AUSERVER=http://www.google.com"));
-  params_.SetBuildTypeOfficial(true);
-  OmahaRequestParams out;
-  EXPECT_TRUE(DoTest(&out, "", ""));
-  EXPECT_EQ("Chrome OS", out.os_platform);
-  EXPECT_EQ(string("0.2.2.3_") + GetMachineType(), out.os_sp);
-  EXPECT_EQ("arm-generic", out.os_board);
-  EXPECT_EQ("{87efface-864d-49a5-9bb3-4b050a7c227a}", out.app_id);
-  EXPECT_EQ("0.2.2.3", out.app_version);
-  EXPECT_EQ("en-US", out.app_lang);
-  EXPECT_EQ("", out.hardware_class);
-  EXPECT_TRUE(out.delta_okay);
-  EXPECT_EQ("", out.app_track);
-  EXPECT_EQ("http://www.google.com", out.update_url);
-}
-
 TEST_F(OmahaRequestDeviceParamsTest, ValidTrackTest) {
   ASSERT_TRUE(WriteFileString(
       kTestDir + "/etc/lsb-release",
@@ -418,7 +417,7 @@
       "CHROMEOS_RELEASE_VERSION=0.2.2.3\n"
       "CHROMEOS_RELEASE_TRACK=dev-channel\n"
       "CHROMEOS_AUSERVER=http://www.google.com"));
-  params_.SetBuildTypeOfficial(true);
+  params_.SetLockDown(true);
   OmahaRequestParams out;
   EXPECT_TRUE(DoTest(&out, "", ""));
   EXPECT_EQ("Chrome OS", out.os_platform);
@@ -433,4 +432,8 @@
   EXPECT_EQ("http://www.google.com", out.update_url);
 }
 
+TEST_F(OmahaRequestDeviceParamsTest, ShouldLockDownTest) {
+  EXPECT_FALSE(params_.ShouldLockDown());
+}
+
 }  // namespace chromeos_update_engine