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
This commit is contained in:
Matt Johnston 2022-04-01 14:13:52 +08:00
parent 7894254afa
commit dd305c1533
4 changed files with 87 additions and 57 deletions

View File

@ -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");
}
}

View File

@ -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;
}

View File

@ -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_ */

View File

@ -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 (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 (!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 = 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 (svr_opts.portcount >= DROPBEAR_MAX_PORTS) {
return;
}
if (split_address_port(spec, &address, &port) == DROPBEAR_FAILURE) {
dropbear_exit("Bad -p argument");
}
/* A bare port */
if (!port) {
port = address;
address = NULL;
}
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] = port;
svr_opts.addresses[svr_opts.portcount] = address;
svr_opts.portcount++;
}
static void disablekey(int type) {