xref: /openbsd/usr.sbin/ikectl/parser.c (revision b41cc0c8)
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 *
parse(int argc,char * argv[])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
parse_addr(const char * word)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 *
match_token(char * word,const struct token table[])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
show_valid_args(const struct token table[])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