📄 pgp.c
字号:
#endif
continue;
}
/* Determine whether this key is OK to use
for encryption */
if (ringTtyKeyOKToEncrypt (ringset,
ringobj)) {
prefAlgs = ringKeyFindSubpacket (ringobj, ringset,
SIGSUB_PREFERRED_ALGS,
0, &numPrefAlgs, NULL, NULL, NULL, NULL, &e);
if (prefAlgs == NULL && e != 0)
exitUsage(e);
AccumAlgVotes(&algVotes, prefAlgs, numPrefAlgs);
temp = ringKeyPubKey (ringset, ringobj,
PGP_PKUSE_ENCRYPT);
if (temp) {
temp->next = publicKey;
publicKey = temp;
}
}
}
bestAlg = ChooseAlgFromVotes(&algVotes);
CleanupAlgVotes(&algVotes);
if (bestAlg > 0)
{
pgpenvSetInt(env, PGPENV_CIPHER, bestAlg, PGPENV_PRI_FORCE);
}
else
{
ErrorOutput(TRUE,
LEVEL_CRITICAL,
"INCONSISTENT_RECIPIENT_SET");
exitCleanup (-1);
}
ringIterDestroy (ringiter);
ringSetDestroy (ringset);
if (e < 0)
exitUsage(e);
}
}
/*
* Don't proceed if couldn't encrypt for anyone, otherwise we send
* out plaintext.
*/
if (flags->numrecips && !publicKey) {
ErrorOutput(TRUE, LEVEL_CRITICAL, "NO_VALID_RECIPIENTS");
exitCleanup (-1);
}
tail = pgpEncryptPipelineCreate (tail,
env,
NULL,
rng_p,
convkeys,
publicKey,
sigspec,
literalParams,
flags->sepsig);
if (tail)
*pipehead = mod;
return tail;
}
/*
* Process the flags that were set. This builds the appropriate
* pipelines and processes the input files.
*/
static int
mainProcessFlags (struct PgpUICb *ui, struct UIArg *ui_arg,
struct PgpEnv *env, int argc, char *argv[],
struct Flags *flags)
{
struct PgpPipeline mod;
struct PgpPipeline **tail = NULL;
struct PgpEnv *tempenv = NULL;
int retval = PGPERR_OK, err;
int encrypting;
int armoring;
int filter = flags->filtermode; /* Assign to 0 or 2 */
if (flags->conventional && flags->numrecips) {
ErrorOutput(TRUE,
LEVEL_CRITICAL,
"CANNOT_COMBINE_CONVENTIONAL_AND_PK");
exitCleanup(PGPEXIT_ARGS);
}
if (!argc) {
filter++;
StatusOutput(TRUE, "USING_STDIN");
argc = -1;
}
memset (&mod, 0, sizeof (mod));
mod.name = "PGP Application";
rng = pgpRandomCreate ();
if (!rng)
exitUsage (PGPERR_NOMEM);
encrypting = (flags->numrecips || flags->conventional ||
(flags->doarmor && !flags->decrypt) ||
flags->sign); /* Encryption */
armoring = pgpenvGetInt (env, PGPENV_ARMOR, NULL, NULL);
/*
* Loop through input files.
*/
for (; argc; argc--, argv++) {
FILE *input;
struct PgpFileRead *context = NULL;
char name[PATH_MAX+1];
char *fn = NULL;
char const *outfile = NULL;
if (argc < 0) {
pgpAssert (filter & 1);
argc = 1;
input = stdin;
} else {
input = fopen (argv[0], "rb");
if (!input) {
ErrorOutput(TRUE,
LEVEL_CRITICAL,
"CANNOT_OPEN_INPUT_FILE",
argv[0]);
continue;
}
}
if (!tempenv)
tempenv = pgpenvCopy (env);
if (!tempenv) {
retval = PGPERR_NOMEM;
break;
}
context = pgpFileReadCreate (input, ((filter & 1) ? 0 : 1));
if (!context) {
fclose (input);
retval = PGPERR_NOMEM;
break;
}
if (flags->decrypt) {
if (flags->doarmor) {
/* Want to just strip off ascii armor */
ui_arg->arg.commits = 0;
} else {
/* Unwind just one layer of PGP */
ui_arg->arg.commits = 1;
}
} else {
/* Unwind all layers if decrypting */
ui_arg->arg.commits = -1;
}
if (encrypting) {
char const *in_name;
if (filter & 1)
in_name = "stdin";
else
in_name = argv[0];
if (flags->outfile)
outfile = flags->outfile;
else if (filter) {
outfile = NULL;
} else {
char *outname = argv[0];
#ifdef MSDOS
outname = fileNameContract(outname);
#endif
fn = fileNameExtend (outname,
(armoring ? ".asc" :
(flags->sign &&
flags->sepsig) ? ".sig"
: ".pgp"));
strncpy (name, fn, sizeof (name));
pgpMemFree (fn);
outfile = name;
}
tail = mainSetupPipeline (&head, tempenv,
flags, rng, in_name,
context, ui_arg);
} else { /* Decryption */
/* Choose an output name */
if (!ui_arg->arg.protect_name) {
/* Allow -o to override -f */
if (flags->outfile) {
ui_arg->arg.outname = flags->outfile;
} else if (filter) {
/* use stdout */
ui_arg->arg.protect_name = -1;
} else {
fn = fileNameContract (argv[0]);
strncpy (name, fn, sizeof (name));
pgpMemFree (fn);
ui_arg->arg.outname = name;
}
}
if (!head) {
tail = &head;
if (filter & 2) /* if -f is used */
tail = pgpBufferModCreate (
tail, &pgpFlexFifoDesc);
tail = pgpDecryptPipelineCreate (tail, tempenv,
NULL, ui,
ui_arg);
if (!head)
exitCleanup (PGPERR_NOMEM);
}
}
if (!tail) {
ErrorOutput(TRUE,
LEVEL_CRITICAL,
"CANNOT_SETUP_PROCESSING_PIPELINE");
exitCleanup (-1);
}
if (encrypting) {
if (!outfile) {
pgpAssert (filter);
if (!pgpFileWriteCreate (tail,
pgpFileWriteOpen
(stdout, NULL), 0)) {
head->teardown (head);
head = NULL;
continue;
}
} else {
if (!pgpArmorFileWriteCreate (tail, openFile,
(void *) env, outfile)) {
head->teardown (head);
head = NULL;
continue;
}
}
}
retval = pgpFileReadPump (context, head);
if (retval)
PGPErrCodeOutput(TRUE, LEVEL_CRITICAL, retval);
if (retval) {
err = pgpFileReadClose (context, head);
if (err) {
PGPErrCodeOutput(TRUE, LEVEL_CRITICAL, err);
}
}
pgpFileReadDestroy (context);
if (encrypting) {
if (!retval) {
retval = head->sizeAdvise (head, 0);
if (retval)
PGPErrCodeOutput(TRUE, LEVEL_CRITICAL, retval);
}
head->teardown (head);
head = NULL;
}
if (retval)
break;
}
if (!retval && head) {
retval = head->sizeAdvise (head, 0);
if (retval)
PGPErrCodeOutput(TRUE, LEVEL_CRITICAL, retval);
}
if (head)
head->teardown (head);
head = NULL;
if (rng)
pgpRandomDestroy (rng);
rng = NULL;
if (tempenv)
pgpenvDestroy (tempenv);
tempenv = NULL;
return retval;
}
/* Clean up allocated space (like the pipeline and the rng) on exit */
static void
mainExit (void)
{
if (head)
head->teardown (head);
head = NULL;
if (rng)
pgpRandomDestroy (rng);
rng = NULL;
if (secretKey)
pgpSecKeyDestroy (secretKey);
secretKey = NULL;
while (publicKey) {
struct PgpPubKey *temp = publicKey->next;
pgpPubKeyDestroy (publicKey);
publicKey = temp;
}
if (ringpool)
ringPoolDestroy (ringpool);
ringpool = NULL;
if (passcache)
pgpPassCacheDestroy (passcache);
passcache = NULL;
memset (phrase, 0, sizeof (phrase));
FreeLanguageStrings();
}
int
appMain (int argc, char *argv[])
{
struct PgpUICb ui;
struct UIArg ui_arg;
struct Flags flags;
struct PgpEnv *env;
struct RingSet *tset;
char const *p;
int retval, prog_code = 0;
PGPInvokedType invoked_type;
/* Setup my exit function to clean myself up */
atexit (mainExit);
/* Setup the UI callback functions */
ui.message = pgpTtyMessage;
ui.doCommit = pgpTtyDoCommit;
ui.newOutput = pgpTtyNewOutput;
ui.needInput = pgpTtyNeedInput;
ui.sigVerify = pgpTtySigVerify;
ui.eskDecrypt = pgpTtyEskDecrypt;
ui.annotate = NULL;
/* Setup the TTY UI argument */
ui_arg.arg.verbose = 1;
ui_arg.arg.fp = stderr;
ui_arg.arg.ringset = NULL;
ui_arg.arg.showpass = 0;
ui_arg.arg.commits = -1;
ui_arg.arg.addKeys = mainAddKeys;
ui_arg.arg.protect_name = 0;
retval = pgpInitApp (&env, &argc, &ui, &ui_arg, prog_code, 0);
if (retval) {
/*XXX Is this message strictly neccessary?*/
fprintf (stderr, "pgpInitApp failed: %d\n", retval);
goto error;
}
/* Now initialize the values that need initialization */
ui_arg.arg.env = env;
ui_arg.arg.passcache = passcache = pgpPassCacheCreate (env);
ui_arg.arg.verbose = pgpenvGetInt(env, PGPENV_VERBOSE, NULL, NULL);
/* Check the exiration date on the application */
exitExpiryCheck (env);
#if defined(UNIX) || defined(VMS)
umask(077); /* Make files default to private */
#endif
/* Grab the pass phrase from the PGPPASS Env Var */
p = getenv ("PGPPASS");
if (p)
pgpPassCacheAdd (passcache, p, strlen (p));
/* XXX add PGPPASSFD here? */
memset (&flags, 0, sizeof (flags));
/* XXX This is never freed */
flags.recips = (char **)malloc (argc * sizeof (*(flags.recips)));
/* Initialize the application from config files, etc. */
invoked_type = getInvokedType(argv[0]);
switch(invoked_type) {
case PGPencrypt:
prog_code = EXIT_PROG_PGPE;
break;
case PGPsign:
prog_code = EXIT_PROG_PGPS;
break;
case PGPverify:
prog_code = EXIT_PROG_PGPV;
break;
case PGPold:
prog_code = EXIT_PROG_PGPO;
break;
case PGPkeys:
/* XXX This shouldn't call exitArgError*/
ErrorOutput(TRUE, LEVEL_CRITICAL, "PGPK_IS_SEPERATE");
exitCleanup(PGPEXIT_ARGS);
/*NOT EXECUTED*/
break;
case PGPraw:
exitInvokedRaw();
/*NOT EXECUTED*/
break;
default:
/* XXX This shouldn't call exitArgError*/
ErrorOutput(TRUE, LEVEL_CRITICAL, "UNKNOWN_SYMLINK");
exitCleanup(PGPEXIT_ARGS);
/*NOT EXECUTED*/
break;
}
SetProgramName(prog_code);
/* Now, read the argument list */
switch(invoked_type) {
case PGPencrypt:
mainParseEncryptArgs(&ui, &ui_arg, env, &argc, argv, &flags);
break;
case PGPsign:
mainParseSignArgs(&ui, &ui_arg, env, &argc, argv, &flags);
break;
case PGPverify:
mainParseVerifyArgs(&ui, &ui_arg, env, &argc, argv, &flags);
break;
case PGPold:
/*XXX this probably needs to be a seperate exe, but I'm not
*100% sure what to do about this, now. -BAT
*/
mainParse262Args(&ui, &ui_arg, env, &argc, argv, &flags);
break;
case Unknown:
case PGPraw:
case PGPkeys:
/*GCC's overly zealous preparser warns us of these, even though*/
/*we can't get here...*/
break;
}
ui_arg.arg.showpass = pgpenvGetInt (env, PGPENV_SHOWPASS, NULL, NULL);
ui_arg.arg.moreflag = flags.moreflag;
ui_arg.arg.pager = getenv ("PAGER");
SetHeaders(pgpenvGetInt(env, PGPENV_HEADERS, NULL, NULL));
if (!ringpool)
ringpool = ringPoolCreate(env);
if (!ringpool) {
retval = PGPERR_NOMEM;
goto error;
}
retval = mainOpenKeyrings (env, ringpool, 0, &tset);
ui_arg.arg.ringset = tset;
if (retval)
goto error;
/* Now process the flags */
retval = mainProcessFlags (&ui, &ui_arg, env, argc, argv, &flags);
exitCleanup (retval);
error:
return (retval);
}
static PGPInvokedType getInvokedType(char *Argv0)
{
char *p = NULL;
PGPInvokedType invoked_type = Unknown;
/*First of all, strip off any leading path info. We don't care WHERE we
*are, just WHAT we are:
*/
invoked_type = PGPencrypt;
/*Thanks to Chuck Bertsch, who pointed out that I'd written this wrong
*and that we should just look at the last character to see what we
*are, which enables you to call it pgp50e, for example.
*/
if((p = pgpFileNameTail(Argv0))) {
p += strlen(p) - 1;
switch(tolower(*p)) {
case 'e':
invoked_type = PGPencrypt;
break;
case 's':
invoked_type = PGPsign;
break;
case 'v':
invoked_type = PGPverify;
break;
case 'o':
invoked_type = PGPold;
break;
case 'k':
/*Huh? They ran us as keys!*/
invoked_type = PGPkeys;
break;
case 'p':
invoked_type = PGPraw;
break;
default:
invoked_type = Unknown;
}
}
return(invoked_type);
}
static void exitInvokedRaw(void) {
ErrorOutput(TRUE, LEVEL_CRITICAL, "DIFFERENT_EXES");
exitCleanup(PGPEXIT_ARGS);
}
/*
* Local Variables:
* tab-width: 4
* End:
* vi: ts=4 sw=4
* vim: si
*/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -