📄 pgpk.c
字号:
/*
* pgpk.c -- PGP keyring manipulation program
*
* Copyright (C) 1996,1997 Pretty Good Privacy, Inc. All rights reserved.
*
* $Id: pgpk.c,v 1.13.2.12.2.13 1997/07/15 22:22:36 quark 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 "pgpEnv.h"
#include "pgpMem.h"
#include "pgpKeyDB.h"
#include "pgpOutput.h"
#include "pgpkUI.h"
#include "pgpUI.h"
#include "pgpInitApp.h"
#include "pgpExit.h"
#include "pgpUI.h"
#include "pgpOpt.h"
#include "pgpUserIO.h"
#include "pgpRndPool.h"
#include "pgpConf.h"
#include "pass.h"
#include "pgpkKeyGen.h"
#include "keyserver.h"
#include "url.h"
#include "pgpLicense.h"
#define KDBTYPE_KEY 1
#define KDBTYPE_USERID 2
#define KDBTYPE_CERT 3
#define MAXARGS 2
struct Flags {
char args[MAXARGS];
int argc;
char const *outfile;
char const *ringfile;
char const *signName;
PGPKey *signKey;
char opt;
byte doarmor;
char quit;
};
PGPKeySet *defaultset = NULL; /* All keys in default keyrings */
Boolean enableUI = TRUE;
#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;
}
ErrorOutput(TRUE, LEVEL_CRITICAL, "ARGS_INCOMPATABLE", flags->opt, opt);
}
/*
* A key printer for selectOneDBObj (above),
* which prints keys for a menu.
*/
static void
keyPrint(PGPKeyIter *iter, PgpOutputType OutputType)
{
SpecifiedOutputString(FALSE, OutputType, 0, "\n");
kdbTtyShowKey(OutputType, iter, defaultset, 0);
}
/*
* A name printer for selectOneDBObj (above),
* which prints keys for a menu.
*/
static void
namePrint(PGPKeyIter *iter, PgpOutputType OutputType)
{
char namestring[256];
size_t len = 256;
SpecifiedOutputString(FALSE, OutputType, 0, "\n");
pgpGetUserIDString (pgpKeyIterUserID (iter), kPGPUserIDPropName,
namestring, &len);
kdbTtyPutString (namestring, len, (unsigned) len, TRUE, OutputType, 0, 0);
SpecifiedOutputString(FALSE, OutputType, 0, "\n");
kdbTtyShowSigs (OutputType, iter, defaultset, 2);
}
/*
* A sig printer for selectOneDBObj (above),
* which prints keys for a menu.
*/
static void
sigPrint(PGPKeyIter *iter, PgpOutputType OutputType)
{
pgpAssert(defaultset);
SpecifiedOutputString(FALSE, OutputType, 0, "\n");
kdbTtyShowSig(OutputType, iter, defaultset, 1);
}
/* Print the deepest current object */
static void
objPrint(PGPKeyIter *iter, PgpOutputType OutputType)
{
PGPKeyIter *printiter = pgpCopyKeyIter (iter);
if (pgpKeyIterCert (printiter))
sigPrint (printiter, OutputType);
else if (pgpKeyIterUserID (printiter))
namePrint (printiter, OutputType);
else
keyPrint (printiter, OutputType);
pgpFreeKeyIter (printiter);
}
/*
* Searches <fullset> for keys matching the substrings on the
* command line.
* If <argc>==0 and <defAll>, uses the entire <fullset>.
* In either case, the *subset returned is a valid, newly created,
* keyset.
*
* Returns 1 if any keys were selected, else 0.
*/
static int
selectKeyArgs(int argc, char *argv[], PGPKeySet *fullset,
PGPKeySet **subset, int defAll, Boolean KeySetReadOnly)
{
PGPError AddKeysResult = PGPERR_OK;
int AnyKeys = 0;
if (argc <= 0 && defAll) {
*subset = pgpCopyKeySet (fullset);
} else {
if(!KeySetReadOnly) {
*subset = pgpFilterKeySetAuto(fullset, argv[0]);
}
else {
int i = 0;
PGPKeySet *SingleMatchSet;
/*Assign subset to a new keyset. We can't just use the result of
*pgpFilterKeySetAuto(), because it returns a read-only keyset
*(not like that's documented, or anything)
*/
*subset = pgpNewKeySet();
/*Loop through the command line arguments, adding each one to the
*resulting keyset.
*/
for(i = 0;
i < argc && *subset && AddKeysResult == PGPERR_OK;
++i) {
if((SingleMatchSet = pgpFilterKeySetAuto (fullset, argv[i]))) {
AddKeysResult = pgpAddKeys(*subset, SingleMatchSet);
pgpFreeKeySet(SingleMatchSet);
}
}
}
}
if((AddKeysResult == PGPERR_OK) &&
*subset &&
(pgpCountKeys(*subset) > 0)) {
AnyKeys = 1;
}
return (AnyKeys);
}
/*
* Select one object of type <selecttype> and return an iterator pointing
* to it. The iterator passed is replaced by a new one.
*
* <targettype> defines the requirements for the returned object. For example,
* if <selecttype> == key and <targettype> == sig, the selected key must
* have a signed userid attached to it.
*/
static int
selectOneDBObj(PGPKeyIter **iter,
int selecttype,
int targettype,
char *header)
{
PGPKeyIter *selectiter = *iter, *targetiter = NULL;
PGPKeyIter *iterList[50];
PGPKey *key = NULL;
PGPUserID *userid = NULL;
PGPCert *cert = NULL;
int maxObjs = sizeof(iterList) / sizeof(iterList[0]);
int numObjs = 0;
int notFirst = 0;
int result = 0;
long choice;
char *endNum, buf[32];
int i;
do {
result = 0;
switch (selecttype) {
case KDBTYPE_KEY:
key = pgpKeyIterNext (selectiter);
if(key) {
/* Do we need a name or a sig on the key? */
if (targettype == KDBTYPE_USERID ||
targettype == KDBTYPE_CERT) {
targetiter = pgpCopyKeyIter (selectiter);
do {
if((userid = pgpKeyIterNextUserID (targetiter)) &&
((targettype == KDBTYPE_USERID) ||
((targettype == KDBTYPE_CERT) &&
(cert = pgpKeyIterNextUIDCert(targetiter)))))
result = 1;
}while(userid && !result);
pgpFreeKeyIter (targetiter);
}
else
result = 1;
}
break;
case KDBTYPE_USERID:
if((userid = pgpKeyIterNextUserID (selectiter))) {
if (targettype == KDBTYPE_CERT) {
targetiter = pgpCopyKeyIter (selectiter);
cert = pgpKeyIterNextUIDCert (targetiter);
if (cert)
result = 1;
pgpFreeKeyIter (targetiter);
}
else
result = 1;
}
break;
case KDBTYPE_CERT:
cert = pgpKeyIterNextUIDCert (selectiter);
if (cert)
result = 1;
break;
}
if(result) {
/*Copy and store the iterator that points to the current object */
iterList[numObjs++] = pgpCopyKeyIter (selectiter);
if (notFirst) {
/*XXX Ambiguous match if we're in batch mode...*/
if (numObjs == 2) {
InteractionOutputString(TRUE, "%s\n 1) ", header);
objPrint(iterList[0], OUTPUT_INTERACTION);
}
InteractionOutputString(TRUE, "%2d) ", numObjs);
objPrint (selectiter, OUTPUT_INTERACTION);
}
else
notFirst = 1;
}
} while(result && (numObjs < maxObjs));
if (numObjs < maxObjs) {
if(numObjs < 1)
result = 0;
else {
if(numObjs == 1) {
objPrint(iterList[0], OUTPUT_INTERACTION);
/* *iter = iterList[0];*/
*iter = pgpCopyKeyIter (iterList[0]);
pgpFreeKeyIter(selectiter);
result = 1;
}
else {
result = 0;
while(!result) {
InteractionOutput(TRUE, "CHOOSE_ONE_ABOVE");
pgpTtyGetString(buf, sizeof(buf), TRUE);
choice = strtol(buf, &endNum, 10);
while (isspace (*endNum))
endNum++;
if (choice >= 1 && choice <= numObjs) {
*iter = pgpCopyKeyIter (iterList[choice - 1]);
pgpFreeKeyIter (selectiter);
result = numObjs;
}
else
InteractionOutput(TRUE, "INVALID_SELECTION");
}
}
}
}
else {
ErrorOutput(TRUE, LEVEL_CRITICAL, "TOO_MANY_MATCHES");
result = -1;
}
/* Free all the key iterators we copied */
for (i = 0; i < numObjs; i++)
pgpFreeKeyIter (iterList[i]);
return result;
}
#if 0
/*
* Select one object of type <selecttype> and return an iterator pointing
* to it. The iterator passed is replaced by a new one.
*
* <targettype> defines the requirements for the returned object. For example,
* if <selecttype> == key and <targettype> == sig, the selected key must
* have a signed userid attached to it.
*/
static int
selectOneDBObj(PGPKeyIter **iter, int selecttype,
int targettype, char const *header)
{
PGPKeyIter *selectiter = *iter, *targetiter = NULL;
PGPKeyIter *iterList[50];
PGPKey *key = NULL;
PGPUserID *userid = NULL;
PGPCert *cert = NULL;
int maxObjs = sizeof(iterList) / sizeof(iterList[0]);
int numObjs = 0;
int notFirst = 0;
int result = 0;
long choice;
char *endNum, buf[32];
int i;
for (;;) {
result = 0;
switch (selecttype) {
case KDBTYPE_KEY:
key = pgpKeyIterNext (selectiter);
if (!key)
break;
/* Do we need a name or a sig on the key? */
if (targettype == KDBTYPE_USERID || targettype == KDBTYPE_CERT) {
targetiter = pgpCopyKeyIter (selectiter);
for (;;) {
userid = pgpKeyIterNextUserID (targetiter);
if (userid && targettype == KDBTYPE_USERID) {
result = 1;
break;
}
else if (!userid)
break;
if (targettype == KDBTYPE_CERT) {
cert = pgpKeyIterNextUIDCert (targetiter);
if (cert) {
result = 1;
break;
}
}
}
pgpFreeKeyIter (targetiter);
}
else
result = 1;
break;
case KDBTYPE_USERID:
userid = pgpKeyIterNextUserID (selectiter);
if (!userid)
break;
if (targettype == KDBTYPE_CERT) {
targetiter = pgpCopyKeyIter (selectiter);
cert = pgpKeyIterNextUIDCert (targetiter);
if (cert)
result = 1;
pgpFreeKeyIter (targetiter);
}
else
result = 1;
break;
case KDBTYPE_CERT:
cert = pgpKeyIterNextUIDCert (selectiter);
if (cert)
result = 1;
break;
}
if (!result)
break;
if (numObjs >= maxObjs) {
ErrorOutput(TRUE, LEVEL_CRITICAL, "TOO_MANY_MATCHES");
goto destroyAndError;
}
/* Copy and store the iterator that points to the current object */
iterList[numObjs++] = pgpCopyKeyIter (selectiter);
if (notFirst) {
if (numObjs == 2) {
InteractionOutputString(TRUE, "%s\n 1) ", header);
objPrint (iterList[0], OUTPUT_INTERACTION);
}
InteractionOutputString(TRUE, "%2d) ", numObjs);
objPrint (selectiter, OUTPUT_INTERACTION);
}
else
notFirst = 1;
}
if (numObjs < 1)
return 0;
else if (numObjs == 1) {
objPrint (iterList[0], OUTPUT_INTERACTION);
*iter = iterList[0];
pgpFreeKeyIter (selectiter);
return numObjs;
}
InteractionOutput(TRUE, "CHOOSE_ONE_ABOVE");
pgpTtyGetString(buf, sizeof(buf), TRUE);
choice = strtol(buf, &endNum, 10);
while (isspace (*endNum))
endNum++;
if (*endNum || choice < 1 || choice > numObjs) {
InteractionOutput(TRUE, "INVALID_SELECTION");
goto destroyAndError;
}
*iter = pgpCopyKeyIter (iterList[choice - 1]);
pgpFreeKeyIter (selectiter);
result = numObjs;
goto destroyAndExit;
destroyAndError:
result = -1;
destroyAndExit:
/* Free all the key iterators we copied */
for (i = 0; i < numObjs; i++)
pgpFreeKeyIter (iterList[i]);
return result;
}
#endif
/*
* Service routine for selectDBObject, below. This one selects a user ID
* and optionally a signature from a RingSet composed of a single key
* and its descendants.
*
* <iter> points to a key object previously selected, and is updated to
* point to the child object.
*/
static int
selectChildObject(PGPKeyIter **iter, int selecttype, char const *prep)
{
int err = 0;
char header[255], *string = NULL;;
pgpAssert (selecttype == KDBTYPE_USERID || selecttype == KDBTYPE_CERT);
if (selecttype == KDBTYPE_USERID)
LoadString(&string, "PLEASE_SELECT_A_USER_ID");
else
LoadString(&string, "PLEASE_SELECT_A_USER_ID_WITH_SIG");
if(string) {
sprintf(header, string, prep);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -