fingerd.c revision 127560
169408Sache/* 259243Sobrien * Copyright (c) 1983, 1993 359243Sobrien * The Regents of the University of California. All rights reserved. 459243Sobrien * 559243Sobrien * Redistribution and use in source and binary forms, with or without 659243Sobrien * modification, are permitted provided that the following conditions 759243Sobrien * are met: 859243Sobrien * 1. Redistributions of source code must retain the above copyright 959243Sobrien * notice, this list of conditions and the following disclaimer. 1059243Sobrien * 2. Redistributions in binary form must reproduce the above copyright 1169408Sache * notice, this list of conditions and the following disclaimer in the 1259243Sobrien * documentation and/or other materials provided with the distribution. 1359243Sobrien * 3. All advertising materials mentioning features or use of this software 1459243Sobrien * must display the following acknowledgement: 1559243Sobrien * This product includes software developed by the University of 1659243Sobrien * California, Berkeley and its contributors. 1759243Sobrien * 4. Neither the name of the University nor the names of its contributors 1859243Sobrien * may be used to endorse or promote products derived from this software 1959243Sobrien * without specific prior written permission. 2059243Sobrien * 2159243Sobrien * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 2259243Sobrien * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 2359243Sobrien * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 2459243Sobrien * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 2559243Sobrien * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 2659243Sobrien * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2759243Sobrien * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2859243Sobrien * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2959243Sobrien * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 3059243Sobrien * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 3159243Sobrien * SUCH DAMAGE. 3259243Sobrien */ 3359243Sobrien 3459243Sobrien#ifndef lint 3559243Sobrienstatic const char copyright[] = 3659243Sobrien"@(#) Copyright (c) 1983, 1993\n\ 3759243Sobrien The Regents of the University of California. All rights reserved.\n"; 3859243Sobrien#endif /* not lint */ 3959243Sobrien 4059243Sobrien#ifndef lint 4159243Sobrien#if 0 4259243Sobrienstatic char sccsid[] = "@(#)fingerd.c 8.1 (Berkeley) 6/4/93"; 4359243Sobrien#endif 4459243Sobrienstatic const char rcsid[] = 4559243Sobrien "$FreeBSD: head/libexec/fingerd/fingerd.c 127560 2004-03-29 09:29:51Z pjd $"; 4659243Sobrien#endif /* not lint */ 4759243Sobrien 4859243Sobrien#include <sys/types.h> 4959243Sobrien#include <sys/param.h> 5059243Sobrien#include <sys/socket.h> 5159243Sobrien#include <netinet/in.h> 5259243Sobrien#include <netinet/tcp.h> 5359243Sobrien#include <arpa/inet.h> 5459243Sobrien#include <errno.h> 5559243Sobrien 5659243Sobrien#include <unistd.h> 5759243Sobrien#include <syslog.h> 5859243Sobrien#include <libutil.h> 5959243Sobrien#include <netdb.h> 6059243Sobrien#include <stdio.h> 6159243Sobrien#include <stdlib.h> 6259243Sobrien#include <string.h> 6359243Sobrien#include "pathnames.h" 6459243Sobrien 6559243Sobrienvoid logerr(const char *, ...) __printflike(1, 2); 6659243Sobrien 6759243Sobrienint 6859243Sobrienmain(int argc, char *argv[]) 6959243Sobrien{ 7059243Sobrien FILE *fp; 7159243Sobrien int ch; 7259243Sobrien char *lp; 7359243Sobrien struct sockaddr_storage ss; 7459243Sobrien int p[2], logging, pflag, secure, sval; 7559243Sobrien#define ENTRIES 50 7659243Sobrien char **ap, *av[ENTRIES + 1], **comp, line[1024], *prog; 7759243Sobrien char rhost[MAXHOSTNAMELEN]; 7859243Sobrien 7959243Sobrien prog = _PATH_FINGER; 8059243Sobrien logging = pflag = secure = 0; 8159243Sobrien openlog("fingerd", LOG_PID | LOG_CONS, LOG_DAEMON); 8259243Sobrien opterr = 0; 8359243Sobrien while ((ch = getopt(argc, argv, "lp:s")) != -1) 8459243Sobrien switch (ch) { 8559243Sobrien case 'l': 8659243Sobrien logging = 1; 8759243Sobrien break; 8859243Sobrien case 'p': 8959243Sobrien prog = optarg; 9059243Sobrien pflag = 1; 9159243Sobrien break; 9259243Sobrien case 's': 9359243Sobrien secure = 1; 9459243Sobrien break; 9559243Sobrien case '?': 9659243Sobrien default: 9759243Sobrien logerr("illegal option -- %c", optopt); 9859243Sobrien } 9959243Sobrien 10059243Sobrien /* 10159243Sobrien * Enable server-side Transaction TCP. 10259243Sobrien */ 10359243Sobrien { 10459243Sobrien int one = 1; 10559243Sobrien if (setsockopt(STDOUT_FILENO, IPPROTO_TCP, TCP_NOPUSH, &one, 10659243Sobrien sizeof one) < 0) { 10759243Sobrien logerr("setsockopt(TCP_NOPUSH) failed: %m"); 10859243Sobrien } 10959243Sobrien } 11059243Sobrien 11159243Sobrien if (!fgets(line, sizeof(line), stdin)) 11259243Sobrien exit(1); 11369408Sache 11469408Sache if (logging || pflag) { 11569408Sache sval = sizeof(ss); 11659243Sobrien if (getpeername(0, (struct sockaddr *)&ss, &sval) < 0) 11759243Sobrien logerr("getpeername: %s", strerror(errno)); 11859243Sobrien realhostname_sa(rhost, sizeof rhost - 1, 11959243Sobrien (struct sockaddr *)&ss, sval); 12059243Sobrien rhost[sizeof(rhost) - 1] = '\0'; 12159243Sobrien if (pflag) 12259243Sobrien setenv("FINGERD_REMOTE_HOST", rhost, 1); 12359243Sobrien } 12459243Sobrien 12559243Sobrien if (logging) { 12659243Sobrien char *t; 12759243Sobrien char *end; 12859243Sobrien 12959243Sobrien end = memchr(line, 0, sizeof(line)); 13059243Sobrien if (end == NULL) { 13159243Sobrien if ((t = malloc(sizeof(line) + 1)) == NULL) 13259243Sobrien logerr("malloc: %s", strerror(errno)); 13359243Sobrien memcpy(t, line, sizeof(line)); 13459243Sobrien t[sizeof(line)] = 0; 13559243Sobrien } else { 13659243Sobrien if ((t = strdup(line)) == NULL) 13759243Sobrien logerr("strdup: %s", strerror(errno)); 13859243Sobrien } 13959243Sobrien for (end = t; *end; end++) 14059243Sobrien if (*end == '\n' || *end == '\r') 14159243Sobrien *end = ' '; 14259243Sobrien syslog(LOG_NOTICE, "query from %s: `%s'", rhost, t); 14359243Sobrien } 14459243Sobrien 14559243Sobrien comp = &av[1]; 14659243Sobrien av[2] = "--"; 14759243Sobrien for (lp = line, ap = &av[3];;) { 14859243Sobrien *ap = strtok(lp, " \t\r\n"); 14959243Sobrien if (!*ap) { 15059243Sobrien if (secure && ap == &av[3]) { 15159243Sobrien puts("must provide username\r\n"); 15259243Sobrien exit(1); 15359243Sobrien } 15459243Sobrien break; 15559243Sobrien } 15659243Sobrien if (secure && strchr(*ap, '@')) { 15759243Sobrien puts("forwarding service denied\r\n"); 15859243Sobrien exit(1); 15959243Sobrien } 16059243Sobrien 16159243Sobrien /* RFC742: "/[Ww]" == "-l" */ 16259243Sobrien if ((*ap)[0] == '/' && ((*ap)[1] == 'W' || (*ap)[1] == 'w')) { 16359243Sobrien av[1] = "-l"; 16459243Sobrien comp = &av[0]; 16559243Sobrien } 16659243Sobrien else if (++ap == av + ENTRIES) { 16759243Sobrien *ap = NULL; 16859243Sobrien break; 16959243Sobrien } 17059243Sobrien lp = NULL; 17159243Sobrien } 17259243Sobrien 17359243Sobrien if ((lp = strrchr(prog, '/')) != NULL) 17459243Sobrien *comp = ++lp; 17559243Sobrien else 17659243Sobrien *comp = prog; 17759243Sobrien if (pipe(p) < 0) 17859243Sobrien logerr("pipe: %s", strerror(errno)); 17959243Sobrien 18059243Sobrien switch(vfork()) { 18159243Sobrien case 0: 18259243Sobrien (void)close(p[0]); 18359243Sobrien if (p[1] != STDOUT_FILENO) { 18459243Sobrien (void)dup2(p[1], STDOUT_FILENO); 18559243Sobrien (void)close(p[1]); 18659243Sobrien } 18759243Sobrien dup2(STDOUT_FILENO, STDERR_FILENO); 18859243Sobrien 18959243Sobrien execv(prog, comp); 19059243Sobrien write(STDERR_FILENO, prog, strlen(prog)); 19159243Sobrien#define MSG ": cannot execute\n" 19259243Sobrien write(STDERR_FILENO, MSG, strlen(MSG)); 19359243Sobrien#undef MSG 19459243Sobrien _exit(1); 19559243Sobrien case -1: 19659243Sobrien logerr("fork: %s", strerror(errno)); 19759243Sobrien } 19859243Sobrien (void)close(p[1]); 19959243Sobrien if (!(fp = fdopen(p[0], "r"))) 20059243Sobrien logerr("fdopen: %s", strerror(errno)); 20159243Sobrien while ((ch = getc(fp)) != EOF) { 20259243Sobrien if (ch == '\n') 20359243Sobrien putchar('\r'); 20459243Sobrien putchar(ch); 20559243Sobrien } 20659243Sobrien exit(0); 20759243Sobrien} 20859243Sobrien 20959243Sobrien#include <stdarg.h> 21059243Sobrien 21159243Sobrienvoid 21259243Sobrienlogerr(const char *fmt, ...) 21359243Sobrien{ 21459243Sobrien va_list ap; 21559243Sobrien va_start(ap, fmt); 21659243Sobrien (void)vsyslog(LOG_ERR, fmt, ap); 21759243Sobrien va_end(ap); 21859243Sobrien exit(1); 21959243Sobrien /* NOTREACHED */ 22059243Sobrien} 22159243Sobrien