xref: /openbsd/lib/libkeynote/keynote.l (revision 4812cf71)
1 %{
2 /* $OpenBSD: keynote.l,v 1.7 2000/02/12 00:26:16 angelos Exp $ */
3 /*
4  * The author of this code is Angelos D. Keromytis (angelos@dsl.cis.upenn.edu)
5  *
6  * This code was written by Angelos D. Keromytis in Philadelphia, PA, USA,
7  * in April-May 1998
8  *
9  * Copyright (C) 1998, 1999 by Angelos D. Keromytis.
10  *
11  * Permission to use, copy, and modify this software without fee
12  * is hereby granted, provided that this entire notice is included in
13  * all copies of any software which is or includes a copy or
14  * modification of this software.
15  *
16  * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR
17  * IMPLIED WARRANTY. IN PARTICULAR, THE AUTHORS MAKES NO
18  * REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE
19  * MERCHANTABILITY OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR
20  * PURPOSE.
21  */
22 
23 #if HAVE_CONFIG_H
24 #include "config.h"
25 #endif /* HAVE_CONFIG_H */
26 
27 #include <sys/types.h>
28 #include <ctype.h>
29 
30 #if STDC_HEADERS
31 #include <string.h>
32 #endif /* STDC_HEADERS */
33 
34 #if HAVE_UNISTD_H
35 #include <unistd.h>
36 #endif /* HAVE_UNISTD_H */
37 
38 #if TIME_WITH_SYS_TIME
39 #include <sys/time.h>
40 #include <time.h>
41 #else
42 #if HAVE_SYS_TIME_H
43 #include <sys/time.h>
44 #else
45 #include <time.h>
46 #endif
47 #endif
48 
49 #include "k.tab.h"
50 #include "header.h"
51 #include "keynote.h"
52 #include "assertion.h"
53 
54 static void mystrncpy(char *, char *, int);
55 
56 struct lex_list
57 {
58     int   lex_type;
59     void *lex_s;
60 };
61 
62 static struct lex_list *keynote_lex_list = (struct lex_list *) NULL;
63 static int    keynote_max_lex_list = 32;
64 static int    keynote_lex_counter = 0;
65 static int    first_tok = 0;
66 %}
67 digit		[0-9]
68 specnumber      [1-9][0-9]*
69 number		{digit}+
70 flt		{digit}+"."{digit}+
71 vstring		[a-zA-Z_][a-zA-Z0-9_]*
72 litstring	\"(([^\"\n])|(\\[\"\n.]))*\"
73 variable	{vstring}
74 comment		"#"[^\n]*
75 %s ACTIONSTRING LOCALINIT KEYPREDICATE SIGNERINIT KEYNOTEVERSION
76 %pointer
77 %option noyywrap never-interactive yylineno
78 %%
79 
80 %{
81     /*
82      * Return a preset token, so we can have more than one grammars
83      * in yacc.
84      */
85     extern int first_tok;
86 
87     if (first_tok)
88     {
89 	int holdtok = first_tok;
90 
91 	first_tok = 0;
92 	return holdtok;
93     }
94 %}
95 
96 <KEYPREDICATE>{specnumber}"-of"		{
97 					  knlval.intval = atoi(kntext);
98 					  return KOF;
99 					}
100 <ACTIONSTRING,KEYPREDICATE>"("		return OPENPAREN;
101 <ACTIONSTRING,KEYPREDICATE>")"		return CLOSEPAREN;
102 <ACTIONSTRING,KEYPREDICATE>"&&"		return AND;
103 <ACTIONSTRING,KEYPREDICATE>"||"		return OR;
104 <ACTIONSTRING>"+"			return PLUS;
105 <ACTIONSTRING>"->"              return HINT;
106 <ACTIONSTRING>"{"               return OPENBLOCK;
107 <ACTIONSTRING>"}"               return CLOSEBLOCK;
108 <ACTIONSTRING>";"               return SEMICOLON;
109 <ACTIONSTRING>"!"		return NOT;
110 <ACTIONSTRING>"~="		return REGEXP;
111 <ACTIONSTRING>"=="		return EQ;
112 <ACTIONSTRING>"!="		return NE;
113 <ACTIONSTRING>"<"		return LT;
114 <ACTIONSTRING>">"		return GT;
115 <ACTIONSTRING>"<="		return LE;
116 <ACTIONSTRING>">="		return GE;
117 <ACTIONSTRING>"-"		return MINUS;
118 <ACTIONSTRING>"*"		return MULT;
119 <ACTIONSTRING>"/"		return DIV;
120 <ACTIONSTRING>"%"		return MOD;
121 <ACTIONSTRING>"^"		return EXP;
122 "."		                return DOTT;
123 <ACTIONSTRING>"true"            return TRUE;
124 <ACTIONSTRING>"false"           return FALSE;
125 {comment}		/* eat up comments */
126 <LOCALINIT>"="	                return EQQ;
127 <KEYPREDICATE>"," 		return COMMA;
128 <ACTIONSTRING,KEYPREDICATE,SIGNERINIT,LOCALINIT>{variable} {
129                                         if (keynote_exceptionflag ||
130 					    keynote_donteval)
131 					{
132 					    knlval.string = (char *) NULL;
133 					    return VARIABLE;
134 					}
135 
136 					knlval.string = calloc(strlen(kntext)
137 							       + 1,
138 							       sizeof(char));
139                                         if (knlval.string == (char *) NULL)
140 					{
141 					    keynote_errno = ERROR_MEMORY;
142 					    return -1;
143 					}
144 		  	          	strcpy(knlval.string, kntext);
145 					if (keynote_lex_add(knlval.string,
146 							    LEXTYPE_CHAR) ==
147 					    -1)
148 					  return -1;
149 		  	         	return VARIABLE;
150 			      	      }
151 "$"                             return DEREF;
152 <ACTIONSTRING>"@"	    	return OPENNUM;
153 <ACTIONSTRING>"&"	    	return OPENFLT;
154 <ACTIONSTRING>{flt}	      {
155 				knlval.doubval = atof(kntext);
156 				return FLOAT;
157 			      }
158 <KEYNOTEVERSION>{number}      {
159                                 if (keynote_exceptionflag ||
160 				    keynote_donteval)
161 				{
162 				    knlval.string = (char *) NULL;
163 				    return STRING;
164 				}
165 
166 				knlval.string = calloc(strlen(kntext) + 1,
167 						       sizeof(char));
168                                 if (knlval.string == (char *) NULL)
169 				{
170 				    keynote_errno = ERROR_MEMORY;
171 				    return -1;
172 				}
173 		  	        strcpy(knlval.string, kntext);
174 				if (keynote_lex_add(knlval.string,
175 						    LEXTYPE_CHAR) == -1)
176 				  return -1;
177 		  	        return STRING;
178 			      }
179 <ACTIONSTRING>{number}	      {
180 				knlval.intval = atoi(kntext);
181 				return NUM;
182 			      }
183 {litstring}                   {
184                                 if (keynote_exceptionflag ||
185 				    keynote_donteval)
186 				{
187 				    knlval.string = (char *) NULL;
188 				    return STRING;
189 				}
190 
191 				knlval.string = calloc(strlen(kntext) - 1,
192 						       sizeof(char));
193                                 if (knlval.string == (char *) NULL)
194 				{
195 				    keynote_errno = ERROR_MEMORY;
196 				    return -1;
197 				}
198 
199 				mystrncpy(knlval.string, kntext + 1,
200 					  strlen(kntext) - 2);
201 
202 				if (keynote_lex_add(knlval.string,
203 						    LEXTYPE_CHAR) == -1)
204 				  return -1;
205 				return STRING;
206                               }
207 [ \t\n]
208 .                             { keynote_errno = ERROR_SYNTAX;
209                                 return -1;
210 				REJECT; /* Avoid -Wall warning. Not reached */
211                               }
212 %%
213 
214 /*
215  * Zap everything.
216  */
217 static void
218 keynote_lex_zap(void)
219 {
220     int i;
221 
222     if (keynote_lex_counter == 0)
223       return;
224 
225     for (i = 0; i < keynote_max_lex_list; i++)
226       if (keynote_lex_list[i].lex_s != (void *) NULL)
227       {
228 	  switch (keynote_lex_list[i].lex_type)
229 	  {
230 	      case LEXTYPE_CHAR:
231 	          free(keynote_lex_list[i].lex_s);
232 		  break;
233 	  }
234 
235 	  keynote_lex_counter--;
236 	  keynote_lex_list[i].lex_s = (void *) NULL;
237 	  keynote_lex_list[i].lex_type = 0;
238       }
239 }
240 
241 /*
242  * Initialize.
243  */
244 static int
245 keynote_lex_init(void)
246 {
247     if (keynote_lex_list != (struct lex_list *) NULL)
248       memset(keynote_lex_list, 0,
249 	     keynote_max_lex_list * sizeof(struct lex_list));
250     else
251     {
252 	keynote_lex_list = (struct lex_list *) calloc(keynote_max_lex_list,
253 					              sizeof(struct lex_list));
254         if (keynote_lex_list == (struct lex_list *) NULL)
255 	{
256 	    keynote_errno = ERROR_MEMORY;
257 	    return -1;
258 	}
259     }
260 
261     return RESULT_TRUE;
262 }
263 
264 /*
265  * Add the string in a list of allocated but "dangling" memory references.
266  * If out of memory, free the string and return -1 (and set keynote_errno).
267  */
268 int
269 keynote_lex_add(void *s, int type)
270 {
271     struct lex_list *p;
272     int i;
273 
274     if (s == (void *) NULL)
275       return RESULT_TRUE;
276 
277     for (i = 0; i < keynote_max_lex_list; i++)
278       if (keynote_lex_list[i].lex_s == (void *) NULL)
279       {
280     	  keynote_lex_list[i].lex_s = (void *) s;
281 	  keynote_lex_list[i].lex_type = type;
282 	  keynote_lex_counter++;
283      	  return RESULT_TRUE;
284       }
285 
286     /* Not enough space, increase the size of the array */
287     keynote_max_lex_list *= 2;
288 
289     p = (struct lex_list *) realloc(keynote_lex_list,
290 				    keynote_max_lex_list *
291 				    sizeof(struct lex_list));
292     if (p == (struct lex_list *) NULL)
293     {
294 	switch (type)
295 	{
296 	    case LEXTYPE_CHAR:
297 	        free(s);
298 		break;
299 	}
300 
301 	keynote_errno = ERROR_MEMORY;
302         return -1;
303     }
304 
305     if (p != keynote_lex_list)
306     {
307 	free(keynote_lex_list);
308         keynote_lex_list = p;
309     }
310 
311     keynote_lex_list[i].lex_s = s;
312     keynote_lex_list[i++].lex_type = type;
313     keynote_lex_counter++;
314 
315     /* Zero out the rest */
316     memset(&(keynote_lex_list[i]), 0,
317 	   (keynote_max_lex_list - i) * sizeof(struct lex_list));
318 
319     return RESULT_TRUE;
320 }
321 
322 /*
323  * Remove string.
324  */
325 void
326 keynote_lex_remove(void *s)
327 {
328     int i;
329 
330     for (i = 0; i < keynote_max_lex_list; i++)
331       if (keynote_lex_list[i].lex_s == s)
332       {
333 	  memset(&(keynote_lex_list[i]), 0, sizeof(struct lex_list));
334 	  keynote_lex_counter--;
335 	  return;
336       }
337 }
338 
339 /*
340  * Return RESULT_TRUE if character is octal digit, RESULT_FALSE otherwise.
341  */
342 static int
343 is_octal(char c)
344 {
345     switch (c)
346     {
347 	case '0': case '1': case '2': case '3':
348 	case '4': case '5': case '6': case '7':
349 	    return RESULT_TRUE;
350 
351 	default:
352 	    return RESULT_FALSE;
353     }
354 }
355 
356 /*
357  * Return octal value (non-zero) if argument starts with such a
358  * representation, otherwise 0.
359  */
360 static unsigned char
361 get_octal(char *s, int len, int *adv)
362 {
363     unsigned char res = 0;
364 
365     if (*s == '0')
366     {
367 	if (len > 0)
368 	{
369 	    if (is_octal(*(s + 1)))
370 	    {
371 		res = *(s + 1) - '0';
372 		*adv = 2;
373 
374 		if (is_octal(*(s + 2)) && (len - 1 > 0))
375 		{
376 		    res = res * 8 + (*(s + 2) - '0');
377 		    *adv = 3;
378 		}
379 	    }
380 	}
381     }
382     else
383       if (is_octal(*s) && (len - 1 > 0))  /* Non-zero leading */
384       {
385 	  if (is_octal(*(s + 1)) &&
386 	      is_octal(*(s + 2)))
387 	  {
388 	      *adv = 3;
389 	      res = (((*s) - '0') * 64) +
390 		    (((*(s + 1)) - '0') * 8) +
391 		    ((*(s + 2)) - '0');
392 	  }
393       }
394 
395     return res;
396 }
397 
398 /*
399  * Copy at most len characters to string s1 from string s2, taking
400  * care of escaped characters in the process. String s1 is assumed
401  * to have enough space, and be zero'ed.
402  */
403 static void
404 mystrncpy(char *s1, char *s2, int len)
405 {
406     unsigned char c;
407     int advance;
408 
409     if (len == 0)
410       return;
411 
412     while (len-- > 0)
413     {
414         if (*s2 == '\\')
415 	{
416 	    s2++;
417 
418 	    if (len-- <= 0)
419 	      break;
420 
421 	    if (*s2 == '\n')
422 	    {
423 		while (isspace(*(++s2)) && (len-- > 0))
424 		  ;
425 	    }
426 	    else
427 	      if ((c = get_octal(s2, len, &advance)) != 0)
428 	      {
429 		  len -= advance - 1;
430 		  s2 += advance;
431 		  *s1++ = c;
432 	      }
433 	      else
434 		if (*s2 == 'n')  /* Newline */
435 		{
436 		    *s1++ = '\n';
437 		    s2++;
438 		}
439 		else
440 		  if (*s2 == 't')  /* Tab */
441 		  {
442 		      *s1++ = '\t';
443 		      s2++;
444 		  }
445 		  else
446 		    if (*s2 == 'r')  /* Linefeed */
447 		    {
448 			*s1++ = '\r';
449 			s2++;
450 		    }
451 		    else
452 		      if (*s2 == 'f')  /* Formfeed */
453 		      {
454 			  *s1++ = '\f';
455 			  s2++;
456 		      }
457 		      else
458 			if ((*s1++ = *s2++) == 0)
459 			  break;
460 
461 	    continue;
462 	}
463 
464         if ((*s1++ = *s2++) == 0)
465 	  break;
466      }
467 }
468 
469 /*
470  * Evaluate an assertion, with as->as_result holding the result.
471  * Return RESULT_TRUE if all ok. Also return the result.
472  */
473 int
474 keynote_evaluate_assertion(struct assertion *as)
475 {
476     YY_BUFFER_STATE keynote_bs;
477 
478     /* Non-existant Conditions field means highest return value */
479     if (as->as_conditions_s == (char *) NULL)
480     {
481 	as->as_result = keynote_current_session->ks_values_num - 1;
482 	return RESULT_TRUE;
483     }
484 
485     if (keynote_lex_init() != RESULT_TRUE)
486       return -1;
487 
488     keynote_used_variable = 0;
489     keynote_init_list = as->as_env;     /* Setup the local-init var list */
490 
491     keynote_bs = kn_scan_bytes(as->as_conditions_s,
492 			       as->as_conditions_e - as->as_conditions_s);
493     BEGIN(ACTIONSTRING);	/* We're doing conditions-string parsing */
494     first_tok = ACTSTR;
495     as->as_result = 0;
496     keynote_returnvalue = 0;
497 
498     switch (knparse())
499     {
500 	case 1:  /* Fall through */
501 	    keynote_errno = ERROR_SYNTAX;
502 	case -1:
503 	    as->as_result = 0;
504 	    break;
505 
506 	case 0:
507 	    as->as_result = keynote_returnvalue;
508 	    break;
509     }
510 
511     keynote_env_cleanup(&keynote_temp_list, 1);
512     keynote_lex_zap();
513     kn_delete_buffer(keynote_bs);
514 
515     keynote_used_variable = 0;
516     keynote_returnvalue = 0;
517     keynote_temp_list = (struct environment *) NULL;
518     keynote_init_list = (struct environment *) NULL;
519 
520     if (keynote_errno != 0)
521       return -1;
522     else
523       return RESULT_TRUE;
524 }
525 
526 /*
527  * Parse/evaluate a key predicate field.
528  * Store keys in key predicate as keylist in as->as_keylist, if third
529  * argument is true.
530  */
531 int
532 keynote_parse_keypred(struct assertion *as, int record)
533 {
534     YY_BUFFER_STATE keypred_state;
535     int p = 0, err;
536 
537     if (as->as_keypred_s == (char *) NULL)
538       return keynote_current_session->ks_values_num - 1;
539 
540     if (keynote_lex_init() != RESULT_TRUE)
541       return -1;
542 
543     keynote_used_variable = 0;
544     keynote_returnvalue = 0;
545     keynote_justrecord = record; /* Just want the list of keys in predicate */
546     keynote_init_list = as->as_env;
547 
548     keypred_state = kn_scan_bytes(as->as_keypred_s,
549 				  as->as_keypred_e - as->as_keypred_s);
550     BEGIN(KEYPREDICATE);
551     first_tok = KEYPRE;
552 
553     err = knparse();
554     if (err != 0)
555       if (keynote_errno == 0)
556 	keynote_errno = ERROR_SYNTAX;
557 
558     kn_delete_buffer(keypred_state);
559     keynote_lex_zap();
560     keynote_cleanup_kth();
561 
562     keynote_init_list = (struct environment *) NULL;
563     keynote_justrecord = 0;
564     p = keynote_returnvalue;
565     keynote_returnvalue = 0;
566 
567     if (record)
568     {
569 	if (keynote_errno != 0)
570 	{
571 	    keynote_keylist_free(keynote_keypred_keylist);
572 	    keynote_keypred_keylist = (struct keylist *) NULL;
573 	    return -1;
574 	}
575 	else
576 	{
577 	    /* Mark for re-processing if/when environment changes */
578 	    if (keynote_used_variable)
579 	    {
580 		keynote_used_variable = 0;
581 		as->as_internalflags |= ASSERT_IFLAG_WEIRDLICS;
582 	    }
583 
584 	    as->as_keylist = keynote_keypred_keylist;
585 	    keynote_keypred_keylist = (struct keylist *) NULL;
586 	    return RESULT_TRUE;
587 	}
588     }
589     else
590       return p;
591 }
592 
593 /* Evaluate an authorizer or signature field. Return RESULT_TRUE on success.
594  * Store key in as->as_authorizer. Second argument is set only for Authorizer
595  * field parsing.
596  */
597 int
598 keynote_evaluate_authorizer(struct assertion *as, int flag)
599 {
600     YY_BUFFER_STATE authorizer_state;
601     int err;
602 
603     if (keynote_lex_init() != RESULT_TRUE)
604       return -1;
605 
606     keynote_init_list = as->as_env;
607     keynote_justrecord = 1;
608     keynote_used_variable = 0;
609 
610     if ((flag) && (as->as_authorizer != (void *) NULL))
611     {
612 	keynote_free_key(as->as_authorizer, as->as_signeralgorithm);
613 	as->as_authorizer = (void *) NULL;
614     }
615 
616     if (flag)
617       authorizer_state = kn_scan_bytes(as->as_authorizer_string_s,
618 				       as->as_authorizer_string_e -
619 				       as->as_authorizer_string_s);
620     else
621       authorizer_state = kn_scan_bytes(as->as_signature_string_s,
622 				       as->as_signature_string_e -
623 				       as->as_signature_string_s);
624 
625     BEGIN(SIGNERINIT);
626     if (flag)
627       first_tok = SIGNERKEY;
628     else
629       first_tok = SIGNATUREENTRY;
630 
631     err = knparse();
632     if ((err != 0) && (keynote_errno == 0))
633       keynote_errno = ERROR_SYNTAX;
634 
635     kn_delete_buffer(authorizer_state);
636     keynote_lex_zap();
637 
638     keynote_justrecord = 0;
639     keynote_init_list = (struct environment *) NULL;
640     keynote_returnvalue = 0;
641 
642     if (keynote_keypred_keylist != (struct keylist *) NULL)
643     {
644 	if (flag)
645 	{
646 	    if (keynote_used_variable)
647 	      as->as_internalflags |= ASSERT_IFLAG_WEIRDAUTH;
648 
649 	    as->as_authorizer = keynote_keypred_keylist->key_key;
650 	    as->as_signeralgorithm = keynote_keypred_keylist->key_alg;
651 	}
652 	else
653 	{
654 	    if (keynote_used_variable)
655 	      as->as_internalflags |= ASSERT_IFLAG_WEIRDSIG;
656 
657 	    as->as_signature = keynote_keypred_keylist->key_key;
658 	}
659 
660 	keynote_keypred_keylist->key_key = (char *) NULL;
661 	keynote_keylist_free(keynote_keypred_keylist);
662 	keynote_keypred_keylist = (struct keylist *) NULL;
663     }
664 
665     keynote_used_variable = 0;
666 
667     if (keynote_errno != 0)
668       return -1;
669     else
670       return RESULT_TRUE;
671 }
672 
673 /*
674  * Parse a private key.
675  */
676 char *
677 keynote_get_private_key(char *buf)
678 {
679     YY_BUFFER_STATE pkey;
680     char *s;
681     int err;
682 
683     if (keynote_lex_init() != RESULT_TRUE)
684       return (char *) NULL;
685 
686     keynote_privkey = (char *) NULL;
687     pkey = kn_scan_bytes(buf, strlen(buf));
688     first_tok = PRIVATEKEY;
689     err = knparse();
690     kn_delete_buffer(pkey);
691     keynote_lex_zap();
692 
693     if (err != 0)
694     {
695 	if (keynote_privkey != (char *) NULL)
696 	{
697 	    free(keynote_privkey);
698 	    keynote_privkey = (char *) NULL;
699 	}
700 
701 	if (keynote_errno == 0)
702 	  keynote_errno = ERROR_SYNTAX;
703 
704 	return (char *) NULL;
705     }
706 
707     s = keynote_privkey;
708     keynote_privkey = (char *) NULL;
709     return s;
710 }
711 
712 /*
713  * Parse Local-Constants and KeyNote-Version fields.
714  */
715 struct environment *
716 keynote_get_envlist(char *buf, char *bufend, int whichfield)
717 {
718     struct environment *en = (struct environment *) NULL;
719     YY_BUFFER_STATE localinit_state;
720     int err;
721 
722     if (keynote_lex_init() != RESULT_TRUE)
723       return (struct environment *) NULL;
724 
725     localinit_state = kn_scan_bytes(buf, bufend - buf);
726     if (whichfield == 0)
727     {
728 	BEGIN(LOCALINIT);	/* We're doing Local-Constants parsing */
729 	first_tok = LOCINI;
730     }
731     else
732     {
733 	BEGIN(KEYNOTEVERSION);	/* KeyNote-Version parsing */
734       	first_tok = KNVERSION;
735     }
736 
737     err = knparse();
738     if (err != 0)
739       if (keynote_errno == 0)
740 	keynote_errno = ERROR_SYNTAX;
741 
742     kn_delete_buffer(localinit_state);
743     keynote_lex_zap();
744 
745     if (!whichfield)
746     {
747 	if (keynote_errno != 0)
748 	  keynote_env_cleanup(&keynote_init_list, 1);
749 	else
750 	  en = keynote_init_list;
751 
752     	keynote_init_list = (struct environment *) NULL;
753     }
754 
755     /* Avoid compiler (-Wall) warnings. Never reached. */
756     if (0)
757     {
758 	yyunput(0, NULL);
759 	yy_flex_realloc(0, NULL);
760     }
761 
762     return en;
763 }
764