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

📄 pgppasscach.c

📁 PGP8.0源码 请认真阅读您的文件包然后写出其具体功能
💻 C
📖 第 1 页 / 共 2 页
字号:
/*____________________________________________________________________________
	Copyright (C) 2002 PGP Corporation
	All rights reserved.
	
	$Id: pgpPassCach.c,v 1.32 2002/08/24 03:50:09 jason Exp $
____________________________________________________________________________*/

/*
 * A Passphrase Cache -- keep a cache of passphrases and
 * try them against ESKs and Secret Keys.  This way you only have to
 * type your passphrase once, it gets cached, and then it gets used
 * again and again.
 */

#include <string.h>
#include "pgpConfig.h"
#include <stdio.h>

#include "pgpMem.h"
#include "pgpPassCach.h"
#include "pgpErrors.h"
#include "pgpPubKey.h"
#include "pgpEnv.h"
#include "pgpContext.h"
#include "pgpKeyPriv.h"
#include "pgpThreads.h"
#include "pgpBinaryTree.h"

#define FOREVER		MAX_PGPUInt32

struct PGPCacheHeader {
	PGPContextRef	context;
	PGPUInt32		nCached;
	struct PGPPassCache	*globalCache;
	struct PGPPassCache	*localCaches;
};

struct PGPPassCache {
	struct PGPPassCache *next;
	PGPConnectRef	clientID;
	PGPBoolean		globalCache;
	PGPKeyID		keyID;
	PGPUInt32		timeoutInterval; /* timeout interval in secs */
	PGPTime			timeoutTime;      /* absolute time this entry expires */
	PGPByte *		hashedPhrase;
	PGPSize			hashedPhraseLength;
	PGPByte *		userName;		/* only used on global cache */
};

/* Mutex to protect local data structures.  Some are accessed by a
 * separate thread.
 */
PGPMutex_t gPassCacheMutex;

/* Passcache clients list, userValue is connectRef */
static PGPBinaryTreeRef pcClients;
static PGPUInt32		numClients = 0;


/* Proc to notify clients */
	static PGPError
sNotifyProc( PGPUserValue uv, PGPInt32 nodeKey, PGPUserValue nodeuv )
{
	(void) uv;
	(void) nodeKey;
	(void) nodeuv;
#if PGP_WIN32 || PGP_OSX
	pgpNotifyClient( (PGPConnectRef)nodeKey,
					 kPGPNotification_PassphraseCacheChanged );
#endif
	return kPGPError_NoErr;
}

/* Create the passphrase cache header and add to the context */
	static PGPError
sInitPassphraseCache( PGPContextRef context )
{
	struct PGPCacheHeader *	cacheHeader;

	cacheHeader = pgpContextMemAlloc( context, sizeof(*cacheHeader), 0 );
	if( IsNull( cacheHeader ) )
		return kPGPError_OutOfMemory;

	pgpClearMemory( cacheHeader, sizeof(*cacheHeader) );

	cacheHeader->context = context;
	pgpContextSetPassphraseCache( context, cacheHeader);
	return kPGPError_NoErr;
}


/* Destroy data in a given passphrase cache entry */
	static void
sDestroyPassCache( struct PGPPassCache *cache )
{
	if( IsntNull( cache->hashedPhrase ) )
	{
		pgpClearMemory( cache->hashedPhrase, cache->hashedPhraseLength );
		PGPFreeData( cache->hashedPhrase );
	}
	if( IsntNull( cache->userName ) )
	{
		PGPFreeData( cache->userName );
	}
	pgpClearMemory( cache, sizeof(*cache) );
	PGPFreeData( cache );
}

/* Given a pointer to a pointer to the cache, destroy and remove it */
	static void
sExpirePassCache( struct PGPPassCache **cachePtr )
{
	struct PGPPassCache *	cache;
	struct PGPPassCache *	cachenext;

	cache = *cachePtr;
	cachenext = cache->next;
	sDestroyPassCache( cache );
	*cachePtr = cachenext;
}
	
	PGPError
pgpPurgePassphraseCache_internal( PGPContextRef context )
{
	struct PGPCacheHeader *	cacheHeader;
	struct PGPPassCache *	cache;
	struct PGPPassCache *	nextcache;
	PGPBoolean freed = FALSE;

	PGPMutexLock(&gPassCacheMutex);

	cacheHeader = pgpContextGetPassphraseCache( context );
	if( IsntNull( cacheHeader ) )
	{
		cache = cacheHeader->globalCache;
		while( IsntNull(cache) )
		{
			nextcache = cache->next;
			sDestroyPassCache( cache );
			cache = nextcache;
			freed = TRUE;
		}

		cache = cacheHeader->localCaches;
		while( IsntNull(cache) )
		{
			nextcache = cache->next;
			sDestroyPassCache( cache );
			cache = nextcache;
			freed = TRUE;
		}

		cacheHeader->globalCache = NULL;
		cacheHeader->localCaches = NULL;
		cacheHeader->nCached = 0;

		pgpClearMemory( cacheHeader, sizeof(*cacheHeader) );
		PGPFreeData( cacheHeader );
		pgpContextSetPassphraseCache( context, NULL);
		if( freed && IsntNull(pcClients) )
			PGPInOrderTraversal( pcClients, sNotifyProc, 0 );
	}

	PGPMutexUnlock(&gPassCacheMutex);
	return kPGPError_NoErr;
}




/* Put the given passphrase into the cache for the given keyID */
	static PGPError
sCachePassphraseInternal(PGPContextRef context, PGPKeyID keyID,
	PGPByte const *passPhrase, PGPSize passLength,
	PGPUInt32 cacheTimeOut, PGPBoolean globalCache)
{
	struct PGPCacheHeader *	cacheHeader;
	struct PGPPassCache *	cache;
	PGPConnectRef			clientID = kPGPConnectRef_Null;
	PGPTime					now;
	PGPByte *				userName = NULL;
	PGPSize					userNameLength = 0;
	PGPBoolean				someAdded = FALSE;

	cacheHeader = pgpContextGetPassphraseCache( context );
	if( IsNull( cacheHeader ) )
	{
		if( IsPGPError( sInitPassphraseCache( context ) ) )
			return kPGPError_NoErr;
		cacheHeader = pgpContextGetPassphraseCache( context );
	}

	if( globalCache )
	{
		cache = cacheHeader->globalCache;
#if ! PGP_OSX && (PGP_WIN32 || PGP_UNIX)
		{
			pgpRPCconnection *connectRef;
			clientID = pgpContextGetConnectRef( context );
			connectRef = (pgpRPCconnection *) clientID;
			if( IsntNull( connectRef ) && IsntNull( connectRef->UserName ) )
			{
				userName = connectRef->UserName;
				userNameLength = strlen( userName );
			}
		}
#endif
	} else {
		clientID = pgpContextGetConnectRef( context );
		cache = cacheHeader->localCaches;
	}

	while( IsntNull(cache) )
	{
		pgpAssert( !cache->globalCache == !globalCache );
		if( pgpConnectRefEqual(cache->clientID, clientID) &&
			(IsNull(userName) || 0 == strcmp((char *) userName, (char *) cache->userName) ) &&
			PGPCompareKeyIDs( &cache->keyID, &keyID ) == 0 )
		{
			/* Found matching entry */
			break;
		}
		cache = cache->next;
	}

	if( IsNull( cache ) )
	{
		cache = (struct PGPPassCache *) pgpContextMemAlloc( context,
												sizeof (*cache), 0 );
		if( IsNull( cache ) )
			return kPGPError_OutOfMemory;
		
		pgpClearMemory( cache, sizeof (*cache) );
		cache->globalCache = !!globalCache;
		cache->clientID = clientID;
		cache->keyID = keyID;
		if( globalCache )
		{
			cache->next = cacheHeader->globalCache;
			cacheHeader->globalCache = cache;
			if( IsntNull( userName ) )
			{
				cache->userName = (PGPByte *) pgpContextMemAlloc( context,
													userNameLength+1, 0 );
				if( IsntNull( cache->userName ) )
					pgpCopyMemory( userName, cache->userName,
								   userNameLength+1 );	/* null terminate */
			}
		} else {
			cache->next = cacheHeader->localCaches;
			cacheHeader->localCaches = cache;
		}
		cacheHeader->nCached++;
		someAdded = TRUE;
	}

	if( IsntNull( cache->hashedPhrase ) )
		PGPFreeData( cache->hashedPhrase );

	cache->hashedPhrase = (PGPByte *)PGPNewSecureData(
						PGPPeekContextMemoryMgr( context ), passLength, 0 );
	pgpCopyMemory( passPhrase, cache->hashedPhrase, passLength );
	cache->hashedPhraseLength = passLength;

	cache->timeoutInterval = cacheTimeOut;
	now = PGPGetTime();
	cache->timeoutTime = now + cache->timeoutInterval;
	if( cache->timeoutTime < now )
		cache->timeoutTime = FOREVER;

	if( someAdded && IsntNull(pcClients) )
		PGPInOrderTraversal( pcClients, sNotifyProc, 0 );

	return kPGPError_NoErr;
}


/* Retrieve the cached passphrase if any for the given keyID */
	static PGPError
sRetrieveCachedPassphraseInternal(PGPContextRef context, PGPKeyID keyID,
	PGPByte const **passPhrase, PGPSize *passLength)
{
	struct PGPCacheHeader *	cacheHeader;
	struct PGPPassCache *	cache;
	PGPConnectRef			clientID;
	PGPTime					now;
	PGPByte *				userName = NULL;

	*passPhrase = NULL;
	*passLength = 0;

	cacheHeader = pgpContextGetPassphraseCache( context );
	if( IsNull( cacheHeader ) )
	{
		if( IsPGPError( sInitPassphraseCache( context ) ) )
			return kPGPError_NoErr;
		cacheHeader = pgpContextGetPassphraseCache( context );
	}

	clientID = pgpContextGetConnectRef( context );
#if ! PGP_OSX && (PGP_WIN32 || PGP_UNIX)
	{
		pgpRPCconnection *connectRef = (pgpRPCconnection *) clientID;
		if( IsntNull( connectRef ) && IsntNull( connectRef->UserName ) )
		{
			userName = connectRef->UserName;
		}
	}
#endif

	/*
	 * Search for matching cache entries.  Skip those which have expired,
	 * they will be removed shortly by the expiration thread.
	 */
	now = PGPGetTime();
	cache = cacheHeader->globalCache;
	while( IsntNull(cache) )
	{
		if( PGPCompareKeyIDs( &cache->keyID, &keyID) == 0  &&
			(IsNull(userName) || 0 == strcmp((char *) userName,
											 (char *) cache->userName) ) &&
			cache->timeoutTime >= now )
		{
			*passLength = cache->hashedPhraseLength;
			*passPhrase = cache->hashedPhrase;
			cache->timeoutTime = now + cache->timeoutInterval;
			if( cache->timeoutTime < now )
				cache->timeoutTime = FOREVER;
			return kPGPError_NoErr;
		}
		cache = cache->next;
	}

	cache = cacheHeader->localCaches;
	while( IsntNull(cache) )
	{
		if( pgpConnectRefEqual(cache->clientID, clientID) &&
			PGPCompareKeyIDs( &cache->keyID, &keyID ) == 0 &&
			cache->timeoutTime >= now )
		{
			*passLength = cache->hashedPhraseLength;
			*passPhrase = cache->hashedPhrase;
			cache->timeoutTime = now + cache->timeoutInterval;
			if( cache->timeoutTime < now )
				cache->timeoutTime = FOREVER;
			return kPGPError_NoErr;
		}
		cache = cache->next;
	}
	return kPGPError_BadPassphrase;
}




/*
 * Unlock the given secret key, using the specified passphrase or one
 * from the cache if available.  Also cache the passphrase if requested.
 */
	PGPError
pgpSecKeyUnlockWithCache( PGPSecKey *sec, PGPByte const *passphrase,
	PGPSize passphraseLength, PGPBoolean hashedPhrase, PGPUInt32 cacheTimeOut,
	PGPBoolean cacheGlobal )
{
	PGPKeyID keyID;
	PGPContextRef context;
	PGPEnv *pgpEnv;
	PGPByte *passBuffer;
	PGPSize bufsize;
	PGPError err = kPGPError_NoErr;
	PGPBoolean usedCache = FALSE;
	PGPBoolean checkedPhrase = FALSE;
	PGPBoolean mustFree = FALSE;

	PGPMutexLock(&gPassCacheMutex);

	context = sec->context;
	pgpEnv = pgpContextGetEnvironment( context );
	pgpNewKeyIDFromRawData( sec->keyID, sec->pkAlg, 8, &keyID );

	if( passphraseLength == 0 )
		passphrase = NULL;

	if (pgpSecKeyIslocked (sec)) {

⌨️ 快捷键说明

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