diff -r -u old/squid-2.4.PRE-STABLE/src/acl.c new/squid-2.4.PRE-STABLE/src/acl.c
--- old/squid-2.4.PRE-STABLE/src/acl.c	Mon Feb 26 18:07:51 2001
+++ new/squid-2.4.PRE-STABLE/src/acl.c	Mon Feb 26 19:17:00 2001
@@ -44,6 +44,7 @@
 static void aclParseIpList(void *curlist);
 static void aclParseIntlist(void *curlist);
 static void aclParseWordList(void *curlist);
+static int aclRemoveWordList(void *curlist, const char *key);
 static void aclParseProtoList(void *curlist);
 static void aclParseMethodList(void *curlist);
 static void aclParseTimeSpec(void *curlist);
@@ -637,6 +638,12 @@
 	wordlistAdd(curlist, t);
 }
 
+static int
+aclRemoveWordList(void *curlist, const char *key)
+{
+    return wordlistRemove(curlist, key);
+}
+
 /**********************/
 /* aclParseDomainList */
 /**********************/
@@ -689,6 +696,7 @@
 	xstrncpy(A->name, aclname, ACL_NAME_SZ);
 	A->type = acltype;
 	A->cfgline = xstrdup(config_input_line);
+	A->flags = 0;
 	new_acl = 1;
     } else {
 	if (acltype != A->type) {
@@ -749,6 +757,14 @@
 	break;
     case ACL_PROXY_AUTH:
 	aclParseWordList(&A->data);
+	if (aclRemoveWordList(&A->data,"BLOCK")) {
+	    A->flags |= FLAG_ACL_REQUEST_BLOCKING;
+	    debug(28, 4) ("aclParseAclLine: ACL '%s': mode 'BLOCK'\n",
+			  A->name);
+	} else 
+	    debug(28, 6) ("aclParseAclLine: ACL '%s': not in mode 'BLOCK'\n", 
+			  A->name);
+
 	if (!proxy_auth_cache) {
 	    /* First time around, 7921 should be big enough */
 	    proxy_auth_cache = hash_create((HASHCMP *) strcmp, 7921, hash_string);
@@ -1079,6 +1095,7 @@
 /* aclMatchProxyAuth can return three exit codes:
  * 0 : user denied access
  * 1 : user validated OK
+ * -3 : user validated OK and we are still in the user blocking_ttl period.
  * -1 : check the password for this user via an external authenticator
  * -2 : invalid Proxy-authorization: header;
  * ask for Proxy-Authorization: header
@@ -1144,6 +1161,7 @@
 	(auth_user->expiretime > current_time.tv_sec)) {
 	if (checklist->src_addr.s_addr == auth_user->ipaddr.s_addr
 	    || auth_user->ip_expiretime <= squid_curtime) {
+	    int ret;
 	    /* user already known and valid */
 	    debug(28, 5) ("aclMatchProxyAuth: user '%s' previously validated\n",
 		user);
@@ -1154,13 +1172,31 @@
 	    xstrncpy(checklist->request->user_ident, user, USER_IDENT_SZ);
 	    switch (acltype) {
 	    case ACL_PROXY_AUTH:
-		return aclMatchUser(data, user);
+		ret = aclMatchUser(data, user);
+		break;
 	    case ACL_PROXY_AUTH_REGEX:
-		return aclMatchRegex(data, user);
+		ret = aclMatchRegex(data, user);
+		break;
 	    default:
 		fatal("aclMatchProxyAuth: unknown ACL type");
 		return 0;	/* NOTREACHED */
 	    }
+	    if (ret != 1)
+		return ret;
+	    if (!auth_user->validatedtime)
+		auth_user->validatedtime = current_time.tv_sec;
+	    if (!auth_user->request_blocking_done) { 
+		if (!Config.blockingTTL) {
+		    auth_user->request_blocking_done = 1;
+		    return -3;
+		}
+		if (Config.blockingTTL + auth_user->validatedtime 
+		    < current_time.tv_sec) {
+		    auth_user->request_blocking_done = 1;
+		} else
+		    return -3;
+	    } 
+	    return 1;
 	} else {
 	    if (Config.onoff.authenticateIpTTLStrict) {
 		/* Access from some other IP address than the one owning
@@ -1225,6 +1261,8 @@
     auth_user->passwd = xstrdup(password);
     auth_user->passwd_ok = -1;
     auth_user->expiretime = -1;
+    auth_user->request_blocking_done = 0;
+    auth_user->validatedtime = 0;
     checklist->auth_user = auth_user;
     authenticateStart(checklist->auth_user, aclLookupProxyAuthDone,
 	checklist);
@@ -1517,8 +1555,19 @@
 	case 0:
 	    /* Correct password, but was not allowed in this ACL */
 	    return 0;
+	case -3:
+	    /* user validated OK but we may block the request */
+	    if (ae->flags & FLAG_ACL_REQUEST_BLOCKING) {
+		RequestBlockingAclMatchedName = ae->name;
+		debug(28, 6) ("aclMatchProxyAuth: request blocked\n");
+	    }
+	    return 1;
 	case 1:
 	    /* user validated OK */
+	    if (ae->flags & FLAG_ACL_REQUEST_BLOCKING) {
+		debug(28, 6) 
+		    ("aclMatchProxyAuth: request not blocked\n");
+	    }
 	    return 1;
 	case -2:
 	    /* no such user OR we need a proxy authentication header */
@@ -1581,6 +1630,7 @@
 int
 aclMatchAclList(const acl_list * list, aclCheck_t * checklist)
 {
+    RequestBlockingAclMatchedName = NULL;
     while (list) {
 	AclMatchedName = list->acl->name;
 	debug(28, 3) ("aclMatchAclList: checking %s%s\n",
diff -r -u old/squid-2.4.PRE-STABLE/src/cache_cf.c new/squid-2.4.PRE-STABLE/src/cache_cf.c
--- old/squid-2.4.PRE-STABLE/src/cache_cf.c	Mon Feb 26 18:07:51 2001
+++ new/squid-2.4.PRE-STABLE/src/cache_cf.c	Mon Feb 26 16:28:28 2001
@@ -112,6 +112,22 @@
     return (*list)->key;
 }
 
+int
+wordlistRemove(wordlist ** list,const char *key)
+{
+    wordlist *w = NULL;
+    while ((w = *list) != NULL) {
+	if (! strcmp(key,w->key)) {
+	    *list = w->next;
+	    safe_free(w->key);
+	    memFree(w, MEM_WORDLIST);
+	    return 1;
+	}
+	list = &(*list)->next;
+    }
+    return 0;
+}
+
 void
 wordlistJoin(wordlist ** list, wordlist ** wl)
 {
diff -r -u old/squid-2.4.PRE-STABLE/src/cf.data.pre new/squid-2.4.PRE-STABLE/src/cf.data.pre
--- old/squid-2.4.PRE-STABLE/src/cf.data.pre	Mon Feb 26 18:07:51 2001
+++ new/squid-2.4.PRE-STABLE/src/cf.data.pre	Mon Feb 26 18:15:19 2001
@@ -1654,6 +1654,11 @@
 	  # to check username/password combinations (see
 	  # authenticate_program).
 	  #
+	  # NOTE: special word BLOCK can be added to the proxy_auth acltype 
+	  # parameters. When present, first requests of the authenticated user
+	  # are blocked and an ACCESS_DENIED page is returned. 
+	  # See blocking_info and blocking_ttl tags below for customizations.
+	  #
 	  # WARNING: proxy_auth can't be used in a transparent proxy. It
 	  # collides with any authentication done by origin servers. It may
 	  # seem like it works at first, but it doesn't.
@@ -2152,6 +2157,28 @@
 
 	You may use ERR_ pages that come with Squid or create your own pages
 	and put them into the configured errors/ directory.
+DOC_END
+
+NAME: blocking_ttl
+TYPE: time_t
+DEFAULT: 0 seconds
+LOC: Config.blockingTTL
+DOC_START
+	The time during which a newly authenticated user will see its requests
+	rejected (see blocking_info below for page customization).
+	Default is `0' which blocks only the first request sent by the user.
+DOC_END
+
+NAME: blocking_info
+TYPE: denyinfo
+LOC: Config.blockInfoList
+DEFAULT: none
+DOC_START
+	Usage:   blocking_info front_page_name acl
+	Example: blocking_info FRONT_PAGE password
+
+	This can be used to return a customized page to a newly authenticated 
+	user. The page is returned in place of his request.
 DOC_END
 
 NAME: memory_pools
diff -r -u old/squid-2.4.PRE-STABLE/src/client_side.c new/squid-2.4.PRE-STABLE/src/client_side.c
--- old/squid-2.4.PRE-STABLE/src/client_side.c	Mon Feb 26 18:07:51 2001
+++ new/squid-2.4.PRE-STABLE/src/client_side.c	Mon Feb 26 19:01:14 2001
@@ -224,11 +224,29 @@
 	AclMatchedName ? AclMatchedName : "NO ACL's");
     http->acl_checklist = NULL;
     if (answer == ACCESS_ALLOWED) {
+	if (RequestBlockingAclMatchedName) {
+	    debug(33, 2) 
+		("The request is blocked by rule '%s'\n", 
+		 RequestBlockingAclMatchedName);
+	    page_id = aclGetDenyInfoPage(&Config.blockInfoList,
+					 RequestBlockingAclMatchedName);
+	    if (page_id <= 0)
+		page_id = ERR_ACCESS_DENIED;
+	    http->log_type = LOG_TAG_NONE;
+	    http->entry = clientCreateStoreEntry(http, http->request->method,
+						 null_request_flags);
+	    status = HTTP_FORBIDDEN;
+	    err = errorCon(page_id, status);
+	    err->request = requestLink(http->request);
+	    err->src_addr = http->conn->peer.sin_addr;
+	    errorAppendEntry(http->entry, err);
+	} else {
 	safe_free(http->uri);
 	http->uri = xstrdup(urlCanonical(http->request));
 	assert(http->redirect_state == REDIRECT_NONE);
 	http->redirect_state = REDIRECT_PENDING;
 	redirectStart(http, clientRedirectDone, http);
+	}
     } else {
 	debug(33, 5) ("Access Denied: %s\n", http->uri);
 	debug(33, 5) ("AclMatchedName = %s\n",
diff -r -u old/squid-2.4.PRE-STABLE/src/enums.h new/squid-2.4.PRE-STABLE/src/enums.h
--- old/squid-2.4.PRE-STABLE/src/enums.h	Mon Feb 26 18:07:51 2001
+++ new/squid-2.4.PRE-STABLE/src/enums.h	Mon Feb 26 16:29:59 2001
@@ -133,6 +133,11 @@
     ACL_PROXY_AUTH_NEEDED
 } acl_lookup_state;
 
+typedef enum {
+    FLAG_ACL_NONE,		/* 0 */
+    FLAG_ACL_REQUEST_BLOCKING   /* 1 */
+} acl_flags;
+
 enum {
     FD_NONE,
     FD_LOG,
diff -r -u old/squid-2.4.PRE-STABLE/src/globals.h new/squid-2.4.PRE-STABLE/src/globals.h
--- old/squid-2.4.PRE-STABLE/src/globals.h	Mon Feb 26 18:07:51 2001
+++ new/squid-2.4.PRE-STABLE/src/globals.h	Mon Feb 26 16:30:08 2001
@@ -152,3 +152,4 @@
 extern int store_pages_max;	/* 0 */
 extern ssize_t store_maxobjsize;	/* -1 */
 extern RemovalPolicy *mem_policy;
+extern const char *RequestBlockingAclMatchedName;	/* NULL */
diff -r -u old/squid-2.4.PRE-STABLE/src/protos.h new/squid-2.4.PRE-STABLE/src/protos.h
--- old/squid-2.4.PRE-STABLE/src/protos.h	Mon Feb 26 18:07:51 2001
+++ new/squid-2.4.PRE-STABLE/src/protos.h	Mon Feb 26 17:37:04 2001
@@ -75,6 +75,7 @@
 extern void intlistDestroy(intlist **);
 extern int intlistFind(intlist * list, int i);
 extern const char *wordlistAdd(wordlist **, const char *);
+extern int wordlistRemove(wordlist **, const char *);
 extern void wordlistAddWl(wordlist **, wordlist *);
 extern void wordlistJoin(wordlist **, wordlist **);
 extern wordlist *wordlistDup(const wordlist *);
diff -r -u old/squid-2.4.PRE-STABLE/src/structs.h new/squid-2.4.PRE-STABLE/src/structs.h
--- old/squid-2.4.PRE-STABLE/src/structs.h	Mon Feb 26 18:07:51 2001
+++ new/squid-2.4.PRE-STABLE/src/structs.h	Mon Feb 26 19:15:39 2001
@@ -66,9 +66,11 @@
     /* extra fields for proxy_auth */
     char *passwd;
     int passwd_ok;		/* 1 = passwd checked OK */
+    int request_blocking_done;	/* 1 = first requests already blocked */
     long expiretime;
     struct in_addr ipaddr;	/* IP addr this user authenticated from */
     time_t ip_expiretime;
+    time_t validatedtime;
 };
 
 struct _acl_deny_info_list {
@@ -120,6 +122,7 @@
     squid_acl type;
     void *data;
     char *cfgline;
+    acl_flags flags;
     acl *next;
 };
 
@@ -451,6 +454,8 @@
 	acl_access *redirector;
     } accessList;
     acl_deny_info_list *denyInfoList;
+    acl_deny_info_list *blockInfoList;
+    time_t blockingTTL;
     char *proxyAuthRealm;
     struct {
 	size_t list_width;

