]> git.ipfire.org Git - thirdparty/squid.git/blame - src/auth/negotiate/Config.cc
Source Format Enforcement (#532)
[thirdparty/squid.git] / src / auth / negotiate / Config.cc
CommitLineData
6bf4f823 1/*
77b1029d 2 * Copyright (C) 1996-2020 The Squid Software Foundation and contributors
6bf4f823 3 *
bbc27441
AJ
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.
6bf4f823 7 */
8
bbc27441
AJ
9/* DEBUG: section 29 Negotiate Authenticator */
10
6bf4f823 11/* The functions in this file handle authentication.
12 * They DO NOT perform access control or auditing.
13 * See acl.c for access control and client_side.c for auditing */
14
582c2af2 15#include "squid.h"
3ad63615 16#include "auth/Gadgets.h"
12daeef6 17#include "auth/negotiate/Config.h"
602d9612
A
18#include "auth/negotiate/Scheme.h"
19#include "auth/negotiate/User.h"
20#include "auth/negotiate/UserRequest.h"
928f3421 21#include "auth/State.h"
8a01b99e 22#include "cache_cf.h"
6bf4f823 23#include "client_side.h"
24438ec5 24#include "helper.h"
d3dddfb5 25#include "http/Stream.h"
a5bac1d2 26#include "HttpHeaderTools.h"
6bf4f823 27#include "HttpReply.h"
28#include "HttpRequest.h"
602d9612 29#include "mgr/Registration.h"
cc192b50 30#include "SquidTime.h"
602d9612 31#include "Store.h"
d295d770 32#include "wordlist.h"
6bf4f823 33
6bf4f823 34static AUTHSSTATS authenticateNegotiateStats;
35
928f3421 36statefulhelper *negotiateauthenticators = NULL;
6bf4f823 37
38static int authnegotiate_initialised = 0;
39
6bf4f823 40static hash_table *proxy_auth_cache = NULL;
41
0bcb6908 42void
372fccd6 43Auth::Negotiate::Config::rotateHelpers()
0bcb6908
AJ
44{
45 /* schedule closure of existing helpers */
46 if (negotiateauthenticators) {
47 helperStatefulShutdown(negotiateauthenticators);
48 }
49
50 /* NP: dynamic helper restart will ensure they start up again as needed. */
51}
52
6bf4f823 53void
372fccd6 54Auth::Negotiate::Config::done()
6bf4f823 55{
dc79fed8 56 Auth::SchemeConfig::done();
d4806c91 57
6bf4f823 58 authnegotiate_initialised = 0;
59
5817ee13
AJ
60 if (negotiateauthenticators) {
61 helperStatefulShutdown(negotiateauthenticators);
5817ee13 62 }
6bf4f823 63
6bf4f823 64 if (!shutting_down)
65 return;
66
48d54e4d 67 delete negotiateauthenticators;
6bf4f823 68 negotiateauthenticators = NULL;
69
58ee2093
AJ
70 if (authenticateProgram)
71 wordlistDestroy(&authenticateProgram);
cdabe87d 72
372fccd6 73 debugs(29, DBG_IMPORTANT, "Reconfigure: Negotiate authentication configuration cleared.");
6bf4f823 74}
75
6bf4f823 76const char *
372fccd6 77Auth::Negotiate::Config::type() const
6bf4f823 78{
d6374be6 79 return Auth::Negotiate::Scheme::GetInstance()->type();
6bf4f823 80}
81
63be0a78 82/**
83 * Initialize helpers and the like for this auth scheme.
84 * Called AFTER parsing the config file
85 */
6bf4f823 86void
dc79fed8 87Auth::Negotiate::Config::init(Auth::SchemeConfig *)
6bf4f823 88{
58ee2093 89 if (authenticateProgram) {
81425fb6 90
6bf4f823 91 authnegotiate_initialised = 1;
92
93 if (negotiateauthenticators == NULL)
48d54e4d 94 negotiateauthenticators = new statefulhelper("negotiateauthenticator");
6bf4f823 95
96 if (!proxy_auth_cache)
30abd221 97 proxy_auth_cache = hash_create((HASHCMP *) strcmp, 7921, hash_string);
6bf4f823 98
99 assert(proxy_auth_cache);
100
58ee2093 101 negotiateauthenticators->cmdline = authenticateProgram;
6bf4f823 102
1af735c7 103 negotiateauthenticators->childs.updateLimits(authenticateChildren);
6bf4f823 104
105 negotiateauthenticators->ipc_type = IPC_STREAM;
106
107 helperStatefulOpenServers(negotiateauthenticators);
6bf4f823 108 }
109}
110
62ee09ca 111void
372fccd6 112Auth::Negotiate::Config::registerWithCacheManager(void)
62ee09ca 113{
8822ebee 114 Mgr::RegisterAction("negotiateauthenticator",
d9fc6862
A
115 "Negotiate User Authenticator Stats",
116 authenticateNegotiateStats, 0, 1);
62ee09ca 117}
118
6bf4f823 119bool
372fccd6 120Auth::Negotiate::Config::active() const
6bf4f823 121{
122 return authnegotiate_initialised == 1;
123}
124
125bool
372fccd6 126Auth::Negotiate::Config::configured() const
6bf4f823 127{
58ee2093 128 if (authenticateProgram && (authenticateChildren.n_max != 0)) {
372fccd6 129 debugs(29, 9, HERE << "returning configured");
6bf4f823 130 return true;
131 }
132
372fccd6 133 debugs(29, 9, HERE << "returning unconfigured");
6bf4f823 134 return false;
135}
136
6bf4f823 137void
789217a2 138Auth::Negotiate::Config::fixHeader(Auth::UserRequest::Pointer auth_user_request, HttpReply *rep, Http::HdrType reqType, HttpRequest * request)
6bf4f823 139{
58ee2093 140 if (!authenticateProgram)
6bf4f823 141 return;
142
81425fb6 143 /* Need keep-alive */
450fe1cb 144 if (!request->flags.proxyKeepalive && request->flags.mustKeepalive)
26ac0430 145 return;
81425fb6 146
6bf4f823 147 /* New request, no user details */
148 if (auth_user_request == NULL) {
372fccd6 149 debugs(29, 9, HERE << "Sending type:" << reqType << " header: 'Negotiate'");
076df709 150 httpHeaderPutStrf(&rep->header, reqType, "Negotiate");
6bf4f823 151
152 if (!keep_alive) {
153 /* drop the connection */
a9925b40 154 rep->header.delByName("keep-alive");
e857372a 155 request->flags.proxyKeepalive = false;
6bf4f823 156 }
157 } else {
c7baff40 158 Auth::Negotiate::UserRequest *negotiate_request = dynamic_cast<Auth::Negotiate::UserRequest *>(auth_user_request.getRaw());
27da7c21 159 assert(negotiate_request != NULL);
160
d232141d 161 switch (negotiate_request->user()->credentials()) {
6bf4f823 162
d87154ee 163 case Auth::Failed:
6bf4f823 164 /* here it makes sense to drop the connection, as auth is
165 * tied to it, even if MAYBE the client could handle it - Kinkie */
a9925b40 166 rep->header.delByName("keep-alive");
e857372a 167 request->flags.proxyKeepalive = false;
f53969cc 168 /* fall through */
6bf4f823 169
d87154ee 170 case Auth::Ok:
6bf4f823 171 /* Special case: authentication finished OK but disallowed by ACL.
172 * Need to start over to give the client another chance.
173 */
6bf4f823 174 if (negotiate_request->server_blob) {
372fccd6 175 debugs(29, 9, HERE << "Sending type:" << reqType << " header: 'Negotiate " << negotiate_request->server_blob << "'");
076df709 176 httpHeaderPutStrf(&rep->header, reqType, "Negotiate %s", negotiate_request->server_blob);
6bf4f823 177 safe_free(negotiate_request->server_blob);
178 } else {
372fccd6 179 debugs(29, 9, HERE << "Connection authenticated");
076df709 180 httpHeaderPutStrf(&rep->header, reqType, "Negotiate");
6bf4f823 181 }
6bf4f823 182 break;
183
d87154ee 184 case Auth::Unchecked:
6bf4f823 185 /* semantic change: do not drop the connection.
186 * 2.5 implementation used to keep it open - Kinkie */
372fccd6 187 debugs(29, 9, HERE << "Sending type:" << reqType << " header: 'Negotiate'");
076df709 188 httpHeaderPutStrf(&rep->header, reqType, "Negotiate");
6bf4f823 189 break;
190
d87154ee 191 case Auth::Handshake:
6bf4f823 192 /* we're waiting for a response from the client. Pass it the blob */
372fccd6 193 debugs(29, 9, HERE << "Sending type:" << reqType << " header: 'Negotiate " << negotiate_request->server_blob << "'");
076df709 194 httpHeaderPutStrf(&rep->header, reqType, "Negotiate %s", negotiate_request->server_blob);
6bf4f823 195 safe_free(negotiate_request->server_blob);
196 break;
197
6bf4f823 198 default:
372fccd6 199 debugs(29, DBG_CRITICAL, "ERROR: Negotiate auth fixHeader: state " << negotiate_request->user()->credentials() << ".");
6bf4f823 200 fatal("unexpected state in AuthenticateNegotiateFixErrorHeader.\n");
201 }
202 }
203}
204
6bf4f823 205static void
206authenticateNegotiateStats(StoreEntry * sentry)
207{
bf3e8d5a
AJ
208 if (negotiateauthenticators)
209 negotiateauthenticators->packStatsInto(sentry, "Negotiate Authenticator Statistics");
6bf4f823 210}
211
6bf4f823 212/*
81425fb6 213 * Decode a Negotiate [Proxy-]Auth string, placing the results in the passed
6bf4f823 214 * Auth_user structure.
215 */
c7baff40 216Auth::UserRequest::Pointer
7e851a3e 217Auth::Negotiate::Config::decode(char const *proxy_auth, const HttpRequest *, const char *aRequestRealm)
6bf4f823 218{
dc79fed8 219 Auth::Negotiate::User *newUser = new Auth::Negotiate::User(Auth::SchemeConfig::Find("negotiate"), aRequestRealm);
c7baff40 220 Auth::UserRequest *auth_user_request = new Auth::Negotiate::UserRequest();
6bf4f823 221 assert(auth_user_request->user() == NULL);
a33a428a 222
6bf4f823 223 auth_user_request->user(newUser);
616cfc4c 224 auth_user_request->user()->auth_type = Auth::AUTH_NEGOTIATE;
6bf4f823 225
c10ebce8
AJ
226 auth_user_request->user()->BuildUserKey(proxy_auth, aRequestRealm);
227
81425fb6 228 /* all we have to do is identify that it's Negotiate - the helper does the rest */
372fccd6 229 debugs(29, 9, HERE << "decode Negotiate authentication");
6bf4f823 230 return auth_user_request;
231}
f53969cc 232