# HG changeset patch # User Matt Johnston # Date 1450186259 -28800 # Node ID 81063d78fe69ff70708a06125e71ab7c0307f933 # Parent d2f9ef67af156caf86661c9379808f7abce250fe# Parent 2907c658fa765d0455972ee837789c4b94b084ac Merge pull request #16 from annulen/openssh_options Implemented ExitOnForwardFailure option for local and remote forwarding. diff -r d2f9ef67af15 -r 81063d78fe69 cli-runopts.c --- a/cli-runopts.c Fri Dec 11 22:12:12 2015 +0800 +++ b/cli-runopts.c Tue Dec 15 21:30:59 2015 +0800 @@ -46,6 +46,7 @@ #ifdef ENABLE_CLI_NETCAT static void add_netcat(const char *str); #endif +static void add_extendedopt(const char *str); static void printhelp() { @@ -64,6 +65,7 @@ "-y Always accept remote host key if unknown\n" "-y -y Don't perform any remote host key checking (caution)\n" "-s Request a subsystem (use by external sftp)\n" + "-o option Set option in OpenSSH-like format ('-o help' to list options)\n" #ifdef ENABLE_CLI_PUBKEY_AUTH "-i (multiple allowed, default %s)\n" #endif @@ -106,6 +108,7 @@ unsigned int i, j; char ** next = 0; enum { + OPT_EXTENDED_OPTIONS, #ifdef ENABLE_CLI_PUBKEY_AUTH OPT_AUTHKEY, #endif @@ -145,6 +148,9 @@ #ifdef ENABLE_CLI_PUBKEY_AUTH cli_opts.privkeys = list_new(); #endif +#ifdef ENABLE_CLI_ANYTCPFWD + cli_opts.exit_on_fwd_failure = 0; +#endif #ifdef ENABLE_CLI_LOCALTCPFWD cli_opts.localfwds = list_new(); opts.listen_fwd_all = 0; @@ -224,6 +230,9 @@ case 's': cli_opts.is_subsystem = 1; break; + case 'o': + opt = OPT_EXTENDED_OPTIONS; + break; #ifdef ENABLE_CLI_LOCALTCPFWD case 'L': opt = OPT_LOCALTCPFWD; @@ -301,7 +310,6 @@ print_version(); exit(EXIT_SUCCESS); break; - case 'o': case 'b': next = &dummy; default: @@ -321,6 +329,11 @@ dropbear_exit("Missing argument"); } + if (opt == OPT_EXTENDED_OPTIONS) { + TRACE(("opt extended")) + add_extendedopt(&argv[i][j]); + } + else #ifdef ENABLE_CLI_PUBKEY_AUTH if (opt == OPT_AUTHKEY) { TRACE(("opt authkey")) @@ -806,3 +819,58 @@ dropbear_exit("Bad TCP port in '%s'", origstr); } #endif + +static int match_extendedopt(const char** strptr, const char *optname) { + int seen_eq = 0; + int optlen = strlen(optname); + const char *str = *strptr; + + while (isspace(*str)) + ++str; + + if (strncasecmp(str, optname, optlen) != 0) + return DROPBEAR_FAILURE; + + str += optlen; + + while (isspace(*str) || (!seen_eq && *str == '=')) { + if (*str == '=') + seen_eq = 1; + ++str; + } + + *strptr = str; + return DROPBEAR_SUCCESS; +} + +static int parse_flag_value(const char *value) +{ + if (strcmp(value, "yes") == 0 || strcmp(value, "true") == 0) + return 1; + else if (strcmp(value, "no") == 0 || strcmp(value, "false") == 0) + return 0; + + dropbear_exit("Bad yes/no argument '%s'", value); +} + +static void add_extendedopt(const char* origstr) { + const char *optstr = origstr; + + if (strcmp(origstr, "help") == 0) { + dropbear_log(LOG_INFO, "Available options:\n" +#ifdef ENABLE_CLI_ANYTCPFWD + "\tExitOnForwardFailure\n" +#endif + ); + exit(EXIT_SUCCESS); + } + +#ifdef ENABLE_CLI_ANYTCPFWD + if (match_extendedopt(&optstr, "ExitOnForwardFailure") == DROPBEAR_SUCCESS) { + cli_opts.exit_on_fwd_failure = parse_flag_value(optstr); + return; + } +#endif + + dropbear_exit("Bad configuration option '%s'", origstr); +} diff -r d2f9ef67af15 -r 81063d78fe69 cli-tcpfwd.c --- a/cli-tcpfwd.c Fri Dec 11 22:12:12 2015 +0800 +++ b/cli-tcpfwd.c Tue Dec 15 21:30:59 2015 +0800 @@ -60,6 +60,22 @@ }; #endif +#ifdef ENABLE_CLI_ANYTCPFWD +static void fwd_failed(const char* format, ...) ATTRIB_PRINTF(1,2); +void fwd_failed(const char* format, ...) +{ + va_list param; + va_start(param, format); + + if (cli_opts.exit_on_fwd_failure) + _dropbear_exit(EXIT_FAILURE, format, param); + else + _dropbear_log(LOG_WARNING, format, param); + + va_end(param); +} +#endif + #ifdef ENABLE_CLI_LOCALTCPFWD void setup_localtcp() { m_list_elem *iter; @@ -75,7 +91,7 @@ fwd->connectaddr, fwd->connectport); if (ret == DROPBEAR_FAILURE) { - dropbear_log(LOG_WARNING, "Failed local port forward %s:%d:%s:%d", + fwd_failed("Failed local port forward %s:%d:%s:%d", fwd->listenaddr, fwd->listenport, fwd->connectaddr, @@ -181,7 +197,10 @@ struct TCPFwdEntry *fwd = (struct TCPFwdEntry*)iter->item; if (!fwd->have_reply) { fwd->have_reply = 1; - dropbear_log(LOG_WARNING, "Remote TCP forward request failed (port %d -> %s:%d)", fwd->listenport, fwd->connectaddr, fwd->connectport); + fwd_failed("Remote TCP forward request failed (port %d -> %s:%d)", + fwd->listenport, + fwd->connectaddr, + fwd->connectport); return; } } diff -r d2f9ef67af15 -r 81063d78fe69 dbclient.1 --- a/dbclient.1 Fri Dec 11 22:12:12 2015 +0800 +++ b/dbclient.1 Tue Dec 15 21:30:59 2015 +0800 @@ -127,6 +127,20 @@ .B \-m \fIMAClist Specify a comma separated list of authentication MACs to enable. Use \fI-m help\fR to list possibilities. .TP +.B \-o \fIoption +Can be used to give options in the format used by OpenSSH config file. This is +useful for specifying options for which there is no separate command-line flag. +For full details of the options listed below, and their possible values, see +ssh_config(5). + +For now only following options have been implemented: +.RS +.RS +.TP +ExitOnForwardFailure +.RE +.RE +.TP .B \-s The specified command will be requested as a subsystem, used for sftp. Dropbear doesn't implement sftp itself but the OpenSSH sftp client can be used eg \fIsftp -S dbclient user@host\fR .TP diff -r d2f9ef67af15 -r 81063d78fe69 runopts.h --- a/runopts.h Fri Dec 11 22:12:12 2015 +0800 +++ b/runopts.h Tue Dec 15 21:30:59 2015 +0800 @@ -140,6 +140,9 @@ #ifdef ENABLE_CLI_PUBKEY_AUTH m_list *privkeys; /* Keys to use for public-key auth */ #endif +#ifdef ENABLE_CLI_ANYTCPFWD + int exit_on_fwd_failure; +#endif #ifdef ENABLE_CLI_REMOTETCPFWD m_list * remotefwds; #endif