xref: /aosp_15_r20/external/curl/lib/vauth/digest_sspi.c (revision 6236dae45794135f37c4eb022389c904c8b0090d)
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