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