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