📄 net_proxy.c
字号:
char urlBuffer[ MAX_DNS_SIZE + 1 + 8 ];
wchar_t unicodeURL[ MAX_DNS_SIZE + 1 + 8 ];
size_t unicodeUrlLen, wcsProxyLen;
int offset, length, proxyStatus;
assert( isWritePtr( proxy, proxyMaxLen ) );
assert( isWritePtr( proxyLen, sizeof( int ) ) );
assert( isReadPtr( url, urlLen ) );
REQUIRES( proxyMaxLen >= 10 && proxyMaxLen <= MAX_DNS_SIZE );
REQUIRES( urlLen > 0 && urlLen <= MAX_DNS_SIZE );
/* Under Win2K SP3 and Windows XP and newer (2003, Vista, etc), or at
least Windows versions with WinHTTP 5.1 installed in some way (it
officially shipped with the versions mentioned earlier) we can use
WinHTTP AutoProxy support, which implements the Web Proxy Auto-
Discovery (WPAD) protocol from an internet draft that expired in May
2001. Under older versions of Windows we have to use the WinINet
InternetGetProxyInfo, however this consists of a ghastly set of
kludges that were never meant to be exposed to the outside world
(they were only crowbarred out of MS as part of the DoJ consent
decree) and user experience with them is that they don't really work
except in the one special way in which MS-internal code calls them.
Since we don't know what this is, we use the WinHTTP functions
instead */
if( hWinHTTP == NULL )
{
if( ( hWinHTTP = LoadLibrary( "WinHTTP.dll" ) ) == NULL )
return( CRYPT_ERROR_NOTFOUND );
pWinHttpOpen = ( WINHTTPOPEN ) \
GetProcAddress( hWinHTTP, "WinHttpOpen" );
pWinHttpGetDefaultProxyConfiguration = ( WINHTTPGETDEFAULTPROXYCONFIGURATION ) \
GetProcAddress( hWinHTTP, "WinHttpGetDefaultProxyConfiguration" );
pWinHttpGetIEProxyConfigForCurrentUser = ( WINHTTPGETIEPROXYCONFIGFORCURRENTUSER ) \
GetProcAddress( hWinHTTP, "WinHttpGetIEProxyConfigForCurrentUser" );
pWinHttpGetProxyForUrl = ( WINHTTPGETPROXYFORURL ) \
GetProcAddress( hWinHTTP, "WinHttpGetProxyForUrl" );
pWinHttpCloseHandle = ( WINHTTPCLOSEHANDLE ) \
GetProcAddress( hWinHTTP, "WinHttpCloseHandle" );
if( pWinHttpOpen == NULL || pWinHttpGetProxyForUrl == NULL || \
pWinHttpCloseHandle == NULL )
{
FreeLibrary( hWinHTTP );
return( CRYPT_ERROR_NOTFOUND );
}
}
/* Autoproxy discovery using WinHttpGetProxyForUrl() can be awfully slow,
often taking several seconds since it requires probing for proxy info
first using DHCP and then if that fails using DNS. Since this is done
via a blocking call everything blocks while it's in progress. To help
mitigate this we try for proxy info direct from the registry if it's
available, avoiding the lengthy autodiscovery process. This also
means that discovery will work if no auto-discovery support is present,
for example on servers where the admin has set the proxy config
directly with ProxyCfg.exe */
if( pWinHttpGetDefaultProxyConfiguration != NULL && \
pWinHttpGetDefaultProxyConfiguration( &proxyInfo ) && \
proxyInfo.lpszProxy != NULL )
{
proxyStatus = wcstombs_s( &wcsProxyLen, proxy, proxyMaxLen,
proxyInfo.lpszProxy, MAX_DNS_SIZE );
GlobalFree( proxyInfo.lpszProxy );
if( proxyInfo.lpszProxyBypass != NULL )
GlobalFree( proxyInfo.lpszProxy );
if( proxyStatus == 0 )
{
*proxyLen = wcsProxyLen;
return( CRYPT_OK );
}
}
/* The next fallback is to get the proxy info from MSIE. This is also
usually much quicker than WinHttpGetProxyForUrl() although sometimes
it seems to fall back to that, based on the longish delay involved.
Another issue with this is that it won't work in a service process
that isn't impersonating an interactive user (since there isn't a
current user), but in that case we just fall back to
WinHttpGetProxyForUrl() */
if( pWinHttpGetIEProxyConfigForCurrentUser != NULL && \
pWinHttpGetIEProxyConfigForCurrentUser( &ieProxyInfo ) )
{
proxyStatus = wcstombs_s( &wcsProxyLen, proxy, proxyMaxLen,
ieProxyInfo.lpszProxy, MAX_DNS_SIZE );
if( ieProxyInfo.lpszAutoConfigUrl != NULL )
GlobalFree( ieProxyInfo.lpszAutoConfigUrl );
if( ieProxyInfo.lpszProxy != NULL )
GlobalFree( ieProxyInfo.lpszProxy );
if( ieProxyInfo.lpszProxyBypass != NULL )
GlobalFree( ieProxyInfo.lpszProxyBypass );
if( proxyStatus == 0 )
{
*proxyLen = wcsProxyLen;
return( CRYPT_OK );
}
}
/* WinHttpGetProxyForUrl() requires a schema for the URL that it's
performing a lookup on, if the URL doesn't contain one we use a
default value of "http://". In addition we need to convert the
raw octet string into a null-terminated string for the mbstowcs_s()
Unicode conversion and following WinHttpGetProxyForUrl() lookup */
if( strFindStr( url, urlLen, "://", 3 ) < 0 )
{
strlcpy_s( urlBuffer, MAX_DNS_SIZE, "http://" );
offset = 7;
length = MAX_DNS_SIZE - offset;
}
else
{
/* There's already a schema present, not need to manually add one */
offset = 0;
length = urlLen;
}
memcpy( urlBuffer + offset, url, length );
urlBuffer[ offset + length ] = '\0';
/* Locate the proxy used for accessing the resource at the supplied URL.
We have to convert to and from Unicode because the WinHTTP functions
all take Unicode strings as args. Note that we use the libc widechar
functions rather than the Windows ones since the latter aren't
present in Win95 or Win98.
WinHttpGetProxyForUrl() can be rather flaky, in some cases it'll fail
instantly (without even trying auto-discovery) with GetLastError() =
87 (parameter error) but then calling it again some time later works
fine. Because of this we leave it as the last resort after trying
all of the other get-proxy mechanisms */
hSession = pWinHttpOpen( L"cryptlib/1.0",
WINHTTP_ACCESS_TYPE_NO_PROXY,
WINHTTP_NO_PROXY_NAME,
WINHTTP_NO_PROXY_BYPASS, 0 );
if( hSession == NULL )
return( CRYPT_ERROR_NOTFOUND );
if( mbstowcs_s( &unicodeUrlLen, unicodeURL, MAX_DNS_SIZE,
urlBuffer, MAX_DNS_SIZE ) != 0 )
{
pWinHttpCloseHandle( hSession );
return( CRYPT_ERROR_NOTFOUND );
}
unicodeURL[ unicodeUrlLen ] = L'\0';
memset( &proxyInfo, 0, sizeof( WINHTTP_PROXY_INFO ) );
if( pWinHttpGetProxyForUrl( hSession, unicodeURL, &autoProxyOptions,
&proxyInfo ) != TRUE )
{
pWinHttpCloseHandle( hSession );
return( CRYPT_ERROR_NOTFOUND );
}
proxyStatus = wcstombs_s( &wcsProxyLen, proxy, proxyMaxLen,
proxyInfo.lpszProxy, MAX_DNS_SIZE );
GlobalFree( proxyInfo.lpszProxy );
if( proxyInfo.lpszProxyBypass != NULL )
GlobalFree( proxyInfo.lpszProxy );
pWinHttpCloseHandle( hSession );
if( proxyStatus != 0 )
return( CRYPT_ERROR_NOTFOUND );
*proxyLen = wcsProxyLen;
return( CRYPT_OK );
}
#if 0
typedef BOOL ( WINAPI *INTERNETGETPROXYINFO )( LPCSTR lpszUrl, DWORD dwUrlLength,
LPSTR lpszUrlHostName, DWORD dwUrlHostNameLength,
LPSTR* lplpszProxyHostName,
LPDWORD lpdwProxyHostNameLength );
typedef BOOL ( WINAPI *INTERNETINITIALIZEAUTOPROXYDLL )( DWORD dwVersion,
LPSTR lpszDownloadedTempFile, LPSTR lpszMime,
AutoProxyHelperFunctions* lpAutoProxyCallbacks,
LPAUTO_PROXY_SCRIPT_BUFFER lpAutoProxyScriptBuffer );
static int findProxyUrl( char *proxy, const int proxyMaxLen,
const char *url, const int urlLen )
{
static INTERNETGETPROXYINFO pInternetGetProxyInfo = NULL;
static INTERNETINITIALIZEAUTOPROXYDLL pInternetInitializeAutoProxyDll = NULL;
URL_INFO urlInfo;
char urlHost[ MAX_DNS_SIZE + 8 ];
char *proxyHost = NULL;
int proxyHostLen, status;
assert( isWritePtr( proxy, proxyMaxLen ) );
assert( isReadPtr( url, urlLen ) );
REQUIRES( proxyMaxLen > 10 && proxyMaxLen < MAX_INTLENGTH );
REQUIRES( urlLen > 0 && urlLen < MAX_INTLENGTH );
/* This gets somewhat complicated, under Win2K SP3 and XP and newer (or
at least Windows versions with WinHTTP 5.1 installed in some way, it
officially shipped with the versions mentioned earlier) we can use
WinHTTP AutoProxy support, which implements the Web Proxy Auto-
Discovery (WPAD) protocol from an internet draft that expired in May
2001. Under older versions of Windows we have to use the WinINet
InternetGetProxyInfo.
These functions were never meant to be used by the general public
(see the comment below) so they work in an extremely peculiar way
and only with the exact calling sequence that's used by MS code - it
looks like they were only intended as components of Windows-internal
implementation of proxy support since they require manual handling
of proxy config script downloading, parsing, and all manner of other
stuff that really doesn't concern us. Because of the extreme
difficulty in doing anything with these functions we use the WinHTTP
approach instead */
if( pInternetGetProxyInfo == NULL )
{
HMODULE hModJS;
if( ( hModJS = LoadLibrary( "JSProxy.dll" ) ) == NULL )
return( CRYPT_ERROR_NOTFOUND );
pInternetGetProxyInfo = ( INTERNETGETPROXYINFO ) \
GetProcAddress( hModJS, "InternetGetProxyInfo" );
pInternetInitializeAutoProxyDll = ( INTERNETINITIALIZEAUTOPROXYDLL ) \
GetProcAddress( hModJS, "InternetInitializeAutoProxyDll" );
if( pInternetGetProxyInfo == NULL || \
pInternetInitializeAutoProxyDll == NULL )
{
FreeLibrary( hModJS );
return( CRYPT_ERROR_NOTFOUND );
}
pInternetInitializeAutoProxyDll( 0, TempFile, NULL,
&HelperFunctions, NULL )
}
/* InternetGetProxyInfo() is a somewhat screwball undocumented function
that was crowbarred out of MS as part of the DoJ consent decree. It
takes as input four parameters that do the work of a single
parameter, the null-terminated target URL string. The documentation
for the function was initially wrong but has since been partially
corrected in places after user complaints, although there are still
missing parts as well as possible errors (why is it necessary to
specify a length for a supposedly null-terminated string?). In order
to meet the strange input-parameter requirements we have to pre-
parse the target URL in order to provide the various bits and pieces
that InternetGetProxyInfo() requires */
status = parseURL( &urlInfo, url, strlen( url ), 80, URL_TYPE_HTTP );
if( cryptStatusError( status ) )
return( status );
if( urlInfo.hostLen > MAX_DNS_SIZE )
return( CRYPT_ERROR_OVERFLOW );
memcpy( urlHost, urlInfo.host, urlInfo.hostLen );
urlHost[ urlInfo.hostLen ] = '\0';
if( !pInternetGetProxyInfo( url, strlen( url ), urlHost, urlInfo.hostLen,
&proxyHost, &proxyHostLen ) )
return( CRYPT_ERROR_NOTFOUND );
memcpy( proxy, proxyHost, proxyHostLen );
proxy[ proxyHostLen ] = '\0';
GlobalFree( proxyHost );
return( CRYPT_OK );
}
#endif /* 0 */
#endif /* Win32 */
#endif /* USE_TCP */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -