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

📄 pgpk.c

📁 著名的加密软件的应用于电子邮件中
💻 C
📖 第 1 页 / 共 5 页
字号:
/*
 * pgpk.c -- PGP Key Management Main Routine!
 *
 * Copyright (C) 1996,1997 Pretty Good Privacy, Inc. All rights reserved.
 *
 * Written by:	Derek Atkins <warlord@MIT.EDU>
 * Mark H. Weaver <mhw@netris.org>
 * Chris Harman <charman@pgp.com>
 *
 * $Id: pgpk.c,v 1.1.2.5 1997/06/07 09:49:18 mhw Exp $
 */

#ifdef HAVE_CONFIG_H
#include "config.h"
#endif

#include <stdio.h>
#include <string.h>
#include <time.h>
#include <ctype.h>

#ifdef HAVE_SYS_PARAM_H
#include <sys/param.h>
#endif
#ifdef HAVE_STDLIB_H
#include <stdlib.h>
#endif
#ifdef HAVE_UNISTD_H
#include <unistd.h>		/* for sbrk() */
#endif
#ifdef UNIX
#include <sys/stat.h>		 /* for umask() */
#endif

#include "pgpDebug.h"
#include "pgpArmor.h"
#include "pgpFileMod.h"
#include "pgpFIFO.h"
#include "pgpKeySpec.h"
#include "pgpMem.h"
#include "pgpPassCach.h"
#include "pgpConf.h"
#include "pgpEnv.h"
#include "pgpErr.h"
#include "pgpFile.h"
#include "pgpUI.h"
#include "pgpPipeline.h"
#include "pgpPubKey.h"
#include "pgpRndom.h"
#include "pgpRndPool.h"
#include "pgpRngPub.h"
#include "pgpRngRead.h"
#include "pgpUserIO.h"
#include "pgpUsuals.h"
#include "pgpRingUI.h"
#include "pgpRngMnt.h"
#include "pgpSigSpec.h"
#include "pgpTrust.h"
#include "pgpTrstPkt.h"

#include "pgpExit.h"
#include "pgpAppFile.h"
#include "pgpKeyRings.h"
#include "pgpInitApp.h"
#include "pgpOpt.h"

#define MAXARGS 2

struct Flags {
	char args[MAXARGS];
	int argc;
	char const *outfile;
	char opt;
	byte doarmor;
};

static struct PgpPassCache *passcache = NULL;
static struct RingPool *ringpool = NULL;
static struct RingSet *allkeys = NULL;
static struct PgpRandomContext *rng = NULL;

#define PASSLEN 256

static void
setOptArgs (char const *args, struct PgpOptContext *opt, struct Flags *flags)
{
	while (*opt->optarg && strchr (args, *opt->optarg))
		flags->args[flags->argc++] = *(opt->optarg++);
}

static void
setOpt (int opt, struct PgpOptContext *optp, struct Flags *flags)
{
	if (!flags->opt) {
		flags->opt = opt;

		if (optp->state == 1 && optp->optarg)
			switch (opt) {
			case 'k':
				setOptArgs ("s", optp, flags);
				break;
			case 'l':
				setOptArgs ("l", optp, flags);
				break;
			case 'r':
				setOptArgs ("su", optp, flags);
				break;
			case 'x':
				setOptArgs ("a", optp, flags);
				break;
			}

		return;
	}

	exitArgError ("Cannot use -%c and -%c together\n", flags->opt, opt);
}

static void
mainParseArgs (struct PgpUICb *ui, void *ui_arg, struct PgpEnv *env,
	int *argcp, char *argv[], struct Flags *flags)
{
	struct PgpOptContext opt;
	int c, argc = *argcp;

	pgpOptStart (&opt, argc, argv);
	argc = 0;

	while ((c = pgpOptNext (&opt)) != EOF) {
		switch (c) {
		case 0:
	if (opt.optarg[0] != '+' || opt.optarg[1] == '\0')
				argv[argc++] = opt.optarg;
			else if (pgpConfigLineProcess (ui, ui_arg, env,
						opt.optarg + 1,
						PGPENV_PRI_CMDLINE))
				exitArgError ("Unrecognized option %s",
					opt.optarg);
			break;
		case '-':
			/* This accepts --foo */
			/* -- is special-cased, so "-- foo" won't do. */
			if (pgpConfigLineProcess(ui, ui_arg, env, opt.optarg,
						PGPENV_PRI_CMDLINE))
				exitArgError (
				"Unrecognized option -%s",
				opt.optarg - 1);
			opt.optarg = NULL;
			break;
		case 'a':	/* Add */
		case 'c':	/* Check */
		case 'd': /* Disable */
		case 'e':	/* Edit */
		case 'g':	/* Generate */
		case 'k':	/* Revo(k)e */
		case 'l':	/* List */
		case 'r':	/* Remove */
		case 's':	/* Sign */
		case 'x':	/* eXtract */
			setOpt (c, &opt, flags);
			break;
		case 'h':	/* Help */
			exitUsage (PGPEXIT_OK);
			/*NOTREACHED*/
		case 'o':	/* Output */
			/* XXX check for duplicate args */
			if (!opt.optarg)
				exitArgError (
				"-o option requires a userid argument");
			flags->outfile = opt.optarg;
			opt.optarg = 0;
			break;
		case 'u':	/* Username (myname) */
			/* XXX Check for duplicate args */
			if (!opt.optarg)
				exitArgError (
				"-u option requires a userid argument");
			pgpenvSetString (env, PGPENV_MYNAME, opt.optarg,
					PGPENV_PRI_CMDLINE);
			opt.optarg = 0;
			break;
		case 'v':	/* Verbose */
			pgpenvSetInt(env, PGPENV_VERBOSE, 1+
			pgpenvGetInt(env, PGPENV_VERBOSE,
					NULL, NULL), PGPENV_PRI_CMDLINE);
			break;
		default:
			exitArgError ("Unrecognized option -%c", c);
		}
	}
	*argcp = argc;
	return;
}

/* Two functions to write out extracted key files */
static int
mainWriteSet (FILE *fp, int flags, struct RingSet const *set)
{
	struct PgpFile *pfp = pgpFileWriteOpen (fp, NULL);
	int rslt = ringSetWrite (set, pfp, NULL, PGPVERSION_3,
				flags);
	pgpFileClose(pfp);
	return rslt;
}

/* Like mainWriteSet, but for armored files */
static int
mainWriteArmoredSet (FILE *fp, int flags, struct RingSet const *set,
struct PgpEnv *env)
{
	struct PgpFile *pfp;
	struct PgpPipeline *ppl = NULL;
	int rslt;
	
	pfp = pgpFileWriteOpen(fp, NULL);
	if (!pfp) {
		fclose(fp);
		return PGPERR_NOMEM;
	}
	if (!pgpFileWriteCreate (&ppl, pfp, 1)) {
		pgpFileClose(pfp);
		return PGPERR_NOMEM;
	}
	if (!rng)
		rng = pgpRandomCreate ();
	if (!pgpArmorWriteCreate(&ppl, env, &pgpByteFifoDesc,
				rng, PGPVERSION_2_6, PGP_ARMOR_NORMAL)) {
		ppl->teardown(ppl);
		return PGPERR_NOMEM;
	}
	pfp = pgpFilePipelineOpen(ppl);
	if (!pfp) {
		ppl->teardown(ppl);
		return PGPERR_NOMEM;
	}
	rslt = ringSetWrite (set, pfp, NULL, PGPVERSION_2_6, flags);
	pgpFileClose(pfp);
	return rslt;
}

#if 0
/* Unused at present. fp must be a seekable stream. */
static struct RingSet const *
mainOpenKeyring (FILE *fp, int trusted)
{
	struct RingFile *ring;
	struct PgpFile *pfp;
	int error = 0;

	pfp = pgpFileReadOpen (fp, NULL, NULL);
	ring = ringFileOpen (ringpool, pfp, trusted, &error);
	if (error)
		fprintf (stderr, "ringFileOpen returned %d: %s\n",
			error, pgperrString (error));
	if (ring)
		return ringFileSet (ring);
	return NULL;
}
#endif

static int
setPassword (struct PgpEnv *env, struct PgpSecKey *seckey, void *ui_arg)
{
	char pass[PASSLEN];
	char pass2[PASSLEN];
	int error;

	pgpAssert (! pgpSecKeyIslocked (seckey));

	do {
		memset (pass, 0, sizeof (pass));
		memset (pass2, 0, sizeof (pass2));

		pgpTtyGetPass (ui_arg, pass, sizeof(pass));
		fputs ("Enter same pass phrase again\n", stderr);
		pgpTtyGetPass (ui_arg, pass2, sizeof(pass2));

		if (!strcmp (pass, pass2))
			break;
		fprintf (stderr,
			"Error: Pass phrases were different.  Try again.\n");
	} while (1);

	if (!strlen (pass))
		return 0;

	memset (pass2, 0, sizeof (pass2));
	error = pgpSecKeyChangeLock (seckey, env, rng, pass, strlen (pass));
	memset (pass, 0, sizeof (pass));
	return error;
}

/* Perform the maintenance pass and get trust info for interesting
keys. */

static const char checking[] = "Checking %d signatures...\n";

static int
doKeyEditTrust(union RingObject *obj, struct RingSet *set, int firsttime,
	FILE *log); /* forward ref */

/*
 * Callback function for displaying sig progress.  We just show a count on
 * every 10th sig check
 */
static void
mainShowSigCheckProgress(void *arg, struct RingIterator *iter, int checkok)
{
	int sigcheckcount = *(int *)arg;
	(void)iter;
	(void)checkok;
	++sigcheckcount;
	*(int *)arg = sigcheckcount;
	if (sigcheckcount % 10 == 0)
		fprintf (stderr, "%6d    \r", sigcheckcount);
}

static int
mainDoMaint (void *ui_arg, struct RingSet *keys, int sigcheck,
			struct RingSet *sigs)
	{
		FILE *fp = ((struct PgpTtyUI *) ui_arg)->fp;
		int numsigs;
		struct RingSet *dest;
		unsigned count = 0;
		int err;
		int sigcheckcount;
#if 0
union RingObject *key, *name;
size_t len;
struct RingIterator *iter;
int rc;
char const *namestring;
#endif
int trust_changed = 0;

/* Check sigs as required */

switch (sigcheck) {
case 1:
/* Only check signatures in sigs that are not
marked as having been checked. */
numsigs = ringPoolCheckCount (sigs, keys, 0);
if (numsigs > 0)
fprintf (fp, checking, numsigs);
sigcheckcount = 0;
	if ((err = ringPoolCheck (sigs, keys, 0, mainShowSigCheckProgress,
			(void *) &sigcheckcount)) != 0)
		fprintf (stderr, "Error %d checking signatures\n", err);
		if (sigcheckcount > 0)
			fprintf (stderr, "\n");
		break;
		case 2:
		/* Check all signatures as part of a full maintenance
		pass */
		numsigs = ringPoolCheckCount (keys, keys, 1);
		if (numsigs > 0)
		fprintf (fp, checking, numsigs);
		sigcheckcount = 0;
		if ((err = ringPoolCheck (keys, keys, 1, mainShowSigCheckProgress,
		(void *) &sigcheckcount)) != 0)
		fprintf (stderr, "Error %d checking signatures\n", err);
		if (sigcheckcount > 0)
			fprintf (stderr, "\n");
		break;
		default:
		fprintf (fp, "No signatures to check...\n");
		/* Don't check any sigs */
		}

		/* Loop around performing maintenance passes until no more
		interesting keys are returned. */

		do {
		dest = ringSetCreate (ringpool);
		if (!dest)
			return ringPoolError(ringpool)->error;
		fprintf (fp, "Computing validity of name/key bindings...\n");
		ringMnt (keys, dest, time ((time_t *) NULL));
#if 0
ringSetFreeze (dest);
if (pgpenvGetInt (((struct PgpTtyUI *) ui_arg)->env, PGPENV_BATCHMODE,
		NULL, NULL))
		count = 0; /* ignore interesting keys in batchmode */
		else
		ringSetCount (dest, &count, 1);
		if (count > 0) {
		iter = ringIterCreate (dest);
		if (!iter) {
			ringSetDestroy (dest);
			return ringPoolError(ringpool)->error;
		}

		/* Ask the user to define the trust for each key returned in dest.
			For the new trust model, we must locate the names with undefined
			trust.
			@@@ May want indication of why key is interesting in future,
			and switch based on the reason. */

		while (ringIterNextObject (iter, 1) > 0) {
		PgpTrustModel pgptrustmodel = pgpTrustModel(ringpool);
		key = ringIterCurrentObject (iter, 1);
		pgpAssert (key && ringObjectType (key) == RINGTYPE_KEY);
		if (pgptrustmodel == PGPTRUST0) {
			fprintf (fp, "Trust in the following key is undefined:\n");
			ringTtyShowKey (ui_arg, key, keys, 0);
			if (doKeyEditTrust (key, keys, 1, fp))
				trust_changed = 1;
			else
				/* So we don't ask again */
				ringKeySetTrust (keys, key, PGP_KEYTRUST_UNKNOWN);
		} else { /* new trust model */
			ringTtyShowKey (ui_arg, key, keys, 0);
			while ((rc = ringIterNextObject (iter, 2)) > 0) {
				name = ringIterCurrentObject (iter, 2);
				if (name && ringObjectType (name) == RINGTYPE_NAME) {
					if (ringNameConfidenceUndefined (keys, name)) {
						fprintf (fp,
"\nConfidence in the following name is undefined:\n");
						namestring = ringNameName (keys, name, &len);
						ringTtyPutString (namestring, len, len+2, fp, '"',
						                    '"');
						putc ('\n', fp);
						if (doKeyEditTrust (name, keys, 1, fp)) {
							trust_changed = 1;
						} else {
							/*
							* This is required to force 'undefined trust' to
							* 'no trust', so we don't ask again.
							*/
							ringNameSetConfidence (keys, name, 0);
												}
										}
								}
						}
				}
		ringIterDestroy (iter);
}
#endif
	ringSetDestroy (dest);
} while (count > 0 && trust_changed);
return 0;
}
	
/*
* Makes sure that the global <allkeys> is loaded,
* and returns an error code or 0 if successful.
* If <canFail> is 0, then an error will cause it to exit.
	*/
static int
loadAllKeys(struct PgpEnv *env, int canFail, int trusted_only)
{
	if (!allkeys) {
		int error = mainOpenKeyrings(env, ringpool, trusted_only,
					&allkeys);

		if (error) {
			fprintf(stderr,
				"mainOpenKeyrings failed (%d): %s\n",
				error, pgperrString (error));
			if (canFail)
				return error;
			else
				exitUsage(error);
		}
	}
	return 0;
}

/*
* Interface to loadAllKeys which makes sure <allkeys> will be reloaded.
* Sometimes we want to load only untrusted keyrings but <allkeys> may
* hold trusted ones.
	*/
static int
reloadAllKeys(struct PgpEnv *env, int canFail, int trusted_only)
{
	if (allkeys) {
		ringSetDestroy(allkeys);
		allkeys = 0;
	}
	return loadAllKeys(env, canFail, trusted_only);
}


/*
* Open key rings and return sets for pubring and secring.
	*/
static void
mainOpenPubSec(struct PgpEnv *env, char const **pub,
	struct RingSet **pubring, char const **sec,
	struct RingSet **secring, FILE *log)
{
	if (pub && pubring) {
		*pub = pgpenvGetString (env, PGPENV_PUBRING, NULL, NULL);

⌨️ 快捷键说明

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