digest: fix OWS and escaped quote handling
No binary (build failed)
—
(log yok)
| @@ -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; | |
| @@ -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); | |
| @@ -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, ',')) | |
| @@ -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 \ | |
| @@ -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 | |
| @@ -0,0 +1,98 @@ | |
| + | <?xml version="1.0" encoding="US-ASCII"?> |
| + | <testcase> |
| + | <info> |
| + | <keywords> |
| + | HTTP |
| + | HTTP GET |
| + | HTTP Digest auth |
| + | </keywords> |
| + | </info> |
| + | |
| + | # Server-side |
| + | <reply> |
| + | <data1 crlf="headers"> |
| + | 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 |
| + | </data1> |
| + | |
| + | <data1001 crlf="headers"> |
| + | 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! |
| + | </data1001> |
| + | |
| + | <data3 crlf="headers"> |
| + | 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 |
| + | </data3> |
| + | |
| + | <data1003 crlf="headers"> |
| + | 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! |
| + | </data1003> |
| + | </reply> |
| + | |
| + | # Client-side |
| + | <client> |
| + | <server> |
| + | http |
| + | </server> |
| + | <features> |
| + | !SSPI |
| + | crypto |
| + | digest |
| + | </features> |
| + | <name> |
| + | HTTP Digest auth with OWS and escaped quotes |
| + | </name> |
| + | <command> |
| + | http://%HOSTIP:%HTTPPORT/%TESTNUMBER0001 -u testuser:testpass --digest --next |
| + | http://%HOSTIP:%HTTPPORT/%TESTNUMBER0003 -u testuser:testpass --digest |
| + | </command> |
| + | </client> |
| + | |
| + | # Verify data after the test has been "shot" |
| + | <verify> |
| + | <protocol crlf="headers"> |
| + | 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: */* |
| + | |
| + | </protocol> |
| + | </verify> |
| + | </testcase> |