]>
git.ipfire.org Git - thirdparty/squid.git/blob - src/auth/SchemeConfig.cc
2 * Copyright (C) 1996-2023 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.
9 /* DEBUG: section 29 Authenticator */
12 #include "auth/Config.h"
13 #include "auth/forward.h"
14 #include "auth/Gadgets.h"
15 #include "auth/UserRequest.h"
17 #include "ConfigParser.h"
18 #include "debug/Stream.h"
19 #include "errorpage.h"
20 #include "format/Format.h"
26 * Get an User credentials object filled out for the given Proxy- or WWW-Authenticate header.
27 * Any decoding which needs to be done will be done.
29 * It may be a cached AuthUser or a new Unauthenticated object.
30 * It may also be NULL reflecting that no user could be created.
32 Auth::UserRequest::Pointer
33 Auth::SchemeConfig::CreateAuthUser(const char *proxy_auth
, AccessLogEntry::Pointer
&al
)
35 assert(proxy_auth
!= nullptr);
36 debugs(29, 9, "header = '" << proxy_auth
<< "'");
38 Auth::SchemeConfig
*config
= Find(proxy_auth
);
40 if (config
== nullptr || !config
->active()) {
41 debugs(29, (shutting_down
?3:DBG_IMPORTANT
), (shutting_down
?"":"WARNING: ") <<
42 "Unsupported or unconfigured/inactive proxy-auth scheme, '" << proxy_auth
<< "'");
47 if (config
->keyExtras
) {
48 // %credentials and %username, which normally included in
49 // request_format, are - at this time, but that is OK
50 // because user name is added to key explicitly, and we do
51 // not want to store authenticated credentials at all.
52 config
->keyExtras
->assemble(rmb
, al
, 0);
55 return config
->decode(proxy_auth
, al
->request
, rmb
.hasContent() ? rmb
.content() : nullptr);
59 Auth::SchemeConfig::Find(const char *proxy_auth
)
61 for (auto *scheme
: Auth::TheConfig
.schemes
) {
62 if (strncasecmp(proxy_auth
, scheme
->type(), strlen(scheme
->type())) == 0)
70 Auth::SchemeConfig::GetParsed(const char *proxy_auth
)
72 if (auto *cfg
= Find(proxy_auth
))
74 fatalf("auth_schemes: required authentication method '%s' is not configured", proxy_auth
);
78 /** Default behaviour is to expose nothing */
80 Auth::SchemeConfig::registerWithCacheManager(void)
84 Auth::SchemeConfig::parse(Auth::SchemeConfig
* scheme
, int, char *param_str
)
86 if (strcmp(param_str
, "program") == 0) {
87 if (authenticateProgram
)
88 wordlistDestroy(&authenticateProgram
);
90 parse_wordlist(&authenticateProgram
);
92 requirePathnameExists("Authentication helper program", authenticateProgram
->key
);
94 } else if (strcmp(param_str
, "realm") == 0) {
97 char *token
= ConfigParser::NextQuotedOrToEol();
99 while (token
&& *token
&& xisspace(*token
))
102 if (!token
|| !*token
) {
103 debugs(29, DBG_PARSE_NOTE(DBG_IMPORTANT
), "ERROR: Missing auth_param " << scheme
->type() << " realm");
110 } else if (strcmp(param_str
, "children") == 0) {
111 authenticateChildren
.parseConfig();
113 } else if (strcmp(param_str
, "key_extras") == 0) {
114 keyExtrasLine
= ConfigParser::NextQuotedToken();
115 Format::Format
*nlf
= new ::Format::Format(scheme
->type());
116 if (!nlf
->parse(keyExtrasLine
.termedBuf())) {
117 debugs(29, DBG_CRITICAL
, "FATAL: Failed parsing key_extras formatting value");
126 if (char *t
= strtok(nullptr, w_space
)) {
127 debugs(29, DBG_CRITICAL
, "FATAL: Unexpected argument '" << t
<< "' after request_format specification");
130 } else if (strcmp(param_str
, "keep_alive") == 0) {
131 parse_onoff(&keep_alive
);
132 } else if (strcmp(param_str
, "utf8") == 0) {
135 debugs(29, DBG_CRITICAL
, "ERROR: Unrecognised " << scheme
->type() << " auth scheme parameter '" << param_str
<< "'");
140 Auth::SchemeConfig::dump(StoreEntry
*entry
, const char *name
, Auth::SchemeConfig
*scheme
) const
142 if (!authenticateProgram
)
143 return false; // not configured
145 const char *schemeType
= scheme
->type();
147 wordlist
*list
= authenticateProgram
;
148 storeAppendPrintf(entry
, "%s %s", name
, schemeType
);
149 while (list
!= nullptr) {
150 storeAppendPrintf(entry
, " %s", list
->key
);
153 storeAppendPrintf(entry
, "\n");
155 storeAppendPrintf(entry
, "%s %s realm " SQUIDSBUFPH
"\n", name
, schemeType
, SQUIDSBUFPRINT(realm
));
157 storeAppendPrintf(entry
, "%s %s children %d startup=%d idle=%d concurrency=%d\n",
159 authenticateChildren
.n_max
, authenticateChildren
.n_startup
,
160 authenticateChildren
.n_idle
, authenticateChildren
.concurrency
);
162 if (keyExtrasLine
.size() > 0) // default is none
163 storeAppendPrintf(entry
, "%s %s key_extras \"%s\"\n", name
, schemeType
, keyExtrasLine
.termedBuf());
165 if (!keep_alive
) // default is on
166 storeAppendPrintf(entry
, "%s %s keep_alive off\n", name
, schemeType
);
168 if (utf8
) // default is off
169 storeAppendPrintf(entry
, "%s %s utf8 on\n", name
, schemeType
);
175 Auth::SchemeConfig::done()
179 keyExtrasLine
.clean();
183 Auth::SchemeConfig::isCP1251EncodingAllowed(const HttpRequest
*request
)
187 if (!request
|| !request
->header
.getList(Http::HdrType::ACCEPT_LANGUAGE
, &hdr
))
191 size_t pos
= 0; // current parsing position in header string
193 while (strHdrAcptLangGetItem(hdr
, lang
, 256, pos
)) {
195 /* wildcard uses the configured default language */
196 if (lang
[0] == '*' && lang
[1] == '\0')
199 if ((strncmp(lang
, "ru", 2) == 0 // Russian
200 || strncmp(lang
, "uk", 2) == 0 // Ukrainian
201 || strncmp(lang
, "be", 2) == 0 // Belorussian
202 || strncmp(lang
, "bg", 2) == 0 // Bulgarian
203 || strncmp(lang
, "sr", 2) == 0)) { // Serbian
204 if (lang
[2] == '-') {
205 if (strcmp(lang
+ 3, "latn") == 0) // not Cyrillic
207 } else if (xisalpha(lang
[2])) {