veriexecctl_parse.y revision 1.13
1%{
2/*	$NetBSD: veriexecctl_parse.y,v 1.13 2005/10/05 13:48:48 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 (stat(params.file, &sb) == -1) {
75		warnx("Line %lu: Can't stat `%s'",
76		    (unsigned long)line, params.file);
77		goto phase_2_end;
78	}
79
80	/* Only regular files */
81	if (!S_ISREG(sb.st_mode)) {
82		warnx("Line %lu: %s is not a regular file",
83		    (unsigned long)line, params.file);
84		goto phase_2_end;
85	}
86
87	if ((p = dev_lookup(sb.st_dev)) != NULL) {
88	    (p->vu_param.hash_size)++;
89	    goto phase_2_end;
90	}
91
92	if (verbose) {
93		struct statvfs sf;
94		if (statvfs(params.file, &sf) == -1)
95			err(1, "Cannot statvfs `%s'", params.file);
96
97		(void)printf( " => Adding device ID %d. (%s)\n",
98		    sb.st_dev, sf.f_mntonname);
99	}
100	dev_add(sb.st_dev);
101phase_2_end:
102	(void)memset(&params, 0, sizeof(params));
103}
104		|	statement eol
105		|	statement error eol {
106	yyerrok;
107}
108		;
109
110path		:	PATH {
111	(void)strlcpy(params.file, $1, MAXPATHLEN);
112}
113		;
114
115type		:	STRING {
116	if (phase == 2) {
117		if (strlen($1) >= sizeof(params.fp_type)) {
118			yyerror("Fingerprint type too long");
119			YYERROR;
120		}
121
122		(void)strlcpy(params.fp_type, $1, sizeof(params.fp_type));
123	}
124}
125		;
126
127
128fingerprint	:	STRING {
129	if (phase == 2) {
130		params.fingerprint = malloc(strlen($1) / 2);
131		if (params.fingerprint == NULL)
132			err(1, "Fingerprint mem alloc failed");
133
134		if ((params.size = convert($1, params.fingerprint)) == -1) {
135			free(params.fingerprint);
136			yyerror("Bad fingerprint");
137			YYERROR;
138		}
139	}
140
141}
142	    ;
143
144flags		:	/* empty */
145		|	flags_spec
146		;
147
148flags_spec	:	flag_spec
149		|	flags_spec TOKEN_COMMA flag_spec
150		;
151
152flag_spec	:	STRING {
153	if (phase == 2) {
154		if (strcasecmp($1, "direct") == 0) {
155			params.type |= VERIEXEC_DIRECT;
156		} else if (strcasecmp($1, "indirect") == 0) {
157			params.type |= VERIEXEC_INDIRECT;
158		} else if (strcasecmp($1, "file") == 0) {
159			params.type |= VERIEXEC_FILE;
160		} else if (strcasecmp($1, "program") == 0) {
161			params.type |= VERIEXEC_DIRECT;
162		} else if (strcasecmp($1, "interpreter") == 0) {
163			params.type |= VERIEXEC_INDIRECT;
164		} else if (strcasecmp($1, "script") == 0) {
165			params.type |= (VERIEXEC_FILE | VERIEXEC_DIRECT);
166		} else if (strcasecmp($1, "library") == 0) {
167			params.type |= VERIEXEC_FILE;
168		} else if (strcasecmp($1, "untrusted") == 0) {
169			params.type |= VERIEXEC_UNTRUSTED;
170		} else {
171			yyerror("Bad flag");
172			YYERROR;
173		}
174	}
175
176}
177		;
178
179eol		:	EOL
180		;
181
182%%
183
184/*
185 * Takes the hexadecimal string pointed to by "fp" and converts it to a
186 * "count" byte binary number which is stored in the array pointed to
187 * by "out".  Returns the number of bytes converted or -1 if the conversion
188 * fails.
189 */
190static int
191convert(u_char *fp, u_char *out)
192{
193	size_t i, count;
194	u_char value;
195
196	count = strlen(fp);
197
198	/*
199	 * if there are not an even number of hex digits then there is
200	 * not an integral number of bytes in the fingerprint.
201	 */
202	if ((count % 2) != 0)
203		return -1;
204
205	count /= 2;
206
207#define cvt(cv) \
208	if (isdigit(cv)) \
209		value += (cv) - '0'; \
210	else if (isxdigit(cv)) \
211		value += 10 + tolower(cv) - 'a'; \
212	else \
213		return -1
214
215	for (i = 0; i < count; i++) {
216		value = 0;
217		cvt(fp[2 * i]);
218		value <<= 4;
219		cvt(fp[2 * i + 1]);
220		out[i] = value;
221	}
222
223	return count;
224}
225