3 #include <libxml/parser.h>
4 #include <libxml/xpath.h>
5 #include <libxml/xpathInternals.h>
7 static const char *soap_mime_type
= "text/xml"; /* SOAP/1.1 requires text/xml */
8 /* DummyOperation response */
9 static const char *pong
= "<?xml version='1.0' encoding='utf-8'?><SOAP-ENV:Envelope xmlns:SOAP-ENV=\"http://schemas.xmlsoap.org/soap/envelope/\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\"><SOAP-ENV:Body><q:DummyOperationResponse xmlns:q=\"http://isds.czechpoint.cz/v20\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"><q:dmStatus><q:dmStatusCode>0000</q:dmStatusCode><q:dmStatusMessage>Provedeno úspěšně.</q:dmStatusMessage></q:dmStatus></q:DummyOperationResponse></SOAP-ENV:Body></SOAP-ENV:Envelope>";
11 /* Used to choose proper name space for message elements.
12 * See _isds_register_namespaces(). */
16 MESSAGE_NS_SIGNED_INCOMING
,
17 MESSAGE_NS_SIGNED_OUTGOING
,
18 MESSAGE_NS_SIGNED_DELIVERY
21 #define SOAP_NS "http://schemas.xmlsoap.org/soap/envelope/"
22 #define SOAP2_NS "http://www.w3.org/2003/05/soap-envelope"
23 #define ISDS1_NS "http://isds.czechpoint.cz"
24 #define ISDS_NS "http://isds.czechpoint.cz/v20"
25 #define SISDS_INCOMING_NS "http://isds.czechpoint.cz/v20/message"
26 #define SISDS_OUTGOING_NS "http://isds.czechpoint.cz/v20/SentMessage"
27 #define SISDS_DELIVERY_NS "http://isds.czechpoint.cz/v20/delivery"
28 #define SCHEMA_NS "http://www.w3.org/2001/XMLSchema"
29 #define DEPOSIT_NS "urn:uschovnaWSDL"
33 const char *end_point
;
35 void (*function
) (int, xmlDocPtr
, xmlXPathContextPtr
, xmlNodePtr
);
38 /* Parse and respond to DummyOperation */
39 static void service_DummyOperation(int socket
, const xmlDocPtr soap_request
,
40 xmlXPathContextPtr xpath_ctx
, xmlNodePtr isds_request
) {
41 http_send_response_200(socket
, pong
, strlen(pong
), soap_mime_type
);
45 /* List of implemented services */
46 static struct service services
[] = {
47 { "DS/dz", BAD_CAST
"DummyOperation", service_DummyOperation
},
51 /* Makes known all relevant namespaces to given XPath context
52 * @xpath_ctx is XPath context
53 * @message_ns selects proper message name space. Unsigned and signed
54 * messages and delivery info's differ in prefix and URI.
55 * @return 0 in success, otherwise not 0. */
56 static int register_namespaces(xmlXPathContextPtr xpath_ctx
,
57 const message_ns_type message_ns
) {
58 const xmlChar
*message_namespace
= NULL
;
60 if (!xpath_ctx
) return -1;
64 message_namespace
= BAD_CAST ISDS1_NS
; break;
65 case MESSAGE_NS_UNSIGNED
:
66 message_namespace
= BAD_CAST ISDS_NS
; break;
67 case MESSAGE_NS_SIGNED_INCOMING
:
68 message_namespace
= BAD_CAST SISDS_INCOMING_NS
; break;
69 case MESSAGE_NS_SIGNED_OUTGOING
:
70 message_namespace
= BAD_CAST SISDS_OUTGOING_NS
; break;
71 case MESSAGE_NS_SIGNED_DELIVERY
:
72 message_namespace
= BAD_CAST SISDS_DELIVERY_NS
; break;
77 if (xmlXPathRegisterNs(xpath_ctx
, BAD_CAST
"soap", BAD_CAST SOAP_NS
))
79 if (xmlXPathRegisterNs(xpath_ctx
, BAD_CAST
"isds", BAD_CAST ISDS_NS
))
81 if (xmlXPathRegisterNs(xpath_ctx
, BAD_CAST
"sisds", message_namespace
))
83 if (xmlXPathRegisterNs(xpath_ctx
, BAD_CAST
"xs", BAD_CAST SCHEMA_NS
))
85 if (xmlXPathRegisterNs(xpath_ctx
, BAD_CAST
"deposit", BAD_CAST DEPOSIT_NS
))
91 /* Parse soap request, pass it to service endpoint and respond to it.
92 * It sends final HTTP response. */
93 void soap(int socket
, const void *request
, size_t request_length
,
94 const char *end_point
) {
95 xmlDocPtr request_doc
= NULL
;
96 xmlXPathContextPtr xpath_ctx
= NULL
;
97 xmlXPathObjectPtr request_soap_body
= NULL
;
98 xmlNodePtr isds_request
= NULL
; /* pointer only */
99 _Bool service_handled
= 0;
101 if (NULL
== request
|| request_length
== 0) {
102 http_send_response_400(socket
, "Client sent empty body");
106 request_doc
= xmlParseMemory(request
, request_length
);
107 if (NULL
== request_doc
) {
108 http_send_response_400(socket
, "Client sent invalid XML document");
112 xpath_ctx
= xmlXPathNewContext(request_doc
);
113 if (NULL
== xpath_ctx
) {
114 xmlFreeDoc(request_doc
);
115 http_send_response_500(socket
, "Could not create XPath context");
119 if (register_namespaces(xpath_ctx
, MESSAGE_NS_UNSIGNED
)) {
120 xmlXPathFreeContext(xpath_ctx
);
121 xmlFreeDoc(request_doc
);
122 http_send_response_500(socket
,
123 "Could not register name spaces to the XPath context");
128 request_soap_body
= xmlXPathEvalExpression(
129 BAD_CAST
"/soap:Envelope/soap:Body", xpath_ctx
);
130 if (NULL
== request_soap_body
) {
131 xmlXPathFreeContext(xpath_ctx
);
132 xmlFreeDoc(request_doc
);
133 http_send_response_400(socket
, "Client sent invalid SOAP request");
136 if (xmlXPathNodeSetIsEmpty(request_soap_body
->nodesetval
)) {
137 xmlXPathFreeObject(request_soap_body
);
138 xmlXPathFreeContext(xpath_ctx
);
139 xmlFreeDoc(request_doc
);
140 http_send_response_400(socket
,
141 "SOAP request does not contain SOAP Body element");
144 if (request_soap_body
->nodesetval
->nodeNr
> 1) {
145 xmlXPathFreeObject(request_soap_body
);
146 xmlXPathFreeContext(xpath_ctx
);
147 xmlFreeDoc(request_doc
);
148 http_send_response_400(socket
,
149 "SOAP response has more than one Body element");
152 isds_request
= request_soap_body
->nodesetval
->nodeTab
[0]->children
;
153 if (isds_request
->next
!= NULL
) {
154 xmlXPathFreeObject(request_soap_body
);
155 xmlXPathFreeContext(xpath_ctx
);
156 xmlFreeDoc(request_doc
);
157 http_send_response_400(socket
, "SOAP body has more than one child");
160 if (isds_request
->type
!= XML_ELEMENT_NODE
|| isds_request
->ns
== NULL
||
161 xmlStrcmp(isds_request
->ns
->href
, BAD_CAST ISDS_NS
)) {
162 xmlXPathFreeObject(request_soap_body
);
163 xmlXPathFreeContext(xpath_ctx
);
164 xmlFreeDoc(request_doc
);
165 http_send_response_400(socket
,
166 "SOAP body does not contain an ISDS elment");
171 /* Dispatch request to service */
172 for (int i
= 0; i
< sizeof(services
)/sizeof(services
[0]); i
++) {
173 if (!strcmp(services
[i
].end_point
, end_point
) &&
174 !xmlStrcmp(services
[i
].name
, isds_request
->name
)) {
175 services
[i
].function(socket
, request_doc
, xpath_ctx
, isds_request
);
181 xmlXPathFreeObject(request_soap_body
);
182 xmlXPathFreeContext(xpath_ctx
);
183 xmlFreeDoc(request_doc
);
185 if (service_handled
) {
186 http_send_response_500(socket
,
187 "Requested ISDS service not implemented");