veriexecctl_parse.y revision 1.18
11.1Sblymn%{
21.18Selad/*	$NetBSD: veriexecctl_parse.y,v 1.18 2006/11/21 00:22:04 elad Exp $	*/
31.5Sblymn
41.5Sblymn/*-
51.18Selad * Copyright 2005 Elad Efrat <elad@NetBSD.org>
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.1Sblymn%}
521.1Sblymn
531.1Sblymn%union {
541.5Sblymn	char *string;
551.5Sblymn	int intval;
561.1Sblymn}
571.1Sblymn
581.1Sblymn%token <string> PATH
591.1Sblymn%token <string> STRING
601.10Selad%token EOL TOKEN_COMMA
611.1Sblymn
621.1Sblymn%%
631.1Sblymn
641.5Sblymnstatement	:	/* empty */
651.5Sblymn		|	statement path type fingerprint flags eol {
661.7Schristos	struct stat sb;
671.8Selad	struct veriexec_up *p;
681.16Selad	struct statvfs sf;
691.5Sblymn
701.7Schristos	if (phase == 2) {
711.7Schristos		phase2_load();
721.7Schristos		goto phase_2_end;
731.7Schristos	}
741.7Schristos
751.7Schristos	if (stat(params.file, &sb) == -1) {
761.7Schristos		warnx("Line %lu: Can't stat `%s'",
771.7Schristos		    (unsigned long)line, params.file);
781.7Schristos		goto phase_2_end;
791.7Schristos	}
801.7Schristos
811.7Schristos	/* Only regular files */
821.7Schristos	if (!S_ISREG(sb.st_mode)) {
831.7Schristos		warnx("Line %lu: %s is not a regular file",
841.7Schristos		    (unsigned long)line, params.file);
851.7Schristos		goto phase_2_end;
861.7Schristos	}
871.7Schristos
881.16Selad	if (statvfs(params.file, &sf) == -1)
891.16Selad		err(1, "Cannot statvfs `%s'", params.file);
901.16Selad
911.16Selad	if ((p = dev_lookup(sf.f_mntonname)) != NULL) {
921.7Schristos	    (p->vu_param.hash_size)++;
931.7Schristos	    goto phase_2_end;
941.7Schristos	}
951.7Schristos
961.7Schristos	if (verbose) {
971.16Selad		(void)printf( " => Adding mount `%s'.\n", sf.f_mntonname);
981.16Selad	}
991.16Selad
1001.16Selad	dev_add(sf.f_mntonname);
1011.5Sblymn
1021.5Sblymnphase_2_end:
1031.7Schristos	(void)memset(&params, 0, sizeof(params));
1041.7Schristos}
1051.5Sblymn		|	statement eol
1061.5Sblymn		|	statement error eol {
1071.7Schristos	yyerrok;
1081.7Schristos}
1091.5Sblymn		;
1101.5Sblymn
1111.5Sblymnpath		:	PATH {
1121.7Schristos	(void)strlcpy(params.file, $1, MAXPATHLEN);
1131.7Schristos}
1141.5Sblymn		;
1151.5Sblymn
1161.5Sblymntype		:	STRING {
1171.10Selad	if (phase == 2) {
1181.7Schristos		if (strlen($1) >= sizeof(params.fp_type)) {
1191.7Schristos			yyerror("Fingerprint type too long");
1201.7Schristos			YYERROR;
1211.7Schristos		}
1221.7Schristos
1231.7Schristos		(void)strlcpy(params.fp_type, $1, sizeof(params.fp_type));
1241.7Schristos	}
1251.7Schristos}
1261.5Sblymn		;
1271.1Sblymn
1281.1Sblymn
1291.5Sblymnfingerprint	:	STRING {
1301.10Selad	if (phase == 2) {
1311.7Schristos		params.fingerprint = malloc(strlen($1) / 2);
1321.7Schristos		if (params.fingerprint == NULL)
1331.7Schristos			err(1, "Fingerprint mem alloc failed");
1341.5Sblymn
1351.7Schristos		if ((params.size = convert($1, params.fingerprint)) == -1) {
1361.7Schristos			free(params.fingerprint);
1371.7Schristos			yyerror("Bad fingerprint");
1381.7Schristos			YYERROR;
1391.7Schristos		}
1401.7Schristos	}
1411.5Sblymn
1421.7Schristos}
1431.7Schristos	    ;
1441.1Sblymn
1451.13Seladflags		:	/* empty */
1461.10Selad		|	flags_spec
1471.10Selad		;
1481.10Selad
1491.10Seladflags_spec	:	flag_spec
1501.10Selad		|	flags_spec TOKEN_COMMA flag_spec
1511.5Sblymn		;
1521.1Sblymn
1531.5Sblymnflag_spec	:	STRING {
1541.10Selad	if (phase == 2) {
1551.10Selad		if (strcasecmp($1, "direct") == 0) {
1561.11Selad			params.type |= VERIEXEC_DIRECT;
1571.10Selad		} else if (strcasecmp($1, "indirect") == 0) {
1581.11Selad			params.type |= VERIEXEC_INDIRECT;
1591.10Selad		} else if (strcasecmp($1, "file") == 0) {
1601.11Selad			params.type |= VERIEXEC_FILE;
1611.12Sblymn		} else if (strcasecmp($1, "program") == 0) {
1621.12Sblymn			params.type |= VERIEXEC_DIRECT;
1631.12Sblymn		} else if (strcasecmp($1, "interpreter") == 0) {
1641.12Sblymn			params.type |= VERIEXEC_INDIRECT;
1651.12Sblymn		} else if (strcasecmp($1, "script") == 0) {
1661.12Sblymn			params.type |= (VERIEXEC_FILE | VERIEXEC_DIRECT);
1671.12Sblymn		} else if (strcasecmp($1, "library") == 0) {
1681.17Selad			params.type |= (VERIEXEC_FILE | VERIEXEC_INDIRECT);
1691.13Selad		} else if (strcasecmp($1, "untrusted") == 0) {
1701.13Selad			params.type |= VERIEXEC_UNTRUSTED;
1711.10Selad		} else {
1721.10Selad			yyerror("Bad flag");
1731.7Schristos			YYERROR;
1741.7Schristos		}
1751.7Schristos	}
1761.1Sblymn
1771.7Schristos}
1781.5Sblymn		;
1791.1Sblymn
1801.5Sblymneol		:	EOL
1811.5Sblymn		;
1821.1Sblymn
1831.1Sblymn%%
1841.1Sblymn
1851.1Sblymn/*
1861.5Sblymn * Takes the hexadecimal string pointed to by "fp" and converts it to a
1871.5Sblymn * "count" byte binary number which is stored in the array pointed to
1881.5Sblymn * by "out".  Returns the number of bytes converted or -1 if the conversion
1891.5Sblymn * fails.
1901.1Sblymn */
1911.7Schristosstatic int
1921.7Schristosconvert(u_char *fp, u_char *out)
1931.7Schristos{
1941.7Schristos	size_t i, count;
1951.7Schristos	u_char value;
1961.5Sblymn
1971.5Sblymn	count = strlen(fp);
1981.5Sblymn
1991.7Schristos	/*
2001.7Schristos	 * if there are not an even number of hex digits then there is
2011.7Schristos	 * not an integral number of bytes in the fingerprint.
2021.7Schristos	 */
2031.5Sblymn	if ((count % 2) != 0)
2041.5Sblymn		return -1;
2051.5Sblymn
2061.5Sblymn	count /= 2;
2071.7Schristos
2081.7Schristos#define cvt(cv) \
2091.7Schristos	if (isdigit(cv)) \
2101.7Schristos		value += (cv) - '0'; \
2111.7Schristos	else if (isxdigit(cv)) \
2121.7Schristos		value += 10 + tolower(cv) - 'a'; \
2131.7Schristos	else \
2141.7Schristos		return -1
2151.5Sblymn
2161.5Sblymn	for (i = 0; i < count; i++) {
2171.7Schristos		value = 0;
2181.7Schristos		cvt(fp[2 * i]);
2191.7Schristos		value <<= 4;
2201.7Schristos		cvt(fp[2 * i + 1]);
2211.5Sblymn		out[i] = value;
2221.5Sblymn	}
2231.1Sblymn
2241.7Schristos	return count;
2251.1Sblymn}
226