• 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/ui/webui/options/certificate_manager_handler.h"
6 
7 #include "base/file_util.h"  // for FileAccessProvider
8 #include "base/memory/scoped_vector.h"
9 #include "base/safe_strerror_posix.h"
10 #include "base/string_number_conversions.h"
11 #include "base/values.h"
12 #include "chrome/browser/browser_process.h"
13 #include "chrome/browser/ui/crypto_module_password_dialog.h"
14 #include "chrome/browser/ui/gtk/certificate_dialogs.h"
15 #include "content/browser/browser_thread.h"  // for FileAccessProvider
16 #include "content/browser/certificate_viewer.h"
17 #include "content/browser/tab_contents/tab_contents.h"
18 #include "content/browser/tab_contents/tab_contents_view.h"
19 #include "grit/generated_resources.h"
20 #include "net/base/crypto_module.h"
21 #include "net/base/x509_certificate.h"
22 #include "ui/base/l10n/l10n_util.h"
23 #include "ui/base/l10n/l10n_util_collator.h"
24 
25 #if defined(OS_CHROMEOS)
26 #include "chrome/browser/chromeos/cros/cros_library.h"
27 #include "chrome/browser/chromeos/cros/cryptohome_library.h"
28 #endif
29 
30 namespace {
31 
32 static const char kKeyId[] = "id";
33 static const char kSubNodesId[] = "subnodes";
34 static const char kNameId[] = "name";
35 static const char kReadOnlyId[] = "readonly";
36 static const char kIconId[] = "icon";
37 static const char kSecurityDeviceId[] = "device";
38 static const char kErrorId[] = "error";
39 
40 // Enumeration of different callers of SelectFile.  (Start counting at 1 so
41 // if SelectFile is accidentally called with params=NULL it won't match any.)
42 enum {
43   EXPORT_PERSONAL_FILE_SELECTED = 1,
44   IMPORT_PERSONAL_FILE_SELECTED,
45   IMPORT_SERVER_FILE_SELECTED,
46   IMPORT_CA_FILE_SELECTED,
47 };
48 
49 // TODO(mattm): These are duplicated from cookies_view_handler.cc
50 // Encodes a pointer value into a hex string.
PointerToHexString(const void * pointer)51 std::string PointerToHexString(const void* pointer) {
52   return base::HexEncode(&pointer, sizeof(pointer));
53 }
54 
55 // Decodes a pointer from a hex string.
HexStringToPointer(const std::string & str)56 void* HexStringToPointer(const std::string& str) {
57   std::vector<uint8> buffer;
58   if (!base::HexStringToBytes(str, &buffer) ||
59       buffer.size() != sizeof(void*)) {
60     return NULL;
61   }
62 
63   return *reinterpret_cast<void**>(&buffer[0]);
64 }
65 
OrgNameToId(const std::string & org)66 std::string OrgNameToId(const std::string& org) {
67   return "org-" + org;
68 }
69 
CertToId(const net::X509Certificate & cert)70 std::string CertToId(const net::X509Certificate& cert) {
71   return "cert-" + PointerToHexString(&cert);
72 }
73 
IdToCert(const std::string & id)74 net::X509Certificate* IdToCert(const std::string& id) {
75   if (!StartsWithASCII(id, "cert-", true))
76     return NULL;
77   return reinterpret_cast<net::X509Certificate*>(
78       HexStringToPointer(id.substr(5)));
79 }
80 
CallbackArgsToCert(const ListValue * args)81 net::X509Certificate* CallbackArgsToCert(const ListValue* args) {
82   std::string node_id;
83   if (!args->GetString(0, &node_id)){
84     return NULL;
85   }
86   net::X509Certificate* cert = IdToCert(node_id);
87   if (!cert) {
88     NOTREACHED();
89     return NULL;
90   }
91   return cert;
92 }
93 
CallbackArgsToBool(const ListValue * args,int index,bool * result)94 bool CallbackArgsToBool(const ListValue* args, int index, bool* result) {
95   std::string string_value;
96   if (!args->GetString(index, &string_value))
97     return false;
98 
99   *result = string_value[0] == 't';
100   return true;
101 }
102 
103 struct DictionaryIdComparator {
DictionaryIdComparator__anon186f7c4b0111::DictionaryIdComparator104   explicit DictionaryIdComparator(icu::Collator* collator)
105       : collator_(collator) {
106   }
107 
operator ()__anon186f7c4b0111::DictionaryIdComparator108   bool operator()(const Value* a,
109                   const Value* b) const {
110     DCHECK(a->GetType() == Value::TYPE_DICTIONARY);
111     DCHECK(b->GetType() == Value::TYPE_DICTIONARY);
112     const DictionaryValue* a_dict = reinterpret_cast<const DictionaryValue*>(a);
113     const DictionaryValue* b_dict = reinterpret_cast<const DictionaryValue*>(b);
114     string16 a_str;
115     string16 b_str;
116     a_dict->GetString(kNameId, &a_str);
117     b_dict->GetString(kNameId, &b_str);
118     if (collator_ == NULL)
119       return a_str < b_str;
120     return l10n_util::CompareString16WithCollator(
121         collator_, a_str, b_str) == UCOL_LESS;
122   }
123 
124   icu::Collator* collator_;
125 };
126 
NetErrorToString(int net_error)127 std::string NetErrorToString(int net_error) {
128   switch (net_error) {
129     // TODO(mattm): handle more cases.
130     case net::ERR_IMPORT_CA_CERT_NOT_CA:
131       return l10n_util::GetStringUTF8(IDS_CERT_MANAGER_ERROR_NOT_CA);
132     default:
133       return l10n_util::GetStringUTF8(IDS_CERT_MANAGER_UNKNOWN_ERROR);
134   }
135 }
136 
137 }  // namespace
138 
139 ///////////////////////////////////////////////////////////////////////////////
140 //  FileAccessProvider
141 
142 // TODO(mattm): Move to some shared location?
143 class FileAccessProvider
144     : public base::RefCountedThreadSafe<FileAccessProvider>,
145       public CancelableRequestProvider {
146  public:
147   // Reports 0 on success or errno on failure, and the data of the file upon
148   // success.
149   // TODO(mattm): don't pass std::string by value.. could use RefCountedBytes
150   // but it's a vector.  Maybe do the derive from CancelableRequest thing
151   // described in cancelable_request.h?
152   typedef Callback2<int, std::string>::Type ReadCallback;
153 
154   // Reports 0 on success or errno on failure, and the number of bytes written,
155   // on success.
156   typedef Callback2<int, int>::Type WriteCallback;
157 
158   Handle StartRead(const FilePath& path,
159                    CancelableRequestConsumerBase* consumer,
160                    ReadCallback* callback);
161   Handle StartWrite(const FilePath& path,
162                     const std::string& data,
163                     CancelableRequestConsumerBase* consumer,
164                     WriteCallback* callback);
165 
166  private:
167   void DoRead(scoped_refptr<CancelableRequest<ReadCallback> > request,
168               FilePath path);
169   void DoWrite(scoped_refptr<CancelableRequest<WriteCallback> > request,
170               FilePath path,
171               std::string data);
172 };
173 
StartRead(const FilePath & path,CancelableRequestConsumerBase * consumer,FileAccessProvider::ReadCallback * callback)174 CancelableRequestProvider::Handle FileAccessProvider::StartRead(
175     const FilePath& path,
176     CancelableRequestConsumerBase* consumer,
177     FileAccessProvider::ReadCallback* callback) {
178   scoped_refptr<CancelableRequest<ReadCallback> > request(
179       new CancelableRequest<ReadCallback>(callback));
180   AddRequest(request, consumer);
181 
182   // Send the parameters and the request to the file thread.
183   BrowserThread::PostTask(
184       BrowserThread::FILE, FROM_HERE,
185       NewRunnableMethod(this, &FileAccessProvider::DoRead, request, path));
186 
187   // The handle will have been set by AddRequest.
188   return request->handle();
189 }
190 
StartWrite(const FilePath & path,const std::string & data,CancelableRequestConsumerBase * consumer,WriteCallback * callback)191 CancelableRequestProvider::Handle FileAccessProvider::StartWrite(
192     const FilePath& path,
193     const std::string& data,
194     CancelableRequestConsumerBase* consumer,
195     WriteCallback* callback) {
196   scoped_refptr<CancelableRequest<WriteCallback> > request(
197       new CancelableRequest<WriteCallback>(callback));
198   AddRequest(request, consumer);
199 
200   // Send the parameters and the request to the file thWrite.
201   BrowserThread::PostTask(
202       BrowserThread::FILE, FROM_HERE,
203       NewRunnableMethod(
204           this, &FileAccessProvider::DoWrite, request, path, data));
205 
206   // The handle will have been set by AddRequest.
207   return request->handle();
208 }
209 
DoRead(scoped_refptr<CancelableRequest<ReadCallback>> request,FilePath path)210 void FileAccessProvider::DoRead(
211     scoped_refptr<CancelableRequest<ReadCallback> > request,
212     FilePath path) {
213   if (request->canceled())
214     return;
215 
216   std::string data;
217   VLOG(1) << "DoRead starting read";
218   bool success = file_util::ReadFileToString(path, &data);
219   int saved_errno = success ? 0 : errno;
220   VLOG(1) << "DoRead done read: " << success << " " << data.size();
221   request->ForwardResult(ReadCallback::TupleType(saved_errno, data));
222 }
223 
DoWrite(scoped_refptr<CancelableRequest<WriteCallback>> request,FilePath path,std::string data)224 void FileAccessProvider::DoWrite(
225     scoped_refptr<CancelableRequest<WriteCallback> > request,
226     FilePath path,
227     std::string data) {
228   VLOG(1) << "DoWrite starting write";
229   int bytes_written = file_util::WriteFile(path, data.data(), data.size());
230   int saved_errno = bytes_written >= 0 ? 0 : errno;
231   VLOG(1) << "DoWrite done write " << bytes_written;
232 
233   if (request->canceled())
234     return;
235 
236   request->ForwardResult(WriteCallback::TupleType(saved_errno, bytes_written));
237 }
238 
239 ///////////////////////////////////////////////////////////////////////////////
240 //  CertificateManagerHandler
241 
CertificateManagerHandler()242 CertificateManagerHandler::CertificateManagerHandler()
243     : file_access_provider_(new FileAccessProvider) {
244   certificate_manager_model_.reset(new CertificateManagerModel(this));
245 }
246 
~CertificateManagerHandler()247 CertificateManagerHandler::~CertificateManagerHandler() {
248 }
249 
GetLocalizedValues(DictionaryValue * localized_strings)250 void CertificateManagerHandler::GetLocalizedValues(
251     DictionaryValue* localized_strings) {
252   DCHECK(localized_strings);
253 
254   RegisterTitle(localized_strings, "certificateManagerPage",
255                 IDS_CERTIFICATE_MANAGER_TITLE);
256 
257   // Tabs.
258   localized_strings->SetString("personalCertsTabTitle",
259       l10n_util::GetStringUTF16(IDS_CERT_MANAGER_PERSONAL_CERTS_TAB_LABEL));
260   localized_strings->SetString("serverCertsTabTitle",
261       l10n_util::GetStringUTF16(IDS_CERT_MANAGER_SERVER_CERTS_TAB_LABEL));
262   localized_strings->SetString("caCertsTabTitle",
263       l10n_util::GetStringUTF16(IDS_CERT_MANAGER_CERT_AUTHORITIES_TAB_LABEL));
264   localized_strings->SetString("unknownCertsTabTitle",
265       l10n_util::GetStringUTF16(IDS_CERT_MANAGER_UNKNOWN_TAB_LABEL));
266 
267   // Tab descriptions.
268   localized_strings->SetString("personalCertsTabDescription",
269       l10n_util::GetStringUTF16(IDS_CERT_MANAGER_USER_TREE_DESCRIPTION));
270   localized_strings->SetString("serverCertsTabDescription",
271       l10n_util::GetStringUTF16(IDS_CERT_MANAGER_SERVER_TREE_DESCRIPTION));
272   localized_strings->SetString("caCertsTabDescription",
273       l10n_util::GetStringUTF16(IDS_CERT_MANAGER_AUTHORITIES_TREE_DESCRIPTION));
274   localized_strings->SetString("unknownCertsTabDescription",
275       l10n_util::GetStringUTF16(IDS_CERT_MANAGER_UNKNOWN_TREE_DESCRIPTION));
276 
277   // Tree columns.
278   localized_strings->SetString("certNameColumn",
279       l10n_util::GetStringUTF16(IDS_CERT_MANAGER_NAME_COLUMN_LABEL));
280   localized_strings->SetString("certDeviceColumn",
281       l10n_util::GetStringUTF16(IDS_CERT_MANAGER_DEVICE_COLUMN_LABEL));
282   localized_strings->SetString("certSerialColumn",
283       l10n_util::GetStringUTF16(IDS_CERT_MANAGER_SERIAL_NUMBER_COLUMN_LABEL));
284   localized_strings->SetString("certExpiresColumn",
285       l10n_util::GetStringUTF16(IDS_CERT_MANAGER_EXPIRES_COLUMN_LABEL));
286 
287   // Buttons.
288   localized_strings->SetString("view_certificate",
289       l10n_util::GetStringUTF16(IDS_CERT_MANAGER_VIEW_CERT_BUTTON));
290   localized_strings->SetString("import_certificate",
291       l10n_util::GetStringUTF16(IDS_CERT_MANAGER_IMPORT_BUTTON));
292   localized_strings->SetString("export_certificate",
293       l10n_util::GetStringUTF16(IDS_CERT_MANAGER_EXPORT_BUTTON));
294   localized_strings->SetString("export_all_certificates",
295       l10n_util::GetStringUTF16(IDS_CERT_MANAGER_EXPORT_ALL_BUTTON));
296   localized_strings->SetString("edit_certificate",
297       l10n_util::GetStringUTF16(IDS_CERT_MANAGER_EDIT_BUTTON));
298   localized_strings->SetString("delete_certificate",
299       l10n_util::GetStringUTF16(IDS_CERT_MANAGER_DELETE_BUTTON));
300 
301   // Certificate Delete overlay strings.
302   localized_strings->SetString("personalCertsTabDeleteConfirm",
303       l10n_util::GetStringUTF16(IDS_CERT_MANAGER_DELETE_USER_FORMAT));
304   localized_strings->SetString("personalCertsTabDeleteImpact",
305       l10n_util::GetStringUTF16(IDS_CERT_MANAGER_DELETE_USER_DESCRIPTION));
306   localized_strings->SetString("serverCertsTabDeleteConfirm",
307       l10n_util::GetStringUTF16(IDS_CERT_MANAGER_DELETE_SERVER_FORMAT));
308   localized_strings->SetString("serverCertsTabDeleteImpact",
309       l10n_util::GetStringUTF16(IDS_CERT_MANAGER_DELETE_SERVER_DESCRIPTION));
310   localized_strings->SetString("caCertsTabDeleteConfirm",
311       l10n_util::GetStringUTF16(IDS_CERT_MANAGER_DELETE_CA_FORMAT));
312   localized_strings->SetString("caCertsTabDeleteImpact",
313       l10n_util::GetStringUTF16(IDS_CERT_MANAGER_DELETE_CA_DESCRIPTION));
314   localized_strings->SetString("unknownCertsTabDeleteConfirm",
315       l10n_util::GetStringUTF16(IDS_CERT_MANAGER_DELETE_UNKNOWN_FORMAT));
316   localized_strings->SetString("unknownCertsTabDeleteImpact", "");
317 
318   // Certificate Restore overlay strings.
319   localized_strings->SetString("certificateRestorePasswordDescription",
320       l10n_util::GetStringUTF16(IDS_CERT_MANAGER_RESTORE_PASSWORD_DESC));
321   localized_strings->SetString("certificatePasswordLabel",
322       l10n_util::GetStringUTF16(IDS_CERT_MANAGER_PASSWORD_LABEL));
323 
324   // Personal Certificate Export overlay strings.
325   localized_strings->SetString("certificateExportPasswordDescription",
326       l10n_util::GetStringUTF16(IDS_CERT_MANAGER_EXPORT_PASSWORD_DESC));
327   localized_strings->SetString("certificateExportPasswordHelp",
328       l10n_util::GetStringUTF16(IDS_CERT_MANAGER_EXPORT_PASSWORD_HELP));
329   localized_strings->SetString("certificateConfirmPasswordLabel",
330       l10n_util::GetStringUTF16(IDS_CERT_MANAGER_CONFIRM_PASSWORD_LABEL));
331 
332   // Edit CA Trust & Import CA overlay strings.
333   localized_strings->SetString("certificateEditTrustLabel",
334       l10n_util::GetStringUTF16(IDS_CERT_MANAGER_EDIT_TRUST_LABEL));
335   localized_strings->SetString("certificateEditCaTrustDescriptionFormat",
336       l10n_util::GetStringUTF16(
337           IDS_CERT_MANAGER_EDIT_CA_TRUST_DESCRIPTION_FORMAT));
338   localized_strings->SetString("certificateImportCaDescriptionFormat",
339       l10n_util::GetStringUTF16(
340           IDS_CERT_MANAGER_IMPORT_CA_DESCRIPTION_FORMAT));
341   localized_strings->SetString("certificateCaTrustSSLLabel",
342       l10n_util::GetStringUTF16(IDS_CERT_MANAGER_EDIT_CA_TRUST_SSL_LABEL));
343   localized_strings->SetString("certificateCaTrustEmailLabel",
344       l10n_util::GetStringUTF16(IDS_CERT_MANAGER_EDIT_CA_TRUST_EMAIL_LABEL));
345   localized_strings->SetString("certificateCaTrustObjSignLabel",
346       l10n_util::GetStringUTF16(IDS_CERT_MANAGER_EDIT_CA_TRUST_OBJSIGN_LABEL));
347   localized_strings->SetString("certificateImportErrorFormat",
348       l10n_util::GetStringUTF16(IDS_CERT_MANAGER_IMPORT_ERROR_FORMAT));
349 
350 #if defined(OS_CHROMEOS)
351   localized_strings->SetString("importAndBindCertificate",
352       l10n_util::GetStringUTF16(IDS_CERT_MANAGER_IMPORT_AND_BIND_BUTTON));
353   localized_strings->SetString("hardwareBackedKeyFormat",
354       l10n_util::GetStringUTF16(IDS_CERT_MANAGER_HARDWARE_BACKED_KEY_FORMAT));
355   localized_strings->SetString("chromeOSDeviceName",
356       l10n_util::GetStringUTF16(IDS_CERT_MANAGER_HARDWARE_BACKED));
357 #endif  // defined(OS_CHROMEOS)
358 }
359 
RegisterMessages()360 void CertificateManagerHandler::RegisterMessages() {
361   web_ui_->RegisterMessageCallback("viewCertificate",
362       NewCallback(this, &CertificateManagerHandler::View));
363 
364   web_ui_->RegisterMessageCallback("getCaCertificateTrust",
365       NewCallback(this, &CertificateManagerHandler::GetCATrust));
366   web_ui_->RegisterMessageCallback("editCaCertificateTrust",
367       NewCallback(this, &CertificateManagerHandler::EditCATrust));
368 
369   web_ui_->RegisterMessageCallback("editServerCertificate",
370       NewCallback(this, &CertificateManagerHandler::EditServer));
371 
372   web_ui_->RegisterMessageCallback("cancelImportExportCertificate",
373       NewCallback(this, &CertificateManagerHandler::CancelImportExportProcess));
374 
375   web_ui_->RegisterMessageCallback("exportPersonalCertificate",
376       NewCallback(this, &CertificateManagerHandler::ExportPersonal));
377   web_ui_->RegisterMessageCallback("exportAllPersonalCertificates",
378       NewCallback(this, &CertificateManagerHandler::ExportAllPersonal));
379   web_ui_->RegisterMessageCallback("exportPersonalCertificatePasswordSelected",
380       NewCallback(this,
381                   &CertificateManagerHandler::ExportPersonalPasswordSelected));
382 
383   web_ui_->RegisterMessageCallback("importPersonalCertificate",
384       NewCallback(this, &CertificateManagerHandler::StartImportPersonal));
385   web_ui_->RegisterMessageCallback("importPersonalCertificatePasswordSelected",
386       NewCallback(this,
387                   &CertificateManagerHandler::ImportPersonalPasswordSelected));
388 
389   web_ui_->RegisterMessageCallback("importCaCertificate",
390       NewCallback(this, &CertificateManagerHandler::ImportCA));
391   web_ui_->RegisterMessageCallback("importCaCertificateTrustSelected",
392       NewCallback(this, &CertificateManagerHandler::ImportCATrustSelected));
393 
394   web_ui_->RegisterMessageCallback("importServerCertificate",
395       NewCallback(this, &CertificateManagerHandler::ImportServer));
396 
397   web_ui_->RegisterMessageCallback("exportCertificate",
398       NewCallback(this, &CertificateManagerHandler::Export));
399 
400   web_ui_->RegisterMessageCallback("deleteCertificate",
401       NewCallback(this, &CertificateManagerHandler::Delete));
402 
403   web_ui_->RegisterMessageCallback("populateCertificateManager",
404       NewCallback(this, &CertificateManagerHandler::Populate));
405 
406 #if defined(OS_CHROMEOS)
407   web_ui_->RegisterMessageCallback("checkTpmTokenReady",
408       NewCallback(this, &CertificateManagerHandler::CheckTpmTokenReady));
409 #endif
410 }
411 
CertificatesRefreshed()412 void CertificateManagerHandler::CertificatesRefreshed() {
413   PopulateTree("personalCertsTab", net::USER_CERT);
414   PopulateTree("serverCertsTab", net::SERVER_CERT);
415   PopulateTree("caCertsTab", net::CA_CERT);
416   PopulateTree("otherCertsTab", net::UNKNOWN_CERT);
417   VLOG(1) << "populating finished";
418 }
419 
FileSelected(const FilePath & path,int index,void * params)420 void CertificateManagerHandler::FileSelected(const FilePath& path, int index,
421                                              void* params) {
422   switch (reinterpret_cast<intptr_t>(params)) {
423     case EXPORT_PERSONAL_FILE_SELECTED:
424       ExportPersonalFileSelected(path);
425       break;
426     case IMPORT_PERSONAL_FILE_SELECTED:
427       ImportPersonalFileSelected(path);
428       break;
429     case IMPORT_SERVER_FILE_SELECTED:
430       ImportServerFileSelected(path);
431       break;
432     case IMPORT_CA_FILE_SELECTED:
433       ImportCAFileSelected(path);
434       break;
435     default:
436       NOTREACHED();
437   }
438 }
439 
FileSelectionCanceled(void * params)440 void CertificateManagerHandler::FileSelectionCanceled(void* params) {
441   switch (reinterpret_cast<intptr_t>(params)) {
442     case EXPORT_PERSONAL_FILE_SELECTED:
443     case IMPORT_PERSONAL_FILE_SELECTED:
444     case IMPORT_SERVER_FILE_SELECTED:
445     case IMPORT_CA_FILE_SELECTED:
446       ImportExportCleanup();
447       break;
448     default:
449       NOTREACHED();
450   }
451 }
452 
View(const ListValue * args)453 void CertificateManagerHandler::View(const ListValue* args) {
454   net::X509Certificate* cert = CallbackArgsToCert(args);
455   if (!cert)
456     return;
457   ShowCertificateViewer(GetParentWindow(), cert);
458 }
459 
GetCATrust(const ListValue * args)460 void CertificateManagerHandler::GetCATrust(const ListValue* args) {
461   net::X509Certificate* cert = CallbackArgsToCert(args);
462   if (!cert) {
463     web_ui_->CallJavascriptFunction("CertificateEditCaTrustOverlay.dismiss");
464     return;
465   }
466 
467   int trust = certificate_manager_model_->cert_db().GetCertTrust(
468       cert, net::CA_CERT);
469   FundamentalValue ssl_value(bool(trust & net::CertDatabase::TRUSTED_SSL));
470   FundamentalValue email_value(bool(trust & net::CertDatabase::TRUSTED_EMAIL));
471   FundamentalValue obj_sign_value(
472       bool(trust & net::CertDatabase::TRUSTED_OBJ_SIGN));
473   web_ui_->CallJavascriptFunction(
474       "CertificateEditCaTrustOverlay.populateTrust",
475       ssl_value, email_value, obj_sign_value);
476 }
477 
EditCATrust(const ListValue * args)478 void CertificateManagerHandler::EditCATrust(const ListValue* args) {
479   net::X509Certificate* cert = CallbackArgsToCert(args);
480   bool fail = !cert;
481   bool trust_ssl = false;
482   bool trust_email = false;
483   bool trust_obj_sign = false;
484   fail |= !CallbackArgsToBool(args, 1, &trust_ssl);
485   fail |= !CallbackArgsToBool(args, 2, &trust_email);
486   fail |= !CallbackArgsToBool(args, 3, &trust_obj_sign);
487   if (fail) {
488     LOG(ERROR) << "EditCATrust args fail";
489     web_ui_->CallJavascriptFunction("CertificateEditCaTrustOverlay.dismiss");
490     return;
491   }
492 
493   bool result = certificate_manager_model_->SetCertTrust(
494       cert,
495       net::CA_CERT,
496       trust_ssl * net::CertDatabase::TRUSTED_SSL +
497           trust_email * net::CertDatabase::TRUSTED_EMAIL +
498           trust_obj_sign * net::CertDatabase::TRUSTED_OBJ_SIGN);
499   web_ui_->CallJavascriptFunction("CertificateEditCaTrustOverlay.dismiss");
500   if (!result) {
501     // TODO(mattm): better error messages?
502     ShowError(
503         l10n_util::GetStringUTF8(IDS_CERT_MANAGER_SET_TRUST_ERROR_TITLE),
504         l10n_util::GetStringUTF8(IDS_CERT_MANAGER_UNKNOWN_ERROR));
505   }
506 }
507 
EditServer(const ListValue * args)508 void CertificateManagerHandler::EditServer(const ListValue* args) {
509   NOTIMPLEMENTED();
510 }
511 
ExportPersonal(const ListValue * args)512 void CertificateManagerHandler::ExportPersonal(const ListValue* args) {
513   net::X509Certificate* cert = CallbackArgsToCert(args);
514   if (!cert)
515     return;
516 
517   selected_cert_list_.push_back(cert);
518 
519   SelectFileDialog::FileTypeInfo file_type_info;
520   file_type_info.extensions.resize(1);
521   file_type_info.extensions[0].push_back(FILE_PATH_LITERAL("p12"));
522   file_type_info.extension_description_overrides.push_back(
523       l10n_util::GetStringUTF16(IDS_CERT_MANAGER_PKCS12_FILES));
524   file_type_info.include_all_files = true;
525   select_file_dialog_ = SelectFileDialog::Create(this);
526   select_file_dialog_->SelectFile(
527       SelectFileDialog::SELECT_SAVEAS_FILE, string16(),
528       FilePath(), &file_type_info, 1, FILE_PATH_LITERAL("p12"),
529       web_ui_->tab_contents(), GetParentWindow(),
530       reinterpret_cast<void*>(EXPORT_PERSONAL_FILE_SELECTED));
531 }
532 
ExportAllPersonal(const ListValue * args)533 void CertificateManagerHandler::ExportAllPersonal(const ListValue* args) {
534   NOTIMPLEMENTED();
535 }
536 
ExportPersonalFileSelected(const FilePath & path)537 void CertificateManagerHandler::ExportPersonalFileSelected(
538     const FilePath& path) {
539   file_path_ = path;
540   web_ui_->CallJavascriptFunction(
541       "CertificateManager.exportPersonalAskPassword");
542 }
543 
ExportPersonalPasswordSelected(const ListValue * args)544 void CertificateManagerHandler::ExportPersonalPasswordSelected(
545     const ListValue* args) {
546   if (!args->GetString(0, &password_)){
547     web_ui_->CallJavascriptFunction("CertificateRestoreOverlay.dismiss");
548     ImportExportCleanup();
549     return;
550   }
551 
552   // Currently, we don't support exporting more than one at a time.  If we do,
553   // this would need to either change this to use UnlockSlotsIfNecessary or
554   // change UnlockCertSlotIfNecessary to take a CertificateList.
555   DCHECK_EQ(selected_cert_list_.size(), 1U);
556 
557   // TODO(mattm): do something smarter about non-extractable keys
558   browser::UnlockCertSlotIfNecessary(
559       selected_cert_list_[0].get(),
560       browser::kCryptoModulePasswordCertExport,
561       "",  // unused.
562       NewCallback(this,
563                   &CertificateManagerHandler::ExportPersonalSlotsUnlocked));
564 }
565 
ExportPersonalSlotsUnlocked()566 void CertificateManagerHandler::ExportPersonalSlotsUnlocked() {
567   std::string output;
568   int num_exported = certificate_manager_model_->cert_db().ExportToPKCS12(
569       selected_cert_list_,
570       password_,
571       &output);
572   if (!num_exported) {
573     web_ui_->CallJavascriptFunction("CertificateRestoreOverlay.dismiss");
574     ShowError(
575         l10n_util::GetStringUTF8(IDS_CERT_MANAGER_PKCS12_EXPORT_ERROR_TITLE),
576         l10n_util::GetStringUTF8(IDS_CERT_MANAGER_UNKNOWN_ERROR));
577     ImportExportCleanup();
578     return;
579   }
580   file_access_provider_->StartWrite(
581       file_path_,
582       output,
583       &consumer_,
584       NewCallback(this, &CertificateManagerHandler::ExportPersonalFileWritten));
585 }
586 
ExportPersonalFileWritten(int write_errno,int bytes_written)587 void CertificateManagerHandler::ExportPersonalFileWritten(int write_errno,
588                                                           int bytes_written) {
589   web_ui_->CallJavascriptFunction("CertificateRestoreOverlay.dismiss");
590   ImportExportCleanup();
591   if (write_errno) {
592     ShowError(
593         l10n_util::GetStringUTF8(IDS_CERT_MANAGER_PKCS12_EXPORT_ERROR_TITLE),
594         l10n_util::GetStringFUTF8(IDS_CERT_MANAGER_WRITE_ERROR_FORMAT,
595                                   UTF8ToUTF16(safe_strerror(write_errno))));
596   }
597 }
598 
StartImportPersonal(const ListValue * args)599 void CertificateManagerHandler::StartImportPersonal(const ListValue* args) {
600   SelectFileDialog::FileTypeInfo file_type_info;
601   if (!args->GetBoolean(0, &use_hardware_backed_)){
602     // Unable to retrieve the hardware backed attribute from the args,
603     // so bail.
604     web_ui_->CallJavascriptFunction("CertificateRestoreOverlay.dismiss");
605     ImportExportCleanup();
606     return;
607   }
608   file_type_info.extensions.resize(1);
609   file_type_info.extensions[0].push_back(FILE_PATH_LITERAL("p12"));
610   file_type_info.extension_description_overrides.push_back(
611       l10n_util::GetStringUTF16(IDS_CERT_MANAGER_PKCS12_FILES));
612   file_type_info.include_all_files = true;
613   select_file_dialog_ = SelectFileDialog::Create(this);
614   select_file_dialog_->SelectFile(
615       SelectFileDialog::SELECT_OPEN_FILE, string16(),
616       FilePath(), &file_type_info, 1, FILE_PATH_LITERAL("p12"),
617       web_ui_->tab_contents(), GetParentWindow(),
618       reinterpret_cast<void*>(IMPORT_PERSONAL_FILE_SELECTED));
619 }
620 
ImportPersonalFileSelected(const FilePath & path)621 void CertificateManagerHandler::ImportPersonalFileSelected(
622     const FilePath& path) {
623   file_path_ = path;
624   web_ui_->CallJavascriptFunction(
625       "CertificateManager.importPersonalAskPassword");
626 }
627 
ImportPersonalPasswordSelected(const ListValue * args)628 void CertificateManagerHandler::ImportPersonalPasswordSelected(
629     const ListValue* args) {
630   if (!args->GetString(0, &password_)){
631     web_ui_->CallJavascriptFunction("CertificateRestoreOverlay.dismiss");
632     ImportExportCleanup();
633     return;
634   }
635   file_access_provider_->StartRead(
636       file_path_,
637       &consumer_,
638       NewCallback(this, &CertificateManagerHandler::ImportPersonalFileRead));
639 }
640 
ImportPersonalFileRead(int read_errno,std::string data)641 void CertificateManagerHandler::ImportPersonalFileRead(
642     int read_errno, std::string data) {
643   if (read_errno) {
644     ImportExportCleanup();
645     web_ui_->CallJavascriptFunction("CertificateRestoreOverlay.dismiss");
646     ShowError(
647         l10n_util::GetStringUTF8(IDS_CERT_MANAGER_PKCS12_IMPORT_ERROR_TITLE),
648         l10n_util::GetStringFUTF8(IDS_CERT_MANAGER_READ_ERROR_FORMAT,
649                                   UTF8ToUTF16(safe_strerror(read_errno))));
650     return;
651   }
652 
653   file_data_ = data;
654 
655   if (use_hardware_backed_) {
656     module_ = certificate_manager_model_->cert_db().GetPrivateModule();
657   } else {
658     module_ = certificate_manager_model_->cert_db().GetPublicModule();
659   }
660 
661   net::CryptoModuleList modules;
662   modules.push_back(module_);
663   browser::UnlockSlotsIfNecessary(
664       modules,
665       browser::kCryptoModulePasswordCertImport,
666       "",  // unused.
667       NewCallback(this,
668                   &CertificateManagerHandler::ImportPersonalSlotUnlocked));
669 }
670 
ImportPersonalSlotUnlocked()671 void CertificateManagerHandler::ImportPersonalSlotUnlocked() {
672   int result = certificate_manager_model_->ImportFromPKCS12(
673       module_, file_data_, password_);
674   ImportExportCleanup();
675   web_ui_->CallJavascriptFunction("CertificateRestoreOverlay.dismiss");
676   switch (result) {
677     case net::OK:
678       break;
679     case net::ERR_PKCS12_IMPORT_BAD_PASSWORD:
680       ShowError(
681           l10n_util::GetStringUTF8(IDS_CERT_MANAGER_PKCS12_IMPORT_ERROR_TITLE),
682           l10n_util::GetStringUTF8(IDS_CERT_MANAGER_BAD_PASSWORD));
683       // TODO(mattm): if the error was a bad password, we should reshow the
684       // password dialog after the user dismisses the error dialog.
685       break;
686     default:
687       ShowError(
688           l10n_util::GetStringUTF8(IDS_CERT_MANAGER_PKCS12_IMPORT_ERROR_TITLE),
689           l10n_util::GetStringUTF8(IDS_CERT_MANAGER_UNKNOWN_ERROR));
690       break;
691   }
692 }
693 
CancelImportExportProcess(const ListValue * args)694 void CertificateManagerHandler::CancelImportExportProcess(
695     const ListValue* args) {
696   ImportExportCleanup();
697 }
698 
ImportExportCleanup()699 void CertificateManagerHandler::ImportExportCleanup() {
700   file_path_.clear();
701   password_.clear();
702   file_data_.clear();
703   use_hardware_backed_ = false;
704   selected_cert_list_.clear();
705   module_ = NULL;
706 
707   // There may be pending file dialogs, we need to tell them that we've gone
708   // away so they don't try and call back to us.
709   if (select_file_dialog_.get())
710     select_file_dialog_->ListenerDestroyed();
711   select_file_dialog_ = NULL;
712 }
713 
ImportServer(const ListValue * args)714 void CertificateManagerHandler::ImportServer(const ListValue* args) {
715   select_file_dialog_ = SelectFileDialog::Create(this);
716   ShowCertSelectFileDialog(
717       select_file_dialog_.get(),
718       SelectFileDialog::SELECT_OPEN_FILE,
719       FilePath(),
720       web_ui_->tab_contents(),
721       GetParentWindow(),
722       reinterpret_cast<void*>(IMPORT_SERVER_FILE_SELECTED));
723 }
724 
ImportServerFileSelected(const FilePath & path)725 void CertificateManagerHandler::ImportServerFileSelected(const FilePath& path) {
726   file_path_ = path;
727   file_access_provider_->StartRead(
728       file_path_,
729       &consumer_,
730       NewCallback(this, &CertificateManagerHandler::ImportServerFileRead));
731 }
732 
ImportServerFileRead(int read_errno,std::string data)733 void CertificateManagerHandler::ImportServerFileRead(int read_errno,
734                                                      std::string data) {
735   if (read_errno) {
736     ImportExportCleanup();
737     ShowError(
738         l10n_util::GetStringUTF8(IDS_CERT_MANAGER_SERVER_IMPORT_ERROR_TITLE),
739         l10n_util::GetStringFUTF8(IDS_CERT_MANAGER_READ_ERROR_FORMAT,
740                                   UTF8ToUTF16(safe_strerror(read_errno))));
741     return;
742   }
743 
744   selected_cert_list_ = net::X509Certificate::CreateCertificateListFromBytes(
745           data.data(), data.size(), net::X509Certificate::FORMAT_AUTO);
746   if (selected_cert_list_.empty()) {
747     ImportExportCleanup();
748     ShowError(
749         l10n_util::GetStringUTF8(IDS_CERT_MANAGER_SERVER_IMPORT_ERROR_TITLE),
750         l10n_util::GetStringUTF8(IDS_CERT_MANAGER_CERT_PARSE_ERROR));
751     return;
752   }
753 
754   net::CertDatabase::ImportCertFailureList not_imported;
755   bool result = certificate_manager_model_->ImportServerCert(
756       selected_cert_list_,
757       &not_imported);
758   if (!result) {
759     ShowError(
760         l10n_util::GetStringUTF8(IDS_CERT_MANAGER_SERVER_IMPORT_ERROR_TITLE),
761         l10n_util::GetStringUTF8(IDS_CERT_MANAGER_UNKNOWN_ERROR));
762   } else if (!not_imported.empty()) {
763     ShowImportErrors(
764         l10n_util::GetStringUTF8(IDS_CERT_MANAGER_SERVER_IMPORT_ERROR_TITLE),
765         not_imported);
766   }
767   ImportExportCleanup();
768 }
769 
ImportCA(const ListValue * args)770 void CertificateManagerHandler::ImportCA(const ListValue* args) {
771   select_file_dialog_ = SelectFileDialog::Create(this);
772   ShowCertSelectFileDialog(select_file_dialog_.get(),
773                            SelectFileDialog::SELECT_OPEN_FILE,
774                            FilePath(),
775                            web_ui_->tab_contents(),
776                            GetParentWindow(),
777                            reinterpret_cast<void*>(IMPORT_CA_FILE_SELECTED));
778 }
779 
ImportCAFileSelected(const FilePath & path)780 void CertificateManagerHandler::ImportCAFileSelected(const FilePath& path) {
781   file_path_ = path;
782   file_access_provider_->StartRead(
783       file_path_,
784       &consumer_,
785       NewCallback(this, &CertificateManagerHandler::ImportCAFileRead));
786 }
787 
ImportCAFileRead(int read_errno,std::string data)788 void CertificateManagerHandler::ImportCAFileRead(int read_errno,
789                                                  std::string data) {
790   if (read_errno) {
791     ImportExportCleanup();
792     ShowError(
793         l10n_util::GetStringUTF8(IDS_CERT_MANAGER_CA_IMPORT_ERROR_TITLE),
794         l10n_util::GetStringFUTF8(IDS_CERT_MANAGER_READ_ERROR_FORMAT,
795                                   UTF8ToUTF16(safe_strerror(read_errno))));
796     return;
797   }
798 
799   selected_cert_list_ = net::X509Certificate::CreateCertificateListFromBytes(
800           data.data(), data.size(), net::X509Certificate::FORMAT_AUTO);
801   if (selected_cert_list_.empty()) {
802     ImportExportCleanup();
803     ShowError(
804         l10n_util::GetStringUTF8(IDS_CERT_MANAGER_CA_IMPORT_ERROR_TITLE),
805         l10n_util::GetStringUTF8(IDS_CERT_MANAGER_CERT_PARSE_ERROR));
806     return;
807   }
808 
809   scoped_refptr<net::X509Certificate> root_cert =
810       certificate_manager_model_->cert_db().FindRootInList(selected_cert_list_);
811 
812   // TODO(mattm): check here if root_cert is not a CA cert and show error.
813 
814   StringValue cert_name(root_cert->subject().GetDisplayName());
815   web_ui_->CallJavascriptFunction("CertificateEditCaTrustOverlay.showImport",
816                                   cert_name);
817 }
818 
ImportCATrustSelected(const ListValue * args)819 void CertificateManagerHandler::ImportCATrustSelected(const ListValue* args) {
820   bool fail = false;
821   bool trust_ssl = false;
822   bool trust_email = false;
823   bool trust_obj_sign = false;
824   fail |= !CallbackArgsToBool(args, 0, &trust_ssl);
825   fail |= !CallbackArgsToBool(args, 1, &trust_email);
826   fail |= !CallbackArgsToBool(args, 2, &trust_obj_sign);
827   if (fail) {
828     LOG(ERROR) << "ImportCATrustSelected args fail";
829     ImportExportCleanup();
830     web_ui_->CallJavascriptFunction("CertificateEditCaTrustOverlay.dismiss");
831     return;
832   }
833 
834   net::CertDatabase::ImportCertFailureList not_imported;
835   bool result = certificate_manager_model_->ImportCACerts(
836       selected_cert_list_,
837       trust_ssl * net::CertDatabase::TRUSTED_SSL +
838           trust_email * net::CertDatabase::TRUSTED_EMAIL +
839           trust_obj_sign * net::CertDatabase::TRUSTED_OBJ_SIGN,
840       &not_imported);
841   web_ui_->CallJavascriptFunction("CertificateEditCaTrustOverlay.dismiss");
842   if (!result) {
843     ShowError(
844         l10n_util::GetStringUTF8(IDS_CERT_MANAGER_CA_IMPORT_ERROR_TITLE),
845         l10n_util::GetStringUTF8(IDS_CERT_MANAGER_UNKNOWN_ERROR));
846   } else if (!not_imported.empty()) {
847     ShowImportErrors(
848         l10n_util::GetStringUTF8(IDS_CERT_MANAGER_CA_IMPORT_ERROR_TITLE),
849         not_imported);
850   }
851   ImportExportCleanup();
852 }
853 
Export(const ListValue * args)854 void CertificateManagerHandler::Export(const ListValue* args) {
855   net::X509Certificate* cert = CallbackArgsToCert(args);
856   if (!cert)
857     return;
858   ShowCertExportDialog(web_ui_->tab_contents(), GetParentWindow(),
859                        cert->os_cert_handle());
860 }
861 
Delete(const ListValue * args)862 void CertificateManagerHandler::Delete(const ListValue* args) {
863   net::X509Certificate* cert = CallbackArgsToCert(args);
864   if (!cert)
865     return;
866   bool result = certificate_manager_model_->Delete(cert);
867   if (!result) {
868     // TODO(mattm): better error messages?
869     ShowError(
870         l10n_util::GetStringUTF8(IDS_CERT_MANAGER_DELETE_CERT_ERROR_TITLE),
871         l10n_util::GetStringUTF8(IDS_CERT_MANAGER_UNKNOWN_ERROR));
872   }
873 }
874 
Populate(const ListValue * args)875 void CertificateManagerHandler::Populate(const ListValue* args) {
876   certificate_manager_model_->Refresh();
877 }
878 
PopulateTree(const std::string & tab_name,net::CertType type)879 void CertificateManagerHandler::PopulateTree(const std::string& tab_name,
880                                              net::CertType type) {
881   const std::string tree_name = tab_name + "-tree";
882 
883   scoped_ptr<icu::Collator> collator;
884   UErrorCode error = U_ZERO_ERROR;
885   collator.reset(
886       icu::Collator::createInstance(
887           icu::Locale(g_browser_process->GetApplicationLocale().c_str()),
888           error));
889   if (U_FAILURE(error))
890     collator.reset(NULL);
891   DictionaryIdComparator comparator(collator.get());
892   CertificateManagerModel::OrgGroupingMap map;
893 
894   certificate_manager_model_->FilterAndBuildOrgGroupingMap(type, &map);
895 
896   {
897     ListValue* nodes = new ListValue;
898     for (CertificateManagerModel::OrgGroupingMap::iterator i = map.begin();
899          i != map.end(); ++i) {
900       // Populate first level (org name).
901       DictionaryValue* dict = new DictionaryValue;
902       dict->SetString(kKeyId, OrgNameToId(i->first));
903       dict->SetString(kNameId, i->first);
904 
905       // Populate second level (certs).
906       ListValue* subnodes = new ListValue;
907       for (net::CertificateList::const_iterator org_cert_it = i->second.begin();
908            org_cert_it != i->second.end(); ++org_cert_it) {
909         DictionaryValue* cert_dict = new DictionaryValue;
910         net::X509Certificate* cert = org_cert_it->get();
911         cert_dict->SetString(kKeyId, CertToId(*cert));
912         cert_dict->SetString(kNameId, certificate_manager_model_->GetColumnText(
913             *cert, CertificateManagerModel::COL_SUBJECT_NAME));
914         cert_dict->SetBoolean(
915             kReadOnlyId,
916             certificate_manager_model_->cert_db().IsReadOnly(cert));
917         // TODO(mattm): Other columns.
918         cert_dict->SetString(kIconId, "none");
919         subnodes->Append(cert_dict);
920       }
921       std::sort(subnodes->begin(), subnodes->end(), comparator);
922 
923       dict->Set(kSubNodesId, subnodes);
924       nodes->Append(dict);
925     }
926     std::sort(nodes->begin(), nodes->end(), comparator);
927 
928     ListValue args;
929     args.Append(Value::CreateStringValue(tree_name));
930     args.Append(nodes);
931     web_ui_->CallJavascriptFunction("CertificateManager.onPopulateTree", args);
932   }
933 }
934 
ShowError(const std::string & title,const std::string & error) const935 void CertificateManagerHandler::ShowError(const std::string& title,
936                                           const std::string& error) const {
937   ScopedVector<const Value> args;
938   args.push_back(Value::CreateStringValue(title));
939   args.push_back(Value::CreateStringValue(error));
940   args.push_back(Value::CreateStringValue(l10n_util::GetStringUTF8(IDS_OK)));
941   args.push_back(Value::CreateNullValue());  // cancelTitle
942   args.push_back(Value::CreateNullValue());  // okCallback
943   args.push_back(Value::CreateNullValue());  // cancelCallback
944   web_ui_->CallJavascriptFunction("AlertOverlay.show", args.get());
945 }
946 
ShowImportErrors(const std::string & title,const net::CertDatabase::ImportCertFailureList & not_imported) const947 void CertificateManagerHandler::ShowImportErrors(
948     const std::string& title,
949     const net::CertDatabase::ImportCertFailureList& not_imported) const {
950   std::string error;
951   if (selected_cert_list_.size() == 1)
952     error = l10n_util::GetStringUTF8(
953         IDS_CERT_MANAGER_IMPORT_SINGLE_NOT_IMPORTED);
954   else if (not_imported.size() == selected_cert_list_.size())
955     error = l10n_util::GetStringUTF8(IDS_CERT_MANAGER_IMPORT_ALL_NOT_IMPORTED);
956   else
957     error = l10n_util::GetStringUTF8(IDS_CERT_MANAGER_IMPORT_SOME_NOT_IMPORTED);
958 
959   ListValue cert_error_list;
960   for (size_t i = 0; i < not_imported.size(); ++i) {
961     const net::CertDatabase::ImportCertFailure& failure = not_imported[i];
962     DictionaryValue* dict = new DictionaryValue;
963     dict->SetString(kNameId, failure.certificate->subject().GetDisplayName());
964     dict->SetString(kErrorId, NetErrorToString(failure.net_error));
965     cert_error_list.Append(dict);
966   }
967 
968   StringValue title_value(title);
969   StringValue error_value(error);
970   web_ui_->CallJavascriptFunction("CertificateImportErrorOverlay.show",
971                                   title_value,
972                                   error_value,
973                                   cert_error_list);
974 }
975 
976 #if defined(OS_CHROMEOS)
CheckTpmTokenReady(const ListValue * args)977 void CertificateManagerHandler::CheckTpmTokenReady(const ListValue* args) {
978   chromeos::CryptohomeLibrary* cryptohome =
979       chromeos::CrosLibrary::Get()->GetCryptohomeLibrary();
980 
981   // TODO(xiyuan): Use async way when underlying supports it.
982   FundamentalValue ready(cryptohome->Pkcs11IsTpmTokenReady());
983   web_ui_->CallJavascriptFunction("CertificateManager.onCheckTpmTokenReady",
984                                   ready);
985 }
986 #endif
987 
GetParentWindow() const988 gfx::NativeWindow CertificateManagerHandler::GetParentWindow() const {
989   return web_ui_->tab_contents()->view()->GetTopLevelNativeWindow();
990 }
991