]>
Commit | Line | Data |
---|---|---|
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 | 15 | int |
c7baff40 | 16 | Auth::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 | */ | |
28 | void | |
c7baff40 | 29 | Auth::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 | 53 | Auth::Direction |
c7baff40 | 54 | Auth::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 */ | |
80 | void | |
4c535e87 | 81 | Auth::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 | 137 | void |
c7baff40 | 138 | Auth::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 | } |