diff options
author | Brian Hinz <bphinz@users.sf.net> | 2015-10-09 23:46:13 -0400 |
---|---|---|
committer | Brian Hinz <bphinz@users.sf.net> | 2015-10-09 23:46:13 -0400 |
commit | bbbead479fde4b70dd722547933c7f9d506db791 (patch) | |
tree | 63f53fe3f24feae76045bf36dfd47deee61ba97c | |
parent | 6a2b6bf396c5f9685d6f282b0abfb55b0f019d80 (diff) | |
parent | 218be2803a981e7449f182ee8657e225ef52f3c0 (diff) | |
download | tigervnc-bbbead479fde4b70dd722547933c7f9d506db791.tar.gz tigervnc-bbbead479fde4b70dd722547933c7f9d506db791.zip |
Merge pull request #214 from bphinz/java-HostnameVerifier
Added hostname verification for x509 authentication types to java viewer
-rw-r--r-- | java/com/tigervnc/rfb/CSecurityTLS.java | 83 | ||||
-rw-r--r-- | java/com/tigervnc/vncviewer/CConn.java | 4 |
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 |