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 |
559 void FUNCTION_NAME(SecurityContext_UsePrivateKeyBytes)( | 565 static const char* GetPasswordArgument(Dart_NativeArguments args, |
560 Dart_NativeArguments args) { | 566 intptr_t index) { |
561 SSL_CTX* context = GetSecurityContext(args); | 567 Dart_Handle password_object = |
562 | 568 ThrowIfError(Dart_GetNativeArgument(args, index)); |
563 Dart_Handle password_object = ThrowIfError(Dart_GetNativeArgument(args, 2)); | |
564 const char* password = NULL; | 569 const char* password = NULL; |
565 if (Dart_IsString(password_object)) { | 570 if (Dart_IsString(password_object)) { |
566 ThrowIfError(Dart_StringToCString(password_object, &password)); | 571 ThrowIfError(Dart_StringToCString(password_object, &password)); |
567 if (strlen(password) > PEM_BUFSIZE - 1) { | 572 if (strlen(password) > PEM_BUFSIZE - 1) { |
568 Dart_ThrowException(DartUtils::NewDartArgumentError( | 573 Dart_ThrowException(DartUtils::NewDartArgumentError( |
569 "SecurityContext.usePrivateKey password length is greater than" | 574 "SecurityContext.usePrivateKey password length is greater than" |
570 " 1023 (PEM_BUFSIZE)")); | 575 " 1023 (PEM_BUFSIZE)")); |
571 } | 576 } |
572 } else if (Dart_IsNull(password_object)) { | 577 } else if (Dart_IsNull(password_object)) { |
573 password = ""; | 578 password = ""; |
574 } else { | 579 } else { |
575 Dart_ThrowException(DartUtils::NewDartArgumentError( | 580 Dart_ThrowException(DartUtils::NewDartArgumentError( |
576 "SecurityContext.usePrivateKey password is not a String or null")); | 581 "Password is not a String or null")); |
577 } | 582 } |
| 583 return password; |
| 584 } |
| 585 |
| 586 |
| 587 void FUNCTION_NAME(SecurityContext_UsePrivateKeyBytes)( |
| 588 Dart_NativeArguments args) { |
| 589 SSL_CTX* context = GetSecurityContext(args); |
| 590 const char* password = GetPasswordArgument(args, 2); |
578 | 591 |
579 int status; | 592 int status; |
580 { | 593 { |
581 ScopedMemBIO bio(ThrowIfError(Dart_GetNativeArgument(args, 1))); | 594 ScopedMemBIO bio(ThrowIfError(Dart_GetNativeArgument(args, 1))); |
582 EVP_PKEY *key = GetPrivateKey(bio.bio(), password); | 595 EVP_PKEY *key = GetPrivateKey(bio.bio(), password); |
583 status = SSL_CTX_use_PrivateKey(context, key); | 596 status = SSL_CTX_use_PrivateKey(context, key); |
584 } | 597 } |
585 | 598 |
586 // TODO(24184): Handle different expected errors here - file missing, | 599 // TODO(24184): Handle different expected errors here - file missing, |
587 // incorrect password, file not a PEM, and throw exceptions. | 600 // incorrect password, file not a PEM, and throw exceptions. |
588 // CheckStatus should also throw an exception in uncaught cases. | 601 // CheckStatus should also throw an exception in uncaught cases. |
589 CheckStatus(status, "TlsException", "Failure in usePrivateKeyBytes"); | 602 CheckStatus(status, "TlsException", "Failure in usePrivateKeyBytes"); |
590 } | 603 } |
591 | 604 |
592 | 605 |
593 static int SetTrustedCertificatesBytesPKCS12(SSL_CTX* context, BIO* bio) { | 606 static int SetTrustedCertificatesBytesPKCS12(SSL_CTX* context, |
| 607 BIO* bio, |
| 608 const char* password) { |
594 ScopedPKCS12 p12(d2i_PKCS12_bio(bio, NULL)); | 609 ScopedPKCS12 p12(d2i_PKCS12_bio(bio, NULL)); |
595 if (p12.get() == NULL) { | 610 if (p12.get() == NULL) { |
596 return NULL; | 611 return NULL; |
597 } | 612 } |
598 | 613 |
599 EVP_PKEY* key = NULL; | 614 EVP_PKEY* key = NULL; |
600 X509 *cert = NULL; | 615 X509 *cert = NULL; |
601 STACK_OF(X509) *ca_certs = NULL; | 616 STACK_OF(X509) *ca_certs = NULL; |
602 // There should be no private keys in this file, so we hardcode the password | 617 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) { | 618 if (status == 0) { |
607 return status; | 619 return status; |
608 } | 620 } |
609 | 621 |
610 ScopedX509Stack cert_stack(ca_certs); | 622 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); | 623 X509_STORE* store = SSL_CTX_get_cert_store(context); |
619 status = X509_STORE_add_cert(store, cert); | 624 status = X509_STORE_add_cert(store, cert); |
620 if (status == 0) { | 625 if (status == 0) { |
621 X509_free(cert); | 626 X509_free(cert); |
622 return status; | 627 return status; |
623 } | 628 } |
624 | 629 |
625 X509* ca; | 630 X509* ca; |
626 while ((ca = sk_X509_shift(cert_stack.get())) != NULL) { | 631 while ((ca = sk_X509_shift(cert_stack.get())) != NULL) { |
627 status = X509_STORE_add_cert(store, ca); | 632 status = X509_STORE_add_cert(store, ca); |
(...skipping 27 matching lines...) Expand all Loading... |
655 (ERR_GET_REASON(err) != PEM_R_NO_START_LINE)) { | 660 (ERR_GET_REASON(err) != PEM_R_NO_START_LINE)) { |
656 // If bio contains data that is trying to be PEM but is malformed, then | 661 // If bio contains data that is trying to be PEM but is malformed, then |
657 // this case will be triggered. | 662 // this case will be triggered. |
658 status = 0; | 663 status = 0; |
659 } | 664 } |
660 | 665 |
661 return status; | 666 return status; |
662 } | 667 } |
663 | 668 |
664 | 669 |
665 static int SetTrustedCertificatesBytes(SSL_CTX* context, BIO* bio) { | 670 static int SetTrustedCertificatesBytes(SSL_CTX* context, |
| 671 BIO* bio, |
| 672 const char* password) { |
666 int status = SetTrustedCertificatesBytesPEM(context, bio); | 673 int status = SetTrustedCertificatesBytesPEM(context, bio); |
667 if (TryPKCS12(status != 0)) { | 674 if (TryPKCS12(status != 0)) { |
668 ERR_clear_error(); | 675 ERR_clear_error(); |
669 BIO_reset(bio); | 676 BIO_reset(bio); |
670 status = SetTrustedCertificatesBytesPKCS12(context, bio); | 677 status = SetTrustedCertificatesBytesPKCS12(context, bio, password); |
671 } else if (status != 0) { | 678 } else if (status != 0) { |
672 // The PEM file was successfully parsed. | 679 // The PEM file was successfully parsed. |
673 ERR_clear_error(); | 680 ERR_clear_error(); |
674 } | 681 } |
675 return status; | 682 return status; |
676 } | 683 } |
677 | 684 |
678 | 685 |
679 void FUNCTION_NAME(SecurityContext_SetTrustedCertificatesBytes)( | 686 void FUNCTION_NAME(SecurityContext_SetTrustedCertificatesBytes)( |
680 Dart_NativeArguments args) { | 687 Dart_NativeArguments args) { |
681 SSL_CTX* context = GetSecurityContext(args); | 688 SSL_CTX* context = GetSecurityContext(args); |
| 689 const char* password = GetPasswordArgument(args, 2); |
682 int status; | 690 int status; |
683 { | 691 { |
684 ScopedMemBIO bio(ThrowIfError(Dart_GetNativeArgument(args, 1))); | 692 ScopedMemBIO bio(ThrowIfError(Dart_GetNativeArgument(args, 1))); |
685 status = SetTrustedCertificatesBytes(context, bio.bio()); | 693 status = SetTrustedCertificatesBytes(context, bio.bio(), password); |
686 } | 694 } |
687 CheckStatus(status, | 695 CheckStatus(status, |
688 "TlsException", | 696 "TlsException", |
689 "Failure in setTrustedCertificatesBytes"); | 697 "Failure in setTrustedCertificatesBytes"); |
690 } | 698 } |
691 | 699 |
692 | 700 |
693 void FUNCTION_NAME(SecurityContext_TrustBuiltinRoots)( | 701 void FUNCTION_NAME(SecurityContext_TrustBuiltinRoots)( |
694 Dart_NativeArguments args) { | 702 Dart_NativeArguments args) { |
695 SSL_CTX* context = GetSecurityContext(args); | 703 SSL_CTX* context = GetSecurityContext(args); |
696 X509_STORE* store = SSL_CTX_get_cert_store(context); | 704 X509_STORE* store = SSL_CTX_get_cert_store(context); |
697 BIO* roots_bio = | 705 BIO* roots_bio = |
698 BIO_new_mem_buf(const_cast<unsigned char*>(root_certificates_pem), | 706 BIO_new_mem_buf(const_cast<unsigned char*>(root_certificates_pem), |
699 root_certificates_pem_length); | 707 root_certificates_pem_length); |
700 X509* root_cert; | 708 X509* root_cert; |
701 // PEM_read_bio_X509 reads PEM-encoded certificates from a bio (in our case, | 709 // 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. | 710 // backed by a memory buffer), and returns X509 objects, one by one. |
703 // When the end of the bio is reached, it returns null. | 711 // When the end of the bio is reached, it returns null. |
704 while ((root_cert = PEM_read_bio_X509(roots_bio, NULL, NULL, NULL))) { | 712 while ((root_cert = PEM_read_bio_X509(roots_bio, NULL, NULL, NULL))) { |
705 X509_STORE_add_cert(store, root_cert); | 713 X509_STORE_add_cert(store, root_cert); |
706 } | 714 } |
707 BIO_free(roots_bio); | 715 BIO_free(roots_bio); |
708 } | 716 } |
709 | 717 |
710 | 718 |
711 static int UseChainBytesPKCS12(SSL_CTX* context, BIO* bio) { | 719 static int UseChainBytesPKCS12(SSL_CTX* context, |
| 720 BIO* bio, |
| 721 const char* password) { |
712 ScopedPKCS12 p12(d2i_PKCS12_bio(bio, NULL)); | 722 ScopedPKCS12 p12(d2i_PKCS12_bio(bio, NULL)); |
713 if (p12.get() == NULL) { | 723 if (p12.get() == NULL) { |
714 return NULL; | 724 return NULL; |
715 } | 725 } |
716 | 726 |
717 EVP_PKEY* key = NULL; | 727 EVP_PKEY* key = NULL; |
718 X509 *cert = NULL; | 728 X509 *cert = NULL; |
719 STACK_OF(X509) *ca_certs = NULL; | 729 STACK_OF(X509) *ca_certs = NULL; |
720 // There should be no private keys in this file, so we hardcode the password | 730 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) { | 731 if (status == 0) { |
725 return status; | 732 return status; |
726 } | 733 } |
727 | 734 |
728 ScopedX509 x509(cert); | 735 ScopedX509 x509(cert); |
729 ScopedX509Stack certs(ca_certs); | 736 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()); | 737 status = SSL_CTX_use_certificate(context, x509.get()); |
737 if (ERR_peek_error() != 0) { | 738 if (ERR_peek_error() != 0) { |
738 // Key/certificate mismatch doesn't imply status is 0. | 739 // Key/certificate mismatch doesn't imply status is 0. |
739 status = 0; | 740 status = 0; |
740 } | 741 } |
741 if (status == 0) { | 742 if (status == 0) { |
742 return status; | 743 return status; |
743 } | 744 } |
744 | 745 |
745 SSL_CTX_clear_chain_certs(context); | 746 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)) { | 795 (ERR_GET_REASON(err) != PEM_R_NO_START_LINE)) { |
795 // If bio contains data that is trying to be PEM but is malformed, then | 796 // If bio contains data that is trying to be PEM but is malformed, then |
796 // this case will be triggered. | 797 // this case will be triggered. |
797 status = 0; | 798 status = 0; |
798 } | 799 } |
799 | 800 |
800 return status; | 801 return status; |
801 } | 802 } |
802 | 803 |
803 | 804 |
804 static int UseChainBytes(SSL_CTX* context, BIO* bio) { | 805 static int UseChainBytes(SSL_CTX* context, BIO* bio, const char* password) { |
805 int status = UseChainBytesPEM(context, bio); | 806 int status = UseChainBytesPEM(context, bio); |
806 if (TryPKCS12(status != 0)) { | 807 if (TryPKCS12(status != 0)) { |
807 ERR_clear_error(); | 808 ERR_clear_error(); |
808 BIO_reset(bio); | 809 BIO_reset(bio); |
809 status = UseChainBytesPKCS12(context, bio); | 810 status = UseChainBytesPKCS12(context, bio, password); |
810 } else if (status != 0) { | 811 } else if (status != 0) { |
811 // The PEM file was successfully read. | 812 // The PEM file was successfully read. |
812 ERR_clear_error(); | 813 ERR_clear_error(); |
813 } | 814 } |
814 return status; | 815 return status; |
815 } | 816 } |
816 | 817 |
817 | 818 |
818 void FUNCTION_NAME(SecurityContext_UseCertificateChainBytes)( | 819 void FUNCTION_NAME(SecurityContext_UseCertificateChainBytes)( |
819 Dart_NativeArguments args) { | 820 Dart_NativeArguments args) { |
820 SSL_CTX* context = GetSecurityContext(args); | 821 SSL_CTX* context = GetSecurityContext(args); |
| 822 const char* password = GetPasswordArgument(args, 2); |
821 int status; | 823 int status; |
822 { | 824 { |
823 ScopedMemBIO bio(ThrowIfError(Dart_GetNativeArgument(args, 1))); | 825 ScopedMemBIO bio(ThrowIfError(Dart_GetNativeArgument(args, 1))); |
824 status = UseChainBytes(context, bio.bio()); | 826 status = UseChainBytes(context, bio.bio(), password); |
825 } | 827 } |
826 CheckStatus(status, | 828 CheckStatus(status, |
827 "TlsException", | 829 "TlsException", |
828 "Failure in useCertificateChainBytes"); | 830 "Failure in useCertificateChainBytes"); |
829 } | 831 } |
830 | 832 |
831 | 833 |
832 static STACK_OF(X509_NAME)* GetCertificateNamesPKCS12(BIO* bio) { | 834 static STACK_OF(X509_NAME)* GetCertificateNamesPKCS12(BIO* bio, |
| 835 const char* password) { |
833 ScopedPKCS12 p12(d2i_PKCS12_bio(bio, NULL)); | 836 ScopedPKCS12 p12(d2i_PKCS12_bio(bio, NULL)); |
834 if (p12.get() == NULL) { | 837 if (p12.get() == NULL) { |
835 return NULL; | 838 return NULL; |
836 } | 839 } |
837 | 840 |
838 ScopedX509NAMEStack result(sk_X509_NAME_new_null()); | 841 ScopedX509NAMEStack result(sk_X509_NAME_new_null()); |
839 if (result.get() == NULL) { | 842 if (result.get() == NULL) { |
840 return NULL; | 843 return NULL; |
841 } | 844 } |
842 | 845 |
843 EVP_PKEY* key = NULL; | 846 EVP_PKEY* key = NULL; |
844 X509 *cert = NULL; | 847 X509 *cert = NULL; |
845 STACK_OF(X509) *ca_certs = NULL; | 848 STACK_OF(X509) *ca_certs = NULL; |
846 // There should be no private keys in this file, so we hardcode the password | 849 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) { | 850 if (status == 0) { |
851 return NULL; | 851 return NULL; |
852 } | 852 } |
853 | 853 |
854 ScopedX509 x509(cert); | 854 ScopedX509 x509(cert); |
855 ScopedX509Stack certs(ca_certs); | 855 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()); | 856 X509_NAME* x509_name = X509_get_subject_name(x509.get()); |
863 if (x509_name == NULL) { | 857 if (x509_name == NULL) { |
864 return NULL; | 858 return NULL; |
865 } | 859 } |
866 | 860 |
867 x509_name = X509_NAME_dup(x509_name); | 861 x509_name = X509_NAME_dup(x509_name); |
868 if (x509_name == NULL) { | 862 if (x509_name == NULL) { |
869 return NULL; | 863 return NULL; |
870 } | 864 } |
871 | 865 |
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
928 if ((ERR_GET_LIB(err) != ERR_LIB_PEM) || | 922 if ((ERR_GET_LIB(err) != ERR_LIB_PEM) || |
929 (ERR_GET_REASON(err) != PEM_R_NO_START_LINE)) { | 923 (ERR_GET_REASON(err) != PEM_R_NO_START_LINE)) { |
930 // The data was trying to be PEM, but was malformed. | 924 // The data was trying to be PEM, but was malformed. |
931 return NULL; | 925 return NULL; |
932 } | 926 } |
933 | 927 |
934 return result.release(); | 928 return result.release(); |
935 } | 929 } |
936 | 930 |
937 | 931 |
938 static STACK_OF(X509_NAME)* GetCertificateNames(BIO* bio) { | 932 static STACK_OF(X509_NAME)* GetCertificateNames(BIO* bio, |
| 933 const char* password) { |
939 STACK_OF(X509_NAME)* result = GetCertificateNamesPEM(bio); | 934 STACK_OF(X509_NAME)* result = GetCertificateNamesPEM(bio); |
940 if (TryPKCS12(result != NULL)) { | 935 if (TryPKCS12(result != NULL)) { |
941 ERR_clear_error(); | 936 ERR_clear_error(); |
942 BIO_reset(bio); | 937 BIO_reset(bio); |
943 result = GetCertificateNamesPKCS12(bio); | 938 result = GetCertificateNamesPKCS12(bio, password); |
944 } else if (result != NULL) { | 939 } else if (result != NULL) { |
945 // The PEM file was successfully parsed. | 940 // The PEM file was successfully parsed. |
946 ERR_clear_error(); | 941 ERR_clear_error(); |
947 } | 942 } |
948 return result; | 943 return result; |
949 } | 944 } |
950 | 945 |
951 | 946 |
952 void FUNCTION_NAME(SecurityContext_SetClientAuthoritiesBytes)( | 947 void FUNCTION_NAME(SecurityContext_SetClientAuthoritiesBytes)( |
953 Dart_NativeArguments args) { | 948 Dart_NativeArguments args) { |
954 SSL_CTX* context = GetSecurityContext(args); | 949 SSL_CTX* context = GetSecurityContext(args); |
| 950 const char* password = GetPasswordArgument(args, 2); |
955 STACK_OF(X509_NAME)* certificate_names; | 951 STACK_OF(X509_NAME)* certificate_names; |
956 | 952 |
957 { | 953 { |
958 ScopedMemBIO bio(ThrowIfError(Dart_GetNativeArgument(args, 1))); | 954 ScopedMemBIO bio(ThrowIfError(Dart_GetNativeArgument(args, 1))); |
959 certificate_names = GetCertificateNames(bio.bio()); | 955 certificate_names = GetCertificateNames(bio.bio(), password); |
960 } | 956 } |
961 | 957 |
962 if (certificate_names != NULL) { | 958 if (certificate_names != NULL) { |
963 SSL_CTX_set_client_CA_list(context, certificate_names); | 959 SSL_CTX_set_client_CA_list(context, certificate_names); |
964 } else { | 960 } else { |
965 Dart_ThrowException(DartUtils::NewDartArgumentError( | 961 Dart_ThrowException(DartUtils::NewDartArgumentError( |
966 "Could not load certificate names from file in SetClientAuthorities")); | 962 "Could not load certificate names from file in SetClientAuthorities")); |
967 } | 963 } |
968 } | 964 } |
969 | 965 |
(...skipping 614 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1584 } else { | 1580 } else { |
1585 if (SSL_LOG_DATA) Log::Print( | 1581 if (SSL_LOG_DATA) Log::Print( |
1586 "WriteEncrypted BIO_read wrote %d bytes\n", bytes_processed); | 1582 "WriteEncrypted BIO_read wrote %d bytes\n", bytes_processed); |
1587 } | 1583 } |
1588 } | 1584 } |
1589 return bytes_processed; | 1585 return bytes_processed; |
1590 } | 1586 } |
1591 | 1587 |
1592 } // namespace bin | 1588 } // namespace bin |
1593 } // namespace dart | 1589 } // namespace dart |
OLD | NEW |