mirror of
https://github.com/moparisthebest/curl
synced 2024-12-21 23:58:49 -05:00
- Christian Krause filed bug #2221237
(http://curl.haxx.se/bug/view.cgi?id=2221237) that identified an infinite loop during GSS authentication given some specific conditions. With his patience and great feedback I managed to narrow down the problem and eventually fix it although I can't test any of this myself!
This commit is contained in:
parent
dff4ce92ad
commit
42365aa7ef
7
CHANGES
7
CHANGES
@ -6,6 +6,13 @@
|
|||||||
|
|
||||||
Changelog
|
Changelog
|
||||||
|
|
||||||
|
Daniel Stenberg (8 Dec 2008)
|
||||||
|
- Christian Krause filed bug #2221237
|
||||||
|
(http://curl.haxx.se/bug/view.cgi?id=2221237) that identified an infinite
|
||||||
|
loop during GSS authentication given some specific conditions. With his
|
||||||
|
patience and great feedback I managed to narrow down the problem and
|
||||||
|
eventually fix it although I can't test any of this myself!
|
||||||
|
|
||||||
Daniel Fandrich (3 Dec 2008)
|
Daniel Fandrich (3 Dec 2008)
|
||||||
- Fixed the getifaddrs version of Curl_if2ip to work on systems without IPv6
|
- Fixed the getifaddrs version of Curl_if2ip to work on systems without IPv6
|
||||||
support (e.g. Minix)
|
support (e.g. Minix)
|
||||||
|
@ -24,6 +24,7 @@ This release includes the following bugfixes:
|
|||||||
o fix SCP/SFTP busyloop by using a new libssh2 0.19 function
|
o fix SCP/SFTP busyloop by using a new libssh2 0.19 function
|
||||||
o bad fclose() after a fatal error in cookie code
|
o bad fclose() after a fatal error in cookie code
|
||||||
o curl_multi_remove_handle() when the handle was in use in a HTTP pipeline
|
o curl_multi_remove_handle() when the handle was in use in a HTTP pipeline
|
||||||
|
o GSS authentication infinite loop problem
|
||||||
|
|
||||||
This release includes the following known bugs:
|
This release includes the following known bugs:
|
||||||
|
|
||||||
|
50
lib/http.c
50
lib/http.c
@ -507,8 +507,8 @@ CURLcode Curl_http_auth_act(struct connectdata *conn)
|
|||||||
static CURLcode
|
static CURLcode
|
||||||
output_auth_headers(struct connectdata *conn,
|
output_auth_headers(struct connectdata *conn,
|
||||||
struct auth *authstatus,
|
struct auth *authstatus,
|
||||||
const char *request,
|
const char *request,
|
||||||
const char *path,
|
const char *path,
|
||||||
bool proxy)
|
bool proxy)
|
||||||
{
|
{
|
||||||
struct SessionHandle *data = conn->data;
|
struct SessionHandle *data = conn->data;
|
||||||
@ -529,6 +529,7 @@ output_auth_headers(struct connectdata *conn,
|
|||||||
if(result)
|
if(result)
|
||||||
return result;
|
return result;
|
||||||
authstatus->done = TRUE;
|
authstatus->done = TRUE;
|
||||||
|
data->state.negotiate.state = GSS_AUTHSENT;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
#endif
|
#endif
|
||||||
@ -545,9 +546,9 @@ output_auth_headers(struct connectdata *conn,
|
|||||||
if(authstatus->picked == CURLAUTH_DIGEST) {
|
if(authstatus->picked == CURLAUTH_DIGEST) {
|
||||||
auth="Digest";
|
auth="Digest";
|
||||||
result = Curl_output_digest(conn,
|
result = Curl_output_digest(conn,
|
||||||
proxy,
|
proxy,
|
||||||
(const unsigned char *)request,
|
(const unsigned char *)request,
|
||||||
(const unsigned char *)path);
|
(const unsigned char *)path);
|
||||||
if(result)
|
if(result)
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
@ -562,7 +563,7 @@ output_auth_headers(struct connectdata *conn,
|
|||||||
auth="Basic";
|
auth="Basic";
|
||||||
result = http_output_basic(conn, proxy);
|
result = http_output_basic(conn, proxy);
|
||||||
if(result)
|
if(result)
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
/* NOTE: this function should set 'done' TRUE, as the other auth
|
/* NOTE: this function should set 'done' TRUE, as the other auth
|
||||||
functions work that way */
|
functions work that way */
|
||||||
@ -571,9 +572,9 @@ output_auth_headers(struct connectdata *conn,
|
|||||||
|
|
||||||
if(auth) {
|
if(auth) {
|
||||||
infof(data, "%s auth using %s with user '%s'\n",
|
infof(data, "%s auth using %s with user '%s'\n",
|
||||||
proxy?"Proxy":"Server", auth,
|
proxy?"Proxy":"Server", auth,
|
||||||
proxy?(conn->proxyuser?conn->proxyuser:""):
|
proxy?(conn->proxyuser?conn->proxyuser:""):
|
||||||
(conn->user?conn->user:""));
|
(conn->user?conn->user:""));
|
||||||
authstatus->multi = (bool)(!authstatus->done);
|
authstatus->multi = (bool)(!authstatus->done);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -707,24 +708,39 @@ CURLcode Curl_http_input_auth(struct connectdata *conn,
|
|||||||
* If the provided authentication is wanted as one out of several accepted
|
* If the provided authentication is wanted as one out of several accepted
|
||||||
* types (using &), we OR this authentication type to the authavail
|
* types (using &), we OR this authentication type to the authavail
|
||||||
* variable.
|
* variable.
|
||||||
|
*
|
||||||
|
* Note:
|
||||||
|
*
|
||||||
|
* ->picked is first set to the 'want' value (one or more bits) before the
|
||||||
|
* request is sent, and then it is again set _after_ all response 401/407
|
||||||
|
* headers have been received but then only to a single preferred method
|
||||||
|
* (bit).
|
||||||
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifdef HAVE_GSSAPI
|
#ifdef HAVE_GSSAPI
|
||||||
if(checkprefix("GSS-Negotiate", start) ||
|
if(checkprefix("GSS-Negotiate", start) ||
|
||||||
checkprefix("Negotiate", start)) {
|
checkprefix("Negotiate", start)) {
|
||||||
|
int neg;
|
||||||
*availp |= CURLAUTH_GSSNEGOTIATE;
|
*availp |= CURLAUTH_GSSNEGOTIATE;
|
||||||
authp->avail |= CURLAUTH_GSSNEGOTIATE;
|
authp->avail |= CURLAUTH_GSSNEGOTIATE;
|
||||||
if(authp->picked == CURLAUTH_GSSNEGOTIATE) {
|
|
||||||
/* if exactly this is wanted, go */
|
if(data->state.negotiate.state == GSS_AUTHSENT) {
|
||||||
int neg = Curl_input_negotiate(conn, (bool)(httpcode == 407), start);
|
/* if we sent GSS authentication in the outgoing request and we get this
|
||||||
|
back, we're in trouble */
|
||||||
|
infof(data, "Authentication problem. Ignoring this.\n");
|
||||||
|
data->state.authproblem = TRUE;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
neg = Curl_input_negotiate(conn, (bool)(httpcode == 407), start);
|
||||||
if(neg == 0) {
|
if(neg == 0) {
|
||||||
DEBUGASSERT(!data->req.newurl);
|
DEBUGASSERT(!data->req.newurl);
|
||||||
data->req.newurl = strdup(data->change.url);
|
data->req.newurl = strdup(data->change.url);
|
||||||
data->state.authproblem = (data->req.newurl == NULL);
|
if(!data->req.newurl)
|
||||||
}
|
return CURLE_OUT_OF_MEMORY;
|
||||||
else {
|
data->state.authproblem = FALSE;
|
||||||
infof(data, "Authentication problem. Ignoring this.\n");
|
/* we received GSS auth info and we dealt with it fine */
|
||||||
data->state.authproblem = TRUE;
|
data->state.negotiate.state = GSS_AUTHRECV;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -299,6 +299,9 @@ struct ntlmdata {
|
|||||||
|
|
||||||
#ifdef HAVE_GSSAPI
|
#ifdef HAVE_GSSAPI
|
||||||
struct negotiatedata {
|
struct negotiatedata {
|
||||||
|
/* when doing Negotiate we first need to receive an auth token and then we
|
||||||
|
need to send our header */
|
||||||
|
enum { GSS_AUTHNONE, GSS_AUTHRECV, GSS_AUTHSENT } state;
|
||||||
bool gss; /* Whether we're processing GSS-Negotiate or Negotiate */
|
bool gss; /* Whether we're processing GSS-Negotiate or Negotiate */
|
||||||
const char* protocol; /* "GSS-Negotiate" or "Negotiate" */
|
const char* protocol; /* "GSS-Negotiate" or "Negotiate" */
|
||||||
OM_uint32 status;
|
OM_uint32 status;
|
||||||
|
Loading…
Reference in New Issue
Block a user