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