mirror of
https://github.com/reactos/reactos.git
synced 2025-08-03 22:46:17 +00:00
[WININET]
- Sync wininet to WINE 1.3.4 - Regenerate wininet_ros.diff so that it actually applies against current WINE head svn path=/trunk/; revision=49081
This commit is contained in:
parent
f39c42c8c2
commit
c95d5d74b8
7 changed files with 516 additions and 257 deletions
|
@ -431,7 +431,7 @@ static BOOL set_cookie(LPCWSTR domain, LPCWSTR path, LPCWSTR cookie_name, LPCWST
|
|||
value = data = heap_strdupW(cookie_data);
|
||||
if (!data)
|
||||
{
|
||||
ERR("could not allocate %zu bytes for the cookie data buffer\n", (strlenW(cookie_data) + 1) * sizeof(WCHAR));
|
||||
ERR("could not allocate the cookie data buffer\n");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
@ -457,7 +457,7 @@ static BOOL set_cookie(LPCWSTR domain, LPCWSTR path, LPCWSTR cookie_name, LPCWST
|
|||
if (value == NULL)
|
||||
{
|
||||
HeapFree(GetProcessHeap(), 0, data);
|
||||
ERR("could not allocate %zu bytes for the cookie value buffer\n", (ptr - data) * sizeof(WCHAR));
|
||||
ERR("could not allocate the cookie value buffer\n");
|
||||
return FALSE;
|
||||
}
|
||||
strcpyW(value, data);
|
||||
|
|
|
@ -181,7 +181,7 @@ struct gzip_stream_t {
|
|||
BOOL end_of_data;
|
||||
};
|
||||
|
||||
typedef struct _authorizationData
|
||||
typedef struct _basicAuthorizationData
|
||||
{
|
||||
struct list entry;
|
||||
|
||||
|
@ -189,9 +189,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 =
|
||||
|
@ -572,13 +587,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))
|
||||
{
|
||||
|
@ -596,14 +611,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;
|
||||
|
@ -621,7 +636,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);
|
||||
|
@ -633,6 +648,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,
|
||||
|
@ -707,7 +811,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;
|
||||
|
@ -717,6 +825,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;
|
||||
|
@ -1426,6 +1541,20 @@ static DWORD HTTP_ResolveName(http_request_t *lpwhr)
|
|||
return ERROR_SUCCESS;
|
||||
}
|
||||
|
||||
static BOOL HTTP_GetRequestURL(http_request_t *req, LPWSTR buf)
|
||||
{
|
||||
LPHTTPHEADERW host_header;
|
||||
|
||||
static const WCHAR formatW[] = {'h','t','t','p',':','/','/','%','s','%','s',0};
|
||||
|
||||
host_header = HTTP_GetHeader(req, hostW);
|
||||
if(!host_header)
|
||||
return FALSE;
|
||||
|
||||
sprintfW(buf, formatW, host_header->lpszValue, req->lpszPath); /* FIXME */
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* HTTPREQ_Destroy (internal)
|
||||
|
@ -1440,9 +1569,19 @@ static void HTTPREQ_Destroy(object_header_t *hdr)
|
|||
|
||||
TRACE("\n");
|
||||
|
||||
if(lpwhr->hCacheFile)
|
||||
if(lpwhr->hCacheFile) {
|
||||
WCHAR url[INTERNET_MAX_URL_LENGTH];
|
||||
FILETIME ft;
|
||||
|
||||
CloseHandle(lpwhr->hCacheFile);
|
||||
|
||||
memset(&ft, 0, sizeof(FILETIME));
|
||||
if(HTTP_GetRequestURL(lpwhr, url)) {
|
||||
CommitUrlCacheEntryW(url, lpwhr->lpszCacheFile, ft, ft,
|
||||
NORMAL_CACHE_ENTRY, NULL, 0, NULL, 0);
|
||||
}
|
||||
}
|
||||
|
||||
HeapFree(GetProcessHeap(), 0, lpwhr->lpszCacheFile);
|
||||
|
||||
DeleteCriticalSection( &lpwhr->read_section );
|
||||
|
@ -1493,20 +1632,6 @@ static void HTTPREQ_CloseConnection(object_header_t *hdr)
|
|||
INTERNET_STATUS_CONNECTION_CLOSED, 0, 0);
|
||||
}
|
||||
|
||||
static BOOL HTTP_GetRequestURL(http_request_t *req, LPWSTR buf)
|
||||
{
|
||||
LPHTTPHEADERW host_header;
|
||||
|
||||
static const WCHAR formatW[] = {'h','t','t','p',':','/','/','%','s','%','s',0};
|
||||
|
||||
host_header = HTTP_GetHeader(req, hostW);
|
||||
if(!host_header)
|
||||
return FALSE;
|
||||
|
||||
sprintfW(buf, formatW, host_header->lpszValue, req->lpszPath); /* FIXME */
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static BOOL HTTP_KeepAlive(http_request_t *lpwhr)
|
||||
{
|
||||
WCHAR szVersion[10];
|
||||
|
@ -1567,18 +1692,25 @@ static DWORD HTTPREQ_QueryOption(object_header_t *hdr, DWORD option, void *buffe
|
|||
|
||||
case INTERNET_OPTION_SECURITY_FLAGS:
|
||||
{
|
||||
http_session_t *lpwhs;
|
||||
lpwhs = req->lpHttpSession;
|
||||
DWORD flags;
|
||||
int bits;
|
||||
|
||||
if (*size < sizeof(ULONG))
|
||||
return ERROR_INSUFFICIENT_BUFFER;
|
||||
|
||||
*size = sizeof(DWORD);
|
||||
if (lpwhs->hdr.dwFlags & INTERNET_FLAG_SECURE)
|
||||
*(DWORD*)buffer = SECURITY_FLAG_SECURE;
|
||||
flags = 0;
|
||||
if (req->hdr.dwFlags & INTERNET_FLAG_SECURE)
|
||||
flags |= SECURITY_FLAG_SECURE;
|
||||
flags |= req->netConnection.security_flags;
|
||||
bits = NETCON_GetCipherStrength(&req->netConnection);
|
||||
if (bits >= 128)
|
||||
flags |= SECURITY_FLAG_STRENGTH_STRONG;
|
||||
else if (bits >= 56)
|
||||
flags |= SECURITY_FLAG_STRENGTH_MEDIUM;
|
||||
else
|
||||
*(DWORD*)buffer = 0;
|
||||
FIXME("Semi-STUB INTERNET_OPTION_SECURITY_FLAGS: %x\n",*(DWORD*)buffer);
|
||||
flags |= SECURITY_FLAG_STRENGTH_WEAK;
|
||||
*(DWORD *)buffer = flags;
|
||||
return ERROR_SUCCESS;
|
||||
}
|
||||
|
||||
|
@ -1696,60 +1828,34 @@ static DWORD HTTPREQ_QueryOption(object_header_t *hdr, DWORD option, void *buffe
|
|||
case INTERNET_OPTION_SECURITY_CERTIFICATE_STRUCT: {
|
||||
PCCERT_CONTEXT context;
|
||||
|
||||
if(*size < sizeof(INTERNET_CERTIFICATE_INFOW)) {
|
||||
*size = sizeof(INTERNET_CERTIFICATE_INFOW);
|
||||
if(*size < sizeof(INTERNET_CERTIFICATE_INFOA)) {
|
||||
*size = sizeof(INTERNET_CERTIFICATE_INFOA);
|
||||
return ERROR_INSUFFICIENT_BUFFER;
|
||||
}
|
||||
|
||||
context = (PCCERT_CONTEXT)NETCON_GetCert(&(req->netConnection));
|
||||
if(context) {
|
||||
INTERNET_CERTIFICATE_INFOW *info = (INTERNET_CERTIFICATE_INFOW*)buffer;
|
||||
INTERNET_CERTIFICATE_INFOA *info = (INTERNET_CERTIFICATE_INFOA*)buffer;
|
||||
DWORD len;
|
||||
|
||||
memset(info, 0, sizeof(INTERNET_CERTIFICATE_INFOW));
|
||||
info->ftExpiry = context->pCertInfo->NotAfter;
|
||||
info->ftStart = context->pCertInfo->NotBefore;
|
||||
if(unicode) {
|
||||
len = CertNameToStrW(context->dwCertEncodingType,
|
||||
&context->pCertInfo->Subject, CERT_SIMPLE_NAME_STR, NULL, 0);
|
||||
info->lpszSubjectInfo = LocalAlloc(0, len*sizeof(WCHAR));
|
||||
if(info->lpszSubjectInfo)
|
||||
CertNameToStrW(context->dwCertEncodingType,
|
||||
&context->pCertInfo->Subject, CERT_SIMPLE_NAME_STR,
|
||||
info->lpszSubjectInfo, len);
|
||||
len = CertNameToStrW(context->dwCertEncodingType,
|
||||
&context->pCertInfo->Issuer, CERT_SIMPLE_NAME_STR, NULL, 0);
|
||||
info->lpszIssuerInfo = LocalAlloc(0, len*sizeof(WCHAR));
|
||||
if (info->lpszIssuerInfo)
|
||||
CertNameToStrW(context->dwCertEncodingType,
|
||||
&context->pCertInfo->Issuer, CERT_SIMPLE_NAME_STR,
|
||||
info->lpszIssuerInfo, len);
|
||||
}else {
|
||||
INTERNET_CERTIFICATE_INFOA *infoA = (INTERNET_CERTIFICATE_INFOA*)info;
|
||||
|
||||
len = CertNameToStrA(context->dwCertEncodingType,
|
||||
&context->pCertInfo->Subject, CERT_SIMPLE_NAME_STR, NULL, 0);
|
||||
infoA->lpszSubjectInfo = LocalAlloc(0, len);
|
||||
if(infoA->lpszSubjectInfo)
|
||||
CertNameToStrA(context->dwCertEncodingType,
|
||||
&context->pCertInfo->Subject, CERT_SIMPLE_NAME_STR,
|
||||
infoA->lpszSubjectInfo, len);
|
||||
len = CertNameToStrA(context->dwCertEncodingType,
|
||||
&context->pCertInfo->Issuer, CERT_SIMPLE_NAME_STR, NULL, 0);
|
||||
infoA->lpszIssuerInfo = LocalAlloc(0, len);
|
||||
if(infoA->lpszIssuerInfo)
|
||||
CertNameToStrA(context->dwCertEncodingType,
|
||||
&context->pCertInfo->Issuer, CERT_SIMPLE_NAME_STR,
|
||||
infoA->lpszIssuerInfo, len);
|
||||
}
|
||||
|
||||
/*
|
||||
* Contrary to MSDN, these do not appear to be set.
|
||||
* lpszProtocolName
|
||||
* lpszSignatureAlgName
|
||||
* lpszEncryptionAlgName
|
||||
* dwKeySize
|
||||
*/
|
||||
len = CertNameToStrA(context->dwCertEncodingType,
|
||||
&context->pCertInfo->Subject, CERT_SIMPLE_NAME_STR, NULL, 0);
|
||||
info->lpszSubjectInfo = LocalAlloc(0, len);
|
||||
if(info->lpszSubjectInfo)
|
||||
CertNameToStrA(context->dwCertEncodingType,
|
||||
&context->pCertInfo->Subject, CERT_SIMPLE_NAME_STR,
|
||||
info->lpszSubjectInfo, len);
|
||||
len = CertNameToStrA(context->dwCertEncodingType,
|
||||
&context->pCertInfo->Issuer, CERT_SIMPLE_NAME_STR, NULL, 0);
|
||||
info->lpszIssuerInfo = LocalAlloc(0, len);
|
||||
if(info->lpszIssuerInfo)
|
||||
CertNameToStrA(context->dwCertEncodingType,
|
||||
&context->pCertInfo->Issuer, CERT_SIMPLE_NAME_STR,
|
||||
info->lpszIssuerInfo, len);
|
||||
info->dwKeySize = NETCON_GetCipherStrength(&req->netConnection);
|
||||
CertFreeCertificateContext(context);
|
||||
return ERROR_SUCCESS;
|
||||
}
|
||||
|
@ -1764,6 +1870,17 @@ static DWORD HTTPREQ_SetOption(object_header_t *hdr, DWORD option, void *buffer,
|
|||
http_request_t *req = (http_request_t*)hdr;
|
||||
|
||||
switch(option) {
|
||||
case INTERNET_OPTION_SECURITY_FLAGS:
|
||||
{
|
||||
DWORD flags;
|
||||
|
||||
if (!buffer || size != sizeof(DWORD))
|
||||
return ERROR_INVALID_PARAMETER;
|
||||
flags = *(DWORD *)buffer;
|
||||
TRACE("%08x\n", flags);
|
||||
req->netConnection.security_flags = flags;
|
||||
return ERROR_SUCCESS;
|
||||
}
|
||||
case INTERNET_OPTION_SEND_TIMEOUT:
|
||||
case INTERNET_OPTION_RECEIVE_TIMEOUT:
|
||||
TRACE("INTERNET_OPTION_SEND/RECEIVE_TIMEOUT\n");
|
||||
|
@ -1970,6 +2087,9 @@ static DWORD read_gzip_data(http_request_t *req, BYTE *buf, int size, BOOL sync,
|
|||
break;
|
||||
}
|
||||
|
||||
if(req->dwContentRead == req->dwContentLength)
|
||||
break;
|
||||
|
||||
buf_avail = req->dwContentLength == ~0 ? req->read_size : min(req->read_size, req->dwContentLength-req->dwContentRead);
|
||||
|
||||
zstream->next_in = req->read_buf+req->read_pos;
|
||||
|
@ -2125,7 +2245,18 @@ done:
|
|||
static DWORD HTTPREQ_ReadFile(object_header_t *hdr, void *buffer, DWORD size, DWORD *read)
|
||||
{
|
||||
http_request_t *req = (http_request_t*)hdr;
|
||||
return HTTPREQ_Read(req, buffer, size, read, TRUE);
|
||||
DWORD res;
|
||||
|
||||
EnterCriticalSection( &req->read_section );
|
||||
if(hdr->dwError == INTERNET_HANDLE_IN_USE)
|
||||
hdr->dwError = ERROR_INTERNET_INTERNAL_ERROR;
|
||||
|
||||
res = HTTPREQ_Read(req, buffer, size, read, TRUE);
|
||||
if(res == ERROR_SUCCESS)
|
||||
res = hdr->dwError;
|
||||
LeaveCriticalSection( &req->read_section );
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
static void HTTPREQ_AsyncReadFileExAProc(WORKREQUEST *workRequest)
|
||||
|
@ -2152,7 +2283,7 @@ static DWORD HTTPREQ_ReadFileExA(object_header_t *hdr, INTERNET_BUFFERSA *buffer
|
|||
DWORD flags, DWORD_PTR context)
|
||||
{
|
||||
http_request_t *req = (http_request_t*)hdr;
|
||||
DWORD res;
|
||||
DWORD res, size, read, error = ERROR_SUCCESS;
|
||||
|
||||
if (flags & ~(IRF_ASYNC|IRF_NO_WAIT))
|
||||
FIXME("these dwFlags aren't implemented: 0x%x\n", flags & ~(IRF_ASYNC|IRF_NO_WAIT));
|
||||
|
@ -2162,7 +2293,7 @@ static DWORD HTTPREQ_ReadFileExA(object_header_t *hdr, INTERNET_BUFFERSA *buffer
|
|||
|
||||
INTERNET_SendCallback(&req->hdr, req->hdr.dwContext, INTERNET_STATUS_RECEIVING_RESPONSE, NULL, 0);
|
||||
|
||||
if ((hdr->dwFlags & INTERNET_FLAG_ASYNC) && !get_avail_data(req))
|
||||
if (hdr->dwFlags & INTERNET_FLAG_ASYNC)
|
||||
{
|
||||
WORKREQUEST workRequest;
|
||||
|
||||
|
@ -2172,6 +2303,7 @@ static DWORD HTTPREQ_ReadFileExA(object_header_t *hdr, INTERNET_BUFFERSA *buffer
|
|||
{
|
||||
res = HTTPREQ_Read(req, buffers->lpvBuffer, buffers->dwBufferLength,
|
||||
&buffers->dwBufferLength, FALSE);
|
||||
size = buffers->dwBufferLength;
|
||||
LeaveCriticalSection( &req->read_section );
|
||||
goto done;
|
||||
}
|
||||
|
@ -2187,17 +2319,52 @@ static DWORD HTTPREQ_ReadFileExA(object_header_t *hdr, INTERNET_BUFFERSA *buffer
|
|||
return ERROR_IO_PENDING;
|
||||
}
|
||||
|
||||
res = HTTPREQ_Read(req, buffers->lpvBuffer, buffers->dwBufferLength, &buffers->dwBufferLength,
|
||||
!(flags & IRF_NO_WAIT));
|
||||
read = 0;
|
||||
size = buffers->dwBufferLength;
|
||||
|
||||
EnterCriticalSection( &req->read_section );
|
||||
if(hdr->dwError == ERROR_SUCCESS)
|
||||
hdr->dwError = INTERNET_HANDLE_IN_USE;
|
||||
else if(hdr->dwError == INTERNET_HANDLE_IN_USE)
|
||||
hdr->dwError = ERROR_INTERNET_INTERNAL_ERROR;
|
||||
|
||||
while(1) {
|
||||
res = HTTPREQ_Read(req, (char*)buffers->lpvBuffer+read, size-read,
|
||||
&buffers->dwBufferLength, !(flags & IRF_NO_WAIT));
|
||||
if(res == ERROR_SUCCESS)
|
||||
read += buffers->dwBufferLength;
|
||||
else
|
||||
break;
|
||||
|
||||
if(!req->read_chunked || read==size || req->dwContentLength!=req->dwContentRead
|
||||
|| !req->dwContentLength || (req->gzip_stream && req->gzip_stream->end_of_data))
|
||||
break;
|
||||
LeaveCriticalSection( &req->read_section );
|
||||
|
||||
INTERNET_SendCallback(&req->hdr, req->hdr.dwContext, INTERNET_STATUS_RESPONSE_RECEIVED,
|
||||
&buffers->dwBufferLength, sizeof(buffers->dwBufferLength));
|
||||
INTERNET_SendCallback(&req->hdr, req->hdr.dwContext,
|
||||
INTERNET_STATUS_RECEIVING_RESPONSE, NULL, 0);
|
||||
|
||||
EnterCriticalSection( &req->read_section );
|
||||
}
|
||||
|
||||
if(hdr->dwError == INTERNET_HANDLE_IN_USE)
|
||||
hdr->dwError = ERROR_SUCCESS;
|
||||
else
|
||||
error = hdr->dwError;
|
||||
|
||||
LeaveCriticalSection( &req->read_section );
|
||||
size = buffers->dwBufferLength;
|
||||
buffers->dwBufferLength = read;
|
||||
|
||||
done:
|
||||
if (res == ERROR_SUCCESS) {
|
||||
DWORD size = buffers->dwBufferLength;
|
||||
INTERNET_SendCallback(&req->hdr, req->hdr.dwContext, INTERNET_STATUS_RESPONSE_RECEIVED,
|
||||
&size, sizeof(size));
|
||||
}
|
||||
|
||||
return res;
|
||||
return res==ERROR_SUCCESS ? error : res;
|
||||
}
|
||||
|
||||
static void HTTPREQ_AsyncReadFileExWProc(WORKREQUEST *workRequest)
|
||||
|
@ -2225,7 +2392,7 @@ static DWORD HTTPREQ_ReadFileExW(object_header_t *hdr, INTERNET_BUFFERSW *buffer
|
|||
{
|
||||
|
||||
http_request_t *req = (http_request_t*)hdr;
|
||||
DWORD res;
|
||||
DWORD res, size, read, error = ERROR_SUCCESS;
|
||||
|
||||
if (flags & ~(IRF_ASYNC|IRF_NO_WAIT))
|
||||
FIXME("these dwFlags aren't implemented: 0x%x\n", flags & ~(IRF_ASYNC|IRF_NO_WAIT));
|
||||
|
@ -2245,6 +2412,7 @@ static DWORD HTTPREQ_ReadFileExW(object_header_t *hdr, INTERNET_BUFFERSW *buffer
|
|||
{
|
||||
res = HTTPREQ_Read(req, buffers->lpvBuffer, buffers->dwBufferLength,
|
||||
&buffers->dwBufferLength, FALSE);
|
||||
size = buffers->dwBufferLength;
|
||||
LeaveCriticalSection( &req->read_section );
|
||||
goto done;
|
||||
}
|
||||
|
@ -2260,17 +2428,52 @@ static DWORD HTTPREQ_ReadFileExW(object_header_t *hdr, INTERNET_BUFFERSW *buffer
|
|||
return ERROR_IO_PENDING;
|
||||
}
|
||||
|
||||
res = HTTPREQ_Read(req, buffers->lpvBuffer, buffers->dwBufferLength, &buffers->dwBufferLength,
|
||||
!(flags & IRF_NO_WAIT));
|
||||
read = 0;
|
||||
size = buffers->dwBufferLength;
|
||||
|
||||
EnterCriticalSection( &req->read_section );
|
||||
if(hdr->dwError == ERROR_SUCCESS)
|
||||
hdr->dwError = INTERNET_HANDLE_IN_USE;
|
||||
else if(hdr->dwError == INTERNET_HANDLE_IN_USE)
|
||||
hdr->dwError = ERROR_INTERNET_INTERNAL_ERROR;
|
||||
|
||||
while(1) {
|
||||
res = HTTPREQ_Read(req, (char*)buffers->lpvBuffer+read, size-read,
|
||||
&buffers->dwBufferLength, !(flags & IRF_NO_WAIT));
|
||||
if(res == ERROR_SUCCESS)
|
||||
read += buffers->dwBufferLength;
|
||||
else
|
||||
break;
|
||||
|
||||
if(!req->read_chunked || read==size || req->dwContentLength!=req->dwContentRead
|
||||
|| !req->dwContentLength || (req->gzip_stream && req->gzip_stream->end_of_data))
|
||||
break;
|
||||
LeaveCriticalSection( &req->read_section );
|
||||
|
||||
INTERNET_SendCallback(&req->hdr, req->hdr.dwContext, INTERNET_STATUS_RESPONSE_RECEIVED,
|
||||
&buffers->dwBufferLength, sizeof(buffers->dwBufferLength));
|
||||
INTERNET_SendCallback(&req->hdr, req->hdr.dwContext,
|
||||
INTERNET_STATUS_RECEIVING_RESPONSE, NULL, 0);
|
||||
|
||||
EnterCriticalSection( &req->read_section );
|
||||
}
|
||||
|
||||
if(hdr->dwError == INTERNET_HANDLE_IN_USE)
|
||||
hdr->dwError = ERROR_SUCCESS;
|
||||
else
|
||||
error = hdr->dwError;
|
||||
|
||||
LeaveCriticalSection( &req->read_section );
|
||||
size = buffers->dwBufferLength;
|
||||
buffers->dwBufferLength = read;
|
||||
|
||||
done:
|
||||
if (res == ERROR_SUCCESS) {
|
||||
DWORD size = buffers->dwBufferLength;
|
||||
INTERNET_SendCallback(&req->hdr, req->hdr.dwContext, INTERNET_STATUS_RESPONSE_RECEIVED,
|
||||
&size, sizeof(size));
|
||||
}
|
||||
|
||||
return res;
|
||||
return res==ERROR_SUCCESS ? error : res;
|
||||
}
|
||||
|
||||
static DWORD HTTPREQ_WriteFile(object_header_t *hdr, const void *buffer, DWORD size, DWORD *written)
|
||||
|
@ -3456,6 +3659,7 @@ static DWORD HTTP_HttpSendRequestW(http_request_t *lpwhr, LPCWSTR lpszHeaders,
|
|||
do
|
||||
{
|
||||
DWORD len;
|
||||
BOOL reusing_connection;
|
||||
char *ascii_req;
|
||||
|
||||
loop_next = FALSE;
|
||||
|
@ -3506,6 +3710,11 @@ static DWORD HTTP_HttpSendRequestW(http_request_t *lpwhr, LPCWSTR lpszHeaders,
|
|||
TRACE("Request header -> %s\n", debugstr_w(requestString) );
|
||||
|
||||
/* Send the request and store the results */
|
||||
if(NETCON_connected(&lpwhr->netConnection))
|
||||
reusing_connection = TRUE;
|
||||
else
|
||||
reusing_connection = FALSE;
|
||||
|
||||
if ((res = HTTP_OpenConnection(lpwhr)) != ERROR_SUCCESS)
|
||||
goto lend;
|
||||
|
||||
|
@ -3547,6 +3756,13 @@ static DWORD HTTP_HttpSendRequestW(http_request_t *lpwhr, LPCWSTR lpszHeaders,
|
|||
goto lend;
|
||||
|
||||
responseLen = HTTP_GetResponseHeaders(lpwhr, TRUE);
|
||||
/* FIXME: We should know that connection is closed before sending
|
||||
* headers. Otherwise wrong callbacks are executed */
|
||||
if(!responseLen && reusing_connection) {
|
||||
TRACE("Connection closed by server, reconnecting\n");
|
||||
loop_next = TRUE;
|
||||
continue;
|
||||
}
|
||||
|
||||
INTERNET_SendCallback(&lpwhr->hdr, lpwhr->hdr.dwContext,
|
||||
INTERNET_STATUS_RESPONSE_RECEIVED, &responseLen,
|
||||
|
@ -3565,7 +3781,9 @@ static DWORD HTTP_HttpSendRequestW(http_request_t *lpwhr, LPCWSTR lpszHeaders,
|
|||
{
|
||||
WCHAR *new_url, szNewLocation[INTERNET_MAX_URL_LENGTH];
|
||||
dwBufferSize=sizeof(szNewLocation);
|
||||
if ((dwStatusCode==HTTP_STATUS_REDIRECT || dwStatusCode==HTTP_STATUS_MOVED) &&
|
||||
if ((dwStatusCode == HTTP_STATUS_REDIRECT ||
|
||||
dwStatusCode == HTTP_STATUS_MOVED ||
|
||||
dwStatusCode == HTTP_STATUS_REDIRECT_METHOD) &&
|
||||
HTTP_HttpQueryInfoW(lpwhr,HTTP_QUERY_LOCATION,szNewLocation,&dwBufferSize,NULL) == ERROR_SUCCESS)
|
||||
{
|
||||
if (strcmpW(lpwhr->lpszVerb, szGET) && strcmpW(lpwhr->lpszVerb, szHEAD))
|
||||
|
@ -3610,6 +3828,12 @@ static DWORD HTTP_HttpSendRequestW(http_request_t *lpwhr, LPCWSTR lpszHeaders,
|
|||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if(!loop_next) {
|
||||
TRACE("Cleaning wrong authorization data\n");
|
||||
destroy_authinfo(lpwhr->pAuthInfo);
|
||||
lpwhr->pAuthInfo = NULL;
|
||||
}
|
||||
}
|
||||
if (dwStatusCode == HTTP_STATUS_PROXY_AUTH_REQ)
|
||||
{
|
||||
|
@ -3626,6 +3850,12 @@ static DWORD HTTP_HttpSendRequestW(http_request_t *lpwhr, LPCWSTR lpszHeaders,
|
|||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if(!loop_next) {
|
||||
TRACE("Cleaning wrong proxy authorization data\n");
|
||||
destroy_authinfo(lpwhr->pProxyAuthInfo);
|
||||
lpwhr->pProxyAuthInfo = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -3674,7 +3904,7 @@ lend:
|
|||
HTTP_ReceiveRequestData(lpwhr, TRUE);
|
||||
else
|
||||
{
|
||||
iar.dwResult = 0;
|
||||
iar.dwResult = (res==ERROR_SUCCESS ? (DWORD_PTR)lpwhr->hdr.hInternet : 0);
|
||||
iar.dwError = res;
|
||||
|
||||
INTERNET_SendCallback(&lpwhr->hdr, lpwhr->hdr.dwContext,
|
||||
|
@ -3758,7 +3988,7 @@ static DWORD HTTP_HttpEndRequestW(http_request_t *lpwhr, DWORD dwFlags, DWORD_PT
|
|||
}
|
||||
}
|
||||
|
||||
iar.dwResult = (DWORD_PTR)lpwhr->hdr.hInternet;
|
||||
iar.dwResult = (res==ERROR_SUCCESS ? (DWORD_PTR)lpwhr->hdr.hInternet : 0);
|
||||
iar.dwError = res;
|
||||
|
||||
INTERNET_SendCallback(&lpwhr->hdr, lpwhr->hdr.dwContext,
|
||||
|
@ -4459,9 +4689,6 @@ static INT HTTP_GetResponseHeaders(http_request_t *lpwhr, BOOL clear)
|
|||
|
||||
TRACE("-->\n");
|
||||
|
||||
/* clear old response headers (eg. from a redirect response) */
|
||||
if (clear) HTTP_clear_response_headers( lpwhr );
|
||||
|
||||
if (!NETCON_connected(&lpwhr->netConnection))
|
||||
goto lend;
|
||||
|
||||
|
@ -4473,6 +4700,13 @@ static INT HTTP_GetResponseHeaders(http_request_t *lpwhr, BOOL clear)
|
|||
buflen = MAX_REPLY_LEN;
|
||||
if (!read_line(lpwhr, bufferA, &buflen))
|
||||
goto lend;
|
||||
|
||||
/* clear old response headers (eg. from a redirect response) */
|
||||
if (clear) {
|
||||
HTTP_clear_response_headers( lpwhr );
|
||||
clear = FALSE;
|
||||
}
|
||||
|
||||
rc += buflen;
|
||||
MultiByteToWideChar( CP_ACP, 0, bufferA, buflen, buffer, MAX_REPLY_LEN );
|
||||
/* check is this a status code line? */
|
||||
|
|
|
@ -3569,8 +3569,8 @@ LPSTR INTERNET_GetResponseBuffer(void)
|
|||
|
||||
LPSTR INTERNET_GetNextLine(INT nSocket, LPDWORD dwLen)
|
||||
{
|
||||
struct timeval tv;
|
||||
fd_set infd;
|
||||
struct timeval tv;
|
||||
BOOL bSuccess = FALSE;
|
||||
INT nRecv = 0;
|
||||
LPSTR lpszBuffer = INTERNET_GetResponseBuffer();
|
||||
|
@ -3578,13 +3578,13 @@ LPSTR INTERNET_GetNextLine(INT nSocket, LPDWORD dwLen)
|
|||
TRACE("\n");
|
||||
|
||||
FD_ZERO(&infd);
|
||||
FD_SET(nSocket, &infd);
|
||||
tv.tv_sec=RESPONSE_TIMEOUT;
|
||||
tv.tv_usec=0;
|
||||
FD_SET(nSocket,&infd);
|
||||
tv.tv_sec = RESPONSE_TIMEOUT;
|
||||
tv.tv_usec = 0;
|
||||
|
||||
while (nRecv < MAX_REPLY_LEN)
|
||||
{
|
||||
if (select(nSocket+1,&infd,NULL,NULL,&tv) > 0)
|
||||
if (select(0, &infd, NULL, NULL, &tv) > 0)
|
||||
{
|
||||
if (recv(nSocket, &lpszBuffer[nRecv], 1, 0) <= 0)
|
||||
{
|
||||
|
|
|
@ -53,6 +53,7 @@ typedef struct
|
|||
BOOL useSSL;
|
||||
int socketFD;
|
||||
void *ssl_s;
|
||||
DWORD security_flags;
|
||||
} WININET_NETCONNECTION;
|
||||
|
||||
static inline LPWSTR heap_strdupW(LPCWSTR str)
|
||||
|
@ -71,6 +72,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;
|
||||
|
@ -148,6 +170,8 @@ typedef struct {
|
|||
DWORD (*FindNextFileW)(object_header_t*,void*);
|
||||
} object_vtbl_t;
|
||||
|
||||
#define INTERNET_HANDLE_IN_USE 1
|
||||
|
||||
struct _object_header_t
|
||||
{
|
||||
WH_TYPE htype;
|
||||
|
@ -436,6 +460,7 @@ DWORD NETCON_recv(WININET_NETCONNECTION *connection, void *buf, size_t len, int
|
|||
int *recvd /* out */);
|
||||
BOOL NETCON_query_data_available(WININET_NETCONNECTION *connection, DWORD *available);
|
||||
LPCVOID NETCON_GetCert(WININET_NETCONNECTION *connection);
|
||||
int NETCON_GetCipherStrength(WININET_NETCONNECTION *connection);
|
||||
DWORD NETCON_set_timeout(WININET_NETCONNECTION *connection, BOOL send, int value);
|
||||
#define sock_get_error(x) WSAGetLastError()
|
||||
|
||||
|
|
|
@ -60,6 +60,7 @@
|
|||
#endif
|
||||
#ifdef HAVE_OPENSSL_SSL_H
|
||||
# include <openssl/ssl.h>
|
||||
# include <openssl/opensslv.h>
|
||||
#undef FAR
|
||||
#undef DSA
|
||||
#endif
|
||||
|
@ -113,10 +114,15 @@ static CRITICAL_SECTION init_ssl_cs = { &init_ssl_cs_debug, -1, 0, 0, 0, 0 };
|
|||
static void *OpenSSL_ssl_handle;
|
||||
static void *OpenSSL_crypto_handle;
|
||||
|
||||
#if defined(OPENSSL_VERSION_NUMBER) && (OPENSSL_VERSION_NUMBER> 0x1000000)
|
||||
static const SSL_METHOD *meth;
|
||||
#else
|
||||
static SSL_METHOD *meth;
|
||||
#endif
|
||||
static SSL_CTX *ctx;
|
||||
static int hostname_idx;
|
||||
static int error_idx;
|
||||
static int conn_idx;
|
||||
|
||||
#define MAKE_FUNCPTR(f) static typeof(f) * p##f
|
||||
|
||||
|
@ -139,12 +145,13 @@ MAKE_FUNCPTR(SSL_get_ex_new_index);
|
|||
MAKE_FUNCPTR(SSL_get_ex_data);
|
||||
MAKE_FUNCPTR(SSL_set_ex_data);
|
||||
MAKE_FUNCPTR(SSL_get_ex_data_X509_STORE_CTX_idx);
|
||||
MAKE_FUNCPTR(SSL_get_verify_result);
|
||||
MAKE_FUNCPTR(SSL_get_peer_certificate);
|
||||
MAKE_FUNCPTR(SSL_CTX_get_timeout);
|
||||
MAKE_FUNCPTR(SSL_CTX_set_timeout);
|
||||
MAKE_FUNCPTR(SSL_CTX_set_default_verify_paths);
|
||||
MAKE_FUNCPTR(SSL_CTX_set_verify);
|
||||
MAKE_FUNCPTR(SSL_get_current_cipher);
|
||||
MAKE_FUNCPTR(SSL_CIPHER_get_bits);
|
||||
MAKE_FUNCPTR(X509_STORE_CTX_get_ex_data);
|
||||
|
||||
/* OpenSSL's libcrypto functions that we use */
|
||||
|
@ -214,7 +221,7 @@ static PCCERT_CONTEXT X509_to_cert_context(X509 *cert)
|
|||
}
|
||||
|
||||
static DWORD netconn_verify_cert(PCCERT_CONTEXT cert, HCERTSTORE store,
|
||||
WCHAR *server)
|
||||
WCHAR *server, DWORD security_flags)
|
||||
{
|
||||
BOOL ret;
|
||||
CERT_CHAIN_PARA chainPara = { sizeof(chainPara), { 0 } };
|
||||
|
@ -231,38 +238,58 @@ static DWORD netconn_verify_cert(PCCERT_CONTEXT cert, HCERTSTORE store,
|
|||
{
|
||||
if (chain->TrustStatus.dwErrorStatus)
|
||||
{
|
||||
static const DWORD supportedErrors =
|
||||
CERT_TRUST_IS_NOT_TIME_VALID |
|
||||
CERT_TRUST_IS_UNTRUSTED_ROOT |
|
||||
CERT_TRUST_IS_OFFLINE_REVOCATION |
|
||||
CERT_TRUST_REVOCATION_STATUS_UNKNOWN |
|
||||
CERT_TRUST_IS_REVOKED |
|
||||
CERT_TRUST_IS_NOT_VALID_FOR_USAGE;
|
||||
|
||||
if (chain->TrustStatus.dwErrorStatus & CERT_TRUST_IS_NOT_TIME_VALID)
|
||||
err = ERROR_INTERNET_SEC_CERT_DATE_INVALID;
|
||||
else if (chain->TrustStatus.dwErrorStatus &
|
||||
CERT_TRUST_IS_UNTRUSTED_ROOT)
|
||||
CERT_TRUST_IS_UNTRUSTED_ROOT &&
|
||||
!(security_flags & SECURITY_FLAG_IGNORE_UNKNOWN_CA))
|
||||
err = ERROR_INTERNET_INVALID_CA;
|
||||
else if ((chain->TrustStatus.dwErrorStatus &
|
||||
else if (!(security_flags & SECURITY_FLAG_IGNORE_REVOCATION) &&
|
||||
((chain->TrustStatus.dwErrorStatus &
|
||||
CERT_TRUST_IS_OFFLINE_REVOCATION) ||
|
||||
(chain->TrustStatus.dwErrorStatus &
|
||||
CERT_TRUST_REVOCATION_STATUS_UNKNOWN))
|
||||
(chain->TrustStatus.dwErrorStatus &
|
||||
CERT_TRUST_REVOCATION_STATUS_UNKNOWN)))
|
||||
err = ERROR_INTERNET_SEC_CERT_NO_REV;
|
||||
else if (chain->TrustStatus.dwErrorStatus & CERT_TRUST_IS_REVOKED)
|
||||
else if (!(security_flags & SECURITY_FLAG_IGNORE_REVOCATION) &&
|
||||
(chain->TrustStatus.dwErrorStatus & CERT_TRUST_IS_REVOKED))
|
||||
err = ERROR_INTERNET_SEC_CERT_REVOKED;
|
||||
else if (chain->TrustStatus.dwErrorStatus &
|
||||
CERT_TRUST_IS_NOT_VALID_FOR_USAGE)
|
||||
else if (!(security_flags & SECURITY_FLAG_IGNORE_WRONG_USAGE) &&
|
||||
(chain->TrustStatus.dwErrorStatus &
|
||||
CERT_TRUST_IS_NOT_VALID_FOR_USAGE))
|
||||
err = ERROR_INTERNET_SEC_INVALID_CERT;
|
||||
else
|
||||
else if (chain->TrustStatus.dwErrorStatus & ~supportedErrors)
|
||||
err = ERROR_INTERNET_SEC_INVALID_CERT;
|
||||
}
|
||||
else
|
||||
if (!err)
|
||||
{
|
||||
CERT_CHAIN_POLICY_PARA policyPara;
|
||||
SSL_EXTRA_CERT_CHAIN_POLICY_PARA sslExtraPolicyPara;
|
||||
CERT_CHAIN_POLICY_STATUS policyStatus;
|
||||
CERT_CHAIN_CONTEXT chainCopy;
|
||||
|
||||
/* Clear chain->TrustStatus.dwErrorStatus so
|
||||
* CertVerifyCertificateChainPolicy will verify additional checks
|
||||
* rather than stopping with an existing, ignored error.
|
||||
*/
|
||||
memcpy(&chainCopy, chain, sizeof(chainCopy));
|
||||
chainCopy.TrustStatus.dwErrorStatus = 0;
|
||||
sslExtraPolicyPara.u.cbSize = sizeof(sslExtraPolicyPara);
|
||||
sslExtraPolicyPara.dwAuthType = AUTHTYPE_SERVER;
|
||||
sslExtraPolicyPara.pwszServerName = server;
|
||||
sslExtraPolicyPara.fdwChecks = security_flags;
|
||||
policyPara.cbSize = sizeof(policyPara);
|
||||
policyPara.dwFlags = 0;
|
||||
policyPara.pvExtraPolicyPara = &sslExtraPolicyPara;
|
||||
ret = CertVerifyCertificateChainPolicy(CERT_CHAIN_POLICY_SSL,
|
||||
chain, &policyPara, &policyStatus);
|
||||
&chainCopy, &policyPara, &policyStatus);
|
||||
/* Any error in the policy status indicates that the
|
||||
* policy couldn't be verified.
|
||||
*/
|
||||
|
@ -285,55 +312,52 @@ static int netconn_secure_verify(int preverify_ok, X509_STORE_CTX *ctx)
|
|||
SSL *ssl;
|
||||
WCHAR *server;
|
||||
BOOL ret = FALSE;
|
||||
HCERTSTORE store = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0,
|
||||
CERT_STORE_CREATE_NEW_FLAG, NULL);
|
||||
WININET_NETCONNECTION *conn;
|
||||
|
||||
ssl = pX509_STORE_CTX_get_ex_data(ctx,
|
||||
pSSL_get_ex_data_X509_STORE_CTX_idx());
|
||||
server = pSSL_get_ex_data(ssl, hostname_idx);
|
||||
if (preverify_ok)
|
||||
conn = pSSL_get_ex_data(ssl, conn_idx);
|
||||
if (store)
|
||||
{
|
||||
HCERTSTORE store = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0,
|
||||
CERT_STORE_CREATE_NEW_FLAG, NULL);
|
||||
X509 *cert;
|
||||
int i;
|
||||
PCCERT_CONTEXT endCert = NULL;
|
||||
|
||||
if (store)
|
||||
ret = TRUE;
|
||||
for (i = 0; ret && i < psk_num((struct stack_st *)ctx->chain); i++)
|
||||
{
|
||||
X509 *cert;
|
||||
int i;
|
||||
PCCERT_CONTEXT endCert = NULL;
|
||||
PCCERT_CONTEXT context;
|
||||
|
||||
ret = TRUE;
|
||||
for (i = 0; ret && i < psk_num((struct stack_st *)ctx->chain); i++)
|
||||
cert = (X509 *)psk_value((struct stack_st *)ctx->chain, i);
|
||||
if ((context = X509_to_cert_context(cert)))
|
||||
{
|
||||
PCCERT_CONTEXT context;
|
||||
|
||||
cert = (X509 *)psk_value((struct stack_st *)ctx->chain, i);
|
||||
if ((context = X509_to_cert_context(cert)))
|
||||
{
|
||||
if (i == 0)
|
||||
ret = CertAddCertificateContextToStore(store, context,
|
||||
CERT_STORE_ADD_ALWAYS, &endCert);
|
||||
else
|
||||
ret = CertAddCertificateContextToStore(store, context,
|
||||
CERT_STORE_ADD_ALWAYS, NULL);
|
||||
CertFreeCertificateContext(context);
|
||||
}
|
||||
if (i == 0)
|
||||
ret = CertAddCertificateContextToStore(store, context,
|
||||
CERT_STORE_ADD_ALWAYS, &endCert);
|
||||
else
|
||||
ret = CertAddCertificateContextToStore(store, context,
|
||||
CERT_STORE_ADD_ALWAYS, NULL);
|
||||
CertFreeCertificateContext(context);
|
||||
}
|
||||
if (!endCert) ret = FALSE;
|
||||
if (ret)
|
||||
{
|
||||
DWORD_PTR err = netconn_verify_cert(endCert, store, server);
|
||||
|
||||
if (err)
|
||||
{
|
||||
pSSL_set_ex_data(ssl, error_idx, (void *)err);
|
||||
ret = FALSE;
|
||||
}
|
||||
}
|
||||
CertFreeCertificateContext(endCert);
|
||||
CertCloseStore(store, 0);
|
||||
}
|
||||
} else
|
||||
pSSL_set_ex_data(ssl, error_idx, (void *)ERROR_INTERNET_SEC_CERT_ERRORS);
|
||||
if (!endCert) ret = FALSE;
|
||||
if (ret)
|
||||
{
|
||||
DWORD_PTR err = netconn_verify_cert(endCert, store, server,
|
||||
conn->security_flags);
|
||||
|
||||
if (err)
|
||||
{
|
||||
pSSL_set_ex_data(ssl, error_idx, (void *)err);
|
||||
ret = FALSE;
|
||||
}
|
||||
}
|
||||
CertFreeCertificateContext(endCert);
|
||||
CertCloseStore(store, 0);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -400,12 +424,13 @@ DWORD NETCON_init(WININET_NETCONNECTION *connection, BOOL useSSL)
|
|||
DYNSSL(SSL_get_ex_data);
|
||||
DYNSSL(SSL_set_ex_data);
|
||||
DYNSSL(SSL_get_ex_data_X509_STORE_CTX_idx);
|
||||
DYNSSL(SSL_get_verify_result);
|
||||
DYNSSL(SSL_get_peer_certificate);
|
||||
DYNSSL(SSL_CTX_get_timeout);
|
||||
DYNSSL(SSL_CTX_set_timeout);
|
||||
DYNSSL(SSL_CTX_set_default_verify_paths);
|
||||
DYNSSL(SSL_CTX_set_verify);
|
||||
DYNSSL(SSL_get_current_cipher);
|
||||
DYNSSL(SSL_CIPHER_get_bits);
|
||||
DYNSSL(X509_STORE_CTX_get_ex_data);
|
||||
#undef DYNSSL
|
||||
|
||||
|
@ -460,6 +485,15 @@ DWORD NETCON_init(WININET_NETCONNECTION *connection, BOOL useSSL)
|
|||
LeaveCriticalSection(&init_ssl_cs);
|
||||
return ERROR_OUTOFMEMORY;
|
||||
}
|
||||
conn_idx = pSSL_get_ex_new_index(0, (void *)"netconn index",
|
||||
NULL, NULL, NULL);
|
||||
if (conn_idx == -1)
|
||||
{
|
||||
ERR("SSL_get_ex_new_index failed; %s\n",
|
||||
pERR_error_string(pERR_get_error(), 0));
|
||||
LeaveCriticalSection(&init_ssl_cs);
|
||||
return ERROR_OUTOFMEMORY;
|
||||
}
|
||||
pSSL_CTX_set_verify(ctx, SSL_VERIFY_PEER, netconn_secure_verify);
|
||||
|
||||
pCRYPTO_set_id_callback(ssl_thread_id);
|
||||
|
@ -637,10 +671,8 @@ DWORD NETCON_close(WININET_NETCONNECTION *connection)
|
|||
DWORD NETCON_secure_connect(WININET_NETCONNECTION *connection, LPWSTR hostname)
|
||||
{
|
||||
DWORD res = ERROR_NOT_SUPPORTED;
|
||||
#ifdef SONAME_LIBSSL
|
||||
long verify_res;
|
||||
X509 *cert;
|
||||
|
||||
#ifdef SONAME_LIBSSL
|
||||
/* can't connect if we are already connected */
|
||||
if (connection->useSSL)
|
||||
{
|
||||
|
@ -665,6 +697,20 @@ DWORD NETCON_secure_connect(WININET_NETCONNECTION *connection, LPWSTR hostname)
|
|||
goto fail;
|
||||
}
|
||||
|
||||
if (!pSSL_set_ex_data(connection->ssl_s, hostname_idx, hostname))
|
||||
{
|
||||
ERR("SSL_set_ex_data failed: %s\n",
|
||||
pERR_error_string(pERR_get_error(), 0));
|
||||
res = ERROR_INTERNET_SECURITY_CHANNEL_ERROR;
|
||||
goto fail;
|
||||
}
|
||||
if (!pSSL_set_ex_data(connection->ssl_s, conn_idx, connection))
|
||||
{
|
||||
ERR("SSL_set_ex_data failed: %s\n",
|
||||
pERR_error_string(pERR_get_error(), 0));
|
||||
res = ERROR_INTERNET_SECURITY_CHANNEL_ERROR;
|
||||
goto fail;
|
||||
}
|
||||
if (pSSL_connect(connection->ssl_s) <= 0)
|
||||
{
|
||||
res = (DWORD_PTR)pSSL_get_ex_data(connection->ssl_s, error_idx);
|
||||
|
@ -673,22 +719,6 @@ DWORD NETCON_secure_connect(WININET_NETCONNECTION *connection, LPWSTR hostname)
|
|||
ERR("SSL_connect failed: %d\n", res);
|
||||
goto fail;
|
||||
}
|
||||
pSSL_set_ex_data(connection->ssl_s, hostname_idx, hostname);
|
||||
cert = pSSL_get_peer_certificate(connection->ssl_s);
|
||||
if (!cert)
|
||||
{
|
||||
ERR("no certificate for server %s\n", debugstr_w(hostname));
|
||||
/* FIXME: is this the best error? */
|
||||
res = ERROR_INTERNET_INVALID_CA;
|
||||
goto fail;
|
||||
}
|
||||
verify_res = pSSL_get_verify_result(connection->ssl_s);
|
||||
if (verify_res != X509_V_OK)
|
||||
{
|
||||
ERR("couldn't verify the security of the connection, %ld\n", verify_res);
|
||||
/* FIXME: we should set an error and return, but we only warn at
|
||||
* the moment */
|
||||
}
|
||||
|
||||
connection->useSSL = TRUE;
|
||||
return ERROR_SUCCESS;
|
||||
|
@ -772,6 +802,8 @@ DWORD NETCON_recv(WININET_NETCONNECTION *connection, void *buf, size_t len, int
|
|||
if (!connection->useSSL)
|
||||
{
|
||||
*recvd = recv(connection->socketFD, buf, len, flags);
|
||||
if(!*recvd)
|
||||
NETCON_close(connection);
|
||||
return *recvd == -1 ? sock_get_error(errno) : ERROR_SUCCESS;
|
||||
}
|
||||
else
|
||||
|
@ -781,8 +813,10 @@ DWORD NETCON_recv(WININET_NETCONNECTION *connection, void *buf, size_t len, int
|
|||
|
||||
/* Check if EOF was received */
|
||||
if(!*recvd && (pSSL_get_error(connection->ssl_s, *recvd)==SSL_ERROR_ZERO_RETURN
|
||||
|| pSSL_get_error(connection->ssl_s, *recvd)==SSL_ERROR_SYSCALL))
|
||||
|| pSSL_get_error(connection->ssl_s, *recvd)==SSL_ERROR_SYSCALL)) {
|
||||
NETCON_close(connection);
|
||||
return ERROR_SUCCESS;
|
||||
}
|
||||
|
||||
return *recvd > 0 ? ERROR_SUCCESS : ERROR_INTERNET_CONNECTION_ABORTED;
|
||||
#else
|
||||
|
@ -840,6 +874,24 @@ LPCVOID NETCON_GetCert(WININET_NETCONNECTION *connection)
|
|||
#endif
|
||||
}
|
||||
|
||||
int NETCON_GetCipherStrength(WININET_NETCONNECTION *connection)
|
||||
{
|
||||
#ifdef SONAME_LIBSSL
|
||||
SSL_CIPHER *cipher;
|
||||
int bits = 0;
|
||||
|
||||
if (!connection->useSSL)
|
||||
return 0;
|
||||
cipher = pSSL_get_current_cipher(connection->ssl_s);
|
||||
if (!cipher)
|
||||
return 0;
|
||||
pSSL_CIPHER_get_bits(cipher, &bits);
|
||||
return bits;
|
||||
#else
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
DWORD NETCON_set_timeout(WININET_NETCONNECTION *connection, BOOL send, int value)
|
||||
{
|
||||
int result;
|
||||
|
|
|
@ -2184,14 +2184,17 @@ BOOL WINAPI CreateUrlCacheEntryA(
|
|||
)
|
||||
{
|
||||
WCHAR *url_name;
|
||||
WCHAR *file_extension;
|
||||
WCHAR *file_extension = NULL;
|
||||
WCHAR file_name[MAX_PATH];
|
||||
BOOL bSuccess = FALSE;
|
||||
DWORD dwError = 0;
|
||||
|
||||
TRACE("(%s %d %s %p %d)\n", debugstr_a(lpszUrlName), dwExpectedFileSize,
|
||||
debugstr_a(lpszFileExtension), lpszFileName, dwReserved);
|
||||
|
||||
if (lpszUrlName && (url_name = heap_strdupAtoW(lpszUrlName)))
|
||||
{
|
||||
if (lpszFileExtension && (file_extension = heap_strdupAtoW(lpszFileExtension)))
|
||||
if (!lpszFileExtension || (file_extension = heap_strdupAtoW(lpszFileExtension)))
|
||||
{
|
||||
if (CreateUrlCacheEntryW(url_name, dwExpectedFileSize, file_extension, file_name, dwReserved))
|
||||
{
|
||||
|
@ -2268,6 +2271,12 @@ BOOL WINAPI CreateUrlCacheEntryW(
|
|||
if (((lpszUrlEnd - lpszUrlName) > 1) && (*(lpszUrlEnd - 1) == '/' || *(lpszUrlEnd - 1) == '\\'))
|
||||
lpszUrlEnd--;
|
||||
|
||||
lpszUrlPart = memchrW(lpszUrlName, '?', lpszUrlEnd - lpszUrlName);
|
||||
if (!lpszUrlPart)
|
||||
lpszUrlPart = memchrW(lpszUrlName, '#', lpszUrlEnd - lpszUrlName);
|
||||
if (lpszUrlPart)
|
||||
lpszUrlEnd = lpszUrlPart;
|
||||
|
||||
for (lpszUrlPart = lpszUrlEnd;
|
||||
(lpszUrlPart >= lpszUrlName);
|
||||
lpszUrlPart--)
|
||||
|
@ -2278,10 +2287,6 @@ BOOL WINAPI CreateUrlCacheEntryW(
|
|||
lpszUrlPart++;
|
||||
break;
|
||||
}
|
||||
else if(*lpszUrlPart == '?' || *lpszUrlPart == '#')
|
||||
{
|
||||
lpszUrlEnd = lpszUrlPart;
|
||||
}
|
||||
}
|
||||
if (!lstrcmpW(lpszUrlPart, szWWW))
|
||||
{
|
||||
|
@ -2327,7 +2332,13 @@ BOOL WINAPI CreateUrlCacheEntryW(
|
|||
CacheDir = (BYTE)(rand() % pHeader->DirectoryCount);
|
||||
|
||||
lBufferSize = MAX_PATH * sizeof(WCHAR);
|
||||
URLCache_LocalFileNameToPathW(pContainer, pHeader, szFile, CacheDir, lpszFileName, &lBufferSize);
|
||||
if (!URLCache_LocalFileNameToPathW(pContainer, pHeader, szFile, CacheDir, lpszFileName, &lBufferSize))
|
||||
{
|
||||
WARN("Failed to get full path for filename %s, needed %u bytes.\n",
|
||||
debugstr_a(szFile), lBufferSize);
|
||||
URLCacheContainer_UnlockIndex(pContainer, pHeader);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
URLCacheContainer_UnlockIndex(pContainer, pHeader);
|
||||
|
||||
|
|
|
@ -1,7 +1,18 @@
|
|||
--- D:/Wine-CVS/wine/dlls/wininet/http.c Wed May 28 14:33:28 2008
|
||||
+++ D:/ReactOS-Trunk/reactos/dll/win32/wininet/http.c Sun Jun 15 18:16:06 2008
|
||||
@@ -61,6 +61,8 @@
|
||||
#include "wine/debug.h"
|
||||
--- wine-1.3.4/dlls/wininet/internet.h 2010-10-01 14:46:44.000000000 -0400
|
||||
+++ dll/win32/wininet/internet.h 2010-10-09 15:34:13.000000000 -0400
|
||||
@@ -462,7 +462,7 @@
|
||||
LPCVOID NETCON_GetCert(WININET_NETCONNECTION *connection);
|
||||
int NETCON_GetCipherStrength(WININET_NETCONNECTION *connection);
|
||||
DWORD NETCON_set_timeout(WININET_NETCONNECTION *connection, BOOL send, int value);
|
||||
-int sock_get_error(int);
|
||||
+#define sock_get_error(x) WSAGetLastError()
|
||||
|
||||
extern void URLCacheContainers_CreateDefaults(void);
|
||||
extern void URLCacheContainers_DeleteAll(void);
|
||||
--- wine-1.3.4/dlls/wininet/http.c 2010-10-01 14:46:44.000000000 -0400
|
||||
+++ dll/win32/wininet/http.c 2010-10-09 15:28:29.000000000 -0400
|
||||
@@ -69,6 +69,8 @@
|
||||
#include "wine/exception.h"
|
||||
#include "wine/unicode.h"
|
||||
|
||||
+#include "inet_ntop.c"
|
||||
|
@ -9,95 +20,21 @@
|
|||
WINE_DEFAULT_DEBUG_CHANNEL(wininet);
|
||||
|
||||
static const WCHAR g_szHttp1_0[] = {'H','T','T','P','/','1','.','0',0};
|
||||
--- D:/Wine-CVS/wine/dlls/wininet/internet.c Wed May 28 14:33:28 2008
|
||||
+++ D:/ReactOS-Trunk/reactos/dll/win32/wininet/internet.c Fri May 30 18:04:29 2008
|
||||
@@ -3101,19 +3101,22 @@
|
||||
|
||||
LPSTR INTERNET_GetNextLine(INT nSocket, LPDWORD dwLen)
|
||||
{
|
||||
- struct pollfd pfd;
|
||||
+ struct timeval tv;
|
||||
+ fd_set infd;
|
||||
BOOL bSuccess = FALSE;
|
||||
INT nRecv = 0;
|
||||
LPSTR lpszBuffer = INTERNET_GetResponseBuffer();
|
||||
|
||||
TRACE("\n");
|
||||
|
||||
- pfd.fd = nSocket;
|
||||
- pfd.events = POLLIN;
|
||||
+ FD_ZERO(&infd);
|
||||
+ FD_SET(nSocket, &infd);
|
||||
+ tv.tv_sec=RESPONSE_TIMEOUT;
|
||||
+ tv.tv_usec=0;
|
||||
|
||||
while (nRecv < MAX_REPLY_LEN)
|
||||
{
|
||||
- if (poll(&pfd,1, RESPONSE_TIMEOUT * 1000) > 0)
|
||||
+ if (select(nSocket+1,&infd,NULL,NULL,&tv) > 0)
|
||||
{
|
||||
if (recv(nSocket, &lpszBuffer[nRecv], 1, 0) <= 0)
|
||||
{
|
||||
--- D:/Wine-CVS/wine/dlls/wininet/internet.h Fri Mar 28 20:13:36 2008
|
||||
+++ D:/ReactOS-Trunk/reactos/dll/win32/wininet/internet.h Thu May 29 19:01:31 2008
|
||||
@@ -23,6 +23,9 @@
|
||||
#ifndef _WINE_INTERNET_H_
|
||||
#define _WINE_INTERNET_H_
|
||||
|
||||
+/* ReactOS-specific definitions */
|
||||
+#define CP_UNIXCP CP_THREAD_ACP
|
||||
+
|
||||
#ifndef __WINE_CONFIG_H
|
||||
# error You must include config.h to use this header
|
||||
#endif
|
||||
--- D:/Wine-CVS/wine/dlls/wininet/netconnection.c Sat May 17 12:09:49 2008
|
||||
+++ D:/ReactOS-Trunk/reactos/dll/win32/wininet/netconnection.c Sat May 31 12:01:55 2008
|
||||
@@ -64,7 +64,7 @@
|
||||
#include "winsock2.h"
|
||||
|
||||
#define RESPONSE_TIMEOUT 30 /* FROM internet.c */
|
||||
-
|
||||
+#define sock_get_error(x) WSAGetLastError()
|
||||
|
||||
WINE_DEFAULT_DEBUG_CHANNEL(wininet);
|
||||
|
||||
@@ -206,6 +206,7 @@
|
||||
--- wine-1.3.4/dlls/wininet/netconnection.c 2010-10-01 14:46:44.000000000 -0400
|
||||
+++ dll/win32/wininet/netconnection.c 2010-10-09 15:33:53.000000000 -0400
|
||||
@@ -547,6 +547,7 @@
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
+#if 0
|
||||
/* translate a unix error code into a winsock one */
|
||||
static int sock_get_error( int err )
|
||||
int sock_get_error( int err )
|
||||
{
|
||||
@@ -272,6 +273,7 @@
|
||||
@@ -613,6 +614,7 @@
|
||||
#endif
|
||||
return err;
|
||||
}
|
||||
+#endif
|
||||
|
||||
/******************************************************************************
|
||||
* NETCON_create
|
||||
@@ -616,16 +618,19 @@
|
||||
|
||||
if (!connection->useSSL)
|
||||
{
|
||||
- struct pollfd pfd;
|
||||
+ struct timeval tv;
|
||||
+ fd_set infd;
|
||||
BOOL bSuccess = FALSE;
|
||||
DWORD nRecv = 0;
|
||||
|
||||
- pfd.fd = connection->socketFD;
|
||||
- pfd.events = POLLIN;
|
||||
+ FD_ZERO(&infd);
|
||||
+ FD_SET(connection->socketFD, &infd);
|
||||
+ tv.tv_sec=RESPONSE_TIMEOUT;
|
||||
+ tv.tv_usec=0;
|
||||
|
||||
while (nRecv < *dwBuffer)
|
||||
{
|
||||
- if (poll(&pfd,1, RESPONSE_TIMEOUT * 1000) > 0)
|
||||
+ if (select(connection->socketFD+1,&infd,NULL,NULL,&tv) > 0)
|
||||
{
|
||||
if (recv(connection->socketFD, &lpszBuffer[nRecv], 1, 0) <= 0)
|
||||
{
|
||||
* NETCON_create
|
Loading…
Add table
Add a link
Reference in a new issue