GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: usr.sbin/ikectl/parser.c Lines: 0 74 0.0 %
Date: 2017-11-07 Branches: 0 72 0.0 %

Line Branch Exec Source
1
/*	$OpenBSD: parser.c,v 1.16 2016/06/14 13:45:40 reyk 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
};
49
50
struct token {
51
	enum token_type		 type;
52
	const char		*keyword;
53
	int			 value;
54
	const struct token	*next;
55
};
56
57
static const struct token t_main[];
58
static const struct token t_reset[];
59
static const struct token t_log[];
60
static const struct token t_load[];
61
static const struct token t_ca[];
62
static const struct token t_ca_pass[];
63
static const struct token t_ca_pass_val[];
64
static const struct token t_ca_export[];
65
static const struct token t_ca_ex_peer[];
66
static const struct token t_ca_ex_pass[];
67
static const struct token t_ca_modifiers[];
68
static const struct token t_ca_cert[];
69
static const struct token t_ca_cert_extusage[];
70
static const struct token t_ca_cert_modifiers[];
71
static const struct token t_ca_key[];
72
static const struct token t_ca_key_modifiers[];
73
static const struct token t_ca_key_path[];
74
static const struct token t_show[];
75
static const struct token t_show_ca[];
76
static const struct token t_show_ca_modifiers[];
77
static const struct token t_show_ca_cert[];
78
static const struct token t_opt_path[];
79
80
static const struct token t_main[] = {
81
	{ KEYWORD,	"active",	ACTIVE,		NULL },
82
	{ KEYWORD,	"passive",	PASSIVE,	NULL },
83
	{ KEYWORD,	"couple",	COUPLE,		NULL },
84
	{ KEYWORD,	"decouple",	DECOUPLE,	NULL },
85
	{ KEYWORD,	"load",		LOAD,		t_load },
86
	{ KEYWORD,	"log",		NONE,		t_log },
87
	{ KEYWORD,	"monitor",	MONITOR,	NULL },
88
	{ KEYWORD,	"reload",	RELOAD,		NULL },
89
	{ KEYWORD,	"reset",	NONE,		t_reset },
90
	{ KEYWORD,	"show",		NONE,		t_show },
91
	{ KEYWORD,	"ca",		CA,		t_ca },
92
	{ ENDTOKEN,	"",		NONE,		NULL }
93
};
94
95
static const struct token t_log[] = {
96
	{ KEYWORD,	"verbose",	LOG_VERBOSE,	NULL },
97
	{ KEYWORD,	"brief",	LOG_BRIEF,	NULL },
98
	{ ENDTOKEN,	"",		NONE,		NULL }
99
};
100
101
static const struct token t_reset[] = {
102
	{ KEYWORD,	"all",		RESETALL,	NULL },
103
	{ KEYWORD,	"ca",		RESETCA,	NULL },
104
	{ KEYWORD,	"policy",	RESETPOLICY,	NULL },
105
	{ KEYWORD,	"sa",		RESETSA,	NULL },
106
	{ KEYWORD,	"user",		RESETUSER,	NULL },
107
	{ ENDTOKEN,	"",		NONE,		NULL }
108
};
109
110
static const struct token t_load[] = {
111
	{ PATH,		"",		NONE,		NULL },
112
	{ ENDTOKEN,	"",		NONE,		NULL }
113
};
114
115
static const struct token t_ca[] = {
116
	{ CANAME,	"",		NONE,		t_ca_modifiers },
117
	{ ENDTOKEN,	"",		NONE,		NULL },
118
};
119
120
static const struct token t_ca_modifiers[] = {
121
	{ KEYWORD,	"create",	CA_CREATE,	t_ca_pass },
122
	{ KEYWORD,	"delete",	CA_DELETE,	NULL },
123
	{ KEYWORD,	"install",	CA_INSTALL,	t_opt_path },
124
	{ KEYWORD,	"certificate",	CA_CERTIFICATE,	t_ca_cert },
125
	{ KEYWORD,	"key",		NONE,		t_ca_key },
126
	{ KEYWORD,	"export",	CA_EXPORT,	t_ca_export },
127
	{ ENDTOKEN,	"",		NONE,		NULL }
128
};
129
130
static const struct token t_ca_pass_val[] = {
131
	{ PASSWORD,	"",		NONE,		NULL },
132
	{ ENDTOKEN,	"",		NONE,		NULL }
133
};
134
135
static const struct token t_ca_pass[] = {
136
	{ NOTOKEN,	"",		NONE,		NULL },
137
	{ KEYWORD,	"password",	NONE,		t_ca_pass_val },
138
	{ ENDTOKEN,	"",		NONE,		NULL }
139
};
140
141
static const struct token t_ca_export[] = {
142
	{ NOTOKEN,	"",		NONE,		NULL },
143
	{ KEYWORD,	"peer",		NONE,		t_ca_ex_peer },
144
	{ KEYWORD,	"password",	NONE,		t_ca_ex_pass },
145
	{ ENDTOKEN,	"",		NONE,		NULL }
146
};
147
148
static const struct token t_ca_ex_peer[] = {
149
	{ PEER,		"",		NONE,		t_ca_export },
150
	{ ENDTOKEN,	"",		NONE,		NULL }
151
};
152
153
static const struct token t_ca_ex_pass[] = {
154
	{ PASSWORD,	"",		NONE,		t_ca_export },
155
	{ ENDTOKEN,	"",		NONE,		NULL }
156
};
157
158
static const struct token t_opt_path[] = {
159
	{ NOTOKEN,	"",		NONE,		NULL },
160
	{ PATH,		"",		NONE,		NULL },
161
	{ ENDTOKEN,	"",		NONE,		NULL }
162
};
163
164
static const struct token t_ca_cert[] = {
165
	{ ADDRESS,	"",		NONE,		t_ca_cert_modifiers },
166
	{ FQDN,		"",		NONE,		t_ca_cert_modifiers },
167
	{ ENDTOKEN,	"",		NONE,		NULL }
168
};
169
170
static const struct token t_ca_cert_modifiers[] = {
171
	{ KEYWORD,	"create",	CA_CERT_CREATE,		t_ca_cert_extusage },
172
	{ KEYWORD,	"delete",	CA_CERT_DELETE,		NULL },
173
	{ KEYWORD,	"install",	CA_CERT_INSTALL,	t_opt_path },
174
	{ KEYWORD,	"export",	CA_CERT_EXPORT,		t_ca_export },
175
	{ KEYWORD,	"revoke",	CA_CERT_REVOKE,		NULL },
176
	{ ENDTOKEN,	"",		NONE,			NULL }
177
};
178
179
static const struct token t_ca_cert_extusage[] = {
180
	{ NOTOKEN,	"",		NONE,		NULL},
181
	{ KEYWORD,	"server",	CA_SERVER,	NULL },
182
	{ KEYWORD,	"client",	CA_CLIENT,	NULL },
183
	{ KEYWORD,	"ocsp",		CA_OCSP,	NULL },
184
	{ ENDTOKEN,	"",		NONE,		NULL },
185
};
186
187
static const struct token t_ca_key[] = {
188
	{ ADDRESS,	"",		NONE,		t_ca_key_modifiers },
189
	{ FQDN,		"",		NONE,		t_ca_key_modifiers },
190
	{ ENDTOKEN,	"",		NONE,		NULL }
191
};
192
193
static const struct token t_ca_key_modifiers[] = {
194
	{ KEYWORD,	"create",	CA_KEY_CREATE,		NULL },
195
	{ KEYWORD,	"delete",	CA_KEY_DELETE,		NULL },
196
	{ KEYWORD,	"install",	CA_KEY_INSTALL,		t_opt_path },
197
	{ KEYWORD,	"import",	CA_KEY_IMPORT,		t_ca_key_path },
198
	{ ENDTOKEN,	"",		NONE,			NULL }
199
};
200
201
static const struct token t_ca_key_path[] = {
202
	{ PATH,		"",		NONE,		NULL },
203
	{ PATH,		"",		NONE,		NULL }
204
};
205
206
static const struct token t_show[] = {
207
	{ KEYWORD,	"ca",		SHOW_CA,	t_show_ca },
208
	{ ENDTOKEN,	"",		NONE,		NULL }
209
};
210
211
static const struct token t_show_ca[] = {
212
	{ CANAME,	"",		NONE,		t_show_ca_modifiers },
213
	{ ENDTOKEN,	"",		NONE,		NULL },
214
};
215
216
static const struct token t_show_ca_modifiers[] = {
217
	{ KEYWORD,	"certificates",	SHOW_CA_CERTIFICATES,	t_show_ca_cert },
218
	{ ENDTOKEN,	"",		NONE,			NULL }
219
};
220
221
static const struct token t_show_ca_cert[] = {
222
	{ NOTOKEN,	"",		NONE,		NULL },
223
	{ ADDRESS,	"",		NONE,		NULL },
224
	{ FQDN,		"",		NONE,		NULL },
225
	{ ENDTOKEN,	"",		NONE,		NULL }
226
};
227
228
static struct parse_result	 res;
229
230
const struct token		*match_token(char *, const struct token []);
231
void				 show_valid_args(const struct token []);
232
int				 parse_addr(const char *);
233
234
struct parse_result *
235
parse(int argc, char *argv[])
236
{
237
	const struct token	*table = t_main;
238
	const struct token	*match;
239
240
	bzero(&res, sizeof(res));
241
242
	while (argc >= 0) {
243
		if ((match = match_token(argv[0], table)) == NULL) {
244
			fprintf(stderr, "valid commands/args:\n");
245
			show_valid_args(table);
246
			return (NULL);
247
		}
248
249
		argc--;
250
		argv++;
251
252
		if (match->type == NOTOKEN || match->next == NULL)
253
			break;
254
255
		table = match->next;
256
	}
257
258
	if (argc > 0) {
259
		fprintf(stderr, "superfluous argument: %s\n", argv[0]);
260
		return (NULL);
261
	}
262
263
	return (&res);
264
}
265
266
int
267
parse_addr(const char *word)
268
{
269
	struct addrinfo hints, *r;
270
271
	bzero(&hints, sizeof(hints));
272
	hints.ai_socktype = SOCK_DGRAM; /* dummy */
273
	hints.ai_family = PF_UNSPEC;
274
	hints.ai_flags = AI_NUMERICHOST;
275
	if (getaddrinfo(word, "0", &hints, &r) == 0) {
276
		return (0);
277
	}
278
279
	return (1);
280
}
281
282
283
const struct token *
284
match_token(char *word, const struct token table[])
285
{
286
	unsigned int		 i, match = 0;
287
	const struct token	*t = NULL;
288
289
	for (i = 0; table[i].type != ENDTOKEN; i++) {
290
		switch (table[i].type) {
291
		case NOTOKEN:
292
			if (word == NULL || strlen(word) == 0) {
293
				match++;
294
				t = &table[i];
295
			}
296
			break;
297
		case KEYWORD:
298
			if (word != NULL && strncmp(word, table[i].keyword,
299
			    strlen(word)) == 0) {
300
				match++;
301
				t = &table[i];
302
				if (t->value)
303
					res.action = t->value;
304
			}
305
			break;
306
		case PATH:
307
			if (!match && word != NULL && strlen(word) > 0) {
308
				res.path = strdup(word);
309
				match++;
310
				t = &table[i];
311
			}
312
			break;
313
		case CANAME:
314
			if (!match && word != NULL && strlen(word) > 0) {
315
				res.caname = strdup(word);
316
				match++;
317
				t = &table[i];
318
			}
319
			break;
320
		case PEER:
321
			if (!match && word != NULL && strlen(word) > 0) {
322
				res.peer = strdup(word);
323
				match++;
324
				t = &table[i];
325
			}
326
			break;
327
		case ADDRESS:
328
		case FQDN:
329
			if (!match && word != NULL && strlen(word) > 0) {
330
				parse_addr(word);
331
				res.host = strdup(word);
332
				if (parse_addr(word) == 0)
333
					res.htype = HOST_IPADDR;
334
				else
335
					res.htype = HOST_FQDN;
336
				match++;
337
				t = &table[i];
338
			}
339
			break;
340
		case PASSWORD:
341
			if (!match && word != NULL && strlen(word) > 0) {
342
				res.pass = strdup(word);
343
				match++;
344
				t = &table[i];
345
			}
346
			break;
347
		case ENDTOKEN:
348
			break;
349
		}
350
	}
351
352
	if (match != 1) {
353
		if (word == NULL)
354
			fprintf(stderr, "missing argument:\n");
355
		else if (match > 1)
356
			fprintf(stderr, "ambiguous argument: %s\n", word);
357
		else if (match < 1)
358
			fprintf(stderr, "unknown argument: %s\n", word);
359
		return (NULL);
360
	}
361
362
	return (t);
363
}
364
365
void
366
show_valid_args(const struct token table[])
367
{
368
	int	i;
369
370
	for (i = 0; table[i].type != ENDTOKEN; i++) {
371
		switch (table[i].type) {
372
		case NOTOKEN:
373
			fprintf(stderr, "  <cr>\n");
374
			break;
375
		case KEYWORD:
376
			fprintf(stderr, "  %s\n", table[i].keyword);
377
			break;
378
		case PATH:
379
			fprintf(stderr, "  <path>\n");
380
			break;
381
		case CANAME:
382
			fprintf(stderr, "  <caname>\n");
383
			break;
384
		case PASSWORD:
385
			fprintf(stderr, "  <password>\n");
386
			break;
387
		case PEER:
388
			fprintf(stderr, "  <peer>\n");
389
			break;
390
		case ADDRESS:
391
			fprintf(stderr, "  <ipaddr>\n");
392
			break;
393
		case FQDN:
394
			fprintf(stderr, "  <fqdn>\n");
395
			break;
396
		case ENDTOKEN:
397
			break;
398
		}
399
	}
400
}