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

 

Introduction

Documentation

Support

Miscellaneous

Web Site Translations

Mirrors