View Javadoc

1   /* 
2    * Copyright (c) 2007, Fraunhofer-Gesellschaft
3    * All rights reserved.
4    * 
5    * Redistribution and use in source and binary forms, with or without
6    * modification, are permitted provided that the following conditions are
7    * met:
8    * 
9    * (1) Redistributions of source code must retain the above copyright
10   *     notice, this list of conditions and the disclaimer at the end.
11   *     Redistributions in binary form must reproduce the above copyright
12   *     notice, this list of conditions and the following disclaimer in
13   *     the documentation and/or other materials provided with the
14   *     distribution.
15   * 
16   * (2) Neither the name of Fraunhofer nor the names of its
17   *     contributors may be used to endorse or promote products derived
18   *     from this software without specific prior written permission.
19   * 
20   * DISCLAIMER
21   * 
22   * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
23   * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
24   * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
25   * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
26   * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
27   * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
28   * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
29   * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
30   * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
31   * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
32   * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33   *  
34   */
35  package org.ogf.graap.wsag.wsrf.security;
36  
37  import java.io.FileInputStream;
38  import java.io.IOException;
39  import java.io.InputStream;
40  import java.net.URL;
41  import java.security.KeyStore;
42  import java.security.PrivateKey;
43  import java.security.cert.X509Certificate;
44  import java.text.MessageFormat;
45  import java.util.Properties;
46  
47  import org.apache.log4j.Logger;
48  import org.apache.ws.security.WSSecurityException;
49  import org.apache.ws.security.components.crypto.CredentialException;
50  import org.apache.ws.security.util.Loader;
51  import org.ogf.graap.wsag.api.WsagConstants;
52  import org.ogf.graap.wsag.api.security.SecurityConstants;
53  import org.ogf.graap.wsag.wsrf.WsrfEngine;
54  import org.ogf.graap.wsag4j.types.configuration.ConfigurationType;
55  import org.ogf.graap.wsag4j.types.configuration.WSRFEngineConfigurationType;
56  
57  /**
58   * Merlin
59   * 
60   * @author Oliver Waeldrich
61   * 
62   */
63  public class Merlin extends org.apache.ws.security.components.crypto.Merlin
64  {
65  
66      private static final Logger LOG = Logger.getLogger( Merlin.class );
67  
68      String truststoreFile = null;
69  
70      String truststoreType = null;
71  
72      String truststorePassword = null;
73  
74      // KeyStore truststore = null;
75  
76      /**
77       * Creates a new {@link org.apache.ws.security.components.crypto.Merlin} instance using the specified
78       * properties.
79       * 
80       * @param properties
81       *            the properties to use
82       * 
83       * @throws CredentialException
84       *             error processing the keystore credentials
85       * @throws IOException
86       *             error accessing the keystore
87       */
88      public Merlin( Properties properties )
89          throws CredentialException, IOException
90      {
91          this( loadProperties( properties ), new MerlinClassLoader( Merlin.class.getClassLoader() ) );
92      }
93  
94      /**
95       * Creates a new {@link org.apache.ws.security.components.crypto.Merlin} instance using the specified
96       * properties and class loader.
97       * 
98       * @param properties
99       *            the properties to use
100      * 
101      * @param loader
102      *            the class loader to use
103      * 
104      * @throws CredentialException
105      *             error processing the keystore credentials
106      * @throws IOException
107      *             error accessing the keystore
108      */
109     public Merlin( Properties properties, ClassLoader loader )
110         throws CredentialException, IOException
111     {
112         super( loadProperties( properties ), loader );
113 
114         this.truststoreFile = this.properties.getProperty( SecurityConstants.PROP_TRUSTSTORE_FILE );
115         this.truststoreType = this.properties.getProperty( SecurityConstants.PROP_TRUSTSTORE_TYPE );
116         this.truststorePassword = this.properties.getProperty( SecurityConstants.PROP_TRUSTSTORE_PASS );
117 
118         loadTrustStore( loader );
119     }
120 
121     private static Properties loadProperties( Properties properties ) throws WSSecurityException
122     {
123 
124         //
125         // if properties are provided, we use them
126         //
127         if ( properties != null )
128         {
129             String value = (String) properties.get( "org.ogf.graap.wsag.security.configuration" );
130             if ( !"useWSRFConfigFile".equalsIgnoreCase( value ) )
131             {
132                 return properties;
133             }
134         }
135 
136         //
137         // if no properties are provided, we read them from the wsrf-configuration file
138         //
139         properties = new Properties();
140 
141         try
142         {
143             ConfigurationType config =
144                 WsrfEngine.findWsrfConfiguration( WsagConstants.WSAG4J_WSRF_ENGINE_CONFIG_FILE );
145             WSRFEngineConfigurationType wsrfConfig = config.getWSRFEngineConfiguration();
146 
147             String alias = wsrfConfig.getKeystore().getAlias();
148             String aliasPassword = wsrfConfig.getKeystore().getAliasPassword();
149             String keystoreFile = wsrfConfig.getKeystore().getKeystoreFile();
150             String keystorePassword = wsrfConfig.getKeystore().getKeystorePassword();
151             String keystoreType = wsrfConfig.getKeystore().getKeystoreType();
152 
153             String truststoreFile = wsrfConfig.getTruststore().getTruststoreFile();
154             String truststorePassword = wsrfConfig.getTruststore().getTruststorePassword();
155             String truststoreType = wsrfConfig.getTruststore().getTruststoreType();
156 
157             setProperty( SecurityConstants.PROP_CRYPTO_PROVIDER, Merlin.class.getName(), properties );
158             setProperty( SecurityConstants.PROP_KEYSTORE_TYPE, keystoreType, properties );
159             setProperty( SecurityConstants.PROP_KEYSTORE_PASS, keystorePassword, properties );
160             setProperty( SecurityConstants.PROP_KEYSTORE_ALIAS, alias, properties );
161             setProperty( SecurityConstants.PROP_KEYSTORE_ALIAS_PASS, aliasPassword, properties );
162             setProperty( SecurityConstants.PROP_KEYSTORE_FILE, keystoreFile, properties );
163 
164             setProperty( SecurityConstants.PROP_TRUSTSTORE_FILE, truststoreFile, properties );
165             setProperty( SecurityConstants.PROP_TRUSTSTORE_PASS, truststorePassword, properties );
166             setProperty( SecurityConstants.PROP_TRUSTSTORE_TYPE, truststoreType, properties );
167 
168             return properties;
169         }
170         catch ( Exception e )
171         {
172             String message = "Merlin: Could not load WSAG4J keystore properties from configuration file.";
173             throw new WSSecurityException( message, e );
174         }
175     }
176 
177     private static void setProperty( String name, String value, Properties properties )
178     {
179         if ( ( name != null ) && ( value != null ) )
180         {
181             properties.setProperty( name, value );
182         }
183     }
184 
185     private void loadTrustStore( ClassLoader loader )
186     {
187 
188         try
189         {
190             KeyStore truststore = null;
191 
192             if ( ( truststoreFile != null ) && ( truststorePassword != null ) )
193             {
194                 try
195                 {
196                     InputStream is = null;
197                     URL url = Loader.getResource( loader, truststoreFile );
198 
199                     if ( url != null )
200                     {
201                         is = url.openStream();
202                     }
203                     else
204                     {
205                         is = new java.io.FileInputStream( truststoreFile );
206                     }
207 
208                     //
209                     // If we don't find it, then look on the file system.
210                     //
211                     if ( is == null )
212                     {
213                         try
214                         {
215                             is = new FileInputStream( truststoreFile );
216                         }
217                         catch ( Exception e )
218                         {
219                             throw new CredentialException( 3, "proxyNotFound",
220                                 new Object[] { truststoreFile } );
221                         }
222                     }
223 
224                     try
225                     {
226                         truststore = load( is, truststorePassword, null, truststoreType );
227                     }
228                     finally
229                     {
230                         is.close();
231                     }
232                 }
233                 catch ( Exception e )
234                 {
235                     Object[] filler = new Object[] { e.getMessage() };
236                     String message =
237                         MessageFormat.format(
238                             "Truststore was not specified or could not be loaded. Message: {0}", filler );
239 
240                     LOG.info( message );
241                     LOG.info( "Use JVM cacerts as truststore." );
242                 }
243             }
244 
245             if ( truststore == null )
246             {
247                 // use default behavior with JVM ca-certs file as truststore
248                 if ( LOG.isDebugEnabled() )
249                 {
250                     LOG.debug( "No truststore specified. Using default JVM ca-certs as truststore." );
251                 }
252             }
253             else
254             {
255                 cacerts = truststore;
256             }
257 
258         }
259         catch ( Exception e )
260         {
261             Object[] filler = new Object[] { e.getMessage() };
262             String message = MessageFormat.format( "truststore was not loaded. Reason: {0}", filler );
263             LOG.error( message );
264         }
265 
266     }
267 
268     /**
269      * {@inheritDoc}
270      * 
271      * @see org.apache.ws.security.components.crypto.Crypto#getPrivateKey(java.lang.String, java.lang.String)
272      * 
273      *      Change the alias name provided in the AXIS2 service configuration to the defaultAlias if necessary
274      *      and change the password accordingly.
275      */
276     @Override
277     public PrivateKey getPrivateKey( String alias, String password ) throws Exception
278     {
279         if ( alias.equals( SecurityConstants.DEFAULT_ALIAS )
280             && password.equals( SecurityConstants.DEFAULT_ALIAS_PASSWORD ) )
281         {
282             alias = getDefaultX509Alias();
283             password = properties.getProperty( "org.apache.ws.security.crypto.merlin.alias.password" );
284         }
285         return super.getPrivateKey( alias, password );
286     }
287 
288     /**
289      * Change the alias name provided in the AXIS2 service configuration to the defaultAlias if necessary.
290      * 
291      * {@inheritDoc}
292      * 
293      * @see org.apache.ws.security.components.crypto.Crypto#getCertificates(java.lang.String)
294      */
295     @Override
296     public X509Certificate[] getCertificates( String alias ) throws WSSecurityException
297     {
298         alias = ( alias.equals( SecurityConstants.DEFAULT_ALIAS ) ) ? getDefaultX509Alias() : alias;
299         return super.getCertificates( alias );
300     }
301 
302 }