You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ws.apache.org by co...@apache.org on 2013/06/11 17:45:28 UTC
svn commit: r1491846 - in /webservices/wss4j/trunk/ws-security-stax/src:
main/java/org/apache/wss4j/stax/ext/
main/java/org/apache/wss4j/stax/impl/processor/input/
main/java/org/apache/wss4j/stax/impl/processor/output/
main/java/org/apache/wss4j/stax/i...
Author: coheigea
Date: Tue Jun 11 15:45:27 2013
New Revision: 1491846
URL: http://svn.apache.org/r1491846
Log:
Adapting JCEMapper fix from Santuario + also adding functionality to use a single Symmetric Key for Encryption + Signature as per the SymmetricBinding
Added:
webservices/wss4j/trunk/ws-security-stax/src/test/java/org/apache/wss4j/stax/test/SignatureEncryptionTest.java
Modified:
webservices/wss4j/trunk/ws-security-stax/src/main/java/org/apache/wss4j/stax/ext/OutboundWSSec.java
webservices/wss4j/trunk/ws-security-stax/src/main/java/org/apache/wss4j/stax/impl/processor/input/DerivedKeyTokenInputHandler.java
webservices/wss4j/trunk/ws-security-stax/src/main/java/org/apache/wss4j/stax/impl/processor/input/SAMLTokenInputHandler.java
webservices/wss4j/trunk/ws-security-stax/src/main/java/org/apache/wss4j/stax/impl/processor/output/BinarySecurityTokenOutputProcessor.java
webservices/wss4j/trunk/ws-security-stax/src/main/java/org/apache/wss4j/stax/impl/processor/output/DerivedKeyTokenOutputProcessor.java
webservices/wss4j/trunk/ws-security-stax/src/main/java/org/apache/wss4j/stax/impl/processor/output/EncryptedKeyOutputProcessor.java
webservices/wss4j/trunk/ws-security-stax/src/main/java/org/apache/wss4j/stax/impl/processor/output/SAMLTokenOutputProcessor.java
webservices/wss4j/trunk/ws-security-stax/src/main/java/org/apache/wss4j/stax/impl/processor/output/WSSSignatureEndingOutputProcessor.java
webservices/wss4j/trunk/ws-security-stax/src/main/java/org/apache/wss4j/stax/impl/securityToken/EncryptedKeySha1SecurityTokenImpl.java
webservices/wss4j/trunk/ws-security-stax/src/main/java/org/apache/wss4j/stax/impl/securityToken/KerberosClientSecurityToken.java
webservices/wss4j/trunk/ws-security-stax/src/main/java/org/apache/wss4j/stax/impl/securityToken/KerberosServiceSecurityTokenImpl.java
webservices/wss4j/trunk/ws-security-stax/src/main/java/org/apache/wss4j/stax/impl/securityToken/OutboundUsernameSecurityToken.java
webservices/wss4j/trunk/ws-security-stax/src/main/java/org/apache/wss4j/stax/impl/securityToken/UsernameSecurityTokenImpl.java
Modified: webservices/wss4j/trunk/ws-security-stax/src/main/java/org/apache/wss4j/stax/ext/OutboundWSSec.java
URL: http://svn.apache.org/viewvc/webservices/wss4j/trunk/ws-security-stax/src/main/java/org/apache/wss4j/stax/ext/OutboundWSSec.java?rev=1491846&r1=1491845&r2=1491846&view=diff
==============================================================================
--- webservices/wss4j/trunk/ws-security-stax/src/main/java/org/apache/wss4j/stax/ext/OutboundWSSec.java (original)
+++ webservices/wss4j/trunk/ws-security-stax/src/main/java/org/apache/wss4j/stax/ext/OutboundWSSec.java Tue Jun 11 15:45:27 2013
@@ -136,7 +136,7 @@ public class OutboundWSSec {
final SecurityHeaderOutputProcessor securityHeaderOutputProcessor = new SecurityHeaderOutputProcessor();
initializeOutputProcessor(outputProcessorChain, securityHeaderOutputProcessor, null);
//todo some combinations are not possible atm: eg Action.SIGNATURE and Action.USERNAMETOKEN_SIGNED
- //todo they use the same signaure parts
+ //todo they use the same signature parts
for (int i = 0; i < securityProperties.getOutAction().length; i++) {
XMLSecurityConstants.Action action = securityProperties.getOutAction()[i];
if (WSSConstants.TIMESTAMP.equals(action)) {
Modified: webservices/wss4j/trunk/ws-security-stax/src/main/java/org/apache/wss4j/stax/impl/processor/input/DerivedKeyTokenInputHandler.java
URL: http://svn.apache.org/viewvc/webservices/wss4j/trunk/ws-security-stax/src/main/java/org/apache/wss4j/stax/impl/processor/input/DerivedKeyTokenInputHandler.java?rev=1491846&r1=1491845&r2=1491846&view=diff
==============================================================================
--- webservices/wss4j/trunk/ws-security-stax/src/main/java/org/apache/wss4j/stax/impl/processor/input/DerivedKeyTokenInputHandler.java (original)
+++ webservices/wss4j/trunk/ws-security-stax/src/main/java/org/apache/wss4j/stax/impl/processor/input/DerivedKeyTokenInputHandler.java Tue Jun 11 15:45:27 2013
@@ -149,7 +149,7 @@ public class DerivedKeyTokenInputHandler
algorithmSuiteSecurityEvent.setCorrelationID(correlationID);
inputProcessorChain.getSecurityContext().registerSecurityEvent(algorithmSuiteSecurityEvent);
- String algo = JCEAlgorithmMapper.getJCERequiredKeyFromURI(algorithmURI);
+ String algo = JCEAlgorithmMapper.getJCEKeyAlgorithmFromURI(algorithmURI);
return new SecretKeySpec(keyBytes, algo);
}
Modified: webservices/wss4j/trunk/ws-security-stax/src/main/java/org/apache/wss4j/stax/impl/processor/input/SAMLTokenInputHandler.java
URL: http://svn.apache.org/viewvc/webservices/wss4j/trunk/ws-security-stax/src/main/java/org/apache/wss4j/stax/impl/processor/input/SAMLTokenInputHandler.java?rev=1491846&r1=1491845&r2=1491846&view=diff
==============================================================================
--- webservices/wss4j/trunk/ws-security-stax/src/main/java/org/apache/wss4j/stax/impl/processor/input/SAMLTokenInputHandler.java (original)
+++ webservices/wss4j/trunk/ws-security-stax/src/main/java/org/apache/wss4j/stax/impl/processor/input/SAMLTokenInputHandler.java Tue Jun 11 15:45:27 2013
@@ -191,7 +191,7 @@ public class SAMLTokenInputHandler exten
Key key = super.getKey(algorithmURI, algorithmUsage, correlationID);
if (key == null) {
- String algoFamily = JCEAlgorithmMapper.getJCERequiredKeyFromURI(algorithmURI);
+ String algoFamily = JCEAlgorithmMapper.getJCEKeyAlgorithmFromURI(algorithmURI);
key = new SecretKeySpec(subjectSecretKey, algoFamily);
setSecretKey(algorithmURI, key);
}
@@ -377,7 +377,7 @@ public class SAMLTokenInputHandler exten
throws XMLSecurityException {
Key key = super.getKey(algorithmURI, algorithmUsage, correlationID);
if (key == null) {
- String algoFamily = JCEAlgorithmMapper.getJCERequiredKeyFromURI(algorithmURI);
+ String algoFamily = JCEAlgorithmMapper.getJCEKeyAlgorithmFromURI(algorithmURI);
key = new SecretKeySpec(Base64.decodeBase64(stringBuilder.toString()), algoFamily);
setSecretKey(algorithmURI, key);
}
Modified: webservices/wss4j/trunk/ws-security-stax/src/main/java/org/apache/wss4j/stax/impl/processor/output/BinarySecurityTokenOutputProcessor.java
URL: http://svn.apache.org/viewvc/webservices/wss4j/trunk/ws-security-stax/src/main/java/org/apache/wss4j/stax/impl/processor/output/BinarySecurityTokenOutputProcessor.java?rev=1491846&r1=1491845&r2=1491846&view=diff
==============================================================================
--- webservices/wss4j/trunk/ws-security-stax/src/main/java/org/apache/wss4j/stax/impl/processor/output/BinarySecurityTokenOutputProcessor.java (original)
+++ webservices/wss4j/trunk/ws-security-stax/src/main/java/org/apache/wss4j/stax/impl/processor/output/BinarySecurityTokenOutputProcessor.java Tue Jun 11 15:45:27 2013
@@ -53,35 +53,57 @@ public class BinarySecurityTokenOutputPr
@Override
public void processEvent(XMLSecEvent xmlSecEvent, OutputProcessorChain outputProcessorChain) throws XMLStreamException, XMLSecurityException {
try {
- final String bstId = IDGenerator.generateID(null);
+ final String bstId;
final X509Certificate[] x509Certificates;
- final Key key;
+ Key key = null;
XMLSecurityConstants.Action action = getAction();
if (WSSConstants.SIGNATURE.equals(action)
|| WSSConstants.SAML_TOKEN_SIGNED.equals(action)
|| WSSConstants.SIGNATURE_WITH_DERIVED_KEY.equals(action)) {
-
- String alias = ((WSSSecurityProperties) getSecurityProperties()).getSignatureUser();
- WSPasswordCallback pwCb = new WSPasswordCallback(alias, WSPasswordCallback.Usage.SIGNATURE);
- WSSUtils.doPasswordCallback(((WSSSecurityProperties)getSecurityProperties()).getCallbackHandler(), pwCb);
- String password = pwCb.getPassword();
- byte[] secretKey = pwCb.getKey();
- if (password == null && secretKey == null) {
- throw new WSSecurityException(WSSecurityException.ErrorCode.FAILED_SIGNATURE, "noPassword", alias);
+ // See if a Symmetric Key is already available
+ String tokenId =
+ outputProcessorChain.getSecurityContext().get(WSSConstants.PROP_USE_THIS_TOKEN_ID_FOR_SIGNATURE);
+ SecurityTokenProvider<OutboundSecurityToken> signatureTokenProvider = null;
+ GenericOutboundSecurityToken securityToken = null;
+ if (tokenId != null && !WSSConstants.SIGNATURE_WITH_DERIVED_KEY.equals(getAction())) {
+ signatureTokenProvider =
+ outputProcessorChain.getSecurityContext().getSecurityTokenProvider(tokenId);
+ if (signatureTokenProvider != null) {
+ securityToken =
+ (GenericOutboundSecurityToken)signatureTokenProvider.getSecurityToken();
+ if (securityToken != null) {
+ key = securityToken.getSecretKey(getSecurityProperties().getSignatureAlgorithm());
+ }
+ }
}
- if (password != null) {
- key = ((WSSSecurityProperties) getSecurityProperties()).getSignatureCrypto().getPrivateKey(alias, password);
- CryptoType cryptoType = new CryptoType(CryptoType.TYPE.ALIAS);
- cryptoType.setAlias(alias);
- x509Certificates = ((WSSSecurityProperties) getSecurityProperties()).getSignatureCrypto().getX509Certificates(cryptoType);
- if (x509Certificates == null || x509Certificates.length == 0) {
- throw new WSSecurityException(WSSecurityException.ErrorCode.FAILED_SIGNATURE, "noUserCertsFound", alias);
+
+ if (key == null) {
+ bstId = IDGenerator.generateID(null);
+ String alias = ((WSSSecurityProperties) getSecurityProperties()).getSignatureUser();
+ WSPasswordCallback pwCb = new WSPasswordCallback(alias, WSPasswordCallback.Usage.SIGNATURE);
+ WSSUtils.doPasswordCallback(((WSSSecurityProperties)getSecurityProperties()).getCallbackHandler(), pwCb);
+ String password = pwCb.getPassword();
+ byte[] secretKey = pwCb.getKey();
+ if (password == null && secretKey == null) {
+ throw new WSSecurityException(WSSecurityException.ErrorCode.FAILED_SIGNATURE, "noPassword", alias);
}
+ if (password != null) {
+ key = ((WSSSecurityProperties) getSecurityProperties()).getSignatureCrypto().getPrivateKey(alias, password);
+ CryptoType cryptoType = new CryptoType(CryptoType.TYPE.ALIAS);
+ cryptoType.setAlias(alias);
+ x509Certificates = ((WSSSecurityProperties) getSecurityProperties()).getSignatureCrypto().getX509Certificates(cryptoType);
+ if (x509Certificates == null || x509Certificates.length == 0) {
+ throw new WSSecurityException(WSSecurityException.ErrorCode.FAILED_SIGNATURE, "noUserCertsFound", alias);
+ }
+ } else {
+ x509Certificates = null;
+ String algoFamily = JCEAlgorithmMapper.getJCEKeyAlgorithmFromURI(getSecurityProperties().getSignatureAlgorithm());
+ key = new SecretKeySpec(secretKey, algoFamily);
+ }
} else {
+ bstId = tokenId;
x509Certificates = null;
- String algoFamily = JCEAlgorithmMapper.getJCERequiredKeyFromURI(getSecurityProperties().getSignatureAlgorithm());
- key = new SecretKeySpec(secretKey, algoFamily);
}
} else if (WSSConstants.ENCRYPT.equals(action) ||
WSSConstants.ENCRYPT_WITH_DERIVED_KEY.equals(action)) {
@@ -116,7 +138,9 @@ public class BinarySecurityTokenOutputPr
}
key = null;
+ bstId = IDGenerator.generateID(null);
} else {
+ bstId = IDGenerator.generateID(null);
x509Certificates = null;
key = null;
}
Modified: webservices/wss4j/trunk/ws-security-stax/src/main/java/org/apache/wss4j/stax/impl/processor/output/DerivedKeyTokenOutputProcessor.java
URL: http://svn.apache.org/viewvc/webservices/wss4j/trunk/ws-security-stax/src/main/java/org/apache/wss4j/stax/impl/processor/output/DerivedKeyTokenOutputProcessor.java?rev=1491846&r1=1491845&r2=1491846&view=diff
==============================================================================
--- webservices/wss4j/trunk/ws-security-stax/src/main/java/org/apache/wss4j/stax/impl/processor/output/DerivedKeyTokenOutputProcessor.java (original)
+++ webservices/wss4j/trunk/ws-security-stax/src/main/java/org/apache/wss4j/stax/impl/processor/output/DerivedKeyTokenOutputProcessor.java Tue Jun 11 15:45:27 2013
@@ -77,9 +77,9 @@ public class DerivedKeyTokenOutputProces
XMLSecurityConstants.Action action = getAction();
if (WSSConstants.SIGNATURE_WITH_DERIVED_KEY.equals(action)) {
- length = JCEAlgorithmMapper.getAlgorithmMapping(getSecurityProperties().getSignatureAlgorithm()).getKeyLength() / 8;
+ length = JCEAlgorithmMapper.getKeyLengthFromURI(getSecurityProperties().getSignatureAlgorithm()) / 8;
} else if (WSSConstants.ENCRYPT_WITH_DERIVED_KEY.equals(action)) {
- length = JCEAlgorithmMapper.getAlgorithmMapping(getSecurityProperties().getEncryptionSymAlgorithm()).getKeyLength() / 8;
+ length = JCEAlgorithmMapper.getKeyLengthFromURI(getSecurityProperties().getEncryptionSymAlgorithm()) / 8;
}
byte[] label;
@@ -137,7 +137,7 @@ public class DerivedKeyTokenOutputProces
if (key != null) {
return key;
}
- String algoFamily = JCEAlgorithmMapper.getJCERequiredKeyFromURI(algorithmURI);
+ String algoFamily = JCEAlgorithmMapper.getJCEKeyAlgorithmFromURI(algorithmURI);
key = new SecretKeySpec(derivedKeyBytes, algoFamily);
setSecretKey(algorithmURI, key);
return key;
Modified: webservices/wss4j/trunk/ws-security-stax/src/main/java/org/apache/wss4j/stax/impl/processor/output/EncryptedKeyOutputProcessor.java
URL: http://svn.apache.org/viewvc/webservices/wss4j/trunk/ws-security-stax/src/main/java/org/apache/wss4j/stax/impl/processor/output/EncryptedKeyOutputProcessor.java?rev=1491846&r1=1491845&r2=1491846&view=diff
==============================================================================
--- webservices/wss4j/trunk/ws-security-stax/src/main/java/org/apache/wss4j/stax/impl/processor/output/EncryptedKeyOutputProcessor.java (original)
+++ webservices/wss4j/trunk/ws-security-stax/src/main/java/org/apache/wss4j/stax/impl/processor/output/EncryptedKeyOutputProcessor.java Tue Jun 11 15:45:27 2013
@@ -74,64 +74,84 @@ public class EncryptedKeyOutputProcessor
if (wrappingSecurityToken == null) {
throw new WSSecurityException(WSSecurityException.ErrorCode.FAILURE);
}
-
- //prepare the symmetric session key for all encryption parts
- String keyAlgorithm = JCEAlgorithmMapper.getJCERequiredKeyFromURI(securityProperties.getEncryptionSymAlgorithm());
- KeyGenerator keyGen;
- try {
- keyGen = KeyGenerator.getInstance(keyAlgorithm);
- } catch (NoSuchAlgorithmException e) {
- throw new WSSecurityException(WSSecurityException.ErrorCode.FAILURE, e);
+
+ // See if a Symmetric Key is already available
+ String encTokenId =
+ outputProcessorChain.getSecurityContext().get(WSSConstants.PROP_USE_THIS_TOKEN_ID_FOR_ENCRYPTION);
+ SecurityTokenProvider<OutboundSecurityToken> encryptedKeySecurityTokenProvider = null;
+ GenericOutboundSecurityToken encryptedKeySecurityToken = null;
+ if (encTokenId != null && !WSSConstants.SIGNATURE_WITH_DERIVED_KEY.equals(getAction())) {
+ encryptedKeySecurityTokenProvider =
+ outputProcessorChain.getSecurityContext().getSecurityTokenProvider(encTokenId);
+ if (encryptedKeySecurityTokenProvider != null) {
+ encryptedKeySecurityToken =
+ (GenericOutboundSecurityToken)encryptedKeySecurityTokenProvider.getSecurityToken();
+ }
}
- //the sun JCE provider expects the real key size for 3DES (112 or 168 bit)
- //whereas bouncy castle expects the block size of 128 or 192 bits
- if (keyAlgorithm.contains("AES")) {
- int keyLength = JCEAlgorithmMapper.getKeyLengthFromURI(securityProperties.getEncryptionSymAlgorithm());
- keyGen.init(keyLength);
+
+ if (encryptedKeySecurityToken == null) {
+ // Generate Key
+ //prepare the symmetric session key for all encryption parts
+ String keyAlgorithm = JCEAlgorithmMapper.getJCEKeyAlgorithmFromURI(securityProperties.getEncryptionSymAlgorithm());
+ KeyGenerator keyGen;
+ try {
+ keyGen = KeyGenerator.getInstance(keyAlgorithm);
+ } catch (NoSuchAlgorithmException e) {
+ throw new WSSecurityException(WSSecurityException.ErrorCode.FAILURE, e);
+ }
+ //the sun JCE provider expects the real key size for 3DES (112 or 168 bit)
+ //whereas bouncy castle expects the block size of 128 or 192 bits
+ if (keyAlgorithm.contains("AES")) {
+ int keyLength = JCEAlgorithmMapper.getKeyLengthFromURI(securityProperties.getEncryptionSymAlgorithm());
+ keyGen.init(keyLength);
+ }
+
+ final Key symmetricKey = keyGen.generateKey();
+
+ final String ekId = IDGenerator.generateID(null);
+
+ final GenericOutboundSecurityToken securityToken = new GenericOutboundSecurityToken(ekId, WSSecurityTokenConstants.EncryptedKeyToken, symmetricKey);
+ final SecurityTokenProvider<OutboundSecurityToken> securityTokenProvider =
+ new SecurityTokenProvider<OutboundSecurityToken>() {
+
+ @Override
+ public OutboundSecurityToken getSecurityToken() throws XMLSecurityException {
+ return securityToken;
+ }
+
+ @Override
+ public String getId() {
+ return ekId;
+ }
+ };
+
+ encryptedKeySecurityTokenProvider = securityTokenProvider;
+ encryptedKeySecurityToken = securityToken;
}
-
- final Key symmetricKey = keyGen.generateKey();
-
- final String ekId = IDGenerator.generateID(null);
-
- final GenericOutboundSecurityToken encryptedKeySecurityToken = new GenericOutboundSecurityToken(ekId, WSSecurityTokenConstants.EncryptedKeyToken, symmetricKey);
+
encryptedKeySecurityToken.setKeyWrappingToken(wrappingSecurityToken);
wrappingSecurityToken.addWrappedToken(encryptedKeySecurityToken);
- final SecurityTokenProvider<OutboundSecurityToken> encryptedKeySecurityTokenProvider =
- new SecurityTokenProvider<OutboundSecurityToken>() {
-
- @Override
- public OutboundSecurityToken getSecurityToken() throws XMLSecurityException {
- return encryptedKeySecurityToken;
- }
-
- @Override
- public String getId() {
- return ekId;
- }
- };
-
FinalEncryptedKeyOutputProcessor finalEncryptedKeyOutputProcessor = new FinalEncryptedKeyOutputProcessor(encryptedKeySecurityToken);
finalEncryptedKeyOutputProcessor.setXMLSecurityProperties(getSecurityProperties());
finalEncryptedKeyOutputProcessor.setAction(getAction());
XMLSecurityConstants.Action action = getAction();
if (WSSConstants.ENCRYPT.equals(action)) {
- outputProcessorChain.getSecurityContext().put(WSSConstants.PROP_USE_THIS_TOKEN_ID_FOR_ENCRYPTION, ekId);
+ outputProcessorChain.getSecurityContext().put(WSSConstants.PROP_USE_THIS_TOKEN_ID_FOR_ENCRYPTION, encryptedKeySecurityToken.getId());
if (wrappingSecurityToken.getProcessor() != null) {
finalEncryptedKeyOutputProcessor.addBeforeProcessor(wrappingSecurityToken.getProcessor());
} else {
finalEncryptedKeyOutputProcessor.addAfterProcessor(EncryptEndingOutputProcessor.class.getName());
}
} else if (WSSConstants.SIGNATURE_WITH_DERIVED_KEY.equals(action)) {
- outputProcessorChain.getSecurityContext().put(WSSConstants.PROP_USE_THIS_TOKEN_ID_FOR_DERIVED_KEY, ekId);
+ outputProcessorChain.getSecurityContext().put(WSSConstants.PROP_USE_THIS_TOKEN_ID_FOR_DERIVED_KEY, encryptedKeySecurityToken.getId());
if (wrappingSecurityToken.getProcessor() != null) {
finalEncryptedKeyOutputProcessor.addBeforeProcessor(wrappingSecurityToken.getProcessor());
} else {
finalEncryptedKeyOutputProcessor.addBeforeProcessor(WSSSignatureOutputProcessor.class.getName());
}
} else if (WSSConstants.ENCRYPT_WITH_DERIVED_KEY.equals(action)) {
- outputProcessorChain.getSecurityContext().put(WSSConstants.PROP_USE_THIS_TOKEN_ID_FOR_DERIVED_KEY, ekId);
+ outputProcessorChain.getSecurityContext().put(WSSConstants.PROP_USE_THIS_TOKEN_ID_FOR_DERIVED_KEY, encryptedKeySecurityToken.getId());
if (wrappingSecurityToken.getProcessor() != null) {
finalEncryptedKeyOutputProcessor.addBeforeProcessor(wrappingSecurityToken.getProcessor());
} else {
@@ -139,7 +159,7 @@ public class EncryptedKeyOutputProcessor
}
}
finalEncryptedKeyOutputProcessor.init(outputProcessorChain);
- outputProcessorChain.getSecurityContext().registerSecurityTokenProvider(ekId, encryptedKeySecurityTokenProvider);
+ outputProcessorChain.getSecurityContext().registerSecurityTokenProvider(encryptedKeySecurityToken.getId(), encryptedKeySecurityTokenProvider);
encryptedKeySecurityToken.setProcessor(finalEncryptedKeyOutputProcessor);
} finally {
outputProcessorChain.removeProcessor(this);
Modified: webservices/wss4j/trunk/ws-security-stax/src/main/java/org/apache/wss4j/stax/impl/processor/output/SAMLTokenOutputProcessor.java
URL: http://svn.apache.org/viewvc/webservices/wss4j/trunk/ws-security-stax/src/main/java/org/apache/wss4j/stax/impl/processor/output/SAMLTokenOutputProcessor.java?rev=1491846&r1=1491845&r2=1491846&view=diff
==============================================================================
--- webservices/wss4j/trunk/ws-security-stax/src/main/java/org/apache/wss4j/stax/impl/processor/output/SAMLTokenOutputProcessor.java (original)
+++ webservices/wss4j/trunk/ws-security-stax/src/main/java/org/apache/wss4j/stax/impl/processor/output/SAMLTokenOutputProcessor.java Tue Jun 11 15:45:27 2013
@@ -234,9 +234,11 @@ public class SAMLTokenOutputProcessor ex
if (key != null) {
return key;
}
- String algoFamily = JCEAlgorithmMapper.getJCERequiredKeyFromURI(algorithmURI);
- key = new SecretKeySpec(samlKeyInfo.getSecret(), algoFamily);
- setSecretKey(algorithmURI, key);
+ if (samlKeyInfo.getSecret() != null) {
+ String algoFamily = JCEAlgorithmMapper.getJCEKeyAlgorithmFromURI(algorithmURI);
+ key = new SecretKeySpec(samlKeyInfo.getSecret(), algoFamily);
+ setSecretKey(algorithmURI, key);
+ }
return key;
}
};
Modified: webservices/wss4j/trunk/ws-security-stax/src/main/java/org/apache/wss4j/stax/impl/processor/output/WSSSignatureEndingOutputProcessor.java
URL: http://svn.apache.org/viewvc/webservices/wss4j/trunk/ws-security-stax/src/main/java/org/apache/wss4j/stax/impl/processor/output/WSSSignatureEndingOutputProcessor.java?rev=1491846&r1=1491845&r2=1491846&view=diff
==============================================================================
--- webservices/wss4j/trunk/ws-security-stax/src/main/java/org/apache/wss4j/stax/impl/processor/output/WSSSignatureEndingOutputProcessor.java (original)
+++ webservices/wss4j/trunk/ws-security-stax/src/main/java/org/apache/wss4j/stax/impl/processor/output/WSSSignatureEndingOutputProcessor.java Tue Jun 11 15:45:27 2013
@@ -89,7 +89,7 @@ public class WSSSignatureEndingOutputPro
WSSecurityTokenConstants.KeyIdentifier keyIdentifier = getSecurityProperties().getSignatureKeyIdentifier();
X509Certificate[] x509Certificates = securityToken.getX509Certificates();
-
+
if (WSSecurityTokenConstants.KeyIdentifier_KeyValue.equals(keyIdentifier)) {
WSSUtils.createKeyValueTokenStructure(this, outputProcessorChain, x509Certificates);
} else {
@@ -97,7 +97,8 @@ public class WSSSignatureEndingOutputPro
attributes.add(createAttribute(WSSConstants.ATT_wsu_Id, IDGenerator.generateID(null)));
if (WSSecurityTokenConstants.KeyIdentifier_SecurityTokenDirectReference.equals(keyIdentifier) && !useSingleCertificate) {
attributes.add(createAttribute(WSSConstants.ATT_wsse11_TokenType, WSSConstants.NS_X509PKIPathv1));
- } else if (WSSecurityTokenConstants.KeyIdentifier_EncryptedKeySha1Identifier.equals(keyIdentifier)) {
+ } else if (WSSecurityTokenConstants.KeyIdentifier_EncryptedKeySha1Identifier.equals(keyIdentifier)
+ || (WSSecurityTokenConstants.KeyIdentifier_EncryptedKey.equals(keyIdentifier))) {
attributes.add(createAttribute(WSSConstants.ATT_wsse11_TokenType, WSSConstants.NS_WSS_ENC_KEY_VALUE_TYPE));
} else if (WSSecurityTokenConstants.Saml10Token.equals(securityToken.getTokenType())
|| WSSecurityTokenConstants.Saml11Token.equals(securityToken.getTokenType())) {
@@ -122,6 +123,9 @@ public class WSSSignatureEndingOutputPro
} else if (WSSecurityTokenConstants.KeyIdentifier_EncryptedKeySha1Identifier.equals(keyIdentifier)) {
WSSUtils.createEncryptedKeySha1IdentifierStructure(this, outputProcessorChain,
securityToken.getSecretKey(getSecurityProperties().getSignatureAlgorithm()));
+ } else if (WSSecurityTokenConstants.KeyIdentifier_EncryptedKey.equals(keyIdentifier)) {
+ String id = securityToken.getId();
+ WSSUtils.createBSTReferenceStructure(this, outputProcessorChain, id, WSSConstants.NS_WSS_ENC_KEY_VALUE_TYPE);
} else if (WSSecurityTokenConstants.KeyIdentifier_SecurityTokenDirectReference.equals(keyIdentifier)) {
String valueType;
if (WSSecurityTokenConstants.Saml20Token.equals(securityToken.getTokenType())) {
Modified: webservices/wss4j/trunk/ws-security-stax/src/main/java/org/apache/wss4j/stax/impl/securityToken/EncryptedKeySha1SecurityTokenImpl.java
URL: http://svn.apache.org/viewvc/webservices/wss4j/trunk/ws-security-stax/src/main/java/org/apache/wss4j/stax/impl/securityToken/EncryptedKeySha1SecurityTokenImpl.java?rev=1491846&r1=1491845&r2=1491846&view=diff
==============================================================================
--- webservices/wss4j/trunk/ws-security-stax/src/main/java/org/apache/wss4j/stax/impl/securityToken/EncryptedKeySha1SecurityTokenImpl.java (original)
+++ webservices/wss4j/trunk/ws-security-stax/src/main/java/org/apache/wss4j/stax/impl/securityToken/EncryptedKeySha1SecurityTokenImpl.java Tue Jun 11 15:45:27 2013
@@ -72,7 +72,7 @@ public class EncryptedKeySha1SecurityTok
throw new WSSecurityException(WSSecurityException.ErrorCode.FAILURE, "noKey", sha1Identifier);
}
- String algoFamily = JCEAlgorithmMapper.getJCERequiredKeyFromURI(algorithmURI);
+ String algoFamily = JCEAlgorithmMapper.getJCEKeyAlgorithmFromURI(algorithmURI);
key = new SecretKeySpec(secretKeyCallback.getKey(), algoFamily);
setSecretKey(algorithmURI, key);
return key;
Modified: webservices/wss4j/trunk/ws-security-stax/src/main/java/org/apache/wss4j/stax/impl/securityToken/KerberosClientSecurityToken.java
URL: http://svn.apache.org/viewvc/webservices/wss4j/trunk/ws-security-stax/src/main/java/org/apache/wss4j/stax/impl/securityToken/KerberosClientSecurityToken.java?rev=1491846&r1=1491845&r2=1491846&view=diff
==============================================================================
--- webservices/wss4j/trunk/ws-security-stax/src/main/java/org/apache/wss4j/stax/impl/securityToken/KerberosClientSecurityToken.java (original)
+++ webservices/wss4j/trunk/ws-security-stax/src/main/java/org/apache/wss4j/stax/impl/securityToken/KerberosClientSecurityToken.java Tue Jun 11 15:45:27 2013
@@ -138,7 +138,7 @@ public class KerberosClientSecurityToken
if (this.secretKey == null) {
getTGT();
}
- String algoFamily = JCEAlgorithmMapper.getJCERequiredKeyFromURI(algorithmURI);
+ String algoFamily = JCEAlgorithmMapper.getJCEKeyAlgorithmFromURI(algorithmURI);
key = new SecretKeySpec(this.secretKey.getEncoded(), algoFamily);
setSecretKey(algorithmURI, key);
return key;
Modified: webservices/wss4j/trunk/ws-security-stax/src/main/java/org/apache/wss4j/stax/impl/securityToken/KerberosServiceSecurityTokenImpl.java
URL: http://svn.apache.org/viewvc/webservices/wss4j/trunk/ws-security-stax/src/main/java/org/apache/wss4j/stax/impl/securityToken/KerberosServiceSecurityTokenImpl.java?rev=1491846&r1=1491845&r2=1491846&view=diff
==============================================================================
--- webservices/wss4j/trunk/ws-security-stax/src/main/java/org/apache/wss4j/stax/impl/securityToken/KerberosServiceSecurityTokenImpl.java (original)
+++ webservices/wss4j/trunk/ws-security-stax/src/main/java/org/apache/wss4j/stax/impl/securityToken/KerberosServiceSecurityTokenImpl.java Tue Jun 11 15:45:27 2013
@@ -140,7 +140,7 @@ public class KerberosServiceSecurityToke
}
byte[] secretToken = this.kerberosTokenDecoder.getSessionKey();
- String algoFamily = JCEAlgorithmMapper.getJCERequiredKeyFromURI(algorithmURI);
+ String algoFamily = JCEAlgorithmMapper.getJCEKeyAlgorithmFromURI(algorithmURI);
key = new SecretKeySpec(secretToken, algoFamily);
setSecretKey(algorithmURI, key);
return key;
Modified: webservices/wss4j/trunk/ws-security-stax/src/main/java/org/apache/wss4j/stax/impl/securityToken/OutboundUsernameSecurityToken.java
URL: http://svn.apache.org/viewvc/webservices/wss4j/trunk/ws-security-stax/src/main/java/org/apache/wss4j/stax/impl/securityToken/OutboundUsernameSecurityToken.java?rev=1491846&r1=1491845&r2=1491846&view=diff
==============================================================================
--- webservices/wss4j/trunk/ws-security-stax/src/main/java/org/apache/wss4j/stax/impl/securityToken/OutboundUsernameSecurityToken.java (original)
+++ webservices/wss4j/trunk/ws-security-stax/src/main/java/org/apache/wss4j/stax/impl/securityToken/OutboundUsernameSecurityToken.java Tue Jun 11 15:45:27 2013
@@ -74,7 +74,7 @@ public class OutboundUsernameSecurityTok
byte[] secretToken =
UsernameTokenUtil.generateDerivedKey(getPassword(), salt, iterations);
- String algoFamily = JCEAlgorithmMapper.getJCERequiredKeyFromURI(algorithmURI);
+ String algoFamily = JCEAlgorithmMapper.getJCEKeyAlgorithmFromURI(algorithmURI);
key = new SecretKeySpec(secretToken, algoFamily);
setSecretKey(algorithmURI, key);
return key;
Modified: webservices/wss4j/trunk/ws-security-stax/src/main/java/org/apache/wss4j/stax/impl/securityToken/UsernameSecurityTokenImpl.java
URL: http://svn.apache.org/viewvc/webservices/wss4j/trunk/ws-security-stax/src/main/java/org/apache/wss4j/stax/impl/securityToken/UsernameSecurityTokenImpl.java?rev=1491846&r1=1491845&r2=1491846&view=diff
==============================================================================
--- webservices/wss4j/trunk/ws-security-stax/src/main/java/org/apache/wss4j/stax/impl/securityToken/UsernameSecurityTokenImpl.java (original)
+++ webservices/wss4j/trunk/ws-security-stax/src/main/java/org/apache/wss4j/stax/impl/securityToken/UsernameSecurityTokenImpl.java Tue Jun 11 15:45:27 2013
@@ -82,7 +82,7 @@ public class UsernameSecurityTokenImpl e
}
byte[] secretToken = generateDerivedKey(wsInboundSecurityContext);
- String algoFamily = JCEAlgorithmMapper.getJCERequiredKeyFromURI(algorithmURI);
+ String algoFamily = JCEAlgorithmMapper.getJCEKeyAlgorithmFromURI(algorithmURI);
key = new SecretKeySpec(secretToken, algoFamily);
setSecretKey(algorithmURI, key);
return key;
Added: webservices/wss4j/trunk/ws-security-stax/src/test/java/org/apache/wss4j/stax/test/SignatureEncryptionTest.java
URL: http://svn.apache.org/viewvc/webservices/wss4j/trunk/ws-security-stax/src/test/java/org/apache/wss4j/stax/test/SignatureEncryptionTest.java?rev=1491846&view=auto
==============================================================================
--- webservices/wss4j/trunk/ws-security-stax/src/test/java/org/apache/wss4j/stax/test/SignatureEncryptionTest.java (added)
+++ webservices/wss4j/trunk/ws-security-stax/src/test/java/org/apache/wss4j/stax/test/SignatureEncryptionTest.java Tue Jun 11 15:45:27 2013
@@ -0,0 +1,252 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.wss4j.stax.test;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.InputStream;
+import java.security.Key;
+import java.security.NoSuchAlgorithmException;
+import java.util.ArrayList;
+
+import javax.crypto.KeyGenerator;
+import javax.xml.namespace.QName;
+import javax.xml.stream.XMLStreamReader;
+import javax.xml.stream.XMLStreamWriter;
+
+import org.apache.wss4j.common.ext.WSSecurityException;
+import org.apache.wss4j.dom.handler.WSHandlerConstants;
+import org.apache.wss4j.stax.WSSec;
+import org.apache.wss4j.stax.ext.OutboundWSSec;
+import org.apache.wss4j.stax.ext.WSSConstants;
+import org.apache.wss4j.stax.ext.WSSSecurityProperties;
+import org.apache.wss4j.stax.securityToken.WSSecurityTokenConstants;
+import org.apache.wss4j.stax.test.utils.XmlReaderToWriter;
+import org.apache.xml.security.exceptions.XMLSecurityException;
+import org.apache.xml.security.stax.config.JCEAlgorithmMapper;
+import org.apache.xml.security.stax.ext.SecurePart;
+import org.apache.xml.security.stax.impl.OutboundSecurityContextImpl;
+import org.apache.xml.security.stax.impl.securityToken.GenericOutboundSecurityToken;
+import org.apache.xml.security.stax.impl.util.IDGenerator;
+import org.apache.xml.security.stax.securityEvent.SecurityEvent;
+import org.apache.xml.security.stax.securityToken.OutboundSecurityToken;
+import org.apache.xml.security.stax.securityToken.SecurityTokenProvider;
+import org.testng.annotations.Test;
+
+public class SignatureEncryptionTest extends AbstractTestBase {
+
+ @Test
+ public void testSignatureEncryptionOutbound() throws Exception {
+
+ ByteArrayOutputStream baos;
+ {
+ WSSSecurityProperties securityProperties = new WSSSecurityProperties();
+ WSSConstants.Action[] actions =
+ new WSSConstants.Action[]{WSSConstants.SIGNATURE, WSSConstants.ENCRYPT, WSSConstants.TIMESTAMP};
+ securityProperties.setOutAction(actions);
+ securityProperties.loadEncryptionKeystore(this.getClass().getClassLoader().getResource("transmitter.jks"), "default".toCharArray());
+ securityProperties.setEncryptionUser("receiver");
+ securityProperties.loadSignatureKeyStore(this.getClass().getClassLoader().getResource("transmitter.jks"), "default".toCharArray());
+ securityProperties.setSignatureUser("transmitter");
+ securityProperties.setCallbackHandler(new CallbackHandlerImpl());
+
+ securityProperties.addSignaturePart(
+ new SecurePart(new QName(WSSConstants.NS_WSU10, "Timestamp"), SecurePart.Modifier.Element)
+ );
+ securityProperties.addSignaturePart(
+ new SecurePart(new QName(WSSConstants.NS_SOAP11, "Body"), SecurePart.Modifier.Element)
+ );
+
+ InputStream sourceDocument = this.getClass().getClassLoader().getResourceAsStream("testdata/plain-soap-1.1.xml");
+ baos = doOutboundSecurity(securityProperties, sourceDocument);
+
+ documentBuilderFactory.newDocumentBuilder().parse(new ByteArrayInputStream(baos.toByteArray()));
+ }
+
+ //done encryption; now test decryption:
+ {
+ String action = WSHandlerConstants.SIGNATURE + " " + WSHandlerConstants.ENCRYPT + " " + WSHandlerConstants.TIMESTAMP;
+ doInboundSecurityWithWSS4J(documentBuilderFactory.newDocumentBuilder().parse(new ByteArrayInputStream(baos.toByteArray())), action);
+ }
+ }
+
+ @Test
+ public void testEncryptionSymmetricOutbound() throws Exception {
+
+ ByteArrayOutputStream baos;
+ {
+ WSSSecurityProperties securityProperties = new WSSSecurityProperties();
+ WSSConstants.Action[] actions =
+ new WSSConstants.Action[]{WSSConstants.ENCRYPT, WSSConstants.TIMESTAMP};
+ securityProperties.setOutAction(actions);
+ securityProperties.loadEncryptionKeystore(this.getClass().getClassLoader().getResource("transmitter.jks"), "default".toCharArray());
+ securityProperties.setEncryptionUser("receiver");
+
+ OutboundWSSec wsSecOut = WSSec.getOutboundWSSec(securityProperties);
+
+ // Symmetric Key
+ String keyAlgorithm =
+ JCEAlgorithmMapper.getJCEKeyAlgorithmFromURI(WSSConstants.NS_XENC_AES128);
+ KeyGenerator keyGen;
+ try {
+ keyGen = KeyGenerator.getInstance(keyAlgorithm);
+ } catch (NoSuchAlgorithmException e) {
+ throw new WSSecurityException(WSSecurityException.ErrorCode.FAILURE, e);
+ }
+ int keyLength = JCEAlgorithmMapper.getKeyLengthFromURI(WSSConstants.NS_XENC_AES128);
+ keyGen.init(keyLength);
+
+ final Key symmetricKey = keyGen.generateKey();
+
+ final String ekId = IDGenerator.generateID(null);
+
+ final GenericOutboundSecurityToken encryptedKeySecurityToken =
+ new GenericOutboundSecurityToken(ekId, WSSecurityTokenConstants.EncryptedKeyToken, symmetricKey);
+
+ final SecurityTokenProvider<OutboundSecurityToken> encryptedKeySecurityTokenProvider =
+ new SecurityTokenProvider<OutboundSecurityToken>() {
+
+ @Override
+ public OutboundSecurityToken getSecurityToken() throws XMLSecurityException {
+ return encryptedKeySecurityToken;
+ }
+
+ @Override
+ public String getId() {
+ return ekId;
+ }
+ };
+
+ final OutboundSecurityContextImpl outboundSecurityContext = new OutboundSecurityContextImpl();
+ outboundSecurityContext.putList(SecurityEvent.class, new ArrayList<SecurityEvent>());
+
+ // Save Token on the security context
+ outboundSecurityContext.registerSecurityTokenProvider(encryptedKeySecurityTokenProvider.getId(), encryptedKeySecurityTokenProvider);
+ outboundSecurityContext.put(WSSConstants.PROP_USE_THIS_TOKEN_ID_FOR_ENCRYPTION, encryptedKeySecurityTokenProvider.getId());
+
+ InputStream sourceDocument = this.getClass().getClassLoader().getResourceAsStream("testdata/plain-soap-1.1.xml");
+
+ baos = new ByteArrayOutputStream();
+ XMLStreamWriter xmlStreamWriter =
+ wsSecOut.processOutMessage(baos, "UTF-8", outboundSecurityContext);
+ XMLStreamReader xmlStreamReader = xmlInputFactory.createXMLStreamReader(sourceDocument);
+ XmlReaderToWriter.writeAll(xmlStreamReader, xmlStreamWriter);
+ xmlStreamWriter.close();
+
+ documentBuilderFactory.newDocumentBuilder().parse(new ByteArrayInputStream(baos.toByteArray()));
+ }
+
+ //done encryption; now test decryption:
+ {
+ String action = WSHandlerConstants.ENCRYPT + " " + WSHandlerConstants.TIMESTAMP;
+ doInboundSecurityWithWSS4J(documentBuilderFactory.newDocumentBuilder().parse(new ByteArrayInputStream(baos.toByteArray())), action);
+ }
+ }
+
+ @Test
+ public void testSignatureEncryptionSymmetricOutbound() throws Exception {
+
+ ByteArrayOutputStream baos;
+ {
+ WSSSecurityProperties securityProperties = new WSSSecurityProperties();
+ WSSConstants.Action[] actions =
+ new WSSConstants.Action[]{WSSConstants.SIGNATURE, WSSConstants.ENCRYPT, WSSConstants.TIMESTAMP};
+ securityProperties.setOutAction(actions);
+ securityProperties.loadEncryptionKeystore(this.getClass().getClassLoader().getResource("transmitter.jks"), "default".toCharArray());
+ securityProperties.setEncryptionUser("receiver");
+
+ securityProperties.loadSignatureKeyStore(this.getClass().getClassLoader().getResource("transmitter.jks"), "default".toCharArray());
+ securityProperties.setSignatureUser("transmitter");
+ securityProperties.setCallbackHandler(new CallbackHandlerImpl());
+
+ securityProperties.setSignatureAlgorithm(WSSConstants.NS_XMLDSIG_HMACSHA1);
+ securityProperties.setSignatureKeyIdentifier(
+ WSSecurityTokenConstants.KeyIdentifier_EncryptedKey
+ );
+
+ securityProperties.addSignaturePart(
+ new SecurePart(new QName(WSSConstants.NS_WSU10, "Timestamp"), SecurePart.Modifier.Element)
+ );
+ securityProperties.addSignaturePart(
+ new SecurePart(new QName(WSSConstants.NS_SOAP11, "Body"), SecurePart.Modifier.Element)
+ );
+
+ OutboundWSSec wsSecOut = WSSec.getOutboundWSSec(securityProperties);
+
+ // Symmetric Key
+ String keyAlgorithm =
+ JCEAlgorithmMapper.getJCEKeyAlgorithmFromURI(WSSConstants.NS_XENC_AES128);
+ KeyGenerator keyGen;
+ try {
+ keyGen = KeyGenerator.getInstance(keyAlgorithm);
+ } catch (NoSuchAlgorithmException e) {
+ throw new WSSecurityException(WSSecurityException.ErrorCode.FAILURE, e);
+ }
+ int keyLength = JCEAlgorithmMapper.getKeyLengthFromURI(WSSConstants.NS_XENC_AES128);
+ keyGen.init(keyLength);
+
+ final Key symmetricKey = keyGen.generateKey();
+
+ final String ekId = IDGenerator.generateID(null);
+
+ final GenericOutboundSecurityToken encryptedKeySecurityToken =
+ new GenericOutboundSecurityToken(ekId, WSSecurityTokenConstants.EncryptedKeyToken, symmetricKey);
+
+ final SecurityTokenProvider<OutboundSecurityToken> encryptedKeySecurityTokenProvider =
+ new SecurityTokenProvider<OutboundSecurityToken>() {
+
+ @Override
+ public OutboundSecurityToken getSecurityToken() throws XMLSecurityException {
+ return encryptedKeySecurityToken;
+ }
+
+ @Override
+ public String getId() {
+ return ekId;
+ }
+ };
+
+ final OutboundSecurityContextImpl outboundSecurityContext = new OutboundSecurityContextImpl();
+ outboundSecurityContext.putList(SecurityEvent.class, new ArrayList<SecurityEvent>());
+
+ // Save Token on the security context
+ outboundSecurityContext.registerSecurityTokenProvider(encryptedKeySecurityTokenProvider.getId(), encryptedKeySecurityTokenProvider);
+ outboundSecurityContext.put(WSSConstants.PROP_USE_THIS_TOKEN_ID_FOR_ENCRYPTION, encryptedKeySecurityTokenProvider.getId());
+ outboundSecurityContext.put(WSSConstants.PROP_USE_THIS_TOKEN_ID_FOR_SIGNATURE, encryptedKeySecurityTokenProvider.getId());
+
+ InputStream sourceDocument = this.getClass().getClassLoader().getResourceAsStream("testdata/plain-soap-1.1.xml");
+
+ baos = new ByteArrayOutputStream();
+ XMLStreamWriter xmlStreamWriter =
+ wsSecOut.processOutMessage(baos, "UTF-8", outboundSecurityContext);
+ XMLStreamReader xmlStreamReader = xmlInputFactory.createXMLStreamReader(sourceDocument);
+ XmlReaderToWriter.writeAll(xmlStreamReader, xmlStreamWriter);
+ xmlStreamWriter.close();
+
+ documentBuilderFactory.newDocumentBuilder().parse(new ByteArrayInputStream(baos.toByteArray()));
+ }
+
+ //done encryption; now test decryption:
+ {
+ String action = WSHandlerConstants.SIGNATURE + " " + WSHandlerConstants.ENCRYPT + " " + WSHandlerConstants.TIMESTAMP;
+ doInboundSecurityWithWSS4J(documentBuilderFactory.newDocumentBuilder().parse(new ByteArrayInputStream(baos.toByteArray())), action);
+ }
+ }
+
+}