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