]> git.ipfire.org Git - thirdparty/squid.git/commitdiff
Merged from trunk
authorAmos Jeffries <squid3@treenet.co.nz>
Thu, 8 Apr 2010 12:14:42 +0000 (00:14 +1200)
committerAmos Jeffries <squid3@treenet.co.nz>
Thu, 8 Apr 2010 12:14:42 +0000 (00:14 +1200)
16 files changed:
1  2 
configure.in
src/HttpRequest.cc
src/HttpRequest.h
src/Makefile.am
src/acl/FilledChecklist.cc
src/adaptation/icap/ModXact.cc
src/auth/digest/auth_digest.cc
src/auth/digest/digestUserRequest.cc
src/cache_cf.cc
src/cf.data.pre
src/client_side.cc
src/client_side_reply.cc
src/client_side_request.cc
src/http.cc
src/main.cc
src/structs.h

diff --cc configure.in
Simple merge
Simple merge
Simple merge
diff --cc src/Makefile.am
Simple merge
index 7cfd5306b34cb5202e3c363b14bb4e8187ccae38,dad2ed501033dd7aad8d2dba2ff54cbd7e24a6ae..f59e5f1aea228098e6487d101f7cbf475ab19d32
@@@ -67,12 -83,19 +67,13 @@@ ACLFilledChecklist::checkCallback(allow
      /* During reconfigure, we can end up not finishing call
       * sequences into the auth code */
  
 -    if (auth_user_request) {
 +    if (auth_user_request != NULL) {
          /* the filled_checklist lock */
 -        AUTHUSERREQUESTUNLOCK(auth_user_request, "ACLFilledChecklist");
 -
 +        auth_user_request = NULL;
          /* it might have been connection based */
-         if(conn()) {
 -        /*
 -         * DPW 2007-05-08
 -         * yuck, this make me uncomfortable.  why do this here?
 -         * ConnStateData will do its own unlocking.
 -         */
+         /* BUG 2827: the connection may also not exist. ie fast ACL tests vs client disconnection. */
+         if (conn()) {
 -            AUTHUSERREQUESTUNLOCK(conn()->auth_user_request, "conn via ACLFilledChecklist");
 +            conn()->auth_user_request = NULL;
              conn()->auth_type = AUTH_BROKEN;
          }
      }
Simple merge
Simple merge
index e3c06ce53086da9e31dd7faf92e71d4182a0cd1f,0000000000000000000000000000000000000000..3fd996c4755601156ae4c1c52c640039f017e177
mode 100644,000000..100644
--- /dev/null
@@@ -1,336 -1,0 +1,337 @@@
-     assert(user() != NULL);
 +#include "config.h"
 +#include "auth/digest/auth_digest.h"
 +#include "auth/digest/digestUserRequest.h"
 +#include "auth/State.h"
 +#include "HttpReply.h"
 +#include "HttpRequest.h"
 +#include "SquidTime.h"
 +
 +AuthDigestUserRequest::AuthDigestUserRequest() :
 +        nonceb64(NULL),
 +        cnonce(NULL),
 +        realm(NULL),
 +        pszPass(NULL),
 +        algorithm(NULL),
 +        pszMethod(NULL),
 +        qop(NULL),
 +        uri(NULL),
 +        response(NULL),
 +        nonce(NULL),
 +        credentials_ok(Unchecked)
 +{}
 +
 +/**
 + * Delete the digest request structure.
 + * Does NOT delete related AuthUser structures
 + */
 +AuthDigestUserRequest::~AuthDigestUserRequest()
 +{
 +    assert(RefCountCount()==0);
 +
 +    safe_free(nonceb64);
 +    safe_free(cnonce);
 +    safe_free(realm);
 +    safe_free(pszPass);
 +    safe_free(algorithm);
 +    safe_free(pszMethod);
 +    safe_free(qop);
 +    safe_free(uri);
 +    safe_free(response);
 +
 +    if (nonce)
 +        authDigestNonceUnlink(nonce);
 +}
 +
 +AuthDigestUserRequest::CredentialsState
 +AuthDigestUserRequest::credentials() const
 +{
 +    return credentials_ok;
 +}
 +
 +void
 +AuthDigestUserRequest::credentials(CredentialsState newCreds)
 +{
 +    credentials_ok = newCreds;
 +}
 +
 +int
 +AuthDigestUserRequest::authenticated() const
 +{
 +    if (credentials() == Ok)
 +        return 1;
 +
 +    return 0;
 +}
 +
 +/** log a digest user in
 + */
 +void
 +AuthDigestUserRequest::authenticate(HttpRequest * request, ConnStateData * conn, http_hdr_type type)
 +{
 +    AuthDigestUserRequest *digest_request;
 +    digest_user_h *digest_user;
 +
 +    HASHHEX SESSIONKEY;
 +    HASHHEX HA2 = "";
 +    HASHHEX Response;
 +
++    assert(authUser() != NULL);
 +    AuthUser *auth_user = user();
 +
 +    digest_user = dynamic_cast<digest_user_h*>(auth_user);
 +    assert(digest_user != NULL);
 +
 +    /* if the check has corrupted the user, just return */
 +
 +    if (credentials() == Failed) {
 +        return;
 +    }
 +
 +    digest_request = this;
 +
 +    /* do we have the HA1 */
 +
 +    if (!digest_user->HA1created) {
 +        credentials(Pending);
 +        return;
 +    }
 +
 +    if (digest_request->nonce == NULL) {
 +        /* this isn't a nonce we issued */
 +        credentials(Failed);
 +        return;
 +    }
 +
 +    DigestCalcHA1(digest_request->algorithm, NULL, NULL, NULL,
 +                  authenticateDigestNonceNonceb64(digest_request->nonce),
 +                  digest_request->cnonce,
 +                  digest_user->HA1, SESSIONKEY);
 +    DigestCalcResponse(SESSIONKEY, authenticateDigestNonceNonceb64(digest_request->nonce),
 +                       digest_request->nc, digest_request->cnonce, digest_request->qop,
 +                       RequestMethodStr(request->method), digest_request->uri, HA2, Response);
 +
 +    debugs(29, 9, "\nResponse = '" << digest_request->response << "'\nsquid is = '" << Response << "'");
 +
 +    if (strcasecmp(digest_request->response, Response) != 0) {
 +        if (!digest_request->flags.helper_queried) {
 +            /* Query the helper in case the password has changed */
 +            digest_request->flags.helper_queried = 1;
 +            digest_request->credentials_ok = Pending;
 +            return;
 +        }
 +
 +       if (static_cast<AuthDigestConfig*>(AuthConfig::Find("digest"))->PostWorkaround && request->method != METHOD_GET) {
 +            /* Ugly workaround for certain very broken browsers using the
 +             * wrong method to calculate the request-digest on POST request.
 +             * This should be deleted once Digest authentication becomes more
 +             * widespread and such broken browsers no longer are commonly
 +             * used.
 +             */
 +            DigestCalcResponse(SESSIONKEY, authenticateDigestNonceNonceb64(digest_request->nonce),
 +                               digest_request->nc, digest_request->cnonce, digest_request->qop,
 +                               RequestMethodStr(METHOD_GET), digest_request->uri, HA2, Response);
 +
 +            if (strcasecmp(digest_request->response, Response)) {
 +                credentials(Failed);
++                digest_request->flags.invalid_password = 1;
 +                digest_request->setDenyMessage("Incorrect password");
 +                return;
 +            } else {
 +                const char *useragent = request->header.getStr(HDR_USER_AGENT);
 +
 +                static IpAddress last_broken_addr;
 +                static int seen_broken_client = 0;
 +
 +                if (!seen_broken_client) {
 +                    last_broken_addr.SetNoAddr();
 +                    seen_broken_client = 1;
 +                }
 +
 +                if (last_broken_addr != request->client_addr) {
 +                    debugs(29, 1, "\nDigest POST bug detected from " <<
 +                           request->client_addr << " using '" <<
 +                           (useragent ? useragent : "-") <<
 +                           "'. Please upgrade browser. See Bug #630 for details.");
 +
 +                    last_broken_addr = request->client_addr;
 +                }
 +            }
 +        } else {
 +            credentials(Failed);
 +            digest_request->flags.invalid_password = 1;
 +            digest_request->setDenyMessage("Incorrect password");
 +            return;
 +        }
 +
 +        /* check for stale nonce */
 +        if (!authDigestNonceIsValid(digest_request->nonce, digest_request->nc)) {
 +            debugs(29, 3, "authenticateDigestAuthenticateuser: user '" << digest_user->username() << "' validated OK but nonce stale");
 +            credentials(Failed);
 +            digest_request->setDenyMessage("Stale nonce");
 +            return;
 +        }
 +    }
 +
 +    credentials(Ok);
 +
 +    /* password was checked and did match */
 +    debugs(29, 4, "authenticateDigestAuthenticateuser: user '" << digest_user->username() << "' validated OK");
 +
 +    /* auth_user is now linked, we reset these values
 +     * after external auth occurs anyway */
 +    auth_user->expiretime = current_time.tv_sec;
 +    return;
 +}
 +
 +int
 +AuthDigestUserRequest::module_direction()
 +{
 +    switch (credentials()) {
 +
 +    case Unchecked:
 +        return -1;
 +
 +    case Ok:
 +        return 0;
 +
 +    case Pending:
 +        return -1;
 +
 +    case Failed:
 +        /* send new challenge */
 +        return 1;
 +    }
 +    return -2;
 +}
 +
 +/* add the [proxy]authorisation header */
 +void
 +AuthDigestUserRequest::addHeader(HttpReply * rep, int accel)
 +{
 +    http_hdr_type type;
 +
 +    /* don't add to authentication error pages */
 +
 +    if ((!accel && rep->sline.status == HTTP_PROXY_AUTHENTICATION_REQUIRED)
 +            || (accel && rep->sline.status == HTTP_UNAUTHORIZED))
 +        return;
 +
 +    type = accel ? HDR_AUTHENTICATION_INFO : HDR_PROXY_AUTHENTICATION_INFO;
 +
 +#if WAITING_FOR_TE
 +    /* test for http/1.1 transfer chunked encoding */
 +    if (chunkedtest)
 +        return;
 +#endif
 +
 +    if ((static_cast<AuthDigestConfig*>(AuthConfig::Find("digest"))->authenticate) && authDigestNonceLastRequest(nonce)) {
 +        flags.authinfo_sent = 1;
 +        debugs(29, 9, "authDigestAddHead: Sending type:" << type << " header: 'nextnonce=\"" << authenticateDigestNonceNonceb64(nonce) << "\"");
 +        httpHeaderPutStrf(&rep->header, type, "nextnonce=\"%s\"", authenticateDigestNonceNonceb64(nonce));
 +    }
 +}
 +
 +#if WAITING_FOR_TE
 +/** add the [proxy]authorisation header */
 +void
 +AuthDigestUserRequest::addTrailer(HttpReply * rep, int accel)
 +{
 +    int type;
 +
 +    if (!auth_user_request)
 +        return;
 +
 +    /* has the header already been send? */
 +    if (flags.authinfo_sent)
 +        return;
 +
 +    /* don't add to authentication error pages */
 +    if ((!accel && rep->sline.status == HTTP_PROXY_AUTHENTICATION_REQUIRED)
 +            || (accel && rep->sline.status == HTTP_UNAUTHORIZED))
 +        return;
 +
 +    type = accel ? HDR_AUTHENTICATION_INFO : HDR_PROXY_AUTHENTICATION_INFO;
 +
 +    if ((static_cast<AuthDigestConfig*>(digestScheme::GetInstance()->getConfig())->authenticate) && authDigestNonceLastRequest(nonce)) {
 +        debugs(29, 9, "authDigestAddTrailer: Sending type:" << type << " header: 'nextnonce=\"" << authenticateDigestNonceNonceb64(nonce) << "\"");
 +        httpTrailerPutStrf(&rep->header, type, "nextnonce=\"%s\"", authenticateDigestNonceNonceb64(nonce));
 +    }
 +}
 +#endif
 +
 +/* send the initial data to a digest authenticator module */
 +void
 +AuthDigestUserRequest::module_start(RH * handler, void *data)
 +{
 +    authenticateStateData *r = NULL;
 +    char buf[8192];
 +    digest_user_h *digest_user;
 +    assert(user()->auth_type == AUTH_DIGEST);
 +    digest_user = dynamic_cast<digest_user_h*>(user());
 +    assert(digest_user != NULL);
 +    debugs(29, 9, "authenticateStart: '\"" << digest_user->username() << "\":\"" << realm << "\"'");
 +
 +    if (static_cast<AuthDigestConfig*>(AuthConfig::Find("digest"))->authenticate == NULL) {
 +        handler(data, NULL);
 +        return;
 +    }
 +
 +    r = cbdataAlloc(authenticateStateData);
 +    r->handler = handler;
 +    r->data = cbdataReference(data);
 +    r->auth_user_request = static_cast<AuthUserRequest*>(this);
 +    if (static_cast<AuthDigestConfig*>(AuthConfig::Find("digest"))->utf8) {
 +        char userstr[1024];
 +        latin1_to_utf8(userstr, sizeof(userstr), digest_user->username());
 +        snprintf(buf, 8192, "\"%s\":\"%s\"\n", userstr, realm);
 +    } else {
 +        snprintf(buf, 8192, "\"%s\":\"%s\"\n", digest_user->username(), realm);
 +    }
 +
 +    helperSubmit(digestauthenticators, buf, AuthDigestUserRequest::HandleReply, r);
 +}
 +
 +void
 +AuthDigestUserRequest::HandleReply(void *data, char *reply)
 +{
 +    authenticateStateData *replyData = static_cast < authenticateStateData * >(data);
 +    char *t = NULL;
 +    void *cbdata;
 +    debugs(29, 9, HERE << "{" << (reply ? reply : "<NULL>") << "}");
 +
 +    if (reply) {
 +        if ((t = strchr(reply, ' ')))
 +            *t++ = '\0';
 +
 +        if (*reply == '\0' || *reply == '\n')
 +            reply = NULL;
 +    }
 +
 +    assert(replyData->auth_user_request != NULL);
 +    AuthUserRequest::Pointer auth_user_request = replyData->auth_user_request;
 +
 +    /* AYJ: 2009-12-12: allow this because the digest_request pointer is purely local */
 +    AuthDigestUserRequest *digest_request = dynamic_cast < AuthDigestUserRequest * >(auth_user_request.getRaw());
 +    assert(digest_request);
 +
 +    digest_user_h *digest_user = dynamic_cast < digest_user_h * >(auth_user_request->user());
 +    assert(digest_user != NULL);
 +
 +    if (reply && (strncasecmp(reply, "ERR", 3) == 0)) {
 +        digest_request->credentials(AuthDigestUserRequest::Failed);
 +        digest_request->flags.invalid_password = 1;
 +
 +        if (t && *t)
 +            digest_request->setDenyMessage(t);
 +    } else if (reply) {
 +        CvtBin(reply, digest_user->HA1);
 +        digest_user->HA1created = 1;
 +    }
 +
 +    if (cbdataReferenceValidDone(replyData->data, &cbdata))
 +        replyData->handler(cbdata, NULL);
 +
 +    replyData->auth_user_request = NULL;
 +
 +    cbdataFree(replyData);
 +}
diff --cc src/cache_cf.cc
Simple merge
diff --cc src/cf.data.pre
Simple merge
Simple merge
Simple merge
Simple merge
diff --cc src/http.cc
Simple merge
diff --cc src/main.cc
Simple merge
diff --cc src/structs.h
Simple merge