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