Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
SSL fixes:
- added MARIADB_OPT_SSL_CIPHER_STRENGTH (value uint) for Schannel
- fixed mutes in all ssl variants
  • Loading branch information
9EOR9 committed Feb 16, 2016
1 parent 448b680 commit 509b948
Show file tree
Hide file tree
Showing 12 changed files with 263 additions and 198 deletions.
1 change: 1 addition & 0 deletions include/ma_common.h
Expand Up @@ -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;
Expand Down
1 change: 1 addition & 0 deletions include/mysql.h
Expand Up @@ -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
};

Expand Down
6 changes: 6 additions & 0 deletions libmariadb/libmariadb.c
Expand Up @@ -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;
Expand Down Expand Up @@ -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;
Expand Down
3 changes: 2 additions & 1 deletion libmariadb/ma_pvio.c
Expand Up @@ -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,
Expand Down
25 changes: 13 additions & 12 deletions libmariadb/ma_ssl.c
Expand Up @@ -140,27 +140,23 @@ 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;
if (fp)
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');
Expand All @@ -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 */
20 changes: 10 additions & 10 deletions libmariadb/secure/gnutls.c
Expand Up @@ -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;
Expand All @@ -130,9 +130,9 @@ int ma_ssl_start(char *errmsg, size_t errmsg_len)
*/
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);
Expand All @@ -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;
}

Expand Down
84 changes: 49 additions & 35 deletions libmariadb/secure/ma_schannel.c
Expand Up @@ -387,7 +387,7 @@ my_bool ma_schannel_load_private_key(MARIADB_PVIO *pvio, CERT_CONTEXT *ctx, char
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;
Expand Down Expand Up @@ -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;


Expand All @@ -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;
}
}

Expand Down Expand Up @@ -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;
Expand All @@ -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,
Expand All @@ -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;
Expand All @@ -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;
}
Expand Down Expand Up @@ -782,23 +782,32 @@ 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)
{
ma_schannel_set_sec_error(pvio, sRet);
return 0;
}

flags= CERT_STORE_SIGNATURE_FLAG |
CERT_STORE_TIME_VALIDITY_FLAG;
if (ca_Check)
{
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 (sctx->client_ca_ctx)
{
if (!(sRet= CertVerifySubjectCertificateContext(pServerCert,
sctx->client_ca_ctx,
&flags)))
if (!is_Ok)
{
ma_schannel_set_win_error(pvio);
return 0;
Expand All @@ -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;
}
Expand Down
12 changes: 3 additions & 9 deletions libmariadb/secure/ma_schannel.h
Expand Up @@ -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;
Expand All @@ -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);
Expand Down

0 comments on commit 509b948

Please sign in to comment.