1 /* $OpenBSD: environment.c,v 1.17 2003/04/02 23:01:10 millert Exp $ */ 2 /* 3 * The author of this code is Angelos D. Keromytis (angelos@dsl.cis.upenn.edu) 4 * 5 * This code was written by Angelos D. Keromytis in Philadelphia, PA, USA, 6 * in April-May 1998 7 * 8 * Copyright (C) 1998, 1999 by Angelos D. Keromytis. 9 * 10 * Permission to use, copy, and modify this software with or without fee 11 * is hereby granted, provided that this entire notice is included in 12 * all copies of any software which is or includes a copy or 13 * modification of this software. 14 * 15 * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR 16 * IMPLIED WARRANTY. IN PARTICULAR, THE AUTHORS MAKES NO 17 * REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE 18 * MERCHANTABILITY OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR 19 * PURPOSE. 20 */ 21 22 #if HAVE_CONFIG_H 23 #include "config.h" 24 #endif /* HAVE_CONFIG_H */ 25 26 #include <sys/types.h> 27 #include <stdlib.h> 28 #include <stdio.h> 29 #include <ctype.h> 30 31 #if STDC_HEADERS 32 #include <string.h> 33 #if !defined(HAVE_MEMCPY) 34 #define memcpy(d, s, n) bcopy ((s), (d), (n)) 35 #endif /* !HAVE_MEMCPY */ 36 #endif /* STDC_HEADERS */ 37 38 #if HAVE_MEMORY_H 39 #include <memory.h> 40 #endif /* HAVE_MEMORY_H */ 41 42 #if HAVE_FCNTL_H 43 #include <fcntl.h> 44 #endif /* HAVE_FCNTL_H */ 45 46 #if HAVE_IO_H 47 #include <io.h> 48 #elif HAVE_UNISTD_H 49 #include <unistd.h> 50 #endif /* HAVE_IO_H */ 51 52 #include "header.h" 53 #include "keynote.h" 54 #include "assertion.h" 55 56 static int sessioncounter = 0; 57 58 char **keynote_values = (char **) NULL; 59 char *keynote_privkey = (char *) NULL; 60 61 struct assertion *keynote_current_assertion = (struct assertion *) NULL; 62 63 struct environment *keynote_init_list = (struct environment *) NULL; 64 struct environment *keynote_temp_list = (struct environment *) NULL; 65 66 struct keylist *keynote_keypred_keylist = (struct keylist *) NULL; 67 68 struct keynote_session *keynote_sessions[SESSIONTABLESIZE]; 69 struct keynote_session *keynote_current_session = NULL; 70 71 int keynote_exceptionflag = 0; 72 int keynote_used_variable = 0; 73 int keynote_returnvalue = 0; 74 int keynote_justrecord = 0; 75 int keynote_donteval = 0; 76 int keynote_errno = 0; 77 78 /* 79 * Construct the _ACTION_AUTHORIZERS variable value. 80 */ 81 static char * 82 keynote_get_action_authorizers(char *name) 83 { 84 struct keylist *kl; 85 size_t cachesize; 86 int len; 87 88 if (!strcmp(name, KEYNOTE_CALLBACK_CLEANUP) || 89 !strcmp(name, KEYNOTE_CALLBACK_INITIALIZE)) 90 { 91 if (keynote_current_session->ks_authorizers_cache != (char *) NULL) 92 { 93 free(keynote_current_session->ks_authorizers_cache); 94 keynote_current_session->ks_authorizers_cache = (char *) NULL; 95 } 96 97 return ""; 98 } 99 100 if (keynote_current_session->ks_authorizers_cache != (char *) NULL) 101 return keynote_current_session->ks_authorizers_cache; 102 103 for (cachesize = 0, kl = keynote_current_session->ks_action_authorizers; 104 kl != (struct keylist *) NULL; 105 kl = kl->key_next) 106 if (kl->key_stringkey != (char *) NULL) 107 cachesize += strlen(kl->key_stringkey) + 1; 108 109 if (cachesize == 0) 110 return ""; 111 112 keynote_current_session->ks_authorizers_cache = 113 (char *) calloc(cachesize, sizeof(char)); 114 if (keynote_current_session->ks_authorizers_cache == (char *) NULL) 115 { 116 keynote_errno = ERROR_MEMORY; 117 return (char *) NULL; 118 } 119 120 for (len = 0, kl = keynote_current_session->ks_action_authorizers; 121 kl != (struct keylist *) NULL; 122 kl = kl->key_next) 123 if (kl->key_stringkey != (char *) NULL) 124 { 125 #if !defined(HAVE_SNPRINTF) 126 sprintf(keynote_current_session->ks_authorizers_cache + len, 127 "%s,", kl->key_stringkey); 128 #else /* !HAVE_SNPRINTF */ 129 snprintf(keynote_current_session->ks_authorizers_cache + len, 130 cachesize - len, "%s,", kl->key_stringkey); 131 #endif /* !HAVE_SNPRINTF */ 132 len += strlen(kl->key_stringkey) + 1; 133 } 134 135 keynote_current_session->ks_authorizers_cache[len - 1] = '\0'; 136 return keynote_current_session->ks_authorizers_cache; 137 } 138 139 /* 140 * Construct the _VALUES variable value. 141 */ 142 static char * 143 keynote_get_values(char *name) 144 { 145 int i, len; 146 size_t cachesize; 147 148 if (!strcmp(name, KEYNOTE_CALLBACK_CLEANUP) || 149 !strcmp(name, KEYNOTE_CALLBACK_INITIALIZE)) 150 { 151 if (keynote_current_session->ks_values_cache != (char *) NULL) 152 { 153 free(keynote_current_session->ks_values_cache); 154 keynote_current_session->ks_values_cache = (char *) NULL; 155 } 156 157 return ""; 158 } 159 160 if (keynote_current_session->ks_values_cache != (char *) NULL) 161 return keynote_current_session->ks_values_cache; 162 163 for (cachesize = 0, i = 0; i < keynote_current_session->ks_values_num; i++) 164 cachesize += strlen(keynote_current_session->ks_values[i]) + 1; 165 166 if (cachesize == 0) 167 return ""; 168 169 keynote_current_session->ks_values_cache = 170 (char *) calloc(cachesize, sizeof(char)); 171 if (keynote_current_session->ks_values_cache == (char *) NULL) 172 { 173 keynote_errno = ERROR_MEMORY; 174 return (char *) NULL; 175 } 176 177 for (len = 0, i = 0; i < keynote_current_session->ks_values_num; i++) 178 { 179 #if !defined(HAVE_SNPRINTF) 180 sprintf(keynote_current_session->ks_values_cache + len, 181 "%s,", keynote_current_session->ks_values[i]); 182 #else /* !HAVE_SNPRINTF */ 183 snprintf(keynote_current_session->ks_values_cache + len, 184 cachesize - len, "%s,", keynote_current_session->ks_values[i]); 185 #endif /* !HAVE_SNPRINTF */ 186 len += strlen(keynote_current_session->ks_values[i]) + 1; 187 } 188 189 keynote_current_session->ks_values_cache[len - 1] = '\0'; 190 return keynote_current_session->ks_values_cache; 191 } 192 193 /* 194 * Free an environment structure. 195 */ 196 void 197 keynote_free_env(struct environment *en) 198 { 199 if (en == (struct environment *) NULL) 200 return; 201 202 if (en->env_name != (char *) NULL) 203 free(en->env_name); 204 205 if (en->env_flags & ENVIRONMENT_FLAG_REGEX) 206 regfree(&(en->env_regex)); 207 208 if (!(en->env_flags & ENVIRONMENT_FLAG_FUNC)) 209 { 210 if (en->env_value != (char *) NULL) 211 free(en->env_value); 212 } 213 else 214 ((char * (*) (char *))en->env_value)(KEYNOTE_CALLBACK_CLEANUP); 215 216 free(en); 217 } 218 219 /* 220 * Lookup for variable "name" in the hash table. If hashsize is 1, 221 * then the second argument is actually a pointer to a list. Last 222 * argument specifies case-insensitivity. 223 */ 224 char * 225 keynote_env_lookup(char *name, struct environment **table, 226 unsigned int hashsize) 227 { 228 struct environment *en; 229 230 for (en = table[keynote_stringhash(name, hashsize)]; 231 en != (struct environment *) NULL; 232 en = en->env_next) 233 if (((en->env_flags & ENVIRONMENT_FLAG_REGEX) && 234 (regexec(&(en->env_regex), name, 0, (regmatch_t *) NULL, 0) == 235 0)) || (!strcmp(name, en->env_name))) 236 { 237 if ((en->env_flags & ENVIRONMENT_FLAG_FUNC) && 238 (en->env_value != (char *) NULL)) 239 return ((char * (*) (char *)) en->env_value)(name); 240 else 241 return en->env_value; 242 } 243 244 return (char *) NULL; 245 } 246 247 /* 248 * Delete a variable from hash table. Return RESULT_TRUE if the deletion was 249 * successful, and RESULT_FALSE if the variable was not found. 250 */ 251 int 252 keynote_env_delete(char *name, struct environment **table, 253 unsigned int hashsize) 254 { 255 struct environment *en, *en2; 256 unsigned int h; 257 258 h = keynote_stringhash(name, hashsize); 259 260 if (table[h] != (struct environment *) NULL) 261 { 262 if (!strcmp(table[h]->env_name, name)) 263 { 264 en = table[h]; 265 table[h] = en->env_next; 266 keynote_free_env(en); 267 return RESULT_TRUE; 268 } 269 else 270 for (en = table[h]; 271 en->env_next != (struct environment *) NULL; 272 en = en->env_next) 273 if (!strcmp(en->env_next->env_name, name)) 274 { 275 en2 = en->env_next; 276 en->env_next = en2->env_next; 277 keynote_free_env(en2); 278 return RESULT_TRUE; 279 } 280 } 281 282 return RESULT_FALSE; 283 } 284 285 /* 286 * Add a new variable in hash table. Return RESULT_TRUE on success, 287 * ERROR_MEMORY on failure. If hashsize is 1, second argument is 288 * actually a pointer to a list. The arguments are duplicated. 289 */ 290 int 291 keynote_env_add(char *name, char *value, struct environment **table, 292 unsigned int hashsize, int flags) 293 { 294 struct environment *en; 295 unsigned int h, i; 296 297 en = calloc(1, sizeof(struct environment)); 298 if (en == (struct environment *) NULL) 299 { 300 keynote_errno = ERROR_MEMORY; 301 return -1; 302 } 303 304 en->env_name = strdup(name); 305 if (en->env_name == (char *) NULL) 306 { 307 keynote_free_env(en); 308 keynote_errno = ERROR_MEMORY; 309 return -1; 310 } 311 312 if (flags & ENVIRONMENT_FLAG_REGEX) /* Regular expression for name */ 313 { 314 if ((i = regcomp(&(en->env_regex), name, REG_EXTENDED)) != 0) 315 { 316 keynote_free_env(en); 317 if (i == REG_ESPACE) 318 keynote_errno = ERROR_MEMORY; 319 else 320 keynote_errno = ERROR_SYNTAX; 321 return -1; 322 } 323 en->env_flags |= ENVIRONMENT_FLAG_REGEX; 324 } 325 326 if (flags & ENVIRONMENT_FLAG_FUNC) /* Callback registration */ 327 { 328 en->env_value = value; 329 en->env_flags |= ENVIRONMENT_FLAG_FUNC; 330 ((char * (*) (char *))en->env_value)(KEYNOTE_CALLBACK_INITIALIZE); 331 if (keynote_errno != 0) 332 { 333 keynote_free_env(en); 334 return -1; 335 } 336 } 337 else 338 { 339 en->env_value = strdup(value); 340 if (en->env_value == (char *) NULL) 341 { 342 keynote_free_env(en); 343 keynote_errno = ERROR_MEMORY; 344 return -1; 345 } 346 } 347 348 /* 349 * This means that new assignments of existing variable will override 350 * the old ones. 351 */ 352 h = keynote_stringhash(name, hashsize); 353 en->env_next = table[h]; 354 table[h] = en; 355 return RESULT_TRUE; 356 } 357 358 /* 359 * Cleanup an environment table. 360 */ 361 void 362 keynote_env_cleanup(struct environment **table, unsigned int hashsize) 363 { 364 struct environment *en2; 365 366 if ((hashsize == 0) || (table == (struct environment **) NULL)) 367 return; 368 369 while (hashsize > 0) 370 { 371 while (table[hashsize - 1] != (struct environment *) NULL) 372 { 373 en2 = table[hashsize - 1]->env_next; 374 keynote_free_env(table[hashsize - 1]); 375 table[hashsize - 1] = en2; 376 } 377 378 hashsize--; 379 } 380 } 381 382 /* 383 * Zero out the attribute structures, seed the RNG. 384 */ 385 static int 386 keynote_init_environment(void) 387 { 388 memset(keynote_current_session->ks_env_table, 0, 389 HASHTABLESIZE * sizeof(struct environment *)); 390 memset(keynote_current_session->ks_assertion_table, 0, 391 HASHTABLESIZE * sizeof(struct assertion *)); 392 keynote_current_session->ks_env_regex = (struct environment *) NULL; 393 394 if (keynote_env_add("_ACTION_AUTHORIZERS", 395 (char *) keynote_get_action_authorizers, 396 keynote_current_session->ks_env_table, HASHTABLESIZE, 397 ENVIRONMENT_FLAG_FUNC) != RESULT_TRUE) 398 return -1; 399 400 if (keynote_env_add("_VALUES", (char *) keynote_get_values, 401 keynote_current_session->ks_env_table, HASHTABLESIZE, 402 ENVIRONMENT_FLAG_FUNC) != RESULT_TRUE) 403 return -1; 404 405 return RESULT_TRUE; 406 } 407 408 /* 409 * Return the index of argument in keynote_values[]. 410 */ 411 int 412 keynote_retindex(char *s) 413 { 414 int i; 415 416 for (i = 0; i < keynote_current_session->ks_values_num; i++) 417 if (!strcmp(s, keynote_current_session->ks_values[i])) 418 return i; 419 420 return -1; 421 } 422 423 /* 424 * Find a session by its id. 425 */ 426 struct keynote_session * 427 keynote_find_session(int sessid) 428 { 429 unsigned int h = sessid % SESSIONTABLESIZE; 430 struct keynote_session *ks; 431 432 for (ks = keynote_sessions[h]; 433 ks != (struct keynote_session *) NULL; 434 ks = ks->ks_next) 435 if (ks->ks_id == sessid) 436 return ks; 437 438 return (struct keynote_session *) NULL; 439 } 440 441 /* 442 * Add a session in the hash table. 443 */ 444 static void 445 keynote_add_session(struct keynote_session *ks) 446 { 447 unsigned int h = ks->ks_id % SESSIONTABLESIZE; 448 449 ks->ks_next = keynote_sessions[h]; 450 if (ks->ks_next != (struct keynote_session *) NULL) 451 ks->ks_next->ks_prev = ks; 452 453 keynote_sessions[h] = ks; 454 } 455 456 /* 457 * Initialize a KeyNote session. 458 */ 459 int 460 kn_init(void) 461 { 462 keynote_errno = 0; 463 keynote_current_session = (struct keynote_session *) calloc(1, sizeof(struct keynote_session)); 464 if (keynote_current_session == (struct keynote_session *) NULL) 465 { 466 keynote_errno = ERROR_MEMORY; 467 return -1; 468 } 469 470 while (keynote_find_session(sessioncounter) != 471 (struct keynote_session *) NULL) 472 { 473 sessioncounter++; 474 if (sessioncounter < 0) 475 sessioncounter = 0; 476 } 477 478 keynote_current_session->ks_id = sessioncounter++; 479 keynote_init_environment(); 480 keynote_add_session(keynote_current_session); 481 return keynote_current_session->ks_id; 482 } 483 484 /* 485 * Cleanup the action environment. 486 */ 487 int 488 kn_cleanup_action_environment(int sessid) 489 { 490 struct keynote_session *ks; 491 492 keynote_errno = 0; 493 if ((keynote_current_session == (struct keynote_session *) NULL) || 494 (keynote_current_session->ks_id != sessid)) 495 { 496 keynote_current_session = keynote_find_session(sessid); 497 if (keynote_current_session == (struct keynote_session *) NULL) 498 { 499 keynote_errno = ERROR_NOTFOUND; 500 return -1; 501 } 502 } 503 504 ks = keynote_current_session; 505 506 /* Cleanup environment */ 507 keynote_env_cleanup(ks->ks_env_table, HASHTABLESIZE); 508 keynote_env_cleanup(&(ks->ks_env_regex), 1); 509 510 return 0; 511 } 512 513 /* 514 * Close a session. 515 */ 516 int 517 kn_close(int sessid) 518 { 519 struct keynote_session *ks; 520 struct assertion *as, *as2; 521 int i; 522 523 keynote_errno = 0; 524 if ((keynote_current_session == (struct keynote_session *) NULL) || 525 (keynote_current_session->ks_id != sessid)) 526 { 527 keynote_current_session = keynote_find_session(sessid); 528 if (keynote_current_session == (struct keynote_session *) NULL) 529 { 530 keynote_errno = ERROR_NOTFOUND; 531 return -1; 532 } 533 } 534 535 ks = keynote_current_session; 536 537 /* Cleanup environment -- no point using kn_cleanup_action_environment() */ 538 keynote_env_cleanup(ks->ks_env_table, HASHTABLESIZE); 539 keynote_env_cleanup(&(ks->ks_env_regex), 1); 540 541 /* Cleanup assertions */ 542 for (i = 0; i < HASHTABLESIZE; i++) 543 for (as = ks->ks_assertion_table[i]; 544 as != (struct assertion *) NULL; 545 as = as2) 546 { 547 as2 = as->as_next; 548 keynote_free_assertion(as); 549 } 550 551 /* Cleanup action authorizers */ 552 keynote_keylist_free(ks->ks_action_authorizers); 553 554 /* Unlink from chain */ 555 if (ks->ks_prev == (struct keynote_session *) NULL) 556 { 557 keynote_sessions[ks->ks_id % SESSIONTABLESIZE] = ks->ks_next; 558 if (ks->ks_next != (struct keynote_session *) NULL) 559 ks->ks_next->ks_prev = (struct keynote_session *) NULL; 560 561 } 562 else 563 { 564 ks->ks_prev->ks_next = ks->ks_next; 565 if (ks->ks_next != (struct keynote_session *) NULL) 566 ks->ks_next->ks_prev = ks->ks_prev; 567 } 568 569 free(ks); 570 keynote_current_session = (struct keynote_session *) NULL; 571 return 0; 572 } 573 574 /* 575 * Add an action attribute. 576 */ 577 int 578 kn_add_action(int sessid, char *name, char *value, int flags) 579 { 580 int i; 581 582 keynote_errno = 0; 583 if ((name == (char *) NULL) || (value == (char *) NULL) || 584 (name[0] == '_')) 585 { 586 keynote_errno = ERROR_SYNTAX; 587 return -1; 588 } 589 590 if ((keynote_current_session == (struct keynote_session *) NULL) || 591 (keynote_current_session->ks_id != sessid)) 592 { 593 keynote_current_session = keynote_find_session(sessid); 594 if (keynote_current_session == (struct keynote_session *) NULL) 595 { 596 keynote_errno = ERROR_NOTFOUND; 597 return -1; 598 } 599 } 600 601 if (flags & ENVIRONMENT_FLAG_REGEX) 602 i = keynote_env_add(name, value, 603 &(keynote_current_session->ks_env_regex), 1, flags); 604 else 605 i = keynote_env_add(name, value, keynote_current_session->ks_env_table, 606 HASHTABLESIZE, flags); 607 608 if (i == RESULT_TRUE) 609 return 0; 610 else 611 return -1; 612 } 613 614 /* 615 * Remove an action attribute. 616 */ 617 int 618 kn_remove_action(int sessid, char *name) 619 { 620 int i; 621 622 keynote_errno = 0; 623 if ((name == (char *) NULL) || (name[0] == '_')) 624 { 625 keynote_errno = ERROR_SYNTAX; 626 return -1; 627 } 628 629 if ((keynote_current_session == (struct keynote_session *) NULL) || 630 (keynote_current_session->ks_id != sessid)) 631 { 632 keynote_current_session = keynote_find_session(sessid); 633 if (keynote_current_session == (struct keynote_session *) NULL) 634 { 635 keynote_errno = ERROR_NOTFOUND; 636 return -1; 637 } 638 } 639 640 i = keynote_env_delete(name, keynote_current_session->ks_env_table, 641 HASHTABLESIZE); 642 if (i == RESULT_TRUE) 643 return 0; 644 645 i = keynote_env_delete(name, &(keynote_current_session->ks_env_regex), 646 HASHTABLESIZE); 647 if (i == RESULT_TRUE) 648 return 0; 649 650 keynote_errno = ERROR_NOTFOUND; 651 return -1; 652 } 653 654 /* 655 * Execute a query. 656 */ 657 int 658 kn_do_query(int sessid, char **returnvalues, int numvalues) 659 { 660 struct assertion *as; 661 int i; 662 663 keynote_errno = 0; 664 if ((keynote_current_session == (struct keynote_session *) NULL) || 665 (keynote_current_session->ks_id != sessid)) 666 { 667 keynote_current_session = keynote_find_session(sessid); 668 if (keynote_current_session == (struct keynote_session *) NULL) 669 { 670 keynote_errno = ERROR_NOTFOUND; 671 return -1; 672 } 673 } 674 675 /* Check that we have at least one action authorizer */ 676 if (keynote_current_session->ks_action_authorizers == 677 (struct keylist *) NULL) 678 { 679 keynote_errno = ERROR_NOTFOUND; 680 return -1; 681 } 682 683 /* 684 * We may use already set returnvalues, or use new ones, 685 * but we must have some before we can evaluate. 686 */ 687 if ((returnvalues == (char **) NULL) && 688 (keynote_current_session->ks_values == (char **) NULL)) 689 { 690 keynote_errno = ERROR_SYNTAX; 691 return -1; 692 } 693 694 /* Replace any existing returnvalues */ 695 if (returnvalues != (char **) NULL) 696 { 697 keynote_current_session->ks_values = returnvalues; 698 keynote_current_session->ks_values_num = numvalues; 699 } 700 701 /* Reset assertion state from any previous queries */ 702 for (i = 0; i < HASHTABLESIZE; i++) 703 for (as = keynote_current_session->ks_assertion_table[i]; 704 as != (struct assertion *) NULL; 705 as = as->as_next) 706 { 707 as->as_kresult = KRESULT_UNTOUCHED; 708 as->as_result = 0; 709 as->as_internalflags &= ~ASSERT_IFLAG_PROCESSED; 710 as->as_error = 0; 711 if (as->as_internalflags & ASSERT_IFLAG_WEIRDSIG) 712 as->as_sigresult = SIGRESULT_UNTOUCHED; 713 } 714 715 return keynote_evaluate_query(); 716 } 717 718 /* 719 * Return assertions that failed, by error type. 720 */ 721 int 722 kn_get_failed(int sessid, int type, int num) 723 { 724 struct assertion *as; 725 int i; 726 727 keynote_errno = 0; 728 if ((keynote_current_session == (struct keynote_session *) NULL) || 729 (keynote_current_session->ks_id != sessid)) 730 { 731 keynote_current_session = keynote_find_session(sessid); 732 if (keynote_current_session == (struct keynote_session *) NULL) 733 { 734 keynote_errno = ERROR_NOTFOUND; 735 return -1; 736 } 737 } 738 739 for (i = 0; i < HASHTABLESIZE; i++) 740 for (as = keynote_current_session->ks_assertion_table[i]; 741 as != (struct assertion *) NULL; 742 as = as->as_next) 743 switch (type) 744 { 745 case KEYNOTE_ERROR_ANY: 746 if ((as->as_error != 0) || 747 ((as->as_sigresult != SIGRESULT_TRUE) && 748 !(as->as_sigresult == SIGRESULT_UNTOUCHED) && 749 !(as->as_flags & ASSERT_FLAG_LOCAL))) 750 if (num-- == 0) /* Return it if it's the num-th found */ 751 return as->as_id; 752 break; 753 754 case KEYNOTE_ERROR_MEMORY: 755 if (as->as_error == ERROR_MEMORY) 756 if (num-- == 0) 757 return as->as_id; 758 break; 759 760 case KEYNOTE_ERROR_SYNTAX: 761 if (as->as_error == ERROR_SYNTAX) 762 if (num-- == 0) 763 return as->as_id; 764 break; 765 766 case KEYNOTE_ERROR_SIGNATURE: 767 if ((as->as_sigresult != SIGRESULT_TRUE) && 768 !(as->as_sigresult == SIGRESULT_UNTOUCHED) && 769 !(as->as_flags & ASSERT_FLAG_LOCAL)) 770 if (num-- == 0) 771 return as->as_id; 772 break; 773 } 774 775 keynote_errno = ERROR_NOTFOUND; 776 return -1; 777 } 778 779 /* 780 * Simple API for doing a single KeyNote query. 781 */ 782 int 783 kn_query(struct environment *env, char **retvalues, int numval, 784 char **trusted, int *trustedlen, int numtrusted, 785 char **untrusted, int *untrustedlen, int numuntrusted, 786 char **authorizers, int numauthorizers) 787 { 788 struct environment *en; 789 int sessid, i, serrno; 790 791 keynote_errno = 0; 792 if ((sessid = kn_init()) == -1) 793 return -1; 794 795 /* Action set */ 796 for (en = env; en != (struct environment *) NULL; en = en->env_next) 797 if (kn_add_action(sessid, en->env_name, en->env_value, 798 en->env_flags) == -1) 799 { 800 serrno = keynote_errno; 801 kn_close(sessid); 802 keynote_errno = serrno; 803 return -1; 804 } 805 806 /* Locally trusted assertions */ 807 for (i = 0; i < numtrusted; i++) 808 if ((kn_add_assertion(sessid, trusted[i], trustedlen[i], 809 ASSERT_FLAG_LOCAL) == -1) && (keynote_errno == ERROR_MEMORY)) 810 { 811 serrno = keynote_errno; 812 kn_close(sessid); 813 keynote_errno = serrno; 814 return -1; 815 } 816 817 /* Untrusted assertions */ 818 for (i = 0; i < numuntrusted; i++) 819 if ((kn_add_assertion(sessid, untrusted[i], untrustedlen[i], 0) == -1) 820 && (keynote_errno == ERROR_MEMORY)) 821 { 822 serrno = keynote_errno; 823 kn_close(sessid); 824 keynote_errno = serrno; 825 return -1; 826 } 827 828 /* Authorizers */ 829 for (i = 0; i < numauthorizers; i++) 830 if (kn_add_authorizer(sessid, authorizers[i]) == -1) 831 { 832 serrno = keynote_errno; 833 kn_close(sessid); 834 keynote_errno = serrno; 835 return -1; 836 } 837 838 i = kn_do_query(sessid, retvalues, numval); 839 serrno = keynote_errno; 840 kn_close(sessid); 841 842 if (serrno) 843 keynote_errno = serrno; 844 845 return i; 846 } 847 848 /* 849 * Read a buffer, break it up in assertions. 850 */ 851 char ** 852 kn_read_asserts(char *buffer, int bufferlen, int *numassertions) 853 { 854 int bufsize = 32, i, flag, valid; 855 char **buf, **tempbuf, *ptr; 856 857 keynote_errno = 0; 858 if (buffer == (char *) NULL) 859 { 860 keynote_errno = ERROR_SYNTAX; 861 return (char **) NULL; 862 } 863 864 buf = (char **) calloc(bufsize, sizeof(char *)); 865 if (buf == (char **) NULL) 866 { 867 keynote_errno = ERROR_MEMORY; 868 return (char **) NULL; 869 } 870 871 /* 872 * We'll go through the whole buffer looking for consecutive newlines, 873 * which imply newline separation. We use the valid flag to keep 874 * track of whether there may be an assertion after the last pair of 875 * newlines, or whether there may be an assertion in the buffer to 876 * begin with, if there are no consecutive newlines. 877 */ 878 for (i = 0, flag = 0, valid = 0, *numassertions = 0, ptr = buffer; 879 i < bufferlen; 880 i++) 881 { 882 if (buffer[i] == '\n') 883 { 884 if (flag) /* Two newlines in a row, copy if there's anything */ 885 { 886 if (valid) /* Something there */ 887 { 888 /* Allocate enough memory */ 889 buf[*numassertions] = (char *) calloc((buffer + i) - ptr 890 + 1, sizeof(char)); 891 if (buf[*numassertions] == (char *) NULL) 892 { 893 /* Free any already-allocated strings */ 894 for (flag = 0; flag < *numassertions; flag++) 895 free(buf[flag]); 896 free(buf); 897 keynote_errno = ERROR_MEMORY; 898 return (char **) NULL; 899 } 900 901 /* Copy string */ 902 memcpy(buf[*numassertions], ptr, (buffer + i) - ptr); 903 (*numassertions)++; 904 } 905 906 valid = 0; /* Reset */ 907 flag = 0; 908 ptr = buffer + i + 1; /* Point right after this newline */ 909 910 /* See if we need to resize the buffer */ 911 if (*numassertions > bufsize - 4) 912 { 913 /* Allocate twice the space */ 914 tempbuf = (char **) realloc(buf, 2 * bufsize * 915 sizeof(char *)); 916 if (tempbuf == (char **) NULL) 917 { 918 for (flag = 0; flag < *numassertions; flag++) 919 free(buf[flag]); 920 free(buf); 921 keynote_errno = ERROR_MEMORY; 922 return (char **) NULL; 923 } 924 925 free(buf); /* Free old buffer */ 926 buf = tempbuf; 927 bufsize *= 2; 928 } 929 } 930 else 931 flag = 1; /* One newline so far */ 932 933 continue; 934 } 935 else 936 flag = 0; 937 938 if (!isspace((int) buffer[i])) 939 valid = 1; 940 } 941 942 /* 943 * There may be a valid assertion after the last pair of newlines. 944 * Notice that because of the resizing check above, there will be 945 * a valid memory location to store this last string. 946 */ 947 if (valid) 948 { 949 /* This one's easy, we can just use strdup() */ 950 if ((buf[*numassertions] = strdup(ptr)) == (char *) NULL) 951 { 952 for (flag = 0; flag < *numassertions; flag++) 953 free(buf[flag]); 954 free(buf); 955 keynote_errno = ERROR_MEMORY; 956 return (char **) NULL; 957 } 958 (*numassertions)++; 959 } 960 961 return buf; 962 } 963 964 /* 965 * Return the authorizer key for a given assertion. 966 */ 967 void * 968 kn_get_authorizer(int sessid, int assertid, int *algorithm) 969 { 970 struct assertion *as; 971 int i; 972 973 keynote_errno = *algorithm = 0; 974 if ((keynote_current_session == (struct keynote_session *) NULL) || 975 (keynote_current_session->ks_id != sessid)) 976 { 977 keynote_current_session = keynote_find_session(sessid); 978 if (keynote_current_session == (struct keynote_session *) NULL) 979 { 980 keynote_errno = ERROR_NOTFOUND; 981 return (void *) NULL; 982 } 983 } 984 985 /* Traverse the hash table looking for assertid */ 986 for (i = 0; i < HASHTABLESIZE; i++) 987 for (as = keynote_current_session->ks_assertion_table[i]; 988 as != (struct assertion *) NULL; 989 as = as->as_next) 990 if (as->as_id == assertid) 991 goto out; 992 993 out: 994 if (as == (struct assertion *) NULL) 995 { 996 keynote_errno = ERROR_NOTFOUND; 997 return (void *) NULL; 998 } 999 1000 if (as->as_authorizer == NULL) 1001 if (keynote_evaluate_authorizer(as, 1) != RESULT_TRUE) 1002 return NULL; 1003 1004 *algorithm = as->as_signeralgorithm; 1005 return as->as_authorizer; 1006 } 1007 1008 /* 1009 * Return the licensees for a given assertion. 1010 */ 1011 struct keynote_keylist * 1012 kn_get_licensees(int sessid, int assertid) 1013 { 1014 struct assertion *as; 1015 int i; 1016 1017 keynote_errno = 0; 1018 if ((keynote_current_session == (struct keynote_session *) NULL) || 1019 (keynote_current_session->ks_id != sessid)) 1020 { 1021 keynote_current_session = keynote_find_session(sessid); 1022 if (keynote_current_session == (struct keynote_session *) NULL) 1023 { 1024 keynote_errno = ERROR_NOTFOUND; 1025 return (struct keynote_keylist *) NULL; 1026 } 1027 } 1028 1029 /* Traverse the hash table looking for assertid */ 1030 for (i = 0; i < HASHTABLESIZE; i++) 1031 for (as = keynote_current_session->ks_assertion_table[i]; 1032 as != (struct assertion *) NULL; 1033 as = as->as_next) 1034 if (as->as_id == assertid) 1035 goto out; 1036 1037 out: 1038 if (as == (struct assertion *) NULL) 1039 { 1040 keynote_errno = ERROR_NOTFOUND; 1041 return (struct keynote_keylist *) NULL; 1042 } 1043 1044 if (as->as_keylist == NULL) 1045 if (keynote_parse_keypred(as, 1) != RESULT_TRUE) 1046 return (struct keynote_keylist *) NULL; 1047 1048 return (struct keynote_keylist *) as->as_keylist; 1049 } 1050