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

📄 pgpk.c

📁 著名的加密软件的应用于电子邮件中
💻 C
📖 第 1 页 / 共 5 页
字号:
		if (!*pub) {
			if (log)
				fprintf (log,
"Unknown pubring file, assuming \"pubring.pkr\"\n");
			*pub = "pubring.pkr";
		}
		*pubring = mainOpenRingfile (env, ringpool, *pub, "public",1);
	}

	if (sec && secring) {
		*sec = pgpenvGetString (env, PGPENV_SECRING, NULL, NULL);
		if (!*sec) {
			if (log)
				fprintf (log,
"Unknown secring file, assuming \"secring.skr\"\n");
			*sec = "secring.skr";
		}
		*secring = mainOpenRingfile (env, ringpool, *sec, "private",0);
	}
}


/*
* Searches <ring> for keys matching the substrings on the
* command line. <ring> must be immutable.
* If <argc>==0 and <defAll>, uses the entire <ring>.
* In either case, the *set returned is a valid, newly created, immutable
* set.
*
* Returns 1 if any keys were selected, else 0.
*/
static int
selectKeyArgs(struct PgpEnv *env, int argc, char *argv[],
		char const *ringName, struct RingSet const *ring,
		struct RingSet **set, int defAll)
{
	int anykeys = 0, i, result;

	(void)env;	/* Avoid warning */
	if (argc <= 0 && defAll) {
	*set = ringSetCopy(ring);
		if (!*set)
			exitUsage(ringPoolError(ringpool)->error);
		anykeys = 1;	/* XXX: Not necessarily, ring might be empty */
	} else {
		*set = ringSetCreate(ringpool);
		if (!*set)
			exitUsage(ringPoolError(ringpool)->error);
	for (i = 0; i < argc; i++) {
			result = ringSetFilterSpec(ring, *set, argv[i], 0);
			if (result < 0)
			exitUsage(result);
			else if (result > 0)
				anykeys = 1;
			else
				fprintf(stderr,
					"No key named \"%s\" in keyring \"%s\"\n",
						argv[i], ringName);
		}
	}
	return anykeys;
}

/*
* This selects one RingObject from the given immutable <set> for which
* (*filt)(env, obj, arg) returns non-zero. (*print)(env, file, obj, arg)
* should print a label for the appropriate object to file (with newline),
* suitable for a menu. If there is more than one candidate, and <print>
* is non-null, the user is presented with a menu to choose from. If
* there's more than one candidate and <print> is null, or if there are no
* candidates, 1 is returned. The object is returned in <obj>, or NULL if
* there was an error. Returns < 0 for a library error, 1 for other error,
* or 0 on success.
*
* The <print> function may assume that the global <allkeys> will be
* set correctly by the time it is called. This routine makes sure of
* that, the caller doesn't have to.
*/
static int
selectOneRingObj(struct PgpEnv *env, struct RingSet *set, int level,
		union RingObject **obj1, FILE *out, char const *header,
		void *arg,
		int (*filt)(struct PgpEnv *env, union RingObject const *obj,
				void *arg),
		void (*print)(struct PgpEnv *env, union RingObject *obj,
				FILE *file, void *arg))
{
	struct RingIterator *iter;
	union RingObject *obj, *objList[50];
	int maxObjs = sizeof(objList) / sizeof(objList[0]);
	int numObjs = 0;
	int notFirst = 0;
	int result;
	long choice;
	char *endNum, buf[32];
	int i;

	*obj1 = NULL;
	iter = ringIterCreate(set);
	if (!iter)
		return ringSetError(set)->error;

	/* Advance iter state */
	for (i=1; i<level; ++i)
		if ((result = ringIterNextObject(iter, i)) < 0)
			return result;
	
	for (;;) {
		result = ringIterNextObject(iter, level);
		if (result < 0)
			goto destroyAndExit;
		else if (result == 0)
			break;
		if (numObjs >= maxObjs) {
			fprintf(stderr, "Too many matches; aborting!\n");
			goto destroyAndError;
		}
		obj = ringIterCurrentObject(iter, level);
		pgpAssert(obj);
		if (filt(env, obj, arg)) {
			objList[numObjs++] = obj;
			if (notFirst) {
				if (!print || !out)
					goto destroyAndError;
				loadAllKeys(env, 0, 0);
				if (numObjs == 2) {
					fprintf(out, "%s\n 1) ", header);
					print(env, objList[0], out, arg);
				}
				fprintf(out, "%2d) ", numObjs);
				print(env, obj, out, arg);
			}
			else
				notFirst = 1;
		}
	}
	ringIterDestroy(iter);

	if (numObjs < 1)
		return 1;
	else if (numObjs == 1) {
		*obj1 = objList[0];
		return 0;
	}
	pgpAssert(out);
	fprintf(out, "Choose one of the above: ");
	pgpTtyGetString(buf, sizeof(buf), out);
	choice = strtol(buf, &endNum, 10);
	while (isspace(*endNum))
		endNum++;
	if (*endNum || choice < 1 || choice > numObjs) {
		fprintf(stderr, "Invalid choice\n");
		return 1;
	}
	*obj1 = objList[choice - 1];
	return 0;

destroyAndError:
	result = 1;
destroyAndExit:
	ringIterDestroy(iter);
	return result;
}

/* A filter for selectOneRingObj (above), which selects all keys */
static
int keyFilt(struct PgpEnv *env, union RingObject const *obj, void *arg)
{
	(void)env;	/* Avoid warnings */
	(void)arg;	

	return ringObjectType(obj) == RINGTYPE_KEY;
}

/* A filter to select the specified type */
static
int typeFilt(struct PgpEnv *env, union RingObject const *obj, void *arg)
{
	byte mtype = *(byte *)arg;

	(void)env;	/* Avoid warnings */
	return ringObjectType(obj) == mtype;
}

/*
* A filter for signatures that won't show revocations. We don't print
* those out explicitly so it is better not to try to choose them.
*/
static
int sigFilt(struct PgpEnv *env, union RingObject const *obj, void *arg)
{
	(void)env;
	(void)arg;
	if (ringObjectType(obj) == RINGTYPE_SIG) {
		int type = ringSigType(allkeys, (union RingObject *) obj);
		if (type != PGP_SIGTYPE_KEY_COMPROMISE &&
		type != PGP_SIGTYPE_KEY_UID_REVOKE)
			return 1; /* accept */
	}
	return 0;	 	/* reject */
}


/*
* A key printer for selectOneRingObj (above),
* which prints keys for a menu.
	*/
static void
keyPrint(struct PgpEnv *env, union RingObject *obj,
		FILE *file, void *arg)
{
struct PgpTtyUI ui;
	(void)env;	/* Avoid warnings */
	(void)arg;
	ui.fp = file;
	fputc('\n', file);
	pgpAssert(allkeys);
	ringTtyShowKey((void *) &ui, obj, allkeys, 0);
}

/*
* A name printer for selectOneRingObj (above),
* which prints keys for a menu.
	*/
static void
namePrint(struct PgpEnv *env, union RingObject *obj,
		FILE *file, void *arg)
{
	char const *namestring;
	size_t len;
	struct PgpTtyUI ui;

	(void)env;	/* Avoid warnings */
	(void)arg;

	ui.fp = file;
	fputc('\n', file);
	pgpAssert(allkeys);
	namestring = ringNameName (allkeys, obj, &len);
	ringTtyPutString (namestring, len, (unsigned) len, file, 0, 0);
	fputs("\n", file);
	ringTtyShowSigs ((void *) &ui, obj, allkeys, 2);
}

/*
* A sig printer for selectOneRingObj (above),
* which prints keys for a menu.
*/
static void
sigPrint(struct PgpEnv *env, union RingObject *obj,
		FILE *file, void *arg)
{
	(void)env;	/* Avoid warnings */
	(void)arg;	

	pgpAssert(allkeys);
	fputc('\n', file);
	ringTtyShowSig(obj, allkeys, file, 1);
}

static void
objPrint(struct PgpEnv *env, union RingObject *obj,
		FILE *file, void *arg)
{
	switch (ringObjectType(obj)) {
	case RINGTYPE_KEY:
		keyPrint(env, obj, file, arg);
		break;
	case RINGTYPE_NAME:
		namePrint(env, obj, file, arg);
		break;
	case RINGTYPE_SIG:
		sigPrint(env, obj, file, arg);
		break;
	}
}

/*
* Add an object with all its children to the dest key set.
* The src key set, which controls which children are taken, must be
* immutable. dest must be mutable.
* Return number of objects added, or negative on error.
	*/
static int
ringSetAddHierarchy(struct RingSet *dest, struct RingSet const *src,
		union RingObject *obj)
{
	struct RingIterator *iter;
	int level, initlevel;
	int nobjs;
	int err;

	/* First add the object */
	if ((err=ringSetAddObject(dest, obj)) < 0)
		return err;

	iter = ringIterCreate(src);
	if (!iter)
		return ringSetError(src)->error;

	nobjs = 1;
	initlevel=ringIterSeekTo(iter, obj);
	if (initlevel < 0)
		return initlevel;
	level = initlevel + 1;
	while (level > initlevel) {
		union RingObject *child;
		err = ringIterNextObject(iter, level);
		if (err < 0) {
			ringIterDestroy(iter);
			return err;
		}
		if (err > 0) {
			child = ringIterCurrentObject(iter, level);
			if (!child)
				return ringSetError(src)->error;
			if ((err=ringSetAddObject(dest, child)) < 0)
				return err;
			++nobjs;
			++level;
		} else {
			--level;
		}
	}
	ringIterDestroy(iter);
	return nobjs;
}

/*
* Service routine for selectRingObject, below. This one selects a user ID
* and optionally a signature from a RingSet composed of a single key
* and its descendants. See the comments for selectRingObject for more
* info on the parameters.
	*/
static int
selectChildObject(struct PgpEnv *env, struct RingSet *to_select,
		int selecttype, char const *prep, FILE *log,
		union RingObject **pobj)
{
	struct RingSet *to_select2;
	int err;
	byte type;
	char header[256];
	unsigned counts[RINGTYPE_MAX];

	pgpAssert (selecttype==RINGTYPE_NAME || selecttype==RINGTYPE_SIG);

	ringSetCountTypes(to_select, counts, RINGTYPE_MAX);
	if (selecttype == RINGTYPE_NAME)
		sprintf (header,
"Please select a user ID %s:", prep);
	else
		sprintf (header,
"Please select a user ID with a signature %s:", prep);
	type = RINGTYPE_NAME;
	err = selectOneRingObj(env, to_select, 2, pobj, log,
			header, &type, typeFilt, namePrint);
	if (err) {
		if (log)
			fprintf (log,
"No user ID's selected %s.\n", prep);
		ringSetDestroy(to_select);
		return 0;
	}
	/* Keep name and all its children */
	if (!(to_select2 = ringSetCreate(ringpool))) {
		ringSetDestroy(to_select);
		return ringPoolError(ringpool)->error;
	}
	ringSetAddHierarchy(to_select2, to_select, *pobj);
	ringSetFreeze(to_select2);

	if (selecttype == RINGTYPE_SIG) {
		ringSetCountTypes(to_select2, counts, RINGTYPE_MAX);
		pgpAssert(counts[RINGTYPE_KEY-1] == 1);
		pgpAssert(counts[RINGTYPE_NAME-1] == 1);
		sprintf (header,
"Please select a signature %s:", prep);
		err = selectOneRingObj(env, to_select2, 3, pobj, log,
				header, &type, sigFilt, sigPrint);
		if (err) {
			if (log)
				fprintf (log,
"No signatures selected %s.\n", prep);
			ringSetDestroy(to_select2);
			return 0;
		}
	}
	ringSetDestroy(to_select2);
	pgpAssert(counts[selecttype-1] >= 1);
	return counts[selecttype-1];	/* success */
}


/*
* Selection routine.
* Selects a key, userid or
* signature depending on the selecttype parameter, a RINGTYPE_ value.
* Returns pointer to the object in *pobj. Prep is a prepositional
* clause like "to be removed". Returns 0 if no keys selected, negative
* on error. If objects are selected returns the number of objects at
* that level, e.g. if a user ID is selected it returns the number of
* user ID's on that key; if a signature is selected it returns the
* number of sigs on that user ID. This will always be at least 1.
	*/
static int
selectRingObject(struct PgpEnv *env, int argc, char **argv, char const *pub,
		struct RingSet const *pubring, int selecttype,
		char const *prep, FILE *log, union RingObject **pobj)
{
	struct RingSet *to_select = NULL, *to_select2 = NULL;
	char namebuf[256];
	char header[256];
	size_t namelen;
	int anykeys = 0;
	int err;
	unsigned counts[RINGTYPE_MAX];

		/*
	* Protect header[] from being overfilled by the sprintf's to it.
	* prep is only set within the program to small strings, so this
	* should never happen.
		*/
	pgpAssert (strlen(prep) < 100);

	if (argc == 0) {
		pgpAssert(log);
		fprintf (log,
"A user ID is required to select the key you want %s.\n\
Enter the key's user ID: ", prep);
		namelen = pgpTtyGetString (namebuf, sizeof (namebuf), log);
		argv = (char **)pgpMemAlloc(sizeof(char *));
		argv[0] = namebuf;
		argc = 1;
	}

	/* Set up for return */
	ringSetCountTypes(pubring, counts, RINGTYPE_MAX);

	anykeys = selectKeyArgs (env, argc, argv, pub, pubring, &to_select, 0);
	if (anykeys) {
		ringSetFreeze(to_select);
		if (selecttype == RINGTYPE_NAME)
			sprintf (header,
"Please select a key with a user ID %s:", prep);
		else if (selecttype == RINGTYPE_SIG)
			sprintf (header,
"Please select a key with a signature %s:", prep);
		else
			sprintf (header,
"Please select a key %s:", prep);
		anykeys = !selectOneRingObj (env, to_select, 1, pobj, log,
					header, NULL, keyFilt, keyPrint);
	}
	if (!anykeys) {
		if (log)
			fprintf (log,
"No keys selected %s.\n", prep);
		ringSetDestroy(to_select);
		return 0;
	}

	/* Add key and all its children to a new ringset called to_select */
	to_select2 = ringSetCreate(ringpool);
	if (!to_select2) {
		ringSetDestroy(to_select);
		return ringPoolError(ringpool)->error;
	}
	ringSetAddHierarchy(to_select2, to_select, *pobj);
	ringSetDestroy(to_select);
	to_select = to_select2;
	ringSetFreeze(to_select);

	/* Handle signature and user ID selection */
	if (selecttype != RINGTYPE_KEY) {
		err = selectChildObject(env, to_select, selecttype,
					prep, log, pobj);
		ringSetDestroy(to_select);
		return err;
	}
					
	ringSetDestroy(to_select);
	pgpAssert(counts[selecttype-1] >= 1);
	return counts[selecttype-1];	/* success */
}


static int
doKeyAdd (struct PgpEnv *env, int argc, char *argv[], struct PgpTtyUI *ui_arg)
{
	struct RingSet *pubring = NULL, *secring = NULL;
	struct RingSet *newpub = NULL, *newsec = NULL;
	struct RingSet *tmpring, *keyfile = NULL;
	struct RingIterator *iter;
	char const *pub, *sec;

⌨️ 快捷键说明

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