1 /*
2  * Copyright 2004-2009 Rob Beverly
3  * Copyright 2015-2021 The Regents of the University of California
4  * All rights reserved.
5  *
6  * This file is part of Spoofer.
7  *
8  * Spoofer is free software: you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License as published by
10  * the Free Software Foundation, either version 3 of the License, or
11  * (at your option) any later version.
12  *
13  * Spoofer is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with Spoofer.  If not, see <http://www.gnu.org/licenses/>.
20  */
21 
22 /****************************************************************************
23    Program:     $Id: util.cc,v 1.64 2021/04/28 17:39:07 kkeys Exp $
24    Author:      Rob Beverly <rbeverly at csail.mit.edu>
25                 Ken Keys, CAIDA
26    Date:        $Date: 2021/04/28 17:39:07 $
27    Description: Spoofer utility routines
28 ****************************************************************************/
29 
30 #ifdef _WIN32
31 #define _CRT_RAND_S // for rand_s() in <stdlib.h>
32 #endif
33 
34 #include <stdarg.h>
35 #include <ctype.h>
36 #include <fcntl.h> // for open()
37 #include "spoof.h"
38 #ifdef HAVE_GETTIMEOFDAY
39  #include <sys/time.h>
40 #endif
41 
42 int verbosity = OFF;
43 
44 static const std::string pbs_magic_array[] = {
45     std::string("SPOOFER\n\n", 9), // preferred as of version 1.1.0
46     std::string("SPOOFER\0", 8), // used in version <= 1.0.8
47     std::string() // sentry
48 };
49 const std::string *pbs_magic = pbs_magic_array;
50 
51 
52 #ifdef _WIN32
53 // Windows' snprintf() and vsnprintf() prior to VC2015 do not handle buffer
54 // overflow as specified by C99:
55 // - it doesn't write the terminating NUL
56 // - it returns -1 instead of the would-be string length
57 // - %n arguments past the overflow point will not be set
58 // Windows' sprintf_s() doesn't match either: it guarantees NUL-termination,
59 // but writes an empty string instead of as much as possible.
60 // This version fixes all the issues.
spoofer_snprintf(char * buf,size_t size,const char * fmt,...)61 int spoofer_snprintf(char *buf, size_t size, const char *fmt, ...)
62 {
63     va_list ap;
64     int n = -1;
65     if (buf) {
66 	va_start(ap, fmt);
67 	n = vsnprintf(buf, size, fmt, ap);
68 	va_end(ap);
69 	buf[size-1] = '\0';
70 	if (n >= 0) return n; // success
71     }
72     // work around broken overflow handling
73     va_start(ap, fmt);
74     FILE *file = fopen("NUL", "w");
75     if (!file) return n; // shouldn't happen
76     n = vfprintf(file, fmt, ap); // returns correct length and sets %n arguments
77     va_end(ap);
78     fclose(file);
79     return n;
80 }
81 #endif
82 
is_interactive(void)83 int is_interactive(void)
84 {
85 #ifdef _WIN32
86     HANDLE hIn = GetStdHandle(STD_INPUT_HANDLE);
87     HANDLE hOut = GetStdHandle(STD_OUTPUT_HANDLE);
88     if (hIn == INVALID_HANDLE_VALUE || hOut == INVALID_HANDLE_VALUE) return 0;
89     DWORD dummyMode;
90     return GetConsoleMode(hIn, &dummyMode) && GetConsoleMode(hOut, &dummyMode);
91 #else
92     return isatty(STDIN_FILENO) && isatty(STDOUT_FILENO);
93 #endif
94 }
95 
exitpause(int status)96 NORETURN void exitpause(int status) {
97 #ifdef _WIN32
98     DWORD proclist[1];
99     if (is_interactive() && GetConsoleProcessList(proclist, 1) <= 1) {
100 	// This console has no other processes; it will close when we exit.
101 	fprintf(stdout, "\nPress Enter to Exit.\n"); \
102 	fflush(stdout); \
103 	while (getchar() != '\n');
104     }
105 #endif
106     exit(status);
107 }
108 
109 /**
110  * Fatal error condition function
111  */
fatal(const char * fmt,...)112 NORETURN void fatal(const char *fmt, ...) {
113     va_list ap;
114     fflush(stdout);
115     va_start(ap, fmt);
116     fprintf(stderr, "*** ");
117     vfprintf(stderr, fmt, ap);
118     va_end(ap);
119     exitpause(-1);
120 }
121 
122 /**
123  * Fatal error condition function; prints error
124  */
pfatal(const char * fmt,...)125 NORETURN void pfatal(const char *fmt, ...) {
126     va_list ap;
127     fflush(stdout);
128     va_start(ap, fmt);
129     vfprintf(stderr, fmt, ap);
130     fprintf(stderr, " ");
131     perror("Error");
132     va_end(ap);
133     exitpause(-1);
134 }
135 
136 /**
137  * binDump -  Debug routine for examining raw packets/buffer/char strings
138  *
139  * @param[in]   msg     pointer to message buffer
140  * @param[in]   len     length of buffer to print
141  * @param[in]   pretty  if true, pretty print
142  * @param[in]   prefix  prefix for each line (if pretty)
143  */
binDump(const void * msg,size_t len,int pretty,const char * prefix)144 void binDump(const void *msg, size_t len, int pretty, const char *prefix) {
145     size_t i;
146     const unsigned char *p = static_cast<const unsigned char*>(msg);
147     // Use a buffer so print is atomic (if len is small enough)
148     size_t buflen = !pretty ? len*2 + 1 :
149 	(len/16+1) * ((prefix ? strlen(prefix) : 0) + 51) + 2;
150     char *buf = new char[buflen];
151     int off = 0; // offset in buf
152     for (i = 1; i <= len; i++) {
153 	if (pretty) {
154 	    if (prefix && (i-1)%16 == 0) off += sprintf(buf+off, "%s", prefix);
155 	    off += sprintf(buf+off, "%02x ", *p++);
156 	    if (i >= len) break;
157 	    if (i%16 == 0) buf[off-1] = '\n';
158 	    else if (i%4 == 0) buf[off++] = ' ';
159 	} else {
160 	    off += sprintf(buf+off, "%02x", *p++);
161 	}
162     }
163     if (pretty) buf[off++] = '\n';
164     buf[off++] = '\0';
165     fputs(buf, stdout);
166     delete[] buf;
167 }
168 
169 /**
170  * win_init -  Windows socket API startup
171  */
172 #ifdef _WIN32
win_init(void)173 void win_init(void) {
174     WSADATA wsd;
175     if (WSAStartup(MAKEWORD(2, 2), &wsd) != 0) {
176         fatal("WSAStartup() failed");
177     }
178 }
179 #endif
180 
181 /**
182  * Pseudo-random number generator
183  */
184 
spoofer_rand_stir()185 void spoofer_rand_stir()
186 {
187 #if defined(HAVE_ARC4RANDOM)
188  #if defined(HAVE_ARC4RANDOM_STIR)
189     // On some newer platforms, the arc4random() function is not actually the
190     // RC4 algorithm, and there is no arc4random_stir() function.
191     arc4random_stir();
192  #endif
193 #elif defined(HAVE_SRANDOMDEV)
194     srandomdev();
195 #else
196     unsigned int seed = 0;
197     int fd = open("/dev/urandom", O_RDONLY);
198     if (fd >= 0) {
199 	if (read(fd, &seed, sizeof(seed)) < (ssize_t)sizeof(seed))
200 	    seed = 0;
201 	close(fd);
202     }
203     if (!seed) {
204  #if defined(HAVE_GETTIMEOFDAY)
205 	struct timeval tv;
206 	gettimeofday(&tv, nullptr);
207 	seed = static_cast<unsigned int>(tv.tv_sec * tv.tv_usec);
208  #else
209 	seed = static_cast<unsigned int>(time(nullptr));
210  #endif
211  #ifndef _WIN32
212 	seed ^= static_cast<unsigned int>(getpid());
213  #endif
214     }
215  #if defined(HAVE_SRANDOM)
216     srandom(seed);
217  #else
218     srand(seed);
219  #endif
220 #endif
221 }
222 
223 #if defined(HAVE_ARC4RANDOM) || defined(_WIN32)
224  #define spoofer_rand_stir_if_needed() /* empty */
225 #else
spoofer_rand_stir_if_needed()226 static void spoofer_rand_stir_if_needed()
227 {
228     // Make sure to re-stir if we've forked, so we don't generate the
229     // same pseudorandom sequence as the parent or siblings.
230     static pid_t stirred_pid = 0;
231     pid_t my_pid = getpid();
232     if (stirred_pid != my_pid) {
233 	spoofer_rand_stir();
234 	stirred_pid = my_pid;
235     }
236 }
237 #endif
238 
spoofer_rand(unsigned long max)239 unsigned long spoofer_rand(unsigned long max)
240 {
241     spoofer_rand_stir_if_needed();
242 #if defined(_WIN32)
243     unsigned int r;
244     rand_s(&r);
245     return r % max;
246 #elif defined(HAVE_ARC4RANDOM)
247     return static_cast<unsigned long>(arc4random_uniform(static_cast<uint32_t>(max)));
248 #elif defined(HAVE_SRANDOM)
249     return static_cast<unsigned long>(random()) % max;
250 #else
251     return static_cast<unsigned long>(rand()) % max;
252 #endif
253 }
254 
255 /**
256  * msleep -  Portable millisecond sleep
257  */
msleep(unsigned int msec)258 void msleep(unsigned int msec) {
259 #ifdef _WIN32
260     Sleep(msec);
261 #else
262     usleep(msec * 1000);
263 #endif
264 }
265 
266 /**
267  * spoofSleep -  Portable 0.1 - 0.5 s random sleep
268  */
spoofSleep(void)269 void spoofSleep(void) {
270     msleep(100 + static_cast<unsigned>(spoofer_rand(400)));
271 }
272 
273 /**
274  * timestring - form time/date string
275  */
timestring(void)276 char *timestring(void) {
277    static char str[BUFSIZE];
278    time_t now;
279    struct tm *t;
280 
281    now = time(nullptr);
282    t = localtime(&now);
283    snprintf(str, sizeof(str), "%d/%02d/%02d %02d:%02d:%02d", t->tm_year + 1900,
284        t->tm_mon + 1, t->tm_mday, t->tm_hour, t->tm_min, t->tm_sec);
285    return (str);
286 }
287 
288 /**
289  * streamSetup - set stdout to be unbuffered, replicate stdout
290  *               to the stderr file descriptor.  useful with
291  *               the authorization services API (for osx gui)
292  *               which doesn't pipe back stderr and prevents
293  *               weird interleaving of stderr, stdout messages.
294  */
streamSetup(void)295 void streamSetup(void) {
296     if (setvbuf(stdout, nullptr, _IONBF, 0) == EOF) {
297         perror("setvbuf");
298     }
299     if (dup2(1,2) < 0) {
300         perror("dup2");
301     }
302 }
303 
304 /* Unified IPv4/IPv6 address field helper routines.
305  *   Ex:
306  *     char bob[IPV6ADDRLEN];
307  *     uint32_t alice = 91232354;
308  *     h4to6n(alice, bob);
309  *     printf("Alice: %u %u\n", alice, n6toh4(bob));
310  */
311 /* network byte-order IPv6 to network byte-order IPv4 */
n6ton4(const unsigned char * addr)312 uint32_t n6ton4(const unsigned char *addr) {
313     const unsigned char *begin = addr + (IPV6ADDRLEN - IPV4ADDRLEN);
314     uint32_t res;
315     memcpy(&res, begin, IPV4ADDRLEN);
316     return (res);
317 }
318 
319 /* network byte-order IPv6 to host byte-order IPv4 */
n6toh4(const unsigned char * addr)320 uint32_t n6toh4(const unsigned char *addr) {
321     return (ntohl(n6ton4(addr)));
322 }
323 
324 /* network byte-order IPv4 to network byte-order IPv6 */
n4ton6(const uint32_t ip,unsigned char * addr)325 int n4ton6(const uint32_t ip, unsigned char *addr) {
326     unsigned char *begin = addr + (IPV6ADDRLEN - IPV4ADDRLEN);
327     memcpy(begin, &ip, IPV4ADDRLEN);
328     return TRUE;
329 }
330 
331 /* host byte-order IPv4 to network byte-order IPv6 */
h4ton6(const uint32_t ip,unsigned char * addr)332 int h4ton6(const uint32_t ip, unsigned char *addr) {
333     unsigned char *begin = addr + (IPV6ADDRLEN - IPV4ADDRLEN);
334     uint32_t res = htonl(ip);
335     memcpy(begin, &res, IPV4ADDRLEN);
336     return TRUE;
337 }
338 
n6tohexstring(const unsigned char * addr,char * res)339 int n6tohexstring(const unsigned char *addr, char *res) {
340     int i=0;
341     snprintf(res, 3, "0x");
342     for (i=1;i<=IPV6ADDRLEN;i++) {
343         snprintf(res + (i*2), 3, "%02x", *addr);
344         addr++;
345     }
346     return TRUE;
347 }
348 
isIPv4(const unsigned char * addr)349 int isIPv4(const unsigned char *addr) {
350     int i=0;
351     const unsigned char *d = addr;
352     for (i=0;i<(IPV6ADDRLEN - IPV4ADDRLEN);i++) {
353         if (*d++ != 0x00)
354             return FALSE;
355     }
356     return TRUE;
357 }
358 
isIPv6(const unsigned char * addr)359 int isIPv6(const unsigned char *addr) {
360     return (isIPv4(addr) ? FALSE : TRUE);
361 }
362 
isIPv6Equal(const unsigned char * a1,const unsigned char * a2)363 int isIPv6Equal(const unsigned char *a1, const unsigned char *a2) {
364     int ret = memcmp(a1, a2, IPV6ADDRLEN);
365     return (ret == 0 ? TRUE : FALSE);
366 }
367 
printIPv6(const unsigned char * a)368 char *printIPv6(const unsigned char *a) {
369     static char v6string[SMALLBUF];
370     inet_ntop(AF_INET6, a, v6string, SMALLBUF);
371     return v6string;
372 }
373 
374 // portable version of BSD's strnstr()
strstrPortable(const char * a,const char * b,size_t n)375 const char *strstrPortable(const char *a, const char *b, size_t n) {
376     size_t alen, blen, i;
377     // don't depend on there being a \0 within the first n chars
378     for (alen = 0; alen < n; alen++)
379 	if (a[alen] == '\0') break;
380     blen = strlen(b);
381     if (blen > alen) return nullptr;
382     if (n > alen - blen)
383 	n = alen - blen;
384     for (i = 0; i <= n; i++) {
385 	if (memcmp(a+i, b, blen) == 0)
386 	    return a+i;
387     }
388     return nullptr;
389 }
390