]>
git.ipfire.org Git - thirdparty/squid.git/blob - src/auth/basic/UserRequest.cc
75d5b7aa60b65e143524c077eeddc3832ea98082
2 * Copyright (C) 1996-2015 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.
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"
17 #include "format/Format.h"
19 #include "helper/Reply.h"
21 #include "HttpRequest.h"
24 #include "SquidTime.h"
26 #if !defined(HELPER_INPUT_BUFFER)
27 #define HELPER_INPUT_BUFFER 8192
31 Auth::Basic::UserRequest::authenticated() const
33 Auth::Basic::User
const *basic_auth
= dynamic_cast<Auth::Basic::User
const *>(user().getRaw());
35 if (basic_auth
&& basic_auth
->authenticated())
42 Auth::Basic::UserRequest::credentialsStr()
44 Auth::Basic::User
const *basic_auth
= dynamic_cast<Auth::Basic::User
const *>(user().getRaw());
46 return basic_auth
->passwd
;
50 /* log a basic user in
53 Auth::Basic::UserRequest::authenticate(HttpRequest
*, ConnStateData
*, Http::HdrType
)
55 assert(user() != NULL
);
57 /* if the password is not ok, do an identity */
58 if (!user() || user()->credentials() != Auth::Ok
)
61 /* are we about to recheck the credentials externally? */
62 if ((user()->expiretime
+ static_cast<Auth::Basic::Config
*>(Auth::Config::Find("basic"))->credentialsTTL
) <= squid_curtime
) {
63 debugs(29, 4, HERE
<< "credentials expired - rechecking");
67 /* we have been through the external helper, and the credentials haven't expired */
68 debugs(29, 9, HERE
<< "user '" << user()->username() << "' authenticated");
70 /* Decode now takes care of finding the AuthUser struct in the cache */
71 /* after external auth occurs anyway */
72 user()->expiretime
= current_time
.tv_sec
;
76 Auth::Basic::UserRequest::module_direction()
78 /* null auth_user is checked for by Auth::UserRequest::direction() */
79 if (user()->auth_type
!= Auth::AUTH_BASIC
)
80 return Auth::CRED_ERROR
;
82 switch (user()->credentials()) {
86 return Auth::CRED_LOOKUP
;
89 if (user()->expiretime
+ static_cast<Auth::Basic::Config
*>(Auth::Config::Find("basic"))->credentialsTTL
<= squid_curtime
)
90 return Auth::CRED_LOOKUP
;
91 return Auth::CRED_VALID
;
94 return Auth::CRED_VALID
;
97 return Auth::CRED_ERROR
;
101 /* send the initial data to a basic authenticator module */
103 Auth::Basic::UserRequest::startHelperLookup(HttpRequest
*request
, AccessLogEntry::Pointer
&al
, AUTHCB
* handler
, void *data
)
105 assert(user()->auth_type
== Auth::AUTH_BASIC
);
106 Auth::Basic::User
*basic_auth
= dynamic_cast<Auth::Basic::User
*>(user().getRaw());
107 assert(basic_auth
!= NULL
);
108 debugs(29, 9, HERE
<< "'" << basic_auth
->username() << ":" << basic_auth
->passwd
<< "'");
110 if (static_cast<Auth::Basic::Config
*>(Auth::Config::Find("basic"))->authenticateProgram
== NULL
) {
111 debugs(29, DBG_CRITICAL
, "ERROR: No Basic authentication program configured.");
116 /* check to see if the auth_user already has a request outstanding */
117 if (user()->credentials() == Auth::Pending
) {
118 /* there is a request with the same credentials already being verified */
120 Auth::QueueNode
*node
= new Auth::QueueNode(this, handler
, data
);
122 /* queue this validation request to be infored of the pending lookup results */
123 node
->next
= basic_auth
->queue
;
124 basic_auth
->queue
= node
;
127 // otherwise submit this request to the auth helper(s) for validation
129 /* mark this user as having verification in progress */
130 user()->credentials(Auth::Pending
);
131 char buf
[HELPER_INPUT_BUFFER
];
132 static char usern
[HELPER_INPUT_BUFFER
];
133 static char pass
[HELPER_INPUT_BUFFER
];
134 if (static_cast<Auth::Basic::Config
*>(user()->config
)->utf8
) {
135 latin1_to_utf8(usern
, sizeof(usern
), user()->username());
136 latin1_to_utf8(pass
, sizeof(pass
), basic_auth
->passwd
);
137 xstrncpy(usern
, rfc1738_escape(usern
), sizeof(usern
));
138 xstrncpy(pass
, rfc1738_escape(pass
), sizeof(pass
));
140 xstrncpy(usern
, rfc1738_escape(user()->username()), sizeof(usern
));
141 xstrncpy(pass
, rfc1738_escape(basic_auth
->passwd
), sizeof(pass
));
144 if (const char *keyExtras
= helperRequestKeyExtras(request
, al
))
145 sz
= snprintf(buf
, sizeof(buf
), "%s %s %s\n", usern
, pass
, keyExtras
);
147 sz
= snprintf(buf
, sizeof(buf
), "%s %s\n", usern
, pass
);
150 debugs(9, DBG_CRITICAL
, "ERROR: Basic Authentication Failure. Can not build helper validation request.");
152 } else if (static_cast<size_t>(sz
) >= sizeof(buf
)) {
153 debugs(9, DBG_CRITICAL
, "ERROR: Basic Authentication Failure. user:password exceeds " << sizeof(buf
) << " bytes.");
156 helperSubmit(basicauthenticators
, buf
, Auth::Basic::UserRequest::HandleReply
,
157 new Auth::StateData(this, handler
, data
));
161 Auth::Basic::UserRequest::HandleReply(void *data
, const Helper::Reply
&reply
)
163 Auth::StateData
*r
= static_cast<Auth::StateData
*>(data
);
165 debugs(29, 5, HERE
<< "reply=" << reply
);
167 assert(r
->auth_user_request
!= NULL
);
168 assert(r
->auth_user_request
->user()->auth_type
== Auth::AUTH_BASIC
);
170 // add new helper kv-pair notes to the credentials object
171 // so that any transaction using those credentials can access them
172 r
->auth_user_request
->user()->notes
.appendNewOnly(&reply
.notes
);
174 /* this is okay since we only play with the Auth::Basic::User child fields below
175 * and dont pass the pointer itself anywhere */
176 Auth::Basic::User
*basic_auth
= dynamic_cast<Auth::Basic::User
*>(r
->auth_user_request
->user().getRaw());
178 assert(basic_auth
!= NULL
);
180 if (reply
.result
== Helper::Okay
)
181 basic_auth
->credentials(Auth::Ok
);
183 basic_auth
->credentials(Auth::Failed
);
185 if (reply
.other().hasContent())
186 r
->auth_user_request
->setDenyMessage(reply
.other().content());
189 basic_auth
->expiretime
= squid_curtime
;
191 if (cbdataReferenceValidDone(r
->data
, &cbdata
))
194 cbdataReferenceDone(r
->data
);
196 while (basic_auth
->queue
) {
197 if (cbdataReferenceValidDone(basic_auth
->queue
->data
, &cbdata
))
198 basic_auth
->queue
->handler(cbdata
);
200 Auth::QueueNode
*tmpnode
= basic_auth
->queue
->next
;
201 basic_auth
->queue
->next
= NULL
;
202 delete basic_auth
->queue
;
204 basic_auth
->queue
= tmpnode
;