veriexecctl_parse.y revision 1.21
11.1Sblymn%{
21.21Selad/*	$NetBSD: veriexecctl_parse.y,v 1.21 2007/05/15 19:47:47 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.21Selad#include <sys/stat.h>
351.21Selad#include <sys/verified_exec.h>
361.5Sblymn
371.5Sblymn#include <ctype.h>
381.1Sblymn#include <stdio.h>
391.1Sblymn#include <string.h>
401.5Sblymn#include <err.h>
411.5Sblymn
421.19Selad#include <prop/proplib.h>
431.19Selad
441.5Sblymn#include "veriexecctl.h"
451.1Sblymn
461.21Seladextern int yylex(void);
471.21Seladextern size_t line;
481.21Seladextern int verbose, error;
491.21Selad
501.21Seladboolean_t keep_filename = FALSE, eval_on_load = FALSE;
511.19Seladprop_dictionary_t load_params;
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.21Selad	extern int gfd;
691.7Schristos	struct stat sb;
701.7Schristos
711.19Selad	if (stat(dict_gets(load_params, "file"), &sb) == -1) {
721.21Selad		if (verbose)
731.21Selad			warnx("Line %zu: Can't stat `%s'", line,
741.21Selad			    dict_gets(load_params, "file"));
751.21Selad		error = EXIT_FAILURE;
761.21Selad		goto skip;
771.7Schristos	}
781.7Schristos
791.7Schristos	/* Only regular files */
801.7Schristos	if (!S_ISREG(sb.st_mode)) {
811.21Selad		if (verbose)
821.21Selad			warnx("Line %zu: %s is not a regular file", line,
831.21Selad			    dict_gets(load_params, "file"));
841.21Selad		error = EXIT_FAILURE;
851.21Selad		goto skip;
861.7Schristos	}
871.7Schristos
881.21Selad	if (verbose) {
891.21Selad		(void)printf( "Adding file `%s'.\n",
901.21Selad		    dict_gets(load_params, "file"));
911.21Selad	}
921.16Selad
931.21Selad	prop_dictionary_set(load_params, "keep-filename",
941.21Selad	    prop_bool_create(keep_filename));
951.19Selad
961.21Selad	prop_dictionary_set(load_params, "eval-on-load",
971.21Selad	    prop_bool_create(eval_on_load));
981.19Selad
991.21Selad	if (prop_dictionary_send_ioctl(load_params, gfd, VERIEXEC_LOAD) != 0) {
1001.21Selad		if (verbose)
1011.21Selad			warn("Cannot load params from `%s'",
1021.21Selad			    dict_gets(load_params, "file"));
1031.21Selad		error = EXIT_FAILURE;
1041.16Selad	}
1051.16Selad
1061.21Selad skip:
1071.21Selad	prop_object_release(load_params);
1081.19Selad	load_params = NULL;
1091.7Schristos}
1101.5Sblymn		|	statement eol
1111.5Sblymn		|	statement error eol {
1121.7Schristos	yyerrok;
1131.7Schristos}
1141.5Sblymn		;
1151.5Sblymn
1161.5Sblymnpath		:	PATH {
1171.19Selad	if (load_params == NULL)
1181.19Selad		load_params = prop_dictionary_create();
1191.19Selad
1201.19Selad	dict_sets(load_params, "file", $1);
1211.7Schristos}
1221.5Sblymn		;
1231.5Sblymn
1241.5Sblymntype		:	STRING {
1251.21Selad	dict_sets(load_params, "fp-type", $1);
1261.7Schristos}
1271.5Sblymn		;
1281.1Sblymn
1291.1Sblymn
1301.5Sblymnfingerprint	:	STRING {
1311.21Selad	char *fp;
1321.21Selad	size_t n;
1331.21Selad
1341.21Selad	fp = malloc(strlen($1) / 2);
1351.21Selad	if (fp == NULL)
1361.21Selad		err(1, "Cannot allocate memory for fingerprint");
1371.19Selad
1381.21Selad	n = convert($1, fp);
1391.21Selad	if (n == -1) {
1401.19Selad		free(fp);
1411.21Selad		if (verbose)
1421.21Selad			warnx("Bad fingerprint `%s' in line %zu", $1, line);
1431.21Selad		error = EXIT_FAILURE;
1441.21Selad		YYERROR;
1451.7Schristos	}
1461.21Selad
1471.21Selad	dict_setd(load_params, "fp", fp, n);
1481.21Selad	free(fp);
1491.7Schristos}
1501.7Schristos	    ;
1511.1Sblymn
1521.13Seladflags		:	/* empty */
1531.10Selad		|	flags_spec
1541.10Selad		;
1551.10Selad
1561.10Seladflags_spec	:	flag_spec
1571.10Selad		|	flags_spec TOKEN_COMMA flag_spec
1581.5Sblymn		;
1591.1Sblymn
1601.5Sblymnflag_spec	:	STRING {
1611.21Selad	uint8_t t = 0;
1621.20Selad
1631.21Selad	prop_dictionary_get_uint8(load_params, "entry-type", &t);
1641.19Selad
1651.21Selad	if (strcasecmp($1, "direct") == 0) {
1661.21Selad		t |= VERIEXEC_DIRECT;
1671.21Selad	} else if (strcasecmp($1, "indirect") == 0) {
1681.21Selad		t |= VERIEXEC_INDIRECT;
1691.21Selad	} else if (strcasecmp($1, "file") == 0) {
1701.21Selad		t |= VERIEXEC_FILE;
1711.21Selad	} else if (strcasecmp($1, "program") == 0) {
1721.21Selad		t |= VERIEXEC_DIRECT;
1731.21Selad	} else if (strcasecmp($1, "interpreter") == 0) {
1741.21Selad		t |= VERIEXEC_INDIRECT;
1751.21Selad	} else if (strcasecmp($1, "script") == 0) {
1761.21Selad		t |= (VERIEXEC_FILE | VERIEXEC_DIRECT);
1771.21Selad	} else if (strcasecmp($1, "library") == 0) {
1781.21Selad		t |= (VERIEXEC_FILE | VERIEXEC_INDIRECT);
1791.21Selad	} else if (strcasecmp($1, "untrusted") == 0) {
1801.21Selad		t |= VERIEXEC_UNTRUSTED;
1811.21Selad	} else {
1821.21Selad		if (verbose)
1831.21Selad			warnx("Bad flag `%s' in line %zu", $1, line);
1841.21Selad		error = EXIT_FAILURE;
1851.21Selad		YYERROR;
1861.7Schristos	}
1871.1Sblymn
1881.21Selad	prop_dictionary_set_uint8(load_params, "entry-type", t);
1891.7Schristos}
1901.5Sblymn		;
1911.1Sblymn
1921.5Sblymneol		:	EOL
1931.5Sblymn		;
1941.1Sblymn
1951.1Sblymn%%
1961.21Selad
1971.1Sblymn/*
1981.5Sblymn * Takes the hexadecimal string pointed to by "fp" and converts it to a
1991.5Sblymn * "count" byte binary number which is stored in the array pointed to
2001.5Sblymn * by "out".  Returns the number of bytes converted or -1 if the conversion
2011.5Sblymn * fails.
2021.1Sblymn */
2031.19Seladstatic size_t
2041.7Schristosconvert(u_char *fp, u_char *out)
2051.7Schristos{
2061.7Schristos	size_t i, count;
2071.7Schristos	u_char value;
2081.5Sblymn
2091.5Sblymn	count = strlen(fp);
2101.5Sblymn
2111.7Schristos	/*
2121.7Schristos	 * if there are not an even number of hex digits then there is
2131.7Schristos	 * not an integral number of bytes in the fingerprint.
2141.7Schristos	 */
2151.5Sblymn	if ((count % 2) != 0)
2161.5Sblymn		return -1;
2171.5Sblymn
2181.5Sblymn	count /= 2;
2191.7Schristos
2201.7Schristos#define cvt(cv) \
2211.7Schristos	if (isdigit(cv)) \
2221.7Schristos		value += (cv) - '0'; \
2231.7Schristos	else if (isxdigit(cv)) \
2241.7Schristos		value += 10 + tolower(cv) - 'a'; \
2251.7Schristos	else \
2261.7Schristos		return -1
2271.5Sblymn
2281.5Sblymn	for (i = 0; i < count; i++) {
2291.7Schristos		value = 0;
2301.7Schristos		cvt(fp[2 * i]);
2311.7Schristos		value <<= 4;
2321.7Schristos		cvt(fp[2 * i + 1]);
2331.5Sblymn		out[i] = value;
2341.5Sblymn	}
2351.1Sblymn
2361.7Schristos	return count;
2371.1Sblymn}
2381.21Selad
2391.21Seladstatic void
2401.21Seladyyerror(const char *msg)
2411.21Selad{
2421.21Selad	if (verbose)
2431.21Selad		warnx("%s in line %zu", msg, line);
2441.21Selad}
245