1 /* $OpenBSD: parser.c,v 1.20 2021/11/21 22:44:08 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 { KEYWORD, "certstore", SHOW_CERTSTORE,NULL }, 218 { ENDTOKEN, "", NONE, NULL } 219 }; 220 221 static const struct token t_show_ca[] = { 222 { CANAME, "", NONE, t_show_ca_modifiers }, 223 { ENDTOKEN, "", NONE, NULL }, 224 }; 225 226 static const struct token t_show_ca_modifiers[] = { 227 { KEYWORD, "certificates", SHOW_CA_CERTIFICATES, t_show_ca_cert }, 228 { ENDTOKEN, "", NONE, NULL } 229 }; 230 231 static const struct token t_show_ca_cert[] = { 232 { NOTOKEN, "", NONE, NULL }, 233 { ADDRESS, "", NONE, NULL }, 234 { FQDN, "", NONE, NULL }, 235 { ENDTOKEN, "", NONE, NULL } 236 }; 237 238 static struct parse_result res; 239 240 const struct token *match_token(char *, const struct token []); 241 void show_valid_args(const struct token []); 242 int parse_addr(const char *); 243 244 struct parse_result * 245 parse(int argc, char *argv[]) 246 { 247 const struct token *table = t_main; 248 const struct token *match; 249 250 bzero(&res, sizeof(res)); 251 252 while (argc >= 0) { 253 if ((match = match_token(argv[0], table)) == NULL) { 254 fprintf(stderr, "valid commands/args:\n"); 255 show_valid_args(table); 256 return (NULL); 257 } 258 259 argc--; 260 argv++; 261 262 if (match->type == NOTOKEN || match->next == NULL) 263 break; 264 265 table = match->next; 266 } 267 268 if (argc > 0) { 269 fprintf(stderr, "superfluous argument: %s\n", argv[0]); 270 return (NULL); 271 } 272 273 return (&res); 274 } 275 276 int 277 parse_addr(const char *word) 278 { 279 struct addrinfo hints, *r; 280 281 bzero(&hints, sizeof(hints)); 282 hints.ai_socktype = SOCK_DGRAM; /* dummy */ 283 hints.ai_family = PF_UNSPEC; 284 hints.ai_flags = AI_NUMERICHOST; 285 if (getaddrinfo(word, "0", &hints, &r) == 0) { 286 freeaddrinfo(r); 287 return (0); 288 } 289 290 return (1); 291 } 292 293 294 const struct token * 295 match_token(char *word, const struct token table[]) 296 { 297 unsigned int i, match = 0; 298 const struct token *t = NULL; 299 300 for (i = 0; table[i].type != ENDTOKEN; i++) { 301 switch (table[i].type) { 302 case NOTOKEN: 303 if (word == NULL || strlen(word) == 0) { 304 match++; 305 t = &table[i]; 306 } 307 break; 308 case KEYWORD: 309 if (word != NULL && strncmp(word, table[i].keyword, 310 strlen(word)) == 0) { 311 match++; 312 t = &table[i]; 313 if (t->value) 314 res.action = t->value; 315 } 316 break; 317 case PATH: 318 if (!match && word != NULL && strlen(word) > 0) { 319 res.path = strdup(word); 320 match++; 321 t = &table[i]; 322 } 323 break; 324 case CANAME: 325 if (!match && word != NULL && strlen(word) > 0) { 326 res.caname = strdup(word); 327 match++; 328 t = &table[i]; 329 } 330 break; 331 case PEER: 332 if (!match && word != NULL && strlen(word) > 0) { 333 res.peer = strdup(word); 334 match++; 335 t = &table[i]; 336 } 337 break; 338 case ADDRESS: 339 case FQDN: 340 if (!match && word != NULL && strlen(word) > 0) { 341 res.host = strdup(word); 342 if (parse_addr(word) == 0) 343 res.htype = HOST_IPADDR; 344 else 345 res.htype = HOST_FQDN; 346 match++; 347 t = &table[i]; 348 } 349 break; 350 case PASSWORD: 351 if (!match && word != NULL && strlen(word) > 0) { 352 res.pass = strdup(word); 353 match++; 354 t = &table[i]; 355 } 356 break; 357 case IKEID: 358 if (!match && word != NULL && strlen(word) > 0) { 359 res.id = strdup(word); 360 match++; 361 t = &table[i]; 362 } 363 break; 364 case ENDTOKEN: 365 break; 366 } 367 } 368 369 if (match != 1) { 370 if (word == NULL) 371 fprintf(stderr, "missing argument:\n"); 372 else if (match > 1) 373 fprintf(stderr, "ambiguous argument: %s\n", word); 374 else if (match < 1) 375 fprintf(stderr, "unknown argument: %s\n", word); 376 return (NULL); 377 } 378 379 return (t); 380 } 381 382 void 383 show_valid_args(const struct token table[]) 384 { 385 int i; 386 387 for (i = 0; table[i].type != ENDTOKEN; i++) { 388 switch (table[i].type) { 389 case NOTOKEN: 390 fprintf(stderr, " <cr>\n"); 391 break; 392 case KEYWORD: 393 fprintf(stderr, " %s\n", table[i].keyword); 394 break; 395 case PATH: 396 fprintf(stderr, " <path>\n"); 397 break; 398 case CANAME: 399 fprintf(stderr, " <caname>\n"); 400 break; 401 case PASSWORD: 402 fprintf(stderr, " <password>\n"); 403 break; 404 case PEER: 405 fprintf(stderr, " <peer>\n"); 406 break; 407 case ADDRESS: 408 fprintf(stderr, " <ipaddr>\n"); 409 break; 410 case FQDN: 411 fprintf(stderr, " <fqdn>\n"); 412 break; 413 case IKEID: 414 fprintf(stderr, " <ikeid>\n"); 415 break; 416 case ENDTOKEN: 417 break; 418 } 419 } 420 } 421