veriexecctl_parse.y revision 1.20
1%{ 2/* $NetBSD: veriexecctl_parse.y,v 1.20 2006/12/08 23:22:19 elad Exp $ */ 3 4/*- 5 * Copyright 2005 Elad Efrat <elad@NetBSD.org> 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 <prop/proplib.h> 47 48#include "veriexecctl.h" 49 50prop_dictionary_t load_params; 51static size_t convert(u_char *, u_char *); 52 53%} 54 55%union { 56 char *string; 57 int intval; 58} 59 60%token <string> PATH 61%token <string> STRING 62%token EOL TOKEN_COMMA 63 64%% 65 66statement : /* empty */ 67 | statement path type fingerprint flags eol { 68 struct stat sb; 69 struct veriexec_up *p; 70 struct statvfs sf; 71 72 if (phase == 2) { 73 phase2_load(); 74 goto phase_2_end; 75 } 76 77 if (stat(dict_gets(load_params, "file"), &sb) == -1) { 78 warnx("Line %lu: Can't stat `%s'", 79 (unsigned long)line, dict_gets(load_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, dict_gets(load_params, "file")); 87 goto phase_2_end; 88 } 89 90 if (statvfs(dict_gets(load_params, "file"), &sf) == -1) 91 err(1, "Cannot statvfs `%s'", dict_gets(load_params, "file")); 92 93 if ((p = dev_lookup(sf.f_mntonname)) != NULL) { 94 uint64_t n; 95 96 prop_dictionary_get_uint64(p->vu_preload, "count", &n); 97 n++; 98 prop_dictionary_set_uint64(p->vu_preload, "count", n); 99 100 goto phase_2_end; 101 } 102 103 if (verbose) { 104 (void)printf( " => Adding mount `%s'.\n", sf.f_mntonname); 105 } 106 107 dev_add(sf.f_mntonname); 108 109phase_2_end: 110 load_params = NULL; 111} 112 | statement eol 113 | statement error eol { 114 yyerrok; 115} 116 ; 117 118path : PATH { 119 if (load_params == NULL) 120 load_params = prop_dictionary_create(); 121 122 dict_sets(load_params, "file", $1); 123} 124 ; 125 126type : STRING { 127 if (phase == 2) { 128 dict_sets(load_params, "fp-type", $1); 129 } 130} 131 ; 132 133 134fingerprint : STRING { 135 if (phase == 2) { 136 char *fp; 137 size_t n; 138 139 fp = malloc(strlen($1) / 2); 140 if (fp == NULL) 141 err(1, "Fingerprint mem alloc failed"); 142 143 n = convert($1, fp); 144 if (n == -1) { 145 free(fp); 146 yyerror("Bad fingerprint"); 147 YYERROR; 148 } 149 150 dict_setd(load_params, "fp", fp, n); 151 free(fp); 152 } 153 154} 155 ; 156 157flags : /* empty */ 158 | flags_spec 159 ; 160 161flags_spec : flag_spec 162 | flags_spec TOKEN_COMMA flag_spec 163 ; 164 165flag_spec : STRING { 166 if (phase == 2) { 167 uint8_t t = 0; 168 169 prop_dictionary_get_uint8(load_params, "entry-type", &t); 170 171 if (strcasecmp($1, "direct") == 0) { 172 t |= VERIEXEC_DIRECT; 173 } else if (strcasecmp($1, "indirect") == 0) { 174 t |= VERIEXEC_INDIRECT; 175 } else if (strcasecmp($1, "file") == 0) { 176 t |= VERIEXEC_FILE; 177 } else if (strcasecmp($1, "program") == 0) { 178 t |= VERIEXEC_DIRECT; 179 } else if (strcasecmp($1, "interpreter") == 0) { 180 t |= VERIEXEC_INDIRECT; 181 } else if (strcasecmp($1, "script") == 0) { 182 t |= (VERIEXEC_FILE | VERIEXEC_DIRECT); 183 } else if (strcasecmp($1, "library") == 0) { 184 t |= (VERIEXEC_FILE | VERIEXEC_INDIRECT); 185 } else if (strcasecmp($1, "untrusted") == 0) { 186 t |= VERIEXEC_UNTRUSTED; 187 } else { 188 yyerror("Bad flag"); 189 YYERROR; 190 } 191 192 prop_dictionary_set_uint8(load_params, "entry-type", t); 193 } 194 195} 196 ; 197 198eol : EOL 199 ; 200 201%% 202 203/* 204 * Takes the hexadecimal string pointed to by "fp" and converts it to a 205 * "count" byte binary number which is stored in the array pointed to 206 * by "out". Returns the number of bytes converted or -1 if the conversion 207 * fails. 208 */ 209static size_t 210convert(u_char *fp, u_char *out) 211{ 212 size_t i, count; 213 u_char value; 214 215 count = strlen(fp); 216 217 /* 218 * if there are not an even number of hex digits then there is 219 * not an integral number of bytes in the fingerprint. 220 */ 221 if ((count % 2) != 0) 222 return -1; 223 224 count /= 2; 225 226#define cvt(cv) \ 227 if (isdigit(cv)) \ 228 value += (cv) - '0'; \ 229 else if (isxdigit(cv)) \ 230 value += 10 + tolower(cv) - 'a'; \ 231 else \ 232 return -1 233 234 for (i = 0; i < count; i++) { 235 value = 0; 236 cvt(fp[2 * i]); 237 value <<= 4; 238 cvt(fp[2 * i + 1]); 239 out[i] = value; 240 } 241 242 return count; 243} 244