| /* |
| * Copyright 2003-2005 The Apache Software Foundation. |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| * |
| */ |
| |
| package org.apache.ws.security; |
| |
| import java.util.HashMap; |
| |
| import javax.xml.namespace.QName; |
| |
| import org.apache.commons.logging.Log; |
| import org.apache.commons.logging.LogFactory; |
| import org.apache.ws.security.action.Action; |
| import org.apache.ws.security.processor.Processor; |
| import org.apache.ws.security.transform.STRTransform; |
| import org.apache.ws.security.util.Loader; |
| import org.apache.xml.security.transforms.Transform; |
| |
| /** |
| * WSSConfig <p/> Carries configuration data so the WSS4J spec compliance can be |
| * modified in runtime. Configure an instance of this object only if you need |
| * WSS4J to emulate certain industry clients or previous OASIS specifications |
| * for WS-Security interoperability testing purposes. <p/> The default settings |
| * follow the latest OASIS and changing anything might violate the OASIS specs. |
| * <p/> <b>WARNING: changing the default settings will break the compliance with |
| * the latest specs. Do this only if you know what you are doing.</b> <p/> |
| * |
| * @author Rami Jaamour (rjaamour@parasoft.com) |
| * @author Werner Dittmann (werner@apache.org) |
| */ |
| public class WSSConfig { |
| |
| private static final Log log = LogFactory.getLog(WSSConfig.class.getName()); |
| |
| /** |
| * The default collection of actions supported by the toolkit. |
| */ |
| private static final java.util.Map DEFAULT_ACTIONS; |
| static { |
| final java.util.Map tmp = new java.util.HashMap(); |
| try { |
| tmp.put( |
| new Integer(WSConstants.UT), |
| org.apache.ws.security.action.UsernameTokenAction.class.getName() |
| ); |
| tmp.put( |
| new Integer(WSConstants.ENCR), |
| org.apache.ws.security.action.EncryptionAction.class.getName() |
| ); |
| tmp.put( |
| new Integer(WSConstants.SIGN), |
| org.apache.ws.security.action.SignatureAction.class.getName() |
| ); |
| // |
| // Note that all actions/processors with dependencies on opensaml are |
| // registered as Strings. This is so that applications that do not use |
| // saml do not have to have the opensaml jar available. |
| // |
| tmp.put( |
| new Integer(WSConstants.ST_SIGNED), |
| "org.apache.ws.security.action.SAMLTokenSignedAction" |
| ); |
| tmp.put( |
| new Integer(WSConstants.ST_UNSIGNED), |
| "org.apache.ws.security.action.SAMLTokenUnsignedAction" |
| ); |
| tmp.put( |
| new Integer(WSConstants.TS), |
| org.apache.ws.security.action.TimestampAction.class.getName() |
| ); |
| tmp.put( |
| new Integer(WSConstants.UT_SIGN), |
| org.apache.ws.security.action.UsernameTokenSignedAction.class.getName() |
| ); |
| tmp.put( |
| new Integer(WSConstants.SC), |
| org.apache.ws.security.action.SignatureConfirmationAction.class.getName() |
| ); |
| } catch (final Throwable t) { |
| if (log.isDebugEnabled()) { |
| log.debug(t.getMessage(), t); |
| } |
| } |
| DEFAULT_ACTIONS = java.util.Collections.unmodifiableMap(tmp); |
| } |
| |
| /** |
| * The default collection of processors supported by the toolkit |
| */ |
| private static final java.util.Map DEFAULT_PROCESSORS; |
| static { |
| final java.util.Map tmp = new java.util.HashMap(); |
| try { |
| tmp.put( |
| WSSecurityEngine.SAML_TOKEN, |
| "org.apache.ws.security.processor.SAMLTokenProcessor" |
| ); |
| tmp.put( |
| WSSecurityEngine.ENCRYPTED_KEY, |
| org.apache.ws.security.processor.EncryptedKeyProcessor.class.getName() |
| ); |
| tmp.put( |
| WSSecurityEngine.SIGNATURE, |
| org.apache.ws.security.processor.SignatureProcessor.class.getName() |
| ); |
| tmp.put( |
| WSSecurityEngine.timeStamp, |
| org.apache.ws.security.processor.TimestampProcessor.class.getName() |
| ); |
| tmp.put( |
| WSSecurityEngine.usernameToken, |
| org.apache.ws.security.processor.UsernameTokenProcessor.class.getName() |
| ); |
| tmp.put( |
| WSSecurityEngine.REFERENCE_LIST, |
| org.apache.ws.security.processor.ReferenceListProcessor.class.getName() |
| ); |
| tmp.put( |
| WSSecurityEngine.signatureConfirmation, |
| org.apache.ws.security.processor.SignatureConfirmationProcessor.class.getName() |
| ); |
| tmp.put( |
| WSSecurityEngine.DERIVED_KEY_TOKEN_05_02, |
| org.apache.ws.security.processor.DerivedKeyTokenProcessor.class.getName() |
| ); |
| tmp.put( |
| WSSecurityEngine.DERIVED_KEY_TOKEN_05_12, |
| tmp.get(WSSecurityEngine.DERIVED_KEY_TOKEN_05_02) |
| ); |
| tmp.put( |
| WSSecurityEngine.SECURITY_CONTEXT_TOKEN_05_02, |
| org.apache.ws.security.processor.SecurityContextTokenProcessor.class.getName() |
| ); |
| tmp.put( |
| WSSecurityEngine.SECURITY_CONTEXT_TOKEN_05_12, |
| tmp.get(WSSecurityEngine.SECURITY_CONTEXT_TOKEN_05_02) |
| ); |
| tmp.put( |
| WSSecurityEngine.binaryToken, |
| org.apache.ws.security.processor.BinarySecurityTokenProcessor.class.getName() |
| ); |
| tmp.put( |
| WSSecurityEngine.ENCRYPTED_DATA, |
| org.apache.ws.security.processor.EncryptedDataProcessor.class.getName() |
| ); |
| } catch (final Throwable t) { |
| if (log.isDebugEnabled()) { |
| log.debug(t.getMessage(), t); |
| } |
| } |
| DEFAULT_PROCESSORS = java.util.Collections.unmodifiableMap(tmp); |
| } |
| |
| protected static WSSConfig defaultConfig = null; |
| |
| protected boolean wsiBSPCompliant = false; |
| |
| /** |
| * Set the timestamp precision mode. If set to <code>true</code> then use |
| * timestamps with milliseconds, otherwise omit the millisconds. As per XML |
| * Date/Time specification the default is to include the milliseconds. |
| */ |
| protected boolean precisionInMilliSeconds = true; |
| |
| protected boolean enableSignatureConfirmation = true; |
| |
| /** |
| * If set to true then the timestamp handling will throw an exception if the |
| * timestamp contains an expires element and the semantics are expired. |
| * |
| * If set to false, no exception will be thrown, even if the semantics are |
| * expired. |
| */ |
| protected boolean timeStampStrict = true; |
| |
| /** |
| * This variable controls whether types other than PasswordDigest or PasswordText |
| * are allowed when processing UsernameTokens. |
| * |
| * By default this is set to false so that the user doesn't have to explicitly |
| * reject custom token types in the callback handler. |
| */ |
| protected boolean handleCustomPasswordTypes = false; |
| |
| protected HashMap jceProvider = new HashMap(10); |
| |
| /** |
| * The known actions. These are initialized from a set of defaults, |
| * but the list may be modified via the setAction operation. |
| */ |
| private final java.util.Map actionMap = new java.util.HashMap(DEFAULT_ACTIONS); |
| |
| /** |
| * The known processors. These are initialized from a set of defaults, |
| * but the list may be modified via the setProcessor operation. |
| */ |
| private final java.util.Map processorMap = new java.util.HashMap(DEFAULT_PROCESSORS); |
| |
| /** |
| * a static boolean flag that determines whether default JCE providers |
| * should be added at the time of construction. |
| * |
| * These providers, and the order in which they are added, can interfere |
| * with some JVMs (such as IBMs). |
| */ |
| private static boolean addJceProviders = true; |
| |
| /** |
| * a boolean flag to record whether we have already been statically |
| * initialized. This flag prevents repeated and unecessary calls |
| * to static initialization code at construction time. |
| */ |
| private static boolean staticallyInitialized = false; |
| |
| /** |
| * Set the value of the internal addJceProviders flag. This flag |
| * turns on (or off) automatic registration of known JCE providers |
| * that provide necessary cryptographic algorithms for use with WSS4J. |
| * By default, this flag is true, for backwards compatibility. You may |
| * wish (or need) to initialize the JCE manually, e.g., in some JVMs. |
| */ |
| public static void setAddJceProviders(boolean value) { |
| addJceProviders = value; |
| } |
| |
| private synchronized void |
| staticInit() { |
| if (!staticallyInitialized) { |
| org.apache.xml.security.Init.init(); |
| if (addJceProviders) { |
| /* |
| * The last provider added has precedence, that is if JuiCE can be add |
| * then WSS4J uses this provider. |
| */ |
| addJceProvider("BC", |
| "org.bouncycastle.jce.provider.BouncyCastleProvider"); |
| addJceProvider("JuiCE", |
| "org.apache.security.juice.provider.JuiCEProviderOpenSSL"); |
| } |
| Transform.init(); |
| try { |
| Transform.register(STRTransform.implementedTransformURI, |
| "org.apache.ws.security.transform.STRTransform"); |
| } catch (Exception ex) { |
| if (log.isDebugEnabled()) { |
| log.debug(ex.getMessage(), ex); |
| } |
| } |
| staticallyInitialized = true; |
| } |
| } |
| |
| protected WSSConfig() { |
| staticInit(); |
| } |
| |
| /** |
| * @return a new WSSConfig instance configured with the default values |
| * (values identical to |
| * {@link #getDefaultWSConfig getDefaultWSConfig()}) |
| */ |
| public static WSSConfig getNewInstance() { |
| WSSConfig config = new WSSConfig(); |
| return config; |
| } |
| |
| /** |
| * returns a static WSConfig instance that is configured with the latest |
| * OASIS WS-Security settings. |
| */ |
| public static WSSConfig getDefaultWSConfig() { |
| if (defaultConfig == null) { |
| defaultConfig = getNewInstance(); |
| } |
| return defaultConfig; |
| } |
| |
| /** |
| * Checks if we are in WS-I Basic Security Profile compliance mode |
| * |
| * @return TODO |
| */ |
| public boolean isWsiBSPCompliant() { |
| return wsiBSPCompliant; |
| } |
| |
| /** |
| * Set the WS-I Basic Security Profile compliance mode. The default is false |
| * (dues to .Net interop problems). |
| * |
| * @param wsiBSPCompliant |
| */ |
| public void setWsiBSPCompliant(boolean wsiBSPCompliant) { |
| this.wsiBSPCompliant = wsiBSPCompliant; |
| } |
| |
| /** |
| * Checks if we need to use milliseconds in timestamps |
| * |
| * @return TODO |
| */ |
| public boolean isPrecisionInMilliSeconds() { |
| return precisionInMilliSeconds; |
| } |
| |
| /** |
| * Set the precision in milliseconds |
| * |
| * @param precisionInMilliSeconds |
| * TODO |
| */ |
| public void setPrecisionInMilliSeconds(boolean precisionInMilliSeconds) { |
| this.precisionInMilliSeconds = precisionInMilliSeconds; |
| } |
| |
| /** |
| * @return Returns the enableSignatureConfirmation. |
| */ |
| public boolean isEnableSignatureConfirmation() { |
| return enableSignatureConfirmation; |
| } |
| |
| /** |
| * @param enableSignatureConfirmation |
| * The enableSignatureConfirmation to set. |
| */ |
| public void setEnableSignatureConfirmation( |
| boolean enableSignatureConfirmation) { |
| this.enableSignatureConfirmation = enableSignatureConfirmation; |
| } |
| |
| /** |
| * @param handleCustomTypes |
| * whether to handle custom UsernameToken password types or not |
| */ |
| public void setHandleCustomPasswordTypes(boolean handleCustomTypes) { |
| this.handleCustomPasswordTypes = handleCustomTypes; |
| } |
| |
| /** |
| * @return whether custom UsernameToken password types are allowed or not |
| */ |
| public boolean getHandleCustomPasswordTypes() { |
| return handleCustomPasswordTypes; |
| } |
| |
| /** |
| * @return Returns if we shall throw an exception on expired request |
| * semantic |
| */ |
| public boolean isTimeStampStrict() { |
| return timeStampStrict; |
| } |
| |
| /** |
| * @param timeStampStrict |
| * If true throw an exception on expired request semantic |
| */ |
| public void setTimeStampStrict(boolean timeStampStrict) { |
| this.timeStampStrict = timeStampStrict; |
| } |
| |
| /** |
| * Associate an action with a specific action code. |
| * |
| * This operation allows applications to supply their own |
| * actions for well-known operations. |
| */ |
| public String setAction(int code, String action) { |
| return (String) actionMap.put(new Integer(code), action); |
| } |
| |
| /** |
| * Lookup action |
| * |
| * @param action |
| * @return An action class to create a security token |
| * @throws WSSecurityException |
| */ |
| public Action getAction(int action) throws WSSecurityException { |
| Integer key = new Integer(action); |
| String name = (String) actionMap.get(key); |
| if (name == null) { |
| throw new WSSecurityException(WSSecurityException.FAILURE, |
| "unknownAction", new Object[] { key }); |
| } |
| try { |
| return (Action) Loader.loadClass(name).newInstance(); |
| } catch (Throwable t) { |
| if (log.isDebugEnabled()) { |
| log.debug(t.getMessage(), t); |
| } |
| throw new WSSecurityException(WSSecurityException.FAILURE, |
| "unableToLoadClass", new Object[] { name }, t); |
| } |
| } |
| |
| /** |
| * Associate a SOAP processor name with a specified SOAP Security header |
| * element QName. Processors registered under this QName will be |
| * called when processing header elements with the specified type. |
| */ |
| public String setProcessor(QName el, String name) { |
| return (String) processorMap.put(el, name); |
| } |
| |
| /** |
| * @return the SOAP processor associated with the specified |
| * QName. The QName is intended to refer to an element |
| * in a SOAP security header. This operation returns |
| * null if there is no processor associated with the |
| * specified QName. |
| */ |
| public Processor getProcessor(QName el) throws WSSecurityException { |
| final String name = (String) processorMap.get(el); |
| if (name != null) { |
| try { |
| return (Processor) Loader.loadClass(name).newInstance(); |
| } catch (Throwable t) { |
| if (log.isDebugEnabled()) { |
| log.debug(t.getMessage(), t); |
| } |
| throw new WSSecurityException(WSSecurityException.FAILURE, |
| "unableToLoadClass", new Object[] { name }, t); |
| } |
| } |
| return null; |
| } |
| |
| private boolean loadProvider(String id, String className) { |
| try { |
| Class c = Loader.loadClass(className); |
| if (java.security.Security.getProvider(id) == null) { |
| if (log.isDebugEnabled()) { |
| log.debug("The provider " + id |
| + " had to be added to the java.security.Security"); |
| } |
| int ret =java.security.Security.insertProviderAt( |
| (java.security.Provider) c.newInstance(), 2); |
| if (log.isDebugEnabled()) { |
| log.debug("The provider " + id + " was added at: " |
| + ret); |
| } |
| } |
| return true; |
| } catch (Throwable t) { |
| if (log.isDebugEnabled()) { |
| log.debug("The provider " + id + " could not be added: " |
| + t.getMessage(), t); |
| } |
| return false; |
| } |
| |
| } |
| |
| /** |
| * Add a new JCE security provider to use for WSS4J. |
| * |
| * If the provider is not already known the method loads a security provider |
| * class and adds the provider to the java security service. |
| * |
| * |
| * @param id |
| * The id string of the provider |
| * @param className |
| * Name of the class the implements the provider. This class must |
| * be a subclass of <code>java.security.Provider</code> |
| * |
| * @return Returns <code>true</code> if the provider was successfully |
| * added, <code>false</code> otherwise. |
| */ |
| public boolean addJceProvider(String id, String className) { |
| if (jceProvider.get(id) == null && loadProvider(id, className)) { |
| jceProvider.put(id, className); |
| return true; |
| } |
| return false; |
| } |
| } |