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