From: Hans Leidekker Subject: [PATCH 3/3] winhttp: Consistently validate the buffer in option query functions. Message-Id: <20210917124114.2970995-3-hans@codeweavers.com> Date: Fri, 17 Sep 2021 14:41:14 +0200 Signed-off-by: Hans Leidekker --- dlls/winhttp/session.c | 103 +++++++++++++++++++++-------------------- 1 file changed, 54 insertions(+), 49 deletions(-) diff --git a/dlls/winhttp/session.c b/dlls/winhttp/session.c index 88e305da864..659a1ec8cee 100644 --- a/dlls/winhttp/session.c +++ b/dlls/winhttp/session.c @@ -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); -- 2.30.2