1 /**
2  * xrdp: A Remote Desktop Protocol server.
3  *
4  * Copyright (C) Jay Sorg 2004-2014
5  *
6  * Licensed under the Apache License, Version 2.0 (the "License");
7  * you may not use this file except in compliance with the License.
8  * You may obtain a copy of the License at
9  *
10  *     http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing, software
13  * distributed under the License is distributed on an "AS IS" BASIS,
14  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  * See the License for the specific language governing permissions and
16  * limitations under the License.
17  *
18  * main program
19  */
20 
21 #if defined(HAVE_CONFIG_H)
22 #include <config_ac.h>
23 #endif
24 
25 #if defined(_WIN32)
26 #include <windows.h>
27 #endif
28 #include "xrdp.h"
29 
30 static struct xrdp_listen *g_listen = 0;
31 static long g_threadid = 0; /* main threadid */
32 
33 #if defined(_WIN32)
34 static SERVICE_STATUS_HANDLE g_ssh = 0;
35 static SERVICE_STATUS g_service_status;
36 #endif
37 static long g_sync_mutex = 0;
38 static long g_sync1_mutex = 0;
39 static tbus g_term_event = 0;
40 static tbus g_sync_event = 0;
41 /* synchronize stuff */
42 static int g_sync_command = 0;
43 static long g_sync_result = 0;
44 static long g_sync_param1 = 0;
45 static long g_sync_param2 = 0;
46 static long (*g_sync_func)(long param1, long param2);
47 
48 /*****************************************************************************/
49 long
g_xrdp_sync(long (* sync_func)(long param1,long param2),long sync_param1,long sync_param2)50 g_xrdp_sync(long (*sync_func)(long param1, long param2), long sync_param1,
51             long sync_param2)
52 {
53     long sync_result;
54     int sync_command;
55 
56     if (tc_threadid_equal(tc_get_threadid(), g_threadid))
57     {
58         /* this is the main thread, call the function directly */
59         sync_result = sync_func(sync_param1, sync_param2);
60     }
61     else
62     {
63         tc_mutex_lock(g_sync1_mutex);
64         tc_mutex_lock(g_sync_mutex);
65         g_sync_param1 = sync_param1;
66         g_sync_param2 = sync_param2;
67         g_sync_func = sync_func;
68         g_sync_command = 100;
69         tc_mutex_unlock(g_sync_mutex);
70         g_set_wait_obj(g_sync_event);
71 
72         do
73         {
74             g_sleep(100);
75             tc_mutex_lock(g_sync_mutex);
76             sync_command = g_sync_command;
77             sync_result = g_sync_result;
78             tc_mutex_unlock(g_sync_mutex);
79         }
80         while (sync_command != 0);
81 
82         tc_mutex_unlock(g_sync1_mutex);
83     }
84 
85     return sync_result;
86 }
87 
88 /*****************************************************************************/
89 void
xrdp_shutdown(int sig)90 xrdp_shutdown(int sig)
91 {
92     tbus threadid;
93 
94     threadid = tc_get_threadid();
95     g_writeln("shutting down");
96     g_writeln("signal %d threadid %p", sig, threadid);
97 
98     if (!g_is_wait_obj_set(g_term_event))
99     {
100         g_set_wait_obj(g_term_event);
101     }
102 }
103 
104 /*****************************************************************************/
105 int
g_is_term(void)106 g_is_term(void)
107 {
108     return g_is_wait_obj_set(g_term_event);
109 }
110 
111 /*****************************************************************************/
112 void
g_set_term(int in_val)113 g_set_term(int in_val)
114 {
115     if (in_val)
116     {
117         g_set_wait_obj(g_term_event);
118     }
119     else
120     {
121         g_reset_wait_obj(g_term_event);
122     }
123 }
124 
125 /*****************************************************************************/
126 tbus
g_get_term_event(void)127 g_get_term_event(void)
128 {
129     return g_term_event;
130 }
131 
132 /*****************************************************************************/
133 tbus
g_get_sync_event(void)134 g_get_sync_event(void)
135 {
136     return g_sync_event;
137 }
138 
139 /*****************************************************************************/
140 void
pipe_sig(int sig_num)141 pipe_sig(int sig_num)
142 {
143     /* do nothing */
144     g_writeln("got XRDP WIN SIGPIPE(%d)", sig_num);
145 }
146 
147 /*****************************************************************************/
148 void
g_process_waiting_function(void)149 g_process_waiting_function(void)
150 {
151     tc_mutex_lock(g_sync_mutex);
152 
153     if (g_sync_command != 0)
154     {
155         if (g_sync_func != 0)
156         {
157             if (g_sync_command == 100)
158             {
159                 g_sync_result = g_sync_func(g_sync_param1, g_sync_param2);
160             }
161         }
162 
163         g_sync_command = 0;
164     }
165 
166     tc_mutex_unlock(g_sync_mutex);
167 }
168 
169 /* win32 service control functions */
170 #if defined(_WIN32)
171 
172 /*****************************************************************************/
173 VOID WINAPI
MyHandler(DWORD fdwControl)174 MyHandler(DWORD fdwControl)
175 {
176     if (g_ssh == 0)
177     {
178         return;
179     }
180 
181     if (fdwControl == SERVICE_CONTROL_STOP)
182     {
183         g_service_status.dwCurrentState = SERVICE_STOP_PENDING;
184         g_set_term(1);
185     }
186     else if (fdwControl == SERVICE_CONTROL_PAUSE)
187     {
188         /* shouldn't happen */
189     }
190     else if (fdwControl == SERVICE_CONTROL_CONTINUE)
191     {
192         /* shouldn't happen */
193     }
194     else if (fdwControl == SERVICE_CONTROL_INTERROGATE)
195     {
196     }
197     else if (fdwControl == SERVICE_CONTROL_SHUTDOWN)
198     {
199         g_service_status.dwCurrentState = SERVICE_STOP_PENDING;
200         g_set_term(1);
201     }
202 
203     SetServiceStatus(g_ssh, &g_service_status);
204 }
205 
206 /*****************************************************************************/
207 static void
log_event(HANDLE han,char * msg)208 log_event(HANDLE han, char *msg)
209 {
210     ReportEvent(han, EVENTLOG_INFORMATION_TYPE, 0, 0, 0, 1, 0, &msg, 0);
211 }
212 
213 /*****************************************************************************/
214 VOID WINAPI
MyServiceMain(DWORD dwArgc,LPTSTR * lpszArgv)215 MyServiceMain(DWORD dwArgc, LPTSTR *lpszArgv)
216 {
217     WSADATA w;
218     char text[256];
219     int pid;
220     //HANDLE event_han;
221     //  int fd;
222     //  char text[256];
223 
224     //  fd = g_file_open("c:\\temp\\xrdp\\log.txt");
225     //  g_file_write(fd, "hi\r\n", 4);
226     //event_han = RegisterEventSource(0, "xrdp");
227     //log_event(event_han, "hi xrdp log");
228     g_threadid = tc_get_threadid();
229     g_set_current_dir("c:\\temp\\xrdp");
230     g_listen = 0;
231     WSAStartup(2, &w);
232     g_sync_mutex = tc_mutex_create();
233     g_sync1_mutex = tc_mutex_create();
234     pid = g_getpid();
235     g_snprintf(text, 255, "xrdp_%8.8x_main_term", pid);
236     g_term_event = g_create_wait_obj(text);
237     g_snprintf(text, 255, "xrdp_%8.8x_main_sync", pid);
238     g_sync_event = g_create_wait_obj(text);
239     g_memset(&g_service_status, 0, sizeof(SERVICE_STATUS));
240     g_service_status.dwServiceType = SERVICE_WIN32_OWN_PROCESS;
241     g_service_status.dwCurrentState = SERVICE_RUNNING;
242     g_service_status.dwControlsAccepted = SERVICE_CONTROL_INTERROGATE |
243                                           SERVICE_ACCEPT_STOP |
244                                           SERVICE_ACCEPT_SHUTDOWN;
245     g_service_status.dwWin32ExitCode = NO_ERROR;
246     g_service_status.dwServiceSpecificExitCode = 0;
247     g_service_status.dwCheckPoint = 0;
248     g_service_status.dwWaitHint = 0;
249     //  g_sprintf(text, "calling RegisterServiceCtrlHandler\r\n");
250     //  g_file_write(fd, text, g_strlen(text));
251     g_ssh = RegisterServiceCtrlHandler("xrdp", MyHandler);
252 
253     if (g_ssh != 0)
254     {
255         //    g_sprintf(text, "ok\r\n");
256         //    g_file_write(fd, text, g_strlen(text));
257         SetServiceStatus(g_ssh, &g_service_status);
258         g_listen = xrdp_listen_create();
259         xrdp_listen_main_loop(g_listen);
260         g_sleep(100);
261         g_service_status.dwCurrentState = SERVICE_STOPPED;
262         SetServiceStatus(g_ssh, &g_service_status);
263     }
264     else
265     {
266         //g_sprintf(text, "RegisterServiceCtrlHandler failed\r\n");
267         //g_file_write(fd, text, g_strlen(text));
268     }
269 
270     xrdp_listen_delete(g_listen);
271     tc_mutex_delete(g_sync_mutex);
272     tc_mutex_delete(g_sync1_mutex);
273     g_destroy_wait_obj(g_term_event);
274     g_destroy_wait_obj(g_sync_event);
275     WSACleanup();
276     //CloseHandle(event_han);
277 }
278 
279 #endif
280 /*****************************************************************************/
281 int
main(int argc,char ** argv)282 main(int argc, char **argv)
283 {
284     int test;
285     int host_be;
286 #if defined(_WIN32)
287     WSADATA w;
288     SC_HANDLE sc_man;
289     SC_HANDLE sc_ser;
290     int run_as_service;
291     SERVICE_TABLE_ENTRY te[2];
292 #else
293     int pid;
294     int fd;
295     int no_daemon;
296     char text[256];
297     char pid_file[256];
298 #endif
299 
300     g_init();
301     ssl_init();
302     /* check compiled endian with actual endian */
303     test = 1;
304     host_be = !((int)(*(unsigned char *)(&test)));
305 #if defined(B_ENDIAN)
306 
307     if (!host_be)
308 #endif
309 #if defined(L_ENDIAN)
310         if (host_be)
311 #endif
312         {
313             g_writeln("endian wrong, edit arch.h");
314             return 0;
315         }
316 
317     /* check long, int and void* sizes */
318     if (sizeof(int) != 4)
319     {
320         g_writeln("unusable int size, must be 4");
321         return 0;
322     }
323 
324     if (sizeof(long) != sizeof(void *))
325     {
326         g_writeln("long size must match void* size");
327         return 0;
328     }
329 
330     if (sizeof(long) != 4 && sizeof(long) != 8)
331     {
332         g_writeln("unusable long size, must be 4 or 8");
333         return 0;
334     }
335 
336     if (sizeof(tui64) != 8)
337     {
338         g_writeln("unusable tui64 size, must be 8");
339         return 0;
340     }
341 
342 #if defined(_WIN32)
343     run_as_service = 1;
344 
345     if (argc == 2)
346     {
347         if (g_strncasecmp(argv[1], "-help", 255) == 0 ||
348                 g_strncasecmp(argv[1], "--help", 255) == 0 ||
349                 g_strncasecmp(argv[1], "-h", 255) == 0)
350         {
351             g_writeln("%s", "");
352             g_writeln("xrdp: A Remote Desktop Protocol server.");
353             g_writeln("Copyright (C) Jay Sorg 2004-2011");
354             g_writeln("See http://www.xrdp.org for more information.");
355             g_writeln("%s", "");
356             g_writeln("Usage: xrdp [options]");
357             g_writeln("   -h: show help");
358             g_writeln("   -install: install service");
359             g_writeln("   -remove: remove service");
360             g_writeln("%s", "");
361             g_exit(0);
362         }
363         else if (g_strncasecmp(argv[1], "-install", 255) == 0 ||
364                  g_strncasecmp(argv[1], "--install", 255) == 0 ||
365                  g_strncasecmp(argv[1], "-i", 255) == 0)
366         {
367             /* open service manager */
368             sc_man = OpenSCManager(0, 0, GENERIC_WRITE);
369 
370             if (sc_man == 0)
371             {
372                 g_writeln("error OpenSCManager, do you have rights?");
373                 g_exit(0);
374             }
375 
376             /* check if service is already installed */
377             sc_ser = OpenService(sc_man, "xrdp", SERVICE_ALL_ACCESS);
378 
379             if (sc_ser == 0)
380             {
381                 /* install service */
382                 CreateService(sc_man, "xrdp", "xrdp", SERVICE_ALL_ACCESS,
383                               SERVICE_WIN32_OWN_PROCESS, SERVICE_DEMAND_START,
384                               SERVICE_ERROR_IGNORE, "c:\\temp\\xrdp\\xrdp.exe",
385                               0, 0, 0, 0, 0);
386 
387             }
388             else
389             {
390                 g_writeln("error service is already installed");
391                 CloseServiceHandle(sc_ser);
392                 CloseServiceHandle(sc_man);
393                 g_exit(0);
394             }
395 
396             CloseServiceHandle(sc_man);
397             g_exit(0);
398         }
399         else if (g_strncasecmp(argv[1], "-remove", 255) == 0 ||
400                  g_strncasecmp(argv[1], "--remove", 255) == 0 ||
401                  g_strncasecmp(argv[1], "-r", 255) == 0)
402         {
403             /* open service manager */
404             sc_man = OpenSCManager(0, 0, GENERIC_WRITE);
405 
406             if (sc_man == 0)
407             {
408                 g_writeln("error OpenSCManager, do you have rights?");
409                 g_exit(0);
410             }
411 
412             /* check if service is already installed */
413             sc_ser = OpenService(sc_man, "xrdp", SERVICE_ALL_ACCESS);
414 
415             if (sc_ser == 0)
416             {
417                 g_writeln("error service is not installed");
418                 CloseServiceHandle(sc_man);
419                 g_exit(0);
420             }
421 
422             DeleteService(sc_ser);
423             CloseServiceHandle(sc_man);
424             g_exit(0);
425         }
426         else
427         {
428             g_writeln("Unknown Parameter");
429             g_writeln("xrdp -h for help");
430             g_writeln("%s", "");
431             g_exit(0);
432         }
433     }
434     else if (argc > 1)
435     {
436         g_writeln("Unknown Parameter");
437         g_writeln("xrdp -h for help");
438         g_writeln("%s", "");
439         g_exit(0);
440     }
441 
442     if (run_as_service)
443     {
444         g_memset(&te, 0, sizeof(te));
445         te[0].lpServiceName = "xrdp";
446         te[0].lpServiceProc = MyServiceMain;
447         StartServiceCtrlDispatcher(&te);
448         g_exit(0);
449     }
450 
451     WSAStartup(2, &w);
452 #else /* _WIN32 */
453     g_snprintf(pid_file, 255, "%s/xrdp.pid", XRDP_PID_PATH);
454     no_daemon = 0;
455 
456     if (argc == 2)
457     {
458         if ((g_strncasecmp(argv[1], "-kill", 255) == 0) ||
459                 (g_strncasecmp(argv[1], "--kill", 255) == 0) ||
460                 (g_strncasecmp(argv[1], "-k", 255) == 0))
461         {
462             g_writeln("stopping xrdp");
463             /* read the xrdp.pid file */
464             fd = -1;
465 
466             if (g_file_exist(pid_file)) /* xrdp.pid */
467             {
468                 fd = g_file_open(pid_file); /* xrdp.pid */
469             }
470 
471             if (fd == -1)
472             {
473                 g_writeln("cannot open %s, maybe xrdp is not running",
474                           pid_file);
475             }
476             else
477             {
478                 g_memset(text, 0, 32);
479                 g_file_read(fd, text, 31);
480                 pid = g_atoi(text);
481                 g_writeln("stopping process id %d", pid);
482 
483                 if (pid > 0)
484                 {
485                     g_sigterm(pid);
486                 }
487 
488                 g_file_close(fd);
489             }
490 
491             g_exit(0);
492         }
493         else if (g_strncasecmp(argv[1], "-nodaemon", 255) == 0 ||
494                  g_strncasecmp(argv[1], "--nodaemon", 255) == 0 ||
495                  g_strncasecmp(argv[1], "-nd", 255) == 0 ||
496                  g_strncasecmp(argv[1], "--nd", 255) == 0 ||
497                  g_strncasecmp(argv[1], "-ns", 255) == 0 ||
498                  g_strncasecmp(argv[1], "--ns", 255) == 0)
499         {
500             no_daemon = 1;
501         }
502         else if (g_strncasecmp(argv[1], "-help", 255) == 0 ||
503                  g_strncasecmp(argv[1], "--help", 255) == 0 ||
504                  g_strncasecmp(argv[1], "-h", 255) == 0)
505         {
506             g_writeln("%s", "");
507             g_writeln("xrdp: A Remote Desktop Protocol server.");
508             g_writeln("Copyright (C) Jay Sorg 2004-2011");
509             g_writeln("See http://www.xrdp.org for more information.");
510             g_writeln("%s", "");
511             g_writeln("Usage: xrdp [options]");
512             g_writeln("   -h: show help");
513             g_writeln("   -nodaemon: don't fork into background");
514             g_writeln("   -kill: shut down xrdp");
515             g_writeln("%s", "");
516             g_exit(0);
517         }
518         else if ((g_strncasecmp(argv[1], "-v", 255) == 0) ||
519                  (g_strncasecmp(argv[1], "--version", 255) == 0))
520         {
521             g_writeln("%s", "");
522             g_writeln("xrdp: A Remote Desktop Protocol server.");
523             g_writeln("Copyright (C) Jay Sorg 2004-2011");
524             g_writeln("See http://www.xrdp.org for more information.");
525             g_writeln("Version %s", PACKAGE_VERSION);
526             g_writeln("%s", "");
527             g_exit(0);
528         }
529         else
530         {
531             g_writeln("Unknown Parameter");
532             g_writeln("xrdp -h for help");
533             g_writeln("%s", "");
534             g_exit(0);
535         }
536     }
537     else if (argc > 1)
538     {
539         g_writeln("Unknown Parameter");
540         g_writeln("xrdp -h for help");
541         g_writeln("%s", "");
542         g_exit(0);
543     }
544 
545     if (g_file_exist(pid_file)) /* xrdp.pid */
546     {
547         g_writeln("It looks like xrdp is already running.");
548         g_writeln("If not, delete %s and try again.", pid_file);
549         g_exit(0);
550     }
551 
552     if (!no_daemon)
553     {
554         /* make sure we can write to pid file */
555         fd = g_file_open(pid_file); /* xrdp.pid */
556 
557         if (fd == -1)
558         {
559             g_writeln("running in daemon mode with no access to pid files, quitting");
560             g_exit(0);
561         }
562 
563         if (g_file_write(fd, "0", 1) == -1)
564         {
565             g_writeln("running in daemon mode with no access to pid files, quitting");
566             g_exit(0);
567         }
568 
569         g_file_close(fd);
570         g_file_delete(pid_file);
571     }
572 
573     if (!no_daemon)
574     {
575         /* start of daemonizing code */
576         pid = g_fork();
577 
578         if (pid == -1)
579         {
580             g_writeln("problem forking");
581             g_exit(1);
582         }
583 
584         if (0 != pid)
585         {
586             g_writeln("process %d started ok", pid);
587             /* exit, this is the main process */
588             g_exit(0);
589         }
590 
591         g_sleep(1000);
592         g_file_close(0);
593         g_file_close(1);
594         g_file_close(2);
595         g_file_open("/dev/null");
596         g_file_open("/dev/null");
597         g_file_open("/dev/null");
598         /* end of daemonizing code */
599     }
600 
601     if (!no_daemon)
602     {
603         /* write the pid to file */
604         pid = g_getpid();
605         fd = g_file_open(pid_file); /* xrdp.pid */
606 
607         if (fd == -1)
608         {
609             g_writeln("trying to write process id to xrdp.pid");
610             g_writeln("problem opening xrdp.pid");
611             g_writeln("maybe no rights");
612         }
613         else
614         {
615             g_sprintf(text, "%d", pid);
616             g_file_write(fd, text, g_strlen(text));
617             g_file_close(fd);
618         }
619     }
620 
621 #endif
622     g_threadid = tc_get_threadid();
623     g_listen = xrdp_listen_create();
624     g_signal_user_interrupt(xrdp_shutdown); /* SIGINT */
625     g_signal_pipe(pipe_sig); /* SIGPIPE */
626     g_signal_terminate(xrdp_shutdown); /* SIGTERM */
627     g_sync_mutex = tc_mutex_create();
628     g_sync1_mutex = tc_mutex_create();
629     pid = g_getpid();
630     g_snprintf(text, 255, "xrdp_%8.8x_main_term", pid);
631     g_term_event = g_create_wait_obj(text);
632     g_snprintf(text, 255, "xrdp_%8.8x_main_sync", pid);
633     g_sync_event = g_create_wait_obj(text);
634 
635     if (g_term_event == 0)
636     {
637         g_writeln("error creating g_term_event");
638     }
639 
640     xrdp_listen_main_loop(g_listen);
641     xrdp_listen_delete(g_listen);
642     tc_mutex_delete(g_sync_mutex);
643     tc_mutex_delete(g_sync1_mutex);
644     g_delete_wait_obj(g_term_event);
645     g_delete_wait_obj(g_sync_event);
646 #if defined(_WIN32)
647     /* I don't think it ever gets here */
648     /* when running in win32 app mode, control c exits right away */
649     WSACleanup();
650 #else
651     /* delete the xrdp.pid file */
652     g_file_delete(pid_file);
653 #endif
654     return 0;
655 }
656