You are viewing a plain text version of this content. The canonical link for it is here.
Posted to cvs@httpd.apache.org by tr...@locus.apache.org on 2000/12/19 17:08:04 UTC

cvs commit: httpd-2.0/server rfc1413.c

trawick     00/12/19 08:08:03

  Modified:    .        CHANGES
               server   rfc1413.c
  Log:
  Rework the RFC1413 handling to make it thread-safe, use a timeout
  on the query, and remove IPv4 dependencies.
  
  Revision  Changes    Path
  1.13      +3 -0      httpd-2.0/CHANGES
  
  Index: CHANGES
  ===================================================================
  RCS file: /home/cvs/httpd-2.0/CHANGES,v
  retrieving revision 1.12
  retrieving revision 1.13
  diff -u -r1.12 -r1.13
  --- CHANGES	2000/12/19 15:08:56	1.12
  +++ CHANGES	2000/12/19 16:08:00	1.13
  @@ -1,5 +1,8 @@
   Changes with Apache 2.0b1
   
  +  *) Rework the RFC1413 handling to make it thread-safe, use a timeout
  +     on the query, and remove IPv4 dependencies.  [Jeff Trawick]
  +
     *) Get all of the auth modules to the point that they will install and
        be loadable into the server.  Our new build/install mechanism expects
        that all modules will have a common name format.  The auth modules 
  
  
  
  1.35      +95 -70    httpd-2.0/server/rfc1413.c
  
  Index: rfc1413.c
  ===================================================================
  RCS file: /home/cvs/httpd-2.0/server/rfc1413.c,v
  retrieving revision 1.34
  retrieving revision 1.35
  diff -u -r1.34 -r1.35
  --- rfc1413.c	2000/11/26 04:47:30	1.34
  +++ rfc1413.c	2000/12/19 16:08:03	1.35
  @@ -81,6 +81,7 @@
   
   #include "apr.h"
   #include "apr_network_io.h"
  +#include "apr_strings.h"
   
   #if APR_HAVE_STDIO_H
   #include <stdio.h>
  @@ -109,83 +110,114 @@
   #ifndef RFC1413_TIMEOUT
   #define RFC1413_TIMEOUT	30
   #endif
  -#define	ANY_PORT	0	/* Any old port will do */
   #define FROM_UNKNOWN  "unknown"
   
   int ap_rfc1413_timeout = RFC1413_TIMEOUT;	/* Global so it can be changed */
   
  -/* bind_connect - bind both ends of a socket */
  -/* Ambarish fix this. Very broken */
  -static int get_rfc1413(apr_socket_t *sock, apr_pool_t *p, 
  -                       const char *local_ip, const char *rmt_ip, 
  -		       char user[RFC1413_USERLEN+1], server_rec *srv)
  +static apr_status_t rfc1413_connect(apr_socket_t **newsock, conn_rec *conn,
  +                                    server_rec *srv)
   {
  -    apr_port_t rmt_port, our_port;
  -    apr_port_t sav_rmt_port, sav_our_port;
  -    apr_status_t status;
  -    size_t i;
  -    char *cp;
  -    char buffer[RFC1413_MAXDATA + 1];
  -    int buflen;
  +    apr_status_t rv;
       apr_sockaddr_t *localsa, *destsa;
  -
  -    /*
  -     * Bind the local and remote ends of the query socket to the same
  -     * IP addresses as the connection under investigation. We go
  -     * through all this trouble because the local or remote system
  -     * might have more than one network address. The RFC1413 etc.
  -     * client sends only port numbers; the server takes the IP
  -     * addresses from the query socket.
  -     */
   
  -    if ((status = apr_getaddrinfo(&localsa, local_ip, APR_INET, 0, 0, p)) 
  -        != APR_SUCCESS) {
  +    if ((rv = apr_getaddrinfo(&localsa, conn->local_ip, APR_UNSPEC, 
  +                              0, /* ephemeral port */
  +                              0, conn->pool)) != APR_SUCCESS) {
  +        /* This should not fail since we have a numeric address string
  +         * as the host. */
  +        ap_log_error(APLOG_MARK, APLOG_CRIT, rv, srv,
  +                     "rfc1413: apr_getaddrinfo(%s) failed",
  +                     conn->local_ip);
  +        return rv;
  +    }
  +    
  +    if ((rv = apr_getaddrinfo(&destsa, conn->remote_ip, 
  +                              localsa->sa.sin.sin_family, /* has to match */
  +                              RFC1413_PORT, 0, conn->pool)) != APR_SUCCESS) {
           /* This should not fail since we have a numeric address string
            * as the host. */
  -        ap_log_error(APLOG_MARK, APLOG_CRIT, status, srv,
  -                     "rfc1413: apr_getaddrinfo() failed");
  -        return -1;
  +        ap_log_error(APLOG_MARK, APLOG_CRIT, rv, srv,
  +                     "rfc1413: apr_getaddrinfo(%s) failed",
  +                     conn->remote_ip);
  +        return rv;
  +    }
  +
  +    if ((rv = apr_create_socket(newsock, 
  +                                localsa->sa.sin.sin_family, /* has to match */
  +                                SOCK_STREAM, conn->pool)) != APR_SUCCESS) {
  +	ap_log_error(APLOG_MARK, APLOG_CRIT, rv, srv,
  +                     "rfc1413: error creating query socket");
  +        return rv;
       }
   
  -    if ((status = apr_bind(sock, localsa)) != APR_SUCCESS) {
  -	ap_log_error(APLOG_MARK, APLOG_CRIT, status, srv,
  -		    "bind: rfc1413: Error binding to local port");
  -	return -1;
  +    if ((rv = apr_setsocketopt(*newsock, APR_SO_TIMEOUT, 
  +                               ap_rfc1413_timeout * APR_USEC_PER_SEC)) 
  +        != APR_SUCCESS) {
  +        ap_log_error(APLOG_MARK, APLOG_CRIT, rv, srv,
  +                     "rfc1413: error setting query socket timeout");
  +        apr_close_socket(*newsock);
  +        return rv;
       }
   
  -    if ((status = apr_getaddrinfo(&destsa, rmt_ip, APR_INET, RFC1413_PORT, 0,
  -                                  p)) != APR_SUCCESS) {
  -        /* This should not fail since we have a numeric address string
  -         * as the host. */
  -        ap_log_error(APLOG_MARK, APLOG_CRIT, status, srv,
  -                     "rfc1413: apr_getaddrinfo() failed");
  -        return -1;
  +/*
  + * Bind the local and remote ends of the query socket to the same
  + * IP addresses as the connection under investigation. We go
  + * through all this trouble because the local or remote system
  + * might have more than one network address. The RFC1413 etc.
  + * client sends only port numbers; the server takes the IP
  + * addresses from the query socket.
  + */
  +
  +    if ((rv = apr_bind(*newsock, localsa)) != APR_SUCCESS) {
  +	ap_log_error(APLOG_MARK, APLOG_CRIT, rv, srv,
  +                     "rfc1413: Error binding query socket to local port");
  +        apr_close_socket(*newsock);
  +	return rv;
       }
  +
   /*
    * errors from connect usually imply the remote machine doesn't support
  - * the service
  + * the service; don't log such an error
    */
  -    if (apr_connect(sock, destsa) != APR_SUCCESS)
  -        return -1;
  +    if ((rv = apr_connect(*newsock, destsa)) != APR_SUCCESS) {
  +        apr_close_socket(*newsock);
  +        return rv;
  +    }
  +
  +    return APR_SUCCESS;
  +}
  +
  +static apr_status_t rfc1413_query(apr_socket_t *sock, conn_rec *conn, 
  +                                  server_rec *srv)
  +{
  +    apr_port_t rmt_port, our_port;
  +    apr_port_t sav_rmt_port, sav_our_port;
  +    size_t i;
  +    char *cp;
  +    char buffer[RFC1413_MAXDATA + 1];
  +    char user[RFC1413_USERLEN + 1];	/* XXX */
  +    int buflen;
  +    apr_sockaddr_t *localsa;
  +
       apr_get_sockaddr(&localsa, APR_LOCAL, sock);
       apr_get_port(&sav_our_port, localsa);
       sav_rmt_port = RFC1413_PORT;
   
  -/* send the data */
  +    /* send the data */
       buflen = apr_snprintf(buffer, sizeof(buffer), "%hu,%hu\r\n", sav_rmt_port,
  -		sav_our_port);
  +                          sav_our_port);
       ap_xlate_proto_to_ascii(buffer, buflen);
   
       /* send query to server. Handle short write. */
       i = 0;
  -    while(i < strlen(buffer)) {
  +    while (i < strlen(buffer)) {
           apr_size_t j = strlen(buffer + i);
           apr_status_t status;
   	status  = apr_send(sock, buffer+i, &j);
  -	if (status != APR_SUCCESS && !APR_STATUS_IS_EINTR(status)) {
  +	if (status != APR_SUCCESS) {
   	    ap_log_error(APLOG_MARK, APLOG_CRIT, status, srv,
   		         "write: rfc1413: error sending request");
  -	    return -1;
  +	    return status;
   	}
   	else if (j > 0) {
   	    i+=j; 
  @@ -208,17 +240,17 @@
           apr_size_t j = sizeof(buffer) - 1 - i;
           apr_status_t status;
   	status = apr_recv(sock, buffer+i, &j);
  -	if (status != APR_SUCCESS && !APR_STATUS_IS_EINTR(status)) {
  +	if (status != APR_SUCCESS) {
   	    ap_log_error(APLOG_MARK, APLOG_CRIT, status, srv,
   			"read: rfc1413: error reading response");
  -	    return -1;
  +	    return status;
   	}
   	else if (j > 0) {
   	    i+=j; 
   	}
           else if (status == APR_SUCCESS && j == 0) {
               /* Oops... we ran out of data before finding newline */
  -            return -1;
  +            return APR_EINVAL;
           }
       }
   
  @@ -227,7 +259,7 @@
       if (sscanf(buffer, "%hu , %hu : USERID :%*[^:]:%512s", &rmt_port, &our_port,
   	       user) != 3 || sav_rmt_port != rmt_port
   	|| sav_our_port != our_port)
  -	return -1;
  +	return APR_EINVAL;
   
       /*
        * Strip trailing carriage return. It is part of the
  @@ -236,31 +268,24 @@
   
       if ((cp = strchr(user, '\r')))
   	*cp = '\0';
  +
  +    conn->remote_logname = apr_pstrdup(conn->pool, user);
   
  -    return 0;
  +    return APR_SUCCESS;
   }
   
  -/* rfc1413 - return remote user name, given socket structures */
   char *ap_rfc1413(conn_rec *conn, server_rec *srv)
   {
  -    apr_status_t status;
  -    static char user[RFC1413_USERLEN + 1];	/* XXX */
  -    static char *result;
  -    static apr_socket_t *sock;
  -
  -    result = FROM_UNKNOWN;
  -
  -    if ((status = apr_create_socket(&sock, APR_INET, SOCK_STREAM, 
  -                                    conn->pool)) != APR_SUCCESS) {
  -	ap_log_error(APLOG_MARK, APLOG_CRIT, status, srv,
  -		    "socket: rfc1413: error creating socket");
  -	conn->remote_logname = result;
  -    }
  -
  -    if (get_rfc1413(sock, conn->pool, conn->local_ip, conn->remote_ip, user, srv) >= 0)
  -        result = user;
  -    apr_close_socket(sock);
  -    conn->remote_logname = result;
  +    apr_socket_t *sock;
  +    apr_status_t rv;
   
  +    rv = rfc1413_connect(&sock, conn, srv);
  +    if (rv == APR_SUCCESS) {
  +        rv = rfc1413_query(sock, conn, srv);
  +        apr_close_socket(sock);
  +    }
  +    if (rv != APR_SUCCESS) {
  +        conn->remote_logname = FROM_UNKNOWN;
  +    }
       return conn->remote_logname;
   }