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

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

Issue 21716004: dart:io | Add SecureSocket.importPrivateCertificates, that reads a PKCS#12 file. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Add documentation about the in-memory certificate cache and the certificate database. Created 7 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a 2 // for details. All rights reserved. Use of this source code is governed by a
3 // BSD-style license that can be found in the LICENSE file. 3 // BSD-style license that can be found in the LICENSE file.
4 4
5 #include "bin/secure_socket.h" 5 #include "bin/secure_socket.h"
6 6
7 #include <errno.h> 7 #include <errno.h>
8 #include <fcntl.h> 8 #include <fcntl.h>
9 #include <sys/stat.h> 9 #include <sys/stat.h>
10 #include <stdio.h> 10 #include <stdio.h>
11 #include <string.h> 11 #include <string.h>
12 12
13 #include <certdb.h>
13 #include <key.h> 14 #include <key.h>
14 #include <keyt.h> 15 #include <keyt.h>
15 #include <nss.h> 16 #include <nss.h>
17 #include <p12.h>
18 #include <p12plcy.h>
16 #include <pk11pub.h> 19 #include <pk11pub.h>
17 #include <prerror.h> 20 #include <prerror.h>
18 #include <prinit.h> 21 #include <prinit.h>
19 #include <prnetdb.h> 22 #include <prnetdb.h>
20 #include <secmod.h> 23 #include <secmod.h>
21 #include <ssl.h> 24 #include <ssl.h>
22 #include <sslproto.h> 25 #include <sslproto.h>
23 26
24 #include "bin/builtin.h" 27 #include "bin/builtin.h"
25 #include "bin/dartutils.h" 28 #include "bin/dartutils.h"
26 #include "bin/net/nss_memio.h" 29 #include "bin/net/nss_memio.h"
27 #include "bin/socket.h" 30 #include "bin/socket.h"
28 #include "bin/thread.h" 31 #include "bin/thread.h"
29 #include "bin/utils.h" 32 #include "bin/utils.h"
30 #include "platform/utils.h" 33 #include "platform/utils.h"
31 34
32 #include "include/dart_api.h" 35 #include "include/dart_api.h"
33 36
34 37
35 namespace dart { 38 namespace dart {
36 namespace bin { 39 namespace bin {
37 40
38 bool SSLFilter::library_initialized_ = false; 41 bool SSLFilter::library_initialized_ = false;
39 // To protect library initialization. 42 // To protect library initialization.
40 dart::Mutex* SSLFilter::mutex_ = new dart::Mutex(); 43 dart::Mutex* SSLFilter::mutex_ = new dart::Mutex();
41 // The password is needed when creating secure server sockets. It can 44 // The password is needed when creating secure server sockets. It can
42 // be null if only secure client sockets are used. 45 // be null if only secure client sockets are used.
43 const char* SSLFilter::password_ = NULL; 46 char* SSLFilter::password_ = NULL;
44 47
45 // Forward declaration. 48 // Forward declaration.
46 static void ProcessFilter(Dart_Port dest_port_id, 49 static void ProcessFilter(Dart_Port dest_port_id,
47 Dart_Port reply_port_id, 50 Dart_Port reply_port_id,
48 Dart_CObject* message); 51 Dart_CObject* message);
49 52
50 NativeService SSLFilter::filter_service_("FilterService", ProcessFilter, 16); 53 NativeService SSLFilter::filter_service_("FilterService", ProcessFilter, 16);
51 54
52 static const int kSSLFilterNativeFieldIndex = 0; 55 static const int kSSLFilterNativeFieldIndex = 0;
53 56
(...skipping 168 matching lines...) Expand 10 before | Expand all | Expand 10 after
222 (Dart_NativeArguments args) { 225 (Dart_NativeArguments args) {
223 Dart_Handle certificate_database_object = 226 Dart_Handle certificate_database_object =
224 ThrowIfError(Dart_GetNativeArgument(args, 0)); 227 ThrowIfError(Dart_GetNativeArgument(args, 0));
225 // Check that the type is string, and get the UTF-8 C string value from it. 228 // Check that the type is string, and get the UTF-8 C string value from it.
226 const char* certificate_database = NULL; 229 const char* certificate_database = NULL;
227 if (Dart_IsString(certificate_database_object)) { 230 if (Dart_IsString(certificate_database_object)) {
228 ThrowIfError(Dart_StringToCString(certificate_database_object, 231 ThrowIfError(Dart_StringToCString(certificate_database_object,
229 &certificate_database)); 232 &certificate_database));
230 } else if (!Dart_IsNull(certificate_database_object)) { 233 } else if (!Dart_IsNull(certificate_database_object)) {
231 Dart_ThrowException(DartUtils::NewDartArgumentError( 234 Dart_ThrowException(DartUtils::NewDartArgumentError(
232 "Non-String certificate directory argument to SetCertificateDatabase")); 235 "SecureSocket.initialize: database argument is not a String or null"));
233 } 236 }
234 // Leave certificate_database as NULL if no value was provided. 237 // Leave certificate_database as NULL if no value was provided.
235 238
236 Dart_Handle password_object = ThrowIfError(Dart_GetNativeArgument(args, 1)); 239 Dart_Handle password_object = ThrowIfError(Dart_GetNativeArgument(args, 1));
237 // Check that the type is string or null, 240 // Check that the type is string or null,
238 // and get the UTF-8 C string value from it. 241 // and get the UTF-8 C string value from it.
239 const char* password = NULL; 242 const char* password = NULL;
240 if (Dart_IsString(password_object)) { 243 if (Dart_IsString(password_object)) {
241 ThrowIfError(Dart_StringToCString(password_object, &password)); 244 ThrowIfError(Dart_StringToCString(password_object, &password));
242 } else if (Dart_IsNull(password_object)) { 245 } else if (Dart_IsNull(password_object)) {
243 // Pass the empty string as the password. 246 // Pass the empty string as the password.
244 password = ""; 247 password = "";
245 } else { 248 } else {
246 Dart_ThrowException(DartUtils::NewDartArgumentError( 249 Dart_ThrowException(DartUtils::NewDartArgumentError(
247 "Password argument to SetCertificateDatabase is not a String or null")); 250 "SecureSocket.initialize: password argument is not a String or null"));
248 } 251 }
249 252
250 Dart_Handle builtin_roots_object = 253 Dart_Handle builtin_roots_object =
251 ThrowIfError(Dart_GetNativeArgument(args, 2)); 254 ThrowIfError(Dart_GetNativeArgument(args, 2));
252 // Check that the type is boolean, and get the boolean value from it. 255 // Check that the type is boolean, and get the boolean value from it.
253 bool builtin_roots = true; 256 bool builtin_roots = true;
254 if (Dart_IsBoolean(builtin_roots_object)) { 257 if (Dart_IsBoolean(builtin_roots_object)) {
255 ThrowIfError(Dart_BooleanValue(builtin_roots_object, &builtin_roots)); 258 ThrowIfError(Dart_BooleanValue(builtin_roots_object, &builtin_roots));
256 } else { 259 } else {
257 Dart_ThrowException(DartUtils::NewDartArgumentError( 260 Dart_ThrowException(DartUtils::NewDartArgumentError(
258 "UseBuiltinRoots argument to SetCertificateDatabase is not a bool")); 261 "SecureSocket.initialize: useBuiltinRoots argument is not a bool"));
259 } 262 }
260 263
261 SSLFilter::InitializeLibrary(certificate_database, password, builtin_roots); 264 Dart_Handle read_only_object =
265 ThrowIfError(Dart_GetNativeArgument(args, 3));
266 // Check that the type is boolean, and get the boolean value from it.
267 bool read_only = true;
268 if (Dart_IsBoolean(read_only_object)) {
269 ThrowIfError(Dart_BooleanValue(read_only_object, &read_only));
270 } else {
271 Dart_ThrowException(DartUtils::NewDartArgumentError(
272 "SecureSocket.initialize: readOnly argument is not a bool"));
273 }
274
275 SSLFilter::InitializeLibrary(
276 certificate_database, password, builtin_roots, read_only);
262 } 277 }
263 278
264 279
265 static Dart_Handle X509FromCertificate(CERTCertificate* certificate) { 280 static Dart_Handle X509FromCertificate(CERTCertificate* certificate) {
266 PRTime start_validity; 281 PRTime start_validity;
267 PRTime end_validity; 282 PRTime end_validity;
268 SECStatus status = 283 SECStatus status =
269 CERT_GetCertTimes(certificate, &start_validity, &end_validity); 284 CERT_GetCertTimes(certificate, &start_validity, &end_validity);
270 if (status != SECSuccess) { 285 if (status != SECSuccess) {
271 ThrowPRException("CertificateException", 286 ThrowPRException("CertificateException",
(...skipping 21 matching lines...) Expand all
293 Dart_Handle x509_type = 308 Dart_Handle x509_type =
294 DartUtils::GetDartType(DartUtils::kIOLibURL, "X509Certificate"); 309 DartUtils::GetDartType(DartUtils::kIOLibURL, "X509Certificate");
295 Dart_Handle arguments[] = { subject_name_object, 310 Dart_Handle arguments[] = { subject_name_object,
296 issuer_name_object, 311 issuer_name_object,
297 start_validity_date, 312 start_validity_date,
298 end_validity_date }; 313 end_validity_date };
299 return Dart_New(x509_type, Dart_Null(), 4, arguments); 314 return Dart_New(x509_type, Dart_Null(), 4, arguments);
300 } 315 }
301 316
302 317
318 char* PasswordCallback(PK11SlotInfo* slot, PRBool retry, void* arg) {
319 if (!retry) {
320 return PL_strdup(static_cast<char*>(arg)); // Freed by NSS internals.
321 }
322 return NULL;
323 }
324
325
303 void FUNCTION_NAME(SecureSocket_AddCertificate) 326 void FUNCTION_NAME(SecureSocket_AddCertificate)
304 (Dart_NativeArguments args) { 327 (Dart_NativeArguments args) {
305 Dart_Handle certificate_object = 328 Dart_Handle certificate_object =
306 ThrowIfError(Dart_GetNativeArgument(args, 0)); 329 ThrowIfError(Dart_GetNativeArgument(args, 0));
307 Dart_Handle trust_object = ThrowIfError(Dart_GetNativeArgument(args, 1)); 330 Dart_Handle trust_object = ThrowIfError(Dart_GetNativeArgument(args, 1));
308 331
309 if (!Dart_IsList(certificate_object) || !Dart_IsString(trust_object)) { 332 if (!Dart_IsList(certificate_object) || !Dart_IsString(trust_object)) {
310 Dart_ThrowException(DartUtils::NewDartArgumentError( 333 Dart_ThrowException(DartUtils::NewDartArgumentError(
311 "Bad argument to SecureSocket.addCertificate")); 334 "Bad argument to SecureSocket.addCertificate"));
312 } 335 }
313 336
314 intptr_t length; 337 intptr_t length;
315 ThrowIfError(Dart_ListLength(certificate_object, &length)); 338 ThrowIfError(Dart_ListLength(certificate_object, &length));
316 uint8_t* certificate = reinterpret_cast<uint8_t*>(malloc(length + 1)); 339 uint8_t* certificate = reinterpret_cast<uint8_t*>(malloc(length + 1));
317 if (certificate == NULL) { 340 if (certificate == NULL) {
318 FATAL("Out of memory in SecureSocket.addCertificate"); 341 FATAL("Out of memory in SecureSocket.addCertificate");
319 } 342 }
320 ThrowIfError(Dart_ListGetAsBytes( 343 ThrowIfError(Dart_ListGetAsBytes(
321 certificate_object, 0, certificate, length)); 344 certificate_object, 0, certificate, length));
322 345
323 const char* trust_string; 346 const char* trust_string;
324 ThrowIfError(Dart_StringToCString(trust_object, 347 ThrowIfError(Dart_StringToCString(trust_object,
325 &trust_string)); 348 &trust_string));
326 349
350 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
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
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
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
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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698