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

 

Introduction

Documentation

Support

Miscellaneous

Web Site Translations

Mirrors