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