curl-library
Reusing Authorization header
Date: Fri, 16 Feb 2007 12:20:30 -0500
Hi,
I am trying to fetch a HTTP URL with the following
configuration.
Red Hat Linux
libcurl version 7.16.0
Authentication : HTTP Digest
Proxy Configured : No
Application code language : C++ (gcc version 3.2.3 20030502 )
Following Options have been set to a meaningful valueon the Curl handle:
CURLOPT_WRITEFUNCTION, CURLOPT_WRITEDATA,
CURLOPT_HEADERFUNCTION, CURLOPT_HEADERDATA,
CURLOPT_FAILONERROR, CURLOPT_URL, CURLOPT_CRLF,
CURLOPT_USERPWD
CURLOPT_FRESH_CONNECT (or any other relevant
parameter) has not been explicitly set to any value,
which makes the connection reuse enabled as default.
Scenario:
1. HTTP GET is tried on a URL with a set of credentials configured in libcurl.
2. The server challanges the GET request with a set of realm, nonce
and qop in the Authenticate header.
3. The Application/Libcurl sends the GET with Authorization header
containing all the required parameters (with correct response).
4. Server responds with 200 OK.
5. Another request for the same request URL is made with a different
set of credentials configured. (before the connection times out)
6. Libcurl uses the Authorization header used for the previous GET
request. (containing the username, response,... used for the previous
GET request)
7. Server challanges the GET request with a set ofrealm, nonce and qop.
8. Libcurl uses the new username/password to create
the Authorization header.
9. Server sends 200 OK.
Analysis:
1. When the Authorization header is encoded for thefirst GET request,
the header value is stored in the allocptr.userpwd structure of conn
structure.
2. When the second get request (in step 5) is made CreateConnection
function (url.c) checks whether we can reuse the connection or not. If
we can then it uses the conn structure used in first get request and
overwrites the username and password parameter in the conn structure.
3. Then the function Curl_output_digest (http_digesti.c) is called
which checks whether we have nonce value for this request
(if(!d->nonce)). Since we don't have a nonce value we return from this
function without encoding a new Authorization header. However, the
previous Authorization header is still present in
conn->allocptr.userpwd field. And may be this field is used eventually
in the GET request.
4. I changed the code in function CreateConnection where the new
user-name and password are being copied to the connection structure,
to free the allocptr.userpwd field and set it to NULL. After this
change there was no Authorization header in the GET
request (of step 5). The changed code looked like this:
----------------------------------------
if (conn->bits.user_passwd) {
/* use the new user namd and password though */
Curl_safefree(conn->user);
Curl_safefree(conn->passwd);
Curl_safefree(conn->allocptr.userpwd); /* Added line */
conn->user = old_conn->user;
conn->passwd = old_conn->passwd;
conn->allocptr.userpwd = NULL; /* Added line */
old_conn->user = NULL;
old_conn->passwd = NULL;
}
----------------------------------------
Queries:
1. Are the changes done by me required and correct ?
2. If the changes done bove are correct then we would probably need
have a similar code in the case where proxy user+password is set.
if (conn->bits.proxy_user_passwd) {
...
}
3. I found a similar query http://curl.haxx.se/mail/lib-2003-11/0148.html.
However, this issue was resolved without a explicit code-change. May
be this was the cause for this.
4. A possible work-around was to set the option CURLOPT_FRESH_CONNECT
(or CURLOPT_FORBID_REUSE with 7.16.1) to a non-zero value. This caused
the conn
structure to be created afresh.
Extra-info:
On of the web-server I am testing against has some issue because of
which it generates the same nonce value for a particular url. So if I
configure a right of set creadentials first time and a wrong set of
credentials in step 5 then I am able to successfully download the
file. (Though this issue is a bigger security concern for the
Web-server in dealing with replay attacks).
Regards,
Achint
Received on 2007-02-16