xmlsecurityengine/xmlsec/src/xmlsec_soap.c
changeset 0 e35f40988205
child 24 74f0b3eb154c
equal deleted inserted replaced
-1:000000000000 0:e35f40988205
       
     1 /** 
       
     2  * XML Security Library (http://www.aleksey.com/xmlsec).
       
     3  *
       
     4  * Simple SOAP messages parsing/creation.
       
     5  *
       
     6  * This is free software; see Copyright file in the source
       
     7  * distribution for preciese wording.
       
     8  * 
       
     9  * Copyright (C) 2002-2003 Aleksey Sanin <aleksey@aleksey.com>
       
    10  * Portion Copyright © 2009 Nokia Corporation and/or its subsidiary(-ies). All rights reserved. 
       
    11  */
       
    12 #include "xmlsec_config.h"
       
    13 #ifndef XMLSEC_NO_SOAP
       
    14 #include "xmlsec_globals.h"
       
    15 
       
    16 #include <stdlib.h>
       
    17 #include <string.h>
       
    18  
       
    19 #include <libxml2_tree.h>
       
    20 #include <libxml2_globals.h>
       
    21 
       
    22 #include "xmlsec_xmlsec.h"
       
    23 #include "xmlsec_xmltree.h"
       
    24 #include "xmlsec_soap.h"
       
    25 #include "xmlsec_errors.h"
       
    26 
       
    27 /***********************************************************************
       
    28  *
       
    29  * SOAP 1.1
       
    30  *
       
    31  **********************************************************************/
       
    32 /**
       
    33  * xmlSecSoap11CreateEnvelope:
       
    34  * @doc:        the parent doc (might be NULL).
       
    35  * 
       
    36  * Creates a new SOAP Envelope node. Caller is responsible for 
       
    37  * adding the returned node to the XML document.
       
    38  *
       
    39  * XML Schema (http://schemas.xmlsoap.org/soap/envelope/):
       
    40  *
       
    41  *     <xs:element name="Envelope" type="tns:Envelope"/>
       
    42  *     <xs:complexType name="Envelope">
       
    43  *         <xs:sequence>
       
    44  *             <xs:element ref="tns:Header" minOccurs="0"/>
       
    45  *             <xs:element ref="tns:Body" minOccurs="1"/>
       
    46  *             <xs:any namespace="##other" minOccurs="0" 
       
    47  *                 maxOccurs="unbounded" processContents="lax"/>
       
    48  *         </xs:sequence>
       
    49  *         <xs:anyAttribute namespace="##other" processContents="lax"/>
       
    50  *     </xs:complexType>
       
    51  *
       
    52  * Returns pointer to newly created <soap:Envelope> node or NULL
       
    53  * if an error occurs.
       
    54  */
       
    55 EXPORT_C
       
    56 xmlNodePtr 
       
    57 xmlSecSoap11CreateEnvelope(xmlDocPtr doc) {
       
    58     xmlNodePtr envNode;
       
    59     xmlNodePtr bodyNode;
       
    60     xmlNsPtr ns;
       
    61     
       
    62     /* create Envelope node */
       
    63     envNode = xmlNewDocNode(doc, NULL, xmlSecNodeEnvelope, NULL);
       
    64     if(envNode == NULL) {
       
    65 	xmlSecError(XMLSEC_ERRORS_HERE,
       
    66 		    NULL,
       
    67 		    "xmlNewDocNode",
       
    68 		    XMLSEC_ERRORS_R_XML_FAILED,
       
    69 		    "node=%s",
       
    70 		    xmlSecErrorsSafeString(xmlSecNodeEnvelope));
       
    71 	return(NULL);	            
       
    72     }
       
    73     
       
    74     ns = xmlNewNs(envNode, xmlSecSoap11Ns, NULL) ;
       
    75     if(ns == NULL) {
       
    76 	xmlSecError(XMLSEC_ERRORS_HERE,
       
    77 		    NULL,
       
    78 		    "xmlNewNs",
       
    79 		    XMLSEC_ERRORS_R_XML_FAILED,
       
    80 		    "ns=%s",
       
    81 		    xmlSecErrorsSafeString(xmlSecSoap11Ns));
       
    82 	xmlFreeNode(envNode);
       
    83 	return(NULL);	        	
       
    84     }
       
    85     xmlSetNs(envNode, ns);
       
    86     
       
    87     /* add required Body node */    
       
    88     bodyNode = xmlSecAddChild(envNode, xmlSecNodeBody, xmlSecSoap11Ns);
       
    89     if(bodyNode == NULL) {
       
    90 	xmlSecError(XMLSEC_ERRORS_HERE,
       
    91 		    NULL,
       
    92 		    "xmlSecAddChild",
       
    93 		    XMLSEC_ERRORS_R_XMLSEC_FAILED,
       
    94 		    "node=%s",
       
    95 		    xmlSecErrorsSafeString(xmlSecNodeBody));
       
    96 	xmlFreeNode(envNode);
       
    97 	return(NULL);	        	
       
    98     }
       
    99     
       
   100     return(envNode);
       
   101 }
       
   102 
       
   103 /**
       
   104  * xmlSecSoap11EnsureHeader:
       
   105  * @envNode:    the pointer to <soap:Envelope> node.
       
   106  * 
       
   107  * Gets the pointer to <soap:Header> node (if necessary, the node
       
   108  * is created).
       
   109  *
       
   110  * XML Schema (http://schemas.xmlsoap.org/soap/envelope/):
       
   111  *
       
   112  *     <xs:element name="Header" type="tns:Header"/>
       
   113  *     <xs:complexType name="Header">
       
   114  *         <xs:sequence>
       
   115  *             <xs:any namespace="##other" minOccurs="0" 
       
   116  *                 maxOccurs="unbounded" processContents="lax"/>
       
   117  *         </xs:sequence>
       
   118  *         <xs:anyAttribute namespace="##other" processContents="lax"/>
       
   119  *     </xs:complexType>
       
   120  *
       
   121  * Returns pointer to <soap:Header> node or NULL if an error occurs.
       
   122  */
       
   123 EXPORT_C
       
   124 xmlNodePtr 
       
   125 xmlSecSoap11EnsureHeader(xmlNodePtr envNode) {
       
   126     xmlNodePtr hdrNode;
       
   127     xmlNodePtr cur;
       
   128     
       
   129     xmlSecAssert2(envNode != NULL, NULL);
       
   130 
       
   131     /* try to find Header node first */
       
   132     cur = xmlSecGetNextElementNode(envNode->children);
       
   133     if((cur != NULL) && xmlSecCheckNodeName(cur, xmlSecNodeHeader, xmlSecSoap11Ns)) {
       
   134         return(cur);
       
   135     }
       
   136 
       
   137     /* if the first element child is not Header then it is Body */
       
   138     if((cur == NULL) || !xmlSecCheckNodeName(cur, xmlSecNodeBody, xmlSecSoap11Ns)) {
       
   139 	xmlSecError(XMLSEC_ERRORS_HERE,
       
   140 		    NULL,
       
   141 		    xmlSecErrorsSafeString(xmlSecNodeBody),
       
   142 		    XMLSEC_ERRORS_R_NODE_NOT_FOUND,
       
   143 		    XMLSEC_ERRORS_NO_MESSAGE);
       
   144 	return(NULL);	
       
   145     }
       
   146     
       
   147     /* finally add Header node before body */
       
   148     hdrNode = xmlSecAddPrevSibling(cur, xmlSecNodeHeader, xmlSecSoap11Ns);
       
   149     if(hdrNode == NULL) {
       
   150 	xmlSecError(XMLSEC_ERRORS_HERE,
       
   151 		    NULL,
       
   152                     "xmlSecAddPrevSibling",
       
   153 		    XMLSEC_ERRORS_R_XMLSEC_FAILED,
       
   154 		    XMLSEC_ERRORS_NO_MESSAGE);
       
   155         return(NULL);
       
   156     }
       
   157     
       
   158     return(hdrNode);
       
   159 }
       
   160 
       
   161 /**
       
   162  * xmlSecSoap11AddBodyEntry:
       
   163  * @envNode:            the pointer to <soap:Envelope> node.
       
   164  * @entryNode:          the pointer to body entry node.
       
   165  * 
       
   166  * Adds a new entry to <soap:Body> node.
       
   167  *
       
   168  * Returns pointer to the added entry (@contentNode) or NULL if an error occurs.
       
   169  */
       
   170 EXPORT_C
       
   171 xmlNodePtr
       
   172 xmlSecSoap11AddBodyEntry(xmlNodePtr envNode, xmlNodePtr entryNode) {
       
   173     xmlNodePtr bodyNode;
       
   174 
       
   175     xmlSecAssert2(envNode != NULL, NULL);
       
   176     xmlSecAssert2(entryNode != NULL, NULL);
       
   177 
       
   178     bodyNode = xmlSecSoap11GetBody(envNode);
       
   179     if(bodyNode == NULL) {
       
   180 	xmlSecError(XMLSEC_ERRORS_HERE,
       
   181 		    NULL,
       
   182 		    "xmlSecSoap11GetBody",
       
   183 		    XMLSEC_ERRORS_R_XMLSEC_FAILED,
       
   184 		    XMLSEC_ERRORS_NO_MESSAGE);
       
   185 	return(NULL);	        	
       
   186     }
       
   187 
       
   188     return(xmlSecAddChildNode(bodyNode, entryNode));
       
   189 }
       
   190 
       
   191 /**
       
   192  * xmlSecSoap11AddFaultEntry:
       
   193  * @envNode:            the pointer to <soap:Envelope> node.
       
   194  * @faultCodeHref:      the fault code QName href (must be known in th context of 
       
   195  *                      <soap:Body> node).
       
   196  * @faultCodeLocalPart: the fault code QName LocalPart.
       
   197  * @faultString:        the human readable explanation of the fault.
       
   198  * @faultActor:         the information about who caused the fault (might be NULL).
       
   199  *
       
   200  * Adds <soap:Fault> entry to the @envNode. Note that only one <soap:Fault>
       
   201  * entry is allowed.
       
   202  *
       
   203  * XML Schema (http://schemas.xmlsoap.org/soap/envelope/):
       
   204  *
       
   205  *     <xs:element name="Fault" type="tns:Fault"/>
       
   206  *     <xs:complexType name="Fault" final="extension">
       
   207  *         <xs:sequence>
       
   208  *             <xs:element name="faultcode" type="xs:QName"/>
       
   209  *             <xs:element name="faultstring" type="xs:string"/>
       
   210  *             <xs:element name="faultactor" type="xs:anyURI" minOccurs="0"/>
       
   211  *             <xs:element name="detail" type="tns:detail" minOccurs="0"/>
       
   212  *         </xs:sequence>
       
   213  *     </xs:complexType>
       
   214  *     <xs:complexType name="detail">
       
   215  *         <xs:sequence>
       
   216  *             <xs:any namespace="##any" minOccurs="0" maxOccurs="unbounded" 
       
   217  *                 processContents="lax"/>
       
   218  *         </xs:sequence>
       
   219  *         <xs:anyAttribute namespace="##any" processContents="lax"/>
       
   220  *     </xs:complexType>
       
   221  * 
       
   222  * Returns pointer to the added entry or NULL if an error occurs.
       
   223  */
       
   224 EXPORT_C
       
   225 xmlNodePtr
       
   226 xmlSecSoap11AddFaultEntry(xmlNodePtr envNode, const xmlChar* faultCodeHref, 
       
   227                           const xmlChar* faultCodeLocalPart, 
       
   228                           const xmlChar* faultString, const xmlChar* faultActor) {
       
   229     xmlNodePtr bodyNode;
       
   230     xmlNodePtr faultNode;
       
   231     xmlNodePtr cur;
       
   232     xmlChar* qname;
       
   233 
       
   234     xmlSecAssert2(envNode != NULL, NULL);
       
   235     xmlSecAssert2(faultCodeLocalPart != NULL, NULL);
       
   236     xmlSecAssert2(faultString != NULL, NULL);
       
   237 
       
   238     /* get Body node */
       
   239     bodyNode = xmlSecSoap11GetBody(envNode);
       
   240     if(bodyNode == NULL) {
       
   241 	xmlSecError(XMLSEC_ERRORS_HERE,
       
   242 		    NULL,
       
   243 		    "xmlSecSoap11GetBody",
       
   244 		    XMLSEC_ERRORS_R_XMLSEC_FAILED,
       
   245 		    XMLSEC_ERRORS_NO_MESSAGE);
       
   246 	return(NULL);	        	
       
   247     }
       
   248     
       
   249     /* check that we don't have Fault node already */
       
   250     faultNode = xmlSecFindChild(bodyNode, xmlSecNodeFault, xmlSecSoap11Ns);
       
   251     if(faultNode != NULL) {
       
   252 	xmlSecError(XMLSEC_ERRORS_HERE,
       
   253 		    NULL,
       
   254 		    xmlSecErrorsSafeString(xmlSecNodeBody),
       
   255 		    XMLSEC_ERRORS_R_NODE_ALREADY_PRESENT,
       
   256 		    XMLSEC_ERRORS_NO_MESSAGE);
       
   257 	return(NULL);	
       
   258     }
       
   259     
       
   260     /* add Fault node */
       
   261     faultNode = xmlSecAddChild(bodyNode, xmlSecNodeFault, xmlSecSoap11Ns);
       
   262     if(faultNode == NULL) {
       
   263 	xmlSecError(XMLSEC_ERRORS_HERE,
       
   264 		    NULL,
       
   265 		    "xmlSecAddChild",
       
   266 		    XMLSEC_ERRORS_R_XMLSEC_FAILED,
       
   267 		    "node=%s",
       
   268 		    xmlSecErrorsSafeString(xmlSecNodeFault));
       
   269 	return(NULL);	        	
       
   270     }
       
   271     
       
   272     /* add faultcode node */
       
   273     cur = xmlSecAddChild(faultNode, xmlSecNodeFaultCode, xmlSecSoap11Ns);
       
   274     if(cur == NULL) {
       
   275 	xmlSecError(XMLSEC_ERRORS_HERE,
       
   276 		    NULL,
       
   277 		    "xmlSecAddChild",
       
   278 		    XMLSEC_ERRORS_R_XMLSEC_FAILED,
       
   279 		    "node=%s",
       
   280 		    xmlSecErrorsSafeString(xmlSecNodeFaultCode));
       
   281         xmlUnlinkNode(faultNode);
       
   282         xmlFreeNode(faultNode);
       
   283 	return(NULL);	        	
       
   284     }
       
   285     
       
   286     /* create qname for fault code */
       
   287     qname = xmlSecGetQName(cur, faultCodeHref, faultCodeLocalPart);
       
   288     if(qname == NULL) {
       
   289         xmlSecError(XMLSEC_ERRORS_HERE,
       
   290                     NULL,
       
   291 	            "xmlSecGetQName",
       
   292 	            XMLSEC_ERRORS_R_XML_FAILED,
       
   293 	            "node=%s",
       
   294 	            xmlSecErrorsSafeString(cur->name));
       
   295         xmlUnlinkNode(faultNode);
       
   296         xmlFreeNode(faultNode);
       
   297 	return(NULL);	        	
       
   298     }
       
   299     
       
   300     /* set faultcode value */
       
   301     xmlNodeSetContent(cur, qname);
       
   302     xmlFree(qname);
       
   303 
       
   304     /* add faultstring node */
       
   305     cur = xmlSecAddChild(faultNode, xmlSecNodeFaultString, xmlSecSoap11Ns);
       
   306     if(cur == NULL) {
       
   307 	xmlSecError(XMLSEC_ERRORS_HERE,
       
   308 		    NULL,
       
   309 		    "xmlSecAddChild",
       
   310 		    XMLSEC_ERRORS_R_XMLSEC_FAILED,
       
   311 		    "node=%s",
       
   312 		    xmlSecErrorsSafeString(xmlSecNodeFaultString));
       
   313         xmlUnlinkNode(faultNode);
       
   314         xmlFreeNode(faultNode);
       
   315 	return(NULL);	        	
       
   316     }
       
   317 
       
   318     /* set faultstring node */
       
   319     xmlNodeSetContent(cur, faultString);
       
   320     
       
   321     if(faultActor != NULL) {
       
   322         /* add faultactor node */
       
   323         cur = xmlSecAddChild(faultNode, xmlSecNodeFaultActor, xmlSecSoap11Ns);
       
   324         if(cur == NULL) {
       
   325 	    xmlSecError(XMLSEC_ERRORS_HERE,
       
   326 		        NULL,
       
   327 		        "xmlSecAddChild",
       
   328 		        XMLSEC_ERRORS_R_XMLSEC_FAILED,
       
   329 		        "node=%s",
       
   330 		        xmlSecErrorsSafeString(xmlSecNodeFaultActor));
       
   331             xmlUnlinkNode(faultNode);
       
   332             xmlFreeNode(faultNode);
       
   333 	    return(NULL);	        	
       
   334         }
       
   335     
       
   336         /* set faultactor node */
       
   337         xmlNodeSetContent(cur, faultActor);
       
   338     }
       
   339     
       
   340     return(faultNode);
       
   341 }
       
   342 
       
   343 /**
       
   344  * xmlSecSoap11CheckEnvelope:
       
   345  * @envNode:    the pointer to <soap:Envelope> node.
       
   346  *
       
   347  * Validates <soap:Envelope> node structure.
       
   348  *
       
   349  * Returns 1 if @envNode has a valid <soap:Envelope> element, 0 if it is
       
   350  * not valid or a negative value if an error occurs.
       
   351  */
       
   352 EXPORT_C
       
   353 int 
       
   354 xmlSecSoap11CheckEnvelope(xmlNodePtr envNode) {
       
   355     xmlNodePtr cur;
       
   356     
       
   357     xmlSecAssert2(envNode != NULL, -1);
       
   358     
       
   359     /* verify envNode itself */
       
   360     if(!xmlSecCheckNodeName(envNode, xmlSecNodeEnvelope, xmlSecSoap11Ns)) {
       
   361 	xmlSecError(XMLSEC_ERRORS_HERE,
       
   362 		    NULL,
       
   363 		    xmlSecErrorsSafeString(xmlSecNodeEnvelope),
       
   364 		    XMLSEC_ERRORS_R_NODE_NOT_FOUND,
       
   365 		    XMLSEC_ERRORS_NO_MESSAGE);
       
   366 	return(0);	
       
   367     }
       
   368 
       
   369     /* optional Header node first */
       
   370     cur = xmlSecGetNextElementNode(envNode->children);
       
   371     if((cur != NULL) && xmlSecCheckNodeName(cur, xmlSecNodeHeader, xmlSecSoap11Ns)) {
       
   372         cur = xmlSecGetNextElementNode(cur->next);
       
   373     }
       
   374 
       
   375     /* required Body node is next */
       
   376     if((cur == NULL) || !xmlSecCheckNodeName(cur, xmlSecNodeBody, xmlSecSoap11Ns)) {
       
   377 	xmlSecError(XMLSEC_ERRORS_HERE,
       
   378 		    NULL,
       
   379 		    xmlSecErrorsSafeString(xmlSecNodeBody),
       
   380 		    XMLSEC_ERRORS_R_NODE_NOT_FOUND,
       
   381 		    XMLSEC_ERRORS_NO_MESSAGE);
       
   382 	return(0);	
       
   383     }
       
   384     
       
   385     return(1);
       
   386 }
       
   387 
       
   388 /**
       
   389  * xmlSecSoap11GetHeader:
       
   390  * @envNode:    the pointer to <soap:Envelope> node.
       
   391  * 
       
   392  * Gets pointer to the <soap:Header> node.
       
   393  *
       
   394  * Returns pointer to <soap:Header> node or NULL if an error occurs.
       
   395  */
       
   396 EXPORT_C
       
   397 xmlNodePtr 
       
   398 xmlSecSoap11GetHeader(xmlNodePtr envNode) {
       
   399     xmlNodePtr cur;
       
   400     
       
   401     xmlSecAssert2(envNode != NULL, NULL);
       
   402 
       
   403     /* optional Header node is first */
       
   404     cur = xmlSecGetNextElementNode(envNode->children);
       
   405     if((cur != NULL) && xmlSecCheckNodeName(cur, xmlSecNodeHeader, xmlSecSoap11Ns)) {
       
   406         return(cur);
       
   407     }
       
   408 
       
   409     return(NULL);
       
   410 }
       
   411 
       
   412 /**
       
   413  * xmlSecSoap11GetBody:
       
   414  * @envNode:    the pointer to <soap:Envelope> node.
       
   415  * 
       
   416  * Gets pointer to the <soap:Body> node.
       
   417  *
       
   418  * Returns pointer to <soap:Body> node or NULL if an error occurs.
       
   419  */
       
   420 EXPORT_C
       
   421 xmlNodePtr 
       
   422 xmlSecSoap11GetBody(xmlNodePtr envNode) {
       
   423     xmlNodePtr cur;
       
   424     
       
   425     xmlSecAssert2(envNode != NULL, NULL);
       
   426 
       
   427     /* optional Header node first */
       
   428     cur = xmlSecGetNextElementNode(envNode->children);
       
   429     if((cur != NULL) && xmlSecCheckNodeName(cur, xmlSecNodeHeader, xmlSecSoap11Ns)) {
       
   430         cur = xmlSecGetNextElementNode(cur->next);
       
   431     }
       
   432 
       
   433     /* Body node is next */
       
   434     if((cur == NULL) || !xmlSecCheckNodeName(cur, xmlSecNodeBody, xmlSecSoap11Ns)) {
       
   435 	xmlSecError(XMLSEC_ERRORS_HERE,
       
   436 		    NULL,
       
   437 		    xmlSecErrorsSafeString(xmlSecNodeBody),
       
   438 		    XMLSEC_ERRORS_R_NODE_NOT_FOUND,
       
   439 		    XMLSEC_ERRORS_NO_MESSAGE);
       
   440 	return(NULL);	
       
   441     }
       
   442 
       
   443     return(cur);
       
   444 }
       
   445 
       
   446 /**
       
   447  * xmlSecSoap11GetBodyEntriesNumber:
       
   448  * @envNode:    the pointer to <soap:Envelope> node.
       
   449  *
       
   450  * Gets the number of body entries.
       
   451  *
       
   452  * Returns the number of body entries.
       
   453  */
       
   454 EXPORT_C
       
   455 xmlSecSize 
       
   456 xmlSecSoap11GetBodyEntriesNumber(xmlNodePtr envNode) {
       
   457     xmlSecSize number = 0;
       
   458     xmlNodePtr bodyNode;
       
   459     xmlNodePtr cur;
       
   460     
       
   461     xmlSecAssert2(envNode != NULL, 0);
       
   462 
       
   463     /* get Body node */
       
   464     bodyNode = xmlSecSoap11GetBody(envNode);
       
   465     if(bodyNode == NULL) {
       
   466 	xmlSecError(XMLSEC_ERRORS_HERE,
       
   467 		    NULL,
       
   468 		    "xmlSecSoap11GetBody",
       
   469 		    XMLSEC_ERRORS_R_XMLSEC_FAILED,
       
   470 		    XMLSEC_ERRORS_NO_MESSAGE);
       
   471 	return(0);
       
   472     }
       
   473 
       
   474     cur = xmlSecGetNextElementNode(bodyNode->children);
       
   475     while(cur != NULL) {
       
   476         number++;
       
   477         cur = xmlSecGetNextElementNode(cur->next);
       
   478     }
       
   479     
       
   480     return(number);
       
   481 }
       
   482 
       
   483 /**
       
   484  * xmlSecSoap11GetBodyEntry:
       
   485  * @envNode:    the pointer to <soap:Envelope> node.
       
   486  * @pos:        the body entry number.
       
   487  * 
       
   488  * Gets the body entry number @pos.
       
   489  *
       
   490  * Returns pointer to body entry node or NULL if an error occurs.
       
   491  */
       
   492 EXPORT_C
       
   493 xmlNodePtr 
       
   494 xmlSecSoap11GetBodyEntry(xmlNodePtr envNode, xmlSecSize pos) {
       
   495     xmlNodePtr bodyNode;
       
   496     xmlNodePtr cur;
       
   497  
       
   498     xmlSecAssert2(envNode != NULL, NULL);
       
   499 
       
   500     /* get Body node */
       
   501     bodyNode = xmlSecSoap11GetBody(envNode);
       
   502     if(bodyNode == NULL) {
       
   503 	xmlSecError(XMLSEC_ERRORS_HERE,
       
   504 		    NULL,
       
   505 		    "xmlSecSoap11GetBody",
       
   506 		    XMLSEC_ERRORS_R_XMLSEC_FAILED,
       
   507 		    XMLSEC_ERRORS_NO_MESSAGE);
       
   508 	return(NULL);	        	
       
   509     }
       
   510 
       
   511     cur = xmlSecGetNextElementNode(bodyNode->children);
       
   512     while((cur != NULL) && (pos > 0)) {
       
   513         pos--;
       
   514         cur = xmlSecGetNextElementNode(cur->next);
       
   515     }
       
   516 
       
   517     return(cur);
       
   518 }
       
   519 
       
   520 /**
       
   521  * xmlSecSoap11GetFaultEntry:
       
   522  * @envNode:    the pointer to <soap:Envelope> node.
       
   523  * 
       
   524  * Gets the Fault entry (if any).
       
   525  *
       
   526  * Returns pointer to Fault entry or NULL if it does not exist.
       
   527  */
       
   528 EXPORT_C
       
   529 xmlNodePtr 
       
   530 xmlSecSoap11GetFaultEntry(xmlNodePtr envNode) {
       
   531     xmlNodePtr bodyNode;
       
   532 
       
   533     xmlSecAssert2(envNode != NULL, NULL);
       
   534 
       
   535     /* get Body node */
       
   536     bodyNode = xmlSecSoap11GetBody(envNode);
       
   537     if(bodyNode == NULL) {
       
   538 	xmlSecError(XMLSEC_ERRORS_HERE,
       
   539 		    NULL,
       
   540 		    "xmlSecSoap11GetBody",
       
   541 		    XMLSEC_ERRORS_R_XMLSEC_FAILED,
       
   542 		    XMLSEC_ERRORS_NO_MESSAGE);
       
   543 	return(NULL);	        	
       
   544     }
       
   545 
       
   546     return(xmlSecFindChild(bodyNode, xmlSecNodeFault, xmlSecSoap11Ns));
       
   547 }
       
   548 								 
       
   549 
       
   550 /***********************************************************************
       
   551  *
       
   552  * SOAP 1.2
       
   553  *
       
   554  **********************************************************************/
       
   555 static const xmlSecQName2IntegerInfo gXmlSecSoap12FaultCodeInfo[] = 
       
   556 {
       
   557     { xmlSecSoap12Ns, xmlSecSoapFaultCodeVersionMismatch,
       
   558       xmlSecSoap12FaultCodeVersionMismatch },
       
   559     { xmlSecSoap12Ns, xmlSecSoapFaultCodeMustUnderstand,
       
   560       xmlSecSoap12FaultCodeMustUnderstand },
       
   561     { xmlSecSoap12Ns, xmlSecSoapFaultDataEncodningUnknown,
       
   562       xmlSecSoap12FaultCodeDataEncodingUnknown },
       
   563     { xmlSecSoap12Ns, xmlSecSoapFaultCodeSender,
       
   564       xmlSecSoap12FaultCodeSender },
       
   565     { xmlSecSoap12Ns, xmlSecSoapFaultCodeReceiver,
       
   566       xmlSecSoap12FaultCodeReceiver },
       
   567     { NULL, NULL, 0 }	/* MUST be last in the list */
       
   568 };
       
   569 
       
   570 /**
       
   571  * xmlSecSoap12CreateEnvelope:
       
   572  * @doc:        the parent doc (might be NULL).
       
   573  * 
       
   574  * Creates a new SOAP 1.2 Envelope node. Caller is responsible for 
       
   575  * adding the returned node to the XML document.
       
   576  *
       
   577  * XML Schema (http://www.w3.org/2003/05/soap-envelope):
       
   578  * 
       
   579  *     <xs:element name="Envelope" type="tns:Envelope"/>
       
   580  *     <xs:complexType name="Envelope">
       
   581  *         <xs:sequence>
       
   582  *             <xs:element ref="tns:Header" minOccurs="0"/>
       
   583  *             <xs:element ref="tns:Body" minOccurs="1"/>
       
   584  *         </xs:sequence>
       
   585  *         <xs:anyAttribute namespace="##other" processContents="lax"/>
       
   586  *     </xs:complexType>
       
   587  *
       
   588  * Returns pointer to newly created <soap:Envelope> node or NULL
       
   589  * if an error occurs.
       
   590  */
       
   591 EXPORT_C
       
   592 xmlNodePtr 
       
   593 xmlSecSoap12CreateEnvelope(xmlDocPtr doc) {
       
   594     xmlNodePtr envNode;
       
   595     xmlNodePtr bodyNode;
       
   596     xmlNsPtr ns;
       
   597     
       
   598     /* create Envelope node */
       
   599     envNode = xmlNewDocNode(doc, NULL, xmlSecNodeEnvelope, NULL);
       
   600     if(envNode == NULL) {
       
   601 	xmlSecError(XMLSEC_ERRORS_HERE,
       
   602 		    NULL,
       
   603 		    "xmlNewDocNode",
       
   604 		    XMLSEC_ERRORS_R_XML_FAILED,
       
   605 		    "node=%s",
       
   606 		    xmlSecErrorsSafeString(xmlSecNodeEnvelope));
       
   607 	return(NULL);	            
       
   608     }
       
   609     
       
   610     ns = xmlNewNs(envNode, xmlSecSoap12Ns, NULL) ;
       
   611     if(ns == NULL) {
       
   612 	xmlSecError(XMLSEC_ERRORS_HERE,
       
   613 		    NULL,
       
   614 		    "xmlNewNs",
       
   615 		    XMLSEC_ERRORS_R_XML_FAILED,
       
   616 		    "ns=%s",
       
   617 		    xmlSecErrorsSafeString(xmlSecSoap12Ns));
       
   618 	xmlFreeNode(envNode);
       
   619 	return(NULL);	        	
       
   620     }
       
   621     xmlSetNs(envNode, ns);
       
   622     
       
   623     /* add required Body node */    
       
   624     bodyNode = xmlSecAddChild(envNode, xmlSecNodeBody, xmlSecSoap12Ns);
       
   625     if(bodyNode == NULL) {
       
   626 	xmlSecError(XMLSEC_ERRORS_HERE,
       
   627 		    NULL,
       
   628 		    "xmlSecAddChild",
       
   629 		    XMLSEC_ERRORS_R_XMLSEC_FAILED,
       
   630 		    "node=%s",
       
   631 		    xmlSecErrorsSafeString(xmlSecNodeBody));
       
   632 	xmlFreeNode(envNode);
       
   633 	return(NULL);	        	
       
   634     }
       
   635     
       
   636     return(envNode);
       
   637 }
       
   638 
       
   639 /**
       
   640  * xmlSecSoap12EnsureHeader:
       
   641  * @envNode:    the pointer to <soap:Envelope> node.
       
   642  * 
       
   643  * Gets the pointer to <soap:Header> node (if necessary, the node
       
   644  * is created).
       
   645  *
       
   646  * XML Schema (http://www.w3.org/2003/05/soap-envelope):
       
   647  *
       
   648  *     <xs:element name="Header" type="tns:Header"/>
       
   649  *     <xs:complexType name="Header">
       
   650  *         <xs:sequence>
       
   651  *             <xs:any namespace="##any" processContents="lax" 
       
   652  *                     minOccurs="0" maxOccurs="unbounded"/>
       
   653  *         </xs:sequence>
       
   654  *         <xs:anyAttribute namespace="##other" processContents="lax"/>
       
   655  *     </xs:complexType>
       
   656  *
       
   657  * Returns pointer to <soap:Header> node or NULL if an error occurs.
       
   658  */
       
   659 EXPORT_C
       
   660 xmlNodePtr 
       
   661 xmlSecSoap12EnsureHeader(xmlNodePtr envNode) {
       
   662     xmlNodePtr hdrNode;
       
   663     xmlNodePtr cur;
       
   664     
       
   665     xmlSecAssert2(envNode != NULL, NULL);
       
   666 
       
   667     /* try to find Header node first */
       
   668     cur = xmlSecGetNextElementNode(envNode->children);
       
   669     if((cur != NULL) && xmlSecCheckNodeName(cur, xmlSecNodeHeader, xmlSecSoap12Ns)) {
       
   670         return(cur);
       
   671     }
       
   672 
       
   673     /* if the first element child is not Header then it is Body */
       
   674     if((cur == NULL) || !xmlSecCheckNodeName(cur, xmlSecNodeBody, xmlSecSoap12Ns)) {
       
   675 	xmlSecError(XMLSEC_ERRORS_HERE,
       
   676 		    NULL,
       
   677 		    xmlSecErrorsSafeString(xmlSecNodeBody),
       
   678 		    XMLSEC_ERRORS_R_NODE_NOT_FOUND,
       
   679 		    XMLSEC_ERRORS_NO_MESSAGE);
       
   680 	return(NULL);	
       
   681     }
       
   682     
       
   683     /* finally add Header node before body */
       
   684     hdrNode = xmlSecAddPrevSibling(cur, xmlSecNodeHeader, xmlSecSoap12Ns);
       
   685     if(hdrNode == NULL) {
       
   686 	xmlSecError(XMLSEC_ERRORS_HERE,
       
   687 		    NULL,
       
   688                     "xmlSecAddPrevSibling",
       
   689 		    XMLSEC_ERRORS_R_XMLSEC_FAILED,
       
   690 		    XMLSEC_ERRORS_NO_MESSAGE);
       
   691         return(NULL);
       
   692     }
       
   693     
       
   694     return(hdrNode);
       
   695 }
       
   696 
       
   697 /**
       
   698  * xmlSecSoap12AddBodyEntry:
       
   699  * @envNode:            the pointer to <soap:Envelope> node.
       
   700  * @entryNode:          the pointer to body entry node.
       
   701  * 
       
   702  * Adds a new entry to <soap:Body> node.
       
   703  *
       
   704  * XML Schema (http://www.w3.org/2003/05/soap-envelope):
       
   705  *
       
   706  *     <xs:element name="Body" type="tns:Body"/>
       
   707  *     <xs:complexType name="Body">
       
   708  *         <xs:sequence>
       
   709  *             <xs:any namespace="##any" processContents="lax" 
       
   710  *                     minOccurs="0" maxOccurs="unbounded"/>
       
   711  *         </xs:sequence>
       
   712  *         <xs:anyAttribute namespace="##other" processContents="lax"/>
       
   713  *     </xs:complexType>
       
   714  *
       
   715  * Returns pointer to the added entry (@contentNode) or NULL if an error occurs.
       
   716  */
       
   717 EXPORT_C
       
   718 xmlNodePtr
       
   719 xmlSecSoap12AddBodyEntry(xmlNodePtr envNode, xmlNodePtr entryNode) {
       
   720     xmlNodePtr bodyNode;
       
   721 
       
   722     xmlSecAssert2(envNode != NULL, NULL);
       
   723     xmlSecAssert2(entryNode != NULL, NULL);
       
   724 
       
   725     bodyNode = xmlSecSoap12GetBody(envNode);
       
   726     if(bodyNode == NULL) {
       
   727 	xmlSecError(XMLSEC_ERRORS_HERE,
       
   728 		    NULL,
       
   729 		    "xmlSecSoap12GetBody",
       
   730 		    XMLSEC_ERRORS_R_XMLSEC_FAILED,
       
   731 		    XMLSEC_ERRORS_NO_MESSAGE);
       
   732 	return(NULL);	        	
       
   733     }
       
   734 
       
   735     return(xmlSecAddChildNode(bodyNode, entryNode));
       
   736 }
       
   737 
       
   738 /**
       
   739  * xmlSecSoap12AddFaultEntry:
       
   740  * @envNode:            the pointer to <soap:Envelope> node.
       
   741  * @faultCode:          the fault code.
       
   742  * @faultReasonText:    the human readable explanation of the fault.
       
   743  * @faultReasonLang:    the language (xml:lang) for @faultReason string.
       
   744  * @faultNodeURI:       the more preciese information about fault source 
       
   745  *                      (might be NULL).
       
   746  * @faultRole:          the role the node was operating in at the point 
       
   747  *                      the fault occurred (might be NULL).
       
   748  *
       
   749  * Adds <soap:Fault> entry to the @envNode. Note that only one <soap:Fault>
       
   750  * entry is allowed.
       
   751  *
       
   752  * XML Schema (http://www.w3.org/2003/05/soap-envelope):
       
   753  *
       
   754  *     <xs:element name="Fault" type="tns:Fault"/>
       
   755  *     <xs:complexType name="Fault" final="extension">
       
   756  *         <xs:sequence>
       
   757  *             <xs:element name="Code" type="tns:faultcode"/>
       
   758  *             <xs:element name="Reason" type="tns:faultreason"/>
       
   759  *             <xs:element name="Node" type="xs:anyURI" minOccurs="0"/>
       
   760  *             <xs:element name="Role" type="xs:anyURI" minOccurs="0"/>
       
   761  *             <xs:element name="Detail" type="tns:detail" minOccurs="0"/>
       
   762  *         </xs:sequence>
       
   763  *     </xs:complexType>
       
   764  *     
       
   765  *     <xs:complexType name="faultcode">
       
   766  *         <xs:sequence>
       
   767  *             <xs:element name="Value" type="tns:faultcodeEnum"/>
       
   768  *             <xs:element name="Subcode" type="tns:subcode" minOccurs="0"/>
       
   769  *         </xs:sequence>
       
   770  *     </xs:complexType>
       
   771  *     
       
   772  *     <xs:complexType name="faultreason">
       
   773  *         <xs:sequence>
       
   774  *             <xs:element name="Text" type="tns:reasontext" 
       
   775  *                         minOccurs="1" maxOccurs="unbounded"/>
       
   776  *         </xs:sequence>
       
   777  *     </xs:complexType>
       
   778  *     
       
   779  *     <xs:complexType name="reasontext">
       
   780  *         <xs:simpleContent>
       
   781  *             <xs:extension base="xs:string">
       
   782  *                 <xs:attribute ref="xml:lang" use="required"/>
       
   783  *             </xs:extension>
       
   784  *         </xs:simpleContent>
       
   785  *     </xs:complexType>
       
   786  *     
       
   787  *     <xs:simpleType name="faultcodeEnum">
       
   788  *         <xs:restriction base="xs:QName">
       
   789  *             <xs:enumeration value="tns:DataEncodingUnknown"/>
       
   790  *             <xs:enumeration value="tns:MustUnderstand"/>
       
   791  *             <xs:enumeration value="tns:Receiver"/>
       
   792  *             <xs:enumeration value="tns:Sender"/>
       
   793  *             <xs:enumeration value="tns:VersionMismatch"/>
       
   794  *         </xs:restriction>
       
   795  *     </xs:simpleType>
       
   796  *     
       
   797  *     <xs:complexType name="subcode">
       
   798  *         <xs:sequence>
       
   799  *             <xs:element name="Value" type="xs:QName"/>
       
   800  *             <xs:element name="Subcode" type="tns:subcode" minOccurs="0"/>
       
   801  *         </xs:sequence>
       
   802  *     </xs:complexType>
       
   803  *     
       
   804  *     <xs:complexType name="detail">
       
   805  *         <xs:sequence>
       
   806  *             <xs:any namespace="##any" processContents="lax" 
       
   807  *                 minOccurs="0" maxOccurs="unbounded"/>
       
   808  *         </xs:sequence>
       
   809  *         <xs:anyAttribute namespace="##other" processContents="lax"/>
       
   810  *     </xs:complexType>
       
   811  *     
       
   812  * Returns pointer to the added entry or NULL if an error occurs.
       
   813  */
       
   814 EXPORT_C
       
   815 xmlNodePtr
       
   816 xmlSecSoap12AddFaultEntry(xmlNodePtr envNode, xmlSecSoap12FaultCode faultCode,
       
   817 			 const xmlChar* faultReasonText, const xmlChar* faultReasonLang,
       
   818 			 const xmlChar* faultNodeURI, const xmlChar* faultRole) {
       
   819     xmlNodePtr bodyNode;
       
   820     xmlNodePtr faultNode;
       
   821     xmlNodePtr cur;
       
   822     int ret;
       
   823 
       
   824     xmlSecAssert2(envNode != NULL, NULL);
       
   825     xmlSecAssert2(faultCode != xmlSecSoap12FaultCodeUnknown, NULL);
       
   826     xmlSecAssert2(faultReasonText != NULL, NULL);
       
   827     xmlSecAssert2(faultReasonLang != NULL, NULL);
       
   828 
       
   829     /* get Body node */
       
   830     bodyNode = xmlSecSoap12GetBody(envNode);
       
   831     if(bodyNode == NULL) {
       
   832 	xmlSecError(XMLSEC_ERRORS_HERE,
       
   833 		    NULL,
       
   834 		    "xmlSecSoap12GetBody",
       
   835 		    XMLSEC_ERRORS_R_XMLSEC_FAILED,
       
   836 		    XMLSEC_ERRORS_NO_MESSAGE);
       
   837 	return(NULL);	        	
       
   838     }
       
   839     
       
   840     /* check that we don't have Fault node already */
       
   841     faultNode = xmlSecFindChild(bodyNode, xmlSecNodeFault, xmlSecSoap12Ns);
       
   842     if(faultNode != NULL) {
       
   843 	xmlSecError(XMLSEC_ERRORS_HERE,
       
   844 		    NULL,
       
   845 		    xmlSecErrorsSafeString(xmlSecNodeBody),
       
   846 		    XMLSEC_ERRORS_R_NODE_ALREADY_PRESENT,
       
   847 		    XMLSEC_ERRORS_NO_MESSAGE);
       
   848 	return(NULL);	
       
   849     }
       
   850     
       
   851     /* add Fault node */
       
   852     faultNode = xmlSecAddChild(bodyNode, xmlSecNodeFault, xmlSecSoap12Ns);
       
   853     if(faultNode == NULL) {
       
   854 	xmlSecError(XMLSEC_ERRORS_HERE,
       
   855 		    NULL,
       
   856 		    "xmlSecAddChild",
       
   857 		    XMLSEC_ERRORS_R_XMLSEC_FAILED,
       
   858 		    "node=%s",
       
   859 		    xmlSecErrorsSafeString(xmlSecNodeFault));
       
   860 	return(NULL);	        	
       
   861     }
       
   862     
       
   863     /* add Code node */
       
   864     cur = xmlSecAddChild(faultNode, xmlSecNodeCode, xmlSecSoap12Ns);
       
   865     if(cur == NULL) {
       
   866 	xmlSecError(XMLSEC_ERRORS_HERE,
       
   867 		    NULL,
       
   868 		    "xmlSecAddChild",
       
   869 		    XMLSEC_ERRORS_R_XMLSEC_FAILED,
       
   870 		    "node=%s",
       
   871 		    xmlSecErrorsSafeString(xmlSecNodeCode));
       
   872         xmlUnlinkNode(faultNode);
       
   873         xmlFreeNode(faultNode);
       
   874 	return(NULL);	        	
       
   875     }
       
   876     
       
   877     /* write the fault code in Value child */
       
   878     ret = xmlSecQName2IntegerNodeWrite(gXmlSecSoap12FaultCodeInfo, cur,
       
   879                                        xmlSecNodeValue, xmlSecSoap12Ns,
       
   880                                        faultCode);
       
   881     if(ret < 0) {
       
   882 	xmlSecError(XMLSEC_ERRORS_HERE,
       
   883 		    NULL,
       
   884 		    "xmlSecQName2IntegerNodeWrite",
       
   885 		    XMLSEC_ERRORS_R_XMLSEC_FAILED,
       
   886 		    "faultCode=%d",
       
   887 		    faultCode);
       
   888         xmlUnlinkNode(faultNode);
       
   889         xmlFreeNode(faultNode);
       
   890 	return(NULL);	
       
   891     }
       
   892 
       
   893     /* add Reason node */
       
   894     cur = xmlSecAddChild(faultNode, xmlSecNodeReason, xmlSecSoap12Ns);
       
   895     if(cur == NULL) {
       
   896 	xmlSecError(XMLSEC_ERRORS_HERE,
       
   897 		    NULL,
       
   898 		    "xmlSecAddChild",
       
   899 		    XMLSEC_ERRORS_R_XMLSEC_FAILED,
       
   900 		    "node=%s",
       
   901 		    xmlSecErrorsSafeString(xmlSecNodeReason));
       
   902         xmlUnlinkNode(faultNode);
       
   903         xmlFreeNode(faultNode);
       
   904 	return(NULL);	        	
       
   905     }
       
   906     
       
   907     /* Add Reason/Text node */
       
   908     if(xmlSecSoap12AddFaultReasonText(faultNode, faultReasonText, faultReasonLang) == NULL) {
       
   909 	xmlSecError(XMLSEC_ERRORS_HERE,
       
   910 		    NULL,
       
   911 		    "xmlSecSoap12AddFaultReasonText",
       
   912 		    XMLSEC_ERRORS_R_XMLSEC_FAILED,
       
   913 		    "text=%s",
       
   914 		    xmlSecErrorsSafeString(faultReasonText));
       
   915         xmlUnlinkNode(faultNode);
       
   916         xmlFreeNode(faultNode);
       
   917 	return(NULL);	        	
       
   918     }
       
   919 
       
   920     if(faultNodeURI != NULL) {
       
   921         /* add Node node */
       
   922         cur = xmlSecAddChild(faultNode, xmlSecNodeNode, xmlSecSoap12Ns);
       
   923         if(cur == NULL) {
       
   924 	    xmlSecError(XMLSEC_ERRORS_HERE,
       
   925 		        NULL,
       
   926 		        "xmlSecAddChild",
       
   927 		        XMLSEC_ERRORS_R_XMLSEC_FAILED,
       
   928 		        "node=%s",
       
   929 		        xmlSecErrorsSafeString(xmlSecNodeNode));
       
   930             xmlUnlinkNode(faultNode);
       
   931             xmlFreeNode(faultNode);
       
   932 	    return(NULL);	        	
       
   933         }
       
   934         xmlNodeSetContent(cur, faultNodeURI);
       
   935     }
       
   936 
       
   937     if(faultRole != NULL) {
       
   938         /* add Role node */
       
   939         cur = xmlSecAddChild(faultNode, xmlSecNodeRole, xmlSecSoap12Ns);
       
   940         if(cur == NULL) {
       
   941 	    xmlSecError(XMLSEC_ERRORS_HERE,
       
   942 		        NULL,
       
   943 		        "xmlSecAddChild",
       
   944 		        XMLSEC_ERRORS_R_XMLSEC_FAILED,
       
   945 		        "node=%s",
       
   946 		        xmlSecErrorsSafeString(xmlSecNodeRole));
       
   947             xmlUnlinkNode(faultNode);
       
   948             xmlFreeNode(faultNode);
       
   949 	    return(NULL);	        	
       
   950         }
       
   951         xmlNodeSetContent(cur, faultRole);
       
   952     }
       
   953     
       
   954     return(faultNode);
       
   955 }
       
   956 
       
   957 /**
       
   958  * xmlSecSoap12AddFaultSubcode:
       
   959  * @faultNode:          the pointer to <Fault> node.
       
   960  * @subCodeHref:        the subcode href.
       
   961  * @subCodeName:        the subcode name.
       
   962  *
       
   963  * Adds a new <Subcode> node to the <Code> node or the last <Subcode> node.
       
   964  *
       
   965  * Returns a pointer to the newly created <Subcode> node or NULL if an error
       
   966  * occurs.
       
   967  */
       
   968 EXPORT_C
       
   969 xmlNodePtr 
       
   970 xmlSecSoap12AddFaultSubcode(xmlNodePtr faultNode, const xmlChar* subCodeHref, const xmlChar* subCodeName) {
       
   971     xmlNodePtr cur, subcodeNode, valueNode;
       
   972     xmlChar* qname;
       
   973 
       
   974     xmlSecAssert2(faultNode != NULL, NULL);
       
   975     xmlSecAssert2(subCodeHref != NULL, NULL);
       
   976     xmlSecAssert2(subCodeName != NULL, NULL);
       
   977 
       
   978     /* Code node is the first childern in Fault node */
       
   979     cur = xmlSecGetNextElementNode(faultNode->children);
       
   980     if((cur == NULL) || !xmlSecCheckNodeName(cur, xmlSecNodeCode, xmlSecSoap12Ns)) {
       
   981         xmlSecError(XMLSEC_ERRORS_HERE,
       
   982 		    NULL,
       
   983                     NULL,
       
   984 	    	    XMLSEC_ERRORS_R_INVALID_NODE,
       
   985 		    "node=%s",
       
   986     		    xmlSecErrorsSafeString(xmlSecNodeCode));
       
   987         return(NULL);
       
   988     }
       
   989 
       
   990     /* find the Code or Subcode node that does not have Subcode child */
       
   991     while(1) {
       
   992         xmlNodePtr tmp;
       
   993 
       
   994         tmp = xmlSecFindChild(cur, xmlSecNodeSubcode, xmlSecSoap12Ns);
       
   995         if(tmp != NULL) {
       
   996             cur = tmp;
       
   997         } else {
       
   998             break;
       
   999         }
       
  1000     }
       
  1001     xmlSecAssert2(cur != NULL, NULL);
       
  1002 
       
  1003     /* add Subcode node */
       
  1004     subcodeNode = xmlSecAddChild(cur, xmlSecNodeSubcode, xmlSecSoap12Ns);
       
  1005     if(subcodeNode == NULL) {
       
  1006 	xmlSecError(XMLSEC_ERRORS_HERE,
       
  1007 		    NULL,
       
  1008 		    "xmlSecAddChild",
       
  1009 		    XMLSEC_ERRORS_R_XMLSEC_FAILED,
       
  1010 		    "node=%s",
       
  1011 		    xmlSecErrorsSafeString(xmlSecNodeSubcode));
       
  1012 	return(NULL);	        	
       
  1013     }
       
  1014 
       
  1015     /* add Value node */
       
  1016     valueNode = xmlSecAddChild(subcodeNode, xmlSecNodeValue, xmlSecSoap12Ns);
       
  1017     if(valueNode == NULL) {
       
  1018 	xmlSecError(XMLSEC_ERRORS_HERE,
       
  1019 		    NULL,
       
  1020 		    "xmlSecAddChild",
       
  1021 		    XMLSEC_ERRORS_R_XMLSEC_FAILED,
       
  1022 		    "node=%s",
       
  1023 		    xmlSecErrorsSafeString(xmlSecNodeValue));
       
  1024         xmlUnlinkNode(subcodeNode);
       
  1025         xmlFreeNode(subcodeNode);
       
  1026 	return(NULL);	        	
       
  1027     }
       
  1028 
       
  1029     /* create qname for fault code */
       
  1030     qname = xmlSecGetQName(cur, subCodeHref, subCodeName);
       
  1031     if(qname == NULL) {
       
  1032         xmlSecError(XMLSEC_ERRORS_HERE,
       
  1033                     NULL,
       
  1034 	            "xmlSecGetQName",
       
  1035 	            XMLSEC_ERRORS_R_XML_FAILED,
       
  1036 	            "node=%s",
       
  1037 	            xmlSecErrorsSafeString(cur->name));
       
  1038         xmlUnlinkNode(subcodeNode);
       
  1039         xmlFreeNode(subcodeNode);
       
  1040 	return(NULL);	        	
       
  1041     }
       
  1042 
       
  1043     /* set result qname in Value node */
       
  1044     xmlNodeSetContent(cur, qname);
       
  1045     if(qname != subCodeName) {
       
  1046         xmlFree(qname);
       
  1047     }
       
  1048 
       
  1049     return(subcodeNode);
       
  1050 }
       
  1051 
       
  1052 /**
       
  1053  * xmlSecSoap12AddFaultReasonText:
       
  1054  * @faultNode:          the pointer to <Fault> node.
       
  1055  * @faultReasonText:    the new reason text.
       
  1056  * @faultReasonLang:    the new reason xml:lang attribute.
       
  1057  *
       
  1058  * Adds a new Text node to the Fault/Reason node.
       
  1059  *
       
  1060  * Returns a pointer to the newly created <Text> node or NULL if an error
       
  1061  * occurs.
       
  1062  */
       
  1063 EXPORT_C
       
  1064 xmlNodePtr 
       
  1065 xmlSecSoap12AddFaultReasonText(xmlNodePtr faultNode, const xmlChar* faultReasonText, 
       
  1066                                const xmlChar* faultReasonLang) {
       
  1067     xmlNodePtr reasonNode;
       
  1068     xmlNodePtr textNode;
       
  1069 
       
  1070     xmlSecAssert2(faultNode != NULL, NULL);
       
  1071     xmlSecAssert2(faultReasonText != NULL, NULL);
       
  1072     xmlSecAssert2(faultReasonLang != NULL, NULL);
       
  1073 
       
  1074     /* find Reason node */
       
  1075     reasonNode = xmlSecFindChild(faultNode,  xmlSecNodeReason, xmlSecSoap12Ns);
       
  1076     if(reasonNode == NULL) {
       
  1077 	xmlSecError(XMLSEC_ERRORS_HERE,
       
  1078 		    NULL,
       
  1079 		    "xmlSecFindChild",
       
  1080 		    XMLSEC_ERRORS_R_XMLSEC_FAILED,
       
  1081 		    "node=%s",
       
  1082 		    xmlSecErrorsSafeString(xmlSecNodeReason));
       
  1083 	return(NULL);	        	
       
  1084     }
       
  1085 
       
  1086     /* add Text node */
       
  1087     textNode = xmlSecAddChild(reasonNode, xmlSecNodeText, xmlSecSoap12Ns);
       
  1088     if(textNode == NULL) {
       
  1089 	xmlSecError(XMLSEC_ERRORS_HERE,
       
  1090 		    NULL,
       
  1091 		    "xmlSecAddChild",
       
  1092 		    XMLSEC_ERRORS_R_XMLSEC_FAILED,
       
  1093 		    "node=%s",
       
  1094 		    xmlSecErrorsSafeString(xmlSecNodeText));
       
  1095 	return(NULL);	        	
       
  1096     }
       
  1097     xmlNodeSetContent(textNode, faultReasonText);
       
  1098     xmlNodeSetLang(textNode, faultReasonLang);
       
  1099 
       
  1100     return(textNode);
       
  1101 }
       
  1102 
       
  1103 /**
       
  1104  * xmlSecSoap12AddFaultDetailEntry:
       
  1105  * @faultNode:          the pointer to <Fault> node.
       
  1106  * @detailEntryNode:    the pointer to detail entry node.
       
  1107  * 
       
  1108  * Adds a new child to the Detail child element of @faultNode.
       
  1109  *
       
  1110  * Returns pointer to the added child (@detailEntryNode) or NULL if an error 
       
  1111  * occurs.
       
  1112  */
       
  1113 EXPORT_C
       
  1114 xmlNodePtr 
       
  1115 xmlSecSoap12AddFaultDetailEntry(xmlNodePtr faultNode, xmlNodePtr detailEntryNode) {
       
  1116     xmlNodePtr detailNode;
       
  1117 
       
  1118     xmlSecAssert2(faultNode != NULL, NULL);
       
  1119     xmlSecAssert2(detailEntryNode != NULL, NULL);
       
  1120 
       
  1121     /* find Detail node and add it if needed */
       
  1122     detailNode = xmlSecFindChild(faultNode,  xmlSecNodeDetail, xmlSecSoap12Ns);
       
  1123     if(detailNode == NULL) {
       
  1124         detailNode = xmlSecAddChild(faultNode, xmlSecNodeDetail, xmlSecSoap12Ns);
       
  1125         if(detailNode == NULL) {
       
  1126     	    xmlSecError(XMLSEC_ERRORS_HERE,
       
  1127 		        NULL,
       
  1128 		        "xmlSecAddChild",
       
  1129 		        XMLSEC_ERRORS_R_XMLSEC_FAILED,
       
  1130 		        "node=%s",
       
  1131 		        xmlSecErrorsSafeString(xmlSecNodeDetail));
       
  1132 	    return(NULL);	        	
       
  1133         }
       
  1134     }
       
  1135     
       
  1136     return(xmlSecAddChildNode(detailNode, detailEntryNode));
       
  1137 }
       
  1138 
       
  1139 /**
       
  1140  * xmlSecSoap12CheckEnvelope:
       
  1141  * @envNode:    the pointer to <soap:Envelope> node.
       
  1142  *
       
  1143  * Validates <soap:Envelope> node structure.
       
  1144  *
       
  1145  * Returns 1 if @envNode has a valid <soap:Envelope> element, 0 if it is
       
  1146  * not valid or a negative value if an error occurs.
       
  1147  */
       
  1148 EXPORT_C
       
  1149 int 
       
  1150 xmlSecSoap12CheckEnvelope(xmlNodePtr envNode) {
       
  1151     xmlNodePtr cur;
       
  1152     
       
  1153     xmlSecAssert2(envNode != NULL, -1);
       
  1154     
       
  1155     /* verify envNode itself */
       
  1156     if(!xmlSecCheckNodeName(envNode, xmlSecNodeEnvelope, xmlSecSoap12Ns)) {
       
  1157 	xmlSecError(XMLSEC_ERRORS_HERE,
       
  1158 		    NULL,
       
  1159 		    xmlSecErrorsSafeString(xmlSecNodeEnvelope),
       
  1160 		    XMLSEC_ERRORS_R_NODE_NOT_FOUND,
       
  1161 		    XMLSEC_ERRORS_NO_MESSAGE);
       
  1162 	return(0);	
       
  1163     }
       
  1164 
       
  1165     /* optional Header node first */
       
  1166     cur = xmlSecGetNextElementNode(envNode->children);
       
  1167     if((cur != NULL) && xmlSecCheckNodeName(cur, xmlSecNodeHeader, xmlSecSoap12Ns)) {
       
  1168         cur = xmlSecGetNextElementNode(cur->next);
       
  1169     }
       
  1170 
       
  1171     /* required Body node is next */
       
  1172     if((cur == NULL) || !xmlSecCheckNodeName(cur, xmlSecNodeBody, xmlSecSoap12Ns)) {
       
  1173 	xmlSecError(XMLSEC_ERRORS_HERE,
       
  1174 		    NULL,
       
  1175 		    xmlSecErrorsSafeString(xmlSecNodeBody),
       
  1176 		    XMLSEC_ERRORS_R_NODE_NOT_FOUND,
       
  1177 		    XMLSEC_ERRORS_NO_MESSAGE);
       
  1178 	return(0);	
       
  1179     }
       
  1180     
       
  1181     return(1);
       
  1182 }
       
  1183 
       
  1184 /**
       
  1185  * xmlSecSoap12GetHeader:
       
  1186  * @envNode:    the pointer to <soap:Envelope> node.
       
  1187  * 
       
  1188  * Gets pointer to the <soap:Header> node.
       
  1189  *
       
  1190  * Returns pointer to <soap:Header> node or NULL if an error occurs.
       
  1191  */
       
  1192 EXPORT_C
       
  1193 xmlNodePtr 
       
  1194 xmlSecSoap12GetHeader(xmlNodePtr envNode) {
       
  1195     xmlNodePtr cur;
       
  1196     
       
  1197     xmlSecAssert2(envNode != NULL, NULL);
       
  1198 
       
  1199     /* optional Header node is first */
       
  1200     cur = xmlSecGetNextElementNode(envNode->children);
       
  1201     if((cur != NULL) && xmlSecCheckNodeName(cur, xmlSecNodeHeader, xmlSecSoap12Ns)) {
       
  1202         return(cur);
       
  1203     }
       
  1204 
       
  1205     return(NULL);
       
  1206 }
       
  1207 
       
  1208 /**
       
  1209  * xmlSecSoap12GetBody:
       
  1210  * @envNode:    the pointer to <soap:Envelope> node.
       
  1211  * 
       
  1212  * Gets pointer to the <soap:Body> node.
       
  1213  *
       
  1214  * Returns pointer to <soap:Body> node or NULL if an error occurs.
       
  1215  */
       
  1216 EXPORT_C
       
  1217 xmlNodePtr 
       
  1218 xmlSecSoap12GetBody(xmlNodePtr envNode) {
       
  1219     xmlNodePtr cur;
       
  1220     
       
  1221     xmlSecAssert2(envNode != NULL, NULL);
       
  1222 
       
  1223     /* optional Header node first */
       
  1224     cur = xmlSecGetNextElementNode(envNode->children);
       
  1225     if((cur != NULL) && xmlSecCheckNodeName(cur, xmlSecNodeHeader, xmlSecSoap12Ns)) {
       
  1226         cur = xmlSecGetNextElementNode(cur->next);
       
  1227     }
       
  1228 
       
  1229     /* Body node is next */
       
  1230     if((cur == NULL) || !xmlSecCheckNodeName(cur, xmlSecNodeBody, xmlSecSoap12Ns)) {
       
  1231 	xmlSecError(XMLSEC_ERRORS_HERE,
       
  1232 		    NULL,
       
  1233 		    xmlSecErrorsSafeString(xmlSecNodeBody),
       
  1234 		    XMLSEC_ERRORS_R_NODE_NOT_FOUND,
       
  1235 		    XMLSEC_ERRORS_NO_MESSAGE);
       
  1236 	return(NULL);	
       
  1237     }
       
  1238 
       
  1239     return(cur);
       
  1240 }
       
  1241 
       
  1242 /**
       
  1243  * xmlSecSoap12GetBodyEntriesNumber:
       
  1244  * @envNode:    the pointer to <soap:Envelope> node.
       
  1245  *
       
  1246  * Gets the number of body entries.
       
  1247  *
       
  1248  * Returns the number of body entries.
       
  1249  */
       
  1250 EXPORT_C
       
  1251 xmlSecSize 
       
  1252 xmlSecSoap12GetBodyEntriesNumber(xmlNodePtr envNode) {
       
  1253     xmlSecSize number = 0;
       
  1254     xmlNodePtr bodyNode;
       
  1255     xmlNodePtr cur;
       
  1256     
       
  1257     xmlSecAssert2(envNode != NULL, 0);
       
  1258 
       
  1259     /* get Body node */
       
  1260     bodyNode = xmlSecSoap12GetBody(envNode);
       
  1261     if(bodyNode == NULL) {
       
  1262 	xmlSecError(XMLSEC_ERRORS_HERE,
       
  1263 		    NULL,
       
  1264 		    "xmlSecSoap12GetBody",
       
  1265 		    XMLSEC_ERRORS_R_XMLSEC_FAILED,
       
  1266 		    XMLSEC_ERRORS_NO_MESSAGE);
       
  1267 	return(0);
       
  1268     }
       
  1269 
       
  1270     cur = xmlSecGetNextElementNode(bodyNode->children);
       
  1271     while(cur != NULL) {
       
  1272         number++;
       
  1273         cur = xmlSecGetNextElementNode(cur->next);
       
  1274     }
       
  1275     
       
  1276     return(number);
       
  1277 }
       
  1278 
       
  1279 /**
       
  1280  * xmlSecSoap12GetBodyEntry:
       
  1281  * @envNode:    the pointer to <soap:Envelope> node.
       
  1282  * @pos:        the body entry number.
       
  1283  * 
       
  1284  * Gets the body entry number @pos.
       
  1285  *
       
  1286  * Returns pointer to body entry node or NULL if an error occurs.
       
  1287  */
       
  1288 EXPORT_C
       
  1289 xmlNodePtr 
       
  1290 xmlSecSoap12GetBodyEntry(xmlNodePtr envNode, xmlSecSize pos) {
       
  1291     xmlNodePtr bodyNode;
       
  1292     xmlNodePtr cur;
       
  1293  
       
  1294     xmlSecAssert2(envNode != NULL, NULL);
       
  1295 
       
  1296     /* get Body node */
       
  1297     bodyNode = xmlSecSoap12GetBody(envNode);
       
  1298     if(bodyNode == NULL) {
       
  1299 	xmlSecError(XMLSEC_ERRORS_HERE,
       
  1300 		    NULL,
       
  1301 		    "xmlSecSoap12GetBody",
       
  1302 		    XMLSEC_ERRORS_R_XMLSEC_FAILED,
       
  1303 		    XMLSEC_ERRORS_NO_MESSAGE);
       
  1304 	return(NULL);	        	
       
  1305     }
       
  1306 
       
  1307     cur = xmlSecGetNextElementNode(bodyNode->children);
       
  1308     while((cur != NULL) && (pos > 0)) {
       
  1309         pos--;
       
  1310         cur = xmlSecGetNextElementNode(cur->next);
       
  1311     }
       
  1312 
       
  1313     return(cur);
       
  1314 }
       
  1315 
       
  1316 /**
       
  1317  * xmlSecSoap12GetFaultEntry:
       
  1318  * @envNode:    the pointer to <soap:Envelope> node.
       
  1319  * 
       
  1320  * Gets the Fault entry (if any).
       
  1321  *
       
  1322  * Returns pointer to Fault entry or NULL if it does not exist.
       
  1323  */
       
  1324 EXPORT_C
       
  1325 xmlNodePtr 
       
  1326 xmlSecSoap12GetFaultEntry(xmlNodePtr envNode) {
       
  1327     xmlNodePtr bodyNode;
       
  1328 
       
  1329     xmlSecAssert2(envNode != NULL, NULL);
       
  1330 
       
  1331     /* get Body node */
       
  1332     bodyNode = xmlSecSoap12GetBody(envNode);
       
  1333     if(bodyNode == NULL) {
       
  1334 	xmlSecError(XMLSEC_ERRORS_HERE,
       
  1335 		    NULL,
       
  1336 		    "xmlSecSoap12GetBody",
       
  1337 		    XMLSEC_ERRORS_R_XMLSEC_FAILED,
       
  1338 		    XMLSEC_ERRORS_NO_MESSAGE);
       
  1339 	return(NULL);	        	
       
  1340     }
       
  1341 
       
  1342     return(xmlSecFindChild(bodyNode, xmlSecNodeFault, xmlSecSoap12Ns));
       
  1343 }
       
  1344 								 
       
  1345 #endif /* XMLSEC_NO_SOAP */
       
  1346 
       
  1347