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 *
keynote_get_action_authorizers(char * name)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 *
keynote_get_values(char * name)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
keynote_free_env(struct environment * en)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 *
keynote_env_lookup(char * name,struct environment ** table,unsigned int hashsize)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
keynote_env_delete(char * name,struct environment ** table,unsigned int hashsize)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
keynote_env_add(char * name,char * value,struct environment ** table,unsigned int hashsize,int flags)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
keynote_env_cleanup(struct environment ** table,unsigned int hashsize)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
keynote_init_environment(void)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
keynote_retindex(char * s)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 *
keynote_find_session(int sessid)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
keynote_add_session(struct keynote_session * ks)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
kn_init(void)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
kn_cleanup_action_environment(int sessid)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
kn_close(int sessid)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
kn_add_action(int sessid,char * name,char * value,int flags)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
kn_remove_action(int sessid,char * name)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
kn_do_query(int sessid,char ** returnvalues,int numvalues)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
kn_get_failed(int sessid,int type,int num)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
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)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 **
kn_read_asserts(char * buffer,int bufferlen,int * numassertions)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 *
kn_get_authorizer(int sessid,int assertid,int * algorithm)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 *
kn_get_licensees(int sessid,int assertid)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