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 168 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 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 Loading... | |
| 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 PK11_SetPasswordFunc(PasswordCallback); | |
|
wtc
2013/08/08 20:01:13
We should ideally call PK11_SetPasswordFunc just o
Bill Hesse
2013/08/09 13:24:05
No, it isn't. Removed.
| |
| 351 PK11SlotInfo* slot = PK11_GetInternalKeySlot(); | |
| 352 SECStatus status = PK11_Authenticate(slot, PR_TRUE, SSLFilter::GetPassword()); | |
| 353 if (status == SECFailure) { | |
| 354 ThrowPRException("CertificateException", | |
| 355 "Could not authenticate to certificate database"); | |
| 356 } | |
| 357 PK11_FreeSlot(slot); | |
|
wtc
2013/08/08 20:01:13
Free |slot| before lie 353.
Bill Hesse
2013/08/09 13:24:05
Done.
| |
| 358 | |
| 327 CERTCertificate* cert = CERT_DecodeCertFromPackage( | 359 CERTCertificate* cert = CERT_DecodeCertFromPackage( |
| 328 reinterpret_cast<char*>(certificate), length); | 360 reinterpret_cast<char*>(certificate), length); |
| 329 if (cert == NULL) { | 361 if (cert == NULL) { |
| 330 ThrowPRException("CertificateException", "Certificate cannot be decoded"); | 362 ThrowPRException("CertificateException", "Certificate cannot be decoded"); |
| 331 } | 363 } |
| 332 CERTCertTrust trust; | 364 CERTCertTrust trust; |
| 333 SECStatus status = CERT_DecodeTrustString(&trust, trust_string); | 365 status = CERT_DecodeTrustString(&trust, trust_string); |
| 334 if (status != SECSuccess) { | 366 if (status != SECSuccess) { |
| 335 ThrowPRException("CertificateException", "Trust string cannot be decoded"); | 367 ThrowPRException("CertificateException", "Trust string cannot be decoded"); |
| 336 } | 368 } |
| 337 | 369 |
| 338 status = CERT_ChangeCertTrust(CERT_GetDefaultCertDB(), cert, &trust); | 370 status = CERT_ChangeCertTrust(CERT_GetDefaultCertDB(), cert, &trust); |
| 339 if (status != SECSuccess) { | 371 if (status != SECSuccess) { |
| 340 ThrowPRException("CertificateException", "Cannot set trust attributes"); | 372 ThrowPRException("CertificateException", "Cannot set trust attributes"); |
| 341 } | 373 } |
| 342 | 374 |
| 343 Dart_SetReturnValue(args, X509FromCertificate(cert)); | 375 Dart_SetReturnValue(args, X509FromCertificate(cert)); |
| 344 return; | 376 return; |
| 345 } | 377 } |
| 346 | 378 |
| 347 | 379 |
| 380 /* | |
| 381 * Called by the PKCS#12 decoder if a certificate's nickname collides with | |
| 382 * the nickname of a different existing certificate in the database. | |
| 383 */ | |
| 384 SECItem* nickname_callback(SECItem *old_nickname, | |
| 385 PRBool *cancel, | |
| 386 void *arg) { | |
| 387 *cancel = PR_TRUE; | |
| 388 return NULL; | |
| 389 } | |
| 390 | |
| 391 | |
| 392 void FUNCTION_NAME(SecureSocket_ImportCertificatesWithPrivateKeys) | |
| 393 (Dart_NativeArguments args) { | |
| 394 Dart_Handle pk12_object = ThrowIfError(Dart_GetNativeArgument(args, 0)); | |
| 395 if (!Dart_IsList(pk12_object)) { | |
| 396 Dart_ThrowException(DartUtils::NewDartArgumentError( | |
| 397 "SecureSocket.importPrivateCertificates: certificates is not a List")); | |
| 398 } | |
| 399 | |
| 400 Dart_Handle password_object = ThrowIfError(Dart_GetNativeArgument(args, 1)); | |
| 401 if (!Dart_IsString(password_object)) { | |
| 402 Dart_ThrowException(DartUtils::NewDartArgumentError( | |
| 403 "SecureSocket.importPrivateCertificates: password is not a String")); | |
| 404 } | |
| 405 | |
| 406 intptr_t length; | |
| 407 ThrowIfError(Dart_ListLength(pk12_object, &length)); | |
| 408 uint8_t* pk12 = Dart_ScopeAllocate(length + 1); // Why +1 ? | |
|
wtc
2013/08/08 20:01:13
Can you try removing "+ 1"?
Bill Hesse
2013/08/09 13:24:05
Done.
| |
| 409 if (pk12 == NULL) { | |
| 410 FATAL("Out of memory in SecureSocket.importPrivateCertificates"); | |
| 411 } | |
| 412 ThrowIfError(Dart_ListGetAsBytes(pk12_object, 0, pk12, length)); | |
| 413 | |
| 414 // A big-endian Unicode (UTF16) password. | |
| 415 intptr_t password_length; | |
| 416 ThrowIfError(Dart_StringLength(password_object, &password_length)); | |
| 417 password_length++; | |
| 418 uint16_t* password = reinterpret_cast<uint16_t*>( | |
| 419 Dart_ScopeAllocate(2 * password_length)); | |
|
wtc
2013/08/08 20:01:13
Nit: replace 2 with sizeof(uint16_t). You may igno
Bill Hesse
2013/08/09 13:24:05
Done.
| |
| 420 if (password == NULL) { | |
| 421 FATAL("Out of memory in SecureSocket.importPrivateCertificates"); | |
| 422 } | |
| 423 intptr_t returned_length = password_length; | |
| 424 ThrowIfError(Dart_StringToUTF16(password_object, password, &returned_length)); | |
| 425 ASSERT(password_length == returned_length + 1); | |
| 426 password[password_length - 1] = 0; | |
| 427 for (int i = 0; i < password_length; ++i) { | |
| 428 password[i] = Utils::HostToBigEndian16(password[i]); | |
| 429 } | |
| 430 SECItem p12_password; | |
| 431 p12_password.type = siBuffer; | |
| 432 p12_password.data = reinterpret_cast<unsigned char*>(password); | |
| 433 p12_password.len = 2 * password_length; | |
|
wtc
2013/08/08 20:01:13
Nit: same here: replace 2 with sizeof(uint16_t).
Bill Hesse
2013/08/09 13:24:05
Done.
| |
| 434 | |
| 435 Dart_SetReturnValue(args, Dart_Null()); | |
| 436 // Set the password callback for the certificate database we are importing to. | |
| 437 // The password for a slot is gotten from a callback, and it is freed by the | |
| 438 // caller of the callback. The argument to the callback comes from the wincx | |
| 439 // argument to a PK11 function. | |
| 440 PK11_SetPasswordFunc(PasswordCallback); | |
| 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 | |
| 463 bool success = | |
| 464 SECSuccess == SEC_PKCS12DecoderUpdate(context, pk12, length) && | |
| 465 SECSuccess == SEC_PKCS12DecoderVerify(context) && | |
| 466 SECSuccess == SEC_PKCS12DecoderValidateBags(context, nickname_callback) && | |
| 467 SECSuccess == SEC_PKCS12DecoderImportBags(context); | |
| 468 SEC_PKCS12DecoderFinish(context); | |
| 469 if (!success) { | |
| 470 ThrowPRException("CertificateException", "Could not import PKCS#12 file"); | |
| 471 } | |
| 472 } | |
| 473 | |
| 474 | |
| 475 void FUNCTION_NAME(SecureSocket_ChangeTrust)(Dart_NativeArguments args) { | |
| 476 Dart_Handle nickname_object = ThrowIfError(Dart_GetNativeArgument(args, 0)); | |
| 477 if (!Dart_IsString(nickname_object)) { | |
| 478 Dart_ThrowException(DartUtils::NewDartArgumentError( | |
| 479 "SecureSocket.changeTrust: nickname argument is not a String")); | |
| 480 } | |
| 481 const char* nickname; | |
| 482 ThrowIfError(Dart_StringToCString(nickname_object, &nickname)); | |
| 483 | |
| 484 Dart_Handle trust_object = ThrowIfError(Dart_GetNativeArgument(args, 1)); | |
| 485 if (!Dart_IsString(trust_object)) { | |
| 486 Dart_ThrowException(DartUtils::NewDartArgumentError( | |
| 487 "SecureSocket.changeTrust: trust argument is not a String")); | |
| 488 } | |
| 489 const char* trust_string; | |
| 490 ThrowIfError(Dart_StringToCString(trust_object, &trust_string)); | |
| 491 | |
| 492 PK11SlotInfo* slot = PK11_GetInternalKeySlot(); | |
| 493 SECStatus status = PK11_Authenticate(slot, PR_TRUE, SSLFilter::GetPassword()); | |
| 494 if (status == SECFailure) { | |
| 495 ThrowPRException("CertificateException", | |
| 496 "Could not authenticate to certificate database"); | |
| 497 } | |
| 498 PK11_FreeSlot(slot); | |
| 499 | |
| 500 CERTCertificate* certificate = | |
| 501 PK11_FindCertFromNickname(nickname, SSLFilter::GetPassword()); | |
| 502 if (certificate == NULL) { | |
| 503 ThrowCertificateException("Cannot find certificate with nickname %s", | |
| 504 nickname); | |
| 505 } | |
| 506 CERTCertTrust trust; | |
| 507 if (SECSuccess != CERT_DecodeTrustString(&trust, trust_string)) { | |
| 508 CERT_DestroyCertificate(certificate); | |
| 509 ThrowPRException("CertificateException", "Trust string cannot be decoded"); | |
| 510 } | |
| 511 if (SECSuccess != | |
| 512 CERT_ChangeCertTrust(CERT_GetDefaultCertDB(), certificate, &trust)) { | |
| 513 CERT_DestroyCertificate(certificate); | |
| 514 ThrowCertificateException("Cannot set trust on certificate %s", nickname); | |
| 515 } | |
| 516 Dart_SetReturnValue(args, X509FromCertificate(certificate)); | |
| 517 CERT_DestroyCertificate(certificate); | |
| 518 } | |
| 519 | |
| 520 | |
| 521 void FUNCTION_NAME(SecureSocket_GetCertificate)(Dart_NativeArguments args) { | |
| 522 Dart_Handle nickname_object = ThrowIfError(Dart_GetNativeArgument(args, 0)); | |
| 523 if (!Dart_IsString(nickname_object)) { | |
| 524 Dart_ThrowException(DartUtils::NewDartArgumentError( | |
| 525 "SecureSocket.getCertificate: nickname argument is not a String")); | |
| 526 } | |
| 527 const char* nickname; | |
| 528 ThrowIfError(Dart_StringToCString(nickname_object, &nickname)); | |
| 529 | |
| 530 CERTCertificate* certificate = PK11_FindCertFromNickname( | |
| 531 nickname, SSLFilter::GetPassword()); | |
| 532 if (certificate != NULL) { | |
| 533 Dart_SetReturnValue(args, X509FromCertificate(certificate)); | |
| 534 CERT_DestroyCertificate(certificate); | |
| 535 } | |
| 536 } | |
| 537 | |
| 538 | |
| 539 void FUNCTION_NAME(SecureSocket_RemoveCertificate)(Dart_NativeArguments args) { | |
| 540 Dart_Handle nickname_object = | |
| 541 ThrowIfError(Dart_GetNativeArgument(args, 0)); | |
| 542 if (!Dart_IsString(nickname_object)) { | |
| 543 Dart_ThrowException(DartUtils::NewDartArgumentError( | |
| 544 "SecureSocket.removeCertificate: nickname is not a String")); | |
| 545 } | |
| 546 const char* nickname; | |
| 547 ThrowIfError(Dart_StringToCString(nickname_object, &nickname)); | |
| 548 | |
| 549 CERTCertificate* certificate = | |
| 550 PK11_FindCertFromNickname(nickname, SSLFilter::GetPassword()); | |
| 551 if (certificate == NULL) { | |
| 552 ThrowCertificateException("Cannot find certificate with nickname %s", | |
| 553 nickname); | |
| 554 } | |
| 555 SECKEYPrivateKey* key = | |
| 556 PK11_FindKeyByAnyCert(certificate, SSLFilter::GetPassword()); | |
| 557 // Free the copy returned from FindKeyByAnyCert. | |
| 558 SECKEY_DestroyPrivateKey(key); | |
| 559 SECStatus status = (key == NULL) ? | |
| 560 SEC_DeletePermCertificate(certificate) : | |
| 561 PK11_DeleteTokenCertAndKey(certificate, SSLFilter::GetPassword()); | |
| 562 CERT_DestroyCertificate(certificate); | |
| 563 if (status != SECSuccess) { | |
| 564 ThrowCertificateException("Cannot remove certificate %s", nickname); | |
| 565 } | |
| 566 } | |
| 567 | |
| 348 | 568 |
| 349 void FUNCTION_NAME(SecureSocket_PeerCertificate) | 569 void FUNCTION_NAME(SecureSocket_PeerCertificate) |
| 350 (Dart_NativeArguments args) { | 570 (Dart_NativeArguments args) { |
| 351 Dart_SetReturnValue(args, GetFilter(args)->PeerCertificate()); | 571 Dart_SetReturnValue(args, GetFilter(args)->PeerCertificate()); |
| 352 } | 572 } |
| 353 | 573 |
| 354 | 574 |
| 355 void FUNCTION_NAME(SecureSocket_FilterPointer)(Dart_NativeArguments args) { | 575 void FUNCTION_NAME(SecureSocket_FilterPointer)(Dart_NativeArguments args) { |
| 356 intptr_t filter_pointer = reinterpret_cast<intptr_t>(GetFilter(args)); | 576 intptr_t filter_pointer = reinterpret_cast<intptr_t>(GetFilter(args)); |
| 357 Dart_SetReturnValue(args, Dart_NewInteger(filter_pointer)); | 577 Dart_SetReturnValue(args, Dart_NewInteger(filter_pointer)); |
| (...skipping 129 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 487 default: | 707 default: |
| 488 UNREACHABLE(); | 708 UNREACHABLE(); |
| 489 } | 709 } |
| 490 } | 710 } |
| 491 return true; | 711 return true; |
| 492 } | 712 } |
| 493 | 713 |
| 494 | 714 |
| 495 void SSLFilter::Init(Dart_Handle dart_this) { | 715 void SSLFilter::Init(Dart_Handle dart_this) { |
| 496 if (!library_initialized_) { | 716 if (!library_initialized_) { |
| 497 InitializeLibrary(NULL, "", true, false); | 717 InitializeLibrary(NULL, "", true, true, false); |
| 498 } | 718 } |
| 499 ASSERT(string_start_ == NULL); | 719 ASSERT(string_start_ == NULL); |
| 500 string_start_ = Dart_NewPersistentHandle(DartUtils::NewString("start")); | 720 string_start_ = Dart_NewPersistentHandle(DartUtils::NewString("start")); |
| 501 ASSERT(string_start_ != NULL); | 721 ASSERT(string_start_ != NULL); |
| 502 ASSERT(string_length_ == NULL); | 722 ASSERT(string_length_ == NULL); |
| 503 string_length_ = Dart_NewPersistentHandle(DartUtils::NewString("length")); | 723 string_length_ = Dart_NewPersistentHandle(DartUtils::NewString("length")); |
| 504 ASSERT(string_length_ != NULL); | 724 ASSERT(string_length_ != NULL); |
| 505 ASSERT(bad_certificate_callback_ == NULL); | 725 ASSERT(bad_certificate_callback_ == NULL); |
| 506 bad_certificate_callback_ = Dart_NewPersistentHandle(Dart_Null()); | 726 bad_certificate_callback_ = Dart_NewPersistentHandle(Dart_Null()); |
| 507 ASSERT(bad_certificate_callback_ != NULL); | 727 ASSERT(bad_certificate_callback_ != NULL); |
| (...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 560 | 780 |
| 561 | 781 |
| 562 void SSLFilter::RegisterBadCertificateCallback(Dart_Handle callback) { | 782 void SSLFilter::RegisterBadCertificateCallback(Dart_Handle callback) { |
| 563 ASSERT(bad_certificate_callback_ != NULL); | 783 ASSERT(bad_certificate_callback_ != NULL); |
| 564 Dart_DeletePersistentHandle(bad_certificate_callback_); | 784 Dart_DeletePersistentHandle(bad_certificate_callback_); |
| 565 bad_certificate_callback_ = Dart_NewPersistentHandle(callback); | 785 bad_certificate_callback_ = Dart_NewPersistentHandle(callback); |
| 566 ASSERT(bad_certificate_callback_ != NULL); | 786 ASSERT(bad_certificate_callback_ != NULL); |
| 567 } | 787 } |
| 568 | 788 |
| 569 | 789 |
| 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 = | 790 static const char* builtin_roots_module = |
| 579 #if defined(TARGET_OS_LINUX) || defined(TARGET_OS_ANDROID) | 791 #if defined(TARGET_OS_LINUX) || defined(TARGET_OS_ANDROID) |
| 580 "name=\"Root Certs\" library=\"libnssckbi.so\""; | 792 "name=\"Root Certs\" library=\"libnssckbi.so\""; |
| 581 #elif defined(TARGET_OS_MACOS) | 793 #elif defined(TARGET_OS_MACOS) |
| 582 "name=\"Root Certs\" library=\"libnssckbi.dylib\""; | 794 "name=\"Root Certs\" library=\"libnssckbi.dylib\""; |
| 583 #elif defined(TARGET_OS_WINDOWS) | 795 #elif defined(TARGET_OS_WINDOWS) |
| 584 "name=\"Root Certs\" library=\"nssckbi.dll\""; | 796 "name=\"Root Certs\" library=\"nssckbi.dll\""; |
| 585 #else | 797 #else |
| 586 #error Automatic target os detection failed. | 798 #error Automatic target os detection failed. |
| 587 #endif | 799 #endif |
| 588 | 800 |
| 589 | 801 |
| 590 | 802 |
| 591 void SSLFilter::InitializeLibrary(const char* certificate_database, | 803 void SSLFilter::InitializeLibrary(const char* certificate_database, |
| 592 const char* password, | 804 const char* password, |
| 593 bool use_builtin_root_certificates, | 805 bool use_builtin_root_certificates, |
| 806 bool read_only, | |
| 594 bool report_duplicate_initialization) { | 807 bool report_duplicate_initialization) { |
| 595 MutexLocker locker(mutex_); | 808 MutexLocker locker(mutex_); |
| 596 SECStatus status; | 809 SECStatus status; |
| 597 if (!library_initialized_) { | 810 if (!library_initialized_) { |
| 598 PR_Init(PR_USER_THREAD, PR_PRIORITY_NORMAL, 0); | 811 PR_Init(PR_USER_THREAD, PR_PRIORITY_NORMAL, 0); |
| 599 // TODO(whesse): Verify there are no UTF-8 issues here. | 812 // TODO(whesse): Verify there are no UTF-8 issues here. |
| 600 if (certificate_database == NULL || certificate_database[0] == '\0') { | 813 if (certificate_database == NULL || certificate_database[0] == '\0') { |
| 601 status = NSS_NoDB_Init(NULL); | 814 status = NSS_NoDB_Init(NULL); |
| 602 if (status != SECSuccess) { | 815 if (status != SECSuccess) { |
| 603 mutex_->Unlock(); // MutexLocker destructor not called when throwing. | 816 mutex_->Unlock(); // MutexLocker destructor not called when throwing. |
| 604 ThrowPRException("TlsException", | 817 ThrowPRException("TlsException", |
| 605 "Failed NSS_NoDB_Init call."); | 818 "Failed NSS_NoDB_Init call."); |
| 606 } | 819 } |
| 607 if (use_builtin_root_certificates) { | 820 if (use_builtin_root_certificates) { |
| 608 SECMODModule* module = SECMOD_LoadUserModule( | 821 SECMODModule* module = SECMOD_LoadUserModule( |
| 609 const_cast<char*>(builtin_roots_module), NULL, PR_FALSE); | 822 const_cast<char*>(builtin_roots_module), NULL, PR_FALSE); |
| 610 if (!module) { | 823 if (!module) { |
| 611 mutex_->Unlock(); // MutexLocker destructor not called when throwing. | 824 mutex_->Unlock(); // MutexLocker destructor not called when throwing. |
| 612 ThrowPRException("TlsException", | 825 ThrowPRException("TlsException", |
| 613 "Failed to load builtin root certificates."); | 826 "Failed to load builtin root certificates."); |
| 614 } | 827 } |
| 615 } | 828 } |
| 616 } else { | 829 } else { |
| 617 PRUint32 init_flags = NSS_INIT_READONLY; | 830 PRUint32 init_flags = read_only ? NSS_INIT_READONLY : 0; |
| 618 if (!use_builtin_root_certificates) { | 831 if (!use_builtin_root_certificates) { |
| 619 init_flags |= NSS_INIT_NOMODDB; | 832 init_flags |= NSS_INIT_NOMODDB; |
| 620 } | 833 } |
| 621 status = NSS_Initialize(certificate_database, | 834 status = NSS_Initialize(certificate_database, |
| 622 "", | 835 "", |
| 623 "", | 836 "", |
| 624 SECMOD_DB, | 837 SECMOD_DB, |
| 625 init_flags); | 838 init_flags); |
| 626 if (status != SECSuccess) { | 839 if (status != SECSuccess) { |
| 627 mutex_->Unlock(); // MutexLocker destructor not called when throwing. | 840 mutex_->Unlock(); // MutexLocker destructor not called when throwing. |
| 628 ThrowPRException("TlsException", | 841 ThrowPRException("TlsException", |
| 629 "Failed NSS_Init call."); | 842 "Failed NSS_Init call."); |
| 630 } | 843 } |
| 631 password_ = strdup(password); // This one copy persists until Dart exits. | 844 password_ = strdup(password); // This one copy persists until Dart exits. |
| 632 PK11_SetPasswordFunc(PasswordCallback); | 845 PK11_SetPasswordFunc(PasswordCallback); |
| 633 } | 846 } |
| 634 library_initialized_ = true; | 847 library_initialized_ = true; |
| 635 | 848 |
| 849 // Allow encoding and decoding of private keys in PKCS#12 files. | |
| 850 SEC_PKCS12EnableCipher(PKCS12_RC2_CBC_40, 1); | |
|
wtc
2013/08/08 20:01:13
I assume you found PKCS12_RC2_CBC_40 is required.
Bill Hesse
2013/08/09 13:24:05
Yes. The certificates are encrypted with RC2, the
| |
| 851 SEC_PKCS12EnableCipher(PKCS12_DES_EDE3_168, 1); | |
| 852 SEC_PKCS12SetPreferredCipher(PKCS12_DES_EDE3_168, 1); | |
| 853 | |
| 636 status = NSS_SetDomesticPolicy(); | 854 status = NSS_SetDomesticPolicy(); |
| 637 if (status != SECSuccess) { | 855 if (status != SECSuccess) { |
| 638 mutex_->Unlock(); // MutexLocker destructor not called when throwing. | 856 mutex_->Unlock(); // MutexLocker destructor not called when throwing. |
| 639 ThrowPRException("TlsException", | 857 ThrowPRException("TlsException", |
| 640 "Failed NSS_SetDomesticPolicy call."); | 858 "Failed NSS_SetDomesticPolicy call."); |
| 641 } | 859 } |
| 860 | |
| 642 // Enable TLS, as well as SSL3 and SSL2. | 861 // Enable TLS, as well as SSL3 and SSL2. |
| 643 status = SSL_OptionSetDefault(SSL_ENABLE_TLS, PR_TRUE); | 862 status = SSL_OptionSetDefault(SSL_ENABLE_TLS, PR_TRUE); |
| 644 if (status != SECSuccess) { | 863 if (status != SECSuccess) { |
| 645 mutex_->Unlock(); // MutexLocker destructor not called when throwing. | 864 mutex_->Unlock(); // MutexLocker destructor not called when throwing. |
| 646 ThrowPRException("TlsException", | 865 ThrowPRException("TlsException", |
| 647 "Failed SSL_OptionSetDefault enable TLS call."); | 866 "Failed SSL_OptionSetDefault enable TLS call."); |
| 648 } | 867 } |
| 649 status = SSL_ConfigServerSessionIDCache(0, 0, 0, NULL); | 868 status = SSL_ConfigServerSessionIDCache(0, 0, 0, NULL); |
| 650 if (status != SECSuccess) { | 869 if (status != SECSuccess) { |
| 651 mutex_->Unlock(); // MutexLocker destructor not called when throwing. | 870 mutex_->Unlock(); // MutexLocker destructor not called when throwing. |
| (...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 722 // Look up certificate using the distinguished name (DN) certificate_name. | 941 // Look up certificate using the distinguished name (DN) certificate_name. |
| 723 CERTCertDBHandle* certificate_database = CERT_GetDefaultCertDB(); | 942 CERTCertDBHandle* certificate_database = CERT_GetDefaultCertDB(); |
| 724 if (certificate_database == NULL) { | 943 if (certificate_database == NULL) { |
| 725 ThrowPRException("CertificateException", | 944 ThrowPRException("CertificateException", |
| 726 "Certificate database cannot be loaded"); | 945 "Certificate database cannot be loaded"); |
| 727 } | 946 } |
| 728 certificate = CERT_FindCertByNameString(certificate_database, | 947 certificate = CERT_FindCertByNameString(certificate_database, |
| 729 const_cast<char*>(certificate_name)); | 948 const_cast<char*>(certificate_name)); |
| 730 if (certificate == NULL) { | 949 if (certificate == NULL) { |
| 731 ThrowCertificateException( | 950 ThrowCertificateException( |
| 732 "Cannot find server certificate by distinguished name: %s", | 951 "Cannot find server certificate with distinguished name %s", |
| 733 certificate_name); | 952 certificate_name); |
| 734 } | 953 } |
| 735 } else { | 954 } else { |
| 736 // Look up certificate using the nickname certificate_name. | 955 // Look up certificate using the nickname certificate_name. |
| 737 certificate = PK11_FindCertFromNickname( | 956 certificate = PK11_FindCertFromNickname( |
| 738 const_cast<char*>(certificate_name), | 957 const_cast<char*>(certificate_name), GetPassword()); |
| 739 static_cast<void*>(const_cast<char*>(password_))); | |
| 740 if (certificate == NULL) { | 958 if (certificate == NULL) { |
| 741 ThrowCertificateException( | 959 ThrowCertificateException( |
| 742 "Cannot find server certificate by nickname: %s", | 960 "Cannot find server certificate with nickname %s", |
| 743 certificate_name); | 961 certificate_name); |
| 744 } | 962 } |
| 745 } | 963 } |
| 746 SECKEYPrivateKey* key = PK11_FindKeyByAnyCert( | 964 SECKEYPrivateKey* key = PK11_FindKeyByAnyCert(certificate, GetPassword()); |
| 747 certificate, | |
| 748 static_cast<void*>(const_cast<char*>(password_))); | |
| 749 if (key == NULL) { | 965 if (key == NULL) { |
| 750 CERT_DestroyCertificate(certificate); | 966 CERT_DestroyCertificate(certificate); |
| 751 if (PR_GetError() == -8177) { | 967 if (PR_GetError() == -8177) { |
| 752 ThrowPRException("CertificateException", | 968 ThrowPRException("CertificateException", |
| 753 "Certificate database password incorrect"); | 969 "Certificate database password incorrect"); |
| 754 } else { | 970 } else { |
| 755 ThrowCertificateException( | 971 ThrowCertificateException( |
| 756 "Cannot find private key for certificate %s", | 972 "Cannot find private key for certificate %s", |
| 757 certificate_name); | 973 certificate_name); |
| 758 } | 974 } |
| (...skipping 263 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1022 if (service_port != ILLEGAL_PORT) { | 1238 if (service_port != ILLEGAL_PORT) { |
| 1023 // Return a send port for the service port. | 1239 // Return a send port for the service port. |
| 1024 Dart_Handle send_port = Dart_NewSendPort(service_port); | 1240 Dart_Handle send_port = Dart_NewSendPort(service_port); |
| 1025 Dart_SetReturnValue(args, send_port); | 1241 Dart_SetReturnValue(args, send_port); |
| 1026 } | 1242 } |
| 1027 } | 1243 } |
| 1028 | 1244 |
| 1029 | 1245 |
| 1030 } // namespace bin | 1246 } // namespace bin |
| 1031 } // namespace dart | 1247 } // namespace dart |
| OLD | NEW |