wininet: Implement NTLM support for proxy authentication.

This commit is contained in:
Rob Shearman 2007-06-05 19:49:58 +01:00 committed by Alexandre Julliard
parent c16bb07186
commit cb28969c2a
2 changed files with 75 additions and 98 deletions

View file

@ -113,8 +113,6 @@ static BOOL HTTP_InsertCustomHeader(LPWININETHTTPREQW lpwhr, LPHTTPHEADERW lpHdr
static INT HTTP_GetCustomHeaderIndex(LPWININETHTTPREQW lpwhr, LPCWSTR lpszField, INT index, BOOL Request);
static BOOL HTTP_DeleteCustomHeader(LPWININETHTTPREQW lpwhr, DWORD index);
static LPWSTR HTTP_build_req( LPCWSTR *list, int len );
static BOOL HTTP_InsertProxyAuthorization( LPWININETHTTPREQW lpwhr,
LPCWSTR username, LPCWSTR password );
static BOOL WINAPI HTTP_HttpQueryInfoW( LPWININETHTTPREQW lpwhr, DWORD
dwInfoLevel, LPVOID lpBuffer, LPDWORD lpdwBufferLength, LPDWORD
lpdwIndex);
@ -399,19 +397,6 @@ static void HTTP_ProcessHeaders( LPWININETHTTPREQW lpwhr )
}
}
static void HTTP_AddProxyInfo( LPWININETHTTPREQW lpwhr )
{
LPWININETHTTPSESSIONW lpwhs = lpwhr->lpHttpSession;
LPWININETAPPINFOW hIC = lpwhs->lpAppInfo;
assert(lpwhs->hdr.htype == WH_HHTTPSESSION);
assert(hIC->hdr.htype == WH_HINIT);
if (hIC && (hIC->lpszProxyUsername || hIC->lpszProxyPassword ))
HTTP_InsertProxyAuthorization(lpwhr, hIC->lpszProxyUsername,
hIC->lpszProxyPassword);
}
static inline BOOL is_basic_auth_value( LPCWSTR pszAuthValue )
{
static const WCHAR szBasic[] = {'B','a','s','i','c'}; /* Note: not nul-terminated */
@ -419,12 +404,12 @@ static inline BOOL is_basic_auth_value( LPCWSTR pszAuthValue )
((pszAuthValue[ARRAYSIZE(szBasic)] != ' ') || !pszAuthValue[ARRAYSIZE(szBasic)]);
}
static BOOL HTTP_DoAuthorization( LPWININETHTTPREQW lpwhr, LPCWSTR pszAuthValue )
static BOOL HTTP_DoAuthorization( LPWININETHTTPREQW lpwhr, LPCWSTR pszAuthValue,
struct HttpAuthInfo **ppAuthInfo,
LPWSTR domain_and_username, LPWSTR password )
{
SECURITY_STATUS sec_status;
struct HttpAuthInfo *pAuthInfo = lpwhr->pAuthInfo;
LPWSTR password = lpwhr->lpHttpSession->lpszPassword;
LPWSTR domain_and_username = lpwhr->lpHttpSession->lpszUserName;
struct HttpAuthInfo *pAuthInfo = *ppAuthInfo;
BOOL first = FALSE;
TRACE("%s\n", debugstr_w(pszAuthValue));
@ -501,7 +486,7 @@ static BOOL HTTP_DoAuthorization( LPWININETHTTPREQW lpwhr, LPCWSTR pszAuthValue
return FALSE;
}
}
lpwhr->pAuthInfo = pAuthInfo;
*ppAuthInfo = pAuthInfo;
}
else if (pAuthInfo->finished)
return FALSE;
@ -1190,99 +1175,41 @@ static UINT HTTP_DecodeBase64( LPCWSTR base64, LPSTR bin )
}
/***********************************************************************
* HTTP_EncodeBasicAuth
*
* Encode the basic authentication string for HTTP 1.1
*/
static LPWSTR HTTP_EncodeBasicAuth( LPCWSTR username, LPCWSTR password)
{
UINT len;
char *in;
LPWSTR out;
static const WCHAR szBasic[] = {'B','a','s','i','c',' '}; /* Note: not nul-terminated */
int userlen = WideCharToMultiByte(CP_UTF8, 0, username, lstrlenW(username), NULL, 0, NULL, NULL);
int passlen = WideCharToMultiByte(CP_UTF8, 0, password, lstrlenW(password), NULL, 0, NULL, NULL);
in = HeapAlloc( GetProcessHeap(), 0, userlen + 1 + passlen );
if( !in )
return NULL;
len = ARRAYSIZE(szBasic) +
(lstrlenW( username ) + 1 + lstrlenW ( password ))*2 + 1 + 1;
out = HeapAlloc( GetProcessHeap(), 0, len*sizeof(WCHAR) );
if( out )
{
WideCharToMultiByte(CP_UTF8, 0, username, -1, in, userlen, NULL, NULL);
in[userlen] = ':';
WideCharToMultiByte(CP_UTF8, 0, password, -1, &in[userlen+1], passlen, NULL, NULL);
memcpy( out, szBasic, sizeof(szBasic) );
HTTP_EncodeBase64( in, userlen + 1 + passlen, &out[strlenW(out)] );
}
HeapFree( GetProcessHeap(), 0, in );
return out;
}
/***********************************************************************
* HTTP_InsertProxyAuthorization
*
* Insert the basic authorization field in the request header
*/
static BOOL HTTP_InsertProxyAuthorization( LPWININETHTTPREQW lpwhr,
LPCWSTR username, LPCWSTR password )
{
WCHAR *authorization = HTTP_EncodeBasicAuth( username, password );
BOOL ret = TRUE;
if (!authorization)
return FALSE;
TRACE( "Inserting authorization: %s\n", debugstr_w( authorization ) );
HTTP_ProcessHeader(lpwhr, szProxy_Authorization, authorization,
HTTP_ADDHDR_FLAG_REPLACE|HTTP_ADDHDR_FLAG_REQ);
HeapFree( GetProcessHeap(), 0, authorization );
return ret;
}
/***********************************************************************
* HTTP_InsertAuthorization
* HTTP_InsertAuthorizationForHeader
*
* Insert or delete the authorization field in the request header.
*/
static BOOL HTTP_InsertAuthorization( LPWININETHTTPREQW lpwhr )
static BOOL HTTP_InsertAuthorizationForHeader( LPWININETHTTPREQW lpwhr, struct HttpAuthInfo *pAuthInfo, LPCWSTR header )
{
WCHAR *authorization = NULL;
if (lpwhr->pAuthInfo && lpwhr->pAuthInfo->auth_data_len)
if (pAuthInfo && pAuthInfo->auth_data_len)
{
static const WCHAR wszSpace[] = {' ',0};
unsigned int len;
/* scheme + space + base64 encoded data (3/2/1 bytes data -> 4 bytes of characters) */
len = strlenW(lpwhr->pAuthInfo->scheme)+1+((lpwhr->pAuthInfo->auth_data_len+2)*4)/3;
len = strlenW(pAuthInfo->scheme)+1+((pAuthInfo->auth_data_len+2)*4)/3;
authorization = HeapAlloc(GetProcessHeap(), 0, (len+1)*sizeof(WCHAR));
if (!authorization)
return FALSE;
strcpyW(authorization, lpwhr->pAuthInfo->scheme);
strcpyW(authorization, pAuthInfo->scheme);
strcatW(authorization, wszSpace);
HTTP_EncodeBase64(lpwhr->pAuthInfo->auth_data,
lpwhr->pAuthInfo->auth_data_len,
HTTP_EncodeBase64(pAuthInfo->auth_data,
pAuthInfo->auth_data_len,
authorization+strlenW(authorization));
/* clear the data as it isn't valid now that it has been sent to the
* server */
HeapFree(GetProcessHeap(), 0, lpwhr->pAuthInfo->auth_data);
lpwhr->pAuthInfo->auth_data = NULL;
lpwhr->pAuthInfo->auth_data_len = 0;
HeapFree(GetProcessHeap(), 0, pAuthInfo->auth_data);
pAuthInfo->auth_data = NULL;
pAuthInfo->auth_data_len = 0;
}
TRACE("Inserting authorization: %s\n", debugstr_w(authorization));
HTTP_ProcessHeader(lpwhr, szAuthorization, authorization,
HTTP_ProcessHeader(lpwhr, header, authorization,
HTTP_ADDHDR_FLAG_REPLACE | HTTP_ADDHDR_FLAG_REQ);
HeapFree(GetProcessHeap(), 0, authorization);
@ -1290,6 +1217,26 @@ static BOOL HTTP_InsertAuthorization( LPWININETHTTPREQW lpwhr )
return TRUE;
}
/***********************************************************************
* HTTP_InsertAuthorization
*
* Insert the authorization field in the request header
*/
static BOOL HTTP_InsertAuthorization( LPWININETHTTPREQW lpwhr )
{
return HTTP_InsertAuthorizationForHeader(lpwhr, lpwhr->pAuthInfo, szAuthorization);
}
/***********************************************************************
* HTTP_InsertProxyAuthorization
*
* Insert the proxy authorization field in the request header
*/
static BOOL HTTP_InsertProxyAuthorization( LPWININETHTTPREQW lpwhr )
{
return HTTP_InsertAuthorizationForHeader(lpwhr, lpwhr->pProxyAuthInfo, szProxy_Authorization);
}
/***********************************************************************
* HTTP_DealWithProxy
*/
@ -2659,8 +2606,7 @@ BOOL WINAPI HTTP_HttpSendRequestW(LPWININETHTTPREQW lpwhr, LPCWSTR lpszHeaders,
HTTP_ADDHDR_FLAG_REQ | HTTP_ADDHDR_FLAG_REPLACE);
HTTP_InsertAuthorization(lpwhr);
/* if there's a proxy username and password, add it to the headers */
HTTP_AddProxyInfo(lpwhr);
HTTP_InsertProxyAuthorization(lpwhr);
requestString = HTTP_BuildHeaderRequestString(lpwhr, lpwhr->lpszVerb, lpwhr->lpszPath, FALSE);
@ -2697,6 +2643,7 @@ BOOL WINAPI HTTP_HttpSendRequestW(LPWININETHTTPREQW lpwhr, LPCWSTR lpszHeaders,
if (bEndRequest)
{
DWORD dwBufferSize;
DWORD dwStatusCode;
INTERNET_SendCallback(&lpwhr->hdr, lpwhr->hdr.dwContext,
INTERNET_STATUS_RECEIVING_RESPONSE, NULL, 0);
@ -2722,13 +2669,16 @@ BOOL WINAPI HTTP_HttpSendRequestW(LPWININETHTTPREQW lpwhr, LPCWSTR lpszHeaders,
if (lpwhr->dwContentLength == 0)
HTTP_FinishedReading(lpwhr);
dwBufferSize = sizeof(dwStatusCode);
if (!HTTP_HttpQueryInfoW(lpwhr,HTTP_QUERY_FLAG_NUMBER|HTTP_QUERY_STATUS_CODE,
&dwStatusCode,&dwBufferSize,NULL))
dwStatusCode = 0;
if (!(lpwhr->hdr.dwFlags & INTERNET_FLAG_NO_AUTO_REDIRECT) && bSuccess)
{
DWORD dwCode,dwCodeLength=sizeof(DWORD);
WCHAR szNewLocation[2048];
dwBufferSize=sizeof(szNewLocation);
if (HTTP_HttpQueryInfoW(lpwhr,HTTP_QUERY_FLAG_NUMBER|HTTP_QUERY_STATUS_CODE,&dwCode,&dwCodeLength,NULL) &&
(dwCode==HTTP_STATUS_REDIRECT || dwCode==HTTP_STATUS_MOVED) &&
if ((dwStatusCode==HTTP_STATUS_REDIRECT || dwStatusCode==HTTP_STATUS_MOVED) &&
HTTP_HttpQueryInfoW(lpwhr,HTTP_QUERY_LOCATION,szNewLocation,&dwBufferSize,NULL))
{
HTTP_DrainContent(lpwhr);
@ -2745,16 +2695,32 @@ BOOL WINAPI HTTP_HttpSendRequestW(LPWININETHTTPREQW lpwhr, LPCWSTR lpszHeaders,
}
if (!(lpwhr->hdr.dwFlags & INTERNET_FLAG_NO_AUTH) && bSuccess)
{
DWORD dwCode,dwCodeLength=sizeof(DWORD);
WCHAR szAuthValue[2048];
dwBufferSize=2048;
if (HTTP_HttpQueryInfoW(lpwhr,HTTP_QUERY_FLAG_NUMBER|HTTP_QUERY_STATUS_CODE,&dwCode,&dwCodeLength,NULL) &&
(dwCode == HTTP_STATUS_DENIED))
if (dwStatusCode == HTTP_STATUS_DENIED)
{
DWORD dwIndex = 0;
while (HTTP_HttpQueryInfoW(lpwhr,HTTP_QUERY_WWW_AUTHENTICATE,szAuthValue,&dwBufferSize,&dwIndex))
{
if (HTTP_DoAuthorization(lpwhr, szAuthValue))
if (HTTP_DoAuthorization(lpwhr, szAuthValue,
&lpwhr->pAuthInfo,
lpwhr->lpHttpSession->lpszUserName,
lpwhr->lpHttpSession->lpszPassword))
{
loop_next = TRUE;
break;
}
}
}
if (dwStatusCode == HTTP_STATUS_PROXY_AUTH_REQ)
{
DWORD dwIndex = 0;
while (HTTP_HttpQueryInfoW(lpwhr,HTTP_QUERY_PROXY_AUTHENTICATE,szAuthValue,&dwBufferSize,&dwIndex))
{
if (HTTP_DoAuthorization(lpwhr, szAuthValue,
&lpwhr->pProxyAuthInfo,
lpwhr->lpHttpSession->lpAppInfo->lpszProxyUsername,
lpwhr->lpHttpSession->lpAppInfo->lpszProxyPassword))
{
loop_next = TRUE;
break;
@ -3349,6 +3315,16 @@ static VOID HTTP_CloseConnection(LPWININETHTTPREQW lpwhr)
HeapFree(GetProcessHeap(), 0, lpwhr->pAuthInfo);
lpwhr->pAuthInfo = NULL;
}
if (lpwhr->pProxyAuthInfo)
{
DeleteSecurityContext(&lpwhr->pProxyAuthInfo->ctx);
FreeCredentialsHandle(&lpwhr->pProxyAuthInfo->cred);
HeapFree(GetProcessHeap(), 0, lpwhr->pProxyAuthInfo->auth_data);
HeapFree(GetProcessHeap(), 0, lpwhr->pProxyAuthInfo->scheme);
HeapFree(GetProcessHeap(), 0, lpwhr->pProxyAuthInfo);
lpwhr->pProxyAuthInfo = NULL;
}
lpwhs = lpwhr->lpHttpSession;
hIC = lpwhs->lpAppInfo;

View file

@ -202,6 +202,7 @@ typedef struct
HTTPHEADERW *pCustHeaders;
DWORD nCustHeaders;
struct HttpAuthInfo *pAuthInfo;
struct HttpAuthInfo *pProxyAuthInfo;
} WININETHTTPREQW, *LPWININETHTTPREQW;