diff options
Diffstat (limited to 'usr.sbin/inetd/inetd.c')
-rw-r--r-- | usr.sbin/inetd/inetd.c | 589 |
1 files changed, 7 insertions, 582 deletions
diff --git a/usr.sbin/inetd/inetd.c b/usr.sbin/inetd/inetd.c index 341c89b..60303da 100644 --- a/usr.sbin/inetd/inetd.c +++ b/usr.sbin/inetd/inetd.c @@ -42,7 +42,7 @@ static const char copyright[] = static char sccsid[] = "@(#)from: inetd.c 8.4 (Berkeley) 4/13/94"; #endif static const char rcsid[] = - "$Id: inetd.c,v 1.62 1999/07/21 12:19:24 sheldonh Exp $"; + "$Id: inetd.c,v 1.63 1999/07/21 16:09:45 sheldonh Exp $"; #endif /* not lint */ /* @@ -104,14 +104,10 @@ static const char rcsid[] = * Comment lines are indicated by a `#' in column 1. */ #include <sys/param.h> -#include <sys/stat.h> #include <sys/ioctl.h> -#include <sys/socket.h> #include <sys/wait.h> #include <sys/time.h> #include <sys/resource.h> -#include <sys/sysctl.h> -#include <sys/ucred.h> #include <netinet/in.h> #include <netinet/tcp.h> @@ -119,7 +115,6 @@ static const char rcsid[] = #include <rpc/rpc.h> #include <rpc/pmap_clnt.h> -#include <ctype.h> #include <errno.h> #include <err.h> #include <fcntl.h> @@ -136,6 +131,9 @@ static const char rcsid[] = #include <libutil.h> #include <sysexits.h> +#include "inetd.h" +#include "pathnames.h" + #ifndef LIBWRAP_ALLOW_FACILITY # define LIBWRAP_ALLOW_FACILITY LOG_AUTH #endif @@ -162,8 +160,6 @@ static const char rcsid[] = #endif -#include "pathnames.h" - #ifndef MAXCHILD #define MAXCHILD -1 /* maximum number of this service < 0 = no limit */ @@ -200,122 +196,9 @@ struct rpcent *rpc; struct in_addr bind_address; int signalpipe[2]; -struct servtab { - char *se_service; /* name of service */ - int se_socktype; /* type of socket to use */ - char *se_proto; /* protocol used */ - int se_maxchild; /* max number of children */ - int se_maxcpm; /* max connects per IP per minute */ - int se_numchild; /* current number of children */ - pid_t *se_pids; /* array of child pids */ - char *se_user; /* user name to run as */ - char *se_group; /* group name to run as */ -#ifdef LOGIN_CAP - char *se_class; /* login class name to run with */ -#endif - struct biltin *se_bi; /* if built-in, description */ - char *se_server; /* server program */ - char *se_server_name; /* server program without path */ -#define MAXARGV 20 - char *se_argv[MAXARGV+1]; /* program arguments */ - int se_fd; /* open descriptor */ - struct sockaddr_in se_ctrladdr;/* bound address */ - u_char se_type; /* type: normal, mux, or mux+ */ - u_char se_checked; /* looked at during merge */ - u_char se_accept; /* i.e., wait/nowait mode */ - u_char se_rpc; /* ==1 if RPC service */ - int se_rpc_prog; /* RPC program number */ - u_int se_rpc_lowvers; /* RPC low version */ - u_int se_rpc_highvers; /* RPC high version */ - int se_count; /* number started since se_time */ - struct timeval se_time; /* start of se_count */ - struct servtab *se_next; -} *servtab; - -#define NORM_TYPE 0 -#define MUX_TYPE 1 -#define MUXPLUS_TYPE 2 -#define TTCP_TYPE 3 -#define ISMUX(sep) (((sep)->se_type == MUX_TYPE) || \ - ((sep)->se_type == MUXPLUS_TYPE)) -#define ISMUXPLUS(sep) ((sep)->se_type == MUXPLUS_TYPE) -#define ISTTCP(sep) ((sep)->se_type == TTCP_TYPE) - - -void chargen_dg __P((int, struct servtab *)); -void chargen_stream __P((int, struct servtab *)); -void close_sep __P((struct servtab *)); -void flag_signal __P((char)); -void flag_config __P((int)); -void config __P((void)); -void daytime_dg __P((int, struct servtab *)); -void daytime_stream __P((int, struct servtab *)); -void discard_dg __P((int, struct servtab *)); -void discard_stream __P((int, struct servtab *)); -void echo_dg __P((int, struct servtab *)); -void echo_stream __P((int, struct servtab *)); -void endconfig __P((void)); -struct servtab *enter __P((struct servtab *)); -void freeconfig __P((struct servtab *)); -struct servtab *getconfigent __P((void)); -void iderror __P((int, int, FILE *, int)); -void ident_stream __P((int, struct servtab *)); -void machtime_dg __P((int, struct servtab *)); -void machtime_stream __P((int, struct servtab *)); -int matchservent __P((char *, char *, char *)); -char *newstr __P((char *)); -char *nextline __P((FILE *)); -void print_service __P((char *, struct servtab *)); -void addchild __P((struct servtab *, int)); -void flag_reapchild __P((int)); -void reapchild __P((void)); -void enable __P((struct servtab *)); -void disable __P((struct servtab *)); -void flag_retry __P((int)); -void retry __P((void)); -int setconfig __P((void)); -void setup __P((struct servtab *)); -char *sskip __P((char **)); -char *skip __P((char **)); -struct servtab *tcpmux __P((int)); -int cpmip __P((struct servtab *, int)); -void inetd_setproctitle __P((char *, int)); - -void unregisterrpc __P((register struct servtab *sep)); - -struct biltin { - char *bi_service; /* internally provided service name */ - int bi_socktype; /* type of socket supported */ - short bi_fork; /* 1 if should fork before call */ - int bi_maxchild; /* max number of children (-1=default) */ - void (*bi_fn)(); /* function which performs it */ -} biltins[] = { - /* Echo received data */ - { "echo", SOCK_STREAM, 1, -1, echo_stream }, - { "echo", SOCK_DGRAM, 0, 1, echo_dg }, - - /* Internet /dev/null */ - { "discard", SOCK_STREAM, 1, -1, discard_stream }, - { "discard", SOCK_DGRAM, 0, 1, discard_dg }, - - /* Return 32 bit time since 1970 */ - { "time", SOCK_STREAM, 0, -1, machtime_stream }, - { "time", SOCK_DGRAM, 0, 1, machtime_dg }, - - /* Return human-readable time */ - { "daytime", SOCK_STREAM, 0, -1, daytime_stream }, - { "daytime", SOCK_DGRAM, 0, 1, daytime_dg }, - - /* Familiar character generator */ - { "chargen", SOCK_STREAM, 1, -1, chargen_stream }, - { "chargen", SOCK_DGRAM, 0, 1, chargen_dg }, - - { "tcpmux", SOCK_STREAM, 1, -1, (void (*)())tcpmux }, - - { "auth", SOCK_STREAM, 1, -1, ident_stream }, - - { NULL } -}; +struct servtab *servtab; + +extern struct biltin biltins[]; #define NUMINT (sizeof(intab) / sizeof(struct inent)) char *CONFIG = _PATH_INETDCONF; @@ -1626,137 +1509,6 @@ inetd_setproctitle(a, s) /* * Internet services provided internally by inetd: */ -#define BUFSIZE 8192 - -/* ARGSUSED */ -void -iderror(lport, fport, fp, er) - int lport, fport, er; - FILE *fp; -{ - fprintf(fp, "%d , %d : ERROR : %s\r\n", lport, fport, - er == -1 ? "HIDDEN-USER" : er ? strerror(er) : "UNKNOWN-ERROR"); - fflush(fp); - fclose(fp); - - exit(0); -} - -/* ARGSUSED */ -void -ident_stream(s, sep) /* Ident service */ - int s; - struct servtab *sep; -{ - struct sockaddr_in sin[2]; - struct ucred uc; - struct passwd *pw; - FILE *fp; - char buf[BUFSIZE], *cp, **av; - int len, c, rflag = 0, fflag = 0, argc = 0; - u_short lport, fport; - - inetd_setproctitle(sep->se_service, s); - optind = 1; - optreset = 1; - for (av = sep->se_argv; *av; av++) - argc++; - if (argc) { - while ((c = getopt(argc, sep->se_argv, "fr")) != -1) - switch (c) { - case 'f': - fflag = 1; - break; - case 'r': - rflag = 1; - break; - default: - break; - } - } - fp = fdopen(s, "r+"); - len = sizeof(sin[0]); - if (getsockname(s, (struct sockaddr *)&sin[0], &len) == -1) - iderror(0, 0, fp, errno); - len = sizeof(sin[1]); - if (getpeername(s, (struct sockaddr *)&sin[1], &len) == -1) - iderror(0, 0, fp, errno); - errno = 0; - if (fgets(buf, sizeof(buf), fp) == NULL) - iderror(0, 0, fp, errno); - buf[BUFSIZE - 1] = '\0'; - strtok(buf, "\r\n"); - cp = strtok(buf, ","); - if (cp == NULL || sscanf(cp, "%hu", &lport) != 1) - iderror(0, 0, fp, 0); - cp = strtok(NULL, ","); - if (cp == NULL || sscanf(cp, "%hu", &fport) != 1) - iderror(0, 0, fp, 0); - if (!rflag) - iderror(lport, fport, fp, -1); - sin[0].sin_port = htons(lport); - sin[1].sin_port = htons(fport); - len = sizeof(uc); - if (sysctlbyname("net.inet.tcp.getcred", &uc, &len, sin, - sizeof(sin)) == -1) - iderror(lport, fport, fp, errno); - pw = getpwuid(uc.cr_uid); - if (pw == NULL) - iderror(lport, fport, fp, errno); - if (fflag) { - FILE *fakeid = NULL; - char fakeid_path[PATH_MAX]; - struct stat sb; - seteuid(pw->pw_uid); - setegid(pw->pw_gid); - snprintf(fakeid_path, sizeof(fakeid_path), "%s/.fakeid", - pw->pw_dir); - if ((fakeid = fopen(fakeid_path, "r")) != NULL && - fstat(fileno(fakeid), &sb) != -1 && S_ISREG(sb.st_mode)) { - buf[sizeof(buf) - 1] = '\0'; - if (fgets(buf, sizeof(buf), fakeid) == NULL) { - cp = pw->pw_name; - fclose(fakeid); - goto printit; - } - fclose(fakeid); - strtok(buf, "\r\n"); - if (strlen(buf) > 16) - buf[16] = '\0'; - cp = buf; - while (isspace(*cp)) - cp++; - strtok(cp, " \t"); - if (!*cp || getpwnam(cp)) - cp = getpwuid(uc.cr_uid)->pw_name; - } else - cp = pw->pw_name; - } else - cp = pw->pw_name; -printit: - fprintf(fp, "%d , %d : USERID : FreeBSD :%s\r\n", lport, fport, - cp); - fflush(fp); - fclose(fp); - - exit(0); -} - -/* ARGSUSED */ -void -echo_stream(s, sep) /* Echo service -- echo data back */ - int s; - struct servtab *sep; -{ - char buffer[BUFSIZE]; - int i; - - inetd_setproctitle(sep->se_service, s); - while ((i = read(s, buffer, sizeof(buffer))) > 0 && - write(s, buffer, i) > 0) - ; - exit(0); -} int check_loop(sin, sep) struct sockaddr_in *sin; @@ -1780,245 +1532,6 @@ int check_loop(sin, sep) return 0; } -/* ARGSUSED */ -void -echo_dg(s, sep) /* Echo service -- echo data back */ - int s; - struct servtab *sep; -{ - char buffer[BUFSIZE]; - int i, size; - struct sockaddr_in sin; - - size = sizeof(sin); - if ((i = recvfrom(s, buffer, sizeof(buffer), 0, - (struct sockaddr *)&sin, &size)) < 0) - return; - - if (check_loop(&sin, sep)) - return; - - (void) sendto(s, buffer, i, 0, (struct sockaddr *)&sin, - sizeof(sin)); -} - -/* ARGSUSED */ -void -discard_stream(s, sep) /* Discard service -- ignore data */ - int s; - struct servtab *sep; -{ - int ret; - char buffer[BUFSIZE]; - - inetd_setproctitle(sep->se_service, s); - while (1) { - while ((ret = read(s, buffer, sizeof(buffer))) > 0) - ; - if (ret == 0 || errno != EINTR) - break; - } - exit(0); -} - -/* ARGSUSED */ -void -discard_dg(s, sep) /* Discard service -- ignore data */ - int s; - struct servtab *sep; -{ - char buffer[BUFSIZE]; - - (void) read(s, buffer, sizeof(buffer)); -} - -#include <ctype.h> -#define LINESIZ 72 -char ring[128]; -char *endring; - -void -initring() -{ - int i; - - endring = ring; - - for (i = 0; i <= 128; ++i) - if (isprint(i)) - *endring++ = i; -} - -/* ARGSUSED */ -void -chargen_stream(s, sep) /* Character generator */ - int s; - struct servtab *sep; -{ - int len; - char *rs, text[LINESIZ+2]; - - inetd_setproctitle(sep->se_service, s); - - if (!endring) { - initring(); - rs = ring; - } - - text[LINESIZ] = '\r'; - text[LINESIZ + 1] = '\n'; - for (rs = ring;;) { - if ((len = endring - rs) >= LINESIZ) - memmove(text, rs, LINESIZ); - else { - memmove(text, rs, len); - memmove(text + len, ring, LINESIZ - len); - } - if (++rs == endring) - rs = ring; - if (write(s, text, sizeof(text)) != sizeof(text)) - break; - } - exit(0); -} - -/* ARGSUSED */ -void -chargen_dg(s, sep) /* Character generator */ - int s; - struct servtab *sep; -{ - struct sockaddr_in sin; - static char *rs; - int len, size; - char text[LINESIZ+2]; - - if (endring == 0) { - initring(); - rs = ring; - } - - size = sizeof(sin); - if (recvfrom(s, text, sizeof(text), 0, - (struct sockaddr *)&sin, &size) < 0) - return; - - if (check_loop(&sin, sep)) - return; - - if ((len = endring - rs) >= LINESIZ) - memmove(text, rs, LINESIZ); - else { - memmove(text, rs, len); - memmove(text + len, ring, LINESIZ - len); - } - if (++rs == endring) - rs = ring; - text[LINESIZ] = '\r'; - text[LINESIZ + 1] = '\n'; - (void) sendto(s, text, sizeof(text), 0, - (struct sockaddr *)&sin, sizeof(sin)); -} - -/* - * Return a machine readable date and time, in the form of the - * number of seconds since midnight, Jan 1, 1900. Since gettimeofday - * returns the number of seconds since midnight, Jan 1, 1970, - * we must add 2208988800 seconds to this figure to make up for - * some seventy years Bell Labs was asleep. - */ - -unsigned long -machtime() -{ - struct timeval tv; - - if (gettimeofday(&tv, (struct timezone *)NULL) < 0) { - if (debug) - warnx("unable to get time of day"); - return (0L); - } -#define OFFSET ((u_long)25567 * 24*60*60) - return (htonl((long)(tv.tv_sec + OFFSET))); -#undef OFFSET -} - -/* ARGSUSED */ -void -machtime_stream(s, sep) - int s; - struct servtab *sep; -{ - unsigned long result; - - result = machtime(); - (void) write(s, (char *) &result, sizeof(result)); -} - -/* ARGSUSED */ -void -machtime_dg(s, sep) - int s; - struct servtab *sep; -{ - unsigned long result; - struct sockaddr_in sin; - int size; - - size = sizeof(sin); - if (recvfrom(s, (char *)&result, sizeof(result), 0, - (struct sockaddr *)&sin, &size) < 0) - return; - - if (check_loop(&sin, sep)) - return; - - result = machtime(); - (void) sendto(s, (char *) &result, sizeof(result), 0, - (struct sockaddr *)&sin, sizeof(sin)); -} - -/* ARGSUSED */ -void -daytime_stream(s, sep) /* Return human-readable time of day */ - int s; - struct servtab *sep; -{ - char buffer[256]; - time_t clock; - - clock = time((time_t *) 0); - - (void) sprintf(buffer, "%.24s\r\n", ctime(&clock)); - (void) write(s, buffer, strlen(buffer)); -} - -/* ARGSUSED */ -void -daytime_dg(s, sep) /* Return human-readable time of day */ - int s; - struct servtab *sep; -{ - char buffer[256]; - time_t clock; - struct sockaddr_in sin; - int size; - - clock = time((time_t *) 0); - - size = sizeof(sin); - if (recvfrom(s, buffer, sizeof(buffer), 0, - (struct sockaddr *)&sin, &size) < 0) - return; - - if (check_loop(&sin, sep)) - return; - - (void) sprintf(buffer, "%.24s\r\n", ctime(&clock)); - (void) sendto(s, buffer, strlen(buffer), 0, - (struct sockaddr *)&sin, sizeof(sin)); -} - /* * print_service: * Dump relevant information to stderr @@ -2042,94 +1555,6 @@ print_service(action, sep) (void *) sep->se_bi, sep->se_server); } -/* - * Based on TCPMUX.C by Mark K. Lottor November 1988 - * sri-nic::ps:<mkl>tcpmux.c - */ - - -static int /* # of characters upto \r,\n or \0 */ -getline(fd, buf, len) - int fd; - char *buf; - int len; -{ - int count = 0, n; - struct sigaction sa; - - sa.sa_flags = 0; - sigemptyset(&sa.sa_mask); - sa.sa_handler = SIG_DFL; - sigaction(SIGALRM, &sa, (struct sigaction *)0); - do { - alarm(10); - n = read(fd, buf, len-count); - alarm(0); - if (n == 0) - return (count); - if (n < 0) - return (-1); - while (--n >= 0) { - if (*buf == '\r' || *buf == '\n' || *buf == '\0') - return (count); - count++; - buf++; - } - } while (count < len); - return (count); -} - -#define MAX_SERV_LEN (256+2) /* 2 bytes for \r\n */ - -#define strwrite(fd, buf) (void) write(fd, buf, sizeof(buf)-1) - -struct servtab * -tcpmux(s) - int s; -{ - struct servtab *sep; - char service[MAX_SERV_LEN+1]; - int len; - - /* Get requested service name */ - if ((len = getline(s, service, MAX_SERV_LEN)) < 0) { - strwrite(s, "-Error reading service name\r\n"); - return (NULL); - } - service[len] = '\0'; - - if (debug) - warnx("tcpmux: someone wants %s", service); - - /* - * Help is a required command, and lists available services, - * one per line. - */ - if (!strcasecmp(service, "help")) { - for (sep = servtab; sep; sep = sep->se_next) { - if (!ISMUX(sep)) - continue; - (void)write(s,sep->se_service,strlen(sep->se_service)); - strwrite(s, "\r\n"); - } - return (NULL); - } - - /* Try matching a service in inetd.conf with the request */ - for (sep = servtab; sep; sep = sep->se_next) { - if (!ISMUX(sep)) - continue; - if (!strcasecmp(service, sep->se_service)) { - if (ISMUXPLUS(sep)) { - strwrite(s, "+Go\r\n"); - } - return (sep); - } - } - strwrite(s, "-Service not available\r\n"); - return (NULL); -} - #define CPMHSIZE 256 #define CPMHMASK (CPMHSIZE-1) #define CHTGRAN 10 |