veriexecctl_parse.y revision 1.26
11.1Sblymn%{
21.26Slukem/*	$NetBSD: veriexecctl_parse.y,v 1.26 2009/03/16 13:38:09 lukem Exp $	*/
31.5Sblymn
41.5Sblymn/*-
51.18Selad * Copyright 2005 Elad Efrat <elad@NetBSD.org>
61.25Sdholland * 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.22Spavel#include <stdbool.h>
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.22Spavelbool 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.1Sblymn}
581.1Sblymn
591.1Sblymn%token <string> PATH
601.1Sblymn%token <string> STRING
611.10Selad%token EOL TOKEN_COMMA
621.1Sblymn
631.1Sblymn%%
641.1Sblymn
651.5Sblymnstatement	:	/* empty */
661.5Sblymn		|	statement path type fingerprint flags eol {
671.21Selad	extern int gfd;
681.7Schristos	struct stat sb;
691.7Schristos
701.19Selad	if (stat(dict_gets(load_params, "file"), &sb) == -1) {
711.21Selad		if (verbose)
721.21Selad			warnx("Line %zu: Can't stat `%s'", line,
731.21Selad			    dict_gets(load_params, "file"));
741.21Selad		error = EXIT_FAILURE;
751.21Selad		goto skip;
761.7Schristos	}
771.7Schristos
781.7Schristos	/* Only regular files */
791.7Schristos	if (!S_ISREG(sb.st_mode)) {
801.21Selad		if (verbose)
811.21Selad			warnx("Line %zu: %s is not a regular file", line,
821.21Selad			    dict_gets(load_params, "file"));
831.21Selad		error = EXIT_FAILURE;
841.21Selad		goto skip;
851.7Schristos	}
861.7Schristos
871.21Selad	if (verbose) {
881.21Selad		(void)printf( "Adding file `%s'.\n",
891.21Selad		    dict_gets(load_params, "file"));
901.21Selad	}
911.16Selad
921.21Selad	prop_dictionary_set(load_params, "keep-filename",
931.21Selad	    prop_bool_create(keep_filename));
941.19Selad
951.21Selad	prop_dictionary_set(load_params, "eval-on-load",
961.21Selad	    prop_bool_create(eval_on_load));
971.19Selad
981.21Selad	if (prop_dictionary_send_ioctl(load_params, gfd, VERIEXEC_LOAD) != 0) {
991.21Selad		if (verbose)
1001.21Selad			warn("Cannot load params from `%s'",
1011.21Selad			    dict_gets(load_params, "file"));
1021.21Selad		error = EXIT_FAILURE;
1031.16Selad	}
1041.16Selad
1051.21Selad skip:
1061.21Selad	prop_object_release(load_params);
1071.19Selad	load_params = NULL;
1081.7Schristos}
1091.5Sblymn		|	statement eol
1101.5Sblymn		|	statement error eol {
1111.7Schristos	yyerrok;
1121.7Schristos}
1131.5Sblymn		;
1141.5Sblymn
1151.5Sblymnpath		:	PATH {
1161.19Selad	if (load_params == NULL)
1171.19Selad		load_params = prop_dictionary_create();
1181.19Selad
1191.19Selad	dict_sets(load_params, "file", $1);
1201.7Schristos}
1211.5Sblymn		;
1221.5Sblymn
1231.5Sblymntype		:	STRING {
1241.21Selad	dict_sets(load_params, "fp-type", $1);
1251.7Schristos}
1261.5Sblymn		;
1271.1Sblymn
1281.1Sblymn
1291.5Sblymnfingerprint	:	STRING {
1301.24Sdholland	u_char *fp;
1311.21Selad	size_t n;
1321.21Selad
1331.21Selad	fp = malloc(strlen($1) / 2);
1341.21Selad	if (fp == NULL)
1351.21Selad		err(1, "Cannot allocate memory for fingerprint");
1361.19Selad
1371.21Selad	n = convert($1, fp);
1381.26Slukem	if (n == (size_t)-1) {
1391.19Selad		free(fp);
1401.21Selad		if (verbose)
1411.21Selad			warnx("Bad fingerprint `%s' in line %zu", $1, line);
1421.21Selad		error = EXIT_FAILURE;
1431.21Selad		YYERROR;
1441.7Schristos	}
1451.21Selad
1461.21Selad	dict_setd(load_params, "fp", fp, n);
1471.21Selad	free(fp);
1481.7Schristos}
1491.7Schristos	    ;
1501.1Sblymn
1511.13Seladflags		:	/* empty */
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.21Selad	uint8_t t = 0;
1611.20Selad
1621.21Selad	prop_dictionary_get_uint8(load_params, "entry-type", &t);
1631.19Selad
1641.21Selad	if (strcasecmp($1, "direct") == 0) {
1651.21Selad		t |= VERIEXEC_DIRECT;
1661.21Selad	} else if (strcasecmp($1, "indirect") == 0) {
1671.21Selad		t |= VERIEXEC_INDIRECT;
1681.21Selad	} else if (strcasecmp($1, "file") == 0) {
1691.21Selad		t |= VERIEXEC_FILE;
1701.21Selad	} else if (strcasecmp($1, "program") == 0) {
1711.21Selad		t |= VERIEXEC_DIRECT;
1721.21Selad	} else if (strcasecmp($1, "interpreter") == 0) {
1731.21Selad		t |= VERIEXEC_INDIRECT;
1741.21Selad	} else if (strcasecmp($1, "script") == 0) {
1751.21Selad		t |= (VERIEXEC_FILE | VERIEXEC_DIRECT);
1761.21Selad	} else if (strcasecmp($1, "library") == 0) {
1771.21Selad		t |= (VERIEXEC_FILE | VERIEXEC_INDIRECT);
1781.21Selad	} else if (strcasecmp($1, "untrusted") == 0) {
1791.21Selad		t |= VERIEXEC_UNTRUSTED;
1801.21Selad	} else {
1811.21Selad		if (verbose)
1821.21Selad			warnx("Bad flag `%s' in line %zu", $1, line);
1831.21Selad		error = EXIT_FAILURE;
1841.21Selad		YYERROR;
1851.7Schristos	}
1861.1Sblymn
1871.21Selad	prop_dictionary_set_uint8(load_params, "entry-type", t);
1881.7Schristos}
1891.5Sblymn		;
1901.1Sblymn
1911.5Sblymneol		:	EOL
1921.5Sblymn		;
1931.1Sblymn
1941.1Sblymn%%
1951.21Selad
1961.1Sblymn/*
1971.25Sdholland * Takes the hexadecimal string pointed to by "fp" and converts it to a
1981.5Sblymn * "count" byte binary number which is stored in the array pointed to
1991.5Sblymn * by "out".  Returns the number of bytes converted or -1 if the conversion
2001.5Sblymn * fails.
2011.1Sblymn */
2021.19Seladstatic size_t
2031.24Sdhollandconvert(char *fp, u_char *out)
2041.7Schristos{
2051.7Schristos	size_t i, count;
2061.7Schristos	u_char value;
2071.5Sblymn
2081.5Sblymn	count = strlen(fp);
2091.5Sblymn
2101.7Schristos	/*
2111.7Schristos	 * if there are not an even number of hex digits then there is
2121.7Schristos	 * not an integral number of bytes in the fingerprint.
2131.7Schristos	 */
2141.5Sblymn	if ((count % 2) != 0)
2151.26Slukem		return (size_t)-1;
2161.25Sdholland
2171.5Sblymn	count /= 2;
2181.7Schristos
2191.7Schristos#define cvt(cv) \
2201.24Sdholland	if (isdigit((unsigned char) cv)) \
2211.7Schristos		value += (cv) - '0'; \
2221.24Sdholland	else if (isxdigit((unsigned char) cv)) \
2231.24Sdholland		value += 10 + tolower((unsigned char) cv) - 'a'; \
2241.7Schristos	else \
2251.26Slukem		return (size_t)-1
2261.5Sblymn
2271.5Sblymn	for (i = 0; i < count; i++) {
2281.7Schristos		value = 0;
2291.7Schristos		cvt(fp[2 * i]);
2301.7Schristos		value <<= 4;
2311.7Schristos		cvt(fp[2 * i + 1]);
2321.5Sblymn		out[i] = value;
2331.5Sblymn	}
2341.1Sblymn
2351.7Schristos	return count;
2361.1Sblymn}
2371.21Selad
2381.21Seladstatic void
2391.21Seladyyerror(const char *msg)
2401.21Selad{
2411.21Selad	if (verbose)
2421.21Selad		warnx("%s in line %zu", msg, line);
2431.21Selad}
244