1 // Copyright 2014 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/users/supervised_user_manager_impl.h"
6 
7 #include <memory>
8 
9 #include "base/bind.h"
10 #include "base/strings/string_util.h"
11 #include "base/strings/stringprintf.h"
12 #include "base/strings/utf_string_conversions.h"
13 #include "base/values.h"
14 #include "chrome/browser/browser_process.h"
15 #include "chrome/browser/chromeos/login/users/chrome_user_manager_impl.h"
16 #include "chrome/browser/chromeos/profiles/profile_helper.h"
17 #include "chrome/browser/supervised_user/supervised_user_service.h"
18 #include "chrome/browser/supervised_user/supervised_user_service_factory.h"
19 #include "chromeos/settings/cros_settings_names.h"
20 #include "components/prefs/pref_registry_simple.h"
21 #include "components/prefs/pref_service.h"
22 #include "components/prefs/scoped_user_pref_update.h"
23 #include "components/user_manager/user_type.h"
24 #include "content/public/browser/browser_thread.h"
25 #include "google_apis/gaia/gaia_auth_util.h"
26 
27 using content::BrowserThread;
28 
29 namespace {
30 
31 // Names for pref keys in Local State.
32 // A map from supervised user local user id to sync user id.
33 const char kSupervisedUserSyncId[] = "ManagedUserSyncId";
34 
35 // A map from supervised user id to manager user id.
36 const char kSupervisedUserManagers[] = "ManagedUserManagers";
37 
38 // A map from supervised user id to manager display name.
39 const char kSupervisedUserManagerNames[] = "ManagedUserManagerNames";
40 
41 // A map from supervised user id to manager display e-mail.
42 const char kSupervisedUserManagerDisplayEmails[] =
43     "ManagedUserManagerDisplayEmails";
44 
45 // A vector pref of the supervised accounts defined on this device, that had
46 // not logged in yet.
47 const char kSupervisedUsersFirstRun[] = "LocallyManagedUsersFirstRun";
48 
49 // A map from user id to password schema id.
50 const char kSupervisedUserPasswordSchema[] = "SupervisedUserPasswordSchema";
51 
52 // A map from user id to password salt.
53 const char kSupervisedUserPasswordSalt[] = "SupervisedUserPasswordSalt";
54 
55 // A map from user id to password revision.
56 const char kSupervisedUserPasswordRevision[] = "SupervisedUserPasswordRevision";
57 
58 // A map from user id to flag indicating if password should be updated upon
59 // signin.
60 const char kSupervisedUserNeedPasswordUpdate[] =
61     "SupervisedUserNeedPasswordUpdate";
62 
63 // A map from user id to flag indicating if cryptohome does not have signature
64 // key.
65 const char kSupervisedUserIncompleteKey[] = "SupervisedUserHasIncompleteKey";
66 
67 }  // namespace
68 
69 namespace chromeos {
70 
71 const char kSchemaVersion[] = "SchemaVersion";
72 const char kPasswordRevision[] = "PasswordRevision";
73 const char kSalt[] = "PasswordSalt";
74 const char kRequirePasswordUpdate[] = "RequirePasswordUpdate";
75 const char kHasIncompleteKey[] = "HasIncompleteKey";
76 
77 // static
RegisterLocalStatePrefs(PrefRegistrySimple * registry)78 void SupervisedUserManager::RegisterLocalStatePrefs(
79     PrefRegistrySimple* registry) {
80   registry->RegisterListPref(kSupervisedUsersFirstRun);
81   registry->RegisterDictionaryPref(kSupervisedUserSyncId);
82   registry->RegisterDictionaryPref(kSupervisedUserManagers);
83   registry->RegisterDictionaryPref(kSupervisedUserManagerNames);
84   registry->RegisterDictionaryPref(kSupervisedUserManagerDisplayEmails);
85 
86   registry->RegisterDictionaryPref(kSupervisedUserPasswordSchema);
87   registry->RegisterDictionaryPref(kSupervisedUserPasswordSalt);
88   registry->RegisterDictionaryPref(kSupervisedUserPasswordRevision);
89 
90   registry->RegisterDictionaryPref(kSupervisedUserNeedPasswordUpdate);
91   registry->RegisterDictionaryPref(kSupervisedUserIncompleteKey);
92 }
93 
SupervisedUserManagerImpl(ChromeUserManagerImpl * owner)94 SupervisedUserManagerImpl::SupervisedUserManagerImpl(
95     ChromeUserManagerImpl* owner)
96     : owner_(owner), cros_settings_(CrosSettings::Get()) {
97   // SupervisedUserManager instance should be used only on UI thread.
98   // (or in unit_tests)
99   if (base::ThreadTaskRunnerHandle::IsSet())
100     DCHECK_CURRENTLY_ON(BrowserThread::UI);
101 }
102 
~SupervisedUserManagerImpl()103 SupervisedUserManagerImpl::~SupervisedUserManagerImpl() {}
104 
GetUserSyncId(const std::string & user_id) const105 std::string SupervisedUserManagerImpl::GetUserSyncId(
106     const std::string& user_id) const {
107   std::string result;
108   GetUserStringValue(user_id, kSupervisedUserSyncId, &result);
109   return result;
110 }
111 
GetManagerDisplayName(const std::string & user_id) const112 base::string16 SupervisedUserManagerImpl::GetManagerDisplayName(
113     const std::string& user_id) const {
114   PrefService* local_state = g_browser_process->local_state();
115   const base::DictionaryValue* manager_names =
116       local_state->GetDictionary(kSupervisedUserManagerNames);
117   base::string16 result;
118   if (manager_names->GetStringWithoutPathExpansion(user_id, &result) &&
119       !result.empty())
120     return result;
121   return base::UTF8ToUTF16(GetManagerDisplayEmail(user_id));
122 }
123 
GetManagerUserId(const std::string & user_id) const124 std::string SupervisedUserManagerImpl::GetManagerUserId(
125     const std::string& user_id) const {
126   std::string result;
127   GetUserStringValue(user_id, kSupervisedUserManagers, &result);
128   return result;
129 }
130 
GetManagerDisplayEmail(const std::string & user_id) const131 std::string SupervisedUserManagerImpl::GetManagerDisplayEmail(
132     const std::string& user_id) const {
133   std::string result;
134   if (GetUserStringValue(user_id, kSupervisedUserManagerDisplayEmails,
135                          &result) &&
136       !result.empty())
137     return result;
138   return GetManagerUserId(user_id);
139 }
140 
GetPasswordInformation(const std::string & user_id,base::DictionaryValue * result)141 void SupervisedUserManagerImpl::GetPasswordInformation(
142     const std::string& user_id,
143     base::DictionaryValue* result) {
144   int value;
145   if (GetUserIntegerValue(user_id, kSupervisedUserPasswordSchema, &value))
146     result->SetKey(kSchemaVersion, base::Value(value));
147   if (GetUserIntegerValue(user_id, kSupervisedUserPasswordRevision, &value))
148     result->SetKey(kPasswordRevision, base::Value(value));
149 
150   bool flag;
151   if (GetUserBooleanValue(user_id, kSupervisedUserNeedPasswordUpdate, &flag))
152     result->SetKey(kRequirePasswordUpdate, base::Value(flag));
153   if (GetUserBooleanValue(user_id, kSupervisedUserIncompleteKey, &flag))
154     result->SetKey(kHasIncompleteKey, base::Value(flag));
155 
156   std::string salt;
157   if (GetUserStringValue(user_id, kSupervisedUserPasswordSalt, &salt))
158     result->SetKey(kSalt, base::Value(salt));
159 }
160 
SetPasswordInformation(const std::string & user_id,const base::DictionaryValue * password_info)161 void SupervisedUserManagerImpl::SetPasswordInformation(
162     const std::string& user_id,
163     const base::DictionaryValue* password_info) {
164   int value;
165   if (password_info->GetIntegerWithoutPathExpansion(kSchemaVersion, &value))
166     SetUserIntegerValue(user_id, kSupervisedUserPasswordSchema, value);
167   if (password_info->GetIntegerWithoutPathExpansion(kPasswordRevision, &value))
168     SetUserIntegerValue(user_id, kSupervisedUserPasswordRevision, value);
169 
170   bool flag;
171   if (password_info->GetBooleanWithoutPathExpansion(kRequirePasswordUpdate,
172                                                     &flag)) {
173     SetUserBooleanValue(user_id, kSupervisedUserNeedPasswordUpdate, flag);
174   }
175   if (password_info->GetBooleanWithoutPathExpansion(kHasIncompleteKey, &flag))
176     SetUserBooleanValue(user_id, kSupervisedUserIncompleteKey, flag);
177 
178   std::string salt;
179   if (password_info->GetStringWithoutPathExpansion(kSalt, &salt))
180     SetUserStringValue(user_id, kSupervisedUserPasswordSalt, salt);
181   g_browser_process->local_state()->CommitPendingWrite();
182 }
183 
GetUserStringValue(const std::string & user_id,const char * key,std::string * out_value) const184 bool SupervisedUserManagerImpl::GetUserStringValue(
185     const std::string& user_id,
186     const char* key,
187     std::string* out_value) const {
188   PrefService* local_state = g_browser_process->local_state();
189   const base::DictionaryValue* dictionary = local_state->GetDictionary(key);
190   return dictionary->GetStringWithoutPathExpansion(user_id, out_value);
191 }
192 
GetUserIntegerValue(const std::string & user_id,const char * key,int * out_value) const193 bool SupervisedUserManagerImpl::GetUserIntegerValue(const std::string& user_id,
194                                                     const char* key,
195                                                     int* out_value) const {
196   PrefService* local_state = g_browser_process->local_state();
197   const base::DictionaryValue* dictionary = local_state->GetDictionary(key);
198   return dictionary->GetIntegerWithoutPathExpansion(user_id, out_value);
199 }
200 
GetUserBooleanValue(const std::string & user_id,const char * key,bool * out_value) const201 bool SupervisedUserManagerImpl::GetUserBooleanValue(const std::string& user_id,
202                                                     const char* key,
203                                                     bool* out_value) const {
204   PrefService* local_state = g_browser_process->local_state();
205   const base::DictionaryValue* dictionary = local_state->GetDictionary(key);
206   return dictionary->GetBooleanWithoutPathExpansion(user_id, out_value);
207 }
208 
SetUserStringValue(const std::string & user_id,const char * key,const std::string & value)209 void SupervisedUserManagerImpl::SetUserStringValue(const std::string& user_id,
210                                                    const char* key,
211                                                    const std::string& value) {
212   PrefService* local_state = g_browser_process->local_state();
213   DictionaryPrefUpdate update(local_state, key);
214   update->SetKey(user_id, base::Value(value));
215 }
216 
SetUserIntegerValue(const std::string & user_id,const char * key,const int value)217 void SupervisedUserManagerImpl::SetUserIntegerValue(const std::string& user_id,
218                                                     const char* key,
219                                                     const int value) {
220   PrefService* local_state = g_browser_process->local_state();
221   DictionaryPrefUpdate update(local_state, key);
222   update->SetKey(user_id, base::Value(value));
223 }
224 
SetUserBooleanValue(const std::string & user_id,const char * key,const bool value)225 void SupervisedUserManagerImpl::SetUserBooleanValue(const std::string& user_id,
226                                                     const char* key,
227                                                     const bool value) {
228   PrefService* local_state = g_browser_process->local_state();
229   DictionaryPrefUpdate update(local_state, key);
230   update->SetKey(user_id, base::Value(value));
231 }
232 
RemoveNonCryptohomeData(const std::string & user_id)233 void SupervisedUserManagerImpl::RemoveNonCryptohomeData(
234     const std::string& user_id) {
235   PrefService* prefs = g_browser_process->local_state();
236   ListPrefUpdate prefs_new_users_update(prefs, kSupervisedUsersFirstRun);
237   prefs_new_users_update->Remove(base::Value(user_id), NULL);
238 
239   CleanPref(user_id, kSupervisedUserSyncId);
240   CleanPref(user_id, kSupervisedUserManagers);
241   CleanPref(user_id, kSupervisedUserManagerNames);
242   CleanPref(user_id, kSupervisedUserManagerDisplayEmails);
243   CleanPref(user_id, kSupervisedUserPasswordSalt);
244   CleanPref(user_id, kSupervisedUserPasswordSchema);
245   CleanPref(user_id, kSupervisedUserPasswordRevision);
246   CleanPref(user_id, kSupervisedUserNeedPasswordUpdate);
247   CleanPref(user_id, kSupervisedUserIncompleteKey);
248 }
249 
CleanPref(const std::string & user_id,const char * key)250 void SupervisedUserManagerImpl::CleanPref(const std::string& user_id,
251                                           const char* key) {
252   PrefService* prefs = g_browser_process->local_state();
253   DictionaryPrefUpdate dict_update(prefs, key);
254   dict_update->RemoveWithoutPathExpansion(user_id, NULL);
255 }
256 
CheckForFirstRun(const std::string & user_id)257 bool SupervisedUserManagerImpl::CheckForFirstRun(const std::string& user_id) {
258   ListPrefUpdate prefs_new_users_update(g_browser_process->local_state(),
259                                         kSupervisedUsersFirstRun);
260   return prefs_new_users_update->Remove(base::Value(user_id), NULL);
261 }
262 
UpdateManagerName(const std::string & manager_id,const base::string16 & new_display_name)263 void SupervisedUserManagerImpl::UpdateManagerName(
264     const std::string& manager_id,
265     const base::string16& new_display_name) {
266   PrefService* local_state = g_browser_process->local_state();
267 
268   const base::DictionaryValue* manager_ids =
269       local_state->GetDictionary(kSupervisedUserManagers);
270 
271   DictionaryPrefUpdate manager_name_update(local_state,
272                                            kSupervisedUserManagerNames);
273   for (base::DictionaryValue::Iterator it(*manager_ids); !it.IsAtEnd();
274        it.Advance()) {
275     std::string user_id;
276     bool has_manager_id = it.value().GetAsString(&user_id);
277     DCHECK(has_manager_id);
278     if (user_id == manager_id) {
279       manager_name_update->SetWithoutPathExpansion(
280           it.key(), std::make_unique<base::Value>(new_display_name));
281     }
282   }
283 }
284 
285 }  // namespace chromeos
286