pgprngpub.c
来自「著名的加密软件的应用于电子邮件中」· C语言 代码 · 共 2,518 行 · 第 1/4 页
C
2,518 行
/*
* pgpRngPub.c - keyring management public functions.
*
* Copyright (C) 1994-1997 Pretty Good Privacy, Inc. All rights reserved.
*
* Written by Colin Plumb.
*
* $Id: pgpRngPub.c,v 1.26.2.4 1997/06/07 09:50:40 mhw Exp $
*/
#if HAVE_CONFIG_H
#include "config.h"
#endif
#include <ctype.h> /* For tolower() */
#include "pgpDebug.h"
#include "pgpRngPriv.h"
#include "pgpRngPars.h"
#include "pgpTrstPkt.h"
#include "pgpTrust.h"
#include "pgpRngMnt.h"
#include "pgpErr.h"
#include "pgpPubKey.h"
#include "pgpRngPub.h"
#include "pgpRngRead.h"
#include "pgpSigSpec.h"
#include "pgpMem.h"
#ifndef NULL
#define NULL 0
#endif
/*
* The four type bits are encoded as follows:
* 76543210
* 1 - Name (n)
* 01 - Signature (s)
* 001 - Key (k)
* 0001 - Secret (We use the letter "c" for this)
* 0000 - Unknown keyring object
*/
int
ringObjectType(union RingObject const *obj)
{
int const types[16] = {
RINGTYPE_UNK, RINGTYPE_SEC, RINGTYPE_KEY, RINGTYPE_KEY,
RINGTYPE_SIG, RINGTYPE_SIG, RINGTYPE_SIG, RINGTYPE_SIG,
RINGTYPE_NAME, RINGTYPE_NAME, RINGTYPE_NAME, RINGTYPE_NAME,
RINGTYPE_NAME, RINGTYPE_NAME, RINGTYPE_NAME, RINGTYPE_NAME
};
pgpAssert (obj);
return types[obj->g.flags/RINGOBJF_SEC & 15];
}
/*
* These are intended to track reference counts for swapping
* pieces of keyring out of memory, but are currently no-ops.
*
* They're called in a few places in the code as placeholders, but
* that's just for documentation purposes.
*/
void
ringObjectHold(union RingObject *obj)
{
(void)obj;
}
void
ringObjectRelease(union RingObject *obj)
{
(void)obj;
}
struct RingPool *
ringSetPool(struct RingSet const *set)
{
if (!set)
return NULL;
return set->pool;
}
/*
* Return errors in all sorts of cases.
*/
struct RingError const *
ringPoolError(struct RingPool const *pool)
{
pgpAssert (pool);
return &pool->e;
}
void
ringPoolClearError(struct RingPool *pool)
{
if (pool) {
pool->e.f = (struct RingFile *)NULL;
pool->e.fpos = (word32)-1;
pool->e.error = 0;
pool->e.syserrno = 0;
}
}
struct RingError const *
ringSetError(struct RingSet const *set)
{
pgpAssert (set);
return &set->pool->e;
}
void
ringSetClearError(struct RingSet *set)
{
if (set)
ringPoolClearError(set->pool);
}
struct RingError const *
ringIterError(struct RingIterator const *iter)
{
pgpAssert (iter);
return &iter->set.pool->e;
}
void
ringIterClearError(struct RingIterator *iter)
{
if (iter)
ringPoolClearError(iter->set.pool);
}
struct RingError const *
ringFileError(struct RingFile const *f)
{
pgpAssert (f);
return &f->set.pool->e;
}
void
ringFileClearError(struct RingFile *f)
{
if (f)
ringPoolClearError(f->set.pool);
}
/*
* Is the object a member of the set?
* Returns the level of the object, or 0 if it is not.
*/
int
ringSetIsMember(struct RingSet const *set, union RingObject const *obj)
{
int level = 1;
while (obj->g.mask & set->mask) {
if (OBJISTOP(obj))
return level;
obj = obj->g.up;
level++;
}
return 0; /* Not a member of the iterator */
}
struct RingSet const *
ringIterSet(struct RingIterator const *iter)
{
if (!iter)
return NULL;
return &iter->set;
}
struct RingSet const *
ringFileSet(struct RingFile const *file)
{
if (!file)
return NULL;
return &file->set;
}
PgpVersion
ringFileVersion(struct RingFile const *file)
{
if (!file)
return 0;
return file->version;
}
/*
* An iterator involves a current position which is a stack, with an
* accessible stack-depth value. The stack depth equals the level
* of the last ringIterNextObject call, and the stack entries
* are the return values. If a query is made for a level which
* is greater than the stack depth, the first entry on the list
* of descendants of the top entry on the stack is returned.
* Only the highest-level entry may be NULL; that indicates that the
* end of the list there has been reached. It is illegal to
* ask for descendants of a NULL entry; although returning NULL
* is another reasonable option, the usefulness is unclear and the
* stricter rule has the advantage of catching bugs faster.
*/
/*
* Find the next object of the given level in the given iterator.
* Returns <0 on error, 0 if there is no object, or the level if
* there is one.
*/
int
ringIterNextObject(struct RingIterator *iter, unsigned level)
{
union RingObject *obj;
pgpAssert(iter);
pgpAssert(level);
pgpAssert(iter->set.type == RINGSET_ITERATOR);
/* Get the head of the list to search */
if (level <= iter->level) {
/* Going along an existing level */
iter->level = level;
obj = iter->stack[level-1];
if (!obj)
return 0;
pgpAssert(obj->g.mask & iter->set.mask);
obj = obj->g.next;
} else {
/* Going down a level */
pgpAssert(level == iter->level+1);
if (level > 1) {
obj = iter->stack[level-2];
pgpAssert(obj);
pgpAssert(obj->g.mask & iter->set.mask);
if (OBJISBOT(obj))
return 0;
obj = obj->g.down;
} else {
obj = iter->set.pool->keys;
}
iter->level = level;
}
/* Search for the next item of interest */
while (obj && !(obj->g.mask & iter->set.mask))
obj = obj->g.next;
pgpAssert(level <= RINGMAXDEPTH);
iter->stack[level-1] = obj;
return obj ? level : 0;
}
/*
* More complex because we need to find the head of the enclosing list and
* search forwards for the last matching object that's not the target object.
*/
int
ringIterPrevObject(struct RingIterator *iter, unsigned level)
{
union RingObject *obj, *found, *target;
pgpAssert(iter);
pgpAssert(level);
pgpAssert(iter->set.type == RINGSET_ITERATOR);
/* There's nothing before the beginning of a list */
if (level > iter->level) {
pgpAssert(level == iter->level+1);
return 0;
}
/* The thing we want the predecessor of */
target = iter->stack[level-1];
/* The head of the list to search along */
if (level > 1) {
obj = iter->stack[level-2];
pgpAssert(obj);
pgpAssert(obj->g.mask & iter->set.mask);
obj = obj->g.down;
/* obj = iter->stack[level-2]->g.down; */
} else {
obj = iter->set.pool->keys;
}
/*
* Search forward along the list until we hit the current
* object, kepping track of the last object in the desired
* ringSet.
*/
found = NULL;
while (obj != target) {
pgpAssert(obj);
if (obj->g.mask & iter->set.mask)
found = obj;
obj = obj->g.next;
}
if (!found) {
/* Hit beginning of list, set up as beginning */
iter->level = level-1;
return 0;
}
iter->stack[level-1] = found;
if (OBJISBOT(found)) {
/* Found an object, but no children. */
return iter->level = level;
} else {
/* An object with children - set up that list at end */
pgpAssert(level <= RINGMAXDEPTH);
iter->stack[level] = NULL;
iter->level = level+1;
}
return (int)level;
}
/* The level of the most recent ringIterNextObject() call */
unsigned
ringIterCurrentLevel(struct RingIterator const *iter)
{
return iter->level;
}
/*
* A trivial little function that just returns the current object
* at a given level, again.
*/
union RingObject *
ringIterCurrentObject(struct RingIterator const *iter, unsigned level)
{
pgpAssert(iter);
pgpAssert(level);
pgpAssert(iter->set.type == RINGSET_ITERATOR);
return level > iter->level ? NULL : iter->stack[level-1];
}
/*
* Seek to the next object at the deepest level possible.
*
* Equivalent to:
* int i;
* unsigned l = ringIterCurrentLevel(iter)+1;
*
* while (l && !(i = ringIterNextObject(iter, l)))
* --l;
* return i;
*/
int
ringIterNextObjectAnywhere(struct RingIterator *iter)
{
union RingObject *obj;
unsigned level = iter->level;
ringmask mask = iter->set.mask;
pgpAssert(iter);
pgpAssert(iter->set.type == RINGSET_ITERATOR);
/* Find first object to be considered */
if (!level) {
level = 1;
obj = iter->set.pool->keys;
} else {
obj = iter->stack[level-1];
if (obj) {
pgpAssert(obj->g.mask & mask);
if (OBJISBOT(obj)) {
obj = obj->g.next;
} else {
level++;
obj = obj->g.down;
}
}
}
for (;;) {
while (obj) {
if (obj->g.mask & mask) {
iter->stack[level-1] = obj;
iter->level = level;
return (int)level;
}
obj = obj->g.next;
}
if (!--level)
break;
obj = iter->stack[level-1];
pgpAssert(obj);
obj = obj->g.next;
}
/* End of list, no luck */
iter->stack[0] = NULL;
iter->level = 1;
return 0;
}
/* Reset the iterator to the beginning of the given level */
int
ringIterRewind(struct RingIterator *iter, unsigned level)
{
pgpAssert(level);
pgpAssert(iter->level >= level - 1);
iter->level = level-1;
return 0;
}
/* Reset the iterator to the end of the given level */
int
ringIterFastForward(struct RingIterator *iter, unsigned level)
{
pgpAssert(level);
pgpAssert(level <= iter->level + 1);
if (level > RINGMAXDEPTH)
level = RINGMAXDEPTH;
else
iter->stack[level-1] = NULL;
iter->level = level;
return 0;
}
/*
* Seek the iterator to the given object, state as if it just
* returned the object. Returns the level of the object, or <0
* on error.
*/
int
ringIterSeekTo(struct RingIterator *iter, union RingObject *obj)
{
union RingObject *p, *pp;
int level;
pgpAssert(iter->set.type == RINGSET_ITERATOR);
if (!(obj->g.mask & iter->set.mask))
return 0; /* Not a member */
/* A bit ad-hoc; there is a general way. */
if (OBJISTOP(obj)) {
iter->stack[0] = obj;
level = 1;
} else {
p = obj->g.up;
pgpAssert(p->g.mask & iter->set.mask);
if (OBJISTOP(p)) {
iter->stack[0] = p;
iter->stack[1] = obj;
level = 2;
} else {
pp = p->g.up;
pgpAssert(pp->g.mask & iter->set.mask);
pgpAssert(OBJISTOP(pp));
iter->stack[0] = pp;
iter->stack[1] = p;
iter->stack[2] = obj;
level = 3;
}
}
return iter->level = level;
}
static void
ringSetCountList(union RingObject const *obj, ringmask mask,
unsigned *counts, unsigned depth)
{
while (obj) {
if (obj->g.mask & mask) {
counts[0]++;
if (depth && !OBJISBOT(obj)) {
ringSetCountList(obj->g.down, mask,
counts+1, depth-1);
}
}
obj = obj->g.next;
}
}
/*
* Count the number of objects in an iterator down to a given depth.
*/
int
ringSetCount(struct RingSet const *set, unsigned *counts, unsigned depth)
{
unsigned i = 0;
for (i = 0; i < depth; i++)
counts[i] = 0;
if (set && set->mask && depth > 0)
ringSetCountList(set->pool->keys, set->mask, counts, depth-1);
return 0;
}
static void
ringSetCountTypesList(union RingObject const *obj, ringmask mask,
unsigned *counts, unsigned max)
{
int t;
while (obj) {
if (obj->g.mask & mask) {
t = ringObjectType(obj);
if ((unsigned)t <= max)
counts[t-1]++;
if (!OBJISBOT(obj))
ringSetCountTypesList(obj->g.down, mask,
counts, max);
}
obj = obj->g.next;
}
}
/*
* Count the number of objects in an iterator of various types.
*/
int
ringSetCountTypes(struct RingSet const *set, unsigned *counts, unsigned max)
{
unsigned i = 0;
for (i = 0; i < max; i++)
counts[i] = 0;
if (set && set->mask && max > 0)
ringSetCountTypesList(set->pool->keys, set->mask, counts, max);
return 0;
}
struct RingIterator *
ringIterCreate(struct RingSet const *set)
{
struct RingPool *pool = set->pool;
struct RingIterator *iter;
pgpAssert(!RINGSETISMUTABLE(set));
/* Allocate the structure */
iter = pool->freeiter;
if (iter) {
pool->freeiter = (struct RingIterator *)iter->set.next;
pgpAssert(iter->set.type == RINGSET_FREE);
} else {
iter = (struct RingIterator *)memPoolNew(&pool->structs,
struct RingIterator);
if (!iter) {
ringAllocErr(pool);
return NULL;
}
}
/* Okay, allocated - fill it in */
iter->set.pool = pool;
iter->set.next = pool->sets;
iter->set.type = RINGSET_ITERATOR;
pool->sets = &iter->set;
iter->set.mask = set->mask;
iter->level = 0; /* Rewind to beginning */
return iter;
}
void
ringIterDestroy(struct RingIterator *iter)
{
struct RingPool *pool;
struct RingSet **setp;
if (iter) {
pool = iter->set.pool;
pgpAssert(iter->set.type == RINGSET_ITERATOR);
iter->set.type = RINGSET_FREE;
/* Remove it from the list of allocated sets */
setp = &pool->sets;
while (*setp != &iter->set) {
pgpAssert(*setp);
setp = &(*setp)->next;
}
*setp = iter->set.next;
/* Add to the list of free iterators. */
iter->set.next = (struct RingSet *)pool->freeiter;
pool->freeiter = iter;
}
}
static struct RingSet *
ringSetAlloc(struct RingPool *pool)
{
struct RingSet *set;
/* Allocate the structure */
set = pool->freesets;
if (set) {
pool->freesets = set->next;
} else {
set = (struct RingSet *)memPoolNew(&pool->structs,
struct RingSet);
if (!set) {
ringAllocErr(pool);
return NULL;
}
}
/* Okay, allocated - fill it in */
set->pool = pool;
set->next = pool->sets;
pool->sets = set;
/* set->mask and set->type uninitialized */
return set;
}
struct RingSet *
ringSetCreate(struct RingPool *pool)
{
ringmask mask;
struct RingSet *set;
int bit;
if (!pool)
return NULL;
/* Allocate a new bit */
bit = ringBitAlloc(pool);
if (bit < 0)
return NULL;
mask = (ringmask)1<<bit;
/* Allocate the structure */
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?