? sslhostname.patch Index: org/postgresql/ssl/MakeSSL.java =================================================================== RCS file: /cvsroot/jdbc/pgjdbc/org/postgresql/ssl/MakeSSL.java,v retrieving revision 1.7 diff -r1.7 MakeSSL.java 11a12,14 > import java.util.Collection; > import java.util.Iterator; > import java.util.List; 15a19,23 > import java.security.cert.CertificateParsingException; > import java.security.cert.X509Certificate; > > import javax.net.ssl.SSLPeerUnverifiedException; > import javax.net.ssl.SSLSocket; 16a25 > import javax.security.auth.x500.X500Principal; 63c72,141 < Socket newConnection = factory.createSocket(stream.getSocket(), stream.getHost(), stream.getPort(), true); --- > SSLSocket newConnection = (SSLSocket)factory.createSocket(stream.getSocket(), stream.getHost(), stream.getPort(), true); > X509Certificate[] peerCerts = (X509Certificate[])newConnection.getSession().getPeerCertificates(); > if (peerCerts == null || peerCerts.length == 0) { > throw new SSLPeerUnverifiedException("Could not find peer certificates!"); > } > X509Certificate serverCert = peerCerts[0]; > try { > boolean foundHostName = false; > // Look for host name in the certificate subjectAltName (DNS entries) > Collection subjectAltNames = serverCert.getSubjectAlternativeNames(); > Iterator subjectAltNameIt = subjectAltNames.iterator(); > while (subjectAltNameIt.hasNext()) { > List subjectAltNameEntry = (List)subjectAltNameIt.next(); > Integer subjectAltNameEntryType = (Integer)subjectAltNameEntry.get(0); > if (!subjectAltNameEntryType.equals(Integer.valueOf(2))) { > continue; > } > String subjectAltNameEntryValue = (String)subjectAltNameEntry.get(1); > if (stream.getHost().equalsIgnoreCase(subjectAltNameEntryValue)) { > foundHostName = true; > break; > } > } > if (!foundHostName) { > // If not found in subjectAltNames, look for CN in Subject DN > String subjectDN = serverCert.getSubjectX500Principal().getName(X500Principal.RFC2253); > // RDNs are separated with ','. AVAs within each RDN are separated with '+' > String avaName = null; > String avaValue = null; > int avaStart = 0; > for (int i = 0; i < subjectDN.length(); i++) { > char currentChar = subjectDN.charAt(i); > if (currentChar == '\\') { > continue; > } > if (avaName == null) { > if (currentChar == '=') { > avaName = subjectDN.substring(avaStart, i); > avaStart = i + 1; > } > } else { > if (currentChar == '+') { > // This is an RDN with multiple AVAs, discarded (RFC 6125 2.3.1) > avaName = "DISCARDED"; > } > if (currentChar == ',') { > avaValue = subjectDN.substring(avaStart, i); > avaStart = i + 1; > if ("CN".equals(avaName) && stream.getHost().equalsIgnoreCase(avaValue)) { > foundHostName = true; > avaName = null; > break; > } > avaName = null; > } > } > if (avaName != null) { > avaValue = subjectDN.substring(avaStart); > if ("CN".equals(avaName) && stream.getHost().equalsIgnoreCase(avaValue)) { > foundHostName = true; > } > } > } > } > if (!foundHostName) { > throw new SSLPeerUnverifiedException("Could not find requested host name ("+stream.getHost()+") in the certificate."); > } > } catch (CertificateParsingException e) { > throw new SSLPeerUnverifiedException(e.getMessage()); > }