GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: lib/libkeynote/environment.c Lines: 0 409 0.0 %
Date: 2017-11-07 Branches: 0 295 0.0 %

Line Branch Exec Source
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 *
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 *
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
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 *
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
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
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
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
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
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 *
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
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
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
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
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
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
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
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
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
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 **
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 *
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 *
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
}