/* * Copyright (c) 1983 The Regents of the University of California. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the University of * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ char copyright[] = "@(#) Copyright (c) 1983 The Regents of the University of California.\n" "All rights reserved.\n"; /* * from: @(#)fingerd.c 5.6 (Berkeley) 6/1/90" */ char rcsid[] = "$Id: fingerd.c,v 1.23 1999/12/12 18:46:28 dholland Exp $"; #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "pathnames.h" #include "../version.h" #define ENTRIES 50 #define WS " \t\r\n" /* These are used in this order if the finger path compiled in doesn't work. */ #define _ALT_PATH_FINGER_1 "/usr/local/bin/finger" #define _ALT_PATH_FINGER_2 "/usr/ucb/finger" #define _ALT_PATH_FINGER_3 "/usr/bin/finger" static void fatal(const char *msg, int use_errno, int tolog, int toclient) { const char *err = ""; const char *sep = ""; if (use_errno) { err = strerror(errno); sep = ": "; } if (tolog) syslog(LOG_ERR, "%s%s%s\n", msg, sep, err); if (toclient) fprintf(stderr, "fingerd: %s%s%s\r\n", msg, sep, err); else fprintf(stderr, "fingerd: Internal error\r\n"); exit(1); } static void timeout(int sig) { (void)sig; errno = ETIMEDOUT; fatal("Input timeout", 0, 1, 1); } int main(int argc, char *argv[]) { #if 0 FILE *fp; int p[2], ch; pid_t pid; #endif int ca; const char *av[ENTRIES + 1]; const char **avy; char *const *avx; char line[1024]; int welcome = 0, heavylogging = 0, nouserlist = 0; int patience = 60, forwarding = 0; int k, nusers; char *s, *t; const char *fingerpath = NULL; struct sockaddr_in sn; socklen_t sval = sizeof(sn); if (getpeername(0, (struct sockaddr *) &sn, &sval) < 0) { fatal("getpeername", 1, 0, 1); } openlog("fingerd", LOG_PID, LOG_DAEMON); if (!getuid() || !geteuid()) { struct passwd *pwd = getpwnam("nobody"); if (pwd) { initgroups(pwd->pw_name, pwd->pw_gid); setgid(pwd->pw_gid); setuid(pwd->pw_uid); } seteuid(0); /* this should fail */ if (!getuid() || !geteuid()) { fatal("setuid: couldn't drop root", 0, 1, 0); } } /*endpwent(); -- is it safe to put this here? */ opterr = 0; while ((ca = getopt(argc, argv, "wlL:p:uft:h?")) != EOF) { switch(ca) { case 'w': welcome = 1; break; case 'l': heavylogging = 1; break; case 'L': case 'p': fingerpath = optarg; break; case 'u': nouserlist = 1; break; case 'f': forwarding = 1; break; case 't': patience = atoi(optarg); break; case '?': case 'h': default: syslog(LOG_ERR, "usage: fingerd [-wulf]" "[-pL /path/finger] [-t timeout]"); exit(1); } } argc -= optind; argv += optind; /* * Hang up after a while so people can't DoS by leaving lots of * open sockets about. */ if (patience != 0) { signal(SIGALRM, timeout); alarm(patience); } if (!fgets(line, sizeof(line), stdin)) { fatal("Client hung up - probable port-scan", 0, 1, 0); } if (welcome) { char buf[256]; struct hostent *hp; struct utsname utsname; uname(&utsname); gethostname(buf, sizeof(buf)); if ((hp = gethostbyname(buf))) { /* paranoia: dns spoofing? */ strncpy(buf, hp->h_name, sizeof(buf)); buf[sizeof(buf)-1] = 0; } printf("\r\nWelcome to %s version %s at %s !\r\n\n", utsname.sysname, utsname.release, buf); fflush(stdout); switch (fork()) { case -1: /* fork failed, oh well */ break; case 0: /* child */ execl(_PATH_UPTIME, _PATH_UPTIME, NULL); _exit(1); default: /* parent */ wait(NULL); break; } fflush(stdout); printf("\r\n"); fflush(stdout); } k = nusers = 0; av[k++] = "finger"; for (s = strtok(line, WS); s && k