summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMatt Johnston <matt@ucc.asn.au>2022-04-01 14:13:52 +0800
committerMatt Johnston <matt@ucc.asn.au>2022-04-01 14:13:52 +0800
commitc8460ec9b7e34b9cfb22d25d762737a268d5bbf2 (patch)
treeb86bb3596978407974ef859aebb9924ecd3e0ee3
parent115c6deb58529f8354bc5937d296787c5439e3bb (diff)
downloaddropbear-c8460ec9b7e34b9cfb22d25d762737a268d5bbf2.tar.gz
Fix IPv6 address parsing for dbclient -b
Now can correctly handle '-b [ipv6address]:port' Code is shared with dropbear -p, though they handle colon-less arguments differently
-rw-r--r--cli-runopts.c14
-rw-r--r--common-runopts.c55
-rw-r--r--runopts.h1
-rw-r--r--svr-runopts.c66
4 files changed, 83 insertions, 53 deletions
diff --git a/cli-runopts.c b/cli-runopts.c
index 4795d67..8df1b7a 100644
--- a/cli-runopts.c
+++ b/cli-runopts.c
@@ -419,7 +419,7 @@ void cli_getopts(int argc, char ** argv) {
/* And now a few sanity checks and setup */
-#if DROPBEAR_CLI_PROXYCMD
+#if DROPBEAR_CLI_PROXYCMD
if (cli_opts.proxycmd) {
/* To match the common path of m_freeing it */
cli_opts.proxycmd = m_strdup(cli_opts.proxycmd);
@@ -431,14 +431,10 @@ void cli_getopts(int argc, char ** argv) {
}
if (bind_arg) {
- /* split [host][:port] */
- char *port = strrchr(bind_arg, ':');
- if (port) {
- cli_opts.bind_port = m_strdup(port+1);
- *port = '\0';
- }
- if (strlen(bind_arg) > 0) {
- cli_opts.bind_address = m_strdup(bind_arg);
+ if (split_address_port(bind_arg,
+ &cli_opts.bind_address, &cli_opts.bind_port)
+ == DROPBEAR_FAILURE) {
+ dropbear_exit("Bad -b argument");
}
}
diff --git a/common-runopts.c b/common-runopts.c
index 37f153c..e9ad314 100644
--- a/common-runopts.c
+++ b/common-runopts.c
@@ -116,3 +116,58 @@ void parse_recv_window(const char* recv_window_arg) {
}
}
+
+/* Splits addr:port. Handles IPv6 [2001:0011::4]:port style format.
+ Returns first/second parts as malloced strings, second will
+ be NULL if no separator is found.
+ :port -> (NULL, "port")
+ port -> (port, NULL)
+ addr:port (addr, port)
+ addr: -> (addr, "")
+ Returns DROPBEAR_SUCCESS/DROPBEAR_FAILURE */
+int split_address_port(const char* spec, char **first, char ** second) {
+ char *spec_copy = NULL, *addr = NULL, *colon = NULL;
+ int ret = DROPBEAR_FAILURE;
+
+ *first = NULL;
+ *second = NULL;
+ spec_copy = m_strdup(spec);
+ addr = spec_copy;
+
+ if (*addr == '[') {
+ addr++;
+ colon = strchr(addr, ']');
+ if (!colon) {
+ dropbear_log(LOG_WARNING, "Bad address '%s'", spec);
+ goto out;
+ }
+ *colon = '\0';
+ colon++;
+ if (*colon == '\0') {
+ /* No port part */
+ colon = NULL;
+ } else if (*colon != ':') {
+ dropbear_log(LOG_WARNING, "Bad address '%s'", spec);
+ goto out;
+ }
+ } else {
+ /* search for ':', that separates address and port */
+ colon = strrchr(addr, ':');
+ }
+
+ /* colon points to ':' now, or is NULL */
+ if (colon) {
+ /* Split the address/port */
+ *colon = '\0';
+ colon++;
+ *second = m_strdup(colon);
+ }
+ if (strlen(addr)) {
+ *first = m_strdup(addr);
+ }
+ ret = DROPBEAR_SUCCESS;
+
+out:
+ m_free(spec_copy);
+ return ret;
+}
diff --git a/runopts.h b/runopts.h
index 4271d1f..8c44b52 100644
--- a/runopts.h
+++ b/runopts.h
@@ -198,5 +198,6 @@ void parse_ciphers_macs(void);
void print_version(void);
void parse_recv_window(const char* recv_window_arg);
+int split_address_port(const char* spec, char **first, char ** second);
#endif /* DROPBEAR_RUNOPTS_H_ */
diff --git a/svr-runopts.c b/svr-runopts.c
index dbb24b3..9f40089 100644
--- a/svr-runopts.c
+++ b/svr-runopts.c
@@ -452,56 +452,34 @@ void svr_getopts(int argc, char ** argv) {
}
static void addportandaddress(const char* spec) {
- char *spec_copy = NULL, *myspec = NULL, *port = NULL, *address = NULL;
+ char *port = NULL, *address = NULL;
- if (svr_opts.portcount < DROPBEAR_MAX_PORTS) {
-
- /* We don't free it, it becomes part of the runopt state */
- spec_copy = m_strdup(spec);
- myspec = spec_copy;
+ if (svr_opts.portcount >= DROPBEAR_MAX_PORTS) {
+ return;
+ }
- if (myspec[0] == '[') {
- myspec++;
- port = strchr(myspec, ']');
- if (!port) {
- /* Unmatched [ -> exit */
- dropbear_exit("Bad listen address");
- }
- port[0] = '\0';
- port++;
- if (port[0] != ':') {
- /* Missing port -> exit */
- dropbear_exit("Missing port");
- }
- } else {
- /* search for ':', that separates address and port */
- port = strrchr(myspec, ':');
- }
+ if (split_address_port(spec, &address, &port) == DROPBEAR_FAILURE) {
+ dropbear_exit("Bad -p argument");
+ }
- if (!port) {
- /* no ':' -> the whole string specifies just a port */
- port = myspec;
- } else {
- /* Split the address/port */
- port[0] = '\0';
- port++;
- address = myspec;
- }
+ /* A bare port */
+ if (!port) {
+ port = address;
+ address = NULL;
+ }
- if (!address) {
- /* no address given -> fill in the default address */
- address = DROPBEAR_DEFADDRESS;
- }
+ if (!address) {
+ /* no address given -> fill in the default address */
+ address = m_strdup(DROPBEAR_DEFADDRESS);
+ }
- if (port[0] == '\0') {
- /* empty port -> exit */
- dropbear_exit("Bad port");
- }
- svr_opts.ports[svr_opts.portcount] = m_strdup(port);
- svr_opts.addresses[svr_opts.portcount] = m_strdup(address);
- svr_opts.portcount++;
- m_free(spec_copy);
+ if (port[0] == '\0') {
+ /* empty port -> exit */
+ dropbear_exit("Bad port");
}
+ svr_opts.ports[svr_opts.portcount] = port;
+ svr_opts.addresses[svr_opts.portcount] = address;
+ svr_opts.portcount++;
}
static void disablekey(int type) {