1 /* $NetBSD: fingerd.c,v 1.15 2002/05/26 00:02:06 wiz 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 #include <sys/cdefs.h> 37 #ifndef lint 38 __COPYRIGHT( 39 "@(#) Copyright (c) 1983, 1993\n\ 40 The Regents of the University of California. All rights reserved.\n"); 41 #endif /* not lint */ 42 43 #ifndef lint 44 #if 0 45 static char sccsid[] = "from: @(#)fingerd.c 8.1 (Berkeley) 6/4/93"; 46 #else 47 __RCSID("$NetBSD: fingerd.c,v 1.15 2002/05/26 00:02:06 wiz Exp $"); 48 #endif 49 #endif /* not lint */ 50 51 #include <sys/param.h> 52 #include <sys/socket.h> 53 #include <netinet/in.h> 54 #include <arpa/inet.h> 55 #include <errno.h> 56 57 #include <unistd.h> 58 #include <syslog.h> 59 #include <netdb.h> 60 #include <stdarg.h> 61 #include <stdio.h> 62 #include <stdlib.h> 63 #include <string.h> 64 #include "pathnames.h" 65 66 void err __P((const char *, ...)); 67 int main __P((int, char *[])); 68 69 int 70 main(argc, argv) 71 int argc; 72 char *argv[]; 73 { 74 register FILE *fp; 75 register int ch, ac = 2; 76 register char *lp = NULL /* XXX gcc */; 77 struct sockaddr_storage ss; 78 int p[2], logging, no_forward, user_required, short_list, sval; 79 #define ENTRIES 50 80 char **ap, *av[ENTRIES + 1], **comp, line[1024], *prog, *s; 81 char hostbuf[MAXHOSTNAMELEN]; 82 83 prog = _PATH_FINGER; 84 logging = no_forward = user_required = short_list = 0; 85 openlog("fingerd", LOG_PID, LOG_DAEMON); 86 opterr = 0; 87 while ((ch = getopt(argc, argv, "gsluShmpP:")) != -1) 88 switch (ch) { 89 case 'l': 90 logging = 1; 91 break; 92 case 'P': 93 prog = optarg; 94 break; 95 case 's': 96 no_forward = 1; 97 break; 98 case 'u': 99 user_required = 1; 100 break; 101 case 'S': 102 short_list = 1; 103 av[ac++] = "-s"; 104 break; 105 case 'h': 106 av[ac++] = "-h"; 107 break; 108 case 'm': 109 av[ac++] = "-m"; 110 break; 111 case 'p': 112 av[ac++] = "-p"; 113 break; 114 case 'g': 115 av[ac++] = "-g"; 116 break; 117 case '?': 118 default: 119 err("illegal option -- %c", ch); 120 } 121 122 123 if (logging) { 124 sval = sizeof(ss); 125 if (getpeername(0, (struct sockaddr *)&ss, &sval) < 0) 126 err("getpeername: %s", strerror(errno)); 127 (void)getnameinfo((struct sockaddr *)&ss, sval, 128 hostbuf, sizeof(hostbuf), NULL, 0, 0); 129 lp = hostbuf; 130 } 131 132 if (!fgets(line, sizeof(line), stdin)) { 133 if (logging) 134 syslog(LOG_NOTICE, "query from %s", lp); 135 exit(1); 136 } 137 while ((s = strrchr(line, '\n')) != NULL || 138 (s = strrchr(line, '\r')) != NULL) 139 *s = '\0'; 140 141 if (logging) { 142 if (*line == '\0') 143 syslog(LOG_NOTICE, "query from %s", lp); 144 else 145 syslog(LOG_NOTICE, "query from %s: %s", lp, line); 146 } 147 148 av[ac++] = "--"; 149 comp = &av[1]; 150 for (lp = line, ap = &av[ac]; ac < ENTRIES;) { 151 if ((*ap = strtok(lp, " \t\r\n")) == NULL) 152 break; 153 lp = NULL; 154 if (no_forward && strchr(*ap, '@')) { 155 (void) puts("fowarding service denied\r\n"); 156 exit(1); 157 } 158 159 ch = strlen(*ap); 160 while ((*ap)[ch-1] == '@') 161 (*ap)[--ch] = '\0'; 162 if (**ap == '\0') 163 continue; 164 165 /* RFC1196: "/[Ww]" == "-l" */ 166 if ((*ap)[0] == '/' && ((*ap)[1] == 'W' || (*ap)[1] == 'w')) { 167 if (!short_list) { 168 av[1] = "-l"; 169 comp = &av[0]; 170 } 171 } else { 172 ap++; 173 ac++; 174 } 175 } 176 av[ENTRIES - 1] = NULL; 177 178 if ((lp = strrchr(prog, '/'))) 179 *comp = ++lp; 180 else 181 *comp = prog; 182 183 if (user_required) { 184 for (ap = comp + 1; strcmp("--", *(ap++)); ); 185 if (*ap == NULL) { 186 (void) puts("must provide username\r\n"); 187 exit(1); 188 } 189 } 190 191 if (pipe(p) < 0) 192 err("pipe: %s", strerror(errno)); 193 194 switch(fork()) { 195 case 0: 196 (void) close(p[0]); 197 if (p[1] != 1) { 198 (void) dup2(p[1], 1); 199 (void) close(p[1]); 200 } 201 execv(prog, comp); 202 err("execv: %s: %s", prog, strerror(errno)); 203 _exit(1); 204 case -1: 205 err("fork: %s", strerror(errno)); 206 } 207 (void) close(p[1]); 208 if (!(fp = fdopen(p[0], "r"))) 209 err("fdopen: %s", strerror(errno)); 210 while ((ch = getc(fp)) != EOF) { 211 if (ch == '\n') 212 putchar('\r'); 213 putchar(ch); 214 } 215 exit(0); 216 } 217 218 void 219 err(const char *fmt, ...) 220 { 221 va_list ap; 222 223 va_start(ap, fmt); 224 (void) vsyslog(LOG_ERR, fmt, ap); 225 va_end(ap); 226 exit(1); 227 /* NOTREACHED */ 228 } 229