Config.cc
Go to the documentation of this file.
1 /*
2  * Copyright (C) 1996-2025 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 Negotiate Authenticator */
10 
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 
15 #include "squid.h"
16 #include "auth/Gadgets.h"
17 #include "auth/negotiate/Config.h"
18 #include "auth/negotiate/Scheme.h"
19 #include "auth/negotiate/User.h"
21 #include "auth/State.h"
22 #include "cache_cf.h"
23 #include "client_side.h"
24 #include "helper.h"
25 #include "http/Stream.h"
26 #include "HttpHeaderTools.h"
27 #include "HttpReply.h"
28 #include "HttpRequest.h"
29 #include "mgr/Registration.h"
30 #include "Store.h"
31 #include "wordlist.h"
32 
34 
36 
38 
39 static hash_table *proxy_auth_cache = nullptr;
40 
41 void
42 Auth::Negotiate::Config::rotateHelpers()
43 {
44  /* schedule closure of existing helpers */
47  }
48 
49  /* NP: dynamic helper restart will ensure they start up again as needed. */
50 }
51 
52 void
53 Auth::Negotiate::Config::done()
54 {
56 
58 
61  }
62 
63  if (!shutting_down)
64  return;
65 
66  negotiateauthenticators = nullptr;
67 
68  if (authenticateProgram)
69  wordlistDestroy(&authenticateProgram);
70 
71  debugs(29, DBG_IMPORTANT, "Reconfigure: Negotiate authentication configuration cleared.");
72 }
73 
74 const char *
75 Auth::Negotiate::Config::type() const
76 {
77  return Auth::Negotiate::Scheme::GetInstance()->type();
78 }
79 
84 void
85 Auth::Negotiate::Config::init(Auth::SchemeConfig *)
86 {
87  if (authenticateProgram) {
88 
90 
91  if (negotiateauthenticators == nullptr)
92  negotiateauthenticators = statefulhelper::Make("negotiateauthenticator");
93 
94  if (!proxy_auth_cache)
95  proxy_auth_cache = hash_create((HASHCMP *) strcmp, 7921, hash_string);
96 
98 
99  negotiateauthenticators->cmdline = authenticateProgram;
100 
101  negotiateauthenticators->childs.updateLimits(authenticateChildren);
102 
104 
106  }
107 }
108 
109 void
110 Auth::Negotiate::Config::registerWithCacheManager(void)
111 {
112  Mgr::RegisterAction("negotiateauthenticator",
113  "Negotiate User Authenticator Stats",
115 }
116 
117 bool
118 Auth::Negotiate::Config::active() const
119 {
120  return authnegotiate_initialised == 1;
121 }
122 
123 void
124 Auth::Negotiate::Config::fixHeader(Auth::UserRequest::Pointer auth_user_request, HttpReply *rep, Http::HdrType reqType, HttpRequest * request)
125 {
126  if (!authenticateProgram)
127  return;
128 
129  /* Need keep-alive */
130  if (!request->flags.proxyKeepalive && request->flags.mustKeepalive)
131  return;
132 
133  /* New request, no user details */
134  if (auth_user_request == nullptr) {
135  debugs(29, 9, "Sending type:" << reqType << " header: 'Negotiate'");
136  httpHeaderPutStrf(&rep->header, reqType, "Negotiate");
137 
138  if (!keep_alive) {
139  /* drop the connection */
140  rep->header.delByName("keep-alive");
141  request->flags.proxyKeepalive = false;
142  }
143  } else {
144  Auth::Negotiate::UserRequest *negotiate_request = dynamic_cast<Auth::Negotiate::UserRequest *>(auth_user_request.getRaw());
145  assert(negotiate_request != nullptr);
146 
147  switch (negotiate_request->user()->credentials()) {
148 
149  case Auth::Failed:
150  /* here it makes sense to drop the connection, as auth is
151  * tied to it, even if MAYBE the client could handle it - Kinkie */
152  rep->header.delByName("keep-alive");
153  request->flags.proxyKeepalive = false;
154  [[fallthrough]];
155 
156  case Auth::Ok:
157  /* Special case: authentication finished OK but disallowed by ACL.
158  * Need to start over to give the client another chance.
159  */
160  if (negotiate_request->server_blob) {
161  debugs(29, 9, "Sending type:" << reqType << " header: 'Negotiate " << negotiate_request->server_blob << "'");
162  httpHeaderPutStrf(&rep->header, reqType, "Negotiate %s", negotiate_request->server_blob);
163  safe_free(negotiate_request->server_blob);
164  } else {
165  debugs(29, 9, "Connection authenticated");
166  httpHeaderPutStrf(&rep->header, reqType, "Negotiate");
167  }
168  break;
169 
170  case Auth::Unchecked:
171  /* semantic change: do not drop the connection.
172  * 2.5 implementation used to keep it open - Kinkie */
173  debugs(29, 9, "Sending type:" << reqType << " header: 'Negotiate'");
174  httpHeaderPutStrf(&rep->header, reqType, "Negotiate");
175  break;
176 
177  case Auth::Handshake:
178  /* we're waiting for a response from the client. Pass it the blob */
179  debugs(29, 9, "Sending type:" << reqType << " header: 'Negotiate " << negotiate_request->server_blob << "'");
180  httpHeaderPutStrf(&rep->header, reqType, "Negotiate %s", negotiate_request->server_blob);
181  safe_free(negotiate_request->server_blob);
182  break;
183 
184  default:
185  debugs(29, DBG_CRITICAL, "ERROR: Negotiate auth fixHeader: state " << negotiate_request->user()->credentials() << ".");
186  fatal("unexpected state in AuthenticateNegotiateFixErrorHeader.\n");
187  }
188  }
189 }
190 
191 static void
193 {
195  negotiateauthenticators->packStatsInto(sentry, "Negotiate Authenticator Statistics");
196 }
197 
198 /*
199  * Decode a Negotiate [Proxy-]Auth string, placing the results in the passed
200  * Auth_user structure.
201  */
203 Auth::Negotiate::Config::decode(char const *proxy_auth, const HttpRequest *, const char *aRequestRealm)
204 {
205  Auth::Negotiate::User *newUser = new Auth::Negotiate::User(Auth::SchemeConfig::Find("negotiate"), aRequestRealm);
206  Auth::UserRequest *auth_user_request = new Auth::Negotiate::UserRequest();
207  assert(auth_user_request->user() == nullptr);
208 
209  auth_user_request->user(newUser);
210  auth_user_request->user()->auth_type = Auth::AUTH_NEGOTIATE;
211 
212  auth_user_request->user()->BuildUserKey(proxy_auth, aRequestRealm);
213 
214  /* all we have to do is identify that it's Negotiate - the helper does the rest */
215  debugs(29, 9, "decode Negotiate authentication");
216  return auth_user_request;
217 }
218 
void fatal(const char *message)
Definition: fatal.cc:28
void wordlistDestroy(wordlist **list)
destroy a wordlist
Definition: wordlist.cc:16
int delByName(const SBuf &name)
Definition: HttpHeader.cc:647
void openSessions() override
Definition: helper.cc:327
#define DBG_CRITICAL
Definition: Stream.h:37
HttpHeader header
Definition: Message.h:74
int ipc_type
Definition: helper.h:120
RequestFlags flags
Definition: HttpRequest.h:141
static Pointer Make(const char *name)
Definition: helper.cc:763
HASHHASH hash_string
Definition: hash.h:45
@ AUTH_NEGOTIATE
Definition: Type.h:22
void packStatsInto(Packable *p, const char *label=nullptr) const
Dump some stats about the helper state to a Packable object.
Definition: helper.cc:694
C * getRaw() const
Definition: RefCount.h:89
int HASHCMP(const void *, const void *)
Definition: hash.h:13
ChildConfig & updateLimits(const ChildConfig &rhs)
Definition: ChildConfig.cc:45
virtual User::Pointer user()
Definition: UserRequest.h:143
static AUTHSSTATS authenticateNegotiateStats
Definition: Config.cc:33
void httpHeaderPutStrf(HttpHeader *hdr, Http::HdrType id, const char *fmt,...)
static SchemeConfig * Find(const char *proxy_auth)
Definition: SchemeConfig.cc:59
void helperStatefulShutdown(const statefulhelper::Pointer &hlp)
Definition: helper.cc:808
ChildConfig childs
Configuration settings for number running.
Definition: helper.h:119
#define safe_free(x)
Definition: xalloc.h:73
#define assert(EX)
Definition: assert.h:17
wordlist * cmdline
Definition: helper.h:115
static hash_table * proxy_auth_cache
Definition: Config.cc:39
void AUTHSSTATS(StoreEntry *)
Definition: Gadgets.h:21
bool mustKeepalive
Definition: RequestFlags.h:83
bool proxyKeepalive
Definition: RequestFlags.h:42
static int authnegotiate_initialised
Definition: Config.cc:37
hash_table * hash_create(HASHCMP *, int, HASHHASH *)
Definition: hash.cc:108
void RegisterAction(char const *action, char const *desc, OBJH *handler, Protected, Atomic, Format)
Definition: Registration.cc:54
#define DBG_IMPORTANT
Definition: Stream.h:38
virtual void done()
int shutting_down
Helper::StatefulClientPointer negotiateauthenticators
Definition: Config.cc:35
#define IPC_STREAM
Definition: defines.h:104
#define debugs(SECTION, LEVEL, CONTENT)
Definition: Stream.h:192

 

Introduction

Documentation

Support

Miscellaneous