📄 pgpkeydb.c
字号:
PGPKeySetRef
PGPPeekKeyDBRootKeySet( PGPKeyDBRef keyDB )
{
if( ! pgpKeyDBIsValid( keyDB ) )
return kInvalidPGPKeySetRef;
pgpEnterZeroFunction();
return pgpKeyDBPeekRootSet( keyDB );
}
PGPError
pgpKeyDBError( PGPKeyDB *kdb )
{
pgpa(pgpaPGPKeyDBValid(kdb));
return kdb->err;
}
void
pgpKeyDBSetError( PGPKeyDB *kdb, PGPError err )
{
pgpa(pgpaPGPKeyDBValid(kdb));
kdb->err = err;
}
PGPError
PGPFlushKeyDB(PGPKeyDBRef keydb)
{
PGPValidateKeyDB( keydb );
pgpEnterPGPErrorFunction();
return pgpKeyDBFlushInternal( keydb );
}
PGPError
PGPCountKeysInKeyDB(
PGPKeyDBRef keydb,
PGPUInt32 * numKeys )
{
PGPKeyDBObj * key;
PGPUInt32 count = 0;
PGPError err = kPGPError_NoErr;
PGPValidatePtr( numKeys );
*numKeys = 0;
PGPValidateKeyDB( keydb );
pgpEnterPGPErrorFunction();
for (key = keydb->firstKeyInDB; key; key = key->next)
{
if( pgpKeyDBObjIsReal(key) )
count++;
}
*numKeys = count;
return( err );
}
static PGPError
sMatchingKeyDB (PGPContextRef context,
PFLFileSpecRef pubFileRef, PFLFileSpecRef privFileRef,
PGPKeyDBRef *keydb )
{
PGPKeyDBRef kdb;
PGPBoolean match = FALSE;
*keydb = NULL;
for( kdb=pgpContextGetFirstKeyDB(context); IsntNull(kdb); kdb=kdb->next )
{
if( pgpFrontEndKeyDB( kdb ) )
continue;
if( IsNull( kdb->privFileRef ) && IsNull( kdb->pubFileRef ) )
continue;
if( IsNull(kdb->privFileRef) || IsNull(privFileRef) )
match = (kdb->privFileRef == privFileRef);
else
match = PFLFileSpecsEqual( kdb->privFileRef, privFileRef );
match &= PFLFileSpecsEqual( kdb->pubFileRef, pubFileRef );
if( match )
break;
}
if( match )
{
pgpAssert( IsntNull( kdb ) );
++kdb->refCount;
*keydb = kdb;
}
return kPGPError_NoErr;
}
/**************************** Notifications **************************/
void
pgpSetPendingNotify( PGPKeySetRef changeset, PGPKeyDBObjRef changeobj,
PGPKeySetRef newset, PGPKeyDBObjRef newobj )
{
PGPKeyDB *db = NULL;
PGPContextRef context;
PGPNotification *nt;
PGPConnectRef id = kPGPConnectRef_Null;
if( IsntNull( changeset ) || IsntNull( newset ) )
{
db = PGPPeekKeySetKeyDB( IsntNull(changeset)?changeset:newset );
} else {
pgpAssert( IsntNull(changeobj) || IsntNull(newobj) );
db = PGPPeekKeyDBObjKeyDB( IsntNull(changeobj)?changeobj:newobj );
}
context = PGPPeekKeyDBContext( db );
id = pgpContextGetConnectRef( context );
for( nt = db->notifies; IsntNull( nt ); nt = nt->next )
{
if( pgpConnectRefEqual( nt->id, id ) )
continue;
if( IsntNull( changeset ) )
PGPAddKeys( changeset, nt->changeSet );
if( IsntNull( newset ) )
PGPAddKeys( newset, nt->newSet );
if( IsntNull( changeobj ) )
PGPAddKey( changeobj, nt->changeSet );
if( IsntNull( newobj ) )
PGPAddKey( newobj, nt->newSet );
}
#if PGP_WIN32 || PGP_OSX
/* Add support for other hosts that do notification */
if( IsntNull( db ) )
{
for( nt = db->notifies; IsntNull( nt ); nt = nt->next )
{
if( pgpConnectRefEqual( nt->id, id ) )
continue;
if( ( !pgpKeySetIsEmpty( nt->changeSet ) )
|| !pgpKeySetIsEmpty( nt->newSet ) )
{
pgpNotifyClient( nt->id, kPGPNotification_KeyDBChanged );
}
}
}
#endif
}
PGPError
pgpUpdateKeyDB_internal( PGPKeyDB *db, PGPKeySetRef newSet,
PGPKeySetRef changeSet )
{
PGPNotification *nt;
PGPContextRef context;
PGPConnectRef id;
PGPError err = kPGPError_NoErr;
context = PGPPeekKeyDBContext( db );
id = pgpContextGetConnectRef( context );
for( nt = db->notifies; IsntNull( nt ); nt = nt->next )
{
if( pgpConnectRefEqual( nt->id, id ) )
{
err = PGPAddKeys( nt->newSet, newSet );
if( IsPGPError( err ) )
break;
err = PGPAddKeys( nt->changeSet, changeSet );
if( IsPGPError( err ) )
break;
PGPFreeKeySet( nt->newSet );
PGPFreeKeySet( nt->changeSet );
nt->newSet = nt->changeSet = NULL;
err = PGPNewEmptyKeySet( db, &nt->newSet );
if( IsPGPError( err ) )
break;
err = PGPNewEmptyKeySet( db, &nt->changeSet );
if( IsPGPError( err ) )
break;
break;
}
}
return err;
}
void
pgpSetBackendUpdateNeeded()
{
PGPContextRef ctx;
ctx = NULL;
while( IsntNull( ctx = pgpContextNextContext( ctx ) ) )
{
pgpContextSetUpdateNeeded( ctx, TRUE );
++sBackendUpdatesNeeded;
}
}
void
pgpKeyDBBackendUpdate( )
{
PGPContextRef ctx;
PGPKeyDBRef kdb;
PGPError err;
PGPUInt32 numNewKeys;
PGPUInt32 * newKeyArray;
PGPSize newKeyArraySize;
PGPUInt32 * changelist;
PGPSize changelistsize;
PGPBoolean firstContext = TRUE;
if (!pgpRPCEnabled())
return;
if( sBackendUpdatesNeeded > 0 )
{
ctx = NULL;
while( IsntNull( ctx = pgpContextNextContext( ctx ) ) &&
pgpContextGetUpdateNeeded( ctx ) )
{
#if PGP_WIN32
/*
* Only handle contexts associated with current thread;
* or if there is only one context we assume that the clients
* are managing multiple thread usage of that context properly
* so we will update them too.
*/
if( GetCurrentThreadId() != pgpContextGetThreadID(ctx) &&
! (firstContext && pgpContextNextContext(ctx) == NULL) )
continue;
#endif
/* Dec counter and clear flag before processing; we may reenter */
--sBackendUpdatesNeeded;
pgpContextSetUpdateNeeded( ctx, FALSE );
for( kdb=pgpContextGetFirstKeyDB(ctx); IsntNull(kdb);
kdb=kdb->next )
{
err = pgpUpdateKeyDB_back( ctx, kdb->id, &numNewKeys,
&newKeyArray, &newKeyArraySize,
&changelist, &changelistsize );
if( IsPGPError( err ) )
continue;
err = pgpAddFromKeyArray( kdb, NULL, newKeyArray, numNewKeys,
FALSE );
if( IsntNull( newKeyArray ) )
PGPFreeData( newKeyArray );
err = pgpKeyRefreshFromList( kdb, changelist, changelistsize );
}
firstContext = FALSE;
}
}
}
/* External function to poll for whether keydb has been changed in backend */
/* Intended for use on architectures where callbacks can't be done */
PGPError
PGPKeyDBIsUpdated( PGPKeyDBRef kdb, PGPBoolean *updated )
{
PGPError err;
PGPUInt32 numNewKeys;
PGPUInt32 * newKeyArray;
PGPSize newKeyArraySize;
PGPUInt32 * changelist;
PGPSize changelistsize;
PGPContextRef context;
PGPValidatePtr( updated );
*updated = FALSE;
PGPValidateKeyDB( kdb );
pgpEnterPGPErrorFunction();
context = kdb->context;
err = pgpUpdateKeyDB_back( context, kdb->id, &numNewKeys,
&newKeyArray, &newKeyArraySize,
&changelist, &changelistsize );
if( IsPGPError( err ) )
return err;
/* Return with updated as false if nothing to do */
if( newKeyArraySize == 0 && changelistsize == 0 )
{
if( IsntNull( newKeyArray ) )
PGPFreeData( newKeyArray );
if( IsntNull( changelist ) )
PGPFreeData( changelist );
return kPGPError_NoErr;
}
err = pgpAddFromKeyArray( kdb, NULL, newKeyArray, numNewKeys,
FALSE );
if( IsntNull( newKeyArray ) )
PGPFreeData( newKeyArray );
err = pgpKeyRefreshFromList( kdb, changelist, changelistsize );
if( IsntPGPError( err ) )
*updated = TRUE;
return err;
}
static void
sAddNotification( PGPKeyDB *db )
{
PGPContextRef context;
PGPConnectRef id;
PGPConnectRef nullId = kPGPConnectRef_Null;
PGPNotification *nt;
context = PGPPeekKeyDBContext( db );
id = pgpContextGetConnectRef( context );
if( !pgpConnectRefEqual( id, nullId ) )
{
nt = (PGPNotification *) pgpContextMemAlloc( context, sizeof(*nt), 0 );
PGPNewEmptyKeySet( db, &nt->newSet );
PGPNewEmptyKeySet( db, &nt->changeSet );
nt->id = id;
nt->next = db->notifies;
db->notifies = nt;
}
}
static void
sRemoveNotification( PGPKeyDB *db )
{
PGPContextRef context;
PGPConnectRef id;
PGPConnectRef nullId = kPGPConnectRef_Null;
PGPNotification *nt, *ntprev;
context = PGPPeekKeyDBContext( db );
id = pgpContextGetConnectRef( context );
if( pgpConnectRefEqual( id, nullId ) )
return;
ntprev = NULL;
for( nt=db->notifies; IsntNull( nt ); ntprev = nt, nt = nt->next )
{
if( pgpConnectRefEqual( nt->id, id ) )
{
if( ntprev == NULL )
{
db->notifies = nt->next;
} else {
ntprev->next = nt->next;
}
PGPFreeKeySet( nt->newSet );
PGPFreeKeySet( nt->changeSet );
PGPFreeData( nt );
return;
}
}
pgpAssert( 0 );
}
/**************************** Constructors **************************/
PGPKeyDBRef
pgpCreateKeyDBFromKeyRings (PGPContextRef context,
PFLFileSpecRef pubFileRef, PFLFileSpecRef privFileRef,
PGPFlags openFlags, PGPError *error)
{
PGPKeyDBRef kdb;
*error = kPGPError_NoErr;
/* See if we have a matching keydb already */
*error = sMatchingKeyDB( context, pubFileRef, privFileRef, &kdb );
if( IsPGPError( *error ) )
return NULL;
if( IsntNull( kdb ) )
{
sAddNotification( kdb );
if( openFlags & kPGPOpenKeyDBFileOptions_Mutable )
kdb->bmutable = TRUE;
return kdb;
}
kdb = (PGPKeyDB *)pgpContextMemAlloc( context, sizeof(PGPKeyDB),
kPGPMemoryMgrFlags_Clear);
if (kdb == NULL)
{
*error = kPGPError_OutOfMemory;
return NULL;
}
pgpKeyDBInit( context, kdb );
if( IsPGPError( *error = PFLCopyFileSpec(pubFileRef, &kdb->pubFileRef) ) )
{
pgpKeyDBDestroyInternal( kdb );
return NULL;
}
if( IsntNull( privFileRef ) &&
IsPGPError( *error = PFLCopyFileSpec(privFileRef, &kdb->privFileRef )))
{
pgpKeyDBDestroyInternal( kdb );
return NULL;
}
kdb->openFlags = openFlags;
*error = sOpenKeyRings ( kdb );
if (*error)
{
pgpKeyDBDestroyInternal( kdb );
return NULL;
}
return kdb;
}
PGPKeyDBRef
pgpCreateKeyDBFromMemory (PGPContextRef context,
const void *buf, PGPSize buflen, PGPError *error)
{
PGPKeyDBRef kdb;
*error = kPGPError_NoErr;
kdb = (PGPKeyDB *)pgpContextMemAlloc( context, sizeof(PGPKeyDB),
kPGPMemoryMgrFlags_Clear);
if (kdb == NULL)
{
*error = kPGPError_OutOfMemory;
return NULL;
}
pgpKeyDBInit( context, kdb );
/* Memfile keydb's are immutable */
kdb->bmutable = FALSE;
kdb->pubFile = pgpFileMemOpen ( context, buf, buflen );
if (!kdb->pubFile)
{
pgpKeyDBDestroyInternal( kdb );
*error = kPGPError_OutOfMemory;
return NULL;
}
*error = pgpReadKeyFile( kdb, kdb->pubFile, FALSE );
if (*error)
{
pgpKeyDBDestroyInternal( kdb );
return NULL;
}
return kdb;
}
/* Create a new, empty keydb, of the memory type */
PGPError
pgpNewKeyDB_internal( PGPContextRef context, PGPKeyDBRef *keydb )
{
PGPKeyDBRef kdb;
*keydb = NULL;
kdb = (PGPKeyDB *)pgpContextMemAlloc( context, sizeof(PGPKeyDB),
kPGPMemoryMgrFlags_Clear);
if (kdb == NULL)
return kPGPError_OutOfMemory;
pgpKeyDBInit( context, kdb );
/* Memfile keydb's are immutable */
kdb->bmutable = FALSE;
*keydb = kdb;
return kPGPError_NoErr;
}
/* Create a new, empty keydb, of the memory type */
PGPError
PGPNewKeyDB( PGPContextRef context, PGPKeyDBRef *keydb )
{
PGPUInt32 kdbid;
PGPError err;
PGPValidatePtr( keydb );
*keydb = NULL;
PGPValidateContext( context );
pgpEnterPGPErrorFunction();
/* In production mode, if no server, don't use double data structs */
#if !PGP_FORCEBACKEND
if( !pgpRPCEnabled() )
{
return pgpNewKeyDB_internal( context, keydb );
}
#endif
err = pgpNewKeyDB_back( context, &kdbid );
if( IsPGPError( err ) )
return err;
return pgpNewFrontEndKeyDB( context, kdbid, NULL, 0, keydb );
}
/* Create a new keydb for the front end, from the given key array */
PGPError
pgpNewFrontEndKeyDB( PGPContextRef context, PGPUInt32 kdbid,
PGPUInt32 *keyArray, PGPUInt32 keyCount, PGPKeyDBRef *keydb )
{
PGPKeyDB *kdb;
PGPError err = kPGPError_NoErr;
PGPValidatePtr( keydb );
*keydb = NULL;
PGPValidateContext( context );
kdb = (PGPKeyDB *)pgpContextMemAlloc( context, sizeof(PGPKeyDB),
kPGPMemoryMgrFlags_Clear);
if (kdb == NULL)
return kPGPError_OutOfMemory;
pgpKeyDBInit( context, kdb );
kdb->id = kdbid;
err = pgpAddFromKeyArray( kdb, NULL, keyArray, keyCount, TRUE );
if( IsPGPError( err ) )
pgpKeyDBDestroyInternal( kdb );
else
*keydb = kdb;
return err;
}
/*
* Local Variables:
* tab-width: 4
* End:
* vi: ts=4 sw=4
* vim: si
*/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -