1/* $NetBSD: sel.c,v 1.1.1.1 2011/04/13 18:15:12 elric Exp $ */ 2 3/* 4 * Copyright (c) 2008 Kungliga Tekniska Högskolan 5 * (Royal Institute of Technology, Stockholm, Sweden). 6 * All rights reserved. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 12 * 1. Redistributions of source code must retain the above copyright 13 * notice, this list of conditions and the following disclaimer. 14 * 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 19 * 3. Neither the name of the Institute nor the names of its contributors 20 * may be used to endorse or promote products derived from this software 21 * without specific prior written permission. 22 * 23 * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 24 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 25 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 26 * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 27 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 28 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 29 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 30 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 31 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 32 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 33 * SUCH DAMAGE. 34 */ 35 36#include "hx_locl.h" 37 38struct hx_expr * 39_hx509_make_expr(enum hx_expr_op op, void *arg1, void *arg2) 40{ 41 struct hx_expr *expr; 42 43 expr = malloc(sizeof(*expr)); 44 if (expr == NULL) 45 return NULL; 46 expr->op = op; 47 expr->arg1 = arg1; 48 expr->arg2 = arg2; 49 50 return expr; 51} 52 53static const char * 54eval_word(hx509_context context, hx509_env env, struct hx_expr *word) 55{ 56 switch (word->op) { 57 case expr_STRING: 58 return word->arg1; 59 case expr_VAR: 60 if (word->arg2 == NULL) 61 return hx509_env_find(context, env, word->arg1); 62 63 env = hx509_env_find_binding(context, env, word->arg1); 64 if (env == NULL) 65 return NULL; 66 67 return eval_word(context, env, word->arg2); 68 default: 69 return NULL; 70 } 71} 72 73static hx509_env 74find_variable(hx509_context context, hx509_env env, struct hx_expr *word) 75{ 76 assert(word->op == expr_VAR); 77 78 if (word->arg2 == NULL) 79 return hx509_env_find_binding(context, env, word->arg1); 80 81 env = hx509_env_find_binding(context, env, word->arg1); 82 if (env == NULL) 83 return NULL; 84 return find_variable(context, env, word->arg2); 85} 86 87static int 88eval_comp(hx509_context context, hx509_env env, struct hx_expr *expr) 89{ 90 switch (expr->op) { 91 case comp_NE: 92 case comp_EQ: 93 case comp_TAILEQ: { 94 const char *s1, *s2; 95 int ret; 96 97 s1 = eval_word(context, env, expr->arg1); 98 s2 = eval_word(context, env, expr->arg2); 99 100 if (s1 == NULL || s2 == NULL) 101 return FALSE; 102 103 if (expr->op == comp_TAILEQ) { 104 size_t len1 = strlen(s1); 105 size_t len2 = strlen(s2); 106 107 if (len1 < len2) 108 return 0; 109 ret = strcmp(s1 + (len1 - len2), s2) == 0; 110 } else { 111 ret = strcmp(s1, s2) == 0; 112 if (expr->op == comp_NE) 113 ret = !ret; 114 } 115 return ret; 116 } 117 case comp_IN: { 118 struct hx_expr *subexpr; 119 const char *w, *s1; 120 121 w = eval_word(context, env, expr->arg1); 122 123 subexpr = expr->arg2; 124 125 if (subexpr->op == expr_WORDS) { 126 while (subexpr) { 127 s1 = eval_word(context, env, subexpr->arg1); 128 if (strcmp(w, s1) == 0) 129 return TRUE; 130 subexpr = subexpr->arg2; 131 } 132 } else if (subexpr->op == expr_VAR) { 133 hx509_env subenv; 134 135 subenv = find_variable(context, env, subexpr); 136 if (subenv == NULL) 137 return FALSE; 138 139 while (subenv) { 140 if (subenv->type != env_string) 141 continue; 142 if (strcmp(w, subenv->name) == 0) 143 return TRUE; 144 if (strcmp(w, subenv->u.string) == 0) 145 return TRUE; 146 subenv = subenv->next; 147 } 148 149 } else 150 _hx509_abort("hx509 eval IN unknown op: %d", (int)subexpr->op); 151 152 return FALSE; 153 } 154 default: 155 _hx509_abort("hx509 eval expr with unknown op: %d", (int)expr->op); 156 } 157 return FALSE; 158} 159 160int 161_hx509_expr_eval(hx509_context context, hx509_env env, struct hx_expr *expr) 162{ 163 switch (expr->op) { 164 case op_TRUE: 165 return 1; 166 case op_FALSE: 167 return 0; 168 case op_NOT: 169 return ! _hx509_expr_eval(context, env, expr->arg1); 170 case op_AND: 171 return _hx509_expr_eval(context, env, expr->arg1) && 172 _hx509_expr_eval(context, env, expr->arg2); 173 case op_OR: 174 return _hx509_expr_eval(context, env, expr->arg1) || 175 _hx509_expr_eval(context, env, expr->arg2); 176 case op_COMP: 177 return eval_comp(context, env, expr->arg1); 178 default: 179 _hx509_abort("hx509 eval expr with unknown op: %d", (int)expr->op); 180 UNREACHABLE(return 0); 181 } 182} 183 184void 185_hx509_expr_free(struct hx_expr *expr) 186{ 187 switch (expr->op) { 188 case expr_STRING: 189 case expr_NUMBER: 190 free(expr->arg1); 191 break; 192 case expr_WORDS: 193 case expr_FUNCTION: 194 case expr_VAR: 195 free(expr->arg1); 196 if (expr->arg2) 197 _hx509_expr_free(expr->arg2); 198 break; 199 default: 200 if (expr->arg1) 201 _hx509_expr_free(expr->arg1); 202 if (expr->arg2) 203 _hx509_expr_free(expr->arg2); 204 break; 205 } 206 free(expr); 207} 208 209struct hx_expr * 210_hx509_expr_parse(const char *buf) 211{ 212 _hx509_expr_input.buf = buf; 213 _hx509_expr_input.length = strlen(buf); 214 _hx509_expr_input.offset = 0; 215 _hx509_expr_input.expr = NULL; 216 217 if (_hx509_expr_input.error) { 218 free(_hx509_expr_input.error); 219 _hx509_expr_input.error = NULL; 220 } 221 222 yyparse(); 223 224 return _hx509_expr_input.expr; 225} 226 227void 228_hx509_sel_yyerror (char *s) 229{ 230 if (_hx509_expr_input.error) 231 free(_hx509_expr_input.error); 232 233 _hx509_expr_input.error = strdup(s); 234} 235 236