veriexecctl_parse.y revision 1.12
11.1Sblymn%{ 21.12Sblymn/* $NetBSD: veriexecctl_parse.y,v 1.12 2005/08/06 09:00:20 blymn Exp $ */ 31.5Sblymn 41.5Sblymn/*- 51.5Sblymn * Copyright 2005 Elad Efrat <elad@bsd.org.il> 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.5Sblymn 691.7Schristos if (phase == 2) { 701.7Schristos phase2_load(); 711.7Schristos goto phase_2_end; 721.7Schristos } 731.7Schristos 741.7Schristos if (stat(params.file, &sb) == -1) { 751.7Schristos warnx("Line %lu: Can't stat `%s'", 761.7Schristos (unsigned long)line, params.file); 771.7Schristos goto phase_2_end; 781.7Schristos } 791.7Schristos 801.7Schristos /* Only regular files */ 811.7Schristos if (!S_ISREG(sb.st_mode)) { 821.7Schristos warnx("Line %lu: %s is not a regular file", 831.7Schristos (unsigned long)line, params.file); 841.7Schristos goto phase_2_end; 851.7Schristos } 861.7Schristos 871.9Selad if ((p = dev_lookup(sb.st_dev)) != NULL) { 881.7Schristos (p->vu_param.hash_size)++; 891.7Schristos goto phase_2_end; 901.7Schristos } 911.7Schristos 921.7Schristos if (verbose) { 931.7Schristos struct statvfs sf; 941.7Schristos if (statvfs(params.file, &sf) == -1) 951.7Schristos err(1, "Cannot statvfs `%s'", params.file); 961.5Sblymn 971.7Schristos (void)printf( " => Adding device ID %d. (%s)\n", 981.7Schristos sb.st_dev, sf.f_mntonname); 991.7Schristos } 1001.7Schristos dev_add(sb.st_dev); 1011.5Sblymnphase_2_end: 1021.7Schristos (void)memset(¶ms, 0, sizeof(params)); 1031.7Schristos} 1041.5Sblymn | statement eol 1051.5Sblymn | statement error eol { 1061.7Schristos yyerrok; 1071.7Schristos} 1081.5Sblymn ; 1091.5Sblymn 1101.5Sblymnpath : PATH { 1111.7Schristos (void)strlcpy(params.file, $1, MAXPATHLEN); 1121.7Schristos} 1131.5Sblymn ; 1141.5Sblymn 1151.5Sblymntype : STRING { 1161.10Selad if (phase == 2) { 1171.7Schristos if (strlen($1) >= sizeof(params.fp_type)) { 1181.7Schristos yyerror("Fingerprint type too long"); 1191.7Schristos YYERROR; 1201.7Schristos } 1211.7Schristos 1221.7Schristos (void)strlcpy(params.fp_type, $1, sizeof(params.fp_type)); 1231.7Schristos } 1241.7Schristos} 1251.5Sblymn ; 1261.1Sblymn 1271.1Sblymn 1281.5Sblymnfingerprint : STRING { 1291.10Selad if (phase == 2) { 1301.7Schristos params.fingerprint = malloc(strlen($1) / 2); 1311.7Schristos if (params.fingerprint == NULL) 1321.7Schristos err(1, "Fingerprint mem alloc failed"); 1331.5Sblymn 1341.7Schristos if ((params.size = convert($1, params.fingerprint)) == -1) { 1351.7Schristos free(params.fingerprint); 1361.7Schristos yyerror("Bad fingerprint"); 1371.7Schristos YYERROR; 1381.7Schristos } 1391.7Schristos } 1401.5Sblymn 1411.7Schristos} 1421.7Schristos ; 1431.1Sblymn 1441.5Sblymnflags : /* empty */ { 1451.7Schristos if (phase == 2) 1461.7Schristos params.type = VERIEXEC_DIRECT; 1471.7Schristos} 1481.10Selad | flags_spec 1491.10Selad ; 1501.10Selad 1511.10Seladflags_spec : flag_spec 1521.10Selad | flags_spec TOKEN_COMMA flag_spec 1531.5Sblymn ; 1541.1Sblymn 1551.5Sblymnflag_spec : STRING { 1561.10Selad if (phase == 2) { 1571.10Selad if (strcasecmp($1, "direct") == 0) { 1581.11Selad params.type |= VERIEXEC_DIRECT; 1591.10Selad } else if (strcasecmp($1, "indirect") == 0) { 1601.11Selad params.type |= VERIEXEC_INDIRECT; 1611.10Selad } else if (strcasecmp($1, "file") == 0) { 1621.11Selad params.type |= VERIEXEC_FILE; 1631.12Sblymn } else if (strcasecmp($1, "program") == 0) { 1641.12Sblymn params.type |= VERIEXEC_DIRECT; 1651.12Sblymn } else if (strcasecmp($1, "interpreter") == 0) { 1661.12Sblymn params.type |= VERIEXEC_INDIRECT; 1671.12Sblymn } else if (strcasecmp($1, "script") == 0) { 1681.12Sblymn params.type |= (VERIEXEC_FILE | VERIEXEC_DIRECT); 1691.12Sblymn } else if (strcasecmp($1, "library") == 0) { 1701.12Sblymn params.type |= VERIEXEC_FILE; 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