📄 pgptrustprop.c
字号:
uid = uid->next;
}
if( IsntNull( uid ) ) {
udata = pgpFetchObject( uid, &len );
hlen = pgpPktBufferHeaderLen( udata );
strncpy (buserid, (char *) udata+hlen, pgpMin(len-hlen, 255));
buserid[len-hlen] = '\0';
fputs (buserid, f);
} else {
fputs ("<null userid>", f);
}
return 0;
}
static int
pgpDebugPrintKey(FILE *f, PGPKeyDBObj *key)
{
pgpDebugPrintKeyID (f, key);
fprintf (f, "(");
pgpDebugPrintKeyUserID (f, key);
fprintf (f, ")");
return 0;
}
static void
pgpDebugPrintPath(FILE *f, Path *path)
{
fprintf (f, " Path ");
while (path) {
fprintf (f, "from ");
pgpDebugPrintKey (f, path->src);
fprintf (f, " to ");
pgpDebugPrintKey (f, path->dest);
fprintf (f, ", conf: %g\n", path->confidence);
path = path->next;
if( IsntNull(path) )
fprintf (f, " ...segment ");
}
}
static void
pgpDebugPrintPathList(FILE *f, PathList *pl)
{
fprintf (f, "Begin PathList\n");
while (pl) {
fprintf (f, " (conf=%g) ", pl->confidence);
pgpDebugPrintPath (f, pl->path);
pl = pl->next;
}
fprintf (f, "End PathList\n");
}
#endif /* DEBUGPATH */
static double pathConfidence (Path *path);
/* Allocate a Path segment */
static Path *
pathAlloc (PGPKeyDB *db)
{
Path *path = db->paths;
if( IsntNull(path) ) {
db->paths = path->next;
} else {
path = (Path *) memPoolAlloc (&db->pathpool, sizeof(Path),
alignof(Path));
}
return path;
}
/* Free a Path segment */
static void
pathFree (Path *path, PGPKeyDB *db)
{
if( IsNull(path) )
return;
path->next = db->paths;
db->paths = path;
}
/* Free an entire Path */
static void
pathFreeAll (Path *phead, PGPKeyDB *db)
{
Path **ptail;
if( IsNull(phead) )
return;
ptail = &phead->next;
while (*ptail) {
ptail = &(*ptail)->next;
}
*ptail = db->paths;
db->paths = phead;
}
/* Allocate a PathList element */
static PathList *
pathListAlloc (PGPKeyDB *db)
{
PathList *plist = db->pathlists;
if( IsntNull(plist) ) {
db->pathlists = plist->next;
plist->next = NULL;
} else {
plist = (PathList *) memPoolAlloc (&db->pathpool,
sizeof(PathList), alignof(PathList));
}
return plist;
}
#if 0
/* Free a PathList element, also freeing any path it points to */
static void
pathListFree (PathList *plist, PGPKeyDB *db)
{
if( IsntNull(plist->path) )
pathFreeAll (plist->path, db);
plist->path = 0;
plist->confidence = 0.;
plist->next = db->pathlists;
db->pathlists = plist;
}
#endif
/* Free a whole PathList, also freeing the Paths it points to */
static void
pathListFreeAll (PathList *plhead, PGPKeyDB *db)
{
PathList **pltail = &plhead->next;
while (*pltail)
pltail = &(*pltail)->next;
*pltail = db->pathlists;
db->pathlists = plhead;
while (plhead != *pltail) {
pathFreeAll (plhead->path, db);
plhead->path = 0;
plhead->confidence = 0.;
plhead = plhead->next;
}
}
/* Add a Path segment to a Path
*
* Returns updated Path tail pointer
*
* tail tail pointer for Path to be added to
* seg pointer to Path segment to add
*
*/
static Path **
pathAddSeg (Path **tail, Path *seg)
{
seg->next = *tail;
*tail = seg;
return &seg->next;
}
/*
* Make a copy of a Path, leaving the original untouched.
*
* Returns pointer to new cloned path
*
* p1 pointer to the path to be cloned
* db KeyDB used for allocations of new path segments
*
*/
static Path *
pathClone (Path *p1, PGPKeyDB *db)
{
Path *phead = NULL,
**ptail = &phead;
while (p1) {
*ptail = pathAlloc(db);
if( IsNull(*ptail) )
return NULL;
**ptail = *p1;
p1 = p1->next;
ptail = &(*ptail)->next;
}
return phead;
}
/* Add a copy of a Path to the PathList
*
* Returns tail pointer of updated PathList
*
* tail tail pointer of PathList to be added to
* path pointer to Path to add to the PathList
* db PGPKeyDB to use for memory allocations
*
*/
static PathList **
pathListAddPathClone (PathList **tail, Path *path, PGPKeyDB *db)
{
PathList *pl;
pl = pathListAlloc(db);
if( IsNull(pl) )
return NULL;
if( IsntNull(path) )
{
pl->path = pathClone (path, db);
pl->confidence = pathConfidence (path);
} else {
pl->path = NULL;
pl->confidence = 1.0;
}
pl->next = *tail;
*tail = pl;
return &pl->next;
}
/* Calculate the confidence associated with a path. */
static double
pathConfidence (Path *path)
{
double conf = 1.0;
while (path) {
conf *= path->confidence;
path = path->next;
}
return conf;
}
/*
* Prune the PathList to keep only the highest-confidence pathmax Paths.
* Return the new PathList, free the no longer used Paths.
*
* Returns new PathList with no more than pathmax paths
*
* plist PathList to be pruned
* pathmax maximum number of paths to allow
* db PGPKeyDB to use for memory allocations
*
*/
static PathList *
pathListPrune (PathList *plist, unsigned pathmax, PGPKeyDB *db)
{
PathList *iplist; /* Copy of plist */
PathList **pl1, /* Iterator over plist */
**maxpl1; /* Max confidence pl1 pointer */
PathList *nplist, /* New pathlist head */
**nptail; /* New pathlist tail */
unsigned npaths, /* Number of paths in plist initially */
newnpaths; /* Number of paths in final nplist */
double maxconf; /* Best confidence value so far */
/* Calculate confidence value for each path */
iplist = plist;
npaths = 0;
while (plist) {
npaths += 1;
pgpAssert( plist->confidence == pathConfidence (plist->path) );
plist = plist->next;
}
plist = iplist;
/* Initialize the new path list */
nplist = plist;
if( npaths > pathmax ) {
nplist = NULL;
nptail = &nplist;
newnpaths = pgpMin (pathmax, npaths);
while (newnpaths--) {
/* Add the best path from plist to nplist */
pl1 = &plist;
maxconf = 0.;
maxpl1 = pl1;
while (*pl1) {
/* Find best path in plist in **maxpl1 */
if( (*pl1)->confidence > maxconf ) {
maxconf = (*pl1)->confidence;
maxpl1 = pl1;
}
pl1 = &(*pl1)->next;
}
*nptail = *maxpl1;
*maxpl1 = (*maxpl1)->next;
nptail = &(*nptail)->next;
*nptail = NULL;
}
if( IsntNull(plist) )
pathListFreeAll (plist, db);
}
return nplist;
}
/*
* Append a (copy of a) second path to the first, removing common segments.
* Return pointer to "next" pointer of last segment (and pass that as ptail)
*
* Return tail pointer for updated Path
*
* phead pointer to Path which gets appended to
* ptail tail pointer for Path which gets appended to
* p2 pointer to Path to append (a copy of)
* db PGPKeyDB to use for memory allocations
*
*/
static Path **
pathUnion (Path *phead, Path **ptail, Path *p2, PGPKeyDB *db)
{
Path *p1;
Path **iptail = ptail;
/* Add path p2 but skip those segments in p1 */
for ( ; p2; p2 = p2->next) {
p1 = phead;
for (p1=phead; p1 && p1 != *iptail; p1 = p1->next) {
/* Eliminate path segments which are in there already */
if( p2->src == p1->src && p2->dest == p1->dest ) {
/* Make sure our confidence rules are working */
pgpAssert (p2->confidence == p1->confidence);
break;
}
}
if( IsntNull(p1) && p1 != *iptail )
continue;
*ptail = pathAlloc(db);
if( IsNull(*ptail) )
return NULL;
**ptail = *p2;
ptail = &(*ptail)->next;
*ptail = NULL;
}
return ptail;
}
/*
* Calculate the confidence for a list of paths. We add the confidence for
* each path, subtrace the confidence for the unions of all pairs of paths,
* add the confidence for the unions for all the triples, and so on.
* We actually do this by taking each subset of the paths, unioning them,
* calculating the confidence for that path, and adding or subtracting it
* based on the parity.
*/
static double
pathListConfidence (PathList *plist, PGPKeyDB *db)
{
unsigned pathcount,
mask,
tmask;
PathList *iplist = plist;
double conf = 0.;
#ifdef DEBUGPATH
fprintf (stdout, "Maurer alg:\n");
#endif
pathcount = 0;
while (plist) {
++pathcount;
plist = plist->next;
}
plist = iplist;
pgpAssert (pathcount < sizeof(unsigned) * 8);
for (mask=1; mask < (1U<<pathcount); ++mask) {
double pathconf;
Path *phead=NULL, **ptail=&phead;
int oddparity = 0;
plist = iplist;
tmask = mask;
while (plist && tmask) {
if( tmask & 1 ) {
ptail = pathUnion (phead, ptail, plist->path, db);
oddparity = !oddparity;
}
plist = plist->next;
tmask >>= 1;
}
pathconf = pathConfidence (phead);
#ifdef DEBUGPATH
fprintf (stdout, "%sing %g: ", oddparity?" add":" subb",pathconf);
pgpDebugPrintPath (stdout, phead);
#endif
if( oddparity )
conf += pathconf;
else
conf -= pathconf;
pathFreeAll (phead, db);
phead = NULL;
ptail = &phead;
}
#ifdef DEBUGPATH
fprintf (stdout, "Net of %g\n", conf);
#endif
return conf;
}
/*
* Find the confidence level to use for the given key.
* This is difficult in this trust model because we generally don't
* have validity on the userids associated with the key, since there is
* no well defined (nor arbitrarily imposed) ordering of the graph.
* The result is that when we do our calculation we may end up with a
* de facto validity on a key/userid that has no relation to the (cached)
* validity stored on the key.
*
* So we have a set of heuristics to choose the confidence associated
* with some userid, to wit:
*
* If all the userids have at least some validity, we choose the
* confidence associated with the most valid userid. Otherwise we
* just choose the lowest confidence of all the userids. The reason
* for the second case is so that if we have a true userid and a false
* userid, but the true userid doesn't have validity yet, while the
* false userid has a little tiny bit of validity, we don't want to
* choose the confidence of the false userid, which might be very
* high. It might be that the next step in the path will give high
* validity to the true (but low confidence) userid. We would end up
* counting this key as both high confidence and high validity, which
* may be wron
*
* This heuristic might seem to have the problem that if you get a new userid
* for a trusted
* key its trust will go away until either the new userid gets some validity
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -