Index: squid/src/authenticate.c diff -c squid/src/authenticate.c:1.36.2.10 squid/src/authenticate.c:1.36.2.11 *** squid/src/authenticate.c:1.36.2.10 Sun May 18 15:49:19 2003 --- squid/src/authenticate.c Wed Feb 4 10:42:28 2004 *************** *** 463,468 **** --- 463,469 ---- } return AUTH_ACL_CHALLENGE; } + #if 0 /* * Is this an already authenticated connection with a new auth header? * No check for function required in the if: its compulsory for conn based *************** *** 487,492 **** --- 488,494 ---- /* Set the connection auth type */ conn->auth_type = AUTH_UNKNOWN; } + #endif /* we have a proxy auth header and as far as we know this connection has * not had bungled connection oriented authentication happen on it. */ debug(28, 9) ("authenticateAuthenticate: header %s.\n", proxy_auth ? proxy_auth : NULL); Index: squid/src/cf.data.pre diff -c squid/src/cf.data.pre:1.245.2.59 squid/src/cf.data.pre:1.245.2.60 *** squid/src/cf.data.pre:1.245.2.59 Tue Feb 3 07:33:40 2004 --- squid/src/cf.data.pre Wed Feb 4 10:42:28 2004 *************** *** 1439,1444 **** --- 1439,1462 ---- AND the number of reused challenges. auth_param ntlm max_challenge_lifetime 2 minutes + "use_ntlm_negotiate" on|off + Enables support for NTLM NEGOTIATE packet exchanges with the + helper. The configured ntlm authenticator must be able to handle + NTLM NEGOTIATE packet, see the authenticator's documentation for + more details. + This is required for support of NTLMv2 and a number of other + negotiable options, and also makes it more likely the negotiation + is successful. + Enabling this parameter will also solve problems encountered when + NT domain policies restrict users to access only certain + workstations. When this is off, all users must be allowed to log + on the proxy servers too, or they'll get "invalid workstation" + errors - and access denied - when trying to use Squid's services. + Use of ntlm NEGOTIATE is incompatible with challenge reuse, so + enabling this parameter will OVERRIDE the max_challenge_reuses and + max_challenge_lifetime parameters and set them to 0. + auth_param ntlm use_ntlm_negotiate off + NOCOMMENT_START #Recommended minimum configuration: #auth_param digest program *************** *** 1451,1456 **** --- 1469,1475 ---- #auth_param ntlm children 5 #auth_param ntlm max_challenge_reuses 0 #auth_param ntlm max_challenge_lifetime 2 minutes + #auth_param ntlm use_ntlm_negotiate off #auth_param basic program auth_param basic children 5 auth_param basic realm Squid proxy-caching web server Index: squid/src/enums.h diff -c squid/src/enums.h:1.203.2.9 squid/src/enums.h:1.203.2.10 *** squid/src/enums.h:1.203.2.9 Fri Dec 19 09:34:23 2003 --- squid/src/enums.h Wed Feb 4 10:42:28 2004 *************** *** 529,542 **** AUTH_BROKEN /* known type, but broken data */ } auth_type_t; - /* stateful helper callback response codes */ - typedef enum { - S_HELPER_UNKNOWN, - S_HELPER_RESERVE, - S_HELPER_RELEASE, - S_HELPER_DEFER - } stateful_helper_callback_t; - /* stateful helper reservation info */ typedef enum { S_HELPER_FREE, /* available for requests */ --- 529,534 ---- Index: squid/src/helper.c diff -c squid/src/helper.c:1.34.2.13 squid/src/helper.c:1.34.2.15 *** squid/src/helper.c:1.34.2.13 Fri Sep 12 14:30:16 2003 --- squid/src/helper.c Mon Feb 9 02:03:49 2004 *************** *** 53,61 **** static void helperRequestFree(helper_request * r); static void helperStatefulRequestFree(helper_stateful_request * r); static void StatefulEnqueue(statefulhelper * hlp, helper_stateful_request * r); - static helper_stateful_request *StatefulServerDequeue(helper_stateful_server * srv); - static void StatefulServerEnqueue(helper_stateful_server * srv, helper_stateful_request * r); - static void helperStatefulServerKickQueue(helper_stateful_server * srv); void helperOpenServers(helper * hlp) --- 53,58 ---- *************** *** 184,195 **** srv = cbdataAlloc(helper_stateful_server); srv->pid = x; srv->flags.alive = 1; ! srv->flags.reserved = S_HELPER_FREE; ! srv->deferred_requests = 0; ! srv->stats.deferbyfunc = 0; ! srv->stats.deferbycb = 0; srv->stats.submits = 0; - srv->stats.releases = 0; srv->index = k; srv->rfd = rfd; srv->wfd = wfd; --- 181,188 ---- srv = cbdataAlloc(helper_stateful_server); srv->pid = x; srv->flags.alive = 1; ! srv->flags.reserved = 0; srv->stats.submits = 0; srv->index = k; srv->rfd = rfd; srv->wfd = wfd; *************** *** 243,256 **** debug(84, 9) ("helperSubmit: %s\n", buf); } - /* lastserver = "server last used as part of a deferred or reserved - * request sequence" - */ void ! helperStatefulSubmit(statefulhelper * hlp, const char *buf, HLPSCB * callback, void *data, helper_stateful_server * lastserver) { helper_stateful_request *r = memAllocate(MEM_HELPER_STATEFUL_REQUEST); - helper_stateful_server *srv; if (hlp == NULL) { debug(84, 3) ("helperStatefulSubmit: hlp == NULL\n"); callback(data, 0, NULL); --- 236,245 ---- debug(84, 9) ("helperSubmit: %s\n", buf); } void ! helperStatefulSubmit(statefulhelper * hlp, const char *buf, HLPSCB * callback, void *data, helper_stateful_server * srv) { helper_stateful_request *r = memAllocate(MEM_HELPER_STATEFUL_REQUEST); if (hlp == NULL) { debug(84, 3) ("helperStatefulSubmit: hlp == NULL\n"); callback(data, 0, NULL); *************** *** 258,366 **** } r->callback = callback; r->data = data; ! if (buf != NULL) { r->buf = xstrdup(buf); - r->placeholder = 0; - } else { - r->buf = NULL; - r->placeholder = 1; - } cbdataLock(r->data); ! if ((buf != NULL) && lastserver) { ! debug(84, 5) ("StatefulSubmit with lastserver %p\n", lastserver); ! /* the queue doesn't count for this assert because queued requests ! * have already gone through here and been tested. ! * It's legal to have deferred_requests == 0 and queue entries ! * and status of S_HELPEER_DEFERRED. ! * BUT: It's not legal to submit a new request w/lastserver in ! * that state. ! */ ! assert(!(lastserver->deferred_requests == 0 && ! lastserver->flags.reserved == S_HELPER_DEFERRED)); ! if (lastserver->flags.reserved != S_HELPER_RESERVED) { ! lastserver->stats.submits++; ! lastserver->deferred_requests--; ! } ! if (!(lastserver->request)) { ! debug(84, 5) ("StatefulSubmit dispatching\n"); ! helperStatefulDispatch(lastserver, r); ! } else { ! debug(84, 5) ("StatefulSubmit queuing\n"); ! StatefulServerEnqueue(lastserver, r); ! } } else { ! if ((srv = StatefulGetFirstAvailable(hlp))) { ! helperStatefulDispatch(srv, r); ! } else ! StatefulEnqueue(hlp, r); } - debug(84, 9) ("helperStatefulSubmit: placeholder: '%d', buf '%s'.\n", r->placeholder, buf); } helper_stateful_server * ! helperStatefulDefer(statefulhelper * hlp) ! /* find and add a deferred request to a server */ { ! dlink_node *n; ! helper_stateful_server *srv = NULL, *rv = NULL; if (hlp == NULL) { ! debug(84, 3) ("helperStatefulDefer: hlp == NULL\n"); return NULL; } ! debug(84, 5) ("helperStatefulDefer: Running servers %d.\n", hlp->n_running); if (hlp->n_running == 0) { ! debug(84, 1) ("helperStatefulDefer: No running servers!. \n"); return NULL; } ! rv = srv = StatefulGetFirstAvailable(hlp); ! if (rv == NULL) { ! /* ! * all currently busy; loop through servers and find server ! * with the shortest queue ! */ ! for (n = hlp->servers.head; n != NULL; n = n->next) { ! srv = n->data; ! if (srv->flags.reserved == S_HELPER_RESERVED) ! continue; ! if (!srv->flags.alive) ! continue; ! if ((hlp->IsAvailable != NULL) && (srv->data != NULL) && ! !(hlp->IsAvailable(srv->data))) ! continue; ! if ((rv != NULL) && (rv->deferred_requests < srv->deferred_requests)) ! continue; ! rv = srv; ! } ! } ! if (rv == NULL) { ! debug(84, 1) ("helperStatefulDefer: None available.\n"); ! return NULL; ! } ! /* consistency check: ! * when the deferred count is 0, ! * submits + releases == deferbyfunc + deferbycb ! * Or in english, when there are no deferred requests, the amount ! * we have submitted to the queue or cancelled must equal the amount ! * we have said we wanted to be able to submit or cancel ! */ ! if (rv->deferred_requests == 0) ! assert(rv->stats.submits + rv->stats.releases == ! rv->stats.deferbyfunc + rv->stats.deferbycb); ! ! rv->flags.reserved = S_HELPER_DEFERRED; ! rv->deferred_requests++; ! rv->stats.deferbyfunc++; ! return rv; } void helperStatefulReset(helper_stateful_server * srv) - /* puts this helper back in the queue. the calling app is required to - * manage the state in the helper. - */ { statefulhelper *hlp = srv->parent; helper_stateful_request *r; r = srv->request; if (r != NULL) { /* reset attempt DURING an outstaning request */ --- 247,296 ---- } r->callback = callback; r->data = data; ! if (buf) r->buf = xstrdup(buf); cbdataLock(r->data); ! if (!srv) ! srv = helperStatefulGetServer(hlp); ! if (srv) { ! debug(84, 5) ("helperStatefulSubmit: sever %p, buf '%s'.\n", srv, buf ? buf : "NULL"); ! assert(!srv->request); ! assert(!srv->flags.busy); ! helperStatefulDispatch(srv, r); } else { ! debug(84, 9) ("helperStatefulSubmit: enqueued, buf '%s'.\n", buf ? buf : "NULL"); ! StatefulEnqueue(hlp, r); } } helper_stateful_server * ! helperStatefulGetServer(statefulhelper * hlp) ! /* find a server for this request */ { ! helper_stateful_server *srv = NULL; if (hlp == NULL) { ! debug(84, 3) ("helperStatefulGetServer: hlp == NULL\n"); return NULL; } ! debug(84, 5) ("helperStatefulGetServer: Running servers %d.\n", hlp->n_running); if (hlp->n_running == 0) { ! debug(84, 1) ("helperStatefulGetServer: No running servers!. \n"); return NULL; } ! srv = StatefulGetFirstAvailable(hlp); ! if (srv) ! srv->flags.reserved = 1; ! debug(84, 5) ("helperStatefulGetServer: Returning %p\n", srv); ! return srv; } + /* puts this helper forcibly back in the queue. */ void helperStatefulReset(helper_stateful_server * srv) { statefulhelper *hlp = srv->parent; helper_stateful_request *r; + debug(84, 5) ("helperStatefulReset: %p\n", srv); r = srv->request; if (r != NULL) { /* reset attempt DURING an outstaning request */ *************** *** 372,402 **** srv->request = NULL; } srv->flags.busy = 0; ! if (srv->queue.head) { ! srv->flags.reserved = S_HELPER_DEFERRED; ! helperStatefulServerKickQueue(srv); } else { - srv->flags.reserved = S_HELPER_FREE; - if ((srv->parent->OnEmptyQueue != NULL) && (srv->data)) - srv->parent->OnEmptyQueue(srv->data); helperStatefulKickQueue(hlp); } } void helperStatefulReleaseServer(helper_stateful_server * srv) - /*decrease the number of 'waiting' clients that set the helper to be DEFERRED */ { ! srv->stats.releases++; ! if (srv->flags.reserved == S_HELPER_DEFERRED) { ! assert(srv->deferred_requests); ! srv->deferred_requests--; ! } ! if (!(srv->deferred_requests) && (srv->flags.reserved == S_HELPER_DEFERRED) && !(srv->queue.head)) { ! srv->flags.reserved = S_HELPER_FREE; ! if ((srv->parent->OnEmptyQueue != NULL) && (srv->data)) ! srv->parent->OnEmptyQueue(srv->data); ! } } void * --- 302,327 ---- srv->request = NULL; } srv->flags.busy = 0; ! srv->flags.reserved = 0; ! if ((srv->parent->Reset != NULL) && (srv->data)) ! srv->parent->Reset(srv->data); ! if (srv->flags.shutdown) { ! int wfd = srv->wfd; ! srv->wfd = -1; ! comm_close(wfd); } else { helperStatefulKickQueue(hlp); } } + /* puts this helper back in the queue. */ void helperStatefulReleaseServer(helper_stateful_server * srv) { ! debug(84, 5) ("helperStatefulReleaseServer: %p\n", srv); ! assert(!srv->request); ! assert(srv->flags.reserved); ! helperStatefulReset(srv); } void * *************** *** 475,486 **** storeAppendPrintf(sentry, "avg service time: %d msec\n", hlp->stats.avg_svc_time); storeAppendPrintf(sentry, "\n"); ! storeAppendPrintf(sentry, "%7s\t%7s\t%7s\t%11s\t%20s\t%s\t%7s\t%7s\t%7s\n", "#", "FD", "PID", "# Requests", - "# Deferred Requests", "Flags", "Time", "Offset", --- 400,410 ---- storeAppendPrintf(sentry, "avg service time: %d msec\n", hlp->stats.avg_svc_time); storeAppendPrintf(sentry, "\n"); ! storeAppendPrintf(sentry, "%7s\t%7s\t%7s\t%11s\t%s\t%7s\t%7s\t%7s\n", "#", "FD", "PID", "# Requests", "Flags", "Time", "Offset", *************** *** 488,505 **** for (link = hlp->servers.head; link; link = link->next) { srv = link->data; tt = 0.001 * tvSubMsec(srv->dispatch_time, current_time); ! storeAppendPrintf(sentry, "%7d\t%7d\t%7d\t%11d\t%20d\t%c%c%c%c%c%c\t%7.3f\t%7d\t%s\n", srv->index + 1, srv->rfd, srv->pid, srv->stats.uses, - (int) srv->deferred_requests, srv->flags.alive ? 'A' : ' ', srv->flags.busy ? 'B' : ' ', srv->flags.closing ? 'C' : ' ', ! srv->flags.reserved != S_HELPER_FREE ? 'R' : ' ', srv->flags.shutdown ? 'S' : ' ', - srv->request ? (srv->request->placeholder ? 'P' : ' ') : ' ', tt < 0.0 ? 0.0 : tt, (int) srv->offset, srv->request ? log_quote(srv->request->buf) : "(none)"); --- 412,427 ---- for (link = hlp->servers.head; link; link = link->next) { srv = link->data; tt = 0.001 * tvSubMsec(srv->dispatch_time, current_time); ! storeAppendPrintf(sentry, "%7d\t%7d\t%7d\t%11d\t%c%c%c%c%c\t%7.3f\t%7d\t%s\n", srv->index + 1, srv->rfd, srv->pid, srv->stats.uses, srv->flags.alive ? 'A' : ' ', srv->flags.busy ? 'B' : ' ', srv->flags.closing ? 'C' : ' ', ! srv->flags.reserved ? 'R' : ' ', srv->flags.shutdown ? 'S' : ' ', tt < 0.0 ? 0.0 : tt, (int) srv->offset, srv->request ? log_quote(srv->request->buf) : "(none)"); *************** *** 570,585 **** hlp->id_name, srv->index + 1); continue; } ! if (srv->flags.reserved != S_HELPER_FREE) { debug(84, 3) ("helperStatefulShutdown: %s #%d is RESERVED.\n", hlp->id_name, srv->index + 1); continue; } - if (srv->deferred_requests) { - debug(84, 3) ("helperStatefulShutdown: %s #%d has DEFERRED requests.\n", - hlp->id_name, srv->index + 1); - continue; - } srv->flags.closing = 1; wfd = srv->wfd; srv->wfd = -1; --- 492,502 ---- hlp->id_name, srv->index + 1); continue; } ! if (srv->flags.reserved) { debug(84, 3) ("helperStatefulShutdown: %s #%d is RESERVED.\n", hlp->id_name, srv->index + 1); continue; } srv->flags.closing = 1; wfd = srv->wfd; srv->wfd = -1; *************** *** 747,757 **** /* end of reply found */ debug(84, 3) ("helperHandleRead: end of reply found\n"); *t = '0円'; - if (cbdataValid(r->data)) - r->callback(r->data, srv->buf); srv->flags.busy = 0; srv->offset = 0; - helperRequestFree(r); srv->request = NULL; hlp->stats.replies++; srv->answer_time = current_time; --- 664,671 ---- *************** *** 759,769 **** intAverage(hlp->stats.avg_svc_time, tvSubUsec(srv->dispatch_time, current_time), hlp->stats.replies, REDIRECT_AV_FACTOR); ! if (srv->flags.shutdown) { ! int wfd = srv->wfd; ! srv->wfd = -1; ! comm_close(wfd); ! } else helperKickQueue(hlp); } else { commSetSelect(srv->rfd, COMM_SELECT_READ, helperHandleRead, srv, 0); --- 673,682 ---- intAverage(hlp->stats.avg_svc_time, tvSubUsec(srv->dispatch_time, current_time), hlp->stats.replies, REDIRECT_AV_FACTOR); ! if (cbdataValid(r->data)) ! r->callback(r->data, srv->buf); ! helperRequestFree(r); ! if (!srv->flags.shutdown) helperKickQueue(hlp); } else { commSetSelect(srv->rfd, COMM_SELECT_READ, helperHandleRead, srv, 0); *************** *** 803,870 **** /* end of reply found */ debug(84, 3) ("helperStatefulHandleRead: end of reply found\n"); *t = '0円'; - if (cbdataValid(r->data)) { - switch ((r->callback(r->data, srv, srv->buf))) { /*if non-zero reserve helper */ - case S_HELPER_UNKNOWN: - fatal("helperStatefulHandleRead: either a non-state aware callback was give to the stateful helper routines, or an uninitialised callback response was recieved.\n"); - break; - case S_HELPER_RELEASE: /* helper finished with */ - if (!srv->deferred_requests && !srv->queue.head) { - srv->flags.reserved = S_HELPER_FREE; - if ((srv->parent->OnEmptyQueue != NULL) && (srv->data)) - srv->parent->OnEmptyQueue(srv->data); - debug(84, 5) ("StatefulHandleRead: releasing %s #%d\n", hlp->id_name, srv->index + 1); - } else { - srv->flags.reserved = S_HELPER_DEFERRED; - debug(84, 5) ("StatefulHandleRead: outstanding deferred requests on %s #%d. reserving for deferred requests.\n", hlp->id_name, srv->index + 1); - } - break; - case S_HELPER_RESERVE: /* 'pin' this helper for the caller */ - if (!srv->queue.head) { - assert(srv->deferred_requests == 0); - srv->flags.reserved = S_HELPER_RESERVED; - debug(84, 5) ("StatefulHandleRead: reserving %s #%d\n", hlp->id_name, srv->index + 1); - } else { - fatal("StatefulHandleRead: Callback routine attempted to reserve a stateful helper with deferred requests. This can lead to deadlock.\n"); - } - break; - case S_HELPER_DEFER: - /* the helper is still needed, but can - * be used for other requests in the meantime. - */ - srv->flags.reserved = S_HELPER_DEFERRED; - srv->deferred_requests++; - srv->stats.deferbycb++; - debug(84, 5) ("StatefulHandleRead: reserving %s #%d for deferred requests.\n", hlp->id_name, srv->index + 1); - break; - default: - fatal("helperStatefulHandleRead: unknown stateful helper callback result.\n"); - } - - } else { - debug(84, 1) ("StatefulHandleRead: no callback data registered\n"); - } srv->flags.busy = 0; srv->offset = 0; - helperStatefulRequestFree(r); srv->request = NULL; hlp->stats.replies++; hlp->stats.avg_svc_time = intAverage(hlp->stats.avg_svc_time, tvSubMsec(srv->dispatch_time, current_time), hlp->stats.replies, REDIRECT_AV_FACTOR); ! if (srv->flags.shutdown ! && srv->flags.reserved == S_HELPER_FREE ! && !srv->deferred_requests) { ! int wfd = srv->wfd; ! srv->wfd = -1; ! comm_close(wfd); } else { ! if (srv->queue.head) ! helperStatefulServerKickQueue(srv); ! else ! helperStatefulKickQueue(hlp); } } else { commSetSelect(srv->rfd, COMM_SELECT_READ, helperStatefulHandleRead, srv, 0); } --- 716,735 ---- /* end of reply found */ debug(84, 3) ("helperStatefulHandleRead: end of reply found\n"); *t = '0円'; srv->flags.busy = 0; srv->offset = 0; srv->request = NULL; hlp->stats.replies++; hlp->stats.avg_svc_time = intAverage(hlp->stats.avg_svc_time, tvSubMsec(srv->dispatch_time, current_time), hlp->stats.replies, REDIRECT_AV_FACTOR); ! if (cbdataValid(r->data)) { ! r->callback(r->data, srv, srv->buf); } else { ! debug(84, 1) ("StatefulHandleRead: no callback data registered\n"); } + helperStatefulRequestFree(r); } else { commSetSelect(srv->rfd, COMM_SELECT_READ, helperStatefulHandleRead, srv, 0); } *************** *** 878,893 **** hlp->stats.queue_size++; if (hlp->stats.queue_size < hlp->n_running) return; ! if (squid_curtime - hlp->last_queue_warn < 600) return; if (shutting_down || reconfiguring) return; hlp->last_queue_warn = squid_curtime; ! debug(84, 0) ("WARNING: All %s processes are busy.\n", hlp->id_name); ! debug(84, 0) ("WARNING: %d pending requests queued\n", hlp->stats.queue_size); if (hlp->stats.queue_size> hlp->n_running * 2) ! fatalf("Too many queued %s requests", hlp->id_name); ! debug(84, 1) ("Consider increasing the number of %s processes in your config file.\n", hlp->id_name); } static void --- 743,762 ---- hlp->stats.queue_size++; if (hlp->stats.queue_size < hlp->n_running) return; ! if (hlp->stats.queue_size < hlp->n_running) ! return; ! if (squid_curtime - hlp->last_queue_warn < 30) return; if (shutting_down || reconfiguring) return; hlp->last_queue_warn = squid_curtime; ! debug(84, 1) ("WARNING: All %s processes are busy.\n", hlp->id_name); ! debug(84, 1) ("WARNING: up to %d pending requests queued\n", hlp->stats.max_queue_size); if (hlp->stats.queue_size> hlp->n_running * 2) ! fatalf("Too many queued %s requests (%d on %d)", hlp->id_name, hlp->stats.queue_size, hlp->n_running); ! if (hlp->stats.max_queue_size> 1) ! debug(84, 1) ("Consider increasing the number of %s processes to at least %d in your config file.\n", hlp->id_name, hlp->n_running + hlp->stats.max_queue_size); ! hlp->stats.max_queue_size = hlp->stats.queue_size; } static void *************** *** 898,940 **** hlp->stats.queue_size++; if (hlp->stats.queue_size < hlp->n_running) return; ! if (hlp->stats.queue_size> hlp->n_running * 2) ! fatalf("Too many queued %s requests", hlp->id_name); ! if (squid_curtime - hlp->last_queue_warn < 600) return; if (shutting_down || reconfiguring) return; hlp->last_queue_warn = squid_curtime; ! debug(84, 0) ("WARNING: All %s processes are busy.\n", hlp->id_name); ! debug(84, 0) ("WARNING: %d pending requests queued\n", hlp->stats.queue_size); ! debug(84, 1) ("Consider increasing the number of %s processes in your config file.\n", hlp->id_name); } - static void - StatefulServerEnqueue(helper_stateful_server * srv, helper_stateful_request * r) - { - dlink_node *link = memAllocate(MEM_DLINK_NODE); - dlinkAddTail(r, link, &srv->queue); - /* TODO: warning if the queue on this server is more than X - * We don't check the queue size at the moment, because - * requests hitting here are deferrable - */ - /* hlp->stats.queue_size++; - * if (hlp->stats.queue_size < hlp->n_running) - * return; - * if (squid_curtime - hlp->last_queue_warn < 600) - * return; - * if (shutting_down || reconfiguring) - * return; - * hlp->last_queue_warn = squid_curtime; - * debug(84, 0) ("WARNING: All %s processes are busy.\n", hlp->id_name); - * debug(84, 0) ("WARNING: %d pending requests queued\n", hlp->stats.queue_size); - * if (hlp->stats.queue_size> hlp->n_running * 2) - * fatalf("Too many queued %s requests", hlp->id_name); - * debug(84, 1) ("Consider increasing the number of %s processes in your config file.\n", hlp->id_name); */ - } - - static helper_request * Dequeue(helper * hlp) { --- 767,788 ---- hlp->stats.queue_size++; if (hlp->stats.queue_size < hlp->n_running) return; ! if (hlp->stats.queue_size> hlp->stats.max_queue_size) ! hlp->stats.max_queue_size = hlp->stats.queue_size; ! if (hlp->stats.queue_size> hlp->n_running * 5) ! fatalf("Too many queued %s requests (%d on %d)", hlp->id_name, hlp->stats.queue_size, hlp->n_running); ! if (squid_curtime - hlp->last_queue_warn < 30) return; if (shutting_down || reconfiguring) return; hlp->last_queue_warn = squid_curtime; ! debug(84, 1) ("WARNING: All %s processes are busy.\n", hlp->id_name); ! debug(84, 1) ("WARNING: up to %d pending requests queued\n", hlp->stats.max_queue_size); ! if (hlp->stats.max_queue_size> 1) ! debug(84, 1) ("Consider increasing the number of %s processes to at least %d in your config file.\n", hlp->id_name, hlp->n_running + hlp->stats.max_queue_size); ! hlp->stats.max_queue_size = hlp->stats.queue_size; } static helper_request * Dequeue(helper * hlp) { *************** *** 950,968 **** } static helper_stateful_request * - StatefulServerDequeue(helper_stateful_server * srv) - { - dlink_node *link; - helper_stateful_request *r = NULL; - if ((link = srv->queue.head)) { - r = link->data; - dlinkDelete(link, &srv->queue); - memFree(link, MEM_DLINK_NODE); - } - return r; - } - - static helper_stateful_request * StatefulDequeue(statefulhelper * hlp) { dlink_node *link; --- 798,803 ---- *************** *** 1006,1012 **** srv = n->data; if (srv->flags.busy) continue; ! if (srv->flags.reserved == S_HELPER_RESERVED) continue; if (!srv->flags.alive) continue; --- 841,847 ---- srv = n->data; if (srv->flags.busy) continue; ! if (srv->flags.reserved) continue; if (!srv->flags.alive) continue; *************** *** 1057,1088 **** helperStatefulRequestFree(r); return; } ! debug(84, 9) ("helperStatefulDispatch busying helper %s #%d\n", hlp->id_name, srv->index + 1); ! if (r->placeholder == 1) { ! /* a callback is needed before this request can _use_ a helper. */ ! /* we don't care about releasing/deferring this helper. The request NEVER ! * gets to the helper. So we throw away the return code */ ! r->callback(r->data, srv, NULL); ! /* throw away the placeholder */ ! helperStatefulRequestFree(r); ! /* and push the queue. Note that the callback may have submitted a new ! * request to the helper which is why we test for the request*/ ! if (srv->request == NULL) { ! if (srv->flags.shutdown ! && srv->flags.reserved == S_HELPER_FREE ! && !srv->deferred_requests) { ! int wfd = srv->wfd; ! srv->wfd = -1; ! comm_close(wfd); ! } else { ! if (srv->queue.head) ! helperStatefulServerKickQueue(srv); ! else ! helperStatefulKickQueue(hlp); ! } } return; } srv->flags.busy = 1; srv->request = r; srv->dispatch_time = current_time; --- 892,907 ---- helperStatefulRequestFree(r); return; } ! if (!r->buf) { ! if (cbdataValid(r->data)) { ! r->callback(r->data, srv, NULL); ! } else { ! debug(84, 1) ("helperStatefulDispatch: no callback data registered\n"); } + helperStatefulRequestFree(r); return; } + debug(84, 9) ("helperStatefulDispatch busying helper %s #%d\n", hlp->id_name, srv->index + 1); srv->flags.busy = 1; srv->request = r; srv->dispatch_time = current_time; *************** *** 1117,1132 **** { helper_stateful_request *r; helper_stateful_server *srv; ! while ((srv = StatefulGetFirstAvailable(hlp)) && (r = StatefulDequeue(hlp))) ! helperStatefulDispatch(srv, r); ! } ! ! static void ! helperStatefulServerKickQueue(helper_stateful_server * srv) ! { ! helper_stateful_request *r; ! if ((r = StatefulServerDequeue(srv))) helperStatefulDispatch(srv, r); } static void --- 936,945 ---- { helper_stateful_request *r; helper_stateful_server *srv; ! while ((srv = StatefulGetFirstAvailable(hlp)) && (r = StatefulDequeue(hlp))) { ! srv->flags.reserved = 1; helperStatefulDispatch(srv, r); + } } static void Index: squid/src/protos.h diff -c squid/src/protos.h:1.420.2.21 squid/src/protos.h:1.420.2.22 *** squid/src/protos.h:1.420.2.21 Sun Dec 14 05:30:37 2003 --- squid/src/protos.h Wed Feb 4 10:42:28 2004 *************** *** 1274,1280 **** extern void helperStatefulReset(helper_stateful_server * srv); extern void helperStatefulReleaseServer(helper_stateful_server * srv); extern void *helperStatefulServerGetData(helper_stateful_server * srv); ! extern helper_stateful_server *helperStatefulDefer(statefulhelper *); --- 1274,1280 ---- extern void helperStatefulReset(helper_stateful_server * srv); extern void helperStatefulReleaseServer(helper_stateful_server * srv); extern void *helperStatefulServerGetData(helper_stateful_server * srv); ! extern helper_stateful_server *helperStatefulGetServer(statefulhelper *); Index: squid/src/structs.h diff -c squid/src/structs.h:1.408.2.22 squid/src/structs.h:1.408.2.23 *** squid/src/structs.h:1.408.2.22 Tue Feb 3 07:33:40 2004 --- squid/src/structs.h Wed Feb 4 10:42:28 2004 *************** *** 2002,2009 **** struct _helper_stateful_request { char *buf; HLPSCB *callback; - int placeholder; /* if 1, this is a dummy request waiting for a stateful helper - * to become available for deferred requests.*/ void *data; }; --- 2002,2007 ---- *************** *** 2021,2026 **** --- 2019,2025 ---- int requests; int replies; int queue_size; + int max_queue_size; int avg_svc_time; } stats; time_t last_restart; *************** *** 2036,2047 **** int ipc_type; MemPool *datapool; HLPSAVAIL *IsAvailable; ! HLPSONEQ *OnEmptyQueue; time_t last_queue_warn; struct { int requests; int replies; int queue_size; int avg_svc_time; } stats; time_t last_restart; --- 2035,2047 ---- int ipc_type; MemPool *datapool; HLPSAVAIL *IsAvailable; ! HLPSRESET *Reset; time_t last_queue_warn; struct { int requests; int replies; int queue_size; + int max_queue_size; int avg_svc_time; } stats; time_t last_restart; *************** *** 2083,2089 **** struct timeval dispatch_time; struct timeval answer_time; dlink_node link; - dlink_list queue; statefulhelper *parent; helper_stateful_request *request; struct _helper_stateful_flags { --- 2083,2088 ---- *************** *** 2091,2106 **** unsigned int busy:1; unsigned int closing:1; unsigned int shutdown:1; ! stateful_helper_reserve_t reserved; } flags; struct { int uses; int submits; int releases; - int deferbyfunc; - int deferbycb; } stats; - int deferred_requests; /* current number of deferred requests */ void *data; /* State data used by the calling routines */ }; --- 2090,2102 ---- unsigned int busy:1; unsigned int closing:1; unsigned int shutdown:1; ! unsigned int reserved:1; } flags; struct { int uses; int submits; int releases; } stats; void *data; /* State data used by the calling routines */ }; Index: squid/src/typedefs.h diff -c squid/src/typedefs.h:1.132.2.3 squid/src/typedefs.h:1.132.2.4 *** squid/src/typedefs.h:1.132.2.3 Sat Dec 6 10:19:38 2003 --- squid/src/typedefs.h Wed Feb 4 10:42:29 2004 *************** *** 249,257 **** typedef void SIGHDLR(int sig); typedef void STVLDCB(void *, int, int); typedef void HLPCB(void *, char *buf); ! typedef stateful_helper_callback_t HLPSCB(void *, void *lastserver, char *buf); typedef int HLPSAVAIL(void *); ! typedef void HLPSONEQ(void *); typedef void HLPCMDOPTS(int *argc, char **argv); typedef void IDNSCB(void *, rfc1035_rr *, int, const char *); --- 249,257 ---- typedef void SIGHDLR(int sig); typedef void STVLDCB(void *, int, int); typedef void HLPCB(void *, char *buf); ! typedef void HLPSCB(void *, void *lastserver, char *buf); typedef int HLPSAVAIL(void *); ! typedef void HLPSRESET(void *); typedef void HLPCMDOPTS(int *argc, char **argv); typedef void IDNSCB(void *, rfc1035_rr *, int, const char *); Index: squid/src/auth/ntlm/auth_ntlm.c diff -c squid/src/auth/ntlm/auth_ntlm.c:1.17.2.4 squid/src/auth/ntlm/auth_ntlm.c:1.17.2.5 *** squid/src/auth/ntlm/auth_ntlm.c:1.17.2.4 Tue Feb 4 16:17:26 2003 --- squid/src/auth/ntlm/auth_ntlm.c Wed Feb 4 10:42:36 2004 *************** *** 74,80 **** /* helper callbacks to handle per server state data */ static HLPSAVAIL authenticateNTLMHelperServerAvailable; ! static HLPSONEQ authenticateNTLMHelperServerOnEmpty; static statefulhelper *ntlmauthenticators = NULL; --- 74,80 ---- /* helper callbacks to handle per server state data */ static HLPSAVAIL authenticateNTLMHelperServerAvailable; ! static HLPSRESET authenticateNTLMHelperServerReset; static statefulhelper *ntlmauthenticators = NULL; *************** *** 148,157 **** storeAppendPrintf(entry, " %s", list->key); list = list->next; } ! storeAppendPrintf(entry, "\n%s %s children %d\n%s %s max_challenge_reuses %d\n%s %s max_challenge_lifetime %d seconds\n", name, "ntlm", config->authenticateChildren, name, "ntlm", config->challengeuses, ! name, "ntlm", (int) config->challengelifetime); } --- 148,158 ---- storeAppendPrintf(entry, " %s", list->key); list = list->next; } ! storeAppendPrintf(entry, "\n%s %s children %d\n%s %s max_challenge_reuses %d\n%s %s max_challenge_lifetime %d seconds\n%s %s use_ntlm_negotiate %s\n", name, "ntlm", config->authenticateChildren, name, "ntlm", config->challengeuses, ! name, "ntlm", (int) config->challengelifetime, ! name, "ntlm", config->use_ntlm_negotiate ? "on" : "off"); } *************** *** 167,172 **** --- 168,174 ---- ntlmConfig->authenticateChildren = 5; ntlmConfig->challengeuses = 0; ntlmConfig->challengelifetime = 60; + ntlmConfig->use_ntlm_negotiate = 0; } ntlmConfig = scheme->scheme_data; if (strcasecmp(param_str, "program") == 0) { *************** *** 180,185 **** --- 182,189 ---- parse_int(&ntlmConfig->challengeuses); } else if (strcasecmp(param_str, "max_challenge_lifetime") == 0) { parse_time_t(&ntlmConfig->challengelifetime); + } else if (strcasecmp(param_str, "use_ntlm_negotiate") == 0) { + parse_onoff(&ntlmConfig->use_ntlm_negotiate); } else { debug(28, 0) ("unrecognised ntlm auth scheme parameter '%s'\n", param_str); } *************** *** 191,198 **** * state will be preserved. Caveats: this should be a post-parse * test, but that can wait for the modular parser to be integrated. */ ! if (ntlmConfig->authenticate) Config.onoff.pipeline_prefetch = 0; } --- 195,207 ---- * state will be preserved. Caveats: this should be a post-parse * test, but that can wait for the modular parser to be integrated. */ ! if (ntlmConfig->authenticate && Config.onoff.pipeline_prefetch != 0) Config.onoff.pipeline_prefetch = 0; + + if (ntlmConfig->use_ntlm_negotiate && ntlmConfig->challengeuses> 0) { + debug(28, 1) ("challenge reuses incompatible with use_ntlm_negotiate. Disabling challenge reuse\n"); + ntlmConfig->challengeuses = 0; + } } *************** *** 245,251 **** ntlmauthenticators->ipc_type = IPC_TCP_SOCKET; ntlmauthenticators->datapool = ntlm_helper_state_pool; ntlmauthenticators->IsAvailable = authenticateNTLMHelperServerAvailable; ! ntlmauthenticators->OnEmptyQueue = authenticateNTLMHelperServerOnEmpty; helperStatefulOpenServers(ntlmauthenticators); /* * TODO: In here send the initial YR to preinitialise the --- 254,260 ---- ntlmauthenticators->ipc_type = IPC_TCP_SOCKET; ntlmauthenticators->datapool = ntlm_helper_state_pool; ntlmauthenticators->IsAvailable = authenticateNTLMHelperServerAvailable; ! ntlmauthenticators->Reset = authenticateNTLMHelperServerReset; helperStatefulOpenServers(ntlmauthenticators); /* * TODO: In here send the initial YR to preinitialise the *************** *** 364,370 **** xfree(ntlm_request->authchallenge); if (ntlm_request->ntlmauthenticate) xfree(ntlm_request->ntlmauthenticate); ! if (ntlm_request->authserver != NULL && ntlm_request->authserver_deferred) { debug(29, 9) ("authenticateNTLMRequestFree: releasing server '%p'\n", ntlm_request->authserver); helperStatefulReleaseServer(ntlm_request->authserver); ntlm_request->authserver = NULL; --- 373,379 ---- xfree(ntlm_request->authchallenge); if (ntlm_request->ntlmauthenticate) xfree(ntlm_request->ntlmauthenticate); ! if (ntlm_request->authserver != NULL) { debug(29, 9) ("authenticateNTLMRequestFree: releasing server '%p'\n", ntlm_request->authserver); helperStatefulReleaseServer(ntlm_request->authserver); ntlm_request->authserver = NULL; *************** *** 407,417 **** auth_user->scheme_data = NULL; } ! static stateful_helper_callback_t ! authenticateNTLMHandleplaceholder(void *data, void *lastserver, char *reply) { authenticateStateData *r = data; - stateful_helper_callback_t result = S_HELPER_UNKNOWN; int valid; /* we should only be called for placeholder requests - which have no reply string */ assert(reply == NULL); --- 416,447 ---- auth_user->scheme_data = NULL; } ! /* clear the NTLM helper of being reserved for future requests */ ! static void ! authenticateNTLMReleaseServer(ntlm_request_t * ntlm_request) ! { ! helper_stateful_server *server = ntlm_request->authserver; ! debug(29, 9) ("authenticateNTLMReleaseServer: releasing server '%p'\n", server); ! ntlm_request->authserver = NULL; ! helperStatefulReleaseServer(server); ! } ! ! /* clear the NTLM helper of being reserved for future requests */ ! static void ! authenticateNTLMResetServer(ntlm_request_t * ntlm_request) ! { ! helper_stateful_server *server = ntlm_request->authserver; ! ntlm_helper_state_t *helperstate = helperStatefulServerGetData(server); ! debug(29, 9) ("authenticateNTLMReleaseServer: releasing server '%p'\n", server); ! ntlm_request->authserver = NULL; ! helperstate->starve = 1; ! helperStatefulReleaseServer(server); ! } ! ! static void ! authenticateNTLMHandleplaceholder(void *data, void *srv, char *reply) { authenticateStateData *r = data; int valid; /* we should only be called for placeholder requests - which have no reply string */ assert(reply == NULL); *************** *** 419,455 **** /* standard callback stuff */ valid = cbdataValid(r->data); if (!valid) { ! debug(29, 1) ("AuthenticateNTLMHandlePlacheholder: invalid callback data.\n"); ! return result; } /* call authenticateNTLMStart to retry this request */ debug(29, 9) ("authenticateNTLMHandleplaceholder: calling authenticateNTLMStart\n"); authenticateNTLMStart(r->auth_user_request, r->handler, r->data); cbdataUnlock(r->data); authenticateStateFree(r); - return result; } ! static stateful_helper_callback_t ! authenticateNTLMHandleReply(void *data, void *lastserver, char *reply) { authenticateStateData *r = data; ntlm_helper_state_t *helperstate; int valid; - stateful_helper_callback_t result = S_HELPER_UNKNOWN; - char *t = NULL; auth_user_request_t *auth_user_request; auth_user_t *auth_user; ntlm_user_t *ntlm_user; ntlm_request_t *ntlm_request; ! debug(29, 9) ("authenticateNTLMHandleReply: Helper: '%p' {%s}\n", lastserver, reply ? reply : ""); valid = cbdataValid(r->data); if (!valid) { ! debug(29, 1) ("AuthenticateNTLMHandleReply: invalid callback data. Releasing helper '%p'.\n", lastserver); cbdataUnlock(r->data); authenticateStateFree(r); ! debug(29, 9) ("NTLM HandleReply, telling stateful helper : %d\n", S_HELPER_RELEASE); ! return S_HELPER_RELEASE; } if (!reply) { /* --- 449,484 ---- /* standard callback stuff */ valid = cbdataValid(r->data); if (!valid) { ! debug(29, 2) ("AuthenticateNTLMHandlePlacheholder: invalid callback data.\n"); ! helperStatefulReleaseServer(srv); ! return; } /* call authenticateNTLMStart to retry this request */ debug(29, 9) ("authenticateNTLMHandleplaceholder: calling authenticateNTLMStart\n"); + helperStatefulReleaseServer(srv); authenticateNTLMStart(r->auth_user_request, r->handler, r->data); cbdataUnlock(r->data); authenticateStateFree(r); } ! static void ! authenticateNTLMHandleReply(void *data, void *srv, char *reply) { authenticateStateData *r = data; ntlm_helper_state_t *helperstate; int valid; auth_user_request_t *auth_user_request; auth_user_t *auth_user; ntlm_user_t *ntlm_user; ntlm_request_t *ntlm_request; ! debug(29, 9) ("authenticateNTLMHandleReply: Helper: '%p' {%s}\n", srv, reply ? reply : ""); valid = cbdataValid(r->data); if (!valid) { ! debug(29, 2) ("AuthenticateNTLMHandleReply: invalid callback data. Releasing helper '%p'.\n", srv); cbdataUnlock(r->data); authenticateStateFree(r); ! helperStatefulReleaseServer(srv); ! return; } if (!reply) { /* *************** *** 458,505 **** */ fatal("authenticateNTLMHandleReply: called with no result string\n"); } /* seperate out the useful data */ if (strncasecmp(reply, "TT ", 3) == 0) { reply += 3; /* we have been given a Challenge */ /* we should check we weren't given an empty challenge */ /* copy the challenge to the state data */ ! helperstate = helperStatefulServerGetData(lastserver); if (helperstate == NULL) fatal("lost NTLM helper state! quitting\n"); helperstate->challenge = xstrndup(reply, NTLM_CHALLENGE_SZ + 5); - helperstate->challengeuses = 0; helperstate->renewed = squid_curtime; /* and we satisfy the request that happended on the refresh boundary */ /* note this code is now in two places FIXME */ - assert(r->auth_user_request != NULL); - assert(r->auth_user_request->auth_user->auth_type == AUTH_NTLM); - auth_user_request = r->auth_user_request; - ntlm_request = auth_user_request->scheme_data; - assert(ntlm_request != NULL); - result = S_HELPER_DEFER; - /* reserve the server for future authentication */ - ntlm_request->authserver_deferred = 1; - debug(29, 9) ("authenticateNTLMHandleReply: helper '%p'\n", lastserver); assert(ntlm_request->auth_state == AUTHENTICATE_STATE_NEGOTIATE); ! ntlm_request->authserver = lastserver; ntlm_request->authchallenge = xstrndup(reply, NTLM_CHALLENGE_SZ + 5); } else if (strncasecmp(reply, "AF ", 3) == 0) { /* we're finished, release the helper */ reply += 3; - assert(r->auth_user_request != NULL); - assert(r->auth_user_request->auth_user->auth_type == AUTH_NTLM); - auth_user_request = r->auth_user_request; - assert(auth_user_request->scheme_data != NULL); - ntlm_request = auth_user_request->scheme_data; auth_user = auth_user_request->auth_user; ntlm_user = auth_user_request->auth_user->scheme_data; assert(ntlm_user != NULL); - result = S_HELPER_RELEASE; /* we only expect OK when finishing the handshake */ assert(ntlm_request->auth_state == AUTHENTICATE_STATE_RESPONSE); ntlm_user->username = xstrndup(reply, MAX_LOGIN_SZ); ntlm_request->authserver = NULL; #ifdef NTLM_FAIL_OPEN } else if (strncasecmp(reply, "LD ", 3) == 0) { /* This is a variant of BH, which rather than deny access --- 487,526 ---- */ fatal("authenticateNTLMHandleReply: called with no result string\n"); } + assert(r->auth_user_request != NULL); + assert(r->auth_user_request->auth_user->auth_type == AUTH_NTLM); + auth_user_request = r->auth_user_request; + ntlm_request = auth_user_request->scheme_data; + assert(ntlm_request != NULL); + /* seperate out the useful data */ if (strncasecmp(reply, "TT ", 3) == 0) { reply += 3; /* we have been given a Challenge */ /* we should check we weren't given an empty challenge */ /* copy the challenge to the state data */ ! helperstate = helperStatefulServerGetData(srv); if (helperstate == NULL) fatal("lost NTLM helper state! quitting\n"); helperstate->challenge = xstrndup(reply, NTLM_CHALLENGE_SZ + 5); helperstate->renewed = squid_curtime; /* and we satisfy the request that happended on the refresh boundary */ /* note this code is now in two places FIXME */ assert(ntlm_request->auth_state == AUTHENTICATE_STATE_NEGOTIATE); ! ntlm_request->authserver = srv; ntlm_request->authchallenge = xstrndup(reply, NTLM_CHALLENGE_SZ + 5); + helperstate->challengeuses = 1; } else if (strncasecmp(reply, "AF ", 3) == 0) { /* we're finished, release the helper */ reply += 3; auth_user = auth_user_request->auth_user; ntlm_user = auth_user_request->auth_user->scheme_data; assert(ntlm_user != NULL); /* we only expect OK when finishing the handshake */ assert(ntlm_request->auth_state == AUTHENTICATE_STATE_RESPONSE); ntlm_user->username = xstrndup(reply, MAX_LOGIN_SZ); ntlm_request->authserver = NULL; + helperStatefulReleaseServer(srv); #ifdef NTLM_FAIL_OPEN } else if (strncasecmp(reply, "LD ", 3) == 0) { /* This is a variant of BH, which rather than deny access *************** *** 512,555 **** * case */ /* AF code: mark user as authenticated */ reply += 3; - assert(r->auth_user_request != NULL); - assert(r->auth_user_request->auth_user->auth_type == AUTH_NTLM); - auth_user_request = r->auth_user_request; - assert(auth_user_request->scheme_data != NULL); - ntlm_request = auth_user_request->scheme_data; auth_user = auth_user_request->auth_user; ntlm_user = auth_user_request->auth_user->scheme_data; assert(ntlm_user != NULL); - result = S_HELPER_RELEASE; /* we only expect LD when finishing the handshake */ assert(ntlm_request->auth_state == AUTHENTICATE_STATE_RESPONSE); ntlm_user->username = xstrndup(reply, MAX_LOGIN_SZ); helperstate = helperStatefulServerGetData(ntlm_request->authserver); - ntlm_request->authserver = NULL; /* BH code: mark helper as broken */ ! /* mark it for starving */ ! helperstate->starve = 1; #endif } else if (strncasecmp(reply, "NA ", 3) == 0) { - /* TODO: only work with auth_user here if it exists */ - assert(r->auth_user_request != NULL); - assert(r->auth_user_request->auth_user->auth_type == AUTH_NTLM); - auth_user_request = r->auth_user_request; - auth_user = auth_user_request->auth_user; - assert(auth_user != NULL); - ntlm_user = auth_user->scheme_data; - ntlm_request = auth_user_request->scheme_data; - assert((ntlm_user != NULL) && (ntlm_request != NULL)); /* todo: action of Negotiate state on error */ - result = S_HELPER_RELEASE; /*some error has occured. no more requests */ - ntlm_request->authserver = NULL; - debug(29, 4) ("authenticateNTLMHandleReply: Error validating user via NTLM. Error returned '%s'\n", reply); ntlm_request->auth_state = AUTHENTICATE_STATE_FAILED; ! if ((t = strchr(reply, ' '))) /* strip after a space */ ! *t = '0円'; ! } else if (strncasecmp(reply, "NA", 2) == 0) { ! /* NTLM Helper protocol violation! */ ! fatal("NTLM Helper returned invalid response \"NA\" - a error message MUST be attached\n"); } else if (strncasecmp(reply, "BH ", 3) == 0) { /* TODO kick off a refresh process. This can occur after a YR or after * a KK. If after a YR release the helper and resubmit the request via --- 533,554 ---- * case */ /* AF code: mark user as authenticated */ reply += 3; auth_user = auth_user_request->auth_user; ntlm_user = auth_user_request->auth_user->scheme_data; assert(ntlm_user != NULL); /* we only expect LD when finishing the handshake */ assert(ntlm_request->auth_state == AUTHENTICATE_STATE_RESPONSE); ntlm_user->username = xstrndup(reply, MAX_LOGIN_SZ); helperstate = helperStatefulServerGetData(ntlm_request->authserver); /* BH code: mark helper as broken */ ! authenticateNTLMResetServer(ntlm_request); ! debug(29, 4) ("authenticateNTLMHandleReply: Error validating user via NTLM. Error returned '%s'\n", reply); #endif } else if (strncasecmp(reply, "NA ", 3) == 0) { /* todo: action of Negotiate state on error */ ntlm_request->auth_state = AUTHENTICATE_STATE_FAILED; ! authenticateNTLMResetServer(ntlm_request); ! debug(29, 4) ("authenticateNTLMHandleReply: Error validating user via NTLM. Error returned '%s'\n", reply); } else if (strncasecmp(reply, "BH ", 3) == 0) { /* TODO kick off a refresh process. This can occur after a YR or after * a KK. If after a YR release the helper and resubmit the request via *************** *** 564,620 **** ntlm_user = auth_user->scheme_data; ntlm_request = auth_user_request->scheme_data; assert((ntlm_user != NULL) && (ntlm_request != NULL)); ! result = S_HELPER_RELEASE; /*some error has occured. no more requests for ! * this helper */ ! assert(ntlm_request->authserver ? ntlm_request->authserver == lastserver : 1); helperstate = helperStatefulServerGetData(ntlm_request->authserver); ! ntlm_request->authserver = NULL; if (ntlm_request->auth_state == AUTHENTICATE_STATE_NEGOTIATE) { /* The helper broke on YR. It automatically * resets */ ! debug(29, 1) ("authenticateNTLMHandleReply: Error obtaining challenge from helper: %p. Error returned '%s'\n", lastserver, reply); ! /* mark it for starving */ ! helperstate->starve = 1; /* resubmit the request. This helper is currently busy, so we will get * a different one. Our auth state stays the same */ authenticateNTLMStart(auth_user_request, r->handler, r->data); /* don't call the callback */ cbdataUnlock(r->data); authenticateStateFree(r); ! debug(29, 9) ("NTLM HandleReply, telling stateful helper : %d\n", result); ! return result; } - /* the helper broke on a KK */ - /* first the standard KK stuff */ - debug(29, 4) ("authenticateNTLMHandleReply: Error validating user via NTLM. Error returned '%s'\n", reply); - if ((t = strchr(reply, ' '))) /* strip after a space */ - *t = '0円'; - /* now we mark the helper for resetting. */ - helperstate->starve = 1; - ntlm_request->auth_state = AUTHENTICATE_STATE_FAILED; } else { ! /* TODO: only work with auth_user here if it exists */ ! /* TODO: take the request state into consideration */ ! assert(r->auth_user_request != NULL); ! assert(r->auth_user_request->auth_user->auth_type == AUTH_NTLM); ! auth_user_request = r->auth_user_request; ! auth_user = auth_user_request->auth_user; ! assert(auth_user != NULL); ! ntlm_user = auth_user->scheme_data; ! ntlm_request = auth_user_request->scheme_data; ! assert((ntlm_user != NULL) && (ntlm_request != NULL)); ! debug(29, 1) ("authenticateNTLMHandleReply: *** Unsupported helper response ***, '%s'\n", reply); ! /* **** NOTE THIS CODE IS EFFECTIVELY UNTESTED **** */ ! /* restart the authentication process */ ! ntlm_request->auth_state = AUTHENTICATE_STATE_NONE; ! assert(ntlm_request->authserver ? ntlm_request->authserver == lastserver : 1); ! ntlm_request->authserver = NULL; } r->handler(r->data, NULL); cbdataUnlock(r->data); authenticateStateFree(r); - debug(29, 9) ("NTLM HandleReply, telling stateful helper : %d\n", result); - return result; } static void --- 563,593 ---- ntlm_user = auth_user->scheme_data; ntlm_request = auth_user_request->scheme_data; assert((ntlm_user != NULL) && (ntlm_request != NULL)); ! assert(!ntlm_request->authserver || ntlm_request->authserver == srv); helperstate = helperStatefulServerGetData(ntlm_request->authserver); ! authenticateNTLMResetServer(ntlm_request); if (ntlm_request->auth_state == AUTHENTICATE_STATE_NEGOTIATE) { /* The helper broke on YR. It automatically * resets */ ! debug(29, 1) ("authenticateNTLMHandleReply: Error obtaining challenge from helper: %p. Error returned '%s'\n", srv, reply); /* resubmit the request. This helper is currently busy, so we will get * a different one. Our auth state stays the same */ authenticateNTLMStart(auth_user_request, r->handler, r->data); /* don't call the callback */ cbdataUnlock(r->data); authenticateStateFree(r); ! return; ! } else { ! /* the helper broke on a KK */ ! debug(29, 1) ("authenticateNTLMHandleReply: Error validating user via NTLM. Error returned '%s'\n", reply); ! ntlm_request->auth_state = AUTHENTICATE_STATE_FAILED; } } else { ! fatalf("authenticateNTLMHandleReply: *** Unsupported helper response ***, '%s'\n", reply); } r->handler(r->data, NULL); cbdataUnlock(r->data); authenticateStateFree(r); } static void *************** *** 717,752 **** * 2: does it have a challenge? * 3: tell it to get a challenge, or give ntlmauthdone the challenge */ ! server = helperStatefulDefer(ntlmauthenticators); helperstate = server ? helperStatefulServerGetData(server) : NULL; ! while ((server != NULL) && authenticateNTLMChangeChallenge_p(helperstate)) { ! /* flag this helper for challenge changing */ ! helperstate->starve = 1; ! /* and release the deferred request */ ! helperStatefulReleaseServer(server); ! /* Get another deferrable server */ ! server = helperStatefulDefer(ntlmauthenticators); ! helperstate = server ? helperStatefulServerGetData(server) : NULL; } - if (server == NULL) - debug(29, 9) ("unable to get a deferred ntlm helper... all helpers are refreshing challenges. Queuing as a placeholder request.\n"); - ntlm_request->authserver = server; /* tell the log what helper we have been given */ ! debug(29, 9) ("authenticateNTLMStart: helper '%p' assigned\n", server); /* server and valid challenge? */ ! if ((server == NULL) || !authenticateNTLMValidChallenge(helperstate)) { /* No server, or server with invalid challenge */ r = cbdataAlloc(authenticateStateData); r->handler = handler; cbdataLock(data); r->data = data; r->auth_user_request = auth_user_request; ! if (server == NULL) { helperStatefulSubmit(ntlmauthenticators, NULL, authenticateNTLMHandleplaceholder, r, NULL); } else { /* Server with invalid challenge */ ! snprintf(buf, 8192, "YR\n"); helperStatefulSubmit(ntlmauthenticators, buf, authenticateNTLMHandleReply, r, ntlm_request->authserver); } } else { --- 690,732 ---- * 2: does it have a challenge? * 3: tell it to get a challenge, or give ntlmauthdone the challenge */ ! server = helperStatefulGetServer(ntlmauthenticators); helperstate = server ? helperStatefulServerGetData(server) : NULL; ! if (ntlmConfig->challengeuses) { ! while ((server != NULL) && authenticateNTLMChangeChallenge_p(helperstate)) { ! /* flag this helper for challenge changing */ ! helperstate->starve = 1; ! helperStatefulReset(server); ! /* Get another server */ ! server = helperStatefulGetServer(ntlmauthenticators); ! helperstate = server ? helperStatefulServerGetData(server) : NULL; ! } } ntlm_request->authserver = server; /* tell the log what helper we have been given */ ! if (server == NULL) ! debug(29, 9) ("authenticateNTLMStart: unable to get a ntlm helper... Queuing as a placeholder request.\n"); ! else ! debug(29, 9) ("authenticateNTLMStart: helper '%p' assigned\n", server); /* server and valid challenge? */ ! if ((server == NULL) || ntlmConfig->challengeuses == 0 || !authenticateNTLMValidChallenge(helperstate)) { /* No server, or server with invalid challenge */ r = cbdataAlloc(authenticateStateData); r->handler = handler; cbdataLock(data); r->data = data; r->auth_user_request = auth_user_request; ! if (server == NULL && ntlmConfig->challengeuses) { helperStatefulSubmit(ntlmauthenticators, NULL, authenticateNTLMHandleplaceholder, r, NULL); } else { /* Server with invalid challenge */ ! ! if (ntlmConfig->use_ntlm_negotiate) { ! snprintf(buf, 8192, "YR %s\n", sent_string); ! } else { ! snprintf(buf, 8192, "YR\n"); ! } ! helperStatefulSubmit(ntlmauthenticators, buf, authenticateNTLMHandleReply, r, ntlm_request->authserver); } } else { *************** *** 756,765 **** helperstate->challengeuses++; /* assign the challenge */ ntlm_request->authchallenge = xstrndup(helperstate->challenge, NTLM_CHALLENGE_SZ + 5); - /* we're not actually submitting a request, so we need to release the helper - * should the connection close unexpectedly - */ - ntlm_request->authserver_deferred = 1; handler(data, NULL); } --- 736,741 ---- *************** *** 771,778 **** r->data = data; r->auth_user_request = auth_user_request; snprintf(buf, 8192, "KK %s\n", sent_string); - /* getting rid of deferred request status */ - ntlm_request->authserver_deferred = 0; helperStatefulSubmit(ntlmauthenticators, buf, authenticateNTLMHandleReply, r, ntlm_request->authserver); debug(29, 9) ("authenticateNTLMstart: finished\n"); break; --- 747,752 ---- *************** *** 800,813 **** } static void ! authenticateNTLMHelperServerOnEmpty(void *data) { ntlm_helper_state_t *statedata = data; if (statedata == NULL) return; if (statedata->starve) { /* we have been starving the helper */ ! debug(29, 9) ("authenticateNTLMHelperServerOnEmpty: resetting challenge details\n"); statedata->starve = 0; statedata->challengeuses = 0; statedata->renewed = 0; --- 774,787 ---- } static void ! authenticateNTLMHelperServerReset(void *data) { ntlm_helper_state_t *statedata = data; if (statedata == NULL) return; if (statedata->starve) { /* we have been starving the helper */ ! debug(29, 9) ("authenticateNTLMHelperServerReset: resetting challenge details\n"); statedata->starve = 0; statedata->challengeuses = 0; statedata->renewed = 0; *************** *** 816,835 **** } } - - /* clear the NTLM helper of being reserved for future requests */ - static void - authenticateNTLMReleaseServer(auth_user_request_t * auth_user_request) - { - ntlm_request_t *ntlm_request; - assert(auth_user_request->auth_user->auth_type == AUTH_NTLM); - assert(auth_user_request->scheme_data != NULL); - ntlm_request = auth_user_request->scheme_data; - debug(29, 9) ("authenticateNTLMReleaseServer: releasing server '%p'\n", ntlm_request->authserver); - helperStatefulReleaseServer(ntlm_request->authserver); - ntlm_request->authserver = NULL; - } - /* clear any connection related authentication details */ static void authenticateNTLMOnCloseConnection(ConnStateData * conn) --- 790,795 ---- *************** *** 840,847 **** assert(conn->auth_user_request->scheme_data != NULL); ntlm_request = conn->auth_user_request->scheme_data; assert(ntlm_request->conn == conn); ! if (ntlm_request->authserver != NULL && ntlm_request->authserver_deferred) ! authenticateNTLMReleaseServer(conn->auth_user_request); /* unlock the connection based lock */ debug(29, 9) ("authenticateNTLMOnCloseConnection: Unlocking auth_user from the connection.\n"); /* minor abstraction break here: FIXME */ --- 800,807 ---- assert(conn->auth_user_request->scheme_data != NULL); ntlm_request = conn->auth_user_request->scheme_data; assert(ntlm_request->conn == conn); ! if (ntlm_request->authserver != NULL) ! authenticateNTLMReleaseServer(ntlm_request); /* unlock the connection based lock */ debug(29, 9) ("authenticateNTLMOnCloseConnection: Unlocking auth_user from the connection.\n"); /* minor abstraction break here: FIXME */ *************** *** 1021,1027 **** debug(29, 4) ("authenticateNTLMAuthenticateUser: ntlm proxy-auth cache hit\n"); /* throw away the temporary entry */ ntlm_request->authserver_deferred = 0; ! authenticateNTLMReleaseServer(auth_user_request); authenticateAuthUserMerge(auth_user, proxy_auth_hash->auth_user); auth_user = proxy_auth_hash->auth_user; auth_user_request->auth_user = auth_user; --- 981,987 ---- debug(29, 4) ("authenticateNTLMAuthenticateUser: ntlm proxy-auth cache hit\n"); /* throw away the temporary entry */ ntlm_request->authserver_deferred = 0; ! authenticateNTLMReleaseServer(ntlm_request); authenticateAuthUserMerge(auth_user, proxy_auth_hash->auth_user); auth_user = proxy_auth_hash->auth_user; auth_user_request->auth_user = auth_user; *************** *** 1053,1074 **** ntlm_request->authchallenge); /* see if this is an existing user with a different proxy_auth * string */ ! if ((usernamehash = hash_lookup(proxy_auth_username_cache, ntlm_user->username))) { ! while ((usernamehash->auth_user->auth_type != auth_user->auth_type) && (usernamehash->next) && !authenticateNTLMcmpUsername(usernamehash->auth_user->scheme_data, ntlm_user)) usernamehash = usernamehash->next; ! if (usernamehash->auth_user->auth_type == auth_user->auth_type) { ! /* ! * add another link from the new proxy_auth to the ! * auth_user structure and update the information */ ! assert(proxy_auth_hash == NULL); ! authenticateProxyAuthCacheAddLink(ntlmhash, usernamehash->auth_user); ! /* we can't seamlessly recheck the username due to the ! * challenge nature of the protocol. Just free the ! * temporary auth_user */ ! authenticateAuthUserMerge(auth_user, usernamehash->auth_user); ! auth_user = usernamehash->auth_user; ! auth_user_request->auth_user = auth_user; ! } } else { /* store user in hash's */ authenticateUserNameCacheAdd(auth_user); --- 1013,1035 ---- ntlm_request->authchallenge); /* see if this is an existing user with a different proxy_auth * string */ ! usernamehash = hash_lookup(proxy_auth_username_cache, ntlm_user->username); ! if (usernamehash) { ! while (usernamehash && (usernamehash->auth_user->auth_type != auth_user->auth_type || authenticateNTLMcmpUsername(usernamehash->auth_user->scheme_data, ntlm_user) != 0)) usernamehash = usernamehash->next; ! } ! if (usernamehash) { ! /* ! * add another link from the new proxy_auth to the ! * auth_user structure and update the information */ ! assert(proxy_auth_hash == NULL); ! authenticateProxyAuthCacheAddLink(ntlmhash, usernamehash->auth_user); ! /* we can't seamlessly recheck the username due to the ! * challenge nature of the protocol. Just free the ! * temporary auth_user */ ! authenticateAuthUserMerge(auth_user, usernamehash->auth_user); ! auth_user = usernamehash->auth_user; ! auth_user_request->auth_user = auth_user; } else { /* store user in hash's */ authenticateUserNameCacheAdd(auth_user); Index: squid/src/auth/ntlm/auth_ntlm.h diff -c squid/src/auth/ntlm/auth_ntlm.h:1.7 squid/src/auth/ntlm/auth_ntlm.h:1.7.2.1 *** squid/src/auth/ntlm/auth_ntlm.h:1.7 Wed Nov 28 01:01:57 2001 --- squid/src/auth/ntlm/auth_ntlm.h Wed Feb 4 10:42:36 2004 *************** *** 15,21 **** AUTHENTICATE_STATE_RESPONSE, AUTHENTICATE_STATE_DONE, AUTHENTICATE_STATE_FAILED ! } auth_state_t; /* connection level auth state */ /* Generic */ typedef struct { --- 15,21 ---- AUTHENTICATE_STATE_RESPONSE, AUTHENTICATE_STATE_DONE, AUTHENTICATE_STATE_FAILED ! } auth_state_t; /* connection level auth state */ /* Generic */ typedef struct { *************** *** 60,65 **** --- 60,66 ---- wordlist *authenticate; int challengeuses; time_t challengelifetime; + int use_ntlm_negotiate; }; typedef struct _ntlm_user ntlm_user_t;

AltStyle によって変換されたページ (->オリジナル) /