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