📄 net_proxy.c
字号:
/****************************************************************************
* *
* Network Stream Proxy Management *
* Copyright Peter Gutmann 1993-2007 *
* *
****************************************************************************/
#if defined( INC_ALL )
#include "stream_int.h"
#else
#include "io/stream_int.h"
#endif /* Compiler-specific includes */
#ifdef USE_TCP
/****************************************************************************
* *
* SOCKS Proxy Management *
* *
****************************************************************************/
/* Open a connection through a Socks proxy. This is currently disabled
since it doesn't appear to be used by anyone */
#if 0
CHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \
int connectViaSocksProxy( INOUT STREAM *stream )
{
MESSAGE_DATA msgData;
BYTE socksBuffer[ 64 + CRYPT_MAX_TEXTSIZE + 8 ], *bufPtr = socksBuffer;
char userName[ CRYPT_MAX_TEXTSIZE + 8 ];
int length, status;
assert( isWritePtr( stream, sizeof( STREAM ) ) );
REQUIRES_S( stream->type == STREAM_TYPE_NETWORK );
/* Get the SOCKS user name, defaulting to "cryptlib" if there's none
set */
setMessageData( &msgData, userName, CRYPT_MAX_TEXTSIZE );
status = krnlSendMessage( DEFAULTUSER_OBJECT_HANDLE,
IMESSAGE_GETATTRIBUTE_S, &msgData,
CRYPT_OPTION_NET_SOCKS_USERNAME );
if( cryptStatusOK( status ) )
userName[ msgData.length ] = '\0';
else
strlcpy_s( userName, CRYPT_MAX_TEXTSIZE, "cryptlib" );
/* Build up the SOCKSv4 request string:
BYTE: version = 4
BYTE: command = 1 (connect)
WORD: port
LONG: IP address
STRING: userName + '\0'
Note that this has a potential problem in that it requires a DNS
lookup by the client, which can lead to problems if the client
can't get DNS requests out because only SOCKSified access is allowed.
A related problem occurs when SOCKS is being used as a tunnelling
interface because the DNS lookup will communicate data about the
client to an observer outside the tunnel.
To work around this there's a so-called SOCKSv4a protocol that has
the SOCKS proxy perform the lookup:
BYTE: version = 4
BYTE: command = 1 (connect)
WORD: port
LONG: IP address = 0x00 0x00 0x00 0xFF
STRING: userName + '\0'
STRING: FQDN + '\0'
Unfortunately there's no way to tell whether a SOCKS server supports
4a or only 4, but in any case since SOCKS support is currently
disabled we leave the poke-and-hope 4a detection until such time as
someone actually requests it */
*bufPtr++ = 4; *bufPtr++ = 1;
mputWord( bufPtr, netStream->port );
status = getIPAddress( stream, bufPtr, netStream->host );
strlcpy_s( bufPtr + 4, CRYPT_MAX_TEXTSIZE, userName );
length = 1 + 1 + 2 + 4 + strlen( userName ) + 1;
if( cryptStatusError( status ) )
{
netStream->transportDisconnectFunction( stream, TRUE );
return( status );
}
/* Send the data to the server and read back the reply */
status = netStream->transportWriteFunction( stream, socksBuffer, length,
TRANSPORT_FLAG_FLUSH );
if( cryptStatusOK( status ) )
status = netStream->transportReadFunction( stream, socksBuffer, 8,
TRANSPORT_FLAG_BLOCKING );
if( cryptStatusError( status ) )
{
/* The involvement of a proxy complicates matters somewhat because
we can usually connect to the proxy OK but may run into problems
going from the proxy to the remote server, so if we get an error
at this stage (which will typically show up as a read error from
the proxy) we report it as an open error instead */
if( status == CRYPT_ERROR_READ || status == CRYPT_ERROR_COMPLETE )
status = CRYPT_ERROR_OPEN;
netStream->transportDisconnectFunction( stream, TRUE );
return( status );
}
/* Make sure that everything is OK:
BYTE: null = 0
BYTE: status = 90 (OK)
WORD: port
LONG: IP address */
if( socksBuffer[ 1 ] != 90 )
{
int i;
netStream->transportDisconnectFunction( stream, TRUE );
strlcpy_s( netStream->errorInfo->errorString, MAX_ERRMSG_SIZE,
"Socks proxy returned" );
for( i = 0; i < 8; i++ )
{
sprintf_s( netStream->errorInfo->errorString + 20 + ( i * 3 ),
MAX_ERRMSG_SIZE - ( 20 + ( i * 3 ) ), " %02X",
socksBuffer[ i ] );
}
strlcat_s( netStream->errorInfo->errorString, MAX_ERRMSG_SIZE, "." );
netStream->errorCode = socksBuffer[ 1 ];
return( CRYPT_ERROR_OPEN );
}
return( CRYPT_OK );
}
#endif /* 0 */
/****************************************************************************
* *
* HTTP Proxy Management *
* *
****************************************************************************/
/* Open a connection via an HTTP proxy */
CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \
int connectViaHttpProxy( INOUT STREAM *stream, INOUT ERROR_INFO *errorInfo )
{
NET_STREAM_INFO *netStream = ( NET_STREAM_INFO * ) stream->netStreamInfo;
BYTE buffer[ 64 + 8 ];
int length, status;
assert( isWritePtr( stream, sizeof( STREAM ) ) );
assert( isWritePtr( errorInfo, sizeof( ERROR_INFO ) ) );
REQUIRES_S( stream->type == STREAM_TYPE_NETWORK );
/* Open the connection via the proxy. To do this we temporarily layer
HTTP I/O over the TCP I/O, then once the proxy messaging has been
completed we re-set the stream to pure TCP I/O and clear any stream
flags that were set during the proxying */
setStreamLayerHTTP( netStream );
status = netStream->writeFunction( stream, "", 0, &length );
if( cryptStatusOK( status ) )
status = netStream->readFunction( stream, buffer, 64, &length );
setStreamLayerDirect( netStream );
stream->flags = 0;
if( cryptStatusError( status ) )
{
/* The involvement of a proxy complicates matters somewhat because
we can usually connect to the proxy OK but may run into problems
going from the proxy to the remote server so if we get an error
at this stage (which will typically show up as a read error from
the proxy) we report it as an open error instead */
if( status == CRYPT_ERROR_READ || status == CRYPT_ERROR_COMPLETE )
status = CRYPT_ERROR_OPEN;
copyErrorInfo( errorInfo, NETSTREAM_ERRINFO );
netStream->transportDisconnectFunction( netStream, TRUE );
}
return( CRYPT_OK );
}
/****************************************************************************
* *
* Proxy Autoconfig Management *
* *
****************************************************************************/
/* Try and auto-detect HTTP proxy information */
#if defined( __WIN32__ )
/* The autoproxy functions were only documented in WinHTTP 5.1 so we have to
provide the necessary defines and structures ourselves */
#ifndef WINHTTP_ACCESS_TYPE_DEFAULT_PROXY
#define HINTERNET HANDLE
typedef struct {
DWORD dwFlags;
DWORD dwAutoDetectFlags;
LPCWSTR lpszAutoConfigUrl;
LPVOID lpvReserved;
DWORD dwReserved;
BOOL fAutoLogonIfChallenged;
} WINHTTP_AUTOPROXY_OPTIONS;
typedef struct {
DWORD dwAccessType;
LPWSTR lpszProxy;
LPWSTR lpszProxyBypass;
} WINHTTP_PROXY_INFO;
typedef struct {
BOOL fAutoDetect;
LPWSTR lpszAutoConfigUrl;
LPWSTR lpszProxy;
LPWSTR lpszProxyBypass;
} WINHTTP_CURRENT_USER_IE_PROXY_CONFIG;
#define WINHTTP_AUTOPROXY_AUTO_DETECT 1
#define WINHTTP_AUTO_DETECT_TYPE_DHCP 1
#define WINHTTP_AUTO_DETECT_TYPE_DNS_A 2
#define WINHTTP_ACCESS_TYPE_NO_PROXY 1
#define WINHTTP_NO_PROXY_NAME NULL
#define WINHTTP_NO_PROXY_BYPASS NULL
#endif /* WinHTTP 5.1 defines and structures */
typedef HINTERNET ( *WINHTTPOPEN )( LPCWSTR pwszUserAgent, DWORD dwAccessType,
LPCWSTR pwszProxyName, LPCWSTR pwszProxyBypass,
DWORD dwFlags );
typedef BOOL ( *WINHTTPGETDEFAULTPROXYCONFIGURATION )( WINHTTP_PROXY_INFO* pProxyInfo );
typedef BOOL ( *WINHTTPGETIEPROXYCONFIGFORCURRENTUSER )(
WINHTTP_CURRENT_USER_IE_PROXY_CONFIG *pProxyConfig );
typedef BOOL ( *WINHTTPGETPROXYFORURL )( HINTERNET hSession, LPCWSTR lpcwszUrl,
WINHTTP_AUTOPROXY_OPTIONS *pAutoProxyOptions,
WINHTTP_PROXY_INFO *pProxyInfo );
typedef BOOL ( *WINHTTPCLOSEHANDLE )( HINTERNET hInternet );
CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 3, 4 ) ) \
int findProxyUrl( OUT_BUFFER( proxyMaxLen, *proxyLen ) char *proxy,
IN_LENGTH_DNS const int proxyMaxLen,
OUT_LENGTH_DNS_Z int *proxyLen,
IN_BUFFER( urlLen ) const char *url,
IN_LENGTH_DNS const int urlLen )
{
static HMODULE hWinHTTP = NULL;
static WINHTTPOPEN pWinHttpOpen = NULL;
static WINHTTPGETDEFAULTPROXYCONFIGURATION pWinHttpGetDefaultProxyConfiguration = NULL;
static WINHTTPGETIEPROXYCONFIGFORCURRENTUSER pWinHttpGetIEProxyConfigForCurrentUser = NULL;
static WINHTTPGETPROXYFORURL pWinHttpGetProxyForUrl = NULL;
static WINHTTPCLOSEHANDLE pWinHttpCloseHandle = NULL;
WINHTTP_AUTOPROXY_OPTIONS autoProxyOptions = \
{ WINHTTP_AUTOPROXY_AUTO_DETECT,
WINHTTP_AUTO_DETECT_TYPE_DHCP | WINHTTP_AUTO_DETECT_TYPE_DNS_A,
NULL, NULL, 0, FALSE };
WINHTTP_CURRENT_USER_IE_PROXY_CONFIG ieProxyInfo;
WINHTTP_PROXY_INFO proxyInfo;
HINTERNET hSession;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -