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