blob: 118e5fa9cddf6bbeddd1e658c4b3101eac7c8a52 [file] [log] [blame]
Vitaly Bukacad20f02015-10-16 17:27:15 -07001// 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.
Vitaly Buka1175a9b2015-08-15 10:42:17 -070014
15#include "buffet/buffet_config.h"
16
Vitaly Bukabecd4612015-08-16 23:31:55 -070017#include <map>
Vitaly Buka1175a9b2015-08-15 10:42:17 -070018#include <set>
19
20#include <base/files/file_util.h>
21#include <base/files/important_file_writer.h>
22#include <base/logging.h>
Vitaly Bukae709fa72016-01-29 16:24:31 -080023#include <base/message_loop/message_loop.h>
Vitaly Buka1175a9b2015-08-15 10:42:17 -070024#include <base/strings/string_number_conversions.h>
Alex Vakulenko41705852015-10-13 10:12:06 -070025#include <brillo/errors/error.h>
26#include <brillo/errors/error_codes.h>
Alex Vakulenko9d448022015-10-30 16:57:43 -070027#include <brillo/osrelease_reader.h>
Alex Vakulenko41705852015-10-13 10:12:06 -070028#include <brillo/strings/string_utils.h>
Vitaly Buka1175a9b2015-08-15 10:42:17 -070029#include <weave/enum_to_string.h>
30
31namespace buffet {
32
Alex Vakulenkodf381642015-10-08 07:34:23 -070033namespace {
34
35const char kErrorDomain[] = "buffet";
36const char kFileReadError[] = "file_read_error";
Alex Vakulenko9d448022015-10-30 16:57:43 -070037const char kProductVersionKey[] = "product_version";
Alex Vakulenkodf381642015-10-08 07:34:23 -070038
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
Vitaly Buka1175a9b2015-08-15 10:42:17 -070052namespace 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";
Vitaly Buka1175a9b2015-08-15 10:42:17 -070068const char kWifiAutoSetupEnabled[] = "wifi_auto_setup_enabled";
Vitaly Buka1175a9b2015-08-15 10:42:17 -070069const char kEmbeddedCode[] = "embedded_code";
70const char kPairingModes[] = "pairing_modes";
71
72} // namespace config_keys
73
Alex Vakulenkodf381642015-10-08 07:34:23 -070074BuffetConfig::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()) {}
Vitaly Buka1175a9b2015-08-15 10:42:17 -070080
81bool BuffetConfig::LoadDefaults(weave::Settings* settings) {
Alex Vakulenko2915a7b2015-10-07 17:04:00 -070082 // Keep this hardcoded default for sometime. This previously was set by
83 // libweave. It should be set by overlay's buffet.conf.
Vitaly Buka74a0c322015-11-20 16:58:00 -080084 // Keys owners: avakulenko, gene, vitalybuka.
Vitaly Buka4de62fa2015-11-17 11:52:48 -080085 settings->client_id =
86 "338428340000-vkb4p6h40c7kja1k3l70kke8t615cjit.apps.googleusercontent."
87 "com";
88 settings->client_secret = "LS_iPYo_WIOE0m2VnLdduhnx";
89 settings->api_key = "AIzaSyACK3oZtmIylUKXiTMqkZqfuRiCgQmQSAQ";
90
Alex Vakulenko0022b752015-10-02 11:09:59 -070091 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))
Vitaly Buka1175a9b2015-08-15 10:42:17 -070097 return true; // Nothing to load.
98
Alex Vakulenko41705852015-10-13 10:12:06 -070099 brillo::KeyValueStore store;
Alex Vakulenko0022b752015-10-02 11:09:59 -0700100 if (!store.Load(options_.defaults))
Vitaly Buka1175a9b2015-08-15 10:42:17 -0700101 return false;
Alex Vakulenko0022b752015-10-02 11:09:59 -0700102 bool result = LoadDefaults(store, settings);
Alex Vakulenko0022b752015-10-02 11:09:59 -0700103 settings->test_privet_ssid = options_.test_privet_ssid;
Vitaly Bukabecd4612015-08-16 23:31:55 -0700104
Alex Vakulenko2915a7b2015-10-07 17:04:00 -0700105 if (!options_.client_id.empty())
106 settings->client_id = options_.client_id;
107 if (!options_.client_secret.empty())
108 settings->client_secret = options_.client_secret;
109 if (!options_.api_key.empty())
110 settings->api_key = options_.api_key;
111 if (!options_.oauth_url.empty())
112 settings->oauth_url = options_.oauth_url;
113 if (!options_.service_url.empty())
114 settings->service_url = options_.service_url;
Vitaly Bukabecd4612015-08-16 23:31:55 -0700115
Vitaly Bukabecd4612015-08-16 23:31:55 -0700116 return result;
117}
118
Alex Vakulenko41705852015-10-13 10:12:06 -0700119bool BuffetConfig::LoadDefaults(const brillo::KeyValueStore& store,
Vitaly Buka1175a9b2015-08-15 10:42:17 -0700120 weave::Settings* settings) {
121 store.GetString(config_keys::kClientId, &settings->client_id);
122 store.GetString(config_keys::kClientSecret, &settings->client_secret);
123 store.GetString(config_keys::kApiKey, &settings->api_key);
124 store.GetString(config_keys::kOAuthURL, &settings->oauth_url);
125 store.GetString(config_keys::kServiceURL, &settings->service_url);
126 store.GetString(config_keys::kOemName, &settings->oem_name);
127 store.GetString(config_keys::kModelName, &settings->model_name);
128 store.GetString(config_keys::kModelId, &settings->model_id);
Vitaly Buka7b9ebee2015-08-16 01:55:41 -0700129
Alex Vakulenko9d448022015-10-30 16:57:43 -0700130 brillo::OsReleaseReader reader;
131 reader.Load();
132 if (!reader.GetString(kProductVersionKey, &settings->firmware_version)) {
133 LOG(ERROR) << "Could not read '" << kProductVersionKey << "' from OS";
Vitaly Buka7b9ebee2015-08-16 01:55:41 -0700134 }
135
Vitaly Buka1175a9b2015-08-15 10:42:17 -0700136 store.GetBoolean(config_keys::kWifiAutoSetupEnabled,
137 &settings->wifi_auto_setup_enabled);
Vitaly Buka1175a9b2015-08-15 10:42:17 -0700138 store.GetString(config_keys::kEmbeddedCode, &settings->embedded_code);
139
140 std::string modes_str;
141 if (store.GetString(config_keys::kPairingModes, &modes_str)) {
142 std::set<weave::PairingType> pairing_modes;
143 for (const std::string& mode :
Alex Vakulenko41705852015-10-13 10:12:06 -0700144 brillo::string_utils::Split(modes_str, ",", true, true)) {
Vitaly Buka1175a9b2015-08-15 10:42:17 -0700145 weave::PairingType pairing_mode;
146 if (!StringToEnum(mode, &pairing_mode))
147 return false;
148 pairing_modes.insert(pairing_mode);
149 }
150 settings->pairing_modes = std::move(pairing_modes);
151 }
152
153 store.GetString(config_keys::kName, &settings->name);
154 store.GetString(config_keys::kDescription, &settings->description);
155 store.GetString(config_keys::kLocation, &settings->location);
Alex Vakulenko0022b752015-10-02 11:09:59 -0700156
157 std::string role_str;
158 if (store.GetString(config_keys::kLocalAnonymousAccessRole, &role_str)) {
159 if (!StringToEnum(role_str, &settings->local_anonymous_access_role))
160 return false;
161 }
Vitaly Buka1175a9b2015-08-15 10:42:17 -0700162 store.GetBoolean(config_keys::kLocalDiscoveryEnabled,
163 &settings->local_discovery_enabled);
164 store.GetBoolean(config_keys::kLocalPairingEnabled,
165 &settings->local_pairing_enabled);
166 return true;
167}
168
Vitaly Bukae709fa72016-01-29 16:24:31 -0800169std::string BuffetConfig::LoadSettings(const std::string& name) {
Alex Vakulenkodf381642015-10-08 07:34:23 -0700170 std::string settings_blob;
Vitaly Bukae709fa72016-01-29 16:24:31 -0800171 base::FilePath path = CreatePath(name);
172 if (!file_io_->ReadFile(path, &settings_blob)) {
173 LOG(WARNING) << "Failed to read \'" + path.value() +
174 "\', proceeding with empty settings.";
Alex Vakulenkodf381642015-10-08 07:34:23 -0700175 return std::string();
176 }
Vitaly Buka1175a9b2015-08-15 10:42:17 -0700177 std::string json_string;
Alex Vakulenkodf381642015-10-08 07:34:23 -0700178 if (!encryptor_->DecryptWithAuthentication(settings_blob, &json_string)) {
179 LOG(WARNING)
180 << "Failed to decrypt settings, proceeding with empty settings.";
Vitaly Bukae709fa72016-01-29 16:24:31 -0800181 SaveSettings(std::string(), name, {});
Alex Vakulenkodf381642015-10-08 07:34:23 -0700182 return std::string();
183 }
Vitaly Buka1175a9b2015-08-15 10:42:17 -0700184 return json_string;
185}
186
Vitaly Bukae709fa72016-01-29 16:24:31 -0800187std::string BuffetConfig::LoadSettings() {
188 return LoadSettings("");
189}
190
191void BuffetConfig::SaveSettings(const std::string& name,
192 const std::string& settings,
193 const weave::DoneCallback& callback) {
Alex Vakulenkodf381642015-10-08 07:34:23 -0700194 std::string encrypted_settings;
Vitaly Bukae709fa72016-01-29 16:24:31 -0800195 weave::ErrorPtr error;
196 base::FilePath path = CreatePath(name);
Alex Vakulenkodf381642015-10-08 07:34:23 -0700197 if (!encryptor_->EncryptWithAuthentication(settings, &encrypted_settings)) {
Vitaly Bukae709fa72016-01-29 16:24:31 -0800198 weave::Error::AddTo(&error, FROM_HERE, "file_write_error",
199 "Failed to encrypt settings.");
Alex Vakulenkodf381642015-10-08 07:34:23 -0700200 encrypted_settings.clear();
201 }
Vitaly Bukae709fa72016-01-29 16:24:31 -0800202 if (!file_io_->WriteFile(path, encrypted_settings)) {
203 weave::Error::AddTo(&error, FROM_HERE, "file_write_error",
204 "Failed to write \'" + path.value() +
205 "\', proceeding with empty settings.");
Alex Vakulenkodf381642015-10-08 07:34:23 -0700206 }
Vitaly Bukae709fa72016-01-29 16:24:31 -0800207 if (!callback.is_null()) {
208 base::MessageLoop::current()->PostTask(
209 FROM_HERE, base::Bind(callback, base::Passed(&error)));
210 }
211}
212
213base::FilePath BuffetConfig::CreatePath(const std::string& name) const {
214 return name.empty() ? options_.settings
215 : options_.settings.InsertBeforeExtension(
216 base::FilePath::kExtensionSeparator + name);
Alex Vakulenkodf381642015-10-08 07:34:23 -0700217}
218
219bool BuffetConfig::LoadFile(const base::FilePath& file_path,
220 std::string* data,
Alex Vakulenko41705852015-10-13 10:12:06 -0700221 brillo::ErrorPtr* error) {
Alex Vakulenkodf381642015-10-08 07:34:23 -0700222 if (!file_io_->ReadFile(file_path, data)) {
Alex Vakulenko41705852015-10-13 10:12:06 -0700223 brillo::errors::system::AddSystemError(error, FROM_HERE, errno);
224 brillo::Error::AddToPrintf(error, FROM_HERE, kErrorDomain, kFileReadError,
Alex Vakulenkodf381642015-10-08 07:34:23 -0700225 "Failed to read file '%s'",
226 file_path.value().c_str());
227 return false;
228 }
229 return true;
Vitaly Buka1175a9b2015-08-15 10:42:17 -0700230}
231
232} // namespace buffet