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