From 976097d67c266ff4c342b2b2dd4cb7f0465a88a0 Mon Sep 17 00:00:00 2001 From: June McEnroe Date: Mon, 4 Apr 2022 18:16:09 -0400 Subject: edit: Shuffle option safety around --- extra/edit/edit.c | 60 +++++++++++++++++++++++++++++++++---------------------- 1 file changed, 36 insertions(+), 24 deletions(-) diff --git a/extra/edit/edit.c b/extra/edit/edit.c index 1f0d8bb..ffbf7a9 100644 --- a/extra/edit/edit.c +++ b/extra/edit/edit.c @@ -240,10 +240,13 @@ static const char *Boolean[] = { "no-names", "no-sts", "palaver", "sasl-external", "verbose", }; +// FIXME: size needs to be validated for power of two static const char *Integer[] = { "local-port", "port", "queue-interval", "size", }; +// FIXME: local-pass needs to be validated for hash +// FIXME: sasl-plain needs to be validated for colon static const char *String[] = { "away", "bind", "blind-req", "client-cert", "client-priv", "host", "join", "local-ca", "local-cert", "local-host", "local-pass", "local-path", @@ -251,52 +254,57 @@ static const char *String[] = { "trust", "user", }; -static const char *Unsafe[] = { - "bind", "blind-req", "client-cert", "client-priv", "host", "local-ca", - "local-cert", "local-host", "local-path", "local-port", "local-priv", - "pass", "port", "sasl-external", "sasl-plain", "save", "trust", "verbose", +// TODO: nick, user aren't safe until pounce can fall back in case +// they're invalid +static const char *Safe[] = { + "away", "join", "local-pass", "mode", "nick", "no-names", "no-sts", + "palaver", "quit", "real", "user", }; static bool allowUnsafe; +static bool safe(const char *name) { + if (allowUnsafe) return true; + for (size_t i = 0; i < ARRAY_LEN(Safe); ++i) { + if (!strcmp(Safe[i], name)) return true; + } + return false; +} -static const char *validate(const char *name, const char *value) { - if (!allowUnsafe) { - for (size_t i = 0; i < ARRAY_LEN(Unsafe); ++i) { - if (!strcmp(Unsafe[i], name)) return "is unsafe"; - } +static bool exists(const char *name) { + for (size_t i = 0; i < ARRAY_LEN(Boolean); ++i) { + if (!strcmp(Boolean[i], name)) return true; } + for (size_t i = 0; i < ARRAY_LEN(Integer); ++i) { + if (!strcmp(Integer[i], name)) return true; + } + for (size_t i = 0; i < ARRAY_LEN(String); ++i) { + if (!strcmp(String[i], name)) return true; + } + return false; +} + +static const char *validate(const char *name, const char *value) { for (size_t i = 0; i < ARRAY_LEN(Boolean); ++i) { if (strcmp(Boolean[i], name)) continue; + if (!safe(name)) return "cannot be set"; return (value ? "does not take a value" : NULL); } for (size_t i = 0; i < ARRAY_LEN(Integer); ++i) { if (strcmp(Integer[i], name)) continue; + if (!safe(name)) return "cannot be set"; if (!value) return "requires a value"; char *end; strtoul(value, &end, 10); - if (!*value || *end) return "must be an integer"; - return NULL; + return (!*value || *end ? "must be an integer" : NULL); } for (size_t i = 0; i < ARRAY_LEN(String); ++i) { if (strcmp(String[i], name)) continue; + if (!safe(name)) return "cannot be set"; return (value ? NULL : "requires a value"); } return "is not an option"; } -static bool exists(const char *name) { - for (size_t i = 0; i < ARRAY_LEN(Boolean); ++i) { - if (!strcmp(Boolean[i], name)) return true; - } - for (size_t i = 0; i < ARRAY_LEN(Integer); ++i) { - if (!strcmp(Integer[i], name)) return true; - } - for (size_t i = 0; i < ARRAY_LEN(String); ++i) { - if (!strcmp(String[i], name)) return true; - } - return false; -} - static void handlePrivmsg(struct Message *msg) { require(msg, true, 2); if (strcmp(msg->nick, msg->params[0])) return; @@ -359,6 +367,10 @@ static void handlePrivmsg(struct Message *msg) { format("NOTICE %s :\2%s\2 is not an option\r\n", msg->nick, name); return; } + if (!safe(name)) { + format("NOTICE %s :\2%s\2 cannot be unset\r\n", msg->nick, name); + return; + } configUnset(&own, name); configWrite(&own, config); -- cgit 1.4.1