xref: /openbsd/lib/libkeynote/keynote.l (revision fc61954a)
1 %{
2 /* $OpenBSD: keynote.l,v 1.23 2015/11/19 19:48:27 tedu 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 = 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 = NULL;
115 					    return VARIABLE;
116 					}
117 
118 					len = strlen(kntext) + 1;
119 					knlval.string = calloc(len, sizeof(char));
120                                         if (knlval.string == 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 = NULL;
146 				    return STRING;
147 				}
148 
149 				len = strlen(kntext) + 1;
150 				knlval.string = calloc(len, sizeof(char));
151                                 if (knlval.string == 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 = NULL;
171 				    return STRING;
172 				}
173 
174 				knlval.string = calloc(strlen(kntext) - 1,
175 						       sizeof(char));
176                                 if (knlval.string == 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 != 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 = 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 != NULL)
231       memset(keynote_lex_list, 0,
232 	     keynote_max_lex_list * sizeof(struct lex_list));
233     else
234     {
235 	keynote_lex_list = calloc(keynote_max_lex_list,
236 					              sizeof(struct lex_list));
237         if (keynote_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 == NULL)
258       return RESULT_TRUE;
259 
260     for (i = 0; i < keynote_max_lex_list; i++)
261       if (keynote_lex_list[i].lex_s == 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 *) reallocarray(keynote_lex_list,
273 					 keynote_max_lex_list,
274 					 sizeof(struct lex_list));
275     if (p == 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     keynote_lex_list = p;
290     keynote_lex_list[i].lex_s = s;
291     keynote_lex_list[i++].lex_type = type;
292     keynote_lex_counter++;
293 
294     /* Zero out the rest */
295     memset(&(keynote_lex_list[i]), 0,
296 	   (keynote_max_lex_list - i) * sizeof(struct lex_list));
297 
298     return RESULT_TRUE;
299 }
300 
301 /*
302  * Remove string.
303  */
304 void
305 keynote_lex_remove(void *s)
306 {
307     int i;
308 
309     for (i = 0; i < keynote_max_lex_list; i++)
310       if (keynote_lex_list[i].lex_s == s)
311       {
312 	  memset(&(keynote_lex_list[i]), 0, sizeof(struct lex_list));
313 	  keynote_lex_counter--;
314 	  return;
315       }
316 }
317 
318 /*
319  * Return RESULT_TRUE if character is octal digit, RESULT_FALSE otherwise.
320  */
321 static int
322 is_octal(char c)
323 {
324     switch (c)
325     {
326 	case '0': case '1': case '2': case '3':
327 	case '4': case '5': case '6': case '7':
328 	    return RESULT_TRUE;
329 
330 	default:
331 	    return RESULT_FALSE;
332     }
333 }
334 
335 /*
336  * Return octal value (non-zero) if argument starts with such a
337  * representation, otherwise 0.
338  */
339 static unsigned char
340 get_octal(char *s, int len, int *adv)
341 {
342     unsigned char res = 0;
343 
344     if (*s == '0')
345     {
346 	if (len > 0)
347 	{
348 	    if (is_octal(*(s + 1)))
349 	    {
350 		res = *(s + 1) - '0';
351 		*adv = 2;
352 
353 		if (is_octal(*(s + 2)) && (len - 1 > 0))
354 		{
355 		    res = res * 8 + (*(s + 2) - '0');
356 		    *adv = 3;
357 		}
358 	    }
359 	}
360     }
361     else
362       if (is_octal(*s) && (len - 1 > 0))  /* Non-zero leading */
363       {
364 	  if (is_octal(*(s + 1)) &&
365 	      is_octal(*(s + 2)))
366 	  {
367 	      *adv = 3;
368 	      res = (((*s) - '0') * 64) +
369 		    (((*(s + 1)) - '0') * 8) +
370 		    ((*(s + 2)) - '0');
371 	  }
372       }
373 
374     return res;
375 }
376 
377 /*
378  * Copy at most len characters to string s1 from string s2, taking
379  * care of escaped characters in the process. String s1 is assumed
380  * to have enough space, and be zero'ed.
381  */
382 static void
383 mystrncpy(char *s1, char *s2, int len)
384 {
385     unsigned char c;
386     int advance;
387 
388     if (len == 0)
389       return;
390 
391     while (len-- > 0)
392     {
393         if (*s2 == '\\')
394 	{
395 	    s2++;
396 
397 	    if (len-- <= 0)
398 	      break;
399 
400 	    if (*s2 == '\n')
401 	    {
402 		while (isspace((unsigned char)*(++s2)) && (len-- > 0))
403 		  ;
404 	    }
405 	    else
406 	      if ((c = get_octal(s2, len, &advance)) != 0)
407 	      {
408 		  len -= advance - 1;
409 		  s2 += advance;
410 		  *s1++ = c;
411 	      }
412 	      else
413 		if (*s2 == 'n')  /* Newline */
414 		{
415 		    *s1++ = '\n';
416 		    s2++;
417 		}
418 		else
419 		  if (*s2 == 't')  /* Tab */
420 		  {
421 		      *s1++ = '\t';
422 		      s2++;
423 		  }
424 		  else
425 		    if (*s2 == 'r')  /* Linefeed */
426 		    {
427 			*s1++ = '\r';
428 			s2++;
429 		    }
430 		    else
431 		      if (*s2 == 'f')  /* Formfeed */
432 		      {
433 			  *s1++ = '\f';
434 			  s2++;
435 		      }
436 		      else
437 			if ((*s1++ = *s2++) == 0)
438 			  break;
439 
440 	    continue;
441 	}
442 
443         if ((*s1++ = *s2++) == 0)
444 	  break;
445      }
446 }
447 
448 /*
449  * Evaluate an assertion, with as->as_result holding the result.
450  * Return RESULT_TRUE if all ok. Also return the result.
451  */
452 int
453 keynote_evaluate_assertion(struct assertion *as)
454 {
455     YY_BUFFER_STATE keynote_bs;
456 
457     /* Non-existent Conditions field means highest return value */
458     if (as->as_conditions_s == NULL)
459     {
460 	as->as_result = keynote_current_session->ks_values_num - 1;
461 	return RESULT_TRUE;
462     }
463 
464     if (keynote_lex_init() != RESULT_TRUE)
465       return -1;
466 
467     keynote_used_variable = 0;
468     keynote_init_list = as->as_env;     /* Setup the local-init var list */
469 
470     keynote_bs = kn_scan_bytes(as->as_conditions_s,
471 			       as->as_conditions_e - as->as_conditions_s);
472     BEGIN(ACTIONSTRING);	/* We're doing conditions-string parsing */
473     first_tok = ACTSTR;
474     as->as_result = 0;
475     keynote_returnvalue = 0;
476 
477     switch (knparse())
478     {
479 	case 1:  /* Fall through */
480 	    keynote_errno = ERROR_SYNTAX;
481 	case -1:
482 	    as->as_result = 0;
483 	    break;
484 
485 	case 0:
486 	    as->as_result = keynote_returnvalue;
487 	    break;
488     }
489 
490     keynote_env_cleanup(&keynote_temp_list, 1);
491     keynote_lex_zap();
492     kn_delete_buffer(keynote_bs);
493 
494     keynote_used_variable = 0;
495     keynote_returnvalue = 0;
496     keynote_temp_list = NULL;
497     keynote_init_list = NULL;
498 
499     if (keynote_errno != 0)
500       return -1;
501     else
502       return RESULT_TRUE;
503 }
504 
505 /*
506  * Parse/evaluate a key predicate field.
507  * Store keys in key predicate as keylist in as->as_keylist, if second
508  * argument is true.
509  */
510 int
511 keynote_parse_keypred(struct assertion *as, int record)
512 {
513     YY_BUFFER_STATE keypred_state;
514     int p = 0, err;
515 
516     if (as->as_keypred_s == NULL)
517       return keynote_current_session->ks_values_num - 1;
518 
519     if (keynote_lex_init() != RESULT_TRUE)
520       return -1;
521 
522     keynote_used_variable = 0;
523     keynote_returnvalue = 0;
524     keynote_justrecord = record; /* Just want the list of keys in predicate */
525     keynote_init_list = as->as_env;
526 
527     keypred_state = kn_scan_bytes(as->as_keypred_s,
528 				  as->as_keypred_e - as->as_keypred_s);
529     BEGIN(KEYPREDICATE);
530     first_tok = KEYPRE;
531 
532     err = knparse();
533     if (err != 0)
534       if (keynote_errno == 0)
535 	keynote_errno = ERROR_SYNTAX;
536 
537     kn_delete_buffer(keypred_state);
538     keynote_lex_zap();
539     keynote_cleanup_kth();
540 
541     keynote_init_list = NULL;
542     keynote_justrecord = 0;
543     p = keynote_returnvalue;
544     keynote_returnvalue = 0;
545 
546     if (record)
547     {
548 	if (keynote_errno != 0)
549 	{
550 	    keynote_keylist_free(keynote_keypred_keylist);
551 	    keynote_keypred_keylist = NULL;
552 	    return -1;
553 	}
554 	else
555 	{
556 	    /* Mark for re-processing if/when environment changes */
557 	    if (keynote_used_variable)
558 	    {
559 		keynote_used_variable = 0;
560 		as->as_internalflags |= ASSERT_IFLAG_WEIRDLICS;
561 	    }
562 
563 	    if (as->as_keylist)
564               keynote_keylist_free(as->as_keylist);
565 	    as->as_keylist = keynote_keypred_keylist;
566 	    keynote_keypred_keylist = NULL;
567 	    return RESULT_TRUE;
568 	}
569     }
570     else
571       return p;
572 }
573 
574 /* Evaluate an authorizer or signature field. Return RESULT_TRUE on success.
575  * Store key in as->as_authorizer. Second argument is set only for Authorizer
576  * field parsing.
577  */
578 int
579 keynote_evaluate_authorizer(struct assertion *as, int flag)
580 {
581     YY_BUFFER_STATE authorizer_state;
582     int err;
583 
584     if (keynote_lex_init() != RESULT_TRUE)
585       return -1;
586 
587     keynote_init_list = as->as_env;
588     keynote_justrecord = 1;
589     keynote_used_variable = 0;
590 
591     if ((flag) && (as->as_authorizer != NULL))
592     {
593 	keynote_free_key(as->as_authorizer, as->as_signeralgorithm);
594 	as->as_authorizer = NULL;
595     }
596 
597     if (flag)
598       authorizer_state = kn_scan_bytes(as->as_authorizer_string_s,
599 				       as->as_authorizer_string_e -
600 				       as->as_authorizer_string_s);
601     else
602       authorizer_state = kn_scan_bytes(as->as_signature_string_s,
603 				       as->as_signature_string_e -
604 				       as->as_signature_string_s);
605 
606     BEGIN(SIGNERINIT);
607     if (flag)
608       first_tok = SIGNERKEY;
609     else
610       first_tok = SIGNATUREENTRY;
611 
612     err = knparse();
613     if ((err != 0) && (keynote_errno == 0))
614       keynote_errno = ERROR_SYNTAX;
615 
616     kn_delete_buffer(authorizer_state);
617     keynote_lex_zap();
618 
619     keynote_justrecord = 0;
620     keynote_init_list = NULL;
621     keynote_returnvalue = 0;
622 
623     if (keynote_keypred_keylist != NULL)
624     {
625 	if (flag)
626 	{
627 	    if (keynote_used_variable)
628 	      as->as_internalflags |= ASSERT_IFLAG_WEIRDAUTH;
629 
630 	    as->as_authorizer = keynote_keypred_keylist->key_key;
631 	    as->as_signeralgorithm = keynote_keypred_keylist->key_alg;
632 	}
633 	else
634 	{
635 	    if (keynote_used_variable)
636 	      as->as_internalflags |= ASSERT_IFLAG_WEIRDSIG;
637 
638 	    as->as_signature = keynote_keypred_keylist->key_key;
639 	}
640 
641 	keynote_keypred_keylist->key_key = NULL;
642 	keynote_keylist_free(keynote_keypred_keylist);
643 	keynote_keypred_keylist = NULL;
644     }
645 
646     keynote_used_variable = 0;
647 
648     if (keynote_errno != 0)
649       return -1;
650     else
651       return RESULT_TRUE;
652 }
653 
654 /*
655  * Exportable front-end to keynote_get_private_key().
656  */
657 char *
658 kn_get_string(char *buf)
659 {
660     return keynote_get_private_key(buf);
661 }
662 
663 /*
664  * Parse a private key -- actually, it can deal with any kind of string.
665  */
666 char *
667 keynote_get_private_key(char *buf)
668 {
669     YY_BUFFER_STATE pkey;
670     char *s;
671     int err;
672 
673     if (keynote_lex_init() != RESULT_TRUE)
674       return NULL;
675 
676     keynote_privkey = NULL;
677     pkey = kn_scan_bytes(buf, strlen(buf));
678     first_tok = PRIVATEKEY;
679     err = knparse();
680     kn_delete_buffer(pkey);
681     keynote_lex_zap();
682 
683     if (err != 0)
684     {
685 	if (keynote_privkey != NULL)
686 	{
687 	    free(keynote_privkey);
688 	    keynote_privkey = NULL;
689 	}
690 
691 	if (keynote_errno == 0)
692 	  keynote_errno = ERROR_SYNTAX;
693 
694 	return NULL;
695     }
696 
697     s = keynote_privkey;
698     keynote_privkey = NULL;
699     return s;
700 }
701 
702 /*
703  * Parse Local-Constants and KeyNote-Version fields.
704  */
705 struct environment *
706 keynote_get_envlist(char *buf, char *bufend, int whichfield)
707 {
708     struct environment *en = NULL;
709     YY_BUFFER_STATE localinit_state;
710     int err;
711 
712     if (keynote_lex_init() != RESULT_TRUE)
713       return NULL;
714 
715     localinit_state = kn_scan_bytes(buf, bufend - buf);
716     if (whichfield == 0)
717     {
718 	BEGIN(LOCALINIT);	/* We're doing Local-Constants parsing */
719 	first_tok = LOCINI;
720     }
721     else
722     {
723 	BEGIN(KEYNOTEVERSION);	/* KeyNote-Version parsing */
724       	first_tok = KNVERSION;
725     }
726 
727     err = knparse();
728     if (err != 0)
729       if (keynote_errno == 0)
730 	keynote_errno = ERROR_SYNTAX;
731 
732     kn_delete_buffer(localinit_state);
733     keynote_lex_zap();
734 
735     if (!whichfield)
736     {
737 	if (keynote_errno != 0)
738 	  keynote_env_cleanup(&keynote_init_list, 1);
739 	else
740 	  en = keynote_init_list;
741 
742     	keynote_init_list = NULL;
743     }
744 
745     /* Avoid compiler (-Wall) warnings. Never reached. */
746     if (0)
747     {
748 	yyunput(0, NULL);
749     }
750 
751     return en;
752 }
753