veriexecctl_parse.y revision 1.14
1%{
2/*	$NetBSD: veriexecctl_parse.y,v 1.14 2006/07/14 18:41:40 elad Exp $	*/
3
4/*-
5 * Copyright 2005 Elad Efrat <elad@bsd.org.il>
6 * Copyright 2005 Brett Lymn <blymn@netbsd.org>
7 *
8 * All rights reserved.
9 *
10 * This code has been donated to The NetBSD Foundation by the Author.
11 *
12 * Redistribution and use in source and binary forms, with or without
13 * modification, are permitted provided that the following conditions
14 * are met:
15 * 1. Redistributions of source code must retain the above copyright
16 *    notice, this list of conditions and the following disclaimer.
17 * 2. The name of the author may not be used to endorse or promote products
18 *    derived from this software withough specific prior written permission
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
21 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
22 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
23 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
24 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
25 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
29 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 *
31 *
32 */
33
34#include <sys/param.h>
35#include <sys/ioctl.h>
36#include <sys/statvfs.h>
37#include <sys/mount.h>
38
39#include <sys/verified_exec.h>
40#include <ctype.h>
41#include <stdio.h>
42#include <string.h>
43#include <errno.h>
44#include <err.h>
45
46#include "veriexecctl.h"
47
48struct veriexec_params params;
49static int convert(u_char *, u_char *);
50
51%}
52
53%union {
54	char *string;
55	int intval;
56}
57
58%token <string> PATH
59%token <string> STRING
60%token EOL TOKEN_COMMA
61
62%%
63
64statement	:	/* empty */
65		|	statement path type fingerprint flags eol {
66	struct stat sb;
67	struct veriexec_up *p;
68
69	if (phase == 2) {
70		phase2_load();
71		goto phase_2_end;
72	}
73
74#if 1
75	if (stat(params.file, &sb) == -1) {
76		warnx("Line %lu: Can't stat `%s'",
77		    (unsigned long)line, params.file);
78		goto phase_2_end;
79	}
80
81	/* Only regular files */
82	if (!S_ISREG(sb.st_mode)) {
83		warnx("Line %lu: %s is not a regular file",
84		    (unsigned long)line, params.file);
85		goto phase_2_end;
86	}
87#endif
88
89	/* if ((p = dev_lookup(sb.st_dev)) != NULL) { */
90	if ((p = dev_lookup(params.file)) != NULL) {
91	    (p->vu_param.hash_size)++;
92	    goto phase_2_end;
93	}
94
95	if (verbose) {
96		struct statvfs sf;
97		if (statvfs(params.file, &sf) == -1)
98			err(1, "Cannot statvfs `%s'", params.file);
99
100		(void)printf( " => Adding device ID %d. (%s)\n",
101		    sb.st_dev, sf.f_mntonname);
102	}
103	dev_add(sb.st_dev, params.file);
104phase_2_end:
105	(void)memset(&params, 0, sizeof(params));
106}
107		|	statement eol
108		|	statement error eol {
109	yyerrok;
110}
111		;
112
113path		:	PATH {
114	(void)strlcpy(params.file, $1, MAXPATHLEN);
115}
116		;
117
118type		:	STRING {
119	if (phase == 2) {
120		if (strlen($1) >= sizeof(params.fp_type)) {
121			yyerror("Fingerprint type too long");
122			YYERROR;
123		}
124
125		(void)strlcpy(params.fp_type, $1, sizeof(params.fp_type));
126	}
127}
128		;
129
130
131fingerprint	:	STRING {
132	if (phase == 2) {
133		params.fingerprint = malloc(strlen($1) / 2);
134		if (params.fingerprint == NULL)
135			err(1, "Fingerprint mem alloc failed");
136
137		if ((params.size = convert($1, params.fingerprint)) == -1) {
138			free(params.fingerprint);
139			yyerror("Bad fingerprint");
140			YYERROR;
141		}
142	}
143
144}
145	    ;
146
147flags		:	/* empty */
148		|	flags_spec
149		;
150
151flags_spec	:	flag_spec
152		|	flags_spec TOKEN_COMMA flag_spec
153		;
154
155flag_spec	:	STRING {
156	if (phase == 2) {
157		if (strcasecmp($1, "direct") == 0) {
158			params.type |= VERIEXEC_DIRECT;
159		} else if (strcasecmp($1, "indirect") == 0) {
160			params.type |= VERIEXEC_INDIRECT;
161		} else if (strcasecmp($1, "file") == 0) {
162			params.type |= VERIEXEC_FILE;
163		} else if (strcasecmp($1, "program") == 0) {
164			params.type |= VERIEXEC_DIRECT;
165		} else if (strcasecmp($1, "interpreter") == 0) {
166			params.type |= VERIEXEC_INDIRECT;
167		} else if (strcasecmp($1, "script") == 0) {
168			params.type |= (VERIEXEC_FILE | VERIEXEC_DIRECT);
169		} else if (strcasecmp($1, "library") == 0) {
170			params.type |= VERIEXEC_FILE;
171		} else if (strcasecmp($1, "untrusted") == 0) {
172			params.type |= VERIEXEC_UNTRUSTED;
173		} else {
174			yyerror("Bad flag");
175			YYERROR;
176		}
177	}
178
179}
180		;
181
182eol		:	EOL
183		;
184
185%%
186
187/*
188 * Takes the hexadecimal string pointed to by "fp" and converts it to a
189 * "count" byte binary number which is stored in the array pointed to
190 * by "out".  Returns the number of bytes converted or -1 if the conversion
191 * fails.
192 */
193static int
194convert(u_char *fp, u_char *out)
195{
196	size_t i, count;
197	u_char value;
198
199	count = strlen(fp);
200
201	/*
202	 * if there are not an even number of hex digits then there is
203	 * not an integral number of bytes in the fingerprint.
204	 */
205	if ((count % 2) != 0)
206		return -1;
207
208	count /= 2;
209
210#define cvt(cv) \
211	if (isdigit(cv)) \
212		value += (cv) - '0'; \
213	else if (isxdigit(cv)) \
214		value += 10 + tolower(cv) - 'a'; \
215	else \
216		return -1
217
218	for (i = 0; i < count; i++) {
219		value = 0;
220		cvt(fp[2 * i]);
221		value <<= 4;
222		cvt(fp[2 * i + 1]);
223		out[i] = value;
224	}
225
226	return count;
227}
228