]>
git.ipfire.org Git - thirdparty/squid.git/blob - src/auth/User.cc
2 * Copyright (C) 1996-2022 The Squid Software Foundation and contributors
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.
9 /* DEBUG: section 29 Authenticator */
13 #include "acl/Gadgets.h"
14 #include "auth/Config.h"
15 #include "auth/CredentialsCache.h"
16 #include "auth/Gadgets.h"
17 #include "auth/User.h"
18 #include "auth/UserRequest.h"
23 Auth::User::User(Auth::SchemeConfig
*aConfig
, const char *aRequestRealm
) :
24 auth_type(Auth::AUTH_UNKNOWN
),
28 credentials_state(Auth::Unchecked
),
30 requestRealm_(aRequestRealm
)
32 proxy_match_cache
.head
= proxy_match_cache
.tail
= nullptr;
33 ip_list
.head
= ip_list
.tail
= nullptr;
34 debugs(29, 5, "Initialised auth_user '" << this << "'.");
38 Auth::User::credentials() const
40 return credentials_state
;
44 Auth::User::credentials(CredentialState newCreds
)
46 credentials_state
= newCreds
;
50 * Combine two user structs. ONLY to be called from within a scheme
51 * module. The scheme module is responsible for ensuring that the
52 * two users _can_ be merged without invalidating all the request
53 * scheme data. The scheme is also responsible for merging any user
54 * related scheme data itself.
55 * The caller is responsible for altering all refcount pointers to
56 * the 'from' object. They are invalid once this method is complete.
59 Auth::User::absorb(Auth::User::Pointer from
)
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;
66 debugs(29, 5, "auth_user '" << from
<< "' into auth_user '" << this << "'.");
68 // combine the helper response annotations. Ensuring no duplicates are copied.
69 notes
.appendNewOnly(&from
->notes
);
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
);
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
));
81 /* catch incipient underflow */
84 /* add to our list. replace if already present. */
85 AuthUserIP
*ipdata
= static_cast<AuthUserIP
*>(ip_list
.head
->data
);
88 AuthUserIP
*tempnode
= static_cast<AuthUserIP
*>(ipdata
->node
.next
->data
);
90 if (ipdata
->ipaddr
== new_ipdata
->ipaddr
) {
91 /* This IP has already been seen. */
93 /* update IP ttl and stop searching. */
94 ipdata
->ip_expiretime
= max(ipdata
->ip_expiretime
, new_ipdata
->ip_expiretime
);
96 } else if (ipdata
->ip_expiretime
<= squid_curtime
) {
97 /* This IP has expired - cleanup the destination list */
98 dlinkDelete(&ipdata
->node
, &ip_list
);
100 /* catch incipient underflow */
109 /* This ip is not in the seen list. Add it. */
110 dlinkAddTail(&new_ipdata
->node
, &ipdata
->node
, &ip_list
);
112 /* remove from the source list */
113 dlinkDelete(&new_ipdata
->node
, &(from
->ip_list
));
122 debugs(29, 5, "Freeing auth_user '" << this << "'.");
123 assert(LockCount() == 0);
125 /* free cached acl results */
126 aclCacheMatchFlush(&proxy_match_cache
);
128 /* free seen ip address's */
132 xfree((char*)username_
);
134 /* prevent accidental reuse */
135 auth_type
= Auth::AUTH_UNKNOWN
;
139 Auth::User::clearIp()
141 AuthUserIP
*ipdata
, *tempnode
;
143 ipdata
= (AuthUserIP
*) ip_list
.head
;
146 tempnode
= (AuthUserIP
*) ipdata
->node
.next
;
147 /* walk the ip list */
148 dlinkDelete(&ipdata
->node
, &ip_list
);
150 /* catch incipient underflow */
156 /* integrity check */
157 assert(ipcount
== 0);
161 Auth::User::removeIp(Ip::Address ipaddr
)
163 AuthUserIP
*ipdata
= (AuthUserIP
*) ip_list
.head
;
166 /* walk the ip list */
168 if (ipdata
->ipaddr
== ipaddr
) {
169 /* remove the node */
170 dlinkDelete(&ipdata
->node
, &ip_list
);
172 /* catch incipient underflow */
178 ipdata
= (AuthUserIP
*) ipdata
->node
.next
;
184 Auth::User::addIp(Ip::Address ipaddr
)
186 AuthUserIP
*ipdata
= (AuthUserIP
*) ip_list
.head
;
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
195 AuthUserIP
*tempnode
= (AuthUserIP
*) ipdata
->node
.next
;
196 /* walk the ip list */
198 if (ipdata
->ipaddr
== ipaddr
) {
199 /* This ip has already been seen. */
202 ipdata
->ip_expiretime
= squid_curtime
+ Auth::TheConfig
.ipTtl
;
203 } else if (ipdata
->ip_expiretime
<= squid_curtime
) {
204 /* This IP has expired - remove from the seen list */
205 dlinkDelete(&ipdata
->node
, &ip_list
);
207 /* catch incipient underflow */
218 /* This ip is not in the seen list */
219 ipdata
= new AuthUserIP(ipaddr
, squid_curtime
+ Auth::TheConfig
.ipTtl
);
221 dlinkAddTail(ipdata
, &ipdata
->node
, &ip_list
);
225 debugs(29, 2, "user '" << username() << "' has been seen at a new IP address (" << ipaddr
<< ")");
229 Auth::User::BuildUserKey(const char *username
, const char *realm
)
233 key
.Printf("%s:%s", username
, realm
);
235 key
.append(username
, strlen(username
));
240 * Dump the username cache statistics for viewing...
243 Auth::User::CredentialsCacheStats(StoreEntry
*output
)
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",
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()],
259 static_cast<int32_t>(auth_user
->expiretime
- squid_curtime
+ Auth::TheConfig
.credentialsTtl
),
260 auth_user
->username(),
261 SQUIDSBUFPRINT(auth_user
->userKey())
267 Auth::User::username(char const *aString
)
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));
275 safe_free(username_
);