=== 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<external_acl_entry *>(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<external_acl_entry *>(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<externalAclState *>(node->data);
 
             if (strcmp(key, oldstatetmp->key) == 0) {
                 oldstate = oldstatetmp;
                 break;
             }
         }


