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 ¬_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 ¬_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