diff --git a/.gitignore b/.gitignore index bc8fa2af..19b565a2 100644 --- a/.gitignore +++ b/.gitignore @@ -88,6 +88,8 @@ unittest/libmariadb/ssl unittest/libmariadb/t_aurora unittest/libmariadb/t_conc173 unittest/libmariadb/thread +unittest/libmariadb/tls +unittest/libmariadb/tls.c unittest/libmariadb/view unittest/libmariadb/conc336 diff --git a/include/ma_tls.h b/include/ma_tls.h index 444ea4aa..8cb46d5f 100644 --- a/include/ma_tls.h +++ b/include/ma_tls.h @@ -141,7 +141,6 @@ const char *ma_tls_get_cipher(MARIADB_TLS *ssl); hash_type hash_type as defined in ma_hash.h fp buffer for fingerprint fp_len buffer length - my_bool verify_period Returns: actual size of finger print diff --git a/include/mysql.h b/include/mysql.h index ba92527d..e050fc55 100644 --- a/include/mysql.h +++ b/include/mysql.h @@ -452,8 +452,8 @@ typedef struct st_mysql_time #define MARIADB_TLS_VERIFY_OK 0 #define MARIADB_TLS_VERIFY_TRUST 1 #define MARIADB_TLS_VERIFY_HOST 2 -#define MARIADB_TLS_VERIFY_PERIOD 4 -#define MARIADB_TLS_VERIFY_FINGERPRINT 8 +#define MARIADB_TLS_VERIFY_FINGERPRINT 4 +#define MARIADB_TLS_VERIFY_PERIOD 8 #define MARIADB_TLS_VERIFY_REVOKED 16 #define MARIADB_TLS_VERIFY_UNKNOWN 32 #define MARIADB_TLS_VERIFY_ERROR 128 /* last */ diff --git a/libmariadb/ma_tls.c b/libmariadb/ma_tls.c index f6ea6661..26951b4b 100644 --- a/libmariadb/ma_tls.c +++ b/libmariadb/ma_tls.c @@ -298,7 +298,7 @@ my_bool ma_pvio_tls_check_fp(MARIADB_TLS *ctls, const char *fp, const char *fp_l } end: - if (rc) + if (rc && !mysql->net.last_errno) { my_set_error(mysql, CR_SSL_CONNECTION_ERROR, SQLSTATE_UNKNOWN, ER(CR_SSL_CONNECTION_ERROR), diff --git a/libmariadb/secure/gnutls.c b/libmariadb/secure/gnutls.c index 0d17a9d5..836472ca 100644 --- a/libmariadb/secure/gnutls.c +++ b/libmariadb/secure/gnutls.c @@ -1483,7 +1483,7 @@ int ma_tls_verify_server_cert(MARIADB_TLS *ctls, unsigned int flags) goto end; } - rc= gnutls_x509_crt_check_hostname2(cert, mysql->host, flags); + rc= gnutls_x509_crt_check_hostname2(cert, mysql->host, 0); gnutls_x509_crt_deinit(cert); if (!rc) @@ -1528,7 +1528,7 @@ unsigned int ma_tls_get_finger_print(MARIADB_TLS *ctls, uint hash_type, char *fp switch (hash_type) { -#ifdef WEAK_HASH +#ifndef DISABLE_WEAK_HASH case MA_HASH_SHA1: hash_alg = GNUTLS_DIG_SHA1; break; diff --git a/libmariadb/secure/ma_schannel.c b/libmariadb/secure/ma_schannel.c index 4d236ccf..7c048491 100644 --- a/libmariadb/secure/ma_schannel.c +++ b/libmariadb/secure/ma_schannel.c @@ -502,6 +502,9 @@ unsigned int ma_schannel_verify_certs(MARIADB_TLS *ctls, unsigned int verify_fla if(status) goto end; + if (!crl_file && !crl_path) // backward compatible behavior + verify_flags &= ~MARIADB_TLS_VERIFY_REVOKED; + status = QueryContextAttributesA(&sctx->hCtxt, SECPKG_ATTR_REMOTE_CERT_CONTEXT, (PVOID)&pServerCert); if (status) { diff --git a/libmariadb/secure/openssl.c b/libmariadb/secure/openssl.c index b5b573a9..29b46f90 100644 --- a/libmariadb/secure/openssl.c +++ b/libmariadb/secure/openssl.c @@ -516,13 +516,17 @@ unsigned int ma_tls_get_peer_cert_info(MARIADB_TLS *ctls, uint hash_size) ctls->cert_info.subject= X509_NAME_oneline(X509_get_subject_name(cert), NULL, 0); ctls->cert_info.issuer= X509_NAME_oneline(X509_get_issuer_name(cert), NULL, 0); ctls->cert_info.version= X509_get_version(cert) + 1; + ctls->cert_info.fingerprint[0]= 0; X509_free(cert); } else return 1; } - ma_tls_get_finger_print(ctls, hash_alg, fp, sizeof(fp)); - mysql_hex_string(ctls->cert_info.fingerprint, fp, (unsigned long)ma_hash_digest_size(hash_alg)); + if (strlen(ctls->cert_info.fingerprint) != hash_size/4) + { + ma_tls_get_finger_print(ctls, hash_alg, fp, sizeof(fp)); + mysql_hex_string(ctls->cert_info.fingerprint, fp, hash_size/8); + } return 0; } @@ -723,22 +727,30 @@ static int ma_verification_callback(int preverify_ok __attribute__((unused)), X5 { SSL *ssl; - int x509_err= X509_STORE_CTX_get_error(ctx); - if ((ssl = X509_STORE_CTX_get_ex_data(ctx, SSL_get_ex_data_X509_STORE_CTX_idx()))) { MYSQL *mysql= (MYSQL *)SSL_get_app_data(ssl); + int x509_err= X509_STORE_CTX_get_error(ctx); + my_bool verify_status= MARIADB_TLS_VERIFY_OK; if ((x509_err == X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT || x509_err == X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN)) - mysql->net.tls_verify_status|= MARIADB_TLS_VERIFY_TRUST; + verify_status= MARIADB_TLS_VERIFY_TRUST; else if (x509_err == X509_V_ERR_CERT_REVOKED) - mysql->net.tls_verify_status|= MARIADB_TLS_VERIFY_REVOKED; + verify_status= MARIADB_TLS_VERIFY_REVOKED; else if (x509_err == X509_V_ERR_CERT_NOT_YET_VALID || x509_err == X509_V_ERR_CERT_HAS_EXPIRED) - mysql->net.tls_verify_status|= MARIADB_TLS_VERIFY_PERIOD; + verify_status= MARIADB_TLS_VERIFY_PERIOD; else if (x509_err != X509_V_OK) - mysql->net.tls_verify_status|= MARIADB_TLS_VERIFY_UNKNOWN; + verify_status= MARIADB_TLS_VERIFY_UNKNOWN; + + if (verify_status) + { + if (mysql->net.tls_verify_status < verify_status) + my_set_error(mysql, CR_SSL_CONNECTION_ERROR, SQLSTATE_UNKNOWN, + ER(CR_SSL_CONNECTION_ERROR), X509_verify_cert_error_string(x509_err)); + mysql->net.tls_verify_status|= verify_status; + } } /* continue verification */ @@ -765,6 +777,12 @@ int ma_tls_verify_server_cert(MARIADB_TLS *ctls, unsigned int verify_flags) mysql= (MYSQL *)SSL_get_app_data(ssl); pvio= mysql->net.pvio; + if ((mysql->net.tls_verify_status > MARIADB_TLS_VERIFY_FINGERPRINT) || + (mysql->net.tls_verify_status & verify_flags)) + { + return 1; + } + if (verify_flags & MARIADB_TLS_VERIFY_FINGERPRINT) { if (ma_pvio_tls_check_fp(ctls, mysql->options.extension->tls_fp, mysql->options.extension->tls_fp_list)) @@ -773,19 +791,8 @@ int ma_tls_verify_server_cert(MARIADB_TLS *ctls, unsigned int verify_flags) return 1; } - /* if certificates are valid and no revocation error occured, - we can return */ - if (!(mysql->net.tls_verify_status & MARIADB_TLS_VERIFY_PERIOD) && - !(mysql->net.tls_verify_status & MARIADB_TLS_VERIFY_REVOKED)) - { - mysql->net.tls_verify_status= MARIADB_TLS_VERIFY_OK; - return 0; - } - } - - if (mysql->net.tls_verify_status & verify_flags) - { - return 1; + mysql->net.tls_verify_status= MARIADB_TLS_VERIFY_OK; + return 0; } if (verify_flags & MARIADB_TLS_VERIFY_HOST) @@ -802,7 +809,7 @@ int ma_tls_verify_server_cert(MARIADB_TLS *ctls, unsigned int verify_flags) { pvio->set_error(mysql, CR_SSL_CONNECTION_ERROR, SQLSTATE_UNKNOWN, ER(CR_SSL_CONNECTION_ERROR), "Unable to get server certificate"); - mysql->net.tls_verify_status|= MARIADB_TLS_VERIFY_HOST; + mysql->net.tls_verify_status|= MARIADB_TLS_VERIFY_UNKNOWN; return MARIADB_TLS_VERIFY_ERROR; } @@ -853,8 +860,7 @@ int ma_tls_verify_server_cert(MARIADB_TLS *ctls, unsigned int verify_flags) } return 0; error: - if (cert) - X509_free(cert); + X509_free(cert); return 1; } diff --git a/libmariadb/secure/schannel_certs.c b/libmariadb/secure/schannel_certs.c index b167f74d..43362057 100644 --- a/libmariadb/secure/schannel_certs.c +++ b/libmariadb/secure/schannel_certs.c @@ -234,7 +234,10 @@ static SECURITY_STATUS add_certs_to_store( file_buffer = pem_file_to_string(file, errmsg, errmsg_len); if (!file_buffer) + { + status = ERROR_FILE_NOT_FOUND; goto cleanup; + } for (cur = file_buffer; ; cur = end) { diff --git a/plugins/auth/my_auth.c b/plugins/auth/my_auth.c index e7429fae..a2fd519d 100644 --- a/plugins/auth/my_auth.c +++ b/plugins/auth/my_auth.c @@ -431,7 +431,7 @@ static int send_client_reply_packet(MCPVIO_EXT *mpvio, verify_flags|= MARIADB_TLS_VERIFY_TRUST | MARIADB_TLS_VERIFY_HOST; } - if (ma_pvio_tls_verify_server_cert(mysql->net.pvio->ctls, verify_flags) > MARIADB_TLS_VERIFY_OK) + if (ma_pvio_tls_verify_server_cert(mysql->net.pvio->ctls, verify_flags)) { if (mysql->net.tls_verify_status > MARIADB_TLS_VERIFY_TRUST || (mysql->options.ssl_ca || mysql->options.ssl_capath)) @@ -440,6 +440,7 @@ static int send_client_reply_packet(MCPVIO_EXT *mpvio, if (is_local_connection(mysql->net.pvio)) { CLEAR_CLIENT_ERROR(mysql); + mysql->net.tls_verify_status&= ~MARIADB_TLS_VERIFY_TRUST; } else if (!password_and_hashing(mysql, mpvio->plugin)) goto error; @@ -841,9 +842,7 @@ retry: if (ma_read_ok_packet(mysql, mysql->net.read_pos + 1, pkt_length)) return -1; - if (!mysql->net.tls_verify_status || - ((mysql->net.tls_verify_status & MARIADB_TLS_VERIFY_TRUST) && - is_local_connection(mysql->net.pvio))) + if (!mysql->net.tls_verify_status) return 0; assert(mysql->options.use_ssl);