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