summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBrian P. Hinz <bphinz@users.sf.net>2015-10-09 23:43:42 -0400
committerBrian P. Hinz <bphinz@users.sf.net>2015-10-09 23:43:42 -0400
commit218be2803a981e7449f182ee8657e225ef52f3c0 (patch)
tree63f53fe3f24feae76045bf36dfd47deee61ba97c
parent6a2b6bf396c5f9685d6f282b0abfb55b0f019d80 (diff)
downloadtigervnc-218be2803a981e7449f182ee8657e225ef52f3c0.tar.gz
tigervnc-218be2803a981e7449f182ee8657e225ef52f3c0.zip
Added hostname verification for x509 authentication types
-rw-r--r--java/com/tigervnc/rfb/CSecurityTLS.java83
-rw-r--r--java/com/tigervnc/vncviewer/CConn.java4
2 files changed, 84 insertions, 3 deletions
diff --git a/java/com/tigervnc/rfb/CSecurityTLS.java b/java/com/tigervnc/rfb/CSecurityTLS.java
index e7510c8b..a0166032 100644
--- a/java/com/tigervnc/rfb/CSecurityTLS.java
+++ b/java/com/tigervnc/rfb/CSecurityTLS.java
@@ -42,6 +42,12 @@ import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
+import java.util.Iterator;
+import java.util.List;
+import javax.naming.InvalidNameException;
+import javax.naming.ldap.LdapName;
+import javax.naming.ldap.Rdn;
+import javax.net.ssl.HostnameVerifier;
import javax.swing.JOptionPane;
import javax.xml.bind.DatatypeConverter;
@@ -279,6 +285,7 @@ public class CSecurityTLS extends CSecurity {
MessageDigest md = null;
try {
md = MessageDigest.getInstance("SHA-1");
+ verifyHostname(chain[0]);
tm.checkServerTrusted(chain, authType);
} catch (CertificateException e) {
if (e.getCause() instanceof CertPathBuilderException) {
@@ -349,13 +356,22 @@ public class CSecurityTLS extends CSecurity {
}
}
} else {
- throw new WarningException("X.509 certificate not trusted");
+ throw new SystemException(e.getCause().getMessage());
}
+ } else if (e instanceof MyCertificateParsingException) {
+ Object[] answer = {"YES", "NO"};
+ int ret = JOptionPane.showOptionDialog(null,
+ "Hostname verification failed. Do you want to continue?",
+ "Hostname Verification Failure",
+ JOptionPane.YES_NO_OPTION, JOptionPane.WARNING_MESSAGE,
+ null, answer, answer[0]);
+ if (ret != JOptionPane.YES_OPTION)
+ throw new WarningException("Hostname verification failed.");
} else {
throw new SystemException(e.getCause().getMessage());
}
} catch (java.lang.Exception e) {
- throw new Exception(e.getCause().getMessage());
+ throw new SystemException(e.getCause().getMessage());
}
}
@@ -364,6 +380,68 @@ public class CSecurityTLS extends CSecurity {
return tm.getAcceptedIssuers();
}
+ private void verifyHostname(X509Certificate cert)
+ throws CertificateParsingException
+ {
+ try {
+ Collection sans = cert.getSubjectAlternativeNames();
+ if (sans == null) {
+ String dn = cert.getSubjectX500Principal().getName();
+ LdapName ln = new LdapName(dn);
+ for (Rdn rdn : ln.getRdns()) {
+ if (rdn.getType().equalsIgnoreCase("CN")) {
+ String peer =
+ ((CConn)client).getSocket().getPeerName().toLowerCase();
+ if (peer.equals(((String)rdn.getValue()).toLowerCase()))
+ return;
+ }
+ }
+ } else {
+ Iterator i = sans.iterator();
+ while (i.hasNext()) {
+ List nxt = (List)i.next();
+ if (((Integer)nxt.get(0)).intValue() == 2) {
+ String peer =
+ ((CConn)client).getSocket().getPeerName().toLowerCase();
+ if (peer.equals(((String)nxt.get(1)).toLowerCase()))
+ return;
+ } else if (((Integer)nxt.get(0)).intValue() == 7) {
+ String peer = ((CConn)client).getSocket().getPeerAddress();
+ if (peer.equals(((String)nxt.get(1)).toLowerCase()))
+ return;
+ }
+ }
+ }
+ throw new MyCertificateParsingException();
+ } catch (CertificateParsingException e) {
+ throw new MyCertificateParsingException(e.getCause());
+ } catch (InvalidNameException e) {
+ throw new MyCertificateParsingException(e.getCause());
+ }
+ }
+
+ private class MyCertificateParsingException
+ extends CertificateParsingException
+ {
+
+ public MyCertificateParsingException() {
+ super();
+ }
+
+ public MyCertificateParsingException(String msg) {
+ super(msg);
+ }
+
+ public MyCertificateParsingException(String msg, Throwable cause) {
+ super(msg, cause);
+ }
+
+ public MyCertificateParsingException(Throwable cause) {
+ super(cause);
+ }
+
+ }
+
private class MyFileInputStream extends InputStream {
// Blank lines in a certificate file will cause Java 6 to throw a
// "DerInputStream.getLength(): lengthTag=127, too big" exception.
@@ -412,7 +490,6 @@ public class CSecurityTLS extends CSecurity {
return len;
}
-
@Override
public int read() throws IOException {
if (!buf.hasRemaining())
diff --git a/java/com/tigervnc/vncviewer/CConn.java b/java/com/tigervnc/vncviewer/CConn.java
index 88b25ec0..f592cb54 100644
--- a/java/com/tigervnc/vncviewer/CConn.java
+++ b/java/com/tigervnc/vncviewer/CConn.java
@@ -1411,6 +1411,10 @@ public class CConn extends CConnection implements
public void actionPerformed(ActionEvent e) {}
+ public Socket getSocket() {
+ return sock;
+ }
+
////////////////////////////////////////////////////////////////////
// The following methods are called from both RFB and GUI threads