1
0
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:
Simon Tatham 2014-01-25 15:58:54 +00:00
parent 0348f57077
commit 8da4fa5063
14 changed files with 65 additions and 78 deletions

View File

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

View File

@ -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
View File

@ -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
View File

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

View File

@ -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
View File

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

View File

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

View File

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

View File

@ -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.

View File

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

View File

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

View File

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

View File

@ -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.

View File

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