diff --git a/U_allow_multiple_certs_with_same_dn_in_saved_certs_file.patch b/U_allow_multiple_certs_with_same_dn_in_saved_certs_file.patch new file mode 100644 index 0000000..b8cdffa --- /dev/null +++ b/U_allow_multiple_certs_with_same_dn_in_saved_certs_file.patch @@ -0,0 +1,87 @@ +Git-commit: 7fcc8614e1ff8c19fd3a1a275fa5ab6eda28f6bd +Author: "Brian P. Hinz" +Subject: Allow multiple certs with same DN in saved certs file. +Signed-off-by: Michal Srb +References: bnc#1041847 + + +diff --git a/java/com/tigervnc/rfb/CSecurityTLS.java b/java/com/tigervnc/rfb/CSecurityTLS.java +index 4b20e0bf..08aa1125 100644 +--- a/java/com/tigervnc/rfb/CSecurityTLS.java ++++ b/java/com/tigervnc/rfb/CSecurityTLS.java +@@ -218,9 +218,8 @@ public class CSecurityTLS extends CSecurity { + Collection cacerts = + cf.generateCertificates(caStream); + for (Certificate cert : cacerts) { +- String dn = +- ((X509Certificate)cert).getSubjectX500Principal().getName(); +- ks.setCertificateEntry(dn, (X509Certificate)cert); ++ String thumbprint = getThumbprint((X509Certificate)cert); ++ ks.setCertificateEntry(thumbprint, (X509Certificate)cert); + } + } + File cacert = new File(cafile); +@@ -229,9 +228,8 @@ public class CSecurityTLS extends CSecurity { + Collection cacerts = + cf.generateCertificates(caStream); + for (Certificate cert : cacerts) { +- String dn = +- ((X509Certificate)cert).getSubjectX500Principal().getName(); +- ks.setCertificateEntry(dn, (X509Certificate)cert); ++ String thumbprint = getThumbprint((X509Certificate)cert); ++ ks.setCertificateEntry(thumbprint, (X509Certificate)cert); + } + } + PKIXBuilderParameters params = +@@ -264,19 +262,13 @@ public class CSecurityTLS extends CSecurity { + public void checkServerTrusted(X509Certificate[] chain, String authType) + throws CertificateException + { +- MessageDigest md = null; + try { +- md = MessageDigest.getInstance("SHA-1"); + verifyHostname(chain[0]); + tm.checkServerTrusted(chain, authType); + } catch (java.lang.Exception e) { + if (e.getCause() instanceof CertPathBuilderException) { + Object[] answer = {"YES", "NO"}; + X509Certificate cert = chain[0]; +- md.update(cert.getEncoded()); +- String thumbprint = +- DatatypeConverter.printHexBinary(md.digest()); +- thumbprint = thumbprint.replaceAll("..(?!$)", "$0 "); + int ret = JOptionPane.showOptionDialog(null, + "This certificate has been signed by an unknown authority\n"+ + "\n"+ +@@ -287,7 +279,7 @@ public class CSecurityTLS extends CSecurity { + " Signature Algorithm: "+cert.getPublicKey().getAlgorithm()+"\n"+ + " Not Valid Before: "+cert.getNotBefore()+"\n"+ + " Not Valid After: "+cert.getNotAfter()+"\n"+ +- " SHA1 Fingerprint: "+thumbprint+"\n"+ ++ " SHA1 Fingerprint: "+getThumbprint(cert)+"\n"+ + "\n"+ + "Do you want to save it and continue?", + "Certificate Issuer Unknown", +@@ -351,6 +343,22 @@ public class CSecurityTLS extends CSecurity { + return tm.getAcceptedIssuers(); + } + ++ private String getThumbprint(X509Certificate cert) ++ { ++ String thumbprint = null; ++ try { ++ MessageDigest md = MessageDigest.getInstance("SHA-1"); ++ md.update(cert.getEncoded()); ++ thumbprint = DatatypeConverter.printHexBinary(md.digest()); ++ thumbprint = thumbprint.replaceAll("..(?!$)", "$0 "); ++ } catch(CertificateEncodingException e) { ++ throw new SystemException(e.getMessage()); ++ } catch(NoSuchAlgorithmException e) { ++ throw new SystemException(e.getMessage()); ++ } ++ return thumbprint; ++ } ++ + private void verifyHostname(X509Certificate cert) + throws CertificateParsingException + { diff --git a/U_handle_certificate_verification_for_saved_certs_correctly.patch b/U_handle_certificate_verification_for_saved_certs_correctly.patch new file mode 100644 index 0000000..ca19463 --- /dev/null +++ b/U_handle_certificate_verification_for_saved_certs_correctly.patch @@ -0,0 +1,131 @@ +Git-commit: 79314c2f6abef363a83cc406de5d6628410e53e5 +Author: "Brian P. Hinz" +Subject: Handle certificate verification for saved certs correctly +Signed-off-by: Michal Srb +References: bnc#1041847 + + +diff --git a/java/com/tigervnc/rfb/CSecurityTLS.java b/java/com/tigervnc/rfb/CSecurityTLS.java +index 08aa1125..733e97d4 100644 +--- a/java/com/tigervnc/rfb/CSecurityTLS.java ++++ b/java/com/tigervnc/rfb/CSecurityTLS.java +@@ -3,7 +3,7 @@ + * Copyright (C) 2005 Martin Koegler + * Copyright (C) 2010 m-privacy GmbH + * Copyright (C) 2010 TigerVNC Team +- * Copyright (C) 2011-2015 Brian P. Hinz ++ * Copyright (C) 2011-2017 Brian P. Hinz + * Copyright (C) 2015 D. R. Commander. All Rights Reserved. + * + * This is free software; you can redistribute it and/or modify +@@ -211,17 +211,7 @@ public class CSecurityTLS extends CSecurity { + for (TrustManager m : tmf.getTrustManagers()) + if (m instanceof X509TrustManager) + for (X509Certificate c : ((X509TrustManager)m).getAcceptedIssuers()) +- ks.setCertificateEntry(c.getSubjectX500Principal().getName(), c); +- File castore = new File(FileUtils.getVncHomeDir()+"x509_savedcerts.pem"); +- if (castore.exists() && castore.canRead()) { +- InputStream caStream = new MyFileInputStream(castore); +- Collection cacerts = +- cf.generateCertificates(caStream); +- for (Certificate cert : cacerts) { +- String thumbprint = getThumbprint((X509Certificate)cert); +- ks.setCertificateEntry(thumbprint, (X509Certificate)cert); +- } +- } ++ ks.setCertificateEntry(getThumbprint((X509Certificate)c), c); + File cacert = new File(cafile); + if (cacert.exists() && cacert.canRead()) { + InputStream caStream = new MyFileInputStream(cacert); +@@ -262,13 +252,25 @@ public class CSecurityTLS extends CSecurity { + public void checkServerTrusted(X509Certificate[] chain, String authType) + throws CertificateException + { ++ Collection certs = null; ++ X509Certificate cert = chain[0]; ++ String thumbprint = getThumbprint(cert); ++ File vncDir = new File(FileUtils.getVncHomeDir()); ++ File certFile = new File(vncDir, "x509_savedcerts.pem"); ++ CertificateFactory cf = CertificateFactory.getInstance("X.509"); ++ if (vncDir.exists() && certFile.exists() && certFile.canRead()) { ++ InputStream certStream = new MyFileInputStream(certFile); ++ certs = cf.generateCertificates(certStream); ++ for (Certificate c : certs) ++ if (thumbprint.equals(getThumbprint((X509Certificate)c))) ++ return; ++ } + try { +- verifyHostname(chain[0]); ++ verifyHostname(cert); + tm.checkServerTrusted(chain, authType); + } catch (java.lang.Exception e) { + if (e.getCause() instanceof CertPathBuilderException) { + Object[] answer = {"YES", "NO"}; +- X509Certificate cert = chain[0]; + int ret = JOptionPane.showOptionDialog(null, + "This certificate has been signed by an unknown authority\n"+ + "\n"+ +@@ -286,13 +288,10 @@ public class CSecurityTLS extends CSecurity { + JOptionPane.YES_NO_OPTION, JOptionPane.WARNING_MESSAGE, + null, answer, answer[0]); + if (ret == JOptionPane.YES_OPTION) { +- Collection cacerts = null; +- File vncDir = new File(FileUtils.getVncHomeDir()); +- File caFile = new File(vncDir, "x509_savedcerts.pem"); + try { + if (!vncDir.exists()) + vncDir.mkdir(); +- if (!caFile.createNewFile()) { ++ if (!certFile.exists() && !certFile.createNewFile()) { + vlog.error("Certificate save failed."); + return; + } +@@ -301,31 +300,24 @@ public class CSecurityTLS extends CSecurity { + vlog.error("Certificate save failed: "+ioe.getMessage()); + return; + } +- InputStream caStream = new MyFileInputStream(caFile); +- CertificateFactory cf = +- CertificateFactory.getInstance("X.509"); +- cacerts = +- (Collection )cf.generateCertificates(caStream); +- for (int i = 0; i < chain.length; i++) { +- if (cacerts == null || !cacerts.contains(chain[i])) { +- byte[] der = chain[i].getEncoded(); +- String pem = DatatypeConverter.printBase64Binary(der); +- pem = pem.replaceAll("(.{64})", "$1\n"); +- FileWriter fw = null; ++ if (certs == null || !certs.contains(cert)) { ++ byte[] der = cert.getEncoded(); ++ String pem = DatatypeConverter.printBase64Binary(der); ++ pem = pem.replaceAll("(.{64})", "$1\n"); ++ FileWriter fw = null; ++ try { ++ fw = new FileWriter(certFile.getAbsolutePath(), true); ++ fw.write("-----BEGIN CERTIFICATE-----\n"); ++ fw.write(pem+"\n"); ++ fw.write("-----END CERTIFICATE-----\n"); ++ } catch (IOException ioe) { ++ throw new Exception(ioe.getMessage()); ++ } finally { + try { +- fw = new FileWriter(caFile.getAbsolutePath(), true); +- fw.write("-----BEGIN CERTIFICATE-----\n"); +- fw.write(pem+"\n"); +- fw.write("-----END CERTIFICATE-----\n"); +- } catch (IOException ioe) { +- throw new Exception(ioe.getMessage()); +- } finally { +- try { +- if (fw != null) +- fw.close(); +- } catch(IOException ioe2) { +- throw new Exception(ioe2.getMessage()); +- } ++ if (fw != null) ++ fw.close(); ++ } catch(IOException ioe2) { ++ throw new Exception(ioe2.getMessage()); + } + } + } diff --git a/tigervnc.changes b/tigervnc.changes index 01671b2..f056deb 100644 --- a/tigervnc.changes +++ b/tigervnc.changes @@ -1,3 +1,16 @@ +------------------------------------------------------------------- +Thu Jul 20 07:49:41 UTC 2017 - msrb@suse.com + +- U_allow_multiple_certs_with_same_dn_in_saved_certs_file.patch, + U_handle_certificate_verification_for_saved_certs_correctly.patch + * Fix certificate handling in the java client. (bnc#1041847) + +- Refresh u_tigervnc-add-autoaccept-parameter.patch and apply it + last. + +- Make sure CN in generated certificate doesn't exceed 64 + characters. (bnc#1041847) + ------------------------------------------------------------------- Fri Jul 7 08:06:00 UTC 2017 - msrb@suse.com diff --git a/tigervnc.spec b/tigervnc.spec index ccd768b..3115434 100644 --- a/tigervnc.spec +++ b/tigervnc.spec @@ -116,10 +116,12 @@ Patch2: tigervnc-clean-pressed-key-on-exit.patch Patch3: u_tigervnc-ignore-epipe-on-write.patch Patch4: n_tigervnc-date-time.patch Patch5: u_tigervnc-cve-2014-8240.patch -Patch6: u_tigervnc-add-autoaccept-parameter.patch -Patch7: u_tigervnc_update_default_vncxstartup.patch -Patch8: u_build_libXvnc_as_separate_library.patch -Patch9: u_tigervnc-show-unencrypted-warning.patch +Patch6: u_tigervnc_update_default_vncxstartup.patch +Patch7: u_build_libXvnc_as_separate_library.patch +Patch8: u_tigervnc-show-unencrypted-warning.patch +Patch9: U_allow_multiple_certs_with_same_dn_in_saved_certs_file.patch +Patch10: U_handle_certificate_verification_for_saved_certs_correctly.patch +Patch11: u_tigervnc-add-autoaccept-parameter.patch %description TigerVNC is a high-performance, platform-neutral implementation of VNC (Virtual Network Computing), @@ -180,6 +182,8 @@ cp -r /usr/src/xserver/* unix/xserver/ %patch7 -p1 %patch8 -p1 %patch9 -p1 +%patch10 -p1 +%patch11 -p1 pushd unix/xserver patch -p1 < ../xserver119.patch diff --git a/u_tigervnc-add-autoaccept-parameter.patch b/u_tigervnc-add-autoaccept-parameter.patch index 7fb8261..bb0bf24 100644 --- a/u_tigervnc-add-autoaccept-parameter.patch +++ b/u_tigervnc-add-autoaccept-parameter.patch @@ -20,19 +20,18 @@ Index: tigervnc-1.8.0/java/com/tigervnc/rfb/CSecurityTLS.java } public static String getDefaultCA() { -@@ -277,6 +281,11 @@ public class CSecurityTLS extends CSecur - String thumbprint = - DatatypeConverter.printHexBinary(md.digest()); - thumbprint = thumbprint.replaceAll("..(?!$)", "$0 "); -+ +@@ -270,6 +274,10 @@ public class CSecurityTLS extends CSecur + tm.checkServerTrusted(chain, authType); + } catch (java.lang.Exception e) { + if (e.getCause() instanceof CertPathBuilderException) { + if (certautoaccept != null && thumbprint.equalsIgnoreCase(certautoaccept)) { + return; + } + + Object[] answer = {"YES", "NO"}; int ret = JOptionPane.showOptionDialog(null, "This certificate has been signed by an unknown authority\n"+ - "\n"+ -@@ -466,7 +475,7 @@ public class CSecurityTLS extends CSecur +@@ -466,7 +474,7 @@ public class CSecurityTLS extends CSecur private SSLEngineManager manager; private boolean anon; diff --git a/with-vnc-key.sh b/with-vnc-key.sh index d7a400c..8da6bdc 100644 --- a/with-vnc-key.sh +++ b/with-vnc-key.sh @@ -26,6 +26,7 @@ fi if ! test -e $TLSCERT ; then # Keeping it short, because hostname could be long and max CN is 64 characters CN="VNC service on `hostname`" + CN=${CN:0:64} openssl req -new -x509 -extensions usr_cert -key $TLSKEY -out $TLSCERT -days 7305 -subj "/CN=$CN/" chown vnc:vnc $TLSCERT fi