1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 package org.apache.wss4j.dom.transform;
21
22 import java.io.ByteArrayInputStream;
23 import java.io.ByteArrayOutputStream;
24 import java.io.OutputStream;
25 import java.security.InvalidAlgorithmParameterException;
26 import java.security.spec.AlgorithmParameterSpec;
27 import java.util.Iterator;
28
29 import javax.xml.crypto.Data;
30 import javax.xml.crypto.MarshalException;
31 import javax.xml.crypto.NodeSetData;
32 import javax.xml.crypto.OctetStreamData;
33 import javax.xml.crypto.XMLCryptoContext;
34 import javax.xml.crypto.XMLStructure;
35 import javax.xml.crypto.dom.DOMCryptoContext;
36 import javax.xml.crypto.dsig.TransformException;
37 import javax.xml.crypto.dsig.TransformService;
38 import javax.xml.crypto.dsig.spec.TransformParameterSpec;
39
40 import org.apache.wss4j.common.bsp.BSPEnforcer;
41 import org.apache.wss4j.common.token.PKIPathSecurity;
42 import org.apache.wss4j.common.token.SecurityTokenReference;
43 import org.apache.wss4j.common.token.X509Security;
44 import org.apache.wss4j.common.util.XMLUtils;
45 import org.apache.wss4j.dom.WSConstants;
46 import org.apache.wss4j.dom.WSDocInfo;
47 import org.apache.xml.security.c14n.Canonicalizer;
48 import org.apache.xml.security.signature.XMLSignatureInput;
49 import org.apache.xml.security.signature.XMLSignatureStreamInput;
50 import org.w3c.dom.Document;
51 import org.w3c.dom.Element;
52 import org.w3c.dom.Node;
53
54
55
56
57
58 public class STRTransform extends TransformService {
59
60 public static final String TRANSFORM_URI =
61 "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-soap-message-security-1.0#STR-Transform";
62
63 public static final String TRANSFORM_WS_DOC_INFO = "transform_ws_doc_info";
64
65 private TransformParameterSpec params;
66
67 private Element transformElement;
68
69 private static final org.slf4j.Logger LOG =
70 org.slf4j.LoggerFactory.getLogger(STRTransform.class);
71
72 public final AlgorithmParameterSpec getParameterSpec() {
73 return params;
74 }
75
76 public void init(TransformParameterSpec params)
77 throws InvalidAlgorithmParameterException {
78 this.params = params;
79 }
80
81 public void init(XMLStructure parent, XMLCryptoContext context)
82 throws InvalidAlgorithmParameterException {
83 if (context != null && !(context instanceof DOMCryptoContext)) {
84 throw new ClassCastException("context must be of type DOMCryptoContext");
85 }
86 if (!(parent instanceof javax.xml.crypto.dom.DOMStructure)) {
87 throw new ClassCastException("parent must be of type DOMStructure");
88 }
89 transformElement = (Element)
90 ((javax.xml.crypto.dom.DOMStructure) parent).getNode();
91 }
92
93 public void marshalParams(XMLStructure parent, XMLCryptoContext context)
94 throws MarshalException {
95 if (context != null && !(context instanceof DOMCryptoContext)) {
96 throw new ClassCastException("context must be of type DOMCryptoContext");
97 }
98 if (!(parent instanceof javax.xml.crypto.dom.DOMStructure)) {
99 throw new ClassCastException("parent must be of type DOMStructure");
100 }
101 Element transformElement2 = (Element)
102 ((javax.xml.crypto.dom.DOMStructure) parent).getNode();
103 appendChild(transformElement2, transformElement);
104 transformElement = transformElement2;
105 }
106
107
108 public Data transform(Data data, XMLCryptoContext xc)
109 throws TransformException {
110 if (data == null) {
111 throw new NullPointerException("data must not be null");
112 }
113 return transformIt(data, xc, null);
114 }
115
116 public Data transform(Data data, XMLCryptoContext xc, OutputStream os)
117 throws TransformException {
118 if (data == null) {
119 throw new NullPointerException("data must not be null");
120 }
121 if (os == null) {
122 throw new NullPointerException("output stream must not be null");
123 }
124 return transformIt(data, xc, os);
125 }
126
127
128 private Data transformIt(Data data, XMLCryptoContext xc, OutputStream os)
129 throws TransformException {
130
131
132
133
134
135 String canonAlgo = null;
136 Element transformParams = XMLUtils.getDirectChildElement(
137 transformElement, "TransformationParameters", WSConstants.WSSE_NS
138 );
139 if (transformParams != null) {
140 Element canonElem =
141 XMLUtils.getDirectChildElement(
142 transformParams, "CanonicalizationMethod", WSConstants.SIG_NS
143 );
144 canonAlgo = canonElem.getAttributeNS(null, "Algorithm");
145 }
146 try {
147
148
149
150 Element str = null;
151 if (data instanceof NodeSetData) {
152 NodeSetData nodeSetData = (NodeSetData)data;
153 Iterator<?> iterator = nodeSetData.iterator();
154 while (iterator.hasNext()) {
155 Node node = (Node)iterator.next();
156 if (node instanceof Element && "SecurityTokenReference".equals(node.getLocalName())) {
157 str = (Element)node;
158 break;
159 }
160 }
161 } else {
162 try {
163 XMLSignatureInput xmlSignatureInput =
164 new XMLSignatureStreamInput(((OctetStreamData)data).getOctetStream());
165 str = (Element)xmlSignatureInput.getSubNode();
166 } catch (Exception ex) {
167 throw new TransformException(ex);
168 }
169 }
170 if (str == null) {
171 throw new TransformException("No SecurityTokenReference found");
172 }
173
174
175
176
177 SecurityTokenReference secRef = new SecurityTokenReference(str, new BSPEnforcer());
178
179 Canonicalizer canon = Canonicalizer.getInstance(canonAlgo);
180
181
182
183
184 Object wsDocInfoObject = xc.getProperty(TRANSFORM_WS_DOC_INFO);
185 WSDocInfo wsDocInfo = null;
186 if (wsDocInfoObject instanceof WSDocInfo) {
187 wsDocInfo = (WSDocInfo)wsDocInfoObject;
188 }
189 if (wsDocInfo == null) {
190 LOG.debug("STRTransform: no WSDocInfo found");
191 }
192
193 Document doc = str.getOwnerDocument();
194 Element dereferencedToken =
195 STRTransformUtil.dereferenceSTR(doc, secRef, wsDocInfo);
196
197 if (dereferencedToken != null) {
198 String type = dereferencedToken.getAttributeNS(null, "ValueType");
199 if (X509Security.X509_V3_TYPE.equals(type)
200 || PKIPathSecurity.getType().equals(type)) {
201
202
203
204 XMLUtils.setNamespace(
205 dereferencedToken, WSConstants.WSSE_NS, WSConstants.WSSE_PREFIX
206 );
207 XMLUtils.setNamespace(
208 dereferencedToken, WSConstants.WSU_NS, WSConstants.WSU_PREFIX
209 );
210 }
211 }
212
213
214
215
216 if (os != null) {
217 canon.canonicalizeSubtree(dereferencedToken, "#default", true, os);
218 return null;
219 }
220
221 try (ByteArrayOutputStream writer = new ByteArrayOutputStream()) {
222 canon.canonicalizeSubtree(dereferencedToken, "#default", true, writer);
223 return new OctetStreamData(new ByteArrayInputStream(writer.toByteArray()));
224 }
225 } catch (Exception ex) {
226 throw new TransformException(ex);
227 }
228 }
229
230
231 public final boolean isFeatureSupported(String feature) {
232 if (feature == null) {
233 throw new NullPointerException();
234 } else {
235 return false;
236 }
237 }
238
239 private static void appendChild(Node parent, Node child) {
240 Document ownerDoc = null;
241 if (parent.getNodeType() == Node.DOCUMENT_NODE) {
242 ownerDoc = (Document)parent;
243 } else {
244 ownerDoc = parent.getOwnerDocument();
245 }
246 if (child.getOwnerDocument() != ownerDoc) {
247 parent.appendChild(ownerDoc.importNode(child, true));
248 } else {
249 parent.appendChild(child);
250 }
251 }
252
253 }