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