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.stax.impl;
20  
21  import java.util.ArrayDeque;
22  import java.util.ArrayList;
23  import java.util.Collections;
24  import java.util.Deque;
25  import java.util.Iterator;
26  import java.util.List;
27  
28  import javax.xml.namespace.QName;
29  
30  import org.apache.wss4j.common.bsp.BSPRule;
31  import org.apache.wss4j.common.ext.WSSecurityException;
32  import org.apache.wss4j.stax.ext.WSInboundSecurityContext;
33  import org.apache.wss4j.stax.ext.WSSConstants;
34  import org.apache.wss4j.stax.securityEvent.HttpsTokenSecurityEvent;
35  import org.apache.wss4j.stax.securityEvent.WSSecurityEventConstants;
36  import org.apache.wss4j.stax.securityToken.WSSecurityTokenConstants;
37  import org.apache.wss4j.stax.utils.WSSUtils;
38  import org.apache.xml.security.exceptions.XMLSecurityException;
39  import org.apache.xml.security.stax.impl.InboundSecurityContextImpl;
40  import org.apache.xml.security.stax.securityEvent.AlgorithmSuiteSecurityEvent;
41  import org.apache.xml.security.stax.securityEvent.ContentEncryptedElementSecurityEvent;
42  import org.apache.xml.security.stax.securityEvent.EncryptedElementSecurityEvent;
43  import org.apache.xml.security.stax.securityEvent.SecurityEvent;
44  import org.apache.xml.security.stax.securityEvent.SecurityEventConstants;
45  import org.apache.xml.security.stax.securityEvent.SignedElementSecurityEvent;
46  import org.apache.xml.security.stax.securityEvent.TokenSecurityEvent;
47  import org.apache.xml.security.stax.securityToken.InboundSecurityToken;
48  import org.apache.xml.security.stax.securityToken.SecurityToken;
49  import org.apache.xml.security.stax.securityToken.SecurityTokenConstants;
50  
51  /**
52   * Concrete security context implementation
53   */
54  public class InboundWSSecurityContextImpl extends InboundSecurityContextImpl implements WSInboundSecurityContext {
55  
56      private static final org.slf4j.Logger LOG =
57              org.slf4j.LoggerFactory.getLogger(InboundWSSecurityContextImpl.class);
58  
59      private final Deque<SecurityEvent> securityEventQueue = new ArrayDeque<>();
60      private boolean operationSecurityEventOccured = false;
61      private boolean messageEncryptionTokenOccured = false;
62      private boolean allowRSA15KeyTransportAlgorithm = false;
63      private boolean disableBSPEnforcement;
64      private boolean soap12;
65  
66      private List<BSPRule> ignoredBSPRules = Collections.emptyList();
67  
68      @Override
69      public synchronized void registerSecurityEvent(SecurityEvent securityEvent) throws XMLSecurityException {
70  
71          if (WSSecurityEventConstants.AlgorithmSuite.equals(securityEvent.getSecurityEventType())) {
72              //do not cache AlgorithmSuite securityEvents and forward them directly to allow
73              //the user to check them before they are used internally.
74              forwardSecurityEvent(securityEvent);
75              return;
76          }
77  
78          if (operationSecurityEventOccured) {
79              if (!this.messageEncryptionTokenOccured
80                      && securityEvent instanceof TokenSecurityEvent) {
81                  @SuppressWarnings("unchecked")
82                  TokenSecurityEvent<? extends InboundSecurityToken> tokenSecurityEvent =
83                          (TokenSecurityEvent<? extends InboundSecurityToken>) securityEvent;
84  
85                  if (tokenSecurityEvent.getSecurityToken().getTokenUsages().contains(WSSecurityTokenConstants.TokenUsage_Encryption)) {
86                      InboundSecurityToken securityToken = WSSUtils.getRootToken(tokenSecurityEvent.getSecurityToken());
87  
88                      TokenSecurityEvent<? extends InboundSecurityToken> newTokenSecurityEvent =
89                              WSSUtils.createTokenSecurityEvent(securityToken, tokenSecurityEvent.getCorrelationID());
90                      setTokenUsage(newTokenSecurityEvent, WSSecurityTokenConstants.TOKENUSAGE_MAIN_ENCRYPTION);
91                      securityEvent = newTokenSecurityEvent;
92                      this.messageEncryptionTokenOccured = true;
93                  }
94              }
95  
96              forwardSecurityEvent(securityEvent);
97              return;
98          }
99  
100         if (WSSecurityEventConstants.OPERATION.equals(securityEvent.getSecurityEventType())) {
101             operationSecurityEventOccured = true;
102 
103             identifySecurityTokenDependenciesAndUsage(securityEventQueue);
104 
105             Iterator<SecurityEvent> securityEventIterator = securityEventQueue.descendingIterator();
106             while (securityEventIterator.hasNext()) {
107                 SecurityEvent prevSecurityEvent = securityEventIterator.next();
108                 forwardSecurityEvent(prevSecurityEvent);
109             }
110             //forward operation security event
111             forwardSecurityEvent(securityEvent);
112 
113             securityEventQueue.clear();
114             return;
115         }
116 
117         securityEventQueue.push(securityEvent);
118     }
119 
120     @Override
121     protected void forwardSecurityEvent(SecurityEvent securityEvent) throws XMLSecurityException {
122 
123         if (!allowRSA15KeyTransportAlgorithm && SecurityEventConstants.AlgorithmSuite.equals(securityEvent.getSecurityEventType())) {
124             AlgorithmSuiteSecurityEvent algorithmSuiteSecurityEvent = (AlgorithmSuiteSecurityEvent)securityEvent;
125             Boolean allowRSA15 = get(WSSConstants.PROP_ALLOW_RSA15_KEYTRANSPORT_ALGORITHM);
126             if ((allowRSA15 == null || !allowRSA15)
127                 && WSSConstants.NS_XENC_RSA15.equals(algorithmSuiteSecurityEvent.getAlgorithmURI())) {
128                 throw new WSSecurityException(WSSecurityException.ErrorCode.FAILED_CHECK,
129                                               WSSConstants.PROP_ALLOW_RSA15_KEYTRANSPORT_ALGORITHM);
130             }
131         }
132 
133         try {
134             super.forwardSecurityEvent(securityEvent);
135         } catch (WSSecurityException e) {
136             throw e;
137         } catch (XMLSecurityException e) {
138             throw new WSSecurityException(WSSecurityException.ErrorCode.FAILED_CHECK, e);
139         }
140     }
141 
142     private void identifySecurityTokenDependenciesAndUsage(
143             Deque<SecurityEvent> securityEventDeque) throws XMLSecurityException {
144 
145         MessageTokens messageTokens = new MessageTokens();
146         HttpsTokenSecurityEvent httpsTokenSecurityEvent = null;
147 
148         List<TokenSecurityEvent<? extends InboundSecurityToken>> tokenSecurityEvents = new ArrayList<>();
149         Iterator<SecurityEvent> securityEventIterator = securityEventDeque.iterator();
150         while (securityEventIterator.hasNext()) {
151             SecurityEvent securityEvent = securityEventIterator.next();
152             if (securityEvent instanceof TokenSecurityEvent) {
153                 @SuppressWarnings("unchecked")
154                 TokenSecurityEvent<? extends InboundSecurityToken> tokenSecurityEvent =
155                         (TokenSecurityEvent<? extends InboundSecurityToken>)securityEvent;
156 
157                 if (WSSecurityEventConstants.HTTPS_TOKEN.equals(securityEvent.getSecurityEventType())) {
158                     HttpsTokenSecurityEvent actHttpsTokenSecurityEvent = (HttpsTokenSecurityEvent) tokenSecurityEvent;
159                     actHttpsTokenSecurityEvent.getSecurityToken().getTokenUsages().clear();
160                     actHttpsTokenSecurityEvent.getSecurityToken().addTokenUsage(WSSecurityTokenConstants.TOKENUSAGE_MAIN_SIGNATURE);
161                     messageTokens.messageSignatureTokens =
162                         addTokenSecurityEvent(actHttpsTokenSecurityEvent, messageTokens.messageSignatureTokens);
163                     HttpsTokenSecurityEvent clonedHttpsTokenSecurityEvent = new HttpsTokenSecurityEvent();
164                     clonedHttpsTokenSecurityEvent.setAuthenticationType(actHttpsTokenSecurityEvent.getAuthenticationType());
165                     clonedHttpsTokenSecurityEvent.setIssuerName(actHttpsTokenSecurityEvent.getIssuerName());
166                     clonedHttpsTokenSecurityEvent.setSecurityToken(actHttpsTokenSecurityEvent.getSecurityToken());
167                     clonedHttpsTokenSecurityEvent.getSecurityToken().addTokenUsage(WSSecurityTokenConstants.TOKENUSAGE_MAIN_ENCRYPTION);
168                     messageTokens.messageEncryptionTokens =
169                         addTokenSecurityEvent(actHttpsTokenSecurityEvent, messageTokens.messageEncryptionTokens);
170                     httpsTokenSecurityEvent = clonedHttpsTokenSecurityEvent;
171                     continue;
172                 }
173                 tokenSecurityEvents.add(tokenSecurityEvent);
174             }
175         }
176 
177         //search the root tokens and create new TokenSecurityEvents if not already there...
178         for (int i = 0; i < tokenSecurityEvents.size(); i++) {
179             TokenSecurityEvent<? extends InboundSecurityToken> tokenSecurityEvent = tokenSecurityEvents.get(i);
180             InboundSecurityToken securityToken = WSSUtils.getRootToken(tokenSecurityEvent.getSecurityToken());
181 
182             if (!containsSecurityToken(messageTokens.supportingTokens, securityToken)) {
183                 TokenSecurityEvent<? extends InboundSecurityToken> newTokenSecurityEvent =
184                         WSSUtils.createTokenSecurityEvent(securityToken, tokenSecurityEvent.getCorrelationID());
185                 messageTokens.supportingTokens = addTokenSecurityEvent(newTokenSecurityEvent, messageTokens.supportingTokens);
186                 securityEventDeque.offer(newTokenSecurityEvent);
187             }
188             //remove old TokenSecurityEvent so that only root tokens are in the queue
189             securityEventDeque.remove(tokenSecurityEvent);
190         }
191 
192         parseSupportingTokens(messageTokens, httpsTokenSecurityEvent, securityEventDeque);
193 
194         if (messageTokens.messageSignatureTokens.isEmpty()) {
195             InboundSecurityToken messageSignatureToken = getSupportingTokenSigningToken(messageTokens, securityEventDeque);
196 
197             TokenSecurityEvent<? extends InboundSecurityToken> tokenSecurityEvent =
198                     getTokenSecurityEvent(messageSignatureToken, tokenSecurityEvents);
199             if (tokenSecurityEvent != null) {
200                 removeTokenSecurityEvent(tokenSecurityEvent, messageTokens.supportingTokens);
201                 removeTokenSecurityEvent(tokenSecurityEvent, messageTokens.signedSupportingTokens);
202                 removeTokenSecurityEvent(tokenSecurityEvent, messageTokens.endorsingSupportingTokens);
203                 removeTokenSecurityEvent(tokenSecurityEvent, messageTokens.signedEndorsingSupportingTokens);
204                 removeTokenSecurityEvent(tokenSecurityEvent, messageTokens.signedEncryptedSupportingTokens);
205                 removeTokenSecurityEvent(tokenSecurityEvent, messageTokens.encryptedSupportingTokens);
206                 removeTokenSecurityEvent(tokenSecurityEvent, messageTokens.endorsingEncryptedSupportingTokens);
207                 removeTokenSecurityEvent(tokenSecurityEvent, messageTokens.signedEndorsingEncryptedSupportingTokens);
208                 messageTokens.messageSignatureTokens = addTokenSecurityEvent(tokenSecurityEvent, messageTokens.messageSignatureTokens);
209             }
210         }
211 
212         if (messageTokens.messageSignatureTokens.isEmpty()) {
213             for (Iterator<TokenSecurityEvent<? extends InboundSecurityToken>> iterator =
214                 messageTokens.supportingTokens.iterator(); iterator.hasNext();) {
215                 TokenSecurityEvent<? extends InboundSecurityToken> supportingToken = iterator.next();
216                 if (supportingToken.getSecurityToken().getTokenUsages().contains(WSSecurityTokenConstants.TokenUsage_Signature)) {
217                     iterator.remove();
218                     messageTokens.messageSignatureTokens = addTokenSecurityEvent(supportingToken, messageTokens.messageSignatureTokens);
219                     break;
220                 }
221             }
222         }
223 
224         if (messageTokens.messageEncryptionTokens.isEmpty()) {
225             for (Iterator<TokenSecurityEvent<? extends InboundSecurityToken>> iterator =
226                 messageTokens.supportingTokens.iterator(); iterator.hasNext();) {
227                 TokenSecurityEvent<? extends InboundSecurityToken> supportingToken = iterator.next();
228                 if (supportingToken.getSecurityToken().getTokenUsages().contains(WSSecurityTokenConstants.TokenUsage_Encryption)) {
229                     iterator.remove();
230                     messageTokens.messageEncryptionTokens = addTokenSecurityEvent(supportingToken, messageTokens.messageEncryptionTokens);
231                     break;
232                 }
233             }
234         }
235 
236         if (!messageTokens.messageEncryptionTokens.isEmpty()) {
237             this.messageEncryptionTokenOccured = true;
238         }
239 
240         setTokenUsage(messageTokens.messageSignatureTokens, WSSecurityTokenConstants.TOKENUSAGE_MAIN_SIGNATURE);
241         setTokenUsage(messageTokens.messageEncryptionTokens, WSSecurityTokenConstants.TOKENUSAGE_MAIN_ENCRYPTION);
242         setTokenUsage(messageTokens.supportingTokens, WSSecurityTokenConstants.TOKENUSAGE_SUPPORTING_TOKENS);
243         setTokenUsage(messageTokens.signedSupportingTokens, WSSecurityTokenConstants.TOKENUSAGE_SIGNED_SUPPORTING_TOKENS);
244         setTokenUsage(messageTokens.endorsingSupportingTokens,
245                       WSSecurityTokenConstants.TOKENUSAGE_ENDORSING_SUPPORTING_TOKENS);
246         setTokenUsage(messageTokens.signedEndorsingSupportingTokens,
247                       WSSecurityTokenConstants.TOKENUSAGE_SIGNED_ENDORSING_SUPPORTING_TOKENS);
248         setTokenUsage(messageTokens.signedEncryptedSupportingTokens,
249                       WSSecurityTokenConstants.TOKENUSAGE_SIGNED_ENCRYPTED_SUPPORTING_TOKENS);
250         setTokenUsage(messageTokens.encryptedSupportingTokens,
251                       WSSecurityTokenConstants.TOKENUSAGE_ENCRYPTED_SUPPORTING_TOKENS);
252         setTokenUsage(messageTokens.endorsingEncryptedSupportingTokens,
253                       WSSecurityTokenConstants.TOKENUSAGE_ENDORSING_ENCRYPTED_SUPPORTING_TOKENS);
254         setTokenUsage(messageTokens.signedEndorsingEncryptedSupportingTokens,
255                       WSSecurityTokenConstants.TOKENUSAGE_SIGNED_ENDORSING_ENCRYPTED_SUPPORTING_TOKENS);
256     }
257 
258     private void parseSupportingTokens(MessageTokens messageTokens, HttpsTokenSecurityEvent httpsTokenSecurityEvent,
259                                        Deque<SecurityEvent> securityEventDeque) throws XMLSecurityException {
260         Iterator<TokenSecurityEvent<? extends InboundSecurityToken>> supportingTokensIterator = messageTokens.supportingTokens.iterator();
261         while (supportingTokensIterator.hasNext()) {
262             TokenSecurityEvent<? extends InboundSecurityToken> tokenSecurityEvent = supportingTokensIterator.next();
263             List<InboundSecurityToken> signingSecurityTokens =
264                 isSignedToken(tokenSecurityEvent, securityEventDeque, httpsTokenSecurityEvent);
265 
266             List<QName> securityHeader =
267                 soap12 ? WSSConstants.SOAP_12_WSSE_SECURITY_HEADER_PATH : WSSConstants.SOAP_11_WSSE_SECURITY_HEADER_PATH;
268             List<QName> signatureElementPath = new ArrayList<>(4);
269             signatureElementPath.addAll(securityHeader);
270             signatureElementPath.add(WSSConstants.TAG_dsig_Signature);
271             boolean signsSignature = signsElement(tokenSecurityEvent, signatureElementPath, securityEventDeque);
272             boolean encryptsSignature = encryptsElement(tokenSecurityEvent, signatureElementPath, securityEventDeque);
273 
274             List<QName> signatureConfirmationElementPath = new ArrayList<>(4);
275             signatureConfirmationElementPath.addAll(securityHeader);
276             signatureConfirmationElementPath.add(WSSConstants.TAG_WSSE11_SIG_CONF);
277             boolean signsSignatureConfirmation =
278                 signsElement(tokenSecurityEvent, signatureConfirmationElementPath, securityEventDeque);
279             boolean encryptsSignatureConfirmation =
280                 encryptsElement(tokenSecurityEvent, signatureConfirmationElementPath, securityEventDeque);
281 
282             List<QName> timestampElementPath = new ArrayList<>(4);
283             timestampElementPath.addAll(securityHeader);
284             timestampElementPath.add(WSSConstants.TAG_WSU_TIMESTAMP);
285             boolean signsTimestamp = signsElement(tokenSecurityEvent, timestampElementPath, securityEventDeque);
286 
287             List<QName> usernameTokenElementPath = new ArrayList<>(4);
288             usernameTokenElementPath.addAll(securityHeader);
289             usernameTokenElementPath.add(WSSConstants.TAG_WSSE_USERNAME_TOKEN);
290             boolean encryptsUsernameToken = encryptsElement(tokenSecurityEvent, usernameTokenElementPath, securityEventDeque);
291 
292             boolean transportSecurityActive = Boolean.TRUE.equals(get(WSSConstants.TRANSPORT_SECURITY_ACTIVE));
293 
294             List<InboundSecurityToken> encryptingSecurityTokens =
295                 isEncryptedToken(tokenSecurityEvent, securityEventDeque, httpsTokenSecurityEvent);
296 
297             boolean signatureUsage =
298                 tokenSecurityEvent.getSecurityToken().getTokenUsages().contains(WSSecurityTokenConstants.TokenUsage_Signature);
299             boolean encryptionUsage =
300                 tokenSecurityEvent.getSecurityToken().getTokenUsages().contains(WSSecurityTokenConstants.TokenUsage_Encryption);
301 
302             if (!transportSecurityActive && signsSignatureConfirmation && signsTimestamp && !signsSignature) {
303                 supportingTokensIterator.remove();
304                 messageTokens.messageSignatureTokens =
305                     addTokenSecurityEvent(tokenSecurityEvent, messageTokens.messageSignatureTokens);
306                 if (encryptionUsage) {
307                     messageTokens.messageEncryptionTokens =
308                         addTokenSecurityEvent(tokenSecurityEvent, messageTokens.messageEncryptionTokens);
309                 }
310             } else if (!transportSecurityActive && signsSignatureConfirmation && !signsSignature) {
311                 supportingTokensIterator.remove();
312                 messageTokens.messageSignatureTokens =
313                     addTokenSecurityEvent(tokenSecurityEvent, messageTokens.messageSignatureTokens);
314                 if (encryptionUsage) {
315                     messageTokens.messageEncryptionTokens =
316                         addTokenSecurityEvent(tokenSecurityEvent, messageTokens.messageEncryptionTokens);
317                 }
318             } else if (!transportSecurityActive && signsTimestamp && !signsSignature) {
319                 supportingTokensIterator.remove();
320                 messageTokens.messageSignatureTokens =
321                     addTokenSecurityEvent(tokenSecurityEvent, messageTokens.messageSignatureTokens);
322                 if (encryptionUsage) {
323                     messageTokens.messageEncryptionTokens =
324                         addTokenSecurityEvent(tokenSecurityEvent, messageTokens.messageEncryptionTokens);
325                 }
326             } else if (!transportSecurityActive
327                 && (encryptsSignature || encryptsSignatureConfirmation || encryptsUsernameToken)) {
328                 supportingTokensIterator.remove();
329                 messageTokens.messageEncryptionTokens =
330                     addTokenSecurityEvent(tokenSecurityEvent, messageTokens.messageEncryptionTokens);
331             } else if (signsSignature && !signingSecurityTokens.isEmpty() && !encryptingSecurityTokens.isEmpty()) {
332                 supportingTokensIterator.remove();
333                 messageTokens.signedEndorsingEncryptedSupportingTokens =
334                     addTokenSecurityEvent(tokenSecurityEvent, messageTokens.signedEndorsingEncryptedSupportingTokens);
335             } else if (transportSecurityActive && signsTimestamp && !signingSecurityTokens.isEmpty()
336                 && !encryptingSecurityTokens.isEmpty()) {
337                 supportingTokensIterator.remove();
338                 messageTokens.signedEndorsingEncryptedSupportingTokens =
339                     addTokenSecurityEvent(tokenSecurityEvent, messageTokens.signedEndorsingEncryptedSupportingTokens);
340             } else if (signsSignature && signingSecurityTokens.isEmpty() && !encryptingSecurityTokens.isEmpty()) {
341                 supportingTokensIterator.remove();
342                 messageTokens.endorsingEncryptedSupportingTokens =
343                     addTokenSecurityEvent(tokenSecurityEvent, messageTokens.endorsingEncryptedSupportingTokens);
344             } else if (signsSignature && !signingSecurityTokens.isEmpty()) {
345                 supportingTokensIterator.remove();
346                 messageTokens.signedEndorsingSupportingTokens =
347                     addTokenSecurityEvent(tokenSecurityEvent, messageTokens.signedEndorsingSupportingTokens);
348             } else if (signatureUsage && !signingSecurityTokens.isEmpty()) {
349                 supportingTokensIterator.remove();
350                 messageTokens.signedEndorsingSupportingTokens =
351                     addTokenSecurityEvent(tokenSecurityEvent, messageTokens.signedEndorsingSupportingTokens);
352             } else if (signsSignature) {
353                 supportingTokensIterator.remove();
354                 messageTokens.endorsingSupportingTokens =
355                     addTokenSecurityEvent(tokenSecurityEvent, messageTokens.endorsingSupportingTokens);
356             } else if (!signingSecurityTokens.isEmpty() && !encryptingSecurityTokens.isEmpty()) {
357                 supportingTokensIterator.remove();
358                 messageTokens.signedEncryptedSupportingTokens =
359                     addTokenSecurityEvent(tokenSecurityEvent, messageTokens.signedEncryptedSupportingTokens);
360             } else if (!signingSecurityTokens.isEmpty()) {
361                 supportingTokensIterator.remove();
362                 messageTokens.signedSupportingTokens =
363                     addTokenSecurityEvent(tokenSecurityEvent, messageTokens.signedSupportingTokens);
364             } else if (!encryptingSecurityTokens.isEmpty()) {
365                 supportingTokensIterator.remove();
366                 messageTokens.encryptedSupportingTokens =
367                     addTokenSecurityEvent(tokenSecurityEvent, messageTokens.encryptedSupportingTokens);
368             }
369         }
370     }
371 
372     private void removeTokenSecurityEvent(TokenSecurityEvent<? extends InboundSecurityToken> tokenSecurityEvent,
373                                           List<TokenSecurityEvent<? extends InboundSecurityToken>> tokenSecurityEventList) {
374         for (int i = 0; i < tokenSecurityEventList.size(); i++) {
375             TokenSecurityEvent<? extends InboundSecurityToken> securityEvent = tokenSecurityEventList.get(i);
376             if (securityEvent.getSecurityToken().getId().equals(tokenSecurityEvent.getSecurityToken().getId())) {
377                 tokenSecurityEventList.remove(securityEvent);
378                 return;
379             }
380         }
381     }
382 
383     private List<TokenSecurityEvent<? extends InboundSecurityToken>> addTokenSecurityEvent(
384             TokenSecurityEvent<? extends InboundSecurityToken> tokenSecurityEvent,
385             List<TokenSecurityEvent<? extends InboundSecurityToken>> tokenSecurityEventList) {
386         if (tokenSecurityEventList == Collections.<TokenSecurityEvent<? extends InboundSecurityToken>>emptyList()) {
387             tokenSecurityEventList = new ArrayList<>();
388         }
389         tokenSecurityEventList.add(tokenSecurityEvent);
390         return tokenSecurityEventList;
391     }
392 
393     private boolean containsSecurityToken(List<TokenSecurityEvent<? extends InboundSecurityToken>> supportingTokens,
394                                           SecurityToken securityToken) {
395         if (securityToken != null) {
396             for (int i = 0; i < supportingTokens.size(); i++) {
397                 TokenSecurityEvent<? extends SecurityToken> tokenSecurityEvent = supportingTokens.get(i);
398                 if (tokenSecurityEvent.getSecurityToken().getId().equals(securityToken.getId())) {
399                     return true;
400                 }
401             }
402         }
403         return false;
404     }
405 
406     private TokenSecurityEvent<? extends InboundSecurityToken> getTokenSecurityEvent(
407             InboundSecurityToken securityToken,
408             List<TokenSecurityEvent<? extends InboundSecurityToken>> tokenSecurityEvents) throws XMLSecurityException {
409         if (securityToken != null) {
410             for (int i = 0; i < tokenSecurityEvents.size(); i++) {
411                 TokenSecurityEvent<? extends InboundSecurityToken> tokenSecurityEvent = tokenSecurityEvents.get(i);
412                 if (tokenSecurityEvent.getSecurityToken().getId().equals(securityToken.getId())) {
413                     return tokenSecurityEvent;
414                 }
415             }
416         }
417         return null;
418     }
419 
420     private InboundSecurityToken getSupportingTokenSigningToken(
421             MessageTokens messageTokens,
422             Deque<SecurityEvent> securityEventDeque
423     ) throws XMLSecurityException {
424 
425         //todo we have to check if the signingTokens also cover the other supporting tokens!
426         for (int i = 0; i < messageTokens.signedSupportingTokens.size(); i++) {
427             TokenSecurityEvent<? extends InboundSecurityToken> tokenSecurityEvent = messageTokens.signedSupportingTokens.get(i);
428             List<? extends InboundSecurityToken> signingSecurityTokens = getSigningToken(tokenSecurityEvent, securityEventDeque);
429             if (signingSecurityTokens.size() == 1) {
430                 return signingSecurityTokens.get(0);
431             }
432         }
433         for (int i = 0; i < messageTokens.signedEndorsingSupportingTokens.size(); i++) {
434             TokenSecurityEvent<? extends SecurityToken> tokenSecurityEvent = messageTokens.signedEndorsingSupportingTokens.get(i);
435             List<InboundSecurityToken> signingSecurityTokens = getSigningToken(tokenSecurityEvent, securityEventDeque);
436             if (signingSecurityTokens.size() == 1) {
437                 return signingSecurityTokens.get(0);
438             }
439         }
440         for (int i = 0; i < messageTokens.signedEncryptedSupportingTokens.size(); i++) {
441             TokenSecurityEvent<? extends SecurityToken> tokenSecurityEvent = messageTokens.signedEncryptedSupportingTokens.get(i);
442             List<InboundSecurityToken> signingSecurityTokens = getSigningToken(tokenSecurityEvent, securityEventDeque);
443             if (signingSecurityTokens.size() == 1) {
444                 return signingSecurityTokens.get(0);
445             }
446         }
447         for (int i = 0; i < messageTokens.signedEndorsingEncryptedSupportingTokens.size(); i++) {
448             TokenSecurityEvent<? extends SecurityToken> tokenSecurityEvent = messageTokens.signedEndorsingEncryptedSupportingTokens.get(i);
449             List<InboundSecurityToken> signingSecurityTokens = getSigningToken(tokenSecurityEvent, securityEventDeque);
450             if (signingSecurityTokens.size() == 1) {
451                 return signingSecurityTokens.get(0);
452             }
453         }
454         return null;
455     }
456 
457     private List<InboundSecurityToken> getSigningToken(TokenSecurityEvent<? extends SecurityToken> tokenSecurityEvent,
458                                                        Deque<SecurityEvent> securityEventDeque) throws XMLSecurityException {
459         List<InboundSecurityToken> signingSecurityTokens = new ArrayList<>();
460 
461         for (Iterator<SecurityEvent> iterator = securityEventDeque.iterator(); iterator.hasNext();) {
462             SecurityEvent securityEvent = iterator.next();
463             if (WSSecurityEventConstants.SignedElement.equals(securityEvent.getSecurityEventType())) {
464                 SignedElementSecurityEvent signedElementSecurityEvent = (SignedElementSecurityEvent) securityEvent;
465                 if (signedElementSecurityEvent.isSigned()
466                         && WSSUtils.pathMatches(
467                         signedElementSecurityEvent.getElementPath(),
468                         ((InboundSecurityToken)tokenSecurityEvent.getSecurityToken()).getElementPath(), false)
469                         ) {
470                     signingSecurityTokens.add((InboundSecurityToken)signedElementSecurityEvent.getSecurityToken());
471                 }
472             }
473         }
474         return signingSecurityTokens;
475     }
476 
477     private void setTokenUsage(List<TokenSecurityEvent<? extends InboundSecurityToken>> tokenSecurityEvents,
478                                WSSecurityTokenConstants.TokenUsage tokenUsage) throws XMLSecurityException {
479         for (int i = 0; i < tokenSecurityEvents.size(); i++) {
480             TokenSecurityEvent<? extends InboundSecurityToken> tokenSecurityEvent = tokenSecurityEvents.get(i);
481             setTokenUsage(tokenSecurityEvent, tokenUsage);
482         }
483     }
484 
485     private void setTokenUsage(TokenSecurityEvent<? extends InboundSecurityToken> tokenSecurityEvent,
486                                WSSecurityTokenConstants.TokenUsage tokenUsage) throws XMLSecurityException {
487         tokenSecurityEvent.getSecurityToken().getTokenUsages().remove(WSSecurityTokenConstants.TOKENUSAGE_SUPPORTING_TOKENS);
488         tokenSecurityEvent.getSecurityToken().getTokenUsages().remove(WSSecurityTokenConstants.TokenUsage_Signature);
489         tokenSecurityEvent.getSecurityToken().getTokenUsages().remove(WSSecurityTokenConstants.TokenUsage_Encryption);
490         tokenSecurityEvent.getSecurityToken().addTokenUsage(tokenUsage);
491     }
492 
493     private List<InboundSecurityToken> isSignedToken(TokenSecurityEvent<? extends SecurityToken> tokenSecurityEvent,
494                                               Deque<SecurityEvent> securityEventDeque,
495                                               HttpsTokenSecurityEvent httpsTokenSecurityEvent) throws XMLSecurityException {
496         List<InboundSecurityToken> securityTokenList = new ArrayList<>();
497         if (httpsTokenSecurityEvent != null) {
498             securityTokenList.add(httpsTokenSecurityEvent.getSecurityToken());
499             return securityTokenList;
500         }
501         for (Iterator<SecurityEvent> iterator = securityEventDeque.iterator(); iterator.hasNext();) {
502             SecurityEvent securityEvent = iterator.next();
503             if (WSSecurityEventConstants.SignedElement.equals(securityEvent.getSecurityEventType())) {
504                 SignedElementSecurityEvent signedElementSecurityEvent = (SignedElementSecurityEvent) securityEvent;
505                 if (signedElementSecurityEvent.isSigned()
506                         && tokenSecurityEvent.getSecurityToken() != null
507                         && signedElementSecurityEvent.getXmlSecEvent() != null
508                         && signedElementSecurityEvent.getXmlSecEvent()
509                             == ((InboundSecurityToken)tokenSecurityEvent.getSecurityToken()).getXMLSecEvent()
510                         && !securityTokenList.contains(signedElementSecurityEvent.getSecurityToken())) {
511                     securityTokenList.add((InboundSecurityToken)signedElementSecurityEvent.getSecurityToken());
512                 }
513             }
514         }
515         return securityTokenList;
516     }
517 
518     private List<InboundSecurityToken> isEncryptedToken(TokenSecurityEvent<? extends SecurityToken> tokenSecurityEvent,
519                                                  Deque<SecurityEvent> securityEventDeque,
520                                                  HttpsTokenSecurityEvent httpsTokenSecurityEvent) throws XMLSecurityException {
521 
522         List<InboundSecurityToken> securityTokenList = new ArrayList<>();
523         if (httpsTokenSecurityEvent != null) {
524             securityTokenList.add(httpsTokenSecurityEvent.getSecurityToken());
525             return securityTokenList;
526         }
527         for (Iterator<SecurityEvent> iterator = securityEventDeque.iterator(); iterator.hasNext();) {
528             SecurityEvent securityEvent = iterator.next();
529             if (WSSecurityEventConstants.EncryptedElement.equals(securityEvent.getSecurityEventType())) {
530                 EncryptedElementSecurityEvent encryptedElementSecurityEvent = (EncryptedElementSecurityEvent) securityEvent;
531                 if (encryptedElementSecurityEvent.isEncrypted()
532                         && tokenSecurityEvent.getSecurityToken() != null
533                         && encryptedElementSecurityEvent.getXmlSecEvent() != null
534                         && encryptedElementSecurityEvent.getXmlSecEvent()
535                             == ((InboundSecurityToken)tokenSecurityEvent.getSecurityToken()).getXMLSecEvent()
536                         && !securityTokenList.contains(encryptedElementSecurityEvent.getSecurityToken())) {
537                     securityTokenList.add((InboundSecurityToken)encryptedElementSecurityEvent.getSecurityToken());
538                 }
539             }
540         }
541         return securityTokenList;
542     }
543 
544     private boolean signsElement(TokenSecurityEvent<? extends SecurityToken> tokenSecurityEvent, List<QName> elementPath,
545                                  Deque<SecurityEvent> securityEventDeque) throws XMLSecurityException {
546         for (Iterator<SecurityEvent> iterator = securityEventDeque.iterator(); iterator.hasNext();) {
547             SecurityEvent securityEvent = iterator.next();
548             if (WSSecurityEventConstants.SignedElement.equals(securityEvent.getSecurityEventType())) {
549                 SignedElementSecurityEvent signedElementSecurityEvent = (SignedElementSecurityEvent) securityEvent;
550                 if (signedElementSecurityEvent.isSigned()
551                         && matchesTokenOrWrappedTokenId(tokenSecurityEvent.getSecurityToken(),
552                         signedElementSecurityEvent.getSecurityToken().getId(),
553                         SecurityTokenConstants.TokenUsage_Signature)
554                         && WSSUtils.pathMatches(elementPath, signedElementSecurityEvent.getElementPath(), false)) {
555                     return true;
556                 }
557             }
558         }
559         return false;
560     }
561 
562     private boolean matchesTokenOrWrappedTokenId(
563             SecurityToken securityToken, String id,
564             SecurityTokenConstants.TokenUsage tokenUsage) throws XMLSecurityException {
565         if (securityToken.getId().equals(id) && securityToken.getTokenUsages().contains(tokenUsage)) {
566             return true;
567         }
568         List<? extends SecurityToken> wrappedTokens = securityToken.getWrappedTokens();
569         for (int i = 0; i < wrappedTokens.size(); i++) {
570             boolean match = matchesTokenOrWrappedTokenId(wrappedTokens.get(i), id, tokenUsage);
571             if (match) {
572                 return match;
573             }
574         }
575         return false;
576     }
577 
578     private boolean encryptsElement(TokenSecurityEvent<? extends SecurityToken> tokenSecurityEvent, List<QName> elementPath,
579                                     Deque<SecurityEvent> securityEventDeque) throws XMLSecurityException {
580         for (Iterator<SecurityEvent> iterator = securityEventDeque.iterator(); iterator.hasNext();) {
581             SecurityEvent securityEvent = iterator.next();
582             if (WSSecurityEventConstants.EncryptedElement.equals(securityEvent.getSecurityEventType())) {
583                 EncryptedElementSecurityEvent encryptedElementSecurityEvent = (EncryptedElementSecurityEvent) securityEvent;
584                 if (encryptedElementSecurityEvent.isEncrypted()
585                         && encryptedElementSecurityEvent.getSecurityToken().getId().equals(tokenSecurityEvent.getSecurityToken().getId())
586                         && WSSUtils.pathMatches(elementPath, encryptedElementSecurityEvent.getElementPath(), false)) {
587                     return true;
588                 }
589             } else if (WSSecurityEventConstants.ContentEncrypted.equals(securityEvent.getSecurityEventType())) {
590                 ContentEncryptedElementSecurityEvent contentEncryptedElementSecurityEvent =
591                     (ContentEncryptedElementSecurityEvent) securityEvent;
592                 String tokenId = tokenSecurityEvent.getSecurityToken().getId();
593                 if (contentEncryptedElementSecurityEvent.isEncrypted()
594                         && contentEncryptedElementSecurityEvent.getSecurityToken().getId().equals(tokenId)
595                         && contentEncryptedElementSecurityEvent.getXmlSecEvent()
596                             == ((InboundSecurityToken)tokenSecurityEvent.getSecurityToken()).getXMLSecEvent()
597                         && WSSUtils.pathMatches(elementPath, contentEncryptedElementSecurityEvent.getElementPath(), false)) {
598                     return true;
599                 }
600             }
601         }
602         return false;
603     }
604 
605     @Override
606     public void handleBSPRule(BSPRule bspRule) throws WSSecurityException {
607         if (disableBSPEnforcement) {
608             return;
609         }
610         if (!ignoredBSPRules.contains(bspRule)) {
611             throw new WSSecurityException(
612                     WSSecurityException.ErrorCode.INVALID_SECURITY,
613                     "empty",
614                     new Object[] {"BSP:" + bspRule.name() + ": " + bspRule.getMsg()});
615         } else {
616             LOG.warn("BSP:" + bspRule.name() + ": " + bspRule.getMsg());
617         }
618     }
619 
620     @Override
621     public void ignoredBSPRules(List<BSPRule> bspRules) {
622         ignoredBSPRules = new ArrayList<>(bspRules);
623     }
624 
625     public boolean isDisableBSPEnforcement() {
626         return disableBSPEnforcement;
627     }
628 
629     public void setDisableBSPEnforcement(boolean disableBSPEnforcement) {
630         this.disableBSPEnforcement = disableBSPEnforcement;
631     }
632 
633     public boolean isAllowRSA15KeyTransportAlgorithm() {
634         return allowRSA15KeyTransportAlgorithm;
635     }
636 
637     public void setAllowRSA15KeyTransportAlgorithm(boolean allowRSA15KeyTransportAlgorithm) {
638         this.allowRSA15KeyTransportAlgorithm = allowRSA15KeyTransportAlgorithm;
639     }
640 
641     public boolean isSoap12() {
642         return soap12;
643     }
644 
645     public void setSoap12(boolean soap12) {
646         this.soap12 = soap12;
647     }
648 
649     private static final class MessageTokens {
650         List<TokenSecurityEvent<? extends InboundSecurityToken>> messageSignatureTokens = Collections.emptyList();
651         List<TokenSecurityEvent<? extends InboundSecurityToken>> messageEncryptionTokens = Collections.emptyList();
652         List<TokenSecurityEvent<? extends InboundSecurityToken>> supportingTokens = Collections.emptyList();
653         List<TokenSecurityEvent<? extends InboundSecurityToken>> signedSupportingTokens = Collections.emptyList();
654         List<TokenSecurityEvent<? extends InboundSecurityToken>> endorsingSupportingTokens = Collections.emptyList();
655         List<TokenSecurityEvent<? extends InboundSecurityToken>> signedEndorsingSupportingTokens = Collections.emptyList();
656         List<TokenSecurityEvent<? extends InboundSecurityToken>> signedEncryptedSupportingTokens = Collections.emptyList();
657         List<TokenSecurityEvent<? extends InboundSecurityToken>> encryptedSupportingTokens = Collections.emptyList();
658         List<TokenSecurityEvent<? extends InboundSecurityToken>> endorsingEncryptedSupportingTokens = Collections.emptyList();
659         List<TokenSecurityEvent<? extends InboundSecurityToken>> signedEndorsingEncryptedSupportingTokens = Collections.emptyList();
660     }
661 }