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