--- pgp/src/armor.c 2018/04/24 16:38:54 1.1.1.2 +++ pgp/src/armor.c 2018/04/24 16:39:37 1.1.1.3 @@ -26,6 +26,15 @@ #include "mpiio.h" #include "language.h" #include "pgp.h" +#include "crypto.h" +#include "armor.h" + +static int dpem_file(char *infile, char *outfile); +static crcword crchware(byte ch, crcword poly, crcword accum); +static int pem_file(char *infilename, char *outfilename, char *clearfilename); +static int pemdecode(FILE *in, FILE *out); +static void mk_crctbl(crcword poly); +static boolean is_pemfile(char *infile); /* Begin PEM routines. This converts a binary file into printable ASCII characters, in a @@ -36,12 +45,14 @@ /* Index this array by a 6 bit value to get the character corresponding * to that value. */ +static unsigned char bintoasc[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ\ abcdefghijklmnopqrstuvwxyz0123456789+/"; /* Index this array by a 7 bit value to get the 6-bit binary field * corresponding to that value. Any illegal characters return high bit set. */ +static unsigned char asctobin[] = { 0200,0200,0200,0200,0200,0200,0200,0200, 0200,0200,0200,0200,0200,0200,0200,0200, @@ -73,8 +84,6 @@ static long infile_line; /* Current lin #define byte unsigned char #define CRCBITS 24 /* may be 16, 24, or 32 */ -/* #define crcword unsigned short */ /* if CRCBITS is 16 */ -#define crcword unsigned long /* if CRCBITS is 24 or 32 */ /* #define maskcrc(crc) ((crcword)(crc)) */ /* if CRCBITS is 16 or 32 */ #define maskcrc(crc) ((crc) & 0xffffffL) /* if CRCBITS is 24 */ #define CRCHIBIT ((crcword) (1L<<(CRCBITS-1))) /* 0x8000 if CRCBITS is 16 */ @@ -105,6 +114,7 @@ static long infile_line; /* Current lin #define PRZCRC 0x864cfbL /* PRZ's 24-bit CRC generator polynomial */ #define CRCINIT 0xB704CEL /* Init value for CRC accumulator */ +static crcword crctable[256]; /* Table for speeding up CRC's */ /* crchware simulates CRC hardware circuit. Generates true CRC @@ -112,6 +122,7 @@ crcword crctable[256]; /* Table for spe to the message. Returns new updated CRC accumulator. */ +static crcword crchware(byte ch, crcword poly, crcword accum) { int i; crcword data; @@ -134,6 +145,7 @@ crcword crchware(byte ch, crcword poly, The table is used later by crcupdate function given below. mk_crctbl only needs to be called once at the dawn of time. */ +static void mk_crctbl(crcword poly) { int i; for (i=0; i<256; i++) @@ -154,7 +166,7 @@ crcword crcupdate(byte data, register cr } /* crcupdate */ /* Initialize the CRC table using our codes */ -void init_crc() +void init_crc(void) { mk_crctbl(PRZCRC); } @@ -224,6 +236,38 @@ static char *numFilename( char *fname, i return(fnamenum); } +/* + * Read a line from file f, buf must be able to hold at least 80 characters. + * Strips trailing spaces, can read LF, CRLF and CR textfiles. + */ +static char * +get_armor_line(char *buf, FILE *f) +{ + int c, n = 79; + char *p = buf; + + do { + c = getc(f); + if (c == '\n' || c == '\r' || c == EOF) + break; + *p++ = c; + } while (--n > 0); + if (p == buf && c == EOF) + { *buf = '\0'; + return NULL; + } + /* skip to end of line */ + while (c != '\n' && c != '\r' && c != EOF) + c = getc(f); + if (c == '\r' && (c = getc(f)) != '\n') + ungetc(c, f); + while (--p >= buf && *p == ' ') + ; + *++p = '\0'; + return buf; +} + + /* Encode a file in sections. 64 ASCII bytes * 720 lines = 46K, recommended max. Usenet message size is 50K so this leaves a nice margin for .signature. In the interests of orthogonality and @@ -250,6 +294,7 @@ extern boolean filter_mode; * If clearfilename is non-NULL, first output that file preceded by a * special header line. */ +static int pem_file(char *infilename, char *outfilename, char *clearfilename) { char buffer[MAX_LINE_SIZE]; @@ -274,6 +319,12 @@ int pem_file(char *infilename, char *out fileLen = ftell(inFile); rewind(inFile); noSections = (fileLen + BYTES_PER_SECTION - 1) / BYTES_PER_SECTION; + if (noSections > 99) + { + pem_lines = ((fileLen+LINE_LEN-1)/LINE_LEN + 98) / 99; + noSections = (fileLen + BYTES_PER_SECTION - 1) / BYTES_PER_SECTION; + fprintf(pgpout, "value for \"armorlines\" is too low, using %d\n", pem_lines); + } } if (outfilename == NULL) @@ -301,8 +352,12 @@ int pem_file(char *infilename, char *out } fprintf (outFile, "-----BEGIN PGP SIGNED MESSAGE-----\n\n"); while (fgets(buffer, sizeof(buffer), clearFile) != NULL) - { /* Quote lines beginning with '-' */ - if (buffer[0] == '-') + { + /* Quote lines beginning with '-' as per RFC1113; + * Also quote lines beginning with "From "; + * this is for Unix systems which add ">" to such lines. + */ + if (buffer[0] == '-' || (strncmp(buffer, "From ", 5)==0)) fputs("- ", outFile); fputs(buffer, outFile); } @@ -393,7 +448,7 @@ int pem_file(char *infilename, char *out else if (noSections == 1) fprintf (pgpout, PSTR("\nTransport armor file: %s\n"), outfilename); else - { int i; + { fprintf (pgpout, PSTR("\nTransport armor files: ")); for (i=1; i<=noSections; ++i) fprintf (pgpout, "%s%s", numFilename(outfilename,i), @@ -402,33 +457,13 @@ int pem_file(char *infilename, char *out return(0); } /* pem_file */ - - - - /* End PEM encode routines. */ + /* PEM decode routines. */ -#define MAX_RETRY_LINES 100 - -/* Strip trailing spaces and CR characters */ -void -strip_trailing (char *buf) -{ - char *bp = buf; - while (*bp++ != '\n') /* Find end of line */ - ; - --bp; --bp; /* And back up... */ - /* Back up over spaces & CR */ - while (bp >= buf && (*bp == ' ' || *bp == '\r')) - --bp; - bp[1] = '\n'; /* Terminate line cleanly */ - bp[2] = '\0'; -} - - +static int dpem_buffer(char *inbuf, char *outbuf, int *outlength) { unsigned char *bp; @@ -436,13 +471,12 @@ int dpem_buffer(char *inbuf, char *outbu unsigned int c1,c2,c3,c4; register int j; - strip_trailing(inbuf); length = 0; bp = (unsigned char *)inbuf; /* FOUR input characters go into each THREE output charcters */ - while (*bp!='\0' && *bp!='\n' && *bp!='\r') + while (*bp!='\0') { if (*bp&0x80 || (c1=asctobin[*bp])&0x80) return -1; ++bp; @@ -486,7 +520,7 @@ static char pemfilename[MAX_PATH]; * the sequence number is expected at the end of the file name */ static FILE * -open_next() +open_next(void) { char *p, *s, c; FILE *fp; @@ -523,9 +557,10 @@ open_next() * Copy from in to out, decoding as you go, with handling for multiple * 500-line blocks of encoded data. */ +static int pemdecode(FILE *in, FILE *out) { -char inbuf[MAX_LINE_SIZE]; +char inbuf[80]; char outbuf[80]; int i, n, status; @@ -533,23 +568,23 @@ int line; int section, currentSection = 1; int noSections = 0; int gotcrc = 0; -long crc=CRCINIT, chkcrc; +long crc=CRCINIT, chkcrc = -1; char crcbuf[4]; int ret_code = 0; +int end_of_message; init_crc(); for (line = 1; ; line++) /* for each input line */ { - if (fgets(inbuf, sizeof(inbuf), in) == NULL) - { - fprintf(pgpout,PSTR("ERROR: ASCII armor decode input ended unexpectedly!\n")); - return(18); + if (get_armor_line(inbuf, in) == NULL) + end_of_message = 1; + else + { end_of_message = (strncmp(inbuf,"-----END PGP MESSAGE,", 21) == 0); + ++infile_line; } - ++infile_line; - if (currentSection!=noSections && - strncmp(inbuf,"-----END PGP MESSAGE,", 21) == 0) + if (currentSection!=noSections && end_of_message) { /* End of this section */ if (gotcrc) { if (chkcrc != crc) @@ -563,7 +598,7 @@ int ret_code = 0; /* Try and find start of next section */ do - { if (fgets(inbuf,sizeof(inbuf),in) == NULL) + { if (get_armor_line(inbuf,in) == NULL) { FILE *nextf; if ((nextf = open_next()) != NULL) { @@ -597,13 +632,13 @@ int ret_code = 0; /* Skip header after BEGIN line */ do { ++infile_line; - if (fgets(inbuf, sizeof inbuf, in) == NULL) + if (get_armor_line(inbuf, in) == NULL) { fprintf(pgpout,PSTR("ERROR: Hit EOF in header of section %d.\n"), currentSection); return(-1); } - } while (inbuf[0] != '\n' && inbuf[0] != '\r'); + } while (inbuf[0] != '\0'); /* Continue decoding */ continue; @@ -622,7 +657,7 @@ int ret_code = 0; gotcrc = 1; continue; } - if (inbuf[0] == '\n' || inbuf[0] == '\r') + if (inbuf[0] == '\0') { fprintf(pgpout,PSTR("WARNING: No ASCII armor `END' line.\n")); break; } @@ -668,12 +703,13 @@ int ret_code = 0; } /* pemdecode */ +static boolean is_pemfile(char *infile) { FILE *in; - char inbuf[MAX_LINE_SIZE]; + char inbuf[80]; char outbuf[80]; - int i, n, status; + int n, status; long il; if ((in = fopen(infile, FOPRTXT)) == NULL) @@ -684,7 +720,7 @@ boolean is_pemfile(char *infile) /* Read to infile_line before we begin looking */ for (il=0; il