ReactOS  0.4.14-dev-98-gb0d4763
netconnection.c
Go to the documentation of this file.
1 /*
2  * Wininet - networking layer
3  *
4  * Copyright 2002 TransGaming Technologies Inc.
5  * Copyright 2013 Jacek Caban for CodeWeavers
6  *
7  * David Hammerton
8  *
9  * This library is free software; you can redistribute it and/or
10  * modify it under the terms of the GNU Lesser General Public
11  * License as published by the Free Software Foundation; either
12  * version 2.1 of the License, or (at your option) any later version.
13  *
14  * This library is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17  * Lesser General Public License for more details.
18  *
19  * You should have received a copy of the GNU Lesser General Public
20  * License along with this library; if not, write to the Free Software
21  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
22  */
23 
24 #define NONAMELESSUNION
25 
26 #include "ws2tcpip.h"
27 
28 #include <time.h>
29 #include <stdarg.h>
30 #include <stdlib.h>
31 #include <string.h>
32 #include <stdio.h>
33 #include <assert.h>
34 
35 #include "wine/library.h"
36 #include "windef.h"
37 #include "winbase.h"
38 #include "wininet.h"
39 #include "winerror.h"
40 
41 #include "wine/debug.h"
42 #include "internet.h"
43 
45 
47 {
48  BOOL ret;
49  CERT_CHAIN_PARA chainPara = { sizeof(chainPara), { 0 } };
51  char oid_server_auth[] = szOID_PKIX_KP_SERVER_AUTH;
52  char *server_auth[] = { oid_server_auth };
53  DWORD err = ERROR_SUCCESS, errors;
54 
55  static const DWORD supportedErrors =
61 
62  TRACE("verifying %s\n", debugstr_w(conn->server->name));
63 
65  chainPara.RequestedUsage.Usage.rgpszUsageIdentifier = server_auth;
66  if (!(ret = CertGetCertificateChain(NULL, cert, NULL, store, &chainPara, 0, NULL, &chain))) {
67  TRACE("failed\n");
68  return GetLastError();
69  }
70 
71  errors = chain->TrustStatus.dwErrorStatus;
72 
73  do {
74  /* This seems strange, but that's what tests show */
75  if(errors & CERT_TRUST_IS_PARTIAL_CHAIN) {
76  WARN("ERROR_INTERNET_SEC_CERT_REV_FAILED\n");
78  if(conn->mask_errors)
81  break;
82  }
83 
84  if (chain->TrustStatus.dwErrorStatus & ~supportedErrors) {
85  WARN("error status %x\n", chain->TrustStatus.dwErrorStatus & ~supportedErrors);
87  errors &= supportedErrors;
88  if(!conn->mask_errors)
89  break;
90  WARN("unknown error flags\n");
91  }
92 
93  if(errors & CERT_TRUST_IS_NOT_TIME_VALID) {
94  WARN("CERT_TRUST_IS_NOT_TIME_VALID\n");
97  if(!conn->mask_errors)
98  break;
100  }
101  errors &= ~CERT_TRUST_IS_NOT_TIME_VALID;
102  }
103 
104  if(errors & CERT_TRUST_IS_UNTRUSTED_ROOT) {
105  WARN("CERT_TRUST_IS_UNTRUSTED_ROOT\n");
108  if(!conn->mask_errors)
109  break;
111  }
112  errors &= ~CERT_TRUST_IS_UNTRUSTED_ROOT;
113  }
114 
115  if(errors & CERT_TRUST_IS_PARTIAL_CHAIN) {
116  WARN("CERT_TRUST_IS_PARTIAL_CHAIN\n");
119  if(!conn->mask_errors)
120  break;
122  }
123  errors &= ~CERT_TRUST_IS_PARTIAL_CHAIN;
124  }
125 
126  if(errors & CERT_TRUST_IS_NOT_SIGNATURE_VALID) {
127  WARN("CERT_TRUST_IS_NOT_SIGNATURE_VALID\n");
130  if(!conn->mask_errors)
131  break;
133  }
135  }
136 
137  if(errors & CERT_TRUST_IS_NOT_VALID_FOR_USAGE) {
138  WARN("CERT_TRUST_IS_NOT_VALID_FOR_USAGE\n");
141  if(!conn->mask_errors)
142  break;
143  WARN("CERT_TRUST_IS_NOT_VALID_FOR_USAGE, unknown error flags\n");
144  }
146  }
147 
150  err = ERROR_SUCCESS;
151  }
152  }while(0);
153 
154  if(!err || conn->mask_errors) {
155  CERT_CHAIN_POLICY_PARA policyPara;
156  SSL_EXTRA_CERT_CHAIN_POLICY_PARA sslExtraPolicyPara;
157  CERT_CHAIN_POLICY_STATUS policyStatus;
158  CERT_CHAIN_CONTEXT chainCopy;
159 
160  /* Clear chain->TrustStatus.dwErrorStatus so
161  * CertVerifyCertificateChainPolicy will verify additional checks
162  * rather than stopping with an existing, ignored error.
163  */
164  memcpy(&chainCopy, chain, sizeof(chainCopy));
165  chainCopy.TrustStatus.dwErrorStatus = 0;
166  sslExtraPolicyPara.u.cbSize = sizeof(sslExtraPolicyPara);
167  sslExtraPolicyPara.dwAuthType = AUTHTYPE_SERVER;
168  sslExtraPolicyPara.pwszServerName = conn->server->name;
169  sslExtraPolicyPara.fdwChecks = conn->security_flags;
170  policyPara.cbSize = sizeof(policyPara);
171  policyPara.dwFlags = 0;
172  policyPara.pvExtraPolicyPara = &sslExtraPolicyPara;
174  &chainCopy, &policyPara, &policyStatus);
175  /* Any error in the policy status indicates that the
176  * policy couldn't be verified.
177  */
178  if(ret) {
179  if(policyStatus.dwError == CERT_E_CN_NO_MATCH) {
180  WARN("CERT_E_CN_NO_MATCH\n");
181  if(conn->mask_errors)
184  }else if(policyStatus.dwError) {
185  WARN("policyStatus.dwError %x\n", policyStatus.dwError);
186  if(conn->mask_errors)
187  WARN("unknown error flags for policy status %x\n", policyStatus.dwError);
189  }
190  }else {
191  err = GetLastError();
192  }
193  }
194 
195  if(err) {
196  WARN("failed %u\n", err);
198  if(conn->server->cert_chain) {
200  conn->server->cert_chain = NULL;
201  }
202  if(conn->mask_errors)
204  return err;
205  }
206 
207  /* FIXME: Reuse cached chain */
208  if(conn->server->cert_chain)
210  else
211  conn->server->cert_chain = chain;
212  return ERROR_SUCCESS;
213 }
214 
217 
220  0, 0, &init_sechandle_cs,
223  0, 0, { (DWORD_PTR)(__FILE__ ": init_sechandle_cs") }
224 };
225 static CRITICAL_SECTION init_sechandle_cs = { &init_sechandle_cs_debug, -1, 0, 0, 0, 0 };
226 
228 {
230 
232 
236 
238  NULL, NULL, &cred_handle, NULL);
239  if(res == SEC_E_OK) {
246  }
247  }
248 
250  }
251 
253 
254  if(res != SEC_E_OK) {
255  WARN("Failed: %08x\n", res);
256  return FALSE;
257  }
258 
259  return TRUE;
260 }
261 
263 
264 static BOOL WINAPI winsock_startup(INIT_ONCE *once, void *param, void **context)
265 {
266  WSADATA wsa_data;
267  DWORD res;
268 
269  res = WSAStartup(MAKEWORD(2,2), &wsa_data);
270  if(res == ERROR_SUCCESS)
272  else
273  ERR("WSAStartup failed: %u\n", res);
274  return TRUE;
275 }
276 
277 void init_winsock(void)
278 {
279  static INIT_ONCE init_once = INIT_ONCE_STATIC_INIT;
281 }
282 
283 static void set_socket_blocking(netconn_t *conn, BOOL is_blocking)
284 {
285  if(conn->is_blocking != is_blocking) {
286  ULONG arg = !is_blocking;
287  ioctlsocket(conn->socket, FIONBIO, &arg);
288  }
289  conn->is_blocking = is_blocking;
290 }
291 
293 {
294  int result;
295  ULONG flag;
296  DWORD res;
297 
298  init_winsock();
299 
300  assert(server->addr_len);
301  result = netconn->socket = socket(server->addr.ss_family, SOCK_STREAM, 0);
302  if(result != -1) {
303  set_socket_blocking(netconn, FALSE);
304  result = connect(netconn->socket, (struct sockaddr*)&server->addr, server->addr_len);
305  if(result == -1)
306  {
307  res = WSAGetLastError();
308  if (res == WSAEINPROGRESS || res == WSAEWOULDBLOCK) {
309  FD_SET set;
310  int res;
311  socklen_t len = sizeof(res);
312  TIMEVAL timeout_timeval = {0, timeout*1000};
313 
314  FD_ZERO(&set);
315  FD_SET(netconn->socket, &set);
316  res = select(netconn->socket+1, NULL, &set, NULL, &timeout_timeval);
317  if(!res || res == SOCKET_ERROR) {
318  closesocket(netconn->socket);
319  netconn->socket = -1;
321  }
322  if (!getsockopt(netconn->socket, SOL_SOCKET, SO_ERROR, (void *)&res, &len) && !res)
323  result = 0;
324  }
325  }
326  if(result == -1)
327  {
328  closesocket(netconn->socket);
329  netconn->socket = -1;
330  }
331  }
332  if(result == -1)
334 
335  flag = 1;
336  result = setsockopt(netconn->socket, IPPROTO_TCP, TCP_NODELAY, (void*)&flag, sizeof(flag));
337  if(result < 0)
338  WARN("setsockopt(TCP_NODELAY) failed\n");
339 
340  return ERROR_SUCCESS;
341 }
342 
343 DWORD create_netconn(BOOL useSSL, server_t *server, DWORD security_flags, BOOL mask_errors, DWORD timeout, netconn_t **ret)
344 {
345  netconn_t *netconn;
346  int result;
347 
348  netconn = heap_alloc_zero(sizeof(*netconn));
349  if(!netconn)
350  return ERROR_OUTOFMEMORY;
351 
352  netconn->socket = -1;
353  netconn->security_flags = security_flags | server->security_flags;
354  netconn->mask_errors = mask_errors;
355  list_init(&netconn->pool_entry);
356  SecInvalidateHandle(&netconn->ssl_ctx);
357 
359  if (result != ERROR_SUCCESS) {
360  heap_free(netconn);
361  return result;
362  }
363 
365  netconn->server = server;
366  *ret = netconn;
367  return result;
368 }
369 
371 {
372  return netconn && netconn->socket != -1;
373 }
374 
375 void close_netconn(netconn_t *netconn)
376 {
377  closesocket(netconn->socket);
378  netconn->socket = -1;
379 }
380 
381 void free_netconn(netconn_t *netconn)
382 {
383  server_release(netconn->server);
384 
385  if (netconn->secure) {
386  heap_free(netconn->peek_msg_mem);
387  netconn->peek_msg_mem = NULL;
388  netconn->peek_msg = NULL;
389  netconn->peek_len = 0;
390  heap_free(netconn->ssl_buf);
391  netconn->ssl_buf = NULL;
392  heap_free(netconn->extra_buf);
393  netconn->extra_buf = NULL;
394  netconn->extra_len = 0;
395  if (SecIsValidHandle(&netconn->ssl_ctx))
396  DeleteSecurityContext(&netconn->ssl_ctx);
397  }
398 
399  close_netconn(netconn);
400  heap_free(netconn);
401 }
402 
403 void NETCON_unload(void)
404 {
410  if(winsock_loaded)
411  WSACleanup();
412 }
413 
414 int sock_send(int fd, const void *msg, size_t len, int flags)
415 {
416  int ret;
417  do
418  {
419  ret = send(fd, msg, len, flags);
420  }
421  while(ret == -1 && WSAGetLastError() == WSAEINTR);
422  return ret;
423 }
424 
425 int sock_recv(int fd, void *msg, size_t len, int flags)
426 {
427  int ret;
428  do
429  {
430  ret = recv(fd, msg, len, flags);
431  }
432  while(ret == -1 && WSAGetLastError() == WSAEINTR);
433  return ret;
434 }
435 
436 static DWORD netcon_secure_connect_setup(netconn_t *connection, BOOL compat_mode)
437 {
438  SecBuffer out_buf = {0, SECBUFFER_TOKEN, NULL}, in_bufs[2] = {{0, SECBUFFER_TOKEN}, {0, SECBUFFER_EMPTY}};
439  SecBufferDesc out_desc = {SECBUFFER_VERSION, 1, &out_buf}, in_desc = {SECBUFFER_VERSION, 2, in_bufs};
440  SecHandle *cred = &cred_handle;
441  BYTE *read_buf;
442  SIZE_T read_buf_size = 2048;
443  ULONG attrs = 0;
444  CtxtHandle ctx;
445  SSIZE_T size;
446  int bits;
447  const CERT_CONTEXT *cert;
450 
453 
454  if(!ensure_cred_handle())
456 
457  if(compat_mode) {
460  cred = &compat_cred_handle;
461  }
462 
463  read_buf = heap_alloc(read_buf_size);
464  if(!read_buf)
465  return ERROR_OUTOFMEMORY;
466 
467  status = InitializeSecurityContextW(cred, NULL, connection->server->name, isc_req_flags, 0, 0, NULL, 0,
468  &ctx, &out_desc, &attrs, NULL);
469 
470  assert(status != SEC_E_OK);
471 
472  set_socket_blocking(connection, TRUE);
473 
475  if(out_buf.cbBuffer) {
477 
478  TRACE("sending %u bytes\n", out_buf.cbBuffer);
479 
480  size = sock_send(connection->socket, out_buf.pvBuffer, out_buf.cbBuffer, 0);
481  if(size != out_buf.cbBuffer) {
482  ERR("send failed\n");
484  break;
485  }
486 
487  FreeContextBuffer(out_buf.pvBuffer);
488  out_buf.pvBuffer = NULL;
489  out_buf.cbBuffer = 0;
490  }
491 
493  assert(in_bufs[1].cbBuffer < read_buf_size);
494 
495  memmove(read_buf, (BYTE*)in_bufs[0].pvBuffer+in_bufs[0].cbBuffer-in_bufs[1].cbBuffer, in_bufs[1].cbBuffer);
496  in_bufs[0].cbBuffer = in_bufs[1].cbBuffer;
497 
498  in_bufs[1].BufferType = SECBUFFER_EMPTY;
499  in_bufs[1].cbBuffer = 0;
500  in_bufs[1].pvBuffer = NULL;
501  }
502 
503  assert(in_bufs[0].BufferType == SECBUFFER_TOKEN);
504  assert(in_bufs[1].BufferType == SECBUFFER_EMPTY);
505 
506  if(in_bufs[0].cbBuffer + 1024 > read_buf_size) {
507  BYTE *new_read_buf;
508 
509  new_read_buf = heap_realloc(read_buf, read_buf_size + 1024);
510  if(!new_read_buf) {
512  break;
513  }
514 
515  in_bufs[0].pvBuffer = read_buf = new_read_buf;
516  read_buf_size += 1024;
517  }
518 
519  size = sock_recv(connection->socket, read_buf+in_bufs[0].cbBuffer, read_buf_size-in_bufs[0].cbBuffer, 0);
520  if(size < 1) {
521  WARN("recv error\n");
523  break;
524  }
525 
526  TRACE("recv %lu bytes\n", size);
527 
528  in_bufs[0].cbBuffer += size;
529  in_bufs[0].pvBuffer = read_buf;
530  status = InitializeSecurityContextW(cred, &ctx, connection->server->name, isc_req_flags, 0, 0, &in_desc,
531  0, NULL, &out_desc, &attrs, NULL);
532  TRACE("InitializeSecurityContext ret %08x\n", status);
533 
534  if(status == SEC_E_OK) {
535  if(SecIsValidHandle(&connection->ssl_ctx))
536  DeleteSecurityContext(&connection->ssl_ctx);
537  connection->ssl_ctx = ctx;
538 
539  if(in_bufs[1].BufferType == SECBUFFER_EXTRA)
540  FIXME("SECBUFFER_EXTRA not supported\n");
541 
543  if(status != SEC_E_OK) {
544  WARN("Could not get sizes\n");
545  break;
546  }
547 
549  if(status == SEC_E_OK) {
550  res = netconn_verify_cert(connection, cert, cert->hCertStore);
552  if(res != ERROR_SUCCESS) {
553  WARN("cert verify failed: %u\n", res);
554  break;
555  }
556  }else {
557  WARN("Could not get cert\n");
558  break;
559  }
560 
561  connection->ssl_buf = heap_alloc(connection->ssl_sizes.cbHeader + connection->ssl_sizes.cbMaximumMessage
562  + connection->ssl_sizes.cbTrailer);
563  if(!connection->ssl_buf) {
564  res = GetLastError();
565  break;
566  }
567  }
568  }
569 
571 
572  if(status != SEC_E_OK || res != ERROR_SUCCESS) {
573  WARN("Failed to establish SSL connection: %08x (%u)\n", status, res);
574  heap_free(connection->ssl_buf);
575  connection->ssl_buf = NULL;
577  }
578 
579  TRACE("established SSL connection\n");
580  connection->secure = TRUE;
581  connection->security_flags |= SECURITY_FLAG_SECURE;
582 
583  bits = NETCON_GetCipherStrength(connection);
584  if (bits >= 128)
586  else if (bits >= 56)
588  else
590 
591  if(connection->mask_errors)
592  connection->server->security_flags = connection->security_flags;
593  return ERROR_SUCCESS;
594 }
595 
596 /******************************************************************************
597  * NETCON_secure_connect
598  * Initiates a secure connection over an existing plaintext connection.
599  */
601 {
602  DWORD res;
603 
604  /* can't connect if we are already connected */
605  if(connection->secure) {
606  ERR("already connected\n");
608  }
609 
610  if(server != connection->server) {
611  server_release(connection->server);
613  connection->server = server;
614  }
615 
616  /* connect with given TLS options */
617  res = netcon_secure_connect_setup(connection, FALSE);
618  if (res == ERROR_SUCCESS)
619  return res;
620 
621  /* FIXME: when got version alert and FIN from server */
622  /* fallback to connect without TLSv1.1/TLSv1.2 */
624  {
625  closesocket(connection->socket);
626  res = create_netconn_socket(connection->server, connection, 500);
627  if (res != ERROR_SUCCESS)
628  return res;
629  res = netcon_secure_connect_setup(connection, TRUE);
630  }
631  return res;
632 }
633 
634 static BOOL send_ssl_chunk(netconn_t *conn, const void *msg, size_t size)
635 {
636  SecBuffer bufs[4] = {
638  {size, SECBUFFER_DATA, conn->ssl_buf+conn->ssl_sizes.cbHeader},
640  {0, SECBUFFER_EMPTY, NULL}
641  };
642  SecBufferDesc buf_desc = {SECBUFFER_VERSION, sizeof(bufs)/sizeof(*bufs), bufs};
644 
645  memcpy(bufs[1].pvBuffer, msg, size);
646  res = EncryptMessage(&conn->ssl_ctx, 0, &buf_desc, 0);
647  if(res != SEC_E_OK) {
648  WARN("EncryptMessage failed\n");
649  return FALSE;
650  }
651 
652  if(sock_send(conn->socket, conn->ssl_buf, bufs[0].cbBuffer+bufs[1].cbBuffer+bufs[2].cbBuffer, 0) < 1) {
653  WARN("send failed\n");
654  return FALSE;
655  }
656 
657  return TRUE;
658 }
659 
660 /******************************************************************************
661  * NETCON_send
662  * Basically calls 'send()' unless we should use SSL
663  * number of chars send is put in *sent
664  */
665 DWORD NETCON_send(netconn_t *connection, const void *msg, size_t len, int flags,
666  int *sent /* out */)
667 {
668  /* send is always blocking. */
669  set_socket_blocking(connection, TRUE);
670 
671  if(!connection->secure)
672  {
673  *sent = sock_send(connection->socket, msg, len, flags);
674  return *sent == -1 ? WSAGetLastError() : ERROR_SUCCESS;
675  }
676  else
677  {
678  const BYTE *ptr = msg;
679  size_t chunk_size;
680 
681  *sent = 0;
682 
683  while(len) {
684  chunk_size = min(len, connection->ssl_sizes.cbMaximumMessage);
685  if(!send_ssl_chunk(connection, ptr, chunk_size))
687 
688  *sent += chunk_size;
689  ptr += chunk_size;
690  len -= chunk_size;
691  }
692 
693  return ERROR_SUCCESS;
694  }
695 }
696 
697 static BOOL read_ssl_chunk(netconn_t *conn, void *buf, SIZE_T buf_size, BOOL blocking, SIZE_T *ret_size, BOOL *eof)
698 {
699  const SIZE_T ssl_buf_size = conn->ssl_sizes.cbHeader+conn->ssl_sizes.cbMaximumMessage+conn->ssl_sizes.cbTrailer;
700  SecBuffer bufs[4];
701  SecBufferDesc buf_desc = {SECBUFFER_VERSION, sizeof(bufs)/sizeof(*bufs), bufs};
702  SSIZE_T size, buf_len = 0;
703  int i;
705 
706  assert(conn->extra_len < ssl_buf_size);
707 
708  if(conn->extra_len) {
709  memcpy(conn->ssl_buf, conn->extra_buf, conn->extra_len);
710  buf_len = conn->extra_len;
711  conn->extra_len = 0;
712  heap_free(conn->extra_buf);
713  conn->extra_buf = NULL;
714  }
715 
716  set_socket_blocking(conn, blocking && !buf_len);
717  size = sock_recv(conn->socket, conn->ssl_buf+buf_len, ssl_buf_size-buf_len, 0);
718  if(size < 0) {
719  if(!buf_len) {
721  TRACE("would block\n");
722  return WSAEWOULDBLOCK;
723  }
724  WARN("recv failed\n");
726  }
727  }else {
728  buf_len += size;
729  }
730 
731  if(!buf_len) {
732  TRACE("EOF\n");
733  *eof = TRUE;
734  *ret_size = 0;
735  return ERROR_SUCCESS;
736  }
737 
738  *eof = FALSE;
739 
740  do {
741  memset(bufs, 0, sizeof(bufs));
742  bufs[0].BufferType = SECBUFFER_DATA;
743  bufs[0].cbBuffer = buf_len;
744  bufs[0].pvBuffer = conn->ssl_buf;
745 
746  res = DecryptMessage(&conn->ssl_ctx, &buf_desc, 0, NULL);
747  switch(res) {
748  case SEC_E_OK:
749  break;
751  TRACE("context expired\n");
752  *eof = TRUE;
753  return ERROR_SUCCESS;
755  assert(buf_len < ssl_buf_size);
756 
757  set_socket_blocking(conn, blocking);
758  size = sock_recv(conn->socket, conn->ssl_buf+buf_len, ssl_buf_size-buf_len, 0);
759  if(size < 1) {
760  if(size < 0 && WSAGetLastError() == WSAEWOULDBLOCK) {
761  TRACE("would block\n");
762 
763  /* FIXME: Optimize extra_buf usage. */
764  conn->extra_buf = heap_alloc(buf_len);
765  if(!conn->extra_buf)
767 
768  conn->extra_len = buf_len;
769  memcpy(conn->extra_buf, conn->ssl_buf, conn->extra_len);
770  return WSAEWOULDBLOCK;
771  }
772 
774  }
775 
776  buf_len += size;
777  continue;
778  default:
779  WARN("failed: %08x\n", res);
781  }
782  } while(res != SEC_E_OK);
783 
784  for(i=0; i < sizeof(bufs)/sizeof(*bufs); i++) {
785  if(bufs[i].BufferType == SECBUFFER_DATA) {
786  size = min(buf_size, bufs[i].cbBuffer);
787  memcpy(buf, bufs[i].pvBuffer, size);
788  if(size < bufs[i].cbBuffer) {
789  assert(!conn->peek_len);
790  conn->peek_msg_mem = conn->peek_msg = heap_alloc(bufs[i].cbBuffer - size);
791  if(!conn->peek_msg)
793  conn->peek_len = bufs[i].cbBuffer-size;
794  memcpy(conn->peek_msg, (char*)bufs[i].pvBuffer+size, conn->peek_len);
795  }
796 
797  *ret_size = size;
798  }
799  }
800 
801  for(i=0; i < sizeof(bufs)/sizeof(*bufs); i++) {
802  if(bufs[i].BufferType == SECBUFFER_EXTRA) {
803  conn->extra_buf = heap_alloc(bufs[i].cbBuffer);
804  if(!conn->extra_buf)
806 
807  conn->extra_len = bufs[i].cbBuffer;
808  memcpy(conn->extra_buf, bufs[i].pvBuffer, conn->extra_len);
809  }
810  }
811 
812  return ERROR_SUCCESS;
813 }
814 
815 /******************************************************************************
816  * NETCON_recv
817  * Basically calls 'recv()' unless we should use SSL
818  * number of chars received is put in *recvd
819  */
820 DWORD NETCON_recv(netconn_t *connection, void *buf, size_t len, BOOL blocking, int *recvd)
821 {
822  *recvd = 0;
823  if (!len)
824  return ERROR_SUCCESS;
825 
826  if (!connection->secure)
827  {
828  set_socket_blocking(connection, blocking);
829  *recvd = sock_recv(connection->socket, buf, len, 0);
830  return *recvd == -1 ? WSAGetLastError() : ERROR_SUCCESS;
831  }
832  else
833  {
834  SIZE_T size = 0;
835  BOOL eof;
836  DWORD res;
837 
838  if(connection->peek_msg) {
839  size = min(len, connection->peek_len);
840  memcpy(buf, connection->peek_msg, size);
841  connection->peek_len -= size;
842  connection->peek_msg += size;
843 
844  if(!connection->peek_len) {
845  heap_free(connection->peek_msg_mem);
846  connection->peek_msg_mem = connection->peek_msg = NULL;
847  }
848 
849  *recvd = size;
850  return ERROR_SUCCESS;
851  }
852 
853  do {
854  res = read_ssl_chunk(connection, (BYTE*)buf, len, blocking, &size, &eof);
855  if(res != ERROR_SUCCESS) {
856  if(res == WSAEWOULDBLOCK) {
857  if(size)
858  res = ERROR_SUCCESS;
859  }else {
860  WARN("read_ssl_chunk failed\n");
861  }
862  break;
863  }
864  }while(!size && !eof);
865 
866  TRACE("received %ld bytes\n", size);
867  *recvd = size;
868  return res;
869  }
870 }
871 
873 {
874  int len;
875  char b;
876 
877  set_socket_blocking(netconn, FALSE);
878  len = sock_recv(netconn->socket, &b, 1, MSG_PEEK);
879 
880  return len == 1 || (len == -1 && WSAGetLastError() == WSAEWOULDBLOCK);
881 }
882 
884 {
885  const CERT_CONTEXT *ret;
887 
889  return res == SEC_E_OK ? ret : NULL;
890 }
891 
893 {
896 
897  if (!connection->secure)
898  return 0;
899 
900  res = QueryContextAttributesW(&connection->ssl_ctx, SECPKG_ATTR_CONNECTION_INFO, (void*)&conn_info);
901  if(res != SEC_E_OK)
902  WARN("QueryContextAttributesW failed: %08x\n", res);
903  return res == SEC_E_OK ? conn_info.dwCipherStrength : 0;
904 }
905 
907 {
908  int result;
909 
910  result = setsockopt(connection->socket, SOL_SOCKET,
911  send ? SO_SNDTIMEO : SO_RCVTIMEO, (void*)&value,
912  sizeof(value));
913  if (result == -1)
914  {
915  WARN("setsockopt failed\n");
916  return WSAGetLastError();
917  }
918  return ERROR_SUCCESS;
919 }
#define ISC_REQ_SEQUENCE_DETECT
Definition: sspi.h:351
BOOL WINAPI CertGetCertificateChain(HCERTCHAINENGINE hChainEngine, PCCERT_CONTEXT pCertContext, LPFILETIME pTime, HCERTSTORE hAdditionalStore, PCERT_CHAIN_PARA pChainPara, DWORD dwFlags, LPVOID pvReserved, PCCERT_CHAIN_CONTEXT *ppChainContext)
Definition: chain.c:2879
Definition: winsock.h:66
size_t extra_len
#define SOCKET_ERROR
Definition: winsock.h:333
#define ERROR_INTERNET_SEC_CERT_CN_INVALID
Definition: wininet.h:2026
CERT_ENHKEY_USAGE Usage
Definition: wincrypt.h:1048
#define SECPKG_ATTR_SUPPORTED_PROTOCOLS
Definition: schannel.h:74
#define ERROR_INTERNET_CONNECTION_ABORTED
Definition: wininet.h:2019
#define SECURITY_FLAG_STRENGTH_MEDIUM
Definition: winhttp.h:287
#define memmove(s1, s2, n)
Definition: mkisofs.h:881
CtxtHandle ssl_ctx
#define TRUE
Definition: types.h:120
static DWORD netconn_verify_cert(netconn_t *conn, PCCERT_CONTEXT cert, HCERTSTORE store)
Definition: netconnection.c:46
#define SECURITY_FLAG_IGNORE_UNKNOWN_CA
Definition: winhttp.h:281
#define SECURITY_FLAG_STRENGTH_STRONG
Definition: winhttp.h:288
#define SECPKG_CRED_OUTBOUND
Definition: sspi.h:277
void close_netconn(netconn_t *netconn)
static rfbScreenInfoPtr server
Definition: vnc.c:74
SOCKET WSAAPI socket(IN INT af, IN INT type, IN INT protocol)
Definition: socklife.c:143
#define CERT_TRUST_IS_NOT_TIME_VALID
Definition: wincrypt.h:870
static BOOL read_ssl_chunk(netconn_t *conn, void *buf, SIZE_T buf_size, BOOL blocking, SIZE_T *ret_size, BOOL *eof)
LPCVOID NETCON_GetCert(netconn_t *connection)
#define ERROR_SUCCESS
Definition: deptool.c:10
#define DWORD_PTR
Definition: treelist.c:76
#define SECBUFFER_STREAM_HEADER
Definition: sspi.h:152
SECURITY_STATUS WINAPI AcquireCredentialsHandleW(SEC_WCHAR *pszPrincipal, SEC_WCHAR *pszPackage, ULONG fCredentialsUse, PLUID pvLogonID, PVOID pAuthData, SEC_GET_KEY_FN pGetKeyFn, PVOID pvGetKeyArgument, PCredHandle phCredential, PTimeStamp ptsExpiry)
Definition: wrapper.c:105
const GLenum * bufs
Definition: glext.h:6026
static BOOL WINAPI winsock_startup(INIT_ONCE *once, void *param, void **context)
Definition: http.c:6587
#define MAKEWORD(a, b)
Definition: typedefs.h:247
GLenum GLuint GLenum GLsizei const GLchar * buf
Definition: glext.h:7751
SECURITY_STATUS WINAPI FreeContextBuffer(PVOID pv)
Definition: sspi.c:699
#define ERROR_INTERNET_SEC_CERT_REV_FAILED
Definition: wininet.h:2044
#define SEC_I_CONTEXT_EXPIRED
Definition: winerror.h:2933
#define SecIsValidHandle(x)
Definition: sspi.h:63
BOOL WINAPI CertFreeCertificateContext(PCCERT_CONTEXT pCertContext)
Definition: cert.c:371
#define WARN(fmt,...)
Definition: debug.h:111
int sock_recv(int fd, void *msg, size_t len, int flags)
#define INIT_ONCE_STATIC_INIT
Definition: winbase.h:593
#define SECPKG_ATTR_REMOTE_CERT_CONTEXT
Definition: schannel.h:69
INT WSAAPI WSACleanup(VOID)
Definition: startup.c:60
#define WSAEWOULDBLOCK
Definition: winerror.h:1948
DWORD NETCON_send(netconn_t *connection, const void *msg, size_t len, int flags, int *sent)
const CERT_CHAIN_CONTEXT * cert_chain
Definition: internet.h:51
static SecHandle cred_handle
CERT_USAGE_MATCH RequestedUsage
Definition: wincrypt.h:1070
#define ERROR_NOT_ENOUGH_MEMORY
Definition: dderror.h:7
#define SECBUFFER_DATA
Definition: sspi.h:146
#define assert(x)
Definition: debug.h:53
DWORD WINAPI GetLastError(VOID)
Definition: except.c:1059
LONG_PTR SSIZE_T
Definition: basetsd.h:183
static int fd
Definition: io.c:51
SECURITY_STATUS WINAPI FreeCredentialsHandle(PCredHandle phCredential)
Definition: wrapper.c:151
Definition: dhcpd.h:245
char * ssl_buf
size_t peek_len
#define szOID_PKIX_KP_SERVER_AUTH
Definition: wincrypt.h:3294
#define SOL_SOCKET
Definition: winsock.h:398
void WINAPI EnterCriticalSection(LPCRITICAL_SECTION)
#define FD_ZERO(set)
Definition: winsock.h:96
#define FD_SET(fd, set)
Definition: winsock.h:89
static BOOL winsock_loaded
void server_release(server_t *server)
Definition: http.c:229
INT WSAAPI connect(IN SOCKET s, IN CONST struct sockaddr *name, IN INT namelen)
Definition: sockctrl.c:23
GLenum GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const GLvoid * bits
Definition: glext.h:10929
#define WSAEINPROGRESS
Definition: winerror.h:1949
VOID WINAPI CertFreeCertificateChain(PCCERT_CHAIN_CONTEXT pChainContext)
Definition: chain.c:2960
static void * heap_realloc(void *mem, size_t len)
Definition: appwiz.h:70
#define CERT_E_CN_NO_MATCH
Definition: winerror.h:3131
static void * heap_alloc(size_t len)
Definition: appwiz.h:65
#define SECBUFFER_EXTRA
Definition: sspi.h:150
unsigned read_buf(z_streamp strm, Bytef *buf, unsigned size)
Definition: deflate.c:1167
#define ERROR_INTERNET_CANNOT_CONNECT
Definition: wininet.h:2018
BOOL WINAPI CertVerifyCertificateChainPolicy(LPCSTR szPolicyOID, PCCERT_CHAIN_CONTEXT pChainContext, PCERT_CHAIN_POLICY_PARA pPolicyPara, PCERT_CHAIN_POLICY_STATUS pPolicyStatus)
Definition: chain.c:3716
void init_winsock(void)
#define TCP_NODELAY
Definition: tcpdef.h:117
#define ISC_REQ_MANUAL_CRED_VALIDATION
Definition: sspi.h:367
#define SECURITY_FLAG_IGNORE_REVOCATION
Definition: wininet.h:829
#define SecInvalidateHandle(x)
Definition: sspi.h:58
static BOOL cred_handle_initialized
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
#define CERT_CHAIN_POLICY_SSL
Definition: wincrypt.h:965
SECURITY_STATUS WINAPI QueryCredentialsAttributesA(PCredHandle phCredential, ULONG ulAttribute, void *pBuffer)
Definition: wrapper.c:177
#define E_OUTOFMEMORY
Definition: ddrawi.h:100
#define closesocket
Definition: main.c:39
unsigned int BOOL
Definition: ntddk_ex.h:94
struct list pool_entry
Definition: internet.h:87
INT WSAAPI select(IN INT s, IN OUT LPFD_SET readfds, IN OUT LPFD_SET writefds, IN OUT LPFD_SET exceptfds, IN CONST struct timeval *timeout)
Definition: select.c:41
DWORD create_netconn(BOOL useSSL, server_t *server, DWORD security_flags, BOOL mask_errors, DWORD timeout, netconn_t **ret)
char * extra_buf
#define debugstr_w
Definition: kernel32.h:32
#define FIXME(fmt,...)
Definition: debug.h:110
void NETCON_unload(void)
INT WSAAPI setsockopt(IN SOCKET s, IN INT level, IN INT optname, IN CONST CHAR FAR *optval, IN INT optlen)
Definition: sockctrl.c:421
static PVOID ptr
Definition: dispmode.c:27
#define SCHANNEL_CRED_VERSION
Definition: schannel.h:22
DWORD NETCON_secure_connect(netconn_t *connection, server_t *server)
INT WINAPI WSAStartup(IN WORD wVersionRequested, OUT LPWSADATA lpWSAData)
Definition: startup.c:113
BOOL is_valid_netconn(netconn_t *netconn)
smooth NULL
Definition: ftsmooth.c:416
#define ERROR_INTERNET_SEC_CERT_ERRORS
Definition: wininet.h:2042
DWORD grbitEnabledProtocols
Definition: schannel.h:96
#define SECBUFFER_EMPTY
Definition: sspi.h:145
#define SO_ERROR
Definition: winsock.h:194
struct sock * chain
Definition: tcpcore.h:1164
int sock_send(int fd, const void *msg, size_t len, int flags)
#define SEC_I_CONTINUE_NEEDED
Definition: winerror.h:2927
static CRITICAL_SECTION init_sechandle_cs
#define ioctlsocket
Definition: main.c:40
static BYTE cert[]
Definition: msg.c:1437
DWORD security_flags
Definition: internet.h:82
CERT_TRUST_STATUS TrustStatus
Definition: wincrypt.h:939
#define b
Definition: ke_i.h:79
LONG SECURITY_STATUS
Definition: sspi.h:34
#define _SECURITY_ERROR_FLAGS_MASK
Definition: internet.h:477
static DWORD netcon_secure_connect_setup(netconn_t *connection, BOOL compat_mode)
static SecHandle compat_cred_handle
BOOL NTAPI InitOnceExecuteOnce(INIT_ONCE *once, PINIT_ONCE_FN func, void *param, void **context)
GLboolean GLboolean GLboolean b
Definition: glext.h:6204
#define SO_RCVTIMEO
Definition: winsock.h:193
#define TRACE(s)
Definition: solgame.cpp:4
INT WSAAPI WSAGetLastError(VOID)
Definition: dllmain.c:112
GLsizeiptr size
Definition: glext.h:5919
SECURITY_STATUS WINAPI InitializeSecurityContextW(PCredHandle phCredential, PCtxtHandle phContext, SEC_WCHAR *pszTargetName, ULONG fContextReq, ULONG Reserved1, ULONG TargetDataRep, PSecBufferDesc pInput, ULONG Reserved2, PCtxtHandle phNewContext, PSecBufferDesc pOutput, ULONG *pfContextAttr, PTimeStamp ptsExpiry)
Definition: wrapper.c:301
static BOOL ensure_cred_handle(void)
BOOL is_blocking
Definition: internet.h:72
__wchar_t WCHAR
Definition: xmlstorage.h:180
void WINAPI DeleteCriticalSection(PCRITICAL_SECTION)
DWORD NETCON_recv(netconn_t *connection, void *buf, size_t len, BOOL blocking, int *recvd)
INT WSAAPI send(IN SOCKET s, IN CONST CHAR FAR *buf, IN INT len, IN INT flags)
Definition: send.c:23
GLfloat param
Definition: glext.h:5796
#define WINAPI
Definition: msvc.h:8
DWORD security_flags
Definition: internet.h:50
static UINT set(struct ID3DXConstantTableImpl *table, IDirect3DDevice9 *device, struct ctab_constant *constant, const void **indata, D3DXPARAMETER_TYPE intype, UINT *size, UINT incol, D3DXPARAMETER_CLASS inclass, UINT index, BOOL is_pointer)
Definition: shader.c:1095
unsigned long DWORD
Definition: ntddk_ex.h:95
int socklen_t
Definition: tcp.c:35
char * peek_msg
#define _SECURITY_FLAG_CERT_INVALID_CN
Definition: internet.h:474
#define CERT_TRUST_IS_NOT_SIGNATURE_VALID
Definition: wincrypt.h:873
#define ISC_REQ_USE_SESSION_KEY
Definition: sspi.h:353
GLbitfield flags
Definition: glext.h:7161
#define SECPKG_ATTR_STREAM_SIZES
Definition: sspi.h:511
#define SECBUFFER_STREAM_TRAILER
Definition: sspi.h:151
int ret
#define ISC_REQ_ALLOCATE_MEMORY
Definition: sspi.h:356
Definition: msg.h:34
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean flag
Definition: glfuncs.h:52
static CRITICAL_SECTION_DEBUG init_sechandle_cs_debug
#define SECBUFFER_TOKEN
Definition: sspi.h:147
#define SECPKG_ATTR_CONNECTION_INFO
Definition: schannel.h:76
#define memcpy(s1, s2, n)
Definition: mkisofs.h:878
GLenum GLsizei len
Definition: glext.h:6722
void server_addref(server_t *server)
Definition: http.c:224
unsigned char BYTE
Definition: mem.h:68
WCHAR * name
Definition: internet.h:37
WINE_DEFAULT_DEBUG_CHANNEL(wininet)
#define err(...)
LIST_ENTRY ProcessLocksList
Definition: winbase.h:855
#define SEC_E_OK
Definition: winerror.h:2356
SECURITY_STATUS WINAPI QueryContextAttributesW(PCtxtHandle phContext, ULONG ulAttribute, void *pBuffer)
Definition: wrapper.c:535
#define FIONBIO
Definition: winsock.h:149
static BOOL send_ssl_chunk(netconn_t *conn, const void *msg, size_t size)
_Check_return_ _CRTIMP int __cdecl __cdecl eof(_In_ int _FileHandle)
INT WSAAPI getsockopt(IN SOCKET s, IN INT level, IN INT optname, OUT CHAR FAR *optval, IN OUT INT FAR *optlen)
Definition: sockctrl.c:271
#define ERR(fmt,...)
Definition: debug.h:109
#define SECURITY_FLAG_IGNORE_CERT_DATE_INVALID
Definition: winhttp.h:282
BOOL mask_errors
Definition: internet.h:83
ULONG_PTR SIZE_T
Definition: typedefs.h:78
#define ERROR_INTERNET_SEC_CERT_DATE_INVALID
Definition: wininet.h:2025
#define ERROR_INTERNET_INVALID_CA
Definition: wininet.h:2033
#define CERT_TRUST_IS_NOT_VALID_FOR_USAGE
Definition: wincrypt.h:874
#define SP_PROT_TLS1_1PLUS_CLIENT
Definition: schannel.h:52
#define ERROR_INTERNET_SEC_INVALID_CERT
Definition: wininet.h:2076
#define SECBUFFER_VERSION
Definition: sspi.h:173
DWORD cUsageIdentifier
Definition: wincrypt.h:719
ULONG cbBuffer
Definition: sspi.h:139
#define ERROR_INTERNET_SECURITY_CHANNEL_ERROR
Definition: wininet.h:2068
#define SECURITY_FLAG_IGNORE_WRONG_USAGE
Definition: wininet.h:831
#define _SECURITY_FLAG_CERT_INVALID_DATE
Definition: internet.h:475
#define min(a, b)
Definition: monoChain.cc:55
SECURITY_STATUS WINAPI DecryptMessage(PCtxtHandle phContext, PSecBufferDesc pMessage, ULONG MessageSeqNo, PULONG pfQOP)
Definition: wrapper.c:1036
DWORD NETCON_set_timeout(netconn_t *connection, BOOL send, DWORD value)
int NETCON_GetCipherStrength(netconn_t *connection)
static void set_socket_blocking(netconn_t *conn, BOOL is_blocking)
#define CERT_TRUST_IS_UNTRUSTED_ROOT
Definition: wincrypt.h:875
#define UNISP_NAME_W
Definition: sspi.h:38
#define msg(x)
Definition: auth_time.c:54
CONST void * LPCVOID
Definition: windef.h:191
LPSTR * rgpszUsageIdentifier
Definition: wincrypt.h:720
#define SO_SNDTIMEO
Definition: winsock.h:192
GLuint res
Definition: glext.h:9613
__WINE_SERVER_LIST_INLINE void list_init(struct list *list)
Definition: list.h:149
unsigned int ULONG
Definition: retypes.h:1
#define _SECURITY_FLAG_CERT_INVALID_CA
Definition: internet.h:473
#define ISC_REQ_CONFIDENTIALITY
Definition: sspi.h:352
#define SECURITY_FLAG_SECURE
Definition: winhttp.h:285
#define ISC_REQ_REPLAY_DETECT
Definition: sspi.h:350
static DWORD create_netconn_socket(server_t *server, netconn_t *netconn, DWORD timeout)
void WINAPI LeaveCriticalSection(LPCRITICAL_SECTION)
#define SOCK_STREAM
Definition: tcpip.h:118
BOOL NETCON_is_alive(netconn_t *netconn)
Definition: _set.h:46
#define AUTHTYPE_SERVER
Definition: wincrypt.h:1035
GLuint64EXT * result
Definition: glext.h:11304
#define memset(x, y, z)
Definition: compat.h:39
static SERVICE_STATUS status
Definition: service.c:31
server_t * server
Definition: internet.h:75
INT WSAAPI recv(IN SOCKET s, OUT CHAR FAR *buf, IN INT len, IN INT flags)
Definition: recv.c:23
void free_netconn(netconn_t *netconn)
SecPkgContext_StreamSizes ssl_sizes
#define WSAEINTR
Definition: winerror.h:1942
#define SEC_E_INCOMPLETE_MESSAGE
Definition: winerror.h:2934
#define SECURITY_FLAG_STRENGTH_WEAK
Definition: winhttp.h:286
SECURITY_STATUS WINAPI EncryptMessage(PCtxtHandle phContext, ULONG fQOP, PSecBufferDesc pMessage, ULONG MessageSeqNo)
Definition: wrapper.c:1006
char * peek_msg_mem
SECURITY_STATUS WINAPI DeleteSecurityContext(PCtxtHandle phContext)
Definition: wrapper.c:450
#define CERT_TRUST_IS_PARTIAL_CHAIN
Definition: wincrypt.h:891
#define ERROR_OUTOFMEMORY
Definition: deptool.c:13
static BOOL have_compat_cred_handle
static BOOL heap_free(void *mem)
Definition: appwiz.h:75
#define _SECURITY_FLAG_CERT_REV_FAILED
Definition: internet.h:472
#define MSG_PEEK
Definition: winsock.h:222
Definition: ps.c:97