summaryrefslogtreecommitdiff
path: root/lib/http.c
diff options
context:
space:
mode:
authorDaniel Stenberg <daniel@haxx.se>2008-12-08 13:52:20 +0000
committerDaniel Stenberg <daniel@haxx.se>2008-12-08 13:52:20 +0000
commit42365aa7ef58f0a466f2e4ee42718c358b5a9937 (patch)
tree58d7f2ee5e5c369b3399575330f6ccc2d37edb9f /lib/http.c
parentdff4ce92ad4772e5debaad86f81b830700f499f4 (diff)
downloadcurl-42365aa7ef58f0a466f2e4ee42718c358b5a9937.tar.gz
- 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!
Diffstat (limited to 'lib/http.c')
-rw-r--r--lib/http.c50
1 files changed, 33 insertions, 17 deletions
diff --git a/lib/http.c b/lib/http.c
index 70bf61e39..f7b3610c6 100644
--- a/lib/http.c
+++ b/lib/http.c
@@ -507,8 +507,8 @@ CURLcode Curl_http_auth_act(struct connectdata *conn)
static CURLcode
output_auth_headers(struct connectdata *conn,
struct auth *authstatus,
- const char *request,
- const char *path,
+ const char *request,
+ const char *path,
bool proxy)
{
struct SessionHandle *data = conn->data;
@@ -529,6 +529,7 @@ output_auth_headers(struct connectdata *conn,
if(result)
return result;
authstatus->done = TRUE;
+ data->state.negotiate.state = GSS_AUTHSENT;
}
else
#endif
@@ -545,9 +546,9 @@ output_auth_headers(struct connectdata *conn,
if(authstatus->picked == CURLAUTH_DIGEST) {
auth="Digest";
result = Curl_output_digest(conn,
- proxy,
- (const unsigned char *)request,
- (const unsigned char *)path);
+ proxy,
+ (const unsigned char *)request,
+ (const unsigned char *)path);
if(result)
return result;
}
@@ -562,7 +563,7 @@ output_auth_headers(struct connectdata *conn,
auth="Basic";
result = http_output_basic(conn, proxy);
if(result)
- return result;
+ return result;
}
/* NOTE: this function should set 'done' TRUE, as the other auth
functions work that way */
@@ -571,9 +572,9 @@ output_auth_headers(struct connectdata *conn,
if(auth) {
infof(data, "%s auth using %s with user '%s'\n",
- proxy?"Proxy":"Server", auth,
- proxy?(conn->proxyuser?conn->proxyuser:""):
- (conn->user?conn->user:""));
+ proxy?"Proxy":"Server", auth,
+ proxy?(conn->proxyuser?conn->proxyuser:""):
+ (conn->user?conn->user:""));
authstatus->multi = (bool)(!authstatus->done);
}
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
* types (using &), we OR this authentication type to the authavail
* 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
if(checkprefix("GSS-Negotiate", start) ||
checkprefix("Negotiate", start)) {
+ int neg;
*availp |= CURLAUTH_GSSNEGOTIATE;
authp->avail |= CURLAUTH_GSSNEGOTIATE;
- if(authp->picked == CURLAUTH_GSSNEGOTIATE) {
- /* if exactly this is wanted, go */
- int neg = Curl_input_negotiate(conn, (bool)(httpcode == 407), start);
+
+ if(data->state.negotiate.state == GSS_AUTHSENT) {
+ /* 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) {
DEBUGASSERT(!data->req.newurl);
data->req.newurl = strdup(data->change.url);
- data->state.authproblem = (data->req.newurl == NULL);
- }
- else {
- infof(data, "Authentication problem. Ignoring this.\n");
- data->state.authproblem = TRUE;
+ if(!data->req.newurl)
+ return CURLE_OUT_OF_MEMORY;
+ data->state.authproblem = FALSE;
+ /* we received GSS auth info and we dealt with it fine */
+ data->state.negotiate.state = GSS_AUTHRECV;
}
}
}