ReactOS  0.4.12-dev-57-g7050ac4
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  {
490  if (res != SEC_E_OK || (prots.grbitProtocol & SP_PROT_TLS1_1PLUS_CLIENT))
491  {
493  res = AcquireCredentialsHandleW(NULL, (WCHAR*)UNISP_NAME_W, SECPKG_CRED_OUTBOUND, NULL, &cred,
494  NULL, NULL, &compat_cred_handle, NULL);
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 
549  while (status == SEC_I_CONTINUE_NEEDED || status == SEC_E_INCOMPLETE_MESSAGE)
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 
568  if (status == SEC_I_CONTINUE_NEEDED)
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  {
588  status = E_OUTOFMEMORY;
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;
689  status = QueryContextAttributesW(&g_ssl->ssl_ctx, SECPKG_ATTR_REMOTE_CERT_CONTEXT, (void*)&cert);
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))
849  FreeCredentialsHandle(&cred_handle);
851  FreeCredentialsHandle(&compat_cred_handle);
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
#define SECPKG_ATTR_SUPPORTED_PROTOCOLS
Definition: schannel.h:73
#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
__wchar_t WCHAR
Definition: xmlstorage.h:180
#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:370
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:68
#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
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
unsigned char * data
Definition: parse.h:26
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
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
GLuint n
Definition: s_context.h:57
static BOOL cred_handle_initialized
GLenum GLclampf GLint i
Definition: glfuncs.h:14
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
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
UINT msg
Definition: msvc.h:92
smooth NULL
Definition: ftsmooth.c:416
DWORD grbitEnabledProtocols
Definition: schannel.h:95
#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
unsigned int BOOL
Definition: ntddk_ex.h:94
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
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 char * end
Definition: parse.h:25
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
unsigned int size
Definition: parse.h:27
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
ULONG BufferType
Definition: sspi.h:140
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
unsigned char BYTE
Definition: ntddk_ex.h:96
int ai_protocol
Definition: ws2def.h:668
_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:51
void scard_lock(int lock)
local unsigned read_buf(z_streamp strm, Bytef *buf, unsigned size)
Definition: deflate.c:1164
#define SECBUFFER_VERSION
Definition: sspi.h:173
int ai_socktype
Definition: ws2def.h:667
ULONG cbBuffer
Definition: sspi.h:139
unsigned short uint16
Definition: types.h:30
#define ssl_handshake
Definition: compat-1.3.h:2306
#define min(a, b)
Definition: monoChain.cc:55
SECURITY_STATUS WINAPI DecryptMessage(PCtxtHandle phContext, PSecBufferDesc pMessage, ULONG MessageSeqNo, PULONG pfQOP)
Definition: wrapper.c:1036
unsigned char * p
Definition: parse.h:24
struct addrinfo * ai_next
Definition: ws2def.h:672
#define UNISP_NAME_W
Definition: sspi.h:38
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
size_t ai_addrlen
Definition: ws2def.h:669
#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
struct sockaddr * ai_addr
Definition: ws2def.h:671
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
int ai_family
Definition: ws2def.h:666