http_digest: Moved challenge decoding into SASL module

This commit is contained in:
Steve Holme
2014-11-05 14:33:26 +00:00
parent 25264131e2
commit 7e6d51a73c
3 changed files with 220 additions and 188 deletions

View File

@@ -42,77 +42,6 @@
/* The last #include file should be: */
#include "memdebug.h"
#define MAX_VALUE_LENGTH 256
#define MAX_CONTENT_LENGTH 1024
/*
* Return 0 on success and then the buffers are filled in fine.
*
* Non-zero means failure to parse.
*/
static int get_pair(const char *str, char *value, char *content,
const char **endptr)
{
int c;
bool starts_with_quote = FALSE;
bool escape = FALSE;
for(c=MAX_VALUE_LENGTH-1; (*str && (*str != '=') && c--); )
*value++ = *str++;
*value=0;
if('=' != *str++)
/* eek, no match */
return 1;
if('\"' == *str) {
/* this starts with a quote so it must end with one as well! */
str++;
starts_with_quote = TRUE;
}
for(c=MAX_CONTENT_LENGTH-1; *str && c--; str++) {
switch(*str) {
case '\\':
if(!escape) {
/* possibly the start of an escaped quote */
escape = TRUE;
*content++ = '\\'; /* even though this is an escape character, we still
store it as-is in the target buffer */
continue;
}
break;
case ',':
if(!starts_with_quote) {
/* this signals the end of the content if we didn't get a starting
quote and then we do "sloppy" parsing */
c=0; /* the end */
continue;
}
break;
case '\r':
case '\n':
/* end of string */
c=0;
continue;
case '\"':
if(!escape && starts_with_quote) {
/* end of string */
c=0;
continue;
}
break;
}
escape = FALSE;
*content++ = *str;
}
*content=0;
*endptr = str;
return 0; /* all is fine! */
}
/* Test example headers:
WWW-Authenticate: Digest realm="testrealm", nonce="1053604598"
@@ -125,12 +54,7 @@ CURLcode Curl_input_digest(struct connectdata *conn,
const char *header) /* rest of the *-authenticate:
header */
{
char *token = NULL;
char *tmp = NULL;
bool foundAuth = FALSE;
bool foundAuthInt = FALSE;
struct SessionHandle *data=conn->data;
bool before = FALSE; /* got a nonce before */
struct digestdata *d;
if(proxy) {
@@ -140,118 +64,14 @@ CURLcode Curl_input_digest(struct connectdata *conn,
d = &data->state.digest;
}
if(checkprefix("Digest", header)) {
header += strlen("Digest");
/* If we already have received a nonce, keep that in mind */
if(d->nonce)
before = TRUE;
/* clear off any former leftovers and init to defaults */
Curl_sasl_digest_cleanup(d);
for(;;) {
char value[MAX_VALUE_LENGTH];
char content[MAX_CONTENT_LENGTH];
while(*header && ISSPACE(*header))
header++;
/* extract a value=content pair */
if(!get_pair(header, value, content, &header)) {
if(Curl_raw_equal(value, "nonce")) {
d->nonce = strdup(content);
if(!d->nonce)
return CURLE_OUT_OF_MEMORY;
}
else if(Curl_raw_equal(value, "stale")) {
if(Curl_raw_equal(content, "true")) {
d->stale = TRUE;
d->nc = 1; /* we make a new nonce now */
}
}
else if(Curl_raw_equal(value, "realm")) {
d->realm = strdup(content);
if(!d->realm)
return CURLE_OUT_OF_MEMORY;
}
else if(Curl_raw_equal(value, "opaque")) {
d->opaque = strdup(content);
if(!d->opaque)
return CURLE_OUT_OF_MEMORY;
}
else if(Curl_raw_equal(value, "qop")) {
char *tok_buf;
/* tokenize the list and choose auth if possible, use a temporary
clone of the buffer since strtok_r() ruins it */
tmp = strdup(content);
if(!tmp)
return CURLE_OUT_OF_MEMORY;
token = strtok_r(tmp, ",", &tok_buf);
while(token != NULL) {
if(Curl_raw_equal(token, "auth")) {
foundAuth = TRUE;
}
else if(Curl_raw_equal(token, "auth-int")) {
foundAuthInt = TRUE;
}
token = strtok_r(NULL, ",", &tok_buf);
}
free(tmp);
/*select only auth o auth-int. Otherwise, ignore*/
if(foundAuth) {
d->qop = strdup("auth");
if(!d->qop)
return CURLE_OUT_OF_MEMORY;
}
else if(foundAuthInt) {
d->qop = strdup("auth-int");
if(!d->qop)
return CURLE_OUT_OF_MEMORY;
}
}
else if(Curl_raw_equal(value, "algorithm")) {
d->algorithm = strdup(content);
if(!d->algorithm)
return CURLE_OUT_OF_MEMORY;
if(Curl_raw_equal(content, "MD5-sess"))
d->algo = CURLDIGESTALGO_MD5SESS;
else if(Curl_raw_equal(content, "MD5"))
d->algo = CURLDIGESTALGO_MD5;
else
return CURLE_BAD_CONTENT_ENCODING;
}
else {
/* unknown specifier, ignore it! */
}
}
else
break; /* we're done here */
/* pass all additional spaces here */
while(*header && ISSPACE(*header))
header++;
if(',' == *header)
/* allow the list to be comma-separated */
header++;
}
/* We had a nonce since before, and we got another one now without
'stale=true'. This means we provided bad credentials in the previous
request */
if(before && !d->stale)
return CURLE_BAD_CONTENT_ENCODING;
/* We got this header without a nonce, that's a bad Digest line! */
if(!d->nonce)
return CURLE_BAD_CONTENT_ENCODING;
}
else
/* else not a digest, get out */
if(!checkprefix("Digest", header))
return CURLE_BAD_CONTENT_ENCODING;
return CURLE_OK;
header += strlen("Digest");
while(*header && ISSPACE(*header))
header++;
return Curl_sasl_decode_digest_http_message(header, d);
}
/* convert md5 chunk to RFC2617 (section 3.1.3) -suitable ascii string*/