ReactOS  0.4.15-dev-2979-gfd8baca
netconnection.c
Go to the documentation of this file.
1 #ifdef __REACTOS__
2 #define NONAMELESSUNION
3 #include "precomp.h"
4 #else
5 /*
6  * Wininet - networking layer
7  *
8  * Copyright 2002 TransGaming Technologies Inc.
9  * Copyright 2013 Jacek Caban for CodeWeavers
10  *
11  * David Hammerton
12  *
13  * This library is free software; you can redistribute it and/or
14  * modify it under the terms of the GNU Lesser General Public
15  * License as published by the Free Software Foundation; either
16  * version 2.1 of the License, or (at your option) any later version.
17  *
18  * This library is distributed in the hope that it will be useful,
19  * but WITHOUT ANY WARRANTY; without even the implied warranty of
20  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
21  * Lesser General Public License for more details.
22  *
23  * You should have received a copy of the GNU Lesser General Public
24  * License along with this library; if not, write to the Free Software
25  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
26  */
27 
28 #define NONAMELESSUNION
29 
30 #include "ws2tcpip.h"
31 
32 #include <time.h>
33 #include <stdarg.h>
34 #include <stdlib.h>
35 #include <string.h>
36 #include <stdio.h>
37 #include <assert.h>
38 
39 #include "windef.h"
40 #include "winbase.h"
41 #include "wininet.h"
42 #include "winerror.h"
43 
44 #include "wine/debug.h"
45 #include "internet.h"
46 #endif /* defined(__REACTOS__) */
47 
49 
51 {
52  BOOL ret;
53  CERT_CHAIN_PARA chainPara = { sizeof(chainPara), { 0 } };
55  char oid_server_auth[] = szOID_PKIX_KP_SERVER_AUTH;
56  char *server_auth[] = { oid_server_auth };
57  DWORD err = ERROR_SUCCESS, errors;
58 
59  static const DWORD supportedErrors =
65 
66  TRACE("verifying %s\n", debugstr_w(conn->server->name));
67 
69  chainPara.RequestedUsage.Usage.rgpszUsageIdentifier = server_auth;
70  if (!(ret = CertGetCertificateChain(NULL, cert, NULL, store, &chainPara, 0, NULL, &chain))) {
71  TRACE("failed\n");
72  return GetLastError();
73  }
74 
75  errors = chain->TrustStatus.dwErrorStatus;
76 
77  do {
78  /* This seems strange, but that's what tests show */
79  if(errors & CERT_TRUST_IS_PARTIAL_CHAIN) {
80  WARN("ERROR_INTERNET_SEC_CERT_REV_FAILED\n");
82  if(conn->mask_errors)
85  break;
86  }
87 
88  if (chain->TrustStatus.dwErrorStatus & ~supportedErrors) {
89  WARN("error status %x\n", chain->TrustStatus.dwErrorStatus & ~supportedErrors);
91  errors &= supportedErrors;
92  if(!conn->mask_errors)
93  break;
94  WARN("unknown error flags\n");
95  }
96 
97  if(errors & CERT_TRUST_IS_NOT_TIME_VALID) {
98  WARN("CERT_TRUST_IS_NOT_TIME_VALID\n");
101  if(!conn->mask_errors)
102  break;
104  }
105  errors &= ~CERT_TRUST_IS_NOT_TIME_VALID;
106  }
107 
108  if(errors & CERT_TRUST_IS_UNTRUSTED_ROOT) {
109  WARN("CERT_TRUST_IS_UNTRUSTED_ROOT\n");
112  if(!conn->mask_errors)
113  break;
115  }
116  errors &= ~CERT_TRUST_IS_UNTRUSTED_ROOT;
117  }
118 
119  if(errors & CERT_TRUST_IS_PARTIAL_CHAIN) {
120  WARN("CERT_TRUST_IS_PARTIAL_CHAIN\n");
123  if(!conn->mask_errors)
124  break;
126  }
127  errors &= ~CERT_TRUST_IS_PARTIAL_CHAIN;
128  }
129 
130  if(errors & CERT_TRUST_IS_NOT_SIGNATURE_VALID) {
131  WARN("CERT_TRUST_IS_NOT_SIGNATURE_VALID\n");
134  if(!conn->mask_errors)
135  break;
137  }
139  }
140 
141  if(errors & CERT_TRUST_IS_NOT_VALID_FOR_USAGE) {
142  WARN("CERT_TRUST_IS_NOT_VALID_FOR_USAGE\n");
145  if(!conn->mask_errors)
146  break;
147  WARN("CERT_TRUST_IS_NOT_VALID_FOR_USAGE, unknown error flags\n");
148  }
150  }
151 
154  err = ERROR_SUCCESS;
155  }
156  }while(0);
157 
158  if(!err || conn->mask_errors) {
159  CERT_CHAIN_POLICY_PARA policyPara;
160  SSL_EXTRA_CERT_CHAIN_POLICY_PARA sslExtraPolicyPara;
161  CERT_CHAIN_POLICY_STATUS policyStatus;
162  CERT_CHAIN_CONTEXT chainCopy;
163 
164  /* Clear chain->TrustStatus.dwErrorStatus so
165  * CertVerifyCertificateChainPolicy will verify additional checks
166  * rather than stopping with an existing, ignored error.
167  */
168  memcpy(&chainCopy, chain, sizeof(chainCopy));
169  chainCopy.TrustStatus.dwErrorStatus = 0;
170  sslExtraPolicyPara.u.cbSize = sizeof(sslExtraPolicyPara);
171  sslExtraPolicyPara.dwAuthType = AUTHTYPE_SERVER;
172  sslExtraPolicyPara.pwszServerName = conn->server->name;
173  sslExtraPolicyPara.fdwChecks = conn->security_flags;
174  policyPara.cbSize = sizeof(policyPara);
175  policyPara.dwFlags = 0;
176  policyPara.pvExtraPolicyPara = &sslExtraPolicyPara;
178  &chainCopy, &policyPara, &policyStatus);
179  /* Any error in the policy status indicates that the
180  * policy couldn't be verified.
181  */
182  if(ret) {
183  if(policyStatus.dwError == CERT_E_CN_NO_MATCH) {
184  WARN("CERT_E_CN_NO_MATCH\n");
185  if(conn->mask_errors)
188  }else if(policyStatus.dwError) {
189  WARN("policyStatus.dwError %x\n", policyStatus.dwError);
190  if(conn->mask_errors)
191  WARN("unknown error flags for policy status %x\n", policyStatus.dwError);
193  }
194  }else {
195  err = GetLastError();
196  }
197  }
198 
199  if(err) {
200  WARN("failed %u\n", err);
202  if(conn->server->cert_chain) {
204  conn->server->cert_chain = NULL;
205  }
206  if(conn->mask_errors)
208  return err;
209  }
210 
211  /* FIXME: Reuse cached chain */
212  if(conn->server->cert_chain)
214  else
215  conn->server->cert_chain = chain;
216  return ERROR_SUCCESS;
217 }
218 
221 
224  0, 0, &init_sechandle_cs,
227  0, 0, { (DWORD_PTR)(__FILE__ ": init_sechandle_cs") }
228 };
229 static CRITICAL_SECTION init_sechandle_cs = { &init_sechandle_cs_debug, -1, 0, 0, 0, 0 };
230 
232 {
234 
236 
240 
242  NULL, NULL, &cred_handle, NULL);
243  if(res == SEC_E_OK) {
250  }
251  }
252 
254  }
255 
257 
258  if(res != SEC_E_OK) {
259  WARN("Failed: %08x\n", res);
260  return FALSE;
261  }
262 
263  return TRUE;
264 }
265 
267 
268 static BOOL WINAPI winsock_startup(INIT_ONCE *once, void *param, void **context)
269 {
270  WSADATA wsa_data;
271  DWORD res;
272 
273  res = WSAStartup(MAKEWORD(2,2), &wsa_data);
274  if(res == ERROR_SUCCESS)
276  else
277  ERR("WSAStartup failed: %u\n", res);
278  return TRUE;
279 }
280 
281 void init_winsock(void)
282 {
283  static INIT_ONCE init_once = INIT_ONCE_STATIC_INIT;
285 }
286 
287 static void set_socket_blocking(netconn_t *conn, BOOL is_blocking)
288 {
289  if(conn->is_blocking != is_blocking) {
290  ULONG arg = !is_blocking;
291  ioctlsocket(conn->socket, FIONBIO, &arg);
292  }
293  conn->is_blocking = is_blocking;
294 }
295 
297 {
298  int result;
299  ULONG flag;
300  DWORD res;
301 
302  init_winsock();
303 
304  assert(server->addr_len);
305  result = netconn->socket = socket(server->addr.ss_family, SOCK_STREAM, 0);
306  if(result != -1) {
308  result = connect(netconn->socket, (struct sockaddr*)&server->addr, server->addr_len);
309  if(result == -1)
310  {
311  res = WSAGetLastError();
312  if (res == WSAEINPROGRESS || res == WSAEWOULDBLOCK) {
313  FD_SET set;
314  int res;
315  socklen_t len = sizeof(res);
316  TIMEVAL timeout_timeval = {0, timeout*1000};
317 
318  FD_ZERO(&set);
319  FD_SET(netconn->socket, &set);
320  res = select(netconn->socket+1, NULL, &set, NULL, &timeout_timeval);
321  if(!res || res == SOCKET_ERROR) {
323  netconn->socket = -1;
325  }
326  if (!getsockopt(netconn->socket, SOL_SOCKET, SO_ERROR, (void *)&res, &len) && !res)
327  result = 0;
328  }
329  }
330  if(result == -1)
331  {
333  netconn->socket = -1;
334  }
335  }
336  if(result == -1)
338 
339  flag = 1;
341  if(result < 0)
342  WARN("setsockopt(TCP_NODELAY) failed\n");
343 
344  return ERROR_SUCCESS;
345 }
346 
348 {
350  int result;
351 
352  netconn = heap_alloc_zero(sizeof(*netconn));
353  if(!netconn)
354  return ERROR_OUTOFMEMORY;
355 
356  netconn->socket = -1;
357  netconn->security_flags = security_flags | server->security_flags;
358  netconn->mask_errors = mask_errors;
359  list_init(&netconn->pool_entry);
361 
363  if (result != ERROR_SUCCESS) {
365  return result;
366  }
367 
369  netconn->server = server;
370  *ret = netconn;
371  return result;
372 }
373 
375 {
376  return netconn && netconn->socket != -1;
377 }
378 
380 {
382  netconn->socket = -1;
383 }
384 
386 {
387  server_release(netconn->server);
388 
389  if (netconn->secure) {
392  netconn->peek_msg = NULL;
393  netconn->peek_len = 0;
395  netconn->ssl_buf = NULL;
398  netconn->extra_len = 0;
399  }
402 
405 }
406 
407 void NETCON_unload(void)
408 {
414  if(winsock_loaded)
415  WSACleanup();
416 }
417 
418 int sock_send(int fd, const void *msg, size_t len, int flags)
419 {
420  int ret;
421  do
422  {
423  ret = send(fd, msg, len, flags);
424  }
425  while(ret == -1 && WSAGetLastError() == WSAEINTR);
426  return ret;
427 }
428 
429 int sock_recv(int fd, void *msg, size_t len, int flags)
430 {
431  int ret;
432  do
433  {
434  ret = recv(fd, msg, len, flags);
435  }
436  while(ret == -1 && WSAGetLastError() == WSAEINTR);
437  return ret;
438 }
439 
440 static DWORD netcon_secure_connect_setup(netconn_t *connection, BOOL compat_mode)
441 {
442  SecBuffer out_buf = {0, SECBUFFER_TOKEN, NULL}, in_bufs[2] = {{0, SECBUFFER_TOKEN}, {0, SECBUFFER_EMPTY}};
443  SecBufferDesc out_desc = {SECBUFFER_VERSION, 1, &out_buf}, in_desc = {SECBUFFER_VERSION, 2, in_bufs};
444  SecHandle *cred = &cred_handle;
445  BYTE *read_buf;
446  SIZE_T read_buf_size = 2048;
447  ULONG attrs = 0;
448  CtxtHandle ctx;
449  SSIZE_T size;
450  int bits;
451  const CERT_CONTEXT *cert;
454 
457 
458  if(!ensure_cred_handle())
460 
461  if(compat_mode) {
464  cred = &compat_cred_handle;
465  }
466 
467  read_buf = heap_alloc(read_buf_size);
468  if(!read_buf)
469  return ERROR_OUTOFMEMORY;
470 
471  status = InitializeSecurityContextW(cred, NULL, connection->server->name, isc_req_flags, 0, 0, NULL, 0,
472  &ctx, &out_desc, &attrs, NULL);
473 
474  assert(status != SEC_E_OK);
475 
476  set_socket_blocking(connection, TRUE);
477 
479  if(out_buf.cbBuffer) {
481 
482  TRACE("sending %u bytes\n", out_buf.cbBuffer);
483 
484  size = sock_send(connection->socket, out_buf.pvBuffer, out_buf.cbBuffer, 0);
485  if(size != out_buf.cbBuffer) {
486  ERR("send failed\n");
488  break;
489  }
490 
491  FreeContextBuffer(out_buf.pvBuffer);
492  out_buf.pvBuffer = NULL;
493  out_buf.cbBuffer = 0;
494  }
495 
497  assert(in_bufs[1].cbBuffer < read_buf_size);
498 
499  memmove(read_buf, (BYTE*)in_bufs[0].pvBuffer+in_bufs[0].cbBuffer-in_bufs[1].cbBuffer, in_bufs[1].cbBuffer);
500  in_bufs[0].cbBuffer = in_bufs[1].cbBuffer;
501 
502  in_bufs[1].BufferType = SECBUFFER_EMPTY;
503  in_bufs[1].cbBuffer = 0;
504  in_bufs[1].pvBuffer = NULL;
505  }
506 
507  assert(in_bufs[0].BufferType == SECBUFFER_TOKEN);
508  assert(in_bufs[1].BufferType == SECBUFFER_EMPTY);
509 
510  if(in_bufs[0].cbBuffer + 1024 > read_buf_size) {
511  BYTE *new_read_buf;
512 
513  new_read_buf = heap_realloc(read_buf, read_buf_size + 1024);
514  if(!new_read_buf) {
516  break;
517  }
518 
519  in_bufs[0].pvBuffer = read_buf = new_read_buf;
520  read_buf_size += 1024;
521  }
522 
523  size = sock_recv(connection->socket, read_buf+in_bufs[0].cbBuffer, read_buf_size-in_bufs[0].cbBuffer, 0);
524  if(size < 1) {
525  WARN("recv error\n");
527  break;
528  }
529 
530  TRACE("recv %lu bytes\n", size);
531 
532  in_bufs[0].cbBuffer += size;
533  in_bufs[0].pvBuffer = read_buf;
534  status = InitializeSecurityContextW(cred, &ctx, connection->server->name, isc_req_flags, 0, 0, &in_desc,
535  0, NULL, &out_desc, &attrs, NULL);
536  TRACE("InitializeSecurityContext ret %08x\n", status);
537 
538  if(status == SEC_E_OK) {
539  if(SecIsValidHandle(&connection->ssl_ctx))
540  DeleteSecurityContext(&connection->ssl_ctx);
541  connection->ssl_ctx = ctx;
542 
543  if(in_bufs[1].BufferType == SECBUFFER_EXTRA)
544  FIXME("SECBUFFER_EXTRA not supported\n");
545 
547  if(status != SEC_E_OK) {
548  WARN("Could not get sizes\n");
549  break;
550  }
551 
553  if(status == SEC_E_OK) {
554  res = netconn_verify_cert(connection, cert, cert->hCertStore);
556  if(res != ERROR_SUCCESS) {
557  WARN("cert verify failed: %u\n", res);
558  break;
559  }
560  }else {
561  WARN("Could not get cert\n");
562  break;
563  }
564 
565  connection->ssl_buf = heap_alloc(connection->ssl_sizes.cbHeader + connection->ssl_sizes.cbMaximumMessage
566  + connection->ssl_sizes.cbTrailer);
567  if(!connection->ssl_buf) {
568  res = GetLastError();
569  break;
570  }
571  }
572  }
573 
575 
576  if(status != SEC_E_OK || res != ERROR_SUCCESS) {
577  WARN("Failed to establish SSL connection: %08x (%u)\n", status, res);
578  heap_free(connection->ssl_buf);
579  connection->ssl_buf = NULL;
581  }
582 
583  TRACE("established SSL connection\n");
584  connection->secure = TRUE;
585  connection->security_flags |= SECURITY_FLAG_SECURE;
586 
587  bits = NETCON_GetCipherStrength(connection);
588  if (bits >= 128)
590  else if (bits >= 56)
592  else
594 
595  if(connection->mask_errors)
596  connection->server->security_flags = connection->security_flags;
597  return ERROR_SUCCESS;
598 }
599 
600 /******************************************************************************
601  * NETCON_secure_connect
602  * Initiates a secure connection over an existing plaintext connection.
603  */
605 {
606  DWORD res;
607 
608  /* can't connect if we are already connected */
609  if(connection->secure) {
610  ERR("already connected\n");
612  }
613 
614  if(server != connection->server) {
615  server_release(connection->server);
617  connection->server = server;
618  }
619 
620  /* connect with given TLS options */
621  res = netcon_secure_connect_setup(connection, FALSE);
622  if (res == ERROR_SUCCESS)
623  return res;
624 
625  /* FIXME: when got version alert and FIN from server */
626  /* fallback to connect without TLSv1.1/TLSv1.2 */
628  {
629  closesocket(connection->socket);
630  res = create_netconn_socket(connection->server, connection, 500);
631  if (res != ERROR_SUCCESS)
632  return res;
633  res = netcon_secure_connect_setup(connection, TRUE);
634  }
635  return res;
636 }
637 
638 static BOOL send_ssl_chunk(netconn_t *conn, const void *msg, size_t size)
639 {
640  SecBuffer bufs[4] = {
642  {size, SECBUFFER_DATA, conn->ssl_buf+conn->ssl_sizes.cbHeader},
644  {0, SECBUFFER_EMPTY, NULL}
645  };
648 
649  memcpy(bufs[1].pvBuffer, msg, size);
650  res = EncryptMessage(&conn->ssl_ctx, 0, &buf_desc, 0);
651  if(res != SEC_E_OK) {
652  WARN("EncryptMessage failed\n");
653  return FALSE;
654  }
655 
656  if(sock_send(conn->socket, conn->ssl_buf, bufs[0].cbBuffer+bufs[1].cbBuffer+bufs[2].cbBuffer, 0) < 1) {
657  WARN("send failed\n");
658  return FALSE;
659  }
660 
661  return TRUE;
662 }
663 
664 /******************************************************************************
665  * NETCON_send
666  * Basically calls 'send()' unless we should use SSL
667  * number of chars send is put in *sent
668  */
669 DWORD NETCON_send(netconn_t *connection, const void *msg, size_t len, int flags,
670  int *sent /* out */)
671 {
672  /* send is always blocking. */
673  set_socket_blocking(connection, TRUE);
674 
675  if(!connection->secure)
676  {
677  *sent = sock_send(connection->socket, msg, len, flags);
678  return *sent == -1 ? WSAGetLastError() : ERROR_SUCCESS;
679  }
680  else
681  {
682  const BYTE *ptr = msg;
683  size_t chunk_size;
684 
685  *sent = 0;
686 
687  while(len) {
688  chunk_size = min(len, connection->ssl_sizes.cbMaximumMessage);
689  if(!send_ssl_chunk(connection, ptr, chunk_size))
691 
692  *sent += chunk_size;
693  ptr += chunk_size;
694  len -= chunk_size;
695  }
696 
697  return ERROR_SUCCESS;
698  }
699 }
700 
701 static BOOL read_ssl_chunk(netconn_t *conn, void *buf, SIZE_T buf_size, BOOL blocking, SIZE_T *ret_size, BOOL *eof)
702 {
703  const SIZE_T ssl_buf_size = conn->ssl_sizes.cbHeader+conn->ssl_sizes.cbMaximumMessage+conn->ssl_sizes.cbTrailer;
704  SecBuffer bufs[4];
706  SSIZE_T size, buf_len = 0;
707  int i;
709 
710  assert(conn->extra_len < ssl_buf_size);
711 
712  if(conn->extra_len) {
713  memcpy(conn->ssl_buf, conn->extra_buf, conn->extra_len);
714  buf_len = conn->extra_len;
715  conn->extra_len = 0;
716  heap_free(conn->extra_buf);
717  conn->extra_buf = NULL;
718  }
719 
720  set_socket_blocking(conn, blocking && !buf_len);
721  size = sock_recv(conn->socket, conn->ssl_buf+buf_len, ssl_buf_size-buf_len, 0);
722  if(size < 0) {
723  if(!buf_len) {
725  TRACE("would block\n");
726  return WSAEWOULDBLOCK;
727  }
728  WARN("recv failed\n");
730  }
731  }else {
732  buf_len += size;
733  }
734 
735  if(!buf_len) {
736  TRACE("EOF\n");
737  *eof = TRUE;
738  *ret_size = 0;
739  return ERROR_SUCCESS;
740  }
741 
742  *eof = FALSE;
743 
744  do {
745  memset(bufs, 0, sizeof(bufs));
746  bufs[0].BufferType = SECBUFFER_DATA;
747  bufs[0].cbBuffer = buf_len;
748  bufs[0].pvBuffer = conn->ssl_buf;
749 
750  res = DecryptMessage(&conn->ssl_ctx, &buf_desc, 0, NULL);
751  switch(res) {
752  case SEC_E_OK:
753  break;
755  TRACE("context expired\n");
756  *eof = TRUE;
757  return ERROR_SUCCESS;
759  assert(buf_len < ssl_buf_size);
760 
761  set_socket_blocking(conn, blocking);
762  size = sock_recv(conn->socket, conn->ssl_buf+buf_len, ssl_buf_size-buf_len, 0);
763  if(size < 1) {
764  if(size < 0 && WSAGetLastError() == WSAEWOULDBLOCK) {
765  TRACE("would block\n");
766 
767  /* FIXME: Optimize extra_buf usage. */
768  conn->extra_buf = heap_alloc(buf_len);
769  if(!conn->extra_buf)
771 
772  conn->extra_len = buf_len;
773  memcpy(conn->extra_buf, conn->ssl_buf, conn->extra_len);
774  return WSAEWOULDBLOCK;
775  }
776 
778  }
779 
780  buf_len += size;
781  continue;
782  default:
783  WARN("failed: %08x\n", res);
785  }
786  } while(res != SEC_E_OK);
787 
788  for(i = 0; i < ARRAY_SIZE(bufs); i++) {
789  if(bufs[i].BufferType == SECBUFFER_DATA) {
790  size = min(buf_size, bufs[i].cbBuffer);
791  memcpy(buf, bufs[i].pvBuffer, size);
792  if(size < bufs[i].cbBuffer) {
793  assert(!conn->peek_len);
794  conn->peek_msg_mem = conn->peek_msg = heap_alloc(bufs[i].cbBuffer - size);
795  if(!conn->peek_msg)
797  conn->peek_len = bufs[i].cbBuffer-size;
798  memcpy(conn->peek_msg, (char*)bufs[i].pvBuffer+size, conn->peek_len);
799  }
800 
801  *ret_size = size;
802  }
803  }
804 
805  for(i = 0; i < ARRAY_SIZE(bufs); i++) {
806  if(bufs[i].BufferType == SECBUFFER_EXTRA) {
807  conn->extra_buf = heap_alloc(bufs[i].cbBuffer);
808  if(!conn->extra_buf)
810 
811  conn->extra_len = bufs[i].cbBuffer;
812  memcpy(conn->extra_buf, bufs[i].pvBuffer, conn->extra_len);
813  }
814  }
815 
816  return ERROR_SUCCESS;
817 }
818 
819 /******************************************************************************
820  * NETCON_recv
821  * Basically calls 'recv()' unless we should use SSL
822  * number of chars received is put in *recvd
823  */
824 DWORD NETCON_recv(netconn_t *connection, void *buf, size_t len, BOOL blocking, int *recvd)
825 {
826  *recvd = 0;
827  if (!len)
828  return ERROR_SUCCESS;
829 
830  if (!connection->secure)
831  {
832  set_socket_blocking(connection, blocking);
833  *recvd = sock_recv(connection->socket, buf, len, 0);
834  return *recvd == -1 ? WSAGetLastError() : ERROR_SUCCESS;
835  }
836  else
837  {
838  SIZE_T size = 0;
839  BOOL eof;
840  DWORD res;
841 
842  if(connection->peek_msg) {
843  size = min(len, connection->peek_len);
844  memcpy(buf, connection->peek_msg, size);
845  connection->peek_len -= size;
846  connection->peek_msg += size;
847 
848  if(!connection->peek_len) {
849  heap_free(connection->peek_msg_mem);
850  connection->peek_msg_mem = connection->peek_msg = NULL;
851  }
852 
853  *recvd = size;
854  return ERROR_SUCCESS;
855  }
856 
857  do {
858  res = read_ssl_chunk(connection, (BYTE*)buf, len, blocking, &size, &eof);
859  if(res != ERROR_SUCCESS) {
860  if(res == WSAEWOULDBLOCK) {
861  if(size)
862  res = ERROR_SUCCESS;
863  }else {
864  WARN("read_ssl_chunk failed\n");
865  }
866  break;
867  }
868  }while(!size && !eof);
869 
870  TRACE("received %ld bytes\n", size);
871  *recvd = size;
872  return res;
873  }
874 }
875 
877 {
878  int len;
879  char b;
880 
882  len = sock_recv(netconn->socket, &b, 1, MSG_PEEK);
883 
884  return len == 1 || (len == -1 && WSAGetLastError() == WSAEWOULDBLOCK);
885 }
886 
888 {
889  const CERT_CONTEXT *ret;
891 
893  return res == SEC_E_OK ? ret : NULL;
894 }
895 
897 {
900 
901  if (!connection->secure)
902  return 0;
903 
904  res = QueryContextAttributesW(&connection->ssl_ctx, SECPKG_ATTR_CONNECTION_INFO, (void*)&conn_info);
905  if(res != SEC_E_OK)
906  WARN("QueryContextAttributesW failed: %08x\n", res);
907  return res == SEC_E_OK ? conn_info.dwCipherStrength : 0;
908 }
909 
911 {
912  int result;
913 
914  result = setsockopt(connection->socket, SOL_SOCKET,
915  send ? SO_SNDTIMEO : SO_RCVTIMEO, (void*)&value,
916  sizeof(value));
917  if (result == -1)
918  {
919  WARN("setsockopt failed\n");
920  return WSAGetLastError();
921  }
922  return ERROR_SUCCESS;
923 }
#define ISC_REQ_SEQUENCE_DETECT
Definition: sspi.h:365
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
Definition: internet.h:77
#define SOCKET_ERROR
Definition: winsock.h:333
#define ERROR_INTERNET_SEC_CERT_CN_INVALID
Definition: wininet.h:2026
char * peek_msg_mem
CERT_ENHKEY_USAGE Usage
Definition: wincrypt.h:1048
size_t peek_len
#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
Definition: pdh_main.c:93
CtxtHandle ssl_ctx
Definition: internet.h:72
static DWORD netconn_verify_cert(netconn_t *conn, PCCERT_CONTEXT cert, HCERTSTORE store)
Definition: netconnection.c:50
#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:291
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)
char * extra_buf
#define ERROR_SUCCESS
Definition: deptool.c:10
#define DWORD_PTR
Definition: treelist.c:76
size_t extra_len
#define SECBUFFER_STREAM_HEADER
Definition: sspi.h:166
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
GLuint64EXT * result
Definition: glext.h:11304
const GLenum * bufs
Definition: glext.h:6026
static BOOL WINAPI winsock_startup(INIT_ONCE *once, void *param, void **context)
Definition: http.c:7251
#define MAKEWORD(a, b)
Definition: typedefs.h:248
SECURITY_STATUS WINAPI FreeContextBuffer(PVOID pv)
Definition: sspi.c:699
#define TRUE
Definition: types.h:120
#define ERROR_INTERNET_SEC_CERT_REV_FAILED
Definition: wininet.h:2044
#define SEC_I_CONTEXT_EXPIRED
Definition: winerror.h:2933
char * peek_msg
#define SecIsValidHandle(x)
Definition: sspi.h:63
BOOL WINAPI CertFreeCertificateContext(PCCERT_CONTEXT pCertContext)
Definition: cert.c:371
#define WARN(fmt,...)
Definition: debug.h:112
int sock_recv(int fd, void *msg, size_t len, int flags)
#define INIT_ONCE_STATIC_INIT
Definition: winbase.h:609
#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:50
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:160
#define assert(x)
Definition: debug.h:53
DWORD WINAPI GetLastError(VOID)
Definition: except.c:1040
#define ioctlsocket
Definition: ncftp.h:481
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
#define closesocket
Definition: ncftp.h:477
Definition: dhcpd.h:245
size_t peek_len
Definition: internet.h:80
#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:154
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
int socket
Definition: internet.h:69
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:164
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:381
#define SECURITY_FLAG_IGNORE_REVOCATION
Definition: wininet.h:829
#define SecInvalidateHandle(x)
Definition: sspi.h:58
GLenum GLuint GLenum GLsizei const GLchar * buf
Definition: glext.h:7751
static BOOL cred_handle_initialized
#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 FALSE
Definition: types.h:117
unsigned int BOOL
Definition: ntddk_ex.h:94
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
#define debugstr_w
Definition: kernel32.h:32
#define FIXME(fmt,...)
Definition: debug.h:111
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)
#define ERROR_INTERNET_SEC_CERT_ERRORS
Definition: wininet.h:2042
DWORD grbitEnabledProtocols
Definition: schannel.h:96
#define SECBUFFER_EMPTY
Definition: sspi.h:159
#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
static BYTE cert[]
Definition: msg.c:1437
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:1102
DWORD security_flags
Definition: internet.h:81
CERT_TRUST_STATUS TrustStatus
Definition: wincrypt.h:939
#define b
Definition: ke_i.h:79
LONG SECURITY_STATUS
Definition: sspi.h:34
BOOL secure
Definition: internet.h:70
#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:71
__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
CtxtHandle ssl_ctx
GLfloat param
Definition: glext.h:5796
#define WINAPI
Definition: msvc.h:6
DWORD security_flags
Definition: internet.h:49
unsigned long DWORD
Definition: ntddk_ex.h:95
int socklen_t
Definition: tcp.c:35
#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:367
GLbitfield flags
Definition: glext.h:7161
#define SECPKG_ATTR_STREAM_SIZES
Definition: sspi.h:525
#define SECBUFFER_STREAM_TRAILER
Definition: sspi.h:165
int ret
char * peek_msg_mem
Definition: internet.h:79
#define ISC_REQ_ALLOCATE_MEMORY
Definition: sspi.h:370
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:161
#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:149
WCHAR * name
Definition: internet.h:36
WINE_DEFAULT_DEBUG_CHANNEL(wininet)
#define err(...)
LIST_ENTRY ProcessLocksList
Definition: winbase.h:877
#define SEC_E_OK
Definition: winerror.h:2356
unsigned char BYTE
Definition: xxhash.c:193
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:110
#define SECURITY_FLAG_IGNORE_CERT_DATE_INVALID
Definition: winhttp.h:282
BOOL mask_errors
Definition: internet.h:82
ULONG_PTR SIZE_T
Definition: typedefs.h:80
#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:2077
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 SECBUFFER_VERSION
Definition: sspi.h:187
DWORD cUsageIdentifier
Definition: wincrypt.h:719
ULONG cbBuffer
Definition: sspi.h:153
#define ERROR_INTERNET_SECURITY_CHANNEL_ERROR
Definition: wininet.h:2069
#define ARRAY_SIZE(a)
Definition: main.h:24
#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
#define NULL
Definition: types.h:112
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
char * peek_msg
Definition: internet.h:78
#define msg(x)
Definition: auth_time.c:54
CONST void * LPCVOID
Definition: windef.h:191
LPSTR * rgpszUsageIdentifier
Definition: wincrypt.h:720
char * ssl_buf
Definition: internet.h:75
#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:366
#define SECURITY_FLAG_SECURE
Definition: winhttp.h:285
#define ISC_REQ_REPLAY_DETECT
Definition: sspi.h:364
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)
char * extra_buf
Definition: internet.h:76
Definition: _set.h:46
#define AUTHTYPE_SERVER
Definition: wincrypt.h:1035
#define memset(x, y, z)
Definition: compat.h:39
static SERVICE_STATUS status
Definition: service.c:31
server_t * server
Definition: internet.h:74
INT WSAAPI recv(IN SOCKET s, OUT CHAR FAR *buf, IN INT len, IN INT flags)
Definition: recv.c:23
DWORD create_netconn(server_t *server, DWORD security_flags, BOOL mask_errors, DWORD timeout, netconn_t **ret)
void free_netconn(netconn_t *netconn)
char * ssl_buf
SecPkgContext_StreamSizes ssl_sizes
Definition: internet.h:73
#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
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