veriexecctl_parse.y revision 1.21
1%{ 2/* $NetBSD: veriexecctl_parse.y,v 1.21 2007/05/15 19:47:47 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/stat.h> 35#include <sys/verified_exec.h> 36 37#include <ctype.h> 38#include <stdio.h> 39#include <string.h> 40#include <err.h> 41 42#include <prop/proplib.h> 43 44#include "veriexecctl.h" 45 46extern int yylex(void); 47extern size_t line; 48extern int verbose, error; 49 50boolean_t keep_filename = FALSE, eval_on_load = FALSE; 51prop_dictionary_t load_params; 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 extern int gfd; 69 struct stat sb; 70 71 if (stat(dict_gets(load_params, "file"), &sb) == -1) { 72 if (verbose) 73 warnx("Line %zu: Can't stat `%s'", line, 74 dict_gets(load_params, "file")); 75 error = EXIT_FAILURE; 76 goto skip; 77 } 78 79 /* Only regular files */ 80 if (!S_ISREG(sb.st_mode)) { 81 if (verbose) 82 warnx("Line %zu: %s is not a regular file", line, 83 dict_gets(load_params, "file")); 84 error = EXIT_FAILURE; 85 goto skip; 86 } 87 88 if (verbose) { 89 (void)printf( "Adding file `%s'.\n", 90 dict_gets(load_params, "file")); 91 } 92 93 prop_dictionary_set(load_params, "keep-filename", 94 prop_bool_create(keep_filename)); 95 96 prop_dictionary_set(load_params, "eval-on-load", 97 prop_bool_create(eval_on_load)); 98 99 if (prop_dictionary_send_ioctl(load_params, gfd, VERIEXEC_LOAD) != 0) { 100 if (verbose) 101 warn("Cannot load params from `%s'", 102 dict_gets(load_params, "file")); 103 error = EXIT_FAILURE; 104 } 105 106 skip: 107 prop_object_release(load_params); 108 load_params = NULL; 109} 110 | statement eol 111 | statement error eol { 112 yyerrok; 113} 114 ; 115 116path : PATH { 117 if (load_params == NULL) 118 load_params = prop_dictionary_create(); 119 120 dict_sets(load_params, "file", $1); 121} 122 ; 123 124type : STRING { 125 dict_sets(load_params, "fp-type", $1); 126} 127 ; 128 129 130fingerprint : STRING { 131 char *fp; 132 size_t n; 133 134 fp = malloc(strlen($1) / 2); 135 if (fp == NULL) 136 err(1, "Cannot allocate memory for fingerprint"); 137 138 n = convert($1, fp); 139 if (n == -1) { 140 free(fp); 141 if (verbose) 142 warnx("Bad fingerprint `%s' in line %zu", $1, line); 143 error = EXIT_FAILURE; 144 YYERROR; 145 } 146 147 dict_setd(load_params, "fp", fp, n); 148 free(fp); 149} 150 ; 151 152flags : /* empty */ 153 | flags_spec 154 ; 155 156flags_spec : flag_spec 157 | flags_spec TOKEN_COMMA flag_spec 158 ; 159 160flag_spec : STRING { 161 uint8_t t = 0; 162 163 prop_dictionary_get_uint8(load_params, "entry-type", &t); 164 165 if (strcasecmp($1, "direct") == 0) { 166 t |= VERIEXEC_DIRECT; 167 } else if (strcasecmp($1, "indirect") == 0) { 168 t |= VERIEXEC_INDIRECT; 169 } else if (strcasecmp($1, "file") == 0) { 170 t |= VERIEXEC_FILE; 171 } else if (strcasecmp($1, "program") == 0) { 172 t |= VERIEXEC_DIRECT; 173 } else if (strcasecmp($1, "interpreter") == 0) { 174 t |= VERIEXEC_INDIRECT; 175 } else if (strcasecmp($1, "script") == 0) { 176 t |= (VERIEXEC_FILE | VERIEXEC_DIRECT); 177 } else if (strcasecmp($1, "library") == 0) { 178 t |= (VERIEXEC_FILE | VERIEXEC_INDIRECT); 179 } else if (strcasecmp($1, "untrusted") == 0) { 180 t |= VERIEXEC_UNTRUSTED; 181 } else { 182 if (verbose) 183 warnx("Bad flag `%s' in line %zu", $1, line); 184 error = EXIT_FAILURE; 185 YYERROR; 186 } 187 188 prop_dictionary_set_uint8(load_params, "entry-type", t); 189} 190 ; 191 192eol : EOL 193 ; 194 195%% 196 197/* 198 * Takes the hexadecimal string pointed to by "fp" and converts it to a 199 * "count" byte binary number which is stored in the array pointed to 200 * by "out". Returns the number of bytes converted or -1 if the conversion 201 * fails. 202 */ 203static size_t 204convert(u_char *fp, u_char *out) 205{ 206 size_t i, count; 207 u_char value; 208 209 count = strlen(fp); 210 211 /* 212 * if there are not an even number of hex digits then there is 213 * not an integral number of bytes in the fingerprint. 214 */ 215 if ((count % 2) != 0) 216 return -1; 217 218 count /= 2; 219 220#define cvt(cv) \ 221 if (isdigit(cv)) \ 222 value += (cv) - '0'; \ 223 else if (isxdigit(cv)) \ 224 value += 10 + tolower(cv) - 'a'; \ 225 else \ 226 return -1 227 228 for (i = 0; i < count; i++) { 229 value = 0; 230 cvt(fp[2 * i]); 231 value <<= 4; 232 cvt(fp[2 * i + 1]); 233 out[i] = value; 234 } 235 236 return count; 237} 238 239static void 240yyerror(const char *msg) 241{ 242 if (verbose) 243 warnx("%s in line %zu", msg, line); 244} 245