]> git.ipfire.org Git - thirdparty/squid.git/blob - src/acl/UserData.cc
5cb3af352f0ec518cd93ffe9d45b3ce9769ff846
[thirdparty/squid.git] / src / acl / UserData.cc
1 /*
2 * Copyright (C) 1996-2015 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 #include "util.h"
17
18 template<class T>
19 inline void
20 xRefFree(T &thing)
21 {
22 xfree (thing);
23 }
24
25 ACLUserData::~ACLUserData()
26 {
27 if (names) {
28 names->destroy(xRefFree);
29 delete names;
30 }
31 }
32
33 static int
34 splaystrcasecmp (char * const &l, char * const &r)
35 {
36 return strcasecmp ((char *)l,(char *)r);
37 }
38
39 static int
40 splaystrcmp (char * const &l, char * const &r)
41 {
42 return strcmp ((char *)l,(char *)r);
43 }
44
45 bool
46 ACLUserData::match(char const *user)
47 {
48 debugs(28, 7, "aclMatchUser: user is " << user << ", case_insensitive is " << flags.case_insensitive);
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 char * const *result;
59
60 if (flags.case_insensitive)
61 result = names->find(const_cast<char *>(user), splaystrcasecmp);
62 else
63 result = names->find(const_cast<char *>(user), splaystrcmp);
64
65 /* Top=splay_splay(user,Top,(splayNode::SPLAYCMP *)dumping_strcmp); */
66 debugs(28, 7, "aclMatchUser: returning " << (result != NULL));
67
68 return (result != NULL);
69 }
70
71 struct UserDataAclDumpVisitor {
72 SBufList contents;
73 void operator() (char * const & node_data) {
74 contents.push_back(SBuf(node_data));
75 }
76 };
77
78 SBufList
79 ACLUserData::dump() const
80 {
81 SBufList sl;
82
83 if (flags.required) {
84 sl.push_back(SBuf("REQUIRED"));
85 return sl;
86 }
87
88 if (flags.case_insensitive)
89 sl.push_back(SBuf("-i"));
90
91 /* damn this is VERY inefficient for long ACL lists... filling
92 * a SBufList this way costs Sum(1,N) iterations. For instance
93 * a 1000-elements list will be filled in 499500 iterations.
94 */
95 if (names) {
96 UserDataAclDumpVisitor visitor;
97 names->visit(visitor);
98 sl.splice(sl.end(),visitor.contents);
99 }
100
101 return sl;
102 }
103
104 void
105 ACLUserData::parse()
106 {
107 debugs(28, 2, "aclParseUserList: parsing user list");
108
109 if (!names)
110 names = new Splay<char *>();
111
112 char *t = NULL;
113 if ((t = ConfigParser::strtokFile())) {
114 debugs(28, 5, "aclParseUserList: First token is " << t);
115
116 if (strcmp("-i", t) == 0) {
117 debugs(28, 5, "aclParseUserList: Going case-insensitive");
118 flags.case_insensitive = true;
119 } else if (strcmp("REQUIRED", t) == 0) {
120 debugs(28, 5, "aclParseUserList: REQUIRED-type enabled");
121 flags.required = true;
122 } else {
123 if (flags.case_insensitive)
124 Tolower(t);
125
126 names->insert(xstrdup(t), splaystrcmp);
127 }
128 }
129
130 debugs(28, 3, "aclParseUserList: Case-insensitive-switch is " << flags.case_insensitive);
131 /* we might inherit from a previous declaration */
132
133 debugs(28, 4, "aclParseUserList: parsing user list");
134
135 while ((t = ConfigParser::strtokFile())) {
136 debugs(28, 6, "aclParseUserList: Got token: " << t);
137
138 if (flags.case_insensitive)
139 Tolower(t);
140
141 names->insert(xstrdup(t), splaystrcmp);
142 }
143 }
144
145 bool
146 ACLUserData::empty() const
147 {
148 return (!names || names->empty()) && !flags.required;
149 }
150
151 ACLData<char const *> *
152 ACLUserData::clone() const
153 {
154 /* Splay trees don't clone yet. */
155 assert (!names);
156 return new ACLUserData;
157 }
158