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) Steve Holme, <[email protected]>.
9*6236dae4SAndroid Build Coastguard Worker * Copyright (C) Daniel Stenberg, <[email protected]>, et al.
10*6236dae4SAndroid Build Coastguard Worker *
11*6236dae4SAndroid Build Coastguard Worker * This software is licensed as described in the file COPYING, which
12*6236dae4SAndroid Build Coastguard Worker * you should have received as part of this distribution. The terms
13*6236dae4SAndroid Build Coastguard Worker * are also available at https://curl.se/docs/copyright.html.
14*6236dae4SAndroid Build Coastguard Worker *
15*6236dae4SAndroid Build Coastguard Worker * You may opt to use, copy, modify, merge, publish, distribute and/or sell
16*6236dae4SAndroid Build Coastguard Worker * copies of the Software, and permit persons to whom the Software is
17*6236dae4SAndroid Build Coastguard Worker * furnished to do so, under the terms of the COPYING file.
18*6236dae4SAndroid Build Coastguard Worker *
19*6236dae4SAndroid Build Coastguard Worker * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
20*6236dae4SAndroid Build Coastguard Worker * KIND, either express or implied.
21*6236dae4SAndroid Build Coastguard Worker *
22*6236dae4SAndroid Build Coastguard Worker * SPDX-License-Identifier: curl
23*6236dae4SAndroid Build Coastguard Worker *
24*6236dae4SAndroid Build Coastguard Worker * RFC2831 DIGEST-MD5 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 #if defined(USE_WINDOWS_SSPI) && !defined(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 "warnless.h"
38*6236dae4SAndroid Build Coastguard Worker #include "curl_multibyte.h"
39*6236dae4SAndroid Build Coastguard Worker #include "sendf.h"
40*6236dae4SAndroid Build Coastguard Worker #include "strdup.h"
41*6236dae4SAndroid Build Coastguard Worker #include "strcase.h"
42*6236dae4SAndroid Build Coastguard Worker #include "strerror.h"
43*6236dae4SAndroid Build Coastguard Worker
44*6236dae4SAndroid Build Coastguard Worker /* The last #include files should be: */
45*6236dae4SAndroid Build Coastguard Worker #include "curl_memory.h"
46*6236dae4SAndroid Build Coastguard Worker #include "memdebug.h"
47*6236dae4SAndroid Build Coastguard Worker
48*6236dae4SAndroid Build Coastguard Worker /*
49*6236dae4SAndroid Build Coastguard Worker * Curl_auth_is_digest_supported()
50*6236dae4SAndroid Build Coastguard Worker *
51*6236dae4SAndroid Build Coastguard Worker * This is used to evaluate if DIGEST is supported.
52*6236dae4SAndroid Build Coastguard Worker *
53*6236dae4SAndroid Build Coastguard Worker * Parameters: None
54*6236dae4SAndroid Build Coastguard Worker *
55*6236dae4SAndroid Build Coastguard Worker * Returns TRUE if DIGEST is supported by Windows SSPI.
56*6236dae4SAndroid Build Coastguard Worker */
Curl_auth_is_digest_supported(void)57*6236dae4SAndroid Build Coastguard Worker bool Curl_auth_is_digest_supported(void)
58*6236dae4SAndroid Build Coastguard Worker {
59*6236dae4SAndroid Build Coastguard Worker PSecPkgInfo SecurityPackage;
60*6236dae4SAndroid Build Coastguard Worker SECURITY_STATUS status;
61*6236dae4SAndroid Build Coastguard Worker
62*6236dae4SAndroid Build Coastguard Worker /* Query the security package for Digest */
63*6236dae4SAndroid Build Coastguard Worker status =
64*6236dae4SAndroid Build Coastguard Worker Curl_pSecFn->QuerySecurityPackageInfo((TCHAR *) TEXT(SP_NAME_DIGEST),
65*6236dae4SAndroid Build Coastguard Worker &SecurityPackage);
66*6236dae4SAndroid Build Coastguard Worker
67*6236dae4SAndroid Build Coastguard Worker /* Release the package buffer as it is not required anymore */
68*6236dae4SAndroid Build Coastguard Worker if(status == SEC_E_OK) {
69*6236dae4SAndroid Build Coastguard Worker Curl_pSecFn->FreeContextBuffer(SecurityPackage);
70*6236dae4SAndroid Build Coastguard Worker }
71*6236dae4SAndroid Build Coastguard Worker
72*6236dae4SAndroid Build Coastguard Worker return (status == SEC_E_OK);
73*6236dae4SAndroid Build Coastguard Worker }
74*6236dae4SAndroid Build Coastguard Worker
75*6236dae4SAndroid Build Coastguard Worker /*
76*6236dae4SAndroid Build Coastguard Worker * Curl_auth_create_digest_md5_message()
77*6236dae4SAndroid Build Coastguard Worker *
78*6236dae4SAndroid Build Coastguard Worker * This is used to generate an already encoded DIGEST-MD5 response message
79*6236dae4SAndroid Build Coastguard Worker * ready for sending to the recipient.
80*6236dae4SAndroid Build Coastguard Worker *
81*6236dae4SAndroid Build Coastguard Worker * Parameters:
82*6236dae4SAndroid Build Coastguard Worker *
83*6236dae4SAndroid Build Coastguard Worker * data [in] - The session handle.
84*6236dae4SAndroid Build Coastguard Worker * chlg [in] - The challenge message.
85*6236dae4SAndroid Build Coastguard Worker * userp [in] - The username in the format User or Domain\User.
86*6236dae4SAndroid Build Coastguard Worker * passwdp [in] - The user's password.
87*6236dae4SAndroid Build Coastguard Worker * service [in] - The service type such as http, smtp, pop or imap.
88*6236dae4SAndroid Build Coastguard Worker * out [out] - The result storage.
89*6236dae4SAndroid Build Coastguard Worker *
90*6236dae4SAndroid Build Coastguard Worker * Returns CURLE_OK on success.
91*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)92*6236dae4SAndroid Build Coastguard Worker CURLcode Curl_auth_create_digest_md5_message(struct Curl_easy *data,
93*6236dae4SAndroid Build Coastguard Worker const struct bufref *chlg,
94*6236dae4SAndroid Build Coastguard Worker const char *userp,
95*6236dae4SAndroid Build Coastguard Worker const char *passwdp,
96*6236dae4SAndroid Build Coastguard Worker const char *service,
97*6236dae4SAndroid Build Coastguard Worker struct bufref *out)
98*6236dae4SAndroid Build Coastguard Worker {
99*6236dae4SAndroid Build Coastguard Worker CURLcode result = CURLE_OK;
100*6236dae4SAndroid Build Coastguard Worker TCHAR *spn = NULL;
101*6236dae4SAndroid Build Coastguard Worker size_t token_max = 0;
102*6236dae4SAndroid Build Coastguard Worker unsigned char *output_token = NULL;
103*6236dae4SAndroid Build Coastguard Worker CredHandle credentials;
104*6236dae4SAndroid Build Coastguard Worker CtxtHandle context;
105*6236dae4SAndroid Build Coastguard Worker PSecPkgInfo SecurityPackage;
106*6236dae4SAndroid Build Coastguard Worker SEC_WINNT_AUTH_IDENTITY identity;
107*6236dae4SAndroid Build Coastguard Worker SEC_WINNT_AUTH_IDENTITY *p_identity;
108*6236dae4SAndroid Build Coastguard Worker SecBuffer chlg_buf;
109*6236dae4SAndroid Build Coastguard Worker SecBuffer resp_buf;
110*6236dae4SAndroid Build Coastguard Worker SecBufferDesc chlg_desc;
111*6236dae4SAndroid Build Coastguard Worker SecBufferDesc resp_desc;
112*6236dae4SAndroid Build Coastguard Worker SECURITY_STATUS status;
113*6236dae4SAndroid Build Coastguard Worker unsigned long attrs;
114*6236dae4SAndroid Build Coastguard Worker TimeStamp expiry; /* For Windows 9x compatibility of SSPI calls */
115*6236dae4SAndroid Build Coastguard Worker
116*6236dae4SAndroid Build Coastguard Worker /* Ensure we have a valid challenge message */
117*6236dae4SAndroid Build Coastguard Worker if(!Curl_bufref_len(chlg)) {
118*6236dae4SAndroid Build Coastguard Worker infof(data, "DIGEST-MD5 handshake failure (empty challenge message)");
119*6236dae4SAndroid Build Coastguard Worker return CURLE_BAD_CONTENT_ENCODING;
120*6236dae4SAndroid Build Coastguard Worker }
121*6236dae4SAndroid Build Coastguard Worker
122*6236dae4SAndroid Build Coastguard Worker /* Query the security package for DigestSSP */
123*6236dae4SAndroid Build Coastguard Worker status =
124*6236dae4SAndroid Build Coastguard Worker Curl_pSecFn->QuerySecurityPackageInfo((TCHAR *) TEXT(SP_NAME_DIGEST),
125*6236dae4SAndroid Build Coastguard Worker &SecurityPackage);
126*6236dae4SAndroid Build Coastguard Worker if(status != SEC_E_OK) {
127*6236dae4SAndroid Build Coastguard Worker failf(data, "SSPI: could not get auth info");
128*6236dae4SAndroid Build Coastguard Worker return CURLE_AUTH_ERROR;
129*6236dae4SAndroid Build Coastguard Worker }
130*6236dae4SAndroid Build Coastguard Worker
131*6236dae4SAndroid Build Coastguard Worker token_max = SecurityPackage->cbMaxToken;
132*6236dae4SAndroid Build Coastguard Worker
133*6236dae4SAndroid Build Coastguard Worker /* Release the package buffer as it is not required anymore */
134*6236dae4SAndroid Build Coastguard Worker Curl_pSecFn->FreeContextBuffer(SecurityPackage);
135*6236dae4SAndroid Build Coastguard Worker
136*6236dae4SAndroid Build Coastguard Worker /* Allocate our response buffer */
137*6236dae4SAndroid Build Coastguard Worker output_token = malloc(token_max);
138*6236dae4SAndroid Build Coastguard Worker if(!output_token)
139*6236dae4SAndroid Build Coastguard Worker return CURLE_OUT_OF_MEMORY;
140*6236dae4SAndroid Build Coastguard Worker
141*6236dae4SAndroid Build Coastguard Worker /* Generate our SPN */
142*6236dae4SAndroid Build Coastguard Worker spn = Curl_auth_build_spn(service, data->conn->host.name, NULL);
143*6236dae4SAndroid Build Coastguard Worker if(!spn) {
144*6236dae4SAndroid Build Coastguard Worker free(output_token);
145*6236dae4SAndroid Build Coastguard Worker return CURLE_OUT_OF_MEMORY;
146*6236dae4SAndroid Build Coastguard Worker }
147*6236dae4SAndroid Build Coastguard Worker
148*6236dae4SAndroid Build Coastguard Worker if(userp && *userp) {
149*6236dae4SAndroid Build Coastguard Worker /* Populate our identity structure */
150*6236dae4SAndroid Build Coastguard Worker result = Curl_create_sspi_identity(userp, passwdp, &identity);
151*6236dae4SAndroid Build Coastguard Worker if(result) {
152*6236dae4SAndroid Build Coastguard Worker free(spn);
153*6236dae4SAndroid Build Coastguard Worker free(output_token);
154*6236dae4SAndroid Build Coastguard Worker return result;
155*6236dae4SAndroid Build Coastguard Worker }
156*6236dae4SAndroid Build Coastguard Worker
157*6236dae4SAndroid Build Coastguard Worker /* Allow proper cleanup of the identity structure */
158*6236dae4SAndroid Build Coastguard Worker p_identity = &identity;
159*6236dae4SAndroid Build Coastguard Worker }
160*6236dae4SAndroid Build Coastguard Worker else
161*6236dae4SAndroid Build Coastguard Worker /* Use the current Windows user */
162*6236dae4SAndroid Build Coastguard Worker p_identity = NULL;
163*6236dae4SAndroid Build Coastguard Worker
164*6236dae4SAndroid Build Coastguard Worker /* Acquire our credentials handle */
165*6236dae4SAndroid Build Coastguard Worker status = Curl_pSecFn->AcquireCredentialsHandle(NULL,
166*6236dae4SAndroid Build Coastguard Worker (TCHAR *) TEXT(SP_NAME_DIGEST),
167*6236dae4SAndroid Build Coastguard Worker SECPKG_CRED_OUTBOUND, NULL,
168*6236dae4SAndroid Build Coastguard Worker p_identity, NULL, NULL,
169*6236dae4SAndroid Build Coastguard Worker &credentials, &expiry);
170*6236dae4SAndroid Build Coastguard Worker
171*6236dae4SAndroid Build Coastguard Worker if(status != SEC_E_OK) {
172*6236dae4SAndroid Build Coastguard Worker Curl_sspi_free_identity(p_identity);
173*6236dae4SAndroid Build Coastguard Worker free(spn);
174*6236dae4SAndroid Build Coastguard Worker free(output_token);
175*6236dae4SAndroid Build Coastguard Worker return CURLE_LOGIN_DENIED;
176*6236dae4SAndroid Build Coastguard Worker }
177*6236dae4SAndroid Build Coastguard Worker
178*6236dae4SAndroid Build Coastguard Worker /* Setup the challenge "input" security buffer */
179*6236dae4SAndroid Build Coastguard Worker chlg_desc.ulVersion = SECBUFFER_VERSION;
180*6236dae4SAndroid Build Coastguard Worker chlg_desc.cBuffers = 1;
181*6236dae4SAndroid Build Coastguard Worker chlg_desc.pBuffers = &chlg_buf;
182*6236dae4SAndroid Build Coastguard Worker chlg_buf.BufferType = SECBUFFER_TOKEN;
183*6236dae4SAndroid Build Coastguard Worker chlg_buf.pvBuffer = (void *) Curl_bufref_ptr(chlg);
184*6236dae4SAndroid Build Coastguard Worker chlg_buf.cbBuffer = curlx_uztoul(Curl_bufref_len(chlg));
185*6236dae4SAndroid Build Coastguard Worker
186*6236dae4SAndroid Build Coastguard Worker /* Setup the response "output" security buffer */
187*6236dae4SAndroid Build Coastguard Worker resp_desc.ulVersion = SECBUFFER_VERSION;
188*6236dae4SAndroid Build Coastguard Worker resp_desc.cBuffers = 1;
189*6236dae4SAndroid Build Coastguard Worker resp_desc.pBuffers = &resp_buf;
190*6236dae4SAndroid Build Coastguard Worker resp_buf.BufferType = SECBUFFER_TOKEN;
191*6236dae4SAndroid Build Coastguard Worker resp_buf.pvBuffer = output_token;
192*6236dae4SAndroid Build Coastguard Worker resp_buf.cbBuffer = curlx_uztoul(token_max);
193*6236dae4SAndroid Build Coastguard Worker
194*6236dae4SAndroid Build Coastguard Worker /* Generate our response message */
195*6236dae4SAndroid Build Coastguard Worker status = Curl_pSecFn->InitializeSecurityContext(&credentials, NULL, spn,
196*6236dae4SAndroid Build Coastguard Worker 0, 0, 0, &chlg_desc, 0,
197*6236dae4SAndroid Build Coastguard Worker &context, &resp_desc, &attrs,
198*6236dae4SAndroid Build Coastguard Worker &expiry);
199*6236dae4SAndroid Build Coastguard Worker
200*6236dae4SAndroid Build Coastguard Worker if(status == SEC_I_COMPLETE_NEEDED ||
201*6236dae4SAndroid Build Coastguard Worker status == SEC_I_COMPLETE_AND_CONTINUE)
202*6236dae4SAndroid Build Coastguard Worker Curl_pSecFn->CompleteAuthToken(&credentials, &resp_desc);
203*6236dae4SAndroid Build Coastguard Worker else if(status != SEC_E_OK && status != SEC_I_CONTINUE_NEEDED) {
204*6236dae4SAndroid Build Coastguard Worker #if !defined(CURL_DISABLE_VERBOSE_STRINGS)
205*6236dae4SAndroid Build Coastguard Worker char buffer[STRERROR_LEN];
206*6236dae4SAndroid Build Coastguard Worker #endif
207*6236dae4SAndroid Build Coastguard Worker
208*6236dae4SAndroid Build Coastguard Worker Curl_pSecFn->FreeCredentialsHandle(&credentials);
209*6236dae4SAndroid Build Coastguard Worker Curl_sspi_free_identity(p_identity);
210*6236dae4SAndroid Build Coastguard Worker free(spn);
211*6236dae4SAndroid Build Coastguard Worker free(output_token);
212*6236dae4SAndroid Build Coastguard Worker
213*6236dae4SAndroid Build Coastguard Worker if(status == SEC_E_INSUFFICIENT_MEMORY)
214*6236dae4SAndroid Build Coastguard Worker return CURLE_OUT_OF_MEMORY;
215*6236dae4SAndroid Build Coastguard Worker
216*6236dae4SAndroid Build Coastguard Worker #if !defined(CURL_DISABLE_VERBOSE_STRINGS)
217*6236dae4SAndroid Build Coastguard Worker infof(data, "schannel: InitializeSecurityContext failed: %s",
218*6236dae4SAndroid Build Coastguard Worker Curl_sspi_strerror(status, buffer, sizeof(buffer)));
219*6236dae4SAndroid Build Coastguard Worker #endif
220*6236dae4SAndroid Build Coastguard Worker
221*6236dae4SAndroid Build Coastguard Worker return CURLE_AUTH_ERROR;
222*6236dae4SAndroid Build Coastguard Worker }
223*6236dae4SAndroid Build Coastguard Worker
224*6236dae4SAndroid Build Coastguard Worker /* Return the response. */
225*6236dae4SAndroid Build Coastguard Worker Curl_bufref_set(out, output_token, resp_buf.cbBuffer, curl_free);
226*6236dae4SAndroid Build Coastguard Worker
227*6236dae4SAndroid Build Coastguard Worker /* Free our handles */
228*6236dae4SAndroid Build Coastguard Worker Curl_pSecFn->DeleteSecurityContext(&context);
229*6236dae4SAndroid Build Coastguard Worker Curl_pSecFn->FreeCredentialsHandle(&credentials);
230*6236dae4SAndroid Build Coastguard Worker
231*6236dae4SAndroid Build Coastguard Worker /* Free the identity structure */
232*6236dae4SAndroid Build Coastguard Worker Curl_sspi_free_identity(p_identity);
233*6236dae4SAndroid Build Coastguard Worker
234*6236dae4SAndroid Build Coastguard Worker /* Free the SPN */
235*6236dae4SAndroid Build Coastguard Worker free(spn);
236*6236dae4SAndroid Build Coastguard Worker
237*6236dae4SAndroid Build Coastguard Worker return result;
238*6236dae4SAndroid Build Coastguard Worker }
239*6236dae4SAndroid Build Coastguard Worker
240*6236dae4SAndroid Build Coastguard Worker /*
241*6236dae4SAndroid Build Coastguard Worker * Curl_override_sspi_http_realm()
242*6236dae4SAndroid Build Coastguard Worker *
243*6236dae4SAndroid Build Coastguard Worker * This is used to populate the domain in a SSPI identity structure
244*6236dae4SAndroid Build Coastguard Worker * The realm is extracted from the challenge message and used as the
245*6236dae4SAndroid Build Coastguard Worker * domain if it is not already explicitly set.
246*6236dae4SAndroid Build Coastguard Worker *
247*6236dae4SAndroid Build Coastguard Worker * Parameters:
248*6236dae4SAndroid Build Coastguard Worker *
249*6236dae4SAndroid Build Coastguard Worker * chlg [in] - The challenge message.
250*6236dae4SAndroid Build Coastguard Worker * identity [in/out] - The identity structure.
251*6236dae4SAndroid Build Coastguard Worker *
252*6236dae4SAndroid Build Coastguard Worker * Returns CURLE_OK on success.
253*6236dae4SAndroid Build Coastguard Worker */
Curl_override_sspi_http_realm(const char * chlg,SEC_WINNT_AUTH_IDENTITY * identity)254*6236dae4SAndroid Build Coastguard Worker CURLcode Curl_override_sspi_http_realm(const char *chlg,
255*6236dae4SAndroid Build Coastguard Worker SEC_WINNT_AUTH_IDENTITY *identity)
256*6236dae4SAndroid Build Coastguard Worker {
257*6236dae4SAndroid Build Coastguard Worker xcharp_u domain, dup_domain;
258*6236dae4SAndroid Build Coastguard Worker
259*6236dae4SAndroid Build Coastguard Worker /* If domain is blank or unset, check challenge message for realm */
260*6236dae4SAndroid Build Coastguard Worker if(!identity->Domain || !identity->DomainLength) {
261*6236dae4SAndroid Build Coastguard Worker for(;;) {
262*6236dae4SAndroid Build Coastguard Worker char value[DIGEST_MAX_VALUE_LENGTH];
263*6236dae4SAndroid Build Coastguard Worker char content[DIGEST_MAX_CONTENT_LENGTH];
264*6236dae4SAndroid Build Coastguard Worker
265*6236dae4SAndroid Build Coastguard Worker /* Pass all additional spaces here */
266*6236dae4SAndroid Build Coastguard Worker while(*chlg && ISBLANK(*chlg))
267*6236dae4SAndroid Build Coastguard Worker chlg++;
268*6236dae4SAndroid Build Coastguard Worker
269*6236dae4SAndroid Build Coastguard Worker /* Extract a value=content pair */
270*6236dae4SAndroid Build Coastguard Worker if(Curl_auth_digest_get_pair(chlg, value, content, &chlg)) {
271*6236dae4SAndroid Build Coastguard Worker if(strcasecompare(value, "realm")) {
272*6236dae4SAndroid Build Coastguard Worker
273*6236dae4SAndroid Build Coastguard Worker /* Setup identity's domain and length */
274*6236dae4SAndroid Build Coastguard Worker domain.tchar_ptr = curlx_convert_UTF8_to_tchar((char *) content);
275*6236dae4SAndroid Build Coastguard Worker if(!domain.tchar_ptr)
276*6236dae4SAndroid Build Coastguard Worker return CURLE_OUT_OF_MEMORY;
277*6236dae4SAndroid Build Coastguard Worker
278*6236dae4SAndroid Build Coastguard Worker dup_domain.tchar_ptr = _tcsdup(domain.tchar_ptr);
279*6236dae4SAndroid Build Coastguard Worker if(!dup_domain.tchar_ptr) {
280*6236dae4SAndroid Build Coastguard Worker curlx_unicodefree(domain.tchar_ptr);
281*6236dae4SAndroid Build Coastguard Worker return CURLE_OUT_OF_MEMORY;
282*6236dae4SAndroid Build Coastguard Worker }
283*6236dae4SAndroid Build Coastguard Worker
284*6236dae4SAndroid Build Coastguard Worker free(identity->Domain);
285*6236dae4SAndroid Build Coastguard Worker identity->Domain = dup_domain.tbyte_ptr;
286*6236dae4SAndroid Build Coastguard Worker identity->DomainLength = curlx_uztoul(_tcslen(dup_domain.tchar_ptr));
287*6236dae4SAndroid Build Coastguard Worker dup_domain.tchar_ptr = NULL;
288*6236dae4SAndroid Build Coastguard Worker
289*6236dae4SAndroid Build Coastguard Worker curlx_unicodefree(domain.tchar_ptr);
290*6236dae4SAndroid Build Coastguard Worker }
291*6236dae4SAndroid Build Coastguard Worker else {
292*6236dae4SAndroid Build Coastguard Worker /* Unknown specifier, ignore it! */
293*6236dae4SAndroid Build Coastguard Worker }
294*6236dae4SAndroid Build Coastguard Worker }
295*6236dae4SAndroid Build Coastguard Worker else
296*6236dae4SAndroid Build Coastguard Worker break; /* We are done here */
297*6236dae4SAndroid Build Coastguard Worker
298*6236dae4SAndroid Build Coastguard Worker /* Pass all additional spaces here */
299*6236dae4SAndroid Build Coastguard Worker while(*chlg && ISBLANK(*chlg))
300*6236dae4SAndroid Build Coastguard Worker chlg++;
301*6236dae4SAndroid Build Coastguard Worker
302*6236dae4SAndroid Build Coastguard Worker /* Allow the list to be comma-separated */
303*6236dae4SAndroid Build Coastguard Worker if(',' == *chlg)
304*6236dae4SAndroid Build Coastguard Worker chlg++;
305*6236dae4SAndroid Build Coastguard Worker }
306*6236dae4SAndroid Build Coastguard Worker }
307*6236dae4SAndroid Build Coastguard Worker
308*6236dae4SAndroid Build Coastguard Worker return CURLE_OK;
309*6236dae4SAndroid Build Coastguard Worker }
310*6236dae4SAndroid Build Coastguard Worker
311*6236dae4SAndroid Build Coastguard Worker /*
312*6236dae4SAndroid Build Coastguard Worker * Curl_auth_decode_digest_http_message()
313*6236dae4SAndroid Build Coastguard Worker *
314*6236dae4SAndroid Build Coastguard Worker * This is used to decode an HTTP DIGEST challenge message into the separate
315*6236dae4SAndroid Build Coastguard Worker * attributes.
316*6236dae4SAndroid Build Coastguard Worker *
317*6236dae4SAndroid Build Coastguard Worker * Parameters:
318*6236dae4SAndroid Build Coastguard Worker *
319*6236dae4SAndroid Build Coastguard Worker * chlg [in] - The challenge message.
320*6236dae4SAndroid Build Coastguard Worker * digest [in/out] - The digest data struct being used and modified.
321*6236dae4SAndroid Build Coastguard Worker *
322*6236dae4SAndroid Build Coastguard Worker * Returns CURLE_OK on success.
323*6236dae4SAndroid Build Coastguard Worker */
Curl_auth_decode_digest_http_message(const char * chlg,struct digestdata * digest)324*6236dae4SAndroid Build Coastguard Worker CURLcode Curl_auth_decode_digest_http_message(const char *chlg,
325*6236dae4SAndroid Build Coastguard Worker struct digestdata *digest)
326*6236dae4SAndroid Build Coastguard Worker {
327*6236dae4SAndroid Build Coastguard Worker size_t chlglen = strlen(chlg);
328*6236dae4SAndroid Build Coastguard Worker
329*6236dae4SAndroid Build Coastguard Worker /* We had an input token before so if there is another one now that means we
330*6236dae4SAndroid Build Coastguard Worker provided bad credentials in the previous request or it is stale. */
331*6236dae4SAndroid Build Coastguard Worker if(digest->input_token) {
332*6236dae4SAndroid Build Coastguard Worker bool stale = FALSE;
333*6236dae4SAndroid Build Coastguard Worker const char *p = chlg;
334*6236dae4SAndroid Build Coastguard Worker
335*6236dae4SAndroid Build Coastguard Worker /* Check for the 'stale' directive */
336*6236dae4SAndroid Build Coastguard Worker for(;;) {
337*6236dae4SAndroid Build Coastguard Worker char value[DIGEST_MAX_VALUE_LENGTH];
338*6236dae4SAndroid Build Coastguard Worker char content[DIGEST_MAX_CONTENT_LENGTH];
339*6236dae4SAndroid Build Coastguard Worker
340*6236dae4SAndroid Build Coastguard Worker while(*p && ISBLANK(*p))
341*6236dae4SAndroid Build Coastguard Worker p++;
342*6236dae4SAndroid Build Coastguard Worker
343*6236dae4SAndroid Build Coastguard Worker if(!Curl_auth_digest_get_pair(p, value, content, &p))
344*6236dae4SAndroid Build Coastguard Worker break;
345*6236dae4SAndroid Build Coastguard Worker
346*6236dae4SAndroid Build Coastguard Worker if(strcasecompare(value, "stale") &&
347*6236dae4SAndroid Build Coastguard Worker strcasecompare(content, "true")) {
348*6236dae4SAndroid Build Coastguard Worker stale = TRUE;
349*6236dae4SAndroid Build Coastguard Worker break;
350*6236dae4SAndroid Build Coastguard Worker }
351*6236dae4SAndroid Build Coastguard Worker
352*6236dae4SAndroid Build Coastguard Worker while(*p && ISBLANK(*p))
353*6236dae4SAndroid Build Coastguard Worker p++;
354*6236dae4SAndroid Build Coastguard Worker
355*6236dae4SAndroid Build Coastguard Worker if(',' == *p)
356*6236dae4SAndroid Build Coastguard Worker p++;
357*6236dae4SAndroid Build Coastguard Worker }
358*6236dae4SAndroid Build Coastguard Worker
359*6236dae4SAndroid Build Coastguard Worker if(stale)
360*6236dae4SAndroid Build Coastguard Worker Curl_auth_digest_cleanup(digest);
361*6236dae4SAndroid Build Coastguard Worker else
362*6236dae4SAndroid Build Coastguard Worker return CURLE_LOGIN_DENIED;
363*6236dae4SAndroid Build Coastguard Worker }
364*6236dae4SAndroid Build Coastguard Worker
365*6236dae4SAndroid Build Coastguard Worker /* Store the challenge for use later */
366*6236dae4SAndroid Build Coastguard Worker digest->input_token = (BYTE *) Curl_memdup(chlg, chlglen + 1);
367*6236dae4SAndroid Build Coastguard Worker if(!digest->input_token)
368*6236dae4SAndroid Build Coastguard Worker return CURLE_OUT_OF_MEMORY;
369*6236dae4SAndroid Build Coastguard Worker
370*6236dae4SAndroid Build Coastguard Worker digest->input_token_len = chlglen;
371*6236dae4SAndroid Build Coastguard Worker
372*6236dae4SAndroid Build Coastguard Worker return CURLE_OK;
373*6236dae4SAndroid Build Coastguard Worker }
374*6236dae4SAndroid Build Coastguard Worker
375*6236dae4SAndroid Build Coastguard Worker /*
376*6236dae4SAndroid Build Coastguard Worker * Curl_auth_create_digest_http_message()
377*6236dae4SAndroid Build Coastguard Worker *
378*6236dae4SAndroid Build Coastguard Worker * This is used to generate an HTTP DIGEST response message ready for sending
379*6236dae4SAndroid Build Coastguard Worker * to the recipient.
380*6236dae4SAndroid Build Coastguard Worker *
381*6236dae4SAndroid Build Coastguard Worker * Parameters:
382*6236dae4SAndroid Build Coastguard Worker *
383*6236dae4SAndroid Build Coastguard Worker * data [in] - The session handle.
384*6236dae4SAndroid Build Coastguard Worker * userp [in] - The username in the format User or Domain\User.
385*6236dae4SAndroid Build Coastguard Worker * passwdp [in] - The user's password.
386*6236dae4SAndroid Build Coastguard Worker * request [in] - The HTTP request.
387*6236dae4SAndroid Build Coastguard Worker * uripath [in] - The path of the HTTP uri.
388*6236dae4SAndroid Build Coastguard Worker * digest [in/out] - The digest data struct being used and modified.
389*6236dae4SAndroid Build Coastguard Worker * outptr [in/out] - The address where a pointer to newly allocated memory
390*6236dae4SAndroid Build Coastguard Worker * holding the result will be stored upon completion.
391*6236dae4SAndroid Build Coastguard Worker * outlen [out] - The length of the output message.
392*6236dae4SAndroid Build Coastguard Worker *
393*6236dae4SAndroid Build Coastguard Worker * Returns CURLE_OK on success.
394*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)395*6236dae4SAndroid Build Coastguard Worker CURLcode Curl_auth_create_digest_http_message(struct Curl_easy *data,
396*6236dae4SAndroid Build Coastguard Worker const char *userp,
397*6236dae4SAndroid Build Coastguard Worker const char *passwdp,
398*6236dae4SAndroid Build Coastguard Worker const unsigned char *request,
399*6236dae4SAndroid Build Coastguard Worker const unsigned char *uripath,
400*6236dae4SAndroid Build Coastguard Worker struct digestdata *digest,
401*6236dae4SAndroid Build Coastguard Worker char **outptr, size_t *outlen)
402*6236dae4SAndroid Build Coastguard Worker {
403*6236dae4SAndroid Build Coastguard Worker size_t token_max;
404*6236dae4SAndroid Build Coastguard Worker char *resp;
405*6236dae4SAndroid Build Coastguard Worker BYTE *output_token;
406*6236dae4SAndroid Build Coastguard Worker size_t output_token_len = 0;
407*6236dae4SAndroid Build Coastguard Worker PSecPkgInfo SecurityPackage;
408*6236dae4SAndroid Build Coastguard Worker SecBuffer chlg_buf[5];
409*6236dae4SAndroid Build Coastguard Worker SecBufferDesc chlg_desc;
410*6236dae4SAndroid Build Coastguard Worker SECURITY_STATUS status;
411*6236dae4SAndroid Build Coastguard Worker
412*6236dae4SAndroid Build Coastguard Worker (void) data;
413*6236dae4SAndroid Build Coastguard Worker
414*6236dae4SAndroid Build Coastguard Worker /* Query the security package for DigestSSP */
415*6236dae4SAndroid Build Coastguard Worker status =
416*6236dae4SAndroid Build Coastguard Worker Curl_pSecFn->QuerySecurityPackageInfo((TCHAR *) TEXT(SP_NAME_DIGEST),
417*6236dae4SAndroid Build Coastguard Worker &SecurityPackage);
418*6236dae4SAndroid Build Coastguard Worker if(status != SEC_E_OK) {
419*6236dae4SAndroid Build Coastguard Worker failf(data, "SSPI: could not get auth info");
420*6236dae4SAndroid Build Coastguard Worker return CURLE_AUTH_ERROR;
421*6236dae4SAndroid Build Coastguard Worker }
422*6236dae4SAndroid Build Coastguard Worker
423*6236dae4SAndroid Build Coastguard Worker token_max = SecurityPackage->cbMaxToken;
424*6236dae4SAndroid Build Coastguard Worker
425*6236dae4SAndroid Build Coastguard Worker /* Release the package buffer as it is not required anymore */
426*6236dae4SAndroid Build Coastguard Worker Curl_pSecFn->FreeContextBuffer(SecurityPackage);
427*6236dae4SAndroid Build Coastguard Worker
428*6236dae4SAndroid Build Coastguard Worker /* Allocate the output buffer according to the max token size as indicated
429*6236dae4SAndroid Build Coastguard Worker by the security package */
430*6236dae4SAndroid Build Coastguard Worker output_token = malloc(token_max);
431*6236dae4SAndroid Build Coastguard Worker if(!output_token) {
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 /* If the user/passwd that was used to make the identity for http_context
436*6236dae4SAndroid Build Coastguard Worker has changed then delete that context. */
437*6236dae4SAndroid Build Coastguard Worker if((userp && !digest->user) || (!userp && digest->user) ||
438*6236dae4SAndroid Build Coastguard Worker (passwdp && !digest->passwd) || (!passwdp && digest->passwd) ||
439*6236dae4SAndroid Build Coastguard Worker (userp && digest->user && Curl_timestrcmp(userp, digest->user)) ||
440*6236dae4SAndroid Build Coastguard Worker (passwdp && digest->passwd && Curl_timestrcmp(passwdp, digest->passwd))) {
441*6236dae4SAndroid Build Coastguard Worker if(digest->http_context) {
442*6236dae4SAndroid Build Coastguard Worker Curl_pSecFn->DeleteSecurityContext(digest->http_context);
443*6236dae4SAndroid Build Coastguard Worker Curl_safefree(digest->http_context);
444*6236dae4SAndroid Build Coastguard Worker }
445*6236dae4SAndroid Build Coastguard Worker Curl_safefree(digest->user);
446*6236dae4SAndroid Build Coastguard Worker Curl_safefree(digest->passwd);
447*6236dae4SAndroid Build Coastguard Worker }
448*6236dae4SAndroid Build Coastguard Worker
449*6236dae4SAndroid Build Coastguard Worker if(digest->http_context) {
450*6236dae4SAndroid Build Coastguard Worker chlg_desc.ulVersion = SECBUFFER_VERSION;
451*6236dae4SAndroid Build Coastguard Worker chlg_desc.cBuffers = 5;
452*6236dae4SAndroid Build Coastguard Worker chlg_desc.pBuffers = chlg_buf;
453*6236dae4SAndroid Build Coastguard Worker chlg_buf[0].BufferType = SECBUFFER_TOKEN;
454*6236dae4SAndroid Build Coastguard Worker chlg_buf[0].pvBuffer = NULL;
455*6236dae4SAndroid Build Coastguard Worker chlg_buf[0].cbBuffer = 0;
456*6236dae4SAndroid Build Coastguard Worker chlg_buf[1].BufferType = SECBUFFER_PKG_PARAMS;
457*6236dae4SAndroid Build Coastguard Worker chlg_buf[1].pvBuffer = (void *) request;
458*6236dae4SAndroid Build Coastguard Worker chlg_buf[1].cbBuffer = curlx_uztoul(strlen((const char *) request));
459*6236dae4SAndroid Build Coastguard Worker chlg_buf[2].BufferType = SECBUFFER_PKG_PARAMS;
460*6236dae4SAndroid Build Coastguard Worker chlg_buf[2].pvBuffer = (void *) uripath;
461*6236dae4SAndroid Build Coastguard Worker chlg_buf[2].cbBuffer = curlx_uztoul(strlen((const char *) uripath));
462*6236dae4SAndroid Build Coastguard Worker chlg_buf[3].BufferType = SECBUFFER_PKG_PARAMS;
463*6236dae4SAndroid Build Coastguard Worker chlg_buf[3].pvBuffer = NULL;
464*6236dae4SAndroid Build Coastguard Worker chlg_buf[3].cbBuffer = 0;
465*6236dae4SAndroid Build Coastguard Worker chlg_buf[4].BufferType = SECBUFFER_PADDING;
466*6236dae4SAndroid Build Coastguard Worker chlg_buf[4].pvBuffer = output_token;
467*6236dae4SAndroid Build Coastguard Worker chlg_buf[4].cbBuffer = curlx_uztoul(token_max);
468*6236dae4SAndroid Build Coastguard Worker
469*6236dae4SAndroid Build Coastguard Worker status = Curl_pSecFn->MakeSignature(digest->http_context, 0, &chlg_desc,
470*6236dae4SAndroid Build Coastguard Worker 0);
471*6236dae4SAndroid Build Coastguard Worker if(status == SEC_E_OK)
472*6236dae4SAndroid Build Coastguard Worker output_token_len = chlg_buf[4].cbBuffer;
473*6236dae4SAndroid Build Coastguard Worker else { /* delete the context so a new one can be made */
474*6236dae4SAndroid Build Coastguard Worker infof(data, "digest_sspi: MakeSignature failed, error 0x%08lx",
475*6236dae4SAndroid Build Coastguard Worker (long)status);
476*6236dae4SAndroid Build Coastguard Worker Curl_pSecFn->DeleteSecurityContext(digest->http_context);
477*6236dae4SAndroid Build Coastguard Worker Curl_safefree(digest->http_context);
478*6236dae4SAndroid Build Coastguard Worker }
479*6236dae4SAndroid Build Coastguard Worker }
480*6236dae4SAndroid Build Coastguard Worker
481*6236dae4SAndroid Build Coastguard Worker if(!digest->http_context) {
482*6236dae4SAndroid Build Coastguard Worker CredHandle credentials;
483*6236dae4SAndroid Build Coastguard Worker SEC_WINNT_AUTH_IDENTITY identity;
484*6236dae4SAndroid Build Coastguard Worker SEC_WINNT_AUTH_IDENTITY *p_identity;
485*6236dae4SAndroid Build Coastguard Worker SecBuffer resp_buf;
486*6236dae4SAndroid Build Coastguard Worker SecBufferDesc resp_desc;
487*6236dae4SAndroid Build Coastguard Worker unsigned long attrs;
488*6236dae4SAndroid Build Coastguard Worker TimeStamp expiry; /* For Windows 9x compatibility of SSPI calls */
489*6236dae4SAndroid Build Coastguard Worker TCHAR *spn;
490*6236dae4SAndroid Build Coastguard Worker
491*6236dae4SAndroid Build Coastguard Worker /* free the copy of user/passwd used to make the previous identity */
492*6236dae4SAndroid Build Coastguard Worker Curl_safefree(digest->user);
493*6236dae4SAndroid Build Coastguard Worker Curl_safefree(digest->passwd);
494*6236dae4SAndroid Build Coastguard Worker
495*6236dae4SAndroid Build Coastguard Worker if(userp && *userp) {
496*6236dae4SAndroid Build Coastguard Worker /* Populate our identity structure */
497*6236dae4SAndroid Build Coastguard Worker if(Curl_create_sspi_identity(userp, passwdp, &identity)) {
498*6236dae4SAndroid Build Coastguard Worker free(output_token);
499*6236dae4SAndroid Build Coastguard Worker return CURLE_OUT_OF_MEMORY;
500*6236dae4SAndroid Build Coastguard Worker }
501*6236dae4SAndroid Build Coastguard Worker
502*6236dae4SAndroid Build Coastguard Worker /* Populate our identity domain */
503*6236dae4SAndroid Build Coastguard Worker if(Curl_override_sspi_http_realm((const char *) digest->input_token,
504*6236dae4SAndroid Build Coastguard Worker &identity)) {
505*6236dae4SAndroid Build Coastguard Worker free(output_token);
506*6236dae4SAndroid Build Coastguard Worker return CURLE_OUT_OF_MEMORY;
507*6236dae4SAndroid Build Coastguard Worker }
508*6236dae4SAndroid Build Coastguard Worker
509*6236dae4SAndroid Build Coastguard Worker /* Allow proper cleanup of the identity structure */
510*6236dae4SAndroid Build Coastguard Worker p_identity = &identity;
511*6236dae4SAndroid Build Coastguard Worker }
512*6236dae4SAndroid Build Coastguard Worker else
513*6236dae4SAndroid Build Coastguard Worker /* Use the current Windows user */
514*6236dae4SAndroid Build Coastguard Worker p_identity = NULL;
515*6236dae4SAndroid Build Coastguard Worker
516*6236dae4SAndroid Build Coastguard Worker if(userp) {
517*6236dae4SAndroid Build Coastguard Worker digest->user = strdup(userp);
518*6236dae4SAndroid Build Coastguard Worker
519*6236dae4SAndroid Build Coastguard Worker if(!digest->user) {
520*6236dae4SAndroid Build Coastguard Worker free(output_token);
521*6236dae4SAndroid Build Coastguard Worker return CURLE_OUT_OF_MEMORY;
522*6236dae4SAndroid Build Coastguard Worker }
523*6236dae4SAndroid Build Coastguard Worker }
524*6236dae4SAndroid Build Coastguard Worker
525*6236dae4SAndroid Build Coastguard Worker if(passwdp) {
526*6236dae4SAndroid Build Coastguard Worker digest->passwd = strdup(passwdp);
527*6236dae4SAndroid Build Coastguard Worker
528*6236dae4SAndroid Build Coastguard Worker if(!digest->passwd) {
529*6236dae4SAndroid Build Coastguard Worker free(output_token);
530*6236dae4SAndroid Build Coastguard Worker Curl_safefree(digest->user);
531*6236dae4SAndroid Build Coastguard Worker return CURLE_OUT_OF_MEMORY;
532*6236dae4SAndroid Build Coastguard Worker }
533*6236dae4SAndroid Build Coastguard Worker }
534*6236dae4SAndroid Build Coastguard Worker
535*6236dae4SAndroid Build Coastguard Worker /* Acquire our credentials handle */
536*6236dae4SAndroid Build Coastguard Worker status = Curl_pSecFn->AcquireCredentialsHandle(NULL,
537*6236dae4SAndroid Build Coastguard Worker (TCHAR *) TEXT(SP_NAME_DIGEST),
538*6236dae4SAndroid Build Coastguard Worker SECPKG_CRED_OUTBOUND, NULL,
539*6236dae4SAndroid Build Coastguard Worker p_identity, NULL, NULL,
540*6236dae4SAndroid Build Coastguard Worker &credentials, &expiry);
541*6236dae4SAndroid Build Coastguard Worker if(status != SEC_E_OK) {
542*6236dae4SAndroid Build Coastguard Worker Curl_sspi_free_identity(p_identity);
543*6236dae4SAndroid Build Coastguard Worker free(output_token);
544*6236dae4SAndroid Build Coastguard Worker
545*6236dae4SAndroid Build Coastguard Worker return CURLE_LOGIN_DENIED;
546*6236dae4SAndroid Build Coastguard Worker }
547*6236dae4SAndroid Build Coastguard Worker
548*6236dae4SAndroid Build Coastguard Worker /* Setup the challenge "input" security buffer if present */
549*6236dae4SAndroid Build Coastguard Worker chlg_desc.ulVersion = SECBUFFER_VERSION;
550*6236dae4SAndroid Build Coastguard Worker chlg_desc.cBuffers = 3;
551*6236dae4SAndroid Build Coastguard Worker chlg_desc.pBuffers = chlg_buf;
552*6236dae4SAndroid Build Coastguard Worker chlg_buf[0].BufferType = SECBUFFER_TOKEN;
553*6236dae4SAndroid Build Coastguard Worker chlg_buf[0].pvBuffer = digest->input_token;
554*6236dae4SAndroid Build Coastguard Worker chlg_buf[0].cbBuffer = curlx_uztoul(digest->input_token_len);
555*6236dae4SAndroid Build Coastguard Worker chlg_buf[1].BufferType = SECBUFFER_PKG_PARAMS;
556*6236dae4SAndroid Build Coastguard Worker chlg_buf[1].pvBuffer = (void *) request;
557*6236dae4SAndroid Build Coastguard Worker chlg_buf[1].cbBuffer = curlx_uztoul(strlen((const char *) request));
558*6236dae4SAndroid Build Coastguard Worker chlg_buf[2].BufferType = SECBUFFER_PKG_PARAMS;
559*6236dae4SAndroid Build Coastguard Worker chlg_buf[2].pvBuffer = NULL;
560*6236dae4SAndroid Build Coastguard Worker chlg_buf[2].cbBuffer = 0;
561*6236dae4SAndroid Build Coastguard Worker
562*6236dae4SAndroid Build Coastguard Worker /* Setup the response "output" security buffer */
563*6236dae4SAndroid Build Coastguard Worker resp_desc.ulVersion = SECBUFFER_VERSION;
564*6236dae4SAndroid Build Coastguard Worker resp_desc.cBuffers = 1;
565*6236dae4SAndroid Build Coastguard Worker resp_desc.pBuffers = &resp_buf;
566*6236dae4SAndroid Build Coastguard Worker resp_buf.BufferType = SECBUFFER_TOKEN;
567*6236dae4SAndroid Build Coastguard Worker resp_buf.pvBuffer = output_token;
568*6236dae4SAndroid Build Coastguard Worker resp_buf.cbBuffer = curlx_uztoul(token_max);
569*6236dae4SAndroid Build Coastguard Worker
570*6236dae4SAndroid Build Coastguard Worker spn = curlx_convert_UTF8_to_tchar((char *) uripath);
571*6236dae4SAndroid Build Coastguard Worker if(!spn) {
572*6236dae4SAndroid Build Coastguard Worker Curl_pSecFn->FreeCredentialsHandle(&credentials);
573*6236dae4SAndroid Build Coastguard Worker
574*6236dae4SAndroid Build Coastguard Worker Curl_sspi_free_identity(p_identity);
575*6236dae4SAndroid Build Coastguard Worker free(output_token);
576*6236dae4SAndroid Build Coastguard Worker
577*6236dae4SAndroid Build Coastguard Worker return CURLE_OUT_OF_MEMORY;
578*6236dae4SAndroid Build Coastguard Worker }
579*6236dae4SAndroid Build Coastguard Worker
580*6236dae4SAndroid Build Coastguard Worker /* Allocate our new context handle */
581*6236dae4SAndroid Build Coastguard Worker digest->http_context = calloc(1, sizeof(CtxtHandle));
582*6236dae4SAndroid Build Coastguard Worker if(!digest->http_context)
583*6236dae4SAndroid Build Coastguard Worker return CURLE_OUT_OF_MEMORY;
584*6236dae4SAndroid Build Coastguard Worker
585*6236dae4SAndroid Build Coastguard Worker /* Generate our response message */
586*6236dae4SAndroid Build Coastguard Worker status = Curl_pSecFn->InitializeSecurityContext(&credentials, NULL,
587*6236dae4SAndroid Build Coastguard Worker spn,
588*6236dae4SAndroid Build Coastguard Worker ISC_REQ_USE_HTTP_STYLE, 0, 0,
589*6236dae4SAndroid Build Coastguard Worker &chlg_desc, 0,
590*6236dae4SAndroid Build Coastguard Worker digest->http_context,
591*6236dae4SAndroid Build Coastguard Worker &resp_desc, &attrs, &expiry);
592*6236dae4SAndroid Build Coastguard Worker curlx_unicodefree(spn);
593*6236dae4SAndroid Build Coastguard Worker
594*6236dae4SAndroid Build Coastguard Worker if(status == SEC_I_COMPLETE_NEEDED ||
595*6236dae4SAndroid Build Coastguard Worker status == SEC_I_COMPLETE_AND_CONTINUE)
596*6236dae4SAndroid Build Coastguard Worker Curl_pSecFn->CompleteAuthToken(&credentials, &resp_desc);
597*6236dae4SAndroid Build Coastguard Worker else if(status != SEC_E_OK && status != SEC_I_CONTINUE_NEEDED) {
598*6236dae4SAndroid Build Coastguard Worker #if !defined(CURL_DISABLE_VERBOSE_STRINGS)
599*6236dae4SAndroid Build Coastguard Worker char buffer[STRERROR_LEN];
600*6236dae4SAndroid Build Coastguard Worker #endif
601*6236dae4SAndroid Build Coastguard Worker
602*6236dae4SAndroid Build Coastguard Worker Curl_pSecFn->FreeCredentialsHandle(&credentials);
603*6236dae4SAndroid Build Coastguard Worker
604*6236dae4SAndroid Build Coastguard Worker Curl_sspi_free_identity(p_identity);
605*6236dae4SAndroid Build Coastguard Worker free(output_token);
606*6236dae4SAndroid Build Coastguard Worker
607*6236dae4SAndroid Build Coastguard Worker Curl_safefree(digest->http_context);
608*6236dae4SAndroid Build Coastguard Worker
609*6236dae4SAndroid Build Coastguard Worker if(status == SEC_E_INSUFFICIENT_MEMORY)
610*6236dae4SAndroid Build Coastguard Worker return CURLE_OUT_OF_MEMORY;
611*6236dae4SAndroid Build Coastguard Worker
612*6236dae4SAndroid Build Coastguard Worker #if !defined(CURL_DISABLE_VERBOSE_STRINGS)
613*6236dae4SAndroid Build Coastguard Worker infof(data, "schannel: InitializeSecurityContext failed: %s",
614*6236dae4SAndroid Build Coastguard Worker Curl_sspi_strerror(status, buffer, sizeof(buffer)));
615*6236dae4SAndroid Build Coastguard Worker #endif
616*6236dae4SAndroid Build Coastguard Worker
617*6236dae4SAndroid Build Coastguard Worker return CURLE_AUTH_ERROR;
618*6236dae4SAndroid Build Coastguard Worker }
619*6236dae4SAndroid Build Coastguard Worker
620*6236dae4SAndroid Build Coastguard Worker output_token_len = resp_buf.cbBuffer;
621*6236dae4SAndroid Build Coastguard Worker
622*6236dae4SAndroid Build Coastguard Worker Curl_pSecFn->FreeCredentialsHandle(&credentials);
623*6236dae4SAndroid Build Coastguard Worker Curl_sspi_free_identity(p_identity);
624*6236dae4SAndroid Build Coastguard Worker }
625*6236dae4SAndroid Build Coastguard Worker
626*6236dae4SAndroid Build Coastguard Worker resp = malloc(output_token_len + 1);
627*6236dae4SAndroid Build Coastguard Worker if(!resp) {
628*6236dae4SAndroid Build Coastguard Worker free(output_token);
629*6236dae4SAndroid Build Coastguard Worker
630*6236dae4SAndroid Build Coastguard Worker return CURLE_OUT_OF_MEMORY;
631*6236dae4SAndroid Build Coastguard Worker }
632*6236dae4SAndroid Build Coastguard Worker
633*6236dae4SAndroid Build Coastguard Worker /* Copy the generated response */
634*6236dae4SAndroid Build Coastguard Worker memcpy(resp, output_token, output_token_len);
635*6236dae4SAndroid Build Coastguard Worker resp[output_token_len] = 0;
636*6236dae4SAndroid Build Coastguard Worker
637*6236dae4SAndroid Build Coastguard Worker /* Return the response */
638*6236dae4SAndroid Build Coastguard Worker *outptr = resp;
639*6236dae4SAndroid Build Coastguard Worker *outlen = output_token_len;
640*6236dae4SAndroid Build Coastguard Worker
641*6236dae4SAndroid Build Coastguard Worker /* Free the response buffer */
642*6236dae4SAndroid Build Coastguard Worker free(output_token);
643*6236dae4SAndroid Build Coastguard Worker
644*6236dae4SAndroid Build Coastguard Worker return CURLE_OK;
645*6236dae4SAndroid Build Coastguard Worker }
646*6236dae4SAndroid Build Coastguard Worker
647*6236dae4SAndroid Build Coastguard Worker /*
648*6236dae4SAndroid Build Coastguard Worker * Curl_auth_digest_cleanup()
649*6236dae4SAndroid Build Coastguard Worker *
650*6236dae4SAndroid Build Coastguard Worker * This is used to clean up the digest specific data.
651*6236dae4SAndroid Build Coastguard Worker *
652*6236dae4SAndroid Build Coastguard Worker * Parameters:
653*6236dae4SAndroid Build Coastguard Worker *
654*6236dae4SAndroid Build Coastguard Worker * digest [in/out] - The digest data struct being cleaned up.
655*6236dae4SAndroid Build Coastguard Worker *
656*6236dae4SAndroid Build Coastguard Worker */
Curl_auth_digest_cleanup(struct digestdata * digest)657*6236dae4SAndroid Build Coastguard Worker void Curl_auth_digest_cleanup(struct digestdata *digest)
658*6236dae4SAndroid Build Coastguard Worker {
659*6236dae4SAndroid Build Coastguard Worker /* Free the input token */
660*6236dae4SAndroid Build Coastguard Worker Curl_safefree(digest->input_token);
661*6236dae4SAndroid Build Coastguard Worker
662*6236dae4SAndroid Build Coastguard Worker /* Reset any variables */
663*6236dae4SAndroid Build Coastguard Worker digest->input_token_len = 0;
664*6236dae4SAndroid Build Coastguard Worker
665*6236dae4SAndroid Build Coastguard Worker /* Delete security context */
666*6236dae4SAndroid Build Coastguard Worker if(digest->http_context) {
667*6236dae4SAndroid Build Coastguard Worker Curl_pSecFn->DeleteSecurityContext(digest->http_context);
668*6236dae4SAndroid Build Coastguard Worker Curl_safefree(digest->http_context);
669*6236dae4SAndroid Build Coastguard Worker }
670*6236dae4SAndroid Build Coastguard Worker
671*6236dae4SAndroid Build Coastguard Worker /* Free the copy of user/passwd used to make the identity for http_context */
672*6236dae4SAndroid Build Coastguard Worker Curl_safefree(digest->user);
673*6236dae4SAndroid Build Coastguard Worker Curl_safefree(digest->passwd);
674*6236dae4SAndroid Build Coastguard Worker }
675*6236dae4SAndroid Build Coastguard Worker
676*6236dae4SAndroid Build Coastguard Worker #endif /* USE_WINDOWS_SSPI && !CURL_DISABLE_DIGEST_AUTH */
677