/*
- * $Id: acl.cc,v 1.285 2002/09/15 06:40:56 robertc Exp $
+ * $Id: acl.cc,v 1.286 2002/09/26 13:33:07 robertc Exp $
*
* DEBUG: section 28 Access Control
* AUTHOR: Duane Wessels
}
/* get authed here */
/* Note: this fills in checklist->auth_user_request when applicable */
- switch (authenticateAuthenticate(&checklist->auth_user_request, headertype, checklist->request, checklist->conn, checklist->src_addr)) {
+ switch (authenticateTryToAuthenticateAndSetAuthUser(&checklist->auth_user_request, headertype, checklist->request, checklist->conn, checklist->src_addr)) {
case AUTH_ACL_CANNOT_AUTHENTICATE:
debug(28, 4) ("aclMatchAcl: returning 0 user authenticated but not authorised.\n");
return 0;
/*
- * $Id: authenticate.cc,v 1.39 2002/07/15 22:13:27 hno Exp $
+ * $Id: authenticate.cc,v 1.40 2002/09/26 13:33:08 robertc Exp $
*
* DEBUG: section 29 Authenticator
* AUTHOR: Duane Wessels
static void
authenticateDecodeAuth(const char *proxy_auth, auth_user_request_t * auth_user_request);
+static auth_acl_t authenticateAuthenticate(auth_user_request_t ** auth_user_request, http_hdr_type headertype, request_t * request, ConnStateData * conn, struct in_addr src_addr);
/*
*
{
const char *proxy_auth;
assert(headertype != 0);
+
proxy_auth = httpHeaderGetStr(&request->header, headertype);
if (conn == NULL) {
return AUTH_AUTHENTICATED;
}
+auth_acl_t
+authenticateTryToAuthenticateAndSetAuthUser(auth_user_request_t ** auth_user_request, http_hdr_type headertype, request_t * request, ConnStateData * conn, struct in_addr src_addr)
+{
+ /* If we have already been called, return the cached value */
+ auth_user_request_t *t = *auth_user_request ? *auth_user_request : conn->auth_user_request;
+ auth_acl_t result;
+ if (t && t->lastReply != AUTH_ACL_CANNOT_AUTHENTICATE
+ && t->lastReply != AUTH_ACL_HELPER) {
+ if (!*auth_user_request)
+ *auth_user_request = t;
+ return t->lastReply;
+ }
+ /* ok, call the actual authenticator routine. */
+ result = authenticateAuthenticate(auth_user_request, headertype, request, conn, src_addr);
+ t = *auth_user_request ? *auth_user_request : conn->auth_user_request;
+ if (t && result != AUTH_ACL_CANNOT_AUTHENTICATE &&
+ result != AUTH_ACL_HELPER)
+ t->lastReply = result;
+ return result;
+}
+
/* authenticateUserUsername: return a pointer to the username in the */
char *
if ((auth_user_request != NULL) && (auth_user_request->auth_user->auth_module > 0)
&& (authscheme_list[auth_user_request->auth_user->auth_module - 1].AddHeader))
authscheme_list[auth_user_request->auth_user->auth_module - 1].AddHeader(auth_user_request, rep, accelerated);
+ if (auth_user_request != NULL)
+ auth_user_request->lastReply = AUTH_ACL_CANNOT_AUTHENTICATE;
}
/* call the active auth module and allow it to add a trailer to the request */
/*
- * $Id: client_side.cc,v 1.594 2002/09/24 11:31:19 robertc Exp $
+ * $Id: client_side.cc,v 1.595 2002/09/26 13:33:08 robertc Exp $
*
* DEBUG: section 33 Client-side Routines
* AUTHOR: Duane Wessels
static int connKeepReadingIncompleteRequest(ConnStateData * conn);
static void connCancelIncompleteRequests(ConnStateData * conn);
static ConnStateData *connStateCreate(struct sockaddr_in peer, struct sockaddr_in me, int fd);
-static clientStreamNode * getClientReplyContext(clientSocketContext * context);
+static clientStreamNode *getClientReplyContext(clientSocketContext * context);
static int connAreAllContextsForThisConnection(ConnStateData * connState);
static void connFreeAllContexts(ConnStateData * connState);
static void clientPullData(clientSocketContext * context);
assert(http != NULL);
request = http->request;
debug(33, 3) ("httpRequestFree: %s\n", http->uri);
- /* FIXME: This needs to use the stream */
- if (!clientCheckTransferDone(http)) {
- if (request && request->body_connection)
- clientAbortBody(request); /* abort body transter */
- /* the ICP check here was erroneous
- * - storeReleaseRequest was always called if entry was valid
- */
- }
+ /* if body_connection !NULL, then ProcessBody has not
+ * found the end of the body yet
+ */
+ if (request && request->body_connection)
+ clientAbortBody(request); /* abort body transter */
+ /* the ICP check here was erroneous
+ * - storeReleaseRequest was always called if entry was valid
+ */
assert(http->logType < LOG_TYPE_MAX);
clientLogRequest(http);
if (request)
/* init mb; put status line and headers if any */
if (rep) {
mb = httpReplyPack(rep);
+ /* Save length of headers for persistent conn checks */
+ context->http->out.headers_sz = mb.size;
#if HEADERS_LOG
headersLog(0, 0, context->http->request->method, rep);
#endif
/*
- * $Id: client_side_reply.cc,v 1.8 2002/09/24 12:09:24 robertc Exp $
+ * $Id: client_side_reply.cc,v 1.9 2002/09/26 13:33:08 robertc Exp $
*
* DEBUG: section 88 Client-side Reply Routines
* AUTHOR: Robert Collins (Originally Duane Wessels in client_side.c)
static void startError(clientReplyContext * context, clientHttpRequest * http, ErrorState * err);
static void triggerStoreReadWithClientParameters(clientReplyContext * context, clientHttpRequest * http);
-
+static int clientCheckTransferDone(clientReplyContext * context);
/* The clientReply clean interface */
/* privates */
#define SENDING_BODY 0
#define SENDING_HDRSONLY 1
int
-clientCheckTransferDone(clientHttpRequest const *http)
+clientCheckTransferDone(clientReplyContext * context)
{
+ clientHttpRequest *http = context->http;
int sending = SENDING_BODY;
StoreEntry *entry = http->entry;
MemObject *mem;
* Handle STORE_OK objects.
* objectLen(entry) will be set proprely.
* RC: Does objectLen(entry) include the Headers?
+ * RC: Yes.
*/
if (entry->store_status == STORE_OK) {
- if (http->out.offset >= objectLen(entry))
+ if (http->out.offset >= objectLen(entry) - context->headers_sz)
return 1;
else
return 0;
mem = entry->mem_obj;
assert(mem != NULL);
assert(http->request != NULL);
+ /* mem->reply was wrong because it uses the UPSTREAM header length!!! */
reply = mem->reply;
- if (reply->hdr_sz == 0)
+ if (context->headers_sz == 0)
return 0; /* haven't found end of headers yet */
else if (reply->sline.status == HTTP_OK)
sending = SENDING_BODY;
* If we are sending a body and we don't have a content-length,
* then we must wait for the object to become STORE_OK.
*/
- if (sending == SENDING_HDRSONLY)
- sendlen = reply->hdr_sz;
- else if (reply->content_length < 0)
+ sendlen = http->out.headers_sz;
+ if (reply->content_length < 0)
return 0;
else
- sendlen = reply->content_length + reply->hdr_sz;
+ sendlen += reply->content_length;
/*
* Now that we have the expected length, did we send it all?
*/
- if (http->out.offset < sendlen)
+ if (http->out.size < sendlen)
return 0;
else
return 1;
* complete. Should we tcp reset such connections ?
*/
return STREAM_FAILED;
- if ((done = clientCheckTransferDone(http)) != 0 || context->flags.complete) {
+ if ((done = clientCheckTransferDone(context)) != 0 || context->flags.complete) {
debug(88, 5) ("clientReplyStatus: transfer is DONE\n");
/* Ok we're finished, but how? */
if (httpReplyBodySize(http->request->method,
http->entry->mem_obj->reply) < 0) {
- debug(88, 5) ("clientWriteComplete: closing, content_length < 0\n");
+ debug(88, 5) ("clientReplyStatus: closing, content_length < 0\n");
return STREAM_FAILED;
- } else if (!done) {
- debug(88, 5) ("clientWriteComplete: closing, !done, but read 0 bytes\n");
+ }
+ if (!done) {
+ debug(88, 5) ("clientReplyStatus: closing, !done, but read 0 bytes\n");
return STREAM_FAILED;
- } else if (clientGotNotEnough(http)) {
- debug(88, 5) ("clientWriteComplete: client didn't get all it expected\n");
+ }
+ if (clientGotNotEnough(http)) {
+ debug(88, 5) ("clientReplyStatus: client didn't get all it expected\n");
return STREAM_UNPLANNED_COMPLETE;
- } else if (http->request->flags.proxy_keepalive) {
+ }
+ if (http->request->flags.proxy_keepalive) {
+ debug(88, 5) ("clientReplyStatus: stream complete and can keepalive\n");
return STREAM_COMPLETE;
}
+ debug(88, 5) ("clientReplyStatus: stream was not expected to complete!\n");
return STREAM_UNPLANNED_COMPLETE;
-
}
- if (clientReplyBodyTooLarge(http->entry->mem_obj->reply, http->out.offset))
+ if (clientReplyBodyTooLarge(http->entry->mem_obj->reply, http->out.offset)) {
+ debug(88, 5) ("clientReplyStatus: client reply body is too large\n");
return STREAM_FAILED;
+ }
return STREAM_NONE;
}
(int) body_size, rep->hdr_sz);
ch = aclChecklistCreate(Config.accessList.reply, http->request, NULL);
ch->reply = rep;
+ if (http->conn)
+ ch->conn = cbdataReference(http->conn); /* acl.c frees */
rv = aclCheckFast(Config.accessList.reply, ch);
aclChecklistFree(ch);
ch = NULL;
/*
- * $Id: protos.h,v 1.447 2002/09/24 10:46:42 robertc Exp $
+ * $Id: protos.h,v 1.448 2002/09/26 13:33:08 robertc Exp $
*
*
* SQUID Web Proxy Cache http://www.squid-cache.org/
extern void httpRequestFree(void *);
/* client_side_reply.c - client side reply related routines (pure logic, no comms) */
-extern int clientCheckTransferDone(clientHttpRequest const *);
extern void *clientReplyNewContext(clientHttpRequest *);
extern int clientHttpRequestStatus(int fd, clientHttpRequest const *http);
extern void clientSetReplyToError(void *, err_type, http_status, method_t, char const *, struct in_addr *, request_t *, char *, auth_user_request_t * auth_user_request);
extern void authenticateShutdown(void);
extern void authenticateFixHeader(HttpReply *, auth_user_request_t *, request_t *, int, int);
extern void authenticateAddTrailer(HttpReply *, auth_user_request_t *, request_t *, int);
-extern auth_acl_t authenticateAuthenticate(auth_user_request_t **, http_hdr_type, request_t *, ConnStateData *, struct in_addr);
+extern auth_acl_t authenticateTryToAuthenticateAndSetAuthUser(auth_user_request_t **, http_hdr_type, request_t *, ConnStateData *, struct in_addr);
extern void authenticateAuthUserUnlock(auth_user_t * auth_user);
extern void authenticateAuthUserLock(auth_user_t * auth_user);
extern void authenticateAuthUserRequestUnlock(auth_user_request_t *);
/*
- * $Id: store_client.cc,v 1.113 2002/09/24 10:46:42 robertc Exp $
+ * $Id: store_client.cc,v 1.114 2002/09/26 13:33:08 robertc Exp $
*
* DEBUG: section 20 Storage Manager Client-Side Interface
* AUTHOR: Duane Wessels
assert(!EBIT_TEST(e->flags, ENTRY_ABORTED));
debug(20, 3) ("storeClientCopy: %s, from %lu, for length %d, cb %p, cbdata %p\n",
storeKeyText(e->hash.key),
- copyInto.offset,
+ (unsigned long) copyInto.offset,
copyInto.length,
callback,
data);
MemObject *mem = e->mem_obj;
size_t sz;
- debug(33, 5) ("co: %lu, hi: %ld\n", sc->copyInto.offset, (long int) mem->inmem_hi);
+ debug(33, 5) ("co: %lu, hi: %ld\n", (unsigned long) sc->copyInto.offset, (long int) mem->inmem_hi);
if (storeClientNoMoreToSend(e, sc)) {
/* There is no more to send! */
return;
storeAppendPrintf(output, "\tClient #%d, %p\n", clientNumber, thisClient->callback_data);
storeAppendPrintf(output, "\t\tcopy_offset: %lu\n",
- thisClient->copyInto.offset);
+ (unsigned long) thisClient->copyInto.offset);
storeAppendPrintf(output, "\t\tcopy_size: %d\n",
(int) thisClient->copyInto.length);
storeAppendPrintf(output, "\t\tflags:");
/*
- * $Id: structs.h,v 1.431 2002/09/24 10:46:42 robertc Exp $
+ * $Id: structs.h,v 1.432 2002/09/26 13:33:08 robertc Exp $
*
*
* SQUID Web Proxy Cache http://www.squid-cache.org/
void *scheme_data;
/* how many 'processes' are working on this data */
size_t references;
+ /* We only attempt authentication once per http request. This
+ * is to allow multiple auth acl references from different _access areas
+ * when using connection based authentication
+ */
+ auth_acl_t lastReply;
};
struct {
off_t offset;
size_t size;
+ size_t headers_sz;
} out;
HttpHdrRangeIter range_iter; /* data for iterating thru range specs */
size_t req_sz; /* raw request size on input, not current request size */