History

My first initial commit with all of mine experimental changes.

Dmitry Kabak (userdima committed 13 years ago

Commit d37b88d1 parent 3f5b46618352 files · +2598093 −-8690Browse files

Showing the changes to java/pkg/sun/security/ssl/SunX509KeyManagerImpl.java (1 of 18352 files). Show all

Unified · Split

java/pkg/sun/security/ssl/SunX509KeyManagerImpl.java+416−0
@@ -0,0 +1,416 @@
1+/*
2+ * Copyright (c) 1999, 2011, Oracle and/or its affiliates. All rights reserved.
3+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4+ *
5+ * This code is free software; you can redistribute it and/or modify it
6+ * under the terms of the GNU General Public License version 2 only, as
7+ * published by the Free Software Foundation. Oracle designates this
8+ * particular file as subject to the "Classpath" exception as provided
9+ * by Oracle in the LICENSE file that accompanied this code.
10+ *
11+ * This code is distributed in the hope that it will be useful, but WITHOUT
12+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14+ * version 2 for more details (a copy is included in the LICENSE file that
15+ * accompanied this code).
16+ *
17+ * You should have received a copy of the GNU General Public License version
18+ * 2 along with this work; if not, write to the Free Software Foundation,
19+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20+ *
21+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22+ * or visit www.oracle.com if you need additional information or have any
23+ * questions.
24+ */
25+
26+package sun.security.ssl;
27+
28+import javax.net.ssl.*;
29+import java.security.*;
30+import java.security.cert.*;
31+import java.security.cert.Certificate;
32+import java.util.*;
33+import java.net.Socket;
34+
35+import javax.security.auth.x500.X500Principal;
36+
37+
38+/**
39+ * An implemention of X509KeyManager backed by a KeyStore.
40+ *
41+ * The backing KeyStore is inspected when this object is constructed.
42+ * All key entries containing a PrivateKey and a non-empty chain of
43+ * X509Certificate are then copied into an internal store. This means
44+ * that subsequent modifications of the KeyStore have no effect on the
45+ * X509KeyManagerImpl object.
46+ *
47+ * Note that this class assumes that all keys are protected by the same
48+ * password.
49+ *
50+ * The JSSE handshake code currently calls into this class via
51+ * chooseClientAlias() and chooseServerAlias() to find the certificates to
52+ * use. As implemented here, both always return the first alias returned by
53+ * getClientAliases() and getServerAliases(). In turn, these methods are
54+ * implemented by calling getAliases(), which performs the actual lookup.
55+ *
56+ * Note that this class currently implements no checking of the local
57+ * certificates. In particular, it is *not* guaranteed that:
58+ * . the certificates are within their validity period and not revoked
59+ * . the signatures verify
60+ * . they form a PKIX compliant chain.
61+ * . the certificate extensions allow the certificate to be used for
62+ * the desired purpose.
63+ *
64+ * Chains that fail any of these criteria will probably be rejected by
65+ * the remote peer.
66+ *
67+ */
68+final class SunX509KeyManagerImpl extends X509ExtendedKeyManager {
69+
70+ private static final Debug debug = Debug.getInstance("ssl");
71+
72+ private static final String[] STRING0 = new String[0];
73+
74+ /*
75+ * The credentials from the KeyStore as
76+ * Map: String(alias) -> X509Credentials(credentials)
77+ */
78+ private Map<String,X509Credentials> credentialsMap;
79+
80+ /*
81+ * Cached server aliases for the case issuers == null.
82+ * (in the current JSSE implementation, issuers are always null for
83+ * server certs). See chooseServerAlias() for details.
84+ *
85+ * Map: String(keyType) -> String[](alias)
86+ */
87+ private Map<String,String[]> serverAliasCache;
88+
89+ /*
90+ * Basic container for credentials implemented as an inner class.
91+ */
92+ private static class X509Credentials {
93+ PrivateKey privateKey;
94+ X509Certificate[] certificates;
95+ private Set<X500Principal> issuerX500Principals;
96+
97+ X509Credentials(PrivateKey privateKey, X509Certificate[] certificates) {
98+ // assert privateKey and certificates != null
99+ this.privateKey = privateKey;
100+ this.certificates = certificates;
101+ }
102+
103+ synchronized Set<X500Principal> getIssuerX500Principals() {
104+ // lazy initialization
105+ if (issuerX500Principals == null) {
106+ issuerX500Principals = new HashSet<X500Principal>();
107+ for (int i = 0; i < certificates.length; i++) {
108+ issuerX500Principals.add(
109+ certificates[i].getIssuerX500Principal());
110+ }
111+ }
112+ return issuerX500Principals;
113+ }
114+ }
115+
116+ SunX509KeyManagerImpl(KeyStore ks, char[] password) throws KeyStoreException,
117+ NoSuchAlgorithmException, UnrecoverableKeyException {
118+
119+ credentialsMap = new HashMap<String,X509Credentials>();
120+ serverAliasCache = new HashMap<String,String[]>();
121+ if (ks == null) {
122+ return;
123+ }
124+
125+ for (Enumeration<String> aliases = ks.aliases();
126+ aliases.hasMoreElements(); ) {
127+ String alias = aliases.nextElement();
128+ if (!ks.isKeyEntry(alias)) {
129+ continue;
130+ }
131+ Key key = ks.getKey(alias, password);
132+ if (key instanceof PrivateKey == false) {
133+ continue;
134+ }
135+ Certificate[] certs = ks.getCertificateChain(alias);
136+ if ((certs == null) || (certs.length == 0) ||
137+ !(certs[0] instanceof X509Certificate)) {
138+ continue;
139+ }
140+ if (!(certs instanceof X509Certificate[])) {
141+ Certificate[] tmp = new X509Certificate[certs.length];
142+ System.arraycopy(certs, 0, tmp, 0, certs.length);
143+ certs = tmp;
144+ }
145+
146+ X509Credentials cred = new X509Credentials((PrivateKey)key,
147+ (X509Certificate[])certs);
148+ credentialsMap.put(alias, cred);
149+ if (debug != null && Debug.isOn("keymanager")) {
150+ System.out.println("***");
151+ System.out.println("found key for : " + alias);
152+ for (int i = 0; i < certs.length; i++) {
153+ System.out.println("chain [" + i + "] = "
154+ + certs[i]);
155+ }
156+ System.out.println("***");
157+ }
158+ }
159+ }
160+
161+ /*
162+ * Returns the certificate chain associated with the given alias.
163+ *
164+ * @return the certificate chain (ordered with the user's certificate first
165+ * and the root certificate authority last)
166+ */
167+ public X509Certificate[] getCertificateChain(String alias) {
168+ if (alias == null) {
169+ return null;
170+ }
171+ X509Credentials cred = credentialsMap.get(alias);
172+ if (cred == null) {
173+ return null;
174+ } else {
175+ return cred.certificates.clone();
176+ }
177+ }
178+
179+ /*
180+ * Returns the key associated with the given alias
181+ */
182+ public PrivateKey getPrivateKey(String alias) {
183+ if (alias == null) {
184+ return null;
185+ }
186+ X509Credentials cred = credentialsMap.get(alias);
187+ if (cred == null) {
188+ return null;
189+ } else {
190+ return cred.privateKey;
191+ }
192+ }
193+
194+ /*
195+ * Choose an alias to authenticate the client side of a secure
196+ * socket given the public key type and the list of
197+ * certificate issuer authorities recognized by the peer (if any).
198+ */
199+ public String chooseClientAlias(String[] keyTypes, Principal[] issuers,
200+ Socket socket) {
201+ /*
202+ * We currently don't do anything with socket, but
203+ * someday we might. It might be a useful hint for
204+ * selecting one of the aliases we get back from
205+ * getClientAliases().
206+ */
207+
208+ if (keyTypes == null) {
209+ return null;
210+ }
211+
212+ for (int i = 0; i < keyTypes.length; i++) {
213+ String[] aliases = getClientAliases(keyTypes[i], issuers);
214+ if ((aliases != null) && (aliases.length > 0)) {
215+ return aliases[0];
216+ }
217+ }
218+ return null;
219+ }
220+
221+ /*
222+ * Choose an alias to authenticate the client side of an
223+ * <code>SSLEngine</code> connection given the public key type
224+ * and the list of certificate issuer authorities recognized by
225+ * the peer (if any).
226+ *
227+ * @since 1.5
228+ */
229+ public String chooseEngineClientAlias(String[] keyType,
230+ Principal[] issuers, SSLEngine engine) {
231+ /*
232+ * If we ever start using socket as a selection criteria,
233+ * we'll need to adjust this.
234+ */
235+ return chooseClientAlias(keyType, issuers, null);
236+ }
237+
238+ /*
239+ * Choose an alias to authenticate the server side of a secure
240+ * socket given the public key type and the list of
241+ * certificate issuer authorities recognized by the peer (if any).
242+ */
243+ public String chooseServerAlias(String keyType,
244+ Principal[] issuers, Socket socket) {
245+ /*
246+ * We currently don't do anything with socket, but
247+ * someday we might. It might be a useful hint for
248+ * selecting one of the aliases we get back from
249+ * getServerAliases().
250+ */
251+ if (keyType == null) {
252+ return null;
253+ }
254+
255+ String[] aliases;
256+
257+ if (issuers == null || issuers.length == 0) {
258+ aliases = serverAliasCache.get(keyType);
259+ if (aliases == null) {
260+ aliases = getServerAliases(keyType, issuers);
261+ // Cache the result (positive and negative lookups)
262+ if (aliases == null) {
263+ aliases = STRING0;
264+ }
265+ serverAliasCache.put(keyType, aliases);
266+ }
267+ } else {
268+ aliases = getServerAliases(keyType, issuers);
269+ }
270+ if ((aliases != null) && (aliases.length > 0)) {
271+ return aliases[0];
272+ }
273+ return null;
274+ }
275+
276+ /*
277+ * Choose an alias to authenticate the server side of an
278+ * <code>SSLEngine</code> connection given the public key type
279+ * and the list of certificate issuer authorities recognized by
280+ * the peer (if any).
281+ *
282+ * @since 1.5
283+ */
284+ public String chooseEngineServerAlias(String keyType,
285+ Principal[] issuers, SSLEngine engine) {
286+ /*
287+ * If we ever start using socket as a selection criteria,
288+ * we'll need to adjust this.
289+ */
290+ return chooseServerAlias(keyType, issuers, null);
291+ }
292+
293+ /*
294+ * Get the matching aliases for authenticating the client side of a secure
295+ * socket given the public key type and the list of
296+ * certificate issuer authorities recognized by the peer (if any).
297+ */
298+ public String[] getClientAliases(String keyType, Principal[] issuers) {
299+ return getAliases(keyType, issuers);
300+ }
301+
302+ /*
303+ * Get the matching aliases for authenticating the server side of a secure
304+ * socket given the public key type and the list of
305+ * certificate issuer authorities recognized by the peer (if any).
306+ */
307+ public String[] getServerAliases(String keyType, Principal[] issuers) {
308+ return getAliases(keyType, issuers);
309+ }
310+
311+ /*
312+ * Get the matching aliases for authenticating the either side of a secure
313+ * socket given the public key type and the list of
314+ * certificate issuer authorities recognized by the peer (if any).
315+ *
316+ * Issuers comes to us in the form of X500Principal[].
317+ */
318+ private String[] getAliases(String keyType, Principal[] issuers) {
319+ if (keyType == null) {
320+ return null;
321+ }
322+ if (issuers == null) {
323+ issuers = new X500Principal[0];
324+ }
325+ if (issuers instanceof X500Principal[] == false) {
326+ // normally, this will never happen but try to recover if it does
327+ issuers = convertPrincipals(issuers);
328+ }
329+ String sigType;
330+ if (keyType.contains("_")) {
331+ int k = keyType.indexOf("_");
332+ sigType = keyType.substring(k + 1);
333+ keyType = keyType.substring(0, k);
334+ } else {
335+ sigType = null;
336+ }
337+
338+ X500Principal[] x500Issuers = (X500Principal[])issuers;
339+ // the algorithm below does not produce duplicates, so avoid Set
340+ List<String> aliases = new ArrayList<>();
341+
342+ for (Map.Entry<String,X509Credentials> entry :
343+ credentialsMap.entrySet()) {
344+
345+ String alias = entry.getKey();
346+ X509Credentials credentials = entry.getValue();
347+ X509Certificate[] certs = credentials.certificates;
348+
349+ if (!keyType.equals(certs[0].getPublicKey().getAlgorithm())) {
350+ continue;
351+ }
352+ if (sigType != null) {
353+ if (certs.length > 1) {
354+ // if possible, check the public key in the issuer cert
355+ if (!sigType.equals(certs[1].getPublicKey().getAlgorithm())) {
356+ continue;
357+ }
358+ } else {
359+ // Check the signature algorithm of the certificate itself.
360+ // Look for the "withRSA" in "SHA1withRSA", etc.
361+ String sigAlgName =
362+ certs[0].getSigAlgName().toUpperCase(Locale.ENGLISH);
363+ String pattern = "WITH" + sigType.toUpperCase(Locale.ENGLISH);
364+ if (sigAlgName.contains(pattern) == false) {
365+ continue;
366+ }
367+ }
368+ }
369+
370+ if (issuers.length == 0) {
371+ // no issuer specified, match all
372+ aliases.add(alias);
373+ if (debug != null && Debug.isOn("keymanager")) {
374+ System.out.println("matching alias: " + alias);
375+ }
376+ } else {
377+ Set<X500Principal> certIssuers =
378+ credentials.getIssuerX500Principals();
379+ for (int i = 0; i < x500Issuers.length; i++) {
380+ if (certIssuers.contains(issuers[i])) {
381+ aliases.add(alias);
382+ if (debug != null && Debug.isOn("keymanager")) {
383+ System.out.println("matching alias: " + alias);
384+ }
385+ break;
386+ }
387+ }
388+ }
389+ }
390+
391+ String[] aliasStrings = aliases.toArray(STRING0);
392+ return ((aliasStrings.length == 0) ? null : aliasStrings);
393+ }
394+
395+ /*
396+ * Convert an array of Principals to an array of X500Principals, if
397+ * possible. Principals that cannot be converted are ignored.
398+ */
399+ private static X500Principal[] convertPrincipals(Principal[] principals) {
400+ List<X500Principal> list = new ArrayList<>(principals.length);
401+ for (int i = 0; i < principals.length; i++) {
402+ Principal p = principals[i];
403+ if (p instanceof X500Principal) {
404+ list.add((X500Principal)p);
405+ } else {
406+ try {
407+ list.add(new X500Principal(p.getName()));
408+ } catch (IllegalArgumentException e) {
409+ // ignore
410+ }
411+ }
412+ }
413+ return list.toArray(new X500Principal[list.size()]);
414+ }
415+
416+}