1*6236dae4SAndroid Build Coastguard Worker /***************************************************************************
2*6236dae4SAndroid Build Coastguard Worker * _ _ ____ _
3*6236dae4SAndroid Build Coastguard Worker * Project ___| | | | _ \| |
4*6236dae4SAndroid Build Coastguard Worker * / __| | | | |_) | |
5*6236dae4SAndroid Build Coastguard Worker * | (__| |_| | _ <| |___
6*6236dae4SAndroid Build Coastguard Worker * \___|\___/|_| \_\_____|
7*6236dae4SAndroid Build Coastguard Worker *
8*6236dae4SAndroid Build Coastguard Worker * Copyright (C) Daniel Stenberg, <[email protected]>, et al.
9*6236dae4SAndroid Build Coastguard Worker *
10*6236dae4SAndroid Build Coastguard Worker * This software is licensed as described in the file COPYING, which
11*6236dae4SAndroid Build Coastguard Worker * you should have received as part of this distribution. The terms
12*6236dae4SAndroid Build Coastguard Worker * are also available at https://curl.se/docs/copyright.html.
13*6236dae4SAndroid Build Coastguard Worker *
14*6236dae4SAndroid Build Coastguard Worker * You may opt to use, copy, modify, merge, publish, distribute and/or sell
15*6236dae4SAndroid Build Coastguard Worker * copies of the Software, and permit persons to whom the Software is
16*6236dae4SAndroid Build Coastguard Worker * furnished to do so, under the terms of the COPYING file.
17*6236dae4SAndroid Build Coastguard Worker *
18*6236dae4SAndroid Build Coastguard Worker * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
19*6236dae4SAndroid Build Coastguard Worker * KIND, either express or implied.
20*6236dae4SAndroid Build Coastguard Worker *
21*6236dae4SAndroid Build Coastguard Worker * SPDX-License-Identifier: curl
22*6236dae4SAndroid Build Coastguard Worker *
23*6236dae4SAndroid Build Coastguard Worker * RFC2831 DIGEST-MD5 authentication
24*6236dae4SAndroid Build Coastguard Worker * RFC7616 DIGEST-SHA256, DIGEST-SHA512-256 authentication
25*6236dae4SAndroid Build Coastguard Worker *
26*6236dae4SAndroid Build Coastguard Worker ***************************************************************************/
27*6236dae4SAndroid Build Coastguard Worker
28*6236dae4SAndroid Build Coastguard Worker #include "curl_setup.h"
29*6236dae4SAndroid Build Coastguard Worker
30*6236dae4SAndroid Build Coastguard Worker #ifndef CURL_DISABLE_DIGEST_AUTH
31*6236dae4SAndroid Build Coastguard Worker
32*6236dae4SAndroid Build Coastguard Worker #include <curl/curl.h>
33*6236dae4SAndroid Build Coastguard Worker
34*6236dae4SAndroid Build Coastguard Worker #include "vauth/vauth.h"
35*6236dae4SAndroid Build Coastguard Worker #include "vauth/digest.h"
36*6236dae4SAndroid Build Coastguard Worker #include "urldata.h"
37*6236dae4SAndroid Build Coastguard Worker #include "curl_base64.h"
38*6236dae4SAndroid Build Coastguard Worker #include "curl_hmac.h"
39*6236dae4SAndroid Build Coastguard Worker #include "curl_md5.h"
40*6236dae4SAndroid Build Coastguard Worker #include "curl_sha256.h"
41*6236dae4SAndroid Build Coastguard Worker #include "curl_sha512_256.h"
42*6236dae4SAndroid Build Coastguard Worker #include "vtls/vtls.h"
43*6236dae4SAndroid Build Coastguard Worker #include "warnless.h"
44*6236dae4SAndroid Build Coastguard Worker #include "strtok.h"
45*6236dae4SAndroid Build Coastguard Worker #include "strcase.h"
46*6236dae4SAndroid Build Coastguard Worker #include "curl_printf.h"
47*6236dae4SAndroid Build Coastguard Worker #include "rand.h"
48*6236dae4SAndroid Build Coastguard Worker
49*6236dae4SAndroid Build Coastguard Worker /* The last #include files should be: */
50*6236dae4SAndroid Build Coastguard Worker #include "curl_memory.h"
51*6236dae4SAndroid Build Coastguard Worker #include "memdebug.h"
52*6236dae4SAndroid Build Coastguard Worker
53*6236dae4SAndroid Build Coastguard Worker #define SESSION_ALGO 1 /* for algos with this bit set */
54*6236dae4SAndroid Build Coastguard Worker
55*6236dae4SAndroid Build Coastguard Worker #define ALGO_MD5 0
56*6236dae4SAndroid Build Coastguard Worker #define ALGO_MD5SESS (ALGO_MD5 | SESSION_ALGO)
57*6236dae4SAndroid Build Coastguard Worker #define ALGO_SHA256 2
58*6236dae4SAndroid Build Coastguard Worker #define ALGO_SHA256SESS (ALGO_SHA256 | SESSION_ALGO)
59*6236dae4SAndroid Build Coastguard Worker #define ALGO_SHA512_256 4
60*6236dae4SAndroid Build Coastguard Worker #define ALGO_SHA512_256SESS (ALGO_SHA512_256 | SESSION_ALGO)
61*6236dae4SAndroid Build Coastguard Worker
62*6236dae4SAndroid Build Coastguard Worker #if !defined(USE_WINDOWS_SSPI)
63*6236dae4SAndroid Build Coastguard Worker #define DIGEST_QOP_VALUE_AUTH (1 << 0)
64*6236dae4SAndroid Build Coastguard Worker #define DIGEST_QOP_VALUE_AUTH_INT (1 << 1)
65*6236dae4SAndroid Build Coastguard Worker #define DIGEST_QOP_VALUE_AUTH_CONF (1 << 2)
66*6236dae4SAndroid Build Coastguard Worker
67*6236dae4SAndroid Build Coastguard Worker #define DIGEST_QOP_VALUE_STRING_AUTH "auth"
68*6236dae4SAndroid Build Coastguard Worker #define DIGEST_QOP_VALUE_STRING_AUTH_INT "auth-int"
69*6236dae4SAndroid Build Coastguard Worker #define DIGEST_QOP_VALUE_STRING_AUTH_CONF "auth-conf"
70*6236dae4SAndroid Build Coastguard Worker #endif
71*6236dae4SAndroid Build Coastguard Worker
Curl_auth_digest_get_pair(const char * str,char * value,char * content,const char ** endptr)72*6236dae4SAndroid Build Coastguard Worker bool Curl_auth_digest_get_pair(const char *str, char *value, char *content,
73*6236dae4SAndroid Build Coastguard Worker const char **endptr)
74*6236dae4SAndroid Build Coastguard Worker {
75*6236dae4SAndroid Build Coastguard Worker int c;
76*6236dae4SAndroid Build Coastguard Worker bool starts_with_quote = FALSE;
77*6236dae4SAndroid Build Coastguard Worker bool escape = FALSE;
78*6236dae4SAndroid Build Coastguard Worker
79*6236dae4SAndroid Build Coastguard Worker for(c = DIGEST_MAX_VALUE_LENGTH - 1; (*str && (*str != '=') && c--);)
80*6236dae4SAndroid Build Coastguard Worker *value++ = *str++;
81*6236dae4SAndroid Build Coastguard Worker *value = 0;
82*6236dae4SAndroid Build Coastguard Worker
83*6236dae4SAndroid Build Coastguard Worker if('=' != *str++)
84*6236dae4SAndroid Build Coastguard Worker /* eek, no match */
85*6236dae4SAndroid Build Coastguard Worker return FALSE;
86*6236dae4SAndroid Build Coastguard Worker
87*6236dae4SAndroid Build Coastguard Worker if('\"' == *str) {
88*6236dae4SAndroid Build Coastguard Worker /* This starts with a quote so it must end with one as well! */
89*6236dae4SAndroid Build Coastguard Worker str++;
90*6236dae4SAndroid Build Coastguard Worker starts_with_quote = TRUE;
91*6236dae4SAndroid Build Coastguard Worker }
92*6236dae4SAndroid Build Coastguard Worker
93*6236dae4SAndroid Build Coastguard Worker for(c = DIGEST_MAX_CONTENT_LENGTH - 1; *str && c--; str++) {
94*6236dae4SAndroid Build Coastguard Worker if(!escape) {
95*6236dae4SAndroid Build Coastguard Worker switch(*str) {
96*6236dae4SAndroid Build Coastguard Worker case '\\':
97*6236dae4SAndroid Build Coastguard Worker if(starts_with_quote) {
98*6236dae4SAndroid Build Coastguard Worker /* the start of an escaped quote */
99*6236dae4SAndroid Build Coastguard Worker escape = TRUE;
100*6236dae4SAndroid Build Coastguard Worker continue;
101*6236dae4SAndroid Build Coastguard Worker }
102*6236dae4SAndroid Build Coastguard Worker break;
103*6236dae4SAndroid Build Coastguard Worker
104*6236dae4SAndroid Build Coastguard Worker case ',':
105*6236dae4SAndroid Build Coastguard Worker if(!starts_with_quote) {
106*6236dae4SAndroid Build Coastguard Worker /* This signals the end of the content if we did not get a starting
107*6236dae4SAndroid Build Coastguard Worker quote and then we do "sloppy" parsing */
108*6236dae4SAndroid Build Coastguard Worker c = 0; /* the end */
109*6236dae4SAndroid Build Coastguard Worker continue;
110*6236dae4SAndroid Build Coastguard Worker }
111*6236dae4SAndroid Build Coastguard Worker break;
112*6236dae4SAndroid Build Coastguard Worker
113*6236dae4SAndroid Build Coastguard Worker case '\r':
114*6236dae4SAndroid Build Coastguard Worker case '\n':
115*6236dae4SAndroid Build Coastguard Worker /* end of string */
116*6236dae4SAndroid Build Coastguard Worker if(starts_with_quote)
117*6236dae4SAndroid Build Coastguard Worker return FALSE; /* No closing quote */
118*6236dae4SAndroid Build Coastguard Worker c = 0;
119*6236dae4SAndroid Build Coastguard Worker continue;
120*6236dae4SAndroid Build Coastguard Worker
121*6236dae4SAndroid Build Coastguard Worker case '\"':
122*6236dae4SAndroid Build Coastguard Worker if(starts_with_quote) {
123*6236dae4SAndroid Build Coastguard Worker /* end of string */
124*6236dae4SAndroid Build Coastguard Worker c = 0;
125*6236dae4SAndroid Build Coastguard Worker continue;
126*6236dae4SAndroid Build Coastguard Worker }
127*6236dae4SAndroid Build Coastguard Worker else
128*6236dae4SAndroid Build Coastguard Worker return FALSE;
129*6236dae4SAndroid Build Coastguard Worker }
130*6236dae4SAndroid Build Coastguard Worker }
131*6236dae4SAndroid Build Coastguard Worker
132*6236dae4SAndroid Build Coastguard Worker escape = FALSE;
133*6236dae4SAndroid Build Coastguard Worker *content++ = *str;
134*6236dae4SAndroid Build Coastguard Worker }
135*6236dae4SAndroid Build Coastguard Worker if(escape)
136*6236dae4SAndroid Build Coastguard Worker return FALSE; /* No character after backslash */
137*6236dae4SAndroid Build Coastguard Worker
138*6236dae4SAndroid Build Coastguard Worker *content = 0;
139*6236dae4SAndroid Build Coastguard Worker *endptr = str;
140*6236dae4SAndroid Build Coastguard Worker
141*6236dae4SAndroid Build Coastguard Worker return TRUE;
142*6236dae4SAndroid Build Coastguard Worker }
143*6236dae4SAndroid Build Coastguard Worker
144*6236dae4SAndroid Build Coastguard Worker #if !defined(USE_WINDOWS_SSPI)
145*6236dae4SAndroid Build Coastguard Worker /* Convert md5 chunk to RFC2617 (section 3.1.3) -suitable ASCII string */
auth_digest_md5_to_ascii(unsigned char * source,unsigned char * dest)146*6236dae4SAndroid Build Coastguard Worker static void auth_digest_md5_to_ascii(unsigned char *source, /* 16 bytes */
147*6236dae4SAndroid Build Coastguard Worker unsigned char *dest) /* 33 bytes */
148*6236dae4SAndroid Build Coastguard Worker {
149*6236dae4SAndroid Build Coastguard Worker int i;
150*6236dae4SAndroid Build Coastguard Worker for(i = 0; i < 16; i++)
151*6236dae4SAndroid Build Coastguard Worker msnprintf((char *) &dest[i * 2], 3, "%02x", source[i]);
152*6236dae4SAndroid Build Coastguard Worker }
153*6236dae4SAndroid Build Coastguard Worker
154*6236dae4SAndroid Build Coastguard Worker /* Convert sha256 or SHA-512/256 chunk to RFC7616 -suitable ASCII string */
auth_digest_sha256_to_ascii(unsigned char * source,unsigned char * dest)155*6236dae4SAndroid Build Coastguard Worker static void auth_digest_sha256_to_ascii(unsigned char *source, /* 32 bytes */
156*6236dae4SAndroid Build Coastguard Worker unsigned char *dest) /* 65 bytes */
157*6236dae4SAndroid Build Coastguard Worker {
158*6236dae4SAndroid Build Coastguard Worker int i;
159*6236dae4SAndroid Build Coastguard Worker for(i = 0; i < 32; i++)
160*6236dae4SAndroid Build Coastguard Worker msnprintf((char *) &dest[i * 2], 3, "%02x", source[i]);
161*6236dae4SAndroid Build Coastguard Worker }
162*6236dae4SAndroid Build Coastguard Worker
163*6236dae4SAndroid Build Coastguard Worker /* Perform quoted-string escaping as described in RFC2616 and its errata */
auth_digest_string_quoted(const char * source)164*6236dae4SAndroid Build Coastguard Worker static char *auth_digest_string_quoted(const char *source)
165*6236dae4SAndroid Build Coastguard Worker {
166*6236dae4SAndroid Build Coastguard Worker char *dest;
167*6236dae4SAndroid Build Coastguard Worker const char *s = source;
168*6236dae4SAndroid Build Coastguard Worker size_t n = 1; /* null terminator */
169*6236dae4SAndroid Build Coastguard Worker
170*6236dae4SAndroid Build Coastguard Worker /* Calculate size needed */
171*6236dae4SAndroid Build Coastguard Worker while(*s) {
172*6236dae4SAndroid Build Coastguard Worker ++n;
173*6236dae4SAndroid Build Coastguard Worker if(*s == '"' || *s == '\\') {
174*6236dae4SAndroid Build Coastguard Worker ++n;
175*6236dae4SAndroid Build Coastguard Worker }
176*6236dae4SAndroid Build Coastguard Worker ++s;
177*6236dae4SAndroid Build Coastguard Worker }
178*6236dae4SAndroid Build Coastguard Worker
179*6236dae4SAndroid Build Coastguard Worker dest = malloc(n);
180*6236dae4SAndroid Build Coastguard Worker if(dest) {
181*6236dae4SAndroid Build Coastguard Worker char *d = dest;
182*6236dae4SAndroid Build Coastguard Worker s = source;
183*6236dae4SAndroid Build Coastguard Worker while(*s) {
184*6236dae4SAndroid Build Coastguard Worker if(*s == '"' || *s == '\\') {
185*6236dae4SAndroid Build Coastguard Worker *d++ = '\\';
186*6236dae4SAndroid Build Coastguard Worker }
187*6236dae4SAndroid Build Coastguard Worker *d++ = *s++;
188*6236dae4SAndroid Build Coastguard Worker }
189*6236dae4SAndroid Build Coastguard Worker *d = '\0';
190*6236dae4SAndroid Build Coastguard Worker }
191*6236dae4SAndroid Build Coastguard Worker
192*6236dae4SAndroid Build Coastguard Worker return dest;
193*6236dae4SAndroid Build Coastguard Worker }
194*6236dae4SAndroid Build Coastguard Worker
195*6236dae4SAndroid Build Coastguard Worker /* Retrieves the value for a corresponding key from the challenge string
196*6236dae4SAndroid Build Coastguard Worker * returns TRUE if the key could be found, FALSE if it does not exists
197*6236dae4SAndroid Build Coastguard Worker */
auth_digest_get_key_value(const char * chlg,const char * key,char * value,size_t max_val_len,char end_char)198*6236dae4SAndroid Build Coastguard Worker static bool auth_digest_get_key_value(const char *chlg,
199*6236dae4SAndroid Build Coastguard Worker const char *key,
200*6236dae4SAndroid Build Coastguard Worker char *value,
201*6236dae4SAndroid Build Coastguard Worker size_t max_val_len,
202*6236dae4SAndroid Build Coastguard Worker char end_char)
203*6236dae4SAndroid Build Coastguard Worker {
204*6236dae4SAndroid Build Coastguard Worker char *find_pos;
205*6236dae4SAndroid Build Coastguard Worker size_t i;
206*6236dae4SAndroid Build Coastguard Worker
207*6236dae4SAndroid Build Coastguard Worker find_pos = strstr(chlg, key);
208*6236dae4SAndroid Build Coastguard Worker if(!find_pos)
209*6236dae4SAndroid Build Coastguard Worker return FALSE;
210*6236dae4SAndroid Build Coastguard Worker
211*6236dae4SAndroid Build Coastguard Worker find_pos += strlen(key);
212*6236dae4SAndroid Build Coastguard Worker
213*6236dae4SAndroid Build Coastguard Worker for(i = 0; *find_pos && *find_pos != end_char && i < max_val_len - 1; ++i)
214*6236dae4SAndroid Build Coastguard Worker value[i] = *find_pos++;
215*6236dae4SAndroid Build Coastguard Worker value[i] = '\0';
216*6236dae4SAndroid Build Coastguard Worker
217*6236dae4SAndroid Build Coastguard Worker return TRUE;
218*6236dae4SAndroid Build Coastguard Worker }
219*6236dae4SAndroid Build Coastguard Worker
auth_digest_get_qop_values(const char * options,int * value)220*6236dae4SAndroid Build Coastguard Worker static CURLcode auth_digest_get_qop_values(const char *options, int *value)
221*6236dae4SAndroid Build Coastguard Worker {
222*6236dae4SAndroid Build Coastguard Worker char *tmp;
223*6236dae4SAndroid Build Coastguard Worker char *token;
224*6236dae4SAndroid Build Coastguard Worker char *tok_buf = NULL;
225*6236dae4SAndroid Build Coastguard Worker
226*6236dae4SAndroid Build Coastguard Worker /* Initialise the output */
227*6236dae4SAndroid Build Coastguard Worker *value = 0;
228*6236dae4SAndroid Build Coastguard Worker
229*6236dae4SAndroid Build Coastguard Worker /* Tokenise the list of qop values. Use a temporary clone of the buffer since
230*6236dae4SAndroid Build Coastguard Worker strtok_r() ruins it. */
231*6236dae4SAndroid Build Coastguard Worker tmp = strdup(options);
232*6236dae4SAndroid Build Coastguard Worker if(!tmp)
233*6236dae4SAndroid Build Coastguard Worker return CURLE_OUT_OF_MEMORY;
234*6236dae4SAndroid Build Coastguard Worker
235*6236dae4SAndroid Build Coastguard Worker token = strtok_r(tmp, ",", &tok_buf);
236*6236dae4SAndroid Build Coastguard Worker while(token) {
237*6236dae4SAndroid Build Coastguard Worker if(strcasecompare(token, DIGEST_QOP_VALUE_STRING_AUTH))
238*6236dae4SAndroid Build Coastguard Worker *value |= DIGEST_QOP_VALUE_AUTH;
239*6236dae4SAndroid Build Coastguard Worker else if(strcasecompare(token, DIGEST_QOP_VALUE_STRING_AUTH_INT))
240*6236dae4SAndroid Build Coastguard Worker *value |= DIGEST_QOP_VALUE_AUTH_INT;
241*6236dae4SAndroid Build Coastguard Worker else if(strcasecompare(token, DIGEST_QOP_VALUE_STRING_AUTH_CONF))
242*6236dae4SAndroid Build Coastguard Worker *value |= DIGEST_QOP_VALUE_AUTH_CONF;
243*6236dae4SAndroid Build Coastguard Worker
244*6236dae4SAndroid Build Coastguard Worker token = strtok_r(NULL, ",", &tok_buf);
245*6236dae4SAndroid Build Coastguard Worker }
246*6236dae4SAndroid Build Coastguard Worker
247*6236dae4SAndroid Build Coastguard Worker free(tmp);
248*6236dae4SAndroid Build Coastguard Worker
249*6236dae4SAndroid Build Coastguard Worker return CURLE_OK;
250*6236dae4SAndroid Build Coastguard Worker }
251*6236dae4SAndroid Build Coastguard Worker
252*6236dae4SAndroid Build Coastguard Worker /*
253*6236dae4SAndroid Build Coastguard Worker * auth_decode_digest_md5_message()
254*6236dae4SAndroid Build Coastguard Worker *
255*6236dae4SAndroid Build Coastguard Worker * This is used internally to decode an already encoded DIGEST-MD5 challenge
256*6236dae4SAndroid Build Coastguard Worker * message into the separate attributes.
257*6236dae4SAndroid Build Coastguard Worker *
258*6236dae4SAndroid Build Coastguard Worker * Parameters:
259*6236dae4SAndroid Build Coastguard Worker *
260*6236dae4SAndroid Build Coastguard Worker * chlgref [in] - The challenge message.
261*6236dae4SAndroid Build Coastguard Worker * nonce [in/out] - The buffer where the nonce will be stored.
262*6236dae4SAndroid Build Coastguard Worker * nlen [in] - The length of the nonce buffer.
263*6236dae4SAndroid Build Coastguard Worker * realm [in/out] - The buffer where the realm will be stored.
264*6236dae4SAndroid Build Coastguard Worker * rlen [in] - The length of the realm buffer.
265*6236dae4SAndroid Build Coastguard Worker * alg [in/out] - The buffer where the algorithm will be stored.
266*6236dae4SAndroid Build Coastguard Worker * alen [in] - The length of the algorithm buffer.
267*6236dae4SAndroid Build Coastguard Worker * qop [in/out] - The buffer where the qop-options will be stored.
268*6236dae4SAndroid Build Coastguard Worker * qlen [in] - The length of the qop buffer.
269*6236dae4SAndroid Build Coastguard Worker *
270*6236dae4SAndroid Build Coastguard Worker * Returns CURLE_OK on success.
271*6236dae4SAndroid Build Coastguard Worker */
auth_decode_digest_md5_message(const struct bufref * chlgref,char * nonce,size_t nlen,char * realm,size_t rlen,char * alg,size_t alen,char * qop,size_t qlen)272*6236dae4SAndroid Build Coastguard Worker static CURLcode auth_decode_digest_md5_message(const struct bufref *chlgref,
273*6236dae4SAndroid Build Coastguard Worker char *nonce, size_t nlen,
274*6236dae4SAndroid Build Coastguard Worker char *realm, size_t rlen,
275*6236dae4SAndroid Build Coastguard Worker char *alg, size_t alen,
276*6236dae4SAndroid Build Coastguard Worker char *qop, size_t qlen)
277*6236dae4SAndroid Build Coastguard Worker {
278*6236dae4SAndroid Build Coastguard Worker const char *chlg = (const char *) Curl_bufref_ptr(chlgref);
279*6236dae4SAndroid Build Coastguard Worker
280*6236dae4SAndroid Build Coastguard Worker /* Ensure we have a valid challenge message */
281*6236dae4SAndroid Build Coastguard Worker if(!Curl_bufref_len(chlgref))
282*6236dae4SAndroid Build Coastguard Worker return CURLE_BAD_CONTENT_ENCODING;
283*6236dae4SAndroid Build Coastguard Worker
284*6236dae4SAndroid Build Coastguard Worker /* Retrieve nonce string from the challenge */
285*6236dae4SAndroid Build Coastguard Worker if(!auth_digest_get_key_value(chlg, "nonce=\"", nonce, nlen, '\"'))
286*6236dae4SAndroid Build Coastguard Worker return CURLE_BAD_CONTENT_ENCODING;
287*6236dae4SAndroid Build Coastguard Worker
288*6236dae4SAndroid Build Coastguard Worker /* Retrieve realm string from the challenge */
289*6236dae4SAndroid Build Coastguard Worker if(!auth_digest_get_key_value(chlg, "realm=\"", realm, rlen, '\"')) {
290*6236dae4SAndroid Build Coastguard Worker /* Challenge does not have a realm, set empty string [RFC2831] page 6 */
291*6236dae4SAndroid Build Coastguard Worker *realm = '\0';
292*6236dae4SAndroid Build Coastguard Worker }
293*6236dae4SAndroid Build Coastguard Worker
294*6236dae4SAndroid Build Coastguard Worker /* Retrieve algorithm string from the challenge */
295*6236dae4SAndroid Build Coastguard Worker if(!auth_digest_get_key_value(chlg, "algorithm=", alg, alen, ','))
296*6236dae4SAndroid Build Coastguard Worker return CURLE_BAD_CONTENT_ENCODING;
297*6236dae4SAndroid Build Coastguard Worker
298*6236dae4SAndroid Build Coastguard Worker /* Retrieve qop-options string from the challenge */
299*6236dae4SAndroid Build Coastguard Worker if(!auth_digest_get_key_value(chlg, "qop=\"", qop, qlen, '\"'))
300*6236dae4SAndroid Build Coastguard Worker return CURLE_BAD_CONTENT_ENCODING;
301*6236dae4SAndroid Build Coastguard Worker
302*6236dae4SAndroid Build Coastguard Worker return CURLE_OK;
303*6236dae4SAndroid Build Coastguard Worker }
304*6236dae4SAndroid Build Coastguard Worker
305*6236dae4SAndroid Build Coastguard Worker /*
306*6236dae4SAndroid Build Coastguard Worker * Curl_auth_is_digest_supported()
307*6236dae4SAndroid Build Coastguard Worker *
308*6236dae4SAndroid Build Coastguard Worker * This is used to evaluate if DIGEST is supported.
309*6236dae4SAndroid Build Coastguard Worker *
310*6236dae4SAndroid Build Coastguard Worker * Parameters: None
311*6236dae4SAndroid Build Coastguard Worker *
312*6236dae4SAndroid Build Coastguard Worker * Returns TRUE as DIGEST as handled by libcurl.
313*6236dae4SAndroid Build Coastguard Worker */
Curl_auth_is_digest_supported(void)314*6236dae4SAndroid Build Coastguard Worker bool Curl_auth_is_digest_supported(void)
315*6236dae4SAndroid Build Coastguard Worker {
316*6236dae4SAndroid Build Coastguard Worker return TRUE;
317*6236dae4SAndroid Build Coastguard Worker }
318*6236dae4SAndroid Build Coastguard Worker
319*6236dae4SAndroid Build Coastguard Worker /*
320*6236dae4SAndroid Build Coastguard Worker * Curl_auth_create_digest_md5_message()
321*6236dae4SAndroid Build Coastguard Worker *
322*6236dae4SAndroid Build Coastguard Worker * This is used to generate an already encoded DIGEST-MD5 response message
323*6236dae4SAndroid Build Coastguard Worker * ready for sending to the recipient.
324*6236dae4SAndroid Build Coastguard Worker *
325*6236dae4SAndroid Build Coastguard Worker * Parameters:
326*6236dae4SAndroid Build Coastguard Worker *
327*6236dae4SAndroid Build Coastguard Worker * data [in] - The session handle.
328*6236dae4SAndroid Build Coastguard Worker * chlg [in] - The challenge message.
329*6236dae4SAndroid Build Coastguard Worker * userp [in] - The username.
330*6236dae4SAndroid Build Coastguard Worker * passwdp [in] - The user's password.
331*6236dae4SAndroid Build Coastguard Worker * service [in] - The service type such as http, smtp, pop or imap.
332*6236dae4SAndroid Build Coastguard Worker * out [out] - The result storage.
333*6236dae4SAndroid Build Coastguard Worker *
334*6236dae4SAndroid Build Coastguard Worker * Returns CURLE_OK on success.
335*6236dae4SAndroid Build Coastguard Worker */
Curl_auth_create_digest_md5_message(struct Curl_easy * data,const struct bufref * chlg,const char * userp,const char * passwdp,const char * service,struct bufref * out)336*6236dae4SAndroid Build Coastguard Worker CURLcode Curl_auth_create_digest_md5_message(struct Curl_easy *data,
337*6236dae4SAndroid Build Coastguard Worker const struct bufref *chlg,
338*6236dae4SAndroid Build Coastguard Worker const char *userp,
339*6236dae4SAndroid Build Coastguard Worker const char *passwdp,
340*6236dae4SAndroid Build Coastguard Worker const char *service,
341*6236dae4SAndroid Build Coastguard Worker struct bufref *out)
342*6236dae4SAndroid Build Coastguard Worker {
343*6236dae4SAndroid Build Coastguard Worker size_t i;
344*6236dae4SAndroid Build Coastguard Worker struct MD5_context *ctxt;
345*6236dae4SAndroid Build Coastguard Worker char *response = NULL;
346*6236dae4SAndroid Build Coastguard Worker unsigned char digest[MD5_DIGEST_LEN];
347*6236dae4SAndroid Build Coastguard Worker char HA1_hex[2 * MD5_DIGEST_LEN + 1];
348*6236dae4SAndroid Build Coastguard Worker char HA2_hex[2 * MD5_DIGEST_LEN + 1];
349*6236dae4SAndroid Build Coastguard Worker char resp_hash_hex[2 * MD5_DIGEST_LEN + 1];
350*6236dae4SAndroid Build Coastguard Worker char nonce[64];
351*6236dae4SAndroid Build Coastguard Worker char realm[128];
352*6236dae4SAndroid Build Coastguard Worker char algorithm[64];
353*6236dae4SAndroid Build Coastguard Worker char qop_options[64];
354*6236dae4SAndroid Build Coastguard Worker int qop_values;
355*6236dae4SAndroid Build Coastguard Worker char cnonce[33];
356*6236dae4SAndroid Build Coastguard Worker char nonceCount[] = "00000001";
357*6236dae4SAndroid Build Coastguard Worker char method[] = "AUTHENTICATE";
358*6236dae4SAndroid Build Coastguard Worker char qop[] = DIGEST_QOP_VALUE_STRING_AUTH;
359*6236dae4SAndroid Build Coastguard Worker char *spn = NULL;
360*6236dae4SAndroid Build Coastguard Worker
361*6236dae4SAndroid Build Coastguard Worker /* Decode the challenge message */
362*6236dae4SAndroid Build Coastguard Worker CURLcode result = auth_decode_digest_md5_message(chlg,
363*6236dae4SAndroid Build Coastguard Worker nonce, sizeof(nonce),
364*6236dae4SAndroid Build Coastguard Worker realm, sizeof(realm),
365*6236dae4SAndroid Build Coastguard Worker algorithm,
366*6236dae4SAndroid Build Coastguard Worker sizeof(algorithm),
367*6236dae4SAndroid Build Coastguard Worker qop_options,
368*6236dae4SAndroid Build Coastguard Worker sizeof(qop_options));
369*6236dae4SAndroid Build Coastguard Worker if(result)
370*6236dae4SAndroid Build Coastguard Worker return result;
371*6236dae4SAndroid Build Coastguard Worker
372*6236dae4SAndroid Build Coastguard Worker /* We only support md5 sessions */
373*6236dae4SAndroid Build Coastguard Worker if(strcmp(algorithm, "md5-sess") != 0)
374*6236dae4SAndroid Build Coastguard Worker return CURLE_BAD_CONTENT_ENCODING;
375*6236dae4SAndroid Build Coastguard Worker
376*6236dae4SAndroid Build Coastguard Worker /* Get the qop-values from the qop-options */
377*6236dae4SAndroid Build Coastguard Worker result = auth_digest_get_qop_values(qop_options, &qop_values);
378*6236dae4SAndroid Build Coastguard Worker if(result)
379*6236dae4SAndroid Build Coastguard Worker return result;
380*6236dae4SAndroid Build Coastguard Worker
381*6236dae4SAndroid Build Coastguard Worker /* We only support auth quality-of-protection */
382*6236dae4SAndroid Build Coastguard Worker if(!(qop_values & DIGEST_QOP_VALUE_AUTH))
383*6236dae4SAndroid Build Coastguard Worker return CURLE_BAD_CONTENT_ENCODING;
384*6236dae4SAndroid Build Coastguard Worker
385*6236dae4SAndroid Build Coastguard Worker /* Generate 32 random hex chars, 32 bytes + 1 null-termination */
386*6236dae4SAndroid Build Coastguard Worker result = Curl_rand_hex(data, (unsigned char *)cnonce, sizeof(cnonce));
387*6236dae4SAndroid Build Coastguard Worker if(result)
388*6236dae4SAndroid Build Coastguard Worker return result;
389*6236dae4SAndroid Build Coastguard Worker
390*6236dae4SAndroid Build Coastguard Worker /* So far so good, now calculate A1 and H(A1) according to RFC 2831 */
391*6236dae4SAndroid Build Coastguard Worker ctxt = Curl_MD5_init(&Curl_DIGEST_MD5);
392*6236dae4SAndroid Build Coastguard Worker if(!ctxt)
393*6236dae4SAndroid Build Coastguard Worker return CURLE_OUT_OF_MEMORY;
394*6236dae4SAndroid Build Coastguard Worker
395*6236dae4SAndroid Build Coastguard Worker Curl_MD5_update(ctxt, (const unsigned char *) userp,
396*6236dae4SAndroid Build Coastguard Worker curlx_uztoui(strlen(userp)));
397*6236dae4SAndroid Build Coastguard Worker Curl_MD5_update(ctxt, (const unsigned char *) ":", 1);
398*6236dae4SAndroid Build Coastguard Worker Curl_MD5_update(ctxt, (const unsigned char *) realm,
399*6236dae4SAndroid Build Coastguard Worker curlx_uztoui(strlen(realm)));
400*6236dae4SAndroid Build Coastguard Worker Curl_MD5_update(ctxt, (const unsigned char *) ":", 1);
401*6236dae4SAndroid Build Coastguard Worker Curl_MD5_update(ctxt, (const unsigned char *) passwdp,
402*6236dae4SAndroid Build Coastguard Worker curlx_uztoui(strlen(passwdp)));
403*6236dae4SAndroid Build Coastguard Worker Curl_MD5_final(ctxt, digest);
404*6236dae4SAndroid Build Coastguard Worker
405*6236dae4SAndroid Build Coastguard Worker ctxt = Curl_MD5_init(&Curl_DIGEST_MD5);
406*6236dae4SAndroid Build Coastguard Worker if(!ctxt)
407*6236dae4SAndroid Build Coastguard Worker return CURLE_OUT_OF_MEMORY;
408*6236dae4SAndroid Build Coastguard Worker
409*6236dae4SAndroid Build Coastguard Worker Curl_MD5_update(ctxt, (const unsigned char *) digest, MD5_DIGEST_LEN);
410*6236dae4SAndroid Build Coastguard Worker Curl_MD5_update(ctxt, (const unsigned char *) ":", 1);
411*6236dae4SAndroid Build Coastguard Worker Curl_MD5_update(ctxt, (const unsigned char *) nonce,
412*6236dae4SAndroid Build Coastguard Worker curlx_uztoui(strlen(nonce)));
413*6236dae4SAndroid Build Coastguard Worker Curl_MD5_update(ctxt, (const unsigned char *) ":", 1);
414*6236dae4SAndroid Build Coastguard Worker Curl_MD5_update(ctxt, (const unsigned char *) cnonce,
415*6236dae4SAndroid Build Coastguard Worker curlx_uztoui(strlen(cnonce)));
416*6236dae4SAndroid Build Coastguard Worker Curl_MD5_final(ctxt, digest);
417*6236dae4SAndroid Build Coastguard Worker
418*6236dae4SAndroid Build Coastguard Worker /* Convert calculated 16 octet hex into 32 bytes string */
419*6236dae4SAndroid Build Coastguard Worker for(i = 0; i < MD5_DIGEST_LEN; i++)
420*6236dae4SAndroid Build Coastguard Worker msnprintf(&HA1_hex[2 * i], 3, "%02x", digest[i]);
421*6236dae4SAndroid Build Coastguard Worker
422*6236dae4SAndroid Build Coastguard Worker /* Generate our SPN */
423*6236dae4SAndroid Build Coastguard Worker spn = Curl_auth_build_spn(service, data->conn->host.name, NULL);
424*6236dae4SAndroid Build Coastguard Worker if(!spn)
425*6236dae4SAndroid Build Coastguard Worker return CURLE_OUT_OF_MEMORY;
426*6236dae4SAndroid Build Coastguard Worker
427*6236dae4SAndroid Build Coastguard Worker /* Calculate H(A2) */
428*6236dae4SAndroid Build Coastguard Worker ctxt = Curl_MD5_init(&Curl_DIGEST_MD5);
429*6236dae4SAndroid Build Coastguard Worker if(!ctxt) {
430*6236dae4SAndroid Build Coastguard Worker free(spn);
431*6236dae4SAndroid Build Coastguard Worker
432*6236dae4SAndroid Build Coastguard Worker return CURLE_OUT_OF_MEMORY;
433*6236dae4SAndroid Build Coastguard Worker }
434*6236dae4SAndroid Build Coastguard Worker
435*6236dae4SAndroid Build Coastguard Worker Curl_MD5_update(ctxt, (const unsigned char *) method,
436*6236dae4SAndroid Build Coastguard Worker curlx_uztoui(strlen(method)));
437*6236dae4SAndroid Build Coastguard Worker Curl_MD5_update(ctxt, (const unsigned char *) ":", 1);
438*6236dae4SAndroid Build Coastguard Worker Curl_MD5_update(ctxt, (const unsigned char *) spn,
439*6236dae4SAndroid Build Coastguard Worker curlx_uztoui(strlen(spn)));
440*6236dae4SAndroid Build Coastguard Worker Curl_MD5_final(ctxt, digest);
441*6236dae4SAndroid Build Coastguard Worker
442*6236dae4SAndroid Build Coastguard Worker for(i = 0; i < MD5_DIGEST_LEN; i++)
443*6236dae4SAndroid Build Coastguard Worker msnprintf(&HA2_hex[2 * i], 3, "%02x", digest[i]);
444*6236dae4SAndroid Build Coastguard Worker
445*6236dae4SAndroid Build Coastguard Worker /* Now calculate the response hash */
446*6236dae4SAndroid Build Coastguard Worker ctxt = Curl_MD5_init(&Curl_DIGEST_MD5);
447*6236dae4SAndroid Build Coastguard Worker if(!ctxt) {
448*6236dae4SAndroid Build Coastguard Worker free(spn);
449*6236dae4SAndroid Build Coastguard Worker
450*6236dae4SAndroid Build Coastguard Worker return CURLE_OUT_OF_MEMORY;
451*6236dae4SAndroid Build Coastguard Worker }
452*6236dae4SAndroid Build Coastguard Worker
453*6236dae4SAndroid Build Coastguard Worker Curl_MD5_update(ctxt, (const unsigned char *) HA1_hex, 2 * MD5_DIGEST_LEN);
454*6236dae4SAndroid Build Coastguard Worker Curl_MD5_update(ctxt, (const unsigned char *) ":", 1);
455*6236dae4SAndroid Build Coastguard Worker Curl_MD5_update(ctxt, (const unsigned char *) nonce,
456*6236dae4SAndroid Build Coastguard Worker curlx_uztoui(strlen(nonce)));
457*6236dae4SAndroid Build Coastguard Worker Curl_MD5_update(ctxt, (const unsigned char *) ":", 1);
458*6236dae4SAndroid Build Coastguard Worker
459*6236dae4SAndroid Build Coastguard Worker Curl_MD5_update(ctxt, (const unsigned char *) nonceCount,
460*6236dae4SAndroid Build Coastguard Worker curlx_uztoui(strlen(nonceCount)));
461*6236dae4SAndroid Build Coastguard Worker Curl_MD5_update(ctxt, (const unsigned char *) ":", 1);
462*6236dae4SAndroid Build Coastguard Worker Curl_MD5_update(ctxt, (const unsigned char *) cnonce,
463*6236dae4SAndroid Build Coastguard Worker curlx_uztoui(strlen(cnonce)));
464*6236dae4SAndroid Build Coastguard Worker Curl_MD5_update(ctxt, (const unsigned char *) ":", 1);
465*6236dae4SAndroid Build Coastguard Worker Curl_MD5_update(ctxt, (const unsigned char *) qop,
466*6236dae4SAndroid Build Coastguard Worker curlx_uztoui(strlen(qop)));
467*6236dae4SAndroid Build Coastguard Worker Curl_MD5_update(ctxt, (const unsigned char *) ":", 1);
468*6236dae4SAndroid Build Coastguard Worker
469*6236dae4SAndroid Build Coastguard Worker Curl_MD5_update(ctxt, (const unsigned char *) HA2_hex, 2 * MD5_DIGEST_LEN);
470*6236dae4SAndroid Build Coastguard Worker Curl_MD5_final(ctxt, digest);
471*6236dae4SAndroid Build Coastguard Worker
472*6236dae4SAndroid Build Coastguard Worker for(i = 0; i < MD5_DIGEST_LEN; i++)
473*6236dae4SAndroid Build Coastguard Worker msnprintf(&resp_hash_hex[2 * i], 3, "%02x", digest[i]);
474*6236dae4SAndroid Build Coastguard Worker
475*6236dae4SAndroid Build Coastguard Worker /* Generate the response */
476*6236dae4SAndroid Build Coastguard Worker response = aprintf("username=\"%s\",realm=\"%s\",nonce=\"%s\","
477*6236dae4SAndroid Build Coastguard Worker "cnonce=\"%s\",nc=\"%s\",digest-uri=\"%s\",response=%s,"
478*6236dae4SAndroid Build Coastguard Worker "qop=%s",
479*6236dae4SAndroid Build Coastguard Worker userp, realm, nonce,
480*6236dae4SAndroid Build Coastguard Worker cnonce, nonceCount, spn, resp_hash_hex, qop);
481*6236dae4SAndroid Build Coastguard Worker free(spn);
482*6236dae4SAndroid Build Coastguard Worker if(!response)
483*6236dae4SAndroid Build Coastguard Worker return CURLE_OUT_OF_MEMORY;
484*6236dae4SAndroid Build Coastguard Worker
485*6236dae4SAndroid Build Coastguard Worker /* Return the response. */
486*6236dae4SAndroid Build Coastguard Worker Curl_bufref_set(out, response, strlen(response), curl_free);
487*6236dae4SAndroid Build Coastguard Worker return result;
488*6236dae4SAndroid Build Coastguard Worker }
489*6236dae4SAndroid Build Coastguard Worker
490*6236dae4SAndroid Build Coastguard Worker /*
491*6236dae4SAndroid Build Coastguard Worker * Curl_auth_decode_digest_http_message()
492*6236dae4SAndroid Build Coastguard Worker *
493*6236dae4SAndroid Build Coastguard Worker * This is used to decode an HTTP DIGEST challenge message into the separate
494*6236dae4SAndroid Build Coastguard Worker * attributes.
495*6236dae4SAndroid Build Coastguard Worker *
496*6236dae4SAndroid Build Coastguard Worker * Parameters:
497*6236dae4SAndroid Build Coastguard Worker *
498*6236dae4SAndroid Build Coastguard Worker * chlg [in] - The challenge message.
499*6236dae4SAndroid Build Coastguard Worker * digest [in/out] - The digest data struct being used and modified.
500*6236dae4SAndroid Build Coastguard Worker *
501*6236dae4SAndroid Build Coastguard Worker * Returns CURLE_OK on success.
502*6236dae4SAndroid Build Coastguard Worker */
Curl_auth_decode_digest_http_message(const char * chlg,struct digestdata * digest)503*6236dae4SAndroid Build Coastguard Worker CURLcode Curl_auth_decode_digest_http_message(const char *chlg,
504*6236dae4SAndroid Build Coastguard Worker struct digestdata *digest)
505*6236dae4SAndroid Build Coastguard Worker {
506*6236dae4SAndroid Build Coastguard Worker bool before = FALSE; /* got a nonce before */
507*6236dae4SAndroid Build Coastguard Worker bool foundAuth = FALSE;
508*6236dae4SAndroid Build Coastguard Worker bool foundAuthInt = FALSE;
509*6236dae4SAndroid Build Coastguard Worker char *token = NULL;
510*6236dae4SAndroid Build Coastguard Worker char *tmp = NULL;
511*6236dae4SAndroid Build Coastguard Worker
512*6236dae4SAndroid Build Coastguard Worker /* If we already have received a nonce, keep that in mind */
513*6236dae4SAndroid Build Coastguard Worker if(digest->nonce)
514*6236dae4SAndroid Build Coastguard Worker before = TRUE;
515*6236dae4SAndroid Build Coastguard Worker
516*6236dae4SAndroid Build Coastguard Worker /* Clean up any former leftovers and initialise to defaults */
517*6236dae4SAndroid Build Coastguard Worker Curl_auth_digest_cleanup(digest);
518*6236dae4SAndroid Build Coastguard Worker
519*6236dae4SAndroid Build Coastguard Worker for(;;) {
520*6236dae4SAndroid Build Coastguard Worker char value[DIGEST_MAX_VALUE_LENGTH];
521*6236dae4SAndroid Build Coastguard Worker char content[DIGEST_MAX_CONTENT_LENGTH];
522*6236dae4SAndroid Build Coastguard Worker
523*6236dae4SAndroid Build Coastguard Worker /* Pass all additional spaces here */
524*6236dae4SAndroid Build Coastguard Worker while(*chlg && ISBLANK(*chlg))
525*6236dae4SAndroid Build Coastguard Worker chlg++;
526*6236dae4SAndroid Build Coastguard Worker
527*6236dae4SAndroid Build Coastguard Worker /* Extract a value=content pair */
528*6236dae4SAndroid Build Coastguard Worker if(Curl_auth_digest_get_pair(chlg, value, content, &chlg)) {
529*6236dae4SAndroid Build Coastguard Worker if(strcasecompare(value, "nonce")) {
530*6236dae4SAndroid Build Coastguard Worker free(digest->nonce);
531*6236dae4SAndroid Build Coastguard Worker digest->nonce = strdup(content);
532*6236dae4SAndroid Build Coastguard Worker if(!digest->nonce)
533*6236dae4SAndroid Build Coastguard Worker return CURLE_OUT_OF_MEMORY;
534*6236dae4SAndroid Build Coastguard Worker }
535*6236dae4SAndroid Build Coastguard Worker else if(strcasecompare(value, "stale")) {
536*6236dae4SAndroid Build Coastguard Worker if(strcasecompare(content, "true")) {
537*6236dae4SAndroid Build Coastguard Worker digest->stale = TRUE;
538*6236dae4SAndroid Build Coastguard Worker digest->nc = 1; /* we make a new nonce now */
539*6236dae4SAndroid Build Coastguard Worker }
540*6236dae4SAndroid Build Coastguard Worker }
541*6236dae4SAndroid Build Coastguard Worker else if(strcasecompare(value, "realm")) {
542*6236dae4SAndroid Build Coastguard Worker free(digest->realm);
543*6236dae4SAndroid Build Coastguard Worker digest->realm = strdup(content);
544*6236dae4SAndroid Build Coastguard Worker if(!digest->realm)
545*6236dae4SAndroid Build Coastguard Worker return CURLE_OUT_OF_MEMORY;
546*6236dae4SAndroid Build Coastguard Worker }
547*6236dae4SAndroid Build Coastguard Worker else if(strcasecompare(value, "opaque")) {
548*6236dae4SAndroid Build Coastguard Worker free(digest->opaque);
549*6236dae4SAndroid Build Coastguard Worker digest->opaque = strdup(content);
550*6236dae4SAndroid Build Coastguard Worker if(!digest->opaque)
551*6236dae4SAndroid Build Coastguard Worker return CURLE_OUT_OF_MEMORY;
552*6236dae4SAndroid Build Coastguard Worker }
553*6236dae4SAndroid Build Coastguard Worker else if(strcasecompare(value, "qop")) {
554*6236dae4SAndroid Build Coastguard Worker char *tok_buf = NULL;
555*6236dae4SAndroid Build Coastguard Worker /* Tokenize the list and choose auth if possible, use a temporary
556*6236dae4SAndroid Build Coastguard Worker clone of the buffer since strtok_r() ruins it */
557*6236dae4SAndroid Build Coastguard Worker tmp = strdup(content);
558*6236dae4SAndroid Build Coastguard Worker if(!tmp)
559*6236dae4SAndroid Build Coastguard Worker return CURLE_OUT_OF_MEMORY;
560*6236dae4SAndroid Build Coastguard Worker
561*6236dae4SAndroid Build Coastguard Worker token = strtok_r(tmp, ",", &tok_buf);
562*6236dae4SAndroid Build Coastguard Worker while(token) {
563*6236dae4SAndroid Build Coastguard Worker /* Pass additional spaces here */
564*6236dae4SAndroid Build Coastguard Worker while(*token && ISBLANK(*token))
565*6236dae4SAndroid Build Coastguard Worker token++;
566*6236dae4SAndroid Build Coastguard Worker if(strcasecompare(token, DIGEST_QOP_VALUE_STRING_AUTH)) {
567*6236dae4SAndroid Build Coastguard Worker foundAuth = TRUE;
568*6236dae4SAndroid Build Coastguard Worker }
569*6236dae4SAndroid Build Coastguard Worker else if(strcasecompare(token, DIGEST_QOP_VALUE_STRING_AUTH_INT)) {
570*6236dae4SAndroid Build Coastguard Worker foundAuthInt = TRUE;
571*6236dae4SAndroid Build Coastguard Worker }
572*6236dae4SAndroid Build Coastguard Worker token = strtok_r(NULL, ",", &tok_buf);
573*6236dae4SAndroid Build Coastguard Worker }
574*6236dae4SAndroid Build Coastguard Worker
575*6236dae4SAndroid Build Coastguard Worker free(tmp);
576*6236dae4SAndroid Build Coastguard Worker
577*6236dae4SAndroid Build Coastguard Worker /* Select only auth or auth-int. Otherwise, ignore */
578*6236dae4SAndroid Build Coastguard Worker if(foundAuth) {
579*6236dae4SAndroid Build Coastguard Worker free(digest->qop);
580*6236dae4SAndroid Build Coastguard Worker digest->qop = strdup(DIGEST_QOP_VALUE_STRING_AUTH);
581*6236dae4SAndroid Build Coastguard Worker if(!digest->qop)
582*6236dae4SAndroid Build Coastguard Worker return CURLE_OUT_OF_MEMORY;
583*6236dae4SAndroid Build Coastguard Worker }
584*6236dae4SAndroid Build Coastguard Worker else if(foundAuthInt) {
585*6236dae4SAndroid Build Coastguard Worker free(digest->qop);
586*6236dae4SAndroid Build Coastguard Worker digest->qop = strdup(DIGEST_QOP_VALUE_STRING_AUTH_INT);
587*6236dae4SAndroid Build Coastguard Worker if(!digest->qop)
588*6236dae4SAndroid Build Coastguard Worker return CURLE_OUT_OF_MEMORY;
589*6236dae4SAndroid Build Coastguard Worker }
590*6236dae4SAndroid Build Coastguard Worker }
591*6236dae4SAndroid Build Coastguard Worker else if(strcasecompare(value, "algorithm")) {
592*6236dae4SAndroid Build Coastguard Worker free(digest->algorithm);
593*6236dae4SAndroid Build Coastguard Worker digest->algorithm = strdup(content);
594*6236dae4SAndroid Build Coastguard Worker if(!digest->algorithm)
595*6236dae4SAndroid Build Coastguard Worker return CURLE_OUT_OF_MEMORY;
596*6236dae4SAndroid Build Coastguard Worker
597*6236dae4SAndroid Build Coastguard Worker if(strcasecompare(content, "MD5-sess"))
598*6236dae4SAndroid Build Coastguard Worker digest->algo = ALGO_MD5SESS;
599*6236dae4SAndroid Build Coastguard Worker else if(strcasecompare(content, "MD5"))
600*6236dae4SAndroid Build Coastguard Worker digest->algo = ALGO_MD5;
601*6236dae4SAndroid Build Coastguard Worker else if(strcasecompare(content, "SHA-256"))
602*6236dae4SAndroid Build Coastguard Worker digest->algo = ALGO_SHA256;
603*6236dae4SAndroid Build Coastguard Worker else if(strcasecompare(content, "SHA-256-SESS"))
604*6236dae4SAndroid Build Coastguard Worker digest->algo = ALGO_SHA256SESS;
605*6236dae4SAndroid Build Coastguard Worker else if(strcasecompare(content, "SHA-512-256")) {
606*6236dae4SAndroid Build Coastguard Worker #ifdef CURL_HAVE_SHA512_256
607*6236dae4SAndroid Build Coastguard Worker digest->algo = ALGO_SHA512_256;
608*6236dae4SAndroid Build Coastguard Worker #else /* ! CURL_HAVE_SHA512_256 */
609*6236dae4SAndroid Build Coastguard Worker return CURLE_NOT_BUILT_IN;
610*6236dae4SAndroid Build Coastguard Worker #endif /* ! CURL_HAVE_SHA512_256 */
611*6236dae4SAndroid Build Coastguard Worker }
612*6236dae4SAndroid Build Coastguard Worker else if(strcasecompare(content, "SHA-512-256-SESS")) {
613*6236dae4SAndroid Build Coastguard Worker #ifdef CURL_HAVE_SHA512_256
614*6236dae4SAndroid Build Coastguard Worker digest->algo = ALGO_SHA512_256SESS;
615*6236dae4SAndroid Build Coastguard Worker #else /* ! CURL_HAVE_SHA512_256 */
616*6236dae4SAndroid Build Coastguard Worker return CURLE_NOT_BUILT_IN;
617*6236dae4SAndroid Build Coastguard Worker #endif /* ! CURL_HAVE_SHA512_256 */
618*6236dae4SAndroid Build Coastguard Worker }
619*6236dae4SAndroid Build Coastguard Worker else
620*6236dae4SAndroid Build Coastguard Worker return CURLE_BAD_CONTENT_ENCODING;
621*6236dae4SAndroid Build Coastguard Worker }
622*6236dae4SAndroid Build Coastguard Worker else if(strcasecompare(value, "userhash")) {
623*6236dae4SAndroid Build Coastguard Worker if(strcasecompare(content, "true")) {
624*6236dae4SAndroid Build Coastguard Worker digest->userhash = TRUE;
625*6236dae4SAndroid Build Coastguard Worker }
626*6236dae4SAndroid Build Coastguard Worker }
627*6236dae4SAndroid Build Coastguard Worker else {
628*6236dae4SAndroid Build Coastguard Worker /* Unknown specifier, ignore it! */
629*6236dae4SAndroid Build Coastguard Worker }
630*6236dae4SAndroid Build Coastguard Worker }
631*6236dae4SAndroid Build Coastguard Worker else
632*6236dae4SAndroid Build Coastguard Worker break; /* We are done here */
633*6236dae4SAndroid Build Coastguard Worker
634*6236dae4SAndroid Build Coastguard Worker /* Pass all additional spaces here */
635*6236dae4SAndroid Build Coastguard Worker while(*chlg && ISBLANK(*chlg))
636*6236dae4SAndroid Build Coastguard Worker chlg++;
637*6236dae4SAndroid Build Coastguard Worker
638*6236dae4SAndroid Build Coastguard Worker /* Allow the list to be comma-separated */
639*6236dae4SAndroid Build Coastguard Worker if(',' == *chlg)
640*6236dae4SAndroid Build Coastguard Worker chlg++;
641*6236dae4SAndroid Build Coastguard Worker }
642*6236dae4SAndroid Build Coastguard Worker
643*6236dae4SAndroid Build Coastguard Worker /* We had a nonce since before, and we got another one now without
644*6236dae4SAndroid Build Coastguard Worker 'stale=true'. This means we provided bad credentials in the previous
645*6236dae4SAndroid Build Coastguard Worker request */
646*6236dae4SAndroid Build Coastguard Worker if(before && !digest->stale)
647*6236dae4SAndroid Build Coastguard Worker return CURLE_BAD_CONTENT_ENCODING;
648*6236dae4SAndroid Build Coastguard Worker
649*6236dae4SAndroid Build Coastguard Worker /* We got this header without a nonce, that is a bad Digest line! */
650*6236dae4SAndroid Build Coastguard Worker if(!digest->nonce)
651*6236dae4SAndroid Build Coastguard Worker return CURLE_BAD_CONTENT_ENCODING;
652*6236dae4SAndroid Build Coastguard Worker
653*6236dae4SAndroid Build Coastguard Worker /* "<algo>-sess" protocol versions require "auth" or "auth-int" qop */
654*6236dae4SAndroid Build Coastguard Worker if(!digest->qop && (digest->algo & SESSION_ALGO))
655*6236dae4SAndroid Build Coastguard Worker return CURLE_BAD_CONTENT_ENCODING;
656*6236dae4SAndroid Build Coastguard Worker
657*6236dae4SAndroid Build Coastguard Worker return CURLE_OK;
658*6236dae4SAndroid Build Coastguard Worker }
659*6236dae4SAndroid Build Coastguard Worker
660*6236dae4SAndroid Build Coastguard Worker /*
661*6236dae4SAndroid Build Coastguard Worker * auth_create_digest_http_message()
662*6236dae4SAndroid Build Coastguard Worker *
663*6236dae4SAndroid Build Coastguard Worker * This is used to generate an HTTP DIGEST response message ready for sending
664*6236dae4SAndroid Build Coastguard Worker * to the recipient.
665*6236dae4SAndroid Build Coastguard Worker *
666*6236dae4SAndroid Build Coastguard Worker * Parameters:
667*6236dae4SAndroid Build Coastguard Worker *
668*6236dae4SAndroid Build Coastguard Worker * data [in] - The session handle.
669*6236dae4SAndroid Build Coastguard Worker * userp [in] - The username.
670*6236dae4SAndroid Build Coastguard Worker * passwdp [in] - The user's password.
671*6236dae4SAndroid Build Coastguard Worker * request [in] - The HTTP request.
672*6236dae4SAndroid Build Coastguard Worker * uripath [in] - The path of the HTTP uri.
673*6236dae4SAndroid Build Coastguard Worker * digest [in/out] - The digest data struct being used and modified.
674*6236dae4SAndroid Build Coastguard Worker * outptr [in/out] - The address where a pointer to newly allocated memory
675*6236dae4SAndroid Build Coastguard Worker * holding the result will be stored upon completion.
676*6236dae4SAndroid Build Coastguard Worker * outlen [out] - The length of the output message.
677*6236dae4SAndroid Build Coastguard Worker *
678*6236dae4SAndroid Build Coastguard Worker * Returns CURLE_OK on success.
679*6236dae4SAndroid Build Coastguard Worker */
auth_create_digest_http_message(struct Curl_easy * data,const char * userp,const char * passwdp,const unsigned char * request,const unsigned char * uripath,struct digestdata * digest,char ** outptr,size_t * outlen,void (* convert_to_ascii)(unsigned char *,unsigned char *),CURLcode (* hash)(unsigned char *,const unsigned char *,const size_t))680*6236dae4SAndroid Build Coastguard Worker static CURLcode auth_create_digest_http_message(
681*6236dae4SAndroid Build Coastguard Worker struct Curl_easy *data,
682*6236dae4SAndroid Build Coastguard Worker const char *userp,
683*6236dae4SAndroid Build Coastguard Worker const char *passwdp,
684*6236dae4SAndroid Build Coastguard Worker const unsigned char *request,
685*6236dae4SAndroid Build Coastguard Worker const unsigned char *uripath,
686*6236dae4SAndroid Build Coastguard Worker struct digestdata *digest,
687*6236dae4SAndroid Build Coastguard Worker char **outptr, size_t *outlen,
688*6236dae4SAndroid Build Coastguard Worker void (*convert_to_ascii)(unsigned char *, unsigned char *),
689*6236dae4SAndroid Build Coastguard Worker CURLcode (*hash)(unsigned char *, const unsigned char *,
690*6236dae4SAndroid Build Coastguard Worker const size_t))
691*6236dae4SAndroid Build Coastguard Worker {
692*6236dae4SAndroid Build Coastguard Worker CURLcode result;
693*6236dae4SAndroid Build Coastguard Worker unsigned char hashbuf[32]; /* 32 bytes/256 bits */
694*6236dae4SAndroid Build Coastguard Worker unsigned char request_digest[65];
695*6236dae4SAndroid Build Coastguard Worker unsigned char ha1[65]; /* 64 digits and 1 zero byte */
696*6236dae4SAndroid Build Coastguard Worker unsigned char ha2[65]; /* 64 digits and 1 zero byte */
697*6236dae4SAndroid Build Coastguard Worker char userh[65];
698*6236dae4SAndroid Build Coastguard Worker char *cnonce = NULL;
699*6236dae4SAndroid Build Coastguard Worker size_t cnonce_sz = 0;
700*6236dae4SAndroid Build Coastguard Worker char *userp_quoted;
701*6236dae4SAndroid Build Coastguard Worker char *realm_quoted;
702*6236dae4SAndroid Build Coastguard Worker char *nonce_quoted;
703*6236dae4SAndroid Build Coastguard Worker char *response = NULL;
704*6236dae4SAndroid Build Coastguard Worker char *hashthis = NULL;
705*6236dae4SAndroid Build Coastguard Worker char *tmp = NULL;
706*6236dae4SAndroid Build Coastguard Worker
707*6236dae4SAndroid Build Coastguard Worker memset(hashbuf, 0, sizeof(hashbuf));
708*6236dae4SAndroid Build Coastguard Worker if(!digest->nc)
709*6236dae4SAndroid Build Coastguard Worker digest->nc = 1;
710*6236dae4SAndroid Build Coastguard Worker
711*6236dae4SAndroid Build Coastguard Worker if(!digest->cnonce) {
712*6236dae4SAndroid Build Coastguard Worker char cnoncebuf[33];
713*6236dae4SAndroid Build Coastguard Worker result = Curl_rand_hex(data, (unsigned char *)cnoncebuf,
714*6236dae4SAndroid Build Coastguard Worker sizeof(cnoncebuf));
715*6236dae4SAndroid Build Coastguard Worker if(result)
716*6236dae4SAndroid Build Coastguard Worker return result;
717*6236dae4SAndroid Build Coastguard Worker
718*6236dae4SAndroid Build Coastguard Worker result = Curl_base64_encode(cnoncebuf, strlen(cnoncebuf),
719*6236dae4SAndroid Build Coastguard Worker &cnonce, &cnonce_sz);
720*6236dae4SAndroid Build Coastguard Worker if(result)
721*6236dae4SAndroid Build Coastguard Worker return result;
722*6236dae4SAndroid Build Coastguard Worker
723*6236dae4SAndroid Build Coastguard Worker digest->cnonce = cnonce;
724*6236dae4SAndroid Build Coastguard Worker }
725*6236dae4SAndroid Build Coastguard Worker
726*6236dae4SAndroid Build Coastguard Worker if(digest->userhash) {
727*6236dae4SAndroid Build Coastguard Worker hashthis = aprintf("%s:%s", userp, digest->realm ? digest->realm : "");
728*6236dae4SAndroid Build Coastguard Worker if(!hashthis)
729*6236dae4SAndroid Build Coastguard Worker return CURLE_OUT_OF_MEMORY;
730*6236dae4SAndroid Build Coastguard Worker
731*6236dae4SAndroid Build Coastguard Worker result = hash(hashbuf, (unsigned char *) hashthis, strlen(hashthis));
732*6236dae4SAndroid Build Coastguard Worker free(hashthis);
733*6236dae4SAndroid Build Coastguard Worker if(result)
734*6236dae4SAndroid Build Coastguard Worker return result;
735*6236dae4SAndroid Build Coastguard Worker convert_to_ascii(hashbuf, (unsigned char *)userh);
736*6236dae4SAndroid Build Coastguard Worker }
737*6236dae4SAndroid Build Coastguard Worker
738*6236dae4SAndroid Build Coastguard Worker /*
739*6236dae4SAndroid Build Coastguard Worker If the algorithm is "MD5" or unspecified (which then defaults to MD5):
740*6236dae4SAndroid Build Coastguard Worker
741*6236dae4SAndroid Build Coastguard Worker A1 = unq(username-value) ":" unq(realm-value) ":" passwd
742*6236dae4SAndroid Build Coastguard Worker
743*6236dae4SAndroid Build Coastguard Worker If the algorithm is "MD5-sess" then:
744*6236dae4SAndroid Build Coastguard Worker
745*6236dae4SAndroid Build Coastguard Worker A1 = H(unq(username-value) ":" unq(realm-value) ":" passwd) ":"
746*6236dae4SAndroid Build Coastguard Worker unq(nonce-value) ":" unq(cnonce-value)
747*6236dae4SAndroid Build Coastguard Worker */
748*6236dae4SAndroid Build Coastguard Worker
749*6236dae4SAndroid Build Coastguard Worker hashthis = aprintf("%s:%s:%s", userp, digest->realm ? digest->realm : "",
750*6236dae4SAndroid Build Coastguard Worker passwdp);
751*6236dae4SAndroid Build Coastguard Worker if(!hashthis)
752*6236dae4SAndroid Build Coastguard Worker return CURLE_OUT_OF_MEMORY;
753*6236dae4SAndroid Build Coastguard Worker
754*6236dae4SAndroid Build Coastguard Worker result = hash(hashbuf, (unsigned char *) hashthis, strlen(hashthis));
755*6236dae4SAndroid Build Coastguard Worker free(hashthis);
756*6236dae4SAndroid Build Coastguard Worker if(result)
757*6236dae4SAndroid Build Coastguard Worker return result;
758*6236dae4SAndroid Build Coastguard Worker convert_to_ascii(hashbuf, ha1);
759*6236dae4SAndroid Build Coastguard Worker
760*6236dae4SAndroid Build Coastguard Worker if(digest->algo & SESSION_ALGO) {
761*6236dae4SAndroid Build Coastguard Worker /* nonce and cnonce are OUTSIDE the hash */
762*6236dae4SAndroid Build Coastguard Worker tmp = aprintf("%s:%s:%s", ha1, digest->nonce, digest->cnonce);
763*6236dae4SAndroid Build Coastguard Worker if(!tmp)
764*6236dae4SAndroid Build Coastguard Worker return CURLE_OUT_OF_MEMORY;
765*6236dae4SAndroid Build Coastguard Worker
766*6236dae4SAndroid Build Coastguard Worker result = hash(hashbuf, (unsigned char *) tmp, strlen(tmp));
767*6236dae4SAndroid Build Coastguard Worker free(tmp);
768*6236dae4SAndroid Build Coastguard Worker if(result)
769*6236dae4SAndroid Build Coastguard Worker return result;
770*6236dae4SAndroid Build Coastguard Worker convert_to_ascii(hashbuf, ha1);
771*6236dae4SAndroid Build Coastguard Worker }
772*6236dae4SAndroid Build Coastguard Worker
773*6236dae4SAndroid Build Coastguard Worker /*
774*6236dae4SAndroid Build Coastguard Worker If the "qop" directive's value is "auth" or is unspecified, then A2 is:
775*6236dae4SAndroid Build Coastguard Worker
776*6236dae4SAndroid Build Coastguard Worker A2 = Method ":" digest-uri-value
777*6236dae4SAndroid Build Coastguard Worker
778*6236dae4SAndroid Build Coastguard Worker If the "qop" value is "auth-int", then A2 is:
779*6236dae4SAndroid Build Coastguard Worker
780*6236dae4SAndroid Build Coastguard Worker A2 = Method ":" digest-uri-value ":" H(entity-body)
781*6236dae4SAndroid Build Coastguard Worker
782*6236dae4SAndroid Build Coastguard Worker (The "Method" value is the HTTP request method as specified in section
783*6236dae4SAndroid Build Coastguard Worker 5.1.1 of RFC 2616)
784*6236dae4SAndroid Build Coastguard Worker */
785*6236dae4SAndroid Build Coastguard Worker
786*6236dae4SAndroid Build Coastguard Worker hashthis = aprintf("%s:%s", request, uripath);
787*6236dae4SAndroid Build Coastguard Worker if(!hashthis)
788*6236dae4SAndroid Build Coastguard Worker return CURLE_OUT_OF_MEMORY;
789*6236dae4SAndroid Build Coastguard Worker
790*6236dae4SAndroid Build Coastguard Worker if(digest->qop && strcasecompare(digest->qop, "auth-int")) {
791*6236dae4SAndroid Build Coastguard Worker /* We do not support auth-int for PUT or POST */
792*6236dae4SAndroid Build Coastguard Worker char hashed[65];
793*6236dae4SAndroid Build Coastguard Worker char *hashthis2;
794*6236dae4SAndroid Build Coastguard Worker
795*6236dae4SAndroid Build Coastguard Worker result = hash(hashbuf, (const unsigned char *)"", 0);
796*6236dae4SAndroid Build Coastguard Worker if(result) {
797*6236dae4SAndroid Build Coastguard Worker free(hashthis);
798*6236dae4SAndroid Build Coastguard Worker return result;
799*6236dae4SAndroid Build Coastguard Worker }
800*6236dae4SAndroid Build Coastguard Worker convert_to_ascii(hashbuf, (unsigned char *)hashed);
801*6236dae4SAndroid Build Coastguard Worker
802*6236dae4SAndroid Build Coastguard Worker hashthis2 = aprintf("%s:%s", hashthis, hashed);
803*6236dae4SAndroid Build Coastguard Worker free(hashthis);
804*6236dae4SAndroid Build Coastguard Worker hashthis = hashthis2;
805*6236dae4SAndroid Build Coastguard Worker }
806*6236dae4SAndroid Build Coastguard Worker
807*6236dae4SAndroid Build Coastguard Worker if(!hashthis)
808*6236dae4SAndroid Build Coastguard Worker return CURLE_OUT_OF_MEMORY;
809*6236dae4SAndroid Build Coastguard Worker
810*6236dae4SAndroid Build Coastguard Worker result = hash(hashbuf, (unsigned char *) hashthis, strlen(hashthis));
811*6236dae4SAndroid Build Coastguard Worker free(hashthis);
812*6236dae4SAndroid Build Coastguard Worker if(result)
813*6236dae4SAndroid Build Coastguard Worker return result;
814*6236dae4SAndroid Build Coastguard Worker convert_to_ascii(hashbuf, ha2);
815*6236dae4SAndroid Build Coastguard Worker
816*6236dae4SAndroid Build Coastguard Worker if(digest->qop) {
817*6236dae4SAndroid Build Coastguard Worker hashthis = aprintf("%s:%s:%08x:%s:%s:%s", ha1, digest->nonce, digest->nc,
818*6236dae4SAndroid Build Coastguard Worker digest->cnonce, digest->qop, ha2);
819*6236dae4SAndroid Build Coastguard Worker }
820*6236dae4SAndroid Build Coastguard Worker else {
821*6236dae4SAndroid Build Coastguard Worker hashthis = aprintf("%s:%s:%s", ha1, digest->nonce, ha2);
822*6236dae4SAndroid Build Coastguard Worker }
823*6236dae4SAndroid Build Coastguard Worker
824*6236dae4SAndroid Build Coastguard Worker if(!hashthis)
825*6236dae4SAndroid Build Coastguard Worker return CURLE_OUT_OF_MEMORY;
826*6236dae4SAndroid Build Coastguard Worker
827*6236dae4SAndroid Build Coastguard Worker result = hash(hashbuf, (unsigned char *) hashthis, strlen(hashthis));
828*6236dae4SAndroid Build Coastguard Worker free(hashthis);
829*6236dae4SAndroid Build Coastguard Worker if(result)
830*6236dae4SAndroid Build Coastguard Worker return result;
831*6236dae4SAndroid Build Coastguard Worker convert_to_ascii(hashbuf, request_digest);
832*6236dae4SAndroid Build Coastguard Worker
833*6236dae4SAndroid Build Coastguard Worker /* For test case 64 (snooped from a Mozilla 1.3a request)
834*6236dae4SAndroid Build Coastguard Worker
835*6236dae4SAndroid Build Coastguard Worker Authorization: Digest username="testuser", realm="testrealm", \
836*6236dae4SAndroid Build Coastguard Worker nonce="1053604145", uri="/64", response="c55f7f30d83d774a3d2dcacf725abaca"
837*6236dae4SAndroid Build Coastguard Worker
838*6236dae4SAndroid Build Coastguard Worker Digest parameters are all quoted strings. Username which is provided by
839*6236dae4SAndroid Build Coastguard Worker the user will need double quotes and backslashes within it escaped.
840*6236dae4SAndroid Build Coastguard Worker realm, nonce, and opaque will need backslashes as well as they were
841*6236dae4SAndroid Build Coastguard Worker de-escaped when copied from request header. cnonce is generated with
842*6236dae4SAndroid Build Coastguard Worker web-safe characters. uri is already percent encoded. nc is 8 hex
843*6236dae4SAndroid Build Coastguard Worker characters. algorithm and qop with standard values only contain web-safe
844*6236dae4SAndroid Build Coastguard Worker characters.
845*6236dae4SAndroid Build Coastguard Worker */
846*6236dae4SAndroid Build Coastguard Worker userp_quoted = auth_digest_string_quoted(digest->userhash ? userh : userp);
847*6236dae4SAndroid Build Coastguard Worker if(!userp_quoted)
848*6236dae4SAndroid Build Coastguard Worker return CURLE_OUT_OF_MEMORY;
849*6236dae4SAndroid Build Coastguard Worker if(digest->realm)
850*6236dae4SAndroid Build Coastguard Worker realm_quoted = auth_digest_string_quoted(digest->realm);
851*6236dae4SAndroid Build Coastguard Worker else {
852*6236dae4SAndroid Build Coastguard Worker realm_quoted = malloc(1);
853*6236dae4SAndroid Build Coastguard Worker if(realm_quoted)
854*6236dae4SAndroid Build Coastguard Worker realm_quoted[0] = 0;
855*6236dae4SAndroid Build Coastguard Worker }
856*6236dae4SAndroid Build Coastguard Worker if(!realm_quoted) {
857*6236dae4SAndroid Build Coastguard Worker free(userp_quoted);
858*6236dae4SAndroid Build Coastguard Worker return CURLE_OUT_OF_MEMORY;
859*6236dae4SAndroid Build Coastguard Worker }
860*6236dae4SAndroid Build Coastguard Worker nonce_quoted = auth_digest_string_quoted(digest->nonce);
861*6236dae4SAndroid Build Coastguard Worker if(!nonce_quoted) {
862*6236dae4SAndroid Build Coastguard Worker free(realm_quoted);
863*6236dae4SAndroid Build Coastguard Worker free(userp_quoted);
864*6236dae4SAndroid Build Coastguard Worker return CURLE_OUT_OF_MEMORY;
865*6236dae4SAndroid Build Coastguard Worker }
866*6236dae4SAndroid Build Coastguard Worker
867*6236dae4SAndroid Build Coastguard Worker if(digest->qop) {
868*6236dae4SAndroid Build Coastguard Worker response = aprintf("username=\"%s\", "
869*6236dae4SAndroid Build Coastguard Worker "realm=\"%s\", "
870*6236dae4SAndroid Build Coastguard Worker "nonce=\"%s\", "
871*6236dae4SAndroid Build Coastguard Worker "uri=\"%s\", "
872*6236dae4SAndroid Build Coastguard Worker "cnonce=\"%s\", "
873*6236dae4SAndroid Build Coastguard Worker "nc=%08x, "
874*6236dae4SAndroid Build Coastguard Worker "qop=%s, "
875*6236dae4SAndroid Build Coastguard Worker "response=\"%s\"",
876*6236dae4SAndroid Build Coastguard Worker userp_quoted,
877*6236dae4SAndroid Build Coastguard Worker realm_quoted,
878*6236dae4SAndroid Build Coastguard Worker nonce_quoted,
879*6236dae4SAndroid Build Coastguard Worker uripath,
880*6236dae4SAndroid Build Coastguard Worker digest->cnonce,
881*6236dae4SAndroid Build Coastguard Worker digest->nc,
882*6236dae4SAndroid Build Coastguard Worker digest->qop,
883*6236dae4SAndroid Build Coastguard Worker request_digest);
884*6236dae4SAndroid Build Coastguard Worker
885*6236dae4SAndroid Build Coastguard Worker /* Increment nonce-count to use another nc value for the next request */
886*6236dae4SAndroid Build Coastguard Worker digest->nc++;
887*6236dae4SAndroid Build Coastguard Worker }
888*6236dae4SAndroid Build Coastguard Worker else {
889*6236dae4SAndroid Build Coastguard Worker response = aprintf("username=\"%s\", "
890*6236dae4SAndroid Build Coastguard Worker "realm=\"%s\", "
891*6236dae4SAndroid Build Coastguard Worker "nonce=\"%s\", "
892*6236dae4SAndroid Build Coastguard Worker "uri=\"%s\", "
893*6236dae4SAndroid Build Coastguard Worker "response=\"%s\"",
894*6236dae4SAndroid Build Coastguard Worker userp_quoted,
895*6236dae4SAndroid Build Coastguard Worker realm_quoted,
896*6236dae4SAndroid Build Coastguard Worker nonce_quoted,
897*6236dae4SAndroid Build Coastguard Worker uripath,
898*6236dae4SAndroid Build Coastguard Worker request_digest);
899*6236dae4SAndroid Build Coastguard Worker }
900*6236dae4SAndroid Build Coastguard Worker free(nonce_quoted);
901*6236dae4SAndroid Build Coastguard Worker free(realm_quoted);
902*6236dae4SAndroid Build Coastguard Worker free(userp_quoted);
903*6236dae4SAndroid Build Coastguard Worker if(!response)
904*6236dae4SAndroid Build Coastguard Worker return CURLE_OUT_OF_MEMORY;
905*6236dae4SAndroid Build Coastguard Worker
906*6236dae4SAndroid Build Coastguard Worker /* Add the optional fields */
907*6236dae4SAndroid Build Coastguard Worker if(digest->opaque) {
908*6236dae4SAndroid Build Coastguard Worker char *opaque_quoted;
909*6236dae4SAndroid Build Coastguard Worker /* Append the opaque */
910*6236dae4SAndroid Build Coastguard Worker opaque_quoted = auth_digest_string_quoted(digest->opaque);
911*6236dae4SAndroid Build Coastguard Worker if(!opaque_quoted) {
912*6236dae4SAndroid Build Coastguard Worker free(response);
913*6236dae4SAndroid Build Coastguard Worker return CURLE_OUT_OF_MEMORY;
914*6236dae4SAndroid Build Coastguard Worker }
915*6236dae4SAndroid Build Coastguard Worker tmp = aprintf("%s, opaque=\"%s\"", response, opaque_quoted);
916*6236dae4SAndroid Build Coastguard Worker free(response);
917*6236dae4SAndroid Build Coastguard Worker free(opaque_quoted);
918*6236dae4SAndroid Build Coastguard Worker if(!tmp)
919*6236dae4SAndroid Build Coastguard Worker return CURLE_OUT_OF_MEMORY;
920*6236dae4SAndroid Build Coastguard Worker
921*6236dae4SAndroid Build Coastguard Worker response = tmp;
922*6236dae4SAndroid Build Coastguard Worker }
923*6236dae4SAndroid Build Coastguard Worker
924*6236dae4SAndroid Build Coastguard Worker if(digest->algorithm) {
925*6236dae4SAndroid Build Coastguard Worker /* Append the algorithm */
926*6236dae4SAndroid Build Coastguard Worker tmp = aprintf("%s, algorithm=%s", response, digest->algorithm);
927*6236dae4SAndroid Build Coastguard Worker free(response);
928*6236dae4SAndroid Build Coastguard Worker if(!tmp)
929*6236dae4SAndroid Build Coastguard Worker return CURLE_OUT_OF_MEMORY;
930*6236dae4SAndroid Build Coastguard Worker
931*6236dae4SAndroid Build Coastguard Worker response = tmp;
932*6236dae4SAndroid Build Coastguard Worker }
933*6236dae4SAndroid Build Coastguard Worker
934*6236dae4SAndroid Build Coastguard Worker if(digest->userhash) {
935*6236dae4SAndroid Build Coastguard Worker /* Append the userhash */
936*6236dae4SAndroid Build Coastguard Worker tmp = aprintf("%s, userhash=true", response);
937*6236dae4SAndroid Build Coastguard Worker free(response);
938*6236dae4SAndroid Build Coastguard Worker if(!tmp)
939*6236dae4SAndroid Build Coastguard Worker return CURLE_OUT_OF_MEMORY;
940*6236dae4SAndroid Build Coastguard Worker
941*6236dae4SAndroid Build Coastguard Worker response = tmp;
942*6236dae4SAndroid Build Coastguard Worker }
943*6236dae4SAndroid Build Coastguard Worker
944*6236dae4SAndroid Build Coastguard Worker /* Return the output */
945*6236dae4SAndroid Build Coastguard Worker *outptr = response;
946*6236dae4SAndroid Build Coastguard Worker *outlen = strlen(response);
947*6236dae4SAndroid Build Coastguard Worker
948*6236dae4SAndroid Build Coastguard Worker return CURLE_OK;
949*6236dae4SAndroid Build Coastguard Worker }
950*6236dae4SAndroid Build Coastguard Worker
951*6236dae4SAndroid Build Coastguard Worker /*
952*6236dae4SAndroid Build Coastguard Worker * Curl_auth_create_digest_http_message()
953*6236dae4SAndroid Build Coastguard Worker *
954*6236dae4SAndroid Build Coastguard Worker * This is used to generate an HTTP DIGEST response message ready for sending
955*6236dae4SAndroid Build Coastguard Worker * to the recipient.
956*6236dae4SAndroid Build Coastguard Worker *
957*6236dae4SAndroid Build Coastguard Worker * Parameters:
958*6236dae4SAndroid Build Coastguard Worker *
959*6236dae4SAndroid Build Coastguard Worker * data [in] - The session handle.
960*6236dae4SAndroid Build Coastguard Worker * userp [in] - The username.
961*6236dae4SAndroid Build Coastguard Worker * passwdp [in] - The user's password.
962*6236dae4SAndroid Build Coastguard Worker * request [in] - The HTTP request.
963*6236dae4SAndroid Build Coastguard Worker * uripath [in] - The path of the HTTP uri.
964*6236dae4SAndroid Build Coastguard Worker * digest [in/out] - The digest data struct being used and modified.
965*6236dae4SAndroid Build Coastguard Worker * outptr [in/out] - The address where a pointer to newly allocated memory
966*6236dae4SAndroid Build Coastguard Worker * holding the result will be stored upon completion.
967*6236dae4SAndroid Build Coastguard Worker * outlen [out] - The length of the output message.
968*6236dae4SAndroid Build Coastguard Worker *
969*6236dae4SAndroid Build Coastguard Worker * Returns CURLE_OK on success.
970*6236dae4SAndroid Build Coastguard Worker */
Curl_auth_create_digest_http_message(struct Curl_easy * data,const char * userp,const char * passwdp,const unsigned char * request,const unsigned char * uripath,struct digestdata * digest,char ** outptr,size_t * outlen)971*6236dae4SAndroid Build Coastguard Worker CURLcode Curl_auth_create_digest_http_message(struct Curl_easy *data,
972*6236dae4SAndroid Build Coastguard Worker const char *userp,
973*6236dae4SAndroid Build Coastguard Worker const char *passwdp,
974*6236dae4SAndroid Build Coastguard Worker const unsigned char *request,
975*6236dae4SAndroid Build Coastguard Worker const unsigned char *uripath,
976*6236dae4SAndroid Build Coastguard Worker struct digestdata *digest,
977*6236dae4SAndroid Build Coastguard Worker char **outptr, size_t *outlen)
978*6236dae4SAndroid Build Coastguard Worker {
979*6236dae4SAndroid Build Coastguard Worker if(digest->algo <= ALGO_MD5SESS)
980*6236dae4SAndroid Build Coastguard Worker return auth_create_digest_http_message(data, userp, passwdp,
981*6236dae4SAndroid Build Coastguard Worker request, uripath, digest,
982*6236dae4SAndroid Build Coastguard Worker outptr, outlen,
983*6236dae4SAndroid Build Coastguard Worker auth_digest_md5_to_ascii,
984*6236dae4SAndroid Build Coastguard Worker Curl_md5it);
985*6236dae4SAndroid Build Coastguard Worker
986*6236dae4SAndroid Build Coastguard Worker if(digest->algo <= ALGO_SHA256SESS)
987*6236dae4SAndroid Build Coastguard Worker return auth_create_digest_http_message(data, userp, passwdp,
988*6236dae4SAndroid Build Coastguard Worker request, uripath, digest,
989*6236dae4SAndroid Build Coastguard Worker outptr, outlen,
990*6236dae4SAndroid Build Coastguard Worker auth_digest_sha256_to_ascii,
991*6236dae4SAndroid Build Coastguard Worker Curl_sha256it);
992*6236dae4SAndroid Build Coastguard Worker #ifdef CURL_HAVE_SHA512_256
993*6236dae4SAndroid Build Coastguard Worker if(digest->algo <= ALGO_SHA512_256SESS)
994*6236dae4SAndroid Build Coastguard Worker return auth_create_digest_http_message(data, userp, passwdp,
995*6236dae4SAndroid Build Coastguard Worker request, uripath, digest,
996*6236dae4SAndroid Build Coastguard Worker outptr, outlen,
997*6236dae4SAndroid Build Coastguard Worker auth_digest_sha256_to_ascii,
998*6236dae4SAndroid Build Coastguard Worker Curl_sha512_256it);
999*6236dae4SAndroid Build Coastguard Worker #endif /* CURL_HAVE_SHA512_256 */
1000*6236dae4SAndroid Build Coastguard Worker
1001*6236dae4SAndroid Build Coastguard Worker /* Should be unreachable */
1002*6236dae4SAndroid Build Coastguard Worker return CURLE_BAD_CONTENT_ENCODING;
1003*6236dae4SAndroid Build Coastguard Worker }
1004*6236dae4SAndroid Build Coastguard Worker
1005*6236dae4SAndroid Build Coastguard Worker /*
1006*6236dae4SAndroid Build Coastguard Worker * Curl_auth_digest_cleanup()
1007*6236dae4SAndroid Build Coastguard Worker *
1008*6236dae4SAndroid Build Coastguard Worker * This is used to clean up the digest specific data.
1009*6236dae4SAndroid Build Coastguard Worker *
1010*6236dae4SAndroid Build Coastguard Worker * Parameters:
1011*6236dae4SAndroid Build Coastguard Worker *
1012*6236dae4SAndroid Build Coastguard Worker * digest [in/out] - The digest data struct being cleaned up.
1013*6236dae4SAndroid Build Coastguard Worker *
1014*6236dae4SAndroid Build Coastguard Worker */
Curl_auth_digest_cleanup(struct digestdata * digest)1015*6236dae4SAndroid Build Coastguard Worker void Curl_auth_digest_cleanup(struct digestdata *digest)
1016*6236dae4SAndroid Build Coastguard Worker {
1017*6236dae4SAndroid Build Coastguard Worker Curl_safefree(digest->nonce);
1018*6236dae4SAndroid Build Coastguard Worker Curl_safefree(digest->cnonce);
1019*6236dae4SAndroid Build Coastguard Worker Curl_safefree(digest->realm);
1020*6236dae4SAndroid Build Coastguard Worker Curl_safefree(digest->opaque);
1021*6236dae4SAndroid Build Coastguard Worker Curl_safefree(digest->qop);
1022*6236dae4SAndroid Build Coastguard Worker Curl_safefree(digest->algorithm);
1023*6236dae4SAndroid Build Coastguard Worker
1024*6236dae4SAndroid Build Coastguard Worker digest->nc = 0;
1025*6236dae4SAndroid Build Coastguard Worker digest->algo = ALGO_MD5; /* default algorithm */
1026*6236dae4SAndroid Build Coastguard Worker digest->stale = FALSE; /* default means normal, not stale */
1027*6236dae4SAndroid Build Coastguard Worker digest->userhash = FALSE;
1028*6236dae4SAndroid Build Coastguard Worker }
1029*6236dae4SAndroid Build Coastguard Worker #endif /* !USE_WINDOWS_SSPI */
1030*6236dae4SAndroid Build Coastguard Worker
1031*6236dae4SAndroid Build Coastguard Worker #endif /* !CURL_DISABLE_DIGEST_AUTH */
1032