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