/src/gdal/curl/lib/http_digest.c
Line  | Count  | Source (jump to first uncovered line)  | 
1  |  | /***************************************************************************  | 
2  |  |  *                                  _   _ ____  _  | 
3  |  |  *  Project                     ___| | | |  _ \| |  | 
4  |  |  *                             / __| | | | |_) | |  | 
5  |  |  *                            | (__| |_| |  _ <| |___  | 
6  |  |  *                             \___|\___/|_| \_\_____|  | 
7  |  |  *  | 
8  |  |  * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.  | 
9  |  |  *  | 
10  |  |  * This software is licensed as described in the file COPYING, which  | 
11  |  |  * you should have received as part of this distribution. The terms  | 
12  |  |  * are also available at https://curl.se/docs/copyright.html.  | 
13  |  |  *  | 
14  |  |  * You may opt to use, copy, modify, merge, publish, distribute and/or sell  | 
15  |  |  * copies of the Software, and permit persons to whom the Software is  | 
16  |  |  * furnished to do so, under the terms of the COPYING file.  | 
17  |  |  *  | 
18  |  |  * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY  | 
19  |  |  * KIND, either express or implied.  | 
20  |  |  *  | 
21  |  |  * SPDX-License-Identifier: curl  | 
22  |  |  *  | 
23  |  |  ***************************************************************************/  | 
24  |  |  | 
25  |  | #include "curl_setup.h"  | 
26  |  |  | 
27  |  | #if !defined(CURL_DISABLE_HTTP) && !defined(CURL_DISABLE_DIGEST_AUTH)  | 
28  |  |  | 
29  |  | #include "urldata.h"  | 
30  |  | #include "strcase.h"  | 
31  |  | #include "vauth/vauth.h"  | 
32  |  | #include "http_digest.h"  | 
33  |  | #include "curlx/strparse.h"  | 
34  |  |  | 
35  |  | /* The last 3 #include files should be in this order */  | 
36  |  | #include "curl_printf.h"  | 
37  |  | #include "curl_memory.h"  | 
38  |  | #include "memdebug.h"  | 
39  |  |  | 
40  |  | /* Test example headers:  | 
41  |  |  | 
42  |  | WWW-Authenticate: Digest realm="testrealm", nonce="1053604598"  | 
43  |  | Proxy-Authenticate: Digest realm="testrealm", nonce="1053604598"  | 
44  |  |  | 
45  |  | */  | 
46  |  |  | 
47  |  | CURLcode Curl_input_digest(struct Curl_easy *data,  | 
48  |  |                            bool proxy,  | 
49  |  |                            const char *header) /* rest of the *-authenticate:  | 
50  |  |                                                   header */  | 
51  | 0  | { | 
52  |  |   /* Point to the correct struct with this */  | 
53  | 0  |   struct digestdata *digest;  | 
54  |  | 
  | 
55  | 0  |   if(proxy) { | 
56  | 0  |     digest = &data->state.proxydigest;  | 
57  | 0  |   }  | 
58  | 0  |   else { | 
59  | 0  |     digest = &data->state.digest;  | 
60  | 0  |   }  | 
61  |  | 
  | 
62  | 0  |   if(!checkprefix("Digest", header) || !ISBLANK(header[6])) | 
63  | 0  |     return CURLE_BAD_CONTENT_ENCODING;  | 
64  |  |  | 
65  | 0  |   header += strlen("Digest"); | 
66  | 0  |   curlx_str_passblanks(&header);  | 
67  |  | 
  | 
68  | 0  |   return Curl_auth_decode_digest_http_message(header, digest);  | 
69  | 0  | }  | 
70  |  |  | 
71  |  | CURLcode Curl_output_digest(struct Curl_easy *data,  | 
72  |  |                             bool proxy,  | 
73  |  |                             const unsigned char *request,  | 
74  |  |                             const unsigned char *uripath)  | 
75  | 0  | { | 
76  | 0  |   CURLcode result;  | 
77  | 0  |   unsigned char *path = NULL;  | 
78  | 0  |   char *tmp = NULL;  | 
79  | 0  |   char *response;  | 
80  | 0  |   size_t len;  | 
81  | 0  |   bool have_chlg;  | 
82  |  |  | 
83  |  |   /* Point to the address of the pointer that holds the string to send to the  | 
84  |  |      server, which is for a plain host or for an HTTP proxy */  | 
85  | 0  |   char **allocuserpwd;  | 
86  |  |  | 
87  |  |   /* Point to the name and password for this */  | 
88  | 0  |   const char *userp;  | 
89  | 0  |   const char *passwdp;  | 
90  |  |  | 
91  |  |   /* Point to the correct struct with this */  | 
92  | 0  |   struct digestdata *digest;  | 
93  | 0  |   struct auth *authp;  | 
94  |  | 
  | 
95  | 0  |   if(proxy) { | 
96  |  | #ifdef CURL_DISABLE_PROXY  | 
97  |  |     return CURLE_NOT_BUILT_IN;  | 
98  |  | #else  | 
99  | 0  |     digest = &data->state.proxydigest;  | 
100  | 0  |     allocuserpwd = &data->state.aptr.proxyuserpwd;  | 
101  | 0  |     userp = data->state.aptr.proxyuser;  | 
102  | 0  |     passwdp = data->state.aptr.proxypasswd;  | 
103  | 0  |     authp = &data->state.authproxy;  | 
104  | 0  | #endif  | 
105  | 0  |   }  | 
106  | 0  |   else { | 
107  | 0  |     digest = &data->state.digest;  | 
108  | 0  |     allocuserpwd = &data->state.aptr.userpwd;  | 
109  | 0  |     userp = data->state.aptr.user;  | 
110  | 0  |     passwdp = data->state.aptr.passwd;  | 
111  | 0  |     authp = &data->state.authhost;  | 
112  | 0  |   }  | 
113  |  | 
  | 
114  | 0  |   Curl_safefree(*allocuserpwd);  | 
115  |  |  | 
116  |  |   /* not set means empty */  | 
117  | 0  |   if(!userp)  | 
118  | 0  |     userp = "";  | 
119  |  | 
  | 
120  | 0  |   if(!passwdp)  | 
121  | 0  |     passwdp = "";  | 
122  |  | 
  | 
123  |  | #if defined(USE_WINDOWS_SSPI)  | 
124  |  |   have_chlg = !!digest->input_token;  | 
125  |  | #else  | 
126  | 0  |   have_chlg = !!digest->nonce;  | 
127  | 0  | #endif  | 
128  |  | 
  | 
129  | 0  |   if(!have_chlg) { | 
130  | 0  |     authp->done = FALSE;  | 
131  | 0  |     return CURLE_OK;  | 
132  | 0  |   }  | 
133  |  |  | 
134  |  |   /* So IE browsers < v7 cut off the URI part at the query part when they  | 
135  |  |      evaluate the MD5 and some (IIS?) servers work with them so we may need to  | 
136  |  |      do the Digest IE-style. Note that the different ways cause different MD5  | 
137  |  |      sums to get sent.  | 
138  |  |  | 
139  |  |      Apache servers can be set to do the Digest IE-style automatically using  | 
140  |  |      the BrowserMatch feature:  | 
141  |  |      https://httpd.apache.org/docs/2.2/mod/mod_auth_digest.html#msie  | 
142  |  |  | 
143  |  |      Further details on Digest implementation differences:  | 
144  |  |      http://www.fngtps.com/2006/09/http-authentication  | 
145  |  |   */  | 
146  |  |  | 
147  | 0  |   if(authp->iestyle) { | 
148  | 0  |     tmp = strchr((const char *)uripath, '?');  | 
149  | 0  |     if(tmp) { | 
150  | 0  |       size_t urilen = tmp - (const char *)uripath;  | 
151  |  |       /* typecast is fine here since the value is always less than 32 bits */  | 
152  | 0  |       path = (unsigned char *) aprintf("%.*s", (int)urilen, uripath); | 
153  | 0  |     }  | 
154  | 0  |   }  | 
155  | 0  |   if(!tmp)  | 
156  | 0  |     path = (unsigned char *) strdup((const char *) uripath);  | 
157  |  | 
  | 
158  | 0  |   if(!path)  | 
159  | 0  |     return CURLE_OUT_OF_MEMORY;  | 
160  |  |  | 
161  | 0  |   result = Curl_auth_create_digest_http_message(data, userp, passwdp, request,  | 
162  | 0  |                                                 path, digest, &response, &len);  | 
163  | 0  |   free(path);  | 
164  | 0  |   if(result)  | 
165  | 0  |     return result;  | 
166  |  |  | 
167  | 0  |   *allocuserpwd = aprintf("%sAuthorization: Digest %s\r\n", | 
168  | 0  |                           proxy ? "Proxy-" : "",  | 
169  | 0  |                           response);  | 
170  | 0  |   free(response);  | 
171  | 0  |   if(!*allocuserpwd)  | 
172  | 0  |     return CURLE_OUT_OF_MEMORY;  | 
173  |  |  | 
174  | 0  |   authp->done = TRUE;  | 
175  |  | 
  | 
176  | 0  |   return CURLE_OK;  | 
177  | 0  | }  | 
178  |  |  | 
179  |  | void Curl_http_auth_cleanup_digest(struct Curl_easy *data)  | 
180  | 142k  | { | 
181  | 142k  |   Curl_auth_digest_cleanup(&data->state.digest);  | 
182  | 142k  |   Curl_auth_digest_cleanup(&data->state.proxydigest);  | 
183  | 142k  | }  | 
184  |  |  | 
185  |  | #endif  |