1 /* Code and variables that is common to both fork and select-based
2 * servers.
3 *
4 * No code here should assume whether sockets are blocking or not.
5 **/
6
7 #define SYSLOG_NAMES
8 #define _GNU_SOURCE
9 #include <stddef.h>
10 #include <stdarg.h>
11 #include <grp.h>
12
13 #include <sys/types.h>
14 #include <ifaddrs.h>
15 #include <netinet/in.h>
16
17 #include "common.h"
18 #include "probe.h"
19 #include "sslh-conf.h"
20
21 /* Added to make the code compilable under CYGWIN
22 * */
23 #ifndef SA_NOCLDWAIT
24 #define SA_NOCLDWAIT 0
25 #endif
26
27 /* Make use of systemd socket activation
28 * */
29 #ifdef SYSTEMD
30 #include <systemd/sd-daemon.h>
31 #endif
32
33 #ifdef LIBBSD
34 #include <bsd/unistd.h>
35 #endif
36
37 /*
38 * Settings that depend on the command line or the config file
39 */
40 struct sslhcfg_item cfg;
41
42 struct addrinfo *addr_listen = NULL; /* what addresses do we listen to? */
43
44
45 static int do_syslog = 1; /* Should we syslog? controled by syslog_facility = "none" */
46
47 #ifdef LIBWRAP
48 #include <tcpd.h>
49 int allow_severity =0, deny_severity = 0;
50 #endif
51
52 typedef enum {
53 CR_DIE,
54 CR_WARN
55 } CR_ACTION;
56
57 /* check result and die, printing the offending address and error */
check_res_dump(CR_ACTION act,int res,struct addrinfo * addr,char * syscall)58 void check_res_dump(CR_ACTION act, int res, struct addrinfo *addr, char* syscall)
59 {
60 char buf[NI_MAXHOST];
61
62 if (res == -1) {
63 fprintf(stderr, "%s:%s: %s\n",
64 sprintaddr(buf, sizeof(buf), addr),
65 syscall,
66 strerror(errno));
67
68 if (act == CR_DIE)
69 exit(1);
70 }
71 }
72
get_fd_sockets(int * sockfd[])73 int get_fd_sockets(int *sockfd[])
74 {
75 int sd = 0;
76
77 #ifdef SYSTEMD
78 sd = sd_listen_fds(0);
79 if (sd < 0) {
80 fprintf(stderr, "sd_listen_fds(): %s\n", strerror(-sd));
81 exit(1);
82 }
83 if (sd > 0) {
84 int i;
85 *sockfd = malloc(sd * sizeof(*sockfd[0]));
86 CHECK_ALLOC(*sockfd, "malloc");
87 for (i = 0; i < sd; i++) {
88 (*sockfd)[i] = SD_LISTEN_FDS_START + i;
89 }
90 }
91 #endif
92
93 return sd;
94 }
95
96 /* Set TCP_FASTOPEN on listening socket if all client protocols support it */
make_listen_tfo(int s)97 int make_listen_tfo(int s)
98 {
99 int i, qlen = 5;
100
101 /* Don't do it if not supported */
102 if (!TCP_FASTOPEN)
103 return 0;
104
105 /* Don't do it if any protocol does not specify it */
106 for (i = 0; i < cfg.protocols_len; i++) {
107 if (! cfg.protocols[i].tfo_ok)
108 return 0;
109 }
110
111 return setsockopt(s, SOL_SOCKET, TCP_FASTOPEN, (char*)&qlen, sizeof(qlen));
112 }
113
114 /* Starts listening sockets on specified addresses.
115 * IN: addr[], num_addr
116 * OUT: *sockfd[] pointer to newly-allocated array of file descriptors
117 * Returns number of addresses bound
118 * Bound file descriptors are returned in newly-allocated *sockfd pointer
119 */
start_listen_sockets(int * sockfd[],struct addrinfo * addr_list)120 int start_listen_sockets(int *sockfd[], struct addrinfo *addr_list)
121 {
122 struct sockaddr_storage *saddr;
123 struct addrinfo *addr;
124 int i, res, one;
125 int num_addr = 0;
126 int sd_socks = 0;
127
128 sd_socks = get_fd_sockets(sockfd);
129
130 if (sd_socks > 0) {
131 return sd_socks;
132 }
133
134 for (addr = addr_list; addr; addr = addr->ai_next)
135 num_addr++;
136
137 if (num_addr == 0) {
138 fprintf(stderr, "FATAL: No available addresses.\n");
139 exit(1);
140 }
141
142 if (cfg.verbose)
143 fprintf(stderr, "listening to %d addresses\n", num_addr);
144
145 *sockfd = malloc(num_addr * sizeof(*sockfd[0]));
146 CHECK_ALLOC(*sockfd, "malloc");
147
148 for (i = 0, addr = addr_list; i < num_addr && addr; i++, addr = addr->ai_next) {
149 if (!addr) {
150 fprintf(stderr, "FATAL: Inconsistent listen number. This should not happen.\n");
151 exit(1);
152 }
153 saddr = (struct sockaddr_storage*)addr->ai_addr;
154
155 (*sockfd)[i] = socket(saddr->ss_family, SOCK_STREAM, 0);
156 check_res_dump(CR_DIE, (*sockfd)[i], addr, "socket");
157
158 one = 1;
159 res = setsockopt((*sockfd)[i], SOL_SOCKET, SO_REUSEADDR, (char*)&one, sizeof(one));
160 check_res_dump(CR_DIE, res, addr, "setsockopt(SO_REUSEADDR)");
161
162 res = make_listen_tfo((*sockfd)[i]);
163 check_res_dump(CR_WARN, res, addr, "setsockopt(TCP_FASTOPEN)");
164
165 if (addr->ai_flags & SO_KEEPALIVE) {
166 res = setsockopt((*sockfd)[i], SOL_SOCKET, SO_KEEPALIVE, (char*)&one, sizeof(one));
167 check_res_dump(CR_DIE, res, addr, "setsockopt(SO_KEEPALIVE)");
168 }
169
170 if (IP_FREEBIND) {
171 res = setsockopt((*sockfd)[i], IPPROTO_IP, IP_FREEBIND, (char*)&one, sizeof(one));
172 check_res_dump(CR_WARN, res, addr, "setsockopt(IP_FREEBIND)");
173 }
174
175 if (addr->ai_addr->sa_family == AF_INET6) {
176 res = setsockopt((*sockfd)[i], IPPROTO_IPV6, IPV6_V6ONLY, (char*)&one, sizeof(one));
177 check_res_dump(CR_WARN, res, addr, "setsockopt(IPV6_V6ONLY)");
178 }
179
180 res = bind((*sockfd)[i], addr->ai_addr, addr->ai_addrlen);
181 check_res_dump(CR_DIE, res, addr, "bind");
182
183 res = listen ((*sockfd)[i], 50);
184 check_res_dump(CR_DIE, res, addr, "listen");
185
186 }
187
188 return num_addr;
189 }
190
191
192 /* returns 1 if given address is on the local machine: iterate through all
193 * network interfaces and check their addresses */
is_same_machine(struct addrinfo * from)194 int is_same_machine(struct addrinfo* from)
195 {
196 struct ifaddrs *ifaddrs_p = NULL, *ifa;
197 int match = 0;
198
199 getifaddrs(&ifaddrs_p);
200
201 for (ifa = ifaddrs_p; ifa != NULL; ifa = ifa->ifa_next)
202 {
203 if (!ifa->ifa_addr)
204 continue;
205 if (from->ai_addr->sa_family == ifa->ifa_addr->sa_family)
206 {
207 int family = ifa->ifa_addr->sa_family;
208 if (family == AF_INET)
209 {
210 struct sockaddr_in *from_addr = (struct sockaddr_in*)from->ai_addr;
211 struct sockaddr_in *ifa_addr = (struct sockaddr_in*)ifa->ifa_addr;
212 if (from_addr->sin_addr.s_addr == ifa_addr->sin_addr.s_addr) {
213 match = 1;
214 break;
215 }
216 }
217 else if (family == AF_INET6)
218 {
219 struct sockaddr_in6 *from_addr = (struct sockaddr_in6*)from->ai_addr;
220 struct sockaddr_in6 *ifa_addr = (struct sockaddr_in6*)ifa->ifa_addr;
221 if (!memcmp(from_addr->sin6_addr.s6_addr, ifa_addr->sin6_addr.s6_addr, 16)) {
222 match = 1;
223 break;
224 }
225 }
226 }
227 }
228 freeifaddrs(ifaddrs_p);
229 return match;
230 }
231
232
233 /* Transparent proxying: bind the peer address of fd to the peer address of
234 * fd_from */
235 #define IP_TRANSPARENT 19
bind_peer(int fd,int fd_from)236 int bind_peer(int fd, int fd_from)
237 {
238 struct addrinfo from;
239 struct sockaddr_storage ss;
240 int res, trans = 1;
241
242 memset(&from, 0, sizeof(from));
243 from.ai_addr = (struct sockaddr*)&ss;
244 from.ai_addrlen = sizeof(ss);
245
246 /* getpeername can fail with ENOTCONN if connection was dropped before we
247 * got here */
248 res = getpeername(fd_from, from.ai_addr, &from.ai_addrlen);
249 CHECK_RES_RETURN(res, "getpeername", res);
250
251 /* if the destination is the same machine, there's no need to do bind */
252 if (is_same_machine(&from))
253 return 0;
254
255 #ifndef IP_BINDANY /* use IP_TRANSPARENT */
256 res = setsockopt(fd, IPPROTO_IP, IP_TRANSPARENT, &trans, sizeof(trans));
257 CHECK_RES_DIE(res, "setsockopt IP_TRANSPARENT");
258 #else
259 if (from.ai_addr->sa_family==AF_INET) { /* IPv4 */
260 res = setsockopt(fd, IPPROTO_IP, IP_BINDANY, &trans, sizeof(trans));
261 CHECK_RES_RETURN(res, "setsockopt IP_BINDANY", res);
262 #ifdef IPV6_BINDANY
263 } else { /* IPv6 */
264 res = setsockopt(fd, IPPROTO_IPV6, IPV6_BINDANY, &trans, sizeof(trans));
265 CHECK_RES_RETURN(res, "setsockopt IPV6_BINDANY", res);
266 #endif /* IPV6_BINDANY */
267 }
268 #endif /* IP_TRANSPARENT / IP_BINDANY */
269 res = bind(fd, from.ai_addr, from.ai_addrlen);
270 CHECK_RES_RETURN(res, "bind", res);
271
272 return 0;
273 }
274
275 /* Connect to first address that works and returns a file descriptor, or -1 if
276 * none work.
277 * If transparent proxying is on, use fd_from peer address on external address
278 * of new file descriptor. */
connect_addr(struct connection * cnx,int fd_from)279 int connect_addr(struct connection *cnx, int fd_from)
280 {
281 struct addrinfo *a, from;
282 struct sockaddr_storage ss;
283 char buf[NI_MAXHOST];
284 int fd, res, one;
285
286 memset(&from, 0, sizeof(from));
287 from.ai_addr = (struct sockaddr*)&ss;
288 from.ai_addrlen = sizeof(ss);
289
290 res = getpeername(fd_from, from.ai_addr, &from.ai_addrlen);
291 CHECK_RES_RETURN(res, "getpeername", res);
292
293 for (a = cnx->proto->saddr; a; a = a->ai_next) {
294 /* When transparent, make sure both connections use the same address family */
295 if (cfg.transparent && a->ai_family != from.ai_addr->sa_family)
296 continue;
297 if (cfg.verbose)
298 fprintf(stderr, "connecting to %s family %d len %d\n",
299 sprintaddr(buf, sizeof(buf), a),
300 a->ai_addr->sa_family, a->ai_addrlen);
301
302 /* XXX Needs to match ai_family from fd_from when being transparent! */
303 fd = socket(a->ai_family, SOCK_STREAM, 0);
304 if (fd == -1) {
305 log_message(LOG_ERR, "forward to %s failed:socket: %s\n",
306 cnx->proto->name, strerror(errno));
307 } else {
308 one = 1;
309 setsockopt(fd, IPPROTO_TCP, TCP_FASTOPEN_CONNECT, &one, sizeof(one));
310 /* no need to check return value; if it's not supported, that's okay */
311
312 if (cfg.transparent) {
313 res = bind_peer(fd, fd_from);
314 CHECK_RES_RETURN(res, "bind_peer", res);
315 }
316 res = connect(fd, a->ai_addr, a->ai_addrlen);
317 if (res == -1) {
318 switch (errno) {
319 case EINPROGRESS:
320 /* Can't be done yet, or TFO already done */
321 break;
322
323 default:
324 log_message(LOG_ERR, "forward to %s failed:connect: %s\n",
325 cnx->proto->name, strerror(errno));
326 close(fd);
327 }
328 } else {
329 if (cnx->proto->keepalive) {
330 res = setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, (char*)&one, sizeof(one));
331 CHECK_RES_RETURN(res, "setsockopt(SO_KEEPALIVE)", res);
332 }
333 return fd;
334 }
335 }
336 }
337 return -1;
338 }
339
340 /* Store some data to write to the queue later */
defer_write(struct queue * q,void * data,int data_size)341 int defer_write(struct queue *q, void* data, int data_size)
342 {
343 char *p;
344 ptrdiff_t data_offset = q->deferred_data - q->begin_deferred_data;
345 if (cfg.verbose)
346 fprintf(stderr, "**** writing deferred on fd %d\n", q->fd);
347
348 p = realloc(q->begin_deferred_data, data_offset + q->deferred_data_size + data_size);
349 CHECK_ALLOC(p, "realloc");
350
351 q->begin_deferred_data = p;
352 q->deferred_data = p + data_offset;
353 p += data_offset + q->deferred_data_size;
354 q->deferred_data_size += data_size;
355 memcpy(p, data, data_size);
356
357 return 0;
358 }
359
360 /* tries to flush some of the data for specified queue
361 * Upon success, the number of bytes written is returned.
362 * Upon failure, -1 returned (e.g. connexion closed)
363 * */
flush_deferred(struct queue * q)364 int flush_deferred(struct queue *q)
365 {
366 int n;
367
368 if (cfg.verbose)
369 fprintf(stderr, "flushing deferred data to fd %d\n", q->fd);
370
371 n = write(q->fd, q->deferred_data, q->deferred_data_size);
372 if (n == -1)
373 return n;
374
375 if (n == q->deferred_data_size) {
376 /* All has been written -- release the memory */
377 free(q->begin_deferred_data);
378 q->begin_deferred_data = NULL;
379 q->deferred_data = NULL;
380 q->deferred_data_size = 0;
381 } else {
382 /* There is data left */
383 q->deferred_data += n;
384 q->deferred_data_size -= n;
385 }
386
387 return n;
388 }
389
390
init_cnx(struct connection * cnx)391 void init_cnx(struct connection *cnx)
392 {
393 memset(cnx, 0, sizeof(*cnx));
394 cnx->q[0].fd = -1;
395 cnx->q[1].fd = -1;
396 cnx->proto = NULL;
397 }
398
dump_connection(struct connection * cnx)399 void dump_connection(struct connection *cnx)
400 {
401 printf("state: %d\n", cnx->state);
402 printf("fd %d, %d deferred\n", cnx->q[0].fd, cnx->q[0].deferred_data_size);
403 printf("fd %d, %d deferred\n", cnx->q[1].fd, cnx->q[1].deferred_data_size);
404 }
405
406
407 /*
408 * moves data from one fd to other
409 *
410 * returns number of bytes copied if success
411 * returns 0 (FD_CNXCLOSED) if incoming socket closed
412 * returns FD_NODATA if no data was available
413 * returns FD_STALLED if data was read, could not be written, and has been
414 * stored in temporary buffer.
415 */
fd2fd(struct queue * target_q,struct queue * from_q)416 int fd2fd(struct queue *target_q, struct queue *from_q)
417 {
418 char buffer[BUFSIZ];
419 int target, from, size_r, size_w;
420
421 target = target_q->fd;
422 from = from_q->fd;
423
424 size_r = read(from, buffer, sizeof(buffer));
425 if (size_r == -1) {
426 switch (errno) {
427 case EAGAIN:
428 if (cfg.verbose)
429 fprintf(stderr, "reading 0 from %d\n", from);
430 return FD_NODATA;
431
432 case ECONNRESET:
433 case EPIPE:
434 return FD_CNXCLOSED;
435 }
436 }
437
438 CHECK_RES_RETURN(size_r, "read",FD_CNXCLOSED);
439
440 if (size_r == 0)
441 return FD_CNXCLOSED;
442
443 size_w = write(target, buffer, size_r);
444 /* process -1 when we know how to deal with it */
445 if (size_w == -1) {
446 switch (errno) {
447 case EAGAIN:
448 /* write blocked: Defer data */
449 defer_write(target_q, buffer, size_r);
450 return FD_STALLED;
451
452 case ECONNRESET:
453 case EPIPE:
454 /* remove end closed -- drop the connection */
455 return FD_CNXCLOSED;
456 }
457 } else if (size_w < size_r) {
458 /* incomplete write -- defer the rest of the data */
459 defer_write(target_q, buffer + size_w, size_r - size_w);
460 return FD_STALLED;
461 }
462
463 CHECK_RES_RETURN(size_w, "write", FD_CNXCLOSED);
464
465 return size_w;
466 }
467
468 /* returns a string that prints the IP and port of the sockaddr */
sprintaddr(char * buf,size_t size,struct addrinfo * a)469 char* sprintaddr(char* buf, size_t size, struct addrinfo *a)
470 {
471 char host[NI_MAXHOST], serv[NI_MAXSERV];
472 int res;
473
474 res = getnameinfo(a->ai_addr, a->ai_addrlen,
475 host, sizeof(host),
476 serv, sizeof(serv),
477 cfg.numeric ? NI_NUMERICHOST | NI_NUMERICSERV : 0 );
478
479 if (res) {
480 log_message(LOG_ERR, "sprintaddr:getnameinfo: %s\n", gai_strerror(res));
481 /* Name resolution failed: do it numerically instead */
482 res = getnameinfo(a->ai_addr, a->ai_addrlen,
483 host, sizeof(host),
484 serv, sizeof(serv),
485 NI_NUMERICHOST | NI_NUMERICSERV);
486 /* should not fail but... */
487 if (res) {
488 log_message(LOG_ERR, "sprintaddr:getnameinfo(NUM): %s\n", gai_strerror(res));
489 strcpy(host, "?");
490 strcpy(serv, "?");
491 }
492 }
493
494 snprintf(buf, size, "%s:%s", host, serv);
495
496 return buf;
497 }
498
499 /* Turns a hostname and port (or service) into a list of struct addrinfo
500 * returns 0 on success, -1 otherwise and logs error
501 */
resolve_split_name(struct addrinfo ** out,char * host,char * serv)502 int resolve_split_name(struct addrinfo **out, char* host, char* serv)
503 {
504 struct addrinfo hint;
505 char *end;
506 int res;
507
508 memset(&hint, 0, sizeof(hint));
509 hint.ai_family = PF_UNSPEC;
510 hint.ai_socktype = SOCK_STREAM;
511
512 /* If it is a RFC-Compliant IPv6 address ("[1234::12]:443"), remove brackets
513 * around IP address */
514 if (host[0] == '[') {
515 end = strrchr(host, ']');
516 if (!end) {
517 fprintf(stderr, "%s: no closing bracket in IPv6 address?\n", host);
518 return -1;
519 }
520 host++; /* skip first bracket */
521 *end = 0; /* remove last bracket */
522 }
523
524 res = getaddrinfo(host, serv, &hint, out);
525 if (res)
526 log_message(LOG_ERR, "%s `%s:%s'\n", gai_strerror(res), host, serv);
527 return res;
528 }
529
530 /* turns a "hostname:port" string into a list of struct addrinfo;
531 out: list of newly allocated addrinfo (see getaddrinfo(3)); freeaddrinfo(3) when done
532 fullname: input string -- it gets clobbered
533 */
resolve_name(struct addrinfo ** out,char * fullname)534 void resolve_name(struct addrinfo **out, char* fullname)
535 {
536 char *serv, *host;
537 int res;
538
539 /* Find port */
540 char *sep = strrchr(fullname, ':');
541 if (!sep) { /* No separator: parameter is just a port */
542 fprintf(stderr, "%s: names must be fully specified as hostname:port\n", fullname);
543 exit(1);
544 }
545 serv = sep+1;
546 *sep = 0;
547
548 host = fullname;
549
550 res = resolve_split_name(out, host, serv);
551 if (res) {
552 fprintf(stderr, "%s `%s'\n", gai_strerror(res), fullname);
553 if (res == EAI_SERVICE)
554 fprintf(stderr, "(Check you have specified all ports)\n");
555 exit(4);
556 }
557 }
558
559 /* Log to syslog or stderr if foreground */
log_message(int type,const char * msg,...)560 void log_message(int type, const char* msg, ...)
561 {
562 va_list ap;
563
564 va_start(ap, msg);
565 if (cfg.foreground)
566 vfprintf(stderr, msg, ap);
567 va_end(ap);
568
569 if (do_syslog) {
570 va_start(ap, msg);
571 vsyslog(type, msg, ap);
572 va_end(ap);
573 }
574 }
575
576
577 /* Fills a connection description; returns 0 on failure */
get_connection_desc(struct connection_desc * desc,const struct connection * cnx)578 int get_connection_desc(struct connection_desc* desc, const struct connection *cnx)
579 {
580 int res;
581 struct addrinfo addr;
582 struct sockaddr_storage ss;
583
584 addr.ai_addr = (struct sockaddr*)&ss;
585 addr.ai_addrlen = sizeof(ss);
586
587 res = getpeername(cnx->q[0].fd, addr.ai_addr, &addr.ai_addrlen);
588 if (res == -1) return 0; /* Can happen if connection drops before we get here.
589 In that case, don't log anything (there is no connection) */
590 sprintaddr(desc->peer, sizeof(desc->peer), &addr);
591
592 addr.ai_addrlen = sizeof(ss);
593 res = getsockname(cnx->q[0].fd, addr.ai_addr, &addr.ai_addrlen);
594 if (res == -1) return 0;
595 sprintaddr(desc->service, sizeof(desc->service), &addr);
596
597 addr.ai_addrlen = sizeof(ss);
598 res = getpeername(cnx->q[1].fd, addr.ai_addr, &addr.ai_addrlen);
599 if (res == -1) return 0;
600 sprintaddr(desc->target, sizeof(desc->target), &addr);
601
602 addr.ai_addrlen = sizeof(ss);
603 res = getsockname(cnx->q[1].fd, addr.ai_addr, &addr.ai_addrlen);
604 if (res == -1) return 0;
605 sprintaddr(desc->local, sizeof(desc->local), &addr);
606
607 return 1;
608 }
609
610 /* syslogs who connected to where
611 * desc: string description of the connection. if NULL, log_connection will
612 * manage on its own
613 * cnx: connection descriptor
614 * */
log_connection(struct connection_desc * desc,const struct connection * cnx)615 void log_connection(struct connection_desc* desc, const struct connection *cnx)
616 {
617 struct connection_desc d;
618
619 if (cnx->proto->log_level < 1)
620 return;
621
622 if (!desc) {
623 desc = &d;
624 get_connection_desc(desc, cnx);
625 }
626
627 log_message(LOG_INFO, "%s:connection from %s to %s forwarded from %s to %s\n",
628 cnx->proto->name,
629 desc->peer,
630 desc->service,
631 desc->local,
632 desc->target);
633 }
634
set_proctitle_shovel(struct connection_desc * desc,const struct connection * cnx)635 void set_proctitle_shovel(struct connection_desc* desc, const struct connection *cnx)
636 {
637 #ifdef LIBBSD
638 struct connection_desc d;
639
640 if (!desc) {
641 desc = &d;
642 get_connection_desc(desc, cnx);
643 }
644 setproctitle("shovel %s %s->%s => %s->%s",
645 cnx->proto->name,
646 desc->peer,
647 desc->service,
648 desc->local,
649 desc->target);
650 #endif
651 }
652
653
654 /* libwrap (tcpd): check the connection is legal. This is necessary because
655 * the actual server will only see a connection coming from localhost and can't
656 * apply the rules itself.
657 *
658 * Returns -1 if access is denied, 0 otherwise
659 */
check_access_rights(int in_socket,const char * service)660 int check_access_rights(int in_socket, const char* service)
661 {
662 #ifdef LIBWRAP
663 union {
664 struct sockaddr saddr;
665 struct sockaddr_storage ss;
666 } peer;
667 socklen_t size = sizeof(peer);
668 char addr_str[NI_MAXHOST], host[NI_MAXHOST];
669 int res;
670
671 res = getpeername(in_socket, &peer.saddr, &size);
672 CHECK_RES_RETURN(res, "getpeername", res);
673
674 /* extract peer address */
675 res = getnameinfo(&peer.saddr, size, addr_str, sizeof(addr_str), NULL, 0, NI_NUMERICHOST);
676 if (res) {
677 if (cfg.verbose)
678 fprintf(stderr, "getnameinfo(NI_NUMERICHOST):%s\n", gai_strerror(res));
679 strcpy(addr_str, STRING_UNKNOWN);
680 }
681 /* extract peer name */
682 strcpy(host, STRING_UNKNOWN);
683 if (!cfg.numeric) {
684 res = getnameinfo(&peer.saddr, size, host, sizeof(host), NULL, 0, NI_NAMEREQD);
685 if (res) {
686 if (cfg.verbose)
687 fprintf(stderr, "getnameinfo(NI_NAMEREQD):%s\n", gai_strerror(res));
688 }
689 }
690
691 if (!hosts_ctl(service, host, addr_str, STRING_UNKNOWN)) {
692 if (cfg.verbose)
693 fprintf(stderr, "access denied\n");
694 log_message(LOG_INFO, "connection from %s(%s): access denied", host, addr_str);
695 close(in_socket);
696 return -1;
697 }
698 #endif
699 return 0;
700 }
701
setup_signals(void)702 void setup_signals(void)
703 {
704 int res;
705 struct sigaction action;
706
707 /* Request no SIGCHLD is sent upon termination of
708 * the children */
709 memset(&action, 0, sizeof(action));
710 action.sa_handler = NULL;
711 action.sa_flags = SA_NOCLDWAIT;
712 res = sigaction(SIGCHLD, &action, NULL);
713 CHECK_RES_DIE(res, "sigaction");
714
715 /* Set SIGTERM to exit. For some reason if it's not set explicitly,
716 * coverage information is lost when killing the process */
717 memset(&action, 0, sizeof(action));
718 action.sa_handler = exit;
719 res = sigaction(SIGTERM, &action, NULL);
720 CHECK_RES_DIE(res, "sigaction");
721
722 /* Ignore SIGPIPE . */
723 action.sa_handler = SIG_IGN;
724 res = sigaction(SIGPIPE, &action, NULL);
725 CHECK_RES_DIE(res, "sigaction");
726
727 }
728
729 /* Open syslog connection with appropriate banner;
730 * banner is made up of basename(bin_name)+"[pid]" */
setup_syslog(const char * bin_name)731 void setup_syslog(const char* bin_name) {
732 char *name1, *name2;
733 int res, fn;
734
735 if (!strcmp(cfg.syslog_facility, "none")) {
736 do_syslog = 0;
737 return;
738 }
739
740 name1 = strdup(bin_name);
741 res = asprintf(&name2, "%s[%d]", basename(name1), getpid());
742 CHECK_RES_DIE(res, "asprintf");
743
744 for (fn = 0; facilitynames[fn].c_val != -1; fn++)
745 if (strcmp(facilitynames[fn].c_name, cfg.syslog_facility) == 0)
746 break;
747 if (facilitynames[fn].c_val == -1) {
748 fprintf(stderr, "Unknown facility %s\n", cfg.syslog_facility);
749 exit(1);
750 }
751
752 openlog(name2, LOG_CONS, facilitynames[fn].c_val);
753 free(name1);
754 /* Don't free name2, as openlog(3) uses it (at least in glibc) */
755
756 log_message(LOG_INFO, "%s %s started\n", server_type, VERSION);
757 }
758
759 /* Ask OS to keep capabilities over a setuid(nonzero) */
set_keepcaps(int val)760 void set_keepcaps(int val) {
761 #ifdef LIBCAP
762 int res;
763 res = prctl(PR_SET_KEEPCAPS, val, 0, 0, 0);
764 if (res) {
765 perror("prctl");
766 exit(1);
767 }
768 #endif
769 }
770
771 /* set needed capabilities for effective and permitted, clear rest */
set_capabilities(void)772 void set_capabilities(void) {
773 #ifdef LIBCAP
774 int res;
775 cap_t caps;
776 cap_value_t cap_list[10];
777 int ncap = 0;
778
779 if (cfg.transparent)
780 cap_list[ncap++] = CAP_NET_ADMIN;
781
782 caps = cap_init();
783
784 #define _cap_set_flag(flag) do { \
785 res = cap_clear_flag(caps, flag); \
786 CHECK_RES_DIE(res, "cap_clear_flag(" #flag ")"); \
787 if (ncap > 0) { \
788 res = cap_set_flag(caps, flag, ncap, cap_list, CAP_SET); \
789 CHECK_RES_DIE(res, "cap_set_flag(" #flag ")"); \
790 } \
791 } while(0)
792
793 _cap_set_flag(CAP_EFFECTIVE);
794 _cap_set_flag(CAP_PERMITTED);
795
796 #undef _cap_set_flag
797
798 res = cap_set_proc(caps);
799 CHECK_RES_DIE(res, "cap_set_proc");
800
801 res = cap_free(caps);
802 if (res) {
803 perror("cap_free");
804 exit(1);
805 }
806 #endif
807 }
808
809 /* We don't want to run as root -- drop privileges if required */
drop_privileges(const char * user_name,const char * chroot_path)810 void drop_privileges(const char* user_name, const char* chroot_path)
811 {
812 int res;
813 struct passwd *pw = NULL;
814
815 if (user_name) {
816 pw = getpwnam(user_name);
817 if (!pw) {
818 fprintf(stderr, "%s: not found\n", user_name);
819 exit(2);
820 }
821 if (cfg.verbose)
822 fprintf(stderr, "turning into %s\n", user_name);
823 }
824
825 if (chroot_path) {
826 if (cfg.verbose)
827 fprintf(stderr, "chrooting into %s\n", chroot_path);
828
829 res = chroot(chroot_path);
830 CHECK_RES_DIE(res, "chroot");
831 }
832
833 if (user_name) {
834 set_keepcaps(1);
835
836 /* remove extraneous groups in case we belong to several extra groups
837 * that may have unwanted rights. If non-root when calling setgroups(),
838 * it fails, which is fine because... we have no unwanted rights
839 * (see POS36-C for security context)
840 * */
841 setgroups(0, NULL);
842
843 res = setgid(pw->pw_gid);
844 CHECK_RES_DIE(res, "setgid");
845 res = setuid(pw->pw_uid);
846 CHECK_RES_DIE(res, "setuid");
847
848 set_capabilities();
849 set_keepcaps(0);
850 }
851 }
852
853 /* Writes my PID */
write_pid_file(const char * pidfile)854 void write_pid_file(const char* pidfile)
855 {
856 FILE *f;
857
858 f = fopen(pidfile, "w");
859 if (!f) {
860 perror(pidfile);
861 exit(3);
862 }
863
864 fprintf(f, "%d\n", getpid());
865 fclose(f);
866 }
867
868