Index: src/libmongoc/src/mongoc/mongoc-secure-transport.c IDEA additional info: Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP <+>UTF-8 =================================================================== --- src/libmongoc/src/mongoc/mongoc-secure-transport.c (date 1538553930000) +++ src/libmongoc/src/mongoc/mongoc-secure-transport.c (date 1538733058000) @@ -201,6 +201,16 @@ return bson_string_free (retval, false); } + +static void +safe_release (CFTypeRef ref) +{ + if (ref) { + CFRelease (ref); + } +} + + bool _mongoc_secure_transport_import_pem (const char *filename, const char *passphrase, @@ -208,14 +218,14 @@ SecExternalItemType *type) { SecExternalFormat format = kSecFormatPEMSequence; - SecItemImportExportKeyParameters params; - SecTransformRef sec_transform; - CFReadStreamRef read_stream; - CFDataRef dataref; - CFErrorRef error; - CFURLRef url; + SecItemImportExportKeyParameters params = {0}; + SecTransformRef sec_transform = NULL; + CFReadStreamRef read_stream = NULL; + CFDataRef dataref = NULL; + CFErrorRef error = NULL; + CFURLRef url = NULL; OSStatus res; - + bool r = false; if (!filename) { TRACE ("%s", "No certificate provided"); @@ -239,43 +249,46 @@ url = CFURLCreateFromFileSystemRepresentation ( kCFAllocatorDefault, (const UInt8 *) filename, strlen (filename), false); read_stream = CFReadStreamCreateWithFile (kCFAllocatorDefault, url); + if (!CFReadStreamOpen (read_stream)) { + MONGOC_ERROR ("Cannot find certificate in '%s', error reading file", + filename); + goto done; + } + sec_transform = SecTransformCreateReadTransformWithReadStream (read_stream); dataref = SecTransformExecute (sec_transform, &error); - if (error) { CFStringRef str = CFErrorCopyDescription (error); MONGOC_ERROR ( "Failed importing PEM '%s': %s", filename, CFStringGetCStringPtr (str, CFStringGetFastestEncoding (str))); - CFRelease (str); - CFRelease (sec_transform); - CFRelease (read_stream); - CFRelease (url); - if (passphrase) { - CFRelease (params.passphrase); - } - return false; + goto done; } res = SecItemImport ( dataref, CFSTR (".pem"), &format, type, 0, ¶ms, NULL, items); - CFRelease (dataref); - CFRelease (sec_transform); - CFRelease (read_stream); - CFRelease (url); + + if (res) { + MONGOC_ERROR ("Failed importing PEM '%s' (code: %d)", filename, res); + goto done; + } + + r = true; + +done: + safe_release (dataref); + safe_release (sec_transform); + safe_release (read_stream); + safe_release (url); if (passphrase) { CFRelease (params.passphrase); } - if (res) { - MONGOC_ERROR ("Failed importing PEM '%s' (code: %d)", filename, res); - return false; - } - return true; + return r; } char * @@ -338,7 +351,7 @@ success = _mongoc_secure_transport_import_pem ( opt->pem_file, opt->pem_pwd, &items, &type); if (!success) { - MONGOC_ERROR ("Can't find certificate in: '%s'", opt->pem_file); + /* caller will log an error */ return false; } @@ -399,7 +412,8 @@ opt->ca_file, NULL, &items, &type); if (!success) { - MONGOC_ERROR ("Can't find certificate in \"%s\"", opt->ca_file); + MONGOC_ERROR ("Cannot load Certificate Authorities from file \'%s\'", + opt->ca_file); return false; } Index: src/libmongoc/src/mongoc/mongoc-stream-tls-secure-transport.c IDEA additional info: Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP <+>UTF-8 =================================================================== --- src/libmongoc/src/mongoc/mongoc-stream-tls-secure-transport.c (date 1538553930000) +++ src/libmongoc/src/mongoc/mongoc-stream-tls-secure-transport.c (date 1538733058000) @@ -473,15 +473,14 @@ if (opt->ca_dir) { MONGOC_ERROR ("Setting mongoc_ssl_opt_t.ca_dir has no effect when built " "against Secure Transport"); - RETURN (false); + RETURN (NULL); } if (opt->crl_file) { MONGOC_ERROR ( "Setting mongoc_ssl_opt_t.crl_file has no effect when built " "against Secure Transport"); - RETURN (false); + RETURN (NULL); } - secure_transport = (mongoc_stream_tls_secure_transport_t *) bson_malloc0 ( sizeof *secure_transport); @@ -503,7 +502,6 @@ tls->handshake = mongoc_stream_tls_secure_transport_handshake; tls->ctx = (void *) secure_transport; tls->timeout_msec = -1; - tls->base_stream = base_stream; secure_transport->ssl_ctx_ref = SSLCreateContext (kCFAllocatorDefault, @@ -515,8 +513,20 @@ mongoc_secure_transport_write); SSLSetProtocolVersionMin (secure_transport->ssl_ctx_ref, kTLSProtocol1); - mongoc_secure_transport_setup_certificate (secure_transport, opt); - mongoc_secure_transport_setup_ca (secure_transport, opt); + if (opt->pem_file && + !mongoc_secure_transport_setup_certificate (secure_transport, opt)) { + mongoc_stream_destroy ((mongoc_stream_t *) tls); + RETURN (NULL); + } + + if (opt->ca_file && + !mongoc_secure_transport_setup_ca (secure_transport, opt)) { + mongoc_stream_destroy ((mongoc_stream_t *) tls); + RETURN (NULL); + } + + /* don't link base_stream to tls until we're sure we won't destroy tls */ + tls->base_stream = base_stream; if (client) { SSLSetSessionOption (secure_transport->ssl_ctx_ref, Index: src/libmongoc/tests/test-mongoc-stream-tls-error.c IDEA additional info: Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP <+>UTF-8 =================================================================== --- src/libmongoc/tests/test-mongoc-stream-tls-error.c (date 1538553930000) +++ src/libmongoc/tests/test-mongoc-stream-tls-error.c (date 1538733058000) @@ -10,6 +10,7 @@ #include "ssl-test.h" #include "test-conveniences.h" #include "TestSuite.h" +#include "test-libmongoc.h" #define TIMEOUT 10000 /* milliseconds */ @@ -350,6 +351,37 @@ #endif /* !MONGOC_ENABLE_SSL_SECURE_TRANSPORT */ #endif /* !MONGOC_ENABLE_SSL_SECURE_CHANNEL && !MONGOC_ENABLE_SSL_LIBRESSL */ +static void +test_mongoc_tls_load_files (void) +{ + mongoc_ssl_opt_t opt = {0}; + mongoc_stream_t *base; + mongoc_stream_t *tls_stream = NULL; + + opt.pem_file = "badfile"; + + capture_logs (true); + base = + mongoc_stream_socket_new (mongoc_socket_new (AF_INET, SOCK_STREAM, 0)); + tls_stream = mongoc_stream_tls_new_with_hostname (base, NULL, &opt, 0); + /* Across TLS libraries, error messages differ and TLS stream might be NULL + * or not. Until CDRIVER-2844, just assert message includes the filename. */ + ASSERT_CAPTURED_LOG ( + "bad TLS config file", MONGOC_LOG_LEVEL_ERROR, "'badfile'"); + + /* TLS stream should be NULL and base stream should still be valid - until + * that's fixed for all TLS integrations, handle either case. */ + if (tls_stream) { + mongoc_stream_destroy (tls_stream); + } else { + mongoc_stream_destroy (base); + } +} + + +#undef TLS_LOAD_ERR + + void test_stream_tls_error_install (TestSuite *suite) { @@ -365,4 +397,5 @@ suite, "/TLS/handshake_stall", test_mongoc_tls_handshake_stall); #endif #endif /* !MONGOC_ENABLE_SSL_SECURE_CHANNEL && !MONGOC_ENABLE_SSL_LIBRESSL */ + TestSuite_Add (suite, "/TLS/load_files", test_mongoc_tls_load_files); }