1
0
mirror of https://github.com/mariadb-corporation/mariadb-connector-c.git synced 2025-08-08 14:02:17 +03:00

Revert "self-signed certificate verification", it's 3.4 feature

This reverts 395641549ac7..536d9e2b9e5b, in particular:

8dffd56936 MDEV-31857 enable MYSQL_OPT_SSL_VERIFY_SERVER_CERT by default
a99570c118 MDEV-31855 SSL cert validation protocol extension
9aa15e72a7 TLS fingerprint

and related commits
This commit is contained in:
Sergei Golubchik
2024-02-19 11:09:11 +01:00
parent 536d9e2b9e
commit f6e99af056
29 changed files with 121 additions and 422 deletions

View File

@@ -305,8 +305,7 @@ IF(NOT WITH_SSL STREQUAL "OFF")
ENDIF()
IF(OPENSSL_FOUND)
ADD_DEFINITIONS(-DHAVE_OPENSSL -DHAVE_TLS)
SET(SSL_SOURCES "${CC_SOURCE_DIR}/libmariadb/secure/openssl.c"
"${CC_SOURCE_DIR}/libmariadb/secure/openssl_crypt.c")
SET(SSL_SOURCES "${CC_SOURCE_DIR}/libmariadb/secure/openssl.c")
SET(SSL_LIBRARIES ${OPENSSL_SSL_LIBRARY} ${OPENSSL_CRYPTO_LIBRARY})
IF(WIN32)
CHECK_INCLUDE_FILES (${OPENSSL_INCLUDE_DIR}/openssl/applink.c HAVE_OPENSSL_APPLINK_C)
@@ -333,8 +332,7 @@ IF(NOT WITH_SSL STREQUAL "OFF")
FIND_PACKAGE(GnuTLS "3.3.24" REQUIRED)
IF(GNUTLS_FOUND)
ADD_DEFINITIONS(-DHAVE_GNUTLS -DHAVE_TLS)
SET(SSL_SOURCES "${CC_SOURCE_DIR}/libmariadb/secure/gnutls.c"
"${CC_SOURCE_DIR}/libmariadb/secure/gnutls_crypt.c")
SET(SSL_SOURCES "${CC_SOURCE_DIR}/libmariadb/secure/gnutls.c")
SET(SSL_LIBRARIES ${GNUTLS_LIBRARY})
SET(TLS_LIBRARY_VERSION "GnuTLS ${GNUTLS_VERSION_STRING}")
INCLUDE_DIRECTORIES(${GNUTLS_INCLUDE_DIR})
@@ -344,13 +342,12 @@ IF(NOT WITH_SSL STREQUAL "OFF")
ENDIF()
IF(WIN32)
IF(WITH_SSL STREQUAL "SCHANNEL")
ADD_DEFINITIONS(-DHAVE_SCHANNEL -DHAVE_TLS -DHAVE_WINCRYPT)
ADD_DEFINITIONS(-DHAVE_SCHANNEL -DHAVE_TLS)
SET(SSL_SOURCES "${CC_SOURCE_DIR}/libmariadb/secure/schannel.c"
"${CC_SOURCE_DIR}/libmariadb/secure/win_crypt.c"
"${CC_SOURCE_DIR}/libmariadb/secure/ma_schannel.c"
"${CC_SOURCE_DIR}/libmariadb/secure/schannel_certs.c")
INCLUDE_DIRECTORIES("${CC_SOURCE_DIR}/plugins/pvio/")
SET(SSL_LIBRARIES secur32 crypt32 bcrypt)
SET(SSL_LIBRARIES secur32)
SET(TLS_LIBRARY_VERSION "Schannel ${CMAKE_SYSTEM_VERSION}")
ENDIF()
ENDIF()
@@ -385,7 +382,7 @@ CONFIGURE_FILE(${CC_SOURCE_DIR}/include/mariadb_version.h.in
INCLUDE_DIRECTORIES(${CC_BINARY_DIR}/include)
IF(WIN32)
SET(SYSTEM_LIBS ws2_32 advapi32 kernel32 shlwapi crypt32 bcrypt ${LIBZ})
SET(SYSTEM_LIBS ws2_32 advapi32 kernel32 shlwapi crypt32 ${LIBZ})
ELSE()
SET(SYSTEM_LIBS ${SYSTEM_LIBS} ${LIBPTHREAD} ${CMAKE_DL_LIBS} ${LIBM})
IF(ICONV_EXTERNAL)

View File

@@ -86,7 +86,7 @@ struct st_mysql_options_extension {
unsigned short rpl_port;
void (*status_callback)(void *ptr, enum enum_mariadb_status_info type, ...);
void *status_data;
my_bool tls_allow_invalid_server_cert;
my_bool tls_verify_server_cert;
};
typedef struct st_connection_handler
@@ -129,16 +129,3 @@ typedef struct st_mariadb_field_extension
{
MARIADB_CONST_STRING metadata[MARIADB_FIELD_ATTR_LAST+1]; /* 10.5 */
} MA_FIELD_EXTENSION;
#if defined(HAVE_SCHANNEL) || defined(HAVE_GNUTLS)
#define reset_tls_self_signed_error(mysql) \
do { \
free((char*)mysql->net.tls_self_signed_error); \
mysql->net.tls_self_signed_error= 0; \
} while(0)
#else
#define reset_tls_self_signed_error(mysql) \
do { \
mysql->net.tls_self_signed_error= 0; \
} while(0)
#endif

View File

@@ -17,20 +17,34 @@
51 Franklin St., Fifth Floor, Boston, MA 02110, USA
*/
#ifndef _ma_crypt_h_
#define _ma_crypt_h_
#ifndef _ma_hash_h_
#define _ma_hash_h_
#include <ma_hash.h>
#include <stddef.h>
#include <stdarg.h>
/*! Hash algorithms */
#define MA_HASH_MD5 1
#define MA_HASH_SHA1 2
#define MA_HASH_SHA224 3
#define MA_HASH_SHA256 4
#define MA_HASH_SHA384 5
#define MA_HASH_SHA512 6
#define MA_HASH_RIPEMD160 7
#define MA_HASH_MAX 8
/*! Hash digest sizes */
#define MA_MD5_HASH_SIZE 16
#define MA_SHA1_HASH_SIZE 20
#define MA_SHA224_HASH_SIZE 28
#define MA_SHA256_HASH_SIZE 32
#define MA_SHA384_HASH_SIZE 48
#define MA_SHA512_HASH_SIZE 64
#define MA_RIPEMD160_HASH_SIZE 20
#define MA_MAX_HASH_SIZE 64
/** \typedef MRL hash context */
#if defined(HAVE_WINCRYPT)
typedef void MA_HASH_CTX;
#elif defined(HAVE_OPENSSL)
@@ -109,6 +123,8 @@ static inline size_t ma_hash_digest_size(unsigned int hash_alg)
return MA_SHA384_HASH_SIZE;
case MA_HASH_SHA512:
return MA_SHA512_HASH_SIZE;
case MA_HASH_RIPEMD160:
return MA_RIPEMD160_HASH_SIZE;
default:
return 0;
}
@@ -136,4 +152,4 @@ static inline void ma_hash(unsigned int algorithm,
ma_hash_free(ctx);
}
#endif /* _ma_crypt_h_ */
#endif /* _ma_hash_h_ */

View File

@@ -1,8 +1,6 @@
#ifndef _ma_tls_h_
#define _ma_tls_h_
#include <ma_hash.h>
enum enum_pvio_tls_type {
SSL_TYPE_DEFAULT=0,
#ifdef _WIN32
@@ -130,14 +128,12 @@ const char *ma_tls_get_cipher(MARIADB_TLS *ssl);
returns SHA1 finger print of server certificate
Parameter:
MARIADB_TLS MariaDB SSL container
hash_type hash_type as defined in ma_hash.h
fp buffer for fingerprint
fp_len buffer length
Returns:
actual size of finger print
*/
unsigned int ma_tls_get_finger_print(MARIADB_TLS *ctls, uint hash_type, char *fp, unsigned int fp_len);
unsigned int ma_tls_get_finger_print(MARIADB_TLS *ctls, char *fp, unsigned int fp_len);
/* ma_tls_get_protocol_version
returns protocol version number in use

View File

@@ -288,7 +288,7 @@ typedef struct st_net {
my_bool unused_2;
my_bool compress;
my_bool unused_3;
const char *tls_self_signed_error;
void *unused_4;
unsigned int last_errno;
unsigned char error;
my_bool unused_5;

View File

@@ -43,7 +43,7 @@
#define MYSQL_CLIENT_PLUGIN_RESERVED2 1
#define MYSQL_CLIENT_AUTHENTICATION_PLUGIN 2 /* authentication */
#define MYSQL_CLIENT_AUTHENTICATION_PLUGIN_INTERFACE_VERSION 0x0101
#define MYSQL_CLIENT_AUTHENTICATION_PLUGIN_INTERFACE_VERSION 0x0100
#define MYSQL_CLIENT_MAX_PLUGINS 3
/* Connector/C specific plugin types */
@@ -128,7 +128,6 @@ struct st_mysql_client_plugin_AUTHENTICATION
{
MYSQL_CLIENT_PLUGIN_HEADER
int (*authenticate_user)(MYSQL_PLUGIN_VIO *vio, struct st_mysql *mysql);
int (*hash_password_bin)(struct st_mysql *mysql, unsigned char *hash, size_t *hash_length);
};
/******** trace plugin *******/

View File

@@ -344,10 +344,6 @@ IF(WIN32)
${CC_SOURCE_DIR}/win-iconv/win_iconv.c
win32_errmsg.c
win32_errmsg.h)
IF(WITH_SSL STREQUAL "SCHANNEL")
SET(LIBMARIADB_SOURCES ${LIBMARIADB_SOURCES}
secure/win_crypt.c)
ENDIF()
ELSE()
IF(ICONV_INCLUDE_DIR)
INCLUDE_DIRECTORIES(BEFORE ${ICONV_INCLUDE_DIR})

View File

@@ -111,7 +111,8 @@ static int get_plugin_nr(uint type)
static const char *check_plugin_version(struct st_mysql_client_plugin *plugin, unsigned int version)
{
if (plugin->interface_version >> 8 != version >> 8)
if (plugin->interface_version < version ||
(plugin->interface_version >> 8) > (version >> 8))
return "Incompatible client plugin interface";
return 0;
}

View File

@@ -522,44 +522,6 @@ my_bool ma_pvio_has_data(MARIADB_PVIO *pvio, ssize_t *data_len)
/* }}} */
#ifdef HAVE_TLS
/**
Checks if self-signed certificate error should be ignored.
*/
static my_bool ignore_self_signed_cert_error(MARIADB_PVIO *pvio)
{
const char *hostname= pvio->mysql->host;
const char *local_host_names[]= {
#ifdef _WIN32
/*
On Unix, we consider TCP connections with "localhost"
an insecure transport, for the single reason to run tests for
insecure transport on CI.This is artificial, but should be ok.
Default client connections use unix sockets anyway, so it
would not hurt much.
On Windows, the situation is quite different.
Default connections type is TCP, default host name is "localhost",
non-password plugin gssapi is common (every installation)
In this environment, there would be a lot of faux/disruptive
"self-signed certificates" errors there. Thus, "localhost" TCP
needs to be considered secure transport.
*/
"localhost",
#endif
"127.0.0.1", "::1", NULL};
int i;
if (pvio->type != PVIO_TYPE_SOCKET)
return TRUE;
if (!hostname)
return FALSE;
for (i= 0; local_host_names[i]; i++)
{
if (strcmp(hostname, local_host_names[i]) == 0)
return TRUE;
}
return FALSE;
}
/* {{{ my_bool ma_pvio_start_ssl */
my_bool ma_pvio_start_ssl(MARIADB_PVIO *pvio)
{
@@ -582,8 +544,7 @@ my_bool ma_pvio_start_ssl(MARIADB_PVIO *pvio)
2. verify CN (requires option ssl_verify_check)
3. verrify finger print
*/
if (!pvio->mysql->options.extension->tls_allow_invalid_server_cert &&
!pvio->mysql->net.tls_self_signed_error &&
if (pvio->mysql->options.extension->tls_verify_server_cert &&
ma_pvio_tls_verify_server_cert(pvio->ctls))
return 1;
@@ -595,12 +556,8 @@ my_bool ma_pvio_start_ssl(MARIADB_PVIO *pvio)
pvio->mysql->options.extension->tls_fp,
pvio->mysql->options.extension->tls_fp_list))
return 1;
reset_tls_self_signed_error(pvio->mysql); // validated
}
if (pvio->mysql->net.tls_self_signed_error && ignore_self_signed_cert_error(pvio))
reset_tls_self_signed_error(pvio->mysql);
return 0;
}
/* }}} */

View File

@@ -41,15 +41,12 @@
#include <ma_tls.h>
#include <mysql/client_plugin.h>
#include <mariadb/ma_io.h>
#include <ma_hash.h>
#ifdef HAVE_NONBLOCK
#include <mariadb_async.h>
#include <ma_context.h>
#endif
#define MAX_FINGERPRINT_LEN 128;
/* Errors should be handled via pvio callback function */
my_bool ma_tls_initialized= FALSE;
unsigned int mariadb_deinitialize_ssl= 1;
@@ -144,96 +141,62 @@ static signed char ma_hex2int(char c)
return -1;
}
#ifndef EVP_MAX_MD_SIZE
#define EVP_MAX_MD_SIZE 64
#endif
static my_bool ma_pvio_tls_compare_fp(MARIADB_TLS *ctls,
const char *cert_fp,
unsigned int cert_fp_len
)
static my_bool ma_pvio_tls_compare_fp(const char *cert_fp,
unsigned int cert_fp_len,
const char *fp, unsigned int fp_len)
{
const char fp[EVP_MAX_MD_SIZE];
unsigned int fp_len= EVP_MAX_MD_SIZE;
unsigned int hash_type;
char *p= (char *)fp,
*c;
char *p, *c;
uint hash_len;
/* check length without colons */
if (strchr(cert_fp, ':'))
hash_len= (uint)((strlen(cert_fp) + 1) / 3) * 2;
else
hash_len= (uint)strlen(cert_fp);
/* check hash size */
switch (hash_len) {
#ifndef DISABLE_WEAK_HASH
case MA_SHA1_HASH_SIZE * 2:
hash_type = MA_HASH_SHA1;
break;
#endif
case MA_SHA224_HASH_SIZE * 2:
hash_type = MA_HASH_SHA224;
break;
case MA_SHA256_HASH_SIZE * 2:
hash_type = MA_HASH_SHA256;
break;
case MA_SHA384_HASH_SIZE * 2:
hash_type = MA_HASH_SHA384;
break;
case MA_SHA512_HASH_SIZE * 2:
hash_type = MA_HASH_SHA512;
break;
default:
{
MYSQL* mysql = ctls->pvio->mysql;
my_set_error(mysql, CR_SSL_CONNECTION_ERROR, SQLSTATE_UNKNOWN,
ER(CR_SSL_CONNECTION_ERROR),
"Unknown or invalid fingerprint hash size detected");
return 1;
}
}
if (!ma_tls_get_finger_print(ctls, hash_type, (char *)fp, fp_len))
/* check length */
if (cert_fp_len != 20)
return 1;
p= (char *)cert_fp;
c = (char *)fp;
/* We support two formats:
2 digits hex numbers, separated by colons (length=59)
20 * 2 digits hex numbers without separators (length = 40)
*/
if (fp_len != (strchr(fp, ':') ? 59 : 40))
return 1;
for (p = (char*)cert_fp; p < cert_fp + cert_fp_len; c++, p += 2)
for(c= (char *)cert_fp; c < cert_fp + cert_fp_len; c++)
{
signed char d1, d2;
if (*p == ':')
p++;
if (p - cert_fp > (int)fp_len - 1)
if (p - fp > (int)fp_len -1)
return 1;
if ((d1 = ma_hex2int(*p)) == -1 ||
(d2 = ma_hex2int(*(p + 1))) == -1 ||
(char)(d1 * 16 + d2) != *c)
if ((d1 = ma_hex2int(*p)) == - 1 ||
(d2 = ma_hex2int(*(p+1))) == -1 ||
(char)(d1 * 16 + d2) != *c)
return 1;
p+= 2;
}
return 0;
}
my_bool ma_pvio_tls_check_fp(MARIADB_TLS *ctls, const char *fp, const char *fp_list)
{
unsigned int cert_fp_len= 64;
char *cert_fp= NULL;
my_bool rc=1;
MYSQL *mysql= ctls->pvio->mysql;
cert_fp= (char *)malloc(cert_fp_len);
if ((cert_fp_len= ma_tls_get_finger_print(ctls, cert_fp, cert_fp_len)) < 1)
goto end;
if (fp)
{
rc = ma_pvio_tls_compare_fp(ctls, fp, (uint)strlen(fp));
}
rc= ma_pvio_tls_compare_fp(cert_fp, cert_fp_len, fp, (unsigned int)strlen(fp));
else if (fp_list)
{
MA_FILE *f;
MA_FILE *fp;
char buff[255];
if (!(f = ma_open(fp_list, "r", mysql)))
if (!(fp = ma_open(fp_list, "r", mysql)))
goto end;
while (ma_gets(buff, sizeof(buff)-1, f))
while (ma_gets(buff, sizeof(buff)-1, fp))
{
/* remove trailing new line character */
char *pos= strchr(buff, '\r');
@@ -242,20 +205,22 @@ my_bool ma_pvio_tls_check_fp(MARIADB_TLS *ctls, const char *fp, const char *fp_l
if (pos)
*pos= '\0';
if (!ma_pvio_tls_compare_fp(ctls, buff, (uint)strlen(buff)))
if (!ma_pvio_tls_compare_fp(cert_fp, cert_fp_len, buff, (unsigned int)strlen(buff)))
{
/* finger print is valid: close file and exit */
ma_close(f);
ma_close(fp);
rc= 0;
goto end;
}
}
/* No finger print matched - close file and return error */
ma_close(f);
ma_close(fp);
}
end:
if (cert_fp)
free(cert_fp);
if (rc)
{
my_set_error(mysql, CR_SSL_CONNECTION_ERROR, SQLSTATE_UNKNOWN,

View File

@@ -1440,8 +1440,6 @@ mysql_real_connect(MYSQL *mysql, const char *host, const char *user,
if (!mysql->options.extension || !mysql->options.extension->status_callback)
mysql_optionsv(mysql, MARIADB_OPT_STATUS_CALLBACK, NULL, NULL);
reset_tls_self_signed_error(mysql);
/* if host contains a semicolon, we need to parse connection string */
if (host && strchr(host, ';'))
{
@@ -2446,7 +2444,6 @@ mysql_close(MYSQL *mysql)
mysql_close_memory(mysql);
mysql_close_options(mysql);
ma_clear_session_state(mysql);
reset_tls_self_signed_error(mysql);
if (mysql->net.extension)
{
@@ -3550,7 +3547,7 @@ mysql_optionsv(MYSQL *mysql,enum mysql_option option, ...)
mysql->options.use_ssl= (*(my_bool *)arg1);
break;
case MYSQL_OPT_SSL_VERIFY_SERVER_CERT:
OPT_SET_EXTENDED_VALUE(&mysql->options, tls_allow_invalid_server_cert, !*(my_bool *)arg1);
OPT_SET_EXTENDED_VALUE(&mysql->options, tls_verify_server_cert, *(my_bool *)arg1);
break;
case MYSQL_OPT_SSL_KEY:
OPT_SET_VALUE_STR(&mysql->options, ssl_key, (char *)arg1);
@@ -3916,7 +3913,7 @@ mysql_get_optionv(MYSQL *mysql, enum mysql_option option, void *arg, ...)
*((my_bool *)arg)= mysql->options.use_ssl;
break;
case MYSQL_OPT_SSL_VERIFY_SERVER_CERT:
*((my_bool*)arg) = mysql->options.extension ? !mysql->options.extension->tls_allow_invalid_server_cert: 1;
*((my_bool*)arg) = mysql->options.extension ? mysql->options.extension->tls_verify_server_cert : 0;
break;
case MYSQL_OPT_SSL_KEY:
*((char **)arg)= mysql->options.ssl_key;

View File

@@ -1357,7 +1357,7 @@ static int my_verify_callback(gnutls_session_t ssl)
CLEAR_CLIENT_ERROR(mysql);
if (!mysql->options.extension->tls_allow_invalid_server_cert)
if ((mysql->options.extension->tls_verify_server_cert))
{
const char *hostname= mysql->host;
@@ -1371,22 +1371,10 @@ static int my_verify_callback(gnutls_session_t ssl)
{
gnutls_datum_t out;
int type;
if (status & GNUTLS_CERT_SIGNER_NOT_FOUND)
{
/* accept self signed certificates if we don't have to verify server cert */
if (mysql->options.extension->tls_allow_invalid_server_cert)
return 0;
/* postpone the error for self signed certificates if CA isn't set */
if (!mysql->options.ssl_ca && !mysql->options.ssl_capath)
{
type= gnutls_certificate_type_get(ssl);
gnutls_certificate_verification_status_print(status, type, &out, 0);
mysql->net.tls_self_signed_error= (char*)out.data;
return 0;
}
}
/* accept self signed certificates if we don't have to verify server cert */
if (!(mysql->options.extension->tls_verify_server_cert) &&
(status & GNUTLS_CERT_SIGNER_NOT_FOUND))
return 0;
/* gnutls default error message "certificate validation failed" isn't very
descriptive, so we provide more information about the error here */
@@ -1403,43 +1391,18 @@ static int my_verify_callback(gnutls_session_t ssl)
return 0;
}
unsigned int ma_tls_get_finger_print(MARIADB_TLS *ctls, uint hash_type, char *fp, unsigned int len)
unsigned int ma_tls_get_finger_print(MARIADB_TLS *ctls, char *fp, unsigned int len)
{
MYSQL *mysql;
size_t fp_len= len;
const gnutls_datum_t *cert_list;
unsigned int cert_list_size;
gnutls_digest_algorithm_t hash_alg;
if (!ctls || !ctls->ssl)
return 0;
mysql= (MYSQL *)gnutls_session_get_ptr(ctls->ssl);
switch (hash_type)
{
case MA_HASH_SHA1:
hash_alg = GNUTLS_DIG_SHA1;
break;
case MA_HASH_SHA224:
hash_alg = GNUTLS_DIG_SHA224;
break;
case MA_HASH_SHA256:
hash_alg = GNUTLS_DIG_SHA256;
break;
case MA_HASH_SHA384:
hash_alg = GNUTLS_DIG_SHA384;
break;
case MA_HASH_SHA512:
hash_alg = GNUTLS_DIG_SHA512;
break;
default:
my_set_error(mysql, CR_SSL_CONNECTION_ERROR, SQLSTATE_UNKNOWN,
ER(CR_SSL_CONNECTION_ERROR),
"Cannot detect hash algorithm for fingerprint verification");
return 0;
}
cert_list = gnutls_certificate_get_peers (ctls->ssl, &cert_list_size);
if (cert_list == NULL)
{
@@ -1449,7 +1412,7 @@ unsigned int ma_tls_get_finger_print(MARIADB_TLS *ctls, uint hash_type, char *fp
return 0;
}
if (gnutls_fingerprint(hash_alg, &cert_list[0], fp, &fp_len) == 0)
if (gnutls_fingerprint(GNUTLS_DIG_SHA1, &cert_list[0], fp, &fp_len) == 0)
return fp_len;
else
{

View File

@@ -34,6 +34,8 @@ static gnutls_digest_algorithm_t ma_hash_get_algorithm(unsigned int alg)
return GNUTLS_DIG_SHA384;
case MA_HASH_SHA512:
return GNUTLS_DIG_SHA512;
case MA_HASH_RIPEMD160:
return GNUTLS_DIG_RMD160;
default:
return GNUTLS_DIG_UNKNOWN;
}

View File

@@ -526,13 +526,6 @@ my_bool ma_schannel_verify_certs(MARIADB_TLS *ctls, BOOL verify_server_name)
end:
if (!ret)
{
/* postpone the error for self signed certificates if CA isn't set */
if (status == CERT_E_UNTRUSTEDROOT && !ca_file && !ca_path)
{
mysql->net.tls_self_signed_error= strdup(errmsg);
ret= 1;
}
else
pvio->set_error(mysql, CR_SSL_CONNECTION_ERROR, SQLSTATE_UNKNOWN, 0, errmsg);
}
if (pServerCert)

View File

@@ -28,7 +28,6 @@
#include <ma_common.h>
#include <ma_pvio.h>
#include <errmsg.h>
#include <ma_hash.h>
#include <wincrypt.h>
@@ -36,7 +35,6 @@
#include <security.h>
#include <ma_crypt.h>
#include <schnlsp.h>
#undef SECURITY_WIN32
@@ -59,7 +57,7 @@ struct st_schannel {
DWORD IoBufferSize;
SecPkgContext_StreamSizes Sizes;
CtxtHandle hCtxt;
BCRYPT_ALG_HANDLE HashProv[MA_MAX_HASH_SIZE];
/* Cached data from the last read/decrypt call.*/
SecBuffer extraBuf; /* encrypted data read from server. */
SecBuffer dataBuf; /* decrypted but still unread data from server.*/

View File

@@ -29,7 +29,6 @@
#include <openssl/err.h> /* error reporting */
#include <openssl/conf.h>
#include <openssl/md4.h>
#include <ma_tls.h>
#if defined(_WIN32) && !defined(_OPENSSL_Applink) && defined(HAVE_OPENSSL_APPLINK_C)
#include <openssl/applink.c>
@@ -506,15 +505,11 @@ my_bool ma_tls_connect(MARIADB_TLS *ctls)
/* In case handshake failed or if a root certificate (ca) was specified,
we need to check the result code of X509 verification. A detailed check
of the peer certificate (hostname checking will follow later) */
if (rc != 1 || !mysql->options.extension->tls_allow_invalid_server_cert ||
if (rc != 1 || mysql->options.extension->tls_verify_server_cert ||
mysql->options.ssl_ca || mysql->options.ssl_capath)
{
long x509_err= SSL_get_verify_result(ssl);
if ((x509_err == X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT ||
x509_err == X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN) && rc == 1 &&
!mysql->options.ssl_ca && !mysql->options.ssl_capath)
mysql->net.tls_self_signed_error= X509_verify_cert_error_string(x509_err);
else if (x509_err != X509_V_OK)
if (x509_err != X509_V_OK)
{
my_set_error(mysql, CR_SSL_CONNECTION_ERROR, SQLSTATE_UNKNOWN,
ER(CR_SSL_CONNECTION_ERROR), X509_verify_cert_error_string(x509_err));
@@ -734,49 +729,16 @@ const char *ma_tls_get_cipher(MARIADB_TLS *ctls)
return SSL_get_cipher_name(ctls->ssl);
}
unsigned int ma_tls_get_finger_print(MARIADB_TLS *ctls, uint hash_type, char *fp, unsigned int len)
unsigned int ma_tls_get_finger_print(MARIADB_TLS *ctls, char *fp, unsigned int len)
{
X509 *cert= NULL;
MYSQL *mysql;
unsigned int fp_len;
const EVP_MD *hash_alg;
if (!ctls || !ctls->ssl)
return 0;
mysql = SSL_get_app_data(ctls->ssl);
if (len < EVP_MAX_MD_SIZE)
{
my_set_error(mysql, CR_SSL_CONNECTION_ERROR, SQLSTATE_UNKNOWN,
ER(CR_SSL_CONNECTION_ERROR),
"Finger print buffer too small");
return 0;
}
switch (hash_type)
{
case MA_HASH_SHA1:
hash_alg = EVP_sha1();
break;
case MA_HASH_SHA224:
hash_alg = EVP_sha224();
break;
case MA_HASH_SHA256:
hash_alg = EVP_sha256();
break;
case MA_HASH_SHA384:
hash_alg = EVP_sha384();
break;
case MA_HASH_SHA512:
hash_alg = EVP_sha512();
break;
default:
my_set_error(mysql, CR_SSL_CONNECTION_ERROR, SQLSTATE_UNKNOWN,
ER(CR_SSL_CONNECTION_ERROR),
"Cannot detect hash algorithm for fingerprint verification");
return 0;
}
mysql= SSL_get_app_data(ctls->ssl);
if (!(cert= SSL_get_peer_certificate(ctls->ssl)))
{
@@ -786,7 +748,14 @@ unsigned int ma_tls_get_finger_print(MARIADB_TLS *ctls, uint hash_type, char *fp
goto end;
}
if (!X509_digest(cert, hash_alg, (unsigned char *)fp, &fp_len))
if (len < EVP_MAX_MD_SIZE)
{
my_set_error(mysql, CR_SSL_CONNECTION_ERROR, SQLSTATE_UNKNOWN,
ER(CR_SSL_CONNECTION_ERROR),
"Finger print buffer too small");
goto end;
}
if (!X509_digest(cert, EVP_sha1(), (unsigned char *)fp, &fp_len))
{
my_set_error(mysql, CR_SSL_CONNECTION_ERROR, SQLSTATE_UNKNOWN,
ER(CR_SSL_CONNECTION_ERROR),

View File

@@ -36,6 +36,8 @@ static const EVP_MD *ma_hash_get_algorithm(unsigned int alg)
return EVP_sha384();
case MA_HASH_SHA512:
return EVP_sha512();
case MA_HASH_RIPEMD160:
return EVP_ripemd160();
default:
return NULL;
}

View File

@@ -20,9 +20,6 @@
#include "ma_schannel.h"
#include "schannel_certs.h"
#include <string.h>
#include <ma_crypt.h>
#include <wincrypt.h>
#include <bcrypt.h>
extern my_bool ma_tls_initialized;
char tls_library_version[] = "Schannel";
@@ -451,11 +448,11 @@ my_bool ma_tls_connect(MARIADB_TLS *ctls)
goto end;
verify_certs = mysql->options.ssl_ca || mysql->options.ssl_capath ||
!mysql->options.extension->tls_allow_invalid_server_cert;
(mysql->options.extension->tls_verify_server_cert);
if (verify_certs)
{
if (!ma_schannel_verify_certs(ctls, !mysql->options.extension->tls_allow_invalid_server_cert))
if (!ma_schannel_verify_certs(ctls, mysql->options.extension->tls_verify_server_cert))
goto end;
}
@@ -553,33 +550,15 @@ const char *ma_tls_get_cipher(MARIADB_TLS *ctls)
return cipher_name(&CipherInfo);
}
unsigned int ma_tls_get_finger_print(MARIADB_TLS *ctls, uint hash_type, char *fp, unsigned int len)
unsigned int ma_tls_get_finger_print(MARIADB_TLS *ctls, char *fp, unsigned int len)
{
MA_HASH_CTX* hash_ctx;
SC_CTX *sctx= (SC_CTX *)ctls->ssl;
PCCERT_CONTEXT pRemoteCertContext = NULL;
int rc= 0;
if (hash_type == MA_HASH_SHA224)
{
MYSQL *mysql = ctls->pvio->mysql;
my_set_error(mysql, CR_SSL_CONNECTION_ERROR, SQLSTATE_UNKNOWN,
ER(CR_SSL_CONNECTION_ERROR),
"SHA224 hash for fingerprint verification is not supported in Schannel");
return 0;
}
if (QueryContextAttributes(&sctx->hCtxt, SECPKG_ATTR_REMOTE_CERT_CONTEXT, (PVOID)&pRemoteCertContext) != SEC_E_OK)
return 0;
hash_ctx = ma_hash_new(hash_type);
ma_hash_input(hash_ctx, pRemoteCertContext->pbCertEncoded, pRemoteCertContext->cbCertEncoded);
ma_hash_result(hash_ctx, fp);
ma_hash_free(hash_ctx);
CertGetCertificateContextProperty(pRemoteCertContext, CERT_HASH_PROP_ID, fp, (DWORD *)&len);
CertFreeCertificateContext(pRemoteCertContext);
return (uint)ma_hash_digest_size(hash_type);
return len;
}
void ma_tls_set_connection(MYSQL *mysql __attribute__((unused)))

View File

@@ -117,6 +117,5 @@ struct st_mysql_client_plugin_AUTHENTICATION _mysql_client_plugin_declaration_ =
NULL,
NULL,
NULL,
gssapi_auth_client,
NULL
gssapi_auth_client
};

View File

@@ -145,8 +145,7 @@ struct st_mysql_client_plugin_AUTHENTICATION _mysql_client_plugin_declaration_ =
auth_caching_sha2_init,
auth_caching_sha2_deinit,
NULL,
auth_caching_sha2_client,
NULL
auth_caching_sha2_client
};
#ifdef HAVE_WINCRYPT

View File

@@ -58,8 +58,7 @@ struct st_mysql_client_plugin_AUTHENTICATION _mysql_client_plugin_declaration_ =
auth_dialog_init,
NULL,
NULL,
auth_dialog_open,
NULL
auth_dialog_open
};

View File

@@ -64,7 +64,6 @@ static int auth_ed25519_init(char *unused1,
size_t unused2,
int unused3,
va_list);
static int auth_ed25519_hash(MYSQL *, unsigned char *out, size_t *outlen);
#ifndef PLUGIN_DYNAMIC
@@ -78,24 +77,21 @@ struct st_mysql_client_plugin_AUTHENTICATION _mysql_client_plugin_declaration_ =
"client_ed25519",
"Sergei Golubchik, Georg Richter",
"Ed25519 Authentication Plugin",
{0,1,1},
{0,1,0},
"LGPL",
NULL,
auth_ed25519_init,
auth_ed25519_deinit,
NULL,
auth_ed25519_client,
auth_ed25519_hash
auth_ed25519_client
};
static int auth_ed25519_client(MYSQL_PLUGIN_VIO *vio, MYSQL *mysql)
{
unsigned char *packet,
signature[CRYPTO_BYTES + NONCE_BYTES],
pk[CRYPTO_PUBLICKEYBYTES];
unsigned long long pkt_len, pwlen= strlen(mysql->passwd);
char *newpw;
signature[CRYPTO_BYTES + NONCE_BYTES];
int pkt_len;
/*
Step 1: Server sends nonce
@@ -110,36 +106,16 @@ static int auth_ed25519_client(MYSQL_PLUGIN_VIO *vio, MYSQL *mysql)
return CR_SERVER_HANDSHAKE_ERR;
/* Sign nonce: the crypto_sign function is part of ref10 */
ma_crypto_sign(signature, pk, packet, NONCE_BYTES, (unsigned char*)mysql->passwd, pwlen);
ma_crypto_sign(signature, packet, NONCE_BYTES, (unsigned char*)mysql->passwd, strlen(mysql->passwd));
/* send signature to server */
if (vio->write_packet(vio, signature, CRYPTO_BYTES))
return CR_ERROR;
/* save pk for the future auth_ed25519_hash() call */
if ((newpw= realloc(mysql->passwd, pwlen + 1 + sizeof(pk))))
{
memcpy(newpw + pwlen + 1, pk, sizeof(pk));
mysql->passwd= newpw;
}
return CR_OK;
}
/* }}} */
/* {{{ static int auth_ed25519_hash */
static int auth_ed25519_hash(MYSQL *mysql, unsigned char *out, size_t *outlen)
{
if (*outlen < CRYPTO_PUBLICKEYBYTES)
return 1;
*outlen= CRYPTO_PUBLICKEYBYTES;
/* use the cached value */
memcpy(out, mysql->passwd + strlen(mysql->passwd) + 1, CRYPTO_PUBLICKEYBYTES);
return 0;
}
/* }}} */
/* {{{ static int auth_ed25519_init */
static int auth_ed25519_init(char *unused1 __attribute__((unused)),
size_t unused2 __attribute__((unused)),

View File

@@ -70,8 +70,7 @@ struct st_mysql_client_plugin_AUTHENTICATION _mysql_client_plugin_declaration_ =
NULL,
NULL,
NULL,
clear_password_auth_client,
NULL
clear_password_auth_client
};

View File

@@ -3,29 +3,17 @@
#include <errmsg.h>
#include <string.h>
#include <ma_common.h>
#include <ma_crypt.h>
#include <mysql/client_plugin.h>
typedef struct st_mysql_client_plugin_AUTHENTICATION auth_plugin_t;
static int client_mpvio_write_packet(struct st_plugin_vio*, const uchar*, size_t);
static int native_password_auth_client(MYSQL_PLUGIN_VIO *vio, MYSQL *mysql);
static int native_password_hash(MYSQL *mysql, unsigned char *out, size_t *outlen);
static int dummy_fallback_auth_client(MYSQL_PLUGIN_VIO *vio, MYSQL *mysql __attribute__((unused)));
extern void read_user_name(char *name);
extern char *ma_send_connect_attr(MYSQL *mysql, unsigned char *buffer);
extern int ma_read_ok_packet(MYSQL *mysql, uchar *pos, ulong length);
extern unsigned char *mysql_net_store_length(unsigned char *packet, ulonglong length);
#define hashing(p) (p->interface_version >= 0x0101 && p->hash_password_bin)
static int set_error_from_tls_self_signed_error(MYSQL *mysql)
{
my_set_error(mysql, CR_SSL_CONNECTION_ERROR, SQLSTATE_UNKNOWN,
ER(CR_SSL_CONNECTION_ERROR), mysql->net.tls_self_signed_error);
reset_tls_self_signed_error(mysql);
return 1;
}
typedef struct {
int (*read_packet)(struct st_plugin_vio *vio, uchar **buf);
int (*write_packet)(struct st_plugin_vio *vio, const uchar *pkt, size_t pkt_len);
@@ -56,14 +44,13 @@ auth_plugin_t mysql_native_password_client_plugin=
native_password_plugin_name,
"R.J.Silk, Sergei Golubchik",
"Native MySQL authentication",
{1, 0, 1},
{1, 0, 0},
"LGPL",
NULL,
NULL,
NULL,
NULL,
native_password_auth_client,
native_password_hash
native_password_auth_client
};
@@ -110,22 +97,6 @@ static int native_password_auth_client(MYSQL_PLUGIN_VIO *vio, MYSQL *mysql)
return CR_OK;
}
static int native_password_hash(MYSQL *mysql, unsigned char *out, size_t *out_length)
{
unsigned char digest[MA_SHA1_HASH_SIZE];
if (*out_length < MA_SHA1_HASH_SIZE)
return 1;
*out_length= MA_SHA1_HASH_SIZE;
/* would it be better to reuse instead of recalculating here? see ed25519 */
ma_hash(MA_HASH_SHA1, (unsigned char*)mysql->passwd, strlen(mysql->passwd),
digest);
ma_hash(MA_HASH_SHA1, digest, sizeof(digest), out);
return 0;
}
auth_plugin_t dummy_fallback_client_plugin=
{
MYSQL_CLIENT_AUTHENTICATION_PLUGIN,
@@ -139,8 +110,7 @@ auth_plugin_t dummy_fallback_client_plugin=
NULL,
NULL,
NULL,
dummy_fallback_auth_client,
NULL
dummy_fallback_auth_client
};
@@ -253,7 +223,7 @@ static int send_client_reply_packet(MCPVIO_EXT *mpvio,
if (mysql->options.ssl_key || mysql->options.ssl_cert ||
mysql->options.ssl_ca || mysql->options.ssl_capath ||
mysql->options.ssl_cipher || mysql->options.use_ssl ||
!mysql->options.extension->tls_allow_invalid_server_cert)
mysql->options.extension->tls_verify_server_cert)
mysql->options.use_ssl= 1;
if (mysql->options.use_ssl)
mysql->client_flag|= CLIENT_SSL;
@@ -273,16 +243,15 @@ static int send_client_reply_packet(MCPVIO_EXT *mpvio,
mysql->net.pvio->type == PVIO_TYPE_SHAREDMEM))
{
mysql->server_capabilities &= ~(CLIENT_SSL);
mysql->options.extension->tls_allow_invalid_server_cert= 1;
}
/* if server doesn't support SSL and verification of server certificate
was set to mandatory, we need to return an error */
if (mysql->options.use_ssl && !(mysql->server_capabilities & CLIENT_SSL))
{
if (!mysql->options.extension->tls_allow_invalid_server_cert ||
mysql->options.extension->tls_fp ||
mysql->options.extension->tls_fp_list)
if (mysql->options.extension->tls_verify_server_cert ||
(mysql->options.extension && (mysql->options.extension->tls_fp ||
mysql->options.extension->tls_fp_list)))
{
my_set_error(mysql, CR_SSL_CONNECTION_ERROR, SQLSTATE_UNKNOWN,
ER(CR_SSL_CONNECTION_ERROR),
@@ -381,13 +350,6 @@ static int send_client_reply_packet(MCPVIO_EXT *mpvio,
}
if (ma_pvio_start_ssl(mysql->net.pvio))
goto error;
if (mysql->net.tls_self_signed_error &&
(!mysql->passwd || !mysql->passwd[0] || !hashing(mpvio->plugin)))
{
/* cannot use auth to validate the cert */
set_error_from_tls_self_signed_error(mysql);
goto error;
}
}
#endif /* HAVE_TLS */
@@ -765,62 +727,15 @@ retry:
auth_plugin_name, MYSQL_CLIENT_AUTHENTICATION_PLUGIN)))
auth_plugin= &dummy_fallback_client_plugin;
/* can we use this plugin with this tls server cert ? */
if (mysql->net.tls_self_signed_error && !hashing(auth_plugin))
return set_error_from_tls_self_signed_error(mysql);
goto retry;
}
/*
net->read_pos[0] should always be 0 here if the server implements
the protocol correctly
*/
if (mysql->net.read_pos[0] != 0)
return 1;
if (ma_read_ok_packet(mysql, mysql->net.read_pos + 1, pkt_length))
return -1;
if (!mysql->net.tls_self_signed_error)
return 0;
assert(mysql->options.use_ssl);
assert(!mysql->options.extension->tls_allow_invalid_server_cert);
assert(!mysql->options.ssl_ca);
assert(!mysql->options.ssl_capath);
assert(!mysql->options.extension->tls_fp);
assert(!mysql->options.extension->tls_fp_list);
assert(hashing(auth_plugin));
assert(mysql->passwd[0]);
if (mysql->info && mysql->info[0] == '\1')
{
MA_HASH_CTX *ctx = NULL;
unsigned char buf[1024], digest[MA_SHA256_HASH_SIZE];
char fp[128], hexdigest[sizeof(digest)*2+1], *hexsig= mysql->info + 1;
size_t buflen= sizeof(buf) - 1, fplen;
mysql->info= NULL; /* no need to confuse the client with binary info */
if (!(fplen= ma_tls_get_finger_print(mysql->net.pvio->ctls, MA_HASH_SHA256,
fp, sizeof(fp))))
return 1; /* error is already set */
if (auth_plugin->hash_password_bin(mysql, buf, &buflen) ||
!(ctx= ma_hash_new(MA_HASH_SHA256)))
{
SET_CLIENT_ERROR(mysql, CR_OUT_OF_MEMORY, SQLSTATE_UNKNOWN, 0);
return 1;
}
ma_hash_input(ctx, (unsigned char*)buf, buflen);
ma_hash_input(ctx, (unsigned char*)mysql->scramble_buff, SCRAMBLE_LENGTH);
ma_hash_input(ctx, (unsigned char*)fp, fplen);
ma_hash_result(ctx, digest);
ma_hash_free(ctx);
mysql_hex_string(hexdigest, (char*)digest, sizeof(digest));
if (strcmp(hexdigest, hexsig) == 0)
return 0; /* phew. self-signed certificate is validated! */
}
return set_error_from_tls_self_signed_error(mysql);
if (mysql->net.read_pos[0] == 0)
return ma_read_ok_packet(mysql, mysql->net.read_pos + 1, pkt_length);
return 1;
}

View File

@@ -63,8 +63,7 @@ struct st_mysql_client_plugin_AUTHENTICATION _mysql_client_plugin_declaration_ =
NULL,
NULL,
NULL,
auth_old_password,
NULL
auth_old_password
};
/**

View File

@@ -3,7 +3,7 @@ int crypto_sign_keypair(
unsigned char *pw, unsigned long long pwlen
);
int ma_crypto_sign(
unsigned char *sm, unsigned char *pk,
unsigned char *sm,
const unsigned char *m, unsigned long long mlen,
const unsigned char *pw, unsigned long long pwlen
);

View File

@@ -5,7 +5,7 @@
#include "sc.h"
int ma_crypto_sign(
unsigned char *sm, unsigned char *pk,
unsigned char *sm,
const unsigned char *m,unsigned long long mlen,
const unsigned char *pw,unsigned long long pwlen
)
@@ -26,7 +26,6 @@ int ma_crypto_sign(
ge_scalarmult_base(&A,az);
ge_p3_tobytes(sm + 32,&A);
memmove(pk, sm + 32, 32);
sc_reduce(nonce);
ge_scalarmult_base(&R,nonce);

View File

@@ -76,8 +76,7 @@ struct st_mysql_client_plugin_AUTHENTICATION _mysql_client_plugin_declaration_ =
auth_sha256_init,
NULL,
NULL,
auth_sha256_client,
NULL
auth_sha256_client
};
#ifdef HAVE_WINCRYPT

View File

@@ -686,7 +686,6 @@ int test_connection_timeout2(MYSQL *unused __attribute__((unused)))
unsigned int timeout= 5;
time_t start, elapsed;
MYSQL *mysql;
my_bool no= 0;
SKIP_SKYSQL;
SKIP_MAXSCALE;
@@ -695,7 +694,6 @@ int test_connection_timeout2(MYSQL *unused __attribute__((unused)))
mysql= mysql_init(NULL);
mysql_options(mysql, MYSQL_OPT_CONNECT_TIMEOUT, (unsigned int *)&timeout);
mysql_options(mysql, MYSQL_INIT_COMMAND, "set @a:=SLEEP(7)");
mysql_options(mysql, MYSQL_OPT_SSL_VERIFY_SERVER_CERT, &no);
start= time(NULL);
if (my_test_connect(mysql, hostname, username, password, schema, port, socketname, CLIENT_REMEMBER_OPTIONS))
{