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