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 }
};