Skip to content

Commit

Permalink
Viewer: Fix issues with IPv6 address handling
Browse files Browse the repository at this point in the history
- Remove brackets from IPv6 addresses before using them to reference
  Preferences nodes.

- Fix several issues that prevented IPv6 addresses from being used as
  VNC hostnames.
  • Loading branch information
dcommander committed Aug 7, 2024
1 parent a254d31 commit 6962f4c
Show file tree
Hide file tree
Showing 6 changed files with 56 additions and 41 deletions.
3 changes: 3 additions & 0 deletions ChangeLog.md
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,9 @@ specified and the session desktop file for the window manager cannot be found.
13. Fixed a regression introduced by 3.0 beta1[24] that caused the TurboVNC
Server to leak memory when the RFB flow control extensions were used.

14. Fixed several issues in the TurboVNC Viewer that prevented IPv6 addresses
from being used as VNC hostnames.


3.0.3
=====
Expand Down
80 changes: 46 additions & 34 deletions java/com/turbovnc/rfb/Hostname.java
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
/* Copyright (C) 2012, 2016, 2018, 2020 D. R. Commander. All Rights Reserved.
/* Copyright (C) 2012, 2016, 2018, 2020, 2023-2024 D. R. Commander.
* All Rights Reserved.
* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved.
*
* This is free software; you can redistribute it and/or modify
Expand All @@ -23,27 +24,56 @@

public final class Hostname {

public static String getHost(String vncServerName) {
// Find the position of the first colon in the display number/port portion of
// the VNC server name.

public static int getColonPos(String vncServerName) {
int colonPos = vncServerName.lastIndexOf(':');
int bracketPos = vncServerName.lastIndexOf(']');
boolean doubleColon = false;

// No colon = hostname only
if (colonPos == -1)
return -1;
// Last colon is inside square brackets = IPv6 address only
if (bracketPos != -1 && colonPos < bracketPos)
colonPos = -1;
while (colonPos > 0 && vncServerName.charAt(colonPos - 1) == ':') {
return -1;
// If the last colon is part of a series, then find the first colon in the
// series.
while (colonPos > 0 && vncServerName.charAt(colonPos - 1) == ':')
colonPos--;
doubleColon = true;
if (colonPos == 0) {
// IPv6 loopback address only (special case)
if (vncServerName.equals("::1"))
return -1;
// Display number/port specified without host
return colonPos;
}
if (doubleColon) {
// Check for preceding single colon, indicating an IPv6 address
for (int p = colonPos - 1; p >= 0; p--) {
if (vncServerName.charAt(p) == ':') {
if (p == 0 || vncServerName.charAt(p - 1) != ':')
colonPos = -1;
break;
}
}
// Display number/port specified with bracketed IPv6 address
if (bracketPos != -1 && colonPos - 1 == bracketPos)
return colonPos;

// Check for preceding colons, indicating an IPv6 address.
int colonCount = 0, p = colonPos;
while ((p = vncServerName.lastIndexOf(':', p - 1)) > 0) {
// Double colon = abbreviated IPv6 address
if (vncServerName.charAt(p - 1) == ':')
return colonPos;
colonCount++;
// 7 colons = full IPv6 address
if (colonCount >= 7)
return colonPos;
}
// Invalid format (IPv6 address is incomplete or hostname contains colons)
if (colonCount > 0)
return -1;

// Display number/port specified with hostname
return colonPos;
}

public static String getHost(String vncServerName) {
int colonPos = getColonPos(vncServerName);

if (colonPos == 0)
return "localhost";
if (colonPos == -1)
Expand All @@ -52,26 +82,8 @@ public static String getHost(String vncServerName) {
}

public static int getPort(String vncServerName) {
int colonPos = vncServerName.lastIndexOf(':');
int bracketPos = vncServerName.lastIndexOf(']');
boolean doubleColon = false;
int colonPos = getColonPos(vncServerName);

if (bracketPos != -1 && colonPos < bracketPos)
colonPos = -1;
while (colonPos > 0 && vncServerName.charAt(colonPos - 1) == ':') {
colonPos--;
doubleColon = true;
}
if (doubleColon) {
// Check for preceding single colon, indicating an IPv6 address
for (int p = colonPos - 1; p >= 0; p--) {
if (vncServerName.charAt(p) == ':') {
if (p == 0 || vncServerName.charAt(p - 1) != ':')
colonPos = -1;
break;
}
}
}
if (colonPos == -1 || colonPos == vncServerName.length() - 1)
return Utils.getBooleanProperty("turbovnc.sessmgr", true) ? 0 : 5900;
if (vncServerName.charAt(colonPos + 1) == ':') {
Expand Down
4 changes: 2 additions & 2 deletions java/com/turbovnc/vncviewer/CConn.java
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,7 @@ public CConn(VncViewer viewer_, Socket sock_) {

if (opts.serverName != null &&
!Params.alwaysShowConnectionDialog.getValue()) {
if (opts.via == null || opts.via.indexOf(':') < 0) {
if (opts.via == null || Hostname.getColonPos(opts.via) < 0) {
port = opts.port = Hostname.getPort(opts.serverName);
serverName = opts.serverName = Hostname.getHost(opts.serverName);
}
Expand All @@ -118,7 +118,7 @@ public CConn(VncViewer viewer_, Socket sock_) {
serverName = opts.serverName;
}

if (opts.via != null && opts.via.indexOf(':') >= 0) {
if (opts.via != null && Hostname.getColonPos(opts.via) >= 0) {
port = Hostname.getPort(opts.via);
serverName = Hostname.getHost(opts.via);
} else if (opts.via != null || opts.tunnel ||
Expand Down
2 changes: 1 addition & 1 deletion java/com/turbovnc/vncviewer/ServerDialog.java
Original file line number Diff line number Diff line change
Expand Up @@ -222,7 +222,7 @@ private boolean commit() {
throw new WarningException("No server name specified");

// set params
if (opts.via != null && opts.via.indexOf(':') >= 0) {
if (opts.via != null && Hostname.getColonPos(opts.via) >= 0) {
opts.serverName = serverName;
} else {
int atIndex = serverName.lastIndexOf('@');
Expand Down
5 changes: 3 additions & 2 deletions java/com/turbovnc/vncviewer/Tunnel.java
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
/* Copyright (C) 2012-2015, 2017-2018, 2020-2023 D. R. Commander.
/* Copyright (C) 2012-2015, 2017-2018, 2020-2024 D. R. Commander.
* All Rights Reserved.
* Copyright (C) 2012, 2016 Brian P. Hinz. All Rights Reserved.
* Copyright (C) 2000 Const Kaplinsky. All Rights Reserved.
Expand Down Expand Up @@ -61,7 +61,7 @@ public static void createTunnel(Options opts) throws Exception {
gatewayHost = opts.via;
remoteHost = Hostname.getHost(opts.serverName);
}
if (opts.serverName != null && opts.serverName.indexOf(':') < 0 &&
if (opts.serverName != null && Hostname.getColonPos(opts.serverName) < 0 &&
opts.port > 0)
remotePort = opts.port;
else
Expand All @@ -85,6 +85,7 @@ public static void createTunnel(Options opts) throws Exception {
vlog.debug("Opening SSH tunnel through gateway " + gatewayHost);
if (opts.sshSession == null)
createTunnelJSch(gatewayHost, opts);
remoteHost = remoteHost.replaceAll("[\\[\\]]", "");
vlog.debug("Forwarding local port " + localPort + " to " + remoteHost +
":" + remotePort + " (relative to gateway)");
opts.sshSession.setPortForwardingL(localPort, remoteHost, remotePort);
Expand Down
3 changes: 1 addition & 2 deletions java/com/turbovnc/vncviewer/VncViewer.java
Original file line number Diff line number Diff line change
Expand Up @@ -625,8 +625,7 @@ public static void tileWindows() {
public void start() {
vlog.debug("start called");
String host = opts.serverName;
if (host != null && host.indexOf(':') < 0 &&
opts.port > 0) {
if (host != null && Hostname.getColonPos(host) < 0 && opts.port > 0) {
opts.serverName = host + ((opts.port >= 5900 && opts.port <= 5999) ?
(":" + (opts.port - 5900)) : ("::" + opts.port));
}
Expand Down

0 comments on commit 6962f4c

Please sign in to comment.