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