xref: /freebsd-src/contrib/tcp_wrappers/tcpd.c (revision 2cadbe468a8e8aef193429565b729d34ec48b266)
12aef6930SMark Murray  /*
22aef6930SMark Murray   * General front end for stream and datagram IP services. This program logs
32aef6930SMark Murray   * the remote host name and then invokes the real daemon. For example,
42aef6930SMark Murray   * install as /usr/etc/{tftpd,fingerd,telnetd,ftpd,rlogind,rshd,rexecd},
52aef6930SMark Murray   * after saving the real daemons in the directory specified with the
62aef6930SMark Murray   * REAL_DAEMON_DIR macro. This arrangement requires that the network daemons
72aef6930SMark Murray   * are started by inetd or something similar. Connections and diagnostics
82aef6930SMark Murray   * are logged through syslog(3).
92aef6930SMark Murray   *
102aef6930SMark Murray   * Author: Wietse Venema, Eindhoven University of Technology, The Netherlands.
118053080cSYoshinobu Inoue   *
128053080cSYoshinobu Inoue   * $FreeBSD$
132aef6930SMark Murray   */
142aef6930SMark Murray 
152aef6930SMark Murray #ifndef lint
162aef6930SMark Murray static char sccsid[] = "@(#) tcpd.c 1.10 96/02/11 17:01:32";
172aef6930SMark Murray #endif
182aef6930SMark Murray 
192aef6930SMark Murray /* System libraries. */
202aef6930SMark Murray 
212aef6930SMark Murray #include <sys/types.h>
222aef6930SMark Murray #include <sys/param.h>
232aef6930SMark Murray #include <sys/stat.h>
242aef6930SMark Murray #include <sys/socket.h>
252aef6930SMark Murray #include <netinet/in.h>
262aef6930SMark Murray #include <stdio.h>
272aef6930SMark Murray #include <syslog.h>
282aef6930SMark Murray #include <string.h>
297d2d393cSBrooks Davis #include <unistd.h>
302aef6930SMark Murray 
312aef6930SMark Murray #ifndef MAXPATHNAMELEN
322aef6930SMark Murray #define MAXPATHNAMELEN	BUFSIZ
332aef6930SMark Murray #endif
342aef6930SMark Murray 
352aef6930SMark Murray #ifndef STDIN_FILENO
362aef6930SMark Murray #define STDIN_FILENO	0
372aef6930SMark Murray #endif
382aef6930SMark Murray 
392aef6930SMark Murray /* Local stuff. */
402aef6930SMark Murray 
412aef6930SMark Murray #include "patchlevel.h"
422aef6930SMark Murray #include "tcpd.h"
432aef6930SMark Murray 
442aef6930SMark Murray int     allow_severity = SEVERITY;	/* run-time adjustable */
452aef6930SMark Murray int     deny_severity = LOG_WARNING;	/* ditto */
462aef6930SMark Murray 
47*2cadbe46SMinsoo Choo int
4814f102eaSEd Maste main(int argc, char **argv)
492aef6930SMark Murray {
502aef6930SMark Murray     struct request_info request;
512aef6930SMark Murray     char    path[MAXPATHNAMELEN];
522aef6930SMark Murray 
532aef6930SMark Murray     /* Attempt to prevent the creation of world-writable files. */
542aef6930SMark Murray 
552aef6930SMark Murray #ifdef DAEMON_UMASK
562aef6930SMark Murray     umask(DAEMON_UMASK);
572aef6930SMark Murray #endif
582aef6930SMark Murray 
592aef6930SMark Murray     /*
602aef6930SMark Murray      * If argv[0] is an absolute path name, ignore REAL_DAEMON_DIR, and strip
612aef6930SMark Murray      * argv[0] to its basename.
622aef6930SMark Murray      */
632aef6930SMark Murray 
642aef6930SMark Murray     if (argv[0][0] == '/') {
654f14ba6cSConrad Meyer 	strlcpy(path, argv[0], sizeof(path));
662aef6930SMark Murray 	argv[0] = strrchr(argv[0], '/') + 1;
672aef6930SMark Murray     } else {
684f14ba6cSConrad Meyer 	snprintf(path, sizeof(path), "%s/%s", REAL_DAEMON_DIR, argv[0]);
692aef6930SMark Murray     }
702aef6930SMark Murray 
712aef6930SMark Murray     /*
722aef6930SMark Murray      * Open a channel to the syslog daemon. Older versions of openlog()
732aef6930SMark Murray      * require only two arguments.
742aef6930SMark Murray      */
752aef6930SMark Murray 
762aef6930SMark Murray #ifdef LOG_MAIL
772aef6930SMark Murray     (void) openlog(argv[0], LOG_PID, FACILITY);
782aef6930SMark Murray #else
792aef6930SMark Murray     (void) openlog(argv[0], LOG_PID);
802aef6930SMark Murray #endif
812aef6930SMark Murray 
822aef6930SMark Murray     /*
832aef6930SMark Murray      * Find out the endpoint addresses of this conversation. Host name
842aef6930SMark Murray      * lookups and double checks will be done on demand.
852aef6930SMark Murray      */
862aef6930SMark Murray 
872aef6930SMark Murray     request_init(&request, RQ_DAEMON, argv[0], RQ_FILE, STDIN_FILENO, 0);
882aef6930SMark Murray     fromhost(&request);
892aef6930SMark Murray 
902aef6930SMark Murray     /*
912aef6930SMark Murray      * Optionally look up and double check the remote host name. Sites
922aef6930SMark Murray      * concerned with security may choose to refuse connections from hosts
932aef6930SMark Murray      * that pretend to have someone elses host name.
942aef6930SMark Murray      */
952aef6930SMark Murray 
962aef6930SMark Murray #ifdef PARANOID
972aef6930SMark Murray     if (STR_EQ(eval_hostname(request.client), paranoid))
982aef6930SMark Murray 	refuse(&request);
992aef6930SMark Murray #endif
1002aef6930SMark Murray 
1012aef6930SMark Murray     /*
1022aef6930SMark Murray      * The BSD rlogin and rsh daemons that came out after 4.3 BSD disallow
1032aef6930SMark Murray      * socket options at the IP level. They do so for a good reason.
1042aef6930SMark Murray      * Unfortunately, we cannot use this with SunOS 4.1.x because the
1052aef6930SMark Murray      * getsockopt() system call can panic the system.
1062aef6930SMark Murray      */
1072aef6930SMark Murray 
1082aef6930SMark Murray #ifdef KILL_IP_OPTIONS
1092aef6930SMark Murray     fix_options(&request);
1102aef6930SMark Murray #endif
1112aef6930SMark Murray 
1122aef6930SMark Murray     /*
1132aef6930SMark Murray      * Check whether this host can access the service in argv[0]. The
1142aef6930SMark Murray      * access-control code invokes optional shell commands as specified in
1152aef6930SMark Murray      * the access-control tables.
1162aef6930SMark Murray      */
1172aef6930SMark Murray 
1182aef6930SMark Murray #ifdef HOSTS_ACCESS
1192aef6930SMark Murray     if (!hosts_access(&request))
1202aef6930SMark Murray 	refuse(&request);
1212aef6930SMark Murray #endif
1222aef6930SMark Murray 
1232aef6930SMark Murray     /* Report request and invoke the real daemon program. */
1242aef6930SMark Murray 
1258053080cSYoshinobu Inoue #ifdef INET6
1268053080cSYoshinobu Inoue     syslog(allow_severity, "connect from %s (%s)",
1278053080cSYoshinobu Inoue 	   eval_client(&request), eval_hostaddr(request.client));
1288053080cSYoshinobu Inoue #else
1292aef6930SMark Murray     syslog(allow_severity, "connect from %s", eval_client(&request));
1308053080cSYoshinobu Inoue #endif
1312aef6930SMark Murray     closelog();
1322aef6930SMark Murray     (void) execv(path, argv);
1332aef6930SMark Murray     syslog(LOG_ERR, "error: cannot execute %s: %m", path);
1342aef6930SMark Murray     clean_exit(&request);
1352aef6930SMark Murray     /* NOTREACHED */
1362aef6930SMark Murray }
137