summaryrefslogtreecommitdiffstats
path: root/usr.sbin/radiusctl/parser.c
diff options
context:
space:
mode:
authoryasuoka <yasuoka@openbsd.org>2015-07-21 04:06:04 +0000
committeryasuoka <yasuoka@openbsd.org>2015-07-21 04:06:04 +0000
commita7ca44b834e2b4e6e0c6ceff73a2050ac81b31a9 (patch)
treea1ae9ded5847cfc9d37dadade2dcbd606cc211b0 /usr.sbin/radiusctl/parser.c
parentwhitespace (diff)
downloadwireguard-openbsd-a7ca44b834e2b4e6e0c6ceff73a2050ac81b31a9.tar.xz
wireguard-openbsd-a7ca44b834e2b4e6e0c6ceff73a2050ac81b31a9.zip
Add radiusd(8) and radiusctl(8). They are WIP. radiusd(8) is a RADIUS
server and radiusctl(8) is to control the server. radiusd(8) currently supports bsdauth and radius (upstream radius servers) as authentication backends. fixes from jsg blambert ok deraadt
Diffstat (limited to 'usr.sbin/radiusctl/parser.c')
-rw-r--r--usr.sbin/radiusctl/parser.c300
1 files changed, 300 insertions, 0 deletions
diff --git a/usr.sbin/radiusctl/parser.c b/usr.sbin/radiusctl/parser.c
new file mode 100644
index 00000000000..b666206f616
--- /dev/null
+++ b/usr.sbin/radiusctl/parser.c
@@ -0,0 +1,300 @@
+/* $OpenBSD: parser.c,v 1.1 2015/07/21 04:06:04 yasuoka Exp $ */
+
+/*
+ * Copyright (c) 2010 Reyk Floeter <reyk@vantronix.net>
+ * Copyright (c) 2004 Esben Norby <norby@openbsd.org>
+ * Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "parser.h"
+
+enum token_type {
+ NOTOKEN,
+ KEYWORD,
+ HOSTNAME,
+ SECRET,
+ USERNAME,
+ PASSWORD,
+ PORT,
+ METHOD,
+ NAS_PORT,
+ ENDTOKEN
+};
+
+struct token {
+ enum token_type type;
+ const char *keyword;
+ int value;
+ const struct token *next;
+};
+
+static struct parse_result res;
+
+static const struct token t_test[];
+static const struct token t_secret[];
+static const struct token t_username[];
+static const struct token t_test_opts[];
+static const struct token t_password[];
+static const struct token t_port[];
+static const struct token t_method[];
+static const struct token t_nas_port[];
+
+static const struct token t_main[] = {
+ { KEYWORD, "test", TEST, t_test },
+ { ENDTOKEN, "", NONE, NULL }
+};
+
+static const struct token t_test[] = {
+ { HOSTNAME, "", NONE, t_secret },
+ { ENDTOKEN, "", NONE, NULL }
+};
+
+static const struct token t_secret[] = {
+ { SECRET, "", NONE, t_username },
+ { ENDTOKEN, "", NONE, NULL }
+};
+
+static const struct token t_username[] = {
+ { USERNAME, "", NONE, t_test_opts },
+ { ENDTOKEN, "", NONE, NULL }
+};
+
+static const struct token t_test_opts[] = {
+ { NOTOKEN, "", NONE, NULL },
+ { KEYWORD, "password", NONE, t_password },
+ { KEYWORD, "port", NONE, t_port },
+ { KEYWORD, "method", NONE, t_method },
+ { KEYWORD, "nas-port", NONE, t_nas_port },
+ { ENDTOKEN, "", NONE, NULL }
+};
+
+static const struct token t_password[] = {
+ { PASSWORD, "", NONE, t_test_opts },
+ { ENDTOKEN, "", NONE, NULL }
+};
+
+static const struct token t_port[] = {
+ { PORT, "", NONE, t_test_opts },
+ { ENDTOKEN, "", NONE, NULL }
+};
+
+static const struct token t_method[] = {
+ { METHOD, "", NONE, t_test_opts },
+ { ENDTOKEN, "", NONE, NULL }
+};
+
+static const struct token t_nas_port[] = {
+ { NAS_PORT, "", NONE, t_test_opts },
+ { ENDTOKEN, "", NONE, NULL }
+};
+
+
+static const struct token *match_token(char *, const struct token []);
+static void show_valid_args(const struct token []);
+
+struct parse_result *
+parse(int argc, char *argv[])
+{
+ const struct token *table = t_main;
+ const struct token *match;
+
+ bzero(&res, sizeof(res));
+
+ while (argc >= 0) {
+ if ((match = match_token(argv[0], table)) == NULL) {
+ fprintf(stderr, "valid commands/args:\n");
+ show_valid_args(table);
+ return (NULL);
+ }
+
+ argc--;
+ argv++;
+
+ if (match->type == NOTOKEN || match->next == NULL)
+ break;
+
+ table = match->next;
+ }
+
+ if (argc > 0) {
+ fprintf(stderr, "superfluous argument: %s\n", argv[0]);
+ return (NULL);
+ }
+
+ return (&res);
+}
+
+static const struct token *
+match_token(char *word, const struct token table[])
+{
+ u_int i, match = 0;
+ const struct token *t = NULL;
+ long long num;
+ const char *errstr;
+
+ for (i = 0; table[i].type != ENDTOKEN; i++) {
+ switch (table[i].type) {
+ case NOTOKEN:
+ if (word == NULL || strlen(word) == 0) {
+ match++;
+ t = &table[i];
+ }
+ break;
+ case KEYWORD:
+ if (word != NULL && strncmp(word, table[i].keyword,
+ strlen(word)) == 0) {
+ match++;
+ t = &table[i];
+ if (t->value)
+ res.action = t->value;
+ }
+ break;
+ case HOSTNAME:
+ if (word == NULL)
+ break;
+ match++;
+ res.hostname = word;
+ t = &table[i];
+ break;
+ case SECRET:
+ if (word == NULL)
+ break;
+ match++;
+ res.secret = word;
+ t = &table[i];
+ break;
+ case USERNAME:
+ if (word == NULL)
+ break;
+ match++;
+ res.username = word;
+ t = &table[i];
+ break;
+ case PASSWORD:
+ if (word == NULL)
+ break;
+ match++;
+ res.password = word;
+ t = &table[i];
+ break;
+ case PORT:
+ if (word == NULL)
+ break;
+ num = strtonum(word, 1, UINT16_MAX, &errstr);
+ if (errstr != NULL) {
+ fprintf(stderr,
+ "invalid argument: %s is %s for \"port\"\n",
+ word, errstr);
+ return (NULL);
+ }
+ match++;
+ res.port = num;
+ t = &table[i];
+ break;
+ case METHOD:
+ if (word == NULL)
+ break;
+ if (strcasecmp(word, "pap") == 0)
+ res.auth_method = PAP;
+ else if (strcasecmp(word, "chap") == 0)
+ res.auth_method = CHAP;
+ else if (strcasecmp(word, "mschapv2") == 0)
+ res.auth_method = MSCHAPV2;
+ else {
+ fprintf(stderr,
+ "invalid argument: %s for \"method\"\n",
+ word);
+ return (NULL);
+ }
+ match++;
+ t = &table[i];
+ break;
+ case NAS_PORT:
+ if (word == NULL)
+ break;
+ num = strtonum(word, 0, 65535, &errstr);
+ if (errstr != NULL) {
+ fprintf(stderr,
+ "invalid argument: %s is %s for "
+ "\"nas-port\"\n", word, errstr);
+ return (NULL);
+ }
+ match++;
+ res.nas_port = num;
+ t = &table[i];
+ break;
+ case ENDTOKEN:
+ break;
+ }
+ }
+
+ if (match != 1) {
+ if (word == NULL)
+ fprintf(stderr, "missing argument:\n");
+ else if (match > 1)
+ fprintf(stderr, "ambiguous argument: %s\n", word);
+ else if (match < 1)
+ fprintf(stderr, "unknown argument: %s\n", word);
+ return (NULL);
+ }
+
+ return (t);
+}
+
+static void
+show_valid_args(const struct token table[])
+{
+ int i;
+
+ for (i = 0; table[i].type != ENDTOKEN; i++) {
+ switch (table[i].type) {
+ case NOTOKEN:
+ fprintf(stderr, " <cr>\n");
+ break;
+ case KEYWORD:
+ fprintf(stderr, " %s\n", table[i].keyword);
+ break;
+ case HOSTNAME:
+ fprintf(stderr, " <hostname>\n");
+ break;
+ case SECRET:
+ fprintf(stderr, " <radius secret>\n");
+ break;
+ case USERNAME:
+ fprintf(stderr, " <username>\n");
+ break;
+ case PASSWORD:
+ fprintf(stderr, " <password>\n");
+ break;
+ case PORT:
+ fprintf(stderr, " <port number>\n");
+ break;
+ case METHOD:
+ fprintf(stderr, " <auth method (pap, chap, "
+ "mschapv2)>\n");
+ break;
+ case NAS_PORT:
+ fprintf(stderr, " <nas-port (0-65535)>\n");
+ break;
+ case ENDTOKEN:
+ break;
+ }
+ }
+}