Module: wine Branch: master Commit: c398e6fc7718030c82215bd1ab10518b1b4b672c URL: http://source.winehq.org/git/wine.git/?a=commit;h=c398e6fc7718030c82215bd1ab...
Author: Piotr Caban piotr@codeweavers.com Date: Sat Jul 17 14:08:44 2010 +0200
wininet: Cache non basic authorization data.
---
dlls/wininet/http.c | 127 ++++++++++++++++++++++++++++++++++++++++++++-- dlls/wininet/internet.h | 21 ++++++++ 2 files changed, 142 insertions(+), 6 deletions(-)
diff --git a/dlls/wininet/http.c b/dlls/wininet/http.c index 57c4f75..c9bbde2 100644 --- a/dlls/wininet/http.c +++ b/dlls/wininet/http.c @@ -179,7 +179,7 @@ struct gzip_stream_t { BOOL end_of_data; };
-typedef struct _authorizationData +typedef struct _basicAuthorizationData { struct list entry;
@@ -187,9 +187,24 @@ typedef struct _authorizationData LPWSTR lpszwRealm; LPSTR lpszAuthorization; UINT AuthorizationLen; +} basicAuthorizationData; + +typedef struct _authorizationData +{ + struct list entry; + + LPWSTR host; + LPWSTR scheme; + LPWSTR domain; + UINT domain_len; + LPWSTR user; + UINT user_len; + LPWSTR password; + UINT password_len; } authorizationData;
static struct list basicAuthorizationCache = LIST_INIT(basicAuthorizationCache); +static struct list authorizationCache = LIST_INIT(authorizationCache);
static CRITICAL_SECTION authcache_cs; static CRITICAL_SECTION_DEBUG critsect_debug = @@ -570,13 +585,13 @@ static void destroy_authinfo( struct HttpAuthInfo *authinfo )
static UINT retrieve_cached_basic_authorization(LPWSTR host, LPWSTR realm, LPSTR *auth_data) { - authorizationData *ad; + basicAuthorizationData *ad; UINT rc = 0;
TRACE("Looking for authorization for %s:%s\n",debugstr_w(host),debugstr_w(realm));
EnterCriticalSection(&authcache_cs); - LIST_FOR_EACH_ENTRY(ad, &basicAuthorizationCache, authorizationData, entry) + LIST_FOR_EACH_ENTRY(ad, &basicAuthorizationCache, basicAuthorizationData, entry) { if (!strcmpiW(host,ad->lpszwHost) && !strcmpW(realm,ad->lpszwRealm)) { @@ -594,14 +609,14 @@ static UINT retrieve_cached_basic_authorization(LPWSTR host, LPWSTR realm, LPSTR static void cache_basic_authorization(LPWSTR host, LPWSTR realm, LPSTR auth_data, UINT auth_data_len) { struct list *cursor; - authorizationData* ad = NULL; + basicAuthorizationData* ad = NULL;
TRACE("caching authorization for %s:%s = %s\n",debugstr_w(host),debugstr_w(realm),debugstr_an(auth_data,auth_data_len));
EnterCriticalSection(&authcache_cs); LIST_FOR_EACH(cursor, &basicAuthorizationCache) { - authorizationData *check = LIST_ENTRY(cursor,authorizationData,entry); + basicAuthorizationData *check = LIST_ENTRY(cursor,basicAuthorizationData,entry); if (!strcmpiW(host,check->lpszwHost) && !strcmpW(realm,check->lpszwRealm)) { ad = check; @@ -619,7 +634,7 @@ static void cache_basic_authorization(LPWSTR host, LPWSTR realm, LPSTR auth_data } else { - ad = HeapAlloc(GetProcessHeap(),0,sizeof(authorizationData)); + ad = HeapAlloc(GetProcessHeap(),0,sizeof(basicAuthorizationData)); ad->lpszwHost = heap_strdupW(host); ad->lpszwRealm = heap_strdupW(realm); ad->lpszAuthorization = HeapAlloc(GetProcessHeap(),0,auth_data_len); @@ -631,6 +646,95 @@ static void cache_basic_authorization(LPWSTR host, LPWSTR realm, LPSTR auth_data LeaveCriticalSection(&authcache_cs); }
+static BOOL retrieve_cached_authorization(LPWSTR host, LPWSTR scheme, + SEC_WINNT_AUTH_IDENTITY_W *nt_auth_identity) +{ + authorizationData *ad; + + TRACE("Looking for authorization for %s:%s\n", debugstr_w(host), debugstr_w(scheme)); + + EnterCriticalSection(&authcache_cs); + LIST_FOR_EACH_ENTRY(ad, &authorizationCache, authorizationData, entry) { + if(!strcmpiW(host, ad->host) && !strcmpiW(scheme, ad->scheme)) { + TRACE("Authorization found in cache\n"); + + nt_auth_identity->User = heap_strdupW(ad->user); + nt_auth_identity->Password = heap_strdupW(ad->password); + nt_auth_identity->Domain = HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR)*ad->domain_len); + if(!nt_auth_identity->User || !nt_auth_identity->Password || + (!nt_auth_identity->Domain && ad->domain_len)) { + HeapFree(GetProcessHeap(), 0, nt_auth_identity->User); + HeapFree(GetProcessHeap(), 0, nt_auth_identity->Password); + HeapFree(GetProcessHeap(), 0, nt_auth_identity->Domain); + break; + } + + nt_auth_identity->Flags = SEC_WINNT_AUTH_IDENTITY_UNICODE; + nt_auth_identity->UserLength = ad->user_len; + nt_auth_identity->PasswordLength = ad->password_len; + memcpy(nt_auth_identity->Domain, ad->domain, sizeof(WCHAR)*ad->domain_len); + nt_auth_identity->DomainLength = ad->domain_len; + LeaveCriticalSection(&authcache_cs); + return TRUE; + } + } + LeaveCriticalSection(&authcache_cs); + + return FALSE; +} + +static void cache_authorization(LPWSTR host, LPWSTR scheme, + SEC_WINNT_AUTH_IDENTITY_W *nt_auth_identity) +{ + authorizationData *ad; + BOOL found = FALSE; + + TRACE("Caching authorization for %s:%s\n", debugstr_w(host), debugstr_w(scheme)); + + EnterCriticalSection(&authcache_cs); + LIST_FOR_EACH_ENTRY(ad, &authorizationCache, authorizationData, entry) + if(!strcmpiW(host, ad->host) && !strcmpiW(scheme, ad->scheme)) { + found = TRUE; + break; + } + + if(found) { + HeapFree(GetProcessHeap(), 0, ad->user); + HeapFree(GetProcessHeap(), 0, ad->password); + HeapFree(GetProcessHeap(), 0, ad->domain); + } else { + ad = HeapAlloc(GetProcessHeap(), 0, sizeof(authorizationData)); + if(!ad) { + LeaveCriticalSection(&authcache_cs); + return; + } + + ad->host = heap_strdupW(host); + ad->scheme = heap_strdupW(scheme); + list_add_head(&authorizationCache, &ad->entry); + } + + ad->user = heap_strndupW(nt_auth_identity->User, nt_auth_identity->UserLength); + ad->password = heap_strndupW(nt_auth_identity->Password, nt_auth_identity->PasswordLength); + ad->domain = heap_strndupW(nt_auth_identity->Domain, nt_auth_identity->DomainLength); + ad->user_len = nt_auth_identity->UserLength; + ad->password_len = nt_auth_identity->PasswordLength; + ad->domain_len = nt_auth_identity->DomainLength; + + if(!ad->host || !ad->scheme || !ad->user || !ad->password + || (nt_auth_identity->Domain && !ad->domain)) { + HeapFree(GetProcessHeap(), 0, ad->host); + HeapFree(GetProcessHeap(), 0, ad->scheme); + HeapFree(GetProcessHeap(), 0, ad->user); + HeapFree(GetProcessHeap(), 0, ad->password); + HeapFree(GetProcessHeap(), 0, ad->domain); + list_remove(&ad->entry); + HeapFree(GetProcessHeap(), 0, ad); + } + + LeaveCriticalSection(&authcache_cs); +} + static BOOL HTTP_DoAuthorization( http_request_t *lpwhr, LPCWSTR pszAuthValue, struct HttpAuthInfo **ppAuthInfo, LPWSTR domain_and_username, LPWSTR password, @@ -705,7 +809,11 @@ static BOOL HTTP_DoAuthorization( http_request_t *lpwhr, LPCWSTR pszAuthValue, nt_auth_identity.DomainLength = domain ? user - domain - 1 : 0; nt_auth_identity.Password = password; nt_auth_identity.PasswordLength = strlenW(nt_auth_identity.Password); + + cache_authorization(host, pAuthInfo->scheme, &nt_auth_identity); } + else if(retrieve_cached_authorization(host, pAuthInfo->scheme, &nt_auth_identity)) + pAuthData = &nt_auth_identity; else /* use default credentials */ pAuthData = NULL; @@ -715,6 +823,13 @@ static BOOL HTTP_DoAuthorization( http_request_t *lpwhr, LPCWSTR pszAuthValue, pAuthData, NULL, NULL, &pAuthInfo->cred, &exp); + + if(pAuthData && !domain_and_username) { + HeapFree(GetProcessHeap(), 0, nt_auth_identity.User); + HeapFree(GetProcessHeap(), 0, nt_auth_identity.Domain); + HeapFree(GetProcessHeap(), 0, nt_auth_identity.Password); + } + if (sec_status == SEC_E_OK) { PSecPkgInfoW sec_pkg_info; diff --git a/dlls/wininet/internet.h b/dlls/wininet/internet.h index 07b92d8..6e41f66 100644 --- a/dlls/wininet/internet.h +++ b/dlls/wininet/internet.h @@ -71,6 +71,27 @@ static inline LPWSTR heap_strdupW(LPCWSTR str) return ret; }
+static inline LPWSTR heap_strndupW(LPCWSTR str, UINT max_len) +{ + LPWSTR ret; + UINT len; + + if(!str) + return NULL; + + for(len=0; len<max_len; len++) + if(str[len] == '\0') + break; + + ret = HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR)*(len+1)); + if(ret) { + memcpy(ret, str, sizeof(WCHAR)*len); + ret[len] = '\0'; + } + + return ret; +} + static inline WCHAR *heap_strdupAtoW(const char *str) { LPWSTR ret = NULL;