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

📄 pgpk.c

📁 著名的加密软件的应用于电子邮件中
💻 C
📖 第 1 页 / 共 5 页
字号:

	/* Write out new results */
	if (needwritesec) {
		ringSetFreeze (secset);
		mainRingNewSet (sec, PGP_WRITETRUST_SEC, secset);
		secset = 0;	/* Don't destroy this */
		fprintf (stderr,
"Private keyring updated.\n");
	}
	if (needwritepub) {
		ringSetFreeze (pubset);
		mainRingNewSet (pub, PGP_WRITETRUST_PUB, pubset);
		pubset = 0;	/* Don't destroy this */
		fprintf (stderr,
"Public keyring updated.\n");
	}
cleanup:
	if (seckey)
		pgpSecKeyDestroy(seckey);
	if (subkey)
		pgpSecKeyDestroy(subkey);
	if (pubset)
		ringSetDestroy(pubset);
	if (secset)
		ringSetDestroy(secset);
	if (pubring)
		ringSetDestroy(pubring);
	if (secring)
		ringSetDestroy(secring);
	return err;
}


static int
doKeyEdit (struct PgpEnv *env, struct Flags *flags, int argc, char *argv[],
	struct PgpTtyUI *ui_arg)
{
	struct RingSet *pubring = NULL, *secring = NULL;
	union RingObject *obj;
	char const *pub, *sec;
	char const *prep = "to edit";
	int err;

	(void)flags;		/* make the compiler happy */

	mainOpenPubSec(env, &pub, &pubring, &sec, &secring, stderr);

	if (!pubring || !secring) {
		fprintf (stderr, "No keys in pubring or secring\n");
		return 0;
	}

	loadAllKeys(env, 1, 0);
	
	/* Select object to sign */
	err = selectRingObject(env, argc, argv, pub, pubring, RINGTYPE_KEY,
			prep, stderr, &obj);
	if (err <= 0)
		return err;

	fprintf (stderr, "\n");
	ringKeyPrint (stderr, pubring, obj, 1);
	fprintf (stderr, "\n");

	if (ringKeyIsSec(allkeys, obj))
		return doKeyEditSelf(env, flags, obj, pub, pubring,
				sec, secring, ui_arg);
	else
		return doKeyEditOthers(env, flags, obj, pub, pubring,
				sec, secring, ui_arg);
}


/*
* This handles key, user ID (with -ru), or signature (with -rs) removal.
*/
static int
doKeyRemove (struct PgpEnv *env, struct Flags *flags, int argc, char *argv[],
	struct PgpTtyUI *ui_arg)
{
	struct RingSet *pubring = NULL;
	struct RingSet *secring = NULL;
	struct RingSet *keyfile = NULL, *seckeyfile = NULL;
	union RingObject *obj;
	char const *pub, *sec;
	int numseckeys = 0;
	int err = 0;
	int removelevel;
	const char *prep = "to be removed";
	const char *typename;
	int removed = 0;

	/* Distinguish what we are to remove */
	if (flags->argc && strchr(flags->args, 's')) {
		removelevel = RINGTYPE_SIG; /* signature */
		typename = "signature";
	} else if (flags->argc && strchr(flags->args, 'u')) {
		removelevel = RINGTYPE_NAME; /* user id */
		typename = "user ID";
	} else {
		removelevel = RINGTYPE_KEY; /* key */
		typename = "key";
	}

	/* Open pub and sec key rings */
	mainOpenPubSec(env, &pub, &pubring, &sec, &secring, stderr);
	if (!pubring) {
		fprintf (stderr,
"No keys in pubring\n");
		goto cleanup;
	}
	loadAllKeys(env, 1, 0);

	/* Select object to remove */
	fprintf (stderr, "\n");
	err = selectRingObject(env, argc, argv, pub, pubring, removelevel,
			prep, stderr, &obj);
	if (err <= 0)
		goto cleanup;

	/* err holds number of possible objects at that level */
	if (removelevel == RINGTYPE_NAME && err == 1) {
		err = 0;
		fprintf (stderr,
"Selected key has only one user ID, can't be selected %s\n", prep);
		goto cleanup;
	}

	/* Confirm removal */
	fprintf(stderr,
"\nThe following %s has been selected %s:\n", typename, prep);
	objPrint(env, obj, stderr, NULL);

	/* See if key is on private ring too */
	numseckeys = secring ? ringSetIsMember(secring, obj) : 0;
	if (numseckeys) {
		fprintf(stderr,
"\nThis %s is also present in the private keyring.\n", typename);
		fprintf(stderr,
"Removing it will remove it from both the public and private keyrings.\n"\
"Do you want to remove it from both keyrings (y/N)? ");
	} else {
		fprintf (stderr,
"\nAre you sure you want this %s %s (y/N)? ", typename, prep);
	}
	if (!pgpTtyGetBool(0, stderr)) {
		fprintf (stderr,
"Removal cancelled.\n");
		err = 0;
		goto cleanup;
	}
	fprintf (stderr, "\n");

	/* Perform removal, but don't write back yet */
	keyfile = ringSetCreate (ringpool);
	if (!keyfile) {
		err = ringPoolError(ringpool)->error;
		goto cleanup;
	}
	err = ringSetAddSet(keyfile, pubring);
	if (err < 0)
		goto cleanup;
	err = ringSetRemObject(keyfile, obj);
	if (err < 0)
		goto cleanup;
	ringSetFreeze (keyfile);
	removed = 1;

	if (numseckeys) {
		/* Remove from private key ring, don't write back yet */
		seckeyfile = ringSetCreate (ringpool);
		if (!seckeyfile) {
			err = ringPoolError(ringpool)->error;
			goto cleanup;
		}
		err = ringSetAddSet(seckeyfile, secring);
		if (err < 0)
			goto cleanup;
		err = ringSetRemObject(seckeyfile, obj);
		if (err < 0)
			goto cleanup;
		ringSetFreeze (seckeyfile);
	}
	ringObjectRelease(obj);
	
	/* Write out results */
	mainRingNewSet (pub, PGP_WRITETRUST_PUB, keyfile);
	keyfile = NULL;		/* Don't destroy this */
	if (err < 0) {
		fprintf (stderr,
"Error - unable to update key file!\n");
		goto cleanup;
	}
	if (numseckeys) {
		mainRingNewSet (sec, PGP_WRITETRUST_SEC, seckeyfile);
		seckeyfile = NULL;	/* Don't destroy this */
		if (err < 0) {
			fprintf (stderr,
"Error - unable to update private key file!\n");
			goto cleanup;
		}
	}
	/* success */
	err = 0;

cleanup:
	if (seckeyfile)
		ringSetDestroy(seckeyfile);
	if (keyfile)
		ringSetDestroy(keyfile);
	if (pubring)
		ringSetDestroy(pubring);
	if (secring)
		ringSetDestroy(secring);

	/*  If no error and something was removed, do a maintenance pass.
	This causes the (new) public keyring to be reopened and re-read,
	but gives us the correct community of keys to be validated. */

	if (err == 0 && removed) {
		/* Close and write out current keyrings before reopening */
		ringSetDestroy(allkeys);
		allkeys = 0;
		mainCloseKeyrings(1 /*update*/, 1 /*newvers*/);
		
		reloadAllKeys (env, 0, 1);
		err = mainDoMaint ((void *) ui_arg, allkeys, 0, NULL);
		fprintf (stderr,
"This %s has now been removed from the public key ring.\n", typename);
		if (numseckeys) {
			fprintf (stderr,
"This %s has also been removed from the private key ring.\n", typename);
		}
	}
	return err;
}


/*
* Issue a signature on a userID.
*/
static int
doKeySign (struct PgpEnv *env, struct Flags *flags, int argc, char *argv[],
	struct PgpTtyUI *ui_arg)
{
	struct RingSet *pubring = NULL;
	struct RingSet *newpub = NULL;
	struct RingSet *tmpring;
	struct RingIterator *iter;
	struct PgpSigSpec *sigspec = NULL;
	struct PgpSecKey *secretKey = NULL;
	union RingObject *obj=NULL, *ringobj = NULL;
	char const *pub;
	int level;
	int err;
	const char *prep = "to be signed";
	byte keyid[8];
	byte pkalg;
	int sigtype = PGP_SIGTYPE_KEY_GENERIC;
	char const *myname = pgpenvGetString (env, PGPENV_MYNAME,
						NULL, NULL);
	(void)flags;

	/* Open pub key ring */
	mainOpenPubSec(env, &pub, &pubring, NULL, NULL, stderr);
	if (!pubring) {
		fprintf (stderr,
"No keys in pubring\n");
		return 0;
	}
	loadAllKeys(env, 1, 0);

	/* Find secret key, make sure it signs */
	ringobj = ringLatestSecret (allkeys, myname, time(NULL),
				PGP_PKUSE_SIGN);
	if (!ringobj) {
		fprintf (stderr,
"Cannot find private key suitable for signing: %s\n", myname);
		ringSetDestroy(pubring);
		return 0;
	}
	secretKey = ringSecSecKey (allkeys, ringobj, PGP_PKUSE_SIGN);
	if (!secretKey) {
		fprintf (stderr, "Cannot convert to private key\n");
		ringSetDestroy(pubring);
		return 0;
	}
	if (!secretKey->sign) {
		fprintf (stderr, "Private Key is not a signature key\n");
		ringSetDestroy(pubring);
		return 0;
	}
	/* Data to check for duplicate sigs below */
	memcpy(keyid, secretKey->keyID, sizeof(keyid));
	pkalg = secretKey->pkAlg;

	/* Select object to sign */
	err = selectRingObject(env, argc, argv, pub, pubring, RINGTYPE_NAME,
			prep, stderr, &obj);
	if (err <= 0)
		return err;

	/* Make sure it doesn't already have a sig on it from this key */
	iter = ringIterCreate(pubring);
	level = ringIterSeekTo(iter, obj);
	if (level < 0) {
		ringSetDestroy(pubring);
		return level;
	}
	++level;
	while (ringIterNextObject(iter, level) > 0) {
		byte sigid[8];
		byte sigpkalg;
		union RingObject *sig = ringIterCurrentObject(iter, level);
		pgpAssert(sig);
		if (ringObjectType(sig) != RINGTYPE_SIG)
			continue;
		ringSigID8(pubring, sig, &sigpkalg, sigid);
		if (sigpkalg==pkalg &&
		memcmp(sigid, keyid, sizeof(sigid))==0 &&
		ringSigType(pubring, sig) == sigtype) {
			/* Duplicate */
			fprintf (stderr,
"User ID is already signed by your private key\n");
			ringIterDestroy(iter);
			ringSetDestroy(pubring);
			return 0;
		}
	}
	ringIterDestroy(iter);

	/* Confirm signature */
	objPrint(env, obj, stderr, NULL);
	fprintf(stderr,
"\n\n"\
"READ CAREFULLY:  Based on your own direct first-hand knowledge, are\n"\
"you absolutely certain that you are prepared to solemnly certify that\n"\
"the above public key actually belongs to the user specified by the\n"\
"above user ID (y/N)? ");

	if (!pgpTtyGetBool(0, stderr)) {
		fprintf (stderr,
"Key sign operation cancelled.\n");
		ringSetDestroy(pubring);
		return 0;
	}

	ui_arg->ringset = allkeys;
	err = pgpTtyUnlockSeckey (ui_arg, ringobj, secretKey,
"\nYou need a pass phrase to unlock your private key.\n");
	ringObjectRelease (ringobj);
	if (err) {
		fprintf (stderr, "Cannot unlock private key\n");
		ringSetDestroy(pubring);
		return 0;
	}
	
	
	/* Actually do the signature */
	sigspec = pgpSigSpecCreate (env, secretKey, sigtype);
	if (!sigspec) {
		ringSetDestroy(pubring);
		return PGPERR_NOMEM;
	}

	newpub = ringSetCreate (ringpool);
	if (!newpub) {
		pgpSigSpecDestroy(sigspec);
		ringSetDestroy(pubring);
		return PGPERR_NOMEM;
	}
	ringSetAddSet (newpub, pubring);
	ringSetDestroy(pubring);
	pubring = NULL;

	if (!rng)
		rng = pgpRandomCreate ();

	err = ringSignObject (newpub, obj, sigspec, rng);
	pgpSigSpecDestroy(sigspec);
	ringSetFreeze(newpub);
	if (err < 0)
		return err;

	/* Do maintenance pass */
	fprintf (stderr, "\n");
	reloadAllKeys (env, 0, 1);
	tmpring = ringSetUnion(allkeys, newpub);
	ringSetDestroy(allkeys);
	allkeys = tmpring;
	err = mainDoMaint ((void *) ui_arg, allkeys, 1, allkeys);
	if (err < 0)
		return err;

	/* Write out results */
	mainRingNewSet (pub, PGP_WRITETRUST_PUB, newpub);
	newpub = NULL;		/* Don't destroy this */
	fprintf (stderr,
"Key signature certificate added.\n");

	return 0;
}

/*
* Return true if a key has been revoked.
*/
static int
mainKeyRevoked (struct RingSet const *set, union RingObject *obj)
{
	struct RingIterator *iter;
	byte keyid[8], keypkalg;
	int level;

	pgpAssert (ringObjectType(obj) == RINGTYPE_KEY);
	ringKeyID8(set, obj, &keypkalg, keyid);

	iter = ringIterCreate(set);
	level = ringIterSeekTo(iter, obj);
	if (level < 0) {
		ringIterDestroy(iter);
		return level;
	}
	++level;
	while (ringIterNextObject(iter, level) > 0) {
		byte sigid[8];
		byte sigpkalg;
		int sigtype;
		union RingObject *sig = ringIterCurrentObject(iter, level);
		pgpAssert(sig);
		if (ringObjectType(sig) != RINGTYPE_SIG)
			continue;
		ringSigID8(set, sig, &sigpkalg, sigid);
		if (memcmp(keyid,sigid,sizeof(keyid))!=0 ||
		sigpkalg != keypkalg)
			continue;
		sigtype = ringSigType(set, sig);
		if (sigtype == PGP_SIGTYPE_KEY_COMPROMISE) {
			ringIterDestroy(iter);
			return 1; /* yes, it is revoked */
		}
	}
	ringIterDestroy(iter);
	return 0;	 	/* no, it is not revoked */
}


/*
* Given a userID signature, return true if it has been revoked.
* @@@ Better to worry more about validity here?
*/
static int
mainSigRevoked (struct RingSet const *set, union RingObject *obj)
{
	struct RingIterator *iter;
	byte keyid[8], pkalg;
	int level;

	pgpAssert (ringObjectType(obj) == RINGTYPE_SIG);
	ringSigID8(set, obj, &pkalg, keyid);
	
	/* Prepare to iterate */
	iter = ringIterCreate(set);
	if (!iter)
		return PGPERR_NOMEM;
	level = ringIterSeekTo(iter, obj);
	if (level < 0) {
		ringIterDestroy(iter);
		return level;
	}

	/* Loop over all sigs on the name */
	ringIterRewind(iter, level);
	while ((level = ringIterNextObject (iter, level)) > 0) {
		union RingObject *sig = ringIterCurrentObject(iter, level);
		byte sigpkalg, sigid[8];
		pgpAssert(sig);
		if (ringObjectType(sig) != RINGTYPE_SIG)
			continue;
		ringSigID8(set, sig, &sigpkalg, sigid);
		if (sigpkalg==pkalg &&
		memcmp(sigid, keyid, sizeof(sigid))==0) {
			int type = ringSigType(set, sig);
			if (type == PGP_SIGTYPE_KEY_UID_REVOKE) {
				ringIterDestroy(iter);
				ringObjectRelease(sig);
				return 1; /* revocation found */
			}
		}
	}
	ringIterDestroy(iter);
	return 0;	 	/* no revocation found */
}

⌨️ 快捷键说明

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