1 /*
2 ** This file is part of "zebedee".
3 **
4 ** Copyright 1999-2005 by Neil Winton. All rights reserved.
5 **
6 ** This program is free software; you can redistribute it and/or modify
7 ** it under the terms of the GNU General Public License as published by
8 ** the Free Software Foundation; either version 2 of the License, or
9 ** (at your option) any later version.
10 **
11 ** This program is distributed in the hope that it will be useful,
12 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
13 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14 ** GNU General Public License for more details.
15 **
16 ** You should have received a copy of the GNU General Public License
17 ** along with this program; if not, write to the Free Software
18 ** Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19 **
20 ** For further details on "zebedee" see http://www.winton.org.uk/zebedee/
21 **
22 */
23 
24 char *zebedee_c_rcsid = "$Id: zebedee.c,v 1.49 2005/09/02 22:20:23 ndwinton Exp $";
25 #define RELEASE_STR "2.5.3"
26 
27 #include <stdio.h>
28 #include <stdlib.h>
29 #include <string.h>
30 #include <stdarg.h>
31 #include <assert.h>
32 #include <errno.h>
33 #include <time.h>
34 #include <ctype.h>
35 #include <fcntl.h>
36 #include <signal.h>
37 
38 #ifdef USE_GMP_LIBRARY
39 #include "gmp.h"
40 #else
41 #include "huge.h"
42 /*
43 ** Zebedee originally used the GMP library (and this can still be enabled
44 ** by defining USE_GMP_LIBRARY) but for reasons of portability it now uses
45 ** the "Huge" number routines bundled with the Zebedee distribution. GMP
46 ** is a very high-quality library but is hard to port to non-UN*X/gcc
47 ** environments.
48 **
49 ** The function calls used in the code are, however, still GMP-compatible
50 ** through the use of the following macro definitions.
51 */
52 
53 typedef Huge *mpz_t;
54 
55 #define mpz_init(z)
56 #define mpz_init_set_str(z, s, n)   (z = huge_from_string(s, NULL, n))
57 #define mpz_powm(k, g, e, m)	    (k = huge_powmod(g, e, m))
58 #define mpz_get_str(p, n, z)	    huge_format(z, n)
59 #define mpz_clear(z)		    huge_free(z)
60 #endif
61 
62 #include "blowfish.h"
63 #include "zlib.h"
64 #ifndef DONT_HAVE_BZIP2
65 #include "bzlib.h"
66 #endif
67 #include "sha.h"
68 
69 #ifdef __CYGWIN__
70 #undef WIN32
71 #endif
72 
73 /*
74 ** Named mutex values (see mutexLock/Unlock)
75 */
76 
77 #define MUTEX_IO	0   /* Mutex to protect stdio and other library calls */
78 #define MUTEX_KEYLIST	1   /* Mutex to protect key list access */
79 #define MUTEX_TOKEN	2   /* Mutex to protect token allocation/access */
80 #define MUTEX_HNDLIST	3   /* Mutex to protect UDP handler list access */
81 #define	MUTEX_ACTIVE	4   /* Mutex to protect count of active handlers */
82 #define MUTEX_MAX	5   /* How many mutexes will we use? */
83 
84 /*
85 ** Named condition variables
86 */
87 
88 #define COND_ACTIVE	0   /* Condition for change in active handler count */
89 #define COND_MAX	1   /* How many condition variables? */
90 
91 /* BUG COMPATIBILITY -- REMOVE FOR PRODUCTION RELEASE */
92 #define BUGHTONL(x) (BugCompatibility == 251 ? (x) : htonl(x))
93 #define BUGNTOHL(x) (BugCompatibility == 251 ? (x) : ntohl(x))
94 
95 #ifdef WIN32
96 /*
97 ** Windows-specific include files and macros
98 */
99 
100 #ifndef FD_SETSIZE
101 /*
102 ** This allows us to manipulate up to 512 sockets in a select call (i.e.
103 ** handle up to about 250 simultaneous tunnels). It can be overridden at
104 ** compile time.
105 */
106 #define FD_SETSIZE	512
107 #endif
108 
109 #include <windows.h>
110 #include <io.h>
111 #include <winsock.h>
112 #include <process.h>
113 #include <mmsystem.h>
114 
115 #include "getopt.h"
116 
117 #define DFLT_SHELL	"c:\\winnt\\system32\\cmd.exe"
118 #define getpid()	GetCurrentProcessId()
119 #define FILE_SEP_CHAR	'\\'
120 #define snprintf	_snprintf
121 #define vsnprintf	_vsnprintf
122 #define strcasecmp	_stricmp
123 #define ETIMEDOUT	WSAETIMEDOUT
124 #define EWOULDBLOCK	WSAEWOULDBLOCK
125 #define EINPROGRESS	WSAEINPROGRESS
126 
127 /*
128 ** Winsock state data
129 */
130 
131 static struct WSAData WsaState;
132 
133 /*
134 ** Global Mutexes and Condition Variables
135 */
136 
137 CRITICAL_SECTION Mutex[MUTEX_MAX];
138 HANDLE Condition[COND_MAX];
139 
140 extern void svcRun(char *name, VOID (*function)(VOID *), VOID *arg);
141 extern int svcInstall(char *name, char *configFile);
142 extern int svcRemove(char *name);
143 
144 #else /* !WIN32 */
145 
146 #include <sys/types.h>
147 #include <sys/time.h>
148 #include <sys/times.h>
149 #include <sys/socket.h>
150 #ifndef DONT_HAVE_SELECT_H
151 #include <sys/select.h>
152 #endif
153 #include <sys/stat.h>
154 #include <sys/wait.h>
155 #include <dirent.h>
156 #include <netinet/in.h>
157 #include <arpa/inet.h>
158 #include <netdb.h>
159 #include <unistd.h>
160 #include <syslog.h>
161 #ifdef USE_UDP_SPOOFING
162 #include <libnet.h>
163 #endif
164 #include <pwd.h>
165 
166 #ifndef INADDR_NONE
167 #define INADDR_NONE 0xffffffff
168 #endif
169 
170 #define DFLT_SHELL	"/bin/sh"
171 #define FILE_SEP_CHAR	'/'
172 
173 #define closesocket(fd)	    close((fd))
174 
175 #ifdef HAVE_PTHREADS
176 #include <pthread.h>
177 
178 pthread_mutex_t Mutex[MUTEX_MAX];
179 pthread_cond_t Condition[COND_MAX];
180 pthread_attr_t ThreadAttr;
181 #endif
182 #endif
183 
184 #ifndef MIN
185 #define MIN(a, b)   ((a) < (b) ? (a) : (b))
186 #endif
187 
188 /**************************\
189 **			  **
190 **  Constants and Macros  **
191 **			  **
192 \**************************/
193 
194 #define MAX_BUF_SIZE	16383	/* Maximum network buffer size (< 2^14) */
195 #define DFLT_BUF_SIZE	8192	/* Default network buffer size */
196 #define MAX_LINE_SIZE	1024	/* Maximum file line size */
197 #define MAX_KEY_BYTES	((BF_ROUNDS + 2)*4) /* Maximum size of Blowfish key */
198 #define	MIN_KEY_BYTES	5	/* Minimum key length */
199 #define MAX_LISTEN	5	/* Depth of listen queue */
200 #define MAX_INCLUDE	5	/* Maximum depth of include files */
201 #define MAX_KEYGEN_LEVEL 2	/* Maximum key generation strength level */
202 
203 #define HASH_STR_SIZE	41	/* Size of SHA hash string including null */
204 #define TIMESTAMP_SIZE	20	/* Size of YYYY-dd-mm-HH:MM:SS timestamp */
205 #define CHALLENGE_SIZE	4	/* Size of challenge data */
206 #define THE_ANSWER	42	/* To Life, the Universe and Everything */
207 #define CHALLENGE_SIZE	4	/* Size of challenge data */
208 #define NONCE_SIZE	8	/* Size of nonce data */
209 
210 #ifndef THREAD_STACK_SIZE
211 #define THREAD_STACK_SIZE   65536   /* Stack size for threads */
212 #endif
213 #define MIN_THREAD_STACK_KB 16	/* Minimum allowable thread stack in kb */
214 #define	CMP_OVERHEAD	250	/* Maximum overhead on 16k message */
215 #define	CMP_MINIMUM	32	/* Minimum message size to attempt compression */
216 
217 #define IP_BUF_SIZE	16	/* Size of buffer for IP address string */
218 
219 /*
220 ** Information about the compression algorithm and level is encoded in
221 ** a single unsigned short value. The high 8 bits are the algorithm and
222 ** the low eight bits the level. Note that the values used ensure that
223 ** taken as a 16-bit quantity all bzip2 values are greater than all
224 ** zlib values. This fact is used so that, in effect, bzip2 compression
225 ** is considered "stronger" than zlib.
226 */
227 
228 #define CMPTYPE_ZLIB	0x0
229 #define CMPTYPE_BZIP2	0x1
230 #define GET_CMPTYPE(z)	    (((z) >> 8) & 0xff)
231 #define SET_CMPTYPE(z, t)   ((z) | ((t) << 8))
232 #define GET_CMPLEVEL(z)	    ((z) & 0xff)
233 #define SET_CMPLEVEL(z, l)  ((z) | ((l) & 0xff))
234 
235 /*
236 ** Each message that Zebedee transmits is preceded by an unsigned short
237 ** value (in big-endian format). The top two bits flag whether the message
238 ** is encrypted and compressed. The lower 14 bits define the payload size
239 ** (which must be no greater than MAX_BUF_SIZE).
240 */
241 
242 #define FLAG_COMPRESSED	0x1
243 #define FLAG_ENCRYPTED	0x2
244 
245 #define CHECKSUM_NONE		0
246 #define CHECKSUM_ADLER		1
247 #define CHECKSUM_CRC32		2
248 #define CHECKSUM_SHA		3
249 #define CHECKSUM_MAX		CHECKSUM_SHA
250 #define CHECKSUM_ADLER_LEN	4	/* ADLER32 32-bit checksum */
251 #define CHECKSUM_CRC32_LEN	4	/* CRC32 32-bit checksum */
252 #define CHECKSUM_SHA_LEN	20	/* SHA 160-bit message digest */
253 #define CHECKSUM_MAX_LEN	CHECKSUM_SHA_LEN /* Max message digest */
254 #define CHECKSUM_INVALID	0xffff
255 
256 #define GET_FLAGS(x)	(((x) >> 14) & 0x3)
257 #define SET_FLAGS(x, f)	((x) | ((f) << 14))
258 
259 #define GET_SIZE(x)	((x) & 0x3fff)
260 
261 #define DFLT_GENERATOR	    "2"	    /* Default generator value */
262 #define DFLT_MODULUS	    	    /* Default modulus value */ \
263 "f488fd584e49dbcd20b49de49107366b336c380d451d0f7c88b31c7c5b2d8ef6" \
264 "f3c923c043f0a55b188d8ebb558cb85d38d334fd7c175743a31d186cde33212c" \
265 "b52aff3ce1b1294018118d7c84a70a72d686c40319c807297aca950cd9969fab" \
266 "d00a509b0246d3083d66a45d419f9c7cbd894b221926baaba25ec355e92f78c7"
267 #define DFLT_CMP_LEVEL	    SET_CMPLEVEL(CMPTYPE_ZLIB, 6)
268 #define DFLT_KEY_BITS	    128	    /* Default key size */
269 #define DFLT_TCP_PORT	    0x2EBD  /* Port on which TCP-mode server listens */
270 #define DFLT_UDP_PORT	    0x2BDE  /* Port on which UDP-mode server listens */
271 #define DFLT_KEY_LIFETIME   3600    /* Reuseable keys last an hour */
272 #define DFLT_TCP_TIMEOUT    0	    /* Default never close idle TCP tunnels */
273 #define DFLT_UDP_TIMEOUT    300	    /* Close UDP tunnels after 5 mins */
274 #define DFLT_CONNECT_TIMEOUT	300 /* Timeout for making/accepting connection */
275 
276 #define PROTOCOL_V100	    0x0100  /* The original and base */
277 #define PROTOCOL_V101	    0x0101  /* Extended buffer size */
278 #define PROTOCOL_V102	    0x0102  /* Optionally omit key exchange */
279 #define PROTOCOL_V200	    0x0200  /* Header, UDP and reusable key support */
280 #define PROTOCOL_V201	    0x0201  /* Remote target selection */
281 #define PROTOCOL_V202	    0x0202  /* Lock of protocol negotiation, checksum and source based targetting */
282 #define DFLT_PROTOCOL	    PROTOCOL_V202
283 
284 #define TOKEN_NEW	    0xffffffff	/* Request new token allocation */
285 #define TOKEN_EXPIRE_GRACE  10		/* CurrentToken valid until this close to expiry */
286 
287 #define HDR_SIZE_V200	    22	/* Size of V200 protocol header message */
288 #define HDR_SIZE_V201	    26	/* Size of V201 protocol header message */
289 #define HDR_SIZE_V202	    28	/* Size of V202 protocol header message */
290 #define HDR_SIZE_MIN	    HDR_SIZE_V200
291 #define HDR_SIZE_MAX	    HDR_SIZE_V202
292 
293 #define HDR_OFFSET_FLAGS    0	/* Offset of flags (TCP vs UDP) */
294 #define HDR_OFFSET_MAXSIZE  2	/* Offset of max message size */
295 #define HDR_OFFSET_CMPINFO  4	/* Offset of compression info */
296 #define HDR_OFFSET_PORT	    6	/* Offset of port request */
297 #define HDR_OFFSET_KEYLEN   8	/* Offset of key length */
298 #define HDR_OFFSET_TOKEN    10	/* Offset of key token */
299 #define HDR_OFFSET_NONCE    14	/* Offset of nonce value */
300 #define HDR_OFFSET_TARGET   22	/* Offset of target host address */
301 #define HDR_OFFSET_CHECKSUM 26	/* Offset of checksum type */
302 
303 #define HDR_FLAG_UDPMODE    0x1	/* Operate in UDP mode */
304 
305 #define ENDPTLIST_TCP	    0x1	/* TCP-type port list */
306 #define ENDPTLIST_UDP	    0x2	/* UDP-type port list */
307 #define ENDPTLIST_ANY	    (ENDPTLIST_TCP | ENDPTLIST_UDP)
308 
309 /***************************\
310 **			   **
311 **  Data Type Definitions  **
312 **			   **
313 \***************************/
314 
315 /*
316 ** The BFState_t structure holds all the state information necessary
317 ** to encrypt one data-stream (unidirectional).
318 */
319 
320 #define	INIT_IVEC	"Time4Bed"  /* ... said Zebedee. Boing! */
321 typedef struct
322 {
323     BF_KEY key;
324     unsigned char iVec[8];
325     int pos;
326     unsigned char cryptBuf[MAX_BUF_SIZE];
327 }
328 BFState_t;
329 
330 /*
331 ** The EndPtList_t structure holds the information about a network end-point,
332 ** or range of similar end-point with ports from "lo" to "hi". A single
333 ** end-point value has both hi and lo set the same. A linked list of these
334 ** structures holds information about a set of ranges.
335 **
336 ** The host element holds the name of the host associated with the end-
337 ** point, addr the matching IP address and addrList, a list of alias
338 ** addresses. The mask is used if an address mask was specified. The type
339 ** is a bitmask combination of ENDPTLIST_TCP and ENDPTLIST_UDP. The idFile
340 ** is the name of the identity file that should be checked for connections
341 ** to this endpoint. If peer is not NULL then it is a list of valid
342 ** peer connections for this endpoint.
343 */
344 
345 typedef struct EndPtList_s
346 {
347     unsigned short lo;
348     unsigned short hi;
349     char *host;
350     struct sockaddr_in addr;
351     struct in_addr *addrList;
352     struct EndPtList_s *next;
353     unsigned long mask;
354     unsigned short type;
355     char *idFile;
356     struct EndPtList_s *peer;
357 }
358 EndPtList_t;
359 
360 /*
361 ** The MsgBuf_t is the general buffer used by the low-level readMessage
362 ** and writeMessage routines. It holds (nearly) all of the state for
363 ** a single connection.
364 */
365 
366 typedef struct MsgBuf_s
367 {
368     unsigned short maxSize;	/* Max size of data buffer read/writes */
369     unsigned short size;	/* Size of current message */
370     unsigned char data[MAX_BUF_SIZE + CHECKSUM_MAX_LEN]; /* Data buffer */
371     unsigned char tmp[MAX_BUF_SIZE + CMP_OVERHEAD + CHECKSUM_MAX_LEN]; /* Temporary work space */
372     unsigned short cmpInfo;	/* Compression level and type */
373     BFState_t *bfRead;		/* Encryption context for reads */
374     BFState_t *bfWrite;		/* Encryption context for writes */
375     unsigned long readCount;	/* Number of reads */
376     unsigned long bytesIn;	/* Actual data bytes from network */
377     unsigned long expBytesIn;	/* Expanded data bytes in */
378     unsigned long writeCount;	/* Number of writes */
379     unsigned long bytesOut;	/* Actual data bytes to network */
380     unsigned long expBytesOut;	/* Expanded data bytes out */
381     unsigned short checksumLevel;   /* Current checksum mode, 0 if none */
382     unsigned short checksumLen;	    /* Current checksum length, 0 if none */
383     unsigned char inSeed[CHECKSUM_MAX_LEN];	/* Seed for input checksum */
384     unsigned char outSeed[CHECKSUM_MAX_LEN];    /* Seed for output checksum */
385 }
386 MsgBuf_t;
387 
388 /*
389 ** These enumerated type values are used to indicate the destination of
390 ** log messages.
391 */
392 
393 typedef enum
394 {
395     LOGFILE_NULL,
396     LOGFILE_SYSLOG,
397     LOGFILE_LOCAL
398 }
399 LogType_t;
400 
401 /*
402 ** The KeyInfo_t structure holds the mapping between a key "token" value
403 ** used to request the reuse of a previously established shared secret
404 ** key and the key value itself. These structures are strung together in
405 ** a doubly linked list.
406 */
407 
408 typedef struct KeyInfo_s
409 {
410     unsigned long token;
411     char *key;
412     time_t expiry;
413     struct KeyInfo_s *prev;
414     struct KeyInfo_s *next;
415 }
416 KeyInfo_t;
417 
418 /*
419 ** This structure is used to pass the arguments to the main "handler"
420 ** thread routines (client() and server()).
421 */
422 
423 typedef struct FnArgs_s
424 {
425     int fd;
426     unsigned short port;
427     struct sockaddr_in addr;
428     int listenFd;
429     int inLine;
430     int udpMode;
431 }
432 FnArgs_t;
433 
434 /*
435 ** This structure is used in UDP mode to find the local socket for
436 ** the handler for traffic coming from a specific client.
437 */
438 
439 typedef struct HndInfo_s
440 {
441     unsigned long id;
442     int fd;
443     struct sockaddr_in fromAddr;
444     struct sockaddr_in localAddr;
445     struct HndInfo_s *prev;
446     struct HndInfo_s *next;
447 }
448 HndInfo_t;
449 
450 /*****************\
451 **		 **
452 **  Global Data  **
453 **		 **
454 \*****************/
455 
456 /*
457 ** Note: Although this data is global most of it is not protected by mutex
458 ** locks because once set in the start-up phases of the program it is
459 ** read-only by the rest of the routines.
460 */
461 
462 FILE *LogFileP = NULL;		/* File handle for log file (NULL => stderr) */
463 LogType_t LogFileType = LOGFILE_LOCAL;	/* Type of log file */
464 unsigned short LogLevel = 1;	/* Message verbosity level */
465 char *Program = "zebedee";	/* Program name (argv[0]) */
466 char *Generator = "";		/* DH generator hex string ("" => default) */
467 char *Modulus = "";		/* DH modulus hex string ("" => default) */
468 char *PrivateKey = NULL;	/* Private key hex string */
469 unsigned short KeyLength = DFLT_KEY_BITS;	/* Key length in bits */
470 unsigned short MinKeyLength = 0;		/* Minimum allowed key length */
471 unsigned short CompressInfo = DFLT_CMP_LEVEL;	/* Compression type and level */
472 int IsDetached = 1;		/* Flag true if program should run detached */
473 int IsServer = 0;		/* Flag true if program is a server */
474 int Debug = 0;			/* Debug mode -- single threaded server */
475 char *CommandString = NULL;	/* Command string to execute (client) */
476 unsigned short ServerPort = 0;	/* Port on which server listens */
477 EndPtList_t *ClientPorts = NULL;	/* Ports on which client listens */
478 EndPtList_t *TargetPorts = NULL;	/* Target port to which to tunnel */
479 char *ServerHost = NULL;	/* Name of host on which server runs */
480 char *TargetHost = "localhost";	/* Default host to which tunnels are targeted */
481 char *IdentityFile = NULL;	/* Name of identity file to check, if any */
482 EndPtList_t *AllowedTargets = NULL; /* List of allowed target hosts/ports */
483 EndPtList_t *AllowedDefault = NULL; /* List of default allowed redirection ports */
484 EndPtList_t *AllowedPeers = NULL; /* List of allowed peer addresses/ports */
485 char *KeyGenCmd = NULL;		/* Key generator command string */
486 unsigned short KeyGenLevel = MAX_KEYGEN_LEVEL;	/* Key generation strength level */
487 int LockProtocol = 0;		/* Is procol negotiation locked? */
488 int DropUnknownProtocol = 0;	/* Allow any request? */
489 int TimestampLog = 0;		/* Should messages have timestamps? */
490 int MultiUse = 1;		/* Client handles multiple connections? */
491 unsigned short MaxBufSize = DFLT_BUF_SIZE;  /* Maximum buffer size */
492 unsigned long CurrentToken = 0;	/* Client reuseable key token */
493 unsigned short KeyLifetime = DFLT_KEY_LIFETIME;	/* Key lifetime in seconds */
494 unsigned short ChecksumLevel = CHECKSUM_CRC32;	/* Type of checksum embedded in the message. Default CRC32 */
495 unsigned short MinChecksumLevel = CHECKSUM_NONE;
496 int UdpMode = 0;		/* Run in UDP mode */
497 int TcpMode = 1;		/* Run in TCP mode */
498 unsigned short TcpTimeout = DFLT_TCP_TIMEOUT;	/* TCP inactivity timeout */
499 unsigned short UdpTimeout = DFLT_UDP_TIMEOUT;	/* UDP inactivity timeout */
500 char *ListenIp = NULL;		/* IP address on which to listen */
501 int ListenMode = 0;		/* True if client waits for server connection */
502 char *ClientHost = NULL;	/* Server initiates connection to client */
503 int ListenSock = -1;		/* Socket on which to listen for server */
504 unsigned short ServerConnectTimeout = DFLT_CONNECT_TIMEOUT; /* Timeout for server connections */
505 unsigned short AcceptConnectTimeout = DFLT_CONNECT_TIMEOUT; /* Timeout for client to accept connections */
506 unsigned short TargetConnectTimeout = DFLT_CONNECT_TIMEOUT; /* Timeout for connection to target */
507 unsigned short ConnectAttempts = 1; /* Number of server-initiated connection attempts */
508 unsigned short ReadTimeout = 0; /* Timeout for remote data reads */
509 int ActiveCount = 0;		/* Count of active handlers */
510 char *ProxyHost = NULL;		/* HTTP proxy host, if used */
511 char *ProxyAuth = NULL;		/* HTTP proxy username:password, if used */
512 unsigned short ProxyPort = 0;	/* HTTP proxy port, if used */
513 int Transparent = 0;		/* Try to propagate the client IP address */
514 char *FieldSeparator = NULL;	/* Input field separator character */
515 char *SharedKey = NULL;		/* Static shared secret key */
516 char *SharedKeyGenCmd = NULL;	/* Command to generate shared secret key */
517 int DumpData = 0;		/* Dump out message contents only if true */
518 #ifndef WIN32
519 uid_t ProcessUID = -1;		/* User id to run zebedee process if started as root */
520 gid_t ProcessGID = -1;          /* Group id to run zebedee process if started as root */
521 #endif
522 long ThreadStackSize = THREAD_STACK_SIZE; /* As it says */
523 unsigned short BugCompatibility = 0;	/* Be nice to development users */
524 unsigned short MaxConnections = 0;      /* Maximum number of simultaneous connections */
525 
526 extern char *optarg;		/* From getopt */
527 extern int optind;		/* From getopt */
528 
529 /*
530 ** The following global data-structure ARE modified during normal operation
531 ** and are protected by mutexes.
532 **
533 ** The ClientKeyList and ServerKeyList are protected by the MUTEX_KEYLIST
534 ** and the HandlerList by MUTEX_HNDLIST.
535 */
536 
537 KeyInfo_t ClientKeyList = { 0, NULL, (time_t)0, NULL, NULL };
538 				/* Client-side list of token->key mappings */
539 KeyInfo_t ServerKeyList = { 0, NULL, (time_t)0, NULL, NULL };
540 				/* Server-side list of token->key mappings */
541 HndInfo_t HandlerList;		/* List of address to handler mappings */
542 
543 
544 /*************************\
545 **			 **
546 **  Function Prototypes  **
547 **			 **
548 \*************************/
549 
550 void threadInit(void);
551 void mutexInit(void);
552 void mutexLock(int num);
553 void mutexUnlock(int num);
554 void conditionInit(void);
555 void conditionSignal(int num);
556 void conditionWait(int condNum, int mutexNum);
557 unsigned long threadPid(void);
558 unsigned long threadTid(void);
559 int incrActiveCount(int num);
560 void waitForInactivity(void);
561 
562 void logToSystemLog(unsigned short level, char *msg);
563 void timestamp(char *timeBuf, int local);
564 void message(unsigned short level, int err, char *fmt, ...);
565 void dumpData(const char *prefix, unsigned char *data, unsigned short size);
566 
567 int readData(int fd, unsigned char *buffer, unsigned short size);
568 int readUShort(int fd, unsigned short *resultP);
569 int writeData(int fd, unsigned char *buffer, unsigned short size);
570 int writeUShort(int fd, unsigned short value);
571 
572 MsgBuf_t *makeMsgBuf(unsigned short maxSize, unsigned short cmpInfo, unsigned short checksumLevel);
573 void freeMsgBuf(MsgBuf_t *msg);
574 void getMsgBuf(MsgBuf_t *msg, void *buffer, unsigned short size);
575 void setMsgBuf(MsgBuf_t *msg, void *buffer, unsigned short size);
576 
577 int readMessage(int fd, MsgBuf_t *msg, unsigned short thisSize);
578 int writeMessage(int fd, MsgBuf_t *msg);
579 
580 int requestResponse(int fd, unsigned short request, unsigned short *responseP);
581 
582 int getHostAddress(const char *host, struct sockaddr_in *addrP, struct in_addr **addrList, unsigned long *maskP);
583 char *ipString(struct in_addr addr, char *buf);
584 int makeConnection(const char *host, const unsigned short port, int udpMode, int useProxy, struct sockaddr_in *fromAddrP, struct sockaddr_in *toAddrP, unsigned short timeout);
585 int proxyConnection(const char *host, const unsigned short port, struct sockaddr_in *localAddrP, unsigned short timeout);
586 int sendSpoofed(int fd, char *buf, int len, struct sockaddr_in *toAddrP, struct sockaddr_in *fromAddrP);
587 int makeListener(unsigned short *portP, char *listenIp, int udpMode, int listenQueue);
588 void setNoLinger(int fd);
589 void setKeepAlive(int fd);
590 void setNonBlocking(int fd, unsigned long nonBlock);
591 int acceptConnection(int listenFd, const char *host, int loop, unsigned short timeout);
592 int socketIsUsable(int sock);
593 
594 void headerSetUShort(unsigned char *hdrBuf, unsigned short value, int offset);
595 void headerSetULong(unsigned char *hdrBuf, unsigned long value, int offset);
596 unsigned short headerGetUShort(unsigned char *hdrBuf, int offset);
597 unsigned long headerGetULong(unsigned char *hdrBuf, int offset);
598 
599 BFState_t *setupBlowfish(char *keyStr, unsigned short keyBits);
600 char *generateKey(struct sockaddr_in *peerAddrP, struct sockaddr_in *targetAddrP, unsigned short targetPort);
601 char *runKeyGenCommand(char *keyGenCmd, struct sockaddr_in *peerAddrP, struct sockaddr_in *targetAddrP, unsigned short targetPort);
602 void generateNonce(unsigned char *);
603 char *generateSessionKey(char *secretKey, unsigned char *cNonce, unsigned char *sNonce, unsigned short bits);
604 unsigned short hexStrToBits(char *hexStr, unsigned short bits, unsigned char *bitVec);
605 char *diffieHellman(char *genStr, char *modStr, char *expStr);
606 void makeChallenge(unsigned char *challenge);
607 void challengeAnswer(unsigned char *challenge);
608 int clientPerformChallenge(int serverFd, MsgBuf_t *msg);
609 int serverPerformChallenge(int clientFd, MsgBuf_t *msg);
610 
611 void freeKeyInfo(KeyInfo_t *info);
612 char *findKeyByToken(KeyInfo_t *list, unsigned long token, struct sockaddr_in *peerAddrP, struct sockaddr_in *targetAddrP, unsigned short targetPort);
613 void addKeyInfoToList(KeyInfo_t *list, unsigned long token, char *key);
614 unsigned long generateToken(KeyInfo_t *list, unsigned long oldToken);
615 unsigned long getCurrentToken(void);
616 
617 int spawnCommand(unsigned short port, char *cmdFormat);
618 int filterLoop(int localFd, int remoteFd, MsgBuf_t *msgBuf,
619 	       struct sockaddr_in *toAddrP, struct sockaddr_in *fromAddrP,
620 	       int replyFd, int udpMode);
621 
622 void hashStrings(char *hashBuf, ...);
623 void hashFile(char *hashBuf, char *fileName);
624 int checkIdentity(char *idFile, char *generator, char *modulus, char *key);
625 char *generateIdentity(char *generator, char *modulus, char *exponent);
626 
627 unsigned long spawnHandler(void (*handler)(FnArgs_t *), int listenFd, int clientFd, int inLine, struct sockaddr_in *addrP, int udpMode);
628 int findHandler(struct sockaddr_in *fromAddrP, struct sockaddr_in *localAddrP);
629 void addHandler(struct sockaddr_in *fromAddrP, unsigned long id, int fd, struct sockaddr_in *localAddrP);
630 void removeHandler(struct sockaddr_in *addrP);
631 
632 void clientListener(EndPtList_t *localPorts);
633 int makeClientListeners(EndPtList_t *ports, fd_set *listenSetP, int udpMode);
634 void client(FnArgs_t *argP);
635 void prepareToDetach(void);
636 void makeDetached(void);
637 void serverListener(unsigned short *portPtr);
638 void serverInitiator(unsigned short *portPtr);
639 int allowRedirect(unsigned short port, struct sockaddr_in *addrP, struct sockaddr_in *peerAddrP, int udpMode, char **hostP, char **idFileP);
640 int checkPeerForSocket(int fd, struct sockaddr_in *addrP);
641 int checkPeerAddress(struct sockaddr_in *addrP, EndPtList_t *peerList);
642 int countPorts(EndPtList_t *list);
643 unsigned short mapPort(unsigned short localPort, char **hostP, struct sockaddr_in *addrP);
644 void server(FnArgs_t *argP);
645 
646 unsigned short scanPortRange(const char *str, unsigned short *loP,
647 			     unsigned short *hiP, unsigned short *typeP);
648 void setBoolean(char *value, int *resultP);
649 void setUShort(char *value, unsigned short *resultP);
650 void setPort(char *value, unsigned short *resultP);
651 EndPtList_t *newEndPtList(unsigned short lo, unsigned short hi, char *host, char *idFile, char *peer, unsigned short type);
652 EndPtList_t *allocEndPtList(unsigned short lo, unsigned short hi, char *host, char *idFile, char *peer, struct in_addr *addrP, struct in_addr *addrList, unsigned long mask, unsigned short type);
653 void setEndPtList(char *value, EndPtList_t **listP, char *host, char *idFile, char *peer, int zeroOk);
654 void setTarget(char *value);
655 void setChecksum(char *value, unsigned short *resultP);
656 void setTunnel(char *value);
657 void setAllowedPeer(char *value, EndPtList_t *peerList);
658 void setString(char *value, char **resultP);
659 void setLogFile(char *newFile);
660 void setCmpInfo(char *value, unsigned short *resultP);
661 void setStackSize(char *value);
662 void setRunAsUser(const char *user);
663 
664 void readConfigFile(const char *fileName, int level);
665 int parseConfigLine(const char *lineBuf, int level);
666 
667 char *cleanHexString(char *str);
668 
669 void usage(void);
670 
671 void sigpipeCatcher(int sig);
672 void sigchldCatcher(int sig);
673 void sigusr1Catcher(int sig);
674 
675 void runAsUser(const char *user);
676 void switchUser(void);
677 
678 /*************************************\
679 **				     **
680 **  Thread Synchronisation Routines  **
681 **				     **
682 \*************************************/
683 
684 /*
685 ** threadInit
686 **
687 ** Set up global mutexes, condition variables and thread attributes. Must
688 ** be called before any other thread routines.
689 */
690 
691 void
threadInit(void)692 threadInit(void)
693 {
694     mutexInit();
695     conditionInit();
696 #if defined(HAVE_PTHREADS)
697     pthread_attr_init(&ThreadAttr);
698     pthread_attr_setstacksize(&ThreadAttr, (size_t)ThreadStackSize);
699     pthread_attr_setdetachstate(&ThreadAttr, PTHREAD_CREATE_DETACHED);
700 #endif
701 }
702 
703 /*
704 ** mutexInit
705 **
706 ** Initialise global mutexes.
707 */
708 
709 void
mutexInit(void)710 mutexInit(void)
711 {
712 #if defined(WIN32)
713     int i;
714 
715     for (i = 0; i < MUTEX_MAX; i++)
716     {
717 	InitializeCriticalSection(&(Mutex[i]));
718     }
719 #elif defined(HAVE_PTHREADS)
720     int i;
721 
722     for (i = 0; i < MUTEX_MAX; i++)
723     {
724 	pthread_mutex_init(&(Mutex[i]), NULL);
725     }
726 #endif
727 }
728 
729 /*
730 ** mutexLock
731 **
732 ** Lock a global mutex
733 */
734 
735 void
mutexLock(int num)736 mutexLock(int num)
737 {
738     assert(num < MUTEX_MAX);
739 
740 #if defined(WIN32)
741     EnterCriticalSection(&(Mutex[num]));
742 #elif defined(HAVE_PTHREADS)
743     pthread_mutex_lock(&(Mutex[num]));
744 #endif
745 }
746 
747 /*
748 ** mutexUnlock
749 **
750 ** Unlock a global mutex
751 */
752 
753 void
mutexUnlock(int num)754 mutexUnlock(int num)
755 {
756     assert(num < MUTEX_MAX);
757 
758 #if defined(WIN32)
759     LeaveCriticalSection(&(Mutex[num]));
760 #elif defined(HAVE_PTHREADS)
761     pthread_mutex_unlock(&(Mutex[num]));
762 #endif
763 }
764 
765 /*
766 ** conditionInit
767 **
768 ** Initialise global condition variables.
769 */
770 
771 void
conditionInit(void)772 conditionInit(void)
773 {
774 #if defined(WIN32)
775     int i;
776 
777     for (i = 0; i < COND_MAX; i++)
778     {
779 	Condition[i] = CreateEvent(NULL,    /* No security attributes */
780 				   TRUE,    /* Manual reset */
781 				   FALSE,   /* Initially cleared */
782 				   NULL);   /* No name */
783     }
784 #elif defined(HAVE_PTHREADS)
785     int i;
786 
787     for (i = 0; i < COND_MAX; i++)
788     {
789 	pthread_cond_init(&(Condition[i]), NULL);
790     }
791 #endif
792 }
793 
794 /*
795 ** conditionSignal
796 **
797 ** Signal a condition variable
798 */
799 
800 void
conditionSignal(int num)801 conditionSignal(int num)
802 {
803     assert(num < COND_MAX);
804 
805 #if defined(WIN32)
806     PulseEvent(Condition[num]);
807 #elif defined(HAVE_PTHREADS)
808     pthread_cond_broadcast(&(Condition[num]));
809 #endif
810 }
811 
812 /*
813 ** conditionWait
814 **
815 ** Wait on a condition variable. Note the specified mutex must be held
816 ** before calling this routine. It will also be held on exit.
817 */
818 
819 void
conditionWait(int condNum,int mutexNum)820 conditionWait(int condNum, int mutexNum)
821 {
822     assert(condNum < COND_MAX && mutexNum < MUTEX_MAX);
823 
824 #if defined(WIN32)
825     LeaveCriticalSection(&(Mutex[mutexNum]));
826     WaitForSingleObject(Condition[condNum], INFINITE);
827     EnterCriticalSection(&(Mutex[mutexNum]));
828 #elif defined(HAVE_PTHREADS)
829     pthread_cond_wait(&(Condition[condNum]), &(Mutex[mutexNum]));
830 #endif
831 }
832 
833 /*
834 ** threadPid
835 **
836 ** Return the current process ID
837 */
838 
839 unsigned long
threadPid(void)840 threadPid(void)
841 {
842 #ifdef WIN32
843     return (unsigned long)GetCurrentProcessId();
844 #else
845     return (unsigned long)getpid();
846 #endif
847 }
848 
849 /*
850 ** threadTid
851 **
852 ** Return the current thread ID
853 */
854 
855 unsigned long
threadTid(void)856 threadTid(void)
857 {
858 #ifdef WIN32
859     return (unsigned long)GetCurrentThreadId();
860 #elif defined(HAVE_PTHREADS)
861     return (unsigned long)pthread_self();
862 #else
863     return 0;
864 #endif
865 }
866 
867 /*
868 ** incrActiveCount
869 **
870 ** This increments or decrements the count of active handler threads.
871 ** If the count reaches zero it also signals the COND_ACTIVE condition
872 ** variable.
873 */
874 
875 int
incrActiveCount(int num)876 incrActiveCount(int num)
877 {
878     mutexLock(MUTEX_ACTIVE);
879     ActiveCount += num;
880     if (ActiveCount == 0)
881     {
882 	conditionSignal(COND_ACTIVE);
883     }
884     mutexUnlock(MUTEX_ACTIVE);
885     return ActiveCount;
886 }
887 
888 /*
889 ** waitForInactivity
890 **
891 ** This routine blocks until the "ActiveCount" global variable reaches
892 ** zero, indicating no more running handler threads.
893 */
894 
895 void
waitForInactivity(void)896 waitForInactivity(void)
897 {
898 #if defined(WIN32) || defined(HAVE_PTHREADS)
899     mutexLock(MUTEX_ACTIVE);
900     while (ActiveCount)
901     {
902 	conditionWait(COND_ACTIVE, MUTEX_ACTIVE);
903     }
904     mutexUnlock(MUTEX_ACTIVE);
905 #else
906     while (waitpid(-1, NULL, 0) > 0 || errno != ECHILD) /* Wait for children */;
907 #endif
908 }
909 
910 /*********************\
911 **		     **
912 **  Message Logging  **
913 **		     **
914 \*********************/
915 
916 /*
917 ** timestamp
918 **
919 ** Generate a time-stamp string
920 */
921 
922 void
timestamp(char * timeBuf,int local)923 timestamp(char *timeBuf, int local)
924 {
925     time_t now;
926     struct tm *tmPtr;
927 
928     /* localtime()/gmtime are not thread-safe */
929 
930     mutexLock(MUTEX_IO);
931     time(&now);
932     if (local)
933     {
934 	tmPtr = localtime(&now);
935     }
936     else
937     {
938 	tmPtr = gmtime(&now);
939     }
940     strftime(timeBuf, TIMESTAMP_SIZE, "%Y-%m-%d-%H:%M:%S", tmPtr);
941     mutexUnlock(MUTEX_IO);
942 }
943 
944 /*
945 ** logToSystemLog
946 **
947 ** Write a message to the system logging facility. On Windows it goes to
948 ** the system application event log. Elsewhere is uses syslog().
949 */
950 
951 void
logToSystemLog(unsigned short level,char * msg)952 logToSystemLog(unsigned short level, char *msg)
953 {
954 #ifdef WIN32
955     HANDLE  eventHandle;
956     char    *strings[2];
957 
958 
959     eventHandle = RegisterEventSource(NULL, Program);
960 
961     strings[0] = msg;
962     strings[1] = NULL;
963 
964     if (eventHandle != NULL)
965     {
966 	ReportEvent(eventHandle,	    /* Handle of event source */
967 		    (level ? EVENTLOG_INFORMATION_TYPE :
968 		     EVENTLOG_ERROR_TYPE),  /* Event type */
969 		    (WORD)level,	    /* Event category */
970 		    0,			    /* Event ID */
971 		    NULL,		    /* User SID */
972 		    1,			    /* Number of message strings */
973 		    0,			    /* Bytes of binary data */
974 		    (const char **)strings, /* Array of message strings */
975 		    NULL);		    /* No binary data */
976 	DeregisterEventSource(eventHandle);
977     }
978 #else
979     int logLevel;
980 
981     /*
982     ** Messages at level 0 are errors, 1 is notice, 2 informational
983     ** and everything else is classed as debug.
984     */
985 
986     switch (level)
987     {
988     case 0:
989 	logLevel = LOG_ERR;
990 	break;
991 
992     case 1:
993 	logLevel = LOG_NOTICE;
994 	break;
995 
996     case 2:
997 	logLevel = LOG_INFO;
998 	break;
999 
1000     default:
1001 	logLevel = LOG_DEBUG;
1002 	break;
1003     }
1004 
1005     syslog(logLevel, msg);
1006 #endif
1007 }
1008 
1009 /*
1010 ** message
1011 **
1012 ** Output a message to the current log file if the message verbosity is
1013 ** greater than or equal to the specified level. Messages at level 0
1014 ** can not be suppressed (unless the log-file type is NULL) and are all
1015 ** error messages.
1016 **
1017 ** If errno is non-zero then append the matching error text.
1018 */
1019 
1020 void
message(unsigned short level,int err,char * fmt,...)1021 message(unsigned short level, int err, char *fmt, ...)
1022 {
1023     FILE *fp = LogFileP;
1024     va_list args;
1025     char timeBuf[TIMESTAMP_SIZE];
1026     char *timePtr = NULL;
1027     char msgBuf[MAX_LINE_SIZE];
1028 
1029 
1030     if (level > LogLevel || LogFileType == LOGFILE_NULL) return;
1031 
1032     /*
1033     ** If we are running detached and no logfile has been set then there
1034     ** is nowhere for the messages to go. Worse still, under UNIX,
1035     ** trying to write to stderr when detached can hang the process.
1036     */
1037 
1038     if (IsDetached == -1 && fp == NULL && LogFileType != LOGFILE_SYSLOG) return;
1039 
1040     va_start(args, fmt);
1041 
1042     if (fp == NULL)
1043     {
1044 	fp = stderr;
1045     }
1046 
1047     if (TimestampLog)
1048     {
1049 	timestamp(timeBuf, 1);
1050 	timePtr = timeBuf;
1051     }
1052 
1053     /*
1054     ** The message format is the program name followed by the (low five
1055     ** digits of) the PID and thread ID then an optional timestamp followed
1056     ** by an amount of indentation determined by the level. This is
1057     ** then followed by the supplied message text and arguments and
1058     ** finally the error message text (if any) associated with the supplied
1059     ** error number!
1060     */
1061 
1062     snprintf(msgBuf, sizeof(msgBuf), "%s(%lu/%lu): %s%s%.*s%s",
1063 	     Program, (threadPid() % 100000), (threadTid() % 100000),
1064 	     (timePtr ? timePtr : ""), (timePtr ? ": " : ""),
1065 	     level, "          ", (level ? "" : "ERROR: "));
1066 
1067     vsnprintf(msgBuf + strlen(msgBuf), sizeof(msgBuf) - strlen(msgBuf),
1068 	      fmt, args);
1069 
1070     va_end(args);
1071 
1072     if (err)
1073     {
1074 	snprintf(msgBuf + strlen(msgBuf), sizeof(msgBuf) - strlen(msgBuf),
1075 		 ": (%s)", strerror(err));
1076     }
1077 
1078     /* Ensure we don't get overlapping messages */
1079 
1080     mutexLock(MUTEX_IO);
1081 
1082     switch (LogFileType)
1083     {
1084     case LOGFILE_LOCAL:
1085 	fprintf(fp, "%s\n", msgBuf);
1086 	fflush(fp);
1087 	break;
1088 
1089     case LOGFILE_SYSLOG:
1090 	logToSystemLog(level, msgBuf);
1091 	break;
1092 
1093     default:
1094 	break;
1095     }
1096 
1097     mutexUnlock(MUTEX_IO);
1098 
1099 }
1100 
1101 /*
1102 ** dumpData
1103 **
1104 ** Dump data buffer (at verbosity level 5) only if DumpData is true.
1105 */
1106 
dumpData(const char * prefix,unsigned char * data,unsigned short size)1107 void dumpData(const char *prefix, unsigned char *data, unsigned short size)
1108 {
1109     unsigned short i;
1110     unsigned char buf[128];
1111     unsigned char *bptr = NULL;
1112     static char *hex = "0123456789abcdef";
1113 
1114     if (!DumpData) return;
1115 
1116     bptr = buf;
1117     for (i = 0; i < size; i++)
1118     {
1119 	if (isprint(data[i]))
1120 	{
1121 	    *bptr++ = data[i];
1122 	    *bptr++ = ' ';
1123 	}
1124 	else
1125 	{
1126 	    *bptr++ = hex[(data[i] >> 4) & 0xf];
1127 	    *bptr++ = hex[data[i] & 0xf];
1128 	}
1129 	*bptr++ = ' ';
1130 
1131 	if ((i % 16) == 15)
1132 	{
1133 	    *(bptr - 1) = '\0';
1134 	    message(5, 0, "%s %04hx %s", prefix, (i - 15), buf);
1135 	    bptr = buf;
1136 	}
1137     }
1138 
1139     if (i % 16)
1140     {
1141 	*bptr = '\0';
1142 	message(5, 0, "%s %04hx %s", prefix, (i - (i % 16)), buf);
1143 	bptr = buf;
1144     }
1145 }
1146 
1147 /*******************************\
1148 **			       **
1149 **  Network Data Transmission  **
1150 **			       **
1151 \*******************************/
1152 
1153 /*
1154 ** readData
1155 **
1156 ** Read and reassemble a potentially fragmented message from the network.
1157 ** If the global ReadTimeout is non-zero then we will only wait for that
1158 ** many seconds for data to arrive.
1159 */
1160 
1161 int
readData(int fd,unsigned char * buffer,unsigned short size)1162 readData(int fd, unsigned char *buffer, unsigned short size)
1163 {
1164     int num = 0;
1165     char *bufP = NULL;
1166     unsigned short total = 0;
1167     struct timeval delay;
1168     fd_set testSet;
1169     int ready;
1170 
1171     bufP = (char *)buffer;
1172     do
1173     {
1174 	if (ReadTimeout != 0)
1175 	{
1176 	    delay.tv_sec = ReadTimeout;
1177 	    delay.tv_usec = 0;
1178 
1179 	    FD_ZERO(&testSet);
1180 	    FD_SET(fd, &testSet);
1181 
1182 	    ready = select(fd + 1, &testSet, 0, 0, &delay);
1183 
1184 	    if (ready == 0)
1185 	    {
1186 		message(0, errno, "timed out reading data");
1187 		return -1;
1188 	    }
1189 	}
1190 
1191 	message(5, 0, "readData: receiving %d of %d", (size - total), size);
1192 	if ((num = recv(fd, (bufP + total), (size - total), 0)) <= 0)
1193 	{
1194 	    message(5, errno, "readData: EOF or error");
1195 	    /* Premature EOF or error */
1196 	    return num;
1197 	}
1198 	message(5, 0, "readData: read %d byte(s)", num);
1199 	total += (unsigned short)num;
1200     }
1201     while (total < size);
1202 
1203     return total;
1204 }
1205 
1206 /*
1207 ** readUShort
1208 **
1209 ** Read an unsigned short value from the network.
1210 **
1211 ** The value is transmitted in big-endian format. The routine returns the
1212 ** number of bytes read (or 0 on EOF, -1 on error) and the value itself
1213 ** via valueP.
1214 */
1215 
1216 int
readUShort(int fd,unsigned short * resultP)1217 readUShort(int fd, unsigned short *resultP)
1218 {
1219     int num = 0;
1220     unsigned char buffer[2];
1221 
1222     if ((num = readData(fd, buffer, 2)) != 2)
1223     {
1224 	return num;
1225     }
1226 
1227     *resultP = ((unsigned short)buffer[0] << 8) + (unsigned short)buffer[1];
1228     message(4, 0, "readUShort: read %hu", *resultP);
1229 
1230     return num;
1231 }
1232 
1233 /*
1234 ** writeData
1235 **
1236 ** Write the supplied buffer of data to the network, handling fragmentation
1237 ** if necessary.
1238 */
1239 
1240 int
writeData(int fd,unsigned char * buffer,unsigned short size)1241 writeData(int fd, unsigned char *buffer, unsigned short size)
1242 {
1243     int num = 0;
1244     char *bufP = NULL;
1245     unsigned short total = 0;
1246 
1247     bufP = (char *)buffer;
1248     do
1249     {
1250 	message(5, 0, "writeData: sending %d of %d", (size - total), size);
1251 	if ((num = send(fd, (bufP + total), (size - total), 0)) <= 0)
1252 	{
1253 	    /* Premature EOF or error */
1254 	    message(5, errno, "writeData: EOF or error");
1255 	    return num;
1256 	}
1257 	total += (unsigned short)num;
1258 	message(5, 0, "writeData: sent %d byte(s)", num);
1259     }
1260     while (total < size);
1261 
1262     return total;
1263 }
1264 
1265 /*
1266 ** writeUShort
1267 **
1268 ** Write an unsigned short value to the network in big-endian format
1269 */
1270 
1271 int
writeUShort(int fd,unsigned short value)1272 writeUShort(int fd, unsigned short value)
1273 {
1274     unsigned char buf[2];
1275 
1276     message(4, 0, "writeUShort: writing %hu", value);
1277 
1278     buf[0] = (unsigned char)((value >> 8) & 0xff);
1279     buf[1] = (unsigned char)(value & 0xff);
1280 
1281     return writeData(fd, buf, 2);
1282 }
1283 
1284 /*
1285 ** makeMsgBuf
1286 **
1287 ** Allocate a MsgBuf_t structure
1288 */
1289 
1290 MsgBuf_t *
makeMsgBuf(unsigned short maxSize,unsigned short cmpInfo,unsigned short checksumLevel)1291 makeMsgBuf(unsigned short maxSize,
1292 	   unsigned short cmpInfo,
1293 	   unsigned short checksumLevel)
1294 {
1295     MsgBuf_t *msg;
1296 
1297 
1298     if ((msg = (MsgBuf_t *)malloc(sizeof(MsgBuf_t))) == NULL)
1299     {
1300 	message(0, errno, "Failed to allocate message structure");
1301 	return NULL;
1302     }
1303 
1304     msg->maxSize = maxSize;
1305     msg->size = 0;
1306     msg->cmpInfo = cmpInfo;
1307     msg->bfRead = NULL;
1308     msg->bfWrite = NULL;
1309     msg->readCount = 0;
1310     msg->bytesIn = 0;
1311     msg->expBytesIn = 0;
1312     msg->writeCount = 0;
1313     msg->bytesOut = 0;
1314     msg->expBytesOut = 0;
1315     msg->checksumLevel = checksumLevel;
1316 
1317     /* Set the checksumLen based on current checksum mode. */
1318 
1319     switch (checksumLevel)
1320     {
1321     case CHECKSUM_NONE:
1322 	msg->checksumLen = 0;
1323 	break;
1324 
1325     case CHECKSUM_ADLER:
1326 	msg->checksumLen = CHECKSUM_ADLER_LEN;
1327 	break;
1328 
1329     case CHECKSUM_CRC32:
1330 	msg->checksumLen = CHECKSUM_CRC32_LEN;
1331 	break;
1332 
1333     case CHECKSUM_SHA:
1334 	msg->checksumLen = CHECKSUM_SHA_LEN;
1335 	break;
1336 
1337     default:
1338 	message(0, 0, "invalid checksum level while allocating message buffer (%hu)", checksumLevel);
1339 	free(msg);
1340 	return NULL;
1341 	break;
1342     }
1343 
1344     return msg;
1345 }
1346 
1347 /*
1348 ** freeMsgBuf
1349 **
1350 ** Free a message buffer. But I bet you could guess that :-)
1351 */
1352 
1353 void
freeMsgBuf(MsgBuf_t * msg)1354 freeMsgBuf(MsgBuf_t *msg)
1355 {
1356     if (msg)
1357     {
1358 	if (msg->bfRead) free(msg->bfRead);
1359 	if (msg->bfWrite) free(msg->bfWrite);
1360 	free(msg);
1361     }
1362 }
1363 
1364 /*
1365 ** getMsgBuf
1366 **
1367 ** Retrieve the contents of a message buffer into the supplied local
1368 ** buffer.
1369 */
1370 
1371 void
getMsgBuf(MsgBuf_t * msg,void * buffer,unsigned short size)1372 getMsgBuf(MsgBuf_t *msg, void *buffer, unsigned short size)
1373 {
1374     if (msg->size > size)
1375     {
1376 	message(0, 0, "supplied buffer too small for received message (%hu > %hu)", msg->size, size);
1377     }
1378 
1379     memcpy(buffer, msg->data, (size < msg->size ? size : msg->size));
1380 }
1381 
1382 /*
1383 ** setMsgBuf
1384 **
1385 ** Set the contents of a message buffer from the supplied local
1386 ** buffer and size.
1387 */
1388 
1389 void
setMsgBuf(MsgBuf_t * msg,void * buffer,unsigned short size)1390 setMsgBuf(MsgBuf_t *msg, void *buffer, unsigned short size)
1391 {
1392     msg->size = size;
1393     memcpy(msg->data, buffer, size);
1394 }
1395 
1396 /*
1397 ** readMessage
1398 **
1399 ** Read a message from the network into the supplied buffer, uncompressing
1400 ** and decrypting as necessary. The maximum amount of data read is given
1401 ** by msg->maxSize UNLESS thisSize is non-zero in which case this overrides
1402 ** the value in the structure.
1403 **
1404 ** If checksumming is being used then the checksum value will have been
1405 ** appended to the message (this is not included in the message size).
1406 ** This will be extracted and checked here.
1407 **
1408 ** The size of the expanded, unencrypted message, stripped of its checksum,
1409 ** is returned as the value of the function and also via msg->size. If there is an error then -1 is
1410 ** returned.
1411 */
1412 
1413 int
readMessage(int fd,MsgBuf_t * msg,unsigned short thisSize)1414 readMessage(int fd, MsgBuf_t *msg, unsigned short thisSize)
1415 {
1416     unsigned short hdr;
1417     unsigned short size;
1418     unsigned short extSize; /* Size with extra checksum info */
1419     unsigned short flags;
1420     int num = 0;
1421     unsigned long uncmpSize = MAX_BUF_SIZE;
1422     unsigned int iUncmpSize = MAX_BUF_SIZE;
1423     SHA_INFO shaExp;
1424     SHA_INFO shaIn;
1425     uint32_t crc32in = 0;
1426     uint32_t crc32exp = 0;
1427     int checksumOk = 0;
1428 
1429 
1430     /* Read the header */
1431 
1432     if ((num = readUShort(fd, &hdr)) != 2) return num;
1433 
1434     /* Extract the flags and message size */
1435 
1436     flags = GET_FLAGS(hdr);
1437     size = GET_SIZE(hdr);
1438 
1439     /* Reject invalid messages */
1440 
1441     if (thisSize ? size > thisSize : size > msg->maxSize)
1442     {
1443 	message(0, 0, "incoming message size too big (%hu > %hu)",
1444 		size, (thisSize ? thisSize : msg->maxSize));
1445 	return -1;
1446     }
1447 
1448     msg->size = size;
1449     msg->readCount++;
1450     extSize = size + msg->checksumLen;
1451     msg->bytesIn += extSize;
1452 
1453     message(4, 0, "readMessage: message size = %hu, %s, %s", size,
1454 	    ((flags & FLAG_ENCRYPTED) ? "encrypted" : "unencrypted"),
1455 	    ((flags & FLAG_COMPRESSED) ? "compressed" : "uncompressed"));
1456 
1457     /* Read the remaining message data, and appended checksum */
1458 
1459     if ((num = readData(fd, msg->tmp, extSize))	!= (int)extSize) return num;
1460 
1461     /* Decrypt if necessary */
1462 
1463     if (flags & FLAG_ENCRYPTED)
1464     {
1465 	if (msg->bfRead == NULL)
1466 	{
1467 	    message(0, 0, "message with encryption flag sent with no encryption context");
1468 	    return -1;
1469 	}
1470 
1471 	BF_cfb64_encrypt(msg->tmp, msg->bfRead->cryptBuf, extSize,
1472 			 &(msg->bfRead->key), msg->bfRead->iVec,
1473 			 &(msg->bfRead->pos), BF_DECRYPT);
1474 	memcpy(msg->tmp, msg->bfRead->cryptBuf, extSize);
1475     }
1476 
1477     switch (msg->checksumLevel)
1478     {
1479     case CHECKSUM_NONE:
1480 	checksumOk = 1;
1481 	break;
1482 
1483     case CHECKSUM_ADLER:
1484 	memcpy(&crc32exp, msg->tmp + size, sizeof(crc32exp));
1485 	crc32exp = BUGNTOHL(crc32exp);
1486 	crc32in = (uint32_t)adler32(0L, (unsigned char *)&msg->inSeed, sizeof(msg->inSeed));
1487 	crc32in = (uint32_t)adler32(crc32in, (unsigned char *)&msg->tmp, size);
1488 	checksumOk = (crc32exp == crc32in);
1489 	message(5, 0, "expected checksum %#08lx, calculated checksum %#08lx", crc32exp, crc32in);
1490 	crc32in = BUGHTONL(crc32in);
1491 	memcpy(&(msg->inSeed), &crc32in, sizeof(crc32in));
1492 	break;
1493 
1494     case CHECKSUM_CRC32:
1495 	memcpy(&crc32exp, msg->tmp + size, sizeof(crc32exp));
1496 	crc32exp = BUGNTOHL(crc32exp);
1497 	crc32in = (uint32_t)crc32(0L, (unsigned char *)&msg->inSeed, sizeof(msg->inSeed));
1498 	crc32in = (uint32_t)crc32(crc32in, (unsigned char *)&msg->tmp, size);
1499 	checksumOk = (crc32exp == crc32in);
1500 	message(5, 0, "expected checksum %#08lx, calculated checksum %#08lx", crc32exp, crc32in);
1501 	crc32in = BUGHTONL(crc32in);
1502 	memcpy(&(msg->inSeed), &crc32in, sizeof(crc32in));
1503 	break;
1504 
1505     case CHECKSUM_SHA:
1506 	sha_init(&shaExp);
1507 	sha_init(&shaIn);
1508 	memcpy(shaExp.digest, msg->tmp + size, sizeof(shaExp.digest));
1509 	shaExp.digest[0] = BUGNTOHL(shaExp.digest[0]);
1510 	shaExp.digest[1] = BUGNTOHL(shaExp.digest[1]);
1511 	shaExp.digest[2] = BUGNTOHL(shaExp.digest[2]);
1512 	shaExp.digest[3] = BUGNTOHL(shaExp.digest[3]);
1513 	shaExp.digest[4] = BUGNTOHL(shaExp.digest[4]);
1514 	sha_update(&shaIn, (SHA_BYTE *)&msg->inSeed, sizeof(msg->inSeed));
1515 	sha_update(&shaIn, (SHA_BYTE *)&msg->tmp, size);
1516 	sha_final(&shaIn);
1517 	checksumOk = (memcmp(&shaIn.digest, &shaExp.digest, sizeof(shaIn.digest)) == 0);
1518 	shaIn.digest[0] = BUGHTONL(shaIn.digest[0]);
1519 	shaIn.digest[1] = BUGHTONL(shaIn.digest[1]);
1520 	shaIn.digest[2] = BUGHTONL(shaIn.digest[2]);
1521 	shaIn.digest[3] = BUGHTONL(shaIn.digest[3]);
1522 	shaIn.digest[4] = BUGHTONL(shaIn.digest[4]);
1523 	memcpy(&(msg->inSeed), &shaIn.digest, sizeof(shaIn.digest));
1524 	message(5, 0, "expected checksum %08lx%08lx%08lx%08lx%08lx, calculated checksum %08lx%08lx%08lx%08lx%08lx",
1525 		BUGNTOHL((unsigned long)shaExp.digest[0]),
1526 		BUGNTOHL((unsigned long)shaExp.digest[1]),
1527 		BUGNTOHL((unsigned long)shaExp.digest[2]),
1528 		BUGNTOHL((unsigned long)shaExp.digest[3]),
1529 		BUGNTOHL((unsigned long)shaExp.digest[4]),
1530 		BUGNTOHL((unsigned long)shaIn.digest[0]),
1531 		BUGNTOHL((unsigned long)shaIn.digest[1]),
1532 		BUGNTOHL((unsigned long)shaIn.digest[2]),
1533 		BUGNTOHL((unsigned long)shaIn.digest[3]),
1534 		BUGNTOHL((unsigned long)shaIn.digest[4]));
1535 	break;
1536 
1537     default:
1538 	message(0, 0, "unknown internal checksum mode (%hu)", msg->checksumLevel);
1539 	return -1;
1540     }
1541 
1542     if (!checksumOk)
1543     {
1544 	message(0, 0, "message failed checksum validation");
1545 	return -1;
1546     }
1547 
1548     /* Decompress if necessary */
1549 
1550     if (flags & FLAG_COMPRESSED)
1551     {
1552 	switch (GET_CMPTYPE(msg->cmpInfo))
1553 	{
1554 	case CMPTYPE_ZLIB:
1555 	    if ((num = uncompress(msg->data, &uncmpSize,
1556 				  (Byte *)(msg->tmp), size)) != Z_OK)
1557 	    {
1558 		message(0, errno, "uncompressing message data (zlib status = %d)", num);
1559 		errno = 0;
1560 		return -1;
1561 	    }
1562 	    break;
1563 
1564 	case CMPTYPE_BZIP2:
1565 #ifndef DONT_HAVE_BZIP2
1566 	    if ((num = BZ2_bzBuffToBuffDecompress((char *)(msg->data),
1567 						  &iUncmpSize,
1568 						  (char *)(msg->tmp),
1569 						  (unsigned int)size,
1570 						  0, 0)) != BZ_OK)
1571 	    {
1572 		message(0, errno, "uncompressing message data (bzip2 status = %d)", num);
1573 		errno = 0;
1574 		return -1;
1575 	    }
1576 	    uncmpSize = (unsigned long)iUncmpSize;
1577 	    break;
1578 #else
1579 	    message(0, 0, "received unsupported bzip2 compressed message -- should never happen!");
1580 	    return -1;
1581 	    break;
1582 #endif
1583 	default:
1584 	    message(0, 0, "invalid compression info in readMessage (%#hx)", msg->cmpInfo);
1585 	    return -1;
1586 	    break;
1587 	}
1588 
1589 	msg->size = size = (unsigned short)uncmpSize;
1590 	message(4, 0, "readMessage: uncompressed size = %hu", size);
1591     }
1592     else
1593     {
1594 	memcpy(msg->data, msg->tmp, size);
1595     }
1596 
1597     msg->expBytesIn += size;
1598 
1599     return (int)size;
1600 }
1601 
1602 /*
1603 ** writeMessage
1604 **
1605 ** Write a message to the network containing the data from buffer, compressing
1606 ** and encrypting as necessary.
1607 **
1608 ** The size of the original expanded, unencrypted message is returned as the
1609 ** value of the function on success or the status from writeData() on error.
1610 **
1611 ** The message is sent as an unsigned short header (in the format written
1612 ** by writeUShort) followed by the data itself. The header value consists
1613 ** of the length or'ed with flags indicating if the message is compressed
1614 ** and encrypted.
1615 */
1616 
1617 int
writeMessage(int fd,MsgBuf_t * msg)1618 writeMessage(int fd, MsgBuf_t *msg)
1619 {
1620     unsigned short size = msg->size;
1621     unsigned short extSize;
1622     unsigned short hdr;
1623     int num = 0;
1624     unsigned long cmpSize = MAX_BUF_SIZE + CMP_OVERHEAD;
1625     unsigned short flags = 0;
1626     unsigned char *data = msg->data;
1627     SHA_INFO sha;
1628     uint32_t crc;
1629 
1630 
1631 
1632     /* Attempt compression if the message size warrants it */
1633 
1634     if (msg->cmpInfo && msg->size > CMP_MINIMUM)
1635     {
1636 	switch (GET_CMPTYPE(msg->cmpInfo))
1637 	{
1638 	case CMPTYPE_ZLIB:
1639 	    if ((num = compress2(msg->tmp + 2, &cmpSize,
1640 				 (const Byte *)(msg->data), size,
1641 				 GET_CMPLEVEL(msg->cmpInfo))) != Z_OK)
1642 	    {
1643 		message(0, errno, "compressing data (zlib status = %d)", num);
1644 		cmpSize = msg->size;
1645 	    }
1646 	    break;
1647 
1648 	case CMPTYPE_BZIP2:
1649 #ifndef DONT_HAVE_BZIP2
1650 	    if ((num = BZ2_bzBuffToBuffCompress((char *)(msg->tmp + 2),
1651 					    (unsigned int *)&cmpSize,
1652 					    (char *)(msg->data),
1653 					    (unsigned int)size,
1654 					    (int)GET_CMPLEVEL(msg->cmpInfo),
1655 					    0, 0)) != BZ_OK)
1656 	    {
1657 		message(0, errno, "compressing data (bzip2 status = %d)", num);
1658 	    }
1659 	    break;
1660 #else
1661 	    message(0, 0, "request to use unsupported bzip2 compression!");
1662 	    cmpSize = (unsigned long)size;
1663 	    break;
1664 #endif
1665 
1666 	default:
1667 	    cmpSize = (unsigned long)size;
1668 	    break;
1669 	}
1670 
1671 	/* Only use compressed message if it is shorter */
1672 
1673 	if (cmpSize < (unsigned long)size)
1674 	{
1675 	    message(4, 0, "writeMessage: message compressed from %hu to %lu bytes", msg->size, cmpSize);
1676 	    data = msg->tmp + 2;
1677 	    size = (unsigned short)cmpSize;
1678 	    flags |= FLAG_COMPRESSED;
1679 	}
1680     }
1681 
1682     switch (msg->checksumLevel)
1683     {
1684     case CHECKSUM_NONE:
1685 	break;
1686 
1687     case CHECKSUM_ADLER:
1688 	crc = (uint32_t)adler32(0L, (unsigned char *)&msg->outSeed, sizeof(msg->outSeed));
1689 	crc = BUGHTONL((uint32_t)adler32(crc, data, size));
1690 	memcpy(data + size, &crc, sizeof(crc));
1691 	memcpy(&msg->outSeed, &crc, sizeof(crc));
1692 	message(5, 0, "calculated checksum %#08lx", BUGNTOHL(crc));
1693 	break;
1694 
1695     case CHECKSUM_CRC32:
1696 	crc = (uint32_t)crc32(0L, (unsigned char *)&msg->outSeed, sizeof(msg->outSeed));
1697 	crc = BUGHTONL((uint32_t)crc32(crc, data, size));
1698 	memcpy(data + size, &crc, sizeof(crc));
1699 	memcpy(&msg->outSeed, &crc, sizeof(crc));
1700 	message(5, 0, "calculated checksum %#08lx", crc);
1701 	break;
1702 
1703     case CHECKSUM_SHA:
1704 	sha_init(&sha);
1705 	sha_update(&sha, (SHA_BYTE *)&msg->outSeed, sizeof(msg->outSeed));
1706 	sha_update(&sha, (SHA_BYTE *)data, size);
1707 	sha_final(&sha);
1708 	sha.digest[0] = BUGHTONL(sha.digest[0]);
1709 	sha.digest[1] = BUGHTONL(sha.digest[1]);
1710 	sha.digest[2] = BUGHTONL(sha.digest[2]);
1711 	sha.digest[3] = BUGHTONL(sha.digest[3]);
1712 	sha.digest[4] = BUGHTONL(sha.digest[4]);
1713 	memcpy(data + size, &sha.digest, sizeof(sha.digest));
1714 	memcpy(&msg->outSeed, &sha.digest, sizeof(sha.digest));
1715 	message(5, 0, "calculated checksum %08lx%08lx%08lx%08lx%08lx",
1716 		(unsigned long)BUGNTOHL(sha.digest[0]),
1717 		(unsigned long)BUGNTOHL(sha.digest[1]),
1718 		(unsigned long)BUGNTOHL(sha.digest[2]),
1719 		(unsigned long)BUGNTOHL(sha.digest[3]),
1720 		(unsigned long)BUGNTOHL(sha.digest[4]));
1721 	break;
1722 
1723     default:
1724 	    message(0, 0, "unknown internal checksum mode");
1725 	    return -1;
1726     }
1727     extSize = size + msg->checksumLen;
1728 
1729     /* Encrypt if required */
1730 
1731     if (msg->bfWrite)
1732     {
1733 	BF_cfb64_encrypt(data, msg->bfWrite->cryptBuf, extSize,
1734 			 &(msg->bfWrite->key), msg->bfWrite->iVec,
1735 			 &(msg->bfWrite->pos), BF_ENCRYPT);
1736 	memcpy(msg->tmp + 2, msg->bfWrite->cryptBuf, extSize);
1737 	flags |= FLAG_ENCRYPTED;
1738     }
1739     else
1740     {
1741 	memmove(msg->tmp + 2, data, extSize);
1742     }
1743 
1744     /* Insert the header */
1745 
1746     hdr = SET_FLAGS(size, flags);
1747 
1748     msg->tmp[0] = (unsigned char)((hdr >> 8) & 0xff);
1749     msg->tmp[1] = (unsigned char)(hdr & 0xff);
1750 
1751     /* Write the message data */
1752 
1753     message(4, 0, "writeMessage: message size = %hu, %s, %s", size,
1754 	    ((flags & FLAG_ENCRYPTED) ? "encrypted" : "unencrypted"),
1755 	    ((flags & FLAG_COMPRESSED) ? "compressed" : "uncompressed"));
1756 
1757     if ((num = writeData(fd, msg->tmp, extSize + 2)) != (int)(extSize + 2)) return num;
1758 
1759     msg->writeCount++;
1760     msg->bytesOut += extSize;
1761     msg->expBytesOut += msg->size;
1762     return msg->size;
1763 }
1764 
1765 /*
1766 ** requestResponse
1767 **
1768 ** This is a helper routine that sends the unsigned short "request" value
1769 ** and awaits the response, storing it in "responseP". It returns 1 if
1770 ** successful or 0 otherwise.
1771 */
1772 
1773 int
requestResponse(int fd,unsigned short request,unsigned short * responseP)1774 requestResponse(int fd, unsigned short request, unsigned short *responseP)
1775 {
1776     /* Write request */
1777 
1778     if (writeUShort(fd, request) != 2)
1779     {
1780 	return 0;
1781     }
1782 
1783     /* Read response */
1784 
1785     if (readUShort(fd, responseP) != 2)
1786     {
1787 	return 0;
1788     }
1789 
1790     return 1;
1791 }
1792 
1793 /*
1794 ** getHostAddress
1795 **
1796 ** Translate a hostname or numeric IP address and store the result in addrP.
1797 ** If addrList is not NULL then return the list of aliases addresses in it.
1798 ** The list is terminated with an address with all components set to 0xff
1799 ** (i.e. 255.255.255.255). If maskP is not NULL and the address is in the
1800 ** form of a CIDR mask specification then it will be set to contain the
1801 ** appropriate address mask.
1802 **
1803 ** Returns 1 on success, 0 on failure.
1804 */
1805 
1806 int
getHostAddress(const char * host,struct sockaddr_in * addrP,struct in_addr ** addrList,unsigned long * maskP)1807 getHostAddress(const char *host,
1808 	       struct sockaddr_in *addrP,
1809 	       struct in_addr **addrList,
1810 	       unsigned long *maskP)
1811 {
1812     struct hostent *entry = NULL;
1813     int result = 1;
1814     int count = 0;
1815     int i = 0;
1816     char *s = NULL;
1817     char *hostCopy = NULL;
1818     unsigned short bits = 32;
1819 
1820 
1821     mutexLock(MUTEX_IO);
1822 
1823     /*
1824     ** If there is a mask spec then eliminate it from the host name
1825     ** and create the mask, if required.
1826     */
1827 
1828     if ((s = strchr(host, '/')) != NULL)
1829     {
1830 	hostCopy = (char *)malloc(strlen(host) + 1);
1831 	if (!hostCopy || (sscanf(host, "%[^/]/%hu", hostCopy, &bits) != 2))
1832 	{
1833 	    errno = 0;
1834 	    result = 0;
1835 	}
1836 	host = hostCopy;
1837 	if (maskP)
1838 	{
1839 	    if (bits <= 0 || bits > 32) bits = 32;
1840 	    *maskP = htonl(0xffffffff << (32 - bits));
1841 	}
1842     }
1843 
1844     /*
1845     ** Try a direct conversion from numeric form first in order to avoid
1846     ** an unnecessary name-service lookup.
1847     */
1848 
1849     if ((addrP->sin_addr.s_addr = inet_addr(host)) == INADDR_NONE)
1850     {
1851 	if ((entry = gethostbyname(host)) == NULL)
1852 	{
1853 	    errno = 0;
1854 	    result = 0;
1855 	}
1856 	else
1857 	{
1858 	    memcpy(&(addrP->sin_addr), entry->h_addr, entry->h_length);
1859 	}
1860     }
1861 
1862     /* Retrieve full list of addresses if required */
1863 
1864     if (addrList != NULL)
1865     {
1866 	if (entry)
1867 	{
1868 	    for (count = 0; entry->h_addr_list[count]; count++)
1869 	    {
1870 		/* Nothing */
1871 	    }
1872 	    *addrList = (struct in_addr *)calloc(count + 1, sizeof(struct in_addr));
1873 	    if (*addrList == NULL)
1874 	    {
1875 		result = 0;
1876 	    }
1877 	    else
1878 	    {
1879 		for (i = 0; i < count; i++)
1880 		{
1881 		    memcpy(&((*addrList)[i]), entry->h_addr_list[i], sizeof(struct in_addr));
1882 		}
1883 		memset(&((*addrList)[i]), 0xff, sizeof(struct in_addr));
1884 	    }
1885 	}
1886 	else
1887 	{
1888 	    *addrList = (struct in_addr *)calloc(2, sizeof(struct in_addr));
1889 	    memcpy(&((*addrList)[0]), &(addrP->sin_addr), sizeof(struct in_addr));
1890 	    memset(&((*addrList)[1]), 0xff, sizeof(struct in_addr));
1891 	}
1892     }
1893 
1894     if (hostCopy)
1895     {
1896 	free(hostCopy);
1897     }
1898 
1899     mutexUnlock(MUTEX_IO);
1900 
1901     return result;
1902 }
1903 
1904 /*
1905 ** ipString
1906 **
1907 ** Convert IP address to a dotted-quad string. This is effectively a
1908 ** reentrant version of inet_ntoa.
1909 */
1910 
1911 char *
ipString(struct in_addr addr,char * buf)1912 ipString(struct in_addr addr, char *buf)
1913 {
1914     unsigned long val = ntohl(addr.s_addr);
1915     sprintf(buf, "%lu.%lu.%lu.%lu",
1916 	    (val >> 24) & 0xff,
1917 	    (val >> 16) & 0xff,
1918 	    (val >>  8) & 0xff,
1919 	    val & 0xff);
1920     return buf;
1921 }
1922 
1923 /*
1924 ** makeConnection
1925 **
1926 ** Set up a socket connection to the specified host and port. The host
1927 ** name can either be a DNS name or a string IP address. If udpMode is
1928 ** true then a UDP socket is created but it is not "connected". If useProxy
1929 ** is true and a TCP connection is requested then we will try to connect
1930 ** via a HTTP proxy.
1931 **
1932 ** If fromAddrP is not NULL then we will try to set the source address for
1933 ** the connection (not fatal if we fail). If toAddrP is not NULL then the
1934 ** address of the destination endpoint is returned.
1935 **
1936 ** If timeout is non-zero then the connection attempt will be timed out
1937 ** after that many seconds. Note that if connecting via proxy this will
1938 ** only affect the connection to the proxy, not the remote system.
1939 */
1940 
1941 int
makeConnection(const char * host,const unsigned short port,int udpMode,int useProxy,struct sockaddr_in * fromAddrP,struct sockaddr_in * toAddrP,unsigned short timeout)1942 makeConnection(const char *host, const unsigned short port,
1943 	       int udpMode, int useProxy,
1944 	       struct sockaddr_in *fromAddrP, struct sockaddr_in *toAddrP,
1945 	       unsigned short timeout)
1946 {
1947     int sfd = -1;
1948     struct sockaddr_in addr;
1949     fd_set testSet;
1950     struct timeval delay;
1951     int ready = -1;
1952 
1953 
1954     /* Sanity check */
1955 
1956     assert(host != NULL && port != 0);
1957 
1958     /*
1959     ** Check for connection via proxy and handle if necessary. This should
1960     ** only be applied to TCP connections between client and server.
1961     */
1962 
1963     if (!udpMode && useProxy)
1964     {
1965 	/* Only try if a proxy has been set */
1966 
1967 	if (ProxyHost && ProxyPort)
1968 	{
1969 	    return proxyConnection(host, port, toAddrP, timeout);
1970 	}
1971     }
1972 
1973     /* Create the socket */
1974 
1975     if ((sfd = socket(AF_INET, (udpMode ? SOCK_DGRAM : SOCK_STREAM), 0)) < 0)
1976     {
1977 	message(0, errno, "socket creation failed");
1978 	errno = 0;
1979 	return -1;
1980     }
1981 
1982     /*
1983     ** If a source address was specified, try to set it. This is not
1984     ** fatal if it fails -- not all platforms support it.
1985     */
1986 
1987 #ifdef TCP_TPROXY_SRCADDR
1988     /*
1989     ** Transparent proxy functionality should probably work in Linux 2.0/2.2
1990     ** but will not work in 2.4 when things were changed. You can hack the
1991     ** kernel if you really want but TCP_TPROXY_SRCADDR should be the way to
1992     ** go in Linux post 2.4. From what I gather anyway ...
1993     */
1994 #error "Time to implement transparent proxy using setsockopt(fd, SOL_TCP, TCP_TPROXY_SRCADDR, ...) now!"
1995 #else
1996     if (fromAddrP && fromAddrP->sin_addr.s_addr)
1997     {
1998 #ifdef USE_UDP_SPOOFING
1999 	closesocket(sfd);
2000 	if ((sfd = libnet_open_raw_sock(IPPROTO_RAW)) < 0)
2001 	{
2002 	    message(0, errno, "raw socket creation failed");
2003 	    errno = 0;
2004 	    return -1;
2005 	}
2006 #else
2007 	memset(&addr, 0, sizeof(addr));
2008 	addr.sin_addr.s_addr = fromAddrP->sin_addr.s_addr;
2009 	if (bind(sfd, (struct sockaddr *)&addr, sizeof(addr)) < 0)
2010 	{
2011 	    message(1, errno, "WARNING: failed to set connection source address -- ignored");
2012 	}
2013 #endif
2014     }
2015 #endif
2016 
2017     /* Translate hostname from DNS or IP-address form */
2018 
2019     memset(&addr, 0, sizeof(addr));
2020     if (!getHostAddress(host, &addr, NULL, NULL))
2021     {
2022 	message(0, 0, "can't resolve host or address '%s'", host);
2023 	closesocket(sfd);
2024 	return -1;
2025     }
2026     addr.sin_family = AF_INET;
2027     addr.sin_port = htons(port);
2028 
2029     if (!udpMode)
2030     {
2031 
2032 	/* Set the "don't linger on close" option */
2033 
2034 	setNoLinger(sfd);
2035 
2036 	/*
2037 	** If there is a timeout on the connection then we need to use
2038 	** non-blocking mode, otherwise we can just do a straight connect
2039 	*/
2040 
2041 	if (timeout == 0)
2042 	{
2043 	    if (connect(sfd, (struct sockaddr *)&addr, sizeof(addr)) < 0)
2044 	    {
2045 		closesocket(sfd);
2046 		return -1;
2047 	    }
2048 	}
2049 	else
2050 	{
2051 	    /* Turn on non-blocking mode */
2052 
2053 	    setNonBlocking(sfd, 1);
2054 
2055 	    /*
2056 	    ** Issue the connect. This may succeed immediately, which
2057 	    ** is highly unlikely, or "fail" but with errno set to
2058 	    ** EWOULDBLOCK or EINPROGRESS. EINTR is also possible
2059 	    */
2060 
2061 	    connect(sfd, (struct sockaddr *)&addr, sizeof(addr));
2062 	    if (errno != 0 && errno != EWOULDBLOCK
2063 		&& errno != EINPROGRESS && errno != EINTR)
2064 	    {
2065 		closesocket(sfd);
2066 		return -1;
2067 	    }
2068 
2069 	    /* Now wait for socket to be writable -- connect complete */
2070 
2071 	    delay.tv_sec = timeout;
2072 	    delay.tv_usec = 0;
2073 
2074 	    FD_ZERO(&testSet);
2075 	    FD_SET(sfd, &testSet);
2076 
2077 	    ready = select(sfd + 1, 0, &testSet, 0, &delay);
2078 
2079 	    /* Check for timeout or other failure */
2080 
2081 	    if (ready <= 0)
2082 	    {
2083 		closesocket(sfd);
2084 		return -1;
2085 	    }
2086 
2087 	    /* Set socket back to blocking mode */
2088 
2089 	    setNonBlocking(sfd, 0);
2090 
2091 	    /* Now see if the socket is *really* usable */
2092 
2093 	    errno = 0;
2094 	    if (!socketIsUsable(sfd))
2095 	    {
2096 		closesocket(sfd);
2097 		return -1;
2098 	    }
2099 	}
2100     }
2101 
2102     /* If the address structure was requested then return it */
2103 
2104     if (toAddrP)
2105     {
2106 	memcpy(toAddrP, &addr, sizeof(addr));
2107     }
2108 
2109     return sfd;
2110 }
2111 
2112 /*
2113 ** base64Encode
2114 **
2115 ** Encode a string using base64 encoding.
2116 */
2117 
2118 char *
base64Encode(char * str)2119 base64Encode(char *str)
2120 {
2121     static char *encoding = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
2122 			    "abcdefghijklmnopqrstuvwxyz"
2123 			    "0123456789+/";
2124     char *s = NULL;
2125     char *buf = NULL;
2126     int len = -1;
2127     int i = 0;
2128     unsigned long bits;
2129 
2130 
2131     if (str == NULL)
2132     {
2133 	return NULL;
2134     }
2135 
2136     len = strlen(str);
2137 
2138     /*
2139     ** Base64 encoding expands 6 bits to 1 char, padded with '=', if
2140     ** necessary.
2141     */
2142 
2143     if ((buf = malloc(4 * ((len + 2) / 3) + 1)) == NULL)
2144     {
2145 	return NULL;
2146     }
2147 
2148     s = buf;
2149     for (i = 0; i <= len - 3; i += 3)
2150     {
2151 	bits = ((unsigned long)(str[i])) << 24;
2152 	bits |= ((unsigned long)(str[i + 1])) << 16;
2153 	bits |= ((unsigned long)(str[i + 2])) << 8;
2154 
2155 	*s++ = encoding[bits >> 26];
2156 	bits <<= 6;
2157 	*s++ = encoding[bits >> 26];
2158 	bits <<= 6;
2159 	*s++ = encoding[bits >> 26];
2160 	bits <<= 6;
2161 	*s++ = encoding[bits >> 26];
2162     }
2163 
2164     switch (len % 3)
2165     {
2166     case 0:
2167 	bits = ((unsigned long)(str[i])) << 24;
2168 	bits |= ((unsigned long)(str[i + 1])) << 16;
2169 	bits |= ((unsigned long)(str[i + 2])) << 8;
2170 	*s++ = encoding[bits >> 26];
2171 	bits <<= 6;
2172 	*s++ = encoding[bits >> 26];
2173 	bits <<= 6;
2174 	*s++ = encoding[bits >> 26];
2175 	bits <<= 6;
2176 	*s++ = encoding[bits >> 26];
2177 	break;
2178 
2179     case 2:
2180 	bits = ((unsigned long)(str[len - 2])) << 24;
2181 	bits |= ((unsigned long)(str[len - 1])) << 16;
2182 	*s++ = encoding[bits >> 26];
2183 	bits <<= 6;
2184 	*s++ = encoding[bits >> 26];
2185 	bits <<= 6;
2186 	*s++ = encoding[bits >> 26];
2187 	*s++ = '=';
2188 	break;
2189 
2190     case 1:
2191 	bits = ((unsigned long)(str[len - 2])) << 24;
2192 	*s++ = encoding[bits >> 26];
2193 	bits <<= 6;
2194 	*s++ = encoding[bits >> 26];
2195 	*s++ = '=';
2196 	*s++ = '=';
2197 	break;
2198     }
2199 
2200     *s = '\0';
2201     return buf;
2202 }
2203 
2204 /*
2205 ** proxyConnection
2206 **
2207 ** Make a connection to the specified host and port via an HTTP proxy
2208 ** supporting the CONNECT method. The toAddrP and timeout arguments are
2209 ** passed on to the (recursive) makeConnection call. Note that ProxyHost
2210 ** must be non-NULL before this function is called.
2211 **
2212 ** A strictly configured proxy server may not allow connection to arbitrary
2213 ** ports but only to that used by HTTPS (port 443). Also, in order to give
2214 ** proxy server owners some chance of blocking Zebedee if they wish to,
2215 ** the connect method header contains a "User-Agent: Zebedee" line. Unless
2216 ** someone has modified this code, that is :-)
2217 **
2218 ** If ProxyAuth is not NULL it should be the base64-encoded username:password
2219 ** which will be passed to the proxy server.
2220 */
2221 
2222 int
proxyConnection(const char * host,const unsigned short port,struct sockaddr_in * toAddrP,unsigned short timeout)2223 proxyConnection(const char *host, const unsigned short port,
2224 		struct sockaddr_in *toAddrP, unsigned short timeout)
2225 {
2226     int fd = -1;
2227     char buf[MAX_LINE_SIZE + 1];
2228     int num = 0;
2229     int total = 0;
2230     char *bufP = NULL;
2231 
2232 
2233     assert(ProxyHost != NULL);
2234 
2235     /* Connect to the proxy server */
2236 
2237     message(4, 0, "connecting to %s:%hu via proxy %s:%hu", host, port, ProxyHost, ProxyPort);
2238 
2239     if ((fd = makeConnection(ProxyHost, ProxyPort, 0, 0, NULL, toAddrP, timeout)) == -1)
2240     {
2241 	message(0, errno, "can't connect to proxy server at %s:%hu", ProxyHost, ProxyPort);
2242 	return -1;
2243     }
2244 
2245     message(5, 0, "connected to proxy");
2246 
2247     /*
2248     ** Write the connect string. This includes a "User-Agent: Zebedee" line
2249     ** in order to help identify this connection as coming from Zebedee.
2250     ** This should be OK -- and conforms to the spec of the connect method
2251     ** as far as I can tell -- but may be rejected by some proxies. It may
2252     ** also be that no proxies currently look at or use this information
2253     ** but it is there if necessary.
2254     */
2255 
2256     buf[MAX_LINE_SIZE] = '\0';
2257     if (ProxyAuth)
2258     {
2259 	snprintf(buf, sizeof(buf) - 1, "CONNECT %s:%hu HTTP/1.0\r\nProxy-Authorization: Basic %s\r\nUser-Agent: Zebedee\r\n\r\n", host, port, ProxyAuth);
2260     }
2261     else
2262     {
2263 	snprintf(buf, sizeof(buf) - 1, "CONNECT %s:%hu HTTP/1.0\r\nUser-Agent: Zebedee\r\n\r\n", host, port);
2264     }
2265 
2266     if (send(fd, buf, strlen(buf), 0) <= 0)
2267     {
2268 	message(0, errno, "failed writing to proxy server");
2269     }
2270 
2271     message(5, 0, "written connect string");
2272 
2273     /*
2274     ** We will now read the response from the proxy (up to MAX_LINE_SIZE
2275     ** bytes) and search for the header termination. This is two CR-LF
2276     ** pairs in succession. All proxies I have tried respond with less
2277     ** than this amount of data, although it is conceivable they might
2278     ** reply with more. If so, this will probably cause the Zebedee
2279     ** protocol exchange to fail.
2280     */
2281 
2282     bufP = buf;
2283     do
2284     {
2285 	if ((num = recv(fd, bufP, (MAX_LINE_SIZE - total), 0)) <= 0)
2286 	{
2287 	    message(0, errno, "failed reading response from proxy");
2288 	    closesocket(fd);
2289 	    return -1;
2290 	}
2291 	total += num;
2292 	bufP += num;
2293 	*bufP = '\0';
2294 	message(5, 0, "read %d bytes from proxy: %s", num, bufP - num);
2295     }
2296     while(total < MAX_LINE_SIZE && strncmp(bufP - 4, "\r\n\r\n", 4));
2297 
2298     /* Check for an OK response */
2299 
2300     if (strncmp(buf, "HTTP/1.0 200", 12) && strncmp(buf, "HTTP/1.1 200", 12))
2301     {
2302 	if ((bufP = strchr(buf, '\r')) != NULL)
2303 	{
2304 	    *bufP = '\0';
2305 	}
2306 	message(0, 0, "proxy server refused connection to %s:%h (%s)", host, port, buf);
2307 	closesocket(fd);
2308 	return -1;
2309     }
2310 
2311     message(4, 0, "connection via proxy successful");
2312 
2313     return fd;
2314 }
2315 
2316 /*
2317 ** sendSpoofed
2318 **
2319 ** Send a UDP packet to the address and port in toAddrP, purporting to
2320 ** originate from the address in fromAddrP.
2321 */
2322 
2323 int
sendSpoofed(int fd,char * buf,int len,struct sockaddr_in * toAddrP,struct sockaddr_in * fromAddrP)2324 sendSpoofed(int fd, char *buf, int len, struct sockaddr_in *toAddrP, struct sockaddr_in *fromAddrP)
2325 {
2326 #ifdef USE_UDP_SPOOFING
2327     u_char *packet = NULL;
2328     int packetSize = 0;
2329     int num = -1;
2330 
2331 
2332     packetSize = LIBNET_IP_H + LIBNET_UDP_H + len;
2333 
2334     libnet_init_packet(packetSize, &packet);
2335     if (packet == NULL)
2336     {
2337 	message(0, 0, "failed to allocate packet buffer");
2338 	return -1;
2339     }
2340 
2341     /* Build IP packet header */
2342 
2343     libnet_build_ip(LIBNET_UDP_H + len,	/* Size beyond IP header */
2344 		    0,			/* IP ToS */
2345 		    rand() % 11965 + 1,	/* IP ID */
2346 		    0,			/* Frag */
2347 		    64,			/* TTL */
2348 		    IPPROTO_UDP,	/* Transport protocol */
2349 		    fromAddrP->sin_addr.s_addr,	/* Source address */
2350 		    toAddrP->sin_addr.s_addr,	/* Destination address */
2351 		    NULL,		/* Pointer to payload */
2352 		    0,			/* Size */
2353 		    packet);		/* Packet buffer */
2354 
2355     /* Add UDP packet header and payload */
2356 
2357     libnet_build_udp(ntohs(fromAddrP->sin_port),    /* Source port */
2358 		     ntohs(toAddrP->sin_port),	    /* Dest port */
2359 		     buf,		/* Payload */
2360 		     len,		/* Payload size */
2361 		     packet + LIBNET_IP_H);
2362 
2363     /* Do the checksum for the UDP header */
2364 
2365     if (libnet_do_checksum(packet, IPPROTO_UDP, LIBNET_UDP_H + len) == -1)
2366     {
2367 	message(0, 0, "packet checksum failed");
2368 	goto cleanup;
2369     }
2370 
2371     /* Write the packet */
2372 
2373     num = libnet_write_ip(fd, packet, packetSize);
2374     if (num < packetSize)
2375     {
2376 	message(1, 0, "Warning: short packet write (%d < %d)", num, packetSize);
2377     }
2378     num -= (LIBNET_IP_H + LIBNET_UDP_H);
2379 
2380 cleanup:
2381     libnet_destroy_packet(&packet);
2382     return num;
2383 #else
2384     return -1;
2385 #endif
2386 }
2387 
2388 /*
2389 ** makeListener
2390 **
2391 ** Set up a listener socket on the port supplied via portP. If listenIp
2392 ** is not NULL then it specifies the address on which we will listen.
2393 **
2394 ** If the requested port is 0 then a new port will be allocated and
2395 ** returned in portP. If the requested port is non-zero then an attempt
2396 ** will be made to re-use the address if possible.
2397 **
2398 ** The routine returns the socket ID on success or -1 on error.
2399 */
2400 
2401 int
makeListener(unsigned short * portP,char * listenIp,int udpMode,int listenQueue)2402 makeListener(unsigned short *portP, char *listenIp, int udpMode, int listenQueue)
2403 {
2404     int sfd = -1;
2405     struct sockaddr_in addr;
2406     int addrLen = sizeof(addr);
2407     int trueVal = 1;
2408     char ipBuf[IP_BUF_SIZE];
2409 
2410 
2411     /* Create the socket */
2412 
2413     if ((sfd = socket(AF_INET, (udpMode ? SOCK_DGRAM: SOCK_STREAM), 0)) < 0)
2414     {
2415 	message(0, errno, "can't create listener socket");
2416 	goto failure;
2417     }
2418 
2419     /* If we requested a specific port then reuse the address if possible */
2420 
2421     if (portP && *portP)
2422     {
2423 	if (setsockopt(sfd, SOL_SOCKET, SO_REUSEADDR, (char *)&trueVal, sizeof(trueVal)) < 0)
2424 	{
2425 	    message(1, 0, "Warning: failed to set SO_REUSEADDR option on socket");
2426 	}
2427     }
2428 
2429     memset(&addr, 0, sizeof(addr));
2430     addr.sin_addr.s_addr = htonl(INADDR_ANY);
2431     if (listenIp != NULL)
2432     {
2433 	if (!getHostAddress(listenIp, &addr, NULL, NULL))
2434 	{
2435 	    message(0, 0, "can't resolve listen address '%s'", listenIp);
2436 	}
2437     }
2438     addr.sin_family = AF_INET;
2439     addr.sin_port = (portP ? htons(*portP) : 0);
2440     message(5, 0, "listening on %s", ipString(addr.sin_addr, ipBuf));
2441 
2442     if (bind(sfd, (struct sockaddr *)&addr, addrLen) < 0)
2443     {
2444 	message(0, errno, "listener bind failed");
2445 	goto failure;
2446     }
2447 
2448     if (!udpMode)
2449     {
2450 	if (listen(sfd, listenQueue) < 0)
2451 	{
2452 	    message(0, errno, "listen failed");
2453 	    goto failure;
2454 	}
2455     }
2456 
2457     if (portP)
2458     {
2459 	/* Retrieve the port actually being used to return via portP */
2460 
2461 	memset(&addr, 0, sizeof(addr));
2462 	if (getsockname(sfd, (struct sockaddr *)&addr, &addrLen))
2463 	{
2464 	    message(0, errno, "can't get local port number");
2465 	    goto failure;
2466 	}
2467 	*portP = ntohs(addr.sin_port);
2468     }
2469 
2470     return sfd;
2471 
2472 failure:
2473     if (sfd != -1)
2474     {
2475 	(void)closesocket(sfd);
2476     }
2477     errno = -1;
2478     return -1;
2479 }
2480 
2481 /*
2482 ** setNoLinger
2483 **
2484 ** Turn off "linger on close" behaviour for a socket.
2485 */
2486 
2487 void
setNoLinger(int fd)2488 setNoLinger(int fd)
2489 {
2490     struct linger lingerVal;
2491 
2492     lingerVal.l_onoff = 0;
2493     lingerVal.l_linger = 0;
2494     if (setsockopt(fd, SOL_SOCKET, SO_LINGER,
2495 		   (char *)&lingerVal, sizeof(lingerVal)) < 0)
2496     {
2497 	message(1, 0, "Warning: failed to set SO_LINGER option on socket");
2498     }
2499 }
2500 
2501 /*
2502 ** setKeepAlive
2503 **
2504 ** Turn on "keep alives" for a socket.
2505 */
2506 
2507 void
setKeepAlive(int fd)2508 setKeepAlive(int fd)
2509 {
2510     int trueVal = 1;
2511 
2512     if (setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE,
2513 		   (char *)&trueVal, sizeof(trueVal)) < 0)
2514     {
2515 	message(1, 0, "Warning: failed to set SO_KEEPALIVE option on socket");
2516     }
2517 }
2518 
2519 /*
2520 ** setNonBlocking
2521 **
2522 ** Turn on/off non-blocking
2523 */
2524 
2525 void
setNonBlocking(int fd,unsigned long nonBlock)2526 setNonBlocking(int fd, unsigned long nonBlock)
2527 {
2528 #ifdef WIN32
2529     ioctlsocket(fd, FIONBIO, &nonBlock);
2530 #else
2531     fcntl(fd, F_SETFL, (nonBlock ? O_NONBLOCK : 0));
2532 #endif
2533 }
2534 
2535 /*
2536 ** acceptConnection
2537 **
2538 ** Accept a connection on the specified listenFd. If the host is "*" then
2539 ** a connection from any source will be accepted otherwise the source
2540 ** address must match that obtained from the forward lookup of the host
2541 ** name (which may be a range of addresses if it contains an address mask).
2542 **
2543 ** If the loop parameter is true then the routine will wait until a "good"
2544 ** connection has been accepted otherwise it will stop on the first error.
2545 ** The timeout parameter sets the maximum number of seconds that the
2546 ** routine will wait.
2547 **
2548 ** On success return the socket number otherwise -1.
2549 */
2550 
2551 int
acceptConnection(int listenFd,const char * host,int loop,unsigned short timeout)2552 acceptConnection(int listenFd, const char *host,
2553 		 int loop, unsigned short timeout)
2554 {
2555     struct sockaddr_in fromAddr;
2556     struct sockaddr_in hostAddr;
2557     int addrLen;
2558     int serverFd = -1;
2559     struct timeval delay;
2560     fd_set testSet;
2561     int ready;
2562     struct in_addr *addrList = NULL;
2563     struct in_addr *addrPtr = NULL;
2564     unsigned long mask = 0xffffffff;
2565     char ipBuf[IP_BUF_SIZE];
2566 
2567 
2568     memset(&hostAddr, 0, sizeof(hostAddr));
2569     if (strcmp(host, "*") == 0)
2570     {
2571 	mask = 0;
2572 	hostAddr.sin_addr.s_addr = 0;
2573     }
2574     else
2575     {
2576 	if (!getHostAddress(host, &hostAddr, &addrList, &mask))
2577 	{
2578 	    message(0, 0, "can't resolve host or address '%s'", host);
2579 	    closesocket(serverFd);
2580 	    errno = 0;
2581 	    return -1;
2582 	}
2583     }
2584 
2585     while (1)
2586     {
2587 	message(3, 0, "waiting to accept connection");
2588 
2589 	delay.tv_sec = timeout;
2590 	delay.tv_usec = 0;
2591 
2592 	FD_ZERO(&testSet);
2593 	FD_SET(listenFd, &testSet);
2594 
2595 	ready = select(listenFd + 1, &testSet, 0, 0, &delay);
2596 
2597 	if (ready == 0)
2598 	{
2599 	    message(0, 0, "timed out waiting to accept connection");
2600 	    goto failure;
2601 	}
2602 
2603 	/* Check for error but ignore interrupted system calls */
2604 
2605 	if (ready < 0 && errno != EINTR)
2606 	{
2607 	    if (errno != EINTR)
2608 	    {
2609 		message(0, errno, "error in select waiting for client to accept connection");
2610 		goto failure;
2611 	    }
2612 	    else
2613 	    {
2614 		continue;
2615 	    }
2616 	}
2617 
2618 	/* Attempt to accept the connection */
2619 
2620 	addrLen = sizeof(struct sockaddr_in);
2621 	memset(&fromAddr, 0, sizeof(fromAddr));
2622 	if ((serverFd = accept(listenFd,
2623 			       (struct sockaddr *)&fromAddr,
2624 			       &addrLen)) < 0)
2625 	{
2626 	    /* This is always an error, looping or not */
2627 	    goto failure;
2628 	}
2629 
2630 	/*
2631 	** Check if the connection is usable, in case it has
2632 	** already been closed at the far end. If it isn't usable
2633 	** the silently discard it.
2634 	*/
2635 
2636 	if (!socketIsUsable(serverFd))
2637 	{
2638 	    closesocket(serverFd);
2639 	    errno = 0;
2640 	    if (loop)
2641 	    {
2642 		continue;
2643 	    }
2644 	    else
2645 	    {
2646 		goto failure;
2647 	    }
2648 	}
2649 
2650 	/*
2651 	** Check the received connection address against the specified
2652 	** server host name (applying a network mask as ppropriate).
2653 	*/
2654 
2655 	if ((fromAddr.sin_addr.s_addr & mask) ==
2656 	    (hostAddr.sin_addr.s_addr & mask))
2657 	{
2658 	    /* We've got a straight match */
2659 	    break;
2660 	}
2661 	else
2662 	{
2663 	    /* Try the alias addresses */
2664 
2665 	    for (addrPtr = addrList; addrPtr->s_addr != 0xffffffff; addrPtr++)
2666 	    {
2667 		if ((fromAddr.sin_addr.s_addr & mask) ==
2668 		    (addrPtr->s_addr & mask))
2669 		{
2670 		    break;
2671 		}
2672 	    }
2673 
2674 	    if (addrPtr->s_addr != 0xffffffff)
2675 	    {
2676 		/* We got a match -- break enclosing loop */
2677 		break;
2678 	    }
2679 	}
2680 
2681 	message(1, 0, "Warning: connection from %s rejected, does not match server host %s",
2682 		ipString(fromAddr.sin_addr, ipBuf), host);
2683 	closesocket(serverFd);
2684 	errno = 0;
2685 	if (!loop)
2686 	{
2687 	    goto failure;
2688 	}
2689     }
2690 
2691     /* Free memory allocated by getHostAddress */
2692 
2693     if (addrList)
2694     {
2695 	free(addrList);
2696     }
2697 
2698     message(3, 0, "accepted connection from %s", ipString(fromAddr.sin_addr, ipBuf));
2699 
2700     /*
2701     ** Set the "don't linger on close" and "keep alive" options. The latter
2702     ** will (eventually) reap defunct connections.
2703     */
2704 
2705     setNoLinger(serverFd);
2706     setKeepAlive(serverFd);
2707 
2708     return serverFd;
2709 
2710 failure:
2711     if (addrList) free(addrList);
2712     return -1;
2713 }
2714 
2715 /*
2716 ** socketIsUsable
2717 **
2718 ** Check if socket is usable. It may be unusable if it has not properly
2719 ** been connected or has been closed remotely.
2720 */
2721 
2722 int
socketIsUsable(int sock)2723 socketIsUsable(int sock)
2724 {
2725     fd_set testSet;
2726     struct timeval delay;
2727     unsigned char buf[1];
2728     struct sockaddr_in addr;
2729     int addrLen = sizeof(addr);
2730 
2731 
2732     /* Get the peer name -- will fail if never connected */
2733 
2734     if (getpeername(sock, (struct sockaddr *)&addr, &addrLen))
2735     {
2736 	message(4, errno, "socket %d has no peer address", sock);
2737 	return 0;
2738     }
2739 
2740     /* Check writability */
2741 
2742     FD_ZERO(&testSet);
2743     FD_SET(sock, &testSet);
2744     delay.tv_sec = 0;
2745     delay.tv_usec = 0;
2746 
2747     if (select(sock + 1, 0, &testSet, 0, &delay) <= 0)
2748     {
2749 	message(4, 0, "socket %d is not writable", sock);
2750 	return 0;
2751     }
2752 
2753     /*
2754     ** Now see if it is readable, and if it is, peek at the contents to
2755     ** see if there is and EOF
2756     */
2757 
2758     FD_ZERO(&testSet);
2759     FD_SET(sock, &testSet);
2760     delay.tv_sec = 0;
2761     delay.tv_usec = 0;
2762 
2763     if (select(sock + 1, &testSet, 0, 0, &delay) > 0)
2764     {
2765 	message(4, 0, "socket %d is readable, checking for EOF", sock);
2766 	errno = 0;
2767 	if (recv(sock, buf, sizeof(buf), MSG_PEEK) <= 0)
2768 	{
2769 	    message(4, errno, "socket %d has immediate EOF or error", sock);
2770 	    return 0;
2771 	}
2772     }
2773 
2774     message(4, 0, "socket %d is usable", sock);
2775     /* Not yet readable, or no EOF so assume OK! */
2776     return 1;
2777 }
2778 
2779 /*
2780 ** headerSetUShort
2781 **
2782 ** Set the specified unsigned short value into the protocol header buffer
2783 ** (hdrBuf) at the specified byte offset.
2784 */
2785 
2786 void
headerSetUShort(unsigned char * hdrBuf,unsigned short value,int offset)2787 headerSetUShort(unsigned char *hdrBuf, unsigned short value, int offset)
2788 {
2789     hdrBuf[offset] = (value >> 8) & 0xff;
2790     hdrBuf[offset + 1] = value & 0xff;
2791 }
2792 
2793 /*
2794 ** headerSetULong
2795 **
2796 ** Set the specified unsigned long (32-bit) value into the protocol header
2797 ** buffer (hdrBuf) at the specified byte offset.
2798 */
2799 
2800 void
headerSetULong(unsigned char * hdrBuf,unsigned long value,int offset)2801 headerSetULong(unsigned char *hdrBuf, unsigned long value, int offset)
2802 {
2803     hdrBuf[offset] = (value >> 24) & 0xff;
2804     hdrBuf[offset + 1] = (value >> 16) & 0xff;
2805     hdrBuf[offset + 2] = (value >> 8) & 0xff;
2806     hdrBuf[offset + 3] = value & 0xff;
2807 }
2808 
2809 /*
2810 ** headerGetUShort
2811 **
2812 ** Retrieve an unsigned short value from the protocol header buffer
2813 ** (hdrBuf) at the specified byte offset.
2814 */
2815 
2816 unsigned short
headerGetUShort(unsigned char * hdrBuf,int offset)2817 headerGetUShort(unsigned char *hdrBuf, int offset)
2818 {
2819     return (((unsigned short)hdrBuf[offset]) << 8) + (unsigned short)hdrBuf[offset + 1];
2820 }
2821 
2822 /*
2823 ** headerGetUShort
2824 **
2825 ** Retrieve an unsigned long (32-bit) value from the protocol header buffer
2826 ** (hdrBuf) at the specified byte offset.
2827 */
2828 
2829 unsigned long
headerGetULong(unsigned char * hdrBuf,int offset)2830 headerGetULong(unsigned char *hdrBuf, int offset)
2831 {
2832     return  (((unsigned long)hdrBuf[offset]) << 24) +
2833 	    (((unsigned long)hdrBuf[offset + 1]) << 16) +
2834 	    (((unsigned long)hdrBuf[offset + 2]) << 8) +
2835 	    (unsigned long)hdrBuf[offset + 3];
2836 }
2837 
2838 /*********************************\
2839 **				 **
2840 **  Encryption-related Routines  **
2841 **				 **
2842 \*********************************/
2843 
2844 /*
2845 ** setupBlowfish
2846 **
2847 ** Create and initialise a BFState_t structure to hold the encryption
2848 ** context for one communication stream (A -> B or B -> A but not both).
2849 **
2850 ** keyStr is the key data which is in the form of a string of hexadecimal
2851 ** digits. The actual key used is the high-order keyBits bits of this
2852 ** number.
2853 **
2854 ** The routine returns a pointer to the newly-allocated structure on success
2855 ** or NULL on error. As a special case, if the key length is zero then no
2856 ** encryption is needed and we also return NULL.
2857 */
2858 
2859 BFState_t *
setupBlowfish(char * keyStr,unsigned short keyBits)2860 setupBlowfish(char *keyStr, unsigned short keyBits)
2861 {
2862     BFState_t *bf = NULL;
2863     unsigned char keyData[MAX_KEY_BYTES];
2864     int keyBytes;
2865 
2866 
2867     /* Special case -- no encryption requeste */
2868 
2869     if (keyBits == 0) return NULL;
2870 
2871     /* Now allocate the necessary space */
2872 
2873     if ((bf = (BFState_t *)malloc(sizeof(BFState_t))) == NULL)
2874     {
2875 	message(0, errno, "out of memory allocating Blowfish state data");
2876 	errno = 0;
2877 	return NULL;
2878     }
2879 
2880     keyBytes = hexStrToBits(keyStr, keyBits, keyData);
2881 
2882     memset(bf, 0, sizeof(BFState_t));
2883     BF_set_key(&(bf->key), keyBytes, keyData);
2884     memcpy(bf->iVec, INIT_IVEC, 8);
2885     bf->pos = 0;
2886 
2887     return bf;
2888 }
2889 
2890 /*
2891 ** generateKey
2892 **
2893 ** Generate the exponent (private key) for the Diffie-Hellman key
2894 ** exchange.
2895 **
2896 ** Good key generation is crucial for the security of the encryption
2897 ** mechanism. Ideally we would generate keys based on truly random
2898 ** sources of data -- like radioactive decay. Unfortunately this is
2899 ** not tremendously practical so we have to do the best we can to
2900 ** generate keys that will be hard to predict. How well we can achieve
2901 ** this depends somewhat on the operating system on which the program
2902 ** is running. See the inline comments below.
2903 **
2904 ** In the comments we will try to set some bounds on the number of
2905 ** "bits of uncertainty" (BOU) -- that is how many bits' worth of
2906 ** imprecision there is in determining various quantities for an attacker.
2907 ** The "Min BOU" is where an attacker has access to the system and can
2908 ** examine system performance counters etc. The "Max BOU" is where there
2909 ** is no such access and all the attacker has access to is the data "on
2910 ** the wire". Please note that these are estimates, NOT guarantees!
2911 **
2912 ** Basically, if you are happy that an attacker can not see the state of
2913 ** your system when the key is generated (either through a direct login
2914 ** or via remote administrative interfaces) then the algorithms below
2915 ** are PROBABLY sufficient but in other cases you will need a
2916 ** different approach.
2917 **
2918 ** If you are not happy with these key generation mechanisms then
2919 ** you can call out to an external program. This needs to generate a
2920 ** single string of hexadecimal digits (at least MIN_KEY_BYTES long)
2921 ** which will be used as the key.
2922 **
2923 ** The peer and target addresses and targe port are passed through in
2924 ** order to allow them to be supplied to an external key generation
2925 ** command, if required.
2926 */
2927 
2928 char *
generateKey(struct sockaddr_in * peerAddrP,struct sockaddr_in * targetAddrP,unsigned short targetPort)2929 generateKey(struct sockaddr_in *peerAddrP,
2930 	    struct sockaddr_in *targetAddrP,
2931 	    unsigned short targetPort)
2932 {
2933     SHA_INFO sha;
2934     time_t now = time(NULL);
2935     unsigned long pid = threadPid();
2936     unsigned long tid = threadTid();
2937     char *result = NULL;
2938 
2939     /* If a private key has been supplied copy it and return it */
2940 
2941     if (PrivateKey)
2942     {
2943 	if ((result = (char *)malloc(strlen(PrivateKey) + 1)) == NULL)
2944 	{
2945 	    return NULL;
2946 	}
2947 	strcpy(result, PrivateKey);
2948 	return result;
2949     }
2950 
2951     /*
2952     ** If a key generator command was specified then use this to generate
2953     ** the key rather than doing it directly here. If the generator fails,
2954     ** however, then we will fall back to the inline method.
2955     */
2956 
2957     if (KeyGenCmd && (result = runKeyGenCommand(KeyGenCmd, peerAddrP, targetAddrP, targetPort)) != NULL)
2958     {
2959 	return result;
2960     }
2961 
2962     /*
2963     ** We use SHA to "stir" whatever bits of "entropy" we can acquire.
2964     ** This distributes the input very well over 160 bits.
2965     */
2966 
2967     sha_init(&sha);
2968 
2969     /*
2970     ** In all cases add the current time and process and thread IDs.
2971     ** The time can be guessed by an attacker to within a second. With
2972     ** physical access to the machine the PID and probably TID can be
2973     ** obtained with certainty. Even without physical access on UNIX
2974     ** the uncertainty in the PID and TID is less than 16 bits. On Win32
2975     ** it seems even less.
2976     **
2977     ** Min BOU: 1
2978     ** Max BOU: 16
2979     */
2980 
2981     sha_update(&sha, (SHA_BYTE *)&now, sizeof(now));
2982     sha_update(&sha, (SHA_BYTE *)&pid, sizeof(pid));
2983     sha_update(&sha, (SHA_BYTE *)&tid, sizeof(tid));
2984 
2985 #if defined(WIN32)
2986     {
2987 	LARGE_INTEGER perf;
2988 	FILETIME created, exited, kernel, user;
2989 	LONG val;
2990 	POINT point;
2991 	MEMORYSTATUS memoryStatus;
2992 
2993 	/*
2994 	** Add in a large number of reasonable hard to guess (from the
2995 	** outside) values. Someone with access to the machines may,
2996 	** however be able to pinpoint these with some accuracy. We will
2997 	** assume a maximum of 8 BOU for each call an a minimum of 1.
2998 	**
2999 	** Min BOU: 13
3000 	** Max BOU: 104
3001 	*/
3002 
3003 #define ADDLONGVAL(func) val = ((LONG)func()); sha_update(&sha, (SHA_BYTE *)&val, sizeof(val))
3004 	ADDLONGVAL(GetActiveWindow);
3005 	ADDLONGVAL(GetCapture);
3006 	ADDLONGVAL(GetClipboardOwner);
3007 	ADDLONGVAL(GetClipboardViewer);
3008 	ADDLONGVAL(GetDesktopWindow);
3009 	ADDLONGVAL(GetFocus);
3010 	ADDLONGVAL(GetInputState);
3011 	ADDLONGVAL(GetMessagePos);
3012 	ADDLONGVAL(GetMessageTime);
3013 	ADDLONGVAL(GetOpenClipboardWindow);
3014 	ADDLONGVAL(GetProcessHeap);
3015 	ADDLONGVAL(GetProcessWindowStation);
3016 	ADDLONGVAL(GetTickCount);
3017 
3018 	/*
3019 	** QueryPerformanceCounter gives a very high resolution 64-bit
3020 	** time result. Unfortunately, if there is no hardware support
3021 	** for a high-resolution timer it can return zero. On hardware
3022 	** I have available the resolution is over 1 million counts per
3023 	** second.
3024 	**
3025 	** Assume, in the worst case that the process start time can
3026 	** be determined with millisecond accuracy.
3027 	**
3028 	** Min BOU: 10
3029 	** Max BOU: 64
3030 	*/
3031 
3032 	(void)QueryPerformanceCounter(&perf);
3033 
3034 	sha_update(&sha, (SHA_BYTE *)&perf, sizeof(perf));
3035 
3036 	/*
3037 	** The following quantities are 64 bit times in 100nsec
3038 	** intervals since Jan 1, 1601. They are available to be
3039 	** read by other suitably privileged processes. I'm not sure
3040 	** of the resolution and only the kernel and user times
3041 	** have any degree of unpredictability from "outside" so
3042 	** we will make conservative estimates.
3043 	**
3044 	** Min BOU: 4
3045 	** Max BOU: 32
3046 	*/
3047 
3048 	GetProcessTimes(GetCurrentProcess(),
3049 			&created, &exited, &kernel, &user);
3050 
3051 	sha_update(&sha, (SHA_BYTE *)&created, sizeof(created));
3052 	sha_update(&sha, (SHA_BYTE *)&exited, sizeof(exited));
3053 	sha_update(&sha, (SHA_BYTE *)&kernel, sizeof(kernel));
3054 	sha_update(&sha, (SHA_BYTE *)&user, sizeof(user));
3055 
3056 	/*
3057 	** Current caret and cursor positon. Maybe somewhere in a 800x600
3058 	** area ... but known to an attacker with physical access.
3059 	**
3060 	** Min BOU: 0
3061 	** Max BOU: 175
3062 	*/
3063 
3064 	GetCaretPos(&point);
3065 	sha_update(&sha, (SHA_BYTE *)&point, sizeof(point));
3066 	GetCursorPos( &point );
3067 	sha_update(&sha, (SHA_BYTE *)&point, sizeof(point));
3068 
3069 	/*
3070 	** Memory usage statistics -- percent of memory in use, bytes of
3071 	** physical memory, bytes of free physical memory, bytes in paging
3072 	** file, free bytes in paging file, user bytes of address space,
3073 	** and free user bytes. Even to an attacker with physical access
3074 	** there is likely to be some uncertainty here, but maybe only
3075 	** a bit per variable quantity.
3076 	**
3077 	** Min BOU: 3
3078 	** Max BOU: 20+
3079 	*/
3080 
3081 	memoryStatus.dwLength = sizeof(MEMORYSTATUS);
3082 	GlobalMemoryStatus(&memoryStatus);
3083 	sha_update(&sha, (SHA_BYTE *)&memoryStatus, sizeof(memoryStatus));
3084 
3085 	/*
3086 	** Total estimates for Win32
3087 	**
3088 	** Min BOU: 31, Max BOU: 400+
3089 	*/
3090     }
3091 #else	/* !WIN32 */
3092     {
3093 	clock_t ticks;
3094 	struct tms tms;
3095 
3096 	/*
3097 	** On all UNIX systems we get the process time stats. These are
3098 	** 32-bit quantities relative to system boot.
3099 	**
3100 	** Min BOU: 2
3101 	** Max BOU: 40
3102 	*/
3103 
3104 	ticks = times(&tms);
3105 
3106 	sha_update(&sha, (SHA_BYTE *)&ticks, sizeof(ticks));
3107 	sha_update(&sha, (SHA_BYTE *)&tms, sizeof(tms));
3108     }
3109 
3110     if (KeyGenLevel == 2)
3111     {
3112 	/*
3113 	** Now we're talking! /dev/random uses internal kernel counters
3114 	** and state not accessible to normal users. We will read 10 chunks
3115 	** of 8 bytes which should give us more than enough to justify
3116 	** claiming that we have a full 160 bits of uncertainty coming
3117 	** out of the final hash.
3118 	**
3119 	** If you look closely we actually try /dev/urandom in preference
3120 	** to /dev/random. On Linux, although it is theoretically less
3121 	** secure, it will not block waiting for "enough" entropy unlike
3122 	** /dev/random.
3123 	**
3124 	** BOU: 160+
3125 	*/
3126 
3127 	int fd = open("/dev/urandom", O_RDONLY);
3128 	char buffer[8];
3129 	int i;
3130 
3131 	if (fd == -1 && (fd = open("/dev/random", O_RDONLY)) == -1)
3132 	{
3133 	    message(3, 0, "can't open /dev/urandom or /dev/random -- downgrading keygenlevel");
3134 	    KeyGenLevel--;
3135 	}
3136 	else
3137 	{
3138 	    for (i = 0; i < 10; i++)
3139 	    {
3140 		read(fd, buffer, 8);
3141 		sha_update(&sha, (SHA_BYTE *)buffer, 8);
3142 	    }
3143 	    close(fd);
3144 	}
3145     }
3146 
3147     if (KeyGenLevel == 1)
3148     {
3149 	/*
3150 	** If we haven't got /dev/random but do have /proc then we can
3151 	** probably do quite well on an active system. We stat every
3152 	** process and hash that data in. On a very stable system this
3153 	** could, however, be fairly predictable to an attacker with
3154 	** access to the system.
3155 	**
3156 	** Min BOU: 4
3157 	** Max BOU: 160+
3158 	*/
3159 
3160 	struct stat sbuf;
3161 	struct dirent *entryP;
3162 	DIR *dir = opendir("/proc");
3163 	char name[MAX_LINE_SIZE];
3164 
3165 
3166 	if (dir == NULL)
3167 	{
3168 	    message(4, 0, "can't open /proc -- downgrading keygenlevel");
3169 	    KeyGenLevel--;
3170 	}
3171 	else
3172 	{
3173 	    while ((entryP = readdir(dir)) != NULL)
3174 	    {
3175 		snprintf(name, sizeof(name), "/proc/%s", entryP->d_name);
3176 		stat(name, &sbuf);
3177 		sha_update(&sha, (SHA_BYTE *)entryP, sizeof(struct dirent));
3178 		sha_update(&sha, (SHA_BYTE *)&sbuf, sizeof(sbuf));
3179 	    }
3180 	    closedir(dir);
3181 	}
3182     }
3183 #endif	/* !WIN32 */
3184 
3185     /* Convert the digest to a string and return */
3186 
3187     sha_final(&sha);
3188 
3189     /* Exclude REALLY bad keys */
3190 
3191     if (sha.digest[0] == 0 && sha.digest[1] == 0 &&
3192 	sha.digest[2] == 0 && sha.digest[3] == 0 &&
3193 	(sha.digest[4] == 0 || sha.digest[4] == 1))
3194     {
3195 	return generateKey(peerAddrP, targetAddrP, targetPort);
3196     }
3197 
3198     if ((result = (char *)malloc(HASH_STR_SIZE)) == NULL)
3199     {
3200 	return NULL;
3201     }
3202 
3203     sprintf(result, "%08lx%08lx%08lx%08lx%08lx",
3204 	    (unsigned long)sha.digest[0], (unsigned long)sha.digest[1],
3205 	    (unsigned long)sha.digest[2], (unsigned long)sha.digest[3],
3206 	    (unsigned long)sha.digest[4]);
3207 
3208     return result;
3209 }
3210 
3211 /*
3212 ** runKeyGenCommand
3213 **
3214 ** This runs the specified key generation command, if any. It reads a single
3215 ** line from the command's standard output and extracts a hex string from
3216 ** it. The string must be at least MIN_KEY_BYTES * 2 bytes long.
3217 **
3218 ** If the key generation command ends with a "+" then the peer address,
3219 ** target address and target port will be appended to it before it is
3220 ** executed.
3221 **
3222 ** If the routine succeeds it malloc's space for the string and returns
3223 ** it otherwise it returns NULL.
3224 */
3225 
3226 char *
runKeyGenCommand(char * keyGenCmd,struct sockaddr_in * peerAddrP,struct sockaddr_in * targetAddrP,unsigned short targetPort)3227 runKeyGenCommand(char *keyGenCmd,
3228 		 struct sockaddr_in *peerAddrP,
3229 		 struct sockaddr_in *targetAddrP,
3230 		 unsigned short targetPort)
3231 {
3232     FILE *fp;
3233     char buf[MAX_LINE_SIZE];
3234     char *result = NULL;
3235     int len;
3236     char ip1[IP_BUF_SIZE];
3237     char ip2[IP_BUF_SIZE];
3238 
3239 
3240     if (keyGenCmd == NULL)
3241     {
3242 	message(3, 0, "no key generation command specified");
3243 	return NULL;
3244     }
3245 
3246     /* Add addresses and ports if command end with + */
3247 
3248     len = strlen(keyGenCmd);
3249     if (peerAddrP && targetAddrP &&
3250 	len > 0 && keyGenCmd[len - 1] == '+' &&
3251 	len < (MAX_LINE_SIZE - 40))
3252     {
3253 	ipString(peerAddrP->sin_addr, ip1);
3254 	ipString(targetAddrP->sin_addr, ip2);
3255 	sprintf(buf, "%.*s %s %s %hu", len - 1, keyGenCmd, ip1, ip2, targetPort);
3256     }
3257     else
3258     {
3259 	strcpy(buf, keyGenCmd);
3260     }
3261     message(3, 0, "running key generation command: %s", buf);
3262 
3263     if ((fp = popen(buf, "r")) == NULL)
3264     {
3265 	message(0, errno, "failed to spawn key generation command '%s'", keyGenCmd);
3266 	return NULL;
3267     }
3268 
3269     if (fgets(buf, MAX_LINE_SIZE, fp) != NULL)
3270     {
3271 	if ((result = (char *)malloc(strlen(buf) + 1)) != NULL)
3272 	{
3273 	    if (sscanf(buf, "%[0-9a-fA-F]", result) != 1 ||
3274 		strlen(buf) < (MIN_KEY_BYTES * 2))
3275 	    {
3276 		free(result);
3277 		result = NULL;
3278 	    }
3279 	}
3280     }
3281 
3282     fclose(fp);
3283 
3284     message(3, 0, "key generation result %s", (result ? "not null" : "NULL"));
3285     return result;
3286 }
3287 
3288 /*
3289 ** generateNonce
3290 **
3291 ** Generate a 64-bit nonce value. This is a cut-down version of generateKey.
3292 ** It does not need the same strength of randomness because these are
3293 ** public values.
3294 **
3295 ** See the comments in generateKey for explanations of the various things
3296 ** going on in here.
3297 */
3298 
3299 void
generateNonce(unsigned char * nonce)3300 generateNonce(unsigned char *nonce)
3301 {
3302     SHA_INFO sha;
3303     time_t now = time(NULL);
3304     unsigned long pid = threadPid();
3305     unsigned long tid = threadTid();
3306     int i;
3307 
3308     sha_init(&sha);
3309 
3310     sha_update(&sha, (SHA_BYTE *)&now, sizeof(now));
3311     sha_update(&sha, (SHA_BYTE *)&pid, sizeof(pid));
3312     sha_update(&sha, (SHA_BYTE *)&tid, sizeof(tid));
3313 
3314 #if defined(WIN32)
3315     {
3316 	LARGE_INTEGER perf;
3317 	DWORD ticks = timeGetTime();
3318 	FILETIME created, exited, kernel, user;
3319 
3320 
3321 	sha_update(&sha, (SHA_BYTE *)&ticks, sizeof(ticks));
3322 
3323 	(void)QueryPerformanceCounter(&perf);
3324 	sha_update(&sha, (SHA_BYTE *)&perf, sizeof(perf));
3325 
3326 	GetProcessTimes(GetCurrentProcess(),
3327 			&created, &exited, &kernel, &user);
3328 
3329 	sha_update(&sha, (SHA_BYTE *)&created, sizeof(created));
3330 	sha_update(&sha, (SHA_BYTE *)&exited, sizeof(exited));
3331 	sha_update(&sha, (SHA_BYTE *)&kernel, sizeof(kernel));
3332 	sha_update(&sha, (SHA_BYTE *)&user, sizeof(user));
3333     }
3334 #else	/* !WIN32 */
3335     {
3336 	clock_t ticks;
3337 	struct tms tms;
3338 
3339 	ticks = times(&tms);
3340 
3341 	sha_update(&sha, (SHA_BYTE *)&ticks, sizeof(ticks));
3342 	sha_update(&sha, (SHA_BYTE *)&tms, sizeof(tms));
3343     }
3344 #endif	/* !WIN32 */
3345 
3346     sha_final(&sha);
3347 
3348     for (i = 0; i < NONCE_SIZE; i++)
3349     {
3350 	nonce[i] = (sha.digest[i / 4] >> ((i % 4) * 8)) & 0xff;
3351     }
3352 }
3353 
3354 /*
3355 ** generateSessionKey
3356 **
3357 ** Given the DH-derived secret key string and the client and server
3358 ** nonces generate a unique session key at least "keyBits" bits long.
3359 */
3360 
3361 char *
generateSessionKey(char * secretKey,unsigned char * cNonce,unsigned char * sNonce,unsigned short keyBits)3362 generateSessionKey(char *secretKey, unsigned char *cNonce,
3363 		   unsigned char *sNonce, unsigned short keyBits)
3364 {
3365     SHA_INFO sha;
3366     unsigned short bits = 0;
3367     unsigned short nybbles = 0;
3368     unsigned short len = (unsigned short)strlen(secretKey);
3369     char *result = NULL;
3370 
3371 
3372     for (bits = 0; bits < keyBits; bits += 160)
3373     {
3374 	sha_init(&sha);
3375 	sha_update(&sha, (SHA_BYTE *)cNonce, NONCE_SIZE);
3376 	sha_update(&sha, (SHA_BYTE *)sNonce, NONCE_SIZE);
3377 	nybbles = bits / 4;
3378 	if (nybbles > len)
3379 	{
3380 	    nybbles %= len;
3381 	}
3382 	sha_update(&sha, (SHA_BYTE *)(secretKey + nybbles), (len - nybbles));
3383 	sha_final(&sha);
3384 
3385 	if ((result = (char *)realloc(result, (bits / 160 + 1) * 40 + 1)) == NULL)
3386 	{
3387 	    return NULL;
3388 	}
3389 
3390 	sprintf(result + (bits / 160) * 40,
3391 		"%08lx%08lx%08lx%08lx%08lx",
3392 		(unsigned long)sha.digest[0], (unsigned long)sha.digest[1],
3393 		(unsigned long)sha.digest[2], (unsigned long)sha.digest[3],
3394 		(unsigned long)sha.digest[4]);
3395     }
3396 
3397     return result;
3398 }
3399 
3400 /*
3401 ** hexStrToBits
3402 **
3403 ** This converts the first "bits" bits of hex string "hexStr" to a
3404 ** bit vector in "bitVec", which must be at least MAX_KEY_BYTES bytes
3405 ** long. It returns the number of bytes of bitVec that were set.
3406 **
3407 ** Note that "bits" is effectively rounded up to the nearest multiple
3408 ** of 4.
3409 */
3410 
3411 unsigned short
hexStrToBits(char * hexStr,unsigned short bits,unsigned char * bitVec)3412 hexStrToBits(char *hexStr, unsigned short bits, unsigned char *bitVec)
3413 {
3414     int i;
3415     unsigned char byte;
3416     int len = strlen(hexStr);
3417 
3418 
3419     memset(bitVec, 0, MAX_KEY_BYTES);
3420 
3421     /* Determine number of nybbles required */
3422 
3423     if ((int)((bits + 3) / 4U) < len)
3424     {
3425 	len = (int)((bits + 3) / 4U);
3426     }
3427 
3428     /* Truncate the number of nybbles to fit in the buffer, if necessary */
3429 
3430     if (len > (MAX_KEY_BYTES * 2))
3431     {
3432 	len = MAX_KEY_BYTES * 2;
3433     }
3434 
3435     /* Now process the string a nybble at a time */
3436 
3437     for (i = 0; i < len; i += 2)
3438     {
3439 	byte = '\0';
3440 
3441 	/* High nybble */
3442 
3443 	if (hexStr[i] >= '0' && hexStr[i] <= '9')
3444 	{
3445 	    byte = (hexStr[i] - '0') << 4;
3446 	}
3447 	else if (toupper(hexStr[i]) >= 'A' && toupper(hexStr[i]) <= 'F')
3448 	{
3449 	    byte = (toupper(hexStr[i]) - 'A' + 0xA) << 4;
3450 	}
3451 
3452 	/* Low nybble -- if any, otherwise left as zero */
3453 
3454 	if (i + 1 < len)
3455 	{
3456 	    if (hexStr[i + 1] >= '0' && hexStr[i + 1] <= '9')
3457 	    {
3458 		byte |= (hexStr[i + 1] - '0');
3459 	    }
3460 	    else if (toupper(hexStr[i + 1]) >= 'A' && toupper(hexStr[i + 1]) <= 'F')
3461 	    {
3462 		byte |= (toupper(hexStr[i + 1]) - 'A' + 0xA);
3463 	    }
3464 	}
3465 
3466 	bitVec[i / 2] = byte;
3467     }
3468 
3469     /* Return number of bytes */
3470 
3471     return (unsigned short)(i / 2);
3472 }
3473 
3474 /*
3475 ** diffieHellman
3476 **
3477 ** Perform the core Diffie-Hellman calculation which is
3478 **
3479 **	(generator ** exponent) mod modulus
3480 **
3481 ** This operates on hex strings and returns a newly-allocated hex string
3482 ** as its answer. If genStr or modStr are NULL or empty strings then
3483 ** the default, built-in values will be used.
3484 */
3485 
3486 char *
diffieHellman(char * genStr,char * modStr,char * expStr)3487 diffieHellman(char *genStr, char *modStr, char *expStr)
3488 {
3489     mpz_t gen, mod, exp, key;
3490     char *keyStr = NULL;
3491 
3492 
3493     if (genStr == NULL || *genStr == '\0') genStr = DFLT_GENERATOR;
3494     if (modStr == NULL || *modStr == '\0') modStr = DFLT_MODULUS;
3495 
3496     mpz_init_set_str(gen, genStr, 16);
3497     mpz_init_set_str(mod, modStr, 16);
3498     mpz_init_set_str(exp, expStr, 16);
3499     mpz_init(key);
3500 
3501     mpz_powm(key, gen, exp, mod);
3502 
3503     keyStr = mpz_get_str(NULL, 16, key);
3504 
3505     mpz_clear(gen);
3506     mpz_clear(exp);
3507     mpz_clear(mod);
3508     mpz_clear(key);
3509 
3510     return keyStr;
3511 }
3512 
3513 /*
3514 ** makeChallenge
3515 **
3516 ** Create a challenge value and write it into "challenge", which
3517 ** must be CHALLENGE_SIZE bytes long. We will just use clock ticks.
3518 */
3519 
3520 void
makeChallenge(unsigned char * challenge)3521 makeChallenge(unsigned char *challenge)
3522 {
3523 #ifdef WIN32
3524     DWORD ticks = timeGetTime();
3525     memcpy(challenge, &ticks, CHALLENGE_SIZE);
3526 #else
3527     struct tms tms;
3528     clock_t ticks = times(&tms);
3529     memcpy(challenge, &ticks, CHALLENGE_SIZE);
3530 #endif
3531 }
3532 
3533 /*
3534 ** challengeAnswer
3535 **
3536 ** Calculate the answer to the challenge. XOR each byte with THE_ANSWER.
3537 */
3538 
3539 void
challengeAnswer(unsigned char * challenge)3540 challengeAnswer(unsigned char *challenge)
3541 {
3542     int i;
3543 
3544     for (i = 0; i < CHALLENGE_SIZE; i++)
3545     {
3546 	challenge[i] ^= THE_ANSWER;
3547     }
3548 }
3549 
3550 /*
3551 ** clientPerformChallenge
3552 **
3553 ** This the client side of the challenge-response dialogue used to establish
3554 ** that both client and server really do know the shared secret key and
3555 ** guard against replay attacks.
3556 **
3557 ** It returns 1 if the dialogue is successfully completed and 0 otherwise.
3558 */
3559 
3560 int
clientPerformChallenge(int serverFd,MsgBuf_t * msg)3561 clientPerformChallenge(int serverFd, MsgBuf_t *msg)
3562 {
3563     unsigned char challenge[CHALLENGE_SIZE];
3564     unsigned char myChallenge[CHALLENGE_SIZE];
3565 
3566 
3567     /* Read encrypted challenge string from the server */
3568 
3569     message(3, 0, "reading challenge from server");
3570 
3571     if (readMessage(serverFd, msg, CHALLENGE_SIZE) <= 0)
3572     {
3573 	message(0, errno, "failed to read challenge from server");
3574 	return 0;
3575     }
3576     getMsgBuf(msg, challenge, CHALLENGE_SIZE);
3577 
3578     message(3, 0, "read challenge");
3579 
3580     /* Calculate the answer and then send that back to the server */
3581 
3582     challengeAnswer(challenge);
3583 
3584     message(3, 0, "writing challenge response");
3585 
3586     setMsgBuf(msg, challenge, CHALLENGE_SIZE);
3587     if (writeMessage(serverFd, msg) != CHALLENGE_SIZE)
3588     {
3589 	message(0, errno, "failed writing challenge response to server");
3590 	return 0;
3591     }
3592     message(3, 0, "wrote challenge response");
3593 
3594     /* Now generate our own challenge value and send it to the server */
3595 
3596     makeChallenge(myChallenge);
3597 
3598     message(3, 0, "sending challenge to server");
3599 
3600     setMsgBuf(msg, myChallenge, CHALLENGE_SIZE);
3601     if (writeMessage(serverFd, msg) != CHALLENGE_SIZE)
3602     {
3603 	message(0, errno, "failed writing challenge to server");
3604 	return 0;
3605     }
3606     message(3, 0, "wrote challenge");
3607 
3608     message(3, 0, "reading challenge response from server");
3609 
3610     if (readMessage(serverFd, msg, CHALLENGE_SIZE) <= 0)
3611     {
3612 	message(0, errno, "failed to read challenge response from server");
3613 	return 0;
3614     }
3615     getMsgBuf(msg, challenge, CHALLENGE_SIZE);
3616 
3617     message(3, 0, "read challenge response");
3618 
3619     /* Calculate the expected answer and then compare with the response */
3620 
3621     challengeAnswer(myChallenge);
3622 
3623     if (memcmp(challenge, myChallenge, CHALLENGE_SIZE) != 0)
3624     {
3625 	message(0, 0, "server responded incorrectly to challenge");
3626 	return 0;
3627     }
3628 
3629     memset(challenge, 0, CHALLENGE_SIZE);
3630     memset(myChallenge, 0, CHALLENGE_SIZE);
3631 
3632     return 1;
3633 }
3634 
3635 /*
3636 ** serverPerformChallenge
3637 **
3638 ** This the server side of the challenge-response dialogue used to establish
3639 ** that both client and server really do know the shared secret key and
3640 ** guard against replay attacks.
3641 **
3642 ** It returns 1 if the dialogue is successfully completed and 0 otherwise.
3643 */
3644 
3645 int
serverPerformChallenge(int clientFd,MsgBuf_t * msg)3646 serverPerformChallenge(int clientFd, MsgBuf_t *msg)
3647 {
3648     unsigned char challenge[CHALLENGE_SIZE];
3649     unsigned char myChallenge[CHALLENGE_SIZE];
3650 
3651 
3652     /* Generate our own challenge value */
3653 
3654     makeChallenge(myChallenge);
3655 
3656     message(3, 0, "sending challenge to client");
3657 
3658     setMsgBuf(msg, myChallenge, CHALLENGE_SIZE);
3659     if (writeMessage(clientFd, msg) != CHALLENGE_SIZE)
3660     {
3661 	message(0, errno, "failed writing challenge to client");
3662 	return 0;
3663     }
3664     message(3, 0, "wrote challenge");
3665 
3666     message(3, 0, "reading challenge response from client");
3667 
3668     if (readMessage(clientFd, msg, CHALLENGE_SIZE) <= 0)
3669     {
3670 	message(0, errno, "failed to read challenge response from client");
3671 	return 0;
3672     }
3673     getMsgBuf(msg, challenge, CHALLENGE_SIZE);
3674 
3675     message(3, 0, "read challenge response");
3676 
3677     /* Calculate the expected answer and then compare with the response */
3678 
3679     challengeAnswer(myChallenge);
3680 
3681     if (memcmp(challenge, myChallenge, CHALLENGE_SIZE) != 0)
3682     {
3683 	message(0, 0, "client responded incorrectly to challenge");
3684 	return 0;
3685     }
3686 
3687     /* Now read challenge from the client */
3688 
3689     message(3, 0, "reading challenge from client");
3690 
3691     if (readMessage(clientFd, msg, CHALLENGE_SIZE) <= 0)
3692     {
3693 	message(0, errno, "failed to read challenge from client");
3694 	return 0;
3695     }
3696     getMsgBuf(msg, challenge, CHALLENGE_SIZE);
3697 
3698     message(3, 0, "read challenge");
3699 
3700     /* Calculate the answer and then send that back to the client */
3701 
3702     challengeAnswer(challenge);
3703 
3704     message(3, 0, "writing challenge response");
3705 
3706     setMsgBuf(msg, challenge, CHALLENGE_SIZE);
3707     if (writeMessage(clientFd, msg) != CHALLENGE_SIZE)
3708     {
3709 	message(0, errno, "failed writing challenge response to client");
3710 	return 0;
3711     }
3712     message(3, 0, "wrote challenge response");
3713     memset(challenge, 0, CHALLENGE_SIZE);
3714 
3715     return 1;
3716 }
3717 
3718 /************************************\
3719 **				    **
3720 **  Reuseable session key routines  **
3721 **				    **
3722 \************************************/
3723 
3724 /*
3725 ** freeKeyInfo
3726 **
3727 ** Free the storage associated with a KeyInfo_t element.
3728 */
3729 
3730 void
freeKeyInfo(KeyInfo_t * info)3731 freeKeyInfo(KeyInfo_t *info)
3732 {
3733     if (info->key)
3734     {
3735 	memset(info->key, 0, strlen(info->key));
3736 	free(info->key);
3737     }
3738     free(info);
3739 }
3740 
3741 /*
3742 ** findKeyByToken
3743 **
3744 ** Given a token value, search the specified list for a matching value
3745 ** and return the key string associated with it, or NULL if not found.
3746 ** The key is returned in newly-allocated storage which must be freed
3747 ** by the caller.
3748 **
3749 ** As a side effect this also checks the expiry time of each entry an
3750 ** purges expired entries from the list. Note that the head of the list
3751 ** is always a static entry (with ptr->expiry zero). This makes the list
3752 ** manipulation easier.
3753 **
3754 ** If a static shared key or key generation command has been specified
3755 ** then this will be used and the value returned regardless of token
3756 ** value specified.
3757 */
3758 
3759 char *
findKeyByToken(KeyInfo_t * list,unsigned long token,struct sockaddr_in * peerAddrP,struct sockaddr_in * targetAddrP,unsigned short targetPort)3760 findKeyByToken(KeyInfo_t *list,
3761 	       unsigned long token,
3762 	       struct sockaddr_in *peerAddrP,
3763 	       struct sockaddr_in *targetAddrP,
3764 	       unsigned short targetPort)
3765 {
3766     KeyInfo_t *ptr = NULL;
3767     char *found = NULL;
3768     KeyInfo_t *tmp = NULL;
3769     time_t now;
3770     char *result = NULL;
3771 
3772 
3773     /* If a shared private key has been supplied copy it and return it */
3774 
3775     if (SharedKey)
3776     {
3777 	if ((result = (char *)malloc(strlen(SharedKey) + 1)) == NULL)
3778 	{
3779 	    return NULL;
3780 	}
3781 	strcpy(result, SharedKey);
3782 	return result;
3783     }
3784 
3785     /*
3786     ** If a key generator command was specified then use this to generate
3787     ** the key rather than doing it directly here.
3788     */
3789 
3790     if (SharedKeyGenCmd && (result = runKeyGenCommand(SharedKeyGenCmd, peerAddrP, targetAddrP, targetPort)) != NULL)
3791     {
3792 	return result;
3793     }
3794 
3795     if (token == 0 || token == TOKEN_NEW) return NULL;
3796 
3797     time(&now);
3798 
3799     mutexLock(MUTEX_KEYLIST);
3800 
3801     for (ptr = list; ptr; ptr = ptr->next)
3802     {
3803 	/* Check if the entry has expired */
3804 
3805 	if (ptr->expiry && now > ptr->expiry)
3806 	{
3807 	    /* It has, so remove it! */
3808 
3809 	    ptr->prev->next = ptr->next;
3810 	    if (ptr->next)
3811 	    {
3812 		ptr->next->prev = ptr->prev;
3813 	    }
3814 	    tmp = ptr;
3815 	    ptr = ptr->prev;
3816 	    freeKeyInfo(tmp);
3817 	}
3818 	else if (!found && ptr->token == token)
3819 	{
3820 	    /* We have a matching element, copy the key to return */
3821 
3822 	    if ((found = (char *)malloc(strlen(ptr->key) + 1)) == NULL)
3823 	    {
3824 		message(0, errno, "Out of memory allocating copy of key");
3825 	    }
3826 	    else
3827 	    {
3828 		strcpy(found, ptr->key);
3829 	    }
3830 
3831 	    /* Carry on with the loop to purge expired entries */
3832 	}
3833     }
3834 
3835     mutexUnlock(MUTEX_KEYLIST);
3836 
3837     return found;
3838 }
3839 
3840 /*
3841 ** addKeyInfoToList
3842 **
3843 ** This adds a new entry to the end of the specified list with the
3844 ** given token and key values. The entry will expire in a number of
3845 ** seconds given by the KeyLifetime global variable.
3846 */
3847 
3848 void
addKeyInfoToList(KeyInfo_t * list,unsigned long token,char * key)3849 addKeyInfoToList(KeyInfo_t *list, unsigned long token, char *key)
3850 {
3851     KeyInfo_t *new = NULL;
3852     KeyInfo_t *ptr = NULL;
3853 
3854 
3855     mutexLock(MUTEX_KEYLIST);
3856 
3857     if ((new = (KeyInfo_t *)malloc(sizeof(KeyInfo_t))) == NULL ||
3858 	(new->key = (char *)malloc(strlen(key) + 1)) == NULL)
3859     {
3860 	message(0, errno, "Out of memory allocating key info element");
3861     }
3862     else
3863     {
3864 	strcpy(new->key, key);
3865 	new->token = token;
3866 	new->next = NULL;
3867 	time(&(new->expiry));
3868 	new->expiry += KeyLifetime;
3869 
3870 	for (ptr = list; ptr->next; ptr = ptr->next) /* move on ... */;
3871 
3872 	ptr->next = new;
3873 	new->prev = ptr;
3874     }
3875 
3876     mutexUnlock(MUTEX_KEYLIST);
3877 }
3878 
3879 /*
3880 ** generateToken
3881 **
3882 ** This routine generates a new token value. It will explicitly avoid
3883 ** generating the same value as oldToken.
3884 */
3885 
3886 unsigned long
generateToken(KeyInfo_t * list,unsigned long oldToken)3887 generateToken(KeyInfo_t *list, unsigned long oldToken)
3888 {
3889     static unsigned long nextToken = 0;
3890     unsigned long token = 0;
3891     char *key = NULL;
3892 
3893 
3894     if (KeyLifetime == 0) return 0;
3895 
3896     mutexLock(MUTEX_TOKEN);
3897 
3898     /* First time, set new random seed and generate first token */
3899 
3900     if (nextToken == 0)
3901     {
3902 	srand((int)threadPid() + (int)time(NULL));
3903 	nextToken = (unsigned long)((rand() & 0xffff) << 16);
3904 	nextToken |= (unsigned long)(rand() & 0xffff);
3905     }
3906 
3907     while (token == 0)
3908     {
3909 	nextToken = (nextToken + 1) & 0xffffffff;   /* Cope with 64-bit! */
3910 
3911 	/* Avoid special values */
3912 
3913 	if (nextToken == 0 || nextToken == TOKEN_NEW || nextToken == oldToken)
3914 	{
3915 	    continue;
3916 	}
3917 
3918 	/*
3919 	** Screen out ones we already have. Note that peer and target
3920 	** information is NULL because if we are in generateToken
3921 	** they can't have been used by any shared key generation
3922 	** command.
3923 	*/
3924 
3925 	if ((key = findKeyByToken(list, nextToken, NULL, NULL, 0)) != NULL)
3926 	{
3927 	    free(key);
3928 	    continue;
3929 	}
3930 
3931 	/* We've got one! */
3932 
3933 	token = nextToken;
3934     }
3935 
3936     mutexUnlock(MUTEX_TOKEN);
3937 
3938     return token;
3939 }
3940 
3941 /*
3942 ** getCurrentToken
3943 **
3944 ** Validate CurrentToken and return it. If it will expire within
3945 ** TOKEN_EXPIRE_GRACE seconds then return TOKEN_NEW.
3946 */
3947 
3948 unsigned long
getCurrentToken(void)3949 getCurrentToken(void)
3950 {
3951     KeyInfo_t *ptr = NULL;
3952     time_t now;
3953 
3954     if (CurrentToken == 0 || CurrentToken == TOKEN_NEW) return CurrentToken;
3955 
3956     time(&now);
3957 
3958     mutexLock(MUTEX_KEYLIST);
3959 
3960     for (ptr = &ClientKeyList; ptr; ptr = ptr->next)
3961     {
3962 	if (ptr->token == CurrentToken)
3963 	{
3964 	    /* Check if the entry has expired or will do soon */
3965 
3966 	    if (ptr->expiry && now > (ptr->expiry - TOKEN_EXPIRE_GRACE))
3967 	    {
3968 		CurrentToken = TOKEN_NEW;
3969 	    }
3970 	    break;
3971 	}
3972     }
3973 
3974     mutexUnlock(MUTEX_KEYLIST);
3975 
3976     return CurrentToken;
3977 }
3978 
3979 /*****************************\
3980 **			     **
3981 **  General Helper Routines  **
3982 **			     **
3983 \*****************************/
3984 
3985 /*
3986 ** spawnCommand
3987 **
3988 ** Start a sub-process running the specified command using the default
3989 ** shell. The command string may contain a single "%d" format character
3990 ** which will be replaced with the local port number.
3991 */
3992 
3993 int
spawnCommand(unsigned short port,char * cmdFormat)3994 spawnCommand(unsigned short port, char *cmdFormat)
3995 {
3996 #ifdef WIN32
3997     char cmdBuf[MAX_LINE_SIZE];
3998     STARTUPINFO	suInfo;
3999     PROCESS_INFORMATION pInfo;
4000 
4001     snprintf(cmdBuf, sizeof(cmdBuf), cmdFormat, (int)port);
4002 
4003     memset(&suInfo, 0, sizeof(suInfo));
4004     suInfo.cb = sizeof(suInfo);
4005 
4006 
4007     if (!CreateProcess(NULL,	/* No executable -- take it from cmdBuf */
4008 		       cmdBuf,	/* Command and arguments */
4009 		       NULL,	/* No security attributes */
4010 		       NULL,	/* No thread attributes */
4011 		       FALSE,	/* Don't inherit handles */
4012 		       0,	/* No special creation flags */
4013 		       NULL,	/* Inherit environment */
4014 		       NULL,	/* Inherit current directory */
4015 		       &suInfo,	/* Start-up info */
4016 		       &pInfo))	/* Process info needed */
4017     {
4018 	message(0, errno, "failed to spawn '%s'", cmdBuf);
4019 	return 0;
4020     }
4021 #else
4022     char *shell = DFLT_SHELL;
4023     char cmdBuf[MAX_LINE_SIZE];
4024 
4025     snprintf(cmdBuf, sizeof(cmdBuf), cmdFormat, (int)port);
4026 
4027     if (((shell = getenv("SHELL")) == NULL) || *shell == '\0')
4028     {
4029 	shell = DFLT_SHELL;
4030     }
4031 
4032     switch (fork())
4033     {
4034     case -1:
4035 	message(0, errno, "fork failed");
4036 	return 0;
4037 	break;
4038 
4039     case 0:
4040 	execl(shell, shell, "-c", cmdBuf, NULL);
4041 	message(0, errno, "failed to exec '%s -c \"%s\"'", shell, cmdBuf);
4042 	break;
4043 
4044     default:
4045 	break;
4046     }
4047 #endif
4048 
4049     return 1;
4050 }
4051 
4052 /*
4053 ** filterLoop
4054 **
4055 ** This is the main processing loop of both client and server. It loops
4056 ** reading data from the local system, encrypts and compresses it and
4057 ** sends it to the remote system. Conversely it reads data from the remote
4058 ** system, decrypts and uncompresses it and writes it to the local system.
4059 **
4060 ** On a normal EOF (on either end) it returns 0, on a remote comms failure
4061 ** 1 and a local failure -1.
4062 **
4063 ** In UDP mode replies are sent back to the address specified by toAddrP using
4064 ** the socket named in replyFd. The fromAddrP is used only if UDP source
4065 ** address spoofing is being used.
4066 **
4067 ** The select will timeout (and the connection be closed) after TcpTimeout
4068 ** or UdpTimeout seconds, as applicable.
4069 */
4070 
4071 int
filterLoop(int localFd,int remoteFd,MsgBuf_t * msgBuf,struct sockaddr_in * toAddrP,struct sockaddr_in * fromAddrP,int replyFd,int udpMode)4072 filterLoop(int localFd, int remoteFd, MsgBuf_t *msgBuf,
4073 	   struct sockaddr_in *toAddrP, struct sockaddr_in *fromAddrP,
4074 	   int replyFd, int udpMode)
4075 {
4076     fd_set testSet;
4077     int ready = 0;
4078     int maxTestFd = (localFd > remoteFd ? (localFd + 1) : (remoteFd + 1));
4079     int num = 0;
4080     int status = 0;
4081     struct timeval delay;
4082 
4083 
4084     do
4085     {
4086 	/* Set up the delay for select */
4087 
4088 	delay.tv_sec = (udpMode ? UdpTimeout : TcpTimeout);
4089 	delay.tv_usec = 0;
4090 
4091 	/* Set up file descriptors in mask to test */
4092 
4093 	FD_ZERO(&testSet);
4094 	if (localFd >= 0)
4095 	{
4096 	    FD_SET(localFd, &testSet);
4097 	}
4098 	if (remoteFd >= 0)
4099 	{
4100 	    FD_SET(remoteFd, &testSet);
4101 	}
4102 
4103 	/* Do a blocking select waiting for any i/o */
4104 
4105 	ready = select(maxTestFd, &testSet, 0, 0, (delay.tv_sec ? &delay : NULL));
4106 
4107 	/*
4108 	** If we get zero then there is nothing left on either fd
4109 	** or we hit the timeout.
4110 	*/
4111 
4112 	if (ready == 0)
4113 	{
4114 	    break;
4115 	}
4116 
4117 	/* Check for error but ignore interrupted system calls */
4118 
4119 	if (ready < 0 && errno != EINTR)
4120 	{
4121 	    message(0, errno, "error in select");
4122 	    status = -1;
4123 	    break;
4124 	}
4125 
4126 	/* Is there local data ready? */
4127 
4128 	if (FD_ISSET(localFd, &testSet))
4129 	{
4130 		if ((num = recv(localFd, (char *)msgBuf->data, msgBuf->maxSize, 0)) > 0)
4131 	    {
4132 		message(5, 0, "read %d bytes from local socket %d", num, localFd);
4133 
4134 		msgBuf->size = (unsigned short)num;
4135 		if (DumpData) dumpData("<", msgBuf->data, msgBuf->size);
4136 
4137 		if (writeMessage(remoteFd, msgBuf) != num)
4138 		{
4139 		    status = 1;
4140 		    break;
4141 		}
4142 	    }
4143 	    else
4144 	    {
4145 		status = (num == 0 ? 0 : -1);
4146 		break;
4147 	    }
4148 	}
4149 
4150 	/* Is there remote data ready? */
4151 
4152 	if (FD_ISSET(remoteFd, &testSet))
4153 	{
4154 	    /* Read the encrypted/compressed message and write to local socket */
4155 
4156 	    num = readMessage(remoteFd, msgBuf, 0);
4157 	    if (num > 0)
4158 	    {
4159 		if (udpMode)
4160 		{
4161 #ifdef USE_UDP_SPOOFING
4162 		    if (Transparent)
4163 		    {
4164 			num = sendSpoofed(replyFd, (char *)(msgBuf->data),
4165 					  msgBuf->size, toAddrP, fromAddrP);
4166 		    }
4167 		    else
4168 #endif
4169 		    {
4170 			num = sendto(replyFd, (char *)(msgBuf->data), msgBuf->size,
4171 				     0, (struct sockaddr *)toAddrP,
4172 				     sizeof(struct sockaddr_in));
4173 		    }
4174 		}
4175 		else
4176 		{
4177 		    num = writeData(localFd, (unsigned char *)(msgBuf->data),
4178 				    msgBuf->size);
4179 		}
4180 		if (num != msgBuf->size)
4181 		{
4182 		    status = -1;
4183 		    break;
4184 		}
4185 		message(5, 0, "sent %d bytes to %s socket %d", num,
4186                         (udpMode ? "reply" : "local"),
4187                         (udpMode ? replyFd : localFd));
4188 		if (DumpData) dumpData(">", msgBuf->data, msgBuf->size);
4189 	    }
4190 	    else
4191 	    {
4192 		status = (num == 0 ? 0 : 1);
4193 		break;
4194 	    }
4195 	}
4196     }
4197     while (1);
4198 
4199     message(3, 0, "connection closed or timed out");
4200 
4201     message(2, 0, "read %lu bytes (%lu expanded) in %lu messages",
4202 	    msgBuf->bytesIn, msgBuf->expBytesIn, msgBuf->readCount);
4203     message(2, 0, "wrote %lu bytes (%lu expanded) in %lu messages",
4204 	    msgBuf->bytesOut, msgBuf->expBytesOut, msgBuf->writeCount);
4205 
4206     return status;
4207 }
4208 
4209 /*
4210 ** hashStrings
4211 **
4212 ** Hash the supplied string arguments (up to a NULL pointer) together and
4213 ** write the resulting hash string into hashBuf.
4214 */
4215 
4216 void
hashStrings(char * hashBuf,...)4217 hashStrings(char *hashBuf, ...)
4218 {
4219     SHA_INFO sha;
4220     va_list ap;
4221     char *str;
4222 
4223     sha_init(&sha);
4224     va_start(ap, hashBuf);
4225     while ((str = va_arg(ap, char *)) != NULL)
4226     {
4227 	sha_update(&sha, (SHA_BYTE *)str, strlen(str));
4228     }
4229     sha_final(&sha);
4230     sprintf(hashBuf, "%08lx%08lx%08lx%08lx%08lx",
4231 	    (unsigned long)sha.digest[0], (unsigned long)sha.digest[1],
4232 	    (unsigned long)sha.digest[2], (unsigned long)sha.digest[3],
4233 	    (unsigned long)sha.digest[4]);
4234 }
4235 
4236 /*
4237 ** hashFile
4238 **
4239 ** Hash the contents of the specified file, read in binary mode in
4240 ** chunks of up to MAX_BUF_SIZE bytes. Write the result into hashBuf.
4241 */
4242 
4243 void
hashFile(char * hashBuf,char * fileName)4244 hashFile(char *hashBuf, char *fileName)
4245 {
4246     SHA_INFO sha;
4247     FILE *fp = NULL;
4248     unsigned char buf[MAX_BUF_SIZE];
4249     size_t num;
4250 
4251 
4252     if (strcmp(fileName, "-") == 0)
4253     {
4254 	fp = stdin;
4255 #if defined(WIN32) || defined(__CYGWIN__)
4256 	setmode(0, O_BINARY);
4257 #endif
4258     }
4259     else if ((fp = fopen(fileName, "rb")) == NULL)
4260     {
4261 	message(0, errno, "can't open '%s'", fileName);
4262 	return;
4263     }
4264 
4265     sha_init(&sha);
4266 
4267     while ((num = fread(buf, 1, MAX_BUF_SIZE, fp)) > 0)
4268     {
4269 	sha_update(&sha, (SHA_BYTE *)buf, num);
4270     }
4271 
4272     fclose(fp);
4273 
4274     sha_final(&sha);
4275     sprintf(hashBuf, "%08lx%08lx%08lx%08lx%08lx",
4276 	    (unsigned long)sha.digest[0], (unsigned long)sha.digest[1],
4277 	    (unsigned long)sha.digest[2], (unsigned long)sha.digest[3],
4278 	    (unsigned long)sha.digest[4]);
4279 }
4280 
4281 /*
4282 ** checkIdentity
4283 **
4284 ** Check the supplied public key string against an "identity file". This
4285 ** file contains lines that consist of the SHA hash of the (generator,
4286 ** modulus, public-key) tuple followed by some optional commentary text.
4287 ** The hash value must begin the line and not contain any white-space.
4288 */
4289 
4290 int
checkIdentity(char * idFile,char * generator,char * modulus,char * key)4291 checkIdentity(char *idFile, char *generator, char *modulus, char *key)
4292 {
4293     FILE *fp;
4294     char keySig[HASH_STR_SIZE];
4295     char checkSig[MAX_LINE_SIZE];
4296     char line[MAX_LINE_SIZE];
4297     int found = 0;
4298     int len = 0;
4299 
4300 
4301     if ((fp = fopen(idFile, "r")) == NULL)
4302     {
4303 	message(0, errno, "can't open identity file '%s'", idFile);
4304 	return 0;
4305     }
4306 
4307     if (*generator == '\0') generator = DFLT_GENERATOR;
4308     if (*modulus == '\0') modulus = DFLT_MODULUS;
4309 
4310     hashStrings(keySig, generator, modulus, key, NULL);
4311     len = strlen(keySig);
4312 
4313     message(3, 0, "checking key with identity hash '%s'", keySig);
4314 
4315     while (fgets(line, MAX_LINE_SIZE, fp) != NULL)
4316     {
4317 	if (sscanf(line, "%s", checkSig) != 1)
4318 	{
4319 	    continue;
4320 	}
4321 
4322 	if (strcasecmp(checkSig, keySig) == 0)
4323 	{
4324 	    message(1, 0, "key identity matched: %.*s", strlen(line) - 1, line);
4325 	    found = 1;
4326 	    break;
4327 	}
4328     }
4329 
4330     fclose(fp);
4331 
4332     return found;
4333 }
4334 
4335 /*
4336 ** generateIdentity
4337 **
4338 ** Given a generator, modulus and private key (exponent) generate
4339 ** the hash of the public key string -- the identity used by the
4340 ** checkIdentity routine. This is the hash of the (generator,
4341 ** modulus, public-key) tuple.
4342 */
4343 
4344 char *
generateIdentity(char * generator,char * modulus,char * exponent)4345 generateIdentity(char *generator, char *modulus, char *exponent)
4346 {
4347     char *dhKey = diffieHellman(generator, modulus, exponent);
4348     static char buffer[HASH_STR_SIZE];
4349 
4350     if (*generator == '\0') generator = DFLT_GENERATOR;
4351     if (*modulus == '\0') modulus = DFLT_MODULUS;
4352 
4353     hashStrings(buffer, generator, modulus, dhKey, NULL);
4354     free(dhKey);
4355 
4356     return buffer;
4357 }
4358 
4359 /*
4360 ** prepareToDetach
4361 **
4362 ** This routine is necessary only on systems which have problems in
4363 ** calling "makeDetached". FreeBSD is one such system because of a
4364 ** bad interaction between fork and running threads.
4365 */
4366 
4367 void
prepareToDetach(void)4368 prepareToDetach(void)
4369 {
4370 #if defined(HAVE_PTHREADS) && defined (BUGGY_FORK_WITH_THREADS)
4371     pid_t pid;
4372     int status = 0;
4373 
4374 
4375     /* Fork now -- child returns immediately, parent carries on here */
4376 
4377     if ((pid = fork()) == 0) return;
4378 
4379     /*
4380     ** The parent now waits for the child or to be sent the SIGUSR1
4381     ** signal. This indicates that the parent should just exit and
4382     ** leave the child detached.
4383     */
4384 
4385     fclose(stdin);
4386     fclose(stdout);
4387     fclose(stderr);
4388 
4389     signal(SIGUSR1, sigusr1Catcher);
4390     waitpid(pid, &status, 0);
4391 
4392     exit(status);
4393 #endif
4394 }
4395 
4396 /*
4397 ** makeDetached
4398 **
4399 ** Detach the current process from its controlling terminal and run
4400 ** in the background. On UNIX this means running as a daemon. On Windows
4401 ** this can not completely detach from a parent process that is waiting
4402 ** for it but can free itself from the console. To get the full
4403 ** effect of a UNIX daemon you should probably also run this as a
4404 ** service (see the -S option).
4405 */
4406 
4407 void
makeDetached(void)4408 makeDetached(void)
4409 {
4410     fflush(stdin);
4411     fflush(stdout);
4412     fflush(stderr);
4413 
4414 #ifdef WIN32
4415     /* Detach from the console */
4416 
4417     if (!FreeConsole())
4418     {
4419 	message(0, errno, "failed to detach from console (Win32 error = %ld)", GetLastError());
4420     }
4421 #elif defined(HAVE_PTHREADS) && defined(BUGGY_FORK_WITH_THREADS)
4422 
4423     /*
4424     ** This is necessary if threads and fork interact badly. See the
4425     ** function prepareToDetach for the other part of this story ...
4426     **
4427     ** Send a signal telling the parent to exit.
4428     */
4429 
4430     kill(getppid(), SIGUSR1);
4431 
4432     /* Detach from controlling terminal */
4433 
4434     setsid();
4435 #else
4436     /* Convert to a daemon */
4437 
4438     switch (fork())
4439     {
4440     case -1:
4441 	/* Error! */
4442 	message(0, errno, "fork failed becoming daemon");
4443 	return;
4444 
4445     case 0:
4446 	/* Child -- continue */
4447 	break;
4448 
4449     default:
4450 	/* Parent -- exit and leave child running */
4451 	exit(EXIT_SUCCESS);
4452 	break;
4453     }
4454 
4455     /* Detach from controlling terminal */
4456 
4457     setsid();
4458 #endif
4459 
4460     /*
4461     ** Close stdio streams because they now have nowhere to go!
4462     ** Note that we would close them on Windows is ... except that
4463     ** doing so causes detaching when the server is running in reverse
4464     ** mode to fail. This seems to be some interaction between a socket
4465     ** connection being made in the same thread that calls makeDetached.
4466     ** Bizarre, but that's Windows for you ...
4467     */
4468 #ifndef WIN32
4469     fclose(stdin);
4470     fclose(stdout);
4471     fclose(stderr);
4472 #endif
4473 
4474     /* Set IsDetached to -1 to indicate that we have now detached */
4475 
4476     IsDetached = -1;
4477 }
4478 
4479 /*
4480 ** allowRedirect
4481 **
4482 ** Decide whether redirection to the specified port at the specified
4483 ** address is allowed or not. The udpMode indicates whether this is a
4484 ** TCP or UDP mode connection.
4485 **
4486 ** Returns 1 if it is or 0 otherwise.
4487 **
4488 ** The target hostname is returned via hostP (this storage must be
4489 ** later freed by the caller). The associated identity file, if any
4490 ** is returned via idFileP.
4491 */
4492 
4493 int
allowRedirect(unsigned short port,struct sockaddr_in * addrP,struct sockaddr_in * peerAddrP,int udpMode,char ** hostP,char ** idFileP)4494 allowRedirect(unsigned short port, struct sockaddr_in *addrP,
4495 	      struct sockaddr_in *peerAddrP, int udpMode,
4496 	      char **hostP, char **idFileP)
4497 {
4498     EndPtList_t *lp1, *lp2;
4499     struct in_addr *alp = NULL;
4500     unsigned long mask = 0;
4501     char *ipName = NULL;
4502 
4503 
4504     assert(AllowedTargets != NULL && addrP != NULL && peerAddrP != NULL);
4505 
4506     /*
4507     ** Port 0 is invalid data in the request packet, never allowed
4508     */
4509     if (port == 0)
4510     {
4511         message(0, 0, "request for target port 0 disallowed");
4512         return 0;
4513     }
4514 
4515     *hostP = NULL;
4516     *idFileP = NULL;
4517 
4518     /*
4519     ** If the address is all zeroes then we will assume the default target
4520     ** host, if any.
4521     */
4522 
4523     if (addrP->sin_addr.s_addr == 0x00000000)
4524     {
4525 	if (!getHostAddress(TargetHost, addrP, NULL, NULL))
4526 	{
4527 	    message(0, 0, "can't resolve host or address '%s'", TargetHost);
4528 	    return 0;
4529 	}
4530     }
4531 
4532     /*
4533     ** The peer address should be looked up by the calling function.
4534     ** It must be available before this check can be made!
4535     */
4536 
4537     if (peerAddrP->sin_addr.s_addr == 0x00000000)
4538     {
4539 	message(0, 0, "client peer address not available");
4540 	return 0;
4541     }
4542 
4543     /* Allocate and fill buffer for returned host IP address string */
4544 
4545     if ((ipName = (char *)malloc(IP_BUF_SIZE)) == NULL)
4546     {
4547 	message(0, errno, "out of memory allocating hostname");
4548 	return 0;
4549     }
4550     *hostP = ipString(addrP->sin_addr, ipName);
4551 
4552     /*
4553     ** Search the AllowedTargets list to determine whether the port lies
4554     ** within any of the permitted ranges for the specified host.
4555     */
4556 
4557     for (lp1 = AllowedTargets; lp1; lp1 = lp1->next)
4558     {
4559 	mask = lp1->mask;
4560 
4561 	if ((addrP->sin_addr.s_addr & mask) != (lp1->addr.sin_addr.s_addr & mask))
4562 	{
4563 	    /* Did not match primary address, check aliases */
4564 
4565 	    for (alp = lp1->addrList; alp->s_addr != 0xffffffff; alp++)
4566 	    {
4567 		if ((addrP->sin_addr.s_addr & mask) == (alp->s_addr & mask))
4568 		{
4569 		    /* Found a matching address in the aliases */
4570 
4571 		    break;
4572 		}
4573 	    }
4574 
4575 	    if (alp->s_addr == 0xffffffff)
4576 	    {
4577 		/* Did not match at all, try next entry */
4578 
4579 		continue;
4580 	    }
4581 	}
4582 
4583 	if (lp1->peer != NULL)
4584 	{
4585 	    message(4, 0, "checking peer address restrictions for target %s:%hu-%hu", lp1->host, lp1->lo, lp1->hi);
4586 	    if (!checkPeerAddress(peerAddrP, lp1->peer))
4587 	    {
4588 		message(4, 0, "peer address disallowed");
4589 		continue;
4590 	    }
4591 	}
4592 	else
4593 	{
4594 	    message(4, 0, "no peer address restrictions for target %s:%hu-%hu", lp1->host, lp1->lo, lp1->hi);
4595 	}
4596 
4597 	message(4, 0, "checking port %hu against range %hu-%hu for host %s", port, lp1->lo, lp1->hi, lp1->host);
4598 
4599 	/* If the port range is 0 -- 0 then look in the default list */
4600 
4601 	if (lp1->lo == 0 && lp1->hi == 0)
4602 	{
4603 	    if (AllowedDefault == NULL)
4604 	    {
4605 		message(4, 0, "no default port restrictions, port is allowed");
4606 		*idFileP = lp1->idFile;
4607 		return 1;
4608 	    }
4609 
4610 	    for (lp2 = AllowedDefault; lp2; lp2 = lp2->next)
4611 	    {
4612 		message(4, 0, "checking port %hu against default range %hu - %hu", port, lp2->lo, lp2->hi);
4613 
4614 		if (port >= lp2->lo && port <= lp2->hi)
4615 		{
4616 		    if (lp2->type & (udpMode ? ENDPTLIST_UDP : ENDPTLIST_TCP))
4617 		    {
4618 			*idFileP = lp1->idFile;
4619 			return 1;
4620 		    }
4621 		}
4622 	    }
4623 	}
4624 
4625 	/* Otherwise check against the entry for this specific host */
4626 
4627 	else if (port >= lp1->lo && port <= lp1->hi)
4628 	{
4629 	    if (lp1->type & (udpMode ? ENDPTLIST_UDP : ENDPTLIST_TCP))
4630 	    {
4631 		*idFileP = lp1->idFile;
4632 		return 1;
4633 	    }
4634 	}
4635     }
4636 
4637     *hostP = NULL;
4638     free(ipName);
4639     return 0;
4640 }
4641 
4642 /*
4643 ** checkPeerForSocket
4644 **
4645 ** Check the address of the peer of the supplied socket against the
4646 ** list of allowed addresses, if any. Returns a true/false result.
4647 **
4648 ** As a side effect, if addrP is not NULL the routine will also return
4649 ** the peer address information.
4650 */
4651 
4652 int
checkPeerForSocket(int fd,struct sockaddr_in * addrP)4653 checkPeerForSocket(int fd, struct sockaddr_in *addrP)
4654 {
4655     struct sockaddr_in addr;
4656     int addrLen = sizeof(struct sockaddr_in);
4657     char ipBuf[IP_BUF_SIZE];
4658 
4659 
4660     /*
4661     ** If there is nothing to check and we do not need to return the peer
4662     ** address we can bail out quickly.
4663     */
4664 
4665     if (AllowedPeers == NULL && addrP == NULL) return 1;
4666 
4667     if (addrP == NULL) addrP = &addr;
4668 
4669     if (getpeername(fd, (struct sockaddr *)addrP, &addrLen))
4670     {
4671 	message(0, errno, "can't get peer address for socket");
4672 	return 0;
4673     }
4674     message(4, 0, "peer address from connection is %s", ipString(addrP->sin_addr, ipBuf));
4675 
4676     /* Now check against the global peer list */
4677 
4678     return checkPeerAddress(addrP, AllowedPeers);
4679 }
4680 
4681 /*
4682 ** checkPeerAddress
4683 **
4684 */
4685 
4686 int
checkPeerAddress(struct sockaddr_in * addrP,EndPtList_t * peerList)4687 checkPeerAddress(struct sockaddr_in *addrP, EndPtList_t *peerList)
4688 {
4689     unsigned short port = 0;
4690     EndPtList_t *lp1 = NULL;
4691     struct in_addr *alp = NULL;
4692     unsigned long mask = 0xffffffff;
4693 
4694     /* A NULL peerList means allow any address */
4695 
4696     if (peerList == NULL) return 1;
4697 
4698     /* Otherwise, search for a match ... */
4699 
4700     port = ntohs(addrP->sin_port);
4701 
4702     for (lp1 = peerList; lp1; lp1 = lp1->next)
4703     {
4704 	mask = lp1->mask;
4705 
4706 	if ((addrP->sin_addr.s_addr & mask) != (lp1->addr.sin_addr.s_addr & mask))
4707 	{
4708 	    /* Did not match primary address, check aliases */
4709 
4710 	    for (alp = lp1->addrList; alp->s_addr != 0xffffffff; alp++)
4711 	    {
4712 		if ((addrP->sin_addr.s_addr & mask) == (alp->s_addr & mask))
4713 		{
4714 		    /* Found a matching address in the aliases */
4715 
4716 		    break;
4717 		}
4718 	    }
4719 
4720 	    if (alp->s_addr == 0xffffffff)
4721 	    {
4722 		/* Did not match at all, try next entry */
4723 
4724 		continue;
4725 	    }
4726 	}
4727 
4728 	message(4, 0, "checking port %hu against range %hu-%hu for host %s", port, lp1->lo, lp1->hi, lp1->host);
4729 
4730 	/* If the port range is 0 -- 0 then any port is OK */
4731 
4732 	if (lp1->lo == 0 && lp1->hi == 0)
4733 	{
4734 	    return 1;
4735 	}
4736 
4737 	/* Otherwise check against the entry for this specific host */
4738 
4739 	else if (port >= lp1->lo && port <= lp1->hi)
4740 	{
4741 	    return 1;
4742 	}
4743     }
4744 
4745     return 0;
4746 
4747 }
4748 
4749 /*
4750 ** countPorts
4751 **
4752 ** Count the number of ports named in a EndPtList_t linked list
4753 */
4754 
4755 int
countPorts(EndPtList_t * list)4756 countPorts(EndPtList_t *list)
4757 {
4758     int count = 0;
4759 
4760     while (list)
4761     {
4762 	count += (int)(list->hi - list->lo + 1);
4763 	list = list->next;
4764     }
4765 
4766     return count;
4767 }
4768 
4769 /*
4770 ** mapPort
4771 **
4772 ** Given a local port number localPort -- which should be found in ClientPorts
4773 ** -- map it to the corresponding remote port number in TargetPorts
4774 **
4775 ** Returns the remote port number on success or zero on error. If the hostP
4776 ** or addrP parameters are not NULL then any hostname and address associated
4777 ** with the port is also returned.
4778 */
4779 
4780 unsigned short
mapPort(unsigned short localPort,char ** hostP,struct sockaddr_in * addrP)4781 mapPort(unsigned short localPort, char **hostP, struct sockaddr_in *addrP)
4782 {
4783     EndPtList_t *localPtr = ClientPorts;
4784     EndPtList_t *remotePtr = TargetPorts;
4785     unsigned short count = 0;
4786 
4787 
4788     /* Find the index of the specified port in ClientPorts */
4789 
4790     while (localPtr)
4791     {
4792 	if (localPort <= localPtr->hi && localPort >= localPtr->lo)
4793 	{
4794 	    count += localPort - localPtr->lo;
4795 	    break;
4796 	}
4797 
4798 	count += (localPtr->hi - localPtr->lo + 1);
4799 	localPtr = localPtr->next;
4800     }
4801 
4802     /* If we have fallen off the end of the list, return 0 */
4803 
4804     if (localPtr == NULL)
4805     {
4806 	return 0;
4807     }
4808 
4809     /* Now find the corresponding element in TargetPorts */
4810 
4811     while (remotePtr)
4812     {
4813 	if (count <= (unsigned short)(remotePtr->hi - remotePtr->lo))
4814 	{
4815 	    if (addrP)
4816 	    {
4817 		addrP->sin_addr.s_addr = remotePtr->addr.sin_addr.s_addr;
4818 	    }
4819 	    if (hostP)
4820 	    {
4821 		if (remotePtr->host)
4822 		{
4823 		    *hostP = remotePtr->host;
4824 		}
4825 		else
4826 		{
4827 		    *hostP = ServerHost;
4828 		}
4829 	    }
4830 	    return (remotePtr->lo + count);
4831 	}
4832 
4833 	count -= (remotePtr->hi - remotePtr->lo + 1);
4834 	remotePtr = remotePtr->next;
4835     }
4836 
4837     return 0;
4838 }
4839 
4840 /******************************************\
4841 **					  **
4842 **  Core Client/Server Protocol Routines  **
4843 **					  **
4844 \******************************************/
4845 
4846 
4847 /*
4848 ** spawnHandler
4849 **
4850 ** This routine creates a single process/thread running the specified
4851 ** handler routine to handle the traffic on a single connection.
4852 */
4853 
4854 unsigned long
spawnHandler(void (* handler)(FnArgs_t *),int listenFd,int clientFd,int inLine,struct sockaddr_in * addrP,int udpMode)4855 spawnHandler(void (*handler)(FnArgs_t *), int listenFd, int clientFd,
4856 	     int inLine, struct sockaddr_in *addrP, int udpMode)
4857 {
4858     FnArgs_t *argP = NULL;
4859     struct sockaddr_in localAddr;
4860     int addrLen = sizeof(localAddr);
4861 
4862 
4863     if ((argP = (FnArgs_t *)malloc(sizeof(FnArgs_t))) == NULL)
4864     {
4865 	message(0, errno, "failed to allocate handler argument structure");
4866 	return 0;
4867     }
4868     argP->fd = clientFd;
4869     if (addrP)
4870     {
4871 	memcpy(&(argP->addr), addrP, sizeof(struct sockaddr_in));
4872     }
4873 
4874     /*
4875     ** Find out what local port is being used so we can map to the
4876     ** corresponding remote port number (used by the client only)
4877     */
4878 
4879     argP->listenFd = listenFd;
4880     if (listenFd >= 0)
4881     {
4882 	addrLen = sizeof(localAddr);
4883 	memset(&localAddr, 0, sizeof(localAddr));
4884 	if (getsockname(listenFd, (struct sockaddr *)&localAddr, &addrLen))
4885 	{
4886 	    message(0, errno, "can't get local port number");
4887 	    return 0;
4888 	}
4889 	argP->port = ntohs(localAddr.sin_port);
4890     }
4891 
4892     argP->udpMode = udpMode;
4893 
4894     argP->inLine = inLine;
4895     if (inLine)
4896     {
4897 	message(4, 0, "running handler function in-line");
4898 	(*handler)(argP);
4899 	return 0;
4900     }
4901 
4902 #if defined(HAVE_PTHREADS)
4903     {
4904 	pthread_t tid;
4905 
4906 	message(4, 0, "spawning handler function thread");
4907 	if (pthread_create(&tid,
4908 			   &ThreadAttr,
4909 			   (void * (*)(void *))handler,
4910 			   (void *)argP) == -1)
4911 	{
4912 	    message(0, errno, "failed to create handler thread");
4913 	}
4914 	message(4, 0, "handler thread %lu created", (unsigned long)tid);
4915 	return ((unsigned long)tid ? (unsigned long)tid : 0xffffffff );    /* Ensure it is never 0 */
4916     }
4917 #elif defined(WIN32)
4918     {
4919 	unsigned long tid = 0;
4920 
4921 	message(4, 0, "spawning handler function thread");
4922 	if ((tid = (unsigned long)_beginthread((void (*)(void *))handler,
4923 					       (DWORD)ThreadStackSize,
4924 					       (LPVOID)argP)) == 0)
4925 	{
4926 	    message(0, errno, "failed to create handler thread");
4927 	}
4928 	else
4929 	{
4930 	    message(4, 0, "handler thread created");
4931 	}
4932 	return tid;
4933     }
4934 #else	/* No PTHREADS and not WIN32 */
4935     {
4936 	pid_t pid;
4937 
4938 
4939 	message(4, 0, "spawning handler sub-process");
4940 	if ((pid = fork()) < 0)
4941 	{
4942 	    message(0, errno, "failed to fork handler sub-process");
4943 	    return 0;
4944 	}
4945         else if (pid == 0)
4946 	{
4947 	    /* Child -- listenFd no longer needed */
4948 
4949 	    if (!udpMode) closesocket(listenFd);
4950 
4951 	    (*handler)(argP);
4952 	    exit(EXIT_SUCCESS);
4953 	}
4954 	else
4955 	{
4956 	    /* Parent -- clientFd no longer needed */
4957 
4958 	    if (!udpMode) closesocket(clientFd);
4959 
4960 	    message(4, 0, "handler sub-process %lu created", (unsigned long)pid);
4961 	    return (unsigned long)pid;
4962 	}
4963     }
4964 #endif
4965 }
4966 
4967 /*
4968 ** findHandler
4969 **
4970 ** Find the socket descriptor associated with the handler for requests
4971 ** from the address "fromAddr", if there is one. Returns the socket id
4972 ** and local "loopback" socket address via localAddrP or -1 if not found.
4973 */
4974 
4975 int
findHandler(struct sockaddr_in * fromAddrP,struct sockaddr_in * localAddrP)4976 findHandler(struct sockaddr_in *fromAddrP, struct sockaddr_in *localAddrP)
4977 {
4978     HndInfo_t *ptr = NULL;
4979     HndInfo_t *tmp = NULL;
4980     int found = -1;
4981     char ipBuf[IP_BUF_SIZE];
4982 
4983 
4984     message(5, 0, "searching for handler for address %s:%hu", ipString(fromAddrP->sin_addr, ipBuf), ntohs(fromAddrP->sin_port));
4985 
4986     mutexLock(MUTEX_HNDLIST);
4987 
4988     for (ptr = &HandlerList; ptr != NULL; ptr = ptr->next)
4989     {
4990 #if !defined(WIN32) && !defined(HAVE_PTHREADS)
4991 	/*
4992 	** If we don't have threads then check whether the handler process
4993 	** is still alive. If not, remove it from the list.
4994 	*/
4995 
4996 	if (kill((pid_t)(ptr->id), 0) != 0)
4997 	{
4998 	    message(5, 0, "removing defunct handler, id = %lu", ptr->id);
4999 
5000 	    ptr->prev->next = ptr->next;
5001 	    if (ptr->next)
5002 	    {
5003 		ptr->next->prev = ptr->prev;
5004 	    }
5005 	    tmp = ptr;
5006 	    ptr = ptr->prev;
5007 	    closesocket(tmp->fd);
5008 	    free(tmp);
5009 	    continue;
5010 	}
5011 #endif
5012 	if (ptr->fromAddr.sin_port == fromAddrP->sin_port &&
5013 	    ptr->fromAddr.sin_addr.s_addr == fromAddrP->sin_addr.s_addr)
5014 	{
5015 	    message(5, 0, "found handler, id = %lu, socket = %d", ptr->id, ptr->fd);
5016 	    found = ptr->fd;
5017 	    memcpy(localAddrP, &(ptr->localAddr), sizeof(struct sockaddr_in));
5018 	}
5019 
5020 	tmp = ptr; /* Shut the compiler up by using tmp! */
5021     }
5022 
5023     mutexUnlock(MUTEX_HNDLIST);
5024 
5025     return found;
5026 }
5027 
5028 /*
5029 ** addHandler
5030 **
5031 ** Register a new handler for requests from fromAddrP. The "id" is only used
5032 ** in the multi-process version and is the PID of the handler process. The
5033 ** "fd" is the socket descriptor for the local "loopback" socket used to
5034 ** communicate with the handler. The "localAddrP" is the address associated
5035 ** with the socket.
5036 */
5037 
5038 void
addHandler(struct sockaddr_in * fromAddrP,unsigned long id,int fd,struct sockaddr_in * localAddrP)5039 addHandler(struct sockaddr_in *fromAddrP, unsigned long id, int fd, struct sockaddr_in *localAddrP)
5040 {
5041     HndInfo_t *ptr = NULL;
5042 
5043 
5044     mutexLock(MUTEX_HNDLIST);
5045 
5046     for (ptr = &HandlerList; ptr->next != NULL; ptr = ptr->next)
5047     {
5048 	/* Walk to end */
5049     }
5050 
5051     if ((ptr->next = (HndInfo_t *)malloc(sizeof(HndInfo_t))) == NULL)
5052     {
5053 	message(0, errno, "failed to allocate memory for handler list element");
5054     }
5055     else
5056     {
5057 	ptr->next->id = id;
5058 	ptr->next->fd = fd;
5059 	memcpy(&(ptr->next->fromAddr), fromAddrP, sizeof(struct sockaddr_in));
5060 	memcpy(&(ptr->next->localAddr), localAddrP, sizeof(struct sockaddr_in));
5061 	ptr->next->prev = ptr;
5062 	ptr->next->next = NULL;
5063     }
5064 
5065     mutexUnlock(MUTEX_HNDLIST);
5066 }
5067 
5068 /*
5069 ** removeHandler
5070 **
5071 ** This removes the handler with the specified address from the list.
5072 */
5073 
5074 void
removeHandler(struct sockaddr_in * addrP)5075 removeHandler(struct sockaddr_in *addrP)
5076 {
5077     HndInfo_t *ptr = NULL;
5078     HndInfo_t *tmp = NULL;
5079 
5080     mutexLock(MUTEX_HNDLIST);
5081 
5082     for (ptr = &HandlerList; ptr != NULL; ptr = ptr->next)
5083     {
5084 	if (ptr->fromAddr.sin_port == addrP->sin_port &&
5085 	    ptr->fromAddr.sin_addr.s_addr == addrP->sin_addr.s_addr)
5086 	{
5087 	    ptr->prev->next = ptr->next;
5088 	    if (ptr->next)
5089 	    {
5090 		ptr->next->prev = ptr->prev;
5091 	    }
5092 	    tmp = ptr;
5093 	    ptr = ptr->prev;
5094 	    /* socket is closed in client routine */
5095 	    free(tmp);
5096 	}
5097     }
5098 
5099     mutexUnlock(MUTEX_HNDLIST);
5100 }
5101 
5102 /*
5103 ** clientListener
5104 **
5105 ** This is the top-level client routine that sets up local sockets
5106 ** and listens for connections. It the then spawns an individual
5107 ** process or thread to handle a client.
5108 **
5109 ** This operates slightly differently in TCP and UDP modes. In TCP mode
5110 ** when a new connection is detected the connection is accepted and then
5111 ** this accepted socket is handed off to a handler routine in a separate
5112 ** thread or process. All data from and to the client is handled directly
5113 ** by the handler function.
5114 **
5115 ** In UDP mode things are more complex. Every datagram from a client is
5116 ** received in this routine. It examines the source address and determines
5117 ** whether it currently has a handler active. If it doesn't it creates one
5118 ** along with a local "loopback" socket which it passes to the handler along
5119 ** with the address of the original client. It then sends the messages it
5120 ** receives to the loopback socket. The handler itself will exit after
5121 ** UdpTimeout seconds of inactivity.
5122 */
5123 
5124 void
clientListener(EndPtList_t * ports)5125 clientListener(EndPtList_t *ports)
5126 {
5127     int listenFd = -1;
5128     int clientFd;
5129     struct sockaddr_in fromAddr;
5130     struct sockaddr_in localAddr;
5131     int addrLen;
5132     unsigned short localPort = 0;
5133     fd_set tcpSet;
5134     fd_set udpSet;
5135     fd_set unionSet;
5136     fd_set testSet;
5137     int maxFd = -1;
5138     int ready = 0;
5139     unsigned long id = 0;
5140     char data[MAX_BUF_SIZE];
5141     int num;
5142     char ipBuf[IP_BUF_SIZE];
5143 
5144 
5145     message(3, 0, "client listener routine entered");
5146 
5147     /*
5148     ** Create the local listener socket(s) and fire up the requested
5149     ** sub-command if necessary. We do this first so that the child
5150     ** process does not inherit the connection to the server.
5151     */
5152 
5153     FD_ZERO(&tcpSet);
5154     FD_ZERO(&udpSet);
5155     if (TcpMode)
5156     {
5157 	maxFd = makeClientListeners(ports, &tcpSet, 0);
5158     }
5159     if (UdpMode)
5160     {
5161 	listenFd = makeClientListeners(ports, &udpSet, 1);
5162 	if (listenFd > maxFd)
5163 	{
5164 	    maxFd = listenFd;
5165 	}
5166     }
5167 
5168     /*
5169     ** Catch possible mix-ups in the client tunnels specification leading to
5170     ** there being no valid ports to listen on.
5171     */
5172 
5173     if (maxFd == -1)
5174     {
5175 	message(0, 0, "client not listening on any ports -- check tunnel specifications");
5176 	exit(EXIT_FAILURE);
5177     }
5178 
5179     /*
5180     ** If running in "listen mode" the client must listen for the server
5181     ** to connect back to it.
5182     */
5183 
5184     if (ListenMode)
5185     {
5186 	message(3, 0, "listening for server connection on port %hu", ServerPort);
5187 
5188 	if ((ListenSock = makeListener(&ServerPort, ListenIp, 0, 1)) == -1)
5189 	{
5190 	    message(0, errno, "can't create listener socket for server connection");
5191 	    exit(EXIT_FAILURE);
5192 	}
5193     }
5194 
5195     /* Detach from terminal, if required */
5196 
5197     if (IsDetached)
5198     {
5199 	message(3, 0, "detaching from terminal");
5200 	makeDetached();
5201     }
5202 
5203     /* Change user ID, if required */
5204 
5205     switchUser();
5206 
5207     /* Spawn the sub-command, if specified */
5208 
5209     if (CommandString)
5210     {
5211 	message(3, 0, "spawning command '%s'", CommandString);
5212 
5213 	if (!spawnCommand(ports->lo, CommandString))
5214 	{
5215 	    exit(EXIT_FAILURE);
5216 	}
5217     }
5218 
5219     /*
5220     ** Now wait for a connection from a local client. If we are operating
5221     ** in "persistent" mode then we will loop forever otherwise this
5222     ** will be a "one shot" connection.
5223     */
5224 
5225     if (UdpMode) message(1, 0, "listening for client UDP data");
5226 
5227     /* Create union fd sets from the TCP and UDP sets */
5228 
5229     FD_ZERO(&unionSet);
5230     for (listenFd = 0; listenFd <= maxFd; listenFd++)
5231     {
5232 	if (FD_ISSET(listenFd, &tcpSet))
5233 	{
5234 	    FD_SET(listenFd, &unionSet);
5235 	}
5236 	else if (FD_ISSET(listenFd, &udpSet))
5237 	{
5238 	    FD_SET(listenFd, &unionSet);
5239 	}
5240     }
5241 
5242     do
5243     {
5244 	memcpy(&testSet, &unionSet, sizeof(fd_set));
5245 
5246 	if (UdpMode)
5247 	{
5248 	    message(5, 0, "waiting for client data", localPort);
5249 	}
5250 	else
5251 	{
5252 	    message(1, 0, "waiting for client connection", localPort);
5253 	}
5254 
5255 	/* Do a blocking select waiting for any i/o */
5256 
5257 	ready = select(maxFd + 1, &testSet, 0, 0, 0);
5258 
5259 	message((UdpMode ? 5 : 3), 0, "select returned %d", ready);
5260 
5261 	/* If we get zero then there is nothing available on any fd. */
5262 
5263 	if (ready == 0)
5264 	{
5265 	    break;
5266 	}
5267 
5268 	/* Check for error but ignore interrupted system calls */
5269 
5270 	if (ready < 0 && errno != EINTR)
5271 	{
5272 	    message(0, errno, "error in select");
5273 	    break;
5274 	}
5275 
5276 	/* See which sockets have connections/data and handle them */
5277 
5278 	for (listenFd = 0; listenFd <= maxFd; listenFd++)
5279 	{
5280 	    if (FD_ISSET(listenFd, &testSet))
5281 	    {
5282 		if (FD_ISSET(listenFd, &udpSet))
5283 		{
5284 		    /* See who this is from */
5285 
5286 		    addrLen = sizeof(fromAddr);
5287 		    if ((num = recvfrom(listenFd, data, MAX_BUF_SIZE, 0,
5288 					(struct sockaddr *)&fromAddr,
5289 					&addrLen)) > 0)
5290 		    {
5291 			/*
5292 			** If there is not already a handler for this
5293 			** address/port combination then create one.
5294 			*/
5295 
5296 			if ((clientFd = findHandler(&fromAddr, &localAddr)) == -1)
5297 			{
5298 			    /* Create a "loopback" socket */
5299 
5300 			    localPort = 0;
5301 			    if ((clientFd = makeListener(&localPort, "127.0.0.1", 1, MAX_LISTEN)) == -1)
5302 			    {
5303 				continue;
5304 			    }
5305 
5306 			    id = spawnHandler(client, listenFd, clientFd,
5307 					      (Debug || !MultiUse), &fromAddr, 1);
5308 
5309 			    if (id != 0)
5310 			    {
5311 				memset(&localAddr, 0, sizeof(localAddr));
5312 				localAddr.sin_family = AF_INET;
5313 				localAddr.sin_port = htons(localPort);
5314 				localAddr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
5315 
5316 				addHandler(&fromAddr, id, clientFd, &localAddr);
5317 			    }
5318 			}
5319 
5320 			/*
5321 			** We should now have a valid loopback socket
5322 			** descriptor associated with a handler. If so,
5323 			** send the data on to it.
5324 			*/
5325 
5326 			if (clientFd != -1)
5327 			{
5328 			    if (sendto(clientFd, data, num, 0,
5329 				       (struct sockaddr *)&localAddr,
5330 				       sizeof(localAddr)) != num)
5331 			    {
5332 				message(0, errno, "failed to send data to loopback socket");
5333 			    }
5334 			}
5335 		    }
5336 		    else
5337 		    {
5338 			message(0, errno, "can't read next message");
5339 		    }
5340 		}
5341 		else
5342 		{
5343 		    /*
5344 		    ** New TCP connection -- accept the connection and
5345 		    ** spawn a new handler for it.
5346 		    */
5347 
5348 		    message(5, 0, "connection ready on socket %d", listenFd);
5349 
5350 		    addrLen = sizeof(struct sockaddr_in);
5351 		    memset(&fromAddr, 0, sizeof(fromAddr));
5352 		    if ((clientFd = accept(listenFd,
5353 					   (struct sockaddr *)&fromAddr,
5354 					   &addrLen)) < 0)
5355 		    {
5356 			message(0, errno, "error on accept");
5357 		    }
5358 		    else
5359 		    {
5360 			message(1, 0, "accepted connection from %s", ipString(fromAddr.sin_addr, ipBuf));
5361 
5362 			/* Set the "don't linger on close" option */
5363 
5364 			setNoLinger(clientFd);
5365 
5366 			/* Set "keep alive" to reap defunct connections */
5367 
5368 			setKeepAlive(clientFd);
5369 
5370 			/* Create the handler process/thread */
5371 
5372 			spawnHandler(client, listenFd, clientFd,
5373 				     (Debug || !MultiUse), &fromAddr, 0);
5374 		    }
5375 		}
5376 	    }
5377 	}
5378     }
5379     while (MultiUse);
5380 
5381     /* We do not need to listen for any more clients */
5382 
5383     for (listenFd = 0; listenFd <= maxFd; listenFd++)
5384     {
5385 	if (FD_ISSET(listenFd, &unionSet)) closesocket(listenFd);
5386     }
5387     listenFd = -1;
5388 
5389     /* Wait for handler threads to terminate (should not be necessary) */
5390 
5391     waitForInactivity();
5392 }
5393 
5394 /*
5395 ** makeClientListeners
5396 **
5397 ** Create the listen sockets for the ports in the supplied port list.
5398 ** Set the appropriate bits in the fd_set. The udpMode value indicates
5399 ** whether we're doing TCP or UDP listens.
5400 */
5401 
5402 int
makeClientListeners(EndPtList_t * ports,fd_set * listenSetP,int udpMode)5403 makeClientListeners(EndPtList_t *ports, fd_set *listenSetP, int udpMode)
5404 {
5405     int listenFd = -1;
5406     unsigned short localPort = 0;
5407     int maxFd = -1;
5408 
5409     while (ports)
5410     {
5411 	for (localPort = ports->lo; localPort <= ports->hi; localPort++)
5412 	{
5413 	    if ((ports->type & (udpMode ? ENDPTLIST_UDP : ENDPTLIST_TCP)) == 0)
5414 	    {
5415 		/* Skip incompatible port types */
5416 		continue;
5417 	    }
5418 
5419 	    message(3, 0, "creating %s-mode local listener socket for port %hu",
5420 		    (udpMode ? "UDP" : "TCP"), localPort);
5421 
5422 	    if ((listenFd = makeListener(&localPort, ListenIp, udpMode, MAX_LISTEN)) == -1)
5423 	    {
5424 		message(0, errno, "can't create listener socket");
5425 		exit(EXIT_FAILURE);
5426 	    }
5427 
5428 	    message(5, 0, "local port %hu has socket %d", localPort, listenFd);
5429 
5430 	    FD_SET(listenFd, listenSetP);
5431 	    if (listenFd > maxFd)
5432 	    {
5433 		maxFd = listenFd;
5434 	    }
5435 
5436 	    if (!CommandString)
5437 	    {
5438 		message(1, 0, "Listening on local port %hu", localPort);
5439 	    }
5440 	    else
5441 	    {
5442 		message(3, 0, "listening on local port %hu", localPort);
5443 	    }
5444 
5445 	    /* Special case port was zero -- modify entry */
5446 
5447 	    if (ports->hi == 0)
5448 	    {
5449 		ports->lo = ports->hi = localPort;
5450 	    }
5451 	}
5452 
5453 	ports = ports->next;
5454     }
5455 
5456     return maxFd;
5457 }
5458 
5459 /*
5460 ** client
5461 **
5462 ** This routine implements the client side of the Zebedee protocol. It is
5463 ** fully re-entrant.
5464 */
5465 
5466 void
client(FnArgs_t * argP)5467 client(FnArgs_t *argP)
5468 {
5469     int clientFd = argP->fd;
5470     const char *serverHost = ServerHost;
5471     const unsigned short serverPort = ServerPort;
5472     unsigned short redirectPort = 0;
5473     unsigned short maxSize = MaxBufSize;
5474     int serverFd = -1;
5475     unsigned short response = 0;
5476     char generator[MAX_LINE_SIZE];
5477     char modulus[MAX_LINE_SIZE];
5478     char serverDhKey[MAX_LINE_SIZE];
5479     char *exponent = NULL;
5480     char *dhKey = NULL;
5481     char *secretKeyStr = NULL;
5482     char *sessionKeyStr = NULL;
5483     MsgBuf_t *msg = NULL;
5484     unsigned short cmpInfo = CompressInfo;
5485     unsigned short keyBits = KeyLength;
5486     unsigned short protocol = DFLT_PROTOCOL;
5487     unsigned long token = 0;
5488     unsigned char hdrData[HDR_SIZE_MAX];
5489     unsigned short hdrSize = HDR_SIZE_MIN;
5490     unsigned char clientNonce[NONCE_SIZE];
5491     unsigned char serverNonce[NONCE_SIZE];
5492     char *targetHost = NULL;
5493     struct sockaddr_in peerAddr;
5494     struct sockaddr_in targetAddr;
5495     int inLine = argP->inLine;
5496     int udpMode = argP->udpMode;
5497     char ipBuf[IP_BUF_SIZE];
5498     unsigned short cksumLevel = CHECKSUM_NONE;
5499     SHA_INFO sha;
5500     int active = 0;
5501 
5502 
5503     active = incrActiveCount(1);
5504     if (MaxConnections > 0 && MaxConnections < active)
5505     {
5506         message(0, 0, "maximum number of concurrent connections exceeded");
5507         goto fatal;
5508     }
5509     message(3, 0, "client routine entered");
5510 
5511     /*
5512     ** Find out what target port we will tunnel to.
5513     */
5514 
5515     redirectPort = mapPort(argP->port, &targetHost, &targetAddr);
5516     if (redirectPort)
5517     {
5518 	message(3, 0, "client on local port %hu tunnels to target %s:%hu", argP->port, targetHost, redirectPort);
5519 	message(4, 0, "target address is %08x", ntohl(targetAddr.sin_addr.s_addr));
5520     }
5521     else
5522     {
5523 	message(0, 0, "no matching target port for local port %hu", argP->port);
5524 	goto fatal;
5525     }
5526 
5527     if (ListenMode)
5528     {
5529 	message(3, 0, "waiting for connection from server");
5530 
5531 	if ((serverFd = acceptConnection(ListenSock, serverHost,
5532 					 1, AcceptConnectTimeout)) == -1)
5533 	{
5534 	    message(0, errno, "failed to accept a connection from %s", serverHost);
5535 	    goto fatal;
5536 	}
5537 	message(3, 0, "accepted connection from server");
5538     }
5539     else
5540     {
5541 	message(3, 0, "making connection to %s:%hu", serverHost, serverPort);
5542 
5543 	if ((serverFd = makeConnection(serverHost, serverPort, 0, 1, NULL, NULL, ServerConnectTimeout)) == -1)
5544 	{
5545 	    message(0, errno, "can't connect to %s port %hu", serverHost, serverPort);
5546 	    goto fatal;
5547 	}
5548 	message(3, 0, "connected to %s:%hu", serverHost, serverPort);
5549     }
5550 
5551     /*
5552     ** Validate the server IP address, if required.
5553     */
5554 
5555     message(3, 0, "validating server IP address");
5556 
5557     if (!checkPeerForSocket(serverFd, &peerAddr))
5558     {
5559 	message(0, 0, "connection with server %s disallowed", ipString(peerAddr.sin_addr, ipBuf));
5560 	goto fatal;
5561     }
5562 
5563     /*
5564     ** Request protocol version.
5565     */
5566 
5567     message(3, 0, "requesting protocol version %#hx", protocol);
5568 
5569     if (!requestResponse(serverFd, protocol, &response))
5570     {
5571 	message(0, errno, "failed requesting protocol version");
5572 	goto fatal;
5573     }
5574 
5575     if (LockProtocol)
5576     {
5577 	/* We have locked all other protocol versions out of the protocol
5578 	** negotiation. A server responding with a higher protocol
5579 	** would indicate that the server is "locked" as well. A lower
5580 	** protocol would violate "our" lock. In any case we have an error.
5581 	*/
5582 	if (response != DFLT_PROTOCOL)
5583 	{
5584 	    message(0, 0, "server responded with incompatible protocol version (%#hx)", response);
5585 	    goto fatal;
5586 	}
5587     }
5588     else
5589     {
5590 	switch (response)
5591 	{
5592 	case PROTOCOL_V202:
5593 	    protocol = PROTOCOL_V202;
5594 	    break;
5595 
5596 	case PROTOCOL_V201:
5597 	    protocol = PROTOCOL_V201;
5598 	    break;
5599 
5600 	case PROTOCOL_V200:
5601 	    protocol = PROTOCOL_V200;
5602 	    break;
5603 
5604 	default:
5605 	    message(0, 0, "server responded with incompatible protocol version (%#hx)", response);
5606 	    goto fatal;
5607 	}
5608     }
5609 
5610     message(3, 0, "accepted protocol version %#hx", response);
5611 
5612     message(3, 0, "requesting %s mode", (udpMode ? "UDP" : "TCP"));
5613     headerSetUShort(hdrData, (udpMode ? HDR_FLAG_UDPMODE : 0), HDR_OFFSET_FLAGS);
5614 
5615     message(3, 0, "requesting buffer size %hu", maxSize);
5616     headerSetUShort(hdrData, maxSize, HDR_OFFSET_MAXSIZE);
5617 
5618     message(3, 0, "requesting compression level %#hx", CompressInfo);
5619     headerSetUShort(hdrData, CompressInfo, HDR_OFFSET_CMPINFO);
5620 
5621     message(3, 0, "requesting redirection to port %hu", redirectPort);
5622     headerSetUShort(hdrData, redirectPort, HDR_OFFSET_PORT);
5623 
5624     message(3, 0, "requesting key length %hu", KeyLength);
5625     headerSetUShort(hdrData, KeyLength, HDR_OFFSET_KEYLEN);
5626 
5627     token = getCurrentToken();
5628     message(3, 0, "requesting key reuse token %#lx", token);
5629     headerSetULong(hdrData, token, HDR_OFFSET_TOKEN);
5630 
5631     generateNonce(clientNonce);
5632     message(3, 0, "sending client nonce %02x%02x...", clientNonce[0], clientNonce[1]);
5633     memcpy(hdrData + HDR_OFFSET_NONCE, clientNonce, NONCE_SIZE);
5634 
5635     if (protocol >= PROTOCOL_V201)
5636     {
5637 	hdrSize = HDR_SIZE_V201;
5638 	/*
5639 	** If the target is the same as the ServerHost then we send
5640 	** all zeroes to indicate the default server target. Otherwise
5641 	** we use the targetAddr.
5642 	*/
5643 
5644 	if (strcmp(targetHost, ServerHost) == 0)
5645 	{
5646 	    message(4, 0, "target is the same as the server");
5647 	    targetAddr.sin_addr.s_addr = 0x00000000;
5648 	}
5649 	message(3, 0, "requesting target address %08x", ntohl(targetAddr.sin_addr.s_addr));
5650 	headerSetULong(hdrData, (unsigned long)ntohl(targetAddr.sin_addr.s_addr), HDR_OFFSET_TARGET);
5651     }
5652 
5653     if (protocol >= PROTOCOL_V202)
5654     {
5655 	hdrSize = HDR_SIZE_V202;
5656 	/*
5657 	** This adds a message checksum to allows us to detect if
5658 	** somebody has tampered with the data "in flight".
5659 	*/
5660 	headerSetUShort(hdrData, ChecksumLevel, HDR_OFFSET_CHECKSUM);
5661 
5662 	/*
5663 	** The header data sent and received is hashed in order to
5664 	** obtain the initial checksum seed.
5665 	*/
5666 	sha_init(&sha);
5667 	sha_update(&sha, hdrData, hdrSize);
5668     }
5669 
5670     if (writeData(serverFd, hdrData, hdrSize) != hdrSize)
5671     {
5672 	message(0, errno, "failed writing protocol header to server");
5673 	goto fatal;
5674     }
5675 
5676     if (readData(serverFd, hdrData, hdrSize) != hdrSize)
5677     {
5678 	message(0, errno, "failed reading protocol header response from server");
5679 	goto fatal;
5680     }
5681 
5682     if ((udpMode && headerGetUShort(hdrData, HDR_OFFSET_FLAGS) != HDR_FLAG_UDPMODE) ||
5683 	(!udpMode && headerGetUShort(hdrData, HDR_OFFSET_FLAGS) == HDR_FLAG_UDPMODE))
5684     {
5685 	message(0, 0, "client requested %s mode and server is in %s mode",
5686 		(udpMode ? "UDP" : "TCP"), (udpMode ? "TCP" : "UDP"));
5687 	goto fatal;
5688     }
5689     else
5690     {
5691 	message(3, 0, "accepted %s mode", (udpMode ? "UDP" : "TCP"));
5692     }
5693 
5694     maxSize = headerGetUShort(hdrData, HDR_OFFSET_MAXSIZE);
5695     if (maxSize > 0)
5696     {
5697 	message(3, 0, "accepted buffer size %hu", maxSize);
5698     }
5699     else
5700     {
5701 	message(0, 0, "server responded with zero buffer size");
5702 	goto fatal;
5703     }
5704 
5705     cmpInfo = headerGetUShort(hdrData, HDR_OFFSET_CMPINFO);
5706     if (cmpInfo <= CompressInfo)
5707     {
5708 	message(3, 0, "accepted compression level %#hx", cmpInfo);
5709     }
5710     else
5711     {
5712 	message(0, 0, "server responded with invalid compression level (%#hx > %#hx)", cmpInfo, CompressInfo);
5713 	goto fatal;
5714     }
5715 
5716     response = headerGetUShort(hdrData, HDR_OFFSET_PORT);
5717     if (response == redirectPort)
5718     {
5719 	message(3, 0, "redirection request accepted");
5720     }
5721     else
5722     {
5723 	message(0, 0, "server refused request for redirection to %s:%hu", targetHost, redirectPort);
5724 	goto fatal;
5725     }
5726 
5727     keyBits = headerGetUShort(hdrData, HDR_OFFSET_KEYLEN);
5728     if (keyBits >= MinKeyLength)
5729     {
5730 	message(3, 0, "accepted key length %hu", keyBits);
5731     }
5732     else
5733     {
5734 	message(0, 0, "server key length too small (%hu < %hu)", keyBits, MinKeyLength);
5735 	goto fatal;
5736     }
5737 
5738     token = headerGetULong(hdrData, HDR_OFFSET_TOKEN);
5739     message(3, 0, "accepted key reuse token %#lx", token);
5740 
5741     memcpy(serverNonce, hdrData + HDR_OFFSET_NONCE, NONCE_SIZE);
5742     message(3, 0, "received server nonce %02x%02x...", serverNonce[0], serverNonce[1]);
5743 
5744     if (protocol >= PROTOCOL_V202)
5745     {
5746 	cksumLevel = headerGetUShort(hdrData, HDR_OFFSET_CHECKSUM);
5747 	if (cksumLevel >= MinChecksumLevel)
5748 	{
5749 	    message(3, 0, "accepted checksum level %hu", cksumLevel);
5750 	}
5751 	else
5752 	{
5753 	    message(0, 0, "server refused request for checksum level %hu", ChecksumLevel);
5754 	    goto fatal;
5755 	}
5756 
5757 	/* Compute the initial checksum seed */
5758 
5759 	sha_update(&sha, hdrData, hdrSize);
5760 	sha_final(&sha);
5761     }
5762     else
5763     {
5764 	cksumLevel = CHECKSUM_NONE;
5765     }
5766 
5767     /* Allocate message buffer */
5768 
5769     if ((msg = makeMsgBuf(maxSize, cmpInfo, cksumLevel)) == NULL)
5770     {
5771 	message(0, errno, "client failed to allocate message buffer");
5772 	goto fatal;
5773     }
5774 
5775     /*
5776     ** Store the initial input and output checksum seeds, if necessary
5777     */
5778     if (protocol >= PROTOCOL_V202)
5779     {
5780 	sha.digest[0] = BUGHTONL(sha.digest[0]);
5781 	sha.digest[1] = BUGHTONL(sha.digest[1]);
5782 	sha.digest[2] = BUGHTONL(sha.digest[2]);
5783 	sha.digest[3] = BUGHTONL(sha.digest[3]);
5784 	sha.digest[4] = BUGHTONL(sha.digest[4]);
5785 	memcpy(msg->inSeed, &sha.digest, sizeof(sha.digest));
5786 	memcpy(msg->outSeed, &sha.digest, sizeof(sha.digest));
5787     }
5788 
5789     /*
5790     ** For all new versions the protocol, if the session token returned
5791     ** by the server matches that sent by the client (and is not zero)
5792     ** then we will perform a challenge-response to verify that there
5793     ** really is a shared key. There is a small possibility that a
5794     ** a server that has restarted since a client received a token will
5795     ** see an apparently valid token value from such a client but will,
5796     ** in reality, have no shared key. This will detect that although
5797     ** the result will be that the client connection is rejected.
5798     */
5799 
5800     if ((secretKeyStr = findKeyByToken(&ClientKeyList, token, &peerAddr, &targetAddr, redirectPort)) != NULL)
5801     {
5802 	sessionKeyStr = generateSessionKey(secretKeyStr, clientNonce,
5803 					   serverNonce, keyBits);
5804 
5805 	message(3, 0, "session key ends '...%s'", sessionKeyStr + strlen(sessionKeyStr) - 4);
5806 
5807 	msg->bfWrite = setupBlowfish(sessionKeyStr, keyBits);
5808 	msg->bfRead = setupBlowfish(sessionKeyStr, keyBits);
5809 
5810 	memset(secretKeyStr, 0, strlen(secretKeyStr));
5811 	free(secretKeyStr);
5812 	secretKeyStr = NULL;
5813 	memset(sessionKeyStr, 0, strlen(sessionKeyStr));
5814 	free(sessionKeyStr);
5815 	sessionKeyStr = NULL;
5816 
5817 	if (!clientPerformChallenge(serverFd, msg))
5818 	{
5819 	    message(0, 0, "challenge/response failed to validate shared key (session token = %#08x)", CurrentToken);
5820 	    mutexLock(MUTEX_TOKEN);
5821 	    CurrentToken = TOKEN_NEW;
5822 	    mutexUnlock(MUTEX_TOKEN);
5823 	    goto fatal;
5824 	}
5825     }
5826 
5827     /*
5828     ** ELSE ...
5829     ** If the key length is zero then we can omit the key exchange
5830     ** protocol because only compression is being used.
5831     */
5832 
5833     else if (keyBits > 0)
5834     {
5835 
5836 	/* Read the DH generator */
5837 
5838 	message(3, 0, "reading DH generator");
5839 
5840 	if (readMessage(serverFd, msg, MAX_LINE_SIZE) <= 0)
5841 	{
5842 	    message(0, errno, "failed reading DH generator");
5843 	    goto fatal;
5844 	}
5845 	getMsgBuf(msg, generator, MAX_LINE_SIZE);
5846 
5847 	message(3, 0, "accepted generator '%s'", generator);
5848 
5849 
5850 	/* Read the DH modulus */
5851 
5852 	message(3, 0, "reading DH modulus");
5853 
5854 	if (readMessage(serverFd, msg, MAX_LINE_SIZE) <= 0)
5855 	{
5856 	    message(0, errno, "failed reading DH modulus");
5857 	    goto fatal;
5858 	}
5859 	getMsgBuf(msg, modulus, MAX_LINE_SIZE);
5860 
5861 	message(3, 0, "accepted modulus '%s'", modulus);
5862 
5863 
5864 	/* Read the server DH key */
5865 
5866 	message(3, 0, "reading server DH key");
5867 
5868 	if (readMessage(serverFd, msg, MAX_LINE_SIZE) <= 0)
5869 	{
5870 	    message(0, errno, "failed reading server DH key");
5871 	    goto fatal;
5872 	}
5873 	getMsgBuf(msg, serverDhKey, MAX_LINE_SIZE);
5874 
5875 	message(3, 0, "accepted server DH key '%s'", serverDhKey);
5876 
5877 	/*
5878 	** If requested, check this against a list of "known" keys
5879 	** to validate the server identity.
5880 	*/
5881 
5882 	if (IdentityFile)
5883 	{
5884 	    message(3, 0, "checking key against identity file '%s'", IdentityFile);
5885 
5886 	    if (!checkIdentity(IdentityFile, generator, modulus, serverDhKey))
5887 	    {
5888 		message(0, 0, "server's identity not found in '%s'", IdentityFile);
5889 		goto fatal;
5890 	    }
5891 	}
5892 
5893 	/*
5894 	** Now generate our exponent (the private key). This is returned
5895 	** as a hex string. If a private key string has been specified
5896 	** then use this.
5897 	*/
5898 
5899 	message(3, 0, "generating private key");
5900 
5901 	if ((exponent = generateKey(&peerAddr, &targetAddr, redirectPort)) == NULL)
5902 	{
5903 	    message(0, 0, "can't generate private key");
5904 	    goto fatal;
5905 	}
5906 	message(3, 0, "private key generated");
5907 
5908 
5909 	/*
5910 	** Generate the public DH key.
5911 	*/
5912 
5913 	message(3, 0, "generating public DH key");
5914 
5915 	if ((dhKey = diffieHellman(generator, modulus, exponent)) == NULL)
5916 	{
5917 	    message(0, 0, "can't generate public DH key");
5918 	    goto fatal;
5919 	}
5920 	message(3, 0, "public DH key is '%s'", dhKey);
5921 
5922 	/* Now send the DH key */
5923 
5924 	message(3, 0, "sending public DH key");
5925 
5926 	setMsgBuf(msg, dhKey, strlen(dhKey) + 1);
5927 	if (writeMessage(serverFd, msg) != msg->size)
5928 	{
5929 	    message(0, errno, "failed writing DH key to server");
5930 	    goto fatal;
5931 	}
5932 	message(3, 0, "sent public DH key");
5933 
5934 	/* Now generate the shared secret key */
5935 
5936 	message(3, 0, "generating shared secret key");
5937 
5938 	secretKeyStr = diffieHellman(serverDhKey, modulus, exponent);
5939 
5940 	message(3, 0, "shared key ends '...%s'", secretKeyStr + strlen(secretKeyStr) - 4);
5941 
5942 	if (protocol >= PROTOCOL_V200)
5943 	{
5944 	    sessionKeyStr = generateSessionKey(secretKeyStr, clientNonce,
5945 					       serverNonce, keyBits);
5946 
5947 	    message(3, 0, "session key ends '...%s'", sessionKeyStr + strlen(sessionKeyStr) - 4);
5948 	}
5949 	else
5950 	{
5951 	    sessionKeyStr = secretKeyStr;
5952 	}
5953 
5954 	message(3, 0, "initialising encryption state");
5955 
5956 	msg->bfWrite = setupBlowfish(sessionKeyStr, keyBits);
5957 	msg->bfRead = setupBlowfish(sessionKeyStr, keyBits);
5958 
5959 	/* Clear unneeded values */
5960 
5961 	memset(exponent, 0, strlen(exponent));
5962 	free(exponent);
5963 	exponent = NULL;
5964 	free(dhKey);
5965 	dhKey = NULL;
5966 
5967 	/*
5968 	** Having established the encrypted channel we now perform a mutual
5969 	** challenge/response dialogue in order to guard against being spoofed
5970 	** by a replay attack if we are using a static key.
5971 	*/
5972 
5973 	if (!clientPerformChallenge(serverFd, msg))
5974 	{
5975 	    goto fatal;
5976 	}
5977 
5978 	/*
5979 	** If we are at protocol version 200 or higher and a new session
5980 	** token was allocated by the server then update the CurrentToken
5981 	** and secret key list.
5982 	*/
5983 
5984 	if (protocol >= PROTOCOL_V200 && token != 0)
5985 	{
5986 	    message(3, 0, "new reusable key token established (%#lx)", token);
5987 
5988 	    addKeyInfoToList(&ClientKeyList, token, secretKeyStr);
5989 	    mutexLock(MUTEX_TOKEN);
5990 	    CurrentToken = token;
5991 	    mutexUnlock(MUTEX_TOKEN);
5992 	}
5993 
5994 	if (sessionKeyStr != secretKeyStr)
5995 	{
5996 	    memset(sessionKeyStr, 0, strlen(sessionKeyStr));
5997 	    free(sessionKeyStr);
5998 	    sessionKeyStr = NULL;
5999 	}
6000 	memset(secretKeyStr, 0, strlen(secretKeyStr));
6001 	free(secretKeyStr);
6002 	secretKeyStr = NULL;
6003     }
6004     else
6005     {
6006 	message(3, 0, "key length is zero, omitting key exchange");
6007 	if (IdentityFile != NULL)
6008 	{
6009 	    message(1, 0, "Warning: agreed key length is zero, no identity checking performed");
6010 	}
6011     }
6012 
6013     message(1, 0, "tunnel established to %s port %hu", serverHost, redirectPort);
6014     message(2, 0, "compression level %#hx, key length %hu", cmpInfo, keyBits);
6015 
6016     /* Now loop handling i/o */
6017 
6018     message(3, 0, "entering filter loop");
6019 
6020     switch (filterLoop(clientFd, serverFd, msg, &(argP->addr), &peerAddr, argP->listenFd, udpMode))
6021     {
6022     case 1:
6023 	message(0, errno, "failed communicating with remote server");
6024 	goto fatal;
6025 
6026     case -1:
6027 	message(0, errno, "failed communicating with local client");
6028 	goto fatal;
6029     }
6030 
6031     message(1, 0, "connection closed");
6032 
6033     closesocket(clientFd);
6034     closesocket(serverFd);
6035     freeMsgBuf(msg);
6036     removeHandler(&(argP->addr));
6037     free(argP);
6038     incrActiveCount(-1);
6039 #ifdef WIN32
6040     if (!inLine) _endthread();
6041 #endif
6042     return;
6043 
6044 fatal:
6045     if (serverFd != -1) closesocket(serverFd);
6046     if (clientFd != -1) closesocket(clientFd);
6047     if (exponent) free(exponent);
6048     if (dhKey) free(dhKey);
6049     if (sessionKeyStr && sessionKeyStr != secretKeyStr) free(sessionKeyStr);
6050     if (secretKeyStr) free(secretKeyStr);
6051     freeMsgBuf(msg);
6052     removeHandler(&(argP->addr));
6053     free(argP);
6054     incrActiveCount(-1);
6055 #ifdef WIN32
6056     if (!inLine) _endthread();
6057 #endif
6058     inLine = 0; /* Use it to shut up the compiler ... */
6059     return;
6060 }
6061 
6062 /*
6063 ** serverListener
6064 **
6065 ** This is top-level server routine that listens for incoming connections
6066 ** and then spawns an individual process/thread the handle that single
6067 ** client.
6068 */
6069 
6070 void
serverListener(unsigned short * portPtr)6071 serverListener(unsigned short *portPtr)
6072 {
6073     int listenFd;
6074     int clientFd;
6075     struct sockaddr_in addr;
6076     int addrLen;
6077     char ipBuf[IP_BUF_SIZE];
6078 
6079 
6080     /* Create the listener socket */
6081 
6082     if ((listenFd = makeListener(portPtr, ListenIp, 0, MAX_LISTEN)) == -1)
6083     {
6084 	message(0, 0, "server can't listen on port %hu", *portPtr);
6085 	exit(EXIT_FAILURE);
6086     }
6087 
6088     /* Detach from terminal, if requested */
6089 
6090     if (IsDetached)
6091     {
6092 	message(3, 0, "detaching from terminal");
6093 	makeDetached();
6094     }
6095 
6096     /* Change user ID, if required */
6097 
6098     switchUser();
6099 
6100     while (1)
6101     {
6102 	message(1, 0, "waiting for connection on port %hu", *portPtr);
6103 
6104 	memset(&addr, 0, sizeof(addr));
6105 	addrLen = sizeof(struct sockaddr_in);
6106 	if ((clientFd = accept(listenFd, (struct sockaddr *)&addr, &addrLen)) < 0)
6107 	{
6108 	    message(0, errno, "error on accept");
6109 	}
6110 	else
6111 	{
6112 	    message(1, 0, "accepted connection from %s", ipString(addr.sin_addr, ipBuf));
6113 
6114 	    /* Set the "don't linger on close" option */
6115 
6116 	    setNoLinger(clientFd);
6117 
6118 	    /* Set "keep alive" to reap defunct connections */
6119 
6120 	    setKeepAlive(clientFd);
6121 
6122 	    /* Create the handler process/thread */
6123 
6124 	    spawnHandler(server, listenFd, clientFd, Debug, &addr, 0);
6125 	}
6126     }
6127 }
6128 
6129 /*
6130 ** serverInitiator
6131 **
6132 ** Initiates a connection back to a client host running in listen-mode.
6133 */
6134 
6135 void
serverInitiator(unsigned short * portPtr)6136 serverInitiator(unsigned short *portPtr)
6137 {
6138     unsigned short port = *portPtr;
6139     int clientFd = -1;
6140     struct timeval delay;
6141     fd_set testSet;
6142     int ready;
6143     unsigned short tries = ConnectAttempts;
6144     int forever = (ConnectAttempts == 0);
6145 
6146 
6147     /*
6148     ** Now is the time to detach, if we are going to do so.
6149     */
6150 
6151     if (IsDetached)
6152     {
6153 	message(3, 0, "detaching from terminal");
6154 	makeDetached();
6155     }
6156 
6157     /* Change user ID, if required */
6158 
6159     switchUser();
6160 
6161 
6162     while (forever || tries > 0)
6163     {
6164 	tries--;
6165 
6166 	message(2, 0, "initiating connection back to client at %s:%hu", ClientHost, port);
6167 
6168 	if ((clientFd = makeConnection(ClientHost, port, 0, 1, NULL, NULL, ServerConnectTimeout)) == -1)
6169 	{
6170 	    /*
6171 	    ** If the connection timed out then we will retry if necessary,
6172 	    ** otherwise it is a fatal error ...
6173 	    */
6174 
6175 	    if (errno == ETIMEDOUT)
6176 	    {
6177 		message(3, 0, "timed out connecting back to client, retrying");
6178 		continue;
6179 	    }
6180 	    else
6181 	    {
6182 		message(3, errno, "failed to connect back to client at %s:%hu", ClientHost, port);
6183 
6184 		/* We need to pause here to avoid continuous connection attempts */
6185 
6186 		message(4, 0, "sleeping for %hu seconds", ServerConnectTimeout);
6187 #ifdef WIN32
6188 		/* Sleeps are shorter on Windows! */
6189 
6190 		Sleep((unsigned long)ServerConnectTimeout * 1000);
6191 #else
6192 		sleep(ServerConnectTimeout);
6193 #endif
6194 		continue;
6195 	    }
6196 	}
6197 
6198 	message(2, 0, "connected to client");
6199 
6200 
6201 	/*
6202 	** Now we will wait until either there is data ready to
6203 	** read from the client or we exceed the timeout value.
6204 	*/
6205 
6206 	delay.tv_sec = AcceptConnectTimeout;
6207 	delay.tv_usec = 0;
6208 
6209 	FD_ZERO(&testSet);
6210 	FD_SET(clientFd, &testSet);
6211 
6212 	ready = select(clientFd + 1, &testSet, 0, 0, &delay);
6213 
6214 	if (ready == 0)
6215 	{
6216 	    message(3, 0, "timed out waiting for accepted connection from client");
6217 	    closesocket(clientFd);
6218 	    continue;
6219 	}
6220 
6221 	/* Check for error but ignore interrupted system calls */
6222 
6223 	if (ready < 0)
6224 	{
6225 	    if (errno != EINTR)
6226 	    {
6227 		message(0, errno, "error in select waiting for client to accept connection");
6228 		break;
6229 	    }
6230 	}
6231 	else
6232 	{
6233 	    /*
6234 	    ** The connection was successful so spawn the handler and
6235 	    ** reset the attempt count.
6236 	    */
6237 
6238 	    spawnHandler(server, -1, clientFd, 0, NULL, 0);
6239 	    tries = ConnectAttempts;
6240 	}
6241     }
6242 
6243     if (ConnectAttempts > 0 && tries == 0)
6244     {
6245 	message(0, errno, "maximum connection attempt tries (%hu) exhausted", ConnectAttempts);
6246     }
6247 
6248     closesocket(clientFd);
6249 
6250     /* Wait for all other threads to exit */
6251 
6252     waitForInactivity();
6253 }
6254 
6255 /*
6256 ** server
6257 **
6258 ** This is the server side of the Zebedee protocol. It should match the
6259 ** interactions in client(). Note that this routine IS thread-safe and
6260 ** should not call exit() directly.
6261 */
6262 
6263 void
server(FnArgs_t * argP)6264 server(FnArgs_t *argP)
6265 {
6266     int clientFd = argP->fd;
6267     int localFd = -1;
6268     unsigned short request = 0;
6269     unsigned short response = 0;
6270     unsigned short result = 0;
6271     unsigned short cmpInfo = CompressInfo;
6272     unsigned short keyBits = KeyLength;
6273     unsigned short port = 0;
6274     unsigned short protocol = DFLT_PROTOCOL;
6275     unsigned short maxSize = MaxBufSize;
6276     char clientDhKey[MAX_LINE_SIZE];
6277     char *exponent = NULL;
6278     char *dhKey = NULL;
6279     char *secretKeyStr = NULL;
6280     char *sessionKeyStr = NULL;
6281     int len = -1;
6282     MsgBuf_t *msg = NULL;
6283     unsigned long token = 0;
6284     unsigned char hdrData[HDR_SIZE_MAX];
6285     unsigned short hdrSize;
6286     struct sockaddr_in localAddr;
6287     struct sockaddr_in peerAddr;
6288     unsigned char clientNonce[NONCE_SIZE];
6289     unsigned char serverNonce[NONCE_SIZE];
6290     char *targetHost = TargetHost;
6291     char *idFile = NULL;
6292     int inLine = argP->inLine;
6293     int udpMode = argP->udpMode;    /* Overridden by client request */
6294     char ipBuf[IP_BUF_SIZE];
6295     unsigned short cksumLevel = CHECKSUM_NONE;
6296     SHA_INFO sha;
6297     int active = 0;
6298 
6299 
6300     active = incrActiveCount(1);
6301     if (MaxConnections > 0 && MaxConnections < active)
6302     {
6303         message(0, 0, "maximum number of concurrent connections exceeded");
6304         goto fatal;
6305     }
6306     message(3, 0, "server routine entered");
6307 
6308     /*
6309     ** Validate the client IP address, if required. Note that this also
6310     ** retrieves the client address information, which we may need later.
6311     */
6312 
6313     message(3, 0, "validating client IP address");
6314     if (!checkPeerForSocket(clientFd, &peerAddr))
6315     {
6316 	message(0, 0, "client connection from %s disallowed", ipString(peerAddr.sin_addr, ipBuf));
6317 	goto fatal;
6318     }
6319 
6320     /* Read protocol version */
6321 
6322     message(3, 0, "reading protocol version ");
6323 
6324     if (readUShort(clientFd, &request) != 2)
6325     {
6326 	message(0, errno, "failed reading protocol version");
6327 	goto fatal;
6328     }
6329 
6330     message(3, 0, "read protocol version %#hx", request);
6331 
6332     /*
6333     ** If the client protocol version matches one that we can support
6334     ** then we just echo it back otherwise we send back the highest
6335     ** that we can support. If the protocol is "locked" then we will
6336     ** only ever send back our default protocol.
6337     */
6338 
6339     if (LockProtocol)
6340     {
6341 	if (request != DFLT_PROTOCOL)
6342 	{
6343 	    message(0, errno, "failed due to client requesting incompatible protocol version (%#hx), server locked to version %#hx ", request, DFLT_PROTOCOL);
6344 	    goto fatal;
6345 	}
6346 	else
6347 	{
6348 	    /* Set to our default */
6349 	    protocol = DFLT_PROTOCOL;
6350 	}
6351     }
6352     else if (request <= PROTOCOL_V202 && request >= PROTOCOL_V200)
6353     {
6354 	/* These we can support directly, as requested */
6355 	protocol = request;
6356     }
6357     else if (DropUnknownProtocol)
6358     {
6359 	/* Don't even try to handle unknown protocol versions */
6360 
6361 	message(0, 0, "client requested unknown protocol version (%#hx), dropped by server", request);
6362 	goto fatal;
6363     }
6364     else
6365     {
6366 	/* Set to highest we can support */
6367 	protocol = DFLT_PROTOCOL;
6368     }
6369 
6370     message(3, 0, "replying with protocol version %#hx", protocol);
6371 
6372     if (writeUShort(clientFd, protocol) != 2)
6373     {
6374 	message(0, errno, "failed writing protocol version back to client");
6375 	goto fatal;
6376     }
6377 
6378     /* Set the size of the protocol header block */
6379 
6380     switch (protocol)
6381     {
6382     case PROTOCOL_V200:
6383 	    hdrSize = HDR_SIZE_V200;
6384 	    break;
6385     case PROTOCOL_V201:
6386 	    hdrSize = HDR_SIZE_V201;
6387 	    break;
6388     default:
6389 	    hdrSize = HDR_SIZE_V202;
6390 	    break;
6391     }
6392 
6393     if (readData(clientFd, hdrData, hdrSize) != hdrSize)
6394     {
6395 	message(0, errno, "failed reading protocol header from client");
6396 	goto fatal;
6397     }
6398 
6399     if (protocol >= PROTOCOL_V202)
6400     {
6401 	/*
6402 	** This adds a message checksum to allows us to detect if
6403 	** somebody has tampered with the data "in flight".
6404 	** The header data sent and received is hashed in order to
6405 	** obtain the initial checksum seed.
6406 	*/
6407 	sha_init(&sha);
6408 	sha_update(&sha, hdrData, hdrSize);
6409     }
6410 
6411     udpMode = (headerGetUShort(hdrData, HDR_OFFSET_FLAGS) == HDR_FLAG_UDPMODE);
6412     if ((udpMode && !UdpMode) || (!udpMode && !TcpMode))
6413     {
6414 	message(0, 0, "client requested %s mode tunnel to %s mode server",
6415 		(udpMode ? "UDP" : "TCP"), (udpMode ? "TCP" : "UDP"));
6416 	headerSetUShort(hdrData, (udpMode ? 0 : HDR_FLAG_UDPMODE), HDR_OFFSET_FLAGS);
6417     }
6418     else
6419     {
6420 	message(3, 0, "replying with %s mode", (udpMode ? "UDP" : "TCP"));
6421 	headerSetUShort(hdrData, (udpMode ? HDR_FLAG_UDPMODE : 0), HDR_OFFSET_FLAGS);
6422     }
6423 
6424     maxSize = headerGetUShort(hdrData, HDR_OFFSET_MAXSIZE);
6425     message(3, 0, "read buffer size request of %hu", maxSize);
6426 
6427     /* Take the smallest of the client and server values */
6428 
6429     maxSize = MIN(maxSize, MaxBufSize);
6430 
6431     message(3, 0, "replying with buffer size %hu", maxSize);
6432     headerSetUShort(hdrData, maxSize, HDR_OFFSET_MAXSIZE);
6433 
6434     request = headerGetUShort(hdrData, HDR_OFFSET_CMPINFO);
6435     message(3, 0, "read compression level %#hx", request);
6436 
6437     /*
6438     ** Use the minimum of the client's and server's compression levels.
6439     **
6440     ** Note that all values for zlib compression are less than those for
6441     ** bzip2 compression so if a client requests bzip2 compression but
6442     ** the server doesn't support it then the protocol degrades naturally
6443     ** to zlib.
6444     */
6445 
6446     if (request < cmpInfo)
6447     {
6448 	cmpInfo = request;
6449 	response = request;
6450     }
6451     else
6452     {
6453 	response = cmpInfo;
6454     }
6455 
6456     message(3, 0, "replying with compression level %#hx", response);
6457     headerSetUShort(hdrData, response, HDR_OFFSET_CMPINFO);
6458 
6459     request = headerGetUShort(hdrData, HDR_OFFSET_PORT);
6460     message(3, 0, "read port %hu", request);
6461 
6462     memset(&localAddr, 0, sizeof(localAddr));
6463     if (protocol >= PROTOCOL_V201)
6464     {
6465 	localAddr.sin_addr.s_addr = htonl(headerGetULong(hdrData, HDR_OFFSET_TARGET) & 0xffffffff);
6466 	message(3, 0, "read target address %s", ipString(localAddr.sin_addr, ipBuf));
6467     }
6468 
6469     /*
6470     ** The server should not, in general, redirect arbitrary ports because
6471     ** the remote client will appear to the target service to have
6472     ** connected from the server machine -- and may assume that greater
6473     ** access should be allowed as a result. So we check the requested
6474     ** port and host against the list of allowed port/host combinations.
6475     ** If the request is not granted then we send zero back to the client
6476     ** otherwise we carry on and attempt to open a connection to that
6477     ** port on the target host. If that succeeds we will send back the
6478     ** requested port number or zero if it fails.
6479     */
6480 
6481     message(3, 0, "checking if redirection is allowed");
6482 
6483     if (allowRedirect(request, &localAddr, &peerAddr, udpMode, &targetHost, &idFile))
6484     {
6485 	message(3, 0, "allowed redirection request to %s:%hu", targetHost, request);
6486 
6487 	/*
6488 	** Attempt to open connection -- if this fails then we write back
6489 	** zero to the client otherwise we send back the requested port
6490 	** number.
6491 	*/
6492 
6493 	message(3, 0, "opening connection to port %hu on %s", request, targetHost);
6494 
6495 	memset(&localAddr, 0, sizeof(localAddr));
6496 	if ((localFd = makeConnection(targetHost, request, udpMode, 0,
6497 				      (Transparent ? &peerAddr : NULL),
6498 				      &localAddr, TargetConnectTimeout)) == -1)
6499 	{
6500 	    port = 0;
6501 	    message(0, errno, "failed connecting to port %hu on %s", request, targetHost);
6502 	    headerSetUShort(hdrData, 0, HDR_OFFSET_PORT);
6503 	}
6504 	else
6505 	{
6506 	    /* All OK -- echo back port number */
6507 
6508 	    port = request;
6509 	    message(3, 0, "made connection to target -- writing back %hu to client", port);
6510 	    headerSetUShort(hdrData, port, HDR_OFFSET_PORT);
6511 	}
6512     }
6513     else
6514     {
6515 	message(0, 0, "client requested redirection to a disallowed target (%s:%hu/%s)", ipString(localAddr.sin_addr, ipBuf), request, (udpMode ? "udp" : "tcp"));
6516 	headerSetUShort(hdrData, 0, HDR_OFFSET_PORT);
6517     }
6518 
6519     request = headerGetUShort(hdrData, HDR_OFFSET_KEYLEN);
6520     message(3, 0, "client requested key length %hu", request);
6521 
6522     /*
6523     ** Use the minimum of the client and server values or MinKeyLength,
6524     ** whichever is the greater.
6525     */
6526 
6527     if (request > keyBits)
6528     {
6529 	response = keyBits;
6530     }
6531     else if (request >= MinKeyLength)
6532     {
6533 	keyBits = request;
6534 	response = request;
6535     }
6536     else
6537     {
6538 	keyBits = MinKeyLength;
6539 	response = MinKeyLength;
6540     }
6541 
6542     message(3, 0, "replying with key length %hu", response);
6543     headerSetUShort(hdrData, response, HDR_OFFSET_KEYLEN);
6544 
6545     token = headerGetULong(hdrData, HDR_OFFSET_TOKEN);
6546     message(3, 0, "client requested key reuse token %#lx", token);
6547 
6548     if (token != 0)
6549     {
6550 	/*
6551 	** Search for matching token. If not found then allocate
6552 	** a new one.
6553 	*/
6554 
6555 	if ((secretKeyStr = findKeyByToken(&ServerKeyList, token, &peerAddr, &localAddr, port)) == NULL)
6556 	{
6557 	    token = generateToken(&ServerKeyList, token);
6558 	}
6559     }
6560     headerSetULong(hdrData, token, HDR_OFFSET_TOKEN);
6561     message(3, 0, "returned key reuse token %#lx", token);
6562 
6563     memcpy(clientNonce, hdrData + HDR_OFFSET_NONCE, NONCE_SIZE);
6564     message(3, 0, "received client nonce %02x%02x...", clientNonce[0], clientNonce[1]);
6565 
6566     generateNonce(serverNonce);
6567     message(3, 0, "sending server nonce %02x%02x...", serverNonce[0], serverNonce[1]);
6568     memcpy(hdrData + HDR_OFFSET_NONCE, serverNonce, NONCE_SIZE);
6569 
6570     if (protocol >= PROTOCOL_V202)
6571     {
6572 	cksumLevel = headerGetUShort(hdrData, HDR_OFFSET_CHECKSUM);
6573 	if (cksumLevel > ChecksumLevel)
6574 	{
6575 	    cksumLevel = ChecksumLevel;
6576 	}
6577 	else if (cksumLevel < MinChecksumLevel)
6578 	{
6579 	    cksumLevel = MinChecksumLevel;
6580 	}
6581 	message(3, 0, "replying with checksum level %hu", cksumLevel);
6582 	headerSetUShort(hdrData, cksumLevel, HDR_OFFSET_CHECKSUM);
6583     }
6584     else
6585     {
6586 	cksumLevel = CHECKSUM_NONE;
6587     }
6588 
6589     if (writeData(clientFd, hdrData, hdrSize) != hdrSize)
6590     {
6591 	message(0, errno, "failed writing protocol header back to client");
6592 	goto fatal;
6593     }
6594 
6595     /* Quit now if we have no local connection */
6596 
6597     if (port == 0)
6598     {
6599 	message(0, 0, "initial protocol exchange failed");
6600 	goto fatal;
6601     }
6602 
6603     /* Allocate message buffer */
6604 
6605     if ((msg = makeMsgBuf(maxSize, cmpInfo, cksumLevel)) == NULL)
6606     {
6607 	message(0, errno, "server failed to allocate message buffer");
6608 	goto fatal;
6609     }
6610 
6611     /* Set the checksum seeds, if necessary */
6612 
6613     if (protocol >= PROTOCOL_V202)
6614     {
6615 	sha_update(&sha, hdrData, hdrSize);
6616 	sha_final(&sha);
6617 	sha.digest[0] = BUGHTONL(sha.digest[0]);
6618 	sha.digest[1] = BUGHTONL(sha.digest[1]);
6619 	sha.digest[2] = BUGHTONL(sha.digest[2]);
6620 	sha.digest[3] = BUGHTONL(sha.digest[3]);
6621 	sha.digest[4] = BUGHTONL(sha.digest[4]);
6622 	memcpy(msg->inSeed, &sha.digest, sizeof(sha.digest));
6623 	memcpy(msg->outSeed, &sha.digest, sizeof(sha.digest));
6624     }
6625 
6626     /*
6627     ** If the session token requested by the client resulted in us
6628     ** finding a key string then we will perform a challenge-response
6629     ** to verify that there really is a shared key ...
6630     */
6631 
6632     if (secretKeyStr != NULL)
6633     {
6634 	sessionKeyStr = generateSessionKey(secretKeyStr, clientNonce,
6635 					   serverNonce, keyBits);
6636 
6637 	message(3, 0, "session key ends '...%s'", sessionKeyStr + strlen(sessionKeyStr) - 4);
6638 
6639 	msg->bfWrite = setupBlowfish(sessionKeyStr, keyBits);
6640 	msg->bfRead = setupBlowfish(sessionKeyStr, keyBits);
6641 
6642 	memset(sessionKeyStr, 0, strlen(sessionKeyStr));
6643 	free(sessionKeyStr);
6644 	sessionKeyStr = NULL;
6645 	memset(secretKeyStr, 0, strlen(secretKeyStr));
6646 	free(secretKeyStr);
6647 	secretKeyStr = NULL;
6648 
6649 	if (!serverPerformChallenge(clientFd, msg))
6650 	{
6651 	    message(0, 0, "challenge/response failed to validate shared key (session token = %#08x)", token);
6652 	    goto fatal;
6653 	}
6654     }
6655 
6656     /*
6657     ** ELSE ...
6658     ** If the key length is zero then we can omit all of the
6659     ** key-exchange traffic.
6660     */
6661 
6662     else if (keyBits > 0)
6663     {
6664 	/*
6665 	** Send the Diffie-Hellman generator
6666 	**
6667 	** The server decides the generator and modulus because to avoid
6668 	** "man-in-the-middle" attacks you are more likely to want to know
6669 	** the identity of the server from the client than vice-versa. This
6670 	** lets the server control its public key identity better.
6671 	*/
6672 
6673 	message(3, 0, "sending DH generator '%s'", Generator);
6674 
6675 	assert((len = strlen(Generator) + 1) <= MAX_LINE_SIZE);
6676 	setMsgBuf(msg, Generator, strlen(Generator) + 1);
6677 
6678 	if (writeMessage(clientFd, msg) != len)
6679 	{
6680 	    message(0, errno, "failed writing generator to client");
6681 	    goto fatal;
6682 	}
6683 
6684 	message(3, 0, "sent generator");
6685 
6686 	/* Send the Diffie-Hellman modulus */
6687 
6688 	message(3, 0, "sending DH modulus '%s'", Modulus);
6689 
6690 	assert((len = strlen(Modulus) + 1) <= MAX_LINE_SIZE);
6691 	setMsgBuf(msg, Modulus, strlen(Modulus) + 1);
6692 
6693 	if (writeMessage(clientFd, msg) != len)
6694 	{
6695 	    message(0, errno, "failed writing modulus to client");
6696 	    goto fatal;
6697 	}
6698 
6699 	message(3, 0, "sent modulus", Modulus);
6700 
6701 
6702 	/*
6703 	** Calculate our DH key
6704 	**
6705 	** This requires that we first generate our private key (the
6706 	** the exponent) and then perform the modular exponentiation
6707 	** to generate the public key.
6708 	*/
6709 
6710 	message(3, 0, "generating private key");
6711 
6712 	if ((exponent = generateKey(&peerAddr, &localAddr, port)) == NULL)
6713 	{
6714 	    message(0, errno, "can't generate private key");
6715 	    goto fatal;
6716 	}
6717 
6718 	message(3, 0, "private key generated");
6719 
6720 	message(3, 0, "generating public DH key");
6721 
6722 	if ((dhKey = diffieHellman(Generator, Modulus, exponent)) == NULL)
6723 	{
6724 	    message(0, errno, "can't generate public DH key");
6725 	    goto fatal;
6726 	}
6727 
6728 	message(3, 0, "public DH key is '%s'", dhKey);
6729 
6730 	/* Now send the DH key */
6731 
6732 	message(3, 0, "sending public DH key");
6733 
6734 	assert((len = strlen(dhKey) + 1) <= MAX_LINE_SIZE);
6735 	setMsgBuf(msg, dhKey, strlen(dhKey) + 1);
6736 
6737 	if (writeMessage(clientFd, msg) != len)
6738 	{
6739 	    message(0, errno, "failed writing DH key to client");
6740 	    goto fatal;
6741 	}
6742 
6743 	message(3, 0, "sent public DH key");
6744 
6745 
6746 	/* Read the client DH key */
6747 
6748 	message(3, 0, "reading client DH key");
6749 
6750 	if (readMessage(clientFd, msg, MAX_LINE_SIZE) <= 0)
6751 	{
6752 	    message(0, errno, "failed reading client DH key");
6753 	    goto fatal;
6754 	}
6755 	getMsgBuf(msg, clientDhKey, MAX_LINE_SIZE);
6756 
6757 	message(3, 0, "accepted client DH key '%s'", clientDhKey);
6758 
6759 
6760 	/*
6761 	** If requested, check this against a list of "known" keys
6762 	** to validate the client identity.
6763 	*/
6764 
6765 	if (idFile == NULL)
6766 	{
6767 	    /* Use the default file if no specific file was given */
6768 	    idFile = IdentityFile;
6769 	}
6770 
6771 	if (idFile)
6772 	{
6773 	    message(3, 0, "checking key against identity file '%s'", idFile);
6774 
6775 	    if (!(result = checkIdentity(idFile, Generator, Modulus, clientDhKey)))
6776 	    {
6777 		message(0, 0, "client's key identity not found in '%s'", idFile);
6778 		goto fatal;
6779 	    }
6780 	}
6781 
6782 	/* Now generate the shared secret key */
6783 
6784 	message(3, 0, "generating shared secret key");
6785 
6786 	secretKeyStr = diffieHellman(clientDhKey, Modulus, exponent);
6787 
6788 	message(3, 0, "shared key ends '...%s'", secretKeyStr + strlen(secretKeyStr) - 4);
6789 
6790 	sessionKeyStr = generateSessionKey(secretKeyStr, clientNonce,
6791 					   serverNonce, keyBits);
6792 
6793 	message(3, 0, "session key ends '...%s'", sessionKeyStr + strlen(sessionKeyStr) - 4);
6794 
6795 	message(3, 0, "initialising encryption state");
6796 
6797 	msg->bfWrite = setupBlowfish(sessionKeyStr, keyBits);
6798 	msg->bfRead = setupBlowfish(sessionKeyStr, keyBits);
6799 
6800 	/* Clear unneeded values */
6801 
6802 	free(dhKey);
6803 	dhKey = NULL;
6804 	memset(exponent, 0, strlen(exponent));
6805 	free(exponent);
6806 	exponent = NULL;
6807 
6808 	/*
6809 	** Having established the encrypted channel we now perform a mutual
6810 	** challenge/response dialogue in order to guard against being spoofed
6811 	** by a replay attack if we are using a static key.
6812 	*/
6813 
6814 	if (!serverPerformChallenge(clientFd, msg))
6815 	{
6816 	    goto fatal;
6817 	}
6818 
6819 	/*
6820 	** If a new session token was allocated then update the secret
6821 	** key list.
6822 	*/
6823 
6824 	if (token != 0)
6825 	{
6826 	    message(3, 0, "new reusable key token established (%#lx)", token);
6827 	    addKeyInfoToList(&ServerKeyList, token, secretKeyStr);
6828 	}
6829 
6830 	if (sessionKeyStr != secretKeyStr)
6831 	{
6832 	    memset(sessionKeyStr, 0, strlen(sessionKeyStr));
6833 	    free(sessionKeyStr);
6834 	    sessionKeyStr = NULL;
6835 	}
6836 	memset(secretKeyStr, 0, strlen(secretKeyStr));
6837 	free(secretKeyStr);
6838 	secretKeyStr = NULL;
6839     }
6840     else
6841     {
6842 	message(3, 0, "key length is zero, omitting key exchange");
6843 	if (IdentityFile != NULL)
6844 	{
6845 	    message(1, 0, "Warning: agreed key length is zero, no identity checking performed");
6846 	}
6847     }
6848 
6849     message(1, 0, "tunnel established to target %s, port %hu", targetHost, port);
6850     message(2, 0, "compression level %#hx, key length %hu", cmpInfo, keyBits);
6851 
6852     /* Now loop handling i/o */
6853 
6854     message(3, 0, "entering filter loop");
6855 
6856     switch (filterLoop(localFd, clientFd, msg, &localAddr, &peerAddr, localFd, udpMode))
6857     {
6858     case 1:
6859 	message(0, errno, "failed communicating with remote client");
6860 	goto fatal;
6861 
6862     case -1:
6863 	message(0, errno, "failed communicating with local server");
6864 	goto fatal;
6865     }
6866 
6867     errno = 0;
6868     message(1, 0, "connection closed");
6869 
6870     closesocket(clientFd);
6871     closesocket(localFd);
6872     if (targetHost != NULL && targetHost != TargetHost) free(targetHost);
6873     freeMsgBuf(msg);
6874     free(argP);
6875     incrActiveCount(-1);
6876 #ifdef WIN32
6877     if (!inLine) _endthread();
6878 #endif
6879     return;
6880 
6881 fatal:
6882     if (clientFd != -1) closesocket(clientFd);
6883     if (localFd != -1) closesocket(localFd);
6884     if (targetHost != NULL && targetHost != TargetHost) free(targetHost);
6885     if (exponent) free(exponent);
6886     if (dhKey) free(dhKey);
6887     if (sessionKeyStr && sessionKeyStr != secretKeyStr) free(sessionKeyStr);
6888     if (secretKeyStr) free(secretKeyStr);
6889     freeMsgBuf(msg);
6890     free(argP);
6891     incrActiveCount(-1);
6892 #ifdef WIN32
6893     if (!inLine) _endthread();
6894 #endif
6895     inLine = 0; /* Use it to shut up the compiler ... */
6896 }
6897 
6898 /*****************************\
6899 **			     **
6900 **  Option Parsing Routines  **
6901 **			     **
6902 \*****************************/
6903 
6904 /*
6905 ** scanPortRange
6906 **
6907 ** Parse a port range specifier and place the high and low ends of the
6908 ** range in hiP and loP. A range can be two shorts integers separated by
6909 ** a "-" -- for example "5900-5910", a single number or a symbolic port name.
6910 ** In the latter two cases both hiP and loP are set the same. If the range
6911 ** is suffixed by /tcp or /udp then the typeP is set accordingly otherwise
6912 ** it is set to both TCP and UDP.
6913 **
6914 ** If either loP or hiP are NULL the corresponding value is not set.
6915 ** The command always returns the vale of the low port.
6916 */
6917 
6918 unsigned short
scanPortRange(const char * str,unsigned short * loP,unsigned short * hiP,unsigned short * typeP)6919 scanPortRange(const char *str, unsigned short *loP, unsigned short *hiP, unsigned short *typeP)
6920 {
6921     struct servent *entry = NULL;
6922     unsigned short loVal = 0;
6923     unsigned short hiVal = 0;
6924     char portName[MAX_LINE_SIZE];
6925     char *slash = NULL;
6926     unsigned short type = ENDPTLIST_ANY;
6927 
6928 
6929     if ((slash = strchr(str, '/')) != NULL)
6930     {
6931 	if (!strcasecmp(slash, "/tcp"))
6932 	{
6933 	    type = ENDPTLIST_TCP;
6934 	}
6935 	else if (!strcasecmp(slash, "/udp"))
6936 	{
6937 	    type = ENDPTLIST_UDP;
6938 	}
6939 	else
6940 	{
6941 	    message(0, 0, "invalid port type (%s)", slash);
6942 	    return 0;
6943 	}
6944     }
6945     if (typeP) *typeP = type;
6946 
6947     switch (sscanf(str, "%hu-%hu", &loVal, &hiVal))
6948     {
6949     case 0:
6950 	break;
6951 
6952     case 1:
6953 	hiVal = loVal;
6954 
6955 	/* Fall through */
6956 
6957     case 2:
6958 	if (hiVal < loVal)
6959 	{
6960 	    hiVal ^= loVal;
6961 	    hiVal = hiVal ^ loVal;
6962 	    hiVal ^= loVal;
6963 	}
6964 
6965 	if (hiVal != loVal && !hiP)
6966 	{
6967 	    message(0, 0, "port range found where single value expected");
6968 	    return 0;
6969 	}
6970 
6971 	if (loP) *loP = loVal;
6972 	if (hiP) *hiP = hiVal;
6973 
6974 	return loVal;
6975     }
6976 
6977     if (sscanf(str, "%[^/]", portName) != 1)
6978     {
6979 	message(0, 0, "missing port name");
6980 	return 0;
6981     }
6982 
6983     if ((entry = getservbyname(portName, (type == ENDPTLIST_UDP ? "udp" : "tcp"))) == NULL)
6984     {
6985 	message(0, errno, "can't find port name entry for '%s'", portName);
6986 	return 0;
6987     }
6988 
6989     loVal = ntohs(entry->s_port);
6990     if (loP) *loP = loVal;
6991     if (hiP) *hiP = loVal;
6992 
6993     return loVal;
6994 }
6995 
6996 /*
6997 ** setBoolean
6998 **
6999 ** Parse a boolean value (either "true" or "false") and set the supplied
7000 ** result appropriately.
7001 */
7002 
7003 void
setBoolean(char * value,int * resultP)7004 setBoolean(char *value, int *resultP)
7005 {
7006     if (strcasecmp(value, "true") == 0)
7007     {
7008 	*resultP = 1;
7009     }
7010     else if (strcasecmp(value, "false") == 0)
7011     {
7012 	*resultP = 0;
7013     }
7014     else
7015     {
7016 	message(0, 0, "can't parse boolean value '%s'", value);
7017     }
7018 }
7019 
7020 /*
7021 ** setUShort
7022 **
7023 ** Parse and set an unsigned short value
7024 */
7025 
7026 void
setUShort(char * value,unsigned short * resultP)7027 setUShort(char *value, unsigned short *resultP)
7028 {
7029     if (sscanf(value, "%hu", resultP) != 1)
7030     {
7031 	message(0, 0, "can't parse unsigned short value '%s'", value);
7032     }
7033 }
7034 
7035 /*
7036 ** setPort
7037 **
7038 ** Parse a port name or number and set an unsigned short value
7039 */
7040 
7041 void
setPort(char * value,unsigned short * resultP)7042 setPort(char *value, unsigned short *resultP)
7043 {
7044     unsigned short port;
7045 
7046 
7047     port = scanPortRange(value, NULL, NULL, NULL);
7048     if (port == 0)
7049     {
7050 	message(0, 0, "can't parse port value '%s' key", value);
7051     }
7052     else
7053     {
7054 	*resultP = port;
7055     }
7056 }
7057 
7058 /*
7059 ** newEndPtList
7060 **
7061 ** Allocate a new EndPtList_t structure (or list of structures if there are
7062 ** multiple addresses for the supplied host name).
7063 */
7064 
7065 EndPtList_t *
newEndPtList(unsigned short lo,unsigned short hi,char * host,char * idFile,char * peer,unsigned short type)7066 newEndPtList(unsigned short lo,
7067 	     unsigned short hi,
7068 	     char *host,
7069 	     char *idFile,
7070 	     char *peer,
7071 	     unsigned short type)
7072 {
7073     EndPtList_t *new = NULL;
7074     struct sockaddr_in addr;
7075     struct in_addr *addrList = NULL;
7076     unsigned long mask = 0xffffffff;
7077 
7078 
7079     if (host && !getHostAddress(host, &addr, &addrList, &mask))
7080     {
7081 	message(0, 0, "can't resolve host or address '%s'", host);
7082 	return NULL;
7083     }
7084 
7085     if (addrList)
7086     {
7087 	new = allocEndPtList(lo, hi, host, idFile, peer, &(addr.sin_addr), addrList, mask, type);
7088     }
7089     else
7090     {
7091 	new = allocEndPtList(lo, hi, NULL, idFile, peer, NULL, NULL, 0xffffffff, type);
7092     }
7093 
7094     return new;
7095 }
7096 
7097 /*
7098 ** allocEndPtList
7099 **
7100 ** Allocate a new EndPtList_t structure and initialize the hi and lo elements.
7101 ** If host is not NULL then we populate the addr element with the supplied
7102 ** address and save the hostname.
7103 */
7104 
7105 EndPtList_t *
allocEndPtList(unsigned short lo,unsigned short hi,char * host,char * idFile,char * peer,struct in_addr * addrP,struct in_addr * addrList,unsigned long mask,unsigned short type)7106 allocEndPtList(unsigned short lo,
7107 	       unsigned short hi,
7108 	       char *host,
7109 	       char *idFile,
7110 	       char *peer,
7111 	       struct in_addr *addrP,
7112 	       struct in_addr *addrList,
7113 	       unsigned long mask,
7114 	       unsigned short type)
7115 {
7116     EndPtList_t *new = NULL;
7117 
7118 
7119     if ((new = (EndPtList_t *)malloc(sizeof(EndPtList_t))) == NULL)
7120     {
7121 	return NULL;
7122     }
7123 
7124     new->lo = lo;
7125     new->hi = hi;
7126     memset(&(new->addr), 0, sizeof(struct in_addr));
7127     new->host = NULL;
7128     new->idFile = NULL;
7129     new->peer = NULL;
7130     if (host && addrP)
7131     {
7132 	memcpy(&(new->addr.sin_addr), addrP, sizeof(struct in_addr));
7133 	if ((new->host = (char *)malloc(strlen(host) + 1)) == NULL)
7134 	{
7135 	    message(0, errno, "out of memory");
7136 	    return NULL;
7137 	}
7138 	strcpy(new->host, host);
7139     }
7140     if (idFile)
7141     {
7142     	if ((new->idFile =(char *)malloc(strlen(idFile) +1 )) == NULL)
7143 	{
7144 	    message(0, errno, "out of memory");
7145 	    return NULL;
7146 	}
7147 	strcpy(new->idFile, idFile);
7148     }
7149     if (peer)
7150     {
7151 	setAllowedPeer(peer, new->peer);
7152     }
7153 
7154     new->addrList = addrList;
7155     new->mask = mask;
7156     new->type = type;
7157 
7158     new->next = NULL;
7159 
7160     return new;
7161 }
7162 
7163 /*
7164 ** setEndPtList
7165 **
7166 ** Parse a list of white-space or comma separated ports or port ranges
7167 ** and add them to listP. Each element of this list is a low-high pair
7168 ** of port numbers. Where single ports are specified both low and high
7169 ** are the same. If zeroOk is false then a list containing port 0 is
7170 ** not allowed.
7171 **
7172 ** The host, idFile and peer parameters are passed on to newEndPtList.
7173 */
7174 
7175 void
setEndPtList(char * value,EndPtList_t ** listP,char * host,char * idFile,char * peer,int zeroOk)7176 setEndPtList(char *value,
7177 	     EndPtList_t **listP,
7178 	     char *host,
7179 	     char *idFile,
7180 	     char *peer,
7181 	     int zeroOk)
7182 {
7183     EndPtList_t *new = NULL;
7184     char *token = NULL;
7185     char tmpBuf[MAX_LINE_SIZE];
7186     char *tmpPtr = NULL;
7187     unsigned short lo = 0;
7188     unsigned short hi = 0;
7189     EndPtList_t *last = *listP;
7190     unsigned short type = ENDPTLIST_ANY;
7191 
7192 
7193     /* Set "last" to point to the last element of the list */
7194 
7195     while (last && last->next)
7196     {
7197 	last = last->next;
7198     }
7199 
7200     token = value;
7201     while (*token)
7202     {
7203 	/* Skip whitespace and commas */
7204 
7205 	while (*token && (isspace(*token) || *token == ',')) token++;
7206 	if (!*token) break;
7207 
7208 	/* Copy the token */
7209 
7210 	tmpPtr = tmpBuf;
7211 	while (*token && !(isspace(*token) || *token == ','))
7212 	{
7213 	    *tmpPtr++ = *token++;
7214 	}
7215 	*tmpPtr = '\0';
7216 
7217 	if (scanPortRange(tmpBuf, &lo, &hi, &type) != 0 || zeroOk)
7218 	{
7219 	    /* Allocate new list element */
7220 
7221 	    if ((new = newEndPtList(lo, hi, host, idFile, peer, type)) == NULL)
7222 	    {
7223 		message(0, errno, "failed allocating memory for port list");
7224 		exit(EXIT_FAILURE);
7225 	    }
7226 
7227 	    /* Add to the end of the list */
7228 
7229 	    if (*listP == NULL)
7230 	    {
7231 		*listP = new;
7232 	    }
7233 	    else
7234 	    {
7235 		last->next = new;
7236 	    }
7237 	    last = new;
7238 	}
7239 	else
7240 	{
7241 	    message(0, 0, "invalid port range '%s'", tmpBuf);
7242 	}
7243     }
7244 }
7245 
7246 /*
7247 ** setTarget
7248 **
7249 ** The target value is either of the form "hostname:portlist",
7250 ** "hostname:portlist?idfile", "hostname:portlist@addresse" or
7251 ** just a plain hostname. In the latter case it will use the
7252 ** default port list (held in AllowedDefault) and also become
7253 ** the default target. Note that
7254 ** the last named target becomes the default.
7255 */
7256 
7257 void
setTarget(char * value)7258 setTarget(char *value)
7259 {
7260     char target[MAX_LINE_SIZE];
7261     char portList[MAX_LINE_SIZE];
7262     char idFile[MAX_LINE_SIZE];
7263     char peerList[MAX_LINE_SIZE];
7264 
7265     if (sscanf(value, "%[^:]:%[^?]?%s", target, portList, idFile) == 3)
7266     {
7267     	setEndPtList(portList, &AllowedTargets, target, idFile, NULL, 0);
7268     }
7269     else if (sscanf(value, "%[^:]:%[^@]@%s", target, portList, peerList) == 3)
7270     {
7271     	setEndPtList(portList, &AllowedTargets, target, NULL, peerList, 0);
7272     }
7273     else if (sscanf(value, "%[^?]?%s", target, idFile) == 2)
7274     {
7275 	setEndPtList("0", &AllowedTargets, target, idFile, NULL, 1);
7276     }
7277     else if (sscanf(value, "%[^@]@%s", target, peerList) == 2)
7278     {
7279 	setEndPtList("0", &AllowedTargets, target, NULL, peerList, 1);
7280     }
7281     else if (sscanf(value, "%[^:]:%s", target, portList) == 2)
7282     {
7283 	setEndPtList(portList, &AllowedTargets, target, NULL, NULL, 0);
7284     }
7285     else
7286     {
7287 	setEndPtList("0", &AllowedTargets, target, NULL, NULL, 1);
7288     }
7289 
7290     /* Set the default target host */
7291 
7292     setString(target, &TargetHost);
7293 }
7294 
7295 /*
7296 ** setChecksum
7297 **
7298 ** The checksum value is in the range 0 to CHECKSUM_MAX.
7299 */
7300 
7301 void
setChecksum(char * value,unsigned short * resultP)7302 setChecksum(char *value, unsigned short *resultP)
7303 {
7304     if (sscanf(value, "%hu", resultP) != 1)
7305     {
7306 	message(0, 0, "can't parse checksum value '%s'", value);
7307 	return;
7308     }
7309 
7310     if (*resultP > CHECKSUM_MAX)
7311     {
7312 	message(1, 0, "WARNING: checksum value out of range, using maximum (%hu)", CHECKSUM_MAX);
7313 	*resultP = CHECKSUM_MAX;
7314     }
7315 }
7316 
7317 /*
7318 ** setTunnel
7319 **
7320 ** Parse a complete client tunnel specification.
7321 **
7322 ** A tunnel spec is of the form "clientports:targethost:targetports".
7323 */
7324 
7325 void
setTunnel(char * value)7326 setTunnel(char *value)
7327 {
7328     char clientList[MAX_LINE_SIZE];
7329     char hostName[MAX_LINE_SIZE];
7330     char targetList[MAX_LINE_SIZE];
7331 
7332 
7333     if (sscanf(value, "%[^:]:%[^:]:%[^:]", clientList, hostName, targetList) == 3)
7334     {
7335 	setEndPtList(clientList, &ClientPorts, NULL, NULL, NULL, 0);
7336 	if (ServerHost == NULL)
7337 	{
7338 	    setString(hostName, &ServerHost);
7339 	}
7340 	if (strcmp(hostName, "*") == 0)
7341 	{
7342 	    setEndPtList(targetList, &TargetPorts, NULL, NULL, NULL, 0);
7343 	}
7344 	else
7345 	{
7346 	    setEndPtList(targetList, &TargetPorts, hostName, NULL, NULL, 0);
7347 	}
7348     }
7349     else if (sscanf(value, "%[^:]:%[^:]", hostName, targetList) == 2)
7350     {
7351 	if (ServerHost == NULL)
7352 	{
7353 	    setString(hostName, &ServerHost);
7354 	}
7355 	if (strcmp(hostName, "*") == 0)
7356 	{
7357 	    setEndPtList(targetList, &TargetPorts, NULL, NULL, NULL, 0);
7358 	}
7359 	else
7360 	{
7361 	    setEndPtList(targetList, &TargetPorts, hostName, NULL, NULL, 0);
7362 	}
7363 	if (countPorts(TargetPorts) != 1)
7364 	{
7365 	    message(0, 0, "target port list contains more than one port");
7366 	    exit(EXIT_FAILURE);
7367 	}
7368     }
7369     else
7370     {
7371 	if (ServerHost == NULL || strcmp(ServerHost, "*") == 0)
7372 	{
7373 	    setString(value, &ServerHost);
7374 	}
7375 	else
7376 	{
7377 	    message(0, 0, "invalid tunnel specification '%s'", value);
7378 	}
7379     }
7380 }
7381 
7382 /*
7383 ** setAllowedPeer
7384 **
7385 ** The value is either of the form "address:portlist" or just a
7386 ** plain address. Addresses can be include CIDR mask specifications.
7387 */
7388 
7389 void
setAllowedPeer(char * value,EndPtList_t * peerList)7390 setAllowedPeer(char *value, EndPtList_t *peerList)
7391 {
7392     char addr[MAX_LINE_SIZE];
7393     char portList[MAX_LINE_SIZE];
7394 
7395 
7396     if (sscanf(value, "%[^:]:%s", addr, portList) == 2)
7397     {
7398 	setEndPtList(portList, &peerList, addr, NULL, NULL, 0);
7399     }
7400     else
7401     {
7402 	setEndPtList("0", &peerList, addr, NULL, NULL, 1);
7403     }
7404 }
7405 
7406 /*
7407 ** setString
7408 **
7409 ** Set a character string value
7410 */
7411 
7412 void
setString(char * value,char ** resultP)7413 setString(char *value, char **resultP)
7414 {
7415     if ((*resultP = (char *)malloc(strlen(value) + 1)) == NULL)
7416     {
7417 	message(0, errno, "failed allocating space for string value '%s'", value);
7418 	exit(EXIT_FAILURE);
7419     }
7420 
7421     strcpy(*resultP, value);
7422 }
7423 
7424 /*
7425 ** setLogFile
7426 **
7427 ** Open the specified log-file for append, closing any currently open
7428 ** log.
7429 **
7430 ** This routine recognises the special names "NULL" and "SYSLOG".
7431 */
7432 
7433 void
setLogFile(char * newFile)7434 setLogFile(char *newFile)
7435 {
7436     if (LogFileP != NULL)
7437     {
7438 	fclose(LogFileP);
7439     }
7440 
7441     if (strcmp(newFile, "NULL") == 0)
7442     {
7443 	LogFileType = LOGFILE_NULL;
7444 	LogFileP = NULL;
7445     }
7446     else if (strcmp(newFile, "SYSLOG") == 0)
7447     {
7448 	LogFileType = LOGFILE_SYSLOG;
7449 	LogFileP = NULL;
7450     }
7451     else
7452     {
7453 	LogFileType = LOGFILE_LOCAL;
7454 	if ((LogFileP = fopen(newFile, "a")) == NULL)
7455 	{
7456 	    message(0, errno, "can't open log file '%s'", newFile);
7457 	}
7458     }
7459 }
7460 
7461 /*
7462 ** setCmpInfo
7463 **
7464 ** Set compression type and level
7465 */
7466 
7467 void
setCmpInfo(char * value,unsigned short * resultP)7468 setCmpInfo(char *value, unsigned short *resultP)
7469 {
7470     unsigned short level = 0;
7471     unsigned short type = CMPTYPE_ZLIB;
7472 
7473     if (sscanf(value, "zlib:%hu", &level) == 1)
7474     {
7475 	type = CMPTYPE_ZLIB;
7476     }
7477     else if (sscanf(value, "bzip2:%hu", &level) == 1)
7478     {
7479 #ifdef DONT_HAVE_BZIP2
7480 	message(1, 0, "Warning: bzip2 compression not supported -- using zlib");
7481 	type = CMPTYPE_ZLIB;
7482 #else
7483 	type = CMPTYPE_BZIP2;
7484 
7485 	/* Compression level > 1 is useless as data buffers are too small */
7486 
7487 	if (level > 1) level = 1;
7488 #endif
7489     }
7490     else if (sscanf(value, "%hu", &level) == 1)
7491     {
7492 	type = CMPTYPE_ZLIB;
7493     }
7494     else
7495     {
7496 	message(0, 0, "invalid compression specification '%s'", value);
7497 	level = DFLT_CMP_LEVEL;
7498     }
7499 
7500     if (level > 9)
7501     {
7502 	message(0, 0, "compression level out of range (%s)", value);
7503 	level = DFLT_CMP_LEVEL;
7504     }
7505 
7506     if (level == 0)
7507     {
7508 	type = CMPTYPE_ZLIB;
7509     }
7510 
7511     *resultP = level;
7512     *resultP = SET_CMPTYPE(*resultP, type);
7513 }
7514 
7515 /*
7516 ** setStackSize
7517 **
7518 ** Set the thread stack size
7519 */
7520 
setStackSize(char * value)7521 void setStackSize(char *value)
7522 {
7523     unsigned short size;
7524 
7525     setUShort(value, &size);
7526     if (size < MIN_THREAD_STACK_KB)
7527     {
7528 	message(0, 0, "threadstacksize must be at least %hu kbytes", MIN_THREAD_STACK_KB);
7529     }
7530     else
7531     {
7532 	ThreadStackSize = size * 1024;
7533     }
7534 }
7535 
7536 /*
7537 ** readConfigFile
7538 **
7539 ** Read a configuration file. If the level is greater than MAX_LEVEL the
7540 ** recursive inclusion has probably been detected.
7541 */
7542 
7543 void
readConfigFile(const char * fileName,int level)7544 readConfigFile(const char *fileName, int level)
7545 {
7546     FILE *fp = NULL;
7547     char lineBuf[MAX_LINE_SIZE];
7548     char *curPtr = NULL;
7549     int size = 0;
7550     int len = 0;
7551     int lineNo = 0;
7552 
7553 
7554     message(2, 0, "reading config file '%s' at level %d", fileName, level);
7555 
7556     if (level > MAX_INCLUDE)
7557     {
7558 	message(0, 0, "include file nesting too deep (> %d)", MAX_INCLUDE);
7559 	return;
7560     }
7561 
7562     if ((fp = fopen(fileName, "r")) == NULL)
7563     {
7564 	message(0, errno, "can't open config file '%s'", fileName);
7565 	return;
7566     }
7567 
7568     curPtr = lineBuf;
7569     size = MAX_LINE_SIZE;
7570 
7571     while (fgets(curPtr, size, fp) != NULL)
7572     {
7573 	lineNo++;
7574 
7575 	len = strlen(curPtr) - 1;
7576 
7577 	/* Strip new-line */
7578 
7579 	if (curPtr[len] == '\n')
7580 	{
7581 	    curPtr[len--] = '\0';
7582 	}
7583 	else if (!feof(fp))
7584 	{
7585 	    message(0, 0, "line too long in config file '%s' at line %d", fileName, lineNo);
7586 	    break;
7587 	}
7588 
7589 	message(4, 0, "line %d: %s", lineNo, curPtr);
7590 
7591 	/* Look for continued lines */
7592 
7593 	if (curPtr[len] == '\\')
7594 	{
7595 	    curPtr[len] = '\0';
7596 	    size -= len;
7597 	    curPtr += len;
7598 
7599 	    /* Go and read some more */
7600 
7601 	    continue;
7602 	}
7603 
7604 	/* Reset for next time */
7605 
7606 	curPtr = lineBuf;
7607 	size = MAX_LINE_SIZE;
7608 
7609 	if (!parseConfigLine(lineBuf, level))
7610 	{
7611 	    message(0, 0, "invalid line in config file '%s' at line %d", fileName, lineNo);
7612 	}
7613     }
7614 
7615     fclose(fp);
7616 }
7617 
7618 /*
7619 ** parseConfigLine
7620 **
7621 ** Parse a single non-continued line from a config file.
7622 **
7623 ** Returns 1 if it was OK and 0 otherwise. Yes, I know that multiple
7624 ** returns are not terribly good practice but I don't much care here ...
7625 */
7626 
7627 int
parseConfigLine(const char * lineBuf,int level)7628 parseConfigLine(const char *lineBuf, int level)
7629 {
7630     char key[MAX_LINE_SIZE];
7631     char value[MAX_LINE_SIZE];
7632     char comment[2];
7633     char tmpBuf[MAX_LINE_SIZE];
7634     const char *s = NULL;
7635     char *t = NULL;
7636 
7637 
7638     /* Substitute field separator, if any */
7639 
7640     if (FieldSeparator)
7641     {
7642 	for (s = lineBuf, t = tmpBuf; *s; s++, t++)
7643 	{
7644 	    if (*s == *FieldSeparator)
7645 	    {
7646 		*t = ' ';
7647 	    }
7648 	    else
7649 	    {
7650 		*t = *s;
7651 	    }
7652 	}
7653 	*t = '\0';
7654 	lineBuf = tmpBuf;
7655     }
7656 
7657     /* Split into key-value pairs */
7658 
7659     *comment = '#';
7660     *key = '#';
7661     if (sscanf(lineBuf, "%s \"%[^\"]\" %1s", key, value, comment) < 2 &&
7662 	sscanf(lineBuf, "%s \'%[^\']' %1s", key, value, comment) < 2 &&
7663 	sscanf(lineBuf, "%s %s %1s", key, value, comment) < 2)
7664     {
7665 	/*
7666 	** Return OK if this is blank or a comment but flag an error
7667 	** otherwise (if it was blank 'key' will be unchanged -- still
7668 	** a comment character).
7669 	*/
7670 
7671 	if (*key != '#')
7672 	{
7673 	    return 0;
7674 	}
7675 	return 1;
7676     }
7677 
7678     /* Skip pure comment lines (that matched the scanf pattern) */
7679 
7680     if (*key == '#')
7681     {
7682 	return 1;
7683     }
7684 
7685     /* Third field if present must be a comment */
7686 
7687     if (*comment != '#')
7688     {
7689 	return 0;
7690     }
7691 
7692     message(4, 0, "key = '%s', value = '%s'", key, value);
7693 
7694     /* Now check for all possible keywords */
7695 
7696     if (!strcasecmp(key, "server")) setBoolean(value, &IsServer);
7697     else if (!strcasecmp(key, "detached")) setBoolean(value, &IsDetached);
7698     else if (!strcasecmp(key, "debug")) setBoolean(value, &Debug);
7699     else if (!strcasecmp(key, "compression")) setCmpInfo(value, &CompressInfo);
7700     else if (!strcasecmp(key, "keylength")) setUShort(value, &KeyLength);
7701     else if (!strcasecmp(key, "minkeylength")) setUShort(value, &MinKeyLength);
7702     else if (!strcasecmp(key, "maxbufsize")) setUShort(value, &MaxBufSize);
7703     else if (!strcasecmp(key, "verbosity")) setUShort(value, &LogLevel);
7704     else if (!strcasecmp(key, "serverport")) setPort(value, &ServerPort);
7705     else if (!strcasecmp(key, "localport")) setEndPtList(value, &ClientPorts, NULL, NULL, NULL, 0);
7706     else if (!strcasecmp(key, "clientport")) setEndPtList(value, &ClientPorts, NULL, NULL, NULL, 0);
7707     else if (!strcasecmp(key, "remoteport")) setEndPtList(value, &TargetPorts, NULL, NULL, NULL, 0);
7708     else if (!strcasecmp(key, "targetport")) setEndPtList(value, &TargetPorts, NULL, NULL, NULL, 0);
7709     else if (!strcasecmp(key, "remotehost")) setString(value, &ServerHost);
7710     else if (!strcasecmp(key, "serverhost")) setString(value, &ServerHost);
7711     else if (!strcasecmp(key, "command"))
7712     {
7713 	setString(value, &CommandString);
7714 	MultiUse = 0;
7715     }
7716     else if (!strcasecmp(key, "dropunknownprotocol")) setBoolean(value, &DropUnknownProtocol);
7717     else if (!strcasecmp(key, "lockprotocol")) setBoolean(value, &LockProtocol);
7718     else if (!strcasecmp(key, "keygencommand")) setString(value, &KeyGenCmd);
7719     else if (!strcasecmp(key, "logfile")) setLogFile(value);
7720     else if (!strcasecmp(key, "timestamplog")) setBoolean(value, &TimestampLog);
7721     else if (!strcasecmp(key, "multiuse")) setBoolean(value, &MultiUse);
7722     else if (!strcasecmp(key, "include")) readConfigFile(value, level+1);
7723     else if (!strcasecmp(key, "modulus")) setString(value, &Modulus);
7724     else if (!strcasecmp(key, "generator")) setString(value, &Generator);
7725     else if (!strcasecmp(key, "privatekey")) setString(value, &PrivateKey);
7726     else if (!strcasecmp(key, "checkidfile")) setString(value, &IdentityFile);
7727     else if (!strcasecmp(key, "checkaddress")) setAllowedPeer(value, AllowedPeers);
7728     else if (!strcasecmp(key, "redirect"))
7729     {
7730 	if (!strcasecmp(value, "none"))
7731 	{
7732 	    /*
7733 	    ** Special case of "none" disables default target ports.
7734 	    ** Yes, I know there's a potential memory leak. No, it doesn't
7735 	    ** matter!
7736 	    */
7737 
7738 	    AllowedDefault = NULL;
7739 	    setEndPtList("0-0", &AllowedDefault, NULL, NULL, NULL, 1);
7740 	}
7741 	else
7742 	{
7743 	    setEndPtList(value, &AllowedDefault, NULL, NULL, NULL, 0);
7744 	}
7745     }
7746     else if (!strcasecmp(key, "message")) message(1, 0, "%s", value);
7747     else if (!strcasecmp(key, "name")) setString(value, &Program);
7748     else if (!strcasecmp(key, "keygenlevel")) setUShort(value, &KeyGenLevel);
7749     else if (!strcasecmp(key, "redirecthost")) setString(value, &TargetHost);
7750     else if (!strcasecmp(key, "targethost")) setTarget(value);
7751     else if (!strcasecmp(key, "keylifetime")) setUShort(value, &KeyLifetime);
7752     else if (!strcasecmp(key, "udpmode"))
7753     {
7754 	setBoolean(value, &UdpMode);
7755 	TcpMode = !UdpMode;
7756     }
7757     else if (!strcasecmp(key, "ipmode"))
7758     {
7759 	if (!strcasecmp(value, "tcp"))
7760 	{
7761 	    TcpMode = 1;
7762 	    UdpMode = 0;
7763 	}
7764 	else if (!strcasecmp(value, "udp"))
7765 	{
7766 	    TcpMode = 0;
7767 	    UdpMode = 1;
7768 	}
7769 	else if (!strcasecmp(value, "both") || !strcasecmp(value, "mixed"))
7770 	{
7771 	    TcpMode = 1;
7772 	    UdpMode = 1;
7773 	}
7774 	else
7775 	{
7776 	    message(0, 0, "invalid value for ipmode: %s", value);
7777 	    return 0;
7778 	}
7779     }
7780     else if (!strcasecmp(key, "checksumlevel")) setChecksum(value, &ChecksumLevel);
7781     else if (!strcasecmp(key, "minchecksumlevel")) setChecksum(value, &MinChecksumLevel);
7782     else if (!strcasecmp(key, "udptimeout")) setUShort(value, &UdpTimeout);
7783     else if (!strcasecmp(key, "tcptimeout")) setUShort(value, &TcpTimeout);
7784     else if (!strcasecmp(key, "idletimeout"))
7785     {
7786 	setUShort(value, &TcpTimeout);
7787 	setUShort(value, &UdpTimeout);
7788     }
7789     else if (!strcasecmp(key, "localsource"))
7790     {
7791 	int yesNo = 0;
7792 	setBoolean(value, &yesNo);
7793 	setString(yesNo ? "127.0.0.1" : "0.0.0.0", &ListenIp);
7794     }
7795     else if (!strcasecmp(key, "listenip")) setString(value, &ListenIp);
7796     else if (!strcasecmp(key, "listenmode")) setBoolean(value, &ListenMode);
7797     else if (!strcasecmp(key, "clienthost")) setString(value, &ClientHost);
7798     else if (!strcasecmp(key, "connecttimeout")) setUShort(value, &AcceptConnectTimeout);
7799     else if (!strcasecmp(key, "serverconnecttimeout")) setUShort(value, &ServerConnectTimeout);
7800     else if (!strcasecmp(key, "targetconnecttimeout")) setUShort(value, &TargetConnectTimeout);
7801     else if (!strcasecmp(key, "acceptconnecttimeout")) setUShort(value, &AcceptConnectTimeout);
7802     else if (!strcasecmp(key, "connectattempts")) setUShort(value, &ConnectAttempts);
7803     else if (!strcasecmp(key, "readtimeout")) setUShort(value, &ReadTimeout);
7804     else if (!strcasecmp(key, "target")) setTarget(value);
7805     else if (!strcasecmp(key, "tunnel")) setTunnel(value);
7806     else if (!strcasecmp(key, "transparent")) setBoolean(value, &Transparent);
7807     else if (!strcasecmp(key, "httpproxy"))
7808     {
7809 	setString(value, &ProxyHost);
7810 	if (sscanf(value, "%[^:]:%hu", ProxyHost, &ProxyPort) != 2)
7811 	{
7812 	    message(0, 0, "invalid httpproxy specification: %s", value);
7813 	    ProxyHost = NULL;
7814 	}
7815     }
7816     else if (!strcasecmp(key, "httpproxyauth")) setString(base64Encode(value), &ProxyAuth);
7817     else if (!strcasecmp(key, "sharedkey")) setString(value, &SharedKey);
7818     else if (!strcasecmp(key, "sharedkeygencommand")) setString(value, &SharedKeyGenCmd);
7819     else if (!strcasecmp(key, "dumpdata")) setBoolean(value, &DumpData);
7820 #ifndef WIN32
7821     else if (!strcasecmp(key, "runasuser")) setRunAsUser(value);
7822 #endif
7823     else if (!strcasecmp(key, "threadstacksize")) setStackSize(value);
7824     else if (!strcasecmp(key, "bugcompatibility")) setUShort(value, &BugCompatibility);
7825     else if (!strcasecmp(key, "maxconnections")) setUShort(value, &MaxConnections);
7826     else
7827     {
7828 	return 0;
7829     }
7830 
7831     return 1;
7832 }
7833 
7834 /*
7835 ** cleanHexStr
7836 **
7837 ** Canonicalize a hexadecimal string converting to lower case and
7838 ** eliminating white-space.
7839 */
7840 
7841 char *
cleanHexString(char * str)7842 cleanHexString(char *str)
7843 {
7844     char *newStr = (char *)malloc(strlen(str) + 1);
7845     char *newp = newStr;
7846     char *oldp = str;
7847 
7848     while (*oldp)
7849     {
7850 	if (isxdigit(*oldp))
7851 	{
7852 	    *newp++ = tolower(*oldp++);
7853 	}
7854 	else if (isspace(*oldp))
7855 	{
7856 	    oldp++;
7857 	}
7858 	else
7859 	{
7860 	    message(0, 0, "invalid character in hex string '%s'", str);
7861 	    break;
7862 	}
7863     }
7864     *newp = '\0';
7865 
7866     return newStr;
7867 }
7868 
7869 /*
7870 ** usage
7871 **
7872 ** Print out usage message and exit
7873 */
7874 
7875 void
usage(void)7876 usage(void)
7877 {
7878     fprintf(stderr, "Zebedee -- A Secure Tunnel Program: Release %s\n", RELEASE_STR);
7879     fprintf(stderr, "Copyright (c) 1999-2005 by Neil Winton. All Rights Reserved.\n");
7880     fprintf(stderr,
7881 	    "This program is free software and may be distributed under the terms of the\n"
7882 	    "GNU General Public License, Version 2.\n");
7883     fprintf(stderr, "Zebedee comes with ABSOLUTELY NO WARRANTY.\n\n");
7884     fprintf(stderr,
7885 	    "Client: %s [options] [[clientports:]serverhost[:targetports]]\n"
7886 	    "Server: %s [options] -s [targethost]\n"
7887 	    "Key generation:  %s -p | -P [-f file]\n"
7888 	    "Hashing: %s -H string ... | -h [file ...]\n"
7889 #ifdef WIN32
7890 	    "Service: %s [options] -S [install[=config-file] | remove | run]\n",
7891 	    Program
7892 #endif
7893 	    , Program, Program, Program, Program);
7894 
7895     fprintf(stderr,
7896 	    "Options are:\n"
7897 	    "    -b address  Bind only this address when listening for connections\n"
7898 	    "    -C num      Set the number of attempts to connect back to client (default 1)\n"
7899 	    "    -c host     Server initiates connection to client host\n"
7900 	    "    -D          Debug mode\n"
7901 	    "    -d          Do not detach from terminal\n"
7902 	    "    -e command  Run command connected to local port (client only)\n"
7903 	    "    -F char     Specify additional field separator character\n"
7904 	    "    -f file     Read configuration file\n"
7905 	    "    -H          Generate hash of string values\n"
7906 	    "    -h          Generate hash of file contents\n"
7907 	    "    -K level    Specify the checksum level (default 2)\n"
7908 	    "    -k keybits  Specify key length in bits (default 128)\n"
7909  	    "    -L          Lock protocol negotiation\n"
7910 	    "    -l          Client listens for server connection\n"
7911 	    "    -m          Client accepts multiple connections (default)\n"
7912 	    "    -n name     Specify program name\n"
7913 #ifndef WIN32
7914 	    "    -N username If running as root, switch to this user\n"
7915 #endif
7916 	    "    -o file     Log output to specified file\n"
7917 	    "    -p          Generate private key\n"
7918 	    "    -P          Generate public key \"fingerprint\"\n"
7919 	    "    -r ports    Specify allowed port redirection list (server only)\n"
7920 	    "    -s          Run as a server\n"
7921 #ifdef WIN32
7922 	    "    -S option   Install/remove/run service\n"
7923 #endif
7924 	    "    -t          Timestamp log entries\n"
7925 	    "    -T port     Specify the server (tunnel) port\n"
7926 	    "    -u          Run in UDP mode\n"
7927 	    "    -U          Run in TCP and UDP mode\n"
7928 	    "    -v level    Set message verbosity level (default 1)\n"
7929 	    "    -x config   Extended configuration statement\n"
7930 	    "    -z type     Set the compression type and level (default zlib:6)\n");
7931 
7932     exit(EXIT_FAILURE);
7933 }
7934 
7935 /*
7936 ** sigpipeCatcher
7937 **
7938 ** Signal handler to ensure that SIGPIPE is caught but does nothing except
7939 ** interrupt a system call and rearms itself.
7940 */
7941 
7942 void
sigpipeCatcher(int sig)7943 sigpipeCatcher(int sig)
7944 {
7945 #ifdef SIGPIPE
7946     signal(SIGPIPE, sigpipeCatcher);
7947 #endif
7948 }
7949 
7950 /*
7951 ** sigchldCatcher
7952 **
7953 ** Signal handler to reap "zombie" processes.
7954 */
7955 
7956 void
sigchldCatcher(int sig)7957 sigchldCatcher(int sig)
7958 {
7959 #ifdef SIGCHLD
7960     while (waitpid(-1, NULL, WNOHANG) > 0) /* No further action */;
7961 
7962     signal(SIGCHLD, sigchldCatcher);
7963 #endif
7964 }
7965 
7966 /*
7967 ** sigusr1Catcher
7968 **
7969 ** Signal handler to ensure catch SIGUSR1 and set a flag.
7970 */
7971 
7972 void
sigusr1Catcher(int sig)7973 sigusr1Catcher(int sig)
7974 {
7975 #ifdef SIGUSR1
7976     _exit(0);
7977 #endif
7978 }
7979 
7980 /*
7981 ** setRunAsUser
7982 **
7983 ** Specify the user as which Zebedee should run, if currently running as root.
7984 */
7985 
7986 void
setRunAsUser(const char * user)7987 setRunAsUser(const char *user)
7988 {
7989 #ifndef WIN32
7990     struct passwd *userent = NULL;
7991 
7992     if (geteuid() != 0)
7993     {
7994 	message(1, 0, "Warning: username to run as can only be specified if effective UID is root");
7995 	return;
7996     }
7997 
7998     if (user != NULL)
7999     {
8000 	if ((userent = getpwnam(user)) != NULL)
8001 	{
8002 	    ProcessUID = userent->pw_uid;
8003             ProcessGID = userent->pw_gid;
8004         }
8005 	else
8006 	{
8007 	    /*
8008 	    ** This is a fatal error because failing to switch identity
8009 	    ** away from root if you are expecting to do so would be
8010 	    ** a Bad Thing.
8011 	    */
8012 
8013 	    message(0, 0, "invalid username '%s'", user);
8014 	    exit(EXIT_FAILURE);
8015 	}
8016     }
8017 #endif
8018 }
8019 
8020 /*
8021 ** switchUser
8022 **
8023 ** If we are running as root and another user has been specified
8024 ** switch to this user and user's primary group and give up root
8025 ** privilege.
8026 */
8027 
8028 void
switchUser(void)8029 switchUser(void)
8030 {
8031 #ifndef WIN32
8032     if (ProcessUID != -1 && ProcessGID != -1)
8033     {
8034 	if (setgid(ProcessGID) == -1)
8035 	{
8036             message(0, errno, "cannot switch group ID to gid = %u", ProcessGID);
8037             exit(EXIT_FAILURE);
8038 	}
8039 
8040 	if (setuid(ProcessUID) == -1)
8041 	{
8042 	    message(0, errno, "cannot switch user ID to uid = %u", ProcessUID);
8043   	    exit(EXIT_FAILURE);
8044 	}
8045     }
8046 #endif
8047 }
8048 
8049 /******************\
8050 **		  **
8051 **  Main Routine  **
8052 **		  **
8053 \******************/
8054 
8055 int
main(int argc,char ** argv)8056 main(int argc, char **argv)
8057 {
8058     int ch;
8059     char hostName[MAX_LINE_SIZE];
8060     int doHash = 0;
8061     int doPrivKey = 0;
8062     int doPubKey = 0;
8063     char hashBuf[HASH_STR_SIZE];
8064     char *last;
8065     char *serviceArgs = NULL;
8066 
8067 
8068 
8069     /* Set program name to the last element of the path minus extension */
8070 
8071     if ((last = strrchr(argv[0], FILE_SEP_CHAR)) != NULL)
8072     {
8073 	Program = last + 1;
8074     }
8075     else
8076     {
8077 	Program = argv[0];
8078     }
8079     if ((last = strrchr(Program, '.')) != NULL)
8080     {
8081 	*last = '\0';
8082     }
8083 
8084     /* Initialise critical stuff */
8085 
8086     threadInit();
8087 #ifdef WIN32
8088     if (WSAStartup(0x0101, &WsaState) != 0)
8089     {
8090 	message(0, errno, "winsock initailization failed");
8091     }
8092 #endif
8093 
8094     /* Parse the options! */
8095 
8096     while ((ch = getopt(argc, argv, "b:C:c:Dde:f:F:hHk:K:LlmN:n:o:pPr:sS:tT:uUv:x:z:")) != -1)
8097     {
8098 	switch (ch)
8099 	{
8100 	case 'C':
8101 	    setUShort(optarg, &ConnectAttempts);
8102 	    break;
8103 
8104 	case 'c':
8105 	    ClientHost = optarg;
8106 	    break;
8107 
8108 	case 'b':
8109 	    ListenIp = optarg;
8110 	    break;
8111 
8112 	case 'D':
8113 	    Debug = 1;
8114 	    break;
8115 
8116 	case 'd':
8117 	    IsDetached = 0;
8118 	    break;
8119 
8120 	case 'e':
8121 	    MultiUse = 0;
8122 	    CommandString = optarg;
8123 	    break;
8124 
8125 	case 'f':
8126 	    readConfigFile(optarg, 1);
8127 	    break;
8128 
8129 	case 'F':
8130 	    FieldSeparator = optarg;
8131 	    break;
8132 
8133 	case 'h':
8134 	    if (doPrivKey || doPubKey)
8135 	    {
8136 		message(0, 0, "-h and -p or -P are mutually exclusive");
8137 		exit(EXIT_FAILURE);
8138 	    }
8139 	    doHash = 1;
8140 	    break;
8141 
8142 	case 'H':
8143 	    if (doPrivKey || doPubKey)
8144 	    {
8145 		message(0, 0, "-H and -p or -P are mutually exclusive");
8146 		exit(EXIT_FAILURE);
8147 	    }
8148 	    doHash = 2;
8149 	    break;
8150 
8151 	case 'k':
8152 	    setUShort(optarg, &KeyLength);
8153 	    break;
8154 
8155 	case 'K':
8156 	    setChecksum(optarg, &ChecksumLevel);
8157 	    break;
8158 
8159 	case 'l':
8160 	    ListenMode++;
8161 	    break;
8162 
8163 	case 'L':
8164 	    LockProtocol = 1;
8165 	    break;
8166 
8167 	case 'm':
8168 	    MultiUse++;
8169 	    break;
8170 
8171 	case 'n':
8172 	    Program = optarg;
8173 	    break;
8174 
8175 #ifndef WIN32
8176 	case 'N':
8177 	    setRunAsUser(optarg);
8178 	    break;
8179 #endif
8180 
8181 	case 'o':
8182 	    setLogFile(optarg);
8183 	    break;
8184 
8185 	case 'p':
8186 	    if (doHash)
8187 	    {
8188 		message(0, 0, "-h or -H and -p or -P are mutually exclusive");
8189 		exit(EXIT_FAILURE);
8190 	    }
8191 	    doPrivKey++;
8192 	    break;
8193 
8194 	case 'P':
8195 	    if (doHash)
8196 	    {
8197 		message(0, 0, "-h or -H and -p or -P are mutually exclusive");
8198 		exit(EXIT_FAILURE);
8199 	    }
8200 	    doPubKey++;
8201 	    break;
8202 
8203 	case 'r':
8204 	    setEndPtList(optarg, &AllowedDefault, NULL, NULL, NULL, 0);
8205 	    break;
8206 
8207 	case 's':
8208 	    IsServer = 1;
8209 	    break;
8210 
8211 #ifdef WIN32
8212 	case 'S':
8213 	    serviceArgs = optarg;
8214 	    break;
8215 #endif
8216 
8217 	case 't':
8218 	    TimestampLog = 1;
8219 	    break;
8220 
8221 	case 'T':
8222 	    setUShort(optarg, &ServerPort);
8223 	    break;
8224 
8225 	case 'u':
8226 	    UdpMode = 1;
8227 	    TcpMode = 0;
8228 	    break;
8229 
8230 	case 'U':
8231 	    UdpMode = 1;
8232 	    TcpMode = 1;
8233 	    break;
8234 
8235 	case 'v':
8236 	    LogLevel = strtoul(optarg, NULL, 10);
8237 	    break;
8238 
8239 	case 'x':
8240 	    if (!parseConfigLine(optarg, 0))
8241 	    {
8242 		message(0, 0, "invalid extended configuration argument '%s'", optarg);
8243 	    }
8244 	    break;
8245 
8246 	case 'z':
8247 	    setCmpInfo(optarg, &CompressInfo);
8248 	    break;
8249 
8250 	default:
8251 	    usage();
8252 	    break;
8253 	}
8254     }
8255 
8256     /*
8257     ** If we are going to detach now is the time to invoke the workaround
8258     ** for those people with BUGGY_FORK_WITH_PTHREADS defined.
8259     */
8260 
8261     if (IsDetached)
8262     {
8263 	prepareToDetach();
8264     }
8265 
8266     /*
8267     ** If using reusable session keys then initialize the CurrentToken
8268     ** to request a new one to be generated on first connection.
8269     */
8270 
8271     if (KeyLifetime != 0)
8272     {
8273 	CurrentToken = TOKEN_NEW;
8274     }
8275 
8276     /*
8277     ** If the user has explicitly set multi-use mode and a command
8278     ** string (and you've got to try hard to do it) then we will
8279     ** complain.
8280     */
8281 
8282     if (CommandString && MultiUse)
8283     {
8284 	message(0, 0, "can't specify a command for a multi-use client");
8285 	exit(EXIT_FAILURE);
8286     }
8287 
8288     /*
8289     ** Figure out what port to listen on/connect to if not specified.
8290     */
8291 
8292     if (ServerPort == 0)
8293     {
8294 	if (UdpMode && !TcpMode)
8295 	{
8296 	    ServerPort = DFLT_UDP_PORT;
8297 	}
8298 	else
8299 	{
8300 	    ServerPort = DFLT_TCP_PORT;
8301 	}
8302     }
8303 
8304     /*
8305     ** Clean up and canonicalize the modulus and generator strings.
8306     ** We do this so that slightly different representations of these
8307     ** values (different case and white space) will be sent across the
8308     ** wire in the same form. This is important for the identity
8309     ** checking feature which calculates a hash of these string values.
8310     */
8311 
8312     Modulus = cleanHexString(Modulus);
8313     Generator = cleanHexString(Generator);
8314 
8315     /*
8316     ** Check the maximum buffer size and reset it if necessary.
8317     */
8318 
8319     if (MaxBufSize > MAX_BUF_SIZE)
8320     {
8321 	message(1, 0, "Warning: maximum buffer size must be < %hu, rounded down", MAX_BUF_SIZE);
8322 	MaxBufSize = MAX_BUF_SIZE;
8323     }
8324     else if (MaxBufSize == 0)
8325     {
8326 	message(1, 0, "Warning: buffer size must be > 0, set to %hu", DFLT_BUF_SIZE);
8327 	MaxBufSize = DFLT_BUF_SIZE;
8328     }
8329 
8330     /*
8331     ** Check for keylength and minkeylength conflict
8332     */
8333 
8334     if (KeyLength < MinKeyLength)
8335     {
8336 	message(1, 0, "Warning: specified keylength (%hu) set to minkeylength (%hu)", KeyLength, MinKeyLength);
8337 	KeyLength = MinKeyLength;
8338     }
8339 
8340 #ifdef SIGPIPE
8341     /*
8342     ** Set up a handler for SIGPIPE so that it will interrupt a select()
8343     ** call but otherwise do nothing.
8344     */
8345 
8346     signal(SIGPIPE, sigpipeCatcher);
8347 #endif
8348 
8349 #ifdef SIGCHLD
8350     /*
8351     ** Set up a handler for SIGCHLD that will clean up any defunct
8352     ** sub-processes when they exit.
8353     */
8354 
8355     signal(SIGCHLD, sigchldCatcher);
8356 #endif
8357 
8358 #ifdef WIN32
8359     if (serviceArgs)
8360     {
8361 	if (!strncmp(serviceArgs, "install", 7))
8362 	{
8363 	    if (strncmp(serviceArgs, "install=", 8) == 0)
8364 	    {
8365 		exit(svcInstall(Program, serviceArgs + 8));
8366 	    }
8367 	    else
8368 	    {
8369 		exit(svcInstall(Program, NULL));
8370 	    }
8371 	}
8372 	else if (!strcmp(serviceArgs, "remove"))
8373 	{
8374 	    exit(svcRemove(Program));
8375 	}
8376 	else if (strcmp(serviceArgs, "run") != 0)
8377 	{
8378 	    message(0, 0, "invalid argument to -S option: %s", serviceArgs);
8379 	    exit(EXIT_FAILURE);
8380 	}
8381 
8382 	/* If it was "run" fall through to the rest ... */
8383     }
8384 #endif
8385 
8386     /*
8387     ** What we do next and how we handle additional arguments depends on
8388     ** what mode we are operating in. With -h or -H we calculate hash values
8389     ** and the arguments are either files or strings. With -p or -P then
8390     ** we will calculate private/public keys and any extra arguments will
8391     ** be ignored as they will if this is a server. Finally, for a client
8392     ** the optional additional argument will be a host/port combination.
8393     */
8394 
8395     if (doHash)
8396     {
8397 	/* Hashing: -h or -H */
8398 
8399 	if (optind >= argc)
8400 	{
8401 	    /* If there are no arguments with -h then we use stdin ... */
8402 
8403 	    if (doHash == 1)
8404 	    {
8405 		hashFile(hashBuf, "-");
8406 		printf("%s\n", hashBuf);
8407 	    }
8408 	    else
8409 	    {
8410 		message(0, 0, "no string argument to hash");
8411 		exit(EXIT_FAILURE);
8412 	    }
8413 	}
8414 	else
8415 	{
8416 	    /* We have arguments -- either strings or filenames */
8417 
8418 	    while (optind < argc && argv[optind])
8419 	    {
8420 		if (doHash == 1)
8421 		{
8422 		    hashFile(hashBuf, argv[optind]);
8423 		}
8424 		else
8425 		{
8426 		    hashStrings(hashBuf, argv[optind], NULL);
8427 		}
8428 		printf("%s %s\n", hashBuf, argv[optind]);
8429 		optind++;
8430 	    }
8431 	}
8432     }
8433     else if (doPrivKey || doPubKey)
8434     {
8435 	/* Key generation: -p or -P */
8436 
8437 	if (doPrivKey)
8438 	{
8439 	    PrivateKey = generateKey(NULL, NULL, 0);
8440 	    if (PrivateKey != NULL)
8441 	    {
8442 		printf("privatekey \"%s\"\n", PrivateKey);
8443 	    }
8444 	    else
8445 	    {
8446 		message(0, errno, "can't generate private key");
8447 	    }
8448 	}
8449 	if (doPubKey)
8450 	{
8451 	    if (PrivateKey == NULL)
8452 	    {
8453 		message(0, 0, "can't generate a identity without a private key being set");
8454 		exit(EXIT_FAILURE);
8455 	    }
8456 	    gethostname(hostName, MAX_LINE_SIZE);
8457 	    printf("%s %s\n", generateIdentity(Generator, Modulus, PrivateKey), hostName);
8458 	}
8459     }
8460     else if (IsServer)
8461     {
8462 	/* Server mode -- check for target host arguments */
8463 
8464 	while (optind < argc)
8465 	{
8466 	    setTarget(argv[optind]);
8467 	    optind++;
8468 	}
8469 
8470 	/*
8471 	** Sanity check the default target. This must be a "pure" hostname
8472 	** without an address mask.
8473 	*/
8474 
8475 	if (strchr(TargetHost, '/') != NULL)
8476 	{
8477 	    message(0, 0, "default target host (%s) must not have an address mask", TargetHost);
8478 	    exit(EXIT_FAILURE);
8479 	}
8480 
8481 	/*
8482 	** If we have not yet set up the allowed redirection ports then we
8483 	** will only allow redirection to ports on the local machine.
8484 	*/
8485 
8486 	if (AllowedTargets == NULL)
8487 	{
8488 	    AllowedTargets = newEndPtList(0, 0, "localhost", NULL, NULL, ENDPTLIST_ANY);
8489 	}
8490 
8491 #ifdef WIN32
8492 	if (serviceArgs)
8493 	{
8494 	    svcRun(Program,
8495 		   (VOID (*)(VOID *))((ClientHost == NULL) ?
8496 				      serverListener : serverInitiator),
8497 		   (VOID *)&ServerPort);
8498 	}
8499 	else
8500 #endif
8501 	if (ClientHost != NULL)
8502 	{
8503 	    serverInitiator(&ServerPort);
8504 	}
8505 	else
8506 	{
8507 	    serverListener(&ServerPort);
8508 	}
8509     }
8510     else
8511     {
8512 	/*
8513 	** Client mode -- treat any remaining arguments as tunnel
8514 	** specifications.
8515 	*/
8516 
8517 	while (optind < argc)
8518 	{
8519 	    setTunnel(argv[optind]);
8520 	    optind++;
8521 	}
8522 
8523 	if (ServerHost == NULL)
8524 	{
8525 	    message(0, 0, "no server host specified");
8526 	    exit(EXIT_FAILURE);
8527 	}
8528 
8529 	/*
8530 	** This next check is for compatibility -- allowing the command
8531 	**
8532 	**  zebedee -e 'telnet localhost %d' serverhost
8533 	**
8534 	** to work.
8535 	*/
8536 
8537 	if (TargetPorts == NULL)
8538 	{
8539 	    setEndPtList("telnet", &TargetPorts, ServerHost, NULL, NULL, 0);
8540 	}
8541 
8542 	/*
8543 	** If no local port has been specified then we will default to
8544 	** using "0" -- which means that one should be dynamically
8545 	** allocated. Note that this will only be allowed if there is
8546 	** a single remote port -- see the checks below.
8547 	*/
8548 
8549 	if (ClientPorts == NULL)
8550 	{
8551 	    if ((ClientPorts = newEndPtList(0, 0, NULL, NULL, NULL, ENDPTLIST_ANY)) == NULL)
8552 	    {
8553 		message(0, errno, "can't allocate space for port list");
8554 		exit(EXIT_FAILURE);
8555 	    }
8556 	}
8557 
8558 	/* Make sure that we have matching local and remote port lists */
8559 
8560 	if (countPorts(ClientPorts) != countPorts(TargetPorts))
8561 	{
8562 	    message(0, 0, "the numbers of entries in the client and target port lists do not match");
8563 	    exit(EXIT_FAILURE);
8564 	}
8565 
8566 	/*
8567 	** If there is more than one target port specified then multi-use
8568 	** mode is implicit. This also means that a command string can not
8569 	** be specified.
8570 	*/
8571 
8572 	if (countPorts(TargetPorts) > 1)
8573 	{
8574 	    MultiUse++;
8575 	    if (CommandString)
8576 	    {
8577 		message(0, 0, "can't specify a command with multiple target ports");
8578 		exit(EXIT_FAILURE);
8579 	    }
8580 	}
8581 
8582 	/* At last! Invoke the client listener routine! */
8583 
8584 #ifdef WIN32
8585 	if (serviceArgs)
8586 	{
8587 	    svcRun(Program, (VOID (*)(VOID *))clientListener, (void *)ClientPorts);
8588 	}
8589 	else
8590 #endif
8591 	{
8592 	    clientListener(ClientPorts);
8593 	}
8594     }
8595 
8596     exit(EXIT_SUCCESS);
8597 }
8598