]> git.ipfire.org Git - thirdparty/squid.git/commitdiff
* ext_user acl type to match user name returned by external acl
authorhno <>
Sat, 28 Jun 2003 04:32:30 +0000 (04:32 +0000)
committerhno <>
Sat, 28 Jun 2003 04:32:30 +0000 (04:32 +0000)
* cleanup of how external acls present a user name to the
  Squid core to make the code more logical and fix a
  minor security issues if there is downstream proxies.

* concept of password returned by external acl type. Integrated
  with login= cache_peer option to have the password forwarded
  to peers (both proxies and origin type peers)

12 files changed:
src/ACLExtUser.cc [new file with mode: 0644]
src/ACLExtUser.h [new file with mode: 0644]
src/ExternalACLEntry.cc
src/ExternalACLEntry.h
src/HttpRequest.cc
src/Makefile.am
src/access_log.cc
src/client_side.cc
src/client_side_request.cc
src/external_acl.cc
src/http.cc
src/structs.h

diff --git a/src/ACLExtUser.cc b/src/ACLExtUser.cc
new file mode 100644 (file)
index 0000000..9def4ed
--- /dev/null
@@ -0,0 +1,133 @@
+/*
+ * $Id: ACLExtUser.cc,v 1.1 2003/06/27 22:32:31 hno Exp $
+ *
+ * DEBUG: section 28    Access Control
+ * AUTHOR: Duane Wessels
+ *
+ * SQUID Web Proxy Cache          http://www.squid-cache.org/
+ * ----------------------------------------------------------
+ *
+ *  Squid is the result of efforts by numerous individuals from
+ *  the Internet community; see the CONTRIBUTORS file for full
+ *  details.   Many organizations have provided support for Squid's
+ *  development; see the SPONSORS file for full details.  Squid is
+ *  Copyrighted (C) 2001 by the Regents of the University of
+ *  California; see the COPYRIGHT file for full details.  Squid
+ *  incorporates software developed and/or copyrighted by other
+ *  sources; see the CREDITS file for full details.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *  
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *  
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA.
+ *
+ *
+ * Copyright (c) 2003, Robert Collins <robertc@squid-cache.org>
+ */
+
+#include "squid.h"
+#include "ACLExtUser.h"
+#include "authenticate.h"
+#include "ACLChecklist.h"
+#include "ACLRegexData.h"
+#include "ACLUserData.h"
+#include "client_side.h"
+
+MemPool *ACLExtUser::Pool(NULL);
+void *
+ACLExtUser::operator new (size_t byteCount)
+{
+    /* derived classes with different sizes must implement their own new */
+    assert (byteCount == sizeof (ACLExtUser));
+
+    if (!Pool)
+        Pool = memPoolCreate("ACLExtUser", sizeof (ACLExtUser));
+
+    return memPoolAlloc(Pool);
+}
+
+void
+ACLExtUser::operator delete (void *address)
+{
+    memPoolFree (Pool, address);
+}
+
+void
+ACLExtUser::deleteSelf() const
+{
+    delete this;
+}
+
+ACLExtUser::~ACLExtUser()
+{
+    data->deleteSelf();
+}
+
+ACLExtUser::ACLExtUser(ACLData<char const *> *newData, char const *newType) : data (newData), type_ (newType) {}
+
+ACLExtUser::ACLExtUser (ACLExtUser const &old) : data (old.data->clone()), type_ (old.type_)
+{}
+
+ACLExtUser &
+ACLExtUser::operator= (ACLExtUser const &rhs)
+{
+    data = rhs.data->clone();
+    type_ = rhs.type_;
+    return *this;
+}
+
+char const *
+ACLExtUser::typeString() const
+{
+    return type_;
+}
+
+void
+ACLExtUser::parse()
+{
+    debug(28, 3) ("aclParseUserList: current is null. Creating\n");
+    data = new ACLUserData;
+    data->parse();
+}
+
+int
+ACLExtUser::match(ACLChecklist *checklist)
+{
+    if (checklist->request->extacl_user.size()) {
+        return data->match(checklist->request->extacl_user.buf());
+    } else {
+        return -1;
+    }
+}
+
+wordlist *
+ACLExtUser::dump() const
+{
+    return data->dump();
+}
+
+bool
+ACLExtUser::valid () const
+{
+    return data != NULL;
+}
+
+ACL *
+ACLExtUser::clone() const
+{
+    return new ACLExtUser(*this);
+}
+
+ACL::Prototype ACLExtUser::UserRegistryProtoype(&ACLExtUser::UserRegistryEntry_, "ext_user");
+ACLExtUser ACLExtUser::UserRegistryEntry_(new ACLUserData, "ext_user");
+ACL::Prototype ACLExtUser::RegexRegistryProtoype(&ACLExtUser::RegexRegistryEntry_, "ext_user_regex" );
+ACLExtUser ACLExtUser::RegexRegistryEntry_(new ACLRegexData, "ext_user_regex");
diff --git a/src/ACLExtUser.h b/src/ACLExtUser.h
new file mode 100644 (file)
index 0000000..ba74c43
--- /dev/null
@@ -0,0 +1,74 @@
+
+/*
+ * $Id: ACLExtUser.h,v 1.1 2003/06/27 22:32:31 hno Exp $
+ *
+ *
+ * SQUID Web Proxy Cache          http://www.squid-cache.org/
+ * ----------------------------------------------------------
+ *
+ *  Squid is the result of efforts by numerous individuals from
+ *  the Internet community; see the CONTRIBUTORS file for full
+ *  details.   Many organizations have provided support for Squid's
+ *  development; see the SPONSORS file for full details.  Squid is
+ *  Copyrighted (C) 2001 by the Regents of the University of
+ *  California; see the COPYRIGHT file for full details.  Squid
+ *  incorporates software developed and/or copyrighted by other
+ *  sources; see the CREDITS file for full details.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *  
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *  
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA.
+ *
+ *
+ * Copyright (c) 2003, Robert Collins <robertc@squid-cache.org>
+ */
+
+#ifndef SQUID_ACLIDENT_H
+#define SQUID_ACLIDENT_H
+#include "ACL.h"
+#include "ACLChecklist.h"
+#include "ACLData.h"
+
+class ACLExtUser : public ACL
+{
+
+public:
+    void *operator new(size_t);
+    void operator delete(void *);
+    virtual void deleteSelf() const;
+
+    ACLExtUser(ACLData<char const *> *newData, char const *);
+    ACLExtUser (ACLExtUser const &old);
+    ACLExtUser & operator= (ACLExtUser const &rhs);
+    ~ACLExtUser();
+
+    virtual char const *typeString() const;
+    virtual void parse();
+    virtual bool isProxyAuth() const {return true;}
+
+    virtual int match(ACLChecklist *checklist);
+    virtual wordlist *dump() const;
+    virtual bool valid () const;
+    virtual ACL *clone()const;
+
+private:
+    static MemPool *Pool;
+    static Prototype UserRegistryProtoype;
+    static ACLExtUser UserRegistryEntry_;
+    static Prototype RegexRegistryProtoype;
+    static ACLExtUser RegexRegistryEntry_;
+    ACLData<char const *> *data;
+    char const *type_;
+};
+
+#endif /* SQUID_ACLIDENT_H */
index bcf9494997b184a3bfaeee7efed8bf7dfcff21d7..aabece6620fa7b1ea8026e7975412fa87d21b960 100644 (file)
@@ -1,6 +1,6 @@
 
 /*
- * $Id: ExternalACLEntry.cc,v 1.2 2003/06/27 20:54:45 hno Exp $
+ * $Id: ExternalACLEntry.cc,v 1.3 2003/06/27 22:32:31 hno Exp $
  *
  * DEBUG: section 82    External ACL
  * AUTHOR: Henrik Nordstrom, MARA Systems AB
@@ -91,6 +91,7 @@ ExternalACLEntry::update(ExternalACLEntryData const &someData)
     result = someData.result;
 
     user = someData.user;
+    password = someData.password;
     message = someData.message;
     tag = someData.tag;
 }
index b7ab27a1caf0bd7fb71451ecacf99c7a2fdee799..64d7c13f6b8c7ee52eb770f5e96103848fa03cde 100644 (file)
@@ -1,6 +1,6 @@
 
 /*
- * $Id: ExternalACLEntry.h,v 1.2 2003/06/27 20:54:45 hno Exp $
+ * $Id: ExternalACLEntry.h,v 1.3 2003/06/27 22:32:31 hno Exp $
  *
  * DEBUG: section 82    External ACL
  * AUTHOR: Henrik Nordstrom, MARA Systems AB
@@ -59,6 +59,7 @@ public:
 
     int result;
     String user;
+    String password;
     String message;
     String tag;
 };
@@ -85,6 +86,7 @@ public:
     int result;
     time_t date;
     String user;
+    String password;
     String message;
     String tag;
     external_acl *def;
index f989a6b8cd651e1a63da674bd61fd1a4669c6c0f..c1f47eaf6bf5c56d6febb82b7931650c056788e7 100644 (file)
@@ -1,6 +1,6 @@
 
 /*
- * $Id: HttpRequest.cc,v 1.36 2003/03/06 06:21:37 robertc Exp $
+ * $Id: HttpRequest.cc,v 1.37 2003/06/27 22:32:31 hno Exp $
  *
  * DEBUG: section 73    HTTP Request
  * AUTHOR: Duane Wessels
@@ -90,6 +90,12 @@ requestDestroy(request_t * req)
     if (req->range)
         req->range->deleteSelf();
 
+    req->tag.clean();
+
+    req->extacl_user.clean();
+
+    req->extacl_passwd.clean();
+
     memFree(req, MEM_REQUEST_T);
 }
 
index 5ab9603dedf121afaf9de7d148f03691c679c035..4ce1975eae36bcc398773d51c4342e95fa84c413 100644 (file)
@@ -1,7 +1,7 @@
 #
 #  Makefile for the Squid Object Cache server
 #
-#  $Id: Makefile.am,v 1.79 2003/06/20 01:00:57 robertc Exp $
+#  $Id: Makefile.am,v 1.80 2003/06/27 22:32:30 hno Exp $
 #
 #  Uncomment and customize the following to suit your needs:
 #
@@ -209,6 +209,8 @@ squid_ACLSOURCES = \
        ACLDestinationIP.h \
        ACLDomainData.h \
        ACLDomainData.cc \
+       ACLExtUser.h \
+       ACLExtUser.cc \
        ACLIntRange.cc \
        ACLIntRange.h \
        ACLIP.cc \
index 72fbd21c2813d84b902164de641e208c460438ab..2ed8b9e6d8b3082f085a9727c2cca0701bd3a172 100644 (file)
@@ -1,6 +1,6 @@
 
 /*
- * $Id: access_log.cc,v 1.82 2003/06/09 21:52:21 wessels Exp $
+ * $Id: access_log.cc,v 1.83 2003/06/27 22:32:30 hno Exp $
  *
  * DEBUG: section 46    Access Log
  * AUTHOR: Duane Wessels
@@ -263,6 +263,9 @@ accessLogSquid(AccessLogEntry * al)
 
     user = accessLogFormatName(al->cache.authuser);
 
+    if (!user)
+        user = accessLogFormatName(al->cache.extuser);
+
 #if USE_SSL
 
     if (!user)
index d19830d33e4f998dcfcb522ccbc59e34ac4db4b6..889d33874e36a54c21d330c7614ec82929fea654 100644 (file)
@@ -1,6 +1,6 @@
 
 /*
- * $Id: client_side.cc,v 1.643 2003/06/23 14:13:03 robertc Exp $
+ * $Id: client_side.cc,v 1.644 2003/06/27 22:32:30 hno Exp $
  *
  * DEBUG: section 33    Client-side Routines
  * AUTHOR: Duane Wessels
@@ -477,6 +477,8 @@ clientPrepareLogWithRequestDetails(request_t * request, AccessLogEntry * aLogEnt
     aLogEntry->headers.request = xstrdup(mb.buf);
     aLogEntry->hier = request->hier;
 
+    aLogEntry->cache.extuser = request->extacl_user.buf();
+
     if (request->auth_user_request) {
         if (authenticateUserRequestUsername(request->auth_user_request))
             aLogEntry->cache.authuser =
index 97cec62b4ee81f30ba302b51c57b61c90cef9774..b487d3b5f9cc021aba091f0e919c007cfc44674c 100644 (file)
@@ -1,6 +1,6 @@
 
 /*
- * $Id: client_side_request.cc,v 1.23 2003/06/20 01:01:00 robertc Exp $
+ * $Id: client_side_request.cc,v 1.24 2003/06/27 22:32:31 hno Exp $
  * 
  * DEBUG: section 85    Client-side Request Routines
  * AUTHOR: Robert Collins (Originally Duane Wessels in client_side.c)
@@ -773,6 +773,8 @@ clientRedirectDone(void *data, char *result)
         }
 
         new_request->content_length = old_request->content_length;
+        new_request->extacl_user = old_request->extacl_user;
+        new_request->extacl_passwd = old_request->extacl_passwd;
         new_request->flags.proxy_keepalive = old_request->flags.proxy_keepalive;
         requestUnlink(old_request);
         http->request = requestLink(new_request);
index cba6d612959a407289c85119b0a0dc85a974443e..33c6c4771a94779b4c6a3b49c3d4189a35f8a3b2 100644 (file)
@@ -1,6 +1,6 @@
 
 /*
- * $Id: external_acl.cc,v 1.45 2003/06/27 20:54:45 hno Exp $
+ * $Id: external_acl.cc,v 1.46 2003/06/27 22:32:31 hno Exp $
  *
  * DEBUG: section 82    External ACL
  * AUTHOR: Henrik Nordstrom, MARA Systems AB
@@ -134,6 +134,7 @@ struct _external_acl_format
         EXT_ACL_USER_CERT,
         EXT_ACL_CA_CERT,
 #endif
+        EXT_ACL_EXT_USER,
         EXT_ACL_END
     } type;
     external_acl_format *next;
@@ -316,6 +317,8 @@ parse_externalAclHelper(external_acl ** list)
         }
 
 #endif
+        else if (strcmp(token, "%EXT_USER") == 0)
+            format->type = _external_acl_format::EXT_ACL_EXT_USER;
         else {
             self_destruct();
         }
@@ -408,6 +411,8 @@ dump_externalAclHelper(StoreEntry * sentry, const char *name, const external_acl
                 break;
 #endif
 
+                DUMP_EXT_ACL_TYPE(EXT_USER);
+
             case _external_acl_format::EXT_ACL_UNKNOWN:
 
             case _external_acl_format::EXT_ACL_END:
@@ -585,20 +590,17 @@ aclMatchExternal(external_acl_data *acl, ACLChecklist * ch)
     external_acl_cache_touch(acl->def, entry);
     result = entry->result;
     debug(82, 2) ("aclMatchExternal: %s = %d\n", acl->def->name, result);
-    /* FIXME: This should allocate it's own storage in the request. This
-     * piggy backs on ident, and may fail if there is child proxies..
-     * Register the username for logging purposes
-     */
 
-    if (entry->user.size()) {
-        xstrncpy(ch->rfc931, entry->user.buf(), USER_IDENT_SZ);
+    if (ch->request) {
+        if (entry->user.size())
+            ch->request->extacl_user = entry->user;
 
-        if (cbdataReferenceValid(ch->conn()))
-            xstrncpy(ch->conn()->rfc931, entry->user.buf(), USER_IDENT_SZ);
-    }
+        if (entry->password.size())
+            ch->request->extacl_passwd = entry->password;
 
-    if (ch->request && !ch->request->tag.size())
-        ch->request->tag = entry->tag;
+        if (!ch->request->tag.size())
+            ch->request->tag = entry->tag;
+    }
 
     return result;
 }
@@ -741,6 +743,10 @@ makeExternalAclKey(ACLChecklist * ch, external_acl_data * acl_data)
             break;
 #endif
 
+        case _external_acl_format::EXT_ACL_EXT_USER:
+            str = request->extacl_user.buf();
+            break;
+
         case _external_acl_format::EXT_ACL_UNKNOWN:
 
         case _external_acl_format::EXT_ACL_END:
@@ -896,15 +902,20 @@ externalAclHandleReply(void *data, char *reply)
             if (value) {
                 *value++ = '\0';       /* terminate the token, and move up to the value */
 
-                if (strcmp(token, "tag") == 0)
-                    entryData.tag = value;
-
                 if (strcmp(token, "user") == 0)
                     entryData.user = value;
                 else if (strcmp(token, "message") == 0)
                     entryData.message = value;
                 else if (strcmp(token, "error") == 0)
                     entryData.message = value;
+                else if (strcmp(token, "tag") == 0)
+                    entryData.tag = value;
+                else if (strcmp(token, "password") == 0)
+                    entryData.password = value;
+                else if (strcmp(token, "passwd") == 0)
+                    entryData.password = value;
+                else if (strcmp(token, "login") == 0)
+                    entryData.user = value;
             }
         }
     }
index caad3027f66d69095f693c2a1a454f17b7dcc78c..037129f9bf64a71c23ea5aa1a7c2e7d2cf1517a5 100644 (file)
@@ -1,6 +1,6 @@
 
 /*
- * $Id: http.cc,v 1.416 2003/06/24 12:42:25 robertc Exp $
+ * $Id: http.cc,v 1.417 2003/06/27 22:32:31 hno Exp $
  *
  * DEBUG: section 11    Hypertext Transfer Protocol (HTTP)
  * AUTHOR: Harvest Derived
@@ -206,6 +206,7 @@ httpMaybeRemovePublic(StoreEntry * e, http_status status)
         /*
          * Any 2xx response should eject previously cached entities...
          */
+
         if (status >= 200 && status < 300)
             remove
                 = 1;
@@ -1217,13 +1218,20 @@ httpBuildRequestHeader(request_t * request,
 
             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.buf();
 
             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) {
-            /* Nothing to do */
+            if (orig_request->extacl_user.size() && orig_request->extacl_passwd.size()) {
+                char loginbuf[256];
+                snprintf(loginbuf, sizeof(loginbuf), "%s:%s", orig_request->extacl_user.buf(), orig_request->extacl_passwd.buf());
+                httpHeaderPutStrf(hdr_out, HDR_PROXY_AUTHORIZATION, "Basic %s",
+                                  base64_encode(loginbuf));
+            }
         } else if (strcmp(orig_request->peer_login, "PROXYPASS") == 0) {
             /* Nothing to do */
         } else {
@@ -1239,11 +1247,17 @@ httpBuildRequestHeader(request_t * request,
             /* No credentials to forward.. (should have been done above if available) */
         } 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 = httpHeaderGetStr(hdr_in, HDR_PROXY_AUTHORIZATION);
 
             if (auth && strncasecmp(auth, "basic ", 6) == 0) {
                 httpHeaderPutStr(hdr_out, HDR_AUTHORIZATION, auth);
+            } else if (orig_request->extacl_user.size() && orig_request->extacl_passwd.size()) {
+                char loginbuf[256];
+                snprintf(loginbuf, sizeof(loginbuf), "%s:%s", orig_request->extacl_user.buf(), orig_request->extacl_passwd.buf());
+                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 */
@@ -1252,6 +1266,8 @@ httpBuildRequestHeader(request_t * request,
 
             if (orig_request->auth_user_request)
                 username = authenticateUserRequestUsername(orig_request->auth_user_request);
+            else if (orig_request->extacl_user.size())
+                username = orig_request->extacl_user.buf();
 
             snprintf(loginbuf, sizeof(loginbuf), "%s%s", username, orig_request->peer_login + 1);
 
@@ -1264,8 +1280,7 @@ httpBuildRequestHeader(request_t * request,
         }
     }
 
-    /* append Cache-Control, add max-age if not there already */
-    {
+    /* append Cache-Control, add max-age if not there already */ {
         HttpHdrCc *cc = httpHeaderGetCc(hdr_in);
 
         if (!cc)
@@ -1329,7 +1344,8 @@ copyOneHeaderFromClientsideRequestToUpstreamRequest(const HttpHeaderEntry *e, St
          */
 
         if (flags.proxying && orig_request->peer_login &&
-                strcmp(orig_request->peer_login, "PASS") == 0) {
+                (strcmp(orig_request->peer_login, "PASS") == 0 ||
+                 strcmp(orig_request->peer_login, "PROXYPASS") == 0)) {
             httpHeaderAddEntry(hdr_out, httpHeaderEntryClone(e));
         }
 
@@ -1345,7 +1361,9 @@ copyOneHeaderFromClientsideRequestToUpstreamRequest(const HttpHeaderEntry *e, St
              * (see also below for proxy->server authentication)
              */
 
-            if (orig_request->peer_login && (strcmp(orig_request->peer_login, "PASS") == 0 || strcmp(orig_request->peer_login, "PROXYPASS") == 0)) {
+            if (orig_request->peer_login &&
+                    (strcmp(orig_request->peer_login, "PASS") == 0 ||
+                     strcmp(orig_request->peer_login, "PROXYPASS") == 0)) {
                 httpHeaderAddEntry(hdr_out, httpHeaderEntryClone(e));
             }
         }
index aace2a32c3239bd0c70f1fe5662a85535620c8bf..0678e21ba12415a59844763a4f0654c34aab258c 100644 (file)
@@ -1,6 +1,6 @@
 
 /*
- * $Id: structs.h,v 1.465 2003/05/29 15:54:08 hno Exp $
+ * $Id: structs.h,v 1.466 2003/06/27 22:32:31 hno Exp $
  *
  *
  * SQUID Web Proxy Cache          http://www.squid-cache.org/
@@ -1071,6 +1071,8 @@ struct _AccessLogEntry
         const char *ssluser;
 #endif
 
+        const char *extuser;
+
     }
 
     cache;
@@ -1703,6 +1705,8 @@ public:
     const char *vary_headers;  /* Used when varying entities are detected. Changes how the store key is calculated */
     char *peer_domain;         /* Configured peer forceddomain */
     String tag;                        /* Internal tag for this request */
+    String extacl_user;                /* User name returned by extacl lookup */
+    String extacl_passwd;      /* Password returned by extacl lookup */
 };
 
 #endif