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

Fixed gnutls support

This commit is contained in:
Georg Richter
2015-08-13 14:01:33 +02:00
parent f2955a4b39
commit 23895fbd4f
17 changed files with 390 additions and 196 deletions

View File

@@ -152,8 +152,7 @@ IF(WITH_SSL STREQUAL "OPENSSL")
FIND_PACKAGE(OpenSSL) FIND_PACKAGE(OpenSSL)
IF(OPENSSL_FOUND) IF(OPENSSL_FOUND)
ADD_DEFINITIONS(-DHAVE_OPENSSL -DHAVE_SSL) ADD_DEFINITIONS(-DHAVE_OPENSSL -DHAVE_SSL)
ADD_DEFINITIONS(-DSSL_PLUGIN=cio_openssl_plugin) SET(SSL_SOURCES "${CMAKE_SOURCE_DIR}/libmariadb/secure/openssl.c")
SET(SSL_SOURCES "${CMAKE_SOURCE_DIR}/plugins/builtin/cio_openssl.c")
SET(SSL_LIBRARIES ${OPENSSL_LIBRARIES} ${OPENSSL_CRYPTO_LIBRARIES}) SET(SSL_LIBRARIES ${OPENSSL_LIBRARIES} ${OPENSSL_CRYPTO_LIBRARIES})
ELSE() ELSE()
MESSAGE(FATAL "OpenSSL not found") MESSAGE(FATAL "OpenSSL not found")
@@ -162,24 +161,23 @@ ENDIF()
IF(WITH_SSL STREQUAL "GNUTLS") IF(WITH_SSL STREQUAL "GNUTLS")
FIND_PACKAGE(GnuTLS) FIND_PACKAGE(GnuTLS)
IF(GNUTLS_FOUND) IF(GNUTLS_FOUND)
ADD_DEFINITIONS(-DSSL_PLUGIN=cio_gnutls_plugin)
ADD_DEFINITIONS(-DHAVE_GNUTLS -DHAVE_SSL) ADD_DEFINITIONS(-DHAVE_GNUTLS -DHAVE_SSL)
SET(SSL_SOURCES "${CMAKE_SOURCE_DIR}/plugins/builtin/cio_gnutls.c") SET(SSL_SOURCES "${CMAKE_SOURCE_DIR}/libmariadb/secure/gnutls.c")
SET(SSL_LIBRARIES ${GNUTLS_LIBRARIES}) SET(SSL_LIBRARIES ${GNUTLS_LIBRARY})
ELSE() ELSE()
MESSAGE(FATAL "GnuTLS not found") MESSAGE(FATAL "GnuTLS not found")
ENDIF() ENDIF()
ENDIF() ENDIF()
IF(WIN32) IF(WIN32)
IF(WITH_SSL STREQUAL "SCHANNEL") IF(WITH_SSL STREQUAL "SCHANNEL")
ADD_DEFINITIONS(-DSSL_PLUGIN=cio_schannel_plugin)
MESSAGE(STATUS "SSL_TYPE ${SSL_TYPE}") MESSAGE(STATUS "SSL_TYPE ${SSL_TYPE}")
ADD_DEFINITIONS(-DHAVE_SCHANNEL -DHAVE_SSL) ADD_DEFINITIONS(-DHAVE_SCHANNEL -DHAVE_SSL)
SET(SSL_SOURCES "${CMAKE_SOURCE_DIR}/plugins/builtin/cio_schannel.c" "${CMAKE_SOURCE_DIR}/plugins/builtin/ma_schannel.c") SET(SSL_SOURCES "${CMAKE_SOURCE_DIR}/libmariadb/secure/schannel.c" "${CMAKE_SOURCE_DIR}/libmariadb/secure/ma_schannel.c")
INCLUDE_DIRECTORIES("${CMAKE_SOURCE_DIR}/plugins/cio/") INCLUDE_DIRECTORIES("${CMAKE_SOURCE_DIR}/plugins/cio/")
ENDIF() ENDIF()
ENDIF() ENDIF()
MARK_AS_ADVANCED(SSL_SOURCES)
IF(WITH_SQLITE) IF(WITH_SQLITE)
@@ -206,7 +204,7 @@ IF(WIN32)
ELSE() ELSE()
SET(SYSTEM_LIBS ${LIBPTHREAD} ${LIBDL} ${LIBM} ${LIBICONV}) SET(SYSTEM_LIBS ${LIBPTHREAD} ${LIBDL} ${LIBM} ${LIBICONV})
ENDIF() ENDIF()
IF(OPENSSL_FOUND) IF(WITH_SSL)
SET(SYSTEM_LIBS ${SYSTEM_LIBS} ${SSL_LIBRARIES}) SET(SYSTEM_LIBS ${SYSTEM_LIBS} ${SSL_LIBRARIES})
ENDIF() ENDIF()
@@ -291,7 +289,7 @@ MESSAGE(STATUS "CPack generation: ${CPACK_GENERATOR}")
IF(CLIENT_DOCS) IF(CLIENT_DOCS)
MESSAGE(STATUS "Documentation included from ${CLIENT_DOCS}") MESSAGE(STATUS "Documentation included from ${CLIENT_DOCS}")
ENDIF() ENDIF()
MESSAGE(STATUS "SSL support: ${WITH_SSL} Sources: ${SSL_SOURCES}") MESSAGE(STATUS "SSL support: ${WITH_SSL} Libs: ${SSL_LIBRARIES}")
MESSAGE(STATUS "Experimental Sqlite support: ${WITH_SQLITE}") MESSAGE(STATUS "Experimental Sqlite support: ${WITH_SQLITE}")
IF(WITH_EXTERNAL_ZLIB) IF(WITH_EXTERNAL_ZLIB)
MESSAGE(STATUS "Zlib support: ${WITH_EXTERNAL_ZLIB}") MESSAGE(STATUS "Zlib support: ${WITH_EXTERNAL_ZLIB}")

View File

@@ -1,10 +1,6 @@
#ifndef _ma_ssl_h_ #ifndef _ma_ssl_h_
#define _ma_ssl_h_ #define _ma_ssl_h_
struct st_ma_cio_ssl_methods;
typedef struct st_ma_cio_ssl_methods CIO_SSL_METHODS;
extern int ssl_default_plugin;
enum enum_cio_ssl_type { enum enum_cio_ssl_type {
SSL_TYPE_DEFAULT=0, SSL_TYPE_DEFAULT=0,
#ifdef _WIN32 #ifdef _WIN32
@@ -16,23 +12,117 @@ enum enum_cio_ssl_type {
typedef struct st_ma_cio_ssl { typedef struct st_ma_cio_ssl {
void *data; void *data;
enum enum_cio_ssl_type type;
MARIADB_CIO *cio; MARIADB_CIO *cio;
CIO_SSL_METHODS *methods;
void *ssl; void *ssl;
} MARIADB_SSL; } MARIADB_SSL;
struct st_ma_cio_ssl_methods /* Function prototypes */
{
void *(*init)(MARIADB_SSL *cssl, MYSQL *mysql); /* ma_ssl_start
my_bool (*connect)(MARIADB_SSL *cssl); initializes the ssl library
size_t (*read)(MARIADB_SSL *cssl, const uchar* buffer, size_t length); Parameter:
size_t (*write)(MARIADB_SSL *cssl, const uchar* buffer, size_t length); errmsg pointer to error message buffer
my_bool (*close)(MARIADB_SSL *cssl); errmsg_len length of error message buffer
int (*verify_server_cert)(MARIADB_SSL *ssl); Returns:
const char *(*cipher)(MARIADB_SSL *ssl); 0 success
my_bool (*check_fp)(MARIADB_SSL *cssl, const char *fp); 1 if an error occured
}; Notes:
On success the global variable ma_ssl_initialized will be set to 1
*/
int ma_ssl_start(char *errmsg, size_t errmsg_len);
/* ma_ssl_end
unloads/deinitializes ssl library and unsets global variable
ma_ssl_initialized
*/
void ma_ssl_end(void);
/* ma_ssl_init
creates a new SSL structure for a SSL connection and loads
client certificates
Parameters:
MYSQL a mysql structure
Returns:
void * a pointer to internal SSL structure
*/
void * ma_ssl_init(MYSQL *mysql);
/* ma_ssl_connect
performs SSL handshake
Parameters:
MARIADB_SSL MariaDB SSL container
Returns:
0 success
1 error
*/
my_bool ma_ssl_connect(MARIADB_SSL *cssl);
/* ma_ssl_read
reads up to length bytes from socket
Parameters:
cssl MariaDB SSL container
buffer read buffer
length buffer length
Returns:
0-n bytes read
-1 if an error occured
*/
size_t ma_ssl_read(MARIADB_SSL *cssl, const uchar* buffer, size_t length);
/* ma_ssl_write
write buffer to socket
Parameters:
cssl MariaDB SSL container
buffer write buffer
length buffer length
Returns:
0-n bytes written
-1 if an error occured
*/
size_t ma_ssl_write(MARIADB_SSL *cssl, const uchar* buffer, size_t length);
/* ma_ssl_close
closes SSL connection and frees SSL structure which was previously
created by ma_ssl_init call
Parameters:
MARIADB_SSL MariaDB SSL container
Returns:
0 success
1 error
*/
my_bool ma_ssl_close(MARIADB_SSL *cssl);
/* ma_ssl_verify_server_cert
validation check of server certificate
Parameter:
MARIADB_SSL MariaDB SSL container
Returns:
ß success
1 error
*/
int ma_ssl_verify_server_cert(MARIADB_SSL *cssl);
/* ma_ssl_get_cipher
returns cipher for current ssl connection
Parameter:
MARIADB_SSL MariaDB SSL container
Returns:
cipher in use or
NULL on error
*/
const char *ma_ssl_get_cipher(MARIADB_SSL *ssl);
/* ma_ssl_get_finger_print
returns SHA1 finger print of server certificate
Parameter:
MARIADB_SSL MariaDB SSL container
fp buffer for fingerprint
fp_len buffer length
Returns:
actual size of finger print
*/
unsigned int ma_ssl_get_finger_print(MARIADB_SSL *cssl, unsigned char *fp, unsigned int fp_len);
/* Function prototypes */ /* Function prototypes */
MARIADB_SSL *ma_cio_ssl_init(MYSQL *mysql); MARIADB_SSL *ma_cio_ssl_init(MYSQL *mysql);
@@ -42,6 +132,6 @@ size_t ma_cio_ssl_write(MARIADB_SSL *cssl, const uchar *buffer, size_t length);
my_bool ma_cio_ssl_close(MARIADB_SSL *cssl); my_bool ma_cio_ssl_close(MARIADB_SSL *cssl);
int ma_cio_ssl_verify_server_cert(MARIADB_SSL *cssl); int ma_cio_ssl_verify_server_cert(MARIADB_SSL *cssl);
const char *ma_cio_ssl_cipher(MARIADB_SSL *cssl); const char *ma_cio_ssl_cipher(MARIADB_SSL *cssl);
my_bool ma_cio_ssl_check_fp(MARIADB_SSL *cssl, const char *fp, size_t length); my_bool ma_cio_ssl_check_fp(MARIADB_SSL *cssl, const char *fp, const char *fp_list);
#endif /* _ma_ssl_h_ */ #endif /* _ma_ssl_h_ */

View File

@@ -325,11 +325,10 @@ client_plugin.c
ma_io.c ma_io.c
${CMAKE_SOURCE_DIR}/plugins/builtin/my_auth.c ${CMAKE_SOURCE_DIR}/plugins/builtin/my_auth.c
${CMAKE_SOURCE_DIR}/plugins/builtin/cio_socket.c ${CMAKE_SOURCE_DIR}/plugins/builtin/cio_socket.c
${SSL_SOURCES}
) )
IF(SSL_SOURCES) MESSAGE(STATUS "${LIBMARIADB_SOURCES}")
SET(LIBMARIADB_SOURCES ${LIBMARIADB_SOURCES} ${SSL_SOURCES})
ENDIF()
IF(WIN32) IF(WIN32)
INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/win-iconv) INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/win-iconv)

View File

@@ -84,18 +84,12 @@ extern struct st_mysql_client_plugin old_password_client_plugin;
extern struct st_mysql_client_plugin native_password_client_plugin; extern struct st_mysql_client_plugin native_password_client_plugin;
extern MARIADB_CIO_PLUGIN cio_socket_plugin; extern MARIADB_CIO_PLUGIN cio_socket_plugin;
#ifdef HAVE_SSL
extern MARIADB_CIO_PLUGIN SSL_PLUGIN;
#endif
struct st_mysql_client_plugin *mysql_client_builtins[]= struct st_mysql_client_plugin *mysql_client_builtins[]=
{ {
(struct st_mysql_client_plugin *)&old_password_client_plugin, (struct st_mysql_client_plugin *)&old_password_client_plugin,
(struct st_mysql_client_plugin *)&native_password_client_plugin, (struct st_mysql_client_plugin *)&native_password_client_plugin,
(struct st_mysql_client_plugin *)&cio_socket_plugin, (struct st_mysql_client_plugin *)&cio_socket_plugin,
#ifdef HAVE_SSL
(struct st_mysql_client_plugin *)&SSL_PLUGIN,
#endif
0 0
}; };

View File

@@ -62,10 +62,10 @@
#define INADDR_NONE -1 #define INADDR_NONE -1
#endif #endif
#include <sha1.h> #include <sha1.h>
#include <ma_cio.h>
#ifndef _WIN32 #ifndef _WIN32
#include <poll.h> #include <poll.h>
#endif #endif
#include <ma_cio.h>
#include <ma_dyncol.h> #include <ma_dyncol.h>
#define ASYNC_CONTEXT_DEFAULT_STACK_SIZE (4096*15) #define ASYNC_CONTEXT_DEFAULT_STACK_SIZE (4096*15)

View File

@@ -116,7 +116,7 @@ MARIADB_CIO *ma_cio_init(MA_CIO_CINFO *cinfo)
cio->methods->set_timeout(cio, CIO_WRITE_TIMEOUT, cinfo->mysql->options.write_timeout); cio->methods->set_timeout(cio, CIO_WRITE_TIMEOUT, cinfo->mysql->options.write_timeout);
} }
if (!(cio->cache= my_malloc(CIO_READ_AHEAD_CACHE_SIZE, MYF(MY_WME)))) if (!(cio->cache= my_malloc(CIO_READ_AHEAD_CACHE_SIZE, MYF(MY_ZEROFILL))))
{ {
CIO_SET_ERROR(cinfo->mysql, CR_OUT_OF_MEMORY, unknown_sqlstate, 0); CIO_SET_ERROR(cinfo->mysql, CR_OUT_OF_MEMORY, unknown_sqlstate, 0);
return NULL; return NULL;
@@ -405,7 +405,9 @@ my_bool ma_cio_start_ssl(MARIADB_CIO *cio)
return 1; return 1;
CLEAR_CLIENT_ERROR(cio->mysql); CLEAR_CLIENT_ERROR(cio->mysql);
if (!(cio->cssl= ma_cio_ssl_init(cio->mysql))) if (!(cio->cssl= ma_cio_ssl_init(cio->mysql)))
{
return 1; return 1;
}
if (ma_cio_ssl_connect(cio->cssl)) if (ma_cio_ssl_connect(cio->cssl))
{ {
my_free((gptr)cio->cssl); my_free((gptr)cio->cssl);
@@ -417,6 +419,16 @@ my_bool ma_cio_start_ssl(MARIADB_CIO *cio)
ma_cio_ssl_verify_server_cert(cio->cssl)) ma_cio_ssl_verify_server_cert(cio->cssl))
return 1; return 1;
if (cio->mysql->options.extension &&
(cio->mysql->options.extension->ssl_fp || cio->mysql->options.extension->ssl_fp_list))
{
if (ma_cio_ssl_check_fp(cio->cssl,
cio->mysql->options.extension->ssl_fp,
cio->mysql->options.extension->ssl_fp_list))
return 1;
}
return 0; return 0;
} }
/* }}} */ /* }}} */

View File

@@ -35,6 +35,7 @@
#include <my_global.h> #include <my_global.h>
#include <my_sys.h> #include <my_sys.h>
#include <ma_common.h> #include <ma_common.h>
#include <string.h>
//#include <ma_secure.h> //#include <ma_secure.h>
#include <errmsg.h> #include <errmsg.h>
#include <ma_cio.h> #include <ma_cio.h>
@@ -47,12 +48,15 @@
*/ */
/* Errors should be handled via cio callback function */ /* Errors should be handled via cio callback function */
my_bool ma_ssl_initialized= FALSE;
MARIADB_SSL *ma_cio_ssl_init(MYSQL *mysql) MARIADB_SSL *ma_cio_ssl_init(MYSQL *mysql)
{ {
MARIADB_CIO_PLUGIN *cio_plugin;
MARIADB_SSL *cssl= NULL; MARIADB_SSL *cssl= NULL;
if (!ma_ssl_initialized)
ma_ssl_start(mysql->net.last_error, MYSQL_ERRMSG_SIZE);
if (!(cssl= (MARIADB_SSL *)my_malloc(sizeof(MARIADB_CIO), if (!(cssl= (MARIADB_SSL *)my_malloc(sizeof(MARIADB_CIO),
MYF(MY_WME | MY_ZEROFILL)))) MYF(MY_WME | MY_ZEROFILL))))
{ {
@@ -60,63 +64,107 @@ MARIADB_SSL *ma_cio_ssl_init(MYSQL *mysql)
} }
/* register error routine and methods */ /* register error routine and methods */
cssl->methods= cio_plugin->ssl_methods;
cssl->cio= mysql->net.cio; cssl->cio= mysql->net.cio;
if (!(cssl->ssl= ma_ssl_init(mysql)))
if (!(cssl->ssl= cssl->methods->init(cssl, mysql)))
{ {
my_free((gptr)cssl); my_free(cssl);
cssl= NULL; cssl= NULL;
} }
return cssl; return cssl;
} }
my_bool ma_cio_ssl_check_fp(MARIADB_SSL *cssl, const char *fp, size_t length)
{
if (cssl && cssl->methods->check_fp)
return cssl->methods->check_fp(cssl, fp);
return 0;
}
my_bool ma_cio_ssl_connect(MARIADB_SSL *cssl) my_bool ma_cio_ssl_connect(MARIADB_SSL *cssl)
{ {
if (cssl && cssl->methods->connect) return ma_ssl_connect(cssl);
return cssl->methods->connect(cssl);
return 1;
} }
size_t ma_cio_ssl_read(MARIADB_SSL *cssl, const uchar* buffer, size_t length) size_t ma_cio_ssl_read(MARIADB_SSL *cssl, const uchar* buffer, size_t length)
{ {
if (cssl && cssl->methods->read) return ma_ssl_read(cssl, buffer, length);
return cssl->methods->read(cssl, buffer, length);
return -1;
} }
size_t ma_cio_ssl_write(MARIADB_SSL *cssl, const uchar* buffer, size_t length) size_t ma_cio_ssl_write(MARIADB_SSL *cssl, const uchar* buffer, size_t length)
{ {
if (cssl && cssl->methods->write) return ma_ssl_write(cssl, buffer, length);
return cssl->methods->write(cssl, buffer, length);
return -1;
} }
my_bool ma_cio_ssl_close(MARIADB_SSL *cssl) my_bool ma_cio_ssl_close(MARIADB_SSL *cssl)
{ {
if (cssl && cssl->methods->close) return ma_ssl_close(cssl);
return cssl->methods->close(cssl);
return 1;
} }
int ma_cio_ssl_verify_server_cert(MARIADB_SSL *cssl) int ma_cio_ssl_verify_server_cert(MARIADB_SSL *cssl)
{ {
if (cssl && cssl->methods->verify_server_cert) return ma_ssl_verify_server_cert(cssl);
return cssl->methods->verify_server_cert(cssl);
return 0;
} }
const char *ma_cio_ssl_cipher(MARIADB_SSL *cssl) const char *ma_cio_ssl_cipher(MARIADB_SSL *cssl)
{ {
if (!cssl && !cssl->methods->cipher) return ma_ssl_get_cipher(cssl);
return NULL; }
return cssl->methods->cipher(cssl);
static my_bool ma_cio_ssl_compare_fp(char *fp1, unsigned int fp1_len,
char *fp2, unsigned int fp2_len)
{
char hexstr[fp1_len * 2 + 1];
fp1_len= (unsigned int)mysql_hex_string(hexstr, fp1, fp1_len);
if (strncasecmp(hexstr, fp2, fp1_len) != 0)
return 1;
return 0;
}
my_bool ma_cio_ssl_check_fp(MARIADB_SSL *cssl, const char *fp, const char *fp_list)
{
unsigned int cert_fp_len= 64;
unsigned char cert_fp[64];
MYSQL *mysql;
my_bool rc=1;
if (ma_ssl_get_finger_print(cssl, cert_fp, cert_fp_len) < 1)
goto end;
if (fp)
rc= ma_cio_ssl_compare_fp(cert_fp, cert_fp_len, fp, strlen(fp));
else if (fp_list)
{
FILE *fp;
char buff[255];
if (!(fp = fopen(fp_list, "r")))
{
/*
my_set_error(mysql, CR_SSL_CONNECTION_ERROR, SQLSTATE_UNKNOWN,
ER(CR_SSL_CONNECTION_ERROR),
"Can't open finger print list");
*/
goto end;
}
while (fgets(buff, sizeof(buff)-1, fp))
{
/* remove trailing new line character */
char *pos= strchr(buff, '\r');
if (!pos)
pos= strchr(buff, '\n');
if (pos)
*pos= '\0';
if (!ma_cio_ssl_compare_fp(cert_fp, cert_fp_len, buff, strlen(buff)))
{
/* finger print is valid: close file and exit */
fclose(fp);
rc= 0;
goto end;
}
}
/* No finger print matched - close file and return error */
fclose(fp);
}
end:
return rc;
} }
#endif /* HAVE_SSL */ #endif /* HAVE_SSL */

View File

@@ -164,7 +164,11 @@ static my_bool net_realloc(NET *net, size_t length)
DBUG_RETURN(1); DBUG_RETURN(1);
} }
pkt_length = (length+IO_SIZE-1) & ~(IO_SIZE-1); pkt_length = (length+IO_SIZE-1) & ~(IO_SIZE-1);
if (!(buff=(uchar*) my_realloc((char*) net->buff, pkt_length + 1, MYF(MY_WME)))) /* reallocate buffer:
size= pkt_length + NET_HEADER_SIZE + COMP_HEADER_SIZE */
if (!(buff=(uchar*) my_realloc((char*) net->buff,
pkt_length + NET_HEADER_SIZE + COMP_HEADER_SIZE,
MYF(MY_WME))))
{ {
DBUG_PRINT("info", ("Out of memory")); DBUG_PRINT("info", ("Out of memory"));
net->error=1; net->error=1;

View File

@@ -29,53 +29,18 @@
#include <my_pthread.h> #include <my_pthread.h>
#include <mysql/client_plugin.h> #include <mysql/client_plugin.h>
#include <string.h> #include <string.h>
#include <ma_ssl.h>
pthread_mutex_t LOCK_gnutls_config; pthread_mutex_t LOCK_gnutls_config;
static my_bool my_gnutls_initialized= FALSE;
static gnutls_certificate_credentials_t GNUTLS_xcred; static gnutls_certificate_credentials_t GNUTLS_xcred;
extern my_bool ma_ssl_initialized;
static int my_verify_callback(gnutls_session_t ssl);
#define MAX_SSL_ERR_LEN 100 #define MAX_SSL_ERR_LEN 100
int cio_gnutls_start(char *errmsg, size_t errmsg_len, int count, va_list); static void ma_ssl_set_error(MYSQL *mysql, int ssl_errno)
int cio_gnutls_end();
void *cio_gnutls_init(MARIADB_SSL *cssl, MYSQL *mysql);
my_bool cio_gnutls_connect(MARIADB_SSL *cssl);
size_t cio_gnutls_read(MARIADB_SSL *cssl, const uchar* buffer, size_t length);
size_t cio_gnutls_write(MARIADB_SSL *cssl, const uchar* buffer, size_t length);
my_bool cio_gnutls_close(MARIADB_SSL *cssl);
int cio_gnutls_verify_server_cert(MARIADB_SSL *cssl);
const char *cio_gnutls_cipher(MARIADB_SSL *cssl);
static int my_verify_callback(gnutls_session_t ssl);
struct st_ma_cio_ssl_methods cio_gnutls_methods= {
cio_gnutls_init,
cio_gnutls_connect,
cio_gnutls_read,
cio_gnutls_write,
cio_gnutls_close,
cio_gnutls_verify_server_cert,
cio_gnutls_cipher
};
MARIADB_CIO_PLUGIN cio_gnutls_plugin=
{
MYSQL_CLIENT_CIO_PLUGIN,
MYSQL_CLIENT_CIO_PLUGIN_INTERFACE_VERSION,
"cio_gnutls",
"Georg Richter",
"MariaDB communication IO plugin for GnuTLS SSL communication",
{1, 0, 0},
"LGPL",
NULL,
cio_gnutls_start,
cio_gnutls_end,
NULL,
&cio_gnutls_methods,
NULL
};
static void cio_gnutls_set_error(MYSQL *mysql, int ssl_errno)
{ {
char ssl_error[MAX_SSL_ERR_LEN]; char ssl_error[MAX_SSL_ERR_LEN];
const char *ssl_error_reason; const char *ssl_error_reason;
@@ -98,7 +63,7 @@ static void cio_gnutls_set_error(MYSQL *mysql, int ssl_errno)
} }
static void cio_gnutls_get_error(char *errmsg, size_t length, int ssl_errno) static void ma_ssl_get_error(char *errmsg, size_t length, int ssl_errno)
{ {
const char *ssl_error_reason; const char *ssl_error_reason;
@@ -127,21 +92,21 @@ static void cio_gnutls_get_error(char *errmsg, size_t length, int ssl_errno)
0 success 0 success
1 error 1 error
*/ */
int cio_gnutls_start(char *errmsg, size_t errmsg_len, int count, va_list list) int ma_ssl_start(char *errmsg, size_t errmsg_len)
{ {
int rc= 0; int rc= 0;
pthread_mutex_init(&LOCK_gnutls_config,MY_MUTEX_INIT_FAST); pthread_mutex_init(&LOCK_gnutls_config,MY_MUTEX_INIT_FAST);
pthread_mutex_lock(&LOCK_gnutls_config); pthread_mutex_lock(&LOCK_gnutls_config);
if (!my_gnutls_initialized) if (!ma_ssl_initialized)
{ {
if ((rc= gnutls_global_init()) != GNUTLS_E_SUCCESS) if ((rc= gnutls_global_init()) != GNUTLS_E_SUCCESS)
{ {
cio_gnutls_get_error(errmsg, errmsg_len, rc); ma_ssl_get_error(errmsg, errmsg_len, rc);
goto end; goto end;
} }
my_gnutls_initialized= TRUE; ma_ssl_initialized= TRUE;
} }
/* Allocate a global context for credentials */ /* Allocate a global context for credentials */
rc= gnutls_certificate_allocate_credentials(&GNUTLS_xcred); rc= gnutls_certificate_allocate_credentials(&GNUTLS_xcred);
@@ -162,10 +127,10 @@ end:
RETURN VALUES RETURN VALUES
void void
*/ */
int cio_gnutls_end() void ma_ssl_end()
{ {
pthread_mutex_lock(&LOCK_gnutls_config); pthread_mutex_lock(&LOCK_gnutls_config);
if (my_gnutls_initialized) if (ma_ssl_initialized)
{ {
gnutls_certificate_free_keys(GNUTLS_xcred); gnutls_certificate_free_keys(GNUTLS_xcred);
gnutls_certificate_free_cas(GNUTLS_xcred); gnutls_certificate_free_cas(GNUTLS_xcred);
@@ -173,14 +138,14 @@ int cio_gnutls_end()
gnutls_certificate_free_ca_names(GNUTLS_xcred); gnutls_certificate_free_ca_names(GNUTLS_xcred);
gnutls_certificate_free_credentials(GNUTLS_xcred); gnutls_certificate_free_credentials(GNUTLS_xcred);
gnutls_global_deinit(); gnutls_global_deinit();
my_gnutls_initialized= FALSE; ma_ssl_initialized= FALSE;
} }
pthread_mutex_unlock(&LOCK_gnutls_config); pthread_mutex_unlock(&LOCK_gnutls_config);
pthread_mutex_destroy(&LOCK_gnutls_config); pthread_mutex_destroy(&LOCK_gnutls_config);
return 0; return;
} }
static int cio_gnutls_set_certs(MYSQL *mysql, MARIADB_SSL *cssl) static int ma_ssl_set_certs(MYSQL *mysql)
{ {
char *certfile= mysql->options.ssl_cert, char *certfile= mysql->options.ssl_cert,
*keyfile= mysql->options.ssl_key; *keyfile= mysql->options.ssl_key;
@@ -218,11 +183,11 @@ static int cio_gnutls_set_certs(MYSQL *mysql, MARIADB_SSL *cssl)
error: error:
if (cipher) if (cipher)
my_free(cipher)); my_free(cipher);
return ssl_error; return ssl_error;
} }
void *cio_gnutls_init(MARIADB_SSL *cssl, MYSQL *mysql) void *ma_ssl_init(MYSQL *mysql)
{ {
gnutls_session_t ssl= NULL; gnutls_session_t ssl= NULL;
int ssl_error= 0; int ssl_error= 0;
@@ -230,7 +195,7 @@ void *cio_gnutls_init(MARIADB_SSL *cssl, MYSQL *mysql)
pthread_mutex_lock(&LOCK_gnutls_config); pthread_mutex_lock(&LOCK_gnutls_config);
if ((ssl_error= cio_gnutls_set_certs(mysql, cssl)) < 0) if ((ssl_error= ma_ssl_set_certs(mysql)) < 0)
goto error; goto error;
if ((ssl_error = gnutls_init(&ssl, GNUTLS_CLIENT & GNUTLS_NONBLOCK)) < 0) if ((ssl_error = gnutls_init(&ssl, GNUTLS_CLIENT & GNUTLS_NONBLOCK)) < 0)
@@ -244,18 +209,17 @@ void *cio_gnutls_init(MARIADB_SSL *cssl, MYSQL *mysql)
if ((ssl_error= gnutls_credentials_set(ssl, GNUTLS_CRD_CERTIFICATE, GNUTLS_xcred)) < 0) if ((ssl_error= gnutls_credentials_set(ssl, GNUTLS_CRD_CERTIFICATE, GNUTLS_xcred)) < 0)
goto error; goto error;
cssl->ssl= ssl;
pthread_mutex_unlock(&LOCK_gnutls_config); pthread_mutex_unlock(&LOCK_gnutls_config);
return (void *)ssl; return (void *)ssl;
error: error:
cio_gnutls_set_error(mysql, ssl_error); ma_ssl_set_error(mysql, ssl_error);
if (ssl) if (ssl)
gnutls_deinit(ssl); gnutls_deinit(ssl);
pthread_mutex_unlock(&LOCK_gnutls_config); pthread_mutex_unlock(&LOCK_gnutls_config);
return NULL; return NULL;
} }
my_bool cio_gnutls_connect(MARIADB_SSL *cssl) my_bool ma_ssl_connect(MARIADB_SSL *cssl)
{ {
gnutls_session_t ssl = (gnutls_session_t)cssl->ssl; gnutls_session_t ssl = (gnutls_session_t)cssl->ssl;
my_bool blocking; my_bool blocking;
@@ -273,7 +237,7 @@ my_bool cio_gnutls_connect(MARIADB_SSL *cssl)
if (!(blocking= cio->methods->is_blocking(cio))) if (!(blocking= cio->methods->is_blocking(cio)))
cio->methods->blocking(cio, TRUE, 0); cio->methods->blocking(cio, TRUE, 0);
gnutls_transport_set_int(ssl, cio->methods->get_socket(cio)); gnutls_transport_set_int(ssl, mysql_get_socket(mysql));
gnutls_handshake_set_timeout(ssl, mysql->options.connect_timeout); gnutls_handshake_set_timeout(ssl, mysql->options.connect_timeout);
do { do {
@@ -282,7 +246,7 @@ my_bool cio_gnutls_connect(MARIADB_SSL *cssl)
if (ret < 0) if (ret < 0)
{ {
cio_gnutls_set_error(mysql, ret); ma_ssl_set_error(mysql, ret);
/* restore blocking mode */ /* restore blocking mode */
if (!blocking) if (!blocking)
cio->methods->blocking(cio, FALSE, 0); cio->methods->blocking(cio, FALSE, 0);
@@ -293,17 +257,17 @@ my_bool cio_gnutls_connect(MARIADB_SSL *cssl)
return 0; return 0;
} }
size_t cio_gnutls_read(MARIADB_SSL *cssl, const uchar* buffer, size_t length) size_t ma_ssl_read(MARIADB_SSL *cssl, const uchar* buffer, size_t length)
{ {
return gnutls_record_recv((gnutls_session_t )cssl->ssl, (void *)buffer, length); return gnutls_record_recv((gnutls_session_t )cssl->ssl, (void *)buffer, length);
} }
size_t cio_gnutls_write(MARIADB_SSL *cssl, const uchar* buffer, size_t length) size_t ma_ssl_write(MARIADB_SSL *cssl, const uchar* buffer, size_t length)
{ {
return gnutls_record_send((gnutls_session_t )cssl->ssl, (void *)buffer, length); return gnutls_record_send((gnutls_session_t )cssl->ssl, (void *)buffer, length);
} }
my_bool cio_gnutls_close(MARIADB_SSL *cssl) my_bool ma_ssl_close(MARIADB_SSL *cssl)
{ {
gnutls_bye((gnutls_session_t )cssl->ssl, GNUTLS_SHUT_WR); gnutls_bye((gnutls_session_t )cssl->ssl, GNUTLS_SHUT_WR);
gnutls_deinit((gnutls_session_t )cssl->ssl); gnutls_deinit((gnutls_session_t )cssl->ssl);
@@ -312,13 +276,13 @@ my_bool cio_gnutls_close(MARIADB_SSL *cssl)
return 0; return 0;
} }
int cio_gnutls_verify_server_cert(MARIADB_SSL *cssl) int ma_ssl_verify_server_cert(MARIADB_SSL *cssl)
{ {
/* server verification is already handled before */ /* server verification is already handled before */
return 0; return 0;
} }
const char *cio_gnutls_cipher(MARIADB_SSL *cssl) const char *ma_ssl_get_cipher(MARIADB_SSL *cssl)
{ {
if (!cssl || !cssl->ssl) if (!cssl || !cssl->ssl)
return NULL; return NULL;
@@ -390,7 +354,6 @@ static int my_verify_callback(gnutls_session_t ssl)
if ((mysql->client_flag & CLIENT_SSL_VERIFY_SERVER_CERT) && if ((mysql->client_flag & CLIENT_SSL_VERIFY_SERVER_CERT) &&
gnutls_x509_crt_check_hostname (cert, hostname) < 0) gnutls_x509_crt_check_hostname (cert, hostname) < 0)
{ {
printf("Error: %s does not match\n", hostname);
gnutls_x509_crt_deinit (cert); gnutls_x509_crt_deinit (cert);
cio->set_error(mysql, CR_SSL_CONNECTION_ERROR, SQLSTATE_UNKNOWN, "Hostname in certificate doesn't match"); cio->set_error(mysql, CR_SSL_CONNECTION_ERROR, SQLSTATE_UNKNOWN, "Hostname in certificate doesn't match");
return GNUTLS_E_CERTIFICATE_ERROR; return GNUTLS_E_CERTIFICATE_ERROR;
@@ -402,4 +365,36 @@ static int my_verify_callback(gnutls_session_t ssl)
return 0; return 0;
} }
unsigned int ma_ssl_get_finger_print(MARIADB_SSL *cssl, unsigned char *fp, unsigned int len)
{
MYSQL *mysql;
size_t fp_len= len;
const gnutls_datum_t *cert_list;
unsigned int cert_list_size;
if (!cssl || !cssl->ssl)
return 0;
mysql= (MYSQL *)gnutls_session_get_ptr(cssl->ssl);
cert_list = gnutls_certificate_get_peers (cssl->ssl, &cert_list_size);
if (cert_list == NULL)
{
my_set_error(mysql, CR_SSL_CONNECTION_ERROR, SQLSTATE_UNKNOWN,
ER(CR_SSL_CONNECTION_ERROR),
"Unable to get server certificate");
return 0;
}
if (gnutls_fingerprint(GNUTLS_DIG_MD5, &cert_list[0], fp, &fp_len) > 0)
return fp_len;
else
{
my_set_error(mysql, CR_SSL_CONNECTION_ERROR, SQLSTATE_UNKNOWN,
ER(CR_SSL_CONNECTION_ERROR),
"Finger print buffer too small");
return 0;
}
}
#endif /* HAVE_GNUTLS */ #endif /* HAVE_GNUTLS */

View File

@@ -22,6 +22,7 @@
#include <ma_common.h> #include <ma_common.h>
#include <ma_cio.h> #include <ma_cio.h>
#include <errmsg.h> #include <errmsg.h>
#include <string.h>
#include <mysql/client_plugin.h> #include <mysql/client_plugin.h>
#include <string.h> #include <string.h>
#include <openssl/ssl.h> /* SSL and SSL_CTX */ #include <openssl/ssl.h> /* SSL and SSL_CTX */
@@ -32,14 +33,14 @@
#include <memory.h> #include <memory.h>
#define my_malloc(A,B) malloc((A)) #define my_malloc(A,B) malloc((A))
#undef my_free #undef my_free
#define my_free(A,B) free((A)) #define my_free(A) free((A))
#define my_snprintf snprintf #define my_snprintf snprintf
#define my_vsnprintf vsnprintf #define my_vsnprintf vsnprintf
#undef SAFE_MUTEX #undef SAFE_MUTEX
#endif #endif
#include <my_pthread.h> #include <my_pthread.h>
static my_bool my_openssl_initialized= FALSE; extern my_bool ma_ssl_initialized;
static SSL_CTX *SSL_context= NULL; static SSL_CTX *SSL_context= NULL;
#define MAX_SSL_ERR_LEN 100 #define MAX_SSL_ERR_LEN 100
@@ -47,43 +48,8 @@ static SSL_CTX *SSL_context= NULL;
static pthread_mutex_t LOCK_openssl_config; static pthread_mutex_t LOCK_openssl_config;
static pthread_mutex_t *LOCK_crypto= NULL; static pthread_mutex_t *LOCK_crypto= NULL;
int cio_openssl_start(char *errmsg, size_t errmsg_len, int count, va_list);
int cio_openssl_end();
void *cio_openssl_init(MARIADB_SSL *cssl, MYSQL *mysql);
my_bool cio_openssl_connect(MARIADB_SSL *cssl);
size_t cio_openssl_read(MARIADB_SSL *cssl, const uchar* buffer, size_t length);
size_t cio_openssl_write(MARIADB_SSL *cssl, const uchar* buffer, size_t length);
my_bool cio_openssl_close(MARIADB_SSL *cssl);
int cio_openssl_verify_server_cert(MARIADB_SSL *cssl);
const char *cio_openssl_cipher(MARIADB_SSL *cssl);
struct st_ma_cio_ssl_methods cio_openssl_methods= { static void ma_ssl_set_error(MYSQL *mysql)
cio_openssl_init,
cio_openssl_connect,
cio_openssl_read,
cio_openssl_write,
cio_openssl_close,
cio_openssl_verify_server_cert,
cio_openssl_cipher
};
MARIADB_CIO_PLUGIN cio_openssl_plugin=
{
MYSQL_CLIENT_CIO_PLUGIN,
MYSQL_CLIENT_CIO_PLUGIN_INTERFACE_VERSION,
"cio_openssl",
"Georg Richter",
"MariaDB communication IO plugin for OpenSSL communication",
{1, 0, 0},
"LGPL",
cio_openssl_start,
cio_openssl_end,
NULL,
&cio_openssl_methods,
NULL
};
static void cio_openssl_set_error(MYSQL *mysql)
{ {
ulong ssl_errno= ERR_get_error(); ulong ssl_errno= ERR_get_error();
char ssl_error[MAX_SSL_ERR_LEN]; char ssl_error[MAX_SSL_ERR_LEN];
@@ -107,7 +73,7 @@ static void cio_openssl_set_error(MYSQL *mysql)
} }
static void cio_openssl_get_error(char *errmsg, size_t length) static void ma_ssl_get_error(char *errmsg, size_t length)
{ {
ulong ssl_errno= ERR_get_error(); ulong ssl_errno= ERR_get_error();
const char *ssl_error_reason; const char *ssl_error_reason;
@@ -189,13 +155,13 @@ static int ssl_thread_init()
0 success 0 success
1 error 1 error
*/ */
int cio_openssl_start(char *errmsg, size_t errmsg_len, int count, va_list list) int ma_ssl_start(char *errmsg, size_t errmsg_len)
{ {
int rc= 1; int rc= 1;
/* lock mutex to prevent multiple initialization */ /* lock mutex to prevent multiple initialization */
pthread_mutex_init(&LOCK_openssl_config,MY_MUTEX_INIT_FAST); pthread_mutex_init(&LOCK_openssl_config,MY_MUTEX_INIT_FAST);
pthread_mutex_lock(&LOCK_openssl_config); pthread_mutex_lock(&LOCK_openssl_config);
if (!my_openssl_initialized) if (!ma_ssl_initialized)
{ {
if (ssl_thread_init()) if (ssl_thread_init())
{ {
@@ -214,11 +180,11 @@ int cio_openssl_start(char *errmsg, size_t errmsg_len, int count, va_list list)
if (!(SSL_context= SSL_CTX_new(TLSv1_client_method()))) if (!(SSL_context= SSL_CTX_new(TLSv1_client_method())))
{ {
cio_openssl_get_error(errmsg, errmsg_len); ma_ssl_get_error(errmsg, errmsg_len);
goto end; goto end;
} }
rc= 0; rc= 0;
my_openssl_initialized= TRUE; ma_ssl_initialized= TRUE;
} }
end: end:
pthread_mutex_unlock(&LOCK_openssl_config); pthread_mutex_unlock(&LOCK_openssl_config);
@@ -237,10 +203,10 @@ end:
RETURN VALUES RETURN VALUES
void void
*/ */
int cio_openssl_end() void ma_ssl_end()
{ {
pthread_mutex_lock(&LOCK_openssl_config); pthread_mutex_lock(&LOCK_openssl_config);
if (my_openssl_initialized) if (ma_ssl_initialized)
{ {
int i; int i;
CRYPTO_set_locking_callback(NULL); CRYPTO_set_locking_callback(NULL);
@@ -249,7 +215,7 @@ int cio_openssl_end()
for (i=0; i < CRYPTO_num_locks(); i++) for (i=0; i < CRYPTO_num_locks(); i++)
pthread_mutex_destroy(&LOCK_crypto[i]); pthread_mutex_destroy(&LOCK_crypto[i]);
my_free((gptr)LOCK_crypto, MYF(0)); my_free((gptr)LOCK_crypto);
LOCK_crypto= NULL; LOCK_crypto= NULL;
if (SSL_context) if (SSL_context)
@@ -265,14 +231,14 @@ int cio_openssl_end()
CONF_modules_free(); CONF_modules_free();
CONF_modules_unload(1); CONF_modules_unload(1);
sk_SSL_COMP_free(SSL_COMP_get_compression_methods()); sk_SSL_COMP_free(SSL_COMP_get_compression_methods());
my_openssl_initialized= FALSE; ma_ssl_initialized= FALSE;
} }
pthread_mutex_unlock(&LOCK_openssl_config); pthread_mutex_unlock(&LOCK_openssl_config);
pthread_mutex_destroy(&LOCK_openssl_config); pthread_mutex_destroy(&LOCK_openssl_config);
return 0; return;
} }
static int cio_openssl_set_certs(MYSQL *mysql) static int ma_ssl_set_certs(MYSQL *mysql)
{ {
char *certfile= mysql->options.ssl_cert, char *certfile= mysql->options.ssl_cert,
*keyfile= mysql->options.ssl_key; *keyfile= mysql->options.ssl_key;
@@ -331,7 +297,7 @@ static int cio_openssl_set_certs(MYSQL *mysql)
return 0; return 0;
error: error:
cio_openssl_set_error(mysql); ma_ssl_set_error(mysql);
return 1; return 1;
} }
@@ -364,14 +330,17 @@ static int my_verify_callback(int ok, X509_STORE_CTX *ctx)
return ok; return ok;
} }
void *cio_openssl_init(MARIADB_SSL *cssl, MYSQL *mysql) void *ma_ssl_init(MYSQL *mysql)
{ {
int verify; int verify;
SSL *ssl= NULL; SSL *ssl= NULL;
pthread_mutex_lock(&LOCK_openssl_config); pthread_mutex_lock(&LOCK_openssl_config);
if (cio_openssl_set_certs(mysql))
if (ma_ssl_set_certs(mysql))
{
goto error; goto error;
}
if (!(ssl= SSL_new(SSL_context))) if (!(ssl= SSL_new(SSL_context)))
goto error; goto error;
@@ -394,12 +363,13 @@ error:
return NULL; return NULL;
} }
my_bool cio_openssl_connect(MARIADB_SSL *cssl) my_bool ma_ssl_connect(MARIADB_SSL *cssl)
{ {
SSL *ssl = (SSL *)cssl->ssl; SSL *ssl = (SSL *)cssl->ssl;
my_bool blocking; my_bool blocking;
MYSQL *mysql; MYSQL *mysql;
MARIADB_CIO *cio; MARIADB_CIO *cio;
int rc;
mysql= (MYSQL *)SSL_get_app_data(ssl); mysql= (MYSQL *)SSL_get_app_data(ssl);
cio= mysql->net.cio; cio= mysql->net.cio;
@@ -415,28 +385,40 @@ my_bool cio_openssl_connect(MARIADB_SSL *cssl)
if (SSL_connect(ssl) != 1) if (SSL_connect(ssl) != 1)
{ {
cio_openssl_set_error(mysql); ma_ssl_set_error(mysql);
/* restore blocking mode */ /* restore blocking mode */
if (!blocking) if (!blocking)
cio->methods->blocking(cio, FALSE, 0); cio->methods->blocking(cio, FALSE, 0);
return 1; return 1;
} }
rc= SSL_get_verify_result(ssl);
if (rc != X509_V_OK)
{
my_set_error(mysql, CR_SSL_CONNECTION_ERROR, SQLSTATE_UNKNOWN,
ER(CR_SSL_CONNECTION_ERROR), X509_verify_cert_error_string(rc));
/* restore blocking mode */
if (!blocking)
cio->methods->blocking(cio, FALSE, 0);
return 1;
}
cio->cssl->ssl= cssl->ssl= (void *)ssl; cio->cssl->ssl= cssl->ssl= (void *)ssl;
return 0; return 0;
} }
size_t cio_openssl_read(MARIADB_SSL *cssl, const uchar* buffer, size_t length) size_t ma_ssl_read(MARIADB_SSL *cssl, const uchar* buffer, size_t length)
{ {
return SSL_read((SSL *)cssl->ssl, (void *)buffer, (int)length); return SSL_read((SSL *)cssl->ssl, (void *)buffer, (int)length);
} }
size_t cio_openssl_write(MARIADB_SSL *cssl, const uchar* buffer, size_t length) size_t ma_ssl_write(MARIADB_SSL *cssl, const uchar* buffer, size_t length)
{ {
return SSL_write((SSL *)cssl->ssl, (void *)buffer, (int)length); return SSL_write((SSL *)cssl->ssl, (void *)buffer, (int)length);
} }
my_bool cio_openssl_close(MARIADB_SSL *cssl) my_bool ma_ssl_close(MARIADB_SSL *cssl)
{ {
int i, rc; int i, rc;
SSL *ssl; SSL *ssl;
@@ -457,7 +439,7 @@ my_bool cio_openssl_close(MARIADB_SSL *cssl)
return rc; return rc;
} }
int cio_openssl_verify_server_cert(MARIADB_SSL *cssl) int ma_ssl_verify_server_cert(MARIADB_SSL *cssl)
{ {
X509 *cert; X509 *cert;
MYSQL *mysql; MYSQL *mysql;
@@ -504,9 +486,48 @@ int cio_openssl_verify_server_cert(MARIADB_SSL *cssl)
return 1; return 1;
} }
const char *cio_openssl_cipher(MARIADB_SSL *cssl) const char *ma_ssl_get_cipher(MARIADB_SSL *cssl)
{ {
if (!cssl || !cssl->ssl) if (!cssl || !cssl->ssl)
return NULL; return NULL;
return SSL_get_cipher_name(cssl->ssl); return SSL_get_cipher_name(cssl->ssl);
} }
unsigned int ma_ssl_get_finger_print(MARIADB_SSL *cssl, unsigned char *fp, unsigned int len)
{
EVP_MD *digest= (EVP_MD *)EVP_sha1();
X509 *cert;
MYSQL *mysql;
unsigned int *fp_len;
if (!cssl || !cssl->ssl)
return NULL;
mysql= SSL_get_app_data(cssl->ssl);
if (!(cert= SSL_get_peer_certificate(cssl->ssl)))
{
my_set_error(mysql, CR_SSL_CONNECTION_ERROR, SQLSTATE_UNKNOWN,
ER(CR_SSL_CONNECTION_ERROR),
"Unable to get server certificate");
return 0;
}
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;
}
*fp_len= len;
if (!X509_digest(cert, digest, fp, fp_len))
{
my_free(fp);
my_set_error(mysql, CR_SSL_CONNECTION_ERROR, SQLSTATE_UNKNOWN,
ER(CR_SSL_CONNECTION_ERROR),
"invalid finger print of server certificate");
return 0;
}
return (*fp_len);
}

View File

@@ -243,6 +243,22 @@ static int send_client_reply_packet(MCPVIO_EXT *mpvio,
if (mpvio->db) if (mpvio->db)
mysql->client_flag|= CLIENT_CONNECT_WITH_DB; mysql->client_flag|= CLIENT_CONNECT_WITH_DB;
/* 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->client_flag & CLIENT_SSL_VERIFY_SERVER_CERT) ||
(mysql->options.extension && (mysql->options.extension->ssl_fp ||
mysql->options.extension->ssl_fp_list)))
{
my_set_error(mysql, CR_SSL_CONNECTION_ERROR, SQLSTATE_UNKNOWN,
ER(CR_SSL_CONNECTION_ERROR),
"Server doesn't support SSL");
goto error;
}
}
/* Remove options that server doesn't support */ /* Remove options that server doesn't support */
mysql->client_flag= mysql->client_flag & mysql->client_flag= mysql->client_flag &
(~(CLIENT_COMPRESS | CLIENT_SSL | CLIENT_PROTOCOL_41) (~(CLIENT_COMPRESS | CLIENT_SSL | CLIENT_PROTOCOL_41)

View File

@@ -53,6 +53,7 @@ MARIADB_CIO_PLUGIN _mysql_client_plugin_declaration_ =
"Georg Richter", "Georg Richter",
"MariaDB communication IO plugin for named pipe communication", "MariaDB communication IO plugin for named pipe communication",
{1, 0, 0}, {1, 0, 0},
"LGPL",
NULL, NULL,
NULL, NULL,
&cio_npipe_methods, &cio_npipe_methods,

View File

@@ -59,6 +59,7 @@ MARIADB_CIO_PLUGIN _mysql_client_plugin_declaration_ =
"Georg Richter", "Georg Richter",
"MariaDB communication IO plugin for named pipe communication", "MariaDB communication IO plugin for named pipe communication",
{1, 0, 0}, {1, 0, 0},
"LGPL",
NULL, NULL,
NULL, NULL,
&cio_shm_methods, &cio_shm_methods,

Binary file not shown.

View File

@@ -25,7 +25,7 @@ SET(API_TESTS "async" "basic-t" "fetch" "charset" "logs" "cursor" "errors" "view
"sp" "result" "connection" "misc" "ps_new" "sqlite3" "thread" "dyncol") "sp" "result" "connection" "misc" "ps_new" "sqlite3" "thread" "dyncol")
# Get finger print from server certificate # Get finger print from server certificate
IF(WITH_OPENSSL) IF(WITH_SSL)
#create certificates #create certificates
IF(EXISTS "${CMAKE_SOURCE_DIR}/unittest/libmariadb/certs/server-cert.pem") IF(EXISTS "${CMAKE_SOURCE_DIR}/unittest/libmariadb/certs/server-cert.pem")

View File

@@ -33,8 +33,8 @@ pthread_mutex_t LOCK_test;
int check_skip_ssl() int check_skip_ssl()
{ {
#ifndef HAVE_OPENSSL #ifndef HAVE_SSL
diag("client library built without OpenSSL support -> skip"); diag("client library built without SSL support -> skip");
return 1; return 1;
#endif #endif
if (skip_ssl) if (skip_ssl)
@@ -92,7 +92,11 @@ static int test_ssl_cipher(MYSQL *unused)
port, socketname, 0), mysql_error(my)); port, socketname, 0), mysql_error(my));
cipher= (char *)mysql_get_ssl_cipher(my); cipher= (char *)mysql_get_ssl_cipher(my);
#ifdef HAVE_OPENSSL
FAIL_IF(strcmp(cipher, "DHE-RSA-AES256-SHA") != 0, "Cipher != DHE-RSA-AES256-SHA"); FAIL_IF(strcmp(cipher, "DHE-RSA-AES256-SHA") != 0, "Cipher != DHE-RSA-AES256-SHA");
#elif defined(HAVE_HNUTLS)
FAIL_IF(strcmp(cipher, "AES-256-CBC") != 0, "Cipher != AES-256-CBC");
#endif
mysql_close(my); mysql_close(my);
return OK; return OK;
} }
@@ -174,7 +178,11 @@ static int test_multi_ssl_connections(MYSQL *unused)
} }
cipher= (char *)mysql_get_ssl_cipher(mysql[i]); cipher= (char *)mysql_get_ssl_cipher(mysql[i]);
#ifdef HAVE_OPENSSL
FAIL_IF(strcmp(cipher, "DHE-RSA-AES256-SHA") != 0, "Cipher != DHE-RSA-AES256-SHA"); FAIL_IF(strcmp(cipher, "DHE-RSA-AES256-SHA") != 0, "Cipher != DHE-RSA-AES256-SHA");
#elif defined(HAVE_HNUTLS)
FAIL_IF(strcmp(cipher, "AES-256-CBC") != 0, "Cipher != AES-256-CBC");
#endif
} }
for (i=0; i < 50; i++) for (i=0; i < 50; i++)
mysql_close(mysql[i]); mysql_close(mysql[i]);
@@ -637,7 +645,11 @@ static int test_ssl_fp(MYSQL *unused)
port, socketname, 0), mysql_error(my)); port, socketname, 0), mysql_error(my));
cipher= (char *)mysql_get_ssl_cipher(my); cipher= (char *)mysql_get_ssl_cipher(my);
#ifdef HAVE_OPENSSL
FAIL_IF(strcmp(cipher, "DHE-RSA-AES256-SHA") != 0, "Cipher != DHE-RSA-AES256-SHA"); FAIL_IF(strcmp(cipher, "DHE-RSA-AES256-SHA") != 0, "Cipher != DHE-RSA-AES256-SHA");
#elif defined(HAVE_HNUTLS)
FAIL_IF(strcmp(cipher, "AES-256-CBC") != 0, "Cipher != AES-256-CBC");
#endif
mysql_close(my); mysql_close(my);
return OK; return OK;
} }
@@ -660,8 +672,11 @@ static int test_ssl_fp_list(MYSQL *unused)
FAIL_IF(!mysql_real_connect(my, hostname, ssluser, sslpw, schema, FAIL_IF(!mysql_real_connect(my, hostname, ssluser, sslpw, schema,
port, socketname, 0), mysql_error(my)); port, socketname, 0), mysql_error(my));
cipher= (char *)mysql_get_ssl_cipher(my); #ifdef HAVE_OPENSSL
FAIL_IF(strcmp(cipher, "DHE-RSA-AES256-SHA") != 0, "Cipher != DHE-RSA-AES256-SHA"); FAIL_IF(strcmp(cipher, "DHE-RSA-AES256-SHA") != 0, "Cipher != DHE-RSA-AES256-SHA");
#elif defined(HAVE_HNUTLS)
FAIL_IF(strcmp(cipher, "AES-256-CBC") != 0, "Cipher != AES-256-CBC");
#endif
mysql_close(my); mysql_close(my);
return OK; return OK;
} }