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

Line Branch Exec Source
1
/*	$OpenBSD: parser.c,v 1.1 2015/07/21 04:06:04 yasuoka Exp $	*/
2
3
/*
4
 * Copyright (c) 2010 Reyk Floeter <reyk@vantronix.net>
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 <stdint.h>
22
#include <stdio.h>
23
#include <stdlib.h>
24
#include <string.h>
25
26
#include "parser.h"
27
28
enum token_type {
29
	NOTOKEN,
30
	KEYWORD,
31
	HOSTNAME,
32
	SECRET,
33
	USERNAME,
34
	PASSWORD,
35
	PORT,
36
	METHOD,
37
	NAS_PORT,
38
	ENDTOKEN
39
};
40
41
struct token {
42
	enum token_type		 type;
43
	const char		*keyword;
44
	int			 value;
45
	const struct token	*next;
46
};
47
48
static struct parse_result res;
49
50
static const struct token t_test[];
51
static const struct token t_secret[];
52
static const struct token t_username[];
53
static const struct token t_test_opts[];
54
static const struct token t_password[];
55
static const struct token t_port[];
56
static const struct token t_method[];
57
static const struct token t_nas_port[];
58
59
static const struct token t_main[] = {
60
	{ KEYWORD,	"test",		TEST,		t_test },
61
	{ ENDTOKEN,	"",		NONE,		NULL }
62
};
63
64
static const struct token t_test[] = {
65
	{ HOSTNAME,	"",		NONE,		t_secret },
66
	{ ENDTOKEN,	"",		NONE,		NULL }
67
};
68
69
static const struct token t_secret[] = {
70
	{ SECRET,	"",		NONE,		t_username },
71
	{ ENDTOKEN,	"",		NONE,		NULL }
72
};
73
74
static const struct token t_username[] = {
75
	{ USERNAME,	"",		NONE,		t_test_opts },
76
	{ ENDTOKEN,	"",		NONE,		NULL }
77
};
78
79
static const struct token t_test_opts[] = {
80
	{ NOTOKEN,	"",		NONE,		NULL },
81
	{ KEYWORD,	"password",	NONE,		t_password },
82
	{ KEYWORD,	"port",		NONE,		t_port },
83
	{ KEYWORD,	"method",	NONE,		t_method },
84
	{ KEYWORD,	"nas-port",	NONE,		t_nas_port },
85
	{ ENDTOKEN,	"",		NONE,		NULL }
86
};
87
88
static const struct token t_password[] = {
89
	{ PASSWORD,	"",		NONE,		t_test_opts },
90
	{ ENDTOKEN,	"",		NONE,		NULL }
91
};
92
93
static const struct token t_port[] = {
94
	{ PORT,		"",		NONE,		t_test_opts },
95
	{ ENDTOKEN,	"",		NONE,		NULL }
96
};
97
98
static const struct token t_method[] = {
99
	{ METHOD,	"",		NONE,		t_test_opts },
100
	{ ENDTOKEN,	"",		NONE,		NULL }
101
};
102
103
static const struct token t_nas_port[] = {
104
	{ NAS_PORT,	"",		NONE,		t_test_opts },
105
	{ ENDTOKEN,	"",		NONE,		NULL }
106
};
107
108
109
static const struct token	*match_token(char *, const struct token []);
110
static void			 show_valid_args(const struct token []);
111
112
struct parse_result *
113
parse(int argc, char *argv[])
114
{
115
	const struct token	*table = t_main;
116
	const struct token	*match;
117
118
	bzero(&res, sizeof(res));
119
120
	while (argc >= 0) {
121
		if ((match = match_token(argv[0], table)) == NULL) {
122
			fprintf(stderr, "valid commands/args:\n");
123
			show_valid_args(table);
124
			return (NULL);
125
		}
126
127
		argc--;
128
		argv++;
129
130
		if (match->type == NOTOKEN || match->next == NULL)
131
			break;
132
133
		table = match->next;
134
	}
135
136
	if (argc > 0) {
137
		fprintf(stderr, "superfluous argument: %s\n", argv[0]);
138
		return (NULL);
139
	}
140
141
	return (&res);
142
}
143
144
static const struct token *
145
match_token(char *word, const struct token table[])
146
{
147
	u_int			 i, match = 0;
148
	const struct token	*t = NULL;
149
	long long		 num;
150
	const char		*errstr;
151
152
	for (i = 0; table[i].type != ENDTOKEN; i++) {
153
		switch (table[i].type) {
154
		case NOTOKEN:
155
			if (word == NULL || strlen(word) == 0) {
156
				match++;
157
				t = &table[i];
158
			}
159
			break;
160
		case KEYWORD:
161
			if (word != NULL && strncmp(word, table[i].keyword,
162
			    strlen(word)) == 0) {
163
				match++;
164
				t = &table[i];
165
				if (t->value)
166
					res.action = t->value;
167
			}
168
			break;
169
		case HOSTNAME:
170
			if (word == NULL)
171
				break;
172
			match++;
173
			res.hostname = word;
174
			t = &table[i];
175
			break;
176
		case SECRET:
177
			if (word == NULL)
178
				break;
179
			match++;
180
			res.secret = word;
181
			t = &table[i];
182
			break;
183
		case USERNAME:
184
			if (word == NULL)
185
				break;
186
			match++;
187
			res.username = word;
188
			t = &table[i];
189
			break;
190
		case PASSWORD:
191
			if (word == NULL)
192
				break;
193
			match++;
194
			res.password = word;
195
			t = &table[i];
196
			break;
197
		case PORT:
198
			if (word == NULL)
199
				break;
200
			num = strtonum(word, 1, UINT16_MAX, &errstr);
201
			if (errstr != NULL) {
202
				fprintf(stderr,
203
				    "invalid argument: %s is %s for \"port\"\n",
204
				    word, errstr);
205
				return (NULL);
206
			}
207
			match++;
208
			res.port = num;
209
			t = &table[i];
210
			break;
211
		case METHOD:
212
			if (word == NULL)
213
				break;
214
			if (strcasecmp(word, "pap") == 0)
215
				res.auth_method = PAP;
216
			else if (strcasecmp(word, "chap") == 0)
217
				res.auth_method = CHAP;
218
			else if (strcasecmp(word, "mschapv2") == 0)
219
				res.auth_method = MSCHAPV2;
220
			else {
221
				fprintf(stderr,
222
				    "invalid argument: %s for \"method\"\n",
223
				    word);
224
				return (NULL);
225
			}
226
			match++;
227
			t = &table[i];
228
			break;
229
		case NAS_PORT:
230
			if (word == NULL)
231
				break;
232
			num = strtonum(word, 0, 65535, &errstr);
233
			if (errstr != NULL) {
234
				fprintf(stderr,
235
				    "invalid argument: %s is %s for "
236
				    "\"nas-port\"\n", word, errstr);
237
				return (NULL);
238
			}
239
			match++;
240
			res.nas_port = num;
241
			t = &table[i];
242
			break;
243
		case ENDTOKEN:
244
			break;
245
		}
246
	}
247
248
	if (match != 1) {
249
		if (word == NULL)
250
			fprintf(stderr, "missing argument:\n");
251
		else if (match > 1)
252
			fprintf(stderr, "ambiguous argument: %s\n", word);
253
		else if (match < 1)
254
			fprintf(stderr, "unknown argument: %s\n", word);
255
		return (NULL);
256
	}
257
258
	return (t);
259
}
260
261
static void
262
show_valid_args(const struct token table[])
263
{
264
	int	i;
265
266
	for (i = 0; table[i].type != ENDTOKEN; i++) {
267
		switch (table[i].type) {
268
		case NOTOKEN:
269
			fprintf(stderr, "  <cr>\n");
270
			break;
271
		case KEYWORD:
272
			fprintf(stderr, "  %s\n", table[i].keyword);
273
			break;
274
		case HOSTNAME:
275
			fprintf(stderr, "  <hostname>\n");
276
			break;
277
		case SECRET:
278
			fprintf(stderr, "  <radius secret>\n");
279
			break;
280
		case USERNAME:
281
			fprintf(stderr, "  <username>\n");
282
			break;
283
		case PASSWORD:
284
			fprintf(stderr, "  <password>\n");
285
			break;
286
		case PORT:
287
			fprintf(stderr, "  <port number>\n");
288
			break;
289
		case METHOD:
290
			fprintf(stderr, "  <auth method (pap, chap, "
291
			    "mschapv2)>\n");
292
			break;
293
		case NAS_PORT:
294
			fprintf(stderr, "  <nas-port (0-65535)>\n");
295
			break;
296
		case ENDTOKEN:
297
			break;
298
		}
299
	}
300
}