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