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