Repository: trafficserver Updated Branches: refs/heads/master b99b8157b -> 38b4765a2
TS-2722 Eliminate the host lookup state, just use the client IP with TSHttpConnect Project: http://git-wip-us.apache.org/repos/asf/trafficserver/repo Commit: http://git-wip-us.apache.org/repos/asf/trafficserver/commit/083e21b0 Tree: http://git-wip-us.apache.org/repos/asf/trafficserver/tree/083e21b0 Diff: http://git-wip-us.apache.org/repos/asf/trafficserver/diff/083e21b0 Branch: refs/heads/master Commit: 083e21b03063264ecb343abb2d35014e8f80b6a4 Parents: b99b815 Author: Leif Hedstrom <[email protected]> Authored: Wed Jul 30 14:42:52 2014 -0600 Committer: Leif Hedstrom <[email protected]> Committed: Fri Aug 15 12:08:34 2014 -0600 ---------------------------------------------------------------------- plugins/experimental/authproxy/authproxy.cc | 135 ++++++----------------- 1 file changed, 34 insertions(+), 101 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/trafficserver/blob/083e21b0/plugins/experimental/authproxy/authproxy.cc ---------------------------------------------------------------------- diff --git a/plugins/experimental/authproxy/authproxy.cc b/plugins/experimental/authproxy/authproxy.cc index fd6c112..ae20a31 100644 --- a/plugins/experimental/authproxy/authproxy.cc +++ b/plugins/experimental/authproxy/authproxy.cc @@ -43,7 +43,9 @@ using std::strlen; struct AuthRequestContext; -typedef bool(*AuthRequestTransform) (AuthRequestContext* auth, const sockaddr* saddr); +typedef bool(*AuthRequestTransform) (AuthRequestContext* auth); + +const static int MAX_HOST_LENGTH = 4096; // We can operate in global plugin mode or remap plugin mode. If we are in // global mode, then we will authorize every request. In remap mode, we will @@ -56,12 +58,13 @@ static TSCont AuthOsDnsContinuation; struct AuthOptions { char* hostname; + int hostname_len; int hostport; bool force; AuthRequestTransform transform; AuthOptions(): - hostname(NULL), hostport(8080), force(false), transform(NULL) + hostname(NULL), hostname_len(-1), hostport(-1), force(false), transform(NULL) { } ~AuthOptions() @@ -88,7 +91,6 @@ struct StateTransition }; static TSEvent StateAuthProxyConnect(AuthRequestContext*, void*); -static TSEvent StateAuthProxyResolve(AuthRequestContext*, void*); static TSEvent StateAuthProxyWriteComplete(AuthRequestContext*, void*); static TSEvent StateUnauthorized(AuthRequestContext*, void*); static TSEvent StateAuthorized(AuthRequestContext*, void*); @@ -140,7 +142,6 @@ static const StateTransition StateTableProxyReadHeader[] = { // State table for sending the request to the auth proxy. static const StateTransition StateTableProxyRequest[] = { - { TS_EVENT_HOST_LOOKUP, StateAuthProxyConnect, StateTableProxyRequest}, { TS_EVENT_VCONN_WRITE_COMPLETE, StateAuthProxyWriteComplete, StateTableProxyReadHeader }, { TS_EVENT_ERROR, StateUnauthorized, NULL }, { TS_EVENT_NONE, NULL, NULL } @@ -148,7 +149,7 @@ static const StateTransition StateTableProxyRequest[] = { // Initial state table. static const StateTransition StateTableInit[] = { - { TS_EVENT_HTTP_OS_DNS, StateAuthProxyResolve, StateTableProxyRequest }, + { TS_EVENT_HTTP_OS_DNS, StateAuthProxyConnect, StateTableProxyRequest }, { TS_EVENT_ERROR, StateUnauthorized, NULL }, { TS_EVENT_NONE, NULL, NULL } }; @@ -288,7 +289,7 @@ AuthChainAuthorizationResponse(AuthRequestContext* auth) // Transform the client request into a HEAD request and write it out. static bool -AuthWriteHeadRequest(AuthRequestContext* auth, const sockaddr* /* saddr ATS_UNUSED */ ) +AuthWriteHeadRequest(AuthRequestContext* auth) { HttpHeader rq; TSMBuffer mbuf; @@ -322,29 +323,20 @@ AuthWriteHeadRequest(AuthRequestContext* auth, const sockaddr* /* saddr ATS_UNUS // Transform the client request into a form that the auth proxy can consume and // write it out. static bool -AuthWriteRedirectedRequest(AuthRequestContext* auth, const sockaddr* saddr) +AuthWriteRedirectedRequest(AuthRequestContext* auth) { + const AuthOptions* options = auth->options(); HttpHeader rq; TSMBuffer mbuf; TSMLoc mhdr; TSMLoc murl; - char addrbuf[INET6_ADDRSTRLEN]; - char hostbuf[INET6_ADDRSTRLEN + sizeof("[]") + sizeof(":65536")]; - uint16_t hostport; + char hostbuf[MAX_HOST_LENGTH + 1]; TSReleaseAssert(TSHttpTxnClientReqGet(auth->txn, &mbuf, &mhdr) == TS_SUCCESS); // First, copy the whole client request to our new auth proxy request. TSReleaseAssert(TSHttpHdrCopy(rq.buffer, rq.header, mbuf, mhdr) == TS_SUCCESS); - hostport = SockaddrGetPort(saddr); - inet_ntop(saddr->sa_family, SockaddrGetAddress(saddr), addrbuf, sizeof(addrbuf)); - if (saddr->sa_family == PF_INET6) { - snprintf(hostbuf, sizeof(hostbuf), "[%s]:%d", addrbuf, hostport); - } else { - snprintf(hostbuf, sizeof(hostbuf), "%s:%d", addrbuf, hostport); - } - // Next, we need to rewrite the client request URL so that the request goes to // the auth proxy instead of the original request. TSReleaseAssert(TSHttpHdrUrlGet(rq.buffer, rq.header, &murl) == TS_SUCCESS); @@ -353,8 +345,14 @@ AuthWriteRedirectedRequest(AuthRequestContext* auth, const sockaddr* saddr) // scheme, forcing ATS to go to the Host header. I wonder how HTTPS would // work in that case. At any rate, we should add a new header containing // the original host so that the auth proxy can examine it. - TSUrlHostSet(rq.buffer, murl, addrbuf, -1); - TSUrlPortSet(rq.buffer, murl, hostport); + TSUrlHostSet(rq.buffer, murl, options->hostname, options->hostname_len); + if (-1 != options->hostport) { + snprintf(hostbuf, sizeof(hostbuf), "%s:%d", options->hostname, options->hostport); + TSUrlPortSet(rq.buffer, murl, options->hostport); + } else { + snprintf(hostbuf, sizeof(hostbuf), "%s", options->hostname); + } + TSHandleMLocRelease(rq.buffer, rq.header, murl); HttpSetMimeHeader(rq.buffer, rq.header, TS_MIME_FIELD_HOST, hostbuf); @@ -372,86 +370,23 @@ AuthWriteRedirectedRequest(AuthRequestContext* auth, const sockaddr* saddr) } static TSEvent -StateAuthProxyResolve(AuthRequestContext* auth, void*) -{ - TSAction lookup; - const AuthOptions* options = auth->options(); - - // If we are authorizing with a HEAD request we want to send that to the - // origin; other requests we want to send to the authorization proxy. - if (options->transform == AuthWriteHeadRequest) { - char hostname[TS_MAX_HOST_NAME_LEN * 2]; - TSMBuffer mbuf; - TSMLoc mhdr; - - TSReleaseAssert(TSHttpTxnClientReqGet(auth->txn, &mbuf, &mhdr) == TS_SUCCESS); - - if (HttpGetOriginHost(mbuf, mhdr, hostname, sizeof(hostname))) { - AuthLogDebug("resolving authorization host %s", hostname); - lookup = TSHostLookup(auth->cont, hostname, strlen(hostname)); - TSHandleMLocRelease(mbuf, TS_NULL_MLOC, mhdr); - } else { - AuthLogError("failed to extract origin host name from client request"); - TSHandleMLocRelease(mbuf, TS_NULL_MLOC, mhdr); - return TS_EVENT_ERROR; - } - - } else { - AuthLogDebug("resolving authorization proxy host %s", options->hostname); - lookup = TSHostLookup(auth->cont, options->hostname, strlen(options->hostname)); - } - - if (TSActionDone(lookup)) { - AuthLogDebug("host lookup was executed in line"); - return TS_EVENT_NONE; - } - - return TS_EVENT_CONTINUE; -} - -static TSEvent StateAuthProxyConnect(AuthRequestContext* auth, void* edata) { const AuthOptions* options = auth->options(); - TSHostLookupResult dns; - const sockaddr* saddr; + struct sockaddr const* ip = TSHttpTxnClientAddrGet(auth->txn); - union - { - sockaddr sa; - sockaddr_in sin; - sockaddr_in6 sin6; - sockaddr_storage storage; - } addr; - - dns = (TSHostLookupResult) edata; - if (dns == NULL) { - AuthLogError("failed to resolve authorization proxy at %s", options->hostname); - return TS_EVENT_ERROR; - } - // Copy the resolved address and add the port. - saddr = TSHostLookupResultAddrGet(dns); - switch (saddr->sa_family) { - case PF_INET: - memcpy(&addr.sin, saddr, sizeof(sockaddr_in)); - addr.sin.sin_port = options->hostport; - break; - case PF_INET6: - memcpy(&addr.sin6, saddr, sizeof(sockaddr_in6)); - addr.sin6.sin6_port = options->hostport; - break; - } + TSReleaseAssert(ip); // We must have a client IP. auth->is_head = AuthRequestIsHead(auth->txn); AuthLogDebug("client request %s a HEAD request", auth->is_head ? "is" : "is not"); - auth->vconn = TSHttpConnect(&addr.sa); + auth->vconn = TSHttpConnect(ip); if (auth->vconn == NULL) { return TS_EVENT_ERROR; } // Transform the client request into an auth proxy request and write it // out to the auth proxy vconn. - if (!options->transform(auth, &addr.sa)) { + if (!options->transform(auth)) { return TS_EVENT_ERROR; } // Start a write and transition to WriteAuthProxyState. @@ -677,35 +612,29 @@ static int AuthProxyGlobalHook(TSCont /* cont ATS_UNUSED */ , TSEvent event, void* edata) { AuthRequestContext* auth; - union - { - TSHostLookupResult dns; - TSHttpTxn txn; - void* edata; - } ptr; + TSHttpTxn txn = (TSHttpTxn)edata; - ptr.edata = edata; AuthLogDebug("handling event=%d edata=%p", (int) event, edata); switch (event) { case TS_EVENT_HTTP_OS_DNS: // Ignore internal requests since we generated them. - if (TSHttpIsInternalRequest(ptr.txn) == TS_SUCCESS) { + if (TSHttpIsInternalRequest(txn) == TS_SUCCESS) { // All our internal requests *must* hit the origin since it is the // agent that needs to make the authorization decision. We can't // allow that to be cached. - TSHttpTxnReqCacheableSet(ptr.txn, 0); + TSHttpTxnReqCacheableSet(txn, 0); AuthLogDebug("re-enabling internal transaction"); - TSHttpTxnReenable(ptr.txn, TS_EVENT_HTTP_CONTINUE); + TSHttpTxnReenable(txn, TS_EVENT_HTTP_CONTINUE); return TS_EVENT_NONE; } // Hook this request if we are in global authorization mode or if a // remap rule tagged it. - if (AuthGlobalOptions != NULL || AuthRequestIsTagged(ptr.txn)) { + if (AuthGlobalOptions != NULL || AuthRequestIsTagged(txn)) { auth = AuthRequestContext::allocate(); auth->state = StateTableInit; - auth->txn = ptr.txn; + auth->txn = txn; return AuthRequestContext::dispatch(auth->cont, event, edata); } // fallthru @@ -733,7 +662,6 @@ AuthParseOptions(int argc, const char** argv) AuthOptions* options = AuthNew<AuthOptions>(); options->transform = AuthWriteRedirectedRequest; - options->hostname = TSstrdup("127.0.0.1"); // We might parse arguments multiple times if we are loaded as a global // plugin and a remap plugin. Reset optind so that getopt_long() does the @@ -746,7 +674,7 @@ AuthParseOptions(int argc, const char** argv) opt = getopt_long(argc, (char* const *) argv, "", longopt, NULL); switch (opt) { case 'h': - TSfree(options->hostname); + TSfree(options->hostname); // Probably isn't set, but safe to always free options->hostname = TSstrdup(optarg); break; case 'p': @@ -773,6 +701,11 @@ AuthParseOptions(int argc, const char** argv) } } + if (NULL == options->hostname) { + options->hostname = TSstrdup("127.0.0.1"); + } + options->hostname_len = strlen(options->hostname); + return options; }
