1 /*
2 * Copyright (C) The Spice Group. All rights reserved.
3 *
4 * This software is published under the terms of the Spice
5 * Software License version 1.1, a copy of which has been included
6 * with this distribution in the LICENSE.txt file.
7 */
8 package org.codehaus.spice.xmlpolicy.builder;
9
10 import java.io.InputStream;
11 import java.lang.reflect.Constructor;
12 import java.net.MalformedURLException;
13 import java.net.URL;
14 import java.security.CodeSource;
15 import java.security.KeyStore;
16 import java.security.KeyStoreException;
17 import java.security.Permission;
18 import java.security.Policy;
19 import java.security.UnresolvedPermission;
20 import java.security.cert.Certificate;
21 import java.util.ArrayList;
22 import java.util.HashMap;
23 import java.util.List;
24 import java.util.Map;
25 import java.util.PropertyPermission;
26 import java.util.StringTokenizer;
27 import org.codehaus.spice.xmlpolicy.metadata.GrantMetaData;
28 import org.codehaus.spice.xmlpolicy.metadata.KeyStoreMetaData;
29 import org.codehaus.spice.xmlpolicy.metadata.PermissionMetaData;
30 import org.codehaus.spice.xmlpolicy.metadata.PolicyMetaData;
31
32 /***
33 * A Utility class that builds a Policy object from a specified
34 * PolicyMetaData.
35 *
36 * @author Peter Donald
37 * @version $Revision: 1.1 $ $Date: 2003/12/02 09:16:06 $
38 */
39 public class PolicyBuilder
40 {
41 /***
42 * Build a policy for a specified meta data.
43 *
44 * @param policy the policy metadata
45 * @return the Policy object
46 * @throws Exception if unable to create Policy object
47 */
48 public Policy buildPolicy( final PolicyMetaData policy,
49 final PolicyResolver resolver )
50 throws Exception
51 {
52 if( null == policy )
53 {
54 throw new NullPointerException( "policy" );
55 }
56 if( null == resolver )
57 {
58 throw new NullPointerException( "resolver" );
59 }
60
61 final Map keyStores =
62 createKeyStores( policy.getKeyStores(), resolver );
63 final Map grants = new HashMap();
64 processGrants( policy.getGrants(), keyStores, grants, resolver );
65
66 final CodeSource codeSource = createDefaultCodeSource();
67 final Permission[] permissions = getDefaultPermissions();
68 grants.put( codeSource, permissions );
69
70 return resolver.createPolicy( grants );
71 }
72
73 /***
74 * Porcess all the grants and build up a grant map.
75 *
76 * @param metaDatas the metadata
77 * @param keyStores the configured keystores
78 * @param grants the grant map
79 * @param resolver the resolver to use to resolve locations etc
80 * @throws Exception if unable to create grant map
81 */
82 private void processGrants( final GrantMetaData[] metaDatas,
83 final Map keyStores,
84 final Map grants,
85 final PolicyResolver resolver )
86 throws Exception
87 {
88 for( int i = 0; i < metaDatas.length; i++ )
89 {
90 processGrant( metaDatas[ i ], keyStores, grants, resolver );
91 }
92 }
93
94 /***
95 * Porcess a grants and add to the grant map.
96 *
97 * @param metaData the metadata
98 * @param keyStores the configured keystores
99 * @param grants the grant map
100 * @param resolver the resolver to use to resolve locations etc
101 * @throws Exception if unable to create grant map
102 */
103 private void processGrant( final GrantMetaData metaData,
104 final Map keyStores,
105 final Map grants,
106 final PolicyResolver resolver )
107 throws Exception
108 {
109 final URL url =
110 resolver.resolveLocation( metaData.getCodebase() );
111
112 final Certificate[] signers =
113 getSigners( metaData.getSignedBy(),
114 metaData.getKeyStore(),
115 keyStores );
116 final CodeSource codeSource = new CodeSource( url, signers );
117
118 final Permission[] permissions =
119 createPermissions( metaData.getPermissions(),
120 keyStores );
121 grants.put( codeSource, permissions );
122 }
123
124 /***
125 * Create all permissions for specified metadata.
126 *
127 * @param metaDatas the metadata
128 * @param keyStores the keystores to use when loading signers
129 * @return the created permissions
130 * @throws Exception if unabel to create permissions
131 */
132 private Permission[] createPermissions( final PermissionMetaData[] metaDatas,
133 final Map keyStores )
134 throws Exception
135 {
136 final List set = new ArrayList();
137
138 for( int i = 0; i < metaDatas.length; i++ )
139 {
140 final Permission permission =
141 createPermission( metaDatas[ i ], keyStores );
142 set.add( permission );
143 }
144
145 return (Permission[])set.toArray( new Permission[ set.size() ] );
146 }
147
148 /***
149 * Create a permission for metadata.
150 *
151 * @param metaData the permission metadata
152 * @param keyStores the keystore to use (if needed)
153 * @return the created permission
154 * @throws Exception if unable to create permission
155 */
156 private Permission createPermission( final PermissionMetaData metaData,
157 final Map keyStores )
158 throws Exception
159 {
160 final String type = metaData.getClassname();
161 final String actions = metaData.getAction();
162 final String signedBy = metaData.getSignedBy();
163 final String keyStoreName = metaData.getKeyStore();
164 final String target = metaData.getTarget();
165
166 final Certificate[] signers =
167 getSigners( signedBy, keyStoreName, keyStores );
168 return createPermission( type, target, actions, signers );
169 }
170
171 /***
172 * Create a mpa of keystores from specified metadata.
173 *
174 * @param metaDatas the metadata
175 * @return the keystore map
176 * @throws Exception if unable to create all keystores
177 */
178 private Map createKeyStores( final KeyStoreMetaData[] metaDatas,
179 final PolicyResolver resolver )
180 throws Exception
181 {
182 final Map keyStores = new HashMap();
183
184 for( int i = 0; i < metaDatas.length; i++ )
185 {
186 final KeyStoreMetaData metaData = metaDatas[ i ];
187 final String name = metaData.getName();
188
189 try
190 {
191 final URL url =
192 resolver.resolveLocation( metaData.getLocation() );
193 final KeyStore keyStore =
194 createKeyStore( metaData.getType(), url );
195
196 keyStores.put( name, keyStore );
197 }
198 catch( final Exception e )
199 {
200 final String message =
201 "Error creating keystore " + name + ". Due to " + e;
202 throw new Exception( message );
203 }
204 }
205
206 return keyStores;
207 }
208
209 /***
210 * Create a permission of specified class and
211 * with specified target, action and signers.
212 *
213 * @param type the classname of Permission object
214 * @param target the target of permission
215 * @param actions the actions allowed on permission (if any)
216 * @param signers the signers (if any)
217 * @return the created Permission object
218 * @throws Exception if unable to create permission
219 */
220 private final Permission createPermission( final String type,
221 final String target,
222 final String actions,
223 final Certificate[] signers )
224 throws Exception
225 {
226 if( null != signers )
227 {
228 return new UnresolvedPermission( type, target, actions, signers );
229 }
230
231 try
232 {
233 final Class clazz = Class.forName( type );
234
235 Class paramClasses[] = null;
236 Object params[] = null;
237
238 if( null == actions && null == target )
239 {
240 paramClasses = new Class[ 0 ];
241 params = new Object[ 0 ];
242 }
243 else if( null == actions )
244 {
245 paramClasses = new Class[ 1 ];
246 paramClasses[ 0 ] = String.class;
247 params = new Object[ 1 ];
248 params[ 0 ] = target;
249 }
250 else
251 {
252 paramClasses = new Class[ 2 ];
253 paramClasses[ 0 ] = String.class;
254 paramClasses[ 1 ] = String.class;
255 params = new Object[ 2 ];
256 params[ 0 ] = target;
257 params[ 1 ] = actions;
258 }
259
260 final Constructor constructor = clazz.getConstructor( paramClasses );
261 return (Permission)constructor.newInstance( params );
262 }
263 catch( final ClassNotFoundException cnfe )
264 {
265 return new UnresolvedPermission( type, target, actions, signers );
266 }
267 }
268
269 /***
270 * Create a keystore of specified type and loading from specified url.
271 *
272 * @param type the type of key store
273 * @param url the location of key store data
274 * @return the create and configured keystore
275 * @throws Exception if unable to create or load keystore
276 */
277 protected KeyStore createKeyStore( final String type,
278 final URL url )
279 throws Exception
280 {
281 final KeyStore keyStore = KeyStore.getInstance( type );
282 final InputStream ins = url.openStream();
283 keyStore.load( ins, null );
284 return keyStore;
285 }
286
287 /***
288 * Retrieve Certificates for specified signers
289 * as loaded from keyStore.
290 *
291 * @param signedBy the signers
292 * @param keyStoreName the name of keystore
293 * @param keyStores the list of keystores to lookup
294 * @return the certificates
295 * @throws Exception if unable to get signers
296 */
297 private Certificate[] getSigners( final String signedBy,
298 final String keyStoreName,
299 final Map keyStores )
300 throws Exception
301 {
302 if( null == signedBy )
303 {
304 return null;
305 }
306 else
307 {
308 final KeyStore keyStore = getKeyStore( keyStoreName, keyStores );
309 return getCertificates( signedBy, keyStore );
310 }
311 }
312
313 /***
314 * Retrieve the set of Ceritificates for all signers.
315 *
316 * @param signedBy the comma separated list of signers
317 * @param keyStore the keystore to look for signers certificates in
318 * @return the certificate set
319 * @throws Exception if unabel to create certificates
320 */
321 private Certificate[] getCertificates( final String signedBy,
322 final KeyStore keyStore )
323 throws Exception
324 {
325 final List certificateSet = new ArrayList();
326
327 final StringTokenizer st = new StringTokenizer( signedBy, "," );
328 while( st.hasMoreTokens() )
329 {
330 final String alias = st.nextToken().trim();
331 Certificate certificate = null;
332
333 try
334 {
335 certificate = keyStore.getCertificate( alias );
336 }
337 catch( final KeyStoreException kse )
338 {
339 final String message =
340 "Unable to get certificate for alias " +
341 alias + " due to " + kse;
342 throw new Exception( message );
343 }
344
345 if( null == certificate )
346 {
347 final String message =
348 "Missing certificate for alias " + alias;
349 throw new Exception( message );
350 }
351
352 if( !certificateSet.contains( certificate ) )
353 {
354 certificateSet.add( certificate );
355 }
356 }
357
358 return (Certificate[])certificateSet.toArray( new Certificate[ certificateSet.size() ] );
359 }
360
361 /***
362 * Retrieve keystore with specified name from map.
363 * If missing throw an exception.
364 *
365 * @param keyStoreName the name of key store
366 * @param keyStores the map of stores
367 * @return the keystore
368 * @throws Exception thrown if unable to locate keystore
369 */
370 private KeyStore getKeyStore( final String keyStoreName, final Map keyStores ) throws Exception
371 {
372 final KeyStore keyStore = (KeyStore)keyStores.get( keyStoreName );
373 if( null == keyStore )
374 {
375 final String message = "Missing keystore named: " + keyStoreName;
376 throw new Exception( message );
377 }
378 else
379 {
380 return keyStore;
381 }
382 }
383
384 /***
385 * A utility method to get a default codesource
386 * that covers all files on fielsystem
387 *
388 * @return the code source
389 */
390 private CodeSource createDefaultCodeSource()
391 {
392 //Create a URL that covers whole file system.
393 final URL url;
394 try
395 {
396 url = new URL( "file:/-" );
397 }
398 catch( final MalformedURLException mue )
399 {
400 //will never happen
401 throw new IllegalStateException( mue.getMessage() );
402 }
403 final CodeSource codeSource = new CodeSource( url, null );
404 return codeSource;
405 }
406
407 /***
408 * A utility method to get all the default permissions.
409 */
410 private Permission[] getDefaultPermissions()
411 {
412 final ArrayList list = new ArrayList();
413 //these properties straight out ot ${java.home}/lib/security/java.policy
414 list.add( new PropertyPermission( "os.name", "read" ) );
415 list.add( new PropertyPermission( "os.arch", "read" ) );
416 list.add( new PropertyPermission( "os.version", "read" ) );
417 list.add( new PropertyPermission( "file.separator", "read" ) );
418 list.add( new PropertyPermission( "path.separator", "read" ) );
419 list.add( new PropertyPermission( "line.separator", "read" ) );
420
421 list.add( new PropertyPermission( "java.version", "read" ) );
422 list.add( new PropertyPermission( "java.vendor", "read" ) );
423 list.add( new PropertyPermission( "java.vendor.url", "read" ) );
424
425 list.add( new PropertyPermission( "java.class.version", "read" ) );
426 list.add( new PropertyPermission( "java.vm.version", "read" ) );
427 list.add( new PropertyPermission( "java.vm.vendor", "read" ) );
428 list.add( new PropertyPermission( "java.vm.name", "read" ) );
429
430 list.add( new PropertyPermission( "java.specification.version", "read" ) );
431 list.add( new PropertyPermission( "java.specification.vendor", "read" ) );
432 list.add( new PropertyPermission( "java.specification.name", "read" ) );
433 list.add( new PropertyPermission( "java.vm.specification.version", "read" ) );
434 list.add( new PropertyPermission( "java.vm.specification.vendor", "read" ) );
435 list.add( new PropertyPermission( "java.vm.specification.name", "read" ) );
436
437 return (Permission[])list.toArray( new Permission[ list.size() ] );
438 }
439 }
This page was automatically generated by Maven