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

Side by Side Diff: runtime/bin/secure_socket.cc

Issue 21716004: dart:io | Add SecureSocket.importPrivateCertificates, that reads a PKCS#12 file. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Cleanup the CL Created 7 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a 2 // for details. All rights reserved. Use of this source code is governed by a
3 // BSD-style license that can be found in the LICENSE file. 3 // BSD-style license that can be found in the LICENSE file.
4 4
5 #include "bin/secure_socket.h" 5 #include "bin/secure_socket.h"
6 6
7 #include <errno.h> 7 #include <errno.h>
8 #include <fcntl.h> 8 #include <fcntl.h>
9 #include <sys/stat.h> 9 #include <sys/stat.h>
10 #include <stdio.h> 10 #include <stdio.h>
11 #include <string.h> 11 #include <string.h>
12 12
13 #include <certdb.h>
13 #include <key.h> 14 #include <key.h>
14 #include <keyt.h> 15 #include <keyt.h>
15 #include <nss.h> 16 #include <nss.h>
17 #include <p12.h>
18 #include <p12plcy.h>
16 #include <pk11pub.h> 19 #include <pk11pub.h>
17 #include <prerror.h> 20 #include <prerror.h>
18 #include <prinit.h> 21 #include <prinit.h>
19 #include <prnetdb.h> 22 #include <prnetdb.h>
20 #include <secmod.h> 23 #include <secmod.h>
21 #include <ssl.h> 24 #include <ssl.h>
22 #include <sslproto.h> 25 #include <sslproto.h>
23 26
24 #include "bin/builtin.h" 27 #include "bin/builtin.h"
25 #include "bin/dartutils.h" 28 #include "bin/dartutils.h"
26 #include "bin/net/nss_memio.h" 29 #include "bin/net/nss_memio.h"
27 #include "bin/socket.h" 30 #include "bin/socket.h"
28 #include "bin/thread.h" 31 #include "bin/thread.h"
29 #include "bin/utils.h" 32 #include "bin/utils.h"
30 #include "platform/utils.h" 33 #include "platform/utils.h"
31 34
32 #include "include/dart_api.h" 35 #include "include/dart_api.h"
33 36
34 37
35 namespace dart { 38 namespace dart {
36 namespace bin { 39 namespace bin {
37 40
38 bool SSLFilter::library_initialized_ = false; 41 bool SSLFilter::library_initialized_ = false;
39 // To protect library initialization. 42 // To protect library initialization.
40 dart::Mutex* SSLFilter::mutex_ = new dart::Mutex(); 43 dart::Mutex* SSLFilter::mutex_ = new dart::Mutex();
41 // The password is needed when creating secure server sockets. It can 44 // The password is needed when creating secure server sockets. It can
42 // be null if only secure client sockets are used. 45 // be null if only secure client sockets are used.
43 const char* SSLFilter::password_ = NULL; 46 char* SSLFilter::password_ = NULL;
44 47
45 // Forward declaration. 48 // Forward declaration.
46 static void ProcessFilter(Dart_Port dest_port_id, 49 static void ProcessFilter(Dart_Port dest_port_id,
47 Dart_Port reply_port_id, 50 Dart_Port reply_port_id,
48 Dart_CObject* message); 51 Dart_CObject* message);
49 52
50 NativeService SSLFilter::filter_service_("FilterService", ProcessFilter, 16); 53 NativeService SSLFilter::filter_service_("FilterService", ProcessFilter, 16);
51 54
52 static const int kSSLFilterNativeFieldIndex = 0; 55 static const int kSSLFilterNativeFieldIndex = 0;
53 56
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after
97 100
98 static void SetFilter(Dart_NativeArguments args, SSLFilter* filter) { 101 static void SetFilter(Dart_NativeArguments args, SSLFilter* filter) {
99 Dart_Handle dart_this = ThrowIfError(Dart_GetNativeArgument(args, 0)); 102 Dart_Handle dart_this = ThrowIfError(Dart_GetNativeArgument(args, 0));
100 ASSERT(Dart_IsInstance(dart_this)); 103 ASSERT(Dart_IsInstance(dart_this));
101 ThrowIfError(Dart_SetNativeInstanceField( 104 ThrowIfError(Dart_SetNativeInstanceField(
102 dart_this, 105 dart_this,
103 kSSLFilterNativeFieldIndex, 106 kSSLFilterNativeFieldIndex,
104 reinterpret_cast<intptr_t>(filter))); 107 reinterpret_cast<intptr_t>(filter)));
105 } 108 }
106 109
107 110
Søren Gjesse 2013/08/07 07:32:28 Maybe move this function closer to where it is use
Bill Hesse 2013/08/08 17:39:21 I have had to keep moving it up and up, as I add u
111 char* PasswordCallback(PK11SlotInfo* slot, PRBool retry, void* arg) {
112 if (!retry) {
113 return PL_strdup(static_cast<char*>(arg)); // Freed by NSS internals.
114 }
115 return NULL;
116 }
117
118
108 void FUNCTION_NAME(SecureSocket_Init)(Dart_NativeArguments args) { 119 void FUNCTION_NAME(SecureSocket_Init)(Dart_NativeArguments args) {
109 Dart_EnterScope(); 120 Dart_EnterScope();
110 Dart_Handle dart_this = ThrowIfError(Dart_GetNativeArgument(args, 0)); 121 Dart_Handle dart_this = ThrowIfError(Dart_GetNativeArgument(args, 0));
111 SSLFilter* filter = new SSLFilter; 122 SSLFilter* filter = new SSLFilter;
112 SetFilter(args, filter); 123 SetFilter(args, filter);
113 filter->Init(dart_this); 124 filter->Init(dart_this);
114 Dart_ExitScope(); 125 Dart_ExitScope();
115 } 126 }
116 127
117 128
(...skipping 119 matching lines...) Expand 10 before | Expand all | Expand 10 after
237 Dart_EnterScope(); 248 Dart_EnterScope();
238 Dart_Handle certificate_database_object = 249 Dart_Handle certificate_database_object =
239 ThrowIfError(Dart_GetNativeArgument(args, 0)); 250 ThrowIfError(Dart_GetNativeArgument(args, 0));
240 // Check that the type is string, and get the UTF-8 C string value from it. 251 // Check that the type is string, and get the UTF-8 C string value from it.
241 const char* certificate_database = NULL; 252 const char* certificate_database = NULL;
242 if (Dart_IsString(certificate_database_object)) { 253 if (Dart_IsString(certificate_database_object)) {
243 ThrowIfError(Dart_StringToCString(certificate_database_object, 254 ThrowIfError(Dart_StringToCString(certificate_database_object,
244 &certificate_database)); 255 &certificate_database));
245 } else if (!Dart_IsNull(certificate_database_object)) { 256 } else if (!Dart_IsNull(certificate_database_object)) {
246 Dart_ThrowException(DartUtils::NewDartArgumentError( 257 Dart_ThrowException(DartUtils::NewDartArgumentError(
247 "Non-String certificate directory argument to SetCertificateDatabase")); 258 "SecureSocket.initialize: database argument is not a String or null"));
248 } 259 }
249 // Leave certificate_database as NULL if no value was provided. 260 // Leave certificate_database as NULL if no value was provided.
250 261
251 Dart_Handle password_object = ThrowIfError(Dart_GetNativeArgument(args, 1)); 262 Dart_Handle password_object = ThrowIfError(Dart_GetNativeArgument(args, 1));
252 // Check that the type is string or null, 263 // Check that the type is string or null,
253 // and get the UTF-8 C string value from it. 264 // and get the UTF-8 C string value from it.
254 const char* password = NULL; 265 const char* password = NULL;
255 if (Dart_IsString(password_object)) { 266 if (Dart_IsString(password_object)) {
256 ThrowIfError(Dart_StringToCString(password_object, &password)); 267 ThrowIfError(Dart_StringToCString(password_object, &password));
257 } else if (Dart_IsNull(password_object)) { 268 } else if (Dart_IsNull(password_object)) {
258 // Pass the empty string as the password. 269 // Pass the empty string as the password.
259 password = ""; 270 password = "";
260 } else { 271 } else {
261 Dart_ThrowException(DartUtils::NewDartArgumentError( 272 Dart_ThrowException(DartUtils::NewDartArgumentError(
262 "Password argument to SetCertificateDatabase is not a String or null")); 273 "SecureSocket.initialize: password argument is not a String or null"));
263 } 274 }
264 275
265 Dart_Handle builtin_roots_object = 276 Dart_Handle builtin_roots_object =
266 ThrowIfError(Dart_GetNativeArgument(args, 2)); 277 ThrowIfError(Dart_GetNativeArgument(args, 2));
267 // Check that the type is boolean, and get the boolean value from it. 278 // Check that the type is boolean, and get the boolean value from it.
268 bool builtin_roots = true; 279 bool builtin_roots = true;
269 if (Dart_IsBoolean(builtin_roots_object)) { 280 if (Dart_IsBoolean(builtin_roots_object)) {
270 ThrowIfError(Dart_BooleanValue(builtin_roots_object, &builtin_roots)); 281 ThrowIfError(Dart_BooleanValue(builtin_roots_object, &builtin_roots));
271 } else { 282 } else {
272 Dart_ThrowException(DartUtils::NewDartArgumentError( 283 Dart_ThrowException(DartUtils::NewDartArgumentError(
273 "UseBuiltinRoots argument to SetCertificateDatabase is not a bool")); 284 "SecureSocket.initialize: useBuiltinRoots argument is not a bool"));
274 } 285 }
275 286
276 SSLFilter::InitializeLibrary(certificate_database, password, builtin_roots); 287 Dart_Handle read_only_object =
288 ThrowIfError(Dart_GetNativeArgument(args, 3));
289 // Check that the type is boolean, and get the boolean value from it.
290 bool read_only = true;
291 if (Dart_IsBoolean(read_only_object)) {
292 ThrowIfError(Dart_BooleanValue(read_only_object, &read_only));
293 } else {
294 Dart_ThrowException(DartUtils::NewDartArgumentError(
295 "SecureSocket.initialize: readOnly argument is not a bool"));
296 }
297
298 SSLFilter::InitializeLibrary(
299 certificate_database, password, builtin_roots, read_only);
277 Dart_ExitScope(); 300 Dart_ExitScope();
278 } 301 }
279 302
280 303
281 static Dart_Handle X509FromCertificate(CERTCertificate* certificate) { 304 static Dart_Handle X509FromCertificate(CERTCertificate* certificate) {
282 PRTime start_validity; 305 PRTime start_validity;
283 PRTime end_validity; 306 PRTime end_validity;
284 SECStatus status = 307 SECStatus status =
285 CERT_GetCertTimes(certificate, &start_validity, &end_validity); 308 CERT_GetCertTimes(certificate, &start_validity, &end_validity);
286 if (status != SECSuccess) { 309 if (status != SECSuccess) {
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after
356 if (status != SECSuccess) { 379 if (status != SECSuccess) {
357 ThrowPRException("CertificateException", "Cannot set trust attributes"); 380 ThrowPRException("CertificateException", "Cannot set trust attributes");
358 } 381 }
359 382
360 Dart_SetReturnValue(args, X509FromCertificate(cert)); 383 Dart_SetReturnValue(args, X509FromCertificate(cert));
361 Dart_ExitScope(); 384 Dart_ExitScope();
362 return; 385 return;
363 } 386 }
364 387
365 388
389 /*
390 * Called by the PKCS#12 decoder if a certificate's nickname collides with
391 * the nickname of a different existing certificate in the database.
392 */
393 SECItem* nickname_callback(SECItem *old_nickname,
394 PRBool *cancel,
395 void *arg) {
wtc 2013/08/06 17:52:48 Nit: fix the indentation of the second and third f
Bill Hesse 2013/08/08 17:39:21 Done.
396 *cancel = PR_TRUE;
397 return NULL;
398 }
399
400
401 void FUNCTION_NAME(SecureSocket_ImportPrivateCertificates)
wtc 2013/08/06 17:52:48 Certificates with corresponding private keys are c
Bill Hesse 2013/08/08 17:39:21 Done.
402 (Dart_NativeArguments args) {
403 Dart_EnterScope();
404 Dart_Handle pk12_object = ThrowIfError(Dart_GetNativeArgument(args, 0));
405 if (!Dart_IsList(pk12_object)) {
406 Dart_ThrowException(DartUtils::NewDartArgumentError(
407 "SecureSocket.importPrivateCertificates: certificates is not a List"));
408 }
409
410 Dart_Handle password_object = ThrowIfError(Dart_GetNativeArgument(args, 1));
411 if (!Dart_IsString(password_object)) {
412 Dart_ThrowException(DartUtils::NewDartArgumentError(
413 "SecureSocket.importPrivateCertificates: password is not a String"));
414 }
415
416 intptr_t length;
417 ThrowIfError(Dart_ListLength(pk12_object, &length));
418 uint8_t* pk12 = Dart_ScopeAllocate(length + 1); // Why +1 ?
Søren Gjesse 2013/08/07 07:32:28 Yes, why + 1?
419 if (pk12 == NULL) {
420 FATAL("Out of memory in SecureSocket.importPrivateCertificates");
421 }
422 ThrowIfError(Dart_ListGetAsBytes(pk12_object, 0, pk12, length));
423
424 // A big-endian Unicode (UTF16) password.
Søren Gjesse 2013/08/07 07:32:28 So the PKCS12 functions use a password in big-endi
Søren Gjesse 2013/08/07 07:32:28 Also you could consider building this in Dart code
Bill Hesse 2013/08/08 17:39:21 The behavior depends on whether the host is big-en
425 intptr_t password_length;
426 ThrowIfError(Dart_StringLength(password_object, &password_length));
427 password_length++;
428 uint16_t* password = reinterpret_cast<uint16_t*>(
429 Dart_ScopeAllocate(2 * password_length));
430 if (password == NULL) {
431 FATAL("Out of memory in SecureSocket.importPrivateCertificates");
432 }
433 intptr_t returned_length = password_length;
434 ThrowIfError(Dart_StringToUTF16(password_object, password, &returned_length));
435 ASSERT(password_length == returned_length + 1);
436 password[password_length - 1] = 0;
437 for (int i = 0; i < password_length; ++i) {
438 password[i] = Utils::HostToBigEndian16(password[i]);
439 }
440 SECItem p12_password;
441 p12_password.type = siBuffer;
442 p12_password.data = (unsigned char*)password;
wtc 2013/08/06 17:52:48 Nit: reinterpret_cast<unsigned char*>(password)
Bill Hesse 2013/08/08 17:39:21 Done.
443 p12_password.len = 2 * password_length;
444
445 Dart_SetReturnValue(args, Dart_Null());
446 // Set the password callback for the certificate database we are importing to.
Søren Gjesse 2013/08/07 07:32:28 Please explain how this callback is used by nss. I
Bill Hesse 2013/08/08 17:39:21 It returns a newly allocated copy of its argument.
447 PK11_SetPasswordFunc(PasswordCallback);
448 PK11SlotInfo* slot = PK11_GetInternalKeySlot();
449 SECStatus status = PK11_Authenticate(slot, PR_TRUE, SSLFilter::GetPassword());
450 if (status == SECFailure) {
451 ThrowPRException("CertificateException",
452 "Could not authenticate to certificate database");
453 }
454
455 SEC_PKCS12DecoderContext* context = SEC_PKCS12DecoderStart(
456 &p12_password,
457 slot,
458 SSLFilter::GetPassword(),
459 NULL,
460 NULL,
461 NULL,
462 NULL,
463 NULL);
464 if (!context) {
465 FATAL("Unexpected error: SecureSocket.addPrivateCertificates DecoderStart");
466 }
467
468 if (SECSuccess == SEC_PKCS12DecoderUpdate(context, pk12, length) &&
469 SECSuccess == SEC_PKCS12DecoderVerify(context) &&
470 SECSuccess == SEC_PKCS12DecoderValidateBags(context, nickname_callback) &&
471 SECSuccess == SEC_PKCS12DecoderImportBags(context)) {
472 SEC_PKCS12DecoderFinish(context);
Søren Gjesse 2013/08/07 07:32:28 "Hiding" the Dart_ExitScope here for the succesful
Bill Hesse 2013/08/08 17:39:21 No more EnterScope and ExitScopes.
473 Dart_ExitScope();
474 return;
475 } else {
wtc 2013/08/06 17:52:48 Nit: some projects have a convention of omitting "
Bill Hesse 2013/08/08 17:39:21 Code rewritten differently.
476 SEC_PKCS12DecoderFinish(context);
477 ThrowPRException("CertificateException",
478 "Could not import PKCS#12 file");
479 }
Søren Gjesse 2013/08/07 07:32:28 Nice use of Dart_ScopeAllocate - Only the context
Bill Hesse 2013/08/08 17:39:21 The password callback stays the same for the entir
480 }
481
482
483 void FUNCTION_NAME(SecureSocket_ChangeTrust)(Dart_NativeArguments args) {
484 Dart_EnterScope();
485 Dart_Handle nickname_object = ThrowIfError(Dart_GetNativeArgument(args, 0));
486 if (!Dart_IsString(nickname_object)) {
487 Dart_ThrowException(DartUtils::NewDartArgumentError(
488 "SecureSocket.changeTrust: nickname argument is not a String"));
489 }
490 const char* nickname;
491 ThrowIfError(Dart_StringToCString(nickname_object, &nickname));
492
493 Dart_Handle trust_object = ThrowIfError(Dart_GetNativeArgument(args, 1));
494 if (!Dart_IsString(trust_object)) {
495 Dart_ThrowException(DartUtils::NewDartArgumentError(
496 "SecureSocket.changeTrust: trust argument is not a String"));
497 }
498 const char* trust_string;
499 ThrowIfError(Dart_StringToCString(trust_object, &trust_string));
500
501 CERTCertificate* certificate =
502 PK11_FindCertFromNickname(nickname, SSLFilter::GetPassword());
503 if (certificate == NULL) {
504 ThrowCertificateException("Cannot find certificate with nickname %s",
505 nickname);
506 }
507 CERTCertTrust trust;
508 SECStatus status = CERT_DecodeTrustString(&trust, trust_string);
509 if (status != SECSuccess) {
510 ThrowPRException("CertificateException", "Trust string cannot be decoded");
wtc 2013/08/06 17:52:48 If these ThrowPRException calls also return from t
Bill Hesse 2013/08/08 17:39:21 Done.
511 }
512 status = CERT_ChangeCertTrust(CERT_GetDefaultCertDB(), certificate, &trust);
513 if (status != SECSuccess) {
514 ThrowCertificateException("Cannot set trust on certificate %s", nickname);
515 }
516
517 CERT_DestroyCertificate(certificate);
518 Dart_ExitScope();
519 }
520
521
522 void FUNCTION_NAME(SecureSocket_RemoveCertificate)(Dart_NativeArguments args) {
523 Dart_EnterScope();
524 Dart_Handle nickname_object =
525 ThrowIfError(Dart_GetNativeArgument(args, 0));
526 if (!Dart_IsString(nickname_object)) {
527 Dart_ThrowException(DartUtils::NewDartArgumentError(
528 "SecureSocket.removeCertificate: nickname is not a String"));
529 }
530 const char* nickname;
531 ThrowIfError(Dart_StringToCString(nickname_object, &nickname));
532
533 CERTCertificate* certificate =
534 PK11_FindCertFromNickname(nickname, SSLFilter::GetPassword());
535 if (certificate == NULL) {
536 ThrowCertificateException("Cannot find certificate with nickname %s",
537 nickname);
538 }
539 SECKEYPrivateKey* key =
540 PK11_FindKeyByAnyCert(certificate, SSLFilter::GetPassword());
541 // Free the copy returned from FindKeyByAnyCert.
542 SECKEY_DestroyPrivateKey(key);
543 SECStatus status = (key == NULL) ?
544 SEC_DeletePermCertificate(certificate) :
545 PK11_DeleteTokenCertAndKey(certificate, SSLFilter::GetPassword());
546 if (status == SECFailure) {
547 CERT_DestroyCertificate(certificate);
548 ThrowCertificateException("Cannot remove certificate %s", nickname);
549 }
wtc 2013/08/06 17:52:48 CERT_DestroyCertificate(certificate) should also b
Bill Hesse 2013/08/08 17:39:21 Done.
550 Dart_ExitScope();
551 }
552
366 553
367 void FUNCTION_NAME(SecureSocket_PeerCertificate) 554 void FUNCTION_NAME(SecureSocket_PeerCertificate)
368 (Dart_NativeArguments args) { 555 (Dart_NativeArguments args) {
369 Dart_EnterScope(); 556 Dart_EnterScope();
370 Dart_SetReturnValue(args, GetFilter(args)->PeerCertificate()); 557 Dart_SetReturnValue(args, GetFilter(args)->PeerCertificate());
371 Dart_ExitScope(); 558 Dart_ExitScope();
372 } 559 }
373 560
374 561
375 void FUNCTION_NAME(SecureSocket_FilterPointer)(Dart_NativeArguments args) { 562 void FUNCTION_NAME(SecureSocket_FilterPointer)(Dart_NativeArguments args) {
(...skipping 133 matching lines...) Expand 10 before | Expand all | Expand 10 after
509 default: 696 default:
510 UNREACHABLE(); 697 UNREACHABLE();
511 } 698 }
512 } 699 }
513 return true; 700 return true;
514 } 701 }
515 702
516 703
517 void SSLFilter::Init(Dart_Handle dart_this) { 704 void SSLFilter::Init(Dart_Handle dart_this) {
518 if (!library_initialized_) { 705 if (!library_initialized_) {
519 InitializeLibrary(NULL, "", true, false); 706 InitializeLibrary(NULL, "", true, true, false);
520 } 707 }
521 ASSERT(string_start_ == NULL); 708 ASSERT(string_start_ == NULL);
522 string_start_ = Dart_NewPersistentHandle(DartUtils::NewString("start")); 709 string_start_ = Dart_NewPersistentHandle(DartUtils::NewString("start"));
523 ASSERT(string_start_ != NULL); 710 ASSERT(string_start_ != NULL);
524 ASSERT(string_length_ == NULL); 711 ASSERT(string_length_ == NULL);
525 string_length_ = Dart_NewPersistentHandle(DartUtils::NewString("length")); 712 string_length_ = Dart_NewPersistentHandle(DartUtils::NewString("length"));
526 ASSERT(string_length_ != NULL); 713 ASSERT(string_length_ != NULL);
527 ASSERT(bad_certificate_callback_ == NULL); 714 ASSERT(bad_certificate_callback_ == NULL);
528 bad_certificate_callback_ = Dart_NewPersistentHandle(Dart_Null()); 715 bad_certificate_callback_ = Dart_NewPersistentHandle(Dart_Null());
529 ASSERT(bad_certificate_callback_ != NULL); 716 ASSERT(bad_certificate_callback_ != NULL);
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after
582 769
583 770
584 void SSLFilter::RegisterBadCertificateCallback(Dart_Handle callback) { 771 void SSLFilter::RegisterBadCertificateCallback(Dart_Handle callback) {
585 ASSERT(bad_certificate_callback_ != NULL); 772 ASSERT(bad_certificate_callback_ != NULL);
586 Dart_DeletePersistentHandle(bad_certificate_callback_); 773 Dart_DeletePersistentHandle(bad_certificate_callback_);
587 bad_certificate_callback_ = Dart_NewPersistentHandle(callback); 774 bad_certificate_callback_ = Dart_NewPersistentHandle(callback);
588 ASSERT(bad_certificate_callback_ != NULL); 775 ASSERT(bad_certificate_callback_ != NULL);
589 } 776 }
590 777
591 778
592 char* PasswordCallback(PK11SlotInfo* slot, PRBool retry, void* arg) {
593 if (!retry) {
594 return PL_strdup(static_cast<char*>(arg)); // Freed by NSS internals.
595 }
596 return NULL;
597 }
598
599
600 static const char* builtin_roots_module = 779 static const char* builtin_roots_module =
601 #if defined(TARGET_OS_LINUX) || defined(TARGET_OS_ANDROID) 780 #if defined(TARGET_OS_LINUX) || defined(TARGET_OS_ANDROID)
602 "name=\"Root Certs\" library=\"libnssckbi.so\""; 781 "name=\"Root Certs\" library=\"libnssckbi.so\"";
603 #elif defined(TARGET_OS_MACOS) 782 #elif defined(TARGET_OS_MACOS)
604 "name=\"Root Certs\" library=\"libnssckbi.dylib\""; 783 "name=\"Root Certs\" library=\"libnssckbi.dylib\"";
605 #elif defined(TARGET_OS_WINDOWS) 784 #elif defined(TARGET_OS_WINDOWS)
606 "name=\"Root Certs\" library=\"nssckbi.dll\""; 785 "name=\"Root Certs\" library=\"nssckbi.dll\"";
607 #else 786 #else
608 #error Automatic target os detection failed. 787 #error Automatic target os detection failed.
609 #endif 788 #endif
610 789
611 790
612 791
613 void SSLFilter::InitializeLibrary(const char* certificate_database, 792 void SSLFilter::InitializeLibrary(const char* certificate_database,
614 const char* password, 793 const char* password,
615 bool use_builtin_root_certificates, 794 bool use_builtin_root_certificates,
795 bool read_only,
616 bool report_duplicate_initialization) { 796 bool report_duplicate_initialization) {
617 MutexLocker locker(mutex_); 797 MutexLocker locker(mutex_);
618 SECStatus status; 798 SECStatus status;
619 if (!library_initialized_) { 799 if (!library_initialized_) {
620 PR_Init(PR_USER_THREAD, PR_PRIORITY_NORMAL, 0); 800 PR_Init(PR_USER_THREAD, PR_PRIORITY_NORMAL, 0);
621 // TODO(whesse): Verify there are no UTF-8 issues here. 801 // TODO(whesse): Verify there are no UTF-8 issues here.
622 if (certificate_database == NULL || certificate_database[0] == '\0') { 802 if (certificate_database == NULL || certificate_database[0] == '\0') {
623 status = NSS_NoDB_Init(NULL); 803 status = NSS_NoDB_Init(NULL);
624 if (status != SECSuccess) { 804 if (status != SECSuccess) {
625 mutex_->Unlock(); // MutexLocker destructor not called when throwing. 805 mutex_->Unlock(); // MutexLocker destructor not called when throwing.
626 ThrowPRException("TlsException", 806 ThrowPRException("TlsException",
627 "Failed NSS_NoDB_Init call."); 807 "Failed NSS_NoDB_Init call.");
628 } 808 }
629 if (use_builtin_root_certificates) { 809 if (use_builtin_root_certificates) {
630 SECMODModule* module = SECMOD_LoadUserModule( 810 SECMODModule* module = SECMOD_LoadUserModule(
631 const_cast<char*>(builtin_roots_module), NULL, PR_FALSE); 811 const_cast<char*>(builtin_roots_module), NULL, PR_FALSE);
632 if (!module) { 812 if (!module) {
633 mutex_->Unlock(); // MutexLocker destructor not called when throwing. 813 mutex_->Unlock(); // MutexLocker destructor not called when throwing.
634 ThrowPRException("TlsException", 814 ThrowPRException("TlsException",
635 "Failed to load builtin root certificates."); 815 "Failed to load builtin root certificates.");
636 } 816 }
637 } 817 }
638 } else { 818 } else {
639 PRUint32 init_flags = NSS_INIT_READONLY; 819 PRUint32 init_flags = read_only ? NSS_INIT_READONLY : 0;
640 if (!use_builtin_root_certificates) { 820 if (!use_builtin_root_certificates) {
641 init_flags |= NSS_INIT_NOMODDB; 821 init_flags |= NSS_INIT_NOMODDB;
642 } 822 }
643 status = NSS_Initialize(certificate_database, 823 status = NSS_Initialize(certificate_database,
644 "", 824 "",
645 "", 825 "",
646 SECMOD_DB, 826 SECMOD_DB,
647 init_flags); 827 init_flags);
648 if (status != SECSuccess) { 828 if (status != SECSuccess) {
649 mutex_->Unlock(); // MutexLocker destructor not called when throwing. 829 mutex_->Unlock(); // MutexLocker destructor not called when throwing.
650 ThrowPRException("TlsException", 830 ThrowPRException("TlsException",
651 "Failed NSS_Init call."); 831 "Failed NSS_Init call.");
652 } 832 }
653 password_ = strdup(password); // This one copy persists until Dart exits. 833 password_ = strdup(password); // This one copy persists until Dart exits.
654 PK11_SetPasswordFunc(PasswordCallback); 834 PK11_SetPasswordFunc(PasswordCallback);
655 } 835 }
656 library_initialized_ = true; 836 library_initialized_ = true;
657 837
658 status = NSS_SetDomesticPolicy(); 838 status = NSS_SetDomesticPolicy();
659 if (status != SECSuccess) { 839 if (status != SECSuccess) {
660 mutex_->Unlock(); // MutexLocker destructor not called when throwing. 840 mutex_->Unlock(); // MutexLocker destructor not called when throwing.
661 ThrowPRException("TlsException", 841 ThrowPRException("TlsException",
662 "Failed NSS_SetDomesticPolicy call."); 842 "Failed NSS_SetDomesticPolicy call.");
663 } 843 }
844
845 // Allow encoding and decoding of private keys in PKCS#12 files (.pk files).
wtc 2013/08/06 17:52:48 Common file suffixes for PKCS #11 files are .p12 a
846 SEC_PKCS12EnableCipher(PKCS12_RC4_40, 1);
847 SEC_PKCS12EnableCipher(PKCS12_RC4_128, 1);
848 SEC_PKCS12EnableCipher(PKCS12_RC2_CBC_40, 1);
849 SEC_PKCS12EnableCipher(PKCS12_RC2_CBC_128, 1);
850 SEC_PKCS12EnableCipher(PKCS12_DES_56, 1);
851 SEC_PKCS12EnableCipher(PKCS12_DES_EDE3_168, 1);
852 SEC_PKCS12SetPreferredCipher(PKCS12_DES_EDE3_168, 1);
wtc 2013/08/06 17:52:48 I know these function calls are modeled after the
Bill Hesse 2013/08/08 17:39:21 Done.
853
664 // Enable TLS, as well as SSL3 and SSL2. 854 // Enable TLS, as well as SSL3 and SSL2.
665 status = SSL_OptionSetDefault(SSL_ENABLE_TLS, PR_TRUE); 855 status = SSL_OptionSetDefault(SSL_ENABLE_TLS, PR_TRUE);
666 if (status != SECSuccess) { 856 if (status != SECSuccess) {
667 mutex_->Unlock(); // MutexLocker destructor not called when throwing. 857 mutex_->Unlock(); // MutexLocker destructor not called when throwing.
668 ThrowPRException("TlsException", 858 ThrowPRException("TlsException",
669 "Failed SSL_OptionSetDefault enable TLS call."); 859 "Failed SSL_OptionSetDefault enable TLS call.");
670 } 860 }
671 status = SSL_ConfigServerSessionIDCache(0, 0, 0, NULL); 861 status = SSL_ConfigServerSessionIDCache(0, 0, 0, NULL);
672 if (status != SECSuccess) { 862 if (status != SECSuccess) {
673 mutex_->Unlock(); // MutexLocker destructor not called when throwing. 863 mutex_->Unlock(); // MutexLocker destructor not called when throwing.
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after
744 // Look up certificate using the distinguished name (DN) certificate_name. 934 // Look up certificate using the distinguished name (DN) certificate_name.
745 CERTCertDBHandle* certificate_database = CERT_GetDefaultCertDB(); 935 CERTCertDBHandle* certificate_database = CERT_GetDefaultCertDB();
746 if (certificate_database == NULL) { 936 if (certificate_database == NULL) {
747 ThrowPRException("CertificateException", 937 ThrowPRException("CertificateException",
748 "Certificate database cannot be loaded"); 938 "Certificate database cannot be loaded");
749 } 939 }
750 certificate = CERT_FindCertByNameString(certificate_database, 940 certificate = CERT_FindCertByNameString(certificate_database,
751 const_cast<char*>(certificate_name)); 941 const_cast<char*>(certificate_name));
752 if (certificate == NULL) { 942 if (certificate == NULL) {
753 ThrowCertificateException( 943 ThrowCertificateException(
754 "Cannot find server certificate by distinguished name: %s", 944 "Cannot find server certificate with distinguished name %s",
755 certificate_name); 945 certificate_name);
756 } 946 }
757 } else { 947 } else {
758 // Look up certificate using the nickname certificate_name. 948 // Look up certificate using the nickname certificate_name.
759 certificate = PK11_FindCertFromNickname( 949 certificate = PK11_FindCertFromNickname(
760 const_cast<char*>(certificate_name), 950 const_cast<char*>(certificate_name), GetPassword());
761 static_cast<void*>(const_cast<char*>(password_)));
762 if (certificate == NULL) { 951 if (certificate == NULL) {
763 ThrowCertificateException( 952 ThrowCertificateException(
764 "Cannot find server certificate by nickname: %s", 953 "Cannot find server certificate with nickname %s",
765 certificate_name); 954 certificate_name);
766 } 955 }
767 } 956 }
768 SECKEYPrivateKey* key = PK11_FindKeyByAnyCert( 957 SECKEYPrivateKey* key = PK11_FindKeyByAnyCert(certificate, GetPassword());
wtc 2013/08/06 17:52:48 You don't need to pass the password as the "void *
769 certificate,
770 static_cast<void*>(const_cast<char*>(password_)));
771 if (key == NULL) { 958 if (key == NULL) {
772 CERT_DestroyCertificate(certificate); 959 CERT_DestroyCertificate(certificate);
773 if (PR_GetError() == -8177) { 960 if (PR_GetError() == -8177) {
774 ThrowPRException("CertificateException", 961 ThrowPRException("CertificateException",
775 "Certificate database password incorrect"); 962 "Certificate database password incorrect");
776 } else { 963 } else {
777 ThrowCertificateException( 964 ThrowCertificateException(
778 "Cannot find private key for certificate %s", 965 "Cannot find private key for certificate %s",
779 certificate_name); 966 certificate_name);
780 } 967 }
(...skipping 265 matching lines...) Expand 10 before | Expand all | Expand 10 after
1046 // Return a send port for the service port. 1233 // Return a send port for the service port.
1047 Dart_Handle send_port = Dart_NewSendPort(service_port); 1234 Dart_Handle send_port = Dart_NewSendPort(service_port);
1048 Dart_SetReturnValue(args, send_port); 1235 Dart_SetReturnValue(args, send_port);
1049 } 1236 }
1050 Dart_ExitScope(); 1237 Dart_ExitScope();
1051 } 1238 }
1052 1239
1053 1240
1054 } // namespace bin 1241 } // namespace bin
1055 } // namespace dart 1242 } // namespace dart
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698