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

📄 pgpkeydb.c

📁 PGP8.0源码 请认真阅读您的文件包然后写出其具体功能
💻 C
📖 第 1 页 / 共 3 页
字号:
	 * Add object to this keydb
	 * Problem: what if object is a sig?  We need to add parents too
	 * But if we are iterating and adding all objects, it is wasteful
	 * to re-add all parents.
	 * Unless we can check quickly if we have them.
	 * This is similar to logic in initial read.
	 * In fact it might be identical - read each object and its data,
	 * add in self-contained way to keydb.
	 * No, better to read each object's data into a buffer, add that.
	 * So the low level add function takes an object's data, and takes
	 * a parent object, and adds it.  If parent is null then it puts it
	 * in as a top level key.
	 * Problem is this requires us to parse it twice as we are reading
	 * from keyring.  Not really, just have to parse the type of the
	 * packet.
	 */

	/* Count how far we are from the top (0=top, 1=one layer down, etc.) */
	parobj = obj;
	count = 0;
	while( !OBJISTOPKEY(parobj) )
	{
		++count;
		parobj = parobj->up;
	}
	pgpAssert( count <= 2 );

	/* Add object and its parents, starting from the top and working down */
	newparobj = NULL;
	for (i=count; i>=0; --i)
	{
		parobj = obj;
		for (j=0; j<i; ++j)
			parobj = parobj->up;

		/* Check our local cache of parents */
		if( (count-i) < 2  &&  kdb->oldobjs[count-i] == parobj )
		{
			newparobj = kdb->newobjs[count-i];
			continue;
		}

		objdata = pgpFetchObject( parobj, &objdatalen );
		/*
		 * This is the low level add function, also used during keyring
		 * read.  It returns the object we added.  Should be optimized to
		 * be fast for the case where we are adding an already existing
		 * object.
		 */
		newparobj = pgpAddObject(objdata, objdatalen, kdb, newparobj, FALSE,
								 &err);
		if( IsPGPError( err )  ||  IsNull( newparobj ) )
			goto error;
		pgpCopyObjectTrust( parobj, newparobj );

		/* Cache our results */
		if( count-i < 2 )
		{
			kdb->oldobjs[count-i]	= parobj;
			kdb->newobjs[count-i]	= newparobj;
		}
	}
	pgpKeyDBChanged( kdb, FALSE );
	if( IsntNull( pnewobj ) )
		*pnewobj = newparobj;
 error:
	return err;
}


	PGPError
pgpKeyDBAddObject (PGPKeyDBRef kdb, PGPKeyDBObj *obj, PGPKeyDBObjRef *pnewobj)
{
	PGPError				err = kPGPError_NoErr;

	if( pgpFrontEndKeyDB( kdb ) )
	{
		PGPUInt32 *newobjs;
		PGPSize newobjslen;
		PGPUInt32 newobjid;

		err = pgpKeyDBAddObject_back( PGPPeekKeyDBContext(kdb), kdb->id,
									  pgpKeyDBObjID(obj), &newobjs,
									  &newobjslen, &newobjid );
		if( IsPGPError( err ) )
			return err;
		err = pgpAddFromKeyArray( kdb, NULL, newobjs, 1, FALSE );
		PGPFreeData( newobjs );
		pgpKeyDBChanged( kdb, FALSE );
		if( IsntNull( pnewobj ) )
			(void)PGPFindNode( kdb->idToObj, newobjid,
							   (PGPUserValue *)pnewobj );
			
		return err;
	}

	return pgpKeyDBAddObject_internal( kdb, obj, pnewobj );
}


	PGPError
pgpKeyDBRemoveObject_internal (PGPKeyDBRef kdb, PGPKeyDBObj *obj)
{
	PGPError		err;

	(void) kdb;
	pgpAssert( PGPPeekKeyDBObjKeyDB(obj) == kdb );

	/* Don't allow deletion of last userid on key */
	if( OBJISUSERID( obj ) )
	{
		PGPKeyDBObj *	parent;
		PGPKeyDBObj *	child;
		PGPUInt32		useridcount;
		useridcount = 0;
		parent = obj->up;
		pgpAssert( OBJISTOPKEY( parent ) );
		for( child=parent->down; IsntNull(child); child=child->next )
		{
			if( !pgpKeyDBObjIsReal( child ) )
				continue;
			if( OBJISUSERID( obj ) )
			{
				++useridcount;
			}
		}
		if( useridcount < 2 )
			return kPGPError_BadParams;
	}

	/* Don't allow deletion of last self-signature on a userid */
	if( OBJISSIG( obj ) && OBJISUSERID( obj->up ) )
	{
		PGPKeyDBObj *	parent;
		PGPKeyDBObj *	topkey;
		PGPKeyDBObj *	child;
		PGPUInt32		selfsigcount;
		selfsigcount = 0;
		parent = obj->up;
		topkey = parent->up;
		pgpAssert( OBJISUSERID( parent ) );
		pgpAssert( OBJISTOPKEY( topkey ) );
		if( OBJISSIG( obj )
			&& pgpSigMaker( obj ) == topkey )
		{
			for( child=parent->down; IsntNull(child); child=child->next )
			{
				if( !pgpKeyDBObjIsReal( child ) )
					continue;
				if( OBJISSIG( child )
					&& pgpSigMaker( child ) == topkey
					&& (pgpSigType( child ) & 0xf0) == PGP_SIGTYPE_KEY_GENERIC
					&& !pgpSigRevoked( child ) )
				{
					++selfsigcount;
				}
			}
			if( selfsigcount < 2 )
				return kPGPError_DeletingSelfSig;
		}
	}
				
	err = pgpMarkKeyDBObjectDeleted( obj );
	pgpKeyDBChanged ( kdb, FALSE );
	return err;
}

	PGPError
pgpKeyDBRemoveObject (PGPKeyDBRef kdb, PGPKeyDBObj *obj)
{
	PGPError		err;

	(void) kdb;
	pgpAssert( PGPPeekKeyDBObjKeyDB(obj) == kdb );

	if( !pgpKeyDBObjIsReal( obj ) )
		return kPGPError_BadParams;

	if( pgpFrontEndKeyDB( kdb ) )
	{
		err = pgpKeyDBRemoveObject_back( PGPPeekKeyDBContext(kdb), kdb->id,
										 pgpKeyDBObjID(obj) );
		if( IsPGPError( err ) )
			return err;
		pgpMarkKeyDBObjectDeleted( obj );
		pgpKeyDBChanged ( kdb, FALSE );
		return err;
	}

	return pgpKeyDBRemoveObject_internal( kdb, obj );
}


/* True if a front end keydb */
	PGPBoolean
pgpFrontEndKeyDB( PGPKeyDBRef kdb )
{
	return kdb->id != 0;
}


/* Flush any necessary changes out to backing store if present */
	PGPError
pgpKeyDBFlush_internal (PGPKeyDBRef kdb, PGPKeySetRef changedSet)
{
	PGPError        error;
	
	if (!kdb->bmutable)
		return kPGPError_ItemIsReadOnly;

	if (!kdb->bdirty)
		return kPGPError_NoErr;

	/* Recheck sigs before writing out */
	error = pgpCheckKeyRingSigs_internal( kdb->rootSet, NULL, FALSE, 0, 0,
										  changedSet);
	if( IsPGPError( error ) )
		return error;
	error = pgpPropagateTrustInternal( kdb->rootSet, NULL, PGPGetTime(),
									   changedSet );
	if( IsPGPError( error ) )
		return error;

	pgpAssert( IsntNull( kdb->pubFile ) );

	error = sWriteKeyRings (kdb);

	if (error)
		return error;
	kdb->bdirty = 0;

	return kPGPError_NoErr;
}

	static PGPError
pgpKeyDBFlushInternal (PGPKeyDBRef kdb)
{
	PGPError err;

	if( pgpFrontEndKeyDB( kdb ) ) {
		PGPUInt32 *changelist;
		PGPSize changelistsize;

		if( IsPGPError( err = pgpKeyDBFlush_back( PGPPeekKeyDBContext(kdb),
							kdb->id, &changelist, &changelistsize ) ) )
			return err;
		err = pgpKeyRefreshFromList( kdb, changelist, changelistsize );
		kdb->bdirty = 0;
		return err;
	}

	return pgpKeyDBFlush_internal( kdb, NULL );
}




	PGPError
PGPFilterKeyDB( PGPKeyDBRef keyDB, PGPFilterRef filter,PGPKeySetRef *resultSet)
{
	PGPValidateKeyDB( keyDB );

	pgpEnterPGPErrorFunction();

	return PGPFilterKeySet( keyDB->rootSet, filter, resultSet );
}


	PGPBoolean
pgpKeyDBIsValid( PGPKeyDB const *	keyDB)
{
	return( IsntNull( keyDB ) && keyDB->fixedMagic == kPGPKeyDBMagic );
}

#if PGP_DEBUG	/* [ */
	PGPBoolean
pgpaInternalPGPKeyDBValid(
	pgpaCallPrefixDef,
	PGPKeyDB const *	keyDB,
	char const *		varName)
{
	pgpaAddrValid(keyDB, PGPKeyDB);
	pgpaFailIf((keyDB->refCount <= 0) && !keyDB->bcached, (pgpaFmtPrefix, "refCount <= 0"));
	pgpaFmtMsg((pgpaFmtPrefix,
			"pgpaPGPKeyDBValid failed on %s (%p)", varName, keyDB));

	return pgpaFailed;
}
#endif /* ] PGP_DEBUG */


	PGPError
PGPIncKeyDBRefCount( PGPKeyDBRef kdb )
{
	PGPValidateKeyDB( kdb );

	pgpEnterPGPErrorFunction();

	++kdb->refCount;
	return kPGPError_NoErr;
}


	void
pgpKeyDBDestroy_internal (PGPKeyDBRef kdb)
{
	PGPKeySetRef		set;
	PGPKeyDBRef			kdbprev;
	PGPNotification *	nt;

	pgpAssertAddrValid( kdb, PGPKeyDB );

	/* First flush out any changes, even if not last copy of keydb */
	if( kdb->bmutable )
	{
		/* Mac does not use front-end/back-end distinction the same way */
#if !PGP_MACINTOSH
		if( !pgpFrontEndKeyDB( kdb ) ) 
#endif
			pgpKeyDBFlushInternal( kdb );
	}

	if( kdb->refCount <= 1 &&
		! ( kdb->bcached && (PGPGetTime() < kdb->cacheclose) ) )
	{
		PGPUInt32 id = kdb->id;
		PGPContextRef context = kdb->context;
		
		if( kdb->pubFile )
			pgpFileClose( kdb->pubFile );
		if( kdb->pubFileRef )
			PFLFreeFileSpec( kdb->pubFileRef );
		if( kdb->privFile )
			pgpFileClose( kdb->privFile );
		if( kdb->privFileRef )
			PFLFreeFileSpec( kdb->privFileRef );
		
		for( set=kdb->firstSetInDB; IsntNull(set);  )
		{
			pgpFreeKeySet( set, TRUE );
			/* Freeing keyset fixes up list so we can just stay at beginning */
			set = kdb->firstSetInDB;
		}

		memPoolEmpty( &kdb->objPool );
		memPoolEmpty( &kdb->structPool );
		memPoolEmpty( &kdb->pathpool );
		memPoolEmpty( &kdb->regexps );

		PGPDisposeBinaryTree( kdb->idToObj );

		/* Unlink kdb from context list */
		kdbprev = pgpContextGetFirstKeyDB( kdb->context );
		if( kdbprev == kdb )
		{
			pgpContextSetFirstKeyDB( kdb->context, kdb->next );
		} else {
			while( kdbprev->next != kdb )
				kdbprev = kdbprev->next;
			kdbprev->next = kdb->next;
		}

		nt = kdb->notifies;
		while( IsntNull( nt ) )
		{
			PGPNotification *ntnext = nt->next;
			PGPFreeData( nt );
			nt = ntnext;
		}

		PGPFreeData( kdb );

		if( id != 0 )
		{
			pgpFreeKeyDB_back( context, id );
		}

	} else {
		if( !pgpFrontEndKeyDB( kdb ) )
			sRemoveNotification( kdb );

		--kdb->refCount;
	}
	return;
}

	static void
pgpKeyDBDestroyInternal (PGPKeyDBRef kdb)
{
	pgpKeyDBDestroy_internal( kdb );
}


	PGPError
PGPFreeKeyDB(PGPKeyDBRef kdb)
{
	PGPValidateKeyDB( kdb );

	pgpEnterPGPErrorFunction();

	pgpKeyDBDestroyInternal( kdb );
	return kPGPError_NoErr;
}


/* Call periodically to check for expiration of cached keydbs */
/* This is called from a different thread than the main one */
/* The caller must arrange for non-contention with the main thread */
	void
pgpExpireKeyDBCache( PGPContextRef context )
{
	PGPTime			curtime;
	PGPKeyDBRef		kdb;
	PGPKeyDBRef		kdbnext;

	curtime = PGPGetTime();

	kdb = pgpContextGetFirstKeyDB( context );
	while( IsntNull( kdb ) )
	{
		kdbnext = pgpKeyDBNextKeyDB( kdb );
		if( kdb->refCount < 1 &&
			! ( kdb->bcached && (PGPGetTime() < kdb->cacheclose) ) )
		{
			pgpKeyDBDestroyInternal( kdb );
		}
		kdb = kdbnext;
	}
}


/* Call to find out if any keydbs are currently cached */
/* The caller must arrange for non-contention with the main thread */
	PGPBoolean
pgpIsKeyDBCached( PGPContextRef context )
{
	PGPKeyDBRef		kdb;
	PGPKeyDBRef		kdbnext;

	kdb = pgpContextGetFirstKeyDB( context );
	while( IsntNull( kdb ) )
	{
		kdbnext = pgpKeyDBNextKeyDB( kdb );

		if( kdb->bcached )
			return TRUE;

		kdb = kdbnext;
	}
	return FALSE;
}


/* Call to clear all cached keydbs */
	PGPError
pgpPurgeKeyDBCache_internal( PGPContextRef context )
{
	PGPKeyDBRef		kdb;
	PGPKeyDBRef		kdbnext;

	kdb = pgpContextGetFirstKeyDB( context );
	while( IsntNull( kdb ) )
	{
		kdbnext = pgpKeyDBNextKeyDB( kdb );
		if( kdb->refCount < 1 )
		{
			kdb->bcached = FALSE;
			kdb->cacheclose = (PGPTime)0;
			kdb->refCount = 1;	/* Suppress warnings on invalid keydb */
			pgpKeyDBDestroyInternal( kdb );
		}
		kdb = kdbnext;
	}

	return kPGPError_NoErr;
}


/* Call to clear all cached keydbs */
	PGPError
PGPPurgeKeyDBCache( PGPContextRef context )
{
	pgpEnterPGPErrorFunction();

	PGPValidateContext( context );

	if (pgpRPCEnabled())
		return pgpPurgeKeyDBCache_back(context);

	return pgpPurgeKeyDBCache_internal(context);
}

	PGPError
pgpCacheKeyDB_internal( PGPKeyDBRef keydb, PGPUInt32 timeoutSeconds )
{
	PGPValidateKeyDB( keydb );

	keydb->bcached = TRUE;
	keydb->cacheclose = PGPGetTime() + timeoutSeconds;

	return kPGPError_NoErr;
}


/*
 * Call to set a keydb as cached so we don't close it when the last
 * user stops using it.
 */
	PGPError
PGPCacheKeyDB( PGPKeyDBRef keydb, PGPUInt32 timeoutSeconds )
{
	PGPValidateKeyDB( keydb );

	pgpEnterPGPErrorFunction();

	if (pgpRPCEnabled())
		return pgpCacheKeyDB_back( keydb->context, keydb->id, timeoutSeconds );

	return pgpCacheKeyDB_internal(keydb, timeoutSeconds);
}


static void
pgpKeyDBInit( PGPContextRef context, PGPKeyDB *kdb )
{
	pgpClearMemory( kdb, sizeof(*kdb) );

	kdb->fixedMagic = kPGPKeyDBMagic;

	kdb->context	= context;
	kdb->refCount	= 1;
	
	memPoolInit( context, &kdb->objPool);
	memPoolInit( context, &kdb->structPool );
	memPoolInit( context, &kdb->pathpool );
	memPoolInit( context, &kdb->regexps );

	PGPNewBinaryTree( PGPPeekContextMemoryMgr(context), &kdb->idToObj );

	kdb->rootSet = pgpRootSet( kdb );

	/* Link kdb into context list */
	kdb->next = pgpContextGetFirstKeyDB( context );
	pgpContextSetFirstKeyDB( context, kdb );

	/* Register for notifications if we are backend */
	sAddNotification( kdb );
}

	PGPKeySet *
pgpKeyDBPeekRootSet( PGPKeyDB *kdb )
{
	pgpa(pgpaPGPKeyDBValid(kdb));

	return kdb->rootSet;
}

⌨️ 快捷键说明

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