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