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

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

unix.superglobalmegacorp.com

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