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

 

Introduction

Documentation

Support

Miscellaneous

Web Site Translations

Mirrors