xref: /openbsd-src/libexec/fingerd/fingerd.c (revision bc5a8259a456844c67e446bf6bd66575acc64837)
1*bc5a8259Sbeck /*	$OpenBSD: fingerd.c,v 1.42 2021/07/12 15:09:18 beck Exp $	*/
2b1b7b0f7Smillert 
3df930be7Sderaadt /*
4adb66708Smillert  * Copyright (c) 1983, 1993
5adb66708Smillert  *	The Regents of the University of California.  All rights reserved.
6df930be7Sderaadt  *
7df930be7Sderaadt  * Redistribution and use in source and binary forms, with or without
8df930be7Sderaadt  * modification, are permitted provided that the following conditions
9df930be7Sderaadt  * are met:
10df930be7Sderaadt  * 1. Redistributions of source code must retain the above copyright
11df930be7Sderaadt  *    notice, this list of conditions and the following disclaimer.
12df930be7Sderaadt  * 2. Redistributions in binary form must reproduce the above copyright
13df930be7Sderaadt  *    notice, this list of conditions and the following disclaimer in the
14df930be7Sderaadt  *    documentation and/or other materials provided with the distribution.
15e33d3bd3Smillert  * 3. Neither the name of the University nor the names of its contributors
16df930be7Sderaadt  *    may be used to endorse or promote products derived from this software
17df930be7Sderaadt  *    without specific prior written permission.
18df930be7Sderaadt  *
19df930be7Sderaadt  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
20df930be7Sderaadt  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21df930be7Sderaadt  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22df930be7Sderaadt  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
23df930be7Sderaadt  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24df930be7Sderaadt  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25df930be7Sderaadt  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26df930be7Sderaadt  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27df930be7Sderaadt  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28df930be7Sderaadt  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29df930be7Sderaadt  * SUCH DAMAGE.
30df930be7Sderaadt  */
31df930be7Sderaadt 
32adb66708Smillert #include <sys/socket.h>
33adb66708Smillert #include <netinet/in.h>
34adb66708Smillert #include <arpa/inet.h>
35adb66708Smillert #include <errno.h>
36adb66708Smillert 
37d4f5291bSray #include <err.h>
38adb66708Smillert #include <unistd.h>
39adb66708Smillert #include <syslog.h>
40adb66708Smillert #include <netdb.h>
41df930be7Sderaadt #include <stdio.h>
42adb66708Smillert #include <stdlib.h>
43328a01feSmillert #include <string.h>
44e7beb4a7Smillert #include <stdarg.h>
45b9fc9a72Sderaadt #include <limits.h>
46df930be7Sderaadt #include "pathnames.h"
47df930be7Sderaadt 
48d4f5291bSray __dead void logerr(const char *, ...);
49d4f5291bSray __dead void usage(void);
5089cdc6afSderaadt 
5189cdc6afSderaadt void
usage(void)525b48e80aSderaadt usage(void)
5389cdc6afSderaadt {
5489cdc6afSderaadt 	syslog(LOG_ERR,
552332387dSjmc 	    "usage: fingerd [-lMmpSsu] [-P filename]");
5689cdc6afSderaadt 	exit(2);
5789cdc6afSderaadt }
5889cdc6afSderaadt 
59adb66708Smillert 
601f9ae09cSderaadt int
main(int argc,char * argv[])615b48e80aSderaadt main(int argc, char *argv[])
62df930be7Sderaadt {
6350d2b651Smpech 	FILE *fp;
6450d2b651Smpech 	int ch, ac = 2;
6509acb487Smillert 	int p[2], logging, secure, user_required, short_list;
66adb66708Smillert #define	ENTRIES	50
67a5553e71Sderaadt 	char **comp, *prog;
68a5553e71Sderaadt 	char **ap, *av[ENTRIES + 1], line[8192], *lp, *hname;
69b9fc9a72Sderaadt 	char hostbuf[HOST_NAME_MAX+1];
70df930be7Sderaadt 
71adb66708Smillert 	prog = _PATH_FINGER;
72adb66708Smillert 	logging = secure = user_required = short_list = 0;
73cd70c027Sgene 	openlog("fingerd", LOG_PID, LOG_DAEMON);
74adb66708Smillert 	opterr = 0;
7572799b18Smillert 	while ((ch = getopt(argc, argv, "sluSmMpP:")) != -1)
76adb66708Smillert 		switch (ch) {
77adb66708Smillert 		case 'l':
78adb66708Smillert 			logging = 1;
79adb66708Smillert 			break;
80adb66708Smillert 		case 'P':
81adb66708Smillert 			prog = optarg;
82adb66708Smillert 			break;
83adb66708Smillert 		case 's':
84adb66708Smillert 			secure = 1;
85adb66708Smillert 			break;
86adb66708Smillert 		case 'u':
87adb66708Smillert 			user_required = 1;
88adb66708Smillert 			break;
89adb66708Smillert 		case 'S':
901ba530f7Smillert 			if (ac < ENTRIES) {
91adb66708Smillert 				short_list = 1;
92adb66708Smillert 				av[ac++] = "-s";
931ba530f7Smillert 			}
94adb66708Smillert 			break;
95adb66708Smillert 		case 'm':
961ba530f7Smillert 			if (ac < ENTRIES)
97adb66708Smillert 				av[ac++] = "-m";
98adb66708Smillert 			break;
99b4e415d7Sdownsj 		case 'M':
1001ba530f7Smillert 			if (ac < ENTRIES)
101b4e415d7Sdownsj 				av[ac++] = "-M";
102b4e415d7Sdownsj 			break;
103adb66708Smillert 		case 'p':
1041ba530f7Smillert 			if (ac < ENTRIES)
105adb66708Smillert 				av[ac++] = "-p";
106adb66708Smillert 			break;
107adb66708Smillert 		default:
10889cdc6afSderaadt 			usage();
109adb66708Smillert 		}
110adb66708Smillert 
11119a58c97Sderaadt 	if (unveil(prog, "x") == -1)
112*bc5a8259Sbeck 		err(1, "unveil %s", prog);
11319a58c97Sderaadt 	if (pledge("stdio inet dns proc exec", NULL) == -1)
11419a58c97Sderaadt 		err(1, "pledge");
11519a58c97Sderaadt 
116adb66708Smillert 	if (logging) {
1170c21f367Sderaadt 		struct sockaddr_storage ss;
11864453b2aSitojun 		struct sockaddr *sa;
11971fc4cb2Sderaadt 		socklen_t sval;
12009acb487Smillert 
1210c21f367Sderaadt 		sval = sizeof(ss);
122df69c215Sderaadt 		if (getpeername(0, (struct sockaddr *)&ss, &sval) == -1)
123d4f5291bSray 			err(1, "getpeername");
12464453b2aSitojun 		sa = (struct sockaddr *)&ss;
1256fc5b115Sderaadt 
1266fc5b115Sderaadt 		if (pledge("stdio dns proc exec", NULL) == -1)
1276fc5b115Sderaadt 			err(1, "pledge");
1286fc5b115Sderaadt 
12964453b2aSitojun 		if (getnameinfo(sa, sa->sa_len, hostbuf, sizeof(hostbuf),
13064453b2aSitojun 		    NULL, 0, 0) != 0) {
131a79f1fdfSderaadt 			strlcpy(hostbuf, "?", sizeof(hostbuf));
13264453b2aSitojun 		}
1330c21f367Sderaadt 		hname = hostbuf;
134adb66708Smillert 	}
1351f9ae09cSderaadt 
1366fc5b115Sderaadt 	if (pledge("stdio proc exec", NULL) == -1)
1376fc5b115Sderaadt 		err(1, "pledge");
1386fc5b115Sderaadt 
139ba879273Smillert 	if (fgets(line, sizeof(line), stdin) == NULL) {
14009acb487Smillert 		if (logging)
14109acb487Smillert 			syslog(LOG_NOTICE, "query from %s: %s", hname,
14209acb487Smillert 			    feof(stdin) ? "EOF" : strerror(errno));
143df930be7Sderaadt 		exit(1);
14409acb487Smillert 	}
14509acb487Smillert 
146ba879273Smillert 	if (logging)
147ba879273Smillert 		syslog(LOG_NOTICE, "query from %s: `%.*s'", hname,
1483d264fe4Sderaadt 		    (int)strcspn(line, "\r\n"), line);
149df930be7Sderaadt 
150b1b7b0f7Smillert 	/*
151b1b7b0f7Smillert 	 * Note: we assume that finger(1) will treat "--" as end of
152b1b7b0f7Smillert 	 * command args (ie: that it uses getopt(3)).
153b1b7b0f7Smillert 	 */
154adb66708Smillert 	av[ac++] = "--";
155adb66708Smillert 	comp = &av[1];
156adb66708Smillert 	for (lp = line, ap = &av[ac]; ac < ENTRIES;) {
157d4f5291bSray 		size_t len;
158d4f5291bSray 
159adb66708Smillert 		if ((*ap = strtok(lp, " \t\r\n")) == NULL)
160df930be7Sderaadt 			break;
161df930be7Sderaadt 		lp = NULL;
162adb66708Smillert 		if (secure && strchr(*ap, '@')) {
1637c475801Saaron 			(void) puts("forwarding service denied\r");
164adb66708Smillert 			exit(1);
165df930be7Sderaadt 		}
166df930be7Sderaadt 
167d4f5291bSray 		len = strlen(*ap);
168aecf04b9Stobias 		while (len > 0 && (*ap)[len - 1] == '@')
169d4f5291bSray 			(*ap)[--len] = '\0';
170adb66708Smillert 		if (**ap == '\0')
1711f9ae09cSderaadt 			continue;
172c549fc11Sderaadt 
173adb66708Smillert 		/* RFC1196: "/[Ww]" == "-l" */
174adb66708Smillert 		if ((*ap)[0] == '/' && ((*ap)[1] == 'W' || (*ap)[1] == 'w')) {
175adb66708Smillert 			if (!short_list) {
176adb66708Smillert 				av[1] = "-l";
177adb66708Smillert 				comp = &av[0];
178adb66708Smillert 			}
179adb66708Smillert 		} else {
180adb66708Smillert 			ap++;
181adb66708Smillert 			ac++;
182adb66708Smillert 		}
183adb66708Smillert 	}
184adb66708Smillert 	av[ENTRIES - 1] = NULL;
185adb66708Smillert 
186adb66708Smillert 	if ((lp = strrchr(prog, '/')))
187adb66708Smillert 		*comp = ++lp;
188adb66708Smillert 	else
189adb66708Smillert 		*comp = prog;
190adb66708Smillert 
191adb66708Smillert 	if (user_required) {
192a5553e71Sderaadt 		for (ap = comp + 1; strcmp("--", *(ap++)); )
193a5553e71Sderaadt 			;
194adb66708Smillert 		if (*ap == NULL) {
19509acb487Smillert 			(void) puts("must provide username\r");
196adb66708Smillert 			exit(1);
197adb66708Smillert 		}
198c549fc11Sderaadt 	}
199c549fc11Sderaadt 
200df69c215Sderaadt 	if (pipe(p) == -1)
201d4f5291bSray 		logerr("pipe: %s", strerror(errno));
202df930be7Sderaadt 
203adb66708Smillert 	switch (vfork()) {
204df930be7Sderaadt 	case 0:
205df930be7Sderaadt 		(void) close(p[0]);
206df930be7Sderaadt 		if (p[1] != 1) {
207df930be7Sderaadt 			(void) dup2(p[1], 1);
208df930be7Sderaadt 			(void) close(p[1]);
209df930be7Sderaadt 		}
210adb66708Smillert 		execv(prog, comp);
211592468f0Sderaadt 		syslog(LOG_ERR, "execv: %s: %s", prog, strerror(errno));
212592468f0Sderaadt 		_exit(1);
213df930be7Sderaadt 	case -1:
214d4f5291bSray 		logerr("fork: %s", strerror(errno));
215df930be7Sderaadt 	}
2166fc5b115Sderaadt 	if (pledge("stdio", NULL) == -1)
2176fc5b115Sderaadt 		err(1, "pledge");
2186fc5b115Sderaadt 
219df930be7Sderaadt 	(void) close(p[1]);
220df930be7Sderaadt 	if (!(fp = fdopen(p[0], "r")))
221d4f5291bSray 		logerr("fdopen: %s", strerror(errno));
222df930be7Sderaadt 	while ((ch = getc(fp)) != EOF) {
223df930be7Sderaadt 		if (ch == '\n')
224df930be7Sderaadt 			putchar('\r');
225df930be7Sderaadt 		putchar(ch);
226df930be7Sderaadt 	}
227df930be7Sderaadt 	exit(0);
228df930be7Sderaadt }
229df930be7Sderaadt 
230adb66708Smillert void
logerr(const char * fmt,...)231d4f5291bSray logerr(const char *fmt, ...)
232adb66708Smillert {
233adb66708Smillert 	va_list ap;
234e7beb4a7Smillert 
235adb66708Smillert 	va_start(ap, fmt);
236adb66708Smillert 	(void) vsyslog(LOG_ERR, fmt, ap);
237adb66708Smillert 	va_end(ap);
238df930be7Sderaadt 	exit(1);
239df930be7Sderaadt }
240