diff options
Diffstat (limited to 'install_attributes')
-rw-r--r-- | install_attributes/libinstallattributes.cc | 82 | ||||
-rw-r--r-- | install_attributes/libinstallattributes.h | 66 | ||||
-rw-r--r-- | install_attributes/mock_install_attributes_reader.cc | 22 | ||||
-rw-r--r-- | install_attributes/mock_install_attributes_reader.h | 19 | ||||
-rw-r--r-- | install_attributes/tests/consumer.pb | 1 | ||||
-rw-r--r-- | install_attributes/tests/corrupt.pb | 0 | ||||
-rw-r--r-- | install_attributes/tests/libinstallattributes_unittest.cc | 83 | ||||
-rw-r--r-- | install_attributes/tests/managed.pb | bin | 0 -> 211 bytes |
8 files changed, 273 insertions, 0 deletions
diff --git a/install_attributes/libinstallattributes.cc b/install_attributes/libinstallattributes.cc new file mode 100644 index 0000000..52f9f70 --- /dev/null +++ b/install_attributes/libinstallattributes.cc @@ -0,0 +1,82 @@ +// Copyright 2016 The Chromium OS Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "libinstallattributes.h" + +#include <base/files/file_util.h> +#include <base/logging.h> + +#include "bindings/install_attributes.pb.h" + +namespace { + +// Written by cryptohome or by lockbox-cache after signature verification and +// thus guaranteed to be unadulterated. +const char kInstallAttributesPath[] = "/run/lockbox/install_attributes.pb"; + +} // namespace + +// The source of truth for these constants is Chromium +// //chrome/browser/chromeos/settings/install_attributes.cc. +const char InstallAttributesReader::kAttrMode[] = "enterprise.mode"; +const char InstallAttributesReader::kDeviceModeConsumer[] = "consumer"; +const char InstallAttributesReader::kDeviceModeEnterprise[] = "enterprise"; +const char InstallAttributesReader::kDeviceModeEnterpriseAD[] = "enterprise_ad"; +const char InstallAttributesReader::kDeviceModeLegacyRetail[] = "kiosk"; +const char InstallAttributesReader::kDeviceModeConsumerKiosk[] = + "consumer_kiosk"; + +InstallAttributesReader::InstallAttributesReader() + : install_attributes_path_(kInstallAttributesPath) { +} + +InstallAttributesReader::~InstallAttributesReader() { +} + +const std::string& InstallAttributesReader::GetAttribute( + const std::string& key) { + // By its very nature of immutable attributes, once read successfully the + // attributes can never change and thus never need reloading. + if (!initialized_) { + TryToLoad(); + } + + const auto entry = attributes_.find(key); + if (entry == attributes_.end()) { + return empty_string_; + } + return entry->second; +} + +bool InstallAttributesReader::IsLocked() { + if (!initialized_) { + TryToLoad(); + } + return initialized_; +} + +void InstallAttributesReader::TryToLoad() { + std::string contents; + if (!base::ReadFileToString(install_attributes_path_, &contents)) { + // May fail during OOBE or early in the boot process. + return; + } + + // Parse errors are unrecoverable (lockbox does atomic write), thus mark as + // inititialized already before checking for parse errors. + initialized_ = true; + + cryptohome::SerializedInstallAttributes install_attributes; + if (!install_attributes.ParseFromString(contents)) { + LOG(ERROR) << "Can't parse install attributes."; + return; + } + + for (int i = 0; i < install_attributes.attributes_size(); ++i) { + const cryptohome::SerializedInstallAttributes_Attribute& attribute = + install_attributes.attributes(i); + // Cast value to C string and back to remove trailing zero. + attributes_[attribute.name()] = std::string(attribute.value().c_str()); + } +} diff --git a/install_attributes/libinstallattributes.h b/install_attributes/libinstallattributes.h new file mode 100644 index 0000000..b947156 --- /dev/null +++ b/install_attributes/libinstallattributes.h @@ -0,0 +1,66 @@ +// Copyright 2016 The Chromium OS Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef LIBBRILLO_INSTALL_ATTRIBUTES_LIBINSTALLATTRIBUTES_H_ +#define LIBBRILLO_INSTALL_ATTRIBUTES_LIBINSTALLATTRIBUTES_H_ + +#include <map> +#include <string> + +#include <base/files/file_path.h> +#include <brillo/brillo_export.h> + +// Simple caching reader for the (verified) install attributes, a TPM-backed +// write once read many store. Install attributes may be written exactly once +// by a single, atomic write-and-lock operation encompassing zero or more +// attributes. Once locked, install attributes cannot be re-written unless TPM +// is reset (eg. by powerwashing the device). +class BRILLO_EXPORT InstallAttributesReader { + public: + static const char kAttrMode[]; + + // Constants for the possible device modes. + static const char kDeviceModeConsumer[]; + static const char kDeviceModeEnterprise[]; + static const char kDeviceModeEnterpriseAD[]; + static const char kDeviceModeLegacyRetail[]; + static const char kDeviceModeConsumerKiosk[]; + + InstallAttributesReader(); + virtual ~InstallAttributesReader(); + + // Try to load install attributes (unless cached already) and return the + // attribute for |key| or an empty string in case |key| doesn't exist or in + // case install attributes couldn't (yet) be loaded. The latter is expected + // during OOBE (install attributes haven't yet been finalized) or early in the + // boot sequence (install attributes haven't yet been verified). + const std::string& GetAttribute(const std::string& key); + + // Try to load install attributes (unless cached already) and return whether + // they have yet been written-and-locked. + bool IsLocked(); + + protected: + // Attributes cache. + std::map<std::string, std::string> attributes_; + + // Path to the *verified* install attributes file on disk. + base::FilePath install_attributes_path_; + + // Whether install attributes have been read successfully. Reading a file + // containing an empty attributes proto indicates consumer mode and counts as + // successful, too. + bool initialized_ = false; + +private: + // Try to load the verified install attributes from disk. This is expected to + // fail when install attributes haven't yet been finalized (OOBE) or verified + // (early in the boot sequence). + void TryToLoad(); + + // Empty string to return on error. + std::string empty_string_; +}; + +#endif // LIBBRILLO_LIBINSTALLATTRIBUTES_H_ diff --git a/install_attributes/mock_install_attributes_reader.cc b/install_attributes/mock_install_attributes_reader.cc new file mode 100644 index 0000000..da18988 --- /dev/null +++ b/install_attributes/mock_install_attributes_reader.cc @@ -0,0 +1,22 @@ +// Copyright 2016 The Chromium OS Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "mock_install_attributes_reader.h" + +MockInstallAttributesReader::MockInstallAttributesReader( + const cryptohome::SerializedInstallAttributes& install_attributes) { + for (int i = 0; i < install_attributes.attributes_size(); ++i) { + const cryptohome::SerializedInstallAttributes_Attribute& attribute = + install_attributes.attributes(i); + // Cast value to C string and back to remove trailing zero. + attributes_[attribute.name()] = std::string(attribute.value().c_str()); + } + initialized_ = true; +} + +MockInstallAttributesReader::MockInstallAttributesReader( + const std::string& device_mode, bool initialized) { + attributes_[kAttrMode] = device_mode; + initialized_ = initialized; +} diff --git a/install_attributes/mock_install_attributes_reader.h b/install_attributes/mock_install_attributes_reader.h new file mode 100644 index 0000000..5ccee02 --- /dev/null +++ b/install_attributes/mock_install_attributes_reader.h @@ -0,0 +1,19 @@ +// Copyright 2016 The Chromium OS Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef LIBBRILLO_INSTALL_ATTRIBUTES_MOCK_INSTALL_ATTRIBUTES_READER_H_ +#define LIBBRILLO_INSTALL_ATTRIBUTES_MOCK_INSTALL_ATTRIBUTES_READER_H_ + +#include "libinstallattributes.h" + +#include "bindings/install_attributes.pb.h" + +class MockInstallAttributesReader : public InstallAttributesReader { + public: + explicit MockInstallAttributesReader( + const cryptohome::SerializedInstallAttributes& install_attributes); + MockInstallAttributesReader(const std::string& device_mode, bool initialized); +}; + +#endif // LIBBRILLO_INSTALL_ATTRIBUTES_MOCK_INSTALL_ATTRIBUTES_READER_H_ diff --git a/install_attributes/tests/consumer.pb b/install_attributes/tests/consumer.pb new file mode 100644 index 0000000..e19a122 --- /dev/null +++ b/install_attributes/tests/consumer.pb @@ -0,0 +1 @@ +
\ No newline at end of file diff --git a/install_attributes/tests/corrupt.pb b/install_attributes/tests/corrupt.pb new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/install_attributes/tests/corrupt.pb diff --git a/install_attributes/tests/libinstallattributes_unittest.cc b/install_attributes/tests/libinstallattributes_unittest.cc new file mode 100644 index 0000000..45ff827 --- /dev/null +++ b/install_attributes/tests/libinstallattributes_unittest.cc @@ -0,0 +1,83 @@ +// Copyright (c) 2012 The Chromium OS Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "install_attributes/libinstallattributes.h" + +#include <string> + +#include <gtest/gtest.h> + +// Allows to override the install attributes path while preserving all the +// functionality of the original class. +class MockInstallAttributesReader : public InstallAttributesReader { + public: + void SetPath(const std::string& filename) { + install_attributes_path_ = base::FilePath(filename); + } + size_t GetAttributesCount() const { return attributes_.size(); } +}; + +TEST(InstallAttributesTest, ReadNonexistingAttributes) { + MockInstallAttributesReader reader; + reader.SetPath("non-existing.pb"); + ASSERT_FALSE(reader.IsLocked()); + ASSERT_EQ(0, reader.GetAttributesCount()); +} + +// corrupt.pb is an invalid proto. +TEST(InstallAttributesTest, ReadCorruptAttributes) { + MockInstallAttributesReader reader; + reader.SetPath("install_attributes/tests/corrupt.pb"); + ASSERT_TRUE(reader.IsLocked()); + ASSERT_EQ(0, reader.GetAttributesCount()); +} + +// consumer.pb is a valid proto containing no attributes. +TEST(InstallAttributesTest, ReadEmptyAttributes) { + MockInstallAttributesReader reader; + reader.SetPath("install_attributes/tests/consumer.pb"); + ASSERT_TRUE(reader.IsLocked()); + ASSERT_EQ(0, reader.GetAttributesCount()); +} + +// managed.pb is a valid proto containing the usual enterprise enrollment +// attributes. +TEST(InstallAttributesTest, ReadManagedAttributes) { + MockInstallAttributesReader reader; + reader.SetPath("install_attributes/tests/managed.pb"); + ASSERT_TRUE(reader.IsLocked()); + ASSERT_EQ(std::string(), reader.GetAttribute("non-existing")); + ASSERT_EQ("enterprise", reader.GetAttribute("enterprise.mode")); +} + +// Going from non-existing attributes file to existing attributes file must +// work, i.e. the non-existence of the attributes file must not be cached. +TEST(InstallAttributesTest, ProgressionFromNonExistingToManaged) { + MockInstallAttributesReader reader; + reader.SetPath("non-existing.pb"); + ASSERT_FALSE(reader.IsLocked()); + ASSERT_EQ(0, reader.GetAttributesCount()); + + reader.SetPath("install_attributes/tests/managed.pb"); + ASSERT_TRUE(reader.IsLocked()); + ASSERT_EQ("enterprise", reader.GetAttribute("enterprise.mode")); +} + +// Going from empty attributes file to non-empty attributes file must not work, +// i.e. the non-existence of the attributes must be cached. +TEST(InstallAttributesTest, NoProgressionFromEmptyToManaged) { + MockInstallAttributesReader reader; + reader.SetPath("install_attributes/tests/consumer.pb"); + ASSERT_TRUE(reader.IsLocked()); + ASSERT_EQ(0, reader.GetAttributesCount()); + + reader.SetPath("install_attributes/tests/managed.pb"); + ASSERT_TRUE(reader.IsLocked()); + ASSERT_EQ(std::string(), reader.GetAttribute("enterprise.mode")); +} + +int main(int argc, char* argv[]) { + ::testing::InitGoogleTest(&argc, argv); + return RUN_ALL_TESTS(); +} diff --git a/install_attributes/tests/managed.pb b/install_attributes/tests/managed.pb Binary files differnew file mode 100644 index 0000000..4060a49 --- /dev/null +++ b/install_attributes/tests/managed.pb |