chuck 97/01/05 01:06:11
Modified: src/modules/proxy mod_proxy.c mod_proxy.h proxy_connect.c proxy_ftp.c proxy_http.c Log: Add ProxyBlock directive w/IP address caching. Add IP address caching to NoCache directive as well. ProxyBlock works with all handlers; NoCache now also works with FTP for anonymous logins. Still more code cleanup. Revision Changes Path 1.8 +40 -1 apache/src/modules/proxy/mod_proxy.c Index: mod_proxy.c =================================================================== RCS file: /export/home/cvs/apache/src/modules/proxy/mod_proxy.c,v retrieving revision 1.7 retrieving revision 1.8 diff -C3 -r1.7 -r1.8 *** mod_proxy.c 1997/01/01 18:19:59 1.7 --- mod_proxy.c 1997/01/05 09:06:05 1.8 *************** *** 256,261 **** --- 256,262 ---- ps->proxies = make_array(p, 10, sizeof(struct proxy_remote)); ps->aliases = make_array(p, 10, sizeof(struct proxy_alias)); + ps->noproxies = make_array(p, 10, sizeof(struct noproxy_entry)); ps->nocaches = make_array(p, 10, sizeof(struct nocache_entry)); ps->req = 0; *************** *** 327,332 **** --- 328,364 ---- } static const char * + set_proxy_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 noproxy_entry *new; + struct noproxy_entry *list=(struct noproxy_entry*)conf->noproxies->elts; + int found = 0; + int i; + + /* Don't duplicate entries */ + for (i=0; i < conf->noproxies->nelts; i++) + { + if (strcmp(arg, list[i].name) == 0) + found = 1; + } + + if (!found) + { + new = push_array (conf->noproxies); + new->name = arg; + /* Don't do name lookups on things that aren't dotted */ + if (strchr(arg, '.') != NULL) + proxy_host2addr(new->name, &new->addr); + else + new->addr.s_addr = 0; + } + return NULL; + } + + static const char * set_proxy_req(cmd_parms *parms, void *dummy, int flag) { proxy_server_conf *psf = *************** *** 455,460 **** --- 487,497 ---- { new = push_array (conf->nocaches); new->name = arg; + /* Don't do name lookups on things that aren't dotted */ + if (strchr(arg, '.') != NULL) + proxy_host2addr(new->name, &new->addr); + else + new->addr.s_addr= 0; } return NULL; } *************** *** 471,476 **** --- 508,515 ---- "a scheme, partial URL or '*' and a proxy server"}, { "ProxyPass", add_pass, NULL, RSRC_CONF, TAKE2, "a virtual path and a URL"}, + { "ProxyBlock", set_proxy_exclude, NULL, RSRC_CONF, ITERATE, + "A list of names, hosts or domains to which the proxy will not connect" }, { "CacheRoot", set_cache_root, NULL, RSRC_CONF, TAKE1, "The directory to store cache files"}, { "CacheSize", set_cache_size, NULL, RSRC_CONF, TAKE1, *************** *** 488,494 **** { "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 } }; --- 527,533 ---- { "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 names, hosts or domains for which caching is *not* provided" }, { NULL } }; 1.7 +11 -8 apache/src/modules/proxy/mod_proxy.h Index: mod_proxy.h =================================================================== RCS file: /export/home/cvs/apache/src/modules/proxy/mod_proxy.h,v retrieving revision 1.6 retrieving revision 1.7 diff -C3 -r1.6 -r1.7 *** mod_proxy.h 1997/01/01 18:20:00 1.6 --- mod_proxy.h 1997/01/05 09:06:05 1.7 *************** *** 84,100 **** 2. Add gopher & WAIS ! 3. NoProxy directive for excluding sites to proxy ! 4. Use protocol handler struct a la Apache module handlers (Dirk van Gulik) ! ! 5. Use a cache expiry database for more efficient GC (Jeremy Wohl) ! ! 6. Handle multiple IPs for doconnect() ! 7. Bulletproof GC against SIGALRM ! 8. Make HTTPS and SNEWS ports configurable from a list Chuck Murcko <[EMAIL PROTECTED]> 1 Oct 96 --- 84,96 ---- 2. Add gopher & WAIS ! 3. Use protocol handler struct a la Apache module handlers (Dirk van Gulik) ! 4. Use a cache expiry database for more efficient GC (Jeremy Wohl) ! 5. Handle multiple IPs for doconnect() ! 6. Bulletproof GC against SIGALRM Chuck Murcko <[EMAIL PROTECTED]> 1 Oct 96 *************** *** 157,164 **** --- 153,166 ---- char *fake; }; + struct noproxy_entry { + char *name; + struct in_addr addr; + }; + struct nocache_entry { char *name; + struct in_addr addr; }; #define DEFAULT_CACHE_SPACE 5 *************** *** 184,189 **** --- 186,192 ---- struct cache_conf cache; /* cache configuration */ array_header *proxies; array_header *aliases; + array_header *noproxies; array_header *nocaches; int req; /* true if proxy requests are enabled */ } proxy_server_conf; 1.5 +27 -6 apache/src/modules/proxy/proxy_connect.c Index: proxy_connect.c =================================================================== RCS file: /export/home/cvs/apache/src/modules/proxy/proxy_connect.c,v retrieving revision 1.4 retrieving revision 1.5 diff -C3 -r1.4 -r1.5 *** proxy_connect.c 1997/01/01 18:20:02 1.4 --- proxy_connect.c 1997/01/05 09:06:06 1.5 *************** *** 87,92 **** --- 87,93 ---- proxy_connect_handler(request_rec *r, struct cache_req *c, char *url) { struct sockaddr_in server; + struct in_addr destaddr; const char *host, *err; char *p; int port, sock; *************** *** 94,99 **** --- 95,105 ---- int nbytes, i; fd_set fds; + void *sconf = r->server->module_config; + proxy_server_conf *conf = + (proxy_server_conf *)get_module_config(sconf, &proxy_module); + struct noproxy_entry *npent=(struct noproxy_entry *)conf->noproxies->elts; + memset(&server, '\0', sizeof(server)); server.sin_family=AF_INET; *************** *** 101,113 **** 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: --- 107,129 ---- host = url; p = strchr(url, ':'); ! if (p==NULL) ! port = DEFAULT_HTTPS_PORT; else { port = atoi(p+1); *p='\0'; } + /* check if ProxyBlock directive on this host */ + inet_aton(host, &destaddr); + for (i=0; i < conf->noproxies->nelts; i++) + { + if ((npent[i].name != NULL && strstr(host, npent[i].name) != NULL) + || destaddr.s_addr == npent[i].addr.s_addr || npent[i].name[0] == '*') + return proxyerror(r, "Connect to remote machine blocked"); + } + switch (port) { case DEFAULT_HTTPS_PORT: *************** *** 121,127 **** server.sin_port = htons(port); err = proxy_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) --- 137,144 ---- server.sin_port = htons(port); err = proxy_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) *************** *** 164,171 **** 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; --- 181,190 ---- 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; *************** *** 176,183 **** 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; --- 195,204 ---- 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; 1.6 +47 -19 apache/src/modules/proxy/proxy_ftp.c Index: proxy_ftp.c =================================================================== RCS file: /export/home/cvs/apache/src/modules/proxy/proxy_ftp.c,v retrieving revision 1.5 retrieving revision 1.6 diff -C3 -r1.5 -r1.6 *** proxy_ftp.c 1997/01/01 18:20:02 1.5 --- proxy_ftp.c 1997/01/05 09:06:06 1.6 *************** *** 110,120 **** proxy_ftp_canon(request_rec *r, char *url) { char *user, *password, *host, *path, *parms, *p, sport[7]; const char *err; int port; port = DEFAULT_FTP_PORT; ! err = proxy_canon_netloc(r->pool, &url, &user, &password, &host, &port); if (err) return BAD_REQUEST; if (user != NULL && !ftp_check_string(user)) return BAD_REQUEST; if (password != NULL && !ftp_check_string(password)) return BAD_REQUEST; --- 110,121 ---- proxy_ftp_canon(request_rec *r, char *url) { char *user, *password, *host, *path, *parms, *p, sport[7]; + pool *pool=r->pool; const char *err; int port; port = DEFAULT_FTP_PORT; ! err = proxy_canon_netloc(pool, &url, &user, &password, &host, &port); if (err) return BAD_REQUEST; if (user != NULL && !ftp_check_string(user)) return BAD_REQUEST; if (password != NULL && !ftp_check_string(password)) return BAD_REQUEST; *************** *** 129,140 **** if (p != NULL) { *(p++) = '\0'; ! parms = proxy_canonenc(r->pool, p, strlen(p), enc_parm, r->proxyreq); if (parms == NULL) return BAD_REQUEST; } else parms = ""; ! path = proxy_canonenc(r->pool, url, strlen(url), enc_path, r->proxyreq); if (path == NULL) return BAD_REQUEST; if (!ftp_check_string(path)) return BAD_REQUEST; --- 130,141 ---- if (p != NULL) { *(p++) = '\0'; ! parms = proxy_canonenc(pool, p, strlen(p), enc_parm, r->proxyreq); if (parms == NULL) return BAD_REQUEST; } else parms = ""; ! path = proxy_canonenc(pool, url, strlen(url), enc_path, r->proxyreq); if (path == NULL) return BAD_REQUEST; if (!ftp_check_string(path)) return BAD_REQUEST; *************** *** 142,156 **** { if (p != NULL) { ! p = proxy_canonenc(r->pool, r->args, strlen(r->args), enc_parm, 1); if (p == NULL) return BAD_REQUEST; ! parms = pstrcat(r->pool, parms, "?", p, NULL); } else { ! p = proxy_canonenc(r->pool, r->args, strlen(r->args), enc_path, 1); if (p == NULL) return BAD_REQUEST; ! path = pstrcat(r->pool, path, "?", p, NULL); } r->args = NULL; } --- 143,157 ---- { if (p != NULL) { ! p = proxy_canonenc(pool, r->args, strlen(r->args), enc_parm, 1); if (p == NULL) return BAD_REQUEST; ! parms = pstrcat(pool, parms, "?", p, NULL); } else { ! p = proxy_canonenc(pool, r->args, strlen(r->args), enc_path, 1); if (p == NULL) return BAD_REQUEST; ! path = pstrcat(pool, path, "?", p, NULL); } r->args = NULL; } *************** *** 160,166 **** if (port != DEFAULT_FTP_PORT) sprintf(sport, ":%d", port); else sport[0] = '\0'; ! r->filename = pstrcat(r->pool, "proxy:ftp://", (user != NULL) ? user : "", (password != NULL) ? ":" : "", (password != NULL) ? password : "", (user != NULL) ? "@" : "", host, sport, "/", path, --- 161,167 ---- if (port != DEFAULT_FTP_PORT) sprintf(sport, ":%d", port); else sport[0] = '\0'; ! r->filename = pstrcat(pool, "proxy:ftp://", (user != NULL) ? user : "", (password != NULL) ? ":" : "", (password != NULL) ? password : "", (user != NULL) ? "@" : "", host, sport, "/", path, *************** *** 333,342 **** { char *host, *path, *p, *user, *password, *parms; const char *err; ! int port, userlen, passlen, i, len, sock, dsock, rc, nocache; int csd = 0; struct sockaddr_in server; struct hdr_entry *hdr; array_header *resp_hdrs; BUFF *f, *cache; BUFF *data = NULL; --- 334,345 ---- { char *host, *path, *p, *user, *password, *parms; const char *err; ! int port, userlen, i, len, sock, dsock, rc, nocache; ! int passlen = 0; int csd = 0; struct sockaddr_in server; struct hdr_entry *hdr; + struct in_addr destaddr; array_header *resp_hdrs; BUFF *f, *cache; BUFF *data = NULL; *************** *** 344,349 **** --- 347,358 ---- const int one=1; 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 noproxy_entry *npent=(struct noproxy_entry *)conf->noproxies->elts; + struct nocache_entry *ncent=(struct nocache_entry *)conf->nocaches->elts; + /* stuff for PASV mode */ unsigned int presult, h0, h1, h2, h3, p0, p1; unsigned int paddr; *************** *** 353,376 **** char pasv[64]; char *pstr; - /* This appears to fix a bug(?) that generates an "Address family not - supported by protocol" error in proxy_doconnect() later (along with - making sure server.sin_family = AF_INET - cdm) */ - memset(&server, 0, sizeof(struct sockaddr_in)); - /* we only support GET and HEAD */ if (r->method_number != M_GET) return NOT_IMPLEMENTED; - host = pstrdup(r->pool, url+6); /* We break the URL into host, port, path-search */ port = DEFAULT_FTP_PORT; path = strchr(host, '/'); ! if (path == NULL) path = ""; ! else *(path++) = '\0'; user = password = NULL; nocache = 0; - passlen=0; /* not actually needed, but it shuts the compiler up */ p = strchr(host, '@'); if (p != NULL) { --- 362,383 ---- char pasv[64]; char *pstr; /* we only support GET and HEAD */ + if (r->method_number != M_GET) return NOT_IMPLEMENTED; /* We break the URL into host, port, path-search */ + + host = pstrdup(pool, url + 6); port = DEFAULT_FTP_PORT; path = strchr(host, '/'); ! if (path == NULL) ! path = ""; ! else ! *(path++) = '\0'; user = password = NULL; nocache = 0; p = strchr(host, '@'); if (p != NULL) { *************** *** 400,406 **** if (p != NULL) { *(p++) = '\0'; ! port = atoi(p); } Explain2("FTP: connect to %s:%d",host,port); --- 407,423 ---- if (p != NULL) { *(p++) = '\0'; ! if (isdigit(*p)) ! port = atoi(p); ! } ! ! /* check if ProxyBlock directive on this host */ ! inet_aton(host, &destaddr); ! for (i=0; i < conf->noproxies->nelts; i++) ! { ! if ((npent[i].name != NULL && strstr(host, npent[i].name) != NULL) ! || destaddr.s_addr == npent[i].addr.s_addr || npent[i].name[0] == '*') ! return proxyerror(r, "Connect to remote machine blocked"); } Explain2("FTP: connect to %s:%d",host,port); *************** *** 408,413 **** --- 425,431 ---- parms = strchr(path, ';'); if (parms != NULL) *(parms++) = '\0'; + memset(&server, 0, sizeof(struct sockaddr_in)); server.sin_family = AF_INET; server.sin_port = htons(port); err = proxy_host2addr(host, &server.sin_addr); *************** *** 752,758 **** --- 770,786 ---- proxy_add_header(resp_hdrs, "Content-Type", "text/plain", HDR_REP); } } + + /* check if NoCache directive on this host */ + for (i=0; i < conf->nocaches->nelts; i++) + { + if ((ncent[i].name != NULL && strstr(host, ncent[i].name) != NULL) + || destaddr.s_addr == ncent[i].addr.s_addr || ncent[i].name[0] == '*') + nocache = 1; + } + i = proxy_cache_update(c, resp_hdrs, "FTP", nocache); + if (i != DECLINED) { pclosef(pool, dsock); 1.11 +14 -3 apache/src/modules/proxy/proxy_http.c Index: proxy_http.c =================================================================== RCS file: /export/home/cvs/apache/src/modules/proxy/proxy_http.c,v retrieving revision 1.10 retrieving revision 1.11 diff -C3 -r1.10 -r1.11 *** proxy_http.c 1997/01/01 18:20:02 1.10 --- proxy_http.c 1997/01/05 09:06:07 1.11 *************** *** 147,152 **** --- 147,153 ---- array_header *reqhdrs_arr, *resp_hdrs; table_entry *reqhdrs; struct sockaddr_in server; + struct in_addr destaddr; BUFF *f, *cache; struct hdr_entry *hdr; char buffer[HUGE_STRING_LEN], inprotocol[9], outprotocol[9]; *************** *** 158,164 **** 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)); --- 159,166 ---- void *sconf = r->server->module_config; proxy_server_conf *conf = (proxy_server_conf *)get_module_config(sconf, &proxy_module); ! struct noproxy_entry *npent=(struct noproxy_entry *)conf->noproxies->elts; ! struct nocache_entry *ncent=(struct nocache_entry *)conf->nocaches->elts; int nocache = 0; memset(&server, '\0', sizeof(server)); *************** *** 193,198 **** --- 195,209 ---- } } + /* check if ProxyBlock directive on this host */ + inet_aton(desthost, &destaddr); + for (i=0; i < conf->noproxies->nelts; i++) + { + if ((npent[i].name != NULL && strstr(desthost, npent[i].name) != NULL) + || destaddr.s_addr == npent[i].addr.s_addr || npent[i].name[0] == '*') + return proxyerror(r, "Connect to remote machine blocked"); + } + if (proxyhost != NULL) { url = r->uri; /* restore original URL */ *************** *** 323,330 **** /* check if NoCache directive on this host */ for (i=0; i < conf->nocaches->nelts; i++) { ! if ((ent[i].name != NULL && strstr(desthost, ent[i].name) != NULL) ! || ent[i].name[0] == '*') nocache = 1; } --- 334,341 ---- /* check if NoCache directive on this host */ for (i=0; i < conf->nocaches->nelts; i++) { ! if ((ncent[i].name != NULL && strstr(desthost, ncent[i].name) != NULL) ! || destaddr.s_addr == ncent[i].addr.s_addr || ncent[i].name[0] == '*') nocache = 1; }