xref: /openbsd/lib/libkeynote/parse_assertion.c (revision 133306f0)
1 /* $OpenBSD: parse_assertion.c,v 1.9 2000/06/13 19:16:16 angelos 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 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 #if HAVE_CONFIG_H
23 #include "config.h"
24 #endif /* HAVE_CONFIG_H */
25 
26 #include <sys/types.h>
27 #include <stdlib.h>
28 #include <stdio.h>
29 #include <ctype.h>
30 
31 #if STDC_HEADERS
32 #include <string.h>
33 #endif /* STDC_HEADERS */
34 
35 #if HAVE_LIMITS_H
36 #include <limits.h>
37 #endif /* HAVE_LIMITS_H */
38 
39 #include "header.h"
40 #include "keynote.h"
41 #include "assertion.h"
42 #include "signature.h"
43 
44 /*
45  * Recurse on graph discovery.
46  */
47 static int
48 rec_evaluate_query(struct assertion *as)
49 {
50     struct assertion *ast;
51     struct keylist *kl;
52     int i, s;
53 
54     as->as_kresult = KRESULT_IN_PROGRESS;
55 
56     /*
57      * If we get the minimum result or an error from evaluating this
58      * assertion, we don't need to recurse.
59      */
60     keynote_evaluate_assertion(as);
61     if (keynote_errno != 0)
62     {
63 	as->as_kresult = KRESULT_DONE;
64 	if (keynote_errno)
65 	  as->as_error = keynote_errno;
66 	if (keynote_errno == ERROR_MEMORY)
67 	  return -1;
68 	else
69 	{
70 	    keynote_errno = 0;  /* Ignore syntax errors for now */
71 	    return 0;
72 	}
73     }
74 
75     if (as->as_result == 0)
76     {
77         as->as_kresult = KRESULT_DONE;
78         return as->as_result;
79     }
80 
81     for (kl = as->as_keylist;
82 	 kl != (struct keylist *) NULL;
83 	 kl = kl->key_next)
84     {
85 	switch (keynote_in_action_authorizers(kl->key_key, kl->key_alg))
86 	{
87 	    case -1:
88 		as->as_kresult = KRESULT_DONE;
89 		if (keynote_errno == ERROR_MEMORY)
90 		{
91 		    as->as_error = ERROR_MEMORY;
92 		    return -1;
93 		}
94 		else
95 		{
96 		    keynote_errno = 0; /* Reset */
97 		    continue;
98 		}
99 
100 	    case RESULT_FALSE:    /* Not there, check for assertions instead */
101 		break;
102 
103 	    case RESULT_TRUE:     /* Ok, don't bother with assertions */
104 		keynote_current_assertion = (struct assertion *) NULL;
105 		continue;
106 	}
107 
108 	for (i = 0;; i++)
109 	{
110 	    ast = keynote_find_assertion(kl->key_key, i, kl->key_alg);
111 	    if (ast == (struct assertion *) NULL)
112 	      break;
113 
114 	    if (ast->as_kresult == KRESULT_IN_PROGRESS) /* Cycle detected */
115 	      continue;
116 
117 	    if (ast->as_kresult == KRESULT_UNTOUCHED)   /* Recurse if needed */
118 	      rec_evaluate_query(ast);
119 
120 	    /* Check for errors */
121 	    if (keynote_errno == ERROR_MEMORY)
122 	    {
123 		as->as_error = ERROR_MEMORY;
124 		as->as_kresult = KRESULT_DONE;
125 		return -1;
126 	    }
127 	    else
128 	      keynote_errno = 0; /* Reset */
129 	}
130     }
131 
132     keynote_current_assertion = as;
133     s = keynote_parse_keypred(as, 0);
134     keynote_current_assertion = (struct assertion *) NULL;
135 
136     if (keynote_errno == ERROR_MEMORY)
137     {
138 	as->as_error = ERROR_MEMORY;
139 	as->as_kresult = KRESULT_DONE;
140 	return -1;
141     }
142     else
143       if (keynote_errno)
144       {
145 	  keynote_errno = 0;
146 	  s = 0;
147       }
148 
149     /* Keep lower of two */
150     as->as_result = (as->as_result < s ? as->as_result : s);
151 
152     /* Check the signature now if we haven't done so already */
153     if (as->as_sigresult == SIGRESULT_UNTOUCHED)
154     {
155 	if (!(as->as_flags & ASSERT_FLAG_LOCAL))
156 	  as->as_sigresult = keynote_sigverify_assertion(as);
157 	else
158 	  as->as_sigresult = SIGRESULT_TRUE;    /* Trusted assertion */
159     }
160 
161     if (as->as_sigresult != SIGRESULT_TRUE)
162     {
163 	as->as_result = 0;
164 	as->as_sigresult = SIGRESULT_FALSE;
165 	if (keynote_errno != ERROR_MEMORY)
166 	  keynote_errno = 0; /* Reset */
167 	else
168 	{
169 	    as->as_error = ERROR_MEMORY;
170 	    as->as_kresult = KRESULT_DONE;
171 	    return -1;
172 	}
173     }
174 
175     as->as_kresult = KRESULT_DONE;
176     return as->as_result;
177 }
178 
179 /*
180  * Fix the Authorizer/Licencees/Signature fields. If the first argument is
181  * empty, fix all assertions. The second argument specifies whether the
182  * Signature field should be parsed or not.
183  */
184 static int
185 keynote_fix_fields(struct assertion *ast, int sigfield)
186 {
187     struct assertion *as;
188     int i;
189 
190     /* Signature generation/verification handling, no need to eval Licensees */
191     if (ast != (struct assertion *) NULL)
192     {
193 	/* Authorizer */
194 	if (keynote_evaluate_authorizer(ast, 1) != RESULT_TRUE)
195 	  return -1;
196 
197 	/* Signature */
198 	if ((sigfield) && (ast->as_signature_string_s != (char *) NULL))
199 	  if (keynote_evaluate_authorizer(ast, 0) != RESULT_TRUE)
200 	    return -1;
201 
202 	return RESULT_TRUE;
203     }
204 
205     for (i = 0; i < HASHTABLESIZE; i++)
206       for (as = keynote_current_session->ks_assertion_table[i];
207 	   as != (struct assertion *) NULL;
208 	   as = as->as_next)
209       {
210 	  if (!(as->as_internalflags & ASSERT_IFLAG_NEEDPROC) &&
211 	      !(as->as_internalflags & ASSERT_IFLAG_WEIRDLICS) &&
212 	      !(as->as_internalflags & ASSERT_IFLAG_WEIRDAUTH) &&
213 	      !(as->as_internalflags & ASSERT_IFLAG_WEIRDSIG))
214 	    continue;
215 
216 	  /* Parse the Signature field */
217 	  if (((as->as_internalflags & ASSERT_IFLAG_WEIRDSIG) ||
218 	       (as->as_internalflags & ASSERT_IFLAG_NEEDPROC)) &&
219 	      (as->as_signature_string_s != (char *) NULL))
220 	    if (keynote_evaluate_authorizer(as, 0) == -1)
221 	    {
222 		if (keynote_errno)
223 		  as->as_error = keynote_errno;
224 		if (keynote_errno == ERROR_MEMORY)
225 		  return -1;
226 		else
227 		  keynote_errno = 0;
228 	    }
229 
230 	  /* Parse the Licensees field */
231 	  if ((as->as_internalflags & ASSERT_IFLAG_WEIRDLICS) ||
232 	      (as->as_internalflags & ASSERT_IFLAG_NEEDPROC))
233 	    if (keynote_parse_keypred(as, 1) == -1)
234 	    {
235 		if (keynote_errno)
236 		    as->as_error = keynote_errno;
237 		if (keynote_errno == ERROR_MEMORY)
238 		  return -1;
239 		else
240 		  keynote_errno = 0;
241 	    }
242 
243 	  /* Parse the Authorizer field */
244 	  if ((as->as_internalflags & ASSERT_IFLAG_WEIRDAUTH) ||
245 	      (as->as_internalflags & ASSERT_IFLAG_NEEDPROC))
246 	    if (keynote_evaluate_authorizer(as, 1) == -1)
247 	    {
248 		if (keynote_errno)
249 		  as->as_error = keynote_errno;
250 		if (keynote_errno == ERROR_MEMORY)
251 		  return -1;
252 		else
253 		  keynote_errno = 0;
254 	    }
255       }
256 
257     /* Reposition if necessary */
258     for (i = 0; i < HASHTABLESIZE; i++)
259       for (as = keynote_current_session->ks_assertion_table[i];
260 	   as != (struct assertion *) NULL;
261 	   as = as->as_next)
262 	if (((as->as_internalflags & ASSERT_IFLAG_WEIRDAUTH) &&
263 	     !(as->as_internalflags & ASSERT_IFLAG_PROCESSED)) ||
264 	    (as->as_internalflags & ASSERT_IFLAG_NEEDPROC))
265 	{
266 	    as->as_internalflags &= ~ASSERT_IFLAG_NEEDPROC;
267 	    as->as_internalflags |= ASSERT_IFLAG_PROCESSED;
268 	    keynote_sremove_assertion(keynote_current_session->ks_id,
269 				      as->as_id);
270 
271 	    if (keynote_add_htable(as, 1) != RESULT_TRUE)
272 	      return -1;
273 
274 	    /* Point to begining of the previous list. */
275 	    i--;
276 	    break;
277 	}
278 
279     return RESULT_TRUE;
280 }
281 
282 /*
283  * Find the trust graph. This is a depth-first search, starting at
284  * POLICY assertions.
285  */
286 int
287 keynote_evaluate_query(void)
288 {
289     struct assertion *as;
290     int p, prev;
291     int i;
292 
293     /* Fix the authorizer/licensees/signature fields */
294     if (keynote_fix_fields((struct assertion *) NULL, 0) != RESULT_TRUE)
295       return -1;
296 
297     /* Find POLICY assertions and try to evaluate the query. */
298     for (i = 0, prev = 0; i < HASHTABLESIZE; i++)
299       for (as = keynote_current_session->ks_assertion_table[i];
300 	   as != (struct assertion *) NULL;
301 	   as = as->as_next)
302 	if ((as->as_authorizer != (void *) NULL) &&      /* Paranoid */
303             (as->as_signeralgorithm == KEYNOTE_ALGORITHM_NONE))
304 	  if ((!strcmp("POLICY", as->as_authorizer)) &&
305 	      (as->as_flags & ASSERT_FLAG_LOCAL))
306 	  {
307 	      if ((p = rec_evaluate_query(as)) == -1)
308 	      {
309 		  if (keynote_errno)
310 		    as->as_error = keynote_errno;
311 		  if (keynote_errno == ERROR_MEMORY)
312 		    return -1;
313 		  else
314 		  {
315 		      keynote_errno = 0;
316 		      continue;
317 		  }
318 	      }
319 
320 	      if (p > prev)
321 		prev = p;
322 
323 	      /* If we get the highest possible return value, just return */
324 	      if (prev == (keynote_current_session->ks_values_num - 1))
325 		return prev;
326 	  }
327 
328     return prev;
329 }
330 
331 /*
332  * Return keyword type.
333  */
334 static int
335 whichkeyword(char *start, char *end)
336 {
337     int len = (end - start);
338 
339     if (len <= 0)
340     {
341 	keynote_errno = ERROR_MEMORY;
342 	return -1;
343     }
344 
345     if (!strncasecmp("keynote-version:", start, len))
346       return KEYWORD_VERSION;
347 
348     if (!strncasecmp("local-constants:", start, len))
349       return KEYWORD_LOCALINIT;
350 
351     if (!strncasecmp("authorizer:", start, len))
352       return KEYWORD_AUTHORIZER;
353 
354     if (!strncasecmp("licensees:", start, len))
355       return KEYWORD_LICENSEES;
356 
357     if (!strncasecmp("conditions:", start, len))
358       return KEYWORD_CONDITIONS;
359 
360     if (!strncasecmp("signature:", start, len))
361       return KEYWORD_SIGNATURE;
362 
363     if (!strncasecmp("comment:", start, len))
364       return KEYWORD_COMMENT;
365 
366     keynote_errno = ERROR_SYNTAX;
367     return -1;
368 }
369 
370 /*
371  * Parse an assertion. Set keynote_errno to ERROR_SYNTAX if parsing
372  * failed due to certificate badness, and ERROR_MEMORY if memory
373  * problem. If more than one assertions have been passed in the
374  * buffer, they will be linked.
375  */
376 struct assertion *
377 keynote_parse_assertion(char *buf, int len, int assertion_flags)
378 {
379     int k, i, j, seen_field = 0, ver = 0, end_of_assertion = 0;
380     char *ks, *ke, *ts, *te = (char *) NULL;
381     struct assertion *as;
382 
383     /* Allocate memory for assertion */
384     as = (struct assertion *) calloc(1, sizeof(struct assertion));
385     if (as == (struct assertion *) NULL)
386     {
387 	keynote_errno = ERROR_MEMORY;
388 	return (struct assertion *) NULL;
389     }
390 
391     /* Keep a copy of the assertion around */
392     as->as_buf = strdup(buf);
393     if (as->as_buf == (char *) NULL)
394     {
395 	keynote_errno = ERROR_MEMORY;
396 	keynote_free_assertion(as);
397 	return (struct assertion *) NULL;
398     }
399 
400     as->as_flags = assertion_flags & ~(ASSERT_FLAG_SIGGEN |
401 				       ASSERT_FLAG_SIGVER);
402 
403     /* Skip any leading whitespace */
404     for (i = 0, j = len; i < j && isspace((int) as->as_buf[i]); i++)
405      ;
406 
407     /* Keyword must start at begining of buffer or line */
408     if ((i >= j) || ((i != 0) && (as->as_buf[i - 1] != '\n')))
409     {
410 	keynote_free_assertion(as);
411 	keynote_errno = ERROR_SYNTAX;
412 	return (struct assertion *) NULL;
413     }
414 
415     while (i < j)			/* Decomposition loop */
416     {
417 	ks = as->as_buf + i;
418 
419 	/* Mark begining of assertion for signature purposes */
420 	if (as->as_startofsignature == (char *) NULL)
421 	  as->as_startofsignature = ks;
422 
423 	/* This catches comments at the begining of an assertion only */
424 	if (as->as_buf[i] == '#')	/* Comment */
425 	{
426 	    seen_field = 1;
427 
428    	    /* Skip until the end of line */
429 	    while ((i< j) && as->as_buf[++i] != '\n')
430 	      ;
431 
432 	    i++;
433 	    continue;  /* Loop */
434 	}
435 
436 	/* Advance until we find a keyword separator */
437 	for (; (as->as_buf[i] != ':') && (i < j); i++)
438 	  ;
439 
440 	if (i + 1 > j)
441 	{
442 	    keynote_free_assertion(as);
443 	    keynote_errno = ERROR_SYNTAX;
444 	    return (struct assertion *) NULL;
445 	}
446 
447 	/* ks points at begining of keyword, ke points at end */
448 	ke = as->as_buf + i;
449 
450 	/* ts points at begining of value field */
451 	ts = as->as_buf + i + 1;	/* Skip ':' */
452 
453 	/*
454 	 * Find the end of the field -- means end of buffer,
455 	 * a newline followed by a non-whitespace character,
456 	 * or two newlines.
457 	 */
458 	while (++i <= j)
459 	{
460 	    /* If end of buffer, we're at the end of the field */
461 	    if (i == j)
462 	    {
463 		end_of_assertion = 1;
464 		te = as->as_buf + i;
465 		break;
466 	    }
467 
468 	    /* If two newlines, end of assertion */
469 	    if ((as->as_buf[i] == '\n') && (i + 1 < j) &&
470 		(as->as_buf[i + 1] == '\n'))
471 	    {
472 		end_of_assertion = 1;
473 		te = as->as_buf + i;
474 		break;
475 	    }
476 
477 	    /* If newline followed by non-whitespace or comment character */
478 	    if ((as->as_buf[i] == '\n') &&
479 		(!isspace((int) as->as_buf[i + 1])) &&
480                 (as->as_buf[i + 1] != '#'))
481 	    {
482 	        te = as->as_buf + i;
483 	        break;
484 	    }
485 	}
486 
487 	i++;
488 
489 	/*
490 	 * On each of the cases (except the first), we check that:
491 	 *  - we've already seen a keynote-version field (and that
492 	 *    it's the first one that appears in the assertion)
493 	 *  - the signature field, if present, is the last one
494 	 *  - no field appears more than once
495 	 */
496 	switch (whichkeyword(ks, ke))
497 	{
498 	    case -1:
499 		keynote_free_assertion(as);
500 		return (struct assertion *) NULL;
501 
502 	    case KEYWORD_VERSION:
503 		if ((ver == 1) || (seen_field == 1))
504 		{
505 		    keynote_free_assertion(as);
506 		    keynote_errno = ERROR_SYNTAX;
507 		    return (struct assertion *) NULL;
508 		}
509 
510 		/* Test for version correctness */
511 		keynote_get_envlist(ts, te, 1);
512 		if (keynote_errno != 0)
513 		{
514 		    keynote_free_assertion(as);
515 		    return (struct assertion *) NULL;
516 		}
517 
518 		ver = 1;
519 		break;
520 
521 	    case KEYWORD_LOCALINIT:
522 		if (as->as_env != (struct environment *) NULL)
523 		{
524 		    keynote_free_assertion(as);
525 		    keynote_errno = ERROR_SYNTAX;
526 		    return (struct assertion *) NULL;
527 		}
528 
529 		as->as_env = keynote_get_envlist(ts, te, 0);
530 		if (keynote_errno != 0)
531 		{
532 		    keynote_free_assertion(as);
533 		    return (struct assertion *) NULL;
534 		}
535 		break;
536 
537 	    case KEYWORD_AUTHORIZER:
538 		if (as->as_authorizer_string_s != (void *) NULL)
539 		{
540 		    keynote_free_assertion(as);
541 		    keynote_errno = ERROR_SYNTAX;
542 		    return (struct assertion *) NULL;
543 		}
544 
545 		as->as_authorizer_string_s = ts;
546 		as->as_authorizer_string_e = te;
547 		break;
548 
549 	    case KEYWORD_LICENSEES:
550 		if (as->as_keypred_s != (char *) NULL)
551 		{
552 		    keynote_free_assertion(as);
553 		    keynote_errno = ERROR_SYNTAX;
554 		    return (struct assertion *) NULL;
555 		}
556 
557 		as->as_keypred_s = ts;
558 		as->as_keypred_e = te;
559 		break;
560 
561 	    case KEYWORD_CONDITIONS:
562 		if (as->as_conditions_s != (char *) NULL)
563 		{
564 		    keynote_free_assertion(as);
565 		    keynote_errno = ERROR_SYNTAX;
566 		    return (struct assertion *) NULL;
567 		}
568 
569 		as->as_conditions_s = ts;
570 		as->as_conditions_e = te;
571 		break;
572 
573 	    case KEYWORD_SIGNATURE:
574 		if (as->as_signature_string_s != (char *) NULL)
575 		{
576 		    keynote_free_assertion(as);
577 		    keynote_errno = ERROR_SYNTAX;
578 		    return (struct assertion *) NULL;
579 		}
580 
581 		end_of_assertion = 1;
582 		as->as_allbutsignature = ks;
583 		as->as_signature_string_s = ts;
584 		as->as_signature_string_e = te;
585 		break;
586 
587 	    case KEYWORD_COMMENT:
588 		if (as->as_comment_s != (char *) NULL)
589 		{
590 		    keynote_free_assertion(as);
591 		    keynote_errno = ERROR_SYNTAX;
592 		    return (struct assertion *) NULL;
593 		}
594 
595 		as->as_comment_s = ts;
596 		as->as_comment_e = te;
597 		break;
598 	}
599 
600 	seen_field = 1;
601 	if (end_of_assertion == 1)
602 	{
603 	    /* End of buffer, good termination */
604 	    if ((te == as->as_buf + len) || (te + 1 == as->as_buf + len) ||
605 		(*(te) == '\0') || (*(te + 1) == '\0'))
606 	      break;
607 
608 	    /* Check whether there's something else following */
609 	    for (k = 1; te + k < as->as_buf + len && *(te + k) != '\n'; k++)
610 	      if (!isspace((int) *(te + k)))
611 	      {
612 		  printf("here %c\n", *(te + k));
613 		  keynote_free_assertion(as);
614 		  keynote_errno = ERROR_SYNTAX;
615 		  return (struct assertion *) NULL;
616 	      }
617 
618 	    break; /* Assertion is "properly" terminated */
619 	}
620     }
621 
622     /* Check that the basic fields are there */
623     if (as->as_authorizer_string_s == (char *) NULL)
624     {
625 	keynote_free_assertion(as);
626 	keynote_errno = ERROR_SYNTAX;
627 	return (struct assertion *) NULL;
628     }
629 
630     /* Signature generation/verification handling */
631     if (assertion_flags & ASSERT_FLAG_SIGGEN)
632     {
633         if (keynote_fix_fields(as, 0) != RESULT_TRUE)
634         {
635 	    keynote_free_assertion(as);
636 	    return (struct assertion *) NULL;
637         }
638     }
639     else
640       if (assertion_flags & ASSERT_FLAG_SIGVER)
641 	if (keynote_fix_fields(as, 1) != RESULT_TRUE)
642 	{
643 	    keynote_free_assertion(as);
644 	    return (struct assertion *) NULL;
645 	}
646 
647     return as;
648 }
649