Annotation of src/lib/libwrap/rfc931.c, Revision 1.8.56.2
1.8.56.2! riz 1: /* $NetBSD: rfc931.c,v 1.8.56.1 2012/04/23 16:48:56 riz Exp $ */
1.2 christos 2:
1.1 mrg 3: /*
4: * rfc931() speaks a common subset of the RFC 931, AUTH, TAP, IDENT and RFC
5: * 1413 protocols. It queries an RFC 931 etc. compatible daemon on a remote
6: * host to look up the owner of a connection. The information should not be
7: * used for authentication purposes. This routine intercepts alarm signals.
1.5 simonb 8: *
1.1 mrg 9: * Diagnostics are reported through syslog(3).
1.5 simonb 10: *
1.1 mrg 11: * Author: Wietse Venema, Eindhoven University of Technology, The Netherlands.
12: */
13:
1.2 christos 14: #include <sys/cdefs.h>
1.1 mrg 15: #ifndef lint
1.2 christos 16: #if 0
1.1 mrg 17: static char sccsid[] = "@(#) rfc931.c 1.10 95/01/02 16:11:34";
1.2 christos 18: #else
1.8.56.2! riz 19: __RCSID("$NetBSD: rfc931.c,v 1.8.56.1 2012/04/23 16:48:56 riz Exp $");
1.2 christos 20: #endif
1.1 mrg 21: #endif
22:
23: /* System libraries. */
24:
25: #include <stdio.h>
26: #include <syslog.h>
27: #include <sys/types.h>
28: #include <sys/socket.h>
29: #include <netinet/in.h>
1.2 christos 30: #include <stdlib.h>
31: #include <unistd.h>
1.1 mrg 32: #include <setjmp.h>
33: #include <signal.h>
34: #include <string.h>
35:
36: /* Local stuff. */
37:
38: #include "tcpd.h"
39:
40: #define RFC931_PORT 113 /* Semi-well-known port */
41: #define ANY_PORT 0 /* Any old port will do */
42:
43: int rfc931_timeout = RFC931_TIMEOUT;/* Global so it can be changed */
44:
45: static jmp_buf timebuf;
46:
1.8.56.2! riz 47: static FILE *fsocket __P((int, int, int));
! 48: static void timeout __P((int));
1.2 christos 49:
1.1 mrg 50: /* fsocket - open stdio stream on top of socket */
51:
1.8.56.2! riz 52: static FILE *fsocket(domain, type, protocol)
! 53: int domain;
! 54: int type;
! 55: int protocol;
1.1 mrg 56: {
57: int s;
58: FILE *fp;
59:
60: if ((s = socket(domain, type, protocol)) < 0) {
61: tcpd_warn("socket: %m");
62: return (0);
63: } else {
64: if ((fp = fdopen(s, "r+")) == 0) {
65: tcpd_warn("fdopen: %m");
66: close(s);
67: }
68: return (fp);
69: }
70: }
71:
72: /* timeout - handle timeouts */
73:
1.8.56.2! riz 74: static void timeout(sig)
! 75: int sig;
1.1 mrg 76: {
77: longjmp(timebuf, sig);
78: }
79:
80: /* rfc931 - return remote user name, given socket structures */
81:
1.8.56.2! riz 82: void rfc931(rmt_sin, our_sin, dest)
! 83: struct sockaddr *rmt_sin;
! 84: struct sockaddr *our_sin;
! 85: char *dest;
1.1 mrg 86: {
87: unsigned rmt_port;
88: unsigned our_port;
1.6 itojun 89: struct sockaddr_storage rmt_query_sin;
90: struct sockaddr_storage our_query_sin;
1.1 mrg 91: char user[256]; /* XXX */
92: char buffer[512]; /* XXX */
93: char *cp;
94: char *result = unknown;
95: FILE *fp;
1.8.56.2! riz 96: int salen;
! 97: u_short *rmt_portp;
! 98: u_short *our_portp;
1.6 itojun 99:
100: /* address family must be the same */
101: if (rmt_sin->sa_family != our_sin->sa_family) {
1.8 itojun 102: strlcpy(dest, result, STRING_LENGTH);
1.6 itojun 103: return;
104: }
105: switch (rmt_sin->sa_family) {
106: case AF_INET:
107: salen = sizeof(struct sockaddr_in);
1.7 itojun 108: rmt_portp = &(((struct sockaddr_in *)rmt_sin)->sin_port);
1.6 itojun 109: break;
110: #ifdef INET6
111: case AF_INET6:
112: salen = sizeof(struct sockaddr_in6);
1.7 itojun 113: rmt_portp = &(((struct sockaddr_in6 *)rmt_sin)->sin6_port);
1.6 itojun 114: break;
115: #endif
116: default:
1.8 itojun 117: strlcpy(dest, result, STRING_LENGTH);
1.6 itojun 118: return;
119: }
120: switch (our_sin->sa_family) {
121: case AF_INET:
1.7 itojun 122: our_portp = &(((struct sockaddr_in *)our_sin)->sin_port);
1.6 itojun 123: break;
124: #ifdef INET6
125: case AF_INET6:
1.7 itojun 126: our_portp = &(((struct sockaddr_in6 *)our_sin)->sin6_port);
1.6 itojun 127: break;
128: #endif
129: default:
1.8 itojun 130: strlcpy(dest, result, STRING_LENGTH);
1.6 itojun 131: return;
132: }
1.1 mrg 133:
1.2 christos 134: #ifdef __GNUC__
1.3 mrg 135: (void)&result; /* Avoid longjmp clobbering */
136: (void)&fp; /* XXX gcc */
1.2 christos 137: #endif
138:
1.1 mrg 139: /*
140: * Use one unbuffered stdio stream for writing to and for reading from
141: * the RFC931 etc. server. This is done because of a bug in the SunOS
142: * 4.1.x stdio library. The bug may live in other stdio implementations,
143: * too. When we use a single, buffered, bidirectional stdio stream ("r+"
144: * or "w+" mode) we read our own output. Such behaviour would make sense
145: * with resources that support random-access operations, but not with
146: * sockets.
147: */
148:
1.6 itojun 149: if ((fp = fsocket(rmt_sin->sa_family, SOCK_STREAM, 0)) != 0) {
1.1 mrg 150: setbuf(fp, (char *) 0);
151:
152: /*
153: * Set up a timer so we won't get stuck while waiting for the server.
154: */
155:
156: if (setjmp(timebuf) == 0) {
157: signal(SIGALRM, timeout);
158: alarm(rfc931_timeout);
159:
160: /*
161: * Bind the local and remote ends of the query socket to the same
162: * IP addresses as the connection under investigation. We go
163: * through all this trouble because the local or remote system
164: * might have more than one network address. The RFC931 etc.
165: * client sends only port numbers; the server takes the IP
166: * addresses from the query socket.
167: */
168:
1.6 itojun 169: memcpy(&our_query_sin, our_sin, salen);
170: switch (our_query_sin.ss_family) {
171: case AF_INET:
172: ((struct sockaddr_in *)&our_query_sin)->sin_port =
173: htons(ANY_PORT);
174: break;
175: #ifdef INET6
176: case AF_INET6:
177: ((struct sockaddr_in6 *)&our_query_sin)->sin6_port =
178: htons(ANY_PORT);
179: break;
180: #endif
181: }
182: memcpy(&rmt_query_sin, rmt_sin, salen);
183: switch (rmt_query_sin.ss_family) {
184: case AF_INET:
185: ((struct sockaddr_in *)&rmt_query_sin)->sin_port =
186: htons(RFC931_PORT);
187: break;
188: #ifdef INET6
189: case AF_INET6:
190: ((struct sockaddr_in6 *)&rmt_query_sin)->sin6_port =
191: htons(RFC931_PORT);
192: break;
193: #endif
194: }
1.1 mrg 195:
196: if (bind(fileno(fp), (struct sockaddr *) & our_query_sin,
1.6 itojun 197: salen) >= 0 &&
1.1 mrg 198: connect(fileno(fp), (struct sockaddr *) & rmt_query_sin,
1.6 itojun 199: salen) >= 0) {
1.1 mrg 200:
201: /*
202: * Send query to server. Neglect the risk that a 13-byte
203: * write would have to be fragmented by the local system and
204: * cause trouble with buggy System V stdio libraries.
205: */
206:
207: fprintf(fp, "%u,%u\r\n",
1.6 itojun 208: ntohs(*rmt_portp),
209: ntohs(*our_portp));
1.1 mrg 210: fflush(fp);
211:
212: /*
213: * Read response from server. Use fgets()/sscanf() so we can
214: * work around System V stdio libraries that incorrectly
215: * assume EOF when a read from a socket returns less than
216: * requested.
217: */
218:
219: if (fgets(buffer, sizeof(buffer), fp) != 0
220: && ferror(fp) == 0 && feof(fp) == 0
221: && sscanf(buffer, "%u , %u : USERID :%*[^:]:%255s",
222: &rmt_port, &our_port, user) == 3
1.6 itojun 223: && ntohs(*rmt_portp) == rmt_port
224: && ntohs(*our_portp) == our_port) {
1.1 mrg 225:
226: /*
227: * Strip trailing carriage return. It is part of the
228: * protocol, not part of the data.
229: */
230:
1.2 christos 231: if ((cp = strchr(user, '\r')) != NULL)
232: *cp = '\0';
1.1 mrg 233: result = user;
234: }
235: }
236: alarm(0);
237: }
238: fclose(fp);
239: }
1.8 itojun 240: strlcpy(dest, result, STRING_LENGTH);
1.1 mrg 241: }
CVSweb <webmaster@jp.NetBSD.org>