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