|
|
1.1 root 1: /*
2: * unseal - disclose and verify the contents of a sealed package
3: */
4:
5: #include "asd.h"
6: #include "seal.h"
7: #include <ctype.h>
8: #include <string.h>
9: #include <unistd.h>
10:
11: static FILE *outfd;
12: static char outf[L_tmpnam];
13: static char line[MAXULINE];
14:
15: static unsigned long length, checksum;
16:
17: static char *
18: csverify (char *p, unsigned long value)
19: {
20: register unsigned long n = 0;
21:
22: while (isspace (*p))
23: p++;
24:
25: if (!isdigit (*p))
26: return NULL;
27:
28: do n = n * 10 + *p++ - '0';
29: while (isdigit (*p));
30:
31: if (!isspace (*p))
32: return NULL;
33:
34: if (n != value)
35: return NULL;
36:
37: return p;
38: }
39:
40: int
41: docksum (char *line, unsigned long length, unsigned long checksum)
42: {
43: register char *p = line + 5;
44:
45: p = csverify (p, length);
46: if (p == NULL) {
47: fprintf (stderr, "unseal: invalid length\n");
48: return 1;
49: }
50: p = csverify (p, checksum);
51: if (p == NULL) {
52: fprintf (stderr, "unseal: invalid checksum\n");
53: return 1;
54: }
55: return 0;
56: }
57:
58: static int
59: unhex (int c)
60: {
61: register char *p;
62:
63: p = hextab;
64: while (*p && *p != c)
65: p++;
66: if (*p)
67: return p - hextab;
68: return -1;
69: }
70:
71: static int
72: hrout (char *line, char *out)
73: {
74: register char *p, *q;
75: register int ch;
76:
77: p = line;
78: q = out;
79:
80: while ((ch = *p++) != '\0') {
81: if (ch != '\\') {
82: *q++ = ch;
83: } else {
84: ch = *p++;
85: if (ch == '\\' || ch == '.' || ch == '!' || ch == 'F') {
86: *q++ = ch;
87: } else if (ch != '\n') {
88: register int n = 0, i = 1;
89:
90: do {
91: ch = unhex (ch);
92: if (ch < 0) {
93: fprintf (stderr,
94: "bad hex char: %s", line);
95: return -1;
96: }
97: n = (n << 4) | ch;
98: if (i)
99: ch = *p++;
100: } while (--i >= 0);
101:
102: *q++ = n;
103: }
104: }
105: }
106:
107: return q - out;
108: }
109:
110: static int
111: mrout (char *line, char *out)
112: {
113: register char *p = line + 1;
114: char *q = out;
115:
116: while (*p != '\n' && *p != '\0') {
117: register unsigned long bits;
118: register int n;
119: register char *rq;
120:
121: n = 0;
122: bits = 0;
123: do {
124: register int ch = *p++;
125: if (ch == '\n')
126: break;
127: if (ch < RADBASE || ch >= RADBASE + RADIX) {
128: fprintf (stderr, "bad input char: %s", line);
129: return -1;
130: }
131: bits = bits * RADIX + ch - RADBASE;
132: n++;
133: } while (n < OUTCPW);
134:
135: n -= OUTCPW - INCPW;
136: if (n <= 0) {
137: fprintf (stderr, "non-positive output count: %s", line);
138: return -1;
139: }
140:
141: rq = q = q + n;
142: do {
143: *--rq = bits;
144: bits >>= BPC;
145: } while (--n > 0);
146: }
147:
148: return q - out;
149: }
150:
151: static int
152: dodata (char *line)
153: {
154: char out[MAXULINE * 2];
155: int r;
156:
157: r = (*(line[0] == '.'? mrout : hrout)) (line, out);
158: if (r < 0)
159: return 1;
160: fwrite (out, sizeof(*out), r, outfd);
161: length += r;
162:
163: if (kflag || Kflag)
164: mangle (out, out + r);
165:
166: checksum = mkcsum (checksum, out, out + r);
167:
168: return 0;
169: }
170:
171: static int
172: unseal (FILE *f, char *fname)
173: {
174: int intext = 0, rc = 0, nulltext = 1;
175:
176: length = checksum = 0;
177: resetN12();
178:
179: while (fgets (line, MAXULINE, f) != NULL) {
180:
181: /* check for a control line, which starts with "!" */
182: if (line[0] == '!') {
183: if (intext) {
184: /* only thing allowed is !end */
185: if (strncmp (line + 1, "end ", 4) == 0) {
186: rc += docksum (line, length, checksum);
187: intext = 0;
188: } else {
189: fprintf (stderr, "invalid control line %s", line);
190: rc++;
191: }
192: } else {
193: /* look for header, else quietly ignore */
194: if (strcmp (line + 1, "<seal>\n") == 0) {
195: intext++;
196: nulltext = 0;
197: }
198: }
199: /* data lines are quietly ignored if not in text */
200: } else if (intext) {
201: rc += dodata (line);
202: }
203: }
204:
205: if (nulltext) {
206: fprintf (stderr, "unseal: no contents\n");
207: rc++;
208: }
209:
210: if (intext) {
211: fprintf (stderr, "unseal: no checksum\n");
212: rc++;
213: }
214:
215: return rc;
216: }
217:
218: int
219: main (int argc, char **argv)
220: {
221: int rc = 0;
222: int c;
223: static char stdbuf[BUFSIZ];
224:
225: setbuf (stdout, stdbuf);
226:
227: umask (077);
228: tmpnam (outf);
229: outfd = fopen (outf, "w+");
230: if (outfd == NULL) {
231: fprintf (stderr, "unseal: can't create temp file\n");
232: exit (1);
233: }
234:
235: /* don't leave dregs */
236: unlink (outf);
237:
238: rc = getargs (argc, argv, "kK:", unseal);
239:
240: /* if successful, copy the temp file to the output */
241: if (rc == 0) {
242: register FILE *in = outfd, *out = stdout;
243: register int ch;
244:
245: rewind (in);
246:
247: while ((ch = getc (in)) != EOF)
248: putc (ch, out);
249:
250: fflush (out);
251:
252: if (ferror (in)) {
253: fprintf (stderr, "unseal: error reading temp file\n");
254: rc++;
255: }
256:
257: if (ferror (out)) {
258: fprintf (stderr, "unseal: error writing stdout\n");
259: rc++;
260: }
261: }
262:
263: return rc;
264: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.