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