Change priority from extra to optional in debian/control.
[debian/iodine.git] / src / common.c
1 /* Copyright (c) 2006-2014 Erik Ekman <yarrick@kryo.se>,
2  * 2006-2009 Bjorn Andersson <flex@kryo.se>
3  * Copyright (c) 2007 Albert Lee <trisk@acm.jhu.edu>.
4  *
5  * Permission to use, copy, modify, and distribute this software for any
6  * purpose with or without fee is hereby granted, provided that the above
7  * copyright notice and this permission notice appear in all copies.
8  *
9  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16  */
17
18 #include <time.h>
19 #include <sys/types.h>
20 #include <sys/param.h>
21 #include <sys/stat.h>
22 #include <stdio.h>
23 #include <stdint.h>
24 #include <stdlib.h>
25 #include <stdint.h>
26 #include <unistd.h>
27 #include <string.h>
28 #include <ctype.h>
29 #include <fcntl.h>
30 #include <errno.h>
31
32 #ifdef WINDOWS32
33 #include <winsock2.h>
34 #include <conio.h>
35 #else
36 #include <arpa/nameser.h>
37 #ifdef DARWIN
38 #define BIND_8_COMPAT
39 #include <arpa/nameser_compat.h>
40 #endif
41 #include <termios.h>
42 #include <err.h>
43 #include <netinet/in.h>
44 #include <arpa/inet.h>
45 #include <syslog.h>
46 #include <sys/socket.h>
47 #include <netdb.h>
48 #endif
49
50 #ifdef HAVE_SETCON
51 # include <selinux/selinux.h>
52 #endif
53
54 #include "common.h"
55
56 /* The raw header used when not using DNS protocol */
57 const unsigned char raw_header[RAW_HDR_LEN] = { 0x10, 0xd1, 0x9e, 0x00 };
58
59 /* daemon(3) exists only in 4.4BSD or later, and in GNU libc */
60 #if !defined(ANDROID) && !defined(WINDOWS32) && !(defined(BSD) && (BSD >= 199306)) && !defined(__GLIBC__)
61 static int daemon(int nochdir, int noclose)
62 {
63         int fd, i;
64
65         switch (fork()) {
66                 case 0:
67                         break;
68                 case -1:
69                         return -1;
70                 default:
71                         _exit(0);
72         }
73
74         if (!nochdir) {
75                 chdir("/");
76         }
77
78         if (setsid() < 0) {
79                 return -1;
80         }
81
82         if (!noclose) {
83                 if ((fd = open("/dev/null", O_RDWR)) >= 0) {
84                         for (i = 0; i < 3; i++) {
85                                 dup2(fd, i);
86                         }
87                         if (fd > 2) {
88                                 close(fd);
89                         }
90                 }
91         }
92         return 0;
93 }
94 #endif
95
96 #if defined(__BEOS__) && !defined(__HAIKU__)
97 int setgroups(int count, int *groups)
98 {
99         /* errno = ENOSYS; */
100         return -1;
101 }
102 #endif
103
104
105 void
106 check_superuser(void (*usage_fn)(void))
107 {
108 #ifndef WINDOWS32
109         if (geteuid() != 0) {
110                 warnx("Run as root and you'll be happy.\n");
111                 usage_fn();
112                 /* NOTREACHED */
113         }
114 #endif
115 }
116
117 char *
118 format_addr(struct sockaddr_storage *sockaddr, int sockaddr_len)
119 {
120         static char dst[INET6_ADDRSTRLEN + 1];
121
122         memset(dst, 0, sizeof(dst));
123         if (sockaddr->ss_family == AF_INET && sockaddr_len >= sizeof(struct sockaddr_in)) {
124                 getnameinfo((struct sockaddr *)sockaddr, sockaddr_len, dst, sizeof(dst) - 1, NULL, 0, NI_NUMERICHOST);
125         } else if (sockaddr->ss_family == AF_INET6 && sockaddr_len >= sizeof(struct sockaddr_in6)) {
126                 struct sockaddr_in6 *addr = (struct sockaddr_in6 *) sockaddr;
127                 if (IN6_IS_ADDR_V4MAPPED(&addr->sin6_addr)) {
128                         struct in_addr ia;
129                         /* Get mapped v4 addr from last 32bit field */
130                         memcpy(&ia.s_addr, &addr->sin6_addr.s6_addr[12], sizeof(ia));
131                         strcpy(dst, inet_ntoa(ia));
132                 } else {
133                         getnameinfo((struct sockaddr *)sockaddr, sockaddr_len, dst, sizeof(dst) - 1, NULL, 0, NI_NUMERICHOST);
134                 }
135         } else {
136                 dst[0] = '?';
137         }
138         return dst;
139 }
140
141 int
142 get_addr(char *host, int port, int addr_family, int flags, struct sockaddr_storage *out)
143 {
144         struct addrinfo hints, *addr;
145         int res;
146         char portnum[8];
147
148         memset(portnum, 0, sizeof(portnum));
149         snprintf(portnum, sizeof(portnum) - 1, "%d", port);
150
151         memset(&hints, 0, sizeof(hints));
152         hints.ai_family = addr_family;
153 #if defined(WINDOWS32) || defined(OPENBSD)
154         /* AI_ADDRCONFIG misbehaves on windows, and does not exist in OpenBSD */
155         hints.ai_flags = flags;
156 #else
157         hints.ai_flags = AI_ADDRCONFIG | flags;
158 #endif
159         hints.ai_socktype = SOCK_DGRAM;
160         hints.ai_protocol = IPPROTO_UDP;
161
162         res = getaddrinfo(host, portnum, &hints, &addr);
163         if (res == 0) {
164                 int addrlen = addr->ai_addrlen;
165                 /* Grab first result */
166                 memcpy(out, addr->ai_addr, addr->ai_addrlen);
167                 freeaddrinfo(addr);
168                 return addrlen;
169         }
170         return res;
171 }
172
173 int
174 open_dns(struct sockaddr_storage *sockaddr, size_t sockaddr_len)
175 {
176         int flag = 1;
177         int fd;
178
179         if ((fd = socket(sockaddr->ss_family, SOCK_DGRAM, IPPROTO_UDP)) < 0) {
180                 err(1, "socket");
181         }
182
183         flag = 1;
184 #ifdef SO_REUSEPORT
185         setsockopt(fd, SOL_SOCKET, SO_REUSEPORT, (const void*) &flag, sizeof(flag));
186 #endif
187         setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (const void*) &flag, sizeof(flag));
188
189 #ifndef WINDOWS32
190         /* To get destination address from each UDP datagram, see iodined.c:read_dns() */
191         setsockopt(fd, IPPROTO_IP, DSTADDR_SOCKOPT, (const void*) &flag, sizeof(flag));
192
193         fd_set_close_on_exec(fd);
194 #endif
195
196 #ifdef IP_OPT_DONT_FRAG
197         /* Set dont-fragment ip header flag */
198         flag = DONT_FRAG_VALUE;
199         setsockopt(fd, IPPROTO_IP, IP_OPT_DONT_FRAG, (const void*) &flag, sizeof(flag));
200 #endif
201
202         if(bind(fd, (struct sockaddr*) sockaddr, sockaddr_len) < 0)
203                 err(1, "bind");
204
205         fprintf(stderr, "Opened IPv%d UDP socket\n", sockaddr->ss_family == AF_INET6 ? 6 : 4);
206
207         return fd;
208 }
209
210 int
211 open_dns_from_host(char *host, int port, int addr_family, int flags)
212 {
213         struct sockaddr_storage addr;
214         int addrlen;
215
216         addrlen = get_addr(host, port, addr_family, flags, &addr);
217         if (addrlen < 0)
218                 return addrlen;
219
220         return open_dns(&addr, addrlen);
221 }
222
223 void
224 close_dns(int fd)
225 {
226         close(fd);
227 }
228
229 void
230 do_chroot(char *newroot)
231 {
232 #if !(defined(WINDOWS32) || defined(__BEOS__) || defined(__HAIKU__))
233         if (chroot(newroot) != 0 || chdir("/") != 0)
234                 err(1, "%s", newroot);
235
236         if (seteuid(geteuid()) != 0 || setuid(getuid()) != 0) {
237                 err(1, "set[e]uid()");
238         }
239 #else
240         warnx("chroot not available");
241 #endif
242 }
243
244 void
245 do_setcon(char *context)
246 {
247 #ifdef HAVE_SETCON
248         if (-1 == setcon(context))
249                 err(1, "%s", context);
250 #else
251         warnx("No SELinux support built in");
252 #endif
253 }
254
255 void
256 do_pidfile(char *pidfile)
257 {
258 #ifndef WINDOWS32
259         FILE *file;
260
261         if ((file = fopen(pidfile, "w")) == NULL) {
262                 syslog(LOG_ERR, "Cannot write pidfile to %s, exiting", pidfile);
263                 err(1, "do_pidfile: Can not write pidfile to %s", pidfile);
264         } else {
265                 fprintf(file, "%d\n", (int)getpid());
266                 fclose(file);
267         }
268 #else
269         fprintf(stderr, "Windows version does not support pid file\n");
270 #endif
271 }
272
273 void
274 do_detach()
275 {
276 #ifndef WINDOWS32
277         fprintf(stderr, "Detaching from terminal...\n");
278         daemon(0, 0);
279         umask(0);
280         alarm(0);
281 #else
282         fprintf(stderr, "Windows version does not support detaching\n");
283 #endif
284 }
285
286 void
287 read_password(char *buf, size_t len)
288 {
289         char pwd[80] = {0};
290 #ifndef WINDOWS32
291         struct termios old;
292         struct termios tp;
293
294         tcgetattr(0, &tp);
295         old = tp;
296
297         tp.c_lflag &= (~ECHO);
298         tcsetattr(0, TCSANOW, &tp);
299 #else
300         int i;
301 #endif
302
303         fprintf(stderr, "Enter password: ");
304         fflush(stderr);
305 #ifndef WINDOWS32
306         fscanf(stdin, "%79[^\n]", pwd);
307 #else
308         for (i = 0; i < sizeof(pwd); i++) {
309                 pwd[i] = getch();
310                 if (pwd[i] == '\r' || pwd[i] == '\n') {
311                         pwd[i] = 0;
312                         break;
313                 } else if (pwd[i] == '\b') {
314                         i--;                    /* Remove the \b char */
315                         if (i >=0) i--;         /* If not first char, remove one more */
316                 }
317         }
318 #endif
319         fprintf(stderr, "\n");
320
321 #ifndef WINDOWS32
322         tcsetattr(0, TCSANOW, &old);
323 #endif
324
325         strncpy(buf, pwd, len);
326         buf[len-1] = '\0';
327 }
328
329 int
330 check_topdomain(char *str, char **errormsg)
331 {
332         int i;
333         int dots = 0;
334         int chunklen = 0;
335
336         if (strlen(str) < 3) {
337                 if (errormsg) *errormsg = "Too short (< 3)";
338                 return 1;
339         }
340         if (strlen(str) > 128) {
341                 if (errormsg) *errormsg = "Too long (> 128)";
342                 return 1;
343         }
344
345         if (str[0] == '.') {
346                 if (errormsg) *errormsg = "Starts with a dot";
347                 return 1;
348         }
349
350         for( i = 0; i < strlen(str); i++) {
351                 if(str[i] == '.') {
352                         dots++;
353                         if (chunklen == 0) {
354                                 if (errormsg) *errormsg = "Consecutive dots";
355                                 return 1;
356                         }
357                         if (chunklen > 63) {
358                                 if (errormsg) *errormsg = "Too long domain part (> 63)";
359                                 return 1;
360                         }
361                         chunklen = 0;
362                 } else {
363                         chunklen++;
364                 }
365                 if( (str[i] >= 'a' && str[i] <= 'z') || (str[i] >= 'A' && str[i] <= 'Z') ||
366                                 isdigit(str[i]) || str[i] == '-' || str[i] == '.' ) {
367                         continue;
368                 } else {
369                         if (errormsg) *errormsg = "Contains illegal character (allowed: [a-zA-Z0-9-.])";
370                         return 1;
371                 }
372         }
373
374         if (dots == 0) {
375                 if (errormsg) *errormsg = "No dots";
376                 return 1;
377         }
378         if (chunklen == 0) {
379                 if (errormsg) *errormsg = "Ends with a dot";
380                 return 1;
381         }
382         if (chunklen > 63) {
383                 if (errormsg) *errormsg = "Too long domain part (> 63)";
384                 return 1;
385         }
386
387         return 0;
388 }
389
390 #if defined(WINDOWS32) || defined(ANDROID)
391 #ifndef ANDROID
392 int
393 inet_aton(const char *cp, struct in_addr *inp)
394 {
395  inp->s_addr = inet_addr(cp);
396  return inp->s_addr != INADDR_ANY;
397 }
398 #endif
399
400 void
401 warn(const char *fmt, ...)
402 {
403         va_list list;
404
405         va_start(list, fmt);
406         if (fmt) fprintf(stderr, fmt, list);
407 #ifndef ANDROID
408         if (errno == 0) {
409                 fprintf(stderr, ": WSA error %d\n", WSAGetLastError());
410         } else {
411                 fprintf(stderr, ": %s\n", strerror(errno));
412         }
413 #endif
414         va_end(list);
415 }
416
417 void
418 warnx(const char *fmt, ...)
419 {
420         va_list list;
421
422         va_start(list, fmt);
423         if (fmt) fprintf(stderr, fmt, list);
424         fprintf(stderr, "\n");
425         va_end(list);
426 }
427
428 void
429 err(int eval, const char *fmt, ...)
430 {
431         va_list list;
432
433         va_start(list, fmt);
434         warn(fmt, list);
435         va_end(list);
436         exit(eval);
437 }
438
439 void
440 errx(int eval, const char *fmt, ...)
441 {
442         va_list list;
443
444         va_start(list, fmt);
445         warnx(fmt, list);
446         va_end(list);
447         exit(eval);
448 }
449 #endif
450
451
452 int recent_seqno(int ourseqno, int gotseqno)
453 /* Return 1 if we've seen gotseqno recently (current or up to 3 back).
454    Return 0 if gotseqno is new (or very old).
455 */
456 {
457         int i;
458         for (i = 0; i < 4; i++, ourseqno--) {
459                 if (ourseqno < 0)
460                         ourseqno = 7;
461                 if (gotseqno == ourseqno)
462                         return 1;
463         }
464         return 0;
465 }
466
467 #ifndef WINDOWS32
468 /* Set FD_CLOEXEC flag on file descriptor.
469  * This stops it from being inherited by system() calls.
470  */
471 void
472 fd_set_close_on_exec(int fd)
473 {
474         int flags;
475
476         flags = fcntl(fd, F_GETFD);
477         if (flags == -1)
478                 err(4, "Failed to get fd flags");
479         flags |= FD_CLOEXEC;
480         if (fcntl(fd, F_SETFD, flags) == -1)
481                 err(4, "Failed to set fd flags");
482 }
483 #endif
484