]> git.ipfire.org Git - thirdparty/squid.git/commitdiff
Rework the auth forwarding special cases
authorHenrik Nordstrom <henrik@henriknordstrom.net>
Wed, 26 Aug 2009 11:43:52 +0000 (13:43 +0200)
committerHenrik Nordstrom <henrik@henriknordstrom.net>
Wed, 26 Aug 2009 11:43:52 +0000 (13:43 +0200)
The auth forwarding special cases had grown a bit hairy with a lot
of duplicated code between WWW-Auth and Proxy-Auth and far from trivial
to follow code logics.

This change breaks this logic out to a separate function shared
in both modes, selecing mode based on type of peer.

Also moves PROXYPASS back into the land of undocumented features. This
is a feature which most would only get confused by and which can cause
significant security issues if used wrongly.

src/cf.data.pre
src/http.cc

index 382208cc432d9b2341fc751993ede3e576906c4d..a5291db5574086169f4b819efa5ab4271cd67460 100644 (file)
@@ -1797,30 +1797,14 @@ DOC_START
                        Note: This will pass any form of authentication but
                        only Basic auth will work through a proxy unless the
                        connection-auth options are also used.
-       
-       login=PROXYPASS
-                       Send login details received from client to this peer.
-                       Only WWW-Authorization headers are passed to the peer.
-                       If the 'originserver' option is also used this will
-                       convert Proxy-Authorization: to WWW-Authorization: before
-                       relaying. The header content is not altered.
-                       
-                       Authentication is not required by Squid for this to work
-                       however it should be noted that without it somewhere down
-                       the proxy chain there may be no Proxy-Authorization:
-                       header to convert.
-                       
-                       Note: This will pass any form of authentication but
-                       only Basic auth will work through a proxy unless the
-                       connection-auth options are also used.
-       
+
        login=PASS      Send login details received from client to this peer.
                        Authentication is not required by this option.
                        
                        If there are no client-provided authentication headers
                        to pass on, but username and password are available
-                       from either proxy login or an external ACL user= and
-                       password= result tags they may be sent instead.
+                       from an external ACL user= and password= result tags
+                       they may be sent instead.
                        
                        Note: To combine this with proxy_auth both proxies must
                        share the same user database as HTTP only allows for
index 9f51b1ea9b0bf90fccce4a27f8fbe3e4c025eb34..198c3fabcc34c05863a7f9a4a9d46a0d00b1fba0 100644 (file)
@@ -1446,6 +1446,75 @@ HttpStateData::doneWithServer() const
     return fd < 0;
 }
 
+
+/*
+ * Fixup authentication request headers for special cases
+ */
+static void
+httpFixupAuthentication(HttpRequest * request, HttpRequest * orig_request, const HttpHeader * hdr_in, HttpHeader * hdr_out, http_state_flags flags)
+{
+    http_hdr_type header = flags.originpeer ? HDR_AUTHORIZATION : HDR_PROXY_AUTHORIZATION;
+
+    /* Nothing to do unless we are forwarding to a peer */
+    if (!request->flags.proxying)
+       return;
+
+    /* Needs to be explicitly enabled */
+       return;
+
+    /* Maybe already dealt with? */
+    if (hdr_out->has(header))
+       return;
+
+    /* Nothing to do here for PASSTHRU */
+    if (strcmp(orig_request->peer_login, "PASSTHRU") == 0)
+       return;
+
+    /* PROXYPASS is a special case, single-signon to servers with the proxy password (basic only) */
+    if (flags.originpeer && strcmp(orig_request->peer_login, "PROXYPASS") == 0 && hdr_in->has(HDR_PROXY_AUTHORIZATION)) {
+       const char *auth = hdr_in->getStr(HDR_PROXY_AUTHORIZATION);
+
+       if (auth && strncasecmp(auth, "basic ", 6) == 0) {
+           hdr_out->putStr(header, auth);
+           return;
+       }
+    }
+
+    /* Special mode to pass the username to the upstream cache */
+    if (*orig_request->peer_login == '*') {
+       char loginbuf[256];
+       const char *username = "-";
+
+       if (orig_request->extacl_user.size())
+           username = orig_request->extacl_user.termedBuf();
+       else if (orig_request->auth_user_request)
+           username = orig_request->auth_user_request->username();
+
+       snprintf(loginbuf, sizeof(loginbuf), "%s%s", username, orig_request->peer_login + 1);
+
+       httpHeaderPutStrf(hdr_out, HDR_PROXY_AUTHORIZATION, "Basic %s",
+                         base64_encode(loginbuf));
+       return;
+    }
+
+    /* external_acl provided credentials */
+    if (orig_request->extacl_user.size() && orig_request->extacl_passwd.size() &&
+           (strcmp(orig_request->peer_login, "PASS") == 0 ||
+            strcmp(orig_request->peer_login, "PROXYPASS"))) {
+       char loginbuf[256];
+       snprintf(loginbuf, sizeof(loginbuf), SQUIDSTRINGPH ":" SQUIDSTRINGPH,
+                SQUIDSTRINGPRINT(orig_request->extacl_user),
+                SQUIDSTRINGPRINT(orig_request->extacl_passwd));
+       httpHeaderPutStrf(hdr_out, HDR_PROXY_AUTHORIZATION, "Basic %s",
+                         base64_encode(loginbuf));
+       return;
+    }
+
+    httpHeaderPutStrf(hdr_out, HDR_PROXY_AUTHORIZATION, "Basic %s",
+                     base64_encode(orig_request->peer_login));
+    return;
+}
+
 /*
  * build request headers and append them to a given MemBuf
  * used by buildRequestPrefix()
@@ -1576,87 +1645,11 @@ HttpStateData::httpBuildRequestHeader(HttpRequest * request,
         }
     }
 
-    /* append Proxy-Authorization if configured for peer, and proxying */
-    if (request->flags.proxying && orig_request->peer_login &&
-            !hdr_out->has(HDR_PROXY_AUTHORIZATION)) {
-        if (*orig_request->peer_login == '*') {
-            /* Special mode, to pass the username to the upstream cache */
-            char loginbuf[256];
-            const char *username = "-";
-
-            if (orig_request->extacl_user.size())
-                username = orig_request->extacl_user.termedBuf();
-            else if (orig_request->auth_user_request)
-                username = orig_request->auth_user_request->username();
-
-            snprintf(loginbuf, sizeof(loginbuf), "%s%s", username, orig_request->peer_login + 1);
-
-            httpHeaderPutStrf(hdr_out, HDR_PROXY_AUTHORIZATION, "Basic %s",
-                              base64_encode(loginbuf));
-        } else if (strcmp(orig_request->peer_login, "PASS") == 0) {
-            if (orig_request->extacl_user.size() && orig_request->extacl_passwd.size()) {
-                char loginbuf[256];
-                snprintf(loginbuf, sizeof(loginbuf), SQUIDSTRINGPH ":" SQUIDSTRINGPH,
-                         SQUIDSTRINGPRINT(orig_request->extacl_user),
-                         SQUIDSTRINGPRINT(orig_request->extacl_passwd));
-                httpHeaderPutStrf(hdr_out, HDR_PROXY_AUTHORIZATION, "Basic %s",
-                                  base64_encode(loginbuf));
-            }
-        } else if (strcmp(orig_request->peer_login, "PROXYPASS") == 0) {
-            /* Nothing to do */
-        } else if (strcmp(orig_request->peer_login, "PASSTHRU") == 0) {
-            /* Nothing to do (yet) */
-        } else {
-            httpHeaderPutStrf(hdr_out, HDR_PROXY_AUTHORIZATION, "Basic %s",
-                              base64_encode(orig_request->peer_login));
-        }
-    }
-
-    /* append WWW-Authorization if configured for peer */
-    if (flags.originpeer && orig_request->peer_login &&
-            !hdr_out->has(HDR_AUTHORIZATION)) {
-        if (strcmp(orig_request->peer_login, "PASS") == 0) {
-            /* No credentials to forward.. (should have been done above if available) */
-        } else if (strcmp(orig_request->peer_login, "PASSTHRU") == 0) {
-            /* Nothing to do (yet) */
-        } else if (strcmp(orig_request->peer_login, "PROXYPASS") == 0) {
-            /* Special mode, convert proxy authentication to WWW authentication
-            * (also applies to authentication provided by external acl)
-             */
-            const char *auth = hdr_in->getStr(HDR_PROXY_AUTHORIZATION);
-
-            if (auth && strncasecmp(auth, "basic ", 6) == 0) {
-                hdr_out->putStr(HDR_AUTHORIZATION, auth);
-            } else if (orig_request->extacl_user.size() && orig_request->extacl_passwd.size()) {
-                char loginbuf[256];
-                snprintf(loginbuf, sizeof(loginbuf), SQUIDSTRINGPH ":" SQUIDSTRINGPH,
-                         SQUIDSTRINGPRINT(orig_request->extacl_user),
-                         SQUIDSTRINGPRINT(orig_request->extacl_passwd));
-                httpHeaderPutStrf(hdr_out, HDR_AUTHORIZATION, "Basic %s",
-                                  base64_encode(loginbuf));
-            }
-        } else if (*orig_request->peer_login == '*') {
-            /* Special mode, to pass the username to the upstream cache */
-            char loginbuf[256];
-            const char *username = "-";
+    /* Fixup (Proxy-)Authorization special cases. Plain relaying dealt with above */
+    httpFixupAuthentication(request, orig_request, hdr_in, hdr_out, flags);
 
-            if (orig_request->auth_user_request)
-                username = orig_request->auth_user_request->username();
-            else if (orig_request->extacl_user.size())
-                username = orig_request->extacl_user.termedBuf();
-
-            snprintf(loginbuf, sizeof(loginbuf), "%s%s", username, orig_request->peer_login + 1);
-
-            httpHeaderPutStrf(hdr_out, HDR_AUTHORIZATION, "Basic %s",
-                              base64_encode(loginbuf));
-        } else {
-            /* Fixed login string */
-            httpHeaderPutStrf(hdr_out, HDR_AUTHORIZATION, "Basic %s",
-                              base64_encode(orig_request->peer_login));
-        }
-    }
-
-    /* append Cache-Control, add max-age if not there already */ {
+    /* append Cache-Control, add max-age if not there already */
+    {
         HttpHdrCc *cc = hdr_in->getCc();
 
         if (!cc)
@@ -1727,9 +1720,9 @@ copyOneHeaderFromClientsideRequestToUpstreamRequest(const HttpHeaderEntry *e, co
          * Only pass on proxy authentication to peers for which
          * authentication forwarding is explicitly enabled
          */
-        if (flags.proxying && orig_request->peer_login &&
-                (strcmp(orig_request->peer_login, "PASS") == 0 ||
-                 strcmp(orig_request->peer_login, "PASSTHRU") == 0)) {
+        if (!flags.originpeer && flags.proxying && orig_request->peer_login &&
+               (strcmp(orig_request->peer_login, "PASS") == 0 ||
+               strcmp(orig_request->peer_login, "PASSTHRU") == 0)) {
             hdr_out->addEntry(e->clone());
         }
         break;
@@ -1756,8 +1749,7 @@ copyOneHeaderFromClientsideRequestToUpstreamRequest(const HttpHeaderEntry *e, co
             hdr_out->addEntry(e->clone());
         } else {
             /** \note In accelerators, only forward authentication if enabled
-             * by login=PASS or login=PROXYPASS or login=PASSTHRU
-             * (see also below for proxy->server authentication)
+             * (see also httpFixupAuthentication for special cases)
              */
             if (orig_request->peer_login &&
                     (strcmp(orig_request->peer_login, "PASS") == 0 ||