UserRequest.cc
Go to the documentation of this file.
1/*
2 * Copyright (C) 1996-2023 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#include "squid.h"
10#include "auth/basic/Config.h"
11#include "auth/basic/User.h"
13#include "auth/QueueNode.h"
14#include "auth/State.h"
15#include "debug/Stream.h"
16#include "format/Format.h"
17#include "helper.h"
18#include "helper/Reply.h"
19#include "HttpRequest.h"
20#include "MemBuf.h"
21#include "rfc1738.h"
22
23#if !defined(HELPER_INPUT_BUFFER)
24#define HELPER_INPUT_BUFFER 8192
25#endif
26
27int
28Auth::Basic::UserRequest::authenticated() const
29{
30 Auth::Basic::User const *basic_auth = dynamic_cast<Auth::Basic::User const *>(user().getRaw());
31
32 if (basic_auth && basic_auth->authenticated())
33 return 1;
34
35 return 0;
36}
37
38const char *
39Auth::Basic::UserRequest::credentialsStr()
40{
41 Auth::Basic::User const *basic_auth = dynamic_cast<Auth::Basic::User const *>(user().getRaw());
42 if (basic_auth)
43 return basic_auth->passwd;
44 return nullptr;
45}
46
47/* log a basic user in
48 */
49void
51{
52 assert(user() != nullptr);
53
54 /* if the password is not ok, do an identity */
55 if (!user() || user()->credentials() != Auth::Ok)
56 return;
57
58 /* are we about to recheck the credentials externally? */
59 if ((user()->expiretime + static_cast<Auth::Basic::Config*>(Auth::SchemeConfig::Find("basic"))->credentialsTTL) <= squid_curtime) {
60 debugs(29, 4, "credentials expired - rechecking");
61 return;
62 }
63
64 /* we have been through the external helper, and the credentials haven't expired */
65 debugs(29, 9, "user '" << user()->username() << "' authenticated");
66
67 /* Decode now takes care of finding the AuthUser struct in the cache */
68 /* after external auth occurs anyway */
69 user()->expiretime = current_time.tv_sec;
70}
71
73Auth::Basic::UserRequest::module_direction()
74{
75 /* null auth_user is checked for by Auth::UserRequest::direction() */
76 if (user()->auth_type != Auth::AUTH_BASIC)
77 return Auth::CRED_ERROR;
78
79 switch (user()->credentials()) {
80
81 case Auth::Unchecked:
82 case Auth::Pending:
83 return Auth::CRED_LOOKUP;
84
85 case Auth::Ok:
86 if (user()->expiretime + static_cast<Auth::Basic::Config*>(Auth::SchemeConfig::Find("basic"))->credentialsTTL <= squid_curtime)
87 return Auth::CRED_LOOKUP;
88 return Auth::CRED_VALID;
89
90 case Auth::Failed:
91 return Auth::CRED_VALID;
92
93 default:
94 return Auth::CRED_ERROR;
95 }
96}
97
98/* send the initial data to a basic authenticator module */
99void
100Auth::Basic::UserRequest::startHelperLookup(HttpRequest *request, AccessLogEntry::Pointer &al, AUTHCB * handler, void *data)
101{
102 assert(user()->auth_type == Auth::AUTH_BASIC);
103 Auth::Basic::User *basic_auth = dynamic_cast<Auth::Basic::User *>(user().getRaw());
104 assert(basic_auth != nullptr);
105 debugs(29, 9, "'" << basic_auth->username() << ":" << basic_auth->passwd << "'");
106
107 if (static_cast<Auth::Basic::Config*>(Auth::SchemeConfig::Find("basic"))->authenticateProgram == nullptr) {
108 debugs(29, DBG_CRITICAL, "ERROR: No Basic authentication program configured.");
109 handler(data);
110 return;
111 }
112
113 /* check to see if the auth_user already has a request outstanding */
114 if (user()->credentials() == Auth::Pending) {
115 /* there is a request with the same credentials already being verified */
116
117 Auth::QueueNode *node = new Auth::QueueNode(this, handler, data);
118
119 /* queue this validation request to be infored of the pending lookup results */
120 node->next = basic_auth->queue;
121 basic_auth->queue = node;
122 return;
123 }
124 // otherwise submit this request to the auth helper(s) for validation
125
126 /* mark this user as having verification in progress */
127 user()->credentials(Auth::Pending);
128 char buf[HELPER_INPUT_BUFFER];
129 static char usern[HELPER_INPUT_BUFFER];
130 static char pass[HELPER_INPUT_BUFFER];
131
132 xstrncpy(usern, rfc1738_escape(user()->username()), sizeof(usern));
133 xstrncpy(pass, rfc1738_escape(basic_auth->passwd), sizeof(pass));
134
135 int sz = 0;
136 if (const char *keyExtras = helperRequestKeyExtras(request, al))
137 sz = snprintf(buf, sizeof(buf), "%s %s %s\n", usern, pass, keyExtras);
138 else
139 sz = snprintf(buf, sizeof(buf), "%s %s\n", usern, pass);
140
141 if (sz<=0) {
142 debugs(9, DBG_CRITICAL, "ERROR: Basic Authentication Failure. Can not build helper validation request.");
143 handler(data);
144 } else if (static_cast<size_t>(sz) >= sizeof(buf)) {
145 debugs(9, DBG_CRITICAL, "ERROR: Basic Authentication Failure. user:password exceeds " << sizeof(buf) << " bytes.");
146 handler(data);
147 } else
148 helperSubmit(basicauthenticators, buf, Auth::Basic::UserRequest::HandleReply,
149 new Auth::StateData(this, handler, data));
150}
151
152void
153Auth::Basic::UserRequest::HandleReply(void *data, const Helper::Reply &reply)
154{
155 Auth::StateData *r = static_cast<Auth::StateData *>(data);
156 void *cbdata;
157 debugs(29, 5, "reply=" << reply);
158
159 assert(r->auth_user_request != nullptr);
160 assert(r->auth_user_request->user()->auth_type == Auth::AUTH_BASIC);
161
162 // add new helper kv-pair notes to the credentials object
163 // so that any transaction using those credentials can access them
164 static const NotePairs::Names appendables = { SBuf("group"), SBuf("tag") };
165 r->auth_user_request->user()->notes.replaceOrAddOrAppend(&reply.notes, appendables);
166
167 /* this is okay since we only play with the Auth::Basic::User child fields below
168 * and do not pass the pointer itself anywhere */
169 Auth::Basic::User *basic_auth = dynamic_cast<Auth::Basic::User *>(r->auth_user_request->user().getRaw());
170
171 assert(basic_auth != nullptr);
172
173 if (reply.result == Helper::Okay)
174 basic_auth->credentials(Auth::Ok);
175 else {
176 basic_auth->credentials(Auth::Failed);
177
178 if (reply.other().hasContent())
180 }
181
182 basic_auth->expiretime = squid_curtime;
183
185 r->handler(cbdata);
186
188
189 while (basic_auth->queue) {
190 if (cbdataReferenceValidDone(basic_auth->queue->data, &cbdata))
191 basic_auth->queue->handler(cbdata);
192
193 Auth::QueueNode *tmpnode = basic_auth->queue->next;
194 basic_auth->queue->next = nullptr;
195 delete basic_auth->queue;
196
197 basic_auth->queue = tmpnode;
198 }
199
200 delete r;
201}
202
time_t squid_curtime
Definition: stub_libtime.cc:20
class SquidConfig Config
Definition: SquidConfig.cc:12
void AUTHCB(void *)
Definition: UserRequest.h:57
#define assert(EX)
Definition: assert.h:17
Helper::ClientPointer basicauthenticators
Definition: Config.cc:39
#define HELPER_INPUT_BUFFER
Definition: UserRequest.cc:24
static void authenticate(int socket_fd, const char *username, const char *passwd)
#define cbdataReferenceDone(var)
Definition: cbdata.h:352
#define cbdataReferenceValidDone(var, ptr)
Definition: cbdata.h:239
Auth::QueueNode * next
Definition: QueueNode.h:54
static SchemeConfig * Find(const char *proxy_auth)
Definition: SchemeConfig.cc:59
UserRequest::Pointer auth_user_request
Definition: State.h:39
AUTHCB * handler
Definition: State.h:40
void * data
Definition: State.h:38
void setDenyMessage(char const *)
Definition: UserRequest.cc:114
virtual User::Pointer user()
Definition: UserRequest.h:143
NotePairs notes
Definition: Reply.h:62
Helper::ResultCode result
The helper response 'result' field.
Definition: Reply.h:59
const MemBuf & other() const
Definition: Reply.h:42
char * content()
start of the added data
Definition: MemBuf.h:41
bool hasContent() const
Definition: MemBuf.h:54
std::vector< SBuf > Names
Definition: Notes.h:199
C * getRaw() const
Definition: RefCount.h:89
Definition: SBuf.h:94
Definition: cbdata.cc:38
#define debugs(SECTION, LEVEL, CONTENT)
Definition: Stream.h:194
#define DBG_CRITICAL
Definition: Stream.h:37
void helperSubmit(const Helper::Client::Pointer &hlp, const char *const buf, HLPCB *const callback, void *const data)
Definition: helper.cc:480
@ AUTH_BASIC
Definition: Type.h:19
Direction
Definition: UserRequest.h:64
@ CRED_ERROR
ERROR in the auth module. Cannot determine the state of this request.
Definition: UserRequest.h:68
@ CRED_LOOKUP
Credentials need to be validated with the backend helper.
Definition: UserRequest.h:67
@ CRED_VALID
Credentials are valid and a up to date. The OK/Failed state is accurate.
Definition: UserRequest.h:66
@ Okay
Definition: ResultCode.h:18
static char credentials[MAX_USERNAME_LEN+MAX_DOMAIN_LEN+2]
static void handler(int signo)
Definition: purge.cc:858
#define rfc1738_escape(x)
Definition: rfc1738.h:52
Definition: parse.c:104
struct node * next
Definition: parse.c:105
struct timeval current_time
the current UNIX time in timeval {seconds, microseconds} format
Definition: gadgets.cc:17
char * xstrncpy(char *dst, const char *src, size_t n)
Definition: xstring.cc:37

 

Introduction

Documentation

Support

Miscellaneous

Web Site Translations

Mirrors