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