diff --git a/lib/curlx/strparse.c b/lib/curlx/strparse.c index aa78921f50..f11b58b7ee 100644 --- a/lib/curlx/strparse.c +++ b/lib/curlx/strparse.c @@ -89,7 +89,7 @@ int curlx_str_untilnl(const char **linep, struct Curl_str *out, return STRE_OK; } -/* Get a "quoted" word. No escaping possible. +/* Get a "quoted" word. Escaped quotes are supported. return non-zero on error */ int curlx_str_quotedword(const char **linep, struct Curl_str *out, const size_t max) @@ -103,6 +103,11 @@ int curlx_str_quotedword(const char **linep, struct Curl_str *out, return STRE_BEGQUOTE; s++; while(*s && (*s != '\"')) { + if(*s == '\\' && s[1]) { + s++; + if(++len > max) + return STRE_BIG; + } s++; if(++len > max) return STRE_BIG; diff --git a/lib/curlx/strparse.h b/lib/curlx/strparse.h index 27fea2957e..ae8fd19d95 100644 --- a/lib/curlx/strparse.h +++ b/lib/curlx/strparse.h @@ -62,7 +62,7 @@ int curlx_str_until(const char **linep, struct Curl_str *out, const size_t max, int curlx_str_untilnl(const char **linep, struct Curl_str *out, const size_t max); -/* Get a "quoted" word. No escaping possible. +/* Get a "quoted" word. Escaped quotes are supported. return non-zero on error */ int curlx_str_quotedword(const char **linep, struct Curl_str *out, const size_t max); diff --git a/lib/vauth/digest.c b/lib/vauth/digest.c index 40e8873913..a1fd248617 100644 --- a/lib/vauth/digest.c +++ b/lib/vauth/digest.c @@ -192,6 +192,9 @@ static bool auth_digest_get_key_value(const char *chlg, const char *key, do { struct Curl_str data; struct Curl_str name; + + curlx_str_passblanks(&chlg); + if(!curlx_str_until(&chlg, &name, 64, '=') && !curlx_str_single(&chlg, '=')) { /* this is the key, get the value, possibly quoted */ @@ -204,11 +207,22 @@ static bool auth_digest_get_key_value(const char *chlg, const char *key, if(curlx_str_cmp(&name, key)) { /* if this is our key, return the value */ - if(curlx_strlen(&data) >= buflen) + size_t len = curlx_strlen(&data); + const char *src = curlx_str(&data); + size_t i; + size_t outlen = 0; + + if(len >= buflen) /* does not fit */ return FALSE; - memcpy(buf, curlx_str(&data), curlx_strlen(&data)); - buf[curlx_strlen(&data)] = 0; + + for(i = 0; i < len; i++) { + if(src[i] == '\\' && i + 1 < len) { + i++; /* skip backslash */ + } + buf[outlen++] = src[i]; + } + buf[outlen] = 0; return TRUE; } if(curlx_str_single(&chlg, ',')) diff --git a/tests/data/Makefile.am b/tests/data/Makefile.am index 74c9aa8f37..de75499a18 100644 --- a/tests/data/Makefile.am +++ b/tests/data/Makefile.am @@ -252,7 +252,7 @@ test2056 test2057 test2058 test2059 test2060 test2061 test2062 test2063 \ test2064 test2065 test2066 test2067 test2068 test2069 test2070 test2071 \ test2072 test2073 test2074 test2075 test2076 test2077 test2078 test2079 \ test2080 test2081 test2082 test2083 test2084 test2085 test2086 test2087 \ -test2088 test2089 test2090 \ +test2088 test2089 test2090 test2091 \ test2100 test2101 test2102 test2103 test2104 \ \ test2200 test2201 test2202 test2203 test2204 test2205 \ diff --git a/tests/data/test1664 b/tests/data/test1664 index a1a2027427..42c4982d57 100644 --- a/tests/data/test1664 +++ b/tests/data/test1664 @@ -49,7 +49,7 @@ curlx_str_quotedword 5: (" "word"") 3, "" [0], line 0 6: (""perfect"") 0, "perfect" [7], line 9 7: (""p r e t"") 0, "p r e t" [7], line 9 -8: (""perfec\"") 0, "perfec\" [7], line 9 +8: (""perfec\"") 1, "" [0], line 0 9: ("""") 0, "" [0], line 2 10: ("") 3, "" [0], line 0 11: (""longerth"") 1, "" [0], line 0 diff --git a/tests/data/test2091 b/tests/data/test2091 new file mode 100644 index 0000000000..33ef0b24ff --- /dev/null +++ b/tests/data/test2091 @@ -0,0 +1,98 @@ + + + + +HTTP +HTTP GET +HTTP Digest auth + + + +# Server-side + + +HTTP/1.1 401 Authorization Required swsclose +Server: Apache/1.3.27 (Darwin) PHP/4.1.2 +WWW-Authenticate: Digest realm="OWS Realm", nonce="1053604145" +Content-Type: text/html; charset=iso-8859-1 +Content-Length: 26 + +This is not the real page + + + +HTTP/1.1 200 OK +Server: Apache/1.3.27 (Darwin) PHP/4.1.2 +Content-Type: text/html; charset=iso-8859-1 +Content-Length: 23 + +This IS the real page! + + + +HTTP/1.1 401 Authorization Required swsclose +Server: Apache/1.3.27 (Darwin) PHP/4.1.2 +WWW-Authenticate: Digest realm="My \"Cool\" Realm", nonce="1053604146" +Content-Type: text/html; charset=iso-8859-1 +Content-Length: 26 + +This is not the real page + + + +HTTP/1.1 200 OK +Server: Apache/1.3.27 (Darwin) PHP/4.1.2 +Content-Type: text/html; charset=iso-8859-1 +Content-Length: 23 + +This IS the real page! + + + +# Client-side + + +http + + +!SSPI +crypto +digest + + +HTTP Digest auth with OWS and escaped quotes + + +http://%HOSTIP:%HTTPPORT/%TESTNUMBER0001 -u testuser:testpass --digest --next +http://%HOSTIP:%HTTPPORT/%TESTNUMBER0003 -u testuser:testpass --digest + + + +# Verify data after the test has been "shot" + + +GET /%TESTNUMBER0001 HTTP/1.1 +Host: %HOSTIP:%HTTPPORT +User-Agent: curl/%VERSION +Accept: */* + +GET /%TESTNUMBER0001 HTTP/1.1 +Host: %HOSTIP:%HTTPPORT +Authorization: Digest username="testuser", realm="OWS Realm", nonce="1053604145", uri="/%TESTNUMBER0001", response="b6c8f707f7781c272e79489771185713" +User-Agent: curl/%VERSION +Accept: */* + +GET /%TESTNUMBER0003 HTTP/1.1 +Host: %HOSTIP:%HTTPPORT +User-Agent: curl/%VERSION +Accept: */* + +GET /%TESTNUMBER0003 HTTP/1.1 +Host: %HOSTIP:%HTTPPORT +Authorization: Digest username="testuser", realm="My \"Cool\" Realm", nonce="1053604146", uri="/%TESTNUMBER0003", response="f10c1586b83b6e5927fef54748f88d36" +User-Agent: curl/%VERSION +Accept: */* + + + +