winhttp: Add support for NTLM and Negotiate authentication.
This commit is contained in:
parent
d63ef4d855
commit
a506d0aa3b
|
@ -1206,29 +1206,45 @@ BOOL WINAPI WinHttpSendRequest( HINTERNET hrequest, LPCWSTR headers, DWORD heade
|
|||
|
||||
#define ARRAYSIZE(array) (sizeof(array) / sizeof((array)[0]))
|
||||
|
||||
static const WCHAR basicW[] = {'B','a','s','i','c',0};
|
||||
static const WCHAR ntlmW[] = {'N','T','L','M',0};
|
||||
static const WCHAR passportW[] = {'P','a','s','s','p','o','r','t',0};
|
||||
static const WCHAR digestW[] = {'D','i','g','e','s','t',0};
|
||||
static const WCHAR negotiateW[] = {'N','e','g','o','t','i','a','t','e',0};
|
||||
|
||||
static const struct
|
||||
{
|
||||
const WCHAR *str;
|
||||
unsigned int len;
|
||||
DWORD scheme;
|
||||
}
|
||||
auth_schemes[] =
|
||||
{
|
||||
{ basicW, ARRAYSIZE(basicW) - 1, WINHTTP_AUTH_SCHEME_BASIC },
|
||||
{ ntlmW, ARRAYSIZE(ntlmW) - 1, WINHTTP_AUTH_SCHEME_NTLM },
|
||||
{ passportW, ARRAYSIZE(passportW) - 1, WINHTTP_AUTH_SCHEME_PASSPORT },
|
||||
{ digestW, ARRAYSIZE(digestW) - 1, WINHTTP_AUTH_SCHEME_DIGEST },
|
||||
{ negotiateW, ARRAYSIZE(negotiateW) - 1, WINHTTP_AUTH_SCHEME_NEGOTIATE }
|
||||
};
|
||||
static const unsigned int num_auth_schemes = sizeof(auth_schemes)/sizeof(auth_schemes[0]);
|
||||
|
||||
static enum auth_scheme scheme_from_flag( DWORD flag )
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < num_auth_schemes; i++) if (flag == auth_schemes[i].scheme) return i;
|
||||
return SCHEME_INVALID;
|
||||
}
|
||||
|
||||
static DWORD auth_scheme_from_header( WCHAR *header )
|
||||
{
|
||||
static const WCHAR basic[] = {'B','a','s','i','c'};
|
||||
static const WCHAR ntlm[] = {'N','T','L','M'};
|
||||
static const WCHAR passport[] = {'P','a','s','s','p','o','r','t'};
|
||||
static const WCHAR digest[] = {'D','i','g','e','s','t'};
|
||||
static const WCHAR negotiate[] = {'N','e','g','o','t','i','a','t','e'};
|
||||
|
||||
if (!strncmpiW( header, basic, ARRAYSIZE(basic) ) &&
|
||||
(header[ARRAYSIZE(basic)] == ' ' || !header[ARRAYSIZE(basic)])) return WINHTTP_AUTH_SCHEME_BASIC;
|
||||
|
||||
if (!strncmpiW( header, ntlm, ARRAYSIZE(ntlm) ) &&
|
||||
(header[ARRAYSIZE(ntlm)] == ' ' || !header[ARRAYSIZE(ntlm)])) return WINHTTP_AUTH_SCHEME_NTLM;
|
||||
|
||||
if (!strncmpiW( header, passport, ARRAYSIZE(passport) ) &&
|
||||
(header[ARRAYSIZE(passport)] == ' ' || !header[ARRAYSIZE(passport)])) return WINHTTP_AUTH_SCHEME_PASSPORT;
|
||||
|
||||
if (!strncmpiW( header, digest, ARRAYSIZE(digest) ) &&
|
||||
(header[ARRAYSIZE(digest)] == ' ' || !header[ARRAYSIZE(digest)])) return WINHTTP_AUTH_SCHEME_DIGEST;
|
||||
|
||||
if (!strncmpiW( header, negotiate, ARRAYSIZE(negotiate) ) &&
|
||||
(header[ARRAYSIZE(negotiate)] == ' ' || !header[ARRAYSIZE(negotiate)])) return WINHTTP_AUTH_SCHEME_NEGOTIATE;
|
||||
unsigned int i;
|
||||
|
||||
for (i = 0; i < num_auth_schemes; i++)
|
||||
{
|
||||
if (!strncmpiW( header, auth_schemes[i].str, auth_schemes[i].len ) &&
|
||||
(header[auth_schemes[i].len] == ' ' || !header[auth_schemes[i].len])) return auth_schemes[i].scheme;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -1341,72 +1357,341 @@ static UINT encode_base64( const char *bin, unsigned int len, WCHAR *base64 )
|
|||
return n;
|
||||
}
|
||||
|
||||
static BOOL set_credentials( request_t *request, DWORD target, DWORD scheme, LPCWSTR username, LPCWSTR password )
|
||||
static inline char decode_char( WCHAR c )
|
||||
{
|
||||
static const WCHAR basic[] = {'B','a','s','i','c',' ',0};
|
||||
const WCHAR *auth_scheme, *auth_target;
|
||||
WCHAR *auth_header;
|
||||
DWORD len, auth_data_len;
|
||||
char *auth_data;
|
||||
if (c >= 'A' && c <= 'Z') return c - 'A';
|
||||
if (c >= 'a' && c <= 'z') return c - 'a' + 26;
|
||||
if (c >= '0' && c <= '9') return c - '0' + 52;
|
||||
if (c == '+') return 62;
|
||||
if (c == '/') return 63;
|
||||
return 64;
|
||||
}
|
||||
|
||||
static unsigned int decode_base64( const WCHAR *base64, unsigned int len, char *buf )
|
||||
{
|
||||
unsigned int i = 0;
|
||||
char c0, c1, c2, c3;
|
||||
const WCHAR *p = base64;
|
||||
|
||||
while (len >= 4)
|
||||
{
|
||||
if ((c0 = decode_char( p[0] )) > 63) return 0;
|
||||
if ((c1 = decode_char( p[1] )) > 63) return 0;
|
||||
if ((c2 = decode_char( p[2] )) > 63) return 0;
|
||||
if ((c3 = decode_char( p[3] )) > 63) return 0;
|
||||
|
||||
if (buf)
|
||||
{
|
||||
buf[i + 0] = (c0 << 2) | (c1 >> 4);
|
||||
buf[i + 1] = (c1 << 4) | (c2 >> 2);
|
||||
buf[i + 2] = (c2 << 6) | c3;
|
||||
}
|
||||
len -= 4;
|
||||
i += 3;
|
||||
p += 4;
|
||||
}
|
||||
if (p[2] == '=')
|
||||
{
|
||||
if ((c0 = decode_char( p[0] )) > 63) return 0;
|
||||
if ((c1 = decode_char( p[1] )) > 63) return 0;
|
||||
|
||||
if (buf) buf[i] = (c0 << 2) | (c1 >> 4);
|
||||
i++;
|
||||
}
|
||||
else if (p[3] == '=')
|
||||
{
|
||||
if ((c0 = decode_char( p[0] )) > 63) return 0;
|
||||
if ((c1 = decode_char( p[1] )) > 63) return 0;
|
||||
if ((c2 = decode_char( p[2] )) > 63) return 0;
|
||||
|
||||
if (buf)
|
||||
{
|
||||
buf[i + 0] = (c0 << 2) | (c1 >> 4);
|
||||
buf[i + 1] = (c1 << 4) | (c2 >> 2);
|
||||
}
|
||||
i += 2;
|
||||
}
|
||||
return i;
|
||||
}
|
||||
|
||||
static struct authinfo *alloc_authinfo(void)
|
||||
{
|
||||
struct authinfo *ret;
|
||||
|
||||
if (!(ret = heap_alloc( sizeof(*ret) ))) return NULL;
|
||||
|
||||
SecInvalidateHandle( &ret->cred );
|
||||
SecInvalidateHandle( &ret->ctx );
|
||||
memset( &ret->exp, 0, sizeof(ret->exp) );
|
||||
ret->scheme = 0;
|
||||
ret->attr = 0;
|
||||
ret->max_token = 0;
|
||||
ret->data = NULL;
|
||||
ret->data_len = 0;
|
||||
ret->finished = FALSE;
|
||||
return ret;
|
||||
}
|
||||
|
||||
void destroy_authinfo( struct authinfo *authinfo )
|
||||
{
|
||||
if (!authinfo) return;
|
||||
|
||||
if (SecIsValidHandle( &authinfo->ctx ))
|
||||
DeleteSecurityContext( &authinfo->ctx );
|
||||
if (SecIsValidHandle( &authinfo->cred ))
|
||||
FreeCredentialsHandle( &authinfo->cred );
|
||||
|
||||
heap_free( authinfo->data );
|
||||
heap_free( authinfo );
|
||||
}
|
||||
|
||||
static BOOL get_authvalue( request_t *request, DWORD level, DWORD scheme, WCHAR *buffer, DWORD len )
|
||||
{
|
||||
DWORD size, index = 0;
|
||||
for (;;)
|
||||
{
|
||||
size = len;
|
||||
if (!query_headers( request, level, NULL, buffer, &size, &index )) return FALSE;
|
||||
if (auth_scheme_from_header( buffer ) == scheme) break;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static BOOL do_authorization( request_t *request, DWORD target, DWORD scheme_flag )
|
||||
{
|
||||
struct authinfo *authinfo, **auth_ptr;
|
||||
enum auth_scheme scheme = scheme_from_flag( scheme_flag );
|
||||
const WCHAR *auth_target, *username, *password;
|
||||
WCHAR auth_value[2048], *auth_reply;
|
||||
DWORD len = sizeof(auth_value), len_scheme, flags;
|
||||
BOOL ret;
|
||||
|
||||
if (scheme == SCHEME_INVALID) return FALSE;
|
||||
|
||||
switch (target)
|
||||
{
|
||||
case WINHTTP_AUTH_TARGET_SERVER:
|
||||
if (!get_authvalue( request, WINHTTP_QUERY_WWW_AUTHENTICATE, scheme_flag, auth_value, len ))
|
||||
return FALSE;
|
||||
auth_ptr = &request->authinfo;
|
||||
auth_target = attr_authorization;
|
||||
username = request->connect->username;
|
||||
password = request->connect->password;
|
||||
break;
|
||||
|
||||
case WINHTTP_AUTH_TARGET_PROXY:
|
||||
if (!get_authvalue( request, WINHTTP_QUERY_PROXY_AUTHENTICATE, scheme_flag, auth_value, len ))
|
||||
return FALSE;
|
||||
auth_ptr = &request->proxy_authinfo;
|
||||
auth_target = attr_proxy_authorization;
|
||||
username = request->connect->session->proxy_username;
|
||||
password = request->connect->session->proxy_password;
|
||||
break;
|
||||
|
||||
default:
|
||||
WARN("unknown target %x\n", target);
|
||||
return FALSE;
|
||||
}
|
||||
authinfo = *auth_ptr;
|
||||
|
||||
switch (scheme)
|
||||
{
|
||||
case SCHEME_BASIC:
|
||||
{
|
||||
int userlen, passlen;
|
||||
|
||||
if (!username || !password) return FALSE;
|
||||
if ((!authinfo && !(authinfo = alloc_authinfo())) || authinfo->finished) return FALSE;
|
||||
|
||||
userlen = WideCharToMultiByte( CP_UTF8, 0, username, strlenW( username ), NULL, 0, NULL, NULL );
|
||||
passlen = WideCharToMultiByte( CP_UTF8, 0, password, strlenW( password ), NULL, 0, NULL, NULL );
|
||||
|
||||
authinfo->data_len = userlen + 1 + passlen;
|
||||
if (!(authinfo->data = heap_alloc( authinfo->data_len ))) return FALSE;
|
||||
|
||||
WideCharToMultiByte( CP_UTF8, 0, username, -1, authinfo->data, userlen, NULL, NULL );
|
||||
authinfo->data[userlen] = ':';
|
||||
WideCharToMultiByte( CP_UTF8, 0, password, -1, authinfo->data + userlen + 1, passlen, NULL, NULL );
|
||||
|
||||
authinfo->scheme = SCHEME_BASIC;
|
||||
authinfo->finished = TRUE;
|
||||
break;
|
||||
}
|
||||
case SCHEME_NTLM:
|
||||
case SCHEME_NEGOTIATE:
|
||||
{
|
||||
SECURITY_STATUS status;
|
||||
SecBufferDesc out_desc, in_desc;
|
||||
SecBuffer out, in;
|
||||
ULONG flags = ISC_REQ_CONNECTION|ISC_REQ_USE_DCE_STYLE|ISC_REQ_MUTUAL_AUTH|ISC_REQ_DELEGATE;
|
||||
const WCHAR *p;
|
||||
BOOL first = FALSE;
|
||||
|
||||
if (!authinfo)
|
||||
{
|
||||
TimeStamp exp;
|
||||
SEC_WINNT_AUTH_IDENTITY_W id;
|
||||
WCHAR *domain, *user;
|
||||
|
||||
if (!username || !password || !(authinfo = alloc_authinfo())) return FALSE;
|
||||
|
||||
first = TRUE;
|
||||
domain = (WCHAR *)username;
|
||||
user = strchrW( username, '\\' );
|
||||
|
||||
if (user) user++;
|
||||
else
|
||||
{
|
||||
user = (WCHAR *)username;
|
||||
domain = NULL;
|
||||
}
|
||||
id.Flags = SEC_WINNT_AUTH_IDENTITY_UNICODE;
|
||||
id.User = user;
|
||||
id.UserLength = strlenW( user );
|
||||
id.Domain = domain;
|
||||
id.DomainLength = domain ? user - domain - 1 : 0;
|
||||
id.Password = (WCHAR *)password;
|
||||
id.PasswordLength = strlenW( password );
|
||||
|
||||
status = AcquireCredentialsHandleW( NULL, (SEC_WCHAR *)auth_schemes[scheme].str,
|
||||
SECPKG_CRED_OUTBOUND, NULL, &id, NULL, NULL,
|
||||
&authinfo->cred, &exp );
|
||||
if (status == SEC_E_OK)
|
||||
{
|
||||
PSecPkgInfoW info;
|
||||
status = QuerySecurityPackageInfoW( (SEC_WCHAR *)auth_schemes[scheme].str, &info );
|
||||
if (status == SEC_E_OK)
|
||||
{
|
||||
authinfo->max_token = info->cbMaxToken;
|
||||
FreeContextBuffer( info );
|
||||
}
|
||||
}
|
||||
if (status != SEC_E_OK)
|
||||
{
|
||||
WARN("AcquireCredentialsHandleW for scheme %s failed with error 0x%08x\n",
|
||||
debugstr_w(auth_schemes[scheme].str), status);
|
||||
heap_free( authinfo );
|
||||
return FALSE;
|
||||
}
|
||||
authinfo->scheme = scheme;
|
||||
}
|
||||
else if (authinfo->finished) return FALSE;
|
||||
|
||||
if ((strlenW( auth_value ) < auth_schemes[authinfo->scheme].len ||
|
||||
strncmpiW( auth_value, auth_schemes[authinfo->scheme].str, auth_schemes[authinfo->scheme].len )))
|
||||
{
|
||||
ERR("authentication scheme changed from %s to %s\n",
|
||||
debugstr_w(auth_schemes[authinfo->scheme].str), debugstr_w(auth_value));
|
||||
return FALSE;
|
||||
}
|
||||
in.BufferType = SECBUFFER_TOKEN;
|
||||
in.cbBuffer = 0;
|
||||
in.pvBuffer = NULL;
|
||||
|
||||
in_desc.ulVersion = 0;
|
||||
in_desc.cBuffers = 1;
|
||||
in_desc.pBuffers = ∈
|
||||
|
||||
p = auth_value + auth_schemes[scheme].len;
|
||||
if (*p == ' ')
|
||||
{
|
||||
int len = strlenW( ++p );
|
||||
in.cbBuffer = decode_base64( p, len, NULL );
|
||||
if (!(in.pvBuffer = heap_alloc( in.cbBuffer ))) return FALSE;
|
||||
decode_base64( p, len, in.pvBuffer );
|
||||
}
|
||||
out.BufferType = SECBUFFER_TOKEN;
|
||||
out.cbBuffer = authinfo->max_token;
|
||||
if (!(out.pvBuffer = heap_alloc( authinfo->max_token )))
|
||||
{
|
||||
heap_free( in.pvBuffer );
|
||||
return FALSE;
|
||||
}
|
||||
out_desc.ulVersion = 0;
|
||||
out_desc.cBuffers = 1;
|
||||
out_desc.pBuffers = &out;
|
||||
|
||||
status = InitializeSecurityContextW( first ? &authinfo->cred : NULL, first ? NULL : &authinfo->ctx,
|
||||
first ? request->connect->servername : NULL, flags, 0,
|
||||
SECURITY_NETWORK_DREP, in.pvBuffer ? &in_desc : NULL, 0,
|
||||
&authinfo->ctx, &out_desc, &authinfo->attr, &authinfo->exp );
|
||||
heap_free( in.pvBuffer );
|
||||
if (status == SEC_E_OK)
|
||||
{
|
||||
heap_free( authinfo->data );
|
||||
authinfo->data = out.pvBuffer;
|
||||
authinfo->data_len = out.cbBuffer;
|
||||
authinfo->finished = TRUE;
|
||||
TRACE("sending last auth packet\n");
|
||||
}
|
||||
else if (status == SEC_I_CONTINUE_NEEDED)
|
||||
{
|
||||
heap_free( authinfo->data );
|
||||
authinfo->data = out.pvBuffer;
|
||||
authinfo->data_len = out.cbBuffer;
|
||||
TRACE("sending next auth packet\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
ERR("InitializeSecurityContextW failed with error 0x%08x\n", status);
|
||||
heap_free( out.pvBuffer );
|
||||
destroy_authinfo( authinfo );
|
||||
*auth_ptr = NULL;
|
||||
return FALSE;
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
ERR("invalid scheme %u\n", scheme);
|
||||
return FALSE;
|
||||
}
|
||||
*auth_ptr = authinfo;
|
||||
|
||||
len_scheme = auth_schemes[authinfo->scheme].len;
|
||||
len = len_scheme + 1 + ((authinfo->data_len + 2) * 4) / 3;
|
||||
if (!(auth_reply = heap_alloc( (len + 1) * sizeof(WCHAR) ))) return FALSE;
|
||||
|
||||
memcpy( auth_reply, auth_schemes[authinfo->scheme].str, len_scheme * sizeof(WCHAR) );
|
||||
auth_reply[len_scheme] = ' ';
|
||||
encode_base64( authinfo->data, authinfo->data_len, auth_reply + len_scheme + 1 );
|
||||
|
||||
flags = WINHTTP_ADDREQ_FLAG_ADD | WINHTTP_ADDREQ_FLAG_REPLACE;
|
||||
ret = process_header( request, auth_target, auth_reply, flags, TRUE );
|
||||
heap_free( auth_reply );
|
||||
return ret;
|
||||
}
|
||||
|
||||
static BOOL set_credentials( request_t *request, DWORD target, DWORD scheme, const WCHAR *username,
|
||||
const WCHAR *password )
|
||||
{
|
||||
if (!username || !password)
|
||||
{
|
||||
set_last_error( ERROR_INVALID_PARAMETER );
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
switch (target)
|
||||
{
|
||||
case WINHTTP_AUTH_TARGET_SERVER: auth_target = attr_authorization; break;
|
||||
case WINHTTP_AUTH_TARGET_PROXY: auth_target = attr_proxy_authorization; break;
|
||||
default:
|
||||
WARN("unknown target %x\n", target);
|
||||
return FALSE;
|
||||
}
|
||||
switch (scheme)
|
||||
case WINHTTP_AUTH_TARGET_SERVER:
|
||||
{
|
||||
case WINHTTP_AUTH_SCHEME_BASIC:
|
||||
{
|
||||
int userlen = WideCharToMultiByte( CP_UTF8, 0, username, strlenW( username ), NULL, 0, NULL, NULL );
|
||||
int passlen = WideCharToMultiByte( CP_UTF8, 0, password, strlenW( password ), NULL, 0, NULL, NULL );
|
||||
|
||||
TRACE("basic authentication\n");
|
||||
|
||||
auth_scheme = basic;
|
||||
auth_data_len = userlen + 1 + passlen;
|
||||
if (!(auth_data = heap_alloc( auth_data_len ))) return FALSE;
|
||||
|
||||
WideCharToMultiByte( CP_UTF8, 0, username, -1, auth_data, userlen, NULL, NULL );
|
||||
auth_data[userlen] = ':';
|
||||
WideCharToMultiByte( CP_UTF8, 0, password, -1, auth_data + userlen + 1, passlen, NULL, NULL );
|
||||
heap_free( request->connect->username );
|
||||
if (!(request->connect->username = strdupW( username ))) return FALSE;
|
||||
heap_free( request->connect->password );
|
||||
if (!(request->connect->password = strdupW( password ))) return FALSE;
|
||||
break;
|
||||
}
|
||||
case WINHTTP_AUTH_SCHEME_NTLM:
|
||||
case WINHTTP_AUTH_SCHEME_PASSPORT:
|
||||
case WINHTTP_AUTH_SCHEME_DIGEST:
|
||||
case WINHTTP_AUTH_SCHEME_NEGOTIATE:
|
||||
FIXME("unimplemented authentication scheme %x\n", scheme);
|
||||
return FALSE;
|
||||
default:
|
||||
WARN("unknown authentication scheme %x\n", scheme);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
len = strlenW( auth_scheme ) + ((auth_data_len + 2) * 4) / 3;
|
||||
if (!(auth_header = heap_alloc( (len + 1) * sizeof(WCHAR) )))
|
||||
case WINHTTP_AUTH_TARGET_PROXY:
|
||||
{
|
||||
heap_free( auth_data );
|
||||
heap_free( request->connect->session->proxy_username );
|
||||
if (!(request->connect->session->proxy_username = strdupW( username ))) return FALSE;
|
||||
heap_free( request->connect->session->proxy_password );
|
||||
if (!(request->connect->session->proxy_password = strdupW( password ))) return FALSE;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
WARN("unknown target %u\n", target);
|
||||
return FALSE;
|
||||
}
|
||||
strcpyW( auth_header, auth_scheme );
|
||||
encode_base64( auth_data, auth_data_len, auth_header + strlenW( auth_header ) );
|
||||
|
||||
ret = process_header( request, auth_target, auth_header, WINHTTP_ADDREQ_FLAG_ADD | WINHTTP_ADDREQ_FLAG_REPLACE, TRUE );
|
||||
|
||||
heap_free( auth_data );
|
||||
heap_free( auth_header );
|
||||
return ret;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
|
@ -1440,8 +1725,7 @@ BOOL WINAPI WinHttpSetCredentials( HINTERNET hrequest, DWORD target, DWORD schem
|
|||
|
||||
static BOOL handle_authorization( request_t *request, DWORD status )
|
||||
{
|
||||
DWORD schemes, level, target;
|
||||
const WCHAR *username, *password;
|
||||
DWORD i, schemes, first, level, target;
|
||||
|
||||
switch (status)
|
||||
{
|
||||
|
@ -1460,23 +1744,15 @@ static BOOL handle_authorization( request_t *request, DWORD status )
|
|||
return FALSE;
|
||||
}
|
||||
|
||||
if (!query_auth_schemes( request, level, &schemes, NULL )) return FALSE;
|
||||
if (!query_auth_schemes( request, level, &schemes, &first )) return FALSE;
|
||||
if (do_authorization( request, target, first )) return TRUE;
|
||||
|
||||
if (target == WINHTTP_AUTH_TARGET_SERVER)
|
||||
schemes &= ~first;
|
||||
for (i = 0; i < num_auth_schemes; i++)
|
||||
{
|
||||
username = request->connect->username;
|
||||
password = request->connect->password;
|
||||
if (!(schemes & auth_schemes[i].scheme)) continue;
|
||||
if (do_authorization( request, target, auth_schemes[i].scheme )) return TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
username = request->connect->session->proxy_username;
|
||||
password = request->connect->session->proxy_password;
|
||||
}
|
||||
|
||||
if (schemes & WINHTTP_AUTH_SCHEME_BASIC)
|
||||
return set_credentials( request, target, WINHTTP_AUTH_SCHEME_BASIC, username, password );
|
||||
|
||||
FIXME("unsupported authentication scheme\n");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
|
|
@ -552,6 +552,9 @@ static void request_destroy( object_header_t *hdr )
|
|||
|
||||
release_object( &request->connect->hdr );
|
||||
|
||||
destroy_authinfo( request->authinfo );
|
||||
destroy_authinfo( request->proxy_authinfo );
|
||||
|
||||
heap_free( request->verb );
|
||||
heap_free( request->path );
|
||||
heap_free( request->version );
|
||||
|
|
|
@ -148,6 +148,29 @@ typedef struct
|
|||
BOOL is_request; /* part of request headers? */
|
||||
} header_t;
|
||||
|
||||
enum auth_scheme
|
||||
{
|
||||
SCHEME_INVALID = -1,
|
||||
SCHEME_BASIC,
|
||||
SCHEME_NTLM,
|
||||
SCHEME_PASSPORT,
|
||||
SCHEME_DIGEST,
|
||||
SCHEME_NEGOTIATE
|
||||
};
|
||||
|
||||
struct authinfo
|
||||
{
|
||||
enum auth_scheme scheme;
|
||||
CredHandle cred;
|
||||
CtxtHandle ctx;
|
||||
TimeStamp exp;
|
||||
ULONG attr;
|
||||
ULONG max_token;
|
||||
char *data;
|
||||
unsigned int data_len;
|
||||
BOOL finished; /* finished authenticating */
|
||||
};
|
||||
|
||||
typedef struct
|
||||
{
|
||||
object_header_t hdr;
|
||||
|
@ -174,6 +197,8 @@ typedef struct
|
|||
DWORD num_headers;
|
||||
WCHAR **accept_types;
|
||||
DWORD num_accept_types;
|
||||
struct authinfo *authinfo;
|
||||
struct authinfo *proxy_authinfo;
|
||||
} request_t;
|
||||
|
||||
typedef struct _task_header_t task_header_t;
|
||||
|
@ -252,7 +277,8 @@ BOOL set_cookies( request_t *, const WCHAR * ) DECLSPEC_HIDDEN;
|
|||
BOOL add_cookie_headers( request_t * ) DECLSPEC_HIDDEN;
|
||||
BOOL add_request_headers( request_t *, LPCWSTR, DWORD, DWORD ) DECLSPEC_HIDDEN;
|
||||
void delete_domain( domain_t * ) DECLSPEC_HIDDEN;
|
||||
BOOL set_server_for_hostname( connect_t *connect, LPCWSTR server, INTERNET_PORT port ) DECLSPEC_HIDDEN;
|
||||
BOOL set_server_for_hostname( connect_t *, LPCWSTR, INTERNET_PORT ) DECLSPEC_HIDDEN;
|
||||
void destroy_authinfo( struct authinfo * ) DECLSPEC_HIDDEN;
|
||||
|
||||
extern HRESULT WinHttpRequest_create( IUnknown *, void ** ) DECLSPEC_HIDDEN;
|
||||
|
||||
|
|
Loading…
Reference in New Issue