[BACK]Return to rfc931.c CVS log [TXT][DIR] Up to [cvs.NetBSD.org] / src / lib / libwrap

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>