fingerd.c revision 12908
197049Speter/*
2174993Srafan * Copyright (c) 1983, 1993
397049Speter *	The Regents of the University of California.  All rights reserved.
497049Speter *
597049Speter * Redistribution and use in source and binary forms, with or without
697049Speter * modification, are permitted provided that the following conditions
797049Speter * are met:
897049Speter * 1. Redistributions of source code must retain the above copyright
997049Speter *    notice, this list of conditions and the following disclaimer.
1097049Speter * 2. Redistributions in binary form must reproduce the above copyright
1197049Speter *    notice, this list of conditions and the following disclaimer in the
1297049Speter *    documentation and/or other materials provided with the distribution.
1397049Speter * 3. All advertising materials mentioning features or use of this software
1497049Speter *    must display the following acknowledgement:
1597049Speter *	This product includes software developed by the University of
1697049Speter *	California, Berkeley and its contributors.
1797049Speter * 4. Neither the name of the University nor the names of its contributors
1897049Speter *    may be used to endorse or promote products derived from this software
1997049Speter *    without specific prior written permission.
2097049Speter *
2197049Speter * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
2297049Speter * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
2397049Speter * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
2497049Speter * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
2597049Speter * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2697049Speter * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2797049Speter * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2897049Speter * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2997049Speter * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
3097049Speter * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
3197049Speter * SUCH DAMAGE.
3297049Speter */
3397049Speter
3497049Speter#ifndef lint
3597049Speterstatic char copyright[] =
3697049Speter"@(#) Copyright (c) 1983, 1993\n\
3797049Speter	The Regents of the University of California.  All rights reserved.\n";
38174993Srafan#endif /* not lint */
3997049Speter
4097049Speter#ifndef lint
4197049Speter/*
42166124Srafanstatic char sccsid[] = "@(#)fingerd.c	8.1 (Berkeley) 6/4/93";
43166124Srafan*/
44166124Srafanstatic const char rcsid[] =
4597049Speter	"$Id$";
4697049Speter#endif /* not lint */
47166124Srafan
48166124Srafan#include <sys/types.h>
49166124Srafan#include <sys/socket.h>
50166124Srafan#include <netinet/in.h>
51166124Srafan#include <netinet/tcp.h>
5297049Speter#include <arpa/inet.h>
5397049Speter#include <errno.h>
5497049Speter
5597049Speter#include <unistd.h>
5697049Speter#include <syslog.h>
57174993Srafan#include <netdb.h>
58174993Srafan#include <stdio.h>
59174993Srafan#include <stdlib.h>
6097049Speter#include <strings.h>
61166124Srafan#include "pathnames.h"
62166124Srafan
63166124Srafanvoid logerr __P((const char *, ...));
6497049Speter
6597049Speterint
66166124Srafanmain(argc, argv)
67166124Srafan	int argc;
6897049Speter	char *argv[];
69166124Srafan{
70166124Srafan	register FILE *fp;
71166124Srafan	register int ch;
72166124Srafan	register char *lp;
7397049Speter	struct hostent *hp;
7497049Speter	struct sockaddr_in sin;
75166124Srafan	int p[2], logging, secure, sval;
7697049Speter#define	ENTRIES	50
7797049Speter	char **ap, *av[ENTRIES + 1], **comp, line[1024], *prog;
7897049Speter
7997049Speter	prog = _PATH_FINGER;
80166124Srafan	logging = secure = 0;
8197049Speter	openlog("fingerd", LOG_PID | LOG_CONS, LOG_DAEMON);
82166124Srafan	opterr = 0;
83166124Srafan	while ((ch = getopt(argc, argv, "slp:")) != EOF)
84166124Srafan		switch (ch) {
85166124Srafan		case 'l':
86166124Srafan			logging = 1;
87166124Srafan			break;
8897049Speter		case 'p':
8997049Speter			prog = optarg;
9097049Speter			break;
9197049Speter		case 's':
9297049Speter			secure = 1;
9397049Speter			break;
9497049Speter		case '?':
9597049Speter		default:
96166124Srafan			logerr("illegal option -- %c", ch);
97166124Srafan		}
98166124Srafan
99166124Srafan	if (logging) {
100166124Srafan		sval = sizeof(sin);
10197049Speter		if (getpeername(0, (struct sockaddr *)&sin, &sval) < 0)
10297049Speter			logerr("getpeername: %s", strerror(errno));
10397049Speter		if (hp = gethostbyaddr((char *)&sin.sin_addr.s_addr,
10497049Speter		    sizeof(sin.sin_addr.s_addr), AF_INET))
10597049Speter			lp = hp->h_name;
10697049Speter		else
10797049Speter			lp = inet_ntoa(sin.sin_addr);
10897049Speter		syslog(LOG_NOTICE, "query from %s", lp);
10997049Speter	}
11097049Speter
11197049Speter	/*
11297049Speter	 * Enable server-side Transaction TCP.
11397049Speter	 */
11497049Speter	{
11597049Speter		int one = 1;
116166124Srafan		if (setsockopt(STDOUT_FILENO, IPPROTO_TCP, TCP_NOPUSH, &one,
117166124Srafan			       sizeof one) < 0) {
11897049Speter			logerr("setsockopt(TCP_NOPUSH) failed: %m");
11997049Speter		}
120166124Srafan	}
12197049Speter
12297049Speter	if (!fgets(line, sizeof(line), stdin))
12397049Speter		exit(1);
12497049Speter
12597049Speter	comp = &av[1];
12697049Speter	av[2] = "--";
12797049Speter	for (lp = line, ap = &av[3];;) {
12897049Speter		*ap = strtok(lp, " \t\r\n");
12997049Speter		if (!*ap) {
130			if (secure && ap == &av[3]) {
131				puts("must provide username\r\n");
132				exit(1);
133			}
134			break;
135		}
136		if (secure && strchr(*ap, '@')) {
137			puts("forwarding service denied\r\n");
138			exit(1);
139		}
140
141		/* RFC742: "/[Ww]" == "-l" */
142		if ((*ap)[0] == '/' && ((*ap)[1] == 'W' || (*ap)[1] == 'w')) {
143			av[1] = "-l";
144			comp = &av[0];
145		}
146		else if (++ap == av + ENTRIES)
147			break;
148		lp = NULL;
149	}
150
151	if (lp = strrchr(prog, '/'))
152		*comp = ++lp;
153	else
154		*comp = prog;
155	if (pipe(p) < 0)
156		logerr("pipe: %s", strerror(errno));
157
158	switch(vfork()) {
159	case 0:
160		(void)close(p[0]);
161		if (p[1] != 1) {
162			(void)dup2(p[1], 1);
163			(void)close(p[1]);
164		}
165		execv(prog, comp);
166		logerr("execv: %s: %s", prog, strerror(errno));
167		_exit(1);
168	case -1:
169		logerr("fork: %s", strerror(errno));
170	}
171	(void)close(p[1]);
172	if (!(fp = fdopen(p[0], "r")))
173		logerr("fdopen: %s", strerror(errno));
174	while ((ch = getc(fp)) != EOF) {
175		if (ch == '\n')
176			putchar('\r');
177		putchar(ch);
178	}
179	exit(0);
180}
181
182#if __STDC__
183#include <stdarg.h>
184#else
185#include <varargs.h>
186#endif
187
188void
189#if __STDC__
190logerr(const char *fmt, ...)
191#else
192logerr(fmt, va_alist)
193	char *fmt;
194        va_dcl
195#endif
196{
197	va_list ap;
198#if __STDC__
199	va_start(ap, fmt);
200#else
201	va_start(ap);
202#endif
203	(void)vsyslog(LOG_ERR, fmt, ap);
204	va_end(ap);
205	exit(1);
206	/* NOTREACHED */
207}
208