home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 October / usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso / misc / volume36 / log_tcp / part02 / rfc931.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-03-07  |  3.7 KB  |  144 lines

  1.  /*
  2.   * rfc931_user() speaks a common subset of the RFC 931, AUTH, TAP and IDENT
  3.   * protocols. It consults an RFC 931 etc. compatible daemon on the client
  4.   * host to look up the remote user name. The information should not be used
  5.   * for authentication purposes.
  6.   * 
  7.   * Diagnostics are reported through syslog(3).
  8.   * 
  9.   * Author: Wietse Venema, Eindhoven University of Technology, The Netherlands.
  10.   * 
  11.   * Inspired by the authutil package (comp.sources.unix volume 22) by Dan
  12.   * Bernstein (brnstnd@kramden.acf.nyu.edu).
  13.   */
  14.  
  15. #ifndef lint
  16. static char sccsid[] = "@(#) rfc931.c 1.4 93/03/07 22:47:52";
  17. #endif
  18.  
  19. #include <stdio.h>
  20. #include <syslog.h>
  21. #include <sys/types.h>
  22. #include <sys/socket.h>
  23. #include <netinet/in.h>
  24. #include <setjmp.h>
  25. #include <signal.h>
  26.  
  27. #include "log_tcp.h"
  28.  
  29. #define    RFC931_PORT    113        /* Semi-well-known port */
  30.  
  31. #ifndef RFC931_TIMEOUT
  32. #define    RFC931_TIMEOUT    30        /* wait for at most 30 seconds */
  33. #endif
  34.  
  35. extern char *strchr();
  36. extern char *inet_ntoa();
  37.  
  38. static jmp_buf timebuf;
  39.  
  40. /* timeout - handle timeouts */
  41.  
  42. static void timeout(sig)
  43. int     sig;
  44. {
  45.     longjmp(timebuf, sig);
  46. }
  47.  
  48. /* rfc931_name - return remote user name */
  49.  
  50. char   *rfc931_name(there)
  51. struct sockaddr_in *there;        /* remote link information */
  52. {
  53.     struct sockaddr_in here;        /* local link information */
  54.     struct sockaddr_in sin;        /* for talking to RFC931 daemon */
  55.     int     length;
  56.     int     s;
  57.     unsigned remote;
  58.     unsigned local;
  59.     static char user[256];        /* XXX */
  60.     char    buffer[512];        /* YYY */
  61.     FILE   *fp;
  62.     char   *cp;
  63.     char   *result = FROM_UNKNOWN;
  64.  
  65.     /* Find out local address and port number of stdin. */
  66.  
  67.     length = sizeof(here);
  68.     if (getsockname(0, (struct sockaddr *) & here, &length) == -1) {
  69.     syslog(LOG_ERR, "getsockname: %m");
  70.     return (result);
  71.     }
  72.  
  73.     /*
  74.      * The socket that will be used for user name lookups should be bound to
  75.      * the same local IP address as stdin. This will automagically happen on
  76.      * hosts that have only one IP network address. When the local host has
  77.      * more than one IP network address, we must do an explicit bind() call.
  78.      */
  79.  
  80.     if ((s = socket(AF_INET, SOCK_STREAM, 0)) == -1)
  81.     return (result);
  82.  
  83.     sin = here;
  84.     sin.sin_port = 0;
  85.     if (bind(s, (struct sockaddr *) & sin, sizeof sin) < 0) {
  86.     syslog(LOG_ERR, "bind: %s: %m", inet_ntoa(here.sin_addr));
  87.     return (result);
  88.     }
  89.     /* Set up timer so we won't get stuck. */
  90.  
  91.     signal(SIGALRM, timeout);
  92.     if (setjmp(timebuf)) {
  93.     close(s);                /* not: fclose(fp) */
  94.     return (result);
  95.     }
  96.     alarm(RFC931_TIMEOUT);
  97.  
  98.     /* Connect to the RFC931 daemon. */
  99.  
  100.     sin = *there;
  101.     sin.sin_port = htons(RFC931_PORT);
  102.     if (connect(s, (struct sockaddr *) & sin, sizeof(sin)) == -1
  103.     || (fp = fdopen(s, "w+")) == 0) {
  104.     close(s);
  105.     alarm(0);
  106.     return (result);
  107.     }
  108.  
  109.     /*
  110.      * Use unbuffered I/O or we may read back our own query. setbuf() must be
  111.      * called before doing any I/O on the stream. Thanks for the reminder,
  112.      * Paul Kranenburg <pk@cs.few.eur.nl>!
  113.      */
  114.  
  115.     setbuf(fp, (char *) 0);
  116.  
  117.     /* Query the RFC 931 server. Would 13-byte writes ever be broken up? */
  118.  
  119.     fprintf(fp, "%u,%u\r\n", ntohs(there->sin_port), ntohs(here.sin_port));
  120.     fflush(fp);
  121.  
  122.     /*
  123.      * Read response from server. Use fgets()/sscanf() instead of fscanf()
  124.      * because there is no buffer for pushback. Thanks, Chris Turbeville
  125.      * <turbo@cse.uta.edu>.
  126.      */
  127.  
  128.     if (fgets(buffer, sizeof(buffer), fp) != 0
  129.     && ferror(fp) == 0 && feof(fp) == 0
  130.     && sscanf(buffer, "%u , %u : USERID :%*[^:]:%255s",
  131.           &remote, &local, user) == 3
  132.     && ntohs(there->sin_port) == remote
  133.     && ntohs(here.sin_port) == local) {
  134.     /* Strip trailing carriage return. */
  135.  
  136.     if (cp = strchr(user, '\r'))
  137.         *cp = 0;
  138.     result = user;
  139.     }
  140.     alarm(0);
  141.     fclose(fp);
  142.     return (result);
  143. }
  144.