=== modified file 'src/external_acl.cc' --- src/external_acl.cc 2011-10-10 03:28:26 +0000 +++ src/external_acl.cc 2011-10-25 05:03:11 +0000 @@ -746,88 +746,109 @@ static allow_t aclMatchExternal(external_acl_data *acl, ACLFilledChecklist *ch) { const char *key = ""; debugs(82, 9, HERE << "acl=\"" << acl->def->name << "\""); external_acl_entry *entry = ch->extacl_entry; if (entry) { if (cbdataReferenceValid(entry) && entry->def == acl->def) { /* Ours, use it.. */ } else { /* Not valid, or not ours.. get rid of it */ debugs(82, 9, HERE << "entry " << entry << " not valid or not ours. Discarded."); if (entry) { debugs(82, 9, HERE << "entry def=" << entry->def << ", our def=" << acl->def); key = makeExternalAclKey(ch, acl); debugs(82, 9, HERE << "entry key='" << (char *)entry->key << "', our key='" << key << "'"); } cbdataReferenceDone(ch->extacl_entry); entry = NULL; } } external_acl_message = "MISSING REQUIRED INFORMATION"; if (!entry) { debugs(82, 9, HERE << "No helper entry available"); #if USE_AUTH if (acl->def->require_auth) { - int ti = AuthenticateAcl(ch); /* Make sure the user is authenticated */ debugs(82, 3, HERE << acl->def->name << " check user authenticated."); - if (ti != 1) { + allow_t ti = AuthenticateAcl(ch); + switch(ti) + { + case ACCESS_ALLOWED: + case ACCESS_AUTH_EXPIRED_OK: + // we have credentials. Trust them. + debugs(82, 3, HERE << acl->def->name << " user has okay authentication credentials."); + break; + + case ACCESS_DENIED: + case ACCESS_AUTH_EXPIRED_BAD: + // XXX: should we re-challenge instead? + debugs(82, 3, HERE << acl->def->name << " user has failed authentication credentials."); + case ACCESS_DUNNO: // need to wait for a full answer. + // XXX: what will happen though? + // AuthenticateAcl() might schedule a lookup on the given credentials + // but what schedules a re-check of this ACL test after they come back? + return ti; + + case ACCESS_AUTH_REQUIRED: + // XXX: why is this so important? + debugs(82, 1, "WARNING: " << acl->def->name << + " user authentication failure (" << ti << ", ch=" << ch << ")"); debugs(82, 2, HERE << acl->def->name << " user not authenticated (" << ti << ")"); return ACCESS_AUTH_REQUIRED; } debugs(82, 3, HERE << acl->def->name << " user is authenticated."); } #endif key = makeExternalAclKey(ch, acl); if (!key) { /* Not sufficient data to process */ return ACCESS_DUNNO; } entry = static_cast(hash_lookup(acl->def->cache, key)); if (!entry || external_acl_grace_expired(acl->def, entry)) { debugs(82, 2, HERE << acl->def->name << "(\"" << key << "\") = lookup needed"); debugs(82, 2, HERE << "\"" << key << "\": entry=@" << entry << ", age=" << (entry ? (long int) squid_curtime - entry->date : 0)); if (acl->def->theHelper->stats.queue_size <= (int)acl->def->theHelper->childs.n_active) { debugs(82, 2, HERE << "\"" << key << "\": queueing a call."); ch->changeState(ExternalACLLookup::Instance()); - debugs(82, 2, HERE << "\"" << key << "\": return -1."); + debugs(82, 2, HERE << "\"" << key << "\": return " << ACCESS_DUNNO); return ACCESS_DUNNO; // to get here we have to have an expired cache entry. MUST not use. } else { if (!entry) { debugs(82, DBG_IMPORTANT, "WARNING: external ACL '" << acl->def->name << "' queue overload. Request rejected '" << key << "'."); external_acl_message = "SYSTEM TOO BUSY, TRY AGAIN LATER"; return ACCESS_DUNNO; } else { debugs(82, DBG_IMPORTANT, "WARNING: external ACL '" << acl->def->name << "' queue overload. Using stale result. '" << key << "'."); /* Fall thru to processing below */ } } } } external_acl_cache_touch(acl->def, entry); external_acl_message = entry->message.termedBuf(); debugs(82, 2, HERE << acl->def->name << " = " << entry->result); if (ch->request) { #if USE_AUTH if (entry->user.size()) ch->request->extacl_user = entry->user; if (entry->password.size()) ch->request->extacl_passwd = entry->password; #endif if (!ch->request->tag.size()) @@ -1331,71 +1352,83 @@ do { void *cbdata; cbdataReferenceDone(state->def); if (state->callback && cbdataReferenceValidDone(state->callback_data, &cbdata)) state->callback(cbdata, entry); next = state->queue; cbdataFree(state); state = next; } while (state); } void ACLExternal::ExternalAclLookup(ACLChecklist *checklist, ACLExternal * me, EAH * callback, void *callback_data) { MemBuf buf; external_acl_data *acl = me->data; external_acl *def = acl->def; externalAclState *state; dlink_node *node; externalAclState *oldstate = NULL; bool graceful = 0; ACLFilledChecklist *ch = Filled(checklist); #if USE_AUTH if (acl->def->require_auth) { - int ti; /* Make sure the user is authenticated */ debugs(82, 3, HERE << acl->def->name << " check user authenticated."); - if ((ti = AuthenticateAcl(ch)) != 1) { + allow_t ti = AuthenticateAcl(ch); + switch(ti) + { + case ACCESS_ALLOWED: + case ACCESS_AUTH_EXPIRED_OK: + // we have credentials. Trust them? + debugs(82, 3, HERE << acl->def->name << " user has okay authentication credentials."); + break; + case ACCESS_DENIED: + case ACCESS_AUTH_EXPIRED_BAD: + // we have credentials. Trust them? + debugs(82, 3, HERE << acl->def->name << " user has failed authentication credentials."); + break; + case ACCESS_DUNNO: + case ACCESS_AUTH_REQUIRED: debugs(82, DBG_IMPORTANT, "WARNING: " << acl->def->name << " user authentication failure (" << ti << ", ch=" << ch << ")"); callback(callback_data, NULL); return; } - debugs(82, 3, HERE << acl->def->name << " user is authenticated."); } #endif const char *key = makeExternalAclKey(ch, acl); if (!key) { debugs(82, 1, "externalAclLookup: lookup in '" << def->name << "', prerequisit failure (ch=" << ch << ")"); callback(callback_data, NULL); return; } debugs(82, 2, "externalAclLookup: lookup in '" << def->name << "' for '" << key << "'"); external_acl_entry *entry = static_cast(hash_lookup(def->cache, key)); if (entry && external_acl_entry_expired(def, entry)) entry = NULL; /* Check for a pending lookup to hook into */ // only possible if we are caching results. if (def->cache_size > 0) { for (node = def->queue.head; node; node = node->next) { externalAclState *oldstatetmp = static_cast(node->data); if (strcmp(key, oldstatetmp->key) == 0) { oldstate = oldstatetmp; break; } }