diff --git libmariadb/mariadb_lib.c libmariadb/mariadb_lib.c index 916024a8..79564a10 100644 --- libmariadb/mariadb_lib.c +++ libmariadb/mariadb_lib.c @@ -133,6 +133,11 @@ my_context_install_suspend_resume_hook(struct mysql_async_context *b, uint mysql_port=0; my_string mysql_unix_port=0; +#include +extern __thread SSL_CTX * thread_ctx; +extern __thread char **local_x509_files; +extern __thread char **local_x509_sha1s; + #define CONNECT_TIMEOUT 0 struct st_mariadb_methods MARIADB_DEFAULT_METHODS; @@ -4650,6 +4655,19 @@ my_bool STDCALL mysql_thread_init(void) void STDCALL mysql_thread_end(void) { + if (local_x509_files != NULL) { + int i; + for (i=0; local_x509_files[i] != NULL ; i++) { + free(local_x509_files[i]); + free(local_x509_sha1s[i]); + } + free(local_x509_files); + free(local_x509_sha1s); + } + if (thread_ctx != NULL) { + SSL_CTX_free(thread_ctx); + thread_ctx = NULL; + } } int STDCALL mysql_set_server_option(MYSQL *mysql, diff --git libmariadb/secure/openssl.c libmariadb/secure/openssl.c index 916024a8..79564a10 100644 --- libmariadb/secure/openssl.c +++ libmariadb/secure/openssl.c @@ -30,6 +30,11 @@ #include #include +#include +#include +#include +#include + #if defined(_WIN32) && !defined(_OPENSSL_Applink) && defined(HAVE_OPENSSL_APPLINK_C) #include #endif @@ -70,6 +75,89 @@ extern my_bool ma_tls_initialized; extern unsigned int mariadb_deinitialize_ssl; +__thread SSL_CTX * thread_ctx = NULL; +__thread void * local_x509store = NULL; +__thread char **local_x509_files = NULL; +__thread char **local_x509_sha1s = NULL; + +static int proxysql_SSL_CTX_local_x509store_add_file(SSL_CTX *ctx, const char *CAfile, int add_in_store) { + int found=0, i=0, fd=-1; + ssize_t bytesRead = 0; + struct stat statbuf; + unsigned char temp[SHA_DIGEST_LENGTH]; + char file_sha1[SHA_DIGEST_LENGTH*2+2]; + memset(file_sha1,0,SHA_DIGEST_LENGTH*2+2); + + fd = open(CAfile, O_RDONLY); + if (fd == -1) return 0; + + if(fstat(fd, &statbuf) == 0) { + // Allocate a buffer to read the file + unsigned char *fb = (unsigned char *)malloc(statbuf.st_size); + if (fb == NULL) { + close(fd); + return 0; + } + // Read the file into the buffer + bytesRead = pread(fd, fb, statbuf.st_size, 0); + if (bytesRead != statbuf.st_size) { + free(fb); + close(fd); + return 0; + } + SHA1(fb, statbuf.st_size, temp); + int i=0; + for (i=0; i < SHA_DIGEST_LENGTH; i++) { + sprintf((char*)&(file_sha1[i*2]), "%02x", temp[i]); + } + free(fb); + close(fd); + } else { + close(fd); + return 0; + } + + if (local_x509_files == NULL) { + local_x509_files = (char **)malloc(sizeof(char *)*1); + local_x509_sha1s = (char **)malloc(sizeof(char *)*1); + local_x509_files[0] = NULL; + local_x509_sha1s[0] = NULL; + } + + while (found == 0 && local_x509_files[i] != NULL) { + if (strcmp(CAfile, local_x509_files[i]) == 0) { + found = 1; + } else { + i++; + } + } + if (found == 1) { + if (strncmp(local_x509_sha1s[i],file_sha1,SHA_DIGEST_LENGTH*2)==0) { + return 1; // all good + } else { + int rc = 1; + free(local_x509_sha1s[i]); + local_x509_sha1s[i] = strdup(file_sha1); + rc = SSL_CTX_load_verify_file(ctx, CAfile); + return rc; + } + } else { + local_x509_files = (char **)realloc(local_x509_files,sizeof(char *)*(i+2)); + local_x509_sha1s = (char **)realloc(local_x509_sha1s,sizeof(char *)*(i+2)); + local_x509_files[i+1] = NULL; + local_x509_sha1s[i+1] = NULL; + local_x509_files[i] = strdup(CAfile); + local_x509_sha1s[i] = strdup(file_sha1); + if (add_in_store == 1) { + int rc = 1; + rc = SSL_CTX_load_verify_file(ctx, CAfile); + return rc; + } + return 1; + } + return 1; +} + #define MAX_SSL_ERR_LEN 100 char tls_library_version[TLS_VERSION_LENGTH]; @@ -331,7 +419,7 @@ *keyfile= mysql->options.ssl_key; char *pw= (mysql->options.extension) ? mysql->options.extension->tls_pw : NULL; - + int ssl_rc = 0; /* add cipher */ if ((mysql->options.ssl_cipher && mysql->options.ssl_cipher[0] != 0)) @@ -345,10 +433,27 @@ } /* ca_file and ca_path */ - if (!SSL_CTX_load_verify_locations(ctx, + if (local_x509store != NULL && mysql->options.ssl_ca != NULL && mysql->options.ssl_capath == NULL) { + SSL_CTX_set1_cert_store(ctx, local_x509store); + ssl_rc = proxysql_SSL_CTX_local_x509store_add_file(ctx, mysql->options.ssl_ca, 1); + } else { + // default behavior + ssl_rc = SSL_CTX_load_verify_locations(ctx, mysql->options.ssl_ca, - mysql->options.ssl_capath)) - { + mysql->options.ssl_capath); + if (ssl_rc == 1) { + if (local_x509store == NULL) + if (SSL_CTX_get_cert_store(ctx) != NULL) { + local_x509store = SSL_CTX_get_cert_store(ctx); + thread_ctx = SSL_CTX_new(TLS_client_method()); + SSL_CTX_set1_cert_store(thread_ctx, local_x509store); + if (mysql->options.ssl_ca != NULL) { + proxysql_SSL_CTX_local_x509store_add_file(ctx,mysql->options.ssl_ca, 0); + } + } + } + } + if (ssl_rc == 0) { if (mysql->options.ssl_ca || mysql->options.ssl_capath) goto error; if (SSL_CTX_set_default_verify_paths(ctx) == 0)