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