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