11592Srgrimes/* 21592Srgrimes * Copyright (c) 1983, 1993 31592Srgrimes * The Regents of the University of California. All rights reserved. 41592Srgrimes * 51592Srgrimes * Redistribution and use in source and binary forms, with or without 61592Srgrimes * modification, are permitted provided that the following conditions 71592Srgrimes * are met: 81592Srgrimes * 1. Redistributions of source code must retain the above copyright 91592Srgrimes * notice, this list of conditions and the following disclaimer. 101592Srgrimes * 2. Redistributions in binary form must reproduce the above copyright 111592Srgrimes * notice, this list of conditions and the following disclaimer in the 121592Srgrimes * documentation and/or other materials provided with the distribution. 13262435Sbrueffer * 3. Neither the name of the University nor the names of its contributors 141592Srgrimes * may be used to endorse or promote products derived from this software 151592Srgrimes * without specific prior written permission. 161592Srgrimes * 171592Srgrimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 181592Srgrimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 191592Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 201592Srgrimes * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 211592Srgrimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 221592Srgrimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 231592Srgrimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 241592Srgrimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 251592Srgrimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 261592Srgrimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 271592Srgrimes * SUCH DAMAGE. 281592Srgrimes */ 291592Srgrimes 301592Srgrimes#ifndef lint 3131308Scharnierstatic const char copyright[] = 321592Srgrimes"@(#) Copyright (c) 1983, 1993\n\ 331592Srgrimes The Regents of the University of California. All rights reserved.\n"; 341592Srgrimes#endif /* not lint */ 351592Srgrimes 361592Srgrimes#ifndef lint 3731308Scharnier#if 0 381592Srgrimesstatic char sccsid[] = "@(#)fingerd.c 8.1 (Berkeley) 6/4/93"; 3931308Scharnier#endif 4012908Swollmanstatic const char rcsid[] = 4150476Speter "$FreeBSD$"; 421592Srgrimes#endif /* not lint */ 431592Srgrimes 4471274Sjedgar#include <sys/types.h> 4545393Sbrian#include <sys/param.h> 461592Srgrimes#include <sys/socket.h> 471592Srgrimes#include <netinet/in.h> 4812908Swollman#include <netinet/tcp.h> 491592Srgrimes#include <arpa/inet.h> 501592Srgrimes#include <errno.h> 511592Srgrimes 521592Srgrimes#include <unistd.h> 531592Srgrimes#include <syslog.h> 5471274Sjedgar#include <libutil.h> 551592Srgrimes#include <netdb.h> 561592Srgrimes#include <stdio.h> 571592Srgrimes#include <stdlib.h> 5897635Swollman#include <string.h> 591592Srgrimes#include "pathnames.h" 601592Srgrimes 61181269Scpercivavoid logerr(const char *, ...) __printflike(1, 2) __dead2; 621592Srgrimes 631592Srgrimesint 6490148Simpmain(int argc, char *argv[]) 651592Srgrimes{ 6690148Simp FILE *fp; 6790148Simp int ch; 6890148Simp char *lp; 6957313Sshin struct sockaddr_storage ss; 70141918Sstefanf socklen_t sval; 71206038Sdes int p[2], debug, kflag, logging, pflag, secure; 721592Srgrimes#define ENTRIES 50 731592Srgrimes char **ap, *av[ENTRIES + 1], **comp, line[1024], *prog; 7445418Sbrian char rhost[MAXHOSTNAMELEN]; 751592Srgrimes 761592Srgrimes prog = _PATH_FINGER; 77206040Sdes debug = logging = kflag = pflag = secure = 0; 781592Srgrimes openlog("fingerd", LOG_PID | LOG_CONS, LOG_DAEMON); 791592Srgrimes opterr = 0; 80206038Sdes while ((ch = getopt(argc, argv, "dklp:s")) != -1) 811592Srgrimes switch (ch) { 82206038Sdes case 'd': 83206038Sdes debug = 1; 84206038Sdes break; 85206038Sdes case 'k': 86206038Sdes kflag = 1; 87206038Sdes break; 881592Srgrimes case 'l': 891592Srgrimes logging = 1; 901592Srgrimes break; 911592Srgrimes case 'p': 921592Srgrimes prog = optarg; 9398897Swollman pflag = 1; 941592Srgrimes break; 951592Srgrimes case 's': 961592Srgrimes secure = 1; 971592Srgrimes break; 981592Srgrimes case '?': 991592Srgrimes default: 10047291Speter logerr("illegal option -- %c", optopt); 1011592Srgrimes } 1021592Srgrimes 10312908Swollman /* 10412908Swollman * Enable server-side Transaction TCP. 10512908Swollman */ 106206038Sdes if (!debug) { 10712908Swollman int one = 1; 10812908Swollman if (setsockopt(STDOUT_FILENO, IPPROTO_TCP, TCP_NOPUSH, &one, 10912908Swollman sizeof one) < 0) { 11012908Swollman logerr("setsockopt(TCP_NOPUSH) failed: %m"); 11112908Swollman } 11212908Swollman } 11312908Swollman 1141592Srgrimes if (!fgets(line, sizeof(line), stdin)) 1151592Srgrimes exit(1); 1168870Srgrimes 117206038Sdes if (!debug && (logging || pflag)) { 11898897Swollman sval = sizeof(ss); 11998897Swollman if (getpeername(0, (struct sockaddr *)&ss, &sval) < 0) 12098897Swollman logerr("getpeername: %s", strerror(errno)); 12198897Swollman realhostname_sa(rhost, sizeof rhost - 1, 12298897Swollman (struct sockaddr *)&ss, sval); 12398897Swollman rhost[sizeof(rhost) - 1] = '\0'; 12498897Swollman if (pflag) 12598897Swollman setenv("FINGERD_REMOTE_HOST", rhost, 1); 12698897Swollman } 12798897Swollman 12831168Ssef if (logging) { 12931168Ssef char *t; 13031168Ssef char *end; 13131168Ssef 13231168Ssef end = memchr(line, 0, sizeof(line)); 13331168Ssef if (end == NULL) { 13471274Sjedgar if ((t = malloc(sizeof(line) + 1)) == NULL) 13571274Sjedgar logerr("malloc: %s", strerror(errno)); 13631168Ssef memcpy(t, line, sizeof(line)); 13731168Ssef t[sizeof(line)] = 0; 13831168Ssef } else { 13971274Sjedgar if ((t = strdup(line)) == NULL) 14071274Sjedgar logerr("strdup: %s", strerror(errno)); 14131168Ssef } 14231168Ssef for (end = t; *end; end++) 14331168Ssef if (*end == '\n' || *end == '\r') 14431168Ssef *end = ' '; 14545393Sbrian syslog(LOG_NOTICE, "query from %s: `%s'", rhost, t); 14631168Ssef } 14731168Ssef 148206038Sdes comp = &av[2]; 149206038Sdes av[3] = "--"; 150206038Sdes if (kflag) 151206038Sdes *comp-- = "-k"; 152206038Sdes for (lp = line, ap = &av[4];;) { 1531592Srgrimes *ap = strtok(lp, " \t\r\n"); 1541592Srgrimes if (!*ap) { 155206038Sdes if (secure && ap == &av[4]) { 1561592Srgrimes puts("must provide username\r\n"); 1571592Srgrimes exit(1); 1581592Srgrimes } 1591592Srgrimes break; 1601592Srgrimes } 1611592Srgrimes if (secure && strchr(*ap, '@')) { 1626180Sphk puts("forwarding service denied\r\n"); 1631592Srgrimes exit(1); 1641592Srgrimes } 1651592Srgrimes 1661592Srgrimes /* RFC742: "/[Ww]" == "-l" */ 1671592Srgrimes if ((*ap)[0] == '/' && ((*ap)[1] == 'W' || (*ap)[1] == 'w')) { 168206038Sdes *comp-- = "-l"; 1691592Srgrimes } 17084454Sru else if (++ap == av + ENTRIES) { 17184454Sru *ap = NULL; 1721592Srgrimes break; 17384454Sru } 1741592Srgrimes lp = NULL; 1751592Srgrimes } 1761592Srgrimes 177127560Spjd if ((lp = strrchr(prog, '/')) != NULL) 1781592Srgrimes *comp = ++lp; 1791592Srgrimes else 1801592Srgrimes *comp = prog; 1811592Srgrimes if (pipe(p) < 0) 18212908Swollman logerr("pipe: %s", strerror(errno)); 1831592Srgrimes 184206038Sdes if (debug) { 185206038Sdes fprintf(stderr, "%s", prog); 186206038Sdes for (ap = comp; *ap != NULL; ++ap) 187206038Sdes fprintf(stderr, " %s", *ap); 188206038Sdes fprintf(stderr, "\n"); 189206038Sdes } 190206038Sdes 1911592Srgrimes switch(vfork()) { 1921592Srgrimes case 0: 1931592Srgrimes (void)close(p[0]); 19498897Swollman if (p[1] != STDOUT_FILENO) { 19598897Swollman (void)dup2(p[1], STDOUT_FILENO); 1961592Srgrimes (void)close(p[1]); 1971592Srgrimes } 19898897Swollman dup2(STDOUT_FILENO, STDERR_FILENO); 19998897Swollman 2001592Srgrimes execv(prog, comp); 20198897Swollman write(STDERR_FILENO, prog, strlen(prog)); 20298897Swollman#define MSG ": cannot execute\n" 20398897Swollman write(STDERR_FILENO, MSG, strlen(MSG)); 20498897Swollman#undef MSG 2051592Srgrimes _exit(1); 2061592Srgrimes case -1: 20712908Swollman logerr("fork: %s", strerror(errno)); 2081592Srgrimes } 2091592Srgrimes (void)close(p[1]); 2101592Srgrimes if (!(fp = fdopen(p[0], "r"))) 21112908Swollman logerr("fdopen: %s", strerror(errno)); 2121592Srgrimes while ((ch = getc(fp)) != EOF) { 2131592Srgrimes if (ch == '\n') 2141592Srgrimes putchar('\r'); 2151592Srgrimes putchar(ch); 2161592Srgrimes } 2171592Srgrimes exit(0); 2181592Srgrimes} 2191592Srgrimes 2201592Srgrimes#include <stdarg.h> 2211592Srgrimes 2221592Srgrimesvoid 22312908Swollmanlogerr(const char *fmt, ...) 2241592Srgrimes{ 2251592Srgrimes va_list ap; 2261592Srgrimes va_start(ap, fmt); 2271592Srgrimes (void)vsyslog(LOG_ERR, fmt, ap); 2281592Srgrimes va_end(ap); 2291592Srgrimes exit(1); 2301592Srgrimes /* NOTREACHED */ 2311592Srgrimes} 232