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.output;
20
21 import org.apache.wss4j.common.ext.WSSecurityException;
22 import org.apache.wss4j.stax.ext.WSSConstants;
23 import org.apache.wss4j.stax.ext.WSSSecurityProperties;
24 import org.apache.wss4j.stax.impl.SecurityHeaderOrder;
25 import org.apache.wss4j.stax.securityToken.WSSecurityTokenConstants;
26 import org.apache.wss4j.stax.utils.WSSUtils;
27 import org.apache.xml.security.exceptions.XMLSecurityException;
28 import org.apache.xml.security.stax.ext.OutputProcessorChain;
29 import org.apache.xml.security.stax.ext.XMLSecurityConstants;
30 import org.apache.xml.security.stax.ext.stax.XMLSecAttribute;
31 import org.apache.xml.security.stax.ext.stax.XMLSecEvent;
32 import org.apache.xml.security.stax.ext.stax.XMLSecStartElement;
33 import org.apache.xml.security.stax.impl.SignaturePartDef;
34 import org.apache.xml.security.stax.impl.algorithms.SignatureAlgorithm;
35 import org.apache.xml.security.stax.impl.processor.output.AbstractSignatureEndingOutputProcessor;
36 import org.apache.xml.security.stax.impl.util.IDGenerator;
37 import org.apache.xml.security.stax.securityEvent.SignatureValueSecurityEvent;
38 import org.apache.xml.security.stax.securityToken.OutboundSecurityToken;
39
40 import javax.xml.stream.XMLStreamConstants;
41 import javax.xml.stream.XMLStreamException;
42
43 import java.security.cert.X509Certificate;
44 import java.security.Key;
45 import java.util.*;
46
47 public class WSSSignatureEndingOutputProcessor extends AbstractSignatureEndingOutputProcessor {
48
49 private SignedInfoProcessor signedInfoProcessor;
50
51 public WSSSignatureEndingOutputProcessor(WSSSignatureOutputProcessor signatureOutputProcessor) throws XMLSecurityException {
52 super(signatureOutputProcessor);
53 this.addAfterProcessor(WSSSignatureOutputProcessor.class);
54 this.addAfterProcessor(UsernameTokenOutputProcessor.class);
55 }
56
57 @Override
58 protected SignedInfoProcessor newSignedInfoProcessor(
59 SignatureAlgorithm signatureAlgorithm, String signatureId, XMLSecStartElement xmlSecStartElement,
60 OutputProcessorChain outputProcessorChain) throws XMLSecurityException {
61
62
63 while (!WSSConstants.TAG_WSSE_SECURITY.equals(xmlSecStartElement.getName())) {
64 xmlSecStartElement = xmlSecStartElement.getParentXMLSecStartElement();
65 }
66
67 this.signedInfoProcessor = new SignedInfoProcessor(signatureAlgorithm, signatureId, xmlSecStartElement);
68 this.signedInfoProcessor.setXMLSecurityProperties(getSecurityProperties());
69 this.signedInfoProcessor.setAction(getAction(), getActionOrder());
70 this.signedInfoProcessor.addAfterProcessor(WSSSignatureEndingOutputProcessor.class);
71 this.signedInfoProcessor.init(outputProcessorChain);
72 return this.signedInfoProcessor;
73 }
74
75 @Override
76 public void processHeaderEvent(OutputProcessorChain outputProcessorChain) throws XMLStreamException, XMLSecurityException {
77 super.processHeaderEvent(outputProcessorChain);
78
79 SignatureValueSecurityEvent signatureValueSecurityEvent = new SignatureValueSecurityEvent();
80 signatureValueSecurityEvent.setSignatureValue(this.signedInfoProcessor.getSignatureValue());
81 signatureValueSecurityEvent.setCorrelationID(this.signedInfoProcessor.getSignatureId());
82 outputProcessorChain.getSecurityContext().registerSecurityEvent(signatureValueSecurityEvent);
83 }
84
85 @Override
86 protected void createKeyInfoStructureForSignature(
87 OutputProcessorChain outputProcessorChain,
88 OutboundSecurityToken securityToken,
89 boolean useSingleCertificate)
90 throws XMLStreamException, XMLSecurityException {
91
92 if (securityToken.getCustomTokenReference() != null) {
93 outputDOMElement(securityToken.getCustomTokenReference(), outputProcessorChain);
94 return;
95 }
96
97 WSSecurityTokenConstants.KeyIdentifier keyIdentifier = null;
98 if (!getSecurityProperties().getSignatureKeyIdentifiers().isEmpty()) {
99 keyIdentifier = getSecurityProperties().getSignatureKeyIdentifiers().get(0);
100 }
101
102 X509Certificate[] x509Certificates = securityToken.getX509Certificates();
103
104 if (WSSecurityTokenConstants.KeyIdentifier_KeyValue.equals(keyIdentifier)) {
105 WSSUtils.createKeyValueTokenStructure(this, outputProcessorChain, x509Certificates);
106 } else {
107 boolean isSAMLToken = false;
108 List<XMLSecAttribute> attributes = new ArrayList<>(2);
109 attributes.add(createAttribute(WSSConstants.ATT_WSU_ID, IDGenerator.generateID(null)));
110 if (WSSecurityTokenConstants.SAML_10_TOKEN.equals(securityToken.getTokenType())
111 || WSSecurityTokenConstants.SAML_11_TOKEN.equals(securityToken.getTokenType())) {
112 attributes.add(createAttribute(WSSConstants.ATT_WSSE11_TOKEN_TYPE, WSSConstants.NS_SAML11_TOKEN_PROFILE_TYPE));
113 isSAMLToken = true;
114 } else if (WSSecurityTokenConstants.SAML_20_TOKEN.equals(securityToken.getTokenType())) {
115 attributes.add(createAttribute(WSSConstants.ATT_WSSE11_TOKEN_TYPE, WSSConstants.NS_SAML20_TOKEN_PROFILE_TYPE));
116 isSAMLToken = true;
117 } else if (WSSecurityTokenConstants.KERBEROS_TOKEN.equals(securityToken.getTokenType())) {
118 attributes.add(createAttribute(WSSConstants.ATT_WSSE11_TOKEN_TYPE, WSSConstants.NS_GSS_KERBEROS5_AP_REQ));
119 } else if (WSSecurityTokenConstants.EncryptedKeyToken.equals(securityToken.getTokenType())
120 || WSSecurityTokenConstants.KEYIDENTIFIER_ENCRYPTED_KEY_SHA1_IDENTIFIER.equals(keyIdentifier)
121 || WSSecurityTokenConstants.KeyIdentifier_EncryptedKey.equals(keyIdentifier)) {
122 attributes.add(createAttribute(WSSConstants.ATT_WSSE11_TOKEN_TYPE, WSSConstants.NS_WSS_ENC_KEY_VALUE_TYPE));
123 } else if (WSSecurityTokenConstants.KEYIDENTIFIER_SECURITY_TOKEN_DIRECT_REFERENCE.equals(keyIdentifier)
124 && !useSingleCertificate) {
125 attributes.add(createAttribute(WSSConstants.ATT_WSSE11_TOKEN_TYPE, WSSConstants.NS_X509_PKIPATH_V1));
126 }
127 createStartElementAndOutputAsEvent(outputProcessorChain, WSSConstants.TAG_WSSE_SECURITY_TOKEN_REFERENCE, false, attributes);
128
129 String tokenId = securityToken.getId();
130
131 if (isSAMLToken) {
132
133 WSSUtils.createSAMLKeyIdentifierStructure(this, outputProcessorChain, securityToken.getTokenType(), tokenId);
134 } else if (WSSecurityTokenConstants.KEYIDENTIFIER_ENCRYPTED_KEY_SHA1_IDENTIFIER.equals(keyIdentifier)) {
135 String identifier = securityToken.getSha1Identifier();
136 if (identifier != null) {
137 WSSUtils.createEncryptedKeySha1IdentifierStructure(this, outputProcessorChain, identifier);
138 } else {
139 Key key = securityToken.getSecretKey(getSecurityProperties().getSignatureAlgorithm());
140 WSSUtils.createEncryptedKeySha1IdentifierStructure(this, outputProcessorChain, key);
141 }
142 } else if (WSSecurityTokenConstants.KEYIDENTIFIER_KERBEROS_SHA1_IDENTIFIER.equals(keyIdentifier)) {
143 String identifier = securityToken.getSha1Identifier();
144 WSSUtils.createKerberosSha1IdentifierStructure(this, outputProcessorChain, identifier);
145 } else if (WSSecurityTokenConstants.EncryptedKeyToken.equals(securityToken.getTokenType())
146 || WSSecurityTokenConstants.KeyIdentifier_EncryptedKey.equals(keyIdentifier)) {
147 String id = securityToken.getId();
148 WSSUtils.createBSTReferenceStructure(this, outputProcessorChain, id, WSSConstants.NS_WSS_ENC_KEY_VALUE_TYPE, true);
149 } else if (WSSecurityTokenConstants.KeyIdentifier_IssuerSerial.equals(keyIdentifier)) {
150 WSSUtils.createX509IssuerSerialStructure(this, outputProcessorChain, x509Certificates);
151 } else if (WSSecurityTokenConstants.KeyIdentifier_SkiKeyIdentifier.equals(keyIdentifier)) {
152 WSSUtils.createX509SubjectKeyIdentifierStructure(this, outputProcessorChain, x509Certificates);
153 } else if (WSSecurityTokenConstants.KeyIdentifier_X509KeyIdentifier.equals(keyIdentifier)) {
154 WSSUtils.createX509KeyIdentifierStructure(this, outputProcessorChain, x509Certificates);
155 } else if (WSSecurityTokenConstants.KEYIDENTIFIER_THUMBPRINT_IDENTIFIER.equals(keyIdentifier)) {
156 WSSUtils.createThumbprintKeyIdentifierStructure(this, outputProcessorChain, x509Certificates);
157 } else if (WSSecurityTokenConstants.KEYIDENTIFIER_SECURITY_TOKEN_DIRECT_REFERENCE.equals(keyIdentifier)) {
158 String valueType;
159 boolean included = true;
160 if (WSSecurityTokenConstants.SAML_20_TOKEN.equals(securityToken.getTokenType())) {
161 valueType = null;
162 } else if (WSSecurityTokenConstants.KERBEROS_TOKEN.equals(securityToken.getTokenType())) {
163 valueType = WSSConstants.NS_GSS_KERBEROS5_AP_REQ;
164 } else if (WSSecurityTokenConstants.DerivedKeyToken.equals(securityToken.getTokenType())) {
165 boolean use200512Namespace = ((WSSSecurityProperties)getSecurityProperties()).isUse200512Namespace();
166 if (use200512Namespace) {
167 valueType = WSSConstants.NS_WSC_05_12 + "/dk";
168 } else {
169 valueType = WSSConstants.NS_WSC_05_02 + "/dk";
170 }
171 } else if (WSSecurityTokenConstants.SPNEGO_CONTEXT_TOKEN.equals(securityToken.getTokenType())
172 || WSSecurityTokenConstants.SECURITY_CONTEXT_TOKEN.equals(securityToken.getTokenType())
173 || WSSecurityTokenConstants.SECURE_CONVERSATION_TOKEN.equals(securityToken.getTokenType())) {
174 boolean use200512Namespace = ((WSSSecurityProperties)getSecurityProperties()).isUse200512Namespace();
175 if (use200512Namespace) {
176 valueType = WSSConstants.NS_WSC_05_12 + "/sct";
177 } else {
178 valueType = WSSConstants.NS_WSC_05_02 + "/sct";
179 }
180 included = ((WSSSecurityProperties)getSecurityProperties()).isIncludeSignatureToken();
181 } else {
182 if (useSingleCertificate) {
183 valueType = WSSConstants.NS_X509_V3_TYPE;
184 } else {
185 valueType = WSSConstants.NS_X509_PKIPATH_V1;
186 }
187 }
188 WSSUtils.createBSTReferenceStructure(this, outputProcessorChain, tokenId, valueType, included);
189 } else if (WSSecurityTokenConstants.KEYIDENTIFIER_EMBEDDED_KEY_IDENTIFIER_REF.equals(keyIdentifier)) {
190 WSSUtils.createEmbeddedKeyIdentifierStructure(this, outputProcessorChain, securityToken.getTokenType(), tokenId);
191 } else if (WSSecurityTokenConstants.KEYIDENTIFIER_USERNAME_TOKEN_REFERENCE.equals(keyIdentifier)) {
192 WSSUtils.createUsernameTokenReferenceStructure(this, outputProcessorChain, tokenId);
193 } else {
194 throw new WSSecurityException(WSSecurityException.ErrorCode.FAILED_SIGNATURE, "unsupportedSecurityToken",
195 new Object[] {keyIdentifier});
196 }
197 createEndElementAndOutputAsEvent(outputProcessorChain, WSSConstants.TAG_WSSE_SECURITY_TOKEN_REFERENCE);
198 }
199 }
200
201 @Override
202 protected void createTransformsStructureForSignature(OutputProcessorChain subOutputProcessorChain, SignaturePartDef signaturePartDef)
203 throws XMLStreamException, XMLSecurityException {
204 String[] transforms = signaturePartDef.getTransforms();
205 if (transforms != null && transforms.length > 0) {
206 createStartElementAndOutputAsEvent(subOutputProcessorChain, WSSConstants.TAG_dsig_Transforms, false, null);
207
208 if (WSSConstants.SOAPMESSAGE_NS10_STR_TRANSFORM.equals(transforms[0])) {
209 List<XMLSecAttribute> attributes = new ArrayList<>(1);
210 attributes.add(createAttribute(WSSConstants.ATT_NULL_Algorithm, transforms[0]));
211 createStartElementAndOutputAsEvent(subOutputProcessorChain, WSSConstants.TAG_dsig_Transform, false, attributes);
212 if (transforms.length >= 2) {
213 createStartElementAndOutputAsEvent(subOutputProcessorChain, WSSConstants.TAG_WSSE_TRANSFORMATION_PARAMETERS,
214 false, null);
215 attributes = new ArrayList<>(1);
216 attributes.add(createAttribute(WSSConstants.ATT_NULL_Algorithm, transforms[1]));
217 createStartElementAndOutputAsEvent(subOutputProcessorChain, WSSConstants.TAG_dsig_CanonicalizationMethod,
218 false, attributes);
219 createEndElementAndOutputAsEvent(subOutputProcessorChain, WSSConstants.TAG_dsig_CanonicalizationMethod);
220 createEndElementAndOutputAsEvent(subOutputProcessorChain, WSSConstants.TAG_WSSE_TRANSFORMATION_PARAMETERS);
221 }
222 createEndElementAndOutputAsEvent(subOutputProcessorChain, WSSConstants.TAG_dsig_Transform);
223 } else {
224 for (int i = 0; i < transforms.length; i++) {
225 String transform = transforms[i];
226
227 List<XMLSecAttribute> attributes = new ArrayList<>(1);
228 attributes.add(createAttribute(WSSConstants.ATT_NULL_Algorithm, transform));
229 createStartElementAndOutputAsEvent(subOutputProcessorChain, WSSConstants.TAG_dsig_Transform, false, attributes);
230
231 if (getSecurityProperties().isAddExcC14NInclusivePrefixes()
232 && !WSSConstants.SWA_ATTACHMENT_CONTENT_SIG_TRANS.equals(transform)
233 && !WSSConstants.SWA_ATTACHMENT_COMPLETE_SIG_TRANS.equals(transform)) {
234 attributes = new ArrayList<>(1);
235 attributes.add(createAttribute(XMLSecurityConstants.ATT_NULL_PrefixList,
236 signaturePartDef.getInclusiveNamespacesPrefixes()));
237 createStartElementAndOutputAsEvent(subOutputProcessorChain, XMLSecurityConstants.TAG_c14nExcl_InclusiveNamespaces,
238 true, attributes);
239 createEndElementAndOutputAsEvent(subOutputProcessorChain, XMLSecurityConstants.TAG_c14nExcl_InclusiveNamespaces);
240 }
241
242 createEndElementAndOutputAsEvent(subOutputProcessorChain, WSSConstants.TAG_dsig_Transform);
243 }
244 }
245 createEndElementAndOutputAsEvent(subOutputProcessorChain, WSSConstants.TAG_dsig_Transforms);
246 }
247 }
248
249 @Override
250 public void flushBufferAndCallbackAfterHeader(OutputProcessorChain outputProcessorChain,
251 Deque<XMLSecEvent> xmlSecEventDeque)
252 throws XMLStreamException, XMLSecurityException {
253
254 final String actor = ((WSSSecurityProperties) getSecurityProperties()).getActor();
255
256
257 loop:
258 while (!xmlSecEventDeque.isEmpty()) {
259 XMLSecEvent xmlSecEvent = xmlSecEventDeque.pop();
260 if (XMLStreamConstants.START_ELEMENT == xmlSecEvent.getEventType()
261 && WSSUtils.isSecurityHeaderElement(xmlSecEvent, actor)) {
262 OutputProcessorUtils.updateSecurityHeaderOrder(
263 outputProcessorChain, WSSConstants.TAG_dsig_Signature, getAction(), true);
264
265 List<SecurityHeaderOrder> securityHeaderOrderList =
266 outputProcessorChain.getSecurityContext().getAsList(SecurityHeaderOrder.class);
267 List<SecurityHeaderOrder> tmpList = null;
268 if (securityHeaderOrderList != null) {
269 tmpList = new ArrayList<>(securityHeaderOrderList);
270 securityHeaderOrderList.clear();
271 }
272
273 outputProcessorChain.reset();
274 outputProcessorChain.processEvent(xmlSecEvent);
275
276 if (securityHeaderOrderList != null) {
277 securityHeaderOrderList.addAll(tmpList);
278 }
279 break loop;
280 }
281 outputProcessorChain.reset();
282 outputProcessorChain.processEvent(xmlSecEvent);
283 }
284 super.flushBufferAndCallbackAfterHeader(outputProcessorChain, xmlSecEventDeque);
285 }
286 }