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.common.WSSPolicyException;
23  import org.apache.wss4j.policy.model.AbstractSecurityAssertion;
24  import org.apache.wss4j.policy.model.Header;
25  import org.apache.wss4j.policy.model.SignedParts;
26  import org.apache.xml.security.stax.securityEvent.SecurityEvent;
27  import org.apache.xml.security.stax.securityEvent.SecurityEventConstants;
28  import org.apache.wss4j.policy.stax.Assertable;
29  import org.apache.wss4j.policy.stax.DummyPolicyAsserter;
30  import org.apache.wss4j.policy.stax.PolicyAsserter;
31  import org.apache.wss4j.stax.ext.WSSConstants;
32  import org.apache.wss4j.stax.securityEvent.SignedPartSecurityEvent;
33  import org.apache.wss4j.stax.securityEvent.WSSecurityEventConstants;
34  import org.apache.wss4j.stax.utils.WSSUtils;
35  
36  import javax.xml.namespace.QName;
37  
38  import java.util.LinkedList;
39  import java.util.List;
40  
41  /**
42   * WSP1.3, 4.1.1 SignedParts Assertion
43   */
44  public class SignedPartsAssertionState extends AssertionState implements Assertable {
45  
46      private int attachmentCount;
47      private int signedAttachmentCount;
48      private boolean signedAttachmentRequired;
49      private PolicyAsserter policyAsserter;
50      private final boolean soap12;
51  
52      public SignedPartsAssertionState(
53          AbstractSecurityAssertion assertion, PolicyAsserter policyAsserter,
54          boolean asserted, int attachmentCount, boolean soap12
55      ) {
56          super(assertion, asserted);
57          this.attachmentCount = attachmentCount;
58  
59          this.policyAsserter = policyAsserter;
60          if (this.policyAsserter == null) {
61              this.policyAsserter = new DummyPolicyAsserter();
62          }
63  
64          if (asserted) {
65              policyAsserter.assertPolicy(getAssertion());
66          }
67  
68          this.soap12 = soap12;
69      }
70  
71      @Override
72      public SecurityEventConstants.Event[] getSecurityEventType() {
73          return new SecurityEventConstants.Event[]{
74                  WSSecurityEventConstants.SIGNED_PART
75          };
76      }
77  
78      @Override
79      public boolean assertEvent(SecurityEvent securityEvent) throws WSSPolicyException {
80  
81          SignedPartSecurityEvent signedPartSecurityEvent = (SignedPartSecurityEvent) securityEvent;
82          SignedParts signedParts = (SignedParts) getAssertion();
83  
84          if (signedParts.getAttachments() != null) {
85              signedAttachmentRequired = true;
86              if (signedPartSecurityEvent.isAttachment()) {
87                  signedAttachmentCount++;
88                  setAsserted(true);
89                  policyAsserter.assertPolicy(getAssertion());
90                  return true;
91              }
92          }
93  
94          List<QName> bodyPath = soap12 ? WSSConstants.SOAP_12_BODY_PATH : WSSConstants.SOAP_11_BODY_PATH;
95          if (signedParts.isBody()
96                  && WSSUtils.pathMatches(bodyPath, signedPartSecurityEvent.getElementPath())) {
97              if (signedPartSecurityEvent.isSigned()) {
98                  setAsserted(true);
99                  policyAsserter.assertPolicy(getAssertion());
100                 return true;
101             } else {
102                 setAsserted(false);
103                 setErrorMessage("Element " + WSSUtils.pathAsString(signedPartSecurityEvent.getElementPath()) + " must be signed");
104                 policyAsserter.unassertPolicy(getAssertion(), getErrorMessage());
105                 return false;
106             }
107         }
108         //body processed above. so this must be a header element
109         if (signedParts.isSignAllHeaders()) {
110             if (signedPartSecurityEvent.isSigned()) {
111                 setAsserted(true);
112                 policyAsserter.assertPolicy(getAssertion());
113                 return true;
114             } else {
115                 setAsserted(false);
116                 setErrorMessage("Element " + WSSUtils.pathAsString(signedPartSecurityEvent.getElementPath()) + " must be signed");
117                 policyAsserter.unassertPolicy(getAssertion(), getErrorMessage());
118                 return false;
119             }
120         } else {
121             for (int i = 0; i < signedParts.getHeaders().size(); i++) {
122                 Header header = signedParts.getHeaders().get(i);
123                 QName headerQName = new QName(header.getNamespace(), header.getName() == null ? "" : header.getName());
124 
125                 List<QName> headerPath = new LinkedList<>();
126                 if (soap12) {
127                     headerPath.addAll(WSSConstants.SOAP_12_HEADER_PATH);
128                 } else {
129                     headerPath.addAll(WSSConstants.SOAP_11_HEADER_PATH);
130                 }
131                 headerPath.add(headerQName);
132 
133                 if (WSSUtils.pathMatches(headerPath, signedPartSecurityEvent.getElementPath(), header.getName() == null)) {
134                     if (signedPartSecurityEvent.isSigned()) {
135                         setAsserted(true);
136                         policyAsserter.assertPolicy(getAssertion());
137                         return true;
138                     } else {
139                         setAsserted(false);
140                         setErrorMessage("Element " + WSSUtils.pathAsString(signedPartSecurityEvent.getElementPath()) + " must be signed");
141                         policyAsserter.unassertPolicy(getAssertion(), getErrorMessage());
142                         return false;
143                     }
144                 }
145             }
146         }
147 
148         //if we return false here other signed elements will trigger a PolicyViolationException
149         policyAsserter.assertPolicy(getAssertion());
150         return true;
151     }
152 
153     @Override
154     public boolean isAsserted() {
155         if (signedAttachmentRequired && signedAttachmentCount < attachmentCount) {
156             return false;
157         }
158         return super.isAsserted();
159     }
160 }