You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@httpd.apache.org by Troy Morrison <sp...@zoom.com> on 1996/06/01 20:11:24 UTC

Apache Proxy CONNECT support diff

diff -5 -u apache_1.1b2/src/http_core.c apache_1.1b2-new/src/http_core.c
--- apache_1.1b2/src/http_core.c	Thu Apr 11 00:00:19 1996
+++ apache_1.1b2-new/src/http_core.c	Sun May 19 19:23:11 1996
@@ -476,10 +476,11 @@
         char *method = getword_conf (cmd->pool, &limited_methods);
 	if(!strcasecmp(method,"GET")) limited |= (1 << M_GET);
 	else if(!strcasecmp(method,"PUT")) limited |= (1 << M_PUT);
 	else if(!strcasecmp(method,"POST")) limited |= (1 << M_POST);
 	else if(!strcasecmp(method,"DELETE")) limited |= (1 << M_DELETE);
+        else if(!strcasecmp(method,"CONNECT")) limited |= (1 << M_CONNECT);
 	else return "unknown method in <Limit>";
     }
 
     cmd->limited = limited;
     return NULL;
@@ -860,10 +861,11 @@
       (core_dir_config *)get_module_config(r->per_dir_config, &core_module);
     int errstatus;
     FILE *f;
     
     if (r->method_number != M_GET) return DECLINED;
+
     if (r->finfo.st_mode == 0 || (r->path_info && *r->path_info)) {
 	log_reason("File does not exist", r->filename, r);
 	return NOT_FOUND;
     }
 	
diff -5 -u apache_1.1b2/src/http_protocol.c apache_1.1b2-new/src/http_protocol.c
--- apache_1.1b2/src/http_protocol.c	Tue Apr 16 06:00:10 1996
+++ apache_1.1b2-new/src/http_protocol.c	Sun May 19 19:26:40 1996
@@ -437,10 +437,12 @@
         r->method_number = M_POST;
     else if(!strcmp(r->method,"PUT")) 
         r->method_number = M_PUT;
     else if(!strcmp(r->method,"DELETE")) 
         r->method_number = M_DELETE;
+    else if(!strcmp(r->method,"CONNECT"))
+        r->method_number = M_CONNECT;
     else 
         r->method_number = M_INVALID; /* Will eventually croak. */
 
     return r;
 }
diff -5 -u apache_1.1b2/src/httpd.h apache_1.1b2-new/src/httpd.h
--- apache_1.1b2/src/httpd.h	Tue Apr 23 20:08:13 1996
+++ apache_1.1b2-new/src/httpd.h	Sun May 19 12:20:58 1996
@@ -237,16 +237,17 @@
 #define NOT_IMPLEMENTED 501
 #define BAD_GATEWAY 502
 #define SERVICE_UNAVAILABLE 503
 #define RESPONSE_CODES 10
 
-#define METHODS 5
+#define METHODS 6
 #define M_GET 0
 #define M_PUT 1
 #define M_POST 2
 #define M_DELETE 3
-#define M_INVALID 4
+#define M_CONNECT 4
+#define M_INVALID 5
 
 #define CGI_MAGIC_TYPE "application/x-httpd-cgi"
 #define INCLUDES_MAGIC_TYPE "text/x-server-parsed-html"
 #define INCLUDES_MAGIC_TYPE3 "text/x-server-parsed-html3"
 #define MAP_FILE_MAGIC_TYPE "application/x-type-map"
diff -5 -u apache_1.1b2/src/mod_mime.c apache_1.1b2-new/src/mod_mime.c
--- apache_1.1b2/src/mod_mime.c	Sat Apr 13 00:00:17 1996
+++ apache_1.1b2-new/src/mod_mime.c	Thu May 16 14:52:22 1996
@@ -226,10 +226,18 @@
     if (S_ISDIR(r->finfo.st_mode)) {
         r->content_type = DIR_MAGIC_TYPE;
 	return OK;
     }
 
+    /* TM -- FIXME
+     * 
+     * if r->filename does not contain a '/', the following passes a null
+     * pointer to getword, causing a SEGV ..
+     */
+
+    if(fn == NULL) fn = r->filename;
+
     /* Parse filename extensions, which can be in any order */
     while ((ext = getword(r->pool, &fn, '.')) && *ext) {
       int found = 0;
 
       /* Check for Content-Type */
diff -5 -u apache_1.1b2/src/mod_proxy.c apache_1.1b2-new/src/mod_proxy.c
--- apache_1.1b2/src/mod_proxy.c	Thu Apr 11 12:00:11 1996
+++ apache_1.1b2-new/src/mod_proxy.c	Mon May 20 12:02:43 1996
@@ -70,11 +70,12 @@
 two passes). Consider doing them the first time round.
 
 Ben Laurie <be...@algroup.co.uk> 30 Mar 96
 */
 
-#define TESTING	1
+#define TESTING	0
+#undef  EXPLAIN
 
 #include "httpd.h"
 #include "http_config.h"
 #include "http_log.h"
 #include "http_main.h"
@@ -197,11 +198,11 @@
 static int ftp_canon(request_rec *r, char *url);
 
 static int http_handler(request_rec *r, struct cache_req *c, char *url,
 			const char *proxyhost, int proxyport);
 static int ftp_handler(request_rec *r, struct cache_req *c, char *url);
-
+static int connect_handler(request_rec *r, struct cache_req *c, char *url);
 
 static BUFF *cache_error(struct cache_req *r);
 
 /* -------------------------------------------------------------- */
 /* Translate the URL into a 'filename' */
@@ -2126,13 +2127,20 @@
 
 /* otherwise, try it direct */
 /* N.B. what if we're behind a firewall, where we must use a proxy or
  * give up??
  */
+
     /* handle the scheme */
     if (strcmp(scheme, "http") == 0) return http_handler(r, cr, url, NULL, 0);
     if (strcmp(scheme, "ftp") == 0) return ftp_handler(r, cr, url);
+    
+    /* This handles Netscape's Secure CONNECT method... it is a bit of a kludge
+     * But works, sort of :-)  
+     */
+
+    if (r->method_number == M_CONNECT) return connect_handler(r, cr, url);
     else return NOT_IMPLEMENTED;
 }
 
 
 static int
@@ -2565,10 +2573,128 @@
     pclosef(pool, sock);
 
     return OK;
 }
 
+/*
+ * This handles Netscape-SSL style "CONNECT" proxy requests.
+ * A connection is opened to the specified host and data is
+ * passed through between the WWW site and the browser.
+ * This code is based on the IETF document at 
+ * http://www.netscape.com/docs/std/tunnelling_ssl.html.
+ *
+ * FIXME: this is bad, because it does its own socket I/O
+ *        instead of using the I/O in buff.c.  However, 
+ *        the I/O in buff.c blocks on reads, and because
+ *        this function doesn't know how much data will
+ *        be sent either way (or when) it can't use blocking
+ *        I/O.  This may be very implementation-specific
+ *        (to Linux).  Any suggestions?
+ * FIXME: this doesn't log the number of bytes sent, but
+ *        that may be okay, since the data is supposed to
+ *        be transparent.
+ * FIXME: doesn't check any headers initally sent from the
+ *        client.
+ * FIXME: according to netscape docs, should only connect
+ *        to well-known SSL ports (https, snews, etc.)
+ * FIXME: should allow authentication, but hopefully the
+ *        generic proxy authentication is good enough.
+ * FIXME: no check for r->assbackwards, whatever that is.
+ */
+
+static int
+connect_handler(request_rec *r, struct cache_req *c, char *url)
+{
+    struct sockaddr_in server;
+    const char *host, *err;
+    char *p;
+    int   port, sock;
+    char buffer[HUGE_STRING_LEN];
+    int  nbytes, i;
+    fd_set fds;
+
+    memset(&server, '\0', sizeof(server));
+    server.sin_family=AF_INET;
+
+    /* Break the URL into host:port pairs */
+
+    host = url;
+    p = strchr(url, ':');
+    if (p==NULL) port = DEFAULT_HTTPS_PORT;
+    else
+    {
+      port = atoi(p+1);
+      *p='\0';
+    }
+
+    Explain2("CONNECT to %s on port %d", host, port);
+
+    server.sin_port = htons(port);
+    err = host2addr(host, &server.sin_addr); 
+    if (err != NULL) return proxyerror(r, err); /* give up */
+
+    sock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
+    if (sock == -1)
+    {
+        log_error("proxy: error creating socket", r->server);
+        return SERVER_ERROR;
+    }
+    note_cleanups_for_fd(r->pool, sock);
+
+    i = doconnect(sock, &server, r);
+    if (i == -1 )
+        return proxyerror(r, "Could not connect to remote machine");
+
+    Explain0("Returning 200 OK Status");
+
+    rvputs(r, "HTTP/1.0 200 Connection established\015\012", NULL);
+    rvputs(r, "Proxy-agent: ", SERVER_VERSION, "\015\012\015\012", NULL);
+    bflush(r->connection->client);
+
+    while (1) /* Infinite loop until error (one side closes the connection) */
+    {
+      FD_ZERO(&fds);
+      FD_SET(sock, &fds);
+      FD_SET(r->connection->client->fd, &fds);
+
+      Explain0("Going to sleep (select)");
+      i = select((r->connection->client->fd > sock ? r->connection->client->fd+1 : sock+1), &fds, NULL, NULL, NULL);
+      Explain1("Woke from select(), i=%d",i);
+
+      if (i)
+      {
+        if (FD_ISSET(sock, &fds))
+        {
+           Explain0("sock was set");
+           if((nbytes=read(sock,buffer,HUGE_STRING_LEN))!=0)
+           {
+              if(nbytes==-1) break;
+              if(write(r->connection->client->fd, buffer, nbytes)==EOF)break;
+              Explain1("Wrote %d bytes to client", nbytes);
+           }
+           else break;
+        }
+        else if (FD_ISSET(r->connection->client->fd, &fds))
+        {
+           Explain0("client->fd was set");
+           if((nbytes=read(r->connection->client->fd,buffer,HUGE_STRING_LEN))!=0)
+           {
+              if(nbytes==-1) break;
+              if(write(sock,buffer,nbytes)==EOF) break;
+              Explain1("Wrote %d bytes to server", nbytes);
+           }
+           else break;
+        }
+        else break; /* Must be done waiting */
+      }
+      else break;
+    }
+
+    pclosef(r->pool,sock);
+
+    return OK;
+}
 
 /*
  * This handles http:// URLs, and other URLs using a remote proxy over http
  * If proxyhost is NULL, then contact the server directly, otherwise
  * go via the proxy.

-- 
Ben Laurie                  Phone: +44 (181) 994 6435
Freelance Consultant and    Fax:   +44 (181) 994 6472
Technical Director          Email: ben@algroup.co.uk
A.L. Digital Ltd,           URL: http://www.algroup.co.uk
London, England.