113498266Sopenharmony_ci/*************************************************************************** 213498266Sopenharmony_ci * _ _ ____ _ 313498266Sopenharmony_ci * Project ___| | | | _ \| | 413498266Sopenharmony_ci * / __| | | | |_) | | 513498266Sopenharmony_ci * | (__| |_| | _ <| |___ 613498266Sopenharmony_ci * \___|\___/|_| \_\_____| 713498266Sopenharmony_ci * 813498266Sopenharmony_ci * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al. 913498266Sopenharmony_ci * 1013498266Sopenharmony_ci * This software is licensed as described in the file COPYING, which 1113498266Sopenharmony_ci * you should have received as part of this distribution. The terms 1213498266Sopenharmony_ci * are also available at https://curl.se/docs/copyright.html. 1313498266Sopenharmony_ci * 1413498266Sopenharmony_ci * You may opt to use, copy, modify, merge, publish, distribute and/or sell 1513498266Sopenharmony_ci * copies of the Software, and permit persons to whom the Software is 1613498266Sopenharmony_ci * furnished to do so, under the terms of the COPYING file. 1713498266Sopenharmony_ci * 1813498266Sopenharmony_ci * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY 1913498266Sopenharmony_ci * KIND, either express or implied. 2013498266Sopenharmony_ci * 2113498266Sopenharmony_ci * SPDX-License-Identifier: curl 2213498266Sopenharmony_ci * 2313498266Sopenharmony_ci ***************************************************************************/ 2413498266Sopenharmony_ci 2513498266Sopenharmony_ci#include "curl_setup.h" 2613498266Sopenharmony_ci 2713498266Sopenharmony_ci#if !defined(CURL_DISABLE_HTTP) && !defined(CURL_DISABLE_DIGEST_AUTH) 2813498266Sopenharmony_ci 2913498266Sopenharmony_ci#include "urldata.h" 3013498266Sopenharmony_ci#include "strcase.h" 3113498266Sopenharmony_ci#include "vauth/vauth.h" 3213498266Sopenharmony_ci#include "http_digest.h" 3313498266Sopenharmony_ci 3413498266Sopenharmony_ci/* The last 3 #include files should be in this order */ 3513498266Sopenharmony_ci#include "curl_printf.h" 3613498266Sopenharmony_ci#include "curl_memory.h" 3713498266Sopenharmony_ci#include "memdebug.h" 3813498266Sopenharmony_ci 3913498266Sopenharmony_ci/* Test example headers: 4013498266Sopenharmony_ci 4113498266Sopenharmony_ciWWW-Authenticate: Digest realm="testrealm", nonce="1053604598" 4213498266Sopenharmony_ciProxy-Authenticate: Digest realm="testrealm", nonce="1053604598" 4313498266Sopenharmony_ci 4413498266Sopenharmony_ci*/ 4513498266Sopenharmony_ci 4613498266Sopenharmony_ciCURLcode Curl_input_digest(struct Curl_easy *data, 4713498266Sopenharmony_ci bool proxy, 4813498266Sopenharmony_ci const char *header) /* rest of the *-authenticate: 4913498266Sopenharmony_ci header */ 5013498266Sopenharmony_ci{ 5113498266Sopenharmony_ci /* Point to the correct struct with this */ 5213498266Sopenharmony_ci struct digestdata *digest; 5313498266Sopenharmony_ci 5413498266Sopenharmony_ci if(proxy) { 5513498266Sopenharmony_ci digest = &data->state.proxydigest; 5613498266Sopenharmony_ci } 5713498266Sopenharmony_ci else { 5813498266Sopenharmony_ci digest = &data->state.digest; 5913498266Sopenharmony_ci } 6013498266Sopenharmony_ci 6113498266Sopenharmony_ci if(!checkprefix("Digest", header) || !ISBLANK(header[6])) 6213498266Sopenharmony_ci return CURLE_BAD_CONTENT_ENCODING; 6313498266Sopenharmony_ci 6413498266Sopenharmony_ci header += strlen("Digest"); 6513498266Sopenharmony_ci while(*header && ISBLANK(*header)) 6613498266Sopenharmony_ci header++; 6713498266Sopenharmony_ci 6813498266Sopenharmony_ci return Curl_auth_decode_digest_http_message(header, digest); 6913498266Sopenharmony_ci} 7013498266Sopenharmony_ci 7113498266Sopenharmony_ciCURLcode Curl_output_digest(struct Curl_easy *data, 7213498266Sopenharmony_ci bool proxy, 7313498266Sopenharmony_ci const unsigned char *request, 7413498266Sopenharmony_ci const unsigned char *uripath) 7513498266Sopenharmony_ci{ 7613498266Sopenharmony_ci CURLcode result; 7713498266Sopenharmony_ci unsigned char *path = NULL; 7813498266Sopenharmony_ci char *tmp = NULL; 7913498266Sopenharmony_ci char *response; 8013498266Sopenharmony_ci size_t len; 8113498266Sopenharmony_ci bool have_chlg; 8213498266Sopenharmony_ci 8313498266Sopenharmony_ci /* Point to the address of the pointer that holds the string to send to the 8413498266Sopenharmony_ci server, which is for a plain host or for an HTTP proxy */ 8513498266Sopenharmony_ci char **allocuserpwd; 8613498266Sopenharmony_ci 8713498266Sopenharmony_ci /* Point to the name and password for this */ 8813498266Sopenharmony_ci const char *userp; 8913498266Sopenharmony_ci const char *passwdp; 9013498266Sopenharmony_ci 9113498266Sopenharmony_ci /* Point to the correct struct with this */ 9213498266Sopenharmony_ci struct digestdata *digest; 9313498266Sopenharmony_ci struct auth *authp; 9413498266Sopenharmony_ci 9513498266Sopenharmony_ci if(proxy) { 9613498266Sopenharmony_ci#ifdef CURL_DISABLE_PROXY 9713498266Sopenharmony_ci return CURLE_NOT_BUILT_IN; 9813498266Sopenharmony_ci#else 9913498266Sopenharmony_ci digest = &data->state.proxydigest; 10013498266Sopenharmony_ci allocuserpwd = &data->state.aptr.proxyuserpwd; 10113498266Sopenharmony_ci userp = data->state.aptr.proxyuser; 10213498266Sopenharmony_ci passwdp = data->state.aptr.proxypasswd; 10313498266Sopenharmony_ci authp = &data->state.authproxy; 10413498266Sopenharmony_ci#endif 10513498266Sopenharmony_ci } 10613498266Sopenharmony_ci else { 10713498266Sopenharmony_ci digest = &data->state.digest; 10813498266Sopenharmony_ci allocuserpwd = &data->state.aptr.userpwd; 10913498266Sopenharmony_ci userp = data->state.aptr.user; 11013498266Sopenharmony_ci passwdp = data->state.aptr.passwd; 11113498266Sopenharmony_ci authp = &data->state.authhost; 11213498266Sopenharmony_ci } 11313498266Sopenharmony_ci 11413498266Sopenharmony_ci Curl_safefree(*allocuserpwd); 11513498266Sopenharmony_ci 11613498266Sopenharmony_ci /* not set means empty */ 11713498266Sopenharmony_ci if(!userp) 11813498266Sopenharmony_ci userp = ""; 11913498266Sopenharmony_ci 12013498266Sopenharmony_ci if(!passwdp) 12113498266Sopenharmony_ci passwdp = ""; 12213498266Sopenharmony_ci 12313498266Sopenharmony_ci#if defined(USE_WINDOWS_SSPI) 12413498266Sopenharmony_ci have_chlg = digest->input_token ? TRUE : FALSE; 12513498266Sopenharmony_ci#else 12613498266Sopenharmony_ci have_chlg = digest->nonce ? TRUE : FALSE; 12713498266Sopenharmony_ci#endif 12813498266Sopenharmony_ci 12913498266Sopenharmony_ci if(!have_chlg) { 13013498266Sopenharmony_ci authp->done = FALSE; 13113498266Sopenharmony_ci return CURLE_OK; 13213498266Sopenharmony_ci } 13313498266Sopenharmony_ci 13413498266Sopenharmony_ci /* So IE browsers < v7 cut off the URI part at the query part when they 13513498266Sopenharmony_ci evaluate the MD5 and some (IIS?) servers work with them so we may need to 13613498266Sopenharmony_ci do the Digest IE-style. Note that the different ways cause different MD5 13713498266Sopenharmony_ci sums to get sent. 13813498266Sopenharmony_ci 13913498266Sopenharmony_ci Apache servers can be set to do the Digest IE-style automatically using 14013498266Sopenharmony_ci the BrowserMatch feature: 14113498266Sopenharmony_ci https://httpd.apache.org/docs/2.2/mod/mod_auth_digest.html#msie 14213498266Sopenharmony_ci 14313498266Sopenharmony_ci Further details on Digest implementation differences: 14413498266Sopenharmony_ci http://www.fngtps.com/2006/09/http-authentication 14513498266Sopenharmony_ci */ 14613498266Sopenharmony_ci 14713498266Sopenharmony_ci if(authp->iestyle) { 14813498266Sopenharmony_ci tmp = strchr((char *)uripath, '?'); 14913498266Sopenharmony_ci if(tmp) { 15013498266Sopenharmony_ci size_t urilen = tmp - (char *)uripath; 15113498266Sopenharmony_ci /* typecast is fine here since the value is always less than 32 bits */ 15213498266Sopenharmony_ci path = (unsigned char *) aprintf("%.*s", (int)urilen, uripath); 15313498266Sopenharmony_ci } 15413498266Sopenharmony_ci } 15513498266Sopenharmony_ci if(!tmp) 15613498266Sopenharmony_ci path = (unsigned char *) strdup((char *) uripath); 15713498266Sopenharmony_ci 15813498266Sopenharmony_ci if(!path) 15913498266Sopenharmony_ci return CURLE_OUT_OF_MEMORY; 16013498266Sopenharmony_ci 16113498266Sopenharmony_ci result = Curl_auth_create_digest_http_message(data, userp, passwdp, request, 16213498266Sopenharmony_ci path, digest, &response, &len); 16313498266Sopenharmony_ci free(path); 16413498266Sopenharmony_ci if(result) 16513498266Sopenharmony_ci return result; 16613498266Sopenharmony_ci 16713498266Sopenharmony_ci *allocuserpwd = aprintf("%sAuthorization: Digest %s\r\n", 16813498266Sopenharmony_ci proxy ? "Proxy-" : "", 16913498266Sopenharmony_ci response); 17013498266Sopenharmony_ci free(response); 17113498266Sopenharmony_ci if(!*allocuserpwd) 17213498266Sopenharmony_ci return CURLE_OUT_OF_MEMORY; 17313498266Sopenharmony_ci 17413498266Sopenharmony_ci authp->done = TRUE; 17513498266Sopenharmony_ci 17613498266Sopenharmony_ci return CURLE_OK; 17713498266Sopenharmony_ci} 17813498266Sopenharmony_ci 17913498266Sopenharmony_civoid Curl_http_auth_cleanup_digest(struct Curl_easy *data) 18013498266Sopenharmony_ci{ 18113498266Sopenharmony_ci Curl_auth_digest_cleanup(&data->state.digest); 18213498266Sopenharmony_ci Curl_auth_digest_cleanup(&data->state.proxydigest); 18313498266Sopenharmony_ci} 18413498266Sopenharmony_ci 18513498266Sopenharmony_ci#endif 186