Annotation of pgp/src/pgp.c, revision 1.1.1.4

1.1.1.3   root        1: #undef TEMP_VERSION    /* if defined, temporary experimental version of PGP */
                      2: /*     pgp.c -- main module for PGP.
                      3:        PGP: Pretty Good(tm) Privacy - public key cryptography for the masses.
                      4: 
                      5:        Synopsis:  PGP uses public-key encryption to protect E-mail. 
                      6:        Communicate securely with people you've never met, with no secure
                      7:        channels needed for prior exchange of keys.  PGP is well featured and
                      8:        fast, with sophisticated key management, digital signatures, data
                      9:        compression, and good ergonomic design.
                     10: 
                     11:        The original PGP version 1.0 was written by Philip Zimmermann, of
                     12:        Phil's Pretty Good(tm) Software.  Many parts of later versions of 
                     13:        PGP were developed by an international collaborative effort, 
                     14:        involving a number of contributors, including major efforts by:
                     15:                Branko Lankester <[email protected]> 
                     16:                Hal Finney <[email protected]>
                     17:                Peter Gutmann <[email protected]>
                     18:        Other contributors who ported or translated or otherwise helped include:
                     19:                Jean-loup Gailly in France
                     20:                Hugh Kennedy in Germany
                     21:                Lutz Frank in Germany
                     22:                Cor Bosman in The Netherlands
                     23:                Felipe Rodriquez Svensson in The Netherlands
                     24:                Armando Ramos in Spain
                     25:                Miguel Angel Gallardo Ortiz in Spain
                     26:                Harry Bush and Maris Gabalins in Latvia
                     27:                Zygimantas Cepaitis in Lithuania
                     28:                Alexander Smishlajev
                     29:                Peter Suchkow and Andrew Chernov in Russia
                     30:                David Vincenzetti in Italy
                     31:                ...and others.
                     32: 
                     33:        Note that while many PGP source modules bear the copyright notice of
                     34:        Philip Zimmermann, some of them may have been revised or in some
                     35:        cases entirely written by other members of the PGP development team,
                     36:        who often failed to put their names in their code.
                     37: 
                     38:        Revisions:
                     39:                Version 1.0 - 5 Jun 91
                     40:                Version 1.4 - 19 Jan 92
                     41:                Version 1.5 - 12 Feb 92
                     42:                Version 1.6 - 24 Feb 92
                     43:                Version 1.7 - 29 Mar 92
                     44:                Version 1.8 - 23 May 92
                     45:                Version 2.0 - 2 Sep 92
                     46:                Version 2.1 - 6 Dec 92
1.1.1.4 ! root       47:                Version 2.2 - 6 Mar 92
1.1.1.3   root       48: 
1.1.1.4 ! root       49:        (c) Copyright 1990-1993 by Philip Zimmermann.  All rights reserved.
1.1.1.3   root       50:        The author assumes no liability for damages resulting from the use
                     51:        of this software, even if the damage results from defects in this
                     52:        software.  No warranty is expressed or implied.
                     53: 
                     54:        All the source code Philip Zimmermann wrote for PGP is available for
                     55:        free under the "Copyleft" General Public License from the Free
                     56:        Software Foundation.  A copy of that license agreement is included in
                     57:        the source release package of PGP.  Code developed by others for PGP
                     58:        is also freely available.  Other code that has been incorporated into
                     59:        PGP from other sources was either originally published in the public
                     60:        domain or was used with permission from the various authors.  See the
                     61:        PGP User's Guide for more complete information about licensing,
                     62:        patent restrictions on certain algorithms, trademarks, copyrights,
                     63:        and export controls.  
                     64: 
                     65:        Philip Zimmermann may be reached at:
                     66:                Boulder Software Engineering
                     67:                3021 Eleventh Street
                     68:                Boulder, Colorado 80304  USA
                     69:                (303) 541-0140  (voice or FAX)
                     70:                email:  [email protected]
                     71: 
                     72: 
                     73:        PGP will run on MSDOS, Sun Unix, VAX/VMS, Ultrix, Atari ST, 
                     74:        Commodore Amiga, and OS/2.  Note:  Don't try to do anything with 
                     75:        this source code without looking at the PGP User's Guide.
                     76: 
                     77:        PGP combines the convenience of the Rivest-Shamir-Adleman (RSA)
                     78:        public key cryptosystem with the speed of fast conventional
                     79:        cryptographic algorithms, fast message digest algorithms, data
                     80:        compression, and sophisticated key management.  And PGP performs 
                     81:        the RSA functions faster than most other software implementations.  
                     82:        PGP is RSA public key cryptography for the masses.
                     83: 
                     84:        Uses RSA Data Security, Inc. MD5 Message Digest Algorithm
                     85:        as a hash for signatures.  Uses the ZIP algorithm for compression.
                     86:        Uses the ETH IPES/IDEA algorithm for conventional encryption.
                     87: 
                     88:        PGP generally zeroes its used stack and memory areas before exiting.
                     89:        This avoids leaving sensitive information in RAM where other users
                     90:        could find it later.  The RSA library and keygen routines also
                     91:        sanitize their own stack areas.  This stack sanitizing has not been
                     92:        checked out under all the error exit conditions, when routines exit
                     93:        abnormally.  Also, we must find a way to clear the C I/O library
                     94:        file buffers, the disk buffers, and and cache buffers.
                     95: 
                     96:        If you modify this code, PLEASE preserve the style of indentation
                     97:        used for {begin...end} blocks.  It drives me bats to have to deal
                     98:        with more than one style in the same program.
                     99: 
                    100:        Modified: 12-Nov-92 HAJK
                    101:        Add FDL stuff for VAX/VMS local mode. 
                    102: */
                    103: 
                    104: 
                    105: #include <ctype.h>
                    106: #ifndef AMIGA
                    107: #include <signal.h>
                    108: #endif
                    109: #include <stdio.h>
                    110: #include <stdlib.h>
                    111: #include <string.h>
1.1.1.4 ! root      112: #include "system.h"
1.1.1.3   root      113: #include "mpilib.h"
                    114: #include "random.h"
                    115: #include "crypto.h"
                    116: #include "fileio.h"
                    117: #include "keymgmt.h"
                    118: #include "language.h"
                    119: #include "pgp.h"
1.1.1.4 ! root      120: #include "exitpgp.h"
        !           121: #include "charset.h"
        !           122: #include "getopt.h"
        !           123: #include "config.h"
        !           124: #include "keymaint.h"
        !           125: #include "keyadd.h"
1.1.1.3   root      126: #ifdef  M_XENIX
                    127: char *strstr();
                    128: long time();
                    129: #endif
                    130: 
                    131: #ifdef MSDOS
                    132: #ifdef __ZTC__ /* Extend stack for Zortech C */
1.1.1.4 ! root      133: unsigned _stack_ = 24*1024;
1.1.1.3   root      134: #endif
                    135: #ifdef __TURBOC__
1.1.1.4 ! root      136: unsigned _stklen = 24*1024;
1.1.1.3   root      137: #endif
                    138: #endif
                    139: #define        STACK_WIPE      4096
                    140: 
                    141: /* Global filenames and system-wide file extensions... */
1.1.1.4 ! root      142: char rel_version[] = "2.2";    /* release version */
        !           143: static char rel_date[] = "6 Mar 93";   /* release date */
1.1.1.3   root      144: char PGP_EXTENSION[] = ".pgp";
                    145: char ASC_EXTENSION[] = ".asc";
                    146: char SIG_EXTENSION[] = ".sig";
                    147: char BAK_EXTENSION[] = ".bak";
1.1.1.4 ! root      148: static char HLP_EXTENSION[] = ".hlp";
1.1.1.3   root      149: char CONSOLE_FILENAME[] = "_CONSOLE";
1.1.1.4 ! root      150: static char HELP_FILENAME[] = "pgp.hlp";
1.1.1.3   root      151: 
                    152: /* These files use the environmental variable PGPPATH as a default path: */
1.1.1.4 ! root      153: static char CONFIG_FILENAME[] = "config.txt";
1.1.1.3   root      154: char PUBLIC_KEYRING_FILENAME[32] = "pubring.pgp";
                    155: char SECRET_KEYRING_FILENAME[32] = "secring.pgp";
                    156: char RANDSEED_FILENAME[32] = "randseed.bin";
                    157: 
                    158: /* Flags which are global across the driver code files */
                    159: boolean verbose = FALSE;       /* -l option: display maximum information */
                    160: FILE   *pgpout;                        /* Place for routine messages */
                    161: 
1.1.1.4 ! root      162: static void usage(void);
        !           163: static void key_usage(void);
        !           164: static void arg_error(void);
        !           165: static void initsigs(void);
        !           166: static int do_keyopt(char);
        !           167: static int do_decrypt(char *);
1.1.1.3   root      168: static void do_armorfile(char *);
                    169: 
                    170: 
                    171: /*     Various compression signatures: PKZIP, Zoo, GIF, Arj, and HPACK.  
                    172:        Lha(rc) is handled specially in the code; it is missing from the 
                    173:        compressSig structure intentionally.  If more formats are added, 
                    174:        put them before lharc to keep the code consistent. 
                    175: */
1.1.1.4 ! root      176: static char *compressSig[] =  { "PK\03\04", "ZOO ", "GIF8", "\352\140",
        !           177:        "HPAK", "\037\213", "\037\235", "\032\013", "\032HP%"
        !           178:        /* lharc is special, must be last */ };
        !           179: static char *compressName[] = { "PKZIP",   "Zoo",  "GIF",  "Arj",
        !           180:        "Hpack", "gzip", "compressed", "PAK", "Hyper",
        !           181:        "LHarc" };
        !           182: static char *compressExt[] =  { ".zip",  ".zoo",  ".gif",  ".arj",
        !           183:        ".hpk", ".z", ".Z", ".pak", ".hyp",
        !           184:        ".lzh" };
        !           185: 
        !           186: /* "\032\0??", "ARC", ".arc" */
1.1.1.3   root      187: 
                    188: int compressSignature(byte *header)
                    189: /* Returns file signature type from a number of popular compression formats
                    190:    or -1 if no match */
                    191: {      int i;
                    192: 
                    193:        for (i=0; i<sizeof(compressSig)/sizeof(*compressSig); i++)
                    194:                if (!strncmp((char *)header, compressSig[i], strlen(compressSig[i])))
                    195:                        return(i);
                    196:        /* Special check for lharc files */
                    197:        if (header[2]=='-' && header[3]=='l' && (header[4]=='z'||header[4]=='h') &&
                    198:                header[6]=='-')
                    199:                return(i);
                    200:        return(-1);
                    201: }      /* compressSignature */
                    202: 
                    203: 
1.1.1.4 ! root      204: static boolean file_compressible(char *filename)
1.1.1.3   root      205: {      /* returns TRUE iff file is likely to be compressible */
                    206:        byte header[8];
                    207:        get_header_info_from_file( filename, header, 8 );
                    208:        if (compressSignature( header ) >= 0)
                    209:                return (FALSE); /* probably not compressible */
                    210:        return (TRUE);  /* possibly compressible */
                    211: }      /* compressible */
                    212: 
                    213: 
                    214: /* Possible error exit codes - not all of these are used.  Note that we
                    215:    don't use the ANSI EXIT_SUCCESS and EXIT_FAILURE.  To make things
                    216:    easier for compilers which don't support enum we use #defines */
                    217: 
                    218: #define EXIT_OK                                        0
                    219: #define INVALID_FILE_ERROR             1
                    220: #define FILE_NOT_FOUND_ERROR   2
                    221: #define UNKNOWN_FILE_ERROR             3
                    222: #define NO_BATCH                               4
                    223: #define BAD_ARG_ERROR                  5
                    224: #define INTERRUPT                              6
                    225: #define OUT_OF_MEM                             7
                    226: 
                    227: /* Keyring errors: Base value = 10 */
                    228: #define KEYGEN_ERROR                   10
                    229: #define NONEXIST_KEY_ERROR             11
                    230: #define KEYRING_ADD_ERROR              12
                    231: #define KEYRING_EXTRACT_ERROR  13
                    232: #define KEYRING_EDIT_ERROR             14
                    233: #define KEYRING_VIEW_ERROR             15
                    234: #define KEYRING_REMOVE_ERROR   16
                    235: #define KEYRING_CHECK_ERROR            17
                    236: #define KEY_SIGNATURE_ERROR            18
                    237: #define KEYSIG_REMOVE_ERROR            19
                    238: 
                    239: /* Encode errors: Base value = 20 */
                    240: #define SIGNATURE_ERROR                        20
                    241: #define RSA_ENCR_ERROR                 21
                    242: #define ENCR_ERROR                             22
                    243: #define COMPRESS_ERROR                 23
                    244: 
                    245: /* Decode errors: Base value = 30 */
                    246: #define SIGNATURE_CHECK_ERROR  30
                    247: #define RSA_DECR_ERROR                 31
                    248: #define DECR_ERROR                             32
                    249: #define DECOMPRESS_ERROR               33
                    250: 
                    251: 
                    252: #ifdef SIGINT
                    253: void breakHandler(int sig)
                    254: /* This function is called if a BREAK signal is sent to the program.  In this
                    255:    case we zap the temporary files.
                    256: */
                    257: {
                    258: #ifdef UNIX
                    259:        if (sig == SIGPIPE)
                    260:        {       signal(SIGPIPE, SIG_IGN);
                    261:                exitPGP(INTERRUPT);
                    262:        }
                    263:        if (sig != SIGINT)
                    264:                fprintf(stderr, "\nreceived signal %d\n", sig);
                    265:        else
                    266: #endif
                    267:                fprintf(pgpout,PSTR("\nStopped at user request\n"));
                    268:        exitPGP(INTERRUPT);
                    269: }
                    270: #endif
                    271: 
                    272: 
1.1.1.4 ! root      273: static void clearscreen(void)
1.1.1.3   root      274: {      /* Clears screen and homes the cursor. */
                    275:        fprintf(pgpout,"\n\033[0;0H\033[J\r           \r");     /* ANSI sequence. */
                    276:        fflush(pgpout);
                    277: }
                    278: 
1.1.1.4 ! root      279: static void signon_msg(void)
1.1.1.3   root      280: {      /*      We had to process the config file first to possibly select the 
                    281:                foreign language to translate the sign-on line that follows... */
                    282:        word32 tstamp;
                    283:                /* display message only once to allow calling multiple times */
                    284:        static boolean printed = FALSE;
                    285: 
1.1.1.4 ! root      286:        if (quietmode || printed)
1.1.1.3   root      287:                return;
                    288:        printed = TRUE;
                    289:        fprintf(stderr,PSTR("Pretty Good Privacy %s - Public-key encryption for the masses.\n"),
                    290:                rel_version);
                    291: #ifdef TEMP_VERSION
                    292:        fprintf(stderr, "Internal development version only - not for general release.\n");
                    293: #endif
1.1.1.4 ! root      294:        fprintf(stderr, PSTR("(c) 1990-1993 Philip Zimmermann, Phil's Pretty Good Software. %s\n"),
1.1.1.3   root      295:                rel_date);
                    296: 
                    297:        get_timestamp((byte *)&tstamp); /* timestamp points to tstamp */
                    298:        fprintf(pgpout,"Date: %s\n",ctdate(&tstamp));
                    299: }
                    300: 
                    301: 
                    302: #ifdef TEMP_VERSION    /* temporary experimental version of PGP */
                    303: #include <time.h>
                    304: #define CREATION_DATE ((unsigned long) 0x2a6f17dcL)     
                    305:        /* CREATION_DATE is Thu Jul 23 14:34:36 1992 */ 
                    306: #define LIFESPAN       ((unsigned long) 30L * (unsigned long) 86400L)
                    307:        /* LIFESPAN is 30 days */
                    308: void check_expiration_date(void)
                    309: {      /* If this is an experimental version of PGP, cut its life short */
                    310:        word32 t;
                    311:        t = time(NULL);
                    312:        if (t > (CREATION_DATE + LIFESPAN))
                    313:        {       fprintf(stderr,"\n\007This experimental version of PGP has expired.\n");
                    314:                exit(-1);       /* error exit */
                    315:        }
                    316: }      /* check_expiration_date */
                    317: #else  /* no expiration date */
                    318: #define check_expiration_date() /* null statement */
                    319: #endif /* TEMP_VERSION */
                    320: 
                    321: 
                    322: 
                    323: /* -f means act as a unix-style filter */
                    324: /* -i means internalize extended file attribute information, only supported
1.1.1.4 ! root      325:  *          between like (or very compatible) operating systems. */
1.1.1.3   root      326: /* -l means show longer more descriptive diagnostic messages */
                    327: /* -m means display plaintext output on screen, like unix "more" */
                    328: /* -d means decrypt only, leaving inner signature wrapping intact */
                    329: /* -t means treat as pure text and convert to canonical text format */
                    330: 
                    331: /* Used by getopt function... */
                    332: #define OPTIONS "abcdefghiklmo:prstu:vwxz:ABCDEFGHIKLMO:PRSTU:VWX?"
                    333: extern int optind;
                    334: extern char *optarg;
                    335: 
                    336: boolean emit_radix_64 = FALSE;         /* set by config file */
1.1.1.4 ! root      337: static boolean sign_flag = FALSE;
1.1.1.3   root      338: boolean moreflag = FALSE;
                    339: boolean filter_mode = FALSE;
1.1.1.4 ! root      340: static boolean preserve_filename = FALSE;
        !           341: static boolean decrypt_only_flag = FALSE;
        !           342: static boolean de_armor_only = FALSE;
        !           343: static boolean strip_sig_flag = FALSE;
1.1.1.3   root      344: boolean clear_signatures = FALSE;
1.1.1.4 ! root      345: boolean strip_spaces;
        !           346: static boolean c_flag = FALSE;
        !           347: boolean encrypt_to_self = FALSE; /* should I encrypt messages to myself? */
        !           348: boolean batchmode = FALSE;     /* if TRUE: don't ask questions */
        !           349: boolean quietmode = FALSE;
        !           350: boolean force_flag = FALSE;    /* overwrite existing file without asking */
1.1.1.3   root      351: #ifdef VMS     /* kludge for those stupid VMS variable-length text records */
1.1.1.4 ! root      352: char literal_mode = MODE_TEXT; /* MODE_TEXT or MODE_BINARY for literal packet */
1.1.1.3   root      353: #else  /* not VMS */
1.1.1.4 ! root      354: char literal_mode = MODE_BINARY;       /* MODE_TEXT or MODE_BINARY for literal packet */
1.1.1.3   root      355: #endif /* not VMS */
                    356: /* my_name is substring of default userid for secret key to make signatures */
                    357: char my_name[256] = "\0"; /* null my_name means take first userid in ring */
                    358: boolean keepctx = FALSE;       /* TRUE means keep .ctx file on decrypt */
1.1.1.4 ! root      359: /* Ask for each key separately if it should be added to the keyring */
        !           360: boolean interactive_add = FALSE;
1.1.1.3   root      361: boolean compress_enabled = TRUE;       /* attempt compression before encryption */
                    362: long timeshift = 0L;   /* seconds from GMT timezone */
1.1.1.4 ! root      363: static boolean attempt_compression; /* attempt compression before encryption */
        !           364: static char *outputfile = NULL;
        !           365: static int errorLvl = EXIT_OK;
        !           366: static char mcguffin[256]; /* userid search tag */
        !           367: boolean signature_checked = FALSE;
1.1.1.3   root      368: char plainfile[MAX_PATH];
                    369: int myArgc = 2;
1.1.1.4 ! root      370: char **myArgv;
1.1.1.3   root      371: char password[256] = "";
                    372: 
                    373: int main(int argc, char *argv[])
                    374: {
                    375:        int status, opt;
                    376:        char *inputfile = NULL;
1.1.1.4 ! root      377:        char **recipient = NULL;
        !           378:        char **mcguffins;
1.1.1.3   root      379:        char *workfile, *tempf;
                    380:        boolean nestflag = FALSE;
                    381:        boolean decrypt_mode = FALSE;
                    382:        boolean wipeflag = FALSE;
                    383:        boolean armor_flag = FALSE;             /* -a option */
                    384:        boolean separate_signature = FALSE;
                    385:        boolean keyflag = FALSE;
                    386:        boolean encrypt_flag = FALSE;
                    387:        boolean conventional_flag = FALSE;
                    388:        char *clearfile = NULL;
                    389:        char *literal_file = NULL;
                    390:        char literal_file_name[MAX_PATH];
                    391:        char cipherfile[MAX_PATH];
                    392:        char keychar = '\0';
                    393:     char *p;
                    394:        byte ctb;
                    395: 
                    396:        /* Initial messages to stderr */
                    397:        pgpout = stderr;
                    398: 
                    399: #ifdef DEBUG1
                    400:        verbose = TRUE;
                    401: #endif
                    402: 
                    403:        if ((p = getenv("PGPPASS")) != NULL)
                    404:                strcpy(password, p);
1.1.1.4 ! root      405: 
        !           406:        /* The -z "password" option should be used instead of PGPPASS if
        !           407:         * the environment can be displayed with the ps command (eg. BSD).
        !           408:         * If the system does not allow overwriting of the command line
        !           409:         * argument list but if it has a "hidden" environment, PGPPASS
        !           410:         * should be used.
        !           411:         */
1.1.1.3   root      412:        for (opt = 1; opt < argc; ++opt)
                    413:        {       if (strcmp(argv[opt], "-z") == 0 && ++opt < argc)
                    414:                {       strcpy(password, argv[opt]);
                    415:                        for (p = argv[opt]; *p; ++p)
                    416:                                *p = ' ';
                    417:                }
                    418:        }
1.1.1.4 ! root      419:        /*
        !           420:         * If PGPPASSFD is set in the environment try to read the password
        !           421:         * from this file descriptor.  If you set PGPPASSFD to 0 pgp will
        !           422:         * use the first line read from stdin as password.
        !           423:         */
        !           424:        if (*password == '\0' && (p = getenv("PGPPASSFD")) != NULL)
        !           425:        {
        !           426:                int passfd;
        !           427:                if (*p && (passfd = atoi(p)) >= 0)
        !           428:                {
        !           429:                        p = password;
        !           430:                        while (read(passfd, p, 1) == 1 && *p != '\n')
        !           431:                                ++p;
        !           432:                        *p = '\0';
        !           433:                }
        !           434:        }
1.1.1.3   root      435: 
                    436:        /* Process the config file first.  Any command-line arguments will
                    437:           override the config file settings */
                    438:        buildfilename( mcguffin, CONFIG_FILENAME );
                    439:        if ( processConfigFile( mcguffin ) < 0 )
                    440:                exit(BAD_ARG_ERROR);
                    441:        init_charset();
                    442: 
                    443: #ifdef MSDOS   /* only on MSDOS systems */
                    444:        if ((p = getenv("TZ")) == NULL || *p == '\0')
                    445:        {       fprintf(pgpout,PSTR("\007WARNING: Environmental variable TZ is not defined, so GMT timestamps\n\
                    446: may be wrong.  See the PGP User's Guide to properly define TZ\n\
                    447: in AUTOEXEC.BAT file.\n"));
                    448:        }
                    449: #endif /* MSDOS */
                    450: 
1.1.1.4 ! root      451: #ifdef VMS
1.1.1.3   root      452: #define TEMP "SYS$SCRATCH"
                    453: #else
                    454: #define TEMP "TMP"
                    455: #endif /* VMS */
                    456:        if ((p = getenv(TEMP)) != NULL && *p != '\0')
                    457:                settmpdir(p);
                    458: 
1.1.1.4 ! root      459:        if ((myArgv = (char **) malloc((argc + 2) * sizeof(char **))) == NULL) {
        !           460:                fprintf(stderr, PSTR("\n\007Out of memory.\n"));
        !           461:                exitPGP(7);
        !           462:        }
        !           463:        myArgv[0] = NULL;
        !           464:        myArgv[1] = NULL;
        !           465: 
1.1.1.3   root      466:        /* Process all the command-line option switches: */
                    467:        while (optind < argc)
                    468:        {       /*
                    469:                 * Allow random order of options and arguments (like GNU getopt)
                    470:                 * NOTE: this does not work with GNU getopt, use getopt.c from
                    471:                 * the PGP distribution.
                    472:                 */
                    473:                if ((opt = getopt(argc, argv, OPTIONS)) == EOF)
                    474:                {       if (optind == argc)             /* -- at end */
                    475:                                break;
                    476:                        myArgv[myArgc++] = argv[optind++];
                    477:                        continue;
                    478:                }
                    479:                opt = to_lower(opt);
                    480:                if (keyflag && (keychar == '\0' || (keychar == 'v' && opt == 'v')))
                    481:                {
                    482:                        if (keychar == 'v')
                    483:                                keychar = 'V';
                    484:                        else
                    485:                                keychar = opt;
                    486:                        continue;
                    487:                }
                    488:                switch (opt)
                    489:                {
                    490:                        case 'a': armor_flag = TRUE; emit_radix_64 = 1; break;
                    491:                        case 'b': separate_signature = strip_sig_flag = TRUE; break;
                    492:                        case 'c': encrypt_flag = conventional_flag = TRUE;
                    493:                                          c_flag = TRUE; break;
                    494:                        case 'd': decrypt_only_flag = TRUE; break;
                    495:                        case 'e': encrypt_flag = TRUE; break;
                    496:                        case 'f': filter_mode = TRUE; break;
                    497:                        case '?':
                    498:                        case 'h': usage(); break;
                    499: #ifdef VMS
1.1.1.4 ! root      500:                        case 'i': literal_mode = MODE_LOCAL; break;
1.1.1.3   root      501: #endif /* VMS */
                    502:                        case 'k': keyflag = TRUE; break;
                    503:                        case 'l': verbose = TRUE; break;
                    504:                        case 'm': moreflag = TRUE; break;
                    505:                        case 'p': preserve_filename = TRUE; break;
                    506:                        case 'o': outputfile = optarg; break;
                    507:                        case 's': sign_flag = TRUE; break;
1.1.1.4 ! root      508:                        case 't': literal_mode = MODE_TEXT; break;
1.1.1.3   root      509:                        case 'u': strncpy(my_name, optarg, sizeof(my_name)-1);
                    510:                                  CONVERT_TO_CANONICAL_CHARSET(my_name);
                    511:                                  break;
                    512:                        case 'w': wipeflag = TRUE; break;
                    513:                        case 'z': break;
                    514:                        /* '+' special option: does not require - */
                    515:                        case '+':
                    516:                                if (processConfigLine(optarg) == 0)
                    517:                                        break;
                    518:                                fprintf(stderr, "\n");
                    519:                                /* fallthrough */
                    520:                        default:
                    521:                                arg_error();
                    522:                }
                    523:        }
1.1.1.4 ! root      524:        myArgv[myArgc] = NULL;  /* Just to make it NULL terminated */
        !           525: 
1.1.1.3   root      526:        if (keyflag && keychar == '\0')
                    527:                key_usage();
                    528: 
                    529:        signon_msg();
                    530:        check_expiration_date();        /* hobble any experimental version */
                    531: 
1.1.1.4 ! root      532:        if (!filter_mode && (outputfile == NULL || strcmp(outputfile, "-")))
1.1.1.3   root      533:                pgpout = stdout;
                    534: 
                    535: #if defined(UNIX) || defined(VMS)
                    536:        umask(077); /* Make files default to private */
                    537: #endif
                    538: 
                    539:        initsigs();
                    540: 
                    541:        if (keyflag)
1.1.1.4 ! root      542:        {       status = do_keyopt(keychar);
        !           543:                if (status < 0)
        !           544:                        user_error();
        !           545:                exitPGP(status);
1.1.1.3   root      546:        }
                    547: 
                    548:        /* -db means break off signature certificate into separate file */
                    549:        if (decrypt_only_flag && strip_sig_flag)
                    550:                decrypt_only_flag = FALSE;
                    551: 
                    552:        if (decrypt_only_flag && armor_flag)
                    553:                decrypt_mode = de_armor_only = TRUE;
                    554: 
                    555:        if (outputfile != NULL)
                    556:                preserve_filename = FALSE;
                    557: 
                    558:        if (!sign_flag && !encrypt_flag && !conventional_flag && !armor_flag)
                    559:        {       if (wipeflag)   /* wipe only */
                    560:                {       if (myArgc != 3)
                    561:                                arg_error();    /* need one argument */
                    562:                        if (wipefile(myArgv[2]) == 0 && remove(myArgv[2]) == 0)
                    563:                        {       fprintf(pgpout,PSTR("\nFile %s wiped and deleted. "),myArgv[2]);
                    564:                                fprintf(pgpout, "\n");
                    565:                                exitPGP(EXIT_OK);
                    566:                        }
                    567:                        exitPGP(UNKNOWN_FILE_ERROR);
                    568:                }
                    569:                /* decrypt if none of the -s -e -c -a -w options are specified */
                    570:                decrypt_mode = TRUE;
                    571:        }
                    572: 
                    573:        if (myArgc == 2)                /* no arguments */
                    574:        {
                    575: #ifdef UNIX
                    576:                if (!filter_mode && !isatty(fileno(stdin)))
                    577:                {       /* piping to pgp without arguments and no -f:
                    578:                         * switch to filter mode but don't write output to stdout
                    579:                         * if it's a tty, use the preserved filename */
1.1.1.4 ! root      580:                        if (!moreflag)
        !           581:                                pgpout = stderr;
1.1.1.3   root      582:                        filter_mode = TRUE;
                    583:                        if (isatty(fileno(stdout)) && !moreflag)
                    584:                                preserve_filename = TRUE;
                    585:                }
                    586: #endif
                    587:                if (!filter_mode)
1.1.1.4 ! root      588:                {
        !           589:                        if (quietmode)
        !           590:                        {
        !           591:                                quietmode = FALSE;
        !           592:                                signon_msg();
        !           593:                        }
        !           594:                        fprintf(pgpout,PSTR("\nFor details on licensing and distribution, see the PGP User's Guide.\
1.1.1.3   root      595: \nFor other cryptography products and custom development services, contact:\
                    596: \nPhilip Zimmermann, 3021 11th St, Boulder CO 80304 USA, phone (303)541-0140\n"));
                    597:                        if (strcmp((p = PSTR("@translator@")), "@translator@"))
                    598:                                fprintf(pgpout, p);
                    599:                        fprintf(pgpout,PSTR("\nFor a usage summary, type:  pgp -h\n"));
                    600:                        exit(BAD_ARG_ERROR);            /* error exit */
                    601:                }
                    602:        }
                    603:        else
                    604:        {       if (filter_mode)
1.1.1.4 ! root      605:                        recipient = &myArgv[2];
1.1.1.3   root      606:                else
                    607:                {       inputfile = myArgv[2];
1.1.1.4 ! root      608:                        recipient = &myArgv[3];
1.1.1.3   root      609:                }
                    610:        }
                    611: 
                    612: 
                    613:        if (filter_mode)
1.1.1.4 ! root      614:                inputfile = "stdin";
1.1.1.3   root      615:        else
                    616:        {       if (decrypt_mode && no_extension(inputfile))
                    617:                {       strcpy(cipherfile, inputfile);
                    618:                        force_extension( cipherfile, ASC_EXTENSION );
                    619:                        if (file_exists (cipherfile))
                    620:                                inputfile = cipherfile;
                    621:                        else
1.1.1.4 ! root      622:                        {       force_extension( cipherfile, PGP_EXTENSION );
1.1.1.3   root      623:                                if (file_exists (cipherfile))
                    624:                                        inputfile = cipherfile;
                    625:                                else
                    626:                                {       force_extension( cipherfile, SIG_EXTENSION );
                    627:                                        if (file_exists (cipherfile))
                    628:                                                inputfile = cipherfile;
                    629:                                }
                    630:                        }
                    631:                }
                    632:                if (! file_exists( inputfile ))
                    633:                {       fprintf(pgpout, PSTR("\007File [%s] does not exist.\n"), inputfile);
                    634:                        errorLvl = FILE_NOT_FOUND_ERROR;
                    635:                        user_error();
                    636:                }
                    637:        }
                    638: 
                    639:        if (strlen(inputfile) >= (unsigned) MAX_PATH-4)
                    640:        {       fprintf(pgpout, PSTR("\007Invalid filename: [%s] too long\n"), inputfile );
                    641:                errorLvl = INVALID_FILE_ERROR;
                    642:                user_error();
                    643:        }
                    644:        strcpy(plainfile, inputfile);
                    645: 
                    646:        if (filter_mode)
                    647:                setoutdir(NULL);        /* NULL means use tmpdir */
                    648:        else
                    649:        {       if (outputfile)
                    650:                        setoutdir(outputfile);
                    651:                else
                    652:                        setoutdir(inputfile);
                    653:        }
                    654: 
                    655:        if (filter_mode)
                    656:        {       workfile = tempfile(TMP_WIPE|TMP_TMPDIR);
                    657:                readPhantomInput(workfile);
                    658:        }
1.1.1.4 ! root      659:        else
        !           660:                workfile = inputfile;
1.1.1.3   root      661: 
                    662:        get_header_info_from_file( workfile, &ctb, 1 );
                    663:        if (decrypt_mode)
1.1.1.4 ! root      664:        {       if (!outputfile && myArgc > 3)
1.1.1.3   root      665:                        outputfile = myArgv[3];
1.1.1.4 ! root      666:                strip_spaces = FALSE;
1.1.1.3   root      667:                if (!is_ctb(ctb) && is_armor_file(workfile, 0L))
                    668:                        do_armorfile(workfile);
                    669:                else
1.1.1.4 ! root      670:                        if (do_decrypt(workfile) < 0)
        !           671:                                user_error();
        !           672:                if (batchmode && !signature_checked)
        !           673:                        exitPGP(1);     /* alternate success, file did not have sig. */
        !           674:                else
        !           675:                        exitPGP(EXIT_OK);
1.1.1.3   root      676:        }
                    677: 
                    678: 
                    679:        /*      See if plaintext input file was actually created by PGP earlier--
                    680:                If it was, maybe we should NOT encapsulate it in a literal packet.
                    681:                Otherwise, always encapsulate it.
                    682:        */
1.1.1.4 ! root      683:        if (force_flag) /* for use with batchmode, force nesting */
        !           684:                nestflag = legal_ctb(ctb);
        !           685:        else
        !           686:                nestflag = FALSE;       /* First assume we will encapsulate it. */
        !           687:        if (!batchmode && !filter_mode && legal_ctb(ctb))
1.1.1.3   root      688:        {       /*      Special case--may be a PGP-created packet, so
                    689:                        do we inhibit encapsulation in literal packet? */
                    690:                fprintf(pgpout, PSTR("\n\007Input file '%s' looks like it may have been created by PGP. "),
                    691:                        inputfile );
                    692:                fprintf(pgpout, PSTR("\nIs it safe to assume that it was created by PGP (y/N)? "));
1.1.1.4 ! root      693:                nestflag = getyesno('n');
1.1.1.3   root      694:        }       /* Possible ciphertext input file */
                    695: 
                    696:        if (moreflag)           /* special name to cause printout on decrypt */
                    697:        {       strcpy (literal_file_name, CONSOLE_FILENAME);
1.1.1.4 ! root      698:                literal_mode = MODE_TEXT;       /* will check for text file later */
1.1.1.3   root      699:        }
                    700:        else
                    701:        {       strcpy (literal_file_name, inputfile);
                    702: #ifdef MSDOS
                    703:                strlwr (literal_file_name);
                    704: #endif
                    705:        }
                    706:        literal_file = literal_file_name;
                    707: 
                    708:        /*      Make sure non-text files are not accidentally converted 
                    709:                to canonical text.  This precaution should only be followed 
                    710:                for US ASCII text files, since European text files may have 
                    711:                8-bit character codes and still be legitimate text files 
                    712:                suitable for conversion to canonical (CR/LF-terminated) 
                    713:                text format. */
1.1.1.4 ! root      714:        if (literal_mode==MODE_TEXT && !is_text_file(workfile))
1.1.1.3   root      715:        {       fprintf(pgpout, 
                    716: PSTR("\n\007Warning: '%s' is not a pure text file.\nFile will be treated as binary data.\n"), 
                    717:                        workfile);
1.1.1.4 ! root      718:                literal_mode = MODE_BINARY; /* now expect straight binary */
1.1.1.3   root      719:        }
                    720: 
1.1.1.4 ! root      721:        if (moreflag && literal_mode==MODE_BINARY)      /* For eyes only?  Can't display binary file. */
1.1.1.3   root      722:        {       fprintf(pgpout, 
                    723:                PSTR("\n\007Error: Only text files may be sent as display-only.\n"));
                    724:                errorLvl = INVALID_FILE_ERROR;
                    725:                user_error();
                    726:        }               
                    727: 
                    728: 
                    729:        /*      See if plainfile looks like it might be incompressible, 
                    730:                by examining its contents for compression headers for 
                    731:                commonly-used compressed file formats like PKZIP, etc.
                    732:                Remember this information for later, when we are deciding
                    733:                whether to attempt compression before encryption.
                    734:        */
                    735:        attempt_compression = compress_enabled && file_compressible(plainfile);
                    736: 
                    737: 
                    738:        if (sign_flag)
                    739:        {
1.1.1.4 ! root      740:                if (!filter_mode && !quietmode)
1.1.1.3   root      741:                        fprintf(pgpout, PSTR("\nA secret key is required to make a signature. "));
1.1.1.4 ! root      742:                if (!quietmode && my_name[0] == '\0')
1.1.1.3   root      743:                {
                    744:                        fprintf(pgpout, PSTR("\nYou specified no user ID to select your secret key,\n\
                    745: so the default user ID and key will be the most recently\n\
                    746: added key on your secret keyring.\n"));
                    747:                }
                    748: 
1.1.1.4 ! root      749:                strip_spaces = FALSE;
        !           750:                clearfile = NULL;
        !           751:                if (literal_mode==MODE_TEXT)
1.1.1.3   root      752:                {               /* Text mode requires becoming canonical */
                    753:                        tempf = tempfile(TMP_WIPE|TMP_TMPDIR);
                    754:                        /* +clear means output file with signature in the clear,
                    755:                           only in combination with -t and -a, not with -e or -b */
                    756:                        if (!encrypt_flag && !separate_signature &&
                    757:                                        emit_radix_64 && clear_signatures) {
                    758:                                clearfile = workfile;
1.1.1.4 ! root      759:                                strip_spaces = TRUE;
1.1.1.3   root      760:                        }
1.1.1.4 ! root      761:                        make_canonical( workfile, tempf );
        !           762:                        if (!clearfile)
        !           763:                                rmtemp(workfile);
1.1.1.3   root      764:                        workfile = tempf;
                    765:                }
                    766:                if ((emit_radix_64 || encrypt_flag) && !separate_signature)
                    767:                        tempf = tempfile(TMP_WIPE|TMP_TMPDIR);
                    768:                else
                    769:                        tempf = tempfile(TMP_WIPE);
                    770:                /* for clear signatures we create a separate signature */
                    771:                status = signfile(nestflag, separate_signature || (clearfile != NULL),
1.1.1.4 ! root      772:                                                        my_name, workfile, tempf, literal_mode, literal_file );
1.1.1.3   root      773:                rmtemp(workfile);
                    774:                workfile = tempf;
                    775: 
                    776:                if (status < 0) /* signfile failed */
                    777:                {       fprintf(pgpout, PSTR("\007Signature error\n") );
                    778:                        errorLvl = SIGNATURE_ERROR;
                    779:                        user_error();
                    780:                }
                    781: 
1.1.1.4 ! root      782:                /*  We used to compress signed files only if they were also armored.
        !           783:                        Now that we have clear signatures it makes more sense to always
        !           784:                        compress signature files. */
        !           785:                if (attempt_compression && !separate_signature && !encrypt_flag &&
1.1.1.3   root      786:                                !clearfile)
                    787:                {       tempf = tempfile(TMP_WIPE|TMP_TMPDIR);
                    788:                        squish_file(workfile, tempf);
                    789:                        rmtemp(workfile);
                    790:                        workfile = tempf;
                    791:                }
                    792: 
                    793:        }       /* sign file */
                    794:        else if (!nestflag)
                    795:        {       /*      Prepend CTB_LITERAL byte to plaintext file.
                    796:                        --sure wish this pass could be optimized away. */
                    797:                tempf = tempfile(TMP_WIPE);
1.1.1.4 ! root      798:                status = make_literal( workfile, tempf, literal_mode, literal_file );
1.1.1.3   root      799:                rmtemp(workfile);
                    800:                workfile = tempf;
                    801:        }
                    802: 
                    803:        if (encrypt_flag)
                    804:        {
1.1.1.4 ! root      805:                tempf = tempfile(TMP_WIPE);
1.1.1.3   root      806:                if (!conventional_flag)
                    807:                {
1.1.1.4 ! root      808:                        if (!filter_mode && !quietmode)
        !           809:                                fprintf(pgpout, PSTR("\n\nRecipients' public key(s) will be used to encrypt. "));
        !           810:                        if (recipient == NULL || *recipient == NULL || **recipient == '\0')
1.1.1.3   root      811:                        {       /* no recipient specified on command line */
                    812:                                fprintf(pgpout, PSTR("\nA user ID is required to select the recipient's public key. "));
                    813:                                fprintf(pgpout, PSTR("\nEnter the recipient's user ID: "));
                    814:                                getstring( mcguffin, 255, TRUE );       /* echo keyboard */
1.1.1.4 ! root      815:                                if ((mcguffins = (char **) malloc (2 * sizeof(char *))) == NULL) {
        !           816:                                        fprintf(stderr, PSTR("\n\007Out of memory.\n"));
        !           817:                                        exitPGP(7);
        !           818:                                }
        !           819:                                mcguffins[0] = mcguffin;
        !           820:                                mcguffins[1] = "";
1.1.1.3   root      821:                        }
                    822:                        else
                    823:                        {       /* recipient specified on command line */
1.1.1.4 ! root      824:                                mcguffins = recipient;
1.1.1.3   root      825:                        }
1.1.1.4 ! root      826:                        for (recipient = mcguffins; *recipient != NULL && 
        !           827:                             **recipient != '\0'; recipient++) {
        !           828:                                CONVERT_TO_CANONICAL_CHARSET(*recipient);
        !           829:                        }
        !           830:                        status = encryptfile( mcguffins, workfile, tempf, attempt_compression);
1.1.1.3   root      831:                }
                    832:                else
1.1.1.4 ! root      833:                        status = idea_encryptfile( workfile, tempf, attempt_compression);
1.1.1.3   root      834: 
                    835:                rmtemp(workfile);
                    836:                workfile = tempf;
                    837: 
                    838:                if (status < 0)
                    839:                {       fprintf(pgpout, PSTR("\007Encryption error\n") );
                    840:                        errorLvl = (conventional_flag ? ENCR_ERROR : RSA_ENCR_ERROR);
                    841:                        user_error();
                    842:                }
                    843:        }       /* encrypt file */
                    844: 
                    845:        if (outputfile)         /* explicit output file overrides filter mode */
                    846:                filter_mode = (strcmp(outputfile, "-") == 0);
                    847: 
                    848:        if (filter_mode)
                    849:        {       if (emit_radix_64)
                    850:                {       /* NULL for outputfile means write to stdout */
                    851:                        if (armor_file(workfile, NULL, inputfile, clearfile) != 0)
                    852:                        {       errorLvl = UNKNOWN_FILE_ERROR;
                    853:                                user_error();
                    854:                        }
                    855:                        if (clearfile)
                    856:                                rmtemp(clearfile);
                    857:                }
                    858:                else
                    859:                        if (writePhantomOutput(workfile) < 0)
                    860:                        {       errorLvl = UNKNOWN_FILE_ERROR;
                    861:                                user_error();
                    862:                        }
                    863:                rmtemp(workfile);
                    864:        }
                    865:        else
                    866:        {       char name[MAX_PATH];
                    867:                if (outputfile)
                    868:                        strcpy(name, outputfile);
                    869:                else
                    870:                {       strcpy(name, inputfile);
                    871:                        drop_extension(name);
                    872:                }
                    873:                if (no_extension(name))
                    874:                {       if (emit_radix_64)
                    875:                                force_extension(name, ASC_EXTENSION);
                    876:                        else if (sign_flag && separate_signature)
                    877:                                force_extension(name, SIG_EXTENSION);
                    878:                        else
1.1.1.4 ! root      879:                                force_extension(name, PGP_EXTENSION);
1.1.1.3   root      880:                }
                    881:                if (emit_radix_64)
                    882:                {
                    883:                        if (armor_file(workfile, name, inputfile, clearfile) != 0)
                    884:                        {       errorLvl = UNKNOWN_FILE_ERROR;
                    885:                                user_error();
                    886:                        }
                    887:                        if (clearfile)
                    888:                                rmtemp(clearfile);
                    889:                }
                    890:                else
                    891:                {       if ((outputfile = savetemp(workfile, name)) == NULL)
                    892:                        {       errorLvl = UNKNOWN_FILE_ERROR;
                    893:                                user_error();
                    894:                        }
1.1.1.4 ! root      895:                        if (!quietmode)
        !           896:                        {
        !           897:                                if (encrypt_flag)
        !           898:                                        fprintf(pgpout, PSTR("\nCiphertext file: %s\n"), outputfile);
        !           899:                                else if (sign_flag)
        !           900:                                        fprintf(pgpout, PSTR("\nSignature file: %s\n"), outputfile);
        !           901:                        }
1.1.1.3   root      902:                }
                    903:        }
                    904: 
                    905:        if (wipeflag)
                    906:        {       /* destroy every trace of plaintext */
                    907:                if (wipefile(inputfile) == 0)
                    908:                {       remove(inputfile);
                    909:                        fprintf(pgpout,PSTR("\nFile %s wiped and deleted. "),inputfile);
                    910:                        fprintf(pgpout, "\n");
                    911:                }
                    912:        }
                    913: 
                    914:        exitPGP(EXIT_OK);
1.1.1.4 ! root      915:        return(0);      /* to shut up lint and some compilers */
1.1.1.3   root      916: }      /* main */
                    917: 
                    918: #ifdef MSDOS
                    919: #include <dos.h>
                    920: static char *dos_errlst[] = {
                    921:        "Write protect error",          /* PSTR ("Write protect error") */
                    922:        "Unknown unit",
                    923:        "Drive not ready",                      /* PSTR ("Drive not ready") */
                    924:        "3", "4", "5", "6", "7", "8", "9",
                    925:        "Write error",                          /* PSTR ("Write error") */
                    926:        "Read error",                           /* PSTR ("Read error") */
                    927:        "General failure",
                    928: };
                    929: 
                    930: /* handler for msdos 'harderrors' */
                    931: #ifndef OS2
                    932: #ifdef __TURBOC__      /* Turbo C 2.0 */
                    933: static int dostrap(int errval)
                    934: #else
                    935: static void dostrap(unsigned deverr, unsigned errval)
                    936: #endif
                    937: {
                    938:        char errbuf[64];
                    939:        int i;
                    940:        sprintf(errbuf, "\r\nDOS error: %s\r\n", dos_errlst[errval]);
                    941:        i = 0;
                    942:        do
                    943:                bdos(2,(unsigned int)errbuf[i],0);
                    944:        while (errbuf[++i]);
                    945: #ifdef __TURBOC__
                    946:        return 0;       /* ignore (fopen will return NULL) */
                    947: #else
                    948:        return;
                    949: #endif
                    950: }
                    951: #endif /* MSDOS */
                    952: #endif
                    953: 
                    954: static void initsigs()
                    955: {
                    956: #ifdef MSDOS
                    957: #ifndef OS2
                    958: #ifdef __TURBOC__
                    959:        harderr(dostrap);
                    960: #else /* MSC */
1.1.1.4 ! root      961: #ifndef __GNUC__ /* DJGPP's not MSC */
1.1.1.3   root      962:        _harderr(dostrap);
                    963: #endif
                    964: #endif
1.1.1.4 ! root      965: #endif
1.1.1.3   root      966: #endif /* MSDOS */
                    967: #ifdef SIGINT
                    968: #ifdef ATARI
                    969:        signal(SIGINT,(sigfunc_t) breakHandler);
                    970: #else
                    971:        signal(SIGINT,breakHandler);
                    972: #if defined(UNIX) || defined(VMS)
                    973:        signal(SIGHUP,breakHandler);
                    974:        signal(SIGQUIT,breakHandler);
                    975: #ifdef UNIX
                    976:        signal(SIGPIPE,breakHandler);
                    977: #endif
                    978:        signal(SIGTERM,breakHandler);
                    979: #ifndef DEBUG
1.1.1.4 ! root      980:        signal(SIGTRAP,breakHandler);
1.1.1.3   root      981:        signal(SIGSEGV,breakHandler);
                    982:        signal(SIGILL,breakHandler);
                    983: #ifdef SIGBUS
                    984:        signal(SIGBUS,breakHandler);
                    985: #endif
                    986: #endif /* DEBUG */
                    987: #endif /* UNIX */
                    988: #endif /* not Atari */
                    989: #endif /* SIGINT */
                    990: }      /* initsigs */
                    991: 
                    992: 
                    993: static void do_armorfile(char *armorfile)
                    994: {
                    995:        char *tempf;
                    996:        char cipherfile[MAX_PATH];
                    997:        long linepos = 0;
                    998:        int status;
1.1.1.4 ! root      999:        int success = 0;
1.1.1.3   root     1000: 
                   1001:        while (TRUE)
                   1002:        {       /* Handle transport armor stripping */
                   1003:                tempf = tempfile(0);
1.1.1.4 ! root     1004:                strip_spaces = FALSE;   /* de_armor_file() sets this for clear signature files */
1.1.1.3   root     1005:                status = de_armor_file(armorfile,tempf,&linepos);
                   1006:                if (status)
                   1007:                {       fprintf(pgpout,PSTR("\n\007Error: Transport armor stripping failed for file %s\n"),armorfile);
                   1008:                        errorLvl = INVALID_FILE_ERROR;
                   1009:                        user_error();    /* Bad file */
                   1010:                }
                   1011:                if (keepctx || de_armor_only)
1.1.1.4 ! root     1012:                {       if (outputfile && de_armor_only)
        !          1013:                        {       if (strcmp(outputfile, "-") == 0)
        !          1014:                                {       writePhantomOutput(tempf);
        !          1015:                                        rmtemp(tempf);
        !          1016:                                        return;
        !          1017:                                }
1.1.1.3   root     1018:                                strcpy(cipherfile, outputfile);
1.1.1.4 ! root     1019:                        }
1.1.1.3   root     1020:                        else
                   1021:                        {       strcpy(cipherfile, file_tail(armorfile));
1.1.1.4 ! root     1022:                                force_extension(cipherfile, PGP_EXTENSION);
1.1.1.3   root     1023:                        }
                   1024:                        if ((tempf = savetemp(tempf, cipherfile)) == NULL)
                   1025:                        {       errorLvl = UNKNOWN_FILE_ERROR;
                   1026:                                user_error();
                   1027:                        }
1.1.1.4 ! root     1028:                        if (!quietmode)
        !          1029:                                fprintf(pgpout,PSTR("Stripped transport armor from '%s', producing '%s'.\n"),
        !          1030:                                        armorfile, tempf);
        !          1031:                        /* -da flag: don't decrypt */
        !          1032:                        if (de_armor_only || do_decrypt(tempf) >= 0)
        !          1033:                                ++success;
1.1.1.3   root     1034:                }
                   1035:                else
1.1.1.4 ! root     1036:                {       if (do_decrypt(tempf) >= 0)
        !          1037:                                ++success;
1.1.1.3   root     1038:                        rmtemp(tempf);
                   1039:                }
                   1040: 
                   1041:                if (!is_armor_file(armorfile, linepos))
1.1.1.4 ! root     1042:                {
        !          1043:                        if (!success)   /* print error msg if we didn't decrypt anything */
        !          1044:                                user_error();
        !          1045:                        return;
        !          1046:                }
1.1.1.3   root     1047: 
                   1048:                fprintf (pgpout, PSTR("\nLooking for next packet in '%s'...\n"), armorfile);
                   1049:        }
                   1050: }      /* do_armorfile */
                   1051: 
                   1052: 
1.1.1.4 ! root     1053: static int do_decrypt(char *cipherfile)
1.1.1.3   root     1054: {
                   1055:        char *outfile = NULL;
                   1056:        int status, i;
                   1057:        boolean nested_info = FALSE;
                   1058:        char ringfile[MAX_PATH];
                   1059:        byte ctb;
                   1060:        byte header[8]; /* used to classify file type at the end. */
                   1061:        char preserved_name[MAX_PATH];
                   1062:        char *newname;
                   1063: 
                   1064:        /* will be set to the original file name after processing a literal packet */
                   1065:        preserved_name[0] = '\0';
                   1066: 
                   1067:        do      /* while nested parsable info present */
                   1068:        {
                   1069:                if (nested_info)
                   1070:                {       rmtemp(cipherfile);             /* never executed on first pass */
                   1071:                        cipherfile = outfile;
                   1072:                }
                   1073:                if (get_header_info_from_file( cipherfile, &ctb, 1) < 0)
                   1074:                {       fprintf(pgpout,PSTR("\n\007Can't open ciphertext file '%s'\n"),cipherfile);
                   1075:                        errorLvl = FILE_NOT_FOUND_ERROR;
1.1.1.4 ! root     1076:                        return -1;
1.1.1.3   root     1077:                }
                   1078: 
                   1079:                if (!is_ctb(ctb))               /* not a real CTB -- complain */
                   1080:                        break;
                   1081: 
                   1082:                outfile = tempfile(TMP_WIPE);
                   1083: 
                   1084:                /* PKE is Public Key Encryption */
                   1085:                if (is_ctb_type( ctb, CTB_PKE_TYPE ))
                   1086:                {
1.1.1.4 ! root     1087:                        if (!quietmode)
1.1.1.3   root     1088:                                fprintf(pgpout,PSTR("\nFile is encrypted.  Secret key is required to read it. "));
                   1089: 
                   1090:                        /* Decrypt to scratch file since we may have a LITERAL2 */
                   1091:                        status = decryptfile( cipherfile, outfile );
                   1092: 
                   1093:                        if (status < 0) /* error return */
                   1094:                        {       errorLvl = RSA_DECR_ERROR;
1.1.1.4 ! root     1095:                                return -1;
1.1.1.3   root     1096:                        }
                   1097:                        nested_info = (status > 0);
                   1098:                }               /* outer CTB is PKE type */
                   1099: 
                   1100:                if (is_ctb_type( ctb, CTB_SKE_TYPE ))
                   1101:                {
                   1102:                        if (decrypt_only_flag)
                   1103:                        {       /* swap file names instead of just copying the file */
                   1104:                                rmtemp(outfile);
                   1105:                                outfile = cipherfile;
                   1106:                                cipherfile = NULL;
1.1.1.4 ! root     1107:                                if (!quietmode)
        !          1108:                                        fprintf(pgpout,PSTR("\nThis file has a signature, which will be left in place.\n"));
1.1.1.3   root     1109:                                break;  /* Do no more */
                   1110:                        }
1.1.1.4 ! root     1111:                        if (!quietmode)
        !          1112:                                fprintf(pgpout,PSTR("\nFile has signature.  Public key is required to check signature. "));
1.1.1.3   root     1113: 
                   1114:                        status = check_signaturefile( cipherfile, outfile, strip_sig_flag, preserved_name );
                   1115: 
                   1116:                        if (status < 0) /* error return */
                   1117:                        {       errorLvl = SIGNATURE_CHECK_ERROR;
1.1.1.4 ! root     1118:                                return -1;
1.1.1.3   root     1119:                        }
                   1120:                        nested_info = (status > 0);
                   1121: 
                   1122:                        if (strcmp(preserved_name, "/dev/null") == 0)
                   1123:                        {       rmtemp(outfile);
                   1124:                                fprintf(pgpout, "\n");
1.1.1.4 ! root     1125:                                return 0;
1.1.1.3   root     1126:                        }
                   1127:                }               /* outer CTB is SKE type */
                   1128: 
                   1129: 
                   1130:                if (is_ctb_type( ctb, CTB_CKE_TYPE ))
                   1131:                {               /* Conventional Key Encrypted ciphertext. */
                   1132:                        /* Tell user it's encrypted here, and prompt for password in subroutine. */
1.1.1.4 ! root     1133:                        if (!quietmode)
1.1.1.3   root     1134:                                fprintf(pgpout,PSTR("\nFile is conventionally encrypted.  "));
                   1135:                        /* Decrypt to scratch file since it may be a LITERAL2 */
                   1136:                        status = idea_decryptfile( cipherfile, outfile );
                   1137:                        if (status < 0) /* error return */
                   1138:                        {       errorLvl = DECR_ERROR;
1.1.1.4 ! root     1139:                                return -1;      /* error exit status */
1.1.1.3   root     1140:                        }
                   1141:                        nested_info = (status > 0);
                   1142:                }               /* CTB is CKE type */
                   1143: 
                   1144: 
                   1145:                if (is_ctb_type( ctb, CTB_COMPRESSED_TYPE ))
                   1146:                {               /* Compressed text. */
                   1147:                        status = decompress_file( cipherfile, outfile );
                   1148:                        if (status < 0) /* error return */
                   1149:                        {       errorLvl = DECOMPRESS_ERROR;
1.1.1.4 ! root     1150:                                return -1;
1.1.1.3   root     1151:                        }
                   1152:                        /* Always assume nested information... */
                   1153:                        nested_info = TRUE;
                   1154:                }               /* CTB is COMPRESSED type */
                   1155: 
                   1156: 
                   1157:                if (is_ctb_type( ctb, CTB_LITERAL_TYPE ) || is_ctb_type( ctb, CTB_LITERAL2_TYPE))
                   1158:                {               /* Raw plaintext.  Just copy it.  No more nesting. */
                   1159:                        /* Strip off CTB_LITERAL prefix byte from file: */
                   1160:                        /* strip_literal may alter plainfile; will set mode */
                   1161:                        status = strip_literal( cipherfile, outfile,
1.1.1.4 ! root     1162:                                        preserved_name, &literal_mode);
1.1.1.3   root     1163:                        if (status < 0) /* error return */
                   1164:                        {       errorLvl = UNKNOWN_FILE_ERROR;
1.1.1.4 ! root     1165:                                return -1;
1.1.1.3   root     1166:                        }
                   1167:                        nested_info = FALSE;
                   1168:                }               /* CTB is LITERAL type */
                   1169: 
                   1170: 
                   1171:                if ((ctb == CTB_CERT_SECKEY) || (ctb == CTB_CERT_PUBKEY))
                   1172:                {       rmtemp(outfile);
                   1173:                        if (decrypt_only_flag)
                   1174:                        {       /* swap file names instead of just copying the file */
                   1175:                                outfile = cipherfile;
                   1176:                                cipherfile = NULL;
                   1177:                                break;  /* no further processing */
                   1178:                        }
                   1179:                                /* Key ring.  View it. */
                   1180:                        fprintf(pgpout, PSTR("\nFile contains key(s).  Contents follow...") );
1.1.1.4 ! root     1181:                        if (view_keyring( NULL, cipherfile, TRUE, FALSE ) < 0)
        !          1182:                        {       errorLvl = KEYRING_VIEW_ERROR;
        !          1183:                                return -1;
1.1.1.3   root     1184:                        }
1.1.1.4 ! root     1185:                        /* filter mode explicit requested with -f */
        !          1186:                        if (filter_mode && !preserve_filename)
        !          1187:                                return 0; /*    No output file */
        !          1188:                        if (batchmode)
        !          1189:                                return 0;
1.1.1.3   root     1190:                        if (ctb == CTB_CERT_SECKEY)
                   1191:                                buildfilename(ringfile,SECRET_KEYRING_FILENAME);
                   1192:                        else
                   1193:                                buildfilename(ringfile,PUBLIC_KEYRING_FILENAME);
                   1194:                        /*      Ask if it should be put on key ring */
1.1.1.4 ! root     1195:                        fprintf(pgpout, PSTR("\nDo you want to add this keyfile to keyring '%s' (y/N)? "), ringfile);
        !          1196:                        if (!getyesno('n'))
        !          1197:                                return 0;
        !          1198:                        status = addto_keyring(cipherfile,ringfile);
1.1.1.3   root     1199:                        if (status < 0)
                   1200:                        {       fprintf(pgpout, PSTR("\007Keyring add error. ") );
                   1201:                                errorLvl = KEYRING_ADD_ERROR;
1.1.1.4 ! root     1202:                                return -1;
1.1.1.3   root     1203:                        }
1.1.1.4 ! root     1204:                        return 0; /*    No output file */
1.1.1.3   root     1205:                }               /* key ring.  view it. */
                   1206: 
                   1207:        } while (nested_info);
                   1208:        /* No more nested parsable information */
                   1209: 
                   1210:        if (outfile == NULL)    /* file was not encrypted */
                   1211:        {       if (!filter_mode && !moreflag)
                   1212:                {       fprintf(pgpout,PSTR("\007\nError: '%s' is not a ciphertext, signature, or key file.\n"),
                   1213:                                cipherfile);
                   1214:                        errorLvl = UNKNOWN_FILE_ERROR;
1.1.1.4 ! root     1215:                        return -1;
1.1.1.3   root     1216:                }
                   1217:                outfile = cipherfile;
                   1218:        }
                   1219:        else
                   1220:                if (cipherfile)
                   1221:                        rmtemp(cipherfile);
                   1222: 
                   1223:        if (moreflag || (strcmp(preserved_name,CONSOLE_FILENAME) == 0))
                   1224:        {       /* blort to screen */
                   1225:                if (strcmp(preserved_name,CONSOLE_FILENAME) == 0)
                   1226:                {       fprintf(pgpout, 
                   1227:                        PSTR("\n\nThis message is marked \"For your eyes only\".  Display now (Y/n)? "));
1.1.1.4 ! root     1228:                        if (batchmode || !getyesno('y'))
1.1.1.3   root     1229:                        {       /* no -- abort display, and clean up */
                   1230:                                rmtemp(outfile);
1.1.1.4 ! root     1231:                                return 0;
1.1.1.3   root     1232:                        }
                   1233:                }
1.1.1.4 ! root     1234:                if (!quietmode)
        !          1235:                        fprintf(pgpout, PSTR("\n\nPlaintext message follows...\n"));
        !          1236:                else
        !          1237:                        putc('\n', pgpout);
        !          1238:                fprintf(pgpout, "------------------------------\n");
1.1.1.3   root     1239:                more_file(outfile);
                   1240:                /* Disallow saving to disk if outfile is console-only: */
                   1241:                if (strcmp(preserved_name,CONSOLE_FILENAME) == 0)
                   1242:                        clearscreen();  /* remove all evidence */
1.1.1.4 ! root     1243:                else if (!quietmode && !batchmode)
        !          1244:                {       
        !          1245:                        fprintf(pgpout, PSTR("Save this file permanently (y/N)? "));
1.1.1.3   root     1246:                        if (getyesno('n'))
                   1247:                        {       char moreFilename[256];
                   1248:                                fprintf(pgpout,PSTR("Enter filename to save file as: "));
                   1249:                                if (preserved_name[0])
                   1250:                                        fprintf(pgpout, "[%s]: ", file_tail(preserved_name));
                   1251:                                getstring( moreFilename, 255, TRUE );
                   1252:                                if (*moreFilename == '\0')
                   1253:                                {       if (*preserved_name != '\0')
                   1254:                                                savetemp (outfile, file_tail(preserved_name));
                   1255:                                        else
                   1256:                                                rmtemp(outfile);
                   1257:                                }
                   1258:                                else
                   1259:                                        savetemp (outfile, moreFilename);
1.1.1.4 ! root     1260:                                return 0;
1.1.1.3   root     1261:                        }
                   1262:                }
                   1263:                rmtemp(outfile);
1.1.1.4 ! root     1264:                return 0;
1.1.1.3   root     1265:        }       /* blort to screen */
                   1266: 
                   1267:        if (outputfile)
                   1268:        {       if (!strcmp(outputfile, "/dev/null"))
                   1269:                {       rmtemp(outfile);
1.1.1.4 ! root     1270:                        return 0;
1.1.1.3   root     1271:                }
                   1272:                filter_mode = (strcmp(outputfile, "-") == 0);
                   1273:                strcpy(plainfile, outputfile);
                   1274:        }
                   1275:        else
                   1276: #ifdef VMS
                   1277:                /* VMS null extension has to be ".", not "" */
                   1278:                force_extension(plainfile, ".");
                   1279: #else  /* not VMS */
                   1280:                drop_extension(plainfile);
                   1281: #endif /* not VMS */
                   1282: 
                   1283:        if (!preserve_filename && filter_mode)
                   1284:        {       if (writePhantomOutput(outfile) < 0)
                   1285:                {       errorLvl = UNKNOWN_FILE_ERROR;
1.1.1.4 ! root     1286:                        return -1;
1.1.1.3   root     1287:                }
                   1288:                rmtemp(outfile);
1.1.1.4 ! root     1289:                return 0;
1.1.1.3   root     1290:        }
                   1291: 
                   1292:        if (preserve_filename && preserved_name[0] != '\0')
                   1293:                strcpy(plainfile, file_tail(preserved_name));
                   1294: 
1.1.1.4 ! root     1295:        if (quietmode)
        !          1296:        {       if (savetemp(outfile, plainfile) == NULL)
        !          1297:                {       errorLvl = UNKNOWN_FILE_ERROR;
        !          1298:                        return -1;
        !          1299:                }
        !          1300:                return 0;
        !          1301:        }
1.1.1.3   root     1302:        if (!verbose)   /* if other filename messages were suppressed */
                   1303:                fprintf(pgpout,PSTR("\nPlaintext filename: %s"), plainfile);
                   1304: 
                   1305: 
                   1306:        /*---------------------------------------------------------*/
                   1307: 
                   1308:        /*      One last thing-- let's attempt to classify some of the more
                   1309:                frequently occurring cases of plaintext output files, as an
                   1310:                aid to the user.
                   1311: 
                   1312:                For example, if output file is a public key, it should have
                   1313:                the right extension on the filename.
                   1314: 
                   1315:                Also, it will likely be common to encrypt files created by
                   1316:                various archivers, so they should be renamed with the archiver
                   1317:                extension.
                   1318:        */
                   1319:        get_header_info_from_file( outfile, header, 8 );
                   1320: 
                   1321:        newname = NULL;
                   1322:        if (header[0] == CTB_CERT_PUBKEY)
                   1323:        {       /* Special case--may be public key, worth renaming */
                   1324:                fprintf(pgpout, PSTR("\nPlaintext file '%s' looks like it contains a public key."),
                   1325:                        plainfile );
                   1326:                newname = maybe_force_extension( plainfile, PGP_EXTENSION );
                   1327:        }       /* Possible public key output file */
                   1328: 
                   1329:        else
                   1330:        if ((i = compressSignature( header )) >= 0)
                   1331:        {       /*      Special case--may be an archived/compressed file, worth renaming        */
                   1332:                fprintf(pgpout, PSTR("\nPlaintext file '%s' looks like a %s file."),
                   1333:                        plainfile, compressName[i] );
                   1334:                newname = maybe_force_extension( plainfile, compressExt[i] );
                   1335:        }       /*      Possible archived/compressed output file        */
                   1336: 
                   1337:        else
                   1338:        if (is_ctb(header[0]) &&
                   1339:           (is_ctb_type (header[0], CTB_PKE_TYPE)
                   1340:         || is_ctb_type (header[0], CTB_SKE_TYPE)
                   1341:         || is_ctb_type (header[0], CTB_CKE_TYPE)))
                   1342:        {       /* Special case--may be another ciphertext file, worth renaming */
                   1343:                fprintf(pgpout, PSTR("\n\007Output file '%s' may contain more ciphertext or signature."),
                   1344:                        plainfile );
1.1.1.4 ! root     1345:                newname = maybe_force_extension( plainfile, PGP_EXTENSION );
1.1.1.3   root     1346:        }       /* Possible ciphertext output file */
                   1347: 
                   1348:        if (savetemp(outfile, (newname ? newname : plainfile)) == NULL)
                   1349:        {       errorLvl = UNKNOWN_FILE_ERROR;
1.1.1.4 ! root     1350:                return -1;
1.1.1.3   root     1351:        }
                   1352: 
                   1353:        fprintf (pgpout, "\n");
1.1.1.4 ! root     1354:        return 0;
1.1.1.3   root     1355: } /* do_decrypt */
                   1356: 
                   1357: 
1.1.1.4 ! root     1358: static int do_keyopt(char keychar)
1.1.1.3   root     1359: {
                   1360:        char keyfile[MAX_PATH];
                   1361:        char ringfile[MAX_PATH];
1.1.1.4 ! root     1362:        char *workfile;
1.1.1.3   root     1363:        int status;
                   1364: 
1.1.1.4 ! root     1365:        if ((filter_mode || batchmode)
        !          1366:                && (keychar == 'g' || keychar == 'e' || keychar == 'd'
        !          1367:                        || (keychar == 'r' && sign_flag)))
1.1.1.3   root     1368:        {       errorLvl = NO_BATCH;
                   1369:                arg_error();     /* interactive process, no go in batch mode */
                   1370:        }
                   1371: 
                   1372:        switch (keychar)
                   1373:        {
                   1374: 
                   1375:                /*-------------------------------------------------------*/
                   1376:                case 'g':
                   1377:                {       /*      Key generation
                   1378:                                Arguments: bitcount, bitcount
                   1379:                        */
                   1380:                        char    keybits[6], ebits[6];
                   1381: 
                   1382:                        if (myArgc > 2)
                   1383:                                strncpy( keybits, myArgv[2], sizeof(keybits)-1 );
                   1384:                        else
                   1385:                                keybits[0] = '\0';
                   1386: 
                   1387:                        if (myArgc > 3)
                   1388:                                strncpy( ebits, myArgv[3], sizeof(ebits)-1 );
                   1389:                        else
                   1390:                                ebits[0] = '\0';
                   1391: 
                   1392:                        /* dokeygen writes the keys out to the key rings... */
                   1393:                        status = dokeygen(keybits, ebits);
                   1394: 
                   1395:                        if (status < 0)
                   1396:                        {       fprintf(pgpout, PSTR("\007Keygen error. ") );
                   1397:                                errorLvl = KEYGEN_ERROR;
                   1398:                        }
1.1.1.4 ! root     1399:                        return status;
1.1.1.3   root     1400:                }       /* Key generation */
                   1401: 
                   1402:                /*-------------------------------------------------------*/
                   1403:                case 'c':
                   1404:                {       /*      Key checking
                   1405:                                Arguments: userid, ringfile
                   1406:                        */
                   1407: 
                   1408:                        if (myArgc < 3)         /* Default to all user ID's */
                   1409:                                mcguffin[0] = '\0';
                   1410:                        else
                   1411:                        {       strcpy ( mcguffin, myArgv[2] );
                   1412:                                if (strcmp( mcguffin, "*" ) == 0)
                   1413:                                        mcguffin[0] = '\0';
                   1414:                        }
                   1415:                        CONVERT_TO_CANONICAL_CHARSET(mcguffin);
                   1416: 
                   1417:                        if (myArgc < 4) /* default key ring filename */
                   1418:                                buildfilename( ringfile, PUBLIC_KEYRING_FILENAME );
                   1419:                        else
                   1420:                                strncpy( ringfile, myArgv[3], sizeof(ringfile)-1 );
                   1421: 
                   1422:                        if ((myArgc < 4 && myArgc > 2)  /* Allow just key file as arg */
                   1423:                        && has_extension( myArgv[2], PGP_EXTENSION ) )
                   1424:                        {       strcpy( ringfile, myArgv[2] );
                   1425:                                mcguffin[0] = '\0';
                   1426:                        }
                   1427: 
1.1.1.4 ! root     1428:                        status = dokeycheck( mcguffin, ringfile, CHECK_ALL );
1.1.1.3   root     1429: 
                   1430:                        if (status < 0)
                   1431:                        {       fprintf(pgpout, PSTR("\007Keyring check error. ") );
                   1432:                                errorLvl = KEYRING_CHECK_ERROR;
                   1433:                        }
1.1.1.4 ! root     1434:                        if (status >= 0 && mcguffin[0] != '\0')
        !          1435:                                return status;  /* just checking a single user, dont do maintenance */
1.1.1.3   root     1436: 
1.1.1.4 ! root     1437:                        if ((status = maint_check(ringfile, 0)) < 0 && status != -7)
1.1.1.3   root     1438:                        {       fprintf(pgpout, PSTR("\007Maintenance pass error. ") );
                   1439:                                errorLvl = KEYRING_CHECK_ERROR;
                   1440:                        }
                   1441: 
1.1.1.4 ! root     1442:                        return (status == -7 ? 0 : status);
1.1.1.3   root     1443:                }       /* Key check */
                   1444: 
                   1445:                /*-------------------------------------------------------*/
                   1446:                case 'm':
                   1447:                {       /*      Maintenance pass
                   1448:                                Arguments: ringfile
                   1449:                        */
                   1450: 
                   1451:                        if (myArgc < 3) /* default key ring filename */
                   1452:                                buildfilename( ringfile, PUBLIC_KEYRING_FILENAME );
                   1453:                        else
                   1454:                                strcpy( ringfile, myArgv[2] );
                   1455: 
                   1456: #ifdef MSDOS
                   1457:                        strlwr( ringfile );
                   1458: #endif
                   1459:                        if (! file_exists( ringfile ))
                   1460:                                default_extension( ringfile, PGP_EXTENSION );
                   1461: 
1.1.1.4 ! root     1462:                        if ((status = maint_check(ringfile,
1.1.1.3   root     1463:                                        MAINT_VERBOSE|(c_flag ? MAINT_CHECK : 0))) < 0)
                   1464:                        {       if (status == -7)
                   1465:                                        fprintf(pgpout, PSTR("File '%s' is not a public keyring\n"), ringfile);
                   1466:                                fprintf(pgpout, PSTR("\007Maintenance pass error. ") );
                   1467:                                errorLvl = KEYRING_CHECK_ERROR;
                   1468:                        }
1.1.1.4 ! root     1469:                        return status;
1.1.1.3   root     1470:                }       /* Maintenance pass */
                   1471: 
                   1472:                /*-------------------------------------------------------*/
                   1473:                case 's':
                   1474:                {       /*      Key signing
                   1475:                                Arguments: her_id, keyfile
                   1476:                        */
                   1477: 
                   1478:                        if (myArgc >= 4)
                   1479:                                strncpy( keyfile, myArgv[3], sizeof(keyfile)-1 );
                   1480:                        else
                   1481:                                buildfilename( keyfile, PUBLIC_KEYRING_FILENAME );
                   1482: 
                   1483:                        if (myArgc >= 3)
                   1484:                                strcpy( mcguffin, myArgv[2] );  /* Userid to sign */
                   1485:                        else
                   1486:                        {
                   1487:                                fprintf(pgpout, PSTR("\nA user ID is required to select the public key you want to sign. "));
1.1.1.4 ! root     1488:                                if (batchmode)  /* not interactive, userid must be on command line */
        !          1489:                                        return -1;
1.1.1.3   root     1490:                                fprintf(pgpout, PSTR("\nEnter the public key's user ID: "));
                   1491:                                getstring( mcguffin, 255, TRUE );       /* echo keyboard */
                   1492:                        }
                   1493:                        CONVERT_TO_CANONICAL_CHARSET(mcguffin);
                   1494: 
                   1495:                        if (my_name[0] == '\0')
                   1496:                        {
                   1497:                                fprintf(pgpout, PSTR("\nA secret key is required to make a signature. "));
                   1498:                                fprintf(pgpout, PSTR("\nYou specified no user ID to select your secret key,\n\
                   1499: so the default user ID and key will be the most recently\n\
                   1500: added key on your secret keyring.\n"));
                   1501:                        }
                   1502: 
                   1503:                        status = signkey ( mcguffin, my_name, keyfile );
                   1504: 
                   1505:                        if (status >= 0) {
1.1.1.4 ! root     1506:                                status = maint_update(keyfile);
1.1.1.3   root     1507:                                if (status == -7)       /* ringfile is a keyfile or secret keyring */
                   1508:                                {       fprintf(pgpout, "Warning: '%s' is not a public keyring\n", keyfile);
1.1.1.4 ! root     1509:                                        return 0;
1.1.1.3   root     1510:                                }
                   1511:                                if (status < 0)
                   1512:                                        fprintf(pgpout, PSTR("\007Maintenance pass error. ") );
                   1513:                        }
                   1514: 
                   1515:                        if (status < 0)
                   1516:                        {       fprintf(pgpout, PSTR("\007Key signature error. ") );
                   1517:                                errorLvl = KEY_SIGNATURE_ERROR;
                   1518:                        }
1.1.1.4 ! root     1519:                        return status;
1.1.1.3   root     1520:                }       /* Key signing */
                   1521: 
                   1522: 
                   1523:                /*-------------------------------------------------------*/
                   1524:                case 'd':
1.1.1.4 ! root     1525:                {       /*      disable/revoke key
1.1.1.3   root     1526:                                Arguments: userid, keyfile
                   1527:                        */
                   1528: 
                   1529:                        if (myArgc >= 4)
                   1530:                                strncpy( keyfile, myArgv[3], sizeof(keyfile)-1 );
                   1531:                        else
                   1532:                                buildfilename( keyfile, PUBLIC_KEYRING_FILENAME );
                   1533: 
                   1534:                        if (myArgc >= 3)
                   1535:                                strcpy( mcguffin, myArgv[2] );  /* Userid to sign */
                   1536:                        else
                   1537:                        {
1.1.1.4 ! root     1538:                                fprintf(pgpout, PSTR("\nA user ID is required to select the key you want to revoke or disable. "));
1.1.1.3   root     1539:                                fprintf(pgpout, PSTR("\nEnter user ID: "));
                   1540:                                getstring( mcguffin, 255, TRUE );       /* echo keyboard */
                   1541:                        }
                   1542:                        CONVERT_TO_CANONICAL_CHARSET(mcguffin);
                   1543: 
1.1.1.4 ! root     1544:                        status = disable_key ( mcguffin, keyfile );
1.1.1.3   root     1545: 
                   1546:                        if (status >= 0) {
1.1.1.4 ! root     1547:                                status = maint_update(keyfile);
1.1.1.3   root     1548:                                if (status == -7)       /* ringfile is a keyfile or secret keyring */
                   1549:                                {       fprintf(pgpout, "Warning: '%s' is not a public keyring\n", keyfile);
1.1.1.4 ! root     1550:                                        return 0;
1.1.1.3   root     1551:                                }
                   1552:                                if (status < 0)
                   1553:                                        fprintf(pgpout, PSTR("\007Maintenance pass error. ") );
                   1554:                        }
                   1555: 
                   1556:                        if (status < 0)
                   1557:                                errorLvl = KEY_SIGNATURE_ERROR;
1.1.1.4 ! root     1558:                        return status;
1.1.1.3   root     1559:                }       /* Key compromise */
                   1560: 
                   1561:                /*-------------------------------------------------------*/
                   1562:                case 'e':
                   1563:                {       /*      Key editing
                   1564:                                Arguments: userid, ringfile
                   1565:                        */
                   1566: 
                   1567:                        if (myArgc >= 4)
                   1568:                                strncpy( ringfile, myArgv[3], sizeof(ringfile)-1 );
                   1569:                        else    /* default key ring filename */
                   1570:                                buildfilename( ringfile, PUBLIC_KEYRING_FILENAME );
                   1571: 
                   1572:                        if (myArgc >= 3)
                   1573:                                strcpy( mcguffin, myArgv[2] );  /* Userid to edit */
                   1574:                        else
                   1575:                        {
                   1576:                                fprintf(pgpout, PSTR("\nA user ID is required to select the key you want to edit. "));
                   1577:                                fprintf(pgpout, PSTR("\nEnter the key's user ID: "));
                   1578:                                getstring( mcguffin, 255, TRUE );       /* echo keyboard */
                   1579:                        }
                   1580:                        CONVERT_TO_CANONICAL_CHARSET(mcguffin);
                   1581: 
                   1582:                        status = dokeyedit( mcguffin, ringfile );
                   1583: 
                   1584:                        if (status >= 0) {
1.1.1.4 ! root     1585:                                status = maint_update(ringfile);
        !          1586:                                if (status == -7)
        !          1587:                                        status = 0;     /* ignore "not a public keyring" error */
        !          1588:                                if (status < 0)
1.1.1.3   root     1589:                                        fprintf(pgpout, PSTR("\007Maintenance pass error. ") );
                   1590:                        }
                   1591: 
1.1.1.4 ! root     1592:                        if (status < 0)
1.1.1.3   root     1593:                        {       fprintf(pgpout, PSTR("\007Keyring edit error. ") );
                   1594:                                errorLvl = KEYRING_EDIT_ERROR;
                   1595:                        }
1.1.1.4 ! root     1596:                        return status;
1.1.1.3   root     1597:                }       /* Key edit */
                   1598: 
                   1599:                /*-------------------------------------------------------*/
                   1600:                case 'a':
                   1601:                {       /*      Add key to key ring
                   1602:                                Arguments: keyfile, ringfile
                   1603:                        */
                   1604: 
1.1.1.4 ! root     1605:                        if (myArgc < 3 && !filter_mode)
1.1.1.3   root     1606:                                arg_error();
                   1607: 
1.1.1.4 ! root     1608:                        if (!filter_mode) {     /* Get the keyfile from args */
        !          1609:                                strncpy( keyfile, myArgv[2], sizeof(keyfile)-1 );
        !          1610:                                
1.1.1.3   root     1611: #ifdef MSDOS
1.1.1.4 ! root     1612:                                strlwr( keyfile  );
1.1.1.3   root     1613: #endif
1.1.1.4 ! root     1614:                                if (! file_exists( keyfile ))
        !          1615:                                        default_extension( keyfile, PGP_EXTENSION );
1.1.1.3   root     1616: 
1.1.1.4 ! root     1617:                                if (! file_exists( keyfile ))
        !          1618:                                {       fprintf(pgpout, PSTR("\n\007Key file '%s' does not exist.\n"), keyfile );
        !          1619:                                        errorLvl = NONEXIST_KEY_ERROR;
        !          1620:                                        return -1;
        !          1621:                                }
        !          1622: 
        !          1623:                                workfile = keyfile;
        !          1624: 
        !          1625:                        } else {
        !          1626:                                workfile = tempfile(TMP_WIPE|TMP_TMPDIR);
        !          1627:                                readPhantomInput(workfile);
1.1.1.3   root     1628:                        }
                   1629: 
1.1.1.4 ! root     1630:                        if (myArgc < (filter_mode ? 3 : 4)) /* default key ring filename */
1.1.1.3   root     1631:                        {       byte ctb;
1.1.1.4 ! root     1632:                                get_header_info_from_file(workfile, &ctb, 1);
1.1.1.3   root     1633:                                if (ctb == CTB_CERT_SECKEY)
                   1634:                                        buildfilename(ringfile,SECRET_KEYRING_FILENAME);
                   1635:                                else
                   1636:                                        buildfilename(ringfile,PUBLIC_KEYRING_FILENAME);
                   1637:                        }
                   1638:                        else
1.1.1.4 ! root     1639:                        {       strncpy( ringfile, myArgv[(filter_mode ? 2 : 3)], sizeof(ringfile)-1 );
1.1.1.3   root     1640:                                default_extension( ringfile, PGP_EXTENSION );
                   1641:                        }
                   1642: #ifdef MSDOS
                   1643:                        strlwr( ringfile );
                   1644: #endif
                   1645: 
1.1.1.4 ! root     1646:                        status = addto_keyring( workfile, ringfile);
        !          1647: 
        !          1648:                        if (filter_mode)
        !          1649:                                rmtemp(workfile);
1.1.1.3   root     1650: 
                   1651:                        if (status < 0)
                   1652:                        {       fprintf(pgpout, PSTR("\007Keyring add error. ") );
                   1653:                                errorLvl = KEYRING_ADD_ERROR;
                   1654:                        }
1.1.1.4 ! root     1655:                        return status;
1.1.1.3   root     1656:                }       /* Add key to key ring */
                   1657: 
                   1658:                /*-------------------------------------------------------*/
                   1659:                case 'x':
                   1660:                {       /*      Extract key from key ring
                   1661:                                Arguments: mcguffin, keyfile, ringfile
                   1662:                        */
                   1663: 
1.1.1.4 ! root     1664:                        if (myArgc >= (filter_mode ? 4 : 5))    /* default key ring filename */
        !          1665:                                strncpy( ringfile, myArgv[(filter_mode ? 3 : 4)], sizeof(ringfile)-1 );
1.1.1.3   root     1666:                        else
                   1667:                                buildfilename( ringfile, PUBLIC_KEYRING_FILENAME );
                   1668: 
1.1.1.4 ! root     1669:                        if (myArgc >= (filter_mode ? 2 : 3))
        !          1670:                        {       if (myArgv[2])
        !          1671:                                        /* Userid to extract */
        !          1672:                                        strcpy( mcguffin, myArgv[2] );  
        !          1673:                                else
        !          1674:                                        strcpy( mcguffin, "" );
        !          1675:                        }
1.1.1.3   root     1676:                        else
                   1677:                        {
                   1678:                                fprintf(pgpout, PSTR("\nA user ID is required to select the key you want to extract. "));
1.1.1.4 ! root     1679:                                if (batchmode)  /* not interactive, userid must be on command line */
        !          1680:                                        return -1;
1.1.1.3   root     1681:                                fprintf(pgpout, PSTR("\nEnter the key's user ID: "));
                   1682:                                getstring( mcguffin, 255, TRUE );       /* echo keyboard */
                   1683:                        }
                   1684:                        CONVERT_TO_CANONICAL_CHARSET(mcguffin);
                   1685: 
1.1.1.4 ! root     1686:                        if (!filter_mode) {
        !          1687:                                if (myArgc >= 4)
        !          1688:                                {       strncpy( keyfile, myArgv[3], sizeof(keyfile)-1 );
        !          1689:                                }
        !          1690:                                else
        !          1691:                                        keyfile[0] = '\0';
        !          1692: 
        !          1693:                                workfile = keyfile;
        !          1694:                        } else {
        !          1695:                                workfile = tempfile(TMP_WIPE|TMP_TMPDIR);
1.1.1.3   root     1696:                        }
                   1697: 
                   1698: #ifdef MSDOS
1.1.1.4 ! root     1699:                        strlwr( workfile );
1.1.1.3   root     1700:                        strlwr( ringfile );
                   1701: #endif
                   1702: 
                   1703:                        default_extension( ringfile, PGP_EXTENSION );
                   1704: 
1.1.1.4 ! root     1705:                        status = extract_from_keyring( mcguffin, workfile,
        !          1706:                                        ringfile, (filter_mode ? FALSE :
        !          1707:                                                   emit_radix_64) );
1.1.1.3   root     1708: 
                   1709:                        if (status < 0)
                   1710:                        {       fprintf(pgpout, PSTR("\007Keyring extract error. ") );
                   1711:                                errorLvl = KEYRING_EXTRACT_ERROR;
1.1.1.4 ! root     1712:                                if (filter_mode)
        !          1713:                                        rmtemp(workfile);
        !          1714:                                return status;
1.1.1.3   root     1715:                        }
1.1.1.4 ! root     1716: 
        !          1717: 
        !          1718:                        if (filter_mode && !status) {
        !          1719:                                if (emit_radix_64)
        !          1720:                                {       /* NULL for outputfile means write to stdout */
        !          1721:                                        if (armor_file(workfile, NULL, NULL, NULL) != 0)
        !          1722:                                        {       errorLvl = UNKNOWN_FILE_ERROR;
        !          1723:                                                return -1;
        !          1724:                                        }
        !          1725:                                }
        !          1726:                                else
        !          1727:                                        if (writePhantomOutput(workfile) < 0)
        !          1728:                                        {       errorLvl = UNKNOWN_FILE_ERROR;
        !          1729:                                                return -1;
        !          1730:                                        }
        !          1731:                                rmtemp(workfile);
        !          1732:                        }
        !          1733: 
        !          1734:                        return 0;
1.1.1.3   root     1735:                }       /* Extract key from key ring */
                   1736: 
                   1737:                /*-------------------------------------------------------*/
                   1738:                case 'r':
                   1739:                {       /*      Remove keys or selected key signatures from userid keys
                   1740:                                Arguments: userid, ringfile
                   1741:                        */
                   1742: 
                   1743:                        if (myArgc >= 4)
                   1744:                                strcpy( ringfile, myArgv[3] );
                   1745:                        else    /* default key ring filename */
                   1746:                                buildfilename( ringfile, PUBLIC_KEYRING_FILENAME );
                   1747: 
                   1748:                        if (myArgc >= 3)
                   1749:                                strcpy( mcguffin, myArgv[2] );  /* Userid to work on */
                   1750:                        else
                   1751:                        {       if (sign_flag)
                   1752:                                {
                   1753:                                        fprintf(pgpout, PSTR("\nA user ID is required to select the public key you want to\n\
                   1754: remove certifying signatures from. "));
                   1755:                                }
                   1756:                                else
                   1757:                                {
                   1758:                                        fprintf(pgpout, PSTR("\nA user ID is required to select the key you want to remove. "));
                   1759:                                }
1.1.1.4 ! root     1760:                                if (batchmode)  /* not interactive, userid must be on command line */
        !          1761:                                        return -1;
1.1.1.3   root     1762:                                fprintf(pgpout, PSTR("\nEnter the key's user ID: "));
                   1763:                                getstring( mcguffin, 255, TRUE );       /* echo keyboard */
                   1764:                        }
                   1765:                        CONVERT_TO_CANONICAL_CHARSET(mcguffin);
                   1766: 
                   1767: #ifdef MSDOS
                   1768:                        strlwr( ringfile );
                   1769: #endif
                   1770:                        if (! file_exists( ringfile ))
                   1771:                                default_extension( ringfile, PGP_EXTENSION );
                   1772: 
                   1773:                        if (sign_flag)          /* Remove signatures */
                   1774:                        {       if (remove_sigs( mcguffin, ringfile ) < 0)
                   1775:                                {       fprintf(pgpout, PSTR("\007Key signature remove error. ") );
                   1776:                                        errorLvl = KEYSIG_REMOVE_ERROR;
1.1.1.4 ! root     1777:                                        return -1;
1.1.1.3   root     1778:                                }
                   1779:                        }
                   1780:                        else            /* Remove keyring */
                   1781:                        {       if (remove_from_keyring( NULL, mcguffin, ringfile, (boolean) (myArgc < 4) ) < 0)
                   1782:                                {       fprintf(pgpout, PSTR("\007Keyring remove error. ") );
                   1783:                                        errorLvl = KEYRING_REMOVE_ERROR;
1.1.1.4 ! root     1784:                                        return -1;
1.1.1.3   root     1785:                                }
                   1786:                        }
1.1.1.4 ! root     1787:                        return 0;
1.1.1.3   root     1788:                }       /* remove key signatures from userid */
                   1789: 
                   1790:                /*-------------------------------------------------------*/
                   1791:                case 'v':
                   1792:                case 'V':               /* -kvv */
                   1793:                {       /*      View or remove key ring entries, with userid match
                   1794:                                Arguments: userid, ringfile
                   1795:                        */
                   1796: 
                   1797:                        if (myArgc < 4) /* default key ring filename */
                   1798:                                buildfilename( ringfile, PUBLIC_KEYRING_FILENAME );
                   1799:                        else
                   1800:                                strcpy( ringfile, myArgv[3] );
                   1801: 
                   1802:                        if (myArgc > 2)
                   1803:                        {       strcpy( mcguffin, myArgv[2] );
                   1804:                                if (strcmp( mcguffin, "*" ) == 0)
                   1805:                                        mcguffin[0] = '\0';
                   1806:                        }
                   1807:                        else
                   1808:                                *mcguffin = '\0';
                   1809: 
                   1810:                        if ((myArgc == 3) && has_extension( myArgv[2], PGP_EXTENSION ))
                   1811:                        {       strcpy( ringfile, myArgv[2] );
                   1812:                                mcguffin[0] = '\0';
                   1813:                        }
                   1814:                        CONVERT_TO_CANONICAL_CHARSET(mcguffin);
                   1815: 
                   1816: #ifdef MSDOS
                   1817:                        strlwr( ringfile );
                   1818: #endif
                   1819:                        if (! file_exists( ringfile ))
                   1820:                                default_extension( ringfile, PGP_EXTENSION );
                   1821: 
                   1822:                        /* If a second 'v' (keychar = V), show signatures too */
1.1.1.4 ! root     1823:                        status = view_keyring(mcguffin, ringfile, (boolean) (keychar == 'V'), c_flag);
        !          1824:                        if (status < 0)
1.1.1.3   root     1825:                        {       fprintf(pgpout, PSTR("\007Keyring view error. ") );
                   1826:                                errorLvl = KEYRING_VIEW_ERROR;
                   1827:                        }
1.1.1.4 ! root     1828:                        return status;
1.1.1.3   root     1829:                }       /* view key ring entries, with userid match */
                   1830: 
                   1831:                default:
                   1832:                        arg_error();
                   1833:        }
1.1.1.4 ! root     1834:        return 0;
1.1.1.3   root     1835: } /* do_keyopt */
                   1836: 
                   1837: 
                   1838: 
                   1839: void user_error() /* comes here if user made a boo-boo. */
                   1840: {
                   1841:        fprintf(pgpout,PSTR("\nFor a usage summary, type:  pgp -h\n"));
                   1842:        fprintf(pgpout,PSTR("For more detailed help, consult the PGP User's Guide.\n"));
1.1.1.4 ! root     1843:        exitPGP(errorLvl ? errorLvl : 127);             /* error exit */
1.1.1.3   root     1844: }
                   1845: 
1.1.1.4 ! root     1846: #if defined(DEBUG) && defined(linux)
        !          1847: #include <malloc.h>
        !          1848: #endif
1.1.1.3   root     1849: /*
                   1850:  * exitPGP: wipes and removes temporary files, also tries to wipe
                   1851:  * the stack.
                   1852:  */
                   1853: void exitPGP(int returnval)
                   1854: {
                   1855:        char buf[STACK_WIPE];
                   1856: 
                   1857:        if (verbose)
                   1858:                fprintf(pgpout, "exitPGP: exitcode = %d\n", returnval);
                   1859:        memset(password, 0, sizeof(password));
                   1860:        cleanup_tmpf();
1.1.1.4 ! root     1861: #if defined(DEBUG) && defined(linux)
        !          1862:        if (verbose)
        !          1863:        {       struct mstats mstat;
        !          1864:                mstat = mstats();
        !          1865:                printf("%d chunks used (%d bytes)  %d bytes total\n",
        !          1866:                        mstat.chunks_used, mstat.bytes_used, mstat.bytes_total);
        !          1867:        }
        !          1868: #endif
1.1.1.3   root     1869:        memset(buf, 0, sizeof(buf));    /* wipe stack */
                   1870: #ifdef VMS
                   1871: /*
                   1872:  * Fake VMS style error returns with severity in bottom 3 bits
                   1873:  */
                   1874:        if (returnval)
                   1875:            returnval = (returnval << 3) | 0x10000002;
                   1876:        else
                   1877:            returnval = 0x10000001;
                   1878: #endif /* VMS */
                   1879:        exit(returnval);
                   1880: }
                   1881: 
                   1882: 
                   1883: static void arg_error()
                   1884: {
                   1885:        signon_msg();
                   1886:        fprintf(pgpout,PSTR("\nInvalid arguments.\n"));
                   1887:        errorLvl = BAD_ARG_ERROR;
                   1888:        user_error();
                   1889: }
                   1890: 
                   1891: static void build_helpfile(char *helpfile)
                   1892: {
                   1893:        if (strcmp(language, "en"))
                   1894:        {       buildfilename(helpfile, language);
                   1895:                force_extension(helpfile, HLP_EXTENSION);
                   1896:                if (!file_exists(helpfile))
                   1897:                        buildfilename(helpfile, HELP_FILENAME);
                   1898:        }
                   1899:        else
                   1900:                buildfilename(helpfile, HELP_FILENAME);
                   1901: }
                   1902: 
                   1903: static void usage()
                   1904: {
                   1905:        char helpfile[MAX_PATH];
                   1906:        char *tmphelp = helpfile;
                   1907:        extern unsigned char *ext_c_ptr;
                   1908: 
                   1909:        signon_msg();
                   1910:        build_helpfile(helpfile);
                   1911:   
                   1912:        if (ext_c_ptr)
                   1913:        {       /* conversion to external format necessary */
                   1914:                tmphelp = tempfile(TMP_TMPDIR);
                   1915:                CONVERSION = EXT_CONV;
                   1916:                if (copyfiles_by_name(helpfile, tmphelp) < 0)
                   1917:                        tmphelp = helpfile;
                   1918:                CONVERSION = NO_CONV;
                   1919:        }
                   1920: 
                   1921:          /* built-in help if pgp.hlp is not available */
                   1922:        if (more_file(tmphelp) < 0)
                   1923:                fprintf(pgpout,PSTR("\nUsage summary:\
                   1924: \nTo encrypt a plaintext file with recipent's public key, type:\
1.1.1.4 ! root     1925: \n   pgp -e textfile her_userid [other userids] (produces textfile.pgp)\
1.1.1.3   root     1926: \nTo sign a plaintext file with your secret key:\
                   1927: \n   pgp -s textfile [-u your_userid]           (produces textfile.pgp)\
                   1928: \nTo sign a plaintext file with your secret key, and then encrypt it\
                   1929: \n   with recipent's public key, producing a .pgp file:\
1.1.1.4 ! root     1930: \n   pgp -es textfile her_userid [other userids] [-u your_userid]\
1.1.1.3   root     1931: \nTo encrypt with conventional encryption only:\
                   1932: \n   pgp -c textfile\
                   1933: \nTo decrypt or check a signature for a ciphertext (.pgp) file:\
                   1934: \n   pgp ciphertextfile [plaintextfile]\
                   1935: \nTo produce output in ASCII for email, add the -a option to other options.\
                   1936: \nTo generate your own unique public/secret key pair:  pgp -kg\
                   1937: \nFor help on other key management functions, type:   pgp -k\n"));
                   1938:        if (ext_c_ptr)
                   1939:                rmtemp(tmphelp);
                   1940:        exit(BAD_ARG_ERROR);            /* error exit */
                   1941: }
                   1942: 
                   1943: 
                   1944: static void key_usage()
                   1945: {
                   1946:        char helpfile[MAX_PATH];
                   1947: 
                   1948:        signon_msg();
                   1949:        build_helpfile(helpfile);
                   1950:        if (file_exists(helpfile))
                   1951:        {       fprintf(pgpout,PSTR("\nFor a usage summary, type:  pgp -h\n"));
                   1952:                fprintf(pgpout,PSTR("For more detailed help, consult the PGP User's Guide.\n"));
                   1953:        }
1.1.1.4 ! root     1954:        else    /* only use built-in help if there is no helpfile */
1.1.1.3   root     1955:                fprintf(pgpout,PSTR("\nKey management functions:\
                   1956: \nTo generate your own unique public/secret key pair:\
                   1957: \n   pgp -kg\
                   1958: \nTo add a key file's contents to your public or secret key ring:\
                   1959: \n   pgp -ka keyfile [keyring]\
                   1960: \nTo remove a key or a user ID from your public or secret key ring:\
                   1961: \n   pgp -kr userid [keyring]\
                   1962: \nTo edit your user ID or pass phrase:\
                   1963: \n   pgp -ke your_userid [keyring]\
                   1964: \nTo extract (copy) a key from your public or secret key ring:\
                   1965: \n   pgp -kx userid keyfile [keyring]\
                   1966: \nTo view the contents of your public key ring:\
                   1967: \n   pgp -kv[v] [userid] [keyring]\
                   1968: \nTo check signatures on your public key ring:\
                   1969: \n   pgp -kc [userid] [keyring]\
                   1970: \nTo sign someone else's public key on your public key ring:\
                   1971: \n   pgp -ks her_userid [-u your_userid] [keyring]\
                   1972: \nTo remove selected signatures from a userid on a keyring:\
                   1973: \n   pgp -krs userid [keyring]\
                   1974: \n"));
                   1975:        exit(BAD_ARG_ERROR);            /* error exit */
                   1976: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.