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

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

unix.superglobalmegacorp.com

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