1 %{ 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 <ctype.h> 28 29 #if STDC_HEADERS 30 #include <string.h> 31 #endif /* STDC_HEADERS */ 32 33 #if HAVE_UNISTD_H 34 #include <unistd.h> 35 #endif /* HAVE_UNISTD_H */ 36 37 #if TIME_WITH_SYS_TIME 38 #include <sys/time.h> 39 #include <time.h> 40 #else 41 #if HAVE_SYS_TIME_H 42 #include <sys/time.h> 43 #else 44 #include <time.h> 45 #endif 46 #endif 47 48 #include "k.tab.h" 49 #include "header.h" 50 #include "keynote.h" 51 #include "assertion.h" 52 53 static void mystrncpy(char *, char *, int); 54 55 struct lex_list 56 { 57 int lex_type; 58 void *lex_s; 59 }; 60 61 static struct lex_list *keynote_lex_list = (struct lex_list *) NULL; 62 static int keynote_max_lex_list = 32; 63 static int keynote_lex_counter = 0; 64 static int first_tok = 0; 65 %} 66 digit [0-9] 67 specnumber [1-9][0-9]* 68 number {digit}+ 69 flt {digit}+"."{digit}+ 70 vstring [a-zA-Z_][a-zA-Z0-9_]* 71 litstring \"(((\\\n)|(\\.)|([^\\\n\"]))*)\" 72 variable {vstring} 73 comment "#"[^\n]* 74 %s ACTIONSTRING LOCALINIT KEYPREDICATE SIGNERINIT KEYNOTEVERSION 75 %pointer 76 %option noyywrap never-interactive yylineno 77 %% 78 %{ 79 /* 80 * Return a preset token, so we can have more than one grammars 81 * in yacc. 82 */ 83 extern int first_tok; 84 85 if (first_tok) 86 { 87 int holdtok = first_tok; 88 89 first_tok = 0; 90 return holdtok; 91 } 92 %} 93 94 <KEYPREDICATE>{specnumber}"-of" { 95 knlval.intval = atoi(kntext); 96 return KOF; 97 } 98 <ACTIONSTRING,KEYPREDICATE>"(" return OPENPAREN; 99 <ACTIONSTRING,KEYPREDICATE>")" return CLOSEPAREN; 100 <ACTIONSTRING,KEYPREDICATE>"&&" return AND; 101 <ACTIONSTRING,KEYPREDICATE>"||" return OR; 102 <ACTIONSTRING>"+" return PLUS; 103 <ACTIONSTRING>"->" return HINT; 104 <ACTIONSTRING>"{" return OPENBLOCK; 105 <ACTIONSTRING>"}" return CLOSEBLOCK; 106 <ACTIONSTRING>";" return SEMICOLON; 107 <ACTIONSTRING>"!" return NOT; 108 <ACTIONSTRING>"~=" return REGEXP; 109 <ACTIONSTRING>"==" return EQ; 110 <ACTIONSTRING>"!=" return NE; 111 <ACTIONSTRING>"<" return LT; 112 <ACTIONSTRING>">" return GT; 113 <ACTIONSTRING>"<=" return LE; 114 <ACTIONSTRING>">=" return GE; 115 <ACTIONSTRING>"-" return MINUS; 116 <ACTIONSTRING>"*" return MULT; 117 <ACTIONSTRING>"/" return DIV; 118 <ACTIONSTRING>"%" return MOD; 119 <ACTIONSTRING>"^" return EXP; 120 "." return DOTT; 121 <ACTIONSTRING>"true" return TRUE; 122 <ACTIONSTRING>"false" return FALSE; 123 {comment} /* eat up comments */ 124 <LOCALINIT>"=" return EQQ; 125 <KEYPREDICATE>"," return COMMA; 126 <ACTIONSTRING,KEYPREDICATE,SIGNERINIT,LOCALINIT>{variable} { 127 if (keynote_exceptionflag || 128 keynote_donteval) 129 { 130 knlval.string = (char *) NULL; 131 return VARIABLE; 132 } 133 134 knlval.string = calloc(strlen(kntext) 135 + 1, 136 sizeof(char)); 137 if (knlval.string == (char *) NULL) 138 { 139 keynote_errno = ERROR_MEMORY; 140 return -1; 141 } 142 strcpy(knlval.string, kntext); 143 if (keynote_lex_add(knlval.string, 144 LEXTYPE_CHAR) == 145 -1) 146 return -1; 147 return VARIABLE; 148 } 149 "$" return DEREF; 150 <ACTIONSTRING>"@" return OPENNUM; 151 <ACTIONSTRING>"&" return OPENFLT; 152 <ACTIONSTRING>{flt} { 153 knlval.doubval = atof(kntext); 154 return FLOAT; 155 } 156 <KEYNOTEVERSION>{number} { 157 if (keynote_exceptionflag || 158 keynote_donteval) 159 { 160 knlval.string = (char *) NULL; 161 return STRING; 162 } 163 164 knlval.string = calloc(strlen(kntext) + 1, 165 sizeof(char)); 166 if (knlval.string == (char *) NULL) 167 { 168 keynote_errno = ERROR_MEMORY; 169 return -1; 170 } 171 strcpy(knlval.string, kntext); 172 if (keynote_lex_add(knlval.string, 173 LEXTYPE_CHAR) == -1) 174 return -1; 175 return STRING; 176 } 177 <ACTIONSTRING>{number} { 178 knlval.intval = atoi(kntext); 179 return NUM; 180 } 181 {litstring} { 182 if (keynote_exceptionflag || 183 keynote_donteval) 184 { 185 knlval.string = (char *) NULL; 186 return STRING; 187 } 188 189 knlval.string = calloc(strlen(kntext) - 1, 190 sizeof(char)); 191 if (knlval.string == (char *) NULL) 192 { 193 keynote_errno = ERROR_MEMORY; 194 return -1; 195 } 196 197 mystrncpy(knlval.string, kntext + 1, 198 strlen(kntext) - 2); 199 200 if (keynote_lex_add(knlval.string, 201 LEXTYPE_CHAR) == -1) 202 return -1; 203 return STRING; 204 } 205 [ \t\n] 206 . { keynote_errno = ERROR_SYNTAX; 207 return -1; 208 REJECT; /* Avoid -Wall warning. Not reached */ 209 } 210 %% 211 212 /* 213 * Zap everything. 214 */ 215 static void 216 keynote_lex_zap(void) 217 { 218 int i; 219 220 if (keynote_lex_counter == 0) 221 return; 222 223 for (i = 0; i < keynote_max_lex_list; i++) 224 if (keynote_lex_list[i].lex_s != (void *) NULL) 225 { 226 switch (keynote_lex_list[i].lex_type) 227 { 228 case LEXTYPE_CHAR: 229 free(keynote_lex_list[i].lex_s); 230 break; 231 } 232 233 keynote_lex_counter--; 234 keynote_lex_list[i].lex_s = (void *) NULL; 235 keynote_lex_list[i].lex_type = 0; 236 } 237 } 238 239 /* 240 * Initialize. 241 */ 242 static int 243 keynote_lex_init(void) 244 { 245 if (keynote_lex_list != (struct lex_list *) NULL) 246 memset(keynote_lex_list, 0, 247 keynote_max_lex_list * sizeof(struct lex_list)); 248 else 249 { 250 keynote_lex_list = (struct lex_list *) calloc(keynote_max_lex_list, 251 sizeof(struct lex_list)); 252 if (keynote_lex_list == (struct lex_list *) NULL) 253 { 254 keynote_errno = ERROR_MEMORY; 255 return -1; 256 } 257 } 258 259 return RESULT_TRUE; 260 } 261 262 /* 263 * Add the string in a list of allocated but "dangling" memory references. 264 * If out of memory, free the string and return -1 (and set keynote_errno). 265 */ 266 int 267 keynote_lex_add(void *s, int type) 268 { 269 struct lex_list *p; 270 int i; 271 272 if (s == (void *) NULL) 273 return RESULT_TRUE; 274 275 for (i = 0; i < keynote_max_lex_list; i++) 276 if (keynote_lex_list[i].lex_s == (void *) NULL) 277 { 278 keynote_lex_list[i].lex_s = (void *) s; 279 keynote_lex_list[i].lex_type = type; 280 keynote_lex_counter++; 281 return RESULT_TRUE; 282 } 283 284 /* Not enough space, increase the size of the array */ 285 keynote_max_lex_list *= 2; 286 287 p = (struct lex_list *) realloc(keynote_lex_list, 288 keynote_max_lex_list * 289 sizeof(struct lex_list)); 290 if (p == (struct lex_list *) NULL) 291 { 292 switch (type) 293 { 294 case LEXTYPE_CHAR: 295 free(s); 296 break; 297 } 298 299 keynote_max_lex_list /= 2; 300 keynote_errno = ERROR_MEMORY; 301 return -1; 302 } 303 304 if (p != keynote_lex_list) 305 { 306 free(keynote_lex_list); 307 keynote_lex_list = p; 308 } 309 310 keynote_lex_list[i].lex_s = s; 311 keynote_lex_list[i++].lex_type = type; 312 keynote_lex_counter++; 313 314 /* Zero out the rest */ 315 memset(&(keynote_lex_list[i]), 0, 316 (keynote_max_lex_list - i) * sizeof(struct lex_list)); 317 318 return RESULT_TRUE; 319 } 320 321 /* 322 * Remove string. 323 */ 324 void 325 keynote_lex_remove(void *s) 326 { 327 int i; 328 329 for (i = 0; i < keynote_max_lex_list; i++) 330 if (keynote_lex_list[i].lex_s == s) 331 { 332 memset(&(keynote_lex_list[i]), 0, sizeof(struct lex_list)); 333 keynote_lex_counter--; 334 return; 335 } 336 } 337 338 /* 339 * Return RESULT_TRUE if character is octal digit, RESULT_FALSE otherwise. 340 */ 341 static int 342 is_octal(char c) 343 { 344 switch (c) 345 { 346 case '0': case '1': case '2': case '3': 347 case '4': case '5': case '6': case '7': 348 return RESULT_TRUE; 349 350 default: 351 return RESULT_FALSE; 352 } 353 } 354 355 /* 356 * Return octal value (non-zero) if argument starts with such a 357 * representation, otherwise 0. 358 */ 359 static unsigned char 360 get_octal(char *s, int len, int *adv) 361 { 362 unsigned char res = 0; 363 364 if (*s == '0') 365 { 366 if (len > 0) 367 { 368 if (is_octal(*(s + 1))) 369 { 370 res = *(s + 1) - '0'; 371 *adv = 2; 372 373 if (is_octal(*(s + 2)) && (len - 1 > 0)) 374 { 375 res = res * 8 + (*(s + 2) - '0'); 376 *adv = 3; 377 } 378 } 379 } 380 } 381 else 382 if (is_octal(*s) && (len - 1 > 0)) /* Non-zero leading */ 383 { 384 if (is_octal(*(s + 1)) && 385 is_octal(*(s + 2))) 386 { 387 *adv = 3; 388 res = (((*s) - '0') * 64) + 389 (((*(s + 1)) - '0') * 8) + 390 ((*(s + 2)) - '0'); 391 } 392 } 393 394 return res; 395 } 396 397 /* 398 * Copy at most len characters to string s1 from string s2, taking 399 * care of escaped characters in the process. String s1 is assumed 400 * to have enough space, and be zero'ed. 401 */ 402 static void 403 mystrncpy(char *s1, char *s2, int len) 404 { 405 unsigned char c; 406 int advance; 407 408 if (len == 0) 409 return; 410 411 while (len-- > 0) 412 { 413 if (*s2 == '\\') 414 { 415 s2++; 416 417 if (len-- <= 0) 418 break; 419 420 if (*s2 == '\n') 421 { 422 while (isspace((int) *(++s2)) && (len-- > 0)) 423 ; 424 } 425 else 426 if ((c = get_octal(s2, len, &advance)) != 0) 427 { 428 len -= advance - 1; 429 s2 += advance; 430 *s1++ = c; 431 } 432 else 433 if (*s2 == 'n') /* Newline */ 434 { 435 *s1++ = '\n'; 436 s2++; 437 } 438 else 439 if (*s2 == 't') /* Tab */ 440 { 441 *s1++ = '\t'; 442 s2++; 443 } 444 else 445 if (*s2 == 'r') /* Linefeed */ 446 { 447 *s1++ = '\r'; 448 s2++; 449 } 450 else 451 if (*s2 == 'f') /* Formfeed */ 452 { 453 *s1++ = '\f'; 454 s2++; 455 } 456 else 457 if ((*s1++ = *s2++) == 0) 458 break; 459 460 continue; 461 } 462 463 if ((*s1++ = *s2++) == 0) 464 break; 465 } 466 } 467 468 /* 469 * Evaluate an assertion, with as->as_result holding the result. 470 * Return RESULT_TRUE if all ok. Also return the result. 471 */ 472 int 473 keynote_evaluate_assertion(struct assertion *as) 474 { 475 YY_BUFFER_STATE keynote_bs; 476 477 /* Non-existant Conditions field means highest return value */ 478 if (as->as_conditions_s == (char *) NULL) 479 { 480 as->as_result = keynote_current_session->ks_values_num - 1; 481 return RESULT_TRUE; 482 } 483 484 if (keynote_lex_init() != RESULT_TRUE) 485 return -1; 486 487 keynote_used_variable = 0; 488 keynote_init_list = as->as_env; /* Setup the local-init var list */ 489 490 keynote_bs = kn_scan_bytes(as->as_conditions_s, 491 as->as_conditions_e - as->as_conditions_s); 492 BEGIN(ACTIONSTRING); /* We're doing conditions-string parsing */ 493 first_tok = ACTSTR; 494 as->as_result = 0; 495 keynote_returnvalue = 0; 496 497 switch (knparse()) 498 { 499 case 1: /* Fall through */ 500 keynote_errno = ERROR_SYNTAX; 501 case -1: 502 as->as_result = 0; 503 break; 504 505 case 0: 506 as->as_result = keynote_returnvalue; 507 break; 508 } 509 510 keynote_env_cleanup(&keynote_temp_list, 1); 511 keynote_lex_zap(); 512 kn_delete_buffer(keynote_bs); 513 514 keynote_used_variable = 0; 515 keynote_returnvalue = 0; 516 keynote_temp_list = (struct environment *) NULL; 517 keynote_init_list = (struct environment *) NULL; 518 519 if (keynote_errno != 0) 520 return -1; 521 else 522 return RESULT_TRUE; 523 } 524 525 /* 526 * Parse/evaluate a key predicate field. 527 * Store keys in key predicate as keylist in as->as_keylist, if second 528 * argument is true. 529 */ 530 int 531 keynote_parse_keypred(struct assertion *as, int record) 532 { 533 YY_BUFFER_STATE keypred_state; 534 int p = 0, err; 535 536 if (as->as_keypred_s == (char *) NULL) 537 return keynote_current_session->ks_values_num - 1; 538 539 if (keynote_lex_init() != RESULT_TRUE) 540 return -1; 541 542 keynote_used_variable = 0; 543 keynote_returnvalue = 0; 544 keynote_justrecord = record; /* Just want the list of keys in predicate */ 545 keynote_init_list = as->as_env; 546 547 keypred_state = kn_scan_bytes(as->as_keypred_s, 548 as->as_keypred_e - as->as_keypred_s); 549 BEGIN(KEYPREDICATE); 550 first_tok = KEYPRE; 551 552 err = knparse(); 553 if (err != 0) 554 if (keynote_errno == 0) 555 keynote_errno = ERROR_SYNTAX; 556 557 kn_delete_buffer(keypred_state); 558 keynote_lex_zap(); 559 keynote_cleanup_kth(); 560 561 keynote_init_list = (struct environment *) NULL; 562 keynote_justrecord = 0; 563 p = keynote_returnvalue; 564 keynote_returnvalue = 0; 565 566 if (record) 567 { 568 if (keynote_errno != 0) 569 { 570 keynote_keylist_free(keynote_keypred_keylist); 571 keynote_keypred_keylist = (struct keylist *) NULL; 572 return -1; 573 } 574 else 575 { 576 /* Mark for re-processing if/when environment changes */ 577 if (keynote_used_variable) 578 { 579 keynote_used_variable = 0; 580 as->as_internalflags |= ASSERT_IFLAG_WEIRDLICS; 581 } 582 583 if (as->as_keylist) 584 keynote_keylist_free(as->as_keylist); 585 as->as_keylist = keynote_keypred_keylist; 586 keynote_keypred_keylist = (struct keylist *) NULL; 587 return RESULT_TRUE; 588 } 589 } 590 else 591 return p; 592 } 593 594 /* Evaluate an authorizer or signature field. Return RESULT_TRUE on success. 595 * Store key in as->as_authorizer. Second argument is set only for Authorizer 596 * field parsing. 597 */ 598 int 599 keynote_evaluate_authorizer(struct assertion *as, int flag) 600 { 601 YY_BUFFER_STATE authorizer_state; 602 int err; 603 604 if (keynote_lex_init() != RESULT_TRUE) 605 return -1; 606 607 keynote_init_list = as->as_env; 608 keynote_justrecord = 1; 609 keynote_used_variable = 0; 610 611 if ((flag) && (as->as_authorizer != (void *) NULL)) 612 { 613 keynote_free_key(as->as_authorizer, as->as_signeralgorithm); 614 as->as_authorizer = (void *) NULL; 615 } 616 617 if (flag) 618 authorizer_state = kn_scan_bytes(as->as_authorizer_string_s, 619 as->as_authorizer_string_e - 620 as->as_authorizer_string_s); 621 else 622 authorizer_state = kn_scan_bytes(as->as_signature_string_s, 623 as->as_signature_string_e - 624 as->as_signature_string_s); 625 626 BEGIN(SIGNERINIT); 627 if (flag) 628 first_tok = SIGNERKEY; 629 else 630 first_tok = SIGNATUREENTRY; 631 632 err = knparse(); 633 if ((err != 0) && (keynote_errno == 0)) 634 keynote_errno = ERROR_SYNTAX; 635 636 kn_delete_buffer(authorizer_state); 637 keynote_lex_zap(); 638 639 keynote_justrecord = 0; 640 keynote_init_list = (struct environment *) NULL; 641 keynote_returnvalue = 0; 642 643 if (keynote_keypred_keylist != (struct keylist *) NULL) 644 { 645 if (flag) 646 { 647 if (keynote_used_variable) 648 as->as_internalflags |= ASSERT_IFLAG_WEIRDAUTH; 649 650 as->as_authorizer = keynote_keypred_keylist->key_key; 651 as->as_signeralgorithm = keynote_keypred_keylist->key_alg; 652 } 653 else 654 { 655 if (keynote_used_variable) 656 as->as_internalflags |= ASSERT_IFLAG_WEIRDSIG; 657 658 as->as_signature = keynote_keypred_keylist->key_key; 659 } 660 661 keynote_keypred_keylist->key_key = (char *) NULL; 662 keynote_keylist_free(keynote_keypred_keylist); 663 keynote_keypred_keylist = (struct keylist *) NULL; 664 } 665 666 keynote_used_variable = 0; 667 668 if (keynote_errno != 0) 669 return -1; 670 else 671 return RESULT_TRUE; 672 } 673 674 /* 675 * Exportable front-end to keynote_get_private_key(). 676 */ 677 char * 678 kn_get_string(char *buf) 679 { 680 return keynote_get_private_key(buf); 681 } 682 683 /* 684 * Parse a private key -- actually, it can deal with any kind of string. 685 */ 686 char * 687 keynote_get_private_key(char *buf) 688 { 689 YY_BUFFER_STATE pkey; 690 char *s; 691 int err; 692 693 if (keynote_lex_init() != RESULT_TRUE) 694 return (char *) NULL; 695 696 keynote_privkey = (char *) NULL; 697 pkey = kn_scan_bytes(buf, strlen(buf)); 698 first_tok = PRIVATEKEY; 699 err = knparse(); 700 kn_delete_buffer(pkey); 701 keynote_lex_zap(); 702 703 if (err != 0) 704 { 705 if (keynote_privkey != (char *) NULL) 706 { 707 free(keynote_privkey); 708 keynote_privkey = (char *) NULL; 709 } 710 711 if (keynote_errno == 0) 712 keynote_errno = ERROR_SYNTAX; 713 714 return (char *) NULL; 715 } 716 717 s = keynote_privkey; 718 keynote_privkey = (char *) NULL; 719 return s; 720 } 721 722 /* 723 * Parse Local-Constants and KeyNote-Version fields. 724 */ 725 struct environment * 726 keynote_get_envlist(char *buf, char *bufend, int whichfield) 727 { 728 struct environment *en = (struct environment *) NULL; 729 YY_BUFFER_STATE localinit_state; 730 int err; 731 732 if (keynote_lex_init() != RESULT_TRUE) 733 return (struct environment *) NULL; 734 735 localinit_state = kn_scan_bytes(buf, bufend - buf); 736 if (whichfield == 0) 737 { 738 BEGIN(LOCALINIT); /* We're doing Local-Constants parsing */ 739 first_tok = LOCINI; 740 } 741 else 742 { 743 BEGIN(KEYNOTEVERSION); /* KeyNote-Version parsing */ 744 first_tok = KNVERSION; 745 } 746 747 err = knparse(); 748 if (err != 0) 749 if (keynote_errno == 0) 750 keynote_errno = ERROR_SYNTAX; 751 752 kn_delete_buffer(localinit_state); 753 keynote_lex_zap(); 754 755 if (!whichfield) 756 { 757 if (keynote_errno != 0) 758 keynote_env_cleanup(&keynote_init_list, 1); 759 else 760 en = keynote_init_list; 761 762 keynote_init_list = (struct environment *) NULL; 763 } 764 765 /* Avoid compiler (-Wall) warnings. Never reached. */ 766 if (0) 767 { 768 yyunput(0, NULL); 769 yy_flex_realloc(0, NULL); 770 } 771 772 return en; 773 } 774