Annotation of embedaddon/curl/lib/vauth/digest_sspi.c, revision 1.1.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>