This patch based on apache-httpd version 2.0.55. It adds a new feature
for the ProxyRemote config item. It is now possible to set an optional
<proxy-user:proxy-passwd@> prefix. This works with http and https
backends.
  ProxyRemote <protocol://backend-server[:port]>
<protocol://[<proxy-user>:<proxy-passwd>@]<proxy-server[:port]>

Example:
  ProxyRemote https://foo.org http://user:[EMAIL PROTECTED]:8080

I could only test this patch with a BlueCoat and a Squid Proxy.

http://issues.apache.org/bugzilla/show_bug.cgi?id=37355

http://issues.apache.org/bugzilla/attachment.cgi?id=17448

--
----------------------------------------------------------
Hendrik Harms
mail: [EMAIL PROTECTED]
--- mod_proxy.c.orig    2005-09-20 20:14:29.000000000 +0200
+++ mod_proxy.c 2005-12-13 11:08:42.000000000 +0100
@@ -434,7 +434,7 @@
                 /* handle the scheme */
                 ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server,
                              "Trying to run scheme_handler against proxy");
-                access_status = proxy_run_scheme_handler(r, conf, url, 
ents[i].hostname, ents[i].port);
+                access_status = proxy_run_scheme_handler(r, conf, url, 
ents[i].hostname, ents[i].port, ents[i].auth);
 
                 /* an error or success */
                 if (access_status != DECLINED && access_status != 
HTTP_BAD_GATEWAY) {
@@ -453,7 +453,7 @@
     /* handle the scheme */
     ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server,
                  "Trying to run scheme_handler");
-    access_status = proxy_run_scheme_handler(r, conf, url, NULL, 0);
+    access_status = proxy_run_scheme_handler(r, conf, url, NULL, 0, NULL);
     if (DECLINED == access_status) {
         ap_log_error(APLOG_MARK, APLOG_WARNING, 0, r->server,
                     "proxy: No protocol handler was valid for the URL %s. "
@@ -558,7 +558,7 @@
     proxy_server_conf *conf =
     (proxy_server_conf *) ap_get_module_config(s->module_config, 
&proxy_module);
     struct proxy_remote *new;
-    char *p, *q;
+    char *p, *q, *a;
     char *r, *f, *scheme;
     regex_t *reg = NULL;
     int port;
@@ -574,9 +574,22 @@
             return "ProxyRemote: Bad syntax for a remote proxy server";
     }
     else {
-        scheme[p-r] = 0;
+        scheme[p-r] = '\0';
     }
-    q = strchr(p + 3, ':');
+    *p = '\0';   /* terminate r (scheme) */
+    p+=3;
+    /* may extract authentication string */
+    q = strchr(p, '@');
+    if (q != NULL) {
+        *q = '\0';
+        a = ap_pbase64encode(cmd->pool, p);
+        p = q;
+        p+=1;
+    }
+    else
+        a = NULL;
+    /* may extract port */
+    q = strchr(p, ':');
     if (q != NULL) {
         if (sscanf(q + 1, "%u", &port) != 1 || port > 65535) {
             if (regex)
@@ -587,8 +600,7 @@
         *q = '\0';
     }
     else
-        port = -1;
-    *p = '\0';
+        port = -1;  /* use default port of scheme */
     if (regex) {
         reg = ap_pregcomp(cmd->pool, f, REG_EXTENDED);
         if (!reg)
@@ -597,7 +609,7 @@
     else
         if (strchr(f, ':') == NULL)
             ap_str_tolower(f);         /* lowercase scheme */
-    ap_str_tolower(p + 3);             /* lowercase hostname */
+    ap_str_tolower(p);         /* lowercase hostname */
 
     if (port == -1) {
         port = apr_uri_port_of_scheme(scheme);
@@ -606,8 +618,9 @@
     new = apr_array_push(conf->proxies);
     new->scheme = f;
     new->protocol = r;
-    new->hostname = p + 3;
+    new->hostname = p;
     new->port = port;
+    new->auth = a;
     new->regexp = reg;
     new->use_regex = regex;
     return NULL;
@@ -1148,8 +1161,9 @@
 APR_IMPLEMENT_EXTERNAL_HOOK_RUN_FIRST(proxy, PROXY, int, scheme_handler, 
                                      (request_rec *r, proxy_server_conf *conf, 
                                      char *url, const char *proxyhost, 
-                                     apr_port_t proxyport),(r,conf,url,
-                                     proxyhost,proxyport),DECLINED)
+                                     apr_port_t proxyport, const char 
*proxyauth),
+                                     (r,conf,url, 
proxyhost,proxyport,proxyauth),
+                                     DECLINED)
 APR_IMPLEMENT_EXTERNAL_HOOK_RUN_FIRST(proxy, PROXY, int, canon_handler, 
                                      (request_rec *r, char *url),(r,
                                      url),DECLINED)
--- mod_proxy.h.orig    2005-02-04 21:21:18.000000000 +0100
+++ mod_proxy.h 2005-12-13 10:51:12.000000000 +0100
@@ -92,6 +92,7 @@
 struct proxy_remote {
     const char *scheme;                /* the schemes handled by this proxy, 
or '*' */
     const char *protocol;      /* the scheme used to talk to this proxy */
+    const char *auth;           /* base64encode(<proxyuser>:<proxypasswd>) */
     const char *hostname;      /* the hostname of this proxy */
     apr_port_t  port;          /* the port for this proxy */
     regex_t *regexp;           /* compiled regex (if any) for the remote */
@@ -213,7 +214,8 @@
 
 APR_DECLARE_EXTERNAL_HOOK(proxy, PROXY, int, scheme_handler, (request_rec *r, 
                           proxy_server_conf *conf, char *url, 
-                          const char *proxyhost, apr_port_t proxyport))
+                          const char *proxyhost, apr_port_t proxyport, 
+                          const char *proxyauth))
 APR_DECLARE_EXTERNAL_HOOK(proxy, PROXY, int, canon_handler, (request_rec *r, 
                           char *url))
 
--- proxy_connect.c.orig        2005-02-04 21:21:18.000000000 +0100
+++ proxy_connect.c     2005-12-13 10:57:39.000000000 +0100
@@ -26,7 +26,7 @@
 int ap_proxy_connect_canon(request_rec *r, char *url);
 int ap_proxy_connect_handler(request_rec *r, proxy_server_conf *conf, 
                              char *url, const char *proxyname, 
-                             apr_port_t proxyport);
+                             apr_port_t proxyport, const char *proxyauth);
 
 /*  
  * This handles Netscape CONNECT method secure proxy requests.
@@ -80,7 +80,7 @@
 /* CONNECT handler */
 int ap_proxy_connect_handler(request_rec *r, proxy_server_conf *conf, 
                              char *url, const char *proxyname, 
-                             apr_port_t proxyport)
+                             apr_port_t proxyport, const char *proxyauth)
 {
     apr_pool_t *p = r->pool;
     apr_socket_t *sock;
--- proxy_ftp.c.orig    2005-08-24 14:50:00.000000000 +0200
+++ proxy_ftp.c 2005-12-13 11:09:49.000000000 +0100
@@ -34,7 +34,7 @@
 int ap_proxy_ftp_canon(request_rec *r, char *url);
 int ap_proxy_ftp_handler(request_rec *r, proxy_server_conf *conf,
                              char *url, const char *proxyhost,
-                             apr_port_t proxyport);
+                             apr_port_t proxyport, const char *proxyauth);
 apr_status_t ap_proxy_send_dir_filter(ap_filter_t * f,
                                                    apr_bucket_brigade *bb);
 
@@ -739,7 +739,7 @@
  */
 int ap_proxy_ftp_handler(request_rec *r, proxy_server_conf *conf,
                              char *url, const char *proxyhost,
-                             apr_port_t proxyport)
+                             apr_port_t proxyport, const char *proxyauth)
 {
     apr_pool_t *p = r->pool;
     conn_rec *c = r->connection;
--- proxy_http.c.orig   2005-09-20 22:47:57.000000000 +0200
+++ proxy_http.c        2005-12-13 14:45:07.000000000 +0100
@@ -23,7 +23,7 @@
 int ap_proxy_http_canon(request_rec *r, char *url);
 int ap_proxy_http_handler(request_rec *r, proxy_server_conf *conf,
                           char *url, const char *proxyname, 
-                          apr_port_t proxyport);
+                          apr_port_t proxyport, const char *proxyauth);
 
 typedef struct {
     const char     *name;
@@ -155,6 +155,83 @@
     apr_table_unset(headers, "Connection");
 }
 
+
+static
+apr_status_t ap_proxy_http_connect(apr_pool_t *p, request_rec *r, 
+                                   apr_socket_t *sock,
+                                   const apr_uri_t *uri,
+                                   const char *proxyauth)
+{
+    apr_status_t status = OK;
+    apr_size_t nbytes;
+    char buffer[HUGE_STRING_LEN];
+    char version[HUGE_STRING_LEN];
+    char desc[HUGE_STRING_LEN];
+    int  code;
+
+    nbytes = apr_snprintf(buffer, sizeof(buffer),
+                          "CONNECT %s:%d HTTP/1.0" CRLF, uri->hostname, 
uri->port);
+    ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server,
+                 "proxy(%d): send %s", getpid(), buffer);
+    apr_send(sock, buffer, &nbytes);
+    if (proxyauth) {
+    /*
+       apr_snprintf(desc, sizeof(desc), 
+                             "%s:%s", proxyuser, proxypasswd);
+       nbytes = apr_snprintf(buffer, sizeof(buffer),
+                             "Proxy-Authorization: Basic %s" CRLF,
+                             ap_pbase64encode(p, desc));
+    */
+       nbytes = apr_snprintf(buffer, sizeof(buffer),
+                             "Proxy-Authorization: Basic %s" CRLF,
+                             proxyauth);
+       ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server,
+                    "proxy(%d): send %s", getpid(), buffer);
+       apr_send(sock, buffer, &nbytes);
+    }
+    nbytes = apr_snprintf(buffer, sizeof(buffer),
+                          "Proxy-agent: %s" CRLF CRLF, 
ap_get_server_version());
+    apr_send(sock, buffer, &nbytes);
+    ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server,
+                 "proxy: send %s", buffer);
+
+    status = HTTP_BAD_REQUEST;
+    memset(buffer, '\0', sizeof(buffer));
+    while (apr_recv(sock, buffer, &nbytes) == OK) {
+       if (nbytes <= 0) break;
+       sscanf(buffer, "%s%d%[^\n]",version,&code,desc);
+       if (strncmp(version, "HTTP/", 5) == 0) {
+           if ((code >= 200) && (code < 300)) {
+               status = OK;
+               ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server,
+                            "proxy(%d): CONNECT successful: \"%s\"", getpid(), 
buffer);
+           } else if (code == 407) { 
+               status = HTTP_PROXY_AUTHENTICATION_REQUIRED;
+               ap_log_error(APLOG_MARK, APLOG_ERR, 0, r->server,
+                            "proxy(%d): authentication required", getpid());
+           } else {
+               status = HTTP_BAD_REQUEST;
+               ap_log_error(APLOG_MARK, APLOG_ERR, 0, r->server,
+                            "proxy(%d): unsupported response code: \"%s\"", 
getpid(), buffer);
+           }
+       } else {
+           /* status = HTTP_BAD_REQUEST; */
+           ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server,
+                        "proxy(%d): ignored response: \"%s\"", getpid(), 
buffer);
+       }
+       if (strstr(buffer, "\r\n\r\n")) break;
+       memset(buffer, '\0', sizeof(buffer));
+    } 
+/*
+else {
+       ap_log_error(APLOG_MARK, APLOG_ERR, 0, r->server,
+                    "proxy(%d): missing response", getpid(), buffer);
+    }
+*/
+    return status;
+}
+
+
 static
 apr_status_t ap_proxy_http_determine_connection(apr_pool_t *p, request_rec *r,
                                                 proxy_http_conn_t *p_conn,
@@ -240,10 +317,13 @@
 static
 apr_status_t ap_proxy_http_create_connection(apr_pool_t *p, request_rec *r,
                                              proxy_http_conn_t *p_conn,
-                                             conn_rec *c, conn_rec **origin,
+                                             conn_rec *c, 
+                                             const apr_uri_t *uri,
+                                             conn_rec **origin,
                                              proxy_conn_rec *backend,
                                              proxy_server_conf *conf,
-                                             const char *proxyname) {
+                                             const char *proxyname,
+                                             const char *proxyauth) {
     int failed=0, new=0;
     apr_socket_t *client_socket = NULL;
 
@@ -380,6 +460,15 @@
                          rc);
             return rc;
         }
+        /*  May send CONNECT
+         *   If a proxy is configured and the backend scheme is https,
+         *   I have to send a CONNECT to open the proxy tunnel */
+        if (backend->is_ssl && proxyname) {
+            rc = ap_proxy_http_connect(p, r, p_conn->sock, uri, proxyauth);
+            if ( rc != OK ) {
+                return rc;
+            }
+        }
     }
     return OK;
 }
@@ -787,6 +876,8 @@
     return status;
 }
 
+
+
 static
 apr_status_t ap_proxy_http_request(apr_pool_t *p, request_rec *r,
                                    proxy_http_conn_t *p_conn, conn_rec 
*origin, 
@@ -794,7 +885,8 @@
                                    apr_uri_t *uri,
                                    char *url, 
                                    apr_bucket_brigade *header_brigade,
-                                   char *server_portstr) 
+                                   char *server_portstr,
+                                   const char *proxyauth) 
 {
     conn_rec *c = r->connection;
     apr_bucket_alloc_t *bucket_alloc = c->bucket_alloc;
@@ -973,7 +1065,9 @@
              * somehow whether this request was authenticated or not.
              */
              || !strcasecmp(headers_in[counter].key,"Proxy-Authorization")
-             || !strcasecmp(headers_in[counter].key,"Proxy-Authenticate")) {
+             || !strcasecmp(headers_in[counter].key,"Proxy-Authenticate")
+             ) {
+            
             continue;
         }
 
@@ -1006,6 +1100,13 @@
         e = apr_bucket_pool_create(buf, strlen(buf), p, c->bucket_alloc);
         APR_BRIGADE_INSERT_TAIL(header_brigade, e);
     }
+    if (proxyauth) {
+        buf = apr_pstrcat(p, "Proxy-Authorization: Basic ", 
+                          proxyauth, CRLF, NULL);
+        ap_xlate_proto_to_ascii(buf, strlen(buf));
+        e = apr_bucket_pool_create(buf, strlen(buf), p, c->bucket_alloc);
+        APR_BRIGADE_INSERT_TAIL(header_brigade, e);
+    }
 
     /* We have headers, let's figure out our request body... */
     input_brigade = apr_brigade_create(p, bucket_alloc);
@@ -1574,7 +1675,7 @@
  */
 int ap_proxy_http_handler(request_rec *r, proxy_server_conf *conf,
                           char *url, const char *proxyname, 
-                          apr_port_t proxyport)
+                          apr_port_t proxyport, const char *proxyauth)
 {
     int status;
     char server_portstr[32];
@@ -1651,15 +1752,16 @@
     }
 
     /* Step Two: Make the Connection */
-    status = ap_proxy_http_create_connection(p, r, p_conn, c, &origin, backend,
-                                             conf, proxyname);
+    status = ap_proxy_http_create_connection(p, r, p_conn, c, uri, &origin, 
backend,
+                                             conf, proxyname, proxyauth);
     if ( status != OK ) {
         return status;
     }
+
    
     /* Step Three: Send the Request */
     status = ap_proxy_http_request(p, r, p_conn, origin, conf, uri, url, bb,
-                                   server_portstr);
+                                   server_portstr, (is_ssl ? NULL : 
proxyauth));
     if ( status != OK ) {
         return status;
     }

Reply via email to