winhttp: Handle Passport redirects.

Signed-off-by: Hans Leidekker <hans@codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
Hans Leidekker 2019-08-02 11:01:37 +02:00 committed by Alexandre Julliard
parent e05590f454
commit d6a80a4833
4 changed files with 122 additions and 4 deletions

View File

@ -873,7 +873,7 @@ static enum auth_scheme scheme_from_flag( DWORD flag )
return SCHEME_INVALID;
}
static DWORD auth_scheme_from_header( WCHAR *header )
static DWORD auth_scheme_from_header( const WCHAR *header )
{
unsigned int i;
@ -2628,7 +2628,7 @@ static WCHAR *get_redirect_url( struct request *request, DWORD *len )
WCHAR *ret;
query_headers( request, WINHTTP_QUERY_LOCATION, NULL, NULL, &size, NULL );
if (GetLastError() != ERROR_INSUFFICIENT_BUFFER) return FALSE;
if (GetLastError() != ERROR_INSUFFICIENT_BUFFER) return NULL;
if (!(ret = heap_alloc( size ))) return NULL;
*len = size / sizeof(WCHAR) - 1;
if (query_headers( request, WINHTTP_QUERY_LOCATION, NULL, ret, &size, NULL )) return ret;
@ -2747,6 +2747,42 @@ end:
return ret;
}
static BOOL is_passport_request( struct request *request )
{
static const WCHAR passportW[] = {'P','a','s','s','p','o','r','t','1','.','4'};
WCHAR buf[1024];
DWORD len = ARRAY_SIZE(buf);
if (!(request->connect->session->passport_flags & WINHTTP_ENABLE_PASSPORT_AUTH) ||
!query_headers( request, WINHTTP_QUERY_WWW_AUTHENTICATE, NULL, buf, &len, NULL )) return FALSE;
if (!strncmpiW( buf, passportW, ARRAY_SIZE(passportW) ) &&
(buf[ARRAY_SIZE(passportW)] == ' ' || !buf[ARRAY_SIZE(passportW)])) return TRUE;
return FALSE;
}
static BOOL handle_passport_redirect( struct request *request )
{
static const WCHAR status401W[] = {'4','0','1',0};
DWORD flags = WINHTTP_ADDREQ_FLAG_ADD | WINHTTP_ADDREQ_FLAG_REPLACE;
int i, len = strlenW( request->raw_headers );
WCHAR *p = request->raw_headers;
if (!process_header( request, attr_status, status401W, flags, FALSE )) return FALSE;
for (i = 0; i < len; i++)
{
if (i <= len - 3 && p[i] == '3' && p[i + 1] == '0' && p[i + 2] == '2')
{
p[i] = '4';
p[i + 2] = '1';
break;
}
}
return TRUE;
}
static BOOL receive_response( struct request *request, BOOL async )
{
BOOL ret;
@ -2774,7 +2810,11 @@ static BOOL receive_response( struct request *request, BOOL async )
if (!(request->hdr.disable_flags & WINHTTP_DISABLE_COOKIES)) record_cookies( request );
if (status == HTTP_STATUS_MOVED || status == HTTP_STATUS_REDIRECT || status == HTTP_STATUS_REDIRECT_KEEP_VERB)
if (status == HTTP_STATUS_REDIRECT && is_passport_request( request ))
{
ret = handle_passport_redirect( request );
}
else if (status == HTTP_STATUS_MOVED || status == HTTP_STATUS_REDIRECT || status == HTTP_STATUS_REDIRECT_KEEP_VERB)
{
if (request->hdr.disable_flags & WINHTTP_DISABLE_REDIRECTS ||
request->hdr.redirect_policy == WINHTTP_OPTION_REDIRECT_POLICY_NEVER) break;

View File

@ -210,7 +210,7 @@ static BOOL session_set_option( struct object_header *hdr, DWORD option, void *b
return TRUE;
case WINHTTP_OPTION_CONFIGURE_PASSPORT_AUTH:
FIXME("WINHTTP_OPTION_CONFIGURE_PASSPORT_AUTH: 0x%x\n", *(DWORD *)buffer);
session->passport_flags = *(DWORD *)buffer;
return TRUE;
case WINHTTP_OPTION_UNLOAD_NOTIFY_EVENT:

View File

@ -2236,6 +2236,13 @@ static const char largeauth[] =
"Content-Type: text/plain\r\n"
"\r\n";
static const char passportauth[] =
"HTTP/1.1 302 Found\r\n"
"Content-Length: 0\r\n"
"Location: /\r\n"
"WWW-Authenticate: Passport1.4\r\n"
"\r\n";
static const char unauthorized[] = "Unauthorized";
static const char hello_world[] = "Hello World";
static const char auth_unseen[] = "Auth Unseen";
@ -2415,6 +2422,10 @@ static DWORD CALLBACK server_thread(LPVOID param)
}
else send(c, notokmsg, sizeof(notokmsg) - 1, 0);
}
else if (strstr(buffer, "GET /passport"))
{
send(c, passportauth, sizeof(passportauth) - 1, 0);
}
if (strstr(buffer, "GET /quit"))
{
send(c, okmsg, sizeof okmsg - 1, 0);
@ -3518,6 +3529,71 @@ static void test_connection_info( int port )
WinHttpCloseHandle( ses );
}
static void test_passport_auth( int port )
{
static const WCHAR passportW[] =
{'/','p','a','s','s','p','o','r','t',0};
static const WCHAR foundW[] =
{'F','o','u','n','d',0};
static const WCHAR unauthorizedW[] =
{'U','n','a','u','t','h','o','r','i','z','e','d',0};
static const WCHAR headersW[] =
{'H','T','T','P','/','1','.','1',' ','4','0','1',' ','F','o','u','n','d','\r','\n',
'C','o','n','t','e','n','t','-','L','e','n','g','t','h',':',' ','0','\r','\n',
'L','o','c','a','t','i','o','n',':',' ','/','\r','\n',
'W','W','W','-','A','u','t','h','e','n','t','i','c','a','t','e',':',' ',
'P','a','s','s','p','o','r','t','1','.','4','\r','\n','\r','\n',0};
HINTERNET ses, con, req;
DWORD status, size, option;
WCHAR buf[128];
BOOL ret;
ses = WinHttpOpen( test_useragent, 0, NULL, NULL, 0 );
ok( ses != NULL, "got %u\n", GetLastError() );
option = WINHTTP_ENABLE_PASSPORT_AUTH;
ret = WinHttpSetOption( ses, WINHTTP_OPTION_CONFIGURE_PASSPORT_AUTH, &option, sizeof(option) );
ok( ret, "got %u\n", GetLastError() );
con = WinHttpConnect( ses, localhostW, port, 0 );
ok( con != NULL, "got %u\n", GetLastError() );
req = WinHttpOpenRequest( con, NULL, passportW, NULL, NULL, NULL, 0 );
ok( req != NULL, "got %u\n", GetLastError() );
ret = WinHttpSendRequest( req, NULL, 0, NULL, 0, 0, 0 );
ok( ret, "got %u\n", GetLastError() );
ret = WinHttpReceiveResponse( req, NULL );
ok( ret, "got %u\n", GetLastError() );
status = 0xdeadbeef;
size = sizeof(status);
ret = WinHttpQueryHeaders( req, WINHTTP_QUERY_STATUS_CODE|WINHTTP_QUERY_FLAG_NUMBER, NULL, &status, &size, NULL );
ok( ret, "got %u\n", GetLastError() );
ok( status == HTTP_STATUS_DENIED, "got %u\n", status );
buf[0] = 0;
size = sizeof(buf);
ret = WinHttpQueryHeaders( req, WINHTTP_QUERY_STATUS_TEXT, NULL, buf, &size, NULL );
ok( ret, "got %u\n", GetLastError() );
ok( !lstrcmpW(foundW, buf) || broken(!lstrcmpW(unauthorizedW, buf)) /* < win7 */, "got %s\n", wine_dbgstr_w(buf) );
buf[0] = 0;
size = sizeof(buf);
ret = WinHttpQueryHeaders( req, WINHTTP_QUERY_RAW_HEADERS_CRLF, NULL, buf, &size, NULL );
ok( ret || broken(!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER) /* < win7 */, "got %u\n", GetLastError() );
if (ret)
{
ok( size == lstrlenW(headersW) * sizeof(WCHAR), "got %u\n", size );
ok( !lstrcmpW(headersW, buf), "got %s\n", wine_dbgstr_w(buf) );
}
WinHttpCloseHandle( req );
WinHttpCloseHandle( con );
WinHttpCloseHandle( ses );
}
static void test_credentials(void)
{
static WCHAR userW[] = {'u','s','e','r',0};
@ -4783,6 +4859,7 @@ START_TEST (winhttp)
test_multiple_reads(si.port);
test_cookies(si.port);
test_request_path_escapes(si.port);
test_passport_auth(si.port);
/* send the basic request again to shutdown the server thread */
test_basic_request(si.port, NULL, quitW);

View File

@ -93,6 +93,7 @@ struct session
struct list cookie_cache;
HANDLE unload_event;
DWORD secure_protocols;
DWORD passport_flags;
};
struct connect