FreeRDP
listener.c
1 
20 #include <freerdp/config.h>
21 
22 #include <stdio.h>
23 #include <stdlib.h>
24 #include <string.h>
25 #include <fcntl.h>
26 #include <errno.h>
27 
28 #include <winpr/crt.h>
29 #include <winpr/windows.h>
30 #include <freerdp/log.h>
31 
32 #ifndef _WIN32
33 #include <netdb.h>
34 #include <unistd.h>
35 #include <sys/un.h>
36 #include <sys/ioctl.h>
37 #include <sys/socket.h>
38 #include <arpa/inet.h>
39 #include <netinet/in.h>
40 #include <net/if.h>
41 #endif
42 
43 #if defined(HAVE_AF_VSOCK_H)
44 #include <ctype.h>
45 #include <linux/vm_sockets.h>
46 #endif
47 
48 #include <winpr/handle.h>
49 
50 #include "listener.h"
51 #include "utils.h"
52 
53 #define TAG FREERDP_TAG("core.listener")
54 
55 static BOOL freerdp_listener_open_from_vsock(freerdp_listener* instance, const char* bind_address,
56  UINT16 port)
57 {
58 #if defined(HAVE_AF_VSOCK_H)
59  rdpListener* listener = (rdpListener*)instance->listener;
60  const int sockfd = socket(AF_VSOCK, SOCK_STREAM, 0);
61  if (sockfd == -1)
62  {
63  char ebuffer[256] = { 0 };
64  WLog_ERR(TAG, "Error creating socket: %s", winpr_strerror(errno, ebuffer, sizeof(ebuffer)));
65  return FALSE;
66  }
67  const int flags = fcntl(sockfd, F_GETFL, 0);
68  if (fcntl(sockfd, F_SETFL, flags | O_NONBLOCK) == -1)
69  {
70  char ebuffer[256] = { 0 };
71  WLog_ERR(TAG, "Error making socket nonblocking: %s",
72  winpr_strerror(errno, ebuffer, sizeof(ebuffer)));
73  close(sockfd);
74  return FALSE;
75  }
76  struct sockaddr_vm addr = { 0 };
77 
78  addr.svm_family = AF_VSOCK;
79  addr.svm_port = port;
80 
81  errno = 0;
82  char* ptr = NULL;
83  unsigned long val = strtoul(bind_address, &ptr, 10);
84  if (errno || (val > UINT32_MAX))
85  {
86  char ebuffer[256] = { 0 };
87  WLog_ERR(TAG, "could not extract port from '%s', value=%ul, error=%s", bind_address, val,
88  winpr_strerror(errno, ebuffer, sizeof(ebuffer)));
89  close(sockfd);
90  return FALSE;
91  }
92  addr.svm_cid = WINPR_ASSERTING_INT_CAST(unsigned int, val);
93  if (bind(sockfd, (struct sockaddr*)&addr, sizeof(struct sockaddr_vm)) == -1)
94  {
95  char ebuffer[256] = { 0 };
96  WLog_ERR(TAG, "Error binding vsock at cid %d port %d: %s", addr.svm_cid, port,
97  winpr_strerror(errno, ebuffer, sizeof(ebuffer)));
98  close(sockfd);
99  return FALSE;
100  }
101 
102  if (listen(sockfd, 10) == -1)
103  {
104  char ebuffer[256] = { 0 };
105  WLog_ERR(TAG, "Error listening to socket at cid %d port %d: %s", addr.svm_cid, port,
106  winpr_strerror(errno, ebuffer, sizeof(ebuffer)));
107  close(sockfd);
108  return FALSE;
109  }
110  listener->sockfds[listener->num_sockfds] = sockfd;
111  listener->events[listener->num_sockfds] = WSACreateEvent();
112 
113  if (!listener->events[listener->num_sockfds])
114  {
115  listener->num_sockfds = 0;
116  }
117 
118  WSAEventSelect((SOCKET)sockfd, listener->events[listener->num_sockfds],
119  FD_READ | FD_ACCEPT | FD_CLOSE);
120  listener->num_sockfds++;
121 
122  WLog_INFO(TAG, "Listening on %s:%d", bind_address, port);
123  return TRUE;
124 #else
125  WLog_ERR(TAG, "compiled without AF_VSOCK, '%s' not supported", bind_address);
126  return FALSE;
127 #endif
128 }
129 
130 static BOOL freerdp_listener_open(freerdp_listener* instance, const char* bind_address, UINT16 port)
131 {
132  int ai_flags = 0;
133  int status = 0;
134  int sockfd = 0;
135  char addr[64];
136  void* sin_addr = NULL;
137  int option_value = 0;
138  struct addrinfo* res = NULL;
139  rdpListener* listener = (rdpListener*)instance->listener;
140 #ifdef _WIN32
141  u_long arg;
142 #endif
143 
144  if (!bind_address)
145  ai_flags = AI_PASSIVE;
146 
147  if (utils_is_vsock(bind_address))
148  {
149  bind_address = utils_is_vsock(bind_address);
150  return freerdp_listener_open_from_vsock(instance, bind_address, port);
151  }
152 
153  res = freerdp_tcp_resolve_host(bind_address, port, ai_flags);
154 
155  if (!res)
156  return FALSE;
157 
158  for (struct addrinfo* ai = res; ai && (listener->num_sockfds < 5); ai = ai->ai_next)
159  {
160  if ((ai->ai_family != AF_INET) && (ai->ai_family != AF_INET6))
161  continue;
162 
163  if (listener->num_sockfds == MAX_LISTENER_HANDLES)
164  {
165  WLog_ERR(TAG, "too many listening sockets");
166  continue;
167  }
168 
169  sockfd = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol);
170 
171  if (sockfd == -1)
172  {
173  WLog_ERR(TAG, "socket");
174  continue;
175  }
176 
177  option_value = 1;
178 
179  if (ai->ai_family == AF_INET)
180  sin_addr = &(((struct sockaddr_in*)ai->ai_addr)->sin_addr);
181  else
182  {
183  sin_addr = &(((struct sockaddr_in6*)ai->ai_addr)->sin6_addr);
184  if (setsockopt(sockfd, IPPROTO_IPV6, IPV6_V6ONLY, (void*)&option_value,
185  sizeof(option_value)) == -1)
186  WLog_ERR(TAG, "setsockopt");
187  }
188 
189  inet_ntop(ai->ai_family, sin_addr, addr, sizeof(addr));
190 
191  if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, (void*)&option_value,
192  sizeof(option_value)) == -1)
193  WLog_ERR(TAG, "setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR)");
194 
195 #ifndef _WIN32
196  if (fcntl(sockfd, F_SETFL, O_NONBLOCK) != 0)
197  WLog_ERR(TAG, "fcntl(sockfd, F_SETFL, O_NONBLOCK)");
198 #else
199  arg = 1;
200  ioctlsocket(sockfd, FIONBIO, &arg);
201 #endif
202  status = _bind((SOCKET)sockfd, ai->ai_addr, WINPR_ASSERTING_INT_CAST(int, ai->ai_addrlen));
203 
204  if (status != 0)
205  {
206  closesocket((SOCKET)sockfd);
207  continue;
208  }
209 
210  status = _listen((SOCKET)sockfd, 10);
211 
212  if (status != 0)
213  {
214  WLog_ERR(TAG, "listen");
215  closesocket((SOCKET)sockfd);
216  continue;
217  }
218 
219  /* FIXME: these file descriptors do not work on Windows */
220  listener->sockfds[listener->num_sockfds] = sockfd;
221  listener->events[listener->num_sockfds] = WSACreateEvent();
222 
223  if (!listener->events[listener->num_sockfds])
224  {
225  listener->num_sockfds = 0;
226  break;
227  }
228 
229  WSAEventSelect((SOCKET)sockfd, listener->events[listener->num_sockfds],
230  FD_READ | FD_ACCEPT | FD_CLOSE);
231  listener->num_sockfds++;
232  WLog_INFO(TAG, "Listening on [%s]:%" PRIu16, addr, port);
233  }
234 
235  freeaddrinfo(res);
236  return (listener->num_sockfds > 0 ? TRUE : FALSE);
237 }
238 
239 static BOOL freerdp_listener_open_local(freerdp_listener* instance, const char* path)
240 {
241 #ifndef _WIN32
242  int status = 0;
243  int sockfd = 0;
244  struct sockaddr_un addr = { 0 };
245  rdpListener* listener = (rdpListener*)instance->listener;
246  HANDLE hevent = NULL;
247 
248  if (listener->num_sockfds == MAX_LISTENER_HANDLES)
249  {
250  WLog_ERR(TAG, "too many listening sockets");
251  return FALSE;
252  }
253 
254  sockfd = socket(AF_UNIX, SOCK_STREAM, 0);
255 
256  if (sockfd == -1)
257  {
258  WLog_ERR(TAG, "socket");
259  return FALSE;
260  }
261 
262  int rc = fcntl(sockfd, F_SETFL, O_NONBLOCK);
263  if (rc != 0)
264  {
265  WLog_ERR(TAG, "fcntl(sockfd, F_SETFL, O_NONBLOCK)");
266  closesocket((SOCKET)sockfd);
267  return FALSE;
268  }
269 
270  addr.sun_family = AF_UNIX;
271  strncpy(addr.sun_path, path, sizeof(addr.sun_path) - 1);
272  unlink(path);
273  status = _bind((SOCKET)sockfd, (struct sockaddr*)&addr, sizeof(addr));
274 
275  if (status != 0)
276  {
277  WLog_ERR(TAG, "bind");
278  closesocket((SOCKET)sockfd);
279  return FALSE;
280  }
281 
282  status = _listen((SOCKET)sockfd, 10);
283 
284  if (status != 0)
285  {
286  WLog_ERR(TAG, "listen");
287  closesocket((SOCKET)sockfd);
288  return FALSE;
289  }
290 
291  hevent = CreateFileDescriptorEvent(NULL, FALSE, FALSE, sockfd, WINPR_FD_READ);
292 
293  if (!hevent)
294  {
295  WLog_ERR(TAG, "failed to create sockfd event");
296  closesocket((SOCKET)sockfd);
297  return FALSE;
298  }
299 
300  listener->sockfds[listener->num_sockfds] = sockfd;
301  listener->events[listener->num_sockfds] = hevent;
302  listener->num_sockfds++;
303  WLog_INFO(TAG, "Listening on socket %s.", addr.sun_path);
304  return TRUE;
305 #else
306  return TRUE;
307 #endif
308 }
309 
310 static BOOL freerdp_listener_open_from_socket(freerdp_listener* instance, int fd)
311 {
312 #ifndef _WIN32
313  rdpListener* listener = (rdpListener*)instance->listener;
314 
315  if (listener->num_sockfds == MAX_LISTENER_HANDLES)
316  {
317  WLog_ERR(TAG, "too many listening sockets");
318  return FALSE;
319  }
320 
321  if (fcntl(fd, F_SETFL, O_NONBLOCK) < 0)
322  return FALSE;
323 
324  listener->sockfds[listener->num_sockfds] = fd;
325  listener->events[listener->num_sockfds] = WSACreateEvent();
326 
327  if (!listener->events[listener->num_sockfds])
328  return FALSE;
329 
330  WSAEventSelect((SOCKET)fd, listener->events[listener->num_sockfds],
331  FD_READ | FD_ACCEPT | FD_CLOSE);
332 
333  listener->num_sockfds++;
334  WLog_INFO(TAG, "Listening on socket %d.", fd);
335  return TRUE;
336 #else
337  return FALSE;
338 #endif
339 }
340 
341 static void freerdp_listener_close(freerdp_listener* instance)
342 {
343  rdpListener* listener = (rdpListener*)instance->listener;
344 
345  for (int i = 0; i < listener->num_sockfds; i++)
346  {
347  closesocket((SOCKET)listener->sockfds[i]);
348  (void)CloseHandle(listener->events[i]);
349  }
350 
351  listener->num_sockfds = 0;
352 }
353 
354 #if defined(WITH_FREERDP_DEPRECATED)
355 static BOOL freerdp_listener_get_fds(freerdp_listener* instance, void** rfds, int* rcount)
356 {
357  rdpListener* listener = (rdpListener*)instance->listener;
358 
359  if (listener->num_sockfds < 1)
360  return FALSE;
361 
362  for (int index = 0; index < listener->num_sockfds; index++)
363  {
364  rfds[*rcount] = (void*)(long)(listener->sockfds[index]);
365  (*rcount)++;
366  }
367 
368  return TRUE;
369 }
370 #endif
371 
372 static DWORD freerdp_listener_get_event_handles(freerdp_listener* instance, HANDLE* events,
373  DWORD nCount)
374 {
375  rdpListener* listener = (rdpListener*)instance->listener;
376 
377  if (listener->num_sockfds < 1)
378  return 0;
379 
380  if (listener->num_sockfds > (INT64)nCount)
381  return 0;
382 
383  for (int index = 0; index < listener->num_sockfds; index++)
384  {
385  events[index] = listener->events[index];
386  }
387 
388  return WINPR_ASSERTING_INT_CAST(uint32_t, listener->num_sockfds);
389 }
390 
391 BOOL freerdp_peer_set_local_and_hostname(freerdp_peer* client,
392  const struct sockaddr_storage* peer_addr)
393 {
394  const void* sin_addr = NULL;
395  const BYTE localhost6_bytes[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 };
396 
397  WINPR_ASSERT(client);
398  WINPR_ASSERT(peer_addr);
399 
400  if (peer_addr->ss_family == AF_INET)
401  {
402  const UINT32* usin_addr = sin_addr = &(((const struct sockaddr_in*)peer_addr)->sin_addr);
403 
404  if ((*usin_addr) == 0x0100007f)
405  client->local = TRUE;
406  }
407  else if (peer_addr->ss_family == AF_INET6)
408  {
409  const struct sockaddr_in6* usin_addr = sin_addr =
410  &(((const struct sockaddr_in6*)peer_addr)->sin6_addr);
411 
412  if (memcmp(usin_addr, localhost6_bytes, 16) == 0)
413  client->local = TRUE;
414  }
415 
416 #ifndef _WIN32
417 #if defined(HAVE_AF_VSOCK_H)
418  else if (peer_addr->ss_family == AF_UNIX || peer_addr->ss_family == AF_VSOCK)
419 #else
420  else if (peer_addr->ss_family == AF_UNIX)
421 #endif
422  client->local = TRUE;
423 #endif
424 
425  if (client->local)
426  WLog_INFO(TAG, "Accepting client from localhost");
427 
428  if (sin_addr)
429  inet_ntop(peer_addr->ss_family, sin_addr, client->hostname, sizeof(client->hostname));
430 
431  return TRUE;
432 }
433 
434 static BOOL freerdp_check_and_create_client(freerdp_listener* instance, int peer_sockfd,
435  const struct sockaddr_storage* peer_addr)
436 {
437  WINPR_ASSERT(instance);
438  WINPR_ASSERT(peer_sockfd >= 0);
439  WINPR_ASSERT(peer_addr);
440 
441  const BOOL check = IFCALLRESULT(TRUE, instance->CheckPeerAcceptRestrictions, instance);
442  if (!check)
443  {
444  closesocket((SOCKET)peer_sockfd);
445  return TRUE;
446  }
447 
448  freerdp_peer* client = freerdp_peer_new(peer_sockfd);
449  if (!client)
450  {
451  closesocket((SOCKET)peer_sockfd);
452  return FALSE;
453  }
454 
455  if (!freerdp_peer_set_local_and_hostname(client, peer_addr))
456  {
457  freerdp_peer_free(client);
458  return FALSE;
459  }
460 
461  const BOOL peer_accepted = IFCALLRESULT(FALSE, instance->PeerAccepted, instance, client);
462  if (!peer_accepted)
463  {
464  WLog_ERR(TAG, "PeerAccepted callback failed");
465  freerdp_peer_free(client);
466  }
467 
468  return TRUE;
469 }
470 
471 static BOOL freerdp_listener_check_fds(freerdp_listener* instance)
472 {
473  rdpListener* listener = (rdpListener*)instance->listener;
474 
475  if (listener->num_sockfds < 1)
476  return FALSE;
477 
478  for (int i = 0; i < listener->num_sockfds; i++)
479  {
480  struct sockaddr_storage peer_addr = { 0 };
481 
482  (void)WSAResetEvent(listener->events[i]);
483  int peer_addr_size = sizeof(peer_addr);
484  SOCKET peer_sockfd =
485  _accept((SOCKET)listener->sockfds[i], (struct sockaddr*)&peer_addr, &peer_addr_size);
486 
487  if (peer_sockfd == (SOCKET)-1)
488  {
489  char buffer[128] = { 0 };
490 #ifdef _WIN32
491  int wsa_error = WSAGetLastError();
492 
493  /* No data available */
494  if (wsa_error == WSAEWOULDBLOCK)
495  continue;
496 
497 #else
498 
499  if (errno == EAGAIN || errno == EWOULDBLOCK)
500  continue;
501 
502 #endif
503  WLog_WARN(TAG, "accept failed with %s", winpr_strerror(errno, buffer, sizeof(buffer)));
504  return FALSE;
505  }
506 
507  if (!freerdp_check_and_create_client(instance, (int)peer_sockfd, &peer_addr))
508  return FALSE;
509  }
510 
511  return TRUE;
512 }
513 
514 freerdp_listener* freerdp_listener_new(void)
515 {
516  freerdp_listener* instance = NULL;
517  rdpListener* listener = NULL;
518  instance = (freerdp_listener*)calloc(1, sizeof(freerdp_listener));
519 
520  if (!instance)
521  return NULL;
522 
523  instance->Open = freerdp_listener_open;
524  instance->OpenLocal = freerdp_listener_open_local;
525  instance->OpenFromSocket = freerdp_listener_open_from_socket;
526 #if defined(WITH_FREERDP_DEPRECATED)
527  instance->GetFileDescriptor = freerdp_listener_get_fds;
528 #endif
529  instance->GetEventHandles = freerdp_listener_get_event_handles;
530  instance->CheckFileDescriptor = freerdp_listener_check_fds;
531  instance->Close = freerdp_listener_close;
532  listener = (rdpListener*)calloc(1, sizeof(rdpListener));
533 
534  if (!listener)
535  {
536  free(instance);
537  return NULL;
538  }
539 
540  listener->instance = instance;
541  instance->listener = (void*)listener;
542  return instance;
543 }
544 
545 void freerdp_listener_free(freerdp_listener* instance)
546 {
547  if (instance)
548  {
549  free(instance->listener);
550  free(instance);
551  }
552 }