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