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