fingerd.c revision 1.14
1/*	$OpenBSD: fingerd.c,v 1.14 1999/07/03 18:24:13 deraadt Exp $	*/
2
3/*
4 * Copyright (c) 1983, 1993
5 *	The Regents of the University of California.  All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 *    notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 *    notice, this list of conditions and the following disclaimer in the
14 *    documentation and/or other materials provided with the distribution.
15 * 3. All advertising materials mentioning features or use of this software
16 *    must display the following acknowledgement:
17 *	This product includes software developed by the University of
18 *	California, Berkeley and its contributors.
19 * 4. Neither the name of the University nor the names of its contributors
20 *    may be used to endorse or promote products derived from this software
21 *    without specific prior written permission.
22 *
23 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
24 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
27 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33 * SUCH DAMAGE.
34 */
35
36#ifndef lint
37static char copyright[] =
38"@(#) Copyright (c) 1983, 1993\n\
39	The Regents of the University of California.  All rights reserved.\n";
40#endif /* not lint */
41
42#ifndef lint
43#if 0
44static char sccsid[] = "from: @(#)fingerd.c	8.1 (Berkeley) 6/4/93";
45#else
46static char rcsid[] = "$OpenBSD: fingerd.c,v 1.14 1999/07/03 18:24:13 deraadt Exp $";
47#endif
48#endif /* not lint */
49
50#include <sys/types.h>
51#include <sys/socket.h>
52#include <netinet/in.h>
53#include <arpa/inet.h>
54#include <errno.h>
55
56#include <unistd.h>
57#include <syslog.h>
58#include <netdb.h>
59#include <stdio.h>
60#include <stdlib.h>
61#include <string.h>
62#include "pathnames.h"
63
64void err __P((const char *, ...));
65
66int
67main(argc, argv)
68	int argc;
69	char *argv[];
70{
71	register FILE *fp;
72	register int ch, ac = 2;
73	int p[2], logging, secure, user_required, short_list;
74	size_t linesiz;
75#define	ENTRIES	50
76	char **ap, *av[ENTRIES + 1], **comp, *line, *prog, *lp, *hname;
77	char hostbuf[MAXHOSTNAMELEN];
78
79	prog = _PATH_FINGER;
80	logging = secure = user_required = short_list = 0;
81	openlog("fingerd", LOG_PID, LOG_DAEMON);
82	opterr = 0;
83	while ((ch = getopt(argc, argv, "sluSmMpP:")) != -1)
84		switch (ch) {
85		case 'l':
86			logging = 1;
87			break;
88		case 'P':
89			prog = optarg;
90			break;
91		case 's':
92			secure = 1;
93			break;
94		case 'u':
95			user_required = 1;
96			break;
97		case 'S':
98			short_list = 1;
99			av[ac++] = "-s";
100			break;
101		case 'm':
102			av[ac++] = "-m";
103			break;
104		case 'M':
105			av[ac++] = "-M";
106			break;
107		case 'p':
108			av[ac++] = "-p";
109			break;
110		case '?':
111		default:
112			err("illegal option -- %c", ch);
113		}
114
115	if (logging) {
116		struct sockaddr_storage ss;
117		int sval;
118
119		sval = sizeof(ss);
120		if (getpeername(0, (struct sockaddr *)&ss, &sval) < 0)
121			err("getpeername: %s", strerror(errno));
122		(void)getnameinfo((struct sockaddr *)&ss, ss.ss_len,
123		    hostbuf, sizeof(hostbuf), NULL, 0, 0);
124		hname = hostbuf;
125	}
126
127	if ((lp = fgetln(stdin, &linesiz)) == NULL) {
128		if (logging)
129			syslog(LOG_NOTICE, "query from %s: %s", hname,
130			    feof(stdin) ? "EOF" : strerror(errno));
131		exit(1);
132	}
133	if ((line = malloc(linesiz + 1)) == NULL)
134		err("Out of memory");
135	memcpy(line, lp, linesiz);
136	line[linesiz] = '\0';
137
138	if (logging) {
139		char *tline;
140
141		if ((tline = strdup(line)) == NULL)
142			err("Out of memory");
143		/* Replace NULL, \r and \n with ' ' */
144		for (ch = 0; ch < linesiz; ch++) {
145			if (tline[ch] == '\0' || tline[ch] == '\r' ||
146			    tline[ch] == '\n')
147				tline[ch] = ' ';
148		}
149		for (lp = tline + linesiz - 1; lp >= tline && *lp == ' '; lp--)
150			*lp = '\0';
151		syslog(LOG_NOTICE, "query from %s: `%s'", hname, tline);
152		free(tline);
153	}
154
155	/*
156	 * Note: we assume that finger(1) will treat "--" as end of
157	 * command args (ie: that it uses getopt(3)).
158	 */
159	av[ac++] = "--";
160	comp = &av[1];
161	for (lp = line, ap = &av[ac]; ac < ENTRIES;) {
162		if ((*ap = strtok(lp, " \t\r\n")) == NULL)
163			break;
164		lp = NULL;
165		if (secure && strchr(*ap, '@')) {
166			(void) puts("forwarding service denied\r");
167			exit(1);
168		}
169
170		ch = strlen(*ap);
171		while ((*ap)[ch-1] == '@')
172			(*ap)[--ch] = '\0';
173		if (**ap == '\0')
174			continue;
175
176		/* RFC1196: "/[Ww]" == "-l" */
177		if ((*ap)[0] == '/' && ((*ap)[1] == 'W' || (*ap)[1] == 'w')) {
178			if (!short_list) {
179				av[1] = "-l";
180				comp = &av[0];
181			}
182		} else {
183			ap++;
184			ac++;
185		}
186	}
187	av[ENTRIES - 1] = NULL;
188
189	if ((lp = strrchr(prog, '/')))
190		*comp = ++lp;
191	else
192		*comp = prog;
193
194	if (user_required) {
195		for (ap = comp + 1; strcmp("--", *(ap++)); );
196		if (*ap == NULL) {
197			(void) puts("must provide username\r");
198			exit(1);
199		}
200	}
201
202	if (pipe(p) < 0)
203		err("pipe: %s", strerror(errno));
204
205	switch(vfork()) {
206	case 0:
207		(void) close(p[0]);
208		if (p[1] != 1) {
209			(void) dup2(p[1], 1);
210			(void) close(p[1]);
211		}
212		execv(prog, comp);
213		err("execv: %s: %s", prog, strerror(errno));
214		_exit(1);
215	case -1:
216		err("fork: %s", strerror(errno));
217	}
218	(void) close(p[1]);
219	if (!(fp = fdopen(p[0], "r")))
220		err("fdopen: %s", strerror(errno));
221	while ((ch = getc(fp)) != EOF) {
222		if (ch == '\n')
223			putchar('\r');
224		putchar(ch);
225	}
226	exit(0);
227}
228
229#ifdef __STDC__
230#include <stdarg.h>
231#else
232#include <varargs.h>
233#endif
234
235void
236#ifdef __STDC__
237err(const char *fmt, ...)
238#else
239err(fmt, va_alist)
240	char *fmt;
241	va_dcl
242#endif
243{
244	va_list ap;
245#ifdef __STDC__
246	va_start(ap, fmt);
247#else
248	va_start(ap);
249#endif
250	(void) vsyslog(LOG_ERR, fmt, ap);
251	va_end(ap);
252	exit(1);
253	/* NOTREACHED */
254}
255