From: robertc <> Date: Thu, 26 Sep 2002 19:33:07 +0000 (+0000) Subject: fix http_reply_access with authentication, delay_access with authentication, persiste... X-Git-Tag: SQUID_3_0_PRE1~731 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=0e3be1eae2a4bd4f662de4d8aad39073e6946865;p=thirdparty%2Fsquid.git fix http_reply_access with authentication, delay_access with authentication, persistent connections on cache hits, and format glitches for BSD types --- diff --git a/src/acl.cc b/src/acl.cc index 2ea7f13407..1aa73c4b06 100644 --- a/src/acl.cc +++ b/src/acl.cc @@ -1,6 +1,6 @@ /* - * $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 @@ -1405,7 +1405,7 @@ aclAuthenticated(aclCheck_t * checklist) } /* 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; diff --git a/src/authenticate.cc b/src/authenticate.cc index 09a2aa79c2..f44bc41f76 100644 --- a/src/authenticate.cc +++ b/src/authenticate.cc @@ -1,6 +1,6 @@ /* - * $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 @@ -44,6 +44,7 @@ CBDATA_TYPE(auth_user_ip_t); 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); /* * @@ -424,6 +425,7 @@ authenticateAuthenticate(auth_user_request_t ** auth_user_request, http_hdr_type { const char *proxy_auth; assert(headertype != 0); + proxy_auth = httpHeaderGetStr(&request->header, headertype); if (conn == NULL) { @@ -571,6 +573,27 @@ authenticateAuthenticate(auth_user_request_t ** auth_user_request, http_hdr_type 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 * @@ -733,6 +756,8 @@ authenticateFixHeader(HttpReply * rep, auth_user_request_t * auth_user_request, 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 */ diff --git a/src/client_side.cc b/src/client_side.cc index 16cabb77c1..041dc8c9b9 100644 --- a/src/client_side.cc +++ b/src/client_side.cc @@ -1,6 +1,6 @@ /* - * $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 @@ -171,7 +171,7 @@ static void connNoteUseOfBuffer(ConnStateData * conn, int byteCount); 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); @@ -412,14 +412,14 @@ httpRequestFree(void *data) 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) @@ -608,6 +608,8 @@ contextSendStartOfMessage(clientSocketContext * context, HttpReply * rep, StoreI /* 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 diff --git a/src/client_side_reply.cc b/src/client_side_reply.cc index ca6061a28e..3cba466583 100644 --- a/src/client_side_reply.cc +++ b/src/client_side_reply.cc @@ -1,6 +1,6 @@ /* - * $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) @@ -90,7 +90,7 @@ extern ErrorState *clientBuildError(err_type, http_status, char const *, 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 */ @@ -886,8 +886,9 @@ clientTraceReply(clientStreamNode * node, clientReplyContext * context) #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; @@ -905,9 +906,10 @@ clientCheckTransferDone(clientHttpRequest const *http) * 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; @@ -918,8 +920,9 @@ clientCheckTransferDone(clientHttpRequest const *http) 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; @@ -938,16 +941,15 @@ clientCheckTransferDone(clientHttpRequest const *http) * 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; @@ -1026,27 +1028,33 @@ clientReplyStatus(clientStreamNode * this, clientHttpRequest * http) * 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; } @@ -1496,6 +1504,8 @@ clientSendMoreData(void *data, StoreIOBuffer result) (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; diff --git a/src/protos.h b/src/protos.h index 6ad0c1d0bb..f9ec8550ad 100644 --- a/src/protos.h +++ b/src/protos.h @@ -1,6 +1,6 @@ /* - * $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/ @@ -145,7 +145,6 @@ extern int clientAbortBody(request_t * req); 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); @@ -755,7 +754,7 @@ extern void authenticateInit(authConfig *); 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 *); diff --git a/src/store_client.cc b/src/store_client.cc index 9f9ef31f83..a606bcdbce 100644 --- a/src/store_client.cc +++ b/src/store_client.cc @@ -1,6 +1,6 @@ /* - * $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 @@ -191,7 +191,7 @@ storeClientCopy(store_client * sc, 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); @@ -275,7 +275,7 @@ storeClientCopy3(StoreEntry * e, store_client * sc) 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! */ @@ -695,7 +695,7 @@ storeClientDumpStats(store_client * thisClient, StoreEntry * output, int clientN 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:"); diff --git a/src/structs.h b/src/structs.h index 763663c711..ee1b466528 100644 --- a/src/structs.h +++ b/src/structs.h @@ -1,6 +1,6 @@ /* - * $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/ @@ -138,6 +138,11 @@ struct _auth_user_request_t { 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; }; @@ -1056,6 +1061,7 @@ struct _clientHttpRequest { 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 */