• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright (c) 2011 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/cros/login_library.h"
6 
7 #include "base/message_loop.h"
8 #include "base/task.h"
9 #include "base/timer.h"
10 #include "chrome/browser/browser_process.h"
11 #include "chrome/browser/chromeos/cros/cros_library.h"
12 #include "chrome/browser/chromeos/login/signed_settings.h"
13 #include "chrome/browser/chromeos/login/signed_settings_temp_storage.h"
14 #include "chrome/browser/policy/proto/device_management_backend.pb.h"
15 #include "chrome/browser/prefs/pref_service.h"
16 #include "content/browser/browser_thread.h"
17 #include "content/common/notification_service.h"
18 #include "content/common/notification_type.h"
19 
20 namespace em = enterprise_management;
21 namespace chromeos {
22 
23 class LoginLibraryImpl : public LoginLibrary {
24  public:
LoginLibraryImpl()25   LoginLibraryImpl()
26       : job_restart_request_(NULL),
27         set_owner_key_callback_(NULL),
28         whitelist_op_callback_(NULL),
29         property_op_callback_(NULL) {
30     if (CrosLibrary::Get()->EnsureLoaded())
31       Init();
32   }
33 
~LoginLibraryImpl()34   virtual ~LoginLibraryImpl() {
35     if (session_connection_) {
36       chromeos::DisconnectSession(session_connection_);
37     }
38   }
39 
EmitLoginPromptReady()40   bool EmitLoginPromptReady() {
41     return chromeos::EmitLoginPromptReady();
42   }
43 
CheckWhitelist(const std::string & email,std::vector<uint8> * OUT_signature)44   bool CheckWhitelist(const std::string& email,
45                       std::vector<uint8>* OUT_signature) {
46     CryptoBlob* sig = NULL;
47     if (chromeos::CheckWhitelistSafe(email.c_str(), &sig)) {
48       OUT_signature->assign(sig->data, sig->data + sig->length);
49       chromeos::FreeCryptoBlob(sig);
50       return true;
51     }
52     return false;
53   }
54 
RequestRetrievePolicy(RetrievePolicyCallback callback,void * delegate)55   void RequestRetrievePolicy(RetrievePolicyCallback callback, void* delegate) {
56     DCHECK(callback) << "must provide a callback to RequestRetrievePolicy()";
57     chromeos::RetrievePolicy(callback, delegate);
58   }
59 
RequestRetrieveProperty(const std::string & name,RetrievePropertyCallback callback,void * user_data)60   void RequestRetrieveProperty(const std::string& name,
61                                RetrievePropertyCallback callback,
62                                void* user_data) {
63     DCHECK(callback) << "must provide a callback to RequestRetrieveProperty()";
64     chromeos::RequestRetrieveProperty(name.c_str(), callback, user_data);
65   }
66 
RequestStorePolicy(const std::string & policy,StorePolicyCallback callback,void * delegate)67   void RequestStorePolicy(const std::string& policy,
68                           StorePolicyCallback callback,
69                           void* delegate) {
70     DCHECK(callback) << "must provide a callback to StorePolicy()";
71     chromeos::StorePolicy(policy.c_str(), policy.length(), callback, delegate);
72   }
73 
StorePropertyAsync(const std::string & name,const std::string & value,const std::vector<uint8> & signature,Delegate * callback)74   bool StorePropertyAsync(const std::string& name,
75                           const std::string& value,
76                           const std::vector<uint8>& signature,
77                           Delegate* callback) {
78     DCHECK(callback) << "must provide a callback to StorePropertyAsync()";
79     if (property_op_callback_)
80       return false;
81     property_op_callback_ = callback;
82     Property* prop = chromeos::CreateProperty(name.c_str(),
83                                               value.c_str(),
84                                               &signature[0],
85                                               signature.size());
86     bool rv = chromeos::StorePropertySafe(prop);
87     chromeos::FreeProperty(prop);
88     return rv;
89   }
90 
UnwhitelistAsync(const std::string & email,const std::vector<uint8> & signature,Delegate * callback)91   bool UnwhitelistAsync(const std::string& email,
92                         const std::vector<uint8>& signature,
93                         Delegate* callback) {
94     DCHECK(callback) << "must provide a callback to UnwhitelistAsync()";
95     if (whitelist_op_callback_)
96       return false;
97     whitelist_op_callback_ =  callback;
98     CryptoBlob* sig = chromeos::CreateCryptoBlob(&signature[0],
99                                                  signature.size());
100     bool rv = chromeos::UnwhitelistSafe(email.c_str(), sig);
101     chromeos::FreeCryptoBlob(sig);
102     return rv;
103   }
104 
WhitelistAsync(const std::string & email,const std::vector<uint8> & signature,Delegate * callback)105   bool WhitelistAsync(const std::string& email,
106                       const std::vector<uint8>& signature,
107                       Delegate* callback) {
108     DCHECK(callback) << "must provide a callback to WhitelistAsync()";
109     if (whitelist_op_callback_)
110       return false;
111     whitelist_op_callback_ =  callback;
112     CryptoBlob* sig = chromeos::CreateCryptoBlob(&signature[0],
113                                                  signature.size());
114     bool rv = chromeos::WhitelistSafe(email.c_str(), sig);
115     chromeos::FreeCryptoBlob(sig);
116     return rv;
117   }
118 
119   // DEPRECATED.
EnumerateWhitelisted(std::vector<std::string> * whitelisted)120   bool EnumerateWhitelisted(std::vector<std::string>* whitelisted) {
121     NOTREACHED();
122     UserList* list = NULL;
123     if (chromeos::EnumerateWhitelistedSafe(&list)) {
124       for (int i = 0; i < list->num_users; i++)
125         whitelisted->push_back(std::string(list->users[i]));
126       chromeos::FreeUserList(list);
127       return true;
128     }
129     return false;
130   }
131 
StartSession(const std::string & user_email,const std::string & unique_id)132   bool StartSession(const std::string& user_email,
133                     const std::string& unique_id /* unused */) {
134     // only pass unique_id through once we use it for something.
135     return chromeos::StartSession(user_email.c_str(), "");
136   }
137 
StopSession(const std::string & unique_id)138   bool StopSession(const std::string& unique_id /* unused */) {
139     // only pass unique_id through once we use it for something.
140     return chromeos::StopSession("");
141   }
142 
RestartEntd()143   bool RestartEntd() {
144     return chromeos::RestartEntd();
145   }
146 
RestartJob(int pid,const std::string & command_line)147   bool RestartJob(int pid, const std::string& command_line) {
148     if (job_restart_request_) {
149       NOTREACHED();
150       return false;
151     }
152     job_restart_request_ = new JobRestartRequest(pid, command_line);
153     return true;
154   }
155 
156  private:
157   class JobRestartRequest
158       : public base::RefCountedThreadSafe<JobRestartRequest> {
159    public:
JobRestartRequest(int pid,const std::string & command_line)160     JobRestartRequest(int pid, const std::string& command_line)
161         : pid_(pid),
162           command_line_(command_line),
163           local_state_(g_browser_process->local_state()) {
164       AddRef();
165       if (local_state_) {
166         // XXX: normally this call must not be needed, however RestartJob
167         // just kills us so settings may be lost. See http://crosbug.com/13102
168         local_state_->CommitPendingWrite();
169         timer_.Start(
170             base::TimeDelta::FromSeconds(3), this,
171             &JobRestartRequest::RestartJob);
172         // Post task on file thread thus it occurs last on task queue, so it
173         // would be executed after committing pending write on file thread.
174         BrowserThread::PostTask(
175             BrowserThread::FILE, FROM_HERE,
176             NewRunnableMethod(this, &JobRestartRequest::RestartJob));
177       } else {
178         RestartJob();
179       }
180     }
181 
182    private:
RestartJob()183     void RestartJob() {
184       if (BrowserThread::CurrentlyOn(BrowserThread::UI)) {
185         if (!chromeos::RestartJob(pid_, command_line_.c_str()))
186           NOTREACHED();
187       } else {
188         BrowserThread::PostTask(
189             BrowserThread::UI, FROM_HERE,
190             NewRunnableMethod(this, &JobRestartRequest::RestartJob));
191         MessageLoop::current()->AssertIdle();
192       }
193     }
194 
195     int pid_;
196     std::string command_line_;
197     PrefService* local_state_;
198     base::OneShotTimer<JobRestartRequest> timer_;
199   };
200 
201   class StubDelegate
202       : public SignedSettings::Delegate<const em::PolicyFetchResponse&> {
203    public:
StubDelegate()204     StubDelegate() : polfetcher_(NULL) {}
~StubDelegate()205     virtual ~StubDelegate() {}
set_fetcher(SignedSettings * s)206     void set_fetcher(SignedSettings* s) { polfetcher_ = s; }
fetcher()207     SignedSettings* fetcher() { return polfetcher_.get(); }
208     // Implementation of SignedSettings::Delegate
OnSettingsOpCompleted(SignedSettings::ReturnCode code,const em::PolicyFetchResponse & value)209     virtual void OnSettingsOpCompleted(SignedSettings::ReturnCode code,
210                                        const em::PolicyFetchResponse& value) {
211       VLOG(2) << "Done Fetching Policy";
212       delete this;
213     }
214    private:
215     scoped_refptr<SignedSettings> polfetcher_;
216     DISALLOW_COPY_AND_ASSIGN(StubDelegate);
217   };
218 
Handler(void * object,const OwnershipEvent & event)219   static void Handler(void* object, const OwnershipEvent& event) {
220     LoginLibraryImpl* self = static_cast<LoginLibraryImpl*>(object);
221     switch (event) {
222       case SetKeySuccess:
223         self->CompleteSetOwnerKey(true);
224         break;
225       case SetKeyFailure:
226         self->CompleteSetOwnerKey(false);
227         break;
228       case WhitelistOpSuccess:
229         self->CompleteWhitelistOp(true);
230         break;
231       case WhitelistOpFailure:
232         self->CompleteWhitelistOp(false);
233         break;
234       case PropertyOpSuccess:
235         self->CompletePropertyOp(true);
236         break;
237       case PropertyOpFailure:
238         self->CompletePropertyOp(false);
239         break;
240       default:
241         NOTREACHED();
242         break;
243     }
244   }
245 
Init()246   void Init() {
247     session_connection_ = chromeos::MonitorSession(&Handler, this);
248   }
249 
CompleteSetOwnerKey(bool value)250   void CompleteSetOwnerKey(bool value) {
251     VLOG(1) << "Owner key generation: " << (value ? "success" : "fail");
252     NotificationType result =
253         NotificationType::OWNER_KEY_FETCH_ATTEMPT_SUCCEEDED;
254     if (!value)
255       result = NotificationType::OWNER_KEY_FETCH_ATTEMPT_FAILED;
256 
257     // Whether we exported the public key or not, send a notification indicating
258     // that we're done with this attempt.
259     NotificationService::current()->Notify(result,
260                                            NotificationService::AllSources(),
261                                            NotificationService::NoDetails());
262 
263     // We stored some settings in transient storage before owner was assigned.
264     // Now owner is assigned and key is generated and we should persist
265     // those settings into signed storage.
266     if (g_browser_process && g_browser_process->local_state()) {
267       SignedSettingsTempStorage::Finalize(g_browser_process->local_state());
268     }
269   }
270 
CompleteWhitelistOp(bool result)271   void CompleteWhitelistOp(bool result) {
272     if (whitelist_op_callback_) {
273       whitelist_op_callback_->OnComplete(result);
274       whitelist_op_callback_ = NULL;
275     }
276   }
277 
CompletePropertyOp(bool result)278   void CompletePropertyOp(bool result) {
279     if (result) {
280       StubDelegate* stub = new StubDelegate();  // Manages its own lifetime.
281       stub->set_fetcher(SignedSettings::CreateRetrievePolicyOp(stub));
282       stub->fetcher()->Execute();
283     }
284   }
285 
286   chromeos::SessionConnection session_connection_;
287   JobRestartRequest* job_restart_request_;
288 
289   Delegate* set_owner_key_callback_;
290   Delegate* whitelist_op_callback_;
291   Delegate* property_op_callback_;
292 
293   DISALLOW_COPY_AND_ASSIGN(LoginLibraryImpl);
294 };
295 
296 class LoginLibraryStubImpl : public LoginLibrary {
297  public:
LoginLibraryStubImpl()298   LoginLibraryStubImpl() {}
~LoginLibraryStubImpl()299   virtual ~LoginLibraryStubImpl() {}
300 
EmitLoginPromptReady()301   bool EmitLoginPromptReady() { return true; }
CheckWhitelist(const std::string & email,std::vector<uint8> * OUT_signature)302   bool CheckWhitelist(const std::string& email,
303                       std::vector<uint8>* OUT_signature) {
304     OUT_signature->assign(2, 0);
305     return true;
306   }
RequestRetrievePolicy(RetrievePolicyCallback callback,void * delegate)307   void RequestRetrievePolicy(RetrievePolicyCallback callback, void* delegate) {
308     callback(delegate, "", 0);
309   }
RequestRetrieveProperty(const std::string & name,RetrievePropertyCallback callback,void * user_data)310   void RequestRetrieveProperty(const std::string& name,
311                                RetrievePropertyCallback callback,
312                                void* user_data) {
313     uint8 sig_bytes[] = { 0, 0 };
314     CryptoBlob sig = { sig_bytes, arraysize(sig_bytes) };
315     Property prop = {
316       "prop_name",
317       "stub",
318       &sig,
319     };
320 
321     callback(user_data, true, &prop);
322   }
RequestStorePolicy(const std::string & policy,StorePolicyCallback callback,void * delegate)323   void RequestStorePolicy(const std::string& policy,
324                           StorePolicyCallback callback,
325                           void* delegate) {
326     callback(delegate, true);
327   }
StorePropertyAsync(const std::string & name,const std::string & value,const std::vector<uint8> & signature,Delegate * callback)328   bool StorePropertyAsync(const std::string& name,
329                           const std::string& value,
330                           const std::vector<uint8>& signature,
331                           Delegate* callback) {
332     BrowserThread::PostTask(
333         BrowserThread::UI, FROM_HERE,
334         NewRunnableFunction(&DoStubCallback, callback));
335     return true;
336   }
UnwhitelistAsync(const std::string & email,const std::vector<uint8> & signature,Delegate * callback)337   bool UnwhitelistAsync(const std::string& email,
338                         const std::vector<uint8>& signature,
339                         Delegate* callback) {
340     BrowserThread::PostTask(
341         BrowserThread::UI, FROM_HERE,
342         NewRunnableFunction(&DoStubCallback, callback));
343     return true;
344   }
WhitelistAsync(const std::string & email,const std::vector<uint8> & signature,Delegate * callback)345   bool WhitelistAsync(const std::string& email,
346                       const std::vector<uint8>& signature,
347                       Delegate* callback) {
348     BrowserThread::PostTask(
349         BrowserThread::UI, FROM_HERE,
350         NewRunnableFunction(&DoStubCallback, callback));
351     return true;
352   }
EnumerateWhitelisted(std::vector<std::string> * whitelisted)353   bool EnumerateWhitelisted(std::vector<std::string>* whitelisted) {
354     return true;
355   }
StartSession(const std::string & user_email,const std::string & unique_id)356   bool StartSession(const std::string& user_email,
357                     const std::string& unique_id /* unused */) { return true; }
StopSession(const std::string & unique_id)358   bool StopSession(const std::string& unique_id /* unused */) { return true; }
RestartJob(int pid,const std::string & command_line)359   bool RestartJob(int pid, const std::string& command_line) { return true; }
RestartEntd()360   bool RestartEntd() { return true; }
361 
362  private:
DoStubCallback(Delegate * callback)363   static void DoStubCallback(Delegate* callback) {
364     callback->OnComplete(true);
365   }
366 
367   DISALLOW_COPY_AND_ASSIGN(LoginLibraryStubImpl);
368 };
369 
370 // static
GetImpl(bool stub)371 LoginLibrary* LoginLibrary::GetImpl(bool stub) {
372   if (stub)
373     return new LoginLibraryStubImpl();
374   else
375     return new LoginLibraryImpl();
376 }
377 
378 }  // namespace chromeos
379