aboutsummaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorDaniel Stenberg <daniel@haxx.se>2003-06-26 11:30:26 +0000
committerDaniel Stenberg <daniel@haxx.se>2003-06-26 11:30:26 +0000
commit2d3734b8b5c7ea1640afaca21aee453b9e74f4c5 (patch)
treeaf37b79923da7ea540f377c740d691dab827ca45 /lib
parented908b7f89eb55fc5163d821feab6adc6b0dfa1b (diff)
Adjusted to work properly with the new authentication stuff
Added code to deal with white spaces in relocation headers.
Diffstat (limited to 'lib')
-rw-r--r--lib/transfer.c258
1 files changed, 201 insertions, 57 deletions
diff --git a/lib/transfer.c b/lib/transfer.c
index 771ec53c6..e98e1e01b 100644
--- a/lib/transfer.c
+++ b/lib/transfer.c
@@ -97,15 +97,13 @@
#include "ssluse.h"
#include "http_digest.h"
#include "http_ntlm.h"
-#ifdef GSSAPI
#include "http_negotiate.h"
-#endif
#define _MPRINTF_REPLACE /* use our functions only */
#include <curl/mprintf.h>
/* The last #include file should be: */
-#ifdef MALLOCDEBUG
+#ifdef CURLDEBUG
#include "memdebug.h"
#endif
@@ -368,6 +366,7 @@ CURLcode Curl_readwrite(struct connectdata *conn,
k->hbufp += full_length;
k->hbuflen += full_length;
*k->hbufp = 0;
+ k->end_ptr = k->hbufp;
k->p = data->state.headerbuff;
@@ -724,53 +723,81 @@ CURLcode Curl_readwrite(struct connectdata *conn,
if(data->set.get_filetime)
data->info.filetime = k->timeofdoc;
}
+ else if(checkprefix("WWW-Authenticate:", k->p) &&
+ (401 == k->httpcode)) {
+ /*
+ * This page requires authentication
+ */
+ char *start = k->p+strlen("WWW-Authenticate:");
+
+ /* pass all white spaces */
+ while(*start && isspace((int)*start))
+ start++;
+
#ifdef GSSAPI
- else if (Curl_compareheader(k->p, "WWW-Authenticate:",
- "GSS-Negotiate") &&
- (401 == k->httpcode) &&
- (data->set.httpauth == CURLAUTH_GSSNEGOTIATE)) {
- int neg;
-
- neg = Curl_input_negotiate(conn,
- k->p+strlen("WWW-Authenticate:"));
- if (neg == 0)
- /* simulate redirection to make curl send the request again */
- conn->newurl = strdup(data->change.url);
- }
+ if (checkprefix("GSS-Negotiate", start)) {
+ if(data->state.authwant == CURLAUTH_GSSNEGOTIATE) {
+ /* if exactly this is wanted, go */
+ int neg = Curl_input_negotiate(conn, start);
+ if (neg == 0)
+ conn->newurl = strdup(data->change.url);
+ }
+ else
+ if(data->state.authwant & CURLAUTH_GSSNEGOTIATE)
+ data->state.authavail |= CURLAUTH_GSSNEGOTIATE;
+ }
+ else
#endif
#ifdef USE_SSLEAY
/* NTLM support requires the SSL crypto libs */
- else if(Curl_compareheader(k->p,
- "WWW-Authenticate:", "NTLM") &&
- (401 == k->httpcode) &&
- (data->set.httpauth == CURLAUTH_NTLM)
- /* NTLM authentication is activated */) {
- CURLntlm ntlm =
- Curl_input_ntlm(conn, k->p+strlen("WWW-Authenticate:"));
-
- if(CURLNTLM_BAD != ntlm)
- conn->newurl = strdup(data->change.url); /* clone string */
+ if(checkprefix("NTLM", start)) {
+ if(data->state.authwant == CURLAUTH_NTLM) {
+ /* NTLM authentication is activated */
+ CURLntlm ntlm =
+ Curl_input_ntlm(conn, start);
+
+ if(CURLNTLM_BAD != ntlm)
+ conn->newurl = strdup(data->change.url); /* clone string */
+ else
+ infof(data, "Authentication problem. Ignoring this.\n");
+ }
+ else
+ if(data->state.authwant & CURLAUTH_NTLM)
+ data->state.authavail |= CURLAUTH_NTLM;
+ }
else
- infof(data, "Authentication problem. Ignoring this.\n");
- }
#endif
- else if(Curl_compareheader(k->p,
- "WWW-Authenticate:", "Digest") &&
- (401 == k->httpcode) &&
- (data->set.httpauth == CURLAUTH_DIGEST)
- /* Digest authentication is activated */) {
- CURLdigest dig = CURLDIGEST_BAD;
-
- if(data->state.digest.nonce)
- infof(data, "Authentication problem. Ignoring this.\n");
- else
- dig = Curl_input_digest(conn,
- k->p+strlen("WWW-Authenticate:"));
-
- if(CURLDIGEST_FINE == dig)
- /* We act on it. Store our new url, which happens to be
- the same one we already use! */
- conn->newurl = strdup(data->change.url); /* clone string */
+ if(checkprefix("Digest", start)) {
+ if(data->state.authwant == CURLAUTH_DIGEST) {
+ /* Digest authentication is activated */
+ CURLdigest dig = CURLDIGEST_BAD;
+
+ if(data->state.digest.nonce)
+ infof(data, "Authentication problem. Ignoring this.\n");
+ else
+ dig = Curl_input_digest(conn, start);
+
+ if(CURLDIGEST_FINE == dig)
+ /* We act on it. Store our new url, which happens to be
+ the same one we already use! */
+ conn->newurl = strdup(data->change.url); /* clone string */
+ }
+ else
+ if(data->state.authwant & CURLAUTH_DIGEST) {
+ /* We don't know if Digest is what we're gonna use, but we
+ call this function anyway to store the digest data that
+ is provided on this line, to skip the extra round-trip
+ we need to do otherwise. We must sure to free this
+ data! */
+ Curl_input_digest(conn, start);
+ data->state.authavail |= CURLAUTH_DIGEST;
+ }
+ }
+ else if(checkprefix("Basic", start)) {
+ if(data->state.authwant & CURLAUTH_BASIC) {
+ data->state.authavail |= CURLAUTH_BASIC;
+ }
+ }
}
else if ((k->httpcode >= 300 && k->httpcode < 400) &&
checkprefix("Location:", k->p)) {
@@ -786,11 +813,17 @@ CURLcode Curl_readwrite(struct connectdata *conn,
white spaces after the "Location:" keyword. */
while(*start && isspace((int)*start ))
start++;
- ptr = start; /* start scanning here */
+
+ /* Scan through the string from the end to find the last
+ non-space. k->end_ptr points to the actual terminating zero
+ letter, move pointer one letter back and start from
+ there. This logic strips off trailing whitespace, but keeps
+ any embedded whitespace. */
+ ptr = k->end_ptr-1;
+ while((ptr>=start) && isspace((int)*ptr))
+ ptr--;
+ ptr++;
- /* scan through the string to find the end */
- while(*ptr && !isspace((int)*ptr))
- ptr++;
backup = *ptr; /* store the ending letter */
if(ptr != start) {
*ptr = '\0'; /* zero terminate */
@@ -852,6 +885,25 @@ CURLcode Curl_readwrite(struct connectdata *conn,
write a piece of the body */
if(conn->protocol&PROT_HTTP) {
/* HTTP-only checks */
+
+ if(data->state.authavail) {
+ if(data->state.authavail & CURLAUTH_GSSNEGOTIATE)
+ data->state.authwant = CURLAUTH_GSSNEGOTIATE;
+ else if(data->state.authavail & CURLAUTH_DIGEST)
+ data->state.authwant = CURLAUTH_DIGEST;
+ else if(data->state.authavail & CURLAUTH_NTLM)
+ data->state.authwant = CURLAUTH_NTLM;
+ else if(data->state.authavail & CURLAUTH_BASIC)
+ data->state.authwant = CURLAUTH_BASIC;
+ else
+ data->state.authwant = CURLAUTH_NONE; /* none */
+
+ if(data->state.authwant)
+ conn->newurl = strdup(data->change.url); /* clone string */
+
+ data->state.authavail = CURLAUTH_NONE; /* clear it here */
+ }
+
if (conn->newurl) {
if(conn->bits.close) {
/* Abort after the headers if "follow Location" is set
@@ -1442,6 +1494,10 @@ CURLcode Curl_pretransfer(struct SessionHandle *data)
data->state.this_is_a_follow = FALSE; /* reset this */
data->state.errorbuf = FALSE; /* no error has occurred */
+ /* set preferred authentication, default to basic */
+ data->state.authwant = data->set.httpauth?data->set.httpauth:CURLAUTH_BASIC;
+ data->state.authavail = CURLAUTH_NONE; /* nothing so far */
+
/* If there was a list of cookie files to read and we haven't done it before,
do it now! */
if(data->change.cookielist) {
@@ -1488,6 +1544,60 @@ CURLcode Curl_posttransfer(struct SessionHandle *data)
return CURLE_OK;
}
+static int strlen_url(char *url)
+{
+ char *ptr;
+ int newlen=0;
+ bool left=TRUE; /* left side of the ? */
+
+ for(ptr=url; *ptr; ptr++) {
+ switch(*ptr) {
+ case '?':
+ left=FALSE;
+ default:
+ newlen++;
+ break;
+ case ' ':
+ if(left)
+ newlen+=3;
+ else
+ newlen++;
+ break;
+ }
+ }
+ return newlen;
+}
+
+static void strcpy_url(char *output, char *url)
+{
+ /* we must add this with whitespace-replacing */
+ bool left=TRUE;
+ char *iptr;
+ char *optr = output;
+ for(iptr = url; /* read from here */
+ *iptr; /* until zero byte */
+ iptr++) {
+ switch(*iptr) {
+ case '?':
+ left=FALSE;
+ default:
+ *optr++=*iptr;
+ break;
+ case ' ':
+ if(left) {
+ *optr++='%'; /* add a '%' */
+ *optr++='2'; /* add a '2' */
+ *optr++='0'; /* add a '0' */
+ }
+ else
+ *optr++='+'; /* add a '+' here */
+ break;
+ }
+ }
+ *optr=0; /* zero terminate output buffer */
+
+}
+
CURLcode Curl_follow(struct SessionHandle *data,
char *newurl) /* this 'newurl' is the Location: string,
and it must be malloc()ed before passed
@@ -1496,6 +1606,8 @@ CURLcode Curl_follow(struct SessionHandle *data,
/* Location: redirect */
char prot[16]; /* URL protocol string storage */
char letter; /* used for a silly sscanf */
+ int newlen;
+ char *newest;
if (data->set.maxredirs &&
(data->set.followlocation >= data->set.maxredirs)) {
@@ -1532,9 +1644,9 @@ CURLcode Curl_follow(struct SessionHandle *data,
*/
char *protsep;
char *pathsep;
- char *newest;
char *useurl = newurl;
+ int urllen;
/* we must make our own copy of the URL to play with, as it may
point to read-only data */
@@ -1607,30 +1719,62 @@ CURLcode Curl_follow(struct SessionHandle *data,
*pathsep=0;
}
- newest=(char *)malloc( strlen(url_clone) +
- 1 + /* possible slash */
- strlen(useurl) + 1/* zero byte */);
+ /* If the new part contains a space, this is a mighty stupid redirect
+ but we still make an effort to do "right". To the left of a '?'
+ letter we replace each space with %20 while it is replaced with '+'
+ on the right side of the '?' letter.
+ */
+ newlen = strlen_url(useurl);
+
+ urllen = strlen(url_clone);
+
+ newest=(char *)malloc( urllen + 1 + /* possible slash */
+ newlen + 1 /* zero byte */);
if(!newest)
return CURLE_OUT_OF_MEMORY; /* go out from this */
- sprintf(newest, "%s%s%s", url_clone,
- (('/' == useurl[0]) || (protsep && !*protsep))?"":"/",
- useurl);
+ /* copy over the root url part */
+ memcpy(newest, url_clone, urllen);
+
+ /* check if we need to append a slash */
+ if(('/' == useurl[0]) || (protsep && !*protsep))
+ ;
+ else
+ newest[urllen++]='/';
+
+ /* then append the new piece on the right side */
+ strcpy_url(&newest[urllen], useurl);
+
free(newurl); /* newurl is the allocated pointer */
free(url_clone);
newurl = newest;
}
- else
+ else {
/* This is an absolute URL, don't allow the custom port number */
data->state.allow_port = FALSE;
+ if(strchr(newurl, ' ')) {
+ /* This new URL contains at least one space, this is a mighty stupid
+ redirect but we still make an effort to do "right". */
+ newlen = strlen_url(newurl);
+
+ newest = malloc(newlen+1); /* get memory for this */
+ if(newest) {
+ strcpy_url(newest, newurl); /* create a space-free URL */
+
+ free(newurl); /* that was no good */
+ newurl = newest; /* use this instead now */
+ }
+ }
+
+ }
+
if(data->change.url_alloc)
free(data->change.url);
else
data->change.url_alloc = TRUE; /* the URL is allocated */
- /* TBD: set the URL with curl_setopt() */
data->change.url = newurl;
newurl = NULL; /* don't free! */