org.apache.wss4j.policy.stax.assertionStates.TokenAssertionState Maven / Gradle / Ivy
/**
* 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.policy.stax.assertionStates;
import org.apache.wss4j.policy.AssertionState;
import org.apache.wss4j.policy.SPConstants;
import org.apache.wss4j.common.WSSPolicyException;
import org.apache.wss4j.policy.model.*;
import org.apache.wss4j.policy.stax.Assertable;
import org.apache.wss4j.policy.stax.DummyPolicyAsserter;
import org.apache.wss4j.policy.stax.PolicyAsserter;
import org.apache.wss4j.stax.securityToken.WSSecurityTokenConstants;
import org.apache.xml.security.exceptions.XMLSecurityException;
import org.apache.xml.security.stax.securityEvent.SecurityEvent;
import org.apache.xml.security.stax.securityEvent.TokenSecurityEvent;
import org.apache.xml.security.stax.securityToken.InboundSecurityToken;
import org.apache.xml.security.stax.securityToken.SecurityToken;
import java.util.Iterator;
import java.util.List;
import javax.xml.namespace.QName;
/**
* WSP1.3, 5 Token Assertions
*/
public abstract class TokenAssertionState extends AssertionState implements Assertable {
//todo WSP1.3, 5.2.1 Token Issuer: wsa:EndpointReferenceType
//todo? WSP1.3 5.2.3 Required Claims
//todo derived keys?
private boolean initiator;
private PolicyAsserter policyAsserter;
public TokenAssertionState(AbstractSecurityAssertion assertion, boolean asserted, boolean initiator) {
this(assertion, asserted, null, initiator);
}
public TokenAssertionState(AbstractSecurityAssertion assertion, boolean asserted,
PolicyAsserter policyAsserter, boolean initiator) {
super(assertion, asserted);
this.initiator = initiator;
this.policyAsserter = policyAsserter;
if (this.policyAsserter == null) {
this.policyAsserter = new DummyPolicyAsserter();
}
if (asserted) {
AbstractToken token = (AbstractToken)getAssertion();
getPolicyAsserter().assertPolicy(token);
if (token.getDerivedKeys() != null) {
AbstractToken.DerivedKeys derivedKeys = token.getDerivedKeys();
String namespace = token.getName().getNamespaceURI();
getPolicyAsserter().assertPolicy(new QName(namespace, derivedKeys.name()));
}
}
}
@Override
public boolean assertEvent(SecurityEvent securityEvent) throws WSSPolicyException, XMLSecurityException {
if (isAsserted()) {
//just return true when this token assertion is already fulfilled.
return true;
}
@SuppressWarnings("unchecked")
TokenSecurityEvent tokenSecurityEvent = (TokenSecurityEvent) securityEvent;
AbstractToken abstractToken = (AbstractToken) getAssertion();
final AbstractSecurityAssertion parentAssertion = abstractToken.getParentAssertion();
int ignoreToken = 0;
final List tokenUsages = tokenSecurityEvent.getSecurityToken().getTokenUsages();
Iterator tokenUsageIterator = tokenUsages.iterator();
loop:
while (tokenUsageIterator.hasNext()) {
WSSecurityTokenConstants.TokenUsage tokenUsage = tokenUsageIterator.next();
if (WSSecurityTokenConstants.TOKENUSAGE_MAIN_SIGNATURE.equals(tokenUsage)) {
if (initiator && !(parentAssertion instanceof RecipientToken)
&& !(parentAssertion instanceof RecipientSignatureToken)
&& !(parentAssertion instanceof SignatureToken)
&& !(parentAssertion instanceof ProtectionToken)
&& !(parentAssertion instanceof TransportToken)) {
ignoreToken++;
continue loop;
} else if (!initiator && !(parentAssertion instanceof InitiatorToken)
&& !(parentAssertion instanceof InitiatorSignatureToken)
&& !(parentAssertion instanceof SignatureToken)
&& !(parentAssertion instanceof ProtectionToken)
&& !(parentAssertion instanceof TransportToken)) {
ignoreToken++;
continue loop;
}
} else if (WSSecurityTokenConstants.TokenUsage_Signature.equals(tokenUsage)) {
throw new WSSPolicyException("Illegal token usage!");
} else if (WSSecurityTokenConstants.TOKENUSAGE_MAIN_ENCRYPTION.equals(tokenUsage)) {
if (initiator && !(parentAssertion instanceof InitiatorToken)
&& !(parentAssertion instanceof InitiatorEncryptionToken)
&& !(parentAssertion instanceof EncryptionToken)
&& !(parentAssertion instanceof ProtectionToken)
&& !(parentAssertion instanceof TransportToken)) {
ignoreToken++;
continue loop;
} else if (!initiator && !(parentAssertion instanceof RecipientToken)
&& !(parentAssertion instanceof RecipientEncryptionToken)
&& !(parentAssertion instanceof EncryptionToken)
&& !(parentAssertion instanceof ProtectionToken)
&& !(parentAssertion instanceof TransportToken)) {
ignoreToken++;
continue loop;
}
} else if (WSSecurityTokenConstants.TokenUsage_Encryption.equals(tokenUsage)) {
throw new WSSPolicyException("Illegal token usage!");
} else if (WSSecurityTokenConstants.TOKENUSAGE_SUPPORTING_TOKENS.equals(tokenUsage)
|| WSSecurityTokenConstants.TOKENUSAGE_SIGNED_SUPPORTING_TOKENS.equals(tokenUsage)
|| WSSecurityTokenConstants.TOKENUSAGE_ENDORSING_SUPPORTING_TOKENS.equals(tokenUsage)
|| WSSecurityTokenConstants.TOKENUSAGE_SIGNED_ENDORSING_SUPPORTING_TOKENS.equals(tokenUsage)
|| WSSecurityTokenConstants.TOKENUSAGE_SIGNED_ENCRYPTED_SUPPORTING_TOKENS.equals(tokenUsage)
|| WSSecurityTokenConstants.TOKENUSAGE_ENCRYPTED_SUPPORTING_TOKENS.equals(tokenUsage)
|| WSSecurityTokenConstants.TOKENUSAGE_ENDORSING_ENCRYPTED_SUPPORTING_TOKENS.equals(tokenUsage)
|| WSSecurityTokenConstants.TOKENUSAGE_SIGNED_ENDORSING_ENCRYPTED_SUPPORTING_TOKENS.equals(tokenUsage)
) {
if (parentAssertion instanceof TransportToken) {
continue loop;
}
if (!(parentAssertion instanceof SupportingTokens)) {
ignoreToken++;
continue loop;
}
// Allow *SupportingToken policies which are processed as Signed|Encrypted*SupportingTokens
final SupportingTokens supportingTokens = (SupportingTokens) parentAssertion;
final String tokenUsageName = tokenUsage.getName();
final String supportingTokensName = supportingTokens.getName().getLocalPart();
if (!tokenUsageName.equals(supportingTokensName)) {
if (supportingTokensName.contains("Endorsing") && !tokenUsageName.contains("Endorsing")) {
ignoreToken++;
continue loop;
}
if (supportingTokensName.startsWith("Signed") && !tokenUsageName.startsWith("Signed")) {
ignoreToken++;
continue loop;
}
if (supportingTokensName.contains("Encrypted") && !tokenUsageName.contains("Encrypted")) {
ignoreToken++;
continue loop;
}
}
}
}
if (ignoreToken >= tokenUsages.size()) {
//token is not for us, so return true to prevent false alarm
return true;
}
boolean asserted = true;
//WSP1.3, 5.1 Token Inclusion
//todo do we need a global token cache to fullfill ".../IncludeToken/Once" ?
SPConstants.IncludeTokenType includeTokenType = abstractToken.getIncludeTokenType();
boolean isIncludedInMessage =
((InboundSecurityToken)tokenSecurityEvent.getSecurityToken()).isIncludedInMessage();
switch (includeTokenType) {
case INCLUDE_TOKEN_NEVER:
if (isIncludedInMessage) {
setErrorMessage("Token must not be included");
asserted = false;
}
break;
case INCLUDE_TOKEN_ONCE:
break;
case INCLUDE_TOKEN_ALWAYS_TO_RECIPIENT:
if (initiator && isIncludedInMessage) {
setErrorMessage("Token must not be included");
asserted = false;
} else if (!initiator && !isIncludedInMessage) {
setErrorMessage("Token must be included");
asserted = false;
}
break;
case INCLUDE_TOKEN_ALWAYS_TO_INITIATOR:
if (initiator && !isIncludedInMessage) {
setErrorMessage("Token must be included");
asserted = false;
} else if (!initiator && isIncludedInMessage) {
setErrorMessage("Token must not be included");
asserted = false;
}
break;
case INCLUDE_TOKEN_ALWAYS:
if (!isIncludedInMessage) {
setErrorMessage("Token must be included");
asserted = false;
}
break;
}
//WSP1.3, 5.3 Token Properties
boolean hasDerivedKeys = false;
hasDerivedKeys = hasDerivedKeys(tokenSecurityEvent.getSecurityToken());
String namespace = getAssertion().getName().getNamespaceURI();
if (abstractToken.getDerivedKeys() != null) {
AbstractToken.DerivedKeys derivedKeys = abstractToken.getDerivedKeys();
switch (derivedKeys) {
case RequireDerivedKeys:
case RequireExplicitDerivedKeys:
case RequireImpliedDerivedKeys:
if (!hasDerivedKeys) {
setErrorMessage("Derived key must be used");
getPolicyAsserter().unassertPolicy(new QName(namespace, derivedKeys.name()),
"Derived key must be used");
asserted = false;
} else {
getPolicyAsserter().assertPolicy(new QName(namespace, derivedKeys.name()));
}
break;
}
} else {
if (hasDerivedKeys) {
setErrorMessage("Derived key must not be used");
asserted = false;
}
}
asserted &= assertToken(tokenSecurityEvent, abstractToken);
if (asserted) {
setAsserted(true);
}
if (!asserted && (tokenUsages.contains(WSSecurityTokenConstants.TOKENUSAGE_MAIN_SIGNATURE)
|| tokenUsages.contains(WSSecurityTokenConstants.TOKENUSAGE_MAIN_ENCRYPTION))) {
//return false if not asserted for the main signature and encryption tokens
return false;
} else {
//always return true for supporting tokens.
return true;
}
}
public abstract boolean assertToken(TokenSecurityEvent extends SecurityToken> tokenSecurityEvent,
AbstractToken abstractToken)
throws WSSPolicyException, XMLSecurityException;
protected boolean hasDerivedKeys(SecurityToken securityToken) throws XMLSecurityException {
if (securityToken == null) {
return false;
} else if (WSSecurityTokenConstants.DerivedKeyToken.equals(securityToken.getTokenType())) {
return true;
}
if (securityToken.getWrappedTokens().isEmpty()) {
return false;
}
//all wrapped tokens must be derived!:
boolean hasDerivedKeys = true;
for (int i = 0; i < securityToken.getWrappedTokens().size(); i++) {
SecurityToken wrappedSecurityToken = securityToken.getWrappedTokens().get(i);
hasDerivedKeys &= hasDerivedKeys(wrappedSecurityToken);
}
return hasDerivedKeys;
}
protected PolicyAsserter getPolicyAsserter() {
return policyAsserter;
}
protected boolean isInitiator() {
return initiator;
}
}