⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 auth_digest.c

📁 一个功能非常全面的代理服务器源代码程序,
💻 C
📖 第 1 页 / 共 4 页
字号:
/* * $Id: auth_digest.c,v 1.21 2006/07/30 23:27:04 hno Exp $ * * DEBUG: section 29    Authenticator * AUTHOR: Robert Collins * * SQUID Internet Object Cache  http://squid.nlanr.net/Squid/ * ---------------------------------------------------------- * *  Squid is the result of efforts by numerous individuals from the *  Internet community.  Development is led by Duane Wessels of the *  National Laboratory for Applied Network Research and funded by the *  National Science Foundation.  Squid is Copyrighted (C) 1998 by *  the Regents of the University of California.  Please see the *  COPYRIGHT file for full details.  Squid incorporates software *  developed and/or copyrighted by other sources.  Please see the *  CREDITS file for full details. * *  This program is free software; you can redistribute it and/or modify *  it under the terms of the GNU General Public License as published by *  the Free Software Foundation; either version 2 of the License, or *  (at your option) any later version. *   *  This program is distributed in the hope that it will be useful, *  but WITHOUT ANY WARRANTY; without even the implied warranty of *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the *  GNU General Public License for more details. *   *  You should have received a copy of the GNU General Public License *  along with this program; if not, write to the Free Software *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA. * *//* The functions in this file handle authentication. * They DO NOT perform access control or auditing. * See acl.c for access control and client_side.c for auditing */#include "squid.h"#include "rfc2617.h"#include "auth_digest.h"extern AUTHSSETUP authSchemeSetup_digest;static voidauthenticateStateFree(authenticateStateData * r){    if (r->auth_user_request) {	authenticateAuthUserRequestUnlock(r->auth_user_request);	r->auth_user_request = NULL;    }    cbdataFree(r);}/* Digest Scheme */static HLPCB authenticateDigestHandleReply;static AUTHSACTIVE authenticateDigestActive;static AUTHSADDHEADER authDigestAddHeader;#if WAITING_FOR_TEstatic AUTHSADDTRAILER authDigestAddTrailer;#endifstatic AUTHSAUTHED authDigestAuthenticated;static AUTHSAUTHUSER authenticateDigestAuthenticateUser;static AUTHSCONFIGURED authDigestConfigured;static AUTHSDIRECTION authenticateDigestDirection;static AUTHSDECODE authenticateDigestDecodeAuth;static AUTHSDUMP authDigestCfgDump;static AUTHSFIXERR authenticateDigestFixHeader;static AUTHSFREE authenticateDigestUserFree;static AUTHSFREECONFIG authDigestFreeConfig;static AUTHSINIT authDigestInit;static AUTHSPARSE authDigestParse;static AUTHSCHECKCONFIG authDigestCheckConfig;static AUTHSREQFREE authDigestAURequestFree;static AUTHSSTART authenticateDigestStart;static AUTHSSTATS authenticateDigestStats;static AUTHSUSERNAME authenticateDigestUsername;static AUTHSSHUTDOWN authDigestDone;static helper *digestauthenticators = NULL;static hash_table *digest_nonce_cache;static auth_digest_config *digestConfig = NULL;static int authdigest_initialised = 0;static MemPool *digest_user_pool = NULL;static MemPool *digest_request_pool = NULL;static MemPool *digest_nonce_pool = NULL;CBDATA_TYPE(authenticateStateData);/* * * Nonce Functions * */static void authenticateDigestNonceCacheCleanup(void *data);static digest_nonce_h *authenticateDigestNonceFindNonce(const char *nonceb64);static digest_nonce_h *authenticateDigestNonceNew(void);static void authenticateDigestNonceDelete(digest_nonce_h * nonce);static void authenticateDigestNonceSetup(void);static void authenticateDigestNonceShutdown(void);static void authenticateDigestNonceReconfigure(void);static const char *authenticateDigestNonceNonceb64(digest_nonce_h * nonce);static int authDigestNonceIsValid(digest_nonce_h * nonce, char nc[9]);static int authDigestNonceIsStale(digest_nonce_h * nonce);static void authDigestNonceEncode(digest_nonce_h * nonce);static int authDigestNonceLastRequest(digest_nonce_h * nonce);static void authDigestNonceLink(digest_nonce_h * nonce);static void authDigestNonceUnlink(digest_nonce_h * nonce);#if NOT_USEDstatic int authDigestNonceLinks(digest_nonce_h * nonce);#endifstatic void authDigestNonceUserUnlink(digest_nonce_h * nonce);static void authDigestNoncePurge(digest_nonce_h * nonce);static voidauthDigestNonceEncode(digest_nonce_h * nonce){    if (!nonce)	return;    if (nonce->hash.key)	xfree(nonce->hash.key);    nonce->hash.key = xstrdup(base64_encode_bin((char *) &(nonce->noncedata), sizeof(digest_nonce_data)));}static digest_nonce_h *authenticateDigestNonceNew(void){    digest_nonce_h *newnonce = memPoolAlloc(digest_nonce_pool);    digest_nonce_h *temp;/* NONCE CREATION - NOTES AND REASONING. RBC 20010108 * === EXCERPT FROM RFC 2617 === * The contents of the nonce are implementation dependent. The quality * of the implementation depends on a good choice. A nonce might, for * example, be constructed as the base 64 encoding of *  * time-stamp H(time-stamp ":" ETag ":" private-key) *  * where time-stamp is a server-generated time or other non-repeating * value, ETag is the value of the HTTP ETag header associated with * the requested entity, and private-key is data known only to the * server.  With a nonce of this form a server would recalculate the * hash portion after receiving the client authentication header and * reject the request if it did not match the nonce from that header * or if the time-stamp value is not recent enough. In this way the * server can limit the time of the nonce's validity. The inclusion of * the ETag prevents a replay request for an updated version of the * resource.  (Note: including the IP address of the client in the * nonce would appear to offer the server the ability to limit the * reuse of the nonce to the same client that originally got it. * However, that would break proxy farms, where requests from a single * user often go through different proxies in the farm. Also, IP * address spoofing is not that hard.) * ==== *  * Now for my reasoning: * We will not accept a unrecognised nonce->we have all recognisable * nonces stored If we send out unique base64 encodings we guarantee * that a given nonce applies to only one user (barring attacks or * really bad timing with expiry and creation).  Using a random * component in the nonce allows us to loop to find a unique nonce. * We use H(nonce_data) so the nonce is meaningless to the reciever. * So our nonce looks like base64(H(timestamp,pointertohash,randomdata)) * And even if our randomness is not very random (probably due to * bad coding on my part) we don't really care - the timestamp and * memory pointer should provide enough protection for the users * authentication. */    /* create a new nonce */    newnonce->nc = 0;    newnonce->flags.valid = 1;    newnonce->noncedata.self = newnonce;    newnonce->noncedata.creationtime = current_time.tv_sec;    newnonce->noncedata.randomdata = squid_random();    authDigestNonceEncode(newnonce);    /*     * loop until we get a unique nonce. The nonce creation must     * have a random factor     */    while ((temp = authenticateDigestNonceFindNonce(newnonce->hash.key))) {	/* create a new nonce */	newnonce->noncedata.randomdata = squid_random();	authDigestNonceEncode(newnonce);    }    hash_join(digest_nonce_cache, &newnonce->hash);    /* the cache's link */    authDigestNonceLink(newnonce);    newnonce->flags.incache = 1;    debug(29, 5) ("authenticateDigestNonceNew: created nonce %p at %ld\n", newnonce, (long int) newnonce->noncedata.creationtime);    return newnonce;}static voidauthenticateDigestNonceDelete(digest_nonce_h * nonce){    if (nonce) {	assert(nonce->references == 0);#if UNREACHABLECODE	if (nonce->flags.incache)	    hash_remove_link(digest_nonce_cache, &nonce->hash);#endif	assert(nonce->flags.incache == 0);	safe_free(nonce->hash.key);	memPoolFree(digest_nonce_pool, nonce);    }}static voidauthenticateDigestNonceSetup(void){    if (!digest_nonce_pool)	digest_nonce_pool = memPoolCreate("Digest Scheme nonce's", sizeof(digest_nonce_h));    if (!digest_nonce_cache) {	digest_nonce_cache = hash_create((HASHCMP *) strcmp, 7921, hash_string);	assert(digest_nonce_cache);	eventAdd("Digest none cache maintenance", authenticateDigestNonceCacheCleanup, NULL, digestConfig->nonceGCInterval, 1);    }}static voidauthenticateDigestNonceShutdown(void){    /*      * We empty the cache of any nonces left in there.     */    digest_nonce_h *nonce;    if (digest_nonce_cache) {	debug(29, 2) ("authenticateDigestNonceShutdown: Shutting down nonce cache \n");	hash_first(digest_nonce_cache);	while ((nonce = ((digest_nonce_h *) hash_next(digest_nonce_cache)))) {	    assert(nonce->flags.incache);	    authDigestNoncePurge(nonce);	}    }    if (digest_nonce_pool) {	assert(memPoolInUseCount(digest_nonce_pool) == 0);	memPoolDestroy(digest_nonce_pool);	digest_nonce_pool = NULL;    }    debug(29, 2) ("authenticateDigestNonceShutdown: Nonce cache shutdown\n");}static voidauthenticateDigestNonceReconfigure(void){}static voidauthenticateDigestNonceCacheCleanup(void *data){    /*     * We walk the hash by nonceb64 as that is the unique key we     * use.  For big hash tables we could consider stepping through     * the cache, 100/200 entries at a time. Lets see how it flies     * first.     */    digest_nonce_h *nonce;    debug(29, 3) ("authenticateDigestNonceCacheCleanup: Cleaning the nonce cache now\n");    debug(29, 3) ("authenticateDigestNonceCacheCleanup: Current time: %ld\n",	(long int) current_time.tv_sec);    hash_first(digest_nonce_cache);    while ((nonce = ((digest_nonce_h *) hash_next(digest_nonce_cache)))) {	debug(29, 3) ("authenticateDigestNonceCacheCleanup: nonce entry  : %p '%s'\n", nonce, (char *) nonce->hash.key);	debug(29, 4) ("authenticateDigestNonceCacheCleanup: Creation time: %ld\n", (long int) nonce->noncedata.creationtime);	if (authDigestNonceIsStale(nonce)) {	    debug(29, 4) ("authenticateDigestNonceCacheCleanup: Removing nonce %s from cache due to timeout.\n", (char *) nonce->hash.key);	    assert(nonce->flags.incache);	    /* invalidate nonce so future requests fail */	    nonce->flags.valid = 0;	    /* if it is tied to a auth_user, remove the tie */	    authDigestNonceUserUnlink(nonce);	    authDigestNoncePurge(nonce);	}    }    debug(29, 3) ("authenticateDigestNonceCacheCleanup: Finished cleaning the nonce cache.\n");    if (authenticateDigestActive())	eventAdd("Digest none cache maintenance", authenticateDigestNonceCacheCleanup, NULL, digestConfig->nonceGCInterval, 1);}static voidauthDigestNonceLink(digest_nonce_h * nonce){    assert(nonce != NULL);    nonce->references++;    debug(29, 9) ("authDigestNonceLink: nonce '%p' now at '%d'.\n", nonce, nonce->references);}#if NOT_USEDstatic intauthDigestNonceLinks(digest_nonce_h * nonce){    if (!nonce)	return -1;    return nonce->references;}#endifstatic voidauthDigestNonceUnlink(digest_nonce_h * nonce){    assert(nonce != NULL);    if (nonce->references > 0) {	nonce->references--;    } else {	debug(29, 1) ("authDigestNonceUnlink; Attempt to lower nonce %p refcount below 0!\n", nonce);    }    debug(29, 9) ("authDigestNonceUnlink: nonce '%p' now at '%d'.\n", nonce, nonce->references);    if (nonce->references == 0)	authenticateDigestNonceDelete(nonce);}static const char *authenticateDigestNonceNonceb64(digest_nonce_h * nonce){    if (!nonce)	return NULL;    return nonce->hash.key;}static digest_nonce_h *authenticateDigestNonceFindNonce(const char *nonceb64){    digest_nonce_h *nonce = NULL;    if (nonceb64 == NULL)	return NULL;    debug(29, 9) ("authDigestNonceFindNonce:looking for nonceb64 '%s' in the nonce cache.\n", nonceb64);    nonce = hash_lookup(digest_nonce_cache, nonceb64);    if ((nonce == NULL) || (strcmp(nonce->hash.key, nonceb64)))	return NULL;    debug(29, 9) ("authDigestNonceFindNonce: Found nonce '%p'\n", nonce);    return nonce;}static intauthDigestNonceIsValid(digest_nonce_h * nonce, char nc[9]){    unsigned long intnc;    /* do we have a nonce ? */    if (!nonce)	return 0;    intnc = strtol(nc, NULL, 16);    /* has it already been invalidated ? */    if (!nonce->flags.valid) {	debug(29, 4) ("authDigestNonceIsValid: Nonce already invalidated\n");	return 0;    }    /* is the nonce-count ok ? */    if (!digestConfig->CheckNonceCount) {	nonce->nc++;	return -1;		/* forced OK by configuration */    }

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -