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