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