veriexecctl_parse.y revision 1.10
1%{ 2/* $NetBSD: veriexecctl_parse.y,v 1.10 2005/06/13 15:18:44 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 51int have_type = 0; 52 53#define FIELD_TYPE 1 54%} 55 56%union { 57 char *string; 58 int intval; 59} 60 61%token <string> PATH 62%token <string> STRING 63%token EOL TOKEN_COMMA 64 65%% 66 67statement : /* empty */ 68 | statement path type fingerprint flags eol { 69 struct stat sb; 70 struct veriexec_up *p; 71 72 if (phase == 2) { 73 phase2_load(); 74 goto phase_2_end; 75 } 76 77 if (stat(params.file, &sb) == -1) { 78 warnx("Line %lu: Can't stat `%s'", 79 (unsigned long)line, params.file); 80 goto phase_2_end; 81 } 82 83 /* Only regular files */ 84 if (!S_ISREG(sb.st_mode)) { 85 warnx("Line %lu: %s is not a regular file", 86 (unsigned long)line, params.file); 87 goto phase_2_end; 88 } 89 90 if ((p = dev_lookup(sb.st_dev)) != NULL) { 91 (p->vu_param.hash_size)++; 92 goto phase_2_end; 93 } 94 95 if (verbose) { 96 struct statvfs sf; 97 if (statvfs(params.file, &sf) == -1) 98 err(1, "Cannot statvfs `%s'", params.file); 99 100 (void)printf( " => Adding device ID %d. (%s)\n", 101 sb.st_dev, sf.f_mntonname); 102 } 103 dev_add(sb.st_dev); 104phase_2_end: 105 (void)memset(¶ms, 0, sizeof(params)); 106 have_type = 0; 107} 108 | statement eol 109 | statement error eol { 110 yyerrok; 111} 112 ; 113 114path : PATH { 115 (void)strlcpy(params.file, $1, MAXPATHLEN); 116} 117 ; 118 119type : STRING { 120 if (phase == 2) { 121 if (strlen($1) >= sizeof(params.fp_type)) { 122 yyerror("Fingerprint type too long"); 123 YYERROR; 124 } 125 126 (void)strlcpy(params.fp_type, $1, sizeof(params.fp_type)); 127 } 128} 129 ; 130 131 132fingerprint : STRING { 133 if (phase == 2) { 134 params.fingerprint = malloc(strlen($1) / 2); 135 if (params.fingerprint == NULL) 136 err(1, "Fingerprint mem alloc failed"); 137 138 if ((params.size = convert($1, params.fingerprint)) == -1) { 139 free(params.fingerprint); 140 yyerror("Bad fingerprint"); 141 YYERROR; 142 } 143 } 144 145} 146 ; 147 148flags : /* empty */ { 149 if (phase == 2) 150 params.type = VERIEXEC_DIRECT; 151} 152 | flags_spec 153 ; 154 155flags_spec : flag_spec 156 | flags_spec TOKEN_COMMA flag_spec 157 ; 158 159flag_spec : STRING { 160 if (phase == 2) { 161 int field; 162 int value; 163 164 /* 165 * XXXEE: It might be a good idea to change this into 166 * XXXEE: something less hard-coded. Perhaps loop on 167 * XXXEE: tuples of (name, field, value)? 168 */ 169 if (strcasecmp($1, "direct") == 0) { 170 field = FIELD_TYPE; 171 value = VERIEXEC_DIRECT; 172 } else if (strcasecmp($1, "indirect") == 0) { 173 field = FIELD_TYPE; 174 value = VERIEXEC_INDIRECT; 175 } else if (strcasecmp($1, "file") == 0) { 176 field = FIELD_TYPE; 177 value = VERIEXEC_FILE; 178 } else { 179 yyerror("Bad flag"); 180 YYERROR; 181 } 182 183 switch (field) { 184 case FIELD_TYPE: 185 if (have_type) { 186 yyerror("Mulitple type definitions"); 187 YYERROR; 188 } 189 190 params.type = value; 191 have_type = 1; 192 break; 193 } 194 } 195 196} 197 ; 198 199eol : EOL 200 ; 201 202%% 203 204/* 205 * Takes the hexadecimal string pointed to by "fp" and converts it to a 206 * "count" byte binary number which is stored in the array pointed to 207 * by "out". Returns the number of bytes converted or -1 if the conversion 208 * fails. 209 */ 210static int 211convert(u_char *fp, u_char *out) 212{ 213 size_t i, count; 214 u_char value; 215 216 count = strlen(fp); 217 218 /* 219 * if there are not an even number of hex digits then there is 220 * not an integral number of bytes in the fingerprint. 221 */ 222 if ((count % 2) != 0) 223 return -1; 224 225 count /= 2; 226 227#define cvt(cv) \ 228 if (isdigit(cv)) \ 229 value += (cv) - '0'; \ 230 else if (isxdigit(cv)) \ 231 value += 10 + tolower(cv) - 'a'; \ 232 else \ 233 return -1 234 235 for (i = 0; i < count; i++) { 236 value = 0; 237 cvt(fp[2 * i]); 238 value <<= 4; 239 cvt(fp[2 * i + 1]); 240 out[i] = value; 241 } 242 243 return count; 244} 245