1 %{ 2 /* $OpenBSD: keynote.l,v 1.7 2000/02/12 00:26:16 angelos 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 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 /* 82 * Return a preset token, so we can have more than one grammars 83 * in yacc. 84 */ 85 extern int first_tok; 86 87 if (first_tok) 88 { 89 int holdtok = first_tok; 90 91 first_tok = 0; 92 return holdtok; 93 } 94 %} 95 96 <KEYPREDICATE>{specnumber}"-of" { 97 knlval.intval = atoi(kntext); 98 return KOF; 99 } 100 <ACTIONSTRING,KEYPREDICATE>"(" return OPENPAREN; 101 <ACTIONSTRING,KEYPREDICATE>")" return CLOSEPAREN; 102 <ACTIONSTRING,KEYPREDICATE>"&&" return AND; 103 <ACTIONSTRING,KEYPREDICATE>"||" return OR; 104 <ACTIONSTRING>"+" return PLUS; 105 <ACTIONSTRING>"->" return HINT; 106 <ACTIONSTRING>"{" return OPENBLOCK; 107 <ACTIONSTRING>"}" return CLOSEBLOCK; 108 <ACTIONSTRING>";" return SEMICOLON; 109 <ACTIONSTRING>"!" return NOT; 110 <ACTIONSTRING>"~=" return REGEXP; 111 <ACTIONSTRING>"==" return EQ; 112 <ACTIONSTRING>"!=" return NE; 113 <ACTIONSTRING>"<" return LT; 114 <ACTIONSTRING>">" return GT; 115 <ACTIONSTRING>"<=" return LE; 116 <ACTIONSTRING>">=" return GE; 117 <ACTIONSTRING>"-" return MINUS; 118 <ACTIONSTRING>"*" return MULT; 119 <ACTIONSTRING>"/" return DIV; 120 <ACTIONSTRING>"%" return MOD; 121 <ACTIONSTRING>"^" return EXP; 122 "." return DOTT; 123 <ACTIONSTRING>"true" return TRUE; 124 <ACTIONSTRING>"false" return FALSE; 125 {comment} /* eat up comments */ 126 <LOCALINIT>"=" return EQQ; 127 <KEYPREDICATE>"," return COMMA; 128 <ACTIONSTRING,KEYPREDICATE,SIGNERINIT,LOCALINIT>{variable} { 129 if (keynote_exceptionflag || 130 keynote_donteval) 131 { 132 knlval.string = (char *) NULL; 133 return VARIABLE; 134 } 135 136 knlval.string = calloc(strlen(kntext) 137 + 1, 138 sizeof(char)); 139 if (knlval.string == (char *) NULL) 140 { 141 keynote_errno = ERROR_MEMORY; 142 return -1; 143 } 144 strcpy(knlval.string, kntext); 145 if (keynote_lex_add(knlval.string, 146 LEXTYPE_CHAR) == 147 -1) 148 return -1; 149 return VARIABLE; 150 } 151 "$" return DEREF; 152 <ACTIONSTRING>"@" return OPENNUM; 153 <ACTIONSTRING>"&" return OPENFLT; 154 <ACTIONSTRING>{flt} { 155 knlval.doubval = atof(kntext); 156 return FLOAT; 157 } 158 <KEYNOTEVERSION>{number} { 159 if (keynote_exceptionflag || 160 keynote_donteval) 161 { 162 knlval.string = (char *) NULL; 163 return STRING; 164 } 165 166 knlval.string = calloc(strlen(kntext) + 1, 167 sizeof(char)); 168 if (knlval.string == (char *) NULL) 169 { 170 keynote_errno = ERROR_MEMORY; 171 return -1; 172 } 173 strcpy(knlval.string, kntext); 174 if (keynote_lex_add(knlval.string, 175 LEXTYPE_CHAR) == -1) 176 return -1; 177 return STRING; 178 } 179 <ACTIONSTRING>{number} { 180 knlval.intval = atoi(kntext); 181 return NUM; 182 } 183 {litstring} { 184 if (keynote_exceptionflag || 185 keynote_donteval) 186 { 187 knlval.string = (char *) NULL; 188 return STRING; 189 } 190 191 knlval.string = calloc(strlen(kntext) - 1, 192 sizeof(char)); 193 if (knlval.string == (char *) NULL) 194 { 195 keynote_errno = ERROR_MEMORY; 196 return -1; 197 } 198 199 mystrncpy(knlval.string, kntext + 1, 200 strlen(kntext) - 2); 201 202 if (keynote_lex_add(knlval.string, 203 LEXTYPE_CHAR) == -1) 204 return -1; 205 return STRING; 206 } 207 [ \t\n] 208 . { keynote_errno = ERROR_SYNTAX; 209 return -1; 210 REJECT; /* Avoid -Wall warning. Not reached */ 211 } 212 %% 213 214 /* 215 * Zap everything. 216 */ 217 static void 218 keynote_lex_zap(void) 219 { 220 int i; 221 222 if (keynote_lex_counter == 0) 223 return; 224 225 for (i = 0; i < keynote_max_lex_list; i++) 226 if (keynote_lex_list[i].lex_s != (void *) NULL) 227 { 228 switch (keynote_lex_list[i].lex_type) 229 { 230 case LEXTYPE_CHAR: 231 free(keynote_lex_list[i].lex_s); 232 break; 233 } 234 235 keynote_lex_counter--; 236 keynote_lex_list[i].lex_s = (void *) NULL; 237 keynote_lex_list[i].lex_type = 0; 238 } 239 } 240 241 /* 242 * Initialize. 243 */ 244 static int 245 keynote_lex_init(void) 246 { 247 if (keynote_lex_list != (struct lex_list *) NULL) 248 memset(keynote_lex_list, 0, 249 keynote_max_lex_list * sizeof(struct lex_list)); 250 else 251 { 252 keynote_lex_list = (struct lex_list *) calloc(keynote_max_lex_list, 253 sizeof(struct lex_list)); 254 if (keynote_lex_list == (struct lex_list *) NULL) 255 { 256 keynote_errno = ERROR_MEMORY; 257 return -1; 258 } 259 } 260 261 return RESULT_TRUE; 262 } 263 264 /* 265 * Add the string in a list of allocated but "dangling" memory references. 266 * If out of memory, free the string and return -1 (and set keynote_errno). 267 */ 268 int 269 keynote_lex_add(void *s, int type) 270 { 271 struct lex_list *p; 272 int i; 273 274 if (s == (void *) NULL) 275 return RESULT_TRUE; 276 277 for (i = 0; i < keynote_max_lex_list; i++) 278 if (keynote_lex_list[i].lex_s == (void *) NULL) 279 { 280 keynote_lex_list[i].lex_s = (void *) s; 281 keynote_lex_list[i].lex_type = type; 282 keynote_lex_counter++; 283 return RESULT_TRUE; 284 } 285 286 /* Not enough space, increase the size of the array */ 287 keynote_max_lex_list *= 2; 288 289 p = (struct lex_list *) realloc(keynote_lex_list, 290 keynote_max_lex_list * 291 sizeof(struct lex_list)); 292 if (p == (struct lex_list *) NULL) 293 { 294 switch (type) 295 { 296 case LEXTYPE_CHAR: 297 free(s); 298 break; 299 } 300 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(*(++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 third 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 as->as_keylist = keynote_keypred_keylist; 585 keynote_keypred_keylist = (struct keylist *) NULL; 586 return RESULT_TRUE; 587 } 588 } 589 else 590 return p; 591 } 592 593 /* Evaluate an authorizer or signature field. Return RESULT_TRUE on success. 594 * Store key in as->as_authorizer. Second argument is set only for Authorizer 595 * field parsing. 596 */ 597 int 598 keynote_evaluate_authorizer(struct assertion *as, int flag) 599 { 600 YY_BUFFER_STATE authorizer_state; 601 int err; 602 603 if (keynote_lex_init() != RESULT_TRUE) 604 return -1; 605 606 keynote_init_list = as->as_env; 607 keynote_justrecord = 1; 608 keynote_used_variable = 0; 609 610 if ((flag) && (as->as_authorizer != (void *) NULL)) 611 { 612 keynote_free_key(as->as_authorizer, as->as_signeralgorithm); 613 as->as_authorizer = (void *) NULL; 614 } 615 616 if (flag) 617 authorizer_state = kn_scan_bytes(as->as_authorizer_string_s, 618 as->as_authorizer_string_e - 619 as->as_authorizer_string_s); 620 else 621 authorizer_state = kn_scan_bytes(as->as_signature_string_s, 622 as->as_signature_string_e - 623 as->as_signature_string_s); 624 625 BEGIN(SIGNERINIT); 626 if (flag) 627 first_tok = SIGNERKEY; 628 else 629 first_tok = SIGNATUREENTRY; 630 631 err = knparse(); 632 if ((err != 0) && (keynote_errno == 0)) 633 keynote_errno = ERROR_SYNTAX; 634 635 kn_delete_buffer(authorizer_state); 636 keynote_lex_zap(); 637 638 keynote_justrecord = 0; 639 keynote_init_list = (struct environment *) NULL; 640 keynote_returnvalue = 0; 641 642 if (keynote_keypred_keylist != (struct keylist *) NULL) 643 { 644 if (flag) 645 { 646 if (keynote_used_variable) 647 as->as_internalflags |= ASSERT_IFLAG_WEIRDAUTH; 648 649 as->as_authorizer = keynote_keypred_keylist->key_key; 650 as->as_signeralgorithm = keynote_keypred_keylist->key_alg; 651 } 652 else 653 { 654 if (keynote_used_variable) 655 as->as_internalflags |= ASSERT_IFLAG_WEIRDSIG; 656 657 as->as_signature = keynote_keypred_keylist->key_key; 658 } 659 660 keynote_keypred_keylist->key_key = (char *) NULL; 661 keynote_keylist_free(keynote_keypred_keylist); 662 keynote_keypred_keylist = (struct keylist *) NULL; 663 } 664 665 keynote_used_variable = 0; 666 667 if (keynote_errno != 0) 668 return -1; 669 else 670 return RESULT_TRUE; 671 } 672 673 /* 674 * Parse a private key. 675 */ 676 char * 677 keynote_get_private_key(char *buf) 678 { 679 YY_BUFFER_STATE pkey; 680 char *s; 681 int err; 682 683 if (keynote_lex_init() != RESULT_TRUE) 684 return (char *) NULL; 685 686 keynote_privkey = (char *) NULL; 687 pkey = kn_scan_bytes(buf, strlen(buf)); 688 first_tok = PRIVATEKEY; 689 err = knparse(); 690 kn_delete_buffer(pkey); 691 keynote_lex_zap(); 692 693 if (err != 0) 694 { 695 if (keynote_privkey != (char *) NULL) 696 { 697 free(keynote_privkey); 698 keynote_privkey = (char *) NULL; 699 } 700 701 if (keynote_errno == 0) 702 keynote_errno = ERROR_SYNTAX; 703 704 return (char *) NULL; 705 } 706 707 s = keynote_privkey; 708 keynote_privkey = (char *) NULL; 709 return s; 710 } 711 712 /* 713 * Parse Local-Constants and KeyNote-Version fields. 714 */ 715 struct environment * 716 keynote_get_envlist(char *buf, char *bufend, int whichfield) 717 { 718 struct environment *en = (struct environment *) NULL; 719 YY_BUFFER_STATE localinit_state; 720 int err; 721 722 if (keynote_lex_init() != RESULT_TRUE) 723 return (struct environment *) NULL; 724 725 localinit_state = kn_scan_bytes(buf, bufend - buf); 726 if (whichfield == 0) 727 { 728 BEGIN(LOCALINIT); /* We're doing Local-Constants parsing */ 729 first_tok = LOCINI; 730 } 731 else 732 { 733 BEGIN(KEYNOTEVERSION); /* KeyNote-Version parsing */ 734 first_tok = KNVERSION; 735 } 736 737 err = knparse(); 738 if (err != 0) 739 if (keynote_errno == 0) 740 keynote_errno = ERROR_SYNTAX; 741 742 kn_delete_buffer(localinit_state); 743 keynote_lex_zap(); 744 745 if (!whichfield) 746 { 747 if (keynote_errno != 0) 748 keynote_env_cleanup(&keynote_init_list, 1); 749 else 750 en = keynote_init_list; 751 752 keynote_init_list = (struct environment *) NULL; 753 } 754 755 /* Avoid compiler (-Wall) warnings. Never reached. */ 756 if (0) 757 { 758 yyunput(0, NULL); 759 yy_flex_realloc(0, NULL); 760 } 761 762 return en; 763 } 764