1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package au.net.zeus.rmi.tls;
17
18 import java.net.Socket;
19 import java.security.AccessControlContext;
20 import java.security.AccessController;
21 import java.security.GeneralSecurityException;
22 import java.security.NoSuchAlgorithmException;
23 import java.security.NoSuchProviderException;
24 import java.security.Principal;
25 import java.security.PrivilegedAction;
26 import java.security.cert.CertPath;
27 import java.security.cert.CertificateException;
28 import java.security.cert.X509Certificate;
29 import java.util.ArrayList;
30 import java.util.Collection;
31 import java.util.Collections;
32 import java.util.List;
33 import java.util.Set;
34 import java.util.logging.Level;
35 import java.util.logging.Logger;
36 import javax.security.auth.Subject;
37 import javax.security.auth.x500.X500PrivateCredential;
38 import net.jini.io.UnsupportedConstraintException;
39 import net.jini.security.AuthenticationPermission;
40 import org.apache.river.logging.Levels;
41
42
43
44
45
46 class ClientSubjectKeyManager extends SubjectKeyManager {
47
48 private static final Logger logger = CLIENT_LOGGER;
49
50
51
52 Logger getLogger() {
53 return logger;
54 }
55
56 ClientSubjectKeyManager(Subject subject) throws NoSuchAlgorithmException, NoSuchProviderException {
57 super(subject);
58 }
59
60 public String[] getClientAliases(String keyType, Principal[] issuers) {
61 List certPaths = getCertificateChains(getSubject());
62 if (certPaths == null) {
63 return null;
64 }
65 Collection result = null;
66 for (int i = certPaths.size(); --i >= 0;) {
67 CertPath chain = (CertPath) certPaths.get(i);
68 Exception exception;
69 try {
70 if (checkChain(chain, keyType, issuers) != null) {
71 if (result == null) {
72 result = new ArrayList(certPaths.size());
73 }
74 result.add(getCertificateName(firstX509Cert(chain)));
75 }
76 continue;
77 } catch (SecurityException e) {
78 exception = e;
79 } catch (GeneralSecurityException ex) {
80 exception = ex;
81 }
82 Logger logger = Logger.getLogger(SubjectKeyManager.class.getName());
83 if (logger.isLoggable(Levels.HANDLED)) {
84 }
85 }
86 if (result == null) {
87 return null;
88 } else {
89 return (String[]) result.toArray(new String[result.size()]);
90 }
91 }
92
93 public synchronized String chooseClientAlias(String[] keyTypes, Principal[] issuers, Socket socket) {
94
95
96
97
98 if (clientCredentialException != null) {
99 return null;
100 } else if (clientCredential == null) {
101 List exceptions = null;
102 for (int i = 0, l = keyTypes.length; i < l; i++) {
103 Exception exception;
104 try {
105 clientCredential = chooseCredential(keyTypes[i], issuers);
106 if (clientCredential != null) {
107 break;
108 }
109 continue;
110 } catch (GeneralSecurityException e) {
111 exception = e;
112 } catch (SecurityException e) {
113 exception = e;
114 }
115 if (exceptions == null) {
116 exceptions = new ArrayList();
117 }
118 exceptions.add(exception);
119 }
120 if (clientCredential == null) {
121 if (exceptions == null) {
122 clientCredentialException = new GeneralSecurityException("Credentials not found");
123 } else if (exceptions.size() == 1) {
124 clientCredentialException = (Exception) exceptions.get(0);
125 } else {
126 for (int i = exceptions.size(); --i >= 0;) {
127 Exception e = (Exception) exceptions.get(i);
128 if (!(e instanceof SecurityException)) {
129 clientCredentialException = new GeneralSecurityException(exceptions.toString());
130 break;
131 }
132 }
133 if (clientCredentialException == null) {
134 clientCredentialException = new SecurityException(exceptions.toString());
135 }
136 }
137 return null;
138 }
139 }
140 X509Certificate cert = clientCredential.getCertificate();
141 clientPrincipal = cert.getSubjectX500Principal();
142 credentialsValidUntil = Math.min(credentialsValidUntil, certificatesValidUntil(getCertificateChain(getSubject(), cert)));
143 authenticationPermission = getAuthenticationPermission(cert);
144 String result = getCertificateName(clientCredential.getCertificate());
145 if (logger.isLoggable(Level.FINE)) {
146 logger.log(
147 Level.FINE,
148 "choose client alias for key types {0}\nand issuers {1}\n" +
149 "returns {2}",
150 new Object[] { toString(keyTypes), toString(issuers), result });
151 }
152 return result;
153 }
154
155
156
157
158
159
160 @Override
161 public synchronized void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException {
162 super.checkServerTrusted(chain, authType);
163 if (serverPrincipal == null) {
164 serverCredential = chain[0];
165 serverPrincipal = serverCredential.getSubjectX500Principal();
166 setPermittedRemotePrincipals(Collections.singleton(serverPrincipal));
167 credentialsValidUntil = certificatesValidUntil(chain);
168 } else if (!serverCredential.equals(chain[0])) {
169 throw new CertificateException("Server credentials changed");
170 }
171 }
172
173 public String[] getServerAliases(String arg0, Principal[] arg1) {
174 return null;
175 }
176
177 public String chooseServerAlias(String arg0, Principal[] arg1, Socket arg2) {
178 return null;
179 }
180
181
182
183
184
185 AuthenticationPermission getAuthenticationPermission(X509Certificate cert) {
186 Set client = Collections.singleton(cert.getSubjectX500Principal());
187 Set server = (serverPrincipal == null) ? null : Collections.singleton(serverPrincipal);
188 return new AuthenticationPermission(client, server, "connect");
189 }
190
191
192
193
194
195
196
197
198
199
200
201 synchronized X500PrivateCredential getPrivateCredential(X509Certificate cert) {
202 return getPrivateCredential(cert, getAuthenticationPermission(cert));
203 }
204
205
206
207
208
209
210
211
212
213
214
215 protected X500PrivateCredential getPrivateCredential(X509Certificate cert, AuthenticationPermission ap) {
216 Subject subject = getSubject();
217 if (subject == null) {
218 return null;
219 }
220 SecurityManager sm = System.getSecurityManager();
221 if (sm != null) {
222 sm.checkPermission(ap);
223 }
224 return (X500PrivateCredential) AccessController.doPrivileged(new GetPrivateCredentialAction(subject, cert));
225 }
226
227
228
229
230
231
232
233
234
235
236
237
238
239 synchronized void checkAuthentication()
240 throws GeneralSecurityException
241 {
242 if (clientCredential == null) {
243 throw new GeneralSecurityException(
244 "Client is not authenticated");
245 } else if (clientCredential.isDestroyed()) {
246 throw new GeneralSecurityException(
247 "Private credentials are destroyed");
248 } else if (System.currentTimeMillis() > credentialsValidUntil) {
249 throw new GeneralSecurityException(
250 "Certificates are no longer valid");
251 }
252 if (subjectIsReadOnly) {
253 SecurityManager sm = System.getSecurityManager();
254 if (sm != null) {
255 sm.checkPermission(authenticationPermission);
256 }
257 } else {
258 Subject subject = getSubject();
259 X509Certificate cert = clientCredential.getCertificate();
260 if (getPrincipal(subject, cert) == null) {
261 throw new GeneralSecurityException("Missing principal");
262 }
263 CertPath chain =
264 getCertificateChain(subject, cert);
265 if (chain == null) {
266 throw new GeneralSecurityException(
267 "Missing public credentials");
268 }
269 X500PrivateCredential pc = getPrivateCredential(
270 cert, authenticationPermission);
271 if (pc == null) {
272 throw new GeneralSecurityException(
273 "Missing private credentials");
274 } else if (!equalPrivateCredentials(clientCredential, pc)) {
275 throw new GeneralSecurityException(
276 "Wrong private credentials");
277 }
278 }
279 }
280 }