1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.apache.wss4j.stax.impl.processor.input;
20
21 import java.lang.reflect.InvocationTargetException;
22 import java.util.ArrayDeque;
23 import java.util.Deque;
24
25 import javax.xml.namespace.QName;
26 import javax.xml.stream.XMLStreamConstants;
27 import javax.xml.stream.XMLStreamException;
28
29 import org.apache.wss4j.common.bsp.BSPRule;
30 import org.apache.wss4j.common.ext.WSSecurityException;
31 import org.apache.wss4j.stax.ext.WSInboundSecurityContext;
32 import org.apache.wss4j.stax.ext.WSSConstants;
33 import org.apache.wss4j.stax.ext.WSSSecurityProperties;
34 import org.apache.wss4j.stax.securityEvent.NoSecuritySecurityEvent;
35 import org.apache.wss4j.stax.utils.WSSUtils;
36 import org.apache.xml.security.exceptions.XMLSecurityException;
37 import org.apache.xml.security.stax.config.SecurityHeaderHandlerMapper;
38 import org.apache.xml.security.stax.ext.AbstractInputProcessor;
39 import org.apache.xml.security.stax.ext.InputProcessorChain;
40 import org.apache.xml.security.stax.ext.XMLSecurityHeaderHandler;
41 import org.apache.xml.security.stax.ext.XMLSecurityProperties;
42 import org.apache.xml.security.stax.ext.stax.XMLSecEndElement;
43 import org.apache.xml.security.stax.ext.stax.XMLSecEvent;
44 import org.apache.xml.security.stax.ext.stax.XMLSecStartElement;
45 import org.apache.xml.security.stax.impl.processor.input.XMLEventReaderInputProcessor;
46 import org.apache.xml.security.stax.impl.util.IDGenerator;
47
48
49
50
51
52 public class SecurityHeaderInputProcessor extends AbstractInputProcessor {
53
54 protected static final org.slf4j.Logger LOG =
55 org.slf4j.LoggerFactory.getLogger(SecurityHeaderInputProcessor.class);
56
57 private final ArrayDeque<XMLSecEvent> xmlSecEventList = new ArrayDeque<>();
58 private int startIndexForProcessor;
59
60 public SecurityHeaderInputProcessor(WSSSecurityProperties securityProperties) {
61 super(securityProperties);
62 setPhase(WSSConstants.Phase.POSTPROCESSING);
63 }
64
65 @Override
66 public XMLSecEvent processHeaderEvent(InputProcessorChain inputProcessorChain)
67 throws XMLStreamException, XMLSecurityException {
68 return null;
69 }
70
71 @Override
72 public XMLSecEvent processEvent(InputProcessorChain inputProcessorChain)
73 throws XMLStreamException, XMLSecurityException {
74
75
76 final InputProcessorChain subInputProcessorChain = inputProcessorChain.createSubChain(this);
77 final InternalSecurityHeaderBufferProcessor internalSecurityHeaderBufferProcessor
78 = new InternalSecurityHeaderBufferProcessor(getSecurityProperties());
79 subInputProcessorChain.addProcessor(internalSecurityHeaderBufferProcessor);
80
81 boolean responsibleSecurityHeaderFound = false;
82 boolean timestampFound = false;
83
84 XMLSecEvent xmlSecEvent;
85 do {
86 subInputProcessorChain.reset();
87 xmlSecEvent = subInputProcessorChain.processHeaderEvent();
88
89 switch (xmlSecEvent.getEventType()) {
90 case XMLStreamConstants.START_ELEMENT:
91 XMLSecStartElement xmlSecStartElement = xmlSecEvent.asStartElement();
92 int documentLevel = xmlSecStartElement.getDocumentLevel();
93
94 if (documentLevel == 1) {
95 if (WSSUtils.getSOAPMessageVersionNamespace(xmlSecStartElement) == null) {
96 throw new WSSecurityException(WSSecurityException.ErrorCode.INVALID_SECURITY, "notASOAPMessage");
97 }
98 } else if (documentLevel == 3
99 && xmlSecStartElement.getName().equals(WSSConstants.TAG_WSSE_SECURITY)
100 && WSSUtils.isInSOAPHeader(xmlSecStartElement)) {
101
102 if (!WSSUtils.isResponsibleActorOrRole(xmlSecStartElement,
103 ((WSSSecurityProperties) getSecurityProperties()).getActor())) {
104 continue;
105 }
106 responsibleSecurityHeaderFound = true;
107
108 } else if (documentLevel == 4 && responsibleSecurityHeaderFound
109 && WSSUtils.isInSecurityHeader(xmlSecStartElement,
110 ((WSSSecurityProperties) getSecurityProperties()).getActor())) {
111 startIndexForProcessor = xmlSecEventList.size() - 1;
112
113
114
115
116 if (WSSConstants.TAG_xenc_EncryptedData.equals(xmlSecStartElement.getName())) {
117 engageSecurityHeaderHandler(subInputProcessorChain, getSecurityProperties(),
118 xmlSecEventList, startIndexForProcessor, xmlSecStartElement.getName());
119 }
120 } else if (documentLevel == 5 && responsibleSecurityHeaderFound
121 && WSSUtils.isInSecurityHeader(xmlSecStartElement,
122 ((WSSSecurityProperties) getSecurityProperties()).getActor())
123 && WSSConstants.TAG_xenc_EncryptedData.equals(xmlSecStartElement.getName())) {
124 startIndexForProcessor = xmlSecEventList.size() - 1;
125
126
127
128 engageSecurityHeaderHandler(subInputProcessorChain, getSecurityProperties(),
129 xmlSecEventList, startIndexForProcessor, xmlSecStartElement.getName());
130 }
131 break;
132 case XMLStreamConstants.END_ELEMENT:
133 XMLSecEndElement xmlSecEndElement = xmlSecEvent.asEndElement();
134 documentLevel = xmlSecEndElement.getDocumentLevel();
135 if (documentLevel == 3 && responsibleSecurityHeaderFound
136 && xmlSecEndElement.getName().equals(WSSConstants.TAG_WSSE_SECURITY)) {
137
138 return finalizeHeaderProcessing(
139 inputProcessorChain, subInputProcessorChain,
140 internalSecurityHeaderBufferProcessor, xmlSecEventList);
141
142 } else if (documentLevel == 4 && responsibleSecurityHeaderFound
143 && WSSUtils.isInSecurityHeader(xmlSecEndElement,
144 ((WSSSecurityProperties) getSecurityProperties()).getActor())) {
145
146
147
148 if (!WSSConstants.TAG_xenc_EncryptedData.equals(xmlSecEndElement.getName())) {
149 engageSecurityHeaderHandler(subInputProcessorChain, getSecurityProperties(),
150 xmlSecEventList, startIndexForProcessor, xmlSecEndElement.getName());
151 }
152
153
154 if (xmlSecEndElement.getName().equals(WSSConstants.TAG_WSU_TIMESTAMP)) {
155 if (timestampFound) {
156 WSInboundSecurityContext context =
157 (WSInboundSecurityContext)subInputProcessorChain.getSecurityContext();
158 context.handleBSPRule(BSPRule.R3227);
159 }
160 timestampFound = true;
161 }
162 }
163 break;
164 }
165
166 } while (!(xmlSecEvent.getEventType() == XMLStreamConstants.START_ELEMENT
167 && xmlSecEvent.asStartElement().getName().getLocalPart().equals(WSSConstants.TAG_SOAP_BODY_LN)
168 && xmlSecEvent.asStartElement().getName().getNamespaceURI().equals(
169 WSSUtils.getSOAPMessageVersionNamespace(xmlSecEvent.asStartElement()))
170 ));
171
172
173 NoSecuritySecurityEvent noSecuritySecurityEvent = new NoSecuritySecurityEvent();
174 noSecuritySecurityEvent.setCorrelationID(IDGenerator.generateID(null));
175 inputProcessorChain.getSecurityContext().registerSecurityEvent(noSecuritySecurityEvent);
176
177 return finalizeHeaderProcessing(
178 inputProcessorChain, subInputProcessorChain,
179 internalSecurityHeaderBufferProcessor, xmlSecEventList);
180 }
181
182 private XMLSecEvent finalizeHeaderProcessing(
183 InputProcessorChain originalInputProcessorChain,
184 InputProcessorChain subInputProcessorChain,
185 InternalSecurityHeaderBufferProcessor internalSecurityHeaderBufferProcessor,
186 Deque<XMLSecEvent> xmlSecEventList) {
187
188 subInputProcessorChain.removeProcessor(internalSecurityHeaderBufferProcessor);
189 subInputProcessorChain.addProcessor(
190 new InternalSecurityHeaderReplayProcessor(getSecurityProperties()));
191
192
193 subInputProcessorChain.removeProcessor(this);
194
195
196 originalInputProcessorChain.getProcessors().clear();
197 originalInputProcessorChain.getProcessors().addAll(subInputProcessorChain.getProcessors());
198
199
200 return xmlSecEventList.pollLast();
201 }
202
203 @SuppressWarnings("unchecked")
204 private void engageSecurityHeaderHandler(InputProcessorChain inputProcessorChain,
205 XMLSecurityProperties securityProperties,
206 Deque<XMLSecEvent> eventQueue,
207 Integer index,
208 QName elementName)
209 throws WSSecurityException, XMLStreamException {
210
211 Class<XMLSecurityHeaderHandler> clazz =
212 (Class<XMLSecurityHeaderHandler>)SecurityHeaderHandlerMapper.getSecurityHeaderHandler(elementName);
213 if (clazz == null) {
214 LOG.warn("No matching handler found for " + elementName);
215 return;
216 }
217 try {
218 XMLSecurityHeaderHandler xmlSecurityHeaderHandler = clazz.getDeclaredConstructor().newInstance();
219 xmlSecurityHeaderHandler.handle(inputProcessorChain, securityProperties, eventQueue, index);
220 } catch (NoSuchMethodException | InvocationTargetException | InstantiationException | IllegalAccessException e) {
221 throw new WSSecurityException(WSSecurityException.ErrorCode.INVALID_SECURITY, e);
222 } catch (WSSecurityException e) {
223 throw e;
224 } catch (XMLSecurityException e) {
225 throw new WSSecurityException(WSSecurityException.ErrorCode.INVALID_SECURITY, e);
226 }
227 }
228
229
230
231
232 public class InternalSecurityHeaderBufferProcessor extends AbstractInputProcessor {
233
234 InternalSecurityHeaderBufferProcessor(XMLSecurityProperties securityProperties) {
235 super(securityProperties);
236 setPhase(WSSConstants.Phase.POSTPROCESSING);
237 addBeforeProcessor(SecurityHeaderInputProcessor.class.getName());
238 }
239
240 @Override
241 public XMLSecEvent processHeaderEvent(InputProcessorChain inputProcessorChain)
242 throws XMLStreamException, XMLSecurityException {
243 XMLSecEvent xmlSecEvent = inputProcessorChain.processHeaderEvent();
244 xmlSecEventList.push(xmlSecEvent);
245 return xmlSecEvent;
246 }
247
248 @Override
249 public XMLSecEvent processEvent(InputProcessorChain inputProcessorChain)
250 throws XMLStreamException, XMLSecurityException {
251
252 return null;
253 }
254 }
255
256
257
258
259 public class InternalSecurityHeaderReplayProcessor extends AbstractInputProcessor {
260
261 public InternalSecurityHeaderReplayProcessor(XMLSecurityProperties securityProperties) {
262 super(securityProperties);
263 setPhase(WSSConstants.Phase.PREPROCESSING);
264 addBeforeProcessor(SecurityHeaderInputProcessor.class.getName());
265 addAfterProcessor(XMLEventReaderInputProcessor.class.getName());
266 }
267
268 @Override
269 public XMLSecEvent processHeaderEvent(InputProcessorChain inputProcessorChain)
270 throws XMLStreamException, XMLSecurityException {
271 return null;
272 }
273
274 @Override
275 public XMLSecEvent processEvent(InputProcessorChain inputProcessorChain)
276 throws XMLStreamException, XMLSecurityException {
277
278 if (!xmlSecEventList.isEmpty()) {
279 return xmlSecEventList.pollLast();
280 } else {
281 inputProcessorChain.removeProcessor(this);
282 return inputProcessorChain.processEvent();
283 }
284 }
285 }
286 }