xref: /netbsd-src/sbin/veriexecctl/veriexecctl_parse.y (revision 4b896b232495b7a9b8b94a1cf1e21873296d53b8)
1 %{
2 /*
3  * Parser for verified exec fingerprint file.
4  *
5  * $NetBSD: veriexecctl_parse.y,v 1.3 2004/03/06 11:59:30 blymn Exp $
6  *
7  */
8 
9 #include <stdio.h>
10 #include <string.h>
11 #include <errno.h>
12 #include <sys/ioctl.h>
13 #include <sys/verified_exec.h>
14 
15 /* yacc internal function */
16 static int     yygrowstack __P((void));
17 int yylex __P((void));
18 void yyerror __P((const char *));
19 
20 /* function prototypes */
21 static int
22 convert(char *fp, unsigned int count, unsigned char *out);
23 
24 /* ioctl parameter struct */
25 static struct verified_exec_params params;
26 extern int fd;
27 extern int lineno;
28 
29 %}
30 
31 %union {
32   char *string;
33   int  intval;
34 }
35 
36 %token EOL
37 %token <string> PATH
38 %token <string> STRING
39 
40 %%
41 
42 statement: /* empty */
43   | statement path type fingerprint flags eol
44   | statement error eol {
45 				yyclearin; /* discard lookahead */
46 				yyerrok;   /* no more error */
47 				fprintf(stderr,
48 					"skipping to next fingerprint\n");
49 			}
50   ;
51 
52 path: PATH
53 {
54 	if (strlen($1) >= MAXPATHLEN) {
55 		yyerror("Path >= MAXPATHLEN");
56 		YYERROR;
57 	}
58 	strncpy(params.file, $1, MAXPATHLEN);
59 	params.type = VERIEXEC_DIRECT;
60 };
61 
62 type: STRING
63 {
64 	if (strcasecmp($1, "md5") == 0) {
65 		params.fp_type = FINGERPRINT_TYPE_MD5;
66 	} else if (strcasecmp($1, "sha1") == 0) {
67 		params.fp_type = FINGERPRINT_TYPE_SHA1;
68 	} else {
69 		fprintf(stderr, "%s %s at %d, %s\n",
70 			"veriexecctl: bad fingerprint type", $1, lineno,
71 			"assuming MD5");
72 		params.fp_type = FINGERPRINT_TYPE_MD5;
73 	}
74 };
75 
76 
77 fingerprint: STRING
78 {
79 	unsigned int count;
80 
81 	if (params.fp_type == FINGERPRINT_TYPE_SHA1)
82 		count = SHA1_FINGERPRINTLEN;
83 	else
84 		count = MD5_FINGERPRINTLEN;
85 
86 	if (convert($1, count, params.fingerprint) < 0) {
87 		fprintf(stderr,
88 			"veriexecctl: bad fingerprint at line %d\n",
89 			lineno);
90 	}
91 };
92 
93 flags: /* empty */
94 	| flag_spec flags;
95 
96 flag_spec: STRING
97 {
98 	params.type = VERIEXEC_DIRECT;
99 	if (strcasecmp($1, "indirect") == 0) {
100 		params.type = VERIEXEC_INDIRECT;
101 	} else if (strcasecmp($1, "file") == 0) {
102 		params.type = VERIEXEC_FILE;
103 	}
104 };
105 
106 eol: EOL
107 {
108 	if (!YYRECOVERING) /* Don't do the ioctl if we saw an error */
109 		do_ioctl();
110 };
111 
112 %%
113 
114 /*
115  * Convert: takes the hexadecimal string pointed to by fp and converts
116  * it to a "count" byte binary number which is stored in the array pointed to
117  * by out.  Returns -1 if the conversion fails.
118  */
119 static int
120 convert(char *fp, unsigned int count, unsigned char *out)
121 {
122         int i, value, error = 0;
123 
124         for (i = 0; i < count; i++) {
125                 if ((fp[2*i] >= '0') && (fp[2*i] <= '9')) {
126                         value = 16 * (fp[2*i] - '0');
127                 } else if ((fp[2*i] >= 'a') && (fp[2*i] <= 'f')) {
128                         value = 16 * (10 + fp[2*i] - 'a');
129                 } else {
130                         error = -1;
131                         break;
132                 }
133 
134                 if ((fp[2*i + 1] >= '0') && (fp[2*i + 1] <= '9')) {
135                         value += fp[2*i + 1] - '0';
136                 } else if ((fp[2*i + 1] >= 'a') && (fp[2*i + 1] <= 'f')) {
137                         value += fp[2*i + 1] - 'a' + 10;
138                 } else {
139                         error = -1;
140                         break;
141                 }
142 
143                 out[i] = value;
144         }
145 
146         return error;
147 }
148 
149 /*
150  * Perform the load of the fingerprint.  Assumes that the fingerprint
151  * pseudo-device is opened and the file handle is in fd.
152  */
153 static void
154 do_ioctl(void)
155 {
156 	if (ioctl(fd, VERIEXECLOAD, &params) < 0)
157 		fprintf(stderr,	"Ioctl failed with error `%s' on file %s\n",
158 			strerror(errno), params.file);
159 }
160