Skip to content

Fix plugin command line parsing logic #194

@struanb

Description

@struanb

When deploying dropbear with the libepka_file.so plugin from https://github.com/fabriziobertocci/dropbear-epka, I encountered intermittent failures in the plugin operating correctly.

Using strace, ltrace and then adding additional debug logging to dropbear and recompiling, I believe I have traced the issue to lines 450-461 of https://github.com/mkj/dropbear/blob/master/svr-runopts.c.

#if DROPBEAR_PLUGIN
        if (pubkey_plugin) {
            char *args = strchr(pubkey_plugin, ',');
            if (args) {
                *args='\0';
                ++args;
            }
            svr_opts.pubkey_plugin = pubkey_plugin;
            svr_opts.pubkey_plugin_options = args;
        }
#endif
}

On the face of it, this code looks sound, and it does work in the main dropbear process.

But when dropbear accepts an incoming ssh connection it forks a child, which reparses the command line. At this point pubkey_plugin appears to be NULL (I'm not sure why) and the , that the above code searches for has already been replaced with \0. And so, the parsing fails to identify the , and it assigns NULL to svr_opts.pubkey_plugin_options instead of the plugin's command line options.

To demonstrate, here is the output from dropbear with some debug logging:

#if DROPBEAR_PLUGIN
        if(svr_opts.pubkey_plugin != NULL) dropbear_log(LOG_INFO, "1:svr_opts.pubkey_plugin=[%s][%s]", svr_opts.pubkey_plugin, svr_opts.pubkey_plugin_options);

        if (pubkey_plugin) {
            dropbear_log(LOG_INFO, "pubkey_plugin=[%s][%s]", pubkey_plugin, pubkey_plugin + strlen(pubkey_plugin)+1);
            char *args = strchr(pubkey_plugin, ',');
            if (args) {
                *args='\0';
                ++args;
            }
            svr_opts.pubkey_plugin = pubkey_plugin;
            svr_opts.pubkey_plugin_options = args;
        }

        if(svr_opts.pubkey_plugin != NULL) dropbear_log(LOG_INFO, "2:svr_opts.pubkey_plugin=[%s][%s]", svr_opts.pubkey_plugin, svr_opts.pubkey_plugin_options);

#endif
}
bash-5.1# ./dropbear -A /root/dropbear-epka/src/.libs/libepka_file.so,/root/epka_file.json -R -E -F
[21832] Nov 08 10:23:18 pubkey_plugin=[/root/dropbear-epka/src/.libs/libepka_file.so,/root/epka_file.json][-R]
[21832] Nov 08 10:23:18 2:svr_opts.pubkey_plugin=[/root/dropbear-epka/src/.libs/libepka_file.so][/root/epka_file.json]
[21832] Nov 08 10:23:18 Not backgrounding
[21834] Nov 08 10:23:22 Child connection from 127.0.0.1:51574
[21834] Nov 08 10:23:22 pubkey_plugin=[/root/dropbear-epka/src/.libs/libepka_file.so][-R]
[21834] Nov 08 10:23:22 2:svr_opts.pubkey_plugin=[/root/dropbear-epka/src/.libs/libepka_file.so][(null)]
[fileauth] - missing auth file from options
[21834] Nov 08 10:23:22 Early exit from <127.0.0.1:51574>: external plugin initialization failed

At this stage I don't know if the underlying issue is that:

  1. the child process shouldn't be reparsing the command-line (if it should, I am curious to know why it should and why svr_opts.pubkey_plugin and svr_opts.pubkey_plugin_options do not appear to be inherited by the child from the parent); or
  2. the command-line parsing process should be repeatable and non-destructive of the input so that the child can reparse the command-line correctly.

P.S. Purely as a proof of issue, if I patch the code to assign a literal filepath to svr_opts.pubkey_plugin_options the plugin does work consistently.

Metadata

Metadata

Assignees

No one assigned

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions