You've already forked mariadb-connector-c
mirror of
https://github.com/mariadb-corporation/mariadb-connector-c.git
synced 2025-08-08 14:02:17 +03:00
SSL fixes:
- added MARIADB_OPT_SSL_CIPHER_STRENGTH (value uint) for Schannel - fixed mutes in all ssl variants
This commit is contained in:
@@ -53,6 +53,7 @@ struct st_mysql_options_extension {
|
||||
char *ssl_fp_list; /* white list of finger prints */
|
||||
char *ssl_pw; /* password for encrypted certificates */
|
||||
char *url; /* for connection handler we need to save URL for reconnect */
|
||||
unsigned int ssl_cipher_strength;
|
||||
my_bool read_only;
|
||||
char *connection_handler;
|
||||
HASH userdata;
|
||||
|
@@ -221,6 +221,7 @@ extern unsigned int mariadb_deinitialize_ssl;
|
||||
MARIADB_OPT_CONNECTION_READ_ONLY,
|
||||
MYSQL_OPT_CONNECT_ATTRS, /* for mysql_get_optionv */
|
||||
MARIADB_OPT_USERDATA,
|
||||
MARIADB_OPT_SSL_CIPHER_STRENGTH,
|
||||
MARIADB_OPT_CONNECTION_HANDLER
|
||||
};
|
||||
|
||||
|
@@ -2930,6 +2930,9 @@ mysql_optionsv(MYSQL *mysql,enum mysql_option option, ...)
|
||||
my_free(mysql->options.bind_address);
|
||||
mysql->options.bind_address= my_strdup(arg1, MYF(MY_WME));
|
||||
break;
|
||||
case MARIADB_OPT_SSL_CIPHER_STRENGTH:
|
||||
OPT_SET_EXTENDED_VALUE_INT(&mysql->options, ssl_cipher_strength, *((unsigned int *)arg1));
|
||||
break;
|
||||
case MARIADB_OPT_SSL_FP:
|
||||
OPT_SET_EXTENDED_VALUE_STR(&mysql->options, ssl_fp, (char *)arg1);
|
||||
break;
|
||||
@@ -3108,6 +3111,9 @@ mysql_get_optionv(MYSQL *mysql, enum mysql_option option, void *arg, ...)
|
||||
case MYSQL_OPT_BIND:
|
||||
*((char **)arg)= mysql->options.bind_address;
|
||||
break;
|
||||
case MARIADB_OPT_SSL_CIPHER_STRENGTH:
|
||||
*((unsigned int *)arg) = mysql->options.extension ? mysql->options.extension->ssl_cipher_strength : 0;
|
||||
break;
|
||||
case MARIADB_OPT_SSL_FP:
|
||||
*((char **)arg)= mysql->options.extension ? mysql->options.extension->ssl_fp : NULL;
|
||||
break;
|
||||
|
@@ -521,7 +521,8 @@ my_bool ma_pvio_start_ssl(MARIADB_PVIO *pvio)
|
||||
return 1;
|
||||
|
||||
if (pvio->mysql->options.extension &&
|
||||
(pvio->mysql->options.extension->ssl_fp || pvio->mysql->options.extension->ssl_fp_list))
|
||||
(pvio->mysql->options.extension->ssl_fp && pvio->mysql->options.extension->ssl_fp[0]) ||
|
||||
(pvio->mysql->options.extension->ssl_fp_list && pvio->mysql->options.extension->ssl_fp_list[0]))
|
||||
{
|
||||
|
||||
if (ma_pvio_ssl_check_fp(pvio->cssl,
|
||||
|
@@ -140,6 +140,7 @@ my_bool ma_pvio_ssl_check_fp(MARIADB_SSL *cssl, const char *fp, const char *fp_l
|
||||
unsigned int cert_fp_len= 64;
|
||||
unsigned char cert_fp[64];
|
||||
my_bool rc=1;
|
||||
MYSQL *mysql= cssl->pvio->mysql;
|
||||
|
||||
if ((cert_fp_len= ma_ssl_get_finger_print(cssl, cert_fp, cert_fp_len)) < 1)
|
||||
goto end;
|
||||
@@ -147,20 +148,15 @@ my_bool ma_pvio_ssl_check_fp(MARIADB_SSL *cssl, const char *fp, const char *fp_l
|
||||
rc= ma_pvio_ssl_compare_fp(cert_fp, cert_fp_len, (char *)fp, (unsigned int)strlen(fp));
|
||||
else if (fp_list)
|
||||
{
|
||||
FILE *fp;
|
||||
MA_FILE *fp;
|
||||
char buff[255];
|
||||
|
||||
if (!(fp = fopen(fp_list, "r")))
|
||||
if (!(fp = ma_open(fp_list, "r", mysql)))
|
||||
{
|
||||
/*
|
||||
my_set_error(mysql, CR_SSL_CONNECTION_ERROR, SQLSTATE_UNKNOWN,
|
||||
ER(CR_SSL_CONNECTION_ERROR),
|
||||
"Can't open finger print list");
|
||||
*/
|
||||
goto end;
|
||||
return 1;
|
||||
}
|
||||
|
||||
while (fgets(buff, sizeof(buff)-1, fp))
|
||||
while (ma_gets(buff, sizeof(buff)-1, fp))
|
||||
{
|
||||
/* remove trailing new line character */
|
||||
char *pos= strchr(buff, '\r');
|
||||
@@ -172,18 +168,23 @@ my_bool ma_pvio_ssl_check_fp(MARIADB_SSL *cssl, const char *fp, const char *fp_l
|
||||
if (!ma_pvio_ssl_compare_fp(cert_fp, cert_fp_len, buff, (unsigned int)strlen(buff)))
|
||||
{
|
||||
/* finger print is valid: close file and exit */
|
||||
fclose(fp);
|
||||
ma_close(fp);
|
||||
rc= 0;
|
||||
goto end;
|
||||
}
|
||||
}
|
||||
|
||||
/* No finger print matched - close file and return error */
|
||||
fclose(fp);
|
||||
ma_close(fp);
|
||||
}
|
||||
|
||||
|
||||
end:
|
||||
if (rc)
|
||||
{
|
||||
my_set_error(mysql, CR_SSL_CONNECTION_ERROR, SQLSTATE_UNKNOWN,
|
||||
ER(CR_SSL_CONNECTION_ERROR),
|
||||
"Fingerprint verification of server certificate failed");
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
#endif /* HAVE_SSL */
|
||||
|
@@ -97,20 +97,20 @@ int ma_ssl_start(char *errmsg, size_t errmsg_len)
|
||||
{
|
||||
int rc= 0;
|
||||
|
||||
if (ma_ssl_initialized)
|
||||
return 0;
|
||||
|
||||
pthread_mutex_init(&LOCK_gnutls_config,MY_MUTEX_INIT_FAST);
|
||||
pthread_mutex_lock(&LOCK_gnutls_config);
|
||||
|
||||
if (!ma_ssl_initialized)
|
||||
if ((rc= gnutls_global_init()) != GNUTLS_E_SUCCESS)
|
||||
{
|
||||
if ((rc= gnutls_global_init()) != GNUTLS_E_SUCCESS)
|
||||
{
|
||||
ma_ssl_get_error(errmsg, errmsg_len, rc);
|
||||
goto end;
|
||||
}
|
||||
ma_ssl_initialized= TRUE;
|
||||
ma_ssl_get_error(errmsg, errmsg_len, rc);
|
||||
goto end;
|
||||
}
|
||||
/* Allocate a global context for credentials */
|
||||
rc= gnutls_certificate_allocate_credentials(&GNUTLS_xcred);
|
||||
ma_ssl_initialized= TRUE;
|
||||
end:
|
||||
pthread_mutex_unlock(&LOCK_gnutls_config);
|
||||
return rc;
|
||||
@@ -130,9 +130,9 @@ end:
|
||||
*/
|
||||
void ma_ssl_end()
|
||||
{
|
||||
pthread_mutex_lock(&LOCK_gnutls_config);
|
||||
if (ma_ssl_initialized)
|
||||
{
|
||||
pthread_mutex_lock(&LOCK_gnutls_config);
|
||||
gnutls_certificate_free_keys(GNUTLS_xcred);
|
||||
gnutls_certificate_free_cas(GNUTLS_xcred);
|
||||
gnutls_certificate_free_crls(GNUTLS_xcred);
|
||||
@@ -141,9 +141,9 @@ void ma_ssl_end()
|
||||
if (mariadb_deinitialize_ssl)
|
||||
gnutls_global_deinit();
|
||||
ma_ssl_initialized= FALSE;
|
||||
pthread_mutex_unlock(&LOCK_gnutls_config);
|
||||
pthread_mutex_destroy(&LOCK_gnutls_config);
|
||||
}
|
||||
pthread_mutex_unlock(&LOCK_gnutls_config);
|
||||
pthread_mutex_destroy(&LOCK_gnutls_config);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@@ -387,7 +387,7 @@ end:
|
||||
SECURITY_STATUS ma_schannel_handshake_loop(MARIADB_PVIO *pvio, my_bool InitialRead, SecBuffer *pExtraData)
|
||||
{
|
||||
SecBufferDesc OutBuffer, InBuffer;
|
||||
SecBuffer InBuffers[2], OutBuffers[1];
|
||||
SecBuffer InBuffers[2], OutBuffers;
|
||||
DWORD dwSSPIFlags, dwSSPIOutFlags, cbData, cbIoBuffer;
|
||||
TimeStamp tsExpiry;
|
||||
SECURITY_STATUS rc;
|
||||
@@ -457,12 +457,12 @@ SECURITY_STATUS ma_schannel_handshake_loop(MARIADB_PVIO *pvio, my_bool InitialRe
|
||||
|
||||
|
||||
/* output buffer */
|
||||
OutBuffers[0].pvBuffer = NULL;
|
||||
OutBuffers[0].BufferType= SECBUFFER_TOKEN;
|
||||
OutBuffers[0].cbBuffer = 0;
|
||||
OutBuffers.pvBuffer = NULL;
|
||||
OutBuffers.BufferType= SECBUFFER_TOKEN;
|
||||
OutBuffers.cbBuffer = 0;
|
||||
|
||||
OutBuffer.cBuffers = 1;
|
||||
OutBuffer.pBuffers = OutBuffers;
|
||||
OutBuffer.pBuffers = &OutBuffers;
|
||||
OutBuffer.ulVersion = SECBUFFER_VERSION;
|
||||
|
||||
|
||||
@@ -484,19 +484,19 @@ SECURITY_STATUS ma_schannel_handshake_loop(MARIADB_PVIO *pvio, my_bool InitialRe
|
||||
rc == SEC_I_CONTINUE_NEEDED ||
|
||||
FAILED(rc) && (dwSSPIOutFlags & ISC_RET_EXTENDED_ERROR))
|
||||
{
|
||||
if(OutBuffers[0].cbBuffer && OutBuffers[0].pvBuffer)
|
||||
if(OutBuffers.cbBuffer && OutBuffers.pvBuffer)
|
||||
{
|
||||
cbData= (DWORD)pvio->methods->write(pvio, (uchar *)OutBuffers[0].pvBuffer, (size_t)OutBuffers[0].cbBuffer);
|
||||
cbData= (DWORD)pvio->methods->write(pvio, (uchar *)OutBuffers.pvBuffer, (size_t)OutBuffers.cbBuffer);
|
||||
if(cbData == SOCKET_ERROR || cbData == 0)
|
||||
{
|
||||
FreeContextBuffer(OutBuffers[0].pvBuffer);
|
||||
FreeContextBuffer(OutBuffers.pvBuffer);
|
||||
DeleteSecurityContext(&sctx->ctxt);
|
||||
return SEC_E_INTERNAL_ERROR;
|
||||
}
|
||||
|
||||
/* Free output context buffer */
|
||||
FreeContextBuffer(OutBuffers[0].pvBuffer);
|
||||
OutBuffers[0].pvBuffer = NULL;
|
||||
FreeContextBuffer(OutBuffers.pvBuffer);
|
||||
OutBuffers.pvBuffer = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -589,7 +589,7 @@ SECURITY_STATUS ma_schannel_client_handshake(MARIADB_SSL *cssl)
|
||||
ISC_REQ_ALLOCATE_MEMORY | ISC_REQ_STREAM;
|
||||
|
||||
SecBufferDesc BufferOut;
|
||||
SecBuffer BuffersOut[1];
|
||||
SecBuffer BuffersOut;
|
||||
|
||||
if (!cssl || !cssl->pvio)
|
||||
return 1;
|
||||
@@ -598,13 +598,13 @@ SECURITY_STATUS ma_schannel_client_handshake(MARIADB_SSL *cssl)
|
||||
sctx= (SC_CTX *)cssl->ssl;
|
||||
|
||||
/* Initialie securifty context */
|
||||
BuffersOut[0].BufferType= SECBUFFER_TOKEN;
|
||||
BuffersOut[0].cbBuffer= 0;
|
||||
BuffersOut[0].pvBuffer= NULL;
|
||||
BuffersOut.BufferType= SECBUFFER_TOKEN;
|
||||
BuffersOut.cbBuffer= 0;
|
||||
BuffersOut.pvBuffer= NULL;
|
||||
|
||||
|
||||
BufferOut.cBuffers= 1;
|
||||
BufferOut.pBuffers= BuffersOut;
|
||||
BufferOut.pBuffers= &BuffersOut;
|
||||
BufferOut.ulVersion= SECBUFFER_VERSION;
|
||||
|
||||
sRet = InitializeSecurityContext(&sctx->CredHdl,
|
||||
@@ -627,9 +627,9 @@ SECURITY_STATUS ma_schannel_client_handshake(MARIADB_SSL *cssl)
|
||||
}
|
||||
|
||||
/* send client hello packaet */
|
||||
if(BuffersOut[0].cbBuffer != 0 && BuffersOut[0].pvBuffer != NULL)
|
||||
if(BuffersOut.cbBuffer != 0 && BuffersOut.pvBuffer != NULL)
|
||||
{
|
||||
r= (DWORD)pvio->methods->write(pvio, (uchar *)BuffersOut[0].pvBuffer, (size_t)BuffersOut[0].cbBuffer);
|
||||
r= (DWORD)pvio->methods->write(pvio, (uchar *)BuffersOut.pvBuffer, (size_t)BuffersOut.cbBuffer);
|
||||
if (r <= 0)
|
||||
{
|
||||
sRet= SEC_E_INTERNAL_ERROR;
|
||||
@@ -654,7 +654,7 @@ SECURITY_STATUS ma_schannel_client_handshake(MARIADB_SSL *cssl)
|
||||
end:
|
||||
LocalFree(sctx->IoBuffer);
|
||||
sctx->IoBufferSize= 0;
|
||||
FreeContextBuffer(BuffersOut[0].pvBuffer);
|
||||
FreeContextBuffer(BuffersOut.pvBuffer);
|
||||
DeleteSecurityContext(&sctx->ctxt);
|
||||
return sRet;
|
||||
}
|
||||
@@ -782,6 +782,9 @@ my_bool ma_schannel_verify_certs(SC_CTX *sctx, DWORD dwCertFlags)
|
||||
DWORD flags;
|
||||
MARIADB_PVIO *pvio= sctx->mysql->net.pvio;
|
||||
PCCERT_CONTEXT pServerCert= NULL;
|
||||
PCERT_CONTEXT ca_CTX = NULL;
|
||||
PCRL_CONTEXT crl_CTX = NULL;
|
||||
my_bool is_Ok = 0;
|
||||
|
||||
if ((sRet= QueryContextAttributes(&sctx->ctxt, SECPKG_ATTR_REMOTE_CERT_CONTEXT, (PVOID)&pServerCert)) != SEC_E_OK)
|
||||
{
|
||||
@@ -789,16 +792,22 @@ my_bool ma_schannel_verify_certs(SC_CTX *sctx, DWORD dwCertFlags)
|
||||
return 0;
|
||||
}
|
||||
|
||||
flags= CERT_STORE_SIGNATURE_FLAG |
|
||||
CERT_STORE_TIME_VALIDITY_FLAG;
|
||||
|
||||
|
||||
|
||||
if (sctx->client_ca_ctx)
|
||||
if (ca_Check)
|
||||
{
|
||||
if (!(sRet= CertVerifySubjectCertificateContext(pServerCert,
|
||||
sctx->client_ca_ctx,
|
||||
&flags)))
|
||||
flags = CERT_STORE_SIGNATURE_FLAG |
|
||||
CERT_STORE_TIME_VALIDITY_FLAG;
|
||||
|
||||
while ((ca_CTX = CertFindCertificateInStore(ca_CertStore, PKCS_7_ASN_ENCODING | X509_ASN_ENCODING,
|
||||
0, CERT_FIND_ANY, 0, ca_CTX)) && !is_Ok)
|
||||
{
|
||||
if (sRet = CertVerifySubjectCertificateContext(pServerCert, ca_CTX, &flags))
|
||||
is_Ok = 1;
|
||||
}
|
||||
|
||||
if (ca_CTX)
|
||||
CertFreeCertificateContext(ca_CTX);
|
||||
|
||||
if (!is_Ok)
|
||||
{
|
||||
ma_schannel_set_win_error(pvio);
|
||||
return 0;
|
||||
@@ -819,18 +828,23 @@ my_bool ma_schannel_verify_certs(SC_CTX *sctx, DWORD dwCertFlags)
|
||||
}
|
||||
|
||||
/* Check if none of the certificates in the certificate chain have been revoked. */
|
||||
if (sctx->client_crl_ctx)
|
||||
if (crl_Check)
|
||||
{
|
||||
PCRL_INFO Info[1];
|
||||
|
||||
Info[0]= sctx->client_crl_ctx->pCrlInfo;
|
||||
if (!(CertVerifyCRLRevocation(X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
|
||||
pServerCert->pCertInfo,
|
||||
1, Info)) )
|
||||
while ((crl_CTX = CertEnumCRLsInStore(crl_CertStore, crl_CTX)))
|
||||
{
|
||||
pvio->set_error(pvio->mysql, CR_SSL_CONNECTION_ERROR, SQLSTATE_UNKNOWN, "CRL Revocation failed");
|
||||
return 0;
|
||||
PCRL_INFO Info[1];
|
||||
|
||||
Info[0] = crl_CTX->pCrlInfo;
|
||||
if (!(CertVerifyCRLRevocation(X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
|
||||
pServerCert->pCertInfo,
|
||||
1, Info)))
|
||||
{
|
||||
CertFreeCRLContext(crl_CTX);
|
||||
pvio->set_error(pvio->mysql, CR_SSL_CONNECTION_ERROR, SQLSTATE_UNKNOWN, "CRL Revocation failed");
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
CertFreeCRLContext(crl_CTX);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
@@ -56,19 +56,10 @@ typedef void VOID;
|
||||
struct st_schannel {
|
||||
HCERTSTORE cert_store;
|
||||
CERT_CONTEXT *client_cert_ctx;
|
||||
CERT_CONTEXT *client_ca_ctx;
|
||||
CRL_CONTEXT *client_crl_ctx;
|
||||
CredHandle CredHdl;
|
||||
my_bool FreeCredHdl;
|
||||
PUCHAR IoBuffer;
|
||||
DWORD IoBufferSize;
|
||||
/* PUCHAR EncryptBuffer;
|
||||
DWORD EncryptBufferSize;
|
||||
DWORD EncryptBufferLength;
|
||||
PUCHAR DecryptBuffer;
|
||||
DWORD DecryptBufferSize;
|
||||
DWORD DecryptBufferLength;
|
||||
uchar thumbprint[21]; */
|
||||
SecPkgContext_StreamSizes Sizes;
|
||||
|
||||
CtxtHandle ctxt;
|
||||
@@ -77,6 +68,9 @@ struct st_schannel {
|
||||
|
||||
typedef struct st_schannel SC_CTX;
|
||||
|
||||
extern HCERTSTORE ca_CertStore, crl_CertStore;
|
||||
extern my_bool ca_Check, crl_Check;
|
||||
|
||||
CERT_CONTEXT *ma_schannel_create_cert_context(MARIADB_PVIO *pvio, const char *pem_file);
|
||||
SECURITY_STATUS ma_schannel_client_handshake(MARIADB_SSL *cssl);
|
||||
SECURITY_STATUS ma_schannel_handshake_loop(MARIADB_PVIO *pvio, my_bool InitialRead, SecBuffer *pExtraData);
|
||||
|
@@ -159,37 +159,37 @@ static int ssl_thread_init()
|
||||
int ma_ssl_start(char *errmsg, size_t errmsg_len)
|
||||
{
|
||||
int rc= 1;
|
||||
if (ma_ssl_initialized)
|
||||
return 0;
|
||||
|
||||
/* lock mutex to prevent multiple initialization */
|
||||
pthread_mutex_init(&LOCK_openssl_config,MY_MUTEX_INIT_FAST);
|
||||
pthread_mutex_lock(&LOCK_openssl_config);
|
||||
if (!ma_ssl_initialized)
|
||||
if (ssl_thread_init())
|
||||
{
|
||||
if (ssl_thread_init())
|
||||
{
|
||||
strncpy(errmsg, "Not enough memory", errmsg_len);
|
||||
goto end;
|
||||
}
|
||||
SSL_library_init();
|
||||
strncpy(errmsg, "Not enough memory", errmsg_len);
|
||||
goto end;
|
||||
}
|
||||
SSL_library_init();
|
||||
|
||||
#if SSLEAY_VERSION_NUMBER >= 0x00907000L
|
||||
OPENSSL_config(NULL);
|
||||
OPENSSL_config(NULL);
|
||||
#endif
|
||||
/* load errors */
|
||||
SSL_load_error_strings();
|
||||
/* digests and ciphers */
|
||||
OpenSSL_add_all_algorithms();
|
||||
/* load errors */
|
||||
SSL_load_error_strings();
|
||||
/* digests and ciphers */
|
||||
OpenSSL_add_all_algorithms();
|
||||
#if (OPENSSL_VERSION_NUMBER >= 0x10100000L)
|
||||
if (!(SSL_context= SSL_CTX_new(TLS_client_method())))
|
||||
if (!(SSL_context= SSL_CTX_new(TLS_client_method())))
|
||||
#else
|
||||
if (!(SSL_context= SSL_CTX_new(SSLv23_client_method())))
|
||||
if (!(SSL_context= SSL_CTX_new(SSLv23_client_method())))
|
||||
#endif
|
||||
{
|
||||
ma_ssl_get_error(errmsg, errmsg_len);
|
||||
goto end;
|
||||
}
|
||||
rc= 0;
|
||||
ma_ssl_initialized= TRUE;
|
||||
{
|
||||
ma_ssl_get_error(errmsg, errmsg_len);
|
||||
goto end;
|
||||
}
|
||||
rc= 0;
|
||||
ma_ssl_initialized= TRUE;
|
||||
end:
|
||||
pthread_mutex_unlock(&LOCK_openssl_config);
|
||||
return rc;
|
||||
@@ -209,10 +209,10 @@ end:
|
||||
*/
|
||||
void ma_ssl_end()
|
||||
{
|
||||
pthread_mutex_lock(&LOCK_openssl_config);
|
||||
if (ma_ssl_initialized)
|
||||
{
|
||||
int i;
|
||||
pthread_mutex_lock(&LOCK_openssl_config);
|
||||
CRYPTO_set_locking_callback(NULL);
|
||||
CRYPTO_set_id_callback(NULL);
|
||||
|
||||
@@ -238,9 +238,9 @@ void ma_ssl_end()
|
||||
sk_SSL_COMP_free(SSL_COMP_get_compression_methods());
|
||||
}
|
||||
ma_ssl_initialized= FALSE;
|
||||
pthread_mutex_unlock(&LOCK_openssl_config);
|
||||
pthread_mutex_destroy(&LOCK_openssl_config);
|
||||
}
|
||||
pthread_mutex_unlock(&LOCK_openssl_config);
|
||||
pthread_mutex_destroy(&LOCK_openssl_config);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@@ -34,61 +34,57 @@ struct st_cipher_suite {
|
||||
CHAR *cipher;
|
||||
};
|
||||
|
||||
const struct st_cipher_suite valid_ciphers[] =
|
||||
{
|
||||
{ CALG_3DES, "CALG_3DES" },
|
||||
{ CALG_3DES_112, "CALG_3DES_112" },
|
||||
{ CALG_AES, "CALG_AES" },
|
||||
{ CALG_AES_128, "CALG_AES_128" },
|
||||
{ CALG_AES_192, "CALG_AES_192" },
|
||||
{ CALG_AES_256, "CALG_AES_256" },
|
||||
{ CALG_AGREEDKEY_ANY, "CALG_AGREEDKEY_ANY" },
|
||||
{ CALG_CYLINK_MEK, "CALG_CYLINK_MEK" },
|
||||
{ CALG_DES, "CALG_DES" },
|
||||
{ CALG_DESX, "CALG_DESX" },
|
||||
{ CALG_DH_EPHEM, "CALG_DH_EPHEM" },
|
||||
{ CALG_DH_SF, "CALG_DH_SF" },
|
||||
{ CALG_DSS_SIGN, "CALG_DSS_SIGN" },
|
||||
{ CALG_ECDH, "CALG_ECDH" },
|
||||
{ CALG_ECDSA, "CALG_ECDSA" },
|
||||
{ CALG_ECMQV, "CALG_ECMQV" },
|
||||
{ CALG_HASH_REPLACE_OWF, "CALG_HASH_REPLACE_OWF" },
|
||||
{ CALG_HUGHES_MD5, "CALG_HUGHES_MD5" },
|
||||
{ CALG_HMAC, "CALG_HMAC" },
|
||||
{ CALG_KEA_KEYX, "CALG_KEA_KEYX" },
|
||||
{ CALG_MAC, "CALG_MAC" },
|
||||
{ CALG_MD2, "CALG_MD2" },
|
||||
{ CALG_MD4, "CALG_MD4" },
|
||||
{ CALG_MD4, "CALG_MD5" },
|
||||
{ CALG_NO_SIGN, "CALG_NO_SIGN" },
|
||||
{ CALG_OID_INFO_CNG_ONLY, "CALG_OID_INFO_CNG_ONLY" },
|
||||
{ CALG_OID_INFO_PARAMETERS, "CALG_OID_INFO_PARAMETERS" },
|
||||
{ CALG_RC2, "CALG_RC2" },
|
||||
{ CALG_RC4, "CALG_RC4" },
|
||||
{ CALG_RC5, "CALG_RC5" },
|
||||
{ CALG_RSA_KEYX, "CALG_RSA_KEYX" },
|
||||
{ CALG_RSA_SIGN, "CALG_RSA_SIGN" },
|
||||
{ CALG_SHA, "CALG_SHA" },
|
||||
{ CALG_SHA1, "CALG_SHA1" },
|
||||
{ CALG_SHA_256, "CALG_SHA_256" },
|
||||
{ CALG_SHA_384, "CALG_SHA_384" },
|
||||
{ CALG_SHA_512, "CALG_SHA_512" },
|
||||
{ 0, NULL }
|
||||
};
|
||||
|
||||
#define MAX_ALG_ID 50
|
||||
|
||||
void ma_schannel_set_sec_error(MARIADB_PVIO *pvio, DWORD ErrorNo);
|
||||
void ma_schannel_set_win_error(MYSQL *mysql);
|
||||
|
||||
const struct st_cipher_suite sc_ciphers[]=
|
||||
{
|
||||
{CALG_3DES, "CALG_3DES"},
|
||||
{CALG_3DES_112, "CALG_3DES_112"},
|
||||
{CALG_AES, "CALG_AES"},
|
||||
{CALG_AES_128, "CALG_AES_128"},
|
||||
{CALG_AES_192, "CALG_AES_192"},
|
||||
{CALG_AES_256, "CALG_AES_256"},
|
||||
{CALG_AGREEDKEY_ANY, "CALG_AGREEDKEY_ANY"},
|
||||
{CALG_CYLINK_MEK, "CALG_CYLINK_MEK"},
|
||||
{CALG_DES, "CALG_DES"},
|
||||
{CALG_DESX, "CALG_DESX"},
|
||||
{CALG_DH_EPHEM, "CALG_DH_EPHEM"},
|
||||
{CALG_DH_SF, "CALG_DH_SF"},
|
||||
{CALG_DSS_SIGN, "CALG_DSS_SIGN"},
|
||||
{CALG_ECDH, "CALG_ECDH"},
|
||||
{CALG_ECDSA, "CALG_ECDSA"},
|
||||
{CALG_ECMQV, "CALG_ECMQV"},
|
||||
{CALG_HASH_REPLACE_OWF, "CALG_HASH_REPLACE_OWF"},
|
||||
{CALG_HUGHES_MD5, "CALG_HUGHES_MD5"},
|
||||
{CALG_HMAC, "CALG_HMAC"},
|
||||
{CALG_KEA_KEYX, "CALG_KEA_KEYX"},
|
||||
{CALG_MAC, "CALG_MAC"},
|
||||
{CALG_MD2, "CALG_MD2"},
|
||||
{CALG_MD4, "CALG_MD4"},
|
||||
{CALG_MD4, "CALG_MD5"},
|
||||
{CALG_NO_SIGN, "CALG_NO_SIGN"},
|
||||
{CALG_OID_INFO_CNG_ONLY, "CALG_OID_INFO_CNG_ONLY"},
|
||||
{CALG_OID_INFO_PARAMETERS, "CALG_OID_INFO_PARAMETERS"},
|
||||
{CALG_PCT1_MASTER, "CALG_PCT1_MASTER"},
|
||||
{CALG_RC2, "CALG_RC2"},
|
||||
{CALG_RC4, "CALG_RC4"},
|
||||
{CALG_RC5, "CALG_RC5"},
|
||||
{CALG_RSA_KEYX, "CALG_RSA_KEYX"},
|
||||
{CALG_RSA_SIGN, "CALG_RSA_SIGN"},
|
||||
{CALG_SCHANNEL_MAC_KEY, "CALG_SCHANNEL_MAC_KEY"},
|
||||
{CALG_SCHANNEL_MASTER_HASH, "CALG_SCHANNEL_MASTER_HASH"},
|
||||
{CALG_SEAL, "CALG_SEAL"},
|
||||
{CALG_SHA, "CALG_SHA"},
|
||||
{CALG_SHA1, "CALG_SHA1"},
|
||||
{CALG_SHA_256, "CALG_SHA_256"},
|
||||
{CALG_SHA_384, "CALG_SHA_384"},
|
||||
{CALG_SHA_512, "CALG_SHA_512"},
|
||||
{CALG_SKIPJACK, "CALG_SKIPJACK"},
|
||||
{CALG_SSL2_MASTER, "CALG_SSL2_MASTER"},
|
||||
{CALG_SSL3_MASTER, "CALG_SSL3_MASTER"},
|
||||
{CALG_SSL3_SHAMD5, "CALG_SSL3_SHAMD5"},
|
||||
{CALG_TEK, "CALG_TEK"},
|
||||
{CALG_TLS1_MASTER, "CALG_TLS1_MASTER"},
|
||||
{CALG_TLS1PRF, "CALG_TLS1PRF"},
|
||||
{0, NULL}
|
||||
};
|
||||
HCERTSTORE ca_CertStore= NULL,
|
||||
crl_CertStore= NULL;
|
||||
my_bool ca_Check = 0, crl_Check = 0;
|
||||
|
||||
|
||||
static int ssl_thread_init()
|
||||
{
|
||||
@@ -113,7 +109,17 @@ int ma_ssl_start(char *errmsg, size_t errmsg_len)
|
||||
{
|
||||
pthread_mutex_init(&LOCK_schannel_config,MY_MUTEX_INIT_FAST);
|
||||
pthread_mutex_lock(&LOCK_schannel_config);
|
||||
ma_ssl_initialized= TRUE;
|
||||
if (!ca_CertStore)
|
||||
{
|
||||
if (!(ca_CertStore = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0, 0, NULL)) ||
|
||||
!(crl_CertStore = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0, 0, NULL)))
|
||||
{
|
||||
snprintf(errmsg, errmsg_len, "Can't open in-memory certstore. Error=%d", GetLastError());
|
||||
return 1;
|
||||
}
|
||||
|
||||
}
|
||||
ma_ssl_initialized = TRUE;
|
||||
pthread_mutex_unlock(&LOCK_schannel_config);
|
||||
}
|
||||
return 0;
|
||||
@@ -133,14 +139,23 @@ int ma_ssl_start(char *errmsg, size_t errmsg_len)
|
||||
*/
|
||||
void ma_ssl_end()
|
||||
{
|
||||
pthread_mutex_lock(&LOCK_schannel_config);
|
||||
if (ma_ssl_initialized)
|
||||
{
|
||||
|
||||
pthread_mutex_lock(&LOCK_schannel_config);
|
||||
if (ca_CertStore)
|
||||
{
|
||||
CertCloseStore(ca_CertStore, 0);
|
||||
ca_CertStore = 0;
|
||||
}
|
||||
if (crl_CertStore)
|
||||
{
|
||||
CertCloseStore(crl_CertStore, 0);
|
||||
crl_CertStore = 0;
|
||||
}
|
||||
ma_ssl_initialized= FALSE;
|
||||
pthread_mutex_unlock(&LOCK_schannel_config);
|
||||
pthread_mutex_destroy(&LOCK_schannel_config);
|
||||
}
|
||||
pthread_mutex_unlock(&LOCK_schannel_config);
|
||||
pthread_mutex_destroy(&LOCK_schannel_config);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -151,32 +166,26 @@ static int ma_ssl_set_client_certs(MARIADB_SSL *cssl)
|
||||
char *certfile= mysql->options.ssl_cert,
|
||||
*keyfile= mysql->options.ssl_key,
|
||||
*cafile= mysql->options.ssl_ca;
|
||||
PCERT_CONTEXT ca_ctx= NULL;
|
||||
PCRL_CONTEXT crl_ctx = NULL;
|
||||
|
||||
SC_CTX *sctx= (SC_CTX *)cssl->ssl;
|
||||
MARIADB_PVIO *pvio= cssl->pvio;
|
||||
|
||||
if (cafile)
|
||||
{
|
||||
HCERTSTORE myCS= NULL;
|
||||
|
||||
if (!(sctx->client_ca_ctx = ma_schannel_create_cert_context(pvio, cafile)))
|
||||
if (!(ca_ctx = ma_schannel_create_cert_context(pvio, cafile)))
|
||||
goto end;
|
||||
|
||||
/* For X509 authentication we need to add ca certificate to local MY store.
|
||||
Schannel doesn't provide a callback to send ca to server during handshake */
|
||||
if ((myCS= CertOpenStore(CERT_STORE_PROV_SYSTEM,
|
||||
0, //X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
|
||||
0,
|
||||
CERT_SYSTEM_STORE_CURRENT_USER,
|
||||
L"CA")))
|
||||
/* Add ca to in-memory certificate store */
|
||||
if (CertAddCertificateContextToStore(ca_CertStore, ca_ctx, CERT_STORE_ADD_NEWER, NULL) != TRUE &&
|
||||
GetLastError() != CRYPT_E_EXISTS)
|
||||
{
|
||||
CertAddCertificateContextToStore(myCS, sctx->client_ca_ctx, CERT_STORE_ADD_NEWER, NULL);
|
||||
CertCloseStore(myCS, 0);
|
||||
}
|
||||
else {
|
||||
ma_schannel_set_win_error(sctx->mysql);
|
||||
goto end;
|
||||
}
|
||||
ca_Check= 0;
|
||||
CertFreeCertificateContext(ca_ctx);
|
||||
}
|
||||
|
||||
if (!certfile && keyfile)
|
||||
@@ -194,20 +203,28 @@ static int ma_ssl_set_client_certs(MARIADB_SSL *cssl)
|
||||
|
||||
if (mysql->options.extension && mysql->options.extension->ssl_crl)
|
||||
{
|
||||
if (!(sctx->client_crl_ctx= (CRL_CONTEXT *)ma_schannel_create_crl_context(pvio, mysql->options.extension->ssl_crl)))
|
||||
if (!(crl_ctx= (CRL_CONTEXT *)ma_schannel_create_crl_context(pvio, mysql->options.extension->ssl_crl)))
|
||||
goto end;
|
||||
/* Add ca to in-memory certificate store */
|
||||
if (CertAddCRLContextToStore(crl_CertStore, crl_ctx, CERT_STORE_ADD_NEWER, NULL) != TRUE &&
|
||||
GetLastError() != CRYPT_E_EXISTS)
|
||||
{
|
||||
ma_schannel_set_win_error(sctx->mysql);
|
||||
goto end;
|
||||
}
|
||||
crl_Check = 1;
|
||||
CertFreeCertificateContext(ca_ctx);
|
||||
}
|
||||
return 0;
|
||||
|
||||
end:
|
||||
if (sctx->client_ca_ctx)
|
||||
CertFreeCertificateContext(sctx->client_ca_ctx);
|
||||
if (ca_ctx)
|
||||
CertFreeCertificateContext(ca_ctx);
|
||||
if (sctx->client_cert_ctx)
|
||||
CertFreeCertificateContext(sctx->client_cert_ctx);
|
||||
if (sctx->client_crl_ctx)
|
||||
CertFreeCRLContext(sctx->client_crl_ctx);
|
||||
sctx->client_ca_ctx= sctx->client_cert_ctx= NULL;
|
||||
sctx->client_crl_ctx= NULL;
|
||||
if (crl_ctx)
|
||||
CertFreeCRLContext(crl_ctx);
|
||||
sctx->client_cert_ctx= NULL;
|
||||
return 1;
|
||||
}
|
||||
/* }}} */
|
||||
@@ -243,7 +260,7 @@ my_bool ma_ssl_connect(MARIADB_SSL *cssl)
|
||||
SECURITY_STATUS sRet;
|
||||
PCCERT_CONTEXT pRemoteCertContext = NULL,
|
||||
pLocalCertContext= NULL;
|
||||
ALG_ID AlgId[2]= {0, 0};
|
||||
ALG_ID AlgId[MAX_ALG_ID]= {0};
|
||||
|
||||
if (!cssl || !cssl->pvio)
|
||||
return 1;;
|
||||
@@ -260,31 +277,42 @@ my_bool ma_ssl_connect(MARIADB_SSL *cssl)
|
||||
if (ma_ssl_set_client_certs(cssl))
|
||||
goto end;
|
||||
|
||||
ZeroMemory(&Cred, sizeof(SCHANNEL_CRED));
|
||||
|
||||
/* Set cipher */
|
||||
if (mysql->options.ssl_cipher)
|
||||
{
|
||||
DWORD i= 0;
|
||||
while (sc_ciphers[i].cipher) {
|
||||
if (!strcmp(sc_ciphers[i].cipher, mysql->options.ssl_cipher))
|
||||
WORD validTokens = 0;
|
||||
char *token = strtok(mysql->options.ssl_cipher, ":");
|
||||
while (token)
|
||||
{
|
||||
struct st_cipher_suite *valid;
|
||||
for (valid = valid_ciphers; valid && valid->aid; valid++)
|
||||
{
|
||||
AlgId[0]= sc_ciphers[i].aid;
|
||||
break;
|
||||
if (!strcmp(token, valid->cipher))
|
||||
{
|
||||
AlgId[validTokens++] = valid->aid;
|
||||
break;
|
||||
}
|
||||
}
|
||||
token = strtok(NULL, ":");
|
||||
}
|
||||
Cred.palgSupportedAlgs= (ALG_ID *)&AlgId;
|
||||
}
|
||||
Cred.palgSupportedAlgs = (ALG_ID *)&AlgId;
|
||||
|
||||
|
||||
ZeroMemory(&Cred, sizeof(SCHANNEL_CRED));
|
||||
Cred.dwVersion= SCHANNEL_CRED_VERSION;
|
||||
if (mysql->options.extension)
|
||||
Cred.dwMinimumCipherStrength = MAX(128, mysql->options.extension->ssl_cipher_strength);
|
||||
else
|
||||
Cred.dwMinimumCipherStrength = 128;
|
||||
Cred.dwFlags |= SCH_CRED_NO_SERVERNAME_CHECK | SCH_SEND_ROOT_CERT |
|
||||
SCH_CRED_NO_DEFAULT_CREDS | SCH_CRED_MANUAL_CRED_VALIDATION;
|
||||
SCH_CRED_NO_DEFAULT_CREDS | SCH_CRED_MANUAL_CRED_VALIDATION;
|
||||
if (sctx->client_cert_ctx)
|
||||
{
|
||||
Cred.cCreds = 1;
|
||||
Cred.paCred = &sctx->client_cert_ctx;
|
||||
}
|
||||
Cred.grbitEnabledProtocols= SP_PROT_TLS1_1PLUS;
|
||||
Cred.grbitEnabledProtocols = SP_PROT_TLS1_0 | SP_PROT_TLS1_1 | SP_PROT_TLS1_2;
|
||||
|
||||
if ((sRet= AcquireCredentialsHandleA(NULL, UNISP_NAME_A, SECPKG_CRED_OUTBOUND,
|
||||
NULL, &Cred, NULL, NULL, &sctx->CredHdl, NULL)) != SEC_E_OK)
|
||||
@@ -315,15 +343,9 @@ end:
|
||||
if (rc && sctx->IoBufferSize)
|
||||
LocalFree(sctx->IoBuffer);
|
||||
sctx->IoBufferSize= 0;
|
||||
if (sctx->client_ca_ctx)
|
||||
CertFreeCertificateContext(sctx->client_ca_ctx);
|
||||
if (sctx->client_cert_ctx)
|
||||
CertFreeCertificateContext(sctx->client_cert_ctx);
|
||||
if (sctx->client_crl_ctx)
|
||||
CertFreeCRLContext(sctx->client_crl_ctx);
|
||||
sctx->client_ca_ctx= 0;
|
||||
sctx->client_cert_ctx= 0;
|
||||
sctx->client_crl_ctx= 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -363,12 +385,8 @@ my_bool ma_ssl_close(MARIADB_SSL *cssl)
|
||||
{
|
||||
if (sctx->IoBufferSize)
|
||||
LocalFree(sctx->IoBuffer);
|
||||
if (sctx->client_ca_ctx)
|
||||
CertFreeCertificateContext(sctx->client_ca_ctx);
|
||||
if (sctx->client_cert_ctx)
|
||||
CertFreeCertificateContext(sctx->client_cert_ctx);
|
||||
if (sctx->client_crl_ctx)
|
||||
CertFreeCRLContext(sctx->client_crl_ctx);
|
||||
FreeCredentialHandle(&sctx->CredHdl);
|
||||
DeleteSecurityContext(&sctx->ctxt);
|
||||
}
|
||||
@@ -458,10 +476,10 @@ const char *ma_ssl_get_cipher(MARIADB_SSL *cssl)
|
||||
if (sRet != SEC_E_OK)
|
||||
return NULL;
|
||||
|
||||
while (sc_ciphers[i].cipher)
|
||||
while (valid_ciphers[i].cipher)
|
||||
{
|
||||
if (sc_ciphers[i].aid == cinfo.aiCipher)
|
||||
return sc_ciphers[i].cipher;
|
||||
if (valid_ciphers[i].aid == cinfo.aiCipher)
|
||||
return valid_ciphers[i].cipher;
|
||||
i++;
|
||||
}
|
||||
return NULL;
|
||||
|
@@ -51,21 +51,21 @@ IF(WITH_SSL AND OPENSSL_FOUND)
|
||||
STRING(REPLACE "\n" "" FINGER_PRINT "${FINGER_PRINT}")
|
||||
STRING(REPLACE ":" "" SSL_CERT_FINGER_PRINT "${FINGER_PRINT}")
|
||||
|
||||
ENDIF()
|
||||
CONFIGURE_FILE(${CMAKE_SOURCE_DIR}/unittest/libmariadb/ssl.c.in
|
||||
${CMAKE_SOURCE_DIR}/unittest/libmariadb/ssl.c)
|
||||
CONFIGURE_FILE(${CMAKE_SOURCE_DIR}/unittest/libmariadb/fingerprint.list.in
|
||||
${CMAKE_SOURCE_DIR}/unittest/libmariadb/fingerprint.list)
|
||||
SET(API_TESTS ${API_TESTS} "ssl")
|
||||
ENDIF()
|
||||
SET(API_TESTS ${API_TESTS} "ssl")
|
||||
|
||||
FOREACH(API_TEST ${API_TESTS})
|
||||
ADD_EXECUTABLE(${API_TEST} ${API_TEST}.c ${CMAKE_SOURCE_DIR}/libmariadb/getopt.c)
|
||||
TARGET_LINK_LIBRARIES(${API_TEST} mytap libmariadb)
|
||||
TARGET_LINK_LIBRARIES(${API_TEST} mytap mariadbclient)
|
||||
ADD_TEST(${API_TEST} ${EXECUTABLE_OUTPUT_PATH}/${API_TEST})
|
||||
SET_TESTS_PROPERTIES(${API_TEST} PROPERTIES TIMEOUT 120)
|
||||
ENDFOREACH(API_TEST)
|
||||
|
||||
FOREACH(API_TEST ${MANUAL_TESTS})
|
||||
ADD_EXECUTABLE(${API_TEST} ${API_TEST}.c ${CMAKE_SOURCE_DIR}/libmariadb/getopt.c)
|
||||
TARGET_LINK_LIBRARIES(${API_TEST} mytap libmariadb)
|
||||
TARGET_LINK_LIBRARIES(${API_TEST} mytap mariadbclient)
|
||||
ENDFOREACH()
|
||||
|
@@ -794,6 +794,33 @@ static int test_ssl_version(MYSQL *mysql)
|
||||
return OK;
|
||||
}
|
||||
|
||||
#ifdef HAVE_SCHANNEL
|
||||
static int test_schannel_cipher(MYSQL *mysql)
|
||||
{
|
||||
MYSQL *my;
|
||||
unsigned int cipher_strength= 256;
|
||||
|
||||
if (check_skip_ssl())
|
||||
return SKIP;
|
||||
|
||||
my= mysql_init(NULL);
|
||||
FAIL_IF(!my, "mysql_init() failed");
|
||||
|
||||
mysql_ssl_set(my,0, 0, "@CMAKE_SOURCE_DIR@/unittest/libmariadb/certs/ca-cert.pem", 0, 0);
|
||||
mysql_options(my, MARIADB_OPT_SSL_CIPHER_STRENGTH, &cipher_strength);
|
||||
FAIL_IF(!mysql_real_connect(my, hostname, ssluser, sslpw, schema,
|
||||
port, socketname, 0), mysql_error(my));
|
||||
|
||||
diag("cipher: %s", mysql_get_ssl_cipher(my));
|
||||
FAIL_IF(strcmp(mysql_get_ssl_cipher(my), "CALG_AES_256") != 0, "expected cipher with 256bit strength");
|
||||
|
||||
mysql_close(my);
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
struct my_tests_st my_tests[] = {
|
||||
{"test_ssl", test_ssl, TEST_CONNECTION_NEW, 0, NULL, NULL},
|
||||
@@ -816,6 +843,8 @@ struct my_tests_st my_tests[] = {
|
||||
{"test_ssl_threads", test_ssl_threads, TEST_CONNECTION_NEW, 0, NULL, NULL},
|
||||
#ifndef HAVE_SCHANNEL
|
||||
{"test_password_protected", test_password_protected, TEST_CONNECTION_NEW, 0, NULL, NULL},
|
||||
#else
|
||||
{"test_schannel_cipher", test_schannel_cipher, TEST_CONNECTION_NEW, 0, NULL, NULL},
|
||||
#endif
|
||||
{NULL, NULL, 0, 0, NULL, NULL}
|
||||
};
|
||||
|
Reference in New Issue
Block a user