I am sending a new patch.
However I believe my first patch is safer for squid-3.2 ...
On 08/10/2012 02:40 PM, Amos Jeffries wrote:
> On 10/08/2012 7:36 p.m., Tsantilas Christos wrote:
>> On 08/10/2012 06:02 AM, Amos Jeffries wrote:
>>> On 10/08/2012 6:54 a.m., Tsantilas Christos wrote:
>>>> Supply client connection and IDENT information to peer_cache_access ACL
>>>> check.
>>>>
>>>> Among other things, this enables SSL client certificate ACL checks
>>>> (user_cert and ca_cert) when making peering decisions
>>>>
>>> It would be better to do this inside the FilledChecklist constructor.
>>> That way all other access lists which pass in HttpRequest can make use
>>> of the details and we can remove duplicate code setting conn()
>>> elsewhere.
>>>
>>> I expect there will be complications from duplicate code with the
>>> assert() that conn_ is only set once. Or places needlessly sending in
>> Exactly.
>> I do not know if it is the right think, unless we make
>> ACLFilledCheckList::conn(ConnStateData *) private, or allow overwriting
>> ACLFilledCheckList::conn_
>> However if found only one case where the
>> ACLFilledCheckList::conn(ConnStateData *) is used, it is inside
>> client_side.cc
>
> Okay. It looks like the clientAclChecklistCreate() is largely useless
> once the conn and ident is pulled out of HttpRequest fields.
Well it sets the ident with a dash not an empty string. Is it possible
to have a valid "-" ident?
>
> If in doubt FilledChecklist::conn(X) can be made to return before the
> assert if the conn_ pointer is being set to its existing value.
ok.
>
>>> ident detail pulled explicitly from the HttpRequest by the caller.
>>> Cleaning those out and using the below would be a good improvement.
>> Well with a second view, setting the ACLFilledCheckList::rfc931 is not
>> required. The ACLIdent will check the
>> ACLFilledCheckList::conn_::clientConnection::rfc931 if the
>> ACLFilledCheckList::conn_ is set and ACLFilledCheckList::rfc931 is not
>> set.
>> I think it is enough and it is better because it allow passing custom
>> ident if needed.
>
> Okay. Excellent.
>
>> I believe the parameters we are passing to checklist need to be
>> reviewed.
>
> Yes they do. Do you have time for it?
Nop.
>
>> As an example look inside src/neighbors.cc near the code I am
>> changing in the patch I sent:
>> ACLFilledChecklist checklist(p->access, request, NULL);
>> checklist.src_addr = request->client_addr;
>> checklist.my_addr = request->my_addr;
>>
>> The checklist.src_addr and checklist.my_addr had already set inside
>> ACLFilledChecklist constructor. Also overwriting the
>> ACLFilledChecklist::src_addr member we are breaking the
>> use_indirect_client_addr feature. Is it normal? Are there cases where
>> this feature must not be used?
>
> Only one case. Inside follow_x_forwarded_for - and I believe that has
> been carefully audited already.
>
> All other places double-setting the src_addr and my_addr can be removed.
> This would actually explain some weird peer selection errors spotted
> recently.
I let it as is now. But I can remove them with a separate patch for
squid trunk if required.
>
>
>>>
>>> === modified file 'src/acl/FilledChecklist.cc'
>>> --- src/acl/FilledChecklist.cc 2012-06-28 18:26:44 +0000
>>> +++ src/acl/FilledChecklist.cc 2012-08-10 01:43:58 +0000
>>> @@ -184,11 +184,19 @@
>>> #endif /* FOLLOW_X_FORWARDED_FOR */
>>> src_addr = request->client_addr;
>>> my_addr = request->my_addr;
>>> +
>>> + if (request->clientConnectionManager.valid())
>>> + conn(request->clientConnectionManager.get());
>>> }
>>>
>>> #if USE_IDENT
>>> if (ident)
>>> xstrncpy(rfc931, ident, USER_IDENT_SZ);
>>> + else if (conn() != NULL) {
>>> + // client connection data may have been provided via
>>> HttpRequest
>>> + if (conn_->clientConnection != NULL &&
>>> conn_->clientConnection->rfc931[0])
>>> + xstrncpy(rfc931, conn_->clientConnection->rfc931,
>>> USER_IDENT_SZ);
>>> + }
>>> #endif
>>> }
>>>
>>>
>>>
>>> Amos
>>>
>
>
=== modified file 'src/acl/FilledChecklist.cc'
--- src/acl/FilledChecklist.cc 2012-06-28 18:26:44 +0000
+++ src/acl/FilledChecklist.cc 2012-08-11 09:50:27 +0000
@@ -72,40 +72,42 @@
cbdataReferenceDone(conn_);
#if USE_SSL
cbdataReferenceDone(sslErrors);
#endif
debugs(28, 4, HERE << "ACLFilledChecklist destroyed " << this);
}
ConnStateData *
ACLFilledChecklist::conn() const
{
return conn_;
}
void
ACLFilledChecklist::conn(ConnStateData *aConn)
{
+ if (conn() == aConn)
+ return;
assert (conn() == NULL);
conn_ = cbdataReference(aConn);
}
int
ACLFilledChecklist::fd() const
{
return (conn_ != NULL && conn_->clientConnection != NULL) ? conn_->clientConnection->fd : fd_;
}
void
ACLFilledChecklist::fd(int aDescriptor)
{
assert(!conn() || conn()->clientConnection == NULL || conn()->clientConnection->fd == aDescriptor);
fd_ = aDescriptor;
}
bool
ACLFilledChecklist::destinationDomainChecked() const
{
@@ -167,28 +169,31 @@
sourceDomainChecked_(false)
{
my_addr.SetEmpty();
src_addr.SetEmpty();
dst_addr.SetEmpty();
rfc931[0] = '\0';
// cbdataReferenceDone() is in either fastCheck() or the destructor
if (A)
accessList = cbdataReference(A);
if (http_request != NULL) {
request = HTTPMSGLOCK(http_request);
#if FOLLOW_X_FORWARDED_FOR
if (Config.onoff.acl_uses_indirect_client)
src_addr = request->indirect_client_addr;
else
#endif /* FOLLOW_X_FORWARDED_FOR */
src_addr = request->client_addr;
my_addr = request->my_addr;
+
+ if (request->clientConnectionManager.valid())
+ conn(request->clientConnectionManager.get());
}
#if USE_IDENT
if (ident)
xstrncpy(rfc931, ident, USER_IDENT_SZ);
#endif
}
=== modified file 'src/client_side.cc'
--- src/client_side.cc 2012-08-06 17:21:57 +0000
+++ src/client_side.cc 2012-08-12 08:06:44 +0000
@@ -3705,41 +3705,40 @@
if (!sslServerBump) {
assert(port->signingCert.get());
certProperties.signWithX509.resetAndLock(port->signingCert.get());
if (port->signPkey.get())
certProperties.signWithPkey.resetAndLock(port->signPkey.get());
certProperties.signAlgorithm = Ssl::algSignTrusted;
return;
}
// In case of an error while connecting to the secure server, use a fake
// trusted certificate, with no mimicked fields and no adaptation
// algorithms. There is nothing we can mimic so we want to minimize the
// number of warnings the user will have to see to get to the error page.
assert(sslServerBump->entry);
if (sslServerBump->entry->isEmpty()) {
if (X509 *mimicCert = sslServerBump->serverCert.get())
certProperties.mimicCert.resetAndLock(mimicCert);
ACLFilledChecklist checklist(NULL, sslServerBump->request,
clientConnection != NULL ? clientConnection->rfc931 : dash_str);
- checklist.conn(this);
checklist.sslErrors = cbdataReference(sslServerBump->sslErrors);
for (sslproxy_cert_adapt *ca = Config.ssl_client.cert_adapt; ca != NULL; ca = ca->next) {
// If the algorithm already set, then ignore it.
if ((ca->alg == Ssl::algSetCommonName && certProperties.setCommonName) ||
(ca->alg == Ssl::algSetValidAfter && certProperties.setValidAfter) ||
(ca->alg == Ssl::algSetValidBefore && certProperties.setValidBefore) )
continue;
if (ca->aclList && checklist.fastCheck(ca->aclList) == ACCESS_ALLOWED) {
const char *alg = Ssl::CertAdaptAlgorithmStr[ca->alg];
const char *param = ca->param;
// For parameterless CN adaptation, use hostname from the
// CONNECT request.
if (ca->alg == Ssl::algSetCommonName) {
if (!param)
param = sslConnectHostOrIp.termedBuf();
certProperties.commonName = param;
certProperties.setCommonName = true;
@@ -4211,50 +4210,40 @@
*/
debugs(33, DBG_IMPORTANT, "varyEvaluateMatch: Oops. Not a Vary match on second attempt, '" <<
entry->mem_obj->url << "' '" << vary << "'");
return VARY_CANCEL;
}
}
}
ACLFilledChecklist *
clientAclChecklistCreate(const acl_access * acl, ClientHttpRequest * http)
{
ConnStateData * conn = http->getConn();
ACLFilledChecklist *ch = new ACLFilledChecklist(acl, http->request,
cbdataReferenceValid(conn) && conn != NULL && conn->clientConnection != NULL ? conn->clientConnection->rfc931 : dash_str);
/*
* hack for ident ACL. It needs to get full addresses, and a place to store
* the ident result on persistent connections...
*/
/* connection oriented auth also needs these two lines for it's operation. */
- /*
- * Internal requests do not have a connection reference, because: A) their
- * byte count may be transformed before being applied to an outbound
- * connection B) they are internal - any limiting on them should be done on
- * the server end.
- */
-
- if (conn != NULL)
- ch->conn(conn); /* unreferenced in FilledCheckList.cc */
-
return ch;
}
CBDATA_CLASS_INIT(ConnStateData);
ConnStateData::ConnStateData() :
AsyncJob("ConnStateData"),
#if USE_SSL
sslBumpMode(Ssl::bumpEnd),
switchedToHttps_(false),
sslServerBump(NULL),
#endif
stoppedSending_(NULL),
stoppedReceiving_(NULL)
{
pinning.pinned = false;
pinning.auth = false;
}
bool
=== modified file 'src/neighbors.cc'
--- src/neighbors.cc 2012-08-06 17:41:08 +0000
+++ src/neighbors.cc 2012-08-11 09:51:35 +0000
@@ -177,51 +177,40 @@
bool do_ping = false;
for (d = p->peer_domain; d; d = d->next) {
if (0 == matchDomainName(request->GetHost(), d->domain)) {
do_ping = d->do_ping;
break;
}
do_ping = !d->do_ping;
}
if (p->peer_domain && !do_ping)
return false;
if (p->access == NULL)
return do_ping;
ACLFilledChecklist checklist(p->access, request, NULL);
checklist.src_addr = request->client_addr;
checklist.my_addr = request->my_addr;
-#if 0 && USE_IDENT
- /*
- * this is currently broken because 'request->user_ident' has been
- * moved to conn->rfc931 and we don't have access to the parent
- * ConnStateData here.
- */
- if (request->user_ident[0])
- xstrncpy(checklist.rfc931, request->user_ident, USER_IDENT_SZ);
-
-#endif
-
return (checklist.fastCheck() == ACCESS_ALLOWED);
}
/* Return TRUE if it is okay to send an ICP request to this peer. */
static int
peerWouldBePinged(const peer * p, HttpRequest * request)
{
if (p->icp.port == 0)
return 0;
if (p->options.no_query)
return 0;
if (p->options.mcast_responder)
return 0;
if (p->n_addresses == 0)
return 0;
if (p->options.background_ping && (squid_curtime - p->stats.last_query < Config.backgroundPingRate))