buffet_config.cc revision e709fa7586dfd3fb8fd41cede0cd5dbc39b31acb
1// Copyright 2015 The Android Open Source Project 2// 3// Licensed under the Apache License, Version 2.0 (the "License"); 4// you may not use this file except in compliance with the License. 5// You may obtain a copy of the License at 6// 7// http://www.apache.org/licenses/LICENSE-2.0 8// 9// Unless required by applicable law or agreed to in writing, software 10// distributed under the License is distributed on an "AS IS" BASIS, 11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12// See the License for the specific language governing permissions and 13// limitations under the License. 14 15#include "buffet/buffet_config.h" 16 17#include <map> 18#include <set> 19 20#include <base/files/file_util.h> 21#include <base/files/important_file_writer.h> 22#include <base/logging.h> 23#include <base/message_loop/message_loop.h> 24#include <base/strings/string_number_conversions.h> 25#include <brillo/errors/error.h> 26#include <brillo/errors/error_codes.h> 27#include <brillo/osrelease_reader.h> 28#include <brillo/strings/string_utils.h> 29#include <weave/enum_to_string.h> 30 31namespace buffet { 32 33namespace { 34 35const char kErrorDomain[] = "buffet"; 36const char kFileReadError[] = "file_read_error"; 37const char kProductVersionKey[] = "product_version"; 38 39class DefaultFileIO : public BuffetConfig::FileIO { 40 public: 41 bool ReadFile(const base::FilePath& path, std::string* content) override { 42 return base::ReadFileToString(path, content); 43 } 44 bool WriteFile(const base::FilePath& path, 45 const std::string& content) override { 46 return base::ImportantFileWriter::WriteFileAtomically(path, content); 47 } 48}; 49 50} // namespace 51 52namespace config_keys { 53 54const char kClientId[] = "client_id"; 55const char kClientSecret[] = "client_secret"; 56const char kApiKey[] = "api_key"; 57const char kOAuthURL[] = "oauth_url"; 58const char kServiceURL[] = "service_url"; 59const char kName[] = "name"; 60const char kDescription[] = "description"; 61const char kLocation[] = "location"; 62const char kLocalAnonymousAccessRole[] = "local_anonymous_access_role"; 63const char kLocalDiscoveryEnabled[] = "local_discovery_enabled"; 64const char kLocalPairingEnabled[] = "local_pairing_enabled"; 65const char kOemName[] = "oem_name"; 66const char kModelName[] = "model_name"; 67const char kModelId[] = "model_id"; 68const char kWifiAutoSetupEnabled[] = "wifi_auto_setup_enabled"; 69const char kEmbeddedCode[] = "embedded_code"; 70const char kPairingModes[] = "pairing_modes"; 71 72} // namespace config_keys 73 74BuffetConfig::BuffetConfig(const Options& options) 75 : options_(options), 76 default_encryptor_(Encryptor::CreateDefaultEncryptor()), 77 encryptor_(default_encryptor_.get()), 78 default_file_io_(new DefaultFileIO), 79 file_io_(default_file_io_.get()) {} 80 81bool BuffetConfig::LoadDefaults(weave::Settings* settings) { 82 // Keep this hardcoded default for sometime. This previously was set by 83 // libweave. It should be set by overlay's buffet.conf. 84 // Keys owners: avakulenko, gene, vitalybuka. 85 settings->client_id = 86 "338428340000-vkb4p6h40c7kja1k3l70kke8t615cjit.apps.googleusercontent." 87 "com"; 88 settings->client_secret = "LS_iPYo_WIOE0m2VnLdduhnx"; 89 settings->api_key = "AIzaSyACK3oZtmIylUKXiTMqkZqfuRiCgQmQSAQ"; 90 91 settings->name = "Developer device"; 92 settings->oem_name = "Chromium"; 93 settings->model_name = "Brillo"; 94 settings->model_id = "AAAAA"; 95 96 if (!base::PathExists(options_.defaults)) 97 return true; // Nothing to load. 98 99 brillo::KeyValueStore store; 100 if (!store.Load(options_.defaults)) 101 return false; 102 bool result = LoadDefaults(store, settings); 103 settings->disable_security = options_.disable_security; 104 settings->test_privet_ssid = options_.test_privet_ssid; 105 106 if (!options_.client_id.empty()) 107 settings->client_id = options_.client_id; 108 if (!options_.client_secret.empty()) 109 settings->client_secret = options_.client_secret; 110 if (!options_.api_key.empty()) 111 settings->api_key = options_.api_key; 112 if (!options_.oauth_url.empty()) 113 settings->oauth_url = options_.oauth_url; 114 if (!options_.service_url.empty()) 115 settings->service_url = options_.service_url; 116 117 return result; 118} 119 120bool BuffetConfig::LoadDefaults(const brillo::KeyValueStore& store, 121 weave::Settings* settings) { 122 store.GetString(config_keys::kClientId, &settings->client_id); 123 store.GetString(config_keys::kClientSecret, &settings->client_secret); 124 store.GetString(config_keys::kApiKey, &settings->api_key); 125 store.GetString(config_keys::kOAuthURL, &settings->oauth_url); 126 store.GetString(config_keys::kServiceURL, &settings->service_url); 127 store.GetString(config_keys::kOemName, &settings->oem_name); 128 store.GetString(config_keys::kModelName, &settings->model_name); 129 store.GetString(config_keys::kModelId, &settings->model_id); 130 131 brillo::OsReleaseReader reader; 132 reader.Load(); 133 if (!reader.GetString(kProductVersionKey, &settings->firmware_version)) { 134 LOG(ERROR) << "Could not read '" << kProductVersionKey << "' from OS"; 135 } 136 137 store.GetBoolean(config_keys::kWifiAutoSetupEnabled, 138 &settings->wifi_auto_setup_enabled); 139 store.GetString(config_keys::kEmbeddedCode, &settings->embedded_code); 140 141 std::string modes_str; 142 if (store.GetString(config_keys::kPairingModes, &modes_str)) { 143 std::set<weave::PairingType> pairing_modes; 144 for (const std::string& mode : 145 brillo::string_utils::Split(modes_str, ",", true, true)) { 146 weave::PairingType pairing_mode; 147 if (!StringToEnum(mode, &pairing_mode)) 148 return false; 149 pairing_modes.insert(pairing_mode); 150 } 151 settings->pairing_modes = std::move(pairing_modes); 152 } 153 154 store.GetString(config_keys::kName, &settings->name); 155 store.GetString(config_keys::kDescription, &settings->description); 156 store.GetString(config_keys::kLocation, &settings->location); 157 158 std::string role_str; 159 if (store.GetString(config_keys::kLocalAnonymousAccessRole, &role_str)) { 160 if (!StringToEnum(role_str, &settings->local_anonymous_access_role)) 161 return false; 162 } 163 store.GetBoolean(config_keys::kLocalDiscoveryEnabled, 164 &settings->local_discovery_enabled); 165 store.GetBoolean(config_keys::kLocalPairingEnabled, 166 &settings->local_pairing_enabled); 167 return true; 168} 169 170std::string BuffetConfig::LoadSettings(const std::string& name) { 171 std::string settings_blob; 172 base::FilePath path = CreatePath(name); 173 if (!file_io_->ReadFile(path, &settings_blob)) { 174 LOG(WARNING) << "Failed to read \'" + path.value() + 175 "\', proceeding with empty settings."; 176 return std::string(); 177 } 178 std::string json_string; 179 if (!encryptor_->DecryptWithAuthentication(settings_blob, &json_string)) { 180 LOG(WARNING) 181 << "Failed to decrypt settings, proceeding with empty settings."; 182 SaveSettings(std::string(), name, {}); 183 return std::string(); 184 } 185 return json_string; 186} 187 188std::string BuffetConfig::LoadSettings() { 189 return LoadSettings(""); 190} 191 192void BuffetConfig::SaveSettings(const std::string& name, 193 const std::string& settings, 194 const weave::DoneCallback& callback) { 195 std::string encrypted_settings; 196 weave::ErrorPtr error; 197 base::FilePath path = CreatePath(name); 198 if (!encryptor_->EncryptWithAuthentication(settings, &encrypted_settings)) { 199 weave::Error::AddTo(&error, FROM_HERE, "file_write_error", 200 "Failed to encrypt settings."); 201 encrypted_settings.clear(); 202 } 203 if (!file_io_->WriteFile(path, encrypted_settings)) { 204 weave::Error::AddTo(&error, FROM_HERE, "file_write_error", 205 "Failed to write \'" + path.value() + 206 "\', proceeding with empty settings."); 207 } 208 if (!callback.is_null()) { 209 base::MessageLoop::current()->PostTask( 210 FROM_HERE, base::Bind(callback, base::Passed(&error))); 211 } 212} 213 214base::FilePath BuffetConfig::CreatePath(const std::string& name) const { 215 return name.empty() ? options_.settings 216 : options_.settings.InsertBeforeExtension( 217 base::FilePath::kExtensionSeparator + name); 218} 219 220bool BuffetConfig::LoadFile(const base::FilePath& file_path, 221 std::string* data, 222 brillo::ErrorPtr* error) { 223 if (!file_io_->ReadFile(file_path, data)) { 224 brillo::errors::system::AddSystemError(error, FROM_HERE, errno); 225 brillo::Error::AddToPrintf(error, FROM_HERE, kErrorDomain, kFileReadError, 226 "Failed to read file '%s'", 227 file_path.value().c_str()); 228 return false; 229 } 230 return true; 231} 232 233} // namespace buffet 234