1 %{ 2 /* $OpenBSD: keynote.l,v 1.23 2015/11/19 19:48:27 tedu 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 = 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 = NULL; 115 return VARIABLE; 116 } 117 118 len = strlen(kntext) + 1; 119 knlval.string = calloc(len, sizeof(char)); 120 if (knlval.string == 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 = NULL; 146 return STRING; 147 } 148 149 len = strlen(kntext) + 1; 150 knlval.string = calloc(len, sizeof(char)); 151 if (knlval.string == 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 = NULL; 171 return STRING; 172 } 173 174 knlval.string = calloc(strlen(kntext) - 1, 175 sizeof(char)); 176 if (knlval.string == 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 != 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 = 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 != NULL) 231 memset(keynote_lex_list, 0, 232 keynote_max_lex_list * sizeof(struct lex_list)); 233 else 234 { 235 keynote_lex_list = calloc(keynote_max_lex_list, 236 sizeof(struct lex_list)); 237 if (keynote_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 == NULL) 258 return RESULT_TRUE; 259 260 for (i = 0; i < keynote_max_lex_list; i++) 261 if (keynote_lex_list[i].lex_s == 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 *) reallocarray(keynote_lex_list, 273 keynote_max_lex_list, 274 sizeof(struct lex_list)); 275 if (p == 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 keynote_lex_list = p; 290 keynote_lex_list[i].lex_s = s; 291 keynote_lex_list[i++].lex_type = type; 292 keynote_lex_counter++; 293 294 /* Zero out the rest */ 295 memset(&(keynote_lex_list[i]), 0, 296 (keynote_max_lex_list - i) * sizeof(struct lex_list)); 297 298 return RESULT_TRUE; 299 } 300 301 /* 302 * Remove string. 303 */ 304 void 305 keynote_lex_remove(void *s) 306 { 307 int i; 308 309 for (i = 0; i < keynote_max_lex_list; i++) 310 if (keynote_lex_list[i].lex_s == s) 311 { 312 memset(&(keynote_lex_list[i]), 0, sizeof(struct lex_list)); 313 keynote_lex_counter--; 314 return; 315 } 316 } 317 318 /* 319 * Return RESULT_TRUE if character is octal digit, RESULT_FALSE otherwise. 320 */ 321 static int 322 is_octal(char c) 323 { 324 switch (c) 325 { 326 case '0': case '1': case '2': case '3': 327 case '4': case '5': case '6': case '7': 328 return RESULT_TRUE; 329 330 default: 331 return RESULT_FALSE; 332 } 333 } 334 335 /* 336 * Return octal value (non-zero) if argument starts with such a 337 * representation, otherwise 0. 338 */ 339 static unsigned char 340 get_octal(char *s, int len, int *adv) 341 { 342 unsigned char res = 0; 343 344 if (*s == '0') 345 { 346 if (len > 0) 347 { 348 if (is_octal(*(s + 1))) 349 { 350 res = *(s + 1) - '0'; 351 *adv = 2; 352 353 if (is_octal(*(s + 2)) && (len - 1 > 0)) 354 { 355 res = res * 8 + (*(s + 2) - '0'); 356 *adv = 3; 357 } 358 } 359 } 360 } 361 else 362 if (is_octal(*s) && (len - 1 > 0)) /* Non-zero leading */ 363 { 364 if (is_octal(*(s + 1)) && 365 is_octal(*(s + 2))) 366 { 367 *adv = 3; 368 res = (((*s) - '0') * 64) + 369 (((*(s + 1)) - '0') * 8) + 370 ((*(s + 2)) - '0'); 371 } 372 } 373 374 return res; 375 } 376 377 /* 378 * Copy at most len characters to string s1 from string s2, taking 379 * care of escaped characters in the process. String s1 is assumed 380 * to have enough space, and be zero'ed. 381 */ 382 static void 383 mystrncpy(char *s1, char *s2, int len) 384 { 385 unsigned char c; 386 int advance; 387 388 if (len == 0) 389 return; 390 391 while (len-- > 0) 392 { 393 if (*s2 == '\\') 394 { 395 s2++; 396 397 if (len-- <= 0) 398 break; 399 400 if (*s2 == '\n') 401 { 402 while (isspace((unsigned char)*(++s2)) && (len-- > 0)) 403 ; 404 } 405 else 406 if ((c = get_octal(s2, len, &advance)) != 0) 407 { 408 len -= advance - 1; 409 s2 += advance; 410 *s1++ = c; 411 } 412 else 413 if (*s2 == 'n') /* Newline */ 414 { 415 *s1++ = '\n'; 416 s2++; 417 } 418 else 419 if (*s2 == 't') /* Tab */ 420 { 421 *s1++ = '\t'; 422 s2++; 423 } 424 else 425 if (*s2 == 'r') /* Linefeed */ 426 { 427 *s1++ = '\r'; 428 s2++; 429 } 430 else 431 if (*s2 == 'f') /* Formfeed */ 432 { 433 *s1++ = '\f'; 434 s2++; 435 } 436 else 437 if ((*s1++ = *s2++) == 0) 438 break; 439 440 continue; 441 } 442 443 if ((*s1++ = *s2++) == 0) 444 break; 445 } 446 } 447 448 /* 449 * Evaluate an assertion, with as->as_result holding the result. 450 * Return RESULT_TRUE if all ok. Also return the result. 451 */ 452 int 453 keynote_evaluate_assertion(struct assertion *as) 454 { 455 YY_BUFFER_STATE keynote_bs; 456 457 /* Non-existent Conditions field means highest return value */ 458 if (as->as_conditions_s == NULL) 459 { 460 as->as_result = keynote_current_session->ks_values_num - 1; 461 return RESULT_TRUE; 462 } 463 464 if (keynote_lex_init() != RESULT_TRUE) 465 return -1; 466 467 keynote_used_variable = 0; 468 keynote_init_list = as->as_env; /* Setup the local-init var list */ 469 470 keynote_bs = kn_scan_bytes(as->as_conditions_s, 471 as->as_conditions_e - as->as_conditions_s); 472 BEGIN(ACTIONSTRING); /* We're doing conditions-string parsing */ 473 first_tok = ACTSTR; 474 as->as_result = 0; 475 keynote_returnvalue = 0; 476 477 switch (knparse()) 478 { 479 case 1: /* Fall through */ 480 keynote_errno = ERROR_SYNTAX; 481 case -1: 482 as->as_result = 0; 483 break; 484 485 case 0: 486 as->as_result = keynote_returnvalue; 487 break; 488 } 489 490 keynote_env_cleanup(&keynote_temp_list, 1); 491 keynote_lex_zap(); 492 kn_delete_buffer(keynote_bs); 493 494 keynote_used_variable = 0; 495 keynote_returnvalue = 0; 496 keynote_temp_list = NULL; 497 keynote_init_list = NULL; 498 499 if (keynote_errno != 0) 500 return -1; 501 else 502 return RESULT_TRUE; 503 } 504 505 /* 506 * Parse/evaluate a key predicate field. 507 * Store keys in key predicate as keylist in as->as_keylist, if second 508 * argument is true. 509 */ 510 int 511 keynote_parse_keypred(struct assertion *as, int record) 512 { 513 YY_BUFFER_STATE keypred_state; 514 int p = 0, err; 515 516 if (as->as_keypred_s == NULL) 517 return keynote_current_session->ks_values_num - 1; 518 519 if (keynote_lex_init() != RESULT_TRUE) 520 return -1; 521 522 keynote_used_variable = 0; 523 keynote_returnvalue = 0; 524 keynote_justrecord = record; /* Just want the list of keys in predicate */ 525 keynote_init_list = as->as_env; 526 527 keypred_state = kn_scan_bytes(as->as_keypred_s, 528 as->as_keypred_e - as->as_keypred_s); 529 BEGIN(KEYPREDICATE); 530 first_tok = KEYPRE; 531 532 err = knparse(); 533 if (err != 0) 534 if (keynote_errno == 0) 535 keynote_errno = ERROR_SYNTAX; 536 537 kn_delete_buffer(keypred_state); 538 keynote_lex_zap(); 539 keynote_cleanup_kth(); 540 541 keynote_init_list = NULL; 542 keynote_justrecord = 0; 543 p = keynote_returnvalue; 544 keynote_returnvalue = 0; 545 546 if (record) 547 { 548 if (keynote_errno != 0) 549 { 550 keynote_keylist_free(keynote_keypred_keylist); 551 keynote_keypred_keylist = NULL; 552 return -1; 553 } 554 else 555 { 556 /* Mark for re-processing if/when environment changes */ 557 if (keynote_used_variable) 558 { 559 keynote_used_variable = 0; 560 as->as_internalflags |= ASSERT_IFLAG_WEIRDLICS; 561 } 562 563 if (as->as_keylist) 564 keynote_keylist_free(as->as_keylist); 565 as->as_keylist = keynote_keypred_keylist; 566 keynote_keypred_keylist = NULL; 567 return RESULT_TRUE; 568 } 569 } 570 else 571 return p; 572 } 573 574 /* Evaluate an authorizer or signature field. Return RESULT_TRUE on success. 575 * Store key in as->as_authorizer. Second argument is set only for Authorizer 576 * field parsing. 577 */ 578 int 579 keynote_evaluate_authorizer(struct assertion *as, int flag) 580 { 581 YY_BUFFER_STATE authorizer_state; 582 int err; 583 584 if (keynote_lex_init() != RESULT_TRUE) 585 return -1; 586 587 keynote_init_list = as->as_env; 588 keynote_justrecord = 1; 589 keynote_used_variable = 0; 590 591 if ((flag) && (as->as_authorizer != NULL)) 592 { 593 keynote_free_key(as->as_authorizer, as->as_signeralgorithm); 594 as->as_authorizer = NULL; 595 } 596 597 if (flag) 598 authorizer_state = kn_scan_bytes(as->as_authorizer_string_s, 599 as->as_authorizer_string_e - 600 as->as_authorizer_string_s); 601 else 602 authorizer_state = kn_scan_bytes(as->as_signature_string_s, 603 as->as_signature_string_e - 604 as->as_signature_string_s); 605 606 BEGIN(SIGNERINIT); 607 if (flag) 608 first_tok = SIGNERKEY; 609 else 610 first_tok = SIGNATUREENTRY; 611 612 err = knparse(); 613 if ((err != 0) && (keynote_errno == 0)) 614 keynote_errno = ERROR_SYNTAX; 615 616 kn_delete_buffer(authorizer_state); 617 keynote_lex_zap(); 618 619 keynote_justrecord = 0; 620 keynote_init_list = NULL; 621 keynote_returnvalue = 0; 622 623 if (keynote_keypred_keylist != NULL) 624 { 625 if (flag) 626 { 627 if (keynote_used_variable) 628 as->as_internalflags |= ASSERT_IFLAG_WEIRDAUTH; 629 630 as->as_authorizer = keynote_keypred_keylist->key_key; 631 as->as_signeralgorithm = keynote_keypred_keylist->key_alg; 632 } 633 else 634 { 635 if (keynote_used_variable) 636 as->as_internalflags |= ASSERT_IFLAG_WEIRDSIG; 637 638 as->as_signature = keynote_keypred_keylist->key_key; 639 } 640 641 keynote_keypred_keylist->key_key = NULL; 642 keynote_keylist_free(keynote_keypred_keylist); 643 keynote_keypred_keylist = NULL; 644 } 645 646 keynote_used_variable = 0; 647 648 if (keynote_errno != 0) 649 return -1; 650 else 651 return RESULT_TRUE; 652 } 653 654 /* 655 * Exportable front-end to keynote_get_private_key(). 656 */ 657 char * 658 kn_get_string(char *buf) 659 { 660 return keynote_get_private_key(buf); 661 } 662 663 /* 664 * Parse a private key -- actually, it can deal with any kind of string. 665 */ 666 char * 667 keynote_get_private_key(char *buf) 668 { 669 YY_BUFFER_STATE pkey; 670 char *s; 671 int err; 672 673 if (keynote_lex_init() != RESULT_TRUE) 674 return NULL; 675 676 keynote_privkey = NULL; 677 pkey = kn_scan_bytes(buf, strlen(buf)); 678 first_tok = PRIVATEKEY; 679 err = knparse(); 680 kn_delete_buffer(pkey); 681 keynote_lex_zap(); 682 683 if (err != 0) 684 { 685 if (keynote_privkey != NULL) 686 { 687 free(keynote_privkey); 688 keynote_privkey = NULL; 689 } 690 691 if (keynote_errno == 0) 692 keynote_errno = ERROR_SYNTAX; 693 694 return NULL; 695 } 696 697 s = keynote_privkey; 698 keynote_privkey = NULL; 699 return s; 700 } 701 702 /* 703 * Parse Local-Constants and KeyNote-Version fields. 704 */ 705 struct environment * 706 keynote_get_envlist(char *buf, char *bufend, int whichfield) 707 { 708 struct environment *en = NULL; 709 YY_BUFFER_STATE localinit_state; 710 int err; 711 712 if (keynote_lex_init() != RESULT_TRUE) 713 return NULL; 714 715 localinit_state = kn_scan_bytes(buf, bufend - buf); 716 if (whichfield == 0) 717 { 718 BEGIN(LOCALINIT); /* We're doing Local-Constants parsing */ 719 first_tok = LOCINI; 720 } 721 else 722 { 723 BEGIN(KEYNOTEVERSION); /* KeyNote-Version parsing */ 724 first_tok = KNVERSION; 725 } 726 727 err = knparse(); 728 if (err != 0) 729 if (keynote_errno == 0) 730 keynote_errno = ERROR_SYNTAX; 731 732 kn_delete_buffer(localinit_state); 733 keynote_lex_zap(); 734 735 if (!whichfield) 736 { 737 if (keynote_errno != 0) 738 keynote_env_cleanup(&keynote_init_list, 1); 739 else 740 en = keynote_init_list; 741 742 keynote_init_list = NULL; 743 } 744 745 /* Avoid compiler (-Wall) warnings. Never reached. */ 746 if (0) 747 { 748 yyunput(0, NULL); 749 } 750 751 return en; 752 } 753