xref: /openbsd/lib/libkeynote/environment.c (revision 8c119664)
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