Hello community, here is the log from the commit of package mariadb-connector-c for openSUSE:Factory checked in at 2020-02-15 22:23:12 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/mariadb-connector-c (Old) and /work/SRC/openSUSE:Factory/.mariadb-connector-c.new.26092 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "mariadb-connector-c" Sat Feb 15 22:23:12 2020 rev:23 rq:770773 version:3.1.7 Changes: -------- --- /work/SRC/openSUSE:Factory/mariadb-connector-c/mariadb-connector-c.changes 2020-01-01 14:57:07.905894537 +0100 +++ /work/SRC/openSUSE:Factory/.mariadb-connector-c.new.26092/mariadb-connector-c.changes 2020-02-15 22:23:13.907238728 +0100 @@ -1,0 +2,8 @@ +Thu Feb 6 20:30:28 UTC 2020 - Kristyna Streitova <kstreit...@suse.com> + +- Update to release 3.1.7 + * TLS/SSL: when the client doesn't procide a CA file and the + option ssl_verify_server_cert was set, the peer cerificate + will be validated against the system CA. + +------------------------------------------------------------------- Old: ---- mariadb-connector-c-3.1.6-src.tar.gz mariadb-connector-c-3.1.6-src.tar.gz.asc New: ---- mariadb-connector-c-3.1.7-src.tar.gz mariadb-connector-c-3.1.7-src.tar.gz.asc ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ mariadb-connector-c.spec ++++++ --- /var/tmp/diff_new_pack.HcwFXN/_old 2020-02-15 22:23:14.387238987 +0100 +++ /var/tmp/diff_new_pack.HcwFXN/_new 2020-02-15 22:23:14.387238987 +0100 @@ -1,7 +1,7 @@ # # spec file for package mariadb-connector-c # -# Copyright (c) 2019 SUSE LLC +# Copyright (c) 2020 SUSE LLC # # All modifications and additions to the file contributed by third parties # remain the property of their copyright owners, unless otherwise agreed @@ -25,7 +25,7 @@ %endif %bcond_with sqlite3 Name: mariadb-connector-c -Version: 3.1.6 +Version: 3.1.7 Release: 0 Summary: MariaDB connector in C License: LGPL-2.1-or-later ++++++ mariadb-connector-c-3.1.6-src.tar.gz -> mariadb-connector-c-3.1.7-src.tar.gz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/mariadb-connector-c-3.1.6-src/CMakeLists.txt new/mariadb-connector-c-3.1.7-src/CMakeLists.txt --- old/mariadb-connector-c-3.1.6-src/CMakeLists.txt 2019-12-08 18:07:48.000000000 +0100 +++ new/mariadb-connector-c-3.1.7-src/CMakeLists.txt 2020-01-22 11:08:18.000000000 +0100 @@ -36,7 +36,7 @@ SET(CPACK_PACKAGE_VERSION_MAJOR 3) SET(CPACK_PACKAGE_VERSION_MINOR 1) -SET(CPACK_PACKAGE_VERSION_PATCH 6) +SET(CPACK_PACKAGE_VERSION_PATCH 7) SET(CPACK_PACKAGE_VERSION "${CPACK_PACKAGE_VERSION_MAJOR}.${CPACK_PACKAGE_VERSION_MINOR}.${CPACK_PACKAGE_VERSION_PATCH}") MATH(EXPR MARIADB_PACKAGE_VERSION_ID "${CPACK_PACKAGE_VERSION_MAJOR} * 10000 + ${CPACK_PACKAGE_VERSION_MINOR} * 100 + @@ -107,6 +107,7 @@ IF(MSVC) # Speedup system tests INCLUDE(${CC_SOURCE_DIR}/cmake/WindowsCache.cmake) + ADD_DEFINITIONS(-DWIN32_LEAN_AND_MEAN) IF (MSVC) SET(CONFIG_TYPES "DEBUG" "RELEASE" "RELWITHDEBINFO") FOREACH(BUILD_TYPE ${CONFIG_TYPES}) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/mariadb-connector-c-3.1.6-src/include/ma_priv.h new/mariadb-connector-c-3.1.7-src/include/ma_priv.h --- old/mariadb-connector-c-3.1.6-src/include/ma_priv.h 1970-01-01 01:00:00.000000000 +0100 +++ new/mariadb-connector-c-3.1.7-src/include/ma_priv.h 2020-01-22 11:08:18.000000000 +0100 @@ -0,0 +1,31 @@ +/**************************************************************************** + Copyright (C) 2020 MariaDB Corporation + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not see <http://www.gnu.org/licenses> + or write to the Free Software Foundation, Inc., + 51 Franklin St., Fifth Floor, Boston, MA 02110, USA + + Part of this code includes code from the PHP project which + is freely available from http://www.php.net + *****************************************************************************/ +#ifndef MA_PRIV_H +#define MA_PRIV_H + +void free_rows(MYSQL_DATA *cur); +int ma_multi_command(MYSQL *mysql, enum enum_multi_status status); +MYSQL_FIELD * unpack_fields(MYSQL_DATA *data, + MA_MEM_ROOT *alloc,uint fields, + my_bool default_value); + +#endif diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/mariadb-connector-c-3.1.6-src/libmariadb/ma_pvio.c new/mariadb-connector-c-3.1.7-src/libmariadb/ma_pvio.c --- old/mariadb-connector-c-3.1.6-src/libmariadb/ma_pvio.c 2019-12-08 18:07:48.000000000 +0100 +++ new/mariadb-connector-c-3.1.7-src/libmariadb/ma_pvio.c 2020-01-22 11:08:18.000000000 +0100 @@ -540,8 +540,7 @@ 2. verify CN (requires option ssl_verify_check) 3. verrify finger print */ - if ((pvio->mysql->options.ssl_ca || pvio->mysql->options.ssl_capath) && - (pvio->mysql->client_flag & CLIENT_SSL_VERIFY_SERVER_CERT) && + if ((pvio->mysql->client_flag & CLIENT_SSL_VERIFY_SERVER_CERT) && ma_pvio_tls_verify_server_cert(pvio->ctls)) return 1; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/mariadb-connector-c-3.1.6-src/libmariadb/mariadb_lib.c new/mariadb-connector-c-3.1.7-src/libmariadb/mariadb_lib.c --- old/mariadb-connector-c-3.1.6-src/libmariadb/mariadb_lib.c 2019-12-08 18:07:48.000000000 +0100 +++ new/mariadb-connector-c-3.1.7-src/libmariadb/mariadb_lib.c 2020-01-22 11:08:18.000000000 +0100 @@ -27,6 +27,7 @@ #include <ma_string.h> #include <mariadb_ctype.h> #include <ma_common.h> +#include "ma_priv.h" #include "ma_context.h" #include "mysql.h" #include "mariadb_version.h" @@ -771,7 +772,7 @@ MYSQL_FIELD * unpack_fields(MYSQL_DATA *data,MA_MEM_ROOT *alloc,uint fields, - my_bool default_value, my_bool long_flag_protocol __attribute__((unused))) + my_bool default_value) { MYSQL_ROWS *row; MYSQL_FIELD *field,*result; @@ -1514,7 +1515,10 @@ scramble_len= pkt_scramble_len; scramble_plugin= scramble_data + scramble_len; if (scramble_data + scramble_len > end_pkt) - scramble_len= (uint)(end_pkt - scramble_data); + { + SET_CLIENT_ERROR(mysql, CR_MALFORMED_PACKET, SQLSTATE_UNKNOWN, 0); + goto error; + } } else { scramble_len= (uint)(end_pkt - scramble_data); @@ -2192,9 +2196,7 @@ if (!(fields=mysql->methods->db_read_rows(mysql,(MYSQL_FIELD*) 0,8))) return(-1); if (!(mysql->fields=unpack_fields(fields,&mysql->field_alloc, - (uint) field_count,1, - (my_bool) test(mysql->server_capabilities & - CLIENT_LONG_FLAG)))) + (uint) field_count, 1))) return(-1); mysql->status=MYSQL_STATUS_GET_RESULT; mysql->field_count=field_count; @@ -2525,9 +2527,7 @@ result->eof=1; result->field_count = (uint) query->rows; result->fields= unpack_fields(query,&result->field_alloc, - result->field_count,1, - (my_bool) test(mysql->server_capabilities & - CLIENT_LONG_FLAG)); + result->field_count, 1); if (result->fields) return(result); @@ -2552,9 +2552,8 @@ field_count=(uint) net_field_length(&pos); if (!(fields = mysql->methods->db_read_rows(mysql,(MYSQL_FIELD*) 0,5))) return(NULL); - if (!(mysql->fields=unpack_fields(fields,&mysql->field_alloc,field_count,0, - (my_bool) test(mysql->server_capabilities & - CLIENT_LONG_FLAG)))) + if (!(mysql->fields=unpack_fields(fields, &mysql->field_alloc, + field_count, 0))) return(NULL); mysql->status=MYSQL_STATUS_GET_RESULT; mysql->field_count=field_count; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/mariadb-connector-c-3.1.6-src/libmariadb/mariadb_stmt.c new/mariadb-connector-c-3.1.7-src/libmariadb/mariadb_stmt.c --- old/mariadb-connector-c-3.1.6-src/libmariadb/mariadb_stmt.c 2019-12-08 18:07:48.000000000 +0100 +++ new/mariadb-connector-c-3.1.7-src/libmariadb/mariadb_stmt.c 2020-01-22 11:08:18.000000000 +0100 @@ -55,6 +55,8 @@ #include <time.h> #include <mysql/client_plugin.h> #include <ma_common.h> +#include "ma_priv.h" + #define UPDATE_STMT_ERROR(stmt)\ SET_CLIENT_STMT_ERROR((stmt), (stmt)->mysql->net.last_errno, (stmt)->mysql->net.sqlstate, (stmt)->mysql->net.last_error) @@ -75,10 +77,6 @@ MA_MEM_ROOT fields_ma_alloc_root; } MADB_STMT_EXTENSION; -MYSQL_DATA *read_rows(MYSQL *mysql,MYSQL_FIELD *mysql_fields, uint fields); -void free_rows(MYSQL_DATA *cur); -int ma_multi_command(MYSQL *mysql, enum enum_multi_status status); -MYSQL_FIELD * unpack_fields(MYSQL_DATA *data,MA_MEM_ROOT *alloc,uint fields, my_bool default_value, my_bool long_flag_protocol); static my_bool net_stmt_close(MYSQL_STMT *stmt, my_bool remove); static my_bool is_not_null= 0; @@ -1598,8 +1596,7 @@ if (!(result= stmt->mysql->methods->db_read_rows(stmt->mysql, (MYSQL_FIELD *)0, 7))) return(1); if (!(stmt->fields= unpack_fields(result,fields_ma_alloc_root, - stmt->field_count, 0, - stmt->mysql->server_capabilities & CLIENT_LONG_FLAG))) + stmt->field_count, 0))) return(1); return(0); } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/mariadb-connector-c-3.1.6-src/libmariadb/secure/gnutls.c new/mariadb-connector-c-3.1.7-src/libmariadb/secure/gnutls.c --- old/mariadb-connector-c-3.1.6-src/libmariadb/secure/gnutls.c 2019-12-08 18:07:48.000000000 +0100 +++ new/mariadb-connector-c-3.1.7-src/libmariadb/secure/gnutls.c 2020-01-22 11:08:18.000000000 +0100 @@ -1080,6 +1080,23 @@ if (ssl_error < 0) goto error; } + + if (mysql->options.ssl_capath) + { + ssl_error= gnutls_certificate_set_x509_trust_dir(ctx, + mysql->options.ssl_capath, + GNUTLS_X509_FMT_PEM); + if (ssl_error < 0) + goto error; + } + + if (!mysql->options.ssl_ca && !mysql->options.ssl_capath) + { + ssl_error= gnutls_certificate_set_x509_system_trust(ctx); + if (ssl_error < 0) + goto error; + } + gnutls_certificate_set_verify_function(ctx, my_verify_callback); @@ -1211,7 +1228,11 @@ if (ret < 0) { - ma_tls_set_error(mysql, ssl, ret); + /* If error message was not set while calling certification callback function, + use default error message (which is not very descriptive */ + if (!mysql_errno(mysql)) + ma_tls_set_error(mysql, ssl, ret); + /* restore blocking mode */ gnutls_deinit((gnutls_session_t )ctls->ssl); free_gnutls_data(data); @@ -1330,7 +1351,7 @@ int ma_tls_verify_server_cert(MARIADB_TLS *ctls __attribute__((unused))) { - /* server verification is already handled before */ + /* server verification is already handled before during handshake */ return 0; } @@ -1352,77 +1373,44 @@ static int my_verify_callback(gnutls_session_t ssl) { unsigned int status= 0; - const gnutls_datum_t *cert_list; - unsigned int cert_list_size; struct st_gnutls_data *data= (struct st_gnutls_data *)gnutls_session_get_ptr(ssl); MYSQL *mysql; - MARIADB_PVIO *pvio; - - gnutls_x509_crt_t cert; - const char *hostname; mysql= data->mysql; - pvio= mysql->net.pvio; - /* read hostname */ - hostname = mysql->host; + CLEAR_CLIENT_ERROR(mysql); - /* This verification function uses the trusted CAs in the credentials - * structure. So you must have installed one or more CA certificates. - */ - if ((mysql->client_flag & CLIENT_SSL_VERIFY_SERVER_CERT) && - gnutls_certificate_verify_peers2 (ssl, &status) < 0) + if ((mysql->client_flag & CLIENT_SSL_VERIFY_SERVER_CERT)) { - pvio->set_error(mysql, CR_SSL_CONNECTION_ERROR, SQLSTATE_UNKNOWN, "CA verification failed"); - return GNUTLS_E_CERTIFICATE_ERROR; - } + const char *hostname= mysql->host; - if (status & GNUTLS_CERT_INVALID) - { - char errbuf[100]; - snprintf(errbuf, 99, "CA Verification failed (Status: %d)", status); - pvio->set_error(mysql, CR_SSL_CONNECTION_ERROR, SQLSTATE_UNKNOWN, errbuf); - return GNUTLS_E_CERTIFICATE_ERROR; - } - /* Up to here the process is the same for X.509 certificates and - * OpenPGP keys. From now on X.509 certificates are assumed. This can - * be easily extended to work with openpgp keys as well. - */ - if (gnutls_certificate_type_get (ssl) != GNUTLS_CRT_X509) - { - pvio->set_error(mysql, CR_SSL_CONNECTION_ERROR, SQLSTATE_UNKNOWN, "Expected X509 certificate"); - return GNUTLS_E_CERTIFICATE_ERROR; + if (gnutls_certificate_verify_peers3 (ssl, hostname, &status) < 0) + return GNUTLS_E_CERTIFICATE_ERROR; + } else { + if (gnutls_certificate_verify_peers2 (ssl, &status) < 0) + return GNUTLS_E_CERTIFICATE_ERROR; } - if (gnutls_x509_crt_init (&cert) < 0) - { - pvio->set_error(mysql, CR_SSL_CONNECTION_ERROR, SQLSTATE_UNKNOWN, "Error during certificate initialization"); - return GNUTLS_E_CERTIFICATE_ERROR; - } - cert_list = gnutls_certificate_get_peers (ssl, &cert_list_size); - if (cert_list == NULL) - { - gnutls_x509_crt_deinit (cert); - pvio->set_error(mysql, CR_SSL_CONNECTION_ERROR, SQLSTATE_UNKNOWN, "No certificate found"); - return GNUTLS_E_CERTIFICATE_ERROR; - } - if (gnutls_x509_crt_import (cert, &cert_list[0], GNUTLS_X509_FMT_DER) < 0) - { - gnutls_x509_crt_deinit (cert); - pvio->set_error(mysql, CR_SSL_CONNECTION_ERROR, SQLSTATE_UNKNOWN, "Unknown SSL error"); - return GNUTLS_E_CERTIFICATE_ERROR; - } - - if ((mysql->client_flag & CLIENT_SSL_VERIFY_SERVER_CERT) && - !gnutls_x509_crt_check_hostname (cert, hostname)) + if (status & GNUTLS_CERT_INVALID) { - gnutls_x509_crt_deinit (cert); - pvio->set_error(mysql, CR_SSL_CONNECTION_ERROR, SQLSTATE_UNKNOWN, "Hostname in certificate doesn't match"); + gnutls_datum_t out; + int type; + /* accept self signed certificates if we don't have to verify server cert */ + if (!(mysql->client_flag & CLIENT_SSL_VERIFY_SERVER_CERT) && + (status & GNUTLS_CERT_SIGNER_NOT_FOUND)) + return 0; + + /* gnutls default error mesage "certificate validation failed" isn't very + descriptive, so we provide more information about the error here */ + type= gnutls_certificate_type_get(ssl); + gnutls_certificate_verification_status_print(status, type, &out, 0); + my_set_error(mysql, CR_SSL_CONNECTION_ERROR, SQLSTATE_UNKNOWN, + ER(CR_SSL_CONNECTION_ERROR), out.data); + gnutls_free(out.data); + return GNUTLS_E_CERTIFICATE_ERROR; } - gnutls_x509_crt_deinit (cert); - /* notify gnutls to continue handshake normally */ + - CLEAR_CLIENT_ERROR(mysql); return 0; } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/mariadb-connector-c-3.1.6-src/libmariadb/secure/openssl.c new/mariadb-connector-c-3.1.7-src/libmariadb/secure/openssl.c --- old/mariadb-connector-c-3.1.6-src/libmariadb/secure/openssl.c 2019-12-08 18:07:48.000000000 +0100 +++ new/mariadb-connector-c-3.1.7-src/libmariadb/secure/openssl.c 2020-01-22 11:08:18.000000000 +0100 @@ -530,8 +530,7 @@ X509_STORE_set_flags(certstore, X509_V_FLAG_CRL_CHECK | X509_V_FLAG_CRL_CHECK_ALL); } } - SSL_CTX_set_verify(ctx, (mysql->options.ssl_ca || mysql->options.ssl_capath)? - SSL_VERIFY_PEER : SSL_VERIFY_NONE, NULL); + SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER, NULL); return 0; error: @@ -647,7 +646,8 @@ pvio->methods->blocking(pvio, FALSE, 0); return 1; } - if ((mysql->client_flag & CLIENT_SSL_VERIFY_SERVER_CERT)) + if ((mysql->client_flag & CLIENT_SSL_VERIFY_SERVER_CERT) || + (mysql->options.ssl_ca || mysql->options.ssl_capath)) { rc= SSL_get_verify_result(ssl); if (rc != X509_V_OK) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/mariadb-connector-c-3.1.6-src/libmariadb/secure/schannel.c new/mariadb-connector-c-3.1.7-src/libmariadb/secure/schannel.c --- old/mariadb-connector-c-3.1.6-src/libmariadb/secure/schannel.c 2019-12-08 18:07:48.000000000 +0100 +++ new/mariadb-connector-c-3.1.7-src/libmariadb/secure/schannel.c 2020-01-22 11:08:18.000000000 +0100 @@ -19,6 +19,7 @@ *************************************************************************************/ #include "ma_schannel.h" #include "schannel_certs.h" +#include <string.h> #pragma comment (lib, "crypt32.lib") #pragma comment (lib, "secur32.lib") @@ -201,7 +202,6 @@ MYSQL *mysql= ctls->pvio->mysql; char *certfile= mysql->options.ssl_cert, *keyfile= mysql->options.ssl_key; - SC_CTX *sctx= (SC_CTX *)ctls->ssl; MARIADB_PVIO *pvio= ctls->pvio; char errmsg[256]; @@ -295,7 +295,7 @@ size_t i; DWORD protocol = 0; int verify_certs; - CERT_CONTEXT* cert_context = NULL; + const CERT_CONTEXT* cert_context = NULL; if (!ctls) return 1; @@ -319,10 +319,10 @@ */ for (i = 0; i < sizeof(tls_version) / sizeof(tls_version[0]); i++) { - if (!stricmp(mysql->options.ssl_cipher, tls_version[i].tls_version)) + if (!_stricmp(mysql->options.ssl_cipher, tls_version[i].tls_version)) protocol |= tls_version[i].protocol; } - memset(AlgId, 0, MAX_ALG_ID * sizeof(ALG_ID)); + memset(AlgId, 0, sizeof(AlgId)); Cred.cSupportedAlgs = (DWORD)set_cipher(mysql->options.ssl_cipher, protocol, AlgId, MAX_ALG_ID); if (Cred.cSupportedAlgs) { diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/mariadb-connector-c-3.1.6-src/libmariadb/secure/schannel_certs.c new/mariadb-connector-c-3.1.7-src/libmariadb/secure/schannel_certs.c --- old/mariadb-connector-c-3.1.6-src/libmariadb/secure/schannel_certs.c 2019-12-08 18:07:48.000000000 +0100 +++ new/mariadb-connector-c-3.1.7-src/libmariadb/secure/schannel_certs.c 2020-01-22 11:08:18.000000000 +0100 @@ -62,6 +62,14 @@ assert(0); return ERROR_INTERNAL_ERROR; } + +#define FAIL(fmt,...) \ + {\ + status = get_last_error();\ + ma_format_win32_error(errmsg, errmsg_len, status, fmt, __VA_ARGS__);\ + goto cleanup;\ + } + /* Load file into memory. Add null terminator at the end, so it will be a valid C string. */ @@ -71,33 +79,31 @@ size_t file_bufsize = 0; size_t total_bytes_read = 0; char* file_buffer = NULL; + SECURITY_STATUS status = SEC_E_OK; HANDLE file_handle = CreateFile(file, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); if (file_handle == INVALID_HANDLE_VALUE) { - ma_format_win32_error(errmsg, errmsg_len, GetLastError(), "failed to open file '%s'", file); - goto cleanup; + FAIL("failed to open file '%s'", file); } if (!GetFileSizeEx(file_handle, &file_size)) { - ma_format_win32_error(errmsg, errmsg_len, get_last_error(), "GetFileSizeEx failed on '%s'", file); - goto cleanup; + FAIL("GetFileSizeEx failed on '%s'", file); } if (file_size.QuadPart > ULONG_MAX - 1) { - snprintf(errmsg, errmsg_len, "file '%s' too large", file); - goto cleanup; + SetLastError(SEC_E_INVALID_PARAMETER); + FAIL("file '%s' too large", file); } file_bufsize = (size_t)file_size.QuadPart; - file_buffer = (char*)malloc(file_bufsize + 1); + file_buffer = (char*)LocalAlloc(0,file_bufsize + 1); if (!file_buffer) { - snprintf(errmsg, errmsg_len, "malloc(%zu) failed, out of memory", file_bufsize + 1); - goto cleanup; + FAIL("LocalAlloc(0,%zu) failed", file_bufsize + 1); } while (total_bytes_read < file_bufsize) @@ -108,9 +114,7 @@ if (!ReadFile(file_handle, file_buffer + total_bytes_read, bytes_to_read, &bytes_read, NULL)) { - ma_format_win32_error(errmsg, errmsg_len, GetLastError(), - "ReadFile() failed to read file '%s'", file); - goto cleanup; + FAIL("ReadFile() failed to read file '%s'", file); } if (bytes_read == 0) { @@ -125,9 +129,18 @@ /* Null terminate the buffer */ file_buffer[file_bufsize] = '\0'; + cleanup: if (file_handle != INVALID_HANDLE_VALUE) + { CloseHandle(file_handle); + } + if (status) + { + /* Some error happened. */ + LocalFree(file_buffer); + file_buffer = NULL; + } return file_buffer; } @@ -214,7 +227,9 @@ { char* file_buffer = NULL; char* cur = NULL; - SECURITY_STATUS status = SEC_E_INTERNAL_ERROR; + SECURITY_STATUS status = SEC_E_OK; + CRL_CONTEXT* crl_context = NULL; + CERT_CONTEXT* cert_context = NULL; char* begin; char* end; @@ -231,14 +246,12 @@ if (!end) { - snprintf(errmsg, errmsg_len, "Invalid PEM file '%s'," - "missing end marker corresponding to begin marker '%s' at offset %zu", + SetLastError(SEC_E_INVALID_PARAMETER); + FAIL("Invalid PEM file '%s', missing end marker corresponding to begin marker '%s' at offset %zu", file, pem_sections[type].begin_tag, (size_t)(begin - file_buffer)); - goto cleanup; } CERT_BLOB cert_blob; void* context = NULL; - int add_cert_result = FALSE; DWORD actual_content_type = 0; cert_blob.pbData = (BYTE*)begin; @@ -249,58 +262,44 @@ CERT_QUERY_FORMAT_FLAG_ALL, 0, NULL, &actual_content_type, NULL, NULL, NULL, (const void**)&context)) { - ma_format_win32_error(errmsg, errmsg_len, GetLastError(), - "failed to extract certificate from PEM file '%s'", - file); - goto cleanup; + FAIL("failed to extract certificate from PEM file '%s'",file); } if (!context) { - ma_format_win32_error(errmsg, errmsg_len, 0, - "unexpected result from CryptQueryObject(),cert_context is NULL" + SetLastError(SEC_E_INTERNAL_ERROR); + FAIL("unexpected result from CryptQueryObject(),cert_context is NULL" " after successful completion, file '%s'", file); - goto cleanup; } if (actual_content_type == CERT_QUERY_CONTENT_CERT) { CERT_CONTEXT* cert_context = (CERT_CONTEXT*)context; - BOOL ok = CertAddCertificateContextToStore( + if (!CertAddCertificateContextToStore( trust_store, cert_context, - CERT_STORE_ADD_ALWAYS, NULL); - if (!ok) - status = get_last_error(); - CertFreeCertificateContext(cert_context); - if (!ok) + CERT_STORE_ADD_ALWAYS, NULL)) { - status = get_last_error(); - ma_format_win32_error(errmsg, errmsg_len, get_last_error(), - "CertAddCertificateContextToStore failed"); - goto cleanup; + FAIL("CertAddCertificateContextToStore failed"); } } else if (actual_content_type == CERT_QUERY_CONTENT_CRL) { CRL_CONTEXT* crl_context = (CRL_CONTEXT*)context; - BOOL ok = CertAddCRLContextToStore( + if (!CertAddCRLContextToStore( trust_store, crl_context, - CERT_STORE_ADD_ALWAYS, NULL); - if (!ok) - status = get_last_error(); - CertFreeCRLContext(crl_context); - if (!ok) + CERT_STORE_ADD_ALWAYS, NULL)) { - ma_format_win32_error(errmsg, errmsg_len, status, "CertAddCRLContextToStore() failed"); - goto cleanup; + FAIL("CertAddCRLContextToStore() failed"); } } } - status = SEC_E_OK; - cleanup: - free(file_buffer); + LocalFree(file_buffer); + if (cert_context) + CertFreeCertificateContext(cert_context); + if (crl_context) + CertFreeCRLContext(crl_context); return status; } @@ -317,38 +316,41 @@ char path[MAX_PATH]; char pattern[MAX_PATH]; DWORD dwAttr; - HANDLE hFind; - SECURITY_STATUS status = SEC_E_INTERNAL_ERROR; + HANDLE hFind = INVALID_HANDLE_VALUE; + SECURITY_STATUS status = SEC_E_OK; if ((dwAttr = GetFileAttributes(dir)) == INVALID_FILE_ATTRIBUTES) { - ma_format_win32_error(errmsg, errmsg_len, 0, "invalid directory '%s'", dir); - return status; + SetLastError(SEC_E_INVALID_PARAMETER); + FAIL("directory '%s' does not exist", dir); } if (!(dwAttr & FILE_ATTRIBUTE_DIRECTORY)) { - ma_format_win32_error(errmsg, errmsg_len, 0, "'%s' is not a directory", dir); - return status; + SetLastError(SEC_E_INVALID_PARAMETER); + FAIL("'%s' is not a directory", dir); } - snprintf(pattern, sizeof(pattern), "%s\\*", dir); + sprintf_s(pattern, sizeof(pattern), "%s\\*", dir); hFind = FindFirstFile(pattern, &ffd); if (hFind == INVALID_HANDLE_VALUE) { - ma_format_win32_error(errmsg, errmsg_len, GetLastError(), "FindFirstFile(%s) failed", pattern); - return status; + FAIL("FindFirstFile(%s) failed",pattern); } do { if (ffd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) continue; - snprintf(path, sizeof(path), "%s\\%s", dir, ffd.cFileName); + sprintf_s(path, sizeof(path), "%s\\%s", dir, ffd.cFileName); // ignore error from add_certs_to_store(), not all file // maybe PEM. add_certs_to_store(trust_store, path, type, errmsg, errmsg_len); } while (FindNextFile(hFind, &ffd) != 0); - FindClose(hFind); + +cleanup: + if (hFind != INVALID_HANDLE_VALUE) + FindClose(hFind); + return status; } @@ -358,7 +360,7 @@ int num_certs = 0; PCCERT_CONTEXT c = NULL; - while (c = CertEnumCertificatesInStore(store, c)) + while ((c = CertEnumCertificatesInStore(store, c))) num_certs++; return num_certs; @@ -389,7 +391,7 @@ HCERTSTORE store = NULL; HCERTSTORE system_store = NULL; - int status = SEC_E_INTERNAL_ERROR; + int status = SEC_E_OK; *out_store = NULL; if (!CAFile && !CAPath && !CRLFile && !CRLPath) @@ -405,9 +407,7 @@ CERT_STORE_CREATE_NEW_FLAG, NULL); if (!store) { - status = get_last_error(); - ma_format_win32_error(errmsg, errmsg_len, status, "failed to create certificate store"); - goto cleanup; + FAIL("CertOpenStore failed for memory store"); } } else if (CRLFile || CRLPath) @@ -419,19 +419,13 @@ CERT_SYSTEM_STORE_CURRENT_USER, L"MY"); if (!system_store) { - status = get_last_error(); - ma_format_win32_error(errmsg, errmsg_len, status, - "failed to open system certificate store"); - goto cleanup; + FAIL("CertOpenStore failed for system store"); } store = CertDuplicateStore(system_store); if (!store) { - status = get_last_error(); - ma_format_win32_error(errmsg, errmsg_len, status, - "failed to duplicate system certificate store"); - goto cleanup; + FAIL("CertDuplicateStore failed"); } } @@ -452,10 +446,9 @@ if ((CAFile || CAPath) && store && !count_certificates(store)) { - snprintf(errmsg, errmsg_len, - "no valid certificates were found, CAFile='%s', CAPath='%s'", + SetLastError(SEC_E_INVALID_PARAMETER); + FAIL("no valid certificates were found, CAFile='%s', CAPath='%s'", CAFile ? CAFile : "<not set>", CAPath ? CAPath : "<not set>"); - goto cleanup; } if (CRLFile) @@ -468,7 +461,6 @@ status = add_dir_to_store(store, CRLPath, PEM_TYPE_X509_CRL, errmsg, errmsg_len); } - status = SEC_E_OK; cleanup: if (system_store) @@ -496,8 +488,8 @@ LPWSTR pwszServerName, DWORD dwRevocationCheckFlags, DWORD dwVerifyFlags, - LPSTR pErrMessage, - size_t cbErrMessage) + LPSTR errmsg, + size_t errmsg_len) { SSL_EXTRA_CERT_CHAIN_POLICY_PARA polExtra; CERT_CHAIN_POLICY_PARA PolicyPara; @@ -509,13 +501,12 @@ szOID_SERVER_GATED_CRYPTO, szOID_SGC_NETSCAPE }; DWORD cUsages = sizeof(rgszUsages) / sizeof(LPSTR); - SECURITY_STATUS Status = SEC_E_INTERNAL_ERROR; + SECURITY_STATUS status = SEC_E_OK; if (pServerCert == NULL) { - snprintf(pErrMessage, cbErrMessage, "Invalid parameter pServerCert passed to VerifyServerCertificate"); - Status = SEC_E_WRONG_PRINCIPAL; - goto cleanup; + SetLastError(SEC_E_WRONG_PRINCIPAL); + FAIL("Invalid parameter pServerCert passed to VerifyServerCertificate"); } ZeroMemory(&ChainPara, sizeof(ChainPara)); @@ -531,10 +522,7 @@ EngineConfig.hExclusiveRoot = hStore; if (!CertCreateCertificateChainEngine(&EngineConfig, &hChainEngine)) { - Status = get_last_error(); - ma_format_win32_error(pErrMessage, cbErrMessage, Status, - "CertCreateCertificateChainEngine failed"); - goto cleanup; + FAIL("CertCreateCertificateChainEngine failed"); } } @@ -548,8 +536,7 @@ NULL, &pChainContext)) { - Status = get_last_error(); - ma_format_win32_error(pErrMessage, cbErrMessage, Status, "CertGetCertificateChain failed"); + FAIL("CertGetCertificateChain failed"); goto cleanup; } @@ -573,18 +560,14 @@ &PolicyPara, &PolicyStatus)) { - Status = get_last_error(); - ma_format_win32_error(pErrMessage, cbErrMessage, Status, "CertVerifyCertificateChainPolicy failed"); - goto cleanup; + FAIL("CertVerifyCertificateChainPolicy failed"); } if (PolicyStatus.dwError) { - Status = PolicyStatus.dwError; - ma_format_win32_error(pErrMessage, cbErrMessage, Status, "Server certificate validation failed"); - goto cleanup; + SetLastError(PolicyStatus.dwError); + FAIL("Server certificate validation failed"); } - Status = SEC_E_OK; cleanup: if (hChainEngine) @@ -595,7 +578,7 @@ { CertFreeCertificateChain(pChainContext); } - return Status; + return status; } @@ -619,7 +602,7 @@ char* errmsg, size_t errmsg_len) { - SECURITY_STATUS status = SEC_E_INTERNAL_ERROR; + SECURITY_STATUS status = SEC_E_OK; wchar_t* wserver_name = NULL; DWORD dwVerifyFlags; DWORD dwRevocationFlags; @@ -627,16 +610,14 @@ if (check_server_name) { int cchServerName = (int)strlen(server_name) + 1; - wserver_name = (wchar_t*)malloc(sizeof(wchar_t) * cchServerName); + wserver_name = (wchar_t*)LocalAlloc(0,sizeof(wchar_t) * cchServerName); if (!wserver_name) { - ma_format_win32_error(errmsg, errmsg_len, ERROR_OUTOFMEMORY, "malloc() failed"); - goto cleanup; + FAIL("LocalAlloc() failed"); } if (MultiByteToWideChar(CP_UTF8, 0, server_name, cchServerName, wserver_name, cchServerName) < 0) { - ma_format_win32_error(errmsg, errmsg_len, GetLastError(), "MultiByteToWideChar() failed"); - goto cleanup; + FAIL("MultiByteToWideChar() failed"); } } @@ -651,7 +632,7 @@ dwRevocationFlags, dwVerifyFlags, errmsg, errmsg_len); cleanup: - free(wserver_name); + LocalFree(wserver_name); return status; } @@ -668,21 +649,17 @@ CERT_KEY_CONTEXT cert_key_context = { 0 }; PCRYPT_PRIVATE_KEY_INFO pki = NULL; DWORD pki_len = 0; - SECURITY_STATUS status = SEC_E_INTERNAL_ERROR; + SECURITY_STATUS status = SEC_E_OK; derbuf = LocalAlloc(0, derlen); if (!derbuf) { - status = get_last_error(); - ma_format_win32_error(errmsg, errmsg_len, status, "Memory allocation failed"); - goto cleanup; + FAIL("LocalAlloc failed") } if (!CryptStringToBinaryA(private_key_str, (DWORD)len, CRYPT_STRING_BASE64HEADER, derbuf, &derlen, NULL, NULL)) { - status = get_last_error(); - ma_format_win32_error(errmsg, errmsg_len, status, "Failed to convert BASE64 private key"); - goto cleanup; + FAIL("Failed to convert BASE64 private key"); } /* @@ -706,10 +683,7 @@ CRYPT_DECODE_ALLOC_FLAG, NULL, &keyblob, &keyblob_len)) { - status = get_last_error(); - ma_format_win32_error(errmsg, errmsg_len, status, - "Failed to parse private key"); - goto cleanup; + FAIL("Failed to parse private key"); } } else if (!CryptDecodeObjectEx( @@ -719,24 +693,17 @@ CRYPT_DECODE_ALLOC_FLAG, NULL, &keyblob, &keyblob_len)) { - status = get_last_error(); - ma_format_win32_error(errmsg, errmsg_len, status, - "Failed to parse private key"); - goto cleanup; + FAIL("Failed to parse private key"); } if (!CryptAcquireContext(&hProv, NULL, MS_ENHANCED_PROV, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT)) { - status = get_last_error(); - ma_format_win32_error(errmsg, errmsg_len, status, "CryptAcquireContext failed"); - goto cleanup; + FAIL("CryptAcquireContext failed"); } if (!CryptImportKey(hProv, keyblob, keyblob_len, 0, 0, (HCRYPTKEY*)&hKey)) { - status = get_last_error(); - ma_format_win32_error(errmsg, errmsg_len, status, "CryptImportKey failed"); - goto cleanup; + FAIL("CryptImportKey failed"); } cert_key_context.hCryptProv = hProv; cert_key_context.dwKeySpec = AT_KEYEXCHANGE; @@ -745,10 +712,8 @@ /* assign private key to certificate context */ if (!CertSetCertificateContextProperty(cert, CERT_KEY_CONTEXT_PROP_ID, 0, &cert_key_context)) { - status = get_last_error(); - ma_format_win32_error(errmsg, errmsg_len, get_last_error(), "Can't assign private key to certificate context"); + FAIL("CertSetCertificateContextProperty failed"); } - status = SEC_E_OK; cleanup: LocalFree(derbuf); @@ -779,7 +744,7 @@ char* end; CERT_BLOB cert_blob; DWORD actual_content_type = 0; - int ok = 0; + SECURITY_STATUS status = SEC_E_OK; /* Parse certificate */ pem_locate(cert_file_content, PEM_TYPE_CERTIFICATE, @@ -787,8 +752,8 @@ if (!begin || !end) { - snprintf(errmsg, errmsg_len, "Client certificate not found in PEM file"); - goto cleanup; + SetLastError(SEC_E_INVALID_PARAMETER); + FAIL("Client certificate not found in PEM file"); } cert_blob.pbData = (BYTE*)begin; @@ -799,9 +764,7 @@ CERT_QUERY_FORMAT_FLAG_ALL, 0, NULL, &actual_content_type, NULL, NULL, NULL, (const void**)&ctx)) { - ma_format_win32_error(errmsg, errmsg_len, GetLastError(), - "Can't parse client certficate"); - goto cleanup; + FAIL("Can't parse client certficate"); } /* Parse key */ @@ -812,22 +775,22 @@ if (begin && end) { /* Assign key to certificate.*/ - ok = !load_private_key(ctx, begin, (end - begin), errmsg, errmsg_len); + status = load_private_key(ctx, begin, (end - begin), errmsg, errmsg_len); goto cleanup; } } if (!begin || !end) - snprintf(errmsg, errmsg_len, "Client private key not found in PEM"); + { + SetLastError(SEC_E_INVALID_PARAMETER); + FAIL("Client private key not found in PEM"); + } cleanup: - if (!ok) + if (status && ctx) { - if (ctx) - { - CertFreeCertificateContext(ctx); - ctx = NULL; - } + CertFreeCertificateContext(ctx); + ctx = NULL; } return ctx; } @@ -859,9 +822,9 @@ ctx = create_client_certificate_mem(cert_file_content, key_file_content, errmsg, errmsg_len); cleanup: - free(cert_file_content); + LocalFree(cert_file_content); if (cert_file != key_file) - free(key_file_content); + LocalFree(key_file_content); return ctx; } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/mariadb-connector-c-3.1.6-src/libmariadb/secure/schannel_certs.h new/mariadb-connector-c-3.1.7-src/libmariadb/secure/schannel_certs.h --- old/mariadb-connector-c-3.1.6-src/libmariadb/secure/schannel_certs.h 2019-12-08 18:07:48.000000000 +0100 +++ new/mariadb-connector-c-3.1.7-src/libmariadb/secure/schannel_certs.h 2020-01-22 11:08:18.000000000 +0100 @@ -35,7 +35,7 @@ extern SECURITY_STATUS schannel_verify_server_certificate( const CERT_CONTEXT* cert, HCERTSTORE store, - BOOL �check_revocation, + BOOL check_revocation, const char* server_name, BOOL check_server_name, char* errmsg, diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/mariadb-connector-c-3.1.6-src/libmariadb/win32_errmsg.c new/mariadb-connector-c-3.1.7-src/libmariadb/win32_errmsg.c --- old/mariadb-connector-c-3.1.6-src/libmariadb/win32_errmsg.c 2019-12-08 18:07:48.000000000 +0100 +++ new/mariadb-connector-c-3.1.7-src/libmariadb/win32_errmsg.c 2020-01-22 11:08:18.000000000 +0100 @@ -21,6 +21,7 @@ #include <windows.h> #include <stdio.h> #include <stdlib.h> +#include <string.h> /* Format Windows error, with optional text. @@ -40,7 +41,7 @@ { va_list vargs; va_start(vargs, fmt); - cur += vsnprintf(cur, end - cur, fmt, vargs); + cur += vsnprintf_s(cur, end - cur, _TRUNCATE, fmt, vargs); va_end(vargs); } @@ -96,7 +97,7 @@ }; struct map_entry* entry = NULL; - strncpy(cur,". ",end-cur); + strncpy_s(cur,end-cur, ". ", _TRUNCATE); cur += 2; for (size_t i = 0; i < sizeof(map) / sizeof(map[0]); i++) @@ -111,7 +112,7 @@ return; if (entry) { - cur += snprintf(cur, end - cur, "%s. Error 0x%08lX(%s)", entry->msg, code, entry->sym); + sprintf_s(cur, end - cur, "%s. Error 0x%08lX(%s)", entry->msg, code, entry->sym); } else { @@ -125,7 +126,7 @@ cur++; *cur = 0; } - cur += snprintf(cur, end - cur, ". Error %lu/0x%08lX", code, code); + sprintf_s(cur, end - cur, ". Error %lu/0x%08lX", code, code); } } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/mariadb-connector-c-3.1.6-src/unittest/libmariadb/ssl.c.in new/mariadb-connector-c-3.1.7-src/unittest/libmariadb/ssl.c.in --- old/mariadb-connector-c-3.1.6-src/unittest/libmariadb/ssl.c.in 2019-12-08 18:07:48.000000000 +0100 +++ new/mariadb-connector-c-3.1.7-src/unittest/libmariadb/ssl.c.in 2020-01-22 11:08:18.000000000 +0100 @@ -1329,8 +1329,48 @@ return OK; } +#ifndef HAVE_SCHANNEL +static int test_ssl_verify(MYSQL *my __attribute__((unused))) +{ + MYSQL *mysql; + my_bool verify= 1, enforce= 1; + + if (check_skip_ssl()) + return SKIP; + + /* verify, using system ca should fail with self signed certificate */ + mysql= mysql_init(NULL); + mysql_options(mysql, MYSQL_OPT_SSL_ENFORCE, &enforce); + mysql_options(mysql, MYSQL_OPT_SSL_VERIFY_SERVER_CERT, &verify); + FAIL_IF(mysql_real_connect(mysql, hostname, username, password, schema, + port, socketname, 0), "Error expected"); + diag("error expected: %s\n", mysql_error(mysql)); + mysql_close(mysql); + + /* verify against local ca, this should pass */ + mysql= mysql_init(NULL); + mysql_ssl_set(mysql,0, 0, sslca, 0, 0); + mysql_options(mysql, MYSQL_OPT_SSL_VERIFY_SERVER_CERT, &verify); + FAIL_IF(!mysql_real_connect(mysql, hostname, username, password, schema, + port, socketname, 0), mysql_error(mysql)); + mysql_close(mysql); + + mysql= mysql_init(NULL); + mysql_options(mysql, MYSQL_OPT_SSL_ENFORCE, &enforce); + FAIL_IF(!mysql_real_connect(mysql, hostname, username, password, schema, + port, socketname, 0), mysql_error(mysql)); + + diag("cipher: %s", mysql_get_ssl_cipher(mysql)); + mysql_close(mysql); + return OK; +} +#endif + struct my_tests_st my_tests[] = { {"test_ssl", test_ssl, TEST_CONNECTION_NEW, 0, NULL, NULL}, +#ifndef HAVE_SCHANNEL + {"test_ssl_verify", test_ssl_verify, TEST_CONNECTION_NEW, 0, NULL, NULL}, +#endif {"test_mdev14101", test_mdev14101, TEST_CONNECTION_NEW, 0, NULL, NULL}, {"test_mdev14027", test_mdev14027, TEST_CONNECTION_NEW, 0, NULL, NULL}, {"test_conc286", test_conc286, TEST_CONNECTION_NEW, 0, NULL, NULL},