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