winhttp: Consistently validate the buffer in option query functions.

Signed-off-by: Hans Leidekker <hans@codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
Hans Leidekker 2021-09-17 14:41:14 +02:00 committed by Alexandre Julliard
parent 1a07093238
commit 73c107fd53
1 changed files with 54 additions and 49 deletions

View File

@ -82,6 +82,17 @@ static void session_destroy( struct object_header *hdr )
free( session );
}
static BOOL validate_buffer( void *buffer, DWORD *buflen, DWORD required )
{
if (!buffer || *buflen < required)
{
*buflen = required;
SetLastError( ERROR_INSUFFICIENT_BUFFER );
return FALSE;
}
return TRUE;
}
static BOOL session_query_option( struct object_header *hdr, DWORD option, void *buffer, DWORD *buflen )
{
struct session *session = (struct session *)hdr;
@ -90,38 +101,43 @@ static BOOL session_query_option( struct object_header *hdr, DWORD option, void
{
case WINHTTP_OPTION_REDIRECT_POLICY:
{
if (!buffer || *buflen < sizeof(DWORD))
{
*buflen = sizeof(DWORD);
SetLastError( ERROR_INSUFFICIENT_BUFFER );
return FALSE;
}
if (!validate_buffer( buffer, buflen, sizeof(DWORD) )) return FALSE;
*(DWORD *)buffer = hdr->redirect_policy;
*buflen = sizeof(DWORD);
return TRUE;
}
case WINHTTP_OPTION_RESOLVE_TIMEOUT:
if (!validate_buffer( buffer, buflen, sizeof(DWORD) )) return FALSE;
*(DWORD *)buffer = session->resolve_timeout;
*buflen = sizeof(DWORD);
return TRUE;
case WINHTTP_OPTION_CONNECT_TIMEOUT:
if (!validate_buffer( buffer, buflen, sizeof(DWORD) )) return FALSE;
*(DWORD *)buffer = session->connect_timeout;
*buflen = sizeof(DWORD);
return TRUE;
case WINHTTP_OPTION_SEND_TIMEOUT:
if (!validate_buffer( buffer, buflen, sizeof(DWORD) )) return FALSE;
*(DWORD *)buffer = session->send_timeout;
*buflen = sizeof(DWORD);
return TRUE;
case WINHTTP_OPTION_RECEIVE_TIMEOUT:
if (!validate_buffer( buffer, buflen, sizeof(DWORD) )) return FALSE;
*(DWORD *)buffer = session->receive_timeout;
*buflen = sizeof(DWORD);
return TRUE;
case WINHTTP_OPTION_RECEIVE_RESPONSE_TIMEOUT:
if (!validate_buffer( buffer, buflen, sizeof(DWORD) )) return FALSE;
*(DWORD *)buffer = session->receive_response_timeout;
*buflen = sizeof(DWORD);
return TRUE;
@ -314,38 +330,43 @@ static BOOL connect_query_option( struct object_header *hdr, DWORD option, void
{
case WINHTTP_OPTION_PARENT_HANDLE:
{
if (!buffer || *buflen < sizeof(HINTERNET))
{
*buflen = sizeof(HINTERNET);
SetLastError( ERROR_INSUFFICIENT_BUFFER );
return FALSE;
}
if (!validate_buffer( buffer, buflen, sizeof(HINTERNET) )) return FALSE;
*(HINTERNET *)buffer = ((struct object_header *)connect->session)->handle;
*buflen = sizeof(HINTERNET);
return TRUE;
}
case WINHTTP_OPTION_RESOLVE_TIMEOUT:
if (!validate_buffer( buffer, buflen, sizeof(DWORD) )) return FALSE;
*(DWORD *)buffer = connect->session->resolve_timeout;
*buflen = sizeof(DWORD);
return TRUE;
case WINHTTP_OPTION_CONNECT_TIMEOUT:
if (!validate_buffer( buffer, buflen, sizeof(DWORD) )) return FALSE;
*(DWORD *)buffer = connect->session->connect_timeout;
*buflen = sizeof(DWORD);
return TRUE;
case WINHTTP_OPTION_SEND_TIMEOUT:
if (!validate_buffer( buffer, buflen, sizeof(DWORD) )) return FALSE;
*(DWORD *)buffer = connect->session->send_timeout;
*buflen = sizeof(DWORD);
return TRUE;
case WINHTTP_OPTION_RECEIVE_TIMEOUT:
if (!validate_buffer( buffer, buflen, sizeof(DWORD) )) return FALSE;
*(DWORD *)buffer = connect->session->receive_timeout;
*buflen = sizeof(DWORD);
return TRUE;
case WINHTTP_OPTION_RECEIVE_RESPONSE_TIMEOUT:
if (!validate_buffer( buffer, buflen, sizeof(DWORD) )) return FALSE;
*(DWORD *)buffer = connect->session->receive_response_timeout;
*buflen = sizeof(DWORD);
return TRUE;
@ -669,12 +690,7 @@ static BOOL request_query_option( struct object_header *hdr, DWORD option, void
DWORD flags;
int bits;
if (!buffer || *buflen < sizeof(flags))
{
*buflen = sizeof(flags);
SetLastError( ERROR_INSUFFICIENT_BUFFER );
return FALSE;
}
if (!validate_buffer( buffer, buflen, sizeof(flags) )) return FALSE;
flags = request->security_flags;
if (request->netconn)
@ -695,12 +711,7 @@ static BOOL request_query_option( struct object_header *hdr, DWORD option, void
{
const CERT_CONTEXT *cert;
if (!buffer || *buflen < sizeof(cert))
{
*buflen = sizeof(cert);
SetLastError( ERROR_INSUFFICIENT_BUFFER );
return FALSE;
}
if (!validate_buffer( buffer, buflen, sizeof(cert) )) return FALSE;
if (!(cert = CertDuplicateCertificateContext( request->server_cert ))) return FALSE;
*(CERT_CONTEXT **)buffer = (CERT_CONTEXT *)cert;
@ -715,13 +726,7 @@ static BOOL request_query_option( struct object_header *hdr, DWORD option, void
FIXME("partial stub\n");
if (!buffer || *buflen < sizeof(*ci))
{
*buflen = sizeof(*ci);
SetLastError( ERROR_INSUFFICIENT_BUFFER );
return FALSE;
}
if (!cert) return FALSE;
if (!validate_buffer( buffer, buflen, sizeof(*ci) ) || !cert) return FALSE;
ci->ftExpiry = cert->pCertInfo->NotAfter;
ci->ftStart = cert->pCertInfo->NotBefore;
@ -741,12 +746,7 @@ static BOOL request_query_option( struct object_header *hdr, DWORD option, void
}
case WINHTTP_OPTION_SECURITY_KEY_BITNESS:
{
if (!buffer || *buflen < sizeof(DWORD))
{
*buflen = sizeof(DWORD);
SetLastError( ERROR_INSUFFICIENT_BUFFER );
return FALSE;
}
if (!validate_buffer( buffer, buflen, sizeof(DWORD) )) return FALSE;
*(DWORD *)buffer = request->netconn ? netconn_get_cipher_strength( request->netconn ) : 0;
*buflen = sizeof(DWORD);
@ -759,12 +759,8 @@ static BOOL request_query_option( struct object_header *hdr, DWORD option, void
socklen_t len = sizeof(local);
const struct sockaddr *remote = (const struct sockaddr *)&request->connect->sockaddr;
if (!buffer || *buflen < sizeof(*info))
{
*buflen = sizeof(*info);
SetLastError( ERROR_INSUFFICIENT_BUFFER );
return FALSE;
}
if (!validate_buffer( buffer, buflen, sizeof(*info) )) return FALSE;
if (!request->netconn)
{
SetLastError( ERROR_WINHTTP_INCORRECT_HANDLE_STATE );
@ -777,26 +773,36 @@ static BOOL request_query_option( struct object_header *hdr, DWORD option, void
return TRUE;
}
case WINHTTP_OPTION_RESOLVE_TIMEOUT:
if (!validate_buffer( buffer, buflen, sizeof(DWORD) )) return FALSE;
*(DWORD *)buffer = request->resolve_timeout;
*buflen = sizeof(DWORD);
return TRUE;
case WINHTTP_OPTION_CONNECT_TIMEOUT:
if (!validate_buffer( buffer, buflen, sizeof(DWORD) )) return FALSE;
*(DWORD *)buffer = request->connect_timeout;
*buflen = sizeof(DWORD);
return TRUE;
case WINHTTP_OPTION_SEND_TIMEOUT:
if (!validate_buffer( buffer, buflen, sizeof(DWORD) )) return FALSE;
*(DWORD *)buffer = request->send_timeout;
*buflen = sizeof(DWORD);
return TRUE;
case WINHTTP_OPTION_RECEIVE_TIMEOUT:
if (!validate_buffer( buffer, buflen, sizeof(DWORD) )) return FALSE;
*(DWORD *)buffer = request->receive_timeout;
*buflen = sizeof(DWORD);
return TRUE;
case WINHTTP_OPTION_RECEIVE_RESPONSE_TIMEOUT:
if (!validate_buffer( buffer, buflen, sizeof(DWORD) )) return FALSE;
*(DWORD *)buffer = request->receive_response_timeout;
*buflen = sizeof(DWORD);
return TRUE;
@ -818,11 +824,15 @@ static BOOL request_query_option( struct object_header *hdr, DWORD option, void
return TRUE;
case WINHTTP_OPTION_MAX_HTTP_AUTOMATIC_REDIRECTS:
if (!validate_buffer( buffer, buflen, sizeof(DWORD) )) return FALSE;
*(DWORD *)buffer = request->max_redirects;
*buflen = sizeof(DWORD);
return TRUE;
case WINHTTP_OPTION_HTTP_PROTOCOL_USED:
if (!validate_buffer( buffer, buflen, sizeof(DWORD) )) return FALSE;
FIXME("WINHTTP_OPTION_HTTP_PROTOCOL_USED\n");
*(DWORD *)buffer = 0;
*buflen = sizeof(DWORD);
@ -1214,12 +1224,7 @@ static BOOL query_option( struct object_header *hdr, DWORD option, void *buffer,
{
case WINHTTP_OPTION_CONTEXT_VALUE:
{
if (!buffer || *buflen < sizeof(DWORD_PTR))
{
*buflen = sizeof(DWORD_PTR);
SetLastError( ERROR_INSUFFICIENT_BUFFER );
return FALSE;
}
if (!validate_buffer( buffer, buflen, sizeof(DWORD_PTR) )) return FALSE;
*(DWORD_PTR *)buffer = hdr->context;
*buflen = sizeof(DWORD_PTR);