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