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
CONC-567 Schannel - handle SEC_I_RENEGOTIATE, prepare for TLSv1.3
There is no real renegotiation in TLSv1.3 protocol, so it is some internal schannel thing, that makes DecryptMessage() to return SEC_I_RENEGOTIATE, to replay a handshake step. This pops up when TLSv1.3 is enabled.
This commit is contained in:
@@ -100,6 +100,13 @@ SECURITY_STATUS ma_schannel_handshake_loop(MARIADB_PVIO *pvio, my_bool InitialRe
|
||||
return SEC_E_INSUFFICIENT_MEMORY;
|
||||
|
||||
cbIoBuffer = 0;
|
||||
|
||||
if (!InitialRead && pExtraData->cbBuffer)
|
||||
{
|
||||
memcpy(IoBuffer, pExtraData->pvBuffer,pExtraData->cbBuffer);
|
||||
cbIoBuffer= pExtraData->cbBuffer;
|
||||
}
|
||||
|
||||
fDoRead = InitialRead;
|
||||
|
||||
/* handshake loop: We will leave if handshake is finished
|
||||
@@ -282,6 +289,8 @@ SECURITY_STATUS ma_schannel_client_handshake(MARIADB_TLS *ctls)
|
||||
SecBufferDesc BufferOut;
|
||||
SecBuffer BuffersOut;
|
||||
|
||||
SecBufferDesc *pBuffersIn= NULL;
|
||||
|
||||
if (!ctls || !ctls->pvio)
|
||||
return 1;
|
||||
|
||||
@@ -445,7 +454,7 @@ SECURITY_STATUS ma_schannel_read_decrypt(MARIADB_PVIO *pvio,
|
||||
} while (sRet == SEC_E_INCOMPLETE_MESSAGE); /* Continue reading until full message arrives */
|
||||
|
||||
|
||||
if (sRet != SEC_E_OK)
|
||||
if (sRet != SEC_E_OK && sRet != SEC_I_RENEGOTIATE)
|
||||
{
|
||||
ma_schannel_set_sec_error(pvio, sRet);
|
||||
return sRet;
|
||||
@@ -462,7 +471,7 @@ SECURITY_STATUS ma_schannel_read_decrypt(MARIADB_PVIO *pvio,
|
||||
}
|
||||
|
||||
|
||||
if (sctx->dataBuf.cbBuffer)
|
||||
if (sctx->dataBuf.cbBuffer || sRet == SEC_I_RENEGOTIATE)
|
||||
{
|
||||
assert(sctx->dataBuf.pvBuffer);
|
||||
/*
|
||||
@@ -470,12 +479,13 @@ SECURITY_STATUS ma_schannel_read_decrypt(MARIADB_PVIO *pvio,
|
||||
Store the rest (if any) to be processed next time.
|
||||
*/
|
||||
nbytes = MIN(sctx->dataBuf.cbBuffer, ReadBufferSize);
|
||||
memcpy((char *)ReadBuffer, sctx->dataBuf.pvBuffer, nbytes);
|
||||
if (nbytes)
|
||||
memcpy((char *)ReadBuffer, sctx->dataBuf.pvBuffer, nbytes);
|
||||
sctx->dataBuf.cbBuffer -= (unsigned long)nbytes;
|
||||
sctx->dataBuf.pvBuffer = (char *)sctx->dataBuf.pvBuffer + nbytes;
|
||||
|
||||
*DecryptLength = (DWORD)nbytes;
|
||||
return SEC_E_OK;
|
||||
return sRet;
|
||||
}
|
||||
// No data buffer, loop
|
||||
}
|
||||
|
@@ -472,13 +472,50 @@ ssize_t ma_tls_read(MARIADB_TLS *ctls, const uchar* buffer, size_t length)
|
||||
SC_CTX *sctx= (SC_CTX *)ctls->ssl;
|
||||
MARIADB_PVIO *pvio= ctls->pvio;
|
||||
DWORD dlength= 0;
|
||||
SECURITY_STATUS status = ma_schannel_read_decrypt(pvio, &sctx->hCtxt, &dlength, (uchar *)buffer, (DWORD)length);
|
||||
if (status == SEC_I_CONTEXT_EXPIRED)
|
||||
return 0; /* other side shut down the connection. */
|
||||
if (status == SEC_I_RENEGOTIATE)
|
||||
return -1; /* Do not handle renegotiate yet */
|
||||
SECURITY_STATUS status;
|
||||
SecBuffer tmp_extra_buf= {0};
|
||||
|
||||
return (status == SEC_E_OK)? (ssize_t)dlength : -1;
|
||||
retry:
|
||||
status= ma_schannel_read_decrypt(pvio, &sctx->hCtxt, &dlength,
|
||||
(uchar *) buffer, (DWORD) length);
|
||||
if (tmp_extra_buf.cbBuffer)
|
||||
{
|
||||
/*
|
||||
This memory was allocated in renegotiation processing
|
||||
below, free it.
|
||||
*/
|
||||
LocalFree(tmp_extra_buf.pvBuffer);
|
||||
tmp_extra_buf.cbBuffer= 0;
|
||||
}
|
||||
switch (status) {
|
||||
case SEC_E_OK:
|
||||
return (ssize_t) dlength;
|
||||
case SEC_I_CONTEXT_EXPIRED:
|
||||
/* Other side shut down the connection. */
|
||||
return 0;
|
||||
case SEC_I_RENEGOTIATE:
|
||||
/* Rerun handshake steps */
|
||||
tmp_extra_buf= sctx->extraBuf;
|
||||
tmp_extra_buf.BufferType= SECBUFFER_TOKEN;
|
||||
sctx->extraBuf.cbBuffer= 0;
|
||||
sctx->extraBuf.pvBuffer= NULL;
|
||||
status= ma_schannel_handshake_loop(pvio, FALSE, &tmp_extra_buf);
|
||||
sctx->extraBuf= tmp_extra_buf;
|
||||
if (status != SEC_E_OK)
|
||||
return -1;
|
||||
/*
|
||||
If decrypt returned some decrypted bytes prior to
|
||||
renegotiation, return them.
|
||||
Otherwise, retry the read-decrypt again
|
||||
*/
|
||||
if (dlength)
|
||||
return dlength;
|
||||
|
||||
goto retry;
|
||||
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
ssize_t ma_tls_write(MARIADB_TLS *ctls, const uchar* buffer, size_t length)
|
||||
|
Reference in New Issue
Block a user