veriexecctl_parse.y revision 1.9
1%{
2/*	$NetBSD: veriexecctl_parse.y,v 1.9 2005/05/27 15:46:23 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
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 != 1) {
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 != 1) {
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	if (phase == 2)
146		params.type = VERIEXEC_DIRECT;
147}
148		|	flags flag_spec
149		;
150
151flag_spec	:	STRING {
152	if (phase != 1) {
153		if (strcasecmp($1, "direct") == 0)
154			params.type = VERIEXEC_DIRECT;
155		else if (strcasecmp($1, "indirect") == 0)
156			params.type = VERIEXEC_INDIRECT;
157		else if (strcasecmp($1, "file") == 0)
158			params.type = VERIEXEC_FILE;
159		else {
160			yyerror("Bad option");
161			YYERROR;
162		}
163	}
164
165}
166		;
167
168eol		:	EOL
169		;
170
171%%
172
173/*
174 * Takes the hexadecimal string pointed to by "fp" and converts it to a
175 * "count" byte binary number which is stored in the array pointed to
176 * by "out".  Returns the number of bytes converted or -1 if the conversion
177 * fails.
178 */
179static int
180convert(u_char *fp, u_char *out)
181{
182	size_t i, count;
183	u_char value;
184
185	count = strlen(fp);
186
187	/*
188	 * if there are not an even number of hex digits then there is
189	 * not an integral number of bytes in the fingerprint.
190	 */
191	if ((count % 2) != 0)
192		return -1;
193
194	count /= 2;
195
196#define cvt(cv) \
197	if (isdigit(cv)) \
198		value += (cv) - '0'; \
199	else if (isxdigit(cv)) \
200		value += 10 + tolower(cv) - 'a'; \
201	else \
202		return -1
203
204	for (i = 0; i < count; i++) {
205		value = 0;
206		cvt(fp[2 * i]);
207		value <<= 4;
208		cvt(fp[2 * i + 1]);
209		out[i] = value;
210	}
211
212	return count;
213}
214