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> |
(...skipping 264 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
275 } | 275 } |
276 | 276 |
277 | 277 |
278 void FUNCTION_NAME(SecureSocket_FilterPointer)(Dart_NativeArguments args) { | 278 void FUNCTION_NAME(SecureSocket_FilterPointer)(Dart_NativeArguments args) { |
279 intptr_t filter_pointer = reinterpret_cast<intptr_t>(GetFilter(args)); | 279 intptr_t filter_pointer = reinterpret_cast<intptr_t>(GetFilter(args)); |
280 Dart_SetReturnValue(args, Dart_NewInteger(filter_pointer)); | 280 Dart_SetReturnValue(args, Dart_NewInteger(filter_pointer)); |
281 } | 281 } |
282 | 282 |
283 | 283 |
284 static Dart_Handle WrappedX509Certificate(X509* certificate) { | 284 static Dart_Handle WrappedX509Certificate(X509* certificate) { |
285 if (certificate == NULL) return Dart_Null(); | 285 if (certificate == NULL) { |
| 286 return Dart_Null(); |
| 287 } |
286 Dart_Handle x509_type = | 288 Dart_Handle x509_type = |
287 DartUtils::GetDartType(DartUtils::kIOLibURL, "X509Certificate"); | 289 DartUtils::GetDartType(DartUtils::kIOLibURL, "X509Certificate"); |
288 if (Dart_IsError(x509_type)) { | 290 if (Dart_IsError(x509_type)) { |
289 return x509_type; | 291 return x509_type; |
290 } | 292 } |
291 Dart_Handle arguments[] = { NULL }; | 293 Dart_Handle arguments[] = { NULL }; |
292 Dart_Handle result = | 294 Dart_Handle result = |
293 Dart_New(x509_type, DartUtils::NewString("_"), 0, arguments); | 295 Dart_New(x509_type, DartUtils::NewString("_"), 0, arguments); |
294 if (Dart_IsError(result)) { | 296 if (Dart_IsError(result)) { |
295 return result; | 297 return result; |
296 } | 298 } |
297 ASSERT(Dart_IsInstance(result)); | 299 ASSERT(Dart_IsInstance(result)); |
298 Dart_Handle status = Dart_SetNativeInstanceField( | 300 Dart_Handle status = Dart_SetNativeInstanceField( |
299 result, | 301 result, |
300 kX509NativeFieldIndex, | 302 kX509NativeFieldIndex, |
301 reinterpret_cast<intptr_t>(certificate)); | 303 reinterpret_cast<intptr_t>(certificate)); |
302 if (Dart_IsError(status)) { | 304 if (Dart_IsError(status)) { |
303 return status; | 305 return status; |
304 } | 306 } |
305 return result; | 307 return result; |
306 } | 308 } |
307 | 309 |
308 | 310 |
309 int CertificateCallback(int preverify_ok, X509_STORE_CTX* store_ctx) { | 311 int CertificateCallback(int preverify_ok, X509_STORE_CTX* store_ctx) { |
310 if (preverify_ok == 1) return 1; | 312 if (preverify_ok == 1) { |
| 313 return 1; |
| 314 } |
311 Dart_Isolate isolate = Dart_CurrentIsolate(); | 315 Dart_Isolate isolate = Dart_CurrentIsolate(); |
312 if (isolate == NULL) { | 316 if (isolate == NULL) { |
313 FATAL("CertificateCallback called with no current isolate\n"); | 317 FATAL("CertificateCallback called with no current isolate\n"); |
314 } | 318 } |
315 X509* certificate = X509_STORE_CTX_get_current_cert(store_ctx); | 319 X509* certificate = X509_STORE_CTX_get_current_cert(store_ctx); |
316 int ssl_index = SSL_get_ex_data_X509_STORE_CTX_idx(); | 320 int ssl_index = SSL_get_ex_data_X509_STORE_CTX_idx(); |
317 SSL* ssl = static_cast<SSL*>( | 321 SSL* ssl = static_cast<SSL*>( |
318 X509_STORE_CTX_get_ex_data(store_ctx, ssl_index)); | 322 X509_STORE_CTX_get_ex_data(store_ctx, ssl_index)); |
319 SSLFilter* filter = static_cast<SSLFilter*>( | 323 SSLFilter* filter = static_cast<SSLFilter*>( |
320 SSL_get_ex_data(ssl, SSLFilter::filter_ssl_index)); | 324 SSL_get_ex_data(ssl, SSLFilter::filter_ssl_index)); |
321 Dart_Handle callback = filter->bad_certificate_callback(); | 325 Dart_Handle callback = filter->bad_certificate_callback(); |
322 if (Dart_IsNull(callback)) return 0; | 326 if (Dart_IsNull(callback)) { |
| 327 return 0; |
| 328 } |
323 Dart_Handle args[1]; | 329 Dart_Handle args[1]; |
324 args[0] = WrappedX509Certificate(certificate); | 330 args[0] = WrappedX509Certificate(certificate); |
325 if (Dart_IsError(args[0])) { | 331 if (Dart_IsError(args[0])) { |
326 filter->callback_error = args[0]; | 332 filter->callback_error = args[0]; |
327 return 0; | 333 return 0; |
328 } | 334 } |
329 Dart_Handle result = Dart_InvokeClosure(callback, 1, args); | 335 Dart_Handle result = Dart_InvokeClosure(callback, 1, args); |
330 if (!Dart_IsError(result) && !Dart_IsBoolean(result)) { | 336 if (!Dart_IsError(result) && !Dart_IsBoolean(result)) { |
331 result = Dart_NewUnhandledExceptionError(DartUtils::NewDartIOException( | 337 result = Dart_NewUnhandledExceptionError(DartUtils::NewDartIOException( |
332 "HandshakeException", | 338 "HandshakeException", |
(...skipping 20 matching lines...) Expand all Loading... |
353 | 359 |
354 | 360 |
355 int PasswordCallback(char* buf, int size, int rwflag, void* userdata) { | 361 int PasswordCallback(char* buf, int size, int rwflag, void* userdata) { |
356 char* password = static_cast<char*>(userdata); | 362 char* password = static_cast<char*>(userdata); |
357 ASSERT(size == PEM_BUFSIZE); | 363 ASSERT(size == PEM_BUFSIZE); |
358 strncpy(buf, password, size); | 364 strncpy(buf, password, size); |
359 return strlen(password); | 365 return strlen(password); |
360 } | 366 } |
361 | 367 |
362 | 368 |
363 void CheckStatus(int status, | 369 void CheckStatus(int status, const char* type, const char* message) { |
364 const char* type, | |
365 const char* message) { | |
366 // TODO(24183): Take appropriate action on failed calls, | 370 // TODO(24183): Take appropriate action on failed calls, |
367 // throw exception that includes all messages from the error stack. | 371 // throw exception that includes all messages from the error stack. |
368 if (status == 1) return; | 372 if (status == 1) { |
| 373 return; |
| 374 } |
369 if (SSL_LOG_STATUS) { | 375 if (SSL_LOG_STATUS) { |
370 int error = ERR_get_error(); | 376 int error = ERR_get_error(); |
371 Log::PrintErr("Failed: %s status %d", message, status); | 377 Log::PrintErr("Failed: %s status %d", message, status); |
372 char error_string[SSL_ERROR_MESSAGE_BUFFER_SIZE]; | 378 char error_string[SSL_ERROR_MESSAGE_BUFFER_SIZE]; |
373 ERR_error_string_n(error, error_string, SSL_ERROR_MESSAGE_BUFFER_SIZE); | 379 ERR_error_string_n(error, error_string, SSL_ERROR_MESSAGE_BUFFER_SIZE); |
374 Log::PrintErr("ERROR: %d %s\n", error, error_string); | 380 Log::PrintErr("ERROR: %d %s\n", error, error_string); |
375 } | 381 } |
376 ThrowIOException(status, type, message); | 382 ThrowIOException(status, type, message); |
377 } | 383 } |
378 | 384 |
(...skipping 170 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
549 ERR_clear_error(); | 555 ERR_clear_error(); |
550 BIO_reset(bio); | 556 BIO_reset(bio); |
551 | 557 |
552 // Try to decode as PKCS12 | 558 // Try to decode as PKCS12 |
553 key = GetPrivateKeyPKCS12(bio, password); | 559 key = GetPrivateKeyPKCS12(bio, password); |
554 } | 560 } |
555 return key; | 561 return key; |
556 } | 562 } |
557 | 563 |
558 | 564 |
| 565 static const char* GetPasswordArgument(Dart_NativeArguments args, |
| 566 intptr_t index) { |
| 567 Dart_Handle password_object = |
| 568 ThrowIfError(Dart_GetNativeArgument(args, index)); |
| 569 const char* password = NULL; |
| 570 if (Dart_IsString(password_object)) { |
| 571 ThrowIfError(Dart_StringToCString(password_object, &password)); |
| 572 if (strlen(password) > PEM_BUFSIZE - 1) { |
| 573 Dart_ThrowException(DartUtils::NewDartArgumentError( |
| 574 "Password length is greater than 1023 (PEM_BUFSIZE)")); |
| 575 } |
| 576 } else if (Dart_IsNull(password_object)) { |
| 577 password = ""; |
| 578 } else { |
| 579 Dart_ThrowException(DartUtils::NewDartArgumentError( |
| 580 "Password is not a String or null")); |
| 581 } |
| 582 return password; |
| 583 } |
| 584 |
| 585 |
559 void FUNCTION_NAME(SecurityContext_UsePrivateKeyBytes)( | 586 void FUNCTION_NAME(SecurityContext_UsePrivateKeyBytes)( |
560 Dart_NativeArguments args) { | 587 Dart_NativeArguments args) { |
561 SSL_CTX* context = GetSecurityContext(args); | 588 SSL_CTX* context = GetSecurityContext(args); |
562 | 589 const char* password = GetPasswordArgument(args, 2); |
563 Dart_Handle password_object = ThrowIfError(Dart_GetNativeArgument(args, 2)); | |
564 const char* password = NULL; | |
565 if (Dart_IsString(password_object)) { | |
566 ThrowIfError(Dart_StringToCString(password_object, &password)); | |
567 if (strlen(password) > PEM_BUFSIZE - 1) { | |
568 Dart_ThrowException(DartUtils::NewDartArgumentError( | |
569 "SecurityContext.usePrivateKey password length is greater than" | |
570 " 1023 (PEM_BUFSIZE)")); | |
571 } | |
572 } else if (Dart_IsNull(password_object)) { | |
573 password = ""; | |
574 } else { | |
575 Dart_ThrowException(DartUtils::NewDartArgumentError( | |
576 "SecurityContext.usePrivateKey password is not a String or null")); | |
577 } | |
578 | 590 |
579 int status; | 591 int status; |
580 { | 592 { |
581 ScopedMemBIO bio(ThrowIfError(Dart_GetNativeArgument(args, 1))); | 593 ScopedMemBIO bio(ThrowIfError(Dart_GetNativeArgument(args, 1))); |
582 EVP_PKEY *key = GetPrivateKey(bio.bio(), password); | 594 EVP_PKEY *key = GetPrivateKey(bio.bio(), password); |
583 status = SSL_CTX_use_PrivateKey(context, key); | 595 status = SSL_CTX_use_PrivateKey(context, key); |
584 } | 596 } |
585 | 597 |
586 // TODO(24184): Handle different expected errors here - file missing, | 598 // TODO(24184): Handle different expected errors here - file missing, |
587 // incorrect password, file not a PEM, and throw exceptions. | 599 // incorrect password, file not a PEM, and throw exceptions. |
588 // CheckStatus should also throw an exception in uncaught cases. | 600 // CheckStatus should also throw an exception in uncaught cases. |
589 CheckStatus(status, "TlsException", "Failure in usePrivateKeyBytes"); | 601 CheckStatus(status, "TlsException", "Failure in usePrivateKeyBytes"); |
590 } | 602 } |
591 | 603 |
592 | 604 |
593 static int SetTrustedCertificatesBytesPKCS12(SSL_CTX* context, BIO* bio) { | 605 static int SetTrustedCertificatesBytesPKCS12(SSL_CTX* context, |
| 606 BIO* bio, |
| 607 const char* password) { |
594 ScopedPKCS12 p12(d2i_PKCS12_bio(bio, NULL)); | 608 ScopedPKCS12 p12(d2i_PKCS12_bio(bio, NULL)); |
595 if (p12.get() == NULL) { | 609 if (p12.get() == NULL) { |
596 return NULL; | 610 return NULL; |
597 } | 611 } |
598 | 612 |
599 EVP_PKEY* key = NULL; | 613 EVP_PKEY* key = NULL; |
600 X509 *cert = NULL; | 614 X509 *cert = NULL; |
601 STACK_OF(X509) *ca_certs = NULL; | 615 STACK_OF(X509) *ca_certs = NULL; |
602 // There should be no private keys in this file, so we hardcode the password | 616 int status = PKCS12_parse(p12.get(), password, &key, &cert, &ca_certs); |
603 // to "". | |
604 // TODO(zra): Allow passing a password anyway. | |
605 int status = PKCS12_parse(p12.get(), "", &key, &cert, &ca_certs); | |
606 if (status == 0) { | 617 if (status == 0) { |
607 return status; | 618 return status; |
608 } | 619 } |
609 | 620 |
610 ScopedX509Stack cert_stack(ca_certs); | 621 ScopedX509Stack cert_stack(ca_certs); |
611 | |
612 // There should be no private key. | |
613 if (key != NULL) { | |
614 X509_free(cert); | |
615 return 0; | |
616 } | |
617 | |
618 X509_STORE* store = SSL_CTX_get_cert_store(context); | 622 X509_STORE* store = SSL_CTX_get_cert_store(context); |
619 status = X509_STORE_add_cert(store, cert); | 623 status = X509_STORE_add_cert(store, cert); |
620 if (status == 0) { | 624 if (status == 0) { |
621 X509_free(cert); | 625 X509_free(cert); |
622 return status; | 626 return status; |
623 } | 627 } |
624 | 628 |
625 X509* ca; | 629 X509* ca; |
626 while ((ca = sk_X509_shift(cert_stack.get())) != NULL) { | 630 while ((ca = sk_X509_shift(cert_stack.get())) != NULL) { |
627 status = X509_STORE_add_cert(store, ca); | 631 status = X509_STORE_add_cert(store, ca); |
(...skipping 27 matching lines...) Expand all Loading... |
655 (ERR_GET_REASON(err) != PEM_R_NO_START_LINE)) { | 659 (ERR_GET_REASON(err) != PEM_R_NO_START_LINE)) { |
656 // If bio contains data that is trying to be PEM but is malformed, then | 660 // If bio contains data that is trying to be PEM but is malformed, then |
657 // this case will be triggered. | 661 // this case will be triggered. |
658 status = 0; | 662 status = 0; |
659 } | 663 } |
660 | 664 |
661 return status; | 665 return status; |
662 } | 666 } |
663 | 667 |
664 | 668 |
665 static int SetTrustedCertificatesBytes(SSL_CTX* context, BIO* bio) { | 669 static int SetTrustedCertificatesBytes(SSL_CTX* context, |
| 670 BIO* bio, |
| 671 const char* password) { |
666 int status = SetTrustedCertificatesBytesPEM(context, bio); | 672 int status = SetTrustedCertificatesBytesPEM(context, bio); |
667 if (TryPKCS12(status != 0)) { | 673 if (TryPKCS12(status != 0)) { |
668 ERR_clear_error(); | 674 ERR_clear_error(); |
669 BIO_reset(bio); | 675 BIO_reset(bio); |
670 status = SetTrustedCertificatesBytesPKCS12(context, bio); | 676 status = SetTrustedCertificatesBytesPKCS12(context, bio, password); |
671 } else if (status != 0) { | 677 } else if (status != 0) { |
672 // The PEM file was successfully parsed. | 678 // The PEM file was successfully parsed. |
673 ERR_clear_error(); | 679 ERR_clear_error(); |
674 } | 680 } |
675 return status; | 681 return status; |
676 } | 682 } |
677 | 683 |
678 | 684 |
679 void FUNCTION_NAME(SecurityContext_SetTrustedCertificatesBytes)( | 685 void FUNCTION_NAME(SecurityContext_SetTrustedCertificatesBytes)( |
680 Dart_NativeArguments args) { | 686 Dart_NativeArguments args) { |
681 SSL_CTX* context = GetSecurityContext(args); | 687 SSL_CTX* context = GetSecurityContext(args); |
| 688 const char* password = GetPasswordArgument(args, 2); |
682 int status; | 689 int status; |
683 { | 690 { |
684 ScopedMemBIO bio(ThrowIfError(Dart_GetNativeArgument(args, 1))); | 691 ScopedMemBIO bio(ThrowIfError(Dart_GetNativeArgument(args, 1))); |
685 status = SetTrustedCertificatesBytes(context, bio.bio()); | 692 status = SetTrustedCertificatesBytes(context, bio.bio(), password); |
686 } | 693 } |
687 CheckStatus(status, | 694 CheckStatus(status, |
688 "TlsException", | 695 "TlsException", |
689 "Failure in setTrustedCertificatesBytes"); | 696 "Failure in setTrustedCertificatesBytes"); |
690 } | 697 } |
691 | 698 |
692 | 699 |
693 void FUNCTION_NAME(SecurityContext_TrustBuiltinRoots)( | 700 void FUNCTION_NAME(SecurityContext_TrustBuiltinRoots)( |
694 Dart_NativeArguments args) { | 701 Dart_NativeArguments args) { |
695 SSL_CTX* context = GetSecurityContext(args); | 702 SSL_CTX* context = GetSecurityContext(args); |
696 X509_STORE* store = SSL_CTX_get_cert_store(context); | 703 X509_STORE* store = SSL_CTX_get_cert_store(context); |
697 BIO* roots_bio = | 704 BIO* roots_bio = |
698 BIO_new_mem_buf(const_cast<unsigned char*>(root_certificates_pem), | 705 BIO_new_mem_buf(const_cast<unsigned char*>(root_certificates_pem), |
699 root_certificates_pem_length); | 706 root_certificates_pem_length); |
700 X509* root_cert; | 707 X509* root_cert; |
701 // PEM_read_bio_X509 reads PEM-encoded certificates from a bio (in our case, | 708 // PEM_read_bio_X509 reads PEM-encoded certificates from a bio (in our case, |
702 // backed by a memory buffer), and returns X509 objects, one by one. | 709 // backed by a memory buffer), and returns X509 objects, one by one. |
703 // When the end of the bio is reached, it returns null. | 710 // When the end of the bio is reached, it returns null. |
704 while ((root_cert = PEM_read_bio_X509(roots_bio, NULL, NULL, NULL))) { | 711 while ((root_cert = PEM_read_bio_X509(roots_bio, NULL, NULL, NULL))) { |
705 X509_STORE_add_cert(store, root_cert); | 712 X509_STORE_add_cert(store, root_cert); |
706 } | 713 } |
707 BIO_free(roots_bio); | 714 BIO_free(roots_bio); |
708 } | 715 } |
709 | 716 |
710 | 717 |
711 static int UseChainBytesPKCS12(SSL_CTX* context, BIO* bio) { | 718 static int UseChainBytesPKCS12(SSL_CTX* context, |
| 719 BIO* bio, |
| 720 const char* password) { |
712 ScopedPKCS12 p12(d2i_PKCS12_bio(bio, NULL)); | 721 ScopedPKCS12 p12(d2i_PKCS12_bio(bio, NULL)); |
713 if (p12.get() == NULL) { | 722 if (p12.get() == NULL) { |
714 return NULL; | 723 return NULL; |
715 } | 724 } |
716 | 725 |
717 EVP_PKEY* key = NULL; | 726 EVP_PKEY* key = NULL; |
718 X509 *cert = NULL; | 727 X509 *cert = NULL; |
719 STACK_OF(X509) *ca_certs = NULL; | 728 STACK_OF(X509) *ca_certs = NULL; |
720 // There should be no private keys in this file, so we hardcode the password | 729 int status = PKCS12_parse(p12.get(), password, &key, &cert, &ca_certs); |
721 // to "". | |
722 // TODO(zra): Allow passing a password anyway. | |
723 int status = PKCS12_parse(p12.get(), "", &key, &cert, &ca_certs); | |
724 if (status == 0) { | 730 if (status == 0) { |
725 return status; | 731 return status; |
726 } | 732 } |
727 | 733 |
728 ScopedX509 x509(cert); | 734 ScopedX509 x509(cert); |
729 ScopedX509Stack certs(ca_certs); | 735 ScopedX509Stack certs(ca_certs); |
730 | |
731 // There should be no private key. | |
732 if (key != NULL) { | |
733 return 0; | |
734 } | |
735 | |
736 status = SSL_CTX_use_certificate(context, x509.get()); | 736 status = SSL_CTX_use_certificate(context, x509.get()); |
737 if (ERR_peek_error() != 0) { | 737 if (ERR_peek_error() != 0) { |
738 // Key/certificate mismatch doesn't imply status is 0. | 738 // Key/certificate mismatch doesn't imply status is 0. |
739 status = 0; | 739 status = 0; |
740 } | 740 } |
741 if (status == 0) { | 741 if (status == 0) { |
742 return status; | 742 return status; |
743 } | 743 } |
744 | 744 |
745 SSL_CTX_clear_chain_certs(context); | 745 SSL_CTX_clear_chain_certs(context); |
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
794 (ERR_GET_REASON(err) != PEM_R_NO_START_LINE)) { | 794 (ERR_GET_REASON(err) != PEM_R_NO_START_LINE)) { |
795 // If bio contains data that is trying to be PEM but is malformed, then | 795 // If bio contains data that is trying to be PEM but is malformed, then |
796 // this case will be triggered. | 796 // this case will be triggered. |
797 status = 0; | 797 status = 0; |
798 } | 798 } |
799 | 799 |
800 return status; | 800 return status; |
801 } | 801 } |
802 | 802 |
803 | 803 |
804 static int UseChainBytes(SSL_CTX* context, BIO* bio) { | 804 static int UseChainBytes(SSL_CTX* context, BIO* bio, const char* password) { |
805 int status = UseChainBytesPEM(context, bio); | 805 int status = UseChainBytesPEM(context, bio); |
806 if (TryPKCS12(status != 0)) { | 806 if (TryPKCS12(status != 0)) { |
807 ERR_clear_error(); | 807 ERR_clear_error(); |
808 BIO_reset(bio); | 808 BIO_reset(bio); |
809 status = UseChainBytesPKCS12(context, bio); | 809 status = UseChainBytesPKCS12(context, bio, password); |
810 } else if (status != 0) { | 810 } else if (status != 0) { |
811 // The PEM file was successfully read. | 811 // The PEM file was successfully read. |
812 ERR_clear_error(); | 812 ERR_clear_error(); |
813 } | 813 } |
814 return status; | 814 return status; |
815 } | 815 } |
816 | 816 |
817 | 817 |
818 void FUNCTION_NAME(SecurityContext_UseCertificateChainBytes)( | 818 void FUNCTION_NAME(SecurityContext_UseCertificateChainBytes)( |
819 Dart_NativeArguments args) { | 819 Dart_NativeArguments args) { |
820 SSL_CTX* context = GetSecurityContext(args); | 820 SSL_CTX* context = GetSecurityContext(args); |
| 821 const char* password = GetPasswordArgument(args, 2); |
821 int status; | 822 int status; |
822 { | 823 { |
823 ScopedMemBIO bio(ThrowIfError(Dart_GetNativeArgument(args, 1))); | 824 ScopedMemBIO bio(ThrowIfError(Dart_GetNativeArgument(args, 1))); |
824 status = UseChainBytes(context, bio.bio()); | 825 status = UseChainBytes(context, bio.bio(), password); |
825 } | 826 } |
826 CheckStatus(status, | 827 CheckStatus(status, |
827 "TlsException", | 828 "TlsException", |
828 "Failure in useCertificateChainBytes"); | 829 "Failure in useCertificateChainBytes"); |
829 } | 830 } |
830 | 831 |
831 | 832 |
832 static STACK_OF(X509_NAME)* GetCertificateNamesPKCS12(BIO* bio) { | 833 static STACK_OF(X509_NAME)* GetCertificateNamesPKCS12(BIO* bio, |
| 834 const char* password) { |
833 ScopedPKCS12 p12(d2i_PKCS12_bio(bio, NULL)); | 835 ScopedPKCS12 p12(d2i_PKCS12_bio(bio, NULL)); |
834 if (p12.get() == NULL) { | 836 if (p12.get() == NULL) { |
835 return NULL; | 837 return NULL; |
836 } | 838 } |
837 | 839 |
838 ScopedX509NAMEStack result(sk_X509_NAME_new_null()); | 840 ScopedX509NAMEStack result(sk_X509_NAME_new_null()); |
839 if (result.get() == NULL) { | 841 if (result.get() == NULL) { |
840 return NULL; | 842 return NULL; |
841 } | 843 } |
842 | 844 |
843 EVP_PKEY* key = NULL; | 845 EVP_PKEY* key = NULL; |
844 X509 *cert = NULL; | 846 X509 *cert = NULL; |
845 STACK_OF(X509) *ca_certs = NULL; | 847 STACK_OF(X509) *ca_certs = NULL; |
846 // There should be no private keys in this file, so we hardcode the password | 848 int status = PKCS12_parse(p12.get(), password, &key, &cert, &ca_certs); |
847 // to "". | |
848 // TODO(zra): Allow passing a password anyway. | |
849 int status = PKCS12_parse(p12.get(), "", &key, &cert, &ca_certs); | |
850 if (status == 0) { | 849 if (status == 0) { |
851 return NULL; | 850 return NULL; |
852 } | 851 } |
853 | 852 |
854 ScopedX509 x509(cert); | 853 ScopedX509 x509(cert); |
855 ScopedX509Stack certs(ca_certs); | 854 ScopedX509Stack certs(ca_certs); |
856 | |
857 // There should be no private key. | |
858 if (key != NULL) { | |
859 return NULL; | |
860 } | |
861 | |
862 X509_NAME* x509_name = X509_get_subject_name(x509.get()); | 855 X509_NAME* x509_name = X509_get_subject_name(x509.get()); |
863 if (x509_name == NULL) { | 856 if (x509_name == NULL) { |
864 return NULL; | 857 return NULL; |
865 } | 858 } |
866 | 859 |
867 x509_name = X509_NAME_dup(x509_name); | 860 x509_name = X509_NAME_dup(x509_name); |
868 if (x509_name == NULL) { | 861 if (x509_name == NULL) { |
869 return NULL; | 862 return NULL; |
870 } | 863 } |
871 | 864 |
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
928 if ((ERR_GET_LIB(err) != ERR_LIB_PEM) || | 921 if ((ERR_GET_LIB(err) != ERR_LIB_PEM) || |
929 (ERR_GET_REASON(err) != PEM_R_NO_START_LINE)) { | 922 (ERR_GET_REASON(err) != PEM_R_NO_START_LINE)) { |
930 // The data was trying to be PEM, but was malformed. | 923 // The data was trying to be PEM, but was malformed. |
931 return NULL; | 924 return NULL; |
932 } | 925 } |
933 | 926 |
934 return result.release(); | 927 return result.release(); |
935 } | 928 } |
936 | 929 |
937 | 930 |
938 static STACK_OF(X509_NAME)* GetCertificateNames(BIO* bio) { | 931 static STACK_OF(X509_NAME)* GetCertificateNames(BIO* bio, |
| 932 const char* password) { |
939 STACK_OF(X509_NAME)* result = GetCertificateNamesPEM(bio); | 933 STACK_OF(X509_NAME)* result = GetCertificateNamesPEM(bio); |
940 if (TryPKCS12(result != NULL)) { | 934 if (TryPKCS12(result != NULL)) { |
941 ERR_clear_error(); | 935 ERR_clear_error(); |
942 BIO_reset(bio); | 936 BIO_reset(bio); |
943 result = GetCertificateNamesPKCS12(bio); | 937 result = GetCertificateNamesPKCS12(bio, password); |
944 } else if (result != NULL) { | 938 } else if (result != NULL) { |
945 // The PEM file was successfully parsed. | 939 // The PEM file was successfully parsed. |
946 ERR_clear_error(); | 940 ERR_clear_error(); |
947 } | 941 } |
948 return result; | 942 return result; |
949 } | 943 } |
950 | 944 |
951 | 945 |
952 void FUNCTION_NAME(SecurityContext_SetClientAuthoritiesBytes)( | 946 void FUNCTION_NAME(SecurityContext_SetClientAuthoritiesBytes)( |
953 Dart_NativeArguments args) { | 947 Dart_NativeArguments args) { |
954 SSL_CTX* context = GetSecurityContext(args); | 948 SSL_CTX* context = GetSecurityContext(args); |
| 949 const char* password = GetPasswordArgument(args, 2); |
955 STACK_OF(X509_NAME)* certificate_names; | 950 STACK_OF(X509_NAME)* certificate_names; |
956 | 951 |
957 { | 952 { |
958 ScopedMemBIO bio(ThrowIfError(Dart_GetNativeArgument(args, 1))); | 953 ScopedMemBIO bio(ThrowIfError(Dart_GetNativeArgument(args, 1))); |
959 certificate_names = GetCertificateNames(bio.bio()); | 954 certificate_names = GetCertificateNames(bio.bio(), password); |
960 } | 955 } |
961 | 956 |
962 if (certificate_names != NULL) { | 957 if (certificate_names != NULL) { |
963 SSL_CTX_set_client_CA_list(context, certificate_names); | 958 SSL_CTX_set_client_CA_list(context, certificate_names); |
964 } else { | 959 } else { |
965 Dart_ThrowException(DartUtils::NewDartArgumentError( | 960 Dart_ThrowException(DartUtils::NewDartArgumentError( |
966 "Could not load certificate names from file in SetClientAuthorities")); | 961 "Could not load certificate names from file in SetClientAuthorities")); |
967 } | 962 } |
968 } | 963 } |
969 | 964 |
(...skipping 614 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1584 } else { | 1579 } else { |
1585 if (SSL_LOG_DATA) Log::Print( | 1580 if (SSL_LOG_DATA) Log::Print( |
1586 "WriteEncrypted BIO_read wrote %d bytes\n", bytes_processed); | 1581 "WriteEncrypted BIO_read wrote %d bytes\n", bytes_processed); |
1587 } | 1582 } |
1588 } | 1583 } |
1589 return bytes_processed; | 1584 return bytes_processed; |
1590 } | 1585 } |
1591 | 1586 |
1592 } // namespace bin | 1587 } // namespace bin |
1593 } // namespace dart | 1588 } // namespace dart |
OLD | NEW |