|
|
researchv10 Norman
/*
* unseal - disclose and verify the contents of a sealed package
*/
#include "asd.h"
#include "seal.h"
#include <ctype.h>
#include <string.h>
#include <unistd.h>
static FILE *outfd;
static char outf[L_tmpnam];
static char line[MAXULINE];
static unsigned long length, checksum;
static char *
csverify (char *p, unsigned long value)
{
register unsigned long n = 0;
while (isspace (*p))
p++;
if (!isdigit (*p))
return NULL;
do n = n * 10 + *p++ - '0';
while (isdigit (*p));
if (!isspace (*p))
return NULL;
if (n != value)
return NULL;
return p;
}
int
docksum (char *line, unsigned long length, unsigned long checksum)
{
register char *p = line + 5;
p = csverify (p, length);
if (p == NULL) {
fprintf (stderr, "unseal: invalid length\n");
return 1;
}
p = csverify (p, checksum);
if (p == NULL) {
fprintf (stderr, "unseal: invalid checksum\n");
return 1;
}
return 0;
}
static int
unhex (int c)
{
register char *p;
p = hextab;
while (*p && *p != c)
p++;
if (*p)
return p - hextab;
return -1;
}
static int
hrout (char *line, char *out)
{
register char *p, *q;
register int ch;
p = line;
q = out;
while ((ch = *p++) != '\0') {
if (ch != '\\') {
*q++ = ch;
} else {
ch = *p++;
if (ch == '\\' || ch == '.' || ch == '!' || ch == 'F') {
*q++ = ch;
} else if (ch != '\n') {
register int n = 0, i = 1;
do {
ch = unhex (ch);
if (ch < 0) {
fprintf (stderr,
"bad hex char: %s", line);
return -1;
}
n = (n << 4) | ch;
if (i)
ch = *p++;
} while (--i >= 0);
*q++ = n;
}
}
}
return q - out;
}
static int
mrout (char *line, char *out)
{
register char *p = line + 1;
char *q = out;
while (*p != '\n' && *p != '\0') {
register unsigned long bits;
register int n;
register char *rq;
n = 0;
bits = 0;
do {
register int ch = *p++;
if (ch == '\n')
break;
if (ch < RADBASE || ch >= RADBASE + RADIX) {
fprintf (stderr, "bad input char: %s", line);
return -1;
}
bits = bits * RADIX + ch - RADBASE;
n++;
} while (n < OUTCPW);
n -= OUTCPW - INCPW;
if (n <= 0) {
fprintf (stderr, "non-positive output count: %s", line);
return -1;
}
rq = q = q + n;
do {
*--rq = bits;
bits >>= BPC;
} while (--n > 0);
}
return q - out;
}
static int
dodata (char *line)
{
char out[MAXULINE * 2];
int r;
r = (*(line[0] == '.'? mrout : hrout)) (line, out);
if (r < 0)
return 1;
fwrite (out, sizeof(*out), r, outfd);
length += r;
if (kflag || Kflag)
mangle (out, out + r);
checksum = mkcsum (checksum, out, out + r);
return 0;
}
static int
unseal (FILE *f, char *fname)
{
int intext = 0, rc = 0, nulltext = 1;
length = checksum = 0;
resetN12();
while (fgets (line, MAXULINE, f) != NULL) {
/* check for a control line, which starts with "!" */
if (line[0] == '!') {
if (intext) {
/* only thing allowed is !end */
if (strncmp (line + 1, "end ", 4) == 0) {
rc += docksum (line, length, checksum);
intext = 0;
} else {
fprintf (stderr, "invalid control line %s", line);
rc++;
}
} else {
/* look for header, else quietly ignore */
if (strcmp (line + 1, "<seal>\n") == 0) {
intext++;
nulltext = 0;
}
}
/* data lines are quietly ignored if not in text */
} else if (intext) {
rc += dodata (line);
}
}
if (nulltext) {
fprintf (stderr, "unseal: no contents\n");
rc++;
}
if (intext) {
fprintf (stderr, "unseal: no checksum\n");
rc++;
}
return rc;
}
int
main (int argc, char **argv)
{
int rc = 0;
int c;
static char stdbuf[BUFSIZ];
setbuf (stdout, stdbuf);
umask (077);
tmpnam (outf);
outfd = fopen (outf, "w+");
if (outfd == NULL) {
fprintf (stderr, "unseal: can't create temp file\n");
exit (1);
}
/* don't leave dregs */
unlink (outf);
rc = getargs (argc, argv, "kK:", unseal);
/* if successful, copy the temp file to the output */
if (rc == 0) {
register FILE *in = outfd, *out = stdout;
register int ch;
rewind (in);
while ((ch = getc (in)) != EOF)
putc (ch, out);
fflush (out);
if (ferror (in)) {
fprintf (stderr, "unseal: error reading temp file\n");
rc++;
}
if (ferror (out)) {
fprintf (stderr, "unseal: error writing stdout\n");
rc++;
}
}
return rc;
}
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.