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

📄 pgpkeyset.c

📁 著名的加密软件的应用于电子邮件中
💻 C
📖 第 1 页 / 共 2 页
字号:
		}
		(*db->destroy)(db);
		pgpKeyDBDestroyInternal (db);
	}
}

static Boolean
rootSetIsMember(PGPKeySet *set, RingObject const *obj)
{
	pgpa((
		pgpaPGPKeySetValid(set),
		pgpaAddrValid(obj, VoidAlign)));	/* XXX use better align check */

	return ringSetIsMember(pgpKeyDBRingSet(set->keyDB), obj);
}

static void
rootSetDestroy(PGPKeySet *set)
{
	(void)set;	/* Avoid warning */
}

Boolean
pgpKeySetMember(PGPKeySet *set, PGPKey *key)
{
	pgpa((
		pgpaPGPKeySetValid(set),
		pgpaPGPKeyValid(key)));
	
	return (*set->isMember)(set, key->key);
}

PGPKeySet *
pgpKeyDBRootSet(PGPKeyDB *db)
{
	PGPKeySet *		set;

	pgpa(pgpaPGPKeyDBValid(db));

/*	set = pgpNew(PGPKeySet); */
	set = (PGPKeySet *)pgpAlloc(sizeof(PGPKeySet));
	if (set != NULL)
	{
		pgpIncKeyDBRefCount(db);

		set->private = NULL;
		set->refCount = 1;
		set->keyDB = db;

		set->prevSetInDB = NULL;
		set->nextSetInDB = db->firstSetInDB;
		if (set->nextSetInDB)
		set->nextSetInDB->prevSetInDB = set;
		db->firstSetInDB = set;

		set->firstListInSet = NULL;

		set->isMember = rootSetIsMember;
		set->destroy = rootSetDestroy;
	}
	return set;
}

/*
* This shortcut version will not work once we implement filtering, but
* for now all keysets are the same, differing only in their keydb's.
*/
PGPKeySet *
pgpCopyKeySet (PGPKeySet *set)
{
	PGPKeyDB	*db;
	PGPKeySet	 *newset;

	db = set->keyDB;
	newset = pgpKeyDBRootSet (db);
	if (!newset)
		return NULL;
	newset->isMember = set->isMember;
	newset->destroy = set->destroy;
	return newset;
}

RingSet *
pgpKeyDBRingSet(PGPKeyDB *db)
{
	pgpa(pgpaPGPKeyDBValid(db));

	return (*db->getRingSet)(db);
}

Boolean
pgpKeyDBIsMutable(PGPKeyDB *db)
{
	pgpa(pgpaPGPKeyDBValid(db));

	return (*db->isMutable)(db);
}

Boolean
pgpKeyDBIsDirty(PGPKeyDB *db)
{
	pgpa(pgpaPGPKeyDBValid(db));

	return (*db->isDirty)(db);
}

/*
* Call this when we have made a change to the keys in the changedkeys set,
* to force those keys to be resorted in all lists depending on the db
*/
PGPError
pgpKeyDBChanged(PGPKeyDB *db, RingSet *changedkeys)
{
	return (*db->changed)(db, changedkeys);
}

PGPError
pgpCommitKeyDB(PGPKeyDB *db)
{
	RingSet		*rset;
	PGPError		error;
	int				count;

	pgpa(pgpaPGPKeyDBValid(db));

	rset = pgpKeyDBRingSet (db);
	if (!rset)
		return PGPERR_NOMEM;
	/* XXX This can take a while, need a progress bar? */
	error = ringPoolCheck (rset, rset, 0, 0, 0);
	if (error)
		return error;
	count = ringMnt (rset, 0, pgpGetTime());
	if (count < 0)
		return (PGPError) count;
	return (*db->commit)(db);
}

PGPError
pgpCheckKeyDB (PGPKeyDB *db)
{
	RingSet *rset;

	pgpa(pgpaPGPKeyDBValid(db));
	
	rset = pgpKeyDBRingSet (db);
	if (!rset)
		return PGPERR_NOMEM;
	/* XXX This can take a while, need a progress bar? */
	return ringPoolCheck (rset, rset, 1, 0, 0);
}


PGPError
pgpRevertKeyDB(PGPKeyDB *db)
{
	pgpa(pgpaPGPKeyDBValid(db));

	return (*db->revert)(db);
}

PGPError
pgpReloadKeyDB(PGPKeyDB *db)
{
	pgpa(pgpaPGPKeyDBValid(db));

	return (*db->reload)(db);
}

PGPError
pgpCommitKeyRingChanges(PGPKeySet *keys)
{
	pgpa(pgpaPGPKeySetValid(keys));

	return pgpCommitKeyDB(keys->keyDB);
}

PGPError
pgpRevertKeyRingChanges(PGPKeySet *keys)
{
	pgpa(pgpaPGPKeySetValid(keys));

	return pgpRevertKeyDB(keys->keyDB);
}

/* Check all sigs in keyset */
PGPError
pgpCheckKeyRingCertificates (PGPKeySet *keys)
{
	return pgpCheckKeyDB (keys->keyDB);
}

PGPError
pgpReloadKeyRings(PGPKeySet *keys)
{
	pgpa(pgpaPGPKeySetValid(keys));

	return pgpReloadKeyDB(keys->keyDB);
}

void
pgpIncKeySetRefCount(PGPKeySet *keys)
{
	pgpa(pgpaPGPKeySetValid(keys));

	keys->refCount++;
}

PGPKeySet *
pgpNewKeySet ()
{
	PGPKeyDB		*memdb;
	PGPKeySet		*set;

	memdb = pgpKeyDBCreate();
	if (!memdb)
		return NULL;
	set = pgpKeyDBRootSet (memdb);
	pgpFreeKeyDB(memdb);
	return set;
}

PGPKeySet *
pgpNewSingletonKeySet (PGPKey *key)
{
	PGPKeyDB		*memdb;
	PGPKeySet		*set = NULL;
	RingSet			*rset;
	RingSet			*tmpset = NULL;
	PGPError		error;

	memdb = pgpKeyDBCreate();
	if (!memdb)
		return NULL;
	rset = pgpKeyDBRingSet (key->keyDB);
	if (!rset)
		goto done;
	error = pgpCopyKey (rset, key->key, &tmpset);
	if (error)
		goto done;
	error = pgpAddObjects (memdb, tmpset);
	if (error)
		goto done;
	set = pgpKeyDBRootSet (memdb);
done:
	if (tmpset)
		ringSetDestroy (tmpset);
	pgpFreeKeyDB(memdb);
	return set;
}



/* Add all the objects in the second key set into the first. */
PGPError
pgpAddKeys (PGPKeySet *set, PGPKeySet *keysToAdd)
{
	PGPKeyList		*kladd = NULL;
	PGPKeyIter		*kiadd = NULL;
	RingSet			*tmpset = NULL;
	PGPKey			*key;
	RingSet			*srcset;
	PGPError		error = PGPERR_OK;

	kladd = pgpOrderKeySet (keysToAdd, kPGPAnyOrdering);
	if (!kladd) {
		error = PGPERR_NOMEM;
		goto err;
	}
	kiadd = pgpNewKeyIter (kladd);
	if (!kiadd) {
		error = PGPERR_NOMEM;
		goto err;
	}

	while ((key = pgpKeyIterNext (kiadd)) != 0) {
		srcset = pgpKeyDBRingSet (key->keyDB);
		if (!srcset) {
			error = PGPERR_NOMEM;
			goto err;
		}
		error = pgpCopyKey (srcset, key->key, &tmpset);
		if (error)
			goto err;
		error = pgpAddObjects (set->keyDB, tmpset);
		if (error)
			goto err;
		ringSetDestroy (tmpset);
		tmpset = NULL;
	}

err:
	if (tmpset)
		ringSetDestroy (tmpset);
	if (kiadd)
		pgpFreeKeyIter (kiadd);
	if (kladd)
		pgpFreeKeyList (kladd);
	return error;
}

/* Remove all objects in the second set from the first */
PGPError
pgpRemoveKeys (PGPKeySet *set, PGPKeySet *keysToRemove)
{
	PGPKeyList		*klrem = NULL;
	PGPKeyIter		*kirem = NULL;
	PGPKey			*key = NULL;
	RingObject		*keyobj = NULL;
	PGPError		error = PGPERR_OK;

	klrem = pgpOrderKeySet (keysToRemove, kPGPAnyOrdering);
	if (!klrem) {
		error = PGPERR_NOMEM;
		goto err;
	}
	kirem = pgpNewKeyIter (klrem);
	if (!kirem) {
		error = PGPERR_NOMEM;
		goto err;
	}
	while ((key = pgpKeyIterNext (kirem)) != 0) {
		keyobj = key->key;
		error = pgpRemoveObject (set->keyDB, keyobj);
		if (error)
			goto err;
	}

err:
	if (kirem)
		pgpFreeKeyIter (kirem);
	if (klrem)
		pgpFreeKeyList (klrem);
	return error;
}


void
pgpFreeKeySet(PGPKeySet *keys)
{
	pgpa (pgpaPGPKeySetValid(keys));

	keys->refCount--;
	if (keys->refCount <= 0)
	{
		(*keys->destroy)(keys);

		if (keys->prevSetInDB)
			keys->prevSetInDB->nextSetInDB = keys->nextSetInDB;
		else
			keys->keyDB->firstSetInDB = keys->nextSetInDB;
		if (keys->nextSetInDB)
			keys->nextSetInDB->prevSetInDB = keys->prevSetInDB;

		pgpAssert(keys->firstListInSet == NULL);

		pgpFreeKeyDB (keys->keyDB);
		pgpFree (keys);
	}
}

Boolean
pgpKeySetIsMutable(PGPKeySet *keys)
{
	pgpa(pgpaPGPKeySetValid(keys));

	return pgpKeyDBIsMutable(keys->keyDB);
}

Boolean
pgpKeySetIsDirty(PGPKeySet *keys)
{
	pgpa(pgpaPGPKeySetValid(keys));

	return pgpKeyDBIsDirty(keys->keyDB);
}

/* Defines when a key should be expanded or collapsed. If set to 1,
	keys are expanded by pgpBuildKeyPool. If set to 2, they are expanded
	when referenced by an iterator, or when the key refCount is explicitly
	incremented by the app. */
#define PGP_EXPANDKEY 1

PGPError
pgpIncKeyRefCount(PGPKey *key)
{

	pgpa(pgpaAddrValid(key, PGPKey));

	key->refCount++;
	if (key->refCount == PGP_EXPANDKEY)
		return pgpExpandKey (key);
	return PGPERR_OK;
}

PGPError
pgpFreeKey(PGPKey *key)
{
	PGPError	err = PGPERR_OK;

	pgpa(pgpaPGPKeyValid(key));

	if (key->refCount == PGP_EXPANDKEY)
		err = pgpCollapseKey (key);
	key->refCount--;
	if (key->refCount <= 0)
		deallocKey(key->keyDB, key);
	return err;
}

long
pgpCountKeys(PGPKeySet *keys)
{
	PGPKey *		key;
	long			count = 0;

	pgpa(pgpaPGPKeySetValid(keys));

	for (key = keys->keyDB->firstKeyInDB; key; key = key->nextKeyInDB)
	{
		pgpa(pgpaPGPKeyValid(key));
		if (pgpKeySetMember(keys, key))
			count++;
	}

	return count;
}

PGPKeyList *
pgpOrderKeySet(PGPKeySet *keys, PGPKeyOrdering order)
{
	PGPKeyList *	list;
	PGPKey *		key;
	long			i, count;

	pgpa(pgpaPGPKeySetValid(keys));

/*	list = pgpNew(PGPKeyList); */
	list = (PGPKeyList *)pgpAlloc(sizeof(PGPKeyList));
	if (list == NULL)
		return NULL;

	list->keyCount = count = pgpCountKeys(keys);
	list->keys = pgpAlloc(count * sizeof(PGPKey *));
	if (list->keys == NULL)
	{
		pgpFree(list);
		return NULL;
	}
	
	list->refCount = 1;
	list->keySet = keys;
	list->order = order;
	list->prevListInSet = NULL;
	list->nextListInSet = keys->firstListInSet;
	keys->firstListInSet = list;
	list->firstIterInList = NULL;

	pgpIncKeySetRefCount(keys);

	i = 0;
	for (key = keys->keyDB->firstKeyInDB; key; key = key->nextKeyInDB)
	{
		pgpa(pgpaPGPKeyValid(key));
		if (pgpKeySetMember(keys, key))
		{
			pgpAssert(i < count);
			list->keys[i++] = key;
		}
	}
	pgpAssert(i == count);

	sortKeyList(list);

	return list;
}

void
pgpIncKeyListRefCount(PGPKeyList *list)
{
	pgpa(pgpaPGPKeyListValid(list));

	list->refCount++;
}

void
pgpFreeKeyList(PGPKeyList *list)
{
	pgpa(pgpaPGPKeyListValid(list));

	list->refCount--;
	if (list->refCount <= 0)
	{
		if (list->prevListInSet)
			list->prevListInSet->nextListInSet = list->nextListInSet;
		else
			list->keySet->firstListInSet = list->nextListInSet;
		if (list->nextListInSet)
			list->nextListInSet->prevListInSet = list->prevListInSet;

		pgpAssert(list->firstIterInList == NULL);

		pgpFree(list->keys);
		pgpFreeKeySet(list->keySet);
		pgpFree(list);
	}
}

PGPKey *
pgpGetKeyByKeyID(PGPKeySet *keys, byte *keyID, size_t keyIDLength)
{
	PGPKeyDB *	db;
	long		lo;
	long		hi;
	long		i;
	PGPKey **	 keyArray;
	size_t		len;
	uchar	 	keyIDA[8];
	uchar	 	keyIDB[8];
	int			comparison;

	pgpa((
		pgpaPGPKeySetValid(keys),
		pgpaAddrValid(keyID, byte),
		pgpaAssert(keyIDLength == 8)));
	(void)keyIDLength;		/* Avoid warning */

	db = keys->keyDB;

	if (db->keysByKeyID == NULL)
	{
		PGPKeySet *		rootSet;

		if ((rootSet = pgpKeyDBRootSet(db)) != NULL)
		{
			db->keysByKeyID = pgpOrderKeySet(rootSet, kPGPKeyIDOrdering);

			/* rootSet will stick around until the keylist is freed */
			pgpFreeKeySet(rootSet);

				/*
			* Undo the additional refCount created by the existence of
			* rootSet. Otherwise the keyDB will never be freed because
			* of the cycle in the reference graph. When the keyDB is
			* actually freed, if keysByKeyID exists, refCount will be
			* incremented again before freeing keysByKeyID.
				*/
			if (db->keysByKeyID != NULL)
				db->refCount--;
		}
		if (db->keysByKeyID == NULL)
			return NULL;
	}

	pgpa((
		pgpaPGPKeyListValid(db->keysByKeyID),
		pgpaAssert(db->keysByKeyID->order == kPGPKeyIDOrdering)));

	keyArray = db->keysByKeyID->keys;
	pgpCopyMemory(keyID, keyIDA, 8);

	lo = 0;
	hi = db->keysByKeyID->keyCount;

	while (lo < hi)
	{
		i = (lo + hi) / 2;
		len = sizeof(keyIDB);
		pgpGetKeyString(keyArray[i], kPGPKeyPropKeyId, (char *)keyIDB, &len);
		comparison = compareKeyIDs(keyIDA, keyIDB);
		if (comparison > 0)
			lo = i + 1;
		else if (comparison < 0)
			hi = i;
		else if (pgpKeySetMember(keys, keyArray[i]))
			return keyArray[i];
		else
			break;
	}
	return NULL;
}

#if DEBUG	/* [ */

	Boolean
pgpaInternalPGPKeyDBValid(
	pgpaCallPrefixDef,
	PGPKeyDB const *	keyDB,
	char const *		varName)
{
	pgpaAddrValid(keyDB, PGPKeyDB);
	pgpaFailIf(keyDB->refCount <= 0, (pgpaFmtPrefix, "refCount <= 0"));
	pgpaFmtMsg((pgpaFmtPrefix,
			"pgpaPGPKeyDBValid failed on %s (%p)", varName, keyDB));

	return pgpaFailed;
}

	Boolean
pgpaInternalPGPKeySetValid(
	pgpaCallPrefixDef,
	PGPKeySet const *	 keySet,
	char const *		varName)
{
	pgpaAddrValid(keySet, PGPKeySet);
	pgpaFailIf(keySet->refCount <= 0, (pgpaFmtPrefix, "refCount <= 0"));
	pgpaFmtMsg((pgpaFmtPrefix,
			"pgpaPGPKeySetValid failed on %s (%p)", varName, keySet));

	return pgpaFailed;
}

	Boolean
pgpaInternalPGPKeyListValid(
	pgpaCallPrefixDef,
	PGPKeyList const *	keyList,
	char const *		varName)
{
	pgpaAddrValid(keyList, PGPKeyList);
	pgpaFailIf(keyList->refCount <= 0, (pgpaFmtPrefix, "refCount <= 0"));
	pgpaFmtMsg((pgpaFmtPrefix,
			"pgpaPGPKeyListValid failed on %s (%p)", varName, keyList));

	return pgpaFailed;
}

	Boolean
pgpaInternalPGPKeyIterValid(
	pgpaCallPrefixDef,
	PGPKeyIter const *	keyIter,
	char const *		varName)
{
	pgpaAddrValid(keyIter, PGPKeyIter);
	pgpaFmtMsg((pgpaFmtPrefix,
			"pgpaPGPKeyIterValid failed on %s (%p)", varName, keyIter));

	return pgpaFailed;
}

	Boolean
pgpaInternalPGPKeyValid(
	pgpaCallPrefixDef,
	PGPKey const *		key,
	char const *		varName)
{
	pgpaAddrValid(key, PGPKey);
	pgpaFailIf(key->refCount <= 0, (pgpaFmtPrefix, "refCount <= 0"));
	pgpaFmtMsg((pgpaFmtPrefix,
			"pgpaPGPKeyValid failed on %s (%p)", varName, key));

	return pgpaFailed;
}

	Boolean
pgpaInternalPGPSubKeyValid(
	pgpaCallPrefixDef,
	PGPSubKey const *	 subKey,
	char const *		varName)
{
	pgpaAddrValid(subKey, PGPSubKey);
/*	pgpaFailIf(subKey->refCount <= 0, (pgpaFmtPrefix, "refCount <= 0"));	*/
	pgpaFmtMsg((pgpaFmtPrefix,
			"pgpaPGPSubKeyValid failed on %s (%p)", varName, subKey));

	return pgpaFailed;
}

	Boolean
pgpaInternalPGPUserIDValid(
	pgpaCallPrefixDef,
	PGPUserID const *	 userID,
	char const *		varName)
{
	pgpaAddrValid(userID, PGPUserID);
/*	pgpaFailIf(userID->refCount <= 0, (pgpaFmtPrefix, "refCount <= 0"));	*/
	pgpaFmtMsg((pgpaFmtPrefix,
			"pgpaPGPUserIDValid failed on %s (%p)", varName, userID));

	return pgpaFailed;
}

	Boolean
pgpaInternalPGPCertValid(
	pgpaCallPrefixDef,
	PGPCert const *		cert,
	char const *		varName)
{
	pgpaAddrValid(cert, PGPCert);
/*	pgpaFailIf(cert->refCount <= 0, (pgpaFmtPrefix, "refCount <= 0")); 	*/
	pgpaFmtMsg((pgpaFmtPrefix,
			"pgpaPGPCertValid failed on %s (%p)", varName, cert));

	return pgpaFailed;
}

#endif /* ] DEBUG */

/*
* Local Variables:
* tab-width: 4
* End:
* vi: ts=4 sw=4
* vim: si
*/

⌨️ 快捷键说明

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