View Javadoc
1   /**
2    * Licensed to the Apache Software Foundation (ASF) under one
3    * or more contributor license agreements. See the NOTICE file
4    * distributed with this work for additional information
5    * regarding copyright ownership. The ASF licenses this file
6    * to you under the Apache License, Version 2.0 (the
7    * "License"); you may not use this file except in compliance
8    * with the License. You may obtain a copy of the License at
9    *
10   * http://www.apache.org/licenses/LICENSE-2.0
11   *
12   * Unless required by applicable law or agreed to in writing,
13   * software distributed under the License is distributed on an
14   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15   * KIND, either express or implied. See the License for the
16   * specific language governing permissions and limitations
17   * under the License.
18   */
19  package org.apache.wss4j.policy.stax.assertionStates;
20  
21  import org.apache.wss4j.policy.AssertionState;
22  import org.apache.wss4j.policy.SPConstants;
23  import org.apache.wss4j.common.WSSPolicyException;
24  import org.apache.wss4j.policy.model.*;
25  import org.apache.wss4j.policy.stax.Assertable;
26  import org.apache.wss4j.policy.stax.DummyPolicyAsserter;
27  import org.apache.wss4j.policy.stax.PolicyAsserter;
28  import org.apache.wss4j.stax.securityToken.WSSecurityTokenConstants;
29  import org.apache.xml.security.exceptions.XMLSecurityException;
30  import org.apache.xml.security.stax.securityEvent.SecurityEvent;
31  import org.apache.xml.security.stax.securityEvent.TokenSecurityEvent;
32  import org.apache.xml.security.stax.securityToken.InboundSecurityToken;
33  import org.apache.xml.security.stax.securityToken.SecurityToken;
34  
35  import java.util.Iterator;
36  import java.util.List;
37  
38  import javax.xml.namespace.QName;
39  
40  /**
41   * WSP1.3, 5 Token Assertions
42   */
43  public abstract class TokenAssertionState extends AssertionState implements Assertable {
44  
45      //todo WSP1.3, 5.2.1 Token Issuer: <sp:Issuer>wsa:EndpointReferenceType</sp:Issuer>
46      //todo? WSP1.3 5.2.3 Required Claims
47      //todo derived keys?
48  
49      private boolean initiator;
50      private PolicyAsserter policyAsserter;
51  
52      public TokenAssertionState(AbstractSecurityAssertion assertion, boolean asserted, boolean initiator) {
53          this(assertion, asserted, null, initiator);
54      }
55  
56      public TokenAssertionState(AbstractSecurityAssertion assertion, boolean asserted,
57                                 PolicyAsserter policyAsserter, boolean initiator) {
58          super(assertion, asserted);
59          this.initiator = initiator;
60  
61          this.policyAsserter = policyAsserter;
62          if (this.policyAsserter == null) {
63              this.policyAsserter = new DummyPolicyAsserter();
64          }
65  
66          if (asserted) {
67              AbstractToken token = (AbstractToken)getAssertion();
68              getPolicyAsserter().assertPolicy(token);
69              if (token.getDerivedKeys() != null) {
70                  AbstractToken.DerivedKeys derivedKeys = token.getDerivedKeys();
71                  String namespace = token.getName().getNamespaceURI();
72                  getPolicyAsserter().assertPolicy(new QName(namespace, derivedKeys.name()));
73              }
74          }
75      }
76  
77      @Override
78      public boolean assertEvent(SecurityEvent securityEvent) throws WSSPolicyException, XMLSecurityException {
79  
80          if (isAsserted()) {
81              //just return true when this token assertion is already fulfilled.
82              return true;
83          }
84  
85          @SuppressWarnings("unchecked")
86          TokenSecurityEvent<SecurityToken> tokenSecurityEvent = (TokenSecurityEvent<SecurityToken>) securityEvent;
87          AbstractToken abstractToken = (AbstractToken) getAssertion();
88          final AbstractSecurityAssertion parentAssertion = abstractToken.getParentAssertion();
89  
90          int ignoreToken = 0;
91          final List<WSSecurityTokenConstants.TokenUsage> tokenUsages = tokenSecurityEvent.getSecurityToken().getTokenUsages();
92          Iterator<WSSecurityTokenConstants.TokenUsage> tokenUsageIterator = tokenUsages.iterator();
93          loop:
94          while (tokenUsageIterator.hasNext()) {
95              WSSecurityTokenConstants.TokenUsage tokenUsage = tokenUsageIterator.next();
96              if (WSSecurityTokenConstants.TOKENUSAGE_MAIN_SIGNATURE.equals(tokenUsage)) {
97                  if (initiator && !(parentAssertion instanceof RecipientToken)
98                          && !(parentAssertion instanceof RecipientSignatureToken)
99                          && !(parentAssertion instanceof SignatureToken)
100                         && !(parentAssertion instanceof ProtectionToken)
101                         && !(parentAssertion instanceof TransportToken)) {
102                     ignoreToken++;
103                     continue loop;
104                 } else if (!initiator && !(parentAssertion instanceof InitiatorToken)
105                         && !(parentAssertion instanceof InitiatorSignatureToken)
106                         && !(parentAssertion instanceof SignatureToken)
107                         && !(parentAssertion instanceof ProtectionToken)
108                         && !(parentAssertion instanceof TransportToken)) {
109                     ignoreToken++;
110                     continue loop;
111                 }
112             } else if (WSSecurityTokenConstants.TokenUsage_Signature.equals(tokenUsage)) {
113                 throw new WSSPolicyException("Illegal token usage!");
114             } else if (WSSecurityTokenConstants.TOKENUSAGE_MAIN_ENCRYPTION.equals(tokenUsage)) {
115                 if (initiator && !(parentAssertion instanceof InitiatorToken)
116                         && !(parentAssertion instanceof InitiatorEncryptionToken)
117                         && !(parentAssertion instanceof EncryptionToken)
118                         && !(parentAssertion instanceof ProtectionToken)
119                         && !(parentAssertion instanceof TransportToken)) {
120                     ignoreToken++;
121                     continue loop;
122                 } else if (!initiator && !(parentAssertion instanceof RecipientToken)
123                         && !(parentAssertion instanceof RecipientEncryptionToken)
124                         && !(parentAssertion instanceof EncryptionToken)
125                         && !(parentAssertion instanceof ProtectionToken)
126                         && !(parentAssertion instanceof TransportToken)) {
127                     ignoreToken++;
128                     continue loop;
129                 }
130             } else if (WSSecurityTokenConstants.TokenUsage_Encryption.equals(tokenUsage)) {
131                 throw new WSSPolicyException("Illegal token usage!");
132             } else if (WSSecurityTokenConstants.TOKENUSAGE_SUPPORTING_TOKENS.equals(tokenUsage)
133                 || WSSecurityTokenConstants.TOKENUSAGE_SIGNED_SUPPORTING_TOKENS.equals(tokenUsage)
134                 || WSSecurityTokenConstants.TOKENUSAGE_ENDORSING_SUPPORTING_TOKENS.equals(tokenUsage)
135                 || WSSecurityTokenConstants.TOKENUSAGE_SIGNED_ENDORSING_SUPPORTING_TOKENS.equals(tokenUsage)
136                 || WSSecurityTokenConstants.TOKENUSAGE_SIGNED_ENCRYPTED_SUPPORTING_TOKENS.equals(tokenUsage)
137                 || WSSecurityTokenConstants.TOKENUSAGE_ENCRYPTED_SUPPORTING_TOKENS.equals(tokenUsage)
138                 || WSSecurityTokenConstants.TOKENUSAGE_ENDORSING_ENCRYPTED_SUPPORTING_TOKENS.equals(tokenUsage)
139                 || WSSecurityTokenConstants.TOKENUSAGE_SIGNED_ENDORSING_ENCRYPTED_SUPPORTING_TOKENS.equals(tokenUsage)
140             ) {
141 
142                 if (parentAssertion instanceof TransportToken) {
143                     continue loop;
144                 }
145 
146                 if (!(parentAssertion instanceof SupportingTokens)) {
147                     ignoreToken++;
148                     continue loop;
149                 }
150 
151                 // Allow *SupportingToken policies which are processed as Signed|Encrypted*SupportingTokens
152                 final SupportingTokens supportingTokens = (SupportingTokens) parentAssertion;
153                 final String tokenUsageName = tokenUsage.getName();
154                 final String supportingTokensName = supportingTokens.getName().getLocalPart();
155                 if (!tokenUsageName.equals(supportingTokensName)) {
156                     if (supportingTokensName.contains("Endorsing") && !tokenUsageName.contains("Endorsing")) {
157                         ignoreToken++;
158                         continue loop;
159                     }
160                     if (supportingTokensName.startsWith("Signed") && !tokenUsageName.startsWith("Signed")) {
161                         ignoreToken++;
162                         continue loop;
163                     }
164                     if (supportingTokensName.contains("Encrypted") && !tokenUsageName.contains("Encrypted")) {
165                         ignoreToken++;
166                         continue loop;
167                     }
168                 }
169             }
170         }
171         if (ignoreToken >= tokenUsages.size()) {
172             //token is not for us, so return true to prevent false alarm
173             return true;
174         }
175 
176         boolean asserted = true;
177 
178         //WSP1.3, 5.1 Token Inclusion
179         //todo do we need a global token cache to fullfill ".../IncludeToken/Once" ?
180         SPConstants.IncludeTokenType includeTokenType = abstractToken.getIncludeTokenType();
181         boolean isIncludedInMessage =
182             ((InboundSecurityToken)tokenSecurityEvent.getSecurityToken()).isIncludedInMessage();
183         switch (includeTokenType) {
184             case INCLUDE_TOKEN_NEVER:
185                 if (isIncludedInMessage) {
186                     setErrorMessage("Token must not be included");
187                     asserted = false;
188                 }
189                 break;
190             case INCLUDE_TOKEN_ONCE:
191                 break;
192             case INCLUDE_TOKEN_ALWAYS_TO_RECIPIENT:
193                 if (initiator && isIncludedInMessage) {
194                     setErrorMessage("Token must not be included");
195                     asserted = false;
196                 } else if (!initiator && !isIncludedInMessage) {
197                     setErrorMessage("Token must be included");
198                     asserted = false;
199                 }
200                 break;
201             case INCLUDE_TOKEN_ALWAYS_TO_INITIATOR:
202                 if (initiator && !isIncludedInMessage) {
203                     setErrorMessage("Token must be included");
204                     asserted = false;
205                 } else if (!initiator && isIncludedInMessage) {
206                     setErrorMessage("Token must not be included");
207                     asserted = false;
208                 }
209                 break;
210             case INCLUDE_TOKEN_ALWAYS:
211                 if (!isIncludedInMessage) {
212                     setErrorMessage("Token must be included");
213                     asserted = false;
214                 }
215                 break;
216         }
217 
218         //WSP1.3, 5.3 Token Properties
219         boolean hasDerivedKeys = false;
220         hasDerivedKeys = hasDerivedKeys(tokenSecurityEvent.getSecurityToken());
221         String namespace = getAssertion().getName().getNamespaceURI();
222         if (abstractToken.getDerivedKeys() != null) {
223             AbstractToken.DerivedKeys derivedKeys = abstractToken.getDerivedKeys();
224             switch (derivedKeys) {
225                 case RequireDerivedKeys:
226                 case RequireExplicitDerivedKeys:
227                 case RequireImpliedDerivedKeys:
228                     if (!hasDerivedKeys) {
229                         setErrorMessage("Derived key must be used");
230                         getPolicyAsserter().unassertPolicy(new QName(namespace, derivedKeys.name()),
231                                                          "Derived key must be used");
232                         asserted = false;
233                     } else {
234                         getPolicyAsserter().assertPolicy(new QName(namespace, derivedKeys.name()));
235                     }
236                     break;
237             }
238         } else {
239             if (hasDerivedKeys) {
240                 setErrorMessage("Derived key must not be used");
241                 asserted = false;
242             }
243         }
244 
245         asserted &= assertToken(tokenSecurityEvent, abstractToken);
246         if (asserted) {
247             setAsserted(true);
248         }
249         //return false if not asserted for the main signature and encryption tokens
250         //always return true for supporting tokens.
251         return !(!asserted && (tokenUsages.contains(WSSecurityTokenConstants.TOKENUSAGE_MAIN_SIGNATURE)
252                 || tokenUsages.contains(WSSecurityTokenConstants.TOKENUSAGE_MAIN_ENCRYPTION)));
253     }
254 
255     public abstract boolean assertToken(TokenSecurityEvent<? extends SecurityToken> tokenSecurityEvent,
256                                         AbstractToken abstractToken)
257         throws WSSPolicyException, XMLSecurityException;
258 
259     protected boolean hasDerivedKeys(SecurityToken securityToken) throws XMLSecurityException {
260         if (securityToken == null) {
261             return false;
262         } else if (WSSecurityTokenConstants.DerivedKeyToken.equals(securityToken.getTokenType())) {
263             return true;
264         }
265 
266         if (securityToken.getWrappedTokens().isEmpty()) {
267             return false;
268         }
269 
270         //all wrapped tokens must be derived!:
271         boolean hasDerivedKeys = true;
272         for (int i = 0; i < securityToken.getWrappedTokens().size(); i++) {
273             SecurityToken wrappedSecurityToken = securityToken.getWrappedTokens().get(i);
274             hasDerivedKeys &= hasDerivedKeys(wrappedSecurityToken);
275         }
276         return hasDerivedKeys;
277     }
278 
279     protected PolicyAsserter getPolicyAsserter() {
280         return policyAsserter;
281     }
282 
283     protected boolean isInitiator() {
284         return initiator;
285     }
286 }