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
20 /*
21 * XSEC
22 *
23 * XSECSOAPRequestorSimple := (Very) Basic implementation of a SOAP
24 * HTTP wrapper for testing the client code.
25 *
26 *
27 * $Id: XSECSOAPRequestorSimple.cpp 1833341 2018-06-11 16:25:41Z scantor $
28 *
29 */
30
31 #include <xsec/framework/XSECError.hpp>
32 #include <xsec/utils/XSECSafeBuffer.hpp>
33 #include <xsec/utils/XSECSOAPRequestorSimple.hpp>
34 #include <xsec/xkms/XKMSConstants.hpp>
35
36 #ifdef XSEC_XKMS_ENABLED
37
38 #include "XSECAutoPtr.hpp"
39 #include "XSECDOMUtils.hpp"
40
41 #include <stdio.h>
42 #include <string.h>
43 #include <stdlib.h>
44
45 #include <xercesc/dom/DOM.hpp>
46 #include <xercesc/parsers/XercesDOMParser.hpp>
47 #include <xercesc/framework/XMLFormatter.hpp>
48 #include <xercesc/framework/MemBufFormatTarget.hpp>
49 #include <xercesc/util/PlatformUtils.hpp>
50 #include <xercesc/util/XMLNetAccessor.hpp>
51 #include <xercesc/util/XMLString.hpp>
52 #include <xercesc/util/XMLExceptMsgs.hpp>
53 #include <xercesc/util/Janitor.hpp>
54 #include <xercesc/util/XMLUniDefs.hpp>
55 #include <xercesc/framework/MemBufInputSource.hpp>
56
57 XERCES_CPP_NAMESPACE_USE
58
59 // --------------------------------------------------------------------------------
60 // Strings for constructing SOAP envelopes
61 // --------------------------------------------------------------------------------
62
63 static XMLCh s_prefix[] = {
64
65 chLatin_e,
66 chLatin_n,
67 chLatin_v,
68 chNull
69 };
70
71 static XMLCh s_Envelope[] = {
72
73 chLatin_E,
74 chLatin_n,
75 chLatin_v,
76 chLatin_e,
77 chLatin_l,
78 chLatin_o,
79 chLatin_p,
80 chLatin_e,
81 chNull
82 };
83
84 static XMLCh s_Body[] = {
85
86 chLatin_B,
87 chLatin_o,
88 chLatin_d,
89 chLatin_y,
90 chNull
91 };
92
93 // --------------------------------------------------------------------------------
94 // Constructors and Destructors
95 // --------------------------------------------------------------------------------
96
97
98 /* NOTE: This is initialised via the platform specific code */
99
~XSECSOAPRequestorSimple()100 XSECSOAPRequestorSimple::~XSECSOAPRequestorSimple() {
101 }
102
103
104 // --------------------------------------------------------------------------------
105 // Wrap and serialise the request message
106 // --------------------------------------------------------------------------------
107
wrapAndSerialise(DOMDocument * request)108 char * XSECSOAPRequestorSimple::wrapAndSerialise(DOMDocument * request) {
109
110 // Prepare the serialiser
111
112 XMLCh tempStr[100];
113 XMLString::transcode("Core", tempStr, 99);
114 DOMImplementation *impl = DOMImplementationRegistry::getDOMImplementation(tempStr);
115 DOMLSSerializer *theSerializer = ((DOMImplementationLS*)impl)->createLSSerializer();
116 Janitor<DOMLSSerializer> j_theSerializer(theSerializer);
117
118 // Get the config so we can set up pretty printing
119 DOMConfiguration *dc = theSerializer->getDomConfig();
120 dc->setParameter(XMLUni::fgDOMWRTFormatPrettyPrint, false);
121
122 // Now create an output object to format to UTF-8
123 DOMLSOutput *theOutput = ((DOMImplementationLS*)impl)->createLSOutput();
124 Janitor<DOMLSOutput> j_theOutput(theOutput);
125 MemBufFormatTarget *formatTarget = new MemBufFormatTarget;
126 Janitor<MemBufFormatTarget> j_formatTarget(formatTarget);
127
128 theOutput->setEncoding(MAKE_UNICODE_STRING("UTF-8"));
129 theOutput->setByteStream(formatTarget);
130
131 if (m_envelopeType != ENVELOPE_NONE) {
132
133 // Create a new document to wrap the request in
134 safeBuffer str;
135
136 makeQName(str, s_prefix, s_Envelope);
137
138 DOMDocument *doc;
139
140 if (m_envelopeType == ENVELOPE_SOAP11) {
141 doc = impl->createDocument(
142 XKMSConstants::s_unicodeStrURISOAP11,
143 str.rawXMLChBuffer(),
144 NULL);
145 DOMElement *rootElem = doc->getDocumentElement();
146
147 makeQName(str, s_prefix, s_Body);
148 DOMElement *body = doc->createElementNS(
149 XKMSConstants::s_unicodeStrURISOAP11,
150 str.rawXMLChBuffer());
151
152 rootElem->appendChild(body);
153
154 // Now replicate the request into the document
155 DOMElement * reqElement = (DOMElement *) doc->importNode(request->getDocumentElement(), true);
156 body->appendChild(reqElement);
157 }
158 else {
159 doc = impl->createDocument(
160 XKMSConstants::s_unicodeStrURISOAP12,
161 str.rawXMLChBuffer(),
162 NULL);
163 DOMElement *rootElem = doc->getDocumentElement();
164
165 makeQName(str, s_prefix, s_Body);
166 DOMElement *body = doc->createElementNS(
167 XKMSConstants::s_unicodeStrURISOAP12,
168 str.rawXMLChBuffer());
169
170 rootElem->appendChild(body);
171
172 // Now replicate the request into the document
173 DOMElement * reqElement = (DOMElement *) doc->importNode(request->getDocumentElement(), true);
174 body->appendChild(reqElement);
175 }
176
177
178 // OK - Now we have the SOAP request as a document, we serialise to a string buffer
179 // and return
180
181 theSerializer->write(doc, theOutput);
182 doc->release();
183
184 }
185 else {
186 theSerializer->write(request, theOutput);
187 }
188
189 // Now replicate the buffer
190 return XMLString::replicate((const char *) formatTarget->getRawBuffer());
191
192 }
193
194 // --------------------------------------------------------------------------------
195 // UnWrap and de-serialise the response message
196 // --------------------------------------------------------------------------------
197
parseAndUnwrap(const char * buf,unsigned int len)198 DOMDocument * XSECSOAPRequestorSimple::parseAndUnwrap(const char * buf, unsigned int len) {
199
200 XercesDOMParser parser;
201 parser.setDoNamespaces(true);
202 parser.setLoadExternalDTD(false);
203
204 SecurityManager securityManager;
205 securityManager.setEntityExpansionLimit(XSEC_ENTITY_EXPANSION_LIMIT);
206 parser.setSecurityManager(&securityManager);
207
208 // Create an input source
209
210 MemBufInputSource memIS((const XMLByte*) buf, len, "XSECMem");
211
212 parser.parse(memIS);
213 XMLSize_t errorCount = parser.getErrorCount();
214 if (errorCount > 0)
215 throw XSECException(XSECException::HTTPURIInputStreamError,
216 "Error parsing response message");
217
218 if (m_envelopeType == ENVELOPE_NONE) {
219
220 return parser.adoptDocument();
221
222 }
223
224 DOMDocument * responseDoc = parser.getDocument();
225
226 // Must be a SOAP message of some kind - so lets remove the wrapper.
227 // First create a new document for the Response message
228
229 XMLCh tempStr[100];
230 XMLString::transcode("Core", tempStr, 99);
231 DOMImplementation *impl = DOMImplementationRegistry::getDOMImplementation(tempStr);
232
233 DOMDocument * retDoc = impl->createDocument();
234
235 // Find the base of the response
236
237
238 DOMNode * e = responseDoc->getDocumentElement();
239
240 e = e->getFirstChild();
241
242 while (e != NULL && (e->getNodeType() != DOMNode::ELEMENT_NODE || !strEquals(e->getLocalName(), "Body")))
243 e = e->getNextSibling();
244
245 if (e == NULL)
246 throw XSECException(XSECException::HTTPURIInputStreamError,
247 "Could not find SOAP body");
248
249 e = findFirstChildOfType(e, DOMNode::ELEMENT_NODE);
250
251 if (e == NULL)
252 throw XSECException(XSECException::HTTPURIInputStreamError,
253 "Could not find message within SOAP body");
254
255 /* See if this is a soap fault */
256 if (strEquals(e->getLocalName(), "Fault")) {
257
258 // Something has gone wrong somewhere!
259 safeBuffer sb;
260 sb.sbTranscodeIn("SOAP Fault : ");
261
262 // Find the fault code
263
264 e = findFirstElementChild(e);
265 while (e != NULL && !strEquals(e->getLocalName(), "Code"))
266 e = findNextElementChild(e);
267
268 if (e != NULL) {
269 DOMNode * c = findFirstElementChild(e);
270 while (c != NULL && !strEquals(c->getLocalName(), "Value"))
271 c = findNextElementChild(c);
272 if (c != NULL) {
273 DOMNode * t = findFirstChildOfType(c, DOMNode::TEXT_NODE);
274 if (t != NULL) {
275 sb.sbXMLChCat(t->getNodeValue());
276 sb.sbXMLChCat(" : ");
277 }
278 }
279 }
280
281 // Find the reason
282 while (e != NULL && !strEquals(e->getLocalName(), "Reason"))
283 e = findNextElementChild(e);
284
285 if (e != NULL) {
286 DOMNode * t = findFirstChildOfType(e, DOMNode::TEXT_NODE);
287 if (t != NULL) {
288 sb.sbXMLChCat(t->getNodeValue());
289 }
290
291 }
292
293 retDoc->release();
294
295 XSECAutoPtrChar msg(sb.rawXMLChBuffer());
296
297 throw XSECException(XSECException::HTTPURIInputStreamError,
298 msg.get());
299 }
300
301
302 retDoc->appendChild(retDoc->importNode(e, true));
303
304 return retDoc;
305
306 }
307
308 // --------------------------------------------------------------------------------
309 // Envelope Type handling
310 // --------------------------------------------------------------------------------
311
setEnvelopeType(envelopeType et)312 void XSECSOAPRequestorSimple::setEnvelopeType(envelopeType et) {
313
314 m_envelopeType = et;
315
316 }
317
318 #endif /* XSEC_XKMS_ENABLED */
319