User.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/* DEBUG: section 29 Authenticator */
10
11#include "squid.h"
12#include "acl/Acl.h"
13#include "acl/Gadgets.h"
14#include "auth/Config.h"
16#include "auth/Gadgets.h"
17#include "auth/User.h"
18#include "auth/UserRequest.h"
19#include "event.h"
20#include "globals.h"
21#include "Store.h"
22
23Auth::User::User(Auth::SchemeConfig *aConfig, const char *aRequestRealm) :
24 auth_type(Auth::AUTH_UNKNOWN),
25 config(aConfig),
26 ipcount(0),
27 expiretime(0),
28 credentials_state(Auth::Unchecked),
29 username_(nullptr),
30 requestRealm_(aRequestRealm)
31{
33 ip_list.head = ip_list.tail = nullptr;
34 debugs(29, 5, "Initialised auth_user '" << this << "'.");
35}
36
39{
40 return credentials_state;
41}
42
43void
45{
46 credentials_state = newCreds;
47}
48
58void
60{
61 /*
62 * XXX Incomplete: it should merge in hash references too and ask the module to merge in scheme data
63 * dlink_list proxy_match_cache;
64 */
65
66 debugs(29, 5, "auth_user '" << from << "' into auth_user '" << this << "'.");
67
68 // combine the helper response annotations. Ensuring no duplicates are copied.
69 notes.appendNewOnly(&from->notes);
70
71 /* absorb the list of IP address sources (for max_user_ip controls) */
72 AuthUserIP *new_ipdata;
73 while (from->ip_list.head != nullptr) {
74 new_ipdata = static_cast<AuthUserIP *>(from->ip_list.head->data);
75
76 /* If this IP has expired - ignore the expensive merge actions. */
77 if (new_ipdata->ip_expiretime <= squid_curtime) {
78 /* This IP has expired - remove from the source list */
79 dlinkDelete(&new_ipdata->node, &(from->ip_list));
80 delete new_ipdata;
81 /* catch incipient underflow */
82 -- from->ipcount;
83 } else {
84 /* add to our list. replace if already present. */
85 AuthUserIP *ipdata = static_cast<AuthUserIP *>(ip_list.head->data);
86 bool found = false;
87 while (ipdata) {
88 AuthUserIP *tempnode = static_cast<AuthUserIP *>(ipdata->node.next->data);
89
90 if (ipdata->ipaddr == new_ipdata->ipaddr) {
91 /* This IP has already been seen. */
92 found = true;
93 /* update IP ttl and stop searching. */
94 ipdata->ip_expiretime = max(ipdata->ip_expiretime, new_ipdata->ip_expiretime);
95 break;
96 } else if (ipdata->ip_expiretime <= squid_curtime) {
97 /* This IP has expired - cleanup the destination list */
98 dlinkDelete(&ipdata->node, &ip_list);
99 delete ipdata;
100 /* catch incipient underflow */
101 assert(ipcount);
102 -- ipcount;
103 }
104
105 ipdata = tempnode;
106 }
107
108 if (!found) {
109 /* This ip is not in the seen list. Add it. */
110 dlinkAddTail(&new_ipdata->node, &ipdata->node, &ip_list);
111 ++ipcount;
112 /* remove from the source list */
113 dlinkDelete(&new_ipdata->node, &(from->ip_list));
114 ++from->ipcount;
115 }
116 }
117 }
118}
119
121{
122 debugs(29, 5, "Freeing auth_user '" << this << "'.");
123 assert(LockCount() == 0);
124
125 /* free cached acl results */
126 aclCacheMatchFlush(&proxy_match_cache);
127
128 /* free seen ip address's */
129 clearIp();
130
131 if (username_)
132 xfree((char*)username_);
133
134 /* prevent accidental reuse */
135 auth_type = Auth::AUTH_UNKNOWN;
136}
137
138void
140{
141 AuthUserIP *ipdata, *tempnode;
142
143 ipdata = (AuthUserIP *) ip_list.head;
144
145 while (ipdata) {
146 tempnode = (AuthUserIP *) ipdata->node.next;
147 /* walk the ip list */
148 dlinkDelete(&ipdata->node, &ip_list);
149 delete ipdata;
150 /* catch incipient underflow */
151 assert(ipcount);
152 -- ipcount;
153 ipdata = tempnode;
154 }
155
156 /* integrity check */
157 assert(ipcount == 0);
158}
159
160void
162{
163 AuthUserIP *ipdata = (AuthUserIP *) ip_list.head;
164
165 while (ipdata) {
166 /* walk the ip list */
167
168 if (ipdata->ipaddr == ipaddr) {
169 /* remove the node */
170 dlinkDelete(&ipdata->node, &ip_list);
171 delete ipdata;
172 /* catch incipient underflow */
173 assert(ipcount);
174 -- ipcount;
175 return;
176 }
177
178 ipdata = (AuthUserIP *) ipdata->node.next;
179 }
180
181}
182
183void
185{
186 AuthUserIP *ipdata = (AuthUserIP *) ip_list.head;
187 int found = 0;
188
189 /*
190 * we walk the entire list to prevent the first item in the list
191 * preventing old entries being flushed and locking a user out after
192 * a timeout+reconfigure
193 */
194 while (ipdata) {
195 AuthUserIP *tempnode = (AuthUserIP *) ipdata->node.next;
196 /* walk the ip list */
197
198 if (ipdata->ipaddr == ipaddr) {
199 /* This ip has already been seen. */
200 found = 1;
201 /* update IP ttl */
203 } else if (ipdata->ip_expiretime <= squid_curtime) {
204 /* This IP has expired - remove from the seen list */
205 dlinkDelete(&ipdata->node, &ip_list);
206 delete ipdata;
207 /* catch incipient underflow */
208 assert(ipcount);
209 -- ipcount;
210 }
211
212 ipdata = tempnode;
213 }
214
215 if (found)
216 return;
217
218 /* This ip is not in the seen list */
219 ipdata = new AuthUserIP(ipaddr, squid_curtime + Auth::TheConfig.ipTtl);
220
221 dlinkAddTail(ipdata, &ipdata->node, &ip_list);
222
223 ++ipcount;
224
225 debugs(29, 2, "user '" << username() << "' has been seen at a new IP address (" << ipaddr << ")");
226}
227
228SBuf
229Auth::User::BuildUserKey(const char *username, const char *realm)
230{
231 SBuf key;
232 if (realm)
233 key.Printf("%s:%s", username, realm);
234 else
235 key.append(username, strlen(username));
236 return key;
237}
238
242void
244{
245 auto userlist = authenticateCachedUsersList();
246 storeAppendPrintf(output, "Cached Usernames: %d", static_cast<int32_t>(userlist.size()));
247 storeAppendPrintf(output, "\n%-15s %-9s %-9s %-9s %s\t%s\n",
248 "Type",
249 "State",
250 "Check TTL",
251 "Cache TTL",
252 "Username", "Key");
253 storeAppendPrintf(output, "--------------- --------- --------- --------- ------------------------------\n");
254 for ( auto auth_user : userlist ) {
255 storeAppendPrintf(output, "%-15s %-9s %-9d %-9d %s\t" SQUIDSBUFPH "\n",
256 Auth::Type_str[auth_user->auth_type],
257 CredentialState_str[auth_user->credentials()],
258 auth_user->ttl(),
259 static_cast<int32_t>(auth_user->expiretime - squid_curtime + Auth::TheConfig.credentialsTtl),
260 auth_user->username(),
261 SQUIDSBUFPRINT(auth_user->userKey())
262 );
263 }
264}
265
266void
267Auth::User::username(char const *aString)
268{
269 if (aString) {
270 assert(!username_);
271 username_ = xstrdup(aString);
272 // NP: param #2 is working around a c_str() data-copy performance regression
273 userKey_ = BuildUserKey(username_, (!requestRealm_.isEmpty() ? requestRealm_.c_str() : nullptr));
274 } else {
275 safe_free(username_);
276 userKey_.clear();
277 }
278}
279
time_t squid_curtime
Definition: stub_libtime.cc:20
#define SQUIDSBUFPH
Definition: SBuf.h:31
#define SQUIDSBUFPRINT(s)
Definition: SBuf.h:32
#define assert(EX)
Definition: assert.h:17
std::vector< Auth::User::Pointer > authenticateCachedUsersList()
Definition: Gadgets.cc:108
Ip::Address ipaddr
IP address this user authenticated from.
Definition: UserRequest.h:47
dlink_node node
Definition: UserRequest.h:44
time_t ip_expiretime
Definition: UserRequest.h:53
time_t credentialsTtl
the authenticate_ttl
Definition: Config.h:43
time_t ipTtl
the authenticate_ip_ttl
Definition: Config.h:46
NotePairs notes
list of key=value pairs the helper produced
Definition: User.h:56
void absorb(Auth::User::Pointer from)
Definition: User.cc:59
dlink_list ip_list
Definition: User.h:121
size_t ipcount
Definition: User.h:52
CredentialState credentials() const
Definition: User.cc:38
static void CredentialsCacheStats(StoreEntry *output)
Definition: User.cc:243
char const * username() const
Definition: User.h:62
static SBuf BuildUserKey(const char *username, const char *realm)
Definition: User.cc:229
User(Auth::SchemeConfig *, const char *requestRealm)
Definition: User.cc:23
dlink_list proxy_match_cache
Definition: User.h:51
~User() override
Definition: User.cc:120
void clearIp()
Definition: User.cc:139
void removeIp(Ip::Address)
Definition: User.cc:161
void addIp(Ip::Address)
Definition: User.cc:184
Definition: SBuf.h:94
SBuf & Printf(const char *fmt,...) PRINTF_FORMAT_ARG2
Definition: SBuf.cc:214
SBuf & append(const SBuf &S)
Definition: SBuf.cc:185
A const & max(A const &lhs, A const &rhs)
#define debugs(SECTION, LEVEL, CONTENT)
Definition: Stream.h:194
void aclCacheMatchFlush(dlink_list *cache)
Definition: Acl.cc:391
HTTP Authentication.
Definition: Config.h:19
@ AUTH_UNKNOWN
Definition: Type.h:18
const char * Type_str[]
const char * CredentialState_str[]
Auth::Config TheConfig
Definition: Config.cc:15
#define xfree
#define xstrdup
void storeAppendPrintf(StoreEntry *e, const char *fmt,...)
Definition: store.cc:841
#define safe_free(x)
Definition: xalloc.h:73

 

Introduction

Documentation

Support

Miscellaneous

Web Site Translations

Mirrors