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 - 2016, 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 /*
32 * Based upon the PolarSSL implementation in polarssl.c and polarssl.h:
33 * Copyright (C) 2010, 2011, Hoi-Ho Chan, <hoiho.chan@gmail.com>
34 *
35 * Based upon the CyaSSL implementation in cyassl.c and cyassl.h:
36 * Copyright (C) 1998 - 2012, Daniel Stenberg, <daniel@haxx.se>, et al.
37 *
38 * Thanks for code and inspiration!
39 */
40
41 #include "curl_setup.h"
42
43 #ifdef USE_SCHANNEL
44
45 #ifndef USE_WINDOWS_SSPI
46 # error "Can't compile SCHANNEL support without SSPI."
47 #endif
48
49 #include "curl_sspi.h"
50 #include "schannel.h"
51 #include "vtls.h"
52 #include "sendf.h"
53 #include "connect.h" /* for the connect timeout */
54 #include "strerror.h"
55 #include "select.h" /* for the socket readyness */
56 #include "inet_pton.h" /* for IP addr SNI check */
57 #include "curl_multibyte.h"
58 #include "warnless.h"
59 #include "x509asn1.h"
60 #include "curl_printf.h"
61 #include "system_win32.h"
62
63 /* The last #include file should be: */
64 #include "curl_memory.h"
65 #include "memdebug.h"
66
67 /* ALPN requires version 8.1 of the Windows SDK, which was
68 shipped with Visual Studio 2013, aka _MSC_VER 1800:
69
70 https://technet.microsoft.com/en-us/library/hh831771%28v=ws.11%29.aspx
71 */
72 #if defined(_MSC_VER) && (_MSC_VER >= 1800) && !defined(_USING_V110_SDK71_)
73 # define HAS_ALPN 1
74 #endif
75
76 /* Uncomment to force verbose output
77 * #define infof(x, y, ...) printf(y, __VA_ARGS__)
78 * #define failf(x, y, ...) printf(y, __VA_ARGS__)
79 */
80
81 static Curl_recv schannel_recv;
82 static Curl_send schannel_send;
83
84 #ifdef _WIN32_WCE
85 static CURLcode verify_certificate(struct connectdata *conn, int sockindex);
86 #endif
87
InitSecBuffer(SecBuffer * buffer,unsigned long BufType,void * BufDataPtr,unsigned long BufByteSize)88 static void InitSecBuffer(SecBuffer *buffer, unsigned long BufType,
89 void *BufDataPtr, unsigned long BufByteSize)
90 {
91 buffer->cbBuffer = BufByteSize;
92 buffer->BufferType = BufType;
93 buffer->pvBuffer = BufDataPtr;
94 }
95
InitSecBufferDesc(SecBufferDesc * desc,SecBuffer * BufArr,unsigned long NumArrElem)96 static void InitSecBufferDesc(SecBufferDesc *desc, SecBuffer *BufArr,
97 unsigned long NumArrElem)
98 {
99 desc->ulVersion = SECBUFFER_VERSION;
100 desc->pBuffers = BufArr;
101 desc->cBuffers = NumArrElem;
102 }
103
104 static CURLcode
schannel_connect_step1(struct connectdata * conn,int sockindex)105 schannel_connect_step1(struct connectdata *conn, int sockindex)
106 {
107 ssize_t written = -1;
108 struct Curl_easy *data = conn->data;
109 struct ssl_connect_data *connssl = &conn->ssl[sockindex];
110 SecBuffer outbuf;
111 SecBufferDesc outbuf_desc;
112 SecBuffer inbuf;
113 SecBufferDesc inbuf_desc;
114 #ifdef HAS_ALPN
115 unsigned char alpn_buffer[128];
116 #endif
117 SCHANNEL_CRED schannel_cred;
118 SECURITY_STATUS sspi_status = SEC_E_OK;
119 struct curl_schannel_cred *old_cred = NULL;
120 struct in_addr addr;
121 #ifdef ENABLE_IPV6
122 struct in6_addr addr6;
123 #endif
124 TCHAR *host_name;
125 CURLcode result;
126 const char * const hostname = SSL_IS_PROXY() ? conn->http_proxy.host.name :
127 conn->host.name;
128
129 infof(data, "schannel: SSL/TLS connection with %s port %hu (step 1/3)\n",
130 hostname, conn->remote_port);
131
132 #ifdef HAS_ALPN
133 /* ALPN is only supported on Windows 8.1 / Server 2012 R2 and above.
134 Also it doesn't seem to be supported for Wine, see curl bug #983. */
135 connssl->use_alpn = conn->bits.tls_enable_alpn &&
136 !GetProcAddress(GetModuleHandleA("ntdll"),
137 "wine_get_version") &&
138 Curl_verify_windows_version(6, 3, PLATFORM_WINNT,
139 VERSION_GREATER_THAN_EQUAL);
140 #else
141 connssl->use_alpn = false;
142 #endif
143
144 connssl->cred = NULL;
145
146 /* check for an existing re-usable credential handle */
147 if(data->set.general_ssl.sessionid) {
148 Curl_ssl_sessionid_lock(conn);
149 if(!Curl_ssl_getsessionid(conn, (void **)&old_cred, NULL, sockindex)) {
150 connssl->cred = old_cred;
151 infof(data, "schannel: re-using existing credential handle\n");
152
153 /* increment the reference counter of the credential/session handle */
154 connssl->cred->refcount++;
155 infof(data, "schannel: incremented credential handle refcount = %d\n",
156 connssl->cred->refcount);
157 }
158 Curl_ssl_sessionid_unlock(conn);
159 }
160
161 if(!connssl->cred) {
162 /* setup Schannel API options */
163 memset(&schannel_cred, 0, sizeof(schannel_cred));
164 schannel_cred.dwVersion = SCHANNEL_CRED_VERSION;
165
166 if(conn->ssl_config.verifypeer) {
167 #ifdef _WIN32_WCE
168 /* certificate validation on CE doesn't seem to work right; we'll
169 do it following a more manual process. */
170 schannel_cred.dwFlags = SCH_CRED_MANUAL_CRED_VALIDATION |
171 SCH_CRED_IGNORE_NO_REVOCATION_CHECK |
172 SCH_CRED_IGNORE_REVOCATION_OFFLINE;
173 #else
174 schannel_cred.dwFlags = SCH_CRED_AUTO_CRED_VALIDATION;
175 /* TODO s/data->set.ssl.no_revoke/SSL_SET_OPTION(no_revoke)/g */
176 if(data->set.ssl.no_revoke)
177 schannel_cred.dwFlags |= SCH_CRED_IGNORE_NO_REVOCATION_CHECK |
178 SCH_CRED_IGNORE_REVOCATION_OFFLINE;
179 else
180 schannel_cred.dwFlags |= SCH_CRED_REVOCATION_CHECK_CHAIN;
181 #endif
182 if(data->set.ssl.no_revoke)
183 infof(data, "schannel: disabled server certificate revocation "
184 "checks\n");
185 else
186 infof(data, "schannel: checking server certificate revocation\n");
187 }
188 else {
189 schannel_cred.dwFlags = SCH_CRED_MANUAL_CRED_VALIDATION |
190 SCH_CRED_IGNORE_NO_REVOCATION_CHECK |
191 SCH_CRED_IGNORE_REVOCATION_OFFLINE;
192 infof(data, "schannel: disabled server certificate revocation checks\n");
193 }
194
195 if(!conn->ssl_config.verifyhost) {
196 schannel_cred.dwFlags |= SCH_CRED_NO_SERVERNAME_CHECK;
197 infof(data, "schannel: verifyhost setting prevents Schannel from "
198 "comparing the supplied target name with the subject "
199 "names in server certificates. Also disables SNI.\n");
200 }
201
202 switch(conn->ssl_config.version) {
203 case CURL_SSLVERSION_DEFAULT:
204 case CURL_SSLVERSION_TLSv1:
205 schannel_cred.grbitEnabledProtocols = SP_PROT_TLS1_0_CLIENT |
206 SP_PROT_TLS1_1_CLIENT |
207 SP_PROT_TLS1_2_CLIENT;
208 break;
209 case CURL_SSLVERSION_TLSv1_0:
210 schannel_cred.grbitEnabledProtocols = SP_PROT_TLS1_0_CLIENT;
211 break;
212 case CURL_SSLVERSION_TLSv1_1:
213 schannel_cred.grbitEnabledProtocols = SP_PROT_TLS1_1_CLIENT;
214 break;
215 case CURL_SSLVERSION_TLSv1_2:
216 schannel_cred.grbitEnabledProtocols = SP_PROT_TLS1_2_CLIENT;
217 break;
218 case CURL_SSLVERSION_TLSv1_3:
219 failf(data, "Schannel: TLS 1.3 is not yet supported");
220 return CURLE_SSL_CONNECT_ERROR;
221 case CURL_SSLVERSION_SSLv3:
222 schannel_cred.grbitEnabledProtocols = SP_PROT_SSL3_CLIENT;
223 break;
224 case CURL_SSLVERSION_SSLv2:
225 schannel_cred.grbitEnabledProtocols = SP_PROT_SSL2_CLIENT;
226 break;
227 default:
228 failf(data, "Unrecognized parameter passed via CURLOPT_SSLVERSION");
229 return CURLE_SSL_CONNECT_ERROR;
230 }
231
232 /* allocate memory for the re-usable credential handle */
233 connssl->cred = (struct curl_schannel_cred *)
234 malloc(sizeof(struct curl_schannel_cred));
235 if(!connssl->cred) {
236 failf(data, "schannel: unable to allocate memory");
237 return CURLE_OUT_OF_MEMORY;
238 }
239 memset(connssl->cred, 0, sizeof(struct curl_schannel_cred));
240 connssl->cred->refcount = 1;
241
242 /* https://msdn.microsoft.com/en-us/library/windows/desktop/aa374716.aspx
243 */
244 sspi_status =
245 s_pSecFn->AcquireCredentialsHandle(NULL, (TCHAR *)UNISP_NAME,
246 SECPKG_CRED_OUTBOUND, NULL,
247 &schannel_cred, NULL, NULL,
248 &connssl->cred->cred_handle,
249 &connssl->cred->time_stamp);
250
251 if(sspi_status != SEC_E_OK) {
252 if(sspi_status == SEC_E_WRONG_PRINCIPAL)
253 failf(data, "schannel: SNI or certificate check failed: %s",
254 Curl_sspi_strerror(conn, sspi_status));
255 else
256 failf(data, "schannel: AcquireCredentialsHandle failed: %s",
257 Curl_sspi_strerror(conn, sspi_status));
258 Curl_safefree(connssl->cred);
259 return CURLE_SSL_CONNECT_ERROR;
260 }
261 }
262
263 /* Warn if SNI is disabled due to use of an IP address */
264 if(Curl_inet_pton(AF_INET, hostname, &addr)
265 #ifdef ENABLE_IPV6
266 || Curl_inet_pton(AF_INET6, hostname, &addr6)
267 #endif
268 ) {
269 infof(data, "schannel: using IP address, SNI is not supported by OS.\n");
270 }
271
272 #ifdef HAS_ALPN
273 if(connssl->use_alpn) {
274 int cur = 0;
275 int list_start_index = 0;
276 unsigned int *extension_len = NULL;
277 unsigned short* list_len = NULL;
278
279 /* The first four bytes will be an unsigned int indicating number
280 of bytes of data in the rest of the the buffer. */
281 extension_len = (unsigned int *)(&alpn_buffer[cur]);
282 cur += sizeof(unsigned int);
283
284 /* The next four bytes are an indicator that this buffer will contain
285 ALPN data, as opposed to NPN, for example. */
286 *(unsigned int *)&alpn_buffer[cur] =
287 SecApplicationProtocolNegotiationExt_ALPN;
288 cur += sizeof(unsigned int);
289
290 /* The next two bytes will be an unsigned short indicating the number
291 of bytes used to list the preferred protocols. */
292 list_len = (unsigned short*)(&alpn_buffer[cur]);
293 cur += sizeof(unsigned short);
294
295 list_start_index = cur;
296
297 #ifdef USE_NGHTTP2
298 if(data->set.httpversion >= CURL_HTTP_VERSION_2) {
299 memcpy(&alpn_buffer[cur], NGHTTP2_PROTO_ALPN, NGHTTP2_PROTO_ALPN_LEN);
300 cur += NGHTTP2_PROTO_ALPN_LEN;
301 infof(data, "schannel: ALPN, offering %s\n", NGHTTP2_PROTO_VERSION_ID);
302 }
303 #endif
304
305 alpn_buffer[cur++] = ALPN_HTTP_1_1_LENGTH;
306 memcpy(&alpn_buffer[cur], ALPN_HTTP_1_1, ALPN_HTTP_1_1_LENGTH);
307 cur += ALPN_HTTP_1_1_LENGTH;
308 infof(data, "schannel: ALPN, offering %s\n", ALPN_HTTP_1_1);
309
310 *list_len = curlx_uitous(cur - list_start_index);
311 *extension_len = *list_len + sizeof(unsigned int) + sizeof(unsigned short);
312
313 InitSecBuffer(&inbuf, SECBUFFER_APPLICATION_PROTOCOLS, alpn_buffer, cur);
314 InitSecBufferDesc(&inbuf_desc, &inbuf, 1);
315 }
316 else
317 {
318 InitSecBuffer(&inbuf, SECBUFFER_EMPTY, NULL, 0);
319 InitSecBufferDesc(&inbuf_desc, &inbuf, 1);
320 }
321 #else /* HAS_ALPN */
322 InitSecBuffer(&inbuf, SECBUFFER_EMPTY, NULL, 0);
323 InitSecBufferDesc(&inbuf_desc, &inbuf, 1);
324 #endif
325
326 /* setup output buffer */
327 InitSecBuffer(&outbuf, SECBUFFER_EMPTY, NULL, 0);
328 InitSecBufferDesc(&outbuf_desc, &outbuf, 1);
329
330 /* setup request flags */
331 connssl->req_flags = ISC_REQ_SEQUENCE_DETECT | ISC_REQ_REPLAY_DETECT |
332 ISC_REQ_CONFIDENTIALITY | ISC_REQ_ALLOCATE_MEMORY |
333 ISC_REQ_STREAM;
334
335 /* allocate memory for the security context handle */
336 connssl->ctxt = (struct curl_schannel_ctxt *)
337 malloc(sizeof(struct curl_schannel_ctxt));
338 if(!connssl->ctxt) {
339 failf(data, "schannel: unable to allocate memory");
340 return CURLE_OUT_OF_MEMORY;
341 }
342 memset(connssl->ctxt, 0, sizeof(struct curl_schannel_ctxt));
343
344 host_name = Curl_convert_UTF8_to_tchar(hostname);
345 if(!host_name)
346 return CURLE_OUT_OF_MEMORY;
347
348 /* Schannel InitializeSecurityContext:
349 https://msdn.microsoft.com/en-us/library/windows/desktop/aa375924.aspx
350
351 At the moment we don't pass inbuf unless we're using ALPN since we only
352 use it for that, and Wine (for which we currently disable ALPN) is giving
353 us problems with inbuf regardless. https://github.com/curl/curl/issues/983
354 */
355 sspi_status = s_pSecFn->InitializeSecurityContext(
356 &connssl->cred->cred_handle, NULL, host_name, connssl->req_flags, 0, 0,
357 (connssl->use_alpn ? &inbuf_desc : NULL),
358 0, &connssl->ctxt->ctxt_handle,
359 &outbuf_desc, &connssl->ret_flags, &connssl->ctxt->time_stamp);
360
361 Curl_unicodefree(host_name);
362
363 if(sspi_status != SEC_I_CONTINUE_NEEDED) {
364 if(sspi_status == SEC_E_WRONG_PRINCIPAL)
365 failf(data, "schannel: SNI or certificate check failed: %s",
366 Curl_sspi_strerror(conn, sspi_status));
367 else
368 failf(data, "schannel: initial InitializeSecurityContext failed: %s",
369 Curl_sspi_strerror(conn, sspi_status));
370 Curl_safefree(connssl->ctxt);
371 return CURLE_SSL_CONNECT_ERROR;
372 }
373
374 infof(data, "schannel: sending initial handshake data: "
375 "sending %lu bytes...\n", outbuf.cbBuffer);
376
377 /* send initial handshake data which is now stored in output buffer */
378 result = Curl_write_plain(conn, conn->sock[sockindex], outbuf.pvBuffer,
379 outbuf.cbBuffer, &written);
380 s_pSecFn->FreeContextBuffer(outbuf.pvBuffer);
381 if((result != CURLE_OK) || (outbuf.cbBuffer != (size_t) written)) {
382 failf(data, "schannel: failed to send initial handshake data: "
383 "sent %zd of %lu bytes", written, outbuf.cbBuffer);
384 return CURLE_SSL_CONNECT_ERROR;
385 }
386
387 infof(data, "schannel: sent initial handshake data: "
388 "sent %zd bytes\n", written);
389
390 connssl->recv_unrecoverable_err = CURLE_OK;
391 connssl->recv_sspi_close_notify = false;
392 connssl->recv_connection_closed = false;
393
394 /* continue to second handshake step */
395 connssl->connecting_state = ssl_connect_2;
396
397 return CURLE_OK;
398 }
399
400 static CURLcode
schannel_connect_step2(struct connectdata * conn,int sockindex)401 schannel_connect_step2(struct connectdata *conn, int sockindex)
402 {
403 int i;
404 ssize_t nread = -1, written = -1;
405 struct Curl_easy *data = conn->data;
406 struct ssl_connect_data *connssl = &conn->ssl[sockindex];
407 unsigned char *reallocated_buffer;
408 size_t reallocated_length;
409 SecBuffer outbuf[3];
410 SecBufferDesc outbuf_desc;
411 SecBuffer inbuf[2];
412 SecBufferDesc inbuf_desc;
413 SECURITY_STATUS sspi_status = SEC_E_OK;
414 TCHAR *host_name;
415 CURLcode result;
416 bool doread;
417 const char * const hostname = SSL_IS_PROXY() ? conn->http_proxy.host.name :
418 conn->host.name;
419
420 doread = (connssl->connecting_state != ssl_connect_2_writing) ? TRUE : FALSE;
421
422 infof(data, "schannel: SSL/TLS connection with %s port %hu (step 2/3)\n",
423 hostname, conn->remote_port);
424
425 if(!connssl->cred || !connssl->ctxt)
426 return CURLE_SSL_CONNECT_ERROR;
427
428 /* buffer to store previously received and decrypted data */
429 if(connssl->decdata_buffer == NULL) {
430 connssl->decdata_offset = 0;
431 connssl->decdata_length = CURL_SCHANNEL_BUFFER_INIT_SIZE;
432 connssl->decdata_buffer = malloc(connssl->decdata_length);
433 if(connssl->decdata_buffer == NULL) {
434 failf(data, "schannel: unable to allocate memory");
435 return CURLE_OUT_OF_MEMORY;
436 }
437 }
438
439 /* buffer to store previously received and encrypted data */
440 if(connssl->encdata_buffer == NULL) {
441 connssl->encdata_offset = 0;
442 connssl->encdata_length = CURL_SCHANNEL_BUFFER_INIT_SIZE;
443 connssl->encdata_buffer = malloc(connssl->encdata_length);
444 if(connssl->encdata_buffer == NULL) {
445 failf(data, "schannel: unable to allocate memory");
446 return CURLE_OUT_OF_MEMORY;
447 }
448 }
449
450 /* if we need a bigger buffer to read a full message, increase buffer now */
451 if(connssl->encdata_length - connssl->encdata_offset <
452 CURL_SCHANNEL_BUFFER_FREE_SIZE) {
453 /* increase internal encrypted data buffer */
454 reallocated_length = connssl->encdata_offset +
455 CURL_SCHANNEL_BUFFER_FREE_SIZE;
456 reallocated_buffer = realloc(connssl->encdata_buffer,
457 reallocated_length);
458
459 if(reallocated_buffer == NULL) {
460 failf(data, "schannel: unable to re-allocate memory");
461 return CURLE_OUT_OF_MEMORY;
462 }
463 else {
464 connssl->encdata_buffer = reallocated_buffer;
465 connssl->encdata_length = reallocated_length;
466 }
467 }
468
469 for(;;) {
470 if(doread) {
471 /* read encrypted handshake data from socket */
472 result = Curl_read_plain(conn->sock[sockindex],
473 (char *) (connssl->encdata_buffer +
474 connssl->encdata_offset),
475 connssl->encdata_length -
476 connssl->encdata_offset,
477 &nread);
478 if(result == CURLE_AGAIN) {
479 if(connssl->connecting_state != ssl_connect_2_writing)
480 connssl->connecting_state = ssl_connect_2_reading;
481 infof(data, "schannel: failed to receive handshake, "
482 "need more data\n");
483 return CURLE_OK;
484 }
485 else if((result != CURLE_OK) || (nread == 0)) {
486 failf(data, "schannel: failed to receive handshake, "
487 "SSL/TLS connection failed");
488 return CURLE_SSL_CONNECT_ERROR;
489 }
490
491 /* increase encrypted data buffer offset */
492 connssl->encdata_offset += nread;
493 }
494
495 infof(data, "schannel: encrypted data buffer: offset %zu length %zu\n",
496 connssl->encdata_offset, connssl->encdata_length);
497
498 /* setup input buffers */
499 InitSecBuffer(&inbuf[0], SECBUFFER_TOKEN, malloc(connssl->encdata_offset),
500 curlx_uztoul(connssl->encdata_offset));
501 InitSecBuffer(&inbuf[1], SECBUFFER_EMPTY, NULL, 0);
502 InitSecBufferDesc(&inbuf_desc, inbuf, 2);
503
504 /* setup output buffers */
505 InitSecBuffer(&outbuf[0], SECBUFFER_TOKEN, NULL, 0);
506 InitSecBuffer(&outbuf[1], SECBUFFER_ALERT, NULL, 0);
507 InitSecBuffer(&outbuf[2], SECBUFFER_EMPTY, NULL, 0);
508 InitSecBufferDesc(&outbuf_desc, outbuf, 3);
509
510 if(inbuf[0].pvBuffer == NULL) {
511 failf(data, "schannel: unable to allocate memory");
512 return CURLE_OUT_OF_MEMORY;
513 }
514
515 /* copy received handshake data into input buffer */
516 memcpy(inbuf[0].pvBuffer, connssl->encdata_buffer,
517 connssl->encdata_offset);
518
519 host_name = Curl_convert_UTF8_to_tchar(hostname);
520 if(!host_name)
521 return CURLE_OUT_OF_MEMORY;
522
523 /* https://msdn.microsoft.com/en-us/library/windows/desktop/aa375924.aspx
524 */
525 sspi_status = s_pSecFn->InitializeSecurityContext(
526 &connssl->cred->cred_handle, &connssl->ctxt->ctxt_handle,
527 host_name, connssl->req_flags, 0, 0, &inbuf_desc, 0, NULL,
528 &outbuf_desc, &connssl->ret_flags, &connssl->ctxt->time_stamp);
529
530 Curl_unicodefree(host_name);
531
532 /* free buffer for received handshake data */
533 Curl_safefree(inbuf[0].pvBuffer);
534
535 /* check if the handshake was incomplete */
536 if(sspi_status == SEC_E_INCOMPLETE_MESSAGE) {
537 connssl->connecting_state = ssl_connect_2_reading;
538 infof(data, "schannel: received incomplete message, need more data\n");
539 return CURLE_OK;
540 }
541
542 /* If the server has requested a client certificate, attempt to continue
543 the handshake without one. This will allow connections to servers which
544 request a client certificate but do not require it. */
545 if(sspi_status == SEC_I_INCOMPLETE_CREDENTIALS &&
546 !(connssl->req_flags & ISC_REQ_USE_SUPPLIED_CREDS)) {
547 connssl->req_flags |= ISC_REQ_USE_SUPPLIED_CREDS;
548 connssl->connecting_state = ssl_connect_2_writing;
549 infof(data, "schannel: a client certificate has been requested\n");
550 return CURLE_OK;
551 }
552
553 /* check if the handshake needs to be continued */
554 if(sspi_status == SEC_I_CONTINUE_NEEDED || sspi_status == SEC_E_OK) {
555 for(i = 0; i < 3; i++) {
556 /* search for handshake tokens that need to be send */
557 if(outbuf[i].BufferType == SECBUFFER_TOKEN && outbuf[i].cbBuffer > 0) {
558 infof(data, "schannel: sending next handshake data: "
559 "sending %lu bytes...\n", outbuf[i].cbBuffer);
560
561 /* send handshake token to server */
562 result = Curl_write_plain(conn, conn->sock[sockindex],
563 outbuf[i].pvBuffer, outbuf[i].cbBuffer,
564 &written);
565 if((result != CURLE_OK) ||
566 (outbuf[i].cbBuffer != (size_t) written)) {
567 failf(data, "schannel: failed to send next handshake data: "
568 "sent %zd of %lu bytes", written, outbuf[i].cbBuffer);
569 return CURLE_SSL_CONNECT_ERROR;
570 }
571 }
572
573 /* free obsolete buffer */
574 if(outbuf[i].pvBuffer != NULL) {
575 s_pSecFn->FreeContextBuffer(outbuf[i].pvBuffer);
576 }
577 }
578 }
579 else {
580 if(sspi_status == SEC_E_WRONG_PRINCIPAL)
581 failf(data, "schannel: SNI or certificate check failed: %s",
582 Curl_sspi_strerror(conn, sspi_status));
583 else
584 failf(data, "schannel: next InitializeSecurityContext failed: %s",
585 Curl_sspi_strerror(conn, sspi_status));
586 return CURLE_SSL_CONNECT_ERROR;
587 }
588
589 /* check if there was additional remaining encrypted data */
590 if(inbuf[1].BufferType == SECBUFFER_EXTRA && inbuf[1].cbBuffer > 0) {
591 infof(data, "schannel: encrypted data length: %lu\n", inbuf[1].cbBuffer);
592 /*
593 There are two cases where we could be getting extra data here:
594 1) If we're renegotiating a connection and the handshake is already
595 complete (from the server perspective), it can encrypted app data
596 (not handshake data) in an extra buffer at this point.
597 2) (sspi_status == SEC_I_CONTINUE_NEEDED) We are negotiating a
598 connection and this extra data is part of the handshake.
599 We should process the data immediately; waiting for the socket to
600 be ready may fail since the server is done sending handshake data.
601 */
602 /* check if the remaining data is less than the total amount
603 and therefore begins after the already processed data */
604 if(connssl->encdata_offset > inbuf[1].cbBuffer) {
605 memmove(connssl->encdata_buffer,
606 (connssl->encdata_buffer + connssl->encdata_offset) -
607 inbuf[1].cbBuffer, inbuf[1].cbBuffer);
608 connssl->encdata_offset = inbuf[1].cbBuffer;
609 if(sspi_status == SEC_I_CONTINUE_NEEDED) {
610 doread = FALSE;
611 continue;
612 }
613 }
614 }
615 else {
616 connssl->encdata_offset = 0;
617 }
618 break;
619 }
620
621 /* check if the handshake needs to be continued */
622 if(sspi_status == SEC_I_CONTINUE_NEEDED) {
623 connssl->connecting_state = ssl_connect_2_reading;
624 return CURLE_OK;
625 }
626
627 /* check if the handshake is complete */
628 if(sspi_status == SEC_E_OK) {
629 connssl->connecting_state = ssl_connect_3;
630 infof(data, "schannel: SSL/TLS handshake complete\n");
631 }
632
633 #ifdef _WIN32_WCE
634 /* Windows CE doesn't do any server certificate validation.
635 We have to do it manually. */
636 if(conn->ssl_config.verifypeer)
637 return verify_certificate(conn, sockindex);
638 #endif
639
640 return CURLE_OK;
641 }
642
643 static CURLcode
schannel_connect_step3(struct connectdata * conn,int sockindex)644 schannel_connect_step3(struct connectdata *conn, int sockindex)
645 {
646 CURLcode result = CURLE_OK;
647 struct Curl_easy *data = conn->data;
648 struct ssl_connect_data *connssl = &conn->ssl[sockindex];
649 SECURITY_STATUS sspi_status = SEC_E_OK;
650 CERT_CONTEXT *ccert_context = NULL;
651 const char * const hostname = SSL_IS_PROXY() ? conn->http_proxy.host.name :
652 conn->host.name;
653 #ifdef HAS_ALPN
654 SecPkgContext_ApplicationProtocol alpn_result;
655 #endif
656
657 DEBUGASSERT(ssl_connect_3 == connssl->connecting_state);
658
659 infof(data, "schannel: SSL/TLS connection with %s port %hu (step 3/3)\n",
660 hostname, conn->remote_port);
661
662 if(!connssl->cred)
663 return CURLE_SSL_CONNECT_ERROR;
664
665 /* check if the required context attributes are met */
666 if(connssl->ret_flags != connssl->req_flags) {
667 if(!(connssl->ret_flags & ISC_RET_SEQUENCE_DETECT))
668 failf(data, "schannel: failed to setup sequence detection");
669 if(!(connssl->ret_flags & ISC_RET_REPLAY_DETECT))
670 failf(data, "schannel: failed to setup replay detection");
671 if(!(connssl->ret_flags & ISC_RET_CONFIDENTIALITY))
672 failf(data, "schannel: failed to setup confidentiality");
673 if(!(connssl->ret_flags & ISC_RET_ALLOCATED_MEMORY))
674 failf(data, "schannel: failed to setup memory allocation");
675 if(!(connssl->ret_flags & ISC_RET_STREAM))
676 failf(data, "schannel: failed to setup stream orientation");
677 return CURLE_SSL_CONNECT_ERROR;
678 }
679
680 #ifdef HAS_ALPN
681 if(connssl->use_alpn) {
682 sspi_status = s_pSecFn->QueryContextAttributes(&connssl->ctxt->ctxt_handle,
683 SECPKG_ATTR_APPLICATION_PROTOCOL, &alpn_result);
684
685 if(sspi_status != SEC_E_OK) {
686 failf(data, "schannel: failed to retrieve ALPN result");
687 return CURLE_SSL_CONNECT_ERROR;
688 }
689
690 if(alpn_result.ProtoNegoStatus ==
691 SecApplicationProtocolNegotiationStatus_Success) {
692
693 infof(data, "schannel: ALPN, server accepted to use %.*s\n",
694 alpn_result.ProtocolIdSize, alpn_result.ProtocolId);
695
696 #ifdef USE_NGHTTP2
697 if(alpn_result.ProtocolIdSize == NGHTTP2_PROTO_VERSION_ID_LEN &&
698 !memcmp(NGHTTP2_PROTO_VERSION_ID, alpn_result.ProtocolId,
699 NGHTTP2_PROTO_VERSION_ID_LEN)) {
700 conn->negnpn = CURL_HTTP_VERSION_2;
701 }
702 else
703 #endif
704 if(alpn_result.ProtocolIdSize == ALPN_HTTP_1_1_LENGTH &&
705 !memcmp(ALPN_HTTP_1_1, alpn_result.ProtocolId,
706 ALPN_HTTP_1_1_LENGTH)) {
707 conn->negnpn = CURL_HTTP_VERSION_1_1;
708 }
709 }
710 else
711 infof(data, "ALPN, server did not agree to a protocol\n");
712 }
713 #endif
714
715 /* save the current session data for possible re-use */
716 if(data->set.general_ssl.sessionid) {
717 bool incache;
718 struct curl_schannel_cred *old_cred = NULL;
719
720 Curl_ssl_sessionid_lock(conn);
721 incache = !(Curl_ssl_getsessionid(conn, (void **)&old_cred, NULL,
722 sockindex));
723 if(incache) {
724 if(old_cred != connssl->cred) {
725 infof(data, "schannel: old credential handle is stale, removing\n");
726 /* we're not taking old_cred ownership here, no refcount++ is needed */
727 Curl_ssl_delsessionid(conn, (void *)old_cred);
728 incache = FALSE;
729 }
730 }
731 if(!incache) {
732 result = Curl_ssl_addsessionid(conn, (void *)connssl->cred,
733 sizeof(struct curl_schannel_cred),
734 sockindex);
735 if(result) {
736 Curl_ssl_sessionid_unlock(conn);
737 failf(data, "schannel: failed to store credential handle");
738 return result;
739 }
740 else {
741 /* this cred session is now also referenced by sessionid cache */
742 connssl->cred->refcount++;
743 infof(data, "schannel: stored credential handle in session cache\n");
744 }
745 }
746 Curl_ssl_sessionid_unlock(conn);
747 }
748
749 if(data->set.ssl.certinfo) {
750 sspi_status = s_pSecFn->QueryContextAttributes(&connssl->ctxt->ctxt_handle,
751 SECPKG_ATTR_REMOTE_CERT_CONTEXT, &ccert_context);
752
753 if((sspi_status != SEC_E_OK) || (ccert_context == NULL)) {
754 failf(data, "schannel: failed to retrieve remote cert context");
755 return CURLE_SSL_CONNECT_ERROR;
756 }
757
758 result = Curl_ssl_init_certinfo(data, 1);
759 if(!result) {
760 if(((ccert_context->dwCertEncodingType & X509_ASN_ENCODING) != 0) &&
761 (ccert_context->cbCertEncoded > 0)) {
762
763 const char *beg = (const char *) ccert_context->pbCertEncoded;
764 const char *end = beg + ccert_context->cbCertEncoded;
765 result = Curl_extract_certinfo(conn, 0, beg, end);
766 }
767 }
768 CertFreeCertificateContext(ccert_context);
769 if(result)
770 return result;
771 }
772
773 connssl->connecting_state = ssl_connect_done;
774
775 return CURLE_OK;
776 }
777
778 static CURLcode
schannel_connect_common(struct connectdata * conn,int sockindex,bool nonblocking,bool * done)779 schannel_connect_common(struct connectdata *conn, int sockindex,
780 bool nonblocking, bool *done)
781 {
782 CURLcode result;
783 struct Curl_easy *data = conn->data;
784 struct ssl_connect_data *connssl = &conn->ssl[sockindex];
785 curl_socket_t sockfd = conn->sock[sockindex];
786 time_t timeout_ms;
787 int what;
788
789 /* check if the connection has already been established */
790 if(ssl_connection_complete == connssl->state) {
791 *done = TRUE;
792 return CURLE_OK;
793 }
794
795 if(ssl_connect_1 == connssl->connecting_state) {
796 /* check out how much more time we're allowed */
797 timeout_ms = Curl_timeleft(data, NULL, TRUE);
798
799 if(timeout_ms < 0) {
800 /* no need to continue if time already is up */
801 failf(data, "SSL/TLS connection timeout");
802 return CURLE_OPERATION_TIMEDOUT;
803 }
804
805 result = schannel_connect_step1(conn, sockindex);
806 if(result)
807 return result;
808 }
809
810 while(ssl_connect_2 == connssl->connecting_state ||
811 ssl_connect_2_reading == connssl->connecting_state ||
812 ssl_connect_2_writing == connssl->connecting_state) {
813
814 /* check out how much more time we're allowed */
815 timeout_ms = Curl_timeleft(data, NULL, TRUE);
816
817 if(timeout_ms < 0) {
818 /* no need to continue if time already is up */
819 failf(data, "SSL/TLS connection timeout");
820 return CURLE_OPERATION_TIMEDOUT;
821 }
822
823 /* if ssl is expecting something, check if it's available. */
824 if(connssl->connecting_state == ssl_connect_2_reading
825 || connssl->connecting_state == ssl_connect_2_writing) {
826
827 curl_socket_t writefd = ssl_connect_2_writing ==
828 connssl->connecting_state ? sockfd : CURL_SOCKET_BAD;
829 curl_socket_t readfd = ssl_connect_2_reading ==
830 connssl->connecting_state ? sockfd : CURL_SOCKET_BAD;
831
832 what = Curl_socket_check(readfd, CURL_SOCKET_BAD, writefd,
833 nonblocking ? 0 : timeout_ms);
834 if(what < 0) {
835 /* fatal error */
836 failf(data, "select/poll on SSL/TLS socket, errno: %d", SOCKERRNO);
837 return CURLE_SSL_CONNECT_ERROR;
838 }
839 else if(0 == what) {
840 if(nonblocking) {
841 *done = FALSE;
842 return CURLE_OK;
843 }
844 else {
845 /* timeout */
846 failf(data, "SSL/TLS connection timeout");
847 return CURLE_OPERATION_TIMEDOUT;
848 }
849 }
850 /* socket is readable or writable */
851 }
852
853 /* Run transaction, and return to the caller if it failed or if
854 * this connection is part of a multi handle and this loop would
855 * execute again. This permits the owner of a multi handle to
856 * abort a connection attempt before step2 has completed while
857 * ensuring that a client using select() or epoll() will always
858 * have a valid fdset to wait on.
859 */
860 result = schannel_connect_step2(conn, sockindex);
861 if(result || (nonblocking &&
862 (ssl_connect_2 == connssl->connecting_state ||
863 ssl_connect_2_reading == connssl->connecting_state ||
864 ssl_connect_2_writing == connssl->connecting_state)))
865 return result;
866
867 } /* repeat step2 until all transactions are done. */
868
869 if(ssl_connect_3 == connssl->connecting_state) {
870 result = schannel_connect_step3(conn, sockindex);
871 if(result)
872 return result;
873 }
874
875 if(ssl_connect_done == connssl->connecting_state) {
876 connssl->state = ssl_connection_complete;
877 conn->recv[sockindex] = schannel_recv;
878 conn->send[sockindex] = schannel_send;
879 *done = TRUE;
880 }
881 else
882 *done = FALSE;
883
884 /* reset our connection state machine */
885 connssl->connecting_state = ssl_connect_1;
886
887 return CURLE_OK;
888 }
889
890 static ssize_t
schannel_send(struct connectdata * conn,int sockindex,const void * buf,size_t len,CURLcode * err)891 schannel_send(struct connectdata *conn, int sockindex,
892 const void *buf, size_t len, CURLcode *err)
893 {
894 ssize_t written = -1;
895 size_t data_len = 0;
896 unsigned char *data = NULL;
897 struct ssl_connect_data *connssl = &conn->ssl[sockindex];
898 SecBuffer outbuf[4];
899 SecBufferDesc outbuf_desc;
900 SECURITY_STATUS sspi_status = SEC_E_OK;
901 CURLcode result;
902
903 /* check if the maximum stream sizes were queried */
904 if(connssl->stream_sizes.cbMaximumMessage == 0) {
905 sspi_status = s_pSecFn->QueryContextAttributes(
906 &connssl->ctxt->ctxt_handle,
907 SECPKG_ATTR_STREAM_SIZES,
908 &connssl->stream_sizes);
909 if(sspi_status != SEC_E_OK) {
910 *err = CURLE_SEND_ERROR;
911 return -1;
912 }
913 }
914
915 /* check if the buffer is longer than the maximum message length */
916 if(len > connssl->stream_sizes.cbMaximumMessage) {
917 *err = CURLE_SEND_ERROR;
918 return -1;
919 }
920
921 /* calculate the complete message length and allocate a buffer for it */
922 data_len = connssl->stream_sizes.cbHeader + len +
923 connssl->stream_sizes.cbTrailer;
924 data = (unsigned char *) malloc(data_len);
925 if(data == NULL) {
926 *err = CURLE_OUT_OF_MEMORY;
927 return -1;
928 }
929
930 /* setup output buffers (header, data, trailer, empty) */
931 InitSecBuffer(&outbuf[0], SECBUFFER_STREAM_HEADER,
932 data, connssl->stream_sizes.cbHeader);
933 InitSecBuffer(&outbuf[1], SECBUFFER_DATA,
934 data + connssl->stream_sizes.cbHeader, curlx_uztoul(len));
935 InitSecBuffer(&outbuf[2], SECBUFFER_STREAM_TRAILER,
936 data + connssl->stream_sizes.cbHeader + len,
937 connssl->stream_sizes.cbTrailer);
938 InitSecBuffer(&outbuf[3], SECBUFFER_EMPTY, NULL, 0);
939 InitSecBufferDesc(&outbuf_desc, outbuf, 4);
940
941 /* copy data into output buffer */
942 memcpy(outbuf[1].pvBuffer, buf, len);
943
944 /* https://msdn.microsoft.com/en-us/library/windows/desktop/aa375390.aspx */
945 sspi_status = s_pSecFn->EncryptMessage(&connssl->ctxt->ctxt_handle, 0,
946 &outbuf_desc, 0);
947
948 /* check if the message was encrypted */
949 if(sspi_status == SEC_E_OK) {
950 written = 0;
951
952 /* send the encrypted message including header, data and trailer */
953 len = outbuf[0].cbBuffer + outbuf[1].cbBuffer + outbuf[2].cbBuffer;
954
955 /*
956 It's important to send the full message which includes the header,
957 encrypted payload, and trailer. Until the client receives all the
958 data a coherent message has not been delivered and the client
959 can't read any of it.
960
961 If we wanted to buffer the unwritten encrypted bytes, we would
962 tell the client that all data it has requested to be sent has been
963 sent. The unwritten encrypted bytes would be the first bytes to
964 send on the next invocation.
965 Here's the catch with this - if we tell the client that all the
966 bytes have been sent, will the client call this method again to
967 send the buffered data? Looking at who calls this function, it
968 seems the answer is NO.
969 */
970
971 /* send entire message or fail */
972 while(len > (size_t)written) {
973 ssize_t this_write;
974 time_t timeleft;
975 int what;
976
977 this_write = 0;
978
979 timeleft = Curl_timeleft(conn->data, NULL, FALSE);
980 if(timeleft < 0) {
981 /* we already got the timeout */
982 failf(conn->data, "schannel: timed out sending data "
983 "(bytes sent: %zd)", written);
984 *err = CURLE_OPERATION_TIMEDOUT;
985 written = -1;
986 break;
987 }
988
989 what = SOCKET_WRITABLE(conn->sock[sockindex], timeleft);
990 if(what < 0) {
991 /* fatal error */
992 failf(conn->data, "select/poll on SSL socket, errno: %d", SOCKERRNO);
993 *err = CURLE_SEND_ERROR;
994 written = -1;
995 break;
996 }
997 else if(0 == what) {
998 failf(conn->data, "schannel: timed out sending data "
999 "(bytes sent: %zd)", written);
1000 *err = CURLE_OPERATION_TIMEDOUT;
1001 written = -1;
1002 break;
1003 }
1004 /* socket is writable */
1005
1006 result = Curl_write_plain(conn, conn->sock[sockindex], data + written,
1007 len - written, &this_write);
1008 if(result == CURLE_AGAIN)
1009 continue;
1010 else if(result != CURLE_OK) {
1011 *err = result;
1012 written = -1;
1013 break;
1014 }
1015
1016 written += this_write;
1017 }
1018 }
1019 else if(sspi_status == SEC_E_INSUFFICIENT_MEMORY) {
1020 *err = CURLE_OUT_OF_MEMORY;
1021 }
1022 else{
1023 *err = CURLE_SEND_ERROR;
1024 }
1025
1026 Curl_safefree(data);
1027
1028 if(len == (size_t)written)
1029 /* Encrypted message including header, data and trailer entirely sent.
1030 The return value is the number of unencrypted bytes that were sent. */
1031 written = outbuf[1].cbBuffer;
1032
1033 return written;
1034 }
1035
1036 static ssize_t
schannel_recv(struct connectdata * conn,int sockindex,char * buf,size_t len,CURLcode * err)1037 schannel_recv(struct connectdata *conn, int sockindex,
1038 char *buf, size_t len, CURLcode *err)
1039 {
1040 size_t size = 0;
1041 ssize_t nread = -1;
1042 struct Curl_easy *data = conn->data;
1043 struct ssl_connect_data *connssl = &conn->ssl[sockindex];
1044 unsigned char *reallocated_buffer;
1045 size_t reallocated_length;
1046 bool done = FALSE;
1047 SecBuffer inbuf[4];
1048 SecBufferDesc inbuf_desc;
1049 SECURITY_STATUS sspi_status = SEC_E_OK;
1050 /* we want the length of the encrypted buffer to be at least large enough
1051 that it can hold all the bytes requested and some TLS record overhead. */
1052 size_t min_encdata_length = len + CURL_SCHANNEL_BUFFER_FREE_SIZE;
1053
1054 /****************************************************************************
1055 * Don't return or set connssl->recv_unrecoverable_err unless in the cleanup.
1056 * The pattern for return error is set *err, optional infof, goto cleanup.
1057 *
1058 * Our priority is to always return as much decrypted data to the caller as
1059 * possible, even if an error occurs. The state of the decrypted buffer must
1060 * always be valid. Transfer of decrypted data to the caller's buffer is
1061 * handled in the cleanup.
1062 */
1063
1064 infof(data, "schannel: client wants to read %zu bytes\n", len);
1065 *err = CURLE_OK;
1066
1067 if(len && len <= connssl->decdata_offset) {
1068 infof(data, "schannel: enough decrypted data is already available\n");
1069 goto cleanup;
1070 }
1071 else if(connssl->recv_unrecoverable_err) {
1072 *err = connssl->recv_unrecoverable_err;
1073 infof(data, "schannel: an unrecoverable error occurred in a prior call\n");
1074 goto cleanup;
1075 }
1076 else if(connssl->recv_sspi_close_notify) {
1077 /* once a server has indicated shutdown there is no more encrypted data */
1078 infof(data, "schannel: server indicated shutdown in a prior call\n");
1079 goto cleanup;
1080 }
1081 else if(!len) {
1082 /* It's debatable what to return when !len. Regardless we can't return
1083 immediately because there may be data to decrypt (in the case we want to
1084 decrypt all encrypted cached data) so handle !len later in cleanup.
1085 */
1086 ; /* do nothing */
1087 }
1088 else if(!connssl->recv_connection_closed) {
1089 /* increase enc buffer in order to fit the requested amount of data */
1090 size = connssl->encdata_length - connssl->encdata_offset;
1091 if(size < CURL_SCHANNEL_BUFFER_FREE_SIZE ||
1092 connssl->encdata_length < min_encdata_length) {
1093 reallocated_length = connssl->encdata_offset +
1094 CURL_SCHANNEL_BUFFER_FREE_SIZE;
1095 if(reallocated_length < min_encdata_length) {
1096 reallocated_length = min_encdata_length;
1097 }
1098 reallocated_buffer = realloc(connssl->encdata_buffer,
1099 reallocated_length);
1100 if(reallocated_buffer == NULL) {
1101 *err = CURLE_OUT_OF_MEMORY;
1102 failf(data, "schannel: unable to re-allocate memory");
1103 goto cleanup;
1104 }
1105
1106 connssl->encdata_buffer = reallocated_buffer;
1107 connssl->encdata_length = reallocated_length;
1108 size = connssl->encdata_length - connssl->encdata_offset;
1109 infof(data, "schannel: encdata_buffer resized %zu\n",
1110 connssl->encdata_length);
1111 }
1112
1113 infof(data, "schannel: encrypted data buffer: offset %zu length %zu\n",
1114 connssl->encdata_offset, connssl->encdata_length);
1115
1116 /* read encrypted data from socket */
1117 *err = Curl_read_plain(conn->sock[sockindex],
1118 (char *)(connssl->encdata_buffer +
1119 connssl->encdata_offset),
1120 size, &nread);
1121 if(*err) {
1122 nread = -1;
1123 if(*err == CURLE_AGAIN)
1124 infof(data, "schannel: Curl_read_plain returned CURLE_AGAIN\n");
1125 else if(*err == CURLE_RECV_ERROR)
1126 infof(data, "schannel: Curl_read_plain returned CURLE_RECV_ERROR\n");
1127 else
1128 infof(data, "schannel: Curl_read_plain returned error %d\n", *err);
1129 }
1130 else if(nread == 0) {
1131 connssl->recv_connection_closed = true;
1132 infof(data, "schannel: server closed the connection\n");
1133 }
1134 else if(nread > 0) {
1135 connssl->encdata_offset += (size_t)nread;
1136 infof(data, "schannel: encrypted data got %zd\n", nread);
1137 }
1138 }
1139
1140 infof(data, "schannel: encrypted data buffer: offset %zu length %zu\n",
1141 connssl->encdata_offset, connssl->encdata_length);
1142
1143 /* decrypt loop */
1144 while(connssl->encdata_offset > 0 && sspi_status == SEC_E_OK &&
1145 (!len || connssl->decdata_offset < len ||
1146 connssl->recv_connection_closed)) {
1147 /* prepare data buffer for DecryptMessage call */
1148 InitSecBuffer(&inbuf[0], SECBUFFER_DATA, connssl->encdata_buffer,
1149 curlx_uztoul(connssl->encdata_offset));
1150
1151 /* we need 3 more empty input buffers for possible output */
1152 InitSecBuffer(&inbuf[1], SECBUFFER_EMPTY, NULL, 0);
1153 InitSecBuffer(&inbuf[2], SECBUFFER_EMPTY, NULL, 0);
1154 InitSecBuffer(&inbuf[3], SECBUFFER_EMPTY, NULL, 0);
1155 InitSecBufferDesc(&inbuf_desc, inbuf, 4);
1156
1157 /* https://msdn.microsoft.com/en-us/library/windows/desktop/aa375348.aspx
1158 */
1159 sspi_status = s_pSecFn->DecryptMessage(&connssl->ctxt->ctxt_handle,
1160 &inbuf_desc, 0, NULL);
1161
1162 /* check if everything went fine (server may want to renegotiate
1163 or shutdown the connection context) */
1164 if(sspi_status == SEC_E_OK || sspi_status == SEC_I_RENEGOTIATE ||
1165 sspi_status == SEC_I_CONTEXT_EXPIRED) {
1166 /* check for successfully decrypted data, even before actual
1167 renegotiation or shutdown of the connection context */
1168 if(inbuf[1].BufferType == SECBUFFER_DATA) {
1169 infof(data, "schannel: decrypted data length: %lu\n",
1170 inbuf[1].cbBuffer);
1171
1172 /* increase buffer in order to fit the received amount of data */
1173 size = inbuf[1].cbBuffer > CURL_SCHANNEL_BUFFER_FREE_SIZE ?
1174 inbuf[1].cbBuffer : CURL_SCHANNEL_BUFFER_FREE_SIZE;
1175 if(connssl->decdata_length - connssl->decdata_offset < size ||
1176 connssl->decdata_length < len) {
1177 /* increase internal decrypted data buffer */
1178 reallocated_length = connssl->decdata_offset + size;
1179 /* make sure that the requested amount of data fits */
1180 if(reallocated_length < len) {
1181 reallocated_length = len;
1182 }
1183 reallocated_buffer = realloc(connssl->decdata_buffer,
1184 reallocated_length);
1185 if(reallocated_buffer == NULL) {
1186 *err = CURLE_OUT_OF_MEMORY;
1187 failf(data, "schannel: unable to re-allocate memory");
1188 goto cleanup;
1189 }
1190 connssl->decdata_buffer = reallocated_buffer;
1191 connssl->decdata_length = reallocated_length;
1192 }
1193
1194 /* copy decrypted data to internal buffer */
1195 size = inbuf[1].cbBuffer;
1196 if(size) {
1197 memcpy(connssl->decdata_buffer + connssl->decdata_offset,
1198 inbuf[1].pvBuffer, size);
1199 connssl->decdata_offset += size;
1200 }
1201
1202 infof(data, "schannel: decrypted data added: %zu\n", size);
1203 infof(data, "schannel: decrypted data cached: offset %zu length %zu\n",
1204 connssl->decdata_offset, connssl->decdata_length);
1205 }
1206
1207 /* check for remaining encrypted data */
1208 if(inbuf[3].BufferType == SECBUFFER_EXTRA && inbuf[3].cbBuffer > 0) {
1209 infof(data, "schannel: encrypted data length: %lu\n",
1210 inbuf[3].cbBuffer);
1211
1212 /* check if the remaining data is less than the total amount
1213 * and therefore begins after the already processed data
1214 */
1215 if(connssl->encdata_offset > inbuf[3].cbBuffer) {
1216 /* move remaining encrypted data forward to the beginning of
1217 buffer */
1218 memmove(connssl->encdata_buffer,
1219 (connssl->encdata_buffer + connssl->encdata_offset) -
1220 inbuf[3].cbBuffer, inbuf[3].cbBuffer);
1221 connssl->encdata_offset = inbuf[3].cbBuffer;
1222 }
1223
1224 infof(data, "schannel: encrypted data cached: offset %zu length %zu\n",
1225 connssl->encdata_offset, connssl->encdata_length);
1226 }
1227 else {
1228 /* reset encrypted buffer offset, because there is no data remaining */
1229 connssl->encdata_offset = 0;
1230 }
1231
1232 /* check if server wants to renegotiate the connection context */
1233 if(sspi_status == SEC_I_RENEGOTIATE) {
1234 infof(data, "schannel: remote party requests renegotiation\n");
1235 if(*err && *err != CURLE_AGAIN) {
1236 infof(data, "schannel: can't renogotiate, an error is pending\n");
1237 goto cleanup;
1238 }
1239 if(connssl->encdata_offset) {
1240 *err = CURLE_RECV_ERROR;
1241 infof(data, "schannel: can't renogotiate, "
1242 "encrypted data available\n");
1243 goto cleanup;
1244 }
1245 /* begin renegotiation */
1246 infof(data, "schannel: renegotiating SSL/TLS connection\n");
1247 connssl->state = ssl_connection_negotiating;
1248 connssl->connecting_state = ssl_connect_2_writing;
1249 *err = schannel_connect_common(conn, sockindex, FALSE, &done);
1250 if(*err) {
1251 infof(data, "schannel: renegotiation failed\n");
1252 goto cleanup;
1253 }
1254 /* now retry receiving data */
1255 sspi_status = SEC_E_OK;
1256 infof(data, "schannel: SSL/TLS connection renegotiated\n");
1257 continue;
1258 }
1259 /* check if the server closed the connection */
1260 else if(sspi_status == SEC_I_CONTEXT_EXPIRED) {
1261 /* In Windows 2000 SEC_I_CONTEXT_EXPIRED (close_notify) is not
1262 returned so we have to work around that in cleanup. */
1263 connssl->recv_sspi_close_notify = true;
1264 if(!connssl->recv_connection_closed) {
1265 connssl->recv_connection_closed = true;
1266 infof(data, "schannel: server closed the connection\n");
1267 }
1268 goto cleanup;
1269 }
1270 }
1271 else if(sspi_status == SEC_E_INCOMPLETE_MESSAGE) {
1272 if(!*err)
1273 *err = CURLE_AGAIN;
1274 infof(data, "schannel: failed to decrypt data, need more data\n");
1275 goto cleanup;
1276 }
1277 else {
1278 *err = CURLE_RECV_ERROR;
1279 infof(data, "schannel: failed to read data from server: %s\n",
1280 Curl_sspi_strerror(conn, sspi_status));
1281 goto cleanup;
1282 }
1283 }
1284
1285 infof(data, "schannel: encrypted data buffer: offset %zu length %zu\n",
1286 connssl->encdata_offset, connssl->encdata_length);
1287
1288 infof(data, "schannel: decrypted data buffer: offset %zu length %zu\n",
1289 connssl->decdata_offset, connssl->decdata_length);
1290
1291 cleanup:
1292 /* Warning- there is no guarantee the encdata state is valid at this point */
1293 infof(data, "schannel: schannel_recv cleanup\n");
1294
1295 /* Error if the connection has closed without a close_notify.
1296 Behavior here is a matter of debate. We don't want to be vulnerable to a
1297 truncation attack however there's some browser precedent for ignoring the
1298 close_notify for compatibility reasons.
1299 Additionally, Windows 2000 (v5.0) is a special case since it seems it doesn't
1300 return close_notify. In that case if the connection was closed we assume it
1301 was graceful (close_notify) since there doesn't seem to be a way to tell.
1302 */
1303 if(len && !connssl->decdata_offset && connssl->recv_connection_closed &&
1304 !connssl->recv_sspi_close_notify) {
1305 bool isWin2k = Curl_verify_windows_version(5, 0, PLATFORM_WINNT,
1306 VERSION_EQUAL);
1307
1308 if(isWin2k && sspi_status == SEC_E_OK)
1309 connssl->recv_sspi_close_notify = true;
1310 else {
1311 *err = CURLE_RECV_ERROR;
1312 infof(data, "schannel: server closed abruptly (missing close_notify)\n");
1313 }
1314 }
1315
1316 /* Any error other than CURLE_AGAIN is an unrecoverable error. */
1317 if(*err && *err != CURLE_AGAIN)
1318 connssl->recv_unrecoverable_err = *err;
1319
1320 size = len < connssl->decdata_offset ? len : connssl->decdata_offset;
1321 if(size) {
1322 memcpy(buf, connssl->decdata_buffer, size);
1323 memmove(connssl->decdata_buffer, connssl->decdata_buffer + size,
1324 connssl->decdata_offset - size);
1325 connssl->decdata_offset -= size;
1326
1327 infof(data, "schannel: decrypted data returned %zu\n", size);
1328 infof(data, "schannel: decrypted data buffer: offset %zu length %zu\n",
1329 connssl->decdata_offset, connssl->decdata_length);
1330 *err = CURLE_OK;
1331 return (ssize_t)size;
1332 }
1333
1334 if(!*err && !connssl->recv_connection_closed)
1335 *err = CURLE_AGAIN;
1336
1337 /* It's debatable what to return when !len. We could return whatever error we
1338 got from decryption but instead we override here so the return is consistent.
1339 */
1340 if(!len)
1341 *err = CURLE_OK;
1342
1343 return *err ? -1 : 0;
1344 }
1345
1346 CURLcode
Curl_schannel_connect_nonblocking(struct connectdata * conn,int sockindex,bool * done)1347 Curl_schannel_connect_nonblocking(struct connectdata *conn, int sockindex,
1348 bool *done)
1349 {
1350 return schannel_connect_common(conn, sockindex, TRUE, done);
1351 }
1352
1353 CURLcode
Curl_schannel_connect(struct connectdata * conn,int sockindex)1354 Curl_schannel_connect(struct connectdata *conn, int sockindex)
1355 {
1356 CURLcode result;
1357 bool done = FALSE;
1358
1359 result = schannel_connect_common(conn, sockindex, FALSE, &done);
1360 if(result)
1361 return result;
1362
1363 DEBUGASSERT(done);
1364
1365 return CURLE_OK;
1366 }
1367
Curl_schannel_data_pending(const struct connectdata * conn,int sockindex)1368 bool Curl_schannel_data_pending(const struct connectdata *conn, int sockindex)
1369 {
1370 const struct ssl_connect_data *connssl = &conn->ssl[sockindex];
1371
1372 if(connssl->use) /* SSL/TLS is in use */
1373 return (connssl->encdata_offset > 0 ||
1374 connssl->decdata_offset > 0) ? TRUE : FALSE;
1375 else
1376 return FALSE;
1377 }
1378
Curl_schannel_close(struct connectdata * conn,int sockindex)1379 void Curl_schannel_close(struct connectdata *conn, int sockindex)
1380 {
1381 if(conn->ssl[sockindex].use)
1382 /* if the SSL/TLS channel hasn't been shut down yet, do that now. */
1383 Curl_ssl_shutdown(conn, sockindex);
1384 }
1385
Curl_schannel_shutdown(struct connectdata * conn,int sockindex)1386 int Curl_schannel_shutdown(struct connectdata *conn, int sockindex)
1387 {
1388 /* See https://msdn.microsoft.com/en-us/library/windows/desktop/aa380138.aspx
1389 * Shutting Down an Schannel Connection
1390 */
1391 struct Curl_easy *data = conn->data;
1392 struct ssl_connect_data *connssl = &conn->ssl[sockindex];
1393 const char * const hostname = SSL_IS_PROXY() ? conn->http_proxy.host.name :
1394 conn->host.name;
1395
1396 infof(data, "schannel: shutting down SSL/TLS connection with %s port %hu\n",
1397 hostname, conn->remote_port);
1398
1399 if(connssl->cred && connssl->ctxt) {
1400 SecBufferDesc BuffDesc;
1401 SecBuffer Buffer;
1402 SECURITY_STATUS sspi_status;
1403 SecBuffer outbuf;
1404 SecBufferDesc outbuf_desc;
1405 CURLcode result;
1406 TCHAR *host_name;
1407 DWORD dwshut = SCHANNEL_SHUTDOWN;
1408
1409 InitSecBuffer(&Buffer, SECBUFFER_TOKEN, &dwshut, sizeof(dwshut));
1410 InitSecBufferDesc(&BuffDesc, &Buffer, 1);
1411
1412 sspi_status = s_pSecFn->ApplyControlToken(&connssl->ctxt->ctxt_handle,
1413 &BuffDesc);
1414
1415 if(sspi_status != SEC_E_OK)
1416 failf(data, "schannel: ApplyControlToken failure: %s",
1417 Curl_sspi_strerror(conn, sspi_status));
1418
1419 host_name = Curl_convert_UTF8_to_tchar(hostname);
1420 if(!host_name)
1421 return CURLE_OUT_OF_MEMORY;
1422
1423 /* setup output buffer */
1424 InitSecBuffer(&outbuf, SECBUFFER_EMPTY, NULL, 0);
1425 InitSecBufferDesc(&outbuf_desc, &outbuf, 1);
1426
1427 sspi_status = s_pSecFn->InitializeSecurityContext(
1428 &connssl->cred->cred_handle,
1429 &connssl->ctxt->ctxt_handle,
1430 host_name,
1431 connssl->req_flags,
1432 0,
1433 0,
1434 NULL,
1435 0,
1436 &connssl->ctxt->ctxt_handle,
1437 &outbuf_desc,
1438 &connssl->ret_flags,
1439 &connssl->ctxt->time_stamp);
1440
1441 Curl_unicodefree(host_name);
1442
1443 if((sspi_status == SEC_E_OK) || (sspi_status == SEC_I_CONTEXT_EXPIRED)) {
1444 /* send close message which is in output buffer */
1445 ssize_t written;
1446 result = Curl_write_plain(conn, conn->sock[sockindex], outbuf.pvBuffer,
1447 outbuf.cbBuffer, &written);
1448
1449 s_pSecFn->FreeContextBuffer(outbuf.pvBuffer);
1450 if((result != CURLE_OK) || (outbuf.cbBuffer != (size_t) written)) {
1451 infof(data, "schannel: failed to send close msg: %s"
1452 " (bytes written: %zd)\n", curl_easy_strerror(result), written);
1453 }
1454 }
1455 }
1456
1457 /* free SSPI Schannel API security context handle */
1458 if(connssl->ctxt) {
1459 infof(data, "schannel: clear security context handle\n");
1460 s_pSecFn->DeleteSecurityContext(&connssl->ctxt->ctxt_handle);
1461 Curl_safefree(connssl->ctxt);
1462 }
1463
1464 /* free SSPI Schannel API credential handle */
1465 if(connssl->cred) {
1466 Curl_ssl_sessionid_lock(conn);
1467 Curl_schannel_session_free(connssl->cred);
1468 Curl_ssl_sessionid_unlock(conn);
1469 connssl->cred = NULL;
1470 }
1471
1472 /* free internal buffer for received encrypted data */
1473 if(connssl->encdata_buffer != NULL) {
1474 Curl_safefree(connssl->encdata_buffer);
1475 connssl->encdata_length = 0;
1476 connssl->encdata_offset = 0;
1477 }
1478
1479 /* free internal buffer for received decrypted data */
1480 if(connssl->decdata_buffer != NULL) {
1481 Curl_safefree(connssl->decdata_buffer);
1482 connssl->decdata_length = 0;
1483 connssl->decdata_offset = 0;
1484 }
1485
1486 return CURLE_OK;
1487 }
1488
Curl_schannel_session_free(void * ptr)1489 void Curl_schannel_session_free(void *ptr)
1490 {
1491 /* this is expected to be called under sessionid lock */
1492 struct curl_schannel_cred *cred = ptr;
1493
1494 cred->refcount--;
1495 if(cred->refcount == 0) {
1496 s_pSecFn->FreeCredentialsHandle(&cred->cred_handle);
1497 Curl_safefree(cred);
1498 }
1499 }
1500
Curl_schannel_init(void)1501 int Curl_schannel_init(void)
1502 {
1503 return (Curl_sspi_global_init() == CURLE_OK ? 1 : 0);
1504 }
1505
Curl_schannel_cleanup(void)1506 void Curl_schannel_cleanup(void)
1507 {
1508 Curl_sspi_global_cleanup();
1509 }
1510
Curl_schannel_version(char * buffer,size_t size)1511 size_t Curl_schannel_version(char *buffer, size_t size)
1512 {
1513 size = snprintf(buffer, size, "WinSSL");
1514
1515 return size;
1516 }
1517
Curl_schannel_random(unsigned char * entropy,size_t length)1518 int Curl_schannel_random(unsigned char *entropy, size_t length)
1519 {
1520 HCRYPTPROV hCryptProv = 0;
1521
1522 if(!CryptAcquireContext(&hCryptProv, NULL, NULL, PROV_RSA_FULL,
1523 CRYPT_VERIFYCONTEXT | CRYPT_SILENT))
1524 return 1;
1525
1526 if(!CryptGenRandom(hCryptProv, (DWORD)length, entropy)) {
1527 CryptReleaseContext(hCryptProv, 0UL);
1528 return 1;
1529 }
1530
1531 CryptReleaseContext(hCryptProv, 0UL);
1532 return 0;
1533 }
1534
1535 #ifdef _WIN32_WCE
verify_certificate(struct connectdata * conn,int sockindex)1536 static CURLcode verify_certificate(struct connectdata *conn, int sockindex)
1537 {
1538 SECURITY_STATUS status;
1539 struct Curl_easy *data = conn->data;
1540 struct ssl_connect_data *connssl = &conn->ssl[sockindex];
1541 CURLcode result = CURLE_OK;
1542 CERT_CONTEXT *pCertContextServer = NULL;
1543 const CERT_CHAIN_CONTEXT *pChainContext = NULL;
1544 const char * const conn_hostname = SSL_IS_PROXY() ?
1545 conn->http_proxy.host.name :
1546 conn->host.name;
1547
1548 status = s_pSecFn->QueryContextAttributes(&connssl->ctxt->ctxt_handle,
1549 SECPKG_ATTR_REMOTE_CERT_CONTEXT,
1550 &pCertContextServer);
1551
1552 if((status != SEC_E_OK) || (pCertContextServer == NULL)) {
1553 failf(data, "schannel: Failed to read remote certificate context: %s",
1554 Curl_sspi_strerror(conn, status));
1555 result = CURLE_PEER_FAILED_VERIFICATION;
1556 }
1557
1558 if(result == CURLE_OK) {
1559 CERT_CHAIN_PARA ChainPara;
1560 memset(&ChainPara, 0, sizeof(ChainPara));
1561 ChainPara.cbSize = sizeof(ChainPara);
1562
1563 if(!CertGetCertificateChain(NULL,
1564 pCertContextServer,
1565 NULL,
1566 pCertContextServer->hCertStore,
1567 &ChainPara,
1568 (data->set.ssl.no_revoke ? 0 :
1569 CERT_CHAIN_REVOCATION_CHECK_CHAIN),
1570 NULL,
1571 &pChainContext)) {
1572 failf(data, "schannel: CertGetCertificateChain failed: %s",
1573 Curl_sspi_strerror(conn, GetLastError()));
1574 pChainContext = NULL;
1575 result = CURLE_PEER_FAILED_VERIFICATION;
1576 }
1577
1578 if(result == CURLE_OK) {
1579 CERT_SIMPLE_CHAIN *pSimpleChain = pChainContext->rgpChain[0];
1580 DWORD dwTrustErrorMask = ~(DWORD)(CERT_TRUST_IS_NOT_TIME_NESTED);
1581 dwTrustErrorMask &= pSimpleChain->TrustStatus.dwErrorStatus;
1582 if(dwTrustErrorMask) {
1583 if(dwTrustErrorMask & CERT_TRUST_IS_REVOKED)
1584 failf(data, "schannel: CertGetCertificateChain trust error"
1585 " CERT_TRUST_IS_REVOKED");
1586 else if(dwTrustErrorMask & CERT_TRUST_IS_PARTIAL_CHAIN)
1587 failf(data, "schannel: CertGetCertificateChain trust error"
1588 " CERT_TRUST_IS_PARTIAL_CHAIN");
1589 else if(dwTrustErrorMask & CERT_TRUST_IS_UNTRUSTED_ROOT)
1590 failf(data, "schannel: CertGetCertificateChain trust error"
1591 " CERT_TRUST_IS_UNTRUSTED_ROOT");
1592 else if(dwTrustErrorMask & CERT_TRUST_IS_NOT_TIME_VALID)
1593 failf(data, "schannel: CertGetCertificateChain trust error"
1594 " CERT_TRUST_IS_NOT_TIME_VALID");
1595 else
1596 failf(data, "schannel: CertGetCertificateChain error mask: 0x%08x",
1597 dwTrustErrorMask);
1598 result = CURLE_PEER_FAILED_VERIFICATION;
1599 }
1600 }
1601 }
1602
1603 if(result == CURLE_OK) {
1604 if(conn->ssl_config.verifyhost) {
1605 TCHAR cert_hostname_buff[128];
1606 xcharp_u hostname;
1607 xcharp_u cert_hostname;
1608 DWORD len;
1609
1610 cert_hostname.const_tchar_ptr = cert_hostname_buff;
1611 hostname.tchar_ptr = Curl_convert_UTF8_to_tchar(conn_hostname);
1612
1613 /* TODO: Fix this for certificates with multiple alternative names.
1614 Right now we're only asking for the first preferred alternative name.
1615 Instead we'd need to do all via CERT_NAME_SEARCH_ALL_NAMES_FLAG
1616 (if WinCE supports that?) and run this section in a loop for each.
1617 https://msdn.microsoft.com/en-us/library/windows/desktop/aa376086.aspx
1618 curl: (51) schannel: CertGetNameString() certificate hostname
1619 (.google.com) did not match connection (google.com)
1620 */
1621 len = CertGetNameString(pCertContextServer,
1622 CERT_NAME_DNS_TYPE,
1623 0,
1624 NULL,
1625 cert_hostname.tchar_ptr,
1626 128);
1627 if(len > 0 && *cert_hostname.tchar_ptr == '*') {
1628 /* this is a wildcard cert. try matching the last len - 1 chars */
1629 int hostname_len = strlen(conn_hostname);
1630 cert_hostname.tchar_ptr++;
1631 if(_tcsicmp(cert_hostname.const_tchar_ptr,
1632 hostname.const_tchar_ptr + hostname_len - len + 2) != 0)
1633 result = CURLE_PEER_FAILED_VERIFICATION;
1634 }
1635 else if(len == 0 || _tcsicmp(hostname.const_tchar_ptr,
1636 cert_hostname.const_tchar_ptr) != 0) {
1637 result = CURLE_PEER_FAILED_VERIFICATION;
1638 }
1639 if(result == CURLE_PEER_FAILED_VERIFICATION) {
1640 char *_cert_hostname;
1641 _cert_hostname = Curl_convert_tchar_to_UTF8(cert_hostname.tchar_ptr);
1642 failf(data, "schannel: CertGetNameString() certificate hostname "
1643 "(%s) did not match connection (%s)",
1644 _cert_hostname, conn_hostname);
1645 Curl_unicodefree(_cert_hostname);
1646 }
1647 Curl_unicodefree(hostname.tchar_ptr);
1648 }
1649 }
1650
1651 if(pChainContext)
1652 CertFreeCertificateChain(pChainContext);
1653
1654 if(pCertContextServer)
1655 CertFreeCertificateContext(pCertContextServer);
1656
1657 return result;
1658 }
1659 #endif /* _WIN32_WCE */
1660
1661 #endif /* USE_SCHANNEL */
1662