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