Skip to content

Commit 3f6bc6c

Browse files
committed
Android: enable saving/loading fingerprints of IPv6 hosts
1 parent 9ddadd4 commit 3f6bc6c

File tree

3 files changed

+31
-8
lines changed

3 files changed

+31
-8
lines changed

android/app/src/main/java/com/coboltforge/dontmind/multivnc/Utils.java

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -131,4 +131,27 @@ public static String byteArrayToColonSeparatedHex(byte[] bytes) {
131131
return hexString.toString();
132132
}
133133

134+
/**
135+
* Formats host and port into a standard URI format that properly handles both IPv4 and IPv6 addresses.
136+
*/
137+
public static String uriFormatHostWithPort(String host, int port) {
138+
// Handle null or empty host
139+
if (host == null || host.isEmpty()) {
140+
return "";
141+
}
142+
143+
// Check if already properly bracketed (e.g., "[2001:db8::1]")
144+
if (host.startsWith("[") && host.endsWith("]")) {
145+
return host + ":" + port;
146+
}
147+
148+
if (host.contains(":")) {
149+
// Likely IPv6 address - bracket it
150+
return "[" + host + "]:" + port;
151+
} else {
152+
// IPv4 address or regular hostname
153+
return host + ":" + port;
154+
}
155+
}
156+
134157
}

android/app/src/main/java/com/coboltforge/dontmind/multivnc/ui/VncCanvas.java

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -905,7 +905,7 @@ public void onClick(DialogInterface dialog, int whichButton) {
905905
public void onRequestSshFingerprintMismatchDecision(String host, int port, byte[] fingerprint, AtomicBoolean doContinue) {
906906
// this method is probably called from the vnc thread
907907
post(() -> {
908-
SshKnownHost maybeFound = VncDatabase.getInstance(getContext()).getSshKnownHostDao().get(host + ":" + port);
908+
SshKnownHost maybeFound = VncDatabase.getInstance(getContext()).getSshKnownHostDao().get(Utils.uriFormatHostWithPort(host, port));
909909
if (maybeFound == null) { // fallback for saves without port
910910
maybeFound = VncDatabase.getInstance(getContext()).getSshKnownHostDao().get(host);
911911
}
@@ -919,7 +919,7 @@ public void onRequestSshFingerprintMismatchDecision(String host, int port, byte[
919919
"SHA256:" + Base64.encodeToString(fingerprint,Base64.NO_PADDING|Base64.NO_WRAP))))
920920
.setCancelable(false)
921921
.setPositiveButton(R.string.ssh_key_new_continue, (dialog12, whichButton) -> {
922-
VncDatabase.getInstance(getContext()).getSshKnownHostDao().insert(new SshKnownHost(0, host + ":" + port, fingerprint));
922+
VncDatabase.getInstance(getContext()).getSshKnownHostDao().insert(new SshKnownHost(0, Utils.uriFormatHostWithPort(host, port), fingerprint));
923923
doContinue.set(true);
924924
synchronized (vncConn) {
925925
vncConn.notify();
@@ -944,7 +944,7 @@ public void onRequestSshFingerprintMismatchDecision(String host, int port, byte[
944944
"SHA256:" + Base64.encodeToString(fingerprint,Base64.NO_PADDING|Base64.NO_WRAP))))
945945
.setCancelable(false)
946946
.setPositiveButton(R.string.ssh_key_mismatch_continue, (dialog12, whichButton) -> {
947-
SshKnownHost updatedHost = new SshKnownHost(knownHost.id, host + ":" + port, fingerprint);
947+
SshKnownHost updatedHost = new SshKnownHost(knownHost.id, Utils.uriFormatHostWithPort(host, port), fingerprint);
948948
VncDatabase.getInstance(getContext()).getSshKnownHostDao().update(updatedHost);
949949
doContinue.set(true);
950950
synchronized (vncConn) {
@@ -969,7 +969,7 @@ public void onRequestSshFingerprintMismatchDecision(String host, int port, byte[
969969
public void onRequestX509FingerprintMismatchDecision(String subject, String validFrom, String validUntil, byte[] fingerprint, final AtomicBoolean decision) {
970970
// this method is probably called from the vnc thread
971971
post(() -> {
972-
X509KnownHost knownHost = VncDatabase.getInstance(getContext()).getX509KnownHostDao().get(vncConn.getConnSettings().address + ":" + vncConn.getConnSettings().port);
972+
X509KnownHost knownHost = VncDatabase.getInstance(getContext()).getX509KnownHostDao().get(Utils.uriFormatHostWithPort(vncConn.getConnSettings().address, vncConn.getConnSettings().port));
973973
if (knownHost == null) {
974974
// no fingerprint expected
975975
AlertDialog dialog = new AlertDialog.Builder(getContext())
@@ -981,7 +981,7 @@ public void onRequestX509FingerprintMismatchDecision(String subject, String vali
981981
Utils.byteArrayToColonSeparatedHex(fingerprint))))
982982
.setCancelable(false)
983983
.setPositiveButton(R.string.x509_key_new_continue, (dialog12, whichButton) -> {
984-
VncDatabase.getInstance(getContext()).getX509KnownHostDao().insert(new X509KnownHost(0, vncConn.getConnSettings().address + ":" + vncConn.getConnSettings().port, fingerprint));
984+
VncDatabase.getInstance(getContext()).getX509KnownHostDao().insert(new X509KnownHost(0, Utils.uriFormatHostWithPort(vncConn.getConnSettings().address, vncConn.getConnSettings().port), fingerprint));
985985
decision.set(true);
986986
synchronized (vncConn) {
987987
vncConn.notify();
@@ -1010,7 +1010,7 @@ public void onRequestX509FingerprintMismatchDecision(String subject, String vali
10101010
.setCancelable(false)
10111011
.setPositiveButton(R.string.x509_key_mismatch_continue, (dialog12, whichButton) -> {
10121012
// update/insert fingerprint of known host
1013-
X509KnownHost updatedHost = new X509KnownHost(knownHost.id, vncConn.getConnSettings().address + ":" + vncConn.getConnSettings().port, fingerprint);
1013+
X509KnownHost updatedHost = new X509KnownHost(knownHost.id, Utils.uriFormatHostWithPort(vncConn.getConnSettings().address, vncConn.getConnSettings().port), fingerprint);
10141014
VncDatabase.getInstance(getContext()).getX509KnownHostDao().update(updatedHost);
10151015
decision.set(true);
10161016
synchronized (vncConn) {

android/app/src/main/java/com/coboltforge/dontmind/multivnc/ui/VncCanvasActivity.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -261,13 +261,13 @@ public void onSystemUiVisibilityChange(int visibility) {
261261
pd.show();
262262
firstFrameWaitDialog = pd;
263263
vncCanvas.initializeVncCanvas(pd, inputHandler, conn); // add conn to canvas
264-
byte[] sshFingerprint = database.getSshKnownHostDao().get(connection.sshHost + ":" + connection.sshPort) != null ? database.getSshKnownHostDao().get(connection.sshHost + ":" + connection.sshPort).fingerprint : null;
264+
byte[] sshFingerprint = database.getSshKnownHostDao().get(Utils.uriFormatHostWithPort(connection.sshHost, connection.sshPort)) != null ? database.getSshKnownHostDao().get(Utils.uriFormatHostWithPort(connection.sshHost, connection.sshPort)).fingerprint : null;
265265
if (sshFingerprint == null) { // fallback for saves without port
266266
sshFingerprint = database.getSshKnownHostDao().get(connection.sshHost) != null ? database.getSshKnownHostDao().get(connection.sshHost).fingerprint : null;
267267
}
268268
conn.init(connection,
269269
sshFingerprint,
270-
database.getX509KnownHostDao().get(connection.address + ":" + connection.port) != null ? database.getX509KnownHostDao().get(connection.address + ":" + connection.port).fingerprint : null,
270+
database.getX509KnownHostDao().get(Utils.uriFormatHostWithPort(connection.address, connection.port)) != null ? database.getX509KnownHostDao().get(Utils.uriFormatHostWithPort(connection.address, connection.port)).fingerprint : null,
271271
// onInit
272272
initError -> runOnUiThread(() -> {
273273
if(isFinishing()) {

0 commit comments

Comments
 (0)