diff cli-runopts.c @ 546:568638be7203 agent-client

propagate from branch 'au.asn.ucc.matt.dropbear' (head 899a8851a5edf840b2f7925bcc26ffe99dcac54d) to branch 'au.asn.ucc.matt.dropbear.cli-agent' (head 6bbab8364de17bd9ecb1dee5ffb796e48c0380d2)
author Matt Johnston <matt@ucc.asn.au>
date Wed, 01 Jul 2009 04:16:32 +0000
parents d588e3ea557a 9e51707cd6f2
children c3f2ec71e3d4
line wrap: on
line diff
--- a/cli-runopts.c	Tue Sep 23 16:05:04 2008 +0000
+++ b/cli-runopts.c	Wed Jul 01 04:16:32 2009 +0000
@@ -49,7 +49,11 @@
 static void printhelp() {
 
 	fprintf(stderr, "Dropbear client v%s\n"
+#ifdef ENABLE_CLI_MULTIHOP
+					"Usage: %s [options] [user@]host[/port][,[user@]host/port],...] [command]\n"
+#else
 					"Usage: %s [options] [user@]host[/port] [command]\n"
+#endif
 					"Options are:\n"
 					"-p <remoteport>\n"
 					"-l <username>\n"
@@ -74,22 +78,22 @@
 #endif
 					"-W <receive_window_buffer> (default %d, larger may be faster, max 1MB)\n"
 					"-K <keepalive>  (0 is never, default %d)\n"
+					"-I <idle_timeout>  (0 is never, default %d)\n"
 #ifdef ENABLE_CLI_NETCAT
-					"-B <endhost:endport> Netcat-alike bouncing\n"
+					"-B <endhost:endport> Netcat-alike forwarding\n"
 #endif				
 #ifdef ENABLE_CLI_PROXYCMD
-					"-J <proxy_program> Use program rather than tcp connection\n"
+					"-J <proxy_program> Use program pipe rather than TCP connection\n"
 #endif
 #ifdef DEBUG_TRACE
-					"-v    verbose\n"
+					"-v    verbose (compiled with DEBUG_TRACE)\n"
 #endif
 					,DROPBEAR_VERSION, cli_opts.progname,
-					DEFAULT_RECV_WINDOW, DEFAULT_KEEPALIVE);
+					DEFAULT_RECV_WINDOW, DEFAULT_KEEPALIVE, DEFAULT_IDLE_TIMEOUT);
 					
 }
 
 void cli_getopts(int argc, char ** argv) {
-
 	unsigned int i, j;
 	char ** next = 0;
 	unsigned int cmdlen;
@@ -109,6 +113,8 @@
 
 	char* recv_window_arg = NULL;
 	char* keepalive_arg = NULL;
+	char* idle_timeout_arg = NULL;
+	char *host_arg = NULL;
 
 	/* see printhelp() for options */
 	cli_opts.progname = argv[0];
@@ -264,6 +270,9 @@
 				case 'K':
 					next = &keepalive_arg;
 					break;
+				case 'I':
+					next = &idle_timeout_arg;
+					break;
 #ifdef ENABLE_CLI_AGENTFWD
 				case 'A':
 					cli_opts.agent_fwd = 1;
@@ -307,12 +316,8 @@
 
 			/* Either the hostname or commands */
 
-			if (cli_opts.remotehost == NULL) {
-#ifdef ENABLE_CLI_MULTIHOP
-				parse_multihop_hostname(argv[i], argv[0]);
-#else
-				parse_hostname(argv[i]);
-#endif
+			if (host_arg == NULL) {
+				host_arg = argv[i];
 			} else {
 
 				/* this is part of the commands to send - after this we
@@ -341,7 +346,7 @@
 
 	/* And now a few sanity checks and setup */
 
-	if (cli_opts.remotehost == NULL) {
+	if (host_arg == NULL) {
 		printhelp();
 		exit(EXIT_FAILURE);
 	}
@@ -377,12 +382,26 @@
 		}
 	}
 
+	if (idle_timeout_arg) {
+		if (m_str_to_uint(idle_timeout_arg, &opts.idle_timeout_secs) == DROPBEAR_FAILURE) {
+			dropbear_exit("Bad idle_timeout '%s'", idle_timeout_arg);
+		}
+	}
+
 #ifdef ENABLE_CLI_NETCAT
 	if (cli_opts.cmd && cli_opts.netcat_host) {
 		dropbear_log(LOG_INFO, "Ignoring command '%s' in netcat mode", cli_opts.cmd);
 	}
 #endif
-	
+
+	/* The hostname gets set up last, since
+	 * in multi-hop mode it will require knowledge
+	 * of other flags such as -i */
+#ifdef ENABLE_CLI_MULTIHOP
+	parse_multihop_hostname(host_arg, argv[0]);
+#else
+	parse_hostname(host_arg);
+#endif
 }
 
 #ifdef ENABLE_CLI_PUBKEY_AUTH
@@ -395,14 +414,12 @@
 	key = new_sign_key();
 	keytype = DROPBEAR_SIGNKEY_ANY;
 	if ( readhostkey(filename, key, &keytype) != DROPBEAR_SUCCESS ) {
-
 		fprintf(stderr, "Failed loading keyfile '%s'\n", filename);
 		sign_key_free(key);
-
 	} else {
-
 		nextkey = (struct SignKeyList*)m_malloc(sizeof(struct SignKeyList));
 		nextkey->key = key;
+		nextkey->filename = m_strdup(filename);
 		nextkey->next = cli_opts.privkeys;
 		nextkey->type = keytype;
 		nextkey->source = SIGNKEY_SOURCE_RAW_FILE;
@@ -413,6 +430,39 @@
 
 #ifdef ENABLE_CLI_MULTIHOP
 
+static char*
+multihop_passthrough_args() {
+	char *ret;
+	int total;
+	unsigned int len = 0;
+	struct SignKeyList *nextkey;
+	/* Fill out -i and -W options that make sense for all
+	 * the intermediate processes */
+	for (nextkey = cli_opts.privkeys; nextkey; nextkey = nextkey->next)
+	{
+		len += 3 + strlen(nextkey->filename);
+	}
+	len += 20; // space for -W <size>, terminator.
+	ret = m_malloc(len);
+	total = 0;
+
+	if (opts.recv_window != DEFAULT_RECV_WINDOW)
+	{
+		int written = snprintf(ret+total, len-total, "-W %d", opts.recv_window);
+		total += written;
+	}
+
+	for (nextkey = cli_opts.privkeys; nextkey; nextkey = nextkey->next)
+	{
+		const size_t size = len - total;
+		int written = snprintf(ret+total, size, "-i %s", nextkey->filename);
+		dropbear_assert(written < size);
+		total += written;
+	}
+
+	return ret;
+}
+
 /* Sets up 'onion-forwarding' connections. This will spawn
  * a separate dbclient process for each hop.
  * As an example, if the cmdline is
@@ -427,6 +477,7 @@
  */
 static void parse_multihop_hostname(const char* orighostarg, const char* argv0) {
 	char *userhostarg = NULL;
+	char *hostbuf = NULL;
 	char *last_hop = NULL;;
 	char *remainder = NULL;
 
@@ -439,11 +490,12 @@
 			&& strchr(cli_opts.username, ',') 
 			&& strchr(cli_opts.username, '@')) {
 		unsigned int len = strlen(orighostarg) + strlen(cli_opts.username) + 2;
-		userhostarg = m_malloc(len);
-		snprintf(userhostarg, len, "%s@%s", cli_opts.username, orighostarg);
+		hostbuf = m_malloc(len);
+		snprintf(hostbuf, len, "%s@%s", cli_opts.username, orighostarg);
 	} else {
-		userhostarg = m_strdup(orighostarg);
+		hostbuf = m_strdup(orighostarg);
 	}
+	userhostarg = hostbuf;
 
 	last_hop = strrchr(userhostarg, ',');
 	if (last_hop) {
@@ -461,19 +513,24 @@
 	if (last_hop) {
 		/* Set up the proxycmd */
 		unsigned int cmd_len = 0;
+		char *passthrough_args = multihop_passthrough_args();
 		if (cli_opts.proxycmd) {
 			dropbear_exit("-J can't be used with multihop mode");
 		}
 		if (cli_opts.remoteport == NULL) {
 			cli_opts.remoteport = "22";
 		}
-		cmd_len = strlen(remainder) 
+		cmd_len = strlen(argv0) + strlen(remainder) 
 			+ strlen(cli_opts.remotehost) + strlen(cli_opts.remoteport)
-			+ strlen(argv0) + 30;
+			+ strlen(passthrough_args)
+			+ 30;
 		cli_opts.proxycmd = m_malloc(cmd_len);
-		snprintf(cli_opts.proxycmd, cmd_len, "%s -B %s:%s %s", 
-				argv0, cli_opts.remotehost, cli_opts.remoteport, remainder);
+		snprintf(cli_opts.proxycmd, cmd_len, "%s -B %s:%s %s %s", 
+				argv0, cli_opts.remotehost, cli_opts.remoteport, 
+				passthrough_args, remainder);
+		m_free(passthrough_args);
 	}
+	m_free(hostbuf);
 }
 #endif /* !ENABLE_CLI_MULTIHOP */
 
@@ -622,6 +679,7 @@
 		goto badport;
 	}
 
+	newfwd->have_reply = 0;
 	newfwd->next = *fwdlist;
 	*fwdlist = newfwd;