]>
Commit | Line | Data |
---|---|---|
1 | /* | |
2 | * Copyright (C) 1996-2025 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/Options.h" | |
14 | #include "acl/UserData.h" | |
15 | #include "ConfigParser.h" | |
16 | #include "debug/Stream.h" | |
17 | #include "globals.h" | |
18 | #include "sbuf/Algorithms.h" | |
19 | #include "util.h" | |
20 | ||
21 | Acl::BooleanOptionValue ACLUserData::CaseInsensitive_; | |
22 | ||
23 | bool | |
24 | ACLUserData::match(char const *user) | |
25 | { | |
26 | debugs(28, 7, "user is " << user << ", case_insensitive is " << flags.case_insensitive); | |
27 | ||
28 | if (user == nullptr || strcmp(user, "-") == 0) | |
29 | return 0; | |
30 | ||
31 | if (flags.required) { | |
32 | debugs(28, 7, "aclMatchUser: user REQUIRED and auth-info present."); | |
33 | return 1; | |
34 | } | |
35 | ||
36 | bool result = (userDataNames.find(SBuf(user)) != userDataNames.end()); | |
37 | debugs(28, 7, "returning " << result); | |
38 | return result; | |
39 | } | |
40 | ||
41 | SBufList | |
42 | ACLUserData::dump() const | |
43 | { | |
44 | SBufList sl; | |
45 | ||
46 | if (flags.required) { | |
47 | sl.push_back(SBuf("REQUIRED")); | |
48 | return sl; | |
49 | } | |
50 | ||
51 | if (flags.case_insensitive) | |
52 | sl.push_back(SBuf("-i")); | |
53 | ||
54 | sl.insert(sl.end(), userDataNames.begin(), userDataNames.end()); | |
55 | ||
56 | debugs(28,5, "ACLUserData dump output: " << | |
57 | JoinContainerToSBuf(userDataNames.begin(), userDataNames.end(), | |
58 | SBuf(" "))); | |
59 | return sl; | |
60 | } | |
61 | ||
62 | static bool | |
63 | CaseSensitiveSBufCompare(const SBuf &lhs, const SBuf &rhs) | |
64 | { | |
65 | return (lhs.cmp(rhs) < 0); | |
66 | } | |
67 | ||
68 | static bool | |
69 | CaseInsensitveSBufCompare(const SBuf &lhs, const SBuf &rhs) | |
70 | { | |
71 | return (lhs.caseCmp(rhs) < 0); | |
72 | } | |
73 | ||
74 | ACLUserData::ACLUserData() : | |
75 | userDataNames(CaseSensitiveSBufCompare) | |
76 | { | |
77 | flags.case_insensitive = false; | |
78 | flags.required = false; | |
79 | } | |
80 | ||
81 | const Acl::Options & | |
82 | ACLUserData::lineOptions() | |
83 | { | |
84 | static auto MyCaseSensitivityOption = Acl::CaseSensitivityOption(); | |
85 | static const Acl::Options MyOptions = { &MyCaseSensitivityOption }; | |
86 | MyCaseSensitivityOption.linkWith(&CaseInsensitive_); | |
87 | return MyOptions; | |
88 | } | |
89 | ||
90 | void | |
91 | ACLUserData::parse() | |
92 | { | |
93 | debugs(28, 2, "parsing user list"); | |
94 | flags.case_insensitive = bool(CaseInsensitive_); | |
95 | ||
96 | char *t = nullptr; | |
97 | if ((t = ConfigParser::strtokFile())) { | |
98 | SBuf s(t); | |
99 | debugs(28, 5, "first token is " << s); | |
100 | ||
101 | if (s.cmp("-i",2) == 0) { | |
102 | debugs(28, 5, "Going case-insensitive"); | |
103 | flags.case_insensitive = true; | |
104 | // due to how the std::set API work, if we want to change | |
105 | // the comparison function we have to create a new std::set | |
106 | UserDataNames_t newUdn(CaseInsensitveSBufCompare); | |
107 | newUdn.insert(userDataNames.begin(), userDataNames.end()); | |
108 | swap(userDataNames,newUdn); | |
109 | } else if (s.cmp("REQUIRED") == 0) { | |
110 | debugs(28, 5, "REQUIRED-type enabled"); | |
111 | flags.required = true; | |
112 | } else { | |
113 | if (flags.case_insensitive) | |
114 | s.toLower(); | |
115 | ||
116 | debugs(28, 6, "Adding user " << s); | |
117 | userDataNames.insert(s); | |
118 | } | |
119 | } | |
120 | ||
121 | debugs(28, 3, "Case-insensitive-switch is " << flags.case_insensitive); | |
122 | /* we might inherit from a previous declaration */ | |
123 | ||
124 | debugs(28, 4, "parsing following tokens"); | |
125 | ||
126 | while ((t = ConfigParser::strtokFile())) { | |
127 | SBuf s(t); | |
128 | debugs(28, 6, "Got token: " << s); | |
129 | ||
130 | if (flags.case_insensitive) | |
131 | s.toLower(); | |
132 | ||
133 | debugs(28, 6, "Adding user " << s); | |
134 | userDataNames.insert(s); | |
135 | } | |
136 | ||
137 | if (flags.required && !userDataNames.empty()) { | |
138 | debugs(28, DBG_PARSE_NOTE(1), "WARNING: detected attempt to add usernames to an acl of type REQUIRED"); | |
139 | userDataNames.clear(); | |
140 | } | |
141 | ||
142 | debugs(28,4, "ACL contains " << userDataNames.size() << " users"); | |
143 | } | |
144 | ||
145 | bool | |
146 | ACLUserData::empty() const | |
147 | { | |
148 | debugs(28,6,"required: " << flags.required << ", number of users: " << userDataNames.size()); | |
149 | if (flags.required) | |
150 | return false; | |
151 | return userDataNames.empty(); | |
152 | } | |
153 |