veriexecctl_parse.y revision 1.20
11.1Sblymn%{
21.20Selad/*	$NetBSD: veriexecctl_parse.y,v 1.20 2006/12/08 23:22:19 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.19Selad#include <prop/proplib.h>
471.19Selad
481.5Sblymn#include "veriexecctl.h"
491.1Sblymn
501.19Seladprop_dictionary_t load_params;
511.19Seladstatic size_t convert(u_char *, u_char *);
521.1Sblymn
531.1Sblymn%}
541.1Sblymn
551.1Sblymn%union {
561.5Sblymn	char *string;
571.5Sblymn	int intval;
581.1Sblymn}
591.1Sblymn
601.1Sblymn%token <string> PATH
611.1Sblymn%token <string> STRING
621.10Selad%token EOL TOKEN_COMMA
631.1Sblymn
641.1Sblymn%%
651.1Sblymn
661.5Sblymnstatement	:	/* empty */
671.5Sblymn		|	statement path type fingerprint flags eol {
681.7Schristos	struct stat sb;
691.8Selad	struct veriexec_up *p;
701.16Selad	struct statvfs sf;
711.5Sblymn
721.7Schristos	if (phase == 2) {
731.7Schristos		phase2_load();
741.7Schristos		goto phase_2_end;
751.7Schristos	}
761.7Schristos
771.19Selad	if (stat(dict_gets(load_params, "file"), &sb) == -1) {
781.7Schristos		warnx("Line %lu: Can't stat `%s'",
791.19Selad		    (unsigned long)line, dict_gets(load_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.19Selad		    (unsigned long)line, dict_gets(load_params, "file"));
871.7Schristos		goto phase_2_end;
881.7Schristos	}
891.7Schristos
901.19Selad	if (statvfs(dict_gets(load_params, "file"), &sf) == -1)
911.19Selad		err(1, "Cannot statvfs `%s'", dict_gets(load_params, "file"));
921.16Selad
931.16Selad	if ((p = dev_lookup(sf.f_mntonname)) != NULL) {
941.19Selad		uint64_t n;
951.19Selad
961.19Selad		prop_dictionary_get_uint64(p->vu_preload, "count", &n);
971.19Selad		n++;
981.19Selad		prop_dictionary_set_uint64(p->vu_preload, "count", n);
991.19Selad
1001.19Selad		goto phase_2_end;
1011.7Schristos	}
1021.7Schristos
1031.7Schristos	if (verbose) {
1041.16Selad		(void)printf( " => Adding mount `%s'.\n", sf.f_mntonname);
1051.16Selad	}
1061.16Selad
1071.16Selad	dev_add(sf.f_mntonname);
1081.5Sblymn
1091.5Sblymnphase_2_end:
1101.19Selad	load_params = NULL;
1111.7Schristos}
1121.5Sblymn		|	statement eol
1131.5Sblymn		|	statement error eol {
1141.7Schristos	yyerrok;
1151.7Schristos}
1161.5Sblymn		;
1171.5Sblymn
1181.5Sblymnpath		:	PATH {
1191.19Selad	if (load_params == NULL)
1201.19Selad		load_params = prop_dictionary_create();
1211.19Selad
1221.19Selad	dict_sets(load_params, "file", $1);
1231.7Schristos}
1241.5Sblymn		;
1251.5Sblymn
1261.5Sblymntype		:	STRING {
1271.10Selad	if (phase == 2) {
1281.19Selad		dict_sets(load_params, "fp-type", $1);
1291.7Schristos	}
1301.7Schristos}
1311.5Sblymn		;
1321.1Sblymn
1331.1Sblymn
1341.5Sblymnfingerprint	:	STRING {
1351.10Selad	if (phase == 2) {
1361.19Selad		char *fp;
1371.19Selad		size_t n;
1381.19Selad
1391.19Selad		fp = malloc(strlen($1) / 2);
1401.19Selad		if (fp == NULL)
1411.7Schristos			err(1, "Fingerprint mem alloc failed");
1421.19Selad
1431.19Selad		n = convert($1, fp);
1441.19Selad		if (n == -1) {
1451.19Selad			free(fp);
1461.7Schristos			yyerror("Bad fingerprint");
1471.7Schristos			YYERROR;
1481.7Schristos		}
1491.19Selad
1501.19Selad		dict_setd(load_params, "fp", fp, n);
1511.19Selad		free(fp);
1521.7Schristos	}
1531.5Sblymn
1541.7Schristos}
1551.7Schristos	    ;
1561.1Sblymn
1571.13Seladflags		:	/* empty */
1581.10Selad		|	flags_spec
1591.10Selad		;
1601.10Selad
1611.10Seladflags_spec	:	flag_spec
1621.10Selad		|	flags_spec TOKEN_COMMA flag_spec
1631.5Sblymn		;
1641.1Sblymn
1651.5Sblymnflag_spec	:	STRING {
1661.10Selad	if (phase == 2) {
1671.19Selad		uint8_t t = 0;
1681.19Selad
1691.20Selad		prop_dictionary_get_uint8(load_params, "entry-type", &t);
1701.20Selad
1711.10Selad		if (strcasecmp($1, "direct") == 0) {
1721.19Selad			t |= VERIEXEC_DIRECT;
1731.10Selad		} else if (strcasecmp($1, "indirect") == 0) {
1741.19Selad			t |= VERIEXEC_INDIRECT;
1751.10Selad		} else if (strcasecmp($1, "file") == 0) {
1761.19Selad			t |= VERIEXEC_FILE;
1771.12Sblymn		} else if (strcasecmp($1, "program") == 0) {
1781.19Selad			t |= VERIEXEC_DIRECT;
1791.12Sblymn		} else if (strcasecmp($1, "interpreter") == 0) {
1801.19Selad			t |= VERIEXEC_INDIRECT;
1811.12Sblymn		} else if (strcasecmp($1, "script") == 0) {
1821.19Selad			t |= (VERIEXEC_FILE | VERIEXEC_DIRECT);
1831.12Sblymn		} else if (strcasecmp($1, "library") == 0) {
1841.19Selad			t |= (VERIEXEC_FILE | VERIEXEC_INDIRECT);
1851.13Selad		} else if (strcasecmp($1, "untrusted") == 0) {
1861.19Selad			t |= VERIEXEC_UNTRUSTED;
1871.10Selad		} else {
1881.10Selad			yyerror("Bad flag");
1891.7Schristos			YYERROR;
1901.7Schristos		}
1911.19Selad
1921.19Selad		prop_dictionary_set_uint8(load_params, "entry-type", t);
1931.7Schristos	}
1941.1Sblymn
1951.7Schristos}
1961.5Sblymn		;
1971.1Sblymn
1981.5Sblymneol		:	EOL
1991.5Sblymn		;
2001.1Sblymn
2011.1Sblymn%%
2021.1Sblymn
2031.1Sblymn/*
2041.5Sblymn * Takes the hexadecimal string pointed to by "fp" and converts it to a
2051.5Sblymn * "count" byte binary number which is stored in the array pointed to
2061.5Sblymn * by "out".  Returns the number of bytes converted or -1 if the conversion
2071.5Sblymn * fails.
2081.1Sblymn */
2091.19Seladstatic size_t
2101.7Schristosconvert(u_char *fp, u_char *out)
2111.7Schristos{
2121.7Schristos	size_t i, count;
2131.7Schristos	u_char value;
2141.5Sblymn
2151.5Sblymn	count = strlen(fp);
2161.5Sblymn
2171.7Schristos	/*
2181.7Schristos	 * if there are not an even number of hex digits then there is
2191.7Schristos	 * not an integral number of bytes in the fingerprint.
2201.7Schristos	 */
2211.5Sblymn	if ((count % 2) != 0)
2221.5Sblymn		return -1;
2231.5Sblymn
2241.5Sblymn	count /= 2;
2251.7Schristos
2261.7Schristos#define cvt(cv) \
2271.7Schristos	if (isdigit(cv)) \
2281.7Schristos		value += (cv) - '0'; \
2291.7Schristos	else if (isxdigit(cv)) \
2301.7Schristos		value += 10 + tolower(cv) - 'a'; \
2311.7Schristos	else \
2321.7Schristos		return -1
2331.5Sblymn
2341.5Sblymn	for (i = 0; i < count; i++) {
2351.7Schristos		value = 0;
2361.7Schristos		cvt(fp[2 * i]);
2371.7Schristos		value <<= 4;
2381.7Schristos		cvt(fp[2 * i + 1]);
2391.5Sblymn		out[i] = value;
2401.5Sblymn	}
2411.1Sblymn
2421.7Schristos	return count;
2431.1Sblymn}
244