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