------------------------------------------------------------ revno: 13210 revision-id: squid3@treenet.co.nz-20150118110213-zbcrupnx78b4y9mq parent: squid3@treenet.co.nz-20150118081150-g92c3d0w5sbsccj1 fixes bug: http://bugs.squid-cache.org/show_bug.cgi?id=3997 author: Amos Jeffries , Steve Hill committer: Amos Jeffries branch nick: 3.4 timestamp: Sun 2015-01-18 03:02:13 -0800 message: Bug 3997: Excessive NTLM or Negotiate auth helper annotations With the transaction annotations feature added in Squid-3.4 auth helper response values get recorded as annotatiions. In the case of NTLM and Negotiate authentication the helper response contains a large credentials token which changes frequently. Also, user credentials state is cached. In the case of NTLM and Negotiate the active credentials are cached in the TCP connection state data, but also for the cache mgr helper reports make use of caching in a global username cache. When these two features are combined, the global username cache for mgr reporting accumulates all TCP connection specific token= values presented by the client on all its connections, and any changes to the token over its lifetime. The result is that for users performing either many transactions, or staying connected for long periods the memory consumption from unnecesarily stored tokens is excessive. When clients do both the machine memory can be consumed, and the CPU can reach 100% consumption just walking the annotations lists during regular operations. To fix this we drop the security credentials tokens from cached annotations list in NTLM and Negotiate. Digest is also included though its HA1 token value is static it has similar privacy issues related to storage. ------------------------------------------------------------ # Bazaar merge directive format 2 (Bazaar 0.90) # revision_id: squid3@treenet.co.nz-20150118110213-zbcrupnx78b4y9mq # target_branch: http://bzr.squid-cache.org/bzr/squid3/3.4 # testament_sha1: a0115b5c42386ae4597d9e9c8e8842571c1fca1f # timestamp: 2015-01-18 11:50:54 +0000 # source_branch: http://bzr.squid-cache.org/bzr/squid3/3.4 # base_revision_id: squid3@treenet.co.nz-20150118081150-\ # g92c3d0w5sbsccj1 # # Begin patch === modified file 'src/Notes.cc' --- src/Notes.cc 2014-05-02 07:51:33 +0000 +++ src/Notes.cc 2015-01-18 11:02:13 +0000 @@ -189,6 +189,21 @@ } void +NotePairs::remove(const char *key) +{ + Vector::iterator i = entries.begin(); + while (i != entries.end()) { + if ((*i)->name.cmp(key) == 0) { + NotePairs::Entry *e = (*i); + entries.prune(e); + delete e; + i = entries.begin(); // vector changed underneath us + } else + ++i; + } +} + +void NotePairs::addStrList(const char *key, const char *values) { String strValues(values); === modified file 'src/Notes.h' --- src/Notes.h 2014-05-02 07:51:33 +0000 +++ src/Notes.h 2015-01-18 11:02:13 +0000 @@ -155,6 +155,11 @@ void add(const char *key, const char *value); /** + * Remove all notes with a given key. + */ + void remove(const char *key); + + /** * Adds a note key and values strList to the notes list. * If the key name already exists in list, add the new values to its set * of values. === modified file 'src/auth/digest/UserRequest.cc' --- src/auth/digest/UserRequest.cc 2014-03-05 02:48:25 +0000 +++ src/auth/digest/UserRequest.cc 2015-01-18 11:02:13 +0000 @@ -298,6 +298,8 @@ // add new helper kv-pair notes to the credentials object // so that any transaction using those credentials can access them auth_user_request->user()->notes.appendNewOnly(&reply.notes); + // remove any private credentials detail which got added. + auth_user_request->user()->notes.remove("ha1"); static bool oldHelperWarningDone = false; switch (reply.result) { === modified file 'src/auth/negotiate/UserRequest.cc' --- src/auth/negotiate/UserRequest.cc 2013-11-29 10:55:53 +0000 +++ src/auth/negotiate/UserRequest.cc 2015-01-18 11:02:13 +0000 @@ -229,6 +229,8 @@ // add new helper kv-pair notes to the credentials object // so that any transaction using those credentials can access them auth_user_request->user()->notes.appendNewOnly(&reply.notes); + // remove any private credentials detail which got added. + auth_user_request->user()->notes.remove("token"); Auth::Negotiate::UserRequest *lm_request = dynamic_cast(auth_user_request.getRaw()); assert(lm_request != NULL); === modified file 'src/auth/ntlm/UserRequest.cc' --- src/auth/ntlm/UserRequest.cc 2013-11-29 10:55:53 +0000 +++ src/auth/ntlm/UserRequest.cc 2015-01-18 11:02:13 +0000 @@ -223,6 +223,8 @@ // add new helper kv-pair notes to the credentials object // so that any transaction using those credentials can access them auth_user_request->user()->notes.appendNewOnly(&reply.notes); + // remove any private credentials detail which got added. + auth_user_request->user()->notes.remove("token"); Auth::Ntlm::UserRequest *lm_request = dynamic_cast(auth_user_request.getRaw()); assert(lm_request != NULL);