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