Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(212)

Side by Side Diff: chrome/browser/chromeos/login/managed/supervised_user_authentication.cc

Issue 393343002: Rename "managed (mode|user)" to "supervised user" (part 7) (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: more alphabetize (and rebase again) Created 6 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
(Empty)
1 // Copyright 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "chrome/browser/chromeos/login/managed/supervised_user_authentication.h "
6
7 #include "base/base64.h"
8 #include "base/json/json_file_value_serializer.h"
9 #include "base/macros.h"
10 #include "base/metrics/histogram.h"
11 #include "base/strings/string_number_conversions.h"
12 #include "base/strings/string_util.h"
13 #include "base/threading/sequenced_worker_pool.h"
14 #include "chrome/browser/chromeos/login/managed/locally_managed_user_constants.h "
15 #include "chrome/browser/chromeos/login/users/supervised_user_manager.h"
16 #include "chrome/browser/chromeos/login/users/user.h"
17 #include "chrome/browser/chromeos/login/users/user_manager.h"
18 #include "chrome/browser/chromeos/profiles/profile_helper.h"
19 #include "chromeos/cryptohome/signed_secret.pb.h"
20 #include "chromeos/login/auth/key.h"
21 #include "content/public/browser/browser_thread.h"
22 #include "crypto/hmac.h"
23 #include "crypto/random.h"
24 #include "crypto/symmetric_key.h"
25
26 namespace chromeos {
27
28 namespace {
29
30 // Byte size of hash salt.
31 const unsigned kSaltSize = 32;
32
33 // Size of key signature.
34 const unsigned kHMACKeySizeInBits = 256;
35 const int kSignatureLength = 32;
36
37 // Size of master key (in bytes).
38 const int kMasterKeySize = 32;
39
40 std::string CreateSalt() {
41 char result[kSaltSize];
42 crypto::RandBytes(&result, sizeof(result));
43 return StringToLowerASCII(base::HexEncode(
44 reinterpret_cast<const void*>(result),
45 sizeof(result)));
46 }
47
48 std::string BuildRawHMACKey() {
49 scoped_ptr<crypto::SymmetricKey> key(crypto::SymmetricKey::GenerateRandomKey(
50 crypto::SymmetricKey::AES, kHMACKeySizeInBits));
51 std::string raw_result, result;
52 key->GetRawKey(&raw_result);
53 base::Base64Encode(raw_result, &result);
54 return result;
55 }
56
57 base::DictionaryValue* LoadPasswordData(base::FilePath profile_dir) {
58 JSONFileValueSerializer serializer(profile_dir.Append(kPasswordUpdateFile));
59 std::string error_message;
60 int error_code = JSONFileValueSerializer::JSON_NO_ERROR;
61 scoped_ptr<base::Value> value(
62 serializer.Deserialize(&error_code, &error_message));
63 if (JSONFileValueSerializer::JSON_NO_ERROR != error_code) {
64 LOG(ERROR) << "Could not deserialize password data, error = " << error_code
65 << " / " << error_message;
66 return NULL;
67 }
68 base::DictionaryValue* result;
69 if (!value->GetAsDictionary(&result)) {
70 LOG(ERROR) << "Stored password data is not a dictionary";
71 return NULL;
72 }
73 ignore_result(value.release());
74 return result;
75 }
76
77 void OnPasswordDataLoaded(
78 const SupervisedUserAuthentication::PasswordDataCallback& success_callback,
79 const base::Closure& failure_callback,
80 base::DictionaryValue* value) {
81 if (!value) {
82 failure_callback.Run();
83 return;
84 }
85 success_callback.Run(value);
86 delete value;
87 }
88
89 } // namespace
90
91 SupervisedUserAuthentication::SupervisedUserAuthentication(
92 SupervisedUserManager* owner)
93 : owner_(owner),
94 stable_schema_(SCHEMA_SALT_HASHED) {
95 }
96
97 SupervisedUserAuthentication::~SupervisedUserAuthentication() {}
98
99 SupervisedUserAuthentication::Schema
100 SupervisedUserAuthentication::GetStableSchema() {
101 return stable_schema_;
102 }
103
104 UserContext SupervisedUserAuthentication::TransformKey(
105 const UserContext& context) {
106 UserContext result = context;
107 int user_schema = GetPasswordSchema(context.GetUserID());
108 if (user_schema == SCHEMA_PLAIN)
109 return result;
110
111 if (user_schema == SCHEMA_SALT_HASHED) {
112 base::DictionaryValue holder;
113 std::string salt;
114 owner_->GetPasswordInformation(context.GetUserID(), &holder);
115 holder.GetStringWithoutPathExpansion(kSalt, &salt);
116 DCHECK(!salt.empty());
117 Key* const key = result.GetKey();
118 key->Transform(Key::KEY_TYPE_SALTED_PBKDF2_AES256_1234, salt);
119 key->SetLabel(kCryptohomeSupervisedUserKeyLabel);
120 result.SetIsUsingOAuth(false);
121 return result;
122 }
123 NOTREACHED() << "Unknown password schema for " << context.GetUserID();
124 return context;
125 }
126
127 bool SupervisedUserAuthentication::FillDataForNewUser(
128 const std::string& user_id,
129 const std::string& password,
130 base::DictionaryValue* password_data,
131 base::DictionaryValue* extra_data) {
132 Schema schema = stable_schema_;
133 if (schema == SCHEMA_PLAIN)
134 return false;
135
136 if (schema == SCHEMA_SALT_HASHED) {
137 password_data->SetIntegerWithoutPathExpansion(kSchemaVersion, schema);
138 std::string salt = CreateSalt();
139 password_data->SetStringWithoutPathExpansion(kSalt, salt);
140 int revision = kMinPasswordRevision;
141 password_data->SetIntegerWithoutPathExpansion(kPasswordRevision, revision);
142 Key key(password);
143 key.Transform(Key::KEY_TYPE_SALTED_PBKDF2_AES256_1234, salt);
144 const std::string salted_password = key.GetSecret();
145 const std::string base64_signature_key = BuildRawHMACKey();
146 const std::string base64_signature =
147 BuildPasswordSignature(salted_password, revision, base64_signature_key);
148 password_data->SetStringWithoutPathExpansion(kEncryptedPassword,
149 salted_password);
150 password_data->SetStringWithoutPathExpansion(kPasswordSignature,
151 base64_signature);
152
153 extra_data->SetStringWithoutPathExpansion(kPasswordEncryptionKey,
154 BuildRawHMACKey());
155 extra_data->SetStringWithoutPathExpansion(kPasswordSignatureKey,
156 base64_signature_key);
157 return true;
158 }
159 NOTREACHED();
160 return false;
161 }
162
163 std::string SupervisedUserAuthentication::GenerateMasterKey() {
164 char master_key_bytes[kMasterKeySize];
165 crypto::RandBytes(&master_key_bytes, sizeof(master_key_bytes));
166 return StringToLowerASCII(
167 base::HexEncode(reinterpret_cast<const void*>(master_key_bytes),
168 sizeof(master_key_bytes)));
169 }
170
171 void SupervisedUserAuthentication::StorePasswordData(
172 const std::string& user_id,
173 const base::DictionaryValue& password_data) {
174 base::DictionaryValue holder;
175 owner_->GetPasswordInformation(user_id, &holder);
176 const base::Value* value;
177 if (password_data.GetWithoutPathExpansion(kSchemaVersion, &value))
178 holder.SetWithoutPathExpansion(kSchemaVersion, value->DeepCopy());
179 if (password_data.GetWithoutPathExpansion(kSalt, &value))
180 holder.SetWithoutPathExpansion(kSalt, value->DeepCopy());
181 if (password_data.GetWithoutPathExpansion(kPasswordRevision, &value))
182 holder.SetWithoutPathExpansion(kPasswordRevision, value->DeepCopy());
183 owner_->SetPasswordInformation(user_id, &holder);
184 }
185
186 SupervisedUserAuthentication::Schema
187 SupervisedUserAuthentication::GetPasswordSchema(
188 const std::string& user_id) {
189 base::DictionaryValue holder;
190
191 owner_->GetPasswordInformation(user_id, &holder);
192 // Default version.
193 int schema_version_index;
194 Schema schema_version = SCHEMA_PLAIN;
195 if (holder.GetIntegerWithoutPathExpansion(kSchemaVersion,
196 &schema_version_index)) {
197 schema_version = static_cast<Schema>(schema_version_index);
198 }
199 return schema_version;
200 }
201
202 bool SupervisedUserAuthentication::NeedPasswordChange(
203 const std::string& user_id,
204 const base::DictionaryValue* password_data) {
205 base::DictionaryValue local;
206 owner_->GetPasswordInformation(user_id, &local);
207 int local_schema = SCHEMA_PLAIN;
208 int local_revision = kMinPasswordRevision;
209 int updated_schema = SCHEMA_PLAIN;
210 int updated_revision = kMinPasswordRevision;
211 local.GetIntegerWithoutPathExpansion(kSchemaVersion, &local_schema);
212 local.GetIntegerWithoutPathExpansion(kPasswordRevision, &local_revision);
213 password_data->GetIntegerWithoutPathExpansion(kSchemaVersion,
214 &updated_schema);
215 password_data->GetIntegerWithoutPathExpansion(kPasswordRevision,
216 &updated_revision);
217 if (updated_schema > local_schema)
218 return true;
219 DCHECK_EQ(updated_schema, local_schema);
220 return updated_revision > local_revision;
221 }
222
223 void SupervisedUserAuthentication::ScheduleSupervisedPasswordChange(
224 const std::string& supervised_user_id,
225 const base::DictionaryValue* password_data) {
226 const User* user = UserManager::Get()->FindUser(supervised_user_id);
227 base::FilePath profile_path = ProfileHelper::GetProfilePathByUserIdHash(
228 user->username_hash());
229 JSONFileValueSerializer serializer(profile_path.Append(kPasswordUpdateFile));
230 if (!serializer.Serialize(*password_data)) {
231 LOG(ERROR) << "Failed to schedule password update for supervised user "
232 << supervised_user_id;
233 UMA_HISTOGRAM_ENUMERATION(
234 "ManagedUsers.ChromeOS.PasswordChange",
235 SupervisedUserAuthentication::PASSWORD_CHANGE_FAILED_STORE_DATA,
236 SupervisedUserAuthentication::PASSWORD_CHANGE_RESULT_MAX_VALUE);
237 return;
238 }
239 base::DictionaryValue holder;
240 owner_->GetPasswordInformation(supervised_user_id, &holder);
241 holder.SetBoolean(kRequirePasswordUpdate, true);
242 owner_->SetPasswordInformation(supervised_user_id, &holder);
243 }
244
245 bool SupervisedUserAuthentication::HasScheduledPasswordUpdate(
246 const std::string& user_id) {
247 base::DictionaryValue holder;
248 owner_->GetPasswordInformation(user_id, &holder);
249 bool require_update = false;
250 holder.GetBoolean(kRequirePasswordUpdate, &require_update);
251 return require_update;
252 }
253
254 void SupervisedUserAuthentication::ClearScheduledPasswordUpdate(
255 const std::string& user_id) {
256 base::DictionaryValue holder;
257 owner_->GetPasswordInformation(user_id, &holder);
258 holder.SetBoolean(kRequirePasswordUpdate, false);
259 owner_->SetPasswordInformation(user_id, &holder);
260 }
261
262 bool SupervisedUserAuthentication::HasIncompleteKey(
263 const std::string& user_id) {
264 base::DictionaryValue holder;
265 owner_->GetPasswordInformation(user_id, &holder);
266 bool incomplete_key = false;
267 holder.GetBoolean(kHasIncompleteKey, &incomplete_key);
268 return incomplete_key;
269 }
270
271 void SupervisedUserAuthentication::MarkKeyIncomplete(const std::string& user_id,
272 bool incomplete) {
273 base::DictionaryValue holder;
274 owner_->GetPasswordInformation(user_id, &holder);
275 holder.SetBoolean(kHasIncompleteKey, incomplete);
276 owner_->SetPasswordInformation(user_id, &holder);
277 }
278
279 void SupervisedUserAuthentication::LoadPasswordUpdateData(
280 const std::string& user_id,
281 const PasswordDataCallback& success_callback,
282 const base::Closure& failure_callback) {
283 const User* user = UserManager::Get()->FindUser(user_id);
284 base::FilePath profile_path =
285 ProfileHelper::GetProfilePathByUserIdHash(user->username_hash());
286 PostTaskAndReplyWithResult(
287 content::BrowserThread::GetBlockingPool(),
288 FROM_HERE,
289 base::Bind(&LoadPasswordData, profile_path),
290 base::Bind(&OnPasswordDataLoaded, success_callback, failure_callback));
291 }
292
293 std::string SupervisedUserAuthentication::BuildPasswordSignature(
294 const std::string& password,
295 int revision,
296 const std::string& base64_signature_key) {
297 ac::chrome::managedaccounts::account::Secret secret;
298 secret.set_revision(revision);
299 secret.set_secret(password);
300 std::string buffer;
301 if (!secret.SerializeToString(&buffer))
302 LOG(FATAL) << "Protobuf::SerializeToString failed";
303 std::string signature_key;
304 base::Base64Decode(base64_signature_key, &signature_key);
305
306 crypto::HMAC hmac(crypto::HMAC::SHA256);
307 if (!hmac.Init(signature_key))
308 LOG(FATAL) << "HMAC::Init failed";
309
310 unsigned char out_bytes[kSignatureLength];
311 if (!hmac.Sign(buffer, out_bytes, sizeof(out_bytes)))
312 LOG(FATAL) << "HMAC::Sign failed";
313
314 std::string raw_result(out_bytes, out_bytes + sizeof(out_bytes));
315
316 std::string result;
317 base::Base64Encode(raw_result, &result);
318 return result;
319 }
320
321 } // namespace chromeos
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698