Annotation of embedaddon/curl/lib/vtls/schannel.c, revision 1.1.1.1

1.1       misho       1: /***************************************************************************
                      2:  *                                  _   _ ____  _
                      3:  *  Project                     ___| | | |  _ \| |
                      4:  *                             / __| | | | |_) | |
                      5:  *                            | (__| |_| |  _ <| |___
                      6:  *                             \___|\___/|_| \_\_____|
                      7:  *
                      8:  * Copyright (C) 2012 - 2016, Marc Hoersken, <info@marc-hoersken.de>
                      9:  * Copyright (C) 2012, Mark Salisbury, <mark.salisbury@hp.com>
                     10:  * Copyright (C) 2012 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
                     11:  *
                     12:  * This software is licensed as described in the file COPYING, which
                     13:  * you should have received as part of this distribution. The terms
                     14:  * are also available at https://curl.haxx.se/docs/copyright.html.
                     15:  *
                     16:  * You may opt to use, copy, modify, merge, publish, distribute and/or sell
                     17:  * copies of the Software, and permit persons to whom the Software is
                     18:  * furnished to do so, under the terms of the COPYING file.
                     19:  *
                     20:  * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
                     21:  * KIND, either express or implied.
                     22:  *
                     23:  ***************************************************************************/
                     24: 
                     25: /*
                     26:  * Source file for all Schannel-specific code for the TLS/SSL layer. No code
                     27:  * but vtls.c should ever call or use these functions.
                     28:  */
                     29: 
                     30: #include "curl_setup.h"
                     31: 
                     32: #ifdef USE_SCHANNEL
                     33: 
                     34: #define EXPOSE_SCHANNEL_INTERNAL_STRUCTS
                     35: 
                     36: #ifndef USE_WINDOWS_SSPI
                     37: #  error "Can't compile SCHANNEL support without SSPI."
                     38: #endif
                     39: 
                     40: #include "schannel.h"
                     41: #include "vtls.h"
                     42: #include "sendf.h"
                     43: #include "connect.h" /* for the connect timeout */
                     44: #include "strerror.h"
                     45: #include "select.h" /* for the socket readyness */
                     46: #include "inet_pton.h" /* for IP addr SNI check */
                     47: #include "curl_multibyte.h"
                     48: #include "warnless.h"
                     49: #include "x509asn1.h"
                     50: #include "curl_printf.h"
                     51: #include "multiif.h"
                     52: #include "system_win32.h"
                     53: 
                     54:  /* The last #include file should be: */
                     55: #include "curl_memory.h"
                     56: #include "memdebug.h"
                     57: 
                     58: /* ALPN requires version 8.1 of the Windows SDK, which was
                     59:    shipped with Visual Studio 2013, aka _MSC_VER 1800:
                     60: 
                     61:    https://technet.microsoft.com/en-us/library/hh831771%28v=ws.11%29.aspx
                     62: */
                     63: #if defined(_MSC_VER) && (_MSC_VER >= 1800) && !defined(_USING_V110_SDK71_)
                     64: #  define HAS_ALPN 1
                     65: #endif
                     66: 
                     67: #ifndef UNISP_NAME_A
                     68: #define UNISP_NAME_A "Microsoft Unified Security Protocol Provider"
                     69: #endif
                     70: 
                     71: #ifndef UNISP_NAME_W
                     72: #define UNISP_NAME_W L"Microsoft Unified Security Protocol Provider"
                     73: #endif
                     74: 
                     75: #ifndef UNISP_NAME
                     76: #ifdef UNICODE
                     77: #define UNISP_NAME  UNISP_NAME_W
                     78: #else
                     79: #define UNISP_NAME  UNISP_NAME_A
                     80: #endif
                     81: #endif
                     82: 
                     83: #if defined(CryptStringToBinary) && defined(CRYPT_STRING_HEX)
                     84: #define HAS_CLIENT_CERT_PATH
                     85: #endif
                     86: 
                     87: #ifdef HAS_CLIENT_CERT_PATH
                     88: #ifdef UNICODE
                     89: #define CURL_CERT_STORE_PROV_SYSTEM CERT_STORE_PROV_SYSTEM_W
                     90: #else
                     91: #define CURL_CERT_STORE_PROV_SYSTEM CERT_STORE_PROV_SYSTEM_A
                     92: #endif
                     93: #endif
                     94: 
                     95: #ifndef SP_PROT_SSL2_CLIENT
                     96: #define SP_PROT_SSL2_CLIENT             0x00000008
                     97: #endif
                     98: 
                     99: #ifndef SP_PROT_SSL3_CLIENT
                    100: #define SP_PROT_SSL3_CLIENT             0x00000008
                    101: #endif
                    102: 
                    103: #ifndef SP_PROT_TLS1_CLIENT
                    104: #define SP_PROT_TLS1_CLIENT             0x00000080
                    105: #endif
                    106: 
                    107: #ifndef SP_PROT_TLS1_0_CLIENT
                    108: #define SP_PROT_TLS1_0_CLIENT           SP_PROT_TLS1_CLIENT
                    109: #endif
                    110: 
                    111: #ifndef SP_PROT_TLS1_1_CLIENT
                    112: #define SP_PROT_TLS1_1_CLIENT           0x00000200
                    113: #endif
                    114: 
                    115: #ifndef SP_PROT_TLS1_2_CLIENT
                    116: #define SP_PROT_TLS1_2_CLIENT           0x00000800
                    117: #endif
                    118: 
                    119: #ifndef SECBUFFER_ALERT
                    120: #define SECBUFFER_ALERT                 17
                    121: #endif
                    122: 
                    123: /* Both schannel buffer sizes must be > 0 */
                    124: #define CURL_SCHANNEL_BUFFER_INIT_SIZE   4096
                    125: #define CURL_SCHANNEL_BUFFER_FREE_SIZE   1024
                    126: 
                    127: #define CERT_THUMBPRINT_STR_LEN 40
                    128: #define CERT_THUMBPRINT_DATA_LEN 20
                    129: 
                    130: /* Uncomment to force verbose output
                    131:  * #define infof(x, y, ...) printf(y, __VA_ARGS__)
                    132:  * #define failf(x, y, ...) printf(y, __VA_ARGS__)
                    133:  */
                    134: 
                    135: #ifndef CALG_SHA_256
                    136: #  define CALG_SHA_256 0x0000800c
                    137: #endif
                    138: 
                    139: #define BACKEND connssl->backend
                    140: 
                    141: static Curl_recv schannel_recv;
                    142: static Curl_send schannel_send;
                    143: 
                    144: static CURLcode pkp_pin_peer_pubkey(struct connectdata *conn, int sockindex,
                    145:                                     const char *pinnedpubkey);
                    146: 
                    147: static void InitSecBuffer(SecBuffer *buffer, unsigned long BufType,
                    148:                           void *BufDataPtr, unsigned long BufByteSize)
                    149: {
                    150:   buffer->cbBuffer = BufByteSize;
                    151:   buffer->BufferType = BufType;
                    152:   buffer->pvBuffer = BufDataPtr;
                    153: }
                    154: 
                    155: static void InitSecBufferDesc(SecBufferDesc *desc, SecBuffer *BufArr,
                    156:                               unsigned long NumArrElem)
                    157: {
                    158:   desc->ulVersion = SECBUFFER_VERSION;
                    159:   desc->pBuffers = BufArr;
                    160:   desc->cBuffers = NumArrElem;
                    161: }
                    162: 
                    163: static CURLcode
                    164: set_ssl_version_min_max(SCHANNEL_CRED *schannel_cred, struct connectdata *conn)
                    165: {
                    166:   struct Curl_easy *data = conn->data;
                    167:   long ssl_version = SSL_CONN_CONFIG(version);
                    168:   long ssl_version_max = SSL_CONN_CONFIG(version_max);
                    169:   long i = ssl_version;
                    170: 
                    171:   switch(ssl_version_max) {
                    172:     case CURL_SSLVERSION_MAX_NONE:
                    173:     case CURL_SSLVERSION_MAX_DEFAULT:
                    174:       ssl_version_max = CURL_SSLVERSION_MAX_TLSv1_2;
                    175:       break;
                    176:   }
                    177:   for(; i <= (ssl_version_max >> 16); ++i) {
                    178:     switch(i) {
                    179:       case CURL_SSLVERSION_TLSv1_0:
                    180:         schannel_cred->grbitEnabledProtocols |= SP_PROT_TLS1_0_CLIENT;
                    181:         break;
                    182:       case CURL_SSLVERSION_TLSv1_1:
                    183:         schannel_cred->grbitEnabledProtocols |= SP_PROT_TLS1_1_CLIENT;
                    184:         break;
                    185:       case CURL_SSLVERSION_TLSv1_2:
                    186:         schannel_cred->grbitEnabledProtocols |= SP_PROT_TLS1_2_CLIENT;
                    187:         break;
                    188:       case CURL_SSLVERSION_TLSv1_3:
                    189:         failf(data, "schannel: TLS 1.3 is not yet supported");
                    190:         return CURLE_SSL_CONNECT_ERROR;
                    191:     }
                    192:   }
                    193:   return CURLE_OK;
                    194: }
                    195: 
                    196: /*longest is 26, buffer is slightly bigger*/
                    197: #define LONGEST_ALG_ID 32
                    198: #define CIPHEROPTION(X) \
                    199: if(strcmp(#X, tmp) == 0) \
                    200:   return X
                    201: 
                    202: static int
                    203: get_alg_id_by_name(char *name)
                    204: {
                    205:   char tmp[LONGEST_ALG_ID] = { 0 };
                    206:   char *nameEnd = strchr(name, ':');
                    207:   size_t n = nameEnd ? min((size_t)(nameEnd - name), LONGEST_ALG_ID - 1) : \
                    208:     min(strlen(name), LONGEST_ALG_ID - 1);
                    209:   strncpy(tmp, name, n);
                    210:   tmp[n] = 0;
                    211:   CIPHEROPTION(CALG_MD2);
                    212:   CIPHEROPTION(CALG_MD4);
                    213:   CIPHEROPTION(CALG_MD5);
                    214:   CIPHEROPTION(CALG_SHA);
                    215:   CIPHEROPTION(CALG_SHA1);
                    216:   CIPHEROPTION(CALG_MAC);
                    217:   CIPHEROPTION(CALG_RSA_SIGN);
                    218:   CIPHEROPTION(CALG_DSS_SIGN);
                    219: /*ifdefs for the options that are defined conditionally in wincrypt.h*/
                    220: #ifdef CALG_NO_SIGN
                    221:   CIPHEROPTION(CALG_NO_SIGN);
                    222: #endif
                    223:   CIPHEROPTION(CALG_RSA_KEYX);
                    224:   CIPHEROPTION(CALG_DES);
                    225: #ifdef CALG_3DES_112
                    226:   CIPHEROPTION(CALG_3DES_112);
                    227: #endif
                    228:   CIPHEROPTION(CALG_3DES);
                    229:   CIPHEROPTION(CALG_DESX);
                    230:   CIPHEROPTION(CALG_RC2);
                    231:   CIPHEROPTION(CALG_RC4);
                    232:   CIPHEROPTION(CALG_SEAL);
                    233: #ifdef CALG_DH_SF
                    234:   CIPHEROPTION(CALG_DH_SF);
                    235: #endif
                    236:   CIPHEROPTION(CALG_DH_EPHEM);
                    237: #ifdef CALG_AGREEDKEY_ANY
                    238:   CIPHEROPTION(CALG_AGREEDKEY_ANY);
                    239: #endif
                    240: #ifdef CALG_HUGHES_MD5
                    241:   CIPHEROPTION(CALG_HUGHES_MD5);
                    242: #endif
                    243:   CIPHEROPTION(CALG_SKIPJACK);
                    244: #ifdef CALG_TEK
                    245:   CIPHEROPTION(CALG_TEK);
                    246: #endif
                    247:   CIPHEROPTION(CALG_CYLINK_MEK);
                    248:   CIPHEROPTION(CALG_SSL3_SHAMD5);
                    249: #ifdef CALG_SSL3_MASTER
                    250:   CIPHEROPTION(CALG_SSL3_MASTER);
                    251: #endif
                    252: #ifdef CALG_SCHANNEL_MASTER_HASH
                    253:   CIPHEROPTION(CALG_SCHANNEL_MASTER_HASH);
                    254: #endif
                    255: #ifdef CALG_SCHANNEL_MAC_KEY
                    256:   CIPHEROPTION(CALG_SCHANNEL_MAC_KEY);
                    257: #endif
                    258: #ifdef CALG_SCHANNEL_ENC_KEY
                    259:   CIPHEROPTION(CALG_SCHANNEL_ENC_KEY);
                    260: #endif
                    261: #ifdef CALG_PCT1_MASTER
                    262:   CIPHEROPTION(CALG_PCT1_MASTER);
                    263: #endif
                    264: #ifdef CALG_SSL2_MASTER
                    265:   CIPHEROPTION(CALG_SSL2_MASTER);
                    266: #endif
                    267: #ifdef CALG_TLS1_MASTER
                    268:   CIPHEROPTION(CALG_TLS1_MASTER);
                    269: #endif
                    270: #ifdef CALG_RC5
                    271:   CIPHEROPTION(CALG_RC5);
                    272: #endif
                    273: #ifdef CALG_HMAC
                    274:   CIPHEROPTION(CALG_HMAC);
                    275: #endif
                    276: #if !defined(__W32API_MAJOR_VERSION) || \
                    277:     !defined(__W32API_MINOR_VERSION) || \
                    278:     defined(__MINGW64_VERSION_MAJOR) || \
                    279:     (__W32API_MAJOR_VERSION > 5)     || \
                    280:     ((__W32API_MAJOR_VERSION == 5) && (__W32API_MINOR_VERSION > 0))
                    281:   /* CALG_TLS1PRF has a syntax error in MinGW's w32api up to version 5.0,
                    282:      see https://osdn.net/projects/mingw/ticket/38391 */
                    283:   CIPHEROPTION(CALG_TLS1PRF);
                    284: #endif
                    285: #ifdef CALG_HASH_REPLACE_OWF
                    286:   CIPHEROPTION(CALG_HASH_REPLACE_OWF);
                    287: #endif
                    288: #ifdef CALG_AES_128
                    289:   CIPHEROPTION(CALG_AES_128);
                    290: #endif
                    291: #ifdef CALG_AES_192
                    292:   CIPHEROPTION(CALG_AES_192);
                    293: #endif
                    294: #ifdef CALG_AES_256
                    295:   CIPHEROPTION(CALG_AES_256);
                    296: #endif
                    297: #ifdef CALG_AES
                    298:   CIPHEROPTION(CALG_AES);
                    299: #endif
                    300: #ifdef CALG_SHA_256
                    301:   CIPHEROPTION(CALG_SHA_256);
                    302: #endif
                    303: #ifdef CALG_SHA_384
                    304:   CIPHEROPTION(CALG_SHA_384);
                    305: #endif
                    306: #ifdef CALG_SHA_512
                    307:   CIPHEROPTION(CALG_SHA_512);
                    308: #endif
                    309: #ifdef CALG_ECDH
                    310:   CIPHEROPTION(CALG_ECDH);
                    311: #endif
                    312: #ifdef CALG_ECMQV
                    313:   CIPHEROPTION(CALG_ECMQV);
                    314: #endif
                    315: #ifdef CALG_ECDSA
                    316:   CIPHEROPTION(CALG_ECDSA);
                    317: #endif
                    318: #ifdef CALG_ECDH_EPHEM
                    319:   CIPHEROPTION(CALG_ECDH_EPHEM);
                    320: #endif
                    321:   return 0;
                    322: }
                    323: 
                    324: static CURLcode
                    325: set_ssl_ciphers(SCHANNEL_CRED *schannel_cred, char *ciphers)
                    326: {
                    327:   char *startCur = ciphers;
                    328:   int algCount = 0;
                    329:   static ALG_ID algIds[45]; /*There are 45 listed in the MS headers*/
                    330:   while(startCur && (0 != *startCur) && (algCount < 45)) {
                    331:     long alg = strtol(startCur, 0, 0);
                    332:     if(!alg)
                    333:       alg = get_alg_id_by_name(startCur);
                    334:     if(alg)
                    335:       algIds[algCount++] = alg;
                    336:     else
                    337:       return CURLE_SSL_CIPHER;
                    338:     startCur = strchr(startCur, ':');
                    339:     if(startCur)
                    340:       startCur++;
                    341:   }
                    342:     schannel_cred->palgSupportedAlgs = algIds;
                    343:   schannel_cred->cSupportedAlgs = algCount;
                    344:   return CURLE_OK;
                    345: }
                    346: 
                    347: #ifdef HAS_CLIENT_CERT_PATH
                    348: static CURLcode
                    349: get_cert_location(TCHAR *path, DWORD *store_name, TCHAR **store_path,
                    350:                   TCHAR **thumbprint)
                    351: {
                    352:   TCHAR *sep;
                    353:   TCHAR *store_path_start;
                    354:   size_t store_name_len;
                    355: 
                    356:   sep = _tcschr(path, TEXT('\\'));
                    357:   if(sep == NULL)
                    358:     return CURLE_SSL_CERTPROBLEM;
                    359: 
                    360:   store_name_len = sep - path;
                    361: 
                    362:   if(_tcsnccmp(path, TEXT("CurrentUser"), store_name_len) == 0)
                    363:     *store_name = CERT_SYSTEM_STORE_CURRENT_USER;
                    364:   else if(_tcsnccmp(path, TEXT("LocalMachine"), store_name_len) == 0)
                    365:     *store_name = CERT_SYSTEM_STORE_LOCAL_MACHINE;
                    366:   else if(_tcsnccmp(path, TEXT("CurrentService"), store_name_len) == 0)
                    367:     *store_name = CERT_SYSTEM_STORE_CURRENT_SERVICE;
                    368:   else if(_tcsnccmp(path, TEXT("Services"), store_name_len) == 0)
                    369:     *store_name = CERT_SYSTEM_STORE_SERVICES;
                    370:   else if(_tcsnccmp(path, TEXT("Users"), store_name_len) == 0)
                    371:     *store_name = CERT_SYSTEM_STORE_USERS;
                    372:   else if(_tcsnccmp(path, TEXT("CurrentUserGroupPolicy"),
                    373:                     store_name_len) == 0)
                    374:     *store_name = CERT_SYSTEM_STORE_CURRENT_USER_GROUP_POLICY;
                    375:   else if(_tcsnccmp(path, TEXT("LocalMachineGroupPolicy"),
                    376:                     store_name_len) == 0)
                    377:     *store_name = CERT_SYSTEM_STORE_LOCAL_MACHINE_GROUP_POLICY;
                    378:   else if(_tcsnccmp(path, TEXT("LocalMachineEnterprise"),
                    379:                     store_name_len) == 0)
                    380:     *store_name = CERT_SYSTEM_STORE_LOCAL_MACHINE_ENTERPRISE;
                    381:   else
                    382:     return CURLE_SSL_CERTPROBLEM;
                    383: 
                    384:   store_path_start = sep + 1;
                    385: 
                    386:   sep = _tcschr(store_path_start, TEXT('\\'));
                    387:   if(sep == NULL)
                    388:     return CURLE_SSL_CERTPROBLEM;
                    389: 
                    390:   *sep = TEXT('\0');
                    391:   *store_path = _tcsdup(store_path_start);
                    392:   *sep = TEXT('\\');
                    393:   if(*store_path == NULL)
                    394:     return CURLE_OUT_OF_MEMORY;
                    395: 
                    396:   *thumbprint = sep + 1;
                    397:   if(_tcslen(*thumbprint) != CERT_THUMBPRINT_STR_LEN)
                    398:     return CURLE_SSL_CERTPROBLEM;
                    399: 
                    400:   return CURLE_OK;
                    401: }
                    402: #endif
                    403: 
                    404: static CURLcode
                    405: schannel_connect_step1(struct connectdata *conn, int sockindex)
                    406: {
                    407:   ssize_t written = -1;
                    408:   struct Curl_easy *data = conn->data;
                    409:   struct ssl_connect_data *connssl = &conn->ssl[sockindex];
                    410:   SecBuffer outbuf;
                    411:   SecBufferDesc outbuf_desc;
                    412:   SecBuffer inbuf;
                    413:   SecBufferDesc inbuf_desc;
                    414: #ifdef HAS_ALPN
                    415:   unsigned char alpn_buffer[128];
                    416: #endif
                    417:   SCHANNEL_CRED schannel_cred;
                    418:   PCCERT_CONTEXT client_certs[1] = { NULL };
                    419:   SECURITY_STATUS sspi_status = SEC_E_OK;
                    420:   struct curl_schannel_cred *old_cred = NULL;
                    421:   struct in_addr addr;
                    422: #ifdef ENABLE_IPV6
                    423:   struct in6_addr addr6;
                    424: #endif
                    425:   TCHAR *host_name;
                    426:   CURLcode result;
                    427:   char * const hostname = SSL_IS_PROXY() ? conn->http_proxy.host.name :
                    428:     conn->host.name;
                    429: 
                    430:   DEBUGF(infof(data,
                    431:                "schannel: SSL/TLS connection with %s port %hu (step 1/3)\n",
                    432:                hostname, conn->remote_port));
                    433: 
                    434:   if(Curl_verify_windows_version(5, 1, PLATFORM_WINNT,
                    435:                                  VERSION_LESS_THAN_EQUAL)) {
                    436:      /* Schannel in Windows XP (OS version 5.1) uses legacy handshakes and
                    437:         algorithms that may not be supported by all servers. */
                    438:      infof(data, "schannel: Windows version is old and may not be able to "
                    439:            "connect to some servers due to lack of SNI, algorithms, etc.\n");
                    440:   }
                    441: 
                    442: #ifdef HAS_ALPN
                    443:   /* ALPN is only supported on Windows 8.1 / Server 2012 R2 and above.
                    444:      Also it doesn't seem to be supported for Wine, see curl bug #983. */
                    445:   BACKEND->use_alpn = conn->bits.tls_enable_alpn &&
                    446:                       !GetProcAddress(GetModuleHandleA("ntdll"),
                    447:                                       "wine_get_version") &&
                    448:                       Curl_verify_windows_version(6, 3, PLATFORM_WINNT,
                    449:                                                   VERSION_GREATER_THAN_EQUAL);
                    450: #else
                    451:   BACKEND->use_alpn = false;
                    452: #endif
                    453: 
                    454: #ifdef _WIN32_WCE
                    455: #ifdef HAS_MANUAL_VERIFY_API
                    456:   /* certificate validation on CE doesn't seem to work right; we'll
                    457:    * do it following a more manual process. */
                    458:   BACKEND->use_manual_cred_validation = true;
                    459: #else
                    460: #error "compiler too old to support requisite manual cert verify for Win CE"
                    461: #endif
                    462: #else
                    463: #ifdef HAS_MANUAL_VERIFY_API
                    464:   if(SSL_CONN_CONFIG(CAfile)) {
                    465:     if(Curl_verify_windows_version(6, 1, PLATFORM_WINNT,
                    466:                                    VERSION_GREATER_THAN_EQUAL)) {
                    467:       BACKEND->use_manual_cred_validation = true;
                    468:     }
                    469:     else {
                    470:       failf(data, "schannel: this version of Windows is too old to support "
                    471:             "certificate verification via CA bundle file.");
                    472:       return CURLE_SSL_CACERT_BADFILE;
                    473:     }
                    474:   }
                    475:   else
                    476:     BACKEND->use_manual_cred_validation = false;
                    477: #else
                    478:   if(SSL_CONN_CONFIG(CAfile)) {
                    479:     failf(data, "schannel: CA cert support not built in");
                    480:     return CURLE_NOT_BUILT_IN;
                    481:   }
                    482: #endif
                    483: #endif
                    484: 
                    485:   BACKEND->cred = NULL;
                    486: 
                    487:   /* check for an existing re-usable credential handle */
                    488:   if(SSL_SET_OPTION(primary.sessionid)) {
                    489:     Curl_ssl_sessionid_lock(conn);
                    490:     if(!Curl_ssl_getsessionid(conn, (void **)&old_cred, NULL, sockindex)) {
                    491:       BACKEND->cred = old_cred;
                    492:       DEBUGF(infof(data, "schannel: re-using existing credential handle\n"));
                    493: 
                    494:       /* increment the reference counter of the credential/session handle */
                    495:       BACKEND->cred->refcount++;
                    496:       DEBUGF(infof(data,
                    497:                    "schannel: incremented credential handle refcount = %d\n",
                    498:                    BACKEND->cred->refcount));
                    499:     }
                    500:     Curl_ssl_sessionid_unlock(conn);
                    501:   }
                    502: 
                    503:   if(!BACKEND->cred) {
                    504:     /* setup Schannel API options */
                    505:     memset(&schannel_cred, 0, sizeof(schannel_cred));
                    506:     schannel_cred.dwVersion = SCHANNEL_CRED_VERSION;
                    507: 
                    508:     if(conn->ssl_config.verifypeer) {
                    509: #ifdef HAS_MANUAL_VERIFY_API
                    510:       if(BACKEND->use_manual_cred_validation)
                    511:         schannel_cred.dwFlags = SCH_CRED_MANUAL_CRED_VALIDATION;
                    512:       else
                    513: #endif
                    514:         schannel_cred.dwFlags = SCH_CRED_AUTO_CRED_VALIDATION;
                    515: 
                    516:       if(data->set.ssl.no_revoke) {
                    517:         schannel_cred.dwFlags |= SCH_CRED_IGNORE_NO_REVOCATION_CHECK |
                    518:           SCH_CRED_IGNORE_REVOCATION_OFFLINE;
                    519: 
                    520:         DEBUGF(infof(data, "schannel: disabled server certificate revocation "
                    521:                      "checks\n"));
                    522:       }
                    523:       else if(data->set.ssl.revoke_best_effort) {
                    524:         schannel_cred.dwFlags |= SCH_CRED_IGNORE_NO_REVOCATION_CHECK |
                    525:           SCH_CRED_IGNORE_REVOCATION_OFFLINE | SCH_CRED_REVOCATION_CHECK_CHAIN;
                    526: 
                    527:         DEBUGF(infof(data, "schannel: ignore revocation offline errors"));
                    528:       }
                    529:       else {
                    530:         schannel_cred.dwFlags |= SCH_CRED_REVOCATION_CHECK_CHAIN;
                    531: 
                    532:         DEBUGF(infof(data,
                    533:                      "schannel: checking server certificate revocation\n"));
                    534:       }
                    535:     }
                    536:     else {
                    537:       schannel_cred.dwFlags = SCH_CRED_MANUAL_CRED_VALIDATION |
                    538:         SCH_CRED_IGNORE_NO_REVOCATION_CHECK |
                    539:         SCH_CRED_IGNORE_REVOCATION_OFFLINE;
                    540:       DEBUGF(infof(data,
                    541:                    "schannel: disabled server cert revocation checks\n"));
                    542:     }
                    543: 
                    544:     if(!conn->ssl_config.verifyhost) {
                    545:       schannel_cred.dwFlags |= SCH_CRED_NO_SERVERNAME_CHECK;
                    546:       DEBUGF(infof(data, "schannel: verifyhost setting prevents Schannel from "
                    547:                    "comparing the supplied target name with the subject "
                    548:                    "names in server certificates.\n"));
                    549:     }
                    550: 
                    551:     switch(conn->ssl_config.version) {
                    552:     case CURL_SSLVERSION_DEFAULT:
                    553:     case CURL_SSLVERSION_TLSv1:
                    554:     case CURL_SSLVERSION_TLSv1_0:
                    555:     case CURL_SSLVERSION_TLSv1_1:
                    556:     case CURL_SSLVERSION_TLSv1_2:
                    557:     case CURL_SSLVERSION_TLSv1_3:
                    558:       {
                    559:         result = set_ssl_version_min_max(&schannel_cred, conn);
                    560:         if(result != CURLE_OK)
                    561:           return result;
                    562:         break;
                    563:       }
                    564:     case CURL_SSLVERSION_SSLv3:
                    565:       schannel_cred.grbitEnabledProtocols = SP_PROT_SSL3_CLIENT;
                    566:       break;
                    567:     case CURL_SSLVERSION_SSLv2:
                    568:       schannel_cred.grbitEnabledProtocols = SP_PROT_SSL2_CLIENT;
                    569:       break;
                    570:     default:
                    571:       failf(data, "Unrecognized parameter passed via CURLOPT_SSLVERSION");
                    572:       return CURLE_SSL_CONNECT_ERROR;
                    573:     }
                    574: 
                    575:     if(SSL_CONN_CONFIG(cipher_list)) {
                    576:       result = set_ssl_ciphers(&schannel_cred, SSL_CONN_CONFIG(cipher_list));
                    577:       if(CURLE_OK != result) {
                    578:         failf(data, "Unable to set ciphers to passed via SSL_CONN_CONFIG");
                    579:         return result;
                    580:       }
                    581:     }
                    582: 
                    583: 
                    584: #ifdef HAS_CLIENT_CERT_PATH
                    585:     /* client certificate */
                    586:     if(data->set.ssl.cert) {
                    587:       DWORD cert_store_name;
                    588:       TCHAR *cert_store_path = NULL;
                    589:       TCHAR *cert_thumbprint_str;
                    590:       CRYPT_HASH_BLOB cert_thumbprint;
                    591:       BYTE cert_thumbprint_data[CERT_THUMBPRINT_DATA_LEN];
                    592:       HCERTSTORE cert_store;
                    593:       FILE *fInCert = NULL;
                    594: 
                    595:       TCHAR *cert_path = Curl_convert_UTF8_to_tchar(data->set.ssl.cert);
                    596:       if(!cert_path)
                    597:         return CURLE_OUT_OF_MEMORY;
                    598: 
                    599:       result = get_cert_location(cert_path, &cert_store_name,
                    600:                                  &cert_store_path, &cert_thumbprint_str);
                    601:       if((result != CURLE_OK) && (data->set.ssl.cert[0]!='\0'))
                    602:         fInCert = fopen(data->set.ssl.cert, "rb");
                    603: 
                    604:       if((result != CURLE_OK) && (fInCert == NULL)) {
                    605:         failf(data, "schannel: Failed to get certificate location"
                    606:               " or file for %s",
                    607:               data->set.ssl.cert);
                    608:         Curl_unicodefree(cert_path);
                    609:         return result;
                    610:       }
                    611: 
                    612:       if(fInCert) {
                    613:         /* Reading a .P12 or .pfx file, like the example at bottom of
                    614:            https://social.msdn.microsoft.com/Forums/windowsdesktop/
                    615:            en-US/3e7bc95f-b21a-4bcd-bd2c-7f996718cae5
                    616:         */
                    617:         void *certdata = NULL;
                    618:         long filesize = 0;
                    619:         CRYPT_DATA_BLOB datablob;
                    620:         WCHAR* pszPassword;
                    621:         size_t pwd_len = 0;
                    622:         int str_w_len = 0;
                    623:         int continue_reading = fseek(fInCert, 0, SEEK_END) == 0;
                    624:         if(continue_reading)
                    625:           filesize = ftell(fInCert);
                    626:         if(filesize < 0)
                    627:           continue_reading = 0;
                    628:         if(continue_reading)
                    629:           continue_reading = fseek(fInCert, 0, SEEK_SET) == 0;
                    630:         if(continue_reading)
                    631:           certdata = malloc(((size_t)filesize) + 1);
                    632:         if((certdata == NULL) ||
                    633:            ((int) fread(certdata, (size_t)filesize, 1, fInCert) != 1))
                    634:           continue_reading = 0;
                    635:         fclose(fInCert);
                    636:         Curl_unicodefree(cert_path);
                    637: 
                    638:         if(!continue_reading) {
                    639:           failf(data, "schannel: Failed to read cert file %s",
                    640:                 data->set.ssl.cert);
                    641:           free(certdata);
                    642:           return CURLE_SSL_CERTPROBLEM;
                    643:         }
                    644: 
                    645:         /* Convert key-pair data to the in-memory certificate store */
                    646:         datablob.pbData = (BYTE*)certdata;
                    647:         datablob.cbData = (DWORD)filesize;
                    648: 
                    649:         if(data->set.ssl.key_passwd != NULL)
                    650:           pwd_len = strlen(data->set.ssl.key_passwd);
                    651:         pszPassword = (WCHAR*)malloc(sizeof(WCHAR)*(pwd_len + 1));
                    652:         if(pwd_len > 0)
                    653:           str_w_len =
                    654:             MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS,
                    655:                                 data->set.ssl.key_passwd, (int)pwd_len,
                    656:                                 pszPassword, (int)(pwd_len + 1));
                    657: 
                    658:         if((str_w_len >= 0) && (str_w_len <= (int)pwd_len))
                    659:           pszPassword[str_w_len] = 0;
                    660:         else
                    661:           pszPassword[0] = 0;
                    662: 
                    663:         cert_store = PFXImportCertStore(&datablob, pszPassword, 0);
                    664:         free(pszPassword);
                    665:         free(certdata);
                    666:         if(cert_store == NULL) {
                    667:           DWORD errorcode = GetLastError();
                    668:           if(errorcode == ERROR_INVALID_PASSWORD)
                    669:             failf(data, "schannel: Failed to import cert file %s, "
                    670:                   "password is bad", data->set.ssl.cert);
                    671:           else
                    672:             failf(data, "schannel: Failed to import cert file %s, "
                    673:                   "last error is 0x%x", data->set.ssl.cert, errorcode);
                    674:           return CURLE_SSL_CERTPROBLEM;
                    675:         }
                    676: 
                    677:         client_certs[0] = CertFindCertificateInStore(
                    678:             cert_store, X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, 0,
                    679:             CERT_FIND_ANY, NULL, NULL);
                    680: 
                    681:         if(client_certs[0] == NULL) {
                    682:           failf(data, "schannel: Failed to get certificate from file %s"
                    683:                 ", last error is 0x%x",
                    684:                 data->set.ssl.cert, GetLastError());
                    685:           CertCloseStore(cert_store, 0);
                    686:           return CURLE_SSL_CERTPROBLEM;
                    687:         }
                    688: 
                    689:         schannel_cred.cCreds = 1;
                    690:         schannel_cred.paCred = client_certs;
                    691:       }
                    692:       else {
                    693:         cert_store =
                    694:           CertOpenStore(CURL_CERT_STORE_PROV_SYSTEM, 0,
                    695:                         (HCRYPTPROV)NULL,
                    696:                         CERT_STORE_OPEN_EXISTING_FLAG | cert_store_name,
                    697:                         cert_store_path);
                    698:         if(!cert_store) {
                    699:           failf(data, "schannel: Failed to open cert store %x %s, "
                    700:                 "last error is 0x%x",
                    701:                 cert_store_name, cert_store_path, GetLastError());
                    702:           free(cert_store_path);
                    703:           Curl_unicodefree(cert_path);
                    704:           return CURLE_SSL_CERTPROBLEM;
                    705:         }
                    706:         free(cert_store_path);
                    707: 
                    708:         cert_thumbprint.pbData = cert_thumbprint_data;
                    709:         cert_thumbprint.cbData = CERT_THUMBPRINT_DATA_LEN;
                    710: 
                    711:         if(!CryptStringToBinary(cert_thumbprint_str,
                    712:                                 CERT_THUMBPRINT_STR_LEN,
                    713:                                 CRYPT_STRING_HEX,
                    714:                                 cert_thumbprint_data,
                    715:                                 &cert_thumbprint.cbData,
                    716:                                 NULL, NULL)) {
                    717:           Curl_unicodefree(cert_path);
                    718:           CertCloseStore(cert_store, 0);
                    719:           return CURLE_SSL_CERTPROBLEM;
                    720:         }
                    721: 
                    722:         client_certs[0] = CertFindCertificateInStore(
                    723:           cert_store, X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, 0,
                    724:           CERT_FIND_HASH, &cert_thumbprint, NULL);
                    725: 
                    726:         Curl_unicodefree(cert_path);
                    727: 
                    728:         if(client_certs[0]) {
                    729:           schannel_cred.cCreds = 1;
                    730:           schannel_cred.paCred = client_certs;
                    731:         }
                    732:         else {
                    733:           /* CRYPT_E_NOT_FOUND / E_INVALIDARG */
                    734:           CertCloseStore(cert_store, 0);
                    735:           return CURLE_SSL_CERTPROBLEM;
                    736:         }
                    737:       }
                    738:       CertCloseStore(cert_store, 0);
                    739:     }
                    740: #else
                    741:     if(data->set.ssl.cert) {
                    742:       failf(data, "schannel: client cert support not built in");
                    743:       return CURLE_NOT_BUILT_IN;
                    744:     }
                    745: #endif
                    746: 
                    747:     /* allocate memory for the re-usable credential handle */
                    748:     BACKEND->cred = (struct curl_schannel_cred *)
                    749:       calloc(1, sizeof(struct curl_schannel_cred));
                    750:     if(!BACKEND->cred) {
                    751:       failf(data, "schannel: unable to allocate memory");
                    752: 
                    753:       if(client_certs[0])
                    754:         CertFreeCertificateContext(client_certs[0]);
                    755: 
                    756:       return CURLE_OUT_OF_MEMORY;
                    757:     }
                    758:     BACKEND->cred->refcount = 1;
                    759: 
                    760:     /* https://msdn.microsoft.com/en-us/library/windows/desktop/aa374716.aspx
                    761:        */
                    762:     sspi_status =
                    763:       s_pSecFn->AcquireCredentialsHandle(NULL, (TCHAR *)UNISP_NAME,
                    764:                                          SECPKG_CRED_OUTBOUND, NULL,
                    765:                                          &schannel_cred, NULL, NULL,
                    766:                                          &BACKEND->cred->cred_handle,
                    767:                                          &BACKEND->cred->time_stamp);
                    768: 
                    769:     if(client_certs[0])
                    770:       CertFreeCertificateContext(client_certs[0]);
                    771: 
                    772:     if(sspi_status != SEC_E_OK) {
                    773:       char buffer[STRERROR_LEN];
                    774:       failf(data, "schannel: AcquireCredentialsHandle failed: %s",
                    775:             Curl_sspi_strerror(sspi_status, buffer, sizeof(buffer)));
                    776:       Curl_safefree(BACKEND->cred);
                    777:       switch(sspi_status) {
                    778:         case SEC_E_INSUFFICIENT_MEMORY:
                    779:           return CURLE_OUT_OF_MEMORY;
                    780:         case SEC_E_NO_CREDENTIALS:
                    781:         case SEC_E_SECPKG_NOT_FOUND:
                    782:         case SEC_E_NOT_OWNER:
                    783:         case SEC_E_UNKNOWN_CREDENTIALS:
                    784:         case SEC_E_INTERNAL_ERROR:
                    785:         default:
                    786:           return CURLE_SSL_CONNECT_ERROR;
                    787:       }
                    788:     }
                    789:   }
                    790: 
                    791:   /* Warn if SNI is disabled due to use of an IP address */
                    792:   if(Curl_inet_pton(AF_INET, hostname, &addr)
                    793: #ifdef ENABLE_IPV6
                    794:      || Curl_inet_pton(AF_INET6, hostname, &addr6)
                    795: #endif
                    796:     ) {
                    797:     infof(data, "schannel: using IP address, SNI is not supported by OS.\n");
                    798:   }
                    799: 
                    800: #ifdef HAS_ALPN
                    801:   if(BACKEND->use_alpn) {
                    802:     int cur = 0;
                    803:     int list_start_index = 0;
                    804:     unsigned int *extension_len = NULL;
                    805:     unsigned short* list_len = NULL;
                    806: 
                    807:     /* The first four bytes will be an unsigned int indicating number
                    808:        of bytes of data in the rest of the buffer. */
                    809:     extension_len = (unsigned int *)(&alpn_buffer[cur]);
                    810:     cur += sizeof(unsigned int);
                    811: 
                    812:     /* The next four bytes are an indicator that this buffer will contain
                    813:        ALPN data, as opposed to NPN, for example. */
                    814:     *(unsigned int *)&alpn_buffer[cur] =
                    815:       SecApplicationProtocolNegotiationExt_ALPN;
                    816:     cur += sizeof(unsigned int);
                    817: 
                    818:     /* The next two bytes will be an unsigned short indicating the number
                    819:        of bytes used to list the preferred protocols. */
                    820:     list_len = (unsigned short*)(&alpn_buffer[cur]);
                    821:     cur += sizeof(unsigned short);
                    822: 
                    823:     list_start_index = cur;
                    824: 
                    825: #ifdef USE_NGHTTP2
                    826:     if(data->set.httpversion >= CURL_HTTP_VERSION_2) {
                    827:       memcpy(&alpn_buffer[cur], NGHTTP2_PROTO_ALPN, NGHTTP2_PROTO_ALPN_LEN);
                    828:       cur += NGHTTP2_PROTO_ALPN_LEN;
                    829:       infof(data, "schannel: ALPN, offering %s\n", NGHTTP2_PROTO_VERSION_ID);
                    830:     }
                    831: #endif
                    832: 
                    833:     alpn_buffer[cur++] = ALPN_HTTP_1_1_LENGTH;
                    834:     memcpy(&alpn_buffer[cur], ALPN_HTTP_1_1, ALPN_HTTP_1_1_LENGTH);
                    835:     cur += ALPN_HTTP_1_1_LENGTH;
                    836:     infof(data, "schannel: ALPN, offering %s\n", ALPN_HTTP_1_1);
                    837: 
                    838:     *list_len = curlx_uitous(cur - list_start_index);
                    839:     *extension_len = *list_len + sizeof(unsigned int) + sizeof(unsigned short);
                    840: 
                    841:     InitSecBuffer(&inbuf, SECBUFFER_APPLICATION_PROTOCOLS, alpn_buffer, cur);
                    842:     InitSecBufferDesc(&inbuf_desc, &inbuf, 1);
                    843:   }
                    844:   else {
                    845:     InitSecBuffer(&inbuf, SECBUFFER_EMPTY, NULL, 0);
                    846:     InitSecBufferDesc(&inbuf_desc, &inbuf, 1);
                    847:   }
                    848: #else /* HAS_ALPN */
                    849:   InitSecBuffer(&inbuf, SECBUFFER_EMPTY, NULL, 0);
                    850:   InitSecBufferDesc(&inbuf_desc, &inbuf, 1);
                    851: #endif
                    852: 
                    853:   /* setup output buffer */
                    854:   InitSecBuffer(&outbuf, SECBUFFER_EMPTY, NULL, 0);
                    855:   InitSecBufferDesc(&outbuf_desc, &outbuf, 1);
                    856: 
                    857:   /* setup request flags */
                    858:   BACKEND->req_flags = ISC_REQ_SEQUENCE_DETECT | ISC_REQ_REPLAY_DETECT |
                    859:     ISC_REQ_CONFIDENTIALITY | ISC_REQ_ALLOCATE_MEMORY |
                    860:     ISC_REQ_STREAM;
                    861: 
                    862:   /* allocate memory for the security context handle */
                    863:   BACKEND->ctxt = (struct curl_schannel_ctxt *)
                    864:     calloc(1, sizeof(struct curl_schannel_ctxt));
                    865:   if(!BACKEND->ctxt) {
                    866:     failf(data, "schannel: unable to allocate memory");
                    867:     return CURLE_OUT_OF_MEMORY;
                    868:   }
                    869: 
                    870:   host_name = Curl_convert_UTF8_to_tchar(hostname);
                    871:   if(!host_name)
                    872:     return CURLE_OUT_OF_MEMORY;
                    873: 
                    874:   /* Schannel InitializeSecurityContext:
                    875:      https://msdn.microsoft.com/en-us/library/windows/desktop/aa375924.aspx
                    876: 
                    877:      At the moment we don't pass inbuf unless we're using ALPN since we only
                    878:      use it for that, and Wine (for which we currently disable ALPN) is giving
                    879:      us problems with inbuf regardless. https://github.com/curl/curl/issues/983
                    880:   */
                    881:   sspi_status = s_pSecFn->InitializeSecurityContext(
                    882:     &BACKEND->cred->cred_handle, NULL, host_name, BACKEND->req_flags, 0, 0,
                    883:     (BACKEND->use_alpn ? &inbuf_desc : NULL),
                    884:     0, &BACKEND->ctxt->ctxt_handle,
                    885:     &outbuf_desc, &BACKEND->ret_flags, &BACKEND->ctxt->time_stamp);
                    886: 
                    887:   Curl_unicodefree(host_name);
                    888: 
                    889:   if(sspi_status != SEC_I_CONTINUE_NEEDED) {
                    890:     char buffer[STRERROR_LEN];
                    891:     Curl_safefree(BACKEND->ctxt);
                    892:     switch(sspi_status) {
                    893:       case SEC_E_INSUFFICIENT_MEMORY:
                    894:         failf(data, "schannel: initial InitializeSecurityContext failed: %s",
                    895:               Curl_sspi_strerror(sspi_status, buffer, sizeof(buffer)));
                    896:         return CURLE_OUT_OF_MEMORY;
                    897:       case SEC_E_WRONG_PRINCIPAL:
                    898:         failf(data, "schannel: SNI or certificate check failed: %s",
                    899:               Curl_sspi_strerror(sspi_status, buffer, sizeof(buffer)));
                    900:         return CURLE_PEER_FAILED_VERIFICATION;
                    901:         /*
                    902:       case SEC_E_INVALID_HANDLE:
                    903:       case SEC_E_INVALID_TOKEN:
                    904:       case SEC_E_LOGON_DENIED:
                    905:       case SEC_E_TARGET_UNKNOWN:
                    906:       case SEC_E_NO_AUTHENTICATING_AUTHORITY:
                    907:       case SEC_E_INTERNAL_ERROR:
                    908:       case SEC_E_NO_CREDENTIALS:
                    909:       case SEC_E_UNSUPPORTED_FUNCTION:
                    910:       case SEC_E_APPLICATION_PROTOCOL_MISMATCH:
                    911:         */
                    912:       default:
                    913:         failf(data, "schannel: initial InitializeSecurityContext failed: %s",
                    914:               Curl_sspi_strerror(sspi_status, buffer, sizeof(buffer)));
                    915:         return CURLE_SSL_CONNECT_ERROR;
                    916:     }
                    917:   }
                    918: 
                    919:   DEBUGF(infof(data, "schannel: sending initial handshake data: "
                    920:                "sending %lu bytes...\n", outbuf.cbBuffer));
                    921: 
                    922:   /* send initial handshake data which is now stored in output buffer */
                    923:   result = Curl_write_plain(conn, conn->sock[sockindex], outbuf.pvBuffer,
                    924:                             outbuf.cbBuffer, &written);
                    925:   s_pSecFn->FreeContextBuffer(outbuf.pvBuffer);
                    926:   if((result != CURLE_OK) || (outbuf.cbBuffer != (size_t) written)) {
                    927:     failf(data, "schannel: failed to send initial handshake data: "
                    928:           "sent %zd of %lu bytes", written, outbuf.cbBuffer);
                    929:     return CURLE_SSL_CONNECT_ERROR;
                    930:   }
                    931: 
                    932:   DEBUGF(infof(data, "schannel: sent initial handshake data: "
                    933:                "sent %zd bytes\n", written));
                    934: 
                    935:   BACKEND->recv_unrecoverable_err = CURLE_OK;
                    936:   BACKEND->recv_sspi_close_notify = false;
                    937:   BACKEND->recv_connection_closed = false;
                    938:   BACKEND->encdata_is_incomplete = false;
                    939: 
                    940:   /* continue to second handshake step */
                    941:   connssl->connecting_state = ssl_connect_2;
                    942: 
                    943:   return CURLE_OK;
                    944: }
                    945: 
                    946: static CURLcode
                    947: schannel_connect_step2(struct connectdata *conn, int sockindex)
                    948: {
                    949:   int i;
                    950:   ssize_t nread = -1, written = -1;
                    951:   struct Curl_easy *data = conn->data;
                    952:   struct ssl_connect_data *connssl = &conn->ssl[sockindex];
                    953:   unsigned char *reallocated_buffer;
                    954:   SecBuffer outbuf[3];
                    955:   SecBufferDesc outbuf_desc;
                    956:   SecBuffer inbuf[2];
                    957:   SecBufferDesc inbuf_desc;
                    958:   SECURITY_STATUS sspi_status = SEC_E_OK;
                    959:   CURLcode result;
                    960:   bool doread;
                    961:   char * const hostname = SSL_IS_PROXY() ? conn->http_proxy.host.name :
                    962:     conn->host.name;
                    963:   const char *pubkey_ptr;
                    964: 
                    965:   doread = (connssl->connecting_state != ssl_connect_2_writing) ? TRUE : FALSE;
                    966: 
                    967:   DEBUGF(infof(data,
                    968:                "schannel: SSL/TLS connection with %s port %hu (step 2/3)\n",
                    969:                hostname, conn->remote_port));
                    970: 
                    971:   if(!BACKEND->cred || !BACKEND->ctxt)
                    972:     return CURLE_SSL_CONNECT_ERROR;
                    973: 
                    974:   /* buffer to store previously received and decrypted data */
                    975:   if(BACKEND->decdata_buffer == NULL) {
                    976:     BACKEND->decdata_offset = 0;
                    977:     BACKEND->decdata_length = CURL_SCHANNEL_BUFFER_INIT_SIZE;
                    978:     BACKEND->decdata_buffer = malloc(BACKEND->decdata_length);
                    979:     if(BACKEND->decdata_buffer == NULL) {
                    980:       failf(data, "schannel: unable to allocate memory");
                    981:       return CURLE_OUT_OF_MEMORY;
                    982:     }
                    983:   }
                    984: 
                    985:   /* buffer to store previously received and encrypted data */
                    986:   if(BACKEND->encdata_buffer == NULL) {
                    987:     BACKEND->encdata_is_incomplete = false;
                    988:     BACKEND->encdata_offset = 0;
                    989:     BACKEND->encdata_length = CURL_SCHANNEL_BUFFER_INIT_SIZE;
                    990:     BACKEND->encdata_buffer = malloc(BACKEND->encdata_length);
                    991:     if(BACKEND->encdata_buffer == NULL) {
                    992:       failf(data, "schannel: unable to allocate memory");
                    993:       return CURLE_OUT_OF_MEMORY;
                    994:     }
                    995:   }
                    996: 
                    997:   /* if we need a bigger buffer to read a full message, increase buffer now */
                    998:   if(BACKEND->encdata_length - BACKEND->encdata_offset <
                    999:      CURL_SCHANNEL_BUFFER_FREE_SIZE) {
                   1000:     /* increase internal encrypted data buffer */
                   1001:     size_t reallocated_length = BACKEND->encdata_offset +
                   1002:       CURL_SCHANNEL_BUFFER_FREE_SIZE;
                   1003:     reallocated_buffer = realloc(BACKEND->encdata_buffer,
                   1004:                                  reallocated_length);
                   1005: 
                   1006:     if(reallocated_buffer == NULL) {
                   1007:       failf(data, "schannel: unable to re-allocate memory");
                   1008:       return CURLE_OUT_OF_MEMORY;
                   1009:     }
                   1010:     else {
                   1011:       BACKEND->encdata_buffer = reallocated_buffer;
                   1012:       BACKEND->encdata_length = reallocated_length;
                   1013:     }
                   1014:   }
                   1015: 
                   1016:   for(;;) {
                   1017:     TCHAR *host_name;
                   1018:     if(doread) {
                   1019:       /* read encrypted handshake data from socket */
                   1020:       result = Curl_read_plain(conn->sock[sockindex],
                   1021:                                (char *) (BACKEND->encdata_buffer +
                   1022:                                          BACKEND->encdata_offset),
                   1023:                                BACKEND->encdata_length -
                   1024:                                BACKEND->encdata_offset,
                   1025:                                &nread);
                   1026:       if(result == CURLE_AGAIN) {
                   1027:         if(connssl->connecting_state != ssl_connect_2_writing)
                   1028:           connssl->connecting_state = ssl_connect_2_reading;
                   1029:         DEBUGF(infof(data, "schannel: failed to receive handshake, "
                   1030:                      "need more data\n"));
                   1031:         return CURLE_OK;
                   1032:       }
                   1033:       else if((result != CURLE_OK) || (nread == 0)) {
                   1034:         failf(data, "schannel: failed to receive handshake, "
                   1035:               "SSL/TLS connection failed");
                   1036:         return CURLE_SSL_CONNECT_ERROR;
                   1037:       }
                   1038: 
                   1039:       /* increase encrypted data buffer offset */
                   1040:       BACKEND->encdata_offset += nread;
                   1041:       BACKEND->encdata_is_incomplete = false;
                   1042:       DEBUGF(infof(data, "schannel: encrypted data got %zd\n", nread));
                   1043:     }
                   1044: 
                   1045:     DEBUGF(infof(data,
                   1046:                  "schannel: encrypted data buffer: offset %zu length %zu\n",
                   1047:                  BACKEND->encdata_offset, BACKEND->encdata_length));
                   1048: 
                   1049:     /* setup input buffers */
                   1050:     InitSecBuffer(&inbuf[0], SECBUFFER_TOKEN, malloc(BACKEND->encdata_offset),
                   1051:                   curlx_uztoul(BACKEND->encdata_offset));
                   1052:     InitSecBuffer(&inbuf[1], SECBUFFER_EMPTY, NULL, 0);
                   1053:     InitSecBufferDesc(&inbuf_desc, inbuf, 2);
                   1054: 
                   1055:     /* setup output buffers */
                   1056:     InitSecBuffer(&outbuf[0], SECBUFFER_TOKEN, NULL, 0);
                   1057:     InitSecBuffer(&outbuf[1], SECBUFFER_ALERT, NULL, 0);
                   1058:     InitSecBuffer(&outbuf[2], SECBUFFER_EMPTY, NULL, 0);
                   1059:     InitSecBufferDesc(&outbuf_desc, outbuf, 3);
                   1060: 
                   1061:     if(inbuf[0].pvBuffer == NULL) {
                   1062:       failf(data, "schannel: unable to allocate memory");
                   1063:       return CURLE_OUT_OF_MEMORY;
                   1064:     }
                   1065: 
                   1066:     /* copy received handshake data into input buffer */
                   1067:     memcpy(inbuf[0].pvBuffer, BACKEND->encdata_buffer,
                   1068:            BACKEND->encdata_offset);
                   1069: 
                   1070:     host_name = Curl_convert_UTF8_to_tchar(hostname);
                   1071:     if(!host_name)
                   1072:       return CURLE_OUT_OF_MEMORY;
                   1073: 
                   1074:     /* https://msdn.microsoft.com/en-us/library/windows/desktop/aa375924.aspx
                   1075:        */
                   1076:     sspi_status = s_pSecFn->InitializeSecurityContext(
                   1077:       &BACKEND->cred->cred_handle, &BACKEND->ctxt->ctxt_handle,
                   1078:       host_name, BACKEND->req_flags, 0, 0, &inbuf_desc, 0, NULL,
                   1079:       &outbuf_desc, &BACKEND->ret_flags, &BACKEND->ctxt->time_stamp);
                   1080: 
                   1081:     Curl_unicodefree(host_name);
                   1082: 
                   1083:     /* free buffer for received handshake data */
                   1084:     Curl_safefree(inbuf[0].pvBuffer);
                   1085: 
                   1086:     /* check if the handshake was incomplete */
                   1087:     if(sspi_status == SEC_E_INCOMPLETE_MESSAGE) {
                   1088:       BACKEND->encdata_is_incomplete = true;
                   1089:       connssl->connecting_state = ssl_connect_2_reading;
                   1090:       DEBUGF(infof(data,
                   1091:                    "schannel: received incomplete message, need more data\n"));
                   1092:       return CURLE_OK;
                   1093:     }
                   1094: 
                   1095:     /* If the server has requested a client certificate, attempt to continue
                   1096:        the handshake without one. This will allow connections to servers which
                   1097:        request a client certificate but do not require it. */
                   1098:     if(sspi_status == SEC_I_INCOMPLETE_CREDENTIALS &&
                   1099:        !(BACKEND->req_flags & ISC_REQ_USE_SUPPLIED_CREDS)) {
                   1100:       BACKEND->req_flags |= ISC_REQ_USE_SUPPLIED_CREDS;
                   1101:       connssl->connecting_state = ssl_connect_2_writing;
                   1102:       DEBUGF(infof(data,
                   1103:                    "schannel: a client certificate has been requested\n"));
                   1104:       return CURLE_OK;
                   1105:     }
                   1106: 
                   1107:     /* check if the handshake needs to be continued */
                   1108:     if(sspi_status == SEC_I_CONTINUE_NEEDED || sspi_status == SEC_E_OK) {
                   1109:       for(i = 0; i < 3; i++) {
                   1110:         /* search for handshake tokens that need to be send */
                   1111:         if(outbuf[i].BufferType == SECBUFFER_TOKEN && outbuf[i].cbBuffer > 0) {
                   1112:           DEBUGF(infof(data, "schannel: sending next handshake data: "
                   1113:                        "sending %lu bytes...\n", outbuf[i].cbBuffer));
                   1114: 
                   1115:           /* send handshake token to server */
                   1116:           result = Curl_write_plain(conn, conn->sock[sockindex],
                   1117:                                     outbuf[i].pvBuffer, outbuf[i].cbBuffer,
                   1118:                                     &written);
                   1119:           if((result != CURLE_OK) ||
                   1120:              (outbuf[i].cbBuffer != (size_t) written)) {
                   1121:             failf(data, "schannel: failed to send next handshake data: "
                   1122:                   "sent %zd of %lu bytes", written, outbuf[i].cbBuffer);
                   1123:             return CURLE_SSL_CONNECT_ERROR;
                   1124:           }
                   1125:         }
                   1126: 
                   1127:         /* free obsolete buffer */
                   1128:         if(outbuf[i].pvBuffer != NULL) {
                   1129:           s_pSecFn->FreeContextBuffer(outbuf[i].pvBuffer);
                   1130:         }
                   1131:       }
                   1132:     }
                   1133:     else {
                   1134:       char buffer[STRERROR_LEN];
                   1135:       switch(sspi_status) {
                   1136:         case SEC_E_INSUFFICIENT_MEMORY:
                   1137:           failf(data, "schannel: next InitializeSecurityContext failed: %s",
                   1138:                 Curl_sspi_strerror(sspi_status, buffer, sizeof(buffer)));
                   1139:           return CURLE_OUT_OF_MEMORY;
                   1140:         case SEC_E_WRONG_PRINCIPAL:
                   1141:           failf(data, "schannel: SNI or certificate check failed: %s",
                   1142:                 Curl_sspi_strerror(sspi_status, buffer, sizeof(buffer)));
                   1143:           return CURLE_PEER_FAILED_VERIFICATION;
                   1144:           /*
                   1145:         case SEC_E_INVALID_HANDLE:
                   1146:         case SEC_E_INVALID_TOKEN:
                   1147:         case SEC_E_LOGON_DENIED:
                   1148:         case SEC_E_TARGET_UNKNOWN:
                   1149:         case SEC_E_NO_AUTHENTICATING_AUTHORITY:
                   1150:         case SEC_E_INTERNAL_ERROR:
                   1151:         case SEC_E_NO_CREDENTIALS:
                   1152:         case SEC_E_UNSUPPORTED_FUNCTION:
                   1153:         case SEC_E_APPLICATION_PROTOCOL_MISMATCH:
                   1154:           */
                   1155:         default:
                   1156:           failf(data, "schannel: next InitializeSecurityContext failed: %s",
                   1157:                 Curl_sspi_strerror(sspi_status, buffer, sizeof(buffer)));
                   1158:           return CURLE_SSL_CONNECT_ERROR;
                   1159:       }
                   1160:     }
                   1161: 
                   1162:     /* check if there was additional remaining encrypted data */
                   1163:     if(inbuf[1].BufferType == SECBUFFER_EXTRA && inbuf[1].cbBuffer > 0) {
                   1164:       DEBUGF(infof(data, "schannel: encrypted data length: %lu\n",
                   1165:                    inbuf[1].cbBuffer));
                   1166:       /*
                   1167:         There are two cases where we could be getting extra data here:
                   1168:         1) If we're renegotiating a connection and the handshake is already
                   1169:         complete (from the server perspective), it can encrypted app data
                   1170:         (not handshake data) in an extra buffer at this point.
                   1171:         2) (sspi_status == SEC_I_CONTINUE_NEEDED) We are negotiating a
                   1172:         connection and this extra data is part of the handshake.
                   1173:         We should process the data immediately; waiting for the socket to
                   1174:         be ready may fail since the server is done sending handshake data.
                   1175:       */
                   1176:       /* check if the remaining data is less than the total amount
                   1177:          and therefore begins after the already processed data */
                   1178:       if(BACKEND->encdata_offset > inbuf[1].cbBuffer) {
                   1179:         memmove(BACKEND->encdata_buffer,
                   1180:                 (BACKEND->encdata_buffer + BACKEND->encdata_offset) -
                   1181:                 inbuf[1].cbBuffer, inbuf[1].cbBuffer);
                   1182:         BACKEND->encdata_offset = inbuf[1].cbBuffer;
                   1183:         if(sspi_status == SEC_I_CONTINUE_NEEDED) {
                   1184:           doread = FALSE;
                   1185:           continue;
                   1186:         }
                   1187:       }
                   1188:     }
                   1189:     else {
                   1190:       BACKEND->encdata_offset = 0;
                   1191:     }
                   1192:     break;
                   1193:   }
                   1194: 
                   1195:   /* check if the handshake needs to be continued */
                   1196:   if(sspi_status == SEC_I_CONTINUE_NEEDED) {
                   1197:     connssl->connecting_state = ssl_connect_2_reading;
                   1198:     return CURLE_OK;
                   1199:   }
                   1200: 
                   1201:   /* check if the handshake is complete */
                   1202:   if(sspi_status == SEC_E_OK) {
                   1203:     connssl->connecting_state = ssl_connect_3;
                   1204:     DEBUGF(infof(data, "schannel: SSL/TLS handshake complete\n"));
                   1205:   }
                   1206: 
                   1207:   pubkey_ptr = SSL_IS_PROXY() ?
                   1208:     data->set.str[STRING_SSL_PINNEDPUBLICKEY_PROXY] :
                   1209:     data->set.str[STRING_SSL_PINNEDPUBLICKEY_ORIG];
                   1210:   if(pubkey_ptr) {
                   1211:     result = pkp_pin_peer_pubkey(conn, sockindex, pubkey_ptr);
                   1212:     if(result) {
                   1213:       failf(data, "SSL: public key does not match pinned public key!");
                   1214:       return result;
                   1215:     }
                   1216:   }
                   1217: 
                   1218: #ifdef HAS_MANUAL_VERIFY_API
                   1219:   if(conn->ssl_config.verifypeer && BACKEND->use_manual_cred_validation) {
                   1220:     return Curl_verify_certificate(conn, sockindex);
                   1221:   }
                   1222: #endif
                   1223: 
                   1224:   return CURLE_OK;
                   1225: }
                   1226: 
                   1227: static bool
                   1228: valid_cert_encoding(const CERT_CONTEXT *cert_context)
                   1229: {
                   1230:   return (cert_context != NULL) &&
                   1231:     ((cert_context->dwCertEncodingType & X509_ASN_ENCODING) != 0) &&
                   1232:     (cert_context->pbCertEncoded != NULL) &&
                   1233:     (cert_context->cbCertEncoded > 0);
                   1234: }
                   1235: 
                   1236: typedef bool(*Read_crt_func)(const CERT_CONTEXT *ccert_context, void *arg);
                   1237: 
                   1238: static void
                   1239: traverse_cert_store(const CERT_CONTEXT *context, Read_crt_func func,
                   1240:                     void *arg)
                   1241: {
                   1242:   const CERT_CONTEXT *current_context = NULL;
                   1243:   bool should_continue = true;
                   1244:   while(should_continue &&
                   1245:         (current_context = CertEnumCertificatesInStore(
                   1246:           context->hCertStore,
                   1247:           current_context)) != NULL)
                   1248:     should_continue = func(current_context, arg);
                   1249: 
                   1250:   if(current_context)
                   1251:     CertFreeCertificateContext(current_context);
                   1252: }
                   1253: 
                   1254: static bool
                   1255: cert_counter_callback(const CERT_CONTEXT *ccert_context, void *certs_count)
                   1256: {
                   1257:   if(valid_cert_encoding(ccert_context))
                   1258:     (*(int *)certs_count)++;
                   1259:   return true;
                   1260: }
                   1261: 
                   1262: struct Adder_args
                   1263: {
                   1264:   struct connectdata *conn;
                   1265:   CURLcode result;
                   1266:   int idx;
                   1267:   int certs_count;
                   1268: };
                   1269: 
                   1270: static bool
                   1271: add_cert_to_certinfo(const CERT_CONTEXT *ccert_context, void *raw_arg)
                   1272: {
                   1273:   struct Adder_args *args = (struct Adder_args*)raw_arg;
                   1274:   args->result = CURLE_OK;
                   1275:   if(valid_cert_encoding(ccert_context)) {
                   1276:     const char *beg = (const char *) ccert_context->pbCertEncoded;
                   1277:     const char *end = beg + ccert_context->cbCertEncoded;
                   1278:     int insert_index = (args->certs_count - 1) - args->idx;
                   1279:     args->result = Curl_extract_certinfo(args->conn, insert_index, beg, end);
                   1280:     args->idx++;
                   1281:   }
                   1282:   return args->result == CURLE_OK;
                   1283: }
                   1284: 
                   1285: static CURLcode
                   1286: schannel_connect_step3(struct connectdata *conn, int sockindex)
                   1287: {
                   1288:   CURLcode result = CURLE_OK;
                   1289:   struct Curl_easy *data = conn->data;
                   1290:   struct ssl_connect_data *connssl = &conn->ssl[sockindex];
                   1291:   SECURITY_STATUS sspi_status = SEC_E_OK;
                   1292:   CERT_CONTEXT *ccert_context = NULL;
                   1293: #ifdef DEBUGBUILD
                   1294:   const char * const hostname = SSL_IS_PROXY() ? conn->http_proxy.host.name :
                   1295:     conn->host.name;
                   1296: #endif
                   1297: #ifdef HAS_ALPN
                   1298:   SecPkgContext_ApplicationProtocol alpn_result;
                   1299: #endif
                   1300: 
                   1301:   DEBUGASSERT(ssl_connect_3 == connssl->connecting_state);
                   1302: 
                   1303:   DEBUGF(infof(data,
                   1304:                "schannel: SSL/TLS connection with %s port %hu (step 3/3)\n",
                   1305:                hostname, conn->remote_port));
                   1306: 
                   1307:   if(!BACKEND->cred)
                   1308:     return CURLE_SSL_CONNECT_ERROR;
                   1309: 
                   1310:   /* check if the required context attributes are met */
                   1311:   if(BACKEND->ret_flags != BACKEND->req_flags) {
                   1312:     if(!(BACKEND->ret_flags & ISC_RET_SEQUENCE_DETECT))
                   1313:       failf(data, "schannel: failed to setup sequence detection");
                   1314:     if(!(BACKEND->ret_flags & ISC_RET_REPLAY_DETECT))
                   1315:       failf(data, "schannel: failed to setup replay detection");
                   1316:     if(!(BACKEND->ret_flags & ISC_RET_CONFIDENTIALITY))
                   1317:       failf(data, "schannel: failed to setup confidentiality");
                   1318:     if(!(BACKEND->ret_flags & ISC_RET_ALLOCATED_MEMORY))
                   1319:       failf(data, "schannel: failed to setup memory allocation");
                   1320:     if(!(BACKEND->ret_flags & ISC_RET_STREAM))
                   1321:       failf(data, "schannel: failed to setup stream orientation");
                   1322:     return CURLE_SSL_CONNECT_ERROR;
                   1323:   }
                   1324: 
                   1325: #ifdef HAS_ALPN
                   1326:   if(BACKEND->use_alpn) {
                   1327:     sspi_status = s_pSecFn->QueryContextAttributes(&BACKEND->ctxt->ctxt_handle,
                   1328:       SECPKG_ATTR_APPLICATION_PROTOCOL, &alpn_result);
                   1329: 
                   1330:     if(sspi_status != SEC_E_OK) {
                   1331:       failf(data, "schannel: failed to retrieve ALPN result");
                   1332:       return CURLE_SSL_CONNECT_ERROR;
                   1333:     }
                   1334: 
                   1335:     if(alpn_result.ProtoNegoStatus ==
                   1336:        SecApplicationProtocolNegotiationStatus_Success) {
                   1337: 
                   1338:       infof(data, "schannel: ALPN, server accepted to use %.*s\n",
                   1339:         alpn_result.ProtocolIdSize, alpn_result.ProtocolId);
                   1340: 
                   1341: #ifdef USE_NGHTTP2
                   1342:       if(alpn_result.ProtocolIdSize == NGHTTP2_PROTO_VERSION_ID_LEN &&
                   1343:          !memcmp(NGHTTP2_PROTO_VERSION_ID, alpn_result.ProtocolId,
                   1344:           NGHTTP2_PROTO_VERSION_ID_LEN)) {
                   1345:         conn->negnpn = CURL_HTTP_VERSION_2;
                   1346:       }
                   1347:       else
                   1348: #endif
                   1349:       if(alpn_result.ProtocolIdSize == ALPN_HTTP_1_1_LENGTH &&
                   1350:          !memcmp(ALPN_HTTP_1_1, alpn_result.ProtocolId,
                   1351:            ALPN_HTTP_1_1_LENGTH)) {
                   1352:         conn->negnpn = CURL_HTTP_VERSION_1_1;
                   1353:       }
                   1354:     }
                   1355:     else
                   1356:       infof(data, "ALPN, server did not agree to a protocol\n");
                   1357:     Curl_multiuse_state(conn, conn->negnpn == CURL_HTTP_VERSION_2 ?
                   1358:                         BUNDLE_MULTIPLEX : BUNDLE_NO_MULTIUSE);
                   1359:   }
                   1360: #endif
                   1361: 
                   1362:   /* save the current session data for possible re-use */
                   1363:   if(SSL_SET_OPTION(primary.sessionid)) {
                   1364:     bool incache;
                   1365:     struct curl_schannel_cred *old_cred = NULL;
                   1366: 
                   1367:     Curl_ssl_sessionid_lock(conn);
                   1368:     incache = !(Curl_ssl_getsessionid(conn, (void **)&old_cred, NULL,
                   1369:                                       sockindex));
                   1370:     if(incache) {
                   1371:       if(old_cred != BACKEND->cred) {
                   1372:         DEBUGF(infof(data,
                   1373:                      "schannel: old credential handle is stale, removing\n"));
                   1374:         /* we're not taking old_cred ownership here, no refcount++ is needed */
                   1375:         Curl_ssl_delsessionid(conn, (void *)old_cred);
                   1376:         incache = FALSE;
                   1377:       }
                   1378:     }
                   1379:     if(!incache) {
                   1380:       result = Curl_ssl_addsessionid(conn, (void *)BACKEND->cred,
                   1381:                                      sizeof(struct curl_schannel_cred),
                   1382:                                      sockindex);
                   1383:       if(result) {
                   1384:         Curl_ssl_sessionid_unlock(conn);
                   1385:         failf(data, "schannel: failed to store credential handle");
                   1386:         return result;
                   1387:       }
                   1388:       else {
                   1389:         /* this cred session is now also referenced by sessionid cache */
                   1390:         BACKEND->cred->refcount++;
                   1391:         DEBUGF(infof(data,
                   1392:                      "schannel: stored credential handle in session cache\n"));
                   1393:       }
                   1394:     }
                   1395:     Curl_ssl_sessionid_unlock(conn);
                   1396:   }
                   1397: 
                   1398:   if(data->set.ssl.certinfo) {
                   1399:     int certs_count = 0;
                   1400:     sspi_status = s_pSecFn->QueryContextAttributes(&BACKEND->ctxt->ctxt_handle,
                   1401:       SECPKG_ATTR_REMOTE_CERT_CONTEXT, &ccert_context);
                   1402: 
                   1403:     if((sspi_status != SEC_E_OK) || (ccert_context == NULL)) {
                   1404:       failf(data, "schannel: failed to retrieve remote cert context");
                   1405:       return CURLE_PEER_FAILED_VERIFICATION;
                   1406:     }
                   1407: 
                   1408:     traverse_cert_store(ccert_context, cert_counter_callback, &certs_count);
                   1409: 
                   1410:     result = Curl_ssl_init_certinfo(data, certs_count);
                   1411:     if(!result) {
                   1412:       struct Adder_args args;
                   1413:       args.conn = conn;
                   1414:       args.idx = 0;
                   1415:       args.certs_count = certs_count;
                   1416:       traverse_cert_store(ccert_context, add_cert_to_certinfo, &args);
                   1417:       result = args.result;
                   1418:     }
                   1419:     CertFreeCertificateContext(ccert_context);
                   1420:     if(result)
                   1421:       return result;
                   1422:   }
                   1423: 
                   1424:   connssl->connecting_state = ssl_connect_done;
                   1425: 
                   1426:   return CURLE_OK;
                   1427: }
                   1428: 
                   1429: static CURLcode
                   1430: schannel_connect_common(struct connectdata *conn, int sockindex,
                   1431:                         bool nonblocking, bool *done)
                   1432: {
                   1433:   CURLcode result;
                   1434:   struct Curl_easy *data = conn->data;
                   1435:   struct ssl_connect_data *connssl = &conn->ssl[sockindex];
                   1436:   curl_socket_t sockfd = conn->sock[sockindex];
                   1437:   timediff_t timeout_ms;
                   1438:   int what;
                   1439: 
                   1440:   /* check if the connection has already been established */
                   1441:   if(ssl_connection_complete == connssl->state) {
                   1442:     *done = TRUE;
                   1443:     return CURLE_OK;
                   1444:   }
                   1445: 
                   1446:   if(ssl_connect_1 == connssl->connecting_state) {
                   1447:     /* check out how much more time we're allowed */
                   1448:     timeout_ms = Curl_timeleft(data, NULL, TRUE);
                   1449: 
                   1450:     if(timeout_ms < 0) {
                   1451:       /* no need to continue if time already is up */
                   1452:       failf(data, "SSL/TLS connection timeout");
                   1453:       return CURLE_OPERATION_TIMEDOUT;
                   1454:     }
                   1455: 
                   1456:     result = schannel_connect_step1(conn, sockindex);
                   1457:     if(result)
                   1458:       return result;
                   1459:   }
                   1460: 
                   1461:   while(ssl_connect_2 == connssl->connecting_state ||
                   1462:         ssl_connect_2_reading == connssl->connecting_state ||
                   1463:         ssl_connect_2_writing == connssl->connecting_state) {
                   1464: 
                   1465:     /* check out how much more time we're allowed */
                   1466:     timeout_ms = Curl_timeleft(data, NULL, TRUE);
                   1467: 
                   1468:     if(timeout_ms < 0) {
                   1469:       /* no need to continue if time already is up */
                   1470:       failf(data, "SSL/TLS connection timeout");
                   1471:       return CURLE_OPERATION_TIMEDOUT;
                   1472:     }
                   1473: 
                   1474:     /* if ssl is expecting something, check if it's available. */
                   1475:     if(connssl->connecting_state == ssl_connect_2_reading
                   1476:        || connssl->connecting_state == ssl_connect_2_writing) {
                   1477: 
                   1478:       curl_socket_t writefd = ssl_connect_2_writing ==
                   1479:         connssl->connecting_state ? sockfd : CURL_SOCKET_BAD;
                   1480:       curl_socket_t readfd = ssl_connect_2_reading ==
                   1481:         connssl->connecting_state ? sockfd : CURL_SOCKET_BAD;
                   1482: 
                   1483:       what = Curl_socket_check(readfd, CURL_SOCKET_BAD, writefd,
                   1484:                                nonblocking ? 0 : (time_t)timeout_ms);
                   1485:       if(what < 0) {
                   1486:         /* fatal error */
                   1487:         failf(data, "select/poll on SSL/TLS socket, errno: %d", SOCKERRNO);
                   1488:         return CURLE_SSL_CONNECT_ERROR;
                   1489:       }
                   1490:       else if(0 == what) {
                   1491:         if(nonblocking) {
                   1492:           *done = FALSE;
                   1493:           return CURLE_OK;
                   1494:         }
                   1495:         else {
                   1496:           /* timeout */
                   1497:           failf(data, "SSL/TLS connection timeout");
                   1498:           return CURLE_OPERATION_TIMEDOUT;
                   1499:         }
                   1500:       }
                   1501:       /* socket is readable or writable */
                   1502:     }
                   1503: 
                   1504:     /* Run transaction, and return to the caller if it failed or if
                   1505:      * this connection is part of a multi handle and this loop would
                   1506:      * execute again. This permits the owner of a multi handle to
                   1507:      * abort a connection attempt before step2 has completed while
                   1508:      * ensuring that a client using select() or epoll() will always
                   1509:      * have a valid fdset to wait on.
                   1510:      */
                   1511:     result = schannel_connect_step2(conn, sockindex);
                   1512:     if(result || (nonblocking &&
                   1513:                   (ssl_connect_2 == connssl->connecting_state ||
                   1514:                    ssl_connect_2_reading == connssl->connecting_state ||
                   1515:                    ssl_connect_2_writing == connssl->connecting_state)))
                   1516:       return result;
                   1517: 
                   1518:   } /* repeat step2 until all transactions are done. */
                   1519: 
                   1520:   if(ssl_connect_3 == connssl->connecting_state) {
                   1521:     result = schannel_connect_step3(conn, sockindex);
                   1522:     if(result)
                   1523:       return result;
                   1524:   }
                   1525: 
                   1526:   if(ssl_connect_done == connssl->connecting_state) {
                   1527:     connssl->state = ssl_connection_complete;
                   1528:     conn->recv[sockindex] = schannel_recv;
                   1529:     conn->send[sockindex] = schannel_send;
                   1530: 
                   1531: #ifdef SECPKG_ATTR_ENDPOINT_BINDINGS
                   1532:     /* When SSPI is used in combination with Schannel
                   1533:      * we need the Schannel context to create the Schannel
                   1534:      * binding to pass the IIS extended protection checks.
                   1535:      * Available on Windows 7 or later.
                   1536:      */
                   1537:     conn->sslContext = &BACKEND->ctxt->ctxt_handle;
                   1538: #endif
                   1539: 
                   1540:     *done = TRUE;
                   1541:   }
                   1542:   else
                   1543:     *done = FALSE;
                   1544: 
                   1545:   /* reset our connection state machine */
                   1546:   connssl->connecting_state = ssl_connect_1;
                   1547: 
                   1548:   return CURLE_OK;
                   1549: }
                   1550: 
                   1551: static ssize_t
                   1552: schannel_send(struct connectdata *conn, int sockindex,
                   1553:               const void *buf, size_t len, CURLcode *err)
                   1554: {
                   1555:   ssize_t written = -1;
                   1556:   size_t data_len = 0;
                   1557:   unsigned char *data = NULL;
                   1558:   struct ssl_connect_data *connssl = &conn->ssl[sockindex];
                   1559:   SecBuffer outbuf[4];
                   1560:   SecBufferDesc outbuf_desc;
                   1561:   SECURITY_STATUS sspi_status = SEC_E_OK;
                   1562:   CURLcode result;
                   1563: 
                   1564:   /* check if the maximum stream sizes were queried */
                   1565:   if(BACKEND->stream_sizes.cbMaximumMessage == 0) {
                   1566:     sspi_status = s_pSecFn->QueryContextAttributes(
                   1567:       &BACKEND->ctxt->ctxt_handle,
                   1568:       SECPKG_ATTR_STREAM_SIZES,
                   1569:       &BACKEND->stream_sizes);
                   1570:     if(sspi_status != SEC_E_OK) {
                   1571:       *err = CURLE_SEND_ERROR;
                   1572:       return -1;
                   1573:     }
                   1574:   }
                   1575: 
                   1576:   /* check if the buffer is longer than the maximum message length */
                   1577:   if(len > BACKEND->stream_sizes.cbMaximumMessage) {
                   1578:     len = BACKEND->stream_sizes.cbMaximumMessage;
                   1579:   }
                   1580: 
                   1581:   /* calculate the complete message length and allocate a buffer for it */
                   1582:   data_len = BACKEND->stream_sizes.cbHeader + len +
                   1583:     BACKEND->stream_sizes.cbTrailer;
                   1584:   data = (unsigned char *) malloc(data_len);
                   1585:   if(data == NULL) {
                   1586:     *err = CURLE_OUT_OF_MEMORY;
                   1587:     return -1;
                   1588:   }
                   1589: 
                   1590:   /* setup output buffers (header, data, trailer, empty) */
                   1591:   InitSecBuffer(&outbuf[0], SECBUFFER_STREAM_HEADER,
                   1592:                 data, BACKEND->stream_sizes.cbHeader);
                   1593:   InitSecBuffer(&outbuf[1], SECBUFFER_DATA,
                   1594:                 data + BACKEND->stream_sizes.cbHeader, curlx_uztoul(len));
                   1595:   InitSecBuffer(&outbuf[2], SECBUFFER_STREAM_TRAILER,
                   1596:                 data + BACKEND->stream_sizes.cbHeader + len,
                   1597:                 BACKEND->stream_sizes.cbTrailer);
                   1598:   InitSecBuffer(&outbuf[3], SECBUFFER_EMPTY, NULL, 0);
                   1599:   InitSecBufferDesc(&outbuf_desc, outbuf, 4);
                   1600: 
                   1601:   /* copy data into output buffer */
                   1602:   memcpy(outbuf[1].pvBuffer, buf, len);
                   1603: 
                   1604:   /* https://msdn.microsoft.com/en-us/library/windows/desktop/aa375390.aspx */
                   1605:   sspi_status = s_pSecFn->EncryptMessage(&BACKEND->ctxt->ctxt_handle, 0,
                   1606:                                          &outbuf_desc, 0);
                   1607: 
                   1608:   /* check if the message was encrypted */
                   1609:   if(sspi_status == SEC_E_OK) {
                   1610:     written = 0;
                   1611: 
                   1612:     /* send the encrypted message including header, data and trailer */
                   1613:     len = outbuf[0].cbBuffer + outbuf[1].cbBuffer + outbuf[2].cbBuffer;
                   1614: 
                   1615:     /*
                   1616:       It's important to send the full message which includes the header,
                   1617:       encrypted payload, and trailer.  Until the client receives all the
                   1618:       data a coherent message has not been delivered and the client
                   1619:       can't read any of it.
                   1620: 
                   1621:       If we wanted to buffer the unwritten encrypted bytes, we would
                   1622:       tell the client that all data it has requested to be sent has been
                   1623:       sent. The unwritten encrypted bytes would be the first bytes to
                   1624:       send on the next invocation.
                   1625:       Here's the catch with this - if we tell the client that all the
                   1626:       bytes have been sent, will the client call this method again to
                   1627:       send the buffered data?  Looking at who calls this function, it
                   1628:       seems the answer is NO.
                   1629:     */
                   1630: 
                   1631:     /* send entire message or fail */
                   1632:     while(len > (size_t)written) {
                   1633:       ssize_t this_write;
                   1634:       timediff_t timeout_ms;
                   1635:       int what;
                   1636: 
                   1637:       this_write = 0;
                   1638: 
                   1639:       timeout_ms = Curl_timeleft(conn->data, NULL, FALSE);
                   1640:       if(timeout_ms < 0) {
                   1641:         /* we already got the timeout */
                   1642:         failf(conn->data, "schannel: timed out sending data "
                   1643:               "(bytes sent: %zd)", written);
                   1644:         *err = CURLE_OPERATION_TIMEDOUT;
                   1645:         written = -1;
                   1646:         break;
                   1647:       }
                   1648:       if(!timeout_ms)
                   1649:         timeout_ms = TIMEDIFF_T_MAX;
                   1650:       what = SOCKET_WRITABLE(conn->sock[sockindex], timeout_ms);
                   1651:       if(what < 0) {
                   1652:         /* fatal error */
                   1653:         failf(conn->data, "select/poll on SSL socket, errno: %d", SOCKERRNO);
                   1654:         *err = CURLE_SEND_ERROR;
                   1655:         written = -1;
                   1656:         break;
                   1657:       }
                   1658:       else if(0 == what) {
                   1659:         failf(conn->data, "schannel: timed out sending data "
                   1660:               "(bytes sent: %zd)", written);
                   1661:         *err = CURLE_OPERATION_TIMEDOUT;
                   1662:         written = -1;
                   1663:         break;
                   1664:       }
                   1665:       /* socket is writable */
                   1666: 
                   1667:       result = Curl_write_plain(conn, conn->sock[sockindex], data + written,
                   1668:                                 len - written, &this_write);
                   1669:       if(result == CURLE_AGAIN)
                   1670:         continue;
                   1671:       else if(result != CURLE_OK) {
                   1672:         *err = result;
                   1673:         written = -1;
                   1674:         break;
                   1675:       }
                   1676: 
                   1677:       written += this_write;
                   1678:     }
                   1679:   }
                   1680:   else if(sspi_status == SEC_E_INSUFFICIENT_MEMORY) {
                   1681:     *err = CURLE_OUT_OF_MEMORY;
                   1682:   }
                   1683:   else{
                   1684:     *err = CURLE_SEND_ERROR;
                   1685:   }
                   1686: 
                   1687:   Curl_safefree(data);
                   1688: 
                   1689:   if(len == (size_t)written)
                   1690:     /* Encrypted message including header, data and trailer entirely sent.
                   1691:        The return value is the number of unencrypted bytes that were sent. */
                   1692:     written = outbuf[1].cbBuffer;
                   1693: 
                   1694:   return written;
                   1695: }
                   1696: 
                   1697: static ssize_t
                   1698: schannel_recv(struct connectdata *conn, int sockindex,
                   1699:               char *buf, size_t len, CURLcode *err)
                   1700: {
                   1701:   size_t size = 0;
                   1702:   ssize_t nread = -1;
                   1703:   struct Curl_easy *data = conn->data;
                   1704:   struct ssl_connect_data *connssl = &conn->ssl[sockindex];
                   1705:   unsigned char *reallocated_buffer;
                   1706:   size_t reallocated_length;
                   1707:   bool done = FALSE;
                   1708:   SecBuffer inbuf[4];
                   1709:   SecBufferDesc inbuf_desc;
                   1710:   SECURITY_STATUS sspi_status = SEC_E_OK;
                   1711:   /* we want the length of the encrypted buffer to be at least large enough
                   1712:      that it can hold all the bytes requested and some TLS record overhead. */
                   1713:   size_t min_encdata_length = len + CURL_SCHANNEL_BUFFER_FREE_SIZE;
                   1714: 
                   1715:   /****************************************************************************
                   1716:    * Don't return or set BACKEND->recv_unrecoverable_err unless in the cleanup.
                   1717:    * The pattern for return error is set *err, optional infof, goto cleanup.
                   1718:    *
                   1719:    * Our priority is to always return as much decrypted data to the caller as
                   1720:    * possible, even if an error occurs. The state of the decrypted buffer must
                   1721:    * always be valid. Transfer of decrypted data to the caller's buffer is
                   1722:    * handled in the cleanup.
                   1723:    */
                   1724: 
                   1725:   DEBUGF(infof(data, "schannel: client wants to read %zu bytes\n", len));
                   1726:   *err = CURLE_OK;
                   1727: 
                   1728:   if(len && len <= BACKEND->decdata_offset) {
                   1729:     infof(data, "schannel: enough decrypted data is already available\n");
                   1730:     goto cleanup;
                   1731:   }
                   1732:   else if(BACKEND->recv_unrecoverable_err) {
                   1733:     *err = BACKEND->recv_unrecoverable_err;
                   1734:     infof(data, "schannel: an unrecoverable error occurred in a prior call\n");
                   1735:     goto cleanup;
                   1736:   }
                   1737:   else if(BACKEND->recv_sspi_close_notify) {
                   1738:     /* once a server has indicated shutdown there is no more encrypted data */
                   1739:     infof(data, "schannel: server indicated shutdown in a prior call\n");
                   1740:     goto cleanup;
                   1741:   }
                   1742:   else if(!len) {
                   1743:     /* It's debatable what to return when !len. Regardless we can't return
                   1744:     immediately because there may be data to decrypt (in the case we want to
                   1745:     decrypt all encrypted cached data) so handle !len later in cleanup.
                   1746:     */
                   1747:     ; /* do nothing */
                   1748:   }
                   1749:   else if(!BACKEND->recv_connection_closed) {
                   1750:     /* increase enc buffer in order to fit the requested amount of data */
                   1751:     size = BACKEND->encdata_length - BACKEND->encdata_offset;
                   1752:     if(size < CURL_SCHANNEL_BUFFER_FREE_SIZE ||
                   1753:        BACKEND->encdata_length < min_encdata_length) {
                   1754:       reallocated_length = BACKEND->encdata_offset +
                   1755:                            CURL_SCHANNEL_BUFFER_FREE_SIZE;
                   1756:       if(reallocated_length < min_encdata_length) {
                   1757:         reallocated_length = min_encdata_length;
                   1758:       }
                   1759:       reallocated_buffer = realloc(BACKEND->encdata_buffer,
                   1760:                                    reallocated_length);
                   1761:       if(reallocated_buffer == NULL) {
                   1762:         *err = CURLE_OUT_OF_MEMORY;
                   1763:         failf(data, "schannel: unable to re-allocate memory");
                   1764:         goto cleanup;
                   1765:       }
                   1766: 
                   1767:       BACKEND->encdata_buffer = reallocated_buffer;
                   1768:       BACKEND->encdata_length = reallocated_length;
                   1769:       size = BACKEND->encdata_length - BACKEND->encdata_offset;
                   1770:       DEBUGF(infof(data, "schannel: encdata_buffer resized %zu\n",
                   1771:                    BACKEND->encdata_length));
                   1772:     }
                   1773: 
                   1774:     DEBUGF(infof(data,
                   1775:                  "schannel: encrypted data buffer: offset %zu length %zu\n",
                   1776:                  BACKEND->encdata_offset, BACKEND->encdata_length));
                   1777: 
                   1778:     /* read encrypted data from socket */
                   1779:     *err = Curl_read_plain(conn->sock[sockindex],
                   1780:                            (char *)(BACKEND->encdata_buffer +
                   1781:                                     BACKEND->encdata_offset),
                   1782:                            size, &nread);
                   1783:     if(*err) {
                   1784:       nread = -1;
                   1785:       if(*err == CURLE_AGAIN)
                   1786:         DEBUGF(infof(data,
                   1787:                      "schannel: Curl_read_plain returned CURLE_AGAIN\n"));
                   1788:       else if(*err == CURLE_RECV_ERROR)
                   1789:         infof(data, "schannel: Curl_read_plain returned CURLE_RECV_ERROR\n");
                   1790:       else
                   1791:         infof(data, "schannel: Curl_read_plain returned error %d\n", *err);
                   1792:     }
                   1793:     else if(nread == 0) {
                   1794:       BACKEND->recv_connection_closed = true;
                   1795:       DEBUGF(infof(data, "schannel: server closed the connection\n"));
                   1796:     }
                   1797:     else if(nread > 0) {
                   1798:       BACKEND->encdata_offset += (size_t)nread;
                   1799:       BACKEND->encdata_is_incomplete = false;
                   1800:       DEBUGF(infof(data, "schannel: encrypted data got %zd\n", nread));
                   1801:     }
                   1802:   }
                   1803: 
                   1804:   DEBUGF(infof(data,
                   1805:                "schannel: encrypted data buffer: offset %zu length %zu\n",
                   1806:                BACKEND->encdata_offset, BACKEND->encdata_length));
                   1807: 
                   1808:   /* decrypt loop */
                   1809:   while(BACKEND->encdata_offset > 0 && sspi_status == SEC_E_OK &&
                   1810:         (!len || BACKEND->decdata_offset < len ||
                   1811:          BACKEND->recv_connection_closed)) {
                   1812:     /* prepare data buffer for DecryptMessage call */
                   1813:     InitSecBuffer(&inbuf[0], SECBUFFER_DATA, BACKEND->encdata_buffer,
                   1814:                   curlx_uztoul(BACKEND->encdata_offset));
                   1815: 
                   1816:     /* we need 3 more empty input buffers for possible output */
                   1817:     InitSecBuffer(&inbuf[1], SECBUFFER_EMPTY, NULL, 0);
                   1818:     InitSecBuffer(&inbuf[2], SECBUFFER_EMPTY, NULL, 0);
                   1819:     InitSecBuffer(&inbuf[3], SECBUFFER_EMPTY, NULL, 0);
                   1820:     InitSecBufferDesc(&inbuf_desc, inbuf, 4);
                   1821: 
                   1822:     /* https://msdn.microsoft.com/en-us/library/windows/desktop/aa375348.aspx
                   1823:        */
                   1824:     sspi_status = s_pSecFn->DecryptMessage(&BACKEND->ctxt->ctxt_handle,
                   1825:                                            &inbuf_desc, 0, NULL);
                   1826: 
                   1827:     /* check if everything went fine (server may want to renegotiate
                   1828:        or shutdown the connection context) */
                   1829:     if(sspi_status == SEC_E_OK || sspi_status == SEC_I_RENEGOTIATE ||
                   1830:        sspi_status == SEC_I_CONTEXT_EXPIRED) {
                   1831:       /* check for successfully decrypted data, even before actual
                   1832:          renegotiation or shutdown of the connection context */
                   1833:       if(inbuf[1].BufferType == SECBUFFER_DATA) {
                   1834:         DEBUGF(infof(data, "schannel: decrypted data length: %lu\n",
                   1835:                      inbuf[1].cbBuffer));
                   1836: 
                   1837:         /* increase buffer in order to fit the received amount of data */
                   1838:         size = inbuf[1].cbBuffer > CURL_SCHANNEL_BUFFER_FREE_SIZE ?
                   1839:                inbuf[1].cbBuffer : CURL_SCHANNEL_BUFFER_FREE_SIZE;
                   1840:         if(BACKEND->decdata_length - BACKEND->decdata_offset < size ||
                   1841:            BACKEND->decdata_length < len) {
                   1842:           /* increase internal decrypted data buffer */
                   1843:           reallocated_length = BACKEND->decdata_offset + size;
                   1844:           /* make sure that the requested amount of data fits */
                   1845:           if(reallocated_length < len) {
                   1846:             reallocated_length = len;
                   1847:           }
                   1848:           reallocated_buffer = realloc(BACKEND->decdata_buffer,
                   1849:                                        reallocated_length);
                   1850:           if(reallocated_buffer == NULL) {
                   1851:             *err = CURLE_OUT_OF_MEMORY;
                   1852:             failf(data, "schannel: unable to re-allocate memory");
                   1853:             goto cleanup;
                   1854:           }
                   1855:           BACKEND->decdata_buffer = reallocated_buffer;
                   1856:           BACKEND->decdata_length = reallocated_length;
                   1857:         }
                   1858: 
                   1859:         /* copy decrypted data to internal buffer */
                   1860:         size = inbuf[1].cbBuffer;
                   1861:         if(size) {
                   1862:           memcpy(BACKEND->decdata_buffer + BACKEND->decdata_offset,
                   1863:                  inbuf[1].pvBuffer, size);
                   1864:           BACKEND->decdata_offset += size;
                   1865:         }
                   1866: 
                   1867:         DEBUGF(infof(data, "schannel: decrypted data added: %zu\n", size));
                   1868:         DEBUGF(infof(data,
                   1869:                      "schannel: decrypted cached: offset %zu length %zu\n",
                   1870:                      BACKEND->decdata_offset, BACKEND->decdata_length));
                   1871:       }
                   1872: 
                   1873:       /* check for remaining encrypted data */
                   1874:       if(inbuf[3].BufferType == SECBUFFER_EXTRA && inbuf[3].cbBuffer > 0) {
                   1875:         DEBUGF(infof(data, "schannel: encrypted data length: %lu\n",
                   1876:                      inbuf[3].cbBuffer));
                   1877: 
                   1878:         /* check if the remaining data is less than the total amount
                   1879:          * and therefore begins after the already processed data
                   1880:          */
                   1881:         if(BACKEND->encdata_offset > inbuf[3].cbBuffer) {
                   1882:           /* move remaining encrypted data forward to the beginning of
                   1883:              buffer */
                   1884:           memmove(BACKEND->encdata_buffer,
                   1885:                   (BACKEND->encdata_buffer + BACKEND->encdata_offset) -
                   1886:                   inbuf[3].cbBuffer, inbuf[3].cbBuffer);
                   1887:           BACKEND->encdata_offset = inbuf[3].cbBuffer;
                   1888:         }
                   1889: 
                   1890:         DEBUGF(infof(data,
                   1891:                      "schannel: encrypted cached: offset %zu length %zu\n",
                   1892:                      BACKEND->encdata_offset, BACKEND->encdata_length));
                   1893:       }
                   1894:       else {
                   1895:         /* reset encrypted buffer offset, because there is no data remaining */
                   1896:         BACKEND->encdata_offset = 0;
                   1897:       }
                   1898: 
                   1899:       /* check if server wants to renegotiate the connection context */
                   1900:       if(sspi_status == SEC_I_RENEGOTIATE) {
                   1901:         infof(data, "schannel: remote party requests renegotiation\n");
                   1902:         if(*err && *err != CURLE_AGAIN) {
                   1903:           infof(data, "schannel: can't renogotiate, an error is pending\n");
                   1904:           goto cleanup;
                   1905:         }
                   1906:         if(BACKEND->encdata_offset) {
                   1907:           *err = CURLE_RECV_ERROR;
                   1908:           infof(data, "schannel: can't renogotiate, "
                   1909:                       "encrypted data available\n");
                   1910:           goto cleanup;
                   1911:         }
                   1912:         /* begin renegotiation */
                   1913:         infof(data, "schannel: renegotiating SSL/TLS connection\n");
                   1914:         connssl->state = ssl_connection_negotiating;
                   1915:         connssl->connecting_state = ssl_connect_2_writing;
                   1916:         *err = schannel_connect_common(conn, sockindex, FALSE, &done);
                   1917:         if(*err) {
                   1918:           infof(data, "schannel: renegotiation failed\n");
                   1919:           goto cleanup;
                   1920:         }
                   1921:         /* now retry receiving data */
                   1922:         sspi_status = SEC_E_OK;
                   1923:         infof(data, "schannel: SSL/TLS connection renegotiated\n");
                   1924:         continue;
                   1925:       }
                   1926:       /* check if the server closed the connection */
                   1927:       else if(sspi_status == SEC_I_CONTEXT_EXPIRED) {
                   1928:         /* In Windows 2000 SEC_I_CONTEXT_EXPIRED (close_notify) is not
                   1929:            returned so we have to work around that in cleanup. */
                   1930:         BACKEND->recv_sspi_close_notify = true;
                   1931:         if(!BACKEND->recv_connection_closed) {
                   1932:           BACKEND->recv_connection_closed = true;
                   1933:           infof(data, "schannel: server closed the connection\n");
                   1934:         }
                   1935:         goto cleanup;
                   1936:       }
                   1937:     }
                   1938:     else if(sspi_status == SEC_E_INCOMPLETE_MESSAGE) {
                   1939:       BACKEND->encdata_is_incomplete = true;
                   1940:       if(!*err)
                   1941:         *err = CURLE_AGAIN;
                   1942:       infof(data, "schannel: failed to decrypt data, need more data\n");
                   1943:       goto cleanup;
                   1944:     }
                   1945:     else {
                   1946: #ifndef CURL_DISABLE_VERBOSE_STRINGS
                   1947:       char buffer[STRERROR_LEN];
                   1948: #endif
                   1949:       *err = CURLE_RECV_ERROR;
                   1950:       infof(data, "schannel: failed to read data from server: %s\n",
                   1951:             Curl_sspi_strerror(sspi_status, buffer, sizeof(buffer)));
                   1952:       goto cleanup;
                   1953:     }
                   1954:   }
                   1955: 
                   1956:   DEBUGF(infof(data,
                   1957:                "schannel: encrypted data buffer: offset %zu length %zu\n",
                   1958:                BACKEND->encdata_offset, BACKEND->encdata_length));
                   1959: 
                   1960:   DEBUGF(infof(data,
                   1961:                "schannel: decrypted data buffer: offset %zu length %zu\n",
                   1962:                BACKEND->decdata_offset, BACKEND->decdata_length));
                   1963: 
                   1964: cleanup:
                   1965:   /* Warning- there is no guarantee the encdata state is valid at this point */
                   1966:   DEBUGF(infof(data, "schannel: schannel_recv cleanup\n"));
                   1967: 
                   1968:   /* Error if the connection has closed without a close_notify.
                   1969:   Behavior here is a matter of debate. We don't want to be vulnerable to a
                   1970:   truncation attack however there's some browser precedent for ignoring the
                   1971:   close_notify for compatibility reasons.
                   1972:   Additionally, Windows 2000 (v5.0) is a special case since it seems it doesn't
                   1973:   return close_notify. In that case if the connection was closed we assume it
                   1974:   was graceful (close_notify) since there doesn't seem to be a way to tell.
                   1975:   */
                   1976:   if(len && !BACKEND->decdata_offset && BACKEND->recv_connection_closed &&
                   1977:      !BACKEND->recv_sspi_close_notify) {
                   1978:     bool isWin2k = Curl_verify_windows_version(5, 0, PLATFORM_WINNT,
                   1979:                                                VERSION_EQUAL);
                   1980: 
                   1981:     if(isWin2k && sspi_status == SEC_E_OK)
                   1982:       BACKEND->recv_sspi_close_notify = true;
                   1983:     else {
                   1984:       *err = CURLE_RECV_ERROR;
                   1985:       infof(data, "schannel: server closed abruptly (missing close_notify)\n");
                   1986:     }
                   1987:   }
                   1988: 
                   1989:   /* Any error other than CURLE_AGAIN is an unrecoverable error. */
                   1990:   if(*err && *err != CURLE_AGAIN)
                   1991:       BACKEND->recv_unrecoverable_err = *err;
                   1992: 
                   1993:   size = len < BACKEND->decdata_offset ? len : BACKEND->decdata_offset;
                   1994:   if(size) {
                   1995:     memcpy(buf, BACKEND->decdata_buffer, size);
                   1996:     memmove(BACKEND->decdata_buffer, BACKEND->decdata_buffer + size,
                   1997:             BACKEND->decdata_offset - size);
                   1998:     BACKEND->decdata_offset -= size;
                   1999:     DEBUGF(infof(data, "schannel: decrypted data returned %zu\n", size));
                   2000:     DEBUGF(infof(data,
                   2001:                  "schannel: decrypted data buffer: offset %zu length %zu\n",
                   2002:                  BACKEND->decdata_offset, BACKEND->decdata_length));
                   2003:     *err = CURLE_OK;
                   2004:     return (ssize_t)size;
                   2005:   }
                   2006: 
                   2007:   if(!*err && !BACKEND->recv_connection_closed)
                   2008:       *err = CURLE_AGAIN;
                   2009: 
                   2010:   /* It's debatable what to return when !len. We could return whatever error we
                   2011:   got from decryption but instead we override here so the return is consistent.
                   2012:   */
                   2013:   if(!len)
                   2014:     *err = CURLE_OK;
                   2015: 
                   2016:   return *err ? -1 : 0;
                   2017: }
                   2018: 
                   2019: static CURLcode Curl_schannel_connect_nonblocking(struct connectdata *conn,
                   2020:                                                   int sockindex, bool *done)
                   2021: {
                   2022:   return schannel_connect_common(conn, sockindex, TRUE, done);
                   2023: }
                   2024: 
                   2025: static CURLcode Curl_schannel_connect(struct connectdata *conn, int sockindex)
                   2026: {
                   2027:   CURLcode result;
                   2028:   bool done = FALSE;
                   2029: 
                   2030:   result = schannel_connect_common(conn, sockindex, FALSE, &done);
                   2031:   if(result)
                   2032:     return result;
                   2033: 
                   2034:   DEBUGASSERT(done);
                   2035: 
                   2036:   return CURLE_OK;
                   2037: }
                   2038: 
                   2039: static bool Curl_schannel_data_pending(const struct connectdata *conn,
                   2040:                                        int sockindex)
                   2041: {
                   2042:   const struct ssl_connect_data *connssl = &conn->ssl[sockindex];
                   2043: 
                   2044:   if(connssl->use) /* SSL/TLS is in use */
                   2045:     return (BACKEND->decdata_offset > 0 ||
                   2046:             (BACKEND->encdata_offset > 0 && !BACKEND->encdata_is_incomplete));
                   2047:   else
                   2048:     return FALSE;
                   2049: }
                   2050: 
                   2051: static void Curl_schannel_close(struct connectdata *conn, int sockindex)
                   2052: {
                   2053:   if(conn->ssl[sockindex].use)
                   2054:     /* if the SSL/TLS channel hasn't been shut down yet, do that now. */
                   2055:     Curl_ssl_shutdown(conn, sockindex);
                   2056: }
                   2057: 
                   2058: static void Curl_schannel_session_free(void *ptr)
                   2059: {
                   2060:   /* this is expected to be called under sessionid lock */
                   2061:   struct curl_schannel_cred *cred = ptr;
                   2062: 
                   2063:   cred->refcount--;
                   2064:   if(cred->refcount == 0) {
                   2065:     s_pSecFn->FreeCredentialsHandle(&cred->cred_handle);
                   2066:     Curl_safefree(cred);
                   2067:   }
                   2068: }
                   2069: 
                   2070: static int Curl_schannel_shutdown(struct connectdata *conn, int sockindex)
                   2071: {
                   2072:   /* See https://msdn.microsoft.com/en-us/library/windows/desktop/aa380138.aspx
                   2073:    * Shutting Down an Schannel Connection
                   2074:    */
                   2075:   struct Curl_easy *data = conn->data;
                   2076:   struct ssl_connect_data *connssl = &conn->ssl[sockindex];
                   2077:   char * const hostname = SSL_IS_PROXY() ? conn->http_proxy.host.name :
                   2078:     conn->host.name;
                   2079: 
                   2080:   DEBUGASSERT(data);
                   2081: 
                   2082:   infof(data, "schannel: shutting down SSL/TLS connection with %s port %hu\n",
                   2083:         hostname, conn->remote_port);
                   2084: 
                   2085:   if(BACKEND->cred && BACKEND->ctxt) {
                   2086:     SecBufferDesc BuffDesc;
                   2087:     SecBuffer Buffer;
                   2088:     SECURITY_STATUS sspi_status;
                   2089:     SecBuffer outbuf;
                   2090:     SecBufferDesc outbuf_desc;
                   2091:     CURLcode result;
                   2092:     TCHAR *host_name;
                   2093:     DWORD dwshut = SCHANNEL_SHUTDOWN;
                   2094: 
                   2095:     InitSecBuffer(&Buffer, SECBUFFER_TOKEN, &dwshut, sizeof(dwshut));
                   2096:     InitSecBufferDesc(&BuffDesc, &Buffer, 1);
                   2097: 
                   2098:     sspi_status = s_pSecFn->ApplyControlToken(&BACKEND->ctxt->ctxt_handle,
                   2099:                                               &BuffDesc);
                   2100: 
                   2101:     if(sspi_status != SEC_E_OK) {
                   2102:       char buffer[STRERROR_LEN];
                   2103:       failf(data, "schannel: ApplyControlToken failure: %s",
                   2104:             Curl_sspi_strerror(sspi_status, buffer, sizeof(buffer)));
                   2105:     }
                   2106: 
                   2107:     host_name = Curl_convert_UTF8_to_tchar(hostname);
                   2108:     if(!host_name)
                   2109:       return CURLE_OUT_OF_MEMORY;
                   2110: 
                   2111:     /* setup output buffer */
                   2112:     InitSecBuffer(&outbuf, SECBUFFER_EMPTY, NULL, 0);
                   2113:     InitSecBufferDesc(&outbuf_desc, &outbuf, 1);
                   2114: 
                   2115:     sspi_status = s_pSecFn->InitializeSecurityContext(
                   2116:       &BACKEND->cred->cred_handle,
                   2117:       &BACKEND->ctxt->ctxt_handle,
                   2118:       host_name,
                   2119:       BACKEND->req_flags,
                   2120:       0,
                   2121:       0,
                   2122:       NULL,
                   2123:       0,
                   2124:       &BACKEND->ctxt->ctxt_handle,
                   2125:       &outbuf_desc,
                   2126:       &BACKEND->ret_flags,
                   2127:       &BACKEND->ctxt->time_stamp);
                   2128: 
                   2129:     Curl_unicodefree(host_name);
                   2130: 
                   2131:     if((sspi_status == SEC_E_OK) || (sspi_status == SEC_I_CONTEXT_EXPIRED)) {
                   2132:       /* send close message which is in output buffer */
                   2133:       ssize_t written;
                   2134:       result = Curl_write_plain(conn, conn->sock[sockindex], outbuf.pvBuffer,
                   2135:                                 outbuf.cbBuffer, &written);
                   2136: 
                   2137:       s_pSecFn->FreeContextBuffer(outbuf.pvBuffer);
                   2138:       if((result != CURLE_OK) || (outbuf.cbBuffer != (size_t) written)) {
                   2139:         infof(data, "schannel: failed to send close msg: %s"
                   2140:               " (bytes written: %zd)\n", curl_easy_strerror(result), written);
                   2141:       }
                   2142:     }
                   2143:   }
                   2144: 
                   2145:   /* free SSPI Schannel API security context handle */
                   2146:   if(BACKEND->ctxt) {
                   2147:     DEBUGF(infof(data, "schannel: clear security context handle\n"));
                   2148:     s_pSecFn->DeleteSecurityContext(&BACKEND->ctxt->ctxt_handle);
                   2149:     Curl_safefree(BACKEND->ctxt);
                   2150:   }
                   2151: 
                   2152:   /* free SSPI Schannel API credential handle */
                   2153:   if(BACKEND->cred) {
                   2154:     /*
                   2155:      * When this function is called from Curl_schannel_close() the connection
                   2156:      * might not have an associated transfer so the check for conn->data is
                   2157:      * necessary.
                   2158:      */
                   2159:     Curl_ssl_sessionid_lock(conn);
                   2160:     Curl_schannel_session_free(BACKEND->cred);
                   2161:     Curl_ssl_sessionid_unlock(conn);
                   2162:     BACKEND->cred = NULL;
                   2163:   }
                   2164: 
                   2165:   /* free internal buffer for received encrypted data */
                   2166:   if(BACKEND->encdata_buffer != NULL) {
                   2167:     Curl_safefree(BACKEND->encdata_buffer);
                   2168:     BACKEND->encdata_length = 0;
                   2169:     BACKEND->encdata_offset = 0;
                   2170:     BACKEND->encdata_is_incomplete = false;
                   2171:   }
                   2172: 
                   2173:   /* free internal buffer for received decrypted data */
                   2174:   if(BACKEND->decdata_buffer != NULL) {
                   2175:     Curl_safefree(BACKEND->decdata_buffer);
                   2176:     BACKEND->decdata_length = 0;
                   2177:     BACKEND->decdata_offset = 0;
                   2178:   }
                   2179: 
                   2180:   return CURLE_OK;
                   2181: }
                   2182: 
                   2183: static int Curl_schannel_init(void)
                   2184: {
                   2185:   return (Curl_sspi_global_init() == CURLE_OK ? 1 : 0);
                   2186: }
                   2187: 
                   2188: static void Curl_schannel_cleanup(void)
                   2189: {
                   2190:   Curl_sspi_global_cleanup();
                   2191: }
                   2192: 
                   2193: static size_t Curl_schannel_version(char *buffer, size_t size)
                   2194: {
                   2195:   size = msnprintf(buffer, size, "Schannel");
                   2196: 
                   2197:   return size;
                   2198: }
                   2199: 
                   2200: static CURLcode Curl_schannel_random(struct Curl_easy *data UNUSED_PARAM,
                   2201:                                      unsigned char *entropy, size_t length)
                   2202: {
                   2203:   HCRYPTPROV hCryptProv = 0;
                   2204: 
                   2205:   (void)data;
                   2206: 
                   2207:   if(!CryptAcquireContext(&hCryptProv, NULL, NULL, PROV_RSA_FULL,
                   2208:                           CRYPT_VERIFYCONTEXT | CRYPT_SILENT))
                   2209:     return CURLE_FAILED_INIT;
                   2210: 
                   2211:   if(!CryptGenRandom(hCryptProv, (DWORD)length, entropy)) {
                   2212:     CryptReleaseContext(hCryptProv, 0UL);
                   2213:     return CURLE_FAILED_INIT;
                   2214:   }
                   2215: 
                   2216:   CryptReleaseContext(hCryptProv, 0UL);
                   2217:   return CURLE_OK;
                   2218: }
                   2219: 
                   2220: static CURLcode pkp_pin_peer_pubkey(struct connectdata *conn, int sockindex,
                   2221:                                     const char *pinnedpubkey)
                   2222: {
                   2223:   struct Curl_easy *data = conn->data;
                   2224:   struct ssl_connect_data *connssl = &conn->ssl[sockindex];
                   2225:   CERT_CONTEXT *pCertContextServer = NULL;
                   2226: 
                   2227:   /* Result is returned to caller */
                   2228:   CURLcode result = CURLE_SSL_PINNEDPUBKEYNOTMATCH;
                   2229: 
                   2230:   /* if a path wasn't specified, don't pin */
                   2231:   if(!pinnedpubkey)
                   2232:     return CURLE_OK;
                   2233: 
                   2234:   do {
                   2235:     SECURITY_STATUS sspi_status;
                   2236:     const char *x509_der;
                   2237:     DWORD x509_der_len;
                   2238:     curl_X509certificate x509_parsed;
                   2239:     curl_asn1Element *pubkey;
                   2240: 
                   2241:     sspi_status =
                   2242:       s_pSecFn->QueryContextAttributes(&BACKEND->ctxt->ctxt_handle,
                   2243:                                        SECPKG_ATTR_REMOTE_CERT_CONTEXT,
                   2244:                                        &pCertContextServer);
                   2245: 
                   2246:     if((sspi_status != SEC_E_OK) || (pCertContextServer == NULL)) {
                   2247:       char buffer[STRERROR_LEN];
                   2248:       failf(data, "schannel: Failed to read remote certificate context: %s",
                   2249:             Curl_sspi_strerror(sspi_status, buffer, sizeof(buffer)));
                   2250:       break; /* failed */
                   2251:     }
                   2252: 
                   2253: 
                   2254:     if(!(((pCertContextServer->dwCertEncodingType & X509_ASN_ENCODING) != 0) &&
                   2255:        (pCertContextServer->cbCertEncoded > 0)))
                   2256:       break;
                   2257: 
                   2258:     x509_der = (const char *)pCertContextServer->pbCertEncoded;
                   2259:     x509_der_len = pCertContextServer->cbCertEncoded;
                   2260:     memset(&x509_parsed, 0, sizeof(x509_parsed));
                   2261:     if(Curl_parseX509(&x509_parsed, x509_der, x509_der + x509_der_len))
                   2262:       break;
                   2263: 
                   2264:     pubkey = &x509_parsed.subjectPublicKeyInfo;
                   2265:     if(!pubkey->header || pubkey->end <= pubkey->header) {
                   2266:       failf(data, "SSL: failed retrieving public key from server certificate");
                   2267:       break;
                   2268:     }
                   2269: 
                   2270:     result = Curl_pin_peer_pubkey(data,
                   2271:                                   pinnedpubkey,
                   2272:                                   (const unsigned char *)pubkey->header,
                   2273:                                   (size_t)(pubkey->end - pubkey->header));
                   2274:     if(result) {
                   2275:       failf(data, "SSL: public key does not match pinned public key!");
                   2276:     }
                   2277:   } while(0);
                   2278: 
                   2279:   if(pCertContextServer)
                   2280:     CertFreeCertificateContext(pCertContextServer);
                   2281: 
                   2282:   return result;
                   2283: }
                   2284: 
                   2285: static void Curl_schannel_checksum(const unsigned char *input,
                   2286:                                    size_t inputlen,
                   2287:                                    unsigned char *checksum,
                   2288:                                    size_t checksumlen,
                   2289:                                    DWORD provType,
                   2290:                                    const unsigned int algId)
                   2291: {
                   2292:   HCRYPTPROV hProv = 0;
                   2293:   HCRYPTHASH hHash = 0;
                   2294:   DWORD cbHashSize = 0;
                   2295:   DWORD dwHashSizeLen = (DWORD)sizeof(cbHashSize);
                   2296:   DWORD dwChecksumLen = (DWORD)checksumlen;
                   2297: 
                   2298:   /* since this can fail in multiple ways, zero memory first so we never
                   2299:    * return old data
                   2300:    */
                   2301:   memset(checksum, 0, checksumlen);
                   2302: 
                   2303:   if(!CryptAcquireContext(&hProv, NULL, NULL, provType,
                   2304:                           CRYPT_VERIFYCONTEXT | CRYPT_SILENT))
                   2305:     return; /* failed */
                   2306: 
                   2307:   do {
                   2308:     if(!CryptCreateHash(hProv, algId, 0, 0, &hHash))
                   2309:       break; /* failed */
                   2310: 
                   2311:     /* workaround for original MinGW, should be (const BYTE*) */
                   2312:     if(!CryptHashData(hHash, (BYTE*)input, (DWORD)inputlen, 0))
                   2313:       break; /* failed */
                   2314: 
                   2315:     /* get hash size */
                   2316:     if(!CryptGetHashParam(hHash, HP_HASHSIZE, (BYTE *)&cbHashSize,
                   2317:                           &dwHashSizeLen, 0))
                   2318:       break; /* failed */
                   2319: 
                   2320:     /* check hash size */
                   2321:     if(checksumlen < cbHashSize)
                   2322:       break; /* failed */
                   2323: 
                   2324:     if(CryptGetHashParam(hHash, HP_HASHVAL, checksum, &dwChecksumLen, 0))
                   2325:       break; /* failed */
                   2326:   } while(0);
                   2327: 
                   2328:   if(hHash)
                   2329:     CryptDestroyHash(hHash);
                   2330: 
                   2331:   if(hProv)
                   2332:     CryptReleaseContext(hProv, 0);
                   2333: }
                   2334: 
                   2335: static CURLcode Curl_schannel_md5sum(unsigned char *input,
                   2336:                                      size_t inputlen,
                   2337:                                      unsigned char *md5sum,
                   2338:                                      size_t md5len)
                   2339: {
                   2340:   Curl_schannel_checksum(input, inputlen, md5sum, md5len,
                   2341:                          PROV_RSA_FULL, CALG_MD5);
                   2342:   return CURLE_OK;
                   2343: }
                   2344: 
                   2345: static CURLcode Curl_schannel_sha256sum(const unsigned char *input,
                   2346:                                     size_t inputlen,
                   2347:                                     unsigned char *sha256sum,
                   2348:                                     size_t sha256len)
                   2349: {
                   2350:   Curl_schannel_checksum(input, inputlen, sha256sum, sha256len,
                   2351:                          PROV_RSA_AES, CALG_SHA_256);
                   2352:   return CURLE_OK;
                   2353: }
                   2354: 
                   2355: static void *Curl_schannel_get_internals(struct ssl_connect_data *connssl,
                   2356:                                          CURLINFO info UNUSED_PARAM)
                   2357: {
                   2358:   (void)info;
                   2359:   return &BACKEND->ctxt->ctxt_handle;
                   2360: }
                   2361: 
                   2362: const struct Curl_ssl Curl_ssl_schannel = {
                   2363:   { CURLSSLBACKEND_SCHANNEL, "schannel" }, /* info */
                   2364: 
                   2365:   SSLSUPP_CERTINFO |
                   2366:   SSLSUPP_PINNEDPUBKEY,
                   2367: 
                   2368:   sizeof(struct ssl_backend_data),
                   2369: 
                   2370:   Curl_schannel_init,                /* init */
                   2371:   Curl_schannel_cleanup,             /* cleanup */
                   2372:   Curl_schannel_version,             /* version */
                   2373:   Curl_none_check_cxn,               /* check_cxn */
                   2374:   Curl_schannel_shutdown,            /* shutdown */
                   2375:   Curl_schannel_data_pending,        /* data_pending */
                   2376:   Curl_schannel_random,              /* random */
                   2377:   Curl_none_cert_status_request,     /* cert_status_request */
                   2378:   Curl_schannel_connect,             /* connect */
                   2379:   Curl_schannel_connect_nonblocking, /* connect_nonblocking */
                   2380:   Curl_schannel_get_internals,       /* get_internals */
                   2381:   Curl_schannel_close,               /* close_one */
                   2382:   Curl_none_close_all,               /* close_all */
                   2383:   Curl_schannel_session_free,        /* session_free */
                   2384:   Curl_none_set_engine,              /* set_engine */
                   2385:   Curl_none_set_engine_default,      /* set_engine_default */
                   2386:   Curl_none_engines_list,            /* engines_list */
                   2387:   Curl_none_false_start,             /* false_start */
                   2388:   Curl_schannel_md5sum,              /* md5sum */
                   2389:   Curl_schannel_sha256sum            /* sha256sum */
                   2390: };
                   2391: 
                   2392: #endif /* USE_SCHANNEL */

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>