1 /* $OpenBSD: parse_assertion.c,v 1.9 2000/06/13 19:16:16 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 <stdlib.h> 28 #include <stdio.h> 29 #include <ctype.h> 30 31 #if STDC_HEADERS 32 #include <string.h> 33 #endif /* STDC_HEADERS */ 34 35 #if HAVE_LIMITS_H 36 #include <limits.h> 37 #endif /* HAVE_LIMITS_H */ 38 39 #include "header.h" 40 #include "keynote.h" 41 #include "assertion.h" 42 #include "signature.h" 43 44 /* 45 * Recurse on graph discovery. 46 */ 47 static int 48 rec_evaluate_query(struct assertion *as) 49 { 50 struct assertion *ast; 51 struct keylist *kl; 52 int i, s; 53 54 as->as_kresult = KRESULT_IN_PROGRESS; 55 56 /* 57 * If we get the minimum result or an error from evaluating this 58 * assertion, we don't need to recurse. 59 */ 60 keynote_evaluate_assertion(as); 61 if (keynote_errno != 0) 62 { 63 as->as_kresult = KRESULT_DONE; 64 if (keynote_errno) 65 as->as_error = keynote_errno; 66 if (keynote_errno == ERROR_MEMORY) 67 return -1; 68 else 69 { 70 keynote_errno = 0; /* Ignore syntax errors for now */ 71 return 0; 72 } 73 } 74 75 if (as->as_result == 0) 76 { 77 as->as_kresult = KRESULT_DONE; 78 return as->as_result; 79 } 80 81 for (kl = as->as_keylist; 82 kl != (struct keylist *) NULL; 83 kl = kl->key_next) 84 { 85 switch (keynote_in_action_authorizers(kl->key_key, kl->key_alg)) 86 { 87 case -1: 88 as->as_kresult = KRESULT_DONE; 89 if (keynote_errno == ERROR_MEMORY) 90 { 91 as->as_error = ERROR_MEMORY; 92 return -1; 93 } 94 else 95 { 96 keynote_errno = 0; /* Reset */ 97 continue; 98 } 99 100 case RESULT_FALSE: /* Not there, check for assertions instead */ 101 break; 102 103 case RESULT_TRUE: /* Ok, don't bother with assertions */ 104 keynote_current_assertion = (struct assertion *) NULL; 105 continue; 106 } 107 108 for (i = 0;; i++) 109 { 110 ast = keynote_find_assertion(kl->key_key, i, kl->key_alg); 111 if (ast == (struct assertion *) NULL) 112 break; 113 114 if (ast->as_kresult == KRESULT_IN_PROGRESS) /* Cycle detected */ 115 continue; 116 117 if (ast->as_kresult == KRESULT_UNTOUCHED) /* Recurse if needed */ 118 rec_evaluate_query(ast); 119 120 /* Check for errors */ 121 if (keynote_errno == ERROR_MEMORY) 122 { 123 as->as_error = ERROR_MEMORY; 124 as->as_kresult = KRESULT_DONE; 125 return -1; 126 } 127 else 128 keynote_errno = 0; /* Reset */ 129 } 130 } 131 132 keynote_current_assertion = as; 133 s = keynote_parse_keypred(as, 0); 134 keynote_current_assertion = (struct assertion *) NULL; 135 136 if (keynote_errno == ERROR_MEMORY) 137 { 138 as->as_error = ERROR_MEMORY; 139 as->as_kresult = KRESULT_DONE; 140 return -1; 141 } 142 else 143 if (keynote_errno) 144 { 145 keynote_errno = 0; 146 s = 0; 147 } 148 149 /* Keep lower of two */ 150 as->as_result = (as->as_result < s ? as->as_result : s); 151 152 /* Check the signature now if we haven't done so already */ 153 if (as->as_sigresult == SIGRESULT_UNTOUCHED) 154 { 155 if (!(as->as_flags & ASSERT_FLAG_LOCAL)) 156 as->as_sigresult = keynote_sigverify_assertion(as); 157 else 158 as->as_sigresult = SIGRESULT_TRUE; /* Trusted assertion */ 159 } 160 161 if (as->as_sigresult != SIGRESULT_TRUE) 162 { 163 as->as_result = 0; 164 as->as_sigresult = SIGRESULT_FALSE; 165 if (keynote_errno != ERROR_MEMORY) 166 keynote_errno = 0; /* Reset */ 167 else 168 { 169 as->as_error = ERROR_MEMORY; 170 as->as_kresult = KRESULT_DONE; 171 return -1; 172 } 173 } 174 175 as->as_kresult = KRESULT_DONE; 176 return as->as_result; 177 } 178 179 /* 180 * Fix the Authorizer/Licencees/Signature fields. If the first argument is 181 * empty, fix all assertions. The second argument specifies whether the 182 * Signature field should be parsed or not. 183 */ 184 static int 185 keynote_fix_fields(struct assertion *ast, int sigfield) 186 { 187 struct assertion *as; 188 int i; 189 190 /* Signature generation/verification handling, no need to eval Licensees */ 191 if (ast != (struct assertion *) NULL) 192 { 193 /* Authorizer */ 194 if (keynote_evaluate_authorizer(ast, 1) != RESULT_TRUE) 195 return -1; 196 197 /* Signature */ 198 if ((sigfield) && (ast->as_signature_string_s != (char *) NULL)) 199 if (keynote_evaluate_authorizer(ast, 0) != RESULT_TRUE) 200 return -1; 201 202 return RESULT_TRUE; 203 } 204 205 for (i = 0; i < HASHTABLESIZE; i++) 206 for (as = keynote_current_session->ks_assertion_table[i]; 207 as != (struct assertion *) NULL; 208 as = as->as_next) 209 { 210 if (!(as->as_internalflags & ASSERT_IFLAG_NEEDPROC) && 211 !(as->as_internalflags & ASSERT_IFLAG_WEIRDLICS) && 212 !(as->as_internalflags & ASSERT_IFLAG_WEIRDAUTH) && 213 !(as->as_internalflags & ASSERT_IFLAG_WEIRDSIG)) 214 continue; 215 216 /* Parse the Signature field */ 217 if (((as->as_internalflags & ASSERT_IFLAG_WEIRDSIG) || 218 (as->as_internalflags & ASSERT_IFLAG_NEEDPROC)) && 219 (as->as_signature_string_s != (char *) NULL)) 220 if (keynote_evaluate_authorizer(as, 0) == -1) 221 { 222 if (keynote_errno) 223 as->as_error = keynote_errno; 224 if (keynote_errno == ERROR_MEMORY) 225 return -1; 226 else 227 keynote_errno = 0; 228 } 229 230 /* Parse the Licensees field */ 231 if ((as->as_internalflags & ASSERT_IFLAG_WEIRDLICS) || 232 (as->as_internalflags & ASSERT_IFLAG_NEEDPROC)) 233 if (keynote_parse_keypred(as, 1) == -1) 234 { 235 if (keynote_errno) 236 as->as_error = keynote_errno; 237 if (keynote_errno == ERROR_MEMORY) 238 return -1; 239 else 240 keynote_errno = 0; 241 } 242 243 /* Parse the Authorizer field */ 244 if ((as->as_internalflags & ASSERT_IFLAG_WEIRDAUTH) || 245 (as->as_internalflags & ASSERT_IFLAG_NEEDPROC)) 246 if (keynote_evaluate_authorizer(as, 1) == -1) 247 { 248 if (keynote_errno) 249 as->as_error = keynote_errno; 250 if (keynote_errno == ERROR_MEMORY) 251 return -1; 252 else 253 keynote_errno = 0; 254 } 255 } 256 257 /* Reposition if necessary */ 258 for (i = 0; i < HASHTABLESIZE; i++) 259 for (as = keynote_current_session->ks_assertion_table[i]; 260 as != (struct assertion *) NULL; 261 as = as->as_next) 262 if (((as->as_internalflags & ASSERT_IFLAG_WEIRDAUTH) && 263 !(as->as_internalflags & ASSERT_IFLAG_PROCESSED)) || 264 (as->as_internalflags & ASSERT_IFLAG_NEEDPROC)) 265 { 266 as->as_internalflags &= ~ASSERT_IFLAG_NEEDPROC; 267 as->as_internalflags |= ASSERT_IFLAG_PROCESSED; 268 keynote_sremove_assertion(keynote_current_session->ks_id, 269 as->as_id); 270 271 if (keynote_add_htable(as, 1) != RESULT_TRUE) 272 return -1; 273 274 /* Point to begining of the previous list. */ 275 i--; 276 break; 277 } 278 279 return RESULT_TRUE; 280 } 281 282 /* 283 * Find the trust graph. This is a depth-first search, starting at 284 * POLICY assertions. 285 */ 286 int 287 keynote_evaluate_query(void) 288 { 289 struct assertion *as; 290 int p, prev; 291 int i; 292 293 /* Fix the authorizer/licensees/signature fields */ 294 if (keynote_fix_fields((struct assertion *) NULL, 0) != RESULT_TRUE) 295 return -1; 296 297 /* Find POLICY assertions and try to evaluate the query. */ 298 for (i = 0, prev = 0; i < HASHTABLESIZE; i++) 299 for (as = keynote_current_session->ks_assertion_table[i]; 300 as != (struct assertion *) NULL; 301 as = as->as_next) 302 if ((as->as_authorizer != (void *) NULL) && /* Paranoid */ 303 (as->as_signeralgorithm == KEYNOTE_ALGORITHM_NONE)) 304 if ((!strcmp("POLICY", as->as_authorizer)) && 305 (as->as_flags & ASSERT_FLAG_LOCAL)) 306 { 307 if ((p = rec_evaluate_query(as)) == -1) 308 { 309 if (keynote_errno) 310 as->as_error = keynote_errno; 311 if (keynote_errno == ERROR_MEMORY) 312 return -1; 313 else 314 { 315 keynote_errno = 0; 316 continue; 317 } 318 } 319 320 if (p > prev) 321 prev = p; 322 323 /* If we get the highest possible return value, just return */ 324 if (prev == (keynote_current_session->ks_values_num - 1)) 325 return prev; 326 } 327 328 return prev; 329 } 330 331 /* 332 * Return keyword type. 333 */ 334 static int 335 whichkeyword(char *start, char *end) 336 { 337 int len = (end - start); 338 339 if (len <= 0) 340 { 341 keynote_errno = ERROR_MEMORY; 342 return -1; 343 } 344 345 if (!strncasecmp("keynote-version:", start, len)) 346 return KEYWORD_VERSION; 347 348 if (!strncasecmp("local-constants:", start, len)) 349 return KEYWORD_LOCALINIT; 350 351 if (!strncasecmp("authorizer:", start, len)) 352 return KEYWORD_AUTHORIZER; 353 354 if (!strncasecmp("licensees:", start, len)) 355 return KEYWORD_LICENSEES; 356 357 if (!strncasecmp("conditions:", start, len)) 358 return KEYWORD_CONDITIONS; 359 360 if (!strncasecmp("signature:", start, len)) 361 return KEYWORD_SIGNATURE; 362 363 if (!strncasecmp("comment:", start, len)) 364 return KEYWORD_COMMENT; 365 366 keynote_errno = ERROR_SYNTAX; 367 return -1; 368 } 369 370 /* 371 * Parse an assertion. Set keynote_errno to ERROR_SYNTAX if parsing 372 * failed due to certificate badness, and ERROR_MEMORY if memory 373 * problem. If more than one assertions have been passed in the 374 * buffer, they will be linked. 375 */ 376 struct assertion * 377 keynote_parse_assertion(char *buf, int len, int assertion_flags) 378 { 379 int k, i, j, seen_field = 0, ver = 0, end_of_assertion = 0; 380 char *ks, *ke, *ts, *te = (char *) NULL; 381 struct assertion *as; 382 383 /* Allocate memory for assertion */ 384 as = (struct assertion *) calloc(1, sizeof(struct assertion)); 385 if (as == (struct assertion *) NULL) 386 { 387 keynote_errno = ERROR_MEMORY; 388 return (struct assertion *) NULL; 389 } 390 391 /* Keep a copy of the assertion around */ 392 as->as_buf = strdup(buf); 393 if (as->as_buf == (char *) NULL) 394 { 395 keynote_errno = ERROR_MEMORY; 396 keynote_free_assertion(as); 397 return (struct assertion *) NULL; 398 } 399 400 as->as_flags = assertion_flags & ~(ASSERT_FLAG_SIGGEN | 401 ASSERT_FLAG_SIGVER); 402 403 /* Skip any leading whitespace */ 404 for (i = 0, j = len; i < j && isspace((int) as->as_buf[i]); i++) 405 ; 406 407 /* Keyword must start at begining of buffer or line */ 408 if ((i >= j) || ((i != 0) && (as->as_buf[i - 1] != '\n'))) 409 { 410 keynote_free_assertion(as); 411 keynote_errno = ERROR_SYNTAX; 412 return (struct assertion *) NULL; 413 } 414 415 while (i < j) /* Decomposition loop */ 416 { 417 ks = as->as_buf + i; 418 419 /* Mark begining of assertion for signature purposes */ 420 if (as->as_startofsignature == (char *) NULL) 421 as->as_startofsignature = ks; 422 423 /* This catches comments at the begining of an assertion only */ 424 if (as->as_buf[i] == '#') /* Comment */ 425 { 426 seen_field = 1; 427 428 /* Skip until the end of line */ 429 while ((i< j) && as->as_buf[++i] != '\n') 430 ; 431 432 i++; 433 continue; /* Loop */ 434 } 435 436 /* Advance until we find a keyword separator */ 437 for (; (as->as_buf[i] != ':') && (i < j); i++) 438 ; 439 440 if (i + 1 > j) 441 { 442 keynote_free_assertion(as); 443 keynote_errno = ERROR_SYNTAX; 444 return (struct assertion *) NULL; 445 } 446 447 /* ks points at begining of keyword, ke points at end */ 448 ke = as->as_buf + i; 449 450 /* ts points at begining of value field */ 451 ts = as->as_buf + i + 1; /* Skip ':' */ 452 453 /* 454 * Find the end of the field -- means end of buffer, 455 * a newline followed by a non-whitespace character, 456 * or two newlines. 457 */ 458 while (++i <= j) 459 { 460 /* If end of buffer, we're at the end of the field */ 461 if (i == j) 462 { 463 end_of_assertion = 1; 464 te = as->as_buf + i; 465 break; 466 } 467 468 /* If two newlines, end of assertion */ 469 if ((as->as_buf[i] == '\n') && (i + 1 < j) && 470 (as->as_buf[i + 1] == '\n')) 471 { 472 end_of_assertion = 1; 473 te = as->as_buf + i; 474 break; 475 } 476 477 /* If newline followed by non-whitespace or comment character */ 478 if ((as->as_buf[i] == '\n') && 479 (!isspace((int) as->as_buf[i + 1])) && 480 (as->as_buf[i + 1] != '#')) 481 { 482 te = as->as_buf + i; 483 break; 484 } 485 } 486 487 i++; 488 489 /* 490 * On each of the cases (except the first), we check that: 491 * - we've already seen a keynote-version field (and that 492 * it's the first one that appears in the assertion) 493 * - the signature field, if present, is the last one 494 * - no field appears more than once 495 */ 496 switch (whichkeyword(ks, ke)) 497 { 498 case -1: 499 keynote_free_assertion(as); 500 return (struct assertion *) NULL; 501 502 case KEYWORD_VERSION: 503 if ((ver == 1) || (seen_field == 1)) 504 { 505 keynote_free_assertion(as); 506 keynote_errno = ERROR_SYNTAX; 507 return (struct assertion *) NULL; 508 } 509 510 /* Test for version correctness */ 511 keynote_get_envlist(ts, te, 1); 512 if (keynote_errno != 0) 513 { 514 keynote_free_assertion(as); 515 return (struct assertion *) NULL; 516 } 517 518 ver = 1; 519 break; 520 521 case KEYWORD_LOCALINIT: 522 if (as->as_env != (struct environment *) NULL) 523 { 524 keynote_free_assertion(as); 525 keynote_errno = ERROR_SYNTAX; 526 return (struct assertion *) NULL; 527 } 528 529 as->as_env = keynote_get_envlist(ts, te, 0); 530 if (keynote_errno != 0) 531 { 532 keynote_free_assertion(as); 533 return (struct assertion *) NULL; 534 } 535 break; 536 537 case KEYWORD_AUTHORIZER: 538 if (as->as_authorizer_string_s != (void *) NULL) 539 { 540 keynote_free_assertion(as); 541 keynote_errno = ERROR_SYNTAX; 542 return (struct assertion *) NULL; 543 } 544 545 as->as_authorizer_string_s = ts; 546 as->as_authorizer_string_e = te; 547 break; 548 549 case KEYWORD_LICENSEES: 550 if (as->as_keypred_s != (char *) NULL) 551 { 552 keynote_free_assertion(as); 553 keynote_errno = ERROR_SYNTAX; 554 return (struct assertion *) NULL; 555 } 556 557 as->as_keypred_s = ts; 558 as->as_keypred_e = te; 559 break; 560 561 case KEYWORD_CONDITIONS: 562 if (as->as_conditions_s != (char *) NULL) 563 { 564 keynote_free_assertion(as); 565 keynote_errno = ERROR_SYNTAX; 566 return (struct assertion *) NULL; 567 } 568 569 as->as_conditions_s = ts; 570 as->as_conditions_e = te; 571 break; 572 573 case KEYWORD_SIGNATURE: 574 if (as->as_signature_string_s != (char *) NULL) 575 { 576 keynote_free_assertion(as); 577 keynote_errno = ERROR_SYNTAX; 578 return (struct assertion *) NULL; 579 } 580 581 end_of_assertion = 1; 582 as->as_allbutsignature = ks; 583 as->as_signature_string_s = ts; 584 as->as_signature_string_e = te; 585 break; 586 587 case KEYWORD_COMMENT: 588 if (as->as_comment_s != (char *) NULL) 589 { 590 keynote_free_assertion(as); 591 keynote_errno = ERROR_SYNTAX; 592 return (struct assertion *) NULL; 593 } 594 595 as->as_comment_s = ts; 596 as->as_comment_e = te; 597 break; 598 } 599 600 seen_field = 1; 601 if (end_of_assertion == 1) 602 { 603 /* End of buffer, good termination */ 604 if ((te == as->as_buf + len) || (te + 1 == as->as_buf + len) || 605 (*(te) == '\0') || (*(te + 1) == '\0')) 606 break; 607 608 /* Check whether there's something else following */ 609 for (k = 1; te + k < as->as_buf + len && *(te + k) != '\n'; k++) 610 if (!isspace((int) *(te + k))) 611 { 612 printf("here %c\n", *(te + k)); 613 keynote_free_assertion(as); 614 keynote_errno = ERROR_SYNTAX; 615 return (struct assertion *) NULL; 616 } 617 618 break; /* Assertion is "properly" terminated */ 619 } 620 } 621 622 /* Check that the basic fields are there */ 623 if (as->as_authorizer_string_s == (char *) NULL) 624 { 625 keynote_free_assertion(as); 626 keynote_errno = ERROR_SYNTAX; 627 return (struct assertion *) NULL; 628 } 629 630 /* Signature generation/verification handling */ 631 if (assertion_flags & ASSERT_FLAG_SIGGEN) 632 { 633 if (keynote_fix_fields(as, 0) != RESULT_TRUE) 634 { 635 keynote_free_assertion(as); 636 return (struct assertion *) NULL; 637 } 638 } 639 else 640 if (assertion_flags & ASSERT_FLAG_SIGVER) 641 if (keynote_fix_fields(as, 1) != RESULT_TRUE) 642 { 643 keynote_free_assertion(as); 644 return (struct assertion *) NULL; 645 } 646 647 return as; 648 } 649