[xmlsec] enhancement to xmlsec

Moultrie, Ferrell (ISSAtlanta) FMoultrie at iss.net
Wed Dec 18 13:15:09 PST 2002


Aleksey:
  My xml documents that I'm signing/verifying contain repeated nodes of
the same name so any beyond the first node are not addressable by the
--node-name construct supported by xmlsec. Additionally, I'm not using a
dtd so the --node-id doesn't help me out either. Finally, the
sign/verify code accept the --node-id/--node-name arguments but ignore
them, always signing/verifying the first Signature node found. 
  To solve the above issues, I'm attaching suggested changes (relative
to 0.0.10) that allow the --node-name argument to contain an absolute
XPath expression to locate the section of the document to be
signed/verified/etc. If the argument starts with a '/' character, it is
processed as an XPath expression, otherwise it is just a ns:node-name as
before. This shouldn't break anything but allows much greater
flexibility in using xmlsec with complex xml structures. 
  For example, "--node-name //Module[2]" would select the 2nd Module
element in the document skeletonized below:
<?xml version="1.0" encoding="UTF-8"?>
<Keys>
  <Modules>
    <Module> first module element including <sig:Signature/> </Module>
    <Module> second module element including <sig:Signature/> </Module>
    <Module> third module element including <sig:Signature/> </Module>
  </Modules>
</Keys>
  Using either "--node-name //Module[1]" or "--node-name Module" would
select the first occurance (note node-name format works just as it did
before).
  While I could have obviously written a new utility to handle manual
signing of my test documents, it seems much better to add this
functionality to the xmlsec application where it could easily be reused
by others. I'm attaching the diff's -- let me know if you need another
format, or, a full copy of the xmlsec.c file before/after my changes.
  I have rather thoroughly tested the digital signature
creation/verification but haven't tested encryption/decryption -- but
since it now uses a common routine, what could go wrong, right? (:>)
Thanks!
  Ferrell


-------------- next part --------------
306a307
> char *nodeXPath = NULL;
388,395c389,400
< 		nodeName = strrchr(argv[++pos], ':');
< 		if(nodeName != NULL) {
< 		    *(nodeName++) = '\0';
< 		    nodeNs = argv[pos];
< 		} else {
< 		    nodeName = argv[pos];
< 		    nodeNs = NULL;
< 		}
---
> 			if (argv[++pos][0] == '/') { /* absolute XPath specification? */ 
> 				nodeXPath = argv[pos];
> 			} else {
> 				nodeName = strrchr(argv[pos], ':');
> 				if(nodeName != NULL) {
> 				    *(nodeName++) = '\0';
> 				    nodeNs = argv[pos];
> 				} else {
> 				    nodeName = argv[pos];
> 				    nodeNs = NULL;
> 				}
> 			}
1245a1251,1281
> 
> /* Function to find base node for operation as specified by user using either
>  * DTD Id, XPath abs expression, NodeName, or default to root node */
> xmlNodePtr findBaseNode(xmlDocPtr doc) {
> 	xmlNodePtr cur = NULL;
> 	if(nodeId != NULL) {
> 	    xmlAttrPtr attr;
> 	    attr = xmlGetID(doc, BAD_CAST nodeId);
> 	    cur = (attr != NULL) ? attr->parent : NULL;
> 	} else if(nodeXPath != NULL) {
> 		xmlNodeSetPtr pNodeList = NULL;
> 		xmlXPathContextPtr pCtx = NULL;
> 		xmlXPathObjectPtr pXPathObj = NULL;
> 		pCtx = xmlXPathNewContext(doc);
> 		pXPathObj = xmlXPathEval(BAD_CAST nodeXPath, pCtx);
> 		if (pXPathObj != NULL) {
> 			pNodeList = pXPathObj->nodesetval;
> 		}
> 		if (pNodeList != NULL && pNodeList->nodeNr > 0) { 
> 			cur = pNodeList->nodeTab[0];
> 		}
> 		xmlXPathFreeContext(pCtx);
> 		xmlXPathFreeObject(pXPathObj);
> 	} else if(nodeName != NULL) {
> 		cur = xmlSecFindNode(xmlDocGetRootElement(doc), BAD_CAST nodeName, BAD_CAST nodeNs);
> 	} else {
> 	    cur = xmlDocGetRootElement(doc);
> 	}
> 	return cur; /* can be NULL .. caller must check */
> } /* of findBaseNode() */
> 
1248a1285
> 	xmlNodePtr cur;
1255,1256c1292,1301
<     signNode = xmlSecFindNode(xmlDocGetRootElement(doc), 
< 			      BAD_CAST "Signature", xmlSecDSigNs);
---
> 
> 	/**
> 	 * What do we want to sign?
> 	 */    
> 	cur = findBaseNode(doc);
> 	if (cur == NULL) { 
> 		fprintf(stderr,"Error: failed to find specified node\n");
> 		return(-1);
> 	}
> 	signNode = xmlSecFindNode(cur, BAD_CAST "Signature", xmlSecDSigNs);
1258,1259c1303,1304
<         fprintf(stderr,"Error: failed to find Signature node\n");
< 	return(-1);
---
> 		fprintf(stderr,"Error: failed to find Signature node\n");
> 		return(-1);
1310a1356
> 	xmlNodePtr cur;
1313,1315c1359,1368
<     	    
<     signNode = xmlSecFindNode(xmlDocGetRootElement(doc), 
< 			      BAD_CAST "Signature", xmlSecDSigNs);
---
> 
> 	/**
> 	 * What do we want to verify?
> 	 */    
> 	cur = findBaseNode(doc);
> 	if (cur == NULL) { 
> 		fprintf(stderr,"Error: failed to find specified node\n");
> 		return(-1);
> 	}
> 	signNode = xmlSecFindNode(cur, BAD_CAST "Signature", xmlSecDSigNs);
1317,1318c1370,1371
<         fprintf(stderr,"Error: failed to find Signature node\n");
< 	return(-1);
---
> 		fprintf(stderr,"Error: failed to find Signature node\n");
> 		return(-1);
1414,1424c1467,1468
< 	if(nodeId != NULL) {
< 	    xmlAttrPtr attr;
< 	    
< 	    attr = xmlGetID(doc, BAD_CAST nodeId);
< 	    cur = (attr != NULL) ? attr->parent : NULL;
< 	} else if(nodeName != NULL) {
< 	    cur = xmlSecFindNode(xmlDocGetRootElement(doc), BAD_CAST nodeName, BAD_CAST nodeNs);
< 	} else {
< 	    cur = xmlDocGetRootElement(doc);
< 	}
< 	
---
> 	cur = findBaseNode(doc);
> 
1498c1542,1547
<     cur = xmlSecFindNode(xmlDocGetRootElement(doc), BAD_CAST "EncryptedData", xmlSecEncNs);
---
> 	cur = findBaseNode(doc);
> 	if (cur == NULL) { 
> 		fprintf(stderr,"Error: failed to find specified node\n");
> 		return(-1);
> 	}
>     cur = xmlSecFindNode(cur, BAD_CAST "EncryptedData", xmlSecEncNs);



More information about the xmlsec mailing list