|
|
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: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.