NotePairs::hasPair(const char *key, const char *value) const
{
for (Vector<NotePairs::Entry *>::const_iterator i = entries.begin(); i != entries.end(); ++i) {
- if ((*i)->name.cmp(key) == 0 || (*i)->value.cmp(value) == 0)
+ if ((*i)->name.cmp(key) == 0 && (*i)->value.cmp(value) == 0)
return true;
}
return false;
}
}
+void
+NotePairs::appendNewOnly(const NotePairs *src)
+{
+ for (Vector<NotePairs::Entry *>::const_iterator i = src->entries.begin(); i != src->entries.end(); ++i) {
+ if (!hasPair((*i)->name.termedBuf(), (*i)->value.termedBuf()))
+ entries.push_back(new NotePairs::Entry((*i)->name.termedBuf(), (*i)->value.termedBuf()));
+ }
+}
+
NotePairs &
SyncNotes(AccessLogEntry &ale, HttpRequest &request)
{
+ // XXX: auth code only has access to HttpRequest being authenticated
+ // so we must handle the case where HttpRequest is set without ALE being set.
+
if (!ale.notes) {
- assert(!request.notes);
- ale.notes = request.notes = new NotePairs;
+ if (!request.notes)
+ request.notes = new NotePairs;
+ ale.notes = request.notes;
} else {
assert(ale.notes == request.notes);
}
*/
void append(const NotePairs *src);
+ /**
+ * Append any new entries of the src NotePairs list to our list.
+ * Entries which already exist in the destination set are ignored.
+ */
+ void appendNewOnly(const NotePairs *src);
+
/**
* Returns a comma separated list of notes with key 'noteKey'.
* Use findFirst instead when a unique kv-pair is needed.
config(aConfig),
ipcount(0),
expiretime(0),
+ notes(),
credentials_state(Auth::Unchecked),
username_(NULL)
{
debugs(29, 5, HERE << "auth_user '" << from << "' into auth_user '" << this << "'.");
+ // combine the helper response annotations. Ensuring no duplicates are copied.
+ notes.appendNewOnly(&from->notes);
+
/* absorb the list of IP address sources (for max_user_ip controls) */
AuthUserIP *new_ipdata;
while (from->ip_list.head != NULL) {
#include "base/RefCount.h"
#include "dlink.h"
#include "ip/Address.h"
+#include "Notes.h"
class AuthUserHashPointer;
class StoreEntry;
size_t ipcount;
long expiretime;
+ /// list of key=value pairs the helper produced
+ NotePairs notes;
+
public:
static void cacheInit();
static void CachedACLsReset();
static Auth::UserRequest::Pointer
authTryGetUser(Auth::UserRequest::Pointer auth_user_request, ConnStateData * conn, HttpRequest * request)
{
+ Auth::UserRequest::Pointer res;
+
if (auth_user_request != NULL)
- return auth_user_request;
+ res = auth_user_request;
else if (request != NULL && request->auth_user_request != NULL)
- return request->auth_user_request;
+ res = request->auth_user_request;
else if (conn != NULL)
- return conn->getAuth();
- else
- return NULL;
+ res = conn->getAuth();
+
+ // attach the credential notes from helper to the transaction
+ if (res != NULL && res->user() != NULL) {
+ // XXX: we have no access to the transaction / AccessLogEntry so cant SyncNotes().
+ // workaround by using anything already set in HttpRequest
+ // OR use new and rely on a later Sync copying these to AccessLogEntry
+ if (!request->notes)
+ request->notes = new NotePairs;
+
+ request->notes->appendNewOnly(&res->user()->notes);
+ }
+
+ return res;
}
/* returns one of
assert(r->auth_user_request != NULL);
assert(r->auth_user_request->user()->auth_type == Auth::AUTH_BASIC);
+ // add new helper kv-pair notes to the credentials object
+ // so that any transaction using those credentials can access them
+ r->auth_user_request->user()->notes.appendNewOnly(&reply.notes);
+
/* this is okay since we only play with the Auth::Basic::User child fields below
* and dont pass the pointer itself anywhere */
Auth::Basic::User *basic_auth = dynamic_cast<Auth::Basic::User *>(r->auth_user_request->user().getRaw());
assert(replyData->auth_user_request != NULL);
Auth::UserRequest::Pointer auth_user_request = replyData->auth_user_request;
+ // 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);
+
static bool oldHelperWarningDone = false;
switch (reply.result) {
case HelperReply::Unknown: {
Auth::UserRequest::Pointer auth_user_request = r->auth_user_request;
assert(auth_user_request != NULL);
+ // 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);
+
Auth::Negotiate::UserRequest *lm_request = dynamic_cast<Auth::Negotiate::UserRequest *>(auth_user_request.getRaw());
assert(lm_request != NULL);
assert(lm_request->waiting);
Auth::UserRequest::Pointer auth_user_request = r->auth_user_request;
assert(auth_user_request != NULL);
+ // 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);
+
Auth::Ntlm::UserRequest *lm_request = dynamic_cast<Auth::Ntlm::UserRequest *>(auth_user_request.getRaw());
assert(lm_request != NULL);
assert(lm_request->waiting);
/*Add notes*/
// The al->notes and request->notes must point to the same object.
- // Enable the following assertion to check for possible bugs.
- // assert(request->notes == al->notes);
+ (void)SyncNotes(*al, *request);
typedef Notes::iterator ACAMLI;
for (ACAMLI i = Config.notes.begin(); i != Config.notes.end(); ++i) {
if (const char *value = (*i)->match(request, al->reply)) {