1 /**
2 * xrdp: A Remote Desktop Protocol server.
3 *
4 * Copyright (C) Jay Sorg 2004-2015
5 *
6 * BSD process grouping by:
7 * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland.
8 * Copyright (c) 2000-2001 Markus Friedl.
9 * Copyright (c) 2011-2015 Koichiro Iwao, Kyushu Institute of Technology.
10 *
11 * Licensed under the Apache License, Version 2.0 (the "License");
12 * you may not use this file except in compliance with the License.
13 * You may obtain a copy of the License at
14 *
15 * http://www.apache.org/licenses/LICENSE-2.0
16 *
17 * Unless required by applicable law or agreed to in writing, software
18 * distributed under the License is distributed on an "AS IS" BASIS,
19 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
20 * See the License for the specific language governing permissions and
21 * limitations under the License.
22 */
23
24 /**
25 *
26 * @file session.c
27 * @brief Session management code
28 * @author Jay Sorg, Simone Fedele
29 *
30 */
31
32 #if defined(HAVE_CONFIG_H)
33 #include "config_ac.h"
34 #endif
35
36 #ifdef HAVE_SYS_PRCTL_H
37 #include <sys/prctl.h>
38 #endif
39
40 #include "sesman.h"
41 #include "libscp_types.h"
42 #include "xauth.h"
43 #include "xrdp_sockets.h"
44 #include "string_calls.h"
45
46 #ifndef PR_SET_NO_NEW_PRIVS
47 #define PR_SET_NO_NEW_PRIVS 38
48 #endif
49
50 extern unsigned char g_fixedkey[8];
51 extern struct config_sesman *g_cfg; /* in sesman.c */
52 extern int g_sck; /* in sesman.c */
53 struct session_chain *g_sessions;
54 int g_session_count;
55
56 extern tbus g_term_event; /* in sesman.c */
57
58 /**
59 * Creates a string consisting of all parameters that is hosted in the param list
60 * @param self
61 * @param outstr, allocate this buffer before you use this function
62 * @param len the allocated len for outstr
63 * @return
64 */
65 char *
dumpItemsToString(struct list * self,char * outstr,int len)66 dumpItemsToString(struct list *self, char *outstr, int len)
67 {
68 int index;
69 int totalLen = 0;
70
71 g_memset(outstr, 0, len);
72 if (self->count == 0)
73 {
74 LOG_DEVEL(LOG_LEVEL_TRACE, "List is empty");
75 }
76
77 for (index = 0; index < self->count; index++)
78 {
79 /* +1 = one space*/
80 totalLen = totalLen + g_strlen((char *)list_get_item(self, index)) + 1;
81
82 if (len > totalLen)
83 {
84 g_strcat(outstr, (char *)list_get_item(self, index));
85 g_strcat(outstr, " ");
86 }
87 }
88
89 return outstr ;
90 }
91
92
93 /******************************************************************************/
94 struct session_item *
session_get_bydata(const char * name,int width,int height,int bpp,int type,const char * client_ip)95 session_get_bydata(const char *name, int width, int height, int bpp, int type,
96 const char *client_ip)
97 {
98 struct session_chain *tmp;
99 enum SESMAN_CFG_SESS_POLICY policy = g_cfg->sess.policy;
100
101 tmp = g_sessions;
102
103 /* convert from SCP_SESSION_TYPE namespace to SESMAN_SESSION_TYPE namespace */
104 switch (type)
105 {
106 case SCP_SESSION_TYPE_XVNC: /* 0 */
107 type = SESMAN_SESSION_TYPE_XVNC; /* 2 */
108 break;
109 case SCP_SESSION_TYPE_XRDP: /* 1 */
110 type = SESMAN_SESSION_TYPE_XRDP; /* 1 */
111 break;
112 case SCP_SESSION_TYPE_XORG:
113 type = SESMAN_SESSION_TYPE_XORG;
114 break;
115 default:
116 return 0;
117 }
118
119 LOG(LOG_LEVEL_DEBUG,
120 "session_get_bydata: search policy %d U %s W %d H %d bpp %d T %d IP %s",
121 policy, name, width, height, bpp, type, client_ip);
122
123 while (tmp != 0)
124 {
125 LOG(LOG_LEVEL_DEBUG,
126 "session_get_bydata: try %p U %s W %d H %d bpp %d T %d IP %s",
127 tmp->item,
128 tmp->item->name,
129 tmp->item->width, tmp->item->height,
130 tmp->item->bpp, tmp->item->type,
131 tmp->item->client_ip);
132
133 if (g_strncmp(name, tmp->item->name, 255) == 0 &&
134 (!(policy & SESMAN_CFG_SESS_POLICY_D) ||
135 (tmp->item->width == width && tmp->item->height == height)) &&
136 (!(policy & SESMAN_CFG_SESS_POLICY_I) ||
137 (g_strncmp_d(client_ip, tmp->item->client_ip, ':', 255) == 0)) &&
138 (!(policy & SESMAN_CFG_SESS_POLICY_C) ||
139 (g_strncmp(client_ip, tmp->item->client_ip, 255) == 0)) &&
140 tmp->item->bpp == bpp &&
141 tmp->item->type == type)
142 {
143 return tmp->item;
144 }
145
146 tmp = tmp->next;
147 }
148
149 return 0;
150 }
151
152 /******************************************************************************/
153 /**
154 *
155 * @brief checks if there's a server running on a display
156 * @param display the display to check
157 * @return 0 if there isn't a display running, nonzero otherwise
158 *
159 */
160 static int
x_server_running_check_ports(int display)161 x_server_running_check_ports(int display)
162 {
163 char text[256];
164 int x_running;
165 int sck;
166
167 g_sprintf(text, "/tmp/.X11-unix/X%d", display);
168 x_running = g_file_exist(text);
169
170 if (!x_running)
171 {
172 LOG(LOG_LEVEL_DEBUG, "Did not find a running X server at %s", text);
173 g_sprintf(text, "/tmp/.X%d-lock", display);
174 x_running = g_file_exist(text);
175 }
176
177 if (!x_running) /* check 59xx */
178 {
179 LOG(LOG_LEVEL_DEBUG, "Did not find a running X server at %s", text);
180 if ((sck = g_tcp_socket()) != -1)
181 {
182 g_sprintf(text, "59%2.2d", display);
183 x_running = g_tcp_bind(sck, text);
184 g_tcp_close(sck);
185 }
186 }
187
188 if (!x_running) /* check 60xx */
189 {
190 LOG(LOG_LEVEL_DEBUG, "Did not find a running X server at %s", text);
191 if ((sck = g_tcp_socket()) != -1)
192 {
193 g_sprintf(text, "60%2.2d", display);
194 x_running = g_tcp_bind(sck, text);
195 g_tcp_close(sck);
196 }
197 }
198
199 if (!x_running) /* check 62xx */
200 {
201 LOG(LOG_LEVEL_DEBUG, "Did not find a running X server at %s", text);
202 if ((sck = g_tcp_socket()) != -1)
203 {
204 g_sprintf(text, "62%2.2d", display);
205 x_running = g_tcp_bind(sck, text);
206 g_tcp_close(sck);
207 }
208 }
209
210 if (!x_running)
211 {
212 LOG(LOG_LEVEL_DEBUG, "Did not find a running X server at %s", text);
213 g_sprintf(text, XRDP_CHANSRV_STR, display);
214 x_running = g_file_exist(text);
215 }
216
217 if (!x_running)
218 {
219 LOG(LOG_LEVEL_DEBUG, "Did not find a running X server at %s", text);
220 g_sprintf(text, CHANSRV_PORT_OUT_STR, display);
221 x_running = g_file_exist(text);
222 }
223
224 if (!x_running)
225 {
226 LOG(LOG_LEVEL_DEBUG, "Did not find a running X server at %s", text);
227 g_sprintf(text, CHANSRV_PORT_IN_STR, display);
228 x_running = g_file_exist(text);
229 }
230
231 if (!x_running)
232 {
233 LOG(LOG_LEVEL_DEBUG, "Did not find a running X server at %s", text);
234 g_sprintf(text, CHANSRV_API_STR, display);
235 x_running = g_file_exist(text);
236 }
237
238 if (!x_running)
239 {
240 LOG(LOG_LEVEL_DEBUG, "Did not find a running X server at %s", text);
241 g_sprintf(text, XRDP_X11RDP_STR, display);
242 x_running = g_file_exist(text);
243 }
244
245 if (x_running)
246 {
247 LOG(LOG_LEVEL_INFO, "Found X server running at %s", text);
248 }
249
250 return x_running;
251 }
252
253 /******************************************************************************/
254 /**
255 *
256 * @brief checks if there's a server running on a display
257 * @param display the display to check
258 * @return 0 if there isn't a display running, nonzero otherwise
259 *
260 */
261 static int
x_server_running(int display)262 x_server_running(int display)
263 {
264 char text[256];
265 int x_running;
266
267 g_sprintf(text, "/tmp/.X11-unix/X%d", display);
268 x_running = g_file_exist(text);
269
270 if (!x_running)
271 {
272 LOG(LOG_LEVEL_DEBUG, "Did not find a running X server at %s", text);
273 g_sprintf(text, "/tmp/.X%d-lock", display);
274 x_running = g_file_exist(text);
275 }
276
277 if (x_running)
278 {
279 LOG(LOG_LEVEL_INFO, "Found X server running at %s", text);
280 }
281 else
282 {
283 LOG(LOG_LEVEL_DEBUG, "Did not find a running X server at %s", text);
284 }
285
286 return x_running;
287 }
288
289 /******************************************************************************/
290 /* called with the main thread
291 returns boolean */
292 static int
session_is_display_in_chain(int display)293 session_is_display_in_chain(int display)
294 {
295 struct session_chain *chain;
296 struct session_item *item;
297
298 chain = g_sessions;
299
300 while (chain != 0)
301 {
302 item = chain->item;
303
304 if (item->display == display)
305 {
306 return 1;
307 }
308
309 chain = chain->next;
310 }
311
312 return 0;
313 }
314
315 /******************************************************************************/
316 /* called with the main thread */
317 static int
session_get_avail_display_from_chain(void)318 session_get_avail_display_from_chain(void)
319 {
320 int display;
321
322 display = g_cfg->sess.x11_display_offset;
323
324 while ((display - g_cfg->sess.x11_display_offset) <= g_cfg->sess.max_sessions)
325 {
326 if (!session_is_display_in_chain(display))
327 {
328 if (!x_server_running_check_ports(display))
329 {
330 return display;
331 }
332 }
333
334 display++;
335 }
336
337 LOG(LOG_LEVEL_ERROR, "X server -- no display in range (%d to %d) is available",
338 g_cfg->sess.x11_display_offset,
339 g_cfg->sess.x11_display_offset + g_cfg->sess.max_sessions);
340 return 0;
341 }
342
343 /******************************************************************************/
344 static int
wait_for_xserver(int display)345 wait_for_xserver(int display)
346 {
347 int i;
348
349 /* give X a bit to start */
350 /* wait up to 10 secs for x server to start */
351 i = 0;
352
353 LOG(LOG_LEVEL_DEBUG, "Waiting for X server to start on display %d", display);
354
355 while (!x_server_running(display))
356 {
357 i++;
358
359 if (i > 40)
360 {
361 LOG(LOG_LEVEL_WARNING,
362 "Timed out waiting for X server on display %d to startup",
363 display);
364 break;
365 }
366
367 g_sleep(250);
368 }
369
370 return 0;
371 }
372
373 /******************************************************************************/
374 static int
session_start_chansrv(char * username,int display)375 session_start_chansrv(char *username, int display)
376 {
377 struct list *chansrv_params;
378 char exe_path[262];
379 int chansrv_pid;
380
381 chansrv_pid = g_fork();
382 if (chansrv_pid == 0)
383 {
384 LOG(LOG_LEVEL_INFO,
385 "Starting the xrdp channel server for display %d", display);
386
387 chansrv_params = list_create();
388 chansrv_params->auto_free = 1;
389
390 /* building parameters */
391 g_snprintf(exe_path, sizeof(exe_path), "%s/xrdp-chansrv",
392 XRDP_SBIN_PATH);
393
394 list_add_item(chansrv_params, (intptr_t) g_strdup(exe_path));
395 list_add_item(chansrv_params, 0); /* mandatory */
396
397 env_set_user(username, 0, display,
398 g_cfg->env_names,
399 g_cfg->env_values);
400
401 /* executing chansrv */
402 g_execvp(exe_path, (char **) (chansrv_params->items));
403
404 /* should not get here */
405 list_delete(chansrv_params);
406 g_exit(1);
407 }
408 return chansrv_pid;
409 }
410
411 /******************************************************************************/
412 /* called with the main thread */
413 static int
session_start_fork(tbus data,tui8 type,struct SCP_CONNECTION * c,struct SCP_SESSION * s)414 session_start_fork(tbus data, tui8 type, struct SCP_CONNECTION *c,
415 struct SCP_SESSION *s)
416 {
417 int display = 0;
418 int pid = 0;
419 char geometry[32];
420 char depth[32];
421 char screen[32]; /* display number */
422 char text[256];
423 char execvpparams[2048];
424 char *xserver = NULL; /* absolute/relative path to Xorg/X11rdp/Xvnc */
425 char *passwd_file;
426 char **pp1 = (char **)NULL;
427 struct session_chain *temp = (struct session_chain *)NULL;
428 struct list *xserver_params = (struct list *)NULL;
429 struct tm stime;
430 time_t ltime;
431 char authfile[256]; /* The filename for storing xauth informations */
432 int chansrv_pid;
433 int display_pid;
434 int window_manager_pid;
435
436 /* initialize (zero out) local variables: */
437 g_memset(<ime, 0, sizeof(time_t));
438 g_memset(&stime, 0, sizeof(struct tm));
439 g_memset(geometry, 0, sizeof(char) * 32);
440 g_memset(depth, 0, sizeof(char) * 32);
441 g_memset(screen, 0, sizeof(char) * 32);
442 g_memset(text, 0, sizeof(char) * 256);
443
444 passwd_file = 0;
445
446 /* check to limit concurrent sessions */
447 if (g_session_count >= g_cfg->sess.max_sessions)
448 {
449 LOG(LOG_LEVEL_ERROR, "max concurrent session limit "
450 "exceeded. login for user %s denied", s->username);
451 return 0;
452 }
453
454 temp = (struct session_chain *)g_malloc(sizeof(struct session_chain), 0);
455
456 if (temp == 0)
457 {
458 LOG(LOG_LEVEL_ERROR, "Out of memory error: cannot create new session "
459 "chain element - user %s", s->username);
460 return 0;
461 }
462
463 temp->item = (struct session_item *)g_malloc(sizeof(struct session_item), 0);
464
465 if (temp->item == 0)
466 {
467 g_free(temp);
468 LOG(LOG_LEVEL_ERROR, "Out of memory error: cannot create new session "
469 "item - user %s", s->username);
470 return 0;
471 }
472
473 display = session_get_avail_display_from_chain();
474
475 if (display == 0)
476 {
477 g_free(temp->item);
478 g_free(temp);
479 return 0;
480 }
481
482 pid = g_fork(); /* parent is fork from tcp accept,
483 child forks X and wm, then becomes scp */
484
485 if (pid == -1)
486 {
487 LOG(LOG_LEVEL_ERROR,
488 "[session start] (display %d): Failed to fork for scp with "
489 "errno: %d, description: %s",
490 display, g_get_errno(), g_get_strerror());
491 }
492 else if (pid == 0)
493 {
494 LOG(LOG_LEVEL_INFO,
495 "[session start] (display %d): calling auth_start_session from pid %d",
496 display, g_getpid());
497 auth_start_session(data, display);
498 g_delete_wait_obj(g_term_event);
499 g_tcp_close(g_sck);
500 g_tcp_close(c->in_sck);
501 g_sprintf(geometry, "%dx%d", s->width, s->height);
502 g_sprintf(depth, "%d", s->bpp);
503 g_sprintf(screen, ":%d", display);
504 #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
505 /*
506 * FreeBSD bug
507 * ports/157282: effective login name is not set by xrdp-sesman
508 * http://www.freebsd.org/cgi/query-pr.cgi?pr=157282
509 *
510 * from:
511 * $OpenBSD: session.c,v 1.252 2010/03/07 11:57:13 dtucker Exp $
512 * with some ideas about BSD process grouping to xrdp
513 */
514 pid_t bsdsespid = g_fork();
515
516 if (bsdsespid == -1)
517 {
518 }
519 else if (bsdsespid == 0) /* BSD session leader */
520 {
521 /**
522 * Create a new session and process group since the 4.4BSD
523 * setlogin() affects the entire process group
524 */
525 if (g_setsid() < 0)
526 {
527 LOG(LOG_LEVEL_WARNING,
528 "[session start] (display %d): setsid failed - pid %d",
529 display, g_getpid());
530 }
531
532 if (g_setlogin(s->username) < 0)
533 {
534 LOG(LOG_LEVEL_WARNING,
535 "[session start] (display %d): setlogin failed for user %s - pid %d",
536 display, s->username, g_getpid());
537 }
538 }
539
540 g_waitpid(bsdsespid);
541
542 if (bsdsespid > 0)
543 {
544 g_exit(0);
545 /*
546 * intermediate sesman should exit here after WM exits.
547 * do not execure the following codes.
548 */
549 }
550 #endif
551 window_manager_pid = g_fork(); /* parent becomes X,
552 child forks wm, and waits, todo */
553 if (window_manager_pid == -1)
554 {
555 LOG(LOG_LEVEL_ERROR,
556 "Failed to fork for the window manager on display %d", display);
557 }
558 else if (window_manager_pid == 0)
559 {
560 wait_for_xserver(display);
561 env_set_user(s->username,
562 0,
563 display,
564 g_cfg->env_names,
565 g_cfg->env_values);
566 if (x_server_running(display))
567 {
568 auth_set_env(data);
569 if (s->directory != 0)
570 {
571 if (s->directory[0] != 0)
572 {
573 g_set_current_dir(s->directory);
574 }
575 }
576 if (s->program != 0 && s->program[0] != 0)
577 {
578 if (g_strchr(s->program, ' ') != 0 || g_strchr(s->program, '\t') != 0)
579 {
580 LOG(LOG_LEVEL_INFO,
581 "Starting user requested window manager on "
582 "display %d with embeded arguments using a shell: %s",
583 display, s->program);
584 const char *params[] = {"sh", "-c", s->program, NULL};
585 g_execvp("/bin/sh", (char **)params);
586 }
587 else
588 {
589 LOG(LOG_LEVEL_INFO,
590 "Starting user requested window manager on "
591 "display %d: %s", display, s->program);
592 g_execlp3(s->program, s->program, 0);
593 }
594 }
595 else
596 {
597 LOG(LOG_LEVEL_DEBUG, "The user session on display %d did "
598 "not request a specific window manager", display);
599 }
600
601 /* try to execute user window manager if enabled */
602 if (g_cfg->enable_user_wm)
603 {
604 g_sprintf(text, "%s/%s", g_getenv("HOME"), g_cfg->user_wm);
605 if (g_file_exist(text))
606 {
607 LOG(LOG_LEVEL_INFO,
608 "Starting window manager on display %d"
609 "from user home directory: %s", display, text);
610 g_execlp3(text, g_cfg->user_wm, 0);
611 }
612 else
613 {
614 LOG(LOG_LEVEL_DEBUG,
615 "The user home directory window manager configuration "
616 "is enabled but window manager program does not exist: %s",
617 text);
618 }
619 }
620
621 LOG(LOG_LEVEL_INFO,
622 "Starting the default window manager on display %d: %s",
623 display, g_cfg->default_wm);
624 g_execlp3(g_cfg->default_wm, g_cfg->default_wm, 0);
625
626 /* still a problem starting window manager just start xterm */
627 LOG(LOG_LEVEL_WARNING,
628 "No window manager on display %d started, "
629 "so falling back to starting xterm for user debugging",
630 display);
631 g_execlp3("xterm", "xterm", 0);
632
633 /* should not get here */
634 }
635 else
636 {
637 LOG(LOG_LEVEL_ERROR,
638 "There is no X server active on display %d", display);
639 }
640
641 LOG(LOG_LEVEL_ERROR, "A fatal error has occured attempting to start "
642 "the window manager on display %d, aborting connection",
643 display);
644 g_exit(0);
645 }
646 else
647 {
648 display_pid = g_fork(); /* parent becomes scp,
649 child becomes X */
650 if (display_pid == -1)
651 {
652 LOG(LOG_LEVEL_ERROR,
653 "Failed to fork for the X server on display %d", display);
654 }
655 else if (display_pid == 0) /* child */
656 {
657 if (type == SESMAN_SESSION_TYPE_XVNC)
658 {
659 env_set_user(s->username,
660 &passwd_file,
661 display,
662 g_cfg->env_names,
663 g_cfg->env_values);
664 }
665 else
666 {
667 env_set_user(s->username,
668 0,
669 display,
670 g_cfg->env_names,
671 g_cfg->env_values);
672 }
673
674 /* setting Xserver environment variables */
675 g_snprintf(text, 255, "%d", g_cfg->sess.max_idle_time);
676 g_setenv("XRDP_SESMAN_MAX_IDLE_TIME", text, 1);
677 g_snprintf(text, 255, "%d", g_cfg->sess.max_disc_time);
678 g_setenv("XRDP_SESMAN_MAX_DISC_TIME", text, 1);
679 g_snprintf(text, 255, "%d", g_cfg->sess.kill_disconnected);
680 g_setenv("XRDP_SESMAN_KILL_DISCONNECTED", text, 1);
681 g_setenv("XRDP_SOCKET_PATH", XRDP_SOCKET_PATH, 1);
682
683 /* prepare the Xauthority stuff */
684 if (g_getenv("XAUTHORITY") != NULL)
685 {
686 g_snprintf(authfile, 255, "%s", g_getenv("XAUTHORITY"));
687 }
688 else
689 {
690 g_snprintf(authfile, 255, "%s", ".Xauthority");
691 }
692
693 /* Add the entry in XAUTHORITY file or exit if error */
694 if (add_xauth_cookie(display, authfile) != 0)
695 {
696 LOG(LOG_LEVEL_ERROR,
697 "Error setting the xauth cookie for display %d in file %s",
698 display, authfile);
699
700 LOG(LOG_LEVEL_ERROR, "A fatal error has occured attempting to start "
701 "the X server on display %d, aborting connection",
702 display);
703 g_exit(1);
704 }
705
706 if (type == SESMAN_SESSION_TYPE_XORG)
707 {
708 #ifdef HAVE_SYS_PRCTL_H
709 /*
710 * Make sure Xorg doesn't run setuid root. Root access is not
711 * needed. Xorg can fail when run as root and the user has no
712 * console permissions.
713 * PR_SET_NO_NEW_PRIVS requires Linux kernel 3.5 and newer.
714 */
715 if (prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0) < 0)
716 {
717 LOG(LOG_LEVEL_WARNING,
718 "[session start] (display %d): Failed to disable "
719 "setuid on X server: %s",
720 display, g_get_strerror());
721 }
722 #endif
723
724 xserver_params = list_create();
725 xserver_params->auto_free = 1;
726
727 /* get path of Xorg from config */
728 xserver = g_strdup((const char *)list_get_item(g_cfg->xorg_params, 0));
729
730 /* these are the must have parameters */
731 list_add_item(xserver_params, (tintptr) g_strdup(xserver));
732 list_add_item(xserver_params, (tintptr) g_strdup(screen));
733 list_add_item(xserver_params, (tintptr) g_strdup("-auth"));
734 list_add_item(xserver_params, (tintptr) g_strdup(authfile));
735
736 /* additional parameters from sesman.ini file */
737 list_append_list_strdup(g_cfg->xorg_params, xserver_params, 1);
738
739 /* make sure it ends with a zero */
740 list_add_item(xserver_params, 0);
741
742 pp1 = (char **) xserver_params->items;
743
744 /* some args are passed via env vars */
745 g_sprintf(geometry, "%d", s->width);
746 g_setenv("XRDP_START_WIDTH", geometry, 1);
747
748 g_sprintf(geometry, "%d", s->height);
749 g_setenv("XRDP_START_HEIGHT", geometry, 1);
750 }
751 else if (type == SESMAN_SESSION_TYPE_XVNC)
752 {
753 char guid_str[64];
754 g_bytes_to_hexstr(s->guid, 16, guid_str, 64);
755 env_check_password_file(passwd_file, guid_str);
756 xserver_params = list_create();
757 xserver_params->auto_free = 1;
758
759 /* get path of Xvnc from config */
760 xserver = g_strdup((const char *)list_get_item(g_cfg->vnc_params, 0));
761
762 /* these are the must have parameters */
763 list_add_item(xserver_params, (tintptr)g_strdup(xserver));
764 list_add_item(xserver_params, (tintptr)g_strdup(screen));
765 list_add_item(xserver_params, (tintptr)g_strdup("-auth"));
766 list_add_item(xserver_params, (tintptr)g_strdup(authfile));
767 list_add_item(xserver_params, (tintptr)g_strdup("-geometry"));
768 list_add_item(xserver_params, (tintptr)g_strdup(geometry));
769 list_add_item(xserver_params, (tintptr)g_strdup("-depth"));
770 list_add_item(xserver_params, (tintptr)g_strdup(depth));
771 list_add_item(xserver_params, (tintptr)g_strdup("-rfbauth"));
772 list_add_item(xserver_params, (tintptr)g_strdup(passwd_file));
773
774 g_free(passwd_file);
775
776 /* additional parameters from sesman.ini file */
777 //config_read_xserver_params(SESMAN_SESSION_TYPE_XVNC,
778 // xserver_params);
779 list_append_list_strdup(g_cfg->vnc_params, xserver_params, 1);
780
781 /* make sure it ends with a zero */
782 list_add_item(xserver_params, 0);
783 pp1 = (char **)xserver_params->items;
784 }
785 else if (type == SESMAN_SESSION_TYPE_XRDP)
786 {
787 xserver_params = list_create();
788 xserver_params->auto_free = 1;
789
790 /* get path of X11rdp from config */
791 xserver = g_strdup((const char *)list_get_item(g_cfg->rdp_params, 0));
792
793 /* these are the must have parameters */
794 list_add_item(xserver_params, (tintptr)g_strdup(xserver));
795 list_add_item(xserver_params, (tintptr)g_strdup(screen));
796 list_add_item(xserver_params, (tintptr)g_strdup("-auth"));
797 list_add_item(xserver_params, (tintptr)g_strdup(authfile));
798 list_add_item(xserver_params, (tintptr)g_strdup("-geometry"));
799 list_add_item(xserver_params, (tintptr)g_strdup(geometry));
800 list_add_item(xserver_params, (tintptr)g_strdup("-depth"));
801 list_add_item(xserver_params, (tintptr)g_strdup(depth));
802
803 /* additional parameters from sesman.ini file */
804 //config_read_xserver_params(SESMAN_SESSION_TYPE_XRDP,
805 // xserver_params);
806 list_append_list_strdup(g_cfg->rdp_params, xserver_params, 1);
807
808 /* make sure it ends with a zero */
809 list_add_item(xserver_params, 0);
810 pp1 = (char **)xserver_params->items;
811 }
812 else
813 {
814 LOG(LOG_LEVEL_ERROR, "Unknown session type: %d", type);
815 LOG(LOG_LEVEL_ERROR, "A fatal error has occured attempting "
816 "to start the X server on display %d, aborting connection",
817 display);
818 g_exit(1);
819 }
820
821 /* fire up X server */
822 LOG(LOG_LEVEL_INFO, "Starting X server on display %d: %s",
823 display, dumpItemsToString(xserver_params, execvpparams, 2048));
824 g_execvp(xserver, pp1);
825
826 /* should not get here */
827 LOG(LOG_LEVEL_ERROR,
828 "Error starting X server on display %d", display);
829 LOG(LOG_LEVEL_ERROR, "A fatal error has occured attempting "
830 "to start the X server on display %d, aborting connection",
831 display);
832
833 list_delete(xserver_params);
834 g_exit(1);
835 }
836 else
837 {
838 int wm_wait_time;
839 struct exit_status wm_exit_status;
840 struct exit_status xserver_exit_status;
841 struct exit_status chansrv_exit_status;
842
843 wait_for_xserver(display);
844 chansrv_pid = session_start_chansrv(s->username, display);
845
846 LOG(LOG_LEVEL_INFO,
847 "Session started successfully for user %s on display %d",
848 s->username, display);
849
850 /* Monitor the amount of time we wait for the
851 * window manager. This is approximately how long the window
852 * manager was running for */
853 LOG(LOG_LEVEL_INFO, "Session in progress on display %d, waiting "
854 "until the window manager (pid %d) exits to end the session",
855 display, window_manager_pid);
856 wm_wait_time = g_time1();
857 wm_exit_status = g_waitpid_status(window_manager_pid);
858 wm_wait_time = g_time1() - wm_wait_time;
859 if (wm_exit_status.exit_code > 0)
860 {
861 LOG(LOG_LEVEL_WARNING, "Window manager (pid %d, display %d) "
862 "exited with non-zero exit code %d and signal %d. This "
863 "could indicate a window manager config problem",
864 window_manager_pid, display, wm_exit_status.exit_code,
865 wm_exit_status.signal_no);
866 }
867 if (wm_wait_time < 10)
868 {
869 /* This could be a config issue. Log a significant error */
870 LOG(LOG_LEVEL_WARNING, "Window manager (pid %d, display %d) "
871 "exited quickly (%d secs). This could indicate a window "
872 "manager config problem",
873 window_manager_pid, display, wm_wait_time);
874 }
875 else
876 {
877 LOG(LOG_LEVEL_DEBUG, "Window manager (pid %d, display %d) "
878 "was running for %d seconds.",
879 window_manager_pid, display, wm_wait_time);
880 }
881 LOG(LOG_LEVEL_INFO,
882 "Calling auth_stop_session and auth_end from pid %d",
883 g_getpid());
884 auth_stop_session(data);
885 auth_end(data);
886
887 LOG(LOG_LEVEL_INFO,
888 "Terminating X server (pid %d) on display %d",
889 display_pid, display);
890 g_sigterm(display_pid);
891
892 LOG(LOG_LEVEL_INFO, "Terminating the xrdp channel server (pid %d) "
893 "on display %d", chansrv_pid, display);
894 g_sigterm(chansrv_pid);
895
896 /* make sure socket cleanup happen after child process exit */
897 xserver_exit_status = g_waitpid_status(display_pid);
898 LOG(LOG_LEVEL_INFO,
899 "X server on display %d (pid %d) returned exit code %d "
900 "and signal number %d",
901 display, display_pid, xserver_exit_status.exit_code,
902 xserver_exit_status.signal_no);
903
904 chansrv_exit_status = g_waitpid_status(chansrv_pid);
905 LOG(LOG_LEVEL_INFO,
906 "xrdp channel server for display %d (pid %d) "
907 "exit code %d and signal number %d",
908 display, chansrv_pid, chansrv_exit_status.exit_code,
909 chansrv_exit_status.signal_no);
910
911 cleanup_sockets(display);
912 g_deinit();
913 g_exit(0);
914 }
915 }
916 }
917 else
918 {
919 LOG(LOG_LEVEL_INFO, "Starting session: session_pid %d, "
920 "display :%d.0, width %d, height %d, bpp %d, client ip %s, "
921 "user name %s",
922 pid, display, s->width, s->height, s->bpp, s->client_ip, s->username);
923 temp->item->pid = pid;
924 temp->item->display = display;
925 temp->item->width = s->width;
926 temp->item->height = s->height;
927 temp->item->bpp = s->bpp;
928 temp->item->data = data;
929 g_strncpy(temp->item->client_ip, s->client_ip, 255); /* store client ip data */
930 g_strncpy(temp->item->name, s->username, 255);
931 g_memcpy(temp->item->guid, s->guid, 16);
932
933 ltime = g_time1();
934 localtime_r(<ime, &stime);
935 temp->item->connect_time.year = (tui16)(stime.tm_year + 1900);
936 temp->item->connect_time.month = (tui8)(stime.tm_mon + 1);
937 temp->item->connect_time.day = (tui8)stime.tm_mday;
938 temp->item->connect_time.hour = (tui8)stime.tm_hour;
939 temp->item->connect_time.minute = (tui8)stime.tm_min;
940 zero_time(&(temp->item->disconnect_time));
941 zero_time(&(temp->item->idle_time));
942
943 temp->item->type = type;
944 temp->item->status = SESMAN_SESSION_STATUS_ACTIVE;
945
946 temp->next = g_sessions;
947 g_sessions = temp;
948 g_session_count++;
949
950 return display;
951 }
952
953 g_free(temp->item);
954 g_free(temp);
955 return display;
956 }
957
958 /******************************************************************************/
959 /* called with the main thread */
960 static int
session_reconnect_fork(int display,char * username,long data)961 session_reconnect_fork(int display, char *username, long data)
962 {
963 int pid;
964
965 pid = g_fork();
966
967 if (pid == -1)
968 {
969 LOG(LOG_LEVEL_ERROR, "Failed to fork for session reconnection script");
970 }
971 else if (pid == 0)
972 {
973 env_set_user(username,
974 0,
975 display,
976 g_cfg->env_names,
977 g_cfg->env_values);
978 auth_set_env(data);
979
980 if (g_file_exist(g_cfg->reconnect_sh))
981 {
982 LOG(LOG_LEVEL_INFO,
983 "Starting session reconnection script on display %d: %s",
984 display, g_cfg->reconnect_sh);
985 g_execlp3(g_cfg->reconnect_sh, g_cfg->reconnect_sh, 0);
986
987 /* should not get here */
988 LOG(LOG_LEVEL_ERROR,
989 "Error starting session reconnection script on display %d: %s",
990 display, g_cfg->reconnect_sh);
991 }
992 else
993 {
994 LOG(LOG_LEVEL_WARNING,
995 "Session reconnection script file does not exist: %s",
996 g_cfg->reconnect_sh);
997 }
998
999 /* TODO: why is this existing with a success error code when the
1000 reconnect script failed to be executed? */
1001 g_exit(0);
1002 }
1003
1004 return display;
1005 }
1006
1007 /******************************************************************************/
1008 /* called by a worker thread, ask the main thread to call session_sync_start
1009 and wait till done */
1010 int
session_start(long data,tui8 type,struct SCP_CONNECTION * c,struct SCP_SESSION * s)1011 session_start(long data, tui8 type, struct SCP_CONNECTION *c,
1012 struct SCP_SESSION *s)
1013 {
1014 return session_start_fork(data, type, c, s);
1015 }
1016
1017 /******************************************************************************/
1018 /* called by a worker thread, ask the main thread to call session_sync_start
1019 and wait till done */
1020 int
session_reconnect(int display,char * username,long data)1021 session_reconnect(int display, char *username, long data)
1022 {
1023 return session_reconnect_fork(display, username, data);
1024 }
1025
1026 /******************************************************************************/
1027 int
session_kill(int pid)1028 session_kill(int pid)
1029 {
1030 struct session_chain *tmp;
1031 struct session_chain *prev;
1032
1033 tmp = g_sessions;
1034 prev = 0;
1035
1036 while (tmp != 0)
1037 {
1038 if (tmp->item == 0)
1039 {
1040 LOG(LOG_LEVEL_ERROR, "session descriptor for "
1041 "pid %d is null!", pid);
1042
1043 if (prev == 0)
1044 {
1045 /* prev does no exist, so it's the first element - so we set
1046 g_sessions */
1047 g_sessions = tmp->next;
1048 }
1049 else
1050 {
1051 prev->next = tmp->next;
1052 }
1053
1054 return SESMAN_SESSION_KILL_NULLITEM;
1055 }
1056
1057 if (tmp->item->pid == pid)
1058 {
1059 /* deleting the session */
1060 LOG(LOG_LEVEL_INFO,
1061 "++ terminated session: username %s, display :%d.0, session_pid %d, ip %s",
1062 tmp->item->name, tmp->item->display, tmp->item->pid, tmp->item->client_ip);
1063 g_free(tmp->item);
1064
1065 if (prev == 0)
1066 {
1067 /* prev does no exist, so it's the first element - so we set
1068 g_sessions */
1069 g_sessions = tmp->next;
1070 }
1071 else
1072 {
1073 prev->next = tmp->next;
1074 }
1075
1076 g_free(tmp);
1077 g_session_count--;
1078 return SESMAN_SESSION_KILL_OK;
1079 }
1080
1081 /* go on */
1082 prev = tmp;
1083 tmp = tmp->next;
1084 }
1085
1086 return SESMAN_SESSION_KILL_NOTFOUND;
1087 }
1088
1089 /******************************************************************************/
1090 void
session_sigkill_all(void)1091 session_sigkill_all(void)
1092 {
1093 struct session_chain *tmp;
1094
1095 tmp = g_sessions;
1096
1097 while (tmp != 0)
1098 {
1099 if (tmp->item == 0)
1100 {
1101 LOG(LOG_LEVEL_ERROR, "found null session descriptor!");
1102 }
1103 else
1104 {
1105 g_sigterm(tmp->item->pid);
1106 }
1107
1108 /* go on */
1109 tmp = tmp->next;
1110 }
1111 }
1112
1113 /******************************************************************************/
1114 struct session_item *
session_get_bypid(int pid)1115 session_get_bypid(int pid)
1116 {
1117 struct session_chain *tmp;
1118 struct session_item *dummy;
1119
1120 dummy = g_new0(struct session_item, 1);
1121
1122 if (0 == dummy)
1123 {
1124 LOG(LOG_LEVEL_ERROR, "session_get_bypid: out of memory");
1125 return 0;
1126 }
1127
1128 tmp = g_sessions;
1129
1130 while (tmp != 0)
1131 {
1132 if (tmp->item == 0)
1133 {
1134 LOG(LOG_LEVEL_ERROR, "session descriptor for pid %d is null!", pid);
1135 g_free(dummy);
1136 return 0;
1137 }
1138
1139 if (tmp->item->pid == pid)
1140 {
1141 g_memcpy(dummy, tmp->item, sizeof(struct session_item));
1142 return dummy;
1143 }
1144
1145 /* go on */
1146 tmp = tmp->next;
1147 }
1148
1149 g_free(dummy);
1150 return 0;
1151 }
1152
1153 /******************************************************************************/
1154 struct SCP_DISCONNECTED_SESSION *
session_get_byuser(const char * user,int * cnt,unsigned char flags)1155 session_get_byuser(const char *user, int *cnt, unsigned char flags)
1156 {
1157 struct session_chain *tmp;
1158 struct SCP_DISCONNECTED_SESSION *sess;
1159 int count;
1160 int index;
1161
1162 count = 0;
1163
1164 tmp = g_sessions;
1165
1166 LOG(LOG_LEVEL_DEBUG, "searching for session by user: %s", user);
1167 while (tmp != 0)
1168 {
1169 if ((NULL == user) || (!g_strncasecmp(user, tmp->item->name, 256)))
1170 {
1171 LOG(LOG_LEVEL_DEBUG, "session_get_byuser: status=%d, flags=%d, "
1172 "result=%d", (tmp->item->status), flags,
1173 ((tmp->item->status) & flags));
1174
1175 if ((tmp->item->status) & flags)
1176 {
1177 count++;
1178 }
1179 }
1180
1181 /* go on */
1182 tmp = tmp->next;
1183 }
1184
1185 if (count == 0)
1186 {
1187 (*cnt) = 0;
1188 return 0;
1189 }
1190
1191 /* malloc() an array of disconnected sessions */
1192 sess = g_new0(struct SCP_DISCONNECTED_SESSION, count);
1193
1194 if (sess == 0)
1195 {
1196 (*cnt) = 0;
1197 return 0;
1198 }
1199
1200 tmp = g_sessions;
1201 index = 0;
1202
1203 while (tmp != 0)
1204 {
1205 /* #warning FIXME: we should get only disconnected sessions! */
1206 if ((NULL == user) || (!g_strncasecmp(user, tmp->item->name, 256)))
1207 {
1208 if ((tmp->item->status) & flags)
1209 {
1210 (sess[index]).SID = tmp->item->pid;
1211 (sess[index]).type = tmp->item->type;
1212 (sess[index]).height = tmp->item->height;
1213 (sess[index]).width = tmp->item->width;
1214 (sess[index]).bpp = tmp->item->bpp;
1215 /* #warning FIXME: setting idle times and such */
1216 /*(sess[index]).connect_time.year = tmp->item->connect_time.year;
1217 (sess[index]).connect_time.month = tmp->item->connect_time.month;
1218 (sess[index]).connect_time.day = tmp->item->connect_time.day;
1219 (sess[index]).connect_time.hour = tmp->item->connect_time.hour;
1220 (sess[index]).connect_time.minute = tmp->item->connect_time.minute;
1221 (sess[index]).disconnect_time.year = tmp->item->disconnect_time.year;
1222 (sess[index]).disconnect_time.month = tmp->item->disconnect_time.month;
1223 (sess[index]).disconnect_time.day = tmp->item->disconnect_time.day;
1224 (sess[index]).disconnect_time.hour = tmp->item->disconnect_time.hour;
1225 (sess[index]).disconnect_time.minute = tmp->item->disconnect_time.minute;
1226 (sess[index]).idle_time.year = tmp->item->idle_time.year;
1227 (sess[index]).idle_time.month = tmp->item->idle_time.month;
1228 (sess[index]).idle_time.day = tmp->item->idle_time.day;
1229 (sess[index]).idle_time.hour = tmp->item->idle_time.hour;
1230 (sess[index]).idle_time.minute = tmp->item->idle_time.minute;*/
1231 (sess[index]).conn_year = tmp->item->connect_time.year;
1232 (sess[index]).conn_month = tmp->item->connect_time.month;
1233 (sess[index]).conn_day = tmp->item->connect_time.day;
1234 (sess[index]).conn_hour = tmp->item->connect_time.hour;
1235 (sess[index]).conn_minute = tmp->item->connect_time.minute;
1236 (sess[index]).idle_days = tmp->item->idle_time.day;
1237 (sess[index]).idle_hours = tmp->item->idle_time.hour;
1238 (sess[index]).idle_minutes = tmp->item->idle_time.minute;
1239
1240 index++;
1241 }
1242 }
1243
1244 /* go on */
1245 tmp = tmp->next;
1246 }
1247
1248 (*cnt) = count;
1249 return sess;
1250 }
1251
1252 /******************************************************************************/
1253 int
cleanup_sockets(int display)1254 cleanup_sockets(int display)
1255 {
1256 LOG(LOG_LEVEL_INFO, "cleanup_sockets:");
1257 char file[256];
1258 int error;
1259
1260 error = 0;
1261
1262 g_snprintf(file, 255, CHANSRV_PORT_OUT_STR, display);
1263 if (g_file_exist(file))
1264 {
1265 LOG(LOG_LEVEL_DEBUG, "cleanup_sockets: deleting %s", file);
1266 if (g_file_delete(file) == 0)
1267 {
1268 LOG(LOG_LEVEL_WARNING,
1269 "cleanup_sockets: failed to delete %s (%s)",
1270 file, g_get_strerror());
1271 error++;
1272 }
1273 }
1274
1275 g_snprintf(file, 255, CHANSRV_PORT_IN_STR, display);
1276 if (g_file_exist(file))
1277 {
1278 LOG(LOG_LEVEL_DEBUG, "cleanup_sockets: deleting %s", file);
1279 if (g_file_delete(file) == 0)
1280 {
1281 LOG(LOG_LEVEL_WARNING,
1282 "cleanup_sockets: failed to delete %s (%s)",
1283 file, g_get_strerror());
1284 error++;
1285 }
1286 }
1287
1288 g_snprintf(file, 255, XRDP_CHANSRV_STR, display);
1289 if (g_file_exist(file))
1290 {
1291 LOG(LOG_LEVEL_DEBUG, "cleanup_sockets: deleting %s", file);
1292 if (g_file_delete(file) == 0)
1293 {
1294 LOG(LOG_LEVEL_WARNING,
1295 "cleanup_sockets: failed to delete %s (%s)",
1296 file, g_get_strerror());
1297 error++;
1298 }
1299 }
1300
1301 g_snprintf(file, 255, CHANSRV_API_STR, display);
1302 if (g_file_exist(file))
1303 {
1304 LOG(LOG_LEVEL_DEBUG, "cleanup_sockets: deleting %s", file);
1305 if (g_file_delete(file) == 0)
1306 {
1307 LOG(LOG_LEVEL_WARNING,
1308 "cleanup_sockets: failed to delete %s (%s)",
1309 file, g_get_strerror());
1310 error++;
1311 }
1312 }
1313
1314 /* the following files should be deleted by xorgxrdp
1315 * but just in case the deletion failed */
1316
1317 g_snprintf(file, 255, XRDP_X11RDP_STR, display);
1318 if (g_file_exist(file))
1319 {
1320 LOG(LOG_LEVEL_DEBUG, "cleanup_sockets: deleting %s", file);
1321 if (g_file_delete(file) == 0)
1322 {
1323 LOG(LOG_LEVEL_WARNING,
1324 "cleanup_sockets: failed to delete %s (%s)",
1325 file, g_get_strerror());
1326 error++;
1327 }
1328 }
1329
1330 g_snprintf(file, 255, XRDP_DISCONNECT_STR, display);
1331 if (g_file_exist(file))
1332 {
1333 LOG(LOG_LEVEL_DEBUG, "cleanup_sockets: deleting %s", file);
1334 if (g_file_delete(file) == 0)
1335 {
1336 LOG(LOG_LEVEL_WARNING,
1337 "cleanup_sockets: failed to delete %s (%s)",
1338 file, g_get_strerror());
1339 error++;
1340 }
1341 }
1342
1343 return error;
1344
1345 }
1346