1 /* $OpenBSD: parser.c,v 1.19 2020/03/22 15:59:05 tobhe Exp $ */ 2 3 /* 4 * Copyright (c) 2010-2013 Reyk Floeter <reyk@openbsd.org> 5 * Copyright (c) 2004 Esben Norby <norby@openbsd.org> 6 * Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org> 7 * 8 * Permission to use, copy, modify, and distribute this software for any 9 * purpose with or without fee is hereby granted, provided that the above 10 * copyright notice and this permission notice appear in all copies. 11 * 12 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 13 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 14 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 15 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 16 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 17 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 18 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 19 */ 20 21 #include <sys/types.h> 22 #include <sys/socket.h> 23 #include <sys/queue.h> 24 #include <sys/tree.h> 25 26 #include <err.h> 27 #include <errno.h> 28 #include <limits.h> 29 #include <stdio.h> 30 #include <stdlib.h> 31 #include <string.h> 32 #include <event.h> 33 #include <netdb.h> 34 35 #include "iked.h" 36 #include "parser.h" 37 38 enum token_type { 39 NOTOKEN, 40 ENDTOKEN, 41 KEYWORD, 42 PATH, 43 CANAME, 44 PEER, 45 ADDRESS, 46 FQDN, 47 PASSWORD, 48 IKEID 49 }; 50 51 struct token { 52 enum token_type type; 53 const char *keyword; 54 int value; 55 const struct token *next; 56 }; 57 58 static const struct token t_main[]; 59 static const struct token t_reset[]; 60 static const struct token t_reset_id[]; 61 static const struct token t_log[]; 62 static const struct token t_load[]; 63 static const struct token t_ca[]; 64 static const struct token t_ca_pass[]; 65 static const struct token t_ca_pass_val[]; 66 static const struct token t_ca_export[]; 67 static const struct token t_ca_ex_peer[]; 68 static const struct token t_ca_ex_pass[]; 69 static const struct token t_ca_modifiers[]; 70 static const struct token t_ca_cert[]; 71 static const struct token t_ca_cert_extusage[]; 72 static const struct token t_ca_cert_modifiers[]; 73 static const struct token t_ca_key[]; 74 static const struct token t_ca_key_modifiers[]; 75 static const struct token t_ca_key_path[]; 76 static const struct token t_show[]; 77 static const struct token t_show_ca[]; 78 static const struct token t_show_ca_modifiers[]; 79 static const struct token t_show_ca_cert[]; 80 static const struct token t_opt_path[]; 81 82 static const struct token t_main[] = { 83 { KEYWORD, "active", ACTIVE, NULL }, 84 { KEYWORD, "passive", PASSIVE, NULL }, 85 { KEYWORD, "couple", COUPLE, NULL }, 86 { KEYWORD, "decouple", DECOUPLE, NULL }, 87 { KEYWORD, "load", LOAD, t_load }, 88 { KEYWORD, "log", NONE, t_log }, 89 { KEYWORD, "monitor", MONITOR, NULL }, 90 { KEYWORD, "reload", RELOAD, NULL }, 91 { KEYWORD, "reset", NONE, t_reset }, 92 { KEYWORD, "show", NONE, t_show }, 93 { KEYWORD, "ca", CA, t_ca }, 94 { ENDTOKEN, "", NONE, NULL } 95 }; 96 97 static const struct token t_log[] = { 98 { KEYWORD, "verbose", LOG_VERBOSE, NULL }, 99 { KEYWORD, "brief", LOG_BRIEF, NULL }, 100 { ENDTOKEN, "", NONE, NULL } 101 }; 102 103 static const struct token t_reset[] = { 104 { KEYWORD, "all", RESETALL, NULL }, 105 { KEYWORD, "ca", RESETCA, NULL }, 106 { KEYWORD, "policy", RESETPOLICY, NULL }, 107 { KEYWORD, "sa", RESETSA, NULL }, 108 { KEYWORD, "user", RESETUSER, NULL }, 109 { KEYWORD, "id", RESET_ID, t_reset_id }, 110 { ENDTOKEN, "", NONE, NULL } 111 }; 112 113 static const struct token t_reset_id[] = { 114 { IKEID, "", NONE, NULL }, 115 { ENDTOKEN, "", NONE, NULL } 116 }; 117 118 static const struct token t_load[] = { 119 { PATH, "", NONE, NULL }, 120 { ENDTOKEN, "", NONE, NULL } 121 }; 122 123 static const struct token t_ca[] = { 124 { CANAME, "", NONE, t_ca_modifiers }, 125 { ENDTOKEN, "", NONE, NULL }, 126 }; 127 128 static const struct token t_ca_modifiers[] = { 129 { KEYWORD, "create", CA_CREATE, t_ca_pass }, 130 { KEYWORD, "delete", CA_DELETE, NULL }, 131 { KEYWORD, "install", CA_INSTALL, t_opt_path }, 132 { KEYWORD, "certificate", CA_CERTIFICATE, t_ca_cert }, 133 { KEYWORD, "key", NONE, t_ca_key }, 134 { KEYWORD, "export", CA_EXPORT, t_ca_export }, 135 { ENDTOKEN, "", NONE, NULL } 136 }; 137 138 static const struct token t_ca_pass_val[] = { 139 { PASSWORD, "", NONE, NULL }, 140 { ENDTOKEN, "", NONE, NULL } 141 }; 142 143 static const struct token t_ca_pass[] = { 144 { NOTOKEN, "", NONE, NULL }, 145 { KEYWORD, "password", NONE, t_ca_pass_val }, 146 { ENDTOKEN, "", NONE, NULL } 147 }; 148 149 static const struct token t_ca_export[] = { 150 { NOTOKEN, "", NONE, NULL }, 151 { KEYWORD, "peer", NONE, t_ca_ex_peer }, 152 { KEYWORD, "password", NONE, t_ca_ex_pass }, 153 { ENDTOKEN, "", NONE, NULL } 154 }; 155 156 static const struct token t_ca_ex_peer[] = { 157 { PEER, "", NONE, t_ca_export }, 158 { ENDTOKEN, "", NONE, NULL } 159 }; 160 161 static const struct token t_ca_ex_pass[] = { 162 { PASSWORD, "", NONE, t_ca_export }, 163 { ENDTOKEN, "", NONE, NULL } 164 }; 165 166 static const struct token t_opt_path[] = { 167 { NOTOKEN, "", NONE, NULL }, 168 { PATH, "", NONE, NULL }, 169 { ENDTOKEN, "", NONE, NULL } 170 }; 171 172 static const struct token t_ca_cert[] = { 173 { ADDRESS, "", NONE, t_ca_cert_modifiers }, 174 { FQDN, "", NONE, t_ca_cert_modifiers }, 175 { ENDTOKEN, "", NONE, NULL } 176 }; 177 178 static const struct token t_ca_cert_modifiers[] = { 179 { KEYWORD, "create", CA_CERT_CREATE, t_ca_cert_extusage }, 180 { KEYWORD, "delete", CA_CERT_DELETE, NULL }, 181 { KEYWORD, "install", CA_CERT_INSTALL, t_opt_path }, 182 { KEYWORD, "export", CA_CERT_EXPORT, t_ca_export }, 183 { KEYWORD, "revoke", CA_CERT_REVOKE, NULL }, 184 { ENDTOKEN, "", NONE, NULL } 185 }; 186 187 static const struct token t_ca_cert_extusage[] = { 188 { NOTOKEN, "", NONE, NULL}, 189 { KEYWORD, "server", CA_SERVER, NULL }, 190 { KEYWORD, "client", CA_CLIENT, NULL }, 191 { KEYWORD, "ocsp", CA_OCSP, NULL }, 192 { ENDTOKEN, "", NONE, NULL }, 193 }; 194 195 static const struct token t_ca_key[] = { 196 { ADDRESS, "", NONE, t_ca_key_modifiers }, 197 { FQDN, "", NONE, t_ca_key_modifiers }, 198 { ENDTOKEN, "", NONE, NULL } 199 }; 200 201 static const struct token t_ca_key_modifiers[] = { 202 { KEYWORD, "create", CA_KEY_CREATE, NULL }, 203 { KEYWORD, "delete", CA_KEY_DELETE, NULL }, 204 { KEYWORD, "install", CA_KEY_INSTALL, t_opt_path }, 205 { KEYWORD, "import", CA_KEY_IMPORT, t_ca_key_path }, 206 { ENDTOKEN, "", NONE, NULL } 207 }; 208 209 static const struct token t_ca_key_path[] = { 210 { PATH, "", NONE, NULL }, 211 { PATH, "", NONE, NULL } 212 }; 213 214 static const struct token t_show[] = { 215 { KEYWORD, "ca", SHOW_CA, t_show_ca }, 216 { KEYWORD, "sa", SHOW_SA, NULL }, 217 { ENDTOKEN, "", NONE, NULL } 218 }; 219 220 static const struct token t_show_ca[] = { 221 { CANAME, "", NONE, t_show_ca_modifiers }, 222 { ENDTOKEN, "", NONE, NULL }, 223 }; 224 225 static const struct token t_show_ca_modifiers[] = { 226 { KEYWORD, "certificates", SHOW_CA_CERTIFICATES, t_show_ca_cert }, 227 { ENDTOKEN, "", NONE, NULL } 228 }; 229 230 static const struct token t_show_ca_cert[] = { 231 { NOTOKEN, "", NONE, NULL }, 232 { ADDRESS, "", NONE, NULL }, 233 { FQDN, "", NONE, NULL }, 234 { ENDTOKEN, "", NONE, NULL } 235 }; 236 237 static struct parse_result res; 238 239 const struct token *match_token(char *, const struct token []); 240 void show_valid_args(const struct token []); 241 int parse_addr(const char *); 242 243 struct parse_result * 244 parse(int argc, char *argv[]) 245 { 246 const struct token *table = t_main; 247 const struct token *match; 248 249 bzero(&res, sizeof(res)); 250 251 while (argc >= 0) { 252 if ((match = match_token(argv[0], table)) == NULL) { 253 fprintf(stderr, "valid commands/args:\n"); 254 show_valid_args(table); 255 return (NULL); 256 } 257 258 argc--; 259 argv++; 260 261 if (match->type == NOTOKEN || match->next == NULL) 262 break; 263 264 table = match->next; 265 } 266 267 if (argc > 0) { 268 fprintf(stderr, "superfluous argument: %s\n", argv[0]); 269 return (NULL); 270 } 271 272 return (&res); 273 } 274 275 int 276 parse_addr(const char *word) 277 { 278 struct addrinfo hints, *r; 279 280 bzero(&hints, sizeof(hints)); 281 hints.ai_socktype = SOCK_DGRAM; /* dummy */ 282 hints.ai_family = PF_UNSPEC; 283 hints.ai_flags = AI_NUMERICHOST; 284 if (getaddrinfo(word, "0", &hints, &r) == 0) { 285 freeaddrinfo(r); 286 return (0); 287 } 288 289 return (1); 290 } 291 292 293 const struct token * 294 match_token(char *word, const struct token table[]) 295 { 296 unsigned int i, match = 0; 297 const struct token *t = NULL; 298 299 for (i = 0; table[i].type != ENDTOKEN; i++) { 300 switch (table[i].type) { 301 case NOTOKEN: 302 if (word == NULL || strlen(word) == 0) { 303 match++; 304 t = &table[i]; 305 } 306 break; 307 case KEYWORD: 308 if (word != NULL && strncmp(word, table[i].keyword, 309 strlen(word)) == 0) { 310 match++; 311 t = &table[i]; 312 if (t->value) 313 res.action = t->value; 314 } 315 break; 316 case PATH: 317 if (!match && word != NULL && strlen(word) > 0) { 318 res.path = strdup(word); 319 match++; 320 t = &table[i]; 321 } 322 break; 323 case CANAME: 324 if (!match && word != NULL && strlen(word) > 0) { 325 res.caname = strdup(word); 326 match++; 327 t = &table[i]; 328 } 329 break; 330 case PEER: 331 if (!match && word != NULL && strlen(word) > 0) { 332 res.peer = strdup(word); 333 match++; 334 t = &table[i]; 335 } 336 break; 337 case ADDRESS: 338 case FQDN: 339 if (!match && word != NULL && strlen(word) > 0) { 340 res.host = strdup(word); 341 if (parse_addr(word) == 0) 342 res.htype = HOST_IPADDR; 343 else 344 res.htype = HOST_FQDN; 345 match++; 346 t = &table[i]; 347 } 348 break; 349 case PASSWORD: 350 if (!match && word != NULL && strlen(word) > 0) { 351 res.pass = strdup(word); 352 match++; 353 t = &table[i]; 354 } 355 break; 356 case IKEID: 357 if (!match && word != NULL && strlen(word) > 0) { 358 res.id = strdup(word); 359 match++; 360 t = &table[i]; 361 } 362 break; 363 case ENDTOKEN: 364 break; 365 } 366 } 367 368 if (match != 1) { 369 if (word == NULL) 370 fprintf(stderr, "missing argument:\n"); 371 else if (match > 1) 372 fprintf(stderr, "ambiguous argument: %s\n", word); 373 else if (match < 1) 374 fprintf(stderr, "unknown argument: %s\n", word); 375 return (NULL); 376 } 377 378 return (t); 379 } 380 381 void 382 show_valid_args(const struct token table[]) 383 { 384 int i; 385 386 for (i = 0; table[i].type != ENDTOKEN; i++) { 387 switch (table[i].type) { 388 case NOTOKEN: 389 fprintf(stderr, " <cr>\n"); 390 break; 391 case KEYWORD: 392 fprintf(stderr, " %s\n", table[i].keyword); 393 break; 394 case PATH: 395 fprintf(stderr, " <path>\n"); 396 break; 397 case CANAME: 398 fprintf(stderr, " <caname>\n"); 399 break; 400 case PASSWORD: 401 fprintf(stderr, " <password>\n"); 402 break; 403 case PEER: 404 fprintf(stderr, " <peer>\n"); 405 break; 406 case ADDRESS: 407 fprintf(stderr, " <ipaddr>\n"); 408 break; 409 case FQDN: 410 fprintf(stderr, " <fqdn>\n"); 411 break; 412 case IKEID: 413 fprintf(stderr, " <ikeid>\n"); 414 break; 415 case ENDTOKEN: 416 break; 417 } 418 } 419 } 420