Chromium Code Reviews| 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 506 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 517 Dart_Handle object_; | 517 Dart_Handle object_; |
| 518 uint8_t* bytes_; | 518 uint8_t* bytes_; |
| 519 intptr_t bytes_len_; | 519 intptr_t bytes_len_; |
| 520 BIO* bio_; | 520 BIO* bio_; |
| 521 bool is_typed_data_; | 521 bool is_typed_data_; |
| 522 | 522 |
| 523 DISALLOW_ALLOCATION(); | 523 DISALLOW_ALLOCATION(); |
| 524 DISALLOW_COPY_AND_ASSIGN(ScopedMemBIO); | 524 DISALLOW_COPY_AND_ASSIGN(ScopedMemBIO); |
| 525 }; | 525 }; |
| 526 | 526 |
| 527 | |
| 528 template<typename T, void (*free_func)(T*)> | 527 template<typename T, void (*free_func)(T*)> |
| 529 class ScopedSSLType { | 528 class ScopedSSLType { |
| 530 public: | 529 public: |
| 531 explicit ScopedSSLType(T* obj) : obj_(obj) {} | 530 explicit ScopedSSLType(T* obj) : obj_(obj) {} |
| 532 | 531 |
| 533 ~ScopedSSLType() { | 532 ~ScopedSSLType() { |
| 534 if (obj_ != NULL) { | 533 if (obj_ != NULL) { |
| 535 free_func(obj_); | 534 free_func(obj_); |
| 536 } | 535 } |
| 537 } | 536 } |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 575 | 574 |
| 576 private: | 575 private: |
| 577 T* obj_; | 576 T* obj_; |
| 578 | 577 |
| 579 DISALLOW_ALLOCATION(); | 578 DISALLOW_ALLOCATION(); |
| 580 DISALLOW_COPY_AND_ASSIGN(ScopedSSLStackType); | 579 DISALLOW_COPY_AND_ASSIGN(ScopedSSLStackType); |
| 581 }; | 580 }; |
| 582 | 581 |
| 583 typedef ScopedSSLType<PKCS12, PKCS12_free> ScopedPKCS12; | 582 typedef ScopedSSLType<PKCS12, PKCS12_free> ScopedPKCS12; |
| 584 typedef ScopedSSLType<X509, X509_free> ScopedX509; | 583 typedef ScopedSSLType<X509, X509_free> ScopedX509; |
| 585 | |
| 586 typedef ScopedSSLStackType<STACK_OF(X509), X509, X509_free> ScopedX509Stack; | 584 typedef ScopedSSLStackType<STACK_OF(X509), X509, X509_free> ScopedX509Stack; |
| 587 typedef ScopedSSLStackType<STACK_OF(X509_NAME), X509_NAME, X509_NAME_free> | |
| 588 ScopedX509NAMEStack; | |
| 589 | |
| 590 | 585 |
| 591 // We try reading data as PKCS12 only if reading as PEM was unsuccessful and | 586 // We try reading data as PKCS12 only if reading as PEM was unsuccessful and |
| 592 // if there is no indication that the data is malformed PEM. We assume the data | 587 // if there is no indication that the data is malformed PEM. We assume the data |
| 593 // is malformed PEM if it contains the start line, i.e. a line with ----- BEGIN. | 588 // is malformed PEM if it contains the start line, i.e. a line with ----- BEGIN. |
| 594 static bool TryPKCS12(bool pem_success) { | 589 static bool TryPKCS12(bool pem_success) { |
| 595 uint32_t last_error = ERR_peek_last_error(); | 590 uint32_t last_error = ERR_peek_last_error(); |
| 596 return !pem_success && | 591 return !pem_success && |
| 597 (ERR_GET_LIB(last_error) == ERR_LIB_PEM) && | 592 (ERR_GET_LIB(last_error) == ERR_LIB_PEM) && |
| 598 (ERR_GET_REASON(last_error) == PEM_R_NO_START_LINE); | 593 (ERR_GET_REASON(last_error) == PEM_R_NO_START_LINE); |
| 599 } | 594 } |
| (...skipping 296 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 896 { | 891 { |
| 897 ScopedMemBIO bio(ThrowIfError(Dart_GetNativeArgument(args, 1))); | 892 ScopedMemBIO bio(ThrowIfError(Dart_GetNativeArgument(args, 1))); |
| 898 status = UseChainBytes(context, bio.bio(), password); | 893 status = UseChainBytes(context, bio.bio(), password); |
| 899 } | 894 } |
| 900 CheckStatus(status, | 895 CheckStatus(status, |
| 901 "TlsException", | 896 "TlsException", |
| 902 "Failure in useCertificateChainBytes"); | 897 "Failure in useCertificateChainBytes"); |
| 903 } | 898 } |
| 904 | 899 |
| 905 | 900 |
| 906 static STACK_OF(X509_NAME)* GetCertificateNamesPKCS12(BIO* bio, | 901 static int SetClientAuthoritiesPKCS12(SSL_CTX* context, |
| 907 const char* password) { | 902 BIO* bio, |
| 903 const char* password) { | |
| 908 ScopedPKCS12 p12(d2i_PKCS12_bio(bio, NULL)); | 904 ScopedPKCS12 p12(d2i_PKCS12_bio(bio, NULL)); |
| 909 if (p12.get() == NULL) { | 905 if (p12.get() == NULL) { |
| 910 return NULL; | 906 return NULL; |
| 911 } | 907 } |
| 912 | 908 |
| 913 ScopedX509NAMEStack result(sk_X509_NAME_new_null()); | |
| 914 if (result.get() == NULL) { | |
| 915 return NULL; | |
| 916 } | |
| 917 | |
| 918 EVP_PKEY* key = NULL; | 909 EVP_PKEY* key = NULL; |
| 919 X509 *cert = NULL; | 910 X509 *cert = NULL; |
| 920 STACK_OF(X509) *ca_certs = NULL; | 911 STACK_OF(X509) *ca_certs = NULL; |
| 921 int status = PKCS12_parse(p12.get(), password, &key, &cert, &ca_certs); | 912 int status = PKCS12_parse(p12.get(), password, &key, &cert, &ca_certs); |
| 922 if (status == 0) { | 913 if (status == 0) { |
| 923 return NULL; | 914 return status; |
| 924 } | 915 } |
| 925 | 916 |
| 926 ScopedX509 x509(cert); | 917 ScopedX509Stack cert_stack(ca_certs); |
| 927 ScopedX509Stack certs(ca_certs); | 918 status = SSL_CTX_add_client_CA(context, cert); |
| 928 X509_NAME* x509_name = X509_get_subject_name(x509.get()); | 919 if (status == 0) { |
| 929 if (x509_name == NULL) { | 920 X509_free(cert); |
| 930 return NULL; | 921 return status; |
| 931 } | 922 } |
| 932 | 923 |
| 933 x509_name = X509_NAME_dup(x509_name); | 924 X509* ca; |
| 934 if (x509_name == NULL) { | 925 while ((ca = sk_X509_shift(cert_stack.get())) != NULL) { |
| 935 return NULL; | 926 status = SSL_CTX_add_client_CA(context, ca); |
| 927 X509_free(ca); // The name has been extracted. | |
| 928 if (status == 0) { | |
| 929 return status; | |
| 930 } | |
| 936 } | 931 } |
| 937 | 932 |
| 938 sk_X509_NAME_push(result.get(), x509_name); | 933 return status; |
| 939 | |
| 940 while (true) { | |
| 941 ScopedX509 ca(sk_X509_shift(certs.get())); | |
| 942 if (ca.get() == NULL) { | |
| 943 break; | |
| 944 } | |
| 945 | |
| 946 X509_NAME* x509_name = X509_get_subject_name(ca.get()); | |
| 947 if (x509_name == NULL) { | |
| 948 return NULL; | |
| 949 } | |
| 950 | |
| 951 x509_name = X509_NAME_dup(x509_name); | |
| 952 if (x509_name == NULL) { | |
| 953 return NULL; | |
| 954 } | |
| 955 | |
| 956 sk_X509_NAME_push(result.get(), x509_name); | |
| 957 } | |
| 958 | |
| 959 return result.release(); | |
| 960 } | 934 } |
| 961 | 935 |
| 962 | 936 |
| 963 static STACK_OF(X509_NAME)* GetCertificateNamesPEM(BIO* bio) { | 937 static int SetClientAuthoritiesPEM(SSL_CTX* context, BIO* bio) { |
| 964 ScopedX509NAMEStack result(sk_X509_NAME_new_null()); | 938 int status = 0; |
| 965 if (result.get() == NULL) { | 939 X509* cert = NULL; |
| 966 return NULL; | 940 while ((cert = PEM_read_bio_X509(bio, NULL, NULL, NULL)) != NULL) { |
| 941 status = SSL_CTX_add_client_CA(context, cert); | |
| 942 X509_free(cert); // The name has been extracted. | |
| 943 if (status == 0) { | |
| 944 return status; | |
| 945 } | |
| 967 } | 946 } |
| 968 | 947 |
| 969 while (true) { | 948 // If bio does not contain PEM data, the first call to PEM_read_bio_X509 will |
| 970 ScopedX509 x509(PEM_read_bio_X509(bio, NULL, NULL, NULL)); | 949 // return NULL, and the while-loop will exit while status is still 0. |
| 971 if (x509.get() == NULL) { | |
| 972 break; | |
| 973 } | |
| 974 | |
| 975 X509_NAME* x509_name = X509_get_subject_name(x509.get()); | |
| 976 if (x509_name == NULL) { | |
| 977 return NULL; | |
| 978 } | |
| 979 | |
| 980 // Duplicate the name to put it on the stack. | |
| 981 x509_name = X509_NAME_dup(x509_name); | |
| 982 if (x509_name == NULL) { | |
| 983 return NULL; | |
| 984 } | |
| 985 sk_X509_NAME_push(result.get(), x509_name); | |
| 986 } | |
| 987 | |
| 988 if (sk_X509_NAME_num(result.get()) == 0) { | |
| 989 // The data was not PEM. | |
| 990 return NULL; | |
| 991 } | |
| 992 | |
| 993 uint32_t err = ERR_peek_last_error(); | 950 uint32_t err = ERR_peek_last_error(); |
| 994 if ((ERR_GET_LIB(err) != ERR_LIB_PEM) || | 951 if ((ERR_GET_LIB(err) != ERR_LIB_PEM) || |
| 995 (ERR_GET_REASON(err) != PEM_R_NO_START_LINE)) { | 952 (ERR_GET_REASON(err) != PEM_R_NO_START_LINE)) { |
| 996 // The data was trying to be PEM, but was malformed. | 953 // If bio contains data that is trying to be PEM but is malformed, then |
| 997 return NULL; | 954 // this case will be triggered. |
| 955 status = 0; | |
| 998 } | 956 } |
| 999 | 957 |
| 1000 return result.release(); | 958 return status; |
| 1001 } | 959 } |
| 1002 | 960 |
| 1003 | 961 |
| 1004 static STACK_OF(X509_NAME)* GetCertificateNames(BIO* bio, | 962 static int SetClientAuthorities(SSL_CTX* context, |
| 1005 const char* password) { | 963 BIO* bio, |
| 1006 STACK_OF(X509_NAME)* result = GetCertificateNamesPEM(bio); | 964 const char* password) { |
| 1007 if (TryPKCS12(result != NULL)) { | 965 int status = SetClientAuthoritiesPEM(context, bio); |
| 966 if (TryPKCS12(status != 0)) { | |
|
Ivan Posva
2016/03/02 21:56:50
Can we please rewrite this to be less backwards to
zra
2016/03/02 23:12:34
Done.
| |
| 1008 ERR_clear_error(); | 967 ERR_clear_error(); |
| 1009 BIO_reset(bio); | 968 BIO_reset(bio); |
| 1010 result = GetCertificateNamesPKCS12(bio, password); | 969 status = SetClientAuthoritiesPKCS12(context, bio, password); |
| 1011 } else if (result != NULL) { | 970 } else if (status != 0) { |
| 1012 // The PEM file was successfully parsed. | 971 // The PEM file was successfully parsed. |
| 1013 ERR_clear_error(); | 972 ERR_clear_error(); |
| 1014 } | 973 } |
| 1015 return result; | 974 return status; |
| 1016 } | 975 } |
| 1017 | 976 |
| 1018 | 977 |
| 1019 void FUNCTION_NAME(SecurityContext_SetClientAuthoritiesBytes)( | 978 void FUNCTION_NAME(SecurityContext_SetClientAuthoritiesBytes)( |
| 1020 Dart_NativeArguments args) { | 979 Dart_NativeArguments args) { |
| 1021 SSL_CTX* context = GetSecurityContext(args); | 980 SSL_CTX* context = GetSecurityContext(args); |
| 1022 const char* password = GetPasswordArgument(args, 2); | 981 const char* password = GetPasswordArgument(args, 2); |
| 1023 STACK_OF(X509_NAME)* certificate_names; | |
| 1024 | 982 |
| 983 int status; | |
| 1025 { | 984 { |
| 1026 ScopedMemBIO bio(ThrowIfError(Dart_GetNativeArgument(args, 1))); | 985 ScopedMemBIO bio(ThrowIfError(Dart_GetNativeArgument(args, 1))); |
| 1027 certificate_names = GetCertificateNames(bio.bio(), password); | 986 status = SetClientAuthorities(context, bio.bio(), password); |
| 1028 } | 987 } |
| 1029 | 988 |
| 1030 if (certificate_names != NULL) { | 989 CheckStatus(status, |
| 1031 SSL_CTX_set_client_CA_list(context, certificate_names); | 990 "TlsException", |
| 1032 } else { | 991 "Failure in setClientAuthoritiesBytes"); |
| 1033 Dart_ThrowException(DartUtils::NewDartArgumentError( | |
| 1034 "Could not load certificate names from file in SetClientAuthorities")); | |
| 1035 } | |
| 1036 } | 992 } |
| 1037 | 993 |
| 1038 | 994 |
| 1039 void FUNCTION_NAME(SecurityContext_SetAlpnProtocols)( | 995 void FUNCTION_NAME(SecurityContext_SetAlpnProtocols)( |
| 1040 Dart_NativeArguments args) { | 996 Dart_NativeArguments args) { |
| 1041 SSL_CTX* context = GetSecurityContext(args); | 997 SSL_CTX* context = GetSecurityContext(args); |
| 1042 Dart_Handle protocols_handle = | 998 Dart_Handle protocols_handle = |
| 1043 ThrowIfError(Dart_GetNativeArgument(args, 1)); | 999 ThrowIfError(Dart_GetNativeArgument(args, 1)); |
| 1044 Dart_Handle is_server_handle = | 1000 Dart_Handle is_server_handle = |
| 1045 ThrowIfError(Dart_GetNativeArgument(args, 2)); | 1001 ThrowIfError(Dart_GetNativeArgument(args, 2)); |
| (...skipping 667 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1713 } else { | 1669 } else { |
| 1714 if (SSL_LOG_DATA) Log::Print( | 1670 if (SSL_LOG_DATA) Log::Print( |
| 1715 "WriteEncrypted BIO_read wrote %d bytes\n", bytes_processed); | 1671 "WriteEncrypted BIO_read wrote %d bytes\n", bytes_processed); |
| 1716 } | 1672 } |
| 1717 } | 1673 } |
| 1718 return bytes_processed; | 1674 return bytes_processed; |
| 1719 } | 1675 } |
| 1720 | 1676 |
| 1721 } // namespace bin | 1677 } // namespace bin |
| 1722 } // namespace dart | 1678 } // namespace dart |
| OLD | NEW |