144743Smarkm /* 244743Smarkm * General front end for stream and datagram IP services. This program logs 344743Smarkm * the remote host name and then invokes the real daemon. For example, 444743Smarkm * install as /usr/etc/{tftpd,fingerd,telnetd,ftpd,rlogind,rshd,rexecd}, 544743Smarkm * after saving the real daemons in the directory specified with the 644743Smarkm * REAL_DAEMON_DIR macro. This arrangement requires that the network daemons 744743Smarkm * are started by inetd or something similar. Connections and diagnostics 844743Smarkm * are logged through syslog(3). 944743Smarkm * 1044743Smarkm * Author: Wietse Venema, Eindhoven University of Technology, The Netherlands. 1156977Sshin * 1256977Sshin * $FreeBSD$ 1344743Smarkm */ 1444743Smarkm 1544743Smarkm#ifndef lint 1644743Smarkmstatic char sccsid[] = "@(#) tcpd.c 1.10 96/02/11 17:01:32"; 1744743Smarkm#endif 1844743Smarkm 1944743Smarkm/* System libraries. */ 2044743Smarkm 2144743Smarkm#include <sys/types.h> 2244743Smarkm#include <sys/param.h> 2344743Smarkm#include <sys/stat.h> 2444743Smarkm#include <sys/socket.h> 2544743Smarkm#include <netinet/in.h> 2644743Smarkm#include <stdio.h> 2744743Smarkm#include <syslog.h> 2844743Smarkm#include <string.h> 2944743Smarkm 3044743Smarkm#ifndef MAXPATHNAMELEN 3144743Smarkm#define MAXPATHNAMELEN BUFSIZ 3244743Smarkm#endif 3344743Smarkm 3444743Smarkm#ifndef STDIN_FILENO 3544743Smarkm#define STDIN_FILENO 0 3644743Smarkm#endif 3744743Smarkm 3844743Smarkm/* Local stuff. */ 3944743Smarkm 4044743Smarkm#include "patchlevel.h" 4144743Smarkm#include "tcpd.h" 4244743Smarkm 4344743Smarkmint allow_severity = SEVERITY; /* run-time adjustable */ 4444743Smarkmint deny_severity = LOG_WARNING; /* ditto */ 4544743Smarkm 4644743Smarkmmain(argc, argv) 4744743Smarkmint argc; 4844743Smarkmchar **argv; 4944743Smarkm{ 5044743Smarkm struct request_info request; 5144743Smarkm char path[MAXPATHNAMELEN]; 5244743Smarkm 5344743Smarkm /* Attempt to prevent the creation of world-writable files. */ 5444743Smarkm 5544743Smarkm#ifdef DAEMON_UMASK 5644743Smarkm umask(DAEMON_UMASK); 5744743Smarkm#endif 5844743Smarkm 5944743Smarkm /* 6044743Smarkm * If argv[0] is an absolute path name, ignore REAL_DAEMON_DIR, and strip 6144743Smarkm * argv[0] to its basename. 6244743Smarkm */ 6344743Smarkm 6444743Smarkm if (argv[0][0] == '/') { 6544743Smarkm strcpy(path, argv[0]); 6644743Smarkm argv[0] = strrchr(argv[0], '/') + 1; 6744743Smarkm } else { 6844743Smarkm sprintf(path, "%s/%s", REAL_DAEMON_DIR, argv[0]); 6944743Smarkm } 7044743Smarkm 7144743Smarkm /* 7244743Smarkm * Open a channel to the syslog daemon. Older versions of openlog() 7344743Smarkm * require only two arguments. 7444743Smarkm */ 7544743Smarkm 7644743Smarkm#ifdef LOG_MAIL 7744743Smarkm (void) openlog(argv[0], LOG_PID, FACILITY); 7844743Smarkm#else 7944743Smarkm (void) openlog(argv[0], LOG_PID); 8044743Smarkm#endif 8144743Smarkm 8244743Smarkm /* 8344743Smarkm * Find out the endpoint addresses of this conversation. Host name 8444743Smarkm * lookups and double checks will be done on demand. 8544743Smarkm */ 8644743Smarkm 8744743Smarkm request_init(&request, RQ_DAEMON, argv[0], RQ_FILE, STDIN_FILENO, 0); 8844743Smarkm fromhost(&request); 8944743Smarkm 9044743Smarkm /* 9144743Smarkm * Optionally look up and double check the remote host name. Sites 9244743Smarkm * concerned with security may choose to refuse connections from hosts 9344743Smarkm * that pretend to have someone elses host name. 9444743Smarkm */ 9544743Smarkm 9644743Smarkm#ifdef PARANOID 9744743Smarkm if (STR_EQ(eval_hostname(request.client), paranoid)) 9844743Smarkm refuse(&request); 9944743Smarkm#endif 10044743Smarkm 10144743Smarkm /* 10244743Smarkm * The BSD rlogin and rsh daemons that came out after 4.3 BSD disallow 10344743Smarkm * socket options at the IP level. They do so for a good reason. 10444743Smarkm * Unfortunately, we cannot use this with SunOS 4.1.x because the 10544743Smarkm * getsockopt() system call can panic the system. 10644743Smarkm */ 10744743Smarkm 10844743Smarkm#ifdef KILL_IP_OPTIONS 10944743Smarkm fix_options(&request); 11044743Smarkm#endif 11144743Smarkm 11244743Smarkm /* 11344743Smarkm * Check whether this host can access the service in argv[0]. The 11444743Smarkm * access-control code invokes optional shell commands as specified in 11544743Smarkm * the access-control tables. 11644743Smarkm */ 11744743Smarkm 11844743Smarkm#ifdef HOSTS_ACCESS 11944743Smarkm if (!hosts_access(&request)) 12044743Smarkm refuse(&request); 12144743Smarkm#endif 12244743Smarkm 12344743Smarkm /* Report request and invoke the real daemon program. */ 12444743Smarkm 12556977Sshin#ifdef INET6 12656977Sshin syslog(allow_severity, "connect from %s (%s)", 12756977Sshin eval_client(&request), eval_hostaddr(request.client)); 12856977Sshin#else 12944743Smarkm syslog(allow_severity, "connect from %s", eval_client(&request)); 13056977Sshin#endif 13144743Smarkm closelog(); 13244743Smarkm (void) execv(path, argv); 13344743Smarkm syslog(LOG_ERR, "error: cannot execute %s: %m", path); 13444743Smarkm clean_exit(&request); 13544743Smarkm /* NOTREACHED */ 13644743Smarkm} 137