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