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