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

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: Add delayed deletion of locked temp directory on Windows. 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 168 matching lines...) Expand 10 before | Expand all | Expand 10 after
222 (Dart_NativeArguments args) { 225 (Dart_NativeArguments args) {
223 Dart_Handle certificate_database_object = 226 Dart_Handle certificate_database_object =
224 ThrowIfError(Dart_GetNativeArgument(args, 0)); 227 ThrowIfError(Dart_GetNativeArgument(args, 0));
225 // Check that the type is string, and get the UTF-8 C string value from it. 228 // Check that the type is string, and get the UTF-8 C string value from it.
226 const char* certificate_database = NULL; 229 const char* certificate_database = NULL;
227 if (Dart_IsString(certificate_database_object)) { 230 if (Dart_IsString(certificate_database_object)) {
228 ThrowIfError(Dart_StringToCString(certificate_database_object, 231 ThrowIfError(Dart_StringToCString(certificate_database_object,
229 &certificate_database)); 232 &certificate_database));
230 } else if (!Dart_IsNull(certificate_database_object)) { 233 } else if (!Dart_IsNull(certificate_database_object)) {
231 Dart_ThrowException(DartUtils::NewDartArgumentError( 234 Dart_ThrowException(DartUtils::NewDartArgumentError(
232 "Non-String certificate directory argument to SetCertificateDatabase")); 235 "SecureSocket.initialize: database argument is not a String or null"));
233 } 236 }
234 // Leave certificate_database as NULL if no value was provided. 237 // Leave certificate_database as NULL if no value was provided.
235 238
236 Dart_Handle password_object = ThrowIfError(Dart_GetNativeArgument(args, 1)); 239 Dart_Handle password_object = ThrowIfError(Dart_GetNativeArgument(args, 1));
237 // Check that the type is string or null, 240 // Check that the type is string or null,
238 // and get the UTF-8 C string value from it. 241 // and get the UTF-8 C string value from it.
239 const char* password = NULL; 242 const char* password = NULL;
240 if (Dart_IsString(password_object)) { 243 if (Dart_IsString(password_object)) {
241 ThrowIfError(Dart_StringToCString(password_object, &password)); 244 ThrowIfError(Dart_StringToCString(password_object, &password));
242 } else if (Dart_IsNull(password_object)) { 245 } else if (Dart_IsNull(password_object)) {
243 // Pass the empty string as the password. 246 // Pass the empty string as the password.
244 password = ""; 247 password = "";
245 } else { 248 } else {
246 Dart_ThrowException(DartUtils::NewDartArgumentError( 249 Dart_ThrowException(DartUtils::NewDartArgumentError(
247 "Password argument to SetCertificateDatabase is not a String or null")); 250 "SecureSocket.initialize: password argument is not a String or null"));
248 } 251 }
249 252
250 Dart_Handle builtin_roots_object = 253 Dart_Handle builtin_roots_object =
251 ThrowIfError(Dart_GetNativeArgument(args, 2)); 254 ThrowIfError(Dart_GetNativeArgument(args, 2));
252 // Check that the type is boolean, and get the boolean value from it. 255 // Check that the type is boolean, and get the boolean value from it.
253 bool builtin_roots = true; 256 bool builtin_roots = true;
254 if (Dart_IsBoolean(builtin_roots_object)) { 257 if (Dart_IsBoolean(builtin_roots_object)) {
255 ThrowIfError(Dart_BooleanValue(builtin_roots_object, &builtin_roots)); 258 ThrowIfError(Dart_BooleanValue(builtin_roots_object, &builtin_roots));
256 } else { 259 } else {
257 Dart_ThrowException(DartUtils::NewDartArgumentError( 260 Dart_ThrowException(DartUtils::NewDartArgumentError(
258 "UseBuiltinRoots argument to SetCertificateDatabase is not a bool")); 261 "SecureSocket.initialize: useBuiltinRoots argument is not a bool"));
259 } 262 }
260 263
261 SSLFilter::InitializeLibrary(certificate_database, password, builtin_roots); 264 Dart_Handle read_only_object =
265 ThrowIfError(Dart_GetNativeArgument(args, 3));
266 // Check that the type is boolean, and get the boolean value from it.
267 bool read_only = true;
268 if (Dart_IsBoolean(read_only_object)) {
269 ThrowIfError(Dart_BooleanValue(read_only_object, &read_only));
270 } else {
271 Dart_ThrowException(DartUtils::NewDartArgumentError(
272 "SecureSocket.initialize: readOnly argument is not a bool"));
273 }
274
275 SSLFilter::InitializeLibrary(
276 certificate_database, password, builtin_roots, read_only);
262 } 277 }
263 278
264 279
265 static Dart_Handle X509FromCertificate(CERTCertificate* certificate) { 280 static Dart_Handle X509FromCertificate(CERTCertificate* certificate) {
266 PRTime start_validity; 281 PRTime start_validity;
267 PRTime end_validity; 282 PRTime end_validity;
268 SECStatus status = 283 SECStatus status =
269 CERT_GetCertTimes(certificate, &start_validity, &end_validity); 284 CERT_GetCertTimes(certificate, &start_validity, &end_validity);
270 if (status != SECSuccess) { 285 if (status != SECSuccess) {
271 ThrowPRException("CertificateException", 286 ThrowPRException("CertificateException",
(...skipping 21 matching lines...) Expand all
293 Dart_Handle x509_type = 308 Dart_Handle x509_type =
294 DartUtils::GetDartType(DartUtils::kIOLibURL, "X509Certificate"); 309 DartUtils::GetDartType(DartUtils::kIOLibURL, "X509Certificate");
295 Dart_Handle arguments[] = { subject_name_object, 310 Dart_Handle arguments[] = { subject_name_object,
296 issuer_name_object, 311 issuer_name_object,
297 start_validity_date, 312 start_validity_date,
298 end_validity_date }; 313 end_validity_date };
299 return Dart_New(x509_type, Dart_Null(), 4, arguments); 314 return Dart_New(x509_type, Dart_Null(), 4, arguments);
300 } 315 }
301 316
302 317
318 char* PasswordCallback(PK11SlotInfo* slot, PRBool retry, void* arg) {
319 if (!retry) {
320 return PL_strdup(static_cast<char*>(arg)); // Freed by NSS internals.
321 }
322 return NULL;
323 }
324
325
303 void FUNCTION_NAME(SecureSocket_AddCertificate) 326 void FUNCTION_NAME(SecureSocket_AddCertificate)
304 (Dart_NativeArguments args) { 327 (Dart_NativeArguments args) {
305 Dart_Handle certificate_object = 328 Dart_Handle certificate_object =
306 ThrowIfError(Dart_GetNativeArgument(args, 0)); 329 ThrowIfError(Dart_GetNativeArgument(args, 0));
307 Dart_Handle trust_object = ThrowIfError(Dart_GetNativeArgument(args, 1)); 330 Dart_Handle trust_object = ThrowIfError(Dart_GetNativeArgument(args, 1));
308 331
309 if (!Dart_IsList(certificate_object) || !Dart_IsString(trust_object)) { 332 if (!Dart_IsList(certificate_object) || !Dart_IsString(trust_object)) {
310 Dart_ThrowException(DartUtils::NewDartArgumentError( 333 Dart_ThrowException(DartUtils::NewDartArgumentError(
311 "Bad argument to SecureSocket.addCertificate")); 334 "Bad argument to SecureSocket.addCertificate"));
312 } 335 }
313 336
314 intptr_t length; 337 intptr_t length;
315 ThrowIfError(Dart_ListLength(certificate_object, &length)); 338 ThrowIfError(Dart_ListLength(certificate_object, &length));
316 uint8_t* certificate = reinterpret_cast<uint8_t*>(malloc(length + 1)); 339 uint8_t* certificate = reinterpret_cast<uint8_t*>(malloc(length + 1));
317 if (certificate == NULL) { 340 if (certificate == NULL) {
318 FATAL("Out of memory in SecureSocket.addCertificate"); 341 FATAL("Out of memory in SecureSocket.addCertificate");
319 } 342 }
320 ThrowIfError(Dart_ListGetAsBytes( 343 ThrowIfError(Dart_ListGetAsBytes(
321 certificate_object, 0, certificate, length)); 344 certificate_object, 0, certificate, length));
322 345
323 const char* trust_string; 346 const char* trust_string;
324 ThrowIfError(Dart_StringToCString(trust_object, 347 ThrowIfError(Dart_StringToCString(trust_object,
325 &trust_string)); 348 &trust_string));
326 349
350 PK11SlotInfo* slot = PK11_GetInternalKeySlot();
351 SECStatus status = PK11_Authenticate(slot, PR_TRUE, SSLFilter::GetPassword());
352 PK11_FreeSlot(slot);
353 if (status == SECFailure) {
354 ThrowPRException("CertificateException",
355 "Could not authenticate to certificate database");
356 }
357
327 CERTCertificate* cert = CERT_DecodeCertFromPackage( 358 CERTCertificate* cert = CERT_DecodeCertFromPackage(
328 reinterpret_cast<char*>(certificate), length); 359 reinterpret_cast<char*>(certificate), length);
329 if (cert == NULL) { 360 if (cert == NULL) {
330 ThrowPRException("CertificateException", "Certificate cannot be decoded"); 361 ThrowPRException("CertificateException", "Certificate cannot be decoded");
331 } 362 }
332 CERTCertTrust trust; 363 CERTCertTrust trust;
333 SECStatus status = CERT_DecodeTrustString(&trust, trust_string); 364 status = CERT_DecodeTrustString(&trust, trust_string);
334 if (status != SECSuccess) { 365 if (status != SECSuccess) {
335 ThrowPRException("CertificateException", "Trust string cannot be decoded"); 366 ThrowPRException("CertificateException", "Trust string cannot be decoded");
336 } 367 }
337 368 {
338 status = CERT_ChangeCertTrust(CERT_GetDefaultCertDB(), cert, &trust); 369 MutexLocker locker(SSLFilter::mutex);
370 status = CERT_ChangeCertTrust(CERT_GetDefaultCertDB(), cert, &trust);
371 }
339 if (status != SECSuccess) { 372 if (status != SECSuccess) {
340 ThrowPRException("CertificateException", "Cannot set trust attributes"); 373 ThrowPRException("CertificateException", "Cannot set trust attributes");
341 } 374 }
342 375
343 Dart_SetReturnValue(args, X509FromCertificate(cert)); 376 Dart_SetReturnValue(args, X509FromCertificate(cert));
344 return; 377 return;
345 } 378 }
346 379
347 380
381 /*
382 * Called by the PKCS#12 decoder if a certificate's nickname collides with
383 * the nickname of a different existing certificate in the database.
384 */
385 SECItem* nickname_callback(SECItem *old_nickname,
386 PRBool *cancel,
387 void *arg) {
388 *cancel = PR_TRUE;
389 return NULL;
390 }
391
392
393 void FUNCTION_NAME(SecureSocket_ImportCertificatesWithPrivateKeys)
394 (Dart_NativeArguments args) {
395 Dart_Handle pk12_object = ThrowIfError(Dart_GetNativeArgument(args, 0));
396 if (!Dart_IsList(pk12_object)) {
397 Dart_ThrowException(DartUtils::NewDartArgumentError(
398 "SecureSocket.importPrivateCertificates: certificates is not a List"));
399 }
400
401 Dart_Handle password_object = ThrowIfError(Dart_GetNativeArgument(args, 1));
402 if (!Dart_IsString(password_object)) {
403 Dart_ThrowException(DartUtils::NewDartArgumentError(
404 "SecureSocket.importPrivateCertificates: password is not a String"));
405 }
406
407 intptr_t length;
408 ThrowIfError(Dart_ListLength(pk12_object, &length));
409 uint8_t* pk12 = Dart_ScopeAllocate(length);
410 if (pk12 == NULL) {
411 FATAL("Out of memory in SecureSocket.importPrivateCertificates");
412 }
413 ThrowIfError(Dart_ListGetAsBytes(pk12_object, 0, pk12, length));
414
415 // A big-endian Unicode (UTF16) password.
416 intptr_t password_length;
417 ThrowIfError(Dart_StringLength(password_object, &password_length));
418 password_length++;
419 uint16_t* password = reinterpret_cast<uint16_t*>(
420 Dart_ScopeAllocate(sizeof(uint16_t) * password_length));
421 if (password == NULL) {
422 FATAL("Out of memory in SecureSocket.importPrivateCertificates");
423 }
424 intptr_t returned_length = password_length;
425 ThrowIfError(Dart_StringToUTF16(password_object, password, &returned_length));
426 ASSERT(password_length == returned_length + 1);
427 password[password_length - 1] = 0;
428 for (int i = 0; i < password_length; ++i) {
429 password[i] = Utils::HostToBigEndian16(password[i]);
430 }
431 SECItem p12_password;
432 p12_password.type = siBuffer;
433 p12_password.data = reinterpret_cast<unsigned char*>(password);
434 p12_password.len = sizeof(uint16_t) * password_length;
435
436 Dart_SetReturnValue(args, Dart_Null());
437 // Set the password callback for the certificate database we are importing to.
438 // The password for a slot is gotten from a callback, and it is freed by the
439 // caller of the callback. The argument to the callback comes from the wincx
440 // argument to a PK11 function.
441 PK11SlotInfo* slot = PK11_GetInternalKeySlot();
442 SECStatus status = PK11_Authenticate(slot, PR_TRUE, SSLFilter::GetPassword());
443 if (status == SECFailure) {
444 PK11_FreeSlot(slot);
445 ThrowPRException("CertificateException",
446 "Could not authenticate to certificate database");
447 }
448
449 SEC_PKCS12DecoderContext* context = SEC_PKCS12DecoderStart(
450 &p12_password,
451 slot,
452 SSLFilter::GetPassword(),
453 NULL,
454 NULL,
455 NULL,
456 NULL,
457 NULL);
458 PK11_FreeSlot(slot);
459 if (!context) {
460 FATAL("Unexpected error: SecureSocket.addPrivateCertificates DecoderStart");
461 }
462 bool success;
463 {
464 MutexLocker locker(SSLFilter::mutex);
465 success =
466 SECSuccess == SEC_PKCS12DecoderUpdate(context, pk12, length) &&
467 SECSuccess == SEC_PKCS12DecoderVerify(context) &&
468 SECSuccess == SEC_PKCS12DecoderValidateBags(context,
469 nickname_callback) &&
470 SECSuccess == SEC_PKCS12DecoderImportBags(context);
471 }
472 SEC_PKCS12DecoderFinish(context);
473 if (!success) {
474 ThrowPRException("CertificateException", "Could not import PKCS#12 file");
475 }
476 }
477
478
479 void FUNCTION_NAME(SecureSocket_ChangeTrust)(Dart_NativeArguments args) {
480 Dart_Handle nickname_object = ThrowIfError(Dart_GetNativeArgument(args, 0));
481 if (!Dart_IsString(nickname_object)) {
482 Dart_ThrowException(DartUtils::NewDartArgumentError(
483 "SecureSocket.changeTrust: nickname argument is not a String"));
484 }
485 const char* nickname;
486 ThrowIfError(Dart_StringToCString(nickname_object, &nickname));
487
488 Dart_Handle trust_object = ThrowIfError(Dart_GetNativeArgument(args, 1));
489 if (!Dart_IsString(trust_object)) {
490 Dart_ThrowException(DartUtils::NewDartArgumentError(
491 "SecureSocket.changeTrust: trust argument is not a String"));
492 }
493 const char* trust_string;
494 ThrowIfError(Dart_StringToCString(trust_object, &trust_string));
495
496 PK11SlotInfo* slot = PK11_GetInternalKeySlot();
497 SECStatus status = PK11_Authenticate(slot, PR_TRUE, SSLFilter::GetPassword());
498 if (status == SECFailure) {
499 ThrowPRException("CertificateException",
500 "Could not authenticate to certificate database");
501 }
502 PK11_FreeSlot(slot);
503
504 CERTCertificate* certificate =
505 PK11_FindCertFromNickname(nickname, SSLFilter::GetPassword());
506 if (certificate == NULL) {
507 ThrowCertificateException("Cannot find certificate with nickname %s",
508 nickname);
509 }
510 CERTCertTrust trust;
511 if (SECSuccess != CERT_DecodeTrustString(&trust, trust_string)) {
512 CERT_DestroyCertificate(certificate);
513 ThrowPRException("CertificateException", "Trust string cannot be decoded");
514 }
515 {
516 MutexLocker locker(SSLFilter::mutex);
517 status = CERT_ChangeCertTrust(CERT_GetDefaultCertDB(), certificate, &trust);
518 }
519 if (status != SECSuccess) {
520 CERT_DestroyCertificate(certificate);
521 ThrowCertificateException("Cannot set trust on certificate %s", nickname);
522 }
523 Dart_SetReturnValue(args, X509FromCertificate(certificate));
524 CERT_DestroyCertificate(certificate);
525 }
526
527
528 void FUNCTION_NAME(SecureSocket_GetCertificate)(Dart_NativeArguments args) {
529 Dart_Handle nickname_object = ThrowIfError(Dart_GetNativeArgument(args, 0));
530 if (!Dart_IsString(nickname_object)) {
531 Dart_ThrowException(DartUtils::NewDartArgumentError(
532 "SecureSocket.getCertificate: nickname argument is not a String"));
533 }
534 const char* nickname;
535 ThrowIfError(Dart_StringToCString(nickname_object, &nickname));
536
537 CERTCertificate* certificate = PK11_FindCertFromNickname(
538 nickname, SSLFilter::GetPassword());
539 if (certificate != NULL) {
540 Dart_SetReturnValue(args, X509FromCertificate(certificate));
541 CERT_DestroyCertificate(certificate);
542 }
543 }
544
545
546 void FUNCTION_NAME(SecureSocket_RemoveCertificate)(Dart_NativeArguments args) {
547 Dart_Handle nickname_object =
548 ThrowIfError(Dart_GetNativeArgument(args, 0));
549 if (!Dart_IsString(nickname_object)) {
550 Dart_ThrowException(DartUtils::NewDartArgumentError(
551 "SecureSocket.removeCertificate: nickname is not a String"));
552 }
553 const char* nickname;
554 ThrowIfError(Dart_StringToCString(nickname_object, &nickname));
555
556 CERTCertificate* certificate =
557 PK11_FindCertFromNickname(nickname, SSLFilter::GetPassword());
558 if (certificate == NULL) {
559 ThrowCertificateException("Cannot find certificate with nickname %s",
560 nickname);
561 }
562 SECKEYPrivateKey* key =
563 PK11_FindKeyByAnyCert(certificate, SSLFilter::GetPassword());
564 // Free the copy returned from FindKeyByAnyCert.
565 SECKEY_DestroyPrivateKey(key);
566 SECStatus status;
567 {
568 MutexLocker locker(SSLFilter::mutex);
569 status = (key == NULL) ?
570 SEC_DeletePermCertificate(certificate) :
571 PK11_DeleteTokenCertAndKey(certificate, SSLFilter::GetPassword());
572 }
573 CERT_DestroyCertificate(certificate);
574 if (status != SECSuccess) {
575 ThrowCertificateException("Cannot remove certificate %s", nickname);
576 }
577 }
578
348 579
349 void FUNCTION_NAME(SecureSocket_PeerCertificate) 580 void FUNCTION_NAME(SecureSocket_PeerCertificate)
350 (Dart_NativeArguments args) { 581 (Dart_NativeArguments args) {
351 Dart_SetReturnValue(args, GetFilter(args)->PeerCertificate()); 582 Dart_SetReturnValue(args, GetFilter(args)->PeerCertificate());
352 } 583 }
353 584
354 585
355 void FUNCTION_NAME(SecureSocket_FilterPointer)(Dart_NativeArguments args) { 586 void FUNCTION_NAME(SecureSocket_FilterPointer)(Dart_NativeArguments args) {
356 intptr_t filter_pointer = reinterpret_cast<intptr_t>(GetFilter(args)); 587 intptr_t filter_pointer = reinterpret_cast<intptr_t>(GetFilter(args));
357 Dart_SetReturnValue(args, Dart_NewInteger(filter_pointer)); 588 Dart_SetReturnValue(args, Dart_NewInteger(filter_pointer));
(...skipping 129 matching lines...) Expand 10 before | Expand all | Expand 10 after
487 default: 718 default:
488 UNREACHABLE(); 719 UNREACHABLE();
489 } 720 }
490 } 721 }
491 return true; 722 return true;
492 } 723 }
493 724
494 725
495 void SSLFilter::Init(Dart_Handle dart_this) { 726 void SSLFilter::Init(Dart_Handle dart_this) {
496 if (!library_initialized_) { 727 if (!library_initialized_) {
497 InitializeLibrary(NULL, "", true, false); 728 InitializeLibrary(NULL, "", true, true, false);
498 } 729 }
499 ASSERT(string_start_ == NULL); 730 ASSERT(string_start_ == NULL);
500 string_start_ = Dart_NewPersistentHandle(DartUtils::NewString("start")); 731 string_start_ = Dart_NewPersistentHandle(DartUtils::NewString("start"));
501 ASSERT(string_start_ != NULL); 732 ASSERT(string_start_ != NULL);
502 ASSERT(string_length_ == NULL); 733 ASSERT(string_length_ == NULL);
503 string_length_ = Dart_NewPersistentHandle(DartUtils::NewString("length")); 734 string_length_ = Dart_NewPersistentHandle(DartUtils::NewString("length"));
504 ASSERT(string_length_ != NULL); 735 ASSERT(string_length_ != NULL);
505 ASSERT(bad_certificate_callback_ == NULL); 736 ASSERT(bad_certificate_callback_ == NULL);
506 bad_certificate_callback_ = Dart_NewPersistentHandle(Dart_Null()); 737 bad_certificate_callback_ = Dart_NewPersistentHandle(Dart_Null());
507 ASSERT(bad_certificate_callback_ != NULL); 738 ASSERT(bad_certificate_callback_ != NULL);
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after
560 791
561 792
562 void SSLFilter::RegisterBadCertificateCallback(Dart_Handle callback) { 793 void SSLFilter::RegisterBadCertificateCallback(Dart_Handle callback) {
563 ASSERT(bad_certificate_callback_ != NULL); 794 ASSERT(bad_certificate_callback_ != NULL);
564 Dart_DeletePersistentHandle(bad_certificate_callback_); 795 Dart_DeletePersistentHandle(bad_certificate_callback_);
565 bad_certificate_callback_ = Dart_NewPersistentHandle(callback); 796 bad_certificate_callback_ = Dart_NewPersistentHandle(callback);
566 ASSERT(bad_certificate_callback_ != NULL); 797 ASSERT(bad_certificate_callback_ != NULL);
567 } 798 }
568 799
569 800
570 char* PasswordCallback(PK11SlotInfo* slot, PRBool retry, void* arg) {
571 if (!retry) {
572 return PL_strdup(static_cast<char*>(arg)); // Freed by NSS internals.
573 }
574 return NULL;
575 }
576
577
578 static const char* builtin_roots_module = 801 static const char* builtin_roots_module =
579 #if defined(TARGET_OS_LINUX) || defined(TARGET_OS_ANDROID) 802 #if defined(TARGET_OS_LINUX) || defined(TARGET_OS_ANDROID)
580 "name=\"Root Certs\" library=\"libnssckbi.so\""; 803 "name=\"Root Certs\" library=\"libnssckbi.so\"";
581 #elif defined(TARGET_OS_MACOS) 804 #elif defined(TARGET_OS_MACOS)
582 "name=\"Root Certs\" library=\"libnssckbi.dylib\""; 805 "name=\"Root Certs\" library=\"libnssckbi.dylib\"";
583 #elif defined(TARGET_OS_WINDOWS) 806 #elif defined(TARGET_OS_WINDOWS)
584 "name=\"Root Certs\" library=\"nssckbi.dll\""; 807 "name=\"Root Certs\" library=\"nssckbi.dll\"";
585 #else 808 #else
586 #error Automatic target os detection failed. 809 #error Automatic target os detection failed.
587 #endif 810 #endif
588 811
589 812
590 813
591 void SSLFilter::InitializeLibrary(const char* certificate_database, 814 void SSLFilter::InitializeLibrary(const char* certificate_database,
592 const char* password, 815 const char* password,
593 bool use_builtin_root_certificates, 816 bool use_builtin_root_certificates,
817 bool read_only,
594 bool report_duplicate_initialization) { 818 bool report_duplicate_initialization) {
595 MutexLocker locker(mutex_); 819 MutexLocker locker(mutex);
596 SECStatus status; 820 SECStatus status;
597 if (!library_initialized_) { 821 if (!library_initialized_) {
598 PR_Init(PR_USER_THREAD, PR_PRIORITY_NORMAL, 0); 822 PR_Init(PR_USER_THREAD, PR_PRIORITY_NORMAL, 0);
599 // TODO(whesse): Verify there are no UTF-8 issues here. 823 // TODO(whesse): Verify there are no UTF-8 issues here.
600 if (certificate_database == NULL || certificate_database[0] == '\0') { 824 if (certificate_database == NULL || certificate_database[0] == '\0') {
601 status = NSS_NoDB_Init(NULL); 825 status = NSS_NoDB_Init(NULL);
602 if (status != SECSuccess) { 826 if (status != SECSuccess) {
603 mutex_->Unlock(); // MutexLocker destructor not called when throwing. 827 mutex->Unlock(); // MutexLocker destructor not called when throwing.
604 ThrowPRException("TlsException", 828 ThrowPRException("TlsException",
605 "Failed NSS_NoDB_Init call."); 829 "Failed NSS_NoDB_Init call.");
606 } 830 }
607 if (use_builtin_root_certificates) { 831 if (use_builtin_root_certificates) {
608 SECMODModule* module = SECMOD_LoadUserModule( 832 SECMODModule* module = SECMOD_LoadUserModule(
609 const_cast<char*>(builtin_roots_module), NULL, PR_FALSE); 833 const_cast<char*>(builtin_roots_module), NULL, PR_FALSE);
610 if (!module) { 834 if (!module) {
611 mutex_->Unlock(); // MutexLocker destructor not called when throwing. 835 mutex->Unlock(); // MutexLocker destructor not called when throwing.
612 ThrowPRException("TlsException", 836 ThrowPRException("TlsException",
613 "Failed to load builtin root certificates."); 837 "Failed to load builtin root certificates.");
614 } 838 }
615 } 839 }
616 } else { 840 } else {
617 PRUint32 init_flags = NSS_INIT_READONLY; 841 PRUint32 init_flags = read_only ? NSS_INIT_READONLY : 0;
618 if (!use_builtin_root_certificates) { 842 if (!use_builtin_root_certificates) {
619 init_flags |= NSS_INIT_NOMODDB; 843 init_flags |= NSS_INIT_NOMODDB;
620 } 844 }
621 status = NSS_Initialize(certificate_database, 845 status = NSS_Initialize(certificate_database,
622 "", 846 "",
623 "", 847 "",
624 SECMOD_DB, 848 SECMOD_DB,
625 init_flags); 849 init_flags);
626 if (status != SECSuccess) { 850 if (status != SECSuccess) {
627 mutex_->Unlock(); // MutexLocker destructor not called when throwing. 851 mutex->Unlock(); // MutexLocker destructor not called when throwing.
628 ThrowPRException("TlsException", 852 ThrowPRException("TlsException",
629 "Failed NSS_Init call."); 853 "Failed NSS_Init call.");
630 } 854 }
631 password_ = strdup(password); // This one copy persists until Dart exits. 855 password_ = strdup(password); // This one copy persists until Dart exits.
632 PK11_SetPasswordFunc(PasswordCallback); 856 PK11_SetPasswordFunc(PasswordCallback);
633 } 857 }
634 library_initialized_ = true; 858 library_initialized_ = true;
635 859
860 // Allow encoding and decoding of private keys in PKCS#12 files.
861 SEC_PKCS12EnableCipher(PKCS12_RC2_CBC_40, 1);
862 SEC_PKCS12EnableCipher(PKCS12_DES_EDE3_168, 1);
863 SEC_PKCS12SetPreferredCipher(PKCS12_DES_EDE3_168, 1);
864
636 status = NSS_SetDomesticPolicy(); 865 status = NSS_SetDomesticPolicy();
637 if (status != SECSuccess) { 866 if (status != SECSuccess) {
638 mutex_->Unlock(); // MutexLocker destructor not called when throwing. 867 mutex->Unlock(); // MutexLocker destructor not called when throwing.
639 ThrowPRException("TlsException", 868 ThrowPRException("TlsException",
640 "Failed NSS_SetDomesticPolicy call."); 869 "Failed NSS_SetDomesticPolicy call.");
641 } 870 }
871
642 // Enable TLS, as well as SSL3 and SSL2. 872 // Enable TLS, as well as SSL3 and SSL2.
643 status = SSL_OptionSetDefault(SSL_ENABLE_TLS, PR_TRUE); 873 status = SSL_OptionSetDefault(SSL_ENABLE_TLS, PR_TRUE);
644 if (status != SECSuccess) { 874 if (status != SECSuccess) {
645 mutex_->Unlock(); // MutexLocker destructor not called when throwing. 875 mutex->Unlock(); // MutexLocker destructor not called when throwing.
646 ThrowPRException("TlsException", 876 ThrowPRException("TlsException",
647 "Failed SSL_OptionSetDefault enable TLS call."); 877 "Failed SSL_OptionSetDefault enable TLS call.");
648 } 878 }
649 status = SSL_ConfigServerSessionIDCache(0, 0, 0, NULL); 879 status = SSL_ConfigServerSessionIDCache(0, 0, 0, NULL);
650 if (status != SECSuccess) { 880 if (status != SECSuccess) {
651 mutex_->Unlock(); // MutexLocker destructor not called when throwing. 881 mutex->Unlock(); // MutexLocker destructor not called when throwing.
652 ThrowPRException("TlsException", 882 ThrowPRException("TlsException",
653 "Failed SSL_ConfigServerSessionIDCache call."); 883 "Failed SSL_ConfigServerSessionIDCache call.");
654 } 884 }
655 885
656 } else if (report_duplicate_initialization) { 886 } else if (report_duplicate_initialization) {
657 mutex_->Unlock(); // MutexLocker destructor not called when throwing. 887 mutex->Unlock(); // MutexLocker destructor not called when throwing.
658 // Like ThrowPRException, without adding an OSError. 888 // Like ThrowPRException, without adding an OSError.
659 Dart_ThrowException(DartUtils::NewDartIOException("TlsException", 889 Dart_ThrowException(DartUtils::NewDartIOException("TlsException",
660 "Called SecureSocket.initialize more than once", 890 "Called SecureSocket.initialize more than once",
661 Dart_Null())); 891 Dart_Null()));
662 } 892 }
663 } 893 }
664 894
665 895
666 SECStatus BadCertificateCallback(void* filter, PRFileDesc* fd) { 896 SECStatus BadCertificateCallback(void* filter, PRFileDesc* fd) {
667 SSLFilter* ssl_filter = static_cast<SSLFilter*>(filter); 897 SSLFilter* ssl_filter = static_cast<SSLFilter*>(filter);
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after
722 // Look up certificate using the distinguished name (DN) certificate_name. 952 // Look up certificate using the distinguished name (DN) certificate_name.
723 CERTCertDBHandle* certificate_database = CERT_GetDefaultCertDB(); 953 CERTCertDBHandle* certificate_database = CERT_GetDefaultCertDB();
724 if (certificate_database == NULL) { 954 if (certificate_database == NULL) {
725 ThrowPRException("CertificateException", 955 ThrowPRException("CertificateException",
726 "Certificate database cannot be loaded"); 956 "Certificate database cannot be loaded");
727 } 957 }
728 certificate = CERT_FindCertByNameString(certificate_database, 958 certificate = CERT_FindCertByNameString(certificate_database,
729 const_cast<char*>(certificate_name)); 959 const_cast<char*>(certificate_name));
730 if (certificate == NULL) { 960 if (certificate == NULL) {
731 ThrowCertificateException( 961 ThrowCertificateException(
732 "Cannot find server certificate by distinguished name: %s", 962 "Cannot find server certificate with distinguished name %s",
733 certificate_name); 963 certificate_name);
734 } 964 }
735 } else { 965 } else {
736 // Look up certificate using the nickname certificate_name. 966 // Look up certificate using the nickname certificate_name.
737 certificate = PK11_FindCertFromNickname( 967 certificate = PK11_FindCertFromNickname(
738 const_cast<char*>(certificate_name), 968 const_cast<char*>(certificate_name), GetPassword());
739 static_cast<void*>(const_cast<char*>(password_)));
740 if (certificate == NULL) { 969 if (certificate == NULL) {
741 ThrowCertificateException( 970 ThrowCertificateException(
742 "Cannot find server certificate by nickname: %s", 971 "Cannot find server certificate with nickname %s",
743 certificate_name); 972 certificate_name);
744 } 973 }
745 } 974 }
746 SECKEYPrivateKey* key = PK11_FindKeyByAnyCert( 975 SECKEYPrivateKey* key = PK11_FindKeyByAnyCert(certificate, GetPassword());
747 certificate,
748 static_cast<void*>(const_cast<char*>(password_)));
749 if (key == NULL) { 976 if (key == NULL) {
750 CERT_DestroyCertificate(certificate); 977 CERT_DestroyCertificate(certificate);
751 if (PR_GetError() == -8177) { 978 if (PR_GetError() == -8177) {
752 ThrowPRException("CertificateException", 979 ThrowPRException("CertificateException",
753 "Certificate database password incorrect"); 980 "Certificate database password incorrect");
754 } else { 981 } else {
755 ThrowCertificateException( 982 ThrowCertificateException(
756 "Cannot find private key for certificate %s", 983 "Cannot find private key for certificate %s",
757 certificate_name); 984 certificate_name);
758 } 985 }
(...skipping 263 matching lines...) Expand 10 before | Expand all | Expand 10 after
1022 if (service_port != ILLEGAL_PORT) { 1249 if (service_port != ILLEGAL_PORT) {
1023 // Return a send port for the service port. 1250 // Return a send port for the service port.
1024 Dart_Handle send_port = Dart_NewSendPort(service_port); 1251 Dart_Handle send_port = Dart_NewSendPort(service_port);
1025 Dart_SetReturnValue(args, send_port); 1252 Dart_SetReturnValue(args, send_port);
1026 } 1253 }
1027 } 1254 }
1028 1255
1029 1256
1030 } // namespace bin 1257 } // namespace bin
1031 } // namespace dart 1258 } // namespace dart
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698