[PATCH 0/2] MR9911: winhttp: Enforce a 5 second resolve timeout in detect_autoproxyconfig_url_dns().
From: Hans Leidekker <hans@codeweavers.com> --- dlls/winhttp/session.c | 58 ++++++++++++++++++++---------------------- 1 file changed, 28 insertions(+), 30 deletions(-) diff --git a/dlls/winhttp/session.c b/dlls/winhttp/session.c index 6385e6a97a4..1d91ef30ba2 100644 --- a/dlls/winhttp/session.c +++ b/dlls/winhttp/session.c @@ -1562,15 +1562,15 @@ done: return ret; } -static char *get_computer_name( COMPUTER_NAME_FORMAT format ) +static WCHAR *get_computer_name( COMPUTER_NAME_FORMAT format ) { - char *ret; + WCHAR *ret; DWORD size = 0; - GetComputerNameExA( format, NULL, &size ); + GetComputerNameExW( format, NULL, &size ); if (GetLastError() != ERROR_MORE_DATA) return NULL; - if (!(ret = malloc( size ))) return NULL; - if (!GetComputerNameExA( format, ret, &size )) + if (!(ret = malloc( size * sizeof(WCHAR) ))) return NULL; + if (!GetComputerNameExW( format, ret, &size )) { free( ret ); return NULL; @@ -1578,44 +1578,42 @@ static char *get_computer_name( COMPUTER_NAME_FORMAT format ) return ret; } -static BOOL is_domain_suffix( const char *domain, const char *suffix ) +static BOOL is_domain_suffix( const WCHAR *domain, const WCHAR *suffix ) { - int len_domain = strlen( domain ), len_suffix = strlen( suffix ); + int len_domain = wcslen( domain ), len_suffix = wcslen( suffix ); if (len_suffix > len_domain) return FALSE; - if (!stricmp( domain + len_domain - len_suffix, suffix )) return TRUE; + if (!wcsicmp( domain + len_domain - len_suffix, suffix )) return TRUE; return FALSE; } -static int reverse_lookup( const struct addrinfo *ai, char *hostname, size_t len ) +static int reverse_lookup( const struct addrinfoW *ai, WCHAR *hostname, size_t len ) { - return getnameinfo( ai->ai_addr, ai->ai_addrlen, hostname, len, NULL, 0, 0 ); + return GetNameInfoW( ai->ai_addr, ai->ai_addrlen, hostname, len, NULL, 0, 0 ); } -static WCHAR *build_wpad_url( const char *hostname, const struct addrinfo *ai ) +static WCHAR *build_wpad_url( const WCHAR *hostname, const struct addrinfoW *ai ) { - char name[NI_MAXHOST]; - WCHAR *ret, *p; + WCHAR name[NI_MAXHOST]; + WCHAR *ret; int len; while (ai && ai->ai_family != AF_INET && ai->ai_family != AF_INET6) ai = ai->ai_next; if (!ai) return NULL; - if (!reverse_lookup( ai, name, sizeof(name) )) hostname = name; + if (!reverse_lookup( ai, name, ARRAY_SIZE(name) )) hostname = name; - len = lstrlenW( L"http://" ) + strlen( hostname ) + lstrlenW( L"/wpad.dat" ); - if (!(ret = p = GlobalAlloc( 0, (len + 1) * sizeof(WCHAR) ))) return NULL; - lstrcpyW( p, L"http://" ); - p += lstrlenW( L"http://" ); - while (*hostname) { *p++ = *hostname++; } - lstrcpyW( p, L"/wpad.dat" ); + len = ARRAY_SIZE( L"http://" ) + wcslen( hostname ) + ARRAY_SIZE( L"/wpad.dat" ); + if (!(ret = GlobalAlloc( 0, len * sizeof(WCHAR) ))) return NULL; + wcscpy( ret, L"http://" ); + wcscat( ret, hostname ); + wcscat( ret, L"/wpad.dat" ); return ret; } static WCHAR *detect_autoproxyconfig_url_dns(void) { - char *fqdn, *domain, *p; - WCHAR *ret = NULL; + WCHAR *fqdn, *domain, *p, *ret = NULL; if (!(fqdn = get_computer_name( ComputerNamePhysicalDnsFullyQualified ))) return NULL; if (!(domain = get_computer_name( ComputerNamePhysicalDnsDomain ))) @@ -1624,28 +1622,28 @@ static WCHAR *detect_autoproxyconfig_url_dns(void) return NULL; } p = fqdn; - while ((p = strchr( p, '.' )) && is_domain_suffix( p + 1, domain )) + while ((p = wcschr( p, '.' )) && is_domain_suffix( p + 1, domain )) { - char *name; - struct addrinfo *ai, hints; + WCHAR *name; + struct addrinfoW *ai, hints; int res; - if (!(name = malloc( sizeof("wpad") + strlen(p) ))) + if (!(name = malloc( sizeof(L"wpad") + wcslen(p) * sizeof(WCHAR) ))) { free( fqdn ); free( domain ); return NULL; } - strcpy( name, "wpad" ); - strcat( name, p ); + wcscpy( name, L"wpad" ); + wcscat( name, p ); memset( &hints, 0, sizeof(hints) ); hints.ai_flags = AI_ALL | AI_DNS_ONLY; hints.ai_family = AF_UNSPEC; - res = getaddrinfo( name, NULL, &hints, &ai ); + res = GetAddrInfoW( name, NULL, &hints, &ai ); if (!res) { ret = build_wpad_url( name, ai ); - freeaddrinfo( ai ); + FreeAddrInfoW( ai ); if (ret) { TRACE("returning %s\n", debugstr_w(ret)); -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/9911
From: Hans Leidekker <hans@codeweavers.com> --- dlls/winhttp/net.c | 15 +++++++++------ dlls/winhttp/request.c | 2 +- dlls/winhttp/session.c | 24 +++++++----------------- dlls/winhttp/winhttp_private.h | 2 +- 4 files changed, 18 insertions(+), 25 deletions(-) diff --git a/dlls/winhttp/net.c b/dlls/winhttp/net.c index e46f2023fae..30e8dc8c2fa 100644 --- a/dlls/winhttp/net.c +++ b/dlls/winhttp/net.c @@ -723,7 +723,7 @@ BOOL netconn_is_alive( struct netconn *netconn ) return len == 1 || (len == -1 && err == WSAEWOULDBLOCK); } -static DWORD resolve_hostname( const WCHAR *name, INTERNET_PORT port, struct sockaddr_storage *sa ) +static DWORD resolve_hostname( const WCHAR *name, INTERNET_PORT port, DWORD flags, struct sockaddr_storage *sa ) { ADDRINFOW *res, hints; int ret; @@ -733,6 +733,7 @@ static DWORD resolve_hostname( const WCHAR *name, INTERNET_PORT port, struct soc * their IPv6 addresses even though they have IPv6 addresses in the DNS. */ hints.ai_family = AF_INET; + hints.ai_flags = flags; ret = GetAddrInfoW( name, NULL, &hints, &res ); if (ret != 0) @@ -766,12 +767,13 @@ struct async_resolve LONG ref; WCHAR *hostname; INTERNET_PORT port; + DWORD flags; struct sockaddr_storage addr; DWORD result; HANDLE done; }; -static struct async_resolve *create_async_resolve( const WCHAR *hostname, INTERNET_PORT port ) +static struct async_resolve *create_async_resolve( const WCHAR *hostname, INTERNET_PORT port, DWORD flags ) { struct async_resolve *ret; @@ -783,6 +785,7 @@ static struct async_resolve *create_async_resolve( const WCHAR *hostname, INTERN ret->ref = 1; ret->hostname = wcsdup( hostname ); ret->port = port; + ret->flags = flags; if (!(ret->done = CreateEventW( NULL, FALSE, FALSE, NULL ))) { free( ret->hostname ); @@ -805,21 +808,21 @@ static void CALLBACK resolve_proc( TP_CALLBACK_INSTANCE *instance, void *ctx ) { struct async_resolve *async = ctx; - async->result = resolve_hostname( async->hostname, async->port, &async->addr ); + async->result = resolve_hostname( async->hostname, async->port, async->flags, &async->addr ); SetEvent( async->done ); async_resolve_release( async ); } -DWORD netconn_resolve( WCHAR *hostname, INTERNET_PORT port, struct sockaddr_storage *addr, int timeout ) +DWORD netconn_resolve( const WCHAR *hostname, INTERNET_PORT port, DWORD flags, struct sockaddr_storage *addr, int timeout ) { DWORD ret; - if (!timeout) ret = resolve_hostname( hostname, port, addr ); + if (!timeout) ret = resolve_hostname( hostname, port, flags, addr ); else { struct async_resolve *async; - if (!(async = create_async_resolve( hostname, port ))) + if (!(async = create_async_resolve( hostname, port, flags ))) return ERROR_OUTOFMEMORY; InterlockedIncrement( &async->ref ); diff --git a/dlls/winhttp/request.c b/dlls/winhttp/request.c index 60aff3ee4ba..3a191cb1a70 100644 --- a/dlls/winhttp/request.c +++ b/dlls/winhttp/request.c @@ -1639,7 +1639,7 @@ static DWORD open_connection( struct request *request ) len = lstrlenW( host->hostname ) + 1; send_callback( &request->hdr, WINHTTP_CALLBACK_STATUS_RESOLVING_NAME, host->hostname, len ); - if ((ret = netconn_resolve( host->hostname, port, &connect->sockaddr, request->resolve_timeout ))) + if ((ret = netconn_resolve( host->hostname, port, 0, &connect->sockaddr, request->resolve_timeout ))) { release_host( host ); return ret; diff --git a/dlls/winhttp/session.c b/dlls/winhttp/session.c index 1d91ef30ba2..1844ebc8571 100644 --- a/dlls/winhttp/session.c +++ b/dlls/winhttp/session.c @@ -1587,21 +1587,18 @@ static BOOL is_domain_suffix( const WCHAR *domain, const WCHAR *suffix ) return FALSE; } -static int reverse_lookup( const struct addrinfoW *ai, WCHAR *hostname, size_t len ) +static int reverse_lookup( const struct sockaddr_storage *addr, WCHAR *hostname, size_t len ) { - return GetNameInfoW( ai->ai_addr, ai->ai_addrlen, hostname, len, NULL, 0, 0 ); + return GetNameInfoW( (const struct sockaddr *)addr, sizeof(*addr), hostname, len, NULL, 0, 0 ); } -static WCHAR *build_wpad_url( const WCHAR *hostname, const struct addrinfoW *ai ) +static WCHAR *build_wpad_url( const WCHAR *hostname, const struct sockaddr_storage *addr ) { WCHAR name[NI_MAXHOST]; WCHAR *ret; int len; - while (ai && ai->ai_family != AF_INET && ai->ai_family != AF_INET6) ai = ai->ai_next; - if (!ai) return NULL; - - if (!reverse_lookup( ai, name, ARRAY_SIZE(name) )) hostname = name; + if (!reverse_lookup( addr, name, ARRAY_SIZE(name) )) hostname = name; len = ARRAY_SIZE( L"http://" ) + wcslen( hostname ) + ARRAY_SIZE( L"/wpad.dat" ); if (!(ret = GlobalAlloc( 0, len * sizeof(WCHAR) ))) return NULL; @@ -1625,8 +1622,7 @@ static WCHAR *detect_autoproxyconfig_url_dns(void) while ((p = wcschr( p, '.' )) && is_domain_suffix( p + 1, domain )) { WCHAR *name; - struct addrinfoW *ai, hints; - int res; + struct sockaddr_storage addr; if (!(name = malloc( sizeof(L"wpad") + wcslen(p) * sizeof(WCHAR) ))) { @@ -1636,15 +1632,9 @@ static WCHAR *detect_autoproxyconfig_url_dns(void) } wcscpy( name, L"wpad" ); wcscat( name, p ); - memset( &hints, 0, sizeof(hints) ); - hints.ai_flags = AI_ALL | AI_DNS_ONLY; - hints.ai_family = AF_UNSPEC; - res = GetAddrInfoW( name, NULL, &hints, &ai ); - if (!res) + if (!netconn_resolve( name, 0, AI_ALL | AI_DNS_ONLY, &addr, 5000 )) { - ret = build_wpad_url( name, ai ); - FreeAddrInfoW( ai ); - if (ret) + if ((ret = build_wpad_url( name, &addr ))) { TRACE("returning %s\n", debugstr_w(ret)); free( name ); diff --git a/dlls/winhttp/winhttp_private.h b/dlls/winhttp/winhttp_private.h index 56adbb75d14..4e33657de5c 100644 --- a/dlls/winhttp/winhttp_private.h +++ b/dlls/winhttp/winhttp_private.h @@ -408,7 +408,7 @@ DWORD netconn_create( struct hostdata *, const struct sockaddr_storage *, int, s void netconn_unload( void ); ULONG netconn_query_data_available( struct netconn * ); DWORD netconn_recv( struct netconn *, void *, size_t, int, int * ); -DWORD netconn_resolve( WCHAR *, INTERNET_PORT, struct sockaddr_storage *, int ); +DWORD netconn_resolve( const WCHAR *, INTERNET_PORT, DWORD, struct sockaddr_storage *, int ); DWORD netconn_secure_connect( struct netconn *, WCHAR *, DWORD, CredHandle *, BOOL ); DWORD netconn_send( struct netconn *, const void *, size_t, int *, WSAOVERLAPPED * ); BOOL netconn_wait_overlapped_result( struct netconn *conn, WSAOVERLAPPED *ovr, DWORD *len ); -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/9911
participants (2)
-
Hans Leidekker -
Hans Leidekker (@hans)