]> git.ipfire.org Git - thirdparty/squid.git/blob - src/acl/UserData.cc
03412949e6664838730baeebe044dd11ac662460
[thirdparty/squid.git] / src / acl / UserData.cc
1 /*
2 * Copyright (C) 1996-2014 The Squid Software Foundation and contributors
3 *
4 * Squid software is distributed under GPLv2+ license and includes
5 * contributions from numerous individuals and organizations.
6 * Please see the COPYING and CONTRIBUTORS files for details.
7 */
8
9 /* DEBUG: section 28 Access Control */
10
11 #include "squid.h"
12 #include "acl/Checklist.h"
13 #include "acl/UserData.h"
14 #include "ConfigParser.h"
15 #include "Debug.h"
16
17 template<class T>
18 inline void
19 xRefFree(T &thing)
20 {
21 xfree (thing);
22 }
23
24 ACLUserData::~ACLUserData()
25 {
26 if (names)
27 names->destroy(xRefFree);
28 }
29
30 static int
31 splaystrcasecmp (char * const &l, char * const &r)
32 {
33 return strcasecmp ((char *)l,(char *)r);
34 }
35
36 static int
37 splaystrcmp (char * const &l, char * const &r)
38 {
39 return strcmp ((char *)l,(char *)r);
40 }
41
42 bool
43 ACLUserData::match(char const *user)
44 {
45 SplayNode<char *> *Top = names;
46
47 debugs(28, 7, "aclMatchUser: user is " << user << ", case_insensitive is " << flags.case_insensitive);
48 debugs(28, 8, "Top is " << Top << ", Top->data is " << ((char *) (Top != NULL ? (Top)->data : "Unavailable")));
49
50 if (user == NULL || strcmp(user, "-") == 0)
51 return 0;
52
53 if (flags.required) {
54 debugs(28, 7, "aclMatchUser: user REQUIRED and auth-info present.");
55 return 1;
56 }
57
58 if (flags.case_insensitive)
59 Top = Top->splay((char *)user, splaystrcasecmp);
60 else
61 Top = Top->splay((char *)user, splaystrcmp);
62
63 /* Top=splay_splay(user,Top,(splayNode::SPLAYCMP *)dumping_strcmp); */
64 debugs(28, 7, "aclMatchUser: returning " << !splayLastResult << ",Top is " <<
65 Top << ", Top->data is " << ((char *) (Top ? Top->data : "Unavailable")));
66
67 names = Top;
68
69 return !splayLastResult;
70 }
71
72 static void
73 aclDumpUserListWalkee(char * const & node_data, void *outlist)
74 {
75 /* outlist is really a SBufList* */
76 static_cast<SBufList *>(outlist)->push_back(SBuf(node_data));
77 }
78
79 SBufList
80 ACLUserData::dump() const
81 {
82 SBufList sl;
83
84 if (flags.case_insensitive)
85 sl.push_back(SBuf("-i"));
86
87 /* damn this is VERY inefficient for long ACL lists... filling
88 * a SBufList this way costs Sum(1,N) iterations. For instance
89 * a 1000-elements list will be filled in 499500 iterations.
90 */
91 if (flags.required)
92 sl.push_back(SBuf("REQUIRED"));
93 else if (names)
94 names->walk(aclDumpUserListWalkee, &sl);
95
96 return sl;
97 }
98
99 void
100 ACLUserData::parse()
101 {
102 debugs(28, 2, "aclParseUserList: parsing user list");
103 char *t = NULL;
104
105 if ((t = ConfigParser::strtokFile())) {
106 debugs(28, 5, "aclParseUserList: First token is " << t);
107
108 if (strcmp("-i", t) == 0) {
109 debugs(28, 5, "aclParseUserList: Going case-insensitive");
110 flags.case_insensitive = true;
111 } else if (strcmp("REQUIRED", t) == 0) {
112 debugs(28, 5, "aclParseUserList: REQUIRED-type enabled");
113 flags.required = true;
114 } else {
115 if (flags.case_insensitive)
116 Tolower(t);
117
118 names = names->insert(xstrdup(t), splaystrcmp);
119 }
120 }
121
122 debugs(28, 3, "aclParseUserList: Case-insensitive-switch is " << flags.case_insensitive);
123 /* we might inherit from a previous declaration */
124
125 debugs(28, 4, "aclParseUserList: parsing user list");
126
127 while ((t = ConfigParser::strtokFile())) {
128 debugs(28, 6, "aclParseUserList: Got token: " << t);
129
130 if (flags.case_insensitive)
131 Tolower(t);
132
133 names = names->insert(xstrdup(t), splaystrcmp);
134 }
135 }
136
137 bool
138 ACLUserData::empty() const
139 {
140 return names->empty() && !flags.required;
141 }
142
143 ACLData<char const *> *
144 ACLUserData::clone() const
145 {
146 /* Splay trees don't clone yet. */
147 assert (!names);
148 return new ACLUserData;
149 }