/** * Duplicate an XML document * @param dstSoap Destination SOAP handle * @param srcDoc the Source document * @return The new XML document */ WsXmlDocH ws_xml_duplicate_doc( WsXmlDocH srcDoc) { WsXmlDocH dst = NULL; WsXmlNodeH srcRoot = NULL; const char *name, *nsUri; if (!srcDoc) return NULL; srcRoot = ws_xml_get_doc_root(srcDoc); if (!srcRoot) return NULL; name = ws_xml_get_node_local_name(srcRoot); nsUri = ws_xml_get_node_name_ns(srcRoot); if ((dst = ws_xml_create_doc(nsUri, name)) != NULL) { int i; WsXmlNodeH node; WsXmlNodeH dstRoot = ws_xml_get_doc_root(dst); for (i = 0; (node = ws_xml_get_child(srcRoot, i, NULL, NULL)) != NULL; i++) { ws_xml_duplicate_tree(dstRoot, node); } } return dst; }
static void generate_notunderstood_fault(op_t * op, WsXmlNodeH notUnderstoodHeader) { WsXmlNodeH child; WsXmlNodeH header; if (op->in_doc == NULL) return; generate_op_fault(op, SOAP_FAULT_MUSTUNDERSTAND, 0); if (op->out_doc != NULL) { header = ws_xml_get_soap_header(op->out_doc); if (header) { child = ws_xml_add_child(header, XML_NS_SOAP_1_2, "NotUnderstood", NULL); ws_xml_add_qname_attr(child, NULL, "qname", ws_xml_get_node_name_ns (notUnderstoodHeader), ws_xml_get_node_local_name (notUnderstoodHeader)); } } else { error("cant generate fault"); } return; }
static int is_mu_header(WsXmlNodeH header) { int i; char *name, *ns; static struct __MuHeaderInfo s_Info[] = { {XML_NS_ADDRESSING, WSA_TO}, {XML_NS_ADDRESSING, WSA_MESSAGE_ID}, {XML_NS_ADDRESSING, WSA_RELATES_TO}, {XML_NS_ADDRESSING, WSA_ACTION}, {XML_NS_ADDRESSING, WSA_REPLY_TO}, {XML_NS_ADDRESSING, WSA_FROM}, {XML_NS_WS_MAN, WSM_RESOURCE_URI}, {XML_NS_WS_MAN, WSM_SELECTOR_SET}, {XML_NS_WS_MAN, WSM_MAX_ENVELOPE_SIZE}, {XML_NS_WS_MAN, WSM_OPERATION_TIMEOUT}, {XML_NS_WS_MAN, WSM_FRAGMENT_TRANSFER}, {XML_NS_TRUST, WST_ISSUEDTOKENS}, {NULL, NULL} }; name = ws_xml_get_node_local_name(header); ns = ws_xml_get_node_name_ns(header); for (i = 0; s_Info[i].name != NULL; i++) { if ((ns == NULL && s_Info[i].ns == NULL) || (ns != NULL && s_Info[i].ns != NULL && !strcmp(ns, s_Info[i].ns))) { if (!strcmp(name, s_Info[i].name)) return 1; } } debug("mustUnderstand: %s:%s", !ns ? "null" : ns, name ? name : "NULL"); return 0; }
static int validate_control_headers(op_t * op) { unsigned long size = 0; time_t duration; WsXmlNodeH header, child, maxsize; char *mu = NULL; header = wsman_get_soap_header_element( op->in_doc, NULL, NULL); maxsize = ws_xml_get_child(header, 0, XML_NS_WS_MAN, WSM_MAX_ENVELOPE_SIZE); mu = ws_xml_find_attr_value(maxsize, XML_NS_SOAP_1_2, SOAP_MUST_UNDERSTAND); if (mu != NULL && strcmp(mu, "true") == 0) { size = ws_deserialize_uint32(NULL, header, 0, XML_NS_WS_MAN, WSM_MAX_ENVELOPE_SIZE); if (size < WSMAN_MINIMAL_ENVELOPE_SIZE_REQUEST) { generate_op_fault(op, WSMAN_ENCODING_LIMIT, WSMAN_DETAIL_MINIMUM_ENVELOPE_LIMIT); return 0; } op->maxsize = size; } child = ws_xml_get_child(header, 0, XML_NS_WS_MAN, WSM_OPERATION_TIMEOUT); if (child != NULL) { char *text = ws_xml_get_node_text(child); char *nsUri = ws_xml_get_node_name_ns(header); if (text == NULL || ws_deserialize_duration(text, &duration)) { generate_op_fault(op, WSA_INVALID_MESSAGE_INFORMATION_HEADER, WSMAN_DETAIL_OPERATION_TIMEOUT); return 0; } if (duration <= 0) { generate_op_fault(op, WSMAN_TIMED_OUT, 0); return 0; } op->expires = duration; // Not supported now if (ws_xml_find_attr_bool (child, nsUri, SOAP_MUST_UNDERSTAND)) { generate_op_fault(op, WSMAN_UNSUPPORTED_FEATURE, WSMAN_DETAIL_OPERATION_TIMEOUT); return 0; } } return 1; }
/** * Is the XML node a qualified name * @param node XML node * @param nsUri Namespace URI * @param name node name * @return Returns 1 if node is QName * @brief Shortcats for QName manipulation name can be NULL, in this case just check namespace */ int ws_xml_is_node_qname(WsXmlNodeH node, const char *nsUri, const char *name) { int retVal = 0; char *nodeNsUri = NULL; if (!node) return 0; nodeNsUri = ws_xml_get_node_name_ns(node); if ((nsUri == NULL) || (nsUri == nodeNsUri) || (nsUri != NULL && nodeNsUri != NULL && !strcmp(nodeNsUri, nsUri))) { if (name == NULL || !strcmp(name, ws_xml_get_node_local_name(node))) retVal = 1; } return retVal; }
/** * Duplication complete XML tree * @param dstNode Destination XML node * @param srcNode Source XML node */ void ws_xml_duplicate_tree(WsXmlNodeH dstNode, WsXmlNodeH srcNode) { WsXmlNodeH node; if (!srcNode || !dstNode) { error("NULL arguments: dst = %p; src = %p", dstNode, srcNode); return; } node = ws_xml_add_child(dstNode, ws_xml_get_node_name_ns(srcNode), ws_xml_get_node_local_name(srcNode), NULL); if (!node) { error("could not add node"); return; } ws_xml_duplicate_attr(node, srcNode); if (ws_xml_duplicate_children(node, srcNode) == 0) { // no children ws_xml_set_node_text(node, ws_xml_get_node_text(srcNode)); } }
/** * Check if Envelope is valid * @param msg Message data * @param doc XML document * @return 1 if envelope is valid, 0 if not */ int wsman_is_valid_xml_envelope(WsXmlDocH doc) { int retval = 1; char *soapNsUri; WsXmlNodeH root = ws_xml_get_doc_root(doc); if (strcmp(SOAP_ENVELOPE, ws_xml_get_node_local_name(root)) != 0) { retval = 0; goto cleanup; } soapNsUri = ws_xml_get_node_name_ns(root); if (strcmp(soapNsUri, XML_NS_SOAP_1_2) != 0) { retval = 0; goto cleanup; } if (ws_xml_get_soap_body(doc) == NULL) { retval = 0; goto cleanup; } cleanup: return retval; }
/** * Get SOAP element * @param doc XML document * @param name Node name * @return Result XML node */ WsXmlNodeH ws_xml_get_soap_element(WsXmlDocH doc, const char *name) { WsXmlNodeH node = NULL; WsXmlNodeH env = ws_xml_get_soap_envelope(doc); char *soapUri = NULL; if (!env) return NULL; soapUri = ws_xml_get_node_name_ns(env); node = ws_xml_get_child(env, 0, NULL, NULL); if (!node) return NULL; if (!ws_xml_is_node_qname(node, soapUri, name)) { if (strcmp(name, SOAP_HEADER) != 0) { node = ws_xml_get_child(env, 1, NULL, NULL); if (node) { if (!ws_xml_is_node_qname(node, soapUri, name)) node = NULL; } } } return node; }
static WsXmlNodeH validate_mustunderstand_headers(op_t * op) { WsXmlNodeH child = NULL, header = NULL; int i; char *nsUri; header = wsman_get_soap_header_element(op->in_doc, NULL, NULL); nsUri = ws_xml_get_node_name_ns(header); for (i = 0;(child = ws_xml_get_child(header, i, NULL, NULL)) != NULL; i++) { if (ws_xml_find_attr_bool(child, nsUri, SOAP_MUST_UNDERSTAND)) { if (!is_mu_header(child)) { break; } } } if (child != NULL) { debug("Mustunderstand Fault: %s", ws_xml_get_node_text(child)); } return child; }
/** * Create a Fault * @param rqstDoc Request document (Envelope) * @param code Fault code * @param subCodeNs Namespace of sub code * @param subCode Sub code * @param lang Language for Reason section * @param reason Fault Reason * @param addDetailProc Callback for details * @param addDetailProcData Pointer to callback data * @return XML document of the fault */ WsXmlDocH wsman_create_fault_envelope(WsXmlDocH rqstDoc, const char *code, const char *subCodeNs, const char *subCode, const char *fault_action, const char *lang, const char *reason, const char *faultDetail) { WsXmlDocH doc = NULL; WsXmlNodeH header, body, fault, codeNode, node; char uuidBuf[50]; char *soapNs; if (rqstDoc) { doc = wsman_create_response_envelope(rqstDoc, fault_action); } else { /* FIXME */ doc = ws_xml_create_envelope(); } if (doc == NULL) { return NULL; } header = ws_xml_get_soap_header(doc); body = ws_xml_get_soap_body(doc); soapNs = ws_xml_get_node_name_ns(body); fault = ws_xml_add_child(body, soapNs, SOAP_FAULT, NULL); codeNode = ws_xml_add_child(fault, soapNs, SOAP_CODE, NULL); node = ws_xml_add_child(codeNode, soapNs, SOAP_VALUE, NULL); ws_xml_set_node_qname_val(node, soapNs, code); if (subCode && subCode[0] != 0 ) { node = ws_xml_add_child(codeNode, soapNs, SOAP_SUBCODE, NULL); node = ws_xml_add_child(node, soapNs, SOAP_VALUE, NULL); if (subCodeNs) ws_xml_set_node_qname_val(node, subCodeNs, subCode); else ws_xml_set_node_text(node, subCode); } if (reason) { node = ws_xml_add_child(fault, soapNs, SOAP_REASON, NULL); node = ws_xml_add_child(node, soapNs, SOAP_TEXT, NULL); ws_xml_set_node_text(node, reason); ws_xml_set_node_lang(node, !lang ? "en" : lang); } if (faultDetail) { WsXmlNodeH d = ws_xml_add_child(fault, soapNs, SOAP_DETAIL, NULL); node = ws_xml_add_child_format(d, XML_NS_WS_MAN, SOAP_FAULT_DETAIL, "%s/%s", XML_NS_WSMAN_FAULT_DETAIL, faultDetail); } generate_uuid(uuidBuf, sizeof(uuidBuf), 0); ws_xml_add_child(header, XML_NS_ADDRESSING, WSA_MESSAGE_ID, uuidBuf); return doc; }
/** * Check if Envelope is valid * @param msg Message data * @param doc XML document * @return 1 if envelope is valid, 0 if not */ int wsman_is_valid_envelope(WsmanMessage * msg, WsXmlDocH doc) { int retval = 1; char *soapNsUri; WsXmlNodeH header; WsXmlNodeH root = ws_xml_get_doc_root(doc); if (strcmp(SOAP_ENVELOPE, ws_xml_get_node_local_name(root)) != 0) { wsman_set_fault(msg, WSA_INVALID_MESSAGE_INFORMATION_HEADER, 0, "No Envelope"); retval = 0; debug("no envelope"); goto cleanup; } soapNsUri = ws_xml_get_node_name_ns(root); if (strcmp(soapNsUri, XML_NS_SOAP_1_2) != 0) { wsman_set_fault(msg, SOAP_FAULT_VERSION_MISMATCH, 0, NULL); retval = 0; debug("version mismatch"); goto cleanup; } if (ws_xml_get_soap_body(doc) == NULL) { wsman_set_fault(msg, WSA_INVALID_MESSAGE_INFORMATION_HEADER, 0, "No Body"); retval = 0; debug("no body"); goto cleanup; } header = ws_xml_get_soap_header(doc); if (!header) { wsman_set_fault(msg, WSA_INVALID_MESSAGE_INFORMATION_HEADER, 0, "No Header"); retval = 0; debug("no header"); goto cleanup; } else { if (!wsman_is_identify_request(doc) && !wsman_is_event_related_request(doc)) { WsXmlNodeH resource_uri = ws_xml_get_child(header, 0, XML_NS_WS_MAN, WSM_RESOURCE_URI); WsXmlNodeH action = ws_xml_get_child(header, 0, XML_NS_ADDRESSING, WSA_ACTION); WsXmlNodeH reply = ws_xml_get_child(header, 0, XML_NS_ADDRESSING, WSA_REPLY_TO); WsXmlNodeH to = ws_xml_get_child(header, 0, XML_NS_ADDRESSING, WSA_TO); if (!resource_uri) { wsman_set_fault(msg, WSA_DESTINATION_UNREACHABLE, WSMAN_DETAIL_INVALID_RESOURCEURI, NULL); retval = 0; debug("no wsman:ResourceURI"); goto cleanup; } if (!action) { wsman_set_fault(msg, WSA_ACTION_NOT_SUPPORTED, 0, NULL); retval = 0; debug("no wsa:Action"); goto cleanup; } if (!reply) { wsman_set_fault(msg, WSA_MESSAGE_INFORMATION_HEADER_REQUIRED, 0, NULL); retval = 0; debug("no wsa:ReplyTo"); goto cleanup; } if (!to) { wsman_set_fault(msg, WSA_DESTINATION_UNREACHABLE, 0, NULL); retval = 0; debug("no wsa:To"); goto cleanup; } } } cleanup: return retval; }