veriexecctl_parse.y revision 1.10
11.1Sblymn%{ 21.10Selad/* $NetBSD: veriexecctl_parse.y,v 1.10 2005/06/13 15:18:44 elad 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.10Seladint have_type = 0; 521.10Selad 531.10Selad#define FIELD_TYPE 1 541.1Sblymn%} 551.1Sblymn 561.1Sblymn%union { 571.5Sblymn char *string; 581.5Sblymn int intval; 591.1Sblymn} 601.1Sblymn 611.1Sblymn%token <string> PATH 621.1Sblymn%token <string> STRING 631.10Selad%token EOL TOKEN_COMMA 641.1Sblymn 651.1Sblymn%% 661.1Sblymn 671.5Sblymnstatement : /* empty */ 681.5Sblymn | statement path type fingerprint flags eol { 691.7Schristos struct stat sb; 701.8Selad struct veriexec_up *p; 711.5Sblymn 721.7Schristos if (phase == 2) { 731.7Schristos phase2_load(); 741.7Schristos goto phase_2_end; 751.7Schristos } 761.7Schristos 771.7Schristos if (stat(params.file, &sb) == -1) { 781.7Schristos warnx("Line %lu: Can't stat `%s'", 791.7Schristos (unsigned long)line, 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.7Schristos (unsigned long)line, params.file); 871.7Schristos goto phase_2_end; 881.7Schristos } 891.7Schristos 901.9Selad if ((p = dev_lookup(sb.st_dev)) != NULL) { 911.7Schristos (p->vu_param.hash_size)++; 921.7Schristos goto phase_2_end; 931.7Schristos } 941.7Schristos 951.7Schristos if (verbose) { 961.7Schristos struct statvfs sf; 971.7Schristos if (statvfs(params.file, &sf) == -1) 981.7Schristos err(1, "Cannot statvfs `%s'", params.file); 991.5Sblymn 1001.7Schristos (void)printf( " => Adding device ID %d. (%s)\n", 1011.7Schristos sb.st_dev, sf.f_mntonname); 1021.7Schristos } 1031.7Schristos dev_add(sb.st_dev); 1041.5Sblymnphase_2_end: 1051.7Schristos (void)memset(¶ms, 0, sizeof(params)); 1061.10Selad have_type = 0; 1071.7Schristos} 1081.5Sblymn | statement eol 1091.5Sblymn | statement error eol { 1101.7Schristos yyerrok; 1111.7Schristos} 1121.5Sblymn ; 1131.5Sblymn 1141.5Sblymnpath : PATH { 1151.7Schristos (void)strlcpy(params.file, $1, MAXPATHLEN); 1161.7Schristos} 1171.5Sblymn ; 1181.5Sblymn 1191.5Sblymntype : STRING { 1201.10Selad if (phase == 2) { 1211.7Schristos if (strlen($1) >= sizeof(params.fp_type)) { 1221.7Schristos yyerror("Fingerprint type too long"); 1231.7Schristos YYERROR; 1241.7Schristos } 1251.7Schristos 1261.7Schristos (void)strlcpy(params.fp_type, $1, sizeof(params.fp_type)); 1271.7Schristos } 1281.7Schristos} 1291.5Sblymn ; 1301.1Sblymn 1311.1Sblymn 1321.5Sblymnfingerprint : STRING { 1331.10Selad if (phase == 2) { 1341.7Schristos params.fingerprint = malloc(strlen($1) / 2); 1351.7Schristos if (params.fingerprint == NULL) 1361.7Schristos err(1, "Fingerprint mem alloc failed"); 1371.5Sblymn 1381.7Schristos if ((params.size = convert($1, params.fingerprint)) == -1) { 1391.7Schristos free(params.fingerprint); 1401.7Schristos yyerror("Bad fingerprint"); 1411.7Schristos YYERROR; 1421.7Schristos } 1431.7Schristos } 1441.5Sblymn 1451.7Schristos} 1461.7Schristos ; 1471.1Sblymn 1481.5Sblymnflags : /* empty */ { 1491.7Schristos if (phase == 2) 1501.7Schristos params.type = VERIEXEC_DIRECT; 1511.7Schristos} 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.10Selad if (phase == 2) { 1611.10Selad int field; 1621.10Selad int value; 1631.10Selad 1641.10Selad /* 1651.10Selad * XXXEE: It might be a good idea to change this into 1661.10Selad * XXXEE: something less hard-coded. Perhaps loop on 1671.10Selad * XXXEE: tuples of (name, field, value)? 1681.10Selad */ 1691.10Selad if (strcasecmp($1, "direct") == 0) { 1701.10Selad field = FIELD_TYPE; 1711.10Selad value = VERIEXEC_DIRECT; 1721.10Selad } else if (strcasecmp($1, "indirect") == 0) { 1731.10Selad field = FIELD_TYPE; 1741.10Selad value = VERIEXEC_INDIRECT; 1751.10Selad } else if (strcasecmp($1, "file") == 0) { 1761.10Selad field = FIELD_TYPE; 1771.10Selad value = VERIEXEC_FILE; 1781.10Selad } else { 1791.10Selad yyerror("Bad flag"); 1801.7Schristos YYERROR; 1811.7Schristos } 1821.10Selad 1831.10Selad switch (field) { 1841.10Selad case FIELD_TYPE: 1851.10Selad if (have_type) { 1861.10Selad yyerror("Mulitple type definitions"); 1871.10Selad YYERROR; 1881.10Selad } 1891.10Selad 1901.10Selad params.type = value; 1911.10Selad have_type = 1; 1921.10Selad break; 1931.10Selad } 1941.7Schristos } 1951.1Sblymn 1961.7Schristos} 1971.5Sblymn ; 1981.1Sblymn 1991.5Sblymneol : EOL 2001.5Sblymn ; 2011.1Sblymn 2021.1Sblymn%% 2031.1Sblymn 2041.1Sblymn/* 2051.5Sblymn * Takes the hexadecimal string pointed to by "fp" and converts it to a 2061.5Sblymn * "count" byte binary number which is stored in the array pointed to 2071.5Sblymn * by "out". Returns the number of bytes converted or -1 if the conversion 2081.5Sblymn * fails. 2091.1Sblymn */ 2101.7Schristosstatic int 2111.7Schristosconvert(u_char *fp, u_char *out) 2121.7Schristos{ 2131.7Schristos size_t i, count; 2141.7Schristos u_char value; 2151.5Sblymn 2161.5Sblymn count = strlen(fp); 2171.5Sblymn 2181.7Schristos /* 2191.7Schristos * if there are not an even number of hex digits then there is 2201.7Schristos * not an integral number of bytes in the fingerprint. 2211.7Schristos */ 2221.5Sblymn if ((count % 2) != 0) 2231.5Sblymn return -1; 2241.5Sblymn 2251.5Sblymn count /= 2; 2261.7Schristos 2271.7Schristos#define cvt(cv) \ 2281.7Schristos if (isdigit(cv)) \ 2291.7Schristos value += (cv) - '0'; \ 2301.7Schristos else if (isxdigit(cv)) \ 2311.7Schristos value += 10 + tolower(cv) - 'a'; \ 2321.7Schristos else \ 2331.7Schristos return -1 2341.5Sblymn 2351.5Sblymn for (i = 0; i < count; i++) { 2361.7Schristos value = 0; 2371.7Schristos cvt(fp[2 * i]); 2381.7Schristos value <<= 4; 2391.7Schristos cvt(fp[2 * i + 1]); 2401.5Sblymn out[i] = value; 2411.5Sblymn } 2421.1Sblymn 2431.7Schristos return count; 2441.1Sblymn} 245