From f08ae49134dbb46917cfa1dd4f7c6d5e795e494f Mon Sep 17 00:00:00 2001 From: Christian Decker Date: Wed, 28 Apr 2021 17:21:14 +0200 Subject: [PATCH] plugin: Restrict plugin notifications only to announced topics We want to have well-behaved notifications that are clearly announced during the initialization, kill plugins that don't behave. --- lightningd/plugin.c | 37 +++++++++++++++++++++++++++++++------ plugins/libplugin.c | 2 ++ 2 files changed, 33 insertions(+), 6 deletions(-) diff --git a/lightningd/plugin.c b/lightningd/plugin.c index 41da67a30..587e3c9dc 100644 --- a/lightningd/plugin.c +++ b/lightningd/plugin.c @@ -417,6 +417,18 @@ static const char *plugin_notify_handle(struct plugin *plugin, return NULL; } +/* Check if the plugin is allowed to send a notification of the + * specified topic, i.e., whether the plugin has announced the topic + * correctly in its manifest. */ +static bool plugin_notification_allowed(const struct plugin *plugin, const char *topic) +{ + for (size_t i=0; inotification_topics); i++) + if (streq(plugin->notification_topics[i], topic)) + return true; + + return false; +} + /* Returns the error string, or NULL */ static const char *plugin_notification_handle(struct plugin *plugin, const jsmntok_t *toks) @@ -453,13 +465,26 @@ static const char *plugin_notification_handle(struct plugin *plugin, methname = json_strdup(tmpctx, plugin->buffer, methtok); if (notifications_have_topic(plugin->plugins, methname)) { - n = jsonrpc_notification_start(NULL, methname); - json_add_string(n->stream, "origin", plugin->shortname); - json_add_tok(n->stream, "payload", paramstok, plugin->buffer); - jsonrpc_notification_end(n); - plugins_notify(plugin->plugins, take(n)); - return NULL; + if (!plugin_notification_allowed(plugin, methname)) { + log_unusual( + plugin->log, + "Plugin attempted to send a notification to topic " + "\"%s\" it hasn't declared in its manifest, not " + "forwarding to subscribers.", + methname); + return NULL; + } else { + + n = jsonrpc_notification_start(NULL, methname); + json_add_string(n->stream, "origin", plugin->shortname); + json_add_tok(n->stream, "payload", paramstok, + plugin->buffer); + jsonrpc_notification_end(n); + + plugins_notify(plugin->plugins, take(n)); + return NULL; + } } else { return tal_fmt(plugin, "Unknown notification method %.*s", json_tok_full_len(methtok), diff --git a/plugins/libplugin.c b/plugins/libplugin.c index 7a0e8fe38..487208cef 100644 --- a/plugins/libplugin.c +++ b/plugins/libplugin.c @@ -91,6 +91,8 @@ struct plugin { /* Location of the RPC filename in case we need to defer RPC * initialization or need to recover from a disconnect. */ const char *rpc_location; + + char **notification_topics; }; /* command_result is mainly used as a compile-time check to encourage you