xref: /openbsd-src/lib/libkeynote/keynote-verify.c (revision b7041c0781c8668129da8084451ded41b0c43954)
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