Chromium Code Reviews| OLD | NEW |
|---|---|
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 |
| OLD | NEW |