xref: /openbsd-src/lib/libkeynote/parse_assertion.c (revision 2c53affbcc0119d6480b86c18f2790523b6a0aad)
1*2c53affbSjmc /* $OpenBSD: parse_assertion.c,v 1.17 2022/12/27 17:10:06 jmc Exp $ */
2983e9580Sangelos /*
3983e9580Sangelos  * The author of this code is Angelos D. Keromytis (angelos@dsl.cis.upenn.edu)
4983e9580Sangelos  *
5983e9580Sangelos  * This code was written by Angelos D. Keromytis in Philadelphia, PA, USA,
6983e9580Sangelos  * in April-May 1998
7983e9580Sangelos  *
8983e9580Sangelos  * Copyright (C) 1998, 1999 by Angelos D. Keromytis.
9983e9580Sangelos  *
105e4ac158Sderaadt  * Permission to use, copy, and modify this software with or without fee
11983e9580Sangelos  * is hereby granted, provided that this entire notice is included in
12983e9580Sangelos  * all copies of any software which is or includes a copy or
13983e9580Sangelos  * modification of this software.
14983e9580Sangelos  *
15983e9580Sangelos  * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR
16983e9580Sangelos  * IMPLIED WARRANTY. IN PARTICULAR, THE AUTHORS MAKES NO
17983e9580Sangelos  * REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE
18983e9580Sangelos  * MERCHANTABILITY OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR
19983e9580Sangelos  * PURPOSE.
20983e9580Sangelos  */
21983e9580Sangelos 
22983e9580Sangelos #include <sys/types.h>
23e0758482Smsf 
24983e9580Sangelos #include <ctype.h>
25983e9580Sangelos #include <limits.h>
2685616838Smsf #include <regex.h>
27e0758482Smsf #include <stdio.h>
28e0758482Smsf #include <stdlib.h>
29e0758482Smsf #include <string.h>
30a8a6ad51Sangelos 
31a8a6ad51Sangelos #include "keynote.h"
32983e9580Sangelos #include "assertion.h"
33983e9580Sangelos #include "signature.h"
34983e9580Sangelos 
35983e9580Sangelos /*
36983e9580Sangelos  * Recurse on graph discovery.
37983e9580Sangelos  */
38983e9580Sangelos static int
rec_evaluate_query(struct assertion * as)39983e9580Sangelos rec_evaluate_query(struct assertion *as)
40983e9580Sangelos {
41983e9580Sangelos     struct assertion *ast;
42983e9580Sangelos     struct keylist *kl;
43983e9580Sangelos     int i, s;
44983e9580Sangelos 
45983e9580Sangelos     as->as_kresult = KRESULT_IN_PROGRESS;
46983e9580Sangelos 
47983e9580Sangelos     /*
48983e9580Sangelos      * If we get the minimum result or an error from evaluating this
49983e9580Sangelos      * assertion, we don't need to recurse.
50983e9580Sangelos      */
51983e9580Sangelos     keynote_evaluate_assertion(as);
52983e9580Sangelos     if (keynote_errno != 0)
53983e9580Sangelos     {
54983e9580Sangelos 	as->as_kresult = KRESULT_DONE;
55983e9580Sangelos 	if (keynote_errno)
56983e9580Sangelos 	  as->as_error = keynote_errno;
57983e9580Sangelos 	if (keynote_errno == ERROR_MEMORY)
58983e9580Sangelos 	  return -1;
59983e9580Sangelos 	else
60983e9580Sangelos 	{
61983e9580Sangelos 	    keynote_errno = 0;  /* Ignore syntax errors for now */
62983e9580Sangelos 	    return 0;
63983e9580Sangelos 	}
64983e9580Sangelos     }
65983e9580Sangelos 
66983e9580Sangelos     if (as->as_result == 0)
67983e9580Sangelos     {
68983e9580Sangelos         as->as_kresult = KRESULT_DONE;
69983e9580Sangelos         return as->as_result;
70983e9580Sangelos     }
71983e9580Sangelos 
72983e9580Sangelos     for (kl = as->as_keylist;
73313d0fe7Smmcc 	 kl != NULL;
74983e9580Sangelos 	 kl = kl->key_next)
75983e9580Sangelos     {
76983e9580Sangelos 	switch (keynote_in_action_authorizers(kl->key_key, kl->key_alg))
77983e9580Sangelos 	{
78983e9580Sangelos 	    case -1:
79983e9580Sangelos 		as->as_kresult = KRESULT_DONE;
80983e9580Sangelos 		if (keynote_errno == ERROR_MEMORY)
81983e9580Sangelos 		{
82983e9580Sangelos 		    as->as_error = ERROR_MEMORY;
83983e9580Sangelos 		    return -1;
84983e9580Sangelos 		}
85983e9580Sangelos 		else
86983e9580Sangelos 		{
87983e9580Sangelos 		    keynote_errno = 0; /* Reset */
88983e9580Sangelos 		    continue;
89983e9580Sangelos 		}
90983e9580Sangelos 
91983e9580Sangelos 	    case RESULT_FALSE:    /* Not there, check for assertions instead */
92983e9580Sangelos 		break;
93983e9580Sangelos 
94983e9580Sangelos 	    case RESULT_TRUE:     /* Ok, don't bother with assertions */
95313d0fe7Smmcc 		keynote_current_assertion = NULL;
96983e9580Sangelos 		continue;
97983e9580Sangelos 	}
98983e9580Sangelos 
99983e9580Sangelos 	for (i = 0;; i++)
100983e9580Sangelos 	{
101983e9580Sangelos 	    ast = keynote_find_assertion(kl->key_key, i, kl->key_alg);
102313d0fe7Smmcc 	    if (ast == NULL)
103983e9580Sangelos 	      break;
104983e9580Sangelos 
105983e9580Sangelos 	    if (ast->as_kresult == KRESULT_IN_PROGRESS) /* Cycle detected */
106983e9580Sangelos 	      continue;
107983e9580Sangelos 
108983e9580Sangelos 	    if (ast->as_kresult == KRESULT_UNTOUCHED)   /* Recurse if needed */
109983e9580Sangelos 	      rec_evaluate_query(ast);
110983e9580Sangelos 
111983e9580Sangelos 	    /* Check for errors */
112983e9580Sangelos 	    if (keynote_errno == ERROR_MEMORY)
113983e9580Sangelos 	    {
114983e9580Sangelos 		as->as_error = ERROR_MEMORY;
115983e9580Sangelos 		as->as_kresult = KRESULT_DONE;
116983e9580Sangelos 		return -1;
117983e9580Sangelos 	    }
118983e9580Sangelos 	    else
119983e9580Sangelos 	      keynote_errno = 0; /* Reset */
120983e9580Sangelos 	}
121983e9580Sangelos     }
122983e9580Sangelos 
123983e9580Sangelos     keynote_current_assertion = as;
124983e9580Sangelos     s = keynote_parse_keypred(as, 0);
125313d0fe7Smmcc     keynote_current_assertion = NULL;
126983e9580Sangelos 
127983e9580Sangelos     if (keynote_errno == ERROR_MEMORY)
128983e9580Sangelos     {
129983e9580Sangelos 	as->as_error = ERROR_MEMORY;
130983e9580Sangelos 	as->as_kresult = KRESULT_DONE;
131983e9580Sangelos 	return -1;
132983e9580Sangelos     }
133983e9580Sangelos     else
134983e9580Sangelos       if (keynote_errno)
135983e9580Sangelos       {
136983e9580Sangelos 	  keynote_errno = 0;
137983e9580Sangelos 	  s = 0;
138983e9580Sangelos       }
139983e9580Sangelos 
140983e9580Sangelos     /* Keep lower of two */
141983e9580Sangelos     as->as_result = (as->as_result < s ? as->as_result : s);
142983e9580Sangelos 
143983e9580Sangelos     /* Check the signature now if we haven't done so already */
144983e9580Sangelos     if (as->as_sigresult == SIGRESULT_UNTOUCHED)
145983e9580Sangelos     {
146983e9580Sangelos 	if (!(as->as_flags & ASSERT_FLAG_LOCAL))
147983e9580Sangelos 	  as->as_sigresult = keynote_sigverify_assertion(as);
148983e9580Sangelos 	else
149983e9580Sangelos 	  as->as_sigresult = SIGRESULT_TRUE;    /* Trusted assertion */
150983e9580Sangelos     }
151983e9580Sangelos 
152983e9580Sangelos     if (as->as_sigresult != SIGRESULT_TRUE)
153983e9580Sangelos     {
154983e9580Sangelos 	as->as_result = 0;
155983e9580Sangelos 	as->as_sigresult = SIGRESULT_FALSE;
156983e9580Sangelos 	if (keynote_errno != ERROR_MEMORY)
157983e9580Sangelos 	  keynote_errno = 0; /* Reset */
158983e9580Sangelos 	else
159983e9580Sangelos 	{
160983e9580Sangelos 	    as->as_error = ERROR_MEMORY;
161983e9580Sangelos 	    as->as_kresult = KRESULT_DONE;
162983e9580Sangelos 	    return -1;
163983e9580Sangelos 	}
164983e9580Sangelos     }
165983e9580Sangelos 
166983e9580Sangelos     as->as_kresult = KRESULT_DONE;
167983e9580Sangelos     return as->as_result;
168983e9580Sangelos }
169983e9580Sangelos 
170983e9580Sangelos /*
171983e9580Sangelos  * Fix the Authorizer/Licencees/Signature fields. If the first argument is
172983e9580Sangelos  * empty, fix all assertions. The second argument specifies whether the
173983e9580Sangelos  * Signature field should be parsed or not.
174983e9580Sangelos  */
175983e9580Sangelos static int
keynote_fix_fields(struct assertion * ast,int sigfield)176983e9580Sangelos keynote_fix_fields(struct assertion *ast, int sigfield)
177983e9580Sangelos {
178983e9580Sangelos     struct assertion *as;
179983e9580Sangelos     int i;
180983e9580Sangelos 
181983e9580Sangelos     /* Signature generation/verification handling, no need to eval Licensees */
182313d0fe7Smmcc     if (ast != NULL)
183983e9580Sangelos     {
184983e9580Sangelos 	/* Authorizer */
185983e9580Sangelos 	if (keynote_evaluate_authorizer(ast, 1) != RESULT_TRUE)
186983e9580Sangelos 	  return -1;
187983e9580Sangelos 
188983e9580Sangelos 	/* Signature */
189313d0fe7Smmcc 	if ((sigfield) && (ast->as_signature_string_s != NULL))
190983e9580Sangelos 	  if (keynote_evaluate_authorizer(ast, 0) != RESULT_TRUE)
191983e9580Sangelos 	    return -1;
192983e9580Sangelos 
193983e9580Sangelos 	return RESULT_TRUE;
194983e9580Sangelos     }
195983e9580Sangelos 
196983e9580Sangelos     for (i = 0; i < HASHTABLESIZE; i++)
197983e9580Sangelos       for (as = keynote_current_session->ks_assertion_table[i];
198313d0fe7Smmcc 	   as != NULL;
199983e9580Sangelos 	   as = as->as_next)
200983e9580Sangelos       {
201983e9580Sangelos 	  if (!(as->as_internalflags & ASSERT_IFLAG_NEEDPROC) &&
202983e9580Sangelos 	      !(as->as_internalflags & ASSERT_IFLAG_WEIRDLICS) &&
203983e9580Sangelos 	      !(as->as_internalflags & ASSERT_IFLAG_WEIRDAUTH) &&
204983e9580Sangelos 	      !(as->as_internalflags & ASSERT_IFLAG_WEIRDSIG))
205983e9580Sangelos 	    continue;
206983e9580Sangelos 
207983e9580Sangelos 	  /* Parse the Signature field */
208983e9580Sangelos 	  if (((as->as_internalflags & ASSERT_IFLAG_WEIRDSIG) ||
209983e9580Sangelos 	       (as->as_internalflags & ASSERT_IFLAG_NEEDPROC)) &&
210313d0fe7Smmcc 	      (as->as_signature_string_s != NULL))
211983e9580Sangelos 	    if (keynote_evaluate_authorizer(as, 0) == -1)
212983e9580Sangelos 	    {
213983e9580Sangelos 		if (keynote_errno)
214983e9580Sangelos 		  as->as_error = keynote_errno;
215983e9580Sangelos 		if (keynote_errno == ERROR_MEMORY)
216983e9580Sangelos 		  return -1;
217983e9580Sangelos 		else
218983e9580Sangelos 		  keynote_errno = 0;
219983e9580Sangelos 	    }
220983e9580Sangelos 
221983e9580Sangelos 	  /* Parse the Licensees field */
222983e9580Sangelos 	  if ((as->as_internalflags & ASSERT_IFLAG_WEIRDLICS) ||
223983e9580Sangelos 	      (as->as_internalflags & ASSERT_IFLAG_NEEDPROC))
224983e9580Sangelos 	    if (keynote_parse_keypred(as, 1) == -1)
225983e9580Sangelos 	    {
226983e9580Sangelos 		if (keynote_errno)
227983e9580Sangelos 		    as->as_error = keynote_errno;
228983e9580Sangelos 		if (keynote_errno == ERROR_MEMORY)
229983e9580Sangelos 		  return -1;
230983e9580Sangelos 		else
231983e9580Sangelos 		  keynote_errno = 0;
232983e9580Sangelos 	    }
233983e9580Sangelos 
234983e9580Sangelos 	  /* Parse the Authorizer field */
235983e9580Sangelos 	  if ((as->as_internalflags & ASSERT_IFLAG_WEIRDAUTH) ||
236983e9580Sangelos 	      (as->as_internalflags & ASSERT_IFLAG_NEEDPROC))
237983e9580Sangelos 	    if (keynote_evaluate_authorizer(as, 1) == -1)
238983e9580Sangelos 	    {
239983e9580Sangelos 		if (keynote_errno)
240983e9580Sangelos 		  as->as_error = keynote_errno;
241983e9580Sangelos 		if (keynote_errno == ERROR_MEMORY)
242983e9580Sangelos 		  return -1;
243983e9580Sangelos 		else
244983e9580Sangelos 		  keynote_errno = 0;
245983e9580Sangelos 	    }
246983e9580Sangelos       }
247983e9580Sangelos 
248983e9580Sangelos     /* Reposition if necessary */
249983e9580Sangelos     for (i = 0; i < HASHTABLESIZE; i++)
250983e9580Sangelos       for (as = keynote_current_session->ks_assertion_table[i];
251313d0fe7Smmcc 	   as != NULL;
252983e9580Sangelos 	   as = as->as_next)
253983e9580Sangelos 	if (((as->as_internalflags & ASSERT_IFLAG_WEIRDAUTH) &&
254983e9580Sangelos 	     !(as->as_internalflags & ASSERT_IFLAG_PROCESSED)) ||
255983e9580Sangelos 	    (as->as_internalflags & ASSERT_IFLAG_NEEDPROC))
256983e9580Sangelos 	{
257983e9580Sangelos 	    as->as_internalflags &= ~ASSERT_IFLAG_NEEDPROC;
258983e9580Sangelos 	    as->as_internalflags |= ASSERT_IFLAG_PROCESSED;
259983e9580Sangelos 	    keynote_sremove_assertion(keynote_current_session->ks_id,
260983e9580Sangelos 				      as->as_id);
261983e9580Sangelos 
262983e9580Sangelos 	    if (keynote_add_htable(as, 1) != RESULT_TRUE)
263983e9580Sangelos 	      return -1;
264983e9580Sangelos 
2655dbcbdb5Smmcc 	    /* Point to beginning of the previous list. */
266983e9580Sangelos 	    i--;
267983e9580Sangelos 	    break;
268983e9580Sangelos 	}
269983e9580Sangelos 
270983e9580Sangelos     return RESULT_TRUE;
271983e9580Sangelos }
272983e9580Sangelos 
273983e9580Sangelos /*
274983e9580Sangelos  * Find the trust graph. This is a depth-first search, starting at
275983e9580Sangelos  * POLICY assertions.
276983e9580Sangelos  */
277983e9580Sangelos int
keynote_evaluate_query(void)278983e9580Sangelos keynote_evaluate_query(void)
279983e9580Sangelos {
280983e9580Sangelos     struct assertion *as;
281983e9580Sangelos     int p, prev;
282983e9580Sangelos     int i;
283983e9580Sangelos 
284983e9580Sangelos     /* Fix the authorizer/licensees/signature fields */
285313d0fe7Smmcc     if (keynote_fix_fields(NULL, 0) != RESULT_TRUE)
286983e9580Sangelos       return -1;
287983e9580Sangelos 
288983e9580Sangelos     /* Find POLICY assertions and try to evaluate the query. */
289983e9580Sangelos     for (i = 0, prev = 0; i < HASHTABLESIZE; i++)
290983e9580Sangelos       for (as = keynote_current_session->ks_assertion_table[i];
291313d0fe7Smmcc 	   as != NULL;
292983e9580Sangelos 	   as = as->as_next)
293313d0fe7Smmcc 	if ((as->as_authorizer != NULL) &&      /* Paranoid */
294983e9580Sangelos             (as->as_signeralgorithm == KEYNOTE_ALGORITHM_NONE))
295983e9580Sangelos 	  if ((!strcmp("POLICY", as->as_authorizer)) &&
296983e9580Sangelos 	      (as->as_flags & ASSERT_FLAG_LOCAL))
297983e9580Sangelos 	  {
298983e9580Sangelos 	      if ((p = rec_evaluate_query(as)) == -1)
299983e9580Sangelos 	      {
300983e9580Sangelos 		  if (keynote_errno)
301983e9580Sangelos 		    as->as_error = keynote_errno;
302983e9580Sangelos 		  if (keynote_errno == ERROR_MEMORY)
303983e9580Sangelos 		    return -1;
304983e9580Sangelos 		  else
305983e9580Sangelos 		  {
306983e9580Sangelos 		      keynote_errno = 0;
307983e9580Sangelos 		      continue;
308983e9580Sangelos 		  }
309983e9580Sangelos 	      }
310983e9580Sangelos 
311983e9580Sangelos 	      if (p > prev)
312983e9580Sangelos 		prev = p;
313983e9580Sangelos 
314983e9580Sangelos 	      /* If we get the highest possible return value, just return */
315983e9580Sangelos 	      if (prev == (keynote_current_session->ks_values_num - 1))
316983e9580Sangelos 		return prev;
317983e9580Sangelos 	  }
318983e9580Sangelos 
319983e9580Sangelos     return prev;
320983e9580Sangelos }
321983e9580Sangelos 
322983e9580Sangelos /*
323983e9580Sangelos  * Return keyword type.
324983e9580Sangelos  */
325983e9580Sangelos static int
whichkeyword(char * start,char * end)326983e9580Sangelos whichkeyword(char *start, char *end)
327983e9580Sangelos {
328983e9580Sangelos     int len = (end - start);
329983e9580Sangelos 
330983e9580Sangelos     if (len <= 0)
331983e9580Sangelos     {
332983e9580Sangelos 	keynote_errno = ERROR_MEMORY;
333983e9580Sangelos 	return -1;
334983e9580Sangelos     }
335983e9580Sangelos 
336983e9580Sangelos     if (!strncasecmp("keynote-version:", start, len))
337983e9580Sangelos       return KEYWORD_VERSION;
338983e9580Sangelos 
339983e9580Sangelos     if (!strncasecmp("local-constants:", start, len))
340983e9580Sangelos       return KEYWORD_LOCALINIT;
341983e9580Sangelos 
342983e9580Sangelos     if (!strncasecmp("authorizer:", start, len))
343983e9580Sangelos       return KEYWORD_AUTHORIZER;
344983e9580Sangelos 
345983e9580Sangelos     if (!strncasecmp("licensees:", start, len))
346983e9580Sangelos       return KEYWORD_LICENSEES;
347983e9580Sangelos 
348983e9580Sangelos     if (!strncasecmp("conditions:", start, len))
349983e9580Sangelos       return KEYWORD_CONDITIONS;
350983e9580Sangelos 
351983e9580Sangelos     if (!strncasecmp("signature:", start, len))
352983e9580Sangelos       return KEYWORD_SIGNATURE;
353983e9580Sangelos 
354983e9580Sangelos     if (!strncasecmp("comment:", start, len))
355983e9580Sangelos       return KEYWORD_COMMENT;
356983e9580Sangelos 
357983e9580Sangelos     keynote_errno = ERROR_SYNTAX;
358983e9580Sangelos     return -1;
359983e9580Sangelos }
360983e9580Sangelos 
361983e9580Sangelos /*
362983e9580Sangelos  * Parse an assertion. Set keynote_errno to ERROR_SYNTAX if parsing
363983e9580Sangelos  * failed due to certificate badness, and ERROR_MEMORY if memory
364983e9580Sangelos  * problem. If more than one assertions have been passed in the
365983e9580Sangelos  * buffer, they will be linked.
366983e9580Sangelos  */
367983e9580Sangelos struct assertion *
keynote_parse_assertion(char * buf,int len,int assertion_flags)368983e9580Sangelos keynote_parse_assertion(char *buf, int len, int assertion_flags)
369983e9580Sangelos {
370204e95a6Sangelos     int k, i, j, seen_field = 0, ver = 0, end_of_assertion = 0;
371313d0fe7Smmcc     char *ks, *ke, *ts, *te = NULL;
372983e9580Sangelos     struct assertion *as;
373983e9580Sangelos 
374983e9580Sangelos     /* Allocate memory for assertion */
375313d0fe7Smmcc     as = calloc(1, sizeof(struct assertion));
376313d0fe7Smmcc     if (as == NULL)
377983e9580Sangelos     {
378983e9580Sangelos 	keynote_errno = ERROR_MEMORY;
379313d0fe7Smmcc 	return NULL;
380983e9580Sangelos     }
381983e9580Sangelos 
382983e9580Sangelos     /* Keep a copy of the assertion around */
383983e9580Sangelos     as->as_buf = strdup(buf);
384313d0fe7Smmcc     if (as->as_buf == NULL)
385983e9580Sangelos     {
386983e9580Sangelos 	keynote_errno = ERROR_MEMORY;
387983e9580Sangelos 	keynote_free_assertion(as);
388313d0fe7Smmcc 	return NULL;
389983e9580Sangelos     }
390983e9580Sangelos 
391983e9580Sangelos     as->as_flags = assertion_flags & ~(ASSERT_FLAG_SIGGEN |
392983e9580Sangelos 				       ASSERT_FLAG_SIGVER);
393983e9580Sangelos 
394983e9580Sangelos     /* Skip any leading whitespace */
39580c62621Sderaadt     for (i = 0, j = len; i < j && isspace((unsigned char)as->as_buf[i]); i++)
396983e9580Sangelos      ;
397983e9580Sangelos 
398*2c53affbSjmc     /* Keyword must start at beginning of buffer or line */
399983e9580Sangelos     if ((i >= j) || ((i != 0) && (as->as_buf[i - 1] != '\n')))
400983e9580Sangelos     {
401983e9580Sangelos 	keynote_free_assertion(as);
402983e9580Sangelos 	keynote_errno = ERROR_SYNTAX;
403313d0fe7Smmcc 	return NULL;
404983e9580Sangelos     }
405983e9580Sangelos 
406983e9580Sangelos     while (i < j)			/* Decomposition loop */
407983e9580Sangelos     {
408983e9580Sangelos 	ks = as->as_buf + i;
409983e9580Sangelos 
410*2c53affbSjmc 	/* Mark beginning of assertion for signature purposes */
411313d0fe7Smmcc 	if (as->as_startofsignature == NULL)
412983e9580Sangelos 	  as->as_startofsignature = ks;
413983e9580Sangelos 
414*2c53affbSjmc 	/* This catches comments at the beginning of an assertion only */
415983e9580Sangelos 	if (as->as_buf[i] == '#')	/* Comment */
416983e9580Sangelos 	{
417983e9580Sangelos 	    seen_field = 1;
418983e9580Sangelos 
419983e9580Sangelos    	    /* Skip until the end of line */
420983e9580Sangelos 	    while ((i< j) && as->as_buf[++i] != '\n')
421983e9580Sangelos 	      ;
422983e9580Sangelos 
423de098062Sangelos 	    i++;
424983e9580Sangelos 	    continue;  /* Loop */
425983e9580Sangelos 	}
426983e9580Sangelos 
427983e9580Sangelos 	/* Advance until we find a keyword separator */
428983e9580Sangelos 	for (; (as->as_buf[i] != ':') && (i < j); i++)
429983e9580Sangelos 	  ;
430983e9580Sangelos 
431983e9580Sangelos 	if (i + 1 > j)
432983e9580Sangelos 	{
433983e9580Sangelos 	    keynote_free_assertion(as);
434983e9580Sangelos 	    keynote_errno = ERROR_SYNTAX;
435313d0fe7Smmcc 	    return NULL;
436983e9580Sangelos 	}
437983e9580Sangelos 
438*2c53affbSjmc 	/* ks points at beginning of keyword, ke points at end */
439983e9580Sangelos 	ke = as->as_buf + i;
440983e9580Sangelos 
441*2c53affbSjmc 	/* ts points at beginning of value field */
442983e9580Sangelos 	ts = as->as_buf + i + 1;	/* Skip ':' */
443983e9580Sangelos 
444983e9580Sangelos 	/*
445983e9580Sangelos 	 * Find the end of the field -- means end of buffer,
446983e9580Sangelos 	 * a newline followed by a non-whitespace character,
447983e9580Sangelos 	 * or two newlines.
448983e9580Sangelos 	 */
449983e9580Sangelos 	while (++i <= j)
450983e9580Sangelos 	{
451983e9580Sangelos 	    /* If end of buffer, we're at the end of the field */
452983e9580Sangelos 	    if (i == j)
453983e9580Sangelos 	    {
454983e9580Sangelos 		end_of_assertion = 1;
455983e9580Sangelos 		te = as->as_buf + i;
456983e9580Sangelos 		break;
457983e9580Sangelos 	    }
458983e9580Sangelos 
459983e9580Sangelos 	    /* If two newlines, end of assertion */
460983e9580Sangelos 	    if ((as->as_buf[i] == '\n') && (i + 1 < j) &&
461983e9580Sangelos 		(as->as_buf[i + 1] == '\n'))
462983e9580Sangelos 	    {
463983e9580Sangelos 		end_of_assertion = 1;
464983e9580Sangelos 		te = as->as_buf + i;
465983e9580Sangelos 		break;
466983e9580Sangelos 	    }
467983e9580Sangelos 
468983e9580Sangelos 	    /* If newline followed by non-whitespace or comment character */
469983e9580Sangelos 	    if ((as->as_buf[i] == '\n') &&
47080c62621Sderaadt 		(!isspace((unsigned char)as->as_buf[i + 1])) &&
471adf9c6c4Sangelos                 (as->as_buf[i + 1] != '#'))
472983e9580Sangelos 	    {
473983e9580Sangelos 	        te = as->as_buf + i;
474983e9580Sangelos 	        break;
475983e9580Sangelos 	    }
476983e9580Sangelos 	}
477983e9580Sangelos 
478983e9580Sangelos 	i++;
479983e9580Sangelos 
480983e9580Sangelos 	/*
481983e9580Sangelos 	 * On each of the cases (except the first), we check that:
482983e9580Sangelos 	 *  - we've already seen a keynote-version field (and that
483983e9580Sangelos 	 *    it's the first one that appears in the assertion)
484983e9580Sangelos 	 *  - the signature field, if present, is the last one
485983e9580Sangelos 	 *  - no field appears more than once
486983e9580Sangelos 	 */
487983e9580Sangelos 	switch (whichkeyword(ks, ke))
488983e9580Sangelos 	{
489983e9580Sangelos 	    case -1:
490983e9580Sangelos 		keynote_free_assertion(as);
491313d0fe7Smmcc 		return NULL;
492983e9580Sangelos 
493983e9580Sangelos 	    case KEYWORD_VERSION:
494983e9580Sangelos 		if ((ver == 1) || (seen_field == 1))
495983e9580Sangelos 		{
496983e9580Sangelos 		    keynote_free_assertion(as);
497983e9580Sangelos 		    keynote_errno = ERROR_SYNTAX;
498313d0fe7Smmcc 		    return NULL;
499983e9580Sangelos 		}
500983e9580Sangelos 
501983e9580Sangelos 		/* Test for version correctness */
502983e9580Sangelos 		keynote_get_envlist(ts, te, 1);
503983e9580Sangelos 		if (keynote_errno != 0)
504983e9580Sangelos 		{
505983e9580Sangelos 		    keynote_free_assertion(as);
506313d0fe7Smmcc 		    return NULL;
507983e9580Sangelos 		}
508983e9580Sangelos 
509983e9580Sangelos 		ver = 1;
510983e9580Sangelos 		break;
511983e9580Sangelos 
512983e9580Sangelos 	    case KEYWORD_LOCALINIT:
513313d0fe7Smmcc 		if (as->as_env != NULL)
514983e9580Sangelos 		{
515983e9580Sangelos 		    keynote_free_assertion(as);
516983e9580Sangelos 		    keynote_errno = ERROR_SYNTAX;
517313d0fe7Smmcc 		    return NULL;
518983e9580Sangelos 		}
519983e9580Sangelos 
520983e9580Sangelos 		as->as_env = keynote_get_envlist(ts, te, 0);
521983e9580Sangelos 		if (keynote_errno != 0)
522983e9580Sangelos 		{
523983e9580Sangelos 		    keynote_free_assertion(as);
524313d0fe7Smmcc 		    return NULL;
525983e9580Sangelos 		}
526983e9580Sangelos 		break;
527983e9580Sangelos 
528983e9580Sangelos 	    case KEYWORD_AUTHORIZER:
529313d0fe7Smmcc 		if (as->as_authorizer_string_s != NULL)
530983e9580Sangelos 		{
531983e9580Sangelos 		    keynote_free_assertion(as);
532983e9580Sangelos 		    keynote_errno = ERROR_SYNTAX;
533313d0fe7Smmcc 		    return NULL;
534983e9580Sangelos 		}
535983e9580Sangelos 
536983e9580Sangelos 		as->as_authorizer_string_s = ts;
537983e9580Sangelos 		as->as_authorizer_string_e = te;
538983e9580Sangelos 		break;
539983e9580Sangelos 
540983e9580Sangelos 	    case KEYWORD_LICENSEES:
541313d0fe7Smmcc 		if (as->as_keypred_s != NULL)
542983e9580Sangelos 		{
543983e9580Sangelos 		    keynote_free_assertion(as);
544983e9580Sangelos 		    keynote_errno = ERROR_SYNTAX;
545313d0fe7Smmcc 		    return NULL;
546983e9580Sangelos 		}
547983e9580Sangelos 
548983e9580Sangelos 		as->as_keypred_s = ts;
549983e9580Sangelos 		as->as_keypred_e = te;
550983e9580Sangelos 		break;
551983e9580Sangelos 
552983e9580Sangelos 	    case KEYWORD_CONDITIONS:
553313d0fe7Smmcc 		if (as->as_conditions_s != NULL)
554983e9580Sangelos 		{
555983e9580Sangelos 		    keynote_free_assertion(as);
556983e9580Sangelos 		    keynote_errno = ERROR_SYNTAX;
557313d0fe7Smmcc 		    return NULL;
558983e9580Sangelos 		}
559983e9580Sangelos 
560983e9580Sangelos 		as->as_conditions_s = ts;
561983e9580Sangelos 		as->as_conditions_e = te;
562983e9580Sangelos 		break;
563983e9580Sangelos 
564983e9580Sangelos 	    case KEYWORD_SIGNATURE:
565313d0fe7Smmcc 		if (as->as_signature_string_s != NULL)
566983e9580Sangelos 		{
567983e9580Sangelos 		    keynote_free_assertion(as);
568983e9580Sangelos 		    keynote_errno = ERROR_SYNTAX;
569313d0fe7Smmcc 		    return NULL;
570983e9580Sangelos 		}
571983e9580Sangelos 
572983e9580Sangelos 		end_of_assertion = 1;
573983e9580Sangelos 		as->as_allbutsignature = ks;
574983e9580Sangelos 		as->as_signature_string_s = ts;
575983e9580Sangelos 		as->as_signature_string_e = te;
576983e9580Sangelos 		break;
577983e9580Sangelos 
578983e9580Sangelos 	    case KEYWORD_COMMENT:
579313d0fe7Smmcc 		if (as->as_comment_s != NULL)
580983e9580Sangelos 		{
581983e9580Sangelos 		    keynote_free_assertion(as);
582983e9580Sangelos 		    keynote_errno = ERROR_SYNTAX;
583313d0fe7Smmcc 		    return NULL;
584983e9580Sangelos 		}
585983e9580Sangelos 
586983e9580Sangelos 		as->as_comment_s = ts;
587983e9580Sangelos 		as->as_comment_e = te;
588983e9580Sangelos 		break;
589983e9580Sangelos 	}
590983e9580Sangelos 
591983e9580Sangelos 	seen_field = 1;
592983e9580Sangelos 	if (end_of_assertion == 1)
593204e95a6Sangelos 	{
594204e95a6Sangelos 	    /* End of buffer, good termination */
595204e95a6Sangelos 	    if ((te == as->as_buf + len) || (te + 1 == as->as_buf + len) ||
596204e95a6Sangelos 		(*(te) == '\0') || (*(te + 1) == '\0'))
597983e9580Sangelos 	      break;
598204e95a6Sangelos 
599204e95a6Sangelos 	    /* Check whether there's something else following */
600204e95a6Sangelos 	    for (k = 1; te + k < as->as_buf + len && *(te + k) != '\n'; k++)
60180c62621Sderaadt 	      if (!isspace((unsigned char)*(te + k)))
602204e95a6Sangelos 	      {
603204e95a6Sangelos 		  keynote_free_assertion(as);
604204e95a6Sangelos 		  keynote_errno = ERROR_SYNTAX;
605313d0fe7Smmcc 		  return NULL;
606204e95a6Sangelos 	      }
607204e95a6Sangelos 
608204e95a6Sangelos 	    break; /* Assertion is "properly" terminated */
609204e95a6Sangelos 	}
610983e9580Sangelos     }
611983e9580Sangelos 
612983e9580Sangelos     /* Check that the basic fields are there */
613313d0fe7Smmcc     if (as->as_authorizer_string_s == NULL)
614983e9580Sangelos     {
615983e9580Sangelos 	keynote_free_assertion(as);
616983e9580Sangelos 	keynote_errno = ERROR_SYNTAX;
617313d0fe7Smmcc 	return NULL;
618983e9580Sangelos     }
619983e9580Sangelos 
620983e9580Sangelos     /* Signature generation/verification handling */
621983e9580Sangelos     if (assertion_flags & ASSERT_FLAG_SIGGEN)
622983e9580Sangelos     {
623983e9580Sangelos         if (keynote_fix_fields(as, 0) != RESULT_TRUE)
624983e9580Sangelos         {
625983e9580Sangelos 	    keynote_free_assertion(as);
626313d0fe7Smmcc 	    return NULL;
627983e9580Sangelos         }
628983e9580Sangelos     }
629983e9580Sangelos     else
630983e9580Sangelos       if (assertion_flags & ASSERT_FLAG_SIGVER)
631983e9580Sangelos 	if (keynote_fix_fields(as, 1) != RESULT_TRUE)
632983e9580Sangelos 	{
633983e9580Sangelos 	    keynote_free_assertion(as);
634313d0fe7Smmcc 	    return NULL;
635983e9580Sangelos 	}
636983e9580Sangelos 
637983e9580Sangelos     return as;
638983e9580Sangelos }
639