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