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

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

unix.superglobalmegacorp.com

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