mirror of
https://git.tartarus.org/simon/putty.git
synced 2025-01-26 01:32:25 +00:00
Use the new host_str* functions to improve IPv6 literal support.
I've gone through everywhere we handle host names / addresses (on command lines, in PuTTY config, in port forwarding, in X display names, in host key storage...) and tried to make them handle IPv6 literals sensibly, by using the host_str* functions I introduced in my previous commit. Generally it's now OK to use a bracketed IPv6 literal anywhere a hostname might have been valid; in a few cases where no ambiguity exists (e.g. no :port suffix is permitted anyway) unbracketed IPv6 literals are also acceptable. [originally from svn r10120]
This commit is contained in:
parent
0348f57077
commit
8da4fa5063
@ -261,9 +261,9 @@ int cmdline_process_param(char *p, char *value, int need_save, Conf *conf)
|
|||||||
|
|
||||||
type = p[1]; /* 'L' or 'R' */
|
type = p[1]; /* 'L' or 'R' */
|
||||||
|
|
||||||
q = qq = strchr(value, ':');
|
q = qq = host_strchr(value, ':');
|
||||||
while (qq) {
|
while (qq) {
|
||||||
char *qqq = strchr(qq+1, ':');
|
char *qqq = host_strchr(qq+1, ':');
|
||||||
if (qqq)
|
if (qqq)
|
||||||
q = qq;
|
q = qq;
|
||||||
qq = qqq;
|
qq = qqq;
|
||||||
@ -301,7 +301,7 @@ int cmdline_process_param(char *p, char *value, int need_save, Conf *conf)
|
|||||||
UNAVAILABLE_IN(TOOLTYPE_FILETRANSFER | TOOLTYPE_NONNETWORK);
|
UNAVAILABLE_IN(TOOLTYPE_FILETRANSFER | TOOLTYPE_NONNETWORK);
|
||||||
SAVEABLE(0);
|
SAVEABLE(0);
|
||||||
|
|
||||||
portp = strchr(value, ':');
|
portp = host_strchr(value, ':');
|
||||||
if (!portp) {
|
if (!portp) {
|
||||||
cmdline_error("-nc expects argument of form 'host:port'");
|
cmdline_error("-nc expects argument of form 'host:port'");
|
||||||
return ret;
|
return ret;
|
||||||
|
2
config.c
2
config.c
@ -1146,7 +1146,7 @@ static void portfwd_handler(union control *ctrl, void *dlg,
|
|||||||
}
|
}
|
||||||
if (*type != 'D') {
|
if (*type != 'D') {
|
||||||
val = dlg_editbox_get(pfd->destbox, dlg);
|
val = dlg_editbox_get(pfd->destbox, dlg);
|
||||||
if (!*val || !strchr(val, ':')) {
|
if (!*val || !host_strchr(val, ':')) {
|
||||||
dlg_error_msg(dlg,
|
dlg_error_msg(dlg,
|
||||||
"You need to specify a destination address\n"
|
"You need to specify a destination address\n"
|
||||||
"in the form \"host.name:port\"");
|
"in the form \"host.name:port\"");
|
||||||
|
22
pscp.c
22
pscp.c
@ -370,15 +370,9 @@ static void do_cmd(char *host, char *user, char *cmd)
|
|||||||
bump("Empty host name");
|
bump("Empty host name");
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Remove fiddly bits of address: remove a colon suffix, and
|
* Remove a colon suffix.
|
||||||
* the square brackets around an IPv6 literal address.
|
|
||||||
*/
|
*/
|
||||||
if (host[0] == '[') {
|
host[host_strcspn(host, ":")] = '\0';
|
||||||
host++;
|
|
||||||
host[strcspn(host, "]")] = '\0';
|
|
||||||
} else {
|
|
||||||
host[strcspn(host, ":")] = '\0';
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If we haven't loaded session details already (e.g., from -load),
|
* If we haven't loaded session details already (e.g., from -load),
|
||||||
@ -613,17 +607,7 @@ static char *colon(char *str)
|
|||||||
if (str[0] == '\0' || str[0] == ':' ||
|
if (str[0] == '\0' || str[0] == ':' ||
|
||||||
(str[0] != '[' && str[1] == ':'))
|
(str[0] != '[' && str[1] == ':'))
|
||||||
return (NULL);
|
return (NULL);
|
||||||
while (*str != '\0' && *str != ':' && *str != '/' && *str != '\\') {
|
str += host_strcspn(str, ":/\\");
|
||||||
if (*str == '[') {
|
|
||||||
/* Skip over IPv6 literal addresses
|
|
||||||
* (eg: 'jeroen@[2001:db8::1]:myfile.txt') */
|
|
||||||
char *ipv6_end = strchr(str, ']');
|
|
||||||
if (ipv6_end) {
|
|
||||||
str = ipv6_end;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
str++;
|
|
||||||
}
|
|
||||||
if (*str == ':')
|
if (*str == ':')
|
||||||
return (str);
|
return (str);
|
||||||
else
|
else
|
||||||
|
11
raw.c
11
raw.c
@ -185,16 +185,11 @@ static const char *raw_init(void *frontend_handle, void **backend_handle,
|
|||||||
|
|
||||||
sfree(*realhost);
|
sfree(*realhost);
|
||||||
*realhost = dupstr(loghost);
|
*realhost = dupstr(loghost);
|
||||||
colon = strrchr(*realhost, ':');
|
|
||||||
if (colon) {
|
colon = host_strrchr(*realhost, ':');
|
||||||
/*
|
if (colon)
|
||||||
* FIXME: if we ever update this aspect of ssh.c for
|
|
||||||
* IPv6 literal management, this should change in line
|
|
||||||
* with it.
|
|
||||||
*/
|
|
||||||
*colon++ = '\0';
|
*colon++ = '\0';
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
11
rlogin.c
11
rlogin.c
@ -226,16 +226,11 @@ static const char *rlogin_init(void *frontend_handle, void **backend_handle,
|
|||||||
|
|
||||||
sfree(*realhost);
|
sfree(*realhost);
|
||||||
*realhost = dupstr(loghost);
|
*realhost = dupstr(loghost);
|
||||||
colon = strrchr(*realhost, ':');
|
|
||||||
if (colon) {
|
colon = host_strrchr(*realhost, ':');
|
||||||
/*
|
if (colon)
|
||||||
* FIXME: if we ever update this aspect of ssh.c for
|
|
||||||
* IPv6 literal management, this should change in line
|
|
||||||
* with it.
|
|
||||||
*/
|
|
||||||
*colon++ = '\0';
|
*colon++ = '\0';
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Send local username, remote username, terminal type and
|
* Send local username, remote username, terminal type and
|
||||||
|
28
ssh.c
28
ssh.c
@ -3411,25 +3411,27 @@ static const char *connect_to_host(Ssh ssh, char *host, int port,
|
|||||||
|
|
||||||
loghost = conf_get_str(ssh->conf, CONF_loghost);
|
loghost = conf_get_str(ssh->conf, CONF_loghost);
|
||||||
if (*loghost) {
|
if (*loghost) {
|
||||||
|
char *tmphost;
|
||||||
char *colon;
|
char *colon;
|
||||||
|
|
||||||
ssh->savedhost = dupstr(loghost);
|
tmphost = dupstr(loghost);
|
||||||
ssh->savedport = 22; /* default ssh port */
|
ssh->savedport = 22; /* default ssh port */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* A colon suffix on savedhost also lets us affect
|
* A colon suffix on the hostname string also lets us affect
|
||||||
* savedport.
|
* savedport.
|
||||||
*
|
|
||||||
* (FIXME: do something about IPv6 address literals here.)
|
|
||||||
*/
|
*/
|
||||||
colon = strrchr(ssh->savedhost, ':');
|
colon = host_strrchr(tmphost, ':');
|
||||||
if (colon) {
|
if (colon) {
|
||||||
*colon++ = '\0';
|
*colon++ = '\0';
|
||||||
if (*colon)
|
if (*colon)
|
||||||
ssh->savedport = atoi(colon);
|
ssh->savedport = atoi(colon);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ssh->savedhost = host_strduptrim(tmphost);
|
||||||
|
sfree(tmphost);
|
||||||
} else {
|
} else {
|
||||||
ssh->savedhost = dupstr(host);
|
ssh->savedhost = host_strduptrim(host);
|
||||||
if (port < 0)
|
if (port < 0)
|
||||||
port = 22; /* default ssh port */
|
port = 22; /* default ssh port */
|
||||||
ssh->savedport = port;
|
ssh->savedport = port;
|
||||||
@ -4915,13 +4917,15 @@ static void ssh_setup_portfwd(Ssh ssh, Conf *conf)
|
|||||||
if (*kp == 'L' || *kp == 'R')
|
if (*kp == 'L' || *kp == 'R')
|
||||||
type = *kp++;
|
type = *kp++;
|
||||||
|
|
||||||
if ((kp2 = strchr(kp, ':')) != NULL) {
|
if ((kp2 = host_strchr(kp, ':')) != NULL) {
|
||||||
/*
|
/*
|
||||||
* There's a colon in the middle of the source port
|
* There's a colon in the middle of the source port
|
||||||
* string, which means that the part before it is
|
* string, which means that the part before it is
|
||||||
* actually a source address.
|
* actually a source address.
|
||||||
*/
|
*/
|
||||||
saddr = dupprintf("%.*s", (int)(kp2 - kp), kp);
|
char *saddr_tmp = dupprintf("%.*s", (int)(kp2 - kp), kp);
|
||||||
|
saddr = host_strduptrim(saddr_tmp);
|
||||||
|
sfree(saddr_tmp);
|
||||||
sports = kp2+1;
|
sports = kp2+1;
|
||||||
} else {
|
} else {
|
||||||
saddr = NULL;
|
saddr = NULL;
|
||||||
@ -4948,7 +4952,7 @@ static void ssh_setup_portfwd(Ssh ssh, Conf *conf)
|
|||||||
} else {
|
} else {
|
||||||
/* ordinary forwarding */
|
/* ordinary forwarding */
|
||||||
vp = val;
|
vp = val;
|
||||||
vp2 = vp + strcspn(vp, ":");
|
vp2 = vp + host_strcspn(vp, ":");
|
||||||
host = dupprintf("%.*s", (int)(vp2 - vp), vp);
|
host = dupprintf("%.*s", (int)(vp2 - vp), vp);
|
||||||
if (vp2)
|
if (vp2)
|
||||||
vp2++;
|
vp2++;
|
||||||
@ -11024,7 +11028,11 @@ void ssh_send_port_open(void *channel, char *hostname, int port, char *org)
|
|||||||
PKT_END);
|
PKT_END);
|
||||||
} else {
|
} else {
|
||||||
pktout = ssh2_chanopen_init(c, "direct-tcpip");
|
pktout = ssh2_chanopen_init(c, "direct-tcpip");
|
||||||
ssh2_pkt_addstring(pktout, hostname);
|
{
|
||||||
|
char *trimmed_host = host_strduptrim(hostname);
|
||||||
|
ssh2_pkt_addstring(pktout, trimmed_host);
|
||||||
|
sfree(trimmed_host);
|
||||||
|
}
|
||||||
ssh2_pkt_adduint32(pktout, port);
|
ssh2_pkt_adduint32(pktout, port);
|
||||||
/*
|
/*
|
||||||
* We make up values for the originator data; partly it's
|
* We make up values for the originator data; partly it's
|
||||||
|
11
telnet.c
11
telnet.c
@ -818,16 +818,11 @@ static const char *telnet_init(void *frontend_handle, void **backend_handle,
|
|||||||
|
|
||||||
sfree(*realhost);
|
sfree(*realhost);
|
||||||
*realhost = dupstr(loghost);
|
*realhost = dupstr(loghost);
|
||||||
colon = strrchr(*realhost, ':');
|
|
||||||
if (colon) {
|
colon = host_strrchr(*realhost, ':');
|
||||||
/*
|
if (colon)
|
||||||
* FIXME: if we ever update this aspect of ssh.c for
|
|
||||||
* IPv6 literal management, this should change in line
|
|
||||||
* with it.
|
|
||||||
*/
|
|
||||||
*colon++ = '\0';
|
*colon++ = '\0';
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
12
unix/uxnet.c
12
unix/uxnet.c
@ -221,7 +221,11 @@ SockAddr sk_namelookup(const char *host, char **canonicalname, int address_famil
|
|||||||
hints.ai_addr = NULL;
|
hints.ai_addr = NULL;
|
||||||
hints.ai_canonname = NULL;
|
hints.ai_canonname = NULL;
|
||||||
hints.ai_next = NULL;
|
hints.ai_next = NULL;
|
||||||
err = getaddrinfo(host, NULL, &hints, &ret->ais);
|
{
|
||||||
|
char *trimmed_host = host_strduptrim(host); /* strip [] on literals */
|
||||||
|
err = getaddrinfo(trimmed_host, NULL, &hints, &ret->ais);
|
||||||
|
sfree(trimmed_host);
|
||||||
|
}
|
||||||
if (err != 0) {
|
if (err != 0) {
|
||||||
ret->error = gai_strerror(err);
|
ret->error = gai_strerror(err);
|
||||||
return ret;
|
return ret;
|
||||||
@ -868,7 +872,11 @@ Socket sk_newlistener(char *srcaddr, int port, Plug plug, int local_host_only, i
|
|||||||
hints.ai_next = NULL;
|
hints.ai_next = NULL;
|
||||||
assert(port >= 0 && port <= 99999);
|
assert(port >= 0 && port <= 99999);
|
||||||
sprintf(portstr, "%d", port);
|
sprintf(portstr, "%d", port);
|
||||||
retcode = getaddrinfo(srcaddr, portstr, &hints, &ai);
|
{
|
||||||
|
char *trimmed_addr = host_strduptrim(srcaddr);
|
||||||
|
retcode = getaddrinfo(trimmed_addr, portstr, &hints, &ai);
|
||||||
|
sfree(trimmed_addr);
|
||||||
|
}
|
||||||
if (retcode == 0) {
|
if (retcode == 0) {
|
||||||
addr = (union sockaddr_union *)ai->ai_addr;
|
addr = (union sockaddr_union *)ai->ai_addr;
|
||||||
addrlen = ai->ai_addrlen;
|
addrlen = ai->ai_addrlen;
|
||||||
|
@ -705,8 +705,7 @@ int main(int argc, char **argv)
|
|||||||
q += 2;
|
q += 2;
|
||||||
conf_set_int(conf, CONF_protocol, PROT_TELNET);
|
conf_set_int(conf, CONF_protocol, PROT_TELNET);
|
||||||
p = q;
|
p = q;
|
||||||
while (*p && *p != ':' && *p != '/')
|
p += host_strcspn(p, ":/");
|
||||||
p++;
|
|
||||||
c = *p;
|
c = *p;
|
||||||
if (*p)
|
if (*p)
|
||||||
*p++ = '\0';
|
*p++ = '\0';
|
||||||
@ -847,7 +846,7 @@ int main(int argc, char **argv)
|
|||||||
/*
|
/*
|
||||||
* Trim off a colon suffix if it's there.
|
* Trim off a colon suffix if it's there.
|
||||||
*/
|
*/
|
||||||
host[strcspn(host, ":")] = '\0';
|
host[host_strcspn(host, ":")] = '\0';
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Remove any remaining whitespace.
|
* Remove any remaining whitespace.
|
||||||
|
@ -76,8 +76,7 @@ int process_nonoption_arg(char *arg, Conf *conf, int *allow_launch)
|
|||||||
q += 2;
|
q += 2;
|
||||||
conf_set_int(conf, CONF_protocol, PROT_TELNET);
|
conf_set_int(conf, CONF_protocol, PROT_TELNET);
|
||||||
p = q;
|
p = q;
|
||||||
while (*p && *p != ':' && *p != '/')
|
p += host_strcspn(p, ":/");
|
||||||
p++;
|
|
||||||
c = *p;
|
c = *p;
|
||||||
if (*p)
|
if (*p)
|
||||||
*p++ = '\0';
|
*p++ = '\0';
|
||||||
|
@ -548,8 +548,7 @@ int WINAPI WinMain(HINSTANCE inst, HINSTANCE prev, LPSTR cmdline, int show)
|
|||||||
q += 2;
|
q += 2;
|
||||||
conf_set_int(conf, CONF_protocol, PROT_TELNET);
|
conf_set_int(conf, CONF_protocol, PROT_TELNET);
|
||||||
p = q;
|
p = q;
|
||||||
while (*p && *p != ':' && *p != '/')
|
p += host_strcspn(p, ":/");
|
||||||
p++;
|
|
||||||
c = *p;
|
c = *p;
|
||||||
if (*p)
|
if (*p)
|
||||||
*p++ = '\0';
|
*p++ = '\0';
|
||||||
@ -614,15 +613,15 @@ int WINAPI WinMain(HINSTANCE inst, HINSTANCE prev, LPSTR cmdline, int show)
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
* Trim a colon suffix off the hostname if it's there. In
|
* Trim a colon suffix off the hostname if it's there. In
|
||||||
* order to protect IPv6 address literals against this
|
* order to protect unbracketed IPv6 address literals
|
||||||
* treatment, we do not do this if there's _more_ than one
|
* against this treatment, we do not do this if there's
|
||||||
* colon.
|
* _more_ than one colon.
|
||||||
*/
|
*/
|
||||||
{
|
{
|
||||||
char *c = strchr(host, ':');
|
char *c = host_strchr(host, ':');
|
||||||
|
|
||||||
if (c) {
|
if (c) {
|
||||||
char *d = strchr(c+1, ':');
|
char *d = host_strchr(c+1, ':');
|
||||||
if (!d)
|
if (!d)
|
||||||
*c = '\0';
|
*c = '\0';
|
||||||
}
|
}
|
||||||
|
@ -527,7 +527,13 @@ SockAddr sk_namelookup(const char *host, char **canonicalname,
|
|||||||
memset(&hints, 0, sizeof(hints));
|
memset(&hints, 0, sizeof(hints));
|
||||||
hints.ai_family = hint_family;
|
hints.ai_family = hint_family;
|
||||||
hints.ai_flags = AI_CANONNAME;
|
hints.ai_flags = AI_CANONNAME;
|
||||||
if ((err = p_getaddrinfo(host, NULL, &hints, &ret->ais)) == 0)
|
{
|
||||||
|
/* strip [] on IPv6 address literals */
|
||||||
|
char *trimmed_host = host_strduptrim(host);
|
||||||
|
err = p_getaddrinfo(trimmed_host, NULL, &hints, &ret->ais);
|
||||||
|
sfree(trimmed_host);
|
||||||
|
}
|
||||||
|
if (err == 0)
|
||||||
ret->resolved = TRUE;
|
ret->resolved = TRUE;
|
||||||
} else
|
} else
|
||||||
#endif
|
#endif
|
||||||
|
@ -382,8 +382,7 @@ int main(int argc, char **argv)
|
|||||||
q += 2;
|
q += 2;
|
||||||
conf_set_int(conf, CONF_protocol, PROT_TELNET);
|
conf_set_int(conf, CONF_protocol, PROT_TELNET);
|
||||||
p = q;
|
p = q;
|
||||||
while (*p && *p != ':' && *p != '/')
|
p += host_strcspn(p, ":/");
|
||||||
p++;
|
|
||||||
c = *p;
|
c = *p;
|
||||||
if (*p)
|
if (*p)
|
||||||
*p++ = '\0';
|
*p++ = '\0';
|
||||||
@ -524,7 +523,7 @@ int main(int argc, char **argv)
|
|||||||
/*
|
/*
|
||||||
* Trim off a colon suffix if it's there.
|
* Trim off a colon suffix if it's there.
|
||||||
*/
|
*/
|
||||||
host[strcspn(host, ":")] = '\0';
|
host[host_strcspn(host, ":")] = '\0';
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Remove any remaining whitespace.
|
* Remove any remaining whitespace.
|
||||||
|
4
x11fwd.c
4
x11fwd.c
@ -230,7 +230,7 @@ struct X11Display *x11_setup_display(char *display, Conf *conf)
|
|||||||
char *colon, *dot, *slash;
|
char *colon, *dot, *slash;
|
||||||
char *protocol, *hostname;
|
char *protocol, *hostname;
|
||||||
|
|
||||||
colon = strrchr(localcopy, ':');
|
colon = host_strrchr(localcopy, ':');
|
||||||
if (!colon) {
|
if (!colon) {
|
||||||
sfree(disp);
|
sfree(disp);
|
||||||
sfree(localcopy);
|
sfree(localcopy);
|
||||||
@ -677,7 +677,7 @@ int x11_get_screen_number(char *display)
|
|||||||
{
|
{
|
||||||
int n;
|
int n;
|
||||||
|
|
||||||
n = strcspn(display, ":");
|
n = host_strcspn(display, ":");
|
||||||
if (!display[n])
|
if (!display[n])
|
||||||
return 0;
|
return 0;
|
||||||
n = strcspn(display, ".");
|
n = strcspn(display, ".");
|
||||||
|
Loading…
Reference in New Issue
Block a user