home *** CD-ROM | disk | FTP | other *** search
/ Il CD di internet / CD.iso / SOURCE / N / TCPIP / NETKIT-A.06 / NETKIT-A / NetKit-A-0.06 / tcp_wrapper-6.3 / rfc931.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-03-27  |  4.6 KB  |  183 lines

  1.  /*
  2.   * rfc931() speaks a common subset of the RFC 931, AUTH, TAP and IDENT
  3.   * protocols. The code queries an RFC 931 etc. compatible daemon on a remote
  4.   * host to look up the owner of a connection. The information should not be
  5.   * used for authentication purposes. This routine intercepts alarm signals.
  6.   * 
  7.   * Diagnostics are reported through syslog(3).
  8.   * 
  9.   * Author: Wietse Venema, Eindhoven University of Technology, The Netherlands.
  10.   */
  11.  
  12. #ifndef lint
  13. static char sccsid[] = "@(#) rfc931.c 1.8 93/12/13 22:23:20";
  14. #endif
  15.  
  16. /* System libraries. */
  17.  
  18. #include <stdio.h>
  19. #include <syslog.h>
  20. #include <sys/types.h>
  21. #include <sys/socket.h>
  22. #include <netinet/in.h>
  23. #include <setjmp.h>
  24. #include <signal.h>
  25.  
  26. extern char *strchr();
  27. extern char *inet_ntoa();
  28.  
  29. /* Local stuff. */
  30.  
  31. #include "log_tcp.h"
  32.  
  33. #define    RFC931_PORT    113        /* Semi-well-known port */
  34. #define    ANY_PORT    0        /* Any old port will do */
  35.  
  36. int     rfc931_timeout = RFC931_TIMEOUT;/* Global so it can be changed */
  37.  
  38. static jmp_buf timebuf;
  39.  
  40. /* fsocket - open stdio stream on top of socket */
  41.  
  42. static FILE *fsocket(domain, type, protocol)
  43. int     domain;
  44. int     type;
  45. int     protocol;
  46. {
  47.     int     s;
  48.     FILE   *fp;
  49.  
  50.     if ((s = socket(domain, type, protocol)) < 0) {
  51.     syslog(LOG_ERR, "socket: %m");
  52.     return (0);
  53.     } else {
  54.     if ((fp = fdopen(s, "r+")) == 0) {
  55.         syslog(LOG_ERR, "fdopen: %m");
  56.         close(s);
  57.     }
  58.     return (fp);
  59.     }
  60. }
  61.  
  62. /* bind_connect - bind both ends of a socket */
  63.  
  64. int     bind_connect(s, local, remote, length)
  65. int     s;
  66. struct sockaddr *local;
  67. struct sockaddr *remote;
  68. int     length;
  69. {
  70.     if (bind(s, local, length) < 0) {
  71.     syslog(LOG_ERR, "bind: %m");
  72.     return (-1);
  73.     } else {
  74.     return (connect(s, remote, length));
  75.     }
  76. }
  77.  
  78. /* timeout - handle timeouts */
  79.  
  80. static void timeout(sig)
  81. int     sig;
  82. {
  83.     longjmp(timebuf, sig);
  84. }
  85.  
  86. /* rfc931 - return remote user name, given socket structures */
  87.  
  88. char   *rfc931(rmt_sin, our_sin)
  89. struct sockaddr_in *rmt_sin;
  90. struct sockaddr_in *our_sin;
  91. {
  92.     unsigned rmt_port;
  93.     unsigned our_port;
  94.     struct sockaddr_in rmt_query_sin;
  95.     struct sockaddr_in our_query_sin;
  96.     static char user[256];        /* XXX */
  97.     char    buffer[512];        /* XXX */
  98.     char   *cp;
  99.     char   *result = FROM_UNKNOWN;    /* XXX */
  100.     FILE   *fp;
  101.  
  102.     /*
  103.      * Use one unbuffered stdio stream for writing to and for reading from
  104.      * the RFC931 etc. server. This is done because of a bug in the SunOS
  105.      * 4.1.x stdio library. The bug may live in other stdio implementations,
  106.      * too. When we use a single, buffered, bidirectional stdio stream ("r+"
  107.      * or "w+" mode) we read our own output. Such behaviour would make sense
  108.      * with resources that support random-access operations, but not with
  109.      * sockets.
  110.      */
  111.  
  112.     if ((fp = fsocket(AF_INET, SOCK_STREAM, 0)) != 0) {
  113.     setbuf(fp, (char *) 0);
  114.  
  115.     /*
  116.      * Set up a timer so we won't get stuck while waiting for the server.
  117.      */
  118.  
  119.     if (setjmp(timebuf) == 0) {
  120.         signal(SIGALRM, timeout);
  121.         alarm(rfc931_timeout);
  122.  
  123.         /*
  124.          * Bind the local and remote ends of the query socket to the same
  125.          * IP addresses as the connection under investigation. We go
  126.          * through all this trouble because the local or remote system
  127.          * might have more than one network address. The RFC931 etc.
  128.          * client sends only port numbers; the server takes the IP
  129.          * addresses from the query socket.
  130.          */
  131.  
  132.         our_query_sin = *our_sin;
  133.         our_query_sin.sin_port = htons(ANY_PORT);
  134.         rmt_query_sin = *rmt_sin;
  135.         rmt_query_sin.sin_port = htons(RFC931_PORT);
  136.  
  137.         if (bind_connect(fileno(fp),
  138.                  (struct sockaddr *) & our_query_sin,
  139.                  (struct sockaddr *) & rmt_query_sin,
  140.                  sizeof(our_query_sin)) >= 0) {
  141.  
  142.         /*
  143.          * Send query to server. Neglect the risk that a 13-byte
  144.          * write would have to be fragmented by the local system and
  145.          * cause trouble with buggy System V stdio libraries.
  146.          */
  147.  
  148.         fprintf(fp, "%u,%u\r\n",
  149.             ntohs(rmt_sin->sin_port),
  150.             ntohs(our_sin->sin_port));
  151.         fflush(fp);
  152.  
  153.         /*
  154.          * Read response from server. Use fgets()/sscanf() so we can
  155.          * work around System V stdio libraries that incorrectly
  156.          * assume EOF when a read from a socket returns less than
  157.          * requested.
  158.          */
  159.  
  160.         if (fgets(buffer, sizeof(buffer), fp) != 0
  161.             && ferror(fp) == 0 && feof(fp) == 0
  162.             && sscanf(buffer, "%u , %u : USERID :%*[^:]:%255s",
  163.                   &rmt_port, &our_port, user) == 3
  164.             && ntohs(rmt_sin->sin_port) == rmt_port
  165.             && ntohs(our_sin->sin_port) == our_port) {
  166.  
  167.             /*
  168.              * Strip trailing carriage return. It is part of the
  169.              * protocol, not part of the data.
  170.              */
  171.  
  172.             if (cp = strchr(user, '\r'))
  173.             *cp = 0;
  174.             result = user;
  175.         }
  176.         }
  177.         alarm(0);
  178.     }
  179.     fclose(fp);
  180.     }
  181.     return (result);
  182. }
  183.