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