#define SQUID_SQUIDCONFIG_H_
#include "acl/forward.h"
+#if USE_AUTH
+#include "auth/SchemesConfig.h"
+#endif
#include "base/RefCount.h"
#include "base/YesNoNone.h"
#include "ClientDelayConfig.h"
acl_access *forceRequestBodyContinuation;
acl_access *serverPconnForNonretriable;
+#if USE_AUTH
+ acl_access *authSchemes;
+#endif
} accessList;
AclDenyInfoList *denyInfoList;
ssize_t packet_max; ///< maximum size EDNS advertised for DNS replies.
} dns;
+#if USE_AUTH
+ Auth::SchemesConfigs authSchemesConfigs;
+#endif
};
extern SquidConfig Config;
return NULL;
}
+Auth::Config *
+Auth::Config::GetParsed(const char *proxy_auth)
+{
+ if (auto *cfg = Find(proxy_auth))
+ return cfg;
+ fatalf("auth_schemes: required authentication method '%s' is not configured", proxy_auth);
+ return nullptr;
+}
+
/** Default behaviour is to expose nothing */
void
Auth::Config::registerWithCacheManager(void)
static UserRequest::Pointer CreateAuthUser(const char *proxy_auth, AccessLogEntry::Pointer &al);
static Config *Find(const char *proxy_auth);
+ /// Call this method if you need a guarantee that all auth schemes has been
+ /// already configured.
+ static Config *GetParsed(const char *proxy_auth);
Config() : authenticateChildren(20), authenticateProgram(NULL), keyExtras(NULL) {}
virtual ~Config() {}
QueueNode.h \
Scheme.cc \
Scheme.h \
+ SchemesConfig.h \
+ SchemesConfig.cc \
State.h \
State.cc \
User.h \
--- /dev/null
+/*
+ * Copyright (C) 1996-2016 The Squid Software Foundation and contributors
+ *
+ * Squid software is distributed under GPLv2+ license and includes
+ * contributions from numerous individuals and organizations.
+ * Please see the COPYING and CONTRIBUTORS files for details.
+ */
+
+#include "squid.h"
+#include "auth/Config.h"
+#include "auth/SchemesConfig.h"
+#include "fatal.h"
+#include "parser/Tokenizer.h"
+
+static void
+addUnique(const SBuf &scheme, std::vector<SBuf> &vec)
+{
+ static const SBuf all("ALL");
+ if (scheme == all) {
+ for (const auto config: Auth::TheConfig)
+ addUnique(SBuf(config->type()), vec);
+ } else if (std::find(vec.begin(), vec.end(), scheme) == vec.end())
+ vec.push_back(scheme);
+}
+
+void
+Auth::SchemesConfig::expand()
+{
+ static const CharacterSet delimiters("delimiters", ",");
+ static const CharacterSet quotedDelimiters("quotedDelimiters", ", ");
+ const CharacterSet *resultDelimiters = quoted ? "edDelimiters : &delimiters;
+ std::vector<SBuf> expanded;
+ Parser::Tokenizer t(schemes);
+ SBuf scheme;
+ while (t.token(scheme, *resultDelimiters))
+ addUnique(scheme, expanded);
+ t.skipAllTrailing(CharacterSet::SP + CharacterSet::HTAB);
+ if (!t.remaining().isEmpty())
+ addUnique(t.remaining(), expanded);
+
+ authConfigs.clear();
+ transform(expanded.begin(), expanded.end(),
+ back_inserter(authConfigs), [](SBuf &s) {
+ return Auth::Config::GetParsed(s.c_str());
+ });
+}
+
--- /dev/null
+/*
+ * Copyright (C) 1996-2016 The Squid Software Foundation and contributors
+ *
+ * Squid software is distributed under GPLv2+ license and includes
+ * contributions from numerous individuals and organizations.
+ * Please see the COPYING and CONTRIBUTORS files for details.
+ */
+
+#ifndef SQUID_SCHEMES_CONFIG_H
+#define SQUID_SCHEMES_CONFIG_H
+
+#if USE_AUTH
+
+#include "auth/Config.h"
+
+namespace Auth
+{
+
+/**
+ * \ingroup AuthAPI
+ * Stores authentication schemes list, configured by auth_schemes
+ * directive.
+ */
+class SchemesConfig
+{
+public:
+ SchemesConfig(const char *s, const bool q) : schemes(s), quoted(q), rawSchemes(schemes.c_str()) {}
+ /// Expands special "ALL" scheme name (if provided), removes
+ /// duplicates and fills authConfigs vector.
+ void expand();
+
+public:
+ /// corresponding vector of Auth::Config objects
+ ConfigVector authConfigs;
+
+private:
+ /// raw auth schemes list (may have duplicates)
+ SBuf schemes;
+ const bool quoted;
+
+public:
+ /// optimization for storing schemes.c_str()
+ const char *rawSchemes;
+};
+
+typedef std::vector<SchemesConfig> SchemesConfigs;
+
+} // namespace Auth
+
+#endif /* USE_AUTH */
+#endif /* SQUID_SCHEMES_CONFIG_H */
+
* See acl.c for access control and client_side.c for auditing */
#include "squid.h"
+#include "acl/FilledChecklist.h"
#include "auth/Config.h"
#include "auth/Scheme.h"
+#include "auth/SchemesConfig.h"
#include "auth/User.h"
#include "auth/UserRequest.h"
#include "client_side.h"
#include "HttpReply.h"
#include "HttpRequest.h"
#include "MemBuf.h"
+#include "SquidConfig.h"
/* Generic Functions */
return result;
}
+static Auth::ConfigVector &
+schemesConfig(HttpRequest *request, HttpReply *rep)
+{
+ if (::Config.accessList.authSchemes) {
+ ACLFilledChecklist ch(NULL, request, NULL);
+ ch.reply = rep;
+ HTTPMSGLOCK(ch.reply);
+ const allow_t answer = ch.fastCheck(::Config.accessList.authSchemes);
+ if (answer == ACCESS_ALLOWED)
+ return ::Config.authSchemesConfigs.at(answer.kind).authConfigs;
+ }
+ return Auth::TheConfig;
+}
+
void
Auth::UserRequest::addReplyAuthHeader(HttpReply * rep, Auth::UserRequest::Pointer auth_user_request, HttpRequest * request, int accelerated, int internal)
/* send the auth types we are configured to support (and have compiled in!) */
auth_user_request->user()->config->fixHeader(auth_user_request, rep, type, request);
else {
/* call each configured & running authscheme */
-
- for (Auth::ConfigVector::iterator i = Auth::TheConfig.begin(); i != Auth::TheConfig.end(); ++i) {
+ Auth::ConfigVector &configs = schemesConfig(request, rep);
+ for (Auth::ConfigVector::iterator i = configs.begin(); i != configs.end(); ++i) {
Auth::Config *scheme = *i;
if (scheme->active()) {
#if USE_AUTH
#include "auth/Config.h"
#include "auth/Scheme.h"
+#include "auth/SchemesConfig.h"
#endif
#if USE_SQUID_ESI
#include "esi/Parser.h"
static void parse_on_unsupported_protocol(acl_access **access);
static void dump_on_unsupported_protocol(StoreEntry *entry, const char *name, acl_access *access);
static void free_on_unsupported_protocol(acl_access **access);
+static void ParseAclWithAction(acl_access **access, const allow_t &action, const char *desc, ACL *acl = nullptr);
/*
* LegacyParser is a parser for legacy code that uses the global
Config.pipeline_max_prefetch = 0;
}
}
+
+ for (auto &authSchemes: Config.authSchemesConfigs) {
+ authSchemes.expand();
+ if (authSchemes.authConfigs.empty()) {
+ debugs(3, DBG_CRITICAL, "auth_schemes: at least one scheme name is required; got: " << authSchemes.rawSchemes);
+ self_destruct();
+ }
+ }
#endif
}
for (Auth::ConfigVector::iterator i = cfg.begin(); i != cfg.end(); ++i)
(*i)->dump(entry, name, (*i));
}
+
+static void
+parse_AuthSchemes(acl_access **authSchemes)
+{
+ const char *tok = ConfigParser::NextQuotedToken();
+ if (!tok) {
+ debugs(29, DBG_CRITICAL, "FATAL: auth_schemes missing the parameter");
+ self_destruct();
+ return;
+ }
+ Config.authSchemesConfigs.push_back(Auth::SchemesConfig(tok, ConfigParser::LastTokenWasQuoted));
+ const allow_t action = allow_t(ACCESS_ALLOWED, Config.authSchemesConfigs.size() - 1);
+ ParseAclWithAction(authSchemes, action, "auth_schemes");
+}
+
+static void
+free_AuthSchemes(acl_access **authSchemes)
+{
+ Config.authSchemesConfigs.clear();
+ free_acl_access(authSchemes);
+}
+
+static void
+dump_AuthSchemes(StoreEntry *entry, const char *name, acl_access *authSchemes)
+{
+ if (authSchemes)
+ dump_SBufList(entry, authSchemes->treeDump(name, [](const allow_t &action) {
+ return Config.authSchemesConfigs.at(action.kind).rawSchemes;
+ }));
+}
+
#endif /* USE_AUTH */
static void
-ParseAclWithAction(acl_access **access, const allow_t &action, const char *desc, ACL *acl = nullptr)
+ParseAclWithAction(acl_access **access, const allow_t &action, const char *desc, ACL *acl)
{
assert(access);
SBuf name;
acl_nfmark acl
address
authparam
+AuthSchemes
b_int64_t
b_size_t
b_ssize_t
environment with relatively static address assignments.
DOC_END
+NAME: auth_schemes
+TYPE: AuthSchemes
+IFDEF: USE_AUTH
+LOC: Config.accessList.authSchemes
+DEFAULT: none
+DEFAULT_DOC: use all auth_param schemes in their configuration order
+DOC_START
+ Use this directive to customize authentication schemes presence and
+ order in Squid's Unauthorized and Authentication Required responses.
+
+ auth_schemes scheme1,scheme2,... [!]aclname ...
+
+ where schemeN is the name of one of the authentication schemes
+ configured using auth_param directives. At least one scheme name is
+ required. Multiple scheme names are separated by commas. Either
+ avoid whitespace or quote the entire schemes list.
+
+ A special "ALL" scheme name expands to all auth_param-configured
+ schemes in their configuration order. This directive cannot be used
+ to configure Squid to offer no authentication schemes at all.
+
+ The first matching auth_schemes rule determines the schemes order
+ for the current Authentication Required transaction. Note that the
+ future response is not yet available during auth_schemes evaluation.
+
+ If this directive is not used or none of its rules match, then Squid
+ responds with all configured authentication schemes in the order of
+ auth_param directives in the configuration file.
+
+ This directive does not determine when authentication is used or
+ how each authentication scheme authenticates clients.
+
+ The following example sends basic and negotiate authentication
+ schemes, in that order, when requesting authentication of HTTP
+ requests matching the isIE ACL (not shown) while sending all
+ auth_param schemes in their configuration order to other clients:
+
+ auth_schemes basic,negotiate isIE
+ auth_schemes ALL all # explicit default
+
+ This directive supports fast ACLs only.
+
+ See also: auth_param.
+DOC_END
+
COMMENT_START
ACCESS CONTROLS
-----------------------------------------------------------------------------
#include "AuthReg.h"
void Auth::Init() STUB_NOP
+#include "auth/SchemesConfig.h"
+void Auth::SchemesConfig::expand() STUB
+
#endif /* USE_AUTH */