Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/libexec/fingerd/fingerd.c
34823 views
1
/*-
2
* SPDX-License-Identifier: BSD-3-Clause
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. Neither the name of the University nor the names of its contributors
16
* may be used to endorse or promote products derived from this software
17
* without specific prior written permission.
18
*
19
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
20
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
23
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29
* SUCH DAMAGE.
30
*/
31
32
#include <sys/types.h>
33
#include <sys/param.h>
34
#include <sys/socket.h>
35
#include <netinet/in.h>
36
#include <netinet/tcp.h>
37
#include <arpa/inet.h>
38
#include <errno.h>
39
40
#include <unistd.h>
41
#include <syslog.h>
42
#include <libutil.h>
43
#include <netdb.h>
44
#include <stdio.h>
45
#include <stdlib.h>
46
#include <string.h>
47
#include "pathnames.h"
48
#ifdef USE_BLACKLIST
49
#include <blacklist.h>
50
#endif
51
52
void logerr(const char *, ...) __printflike(1, 2) __dead2;
53
54
int
55
main(int argc, char *argv[])
56
{
57
FILE *fp;
58
int ch;
59
char *lp;
60
struct sockaddr_storage ss;
61
socklen_t sval;
62
int p[2], debug, kflag, logging, pflag, secure;
63
#define ENTRIES 50
64
char **ap, *av[ENTRIES + 1], **comp, line[1024], *prog;
65
char rhost[MAXHOSTNAMELEN];
66
67
prog = _PATH_FINGER;
68
debug = logging = kflag = pflag = secure = 0;
69
openlog("fingerd", LOG_PID | LOG_CONS, LOG_DAEMON);
70
opterr = 0;
71
while ((ch = getopt(argc, argv, "dklp:s")) != -1)
72
switch (ch) {
73
case 'd':
74
debug = 1;
75
break;
76
case 'k':
77
kflag = 1;
78
break;
79
case 'l':
80
logging = 1;
81
break;
82
case 'p':
83
prog = optarg;
84
pflag = 1;
85
break;
86
case 's':
87
secure = 1;
88
break;
89
case '?':
90
default:
91
logerr("illegal option -- %c", optopt);
92
}
93
94
/*
95
* Enable server-side Transaction TCP.
96
*/
97
if (!debug) {
98
int one = 1;
99
if (setsockopt(STDOUT_FILENO, IPPROTO_TCP, TCP_NOPUSH, &one,
100
sizeof one) < 0) {
101
logerr("setsockopt(TCP_NOPUSH) failed: %m");
102
}
103
}
104
105
if (!fgets(line, sizeof(line), stdin))
106
exit(1);
107
108
if (!debug && (logging || pflag)) {
109
sval = sizeof(ss);
110
if (getpeername(0, (struct sockaddr *)&ss, &sval) < 0)
111
logerr("getpeername: %s", strerror(errno));
112
realhostname_sa(rhost, sizeof rhost - 1,
113
(struct sockaddr *)&ss, sval);
114
rhost[sizeof(rhost) - 1] = '\0';
115
if (pflag)
116
setenv("FINGERD_REMOTE_HOST", rhost, 1);
117
}
118
119
if (logging) {
120
char *t;
121
char *end;
122
123
end = memchr(line, 0, sizeof(line));
124
if (end == NULL) {
125
if ((t = malloc(sizeof(line) + 1)) == NULL)
126
logerr("malloc: %s", strerror(errno));
127
memcpy(t, line, sizeof(line));
128
t[sizeof(line)] = 0;
129
} else {
130
if ((t = strdup(line)) == NULL)
131
logerr("strdup: %s", strerror(errno));
132
}
133
for (end = t; *end; end++)
134
if (*end == '\n' || *end == '\r')
135
*end = ' ';
136
syslog(LOG_NOTICE, "query from %s: `%s'", rhost, t);
137
}
138
139
comp = &av[2];
140
av[3] = "--";
141
if (kflag)
142
*comp-- = "-k";
143
for (lp = line, ap = &av[4];;) {
144
*ap = strtok(lp, " \t\r\n");
145
if (!*ap) {
146
if (secure && ap == &av[4]) {
147
#ifdef USE_BLACKLIST
148
blacklist(1, STDIN_FILENO, "nousername");
149
#endif
150
puts("must provide username\r\n");
151
exit(1);
152
}
153
break;
154
}
155
if (secure && strchr(*ap, '@')) {
156
#ifdef USE_BLACKLIST
157
blacklist(1, STDIN_FILENO, "noforwarding");
158
#endif
159
puts("forwarding service denied\r\n");
160
exit(1);
161
}
162
163
/* RFC742: "/[Ww]" == "-l" */
164
if ((*ap)[0] == '/' && ((*ap)[1] == 'W' || (*ap)[1] == 'w')) {
165
*comp-- = "-l";
166
}
167
else if (++ap == av + ENTRIES) {
168
*ap = NULL;
169
break;
170
}
171
lp = NULL;
172
}
173
174
if ((lp = strrchr(prog, '/')) != NULL)
175
*comp = ++lp;
176
else
177
*comp = prog;
178
if (pipe(p) < 0)
179
logerr("pipe: %s", strerror(errno));
180
181
if (debug) {
182
fprintf(stderr, "%s", prog);
183
for (ap = comp; *ap != NULL; ++ap)
184
fprintf(stderr, " %s", *ap);
185
fprintf(stderr, "\n");
186
}
187
188
switch(vfork()) {
189
case 0:
190
(void)close(p[0]);
191
if (p[1] != STDOUT_FILENO) {
192
(void)dup2(p[1], STDOUT_FILENO);
193
(void)close(p[1]);
194
}
195
dup2(STDOUT_FILENO, STDERR_FILENO);
196
197
#ifdef USE_BLACKLIST
198
blacklist(0, STDIN_FILENO, "success");
199
#endif
200
execv(prog, comp);
201
write(STDERR_FILENO, prog, strlen(prog));
202
#define MSG ": cannot execute\n"
203
write(STDERR_FILENO, MSG, strlen(MSG));
204
#undef MSG
205
_exit(1);
206
case -1:
207
logerr("fork: %s", strerror(errno));
208
}
209
(void)close(p[1]);
210
if (!(fp = fdopen(p[0], "r")))
211
logerr("fdopen: %s", strerror(errno));
212
while ((ch = getc(fp)) != EOF) {
213
if (ch == '\n')
214
putchar('\r');
215
putchar(ch);
216
}
217
exit(0);
218
}
219
220
#include <stdarg.h>
221
222
void
223
logerr(const char *fmt, ...)
224
{
225
va_list ap;
226
va_start(ap, fmt);
227
(void)vsyslog(LOG_ERR, fmt, ap);
228
va_end(ap);
229
exit(1);
230
/* NOTREACHED */
231
}
232
233