📄 pgptrustprop.c
字号:
newseg = pathAlloc(db);
if( IsNull(newseg) ) {
/* Out of memory */
return NULL;
}
newseg->dest = userid->up;
newseg->src = sigkey;
newseg->next = NULL;
newseg->confidence = 1.0;
newpredt = pathAddSeg (predt, newseg);
ppath = sFindPathsUserID (paireduserid, ppath, predh, newpredt,
depth, maxdepth, timenow, db, altdb, userid->down);
pathFree (newseg, db);
*predt = NULL;
if( IsNull(ppath) ) {
/* Out of memory */
return NULL;
}
}
}
}
return ppath;
}
/*
* Find all the paths from the starting key back to an axiomatically
* trusted key.
*
* Returns tail pointer for updated PathList
*
* start starting key object for search backwards through web of trust
* ppath tail pointer of PathList to add our new paths to
* predh pointer to the (head of the) Path we will add to
* predt tail pointer to the Path we will add to
* depth length of path, counting segment added in sFindPathsUserID
* maxdepth maximum length of paths we allow
* timenow current timestamp
* db PGPKeyDB to use for memory allocations
*
*/
static PathList **
sFindPathsKey (PGPKeyDBObj *start, PathList **ppath,
Path **predh, Path **predt, unsigned depth,
unsigned maxdepth, PGPUInt32 timenow, PGPKeyDB *db, PGPKeyDB *altdb)
{
PGPKeyDBObj *userid;
PGPBoolean firstuserid;
PGPKeyInfo * kinfo;
PGPUserIDInfo * uinfo;
/* It's a key but not axiomatic */
pgpAssert (OBJISKEY(start));
kinfo = pgpKeyToKeyInfo( start );
pgpAssert (!(kinfo->trust & PGP_KEYTRUSTF_BUCKSTOP));
SETLOOKINGAT(kinfo);
firstuserid = TRUE;
for (userid = start->down; IsntNull(userid); userid = userid->next) {
if( !pgpKeyDBObjIsReal( userid ) )
continue;
if( !OBJISUSERID(userid) )
continue;
uinfo = pgpUserIDToUserIDInfo( userid );
if( (uinfo->confidence != 0 &&
uinfo->confidence != PGP_NEWTRUST_UNDEFINED) ||
(kinfo->signedTrust != 0 && firstuserid) ) {
ppath = sFindPathsUserID (userid, ppath, predh, predt,
depth, maxdepth, timenow, db, altdb, NULL);
if( IsNull(ppath) ) /* out of memory */
break;
}
firstuserid = FALSE;
}
CLEARLOOKINGAT(kinfo);
return ppath;
}
/*
* Find all paths backwards from the specified target userid to some key
* which is axiomatically trusted.
*
* Returns tail pointer for new PathList
*
* userid starting userid object for search backwards through web of trust
* ppath address of PathList pointer we set to point to head of PathList
* maxdepth maximum length of paths we allow
* timenow current timestamp
* db PGPKeyDB to use for memory allocations
*
*/
static PathList **
sFindPathsBack (PGPKeyDBObj *userid, PathList **ppath, unsigned maxdepth,
PGPUInt32 const timenow, PGPKeyDB *db, PGPKeyDB *altdb)
{
Path *phead = NULL,
**ptail = &phead;
pgpAssert (OBJISUSERID(userid));
/* Don't SETLOOKINGAT here; must allow use of endpoint key as signer */
ppath = sFindPathsUserID (userid, ppath, &phead, ptail, 1, maxdepth,
timenow, db, altdb, NULL);
return ppath;
}
/*
* Test whether the given key has at least one userid with defined
* confidence, or is confident by being signed by meta introducers, or
* is confident by being axiomatic.
*/
static PGPBoolean
sKeyHasConfidence (PGPKeyDBObj *key)
{
PGPKeyDBObj *uid;
PGPKeyInfo * kinfo;
PGPUserIDInfo * uinfo;
pgpAssert (OBJISKEY(key));
if( pgpKeyAxiomatic (key) )
return TRUE;
kinfo = pgpKeyToKeyInfo( key );
if( kinfo->signedTrust != 0 )
return TRUE;
/* True if any userids have defined confidence */
for (uid = key->down; IsntNull(uid); uid = uid->next) {
if( !pgpKeyDBObjIsReal( uid ) )
continue;
if( !OBJISUSERID(uid) )
continue;
uinfo = pgpUserIDToUserIDInfo( uid );
if( uinfo->confidence != PGP_NEWTRUST_UNDEFINED &&
uinfo->confidence != 0 )
return TRUE;
}
return FALSE;
}
#if 0
/*
* Test whether the given userid has defined confidence, or is confident
* because the parent key is axiomatic or signed by meta introducers.
*/
static PGPBoolean
sUserIDHasConfidence (PGPKeyDBObj *userid)
{
PGPKeyDBObj *key;
PGPKeyInfo * kinfo;
PGPUserIDInfo * uinfo;
pgpAssert (OBJISUSERID(userid));
key = userid->up;
pgpAssert (OBJISKEY(key));
if( pgpKeyAxiomatic (key) )
return TRUE;
kinfo = pgpKeyToKeyInfo( key );
if( kinfo->signedTrust != 0 )
return TRUE;
uinfo = pgpUserIDToUserIDInfo( userid );
if( uinfo->confidence != PGP_NEWTRUST_UNDEFINED &&
uinfo->confidence != 0 )
return TRUE;
return FALSE;
}
#endif
/******************** Trust Model 2 Helpers *************************/
PGPUInt16
pgpKeyCalcTrust(PGPKeyDBObj *key)
{
PGPUInt16 trust;
double confidence;
pgpAssert(OBJISKEY(key));
confidence = pathKeyConfidence (key);
if( confidence >= 1. )
trust = PGP_TRUST_INFINITE;
else
trust = pgpDoubleToTrust (1. / (1.-confidence));
return trust;
}
/* Meta-Introducer and trust signature support */
/*
* Given a signature of level >= 1, a current trust level, and an allowed
* further recursion depth, calculate the signedTrust levels for the key,
* and propagate further if level > 1. depthLimit tells how many levels
* max we can propagate, counting this as one. That is used to enforce
* both a maximum limit on how deep this process goes, and for each
* MI/MMI etc. to limit how far forward trust goes depending on the
* amount of "meta", that is, the level.
*
* A level of 0 means an ordinary signature; those aren't considered here.
* A level of 1 means a trust signature, typically issued by a meta-
* introducer, but also possibly by an axiomatic key. Those are applied
* here to form the signedTrust level on the key. A simple maximum is
* used to deal with multiple signed trusts on the key (e. if both a
* MI and the user specified trust on the key).
* A level of 2 means a meta introducer. Any trust signatures by him
* get propagated via one level of recursion.
* Higher levels allow more levels of recursion.
*
* We apply several simplifications which future versions may enhance.
* We only allow 2nd-level (meta and above) propagation if fully
* trusted. That is, meta introducers, and the user himself, can specify
* partial trust levels. But the MI, or an MMI, etc., must be given
* full trust. In this trust model we can't easily handle gracefully
* degrading trust.
*/
static void
mntApplyTrustSig (PGPKeyDBObj const *sig, PGPByte trustValue,
PGPUInt32 depthLimit, int thresh, PGPUInt32 timenow)
{
PGPKeyDBObj *key;
PGPKeyInfo * kinfo;
PGPSigInfo * sinfo;
PGPByte trustVal;
pgpAssert( OBJISSIG( sig ) );
sinfo = pgpSigToSigInfo( sig );
/* First calculate signed trust on this key. */
/* Don't count nonexportable sigs by others */
if( mntForeignSignature(sig) )
return;
/* For now support only full trust on meta introducer signatures */
if( trustValue < thresh && sinfo->trustLevel >= 2 )
return;
/*
* See if trust signature is ruled out by regexp.
* (Note that this looks not at the sig's regexp, but at any on the
* signing key. E. a meta introducer may include a regexp on a sig
* it issues.)
*/
if( !mntSigOKWithRegexp( sig ) )
return;
/* Find signed key */
key = sig->up;
while (!OBJISTOPKEY(key))
key = key->up;
kinfo = pgpKeyToKeyInfo( key );
/*
* For now only use the maximum value of signed trusts, don't try
* to accumulate them. Thorny problems!
*/
trustVal = sinfo->trustValue;
/*
* Mark trust value. If ours is used, copy any regexp associated with
* the signature.
* Have some heuristics to compare regexp and non-regexp sigs.
*/
if( SIGUSESREGEXP( sinfo ) ) {
if( kinfo->signedTrust > 0 && IsNull(kinfo->regexp) ) {
/* Key already has some non-regexp trust, so leave it */
} else if( trustVal > kinfo->signedTrust ) {
/* Key had no trust or regexp trust, and we are stronger */
void *rexp = pgpSigRegexp( sig );
/* Abort this chain if some problem parsing regexp */
if( IsNull(rexp) )
return;
kinfo->signedTrust = trustVal;
kinfo->regexp = rexp;
}
} else {
if( IsntNull(kinfo->regexp) || trustVal > kinfo->signedTrust ) {
/*
* Key had regexp trust, but we don't; or key had no regexp trust,
* but we are stronger.
*/
kinfo->regexp = NULL;
kinfo->signedTrust = trustVal;
}
}
/*
* Then, if level > 1 and we have not reached depthLimit,
* propagate forwards
*/
if( sinfo->trustLevel > 1 && depthLimit > 1 ) {
PGPKeyDBObj const *keysig = kinfo->sigsby;
while( IsntNull(keysig) ) {
PGPKeyDBObj *newestsig;
PGPSigInfo *newestsinfo;
pgpAssert( OBJISSIG( keysig ) );
newestsig = mntNewestSiblingSig(&keysig);
if( !mntSigIsValid( newestsig, timenow ) )
continue;
newestsinfo = pgpSigToSigInfo( newestsig );
/* Skip if not a trust sig */
if( newestsinfo->trustLevel < 1 )
continue;
/* Skip if not a valid key sig */
if( !mntSigIsValidTimeKeySig (newestsig, timenow) )
continue;
/*
* Here we have a good trust or metaintroducer si
* Propagate it forward.
*/
mntApplyTrustSig (newestsig, sinfo->trustValue,
pgpMin(sinfo->trustLevel-1, (PGPByte)depthLimit-1),
thresh, timenow);
}
}
}
/******************** Trust Propagation Main *************************/
/* Do preliminary work for trustprop */
static PGPKeyDBObj const *
sPropagateTrustPass1( PGPKeyDB *db, PGPKeySetRef set, PGPKeyDB *altdb,
PGPUInt32 const timenow, PGPBoolean clearValidity,
PGPBoolean *bChanged, PGPKeySet *changedSet )
{
PGPKeyDBObj const *list;
PGPKeyDBObj *key, *child;
PGPKeyDBObj *sig;
PGPKeyInfo *kinfo;
PGPKeyInfo *kinfo2;
PGPUserIDInfo *uinfo;
PGPSigInfo *sinfo;
PGPSigInfo *sinfo2 = NULL;
unsigned tmptrust;
/*
* Preprocessing: reset all userid trusts to 0, and initialize list
* of trusted keys to the axiomatic ones.
*/
list = NULL;
for (key = db->firstKeyInDB; IsntNull(key); key = key->next) {
if( !pgpKeyDBObjIsReal( key ) )
continue;
if( !pgpKeySetIsMember( key, set ) )
continue;
pgpAssert(OBJISKEY(key));
kinfo = pgpKeyToKeyInfo( key );
kinfo->signedTrust = 0;
CLEARLOOKINGAT(kinfo);
for (child = key->down; IsntNull(child); child = child->next) {
if( !pgpKeyDBObjIsReal( child ) )
continue;
if( !pgpKeySetIsMember( child, set ) )
continue;
if( clearValidity && OBJISUSERID(child) ) {
uinfo = pgpUserIDToUserIDInfo( child );
uinfo->valid = 0;
}
}
/*
* Find each key's revoked status - find
* the most important self-signature.
*/
sig = 0;
for (child = key->down; IsntNull(child); child = child->next) {
if( !pgpKeyDBObjIsReal( child ) )
continue;
if( !pgpKeySetIsMember( child, set ) )
continue;
/*
* Ignore sigs by others, unchecked sigs,
* postdated sigs, and expired sigs.
* @@@ TODO: change the CHECKED and TRIED bits
* For untried revocation sigs, accept them if key's
* trust bits already show it as revoked. PGP 2 does
* not store trust packets on revocation signatures, and so
* neither does this library, to avoid crashing older PGP's
* when they are run on our keyrings.
*/
if( OBJISSIG(child) ) {
sinfo = pgpSigToSigInfo( child );
if( mntSigIsValidTime(timenow, sinfo->tstamp,
sinfo->sigvalidity)) {
/* Any revocation certificate wins, period. */
if( sigRevokesKey(child) ) {
sig = child;
sinfo2 = sinfo;
break;
}
/* Among other checked selfsigs, choose the most recent */
if( sinfo->by == key
&& (sinfo->trust & PGP_SIGTRUSTF_CHECKED) ) {
if( IsNull(sig) || (sinfo2->tstamp < sinfo->tstamp) ) {
sig = child;
sinfo2 = sinfo;
}
}
}
}
}
sinfo = sinfo2;
/* At this point sig holds most recent sig, or first revocation
* sig found, which is directly on the key.
*/
tmptrust = kinfo->trust;
/* Revocation is a function of revocation certificates.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -