615 lines
16 KiB
C++
615 lines
16 KiB
C++
//---------------------------------------------------------------------------
|
|
// Copyright (C) Microsoft Corporation, 1997 - 1999
|
|
//
|
|
// httpreg.c
|
|
//
|
|
// HTTP/RPC protocol specific functions.
|
|
//
|
|
// Author:
|
|
// 06-02-97 Edward Reus Initial version.
|
|
//
|
|
//---------------------------------------------------------------------------
|
|
|
|
#define FD_SETSIZE 1
|
|
|
|
#include <precomp.hxx>
|
|
|
|
|
|
//-------------------------------------------------------------------------
|
|
// HttpParseServerPort()
|
|
//
|
|
// Parse strings of the form: <svr>[:<port>]
|
|
//-------------------------------------------------------------------------
|
|
static BOOL HttpParseServerPort( IN char *pszServerPort,
|
|
IN char *pszDefaultPort,
|
|
OUT char *pszServer,
|
|
OUT char *pszPort )
|
|
{
|
|
char ch;
|
|
char *psz;
|
|
char *pszColon;
|
|
|
|
if (pszColon=strchr(pszServerPort,':'))
|
|
{
|
|
*pszColon = 0;
|
|
psz = pszColon;
|
|
psz++;
|
|
strcpy(pszServer,pszServerPort);
|
|
*pszColon = ':';
|
|
if (*psz)
|
|
{
|
|
strcpy(pszPort,psz);
|
|
}
|
|
else
|
|
{
|
|
strcpy(pszPort,pszDefaultPort);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
strcpy(pszServer,pszServerPort);
|
|
strcpy(pszPort,pszDefaultPort);
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
//-------------------------------------------------------------------------
|
|
// HttpParseProxyName()
|
|
//
|
|
//-------------------------------------------------------------------------
|
|
|
|
const char *HttpProxyPrefix = "http://";
|
|
const int HttpProxyPrefixSize = sizeof("http://") - 1;
|
|
|
|
BOOL HttpParseProxyName( IN char *pszProxyList,
|
|
OUT char *pszHttpProxy,
|
|
OUT char *pszHttpProxyPort )
|
|
{
|
|
BOOL fStatus;
|
|
char *psz;
|
|
char *pszSemiColon;
|
|
int StringLength;
|
|
|
|
strcpy(pszHttpProxy,"");
|
|
strcpy(pszHttpProxyPort,"");
|
|
|
|
// Check for no configured proxy:
|
|
if ((!pszProxyList)||(!*pszProxyList))
|
|
{
|
|
return TRUE;
|
|
}
|
|
|
|
// if the string is large enough to contain the prefix, check
|
|
// whether it has a prefix
|
|
StringLength = strlen(pszProxyList);
|
|
if (StringLength >= HttpProxyPrefixSize)
|
|
{
|
|
if (RpcpStringNCompareA(pszProxyList, HttpProxyPrefix, HttpProxyPrefixSize) == 0)
|
|
pszProxyList += HttpProxyPrefixSize;
|
|
}
|
|
|
|
if (!strstr(pszProxyList,EQUALS_STR))
|
|
{
|
|
return HttpParseServerPort(pszProxyList,DEF_HTTP_PORT,pszHttpProxy,pszHttpProxyPort);
|
|
}
|
|
|
|
if (psz=strstr(pszProxyList,HTTP_EQUALS_STR))
|
|
{
|
|
psz += strlen(HTTP_EQUALS_STR);
|
|
if (pszSemiColon=strstr(psz,SEMICOLON_STR))
|
|
{
|
|
*pszSemiColon = 0;
|
|
fStatus = HttpParseServerPort(psz,DEF_HTTP_PORT,pszHttpProxy,pszHttpProxyPort);
|
|
*pszSemiColon = CHAR_SEMICOLON;
|
|
return fStatus;
|
|
}
|
|
else
|
|
{
|
|
return HttpParseServerPort(psz,DEF_HTTP_PORT,pszHttpProxy,pszHttpProxyPort);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
return TRUE;
|
|
}
|
|
}
|
|
|
|
//-------------------------------------------------------------------------
|
|
// HttpFreeProxyOverrideList()
|
|
//
|
|
//-------------------------------------------------------------------------
|
|
static void HttpFreeProxyOverrideList( IN char **ppszOverrideList )
|
|
{
|
|
char **ppszTmp = ppszOverrideList;
|
|
|
|
if (ppszOverrideList)
|
|
{
|
|
while (*ppszTmp)
|
|
{
|
|
I_RpcFree(*ppszTmp);
|
|
ppszTmp++;
|
|
}
|
|
|
|
I_RpcFree(ppszOverrideList);
|
|
}
|
|
}
|
|
|
|
//-------------------------------------------------------------------------
|
|
// HttpParseProxyOverrideList()
|
|
//
|
|
//-------------------------------------------------------------------------
|
|
static char **HttpParseProxyOverrideList( IN char *pszProxyOverrideList )
|
|
{
|
|
int i;
|
|
int iLen;
|
|
int count = 1;
|
|
DWORD dwSize = 1+strlen(pszProxyOverrideList);
|
|
char *pszList;
|
|
char *psz;
|
|
char **ppszPatternList;
|
|
|
|
if (!dwSize)
|
|
{
|
|
return NULL;
|
|
}
|
|
|
|
// Make a local copy of the pattern list, to work with:
|
|
pszList = (char *) alloca(dwSize);
|
|
|
|
strcpy(pszList,pszProxyOverrideList);
|
|
|
|
// See how many separate patterns ther are in the override list:
|
|
//
|
|
// NOTE: That count may be too high, if either the list contains
|
|
// double semicolons or the list ends with a semicolon. If
|
|
// either/both of these happen that's Ok.
|
|
psz = pszList;
|
|
while (psz=strstr(psz,";"))
|
|
{
|
|
count++;
|
|
psz++;
|
|
}
|
|
|
|
ppszPatternList = (char**)RpcpFarAllocate( (1+count)*sizeof(char*) );
|
|
if (!ppszPatternList)
|
|
{
|
|
// Out of memory.
|
|
return NULL;
|
|
}
|
|
|
|
memset(ppszPatternList,0,(1+count)*sizeof(char*));
|
|
|
|
i = 0;
|
|
while (i<count)
|
|
{
|
|
if (!*pszList)
|
|
{
|
|
// End of list. This happens when the list contained empty
|
|
// patterns.
|
|
break;
|
|
}
|
|
|
|
psz = strstr(pszList,";");
|
|
if (psz)
|
|
{
|
|
*psz = 0;
|
|
|
|
if ( (iLen=strlen(pszList)) == 0)
|
|
{
|
|
// Zero length pattern.
|
|
pszList = ++psz;
|
|
continue;
|
|
}
|
|
|
|
ppszPatternList[i] = (char*)RpcpFarAllocate(1+iLen);
|
|
if (!ppszPatternList[i])
|
|
{
|
|
HttpFreeProxyOverrideList(ppszPatternList);
|
|
return NULL;
|
|
}
|
|
strcpy(ppszPatternList[i++],pszList);
|
|
pszList = ++psz;
|
|
}
|
|
else
|
|
{
|
|
ppszPatternList[i] = (char*)RpcpFarAllocate(1+strlen(pszList));
|
|
if (!ppszPatternList[i])
|
|
{
|
|
HttpFreeProxyOverrideList(ppszPatternList);
|
|
return NULL;
|
|
}
|
|
strcpy(ppszPatternList[i++],pszList);
|
|
}
|
|
}
|
|
|
|
return ppszPatternList;
|
|
}
|
|
|
|
//-------------------------------------------------------------------------
|
|
// HttpCheckRegistry()
|
|
//
|
|
// With IE and WinInet you can setup a list of proxies to use to go through
|
|
// with an HTTP (or other) internet request. We need to support this as
|
|
// well. There are three registry entries of interest, which are located
|
|
// at:
|
|
//
|
|
// \HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Internet Settings
|
|
//
|
|
// They are:
|
|
//
|
|
// ProxyEnable: REG_BINARY
|
|
// A flag (TRUE/FALSE) to enable/disable proxies.
|
|
//
|
|
// ProxyServer: REG_SZ
|
|
// On of: an empty string (no proxy specified), a single proxy server
|
|
// name (for any format), or a list of proxy servers to use by format.
|
|
// The list is of the form:
|
|
//
|
|
// ftp=<svr:port>,gopher=<svr:port>,http=<svr:port>,...
|
|
//
|
|
// Note that not all protocols need to be in the list. And the port#
|
|
// does not need to be specifed. If not present then default the port#
|
|
// to the default for that internet protocol (scheme).
|
|
//
|
|
// ProxyOverride: REG_SZ
|
|
// A semicolon separated list of server names, internet addresses or
|
|
// patterns which, if specified are used to denote machines that you
|
|
// want to directly access, without using the proxy server. Examples
|
|
// would be:
|
|
//
|
|
// 12.34.56.78;MySvr*;111.222.*;*green*
|
|
//
|
|
//-------------------------------------------------------------------------
|
|
BOOL HttpCheckRegistry( IN char *pszServer,
|
|
OUT char **ppszHttpProxy,
|
|
OUT char **ppszHttpProxyPort,
|
|
OUT RPCProxyAccessType *AccessType
|
|
)
|
|
{
|
|
int i;
|
|
long lStatus;
|
|
DWORD dwType;
|
|
DWORD dwEnabled;
|
|
DWORD dwSize;
|
|
HKEY hKey;
|
|
HKEY hUserKey;
|
|
char szProxyList[256];
|
|
char szProxyOverrideList[256];
|
|
char szHttpProxy[MAX_HTTP_COMPUTERNAME_SIZE];
|
|
char szHttpProxyPort[MAX_HTTP_PORTSTRING_SIZE];
|
|
char *pszDotServer;
|
|
char **ppszOverrideList;
|
|
struct hostent UNALIGNED *pHostEnt;
|
|
struct in_addr ServerInAddr;
|
|
BOOL LocalDirect;
|
|
|
|
*ppszHttpProxy = NULL;
|
|
*ppszHttpProxyPort = NULL;
|
|
*AccessType = rpcpatDirect;
|
|
|
|
#if TRUE
|
|
|
|
lStatus = RegOpenCurrentUser( KEY_READ, &hUserKey );
|
|
|
|
if (lStatus != ERROR_SUCCESS)
|
|
{
|
|
return TRUE;
|
|
}
|
|
|
|
lStatus = RegOpenKeyEx( hUserKey,
|
|
REG_PROXY_PATH_STR,
|
|
0,
|
|
KEY_READ,
|
|
&hKey );
|
|
|
|
RegCloseKey(hUserKey);
|
|
|
|
if (lStatus != ERROR_SUCCESS)
|
|
{
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
#else
|
|
|
|
HANDLE hUserToken;
|
|
HANDLE hThread = GetCurrentThread(); // Note: don't need to CloseHandle().
|
|
DWORD dwStatus = 0;
|
|
DWORD dwSizeNeeded = 0;
|
|
TOKEN_USER *pTokenData;
|
|
|
|
//
|
|
// First, try to get the access token from the thread, in case
|
|
// we are impersonating.
|
|
//
|
|
if (!hThread)
|
|
{
|
|
dwStatus = GetLastError();
|
|
return TRUE;
|
|
}
|
|
|
|
BOOL b = OpenThreadToken( hThread,
|
|
TOKEN_READ,
|
|
FALSE, // Use context of the thread...
|
|
&hUserToken );
|
|
if (!b)
|
|
{
|
|
dwStatus = GetLastError();
|
|
if (dwStatus == ERROR_NO_TOKEN)
|
|
{
|
|
// If we get here, then the thread has no access token, so
|
|
// try to get the process's access token.
|
|
//
|
|
HANDLE hProcess = GetCurrentProcess(); // Never fails.
|
|
|
|
dwStatus = NO_ERROR;
|
|
b = OpenProcessToken(hProcess,
|
|
TOKEN_READ,
|
|
&hUserToken);
|
|
if (!b)
|
|
{
|
|
dwStatus = GetLastError();
|
|
}
|
|
}
|
|
}
|
|
|
|
if (dwStatus)
|
|
{
|
|
#ifdef DBG_REGISTRY
|
|
TransDbgPrint((DPFLTR_RPCPROXY_ID,
|
|
DPFLTR_WARNING_LEVEL,
|
|
"HttpCheckRegistry(): OpenThreadToken() Failed: %d\n",
|
|
dwStatus));
|
|
#endif
|
|
return TRUE;
|
|
}
|
|
|
|
GetTokenInformation( hUserToken,
|
|
TokenUser,
|
|
0,
|
|
0,
|
|
&dwSizeNeeded
|
|
);
|
|
|
|
pTokenData = (TOKEN_USER*)_alloca(dwSizeNeeded);
|
|
|
|
if (!GetTokenInformation( hUserToken,
|
|
TokenUser,
|
|
pTokenData,
|
|
dwSizeNeeded,
|
|
&dwSizeNeeded ))
|
|
{
|
|
CloseHandle(hUserToken);
|
|
return TRUE;
|
|
}
|
|
|
|
CloseHandle(hUserToken);
|
|
|
|
wchar_t UnicodeBuffer[256]; // Large enough....
|
|
UNICODE_STRING UnicodeString;
|
|
|
|
UnicodeString.Buffer = UnicodeBuffer;
|
|
UnicodeString.Length = 0;
|
|
UnicodeString.MaximumLength = sizeof(UnicodeBuffer);
|
|
|
|
NTSTATUS NtStatus;
|
|
NtStatus = RtlConvertSidToUnicodeString( &UnicodeString,
|
|
pTokenData->User.Sid,
|
|
FALSE );
|
|
if (!NT_SUCCESS(NtStatus))
|
|
{
|
|
return TRUE;
|
|
}
|
|
|
|
UnicodeString.Buffer[UnicodeString.Length] = 0;
|
|
|
|
//
|
|
// Open the user key (equivalent to HKCU).
|
|
//
|
|
lStatus = RegOpenKeyEx( HKEY_USERS,
|
|
UnicodeString.Buffer,
|
|
0,
|
|
KEY_READ,
|
|
&hUserKey );
|
|
|
|
if (lStatus != ERROR_SUCCESS)
|
|
{
|
|
return TRUE;
|
|
}
|
|
|
|
lStatus = RegOpenKeyEx( hUserKey,
|
|
REG_PROXY_PATH_STR,
|
|
0,
|
|
KEY_READ,
|
|
&hKey );
|
|
|
|
if (lStatus != ERROR_SUCCESS)
|
|
{
|
|
RegCloseKey(hUserKey);
|
|
return TRUE;
|
|
}
|
|
|
|
RegCloseKey(hUserKey);
|
|
|
|
#endif
|
|
|
|
dwSize = sizeof(dwEnabled);
|
|
lStatus = RegQueryValueEx(
|
|
hKey,
|
|
REG_PROXY_ENABLE_STR,
|
|
0,
|
|
&dwType,
|
|
(LPBYTE)&dwEnabled,
|
|
&dwSize
|
|
);
|
|
if (lStatus != ERROR_SUCCESS)
|
|
{
|
|
RegCloseKey(hKey);
|
|
return TRUE;
|
|
}
|
|
|
|
#ifdef DBG_REGISTRY
|
|
if (dwType == REG_BINARY)
|
|
{
|
|
TransDbgPrint((DPFLTR_RPCPROXY_ID,
|
|
DPFLTR_WARNING_LEVEL,
|
|
"HttpCheckRegistry(): Proxy Enabled: %s\n",
|
|
(dwEnabled)? "TRUE" : "FALSE"));
|
|
}
|
|
#endif // DBG_REGISTRY
|
|
|
|
if (!dwEnabled)
|
|
{
|
|
// IE proxies are disabled, no need to go on.
|
|
RegCloseKey(hKey);
|
|
return TRUE;
|
|
}
|
|
|
|
dwSize = sizeof(szProxyList);
|
|
lStatus = RegQueryValueExA( // Needs to be ANSI
|
|
hKey,
|
|
REG_PROXY_SERVER_STR,
|
|
0,
|
|
&dwType,
|
|
(LPBYTE)szProxyList,
|
|
&dwSize
|
|
);
|
|
if (lStatus != ERROR_SUCCESS)
|
|
{
|
|
RegCloseKey(hKey);
|
|
return TRUE;
|
|
}
|
|
|
|
#ifdef DBG_REGISTRY
|
|
if (dwType == REG_SZ)
|
|
{
|
|
TransDbgPrint((DPFLTR_RPCPROXY_ID,
|
|
DPFLTR_WARNING_LEVEL,
|
|
"HttpCheckRegistry(): Proxy List: %s\n",
|
|
szProxyList));
|
|
}
|
|
#endif // DBG_REGISTRY
|
|
|
|
if (!HttpParseProxyName(szProxyList,szHttpProxy,szHttpProxyPort))
|
|
{
|
|
RegCloseKey(hKey);
|
|
return TRUE;
|
|
}
|
|
|
|
dwSize = sizeof(szProxyOverrideList);
|
|
lStatus = RegQueryValueExA( // Needs to be ANSI
|
|
hKey,
|
|
REG_PROXY_OVERRIDE_STR,
|
|
0,
|
|
&dwType,
|
|
(LPBYTE)szProxyOverrideList,
|
|
&dwSize
|
|
);
|
|
if (lStatus != ERROR_SUCCESS)
|
|
{
|
|
// Don't quit if the ProxyOverride entry is missing, that's Ok...
|
|
szProxyOverrideList[0] = 0;
|
|
}
|
|
|
|
#ifdef DBG_REGISTRY
|
|
if (dwType == REG_SZ)
|
|
{
|
|
TransDbgPrint((DPFLTR_RPCPROXY_ID,
|
|
DPFLTR_WARNING_LEVEL,
|
|
"HttpCheckRegistry(): Proxy Override List: %s\n",
|
|
szProxyOverrideList));
|
|
}
|
|
#endif // DBG_REGISTRY
|
|
|
|
RegCloseKey(hKey);
|
|
|
|
ppszOverrideList = HttpParseProxyOverrideList(szProxyOverrideList);
|
|
|
|
if (ppszOverrideList)
|
|
{
|
|
LocalDirect = MatchExactList(
|
|
(unsigned char *) LOCAL_ADDRESSES_STR,
|
|
(unsigned char **) ppszOverrideList
|
|
);
|
|
|
|
if (!LocalDirect)
|
|
*AccessType = rpcpatHTTPProxy;
|
|
else
|
|
{
|
|
// we don't know. <local> is in the list of overrides,
|
|
// but we don't know whether the server is local
|
|
*AccessType = rpcpatUnknown;
|
|
}
|
|
|
|
// Check the server name to see if it's in the override list:
|
|
if (MatchREList(
|
|
(unsigned char *) pszServer,
|
|
(unsigned char **) ppszOverrideList
|
|
))
|
|
{
|
|
// The server name is in the override list.
|
|
HttpFreeProxyOverrideList(ppszOverrideList);
|
|
*AccessType = rpcpatDirect;
|
|
return TRUE;
|
|
}
|
|
|
|
// Convert the server name to dot notation and see if its in
|
|
// the override list:
|
|
pHostEnt = gethostbyname(pszServer);
|
|
if (pHostEnt)
|
|
{
|
|
// Note that the server may actually have several addresses in
|
|
// a (NULL terminated) array. Need to check each one...
|
|
i = 0;
|
|
while (pHostEnt->h_addr_list[i])
|
|
{
|
|
memcpy(&ServerInAddr,pHostEnt->h_addr_list[i++],pHostEnt->h_length);
|
|
pszDotServer = inet_ntoa(ServerInAddr);
|
|
#ifdef DBG_REGISTRY
|
|
TransDbgPrint((DPFLTR_RPCPROXY_ID,
|
|
DPFLTR_WARNING_LEVEL,
|
|
"HttpCheckRegistry(): Server: %s Address: %s\n",
|
|
pszServer,
|
|
pszDotServer));
|
|
#endif // DBG_REGISTRY
|
|
if ( (pszDotServer)
|
|
&& MatchREList(
|
|
(unsigned char *) pszDotServer,
|
|
(unsigned char **) ppszOverrideList
|
|
) )
|
|
{
|
|
// The server name (in dot notation) is in the override list.
|
|
HttpFreeProxyOverrideList(ppszOverrideList);
|
|
*AccessType = rpcpatDirect;
|
|
return TRUE;
|
|
}
|
|
}
|
|
}
|
|
|
|
HttpFreeProxyOverrideList(ppszOverrideList);
|
|
}
|
|
|
|
|
|
*ppszHttpProxy = (char *)RpcpFarAllocate(1+strlen(szHttpProxy));
|
|
if (!*ppszHttpProxy)
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
strcpy(*ppszHttpProxy,szHttpProxy);
|
|
|
|
*ppszHttpProxyPort = (char*)RpcpFarAllocate(1+strlen(szHttpProxyPort));
|
|
if (!*ppszHttpProxyPort)
|
|
{
|
|
I_RpcFree(*ppszHttpProxy);
|
|
*ppszHttpProxy = NULL;
|
|
return FALSE;
|
|
}
|
|
|
|
strcpy(*ppszHttpProxyPort,szHttpProxyPort);
|
|
|
|
return TRUE;
|
|
}
|
|
|