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
36 static int sessioncounter = 0;
37
38 char **keynote_values = NULL;
39 char *keynote_privkey = NULL;
40
41 struct assertion *keynote_current_assertion = NULL;
42
43 struct environment *keynote_init_list = NULL;
44 struct environment *keynote_temp_list = NULL;
45
46 struct keylist *keynote_keypred_keylist = NULL;
47
48 struct keynote_session *keynote_sessions[SESSIONTABLESIZE];
49 struct keynote_session *keynote_current_session = NULL;
50
51 int keynote_exceptionflag = 0;
52 int keynote_used_variable = 0;
53 int keynote_returnvalue = 0;
54 int keynote_justrecord = 0;
55 int keynote_donteval = 0;
56 int keynote_errno = 0;
57
58 /*
59 * Construct the _ACTION_AUTHORIZERS variable value.
60 */
61 static char *
keynote_get_action_authorizers(char * name)62 keynote_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 */
112 static char *
keynote_get_values(char * name)113 keynote_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 */
157 void
keynote_free_env(struct environment * en)158 keynote_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 */
183 char *
keynote_env_lookup(char * name,struct environment ** table,unsigned int hashsize)184 keynote_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 */
210 int
keynote_env_delete(char * name,struct environment ** table,unsigned int hashsize)211 keynote_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 */
249 int
keynote_env_add(char * name,char * value,struct environment ** table,unsigned int hashsize,int flags)250 keynote_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 */
317 void
keynote_env_cleanup(struct environment ** table,unsigned int hashsize)318 keynote_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 */
340 static int
keynote_init_environment(void)341 keynote_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 */
366 int
keynote_retindex(char * s)367 keynote_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 */
381 struct keynote_session *
keynote_find_session(int sessid)382 keynote_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 */
399 static void
keynote_add_session(struct keynote_session * ks)400 keynote_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 */
414 int
kn_init(void)415 kn_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 */
439 int
kn_cleanup_action_environment(int sessid)440 kn_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 */
467 int
kn_close(int sessid)468 kn_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 */
526 int
kn_add_action(int sessid,char * name,char * value,int flags)527 kn_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 */
563 int
kn_remove_action(int sessid,char * name)564 kn_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 */
601 int
kn_do_query(int sessid,char ** returnvalues,int numvalues)602 kn_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 */
661 int
kn_get_failed(int sessid,int type,int num)662 kn_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 */
721 int
kn_query(struct environment * env,char ** retvalues,int numval,char ** trusted,int * trustedlen,int numtrusted,char ** untrusted,int * untrustedlen,int numuntrusted,char ** authorizers,int numauthorizers)722 kn_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 */
790 char **
kn_read_asserts(char * buffer,int bufferlen,int * numassertions)791 kn_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 */
898 void *
kn_get_authorizer(int sessid,int assertid,int * algorithm)899 kn_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 */
940 struct keynote_keylist *
kn_get_licensees(int sessid,int assertid)941 kn_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