From abb929f03f54f744e6b67fdf84b41508a85aae36 Mon Sep 17 00:00:00 2001 From: hno <> Date: Sat, 28 Jun 2003 04:32:30 +0000 Subject: [PATCH] * ext_user acl type to match user name returned by external acl * cleanup of how external acls present a user name to the Squid core to make the code more logical and fix a minor security issues if there is downstream proxies. * concept of password returned by external acl type. Integrated with login= cache_peer option to have the password forwarded to peers (both proxies and origin type peers) --- src/ACLExtUser.cc | 133 +++++++++++++++++++++++++++++++++++++ src/ACLExtUser.h | 74 +++++++++++++++++++++ src/ExternalACLEntry.cc | 3 +- src/ExternalACLEntry.h | 4 +- src/HttpRequest.cc | 8 ++- src/Makefile.am | 4 +- src/access_log.cc | 5 +- src/client_side.cc | 4 +- src/client_side_request.cc | 4 +- src/external_acl.cc | 41 +++++++----- src/http.cc | 30 +++++++-- src/structs.h | 6 +- 12 files changed, 287 insertions(+), 29 deletions(-) create mode 100644 src/ACLExtUser.cc create mode 100644 src/ACLExtUser.h diff --git a/src/ACLExtUser.cc b/src/ACLExtUser.cc new file mode 100644 index 0000000000..9def4ed31c --- /dev/null +++ b/src/ACLExtUser.cc @@ -0,0 +1,133 @@ +/* + * $Id: ACLExtUser.cc,v 1.1 2003/06/27 22:32:31 hno Exp $ + * + * DEBUG: section 28 Access Control + * AUTHOR: Duane Wessels + * + * SQUID Web Proxy Cache http://www.squid-cache.org/ + * ---------------------------------------------------------- + * + * Squid is the result of efforts by numerous individuals from + * the Internet community; see the CONTRIBUTORS file for full + * details. Many organizations have provided support for Squid's + * development; see the SPONSORS file for full details. Squid is + * Copyrighted (C) 2001 by the Regents of the University of + * California; see the COPYRIGHT file for full details. Squid + * incorporates software developed and/or copyrighted by other + * sources; see the CREDITS file for full details. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA. + * + * + * Copyright (c) 2003, Robert Collins + */ + +#include "squid.h" +#include "ACLExtUser.h" +#include "authenticate.h" +#include "ACLChecklist.h" +#include "ACLRegexData.h" +#include "ACLUserData.h" +#include "client_side.h" + +MemPool *ACLExtUser::Pool(NULL); +void * +ACLExtUser::operator new (size_t byteCount) +{ + /* derived classes with different sizes must implement their own new */ + assert (byteCount == sizeof (ACLExtUser)); + + if (!Pool) + Pool = memPoolCreate("ACLExtUser", sizeof (ACLExtUser)); + + return memPoolAlloc(Pool); +} + +void +ACLExtUser::operator delete (void *address) +{ + memPoolFree (Pool, address); +} + +void +ACLExtUser::deleteSelf() const +{ + delete this; +} + +ACLExtUser::~ACLExtUser() +{ + data->deleteSelf(); +} + +ACLExtUser::ACLExtUser(ACLData *newData, char const *newType) : data (newData), type_ (newType) {} + +ACLExtUser::ACLExtUser (ACLExtUser const &old) : data (old.data->clone()), type_ (old.type_) +{} + +ACLExtUser & +ACLExtUser::operator= (ACLExtUser const &rhs) +{ + data = rhs.data->clone(); + type_ = rhs.type_; + return *this; +} + +char const * +ACLExtUser::typeString() const +{ + return type_; +} + +void +ACLExtUser::parse() +{ + debug(28, 3) ("aclParseUserList: current is null. Creating\n"); + data = new ACLUserData; + data->parse(); +} + +int +ACLExtUser::match(ACLChecklist *checklist) +{ + if (checklist->request->extacl_user.size()) { + return data->match(checklist->request->extacl_user.buf()); + } else { + return -1; + } +} + +wordlist * +ACLExtUser::dump() const +{ + return data->dump(); +} + +bool +ACLExtUser::valid () const +{ + return data != NULL; +} + +ACL * +ACLExtUser::clone() const +{ + return new ACLExtUser(*this); +} + +ACL::Prototype ACLExtUser::UserRegistryProtoype(&ACLExtUser::UserRegistryEntry_, "ext_user"); +ACLExtUser ACLExtUser::UserRegistryEntry_(new ACLUserData, "ext_user"); +ACL::Prototype ACLExtUser::RegexRegistryProtoype(&ACLExtUser::RegexRegistryEntry_, "ext_user_regex" ); +ACLExtUser ACLExtUser::RegexRegistryEntry_(new ACLRegexData, "ext_user_regex"); diff --git a/src/ACLExtUser.h b/src/ACLExtUser.h new file mode 100644 index 0000000000..ba74c43c0e --- /dev/null +++ b/src/ACLExtUser.h @@ -0,0 +1,74 @@ + +/* + * $Id: ACLExtUser.h,v 1.1 2003/06/27 22:32:31 hno Exp $ + * + * + * SQUID Web Proxy Cache http://www.squid-cache.org/ + * ---------------------------------------------------------- + * + * Squid is the result of efforts by numerous individuals from + * the Internet community; see the CONTRIBUTORS file for full + * details. Many organizations have provided support for Squid's + * development; see the SPONSORS file for full details. Squid is + * Copyrighted (C) 2001 by the Regents of the University of + * California; see the COPYRIGHT file for full details. Squid + * incorporates software developed and/or copyrighted by other + * sources; see the CREDITS file for full details. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA. + * + * + * Copyright (c) 2003, Robert Collins + */ + +#ifndef SQUID_ACLIDENT_H +#define SQUID_ACLIDENT_H +#include "ACL.h" +#include "ACLChecklist.h" +#include "ACLData.h" + +class ACLExtUser : public ACL +{ + +public: + void *operator new(size_t); + void operator delete(void *); + virtual void deleteSelf() const; + + ACLExtUser(ACLData *newData, char const *); + ACLExtUser (ACLExtUser const &old); + ACLExtUser & operator= (ACLExtUser const &rhs); + ~ACLExtUser(); + + virtual char const *typeString() const; + virtual void parse(); + virtual bool isProxyAuth() const {return true;} + + virtual int match(ACLChecklist *checklist); + virtual wordlist *dump() const; + virtual bool valid () const; + virtual ACL *clone()const; + +private: + static MemPool *Pool; + static Prototype UserRegistryProtoype; + static ACLExtUser UserRegistryEntry_; + static Prototype RegexRegistryProtoype; + static ACLExtUser RegexRegistryEntry_; + ACLData *data; + char const *type_; +}; + +#endif /* SQUID_ACLIDENT_H */ diff --git a/src/ExternalACLEntry.cc b/src/ExternalACLEntry.cc index bcf9494997..aabece6620 100644 --- a/src/ExternalACLEntry.cc +++ b/src/ExternalACLEntry.cc @@ -1,6 +1,6 @@ /* - * $Id: ExternalACLEntry.cc,v 1.2 2003/06/27 20:54:45 hno Exp $ + * $Id: ExternalACLEntry.cc,v 1.3 2003/06/27 22:32:31 hno Exp $ * * DEBUG: section 82 External ACL * AUTHOR: Henrik Nordstrom, MARA Systems AB @@ -91,6 +91,7 @@ ExternalACLEntry::update(ExternalACLEntryData const &someData) result = someData.result; user = someData.user; + password = someData.password; message = someData.message; tag = someData.tag; } diff --git a/src/ExternalACLEntry.h b/src/ExternalACLEntry.h index b7ab27a1ca..64d7c13f6b 100644 --- a/src/ExternalACLEntry.h +++ b/src/ExternalACLEntry.h @@ -1,6 +1,6 @@ /* - * $Id: ExternalACLEntry.h,v 1.2 2003/06/27 20:54:45 hno Exp $ + * $Id: ExternalACLEntry.h,v 1.3 2003/06/27 22:32:31 hno Exp $ * * DEBUG: section 82 External ACL * AUTHOR: Henrik Nordstrom, MARA Systems AB @@ -59,6 +59,7 @@ public: int result; String user; + String password; String message; String tag; }; @@ -85,6 +86,7 @@ public: int result; time_t date; String user; + String password; String message; String tag; external_acl *def; diff --git a/src/HttpRequest.cc b/src/HttpRequest.cc index f989a6b8cd..c1f47eaf6b 100644 --- a/src/HttpRequest.cc +++ b/src/HttpRequest.cc @@ -1,6 +1,6 @@ /* - * $Id: HttpRequest.cc,v 1.36 2003/03/06 06:21:37 robertc Exp $ + * $Id: HttpRequest.cc,v 1.37 2003/06/27 22:32:31 hno Exp $ * * DEBUG: section 73 HTTP Request * AUTHOR: Duane Wessels @@ -90,6 +90,12 @@ requestDestroy(request_t * req) if (req->range) req->range->deleteSelf(); + req->tag.clean(); + + req->extacl_user.clean(); + + req->extacl_passwd.clean(); + memFree(req, MEM_REQUEST_T); } diff --git a/src/Makefile.am b/src/Makefile.am index 5ab9603ded..4ce1975eae 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -1,7 +1,7 @@ # # Makefile for the Squid Object Cache server # -# $Id: Makefile.am,v 1.79 2003/06/20 01:00:57 robertc Exp $ +# $Id: Makefile.am,v 1.80 2003/06/27 22:32:30 hno Exp $ # # Uncomment and customize the following to suit your needs: # @@ -209,6 +209,8 @@ squid_ACLSOURCES = \ ACLDestinationIP.h \ ACLDomainData.h \ ACLDomainData.cc \ + ACLExtUser.h \ + ACLExtUser.cc \ ACLIntRange.cc \ ACLIntRange.h \ ACLIP.cc \ diff --git a/src/access_log.cc b/src/access_log.cc index 72fbd21c28..2ed8b9e6d8 100644 --- a/src/access_log.cc +++ b/src/access_log.cc @@ -1,6 +1,6 @@ /* - * $Id: access_log.cc,v 1.82 2003/06/09 21:52:21 wessels Exp $ + * $Id: access_log.cc,v 1.83 2003/06/27 22:32:30 hno Exp $ * * DEBUG: section 46 Access Log * AUTHOR: Duane Wessels @@ -263,6 +263,9 @@ accessLogSquid(AccessLogEntry * al) user = accessLogFormatName(al->cache.authuser); + if (!user) + user = accessLogFormatName(al->cache.extuser); + #if USE_SSL if (!user) diff --git a/src/client_side.cc b/src/client_side.cc index d19830d33e..889d33874e 100644 --- a/src/client_side.cc +++ b/src/client_side.cc @@ -1,6 +1,6 @@ /* - * $Id: client_side.cc,v 1.643 2003/06/23 14:13:03 robertc Exp $ + * $Id: client_side.cc,v 1.644 2003/06/27 22:32:30 hno Exp $ * * DEBUG: section 33 Client-side Routines * AUTHOR: Duane Wessels @@ -477,6 +477,8 @@ clientPrepareLogWithRequestDetails(request_t * request, AccessLogEntry * aLogEnt aLogEntry->headers.request = xstrdup(mb.buf); aLogEntry->hier = request->hier; + aLogEntry->cache.extuser = request->extacl_user.buf(); + if (request->auth_user_request) { if (authenticateUserRequestUsername(request->auth_user_request)) aLogEntry->cache.authuser = diff --git a/src/client_side_request.cc b/src/client_side_request.cc index 97cec62b4e..b487d3b5f9 100644 --- a/src/client_side_request.cc +++ b/src/client_side_request.cc @@ -1,6 +1,6 @@ /* - * $Id: client_side_request.cc,v 1.23 2003/06/20 01:01:00 robertc Exp $ + * $Id: client_side_request.cc,v 1.24 2003/06/27 22:32:31 hno Exp $ * * DEBUG: section 85 Client-side Request Routines * AUTHOR: Robert Collins (Originally Duane Wessels in client_side.c) @@ -773,6 +773,8 @@ clientRedirectDone(void *data, char *result) } new_request->content_length = old_request->content_length; + new_request->extacl_user = old_request->extacl_user; + new_request->extacl_passwd = old_request->extacl_passwd; new_request->flags.proxy_keepalive = old_request->flags.proxy_keepalive; requestUnlink(old_request); http->request = requestLink(new_request); diff --git a/src/external_acl.cc b/src/external_acl.cc index cba6d61295..33c6c4771a 100644 --- a/src/external_acl.cc +++ b/src/external_acl.cc @@ -1,6 +1,6 @@ /* - * $Id: external_acl.cc,v 1.45 2003/06/27 20:54:45 hno Exp $ + * $Id: external_acl.cc,v 1.46 2003/06/27 22:32:31 hno Exp $ * * DEBUG: section 82 External ACL * AUTHOR: Henrik Nordstrom, MARA Systems AB @@ -134,6 +134,7 @@ struct _external_acl_format EXT_ACL_USER_CERT, EXT_ACL_CA_CERT, #endif + EXT_ACL_EXT_USER, EXT_ACL_END } type; external_acl_format *next; @@ -316,6 +317,8 @@ parse_externalAclHelper(external_acl ** list) } #endif + else if (strcmp(token, "%EXT_USER") == 0) + format->type = _external_acl_format::EXT_ACL_EXT_USER; else { self_destruct(); } @@ -408,6 +411,8 @@ dump_externalAclHelper(StoreEntry * sentry, const char *name, const external_acl break; #endif + DUMP_EXT_ACL_TYPE(EXT_USER); + case _external_acl_format::EXT_ACL_UNKNOWN: case _external_acl_format::EXT_ACL_END: @@ -585,20 +590,17 @@ aclMatchExternal(external_acl_data *acl, ACLChecklist * ch) external_acl_cache_touch(acl->def, entry); result = entry->result; debug(82, 2) ("aclMatchExternal: %s = %d\n", acl->def->name, result); - /* FIXME: This should allocate it's own storage in the request. This - * piggy backs on ident, and may fail if there is child proxies.. - * Register the username for logging purposes - */ - if (entry->user.size()) { - xstrncpy(ch->rfc931, entry->user.buf(), USER_IDENT_SZ); + if (ch->request) { + if (entry->user.size()) + ch->request->extacl_user = entry->user; - if (cbdataReferenceValid(ch->conn())) - xstrncpy(ch->conn()->rfc931, entry->user.buf(), USER_IDENT_SZ); - } + if (entry->password.size()) + ch->request->extacl_passwd = entry->password; - if (ch->request && !ch->request->tag.size()) - ch->request->tag = entry->tag; + if (!ch->request->tag.size()) + ch->request->tag = entry->tag; + } return result; } @@ -741,6 +743,10 @@ makeExternalAclKey(ACLChecklist * ch, external_acl_data * acl_data) break; #endif + case _external_acl_format::EXT_ACL_EXT_USER: + str = request->extacl_user.buf(); + break; + case _external_acl_format::EXT_ACL_UNKNOWN: case _external_acl_format::EXT_ACL_END: @@ -896,15 +902,20 @@ externalAclHandleReply(void *data, char *reply) if (value) { *value++ = '\0'; /* terminate the token, and move up to the value */ - if (strcmp(token, "tag") == 0) - entryData.tag = value; - if (strcmp(token, "user") == 0) entryData.user = value; else if (strcmp(token, "message") == 0) entryData.message = value; else if (strcmp(token, "error") == 0) entryData.message = value; + else if (strcmp(token, "tag") == 0) + entryData.tag = value; + else if (strcmp(token, "password") == 0) + entryData.password = value; + else if (strcmp(token, "passwd") == 0) + entryData.password = value; + else if (strcmp(token, "login") == 0) + entryData.user = value; } } } diff --git a/src/http.cc b/src/http.cc index caad3027f6..037129f9bf 100644 --- a/src/http.cc +++ b/src/http.cc @@ -1,6 +1,6 @@ /* - * $Id: http.cc,v 1.416 2003/06/24 12:42:25 robertc Exp $ + * $Id: http.cc,v 1.417 2003/06/27 22:32:31 hno Exp $ * * DEBUG: section 11 Hypertext Transfer Protocol (HTTP) * AUTHOR: Harvest Derived @@ -206,6 +206,7 @@ httpMaybeRemovePublic(StoreEntry * e, http_status status) /* * Any 2xx response should eject previously cached entities... */ + if (status >= 200 && status < 300) remove = 1; @@ -1217,13 +1218,20 @@ httpBuildRequestHeader(request_t * request, if (orig_request->auth_user_request) username = orig_request->auth_user_request->username(); + else if (orig_request->extacl_user.size()) + username = orig_request->extacl_user.buf(); snprintf(loginbuf, sizeof(loginbuf), "%s%s", username, orig_request->peer_login + 1); httpHeaderPutStrf(hdr_out, HDR_PROXY_AUTHORIZATION, "Basic %s", base64_encode(loginbuf)); } else if (strcmp(orig_request->peer_login, "PASS") == 0) { - /* Nothing to do */ + if (orig_request->extacl_user.size() && orig_request->extacl_passwd.size()) { + char loginbuf[256]; + snprintf(loginbuf, sizeof(loginbuf), "%s:%s", orig_request->extacl_user.buf(), orig_request->extacl_passwd.buf()); + httpHeaderPutStrf(hdr_out, HDR_PROXY_AUTHORIZATION, "Basic %s", + base64_encode(loginbuf)); + } } else if (strcmp(orig_request->peer_login, "PROXYPASS") == 0) { /* Nothing to do */ } else { @@ -1239,11 +1247,17 @@ httpBuildRequestHeader(request_t * request, /* No credentials to forward.. (should have been done above if available) */ } else if (strcmp(orig_request->peer_login, "PROXYPASS") == 0) { /* Special mode, convert proxy authentication to WWW authentication + * (also applies to authentication provided by external acl) */ const char *auth = httpHeaderGetStr(hdr_in, HDR_PROXY_AUTHORIZATION); if (auth && strncasecmp(auth, "basic ", 6) == 0) { httpHeaderPutStr(hdr_out, HDR_AUTHORIZATION, auth); + } else if (orig_request->extacl_user.size() && orig_request->extacl_passwd.size()) { + char loginbuf[256]; + snprintf(loginbuf, sizeof(loginbuf), "%s:%s", orig_request->extacl_user.buf(), orig_request->extacl_passwd.buf()); + httpHeaderPutStrf(hdr_out, HDR_AUTHORIZATION, "Basic %s", + base64_encode(loginbuf)); } } else if (*orig_request->peer_login == '*') { /* Special mode, to pass the username to the upstream cache */ @@ -1252,6 +1266,8 @@ httpBuildRequestHeader(request_t * request, if (orig_request->auth_user_request) username = authenticateUserRequestUsername(orig_request->auth_user_request); + else if (orig_request->extacl_user.size()) + username = orig_request->extacl_user.buf(); snprintf(loginbuf, sizeof(loginbuf), "%s%s", username, orig_request->peer_login + 1); @@ -1264,8 +1280,7 @@ httpBuildRequestHeader(request_t * request, } } - /* append Cache-Control, add max-age if not there already */ - { + /* append Cache-Control, add max-age if not there already */ { HttpHdrCc *cc = httpHeaderGetCc(hdr_in); if (!cc) @@ -1329,7 +1344,8 @@ copyOneHeaderFromClientsideRequestToUpstreamRequest(const HttpHeaderEntry *e, St */ if (flags.proxying && orig_request->peer_login && - strcmp(orig_request->peer_login, "PASS") == 0) { + (strcmp(orig_request->peer_login, "PASS") == 0 || + strcmp(orig_request->peer_login, "PROXYPASS") == 0)) { httpHeaderAddEntry(hdr_out, httpHeaderEntryClone(e)); } @@ -1345,7 +1361,9 @@ copyOneHeaderFromClientsideRequestToUpstreamRequest(const HttpHeaderEntry *e, St * (see also below for proxy->server authentication) */ - if (orig_request->peer_login && (strcmp(orig_request->peer_login, "PASS") == 0 || strcmp(orig_request->peer_login, "PROXYPASS") == 0)) { + if (orig_request->peer_login && + (strcmp(orig_request->peer_login, "PASS") == 0 || + strcmp(orig_request->peer_login, "PROXYPASS") == 0)) { httpHeaderAddEntry(hdr_out, httpHeaderEntryClone(e)); } } diff --git a/src/structs.h b/src/structs.h index aace2a32c3..0678e21ba1 100644 --- a/src/structs.h +++ b/src/structs.h @@ -1,6 +1,6 @@ /* - * $Id: structs.h,v 1.465 2003/05/29 15:54:08 hno Exp $ + * $Id: structs.h,v 1.466 2003/06/27 22:32:31 hno Exp $ * * * SQUID Web Proxy Cache http://www.squid-cache.org/ @@ -1071,6 +1071,8 @@ struct _AccessLogEntry const char *ssluser; #endif + const char *extuser; + } cache; @@ -1703,6 +1705,8 @@ public: const char *vary_headers; /* Used when varying entities are detected. Changes how the store key is calculated */ char *peer_domain; /* Configured peer forceddomain */ String tag; /* Internal tag for this request */ + String extacl_user; /* User name returned by extacl lookup */ + String extacl_passwd; /* Password returned by extacl lookup */ }; #endif -- 2.39.5