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