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