1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.apache.wss4j.policy.stax.enforcer;
20
21 import org.apache.wss4j.common.ext.WSSecurityException;
22 import org.apache.wss4j.common.WSSPolicyException;
23 import org.apache.wss4j.stax.ext.WSSConstants;
24 import org.apache.wss4j.stax.ext.WSSSecurityProperties;
25 import org.apache.wss4j.stax.impl.processor.input.SecurityHeaderInputProcessor;
26 import org.apache.wss4j.stax.securityEvent.EncryptedPartSecurityEvent;
27 import org.apache.wss4j.stax.securityEvent.RequiredElementSecurityEvent;
28 import org.apache.wss4j.stax.securityEvent.RequiredPartSecurityEvent;
29 import org.apache.wss4j.stax.securityEvent.SignedPartSecurityEvent;
30 import org.apache.wss4j.stax.utils.WSSUtils;
31 import org.apache.xml.security.exceptions.XMLSecurityException;
32 import org.apache.xml.security.stax.ext.*;
33 import org.apache.xml.security.stax.ext.stax.XMLSecEvent;
34 import org.apache.xml.security.stax.ext.stax.XMLSecStartElement;
35 import org.apache.xml.security.stax.securityEvent.ContentEncryptedElementSecurityEvent;
36 import org.apache.xml.security.stax.securityEvent.EncryptedElementSecurityEvent;
37 import org.apache.xml.security.stax.securityEvent.SignedElementSecurityEvent;
38
39 import javax.xml.namespace.QName;
40 import javax.xml.stream.XMLStreamConstants;
41 import javax.xml.stream.XMLStreamException;
42 import javax.xml.stream.events.Attribute;
43
44 import java.util.List;
45
46
47
48
49 public class PolicyInputProcessor extends AbstractInputProcessor {
50
51 private final PolicyEnforcer policyEnforcer;
52 private boolean initDone = false;
53 private boolean transportSecurityActive = false;
54
55 public PolicyInputProcessor(PolicyEnforcer policyEnforcer, XMLSecurityProperties securityProperties) {
56 super(securityProperties);
57 this.setPhase(WSSConstants.Phase.POSTPROCESSING);
58 this.addBeforeProcessor(SecurityHeaderInputProcessor.class.getName());
59 this.policyEnforcer = policyEnforcer;
60 }
61
62 @Override
63 public XMLSecEvent processHeaderEvent(InputProcessorChain inputProcessorChain) throws XMLStreamException, XMLSecurityException {
64 XMLSecEvent xmlSecEvent = inputProcessorChain.processHeaderEvent();
65
66 init(inputProcessorChain);
67
68
69 List<QName> elementPath = null;
70 if (!transportSecurityActive) {
71 elementPath = xmlSecEvent.getElementPath();
72 if (!inputProcessorChain.getDocumentContext().isInEncryptedContent()
73 && WSSUtils.isInSecurityHeader(xmlSecEvent, elementPath,
74 ((WSSSecurityProperties) getSecurityProperties()).getActor())) {
75 testEncryptionPolicy(xmlSecEvent, elementPath);
76 }
77 }
78 if (xmlSecEvent.getEventType() == XMLStreamConstants.START_ELEMENT) {
79 XMLSecStartElement xmlSecStartElement = xmlSecEvent.asStartElement();
80 if (elementPath == null) {
81 elementPath = xmlSecStartElement.getElementPath();
82 }
83 final int documentLevel = elementPath.size();
84 if (documentLevel == 3 && WSSUtils.isInSOAPHeader(elementPath)) {
85
86 RequiredPartSecurityEvent requiredPartSecurityEvent = new RequiredPartSecurityEvent();
87 requiredPartSecurityEvent.setElementPath(elementPath);
88 policyEnforcer.registerSecurityEvent(requiredPartSecurityEvent);
89 RequiredElementSecurityEvent requiredElementSecurityEvent = new RequiredElementSecurityEvent();
90 requiredElementSecurityEvent.setElementPath(elementPath);
91 policyEnforcer.registerSecurityEvent(requiredElementSecurityEvent);
92 } else if (documentLevel > 3) {
93
94 RequiredElementSecurityEvent requiredElementSecurityEvent = new RequiredElementSecurityEvent();
95 requiredElementSecurityEvent.setElementPath(elementPath);
96 policyEnforcer.registerSecurityEvent(requiredElementSecurityEvent);
97 }
98 }
99 return xmlSecEvent;
100 }
101
102 @Override
103 public XMLSecEvent processEvent(InputProcessorChain inputProcessorChain) throws XMLStreamException, XMLSecurityException {
104 XMLSecEvent xmlSecEvent = inputProcessorChain.processEvent();
105
106 List<QName> elementPath = null;
107 if (XMLStreamConstants.START_ELEMENT == xmlSecEvent.getEventType()) {
108 XMLSecStartElement xmlSecStartElement = xmlSecEvent.asStartElement();
109 int documentLevel = xmlSecStartElement.getDocumentLevel();
110
111 if (documentLevel > 3) {
112 RequiredElementSecurityEvent requiredElementSecurityEvent = new RequiredElementSecurityEvent();
113 elementPath = xmlSecStartElement.getElementPath();
114 requiredElementSecurityEvent.setElementPath(elementPath);
115 policyEnforcer.registerSecurityEvent(requiredElementSecurityEvent);
116 }
117 }
118
119
120
121
122 if (!transportSecurityActive) {
123 final DocumentContext documentContext = inputProcessorChain.getDocumentContext();
124 final boolean inEncryptedContent = documentContext.isInEncryptedContent();
125 final boolean inSignedContent = documentContext.isInSignedContent();
126 if (!inEncryptedContent || !inSignedContent) {
127 if (elementPath == null) {
128 elementPath = xmlSecEvent.getElementPath();
129 }
130 if (!inEncryptedContent
131 && !WSSUtils.isInSecurityHeader(xmlSecEvent, elementPath,
132 ((WSSSecurityProperties) getSecurityProperties()).getActor())) {
133 testEncryptionPolicy(xmlSecEvent, elementPath);
134 }
135
136
137
138 if (!inSignedContent) {
139 testSignaturePolicy(xmlSecEvent, elementPath);
140 }
141 }
142 }
143 return xmlSecEvent;
144 }
145
146 @Override
147 public void doFinal(InputProcessorChain inputProcessorChain) throws XMLStreamException, XMLSecurityException {
148 super.doFinal(inputProcessorChain);
149
150 try {
151 policyEnforcer.doFinal();
152 } catch (WSSPolicyException e) {
153 throw new WSSecurityException(WSSecurityException.ErrorCode.INVALID_SECURITY, e);
154 }
155 }
156
157 private void testSignaturePolicy(XMLSecEvent xmlSecEvent, List<QName> elementPath) throws WSSecurityException {
158 if (xmlSecEvent.getEventType() == XMLStreamConstants.START_ELEMENT) {
159 final int documentLevel = elementPath.size();
160 if (documentLevel == 3 && WSSUtils.isInSOAPHeader(elementPath)) {
161 SignedPartSecurityEvent signedPartSecurityEvent = new SignedPartSecurityEvent(null, false, null);
162 signedPartSecurityEvent.setElementPath(elementPath);
163 policyEnforcer.registerSecurityEvent(signedPartSecurityEvent);
164 } else if (documentLevel == 2 && WSSUtils.isInSOAPBody(elementPath)) {
165 SignedPartSecurityEvent signedPartSecurityEvent = new SignedPartSecurityEvent(null, false, null);
166 signedPartSecurityEvent.setElementPath(elementPath);
167 policyEnforcer.registerSecurityEvent(signedPartSecurityEvent);
168 } else if (documentLevel > 3) {
169 SignedElementSecurityEvent signedElementSecurityEvent = new SignedElementSecurityEvent(null, false, null);
170 signedElementSecurityEvent.setElementPath(elementPath);
171 policyEnforcer.registerSecurityEvent(signedElementSecurityEvent);
172 }
173 }
174 }
175
176 private void testEncryptionPolicy(XMLSecEvent xmlSecEvent, List<QName> elementPath) throws WSSecurityException {
177
178 switch (xmlSecEvent.getEventType()) {
179 case XMLStreamConstants.START_ELEMENT:
180 final int documentLevel = elementPath.size();
181 if (documentLevel == 3 && WSSUtils.isInSOAPHeader(elementPath)) {
182
183 EncryptedPartSecurityEvent encryptedPartSecurityEvent
184 = new EncryptedPartSecurityEvent(null, false, null);
185 encryptedPartSecurityEvent.setElementPath(elementPath);
186 policyEnforcer.registerSecurityEvent(encryptedPartSecurityEvent);
187 } else if (documentLevel == 3 && WSSUtils.isInSOAPBody(elementPath)) {
188
189
190
191
192 EncryptedPartSecurityEvent encryptedPartSecurityEvent
193 = new EncryptedPartSecurityEvent(null, false, null);
194 encryptedPartSecurityEvent.setElementPath(elementPath);
195 policyEnforcer.registerSecurityEvent(encryptedPartSecurityEvent);
196 } else if (documentLevel > 3) {
197
198 EncryptedElementSecurityEvent encryptedElementSecurityEvent
199 = new EncryptedElementSecurityEvent(null, false, null);
200 encryptedElementSecurityEvent.setCorrelationID(getId(xmlSecEvent));
201 encryptedElementSecurityEvent.setElementPath(elementPath);
202 policyEnforcer.registerSecurityEvent(encryptedElementSecurityEvent);
203
204
205 ContentEncryptedElementSecurityEvent contentEncryptedElementSecurityEvent
206 = new ContentEncryptedElementSecurityEvent(null, false, null);
207 contentEncryptedElementSecurityEvent.setElementPath(xmlSecEvent.getParentXMLSecStartElement().getElementPath());
208 policyEnforcer.registerSecurityEvent(contentEncryptedElementSecurityEvent);
209 }
210 break;
211 case XMLStreamConstants.CHARACTERS:
212 case XMLStreamConstants.ENTITY_REFERENCE:
213 case XMLStreamConstants.PROCESSING_INSTRUCTION:
214
215 ContentEncryptedElementSecurityEvent contentEncryptedElementSecurityEvent
216 = new ContentEncryptedElementSecurityEvent(null, false, null);
217 contentEncryptedElementSecurityEvent.setElementPath(xmlSecEvent.getElementPath());
218 policyEnforcer.registerSecurityEvent(contentEncryptedElementSecurityEvent);
219 break;
220 }
221 }
222
223 protected String getId(XMLSecEvent xmlSecEvent) {
224 XMLSecStartElement xmlSecStartElement = xmlSecEvent.asStartElement();
225 if (!xmlSecStartElement.getOnElementDeclaredAttributes().isEmpty()) {
226 Attribute attribute = xmlSecStartElement.getAttributeByName(WSSConstants.ATT_WSU_ID);
227 if (attribute != null) {
228 return attribute.getValue();
229 }
230 attribute = xmlSecStartElement.getAttributeByName(WSSConstants.ATT_NULL_Id);
231 if (attribute != null) {
232 return attribute.getValue();
233 }
234 attribute = xmlSecStartElement.getAttributeByName(WSSConstants.ATT_NULL_ID);
235 if (attribute != null) {
236 return attribute.getValue();
237 }
238 attribute = xmlSecStartElement.getAttributeByName(WSSConstants.ATT_NULL_ASSERTION_ID);
239 if (attribute != null) {
240 return attribute.getValue();
241 }
242 }
243 return null;
244 }
245
246 protected void init(InputProcessorChain inputProcessorChain) {
247 if (!this.initDone) {
248 this.initDone = true;
249 this.transportSecurityActive =
250 Boolean.TRUE.equals(inputProcessorChain.getSecurityContext().get(WSSConstants.TRANSPORT_SECURITY_ACTIVE));
251 inputProcessorChain.getSecurityContext().put(WSSConstants.PROP_ALLOW_RSA15_KEYTRANSPORT_ALGORITHM, Boolean.TRUE);
252 inputProcessorChain.getSecurityContext().put(WSSConstants.PROP_ALLOW_USERNAMETOKEN_NOPASSWORD, Boolean.TRUE.toString());
253 }
254 }
255 }