/*
- * $Id: acl.cc,v 1.194 1999/01/13 22:13:38 wessels Exp $
+ * $Id: acl.cc,v 1.195 1999/01/24 02:22:53 wessels Exp $
*
* DEBUG: section 28 Access Control
* AUTHOR: Duane Wessels
static int decode_addr(const char *, struct in_addr *, struct in_addr *);
static void aclCheck(aclCheck_t * checklist);
static void aclCheckCallback(aclCheck_t * checklist, allow_t answer);
+static IDCB aclLookupIdentDone;
static IPH aclLookupDstIPDone;
static IPH aclLookupDstIPforASNDone;
static FQDNH aclLookupSrcFQDNDone;
aclParseIntRange(&A->data);
break;
case ACL_IDENT:
- Config.onoff.ident_lookup = 1;
aclParseWordList(&A->data);
break;
case ACL_PROTO:
debug(28, 3) ("aclMatchUser: checking '%s'\n", user);
while (data) {
debug(28, 3) ("aclMatchUser: looking for '%s'\n", data->key);
- if (strcmp(data->key, "REQUIRED") == 0 && *user != '\0')
+ if (strcmp(data->key, "REQUIRED") == 0 && *user != '\0' && strcmp(user, "-") != 0)
return 1;
if (strcmp(data->key, user) == 0)
return 1;
return aclMatchIntegerRange(ae->data, r->port);
/* NOTREACHED */
case ACL_IDENT:
- return aclMatchUser(ae->data, checklist->ident);
+ if (*checklist->ident) {
+ return aclMatchUser(ae->data, checklist->ident);
+ } else {
+ checklist->state[ACL_IDENT] = ACL_LOOKUP_NEEDED;
+ return 0;
+ }
/* NOTREACHED */
case ACL_PROTO:
return aclMatchInteger(ae->data, r->protocol);
match = -1;
} else if (checklist->state[ACL_IDENT] == ACL_LOOKUP_NEEDED) {
debug(28, 3) ("aclCheck: Doing ident lookup\n");
- /* XXX how to do ident lookup? */
- checklist->state[ACL_IDENT] = ACL_LOOKUP_PENDING;
- return;
+ if (cbdataValid(checklist->conn)) {
+ identStart(&checklist->conn->me, &checklist->conn->peer,
+ aclLookupIdentDone, checklist);
+ checklist->state[ACL_IDENT] = ACL_LOOKUP_PENDING;
+ return;
+ } else {
+ debug(28, 1) ("aclCheck: Can't start ident lookup. No client connection\n");
+ cbdataUnlock(checklist->conn);
+ checklist->conn = NULL;
+ allow = 0;
+ match = -1;
+ }
}
/*
* We are done with this _acl_access entry. Either the request
if (checklist->request)
requestUnlink(checklist->request);
checklist->request = NULL;
+ if (checklist->conn) {
+ cbdataUnlock(checklist->conn);
+ checklist->conn = NULL;
+ }
cbdataFree(checklist);
}
aclChecklistFree(checklist);
}
+static void
+aclLookupIdentDone(const char *ident, void *data)
+{
+ aclCheck_t *checklist = data;
+ if (ident) {
+ xstrncpy(checklist->ident, ident, sizeof(checklist->ident));
+ xstrncpy(checklist->request->user_ident, ident, sizeof(checklist->request->user_ident));
+ } else {
+ xstrncpy(checklist->ident, "-", sizeof(checklist->ident));
+ }
+ /* Cache the ident result in the connection, to avoid redoing ident lookup
+ * over and over on persistent connections
+ */
+ if (cbdataValid(checklist->conn) && !*checklist->conn->ident)
+ xstrncpy(checklist->conn->ident, checklist->ident, sizeof(checklist->conn->ident));
+ aclCheck(checklist);
+}
+
static void
aclLookupDstIPDone(const ipcache_addrs * ia, void *data)
{
#
-# $Id: cf.data.pre,v 1.134 1999/01/22 19:07:03 glenn Exp $
+# $Id: cf.data.pre,v 1.135 1999/01/24 02:22:54 wessels Exp $
#
#
# SQUID Internet Object Cache http://squid.nlanr.net/Squid/
pconn_timeout 120 seconds
DOC_END
+NAME: ident_timeout
+TYPE: time_t
+LOC: Config.Timeout.ident
+DEFAULT: 10 seconds
+DOC_START
+ Maximum time to wait for IDENT requests. If this is too high,
+ and you enabled 'ident_lookup', then you might be susceptible
+ to denial-of-service by having many ident requests going at
+ once.
+ident_timeout 10 seconds
+DOC_END
+
NAME: shutdown_lifetime
COMMENT: time-units
/*
- * $Id: client_side.cc,v 1.434 1999/01/21 23:58:43 wessels Exp $
+ * $Id: client_side.cc,v 1.435 1999/01/24 02:22:56 wessels Exp $
*
* DEBUG: section 33 Client-side Routines
* AUTHOR: Duane Wessels
static STCB clientHandleIMSReply;
static int clientGetsOldEntry(StoreEntry * new, StoreEntry * old, request_t * request);
static int checkAccelOnly(clientHttpRequest *);
+static IDCB clientIdentDone;
static int clientOnlyIfCached(clientHttpRequest * http);
static STCB clientSendMoreData;
static STCB clientCacheHit;
return 1;
}
+void
+clientIdentDone(const char *ident, void *data)
+{
+ ConnStateData *conn = data;
+ if (ident)
+ xstrncpy(conn->ident, ident, sizeof(conn->ident));
+ else
+ xstrncpy(conn->ident, "-", sizeof(conn->ident));
+}
+
void
clientAccessCheck(void *data)
{
clientHttpRequest *http = data;
ConnStateData *conn = http->conn;
const char *browser;
- if (Config.onoff.ident_lookup && conn->ident.state == IDENT_NONE) {
- identStart(-1, conn, clientAccessCheck, http);
- return;
- }
if (checkAccelOnly(http)) {
clientAccessCheckDone(0, http);
return;
http->request,
conn->peer.sin_addr,
browser,
- conn->ident.ident);
+ conn->ident);
+ /* hack for ident ACL. It needs to get full addresses, and a
+ * place to store the ident result on persistent connections...
+ */
+ http->acl_checklist->conn = conn;
+ cbdataLock(http->acl_checklist->conn);
aclNBCheck(http->acl_checklist, clientAccessCheckDone, http);
}
if (request->user_ident[0])
http->al.cache.ident = request->user_ident;
else
- http->al.cache.ident = conn->ident.ident;
+ http->al.cache.ident = conn->ident;
if (request) {
Packer p;
MemBuf mb;
assert(connState->chr != connState->chr->next);
httpRequestFree(http);
}
- if (connState->ident.fd > -1)
- comm_close(connState->ident.fd);
safe_free(connState->in.buf);
/* XXX account connState->in.buf */
pconnHistCount(0, connState->nrequests);
connState->log_addr.s_addr &= Config.Addrs.client_netmask.s_addr;
connState->me = me;
connState->fd = fd;
- connState->ident.fd = -1;
connState->in.size = REQUEST_BUF_SIZE;
connState->in.buf = xcalloc(connState->in.size, 1);
cbdataAdd(connState, cbdataXfree, 0);
if (Config.onoff.log_fqdn)
fqdncache_gethostbyaddr(peer.sin_addr, FQDN_LOOKUP_IF_MISS);
commSetTimeout(fd, Config.Timeout.request, requestTimeout, connState);
+ if (Config.onoff.ident_lookup)
+ identStart(&me, &peer, clientIdentDone, connState);
commSetSelect(fd, COMM_SELECT_READ, clientReadRequest, connState, 0);
commSetDefer(fd, clientReadDefer, connState);
(*N)++;
/*
- * $Id: ident.cc,v 1.46 1998/12/04 22:20:17 wessels Exp $
+ * $Id: ident.cc,v 1.47 1999/01/24 02:22:57 wessels Exp $
*
* DEBUG: section 30 Ident (RFC 931)
* AUTHOR: Duane Wessels
#include "squid.h"
#define IDENT_PORT 113
+#define IDENT_KEY_SZ 50
+
+typedef struct _IdentClient {
+ IDCB *callback;
+ void *callback_data;
+ struct _IdentClient *next;
+} IdentClient;
+
+typedef struct _IdentStateData {
+ char *key;
+ struct _IdentStateData *next;
+ int fd; /* IDENT fd */
+ struct sockaddr_in me;
+ struct sockaddr_in peer;
+ IdentClient *clients;
+} IdentStateData;
static PF identReadReply;
static PF identClose;
static PF identTimeout;
static CNCB identConnectDone;
-static void identCallback(ConnStateData * connState);
+static hash_table *ident_hash = NULL;
+static void identClientAdd(IdentStateData *, IDCB *, void *);
+
+/**** PRIVATE FUNCTIONS ****/
+
+static void
+identCallback(IdentStateData * state, char *result)
+{
+ IdentClient *client;
+ if (result && *result == '\0')
+ result = NULL;
+ while ((client = state->clients)) {
+ state->clients = client->next;
+ if (cbdataValid(client->callback_data))
+ client->callback(result, client->callback_data);
+ cbdataUnlock(client->callback_data);
+ xfree(client);
+ }
+}
static void
identClose(int fdnotused, void *data)
{
- ConnStateData *connState = data;
- connState->ident.fd = -1;
+ IdentStateData *state = data;
+ identCallback(state, NULL);
+ comm_close(state->fd);
+ hash_remove_link(ident_hash, (hash_link *) state);
+ cbdataFree(state);
}
static void
identTimeout(int fd, void *data)
{
- ConnStateData *connState = data;
+ IdentStateData *state = data;
debug(30, 3) ("identTimeout: FD %d, %s\n", fd,
- inet_ntoa(connState->peer.sin_addr));
+ inet_ntoa(state->peer.sin_addr));
comm_close(fd);
}
-/* start a TCP connection to the peer host on port 113 */
-void
-identStart(int fd, ConnStateData * connState, IDCB * callback, void *data)
-{
- connState->ident.callback = callback;
- connState->ident.callback_data = data;
- connState->ident.state = IDENT_PENDING;
- if (fd < 0) {
- fd = comm_open(SOCK_STREAM,
- 0,
- connState->me.sin_addr,
- 0,
- COMM_NONBLOCKING,
- "ident");
- if (fd == COMM_ERROR) {
- identCallback(connState);
- return;
- }
- }
- connState->ident.fd = fd;
- comm_add_close_handler(fd,
- identClose,
- connState);
- commConnectStart(fd,
- inet_ntoa(connState->peer.sin_addr),
- IDENT_PORT,
- identConnectDone,
- connState);
-}
-
static void
identConnectDone(int fd, int status, void *data)
{
- ConnStateData *connState = data;
+ IdentStateData *state = data;
+ IdentClient *c;
MemBuf mb;
if (status != COMM_OK) {
+ /* Failed to connect */
comm_close(fd);
- identCallback(connState);
return;
}
+ /*
+ * see if our clients still care
+ */
+ for (c = state->clients; c; c = c->next) {
+ if (cbdataValid(c->callback_data))
+ break;
+ }
+ if (c == NULL) /* no clients care */
+ comm_close(fd);
memBufDefInit(&mb);
memBufPrintf(&mb, "%d, %d\r\n",
- ntohs(connState->peer.sin_port),
- ntohs(connState->me.sin_port));
- comm_write_mbuf(fd, mb, NULL, connState);
- commSetSelect(fd, COMM_SELECT_READ, identReadReply, connState, 0);
- commSetTimeout(fd, Config.Timeout.read, identTimeout, connState);
+ ntohs(state->peer.sin_port),
+ ntohs(state->me.sin_port));
+ comm_write_mbuf(fd, mb, NULL, state);
+ commSetSelect(fd, COMM_SELECT_READ, identReadReply, state, 0);
+ commSetTimeout(fd, Config.Timeout.ident, identTimeout, state);
}
static void
identReadReply(int fd, void *data)
{
- ConnStateData *connState = data;
+ IdentStateData *state = data;
LOCAL_ARRAY(char, buf, BUFSIZ);
+ char *ident = NULL;
char *t = NULL;
int len = -1;
-
buf[0] = '\0';
Counter.syscalls.sock.reads++;
len = read(fd, buf, BUFSIZ - 1);
fd_bytes(fd, len, FD_READ);
- if (len > 0) {
- buf[len] = '\0';
- if ((t = strchr(buf, '\r')))
- *t = '\0';
- if ((t = strchr(buf, '\n')))
- *t = '\0';
- debug(30, 5) ("identReadReply: FD %d: Read '%s'\n", fd, buf);
- if (strstr(buf, "USERID")) {
- if ((t = strrchr(buf, ':'))) {
- while (isspace(*++t));
- xstrncpy(connState->ident.ident, t, USER_IDENT_SZ);
- }
+ if (len <= 0) {
+ comm_close(fd);
+ return;
+ }
+ /*
+ * XXX This isn't really very tolerant. It should read until EOL
+ * or EOF and then decode the answer... If the reply is fragmented
+ * then this will fail
+ */
+ buf[len] = '\0';
+ if ((t = strchr(buf, '\r')))
+ *t = '\0';
+ if ((t = strchr(buf, '\n')))
+ *t = '\0';
+ debug(30, 5) ("identReadReply: FD %d: Read '%s'\n", fd, buf);
+ if (strstr(buf, "USERID")) {
+ if ((ident = strrchr(buf, ':'))) {
+ while (isspace(*++ident));
+ identCallback(state, ident);
}
}
comm_close(fd);
- identCallback(connState);
}
+
static void
-identCallback(ConnStateData * connState)
+identClientAdd(IdentStateData * state, IDCB * callback, void *callback_data)
+{
+ IdentClient *c = xcalloc(1, sizeof(*c));
+ IdentClient **C;
+ c->callback = callback;
+ c->callback_data = callback_data;
+ cbdataLock(callback_data);
+ for (C = &state->clients; *C; C = &(*C)->next);
+ *C = c;
+}
+
+/**** PUBLIC FUNCTIONS ****/
+
+/*
+ * start a TCP connection to the peer host on port 113
+ */
+void
+identStart(struct sockaddr_in *me, struct sockaddr_in *peer, IDCB * callback, void *data)
+{
+ IdentStateData *state;
+ int fd;
+ char key1[IDENT_KEY_SZ];
+ char key2[IDENT_KEY_SZ];
+ char key[IDENT_KEY_SZ];
+ snprintf(key1, IDENT_KEY_SZ, "%s:%d",
+ inet_ntoa(me->sin_addr),
+ ntohs(me->sin_port));
+ snprintf(key2, IDENT_KEY_SZ, "%s:%d",
+ inet_ntoa(peer->sin_addr),
+ ntohs(peer->sin_port));
+ snprintf(key, IDENT_KEY_SZ, "%s,%s", key1, key2);
+ if ((state = hash_lookup(ident_hash, key)) != NULL) {
+ identClientAdd(state, callback, data);
+ return;
+ }
+ fd = comm_open(SOCK_STREAM,
+ 0,
+ me->sin_addr,
+ 0,
+ COMM_NONBLOCKING,
+ "ident");
+ if (fd == COMM_ERROR) {
+ /* Failed to get a local socket */
+ callback(NULL, data);
+ return;
+ }
+ state = xcalloc(1, sizeof(IdentStateData));
+ cbdataAdd(state, cbdataXfree, 0);
+ state->key = xstrdup(key);
+ state->fd = fd;
+ state->me = *me;
+ state->peer = *peer;
+ identClientAdd(state, callback, data);
+ hash_join(ident_hash, (hash_link *) state);
+ comm_add_close_handler(fd,
+ identClose,
+ state);
+ commSetTimeout(fd, Config.Timeout.ident, identTimeout, state);
+ commConnectStart(fd,
+ inet_ntoa(state->peer.sin_addr),
+ IDENT_PORT,
+ identConnectDone,
+ state);
+}
+
+void
+identInit(void)
{
- connState->ident.state = IDENT_DONE;
- if (connState->ident.callback)
- connState->ident.callback(connState->ident.callback_data);
+ ident_hash = hash_create((HASHCMP *) strcmp,
+ hashPrime(Squid_MaxFD / 8),
+ hash4);
}
/*
- * $Id: main.cc,v 1.288 1999/01/22 19:07:04 glenn Exp $
+ * $Id: main.cc,v 1.289 1999/01/24 02:22:57 wessels Exp $
*
* DEBUG: section 1 Startup and Main Loop
* AUTHOR: Harvest Derived
httpReplyInitModule(); /* must go before accepting replies */
errorInitialize();
accessLogInit();
+ identInit();
#ifdef SQUID_SNMP
snmpInit();
#endif
/*
- * $Id: protos.h,v 1.310 1999/01/22 19:07:05 glenn Exp $
+ * $Id: protos.h,v 1.311 1999/01/24 02:22:58 wessels Exp $
*
*
* SQUID Internet Object Cache http://squid.nlanr.net/Squid/
extern void start_announce(void *unused);
extern void sslStart(int fd, const char *, request_t *, size_t * sz);
extern void waisStart(FwdState *);
-extern void identStart(int, ConnStateData *, IDCB * callback, void *);
+
+/* ident.c */
+extern void identStart(struct sockaddr_in *me, struct sockaddr_in *peer, IDCB * callback, void *cbdata);
+extern void identInit(void);
extern void statInit(void);
extern void statFreeMemory(void);
/*
- * $Id: redirect.cc,v 1.77 1998/12/05 00:54:38 wessels Exp $
+ * $Id: redirect.cc,v 1.78 1999/01/24 02:22:59 wessels Exp $
*
* DEBUG: section 29 Redirector
* AUTHOR: Duane Wessels
cbdataAdd(r, cbdataXfree, 0);
r->orig_url = xstrdup(http->uri);
r->client_addr = conn->log_addr;
- if (conn->ident.ident == NULL || *conn->ident.ident == '\0') {
+ if (conn->ident == NULL || *conn->ident == '\0') {
r->client_ident = dash_str;
} else {
- r->client_ident = conn->ident.ident;
+ r->client_ident = conn->ident;
}
r->method_s = RequestMethodStr[http->request->method];
r->handler = handler;
/*
- * $Id: structs.h,v 1.268 1999/01/22 19:07:06 glenn Exp $
+ * $Id: structs.h,v 1.269 1999/01/24 02:22:59 wessels Exp $
*
*
* SQUID Internet Object Cache http://squid.nlanr.net/Squid/
const acl_access *access_list;
struct in_addr src_addr;
struct in_addr dst_addr;
+ ConnStateData *conn; /* hack for ident */
request_t *request;
char ident[USER_IDENT_SZ];
char browser[BROWSERNAMELEN];
time_t deadPeer;
int icp_query; /* msec */
int mcast_icp_query; /* msec */
+ time_t ident;
} Timeout;
size_t maxRequestSize;
struct {
struct sockaddr_in peer;
struct sockaddr_in me;
struct in_addr log_addr;
- struct {
- int fd;
- char ident[USER_IDENT_SZ];
- IDCB *callback;
- int state;
- void *callback_data;
- } ident;
+ char ident[USER_IDENT_SZ];
int nrequests;
int persistent;
struct {
/*
- * $Id: typedefs.h,v 1.84 1999/01/11 21:55:45 wessels Exp $
+ * $Id: typedefs.h,v 1.85 1999/01/24 02:23:00 wessels Exp $
*
*
* SQUID Internet Object Cache http://squid.nlanr.net/Squid/
typedef void DRCB(int fd, const char *buf, int size, int errflag, void *data);
typedef void DWCB(int, int, size_t, void *);
typedef void FQDNH(const char *, void *);
-typedef void IDCB(void *);
+typedef void IDCB(const char *ident, void *data);
typedef void IPH(const ipcache_addrs *, void *);
typedef void IRCB(peer *, peer_t, protocol_t, void *, void *data);
typedef void PSC(FwdServer *, void *);