ReactOS  0.4.13-dev-563-g0561610
tcp.c
Go to the documentation of this file.
1 /* -*- c-basic-offset: 8 -*-
2  rdesktop: A Remote Desktop Protocol client.
3  Protocol services - TCP layer
4  Copyright (C) Matthew Chapman <matthewc.unsw.edu.au> 1999-2008
5  Copyright 2005-2011 Peter Astrand <astrand@cendio.se> for Cendio AB
6  Copyright 2012-2013 Henrik Andersson <hean01@cendio.se> for Cendio AB
7 
8  This program is free software: you can redistribute it and/or modify
9  it under the terms of the GNU General Public License as published by
10  the Free Software Foundation, either version 3 of the License, or
11  (at your option) any later version.
12 
13  This program is distributed in the hope that it will be useful,
14  but WITHOUT ANY WARRANTY; without even the implied warranty of
15  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16  GNU General Public License for more details.
17 
18  You should have received a copy of the GNU General Public License
19  along with this program. If not, see <http://www.gnu.org/licenses/>.
20 */
21 
22 #include "precomp.h"
23 #ifdef WITH_SSL
24 #include <sspi.h>
25 #include <schannel.h>
26 #endif
27 
28 #ifdef _WIN32
29 #define socklen_t int
30 #define TCP_CLOSE(_sck) closesocket(_sck)
31 #define TCP_STRERROR "tcp error"
32 #define TCP_SLEEP(_n) Sleep(_n)
33 #define TCP_BLOCKS (WSAGetLastError() == WSAEWOULDBLOCK)
34 #else /* _WIN32 */
35 #define TCP_CLOSE(_sck) close(_sck)
36 #define TCP_STRERROR strerror(errno)
37 #define TCP_SLEEP(_n) sleep(_n)
38 #define TCP_BLOCKS (errno == EWOULDBLOCK)
39 #endif /* _WIN32 */
40 
41 #ifndef INADDR_NONE
42 #define INADDR_NONE ((unsigned long) -1)
43 #endif
44 
45 #ifdef WITH_SCARD
46 #define STREAM_COUNT 8
47 #else
48 #define STREAM_COUNT 1
49 #endif
50 
51 #ifdef WITH_SSL
52 typedef struct
53 {
54  CtxtHandle ssl_ctx;
55  SecPkgContext_StreamSizes ssl_sizes;
56  char *ssl_buf;
57  char *extra_buf;
58  size_t extra_len;
59  char *peek_msg;
60  char *peek_msg_mem;
61  size_t peek_len;
62  DWORD security_flags;
63 } netconn_t;
64 static char * g_ssl_server = NULL;
65 static RD_BOOL g_ssl_initialized = False;
69 static netconn_t g_ssl1;
70 static netconn_t *g_ssl = NULL;
71 #endif /* WITH_SSL */
72 static int g_sock;
73 static struct stream g_in;
74 static struct stream g_out[STREAM_COUNT];
76 extern RD_BOOL g_user_quit;
79 
80 /* Initialise TCP transport data packet */
81 STREAM
83 {
84  static int cur_stream_id = 0;
85  STREAM result = NULL;
86 
87 #ifdef WITH_SCARD
89 #endif
90  result = &g_out[cur_stream_id];
91  cur_stream_id = (cur_stream_id + 1) % STREAM_COUNT;
92 
93  if (maxlen > result->size)
94  {
95  result->data = (uint8 *) xrealloc(result->data, maxlen);
96  result->size = maxlen;
97  }
98 
99  result->p = result->data;
100  result->end = result->data + result->size;
101 #ifdef WITH_SCARD
103 #endif
104  return result;
105 }
106 
107 #ifdef WITH_SSL
108 
109 RD_BOOL send_ssl_chunk(const void *msg, size_t size)
110 {
111  SecBuffer bufs[4] = {
113  {size, SECBUFFER_DATA, g_ssl->ssl_buf+g_ssl->ssl_sizes.cbHeader},
115  {0, SECBUFFER_EMPTY, NULL}
116  };
117  SecBufferDesc buf_desc = {SECBUFFER_VERSION, sizeof(bufs)/sizeof(*bufs), bufs};
119  int tcp_res;
120 
121  memcpy(bufs[1].pvBuffer, msg, size);
122  res = EncryptMessage(&g_ssl->ssl_ctx, 0, &buf_desc, 0);
123  if (res != SEC_E_OK)
124  {
125  error("EncryptMessage failed: %d\n", res);
126  return False;
127  }
128 
129  tcp_res = send(g_sock, g_ssl->ssl_buf, bufs[0].cbBuffer+bufs[1].cbBuffer+bufs[2].cbBuffer, 0);
130  if (tcp_res < 1)
131  {
132  error("send failed: %d (%s)\n", tcp_res, TCP_STRERROR);
133  return False;
134  }
135 
136  return True;
137 }
138 
139 DWORD read_ssl_chunk(void *buf, SIZE_T buf_size, BOOL blocking, SIZE_T *ret_size, BOOL *eof)
140 {
141  const SIZE_T ssl_buf_size = g_ssl->ssl_sizes.cbHeader+g_ssl->ssl_sizes.cbMaximumMessage+g_ssl->ssl_sizes.cbTrailer;
142  SecBuffer bufs[4];
143  SecBufferDesc buf_desc = {SECBUFFER_VERSION, sizeof(bufs)/sizeof(*bufs), bufs};
144  SSIZE_T size, buf_len = 0;
145  int i;
147 
148  //assert(conn->extra_len < ssl_buf_size);
149 
150  if (g_ssl->extra_len)
151  {
152  memcpy(g_ssl->ssl_buf, g_ssl->extra_buf, g_ssl->extra_len);
153  buf_len = g_ssl->extra_len;
154  g_ssl->extra_len = 0;
155  xfree(g_ssl->extra_buf);
156  g_ssl->extra_buf = NULL;
157  }
158 
159  size = recv(g_sock, g_ssl->ssl_buf+buf_len, ssl_buf_size-buf_len, 0);
160  if (size < 0)
161  {
162  if (!buf_len)
163  {
164  if (size == -1 && TCP_BLOCKS)
165  {
166  return WSAEWOULDBLOCK;
167  }
168  error("recv failed: %d (%s)\n", size, TCP_STRERROR);
169  return -1;//ERROR_INTERNET_CONNECTION_ABORTED;
170  }
171  }
172  else
173  {
174  buf_len += size;
175  }
176 
177  if (!buf_len)
178  {
179  *eof = TRUE;
180  *ret_size = 0;
181  return ERROR_SUCCESS;
182  }
183 
184  *eof = FALSE;
185 
186  do
187  {
188  memset(bufs, 0, sizeof(bufs));
189  bufs[0].BufferType = SECBUFFER_DATA;
190  bufs[0].cbBuffer = buf_len;
191  bufs[0].pvBuffer = g_ssl->ssl_buf;
192 
193  res = DecryptMessage(&g_ssl->ssl_ctx, &buf_desc, 0, NULL);
194  switch (res)
195  {
196  case SEC_E_OK:
197  break;
199  *eof = TRUE;
200  return ERROR_SUCCESS;
202  //assert(buf_len < ssl_buf_size);
203 
204  size = recv(g_sock, g_ssl->ssl_buf+buf_len, ssl_buf_size-buf_len, 0);
205  if (size < 1)
206  {
207  if (size == -1 && TCP_BLOCKS)
208  {
209  /* FIXME: Optimize extra_buf usage. */
210  g_ssl->extra_buf = xmalloc(buf_len);
211  if (!g_ssl->extra_buf)
213 
214  g_ssl->extra_len = buf_len;
215  memcpy(g_ssl->extra_buf, g_ssl->ssl_buf, g_ssl->extra_len);
216  return WSAEWOULDBLOCK;
217  }
218 
219  error("recv failed: %d (%s)\n", size, TCP_STRERROR);
220  return -1;//ERROR_INTERNET_CONNECTION_ABORTED;
221  }
222 
223  buf_len += size;
224  continue;
225  default:
226  error("DecryptMessage failed: %d\n", res);
227  return -1;//ERROR_INTERNET_CONNECTION_ABORTED;
228  }
229  }
230  while (res != SEC_E_OK);
231 
232  for (i=0; i < sizeof(bufs)/sizeof(*bufs); i++)
233  {
234  if (bufs[i].BufferType == SECBUFFER_DATA)
235  {
236  size = min(buf_size, bufs[i].cbBuffer);
237  memcpy(buf, bufs[i].pvBuffer, size);
238  if (size < bufs[i].cbBuffer)
239  {
240  //assert(!conn->peek_len);
241  g_ssl->peek_msg_mem = g_ssl->peek_msg = xmalloc(bufs[i].cbBuffer - size);
242  if (!g_ssl->peek_msg)
244  g_ssl->peek_len = bufs[i].cbBuffer-size;
245  memcpy(g_ssl->peek_msg, (char*)bufs[i].pvBuffer+size, g_ssl->peek_len);
246  }
247 
248  *ret_size = size;
249  }
250  }
251 
252  for (i=0; i < sizeof(bufs)/sizeof(*bufs); i++)
253  {
254  if (bufs[i].BufferType == SECBUFFER_EXTRA)
255  {
256  g_ssl->extra_buf = xmalloc(bufs[i].cbBuffer);
257  if (!g_ssl->extra_buf)
259 
260  g_ssl->extra_len = bufs[i].cbBuffer;
261  memcpy(g_ssl->extra_buf, bufs[i].pvBuffer, g_ssl->extra_len);
262  }
263  }
264 
265  return ERROR_SUCCESS;
266 }
267 #endif /* WITH_SSL */
268 /* Send TCP transport data packet */
269 void
271 {
272  int length = s->end - s->data;
273  int sent, total = 0;
274 
275  if (g_network_error == True)
276  return;
277 
278 #ifdef WITH_SCARD
280 #endif
281  while (total < length)
282  {
283 #ifdef WITH_SSL
284  if (g_ssl)
285  {
286  const BYTE *ptr = s->data + total;
287  size_t chunk_size;
288 
289  sent = 0;
290 
291  while (length - total)
292  {
293  chunk_size = min(length - total, g_ssl->ssl_sizes.cbMaximumMessage);
294  if (!send_ssl_chunk(ptr, chunk_size))
295  {
296 #ifdef WITH_SCARD
298 #endif
299 
300  //error("send_ssl_chunk: %d (%s)\n", sent, TCP_STRERROR);
302  return;
303  }
304 
305  sent += chunk_size;
306  ptr += chunk_size;
307  length -= chunk_size;
308  }
309  }
310  else
311  {
312 #endif /* WITH_SSL */
313  sent = send(g_sock, (const char *)s->data + total, length - total, 0);
314  if (sent <= 0)
315  {
316  if (sent == -1 && TCP_BLOCKS)
317  {
318  TCP_SLEEP(0);
319  sent = 0;
320  }
321  else
322  {
323 #ifdef WITH_SCARD
325 #endif
326 
327  error("send: %d (%s)\n", sent, TCP_STRERROR);
329  return;
330  }
331  }
332 #ifdef WITH_SSL
333  }
334 #endif /* WITH_SSL */
335  total += sent;
336  }
337 #ifdef WITH_SCARD
339 #endif
340 }
341 
342 /* Receive a message on the TCP layer */
343 STREAM
345 {
346  uint32 new_length, end_offset, p_offset;
347  int rcvd = 0;
348 
349  if (g_network_error == True)
350  return NULL;
351 
352  if (s == NULL)
353  {
354  /* read into "new" stream */
355  if (length > g_in.size)
356  {
357  g_in.data = (uint8 *) xrealloc(g_in.data, length);
358  g_in.size = length;
359  }
360  g_in.end = g_in.p = g_in.data;
361  s = &g_in;
362  }
363  else
364  {
365  /* append to existing stream */
366  new_length = (s->end - s->data) + length;
367  if (new_length > s->size)
368  {
369  p_offset = s->p - s->data;
370  end_offset = s->end - s->data;
371  s->data = (uint8 *) xrealloc(s->data, new_length);
372  s->size = new_length;
373  s->p = s->data + p_offset;
374  s->end = s->data + end_offset;
375  }
376  }
377 
378  while (length > 0)
379  {
380 #ifdef WITH_SSL
381  if (!g_ssl)
382 #endif /* WITH_SSL */
383  {
384  if (!ui_select(g_sock))
385  {
386  /* User quit */
387  g_user_quit = True;
388  return NULL;
389  }
390  }
391 
392 #ifdef WITH_SSL
393  if (g_ssl)
394  {
395  SIZE_T size = 0;
396  BOOL eof;
397  DWORD res;
398 
399  if (g_ssl->peek_msg)
400  {
401  size = min(length, g_ssl->peek_len);
402  memcpy(s->end, g_ssl->peek_msg, size);
403  g_ssl->peek_len -= size;
404  g_ssl->peek_msg += size;
405  s->end += size;
406 
407  if (!g_ssl->peek_len)
408  {
409  xfree(g_ssl->peek_msg_mem);
410  g_ssl->peek_msg_mem = g_ssl->peek_msg = NULL;
411  }
412 
413  return s;
414  }
415 
416  do
417  {
418  res = read_ssl_chunk((BYTE*)s->end, length, TRUE, &size, &eof);
419  if (res != ERROR_SUCCESS)
420  {
421  if (res == WSAEWOULDBLOCK)
422  {
423  if (size)
424  {
425  res = ERROR_SUCCESS;
426  }
427  }
428  else
429  {
430  error("read_ssl_chunk: %d (%s)\n", res, TCP_STRERROR);
432  return NULL;
433  }
434  break;
435  }
436  }
437  while (!size && !eof);
438  rcvd = size;
439  }
440  else
441  {
442 #endif /* WITH_SSL */
443  rcvd = recv(g_sock, (char *)s->end, length, 0);
444  if (rcvd < 0)
445  {
446  if (rcvd == -1 && TCP_BLOCKS)
447  {
448  rcvd = 0;
449  }
450  else
451  {
452  error("recv: %d (%s)\n", rcvd, TCP_STRERROR);
454  return NULL;
455  }
456  }
457  else if (rcvd == 0)
458  {
459  error("Connection closed\n");
460  return NULL;
461  }
462 #ifdef WITH_SSL
463  }
464 #endif /* WITH_SSL */
465 
466  s->end += rcvd;
467  length -= rcvd;
468  }
469 
470  return s;
471 }
472 
473 #ifdef WITH_SSL
474 
475 RD_BOOL
476 ensure_cred_handle(void)
477 {
479 
481  {
484 
486  NULL, NULL, &cred_handle, NULL);
487  if (res == SEC_E_OK)
488  {
491  {
496  }
497  }
498 
500  }
501 
502  if (res != SEC_E_OK)
503  {
504  error("ensure_cred_handle failed: %ld\n", res);
505  return False;
506  }
507 
508  return True;
509 }
510 
511 DWORD
512 ssl_handshake(RD_BOOL compat_mode)
513 {
514  SecBuffer out_buf = {0, SECBUFFER_TOKEN, NULL}, in_bufs[2] = {{0, SECBUFFER_TOKEN}, {0, SECBUFFER_EMPTY}};
515  SecBufferDesc out_desc = {SECBUFFER_VERSION, 1, &out_buf}, in_desc = {SECBUFFER_VERSION, 2, in_bufs};
516  SecHandle *cred = &cred_handle;
517  BYTE *read_buf;
518  SIZE_T read_buf_size = 2048;
519  ULONG attrs = 0;
520  CtxtHandle ctx;
521  SSIZE_T size;
524 
527 
528  if (!ensure_cred_handle())
529  return -1;
530 
531  if (compat_mode) {
533  return -1;
534  cred = &compat_cred_handle;
535  }
536 
537  read_buf = xmalloc(read_buf_size);
538  if (!read_buf)
539  return ERROR_OUTOFMEMORY;
540 
541  if (!g_ssl_server)
542  return -1;
543 
544  status = InitializeSecurityContextA(cred, NULL, g_ssl_server, isc_req_flags, 0, 0, NULL, 0,
545  &ctx, &out_desc, &attrs, NULL);
546 
547  //assert(status != SEC_E_OK);
548 
550  {
551  if (out_buf.cbBuffer)
552  {
553  //assert(status == SEC_I_CONTINUE_NEEDED);
554 
555  size = send(g_sock, out_buf.pvBuffer, out_buf.cbBuffer, 0);
556  if (size != out_buf.cbBuffer)
557  {
558  error("send failed: %d (%s)\n", size, TCP_STRERROR);
559  status = -1;
560  break;
561  }
562 
563  FreeContextBuffer(out_buf.pvBuffer);
564  out_buf.pvBuffer = NULL;
565  out_buf.cbBuffer = 0;
566  }
567 
569  {
570  //assert(in_bufs[1].cbBuffer < read_buf_size);
571 
572  memmove(read_buf, (BYTE*)in_bufs[0].pvBuffer+in_bufs[0].cbBuffer-in_bufs[1].cbBuffer, in_bufs[1].cbBuffer);
573  in_bufs[0].cbBuffer = in_bufs[1].cbBuffer;
574 
575  in_bufs[1].BufferType = SECBUFFER_EMPTY;
576  in_bufs[1].cbBuffer = 0;
577  in_bufs[1].pvBuffer = NULL;
578  }
579 
580  //assert(in_bufs[0].BufferType == SECBUFFER_TOKEN);
581  //assert(in_bufs[1].BufferType == SECBUFFER_EMPTY);
582 
583  if (in_bufs[0].cbBuffer + 1024 > read_buf_size)
584  {
585  BYTE *new_read_buf = xrealloc(read_buf, read_buf_size + 1024);
586  if (!new_read_buf)
587  {
589  break;
590  }
591 
592  in_bufs[0].pvBuffer = read_buf = new_read_buf;
593  read_buf_size += 1024;
594  }
595 
596  size = recv(g_sock, (char *)read_buf + in_bufs[0].cbBuffer, read_buf_size - in_bufs[0].cbBuffer, 0);
597  if (size < 1)
598  {
599  error("recv failed: %d (%s)\n", size, TCP_STRERROR);
600  res = -1;
601  break;
602  }
603 
604  in_bufs[0].cbBuffer += size;
605  in_bufs[0].pvBuffer = read_buf;
606  status = InitializeSecurityContextA(cred, &ctx, g_ssl_server, isc_req_flags, 0, 0, &in_desc,
607  0, NULL, &out_desc, &attrs, NULL);
608 
609  if (status == SEC_E_OK) {
610  if (SecIsValidHandle(&g_ssl->ssl_ctx))
612  g_ssl->ssl_ctx = ctx;
613 
614  if (in_bufs[1].BufferType == SECBUFFER_EXTRA)
615  {
616  //FIXME("SECBUFFER_EXTRA not supported\n");
617  }
618 
620  if (status != SEC_E_OK)
621  {
622  //error("Can't determine ssl buffer sizes: %ld\n", status);
623  break;
624  }
625 
627  + g_ssl->ssl_sizes.cbTrailer);
628  if (!g_ssl->ssl_buf)
629  {
630  res = GetLastError();
631  break;
632  }
633  }
634  }
635 
636  xfree(read_buf);
637 
638  if (status != SEC_E_OK || res != ERROR_SUCCESS)
639  {
640  error("Failed to establish SSL connection: %08x (%u)\n", status, res);
641  xfree(g_ssl->ssl_buf);
642  g_ssl->ssl_buf = NULL;
643  return res ? res : -1;
644  }
645 
646  return ERROR_SUCCESS;
647 }
648 
649 /* Establish a SSL/TLS 1.0 connection */
650 RD_BOOL
651 tcp_tls_connect(void)
652 {
653  int err;
654  char tcp_port_rdp_s[10];
655 
656  if (!g_ssl_initialized)
657  {
658  g_ssl = &g_ssl1;
659  SecInvalidateHandle(&g_ssl->ssl_ctx);
660 
661  g_ssl_initialized = True;
662  }
663 
664  snprintf(tcp_port_rdp_s, 10, "%d", g_tcp_port_rdp);
665  if ((err = ssl_handshake(FALSE)) != 0)
666  {
667  goto fail;
668  }
669 
670  return True;
671 
672  fail:
673  g_ssl = NULL;
674  return False;
675 }
676 
677 /* Get public key from server of TLS 1.0 connection */
678 RD_BOOL
680 {
681  const CERT_CONTEXT *cert = NULL;
683 
684  s->data = s->p = NULL;
685  s->size = 0;
686 
687  if (g_ssl == NULL)
688  goto out;
690  if (status != SEC_E_OK)
691  {
692  error("tcp_tls_get_server_pubkey: QueryContextAttributesW() failed %ld\n", status);
693  goto out;
694  }
695 
696  s->size = cert->cbCertEncoded;
697  if (s->size < 1)
698  {
699  error("tcp_tls_get_server_pubkey: cert->cbCertEncoded = %ld\n", cert->cbCertEncoded);
700  goto out;
701  }
702 
703  s->data = s->p = (unsigned char *)xmalloc(s->size);
704  memcpy(cert->pbCertEncoded, &s->p, s->size);
705  s->p = s->data;
706  s->end = s->p + s->size;
707 
708  out:
709  if (cert)
711  return (s->size != 0);
712 }
713 #endif /* WITH_SSL */
714 
715 /* Establish a connection on the TCP layer */
716 RD_BOOL
718 {
719  socklen_t option_len;
720  uint32 option_value;
721  int i;
722 
723 #ifdef IPv6
724 
725  int n;
726  struct addrinfo hints, *res, *ressave;
727  char tcp_port_rdp_s[10];
728 
729  snprintf(tcp_port_rdp_s, 10, "%d", g_tcp_port_rdp);
730 
731  memset(&hints, 0, sizeof(struct addrinfo));
732  hints.ai_family = AF_UNSPEC;
733  hints.ai_socktype = SOCK_STREAM;
734 
735  if ((n = getaddrinfo(server, tcp_port_rdp_s, &hints, &res)))
736  {
737  error("getaddrinfo: %s\n", gai_strerror(n));
738  return False;
739  }
740 
741  ressave = res;
742  g_sock = -1;
743  while (res)
744  {
745  g_sock = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
746  if (!(g_sock < 0))
747  {
748  if (connect(g_sock, res->ai_addr, res->ai_addrlen) == 0)
749  break;
750  TCP_CLOSE(g_sock);
751  g_sock = -1;
752  }
753  res = res->ai_next;
754  }
755  freeaddrinfo(ressave);
756 
757  if (g_sock == -1)
758  {
759  error("%s: unable to connect\n", server);
760  return False;
761  }
762 
763 #else /* no IPv6 support */
764 
765  struct hostent *nslookup;
766  struct sockaddr_in servaddr;
767 
768  if ((nslookup = gethostbyname(server)) != NULL)
769  {
770  memcpy(&servaddr.sin_addr, nslookup->h_addr, sizeof(servaddr.sin_addr));
771  }
772  else if ((servaddr.sin_addr.s_addr = inet_addr(server)) == INADDR_NONE)
773  {
774  error("%s: unable to resolve host\n", server);
775  return False;
776  }
777 
778  if ((g_sock = socket(AF_INET, SOCK_STREAM, 0)) < 0)
779  {
780  error("socket: %s\n", TCP_STRERROR);
781  return False;
782  }
783 
784  servaddr.sin_family = AF_INET;
785  servaddr.sin_port = htons((uint16) g_tcp_port_rdp);
786 
787  if (connect(g_sock, (struct sockaddr *) &servaddr, sizeof(struct sockaddr)) < 0)
788  {
789  if (!g_reconnect_loop)
790  error("connect: %s\n", TCP_STRERROR);
791 
792  TCP_CLOSE(g_sock);
793  g_sock = -1;
794  return False;
795  }
796 
797 #endif /* IPv6 */
798 
799  option_value = 1;
800  option_len = sizeof(option_value);
801  setsockopt(g_sock, IPPROTO_TCP, TCP_NODELAY, (void *) &option_value, option_len);
802  /* receive buffer must be a least 16 K */
803  if (getsockopt(g_sock, SOL_SOCKET, SO_RCVBUF, (void *) &option_value, &option_len) == 0)
804  {
805  if (option_value < (1024 * 16))
806  {
807  option_value = 1024 * 16;
808  option_len = sizeof(option_value);
809  setsockopt(g_sock, SOL_SOCKET, SO_RCVBUF, (void *) &option_value,
810  option_len);
811  }
812  }
813 
814  g_in.size = 4096;
815  g_in.data = (uint8 *) xmalloc(g_in.size);
816 
817  for (i = 0; i < STREAM_COUNT; i++)
818  {
819  g_out[i].size = 4096;
820  g_out[i].data = (uint8 *) xmalloc(g_out[i].size);
821  }
822 
823 #ifdef WITH_SSL
824  g_ssl_server = xmalloc(strlen(server)+1);
825 #endif /* WITH_SSL */
826 
827  return True;
828 }
829 
830 /* Disconnect on the TCP layer */
831 void
833 {
834 #ifdef WITH_SSL
835  if (g_ssl)
836  {
837  xfree(g_ssl->peek_msg_mem);
838  g_ssl->peek_msg_mem = NULL;
839  g_ssl->peek_msg = NULL;
840  g_ssl->peek_len = 0;
841  xfree(g_ssl->ssl_buf);
842  g_ssl->ssl_buf = NULL;
843  xfree(g_ssl->extra_buf);
844  g_ssl->extra_buf = NULL;
845  g_ssl->extra_len = 0;
846  if (SecIsValidHandle(&g_ssl->ssl_ctx))
852  if (g_ssl_server)
853  {
854  xfree(g_ssl_server);
855  g_ssl_server = NULL;
856  }
857  g_ssl = NULL;
858  g_ssl_initialized = False;
859  }
860 #endif /* WITH_SSL */
861  TCP_CLOSE(g_sock);
862  g_sock = -1;
863 }
864 
865 char *
867 {
868  static char ipaddr[32];
869  struct sockaddr_in sockaddr;
870  socklen_t len = sizeof(sockaddr);
871  if (getsockname(g_sock, (struct sockaddr *) &sockaddr, &len) == 0)
872  {
873  uint8 *ip = (uint8 *) & sockaddr.sin_addr;
874  sprintf(ipaddr, "%d.%d.%d.%d", ip[0], ip[1], ip[2], ip[3]);
875  }
876  else
877  strcpy(ipaddr, "127.0.0.1");
878  return ipaddr;
879 }
880 
881 RD_BOOL
883 {
884  struct sockaddr_in sockaddr;
885  socklen_t len = sizeof(sockaddr);
886  if (getpeername(g_sock, (struct sockaddr *) &sockaddr, &len))
887  return True;
888  return False;
889 }
890 
891 /* reset the state of the tcp layer */
892 /* Support for Session Directory */
893 void
895 {
896  int i;
897 
898  /* Clear the incoming stream */
899  if (g_in.data != NULL)
900  xfree(g_in.data);
901  g_in.p = NULL;
902  g_in.end = NULL;
903  g_in.data = NULL;
904  g_in.size = 0;
905  g_in.iso_hdr = NULL;
906  g_in.mcs_hdr = NULL;
907  g_in.sec_hdr = NULL;
908  g_in.rdp_hdr = NULL;
909  g_in.channel_hdr = NULL;
910 
911  /* Clear the outgoing stream(s) */
912  for (i = 0; i < STREAM_COUNT; i++)
913  {
914  if (g_out[i].data != NULL)
915  xfree(g_out[i].data);
916  g_out[i].p = NULL;
917  g_out[i].end = NULL;
918  g_out[i].data = NULL;
919  g_out[i].size = 0;
920  g_out[i].iso_hdr = NULL;
921  g_out[i].mcs_hdr = NULL;
922  g_out[i].sec_hdr = NULL;
923  g_out[i].rdp_hdr = NULL;
924  g_out[i].channel_hdr = NULL;
925  }
926 }
#define ISC_REQ_SEQUENCE_DETECT
Definition: sspi.h:351
size_t extra_len
namespace GUID const ADDRINFOEXW * hints
Definition: sock.c:80
#define SECPKG_ATTR_SUPPORTED_PROTOCOLS
Definition: schannel.h:74
#define memmove(s1, s2, n)
Definition: mkisofs.h:881
#define TCP_BLOCKS
Definition: tcp.c:38
CtxtHandle ssl_ctx
#define TRUE
Definition: types.h:120
#define TCP_STRERROR
Definition: tcp.c:36
#define SECPKG_CRED_OUTBOUND
Definition: sspi.h:277
static rfbScreenInfoPtr server
Definition: vnc.c:74
SOCKET WSAAPI socket(IN INT af, IN INT type, IN INT protocol)
Definition: socklife.c:143
u_short sin_port
Definition: winsock.h:511
#define freeaddrinfo
Definition: wspiapi.h:46
#define inet_addr(cp)
Definition: inet.h:98
#define ERROR_SUCCESS
Definition: deptool.c:10
RD_BOOL tcp_tls_connect(void)
#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
#define error(str)
Definition: mkdosfs.c:1605
const GLenum * bufs
Definition: glext.h:6026
ACPI_SIZE strlen(const char *String)
Definition: utclib.c:269
SECURITY_STATUS WINAPI FreeContextBuffer(PVOID pv)
Definition: sspi.c:699
GLenum GLuint GLenum GLsizei const GLchar * buf
Definition: glext.h:7751
#define SEC_I_CONTEXT_EXPIRED
Definition: winerror.h:2933
unsigned int uint32
Definition: types.h:32
#define SecIsValidHandle(x)
Definition: sspi.h:63
BOOL WINAPI CertFreeCertificateContext(PCCERT_CONTEXT pCertContext)
Definition: cert.c:371
void tcp_send(STREAM s)
Definition: tcp.c:270
#define INADDR_NONE
Definition: tcp.c:42
#define SECPKG_ATTR_REMOTE_CERT_CONTEXT
Definition: schannel.h:69
#define SCARD_LOCK_TCP
Definition: constants.h:579
STREAM tcp_init(uint32 maxlen)
Definition: tcp.c:82
#define WSAEWOULDBLOCK
Definition: winerror.h:1948
static BOOL send_ssl_chunk(netconn_t *conn, const void *msg, size_t size)
Definition: net.c:560
GLdouble n
Definition: glext.h:7729
static SecHandle cred_handle
#define snprintf
Definition: wintirpc.h:48
#define ERROR_NOT_ENOUGH_MEMORY
Definition: dderror.h:7
#define SECBUFFER_DATA
Definition: sspi.h:146
DWORD WINAPI GetLastError(VOID)
Definition: except.c:1059
LONG_PTR SSIZE_T
Definition: basetsd.h:183
SECURITY_STATUS WINAPI FreeCredentialsHandle(PCredHandle phCredential)
Definition: wrapper.c:151
char * ssl_buf
size_t peek_len
#define SOL_SOCKET
Definition: winsock.h:398
INT WSAAPI connect(IN SOCKET s, IN CONST struct sockaddr *name, IN INT namelen)
Definition: sockctrl.c:23
#define SECBUFFER_EXTRA
Definition: sspi.h:150
unsigned read_buf(z_streamp strm, Bytef *buf, unsigned size)
Definition: deflate.c:1167
STREAM tcp_recv(STREAM s, uint32 length)
Definition: tcp.c:344
static struct stream g_out[STREAM_COUNT]
Definition: tcp.c:74
#define TCP_NODELAY
Definition: tcpdef.h:117
#define TCP_CLOSE(_sck)
Definition: tcp.c:35
#define ISC_REQ_MANUAL_CRED_VALIDATION
Definition: sspi.h:367
#define sprintf(buf, format,...)
Definition: sprintf.c:55
#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
SECURITY_STATUS WINAPI QueryCredentialsAttributesA(PCredHandle phCredential, ULONG ulAttribute, void *pBuffer)
Definition: wrapper.c:177
void * xrealloc(void *oldmem, size_t size)
Definition: uimain.c:736
RD_BOOL tcp_connect(char *server)
Definition: tcp.c:717
#define E_OUTOFMEMORY
Definition: ddrawi.h:100
void * xmalloc(int size)
Definition: uimain.c:747
unsigned int BOOL
Definition: ntddk_ex.h:94
char * extra_buf
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
smooth NULL
Definition: ftsmooth.c:416
DWORD grbitEnabledProtocols
Definition: schannel.h:96
#define SECBUFFER_EMPTY
Definition: sspi.h:145
#define TCP_PORT_RDP
Definition: constants.h:21
#define SEC_I_CONTINUE_NEEDED
Definition: winerror.h:2927
static BYTE cert[]
Definition: msg.c:1437
int RD_BOOL
Definition: types.h:21
#define STREAM_COUNT
Definition: tcp.c:48
#define AF_UNSPEC
Definition: winsock.h:344
INT WSAAPI getpeername(IN SOCKET s, OUT LPSOCKADDR name, IN OUT INT FAR *namelen)
Definition: sockctrl.c:167
LONG SECURITY_STATUS
Definition: sspi.h:34
void tcp_reset_state(void)
Definition: tcp.c:894
#define True
Definition: types.h:24
static SecHandle compat_cred_handle
PHOSTENT WSAAPI gethostbyname(IN const char FAR *name)
Definition: getxbyxx.c:221
static BOOL ensure_cred_handle(session_t *session)
Definition: request.c:1625
#define False
Definition: types.h:25
char * tcp_get_address()
Definition: tcp.c:866
GLsizeiptr size
Definition: glext.h:5919
void xfree(void *mem)
Definition: uimain.c:758
Definition: dhcpd.h:61
#define SO_RCVBUF
Definition: winsock.h:189
__wchar_t WCHAR
Definition: xmlstorage.h:180
GLenum GLuint GLenum GLsizei length
Definition: glext.h:5579
INT WSAAPI send(IN SOCKET s, IN CONST CHAR FAR *buf, IN INT len, IN INT flags)
Definition: send.c:23
SECURITY_STATUS WINAPI InitializeSecurityContextA(PCredHandle phCredential, PCtxtHandle phContext, SEC_CHAR *pszTargetName, ULONG fContextReq, ULONG Reserved1, ULONG TargetDataRep, PSecBufferDesc pInput, ULONG Reserved2, PCtxtHandle phNewContext, PSecBufferDesc pOutput, ULONG *pfContextAttr, PTimeStamp ptsExpiry)
Definition: wrapper.c:237
RD_BOOL g_user_quit
Definition: uimain.c:76
static FILE * out
Definition: regtests2xml.c:44
unsigned long DWORD
Definition: ntddk_ex.h:95
void scard_unlock(int lock)
int socklen_t
Definition: tcp.c:35
unsigned char uint8
Definition: types.h:28
char * peek_msg
#define gai_strerror
Definition: ws2tcpip.h:521
static BOOL read_ssl_chunk(netconn_t *conn, void *buf, SIZE_T buf_size, SIZE_T *ret_size, BOOL *eof)
Definition: net.c:615
GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const GLvoid * data
Definition: gl.h:1950
#define ISC_REQ_USE_SESSION_KEY
Definition: sspi.h:353
#define SECPKG_ATTR_STREAM_SIZES
Definition: sspi.h:511
#define SECBUFFER_STREAM_TRAILER
Definition: sspi.h:151
#define ISC_REQ_ALLOCATE_MEMORY
Definition: sspi.h:356
Definition: msg.h:34
Definition: parse.h:22
#define SECBUFFER_TOKEN
Definition: sspi.h:147
#define memcpy(s1, s2, n)
Definition: mkisofs.h:878
GLenum GLsizei len
Definition: glext.h:6722
unsigned char BYTE
Definition: mem.h:68
GLdouble s
Definition: gl.h:2039
#define err(...)
#define SEC_E_OK
Definition: winerror.h:2356
SECURITY_STATUS WINAPI QueryContextAttributesW(PCtxtHandle phContext, ULONG ulAttribute, void *pBuffer)
Definition: wrapper.c:535
_Check_return_ _CRTIMP int __cdecl __cdecl eof(_In_ int _FileHandle)
struct in_addr sin_addr
Definition: winsock.h:512
void tcp_disconnect(void)
Definition: tcp.c:832
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
int ui_select(int rdp_socket)
Definition: uimain.c:164
ULONG_PTR SIZE_T
Definition: typedefs.h:78
#define SP_PROT_TLS1_1PLUS_CLIENT
Definition: schannel.h:52
void scard_lock(int lock)
#define SECBUFFER_VERSION
Definition: sspi.h:173
ULONG cbBuffer
Definition: sspi.h:139
unsigned short uint16
Definition: types.h:30
#define ssl_handshake
Definition: compat-1.3.h:2313
#define min(a, b)
Definition: monoChain.cc:55
SECURITY_STATUS WINAPI DecryptMessage(PCtxtHandle phContext, PSecBufferDesc pMessage, ULONG MessageSeqNo, PULONG pfQOP)
Definition: wrapper.c:1036
#define UNISP_NAME_W
Definition: sspi.h:38
#define msg(x)
Definition: auth_time.c:54
GLuint res
Definition: glext.h:9613
int g_tcp_port_rdp
Definition: tcp.c:75
static struct stream g_in
Definition: tcp.c:73
char * strcpy(char *DstString, const char *SrcString)
Definition: utclib.c:388
unsigned int ULONG
Definition: retypes.h:1
#define AF_INET
Definition: tcpip.h:117
#define ISC_REQ_CONFIDENTIALITY
Definition: sspi.h:352
static int g_sock
Definition: tcp.c:72
#define TCP_SLEEP(_n)
Definition: tcp.c:37
#define ISC_REQ_REPLAY_DETECT
Definition: sspi.h:350
#define SOCK_STREAM
Definition: tcpip.h:118
#define htons(x)
Definition: module.h:213
RD_BOOL tcp_tls_get_server_pubkey(STREAM s)
GLuint64EXT * result
Definition: glext.h:11304
#define memset(x, y, z)
Definition: compat.h:39
static SERVICE_STATUS status
Definition: service.c:31
RD_BOOL g_reconnect_loop
Definition: uimain.c:86
INT WSAAPI recv(IN SOCKET s, OUT CHAR FAR *buf, IN INT len, IN INT flags)
Definition: recv.c:23
short sin_family
Definition: winsock.h:510
INT WSAAPI getsockname(IN SOCKET s, OUT LPSOCKADDR name, IN OUT INT FAR *namelen)
Definition: sockctrl.c:213
SecPkgContext_StreamSizes ssl_sizes
#define SEC_E_INCOMPLETE_MESSAGE
Definition: winerror.h:2934
SECURITY_STATUS WINAPI EncryptMessage(PCtxtHandle phContext, ULONG fQOP, PSecBufferDesc pMessage, ULONG MessageSeqNo)
Definition: wrapper.c:1006
char * peek_msg_mem
RD_BOOL tcp_is_connected()
Definition: tcp.c:882
SECURITY_STATUS WINAPI DeleteSecurityContext(PCtxtHandle phContext)
Definition: wrapper.c:450
#define ERROR_OUTOFMEMORY
Definition: deptool.c:13
static BOOL have_compat_cred_handle
RD_BOOL g_network_error
Definition: uimain.c:77
#define getaddrinfo
Definition: wspiapi.h:44
Definition: ps.c:97