Previously key=value on the command line allowed the key to be pretty much anything that didn't contain an '=' character. Even empty strings were permitted. This tightens up the permitted keys so they must contain only ASCII alphanumeric, period, underscore or dash characters, and must not be an empty string. --- docs/nbdkit-plugin.pod | 18 ++++++++++-------- src/main.c | 32 +++++++++++++++++++++++++++++++- 2 files changed, 41 insertions(+), 9 deletions(-) diff --git a/docs/nbdkit-plugin.pod b/docs/nbdkit-plugin.pod index 570a142..b37cac1 100644 --- a/docs/nbdkit-plugin.pod +++ b/docs/nbdkit-plugin.pod @@ -376,15 +376,17 @@ optional list of C<key=value> arguments. These are passed to the plugin through this callback when the plugin is first loaded and before any connections are accepted. -This callback may be called zero or more times. Both C<key> and -C<value> parameters will be non-NULL, but it is possible for either to -be empty strings. The strings are owned by nbdkit but will remain -valid for the lifetime of the plugin, so the plugin does not need to -copy them. +This callback may be called zero or more times. -The format of the C<key> accepted by plugins is up to the plugin, but -you should probably look at other plugins and follow the same -conventions. +Both C<key> and C<value> parameters will be non-NULL. They key will +be a non-empty string containing only ASCII alphanumeric plus period, +underscore or dash characters (C<A-Z> C<a-z> C<0-9> C<.> C<_> C<->). +The value may be an arbitrary string, including an empty string. The +strings are owned by nbdkit but will remain valid for the lifetime of +the plugin, so the plugin does not need to copy them. + +The names of C<key>s accepted by plugins is up to the plugin, but you +should probably look at other plugins and follow the same conventions. If the value is a relative path, then note that the server changes directory when it starts up. See L</FILENAMES AND PATHS> above. diff --git a/src/main.c b/src/main.c index 9c18d6f..c523854 100644 --- a/src/main.c +++ b/src/main.c @@ -72,6 +72,7 @@ static void fork_into_background (void); static uid_t parseuser (const char *); static gid_t parsegroup (const char *); static unsigned int get_socket_activation (void); +static int is_config_key (const char *key, size_t len); struct debug_flag *debug_flags; /* -D */ int exit_with_parent; /* --exit-with-parent */ @@ -694,7 +695,7 @@ main (int argc, char *argv[]) magic_config_key = backend->magic_config_key (backend); for (i = 0; optind < argc; ++i, ++optind) { p = strchr (argv[optind], '='); - if (p) { /* key=value */ + if (p && is_config_key (argv[optind], p - argv[optind])) { /* key=value */ *p = '\0'; backend->config (backend, argv[optind], p+1); } @@ -1281,3 +1282,32 @@ get_socket_activation (void) return nr_fds; } + +/* When parsing plugin and filter config key=value from the command + * line, check that the key is a simple alphanumeric with period, + * underscore or dash. + * + * Note this doesn't return an error. If the key is not valid then we + * return false and the parsing code will assume that this is a bare + * value instead. + */ +static int +is_config_key (const char *key, size_t len) +{ + const char allowed[] = + "abcdefghijklmnopqrstuvwxyz" + "ABCDEFGHIJKLMNOPQRSTUVWXYZ" + "0123456789" + "._-"; + size_t i; + + if (key[0] == '\0') + return 0; + + for (i = 0; i < len; ++i) { + if (strchr (allowed, key[i]) == NULL) + return 0; + } + + return 1; +} -- 2.18.0