1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28 package org.apache.hc.client5.http.ssl;
29
30 import java.security.cert.Certificate;
31 import java.security.cert.X509Certificate;
32 import java.util.ArrayList;
33 import java.util.Collection;
34 import java.util.List;
35
36 import javax.net.ssl.HostnameVerifier;
37 import javax.net.ssl.SSLException;
38 import javax.net.ssl.SSLPeerUnverifiedException;
39 import javax.net.ssl.SSLSession;
40 import javax.security.auth.x500.X500Principal;
41
42 import org.slf4j.Logger;
43
44 final class TlsSessionValidator {
45
46 private final Logger log;
47
48 TlsSessionValidator(final Logger log) {
49 this.log = log;
50 }
51
52 void verifySession(
53 final String hostname,
54 final SSLSession sslsession,
55 final HostnameVerifier hostnameVerifier) throws SSLException {
56
57 if (log.isDebugEnabled()) {
58 log.debug("Secure session established");
59 log.debug(" negotiated protocol: {}", sslsession.getProtocol());
60 log.debug(" negotiated cipher suite: {}", sslsession.getCipherSuite());
61
62 try {
63
64 final Certificate[] certs = sslsession.getPeerCertificates();
65 final Certificate cert = certs[0];
66 if (cert instanceof X509Certificate) {
67 final X509Certificate x509 = (X509Certificate) cert;
68 final X500Principal peer = x509.getSubjectX500Principal();
69
70 log.debug(" peer principal: {}", peer);
71 final Collection<List<?>> altNames1 = x509.getSubjectAlternativeNames();
72 if (altNames1 != null) {
73 final List<String> altNames = new ArrayList<>();
74 for (final List<?> aC : altNames1) {
75 if (!aC.isEmpty()) {
76 altNames.add((String) aC.get(1));
77 }
78 }
79 log.debug(" peer alternative names: {}", altNames);
80 }
81
82 final X500Principal issuer = x509.getIssuerX500Principal();
83 log.debug(" issuer principal: {}", issuer);
84 final Collection<List<?>> altNames2 = x509.getIssuerAlternativeNames();
85 if (altNames2 != null) {
86 final List<String> altNames = new ArrayList<>();
87 for (final List<?> aC : altNames2) {
88 if (!aC.isEmpty()) {
89 altNames.add((String) aC.get(1));
90 }
91 }
92 log.debug(" issuer alternative names: {}", altNames);
93 }
94 }
95 } catch (final Exception ignore) {
96 }
97 }
98
99 if (hostnameVerifier != null) {
100 final Certificate[] certs = sslsession.getPeerCertificates();
101 if (certs.length < 1) {
102 throw new SSLPeerUnverifiedException("Peer certificate chain is empty");
103 }
104 final Certificate peerCertificate = certs[0];
105 final X509Certificate x509Certificate;
106 if (peerCertificate instanceof X509Certificate) {
107 x509Certificate = (X509Certificate) peerCertificate;
108 } else {
109 throw new SSLPeerUnverifiedException("Unexpected certificate type: " + peerCertificate.getType());
110 }
111 if (hostnameVerifier instanceof HttpClientHostnameVerifier) {
112 ((HttpClientHostnameVerifier) hostnameVerifier).verify(hostname, x509Certificate);
113 } else if (!hostnameVerifier.verify(hostname, sslsession)) {
114 final List<SubjectName> subjectAlts = DefaultHostnameVerifier.getSubjectAltNames(x509Certificate);
115 throw new SSLPeerUnverifiedException("Certificate for <" + hostname + "> doesn't match any " +
116 "of the subject alternative names: " + subjectAlts);
117 }
118 }
119 }
120
121 }