View Javadoc
1   /*
2    * Copyright 2018 peter.
3    *
4    * Licensed under the Apache License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    *
8    *      http://www.apache.org/licenses/LICENSE-2.0
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   */
16  package au.net.zeus.rmi.tls;
17  
18  import java.security.KeyStore;
19  import java.security.KeyStoreException;
20  import java.security.NoSuchAlgorithmException;
21  import java.security.NoSuchProviderException;
22  import java.security.PrivilegedAction;
23  import java.security.cert.CertificateException;
24  import java.security.cert.X509Certificate;
25  import java.util.HashSet;
26  import java.util.Set;
27  import java.util.logging.Level;
28  import javax.net.ssl.TrustManagerFactory;
29  import javax.net.ssl.X509TrustManager;
30  import net.jini.security.Security;
31  import org.apache.river.action.GetPropertyAction;
32  
33  /**
34   *
35   * 
36   */
37  abstract class FilterX509TrustManager extends Utilities implements X509TrustManager {
38      
39      /* -- Fields -- */
40      /** The trust manager to delegate to. */
41      private static volatile X509TrustManager trustManager;
42  
43      /** Use for synchronizing initialization of the trustManager field. */
44      private static final Object lock = new Object();
45  
46      /** The trust manager factory algorithm. */
47      private static final String trustManagerFactoryAlgorithm =
48  	Security.doPrivileged(
49  	    new GetPropertyAction(
50  		"org.apache.river.jeri.ssl.trustManagerFactoryAlgorithm",
51  		TrustManagerFactory.getDefaultAlgorithm()
52  	    )
53  	);
54      
55      /** The set of permitted remote principals, or null if no restriction. */
56      private Set principals;
57  
58      /* -- Constructors -- */
59  
60      /**
61       * Creates an X509TrustManager that only trusts certificate chains whose
62       * first certificate identifies one of a set of principals.
63       *
64       * @param principals the set of permitted remote principals, or null if no
65       *	      restriction
66       * @throws NoSuchAlgorithmException if the trust manager factory algorithm
67       *	       is not found
68       */
69      FilterX509TrustManager() throws NoSuchAlgorithmException, NoSuchProviderException {
70  	synchronized (lock) {
71  	    if (trustManager == null) {
72  		trustManager = getTrustManager();
73  	    }
74  	}
75  //	setPermittedRemotePrincipals(principals);
76      }
77  
78      /* -- Implement X509TrustManager -- */
79  
80      public void checkClientTrusted(X509Certificate[] chain, String authType)
81  	throws CertificateException
82      {
83  	trustManager.checkClientTrusted(chain, authType);
84  	check(chain);
85  	if (SERVER_LOGGER.isLoggable(Level.FINE)) {
86  	    SERVER_LOGGER.log(Level.FINE,
87  			     "check client trusted succeeds " +
88  			     "for auth type {0}\nchain {1}",
89  			     new Object[] { authType, toString(chain) });
90  	}
91      }
92  
93      public void checkServerTrusted(X509Certificate[] chain, String authType)
94  	throws CertificateException
95      {
96  	trustManager.checkServerTrusted(chain, authType);
97  	check(chain);
98  	if (CLIENT_LOGGER.isLoggable(Level.FINE)) {
99  	    CLIENT_LOGGER.log(Level.FINE,
100 			     "check server trusted succeeds " +
101 			     "for auth type {0}\nchain {1}",
102 			     new Object[] { authType, toString(chain) });
103 	}
104     }
105 
106     public X509Certificate[] getAcceptedIssuers() {
107 	return trustManager.getAcceptedIssuers();
108     }
109 
110     /* -- Other methods -- */
111 
112     /**
113      * Specifies the set of permitted remote principals.
114      * 
115      * externally synchronized.
116      *
117      * @param principals the set of permitted remote principals, or null if no
118      *	      restriction
119      */
120     void setPermittedRemotePrincipals(Set principals) {
121 	this.principals = (principals == null) ? null : new HashSet(principals);
122     }	
123 
124     /**
125      * Make sure the subject of the leaf certificate is one of the permitted
126      * principals.
127      */
128     private synchronized void check(X509Certificate[] chain) throws CertificateException {
129 	if (principals != null &&
130 	    !principals.contains(chain[0].getSubjectX500Principal()))
131 	{
132 	    throw new CertificateException("Remote principal is not trusted");
133 	}
134     }
135 
136     /** Returns the X509TrustManager to delegate to. */
137     private static X509TrustManager getTrustManager()
138 	throws NoSuchAlgorithmException, NoSuchProviderException
139     {
140 	final TrustManagerFactory factory = JSSE_PROVIDER != null ?
141 		TrustManagerFactory.getInstance(trustManagerFactoryAlgorithm, JSSE_PROVIDER)
142 		: TrustManagerFactory.getInstance(trustManagerFactoryAlgorithm);
143 	Security.doPrivileged(
144 	    new PrivilegedAction() {
145 		public Object run() {
146 		    /*
147 		     * Initialize the trust managers for the trust manager
148 		     * factory.  Call in a doPrivileged because access to the
149 		     * CA certificates file should be allowed to all programs
150 		     * that use this provider.
151 		     */
152 		    try {
153 			/*
154 			 * Calling init with null reads the default truststore
155 			 */
156 			factory.init((KeyStore) null);
157 		    } catch (KeyStoreException e) {
158 			INIT_LOGGER.log(
159 			    Level.WARNING,
160 			    "Problem initializing JSSE trust manager keystore",
161 			    e);
162 		    }
163 		    return null;
164 		}
165 	    });
166 
167 	/*
168 	 * Although JSSE doesn't document this, there should be only one X.509
169 	 * trust manager for X.509 certificates read from KeyStores.
170 	 */
171 	return (X509TrustManager) factory.getTrustManagers()[0];
172     }
173     
174 }