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.AbstractSecurityAssertion;
25  import org.apache.wss4j.policy.model.AbstractSymmetricAsymmetricBinding;
26  import org.apache.wss4j.policy.stax.Assertable;
27  import org.apache.wss4j.policy.stax.DummyPolicyAsserter;
28  import org.apache.wss4j.policy.stax.PolicyAsserter;
29  import org.apache.wss4j.stax.securityEvent.*;
30  import org.apache.wss4j.stax.utils.WSSUtils;
31  import org.apache.xml.security.stax.ext.XMLSecurityConstants;
32  import org.apache.xml.security.stax.securityEvent.ContentEncryptedElementSecurityEvent;
33  import org.apache.xml.security.stax.securityEvent.EncryptedElementSecurityEvent;
34  import org.apache.xml.security.stax.securityEvent.SecurityEvent;
35  import org.apache.xml.security.stax.securityEvent.SecurityEventConstants;
36  import org.apache.xml.security.stax.securityEvent.SignedElementSecurityEvent;
37  
38  import javax.xml.namespace.QName;
39  
40  import java.util.List;
41  
42  /**
43   * WSP1.3, 6.3 Protection Order Property
44   */
45  
46  public class ProtectionOrderAssertionState extends AssertionState implements Assertable {
47  
48      private PolicyAsserter policyAsserter;
49  
50      public ProtectionOrderAssertionState(AbstractSecurityAssertion assertion,
51                                           PolicyAsserter policyAsserter,
52                                           boolean asserted) {
53          super(assertion, asserted);
54          this.policyAsserter = policyAsserter;
55          if (this.policyAsserter == null) {
56              this.policyAsserter = new DummyPolicyAsserter();
57          }
58  
59          if (asserted) {
60              String namespace = getAssertion().getName().getNamespaceURI();
61              AbstractSymmetricAsymmetricBinding.ProtectionOrder protectionOrder =
62                  ((AbstractSymmetricAsymmetricBinding) getAssertion()).getProtectionOrder();
63              switch (protectionOrder) {  //NOPMD
64              case SignBeforeEncrypting:
65                  policyAsserter.assertPolicy(new QName(namespace, SPConstants.SIGN_BEFORE_ENCRYPTING));
66                  break;
67              case EncryptBeforeSigning:
68                  policyAsserter.assertPolicy(new QName(namespace, SPConstants.ENCRYPT_BEFORE_SIGNING));
69                  break;
70              }
71          }
72      }
73  
74      @Override
75      public SecurityEventConstants.Event[] getSecurityEventType() {
76          return new SecurityEventConstants.Event[]{
77                  SecurityEventConstants.SignedElement,
78                  WSSecurityEventConstants.SIGNED_PART,
79                  WSSecurityEventConstants.EncryptedElement,
80                  WSSecurityEventConstants.ENCRYPTED_PART,
81                  WSSecurityEventConstants.ContentEncrypted,
82          };
83      }
84  
85      @Override
86      public boolean assertEvent(SecurityEvent securityEvent) throws WSSPolicyException {
87          AbstractSymmetricAsymmetricBinding.ProtectionOrder protectionOrder =
88              ((AbstractSymmetricAsymmetricBinding) getAssertion()).getProtectionOrder();
89          SecurityEventConstants.Event event = securityEvent.getSecurityEventType();
90          if (WSSecurityEventConstants.SignedElement.equals(event)) {
91              SignedElementSecurityEvent signedElementSecurityEvent = (SignedElementSecurityEvent) securityEvent;
92              if (!signedElementSecurityEvent.isSigned()) {
93                  return true;
94              }
95              List<XMLSecurityConstants.ContentType> contentTypes = signedElementSecurityEvent.getProtectionOrder();
96              testProtectionOrder(protectionOrder, contentTypes, signedElementSecurityEvent.getElementPath());
97          } else if (WSSecurityEventConstants.SIGNED_PART.equals(event)) {
98              SignedPartSecurityEvent signedPartSecurityEvent = (SignedPartSecurityEvent) securityEvent;
99              if (!signedPartSecurityEvent.isSigned()) {
100                 return true;
101             }
102             List<XMLSecurityConstants.ContentType> contentTypes = signedPartSecurityEvent.getProtectionOrder();
103             testProtectionOrder(protectionOrder, contentTypes, signedPartSecurityEvent.getElementPath());
104         } else if (WSSecurityEventConstants.EncryptedElement.equals(event)) {
105             EncryptedElementSecurityEvent encryptedElementSecurityEvent = (EncryptedElementSecurityEvent) securityEvent;
106             if (!encryptedElementSecurityEvent.isEncrypted()) {
107                 return true;
108             }
109             List<XMLSecurityConstants.ContentType> contentTypes = encryptedElementSecurityEvent.getProtectionOrder();
110             testProtectionOrder(protectionOrder, contentTypes, encryptedElementSecurityEvent.getElementPath());
111         } else if (WSSecurityEventConstants.ENCRYPTED_PART.equals(event)) {
112             EncryptedPartSecurityEvent encryptedPartSecurityEvent = (EncryptedPartSecurityEvent) securityEvent;
113             if (!encryptedPartSecurityEvent.isEncrypted()) {
114                 return true;
115             }
116             List<XMLSecurityConstants.ContentType> contentTypes = encryptedPartSecurityEvent.getProtectionOrder();
117             testProtectionOrder(protectionOrder, contentTypes, encryptedPartSecurityEvent.getElementPath());
118         } else if (WSSecurityEventConstants.ContentEncrypted.equals(event)) {
119             ContentEncryptedElementSecurityEvent contentEncryptedElementSecurityEvent =
120                 (ContentEncryptedElementSecurityEvent) securityEvent;
121             if (!contentEncryptedElementSecurityEvent.isEncrypted()) {
122                 return true;
123             }
124             List<XMLSecurityConstants.ContentType> contentTypes = contentEncryptedElementSecurityEvent.getProtectionOrder();
125             testProtectionOrder(protectionOrder, contentTypes, contentEncryptedElementSecurityEvent.getElementPath());
126         }
127         return isAsserted();
128     }
129 
130     private void testProtectionOrder(AbstractSymmetricAsymmetricBinding.ProtectionOrder protectionOrder,
131                                      List<XMLSecurityConstants.ContentType> contentTypes, List<QName> elementPath) {
132         String namespace = getAssertion().getName().getNamespaceURI();
133 
134         switch (protectionOrder) {  //NOPMD
135             case SignBeforeEncrypting:
136                 int lastSignature = contentTypes.lastIndexOf(XMLSecurityConstants.ContentType.SIGNATURE);
137                 int firstEncryption = contentTypes.indexOf(XMLSecurityConstants.ContentType.ENCRYPTION);
138                 if (firstEncryption >= 0 && firstEncryption < lastSignature) {
139                     setAsserted(false);
140                     setErrorMessage("Policy enforces " + protectionOrder + " but the " + WSSUtils.pathAsString(elementPath)
141                         + " was encrypted and then signed");
142                     policyAsserter.unassertPolicy(new QName(namespace, SPConstants.SIGN_BEFORE_ENCRYPTING),
143                                                   getErrorMessage());
144                 } else {
145                     policyAsserter.assertPolicy(new QName(namespace, SPConstants.SIGN_BEFORE_ENCRYPTING));
146                 }
147                 break;
148             case EncryptBeforeSigning:
149                 int lastEncryption = contentTypes.lastIndexOf(XMLSecurityConstants.ContentType.ENCRYPTION);
150                 int firstSignature = contentTypes.indexOf(XMLSecurityConstants.ContentType.SIGNATURE);
151                 if (firstSignature >= 0 && firstSignature < lastEncryption) {
152                     setAsserted(false);
153                     setErrorMessage("Policy enforces " + protectionOrder + " but the " + WSSUtils.pathAsString(elementPath)
154                         + " was signed and then encrypted");
155                     policyAsserter.unassertPolicy(new QName(namespace, SPConstants.ENCRYPT_BEFORE_SIGNING),
156                                                   getErrorMessage());
157                 } else {
158                     policyAsserter.assertPolicy(new QName(namespace, SPConstants.ENCRYPT_BEFORE_SIGNING));
159                 }
160                 break;
161         }
162     }
163 }