]> git.ipfire.org Git - thirdparty/squid.git/blobdiff - src/acl/UserData.cc
Docs: Copyright updates for 2018 (#114)
[thirdparty/squid.git] / src / acl / UserData.cc
index 0579f5aff025711504ce56880032189564ffeefd..775117c9e07824987d1c741f29af0a92cdb0cdeb 100644 (file)
@@ -1,76 +1,26 @@
 /*
- * DEBUG: section 28    Access Control
- * AUTHOR: Duane Wessels
+ * Copyright (C) 1996-2018 The Squid Software Foundation and contributors
  *
- * 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>
+ * Squid software is distributed under GPLv2+ license and includes
+ * contributions from numerous individuals and organizations.
+ * Please see the COPYING and CONTRIBUTORS files for details.
  */
 
+/* DEBUG: section 28    Access Control */
+
 #include "squid.h"
-#include "acl/UserData.h"
 #include "acl/Checklist.h"
-#include "Debug.h"
-#include "wordlist.h"
+#include "acl/UserData.h"
 #include "ConfigParser.h"
-
-template<class T>
-inline void
-xRefFree(T &thing)
-{
-    xfree (thing);
-}
-
-ACLUserData::~ACLUserData()
-{
-    if (names)
-        names->destroy(xRefFree);
-}
-
-static int
-splaystrcasecmp (char * const &l, char * const &r)
-{
-    return strcasecmp ((char *)l,(char *)r);
-}
-
-static int
-splaystrcmp (char * const &l, char * const &r)
-{
-    return strcmp ((char *)l,(char *)r);
-}
+#include "Debug.h"
+#include "globals.h"
+#include "sbuf/Algorithms.h"
+#include "util.h"
 
 bool
 ACLUserData::match(char const *user)
 {
-    SplayNode<char *> *Top = names;
-
-    debugs(28, 7, "aclMatchUser: user is " << user << ", case_insensitive is " << flags.case_insensitive);
-    debugs(28, 8, "Top is " << Top << ", Top->data is " << ((char *) (Top != NULL ? (Top)->data : "Unavailable")));
+    debugs(28, 7, "user is " << user << ", case_insensitive is " << flags.case_insensitive);
 
     if (user == NULL || strcmp(user, "-") == 0)
         return 0;
@@ -80,95 +30,117 @@ ACLUserData::match(char const *user)
         return 1;
     }
 
-    if (flags.case_insensitive)
-        Top = Top->splay((char *)user, splaystrcasecmp);
-    else
-        Top = Top->splay((char *)user, splaystrcmp);
+    bool result = (userDataNames.find(SBuf(user)) != userDataNames.end());
+    debugs(28, 7, "returning " << result);
+    return result;
+}
 
-    /* Top=splay_splay(user,Top,(splayNode::SPLAYCMP *)dumping_strcmp); */
-    debugs(28, 7, "aclMatchUser: returning " << !splayLastResult << ",Top is " <<
-           Top << ", Top->data is " << ((char *) (Top ? Top->data : "Unavailable")));
+SBufList
+ACLUserData::dump() const
+{
+    SBufList sl;
 
-    names = Top;
+    if (flags.required) {
+        sl.push_back(SBuf("REQUIRED"));
+        return sl;
+    }
 
-    return !splayLastResult;
+    if (flags.case_insensitive)
+        sl.push_back(SBuf("-i"));
+
+    sl.insert(sl.end(), userDataNames.begin(), userDataNames.end());
+
+    debugs(28,5, "ACLUserData dump output: " <<
+           JoinContainerToSBuf(userDataNames.begin(), userDataNames.end(),
+                               SBuf(" ")));
+    return sl;
 }
 
-static void
-aclDumpUserListWalkee(char * const & node_data, void *outlist)
+static bool
+CaseSensitiveSBufCompare(const SBuf &lhs, const SBuf &rhs)
 {
-    /* outlist is really a wordlist ** */
-    wordlistAdd((wordlist **)outlist, (char const *)node_data);
+    return (lhs.cmp(rhs) < 0);
 }
 
-wordlist *
-ACLUserData::dump()
+static bool
+CaseInsensitveSBufCompare(const SBuf &lhs, const SBuf &rhs)
 {
-    wordlist *wl = NULL;
-
-    if (flags.case_insensitive)
-        wordlistAdd(&wl, "-i");
-
-    /* damn this is VERY inefficient for long ACL lists... filling
-     * a wordlist this way costs Sum(1,N) iterations. For instance
-     * a 1000-elements list will be filled in 499500 iterations.
-     */
-    if (flags.required)
-        wordlistAdd(&wl, "REQUIRED");
-    else if (names)
-        names->walk(aclDumpUserListWalkee, &wl);
+    return (lhs.caseCmp(rhs) < 0);
+}
 
-    return wl;
+ACLUserData::ACLUserData() :
+    userDataNames(CaseSensitiveSBufCompare)
+{
+    flags.case_insensitive = false;
+    flags.required = false;
 }
 
 void
 ACLUserData::parse()
 {
-    debugs(28, 2, "aclParseUserList: parsing user list");
-    char *t = NULL;
+    debugs(28, 2, "parsing user list");
 
+    char *t = NULL;
     if ((t = ConfigParser::strtokFile())) {
-        debugs(28, 5, "aclParseUserList: First token is " << t);
-
-        if (strcmp("-i", t) == 0) {
-            debugs(28, 5, "aclParseUserList: Going case-insensitive");
-            flags.case_insensitive = 1;
-        } else if (strcmp("REQUIRED", t) == 0) {
-            debugs(28, 5, "aclParseUserList: REQUIRED-type enabled");
-            flags.required = 1;
+        SBuf s(t);
+        debugs(28, 5, "first token is " << s);
+
+        if (s.cmp("-i",2) == 0) {
+            debugs(28, 5, "Going case-insensitive");
+            flags.case_insensitive = true;
+            // due to how the std::set API work, if we want to change
+            // the comparison function we have to create a new std::set
+            UserDataNames_t newUdn(CaseInsensitveSBufCompare);
+            newUdn.insert(userDataNames.begin(), userDataNames.end());
+            swap(userDataNames,newUdn);
+        } else if (s.cmp("REQUIRED") == 0) {
+            debugs(28, 5, "REQUIRED-type enabled");
+            flags.required = true;
         } else {
             if (flags.case_insensitive)
-                Tolower(t);
+                s.toLower();
 
-            names = names->insert(xstrdup(t), splaystrcmp);
+            debugs(28, 6, "Adding user " << s);
+            userDataNames.insert(s);
         }
     }
 
-    debugs(28, 3, "aclParseUserList: Case-insensitive-switch is " << flags.case_insensitive);
+    debugs(28, 3, "Case-insensitive-switch is " << flags.case_insensitive);
     /* we might inherit from a previous declaration */
 
-    debugs(28, 4, "aclParseUserList: parsing user list");
+    debugs(28, 4, "parsing following tokens");
 
     while ((t = ConfigParser::strtokFile())) {
-        debugs(28, 6, "aclParseUserList: Got token: " << t);
+        SBuf s(t);
+        debugs(28, 6, "Got token: " << s);
 
         if (flags.case_insensitive)
-            Tolower(t);
+            s.toLower();
 
-        names = names->insert(xstrdup(t), splaystrcmp);
+        debugs(28, 6, "Adding user " << s);
+        userDataNames.insert(s);
     }
+
+    if (flags.required && !userDataNames.empty()) {
+        debugs(28, DBG_PARSE_NOTE(1), "WARNING: detected attempt to add usernames to an acl of type REQUIRED");
+        userDataNames.clear();
+    }
+
+    debugs(28,4, "ACL contains " << userDataNames.size() << " users");
 }
 
 bool
 ACLUserData::empty() const
 {
-    return names->empty() && !flags.required;
+    debugs(28,6,"required: " << flags.required << ", number of users: " << userDataNames.size());
+    if (flags.required)
+        return false;
+    return userDataNames.empty();
 }
 
 ACLData<char const *> *
 ACLUserData::clone() const
 {
-    /* Splay trees don't clone yet. */
-    assert (!names);
     return new ACLUserData;
 }
+