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