📄 pgpfiledb.c
字号:
rdb->bwriteable = FALSE;
rdb->openFlags &= ~kPGPKeyRingOpenFlags_Mutable;
}
if ( IsntNull( newRingFile ) )
{
if( IsPGPError( ringFileClose( newRingFile ) ) )
pgpDebugMsg( "Failed to close newRingFile" );
}
if ( IsntNull( newPGPFile ) )
pgpFileClose( newPGPFile );
if ( newFileRef != kInvalidPFLFileSpecRef )
PFLFreeFileSpec( newFileRef );
if ( IsntNull( tempPGPFile ) )
pgpFileClose( tempPGPFile );
if ( IsntNull( tempStdFile ) )
PFLFileSpecDelete( tempFileRef );
if ( tempFileRef != kInvalidPFLFileSpecRef )
PFLFreeFileSpec( tempFileRef );
if ( IsntNull( mainFileName ) )
PGPFreeData( mainFileName );
return err;
}
static PGPError
CloseKeyRing( RingDB * rdb )
{
PGPContextRef context;
pgpAssertAddrValid( rdb, RingDB );
context = rdb->context;
if (rdb->frozenSet)
{
ringSetDestroy (rdb->frozenSet);
rdb->frozenSet = 0;
}
rdb->immutableSet = 0;
if (rdb->mutableSet)
ringSetDestroy (rdb->mutableSet);
rdb->mutableSet = 0;
if( IsPGPError( ringFileClose (rdb->ringFile) ) )
pgpDebugMsg( "Failed to close rdb->ringFile" );
rdb->ringFile = 0;
pgpFileClose (rdb->pgpFile);
rdb->pgpFile = 0;
if ( IsntNull( rdb->mainStdFile ) )
pgpStdIOClose( rdb->mainStdFile );
if ( rdb->mainFileRef != kInvalidPFLFileSpecRef )
{
if ( rdb->bwriteable || !PFL_PLATFORM_UNSAFE_DELETE )
PurgeOldBackups( rdb->mainFileRef );
PFLFreeFileSpec( rdb->mainFileRef );
rdb->mainFileRef = kInvalidPFLFileSpecRef;
}
if ( rdb->readFileRef != kInvalidPFLFileSpecRef )
{
if ( rdb->btempfile )
PFLFileSpecDelete( rdb->readFileRef );
PFLFreeFileSpec( rdb->readFileRef );
rdb->readFileRef = kInvalidPFLFileSpecRef;
}
return kPGPError_NoErr;
}
/******************** Virtual Functions ************************/
static PGPBoolean
rdbIsMutable (PGPKeyDBRef kdb) {
RingDB *rdb = (RingDB *)kdb->priv;
return rdb->bwriteable;
}
static PGPBoolean
rdbObjIsMutable (PGPKeyDBRef kdb, RingObject *testObj)
{
RingDB *rdb = (RingDB *)kdb->priv;
return rdb->bwriteable && ringSetIsMember (rdb->mutableSet, testObj);
}
static PGPBoolean
rdbIsDirty (PGPKeyDBRef kdb)
{
RingDB *rdb = (RingDB *)kdb->priv;
return rdb->bdirty;
}
/* Mark as dirty */
static void
rdbDirty (RingDB *rdb)
{
rdb->bdirty = TRUE;
if (rdb->frozenSet) {
ringSetDestroy (rdb->frozenSet);
rdb->frozenSet = 0;
}
}
static const RingSet *
rdbGetRingSet (PGPKeyDBRef kdb)
{
RingDB *rdb = (RingDB *)kdb->priv;
RingSet *rset;
if (!rdb->bwriteable) {
return rdb->immutableSet;
} else if (!(rset = rdb->frozenSet)) {
rset = ringSetCreate (ringSetPool (rdb->mutableSet));
ringSetAddSet (rset, rdb->mutableSet);
ringSetFreeze (rset);
rdb->frozenSet = rset;
}
return rset;
}
static PGPError
rdbAdd (PGPKeyDBRef kdb, RingSet *toAdd)
{
RingDB *rdb = (RingDB *)kdb->priv;
RingIterator *riAdd; /* Iterator over toAdd set */
RingObject *robj; /* Object we are adding */
int level; /* Level of iterator in hierarchy */
int type; /* Type of robj */
int added; /* Number of objects added */
int skipped; /* Number of objects skipped */
PGPBoolean skipparts; /* True if skipping, obj not for us */
if (!rdb->bwriteable)
return kPGPError_ItemIsReadOnly;
riAdd = ringIterCreate (toAdd);
if (!riAdd) {
return ringSetError(toAdd)->error;
}
added = 0;
skipped = 0;
skipparts = FALSE;
while ((level = ringIterNextObjectAnywhere(riAdd)) > 0) {
robj = ringIterCurrentObject (riAdd, level);
type = ringObjectType (robj);
if (type==RINGTYPE_KEY) {
/*
* If key lacks secret object, put it only on the public
* ring, and if key comes only from a source where it is a
* secret key, put it only on the secret ring. This is
* important to prevent propagation of the 2.6.2 "version bug",
* where changing passphrase on a V2 secret key turns it into
* V3. We must not let that get into the public keyring.
*/
if (rdb->bprivate) {
skipparts = !ringKeyIsSec (toAdd, robj);
if (skipparts && !ringKeyIsSubkey (toAdd, robj)) {
/* Don't skip if any subkey has a secret part */
unsigned levelx;
RingObject *robjx;
while ((levelx = ringIterNextObjectAnywhere(riAdd)) > 1) {
robjx = ringIterCurrentObject (riAdd, levelx);
if (ringObjectType(robjx) == RINGTYPE_KEY &&
ringKeyIsSec (toAdd, robjx)) {
skipparts = FALSE;
break;
}
}
ringIterSeekTo (riAdd, robj);
}
} else {
skipparts = ringKeyIsSecOnly (toAdd, robj);
/* Go ahead and add to pubring if key has a signature */
if (skipparts) {
unsigned levelx;
RingObject *robjx;
int typex;
while ((levelx = ringIterNextObjectAnywhere(riAdd)) > 1) {
robjx = ringIterCurrentObject (riAdd, levelx);
typex = ringObjectType (robjx);
if (typex == RINGTYPE_KEY)
break;
if (typex == RINGTYPE_SIG) {
skipparts = FALSE;
break;
}
}
ringIterSeekTo (riAdd, robj);
}
}
}
if (skipparts) {
skipped += 1;
} else if ((type==RINGTYPE_SEC) && !rdb->bprivate) {
/* Secrets only go to private keyrings */
skipped += 1;
} else if ((type==RINGTYPE_SIG) && rdb->bprivate &&
!ringSigIsSelfSig( toAdd, robj )) {
/*
* Signatures only go to public keyrings, normally. The
* exception is your own self-sigs. If you lose the one
* on your subkey, people won't be able to encrypt to you.
* If you lose the one on your username, you'll lose expiration
* or preferred algorithms.
*/
skipped += 1;
} else if ((type==RINGTYPE_CRL) && rdb->bprivate) {
/* CRLs only on public keyring */
skipped += 1;
} else {
ringSetAddObject (rdb->mutableSet, robj);
added += 1;
}
}
ringIterDestroy (riAdd);
rdbDirty (rdb);
return kPGPError_NoErr;
}
static PGPError
rdbRemove (PGPKeyDBRef kdb, RingObject *toRemove)
{
RingDB *rdb = (RingDB *)kdb->priv;
if (!rdb->bwriteable)
return kPGPError_ItemIsReadOnly;
if (ringSetIsMember (rdb->mutableSet, toRemove))
rdbDirty (rdb);
return (PGPError)ringSetRemObject (rdb->mutableSet, toRemove);
}
/*
* Note that unions don't pass this call down, they take care of it
* themselves
*/
static PGPError
rdbChanged (PGPKeyDBRef kdb, RingSet *changedkeys)
{
RingDB *rdb = (RingDB *)kdb->priv;
if (!rdb->bwriteable)
return kPGPError_ItemIsReadOnly;
rdbDirty (rdb);
return pgpReSortKeys (kdb, changedkeys);
}
static PGPError
rdbCommit (PGPKeyDBRef kdb)
{
RingDB *rdb = (RingDB *)kdb->priv;
RingPool *ringpool = ringSetPool (rdb->immutableSet);
PGPError error;
if (!rdb->bwriteable)
return kPGPError_NoErr;
/* Don't check for trust changed if untrusted file */
if (!rdb->bdirty && (!rdb->btrusted ||
(rdb->btrusted && !ringFileIsTrustChanged(rdb->ringFile))))
return kPGPError_NoErr;
/* Must use frozen set for writing */
ringSetFreeze (rdb->mutableSet);
if (rdb->frozenSet) {
ringSetDestroy (rdb->frozenSet);
rdb->frozenSet = 0;
}
error = WriteKeyRing (rdb);
if (error) {
/*
* Sometimes on error we have fixed rdb->mutableSet, but possibly it
* may still be frozen as above. To be safe we will always make a
* copy here so it is writeable in the future.
*/
RingSet *rset = ringSetCreate (ringpool);
pgpAssert (rset);
pgpAssert (rdb->mutableSet);
ringSetAddSet (rset, rdb->mutableSet);
ringSetDestroy (rdb->mutableSet);
rdb->mutableSet = rset;
return error;
}
rdb->immutableSet = ringFileSet (rdb->ringFile);
rdb->mutableSet = ringSetCreate (ringpool);
ringSetAddSet (rdb->mutableSet, rdb->immutableSet);
rdb->bdirty = 0;
return kPGPError_NoErr;
}
static PGPError
rdbRevert (PGPKeyDBRef kdb)
{
RingDB *rdb = (RingDB *)kdb->priv;
if (!rdb->bdirty)
return kPGPError_NoErr;
rdb->bdirty = 0;
if (rdb->mutableSet) {
ringSetDestroy (rdb->mutableSet);
rdb->mutableSet = ringSetCreate (ringSetPool(rdb->immutableSet));
if (!rdb->mutableSet) {
return ringSetError( rdb->immutableSet )->error;
}
ringSetAddSet (rdb->mutableSet, rdb->immutableSet);
}
if (rdb->frozenSet) {
ringSetDestroy (rdb->frozenSet);
rdb->frozenSet = 0;
}
return kPGPError_NoErr;
}
static PGPError
rdbReload (PGPKeyDBRef kdb)
{
RingDB *rdb = (RingDB *)kdb->priv;
PFLFileSpecRef fileRef;
PGPError err = kPGPError_NoErr;
PGPContextRef cdkContext = pgpGetKeyDBContext( kdb );
RingPool *pool = ringSetPool (rdb->immutableSet);
if (rdb->bmembuf)
return kPGPError_NoErr;
if ( IsPGPError(err = PFLCopyFileSpec(rdb->mainFileRef, &fileRef)))
return kPGPError_OutOfMemory;
err = CloseKeyRing (rdb);
if (err) {
PFLFreeFileSpec(fileRef);
return err;
}
err = OpenKeyRing ( cdkContext, fileRef, rdb->openFlags, pool, rdb);
rdb->bdirty = 0;
PFLFreeFileSpec(fileRef);
return err;
}
static void
rdbDestroy (PGPKeyDBRef kdb)
{
RingDB *rdb = (RingDB *)kdb->priv;
PGPContextRef context;
pgpAssertAddrValid( kdb, RingDB );
context = rdb->context;
CloseKeyRing (rdb);
kdb->typeMagic = ~ kdb->typeMagic; /* mark as invalid */
kdb->fixedMagic = ~ kdb->fixedMagic; /* mark as invalid */
pgpContextMemFree( context, rdb);
}
/**************************** Constructor **************************/
PGPKeyDBRef
pgpCreateFileKeyDB (PGPContextRef context, PFLConstFileSpecRef fileRef,
PGPKeyRingOpenFlags openFlags, RingPool *ringpool,
PGPError *error)
{
PGPKeyDBRef kdb;
RingDB *rdb;
*error = kPGPError_NoErr;
kdb = pgpKeyDBCreateInternal (context);
if (!kdb) {
*error = kPGPError_OutOfMemory;
return NULL;
}
rdb = (RingDB *) pgpContextMemAlloc( context,
sizeof (RingDB), kPGPMemoryMgrFlags_Clear);
if (!rdb) {
*error = kPGPError_OutOfMemory;
pgpKeyDBDestroyInternal (kdb);
return NULL;
}
rdb->context = context;
*error = OpenKeyRing ( context, fileRef, openFlags, ringpool, rdb);
if (*error) {
pgpContextMemFree( context, rdb);
pgpKeyDBDestroyInternal (kdb);
return NULL;
}
kdb->priv = rdb;
kdb->typeMagic = PGPKDBFILEMAGIC;
kdb->fixedMagic = kPGPKeyDBMagic;
kdb->isMutable = rdbIsMutable;
kdb->objIsMutable = rdbObjIsMutable;
kdb->isDirty = rdbIsDirty;
kdb->getRingSet = rdbGetRingSet;
kdb->add = rdbAdd;
kdb->remove = rdbRemove;
kdb->changed = rdbChanged;
kdb->commit = rdbCommit;
kdb->revert = rdbRevert;
kdb->reload = rdbReload;
kdb->destroy = rdbDestroy;
pgpKeyDBInitInternal(kdb);
return kdb;
}
/*
* Create a File type KeyDB from a memory buffer. This will be an
* immutable KeyDB since we can't save our changes anywhere.
* We make a copy of the buffer passed in, so caller can free it.
*/
PGPKeyDBRef
pgpCreateMemFileKeyDB (
PGPContextRef context,
PGPByte * buf,
size_t length,
RingPool * ringpool,
PGPError * error)
{
PGPKeyDBRef kdb;
RingDB *rdb;
*error = kPGPError_NoErr;
kdb = pgpKeyDBCreateInternal (context);
if (!kdb) {
*error = kPGPError_OutOfMemory;
return NULL;
}
rdb = (RingDB *) pgpContextMemAlloc( context,
sizeof (RingDB), kPGPMemoryMgrFlags_Clear);
if (!rdb) {
*error = kPGPError_OutOfMemory;
pgpKeyDBDestroyInternal (kdb);
return NULL;
}
rdb->context = context;
/* Memfile keydb's are immutable */
rdb->mutableSet = NULL;
rdb->pgpFile = pgpFileMemOpen ( context, buf, length);
if (!rdb->pgpFile) {
pgpContextMemFree( context, rdb);
pgpKeyDBDestroyInternal (kdb);
*error = kPGPError_OutOfMemory;
return NULL;
}
rdb->ringFile = ringFileOpen (ringpool, rdb->pgpFile, 0, error);
if (!rdb->ringFile) {
pgpFileClose (rdb->pgpFile);
pgpContextMemFree( context, rdb);
pgpKeyDBDestroyInternal (kdb);
*error = ringPoolError(ringpool)->error;
if (!*error)
*error = kPGPError_OutOfMemory;
return NULL;
}
rdb->immutableSet = ringFileSet (rdb->ringFile);
rdb->bmembuf = TRUE;
rdb->mainStdFile = NULL;
rdb->mainFileRef = rdb->readFileRef = NULL;
kdb->priv = rdb;
kdb->typeMagic = PGPKDBFILEMAGIC;
kdb->fixedMagic = kPGPKeyDBMagic;
kdb->isMutable = rdbIsMutable;
kdb->objIsMutable = rdbObjIsMutable;
kdb->isDirty = rdbIsDirty;
kdb->getRingSet = rdbGetRingSet;
kdb->add = rdbAdd;
kdb->remove = rdbRemove;
kdb->changed = rdbChanged;
kdb->commit = rdbCommit;
kdb->revert = rdbRevert;
kdb->reload = rdbReload;
kdb->destroy = rdbDestroy;
pgpKeyDBInitInternal(kdb);
return kdb;
}
/*
* Local Variables:
* tab-width: 4
* End:
* vi: ts=4 sw=4
* vim: si
*/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -