1 /* $OpenBSD: inetd.c,v 1.165 2023/09/03 22:01:00 bluhm Exp $ */
2
3 /*
4 * Copyright (c) 1983,1991 The Regents of the University of California.
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the University nor the names of its contributors
16 * may be used to endorse or promote products derived from this software
17 * without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32 /*
33 * Inetd - Internet super-server
34 *
35 * This program invokes all internet services as needed.
36 * connection-oriented services are invoked each time a
37 * connection is made, by creating a process. This process
38 * is passed the connection as file descriptor 0 and is
39 * expected to do a getpeername to find out the source host
40 * and port.
41 *
42 * Datagram oriented services are invoked when a datagram
43 * arrives; a process is created and passed a pending message
44 * on file descriptor 0. Datagram servers may either connect
45 * to their peer, freeing up the original socket for inetd
46 * to receive further messages on, or ``take over the socket'',
47 * processing all arriving datagrams and, eventually, timing
48 * out. The first type of server is said to be ``multi-threaded'';
49 * the second type of server ``single-threaded''.
50 *
51 * Inetd uses a configuration file which is read at startup
52 * and, possibly, at some later time in response to a hangup signal.
53 * The configuration file is ``free format'' with fields given in the
54 * order shown below. Continuation lines for an entry must begin with
55 * a space or tab. All fields must be present in each entry.
56 *
57 * service name must be in /etc/services
58 * socket type stream/dgram
59 * protocol must be in /etc/protocols
60 * wait/nowait[.max] single-threaded/multi-threaded, max #
61 * user[.group] or user[:group] user/group to run daemon as
62 * server program full path name
63 * server program arguments maximum of MAXARGS (20)
64 *
65 * For RPC services
66 * service name/version must be in /etc/rpc
67 * socket type stream/dgram
68 * protocol must be in /etc/protocols
69 * wait/nowait[.max] single-threaded/multi-threaded
70 * user[.group] or user[:group] user to run daemon as
71 * server program full path name
72 * server program arguments maximum of MAXARGS (20)
73 *
74 * For non-RPC services, the "service name" can be of the form
75 * hostaddress:servicename, in which case the hostaddress is used
76 * as the host portion of the address to listen on. If hostaddress
77 * consists of a single `*' character, INADDR_ANY is used.
78 *
79 * A line can also consist of just
80 * hostaddress:
81 * where hostaddress is as in the preceding paragraph. Such a line must
82 * have no further fields; the specified hostaddress is remembered and
83 * used for all further lines that have no hostaddress specified,
84 * until the next such line (or EOF). (This is why * is provided to
85 * allow explicit specification of INADDR_ANY.) A line
86 * *:
87 * is implicitly in effect at the beginning of the file.
88 *
89 * The hostaddress specifier may (and often will) contain dots;
90 * the service name must not.
91 *
92 * For RPC services, host-address specifiers are accepted and will
93 * work to some extent; however, because of limitations in the
94 * portmapper interface, it will not work to try to give more than
95 * one line for any given RPC service, even if the host-address
96 * specifiers are different.
97 *
98 * Comment lines are indicated by a `#' in column 1.
99 */
100
101 /*
102 * Here's the scoop concerning the user[.:]group feature:
103 *
104 * 1) set-group-option off.
105 *
106 * a) user = root: NO setuid() or setgid() is done
107 *
108 * b) other: setgid(primary group as found in passwd)
109 * initgroups(name, primary group)
110 * setuid()
111 *
112 * 2) set-group-option on.
113 *
114 * a) user = root: setgid(specified group)
115 * NO initgroups()
116 * NO setuid()
117 *
118 * b) other: setgid(specified group)
119 * initgroups(name, specified group)
120 * setuid()
121 *
122 */
123
124 #include <sys/stat.h>
125 #include <sys/socket.h>
126 #include <sys/un.h>
127 #include <sys/wait.h>
128 #include <sys/time.h>
129 #include <sys/resource.h>
130
131 #include <net/if.h>
132 #include <netinet/in.h>
133 #include <arpa/inet.h>
134
135 #include <err.h>
136 #include <errno.h>
137 #include <ctype.h>
138 #include <signal.h>
139 #include <netdb.h>
140 #include <syslog.h>
141 #include <pwd.h>
142 #include <grp.h>
143 #include <stdio.h>
144 #include <stdlib.h>
145 #include <unistd.h>
146 #include <limits.h>
147 #include <string.h>
148 #include <login_cap.h>
149 #include <ifaddrs.h>
150 #include <rpc/rpc.h>
151 #include <rpc/pmap_clnt.h>
152 #include <rpcsvc/nfs_prot.h>
153 #include <event.h>
154 #include "pathnames.h"
155
156 #define MINIMUM(a, b) (((a) < (b)) ? (a) : (b))
157
158 #define TOOMANY 256 /* don't start more than TOOMANY */
159 #define CNT_INTVL 60 /* servers in CNT_INTVL sec. */
160 #define RETRYTIME (60*10) /* retry after bind or server fail */
161
162 int debug = 0;
163 int maxsock;
164 int toomany = TOOMANY;
165 int timingout;
166 struct servent *sp;
167 uid_t uid;
168
169 #ifndef OPEN_MAX
170 #define OPEN_MAX 64
171 #endif
172
173 /* Reserve some descriptors, 3 stdio + at least: 1 log, 1 conf. file */
174 #define FD_MARGIN (8)
175 rlim_t rlim_nofile_cur = OPEN_MAX;
176
177 struct rlimit rlim_nofile;
178
179 struct servtab {
180 char *se_hostaddr; /* host address to listen on */
181 char *se_service; /* name of service */
182 int se_socktype; /* type of socket to use */
183 int se_family; /* address family */
184 char *se_proto; /* protocol used */
185 int se_rpcprog; /* rpc program number */
186 int se_rpcversl; /* rpc program lowest version */
187 int se_rpcversh; /* rpc program highest version */
188 #define isrpcservice(sep) ((sep)->se_rpcversl != 0)
189 pid_t se_wait; /* single threaded server */
190 short se_checked; /* looked at during merge */
191 char *se_user; /* user name to run as */
192 char *se_group; /* group name to run as */
193 struct biltin *se_bi; /* if built-in, description */
194 char *se_server; /* server program */
195 #define MAXARGV 20
196 char *se_argv[MAXARGV+1]; /* program arguments */
197 int se_fd; /* open descriptor */
198 union {
199 struct sockaddr se_un_ctrladdr;
200 struct sockaddr_in se_un_ctrladdr_in;
201 struct sockaddr_in6 se_un_ctrladdr_in6;
202 struct sockaddr_un se_un_ctrladdr_un;
203 struct sockaddr_storage se_un_ctrladdr_storage;
204 } se_un; /* bound address */
205 #define se_ctrladdr se_un.se_un_ctrladdr
206 #define se_ctrladdr_in se_un.se_un_ctrladdr_in
207 #define se_ctrladdr_in6 se_un.se_un_ctrladdr_in6
208 #define se_ctrladdr_un se_un.se_un_ctrladdr_un
209 #define se_ctrladdr_storage se_un.se_un_ctrladdr_storage
210 int se_ctrladdr_size;
211 int se_max; /* max # of instances of this service */
212 int se_count; /* number started since se_time */
213 struct timeval se_time; /* start of se_count */
214 struct servtab *se_next;
215 struct event se_event;
216 } *servtab;
217
218 void echo_stream(int, struct servtab *);
219 void discard_stream(int, struct servtab *);
220 void machtime_stream(int, struct servtab *);
221 void daytime_stream(int, struct servtab *);
222 void chargen_stream(int, struct servtab *);
223 void echo_dg(int, struct servtab *);
224 void discard_dg(int, struct servtab *);
225 void machtime_dg(int, struct servtab *);
226 void daytime_dg(int, struct servtab *);
227 void chargen_dg(int, struct servtab *);
228
229 struct biltin {
230 char *bi_service; /* internally provided service name */
231 int bi_socktype; /* type of socket supported */
232 short bi_fork; /* 1 if should fork before call */
233 short bi_wait; /* 1 if should wait for child */
234 void (*bi_fn)(int, struct servtab *);
235 } biltins[] = {
236 /* Echo received data */
237 { "echo", SOCK_STREAM, 1, 0, echo_stream },
238 { "echo", SOCK_DGRAM, 0, 0, echo_dg },
239
240 /* Internet /dev/null */
241 { "discard", SOCK_STREAM, 1, 0, discard_stream },
242 { "discard", SOCK_DGRAM, 0, 0, discard_dg },
243
244 /* Return 32 bit time since 1900 */
245 { "time", SOCK_STREAM, 0, 0, machtime_stream },
246 { "time", SOCK_DGRAM, 0, 0, machtime_dg },
247
248 /* Return human-readable time */
249 { "daytime", SOCK_STREAM, 0, 0, daytime_stream },
250 { "daytime", SOCK_DGRAM, 0, 0, daytime_dg },
251
252 /* Familiar character generator */
253 { "chargen", SOCK_STREAM, 1, 0, chargen_stream },
254 { "chargen", SOCK_DGRAM, 0, 0, chargen_dg },
255
256 { 0 }
257 };
258
259 struct event evsig_alrm;
260 struct event evsig_hup;
261 struct event evsig_chld;
262 struct event evsig_term;
263 struct event evsig_int;
264
265 void config(int, short, void *);
266 void reap(int, short, void *);
267 void retry(int, short, void *);
268 void die(int, short, void *);
269
270 void spawn(int, short, void *);
271 void gettcp(int, short, void *);
272 int setconfig(void);
273 void endconfig(void);
274 void register_rpc(struct servtab *);
275 void unregister_rpc(struct servtab *);
276 void freeconfig(struct servtab *);
277 void print_service(char *, struct servtab *);
278 void setup(struct servtab *);
279 struct servtab *getconfigent(void);
280 int bump_nofile(void);
281 struct servtab *enter(struct servtab *);
282 int matchconf(struct servtab *, struct servtab *);
283 int dg_broadcast(struct in_addr *in);
284
285 #define NUMINT (sizeof(intab) / sizeof(struct inent))
286 char *CONFIG = _PATH_INETDCONF;
287
288 int dg_badinput(struct sockaddr *sa);
289 void inetd_setproctitle(char *a, int s);
290 void initring(void);
291 u_int32_t machtime(void);
292
293 int
main(int argc,char * argv[])294 main(int argc, char *argv[])
295 {
296 int ch;
297
298 while ((ch = getopt(argc, argv, "dR:")) != -1)
299 switch (ch) {
300 case 'd':
301 debug = 1;
302 break;
303 case 'R': { /* invocation rate */
304 char *p;
305 int val;
306
307 val = strtoul(optarg, &p, 0);
308 if (val >= 1 && *p == '\0') {
309 toomany = val;
310 break;
311 }
312 syslog(LOG_ERR,
313 "-R %s: bad value for service invocation rate",
314 optarg);
315 break;
316 }
317 default:
318 fprintf(stderr,
319 "usage: inetd [-d] [-R rate] [configuration_file]\n");
320 exit(1);
321 }
322 argc -= optind;
323 argv += optind;
324
325 uid = getuid();
326 if (uid != 0)
327 CONFIG = NULL;
328 if (argc > 0)
329 CONFIG = argv[0];
330 if (CONFIG == NULL) {
331 fprintf(stderr, "inetd: non-root must specify a config file\n");
332 exit(1);
333 }
334 if (argc > 1) {
335 fprintf(stderr, "inetd: more than one argument specified\n");
336 exit(1);
337 }
338
339 umask(022);
340 if (debug == 0) {
341 daemon(0, 0);
342 if (uid == 0)
343 (void) setlogin("");
344 }
345
346 if (pledge("stdio rpath cpath getpw dns inet unix proc exec id", NULL) == -1)
347 err(1, "pledge");
348
349 if (uid == 0) {
350 gid_t gid = getgid();
351
352 /* If run by hand, ensure groups vector gets trashed */
353 setgroups(1, &gid);
354 }
355
356 openlog("inetd", LOG_PID | LOG_NOWAIT, LOG_DAEMON);
357
358 if (getrlimit(RLIMIT_NOFILE, &rlim_nofile) == -1) {
359 syslog(LOG_ERR, "getrlimit: %m");
360 } else {
361 rlim_nofile_cur = rlim_nofile.rlim_cur;
362 if (rlim_nofile_cur == RLIM_INFINITY) /* ! */
363 rlim_nofile_cur = OPEN_MAX;
364 }
365
366 event_init();
367
368 signal_set(&evsig_alrm, SIGALRM, retry, NULL);
369 signal_add(&evsig_alrm, NULL);
370
371 config(0, 0, NULL);
372
373 signal_set(&evsig_hup, SIGHUP, config, NULL);
374 signal_add(&evsig_hup, NULL);
375 signal_set(&evsig_chld, SIGCHLD, reap, NULL);
376 signal_add(&evsig_chld, NULL);
377 signal_set(&evsig_term, SIGTERM, die, NULL);
378 signal_add(&evsig_term, NULL);
379 signal_set(&evsig_int, SIGINT, die, NULL);
380 signal_add(&evsig_int, NULL);
381
382 signal(SIGPIPE, SIG_IGN);
383
384 event_dispatch();
385
386 return (0);
387 }
388
389 void
gettcp(int fd,short events,void * xsep)390 gettcp(int fd, short events, void *xsep)
391 {
392 struct servtab *sep = xsep;
393 int ctrl;
394
395 if (debug)
396 fprintf(stderr, "someone wants %s\n", sep->se_service);
397
398 ctrl = accept(sep->se_fd, NULL, NULL);
399 if (debug)
400 fprintf(stderr, "accept, ctrl %d\n", ctrl);
401 if (ctrl == -1) {
402 if (errno != EWOULDBLOCK && errno != EINTR &&
403 errno != ECONNABORTED)
404 syslog(LOG_WARNING, "accept (for %s): %m",
405 sep->se_service);
406 return;
407 }
408 if ((sep->se_family == AF_INET || sep->se_family == AF_INET6) &&
409 sep->se_socktype == SOCK_STREAM) {
410 struct sockaddr_storage peer;
411 socklen_t plen = sizeof(peer);
412 char sbuf[NI_MAXSERV];
413
414 if (getpeername(ctrl, (struct sockaddr *)&peer, &plen) == -1) {
415 syslog(LOG_WARNING, "could not getpeername");
416 close(ctrl);
417 return;
418 }
419 if (getnameinfo((struct sockaddr *)&peer, plen, NULL, 0,
420 sbuf, sizeof(sbuf), NI_NUMERICSERV) == 0 &&
421 strtonum(sbuf, 1, USHRT_MAX, NULL) == 20) {
422 /*
423 * ignore things that look like ftp bounce
424 */
425 close(ctrl);
426 return;
427 }
428 }
429
430 spawn(ctrl, 0, sep);
431 }
432
433 int
dg_badinput(struct sockaddr * sa)434 dg_badinput(struct sockaddr *sa)
435 {
436 struct in_addr in;
437 struct in6_addr *in6;
438 u_int16_t port;
439
440 switch (sa->sa_family) {
441 case AF_INET:
442 in.s_addr = ntohl(((struct sockaddr_in *)sa)->sin_addr.s_addr);
443 port = ntohs(((struct sockaddr_in *)sa)->sin_port);
444 if (IN_MULTICAST(in.s_addr))
445 goto bad;
446 switch ((in.s_addr & 0xff000000) >> 24) {
447 case 0: case 255:
448 goto bad;
449 }
450 if (dg_broadcast(&in))
451 goto bad;
452 break;
453 case AF_INET6:
454 in6 = &((struct sockaddr_in6 *)sa)->sin6_addr;
455 port = ntohs(((struct sockaddr_in6 *)sa)->sin6_port);
456 if (IN6_IS_ADDR_MULTICAST(in6) || IN6_IS_ADDR_UNSPECIFIED(in6))
457 goto bad;
458 /*
459 * OpenBSD does not support IPv4-mapped and
460 * IPv4-compatible IPv6 addresses (RFC2553). We should
461 * drop the packet.
462 */
463 if (IN6_IS_ADDR_V4MAPPED(in6) || IN6_IS_ADDR_V4COMPAT(in6))
464 goto bad;
465 break;
466 default:
467 /* Unsupported AF */
468 goto bad;
469 }
470
471 if (port < IPPORT_RESERVED || port == NFS_PORT)
472 goto bad;
473
474 return (0);
475
476 bad:
477 return (1);
478 }
479
480 int
dg_broadcast(struct in_addr * in)481 dg_broadcast(struct in_addr *in)
482 {
483 struct ifaddrs *ifa, *ifap;
484 struct sockaddr_in *sin;
485
486 if (getifaddrs(&ifap) == -1)
487 return (0);
488 for (ifa = ifap; ifa; ifa = ifa->ifa_next) {
489 if (ifa->ifa_addr == NULL ||
490 ifa->ifa_addr->sa_family != AF_INET ||
491 (ifa->ifa_flags & IFF_BROADCAST) == 0)
492 continue;
493 sin = (struct sockaddr_in *)ifa->ifa_broadaddr;
494 if (sin->sin_addr.s_addr == in->s_addr) {
495 freeifaddrs(ifap);
496 return (1);
497 }
498 }
499 freeifaddrs(ifap);
500 return (0);
501 }
502
503 void
reap(int sig,short event,void * arg)504 reap(int sig, short event, void *arg)
505 {
506 struct servtab *sep;
507 int status;
508 pid_t pid;
509
510 if (debug)
511 fprintf(stderr, "reaping asked for\n");
512
513 for (;;) {
514 if ((pid = wait3(&status, WNOHANG, NULL)) <= 0) {
515 if (pid == -1 && errno == EINTR)
516 continue;
517 break;
518 }
519 if (debug)
520 fprintf(stderr, "%ld reaped, status %x\n",
521 (long)pid, status);
522 for (sep = servtab; sep; sep = sep->se_next)
523 if (sep->se_wait == pid) {
524 if (WIFEXITED(status) && WEXITSTATUS(status))
525 syslog(LOG_WARNING,
526 "%s: exit status %d",
527 sep->se_server, WEXITSTATUS(status));
528 else if (WIFSIGNALED(status))
529 syslog(LOG_WARNING,
530 "%s: exit signal %d",
531 sep->se_server, WTERMSIG(status));
532 sep->se_wait = 1;
533 event_add(&sep->se_event, NULL);
534 if (debug)
535 fprintf(stderr, "restored %s, fd %d\n",
536 sep->se_service, sep->se_fd);
537 }
538 }
539 }
540
541 void
config(int sig,short event,void * arg)542 config(int sig, short event, void *arg)
543 {
544 struct servtab *sep, *cp, **sepp;
545 int add;
546 char protoname[11];
547
548 if (!setconfig()) {
549 syslog(LOG_ERR, "%s: %m", CONFIG);
550 exit(1);
551 }
552 for (sep = servtab; sep; sep = sep->se_next)
553 sep->se_checked = 0;
554 cp = getconfigent();
555 while (cp != NULL) {
556 for (sep = servtab; sep; sep = sep->se_next)
557 if (matchconf(sep, cp))
558 break;
559 add = 0;
560 if (sep != NULL) {
561 int i;
562
563 #define SWAP(type, a, b) {type c=(type)a; a=(type)b; b=(type)c;}
564
565 /*
566 * sep->se_wait may be holding the pid of a daemon
567 * that we're waiting for. If so, don't overwrite
568 * it unless the config file explicitly says don't
569 * wait.
570 */
571 if (cp->se_bi == 0 &&
572 (sep->se_wait == 1 || cp->se_wait == 0))
573 sep->se_wait = cp->se_wait;
574 SWAP(int, cp->se_max, sep->se_max);
575 SWAP(char *, sep->se_user, cp->se_user);
576 SWAP(char *, sep->se_group, cp->se_group);
577 SWAP(char *, sep->se_server, cp->se_server);
578 for (i = 0; i < MAXARGV; i++)
579 SWAP(char *, sep->se_argv[i], cp->se_argv[i]);
580 #undef SWAP
581 if (isrpcservice(sep))
582 unregister_rpc(sep);
583 sep->se_rpcversl = cp->se_rpcversl;
584 sep->se_rpcversh = cp->se_rpcversh;
585 freeconfig(cp);
586 add = 1;
587 } else {
588 sep = enter(cp);
589 }
590 sep->se_checked = 1;
591
592 switch (sep->se_family) {
593 case AF_UNIX:
594 if (sep->se_fd != -1)
595 break;
596 sep->se_ctrladdr_size =
597 strlcpy(sep->se_ctrladdr_un.sun_path,
598 sep->se_service,
599 sizeof sep->se_ctrladdr_un.sun_path);
600 if (sep->se_ctrladdr_size >=
601 sizeof sep->se_ctrladdr_un.sun_path) {
602 syslog(LOG_WARNING, "%s/%s: UNIX domain socket "
603 "path too long", sep->se_service,
604 sep->se_proto);
605 goto serv_unknown;
606 }
607 sep->se_ctrladdr_un.sun_family = AF_UNIX;
608 sep->se_ctrladdr_size +=
609 1 + sizeof sep->se_ctrladdr_un.sun_family;
610 (void)unlink(sep->se_service);
611 setup(sep);
612 break;
613 case AF_INET:
614 sep->se_ctrladdr_in.sin_family = AF_INET;
615 /* se_ctrladdr_in was set in getconfigent */
616 sep->se_ctrladdr_size = sizeof sep->se_ctrladdr_in;
617
618 if (isrpcservice(sep)) {
619 struct rpcent *rp;
620
621 sep->se_rpcprog = strtonum(sep->se_service,
622 1, USHRT_MAX, NULL);
623 if (sep->se_rpcprog == 0) {
624 rp = getrpcbyname(sep->se_service);
625 if (rp == 0) {
626 syslog(LOG_ERR,
627 "%s: unknown rpc service",
628 sep->se_service);
629 goto serv_unknown;
630 }
631 sep->se_rpcprog = rp->r_number;
632 }
633 if (sep->se_fd == -1)
634 setup(sep);
635 if (sep->se_fd != -1)
636 register_rpc(sep);
637 } else {
638 u_short port = htons(strtonum(sep->se_service,
639 1, USHRT_MAX, NULL));
640
641 if (!port) {
642 (void)strlcpy(protoname, sep->se_proto,
643 sizeof(protoname));
644 if (isdigit((unsigned char)
645 protoname[strlen(protoname) - 1]))
646 protoname[strlen(protoname) - 1] = '\0';
647 sp = getservbyname(sep->se_service,
648 protoname);
649 if (sp == 0) {
650 syslog(LOG_ERR,
651 "%s/%s: unknown service",
652 sep->se_service, sep->se_proto);
653 goto serv_unknown;
654 }
655 port = sp->s_port;
656 }
657 if (port != sep->se_ctrladdr_in.sin_port) {
658 sep->se_ctrladdr_in.sin_port = port;
659 if (sep->se_fd != -1) {
660 event_del(&sep->se_event);
661 (void) close(sep->se_fd);
662 }
663 sep->se_fd = -1;
664 }
665 if (sep->se_fd == -1)
666 setup(sep);
667 }
668 break;
669 case AF_INET6:
670 sep->se_ctrladdr_in6.sin6_family = AF_INET6;
671 /* se_ctrladdr_in was set in getconfigent */
672 sep->se_ctrladdr_size = sizeof sep->se_ctrladdr_in6;
673
674 if (isrpcservice(sep)) {
675 struct rpcent *rp;
676
677 sep->se_rpcprog = strtonum(sep->se_service,
678 1, USHRT_MAX, NULL);
679 if (sep->se_rpcprog == 0) {
680 rp = getrpcbyname(sep->se_service);
681 if (rp == 0) {
682 syslog(LOG_ERR,
683 "%s: unknown rpc service",
684 sep->se_service);
685 goto serv_unknown;
686 }
687 sep->se_rpcprog = rp->r_number;
688 }
689 if (sep->se_fd == -1)
690 setup(sep);
691 if (sep->se_fd != -1)
692 register_rpc(sep);
693 } else {
694 u_short port = htons(strtonum(sep->se_service,
695 1, USHRT_MAX, NULL));
696
697 if (!port) {
698 (void)strlcpy(protoname, sep->se_proto,
699 sizeof(protoname));
700 if (isdigit((unsigned char)
701 protoname[strlen(protoname) - 1]))
702 protoname[strlen(protoname) - 1] = '\0';
703 sp = getservbyname(sep->se_service,
704 protoname);
705 if (sp == 0) {
706 syslog(LOG_ERR,
707 "%s/%s: unknown service",
708 sep->se_service, sep->se_proto);
709 goto serv_unknown;
710 }
711 port = sp->s_port;
712 }
713 if (port != sep->se_ctrladdr_in6.sin6_port) {
714 sep->se_ctrladdr_in6.sin6_port = port;
715 if (sep->se_fd != -1) {
716 event_del(&sep->se_event);
717 (void) close(sep->se_fd);
718 }
719 sep->se_fd = -1;
720 }
721 if (sep->se_fd == -1)
722 setup(sep);
723 }
724 break;
725 }
726 serv_unknown:
727 if (cp->se_next != NULL) {
728 struct servtab *tmp = cp;
729
730 cp = cp->se_next;
731 free(tmp);
732 } else {
733 free(cp);
734 cp = getconfigent();
735 }
736 if (debug)
737 print_service(add ? "REDO" : "ADD", sep);
738 }
739 endconfig();
740 /*
741 * Purge anything not looked at above.
742 */
743 sepp = &servtab;
744 while ((sep = *sepp)) {
745 if (sep->se_checked) {
746 sepp = &sep->se_next;
747 continue;
748 }
749 *sepp = sep->se_next;
750 if (sep->se_fd != -1) {
751 event_del(&sep->se_event);
752 (void) close(sep->se_fd);
753 }
754 if (isrpcservice(sep))
755 unregister_rpc(sep);
756 if (sep->se_family == AF_UNIX)
757 (void)unlink(sep->se_service);
758 if (debug)
759 print_service("FREE", sep);
760 freeconfig(sep);
761 free(sep);
762 }
763 }
764
765 void
retry(int sig,short events,void * arg)766 retry(int sig, short events, void *arg)
767 {
768 struct servtab *sep;
769
770 timingout = 0;
771 for (sep = servtab; sep; sep = sep->se_next) {
772 if (sep->se_fd == -1) {
773 switch (sep->se_family) {
774 case AF_UNIX:
775 case AF_INET:
776 case AF_INET6:
777 setup(sep);
778 if (sep->se_fd != -1 && isrpcservice(sep))
779 register_rpc(sep);
780 break;
781 }
782 }
783 }
784 }
785
786 void
die(int sig,short events,void * arg)787 die(int sig, short events, void *arg)
788 {
789 struct servtab *sep;
790
791 for (sep = servtab; sep; sep = sep->se_next) {
792 if (sep->se_fd == -1)
793 continue;
794
795 switch (sep->se_family) {
796 case AF_UNIX:
797 (void)unlink(sep->se_service);
798 break;
799 case AF_INET:
800 case AF_INET6:
801 if (sep->se_wait == 1 && isrpcservice(sep))
802 unregister_rpc(sep);
803 break;
804 }
805 (void)close(sep->se_fd);
806 }
807 exit(0);
808 }
809
810 void
setup(struct servtab * sep)811 setup(struct servtab *sep)
812 {
813 int on = 1;
814 int r;
815 mode_t mask = 0;
816
817 if ((sep->se_fd = socket(sep->se_family, sep->se_socktype, 0)) == -1) {
818 syslog(LOG_ERR, "%s/%s: socket: %m",
819 sep->se_service, sep->se_proto);
820 return;
821 }
822 #define turnon(fd, opt) \
823 setsockopt(fd, SOL_SOCKET, opt, &on, sizeof (on))
824 if (strncmp(sep->se_proto, "tcp", 3) == 0 && debug &&
825 turnon(sep->se_fd, SO_DEBUG) < 0)
826 syslog(LOG_ERR, "setsockopt (SO_DEBUG): %m");
827 if (turnon(sep->se_fd, SO_REUSEADDR) < 0)
828 syslog(LOG_ERR, "setsockopt (SO_REUSEADDR): %m");
829 #undef turnon
830 if (isrpcservice(sep)) {
831 struct passwd *pwd;
832
833 /*
834 * for RPC services, attempt to use a reserved port
835 * if they are going to be running as root.
836 *
837 * Also, zero out the port for all RPC services; let bind()
838 * find one.
839 */
840 sep->se_ctrladdr_in.sin_port = 0;
841 if (sep->se_user && (pwd = getpwnam(sep->se_user)) &&
842 pwd->pw_uid == 0 && uid == 0)
843 r = bindresvport(sep->se_fd, &sep->se_ctrladdr_in);
844 else {
845 r = bind(sep->se_fd, &sep->se_ctrladdr,
846 sep->se_ctrladdr_size);
847 if (r == 0) {
848 socklen_t len = sep->se_ctrladdr_size;
849 int saveerrno = errno;
850
851 /* update se_ctrladdr_in.sin_port */
852 r = getsockname(sep->se_fd, &sep->se_ctrladdr,
853 &len);
854 if (r <= 0)
855 errno = saveerrno;
856 }
857 }
858 } else {
859 if (sep->se_family == AF_UNIX)
860 mask = umask(0111);
861 r = bind(sep->se_fd, &sep->se_ctrladdr, sep->se_ctrladdr_size);
862 if (sep->se_family == AF_UNIX)
863 umask(mask);
864 }
865 if (r == -1) {
866 syslog(LOG_ERR, "%s/%s: bind: %m",
867 sep->se_service, sep->se_proto);
868 (void) close(sep->se_fd);
869 sep->se_fd = -1;
870 if (!timingout) {
871 timingout = 1;
872 alarm(RETRYTIME);
873 }
874 return;
875 }
876 if (sep->se_socktype == SOCK_STREAM)
877 listen(sep->se_fd, 10);
878
879 if (!sep->se_wait && sep->se_socktype == SOCK_STREAM) {
880 event_set(&sep->se_event, sep->se_fd, EV_READ|EV_PERSIST,
881 gettcp, sep);
882 } else {
883 event_set(&sep->se_event, sep->se_fd, EV_READ|EV_PERSIST,
884 spawn, sep);
885 }
886
887 event_add(&sep->se_event, NULL);
888
889 if (sep->se_fd > maxsock) {
890 maxsock = sep->se_fd;
891 if (maxsock > rlim_nofile_cur - FD_MARGIN)
892 bump_nofile();
893 }
894 }
895
896 void
register_rpc(struct servtab * sep)897 register_rpc(struct servtab *sep)
898 {
899 socklen_t n;
900 struct sockaddr_in sin;
901 struct protoent *pp;
902
903 if ((pp = getprotobyname(sep->se_proto+4)) == NULL) {
904 syslog(LOG_ERR, "%s: getproto: %m",
905 sep->se_proto);
906 return;
907 }
908 n = sizeof sin;
909 if (getsockname(sep->se_fd, (struct sockaddr *)&sin, &n) == -1) {
910 syslog(LOG_ERR, "%s/%s: getsockname: %m",
911 sep->se_service, sep->se_proto);
912 return;
913 }
914
915 for (n = sep->se_rpcversl; n <= sep->se_rpcversh; n++) {
916 if (debug)
917 fprintf(stderr, "pmap_set: %u %u %u %u\n",
918 sep->se_rpcprog, n, pp->p_proto,
919 ntohs(sin.sin_port));
920 (void)pmap_unset(sep->se_rpcprog, n);
921 if (!pmap_set(sep->se_rpcprog, n, pp->p_proto, ntohs(sin.sin_port)))
922 syslog(LOG_ERR, "%s %s: pmap_set: %u %u %u %u: %m",
923 sep->se_service, sep->se_proto,
924 sep->se_rpcprog, n, pp->p_proto,
925 ntohs(sin.sin_port));
926 }
927 }
928
929 void
unregister_rpc(struct servtab * sep)930 unregister_rpc(struct servtab *sep)
931 {
932 int n;
933
934 for (n = sep->se_rpcversl; n <= sep->se_rpcversh; n++) {
935 if (debug)
936 fprintf(stderr, "pmap_unset(%u, %u)\n",
937 sep->se_rpcprog, n);
938 if (!pmap_unset(sep->se_rpcprog, n))
939 syslog(LOG_ERR, "pmap_unset(%u, %u)",
940 sep->se_rpcprog, n);
941 }
942 }
943
944
945 struct servtab *
enter(struct servtab * cp)946 enter(struct servtab *cp)
947 {
948 struct servtab *sep;
949
950 sep = malloc(sizeof (*sep));
951 if (sep == NULL) {
952 syslog(LOG_ERR, "Out of memory.");
953 exit(1);
954 }
955 *sep = *cp;
956 sep->se_fd = -1;
957 sep->se_rpcprog = -1;
958 sep->se_next = servtab;
959 servtab = sep;
960 return (sep);
961 }
962
963 int
matchconf(struct servtab * old,struct servtab * new)964 matchconf(struct servtab *old, struct servtab *new)
965 {
966 if (strcmp(old->se_service, new->se_service) != 0)
967 return (0);
968
969 if (strcmp(old->se_hostaddr, new->se_hostaddr) != 0)
970 return (0);
971
972 if (strcmp(old->se_proto, new->se_proto) != 0)
973 return (0);
974
975 /*
976 * If the new servtab is bound to a specific address, check that the
977 * old servtab is bound to the same entry. If the new service is not
978 * bound to a specific address then the check of se_hostaddr above
979 * is sufficient.
980 */
981
982 if (old->se_family == AF_INET && new->se_family == AF_INET &&
983 bcmp(&old->se_ctrladdr_in.sin_addr,
984 &new->se_ctrladdr_in.sin_addr,
985 sizeof(new->se_ctrladdr_in.sin_addr)) != 0)
986 return (0);
987
988 if (old->se_family == AF_INET6 && new->se_family == AF_INET6 &&
989 bcmp(&old->se_ctrladdr_in6.sin6_addr,
990 &new->se_ctrladdr_in6.sin6_addr,
991 sizeof(new->se_ctrladdr_in6.sin6_addr)) != 0)
992 return (0);
993 if (old->se_family == AF_INET6 && new->se_family == AF_INET6 &&
994 old->se_ctrladdr_in6.sin6_scope_id !=
995 new->se_ctrladdr_in6.sin6_scope_id)
996 return (0);
997
998 return (1);
999 }
1000
1001 FILE *fconfig = NULL;
1002 char line[1024];
1003 char *defhost;
1004 char *skip(char **, int);
1005 char *nextline(FILE *);
1006 char *newstr(char *);
1007 struct servtab *dupconfig(struct servtab *);
1008
1009 int
setconfig(void)1010 setconfig(void)
1011 {
1012 free(defhost);
1013 defhost = newstr("*");
1014 if (fconfig != NULL) {
1015 fseek(fconfig, 0L, SEEK_SET);
1016 return (1);
1017 }
1018 fconfig = fopen(CONFIG, "r");
1019 return (fconfig != NULL);
1020 }
1021
1022 void
endconfig(void)1023 endconfig(void)
1024 {
1025 if (fconfig) {
1026 (void) fclose(fconfig);
1027 fconfig = NULL;
1028 }
1029 if (defhost) {
1030 free(defhost);
1031 defhost = 0;
1032 }
1033 }
1034
1035 struct servtab *
getconfigent(void)1036 getconfigent(void)
1037 {
1038 struct servtab *sep, *tsep;
1039 char *arg, *cp, *hostdelim, *s;
1040 int argc;
1041
1042 sep = calloc(1, sizeof(struct servtab));
1043 if (sep == NULL) {
1044 syslog(LOG_ERR, "calloc: %m");
1045 exit(1);
1046 }
1047 more:
1048 freeconfig(sep);
1049
1050 while ((cp = nextline(fconfig)) && *cp == '#')
1051 ;
1052 if (cp == NULL) {
1053 free(sep);
1054 return (NULL);
1055 }
1056
1057 memset(sep, 0, sizeof *sep);
1058 arg = skip(&cp, 0);
1059 if (arg == NULL) {
1060 /* A blank line. */
1061 goto more;
1062 }
1063
1064 /* Check for a host name. */
1065 hostdelim = strrchr(arg, ':');
1066 if (hostdelim) {
1067 *hostdelim = '\0';
1068 if (arg[0] == '[' && hostdelim > arg && hostdelim[-1] == ']') {
1069 hostdelim[-1] = '\0';
1070 sep->se_hostaddr = newstr(arg + 1);
1071 } else if (hostdelim == arg)
1072 sep->se_hostaddr = newstr("*");
1073 else
1074 sep->se_hostaddr = newstr(arg);
1075 arg = hostdelim + 1;
1076 /*
1077 * If the line is of the form `host:', then just change the
1078 * default host for the following lines.
1079 */
1080 if (*arg == '\0') {
1081 arg = skip(&cp, 0);
1082 if (cp == NULL) {
1083 free(defhost);
1084 defhost = newstr(sep->se_hostaddr);
1085 goto more;
1086 }
1087 }
1088 } else
1089 sep->se_hostaddr = newstr(defhost);
1090
1091 sep->se_service = newstr(arg);
1092 if ((arg = skip(&cp, 1)) == NULL)
1093 goto more;
1094
1095 if (strcmp(arg, "stream") == 0)
1096 sep->se_socktype = SOCK_STREAM;
1097 else if (strcmp(arg, "dgram") == 0)
1098 sep->se_socktype = SOCK_DGRAM;
1099 else
1100 sep->se_socktype = -1;
1101
1102 if ((arg = skip(&cp, 1)) == NULL)
1103 goto more;
1104
1105 sep->se_proto = newstr(arg);
1106
1107 if (strcmp(sep->se_proto, "unix") == 0) {
1108 sep->se_family = AF_UNIX;
1109 } else {
1110 int s;
1111
1112 sep->se_family = AF_INET;
1113 if (sep->se_proto[strlen(sep->se_proto) - 1] == '6')
1114 sep->se_family = AF_INET6;
1115
1116 /* check if the family is supported */
1117 s = socket(sep->se_family, SOCK_DGRAM, 0);
1118 if (s == -1) {
1119 syslog(LOG_WARNING, "%s/%s: %s: the address family is "
1120 "not supported by the kernel", sep->se_service,
1121 sep->se_proto, sep->se_hostaddr);
1122 goto more;
1123 }
1124 close(s);
1125
1126 if (strncmp(sep->se_proto, "rpc/", 4) == 0) {
1127 char *cp, *ccp;
1128 long l;
1129
1130 cp = strchr(sep->se_service, '/');
1131 if (cp == 0) {
1132 syslog(LOG_ERR, "%s: no rpc version",
1133 sep->se_service);
1134 goto more;
1135 }
1136 *cp++ = '\0';
1137 l = strtol(cp, &ccp, 0);
1138 if (ccp == cp || l < 0 || l > INT_MAX) {
1139 badafterall:
1140 syslog(LOG_ERR, "%s/%s: bad rpc version",
1141 sep->se_service, cp);
1142 goto more;
1143 }
1144 sep->se_rpcversl = sep->se_rpcversh = l;
1145 if (*ccp == '-') {
1146 cp = ccp + 1;
1147 l = strtol(cp, &ccp, 0);
1148 if (ccp == cp || l < 0 || l > INT_MAX ||
1149 l < sep->se_rpcversl || *ccp)
1150 goto badafterall;
1151 sep->se_rpcversh = l;
1152 } else if (*ccp != '\0')
1153 goto badafterall;
1154 }
1155 }
1156 arg = skip(&cp, 1);
1157 if (arg == NULL)
1158 goto more;
1159
1160 s = strchr(arg, '.');
1161 if (s) {
1162 char *p;
1163
1164 *s++ = '\0';
1165 sep->se_max = strtoul(s, &p, 0);
1166 if (sep->se_max < 1 || *p) {
1167 syslog(LOG_ERR,
1168 "%s: illegal max field \"%s\", setting to %d",
1169 sep->se_service, s, toomany);
1170 sep->se_max = toomany;
1171 }
1172 } else
1173 sep->se_max = toomany;
1174
1175 sep->se_wait = strcmp(arg, "wait") == 0;
1176 if ((arg = skip(&cp, 1)) == NULL)
1177 goto more;
1178 sep->se_user = newstr(arg);
1179 arg = strchr(sep->se_user, '.');
1180 if (arg == NULL)
1181 arg = strchr(sep->se_user, ':');
1182 if (arg) {
1183 *arg++ = '\0';
1184 sep->se_group = newstr(arg);
1185 }
1186 if ((arg = skip(&cp, 1)) == NULL)
1187 goto more;
1188
1189 sep->se_server = newstr(arg);
1190 if (strcmp(sep->se_server, "internal") == 0) {
1191 struct biltin *bi;
1192
1193 for (bi = biltins; bi->bi_service; bi++)
1194 if (bi->bi_socktype == sep->se_socktype &&
1195 strcmp(bi->bi_service, sep->se_service) == 0)
1196 break;
1197 if (bi->bi_service == 0) {
1198 syslog(LOG_ERR, "internal service %s unknown",
1199 sep->se_service);
1200 goto more;
1201 }
1202 sep->se_bi = bi;
1203 sep->se_wait = bi->bi_wait;
1204 } else
1205 sep->se_bi = NULL;
1206 argc = 0;
1207 for (arg = skip(&cp, 0); cp; arg = skip(&cp, 0)) {
1208 if (argc < MAXARGV)
1209 sep->se_argv[argc++] = newstr(arg);
1210 }
1211 if (argc == 0 && sep->se_bi == NULL) {
1212 if ((arg = strrchr(sep->se_server, '/')) != NULL)
1213 arg++;
1214 else
1215 arg = sep->se_server;
1216 sep->se_argv[argc++] = newstr(arg);
1217 }
1218 while (argc <= MAXARGV)
1219 sep->se_argv[argc++] = NULL;
1220
1221 /*
1222 * Resolve each hostname in the se_hostaddr list (if any)
1223 * and create a new entry for each resolved address.
1224 */
1225 if (sep->se_hostaddr != NULL && strcmp(sep->se_proto, "unix") != 0) {
1226 struct addrinfo hints, *res0, *res;
1227 char *host, *hostlist0, *hostlist, *port;
1228 int error;
1229
1230 hostlist = hostlist0 = sep->se_hostaddr;
1231 sep->se_hostaddr = NULL;
1232 sep->se_checked = -1;
1233 while ((host = strsep(&hostlist, ",")) != NULL) {
1234 if (*host == '\0')
1235 continue;
1236
1237 memset(&hints, 0, sizeof(hints));
1238 hints.ai_family = sep->se_family;
1239 hints.ai_socktype = sep->se_socktype;
1240 hints.ai_flags = AI_PASSIVE;
1241 port = "0";
1242 error = getaddrinfo(strcmp(host, "*") ? host : NULL,
1243 port, &hints, &res0);
1244 if (error) {
1245 syslog(LOG_ERR, "%s/%s: %s: %s",
1246 sep->se_service, sep->se_proto,
1247 host, gai_strerror(error));
1248 continue;
1249 }
1250 for (res = res0; res; res = res->ai_next) {
1251 /*
1252 * If sep is unused, store host in there.
1253 * Otherwise, dup a new entry and prepend it.
1254 */
1255 if (sep->se_checked == -1) {
1256 sep->se_checked = 0;
1257 } else {
1258 tsep = dupconfig(sep);
1259 tsep->se_next = sep;
1260 sep = tsep;
1261 }
1262 sep->se_hostaddr = newstr(host);
1263 memcpy(&sep->se_ctrladdr_storage,
1264 res->ai_addr, res->ai_addrlen);
1265 sep->se_ctrladdr_size = res->ai_addrlen;
1266 }
1267 freeaddrinfo(res0);
1268 }
1269 free(hostlist0);
1270 if (sep->se_checked == -1)
1271 goto more; /* no resolvable names/addresses */
1272 }
1273
1274 return (sep);
1275 }
1276
1277 void
freeconfig(struct servtab * cp)1278 freeconfig(struct servtab *cp)
1279 {
1280 int i;
1281
1282 free(cp->se_hostaddr);
1283 cp->se_hostaddr = NULL;
1284 free(cp->se_service);
1285 cp->se_service = NULL;
1286 free(cp->se_proto);
1287 cp->se_proto = NULL;
1288 free(cp->se_user);
1289 cp->se_user = NULL;
1290 free(cp->se_group);
1291 cp->se_group = NULL;
1292 free(cp->se_server);
1293 cp->se_server = NULL;
1294 for (i = 0; i < MAXARGV; i++) {
1295 free(cp->se_argv[i]);
1296 cp->se_argv[i] = NULL;
1297 }
1298 }
1299
1300 char *
skip(char ** cpp,int report)1301 skip(char **cpp, int report)
1302 {
1303 char *cp = *cpp;
1304 char *start;
1305
1306 erp:
1307 if (*cpp == NULL) {
1308 if (report)
1309 syslog(LOG_ERR, "syntax error in inetd config file");
1310 return (NULL);
1311 }
1312
1313 again:
1314 while (*cp == ' ' || *cp == '\t')
1315 cp++;
1316 if (*cp == '\0') {
1317 int c;
1318
1319 c = getc(fconfig);
1320 (void) ungetc(c, fconfig);
1321 if (c == ' ' || c == '\t')
1322 if ((cp = nextline(fconfig)))
1323 goto again;
1324 *cpp = NULL;
1325 goto erp;
1326 }
1327 start = cp;
1328 while (*cp && *cp != ' ' && *cp != '\t')
1329 cp++;
1330 if (*cp != '\0')
1331 *cp++ = '\0';
1332 if ((*cpp = cp) == NULL)
1333 goto erp;
1334
1335 return (start);
1336 }
1337
1338 char *
nextline(FILE * fd)1339 nextline(FILE *fd)
1340 {
1341 if (fgets(line, sizeof (line), fd) == NULL)
1342 return (NULL);
1343 line[strcspn(line, "\n")] = '\0';
1344 return (line);
1345 }
1346
1347 char *
newstr(char * cp)1348 newstr(char *cp)
1349 {
1350 if ((cp = strdup(cp ? cp : "")))
1351 return(cp);
1352 syslog(LOG_ERR, "strdup: %m");
1353 exit(1);
1354 }
1355
1356 struct servtab *
dupconfig(struct servtab * sep)1357 dupconfig(struct servtab *sep)
1358 {
1359 struct servtab *newtab;
1360 int argc;
1361
1362 newtab = calloc(1, sizeof(struct servtab));
1363
1364 if (newtab == NULL) {
1365 syslog(LOG_ERR, "calloc: %m");
1366 exit(1);
1367 }
1368
1369 newtab->se_service = sep->se_service ? newstr(sep->se_service) : NULL;
1370 newtab->se_socktype = sep->se_socktype;
1371 newtab->se_family = sep->se_family;
1372 newtab->se_proto = sep->se_proto ? newstr(sep->se_proto) : NULL;
1373 newtab->se_rpcprog = sep->se_rpcprog;
1374 newtab->se_rpcversl = sep->se_rpcversl;
1375 newtab->se_rpcversh = sep->se_rpcversh;
1376 newtab->se_wait = sep->se_wait;
1377 newtab->se_user = sep->se_user ? newstr(sep->se_user) : NULL;
1378 newtab->se_group = sep->se_group ? newstr(sep->se_group) : NULL;
1379 newtab->se_bi = sep->se_bi;
1380 newtab->se_server = sep->se_server ? newstr(sep->se_server) : 0;
1381
1382 for (argc = 0; argc <= MAXARGV; argc++)
1383 newtab->se_argv[argc] = sep->se_argv[argc] ?
1384 newstr(sep->se_argv[argc]) : NULL;
1385 newtab->se_max = sep->se_max;
1386
1387 return (newtab);
1388 }
1389
1390 void
inetd_setproctitle(char * a,int s)1391 inetd_setproctitle(char *a, int s)
1392 {
1393 socklen_t size;
1394 struct sockaddr_storage ss;
1395 char hbuf[NI_MAXHOST];
1396
1397 size = sizeof(ss);
1398 if (getpeername(s, (struct sockaddr *)&ss, &size) == 0) {
1399 if (getnameinfo((struct sockaddr *)&ss, size, hbuf,
1400 sizeof(hbuf), NULL, 0, NI_NUMERICHOST) == 0)
1401 setproctitle("-%s [%s]", a, hbuf);
1402 else
1403 setproctitle("-%s [?]", a);
1404 } else
1405 setproctitle("-%s", a);
1406 }
1407
1408 int
bump_nofile(void)1409 bump_nofile(void)
1410 {
1411 #define FD_CHUNK 32
1412
1413 struct rlimit rl;
1414
1415 if (getrlimit(RLIMIT_NOFILE, &rl) == -1) {
1416 syslog(LOG_ERR, "getrlimit: %m");
1417 return -1;
1418 }
1419 rl.rlim_cur = MINIMUM(rl.rlim_max, rl.rlim_cur + FD_CHUNK);
1420 rl.rlim_cur = MINIMUM(FD_SETSIZE, rl.rlim_cur + FD_CHUNK);
1421 if (rl.rlim_cur <= rlim_nofile_cur) {
1422 syslog(LOG_ERR,
1423 "bump_nofile: cannot extend file limit, max = %d",
1424 (int)rl.rlim_cur);
1425 return -1;
1426 }
1427
1428 if (setrlimit(RLIMIT_NOFILE, &rl) == -1) {
1429 syslog(LOG_ERR, "setrlimit: %m");
1430 return -1;
1431 }
1432
1433 rlim_nofile_cur = rl.rlim_cur;
1434 return 0;
1435 }
1436
1437 /*
1438 * Internet services provided internally by inetd:
1439 */
1440 #define BUFSIZE 4096
1441
1442 void
echo_stream(int s,struct servtab * sep)1443 echo_stream(int s, struct servtab *sep)
1444 {
1445 char buffer[BUFSIZE];
1446 int i;
1447
1448 inetd_setproctitle(sep->se_service, s);
1449 while ((i = read(s, buffer, sizeof(buffer))) > 0 &&
1450 write(s, buffer, i) > 0)
1451 ;
1452 exit(0);
1453 }
1454
1455 void
echo_dg(int s,struct servtab * sep)1456 echo_dg(int s, struct servtab *sep)
1457 {
1458 char buffer[BUFSIZE];
1459 int i;
1460 socklen_t size;
1461 struct sockaddr_storage ss;
1462
1463 size = sizeof(ss);
1464 if ((i = recvfrom(s, buffer, sizeof(buffer), 0,
1465 (struct sockaddr *)&ss, &size)) == -1)
1466 return;
1467 if (dg_badinput((struct sockaddr *)&ss))
1468 return;
1469 (void) sendto(s, buffer, i, 0, (struct sockaddr *)&ss, size);
1470 }
1471
1472 void
discard_stream(int s,struct servtab * sep)1473 discard_stream(int s, struct servtab *sep)
1474 {
1475 char buffer[BUFSIZE];
1476
1477 inetd_setproctitle(sep->se_service, s);
1478 while ((errno = 0, read(s, buffer, sizeof(buffer)) > 0) ||
1479 errno == EINTR)
1480 ;
1481 exit(0);
1482 }
1483
1484 void
discard_dg(int s,struct servtab * sep)1485 discard_dg(int s, struct servtab *sep)
1486 {
1487 char buffer[BUFSIZE];
1488
1489 (void) read(s, buffer, sizeof(buffer));
1490 }
1491
1492 #define LINESIZ 72
1493 char ring[128];
1494 char *endring;
1495
1496 void
initring(void)1497 initring(void)
1498 {
1499 int i;
1500
1501 endring = ring;
1502
1503 for (i = 0; i <= sizeof ring; ++i)
1504 if (isprint((unsigned char)i))
1505 *endring++ = i;
1506 }
1507
1508 void
chargen_stream(int s,struct servtab * sep)1509 chargen_stream(int s, struct servtab *sep)
1510 {
1511 char *rs;
1512 int len;
1513 char text[LINESIZ+2];
1514
1515 inetd_setproctitle(sep->se_service, s);
1516
1517 if (!endring) {
1518 initring();
1519 rs = ring;
1520 }
1521
1522 text[LINESIZ] = '\r';
1523 text[LINESIZ + 1] = '\n';
1524 for (rs = ring;;) {
1525 if ((len = endring - rs) >= LINESIZ)
1526 memmove(text, rs, LINESIZ);
1527 else {
1528 memmove(text, rs, len);
1529 memmove(text + len, ring, LINESIZ - len);
1530 }
1531 if (++rs == endring)
1532 rs = ring;
1533 if (write(s, text, sizeof(text)) != sizeof(text))
1534 break;
1535 }
1536 exit(0);
1537 }
1538
1539 void
chargen_dg(int s,struct servtab * sep)1540 chargen_dg(int s, struct servtab *sep)
1541 {
1542 struct sockaddr_storage ss;
1543 static char *rs;
1544 int len;
1545 socklen_t size;
1546 char text[LINESIZ+2];
1547
1548 if (endring == 0) {
1549 initring();
1550 rs = ring;
1551 }
1552
1553 size = sizeof(ss);
1554 if (recvfrom(s, text, sizeof(text), 0, (struct sockaddr *)&ss,
1555 &size) == -1)
1556 return;
1557 if (dg_badinput((struct sockaddr *)&ss))
1558 return;
1559
1560 if ((len = endring - rs) >= LINESIZ)
1561 memmove(text, rs, LINESIZ);
1562 else {
1563 memmove(text, rs, len);
1564 memmove(text + len, ring, LINESIZ - len);
1565 }
1566 if (++rs == endring)
1567 rs = ring;
1568 text[LINESIZ] = '\r';
1569 text[LINESIZ + 1] = '\n';
1570 (void) sendto(s, text, sizeof(text), 0, (struct sockaddr *)&ss, size);
1571 }
1572
1573 /*
1574 * Return a machine readable date and time, in the form of the
1575 * number of seconds since midnight, Jan 1, 1900. Since gettimeofday
1576 * returns the number of seconds since midnight, Jan 1, 1970,
1577 * we must add 2208988800 seconds to this figure to make up for
1578 * some seventy years Bell Labs was asleep.
1579 */
1580 u_int32_t
machtime(void)1581 machtime(void)
1582 {
1583 struct timeval tv;
1584
1585 if (gettimeofday(&tv, NULL) == -1)
1586 return (0L);
1587
1588 return (htonl((u_int32_t)tv.tv_sec + 2208988800UL));
1589 }
1590
1591 void
machtime_stream(int s,struct servtab * sep)1592 machtime_stream(int s, struct servtab *sep)
1593 {
1594 u_int32_t result;
1595
1596 result = machtime();
1597 (void) write(s, &result, sizeof(result));
1598 }
1599
1600 void
machtime_dg(int s,struct servtab * sep)1601 machtime_dg(int s, struct servtab *sep)
1602 {
1603 u_int32_t result;
1604 struct sockaddr_storage ss;
1605 socklen_t size;
1606
1607 size = sizeof(ss);
1608 if (recvfrom(s, &result, sizeof(result), 0,
1609 (struct sockaddr *)&ss, &size) == -1)
1610 return;
1611 if (dg_badinput((struct sockaddr *)&ss))
1612 return;
1613 result = machtime();
1614 (void) sendto(s, &result, sizeof(result), 0,
1615 (struct sockaddr *)&ss, size);
1616 }
1617
1618 /* Return human-readable time of day */
1619 void
daytime_stream(int s,struct servtab * sep)1620 daytime_stream(int s, struct servtab *sep)
1621 {
1622 char buffer[256];
1623 time_t clock;
1624
1625 clock = time(NULL);
1626
1627 (void) snprintf(buffer, sizeof buffer, "%.24s\r\n", ctime(&clock));
1628 (void) write(s, buffer, strlen(buffer));
1629 }
1630
1631 /* Return human-readable time of day */
1632 void
daytime_dg(int s,struct servtab * sep)1633 daytime_dg(int s, struct servtab *sep)
1634 {
1635 char buffer[256];
1636 time_t clock;
1637 struct sockaddr_storage ss;
1638 socklen_t size;
1639
1640 clock = time(NULL);
1641
1642 size = sizeof(ss);
1643 if (recvfrom(s, buffer, sizeof(buffer), 0, (struct sockaddr *)&ss,
1644 &size) == -1)
1645 return;
1646 if (dg_badinput((struct sockaddr *)&ss))
1647 return;
1648 (void) snprintf(buffer, sizeof buffer, "%.24s\r\n", ctime(&clock));
1649 (void) sendto(s, buffer, strlen(buffer), 0, (struct sockaddr *)&ss,
1650 size);
1651 }
1652
1653 /*
1654 * print_service:
1655 * Dump relevant information to stderr
1656 */
1657 void
print_service(char * action,struct servtab * sep)1658 print_service(char *action, struct servtab *sep)
1659 {
1660 if (strcmp(sep->se_hostaddr, "*") == 0)
1661 fprintf(stderr, "%s: %s ", action, sep->se_service);
1662 else
1663 fprintf(stderr, "%s: %s:%s ", action, sep->se_hostaddr,
1664 sep->se_service);
1665
1666 if (isrpcservice(sep))
1667 fprintf(stderr, "rpcprog=%d, rpcvers=%d/%d, proto=%s,",
1668 sep->se_rpcprog, sep->se_rpcversh,
1669 sep->se_rpcversl, sep->se_proto);
1670 else
1671 fprintf(stderr, "proto=%s,", sep->se_proto);
1672
1673 fprintf(stderr,
1674 " wait.max=%d.%d user:group=%s:%s builtin=%lx server=%s\n",
1675 sep->se_wait, sep->se_max, sep->se_user,
1676 sep->se_group ? sep->se_group : "wheel",
1677 (long)sep->se_bi, sep->se_server);
1678 }
1679
1680 void
spawn(int ctrl,short events,void * xsep)1681 spawn(int ctrl, short events, void *xsep)
1682 {
1683 struct servtab *sep = xsep;
1684 struct passwd *pwd;
1685 int tmpint, dofork;
1686 struct group *grp = NULL;
1687 char buf[50];
1688 pid_t pid;
1689
1690 if (debug)
1691 fprintf(stderr, "someone wants %s\n", sep->se_service);
1692
1693 pid = 0;
1694 dofork = (sep->se_bi == 0 || sep->se_bi->bi_fork);
1695 if (dofork) {
1696 if (sep->se_count++ == 0)
1697 (void)gettimeofday(&sep->se_time, NULL);
1698 else if (sep->se_count >= sep->se_max) {
1699 struct timeval now;
1700
1701 (void)gettimeofday(&now, NULL);
1702 if (now.tv_sec - sep->se_time.tv_sec >
1703 CNT_INTVL) {
1704 sep->se_time = now;
1705 sep->se_count = 1;
1706 } else {
1707 if (!sep->se_wait &&
1708 sep->se_socktype == SOCK_STREAM)
1709 close(ctrl);
1710 if (sep->se_family == AF_INET &&
1711 ntohs(sep->se_ctrladdr_in.sin_port) >=
1712 IPPORT_RESERVED) {
1713 /*
1714 * Cannot close it -- there are
1715 * thieves on the system.
1716 * Simply ignore the connection.
1717 */
1718 --sep->se_count;
1719 return;
1720 }
1721 syslog(LOG_ERR,
1722 "%s/%s server failing (looping), service terminated",
1723 sep->se_service, sep->se_proto);
1724 if (!sep->se_wait &&
1725 sep->se_socktype == SOCK_STREAM)
1726 close(ctrl);
1727 event_del(&sep->se_event);
1728 (void) close(sep->se_fd);
1729
1730 sep->se_fd = -1;
1731 sep->se_count = 0;
1732 if (!timingout) {
1733 timingout = 1;
1734 alarm(RETRYTIME);
1735 }
1736 return;
1737 }
1738 }
1739 pid = fork();
1740 }
1741 if (pid == -1) {
1742 syslog(LOG_ERR, "fork: %m");
1743 if (!sep->se_wait && sep->se_socktype == SOCK_STREAM)
1744 close(ctrl);
1745 sleep(1);
1746 return;
1747 }
1748
1749 if (pid && sep->se_wait) {
1750 sep->se_wait = pid;
1751 event_del(&sep->se_event);
1752 }
1753 if (pid == 0) {
1754 if (sep->se_bi) {
1755 if (dofork && pledge("stdio inet", NULL) == -1)
1756 err(1, "pledge");
1757 (*sep->se_bi->bi_fn)(ctrl, sep);
1758 } else {
1759 if ((pwd = getpwnam(sep->se_user)) == NULL) {
1760 syslog(LOG_ERR,
1761 "getpwnam: %s: No such user",
1762 sep->se_user);
1763 if (sep->se_socktype != SOCK_STREAM)
1764 recv(0, buf, sizeof (buf), 0);
1765 exit(1);
1766 }
1767 if (setsid() <0)
1768 syslog(LOG_ERR, "%s: setsid: %m",
1769 sep->se_service);
1770 if (sep->se_group &&
1771 (grp = getgrnam(sep->se_group)) == NULL) {
1772 syslog(LOG_ERR,
1773 "getgrnam: %s: No such group",
1774 sep->se_group);
1775 if (sep->se_socktype != SOCK_STREAM)
1776 recv(0, buf, sizeof (buf), 0);
1777 exit(1);
1778 }
1779 if (uid != 0) {
1780 /* a user running private inetd */
1781 if (uid != pwd->pw_uid)
1782 exit(1);
1783 } else {
1784 tmpint = LOGIN_SETALL &
1785 ~(LOGIN_SETGROUP|LOGIN_SETLOGIN);
1786 if (pwd->pw_uid)
1787 tmpint |= LOGIN_SETGROUP|LOGIN_SETLOGIN;
1788 if (sep->se_group) {
1789 pwd->pw_gid = grp->gr_gid;
1790 tmpint |= LOGIN_SETGROUP;
1791 }
1792 if (setusercontext(NULL, pwd, pwd->pw_uid,
1793 tmpint) == -1) {
1794 syslog(LOG_ERR,
1795 "%s/%s: setusercontext: %m",
1796 sep->se_service, sep->se_proto);
1797 exit(1);
1798 }
1799 }
1800 if (debug)
1801 fprintf(stderr, "%ld execv %s\n",
1802 (long)getpid(), sep->se_server);
1803 if (ctrl != STDIN_FILENO) {
1804 dup2(ctrl, STDIN_FILENO);
1805 close(ctrl);
1806 }
1807 dup2(STDIN_FILENO, STDOUT_FILENO);
1808 dup2(STDIN_FILENO, STDERR_FILENO);
1809 closelog();
1810 closefrom(3);
1811 signal(SIGPIPE, SIG_DFL);
1812 execv(sep->se_server, sep->se_argv);
1813 if (sep->se_socktype != SOCK_STREAM)
1814 recv(0, buf, sizeof (buf), 0);
1815 syslog(LOG_ERR, "execv %s: %m", sep->se_server);
1816 exit(1);
1817 }
1818 }
1819 if (!sep->se_wait && sep->se_socktype == SOCK_STREAM)
1820 close(ctrl);
1821 }
1822