wininet: Implement NTLM support for proxy authentication.
Robert Shearman
rob at codeweavers.com
Tue Jun 5 13:49:58 CDT 2007
---
dlls/wininet/http.c | 174
++++++++++++++++++++---------------------------
dlls/wininet/internet.h | 1
2 files changed, 76 insertions(+), 99 deletions(-)
-------------- next part --------------
diff --git a/dlls/wininet/http.c b/dlls/wininet/http.c
index 97cc54b..b7686a8 100644
--- a/dlls/wininet/http.c
+++ b/dlls/wininet/http.c
@@ -113,8 +113,6 @@ static BOOL HTTP_InsertCustomHeader(LPWI
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( LPWININ
}
}
-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(
((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( LPWINI
return FALSE;
}
}
- lpwhr->pAuthInfo = pAuthInfo;
+ *ppAuthInfo = pAuthInfo;
}
else if (pAuthInfo->finished)
return FALSE;
@@ -1190,99 +1175,41 @@ static UINT HTTP_DecodeBase64( LPCWSTR b
}
/***********************************************************************
- * 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);
@@ -1291,6 +1218,26 @@ static BOOL HTTP_InsertAuthorization( LP
}
/***********************************************************************
+ * 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
*/
static BOOL HTTP_DealWithProxy( LPWININETAPPINFOW hIC,
@@ -2659,8 +2606,7 @@ BOOL WINAPI HTTP_HttpSendRequestW(LPWINI
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(LPWINI
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(LPWINI
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(LPWINI
}
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,7 +3315,17 @@ static VOID HTTP_CloseConnection(LPWININ
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;
diff --git a/dlls/wininet/internet.h b/dlls/wininet/internet.h
index 4bb7a88..76d98f1 100644
--- a/dlls/wininet/internet.h
+++ b/dlls/wininet/internet.h
@@ -202,6 +202,7 @@ typedef struct
HTTPHEADERW *pCustHeaders;
DWORD nCustHeaders;
struct HttpAuthInfo *pAuthInfo;
+ struct HttpAuthInfo *pProxyAuthInfo;
} WININETHTTPREQW, *LPWININETHTTPREQW;
More information about the wine-patches
mailing list