# HG changeset patch # User Matt Johnston # Date 1648793632 -28800 # Node ID 4528afefe45d22860f44583890af0d53f449c57e # Parent a7ad060707b63015fd245f0e6e70d8b6cb8b5da0 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 diff -r a7ad060707b6 -r 4528afefe45d cli-runopts.c --- a/cli-runopts.c Fri Apr 01 12:17:02 2022 +0800 +++ b/cli-runopts.c Fri Apr 01 14:13:52 2022 +0800 @@ -419,7 +419,7 @@ /* 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 @@ } 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 -r a7ad060707b6 -r 4528afefe45d common-runopts.c --- a/common-runopts.c Fri Apr 01 12:17:02 2022 +0800 +++ b/common-runopts.c Fri Apr 01 14:13:52 2022 +0800 @@ -116,3 +116,58 @@ } } + +/* 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 -r a7ad060707b6 -r 4528afefe45d runopts.h --- a/runopts.h Fri Apr 01 12:17:02 2022 +0800 +++ b/runopts.h Fri Apr 01 14:13:52 2022 +0800 @@ -198,5 +198,6 @@ 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 -r a7ad060707b6 -r 4528afefe45d svr-runopts.c --- a/svr-runopts.c Fri Apr 01 12:17:02 2022 +0800 +++ b/svr-runopts.c Fri Apr 01 14:13:52 2022 +0800 @@ -452,56 +452,34 @@ } static void addportandaddress(const char* spec) { - char *spec_copy = NULL, *myspec = NULL, *port = NULL, *address = NULL; - - if (svr_opts.portcount < DROPBEAR_MAX_PORTS) { + char *port = NULL, *address = NULL; - /* 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 (split_address_port(spec, &address, &port) == DROPBEAR_FAILURE) { + dropbear_exit("Bad -p argument"); + } - 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, ':'); - } + /* A bare port */ + if (!port) { + port = address; + address = NULL; + } - if (!port) { - /* no ':' -> the whole string specifies just a port */ - port = myspec; - } else { - /* Split the address/port */ - port[0] = '\0'; - port++; - address = myspec; - } + if (!address) { + /* no address given -> fill in the default address */ + address = m_strdup(DROPBEAR_DEFADDRESS); + } - if (!address) { - /* no address given -> fill in the default address */ - address = 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) {