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(¶ms, 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