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
29
30 package dk.sosi.seal.ssl;
31
32 import javax.net.ssl.X509TrustManager;
33 import java.security.InvalidKeyException;
34 import java.security.NoSuchAlgorithmException;
35 import java.security.NoSuchProviderException;
36 import java.security.SignatureException;
37 import java.security.cert.CertificateEncodingException;
38 import java.security.cert.CertificateException;
39 import java.security.cert.X509Certificate;
40 import java.util.ArrayList;
41 import java.util.Arrays;
42 import java.util.Iterator;
43 import java.util.List;
44
45
46
47
48
49
50
51
52
53
54
55 public class SOSITrustManager implements X509TrustManager {
56
57 private List<X509Certificate> trustedCertificates;
58
59 public SOSITrustManager() {
60 super();
61 trustedCertificates = new ArrayList<X509Certificate>();
62 }
63
64
65
66
67
68
69 public void checkClientTrusted(X509Certificate[] chain, String authType) {
70 }
71
72
73
74
75
76
77
78 public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException {
79
80 if (!isChainValid(chain)) {
81 throw new CertificateException("Presented chain is not valid.");
82 }
83
84 if (!isTrustedCertificate(getTerminatingCertificate(chain))) {
85 throw new CertificateException("Presented chain is not trusted");
86 }
87
88 }
89
90
91
92
93
94
95 public X509Certificate[] getAcceptedIssuers() {
96 return trustedCertificates.toArray(new X509Certificate[0]);
97 }
98
99
100
101
102
103 public void addTrustedCertificate(X509Certificate trusted) {
104 trustedCertificates.add(trusted);
105 }
106
107
108 private boolean isChainValid(X509Certificate[] chain) throws CertificateException {
109
110 if (chain.length == 1) {
111 return true;
112 }
113
114 boolean issuerFirst = isIssuerFirstOrdering(chain);
115 for (int i = 0; i < chain.length - 1; i++) {
116 chain[i].checkValidity();
117
118 X509Certificate issuer;
119 X509Certificate subject;
120
121 if (issuerFirst) {
122 issuer = chain[i];
123 subject = chain[i + 1];
124 } else {
125 issuer = chain[i + 1];
126 subject = chain[i];
127 }
128
129 if (!isIssuerSubjectPair(issuer, subject)) {
130 return false;
131 }
132
133 }
134
135 return true;
136 }
137
138
139 private boolean isIssuerFirstOrdering(X509Certificate[] chain) {
140 if(chain.length == 1) return true;
141 return chain[0].getSubjectDN().equals(chain[1].getIssuerDN());
142 }
143
144 private boolean isIssuerSubjectPair(X509Certificate issuer, X509Certificate subject) throws CertificateException {
145 try {
146 subject.verify(issuer.getPublicKey());
147 return true;
148 } catch (InvalidKeyException e) {
149
150 } catch (NoSuchAlgorithmException e) {
151 throw new RuntimeException(e);
152 } catch (NoSuchProviderException e) {
153 throw new RuntimeException(e);
154 } catch (SignatureException e) {
155
156 }
157 return false;
158
159 }
160
161 private X509Certificate getTerminatingCertificate(X509Certificate[] chain) {
162 if (isIssuerFirstOrdering(chain)) {
163 return chain[0];
164 }
165 return chain[chain.length - 1];
166 }
167
168 private boolean isTrustedCertificate(X509Certificate candidate) throws CertificateException {
169
170 boolean isCACert = isCACertificate(candidate);
171 for (Iterator<X509Certificate> iter = trustedCertificates.iterator(); iter.hasNext();) {
172 X509Certificate trusted = iter.next();
173 if (isCACert) {
174
175 try {
176 if (Arrays.equals(trusted.getEncoded(), candidate.getEncoded())) {
177 return true;
178 }
179 } catch (CertificateEncodingException e) {
180 return false;
181 }
182 } else {
183
184 if (isIssuerSubjectPair(trusted, candidate)) {
185 return true;
186 }
187 }
188 }
189
190 return false;
191 }
192
193 private boolean isCACertificate(X509Certificate candidate) {
194 return candidate.getIssuerDN().equals(candidate.getSubjectDN());
195 }
196
197 }