| 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 |