]> git.ipfire.org Git - thirdparty/squid.git/blob - src/auth/AclProxyAuth.cc
Source Format Enforcement (#1234)
[thirdparty/squid.git] / src / auth / AclProxyAuth.cc
1 /*
2 * Copyright (C) 1996-2023 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/FilledChecklist.h"
13 #include "acl/RegexData.h"
14 #include "acl/UserData.h"
15 #include "auth/Acl.h"
16 #include "auth/AclProxyAuth.h"
17 #include "auth/Gadgets.h"
18 #include "auth/User.h"
19 #include "auth/UserRequest.h"
20 #include "client_side.h"
21 #include "http/Stream.h"
22 #include "HttpRequest.h"
23
24 ACLProxyAuth::~ACLProxyAuth()
25 {
26 delete data;
27 }
28
29 ACLProxyAuth::ACLProxyAuth(ACLData<char const *> *newData, char const *theType) :
30 data(newData),
31 type_(theType)
32 {}
33
34 char const *
35 ACLProxyAuth::typeString() const
36 {
37 return type_;
38 }
39
40 const Acl::Options &
41 ACLProxyAuth::lineOptions()
42 {
43 return data->lineOptions();
44 }
45
46 void
47 ACLProxyAuth::parse()
48 {
49 data->parse();
50 }
51
52 int
53 ACLProxyAuth::match(ACLChecklist *checklist)
54 {
55 auto answer = AuthenticateAcl(checklist);
56
57 // convert to tri-state ACL match 1,0,-1
58 switch (answer) {
59 case ACCESS_ALLOWED:
60 // check for a match
61 return matchProxyAuth(checklist);
62
63 case ACCESS_DENIED:
64 return 0; // non-match
65
66 case ACCESS_DUNNO:
67 case ACCESS_AUTH_REQUIRED:
68 default:
69 // If the answer is not allowed or denied (matches/not matches) and
70 // async authentication is not in progress, then we are done.
71 if (checklist->keepMatching())
72 checklist->markFinished(answer, "AuthenticateAcl exception");
73 return -1; // other
74 }
75 }
76
77 SBufList
78 ACLProxyAuth::dump() const
79 {
80 return data->dump();
81 }
82
83 bool
84 ACLProxyAuth::empty() const
85 {
86 return data->empty();
87 }
88
89 bool
90 ACLProxyAuth::valid() const
91 {
92 if (authenticateSchemeCount() == 0) {
93 debugs(28, DBG_CRITICAL, "ERROR: Cannot use proxy auth because no authentication schemes were compiled.");
94 return false;
95 }
96
97 if (authenticateActiveSchemeCount() == 0) {
98 debugs(28, DBG_CRITICAL, "ERROR: Cannot use proxy auth because no authentication schemes are fully configured.");
99 return false;
100 }
101
102 return true;
103 }
104
105 ProxyAuthLookup ProxyAuthLookup::instance_;
106
107 ProxyAuthLookup *
108 ProxyAuthLookup::Instance()
109 {
110 return &instance_;
111 }
112
113 void
114 ProxyAuthLookup::checkForAsync(ACLChecklist *cl) const
115 {
116 ACLFilledChecklist *checklist = Filled(cl);
117
118 debugs(28, 3, "checking password via authenticator");
119
120 /* make sure someone created auth_user_request for us */
121 assert(checklist->auth_user_request != nullptr);
122 assert(checklist->auth_user_request->valid());
123 checklist->auth_user_request->start(checklist->request, checklist->al, LookupDone, checklist);
124 }
125
126 void
127 ProxyAuthLookup::LookupDone(void *data)
128 {
129 ACLFilledChecklist *checklist = Filled(static_cast<ACLChecklist*>(data));
130
131 if (checklist->auth_user_request == nullptr || !checklist->auth_user_request->valid() || checklist->conn() == nullptr) {
132 /* credentials could not be checked either way
133 * restart the whole process */
134 /* OR the connection was closed, there's no way to continue */
135 checklist->auth_user_request = nullptr;
136
137 if (checklist->conn() != nullptr) {
138 checklist->conn()->setAuth(nullptr, "proxy_auth ACL failure");
139 }
140 }
141
142 checklist->resumeNonBlockingCheck(ProxyAuthLookup::Instance());
143 }
144
145 int
146 ACLProxyAuth::matchForCache(ACLChecklist *cl)
147 {
148 ACLFilledChecklist *checklist = Filled(cl);
149 assert (checklist->auth_user_request != nullptr);
150 return data->match(checklist->auth_user_request->username());
151 }
152
153 /* aclMatchProxyAuth can return two exit codes:
154 * 0 : Authorisation for this ACL failed. (Did not match)
155 * 1 : Authorisation OK. (Matched)
156 */
157 int
158 ACLProxyAuth::matchProxyAuth(ACLChecklist *cl)
159 {
160 ACLFilledChecklist *checklist = Filled(cl);
161 if (!checklist->request->flags.sslBumped) {
162 if (!authenticateUserAuthenticated(checklist->auth_user_request)) {
163 return 0;
164 }
165 }
166 /* check to see if we have matched the user-acl before */
167 int result = cacheMatchAcl(&checklist->auth_user_request->user()->proxy_match_cache, checklist);
168 checklist->auth_user_request = nullptr;
169 return result;
170 }
171