veriexecctl_parse.y revision 1.19
11.1Sblymn%{ 21.19Selad/* $NetBSD: veriexecctl_parse.y,v 1.19 2006/11/28 22:22:03 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.10Selad if (strcasecmp($1, "direct") == 0) { 1701.19Selad t |= VERIEXEC_DIRECT; 1711.10Selad } else if (strcasecmp($1, "indirect") == 0) { 1721.19Selad t |= VERIEXEC_INDIRECT; 1731.10Selad } else if (strcasecmp($1, "file") == 0) { 1741.19Selad t |= VERIEXEC_FILE; 1751.12Sblymn } else if (strcasecmp($1, "program") == 0) { 1761.19Selad t |= VERIEXEC_DIRECT; 1771.12Sblymn } else if (strcasecmp($1, "interpreter") == 0) { 1781.19Selad t |= VERIEXEC_INDIRECT; 1791.12Sblymn } else if (strcasecmp($1, "script") == 0) { 1801.19Selad t |= (VERIEXEC_FILE | VERIEXEC_DIRECT); 1811.12Sblymn } else if (strcasecmp($1, "library") == 0) { 1821.19Selad t |= (VERIEXEC_FILE | VERIEXEC_INDIRECT); 1831.13Selad } else if (strcasecmp($1, "untrusted") == 0) { 1841.19Selad t |= VERIEXEC_UNTRUSTED; 1851.10Selad } else { 1861.10Selad yyerror("Bad flag"); 1871.7Schristos YYERROR; 1881.7Schristos } 1891.19Selad 1901.19Selad prop_dictionary_set_uint8(load_params, "entry-type", t); 1911.7Schristos } 1921.1Sblymn 1931.7Schristos} 1941.5Sblymn ; 1951.1Sblymn 1961.5Sblymneol : EOL 1971.5Sblymn ; 1981.1Sblymn 1991.1Sblymn%% 2001.1Sblymn 2011.1Sblymn/* 2021.5Sblymn * Takes the hexadecimal string pointed to by "fp" and converts it to a 2031.5Sblymn * "count" byte binary number which is stored in the array pointed to 2041.5Sblymn * by "out". Returns the number of bytes converted or -1 if the conversion 2051.5Sblymn * fails. 2061.1Sblymn */ 2071.19Seladstatic size_t 2081.7Schristosconvert(u_char *fp, u_char *out) 2091.7Schristos{ 2101.7Schristos size_t i, count; 2111.7Schristos u_char value; 2121.5Sblymn 2131.5Sblymn count = strlen(fp); 2141.5Sblymn 2151.7Schristos /* 2161.7Schristos * if there are not an even number of hex digits then there is 2171.7Schristos * not an integral number of bytes in the fingerprint. 2181.7Schristos */ 2191.5Sblymn if ((count % 2) != 0) 2201.5Sblymn return -1; 2211.5Sblymn 2221.5Sblymn count /= 2; 2231.7Schristos 2241.7Schristos#define cvt(cv) \ 2251.7Schristos if (isdigit(cv)) \ 2261.7Schristos value += (cv) - '0'; \ 2271.7Schristos else if (isxdigit(cv)) \ 2281.7Schristos value += 10 + tolower(cv) - 'a'; \ 2291.7Schristos else \ 2301.7Schristos return -1 2311.5Sblymn 2321.5Sblymn for (i = 0; i < count; i++) { 2331.7Schristos value = 0; 2341.7Schristos cvt(fp[2 * i]); 2351.7Schristos value <<= 4; 2361.7Schristos cvt(fp[2 * i + 1]); 2371.5Sblymn out[i] = value; 2381.5Sblymn } 2391.1Sblymn 2401.7Schristos return count; 2411.1Sblymn} 242