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:
parent
e05590f454
commit
d6a80a4833
|
@ -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;
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -93,6 +93,7 @@ struct session
|
|||
struct list cookie_cache;
|
||||
HANDLE unload_event;
|
||||
DWORD secure_protocols;
|
||||
DWORD passport_flags;
|
||||
};
|
||||
|
||||
struct connect
|
||||
|
|
Loading…
Reference in New Issue