📄 pgprngmnt.c
字号:
newseg = pathAlloc(pool);
if (!newseg) {
/* Out of memory */
return NULL;
}
newseg->dest = name->g.up;
newseg->src = sigkey;
newseg->next = NULL;
newseg->confidence = 1.0;
newpredt = pathAddSeg (predt, newseg);
ppath = ringFindPathsName (pairedname, ppath, predh, newpredt,
depth, maxdepth, confset, allset, timenow, pool, name->g.down);
pathFree (newseg, pool);
*predt = NULL;
if (!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 ringFindPathsName
* maxdepth maximum length of paths we allow
* confset ringset for trusted keys
* allset ringset for all keys
* timenow current timestamp
* pool ringpool to use for memory allocations
*
*/
static PathList **
ringFindPathsKey (RingObject *start, PathList **ppath,
Path **predh, Path **predt, unsigned depth,
unsigned maxdepth, RingSet const *confset, RingSet const *allset,
PGPUInt32 timenow, RingPool *pool)
{
RingObject *name;
PGPBoolean firstname;
/* It's a key but not axiomatic */
pgpAssert (OBJISKEY(start));
pgpAssert (!(start->k.trust & PGP_KEYTRUSTF_BUCKSTOP));
SETLOOKINGAT(&start->k);
firstname = TRUE;
for (name = start->g.down; name; name = name->g.next) {
if (!OBJISNAME(name))
continue;
if ((name->n.confidence != 0 &&
name->n.confidence != PGP_NEWTRUST_UNDEFINED) ||
(start->k.signedTrust != 0 && firstname)) {
ppath = ringFindPathsName (name, ppath, predh, predt,
depth, maxdepth, confset, allset, timenow, pool, NULL);
if (!ppath) /* out of memory */
break;
}
firstname = FALSE;
}
CLEARLOOKINGAT(&start->k);
return ppath;
}
/*
* Find all paths backwards from the specified target name to some key
* which is axiomatically trusted.
*
* Returns tail pointer for new PathList
*
* name starting name 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
* confset ringset for trusted keys
* allset ringset for all keys
* timenow current timestamp
* pool ringpool to use for memory allocations
*
*/
static PathList **
ringFindPathsBack (RingObject *name, PathList **ppath, unsigned maxdepth,
RingSet const *confset, RingSet const *allset, PGPUInt32 const timenow,
RingPool *pool)
{
Path *phead = NULL,
**ptail = &phead;
pgpAssert (OBJISNAME(name));
pgpAssert (pgpIsRingSetMember(allset, name));
/* Don't SETLOOKINGAT here; must allow use of endpoint key as signer */
ppath = ringFindPathsName (name, ppath, &phead, ptail, 1, maxdepth,
confset, allset, timenow, pool, NULL);
return ppath;
}
/*
* Create a copy of the given ringSet, but containing only keys which have
* at least one name with defined confidence, or which are confident by
* being signed by meta introducers.
*/
static RingSet *
ringSetConfidentSet (RingSet const *set)
{
RingSet *trustedset;
RingIterator *iter;
trustedset = ringSetCreate (ringSetPool (set));
if (!trustedset)
return 0;
iter = ringIterCreate (set);
if (!iter) {
ringSetDestroy (trustedset);
return 0;
}
ringSetAddSet (trustedset, set);
while (ringIterNextObject (iter, 1)) {
int goodconf = 0; /* True if key has a conf. name */
RingObject *key = ringIterCurrentObject (iter, 1);
while (ringIterNextObject (iter, 2)) {
union RingObject *nameobj;
nameobj = ringIterCurrentObject (iter, 2);
if (!OBJISNAME(nameobj))
continue;
/* Remove names with undefined or zero confidence */
if (key->k.signedTrust != 0) {
/* Need to keep sig-based trusted introducer names */
goodconf = 1;
} else if (ringKeyAxiomatic (set, key)) {
goodconf = 1;
} else if (nameobj->n.confidence == PGP_NEWTRUST_UNDEFINED ||
nameobj->n.confidence == 0) {
ringSetRemObject (trustedset, nameobj);
} else {
goodconf = 1;
}
}
if (!goodconf) {
ringSetRemObject (trustedset, ringIterCurrentObject (iter, 1));
}
}
ringIterDestroy (iter);
ringSetFreeze (trustedset);
return trustedset;
}
#endif /* PGPTRUSTMODEL==2 */
/********************** Trust Model 0 ***************************/
#if PGPTRUSTMODEL==0
/*
* Add "inc" trust to the name signed by the given sig.
* If the trust passes "thresh", mark the name with the level
* and add the key that owns it to the list. Return the expanded list.
*
* TODO: Do something sensible with signatures on keys.
*/
static RingKey const *
mntDoSig(RingSig const *sig, RingKey const *list,
int const inc, int const thresh, PGPUInt32 const timenow, int const level)
{
union RingObject *name, *key;
PGPByte sigtype;
(void)timenow; /* Avoid warning */
pgpAssert(mntSigIsValid(timenow, sig->tstamp, sig->sigvalidity));
name = sig->up;
if (!OBJISNAME(name)) {
/* @@@ do anything with sigs on keys? */
return list;
}
#if 0
/* Ignore self-signature */
key = name->n.up;
pgpAssert(OBJISKEY(key));
if (key == sig->by)
return list;
#endif
sigtype = sig->type & 0xF0;
if (sigtype != PGP_SIGTYPE_KEY_GENERIC)
return list;
#if PRINT_PROGRESS
printf(" Trust %d/%d -> %d/%d on name ",
name->n.trustval, thresh,
name->trustval + inc, thresh);
(void)ringTtyPutString(name->name, name->len, -1u, stdout, '"', '"');
putchar('\n');
#endif
name->n.trustval += inc;
/*
* If we are not yet at the valid level or have already
* marked this name as validated, bail out.
*/
if (name->n.trustval < thresh || NAMELEVEL(&name->n))
return list;
/* Passed threshold - label with certification level. */
NAMESETLEVEL(&name->n, level);
key = name->n.up;
pgpAssert(OBJISKEY(key));
if (key->g.flags & KEYF_TRUSTED || /* Already listed? */
key->k.trust & (PGP_KEYTRUSTF_REVOKED | PGP_KEYTRUSTF_EXPIRED))
return list;
#if PRINT_PROGRESS
ringKeyIDprint(stdout,
" Potential introducer: first userID trust >= 1 on keyID ",
key->keyID);
#endif
key->k.util = (RingKey *)list;
key->g.flags |= KEYF_TRUSTED;
return &key->k;
}
/*
* Look for other keys signed by the grandparent of sig which have the same
* name. Propagate the same trust to those names. (Don't do it if they
* have a sig by the same signing key.) The reasoning is that the same
* person owns both keys, he has the same name, so sigs on the first name
* can be treated as though they are on the other name. This will facilitate
* moving to a new key from an old one.
*
* One issue not dealt with here is that if the grandparent key here is also
* a trusted introducer, trust will move to the destination key in two ways:
* here, by direct "pair propagation" from signatures on that key's names
* which match the names here; and also by normal trust propagation due to
* the signature. This could end up counting some trust twice, although
* in this trust model it doesn't look like it introduces any significant
* weaknesses.
*/
static RingKey const *
mntDoMatchingNames(RingSig const *sig, RingKey const *list,
RingSet const *set, int const inc, int const thresh,
PGPUInt32 const timenow,
int const level)
{
RingObject *name; /* Name which sig is on */
RingObject *key; /* Key which name is on */
RingObject *propsig; /* All sigs by key */
RingObject *propname; /* Name which propsig is on */
RingObject *propkey; /* Key which propname is on */
RingObject *namesig; /* All sigs on propname */
PGPByte sigtype;
PGPByte selfsigfound;
pgpAssert(mntSigIsValid(timenow, sig->tstamp, sig->sigvalidity));
/* Ignore sigs not on names */
name = sig->up;
if (!OBJISNAME(name))
return list;
/* Ignore self signatures, invalid keys, and keys which don't sign */
key = name->n.up;
pgpAssert(OBJISKEY(key));
if (key == sig->by)
return list;
if (key->k.trust & (PGP_KEYTRUSTF_REVOKED | PGP_KEYTRUSTF_EXPIRED))
return list;
/* Ignore funny kinds of sigantures */
sigtype = sig->type & 0xF0;
if (sigtype != PGP_SIGTYPE_KEY_GENERIC)
return list;
/*
* As a short-term security precaution, only propagate for fully valid
* names. The problem is that otherwise, someone could have two keys,
* A and B, which both are marginally valid. If both A and B sign key
* C which has the same name, the marginally valid signatures combine
* to give full validity to C. We have a solution to this but it is
* complex. For now we will only do propagation from names which are
* fully valid, which will mean that only fully valid keys get their
* trust propagated to matching names.
*/
if (!NAMELEVEL(&name->n))
return list;
/* Look for other keys with same name */
for (propsig = key->k.sigsby; propsig;
propsig = (RingObject *)propsig->s.nextby) {
if (!pgpIsRingSetMember(set, propsig))
continue;
propname = propsig->s.up;
/* Ignore sigs not on names */
if (!OBJISNAME(propname))
continue;
propkey = propname->n.up;
/* Ignore nonkeys(?) or self sigs */
if (!OBJISKEY(propkey) || propkey == key)
continue;
/* Make sure signature is valid */
if (!mntSigIsValidKeySig(propsig, set, timenow))
continue;
/* See if names match */
if (ringNamesDiffer (set, name, propname))
continue;
/* Skip if name already has a sig from our signer */
/* Also, this must be the newest sig by us */
/* Also, it must have a self signature */
selfsigfound = 0;
for (namesig=propname->n.down; namesig; namesig=namesig->s.next) {
if (!OBJISSIG(namesig) || !pgpIsRingSetMember(set, namesig))
continue;
if (namesig->s.by == sig->by)
break; /* Break out with nonnull namesig on match */
if (namesig != propsig && namesig->s.by == key
&& namesig->s.tstamp >= propsig->s.tstamp)
break; /* Break outwith nonnull namesig if not newest */
/* Check for valid self signature */
if (namesig->s.by == propkey
&& mntSigIsValidKeySig(namesig, set, timenow)) {
selfsigfound = 1;
}
}
/* If namesig is non-null it had a matching sig, skip this name */
/* Also if there was no self signature */
if (namesig || !selfsigfound)
continue;
/* OK, we have a name suitable for propagating trust to */
list = mntDoSig(&propsig->s, list, inc, thresh, timenow, level);
}
return list;
}
/*
* Add "inc" trust to each name signed by a valid signature on
* the "sigs" list. If the trust passes "thresh", add the resultant
* key to the list. Return the expanded list.
*
* Signatures that are expired or have been superseded are weeded out.
* Note that a postdated signature does not supersede one dated yesterday!
*/
static RingKey const *
mntWalkSigList(RingSig const *sigs, RingKey const *list,
RingSet const *set, int const inc, int const signedinc,
int const thresh, PGPUInt32 const timenow, int const level)
{
RingSig const *cur;
int effectivetrustinc;
while (sigs) {
/* Find the first valid checked signature in the set. */
if (!(sigs->trust & PGP_SIGTRUSTF_CHECKED)
|| (sigs->trust & PGP_SIGTRUSTF_REVOKEDBYCRL)
|| !pgpIsRingSetMember(set, (RingObject *)sigs)
|| !mntSigIsValid(timenow, sigs->tstamp, sigs->sigvalidity)
|| mntForeignSignature(sigs, set))
{
sigs = sigs->nextby;
continue;
}
/* The first candidate signature */
cur = mntNewestValidSiblingSig( &sigs, set, timenow );
/* Don't count signedinc if signature is limited by regexp */
if (signedinc <= 0 || !mntSigOKWithRegexp( set, cur ) )
effectivetrustinc = inc;
else
effectivetrustinc = pgpMax( inc, signedinc );
if( effectivetrustinc <= 0 )
continue;
/* Do the trust computations on the resultant signature. */
list = mntDoSig(cur, list, effectivetrustinc, thresh, timenow, level);
/* Propagate sig info also to linked keys with matching names */
list = mntDoMatchingNames(cur, list, set, effectivetrustinc, thresh,
timenow, level);
}
return list;
}
/*
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -