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.enforcer;
20  
21  import java.util.Deque;
22  import java.util.HashMap;
23  import java.util.Iterator;
24  import java.util.LinkedList;
25  import java.util.List;
26  import java.util.Map;
27  import java.util.Set;
28  
29  import javax.xml.namespace.QName;
30  
31  import org.apache.neethi.Assertion;
32  import org.apache.neethi.ExactlyOne;
33  import org.apache.neethi.Policy;
34  import org.apache.neethi.PolicyComponent;
35  import org.apache.neethi.PolicyContainingAssertion;
36  import org.apache.neethi.PolicyOperator;
37  import org.apache.neethi.builders.PrimitiveAssertion;
38  import org.apache.wss4j.common.ext.WSSecurityException;
39  import org.apache.wss4j.policy.SPConstants;
40  import org.apache.wss4j.common.WSSPolicyException;
41  import org.apache.wss4j.policy.SPConstants.IncludeTokenType;
42  import org.apache.wss4j.policy.model.AbstractBinding;
43  import org.apache.wss4j.policy.model.AbstractSecurityAssertion;
44  import org.apache.wss4j.policy.model.AbstractSymmetricAsymmetricBinding;
45  import org.apache.wss4j.policy.model.AbstractToken;
46  import org.apache.wss4j.policy.model.AlgorithmSuite;
47  import org.apache.wss4j.policy.model.ContentEncryptedElements;
48  import org.apache.wss4j.policy.model.EncryptedElements;
49  import org.apache.wss4j.policy.model.EncryptedParts;
50  import org.apache.wss4j.policy.model.HttpsToken;
51  import org.apache.wss4j.policy.model.IssuedToken;
52  import org.apache.wss4j.policy.model.KerberosToken;
53  import org.apache.wss4j.policy.model.KeyValueToken;
54  import org.apache.wss4j.policy.model.Layout;
55  import org.apache.wss4j.policy.model.RelToken;
56  import org.apache.wss4j.policy.model.RequiredElements;
57  import org.apache.wss4j.policy.model.RequiredParts;
58  import org.apache.wss4j.policy.model.SamlToken;
59  import org.apache.wss4j.policy.model.SecureConversationToken;
60  import org.apache.wss4j.policy.model.SecurityContextToken;
61  import org.apache.wss4j.policy.model.SignedElements;
62  import org.apache.wss4j.policy.model.SignedParts;
63  import org.apache.wss4j.policy.model.SpnegoContextToken;
64  import org.apache.wss4j.policy.model.SupportingTokens;
65  import org.apache.wss4j.policy.model.Trust10;
66  import org.apache.wss4j.policy.model.Trust13;
67  import org.apache.wss4j.policy.model.UsernameToken;
68  import org.apache.wss4j.policy.model.Wss10;
69  import org.apache.wss4j.policy.model.X509Token;
70  import org.apache.wss4j.policy.model.Wss11;
71  import org.apache.wss4j.policy.stax.Assertable;
72  import org.apache.wss4j.policy.stax.DummyPolicyAsserter;
73  import org.apache.wss4j.policy.stax.OperationPolicy;
74  import org.apache.wss4j.policy.stax.PolicyAsserter;
75  import org.apache.wss4j.policy.stax.PolicyViolationException;
76  import org.apache.wss4j.policy.stax.assertionStates.AlgorithmSuiteAssertionState;
77  import org.apache.wss4j.policy.stax.assertionStates.ContentEncryptedElementsAssertionState;
78  import org.apache.wss4j.policy.stax.assertionStates.EncryptedElementsAssertionState;
79  import org.apache.wss4j.policy.stax.assertionStates.EncryptedPartsAssertionState;
80  import org.apache.wss4j.policy.stax.assertionStates.HttpsTokenAssertionState;
81  import org.apache.wss4j.policy.stax.assertionStates.IncludeTimeStampAssertionState;
82  import org.apache.wss4j.policy.stax.assertionStates.IssuedTokenAssertionState;
83  import org.apache.wss4j.policy.stax.assertionStates.KerberosTokenAssertionState;
84  import org.apache.wss4j.policy.stax.assertionStates.KeyValueTokenAssertionState;
85  import org.apache.wss4j.policy.stax.assertionStates.OnlySignEntireHeadersAndBodyAssertionState;
86  import org.apache.wss4j.policy.stax.assertionStates.ProtectionOrderAssertionState;
87  import org.apache.wss4j.policy.stax.assertionStates.RelTokenAssertionState;
88  import org.apache.wss4j.policy.stax.assertionStates.RequiredElementsAssertionState;
89  import org.apache.wss4j.policy.stax.assertionStates.RequiredPartsAssertionState;
90  import org.apache.wss4j.policy.stax.assertionStates.SamlTokenAssertionState;
91  import org.apache.wss4j.policy.stax.assertionStates.SecureConversationTokenAssertionState;
92  import org.apache.wss4j.policy.stax.assertionStates.SecurityContextTokenAssertionState;
93  import org.apache.wss4j.policy.stax.assertionStates.SignatureConfirmationAssertionState;
94  import org.apache.wss4j.policy.stax.assertionStates.SignatureProtectionAssertionState;
95  import org.apache.wss4j.policy.stax.assertionStates.SignedElementsAssertionState;
96  import org.apache.wss4j.policy.stax.assertionStates.SignedPartsAssertionState;
97  import org.apache.wss4j.policy.stax.assertionStates.SpnegoContextTokenAssertionState;
98  import org.apache.wss4j.policy.stax.assertionStates.TokenAssertionState;
99  import org.apache.wss4j.policy.stax.assertionStates.TokenProtectionAssertionState;
100 import org.apache.wss4j.policy.stax.assertionStates.UsernameTokenAssertionState;
101 import org.apache.wss4j.policy.stax.assertionStates.X509TokenAssertionState;
102 import org.apache.wss4j.stax.ext.WSSConstants;
103 import org.apache.wss4j.stax.securityEvent.NoSecuritySecurityEvent;
104 import org.apache.wss4j.stax.securityEvent.OperationSecurityEvent;
105 import org.apache.wss4j.stax.securityEvent.WSSecurityEventConstants;
106 import org.apache.xml.security.exceptions.XMLSecurityException;
107 import org.apache.xml.security.stax.securityEvent.SecurityEvent;
108 import org.apache.xml.security.stax.securityEvent.SecurityEventConstants;
109 import org.apache.xml.security.stax.securityEvent.SecurityEventListener;
110 
111 /**
112  * The PolicyEnforcer verifies the Policy assertions
113  * The Assertion will be validated in realtime as far as possible
114  */
115 public class PolicyEnforcer implements SecurityEventListener {
116 
117     //todo:
118     // AlgorithmSuite SoapNorm
119     // AlgorithmSuite STR Trans
120     // AlgorithmSuite XPATH
121     // AlgorithmSuite Comp Key
122     // Layout? I don't know if it is that relevant and worth. We need security header element numbering
123     //to implement it.
124     // HttpsToken Algorithms
125     //unused tokens must be checked (algorithms etc)
126 
127     private static final transient org.slf4j.Logger LOG =
128         org.slf4j.LoggerFactory.getLogger(PolicyEnforcer.class);
129 
130     private static final QName SOAP11_FAULT = new QName(WSSConstants.NS_SOAP11, "Fault");
131     private static final QName SOAP12_FAULT = new QName(WSSConstants.NS_SOAP12, "Fault");
132 
133     private final List<OperationPolicy> operationPolicies;
134     private OperationPolicy effectivePolicy;
135     private final List<Map<SecurityEventConstants.Event, Map<Assertion, List<Assertable>>>> assertionStateMap;
136     private final List<Map<SecurityEventConstants.Event, Map<Assertion, List<Assertable>>>> failedAssertionStateMap;
137 
138     private final Deque<SecurityEvent> securityEventQueue = new LinkedList<>();
139     private boolean operationSecurityEventOccured = false;
140     private boolean initiator;
141     private String actorOrRole;
142     private int attachmentCount;
143     private boolean noSecurityHeader;
144     private boolean faultOccurred;
145     private final PolicyAsserter policyAsserter;
146     private boolean soap12;
147 
148     public PolicyEnforcer(List<OperationPolicy> operationPolicies, String soapAction, boolean initiator,
149                           String actorOrRole, int attachmentCount, PolicyAsserter policyAsserter, boolean soap12
150     ) throws WSSPolicyException {
151         this.operationPolicies = operationPolicies;
152         this.initiator = initiator;
153         this.actorOrRole = actorOrRole;
154         this.attachmentCount = attachmentCount;
155         this.soap12 = soap12;
156         assertionStateMap = new LinkedList<>();
157         failedAssertionStateMap = new LinkedList<>();
158 
159         if (policyAsserter == null) {
160             this.policyAsserter = new DummyPolicyAsserter();
161         } else {
162             this.policyAsserter = policyAsserter;
163         }
164 
165         if (soapAction != null && !soapAction.isEmpty()) {
166             effectivePolicy = findPolicyBySOAPAction(operationPolicies, soapAction);
167             if (effectivePolicy != null) {
168                 buildAssertionStateMap(effectivePolicy.getPolicy(), assertionStateMap);
169             }
170         }
171     }
172 
173     private OperationPolicy findPolicyBySOAPAction(List<OperationPolicy> operationPolicies, String soapAction) {
174         Iterator<OperationPolicy> operationPolicyIterator = operationPolicies.iterator();
175         while (operationPolicyIterator.hasNext()) {
176             OperationPolicy operationPolicy = operationPolicyIterator.next();
177             if (soapAction.equals(operationPolicy.getOperationAction())) {
178                 return operationPolicy;
179             }
180         }
181         return null;
182     }
183 
184     private OperationPolicy findPolicyBySOAPOperationName(List<OperationPolicy> operationPolicies,
185                                                           QName soapOperationName) {
186         Iterator<OperationPolicy> operationPolicyIterator = operationPolicies.iterator();
187         OperationPolicy noNamespaceOperation = null;
188 
189         while (operationPolicyIterator.hasNext()) {
190             OperationPolicy operationPolicy = operationPolicyIterator.next();
191             QName operationName = operationPolicy.getOperationName();
192             if (operationName != null) {
193                 if (soapOperationName.equals(operationName)) {
194                     return operationPolicy;
195                 } else if ((operationName.getNamespaceURI() == null || operationName.getNamespaceURI().length() == 0)
196                     && soapOperationName.getLocalPart().equals(operationName.getLocalPart())) {
197                     noNamespaceOperation = operationPolicy;
198                 }
199             }
200         }
201 
202         return noNamespaceOperation;
203     }
204 
205     /**
206      * Precondition: Policy _must_ be normalized!
207      */
208     private void buildAssertionStateMap(
209             PolicyComponent policyComponent,
210             List<Map<SecurityEventConstants.Event, Map<Assertion, List<Assertable>>>> assertionStateMap
211     ) throws WSSPolicyException {
212         if (policyComponent instanceof PolicyOperator) {
213             PolicyOperator policyOperator = (PolicyOperator) policyComponent;
214             List<PolicyComponent> policyComponents = policyOperator.getPolicyComponents();
215             int alternative = 0;
216             Iterator<PolicyComponent> policyComponentIterator = policyComponents.iterator();
217             while (policyComponentIterator.hasNext()) {
218                 PolicyComponent curPolicyComponent = policyComponentIterator.next();
219                 if (policyOperator instanceof ExactlyOne) {
220                     assertionStateMap.add(new HashMap<SecurityEventConstants.Event,
221                                           Map<Assertion, List<Assertable>>>());
222                     buildAssertionStateMap(curPolicyComponent, assertionStateMap, alternative++);
223                 } else {
224                     buildAssertionStateMap(curPolicyComponent, assertionStateMap);
225                 }
226             }
227         } else {
228             throw new WSSPolicyException("Invalid PolicyComponent: " + policyComponent
229                                          + " " + policyComponent.getType());
230         }
231     }
232 
233     private void buildAssertionStateMap(
234             PolicyComponent policyComponent,
235             List<Map<SecurityEventConstants.Event,
236             Map<Assertion, List<Assertable>>>> assertionStateMap,
237             int alternative
238     ) throws WSSPolicyException {
239         if (policyComponent instanceof PolicyOperator) {
240             PolicyOperator policyOperator = (PolicyOperator) policyComponent;
241             List<PolicyComponent> policyComponents = policyOperator.getPolicyComponents();
242             Iterator<PolicyComponent> policyComponentIterator = policyComponents.iterator();
243             while (policyComponentIterator.hasNext()) {
244                 PolicyComponent curPolicyComponent = policyComponentIterator.next();
245                 buildAssertionStateMap(curPolicyComponent, assertionStateMap, alternative);
246             }
247         } else if (policyComponent instanceof AbstractSecurityAssertion) {
248             AbstractSecurityAssertion abstractSecurityAssertion = (AbstractSecurityAssertion) policyComponent;
249 
250             List<Assertable> assertablesList = getAssertableForAssertion(abstractSecurityAssertion);
251             Iterator<Assertable> assertableIterator = assertablesList.iterator();
252             while (assertableIterator.hasNext()) {
253                 Assertable assertable = assertableIterator.next();
254                 final Map<SecurityEventConstants.Event, Map<Assertion, List<Assertable>>> map =
255                     assertionStateMap.get(alternative);
256                 final SecurityEventConstants.Event[] securityEventType = assertable.getSecurityEventType();
257                 for (int j = 0; j < securityEventType.length; j++) {
258                     SecurityEventConstants.Event event = securityEventType[j];
259                     Map<Assertion, List<Assertable>> assertables = map.get(event);
260                     if (assertables == null) {
261                         assertables = new HashMap<>();
262                         map.put(event, assertables);
263                     }
264                     addAssertionState(assertables, abstractSecurityAssertion, assertable);
265                 }
266             }
267             if (abstractSecurityAssertion instanceof PolicyContainingAssertion) {
268                 buildAssertionStateMap(((PolicyContainingAssertion) abstractSecurityAssertion).getPolicy(),
269                                        assertionStateMap, alternative);
270             }
271         } else if (!(policyComponent instanceof PrimitiveAssertion)) {
272             throw new WSSPolicyException("Unsupported PolicyComponent: " + policyComponent
273                                          + " type: " + policyComponent.getType());
274         }
275     }
276 
277     private void addAssertionState(Map<Assertion, List<Assertable>> assertables,
278                                    Assertion keyAssertion,
279                                    Assertable assertable) {
280         List<Assertable> assertableList = assertables.get(keyAssertion);
281         if (assertableList == null) {
282             assertableList = new LinkedList<>();
283             assertables.put(keyAssertion, assertableList);
284         }
285         assertableList.add(assertable);
286     }
287 
288     // Don't return a Token that is not required
289     private boolean isTokenRequired(AbstractToken token) {
290         SPConstants.IncludeTokenType includeTokenType = token.getIncludeTokenType();
291         if (includeTokenType == IncludeTokenType.INCLUDE_TOKEN_NEVER) {
292             return false;
293         } else if (initiator && includeTokenType == IncludeTokenType.INCLUDE_TOKEN_ALWAYS_TO_RECIPIENT) {
294             return false;
295         } else if (initiator && includeTokenType == IncludeTokenType.INCLUDE_TOKEN_ONCE) {
296             return false;
297         } else if (!initiator && includeTokenType == IncludeTokenType.INCLUDE_TOKEN_ALWAYS_TO_INITIATOR) {
298             return false;
299         }
300         return true;
301     }
302 
303     protected List<Assertable> getAssertableForAssertion(AbstractSecurityAssertion abstractSecurityAssertion)
304         throws WSSPolicyException {
305         List<Assertable> assertableList = new LinkedList<>();
306         boolean tokenRequired = true;
307         if (abstractSecurityAssertion instanceof AbstractToken) {
308             tokenRequired = isTokenRequired((AbstractToken)abstractSecurityAssertion);
309         }
310 
311         if (abstractSecurityAssertion instanceof ContentEncryptedElements) {
312             // initialized with asserted=true because it could be that parent elements are encrypted and
313             // therefore these element are also encrypted
314             // the test if it is really encrypted is done via the PolicyInputProcessor which emits
315             // EncryptedElementEvents for unencrypted elements with the unencrypted flag
316             assertableList.add(new ContentEncryptedElementsAssertionState(abstractSecurityAssertion, policyAsserter, true));
317         } else if (abstractSecurityAssertion instanceof EncryptedParts) {
318             // initialized with asserted=true with the same reason as by the EncryptedParts above
319             assertableList.add(new EncryptedPartsAssertionState(abstractSecurityAssertion, policyAsserter, true, attachmentCount, soap12));
320         } else if (abstractSecurityAssertion instanceof EncryptedElements) {
321             // initialized with asserted=true with the same reason as by the EncryptedParts above
322             assertableList.add(new EncryptedElementsAssertionState(abstractSecurityAssertion, policyAsserter, true));
323         } else if (abstractSecurityAssertion instanceof SignedParts) {
324             // initialized with asserted=true because it could be that parent elements are signed and
325             // therefore these element are also signed
326             // the test if it is really signed is done via the PolicyInputProcessor which emits SignedElementEvents for
327             // unsigned elements with the unsigned flag
328             assertableList.add(new SignedPartsAssertionState(abstractSecurityAssertion, policyAsserter, true, attachmentCount, soap12));
329         } else if (abstractSecurityAssertion instanceof SignedElements) {
330             // initialized with asserted=true with the same reason as by the SignedParts above
331             assertableList.add(new SignedElementsAssertionState(abstractSecurityAssertion, policyAsserter, true));
332         } else if (abstractSecurityAssertion instanceof RequiredElements) {
333             assertableList.add(new RequiredElementsAssertionState(abstractSecurityAssertion, policyAsserter, false));
334         } else if (abstractSecurityAssertion instanceof RequiredParts) {
335             assertableList.add(new RequiredPartsAssertionState(abstractSecurityAssertion, policyAsserter, false, soap12));
336         } else if (abstractSecurityAssertion instanceof UsernameToken) {
337             assertableList.add(new UsernameTokenAssertionState(abstractSecurityAssertion, !tokenRequired, policyAsserter, initiator));
338         } else if (abstractSecurityAssertion instanceof IssuedToken) {
339             assertableList.add(new IssuedTokenAssertionState(abstractSecurityAssertion, !tokenRequired, policyAsserter, initiator));
340         } else if (abstractSecurityAssertion instanceof X509Token) {
341             assertableList.add(new X509TokenAssertionState(abstractSecurityAssertion, !tokenRequired, policyAsserter, initiator));
342         } else if (abstractSecurityAssertion instanceof KerberosToken) {
343             assertableList.add(new KerberosTokenAssertionState(abstractSecurityAssertion, !tokenRequired, policyAsserter, initiator));
344         } else if (abstractSecurityAssertion instanceof SpnegoContextToken) {
345             assertableList.add(new SpnegoContextTokenAssertionState(abstractSecurityAssertion, !tokenRequired, policyAsserter, initiator));
346         } else if (abstractSecurityAssertion instanceof SecureConversationToken) {
347             assertableList.add(new SecureConversationTokenAssertionState(abstractSecurityAssertion, !tokenRequired,
348                                                                          policyAsserter, initiator));
349         } else if (abstractSecurityAssertion instanceof SecurityContextToken) {
350             assertableList.add(new SecurityContextTokenAssertionState(abstractSecurityAssertion, !tokenRequired,
351                                                                       policyAsserter, initiator));
352         } else if (abstractSecurityAssertion instanceof SamlToken) {
353             assertableList.add(new SamlTokenAssertionState(abstractSecurityAssertion, !tokenRequired, policyAsserter, initiator));
354         } else if (abstractSecurityAssertion instanceof RelToken) {
355             assertableList.add(new RelTokenAssertionState(abstractSecurityAssertion, !tokenRequired, policyAsserter, initiator));
356         } else if (abstractSecurityAssertion instanceof HttpsToken) {
357             assertableList.add(new HttpsTokenAssertionState(abstractSecurityAssertion,
358                                                             !tokenRequired || initiator, policyAsserter, initiator));
359         } else if (abstractSecurityAssertion instanceof KeyValueToken) {
360             assertableList.add(new KeyValueTokenAssertionState(abstractSecurityAssertion, !tokenRequired, policyAsserter, initiator));
361         } else if (abstractSecurityAssertion instanceof AlgorithmSuite) {
362             // initialized with asserted=true because we do negative matching
363             assertableList.add(new AlgorithmSuiteAssertionState(abstractSecurityAssertion, policyAsserter, true));
364         } else if (abstractSecurityAssertion instanceof Layout) {
365             //assertableList.add(new LayoutAssertionState(abstractSecurityAssertion, true));
366             String namespace = abstractSecurityAssertion.getName().getNamespaceURI();
367             policyAsserter.assertPolicy(new QName(namespace, SPConstants.LAYOUT_LAX));
368             policyAsserter.assertPolicy(new QName(namespace, SPConstants.LAYOUT_LAX_TIMESTAMP_FIRST));
369             policyAsserter.assertPolicy(new QName(namespace, SPConstants.LAYOUT_LAX_TIMESTAMP_LAST));
370             policyAsserter.assertPolicy(new QName(namespace, SPConstants.LAYOUT_STRICT));
371             policyAsserter.assertPolicy(abstractSecurityAssertion);
372         } else if (abstractSecurityAssertion instanceof AbstractBinding) {
373             policyAsserter.assertPolicy(abstractSecurityAssertion);
374             AbstractBinding abstractBinding = (AbstractBinding) abstractSecurityAssertion;
375             if (abstractBinding instanceof AbstractSymmetricAsymmetricBinding) {
376                 AbstractSymmetricAsymmetricBinding abstractSymmetricAsymmetricBinding =
377                     (AbstractSymmetricAsymmetricBinding) abstractSecurityAssertion;
378                 assertableList.add(new ProtectionOrderAssertionState(abstractSymmetricAsymmetricBinding, policyAsserter, true));
379                 assertableList.add(new SignatureProtectionAssertionState(abstractSymmetricAsymmetricBinding, policyAsserter, true));
380                 if (abstractSymmetricAsymmetricBinding.isOnlySignEntireHeadersAndBody()) {
381                     //initialized with asserted=true because we do negative matching
382                     assertableList.add(new OnlySignEntireHeadersAndBodyAssertionState(abstractSecurityAssertion, policyAsserter,
383                                                                                       true, actorOrRole));
384                 }
385                 assertableList.add(new TokenProtectionAssertionState(abstractSecurityAssertion, policyAsserter, true, soap12));
386             }
387 
388             //WSP1.3, 6.2 Timestamp Property
389             assertableList.add(new IncludeTimeStampAssertionState(abstractBinding, policyAsserter, true));
390             if (abstractBinding.isIncludeTimestamp()) {
391                 List<QName> timestampElementPath = new LinkedList<>();
392                 if (soap12) {
393                     timestampElementPath.addAll(WSSConstants.SOAP_12_WSSE_SECURITY_HEADER_PATH);
394                 } else {
395                     timestampElementPath.addAll(WSSConstants.SOAP_11_WSSE_SECURITY_HEADER_PATH);
396                 }
397                 timestampElementPath.add(WSSConstants.TAG_WSU_TIMESTAMP);
398                 RequiredElementsAssertionState requiredElementsAssertionState =
399                     new RequiredElementsAssertionState(abstractBinding, policyAsserter, false);
400                 requiredElementsAssertionState.addElement(timestampElementPath);
401                 assertableList.add(requiredElementsAssertionState);
402 
403                 SignedElementsAssertionState signedElementsAssertionState =
404                     new SignedElementsAssertionState(abstractSecurityAssertion, policyAsserter, true);
405                 signedElementsAssertionState.addElement(timestampElementPath);
406                 assertableList.add(signedElementsAssertionState);
407             }
408         } else if (abstractSecurityAssertion instanceof Wss10) {
409             Wss10 wss10 = (Wss10)abstractSecurityAssertion;
410             String namespace = wss10.getName().getNamespaceURI();
411             policyAsserter.assertPolicy(abstractSecurityAssertion);
412 
413             if (wss10.isMustSupportRefEmbeddedToken()) {
414                 policyAsserter.assertPolicy(new QName(namespace, SPConstants.MUST_SUPPORT_REF_EMBEDDED_TOKEN));
415             }
416             if (wss10.isMustSupportRefExternalURI()) {
417                 policyAsserter.assertPolicy(new QName(namespace, SPConstants.MUST_SUPPORT_REF_EXTERNAL_URI));
418             }
419             if (wss10.isMustSupportRefIssuerSerial()) {
420                 policyAsserter.assertPolicy(new QName(namespace, SPConstants.MUST_SUPPORT_REF_ISSUER_SERIAL));
421             }
422             if (wss10.isMustSupportRefKeyIdentifier()) {
423                 policyAsserter.assertPolicy(new QName(namespace, SPConstants.MUST_SUPPORT_REF_KEY_IDENTIFIER));
424             }
425 
426             if (abstractSecurityAssertion instanceof Wss11) {
427                 Wss11 wss11 = (Wss11)abstractSecurityAssertion;
428                 if (wss11.isMustSupportRefEncryptedKey()) {
429                     policyAsserter.assertPolicy(new QName(namespace, SPConstants.MUST_SUPPORT_REF_ENCRYPTED_KEY));
430                 }
431                 if (wss11.isMustSupportRefThumbprint()) {
432                     policyAsserter.assertPolicy(new QName(namespace, SPConstants.MUST_SUPPORT_REF_THUMBPRINT));
433                 }
434                 if (wss11.isRequireSignatureConfirmation()) {
435                     assertableList.add(new SignatureConfirmationAssertionState(wss11, policyAsserter, true));
436                     if (initiator) {
437                         //9 WSS: SOAP Message Security Options [Signature Confirmation]
438                         List<QName> signatureConfirmationElementPath = new LinkedList<>();
439                         if (soap12) {
440                             signatureConfirmationElementPath.addAll(WSSConstants.SOAP_12_WSSE_SECURITY_HEADER_PATH);
441                         } else {
442                             signatureConfirmationElementPath.addAll(WSSConstants.SOAP_11_WSSE_SECURITY_HEADER_PATH);
443                         }
444                         signatureConfirmationElementPath.add(WSSConstants.TAG_WSSE11_SIG_CONF);
445                         RequiredElementsAssertionState requiredElementsAssertionState =
446                             new RequiredElementsAssertionState(wss11, policyAsserter, false);
447                         requiredElementsAssertionState.addElement(signatureConfirmationElementPath);
448                         assertableList.add(requiredElementsAssertionState);
449 
450                         SignedElementsAssertionState signedElementsAssertionState =
451                             new SignedElementsAssertionState(wss11, policyAsserter, true);
452                         signedElementsAssertionState.addElement(signatureConfirmationElementPath);
453                         assertableList.add(signedElementsAssertionState);
454                     }
455                 }
456             }
457         } else if (abstractSecurityAssertion instanceof Trust10) {
458             Trust10 trust10 = (Trust10)abstractSecurityAssertion;
459             String namespace = trust10.getName().getNamespaceURI();
460             policyAsserter.assertPolicy(abstractSecurityAssertion);
461 
462             if (trust10.isMustSupportClientChallenge()) {
463                 policyAsserter.assertPolicy(new QName(namespace, SPConstants.MUST_SUPPORT_CLIENT_CHALLENGE));
464             }
465             if (trust10.isMustSupportIssuedTokens()) {
466                 policyAsserter.assertPolicy(new QName(namespace, SPConstants.MUST_SUPPORT_ISSUED_TOKENS));
467             }
468             if (trust10.isMustSupportServerChallenge()) {
469                 policyAsserter.assertPolicy(new QName(namespace, SPConstants.MUST_SUPPORT_SERVER_CHALLENGE));
470             }
471             if (trust10.isRequireClientEntropy()) {
472                 policyAsserter.assertPolicy(new QName(namespace, SPConstants.REQUIRE_CLIENT_ENTROPY));
473             }
474             if (trust10.isRequireServerEntropy()) {
475                 policyAsserter.assertPolicy(new QName(namespace, SPConstants.REQUIRE_SERVER_ENTROPY));
476             }
477             if (trust10 instanceof Trust13) {
478                 Trust13 trust13 = (Trust13)trust10;
479                 if (trust13.isMustSupportInteractiveChallenge()) {
480                     policyAsserter.assertPolicy(new QName(namespace, SPConstants.MUST_SUPPORT_INTERACTIVE_CHALLENGE));
481                 }
482                 if (trust13.isRequireAppliesTo()) {
483                     policyAsserter.assertPolicy(new QName(namespace, SPConstants.REQUIRE_APPLIES_TO));
484                 }
485                 if (trust13.isRequireRequestSecurityTokenCollection()) {
486                     policyAsserter.assertPolicy(new QName(namespace,
487                                                           SPConstants.REQUIRE_REQUEST_SECURITY_TOKEN_COLLECTION));
488                 }
489                 if (trust13.isScopePolicy15()) {
490                     policyAsserter.assertPolicy(new QName(namespace, SPConstants.SCOPE_POLICY_15));
491                 }
492             }
493         } else {
494             policyAsserter.assertPolicy(abstractSecurityAssertion);
495         }
496 
497         /*else if (abstractSecurityAssertion instanceof AsymmetricBinding) {
498         } else if (abstractSecurityAssertion instanceof SymmetricBinding) {
499         } else if (abstractSecurityAssertion instanceof TransportBinding) {
500         } */
501 
502         return assertableList;
503     }
504 
505     /**
506      * tries to verify a SecurityEvent in realtime.
507      *
508      * @param securityEvent
509      * @throws WSSPolicyException
510      */
511     private void verifyPolicy(SecurityEvent securityEvent) throws WSSPolicyException, XMLSecurityException {
512         // We have to check the failed assertions for logging purposes firstly...
513         if (!this.failedAssertionStateMap.isEmpty()) {
514             Iterator<Map<SecurityEventConstants.Event, Map<Assertion, List<Assertable>>>> assertionStateMapIterator =
515                 this.failedAssertionStateMap.iterator();
516             alternative:
517                 while (assertionStateMapIterator.hasNext()) {
518                     Map<SecurityEventConstants.Event, Map<Assertion, List<Assertable>>> map =
519                         assertionStateMapIterator.next();
520                     // every list entry counts as an alternative...
521                     Map<Assertion, List<Assertable>> assertionListMap = map.get(securityEvent.getSecurityEventType());
522                     if (assertionListMap != null && !assertionListMap.isEmpty()) {
523                         Iterator<Map.Entry<Assertion, List<Assertable>>> assertionStateIterator =
524                             assertionListMap.entrySet().iterator();
525                         while (assertionStateIterator.hasNext()) {
526                             Map.Entry<Assertion, List<Assertable>> assertionStateEntry =
527                                 assertionStateIterator.next();
528                             List<Assertable> assertionStates = assertionStateEntry.getValue();
529                             Iterator<Assertable> assertableIterator = assertionStates.iterator();
530                             while (assertableIterator.hasNext()) {
531                                 Assertable assertable = assertableIterator.next();
532                                 boolean asserted = assertable.assertEvent(securityEvent);
533                                 // ...so if one fails, continue with the next map entry and
534                                 // increment the notAssertedCount
535                                 if (!asserted) {
536                                     continue alternative;
537                                 }
538                             }
539                         }
540                     }
541                 }
542         }
543 
544         String assertionMessage = null;
545         //...and then check the remaining alternatives
546         Iterator<Map<SecurityEventConstants.Event, Map<Assertion, List<Assertable>>>> assertionStateMapIterator =
547             this.assertionStateMap.iterator();
548         //every map entry counts as an alternative...
549         alternative:
550             while (assertionStateMapIterator.hasNext()) {
551                 Map<SecurityEventConstants.Event, Map<Assertion, List<Assertable>>> map =
552                     assertionStateMapIterator.next();
553                 Map<Assertion, List<Assertable>> assertionListMap = map.get(securityEvent.getSecurityEventType());
554                 if (assertionListMap != null && !assertionListMap.isEmpty()) {
555                     Iterator<Map.Entry<Assertion, List<Assertable>>> assertionStateIterator =
556                         assertionListMap.entrySet().iterator();
557                     while (assertionStateIterator.hasNext()) {
558                         Map.Entry<Assertion, List<Assertable>> assertionStateEntry = assertionStateIterator.next();
559                         List<Assertable> assertionStates = assertionStateEntry.getValue();
560                         Iterator<Assertable> assertableIterator = assertionStates.iterator();
561                         while (assertableIterator.hasNext()) {
562                             Assertable assertable = assertableIterator.next();
563                             boolean asserted = assertable.assertEvent(securityEvent);
564                             //...so if one fails, continue with the next map entry and increment the notAssertedCount
565                             if (!asserted) {
566                                 assertionMessage = assertable.getErrorMessage();
567                                 failedAssertionStateMap.add(map);
568                                 assertionStateMapIterator.remove();
569                                 continue alternative;
570                             }
571                         }
572                     }
573                 }
574             }
575         //if the assertionStateMap is empty (the size of the list is equal to the alternatives)
576         //then we could not satisfy any alternative
577         if (assertionStateMap.isEmpty() && !(faultOccurred && noSecurityHeader && initiator)) {
578             logFailedAssertions();
579             throw new PolicyViolationException(assertionMessage);
580         }
581     }
582 
583     /**
584      * verifies the whole policy to try to find a satisfied alternative
585      *
586      * @throws WSSPolicyException       throws when the policy is invalid
587      * @throws PolicyViolationException thrown when no alternative could be satisfied
588      */
589     private void verifyPolicy() throws WSSPolicyException {
590         String assertionMessage = null;
591         Iterator<Map<SecurityEventConstants.Event, Map<Assertion, List<Assertable>>>> assertionStateMapIterator =
592             this.assertionStateMap.iterator();
593         alternative:
594         while (assertionStateMapIterator.hasNext()) {
595             Map<SecurityEventConstants.Event, Map<Assertion, List<Assertable>>> map =
596                 assertionStateMapIterator.next();
597             Iterator<Map.Entry<SecurityEventConstants.Event, Map<Assertion, List<Assertable>>>> iterator =
598                 map.entrySet().iterator();
599             while (iterator.hasNext()) {
600                 Map.Entry<SecurityEventConstants.Event, Map<Assertion, List<Assertable>>> mapEntry =
601                     iterator.next();
602                 Iterator<Map.Entry<Assertion, List<Assertable>>> assertionStateIterator =
603                     mapEntry.getValue().entrySet().iterator();
604                 while (assertionStateIterator.hasNext()) {
605                     Map.Entry<Assertion, List<Assertable>> assertionListEntry = assertionStateIterator.next();
606                     List<Assertable> assertableList = assertionListEntry.getValue();
607                     Iterator<Assertable> assertableIterator = assertableList.iterator();
608                     while (assertableIterator.hasNext()) {
609                         Assertable assertable = assertableIterator.next();
610                         if (!assertable.isAsserted()) {
611                             assertionMessage = assertable.getErrorMessage();
612                             failedAssertionStateMap.add(map);
613                             assertionStateMapIterator.remove();
614                             continue alternative;
615                         }
616                     }
617                 }
618             }
619         }
620         if (assertionStateMap.isEmpty() && !(faultOccurred && noSecurityHeader && initiator)) {
621             logFailedAssertions();
622             throw new WSSPolicyException(assertionMessage);
623         }
624     }
625 
626     /**
627      * verifies the policy after the OperationSecurityEvent occurred. This allows to
628      * stop further processing after the header is processed when the policy is not fulfilled.
629      *
630      * @throws WSSPolicyException       throws when the policy is invalid
631      * @throws PolicyViolationException thrown when no alternative could be satisfied
632      */
633     private void verifyPolicyAfterOperationSecurityEvent() throws WSSPolicyException {
634         String assertionMessage = null;
635         Iterator<Map<SecurityEventConstants.Event, Map<Assertion, List<Assertable>>>> assertionStateMapIterator =
636             this.assertionStateMap.iterator();
637         alternative:
638         while (assertionStateMapIterator.hasNext()) {
639             Map<SecurityEventConstants.Event, Map<Assertion, List<Assertable>>> map =
640                 assertionStateMapIterator.next();
641             Iterator<Map.Entry<SecurityEventConstants.Event, Map<Assertion, List<Assertable>>>> iterator =
642                 map.entrySet().iterator();
643             while (iterator.hasNext()) {
644                 Map.Entry<SecurityEventConstants.Event, Map<Assertion, List<Assertable>>> mapEntry =
645                     iterator.next();
646                 Iterator<Map.Entry<Assertion, List<Assertable>>> assertionStateIterator =
647                     mapEntry.getValue().entrySet().iterator();
648                 while (assertionStateIterator.hasNext()) {
649                     Map.Entry<Assertion, List<Assertable>> assertionListEntry = assertionStateIterator.next();
650                     List<Assertable> assertableList = assertionListEntry.getValue();
651                     Iterator<Assertable> assertableIterator = assertableList.iterator();
652                     while (assertableIterator.hasNext()) {
653                         Assertable assertable = assertableIterator.next();
654 
655                         boolean doAssert = false;
656                         if (assertable instanceof TokenAssertionState) {
657                             TokenAssertionState tokenAssertionState = (TokenAssertionState) assertable;
658                             AbstractToken abstractToken = (AbstractToken) tokenAssertionState.getAssertion();
659                             AbstractSecurityAssertion assertion = abstractToken.getParentAssertion();
660                             //Other tokens may not be resolved yet fully therefore we skip it here
661                             if (assertion instanceof SupportingTokens
662                                 || assertable instanceof HttpsTokenAssertionState
663                                 || assertable instanceof RelTokenAssertionState
664                                 || assertable instanceof SecurityContextTokenAssertionState
665                                 || assertable instanceof SpnegoContextTokenAssertionState
666                                 || assertable instanceof UsernameTokenAssertionState) {
667                                 doAssert = true;
668                             }
669                         } else if (assertable instanceof TokenProtectionAssertionState
670                             || assertable instanceof SignatureConfirmationAssertionState
671                             || assertable instanceof IncludeTimeStampAssertionState
672                             || assertable instanceof RequiredPartsAssertionState
673                             || assertable instanceof SignatureProtectionAssertionState) {
674                             doAssert = true;
675                         }
676 
677                         if ((doAssert || assertable.isHardFailure()) && !assertable.isAsserted()) {
678                             assertionMessage = assertable.getErrorMessage();
679                             failedAssertionStateMap.add(map);
680                             assertionStateMapIterator.remove();
681                             continue alternative;
682                         }
683                     }
684                 }
685             }
686         }
687         if (assertionStateMap.isEmpty() && !(faultOccurred && noSecurityHeader && initiator)) {
688             logFailedAssertions();
689             throw new WSSPolicyException(assertionMessage);
690         }
691     }
692 
693     private void logFailedAssertions() {
694         if (this.failedAssertionStateMap.isEmpty()) {
695             return;
696         }
697 
698         Iterator<Map<SecurityEventConstants.Event, Map<Assertion, List<Assertable>>>> assertionStateMapIterator =
699             this.failedAssertionStateMap.iterator();
700         while (assertionStateMapIterator.hasNext()) {
701             Map<SecurityEventConstants.Event, Map<Assertion, List<Assertable>>> map =
702                 assertionStateMapIterator.next();
703             Set<Map.Entry<SecurityEventConstants.Event, Map<Assertion, List<Assertable>>>> entrySet = map.entrySet();
704             Iterator<Map.Entry<SecurityEventConstants.Event, Map<Assertion, List<Assertable>>>> entryIterator =
705                 entrySet.iterator();
706             while (entryIterator.hasNext()) {
707                 Map.Entry<SecurityEventConstants.Event, Map<Assertion, List<Assertable>>> eventCollectionEntry =
708                     entryIterator.next();
709                 Map<Assertion, List<Assertable>> assertionListMap = eventCollectionEntry.getValue();
710                 Iterator<Map.Entry<Assertion, List<Assertable>>> assertionStateEntryIterator =
711                     assertionListMap.entrySet().iterator();
712                 while (assertionStateEntryIterator.hasNext()) {
713                     Map.Entry<Assertion, List<Assertable>> entry = assertionStateEntryIterator.next();
714                     List<Assertable> assertionStates = entry.getValue();
715                     Iterator<Assertable> assertableIterator = assertionStates.iterator();
716                     while (assertableIterator.hasNext()) {
717                         Assertable assertable = assertableIterator.next();
718                         if (!assertable.isAsserted() && !assertable.isLogged()) {
719                             LOG.error(entry.getKey().getName() + " not satisfied: " + assertable.getErrorMessage());
720                             assertable.setLogged(true);
721                         }
722                     }
723                 }
724             }
725         }
726     }
727 
728     //multiple threads can call this method concurrently -> synchronize access
729     @Override
730     public synchronized void registerSecurityEvent(SecurityEvent securityEvent) throws WSSecurityException {
731 
732         if (!noSecurityHeader && securityEvent instanceof NoSecuritySecurityEvent) {
733             noSecurityHeader = true;
734         }
735 
736         if (operationSecurityEventOccured) {
737             try {
738                 verifyPolicy(securityEvent);
739             } catch (WSSPolicyException | XMLSecurityException e) {
740                 throw new WSSecurityException(WSSecurityException.ErrorCode.INVALID_SECURITY, e);
741             }
742         }
743 
744         if (WSSecurityEventConstants.OPERATION.equals(securityEvent.getSecurityEventType())) {
745             operationSecurityEventOccured = true;
746             final OperationSecurityEvent operationSecurityEvent = (OperationSecurityEvent) securityEvent;
747             if (!faultOccurred && (SOAP11_FAULT.equals(operationSecurityEvent.getOperation())
748                 || SOAP12_FAULT.equals(operationSecurityEvent.getOperation()))) {
749                 faultOccurred = true;
750             }
751 
752             if (effectivePolicy == null) {
753                 effectivePolicy = findPolicyBySOAPOperationName(operationPolicies,
754                                                                 operationSecurityEvent.getOperation());
755                 if (effectivePolicy == null) {
756                     //no policy to the operation given
757                     effectivePolicy = new OperationPolicy(new QName(null, "NoPolicyFoundForOperation"));
758                     effectivePolicy.setPolicy(new Policy());
759                 }
760                 try {
761                     buildAssertionStateMap(effectivePolicy.getPolicy(), assertionStateMap);
762                 } catch (WSSPolicyException e) {
763                     throw new WSSecurityException(WSSecurityException.ErrorCode.INVALID_SECURITY, e);
764                 }
765             }
766             try {
767                 Iterator<SecurityEvent> securityEventIterator = securityEventQueue.descendingIterator();
768                 while (securityEventIterator.hasNext()) {
769                     SecurityEvent prevSecurityEvent = securityEventIterator.next();
770                     verifyPolicy(prevSecurityEvent);
771                 }
772 
773                 verifyPolicy(securityEvent);
774 
775                 verifyPolicyAfterOperationSecurityEvent();
776             } catch (WSSPolicyException | XMLSecurityException e) {
777                 throw new WSSecurityException(WSSecurityException.ErrorCode.INVALID_SECURITY, e);
778             }
779             securityEventQueue.clear();
780 
781             return;
782         } else {
783             securityEventQueue.push(securityEvent);
784         }
785     }
786 
787     /**
788      * the final Policy validation to find a satisfied alternative
789      *
790      * @throws PolicyViolationException if no alternative could be satisfied
791      */
792     public void doFinal() throws WSSPolicyException {
793         verifyPolicy();
794     }
795 
796 }