⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 pgprngread.c

📁 vc环境下的pgp源码
💻 C
📖 第 1 页 / 共 5 页
字号:
			pgpAssert (OBJISBOT(obj) || IsNull(obj->g.down));
			ringRemObject (pool, obj);
		}
	}
}



/*** Closing a Ringfile ***/

/*
 * Set the destruction function for a RingFile.
 */
void
ringFileSetDestructor(RingFile *file,
	void (*destructor)(RingFile *, PGPFile *, void *),
	void *arg)
{
	file->destructor = destructor;
	file->arg = arg;
}

/*
 * Helper function for ringFileDoClose.
 *
 * Delete the given file's FilePos entries from the objects in
 * the given list, and delete the objects if they are no longer
 * needed (mask has gone to 0).  Recurse as necessary.
 *
 * Note that this is not used on the main keys list, because
 * there we need to preserve dummy keys which this does not
 * understand.
 *
 * This also removes any cached names from objects.
 */
static void
ringFileCloseList(union RingObject **objp, RingFile *file,
	PGPVirtMask *allocmask)
{
	union RingObject *obj;
	PGPVirtMask mask;
	RingPool *pool = file->set.pool;

	pgpVirtMaskInit (pool, &mask);

	while ((obj = *objp) != NULL) {
		/*
		 * Delete low-level objects with mask==0 as well as objects on
		 * the ringfile which is going away.  We create those objects, e.g.
		 * when importing a non-exportable sig, and then they prevent the
		 * parent objects from being deleted properly, later leading to
		 * an assertion in keysdiffer.
		 */
		if (pgpIsRingSetMember(&file->set, obj) ||
			pgpVirtMaskIsEmpty (&obj->g.mask)) {
			if (!OBJISBOT(obj))
				ringFileCloseList(&obj->g.down, file, allocmask);
			ringRemFilePos(obj, file);
			/*
			 * Delete objects which have no homes other than MEMRING.
			 * But:
			 * Do not delete objects which have children, because they may
			 * have a child obj in the MEMRING which didn't get deleted
			 * because it was not in this RingFile.
			 * Do not delete objects whose only home is in the MEMRING
			 * but which are currently in use in active RingSets.  They
			 * may be newly created objects which will soon be given homes
			 * in some other RingFile.
			 */
			pgpVirtMaskCopy (pool, &pool->filemask, &mask);
			pgpVirtMaskANDNOT (pool, &pool->memringmask, &mask);
			if (!pgpVirtMaskIsOverlapping (&mask, &obj->g.mask)
					&& (OBJISBOT(obj) || !obj->g.down)
					&& !pgpVirtMaskIsOverlapping (allocmask, &obj->g.mask)) {
				*objp = obj->g.next;
				ringFreeObject(file->set.pool, obj);
			} else {
				/*
				 * If a name is cached from the file which is closing,
				 * purge it since the file's strings table holds the cached
				 * names and it's going away.
				 */
				if (OBJISNAME(obj))
					ringPurgeCachedName(file->set.pool, &obj->n,
										&file->set.mask);
				objp = &obj->g.next;
			}
		} else
			objp = &obj->g.next;
	}
	pgpVirtMaskCleanup (pool, &mask);
}

/*
 * Close the given Ringfile.  Returns an error if it can't due to
 * conflicts, in which case the file is NOT closed.
 *
 * This performs four passes over the pool.
 * 1. The first does the bulk of the deletion, removing the
 *    FilePos from the objects and deleting all things
 *    at levels greater than 1.
 * 2. The second rebuilds the sigs-by lists which were broken by
 *    deleting objects in the middle of them.
 * 3. The third finds all keys that are not referenced and do not
 *    make any signatures, and deletes those keys.
 * 4. The fourth rebuilds the hash index of the remaining keys.
 *
 * Note that the second and third passes delete any allocated-but-not
 * linked keys, which are left by ringFileOpen if it runs out of memory
 * in mid-operation.
 */
static void
ringFileDoClose(RingFile *file)
{
	union RingObject *obj, **objp;
	RingPool *pool = file->set.pool;
	int i;
	PGPVirtMask allocmask;
	PGPVirtMask mask;
	PGPUInt32 filebit;

	pgpVirtMaskInit (pool, &allocmask);
	pgpVirtMaskInit (pool, &mask);

	ringAllocMask (pool, &file->set, &allocmask);

	/* Free some memory right away */
	ringFilePurgeTrouble(file);

	/* 1: Remove everything in the keyring, but don't delete the keys */
	for (obj = pool->keys; obj; obj = obj->g.next) {
		if (pgpIsRingSetMember (&file->set, obj)) {
			if (!OBJISBOT(obj))
				ringFileCloseList(&obj->g.down, file, &allocmask);
			ringRemFilePos(obj, file);
		}
	}

	/* 2: Recreate the shattered sigs-by lists */
	ringPoolListSigsBy(pool);

	/* 3: Now purge the unneeded keys */
	objp = &pool->keys;
	while ((obj = *objp) != NULL) {
		pgpAssert(OBJISTOPKEY(obj));
		pgpVirtMaskCopy (pool, &obj->g.mask, &mask);
		pgpVirtMaskANDNOT (pool, &pool->memringmask, &mask);
		if (pgpVirtMaskIsOverlapping (&mask, &pool->filemask) || obj->g.down) {
			objp = &obj->g.next;
		} else if (obj->k.sigsby) {
			/* Retain key as a dummy key */
			pgpAssert(!pgpVirtMaskIsOverlapping (&mask, &allocmask));
			pgpAssert(!obj->g.down);
			pgpVirtMaskCleanup (pool, &obj->g.mask);
			objp = &obj->g.next;
		} else {
			/* Delete the key */
			pgpAssert(!pgpVirtMaskIsOverlapping (&mask, &allocmask));
			pgpAssert(!obj->g.down);
			*objp = obj->g.next;
			ringFreeObject(pool, obj);
		}
	}

	/* 4: Re-initialize the hash chains */
	ringPoolHash(pool);

	/* Clean up the file's memory pools */
	memPoolEmpty(&file->strings);
	file->freepos = NULL;
	memPoolEmpty(&file->fpos);

	pgpAssert(!file->set.next);

	/*
	 * If there's nothing in the structs MemPool that's
	 * allocated, purge all the memory.
	 */
	if (!pool->keys && !pool->sets) {
		for (i = 0; i < RINGTYPE_MAX; i++)
			pool->freeobjs[i] = NULL;
		pool->freesets = NULL;
		pool->freeiter = NULL;
		memPoolEmpty(&pool->structs);
	}

	/* Cal the file's destructor function, if any */
	if (file->destructor) {
		file->destructor(file, file->f, file->arg);
		file->destructor = NULL;
	}

	/* Final deallocation of the file */
	file->flags = 0;
	pgpVirtMaskANDNOT (pool, &file->set.mask, &pool->filemask);

	filebit = pgpVirtMaskLSBit (&file->set.mask);
	pgpVirtMaskCleanup (pool, &file->set.mask);
	pgpVirtMaskCleanup (pool, &file->higherpri);
	pgpAssert (pool->files[filebit] == file);
	pgpContextMemFree (pool->context, file);
	pool->files[filebit] = NULL;

	pgpVirtMaskCleanup (pool, &mask);
	pgpVirtMaskCleanup (pool, &allocmask);
}

/*
 * Check to see if an object anywhere on the list (including children,
 * recursively) is included in "allocmask" but not in "filemask."
 * Such an object is orphaned, an undesirable state of affairs.
 * We have to check the entire keyring, recursively, because a
 * given key or name might be duplicated in another keyring, but
 * a signature lower down might not be.
 */
static int
ringFileCheckList(union RingObject const *obj, PGPVirtMask *filemask,
	PGPVirtMask *allocmask)
{
	while (obj) {
		if (pgpVirtMaskIsOverlapping (&obj->g.mask, allocmask)) {
			/* Would closing orphan this object? */
			if (!pgpVirtMaskIsOverlapping (&obj->g.mask, filemask))
				return 1;
			/* Would closing orphan its children? */
			if (!OBJISBOT(obj) && ringFileCheckList(obj->g.down,
			                                        filemask,
			                                        allocmask))
				return 1;
		}
		obj = obj->g.next;
	}
	return 0;
}

/* Is it safe to close the given file? */
int
ringFileCheckClose(RingFile const *file)
{
	RingPool const *pool = file->set.pool;
	int rtrn;
	PGPVirtMask allocmask;
	PGPVirtMask mask;

	if (!file)
		return 0;
	pgpVirtMaskInit (pool, &allocmask);
	pgpVirtMaskInit (pool, &mask);
	ringAllocMask (pool, &file->set, &allocmask);
	pgpVirtMaskCopy (pool, &pool->filemask, &mask);
	pgpVirtMaskANDNOT (pool, &file->set.mask, &mask);

	rtrn = ringFileCheckList(pool->keys, &mask, &allocmask);

	pgpVirtMaskCleanup (pool, &allocmask);
	pgpVirtMaskCleanup (pool, &mask);
	return rtrn;
}

/*
 * Close the given Ringfile.  Returns an error if it can't due to
 * conflicts, in which case the file is NOT closed.
 */
	PGPError
ringFileClose(RingFile *file)
{
	if (!file)
		return kPGPError_NoErr;	/* close(NULL) is defines as harmless */

	if (ringFileCheckClose(file))
		return kPGPError_LazyProgrammer;

	/* Okay, nothing can fail now */
	ringFileDoClose(file);

	return kPGPError_NoErr;
}

/*** Routines for fetching things from the keyring ***/

/* Make sure the pool's packet buffer is large enough */
char *
ringReserve(RingPool *pool, size_t len)
{
	PGPError	err	= kPGPError_NoErr;

	if (pool->pktbufalloc >= len)
		return pool->pktbuf;
	
	if( IsNull( pool->pktbuf ) ) {
		pool->pktbuf = (char *)
			pgpContextMemAlloc( pool->context, len, 0 );
				
		if( IsNull( pool->pktbuf ) )
			err = kPGPError_OutOfMemory;
	} else {
		void *vpktbuf = pool->pktbuf;
		err	= pgpContextMemRealloc( pool->context, &vpktbuf, len,
									0 );
		pool->pktbuf = (char *)vpktbuf;
	}
	if ( IsPGPError( err ) )
	{
		ringAllocErr(pool);
		return NULL;
	}
	pool->pktbufalloc = len;
	return pool->pktbuf;
}


/*
 * File priorities are handled by a "higherpri" mask with each file,
 * which is a mask of other files of higher priority than that file.
 * If obj->g.mask & pool->filmask && file->higherpri is 0,
 * this is the highest-priority file.
 */
/* Set file to the highest priority, except for the memory file */
void
ringFileHighPri(RingFile *file)
{
	RingPool *pool = file->set.pool;
	unsigned i;

	/* Add this file to everything else's higher priority mask */
	for (i = 0; i < pool->nfiles; i++)
		if (IsntNull(pool->files[i]))
			pgpVirtMaskOR (pool, &file->set.mask, &pool->files[i]->higherpri);
	/* The only thing higher priority than this file is MEMRING */
	pgpVirtMaskCopy (pool, &pool->memringmask, &file->higherpri);
}

/* Set file to the lowest priority */
void
ringFileLowPri(RingFile *file)
{
	RingPool *pool = file->set.pool;
	unsigned i;

	/* Remove this file from everything else's higher priority mask */
	for (i = 0; i < pool->nfiles; i++) {
		if (IsntNull(pool->files[i])) {
			pgpVirtMaskANDNOT (pool, &file->set.mask,
							   &pool->files[i]->higherpri);
			if (pool->files[i] != file)
				pgpVirtMaskSetBit (pool, &file->higherpri, i);
		}
	}
}


/* The mask of sets that this key has *any* secret components in */
static PGPError
ringKeySecMask(RingPool *pool, RingObject const *obj, PGPVirtMask *omask)
{
	pgpAssert(OBJISKEY(obj));

	pgpVirtMaskCleanup (pool, omask);
	for (obj = obj->g.down; obj; obj = obj->g.next)
		if (OBJISSEC(obj)) {
			pgpVirtMaskOR (pool, &obj->g.mask, omask);
		}
	return kPGPError_NoErr;
}

/*
 * Given an object, find the best RingFile to fetch it from,
 * for fetching purposes.  Bits set in "avoidmask" are
 * NOT valid for fetching, if avoidmask is nonnull.
 */
static RingFile *
ringBestFile(RingPool *pool, union RingObject const *obj,
	PGPVirtMask *avoidmask)
{
	PGPVirtMask mask, tmpmask;
	RingFile *file;
	int bit;

	pgpVirtMaskInit (pool, &mask);
	pgpVirtMaskInit (pool, &tmpmask);

	pgpVirtMaskCopy (pool, &obj->g.mask, &mask);
	pgpVirtMaskAND (pool, &pool->filemask, &mask);

	pgpVirtMaskCopy (pool, &mask, &tmpmask);
	if (IsntNull(avoidmask))
		pgpVirtMaskANDNOT (pool, avoidmask, &tmpmask);
	if (pgpVirtMaskIsEmpty (&tmpmask)) {
		pgpVirtMaskCleanup (pool, &mask);
		pgpVirtMaskCleanup (pool, &tmpmask);
		return NULL;
	}

	/* find highest-priority fetchable file */
	for (;;) {
		/* Is least-significant bit set in mask fetchable? */
		bit = pgpVirtMaskLSBit (&mask);
		pgpVirtMaskCleanup (pool, &tmpmask);
		pgpVirtMaskSetBit (pool, &tmpmask, bit);
		if (IsNull(avoidmask) ||
			!pgpVirtMaskIsOverlapping (&tmpmask, avoidmask)) {
			file = pool->files[bit];
			/* Is it highest priority? */
			pgpVirtMaskCopy (pool, &mask, &tmpmask);
			if (IsntNull(avoidmask))
				pgpVirtMaskANDNOT (pool, avoidmask, &tmpmask);
			if (!pgpVirtMaskIsOverlapping (&tmpmask, &file->higherpri))
				break;
			pgpAssert(file->f);
		}
		pgpVirtMaskClearBit (pool, &mask, bit);
		pgpAssert(!pgpVirtMaskIsEmpty(&mask));
	}
	pgpVirtMaskCleanup (pool, &mask);
	pgpVirtMaskCleanup (pool, &tmpmask);
	return file;
}

/* Macro wrapper to inline the important part */
#define ringReserve(pool, len) \
	((pool)->pktbufalloc < (len) ? ringReserve(pool, len) : (pool)->pktbuf)

/* 
 * This is the routine which fetches a packet from a keyring file.
 * It tries the highest-priority file that the object is in which is also
 * listed in "avoidmask."  If the memory keyring is one of those, it has
 * absolute priority.  (It is also not verified; it is assumed correct.)
 * Otherwise, the object is fetched from the highest-priority open file.
 *

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -