[squid-dev] [PATCH] refactor Auth::Config
Amos Jeffries
squid3 at treenet.co.nz
Tue Dec 20 18:05:56 UTC 2016
This is the patch refactoring the Auth::Config objects to get v5
building again.
The object storing auth_param settings is renamed to SchemeConfig.
A new Auth::Config object is added. The objects holding auth_param,
auth_schemes and other authenticate_* directives settings are stored
there instead of just auth_params.
Lots of outdated doxygen docs that have more up to date copies elsewhere
are removed. The "\ingroup AuthAPI" are left for now since some auth
things are not yet in the Auth:: namespace, but other auth related
groups are dropped completely.
Code parsing and dumping auth_param lines has been de-duplicated. Along
with the keep_alive and utf8 settings, which are shared by multiple
schemes. This allows dropping several virtual methods from NTLM and
Negotiate scheme objects.
An auth/forward.h file is added for predefines. Some initial Auth::
symbols are listed there. It is not complete, but others can be added as
needed later.
Some unnecessary includes have been removed. There are probably more. I
just did the obvious ones related to the new auth/forward.h and
auth/Config.h files at this time.
Amos
-------------- next part --------------
=== removed file 'doc/Programming-Guide/BasicAuthentication.dox'
--- doc/Programming-Guide/BasicAuthentication.dox 2016-01-01 00:12:18 +0000
+++ doc/Programming-Guide/BasicAuthentication.dox 1970-01-01 00:00:00 +0000
@@ -1,51 +0,0 @@
-/*
- * 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.
- */
-
-/**
-\defgroup AuthAPIBasic Basic Authentication
-\ingroup AuthAPI
-
-\par
-Basic authentication provides a username and password. These
-are written to the authentication module processes on a single
-line, separated by a space:
-\code
-<USERNAME> <PASSWORD>
-\endcode
-
-\par
- The authentication module process reads username, password pairs
- on stdin and returns either "OK" or "ERR" on stdout for
- each input line.
-
-\par
- The following simple perl script demonstrates how the
- authentication module works. This script allows any
- user named "Dirk" (without checking the password)
- and allows any user that uses the password "Sekrit":
-
-\code
-#!/usr/bin/perl -w
-$|=1; # no buffering, important!
-while (<>) {
- chop;
- ($u,$p) = split;
- $ans = &check($u,$p);
- print "$ans\n";
-}
-
-sub check {
- local($u,$p) = @_;
- return 'ERR' unless (defined $p && defined $u);
- return 'OK' if ('Dirk' eq $u);
- return 'OK' if ('Sekrit' eq $p);
- return 'ERR';
-}
-\endcode
-
- */
=== modified file 'src/SquidConfig.h'
--- src/SquidConfig.h 2016-12-10 04:48:25 +0000
+++ src/SquidConfig.h 2016-12-19 14:14:57 +0000
@@ -1,35 +1,32 @@
/*
* 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_SQUIDCONFIG_H_
#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"
#include "DelayConfig.h"
#include "helper/ChildConfig.h"
#include "HttpHeaderTools.h"
#include "ip/Address.h"
#include "Notes.h"
#include "security/forward.h"
#include "SquidTime.h"
#if USE_OPENSSL
#include "ssl/support.h"
#endif
#include "store/forward.h"
#if USE_OPENSSL
class sslproxy_cert_sign;
class sslproxy_cert_adapt;
#endif
@@ -184,43 +181,40 @@
char *effectiveGroup;
struct {
wordlist *redirect;
wordlist *store_id;
#if USE_UNLINKD
char *unlinkd;
#endif
char *diskd;
#if USE_OPENSSL
char *ssl_password;
#endif
} Program;
Helper::ChildConfig redirectChildren;
Helper::ChildConfig storeIdChildren;
- time_t authenticateGCInterval;
- time_t authenticateTTL;
- time_t authenticateIpTTL;
struct {
char *surrogate_id;
} Accel;
char *appendDomain;
size_t appendDomainLen;
char *pidFilename;
char *netdbFilename;
char *mimeTablePathname;
char *etcHostsPath;
char *visibleHostname;
char *uniqueHostname;
wordlist *hostnameAliases;
char *errHtmlText;
struct {
char *host;
char *file;
time_t period;
unsigned short port;
@@ -383,43 +377,40 @@
#if USE_OPENSSL
acl_access *ssl_bump;
#endif
#if FOLLOW_X_FORWARDED_FOR
acl_access *followXFF;
#endif /* FOLLOW_X_FORWARDED_FOR */
/// acceptible PROXY protocol clients
acl_access *proxyProtocol;
/// spoof_client_ip squid.conf acl.
/// nil unless configured
acl_access* spoof_client_ip;
acl_access *on_unsupported_protocol;
acl_access *ftp_epsv;
acl_access *forceRequestBodyContinuation;
acl_access *serverPconnForNonretriable;
-#if USE_AUTH
- acl_access *authSchemes;
-#endif
} accessList;
AclDenyInfoList *denyInfoList;
struct {
size_t list_width;
int list_wrap;
char *anon_user;
int passive;
int epsv_all;
int epsv;
int eprt;
int sanitycheck;
int telnet;
} Ftp;
RefreshPattern *Refresh;
Store::DiskConfig cacheSwap;
struct {
char *directory;
@@ -526,44 +517,40 @@
#if USE_LOADABLE_MODULES
wordlist *loadable_module_names;
#endif
int client_ip_max_connections;
char *redirector_extras;
struct UrlHelperTimeout {
int action;
char *response;
} onUrlRewriteTimeout;
char *storeId_extras;
struct {
int v4_first; ///< Place IPv4 first in the order of DNS results.
ssize_t packet_max; ///< maximum size EDNS advertised for DNS replies.
} dns;
-
-#if USE_AUTH
- Auth::SchemesConfigs authSchemesConfigs;
-#endif
};
extern SquidConfig Config;
class SquidConfig2
{
public:
void clear() {
*this = SquidConfig2();
}
struct {
int enable_purge = 0;
} onoff;
uid_t effectiveUserID = 0;
gid_t effectiveGroupID = 0;
};
extern SquidConfig2 Config2;
=== added file 'src/auth/Config.cc'
--- src/auth/Config.cc 1970-01-01 00:00:00 +0000
+++ src/auth/Config.cc 2016-12-19 13:25:50 +0000
@@ -0,0 +1,16 @@
+/*
+ * 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.
+ */
+
+/* DEBUG: section 29 Authenticator */
+
+#include "squid.h"
+#include "acl/Tree.h"
+#include "auth/Config.h"
+
+Auth::Config Auth::TheConfig;
+
=== added file 'src/auth/Config.h'
--- src/auth/Config.h 1970-01-01 00:00:00 +0000
+++ src/auth/Config.h 2016-12-19 14:21:57 +0000
@@ -0,0 +1,49 @@
+/*
+ * 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_SRC_AUTH_CONFIG_H
+#define SQUID_SRC_AUTH_CONFIG_H
+
+#if USE_AUTH
+
+#include "acl/forward.h"
+#include "auth/SchemeConfig.h"
+#include "auth/SchemesConfig.h"
+
+namespace Auth
+{
+
+class Config
+{
+public:
+ /// set of auth_params directives
+ Auth::ConfigVector schemes;
+
+ /// set of auth_schemes directives
+ std::vector<Auth::SchemesConfig> schemeLists;
+
+ /// the ACL list for auth_schemes directives
+ acl_access *schemeAccess = nullptr;
+
+ /// the authenticate_cache_garbage_interval
+ time_t authenticateGCInterval;
+
+ /// the authenticate_ttl
+ time_t authenticateTTL;
+
+ /// the authenticate_ip_ttl
+ time_t authenticateIpTTL;
+};
+
+extern Auth::Config TheConfig;
+
+} // namespace Auth
+
+#endif /* USE_AUTH */
+#endif /* SQUID_SRC_AUTH_CONFIG_H */
+
=== modified file 'src/auth/CredentialsCache.cc'
--- src/auth/CredentialsCache.cc 2016-11-15 09:34:16 +0000
+++ src/auth/CredentialsCache.cc 2016-12-19 15:30:31 +0000
@@ -1,38 +1,37 @@
/*
* 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.
*/
/* DEBUG: section 29 Authenticator */
#include "squid.h"
#include "acl/Gadgets.h"
+#include "auth/Config.h"
#include "auth/CredentialsCache.h"
#include "base/RunnersRegistry.h"
#include "Debug.h"
#include "event.h"
-#include "SquidConfig.h"
-#include "SquidTime.h"
namespace Auth {
class CredentialCacheRr : public RegisteredRunner
{
public:
explicit CredentialCacheRr(const char *n, CredentialsCache * const c) :
name(n),
whichCache(c)
{}
virtual ~CredentialCacheRr() {
debugs(29, 5, "Terminating Auth credentials cache: " << name);
// invalidate the CBDATA reference.
// causes Auth::*::User::Cache() to produce nil / invalid pointer
delete whichCache.get();
}
virtual void endingShutdown() override {
debugs(29, 5, "Clearing Auth credentials cache: " << name);
@@ -68,41 +67,41 @@
debugs(29, 6, "lookup for " << userKey);
auto p = store_.find(userKey);
if (p == store_.end())
return User::Pointer(nullptr);
return p->second;
}
void
CredentialsCache::Cleanup(void *data)
{
debugs(29, 5, "checkpoint");
// data is this in disguise
CredentialsCache *self = static_cast<CredentialsCache *>(data);
self->cleanup();
}
void
CredentialsCache::cleanup()
{
// cache entries with expiretime <= expirationTime are to be evicted
- const time_t expirationTime = current_time.tv_sec - ::Config.authenticateTTL;
+ const time_t expirationTime = current_time.tv_sec - Auth::TheConfig.authenticateTTL;
const auto end = store_.end();
for (auto i = store_.begin(); i != end;) {
debugs(29, 6, "considering " << i->first << "(expires in " <<
(expirationTime - i->second->expiretime) << " sec)");
if (i->second->expiretime <= expirationTime) {
debugs(29, 6, "evicting " << i->first);
i = store_.erase(i); //erase advances i
} else {
++i;
}
}
gcScheduled_ = false;
scheduleCleanup();
}
void
CredentialsCache::insert(const SBuf &userKey, Auth::User::Pointer anAuth_user)
{
debugs(29, 6, "adding " << userKey << " (" << anAuth_user->username() << ")");
@@ -116,37 +115,37 @@
CredentialsCache::sortedUsersList() const
{
std::vector<Auth::User::Pointer> rv(size(), nullptr);
std::transform(store_.begin(), store_.end(), rv.begin(),
[](StoreType::value_type v) { return v.second; }
);
std::sort(rv.begin(), rv.end(),
[](const Auth::User::Pointer &lhs, const Auth::User::Pointer &rhs) {
return strcmp(lhs->username(), rhs->username()) < 0;
}
);
return rv;
}
void
CredentialsCache::scheduleCleanup()
{
if (!gcScheduled_ && store_.size()) {
gcScheduled_ = true;
eventAdd(cacheCleanupEventName, &CredentialsCache::Cleanup,
- this, ::Config.authenticateGCInterval, 1);
+ this, Auth::TheConfig.authenticateGCInterval, 1);
}
}
void
CredentialsCache::doConfigChangeCleanup()
{
// purge expired entries entirely
cleanup();
// purge the ACL match data stored in the credentials
for (auto i : store_) {
aclCacheMatchFlush(&i.second->proxy_match_cache);
}
}
} /* namespace Auth */
=== modified file 'src/auth/Gadgets.cc'
--- src/auth/Gadgets.cc 2016-01-24 17:41:43 +0000
+++ src/auth/Gadgets.cc 2016-12-20 10:20:36 +0000
@@ -22,128 +22,126 @@
#include "auth/digest/User.h"
#include "auth/Gadgets.h"
#include "auth/negotiate/User.h"
#include "auth/ntlm/User.h"
#include "auth/Scheme.h"
#include "auth/User.h"
#include "auth/UserRequest.h"
#include "client_side.h"
#include "globals.h"
#include "http/Stream.h"
#include "HttpReply.h"
#include "HttpRequest.h"
/**** PUBLIC FUNCTIONS (ALL GENERIC!) ****/
int
authenticateActiveSchemeCount(void)
{
int rv = 0;
- for (Auth::ConfigVector::iterator i = Auth::TheConfig.begin(); i != Auth::TheConfig.end(); ++i)
- if ((*i)->configured())
+ for (auto *scheme : Auth::TheConfig.schemes) {
+ if (scheme->configured())
++rv;
+ }
debugs(29, 9, HERE << rv << " active.");
return rv;
}
int
authenticateSchemeCount(void)
{
int rv = Auth::Scheme::GetSchemes().size();
debugs(29, 9, HERE << rv << " active.");
return rv;
}
static void
authenticateRegisterWithCacheManager(Auth::ConfigVector * config)
{
- for (Auth::ConfigVector::iterator i = config->begin(); i != config->end(); ++i) {
- Auth::Config *scheme = *i;
+ for (auto *scheme : *config)
scheme->registerWithCacheManager();
- }
}
void
authenticateInit(Auth::ConfigVector * config)
{
/* If we do not have any auth config state to create stop now. */
if (!config)
return;
- for (Auth::ConfigVector::iterator i = config->begin(); i != config->end(); ++i) {
- Auth::Config *schemeCfg = *i;
-
- if (schemeCfg->configured())
- schemeCfg->init(schemeCfg);
+ for (auto *scheme : *config) {
+ if (scheme->configured())
+ scheme->init(scheme);
}
authenticateRegisterWithCacheManager(config);
}
void
authenticateRotate(void)
{
- for (Auth::ConfigVector::iterator i = Auth::TheConfig.begin(); i != Auth::TheConfig.end(); ++i)
- if ((*i)->configured())
- (*i)->rotateHelpers();
+ for (auto *scheme : Auth::TheConfig.schemes) {
+ if (scheme->configured())
+ scheme->rotateHelpers();
+ }
}
void
authenticateReset(void)
{
debugs(29, 2, "Reset authentication State.");
// username cache is cleared via Runner registry
/* schedule shutdown of the helpers */
authenticateRotate();
/* free current global config details too. */
- Auth::TheConfig.clear();
+ Auth::TheConfig.schemes.clear();
}
std::vector<Auth::User::Pointer>
authenticateCachedUsersList()
{
auto aucp_compare = [=](const Auth::User::Pointer lhs, const Auth::User::Pointer rhs) {
return lhs->userKey() < rhs->userKey();
};
std::vector<Auth::User::Pointer> v1, v2, rv, u1, u2;
#if HAVE_AUTH_MODULE_BASIC
- if (Auth::Config::Find("basic") != nullptr)
+ if (Auth::SchemeConfig::Find("basic"))
u1 = Auth::Basic::User::Cache()->sortedUsersList();
#endif
#if HAVE_AUTH_MODULE_DIGEST
- if (Auth::Config::Find("digest") != nullptr)
+ if (Auth::SchemeConfig::Find("digest"))
u2 = Auth::Digest::User::Cache()->sortedUsersList();
#endif
if (u1.size() > 0 || u2.size() > 0) {
v1.reserve(u1.size()+u2.size());
std::merge(u1.begin(), u1.end(),u2.begin(), u2.end(),
std::back_inserter(v1), aucp_compare);
u1.clear();
u2.clear();
}
#if HAVE_AUTH_MODULE_NEGOTIATE
- if (Auth::Config::Find("negotiate") != nullptr)
+ if (Auth::SchemeConfig::Find("negotiate"))
u1 = Auth::Negotiate::User::Cache()->sortedUsersList();
#endif
#if HAVE_AUTH_MODULE_NTLM
- if (Auth::Config::Find("ntlm") != nullptr)
+ if (Auth::SchemeConfig::Find("ntlm"))
u2 = Auth::Ntlm::User::Cache()->sortedUsersList();
#endif
if (u1.size() > 0 || u2.size() > 0) {
v2.reserve(u1.size()+u2.size());
std::merge(u1.begin(), u1.end(),u2.begin(), u2.end(),
std::back_inserter(v2), aucp_compare);
}
rv.reserve(v1.size()+v2.size());
std::merge(v1.begin(), v1.end(),v2.begin(), v2.end(),
std::back_inserter(rv), aucp_compare);
return rv;
}
=== modified file 'src/auth/Gadgets.h'
--- src/auth/Gadgets.h 2016-01-01 00:12:18 +0000
+++ src/auth/Gadgets.h 2016-12-19 13:25:57 +0000
@@ -1,48 +1,40 @@
/*
* 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_AUTH_GADGETS_H
#define SQUID_AUTH_GADGETS_H
#if USE_AUTH
-#include "auth/Config.h"
#include "auth/User.h"
#include "hash.h"
-namespace Auth
-{
-class Scheme;
-}
class ConnStateData;
class StoreEntry;
-/**
- \ingroup AuthAPI
- \todo this should be a generic cachemgr API type ?
- */
+// TODO this should be a generic cachemgr API type ?
typedef void AUTHSSTATS(StoreEntry *);
/// \ingroup AuthAPI
void authenticateInit(Auth::ConfigVector *);
/** \ingroup AuthAPI
* Remove all idle authentication state. Intended for use by reconfigure.
*
* Removes the username cache contents and global configuration state.
* Stops just short of detaching the auth components completely.
*
* Currently active requests should finish. Howevee new requests will not use
* authentication unless something causes the global config to be rebuilt.
* Such as a configure load action adding config and re-running authenticateInit().
*/
void authenticateReset(void);
void authenticateRotate(void);
/// \ingroup AuthAPI
=== modified file 'src/auth/Makefile.am'
--- src/auth/Makefile.am 2016-12-10 04:48:25 +0000
+++ src/auth/Makefile.am 2016-12-19 13:25:57 +0000
@@ -8,45 +8,48 @@
include $(top_srcdir)/src/Common.am
include $(top_srcdir)/src/TestHeaders.am
SUBDIRS = $(AUTH_MODULES)
DIST_SUBDIRS = basic digest negotiate ntlm
noinst_LTLIBRARIES = libauth.la libacls.la
## not needed? $(AUTH_LIBS_TO_BUILD)
## EXTRA_LTLIBRARIES = libdigest.la libntlm.la libnegotiate.la
## authentication framework; this library is always built
libauth_la_SOURCES = \
Type.h \
Type.cc \
Config.cc \
Config.h \
CredentialsCache.h \
CredentialsCache.cc \
CredentialState.cc \
CredentialState.h \
+ forward.h \
Gadgets.cc \
Gadgets.h \
QueueNode.h \
Scheme.cc \
Scheme.h \
+ SchemeConfig.cc \
+ SchemeConfig.h \
SchemesConfig.h \
SchemesConfig.cc \
State.h \
State.cc \
User.h \
User.cc \
UserRequest.h \
UserRequest.cc
libauth_la_LIBADD = $(AUTH_LIBS_TO_BUILD)
libauth_la_DEPENDENCIES = $(AUTH_LIBS_TO_BUILD)
## authentication-dependent ACLs and authentication code they share
libacls_la_SOURCES = \
Acl.cc \
Acl.h \
\
AclMaxUserIp.cc \
AclMaxUserIp.h \
AclProxyAuth.cc \
=== modified file 'src/auth/QueueNode.h'
--- src/auth/QueueNode.h 2016-01-01 00:12:18 +0000
+++ src/auth/QueueNode.h 2016-12-19 13:25:58 +0000
@@ -1,31 +1,32 @@
/*
* 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_SRC_AUTH_QUEUENODE_H
#define SQUID_SRC_AUTH_QUEUENODE_H
+#include "auth/forward.h"
#include "cbdata.h"
namespace Auth
{
/**
* A queue of auth requests waiting for verification to occur.
*
* Certain authentication schemes such a Basic and Bearer auth
* permit credentials tokens to be repeated from multiple sources
* simultaneously. This queue node allows multiple validation
* queries to be collapsed into one backend helper lookup.
* CBDATA and handlers stored in these queue nodes can be notified
* all at once with a result when the lookup completes.
*/
class QueueNode
{
MEMPROXY_CLASS(Auth::QueueNode);
private:
=== modified file 'src/auth/Scheme.cc'
--- src/auth/Scheme.cc 2016-01-01 00:12:18 +0000
+++ src/auth/Scheme.cc 2016-12-19 13:25:59 +0000
@@ -1,34 +1,34 @@
/*
* 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.
*/
/* DEBUG: section 29 Authenticator */
#include "squid.h"
-#include "auth/Config.h"
#include "auth/Gadgets.h"
#include "auth/Scheme.h"
+#include "auth/SchemeConfig.h"
#include "globals.h"
std::vector<Auth::Scheme::Pointer> *Auth::Scheme::_Schemes = NULL;
void
Auth::Scheme::AddScheme(Auth::Scheme::Pointer instance)
{
iterator i = GetSchemes().begin();
while (i != GetSchemes().end()) {
assert(strcmp((*i)->type(), instance->type()) != 0);
++i;
}
GetSchemes().push_back(instance);
}
Auth::Scheme::Pointer
Auth::Scheme::Find(const char *typestr)
{
=== modified file 'src/auth/Scheme.h'
--- src/auth/Scheme.h 2016-01-01 00:12:18 +0000
+++ src/auth/Scheme.h 2016-12-19 13:26:00 +0000
@@ -1,88 +1,77 @@
/*
* 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_AUTH_SCHEME_H
#define SQUID_AUTH_SCHEME_H
#if USE_AUTH
+#include "auth/forward.h"
#include "base/RefCount.h"
-#include <vector>
-
-/**
- \defgroup AuthSchemeAPI Authentication Scheme API
- \ingroup AuthAPI
- */
-
namespace Auth
{
-class Config;
-
/**
- * \ingroup AuthAPI
- * \ingroup AuthSchemeAPI
- * \par
* I represent an authentication scheme. For now my children
* store the scheme metadata.
- * \par
+ *
* Should we need multiple configs of a single scheme,
* a new class should be made, and the config specific calls on Auth::Scheme moved to it.
*/
class Scheme : public RefCountable
{
public:
typedef RefCount<Scheme> Pointer;
typedef std::vector<Scheme::Pointer>::iterator iterator;
typedef std::vector<Scheme::Pointer>::const_iterator const_iterator;
public:
Scheme() : initialised (false) {};
virtual ~Scheme() {};
static void AddScheme(Scheme::Pointer);
/**
* Final termination of all authentication components.
* To be used only on shutdown. All global pointers are released.
* After this all schemes will appear completely unsupported
* until a call to InitAuthModules().
* Release the Auth::TheConfig handles instead to disable authentication
* without terminiating all support.
*/
static void FreeAll();
/**
* Locate an authentication scheme component by Name.
*/
static Scheme::Pointer Find(const char *);
/* per scheme methods */
virtual char const *type() const = 0;
virtual void shutdownCleanup() = 0;
- virtual Auth::Config *createConfig() = 0;
+ virtual Auth::SchemeConfig *createConfig() = 0;
// Not implemented
Scheme(Scheme const &);
Scheme &operator=(Scheme const&);
static std::vector<Scheme::Pointer> &GetSchemes();
protected:
bool initialised;
private:
static std::vector<Scheme::Pointer> *_Schemes;
};
} // namespace Auth
#endif /* USE_AUTH */
#endif /* SQUID_AUTH_SCHEME_H */
=== renamed file 'src/auth/Config.cc' => 'src/auth/SchemeConfig.cc'
--- src/auth/Config.cc 2016-12-10 04:48:25 +0000
+++ src/auth/SchemeConfig.cc 2016-12-20 13:49:00 +0000
@@ -1,103 +1,103 @@
/*
* 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.
*/
/* DEBUG: section 29 Authenticator */
#include "squid.h"
#include "auth/Config.h"
+#include "auth/forward.h"
#include "auth/Gadgets.h"
#include "auth/UserRequest.h"
#include "cache_cf.h"
#include "ConfigParser.h"
#include "Debug.h"
#include "format/Format.h"
#include "globals.h"
#include "Store.h"
#include "wordlist.h"
-Auth::ConfigVector Auth::TheConfig;
-
/**
* Get an User credentials object filled out for the given Proxy- or WWW-Authenticate header.
* Any decoding which needs to be done will be done.
*
* It may be a cached AuthUser or a new Unauthenticated object.
* It may also be NULL reflecting that no user could be created.
*/
Auth::UserRequest::Pointer
-Auth::Config::CreateAuthUser(const char *proxy_auth, AccessLogEntry::Pointer &al)
+Auth::SchemeConfig::CreateAuthUser(const char *proxy_auth, AccessLogEntry::Pointer &al)
{
assert(proxy_auth != NULL);
debugs(29, 9, HERE << "header = '" << proxy_auth << "'");
- Auth::Config *config = Find(proxy_auth);
+ Auth::SchemeConfig *config = Find(proxy_auth);
if (config == NULL || !config->active()) {
debugs(29, (shutting_down?3:DBG_IMPORTANT), (shutting_down?"":"WARNING: ") <<
"Unsupported or unconfigured/inactive proxy-auth scheme, '" << proxy_auth << "'");
return NULL;
}
static MemBuf rmb;
rmb.reset();
if (config->keyExtras) {
// %credentials and %username, which normally included in
// request_format, are - at this time, but that is OK
// because user name is added to key explicitly, and we do
// not want to store authenticated credentials at all.
config->keyExtras->assemble(rmb, al, 0);
}
return config->decode(proxy_auth, rmb.hasContent() ? rmb.content() : NULL);
}
-Auth::Config *
-Auth::Config::Find(const char *proxy_auth)
+Auth::SchemeConfig *
+Auth::SchemeConfig::Find(const char *proxy_auth)
{
- for (Auth::ConfigVector::iterator i = Auth::TheConfig.begin(); i != Auth::TheConfig.end(); ++i)
- if (strncasecmp(proxy_auth, (*i)->type(), strlen((*i)->type())) == 0)
- return *i;
+ for (auto *scheme : Auth::TheConfig.schemes) {
+ if (strncasecmp(proxy_auth, scheme->type(), strlen(scheme->type())) == 0)
+ return scheme;
+ }
return NULL;
}
-Auth::Config *
-Auth::Config::GetParsed(const char *proxy_auth)
+Auth::SchemeConfig *
+Auth::SchemeConfig::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)
+Auth::SchemeConfig::registerWithCacheManager(void)
{}
void
-Auth::Config::parse(Auth::Config * scheme, int, char *param_str)
+Auth::SchemeConfig::parse(Auth::SchemeConfig * scheme, int, char *param_str)
{
if (strcmp(param_str, "program") == 0) {
if (authenticateProgram)
wordlistDestroy(&authenticateProgram);
parse_wordlist(&authenticateProgram);
requirePathnameExists("Authentication helper program", authenticateProgram->key);
} else if (strcmp(param_str, "realm") == 0) {
realm.clear();
char *token = ConfigParser::NextQuotedOrToEol();
while (token && *token && xisspace(*token))
++token;
if (!token || !*token) {
debugs(29, DBG_PARSE_NOTE(DBG_IMPORTANT), "ERROR: Missing auth_param " << scheme->type() << " realm");
self_destruct();
@@ -109,60 +109,72 @@
} else if (strcmp(param_str, "children") == 0) {
authenticateChildren.parseConfig();
} else if (strcmp(param_str, "key_extras") == 0) {
keyExtrasLine = ConfigParser::NextQuotedToken();
Format::Format *nlf = new ::Format::Format(scheme->type());
if (!nlf->parse(keyExtrasLine.termedBuf())) {
debugs(29, DBG_CRITICAL, "FATAL: Failed parsing key_extras formatting value");
self_destruct();
return;
}
if (keyExtras)
delete keyExtras;
keyExtras = nlf;
if (char *t = strtok(NULL, w_space)) {
debugs(29, DBG_CRITICAL, "FATAL: Unexpected argument '" << t << "' after request_format specification");
self_destruct();
}
+ } else if (strcmp(param_str, "keep_alive") == 0) {
+ parse_onoff(&keep_alive);
+ } else if (strcmp(param_str, "utf8") == 0) {
+ parse_onoff(&utf8);
} else {
debugs(29, DBG_CRITICAL, "Unrecognised " << scheme->type() << " auth scheme parameter '" << param_str << "'");
}
}
bool
-Auth::Config::dump(StoreEntry *entry, const char *name, Auth::Config *scheme) const
+Auth::SchemeConfig::dump(StoreEntry *entry, const char *name, Auth::SchemeConfig *scheme) const
{
if (!authenticateProgram)
return false; // not configured
+ const char *schemeType = scheme->type();
+
wordlist *list = authenticateProgram;
- storeAppendPrintf(entry, "%s %s", name, scheme->type());
+ storeAppendPrintf(entry, "%s %s", name, schemeType);
while (list != NULL) {
storeAppendPrintf(entry, " %s", list->key);
list = list->next;
}
storeAppendPrintf(entry, "\n");
- storeAppendPrintf(entry, "%s %s realm " SQUIDSBUFPH "\n", name, scheme->type(), SQUIDSBUFPRINT(realm));
+ storeAppendPrintf(entry, "%s %s realm " SQUIDSBUFPH "\n", name, schemeType, SQUIDSBUFPRINT(realm));
storeAppendPrintf(entry, "%s %s children %d startup=%d idle=%d concurrency=%d\n",
- name, scheme->type(),
+ name, schemeType,
authenticateChildren.n_max, authenticateChildren.n_startup,
authenticateChildren.n_idle, authenticateChildren.concurrency);
- if (keyExtrasLine.size() > 0)
- storeAppendPrintf(entry, "%s %s key_extras \"%s\"\n", name, scheme->type(), keyExtrasLine.termedBuf());
+ if (keyExtrasLine.size() > 0) // default is none
+ storeAppendPrintf(entry, "%s %s key_extras \"%s\"\n", name, schemeType, keyExtrasLine.termedBuf());
+
+ if (!keep_alive) // default is on
+ storeAppendPrintf(entry, "%s %s keep_alive off\n", name, schemeType);
+
+ if (utf8) // default is off
+ storeAppendPrintf(entry, "%s %s utf8 on\n", name, schemeType);
return true;
}
void
-Auth::Config::done()
+Auth::SchemeConfig::done()
{
delete keyExtras;
keyExtras = NULL;
keyExtrasLine.clean();
}
=== renamed file 'src/auth/Config.h' => 'src/auth/SchemeConfig.h'
--- src/auth/Config.h 2016-12-10 04:48:25 +0000
+++ src/auth/SchemeConfig.h 2016-12-20 12:15:10 +0000
@@ -1,77 +1,78 @@
/*
* 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_AUTH_CONFIG_H
-#define SQUID_AUTH_CONFIG_H
+#ifndef SQUID_SRC_AUTH_SCHEMECONFIG_H
+#define SQUID_SRC_AUTH_SCHEMECONFIG_H
#if USE_AUTH
#include "AccessLogEntry.h"
+#include "auth/forward.h"
#include "auth/UserRequest.h"
#include "helper/ChildConfig.h"
class StoreEntry;
class HttpReply;
class HttpRequest;
class wordlist;
/* for Http::HdrType parameters-by-value */
#include "HttpHeader.h"
namespace Format
{
class Format;
}
namespace Auth
{
/**
* \ingroup AuthAPI
* \par
* I am the configuration for an auth scheme.
* Currently each scheme has only one instance of me,
* but this may change.
* \par
* This class is treated like a ref counted class.
* If the children ever stop being singletons, implement the
* ref counting...
*/
-class Config
+class SchemeConfig
{
public:
static UserRequest::Pointer CreateAuthUser(const char *proxy_auth, AccessLogEntry::Pointer &al);
- static Config *Find(const char *proxy_auth);
+ static SchemeConfig *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) {}
+ static SchemeConfig *GetParsed(const char *proxy_auth);
+ SchemeConfig() : authenticateChildren(20) {}
- virtual ~Config() {}
+ virtual ~SchemeConfig() {}
/**
* Used by squid to determine whether the auth module has successfully initialised itself with the current configuration.
*
\retval true Authentication Module loaded and running.
\retval false No Authentication Module loaded.
*/
virtual bool active() const = 0;
/**
* new decode API: virtual factory pattern
\par
* Responsible for decoding the passed authentication header, creating or
* linking to a AuthUser object and for storing any needed details to complete
* authentication in Auth::UserRequest::authenticate().
*
\param proxy_auth Login Pattern to parse.
\retval * Details needed to authenticate.
*/
virtual UserRequest::Pointer decode(char const *proxy_auth, const char *requestRealm) = 0;
@@ -89,57 +90,55 @@
* The configured function is used to see if the auth module has been given valid
* parameters and is able to handle authentication requests.
*
\retval true Authentication Module configured ready for use.
\retval false Not configured or Configuration Error.
* No other module functions except Shutdown/Dump/Parse/FreeConfig will be called by Squid.
*/
virtual bool configured() const = 0;
/**
* Shutdown just the auth helpers.
* For use by log rotate etc. where auth needs to stay running, with the helpers restarted.
*/
virtual void rotateHelpers(void) = 0;
/**
* Responsible for writing to the StoreEntry the configuration parameters that a user
* would put in a config file to recreate the running configuration.
* Returns whether the scheme is configured.
*/
- virtual bool dump(StoreEntry *, const char *, Config *) const;
+ virtual bool dump(StoreEntry *, const char *, SchemeConfig *) const;
/** add headers as needed when challenging for auth */
virtual void fixHeader(UserRequest::Pointer, HttpReply *, Http::HdrType, HttpRequest *) = 0;
/** prepare to handle requests */
- virtual void init(Config *) = 0;
+ virtual void init(SchemeConfig *) = 0;
/** expose any/all statistics to a CacheManager */
virtual void registerWithCacheManager(void);
/** parse config options */
- virtual void parse(Config *, int, char *);
+ virtual void parse(SchemeConfig *, int, char *);
/** the http string id */
virtual const char * type() const = 0;
public:
Helper::ChildConfig authenticateChildren;
- wordlist *authenticateProgram; ///< Helper program to run, includes all parameters
+ wordlist *authenticateProgram = nullptr; ///< Helper program to run, includes all parameters
String keyExtrasLine; ///< The format of the request to the auth helper
- Format::Format *keyExtras; ///< The compiled request format
+ Format::Format *keyExtras = nullptr; ///< The compiled request format
+ int keep_alive = 1; ///< whether to close the connection on auth challenges. default: on
+ int utf8 = 0; ///< wheter to accept UTF-8 characterset instead of ASCII. default: off
protected:
/// RFC 7235 section 2.2 - Protection Space (Realm)
SBuf realm;
};
-typedef std::vector<Config *> ConfigVector;
-
-extern ConfigVector TheConfig;
-
} // namespace Auth
#endif /* USE_AUTH */
-#endif /* SQUID_AUTHCONFIG_H */
+#endif /* SQUID_SRC_AUTH_SCHEMECONFIG_H */
=== modified file 'src/auth/SchemesConfig.cc'
--- src/auth/SchemesConfig.cc 2016-12-10 04:48:25 +0000
+++ src/auth/SchemesConfig.cc 2016-12-19 13:26:03 +0000
@@ -1,47 +1,46 @@
/*
* 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)
+ for (const auto config: Auth::TheConfig.schemes)
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());
+ return Auth::SchemeConfig::GetParsed(s.c_str());
});
}
=== modified file 'src/auth/SchemesConfig.h'
--- src/auth/SchemesConfig.h 2016-12-10 04:48:25 +0000
+++ src/auth/SchemesConfig.h 2016-12-19 13:26:04 +0000
@@ -1,52 +1,49 @@
/*
* 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"
+#include "auth/SchemeConfig.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;
+ Auth::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 */
=== modified file 'src/auth/User.cc'
--- src/auth/User.cc 2016-07-05 05:45:44 +0000
+++ src/auth/User.cc 2016-12-19 15:32:50 +0000
@@ -1,45 +1,44 @@
/*
* 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.
*/
/* DEBUG: section 29 Authenticator */
#include "squid.h"
#include "acl/Acl.h"
#include "acl/Gadgets.h"
#include "auth/Config.h"
#include "auth/CredentialsCache.h"
#include "auth/Gadgets.h"
#include "auth/User.h"
#include "auth/UserRequest.h"
#include "event.h"
#include "globals.h"
-#include "SquidConfig.h"
#include "SquidTime.h"
#include "Store.h"
-Auth::User::User(Auth::Config *aConfig, const char *aRequestRealm) :
+Auth::User::User(Auth::SchemeConfig *aConfig, const char *aRequestRealm) :
auth_type(Auth::AUTH_UNKNOWN),
config(aConfig),
ipcount(0),
expiretime(0),
credentials_state(Auth::Unchecked),
username_(nullptr),
requestRealm_(aRequestRealm)
{
proxy_match_cache.head = proxy_match_cache.tail = NULL;
ip_list.head = ip_list.tail = NULL;
debugs(29, 5, HERE << "Initialised auth_user '" << this << "'.");
}
Auth::CredentialState
Auth::User::credentials() const
{
return credentials_state;
}
void
@@ -184,98 +183,98 @@
void
Auth::User::addIp(Ip::Address ipaddr)
{
AuthUserIP *ipdata = (AuthUserIP *) ip_list.head;
int found = 0;
/*
* we walk the entire list to prevent the first item in the list
* preventing old entries being flushed and locking a user out after
* a timeout+reconfigure
*/
while (ipdata) {
AuthUserIP *tempnode = (AuthUserIP *) ipdata->node.next;
/* walk the ip list */
if (ipdata->ipaddr == ipaddr) {
/* This ip has already been seen. */
found = 1;
/* update IP ttl */
- ipdata->ip_expiretime = squid_curtime + ::Config.authenticateIpTTL;
+ ipdata->ip_expiretime = squid_curtime + Auth::TheConfig.authenticateIpTTL;
} else if (ipdata->ip_expiretime <= squid_curtime) {
/* This IP has expired - remove from the seen list */
dlinkDelete(&ipdata->node, &ip_list);
delete ipdata;
/* catch incipient underflow */
assert(ipcount);
-- ipcount;
}
ipdata = tempnode;
}
if (found)
return;
/* This ip is not in the seen list */
- ipdata = new AuthUserIP(ipaddr, squid_curtime + ::Config.authenticateIpTTL);
+ ipdata = new AuthUserIP(ipaddr, squid_curtime + Auth::TheConfig.authenticateIpTTL);
dlinkAddTail(ipdata, &ipdata->node, &ip_list);
++ipcount;
debugs(29, 2, HERE << "user '" << username() << "' has been seen at a new IP address (" << ipaddr << ")");
}
SBuf
Auth::User::BuildUserKey(const char *username, const char *realm)
{
SBuf key;
if (realm)
key.Printf("%s:%s", username, realm);
else
key.append(username, strlen(username));
return key;
}
/**
* Dump the username cache statictics for viewing...
*/
void
Auth::User::CredentialsCacheStats(StoreEntry *output)
{
auto userlist = authenticateCachedUsersList();
storeAppendPrintf(output, "Cached Usernames: %d", static_cast<int32_t>(userlist.size()));
storeAppendPrintf(output, "\n%-15s %-9s %-9s %-9s %s\t%s\n",
"Type",
"State",
"Check TTL",
"Cache TTL",
"Username", "Key");
storeAppendPrintf(output, "--------------- --------- --------- --------- ------------------------------\n");
for ( auto auth_user : userlist ) {
storeAppendPrintf(output, "%-15s %-9s %-9d %-9d %s\t" SQUIDSBUFPH "\n",
Auth::Type_str[auth_user->auth_type],
CredentialState_str[auth_user->credentials()],
auth_user->ttl(),
- static_cast<int32_t>(auth_user->expiretime - squid_curtime + ::Config.authenticateTTL),
+ static_cast<int32_t>(auth_user->expiretime - squid_curtime + Auth::TheConfig.authenticateTTL),
auth_user->username(),
SQUIDSBUFPRINT(auth_user->userKey())
);
}
}
void
Auth::User::username(char const *aString)
{
if (aString) {
assert(!username_);
username_ = xstrdup(aString);
// NP: param #2 is working around a c_str() data-copy performance regression
userKey_ = BuildUserKey(username_, (!requestRealm_.isEmpty() ? requestRealm_.c_str() : NULL));
} else {
safe_free(username_);
userKey_.clear();
}
}
=== modified file 'src/auth/User.h'
--- src/auth/User.h 2016-02-23 08:51:22 +0000
+++ src/auth/User.h 2016-12-19 13:26:10 +0000
@@ -1,72 +1,70 @@
/*
* 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_AUTH_USER_H
#define SQUID_AUTH_USER_H
#if USE_AUTH
#include "auth/CredentialState.h"
+#include "auth/forward.h"
#include "auth/Type.h"
#include "base/CbcPointer.h"
#include "base/RefCount.h"
#include "dlink.h"
#include "ip/Address.h"
#include "Notes.h"
#include "sbuf/SBuf.h"
class StoreEntry;
namespace Auth
{
-class Config;
-class CredentialsCache;
-
/**
* This is the main user related structure. It stores user-related data,
* and is persistent across requests. It can even persist across
* multiple external authentications. One major benefit of preserving this
* structure is the cached ACL match results. This structure, is private to
* the authentication framework.
*/
class User : public RefCountable
{
public:
typedef RefCount<User> Pointer;
protected:
- User(Auth::Config *, const char *requestRealm);
+ User(Auth::SchemeConfig *, const char *requestRealm);
public:
virtual ~User();
/* extra fields for proxy_auth */
/** \deprecated this determines what scheme owns the user data. */
Auth::Type auth_type;
/** the config for this user */
- Auth::Config *config;
+ Auth::SchemeConfig *config;
dlink_list proxy_match_cache;
size_t ipcount;
long expiretime;
/// list of key=value pairs the helper produced
NotePairs notes;
public:
static SBuf BuildUserKey(const char *username, const char *realm);
void absorb(Auth::User::Pointer from);
char const *username() const { return username_; }
void username(char const *); ///< set stored username and userKey
// NP: key is set at the same time as username_. Until then both are empty/NULL.
const SBuf userKey() const {return userKey_;}
/**
* How long these credentials are still valid for.
* Negative numbers means already expired.
=== modified file 'src/auth/UserRequest.cc'
--- src/auth/UserRequest.cc 2016-12-10 04:48:25 +0000
+++ src/auth/UserRequest.cc 2016-12-19 14:28:42 +0000
@@ -1,50 +1,45 @@
/*
* 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.
*/
/* DEBUG: section 29 Authenticator */
/* The functions in this file handle authentication.
* They DO NOT perform access control or auditing.
* 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 "comm/Connection.h"
#include "fatal.h"
#include "format/Format.h"
#include "http/Stream.h"
#include "HttpReply.h"
#include "HttpRequest.h"
#include "MemBuf.h"
-#include "SquidConfig.h"
/* Generic Functions */
char const *
Auth::UserRequest::username() const
{
if (user() != NULL)
return user()->username();
else
return NULL;
}
/**** PUBLIC FUNCTIONS (ALL GENERIC!) ****/
/* send the initial data to an authenticator module */
void
Auth::UserRequest::start(HttpRequest *request, AccessLogEntry::Pointer &al, AUTHCB * handler, void *data)
{
assert(handler);
assert(data);
@@ -321,57 +316,57 @@
/* remove this request struct - the link is already authed and it can't be to reauth. */
/* This should _only_ ever occur on the first pass through
* authenticateAuthenticate
*/
assert(*auth_user_request == NULL);
conn->setAuth(NULL, "changed credentials token");
}
/* we have a proxy auth header and as far as we know this connection has
* not had bungled connection oriented authentication happen on it. */
debugs(29, 9, HERE << "header " << (proxy_auth ? proxy_auth : "-") << ".");
if (*auth_user_request == NULL) {
if (conn != NULL) {
debugs(29, 9, HERE << "This is a new checklist test on:" << conn->clientConnection);
}
if (proxy_auth && request->auth_user_request == NULL && conn != NULL && conn->getAuth() != NULL) {
- Auth::Config * scheme = Auth::Config::Find(proxy_auth);
+ Auth::SchemeConfig * scheme = Auth::SchemeConfig::Find(proxy_auth);
if (conn->getAuth()->user() == NULL || conn->getAuth()->user()->config != scheme) {
debugs(29, DBG_IMPORTANT, "WARNING: Unexpected change of authentication scheme from '" <<
(conn->getAuth()->user()!=NULL?conn->getAuth()->user()->config->type():"[no user]") <<
"' to '" << proxy_auth << "' (client " <<
src_addr << ")");
conn->setAuth(NULL, "changed auth scheme");
}
}
if (request->auth_user_request == NULL && (conn == NULL || conn->getAuth() == NULL)) {
/* beginning of a new request check */
debugs(29, 4, HERE << "No connection authentication type");
- *auth_user_request = Auth::Config::CreateAuthUser(proxy_auth, al);
+ *auth_user_request = Auth::SchemeConfig::CreateAuthUser(proxy_auth, al);
if (*auth_user_request == NULL)
return AUTH_ACL_CHALLENGE;
else if (!(*auth_user_request)->valid()) {
/* the decode might have left a username for logging, or a message to
* the user */
if ((*auth_user_request)->username()) {
request->auth_user_request = *auth_user_request;
}
*auth_user_request = NULL;
return AUTH_ACL_CHALLENGE;
}
} else if (request->auth_user_request != NULL) {
*auth_user_request = request->auth_user_request;
} else {
assert (conn != NULL);
if (conn->getAuth() != NULL) {
*auth_user_request = conn->getAuth();
@@ -450,92 +445,90 @@
request->auth_user_request = t;
}
return t->lastReply;
}
// ok, call the actual authenticator routine.
AuthAclState result = authenticate(aUR, headertype, request, conn, src_addr, al);
// auth process may have changed the UserRequest we are dealing with
t = authTryGetUser(*aUR, conn, request);
if (t != NULL && result != AUTH_ACL_CANNOT_AUTHENTICATE && result != AUTH_ACL_HELPER)
t->lastReply = result;
return result;
}
static Auth::ConfigVector &
schemesConfig(HttpRequest *request, HttpReply *rep)
{
- if (::Config.accessList.authSchemes) {
+ if (!Auth::TheConfig.schemeLists.empty() && Auth::TheConfig.schemeAccess) {
ACLFilledChecklist ch(NULL, request, NULL);
ch.reply = rep;
HTTPMSGLOCK(ch.reply);
- const allow_t answer = ch.fastCheck(::Config.accessList.authSchemes);
+ const allow_t answer = ch.fastCheck(Auth::TheConfig.schemeAccess);
if (answer == ACCESS_ALLOWED)
- return ::Config.authSchemesConfigs.at(answer.kind).authConfigs;
+ return Auth::TheConfig.schemeLists.at(answer.kind).authConfigs;
}
- return Auth::TheConfig;
+ return Auth::TheConfig.schemes;
}
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!) */
{
Http::HdrType type;
switch (rep->sline.status()) {
case Http::scProxyAuthenticationRequired:
/* Proxy authorisation needed */
type = Http::HdrType::PROXY_AUTHENTICATE;
break;
case Http::scUnauthorized:
/* WWW Authorisation needed */
type = Http::HdrType::WWW_AUTHENTICATE;
break;
default:
/* Keep GCC happy */
/* some other HTTP status */
type = Http::HdrType::BAD_HDR;
break;
}
debugs(29, 9, "headertype:" << type << " authuser:" << auth_user_request);
if (((rep->sline.status() == Http::scProxyAuthenticationRequired)
|| (rep->sline.status() == Http::scUnauthorized)) && internal)
/* this is a authenticate-needed response */
{
if (auth_user_request != NULL && auth_user_request->direction() == Auth::CRED_CHALLENGE)
/* add the scheme specific challenge header to the response */
auth_user_request->user()->config->fixHeader(auth_user_request, rep, type, request);
else {
- /* call each configured & running authscheme */
+ /* call each configured & running auth scheme */
Auth::ConfigVector &configs = schemesConfig(request, rep);
- for (Auth::ConfigVector::iterator i = configs.begin(); i != configs.end(); ++i) {
- Auth::Config *scheme = *i;
-
+ for (auto *scheme : configs) {
if (scheme->active()) {
if (auth_user_request != NULL && auth_user_request->scheme()->type() == scheme->type())
scheme->fixHeader(auth_user_request, rep, type, request);
else
scheme->fixHeader(NULL, rep, type, request);
} else
debugs(29, 4, HERE << "Configured scheme " << scheme->type() << " not Active");
}
}
}
/*
* allow protocol specific headers to be _added_ to the existing
* response - currently Digest or Negotiate auth
*/
if (auth_user_request != NULL) {
auth_user_request->addAuthenticationInfoHeader(rep, accelerated);
if (auth_user_request->lastReply != AUTH_AUTHENTICATED)
auth_user_request->lastReply = AUTH_ACL_CANNOT_AUTHENTICATE;
=== modified file 'src/auth/basic/Config.cc'
--- src/auth/basic/Config.cc 2016-01-01 00:12:18 +0000
+++ src/auth/basic/Config.cc 2016-12-20 12:18:51 +0000
@@ -79,87 +79,83 @@
debugs(29, 9, "Sending type:" << hdrType << " header: 'Basic realm=\"" << realm << "\"'");
httpHeaderPutStrf(&rep->header, hdrType, "Basic realm=\"" SQUIDSBUFPH "\"", SQUIDSBUFPRINT(realm));
}
}
void
Auth::Basic::Config::rotateHelpers()
{
/* schedule closure of existing helpers */
if (basicauthenticators) {
helperShutdown(basicauthenticators);
}
/* NP: dynamic helper restart will ensure they start up again as needed. */
}
/** shutdown the auth helpers and free any allocated configuration details */
void
Auth::Basic::Config::done()
{
- Auth::Config::done();
+ Auth::SchemeConfig::done();
authbasic_initialised = 0;
if (basicauthenticators) {
helperShutdown(basicauthenticators);
}
delete basicauthenticators;
basicauthenticators = NULL;
if (authenticateProgram)
wordlistDestroy(&authenticateProgram);
}
bool
-Auth::Basic::Config::dump(StoreEntry * entry, const char *name, Auth::Config * scheme) const
+Auth::Basic::Config::dump(StoreEntry * entry, const char *name, Auth::SchemeConfig * scheme) const
{
- if (!Auth::Config::dump(entry, name, scheme))
+ if (!Auth::SchemeConfig::dump(entry, name, scheme))
return false; // not configured
storeAppendPrintf(entry, "%s basic credentialsttl %d seconds\n", name, (int) credentialsTTL);
storeAppendPrintf(entry, "%s basic casesensitive %s\n", name, casesensitive ? "on" : "off");
- storeAppendPrintf(entry, "%s basic utf8 %s\n", name, utf8 ? "on" : "off");
return true;
}
Auth::Basic::Config::Config() :
credentialsTTL( 2*60*60 ),
- casesensitive(0),
- utf8(0)
+ casesensitive(0)
{
static const SBuf defaultRealm("Squid proxy-caching web server");
realm = defaultRealm;
}
void
-Auth::Basic::Config::parse(Auth::Config * scheme, int n_configured, char *param_str)
+Auth::Basic::Config::parse(Auth::SchemeConfig * scheme, int n_configured, char *param_str)
{
if (strcmp(param_str, "credentialsttl") == 0) {
parse_time_t(&credentialsTTL);
} else if (strcmp(param_str, "casesensitive") == 0) {
parse_onoff(&casesensitive);
- } else if (strcmp(param_str, "utf8") == 0) {
- parse_onoff(&utf8);
} else
- Auth::Config::parse(scheme, n_configured, param_str);
+ Auth::SchemeConfig::parse(scheme, n_configured, param_str);
}
static void
authenticateBasicStats(StoreEntry * sentry)
{
if (basicauthenticators)
basicauthenticators->packStatsInto(sentry, "Basic Authenticator Statistics");
}
char *
Auth::Basic::Config::decodeCleartext(const char *httpAuthHeader)
{
const char *proxy_auth = httpAuthHeader;
/* trim BASIC from string */
while (xisgraph(*proxy_auth))
++proxy_auth;
/* Trim leading whitespace before decoding */
while (xisspace(*proxy_auth))
@@ -262,41 +258,41 @@
lb->addToNameCache();
auth_user = lb;
assert(auth_user != NULL);
} else {
/* replace the current cached password with the new one */
Auth::Basic::User *basic_auth = dynamic_cast<Auth::Basic::User *>(auth_user.getRaw());
assert(basic_auth);
basic_auth->updateCached(local_basic);
auth_user = basic_auth;
}
/* link the request to the in-cache user */
auth_user_request->user(auth_user);
return auth_user_request;
}
/** Initialize helpers and the like for this auth scheme. Called AFTER parsing the
* config file */
void
-Auth::Basic::Config::init(Auth::Config *)
+Auth::Basic::Config::init(Auth::SchemeConfig *)
{
if (authenticateProgram) {
authbasic_initialised = 1;
if (basicauthenticators == NULL)
basicauthenticators = new helper("basicauthenticator");
basicauthenticators->cmdline = authenticateProgram;
basicauthenticators->childs.updateLimits(authenticateChildren);
basicauthenticators->ipc_type = IPC_STREAM;
helperOpenServers(basicauthenticators);
}
}
void
Auth::Basic::Config::registerWithCacheManager(void)
{
=== modified file 'src/auth/basic/Config.h'
--- src/auth/basic/Config.h 2016-01-01 00:12:18 +0000
+++ src/auth/basic/Config.h 2016-12-20 12:14:04 +0000
@@ -1,58 +1,57 @@
/*
* 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 __AUTH_BASIC_H__
#define __AUTH_BASIC_H__
#if HAVE_AUTH_MODULE_BASIC
-#include "auth/Config.h"
#include "auth/Gadgets.h"
+#include "auth/SchemeConfig.h"
#include "auth/UserRequest.h"
#include "helper/forward.h"
namespace Auth
{
namespace Basic
{
/** Basic authentication configuration data */
-class Config : public Auth::Config
+class Config : public Auth::SchemeConfig
{
public:
Config();
virtual bool active() const;
virtual bool configured() const;
virtual Auth::UserRequest::Pointer decode(char const *proxy_auth, const char *requestRealm);
virtual void done();
virtual void rotateHelpers();
- virtual bool dump(StoreEntry *, const char *, Auth::Config *) const;
+ virtual bool dump(StoreEntry *, const char *, Auth::SchemeConfig *) const;
virtual void fixHeader(Auth::UserRequest::Pointer, HttpReply *, Http::HdrType, HttpRequest *);
- virtual void init(Auth::Config *);
- virtual void parse(Auth::Config *, int, char *);
+ virtual void init(Auth::SchemeConfig *);
+ virtual void parse(Auth::SchemeConfig *, int, char *);
void decode(char const *httpAuthHeader, Auth::UserRequest::Pointer);
virtual void registerWithCacheManager(void);
virtual const char * type() const;
public:
time_t credentialsTTL;
int casesensitive;
- int utf8;
private:
char * decodeCleartext(const char *httpAuthHeader);
};
} // namespace Basic
} // namespace Auth
extern helper *basicauthenticators;
#endif /* HAVE_AUTH_MODULE_BASIC */
#endif /* __AUTH_BASIC_H__ */
=== modified file 'src/auth/basic/Scheme.cc'
--- src/auth/basic/Scheme.cc 2016-01-01 00:12:18 +0000
+++ src/auth/basic/Scheme.cc 2016-12-19 13:27:07 +0000
@@ -23,27 +23,27 @@
}
return _instance;
}
char const *
Auth::Basic::Scheme::type() const
{
return "basic";
}
void
Auth::Basic::Scheme::shutdownCleanup()
{
if (_instance == NULL)
return;
_instance = NULL;
debugs(29, DBG_CRITICAL, "Shutdown: Basic authentication.");
}
-Auth::Config *
+Auth::SchemeConfig *
Auth::Basic::Scheme::createConfig()
{
Auth::Basic::Config *newCfg = new Auth::Basic::Config;
- return dynamic_cast<Auth::Config*>(newCfg);
+ return dynamic_cast<Auth::SchemeConfig*>(newCfg);
}
=== modified file 'src/auth/basic/Scheme.h'
--- src/auth/basic/Scheme.h 2016-01-01 00:12:18 +0000
+++ src/auth/basic/Scheme.h 2016-12-19 13:27:08 +0000
@@ -2,47 +2,46 @@
* 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_AUTH_BASIC_SCHEME_H
#define SQUID_AUTH_BASIC_SCHEME_H
#if HAVE_AUTH_MODULE_BASIC
#include "auth/Scheme.h"
namespace Auth
{
namespace Basic
{
/// \ingroup AuthAPI
-/// \ingroup AuthSchemeAPI
class Scheme : public Auth::Scheme
{
public:
static Auth::Scheme::Pointer GetInstance();
Scheme() {};
virtual ~Scheme() {}
/* per scheme */
virtual char const *type() const;
virtual void shutdownCleanup();
- virtual Auth::Config *createConfig();
+ virtual Auth::SchemeConfig *createConfig();
/* Not implemented */
Scheme(Scheme const &);
Scheme &operator=(Scheme const &);
private:
static Auth::Scheme::Pointer _instance;
};
} // namespace Basic
} // namespace Auth
#endif /* HAVE_AUTH_MODULE_BASIC */
#endif /* SQUID_AUTH_BASIC_SCHEME_H */
=== modified file 'src/auth/basic/User.cc'
--- src/auth/basic/User.cc 2016-01-01 00:12:18 +0000
+++ src/auth/basic/User.cc 2016-12-19 14:43:15 +0000
@@ -1,56 +1,55 @@
/*
* 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/basic/Config.h"
#include "auth/basic/User.h"
+#include "auth/Config.h"
#include "auth/CredentialsCache.h"
#include "Debug.h"
-#include "SquidConfig.h"
-#include "SquidTime.h"
-Auth::Basic::User::User(Auth::Config *aConfig, const char *aRequestRealm) :
+Auth::Basic::User::User(Auth::SchemeConfig *aConfig, const char *aRequestRealm) :
Auth::User(aConfig, aRequestRealm),
passwd(NULL),
queue(NULL),
currentRequest(NULL)
{}
Auth::Basic::User::~User()
{
safe_free(passwd);
}
int32_t
Auth::Basic::User::ttl() const
{
if (credentials() != Auth::Ok && credentials() != Auth::Pending)
return -1; // TTL is obsolete NOW.
int32_t basic_ttl = expiretime - squid_curtime + static_cast<Auth::Basic::Config*>(config)->credentialsTTL;
- int32_t global_ttl = static_cast<int32_t>(expiretime - squid_curtime + ::Config.authenticateTTL);
+ int32_t global_ttl = static_cast<int32_t>(expiretime - squid_curtime + Auth::TheConfig.authenticateTTL);
return min(basic_ttl, global_ttl);
}
bool
Auth::Basic::User::authenticated() const
{
if ((credentials() == Auth::Ok) && (expiretime + static_cast<Auth::Basic::Config*>(config)->credentialsTTL > squid_curtime))
return true;
debugs(29, 4, "User not authenticated or credentials need rechecking.");
return false;
}
bool
Auth::Basic::User::valid() const
{
if (username() == NULL)
return false;
=== modified file 'src/auth/basic/User.h'
--- src/auth/basic/User.h 2016-01-01 00:12:18 +0000
+++ src/auth/basic/User.h 2016-12-19 13:27:10 +0000
@@ -1,52 +1,52 @@
/*
* 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_AUTH_BASIC_USER_H
#define _SQUID_AUTH_BASIC_USER_H
#if HAVE_AUTH_MODULE_BASIC
#include "auth/User.h"
#include "auth/UserRequest.h"
namespace Auth
{
-class Config;
+class SchemeConfig;
class QueueNode;
namespace Basic
{
/** User credentials for the Basic authentication protocol */
class User : public Auth::User
{
MEMPROXY_CLASS(Auth::Basic::User);
public:
- User(Auth::Config *, const char *requestRealm);
+ User(Auth::SchemeConfig *, const char *requestRealm);
virtual ~User();
bool authenticated() const;
bool valid() const;
/** Update the cached password for a username. */
void updateCached(User *from);
virtual int32_t ttl() const override;
/* Auth::User API */
static CbcPointer<Auth::CredentialsCache> Cache();
virtual void addToNameCache() override;
char *passwd;
QueueNode *queue;
private:
Auth::UserRequest::Pointer currentRequest;
};
=== modified file 'src/auth/basic/UserRequest.cc'
--- src/auth/basic/UserRequest.cc 2016-01-01 00:12:18 +0000
+++ src/auth/basic/UserRequest.cc 2016-12-19 13:27:11 +0000
@@ -42,89 +42,89 @@
Auth::Basic::UserRequest::credentialsStr()
{
Auth::Basic::User const *basic_auth = dynamic_cast<Auth::Basic::User const *>(user().getRaw());
if (basic_auth)
return basic_auth->passwd;
return NULL;
}
/* log a basic user in
*/
void
Auth::Basic::UserRequest::authenticate(HttpRequest *, ConnStateData *, Http::HdrType)
{
assert(user() != NULL);
/* if the password is not ok, do an identity */
if (!user() || user()->credentials() != Auth::Ok)
return;
/* are we about to recheck the credentials externally? */
- if ((user()->expiretime + static_cast<Auth::Basic::Config*>(Auth::Config::Find("basic"))->credentialsTTL) <= squid_curtime) {
+ if ((user()->expiretime + static_cast<Auth::Basic::Config*>(Auth::SchemeConfig::Find("basic"))->credentialsTTL) <= squid_curtime) {
debugs(29, 4, HERE << "credentials expired - rechecking");
return;
}
/* we have been through the external helper, and the credentials haven't expired */
debugs(29, 9, HERE << "user '" << user()->username() << "' authenticated");
/* Decode now takes care of finding the AuthUser struct in the cache */
/* after external auth occurs anyway */
user()->expiretime = current_time.tv_sec;
}
Auth::Direction
Auth::Basic::UserRequest::module_direction()
{
/* null auth_user is checked for by Auth::UserRequest::direction() */
if (user()->auth_type != Auth::AUTH_BASIC)
return Auth::CRED_ERROR;
switch (user()->credentials()) {
case Auth::Unchecked:
case Auth::Pending:
return Auth::CRED_LOOKUP;
case Auth::Ok:
- if (user()->expiretime + static_cast<Auth::Basic::Config*>(Auth::Config::Find("basic"))->credentialsTTL <= squid_curtime)
+ if (user()->expiretime + static_cast<Auth::Basic::Config*>(Auth::SchemeConfig::Find("basic"))->credentialsTTL <= squid_curtime)
return Auth::CRED_LOOKUP;
return Auth::CRED_VALID;
case Auth::Failed:
return Auth::CRED_VALID;
default:
return Auth::CRED_ERROR;
}
}
/* send the initial data to a basic authenticator module */
void
Auth::Basic::UserRequest::startHelperLookup(HttpRequest *request, AccessLogEntry::Pointer &al, AUTHCB * handler, void *data)
{
assert(user()->auth_type == Auth::AUTH_BASIC);
Auth::Basic::User *basic_auth = dynamic_cast<Auth::Basic::User *>(user().getRaw());
assert(basic_auth != NULL);
debugs(29, 9, HERE << "'" << basic_auth->username() << ":" << basic_auth->passwd << "'");
- if (static_cast<Auth::Basic::Config*>(Auth::Config::Find("basic"))->authenticateProgram == NULL) {
+ if (static_cast<Auth::Basic::Config*>(Auth::SchemeConfig::Find("basic"))->authenticateProgram == NULL) {
debugs(29, DBG_CRITICAL, "ERROR: No Basic authentication program configured.");
handler(data);
return;
}
/* check to see if the auth_user already has a request outstanding */
if (user()->credentials() == Auth::Pending) {
/* there is a request with the same credentials already being verified */
Auth::QueueNode *node = new Auth::QueueNode(this, handler, data);
/* queue this validation request to be infored of the pending lookup results */
node->next = basic_auth->queue;
basic_auth->queue = node;
return;
}
// otherwise submit this request to the auth helper(s) for validation
/* mark this user as having verification in progress */
user()->credentials(Auth::Pending);
=== modified file 'src/auth/digest/Config.cc'
--- src/auth/digest/Config.cc 2016-11-27 13:57:50 +0000
+++ src/auth/digest/Config.cc 2016-12-20 12:18:55 +0000
@@ -198,41 +198,41 @@
#endif
assert(!nonce->flags.incache);
safe_free(nonce->key);
digest_nonce_pool->freeOne(nonce);
}
}
static void
authenticateDigestNonceSetup(void)
{
if (!digest_nonce_pool)
digest_nonce_pool = memPoolCreate("Digest Scheme nonce's", sizeof(digest_nonce_h));
if (!digest_nonce_cache) {
digest_nonce_cache = hash_create((HASHCMP *) strcmp, 7921, hash_string);
assert(digest_nonce_cache);
- eventAdd("Digest nonce cache maintenance", authenticateDigestNonceCacheCleanup, NULL, static_cast<Auth::Digest::Config*>(Auth::Config::Find("digest"))->nonceGCInterval, 1);
+ eventAdd("Digest nonce cache maintenance", authenticateDigestNonceCacheCleanup, NULL, static_cast<Auth::Digest::Config*>(Auth::SchemeConfig::Find("digest"))->nonceGCInterval, 1);
}
}
void
authenticateDigestNonceShutdown(void)
{
/*
* We empty the cache of any nonces left in there.
*/
digest_nonce_h *nonce;
if (digest_nonce_cache) {
debugs(29, 2, "Shutting down nonce cache");
hash_first(digest_nonce_cache);
while ((nonce = ((digest_nonce_h *) hash_next(digest_nonce_cache)))) {
assert(nonce->flags.incache);
authDigestNoncePurge(nonce);
}
}
@@ -261,42 +261,42 @@
debugs(29, 3, "Current time: " << current_time.tv_sec);
hash_first(digest_nonce_cache);
while ((nonce = ((digest_nonce_h *) hash_next(digest_nonce_cache)))) {
debugs(29, 3, "nonce entry : " << nonce << " '" << (char *) nonce->key << "'");
debugs(29, 4, "Creation time: " << nonce->noncedata.creationtime);
if (authDigestNonceIsStale(nonce)) {
debugs(29, 4, "Removing nonce " << (char *) nonce->key << " from cache due to timeout.");
assert(nonce->flags.incache);
/* invalidate nonce so future requests fail */
nonce->flags.valid = false;
/* if it is tied to a auth_user, remove the tie */
authDigestNonceUserUnlink(nonce);
authDigestNoncePurge(nonce);
}
}
debugs(29, 3, "Finished cleaning the nonce cache.");
- if (static_cast<Auth::Digest::Config*>(Auth::Config::Find("digest"))->active())
- eventAdd("Digest nonce cache maintenance", authenticateDigestNonceCacheCleanup, NULL, static_cast<Auth::Digest::Config*>(Auth::Config::Find("digest"))->nonceGCInterval, 1);
+ if (static_cast<Auth::Digest::Config*>(Auth::SchemeConfig::Find("digest"))->active())
+ eventAdd("Digest nonce cache maintenance", authenticateDigestNonceCacheCleanup, NULL, static_cast<Auth::Digest::Config*>(Auth::SchemeConfig::Find("digest"))->nonceGCInterval, 1);
}
static void
authDigestNonceLink(digest_nonce_h * nonce)
{
assert(nonce != NULL);
++nonce->references;
debugs(29, 9, "nonce '" << nonce << "' now at '" << nonce->references << "'.");
}
#if NOT_USED
static int
authDigestNonceLinks(digest_nonce_h * nonce)
{
if (!nonce)
return -1;
return nonce->references;
}
@@ -349,162 +349,161 @@
}
int
authDigestNonceIsValid(digest_nonce_h * nonce, char nc[9])
{
unsigned long intnc;
/* do we have a nonce ? */
if (!nonce)
return 0;
intnc = strtol(nc, NULL, 16);
/* has it already been invalidated ? */
if (!nonce->flags.valid) {
debugs(29, 4, "Nonce already invalidated");
return 0;
}
/* is the nonce-count ok ? */
- if (!static_cast<Auth::Digest::Config*>(Auth::Config::Find("digest"))->CheckNonceCount) {
+ if (!static_cast<Auth::Digest::Config*>(Auth::SchemeConfig::Find("digest"))->CheckNonceCount) {
/* Ignore client supplied NC */
intnc = nonce->nc + 1;
}
- if ((static_cast<Auth::Digest::Config*>(Auth::Config::Find("digest"))->NonceStrictness && intnc != nonce->nc + 1) ||
+ if ((static_cast<Auth::Digest::Config*>(Auth::SchemeConfig::Find("digest"))->NonceStrictness && intnc != nonce->nc + 1) ||
intnc < nonce->nc + 1) {
debugs(29, 4, "Nonce count doesn't match");
nonce->flags.valid = false;
return 0;
}
/* increment the nonce count - we've already checked that intnc is a
* valid representation for us, so we don't need the test here.
*/
nonce->nc = intnc;
return !authDigestNonceIsStale(nonce);
}
int
authDigestNonceIsStale(digest_nonce_h * nonce)
{
/* do we have a nonce ? */
if (!nonce)
return -1;
/* Is it already invalidated? */
if (!nonce->flags.valid)
return -1;
/* has it's max duration expired? */
- if (nonce->noncedata.creationtime + static_cast<Auth::Digest::Config*>(Auth::Config::Find("digest"))->noncemaxduration < current_time.tv_sec) {
+ if (nonce->noncedata.creationtime + static_cast<Auth::Digest::Config*>(Auth::SchemeConfig::Find("digest"))->noncemaxduration < current_time.tv_sec) {
debugs(29, 4, "Nonce is too old. " <<
nonce->noncedata.creationtime << " " <<
- static_cast<Auth::Digest::Config*>(Auth::Config::Find("digest"))->noncemaxduration << " " <<
+ static_cast<Auth::Digest::Config*>(Auth::SchemeConfig::Find("digest"))->noncemaxduration << " " <<
current_time.tv_sec);
nonce->flags.valid = false;
return -1;
}
if (nonce->nc > 99999998) {
debugs(29, 4, "Nonce count overflow");
nonce->flags.valid = false;
return -1;
}
- if (nonce->nc > static_cast<Auth::Digest::Config*>(Auth::Config::Find("digest"))->noncemaxuses) {
+ if (nonce->nc > static_cast<Auth::Digest::Config*>(Auth::SchemeConfig::Find("digest"))->noncemaxuses) {
debugs(29, 4, "Nonce count over user limit");
nonce->flags.valid = false;
return -1;
}
/* seems ok */
return 0;
}
/**
* \retval 0 the digest is not stale yet
* \retval -1 the digest will be stale on the next request
*/
int
authDigestNonceLastRequest(digest_nonce_h * nonce)
{
if (!nonce)
return -1;
if (nonce->nc == 99999997) {
debugs(29, 4, "Nonce count about to overflow");
return -1;
}
- if (nonce->nc >= static_cast<Auth::Digest::Config*>(Auth::Config::Find("digest"))->noncemaxuses - 1) {
+ if (nonce->nc >= static_cast<Auth::Digest::Config*>(Auth::SchemeConfig::Find("digest"))->noncemaxuses - 1) {
debugs(29, 4, "Nonce count about to hit user limit");
return -1;
}
/* and other tests are possible. */
return 0;
}
void
authDigestNoncePurge(digest_nonce_h * nonce)
{
if (!nonce)
return;
if (!nonce->flags.incache)
return;
hash_remove_link(digest_nonce_cache, nonce);
nonce->flags.incache = false;
/* the cache's link */
authDigestNonceUnlink(nonce);
}
void
Auth::Digest::Config::rotateHelpers()
{
/* schedule closure of existing helpers */
if (digestauthenticators) {
helperShutdown(digestauthenticators);
}
/* NP: dynamic helper restart will ensure they start up again as needed. */
}
bool
-Auth::Digest::Config::dump(StoreEntry * entry, const char *name, Auth::Config * scheme) const
+Auth::Digest::Config::dump(StoreEntry * entry, const char *name, Auth::SchemeConfig * scheme) const
{
- if (!Auth::Config::dump(entry, name, scheme))
+ if (!Auth::SchemeConfig::dump(entry, name, scheme))
return false;
storeAppendPrintf(entry, "%s %s nonce_max_count %d\n%s %s nonce_max_duration %d seconds\n%s %s nonce_garbage_interval %d seconds\n",
name, "digest", noncemaxuses,
name, "digest", (int) noncemaxduration,
name, "digest", (int) nonceGCInterval);
- storeAppendPrintf(entry, "%s digest utf8 %s\n", name, utf8 ? "on" : "off");
return true;
}
bool
Auth::Digest::Config::active() const
{
return authdigest_initialised == 1;
}
bool
Auth::Digest::Config::configured() const
{
if ((authenticateProgram != NULL) &&
(authenticateChildren.n_max != 0) &&
!realm.isEmpty() && (noncemaxduration > -1))
return true;
return false;
}
@@ -529,124 +528,114 @@
}
}
}
if (!nonce) {
nonce = authenticateDigestNonceNew();
}
debugs(29, 9, "Sending type:" << hdrType <<
" header: 'Digest realm=\"" << realm << "\", nonce=\"" <<
authenticateDigestNonceNonceb64(nonce) << "\", qop=\"" << QOP_AUTH <<
"\", stale=" << (stale ? "true" : "false"));
/* in the future, for WWW auth we may want to support the domain entry */
httpHeaderPutStrf(&rep->header, hdrType, "Digest realm=\"" SQUIDSBUFPH "\", nonce=\"%s\", qop=\"%s\", stale=%s",
SQUIDSBUFPRINT(realm), authenticateDigestNonceNonceb64(nonce), QOP_AUTH, stale ? "true" : "false");
}
/* Initialize helpers and the like for this auth scheme. Called AFTER parsing the
* config file */
void
-Auth::Digest::Config::init(Auth::Config *)
+Auth::Digest::Config::init(Auth::SchemeConfig *)
{
if (authenticateProgram) {
authenticateDigestNonceSetup();
authdigest_initialised = 1;
if (digestauthenticators == NULL)
digestauthenticators = new helper("digestauthenticator");
digestauthenticators->cmdline = authenticateProgram;
digestauthenticators->childs.updateLimits(authenticateChildren);
digestauthenticators->ipc_type = IPC_STREAM;
helperOpenServers(digestauthenticators);
}
}
void
Auth::Digest::Config::registerWithCacheManager(void)
{
Mgr::RegisterAction("digestauthenticator",
"Digest User Authenticator Stats",
authenticateDigestStats, 0, 1);
}
/* free any allocated configuration details */
void
Auth::Digest::Config::done()
{
- Auth::Config::done();
+ Auth::SchemeConfig::done();
authdigest_initialised = 0;
if (digestauthenticators)
helperShutdown(digestauthenticators);
if (!shutting_down)
return;
delete digestauthenticators;
digestauthenticators = NULL;
if (authenticateProgram)
wordlistDestroy(&authenticateProgram);
}
Auth::Digest::Config::Config() :
nonceGCInterval(5*60),
noncemaxduration(30*60),
noncemaxuses(50),
NonceStrictness(0),
CheckNonceCount(1),
- PostWorkaround(0),
- utf8(0)
+ PostWorkaround(0)
{}
void
-Auth::Digest::Config::parse(Auth::Config * scheme, int n_configured, char *param_str)
+Auth::Digest::Config::parse(Auth::SchemeConfig * scheme, int n_configured, char *param_str)
{
- if (strcmp(param_str, "program") == 0) {
- if (authenticateProgram)
- wordlistDestroy(&authenticateProgram);
-
- parse_wordlist(&authenticateProgram);
-
- requirePathnameExists("auth_param digest program", authenticateProgram->key);
- } else if (strcmp(param_str, "nonce_garbage_interval") == 0) {
+ if (strcmp(param_str, "nonce_garbage_interval") == 0) {
parse_time_t(&nonceGCInterval);
} else if (strcmp(param_str, "nonce_max_duration") == 0) {
parse_time_t(&noncemaxduration);
} else if (strcmp(param_str, "nonce_max_count") == 0) {
parse_int((int *) &noncemaxuses);
} else if (strcmp(param_str, "nonce_strictness") == 0) {
parse_onoff(&NonceStrictness);
} else if (strcmp(param_str, "check_nonce_count") == 0) {
parse_onoff(&CheckNonceCount);
} else if (strcmp(param_str, "post_workaround") == 0) {
parse_onoff(&PostWorkaround);
- } else if (strcmp(param_str, "utf8") == 0) {
- parse_onoff(&utf8);
} else
- Auth::Config::parse(scheme, n_configured, param_str);
+ Auth::SchemeConfig::parse(scheme, n_configured, param_str);
}
const char *
Auth::Digest::Config::type() const
{
return Auth::Digest::Scheme::GetInstance()->type();
}
static void
authenticateDigestStats(StoreEntry * sentry)
{
if (digestauthenticators)
digestauthenticators->packStatsInto(sentry, "Digest Authenticator Statistics");
}
/* NonceUserUnlink: remove the reference to auth_user and unlink the node from the list */
static void
authDigestNonceUserUnlink(digest_nonce_h * nonce)
{
@@ -709,41 +698,41 @@
authDigestNonceLink(nonce);
/* ping this nonce to this auth user */
assert((nonce->user == NULL) || (nonce->user == user));
/* we don't lock this reference because removing the user removes the
* hash too. Of course if that changes we're stuffed so read the code huh?
*/
nonce->user = user;
}
/* setup the necessary info to log the username */
static Auth::UserRequest::Pointer
authDigestLogUsername(char *username, Auth::UserRequest::Pointer auth_user_request, const char *requestRealm)
{
assert(auth_user_request != NULL);
/* log the username */
debugs(29, 9, "Creating new user for logging '" << (username?username:"[no username]") << "'");
- Auth::User::Pointer digest_user = new Auth::Digest::User(static_cast<Auth::Digest::Config*>(Auth::Config::Find("digest")), requestRealm);
+ Auth::User::Pointer digest_user = new Auth::Digest::User(static_cast<Auth::Digest::Config*>(Auth::SchemeConfig::Find("digest")), requestRealm);
/* save the credentials */
digest_user->username(username);
/* set the auth_user type */
digest_user->auth_type = Auth::AUTH_BROKEN;
/* link the request to the user */
auth_user_request->user(digest_user);
return auth_user_request;
}
/*
* Decode a Digest [Proxy-]Auth string, placing the results in the passed
* Auth_user structure.
*/
Auth::UserRequest::Pointer
Auth::Digest::Config::decode(char const *proxy_auth, const char *aRequestRealm)
{
const char *item;
const char *p;
const char *pos = NULL;
char *username = NULL;
=== modified file 'src/auth/digest/Config.h'
--- src/auth/digest/Config.h 2016-01-01 00:12:18 +0000
+++ src/auth/digest/Config.h 2016-12-20 12:14:14 +0000
@@ -1,35 +1,35 @@
/*
* 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 __AUTH_DIGEST_H__
#define __AUTH_DIGEST_H__
#if HAVE_AUTH_MODULE_DIGEST
-#include "auth/Config.h"
#include "auth/Gadgets.h"
+#include "auth/SchemeConfig.h"
#include "auth/UserRequest.h"
#include "helper/forward.h"
#include "rfc2617.h"
namespace Auth
{
namespace Digest
{
class User;
}
}
/* Generic */
typedef struct _digest_nonce_data digest_nonce_data;
typedef struct _digest_nonce_h digest_nonce_h;
/* data to be encoded into the nonce's b64 representation */
struct _digest_nonce_data {
time_t creationtime;
/* in memory address of the nonce struct (similar purpose to an ETag) */
@@ -54,57 +54,56 @@
bool incache;
} flags;
};
void authDigestNonceUnlink(digest_nonce_h * nonce);
int authDigestNonceIsValid(digest_nonce_h * nonce, char nc[9]);
int authDigestNonceIsStale(digest_nonce_h * nonce);
const char *authenticateDigestNonceNonceb64(const digest_nonce_h * nonce);
int authDigestNonceLastRequest(digest_nonce_h * nonce);
void authenticateDigestNonceShutdown(void);
void authDigestNoncePurge(digest_nonce_h * nonce);
void authDigestUserLinkNonce(Auth::Digest::User * user, digest_nonce_h * nonce);
digest_nonce_h *authenticateDigestNonceNew(void);
namespace Auth
{
namespace Digest
{
/** Digest Authentication configuration data */
-class Config : public Auth::Config
+class Config : public Auth::SchemeConfig
{
public:
Config();
virtual bool active() const;
virtual bool configured() const;
virtual Auth::UserRequest::Pointer decode(char const *proxy_auth, const char *requestRealm);
virtual void done();
virtual void rotateHelpers();
- virtual bool dump(StoreEntry *, const char *, Auth::Config *) const;
+ virtual bool dump(StoreEntry *, const char *, Auth::SchemeConfig *) const;
virtual void fixHeader(Auth::UserRequest::Pointer, HttpReply *, Http::HdrType, HttpRequest *);
- virtual void init(Auth::Config *);
- virtual void parse(Auth::Config *, int, char *);
+ virtual void init(Auth::SchemeConfig *);
+ virtual void parse(Auth::SchemeConfig *, int, char *);
virtual void registerWithCacheManager(void);
virtual const char * type() const;
public:
time_t nonceGCInterval;
time_t noncemaxduration;
unsigned int noncemaxuses;
int NonceStrictness;
int CheckNonceCount;
int PostWorkaround;
- int utf8;
};
} // namespace Digest
} // namespace Auth
/* strings */
#define QOP_AUTH "auth"
extern helper *digestauthenticators;
#endif /* HAVE_AUTH_MODULE_DIGEST */
#endif
=== modified file 'src/auth/digest/Scheme.cc'
--- src/auth/digest/Scheme.cc 2016-01-01 00:12:18 +0000
+++ src/auth/digest/Scheme.cc 2016-12-19 13:27:31 +0000
@@ -26,27 +26,27 @@
}
char const *
Auth::Digest::Scheme::type() const
{
return "digest";
}
void
Auth::Digest::Scheme::shutdownCleanup()
{
if (_instance == NULL)
return;
authenticateDigestNonceShutdown();
_instance = NULL;
debugs(29, DBG_CRITICAL, "Shutdown: Digest authentication.");
}
-Auth::Config *
+Auth::SchemeConfig *
Auth::Digest::Scheme::createConfig()
{
Auth::Digest::Config *digestCfg = new Auth::Digest::Config;
- return dynamic_cast<Auth::Config*>(digestCfg);
+ return dynamic_cast<Auth::SchemeConfig*>(digestCfg);
}
=== modified file 'src/auth/digest/Scheme.h'
--- src/auth/digest/Scheme.h 2016-01-01 00:12:18 +0000
+++ src/auth/digest/Scheme.h 2016-12-19 13:27:32 +0000
@@ -1,50 +1,49 @@
/*
* 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_AUTH_DIGEST_SCHEME_H
#define SQUID_AUTH_DIGEST_SCHEME_H
#if HAVE_AUTH_MODULE_DIGEST
#include "auth/Scheme.h"
namespace Auth
{
namespace Digest
{
-/// \ingroup AuthSchemeAPI
/// \ingroup AuthAPI
class Scheme : public Auth::Scheme
{
public:
static Auth::Scheme::Pointer GetInstance();
Scheme() {};
virtual ~Scheme() {}
/* per scheme */
virtual char const *type () const;
virtual void shutdownCleanup();
- virtual Auth::Config *createConfig();
+ virtual Auth::SchemeConfig *createConfig();
/* Not implemented */
Scheme(Scheme const &);
Scheme &operator=(Scheme const &);
private:
static Auth::Scheme::Pointer _instance;
};
} // namespace Digest
} // namespace Auth
#endif /* HAVE_AUTH_MODULE_DIGEST */
#endif /* SQUID_AUTH_DIGEST_SCHEME_H */
=== modified file 'src/auth/digest/User.cc'
--- src/auth/digest/User.cc 2016-01-01 00:12:18 +0000
+++ src/auth/digest/User.cc 2016-12-19 14:50:30 +0000
@@ -1,78 +1,77 @@
/*
* 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/CredentialsCache.h"
#include "auth/digest/Config.h"
#include "auth/digest/User.h"
#include "Debug.h"
#include "dlink.h"
-#include "SquidConfig.h"
-#include "SquidTime.h"
-Auth::Digest::User::User(Auth::Config *aConfig, const char *aRequestRealm) :
+Auth::Digest::User::User(Auth::SchemeConfig *aConfig, const char *aRequestRealm) :
Auth::User(aConfig, aRequestRealm),
HA1created(0)
{
memset(HA1, 0, sizeof(HA1));
}
Auth::Digest::User::~User()
{
dlink_node *link, *tmplink;
link = nonces.head;
while (link) {
tmplink = link;
link = link->next;
dlinkDelete(tmplink, &nonces);
authDigestNoncePurge(static_cast < digest_nonce_h * >(tmplink->data));
authDigestNonceUnlink(static_cast < digest_nonce_h * >(tmplink->data));
delete tmplink;
}
}
int32_t
Auth::Digest::User::ttl() const
{
- int32_t global_ttl = static_cast<int32_t>(expiretime - squid_curtime + ::Config.authenticateTTL);
+ int32_t global_ttl = static_cast<int32_t>(expiretime - squid_curtime + Auth::TheConfig.authenticateTTL);
/* find the longest lasting nonce. */
int32_t latest_nonce = -1;
dlink_node *link = nonces.head;
while (link) {
digest_nonce_h *nonce = static_cast<digest_nonce_h *>(link->data);
if (nonce->flags.valid && nonce->noncedata.creationtime > latest_nonce)
latest_nonce = nonce->noncedata.creationtime;
link = link->next;
}
if (latest_nonce == -1)
return min(-1, global_ttl);
- int32_t nonce_ttl = latest_nonce - current_time.tv_sec + static_cast<Config*>(Auth::Config::Find("digest"))->noncemaxduration;
+ int32_t nonce_ttl = latest_nonce - current_time.tv_sec + static_cast<Config*>(Auth::SchemeConfig::Find("digest"))->noncemaxduration;
return min(nonce_ttl, global_ttl);
}
digest_nonce_h *
Auth::Digest::User::currentNonce()
{
digest_nonce_h *nonce = NULL;
dlink_node *link = nonces.tail;
if (link) {
nonce = static_cast<digest_nonce_h *>(link->data);
if (authDigestNonceIsStale(nonce))
nonce = NULL;
}
return nonce;
}
CbcPointer<Auth::CredentialsCache>
Auth::Digest::User::Cache()
{
=== modified file 'src/auth/digest/User.h'
--- src/auth/digest/User.h 2016-01-01 00:12:18 +0000
+++ src/auth/digest/User.h 2016-12-19 13:27:34 +0000
@@ -9,41 +9,41 @@
#ifndef _SQUID_AUTH_DIGEST_USER_H
#define _SQUID_AUTH_DIGEST_USER_H
#if HAVE_AUTH_MODULE_DIGEST
#include "auth/digest/Config.h"
#include "auth/User.h"
#include "rfc2617.h"
namespace Auth
{
namespace Digest
{
/** User credentials for the Digest authentication protocol */
class User : public Auth::User
{
MEMPROXY_CLASS(Auth::Digest::User);
public:
- User(Auth::Config *, const char *requestRealm);
+ User(Auth::SchemeConfig *, const char *requestRealm);
virtual ~User();
int authenticated() const;
virtual int32_t ttl() const override;
/* Auth::User API */
static CbcPointer<Auth::CredentialsCache> Cache();
virtual void addToNameCache() override;
HASH HA1;
int HA1created;
/* what nonces have been allocated to this user */
dlink_list nonces;
digest_nonce_h * currentNonce();
};
} // namespace Digest
} // namespace Auth
=== modified file 'src/auth/digest/UserRequest.cc'
--- src/auth/digest/UserRequest.cc 2016-11-27 13:57:50 +0000
+++ src/auth/digest/UserRequest.cc 2016-12-19 13:27:35 +0000
@@ -110,41 +110,41 @@
DigestCalcHA1(digest_request->algorithm, NULL, NULL, NULL,
authenticateDigestNonceNonceb64(digest_request->nonce),
digest_request->cnonce,
digest_user->HA1, SESSIONKEY);
SBuf sTmp = request->method.image();
DigestCalcResponse(SESSIONKEY, authenticateDigestNonceNonceb64(digest_request->nonce),
digest_request->nc, digest_request->cnonce, digest_request->qop,
sTmp.c_str(), digest_request->uri, HA2, Response);
debugs(29, 9, "\nResponse = '" << digest_request->response << "'\nsquid is = '" << Response << "'");
if (strcasecmp(digest_request->response, Response) != 0) {
if (!digest_request->flags.helper_queried) {
/* Query the helper in case the password has changed */
digest_request->flags.helper_queried = true;
auth_user->credentials(Auth::Pending);
return;
}
- if (static_cast<Auth::Digest::Config*>(Auth::Config::Find("digest"))->PostWorkaround && request->method != Http::METHOD_GET) {
+ if (static_cast<Auth::Digest::Config*>(Auth::SchemeConfig::Find("digest"))->PostWorkaround && request->method != Http::METHOD_GET) {
/* Ugly workaround for certain very broken browsers using the
* wrong method to calculate the request-digest on POST request.
* This should be deleted once Digest authentication becomes more
* widespread and such broken browsers no longer are commonly
* used.
*/
sTmp = HttpRequestMethod(Http::METHOD_GET).image();
DigestCalcResponse(SESSIONKEY, authenticateDigestNonceNonceb64(digest_request->nonce),
digest_request->nc, digest_request->cnonce, digest_request->qop,
sTmp.c_str(), digest_request->uri, HA2, Response);
if (strcasecmp(digest_request->response, Response)) {
auth_user->credentials(Auth::Failed);
digest_request->flags.invalid_password = true;
digest_request->setDenyMessage("Incorrect password");
return;
} else {
const char *useragent = request->header.getStr(Http::HdrType::USER_AGENT);
static Ip::Address last_broken_addr;
@@ -216,41 +216,41 @@
}
void
Auth::Digest::UserRequest::addAuthenticationInfoHeader(HttpReply * rep, int accel)
{
Http::HdrType type;
/* don't add to authentication error pages */
if ((!accel && rep->sline.status() == Http::scProxyAuthenticationRequired)
|| (accel && rep->sline.status() == Http::scUnauthorized))
return;
type = accel ? Http::HdrType::AUTHENTICATION_INFO : Http::HdrType::PROXY_AUTHENTICATION_INFO;
#if WAITING_FOR_TE
/* test for http/1.1 transfer chunked encoding */
if (chunkedtest)
return;
#endif
- if ((static_cast<Auth::Digest::Config*>(Auth::Config::Find("digest"))->authenticateProgram) && authDigestNonceLastRequest(nonce)) {
+ if ((static_cast<Auth::Digest::Config*>(Auth::SchemeConfig::Find("digest"))->authenticateProgram) && authDigestNonceLastRequest(nonce)) {
flags.authinfo_sent = true;
Auth::Digest::User *digest_user = dynamic_cast<Auth::Digest::User *>(user().getRaw());
if (!digest_user)
return;
digest_nonce_h *nextnonce = digest_user->currentNonce();
if (!nextnonce || authDigestNonceLastRequest(nonce)) {
nextnonce = authenticateDigestNonceNew();
authDigestUserLinkNonce(digest_user, nextnonce);
}
debugs(29, 9, "Sending type:" << type << " header: 'nextnonce=\"" << authenticateDigestNonceNonceb64(nextnonce) << "\"");
httpHeaderPutStrf(&rep->header, type, "nextnonce=\"%s\"", authenticateDigestNonceNonceb64(nextnonce));
}
}
#if WAITING_FOR_TE
void
Auth::Digest::UserRequest::addAuthenticationInfoTrailer(HttpReply * rep, int accel)
{
int type;
@@ -274,48 +274,48 @@
nonce = digest_user->currentNonce();
if (!nonce) {
nonce = authenticateDigestNonceNew();
authDigestUserLinkNonce(digest_user, nonce);
}
debugs(29, 9, "Sending type:" << type << " header: 'nextnonce=\"" << authenticateDigestNonceNonceb64(nonce) << "\"");
httpTrailerPutStrf(&rep->header, type, "nextnonce=\"%s\"", authenticateDigestNonceNonceb64(nonce));
}
}
#endif
/* send the initial data to a digest authenticator module */
void
Auth::Digest::UserRequest::startHelperLookup(HttpRequest *request, AccessLogEntry::Pointer &al, AUTHCB * handler, void *data)
{
char buf[8192];
assert(user() != NULL && user()->auth_type == Auth::AUTH_DIGEST);
debugs(29, 9, HERE << "'\"" << user()->username() << "\":\"" << realm << "\"'");
- if (static_cast<Auth::Digest::Config*>(Auth::Config::Find("digest"))->authenticateProgram == NULL) {
+ if (static_cast<Auth::Digest::Config*>(Auth::SchemeConfig::Find("digest"))->authenticateProgram == NULL) {
debugs(29, DBG_CRITICAL, "ERROR: No Digest authentication program configured.");
handler(data);
return;
}
const char *keyExtras = helperRequestKeyExtras(request, al);
- if (static_cast<Auth::Digest::Config*>(Auth::Config::Find("digest"))->utf8) {
+ if (static_cast<Auth::Digest::Config*>(Auth::SchemeConfig::Find("digest"))->utf8) {
char userstr[1024];
latin1_to_utf8(userstr, sizeof(userstr), user()->username());
if (keyExtras)
snprintf(buf, 8192, "\"%s\":\"%s\" %s\n", userstr, realm, keyExtras);
else
snprintf(buf, 8192, "\"%s\":\"%s\"\n", userstr, realm);
} else {
if (keyExtras)
snprintf(buf, 8192, "\"%s\":\"%s\" %s\n", user()->username(), realm, keyExtras);
else
snprintf(buf, 8192, "\"%s\":\"%s\"\n", user()->username(), realm);
}
helperSubmit(digestauthenticators, buf, Auth::Digest::UserRequest::HandleReply,
new Auth::StateData(this, handler, data));
}
void
Auth::Digest::UserRequest::HandleReply(void *data, const Helper::Reply &reply)
{
=== added file 'src/auth/forward.h'
--- src/auth/forward.h 1970-01-01 00:00:00 +0000
+++ src/auth/forward.h 2016-12-19 13:27:53 +0000
@@ -0,0 +1,30 @@
+/*
+ * 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_SRC_AUTH_FORWARD_H
+#define SQUID_SRC_AUTH_FORWARD_H
+
+#if USE_AUTH
+
+#include <vector>
+
+/// HTTP Authentication
+namespace Auth
+{
+
+class CredentialsCache;
+
+class Scheme;
+class SchemeConfig;
+typedef std::vector<Auth::SchemeConfig *> ConfigVector;
+
+} // namespace Auth
+
+#endif /* USE_AUTH */
+#endif /* SQUID_SRC_AUTH_FORWARD_H */
+
=== modified file 'src/auth/negotiate/Config.cc'
--- src/auth/negotiate/Config.cc 2016-01-24 17:41:43 +0000
+++ src/auth/negotiate/Config.cc 2016-12-20 11:17:35 +0000
@@ -14,132 +14,94 @@
#include "squid.h"
#include "auth/Gadgets.h"
#include "auth/negotiate/Config.h"
#include "auth/negotiate/Scheme.h"
#include "auth/negotiate/User.h"
#include "auth/negotiate/UserRequest.h"
#include "auth/State.h"
#include "cache_cf.h"
#include "client_side.h"
#include "helper.h"
#include "http/Stream.h"
#include "HttpHeaderTools.h"
#include "HttpReply.h"
#include "HttpRequest.h"
#include "mgr/Registration.h"
#include "SquidTime.h"
#include "Store.h"
#include "wordlist.h"
-/**
- \defgroup AuthNegotiateInternal Negotiate Authenticator Internals
- \ingroup AuthNegotiateAPI
- */
-
-/* Negotiate Scheme */
static AUTHSSTATS authenticateNegotiateStats;
-/// \ingroup AuthNegotiateInternal
statefulhelper *negotiateauthenticators = NULL;
-/// \ingroup AuthNegotiateInternal
static int authnegotiate_initialised = 0;
-/// \ingroup AuthNegotiateInternal
static hash_table *proxy_auth_cache = NULL;
void
Auth::Negotiate::Config::rotateHelpers()
{
/* schedule closure of existing helpers */
if (negotiateauthenticators) {
helperStatefulShutdown(negotiateauthenticators);
}
/* NP: dynamic helper restart will ensure they start up again as needed. */
}
void
Auth::Negotiate::Config::done()
{
- Auth::Config::done();
+ Auth::SchemeConfig::done();
authnegotiate_initialised = 0;
if (negotiateauthenticators) {
helperStatefulShutdown(negotiateauthenticators);
}
if (!shutting_down)
return;
delete negotiateauthenticators;
negotiateauthenticators = NULL;
if (authenticateProgram)
wordlistDestroy(&authenticateProgram);
debugs(29, DBG_IMPORTANT, "Reconfigure: Negotiate authentication configuration cleared.");
}
-bool
-Auth::Negotiate::Config::dump(StoreEntry * entry, const char *name, Auth::Config * scheme) const
-{
- if (!Auth::Config::dump(entry, name, scheme))
- return false;
-
- storeAppendPrintf(entry, "%s negotiate keep_alive %s\n", name, keep_alive ? "on" : "off");
- return true;
-}
-
-Auth::Negotiate::Config::Config() : keep_alive(1)
-{ }
-
-void
-Auth::Negotiate::Config::parse(Auth::Config * scheme, int n_configured, char *param_str)
-{
- if (strcmp(param_str, "program") == 0) {
- if (authenticateProgram)
- wordlistDestroy(&authenticateProgram);
-
- parse_wordlist(&authenticateProgram);
-
- requirePathnameExists("auth_param negotiate program", authenticateProgram->key);
- } else if (strcmp(param_str, "keep_alive") == 0) {
- parse_onoff(&keep_alive);
- } else
- Auth::Config::parse(scheme, n_configured, param_str);
-}
-
const char *
Auth::Negotiate::Config::type() const
{
return Auth::Negotiate::Scheme::GetInstance()->type();
}
/**
* Initialize helpers and the like for this auth scheme.
* Called AFTER parsing the config file
*/
void
-Auth::Negotiate::Config::init(Auth::Config *)
+Auth::Negotiate::Config::init(Auth::SchemeConfig *)
{
if (authenticateProgram) {
authnegotiate_initialised = 1;
if (negotiateauthenticators == NULL)
negotiateauthenticators = new statefulhelper("negotiateauthenticator");
if (!proxy_auth_cache)
proxy_auth_cache = hash_create((HASHCMP *) strcmp, 7921, hash_string);
assert(proxy_auth_cache);
negotiateauthenticators->cmdline = authenticateProgram;
negotiateauthenticators->childs.updateLimits(authenticateChildren);
negotiateauthenticators->ipc_type = IPC_STREAM;
helperStatefulOpenServers(negotiateauthenticators);
@@ -155,42 +117,40 @@
}
bool
Auth::Negotiate::Config::active() const
{
return authnegotiate_initialised == 1;
}
bool
Auth::Negotiate::Config::configured() const
{
if (authenticateProgram && (authenticateChildren.n_max != 0)) {
debugs(29, 9, HERE << "returning configured");
return true;
}
debugs(29, 9, HERE << "returning unconfigured");
return false;
}
-/* Negotiate Scheme */
-
void
Auth::Negotiate::Config::fixHeader(Auth::UserRequest::Pointer auth_user_request, HttpReply *rep, Http::HdrType reqType, HttpRequest * request)
{
if (!authenticateProgram)
return;
/* Need keep-alive */
if (!request->flags.proxyKeepalive && request->flags.mustKeepalive)
return;
/* New request, no user details */
if (auth_user_request == NULL) {
debugs(29, 9, HERE << "Sending type:" << reqType << " header: 'Negotiate'");
httpHeaderPutStrf(&rep->header, reqType, "Negotiate");
if (!keep_alive) {
/* drop the connection */
rep->header.delByName("keep-alive");
request->flags.proxyKeepalive = false;
}
@@ -239,34 +199,34 @@
debugs(29, DBG_CRITICAL, "ERROR: Negotiate auth fixHeader: state " << negotiate_request->user()->credentials() << ".");
fatal("unexpected state in AuthenticateNegotiateFixErrorHeader.\n");
}
}
}
static void
authenticateNegotiateStats(StoreEntry * sentry)
{
if (negotiateauthenticators)
negotiateauthenticators->packStatsInto(sentry, "Negotiate Authenticator Statistics");
}
/*
* Decode a Negotiate [Proxy-]Auth string, placing the results in the passed
* Auth_user structure.
*/
Auth::UserRequest::Pointer
Auth::Negotiate::Config::decode(char const *proxy_auth, const char *aRequestRealm)
{
- Auth::Negotiate::User *newUser = new Auth::Negotiate::User(Auth::Config::Find("negotiate"), aRequestRealm);
+ Auth::Negotiate::User *newUser = new Auth::Negotiate::User(Auth::SchemeConfig::Find("negotiate"), aRequestRealm);
Auth::UserRequest *auth_user_request = new Auth::Negotiate::UserRequest();
assert(auth_user_request->user() == NULL);
auth_user_request->user(newUser);
auth_user_request->user()->auth_type = Auth::AUTH_NEGOTIATE;
auth_user_request->user()->BuildUserKey(proxy_auth, aRequestRealm);
/* all we have to do is identify that it's Negotiate - the helper does the rest */
debugs(29, 9, HERE << "decode Negotiate authentication");
return auth_user_request;
}
=== modified file 'src/auth/negotiate/Config.h'
--- src/auth/negotiate/Config.h 2016-01-01 00:12:18 +0000
+++ src/auth/negotiate/Config.h 2016-12-20 11:16:46 +0000
@@ -1,52 +1,46 @@
/*
* 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 __AUTH_NEGOTIATE_H__
#define __AUTH_NEGOTIATE_H__
#if HAVE_AUTH_MODULE_NEGOTIATE
-#include "auth/Config.h"
#include "auth/Gadgets.h"
+#include "auth/SchemeConfig.h"
#include "auth/UserRequest.h"
#include "helper/forward.h"
namespace Auth
{
namespace Negotiate
{
/** Negotiate Authentication configuration data */
-class Config : public Auth::Config
+class Config : public Auth::SchemeConfig
{
public:
- Config();
virtual bool active() const;
virtual bool configured() const;
virtual Auth::UserRequest::Pointer decode(char const *proxy_auth, const char *requestRealm);
virtual void done();
virtual void rotateHelpers();
- virtual bool dump(StoreEntry *, const char *, Auth::Config *) const;
virtual void fixHeader(Auth::UserRequest::Pointer, HttpReply *, Http::HdrType, HttpRequest *);
- virtual void init(Auth::Config *);
- virtual void parse(Auth::Config *, int, char *);
+ virtual void init(Auth::SchemeConfig *);
virtual void registerWithCacheManager(void);
virtual const char * type() const;
-
-public:
- int keep_alive;
};
} // namespace Negotiate
} // namespace Auth
extern statefulhelper *negotiateauthenticators;
#endif /* HAVE_AUTH_MODULE_NEGOTIATE */
#endif
=== modified file 'src/auth/negotiate/Scheme.cc'
--- src/auth/negotiate/Scheme.cc 2016-01-01 00:12:18 +0000
+++ src/auth/negotiate/Scheme.cc 2016-12-19 13:28:02 +0000
@@ -23,27 +23,27 @@
}
return _instance;
}
char const *
Auth::Negotiate::Scheme::type() const
{
return "negotiate";
}
void
Auth::Negotiate::Scheme::shutdownCleanup()
{
if (_instance == NULL)
return;
_instance = NULL;
debugs(29, DBG_CRITICAL, "Shutdown: Negotiate authentication.");
}
-Auth::Config *
+Auth::SchemeConfig *
Auth::Negotiate::Scheme::createConfig()
{
Auth::Negotiate::Config *negotiateCfg = new Auth::Negotiate::Config;
- return dynamic_cast<Auth::Config*>(negotiateCfg);
+ return dynamic_cast<Auth::SchemeConfig*>(negotiateCfg);
}
=== modified file 'src/auth/negotiate/Scheme.h'
--- src/auth/negotiate/Scheme.h 2016-01-01 00:12:18 +0000
+++ src/auth/negotiate/Scheme.h 2016-12-19 13:28:04 +0000
@@ -1,49 +1,48 @@
/*
* 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_AUTH_NEGOTIATE_SCHEME_H
#define SQUID_AUTH_NEGOTIATE_SCHEME_H
#if HAVE_AUTH_MODULE_NEGOTIATE
#include "auth/Scheme.h"
namespace Auth
{
namespace Negotiate
{
-/// \ingroup AuthSchemeAPI
/// \ingroup AuthAPI
class Scheme : public Auth::Scheme
{
public:
static Auth::Scheme::Pointer GetInstance();
Scheme() {};
virtual ~Scheme() {};
/* per scheme */
virtual char const *type() const;
virtual void shutdownCleanup();
- virtual Auth::Config *createConfig();
+ virtual Auth::SchemeConfig *createConfig();
/* Not implemented */
Scheme (Scheme const &);
Scheme &operator=(Scheme const &);
private:
static Auth::Scheme::Pointer _instance;
};
} // namespace Negotiate
} // namespace Auth
#endif /* HAVE_AUTH_MODULE_NEGOTIATE */
#endif /* SQUID_AUTH_NEGOTIATE_SCHEME_H */
=== modified file 'src/auth/negotiate/User.cc'
--- src/auth/negotiate/User.cc 2016-01-01 00:12:18 +0000
+++ src/auth/negotiate/User.cc 2016-12-19 13:28:05 +0000
@@ -1,35 +1,35 @@
/*
* 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/CredentialsCache.h"
#include "auth/negotiate/User.h"
+#include "auth/SchemeConfig.h"
#include "Debug.h"
-Auth::Negotiate::User::User(Auth::Config *aConfig, const char *aRequestRealm) :
+Auth::Negotiate::User::User(Auth::SchemeConfig *aConfig, const char *aRequestRealm) :
Auth::User(aConfig, aRequestRealm)
{
}
Auth::Negotiate::User::~User()
{
debugs(29, 5, HERE << "doing nothing to clear Negotiate scheme data for '" << this << "'");
}
int32_t
Auth::Negotiate::User::ttl() const
{
return -1; // Negotiate cannot be cached.
}
CbcPointer<Auth::CredentialsCache>
Auth::Negotiate::User::Cache()
{
static CbcPointer<Auth::CredentialsCache> p(new Auth::CredentialsCache("negotiate", "GC Negotiate user credentials"));
return p;
=== modified file 'src/auth/negotiate/User.h'
--- src/auth/negotiate/User.h 2016-01-01 00:12:18 +0000
+++ src/auth/negotiate/User.h 2016-12-19 13:28:06 +0000
@@ -1,46 +1,46 @@
/*
* 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_AUTH_NEGOTIATE_USER_H
#define _SQUID_AUTH_NEGOTIATE_USER_H
#if HAVE_AUTH_MODULE_NEGOTIATE
#include "auth/User.h"
namespace Auth
{
-class Config;
+class SchemeConfig;
namespace Negotiate
{
/** User credentials for the Negotiate authentication protocol */
class User : public Auth::User
{
MEMPROXY_CLASS(Auth::Negotiate::User);
public:
- User(Auth::Config *, const char *requestRealm);
+ User(Auth::SchemeConfig *, const char *requestRealm);
virtual ~User();
virtual int32_t ttl() const override;
/* Auth::User API */
static CbcPointer<Auth::CredentialsCache> Cache();
virtual void addToNameCache() override;
dlink_list proxy_auth_list;
};
} // namespace Negotiate
} // namespace Auth
#endif /* HAVE_AUTH_MODULE_NEGOTIATE */
#endif /* _SQUID_AUTH_NEGOTIATE_USER_H */
=== modified file 'src/auth/negotiate/UserRequest.cc'
--- src/auth/negotiate/UserRequest.cc 2016-01-24 17:41:43 +0000
+++ src/auth/negotiate/UserRequest.cc 2016-12-19 13:28:07 +0000
@@ -111,41 +111,41 @@
case Auth::Failed:
return Auth::CRED_ERROR; // XXX: really? not VALID or CHALLENGE?
default:
debugs(29, DBG_IMPORTANT, "WARNING: Negotiate Authentication in unexpected state: " << user()->credentials());
return Auth::CRED_ERROR;
}
}
void
Auth::Negotiate::UserRequest::startHelperLookup(HttpRequest *, AccessLogEntry::Pointer &al, AUTHCB * handler, void *data)
{
static char buf[MAX_AUTHTOKEN_LEN];
assert(data);
assert(handler);
assert(user() != NULL);
assert(user()->auth_type == Auth::AUTH_NEGOTIATE);
- if (static_cast<Auth::Negotiate::Config*>(Auth::Config::Find("negotiate"))->authenticateProgram == NULL) {
+ if (static_cast<Auth::Negotiate::Config*>(Auth::SchemeConfig::Find("negotiate"))->authenticateProgram == NULL) {
debugs(29, DBG_CRITICAL, "ERROR: No Negotiate authentication program configured.");
handler(data);
return;
}
debugs(29, 8, HERE << "credentials state is '" << user()->credentials() << "'");
const char *keyExtras = helperRequestKeyExtras(request, al);
int printResult = 0;
if (user()->credentials() == Auth::Pending) {
if (keyExtras)
printResult = snprintf(buf, sizeof(buf), "YR %s %s\n", client_blob, keyExtras);
else
printResult = snprintf(buf, sizeof(buf), "YR %s\n", client_blob); //CHECKME: can ever client_blob be 0 here?
} else {
if (keyExtras)
printResult = snprintf(buf, sizeof(buf), "KK %s %s\n", client_blob, keyExtras);
else
printResult = snprintf(buf, sizeof(buf), "KK %s\n", client_blob);
}
=== modified file 'src/auth/negotiate/UserRequest.h'
--- src/auth/negotiate/UserRequest.h 2016-01-01 00:12:18 +0000
+++ src/auth/negotiate/UserRequest.h 2016-12-19 13:28:08 +0000
@@ -6,41 +6,40 @@
* Please see the COPYING and CONTRIBUTORS files for details.
*/
#ifndef _SQUID_SRC_AUTH_NEGOTIATE_USERREQUEST_H
#define _SQUID_SRC_AUTH_NEGOTIATE_USERREQUEST_H
#if HAVE_AUTH_MODULE_NEGOTIATE
#include "auth/UserRequest.h"
#include "helper/forward.h"
class ConnStateData;
class HttpReply;
class HttpRequest;
namespace Auth
{
namespace Negotiate
{
-/// \ingroup AuthNegotiateAPI
class UserRequest : public Auth::UserRequest
{
MEMPROXY_CLASS(Auth::Negotiate::UserRequest);
public:
UserRequest();
virtual ~UserRequest();
virtual int authenticated() const;
virtual void authenticate(HttpRequest * request, ConnStateData * conn, Http::HdrType type);
virtual Direction module_direction();
virtual void startHelperLookup(HttpRequest *request, AccessLogEntry::Pointer &al, AUTHCB *, void *);
virtual const char *credentialsStr();
virtual const char * connLastHeader();
/* we need to store the helper server between requests */
helper_stateful_server *authserver;
void releaseAuthServer(void); ///< Release the authserver helper server properly.
/* what connection is this associated with */
=== modified file 'src/auth/ntlm/Config.cc'
--- src/auth/ntlm/Config.cc 2016-01-24 17:41:43 +0000
+++ src/auth/ntlm/Config.cc 2016-12-20 11:18:30 +0000
@@ -37,99 +37,70 @@
statefulhelper *ntlmauthenticators = NULL;
static int authntlm_initialised = 0;
static hash_table *proxy_auth_cache = NULL;
void
Auth::Ntlm::Config::rotateHelpers()
{
/* schedule closure of existing helpers */
if (ntlmauthenticators) {
helperStatefulShutdown(ntlmauthenticators);
}
/* NP: dynamic helper restart will ensure they start up again as needed. */
}
/* free any allocated configuration details */
void
Auth::Ntlm::Config::done()
{
- Auth::Config::done();
+ Auth::SchemeConfig::done();
authntlm_initialised = 0;
if (ntlmauthenticators) {
helperStatefulShutdown(ntlmauthenticators);
}
if (!shutting_down)
return;
delete ntlmauthenticators;
ntlmauthenticators = NULL;
if (authenticateProgram)
wordlistDestroy(&authenticateProgram);
debugs(29, DBG_IMPORTANT, "Reconfigure: NTLM authentication configuration cleared.");
}
-bool
-Auth::Ntlm::Config::dump(StoreEntry * entry, const char *name, Auth::Config * scheme) const
-{
- if (!Auth::Config::dump(entry, name, scheme))
- return false;
-
- storeAppendPrintf(entry, "%s ntlm keep_alive %s\n", name, keep_alive ? "on" : "off");
- return true;
-}
-
-Auth::Ntlm::Config::Config() : keep_alive(1)
-{ }
-
-void
-Auth::Ntlm::Config::parse(Auth::Config * scheme, int n_configured, char *param_str)
-{
- if (strcmp(param_str, "program") == 0) {
- if (authenticateProgram)
- wordlistDestroy(&authenticateProgram);
-
- parse_wordlist(&authenticateProgram);
-
- requirePathnameExists("auth_param ntlm program", authenticateProgram->key);
- } else if (strcmp(param_str, "keep_alive") == 0) {
- parse_onoff(&keep_alive);
- } else
- Auth::Config::parse(scheme, n_configured, param_str);
-}
-
const char *
Auth::Ntlm::Config::type() const
{
return Auth::Ntlm::Scheme::GetInstance()->type();
}
/* Initialize helpers and the like for this auth scheme. Called AFTER parsing the
* config file */
void
-Auth::Ntlm::Config::init(Auth::Config *)
+Auth::Ntlm::Config::init(Auth::SchemeConfig *)
{
if (authenticateProgram) {
authntlm_initialised = 1;
if (ntlmauthenticators == NULL)
ntlmauthenticators = new statefulhelper("ntlmauthenticator");
if (!proxy_auth_cache)
proxy_auth_cache = hash_create((HASHCMP *) strcmp, 7921, hash_string);
assert(proxy_auth_cache);
ntlmauthenticators->cmdline = authenticateProgram;
ntlmauthenticators->childs.updateLimits(authenticateChildren);
ntlmauthenticators->ipc_type = IPC_STREAM;
helperStatefulOpenServers(ntlmauthenticators);
@@ -219,34 +190,34 @@
debugs(29, DBG_CRITICAL, "NTLM Auth fixHeader: state " << ntlm_request->user()->credentials() << ".");
fatal("unexpected state in AuthenticateNTLMFixErrorHeader.\n");
}
}
}
static void
authenticateNTLMStats(StoreEntry * sentry)
{
if (ntlmauthenticators)
ntlmauthenticators->packStatsInto(sentry, "NTLM Authenticator Statistics");
}
/*
* Decode a NTLM [Proxy-]Auth string, placing the results in the passed
* Auth_user structure.
*/
Auth::UserRequest::Pointer
Auth::Ntlm::Config::decode(char const *proxy_auth, const char *aRequestRealm)
{
- Auth::Ntlm::User *newUser = new Auth::Ntlm::User(Auth::Config::Find("ntlm"), aRequestRealm);
+ Auth::Ntlm::User *newUser = new Auth::Ntlm::User(Auth::SchemeConfig::Find("ntlm"), aRequestRealm);
Auth::UserRequest::Pointer auth_user_request = new Auth::Ntlm::UserRequest();
assert(auth_user_request->user() == NULL);
auth_user_request->user(newUser);
auth_user_request->user()->auth_type = Auth::AUTH_NTLM;
auth_user_request->user()->BuildUserKey(proxy_auth, aRequestRealm);
/* all we have to do is identify that it's NTLM - the helper does the rest */
debugs(29, 9, HERE << "decode: NTLM authentication");
return auth_user_request;
}
=== modified file 'src/auth/ntlm/Config.h'
--- src/auth/ntlm/Config.h 2016-01-01 00:12:18 +0000
+++ src/auth/ntlm/Config.h 2016-12-20 11:17:01 +0000
@@ -1,55 +1,49 @@
/*
* 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 __AUTH_NTLM_H__
#define __AUTH_NTLM_H__
#if HAVE_AUTH_MODULE_NTLM
-#include "auth/Config.h"
#include "auth/Gadgets.h"
+#include "auth/SchemeConfig.h"
#include "auth/UserRequest.h"
#include "helper/forward.h"
class HttpRequest;
class StoreEntry;
namespace Auth
{
namespace Ntlm
{
/** NTLM Authentication configuration data */
-class Config : public Auth::Config
+class Config : public Auth::SchemeConfig
{
public:
- Config();
virtual bool active() const;
virtual bool configured() const;
virtual Auth::UserRequest::Pointer decode(char const *proxy_auth, const char *requestRealm);
virtual void done();
virtual void rotateHelpers();
- virtual bool dump(StoreEntry *, const char *, Auth::Config *) const;
virtual void fixHeader(Auth::UserRequest::Pointer, HttpReply *, Http::HdrType, HttpRequest *);
- virtual void init(Auth::Config *);
- virtual void parse(Auth::Config *, int, char *);
+ virtual void init(Auth::SchemeConfig *);
virtual void registerWithCacheManager(void);
virtual const char * type() const;
-
-public:
- int keep_alive;
};
} // namespace Ntlm
} // namespace Auth
extern statefulhelper *ntlmauthenticators;
#endif /* HAVE_AUTH_MODULE_NTLM */
#endif
=== modified file 'src/auth/ntlm/Scheme.cc'
--- src/auth/ntlm/Scheme.cc 2016-01-01 00:12:18 +0000
+++ src/auth/ntlm/Scheme.cc 2016-12-19 13:28:29 +0000
@@ -23,27 +23,27 @@
}
return _instance;
}
char const *
Auth::Ntlm::Scheme::type() const
{
return "ntlm";
}
void
Auth::Ntlm::Scheme::shutdownCleanup()
{
if (_instance == NULL)
return;
_instance = NULL;
debugs(29, DBG_CRITICAL, "Shutdown: NTLM authentication.");
}
-Auth::Config *
+Auth::SchemeConfig *
Auth::Ntlm::Scheme::createConfig()
{
Auth::Ntlm::Config *ntlmCfg = new Auth::Ntlm::Config;
- return dynamic_cast<Auth::Config*>(ntlmCfg);
+ return dynamic_cast<Auth::SchemeConfig*>(ntlmCfg);
}
=== modified file 'src/auth/ntlm/Scheme.h'
--- src/auth/ntlm/Scheme.h 2016-01-01 00:12:18 +0000
+++ src/auth/ntlm/Scheme.h 2016-12-19 13:28:30 +0000
@@ -1,53 +1,52 @@
/*
* 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_AUTH_NTLM_SCHEME_H
#define SQUID_AUTH_NTLM_SCHEME_H
#if HAVE_AUTH_MODULE_NTLM
#include "auth/Scheme.h"
namespace Auth
{
namespace Ntlm
{
-/// \ingroup AuthSchemeAPI
/// \ingroup AuthAPI
class Scheme : public Auth::Scheme
{
public:
static Auth::Scheme::Pointer GetInstance();
Scheme() {};
virtual ~Scheme() {};
/* per scheme */
virtual char const *type() const;
virtual void shutdownCleanup();
- virtual Auth::Config *createConfig();
+ virtual Auth::SchemeConfig *createConfig();
/* Not implemented */
Scheme (Scheme const &);
Scheme &operator=(Scheme const &);
private:
/**
* Main instance of this authentication Scheme.
* NULL when the scheme is not being used.
*/
static Auth::Scheme::Pointer _instance;
};
} // namespace Ntlm
} // namespace Auth
#endif /* HAVE_AUTH_MODULE_NTLM */
#endif /* SQUID_AUTH_NTLM_SCHEME_H */
=== modified file 'src/auth/ntlm/User.cc'
--- src/auth/ntlm/User.cc 2016-01-01 00:12:18 +0000
+++ src/auth/ntlm/User.cc 2016-12-19 13:28:31 +0000
@@ -1,35 +1,35 @@
/*
* 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/CredentialsCache.h"
#include "auth/ntlm/User.h"
+#include "auth/SchemeConfig.h"
#include "Debug.h"
-Auth::Ntlm::User::User(Auth::Config *aConfig, const char *aRequestRealm) :
+Auth::Ntlm::User::User(Auth::SchemeConfig *aConfig, const char *aRequestRealm) :
Auth::User(aConfig, aRequestRealm)
{
}
Auth::Ntlm::User::~User()
{
debugs(29, 5, HERE << "doing nothing to clear NTLM scheme data for '" << this << "'");
}
int32_t
Auth::Ntlm::User::ttl() const
{
return -1; // NTLM credentials cannot be cached.
}
CbcPointer<Auth::CredentialsCache>
Auth::Ntlm::User::Cache()
{
static CbcPointer<Auth::CredentialsCache> p(new Auth::CredentialsCache("ntlm", "GC NTLM user credentials"));
return p;
=== modified file 'src/auth/ntlm/User.h'
--- src/auth/ntlm/User.h 2016-01-01 00:12:18 +0000
+++ src/auth/ntlm/User.h 2016-12-19 13:28:32 +0000
@@ -1,46 +1,44 @@
/*
* 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_AUTH_NTLM_USER_H
#define _SQUID_AUTH_NTLM_USER_H
#if HAVE_AUTH_MODULE_NTLM
#include "auth/User.h"
namespace Auth
{
-class Config;
-
namespace Ntlm
{
/** User credentials for the NTLM authentication protocol */
class User : public Auth::User
{
MEMPROXY_CLASS(Auth::Ntlm::User);
public:
- User(Auth::Config *, const char *requestRealm);
+ User(Auth::SchemeConfig *, const char *requestRealm);
virtual ~User();
virtual int32_t ttl() const override;
/* Auth::User API */
static CbcPointer<Auth::CredentialsCache> Cache();
virtual void addToNameCache() override;
dlink_list proxy_auth_list;
};
} // namespace Ntlm
} // namespace Auth
#endif /* HAVE_AUTH_MODULE_NTLM */
#endif /* _SQUID_AUTH_NTLM_USER_H */
=== modified file 'src/auth/ntlm/UserRequest.cc'
--- src/auth/ntlm/UserRequest.cc 2016-01-24 17:41:43 +0000
+++ src/auth/ntlm/UserRequest.cc 2016-12-19 13:28:33 +0000
@@ -107,41 +107,41 @@
case Auth::Ok:
return Auth::CRED_VALID;
case Auth::Failed:
return Auth::CRED_ERROR; // XXX: really? not VALID or CHALLENGE?
default:
debugs(29, DBG_IMPORTANT, "WARNING: NTLM Authentication in unexpected state: " << user()->credentials());
return Auth::CRED_ERROR;
}
}
void
Auth::Ntlm::UserRequest::startHelperLookup(HttpRequest *, AccessLogEntry::Pointer &al, AUTHCB * handler, void *data)
{
static char buf[MAX_AUTHTOKEN_LEN];
assert(data);
assert(handler);
- if (static_cast<Auth::Ntlm::Config*>(Auth::Config::Find("ntlm"))->authenticateProgram == NULL) {
+ if (static_cast<Auth::Ntlm::Config*>(Auth::SchemeConfig::Find("ntlm"))->authenticateProgram == NULL) {
debugs(29, DBG_CRITICAL, "ERROR: NTLM Start: no NTLM program configured.");
handler(data);
return;
}
debugs(29, 8, HERE << "credentials state is '" << user()->credentials() << "'");
const char *keyExtras = helperRequestKeyExtras(request, al);
int printResult = 0;
if (user()->credentials() == Auth::Pending) {
if (keyExtras)
printResult = snprintf(buf, sizeof(buf), "YR %s %s\n", client_blob, keyExtras);
else
printResult = snprintf(buf, sizeof(buf), "YR %s\n", client_blob); //CHECKME: can ever client_blob be 0 here?
} else {
if (keyExtras)
printResult = snprintf(buf, sizeof(buf), "KK %s %s\n", client_blob, keyExtras);
else
printResult = snprintf(buf, sizeof(buf), "KK %s\n", client_blob);
}
=== modified file 'src/cache_cf.cc'
--- src/cache_cf.cc 2016-12-10 16:27:09 +0000
+++ src/cache_cf.cc 2016-12-19 13:29:15 +0000
@@ -1,40 +1,42 @@
/*
* 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.
*/
/* DEBUG: section 03 Configuration File Parsing */
#include "squid.h"
#include "acl/Acl.h"
#include "acl/AclDenyInfoList.h"
#include "acl/AclSizeLimit.h"
#include "acl/Address.h"
#include "acl/Gadgets.h"
#include "acl/MethodData.h"
#include "acl/Tree.h"
#include "anyp/PortCfg.h"
#include "anyp/UriScheme.h"
+#include "auth/Config.h"
+#include "auth/Scheme.h"
#include "AuthReg.h"
#include "base/RunnersRegistry.h"
#include "cache_cf.h"
#include "CachePeer.h"
#include "ConfigParser.h"
#include "CpuAffinityMap.h"
#include "DiskIO/DiskIOModule.h"
#include "eui/Config.h"
#include "ExternalACL.h"
#include "format/Format.h"
#include "ftp/Elements.h"
#include "globals.h"
#include "HttpHeaderTools.h"
#include "icmp/IcmpConfig.h"
#include "ident/Config.h"
#include "ip/Intercept.h"
#include "ip/QosConfig.h"
#include "ip/tools.h"
#include "ipc/Kids.h"
#include "log/Config.h"
@@ -60,45 +62,40 @@
#include "store/Disks.h"
#include "StoreFileSystem.h"
#include "tools.h"
#include "util.h"
#include "wordlist.h"
/* wccp2 has its own conditional definitions */
#include "wccp2.h"
#if USE_ADAPTATION
#include "adaptation/Config.h"
#endif
#if ICAP_CLIENT
#include "adaptation/icap/Config.h"
#endif
#if USE_ECAP
#include "adaptation/ecap/Config.h"
#endif
#if USE_OPENSSL
#include "ssl/Config.h"
#include "ssl/support.h"
#endif
-#if USE_AUTH
-#include "auth/Config.h"
-#include "auth/Scheme.h"
-#include "auth/SchemesConfig.h"
-#endif
#if USE_SQUID_ESI
#include "esi/Parser.h"
#endif
#if SQUID_SNMP
#include "snmp.h"
#endif
#if HAVE_GLOB_H
#include <glob.h>
#endif
#include <limits>
#include <list>
#if HAVE_PWD_H
#include <pwd.h>
#endif
#if HAVE_GRP_H
#include <grp.h>
#endif
#if HAVE_SYS_STAT_H
#include <sys/stat.h>
@@ -921,49 +918,49 @@
/*
* Disable client side request pipelining if client_persistent_connections OFF.
* Waste of resources queueing any pipelined requests when the first will close the connection.
*/
if (Config.pipeline_max_prefetch > 0 && !Config.onoff.client_pconns) {
debugs(3, DBG_PARSE_NOTE(DBG_IMPORTANT), "WARNING: pipeline_prefetch " << Config.pipeline_max_prefetch <<
" requires client_persistent_connections ON. Forced pipeline_prefetch 0.");
Config.pipeline_max_prefetch = 0;
}
#if USE_AUTH
/*
* disable client side request pipelining. There is a race with
* Negotiate and NTLM when the client sends a second request on an
* connection before the authenticate challenge is sent. With
* pipelining OFF, the client may fail to authenticate, but squid's
* state will be preserved.
*/
if (Config.pipeline_max_prefetch > 0) {
- Auth::Config *nego = Auth::Config::Find("Negotiate");
- Auth::Config *ntlm = Auth::Config::Find("NTLM");
+ Auth::SchemeConfig *nego = Auth::SchemeConfig::Find("Negotiate");
+ Auth::SchemeConfig *ntlm = Auth::SchemeConfig::Find("NTLM");
if ((nego && nego->active()) || (ntlm && ntlm->active())) {
debugs(3, DBG_PARSE_NOTE(DBG_IMPORTANT), "WARNING: pipeline_prefetch breaks NTLM and Negotiate authentication. Forced pipeline_prefetch 0.");
Config.pipeline_max_prefetch = 0;
}
}
- for (auto &authSchemes: Config.authSchemesConfigs) {
+ for (auto &authSchemes : Auth::TheConfig.schemeLists) {
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
}
/** Parse a line containing an obsolete directive.
* To upgrade it where possible instead of just "Bungled config" for
* directives which cannot be marked as simply aliases of the some name.
* For example if the parameter order and content has changed.
* Or if the directive has been completely removed.
*/
void
parse_obsolete(const char *name)
{
// Directives which have been radically changed rather than removed
if (!strcmp(name, "url_rewrite_concurrency")) {
@@ -1775,110 +1772,110 @@
return s == NULL;
}
#if USE_AUTH
static void
parse_authparam(Auth::ConfigVector * config)
{
char *type_str = ConfigParser::NextToken();
if (!type_str) {
self_destruct();
return;
}
char *param_str = ConfigParser::NextToken();
if (!param_str) {
self_destruct();
return;
}
/* find a configuration for the scheme in the currently parsed configs... */
- Auth::Config *schemeCfg = Auth::Config::Find(type_str);
+ Auth::SchemeConfig *schemeCfg = Auth::SchemeConfig::Find(type_str);
if (schemeCfg == NULL) {
/* Create a configuration based on the scheme info */
Auth::Scheme::Pointer theScheme = Auth::Scheme::Find(type_str);
if (theScheme == NULL) {
debugs(3, DBG_CRITICAL, "Parsing Config File: Unknown authentication scheme '" << type_str << "'.");
self_destruct();
return;
}
config->push_back(theScheme->createConfig());
- schemeCfg = Auth::Config::Find(type_str);
+ schemeCfg = Auth::SchemeConfig::Find(type_str);
if (schemeCfg == NULL) {
debugs(3, DBG_CRITICAL, "Parsing Config File: Corruption configuring authentication scheme '" << type_str << "'.");
self_destruct();
return;
}
}
schemeCfg->parse(schemeCfg, config->size(), param_str);
}
static void
free_authparam(Auth::ConfigVector * cfg)
{
/* Wipe the Auth globals and Detach/Destruct component config + state. */
cfg->clear();
/* on reconfigure initialize new auth schemes for the new config. */
if (reconfiguring) {
Auth::Init();
}
}
static void
dump_authparam(StoreEntry * entry, const char *name, Auth::ConfigVector cfg)
{
- for (Auth::ConfigVector::iterator i = cfg.begin(); i != cfg.end(); ++i)
- (*i)->dump(entry, name, (*i));
+ for (auto *scheme : cfg)
+ scheme->dump(entry, name, scheme);
}
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);
+ Auth::TheConfig.schemeLists.emplace_back(tok, ConfigParser::LastTokenWasQuoted());
+ const allow_t action = allow_t(ACCESS_ALLOWED, Auth::TheConfig.schemeLists.size() - 1);
ParseAclWithAction(authSchemes, action, "auth_schemes");
}
static void
free_AuthSchemes(acl_access **authSchemes)
{
- Config.authSchemesConfigs.clear();
+ Auth::TheConfig.schemeLists.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;
+ return Auth::TheConfig.schemeLists.at(action.kind).rawSchemes;
}));
}
#endif /* USE_AUTH */
static void
ParseAclWithAction(acl_access **access, const allow_t &action, const char *desc, ACL *acl)
{
assert(access);
SBuf name;
if (!*access) {
*access = new Acl::Tree;
name.Printf("(%s rules)", desc);
(*access)->context(name.c_str(), config_input_line);
}
Acl::AndNode *rule = new Acl::AndNode;
name.Printf("(%s rule)", desc);
rule->context(name.c_str(), config_input_line);
acl ? rule->add(acl) : rule->lineParse();
(*access)->add(rule, action);
=== modified file 'src/cf.data.depend'
--- src/cf.data.depend 2016-12-10 04:48:25 +0000
+++ src/cf.data.depend 2016-12-15 06:41:12 +0000
@@ -1,39 +1,39 @@
## 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.
##
#
# type dependencies
#
access_log acl logformat
acl external_acl_type auth_param
acl_access acl
acl_address acl
acl_b_size_t acl
acl_tos acl
acl_nfmark acl
address
authparam
-AuthSchemes
+AuthSchemes acl auth_param
b_int64_t
b_size_t
b_ssize_t
cachedir cache_replacement_policy
cachemgrpasswd
ConfigAclTos
configuration_includes_quoted_values
CpuAffinityMap
debug
delay_pool_access acl delay_class
delay_pool_class delay_pools
delay_pool_count
delay_pool_rates delay_class
client_delay_pool_access acl
client_delay_pool_count
client_delay_pool_rates
denyinfo acl
eol
externalAclHelper auth_param
HelperChildConfig
=== modified file 'src/cf.data.pre'
--- src/cf.data.pre 2016-12-10 04:48:25 +0000
+++ src/cf.data.pre 2016-12-20 12:37:28 +0000
@@ -464,41 +464,41 @@
"optimistic" kernel simply kills Squid kid with a SIGBUS signal.
Some of the memory limits enforced by the kernel are currently
poorly understood: We do not know how to detect and check them. This
option ensures that the mapped memory will be available.
This option may have a positive performance side-effect: Locking
memory at start avoids runtime paging I/O. Paging slows Squid down.
Locking memory may require a large enough RLIMIT_MEMLOCK OS limit,
CAP_IPC_LOCK capability, or equivalent.
DOC_END
COMMENT_START
OPTIONS FOR AUTHENTICATION
-----------------------------------------------------------------------------
COMMENT_END
NAME: auth_param
TYPE: authparam
IFDEF: USE_AUTH
-LOC: Auth::TheConfig
+LOC: Auth::TheConfig.schemes
DEFAULT: none
DOC_START
This is used to define parameters for the various authentication
schemes supported by Squid.
format: auth_param scheme parameter [setting]
The order in which authentication schemes are presented to the client is
dependent on the order the scheme first appears in config file. IE
has a bug (it's not RFC 2617 compliant) in that it will use the basic
scheme if basic is the first entry presented, even if more secure
schemes are presented. For now use the order in the recommended
settings section below. If other browsers have difficulties (don't
recognize the schemes offered even if you are using basic) either
put basic first, or disable the other schemes (by commenting out their
program entry).
Once an authentication scheme is fully configured, it can only be
shutdown by shutting squid down and restarting. Changes can be made on
the fly and activated with a reconfigure. I.E. You can change to a
@@ -600,239 +600,177 @@
on-persistent-overload option applies.
The on-persistent-overload=action option specifies Squid
reaction to a new helper request arriving when the helper
has been overloaded for more that 3 minutes already. The number
of queued requests determines whether the helper is overloaded
(see the queue-size option).
Two actions are supported:
die Squid worker quits. This is the default behavior.
ERR Squid treats the helper request as if it was
immediately submitted, and the helper immediately
replied with an ERR response. This action has no effect
on the already queued and in-progress helper requests.
NOTE: NTLM and Negotiate schemes do not support concurrency
in the Squid code module even though some helpers can.
+ "keep_alive" on|off
+ If you experience problems with PUT/POST requests when using
+ the NTLM or Negotiate schemes then you can try setting this
+ to off. This will cause Squid to forcibly close the connection
+ on the initial request where the browser asks which schemes
+ are supported by the proxy.
-IF HAVE_AUTH_MODULE_BASIC
- === Basic authentication parameters ===
+ For Basic and Digest this parameter is ignored.
"utf8" on|off
HTTP uses iso-latin-1 as character set, while some
authentication backends such as LDAP expects UTF-8. If this is
set to on Squid will translate the HTTP iso-latin-1 charset to
UTF-8 before sending the username and password to the helper.
+ For NTLM and Negotiate this parameter is ignored.
+
+IF HAVE_AUTH_MODULE_BASIC
+ === Basic authentication parameters ===
+
"credentialsttl" timetolive
Specifies how long squid assumes an externally validated
username:password pair is valid for - in other words how
often the helper program is called for that user. Set this
low to force revalidation with short lived passwords.
NOTE: setting this high does not impact your susceptibility
to replay attacks unless you are using an one-time password
system (such as SecureID). If you are using such a system,
you will be vulnerable to replay attacks unless you also
use the max_user_ip ACL in an http_access rule.
"casesensitive" on|off
Specifies if usernames are case sensitive. Most user databases
are case insensitive allowing the same username to be spelled
using both lower and upper case letters, but some are case
sensitive. This makes a big difference for user_max_ip ACL
processing and similar.
ENDIF
IF HAVE_AUTH_MODULE_DIGEST
=== Digest authentication parameters ===
- "utf8" on|off
- HTTP uses iso-latin-1 as character set, while some
- authentication backends such as LDAP expects UTF-8. If this is
- set to on Squid will translate the HTTP iso-latin-1 charset to
- UTF-8 before sending the username and password to the helper.
-
"nonce_garbage_interval" timeinterval
Specifies the interval that nonces that have been issued
to client_agent's are checked for validity.
"nonce_max_duration" timeinterval
Specifies the maximum length of time a given nonce will be
valid for.
"nonce_max_count" number
Specifies the maximum number of times a given nonce can be
used.
"nonce_strictness" on|off
Determines if squid requires strict increment-by-1 behavior
for nonce counts, or just incrementing (off - for use when
user agents generate nonce counts that occasionally miss 1
(ie, 1,2,4,6)). Default off.
"check_nonce_count" on|off
This directive if set to off can disable the nonce count check
completely to work around buggy digest qop implementations in
certain mainstream browser versions. Default on to check the
nonce count to protect from authentication replay attacks.
"post_workaround" on|off
This is a workaround to certain buggy browsers who send an
incorrect request digest in POST requests when reusing the
same nonce as acquired earlier on a GET request.
ENDIF
-IF HAVE_AUTH_MODULE_NEGOTIATE
- === Negotiate authentication parameters ===
-
- "keep_alive" on|off
- If you experience problems with PUT/POST requests when using
- the this authentication scheme then you can try setting this
- to off. This will cause Squid to forcibly close the connection
- on the initial request where the browser asks which schemes
- are supported by the proxy.
-
-ENDIF
-IF HAVE_AUTH_MODULE_NTLM
- === NTLM authentication parameters ===
-
- "keep_alive" on|off
- If you experience problems with PUT/POST requests when using
- the this authentication scheme then you can try setting this
- to off. This will cause Squid to forcibly close the connection
- on the initial request where the browser asks which schemes
- are supported by the proxy.
-ENDIF
=== Example Configuration ===
This configuration displays the recommended authentication scheme
order from most to least secure with recommended minimum configuration
settings for each scheme:
#auth_param negotiate program <uncomment and complete this line to activate>
#auth_param negotiate children 20 startup=0 idle=1
-#auth_param negotiate keep_alive on
#
#auth_param digest program <uncomment and complete this line to activate>
#auth_param digest children 20 startup=0 idle=1
#auth_param digest realm Squid proxy-caching web server
#auth_param digest nonce_garbage_interval 5 minutes
#auth_param digest nonce_max_duration 30 minutes
#auth_param digest nonce_max_count 50
#
#auth_param ntlm program <uncomment and complete this line to activate>
#auth_param ntlm children 20 startup=0 idle=1
-#auth_param ntlm keep_alive on
#
#auth_param basic program <uncomment and complete this line>
#auth_param basic children 5 startup=5 idle=1
-#auth_param basic realm Squid proxy-caching web server
#auth_param basic credentialsttl 2 hours
DOC_END
NAME: authenticate_cache_garbage_interval
+IFDEF: USE_AUTH
TYPE: time_t
DEFAULT: 1 hour
-LOC: Config.authenticateGCInterval
+LOC: Auth::TheConfig.authenticateGCInterval
DOC_START
The time period between garbage collection across the username cache.
This is a trade-off between memory utilization (long intervals - say
2 days) and CPU (short intervals - say 1 minute). Only change if you
have good reason to.
DOC_END
NAME: authenticate_ttl
+IFDEF: USE_AUTH
TYPE: time_t
DEFAULT: 1 hour
-LOC: Config.authenticateTTL
+LOC: Auth::TheConfig.authenticateTTL
DOC_START
The time a user & their credentials stay in the logged in
user cache since their last request. When the garbage
interval passes, all user credentials that have passed their
TTL are removed from memory.
DOC_END
NAME: authenticate_ip_ttl
+IFDEF: USE_AUTH
TYPE: time_t
-LOC: Config.authenticateIpTTL
+LOC: Auth::TheConfig.authenticateIpTTL
DEFAULT: 1 second
DOC_START
If you use proxy authentication and the 'max_user_ip' ACL,
this directive controls how long Squid remembers the IP
addresses associated with each user. Use a small value
(e.g., 60 seconds) if your users might change addresses
quickly, as is the case with dialup. You might be safe
using a larger value (e.g., 2 hours) in a corporate LAN
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
-----------------------------------------------------------------------------
COMMENT_END
NAME: external_acl_type
TYPE: externalAclHelper
LOC: Config.externalAclHelperList
DEFAULT: none
DOC_START
This option defines external acl classes using a helper program
to look up the status
external_acl_type name [options] FORMAT /path/to/helper [helper arguments]
Options:
ttl=n TTL in seconds for cached results (defaults to 3600
for 1 hour)
@@ -1914,40 +1852,85 @@
Currently, this directive has effect on intercepted connections and
bumped tunnels only. Other cases are not supported because Squid
cannot know the intended destination of other traffic.
For example:
# define what Squid errors indicate receiving non-HTTP traffic:
acl foreignProtocol squid_error ERR_PROTOCOL_UNKNOWN ERR_TOO_BIG
# define what Squid errors indicate receiving nothing:
acl serverTalksFirstProtocol squid_error ERR_REQUEST_START_TIMEOUT
# tunnel everything that does not look like HTTP:
on_unsupported_protocol tunnel foreignProtocol
# tunnel if we think the client waits for the server to talk first:
on_unsupported_protocol tunnel serverTalksFirstProtocol
# in all other error cases, just send an HTTP "error page" response:
on_unsupported_protocol respond all
See also: squid_error ACL
DOC_END
+NAME: auth_schemes
+TYPE: AuthSchemes
+IFDEF: USE_AUTH
+LOC: Auth::TheConfig.schemeAccess
+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
NETWORK OPTIONS
-----------------------------------------------------------------------------
COMMENT_END
NAME: http_port ascii_port
TYPE: PortCfg
DEFAULT: none
LOC: HttpPortList
DOC_START
Usage: port [mode] [options]
hostname:port [mode] [options]
1.2.3.4:port [mode] [options]
The socket addresses where Squid will listen for HTTP client
requests. You may specify multiple socket addresses.
There are three forms: port alone, hostname with port, and
IP address with port. If you specify a hostname or IP
address, Squid binds the socket to that specific
address. Most likely, you do not need to bind to a specific
=== modified file 'src/main.cc'
--- src/main.cc 2016-10-03 04:33:08 +0000
+++ src/main.cc 2016-12-19 13:36:49 +0000
@@ -1,34 +1,36 @@
/*
* 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.
*/
/* DEBUG: section 01 Startup and Main Loop */
#include "squid.h"
#include "AccessLogEntry.h"
#include "acl/Acl.h"
#include "acl/Asn.h"
+#include "auth/Config.h"
+#include "auth/Gadgets.h"
#include "AuthReg.h"
#include "base/RunnersRegistry.h"
#include "base/Subscription.h"
#include "base/TextException.h"
#include "cache_cf.h"
#include "CachePeer.h"
#include "carp.h"
#include "client_db.h"
#include "client_side.h"
#include "comm.h"
#include "ConfigParser.h"
#include "CpuAffinity.h"
#include "DiskIO/DiskIOModule.h"
#include "dns/forward.h"
#include "errorpage.h"
#include "event.h"
#include "EventLoop.h"
#include "ExternalACL.h"
#include "fd.h"
#include "format/Token.h"
@@ -70,43 +72,40 @@
#include "store/Disks.h"
#include "store_log.h"
#include "StoreFileSystem.h"
#include "tools.h"
#include "unlinkd.h"
#include "URL.h"
#include "wccp.h"
#include "wccp2.h"
#include "WinSvc.h"
#if USE_ADAPTATION
#include "adaptation/Config.h"
#endif
#if USE_ECAP
#include "adaptation/ecap/Config.h"
#endif
#if ICAP_CLIENT
#include "adaptation/icap/Config.h"
#include "adaptation/icap/icap_log.h"
#endif
-#if USE_AUTH
-#include "auth/Gadgets.h"
-#endif
#if USE_DELAY_POOLS
#include "ClientDelayConfig.h"
#endif
#if USE_DELAY_POOLS
#include "DelayPools.h"
#endif
#if USE_LOADABLE_MODULES
#include "LoadableModules.h"
#endif
#if USE_OPENSSL
#include "ssl/context_storage.h"
#include "ssl/helper.h"
#endif
#if ICAP_CLIENT
#include "adaptation/icap/Config.h"
#endif
#if USE_ECAP
#include "adaptation/ecap/Config.h"
#endif
#if USE_ADAPTATION
@@ -947,41 +946,41 @@
enableAdaptation = Adaptation::Ecap::TheConfig.onoff || enableAdaptation;
#endif
Adaptation::Config::Finalize(enableAdaptation);
#endif
#if ICAP_CLIENT
icapLogOpen();
#endif
storeLogOpen();
Dns::Init();
#if USE_SSL_CRTD
Ssl::Helper::GetInstance()->Init();
#endif
#if USE_OPENSSL
if (Ssl::CertValidationHelper::GetInstance())
Ssl::CertValidationHelper::GetInstance()->Init();
#endif
redirectInit();
#if USE_AUTH
- authenticateInit(&Auth::TheConfig);
+ authenticateInit(&Auth::TheConfig.schemes);
#endif
externalAclInit();
if (IamPrimaryProcess()) {
#if USE_WCCP
wccpInit();
#endif
#if USE_WCCPv2
wccp2Init();
#endif
}
serverConnectionsOpen();
neighbors_init();
storeDirOpenSwapLogs();
@@ -1014,41 +1013,41 @@
if (AvoidSignalAction("log rotation", do_rotate))
return;
icmpEngine.Close();
redirectShutdown();
#if USE_AUTH
authenticateRotate();
#endif
externalAclShutdown();
_db_rotate_log(); /* cache.log */
storeDirWriteCleanLogs(1);
storeLogRotate(); /* store.log */
accessLogRotate(); /* access.log */
#if ICAP_CLIENT
icapLogRotate(); /*icap.log*/
#endif
icmpEngine.Open();
redirectInit();
#if USE_AUTH
- authenticateInit(&Auth::TheConfig);
+ authenticateInit(&Auth::TheConfig.schemes);
#endif
externalAclInit();
}
static void
setEffectiveUser(void)
{
keepCapabilities();
leave_suid(); /* Run as non privilegied user */
#if _SQUID_OS2_
return;
#endif
if (geteuid() == 0) {
debugs(0, DBG_CRITICAL, "Squid is not safe to run as root! If you must");
debugs(0, DBG_CRITICAL, "start Squid as root, then you must configure");
debugs(0, DBG_CRITICAL, "it to run as a non-priveledged user with the");
debugs(0, DBG_CRITICAL, "'cache_effective_user' option in the config file.");
fatal("Don't run Squid as root, set 'cache_effective_user'!");
@@ -1158,41 +1157,41 @@
ipcache_init();
fqdncache_init();
parseEtcHosts();
Dns::Init();
#if USE_SSL_CRTD
Ssl::Helper::GetInstance()->Init();
#endif
#if USE_OPENSSL
if (Ssl::CertValidationHelper::GetInstance())
Ssl::CertValidationHelper::GetInstance()->Init();
#endif
redirectInit();
#if USE_AUTH
- authenticateInit(&Auth::TheConfig);
+ authenticateInit(&Auth::TheConfig.schemes);
#endif
externalAclInit();
httpHeaderInitModule(); /* must go before any header processing (e.g. the one in errorInitialize) */
errorInitialize();
accessLogInit();
#if ICAP_CLIENT
icapLogOpen();
#endif
#if USE_IDENT
Ident::Init();
#endif
#if SQUID_SNMP
snmpInit();
=== modified file 'src/tests/stub_libauth.cc'
--- src/tests/stub_libauth.cc 2016-12-10 04:48:25 +0000
+++ src/tests/stub_libauth.cc 2016-12-19 13:43:02 +0000
@@ -1,81 +1,84 @@
/*
* 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"
#define STUB_API "auth/libauth.la"
#include "STUB.h"
#if USE_AUTH
-#include "auth/Config.h"
-Auth::UserRequest::Pointer Auth::Config::CreateAuthUser(const char *, AccessLogEntry::Pointer &al) STUB_RETVAL(NULL)
-Auth::Config * Auth::Config::Find(const char *) STUB_RETVAL(NULL)
-void Auth::Config::registerWithCacheManager(void) STUB_NOP
-Auth::ConfigVector Auth::TheConfig;
+#include "auth/SchemeConfig.h"
+namespace Auth
+{
+Auth::UserRequest::Pointer SchemeConfig::CreateAuthUser(const char *, AccessLogEntry::Pointer &al) STUB_RETVAL(NULL)
+Auth::SchemeConfig * SchemeConfig::Find(const char *) STUB_RETVAL(NULL)
+void SchemeConfig::registerWithCacheManager(void) STUB_NOP
+Auth::ConfigVector TheConfig;
+}
#include "auth/Gadgets.h"
int authenticateActiveSchemeCount(void) STUB_RETVAL(0)
int authenticateSchemeCount(void) STUB_RETVAL(0)
void authenticateInit(Auth::ConfigVector *) STUB
void authenticateRotate(void) STUB
void authenticateReset(void) STUB
#include "auth/Scheme.h"
#include <vector>
std::vector<Auth::Scheme::Pointer> *Auth::Scheme::_Schemes = NULL;
void Auth::Scheme::AddScheme(Auth::Scheme::Pointer) STUB
Auth::Scheme::Pointer Auth::Scheme::Find(const char *) STUB_RETVAL(NULL)
std::vector<Auth::Scheme::Pointer> & Auth::Scheme::GetSchemes() STUB_RETVAL(*_Schemes);
void Auth::Scheme::FreeAll() STUB
+#include "auth/SchemesConfig.h"
+void Auth::SchemesConfig::expand() STUB
+
#include "auth/User.h"
-Auth::User::User(Auth::Config *, const char *) STUB
+Auth::User::User(Auth::SchemeConfig *, const char *) STUB
Auth::CredentialState Auth::User::credentials() const STUB_RETVAL(credentials_state)
void Auth::User::credentials(CredentialState) STUB
void Auth::User::absorb(Auth::User::Pointer) STUB
Auth::User::~User() STUB_NOP
void Auth::User::clearIp() STUB
void Auth::User::removeIp(Ip::Address) STUB
void Auth::User::addIp(Ip::Address) STUB
void Auth::User::CredentialsCacheStats(StoreEntry *) STUB
#include "auth/UserRequest.h"
char const * Auth::UserRequest::username() const STUB_RETVAL("stub_username")
void Auth::UserRequest::start(HttpRequest *, AccessLogEntry::Pointer &, AUTHCB *, void *) STUB
bool Auth::UserRequest::valid() const STUB_RETVAL(false)
void * Auth::UserRequest::operator new (size_t) STUB_RETVAL((void *)1)
void Auth::UserRequest::operator delete (void *) STUB
Auth::UserRequest::UserRequest() STUB
Auth::UserRequest::~UserRequest() STUB
void Auth::UserRequest::setDenyMessage(char const *) STUB
char const * Auth::UserRequest::getDenyMessage() STUB_RETVAL("stub")
char const * Auth::UserRequest::denyMessage(char const * const) STUB_RETVAL("stub")
void authenticateAuthUserRequestRemoveIp(Auth::UserRequest::Pointer, Ip::Address const &) STUB
void authenticateAuthUserRequestClearIp(Auth::UserRequest::Pointer) STUB
int authenticateAuthUserRequestIPCount(Auth::UserRequest::Pointer) STUB_RETVAL(0)
int authenticateUserAuthenticated(Auth::UserRequest::Pointer) STUB_RETVAL(0)
Auth::Direction Auth::UserRequest::direction() STUB_RETVAL(Auth::CRED_ERROR)
void Auth::UserRequest::addAuthenticationInfoHeader(HttpReply *, int) STUB
void Auth::UserRequest::addAuthenticationInfoTrailer(HttpReply *, int) STUB
void Auth::UserRequest::releaseAuthServer() STUB
const char * Auth::UserRequest::connLastHeader() STUB_RETVAL("stub")
AuthAclState Auth::UserRequest::authenticate(Auth::UserRequest::Pointer *, Http::HdrType, HttpRequest *, ConnStateData *, Ip::Address &, AccessLogEntry::Pointer &) STUB_RETVAL(AUTH_AUTHENTICATED)
AuthAclState Auth::UserRequest::tryToAuthenticateAndSetAuthUser(Auth::UserRequest::Pointer *, Http::HdrType, HttpRequest *, ConnStateData *, Ip::Address &, AccessLogEntry::Pointer &) STUB_RETVAL(AUTH_AUTHENTICATED)
void Auth::UserRequest::addReplyAuthHeader(HttpReply *, Auth::UserRequest::Pointer, HttpRequest *, int, int) STUB
void authenticateFixHeader(HttpReply *, Auth::UserRequest::Pointer, HttpRequest *, int, int) STUB
void authenticateAddTrailer(HttpReply *, Auth::UserRequest::Pointer, HttpRequest *, int) STUB
Auth::Scheme::Pointer Auth::UserRequest::scheme() const STUB_RETVAL(NULL)
#include "AuthReg.h"
void Auth::Init() STUB_NOP
-#include "auth/SchemesConfig.h"
-void Auth::SchemesConfig::expand() STUB
-
#endif /* USE_AUTH */
=== modified file 'src/tests/testAuth.cc'
--- src/tests/testAuth.cc 2016-01-01 00:12:18 +0000
+++ src/tests/testAuth.cc 2016-12-19 13:43:38 +0000
@@ -1,35 +1,34 @@
/*
* 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"
#if USE_AUTH
#include "auth/Config.h"
#include "auth/Gadgets.h"
-#include "auth/Scheme.h"
#include "auth/UserRequest.h"
#include "ConfigParser.h"
#include "testAuth.h"
#include "unitTestMain.h"
CPPUNIT_TEST_SUITE_REGISTRATION( testAuth );
CPPUNIT_TEST_SUITE_REGISTRATION( testAuthConfig );
CPPUNIT_TEST_SUITE_REGISTRATION( testAuthUserRequest );
#if HAVE_AUTH_MODULE_BASIC
CPPUNIT_TEST_SUITE_REGISTRATION( testAuthBasicUserRequest );
#endif
#if HAVE_AUTH_MODULE_DIGEST
CPPUNIT_TEST_SUITE_REGISTRATION( testAuthDigestUserRequest );
#endif
#if HAVE_AUTH_MODULE_NTLM
CPPUNIT_TEST_SUITE_REGISTRATION( testAuthNTLMUserRequest );
#endif
#if HAVE_AUTH_MODULE_NEGOTIATE
CPPUNIT_TEST_SUITE_REGISTRATION( testAuthNegotiateUserRequest );
#endif
More information about the squid-dev
mailing list