chuck 96/06/07 13:19:06
Modified: src http_core.c http_protocol.c httpd.h mod_mime.c mod_proxy.c Log: Reviewed by: Chuck Murcko Submitted by: Chuck Murcko Obtained from: Troy Morrison <[EMAIL PROTECTED]> (CONNECT patch) This patch adds a CONNECT method SSL proxy, and a NoCache config file option, which is a list of hosts or domains not to cache. Revision Changes Path 1.14 +2 -0 apache/src/http_core.c Index: http_core.c =================================================================== RCS file: /export/home/cvs/apache/src/http_core.c,v retrieving revision 1.13 retrieving revision 1.14 diff -C3 -r1.13 -r1.14 *** http_core.c 1996/06/07 17:39:24 1.13 --- http_core.c 1996/06/07 20:18:58 1.14 *************** *** 487,492 **** --- 487,493 ---- 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>"; } *************** *** 873,878 **** --- 874,880 ---- 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; 1.21 +2 -0 apache/src/http_protocol.c Index: http_protocol.c =================================================================== RCS file: /export/home/cvs/apache/src/http_protocol.c,v retrieving revision 1.20 retrieving revision 1.21 diff -C3 -r1.20 -r1.21 *** http_protocol.c 1996/05/27 21:08:28 1.20 --- http_protocol.c 1996/06/07 20:18:59 1.21 *************** *** 443,448 **** --- 443,450 ---- 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. */ 1.26 +3 -2 apache/src/httpd.h Index: httpd.h =================================================================== RCS file: /export/home/cvs/apache/src/httpd.h,v retrieving revision 1.25 retrieving revision 1.26 diff -C3 -r1.25 -r1.26 *** httpd.h 1996/06/07 17:39:25 1.25 --- httpd.h 1996/06/07 20:19:00 1.26 *************** *** 261,272 **** #define SERVICE_UNAVAILABLE 503 #define RESPONSE_CODES 10 ! #define METHODS 5 #define M_GET 0 #define M_PUT 1 #define M_POST 2 #define M_DELETE 3 ! #define M_INVALID 4 #define CGI_MAGIC_TYPE "application/x-httpd-cgi" #define INCLUDES_MAGIC_TYPE "text/x-server-parsed-html" --- 261,273 ---- #define SERVICE_UNAVAILABLE 503 #define RESPONSE_CODES 10 ! #define METHODS 6 #define M_GET 0 #define M_PUT 1 #define M_POST 2 #define M_DELETE 3 ! #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" 1.10 +8 -0 apache/src/mod_mime.c Index: mod_mime.c =================================================================== RCS file: /export/home/cvs/apache/src/mod_mime.c,v retrieving revision 1.9 retrieving revision 1.10 diff -C3 -r1.9 -r1.10 *** mod_mime.c 1996/04/13 01:26:53 1.9 --- mod_mime.c 1996/06/07 20:19:01 1.10 *************** *** 228,233 **** --- 228,241 ---- 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; 1.23 +187 -30 apache/src/mod_proxy.c Index: mod_proxy.c =================================================================== RCS file: /export/home/cvs/apache/src/mod_proxy.c,v retrieving revision 1.22 retrieving revision 1.23 diff -C3 -r1.22 -r1.23 *** mod_proxy.c 1996/05/28 02:33:47 1.22 --- mod_proxy.c 1996/06/07 20:19:02 1.23 *************** *** 73,93 **** More changes: ! 0) tested w/SOCKS proxy for httpd ! 1) fixed IP address formation in host2addr() - 2) fixed SIGALRM on big cache cleanup - 3) fixed temp files #tmp not removed - 4) changed PF_INET to AF_INET in socket() calls ! Chuck Murcko <[EMAIL PROTECTED]> 27 May 96 */ ! #define TESTING 1 #include "httpd.h" #include "http_config.h" --- 73,91 ---- More changes: ! 0) tested w/SOCKS proxy for http 1) fixed IP address formation in host2addr() 2) fixed SIGALRM on big cache cleanup 3) fixed temp files #tmp not removed 4) changed PF_INET to AF_INET in socket() calls + 5) installed CONNECT code from Troy Morrison <[EMAIL PROTECTED]> for testing + 6) added NoCache config directive to disallow caching for selected hosts ! Chuck Murcko <[EMAIL PROTECTED]> 2 Jun 96 */ ! #define TESTING 0 #include "httpd.h" #include "http_config.h" *************** *** 106,116 **** --- 104,116 ---- #define SEC_ONE_DAY 86400 /* one day, in seconds */ #define SEC_ONE_HR 3600 /* one hour, in seconds */ + #define DEFAULT_FTP_DATA_PORT 20 #define DEFAULT_FTP_PORT 21 #define DEFAULT_GOPHER_PORT 70 #define DEFAULT_NNTP_PORT 119 #define DEFAULT_WAIS_PORT 210 #define DEFAULT_HTTPS_PORT 443 + #define DEFAULT_SNEWS_PORT 563 #define DEFAULT_PROSPERO_PORT 1525 /* WARNING: conflict w/Oracle */ /* Some WWW schemes and their default ports; this is basically /etc/services */ *************** *** 125,130 **** --- 125,131 ---- { "nntp", DEFAULT_NNTP_PORT}, { "wais", DEFAULT_WAIS_PORT}, { "https", DEFAULT_HTTPS_PORT}, + { "snews", DEFAULT_SNEWS_PORT}, { "prospero", DEFAULT_PROSPERO_PORT}, { NULL, -1} /* unknown port */ }; *************** *** 144,149 **** --- 145,153 ---- char *fake; }; + struct nocache_entry { + char *name; + }; #define DEFAULT_CACHE_SPACE 5 #define DEFAULT_CACHE_MAXEXPIRE SEC_ONE_DAY *************** *** 169,174 **** --- 173,179 ---- struct cache_conf cache; /* cache configuration */ array_header *proxies; array_header *aliases; + array_header *nocaches; int req; /* true if proxy requests are enabled */ } proxy_server_conf; *************** *** 220,229 **** static int http_handler(request_rec *r, struct cache_req *c, char *url, const char *proxyhost, int proxyport); - static int https_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 BUFF *cache_error(struct cache_req *r); --- 225,233 ---- 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); *************** *** 325,334 **** /* canonicalise each specific scheme */ if (strncmp(url, "http:", 5) == 0) return http_canon(r, url+5, "http", DEFAULT_PORT); - # if 0 - else if (strncmp(url, "https:", 6) == 0) - return http_canon(r, url+6, "https", DEFAULT_HTTPS_PORT); - #endif else if (strncmp(url, "ftp:", 4) == 0) return ftp_canon(r, url+4); else return OK; /* otherwise; we've done the best we can */ } --- 329,334 ---- *************** *** 2158,2164 **** * give up?? */ /* handle the scheme */ ! if (strcmp(scheme, "https") == 0) return https_handler(r, cr, url, NULL, 0); if (strcmp(scheme, "http") == 0) return http_handler(r, cr, url, NULL, 0); if (strcmp(scheme, "ftp") == 0) return ftp_handler(r, cr, url); else return NOT_IMPLEMENTED; --- 2158,2164 ---- * give up?? */ /* handle the scheme */ ! if (r->method_number == M_CONNECT) return connect_handler(r, cr, url); if (strcmp(scheme, "http") == 0) return http_handler(r, cr, url, NULL, 0); if (strcmp(scheme, "ftp") == 0) return ftp_handler(r, cr, url); else return NOT_IMPLEMENTED; *************** *** 2260,2266 **** hard_timeout ("proxy connect", r); do i = connect(sock, (struct sockaddr *)addr, sizeof(struct sockaddr_in)); ! while (i == -1 && errno == EINTR); /* SHUDDER - cdm */ if (i == -1) log_uerror("connect", NULL, NULL, r->server); kill_timeout(r); --- 2260,2266 ---- hard_timeout ("proxy connect", r); do i = connect(sock, (struct sockaddr *)addr, sizeof(struct sockaddr_in)); ! while (i == -1 && errno == EINTR); if (i == -1) log_uerror("connect", NULL, NULL, r->server); kill_timeout(r); *************** *** 2518,2524 **** hard_timeout ("proxy ftp data connect", r); len = sizeof(struct sockaddr_in); do csd = accept(dsock, (struct sockaddr *)&server, &len); ! while (csd == -1 && errno == EINTR); if (csd == -1) { log_uerror("accept", NULL, "proxy: failed to accept data connection", --- 2518,2524 ---- hard_timeout ("proxy ftp data connect", r); len = sizeof(struct sockaddr_in); do csd = accept(dsock, (struct sockaddr *)&server, &len); ! while (csd == -1 && errno == EINTR); /* SHUDDER on SOCKS - cdm */ if (csd == -1) { log_uerror("accept", NULL, "proxy: failed to accept data connection", *************** *** 2594,2614 **** 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. ! * Note that if a proxy is used, then URLs other than http: can be accessed, ! * also, if we have trouble which is clearly specific to the proxy, then ! * we return DECLINED so that we can try another proxy. (Or the direct ! * route.) ! */ static int ! https_handler(request_rec *r, struct cache_req *c, char *url, ! const char *proxyhost, int proxyport) { ! return NOT_IMPLEMENTED; ! } /* * This handles http:// URLs, and other URLs using a remote proxy over http --- 2594,2729 ---- 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. In fact, this doesn't log at all ! * yet. 8^) ! * FIXME: doesn't check any headers initally sent from the ! * client. ! * 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'; ! } ! ! switch (port) ! { ! case DEFAULT_HTTPS_PORT: ! case DEFAULT_SNEWS_PORT: ! break; ! default: ! return SERVICE_UNAVAILABLE; ! break; ! } ! ! 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(AF_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 *************** *** 2635,2640 **** --- 2750,2761 ---- pool *pool=r->pool; const long int zero=0L; + void *sconf = r->server->module_config; + proxy_server_conf *conf = + (proxy_server_conf *)get_module_config(sconf, &proxy_module); + struct nocache_entry *ent=(struct nocache_entry *)conf->nocaches->elts; + int nocache = 0; + memset(&server, '\0', sizeof(server)); server.sin_family = AF_INET; *************** *** 2790,2796 **** hdr[i].value = date_canon(pool, hdr[i].value); } ! i = cache_update(c, resp_hdrs, inprotocol, 0); if (i != DECLINED) { pclosef(pool, sock); --- 2911,2924 ---- hdr[i].value = date_canon(pool, hdr[i].value); } ! /* check if NoCache directive on this host */ ! for (i=0; i < conf->nocaches->nelts; i++) ! { ! if (ent[i].name != NULL && strstr(host, ent[i].name) != NULL) ! nocache = 1; ! } ! ! i = cache_update(c, resp_hdrs, inprotocol, nocache); if (i != DECLINED) { pclosef(pool, sock); *************** *** 2862,2867 **** --- 2990,2996 ---- ps->proxies = make_array(p, 10, sizeof(struct proxy_remote)); ps->aliases = make_array(p, 10, sizeof(struct proxy_alias)); + ps->nocaches = make_array(p, 10, sizeof(struct nocache_entry)); ps->req = 0; ps->cache.root = NULL; *************** *** 3038,3043 **** --- 3167,3198 ---- return NULL; } + static char * + set_cache_exclude(cmd_parms *parms, void *dummy, char *arg) + { + server_rec *s = parms->server; + proxy_server_conf *conf = + get_module_config (s->module_config, &proxy_module); + struct nocache_entry *new; + struct nocache_entry *list=(struct nocache_entry*)conf->nocaches->elts; + int found = 0; + int i; + + /* Don't duplicate entries */ + for (i=0; i < conf->nocaches->nelts; i++) + { + if (strcmp(arg, list[i].name) == 0) + found = 1; + } + + if (!found) + { + new = push_array (conf->nocaches); + new->name = arg; + } + return NULL; + } + static command_rec proxy_cmds[] = { { "ProxyRequests", set_proxy_req, NULL, RSRC_CONF, FLAG, "on if the true proxy requests should be accepted"}, *************** *** 3061,3066 **** --- 3216,3223 ---- "The number of levels of subdirectories in the cache" }, { "CacheDirLength", set_cache_dirlength, NULL, RSRC_CONF, TAKE1, "The number of characters in subdirectory names" }, + { "NoCache", set_cache_exclude, NULL, RSRC_CONF, ITERATE, + "A list of hosts or domains for which caching is *not* provided" }, { NULL } };