--- mod_proxy.c.orig 2005-09-20 20:14:29.000000000 +0200 +++ mod_proxy.c.orig 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.orig 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(:) */ 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.orig 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.orig 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.orig 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; }