xref: /openbsd/lib/libkeynote/keynote-verify.c (revision b7041c07)
1 /* $OpenBSD: keynote-verify.c,v 1.20 2021/10/24 21:24:20 deraadt Exp $ */
2 /*
3  * The author of this code is Angelos D. Keromytis (angelos@dsl.cis.upenn.edu)
4  *
5  * This code was written by Angelos D. Keromytis in Philadelphia, PA, USA,
6  * in April-May 1998
7  *
8  * Copyright (C) 1998, 1999 by Angelos D. Keromytis.
9  *
10  * Permission to use, copy, and modify this software with or without fee
11  * is hereby granted, provided that this entire notice is included in
12  * all copies of any software which is or includes a copy or
13  * modification of this software.
14  *
15  * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR
16  * IMPLIED WARRANTY. IN PARTICULAR, THE AUTHORS MAKES NO
17  * REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE
18  * MERCHANTABILITY OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR
19  * PURPOSE.
20  */
21 
22 #include <sys/types.h>
23 #include <sys/stat.h>
24 
25 #include <ctype.h>
26 #include <fcntl.h>
27 #include <getopt.h>
28 #include <regex.h>
29 #include <stdio.h>
30 #include <stdlib.h>
31 #include <string.h>
32 #include <unistd.h>
33 
34 #include "header.h"
35 #include "keynote.h"
36 
37 int sessid;
38 
39 void	verifyusage(void);
40 
41 void
verifyusage(void)42 verifyusage(void)
43 {
44     fprintf(stderr, "Arguments:\n");
45     fprintf(stderr, "\t-h:             This message\n");
46     fprintf(stderr,
47 	    "\t-r <valuelist>: Comma separated, ordered return-value list\n");
48     fprintf(stderr, "\t-e <filename>:  Environment settings\n");
49     fprintf(stderr, "\t-l <filename>:  Trusted (local) assertion\n");
50     fprintf(stderr, "\t-k <filename>:  File containing key\n");
51     fprintf(stderr, "Followed by a list of:\n");
52     fprintf(stderr, "\t<filename>:     Non-local assertion\n");
53 }
54 
55 void
keynote_verify(int argc,char * argv[])56 keynote_verify(int argc, char *argv[])
57 {
58     int fd, i, ch, se = 0, cl = 8192, sk = 0, sl = 0, p, ac = argc;
59     char *buf, **av = argv, **retv, **foov, *ptr;
60     int numretv = 16, numret = 0, sn;
61     struct stat sb;
62 
63     if (argc == 1)
64     {
65 	verifyusage();
66 	exit(1);
67     }
68 
69     if ((buf = calloc(cl, sizeof(char))) == NULL)
70     {
71 	perror("calloc()");
72 	exit(1);
73     }
74 
75     if ((retv = calloc(numretv, sizeof(char *))) == NULL)
76     {
77 	perror("calloc()");
78 	exit(1);
79     }
80 
81     /* "ac" and "av" are used for stress-testing, ignore otherwise */
82     argv = av;
83     argc = ac;
84     sn = 0;
85     opterr = 0;
86 
87     sessid = kn_init();
88     if (sessid == -1)
89     {
90 	fprintf(stderr, "kn_init() failed (errno %d).\n", keynote_errno);
91 	exit(keynote_errno);
92     }
93 
94     while ((ch = getopt(argc, argv, "hqistl:e:k:r:")) != -1)
95     {
96 	switch (ch)
97 	{
98 	    case 'e':
99 		if (read_environment(optarg) == -1)
100 	 	  exit(1);
101 		se = 1;
102 		break;
103 
104 	    case 'k':
105 		sk = 1;
106 
107 		if ((fd = open(optarg, O_RDONLY)) == -1)
108 		{
109 		    perror(optarg);
110 		    exit(1);
111 		}
112 
113 		if (fstat(fd, &sb) == -1)
114 		{
115 		    perror("fstat()");
116 		    exit(1);
117 		}
118 
119 		if (sb.st_size > cl - 1)
120 		{
121 		    free(buf);
122 		    cl = sb.st_size + 1;
123 		    buf = calloc(cl, sizeof(char));
124 		    if (buf == NULL)
125 		    {
126 			perror("calloc()");
127 			exit(1);
128 		    }
129 		}
130 
131 		i = read(fd, buf, sb.st_size);
132 		if (i == -1)
133 		{
134 		    perror("read()");
135 		    exit(1);
136 		}
137 
138 		close(fd);
139 
140 		parse_key(buf);
141 		switch (keynote_errno)
142 		{
143 		    case 0:    /* No errors */
144 			break;
145 
146 		    case ERROR_SYNTAX:
147 			fprintf(stderr, "Syntax error adding authorizer "
148 				"%s\n", optarg);
149 			exit(1);
150 
151 		    case ERROR_MEMORY:
152 			perror("Out of memory.\n");
153 			exit(1);
154 
155 		    default:
156 			fprintf(stderr, "Unknown error (%d).\n",
157 				keynote_errno);
158 		}
159 
160 		break;
161 
162 	    case 'h':
163 		verifyusage();
164 		exit(0);
165 
166 	    case 'r':
167 		if (sn != 0)
168 		{
169 		    fprintf(stderr,
170 			    "Do not define two sets of return values.\n");
171 		    exit(1);
172 		}
173 
174 		sn = 1;
175 
176 		for (numret = 0;
177 		     (ptr = strchr(optarg, ',')) != NULL;
178 		     numret++)
179 		{
180 		    /* Running out of memory */
181 		    if (numret > numretv - 3)
182 		    {
183 			numretv *= 2;
184 			foov = calloc(numretv, sizeof(char **));
185 			if (foov == NULL)
186 			{
187 			    /*
188 			     * If this were a real program, we 'd be freeing
189 			     * retv here. Since we're exiting, we can be a
190 			     * little sloppy.
191 			     */
192 			    perror("calloc()");
193 			    exit(1);
194 			}
195 
196 			memcpy(foov, retv, numretv * sizeof(char **));
197 			free(retv);
198 			retv = foov;
199 		    }
200 
201 		    retv[numret] = calloc((ptr - optarg) + 1,
202 						       sizeof(char));
203 		    if (retv[numret] == NULL)
204 		    {
205 			/* Comment from above applies here as well */
206 			perror("calloc()");
207 			exit(1);
208 		    }
209 
210 		    /* Copy */
211 		    memcpy(retv[numret], optarg, ptr - optarg);
212 		    optarg = ptr + 1;
213 		}
214 
215 		/* Last component */
216 		retv[numret] = strdup(optarg);
217 		if (retv[numret] == NULL)
218 		{
219 		    perror("calloc()");
220 		    exit(1);
221 		}
222 
223 		numret++;
224 		break;
225 
226 	    case 'l':
227 		if ((fd = open(optarg, O_RDONLY)) == -1)
228 		{
229 		    perror(optarg);
230 		    exit(1);
231 		}
232 
233 		if (fstat(fd, &sb) == -1)
234 		{
235 		    perror("fstat()");
236 		    exit(1);
237 		}
238 
239 		if (sb.st_size > cl - 1)
240 		{
241 		    free(buf);
242 		    cl = sb.st_size + 1;
243 		    buf = calloc(cl, sizeof(char));
244 		    if (buf == NULL)
245 		    {
246 			perror("calloc()");
247 			exit(1);
248 		    }
249 		}
250 
251 		i = read(fd, buf, sb.st_size);
252 		if (i == -1)
253 		{
254 		    perror("read()");
255 		    exit(1);
256 		}
257 
258 		close(fd);
259 		p = kn_add_assertion(sessid, buf, i, ASSERT_FLAG_LOCAL);
260 		if (p == -1)
261 		{
262 		    fprintf(stderr,
263 			    "Error for assertion in file <%s>, errno %d.\n",
264 			   optarg, keynote_errno);
265 		    keynote_errno = 0;
266 		}
267 
268 		memset(buf, 0, sb.st_size);
269 		sl = 1;
270 		break;
271 
272 	    case '?':
273 	    default:
274 		verifyusage();
275 		exit(1);
276 	}
277     }
278 
279     argc -= optind;
280     argv += optind;
281     optind = 1;
282 
283     if (sn == 0)
284     {
285 	fprintf(stderr,
286 		"Should set return values before evaluations begin.\n");
287 	exit(1);
288     }
289 
290     if (se == 0)
291     {
292 	fprintf(stderr, "Should set environment before evaluations begin.\n");
293 	exit(1);
294     }
295 
296     if (sk == 0)
297     {
298 	fprintf(stderr, "Should specify at least one action authorizer.\n");
299 	exit(1);
300     }
301 
302     if (sl == 0)
303     {
304 	fprintf(stderr,
305 		"Should specify at least one trusted assertion (POLICY).\n");
306 	exit(1);
307     }
308 
309     while (argc--)
310     {
311 	if ((fd = open(argv[argc], O_RDONLY)) == -1)
312 	{
313 	    perror(argv[argc]);
314 	    exit(1);
315 	}
316 
317 	if (fstat(fd, &sb) == -1)
318 	{
319 	    perror("fstat()");
320 	    exit(1);
321 	}
322 
323 	if (sb.st_size > cl - 1)
324 	{
325 	    free(buf);
326 	    cl = sb.st_size + 1;
327 	    buf = calloc(cl, sizeof(char));
328 	    if (buf == NULL)
329 	    {
330 		perror("calloc()");
331 		exit(1);
332 	    }
333 	}
334 
335 	i = read(fd, buf, sb.st_size);
336 	if (i == -1)
337 	{
338 	    perror("read()");
339 	    exit(1);
340 	}
341 
342 	close(fd);
343 	p = kn_add_assertion(sessid, buf, i, 0);
344 	if (p == -1)
345 	{
346 	    fprintf(stderr, "Error for assertion in file <%s>, errno %d.\n",
347 		    argv[argc], keynote_errno);
348 	    keynote_errno = 0;
349 	}
350 
351 	memset(buf, 0, sb.st_size);
352     }
353 
354     p = kn_do_query(sessid, retv, numret); /* Evaluation time */
355 
356     printf("Query result = ");
357 
358     switch (keynote_errno)
359     {
360 	case ERROR_MEMORY:
361 	    printf("<out of memory>\n");
362 	    exit(1);
363 
364 	case ERROR_SYNTAX:
365 	    printf("<uninitialized authorizers or all POLICY "
366 		   "assertions are malformed!>\n");
367 	    exit(1);
368 
369 	case ERROR_NOTFOUND:
370 	    printf("<session or other information not found!>\n");
371 	    exit(1);
372 
373 	case 0:	/* No errors */
374 	    break;
375 
376 	default:
377 	    printf("<should never happen (%d)!>\n", keynote_errno);
378 	    exit(1);
379     }
380 
381     printf("%s\n", retv[p]);
382 
383     keynote_errno = 0;
384 
385     while ((i = kn_get_failed(sessid, KEYNOTE_ERROR_MEMORY, 0)) != -1)
386     {
387         printf("Failed assertion %d due to memory error.\n", i);
388         kn_remove_assertion(sessid, i);
389     }
390 
391     while ((i = kn_get_failed(sessid, KEYNOTE_ERROR_SYNTAX, 0)) != -1)
392     {
393         printf("Failed assertion %d due to syntax or semantic error.\n", i);
394         kn_remove_assertion(sessid, i);
395     }
396 
397     while ((i = kn_get_failed(sessid, KEYNOTE_ERROR_SIGNATURE, 0)) != -1)
398     {
399         printf("Failed assertion %d due to signature verification failure.\n",
400 	       i);
401         kn_remove_assertion(sessid, i);
402     }
403 
404     while ((i = kn_get_failed(sessid, KEYNOTE_ERROR_ANY, 0)) != -1)
405     {
406         printf("Failed assertion %d due to unspecified error.\n", i);
407         kn_remove_assertion(sessid, i);
408     }
409 
410     kn_close(sessid);
411 
412     /* This is a reminder that return values are not free'ed by KeyNote */
413     for (sn = 0; sn < numret; sn++)
414       free(retv[sn]);
415     free(retv);
416     retv = NULL;
417 
418     exit(0);
419 }
420