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