Index: runtime/bin/secure_socket_boringssl.cc |
diff --git a/runtime/bin/secure_socket_boringssl.cc b/runtime/bin/secure_socket_boringssl.cc |
index def3aae0b8e3875efc66891a7f3769fa299d46bc..e881815796af5c897652ef5f08f09ba3aa652799 100644 |
--- a/runtime/bin/secure_socket_boringssl.cc |
+++ b/runtime/bin/secure_socket_boringssl.cc |
@@ -94,11 +94,14 @@ static void ThrowIOException(int status, |
const char* message) { |
char error_string[SSL_ERROR_MESSAGE_BUFFER_SIZE]; |
FetchErrorString(error_string, SSL_ERROR_MESSAGE_BUFFER_SIZE); |
- OSError os_error_struct(status, error_string, OSError::kBoringSSL); |
- Dart_Handle os_error = DartUtils::NewDartOSError(&os_error_struct); |
- Dart_Handle exception = |
- DartUtils::NewDartIOException(exception_type, message, os_error); |
- ASSERT(!Dart_IsError(exception)); |
+ Dart_Handle exception; |
+ { |
+ OSError os_error_struct(status, error_string, OSError::kBoringSSL); |
+ Dart_Handle os_error = DartUtils::NewDartOSError(&os_error_struct); |
+ exception = |
+ DartUtils::NewDartIOException(exception_type, message, os_error); |
+ ASSERT(!Dart_IsError(exception)); |
+ } |
Dart_ThrowException(exception); |
UNREACHABLE(); |
} |
@@ -143,8 +146,8 @@ static Dart_Handle SetFilter(Dart_NativeArguments args, SSLFilter* filter) { |
} |
-static SSL_CTX* GetSecurityContext(Dart_NativeArguments args) { |
- SSL_CTX* context; |
+static SSLContext* GetSecurityContext(Dart_NativeArguments args) { |
+ SSLContext* context; |
Dart_Handle dart_this = ThrowIfError(Dart_GetNativeArgument(args, 0)); |
ASSERT(Dart_IsInstance(dart_this)); |
ThrowIfError(Dart_GetNativeInstanceField( |
@@ -155,17 +158,17 @@ static SSL_CTX* GetSecurityContext(Dart_NativeArguments args) { |
} |
-static void FreeSecurityContext( |
+static void DeleteSecurityContext( |
void* isolate_data, |
Dart_WeakPersistentHandle handle, |
void* context_pointer) { |
- SSL_CTX* context = static_cast<SSL_CTX*>(context_pointer); |
- SSL_CTX_free(context); |
+ SSLContext* context = static_cast<SSLContext*>(context_pointer); |
+ delete context; |
} |
static Dart_Handle SetSecurityContext(Dart_NativeArguments args, |
- SSL_CTX* context) { |
+ SSLContext* context) { |
const int approximate_size_of_context = 1500; |
Dart_Handle dart_this = Dart_GetNativeArgument(args, 0); |
RETURN_IF_ERROR(dart_this); |
@@ -178,7 +181,7 @@ static Dart_Handle SetSecurityContext(Dart_NativeArguments args, |
Dart_NewWeakPersistentHandle(dart_this, |
context, |
approximate_size_of_context, |
- FreeSecurityContext); |
+ DeleteSecurityContext); |
return Dart_Null(); |
} |
@@ -198,7 +201,7 @@ static X509* GetX509Certificate(Dart_NativeArguments args) { |
// Forward declaration. |
static void SetAlpnProtocolList(Dart_Handle protocols_handle, |
SSL* ssl, |
- SSL_CTX* context, |
+ SSLContext* context, |
bool is_server); |
@@ -235,7 +238,7 @@ void FUNCTION_NAME(SecureSocket_Connect)(Dart_NativeArguments args) { |
// TODO(whesse): Is truncating a Dart string containing \0 what we want? |
ThrowIfError(Dart_StringToCString(host_name_object, &host_name)); |
- SSL_CTX* context = NULL; |
+ SSLContext* context = NULL; |
if (!Dart_IsNull(context_object)) { |
ThrowIfError(Dart_GetNativeInstanceField( |
context_object, |
@@ -248,7 +251,7 @@ void FUNCTION_NAME(SecureSocket_Connect)(Dart_NativeArguments args) { |
ASSERT(!Dart_IsNull(protocols_handle)); |
GetFilter(args)->Connect(host_name, |
- context, |
+ context->context(), |
is_server, |
request_client_certificate, |
require_client_certificate, |
@@ -426,14 +429,15 @@ int CertificateCallback(int preverify_ok, X509_STORE_CTX* store_ctx) { |
void FUNCTION_NAME(SecurityContext_Allocate)(Dart_NativeArguments args) { |
SSLFilter::InitializeLibrary(); |
- SSL_CTX* context = SSL_CTX_new(TLS_method()); |
- SSL_CTX_set_verify(context, SSL_VERIFY_PEER, CertificateCallback); |
- SSL_CTX_set_min_version(context, TLS1_VERSION); |
- SSL_CTX_set_cipher_list(context, "HIGH:MEDIUM"); |
- SSL_CTX_set_cipher_list_tls11(context, "HIGH:MEDIUM"); |
+ SSL_CTX* ctx = SSL_CTX_new(TLS_method()); |
+ SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER, CertificateCallback); |
+ SSL_CTX_set_min_version(ctx, TLS1_VERSION); |
+ SSL_CTX_set_cipher_list(ctx, "HIGH:MEDIUM"); |
+ SSL_CTX_set_cipher_list_tls11(ctx, "HIGH:MEDIUM"); |
+ SSLContext* context = new SSLContext(ctx); |
Dart_Handle err = SetSecurityContext(args, context); |
if (Dart_IsError(err)) { |
- SSL_CTX_free(context); |
+ delete context; |
Dart_PropagateError(err); |
} |
} |
@@ -663,14 +667,17 @@ static const char* GetPasswordArgument(Dart_NativeArguments args, |
void FUNCTION_NAME(SecurityContext_UsePrivateKeyBytes)( |
Dart_NativeArguments args) { |
- SSL_CTX* context = GetSecurityContext(args); |
+ SSLContext* context = GetSecurityContext(args); |
const char* password = GetPasswordArgument(args, 2); |
int status; |
{ |
ScopedMemBIO bio(ThrowIfError(Dart_GetNativeArgument(args, 1))); |
EVP_PKEY *key = GetPrivateKey(bio.bio(), password); |
- status = SSL_CTX_use_PrivateKey(context, key); |
+ status = SSL_CTX_use_PrivateKey(context->context(), key); |
+ // SSL_CTX_use_PrivateKey increments the reference count of key on success, |
+ // so we have to call EVP_PKEY_free on both success and failure. |
+ EVP_PKEY_free(key); |
} |
// TODO(24184): Handle different expected errors here - file missing, |
@@ -699,16 +706,18 @@ static int SetTrustedCertificatesBytesPKCS12(SSL_CTX* context, |
ScopedX509Stack cert_stack(ca_certs); |
X509_STORE* store = SSL_CTX_get_cert_store(context); |
status = X509_STORE_add_cert(store, cert); |
+ // X509_STORE_add_cert increments the reference count of cert on success. |
+ X509_free(cert); |
if (status == 0) { |
- X509_free(cert); |
return status; |
} |
X509* ca; |
while ((ca = sk_X509_shift(cert_stack.get())) != NULL) { |
status = X509_STORE_add_cert(store, ca); |
+ // X509_STORE_add_cert increments the reference count of cert on success. |
+ X509_free(ca); |
if (status == 0) { |
- X509_free(ca); |
return status; |
} |
} |
@@ -724,8 +733,9 @@ static int SetTrustedCertificatesBytesPEM(SSL_CTX* context, BIO* bio) { |
X509* cert = NULL; |
while ((cert = PEM_read_bio_X509(bio, NULL, NULL, NULL)) != NULL) { |
status = X509_STORE_add_cert(store, cert); |
+ // X509_STORE_add_cert increments the reference count of cert on success. |
+ X509_free(cert); |
if (status == 0) { |
- X509_free(cert); |
return status; |
} |
} |
@@ -759,12 +769,13 @@ static int SetTrustedCertificatesBytes(SSL_CTX* context, |
void FUNCTION_NAME(SecurityContext_SetTrustedCertificatesBytes)( |
Dart_NativeArguments args) { |
- SSL_CTX* context = GetSecurityContext(args); |
+ SSLContext* context = GetSecurityContext(args); |
const char* password = GetPasswordArgument(args, 2); |
int status; |
{ |
ScopedMemBIO bio(ThrowIfError(Dart_GetNativeArgument(args, 1))); |
- status = SetTrustedCertificatesBytes(context, bio.bio(), password); |
+ status = SetTrustedCertificatesBytes( |
+ context->context(), bio.bio(), password); |
} |
CheckStatus(status, |
"TlsException", |
@@ -779,7 +790,7 @@ void FUNCTION_NAME(SecurityContext_AlpnSupported)(Dart_NativeArguments args) { |
void FUNCTION_NAME(SecurityContext_TrustBuiltinRoots)( |
Dart_NativeArguments args) { |
- SSL_CTX* context = GetSecurityContext(args); |
+ SSLContext* context = GetSecurityContext(args); |
#if defined(TARGET_OS_ANDROID) |
// On Android, we don't compile in the trusted root certificates. Insead, |
// we use the directory of trusted certificates already present on the device. |
@@ -789,10 +800,11 @@ void FUNCTION_NAME(SecurityContext_TrustBuiltinRoots)( |
// the Dart thread so that Dart code can be invoked from the "bad certificate" |
// callback called by SSL_do_handshake. |
const char* android_cacerts = "/system/etc/security/cacerts"; |
- int status = SSL_CTX_load_verify_locations(context, NULL, android_cacerts); |
+ int status = SSL_CTX_load_verify_locations( |
+ context->context(), NULL, android_cacerts); |
CheckStatus(status, "TlsException", "Failure trusting builtint roots"); |
#else |
- X509_STORE* store = SSL_CTX_get_cert_store(context); |
+ X509_STORE* store = SSL_CTX_get_cert_store(context->context()); |
BIO* roots_bio = |
BIO_new_mem_buf(const_cast<unsigned char*>(root_certificates_pem), |
root_certificates_pem_length); |
@@ -801,7 +813,12 @@ void FUNCTION_NAME(SecurityContext_TrustBuiltinRoots)( |
// backed by a memory buffer), and returns X509 objects, one by one. |
// When the end of the bio is reached, it returns null. |
while ((root_cert = PEM_read_bio_X509(roots_bio, NULL, NULL, NULL)) != NULL) { |
- X509_STORE_add_cert(store, root_cert); |
+ int status = X509_STORE_add_cert(store, root_cert); |
+ // X509_STORE_add_cert increments the reference count of cert on success. |
+ X509_free(root_cert); |
+ if (status == 0) { |
+ break; |
+ } |
} |
BIO_free(roots_bio); |
// If there is an error here, it must be the error indicating that we are done |
@@ -844,6 +861,8 @@ static int UseChainBytesPKCS12(SSL_CTX* context, |
X509* ca; |
while ((ca = sk_X509_shift(certs.get())) != NULL) { |
status = SSL_CTX_add0_chain_cert(context, ca); |
+ // SSL_CTX_add0_chain_cert does not inc ref count, so don't free unless the |
+ // call fails. |
if (status == 0) { |
X509_free(ca); |
return status; |
@@ -875,6 +894,8 @@ static int UseChainBytesPEM(SSL_CTX* context, BIO* bio) { |
X509* ca; |
while ((ca = PEM_read_bio_X509(bio, NULL, NULL, NULL)) != NULL) { |
status = SSL_CTX_add0_chain_cert(context, ca); |
+ // SSL_CTX_add0_chain_cert does not inc ref count, so don't free unless the |
+ // call fails. |
if (status == 0) { |
X509_free(ca); |
return status; |
@@ -906,12 +927,12 @@ static int UseChainBytes(SSL_CTX* context, BIO* bio, const char* password) { |
void FUNCTION_NAME(SecurityContext_UseCertificateChainBytes)( |
Dart_NativeArguments args) { |
- SSL_CTX* context = GetSecurityContext(args); |
+ SSLContext* context = GetSecurityContext(args); |
const char* password = GetPasswordArgument(args, 2); |
int status; |
{ |
ScopedMemBIO bio(ThrowIfError(Dart_GetNativeArgument(args, 1))); |
- status = UseChainBytes(context, bio.bio(), password); |
+ status = UseChainBytes(context->context(), bio.bio(), password); |
} |
CheckStatus(status, |
"TlsException", |
@@ -937,14 +958,16 @@ static int SetClientAuthoritiesPKCS12(SSL_CTX* context, |
ScopedX509Stack cert_stack(ca_certs); |
status = SSL_CTX_add_client_CA(context, cert); |
+ // SSL_CTX_add_client_CA increments the reference count of cert on success. |
+ X509_free(cert); |
if (status == 0) { |
- X509_free(cert); |
return status; |
} |
X509* ca; |
while ((ca = sk_X509_shift(cert_stack.get())) != NULL) { |
status = SSL_CTX_add_client_CA(context, ca); |
+ // SSL_CTX_add_client_CA increments the reference count of ca on success. |
X509_free(ca); // The name has been extracted. |
if (status == 0) { |
return status; |
@@ -989,13 +1012,13 @@ static int SetClientAuthorities(SSL_CTX* context, |
void FUNCTION_NAME(SecurityContext_SetClientAuthoritiesBytes)( |
Dart_NativeArguments args) { |
- SSL_CTX* context = GetSecurityContext(args); |
+ SSLContext* context = GetSecurityContext(args); |
const char* password = GetPasswordArgument(args, 2); |
int status; |
{ |
ScopedMemBIO bio(ThrowIfError(Dart_GetNativeArgument(args, 1))); |
- status = SetClientAuthorities(context, bio.bio(), password); |
+ status = SetClientAuthorities(context->context(), bio.bio(), password); |
} |
CheckStatus(status, |
@@ -1006,7 +1029,7 @@ void FUNCTION_NAME(SecurityContext_SetClientAuthoritiesBytes)( |
void FUNCTION_NAME(SecurityContext_SetAlpnProtocols)( |
Dart_NativeArguments args) { |
- SSL_CTX* context = GetSecurityContext(args); |
+ SSLContext* context = GetSecurityContext(args); |
Dart_Handle protocols_handle = |
ThrowIfError(Dart_GetNativeArgument(args, 1)); |
Dart_Handle is_server_handle = |
@@ -1363,7 +1386,7 @@ int AlpnCallback(SSL *ssl, |
// Sets the protocol list for ALPN on a SSL object or a context. |
static void SetAlpnProtocolList(Dart_Handle protocols_handle, |
SSL* ssl, |
- SSL_CTX* context, |
+ SSLContext* context, |
bool is_server) { |
// Enable ALPN (application layer protocol negotiation) if the caller provides |
// a valid list of supported protocols. |
@@ -1400,13 +1423,9 @@ static void SetAlpnProtocolList(Dart_Handle protocols_handle, |
static_cast<uint8_t*>(malloc(protocol_string_len + 1)); |
memmove(protocol_string_copy, protocol_string, protocol_string_len); |
protocol_string_copy[protocol_string_len] = '\0'; |
- SSL_CTX_set_alpn_select_cb(context, AlpnCallback, protocol_string_copy); |
- // TODO(whesse): If this function is called again, free the previous |
- // protocol_string_copy. It may be better to keep this as a native |
- // field on the Dart object, since fetching it from the structure is |
- // not in the public api. |
- // Also free protocol_string_copy when the context is destroyed, |
- // in FreeSecurityContext() |
+ SSL_CTX_set_alpn_select_cb( |
+ context->context(), AlpnCallback, protocol_string_copy); |
+ context->set_alpn_protocol_string(protocol_string_copy); |
} else { |
// The function makes a local copy of protocol_string, which it owns. |
if (ssl != NULL) { |
@@ -1416,7 +1435,7 @@ static void SetAlpnProtocolList(Dart_Handle protocols_handle, |
ASSERT(context != NULL); |
ASSERT(ssl == NULL); |
status = SSL_CTX_set_alpn_protos( |
- context, protocol_string, protocol_string_len); |
+ context->context(), protocol_string, protocol_string_len); |
} |
ASSERT(status == 0); // The function returns a non-standard status. |
} |