changeset 1207:81063d78fe69

Merge pull request #16 from annulen/openssh_options Implemented ExitOnForwardFailure option for local and remote forwarding.
author Matt Johnston <matt@ucc.asn.au>
date Tue, 15 Dec 2015 21:30:59 +0800
parents d2f9ef67af15 (current diff) 2907c658fa76 (diff)
children ab7d9c12caa7
files runopts.h
diffstat 4 files changed, 107 insertions(+), 3 deletions(-) [+]
line wrap: on
line diff
--- 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 <identityfile>   (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);
+}
--- 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;
 		}
 	}
--- 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
--- 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