From 50b5c98347c07ffd55faf6a3abb09479e491db1c Mon Sep 17 00:00:00 2001 From: Amos Jeffries Date: Mon, 20 Jul 2015 11:09:23 -0700 Subject: [PATCH] Support %un (any available user name) format code for external ACLs. The same %un code, with the same meaning is already supported in access.log. In an external ACL request, it expands to the first available user name from the following list of information sources: - authenticated user name, like %ul or %LOGIN - user name supplied by an external ACL to Squid via the "user=..." key=value pair, like %ue or %EXT_USER - SSL client name, like %us - ident user name, like %ui Based on Amos Jeffries 2011 patch and "arronax28" design: http://www.squid-cache.org/mail-archive/squid-dev/201112/0080.html with TODO completion by Measurement Factory --- src/cf.data.pre | 12 ++++++++++++ src/external_acl.cc | 41 ++++++++++++++++++++++++++++++++++++----- 2 files changed, 48 insertions(+), 5 deletions(-) diff --git a/src/cf.data.pre b/src/cf.data.pre index ecb9b735aa..12fb8ebb53 100644 --- a/src/cf.data.pre +++ b/src/cf.data.pre @@ -764,6 +764,12 @@ DOC_START FORMAT specifications %LOGIN Authenticated user login name + %un A user name. Expands to the first available name + from the following list of information sources: + - authenticated user name, like %ul or %LOGIN + - user name sent by an external ACL, like %EXT_USER + - SSL client name, like %us in logformat + - ident user name, like %ui in logformat %EXT_USER Username from previous external acl %EXT_LOG Log details from previous external acl %EXT_TAG Tag from previous external acl @@ -4149,6 +4155,12 @@ DOC_START ue User name from external acl helper ui User name from ident us User name from SSL + un A user name. Expands to the first available name + from the following list of information sources: + - authenticated user name, like %ul + - user name supplied by an external ACL, like %ue + - SSL client name, like %us + - ident user name, like %ui credentials Client credentials. The exact meaning depends on the authentication scheme: For Basic authentication, it is the password; for Digest, the realm sent by the diff --git a/src/external_acl.cc b/src/external_acl.cc index fe480cf88c..3d418cc669 100644 --- a/src/external_acl.cc +++ b/src/external_acl.cc @@ -418,6 +418,10 @@ parse_externalAclHelper(external_acl ** list) #if USE_AUTH else if (strcmp(token, "%EXT_USER") == 0 || strcmp(token, "%ue") == 0) format->type = Format::LFT_USER_EXTERNAL; +#endif +#if USE_AUTH || defined(USE_OPENSSL) || defined(USE_IDENT) + else if (strcmp(token, "%un") == 0) + format->type = Format::LFT_USER_NAME; #endif else if (strcmp(token, "%EXT_LOG") == 0 || strcmp(token, "%ea") == 0) format->type = Format::LFT_EXT_LOG; @@ -524,6 +528,7 @@ dump_externalAclHelper(StoreEntry * sentry, const char *name, const external_acl break #if USE_AUTH DUMP_EXT_ACL_TYPE_FMT(USER_LOGIN," %%ul"); + DUMP_EXT_ACL_TYPE_FMT(USER_NAME," %%un"); #endif #if USE_IDENT @@ -887,6 +892,18 @@ external_acl_cache_touch(external_acl * def, const ExternalACLEntryPointer &entr dlinkAdd(e, &entry->lru, &def->lru_list); } +#if USE_OPENSSL +static const char * +external_acl_ssl_get_user_attribute(const ACLFilledChecklist &ch, const char *attr) +{ + if (ch.conn() != NULL && Comm::IsConnOpen(ch.conn()->clientConnection)) { + if (SSL *ssl = fd_table[ch.conn()->clientConnection->fd].ssl) + return sslGetUserAttribute(ssl, attr); + } + return NULL; +} +#endif + static char * makeExternalAclKey(ACLFilledChecklist * ch, external_acl_data * acl_data) { @@ -1050,11 +1067,7 @@ makeExternalAclKey(ACLFilledChecklist * ch, external_acl_data * acl_data) case Format::LFT_EXT_ACL_USER_CERT: - if (ch->conn() != NULL && Comm::IsConnOpen(ch->conn()->clientConnection)) { - if (auto ssl = fd_table[ch->conn()->clientConnection->fd].ssl) - str = sslGetUserAttribute(ssl, format->header); - } - + str = external_acl_ssl_get_user_attribute(*ch, format->header); break; case Format::LFT_EXT_ACL_USER_CA_CERT: @@ -1098,6 +1111,24 @@ makeExternalAclKey(ACLFilledChecklist * ch, external_acl_data * acl_data) str = request->extacl_user.termedBuf(); break; #endif + case Format::LFT_USER_NAME: + /* find the first available name from various sources */ +#if USE_AUTH + if (ch->auth_user_request != NULL) + str = ch->auth_user_request->username(); + if ((!str || !*str) && + (request->extacl_user.size() > 0 && request->extacl_user[0] != '-')) + str = request->extacl_user.termedBuf(); +#endif +#if USE_OPENSSL + if (!str || !*str) + str = external_acl_ssl_get_user_attribute(*ch, "CN"); +#endif +#if USE_IDENT + if (!str || !*str) + str = ch->rfc931; +#endif + break; case Format::LFT_EXT_LOG: str = request->extacl_log.termedBuf(); break; -- 2.47.3