📄 pgpkeyset.c
字号:
}
(*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 + -