a specific URL.
/*
- * $Id: acl.cc,v 1.29 1996/09/04 22:03:18 wessels Exp $
+ * $Id: acl.cc,v 1.30 1996/09/11 22:31:04 wessels Exp $
*
* DEBUG: section 28 Access Control
* AUTHOR: Duane Wessels
#include "squid.h"
-/* These two should never be referenced directly in this file! */
+/* Global */
+char *AclMatchedName = NULL;
+
+/* These three should never be referenced directly in this file! */
+struct _acl_deny_info_list *DenyInfoList = NULL;
struct _acl_access *HTTPAccessList = NULL;
struct _acl_access *ICPAccessList = NULL;
AclListTail = &A->next;
}
+/* maex@space.net (06.09.96)
+ * get (if any) the URL from deny_info for a certain acl
+ */
+char *aclGetDenyInfoUrl(head, name)
+ struct _acl_deny_info_list **head;
+ char *name;
+{
+ struct _acl_deny_info_list *A = NULL;
+ struct _acl_name_list *L = NULL;
+
+ A = *head;
+ if (NULL == *head) /* empty list */
+ return (NULL);
+ while (A) {
+ L = A->acl_list;
+ if (NULL == L) /* empty list should never happen, but in case */
+ continue;
+ while (L) {
+ if (!strcmp(name, L->name))
+ return (A->url);
+ L = L->next;
+ }
+ A = A->next;
+ }
+ return (NULL);
+}
+/* maex@space.net (05.09.96)
+ * get the info for redirecting "access denied" to info pages
+ * TODO (probably ;-)
+ * currently there is no optimization for
+ * - more than one deny_info line with the same url
+ * - a check, whether the given acl really is defined
+ * - a check, whether an acl is added more than once for the same url
+ */
+void aclParseDenyInfoLine(head)
+ struct _acl_deny_info_list **head;
+{
+ char *t = NULL;
+ struct _acl_deny_info_list *A = NULL;
+ struct _acl_deny_info_list *B = NULL;
+ struct _acl_deny_info_list **T = NULL;
+ struct _acl_name_list *L = NULL;
+ struct _acl_name_list **Tail = NULL;
+
+ /* first expect an url */
+ if ((t = strtok(NULL, w_space)) == NULL) {
+ debug(28, 0, "%s line %d: %s\n",
+ cfg_filename, config_lineno, config_input_line);
+ debug(28, 0, "aclParseDenyInfoLine: missing 'url' parameter.\n");
+ return;
+ }
+ A = xcalloc(1, sizeof(struct _acl_deny_info_list));
+ strncpy(A->url, t, MAX_URL);
+ A->url[MAX_URL] = '\0'; /* just in case strlen(t) >= MAX_URL */
+ A->next = (struct _acl_deny_info_list *) NULL;
+ /* next expect a list of ACL names */
+ Tail = &A->acl_list;
+ while ((t = strtok(NULL, w_space))) {
+ L = xcalloc(1, sizeof(struct _acl_name_list));
+ strncpy(L->name, t, ACL_NAME_SZ);
+ L->name[ACL_NAME_SZ] = '\0'; /* just in case strlen(t) >= ACL_NAME_SZ */
+ *Tail = L;
+ Tail = &L->next;
+ }
+ if (A->acl_list == NULL) {
+ debug(28, 0, "%s line %d: %s\n",
+ cfg_filename, config_lineno, config_input_line);
+ debug(28, 0, "aclParseDenyInfoLine: deny_info line contains no ACL's, skipping\n");
+ xfree(A);
+ return;
+ }
+ for (B = *head, T = head; B; T = &B->next, B = B->next); /* find the tail */
+ *T = A;
+}
+
void aclParseAccessLine(head)
struct _acl_access **head;
{
aclCheck_t *checklist;
{
while (list) {
+ AclMatchedName = list->acl->name;
debug(28, 3, "aclMatchAclList: checking %s%s\n",
list->op ? "" : "!", list->acl->name);
if (aclMatchAcl(list->acl, checklist) != list->op) {
}
*list = NULL;
}
+
+/* maex@space.net (06.09.1996)
+ * destroy an _acl_deny_info_list
+ */
+void aclDestroyDenyInfoList(list)
+ struct _acl_deny_info_list **list;
+{
+ struct _acl_deny_info_list *a = NULL;
+ struct _acl_deny_info_list *a_next = NULL;
+ struct _acl_name_list *l = NULL;
+ struct _acl_name_list *l_next = NULL;
+
+ for (a = *list; a; a = a_next) {
+ for (l = a->acl_list; l; l = l_next) {
+ l_next = l->next;
+ safe_free(l);
+ }
+ a_next = a->next;
+ safe_free(a);
+ }
+}
/*
- * $Id: client_side.cc,v 1.16 1996/09/05 16:59:49 wessels Exp $
+ * $Id: client_side.cc,v 1.17 1996/09/11 22:31:07 wessels Exp $
*
* DEBUG: section 33 Client-side Routines
* AUTHOR: Duane Wessels
{
int fd = icpState->fd;
char *buf = NULL;
+ char *redirectUrl = NULL;
debug(33, 5, "clientAccessCheckDone: '%s' answer=%d\n", icpState->url, answer);
if (answer) {
urlCanonical(icpState->request, icpState->url);
redirectStart(fd, icpState, clientRedirectDone, icpState);
} else {
debug(33, 5, "Access Denied: %s\n", icpState->url);
- buf = access_denied_msg(icpState->http_code = 400,
- icpState->method,
- icpState->url,
- fd_table[fd].ipaddr);
- icpSendERROR(fd, LOG_TCP_DENIED, buf, icpState, 403);
+ redirectUrl = aclGetDenyInfoUrl(&DenyInfoList, AclMatchedName);
+ if (redirectUrl) {
+ icpState->http_code = 302,
+ buf = access_denied_redirect(icpState->http_code,
+ icpState->method,
+ icpState->url,
+ fd_table[fd].ipaddr,
+ redirectUrl);
+ } else {
+ icpState->http_code = 400;
+ buf = access_denied_msg(icpState->http_code,
+ icpState->method,
+ icpState->url,
+ fd_table[fd].ipaddr);
+ }
+ icpSendERROR(fd, LOG_TCP_DENIED, buf, icpState, icpState->http_code);
}
}
MemObject *mem = entry->mem_obj;
LOCAL_ARRAY(char, hbuf, 8192);
int len;
+ int unlink_request = 0;
debug(33, 0, "icpHandleIMSReply: FD %d '%s'\n", fd, entry->url);
/* unregister this handler */
storeUnregister(entry, fd);
icpState->log_type = LOG_TCP_EXPIRED_HIT;
/* We initiated the IMS request, the client is not expecting
* 304, so put the good one back */
- if (icpState->old_entry->mem_obj->request == NULL)
+ if (icpState->old_entry->mem_obj->request == NULL) {
icpState->old_entry->mem_obj->request = requestLink(mem->request);
+ unlink_request = 1;
+ }
storeUnlockObject(entry);
entry = icpState->entry = icpState->old_entry;
/* Extend the TTL
fatal_dump("icpHandleIMSReply: failed to load headers, lost race");
httpParseHeaders(hbuf, entry->mem_obj->reply);
ttlSet(entry);
- requestUnlink(entry->mem_obj->request);
+ if (unlink_request)
+ requestUnlink(entry->mem_obj->request);
} else {
/* the client can handle this reply, whatever it is */
icpState->log_type = LOG_TCP_EXPIRED_MISS;
/*
- * $Id: errorpage.cc,v 1.36 1996/09/04 22:03:22 wessels Exp $
+ * $Id: errorpage.cc,v 1.37 1996/09/11 22:31:06 wessels Exp $
*
* DEBUG: section 4 Error Generation
* AUTHOR: Duane Wessels
char *msg;
{
int index;
+
if (type < ERR_MIN || type > ERR_MAX)
fatal_dump("squid_error_entry: type out of range.");
index = (int) (type - ERR_MIN);
char *msg;
{
int index;
+
*tmp_error_buf = '\0';
if (type < ERR_MIN || type > ERR_MAX)
fatal_dump("squid_error_url: type out of range.");
int code;
{
int index;
+
*tmp_error_buf = '\0';
if (type < ERR_MIN || type > ERR_MAX)
fatal_dump("squid_error_request: type out of range.");
return tmp_error_buf;
}
+/* maex@space.net (06.09.1996)
+ * the message that is sent on deny_info
+ * add a Location: and for old browsers a HREF to the info page
+ */
+char *access_denied_redirect(code, method, url, client, redirect)
+ int code;
+ int method;
+ char *url;
+ char *client;
+ char *redirect;
+{
+ sprintf(tmp_error_buf, "\
+HTTP/1.0 %d Cache Access Deny Redirect\r\n\
+Location: %s\r\n\
+Content-type: text/html\r\n\
+\r\n\
+<HTML><HEAD><TITLE>Cache Access Denied</TITLE></HEAD>\n\
+<BODY><H1>Error</H1>\n\
+<H2>Access Denied</H2>\n\
+<P>\n\
+Sorry, you are not currently allowed to request\n\
+<PRE> %s</PRE>\n\
+from this cache.\n\
+<P>\n\
+You may take a look at\n\
+<PRE> <A HREF=\"%s\">%s</A></PRE>\n\
+or check with the cache administrator if you\n\
+believe this is incorrect.\n\
+<P>\n\
+%s\n\
+<HR>\n\
+<ADDRESS>\n\
+Generated by %s/%s@%s\n\
+</ADDRESS></BODY></HTML>\n\
+\n",
+ code,
+ redirect,
+ url,
+ redirect,
+ redirect,
+ Config.errHtmlText,
+ appname,
+ version_string,
+ getMyHostname());
+ return tmp_error_buf;
+}
+
char *authorization_needed_msg(request, realm)
request_t *request;
char *realm;