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