/** * XML Security Library (http://www.aleksey.com/xmlsec). * * Simple SOAP messages parsing/creation. * * This is free software; see Copyright file in the source * distribution for preciese wording. * * Copyright (C) 2002-2003 Aleksey Sanin */ #include "globals.h" #ifndef XMLSEC_NO_SOAP #include #include #include #include #include #include #include /*********************************************************************** * * SOAP 1.1 * **********************************************************************/ /** * xmlSecSoap11CreateEnvelope: * @doc: the parent doc (might be NULL). * * Creates a new SOAP Envelope node. Caller is responsible for * adding the returned node to the XML document. * * XML Schema (http://schemas.xmlsoap.org/soap/envelope/): * * * * * * * * * * * * Returns: pointer to newly created node or NULL * if an error occurs. */ xmlNodePtr xmlSecSoap11CreateEnvelope(xmlDocPtr doc) { xmlNodePtr envNode; xmlNodePtr bodyNode; xmlNsPtr ns; /* create Envelope node */ envNode = xmlNewDocNode(doc, NULL, xmlSecNodeEnvelope, NULL); if(envNode == NULL) { xmlSecError(XMLSEC_ERRORS_HERE, NULL, "xmlNewDocNode", XMLSEC_ERRORS_R_XML_FAILED, "node=%s", xmlSecErrorsSafeString(xmlSecNodeEnvelope)); return(NULL); } ns = xmlNewNs(envNode, xmlSecSoap11Ns, NULL) ; if(ns == NULL) { xmlSecError(XMLSEC_ERRORS_HERE, NULL, "xmlNewNs", XMLSEC_ERRORS_R_XML_FAILED, "ns=%s", xmlSecErrorsSafeString(xmlSecSoap11Ns)); xmlFreeNode(envNode); return(NULL); } xmlSetNs(envNode, ns); /* add required Body node */ bodyNode = xmlSecAddChild(envNode, xmlSecNodeBody, xmlSecSoap11Ns); if(bodyNode == NULL) { xmlSecError(XMLSEC_ERRORS_HERE, NULL, "xmlSecAddChild", XMLSEC_ERRORS_R_XMLSEC_FAILED, "node=%s", xmlSecErrorsSafeString(xmlSecNodeBody)); xmlFreeNode(envNode); return(NULL); } return(envNode); } /** * xmlSecSoap11EnsureHeader: * @envNode: the pointer to node. * * Gets the pointer to node (if necessary, the node * is created). * * XML Schema (http://schemas.xmlsoap.org/soap/envelope/): * * * * * * * * * * Returns: pointer to node or NULL if an error occurs. */ xmlNodePtr xmlSecSoap11EnsureHeader(xmlNodePtr envNode) { xmlNodePtr hdrNode; xmlNodePtr cur; xmlSecAssert2(envNode != NULL, NULL); /* try to find Header node first */ cur = xmlSecGetNextElementNode(envNode->children); if((cur != NULL) && xmlSecCheckNodeName(cur, xmlSecNodeHeader, xmlSecSoap11Ns)) { return(cur); } /* if the first element child is not Header then it is Body */ if((cur == NULL) || !xmlSecCheckNodeName(cur, xmlSecNodeBody, xmlSecSoap11Ns)) { xmlSecError(XMLSEC_ERRORS_HERE, NULL, xmlSecErrorsSafeString(xmlSecNodeBody), XMLSEC_ERRORS_R_NODE_NOT_FOUND, XMLSEC_ERRORS_NO_MESSAGE); return(NULL); } /* finally add Header node before body */ hdrNode = xmlSecAddPrevSibling(cur, xmlSecNodeHeader, xmlSecSoap11Ns); if(hdrNode == NULL) { xmlSecError(XMLSEC_ERRORS_HERE, NULL, "xmlSecAddPrevSibling", XMLSEC_ERRORS_R_XMLSEC_FAILED, XMLSEC_ERRORS_NO_MESSAGE); return(NULL); } return(hdrNode); } /** * xmlSecSoap11AddBodyEntry: * @envNode: the pointer to node. * @entryNode: the pointer to body entry node. * * Adds a new entry to node. * * Returns: pointer to the added entry (@contentNode) or NULL if an error occurs. */ xmlNodePtr xmlSecSoap11AddBodyEntry(xmlNodePtr envNode, xmlNodePtr entryNode) { xmlNodePtr bodyNode; xmlSecAssert2(envNode != NULL, NULL); xmlSecAssert2(entryNode != NULL, NULL); bodyNode = xmlSecSoap11GetBody(envNode); if(bodyNode == NULL) { xmlSecError(XMLSEC_ERRORS_HERE, NULL, "xmlSecSoap11GetBody", XMLSEC_ERRORS_R_XMLSEC_FAILED, XMLSEC_ERRORS_NO_MESSAGE); return(NULL); } return(xmlSecAddChildNode(bodyNode, entryNode)); } /** * xmlSecSoap11AddFaultEntry: * @envNode: the pointer to node. * @faultCodeHref: the fault code QName href (must be known in th context of * node). * @faultCodeLocalPart: the fault code QName LocalPart. * @faultString: the human readable explanation of the fault. * @faultActor: the information about who caused the fault (might be NULL). * * Adds entry to the @envNode. Note that only one * entry is allowed. * * XML Schema (http://schemas.xmlsoap.org/soap/envelope/): * * * * * * * * * * * * * * * * * * Returns: pointer to the added entry or NULL if an error occurs. */ xmlNodePtr xmlSecSoap11AddFaultEntry(xmlNodePtr envNode, const xmlChar* faultCodeHref, const xmlChar* faultCodeLocalPart, const xmlChar* faultString, const xmlChar* faultActor) { xmlNodePtr bodyNode; xmlNodePtr faultNode; xmlNodePtr cur; xmlChar* qname; xmlSecAssert2(envNode != NULL, NULL); xmlSecAssert2(faultCodeLocalPart != NULL, NULL); xmlSecAssert2(faultString != NULL, NULL); /* get Body node */ bodyNode = xmlSecSoap11GetBody(envNode); if(bodyNode == NULL) { xmlSecError(XMLSEC_ERRORS_HERE, NULL, "xmlSecSoap11GetBody", XMLSEC_ERRORS_R_XMLSEC_FAILED, XMLSEC_ERRORS_NO_MESSAGE); return(NULL); } /* check that we don't have Fault node already */ faultNode = xmlSecFindChild(bodyNode, xmlSecNodeFault, xmlSecSoap11Ns); if(faultNode != NULL) { xmlSecError(XMLSEC_ERRORS_HERE, NULL, xmlSecErrorsSafeString(xmlSecNodeBody), XMLSEC_ERRORS_R_NODE_ALREADY_PRESENT, XMLSEC_ERRORS_NO_MESSAGE); return(NULL); } /* add Fault node */ faultNode = xmlSecAddChild(bodyNode, xmlSecNodeFault, xmlSecSoap11Ns); if(faultNode == NULL) { xmlSecError(XMLSEC_ERRORS_HERE, NULL, "xmlSecAddChild", XMLSEC_ERRORS_R_XMLSEC_FAILED, "node=%s", xmlSecErrorsSafeString(xmlSecNodeFault)); return(NULL); } /* add faultcode node */ cur = xmlSecAddChild(faultNode, xmlSecNodeFaultCode, xmlSecSoap11Ns); if(cur == NULL) { xmlSecError(XMLSEC_ERRORS_HERE, NULL, "xmlSecAddChild", XMLSEC_ERRORS_R_XMLSEC_FAILED, "node=%s", xmlSecErrorsSafeString(xmlSecNodeFaultCode)); xmlUnlinkNode(faultNode); xmlFreeNode(faultNode); return(NULL); } /* create qname for fault code */ qname = xmlSecGetQName(cur, faultCodeHref, faultCodeLocalPart); if(qname == NULL) { xmlSecError(XMLSEC_ERRORS_HERE, NULL, "xmlSecGetQName", XMLSEC_ERRORS_R_XML_FAILED, "node=%s", xmlSecErrorsSafeString(cur->name)); xmlUnlinkNode(faultNode); xmlFreeNode(faultNode); return(NULL); } /* set faultcode value */ xmlNodeSetContent(cur, qname); xmlFree(qname); /* add faultstring node */ cur = xmlSecAddChild(faultNode, xmlSecNodeFaultString, xmlSecSoap11Ns); if(cur == NULL) { xmlSecError(XMLSEC_ERRORS_HERE, NULL, "xmlSecAddChild", XMLSEC_ERRORS_R_XMLSEC_FAILED, "node=%s", xmlSecErrorsSafeString(xmlSecNodeFaultString)); xmlUnlinkNode(faultNode); xmlFreeNode(faultNode); return(NULL); } /* set faultstring node */ xmlNodeSetContent(cur, faultString); if(faultActor != NULL) { /* add faultactor node */ cur = xmlSecAddChild(faultNode, xmlSecNodeFaultActor, xmlSecSoap11Ns); if(cur == NULL) { xmlSecError(XMLSEC_ERRORS_HERE, NULL, "xmlSecAddChild", XMLSEC_ERRORS_R_XMLSEC_FAILED, "node=%s", xmlSecErrorsSafeString(xmlSecNodeFaultActor)); xmlUnlinkNode(faultNode); xmlFreeNode(faultNode); return(NULL); } /* set faultactor node */ xmlNodeSetContent(cur, faultActor); } return(faultNode); } /** * xmlSecSoap11CheckEnvelope: * @envNode: the pointer to node. * * Validates node structure. * * Returns: 1 if @envNode has a valid element, 0 if it is * not valid or a negative value if an error occurs. */ int xmlSecSoap11CheckEnvelope(xmlNodePtr envNode) { xmlNodePtr cur; xmlSecAssert2(envNode != NULL, -1); /* verify envNode itself */ if(!xmlSecCheckNodeName(envNode, xmlSecNodeEnvelope, xmlSecSoap11Ns)) { xmlSecError(XMLSEC_ERRORS_HERE, NULL, xmlSecErrorsSafeString(xmlSecNodeEnvelope), XMLSEC_ERRORS_R_NODE_NOT_FOUND, XMLSEC_ERRORS_NO_MESSAGE); return(0); } /* optional Header node first */ cur = xmlSecGetNextElementNode(envNode->children); if((cur != NULL) && xmlSecCheckNodeName(cur, xmlSecNodeHeader, xmlSecSoap11Ns)) { cur = xmlSecGetNextElementNode(cur->next); } /* required Body node is next */ if((cur == NULL) || !xmlSecCheckNodeName(cur, xmlSecNodeBody, xmlSecSoap11Ns)) { xmlSecError(XMLSEC_ERRORS_HERE, NULL, xmlSecErrorsSafeString(xmlSecNodeBody), XMLSEC_ERRORS_R_NODE_NOT_FOUND, XMLSEC_ERRORS_NO_MESSAGE); return(0); } return(1); } /** * xmlSecSoap11GetHeader: * @envNode: the pointer to node. * * Gets pointer to the node. * * Returns: pointer to node or NULL if an error occurs. */ xmlNodePtr xmlSecSoap11GetHeader(xmlNodePtr envNode) { xmlNodePtr cur; xmlSecAssert2(envNode != NULL, NULL); /* optional Header node is first */ cur = xmlSecGetNextElementNode(envNode->children); if((cur != NULL) && xmlSecCheckNodeName(cur, xmlSecNodeHeader, xmlSecSoap11Ns)) { return(cur); } return(NULL); } /** * xmlSecSoap11GetBody: * @envNode: the pointer to node. * * Gets pointer to the node. * * Returns: pointer to node or NULL if an error occurs. */ xmlNodePtr xmlSecSoap11GetBody(xmlNodePtr envNode) { xmlNodePtr cur; xmlSecAssert2(envNode != NULL, NULL); /* optional Header node first */ cur = xmlSecGetNextElementNode(envNode->children); if((cur != NULL) && xmlSecCheckNodeName(cur, xmlSecNodeHeader, xmlSecSoap11Ns)) { cur = xmlSecGetNextElementNode(cur->next); } /* Body node is next */ if((cur == NULL) || !xmlSecCheckNodeName(cur, xmlSecNodeBody, xmlSecSoap11Ns)) { xmlSecError(XMLSEC_ERRORS_HERE, NULL, xmlSecErrorsSafeString(xmlSecNodeBody), XMLSEC_ERRORS_R_NODE_NOT_FOUND, XMLSEC_ERRORS_NO_MESSAGE); return(NULL); } return(cur); } /** * xmlSecSoap11GetBodyEntriesNumber: * @envNode: the pointer to node. * * Gets the number of body entries. * * Returns: the number of body entries. */ xmlSecSize xmlSecSoap11GetBodyEntriesNumber(xmlNodePtr envNode) { xmlSecSize number = 0; xmlNodePtr bodyNode; xmlNodePtr cur; xmlSecAssert2(envNode != NULL, 0); /* get Body node */ bodyNode = xmlSecSoap11GetBody(envNode); if(bodyNode == NULL) { xmlSecError(XMLSEC_ERRORS_HERE, NULL, "xmlSecSoap11GetBody", XMLSEC_ERRORS_R_XMLSEC_FAILED, XMLSEC_ERRORS_NO_MESSAGE); return(0); } cur = xmlSecGetNextElementNode(bodyNode->children); while(cur != NULL) { number++; cur = xmlSecGetNextElementNode(cur->next); } return(number); } /** * xmlSecSoap11GetBodyEntry: * @envNode: the pointer to node. * @pos: the body entry number. * * Gets the body entry number @pos. * * Returns: pointer to body entry node or NULL if an error occurs. */ xmlNodePtr xmlSecSoap11GetBodyEntry(xmlNodePtr envNode, xmlSecSize pos) { xmlNodePtr bodyNode; xmlNodePtr cur; xmlSecAssert2(envNode != NULL, NULL); /* get Body node */ bodyNode = xmlSecSoap11GetBody(envNode); if(bodyNode == NULL) { xmlSecError(XMLSEC_ERRORS_HERE, NULL, "xmlSecSoap11GetBody", XMLSEC_ERRORS_R_XMLSEC_FAILED, XMLSEC_ERRORS_NO_MESSAGE); return(NULL); } cur = xmlSecGetNextElementNode(bodyNode->children); while((cur != NULL) && (pos > 0)) { pos--; cur = xmlSecGetNextElementNode(cur->next); } return(cur); } /** * xmlSecSoap11GetFaultEntry: * @envNode: the pointer to node. * * Gets the Fault entry (if any). * * Returns: pointer to Fault entry or NULL if it does not exist. */ xmlNodePtr xmlSecSoap11GetFaultEntry(xmlNodePtr envNode) { xmlNodePtr bodyNode; xmlSecAssert2(envNode != NULL, NULL); /* get Body node */ bodyNode = xmlSecSoap11GetBody(envNode); if(bodyNode == NULL) { xmlSecError(XMLSEC_ERRORS_HERE, NULL, "xmlSecSoap11GetBody", XMLSEC_ERRORS_R_XMLSEC_FAILED, XMLSEC_ERRORS_NO_MESSAGE); return(NULL); } return(xmlSecFindChild(bodyNode, xmlSecNodeFault, xmlSecSoap11Ns)); } /*********************************************************************** * * SOAP 1.2 * **********************************************************************/ static const xmlSecQName2IntegerInfo gXmlSecSoap12FaultCodeInfo[] = { { xmlSecSoap12Ns, xmlSecSoapFaultCodeVersionMismatch, xmlSecSoap12FaultCodeVersionMismatch }, { xmlSecSoap12Ns, xmlSecSoapFaultCodeMustUnderstand, xmlSecSoap12FaultCodeMustUnderstand }, { xmlSecSoap12Ns, xmlSecSoapFaultDataEncodningUnknown, xmlSecSoap12FaultCodeDataEncodingUnknown }, { xmlSecSoap12Ns, xmlSecSoapFaultCodeSender, xmlSecSoap12FaultCodeSender }, { xmlSecSoap12Ns, xmlSecSoapFaultCodeReceiver, xmlSecSoap12FaultCodeReceiver }, { NULL, NULL, 0 } /* MUST be last in the list */ }; /** * xmlSecSoap12CreateEnvelope: * @doc: the parent doc (might be NULL). * * Creates a new SOAP 1.2 Envelope node. Caller is responsible for * adding the returned node to the XML document. * * XML Schema (http://www.w3.org/2003/05/soap-envelope): * * * * * * * * * * * Returns: pointer to newly created node or NULL * if an error occurs. */ xmlNodePtr xmlSecSoap12CreateEnvelope(xmlDocPtr doc) { xmlNodePtr envNode; xmlNodePtr bodyNode; xmlNsPtr ns; /* create Envelope node */ envNode = xmlNewDocNode(doc, NULL, xmlSecNodeEnvelope, NULL); if(envNode == NULL) { xmlSecError(XMLSEC_ERRORS_HERE, NULL, "xmlNewDocNode", XMLSEC_ERRORS_R_XML_FAILED, "node=%s", xmlSecErrorsSafeString(xmlSecNodeEnvelope)); return(NULL); } ns = xmlNewNs(envNode, xmlSecSoap12Ns, NULL) ; if(ns == NULL) { xmlSecError(XMLSEC_ERRORS_HERE, NULL, "xmlNewNs", XMLSEC_ERRORS_R_XML_FAILED, "ns=%s", xmlSecErrorsSafeString(xmlSecSoap12Ns)); xmlFreeNode(envNode); return(NULL); } xmlSetNs(envNode, ns); /* add required Body node */ bodyNode = xmlSecAddChild(envNode, xmlSecNodeBody, xmlSecSoap12Ns); if(bodyNode == NULL) { xmlSecError(XMLSEC_ERRORS_HERE, NULL, "xmlSecAddChild", XMLSEC_ERRORS_R_XMLSEC_FAILED, "node=%s", xmlSecErrorsSafeString(xmlSecNodeBody)); xmlFreeNode(envNode); return(NULL); } return(envNode); } /** * xmlSecSoap12EnsureHeader: * @envNode: the pointer to node. * * Gets the pointer to node (if necessary, the node * is created). * * XML Schema (http://www.w3.org/2003/05/soap-envelope): * * * * * * * * * * Returns: pointer to node or NULL if an error occurs. */ xmlNodePtr xmlSecSoap12EnsureHeader(xmlNodePtr envNode) { xmlNodePtr hdrNode; xmlNodePtr cur; xmlSecAssert2(envNode != NULL, NULL); /* try to find Header node first */ cur = xmlSecGetNextElementNode(envNode->children); if((cur != NULL) && xmlSecCheckNodeName(cur, xmlSecNodeHeader, xmlSecSoap12Ns)) { return(cur); } /* if the first element child is not Header then it is Body */ if((cur == NULL) || !xmlSecCheckNodeName(cur, xmlSecNodeBody, xmlSecSoap12Ns)) { xmlSecError(XMLSEC_ERRORS_HERE, NULL, xmlSecErrorsSafeString(xmlSecNodeBody), XMLSEC_ERRORS_R_NODE_NOT_FOUND, XMLSEC_ERRORS_NO_MESSAGE); return(NULL); } /* finally add Header node before body */ hdrNode = xmlSecAddPrevSibling(cur, xmlSecNodeHeader, xmlSecSoap12Ns); if(hdrNode == NULL) { xmlSecError(XMLSEC_ERRORS_HERE, NULL, "xmlSecAddPrevSibling", XMLSEC_ERRORS_R_XMLSEC_FAILED, XMLSEC_ERRORS_NO_MESSAGE); return(NULL); } return(hdrNode); } /** * xmlSecSoap12AddBodyEntry: * @envNode: the pointer to node. * @entryNode: the pointer to body entry node. * * Adds a new entry to node. * * XML Schema (http://www.w3.org/2003/05/soap-envelope): * * * * * * * * * * Returns: pointer to the added entry (@contentNode) or NULL if an error occurs. */ xmlNodePtr xmlSecSoap12AddBodyEntry(xmlNodePtr envNode, xmlNodePtr entryNode) { xmlNodePtr bodyNode; xmlSecAssert2(envNode != NULL, NULL); xmlSecAssert2(entryNode != NULL, NULL); bodyNode = xmlSecSoap12GetBody(envNode); if(bodyNode == NULL) { xmlSecError(XMLSEC_ERRORS_HERE, NULL, "xmlSecSoap12GetBody", XMLSEC_ERRORS_R_XMLSEC_FAILED, XMLSEC_ERRORS_NO_MESSAGE); return(NULL); } return(xmlSecAddChildNode(bodyNode, entryNode)); } /** * xmlSecSoap12AddFaultEntry: * @envNode: the pointer to node. * @faultCode: the fault code. * @faultReasonText: the human readable explanation of the fault. * @faultReasonLang: the language (xml:lang) for @faultReason string. * @faultNodeURI: the more preciese information about fault source * (might be NULL). * @faultRole: the role the node was operating in at the point * the fault occurred (might be NULL). * * Adds entry to the @envNode. Note that only one * entry is allowed. * * XML Schema (http://www.w3.org/2003/05/soap-envelope): * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Returns: pointer to the added entry or NULL if an error occurs. */ xmlNodePtr xmlSecSoap12AddFaultEntry(xmlNodePtr envNode, xmlSecSoap12FaultCode faultCode, const xmlChar* faultReasonText, const xmlChar* faultReasonLang, const xmlChar* faultNodeURI, const xmlChar* faultRole) { xmlNodePtr bodyNode; xmlNodePtr faultNode; xmlNodePtr cur; int ret; xmlSecAssert2(envNode != NULL, NULL); xmlSecAssert2(faultCode != xmlSecSoap12FaultCodeUnknown, NULL); xmlSecAssert2(faultReasonText != NULL, NULL); xmlSecAssert2(faultReasonLang != NULL, NULL); /* get Body node */ bodyNode = xmlSecSoap12GetBody(envNode); if(bodyNode == NULL) { xmlSecError(XMLSEC_ERRORS_HERE, NULL, "xmlSecSoap12GetBody", XMLSEC_ERRORS_R_XMLSEC_FAILED, XMLSEC_ERRORS_NO_MESSAGE); return(NULL); } /* check that we don't have Fault node already */ faultNode = xmlSecFindChild(bodyNode, xmlSecNodeFault, xmlSecSoap12Ns); if(faultNode != NULL) { xmlSecError(XMLSEC_ERRORS_HERE, NULL, xmlSecErrorsSafeString(xmlSecNodeBody), XMLSEC_ERRORS_R_NODE_ALREADY_PRESENT, XMLSEC_ERRORS_NO_MESSAGE); return(NULL); } /* add Fault node */ faultNode = xmlSecAddChild(bodyNode, xmlSecNodeFault, xmlSecSoap12Ns); if(faultNode == NULL) { xmlSecError(XMLSEC_ERRORS_HERE, NULL, "xmlSecAddChild", XMLSEC_ERRORS_R_XMLSEC_FAILED, "node=%s", xmlSecErrorsSafeString(xmlSecNodeFault)); return(NULL); } /* add Code node */ cur = xmlSecAddChild(faultNode, xmlSecNodeCode, xmlSecSoap12Ns); if(cur == NULL) { xmlSecError(XMLSEC_ERRORS_HERE, NULL, "xmlSecAddChild", XMLSEC_ERRORS_R_XMLSEC_FAILED, "node=%s", xmlSecErrorsSafeString(xmlSecNodeCode)); xmlUnlinkNode(faultNode); xmlFreeNode(faultNode); return(NULL); } /* write the fault code in Value child */ ret = xmlSecQName2IntegerNodeWrite(gXmlSecSoap12FaultCodeInfo, cur, xmlSecNodeValue, xmlSecSoap12Ns, faultCode); if(ret < 0) { xmlSecError(XMLSEC_ERRORS_HERE, NULL, "xmlSecQName2IntegerNodeWrite", XMLSEC_ERRORS_R_XMLSEC_FAILED, "faultCode=%d", faultCode); xmlUnlinkNode(faultNode); xmlFreeNode(faultNode); return(NULL); } /* add Reason node */ cur = xmlSecAddChild(faultNode, xmlSecNodeReason, xmlSecSoap12Ns); if(cur == NULL) { xmlSecError(XMLSEC_ERRORS_HERE, NULL, "xmlSecAddChild", XMLSEC_ERRORS_R_XMLSEC_FAILED, "node=%s", xmlSecErrorsSafeString(xmlSecNodeReason)); xmlUnlinkNode(faultNode); xmlFreeNode(faultNode); return(NULL); } /* Add Reason/Text node */ if(xmlSecSoap12AddFaultReasonText(faultNode, faultReasonText, faultReasonLang) == NULL) { xmlSecError(XMLSEC_ERRORS_HERE, NULL, "xmlSecSoap12AddFaultReasonText", XMLSEC_ERRORS_R_XMLSEC_FAILED, "text=%s", xmlSecErrorsSafeString(faultReasonText)); xmlUnlinkNode(faultNode); xmlFreeNode(faultNode); return(NULL); } if(faultNodeURI != NULL) { /* add Node node */ cur = xmlSecAddChild(faultNode, xmlSecNodeNode, xmlSecSoap12Ns); if(cur == NULL) { xmlSecError(XMLSEC_ERRORS_HERE, NULL, "xmlSecAddChild", XMLSEC_ERRORS_R_XMLSEC_FAILED, "node=%s", xmlSecErrorsSafeString(xmlSecNodeNode)); xmlUnlinkNode(faultNode); xmlFreeNode(faultNode); return(NULL); } xmlNodeSetContent(cur, faultNodeURI); } if(faultRole != NULL) { /* add Role node */ cur = xmlSecAddChild(faultNode, xmlSecNodeRole, xmlSecSoap12Ns); if(cur == NULL) { xmlSecError(XMLSEC_ERRORS_HERE, NULL, "xmlSecAddChild", XMLSEC_ERRORS_R_XMLSEC_FAILED, "node=%s", xmlSecErrorsSafeString(xmlSecNodeRole)); xmlUnlinkNode(faultNode); xmlFreeNode(faultNode); return(NULL); } xmlNodeSetContent(cur, faultRole); } return(faultNode); } /** * xmlSecSoap12AddFaultSubcode: * @faultNode: the pointer to node. * @subCodeHref: the subcode href. * @subCodeName: the subcode name. * * Adds a new node to the node or the last node. * * Returns: a pointer to the newly created node or NULL if an error * occurs. */ xmlNodePtr xmlSecSoap12AddFaultSubcode(xmlNodePtr faultNode, const xmlChar* subCodeHref, const xmlChar* subCodeName) { xmlNodePtr cur, subcodeNode, valueNode; xmlChar* qname; xmlSecAssert2(faultNode != NULL, NULL); xmlSecAssert2(subCodeHref != NULL, NULL); xmlSecAssert2(subCodeName != NULL, NULL); /* Code node is the first childern in Fault node */ cur = xmlSecGetNextElementNode(faultNode->children); if((cur == NULL) || !xmlSecCheckNodeName(cur, xmlSecNodeCode, xmlSecSoap12Ns)) { xmlSecError(XMLSEC_ERRORS_HERE, NULL, NULL, XMLSEC_ERRORS_R_INVALID_NODE, "node=%s", xmlSecErrorsSafeString(xmlSecNodeCode)); return(NULL); } /* find the Code or Subcode node that does not have Subcode child */ while(1) { xmlNodePtr tmp; tmp = xmlSecFindChild(cur, xmlSecNodeSubcode, xmlSecSoap12Ns); if(tmp != NULL) { cur = tmp; } else { break; } } xmlSecAssert2(cur != NULL, NULL); /* add Subcode node */ subcodeNode = xmlSecAddChild(cur, xmlSecNodeSubcode, xmlSecSoap12Ns); if(subcodeNode == NULL) { xmlSecError(XMLSEC_ERRORS_HERE, NULL, "xmlSecAddChild", XMLSEC_ERRORS_R_XMLSEC_FAILED, "node=%s", xmlSecErrorsSafeString(xmlSecNodeSubcode)); return(NULL); } /* add Value node */ valueNode = xmlSecAddChild(subcodeNode, xmlSecNodeValue, xmlSecSoap12Ns); if(valueNode == NULL) { xmlSecError(XMLSEC_ERRORS_HERE, NULL, "xmlSecAddChild", XMLSEC_ERRORS_R_XMLSEC_FAILED, "node=%s", xmlSecErrorsSafeString(xmlSecNodeValue)); xmlUnlinkNode(subcodeNode); xmlFreeNode(subcodeNode); return(NULL); } /* create qname for fault code */ qname = xmlSecGetQName(cur, subCodeHref, subCodeName); if(qname == NULL) { xmlSecError(XMLSEC_ERRORS_HERE, NULL, "xmlSecGetQName", XMLSEC_ERRORS_R_XML_FAILED, "node=%s", xmlSecErrorsSafeString(cur->name)); xmlUnlinkNode(subcodeNode); xmlFreeNode(subcodeNode); return(NULL); } /* set result qname in Value node */ xmlNodeSetContent(cur, qname); if(qname != subCodeName) { xmlFree(qname); } return(subcodeNode); } /** * xmlSecSoap12AddFaultReasonText: * @faultNode: the pointer to node. * @faultReasonText: the new reason text. * @faultReasonLang: the new reason xml:lang attribute. * * Adds a new Text node to the Fault/Reason node. * * Returns: a pointer to the newly created node or NULL if an error * occurs. */ xmlNodePtr xmlSecSoap12AddFaultReasonText(xmlNodePtr faultNode, const xmlChar* faultReasonText, const xmlChar* faultReasonLang) { xmlNodePtr reasonNode; xmlNodePtr textNode; xmlSecAssert2(faultNode != NULL, NULL); xmlSecAssert2(faultReasonText != NULL, NULL); xmlSecAssert2(faultReasonLang != NULL, NULL); /* find Reason node */ reasonNode = xmlSecFindChild(faultNode, xmlSecNodeReason, xmlSecSoap12Ns); if(reasonNode == NULL) { xmlSecError(XMLSEC_ERRORS_HERE, NULL, "xmlSecFindChild", XMLSEC_ERRORS_R_XMLSEC_FAILED, "node=%s", xmlSecErrorsSafeString(xmlSecNodeReason)); return(NULL); } /* add Text node */ textNode = xmlSecAddChild(reasonNode, xmlSecNodeText, xmlSecSoap12Ns); if(textNode == NULL) { xmlSecError(XMLSEC_ERRORS_HERE, NULL, "xmlSecAddChild", XMLSEC_ERRORS_R_XMLSEC_FAILED, "node=%s", xmlSecErrorsSafeString(xmlSecNodeText)); return(NULL); } xmlNodeSetContent(textNode, faultReasonText); xmlNodeSetLang(textNode, faultReasonLang); return(textNode); } /** * xmlSecSoap12AddFaultDetailEntry: * @faultNode: the pointer to node. * @detailEntryNode: the pointer to detail entry node. * * Adds a new child to the Detail child element of @faultNode. * * Returns: pointer to the added child (@detailEntryNode) or NULL if an error * occurs. */ xmlNodePtr xmlSecSoap12AddFaultDetailEntry(xmlNodePtr faultNode, xmlNodePtr detailEntryNode) { xmlNodePtr detailNode; xmlSecAssert2(faultNode != NULL, NULL); xmlSecAssert2(detailEntryNode != NULL, NULL); /* find Detail node and add it if needed */ detailNode = xmlSecFindChild(faultNode, xmlSecNodeDetail, xmlSecSoap12Ns); if(detailNode == NULL) { detailNode = xmlSecAddChild(faultNode, xmlSecNodeDetail, xmlSecSoap12Ns); if(detailNode == NULL) { xmlSecError(XMLSEC_ERRORS_HERE, NULL, "xmlSecAddChild", XMLSEC_ERRORS_R_XMLSEC_FAILED, "node=%s", xmlSecErrorsSafeString(xmlSecNodeDetail)); return(NULL); } } return(xmlSecAddChildNode(detailNode, detailEntryNode)); } /** * xmlSecSoap12CheckEnvelope: * @envNode: the pointer to node. * * Validates node structure. * * Returns: 1 if @envNode has a valid element, 0 if it is * not valid or a negative value if an error occurs. */ int xmlSecSoap12CheckEnvelope(xmlNodePtr envNode) { xmlNodePtr cur; xmlSecAssert2(envNode != NULL, -1); /* verify envNode itself */ if(!xmlSecCheckNodeName(envNode, xmlSecNodeEnvelope, xmlSecSoap12Ns)) { xmlSecError(XMLSEC_ERRORS_HERE, NULL, xmlSecErrorsSafeString(xmlSecNodeEnvelope), XMLSEC_ERRORS_R_NODE_NOT_FOUND, XMLSEC_ERRORS_NO_MESSAGE); return(0); } /* optional Header node first */ cur = xmlSecGetNextElementNode(envNode->children); if((cur != NULL) && xmlSecCheckNodeName(cur, xmlSecNodeHeader, xmlSecSoap12Ns)) { cur = xmlSecGetNextElementNode(cur->next); } /* required Body node is next */ if((cur == NULL) || !xmlSecCheckNodeName(cur, xmlSecNodeBody, xmlSecSoap12Ns)) { xmlSecError(XMLSEC_ERRORS_HERE, NULL, xmlSecErrorsSafeString(xmlSecNodeBody), XMLSEC_ERRORS_R_NODE_NOT_FOUND, XMLSEC_ERRORS_NO_MESSAGE); return(0); } return(1); } /** * xmlSecSoap12GetHeader: * @envNode: the pointer to node. * * Gets pointer to the node. * * Returns: pointer to node or NULL if an error occurs. */ xmlNodePtr xmlSecSoap12GetHeader(xmlNodePtr envNode) { xmlNodePtr cur; xmlSecAssert2(envNode != NULL, NULL); /* optional Header node is first */ cur = xmlSecGetNextElementNode(envNode->children); if((cur != NULL) && xmlSecCheckNodeName(cur, xmlSecNodeHeader, xmlSecSoap12Ns)) { return(cur); } return(NULL); } /** * xmlSecSoap12GetBody: * @envNode: the pointer to node. * * Gets pointer to the node. * * Returns: pointer to node or NULL if an error occurs. */ xmlNodePtr xmlSecSoap12GetBody(xmlNodePtr envNode) { xmlNodePtr cur; xmlSecAssert2(envNode != NULL, NULL); /* optional Header node first */ cur = xmlSecGetNextElementNode(envNode->children); if((cur != NULL) && xmlSecCheckNodeName(cur, xmlSecNodeHeader, xmlSecSoap12Ns)) { cur = xmlSecGetNextElementNode(cur->next); } /* Body node is next */ if((cur == NULL) || !xmlSecCheckNodeName(cur, xmlSecNodeBody, xmlSecSoap12Ns)) { xmlSecError(XMLSEC_ERRORS_HERE, NULL, xmlSecErrorsSafeString(xmlSecNodeBody), XMLSEC_ERRORS_R_NODE_NOT_FOUND, XMLSEC_ERRORS_NO_MESSAGE); return(NULL); } return(cur); } /** * xmlSecSoap12GetBodyEntriesNumber: * @envNode: the pointer to node. * * Gets the number of body entries. * * Returns: the number of body entries. */ xmlSecSize xmlSecSoap12GetBodyEntriesNumber(xmlNodePtr envNode) { xmlSecSize number = 0; xmlNodePtr bodyNode; xmlNodePtr cur; xmlSecAssert2(envNode != NULL, 0); /* get Body node */ bodyNode = xmlSecSoap12GetBody(envNode); if(bodyNode == NULL) { xmlSecError(XMLSEC_ERRORS_HERE, NULL, "xmlSecSoap12GetBody", XMLSEC_ERRORS_R_XMLSEC_FAILED, XMLSEC_ERRORS_NO_MESSAGE); return(0); } cur = xmlSecGetNextElementNode(bodyNode->children); while(cur != NULL) { number++; cur = xmlSecGetNextElementNode(cur->next); } return(number); } /** * xmlSecSoap12GetBodyEntry: * @envNode: the pointer to node. * @pos: the body entry number. * * Gets the body entry number @pos. * * Returns: pointer to body entry node or NULL if an error occurs. */ xmlNodePtr xmlSecSoap12GetBodyEntry(xmlNodePtr envNode, xmlSecSize pos) { xmlNodePtr bodyNode; xmlNodePtr cur; xmlSecAssert2(envNode != NULL, NULL); /* get Body node */ bodyNode = xmlSecSoap12GetBody(envNode); if(bodyNode == NULL) { xmlSecError(XMLSEC_ERRORS_HERE, NULL, "xmlSecSoap12GetBody", XMLSEC_ERRORS_R_XMLSEC_FAILED, XMLSEC_ERRORS_NO_MESSAGE); return(NULL); } cur = xmlSecGetNextElementNode(bodyNode->children); while((cur != NULL) && (pos > 0)) { pos--; cur = xmlSecGetNextElementNode(cur->next); } return(cur); } /** * xmlSecSoap12GetFaultEntry: * @envNode: the pointer to node. * * Gets the Fault entry (if any). * * Returns: pointer to Fault entry or NULL if it does not exist. */ xmlNodePtr xmlSecSoap12GetFaultEntry(xmlNodePtr envNode) { xmlNodePtr bodyNode; xmlSecAssert2(envNode != NULL, NULL); /* get Body node */ bodyNode = xmlSecSoap12GetBody(envNode); if(bodyNode == NULL) { xmlSecError(XMLSEC_ERRORS_HERE, NULL, "xmlSecSoap12GetBody", XMLSEC_ERRORS_R_XMLSEC_FAILED, XMLSEC_ERRORS_NO_MESSAGE); return(NULL); } return(xmlSecFindChild(bodyNode, xmlSecNodeFault, xmlSecSoap12Ns)); } #endif /* XMLSEC_NO_SOAP */