]> git.ipfire.org Git - thirdparty/squid.git/blame - src/auth/basic/UserRequest.cc
Bug 4843 pt1: ext_edirectory_userip_acl refactoring for GCC-8 (#204)
[thirdparty/squid.git] / src / auth / basic / UserRequest.cc
CommitLineData
bbc27441 1/*
5b74111a 2 * Copyright (C) 1996-2018 The Squid Software Foundation and contributors
bbc27441
AJ
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
f7f3304a 9#include "squid.h"
12daeef6 10#include "auth/basic/Config.h"
aa110616 11#include "auth/basic/User.h"
616cfc4c 12#include "auth/basic/UserRequest.h"
bf929433 13#include "auth/QueueNode.h"
fe0a0419
AJ
14#include "auth/State.h"
15#include "charset.h"
582c2af2 16#include "Debug.h"
86c63190 17#include "format/Format.h"
24438ec5
AJ
18#include "helper.h"
19#include "helper/Reply.h"
d4806c91 20#include "HttpRequest.h"
d4806c91 21#include "MemBuf.h"
fe0a0419 22#include "rfc1738.h"
616cfc4c 23#include "SquidTime.h"
928f3421 24
fe0a0419
AJ
25#if !defined(HELPER_INPUT_BUFFER)
26#define HELPER_INPUT_BUFFER 8192
27#endif
28
928f3421 29int
c7baff40 30Auth::Basic::UserRequest::authenticated() const
928f3421 31{
aa110616 32 Auth::Basic::User const *basic_auth = dynamic_cast<Auth::Basic::User const *>(user().getRaw());
928f3421
AJ
33
34 if (basic_auth && basic_auth->authenticated())
35 return 1;
36
37 return 0;
38}
39
d4806c91
CT
40const char *
41Auth::Basic::UserRequest::credentialsStr()
42{
43 Auth::Basic::User const *basic_auth = dynamic_cast<Auth::Basic::User const *>(user().getRaw());
44 if (basic_auth)
45 return basic_auth->passwd;
46 return NULL;
47}
48
928f3421
AJ
49/* log a basic user in
50 */
51void
789217a2 52Auth::Basic::UserRequest::authenticate(HttpRequest *, ConnStateData *, Http::HdrType)
928f3421
AJ
53{
54 assert(user() != NULL);
55
928f3421 56 /* if the password is not ok, do an identity */
d87154ee 57 if (!user() || user()->credentials() != Auth::Ok)
928f3421
AJ
58 return;
59
60 /* are we about to recheck the credentials externally? */
dc79fed8 61 if ((user()->expiretime + static_cast<Auth::Basic::Config*>(Auth::SchemeConfig::Find("basic"))->credentialsTTL) <= squid_curtime) {
d232141d 62 debugs(29, 4, HERE << "credentials expired - rechecking");
928f3421
AJ
63 return;
64 }
65
66 /* we have been through the external helper, and the credentials haven't expired */
d232141d 67 debugs(29, 9, HERE << "user '" << user()->username() << "' authenticated");
928f3421
AJ
68
69 /* Decode now takes care of finding the AuthUser struct in the cache */
70 /* after external auth occurs anyway */
d232141d 71 user()->expiretime = current_time.tv_sec;
928f3421
AJ
72}
73
51a3dd58 74Auth::Direction
c7baff40 75Auth::Basic::UserRequest::module_direction()
928f3421 76{
c7baff40 77 /* null auth_user is checked for by Auth::UserRequest::direction() */
616cfc4c 78 if (user()->auth_type != Auth::AUTH_BASIC)
51a3dd58 79 return Auth::CRED_ERROR;
928f3421 80
d232141d 81 switch (user()->credentials()) {
928f3421 82
d87154ee
AJ
83 case Auth::Unchecked:
84 case Auth::Pending:
51a3dd58 85 return Auth::CRED_LOOKUP;
928f3421 86
d87154ee 87 case Auth::Ok:
dc79fed8 88 if (user()->expiretime + static_cast<Auth::Basic::Config*>(Auth::SchemeConfig::Find("basic"))->credentialsTTL <= squid_curtime)
51a3dd58
AJ
89 return Auth::CRED_LOOKUP;
90 return Auth::CRED_VALID;
928f3421 91
d87154ee 92 case Auth::Failed:
51a3dd58 93 return Auth::CRED_VALID;
928f3421 94
d232141d 95 default:
51a3dd58 96 return Auth::CRED_ERROR;
d232141d 97 }
928f3421
AJ
98}
99
100/* send the initial data to a basic authenticator module */
101void
30c3f584 102Auth::Basic::UserRequest::startHelperLookup(HttpRequest *request, AccessLogEntry::Pointer &al, AUTHCB * handler, void *data)
928f3421 103{
616cfc4c 104 assert(user()->auth_type == Auth::AUTH_BASIC);
aa110616 105 Auth::Basic::User *basic_auth = dynamic_cast<Auth::Basic::User *>(user().getRaw());
928f3421
AJ
106 assert(basic_auth != NULL);
107 debugs(29, 9, HERE << "'" << basic_auth->username() << ":" << basic_auth->passwd << "'");
108
dc79fed8 109 if (static_cast<Auth::Basic::Config*>(Auth::SchemeConfig::Find("basic"))->authenticateProgram == NULL) {
d232141d 110 debugs(29, DBG_CRITICAL, "ERROR: No Basic authentication program configured.");
4c535e87 111 handler(data);
928f3421
AJ
112 return;
113 }
114
115 /* check to see if the auth_user already has a request outstanding */
d87154ee 116 if (user()->credentials() == Auth::Pending) {
928f3421 117 /* there is a request with the same credentials already being verified */
fe0a0419 118
bf929433 119 Auth::QueueNode *node = new Auth::QueueNode(this, handler, data);
fe0a0419
AJ
120
121 /* queue this validation request to be infored of the pending lookup results */
bf929433
AJ
122 node->next = basic_auth->queue;
123 basic_auth->queue = node;
928f3421
AJ
124 return;
125 }
fe0a0419
AJ
126 // otherwise submit this request to the auth helper(s) for validation
127
128 /* mark this user as having verification in progress */
129 user()->credentials(Auth::Pending);
130 char buf[HELPER_INPUT_BUFFER];
9dca980d 131 static char usern[HELPER_INPUT_BUFFER];
fe0a0419
AJ
132 static char pass[HELPER_INPUT_BUFFER];
133 if (static_cast<Auth::Basic::Config*>(user()->config)->utf8) {
9dca980d 134 latin1_to_utf8(usern, sizeof(usern), user()->username());
fe0a0419 135 latin1_to_utf8(pass, sizeof(pass), basic_auth->passwd);
9dca980d 136 xstrncpy(usern, rfc1738_escape(usern), sizeof(usern));
fe0a0419
AJ
137 xstrncpy(pass, rfc1738_escape(pass), sizeof(pass));
138 } else {
9dca980d 139 xstrncpy(usern, rfc1738_escape(user()->username()), sizeof(usern));
fe0a0419
AJ
140 xstrncpy(pass, rfc1738_escape(basic_auth->passwd), sizeof(pass));
141 }
d4806c91
CT
142 int sz = 0;
143 if (const char *keyExtras = helperRequestKeyExtras(request, al))
144 sz = snprintf(buf, sizeof(buf), "%s %s %s\n", usern, pass, keyExtras);
145 else
146 sz = snprintf(buf, sizeof(buf), "%s %s\n", usern, pass);
147
fe0a0419
AJ
148 if (sz<=0) {
149 debugs(9, DBG_CRITICAL, "ERROR: Basic Authentication Failure. Can not build helper validation request.");
4c535e87 150 handler(data);
56946509 151 } else if (static_cast<size_t>(sz) >= sizeof(buf)) {
fe0a0419 152 debugs(9, DBG_CRITICAL, "ERROR: Basic Authentication Failure. user:password exceeds " << sizeof(buf) << " bytes.");
4c535e87 153 handler(data);
fe0a0419 154 } else
c7baff40 155 helperSubmit(basicauthenticators, buf, Auth::Basic::UserRequest::HandleReply,
fe0a0419 156 new Auth::StateData(this, handler, data));
928f3421
AJ
157}
158
fe0a0419 159void
24438ec5 160Auth::Basic::UserRequest::HandleReply(void *data, const Helper::Reply &reply)
fe0a0419
AJ
161{
162 Auth::StateData *r = static_cast<Auth::StateData *>(data);
fe0a0419 163 void *cbdata;
e166785a 164 debugs(29, 5, HERE << "reply=" << reply);
fe0a0419
AJ
165
166 assert(r->auth_user_request != NULL);
167 assert(r->auth_user_request->user()->auth_type == Auth::AUTH_BASIC);
168
71e7400c
AJ
169 // add new helper kv-pair notes to the credentials object
170 // so that any transaction using those credentials can access them
171 r->auth_user_request->user()->notes.appendNewOnly(&reply.notes);
172
fe0a0419
AJ
173 /* this is okay since we only play with the Auth::Basic::User child fields below
174 * and dont pass the pointer itself anywhere */
175 Auth::Basic::User *basic_auth = dynamic_cast<Auth::Basic::User *>(r->auth_user_request->user().getRaw());
176
177 assert(basic_auth != NULL);
178
2428ce02 179 if (reply.result == Helper::Okay)
fe0a0419
AJ
180 basic_auth->credentials(Auth::Ok);
181 else {
182 basic_auth->credentials(Auth::Failed);
183
e166785a
AJ
184 if (reply.other().hasContent())
185 r->auth_user_request->setDenyMessage(reply.other().content());
fe0a0419
AJ
186 }
187
188 basic_auth->expiretime = squid_curtime;
189
190 if (cbdataReferenceValidDone(r->data, &cbdata))
4c535e87 191 r->handler(cbdata);
fe0a0419
AJ
192
193 cbdataReferenceDone(r->data);
194
bf929433
AJ
195 while (basic_auth->queue) {
196 if (cbdataReferenceValidDone(basic_auth->queue->data, &cbdata))
197 basic_auth->queue->handler(cbdata);
fe0a0419 198
bf929433
AJ
199 Auth::QueueNode *tmpnode = basic_auth->queue->next;
200 basic_auth->queue->next = NULL;
201 delete basic_auth->queue;
fe0a0419 202
bf929433 203 basic_auth->queue = tmpnode;
fe0a0419
AJ
204 }
205
206 delete r;
207}
f53969cc 208