1*b7041c07Sderaadt /* $OpenBSD: keynote-verify.c,v 1.20 2021/10/24 21:24:20 deraadt Exp $ */
2983e9580Sangelos /*
3983e9580Sangelos * The author of this code is Angelos D. Keromytis (angelos@dsl.cis.upenn.edu)
4983e9580Sangelos *
5983e9580Sangelos * This code was written by Angelos D. Keromytis in Philadelphia, PA, USA,
6983e9580Sangelos * in April-May 1998
7983e9580Sangelos *
8983e9580Sangelos * Copyright (C) 1998, 1999 by Angelos D. Keromytis.
9983e9580Sangelos *
105e4ac158Sderaadt * Permission to use, copy, and modify this software with or without fee
11983e9580Sangelos * is hereby granted, provided that this entire notice is included in
12983e9580Sangelos * all copies of any software which is or includes a copy or
13983e9580Sangelos * modification of this software.
14983e9580Sangelos *
15983e9580Sangelos * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR
16983e9580Sangelos * IMPLIED WARRANTY. IN PARTICULAR, THE AUTHORS MAKES NO
17983e9580Sangelos * REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE
18983e9580Sangelos * MERCHANTABILITY OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR
19983e9580Sangelos * PURPOSE.
20983e9580Sangelos */
21983e9580Sangelos
22983e9580Sangelos #include <sys/types.h>
23983e9580Sangelos #include <sys/stat.h>
24e0758482Smsf
25983e9580Sangelos #include <ctype.h>
269186b70cSangelos #include <fcntl.h>
279186b70cSangelos #include <getopt.h>
2885616838Smsf #include <regex.h>
29e0758482Smsf #include <stdio.h>
30e0758482Smsf #include <stdlib.h>
31e0758482Smsf #include <string.h>
32983e9580Sangelos #include <unistd.h>
33983e9580Sangelos
34dd34a27eSangelos #include "header.h"
351c338448Sangelos #include "keynote.h"
36983e9580Sangelos
3702d661e9Smortimer int sessid;
3802d661e9Smortimer
39aa31cba2Sderaadt void verifyusage(void);
40aa31cba2Sderaadt
41983e9580Sangelos void
verifyusage(void)42e482c692Sangelos verifyusage(void)
43983e9580Sangelos {
44983e9580Sangelos fprintf(stderr, "Arguments:\n");
45983e9580Sangelos fprintf(stderr, "\t-h: This message\n");
46983e9580Sangelos fprintf(stderr,
47983e9580Sangelos "\t-r <valuelist>: Comma separated, ordered return-value list\n");
48983e9580Sangelos fprintf(stderr, "\t-e <filename>: Environment settings\n");
49983e9580Sangelos fprintf(stderr, "\t-l <filename>: Trusted (local) assertion\n");
50983e9580Sangelos fprintf(stderr, "\t-k <filename>: File containing key\n");
51983e9580Sangelos fprintf(stderr, "Followed by a list of:\n");
52983e9580Sangelos fprintf(stderr, "\t<filename>: Non-local assertion\n");
53983e9580Sangelos }
54983e9580Sangelos
55983e9580Sangelos void
keynote_verify(int argc,char * argv[])56e482c692Sangelos keynote_verify(int argc, char *argv[])
57983e9580Sangelos {
58983e9580Sangelos int fd, i, ch, se = 0, cl = 8192, sk = 0, sl = 0, p, ac = argc;
59983e9580Sangelos char *buf, **av = argv, **retv, **foov, *ptr;
60983e9580Sangelos int numretv = 16, numret = 0, sn;
61983e9580Sangelos struct stat sb;
62983e9580Sangelos
63983e9580Sangelos if (argc == 1)
64983e9580Sangelos {
65e482c692Sangelos verifyusage();
663cb7a939Sangelos exit(1);
67983e9580Sangelos }
68983e9580Sangelos
69313d0fe7Smmcc if ((buf = calloc(cl, sizeof(char))) == NULL)
70983e9580Sangelos {
71983e9580Sangelos perror("calloc()");
723cb7a939Sangelos exit(1);
73983e9580Sangelos }
74983e9580Sangelos
75313d0fe7Smmcc if ((retv = calloc(numretv, sizeof(char *))) == NULL)
76983e9580Sangelos {
77983e9580Sangelos perror("calloc()");
783cb7a939Sangelos exit(1);
79983e9580Sangelos }
80983e9580Sangelos
81983e9580Sangelos /* "ac" and "av" are used for stress-testing, ignore otherwise */
82983e9580Sangelos argv = av;
83983e9580Sangelos argc = ac;
84983e9580Sangelos sn = 0;
85983e9580Sangelos opterr = 0;
86983e9580Sangelos
87983e9580Sangelos sessid = kn_init();
88983e9580Sangelos if (sessid == -1)
89983e9580Sangelos {
90983e9580Sangelos fprintf(stderr, "kn_init() failed (errno %d).\n", keynote_errno);
91983e9580Sangelos exit(keynote_errno);
92983e9580Sangelos }
93983e9580Sangelos
94983e9580Sangelos while ((ch = getopt(argc, argv, "hqistl:e:k:r:")) != -1)
95983e9580Sangelos {
96983e9580Sangelos switch (ch)
97983e9580Sangelos {
98983e9580Sangelos case 'e':
99983e9580Sangelos if (read_environment(optarg) == -1)
1003cb7a939Sangelos exit(1);
101983e9580Sangelos se = 1;
102983e9580Sangelos break;
103983e9580Sangelos
104983e9580Sangelos case 'k':
105983e9580Sangelos sk = 1;
106983e9580Sangelos
107*b7041c07Sderaadt if ((fd = open(optarg, O_RDONLY)) == -1)
108983e9580Sangelos {
109ca0ac210Sangelos perror(optarg);
1103cb7a939Sangelos exit(1);
111983e9580Sangelos }
112983e9580Sangelos
113df69c215Sderaadt if (fstat(fd, &sb) == -1)
114983e9580Sangelos {
115983e9580Sangelos perror("fstat()");
1163cb7a939Sangelos exit(1);
117983e9580Sangelos }
118983e9580Sangelos
119983e9580Sangelos if (sb.st_size > cl - 1)
120983e9580Sangelos {
121983e9580Sangelos free(buf);
122983e9580Sangelos cl = sb.st_size + 1;
123313d0fe7Smmcc buf = calloc(cl, sizeof(char));
124313d0fe7Smmcc if (buf == NULL)
125983e9580Sangelos {
126983e9580Sangelos perror("calloc()");
1273cb7a939Sangelos exit(1);
128983e9580Sangelos }
129983e9580Sangelos }
130983e9580Sangelos
131983e9580Sangelos i = read(fd, buf, sb.st_size);
132df69c215Sderaadt if (i == -1)
133983e9580Sangelos {
134983e9580Sangelos perror("read()");
1353cb7a939Sangelos exit(1);
136983e9580Sangelos }
137983e9580Sangelos
138983e9580Sangelos close(fd);
139983e9580Sangelos
140983e9580Sangelos parse_key(buf);
141983e9580Sangelos switch (keynote_errno)
142983e9580Sangelos {
143983e9580Sangelos case 0: /* No errors */
144983e9580Sangelos break;
145983e9580Sangelos
146983e9580Sangelos case ERROR_SYNTAX:
147983e9580Sangelos fprintf(stderr, "Syntax error adding authorizer "
148983e9580Sangelos "%s\n", optarg);
1493cb7a939Sangelos exit(1);
150983e9580Sangelos
151983e9580Sangelos case ERROR_MEMORY:
152983e9580Sangelos perror("Out of memory.\n");
1533cb7a939Sangelos exit(1);
154983e9580Sangelos
155983e9580Sangelos default:
156983e9580Sangelos fprintf(stderr, "Unknown error (%d).\n",
157983e9580Sangelos keynote_errno);
158983e9580Sangelos }
159983e9580Sangelos
160983e9580Sangelos break;
161983e9580Sangelos
162983e9580Sangelos case 'h':
163e482c692Sangelos verifyusage();
164983e9580Sangelos exit(0);
165983e9580Sangelos
166983e9580Sangelos case 'r':
167983e9580Sangelos if (sn != 0)
168983e9580Sangelos {
169983e9580Sangelos fprintf(stderr,
170983e9580Sangelos "Do not define two sets of return values.\n");
1713cb7a939Sangelos exit(1);
172983e9580Sangelos }
173983e9580Sangelos
174983e9580Sangelos sn = 1;
175983e9580Sangelos
176983e9580Sangelos for (numret = 0;
177313d0fe7Smmcc (ptr = strchr(optarg, ',')) != NULL;
178983e9580Sangelos numret++)
179983e9580Sangelos {
180983e9580Sangelos /* Running out of memory */
181983e9580Sangelos if (numret > numretv - 3)
182983e9580Sangelos {
183983e9580Sangelos numretv *= 2;
184313d0fe7Smmcc foov = calloc(numretv, sizeof(char **));
185313d0fe7Smmcc if (foov == NULL)
186983e9580Sangelos {
187983e9580Sangelos /*
188983e9580Sangelos * If this were a real program, we 'd be freeing
189983e9580Sangelos * retv here. Since we're exiting, we can be a
190983e9580Sangelos * little sloppy.
191983e9580Sangelos */
192983e9580Sangelos perror("calloc()");
1933cb7a939Sangelos exit(1);
194983e9580Sangelos }
195983e9580Sangelos
1969186b70cSangelos memcpy(foov, retv, numretv * sizeof(char **));
197983e9580Sangelos free(retv);
198983e9580Sangelos retv = foov;
199983e9580Sangelos }
200983e9580Sangelos
201313d0fe7Smmcc retv[numret] = calloc((ptr - optarg) + 1,
202983e9580Sangelos sizeof(char));
203313d0fe7Smmcc if (retv[numret] == NULL)
204983e9580Sangelos {
205983e9580Sangelos /* Comment from above applies here as well */
206983e9580Sangelos perror("calloc()");
2073cb7a939Sangelos exit(1);
208983e9580Sangelos }
209983e9580Sangelos
210983e9580Sangelos /* Copy */
2119186b70cSangelos memcpy(retv[numret], optarg, ptr - optarg);
212983e9580Sangelos optarg = ptr + 1;
213983e9580Sangelos }
214983e9580Sangelos
215983e9580Sangelos /* Last component */
216313d0fe7Smmcc retv[numret] = strdup(optarg);
217313d0fe7Smmcc if (retv[numret] == NULL)
218983e9580Sangelos {
219983e9580Sangelos perror("calloc()");
2203cb7a939Sangelos exit(1);
221983e9580Sangelos }
222983e9580Sangelos
223983e9580Sangelos numret++;
224983e9580Sangelos break;
225983e9580Sangelos
226983e9580Sangelos case 'l':
227*b7041c07Sderaadt if ((fd = open(optarg, O_RDONLY)) == -1)
228983e9580Sangelos {
229ca0ac210Sangelos perror(optarg);
2303cb7a939Sangelos exit(1);
231983e9580Sangelos }
232983e9580Sangelos
233df69c215Sderaadt if (fstat(fd, &sb) == -1)
234983e9580Sangelos {
235983e9580Sangelos perror("fstat()");
2363cb7a939Sangelos exit(1);
237983e9580Sangelos }
238983e9580Sangelos
239983e9580Sangelos if (sb.st_size > cl - 1)
240983e9580Sangelos {
241983e9580Sangelos free(buf);
242983e9580Sangelos cl = sb.st_size + 1;
243313d0fe7Smmcc buf = calloc(cl, sizeof(char));
244313d0fe7Smmcc if (buf == NULL)
245983e9580Sangelos {
246983e9580Sangelos perror("calloc()");
2473cb7a939Sangelos exit(1);
248983e9580Sangelos }
249983e9580Sangelos }
250983e9580Sangelos
251983e9580Sangelos i = read(fd, buf, sb.st_size);
252df69c215Sderaadt if (i == -1)
253983e9580Sangelos {
254983e9580Sangelos perror("read()");
2553cb7a939Sangelos exit(1);
256983e9580Sangelos }
257983e9580Sangelos
258983e9580Sangelos close(fd);
259983e9580Sangelos p = kn_add_assertion(sessid, buf, i, ASSERT_FLAG_LOCAL);
260983e9580Sangelos if (p == -1)
261983e9580Sangelos {
262983e9580Sangelos fprintf(stderr,
263983e9580Sangelos "Error for assertion in file <%s>, errno %d.\n",
264983e9580Sangelos optarg, keynote_errno);
265983e9580Sangelos keynote_errno = 0;
266983e9580Sangelos }
267983e9580Sangelos
268983e9580Sangelos memset(buf, 0, sb.st_size);
269983e9580Sangelos sl = 1;
270983e9580Sangelos break;
271983e9580Sangelos
272983e9580Sangelos case '?':
273983e9580Sangelos default:
274e482c692Sangelos verifyusage();
2753cb7a939Sangelos exit(1);
276983e9580Sangelos }
277983e9580Sangelos }
278983e9580Sangelos
279983e9580Sangelos argc -= optind;
280983e9580Sangelos argv += optind;
281983e9580Sangelos optind = 1;
282983e9580Sangelos
283983e9580Sangelos if (sn == 0)
284983e9580Sangelos {
285983e9580Sangelos fprintf(stderr,
286983e9580Sangelos "Should set return values before evaluations begin.\n");
2873cb7a939Sangelos exit(1);
288983e9580Sangelos }
289983e9580Sangelos
290983e9580Sangelos if (se == 0)
291983e9580Sangelos {
292983e9580Sangelos fprintf(stderr, "Should set environment before evaluations begin.\n");
2933cb7a939Sangelos exit(1);
294983e9580Sangelos }
295983e9580Sangelos
296983e9580Sangelos if (sk == 0)
297983e9580Sangelos {
298983e9580Sangelos fprintf(stderr, "Should specify at least one action authorizer.\n");
2993cb7a939Sangelos exit(1);
300983e9580Sangelos }
301983e9580Sangelos
302983e9580Sangelos if (sl == 0)
303983e9580Sangelos {
304983e9580Sangelos fprintf(stderr,
305983e9580Sangelos "Should specify at least one trusted assertion (POLICY).\n");
3063cb7a939Sangelos exit(1);
307983e9580Sangelos }
308983e9580Sangelos
309983e9580Sangelos while (argc--)
310983e9580Sangelos {
311*b7041c07Sderaadt if ((fd = open(argv[argc], O_RDONLY)) == -1)
312983e9580Sangelos {
313ca0ac210Sangelos perror(argv[argc]);
3143cb7a939Sangelos exit(1);
315983e9580Sangelos }
316983e9580Sangelos
317df69c215Sderaadt if (fstat(fd, &sb) == -1)
318983e9580Sangelos {
319983e9580Sangelos perror("fstat()");
3203cb7a939Sangelos exit(1);
321983e9580Sangelos }
322983e9580Sangelos
323983e9580Sangelos if (sb.st_size > cl - 1)
324983e9580Sangelos {
325983e9580Sangelos free(buf);
326983e9580Sangelos cl = sb.st_size + 1;
327313d0fe7Smmcc buf = calloc(cl, sizeof(char));
328313d0fe7Smmcc if (buf == NULL)
329983e9580Sangelos {
330983e9580Sangelos perror("calloc()");
3313cb7a939Sangelos exit(1);
332983e9580Sangelos }
333983e9580Sangelos }
334983e9580Sangelos
335983e9580Sangelos i = read(fd, buf, sb.st_size);
336df69c215Sderaadt if (i == -1)
337983e9580Sangelos {
338983e9580Sangelos perror("read()");
3393cb7a939Sangelos exit(1);
340983e9580Sangelos }
341983e9580Sangelos
342983e9580Sangelos close(fd);
343983e9580Sangelos p = kn_add_assertion(sessid, buf, i, 0);
344983e9580Sangelos if (p == -1)
345983e9580Sangelos {
346983e9580Sangelos fprintf(stderr, "Error for assertion in file <%s>, errno %d.\n",
347983e9580Sangelos argv[argc], keynote_errno);
348983e9580Sangelos keynote_errno = 0;
349983e9580Sangelos }
350983e9580Sangelos
351983e9580Sangelos memset(buf, 0, sb.st_size);
352983e9580Sangelos }
353983e9580Sangelos
354983e9580Sangelos p = kn_do_query(sessid, retv, numret); /* Evaluation time */
355983e9580Sangelos
356983e9580Sangelos printf("Query result = ");
357983e9580Sangelos
358983e9580Sangelos switch (keynote_errno)
359983e9580Sangelos {
360983e9580Sangelos case ERROR_MEMORY:
361983e9580Sangelos printf("<out of memory>\n");
3623cb7a939Sangelos exit(1);
363983e9580Sangelos
364983e9580Sangelos case ERROR_SYNTAX:
365983e9580Sangelos printf("<uninitialized authorizers or all POLICY "
366983e9580Sangelos "assertions are malformed!>\n");
3673cb7a939Sangelos exit(1);
368983e9580Sangelos
369983e9580Sangelos case ERROR_NOTFOUND:
370983e9580Sangelos printf("<session or other information not found!>\n");
3713cb7a939Sangelos exit(1);
372983e9580Sangelos
373983e9580Sangelos case 0: /* No errors */
374983e9580Sangelos break;
375983e9580Sangelos
376983e9580Sangelos default:
377983e9580Sangelos printf("<should never happen (%d)!>\n", keynote_errno);
3783cb7a939Sangelos exit(1);
379983e9580Sangelos }
380983e9580Sangelos
381983e9580Sangelos printf("%s\n", retv[p]);
382983e9580Sangelos
383983e9580Sangelos keynote_errno = 0;
384983e9580Sangelos
385983e9580Sangelos while ((i = kn_get_failed(sessid, KEYNOTE_ERROR_MEMORY, 0)) != -1)
386983e9580Sangelos {
387983e9580Sangelos printf("Failed assertion %d due to memory error.\n", i);
388983e9580Sangelos kn_remove_assertion(sessid, i);
389983e9580Sangelos }
390983e9580Sangelos
391983e9580Sangelos while ((i = kn_get_failed(sessid, KEYNOTE_ERROR_SYNTAX, 0)) != -1)
392983e9580Sangelos {
393983e9580Sangelos printf("Failed assertion %d due to syntax or semantic error.\n", i);
394983e9580Sangelos kn_remove_assertion(sessid, i);
395983e9580Sangelos }
396983e9580Sangelos
397983e9580Sangelos while ((i = kn_get_failed(sessid, KEYNOTE_ERROR_SIGNATURE, 0)) != -1)
398983e9580Sangelos {
399983e9580Sangelos printf("Failed assertion %d due to signature verification failure.\n",
400983e9580Sangelos i);
401983e9580Sangelos kn_remove_assertion(sessid, i);
402983e9580Sangelos }
403983e9580Sangelos
404983e9580Sangelos while ((i = kn_get_failed(sessid, KEYNOTE_ERROR_ANY, 0)) != -1)
405983e9580Sangelos {
406983e9580Sangelos printf("Failed assertion %d due to unspecified error.\n", i);
407983e9580Sangelos kn_remove_assertion(sessid, i);
408983e9580Sangelos }
409983e9580Sangelos
410983e9580Sangelos kn_close(sessid);
411983e9580Sangelos
412983e9580Sangelos /* This is a reminder that return values are not free'ed by KeyNote */
413983e9580Sangelos for (sn = 0; sn < numret; sn++)
414983e9580Sangelos free(retv[sn]);
415983e9580Sangelos free(retv);
416313d0fe7Smmcc retv = NULL;
417983e9580Sangelos
418983e9580Sangelos exit(0);
419983e9580Sangelos }
420