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