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