veriexecctl_parse.y revision 1.10
11.1Sblymn%{
21.10Selad/*	$NetBSD: veriexecctl_parse.y,v 1.10 2005/06/13 15:18:44 elad Exp $	*/
31.5Sblymn
41.5Sblymn/*-
51.5Sblymn * Copyright 2005 Elad Efrat <elad@bsd.org.il>
61.5Sblymn * Copyright 2005 Brett Lymn <blymn@netbsd.org>
71.5Sblymn *
81.5Sblymn * All rights reserved.
91.5Sblymn *
101.5Sblymn * This code has been donated to The NetBSD Foundation by the Author.
111.5Sblymn *
121.5Sblymn * Redistribution and use in source and binary forms, with or without
131.5Sblymn * modification, are permitted provided that the following conditions
141.5Sblymn * are met:
151.5Sblymn * 1. Redistributions of source code must retain the above copyright
161.5Sblymn *    notice, this list of conditions and the following disclaimer.
171.5Sblymn * 2. The name of the author may not be used to endorse or promote products
181.5Sblymn *    derived from this software withough specific prior written permission
191.5Sblymn *
201.5Sblymn * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
211.5Sblymn * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
221.5Sblymn * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
231.5Sblymn * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
241.5Sblymn * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
251.5Sblymn * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
261.5Sblymn * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
271.5Sblymn * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
281.5Sblymn * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
291.5Sblymn * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
301.1Sblymn *
311.1Sblymn *
321.1Sblymn */
331.1Sblymn
341.5Sblymn#include <sys/param.h>
351.5Sblymn#include <sys/ioctl.h>
361.5Sblymn#include <sys/statvfs.h>
371.5Sblymn#include <sys/mount.h>
381.5Sblymn
391.5Sblymn#include <sys/verified_exec.h>
401.5Sblymn#include <ctype.h>
411.1Sblymn#include <stdio.h>
421.1Sblymn#include <string.h>
431.1Sblymn#include <errno.h>
441.5Sblymn#include <err.h>
451.5Sblymn
461.5Sblymn#include "veriexecctl.h"
471.1Sblymn
481.5Sblymnstruct veriexec_params params;
491.7Schristosstatic int convert(u_char *, u_char *);
501.1Sblymn
511.10Seladint have_type = 0;
521.10Selad
531.10Selad#define	FIELD_TYPE	1
541.1Sblymn%}
551.1Sblymn
561.1Sblymn%union {
571.5Sblymn	char *string;
581.5Sblymn	int intval;
591.1Sblymn}
601.1Sblymn
611.1Sblymn%token <string> PATH
621.1Sblymn%token <string> STRING
631.10Selad%token EOL TOKEN_COMMA
641.1Sblymn
651.1Sblymn%%
661.1Sblymn
671.5Sblymnstatement	:	/* empty */
681.5Sblymn		|	statement path type fingerprint flags eol {
691.7Schristos	struct stat sb;
701.8Selad	struct veriexec_up *p;
711.5Sblymn
721.7Schristos	if (phase == 2) {
731.7Schristos		phase2_load();
741.7Schristos		goto phase_2_end;
751.7Schristos	}
761.7Schristos
771.7Schristos	if (stat(params.file, &sb) == -1) {
781.7Schristos		warnx("Line %lu: Can't stat `%s'",
791.7Schristos		    (unsigned long)line, params.file);
801.7Schristos		goto phase_2_end;
811.7Schristos	}
821.7Schristos
831.7Schristos	/* Only regular files */
841.7Schristos	if (!S_ISREG(sb.st_mode)) {
851.7Schristos		warnx("Line %lu: %s is not a regular file",
861.7Schristos		    (unsigned long)line, params.file);
871.7Schristos		goto phase_2_end;
881.7Schristos	}
891.7Schristos
901.9Selad	if ((p = dev_lookup(sb.st_dev)) != NULL) {
911.7Schristos	    (p->vu_param.hash_size)++;
921.7Schristos	    goto phase_2_end;
931.7Schristos	}
941.7Schristos
951.7Schristos	if (verbose) {
961.7Schristos		struct statvfs sf;
971.7Schristos		if (statvfs(params.file, &sf) == -1)
981.7Schristos			err(1, "Cannot statvfs `%s'", params.file);
991.5Sblymn
1001.7Schristos		(void)printf( " => Adding device ID %d. (%s)\n",
1011.7Schristos		    sb.st_dev, sf.f_mntonname);
1021.7Schristos	}
1031.7Schristos	dev_add(sb.st_dev);
1041.5Sblymnphase_2_end:
1051.7Schristos	(void)memset(&params, 0, sizeof(params));
1061.10Selad	have_type = 0;
1071.7Schristos}
1081.5Sblymn		|	statement eol
1091.5Sblymn		|	statement error eol {
1101.7Schristos	yyerrok;
1111.7Schristos}
1121.5Sblymn		;
1131.5Sblymn
1141.5Sblymnpath		:	PATH {
1151.7Schristos	(void)strlcpy(params.file, $1, MAXPATHLEN);
1161.7Schristos}
1171.5Sblymn		;
1181.5Sblymn
1191.5Sblymntype		:	STRING {
1201.10Selad	if (phase == 2) {
1211.7Schristos		if (strlen($1) >= sizeof(params.fp_type)) {
1221.7Schristos			yyerror("Fingerprint type too long");
1231.7Schristos			YYERROR;
1241.7Schristos		}
1251.7Schristos
1261.7Schristos		(void)strlcpy(params.fp_type, $1, sizeof(params.fp_type));
1271.7Schristos	}
1281.7Schristos}
1291.5Sblymn		;
1301.1Sblymn
1311.1Sblymn
1321.5Sblymnfingerprint	:	STRING {
1331.10Selad	if (phase == 2) {
1341.7Schristos		params.fingerprint = malloc(strlen($1) / 2);
1351.7Schristos		if (params.fingerprint == NULL)
1361.7Schristos			err(1, "Fingerprint mem alloc failed");
1371.5Sblymn
1381.7Schristos		if ((params.size = convert($1, params.fingerprint)) == -1) {
1391.7Schristos			free(params.fingerprint);
1401.7Schristos			yyerror("Bad fingerprint");
1411.7Schristos			YYERROR;
1421.7Schristos		}
1431.7Schristos	}
1441.5Sblymn
1451.7Schristos}
1461.7Schristos	    ;
1471.1Sblymn
1481.5Sblymnflags		:	/* empty */ {
1491.7Schristos	if (phase == 2)
1501.7Schristos		params.type = VERIEXEC_DIRECT;
1511.7Schristos}
1521.10Selad		|	flags_spec
1531.10Selad		;
1541.10Selad
1551.10Seladflags_spec	:	flag_spec
1561.10Selad		|	flags_spec TOKEN_COMMA flag_spec
1571.5Sblymn		;
1581.1Sblymn
1591.5Sblymnflag_spec	:	STRING {
1601.10Selad	if (phase == 2) {
1611.10Selad		int field;
1621.10Selad		int value;
1631.10Selad
1641.10Selad		/*
1651.10Selad		 * XXXEE: It might be a good idea to change this into
1661.10Selad		 * XXXEE: something less hard-coded. Perhaps loop on
1671.10Selad		 * XXXEE: tuples of (name, field, value)?
1681.10Selad		 */
1691.10Selad		if (strcasecmp($1, "direct") == 0) {
1701.10Selad			field = FIELD_TYPE;
1711.10Selad			value = VERIEXEC_DIRECT;
1721.10Selad		} else if (strcasecmp($1, "indirect") == 0) {
1731.10Selad			field = FIELD_TYPE;
1741.10Selad			value = VERIEXEC_INDIRECT;
1751.10Selad		} else if (strcasecmp($1, "file") == 0) {
1761.10Selad			field = FIELD_TYPE;
1771.10Selad			value = VERIEXEC_FILE;
1781.10Selad		} else {
1791.10Selad			yyerror("Bad flag");
1801.7Schristos			YYERROR;
1811.7Schristos		}
1821.10Selad
1831.10Selad		switch (field) {
1841.10Selad		case FIELD_TYPE:
1851.10Selad			if (have_type) {
1861.10Selad				yyerror("Mulitple type definitions");
1871.10Selad				YYERROR;
1881.10Selad			}
1891.10Selad
1901.10Selad			params.type = value;
1911.10Selad			have_type = 1;
1921.10Selad			break;
1931.10Selad		}
1941.7Schristos	}
1951.1Sblymn
1961.7Schristos}
1971.5Sblymn		;
1981.1Sblymn
1991.5Sblymneol		:	EOL
2001.5Sblymn		;
2011.1Sblymn
2021.1Sblymn%%
2031.1Sblymn
2041.1Sblymn/*
2051.5Sblymn * Takes the hexadecimal string pointed to by "fp" and converts it to a
2061.5Sblymn * "count" byte binary number which is stored in the array pointed to
2071.5Sblymn * by "out".  Returns the number of bytes converted or -1 if the conversion
2081.5Sblymn * fails.
2091.1Sblymn */
2101.7Schristosstatic int
2111.7Schristosconvert(u_char *fp, u_char *out)
2121.7Schristos{
2131.7Schristos	size_t i, count;
2141.7Schristos	u_char value;
2151.5Sblymn
2161.5Sblymn	count = strlen(fp);
2171.5Sblymn
2181.7Schristos	/*
2191.7Schristos	 * if there are not an even number of hex digits then there is
2201.7Schristos	 * not an integral number of bytes in the fingerprint.
2211.7Schristos	 */
2221.5Sblymn	if ((count % 2) != 0)
2231.5Sblymn		return -1;
2241.5Sblymn
2251.5Sblymn	count /= 2;
2261.7Schristos
2271.7Schristos#define cvt(cv) \
2281.7Schristos	if (isdigit(cv)) \
2291.7Schristos		value += (cv) - '0'; \
2301.7Schristos	else if (isxdigit(cv)) \
2311.7Schristos		value += 10 + tolower(cv) - 'a'; \
2321.7Schristos	else \
2331.7Schristos		return -1
2341.5Sblymn
2351.5Sblymn	for (i = 0; i < count; i++) {
2361.7Schristos		value = 0;
2371.7Schristos		cvt(fp[2 * i]);
2381.7Schristos		value <<= 4;
2391.7Schristos		cvt(fp[2 * i + 1]);
2401.5Sblymn		out[i] = value;
2411.5Sblymn	}
2421.1Sblymn
2431.7Schristos	return count;
2441.1Sblymn}
245