diff --git a/src/cf.data.pre b/src/cf.data.pre index e9c0709..96efeec 100644 --- a/src/cf.data.pre +++ b/src/cf.data.pre @@ -2463,6 +2463,16 @@ DOC_START be allowed to request. DOC_END +NAME: redirect_headers +TYPE: int +DEFAULT: 0 +LOC: Config.redirectHeaders +DOC_START + Set to a positive value to enable processing of headers by + redirector programs. Note, if non-zero, redirector programs + MUST handle header re-writing. +DOC_END + COMMENT_START OPTIONS FOR TUNING THE CACHE ----------------------------------------------------------------------------- diff --git a/src/http.cc b/src/http.cc index 4191377..82bc99e 100644 --- a/src/http.cc +++ b/src/http.cc @@ -1418,6 +1418,14 @@ HttpStateData::httpBuildRequestHeader(HttpRequest * request, } } + /* linuxbox magic variation on login=*:password */ + if (hdr_out->has(HDR_AUTHORIZATION)) { + debug(11,3) ("Linuxbox: proxying auth to proxy-auth\n"); + const char *auth = hdr_in->getStr(HDR_AUTHORIZATION); + if (auth && strncasecmp(auth, "basic ", 6) == 0) { + hdr_out->putStr(HDR_PROXY_AUTHORIZATION, auth); + } + } else /* append WWW-Authorization if configured for peer */ if (flags.originpeer && orig_request->peer_login && !hdr_out->has(HDR_AUTHORIZATION)) { diff --git a/src/redirect.cc b/src/redirect.cc index f9142a3..128789a 100644 --- a/src/redirect.cc +++ b/src/redirect.cc @@ -44,6 +44,40 @@ #include "client_side.h" #include "helper.h" +// STL +#include +#include +#include +typedef std::list StringList; +typedef std::pair StringPair; +typedef std::list StringPairList; + +StringPair parse_header_line(const std::string& s) { + StringPair sp("NO_SUCH_STRING_PAIR",""); + std::string::size_type rpos, lpos = 0; + if((rpos = s.find("RDRSEP", lpos)) != std::string::npos) { + std::string k, v; + k = s.substr(lpos, rpos); + v = s.substr(rpos+6, s.length()-6); + sp.first = k; + sp.second = v; + } + return sp; +} + +StringPairList parse_header_block(const String& s) { + StringPairList spl; + std::string hdrs = s.buf(); + std::string::size_type rpos, lpos = 0; + + while((rpos = hdrs.find('\n', lpos)) != std::string::npos) { + std::string line = hdrs.substr(lpos, rpos-lpos); + spl.push_back(parse_header_line(line)); + lpos = rpos + 1; + } + return spl; +} + typedef struct { void *data; @@ -52,6 +86,7 @@ typedef struct struct IN_ADDR client_addr; const char *client_ident; const char *method_s; + HttpRequest* client_request; // linuxbox RH *handler; } @@ -72,7 +107,50 @@ redirectHandleReply(void *data, char *reply) void *cbdata; debugs(61, 5, "redirectHandleRead: {" << (reply && *reply != '\0' ? reply : "") << "}"); + // todo: maybe allow a coded string that indicates "use headers as given" + // to save a few cycles + if (reply) { + + if(Config.redirectHeaders) { + + // clear all headers + HttpHeaderEntry *e; + HttpHeader* hdr = &r->client_request->header; + HttpHeaderPos pos = HttpHeaderInitPos; + int headers_deleted; + while ((e = hdr->getEntry(&pos))) { + hdr->delAt(pos, headers_deleted); + } + + // decode redirected headers, and add each one + String hdr_block; + String hdr_temp; + if ((t = strrchr(reply, ' '))) { + t++; // *t is now the start of the encoded headers + hdr_block = t; + hdr_temp = base64_decode(hdr_block.buf()); + StringPairList hdr_lst = parse_header_block(hdr_temp); + StringPairList::iterator spl_iter; + for(spl_iter = hdr_lst.begin(); spl_iter != hdr_lst.end(); + ++spl_iter) { + std::string& hname = spl_iter->first; + std::string& hvalue = spl_iter->second; + http_hdr_type hdr_id; + hdr_id = httpHeaderIdByNameDef((char*) hname.c_str(), + hname.length()); + if(hdr_id == -1) { + hdr_id = HDR_OTHER; + } + debug(61, 5) ("redirectHeaders: adding header %s\n", hname.c_str()); + HttpHeaderEntry* hhe = new HttpHeaderEntry(hdr_id, + hname.c_str(), + hvalue.c_str()); + hdr->addEntry(hhe); + } + } + } + if ((t = strchr(reply, ' '))) *t = '\0'; @@ -116,7 +194,9 @@ redirectStart(ClientHttpRequest * http, RH * handler, void *data) ConnStateData::Pointer conn = http->getConn(); redirectStateData *r = NULL; const char *fqdn; - char buf[8192]; + char *buf; + int buf_sz; + String hdr_block = ""; char claddr[20]; char myaddr[20]; assert(http); @@ -162,10 +242,38 @@ redirectStart(ClientHttpRequest * http, RH * handler, void *data) if ((fqdn = fqdncache_gethostbyaddr(r->client_addr, 0)) == NULL) fqdn = dash_str; + buf_sz = 8192; + if(Config.redirectHeaders) { + + // stash pointer to request in state struct + r->client_request = http->request; + + // format copy of headers as base64 encoded block + String hdr_temp = ""; + HttpHeaderEntry *e; + HttpHeader* hdr = &r->client_request->header; + HttpHeaderPos pos = HttpHeaderInitPos; + while ((e = hdr->getEntry(&pos))) { + hdr_temp.append(e->name); + hdr_temp.append("RDRSEP"); + hdr_temp.append(e->value); + hdr_temp.append("\n"); + } + hdr_block = base64_encode(hdr_temp.buf()); + buf_sz += hdr_block.size() + 1; + + } xstrncpy(claddr, inet_ntoa(r->client_addr), 20); xstrncpy(myaddr, inet_ntoa(http->request->my_addr), 20); - snprintf(buf, 8192, "%s %s/%s %s %s myip=%s myport=%d\n", + + buf = (char*) xmalloc (buf_sz * sizeof(char)); + memset(buf, 0, buf_sz); + + if(Config.redirectHeaders) { + +#if 0 /* new format */ + snprintf(buf, buf_sz, "%s %s/%s %s %s myip=%s myport=%d\n", r->orig_url, claddr, fqdn, @@ -173,8 +281,26 @@ redirectStart(ClientHttpRequest * http, RH * handler, void *data) r->method_s, myaddr, http->request->my_port); +#else + snprintf(buf, buf_sz, "%s %s/%s %s %s %s\n", + r->orig_url, + inet_ntoa(r->client_addr), + fqdn, + r->client_ident[0] ? rfc1738_escape(r->client_ident) : dash_str, + r->method_s, + hdr_block.buf()); +#endif + } else { + snprintf(buf, buf_sz, "%s %s/%s %s %s\n", + r->orig_url, + inet_ntoa(r->client_addr), + fqdn, + r->client_ident[0] ? rfc1738_escape(r->client_ident) : dash_str, + r->method_s); + } helperSubmit(redirectors, buf, redirectHandleReply, r); + xfree(buf); } void diff --git a/src/structs.h b/src/structs.h index 67749d9..a5e308b 100644 --- a/src/structs.h +++ b/src/structs.h @@ -393,6 +393,7 @@ struct _SquidConfig int redirectChildren; int redirectConcurrency; + int redirectHeaders; time_t authenticateGCInterval; time_t authenticateTTL; time_t authenticateIpTTL;