]> git.ipfire.org Git - thirdparty/squid.git/blame - src/auth/basic/UserRequest.cc
Fix spelling and compile issues in CommIO
[thirdparty/squid.git] / src / auth / basic / UserRequest.cc
CommitLineData
f7f3304a 1#include "squid.h"
928f3421 2#include "auth/basic/auth_basic.h"
aa110616 3#include "auth/basic/User.h"
616cfc4c 4#include "auth/basic/UserRequest.h"
fe0a0419
AJ
5#include "auth/State.h"
6#include "charset.h"
582c2af2 7#include "Debug.h"
fe0a0419 8#include "rfc1738.h"
616cfc4c 9#include "SquidTime.h"
928f3421 10
fe0a0419
AJ
11#if !defined(HELPER_INPUT_BUFFER)
12#define HELPER_INPUT_BUFFER 8192
13#endif
14
928f3421 15int
c7baff40 16Auth::Basic::UserRequest::authenticated() const
928f3421 17{
aa110616 18 Auth::Basic::User const *basic_auth = dynamic_cast<Auth::Basic::User const *>(user().getRaw());
928f3421
AJ
19
20 if (basic_auth && basic_auth->authenticated())
21 return 1;
22
23 return 0;
24}
25
26/* log a basic user in
27 */
28void
c7baff40 29Auth::Basic::UserRequest::authenticate(HttpRequest * request, ConnStateData * conn, http_hdr_type type)
928f3421
AJ
30{
31 assert(user() != NULL);
32
928f3421 33 /* if the password is not ok, do an identity */
d87154ee 34 if (!user() || user()->credentials() != Auth::Ok)
928f3421
AJ
35 return;
36
37 /* are we about to recheck the credentials externally? */
372fccd6 38 if ((user()->expiretime + static_cast<Auth::Basic::Config*>(Auth::Config::Find("basic"))->credentialsTTL) <= squid_curtime) {
d232141d 39 debugs(29, 4, HERE << "credentials expired - rechecking");
928f3421
AJ
40 return;
41 }
42
43 /* we have been through the external helper, and the credentials haven't expired */
d232141d 44 debugs(29, 9, HERE << "user '" << user()->username() << "' authenticated");
928f3421
AJ
45
46 /* Decode now takes care of finding the AuthUser struct in the cache */
47 /* after external auth occurs anyway */
d232141d 48 user()->expiretime = current_time.tv_sec;
928f3421
AJ
49
50 return;
51}
52
51a3dd58 53Auth::Direction
c7baff40 54Auth::Basic::UserRequest::module_direction()
928f3421 55{
c7baff40 56 /* null auth_user is checked for by Auth::UserRequest::direction() */
616cfc4c 57 if (user()->auth_type != Auth::AUTH_BASIC)
51a3dd58 58 return Auth::CRED_ERROR;
928f3421 59
d232141d 60 switch (user()->credentials()) {
928f3421 61
d87154ee
AJ
62 case Auth::Unchecked:
63 case Auth::Pending:
51a3dd58 64 return Auth::CRED_LOOKUP;
928f3421 65
d87154ee 66 case Auth::Ok:
372fccd6 67 if (user()->expiretime + static_cast<Auth::Basic::Config*>(Auth::Config::Find("basic"))->credentialsTTL <= squid_curtime)
51a3dd58
AJ
68 return Auth::CRED_LOOKUP;
69 return Auth::CRED_VALID;
928f3421 70
d87154ee 71 case Auth::Failed:
51a3dd58 72 return Auth::CRED_VALID;
928f3421 73
d232141d 74 default:
51a3dd58 75 return Auth::CRED_ERROR;
d232141d 76 }
928f3421
AJ
77}
78
79/* send the initial data to a basic authenticator module */
80void
4c535e87 81Auth::Basic::UserRequest::module_start(AUTHCB * handler, void *data)
928f3421 82{
616cfc4c 83 assert(user()->auth_type == Auth::AUTH_BASIC);
aa110616 84 Auth::Basic::User *basic_auth = dynamic_cast<Auth::Basic::User *>(user().getRaw());
928f3421
AJ
85 assert(basic_auth != NULL);
86 debugs(29, 9, HERE << "'" << basic_auth->username() << ":" << basic_auth->passwd << "'");
87
372fccd6 88 if (static_cast<Auth::Basic::Config*>(Auth::Config::Find("basic"))->authenticateProgram == NULL) {
d232141d 89 debugs(29, DBG_CRITICAL, "ERROR: No Basic authentication program configured.");
4c535e87 90 handler(data);
928f3421
AJ
91 return;
92 }
93
94 /* check to see if the auth_user already has a request outstanding */
d87154ee 95 if (user()->credentials() == Auth::Pending) {
928f3421 96 /* there is a request with the same credentials already being verified */
fe0a0419
AJ
97
98 BasicAuthQueueNode *node = static_cast<BasicAuthQueueNode *>(xcalloc(1, sizeof(BasicAuthQueueNode)));
99 assert(node);
100 node->auth_user_request = this;
101 node->handler = handler;
102 node->data = cbdataReference(data);
103
104 /* queue this validation request to be infored of the pending lookup results */
105 node->next = basic_auth->auth_queue;
106 basic_auth->auth_queue = node;
928f3421
AJ
107 return;
108 }
fe0a0419
AJ
109 // otherwise submit this request to the auth helper(s) for validation
110
111 /* mark this user as having verification in progress */
112 user()->credentials(Auth::Pending);
113 char buf[HELPER_INPUT_BUFFER];
114 static char username[HELPER_INPUT_BUFFER];
115 static char pass[HELPER_INPUT_BUFFER];
116 if (static_cast<Auth::Basic::Config*>(user()->config)->utf8) {
117 latin1_to_utf8(username, sizeof(username), user()->username());
118 latin1_to_utf8(pass, sizeof(pass), basic_auth->passwd);
119 xstrncpy(username, rfc1738_escape(username), sizeof(username));
120 xstrncpy(pass, rfc1738_escape(pass), sizeof(pass));
121 } else {
122 xstrncpy(username, rfc1738_escape(user()->username()), sizeof(username));
123 xstrncpy(pass, rfc1738_escape(basic_auth->passwd), sizeof(pass));
124 }
125 int sz = snprintf(buf, sizeof(buf), "%s %s\n", username, pass);
126 if (sz<=0) {
127 debugs(9, DBG_CRITICAL, "ERROR: Basic Authentication Failure. Can not build helper validation request.");
4c535e87 128 handler(data);
56946509 129 } else if (static_cast<size_t>(sz) >= sizeof(buf)) {
fe0a0419 130 debugs(9, DBG_CRITICAL, "ERROR: Basic Authentication Failure. user:password exceeds " << sizeof(buf) << " bytes.");
4c535e87 131 handler(data);
fe0a0419 132 } else
c7baff40 133 helperSubmit(basicauthenticators, buf, Auth::Basic::UserRequest::HandleReply,
fe0a0419 134 new Auth::StateData(this, handler, data));
928f3421
AJ
135}
136
fe0a0419 137void
c7baff40 138Auth::Basic::UserRequest::HandleReply(void *data, char *reply)
fe0a0419
AJ
139{
140 Auth::StateData *r = static_cast<Auth::StateData *>(data);
141 BasicAuthQueueNode *tmpnode;
142 char *t = NULL;
143 void *cbdata;
48e7baac 144 debugs(29, 5, HERE << "{" << (reply ? reply : "<NULL>") << "}");
fe0a0419
AJ
145
146 if (reply) {
f207fe64
FC
147 if ((t = strchr(reply, ' '))) {
148 *t = '\0';
149 ++t;
150 }
fe0a0419
AJ
151
152 if (*reply == '\0')
153 reply = NULL;
154 }
155
156 assert(r->auth_user_request != NULL);
157 assert(r->auth_user_request->user()->auth_type == Auth::AUTH_BASIC);
158
159 /* this is okay since we only play with the Auth::Basic::User child fields below
160 * and dont pass the pointer itself anywhere */
161 Auth::Basic::User *basic_auth = dynamic_cast<Auth::Basic::User *>(r->auth_user_request->user().getRaw());
162
163 assert(basic_auth != NULL);
164
165 if (reply && (strncasecmp(reply, "OK", 2) == 0))
166 basic_auth->credentials(Auth::Ok);
167 else {
168 basic_auth->credentials(Auth::Failed);
169
170 if (t && *t)
171 r->auth_user_request->setDenyMessage(t);
172 }
173
174 basic_auth->expiretime = squid_curtime;
175
176 if (cbdataReferenceValidDone(r->data, &cbdata))
4c535e87 177 r->handler(cbdata);
fe0a0419
AJ
178
179 cbdataReferenceDone(r->data);
180
181 while (basic_auth->auth_queue) {
182 tmpnode = basic_auth->auth_queue->next;
183
184 if (cbdataReferenceValidDone(basic_auth->auth_queue->data, &cbdata))
4c535e87 185 basic_auth->auth_queue->handler(cbdata);
fe0a0419
AJ
186
187 xfree(basic_auth->auth_queue);
188
189 basic_auth->auth_queue = tmpnode;
190 }
191
192 delete r;
193}