veriexecctl_parse.y revision 1.13
1%{ 2/* $NetBSD: veriexecctl_parse.y,v 1.13 2005/10/05 13:48:48 elad Exp $ */ 3 4/*- 5 * Copyright 2005 Elad Efrat <elad@bsd.org.il> 6 * Copyright 2005 Brett Lymn <blymn@netbsd.org> 7 * 8 * All rights reserved. 9 * 10 * This code has been donated to The NetBSD Foundation by the Author. 11 * 12 * Redistribution and use in source and binary forms, with or without 13 * modification, are permitted provided that the following conditions 14 * are met: 15 * 1. Redistributions of source code must retain the above copyright 16 * notice, this list of conditions and the following disclaimer. 17 * 2. The name of the author may not be used to endorse or promote products 18 * derived from this software withough specific prior written permission 19 * 20 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 21 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 22 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 23 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 24 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 25 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 26 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 27 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 28 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 29 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 * 31 * 32 */ 33 34#include <sys/param.h> 35#include <sys/ioctl.h> 36#include <sys/statvfs.h> 37#include <sys/mount.h> 38 39#include <sys/verified_exec.h> 40#include <ctype.h> 41#include <stdio.h> 42#include <string.h> 43#include <errno.h> 44#include <err.h> 45 46#include "veriexecctl.h" 47 48struct veriexec_params params; 49static int convert(u_char *, u_char *); 50 51%} 52 53%union { 54 char *string; 55 int intval; 56} 57 58%token <string> PATH 59%token <string> STRING 60%token EOL TOKEN_COMMA 61 62%% 63 64statement : /* empty */ 65 | statement path type fingerprint flags eol { 66 struct stat sb; 67 struct veriexec_up *p; 68 69 if (phase == 2) { 70 phase2_load(); 71 goto phase_2_end; 72 } 73 74 if (stat(params.file, &sb) == -1) { 75 warnx("Line %lu: Can't stat `%s'", 76 (unsigned long)line, params.file); 77 goto phase_2_end; 78 } 79 80 /* Only regular files */ 81 if (!S_ISREG(sb.st_mode)) { 82 warnx("Line %lu: %s is not a regular file", 83 (unsigned long)line, params.file); 84 goto phase_2_end; 85 } 86 87 if ((p = dev_lookup(sb.st_dev)) != NULL) { 88 (p->vu_param.hash_size)++; 89 goto phase_2_end; 90 } 91 92 if (verbose) { 93 struct statvfs sf; 94 if (statvfs(params.file, &sf) == -1) 95 err(1, "Cannot statvfs `%s'", params.file); 96 97 (void)printf( " => Adding device ID %d. (%s)\n", 98 sb.st_dev, sf.f_mntonname); 99 } 100 dev_add(sb.st_dev); 101phase_2_end: 102 (void)memset(¶ms, 0, sizeof(params)); 103} 104 | statement eol 105 | statement error eol { 106 yyerrok; 107} 108 ; 109 110path : PATH { 111 (void)strlcpy(params.file, $1, MAXPATHLEN); 112} 113 ; 114 115type : STRING { 116 if (phase == 2) { 117 if (strlen($1) >= sizeof(params.fp_type)) { 118 yyerror("Fingerprint type too long"); 119 YYERROR; 120 } 121 122 (void)strlcpy(params.fp_type, $1, sizeof(params.fp_type)); 123 } 124} 125 ; 126 127 128fingerprint : STRING { 129 if (phase == 2) { 130 params.fingerprint = malloc(strlen($1) / 2); 131 if (params.fingerprint == NULL) 132 err(1, "Fingerprint mem alloc failed"); 133 134 if ((params.size = convert($1, params.fingerprint)) == -1) { 135 free(params.fingerprint); 136 yyerror("Bad fingerprint"); 137 YYERROR; 138 } 139 } 140 141} 142 ; 143 144flags : /* empty */ 145 | flags_spec 146 ; 147 148flags_spec : flag_spec 149 | flags_spec TOKEN_COMMA flag_spec 150 ; 151 152flag_spec : STRING { 153 if (phase == 2) { 154 if (strcasecmp($1, "direct") == 0) { 155 params.type |= VERIEXEC_DIRECT; 156 } else if (strcasecmp($1, "indirect") == 0) { 157 params.type |= VERIEXEC_INDIRECT; 158 } else if (strcasecmp($1, "file") == 0) { 159 params.type |= VERIEXEC_FILE; 160 } else if (strcasecmp($1, "program") == 0) { 161 params.type |= VERIEXEC_DIRECT; 162 } else if (strcasecmp($1, "interpreter") == 0) { 163 params.type |= VERIEXEC_INDIRECT; 164 } else if (strcasecmp($1, "script") == 0) { 165 params.type |= (VERIEXEC_FILE | VERIEXEC_DIRECT); 166 } else if (strcasecmp($1, "library") == 0) { 167 params.type |= VERIEXEC_FILE; 168 } else if (strcasecmp($1, "untrusted") == 0) { 169 params.type |= VERIEXEC_UNTRUSTED; 170 } else { 171 yyerror("Bad flag"); 172 YYERROR; 173 } 174 } 175 176} 177 ; 178 179eol : EOL 180 ; 181 182%% 183 184/* 185 * Takes the hexadecimal string pointed to by "fp" and converts it to a 186 * "count" byte binary number which is stored in the array pointed to 187 * by "out". Returns the number of bytes converted or -1 if the conversion 188 * fails. 189 */ 190static int 191convert(u_char *fp, u_char *out) 192{ 193 size_t i, count; 194 u_char value; 195 196 count = strlen(fp); 197 198 /* 199 * if there are not an even number of hex digits then there is 200 * not an integral number of bytes in the fingerprint. 201 */ 202 if ((count % 2) != 0) 203 return -1; 204 205 count /= 2; 206 207#define cvt(cv) \ 208 if (isdigit(cv)) \ 209 value += (cv) - '0'; \ 210 else if (isxdigit(cv)) \ 211 value += 10 + tolower(cv) - 'a'; \ 212 else \ 213 return -1 214 215 for (i = 0; i < count; i++) { 216 value = 0; 217 cvt(fp[2 * i]); 218 value <<= 4; 219 cvt(fp[2 * i + 1]); 220 out[i] = value; 221 } 222 223 return count; 224} 225