veriexecctl_parse.y revision 1.4
1%{
2/*
3 * Parser for verified exec fingerprint file.
4 *
5 * $NetBSD: veriexecctl_parse.y,v 1.4 2005/01/19 20:42:04 xtraeme 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 */
16static int     yygrowstack(void);
17int yylex(void);
18void yyerror(const char *);
19
20/* function prototypes */
21static int
22convert(char *fp, unsigned int count, unsigned char *out);
23
24/* ioctl parameter struct */
25static struct verified_exec_params params;
26extern int fd;
27extern 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
42statement: /* 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
52path: 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
62type: 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
77fingerprint: 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
93flags: /* empty */
94	| flag_spec flags;
95
96flag_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
106eol: 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 */
119static int
120convert(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 */
153static void
154do_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