📄 pgpkeyadd.c
字号:
default:
pgpAssert(0);
case RINGTYPE_KEY:
case RINGTYPE_SUBKEY:
pgpAssert(OBJISKEY(newobj));
okinfo = pgpKeyToKeyInfo( oldobj );
nkinfo = pgpKeyToKeyInfo( newobj );
nkinfo->trust = pgpMax(okinfo->trust, nkinfo->trust);
nkinfo->validityperiod = pgpMax(okinfo->validityperiod,
nkinfo->validityperiod);
/* Copy residence on crypto token */
if( okinfo->flags & KEYF_TOKEN ) {
nkinfo->flags |= KEYF_TOKEN;
nkinfo->tokenNum1 = okinfo->tokenNum1;
}
break;
case RINGTYPE_SIG:
pgpAssert(OBJISSIG(newobj));
osinfo = pgpSigToSigInfo( oldobj );
nsinfo = pgpSigToSigInfo( newobj );
if( (osinfo->trust & PGP_SIGTRUSTF_CHECKED) &&
!(nsinfo->trust & PGP_SIGTRUSTF_CHECKED) )
{
/* Newly trusted signature */
if( SIGISPRIMARYUID (nsinfo) )
{
/* Clear any manual primary uid settings we had */
PGPKeyDBObjRef key = PGPPeekKeyDBObjKey( newobj );
if( pgpSigMaker( newobj ) == key )
pgpKeyClearPrimaryUserIDs( key, (PGPUInt32)-1UL );
}
}
nsinfo->trust = pgpMax(osinfo->trust, nsinfo->trust);
break;
case RINGTYPE_CRL:
pgpAssert(OBJISCRL(newobj));
ocinfo = pgpCRLToCRLInfo( oldobj );
ncinfo = pgpCRLToCRLInfo( newobj );
ncinfo->trust = pgpMax(ocinfo->trust, ncinfo->trust);
break;
case RINGTYPE_UNK:
pgpAssert(pgpObjectType(newobj) == RINGTYPE_UNK);
oninfo = pgpUnkToUnkInfo( oldobj );
nninfo = pgpUnkToUnkInfo( newobj );
nninfo->trust = pgpMax(oninfo->trust, nninfo->trust);
break;
}
}
}
static PGPError
sCleanupThirdPartyRevocations(PGPKeyDBObj *key, PGPBoolean trusted)
{
PGPKeyDBObj *rsig, *nextrsig;
PGPKeyDBObj *ssig;
PGPSigInfo *rsinfo, *ssinfo;
PGPKeyInfo *rskinfo;
PGPBoolean success;
PGPUInt32 i;
PGPUInt32 matches;
PGPByte const *p;
PGPSize len;
(void) trusted;
for( rsig=key->down; IsntNull(rsig); rsig=nextrsig )
{
nextrsig = rsig->next;
if( !OBJISSIG(rsig) )
continue;
rsinfo = pgpSigToSigInfo( rsig );
if( rsinfo->type != PGP_SIGTYPE_KEY_REVOKE )
continue;
if( rsinfo->by == key )
continue;
rskinfo = pgpKeyToKeyInfo( rsinfo->by );
/* Here we have a third party revocation signature */
/* See if there is a self-sig on the key that authorizes it */
success = FALSE;
for( ssig=key->down; IsntNull(ssig); ssig=ssig->next )
{
if( !OBJISSIG(ssig) )
continue;
ssinfo = pgpSigToSigInfo( ssig );
if( ssinfo->type != PGP_SIGTYPE_KEY_PROPERTY )
continue;
if( ssinfo->by != key )
continue;
p = pgpFetchObject( ssig, &len );
if( IsNull(p) )
continue;
i = 0;
do {
PGPBoolean hashed;
p = pgpSigFindSubpacket( p,
SIGSUB_KEY_REVOCATION_KEY, i++, NULL, NULL,
&hashed, NULL, &matches );
if( !p || !hashed )
break;
/*
* data is 1 byte of class, 1 of pkalg, 20 bytes of
* fingerprint. Last 8 of 20 are keyid.
*/
if( pgpMemoryEqual( p+2+20-8, rskinfo->keyID, 8 ) &&
p[1] == rskinfo->pkalg )
{
/* Test to see that the self-sig is valid */
if( !pgpSigTried( ssig ) )
{
/* Validate the self-sig */
PGPKeySetRef kset;
PGPNewOneKeySet( ssig, &kset );
if( IsntNull( kset ) )
{
pgpCheckKeySigs( kset, NULL, FALSE, FALSE, FALSE,
NULL, NULL, NULL );
PGPFreeKeySet( kset );
}
}
/* Only accept if self-sig is valid */
if( pgpSigChecked( ssig ) )
success = TRUE;
/* No point in searching ssig further even if bad */
break; /* out of while( i<matches) loop */
}
} while( i < matches && !success );
if( success )
break;
}
/* Now verify revocation sig if we can */
if( success )
{
/* Look for signing key in any keydb */
PGPKeyDBObjRef signkey = NULL;
PGPContextRef context = PGPPeekKeyDBObjContext( key );
PGPKeyDBRef refdb = pgpContextGetFirstKeyDB(context);
PGPKeyID keyid;
pgpSigID8( rsig, NULL, &keyid );
while( IsntNull( refdb ) && IsNull( signkey ) )
{
pgpGetKeyByKeyID( refdb, &keyid, FALSE, FALSE, &signkey );
if( IsNull(signkey) )
refdb = pgpKeyDBNextKeyDB( refdb );
}
if( IsntNull( signkey ) )
{
/* If found signkey, verify rev signature and remove if bad */
pgpAssert( pgpKeyDBObjIsReal( signkey ) );
if( !pgpSigTried( rsig ) )
{
/* Validate the revocation sig */
PGPKeySetRef kset;
PGPNewOneKeySet( rsig, &kset );
if( IsntNull( kset ) )
{
if( refdb == PGPPeekKeySetKeyDB( kset ) )
refdb = NULL;
pgpCheckKeySigs( kset, refdb, FALSE, FALSE, FALSE,
NULL, NULL, NULL );
PGPFreeKeySet( kset );
}
}
if( pgpSigTried(rsig) && !pgpSigChecked(rsig) )
success = FALSE;
}
}
if( !success )
pgpMarkKeyDBObjectDeleted( rsig );
}
return kPGPError_NoErr;
}
/*
* Called after we have read in a PGP Key and all its children. Check
* it for various conditions.
*/
PGPError
pgpKeyCleanup( PGPKeyDBObj *key, PGPBoolean trusted )
{
return sCleanupThirdPartyRevocations( key, trusted );
}
PGPError
pgpReadKeyFile (PGPKeyDB *kdb, PGPFile *f, PGPBoolean trusted)
{
PGPEnv *pgpEnv;
PGPContextRef context;
PGPKeyDBObj * topobj = NULL;
PGPKeyDBObj * lastobj = NULL;
PGPKeyDBObj * parobj = NULL;
PGPFileOffset pos;
PGPSize len;
PGPUInt32 size;
PGPUInt32 bodylen;
PGPUInt32 maxbuflen = 0;
PGPSize len1;
PGPInt32 pktbyte;
PGPByte * buf = NULL;
PGPError err = kPGPError_NoErr;
context = PGPPeekKeyDBContext( kdb );
pgpEnv = pgpContextGetEnvironment( context );
/* Skip until we get to a key packet */
pos = pgpFileTell( f );
while ((pktbyte = pgpPktByteGet(f, &len, &len1, &pos)) > 0) {
if( PKTBYTE_TYPE(pktbyte) == PKTBYTE_PUBKEY
|| PKTBYTE_TYPE(pktbyte) == PKTBYTE_SECKEY ) {
pgpFileSeek( f, pos, SEEK_SET );
break;
}
pos = pgpFileTell( f );
}
/* If no key packets, return empty-handed */
if( pktbyte < 0 )
goto error;
/* Read each packet, add to kdb, remember where it came from */
pos = pgpFileTell( f );
while ((pktbyte = pgpPktByteGet(f, &len, &len1, &pos)) > 0) {
if( len > PGPOBJ_MAXSIZE )
{
err = pgpFileSeek( f, len, SEEK_CUR );
if( IsPGPError( err ) )
goto error;
continue;
}
bodylen = len;
len += pgpPktHeaderLen( pktbyte, len );
if( len > maxbuflen ) {
void *vbuf = buf;
err = pgpContextMemRealloc( context, &vbuf, len, 0 );
buf = vbuf;
if( IsPGPError( err ) )
{
err = pgpFileSeek( f, len, SEEK_CUR );
if( IsPGPError( err ) )
goto error;
continue;
}
maxbuflen = len;
}
/* Put the pktbyte + length into the beginning of buf */
pgpPktHeaderPut( buf, pktbyte, bodylen );
size = pgpPktBodyRead( buf+len-bodylen, bodylen, len1, f );
if( size != bodylen )
/* Premature EOF, just return with what we have */
break;
size = len;
switch (PKTBYTE_TYPE(pktbyte)) {
case PKTBYTE_PUBKEY:
case PKTBYTE_SECKEY:
/* Do some checks on previously read-in key certificate */
if( IsntNull( topobj ) )
pgpKeyCleanup( topobj, trusted );
topobj = pgpAddObject( buf, len, kdb, NULL, trusted, &err );
lastobj = parobj = topobj;
if( IsPGPError( err ) )
goto error;
break;
case PKTBYTE_PUBSUBKEY:
case PKTBYTE_SECSUBKEY:
case PKTBYTE_ATTRIBUTE:
case PKTBYTE_USERID:
if( IsNull(topobj) || !OBJISTOPKEY(topobj) )
break;
parobj = pgpAddObject( buf, len, kdb, topobj, trusted, &err);
lastobj = parobj;
if( IsPGPError( err ) )
goto error;
break;
case PKTBYTE_SIG:
if( IsNull(parobj) || IsNull(topobj) || !OBJISTOPKEY(topobj) )
break;
lastobj = pgpAddObject(buf, len, kdb, parobj, trusted, &err);
if( IsPGPError( err ) )
goto error;
break;
case PKTBYTE_CRL:
if(IsNull(parobj) || IsNull(topobj) || !OBJISTOPKEY(topobj) )
break;
if( !OBJISKEY( parobj ) )
parobj = topobj;
pgpAssert( OBJISKEY(parobj) );
lastobj = pgpAddObject(buf, len, kdb, parobj, trusted, &err);
if( IsPGPError( err ) )
goto error;
break;
case PKTBYTE_TRUST:
if( IsNull(lastobj) || !trusted )
break;
err = pgpTrustPacket( buf, len, kdb, lastobj, pgpEnv );
if( IsPGPError( err ) )
goto error;
break;
case PKTBYTE_COMMENT:
/* Skip this */
break;
default:
/* Unknown packet type; save it for output */
if( IsNull(parobj) )
break;
lastobj = pgpAddObject(buf, len, kdb, parobj, trusted, &err);
if( IsPGPError( err ) )
goto error;
break;
}
pos = pgpFileTell( f );
}
error:
if( IsntNull( buf ) )
PGPFreeData( buf );
if( IsntNull( topobj ) )
pgpKeyCleanup( topobj, trusted );
return err;
}
/*
* Add objects from back-end supplied key array. If newobjs is false we do
* lookups to merge them with existing keys; if true we know they are all
* new objects and skip the lookup.
*/
static PGPError
sAddFromKeyArray( PGPKeyDB *kdb, PGPKeyDBObj *parent, PGPKeyDBObj *prev,
PGPUInt32 **keyArray, PGPUInt32 keyCount, PGPBoolean newobjs )
{
PGPUInt32 i;
PGPUInt32 id;
PGPUInt32 flags;
PGPUInt32 nchildren;
PGPKeyDBObj * obj;
PGPError err = kPGPError_NoErr;
for( i = 0; i<keyCount; ++i ) {
id = *(*keyArray)++;
flags = *(*keyArray)++;
if( !newobjs &&
IsntPGPError( PGPFindNode( kdb->idToObj, id,
(PGPUserValue *)&obj ) ) )
{
/* Type should be same, except dummy top key may become subkey */
pgpAssert( (flags & 0x3f) == (obj->objflags & 0x3f)
|| ( (flags&0x3f)==kPGPKeyDBObjType_SubKey &&
pgpKeyDBObjIsDummy(obj) ) );
/*
* If prev is valid and we have a parent, make sure our order
* is correct
*/
if( prev != (PGPKeyDBObj *)-1UL && IsntNull( parent ) )
{
if( IsntNull( prev ) )
{
if( prev->next != obj )
{
if( OBJISTOPKEY( obj ) )
pgpUnlinkKey( obj, kdb ); /* dummy to subkey */
else
pgpUnlinkChild( obj, parent );
obj->next = prev->next;
obj->up = parent;
prev->next = obj;
}
} else {
/* Null prev means we should be first child */
if( parent->down != obj )
{
if( OBJISTOPKEY( obj ) )
pgpUnlinkKey( obj, kdb ); /* dummy to subkey */
else
pgpUnlinkChild( obj, parent );
obj->next = parent->down;
obj->up = parent;
parent->down = obj;
}
}
}
obj->objflags &= ~( kPGPKeyDBObjFlags_Deleted |
kPGPKeyDBObjFlags_Dummy |
kPGPKeyDBObjFlags_X509 | 0x3f );
obj->objflags |= flags & ( kPGPKeyDBObjFlags_Deleted |
kPGPKeyDBObjFlags_Dummy |
kPGPKeyDBObjFlags_X509 | 0x3f );
/* Keys may get info field changed, so force update */
if( OBJISKEY(obj) )
pgpKeyDBObjRefresh( obj, FALSE );
} else {
if( flags & kPGPKeyDBObjType_Key ) {
obj = sNewKey( kdb );
if ( obj == NULL )
{
err = kPGPError_OutOfMemory;
goto error;
}
pgpLinkKey( obj, kdb );
} else {
if ( flags & kPGPKeyDBObjType_SubKey )
obj = sNewSubKey( kdb );
else if ( flags & kPGPKeyDBObjType_UserID )
obj = sNewUserID( kdb );
else if ( flags & kPGPKeyDBObjType_Signature )
obj = sNewSig( kdb );
else if ( flags & kPGPKeyDBObjType_CRL )
obj = sNewCRL( kdb );
else
obj = sNewUnknown( kdb );
if ( obj == NULL )
{
err = kPGPError_OutOfMemory;
goto error;
}
pgpLinkChild( obj, parent );
}
obj->idinfo.id = id;
obj->objflags = flags | kPGPKeyDBObjFlags_ID;
PGPAddNode( kdb->idToObj, id, (PGPUserValue)obj );
}
if( !OBJISSIG( obj ) )
{
nchildren = *(*keyArray)++;
err = sAddFromKeyArray( kdb, obj, NULL, keyArray,
nchildren, newobjs );
if( IsPGPError( err ) )
goto error;
}
prev = obj;
}
error:
return err;
}
PGPError
pgpAddFromKeyArray( PGPKeyDB *kdb, PGPKeyDBObj *parent, PGPUInt32 *keyArray,
PGPUInt32 keyCount, PGPBoolean newobjs )
{
PGPError err;
err = sAddFromKeyArray( kdb, parent, (PGPKeyDBObj *)-1UL,
&keyArray, keyCount, newobjs );
if( IsPGPError( err ) )
return err;
pgpKeyDBChanged( kdb, TRUE );
return kPGPError_NoErr;
}
/*
* Given a seckey, a keydb, and some other information, create a new
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -