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