1 // ///////////////////////////////////////////////////////////////////////////
2 // Copyright (C) 2002 Ultr@VNC Team Members. All Rights Reserved.
3 //
4 // This program is free software; you can redistribute it and/or modify
5 // it under the terms of the GNU General Public License as published by
6 // the Free Software Foundation; either version 2 of the License, or
7 // (at your option) any later version.
8 //
9 // This program is distributed in the hope that it will be useful,
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 // GNU General Public License for more details.
13 //
14 // You should have received a copy of the GNU General Public License
15 // along with this program; if not, write to the Free Software
16 // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
17 // USA.
18 //
19 // Program is based on the
20 // http://www.imasy.or.jp/~gotoh/ssh/connect.c
21 // Written By Shun-ichi GOTO <gotoh@taiyo.co.jp>
22 //
23 // If the source code for the program is not available from the place
24 // from which you received this file, check
25 // http://ultravnc.sourceforge.net/
26 //
27 // Linux port (C) 2005- Jari Korhonen, jarit1.korhonen@dnainternet.net
28 //////////////////////////////////////////////////////////////////////
29
30 #include <sys/types.h>
31 #include <sys/wait.h>
32 #include <sys/stat.h>
33 #include <sys/socket.h>
34 #include <sys/time.h>
35 #include <stdio.h>
36 #include <stdlib.h>
37 #include <string.h>
38 #include <ctype.h>
39 #include <limits.h>
40 #include <memory.h>
41 #include <errno.h>
42 #include <assert.h>
43 #include <stdarg.h>
44 #include <fcntl.h>
45 #include <signal.h>
46 #include <time.h>
47 #include <netdb.h>
48 #include <unistd.h>
49 #include <netinet/in.h>
50 #include <arpa/inet.h>
51 #include <pwd.h> //for getpwnam() in dropPrivileges()
52
53 #include "commondefines.h"
54 #include "repeaterproc.h"
55 #include "readini.h"
56 #include "repeaterutil.h"
57 #include "repeaterevents.h"
58 #include "repeater.h"
59
60 #define REPEATER_VERSION "0.14"
61
62 #define RFB_PROTOCOL_VERSION_FORMAT "RFB %03d.%03d\n"
63 #define RFB_PROTOCOL_MAJOR_VERSION 0
64 #define RFB_PROTOCOL_MINOR_VERSION 0
65 #define SIZE_RFBPROTOCOLVERSIONMSG 12
66
67 #define RFB_PORT_OFFSET 5900 //servers 1st display is in this port number
68 #define MAX_IDLE_CONNECTION_TIME 600 //Seconds
69 #define MAX_HOST_NAME_LEN 250
70 #define MAX_PATH 250
71 #define MAX_HANDSHAKE_LEN 100
72 #define UNKNOWN_REPINFO_IND 999999 //Notice: This should always be bigger than maxSessions
73
74 #define LISTEN_BACKLOG 5 //Listen() queues 5 connections
75
76 //connectionFrom defines for acceptConnection(). Used also in connectionRemover()
77 #define CONNECTION_FROM_SERVER 0
78 #define CONNECTION_FROM_VIEWER 1
79
80 //Use safer openbsd stringfuncs: strlcpy, strlcat
81 #include "openbsd_stringfuncs.h"
82
83 typedef char rfbProtocolVersionMsg[SIZE_RFBPROTOCOLVERSIONMSG+1]; /* allow extra byte for null */
84
85 typedef struct _repeaterInfo {
86 int socket;
87
88 //Code is used for cross-connection between servers and viewers
89 //In Mode 2, Server/Viewer sends IdCode string "ID:xxxxx", where xxxxx is some positive (1 or bigger) long integer number
90 //In Mode 1, Repeater "invents" a non-used code (negative number) and assigns that to both Server/Viewer
91 //code == 0 means that entry in servers[] / viewers[] table is free
92 long code;
93
94 unsigned long timeStamp;
95
96 //Ip address of peer
97 addrParts peerIp;
98
99 //There are 3 connection levels (using variables "code" and "active"):
100 //A. code==0,active==false: fully idle, no connection attempt detected
101 //B. code==non-zero,active==false: server/viewer has connected, waiting for other end to connect
102 //C. code==non-zero,active=true: doRepeater() running on viewer/server connection, fully active
103 //-after viewer/server disconnects or some error in doRepeater, returns both to level A
104 //(and closes respective sockets)
105 //This logic means, that when one end disconnects, BOTH ends need to reconnect.
106 //This is not a bug, it is a feature ;-)
107 bool active;
108 } repeaterInfo;
109 static repeaterInfo *servers[MAX_SESSIONS_MAX];
110 static repeaterInfo *viewers[MAX_SESSIONS_MAX];
111
112
113 //Server handshake strings for use when respective viewer connects later
114 typedef struct _handShakeInfo
115 {
116 char handShake[MAX_HANDSHAKE_LEN];
117 int handShakeLength;
118 } handShakeInfo;
119 static handShakeInfo *handShakes[MAX_SESSIONS_MAX];
120
121 //mode1ConnCode is used in Mode1 to "invent" code field in repeaterInfo, when new Mode1 connection from
122 //viewer is accepted. This is just decremented for each new Mode 1 connection to ensure unique number
123 //for each Mode 1 session
124 //Values for this are: 0=program has just started, -1....MIN_INVENTED_CONN_CODE: Codes for each session
125 #define MIN_INVENTED_CONN_CODE -1000000
126 static long mode1ConnCode;
127
128
129 //This structure (and repeaterProcs[] table) is used for
130 //keeping track of child processes running doRepeater
131 //and cleaning up after they exit
132 typedef struct _repeaterProcInfo
133 {
134 long code;
135 pid_t pid;
136 } repeaterProcInfo;
137 static repeaterProcInfo *repeaterProcs[MAX_SESSIONS_MAX];
138
139
140 //This structure keeps information of ports/socket used when
141 //routeConnections() listens for new incoming connections
142 typedef struct _listenPortInfo {
143 int socket;
144 int port;
145 } listenPortInfo;
146
147 //Repeater "events" interface uses this variable. Various "events"
148 //are sent to interface using function sendRepeaterEvent()
149 //and later handled with function handleRepeaterEvents(), which forks a child
150 //process to handle the grunt work of event posting
151 //Child process is later cleaned up calling function cleanUpAfterEventProc()
152 static repeaterEvent event;
153
154 //stopped==true means that user wants program to stop (has pressed ctrl+c)
155 //From version 0.08 onwards, function fatal() also sets stopped == TRUE to achieve clean shutdown
156 static bool stopped;
157
158 static int nonBlockingRead(int sock, char *buf, int len, int timeOut);
159 static int findViewerList(long code);
160 static void cleanUpAfterRepeaterProcs(void);
161 static void logLineStart(const char *prefix);
162 static int connectWithTimeout(int socket, const struct sockaddr *addr, socklen_t addrlen, int timeOutSecs);
163
164 //Global functions
165 //Global functions
166 //Global functions
167
debug(int msgLevel,const char * fmt,...)168 void debug(int msgLevel, const char *fmt, ...)
169 {
170 va_list args;
171
172 if (msgLevel <= loggingLevel) {
173 logLineStart("UltraVnc");
174
175 va_start(args, fmt);
176
177 vfprintf(stderr, fmt, args);
178 va_end(args);
179 }
180 }
181
fatal(const char * fmt,...)182 void fatal(const char *fmt, ...)
183 {
184 va_list args;
185
186 logLineStart("UltraVnc FATAL");
187
188 va_start(args, fmt);
189
190 vfprintf(stderr, fmt, args);
191 va_end(args);
192
193 //Close program down cleanly (as if user just pressed ctrl+c, of course
194 //log file will show FATAL message in case program shuts down)
195 stopped = true;
196 }
197
198
199 //Try to connect to event listener, return connected socket if success, -1 if error
200 //parameter listenerIp holds eventlistener's ip address on return (or "" in case of error)
openConnectionToEventListener(const char * host,unsigned short port,char * listenerIp,int listenerIpSize)201 int openConnectionToEventListener(const char *host, unsigned short port, char *listenerIp, int listenerIpSize)
202 {
203 int s;
204 struct sockaddr_in saddr;
205 struct hostent *h;
206
207 h = gethostbyname(host);
208 if (NULL == h) {
209 debug(LEVEL_2, "openConnectionToEventListener(): can't resolve hostname: %s\n", host);
210 return -1;
211 }
212 saddr.sin_family = AF_INET;
213 saddr.sin_port = htons(port);
214
215 //Interesting;-) typecast / indirection thing copied from "Beej's Guide to network programming".
216 //See http://beej.us/guide/bgnet/ for more info
217 saddr.sin_addr = *((struct in_addr *)h->h_addr);
218
219 memset(&(saddr.sin_zero), '\0', 8); // zero the rest of the struct
220
221 strlcpy(listenerIp, inet_ntoa(saddr.sin_addr), listenerIpSize);
222
223 debug(LEVEL_3, "openConnectionToEventListener(): connecting to %s:%u\n", listenerIp, port);
224
225 s = socket(AF_INET, SOCK_STREAM, 0);
226
227 //Trying to connect with timeout
228 if (connectWithTimeout(s, (struct sockaddr *) &saddr, sizeof(saddr), TIMEOUT_10SECS) != 0) {
229 debug(LEVEL_2, "openConnectionToEventListener(): connectWithTimeout() failed.\n");
230 close(s);
231 strlcpy(listenerIp, "", listenerIpSize);
232 return -1;
233 }
234 else
235 return s;
236 }
237
238
239 //Try to write exact number of bytes to socket
240 //return 1 if things went OK,
241 //return -2 in case of timeout
242 //return -1 in case of error
writeExact(int sock,char * buf,int len,int timeOutSecs)243 int writeExact(int sock, char *buf, int len, int timeOutSecs)
244 {
245 int n;
246 int timeOutCtr;
247
248 debug(LEVEL_3, "writeExact(): start\n");
249 timeOutCtr=0;
250 while ((len > 0) && (timeOutCtr < timeOutSecs)) {
251 n = send(sock, buf, len, MSG_DONTWAIT);
252
253 if (n > 0) {
254 buf += n;
255 len -= n;
256 }
257 else if (n == 0) {
258 debug(LEVEL_3, "writeExact(): send returned 0\n");
259 return -1;
260 }
261 else {
262 //send() returned -1 to indicate some error
263 //Because we use non-blocking in send(), we have to
264 //handle EAGAIN by incrementing timeout counter
265 if (errno == EAGAIN) {
266 debug(LEVEL_3, "writeExact(): EAGAIN detected\n");
267 sleep(1);
268 timeOutCtr++;
269 }
270 else {
271 debug(LEVEL_3, "writeExact(): send() returned error, errno = %d (%s)\n", errno, strerror(errno));
272 return -1;
273 }
274 }
275 }
276
277 if (timeOutCtr < timeOutSecs) {
278 debug(LEVEL_3, "writeExact(): returning normally\n");
279 return 1;
280 }
281 else {
282 debug(LEVEL_3, "writeExact(): timeout error\n");
283 return -2;
284 }
285 }
286
287
288 //Local functions
289 //Local functions
290 //Local functions
291
292 //Standard log line start common for all types of messages: debug / fatal
logLineStart(const char * prefix)293 static void logLineStart(const char *prefix)
294 {
295 time_t errTime;
296 char buf[MY_TMP_BUF_LEN];
297 char *lf;
298
299 errTime = time(NULL);
300
301 //ctime() adds '\n' to line end, change that to space
302 strlcpy(buf, ((errTime != -1) ? ctime(&errTime) : ""), MY_TMP_BUF_LEN);
303 lf = strchr(buf, '\n');
304 if (NULL != lf)
305 *lf = ' ';
306
307 fprintf(stderr, "%s %s> ", prefix, buf);
308 }
309
310 //Allocate memory for various lists of repeater when program starts
311 //This routine is needed from version 0.12,
312 //because lists are not statically allocated anymore
313 //but can be dynamically changed via ini file setting
314 //Return true if Ok, false if error
allocateMemoryForRepeaterLists(int numSessions)315 static bool allocateMemoryForRepeaterLists(int numSessions)
316 {
317 int ii;
318
319 for(ii = 0; ii < MAX_SESSIONS_MAX; ii++) {
320 handShakes[ii] = NULL;
321 repeaterProcs[ii] = NULL;
322 servers[ii] = NULL;
323 viewers[ii] = NULL;
324 }
325
326
327 for(ii = 0; ii < numSessions; ii++) {
328 handShakes[ii] = (handShakeInfo *) calloc(1, sizeof(handShakeInfo));
329 if (handShakes[ii] == NULL)
330 return false;
331
332 repeaterProcs[ii] = (repeaterProcInfo *) calloc(1, sizeof(repeaterProcInfo));
333 if (repeaterProcs[ii] == NULL)
334 return false;
335
336 servers[ii] = (repeaterInfo *) calloc(1, sizeof(repeaterInfo));
337 if (servers[ii] == NULL)
338 return false;
339
340 viewers[ii] = (repeaterInfo *) calloc(1, sizeof(repeaterInfo));
341 if (viewers[ii] == NULL)
342 return false;
343 }
344
345 return true;
346 }
347
348 //Free memory of various repeater lists (if allocated)
freeMemoryOfRepeaterLists(void)349 static void freeMemoryOfRepeaterLists(void)
350 {
351 int ii;
352
353 for(ii = 0; ii < MAX_SESSIONS_MAX; ii++) {
354 if (handShakes[ii] != NULL) {
355 free(handShakes[ii]);
356 handShakes[ii] = NULL;
357 }
358
359 if (repeaterProcs[ii] != NULL) {
360 free(repeaterProcs[ii]);
361 repeaterProcs[ii] = NULL;
362 }
363
364 if (servers[ii] != NULL) {
365 free(servers[ii]);
366 servers[ii] = NULL;
367 }
368
369 if (viewers[ii] != NULL) {
370 free(viewers[ii]);
371 viewers[ii] = NULL;
372 }
373 }
374 }
375
376
377 //Clean various lists of repeater when program starts
cleanLists(void)378 static void cleanLists(void)
379 {
380 int ii;
381 for (ii = 0; ii < maxSessions; ii++) {
382 memset(handShakes[ii], 0, sizeof(handShakeInfo));
383 memset(repeaterProcs[ii], 0, sizeof(repeaterProcInfo));
384 memset(servers[ii], 0, sizeof(repeaterInfo));
385 memset(viewers[ii], 0, sizeof(repeaterInfo));
386 }
387 }
388
389
addRepeaterProcList(long code,pid_t pid)390 static void addRepeaterProcList(long code, pid_t pid)
391 {
392 int i;
393
394 for (i = 0; i < maxSessions; i++) {
395 if (repeaterProcs[i] -> code == 0) {
396 debug(LEVEL_3, "addRepeaterProcList(): Added proc to index=%d, pid=%d, code=%ld\n", i, pid, code);
397 repeaterProcs[i] -> code = code;
398 repeaterProcs[i] -> pid = pid;
399 return;
400 }
401 }
402 debug(LEVEL_2, "addRepeaterProcList(): Warning, no free process slots found\n");
403 }
404
405
removeRepeaterProcList(pid_t pid)406 static void removeRepeaterProcList(pid_t pid)
407 {
408 int i;
409
410 for (i = 0; i < maxSessions; i++) {
411 if (repeaterProcs[i] -> pid == pid) {
412 debug(LEVEL_3, "removeRepeaterProcList(): Removing proc from index=%d, pid=%d\n", i, pid);
413 repeaterProcs[i] -> code = 0;
414 repeaterProcs[i] -> pid = 0;
415 return;
416 }
417 }
418 debug(LEVEL_2, "removeRepeaterProcList(): Warning, did not find any process to remove\n");
419
420 }
421
422
423
424
findRepeaterProcList(pid_t pid)425 static int findRepeaterProcList(pid_t pid)
426 {
427 int i;
428
429 for (i = 0; i < maxSessions; i++) {
430 if (repeaterProcs[i] -> pid == pid) {
431 debug(LEVEL_3, "findRepeaterProcList(): proc found at index=%d, pid=%d, code = %ld\n",
432 i, pid, repeaterProcs[i] -> code);
433 return i;
434 }
435 }
436
437 debug(LEVEL_2, "findRepeaterProcList(): Warning, did not find any proc (pid=%d)\n", pid);
438 return UNKNOWN_REPINFO_IND;
439 }
440
441
addServerList(int socket,long code,char * peerIp)442 static int addServerList(int socket, long code, char *peerIp)
443 {
444 int i;
445
446 for (i = 0; i < maxSessions; i++) {
447 if (servers[i] -> code == 0) {
448 debug(LEVEL_3, "addServerList(): Server added to list: code = %ld, index = %d\n", code, i);
449 servers[i] -> code = code;
450 servers[i] -> socket = socket;
451 servers[i] -> peerIp = getAddrPartsFromString(peerIp);
452 servers[i] -> timeStamp = time(NULL); /* 1 second accuracy is enough ? */
453 servers[i] -> active = false;
454 return i;
455 }
456 }
457
458 debug(LEVEL_2, "addServerList(): Warning, no table slots available\n");
459 return -1; //Not added
460 }
461
462
removeServerList(long code)463 static void removeServerList(long code)
464 {
465 int i;
466
467 for (i = 0; i < maxSessions; i++) {
468 if (servers[i] -> code == code) {
469 debug(LEVEL_3, "removeServerList(): Server Removed from list: code = %ld, index = %d\n", code, i);
470 servers[i] -> code = 0;
471 servers[i] -> active = false;
472 return;
473 }
474 }
475 debug(LEVEL_2, "removeServerList(): Warning, server not found (code = %ld)\n", code);
476 }
477
478
setServerActive(long code)479 static void setServerActive(long code)
480 {
481 int i;
482
483 for (i = 0; i < maxSessions; i++) {
484 if (servers[i] -> code == code) {
485 servers[i] -> active = true;
486 debug(LEVEL_3, "setServerActive(): activated server at index = %d, code = %ld\n", i, servers[i] -> code);
487 return;
488 }
489 }
490 debug(LEVEL_2, "setServerActive(): server not found (code = %ld)\n", code);
491 }
492
493
findServerList(long code)494 static int findServerList(long code)
495 {
496 int i;
497
498 for (i = 0; i < maxSessions; i++) {
499 if (servers[i] -> code == code) {
500 debug(LEVEL_3, "findServerList(): server found at index %d, code = %ld\n", i, servers[i] -> code);
501 return i;
502 }
503 }
504
505 debug(LEVEL_2, "findServerList(): server not found (code = %ld)\n", code);
506 return UNKNOWN_REPINFO_IND;
507 }
508
509
addViewerList(int socket,long code,char * peerIp)510 static int addViewerList(int socket, long code, char *peerIp)
511 {
512 int i;
513
514 for (i = 0; i < maxSessions; i++) {
515 if (viewers[i] -> code == 0) {
516 debug(LEVEL_3, "addViewerList(): Viewer added to list: code = %ld, index = %d\n", code, i);
517 viewers[i] -> code = code;
518 viewers[i] -> socket = socket;
519 viewers[i] -> peerIp = getAddrPartsFromString(peerIp);
520 viewers[i] -> timeStamp = time(NULL);
521 viewers[i] -> active = false;
522 return i;
523 }
524 }
525
526 debug(LEVEL_2, "addViewerList(): Warning, no table slots available\n");
527 return -1; //Not added
528 }
529
530
removeViewerList(long code)531 static void removeViewerList(long code)
532 {
533 int i;
534
535 for (i = 0; i < maxSessions; i++) {
536 if (viewers[i] -> code == code) {
537 debug(LEVEL_3, "removeViewerList(): Viewer removed from list: code = %ld, index = %d\n", code, i);
538 viewers[i] -> code = 0;
539 viewers[i] -> active = false;
540 return;
541 }
542 }
543
544 debug(LEVEL_2, "removeViewerList(): Warning, viewer not found (code = %ld)\n", code);
545 }
546
547
setViewerActive(long code)548 static void setViewerActive(long code)
549 {
550 int i;
551
552 for (i = 0; i < maxSessions; i++) {
553 if (viewers[i] -> code == code) {
554 viewers[i] -> active = true;
555 debug(LEVEL_3, "setViewerActive(): activated viewer at index %d, code = %ld\n", i, viewers[i] -> code);
556 return;
557 }
558 }
559
560 debug(LEVEL_2, "setViewerActive(): Warning, viewer not found (code = %ld)\n", code);
561 }
562
563
findViewerList(long code)564 static int findViewerList(long code)
565 {
566 int i;
567
568 for (i = 0; i < maxSessions; i++) {
569 if (viewers[i] -> code == code) {
570 debug(LEVEL_3, "findViewerList(): viewer found at index %d, code = %ld\n", i, viewers[i] -> code);
571 return i;
572 }
573 }
574
575 debug(LEVEL_2, "findViewerList(): Warning, viewer not found (code = %ld)\n", code);
576 return UNKNOWN_REPINFO_IND;
577 }
578
579
580 //Check IdCode string, require that 1st 3 characters of IdCode are 'I','D',':'
checkIdCode(char * IdCode)581 static bool checkIdCode(char *IdCode)
582 {
583 if ((IdCode[0] != 'I') || (IdCode[1] != 'D') || (IdCode[2] != ':')) {
584 debug(LEVEL_3, "checkIdCode(): %s is not IdCode string\n", IdCode);
585 return false;
586 }
587 return true;
588 }
589
590
591 //Parse IdCode string of format "ID:xxxxx", where xxxxx is some positive (non-zero) long integer number
592 //Return -1 on error, xxxxx on success
parseId(char * IdCode)593 static long parseId(char *IdCode)
594 {
595 unsigned int ii;
596 int retVal;
597
598 debug(LEVEL_3, "parseId(): IdCode = %s\n", IdCode);
599
600 //Require that 1st 3 characters of IdCode are 'I','D',':'
601 if (false == checkIdCode(IdCode)) {
602 debug(LEVEL_3, "parseId(): IdCode format error, does not start ""ID:"" \n");
603 return -1;
604 }
605 else {
606 //Require that all other characters of IdCode are digits
607 for (ii = 3; ii < strlen(IdCode); ii++) {
608 if (!isdigit(IdCode[ii])) {
609 debug(LEVEL_3, "parseId(): IdCode format error, code should consist of decimal digits\n");
610 return -1;
611 }
612 }
613
614 retVal = strtol(&(IdCode[3]), NULL, 10);
615 if (retVal <= 0) {
616 debug(LEVEL_3, "parseId(): IdCode format error, code should be positive long integer number\n");
617 return -1;
618 }
619 else if (retVal == LONG_MAX) {
620 debug(LEVEL_3, "parseId(): IdCode format error, code is too big\n");
621 return -1;
622 }
623
624 return retVal;
625 }
626 }
627
628
629
630
631 //Return value: n > 0: number of bytes read
632 //-1: recv() error
633 //-2: timeout error
nonBlockingRead(int sock,char * buf,int len,int timeOut)634 static int nonBlockingRead(int sock, char *buf, int len, int timeOut)
635 {
636 int n;
637 int timeOutCtr;
638 int numRead = 0;
639
640 debug(LEVEL_3, "nonBlockingRead(): start\n");
641 timeOutCtr=0;
642 while ((len > 0) && (timeOutCtr < timeOut)) {
643 n = recv(sock, buf, len, MSG_DONTWAIT);
644
645 if (n > 0) {
646 buf += n;
647 len -= n;
648 numRead += n;
649 }
650 else {
651 if (n == -1) {
652 //recv() returned -1 to indicate some error
653 //Because we use non-blocking in recv(), we have to
654 //handle EAGAIN by incrementing timeout counter
655 if (errno == EAGAIN) {
656 sleep(1);
657 timeOutCtr++;
658 }
659 }
660 else {
661 debug(LEVEL_2, "nonBlockingRead(): recv() returned error, errno= %d (%s)\n", errno, strerror(errno));
662 return -1; //return value of recv() was unknown
663 }
664 }
665 }
666
667 if (timeOutCtr < timeOut) {
668 debug(LEVEL_3, "nonBlockingRead(): returning normally\n");
669 return numRead;
670 }
671 else {
672 //In case of timeout, return number of bytes received if > 0,
673 //otherwise return -2 to indicate timeout
674 if (numRead > 0) {
675 debug(LEVEL_3, "nonBlockingRead(): returning %d bytes\n", numRead);
676 return numRead;
677 }
678 else {
679 debug(LEVEL_3, "nonBlockingRead(): timeout error\n");
680 return -2;
681 }
682 }
683 }
684
685
686 //Function determines if connection is "too old" (older thar MAX_IDLE_CONNECTION_TIME)
isConnectionTooOld(unsigned long timeStamp)687 bool isConnectionTooOld(unsigned long timeStamp)
688 {
689 unsigned long tick = time(NULL);
690 if ((tick - timeStamp) > MAX_IDLE_CONNECTION_TIME)
691 return true;
692 else
693 return false;
694 }
695
696
697 //Function determines if connection is inactive
isExistingConnectionInactive(bool active,bool existing)698 bool isExistingConnectionInactive(bool active, bool existing)
699 {
700 if ((existing) && (!active))
701 return true;
702 else
703 return false;
704 }
705
706
707 //Function determines if connection is broken
isPeerDisconnected(int socket,int connectionFrom)708 bool isPeerDisconnected(int socket, int connectionFrom)
709 {
710 ssize_t n;
711
712 char buf[SIZE_RFBPROTOCOLVERSIONMSG+1];
713 buf[SIZE_RFBPROTOCOLVERSIONMSG] = '\0';
714
715 n = recv(socket, buf, SIZE_RFBPROTOCOLVERSIONMSG, MSG_DONTWAIT);
716
717 if (n == 0) {
718 debug(LEVEL_3, "isPeerDisconnected: recv() returned 0 (peer has disconnected orderly)\n");
719 return true; //peer has disconnected orderly
720 }
721 else if (n == -1) {
722 //recv() returned -1 to indicate some error
723 if (errno == EAGAIN) {
724 //Because we use non-blocking in recv(), EAGAIN is ok
725 return false;
726 }
727 else {
728 debug(LEVEL_2, "isPeerDisconnected: recv() returned error, errno = %d (%s)\n", errno, strerror(errno));
729 return true;
730 }
731 }
732 else if (n >= 1) {
733 //peer has sent data OK
734 debug(LEVEL_3, "isPeerDisconnected: recv() returned: %s\n", buf);
735 return false;
736 }
737 else {
738 //unknown error
739 debug(LEVEL_2, "isPeerDisconnected: recv() returned error, errno = %d (%s)\n", errno, strerror(errno));
740 return true;
741 }
742 }
743
744 //Remove [old idle | broken] [viewer | server] connection
connectionRemover(int connectionFrom,repeaterInfo * rI,int index)745 static void connectionRemover(int connectionFrom, repeaterInfo *rI, int index)
746 {
747 bool fRemove;
748 char removalReason[MY_TMP_BUF_LEN];
749
750 fRemove = false;
751 strlcpy(removalReason, "", MY_TMP_BUF_LEN);
752
753
754 if (isExistingConnectionInactive(rI -> active, (rI -> code != 0))) {
755 if (isConnectionTooOld(rI -> timeStamp)) {
756 //Existing connection has been idle for too long, remove
757 fRemove = true;
758 snprintf(removalReason, MY_TMP_BUF_LEN, "%s", "idle connection too old");
759 }
760 else if (isPeerDisconnected(rI -> socket, connectionFrom)) {
761 //Peer has closed the connection before another peer appeared, remove
762 fRemove = true;
763 snprintf(removalReason, MY_TMP_BUF_LEN, "%s", "peer has disconnected");
764 }
765
766 if (fRemove) {
767 //Send VIEWER_DISCONNECT / SERVER_DISCONNECT to event interface
768 if (useEventInterface) {
769 repeaterEvent event;
770 connectionEvent connEv;
771
772 event.eventNum = (connectionFrom == CONNECTION_FROM_VIEWER) ? VIEWER_DISCONNECT : SERVER_DISCONNECT;
773 event.timeStamp = time(NULL);
774 event.repeaterProcessId = getpid();
775
776 connEv.tableIndex = index;
777 connEv.code = rI -> code;
778 connEv.connMode = (rI -> code < 0) ? CONN_MODE1 : CONN_MODE2;
779 connEv.peerIp = rI -> peerIp;
780 memcpy(event.extraInfo, &connEv, sizeof(connectionEvent));
781
782 if (false == sendRepeaterEvent(event)) {
783 debug(LEVEL_1, "connectionRemover(): Warning, event fifo is full\n");
784 }
785 }
786
787 //Remove & close connection
788 close(rI -> socket);
789 debug(LEVEL_1, "connectionRemover(): Removing %s %ld at index %d (%s)\n",
790 (connectionFrom == CONNECTION_FROM_VIEWER) ? "viewer" : "server",
791 rI -> code,
792 index,
793 removalReason);
794
795 if (connectionFrom == CONNECTION_FROM_VIEWER)
796 removeViewerList(rI -> code);
797 else
798 removeServerList(rI -> code);
799 }
800 }
801 }
802
803 //This function is periodically called from routeConnections() to remove
804 //servers / viewers that did not receive any matching other end connection
removeOldOrBrokenConnections(void)805 static void removeOldOrBrokenConnections(void)
806 {
807 int ii;
808
809 for (ii = 0; ii < maxSessions; ii++) {
810 //Remove old inactive viewers
811 connectionRemover(CONNECTION_FROM_VIEWER, viewers[ii], ii);
812
813
814 //Remove old inactive servers
815 connectionRemover(CONNECTION_FROM_SERVER, servers[ii], ii);
816 }
817 }
818
819
820 //Parse [hostname / ip address] / [port number / display number] combination
821 //Return true if success, false if error
parseHostAndPort(char * id,char * host,int hostLen,int * port)822 static bool parseHostAndPort(char *id, char *host, int hostLen, int *port)
823 {
824 int tmpPort;
825 char *colonPos;
826
827 debug(LEVEL_3, "parseHostAndPort() start: id = %s\n", id);
828
829 colonPos = strchr(id, ':');
830 if (hostLen < (int) strlen(id)) {
831 debug(LEVEL_3, "parseHostAndPort(): Id string too long\n");
832 return false;
833 }
834
835 if (colonPos == NULL) {
836 // No colon -- use default port number
837 tmpPort = RFB_PORT_OFFSET;
838 strlcpy(host, id, hostLen);
839 }
840 else {
841 strlcpy(host, id, (colonPos-id)+1);
842
843 if (colonPos[1] == ':') {
844 // Two colons -- interpret as a port number
845 if (sscanf(colonPos + 2, "%d", &tmpPort) != 1) {
846 debug(LEVEL_3, "parseHostAndPort(): sscanf error 1\n");
847 return false;
848 }
849 }
850 else {
851 // One colon -- interpret as a display number or port
852 // number
853 if (sscanf(colonPos + 1, "%d", &tmpPort) != 1) {
854 return false;
855 }
856 // RealVNC method - If port < 100 interpret as display
857 // number else as Port number
858 if (tmpPort < 100)
859 tmpPort += RFB_PORT_OFFSET;
860 }
861 }
862
863 *port = tmpPort;
864 debug(LEVEL_3, "parseHostAndPort() end: host = %s, port = %d\n", host, tmpPort);
865 return true;
866 }
867
868 //Connect-with-timeout function borrowed from unix sockets faq
869 //Maybe Java guys have some point when talking about exception handling ;-)
connectWithTimeout(int socket,const struct sockaddr * addr,socklen_t addrlen,int timeOutSecs)870 static int connectWithTimeout(int socket, const struct sockaddr *addr, socklen_t addrlen, int timeOutSecs)
871 {
872 int res;
873 long arg;
874 fd_set myset;
875 struct timeval tv;
876 int valopt;
877 socklen_t lon;
878
879 //First, set socket non-blocking
880 arg = fcntl(socket, F_GETFL, NULL);
881 if (arg < 0) {
882 debug(LEVEL_2, "connectWithTimeout(): error in fcntl(..., F_GETFL) (%s)\n", strerror(errno));
883 return -1;
884 }
885 arg |= O_NONBLOCK;
886 if (fcntl(socket, F_SETFL, arg) < 0) {
887 debug(LEVEL_2, "connectWithTimeout(): error in fcntl(..., F_SETFL) (%s)\n", strerror(errno));
888 return -1;
889 }
890
891 //Try to connect with timeout
892 res = connect(socket, addr, addrlen);
893 if (res < 0) {
894 if (errno == EINPROGRESS) {
895 debug(LEVEL_3, "connectWithTimeout(): EINPROGRESS in connect() - selecting\n");
896
897 do {
898 tv.tv_sec = timeOutSecs;
899 tv.tv_usec = 0;
900
901 FD_ZERO(&myset);
902 FD_SET(socket, &myset);
903
904 res = select(socket + 1, NULL, &myset, NULL, &tv);
905
906 if ((res < 0) && (errno != EINTR)) {
907 debug(LEVEL_3, "connectWithTimeout(): Error connecting %d (%s)\n", errno, strerror(errno));
908 return -1;
909 }
910 else if (res > 0) {
911 // Socket selected for write, check if connection was succesful
912 lon = sizeof(int);
913
914 if (getsockopt(socket, SOL_SOCKET, SO_ERROR, (void*)(&valopt), &lon) < 0) {
915 debug(LEVEL_2, "connectWithTimeout(): Error in getsockopt() %d (%s)\n", errno, strerror(errno));
916 return -1;
917 }
918
919 // Check the value returned...
920 if (valopt) {
921 debug(LEVEL_2, "connectWithTimeout(): Error in delayed connection() %d (%s)\n",
922 valopt, strerror(valopt));
923 return -1;
924 }
925 else {
926 debug(LEVEL_3, "connectWithTimeout(): connected OK\n");
927 break;
928 }
929 }
930 else {
931 debug(LEVEL_3, "connectWithTimeout(): Timeout in select() - Cancelling!\n");
932 return -1;
933 }
934 } while (1);
935 }
936 else {
937 debug(LEVEL_3, "connectWithTimeout(): Error connecting %d (%s)\n", errno, strerror(errno));
938 return -1;
939 }
940 }
941
942 //Set to blocking mode again...
943 if ((arg = fcntl(socket, F_GETFL, NULL)) < 0) {
944 debug(LEVEL_2, "connectWithTimeout(): Error fcntl(..., F_GETFL) (%s)\n", strerror(errno));
945 return -1;
946 }
947 arg &= (~O_NONBLOCK);
948 if (fcntl(socket, F_SETFL, arg) < 0) {
949 debug(LEVEL_2, "connectWithTimeout(): Error fcntl(..., F_SETFL) (%s)\n", strerror(errno));
950 return -1;
951 }
952
953 return 0;
954 }
955
956
957 //check intended Mode 1 server address against list of denied addresses/ranges in repeater.ini
958 //return true if denied address, false otherwise
isServerAddressDenied(addrParts srvAddr)959 static bool isServerAddressDenied(addrParts srvAddr)
960 {
961 int ii;
962
963 for(ii = 0; ii < SERVERS_LIST_SIZE; ii++) {
964 if (((srvAddr.a == srvListDeny[ii].a) || (srvListDeny[ii].a == 0)) &&
965 ((srvAddr.b == srvListDeny[ii].b) || (srvListDeny[ii].b == 0)) &&
966 ((srvAddr.c == srvListDeny[ii].c) || (srvListDeny[ii].c == 0)) &&
967 ((srvAddr.d == srvListDeny[ii].d) || (srvListDeny[ii].d == 0)) ) {
968 debug(LEVEL_3, "isServerAddressDenied(): address is in deny list, denying (%d.%d.%d.%d)\n",
969 srvAddr.a,srvAddr.b,srvAddr.c,srvAddr.d);
970
971 return true;
972 }
973 }
974
975 return false;
976 }
977
978 //check intended Mode 1 server address against list of allowed addresses/ranges in repeater.ini
979 //return true if allowed address, false otherwise
isServerAddressAllowed(char * serverIp)980 static bool isServerAddressAllowed(char *serverIp)
981 {
982 int ii;
983 addrParts srvAddr;
984 bool allow;
985
986 srvAddr = getAddrPartsFromString(serverIp);
987
988 for(ii = 0; ii < SERVERS_LIST_SIZE; ii++) {
989 allow = true;
990
991 //List 255 == denied
992 if ((srvListAllow[ii].a == 255) || (srvListAllow[ii].b == 255) ||
993 (srvListAllow[ii].c == 255) || (srvListAllow[ii].d == 255))
994 allow = false;
995
996 //server 255 == denied
997 if ((srvAddr.a == 255) || (srvAddr.b == 255) || (srvAddr.c == 255) || (srvAddr.d == 255))
998 allow = false;
999
1000 //server 0 == denied
1001 if ((srvAddr.a == 0) || (srvAddr.b == 0) || (srvAddr.c == 0) || (srvAddr.d == 0))
1002 allow = false;
1003
1004
1005 //allowed so far ?
1006 if (allow)
1007 {
1008 //allow if exact match or if place is 0 in allow list
1009 if (((srvAddr.a == srvListAllow[ii].a) || (srvListAllow[ii].a == 0)) &&
1010 ((srvAddr.b == srvListAllow[ii].b) || (srvListAllow[ii].b == 0)) &&
1011 ((srvAddr.c == srvListAllow[ii].c) || (srvListAllow[ii].c == 0)) &&
1012 ((srvAddr.d == srvListAllow[ii].d) || (srvListAllow[ii].d == 0)) ) {
1013 //Allowed so far, check denial
1014 if (!isServerAddressDenied(srvAddr)) {
1015 debug(LEVEL_3, "isServerAddressAllowed(): address is OK, allowing (%s)\n", serverIp);
1016 return true;
1017 }
1018 }
1019 }
1020 }
1021
1022 return false;
1023 }
1024
1025
1026 //Try to connect to vnc server, return connected socket if success, -1 if error
1027 //parameter serverIp holds server ip address on return (or "" in case of error)
openConnectionToVncServer(const char * host,unsigned short port,char * serverIp)1028 static int openConnectionToVncServer(const char *host, unsigned short port, char *serverIp)
1029 {
1030 int s;
1031 struct sockaddr_in saddr;
1032 struct hostent *h;
1033
1034 h = gethostbyname(host);
1035 if (NULL == h) {
1036 debug(LEVEL_2, "openConnectionToVncServer(): can't resolve hostname: %s\n", host);
1037 return -1;
1038 }
1039 saddr.sin_family = AF_INET;
1040 saddr.sin_port = htons(port);
1041
1042 //Interesting;-) typecast / indirection thing copied from "Beej's Guide to network programming".
1043 //See http://beej.us/guide/bgnet/ for more info
1044 saddr.sin_addr = *((struct in_addr *)h->h_addr);
1045
1046 memset(&(saddr.sin_zero), '\0', 8); // zero the rest of the struct
1047
1048 strlcpy(serverIp, inet_ntoa(saddr.sin_addr), MAX_IP_LEN);
1049
1050 //Check server addresses against list of allowed addresses / ranges
1051 if (requireListedServer == 1) {
1052 if (!isServerAddressAllowed(serverIp)) {
1053 debug(LEVEL_2, "openConnectionToVncServer(): server is not allowed (%s)\n", serverIp);
1054 return -1;
1055 }
1056 }
1057
1058 debug(LEVEL_3, "openConnectionToVncServer(): connecting to %s:%u\n", serverIp, port);
1059
1060 s = socket(AF_INET, SOCK_STREAM, 0);
1061
1062 //Trying to connect with timeout
1063 if (connectWithTimeout(s, (struct sockaddr *) &saddr, sizeof(saddr), TIMEOUT_10SECS) != 0) {
1064 debug(LEVEL_2, "openConnectionToVncServer(): connectWithTimeout() failed.\n");
1065 close(s);
1066 strlcpy(serverIp, "", MAX_IP_LEN);
1067 return -1;
1068 }
1069 else
1070 return s;
1071 }
1072
1073
1074 //Check ID code against connection tables.
1075 //Return index of similar ID if similar connection found
1076 //Return -1 if similar connection not found
findDuplicateIdIndex(int connectionFrom,long code)1077 static int findDuplicateIdIndex(int connectionFrom, long code)
1078 {
1079 repeaterInfo *repInfo;
1080 int ii;
1081
1082 for(ii = 0; ii < maxSessions; ii++) {
1083 if (connectionFrom == CONNECTION_FROM_VIEWER)
1084 repInfo = viewers[ii];
1085 else
1086 repInfo = servers[ii];
1087
1088 if (repInfo -> code == code) {
1089 debug(LEVEL_2, "findDuplicateIdIndex(): similar %s ID already there\n",
1090 (connectionFrom == CONNECTION_FROM_VIEWER) ? "viewer" : "server");
1091 return ii;
1092 }
1093 }
1094
1095 debug(LEVEL_3, "findDuplicateIdIndex(): similar ID not found\n");
1096 return -1;
1097 }
1098
1099 //Common part of forking repeater for various connection modes
forkRepeater(int serverSocket,int viewerSocket,long idCode)1100 static void forkRepeater(int serverSocket, int viewerSocket, long idCode)
1101 {
1102 pid_t pid;
1103
1104 //fork repeater
1105 pid = fork();
1106 if (-1 == pid) {
1107 //fork failed. This is so unfair. Exit and blame Linus ;-)
1108 fatal(LEVEL_0, "forkRepeater(): fork() failed. Linus, this is *so* unfair.\n");
1109 }
1110 else if (0 == pid) {
1111 //child code
1112 debug(LEVEL_3, "forkRepeater(): in child process, starting doRepeater(%d, %d)\n", serverSocket, viewerSocket);
1113 exit(doRepeater(serverSocket, viewerSocket));
1114 }
1115 else {
1116 //parent code
1117 //Add necessary information of child to repeaterProcs list so we can
1118 //properly clean up after child has exited
1119 addRepeaterProcList(idCode, pid);
1120
1121 //Close (parents copies of) repeater sockets right away here,
1122 //so we don't need to close them in cleanUpAfterRepeaterProcExit()
1123 close(serverSocket);
1124 close(viewerSocket);
1125 }
1126 }
1127
1128 //Compare ID code against codes in list
1129 //return true if match found, false otherwise
isCodeInIdList(long code)1130 static bool isCodeInIdList(long code)
1131 {
1132 int ii;
1133
1134 for(ii = 0; ii < ID_LIST_SIZE; ii++) {
1135 if (code == idList[ii]) {
1136 debug(LEVEL_3, "isCodeInIdList(): ID code match found (%ld)\n", code);
1137 return true;
1138 }
1139 }
1140
1141 return false;
1142 }
1143
1144 //Read peer handshake
readPeerHandShake(int socket,int index)1145 void readPeerHandShake(int socket, int index)
1146 {
1147 int len;
1148
1149 //Make sure handshake is null-terminated
1150 handShakes[index] -> handShake[MAX_HANDSHAKE_LEN-1] ='\0';
1151
1152 len = nonBlockingRead(socket, handShakes[index] -> handShake, MAX_HANDSHAKE_LEN - 1, TIMEOUT_5SECS);
1153 if (len < 0) {
1154 strlcpy(handShakes[index] -> handShake, "", MAX_HANDSHAKE_LEN);
1155 handShakes[index] -> handShakeLength = 0;
1156 }
1157 else {
1158 debug(LEVEL_3, "readPeerHandShake(): len = %d\n", len);
1159 handShakes[index] -> handShakeLength = len;
1160 }
1161 }
1162
1163
1164 //Accept connection in non-blocking way (this should stop hanging if something bad
1165 //has happened to socket between select() and accept())
1166 //Return -1 if error, accept():ed socket in normal case
nonBlockingAccept(int socket,struct sockaddr * sa,socklen_t * sockLen)1167 int nonBlockingAccept(int socket, struct sockaddr *sa, socklen_t *sockLen)
1168 {
1169 long arg;
1170 int socketToReturn;
1171
1172 //First, set socket non-blocking
1173 arg = fcntl(socket, F_GETFL, NULL);
1174 if (arg < 0) {
1175 debug(LEVEL_2, "nonBlockingAccept(): error in fcntl(..., F_GETFL) (%s)\n", strerror(errno));
1176 return -1;
1177 }
1178 arg |= O_NONBLOCK;
1179 if (fcntl(socket, F_SETFL, arg) < 0) {
1180 debug(LEVEL_2, "nonBlockingAccept(): error in fcntl(..., F_SETFL) (%s)\n", strerror(errno));
1181 return -1;
1182 }
1183
1184 //Accept connection
1185 socketToReturn = accept(socket, sa, sockLen);
1186
1187 //Set to blocking mode again...
1188 if ((arg = fcntl(socket, F_GETFL, NULL)) < 0) {
1189 debug(LEVEL_2, "nonBlockingAccept(): Error fcntl(..., F_GETFL) (%s)\n", strerror(errno));
1190 if (socketToReturn != -1)
1191 close(socketToReturn);
1192 return -1;
1193 }
1194 arg &= (~O_NONBLOCK);
1195 if (fcntl(socket, F_SETFL, arg) < 0) {
1196 debug(LEVEL_2, "nonBlockingAccept(): Error fcntl(..., F_SETFL) (%s)\n", strerror(errno));
1197 if (socketToReturn != -1)
1198 close(socketToReturn);
1199 return -1;
1200 }
1201
1202 //At last, we are ready to return accept():ed socket ;-)
1203 return socketToReturn;
1204 }
1205
1206
1207 //Accept connections from both servers and viewers
1208 // connectionFrom == CONNECTIONFROMSERVER means server is connecting,
1209 // connectionFrom==CONNECTIONFROMVIEWER means viewer is connecting
1210 // Mode 1 connections are only accepted from viewers (repeater then connects to server)
acceptConnection(int socket,int connectionFrom)1211 static void acceptConnection(int socket, int connectionFrom)
1212 {
1213 rfbProtocolVersionMsg pv;
1214 int connection;
1215 char id[MAX_HOST_NAME_LEN + 1];
1216 long code;
1217 struct sockaddr_in client;
1218 socklen_t sockLen;
1219 char peerIp[MAX_IP_LEN];
1220 int connMode; //Connection mode: CONN_MODE1 or CONN_MODE2
1221
1222 //These variables are used in Mode 1
1223 char host[MAX_HOST_NAME_LEN+1];
1224 char connMode1ServerIp[MAX_IP_LEN];
1225 int port;
1226
1227 sockLen = sizeof(struct sockaddr_in);
1228
1229 connection = nonBlockingAccept(socket, (struct sockaddr *) &client, &sockLen);
1230
1231 if (connection < 0)
1232 debug(LEVEL_2, "acceptConnection(): accept() failed, errno=%d (%s)\n", errno, strerror(errno));
1233 else {
1234 strlcpy(peerIp, inet_ntoa(client.sin_addr), MAX_IP_LEN);
1235
1236 debug(LEVEL_1, "acceptConnection(): connection accepted ok from ip: %s\n", peerIp);
1237
1238 if (connectionFrom == CONNECTION_FROM_VIEWER) {
1239 //We handshake viewers by transmitting rfbProtocolVersion first
1240 snprintf(pv, SIZE_RFBPROTOCOLVERSIONMSG+1, RFB_PROTOCOL_VERSION_FORMAT,
1241 RFB_PROTOCOL_MAJOR_VERSION, RFB_PROTOCOL_MINOR_VERSION);
1242
1243 debug(LEVEL_3, "acceptConnection(): pv = %s", pv);
1244
1245 if (writeExact(connection, pv, SIZE_RFBPROTOCOLVERSIONMSG, TIMEOUT_10SECS) < 0) {
1246 debug(LEVEL_2, "acceptConnection(): Writing protocol version error\n");
1247 close(connection);
1248 return;
1249 }
1250 }
1251
1252 //Make sure that id is null-terminated
1253 id[MAX_HOST_NAME_LEN] = '\0';
1254 if (nonBlockingRead(connection, id, MAX_HOST_NAME_LEN, TIMEOUT_5SECS) < 0) {
1255 debug(LEVEL_2, "acceptConnection(): Reading id error\n");
1256 close(connection);
1257 return;
1258 }
1259
1260 //id can be of format:
1261 //Normally in Mode 2:
1262 //"ID:xxxxx", where xxxxx is some positive (non-zero) long integer number.
1263 //
1264 //Normally in Mode 1:
1265 //"xx.yy.zz.nn::pppp" (Ip address, 2 colons, port number)
1266 //"xx.yy.zz.nn:pppp" (Ip address, 1 colons, some number): This is a problematic case.
1267 //It is interpreted in the following way (copied directly from original repeater):
1268 //If pppp is < 100, it is a display number. If >= 100, it is a port number.
1269 //"xx.yy.zz.nn" (Only Ip Address): Default port number RFB_PORT_OFFSET is used
1270 //In mode 1, instead of ip address, also DNS hostname can be used in any combination with
1271 //port / display number
1272 if (checkIdCode(id)) {
1273 if ((allowedModes & CONN_MODE2) > 0) {
1274 connMode = CONN_MODE2;
1275
1276 //id is an IdCode string, parse it
1277 code = parseId(id);
1278 if (-1 == code) {
1279 debug(LEVEL_3, "acceptConnection(): parseId returned error, closing connection\n");
1280 close(connection);
1281 return;
1282 }
1283 debug(LEVEL_3, "acceptConnection(): %s sent code %ld \n",
1284 (connectionFrom == CONNECTION_FROM_VIEWER) ? "Viewer" : "Server", code);
1285
1286 //Check that there isn't similar ID:xxxx string in use
1287 //If similar ID:xxxx is found, refuse new connection
1288 int index;
1289 index = findDuplicateIdIndex(connectionFrom, code);
1290 if (index != -1) {
1291 debug(LEVEL_2, "acceptConnection(): duplicate ID string found, closing connection\n");
1292 close(connection);
1293 return;
1294 }
1295
1296 //If listed ID is required, check that ID matches one in list
1297 if (requireListedId) {
1298 if (!isCodeInIdList(code)) {
1299 debug(LEVEL_2,
1300 "acceptConnection(): Id code does not match codes in list, closing connection\n", code);
1301 close(connection);
1302 return;
1303 }
1304 }
1305 }
1306 else {
1307 debug(LEVEL_2, "acceptConnection(): mode 2 connections are not allowed, closing connection\n");
1308 close(connection);
1309 return;
1310 }
1311 }
1312 else {
1313 if ((allowedModes & CONN_MODE1) > 0) {
1314 connMode = CONN_MODE1;
1315
1316 //id is an [hostname / ip address] / [port number / display number] combination of some sort, parse it
1317 if (false == parseHostAndPort(id, host, MAX_HOST_NAME_LEN + 1, &port)) {
1318 debug(LEVEL_2, "acceptConnection(): parseHostAndPort returned error\n");
1319 close(connection);
1320 return;
1321 }
1322
1323 //check server port if not all allowed
1324 if (allowedMode1ServerPort != 0) {
1325 if (port != allowedMode1ServerPort) {
1326 debug(LEVEL_2, "acceptConnection(): connection to server port %d is not allowed,"
1327 " closing connection\n", port);
1328 close(connection);
1329 return;
1330 }
1331 }
1332 }
1333 else {
1334 debug(LEVEL_2, "acceptConnection(): mode 1 connections are not allowed, closing connection\n");
1335 close(connection);
1336 return;
1337 }
1338 }
1339
1340 if (connMode == CONN_MODE1) {
1341 if (connectionFrom == CONNECTION_FROM_VIEWER) {
1342 int server;
1343
1344 server = openConnectionToVncServer(host, (unsigned short) port, connMode1ServerIp);
1345 if (server == -1) {
1346 debug(LEVEL_2, "acceptConnection(): openConnectionToVncServer() failed\n");
1347 close(connection);
1348 return;
1349 }
1350 else {
1351 bool fServerOk ;
1352 bool fViewerOk;
1353 int viewerInd;
1354 int serverInd;
1355
1356 fServerOk = true;
1357 fViewerOk = true;
1358
1359 //Invent new unique connection code
1360 //Minus-side numbers are used for Mode1 sessions
1361 mode1ConnCode--;
1362 if (mode1ConnCode < MIN_INVENTED_CONN_CODE)
1363 mode1ConnCode = -1;
1364
1365 //Add new viewer
1366 viewerInd = addViewerList(connection, mode1ConnCode, peerIp);
1367 if (-1 != viewerInd) {
1368 setViewerActive(mode1ConnCode);
1369 }
1370 else
1371 fViewerOk = false; //Out of slots in viewer table
1372
1373 //Add new server
1374 serverInd = addServerList(server, mode1ConnCode, connMode1ServerIp);
1375 if (-1 != serverInd) {
1376 setServerActive(mode1ConnCode);
1377 }
1378 else
1379 fServerOk = false; //Out of slots in server table
1380
1381 if ((fServerOk) && (fViewerOk)) {
1382 //fork repeater
1383 forkRepeater(server, connection, mode1ConnCode);
1384
1385 //Send appropriate events to event interface
1386 //Here we post 3 events:
1387 //VIEWER_CONNECT, SERVER_CONNECT, VIEWER_SERVER_SESSION_START
1388 if (useEventInterface) {
1389 repeaterEvent event;
1390 connectionEvent connEv;
1391 sessionEvent sessEv;
1392 addrParts serverIp;
1393 addrParts viewerIp;
1394
1395 //Addresses in compact binary form
1396 viewerIp = getAddrPartsFromString(peerIp);
1397 serverIp = getAddrPartsFromString(connMode1ServerIp);
1398
1399 //VIEWER_CONNECT
1400 event.eventNum = VIEWER_CONNECT;
1401 event.timeStamp = time(NULL);
1402 event.repeaterProcessId = getpid();
1403
1404 connEv.tableIndex = viewerInd;
1405 connEv.code = mode1ConnCode;
1406 connEv.connMode = CONN_MODE1;
1407 connEv.peerIp = viewerIp;
1408 memcpy(event.extraInfo, &connEv, sizeof(connectionEvent));
1409 if (false == sendRepeaterEvent(event)) {
1410 debug(LEVEL_1, "acceptConnection(): Warning, event fifo is full\n");
1411 }
1412
1413 //SERVER_CONNECT
1414 event.eventNum = SERVER_CONNECT;
1415 event.timeStamp = time(NULL);
1416 event.repeaterProcessId = getpid();
1417
1418 connEv.tableIndex = serverInd;
1419 connEv.code = mode1ConnCode;
1420 connEv.connMode = CONN_MODE1;
1421 connEv.peerIp = serverIp;
1422 memcpy(event.extraInfo, &connEv, sizeof(connectionEvent));
1423 if (false == sendRepeaterEvent(event)) {
1424 debug(LEVEL_1, "acceptConnection(): Warning, event fifo is full\n");
1425 }
1426
1427 //VIEWER_SERVER_SESSION_START
1428 event.eventNum = VIEWER_SERVER_SESSION_START;
1429 event.timeStamp = time(NULL);
1430 event.repeaterProcessId = getpid();
1431
1432 sessEv.serverTableIndex = serverInd;
1433 sessEv.viewerTableIndex = viewerInd;
1434 sessEv.code = mode1ConnCode;
1435 sessEv.connMode = CONN_MODE1;
1436 sessEv.serverIp = serverIp;
1437 sessEv.viewerIp = viewerIp;
1438 memcpy(event.extraInfo, &sessEv, sizeof(sessionEvent));
1439 if (false == sendRepeaterEvent(event)) {
1440 debug(LEVEL_1, "acceptConnection(): Warning, event fifo is full\n");
1441 }
1442 }
1443 }
1444 else {
1445 //we have run out of slots in server or viewer table, refuse new connection
1446 if (!fServerOk) {
1447 debug(LEVEL_3, "acceptConnection(): Mode1: out of slots in server table, closing connection\n");
1448 close(server);
1449 }
1450
1451 if (!fViewerOk) {
1452 debug(LEVEL_3, "acceptConnection(): Mode1: out of slots in viewer table, closing connection\n");
1453 close(connection);
1454 }
1455
1456 return;
1457 }
1458 }
1459 }
1460 else {
1461 debug(LEVEL_3, "acceptConnection(): Mode 1 connections only allowed from viewers, closing connection\n");
1462 close(connection);
1463 return;
1464 }
1465 }
1466 else if (connMode == CONN_MODE2) {
1467 if (connectionFrom == CONNECTION_FROM_VIEWER) {
1468 int serverInd;
1469 int viewerInd;
1470
1471 viewerInd = addViewerList(connection, code, peerIp);
1472 if (-1 != viewerInd) {
1473 //Send VIEWER_CONNECT to event interface
1474 if (useEventInterface) {
1475 repeaterEvent event;
1476 connectionEvent connEv;
1477 addrParts viewerIp;
1478
1479 //Address in compact binary form
1480 viewerIp = getAddrPartsFromString(peerIp);
1481
1482 //VIEWER_CONNECT
1483 event.eventNum = VIEWER_CONNECT;
1484 event.timeStamp = time(NULL);
1485 event.repeaterProcessId = getpid();
1486
1487 connEv.tableIndex = viewerInd;
1488 connEv.code = code;
1489 connEv.connMode = CONN_MODE2;
1490 connEv.peerIp = viewerIp;
1491 memcpy(event.extraInfo, &connEv, sizeof(connectionEvent));
1492 if (false == sendRepeaterEvent(event)) {
1493 debug(LEVEL_1, "acceptConnection(): Warning, event fifo is full\n");
1494 }
1495 }
1496
1497 //New viewer, find respective server
1498 serverInd = findServerList(code);
1499 if (serverInd != UNKNOWN_REPINFO_IND) {
1500 int server;
1501
1502 //found respective server, activate viewer and server
1503 setViewerActive(code);
1504 setServerActive(code);
1505
1506 server = servers[serverInd] -> socket;
1507
1508 //kickstart viewer using handshake received previously (if any) from server
1509 if (handShakes[serverInd] -> handShakeLength > 0)
1510 writeExact(connection, handShakes[serverInd] -> handShake,
1511 handShakes[serverInd] -> handShakeLength, TIMEOUT_5SECS);
1512
1513 //fork repeater
1514 forkRepeater(server, connection, code);
1515
1516 //Send VIEWER_SERVER_SESSION_START to event interface
1517 if (useEventInterface) {
1518 repeaterEvent event;
1519 sessionEvent sessEv;
1520
1521 //VIEWER_SERVER_SESSION_START
1522 event.eventNum = VIEWER_SERVER_SESSION_START;
1523 event.timeStamp = time(NULL);
1524 event.repeaterProcessId = getpid();
1525
1526 sessEv.serverTableIndex = serverInd;
1527 sessEv.viewerTableIndex = viewerInd;
1528 sessEv.code = code;
1529 sessEv.connMode = CONN_MODE2;
1530 sessEv.serverIp = servers[serverInd] -> peerIp;
1531 sessEv.viewerIp = viewers[viewerInd] -> peerIp;
1532 memcpy(event.extraInfo, &sessEv, sizeof(sessionEvent));
1533 if (false == sendRepeaterEvent(event)) {
1534 debug(LEVEL_1, "acceptConnection(): Warning, event fifo is full\n");
1535 }
1536 }
1537 }
1538 else {
1539 debug(LEVEL_3, "acceptConnection(): respective server has not connected yet\n");
1540 }
1541 }
1542 else {
1543 //we have run out of slots in viewer table, refuse new connection
1544 debug(LEVEL_3, "acceptConnection(): Mode 2: out of slots in viewer table, closing connection\n");
1545 close(connection);
1546 return;
1547 }
1548 }
1549 else {
1550 int viewerInd;
1551 int serverInd;
1552
1553 //Add server to tables, initialize handshake to nil
1554 serverInd = addServerList(connection, code, peerIp);
1555 if (serverInd != -1) {
1556 handShakes[serverInd] -> handShakeLength = 0;
1557
1558 //Send SERVER_CONNECT to event interface
1559 if (useEventInterface) {
1560 repeaterEvent event;
1561 connectionEvent connEv;
1562
1563 //SERVER_CONNECT
1564 event.eventNum = SERVER_CONNECT;
1565 event.timeStamp = time(NULL);
1566 event.repeaterProcessId = getpid();
1567
1568 connEv.tableIndex = serverInd;
1569 connEv.code = code;
1570 connEv.connMode = CONN_MODE2;
1571 connEv.peerIp = servers[serverInd] -> peerIp;
1572 memcpy(event.extraInfo, &connEv, sizeof(connectionEvent));
1573 if (false == sendRepeaterEvent(event)) {
1574 debug(LEVEL_1, "acceptConnection(): Warning, event fifo is full\n");
1575 }
1576 }
1577
1578 //New server, find respective viewer
1579 viewerInd = findViewerList(code);
1580 if (viewerInd != UNKNOWN_REPINFO_IND) {
1581 int viewer;
1582
1583 //found respective viewer, activate server and viewer
1584 setServerActive(code);
1585 setViewerActive(code);
1586
1587 viewer = viewers[viewerInd] -> socket;
1588
1589 //fork repeater
1590 forkRepeater(connection, viewer, code);
1591
1592 //Send VIEWER_SERVER_SESSION_START to event interface
1593 if (useEventInterface) {
1594 repeaterEvent event;
1595 sessionEvent sessEv;
1596
1597 //VIEWER_SERVER_SESSION_START
1598 event.eventNum = VIEWER_SERVER_SESSION_START;
1599 event.timeStamp = time(NULL);
1600 event.repeaterProcessId = getpid();
1601
1602 sessEv.serverTableIndex = serverInd;
1603 sessEv.viewerTableIndex = viewerInd;
1604 sessEv.code = code;
1605 sessEv.connMode = CONN_MODE2;
1606 sessEv.serverIp = servers[serverInd] -> peerIp;
1607 sessEv.viewerIp = viewers[viewerInd] -> peerIp;
1608 memcpy(event.extraInfo, &sessEv, sizeof(sessionEvent));
1609 if (false == sendRepeaterEvent(event)) {
1610 debug(LEVEL_1, "acceptConnection(): Warning, event fifo is full\n");
1611 }
1612 }
1613 }
1614 else {
1615 debug(LEVEL_3, "acceptConnection(): respective viewer has not connected yet\n");
1616
1617 //Read servers' handshake string to buffer, for use when respective
1618 //viewer later connects and needs a kickstart
1619 if (serverInd != -1) {
1620 readPeerHandShake(connection, serverInd);
1621 }
1622 }
1623 }
1624 else {
1625 //we have run out of slots in server table, refuse new connection
1626 debug(LEVEL_3, "acceptConnection(): Mode 2: out of slots in server table, closing connection\n");
1627 close(connection);
1628 return;
1629 }
1630 }
1631 }
1632 }
1633 }
1634
1635 //Initialize listening on port.
1636 //Listening itself happens on function routeConnections
startListeningOnPort(listenPortInfo * pInfo)1637 static void startListeningOnPort(listenPortInfo * pInfo)
1638 {
1639 int yes = 1;
1640 struct sockaddr_in name;
1641
1642 pInfo->socket = socket(PF_INET, SOCK_STREAM, 0);
1643
1644 if (pInfo->socket < 0)
1645 fatal("startListeningOnPort(): socket() failed, errno=%d (%s)\n", errno, strerror(errno));
1646 else
1647 debug(LEVEL_3, "startListeningOnPort(): socket() initialized\n");
1648
1649 if (setsockopt(pInfo->socket, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(int)) == -1)
1650 fatal("startListeningOnPort(): setsockopt() failed, errno=%d (%s)\n", errno, strerror(errno));
1651 else
1652 debug(LEVEL_3, "startListeningOnPort(): setsockopt() success\n");
1653
1654 name.sin_family = AF_INET;
1655
1656 name.sin_port = htons(pInfo->port);
1657
1658 name.sin_addr.s_addr = inet_addr(ownIpAddress);
1659
1660 if (bind(pInfo->socket, (struct sockaddr *) &name, sizeof(name)) < 0)
1661 fatal("startListeningOnPort(): bind() to (ip: %s, port: %d) failed, errno=%d (%s)\n",
1662 ownIpAddress, pInfo -> port, errno, strerror(errno));
1663 else
1664 debug(LEVEL_3, "startListeningOnPort(): bind() to (ip: %s, port: %d) succeeded\n", ownIpAddress, pInfo->port);
1665
1666 if (listen(pInfo->socket, LISTEN_BACKLOG) < 0)
1667 fatal("startListeningOnPort(): listen() failed, errno=%d (%s)\n", errno, strerror(errno));
1668 else
1669 debug(LEVEL_3, "startListeningOnPort(): listen() succeeded\n");
1670
1671 }
1672
1673 //1976578th implementation of max(). Where was it in my system when I needed it ?
myMax(int valA,int valB)1674 static int myMax(int valA, int valB)
1675 {
1676 return (valA > valB) ? valA : valB;
1677 }
1678
1679 //Listen for new connections on both server and viewer ports,
1680 //call acceptConnection() to accept them.
1681 //Periodically also remove old inactive (or broken) connections by calling removeOldOrBrokenConnections()
1682 //Periodically call updateServerViewerInfo() to check changes in servers[]/viewers[] tables
routeConnections(int viewerSocket,int serverSocket)1683 static void routeConnections(int viewerSocket, int serverSocket)
1684 {
1685 int seconds;
1686 int heartBeatSeconds;
1687 fd_set readfds;
1688 int numfds;
1689 bool select_ok;
1690 struct timeval tv;
1691 const int SELECT_WAIT_SECONDS=1;
1692 const int CLEANUP_SECONDS=5;
1693 const int HEARTBEAT_SECONDS=90;
1694 startEndEvent seEv;
1695
1696 seconds = 0;
1697 heartBeatSeconds = 0;
1698 numfds = myMax(viewerSocket, serverSocket) + 1;
1699
1700 debug(LEVEL_0, "routeConnections(): starting select() loop, terminate with ctrl+c\n");
1701 while (stopped == false) {
1702 FD_ZERO(&readfds);
1703
1704 if (viewerSocket != -1)
1705 FD_SET(viewerSocket, &readfds);
1706
1707 if (serverSocket != -1)
1708 FD_SET(serverSocket, &readfds);
1709
1710 tv.tv_sec = SELECT_WAIT_SECONDS;
1711 tv.tv_usec = 0;
1712
1713 select_ok = true;
1714 if (-1 == select(numfds, &readfds, NULL, NULL, &tv)) {
1715 select_ok = false;
1716 if (stopped == false) {
1717 debug(LEVEL_2, "routeConnections(): select() failed, errno=%d (%s)\n", errno, strerror(errno));
1718 }
1719 }
1720
1721 if ((select_ok == true) && (stopped == false)) {
1722 //New viewer trying to connect ?
1723 if (viewerSocket != -1) {
1724 if (FD_ISSET(viewerSocket, &readfds)) {
1725 debug(LEVEL_3, "routeConnections(): new viewer connecting, accepting...\n");
1726 acceptConnection(viewerSocket, CONNECTION_FROM_VIEWER);
1727 }
1728 }
1729
1730 //New server trying to connect ?
1731 if (serverSocket != -1) {
1732 if (FD_ISSET(serverSocket, &readfds)) {
1733 debug(LEVEL_3, "routeConnections(): new server connecting, accepting...\n");
1734 acceptConnection(serverSocket, CONNECTION_FROM_SERVER);
1735 }
1736 }
1737
1738 //Remove old inactive connections, check after every 5 seconds
1739 seconds += SELECT_WAIT_SECONDS;
1740 if (seconds >= CLEANUP_SECONDS) {
1741 seconds = 0;
1742 removeOldOrBrokenConnections();
1743 }
1744
1745 //Send REPEATER_HEATBEAT to event interface every 90 seconds
1746 heartBeatSeconds += SELECT_WAIT_SECONDS;
1747 if (heartBeatSeconds >= HEARTBEAT_SECONDS) {
1748 heartBeatSeconds = 0;
1749 if (useEventInterface) {
1750 event.eventNum = REPEATER_HEARTBEAT;
1751 event.timeStamp = time(NULL);
1752 event.repeaterProcessId = getpid();
1753
1754 seEv.maxSessions = maxSessions;
1755 memcpy(event.extraInfo, &seEv, sizeof(startEndEvent));
1756
1757 if (false == sendRepeaterEvent(event)) {
1758 debug(LEVEL_1, "routeConnections(): Warning, event fifo is full\n");
1759 }
1760 }
1761 }
1762
1763 //Clean up after children (Repeaterprocs that have exited)
1764 cleanUpAfterRepeaterProcs();
1765
1766 //Handle event interface posting & cleanup
1767 handleRepeaterEvents();
1768 }
1769 }
1770 }
1771
1772
1773 //After doRepeater process has exited, this function reads exit code/pid and clears
1774 //servers[], viewers[] and repeaterProcs[] tables accordingly
cleanUpAfterRepeaterProcExit(int exitCode,pid_t pid)1775 static void cleanUpAfterRepeaterProcExit(int exitCode, pid_t pid) {
1776 long code;
1777 int index;
1778 int serverInd;
1779 int viewerInd;
1780
1781 debug(LEVEL_3, "cleanUpAfterRepeaterProcExit(): exitCode=%d, pid=%d\n", exitCode, pid);
1782 index = findRepeaterProcList(pid);
1783 if (index != UNKNOWN_REPINFO_IND) {
1784 code = repeaterProcs[index] -> code;
1785 serverInd = findServerList(code);
1786 viewerInd = findViewerList(code);
1787
1788 if ((serverInd != UNKNOWN_REPINFO_IND) && (viewerInd != UNKNOWN_REPINFO_IND)) {
1789 //Remove repeaterproc from list
1790 removeRepeaterProcList(pid);
1791
1792 debug(LEVEL_3, "cleanUpAfterRepeaterProcExit(): code=%ld, serverInd=%d, viewerInd=%d\n",
1793 code, serverInd, viewerInd);
1794
1795 //Send VIEWER_SERVER_SESSION_END to event interface
1796 if (useEventInterface) {
1797 repeaterEvent event;
1798 sessionEvent sessEv;
1799
1800 //VIEWER_SERVER_SESSION_END
1801 event.eventNum = VIEWER_SERVER_SESSION_END;
1802 event.timeStamp = time(NULL);
1803 event.repeaterProcessId = getpid();
1804
1805 sessEv.serverTableIndex = serverInd;
1806 sessEv.viewerTableIndex = viewerInd;
1807 sessEv.code = code;
1808 sessEv.connMode = (code < 0) ? CONN_MODE1 : CONN_MODE2;
1809 sessEv.serverIp = servers[serverInd] -> peerIp;
1810 sessEv.viewerIp = viewers[viewerInd] -> peerIp;
1811 memcpy(event.extraInfo, &sessEv, sizeof(sessionEvent));
1812 if (false == sendRepeaterEvent(event)) {
1813 debug(LEVEL_1, "cleanUpAfterRepeaterProcExit(): Warning, event fifo is full\n");
1814 }
1815 }
1816
1817 switch(exitCode) {
1818 case 1:
1819 //Error in select(), fall through
1820 case 2:
1821 //Server has disconnected, fall through
1822 case 3:
1823 //Viewer has disconnected, fall through
1824 case 4:
1825 //Error when reading from viewer, fall through
1826 case 5:
1827 //Error when reading from server
1828 debug(LEVEL_1, "cleanUpAfterRepeaterProcExit(): closing connection (server=%d, viewer=%d)\n",
1829 servers[serverInd] -> socket, viewers[viewerInd] -> socket);
1830 removeServerList(code);
1831 removeViewerList(code);
1832 break;
1833
1834 default:
1835 break;
1836 }
1837 }
1838 else {
1839 debug(LEVEL_2, "cleanUpAfterRepeaterProcExit(): illegal viewerInd = %d or serverInd =%d\n",
1840 viewerInd, serverInd);
1841 }
1842 }
1843 else {
1844 debug(LEVEL_2, "cleanUpAfterRepeaterProcExit(): proc not found\n");
1845 }
1846 }
1847
1848 //Check each possible children and clean up after they have exited
cleanUpAfterRepeaterProcs(void)1849 static void cleanUpAfterRepeaterProcs(void)
1850 {
1851 int status;
1852 pid_t pid;
1853 int i;
1854
1855 for(i = 0; i < maxSessions; i++) {
1856 if (repeaterProcs[i] -> code != 0) {
1857 pid = waitpid(repeaterProcs[i] -> pid, &status, WNOHANG);
1858 if (pid > 0) {
1859 cleanUpAfterRepeaterProcExit(WEXITSTATUS(status), pid);
1860 }
1861 }
1862 }
1863 }
1864
1865 //Terminate program with ctrl+c cleanly
handleSigInt(int s)1866 static void handleSigInt(int s)
1867 {
1868 stopped = true;
1869 }
1870
1871
1872 //Announce what initializations we got
listInitializationValues(void)1873 static void listInitializationValues(void)
1874 {
1875 int ii;
1876
1877 debug(LEVEL_2, "listInitializationValues(): viewerPort : %d\n", viewerPort);
1878 debug(LEVEL_2, "listInitializationValues(): serverPort : %d\n", serverPort);
1879 debug(LEVEL_2, "listInitializationValues(): maxSessions: %d\n", maxSessions);
1880 debug(LEVEL_2, "listInitializationValues(): loggingLevel: %d\n", loggingLevel);
1881 debug(LEVEL_2, "listInitializationValues(): ownIpAddress (0.0.0.0 = listen all interfaces) : %s\n", ownIpAddress);
1882 debug(LEVEL_2, "listInitializationValues(): runAsUser (if started as root) : %s\n", runAsUser);
1883
1884 debug(LEVEL_2, "listInitializationValues(): Mode 1 connections allowed : %s\n",
1885 ((allowedModes & CONN_MODE1) > 0) ? "Yes" : "No");
1886 debug(LEVEL_2, "listInitializationValues(): Mode 2 connections allowed : %s\n",
1887 ((allowedModes & CONN_MODE2) > 0) ? "Yes" : "No");
1888
1889 debug(LEVEL_2, "listInitializationValues(): Mode 1 allowed server port (0=All) : %d\n", allowedMode1ServerPort);
1890 debug(LEVEL_2, "listInitializationValues(): Mode 1 requires listed addresses : %s\n",
1891 (requireListedServer == 1) ? "Yes" : "No");
1892 if (requireListedServer == 1) {
1893 //Allow list
1894 if (LEVEL_2 <= loggingLevel) {
1895 debug(LEVEL_2, "listInitializationValues(): Mode 1 allowed servers/networks (255=Not allowed):");
1896 for(ii = 0; ii < SERVERS_LIST_SIZE; ii++) {
1897 fprintf(stderr, " %d.%d.%d.%d", srvListAllow[ii].a, srvListAllow[ii].b,
1898 srvListAllow[ii].c, srvListAllow[ii].d);
1899 }
1900 fprintf(stderr, "\n");
1901 }
1902
1903 //Deny list
1904 if (LEVEL_2 <= loggingLevel) {
1905 debug(LEVEL_2, "listInitializationValues(): Mode 1 denied servers/networks (255=Not denied):");
1906 for(ii = 0; ii < SERVERS_LIST_SIZE; ii++) {
1907 fprintf(stderr, " %d.%d.%d.%d", srvListDeny[ii].a, srvListDeny[ii].b, srvListDeny[ii].c, srvListDeny[ii].d);
1908 }
1909 fprintf(stderr, "\n");
1910 }
1911 }
1912
1913 debug(LEVEL_2, "listInitializationValues(): Mode 2 requires listed ID numbers : %s\n",
1914 (requireListedId == 1) ? "Yes" : "No");
1915
1916 if (requireListedId == 1) {
1917 if (LEVEL_2 <= loggingLevel) {
1918 debug(LEVEL_2, "listInitializationValues(): Mode 2 allowed ID list (0=Not allowed):");
1919
1920 for(ii = 0; ii < ID_LIST_SIZE; ii++) {
1921 fprintf(stderr, " %d", idList[ii]);
1922 }
1923 fprintf(stderr, "\n");
1924 }
1925 }
1926
1927 debug(LEVEL_2, "listInitializationValues(): useEventInterface: %s\n",
1928 (useEventInterface) ? "true" : "false");
1929
1930 debug(LEVEL_2, "listInitializationValues(): eventListenerHost : %s\n", eventListenerHost);
1931
1932 debug(LEVEL_2, "listInitializationValues(): eventListenerPort : %d\n", eventListenerPort);
1933
1934 debug(LEVEL_2, "listInitializationValues(): useHttpForEventListener : %s\n",
1935 (useHttpForEventListener) ? "true" : "false");
1936 }
1937
1938 //After bind() we drop to mere mortal privileges (in case we started as root)
1939 //to limit damages in case of security flaws in this program
1940 //In case of error, calls fatal() which sets up a clean exit from program
dropRootPrivileges()1941 static void dropRootPrivileges()
1942 {
1943 struct passwd *pw;
1944
1945 pw = getpwnam(runAsUser);
1946
1947 if (pw != NULL) {
1948 if (0 != setgid(pw -> pw_gid)) {
1949 fatal("dropRootPrivileges(): setgid() failed\n");
1950 }
1951
1952 if (0 != setuid(pw -> pw_uid)) {
1953 fatal("dropRootPrivileges(): setuid() failed\n");
1954 }
1955
1956 //We should now be mere mortal, check effective uid to be sure
1957 if (geteuid() == 0) {
1958 //Still root, was this intended ?
1959 if (strcmp("root", runAsUser) == 0) {
1960 //Intentionally root, complain about this security violation
1961 debug(LEVEL_1, "dropRootPrivileges(): you seem to WANT TO run as user root, this IS VERY DANGEROUS !\n");
1962 }
1963 else
1964 fatal("dropRootPrivileges(): dropping privileges failed\n");
1965 }
1966 else
1967 debug(LEVEL_1, "dropRootPrivileges(): privileges successfully dropped, now running as user %s\n", runAsUser);
1968 }
1969 else
1970 fatal("dropRootPrivileges(): getpwnam() failed\n");
1971 }
1972
1973
main(int argc,char ** argv)1974 int main(int argc, char **argv)
1975 {
1976 //Viewer port listener variable
1977 listenPortInfo viewerListener = {-1, -1};
1978
1979 //Server port listener variable
1980 listenPortInfo serverListener = {-1, -1};
1981
1982 //ctrl+c signal handler
1983 struct sigaction saInt;
1984
1985 //ini file default
1986 char defaultIniFilePathAndName[] = "/etc/uvncrepeater.ini";
1987 char tmpBuf[MAX_PATH];
1988 bool memoryOk;
1989
1990 //Startup event
1991 startEndEvent seEv;
1992
1993 stopped = false;
1994 mode1ConnCode = 0;
1995
1996 fprintf(stderr, "UltraVnc Linux Repeater version %s\n", REPEATER_VERSION);
1997
1998 //Read parameters from ini file
1999 strlcpy(tmpBuf, (argc >= 2) ? argv[1] : defaultIniFilePathAndName, MAX_PATH);
2000 if (false == readIniFile(tmpBuf)) {
2001 debug(LEVEL_1, "main(): ini file (%s) read error, using defaults\n", tmpBuf);
2002 }
2003 listInitializationValues();
2004
2005 //Send startup event to event interface
2006 initRepeaterEventInterface();
2007 if (useEventInterface) {
2008 event.eventNum = REPEATER_STARTUP;
2009 event.timeStamp = time(NULL);
2010 event.repeaterProcessId = getpid();
2011
2012 seEv.maxSessions = maxSessions;
2013 memcpy(event.extraInfo, &seEv, sizeof(startEndEvent));
2014
2015 //Event fifo can not be full here ;-)
2016 sendRepeaterEvent(event);
2017 }
2018
2019 //Allocate and clean various repeater lists
2020 if (false == allocateMemoryForRepeaterLists(maxSessions)) {
2021 debug(LEVEL_0, "main(): memory allocation for repeater lists failed, exiting program\n");
2022 memoryOk = false;
2023 }
2024 else {
2025 memoryOk = true;
2026 cleanLists();
2027 }
2028
2029 //If we got lists allocated, we can run
2030 if (memoryOk) {
2031 //Initialize ctrl+c signal handler
2032 memset(&saInt, 0, sizeof(saInt));
2033
2034 //Restart interrupted system calls after handler returns
2035 saInt.sa_flags = SA_RESTART;
2036 saInt.sa_handler = &handleSigInt;
2037 sigaction(SIGINT, &saInt, NULL);
2038
2039 //Initialize and start listening on viewer port
2040 if (((allowedModes & CONN_MODE1) > 0) || ((allowedModes & CONN_MODE2) > 0)) {
2041 viewerListener.port = viewerPort;
2042 startListeningOnPort(&viewerListener);
2043 }
2044
2045 //Initialize and start listening on server port
2046 if ((allowedModes & CONN_MODE2) > 0) {
2047 serverListener.port = serverPort;
2048 startListeningOnPort(&serverListener);
2049 }
2050
2051 //Drop root privileges (if we are running as root) after all listen ports have been bound
2052 if (geteuid() == 0) {
2053 dropRootPrivileges();
2054 }
2055
2056 //Accept & Route new connections
2057 if (stopped == false) {
2058 routeConnections(viewerListener.socket, serverListener.socket);
2059 }
2060
2061 close(viewerListener.socket);
2062 close(serverListener.socket);
2063 }
2064
2065 //Free allocated memory of repeater lists
2066 freeMemoryOfRepeaterLists();
2067
2068 //Send shutdown event to event interface
2069 if (useEventInterface) {
2070 event.eventNum = REPEATER_SHUTDOWN;
2071 event.timeStamp = time(NULL);
2072 event.repeaterProcessId = getpid();
2073
2074 seEv.maxSessions = maxSessions;
2075 memcpy(event.extraInfo, &seEv, sizeof(startEndEvent));
2076 if (false == sendRepeaterEvent(event)) {
2077 debug(LEVEL_1, "main(): Warning, event fifo is full\n");
2078 }
2079 handleRepeaterEvents();
2080 }
2081
2082 debug(LEVEL_0, "main(): relaying done.\n");
2083
2084 return 0;
2085 }
2086