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