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