I attached the patch that allows the replaced nodes during encryption and decryption to be returned in the 'xmlSecEncCtxPtr' structure. Actually, I added two entries in the 'xmlSecEncCtrPtr' structure : - nodeReplacementMode, an enum of type 'xmlEncCtxNodeReplacementMode', to define if the nodes will be released or returned in the second entry, - a pointer to a xmlNodePtr called 'replacedNodeList' that contains the list of the nodes that have been replaced.

One additional point, as it's up to the user to release the returned nodes, I'm not sure if the code I added in the 'xmlSecEncCtxReset' function to release the node list is necessary, because if someone releases the node but forget to set the pointer to NULL it will crash. But if he doesn't release the nodes, and this code is not there we got a memory leak.

If you could take a look

Thanks,
Frank

Aleksey Sanin a écrit :
Sure, I love patches :) BTW, you can't find any docs about
flags/flags2 in xmlSecEncCtx because they are not used at the moment :)
Just reserved for the future :)

Aleksey

Frank Gross wrote:
Yes I agree, but it would be more efficient if I wouldn't have to do that. And I have the same problem when I try to encrypt only the content of an element, where all sub-nodes are removed. Actually, I try to write an API where you give the node to be encrypted, but the node passed to my function is still alive, and simply destroying the nodes inside the library is impossible in my case, because some other references can point on these nodes.

Therefore may I suggest a request ? Could you add an option in the 'xmlSecEncCtxPtr' structure to specify how the nodes to be replaced should be handled, and return them in a list in the structure if for instance the option was set to not releasing them so that the user can choose to release them by hand or not. And the same kind of feature when decrypting a node, because in some cases you want to keep trace of the encrypted node.

My 2 cents contribution that could really help in my case, and allow the programmer to choose instead of the library.

If you agree I could make a patch, using flags or flags2 in the 'xmlSecEncCtxPtr' structure, and add a new entry of type xmlNodePtr with the list of nodes that were replaced but not released according to flags or flags2 value. BTW what is the difference between flags and flags2 ? Are they used because I didn't find any information in the documentation ?

Best Regards,

Frank

Aleksey Sanin a écrit :
Well, you can always copy the node yourself before encrypting it.

Aleksey

Frank Gross wrote:
Hi,

I noticed that function 'xmlSecEncCtxXmlEncrypt' releases the node that was encrypted when replaced by the 'EncryptedData' node. Does it exist a way to not release that node, and let the user choose whether he wants to destroy it or not ?

Thanks,

Frank
_______________________________________________
xmlsec mailing list
[email protected]
http://www.aleksey.com/mailman/listinfo/xmlsec

_______________________________________________
xmlsec mailing list
[email protected]
http://www.aleksey.com/mailman/listinfo/xmlsec

diff --exclude-from=./exclude -rc xmlsec1-1.2.11/include/xmlsec/xmlenc.h 1.2.11/src/include/xmlsec/xmlenc.h
*** xmlsec1-1.2.11/include/xmlsec/xmlenc.h	Thu Mar  6 18:55:32 2008
--- 1.2.11/src/include/xmlsec/xmlenc.h	Thu Mar 13 16:15:18 2008
***************
*** 42,53 ****
--- 42,67 ----
  } xmlEncCtxMode;
  
  /** 
+  * xmlEncCtxNodeReplacementMode: 
+  * @xmlEncCtxNodeRelease:	the nodes are released
+  * @xmlEncCtxNodeKeep:	  the nodes are kept and located in the replacedNodeList
+  *
+  * The #xmlEncCtxNodeReplacementMode mode.
+  */
+ typedef enum {
+     xmlEncCtxNodeRelease = 0,
+     xmlEncCtxNodeKeep
+ } xmlEncCtxNodeReplacementMode;
+ 
+ /** 
   * xmlSecEncCtx:
   * @userData:			the pointer to user data (xmlsec and xmlsec-crypto libraries
   *				never touches this).
   * @flags:			the XML Encryption processing flags.
   * @flags2:			the XML Encryption processing flags.
   * @mode:			the mode.
+  * @nodeReplacementMode:  whether the node replaced during encryption or decryption 
+                           are kept or released
   * @keyInfoReadCtx:		the reading key context.
   * @keyInfoWriteCtx:		the writing key context (not used for signature verification).
   * @transformCtx:		the transforms processing context.
***************
*** 61,66 ****
--- 75,81 ----
   * @resultReplaced:		the flag: if set then resulted <enc:EncryptedData/>
   *				or <enc:EncryptedKey/> node is added to the document.
   * @encMethod:			the pointer to encryption transform.
+  * @replacedNodeList: the first node of the list of replaced nodes depending on the nodeReplacementMode
   * @id:				the ID attribute of <enc:EncryptedData/>
   *				or <enc:EncryptedKey/> node.
   * @type:			the Type attribute of <enc:EncryptedData/>
***************
*** 87,92 ****
--- 102,108 ----
      unsigned int		flags;
      unsigned int		flags2;    
      xmlEncCtxMode		mode;
+     xmlEncCtxNodeReplacementMode	nodeReplacementMode;
      xmlSecKeyInfoCtx		keyInfoReadCtx;
      xmlSecKeyInfoCtx		keyInfoWriteCtx;
      xmlSecTransformCtx		transformCtx;
***************
*** 99,105 ****
      int				resultBase64Encoded;
      int				resultReplaced;
      xmlSecTransformPtr		encMethod;
! 
      /* attributes from EncryptedData or EncryptedKey */    
      xmlChar*			id;
      xmlChar*			type;
--- 115,122 ----
      int				resultBase64Encoded;
      int				resultReplaced;
      xmlSecTransformPtr		encMethod;
! 		xmlNodePtr	replacedNodeList;
! 		
      /* attributes from EncryptedData or EncryptedKey */    
      xmlChar*			id;
      xmlChar*			type;
diff --exclude-from=./exclude -rc xmlsec1-1.2.11/include/xmlsec/xmltree.h 1.2.11/src/include/xmlsec/xmltree.h
*** xmlsec1-1.2.11/include/xmlsec/xmltree.h	Thu Mar  6 18:55:32 2008
--- 1.2.11/src/include/xmlsec/xmltree.h	Thu Mar 13 16:15:18 2008
***************
*** 55,66 ****
  							 const xmlChar *ns);
  
  XMLSEC_EXPORT int		xmlSecReplaceNode	(xmlNodePtr node,
! 						         xmlNodePtr newNode);
  XMLSEC_EXPORT int		xmlSecReplaceContent	(xmlNodePtr node,
! 							 xmlNodePtr newNode);
  XMLSEC_EXPORT int		xmlSecReplaceNodeBuffer	(xmlNodePtr node,
  							 const xmlSecByte *buffer, 
! 							 xmlSecSize size);
  
  XMLSEC_EXPORT void		xmlSecAddIDs		(xmlDocPtr doc,
  							 xmlNodePtr cur,
--- 55,69 ----
  							 const xmlChar *ns);
  
  XMLSEC_EXPORT int		xmlSecReplaceNode	(xmlNodePtr node,
! 						         xmlNodePtr newNode,
! 						         xmlNodePtr* replaced);
  XMLSEC_EXPORT int		xmlSecReplaceContent	(xmlNodePtr node,
! 							 xmlNodePtr newNode,
! 							 xmlNodePtr* replaced);
  XMLSEC_EXPORT int		xmlSecReplaceNodeBuffer	(xmlNodePtr node,
  							 const xmlSecByte *buffer, 
! 							 xmlSecSize size,
! 							 xmlNodePtr* replaced);
  
  XMLSEC_EXPORT void		xmlSecAddIDs		(xmlDocPtr doc,
  							 xmlNodePtr cur,
diff --exclude-from=./exclude -rc xmlsec1-1.2.11/src/templates.c 1.2.11/src/src/templates.c
*** xmlsec1-1.2.11/src/templates.c	Thu Mar  6 18:55:36 2008
--- 1.2.11/src/src/templates.c	Thu Mar 13 16:15:16 2008
***************
*** 1860,1866 ****
  	return(-1);
      }
      
!     ret = xmlSecReplaceContent(transformNode, xmlDocGetRootElement(xsltDoc));
      if(ret < 0) {
  	xmlSecError(XMLSEC_ERRORS_HERE,
  		    NULL,
--- 1860,1866 ----
  	return(-1);
      }
      
!     ret = xmlSecReplaceContent(transformNode, xmlDocGetRootElement(xsltDoc),NULL);
      if(ret < 0) {
  	xmlSecError(XMLSEC_ERRORS_HERE,
  		    NULL,
diff --exclude-from=./exclude -rc xmlsec1-1.2.11/src/xmlenc.c 1.2.11/src/src/xmlenc.c
*** xmlsec1-1.2.11/src/xmlenc.c	Thu Mar  6 18:55:36 2008
--- 1.2.11/src/src/xmlenc.c	Thu Mar 13 16:22:26 2008
***************
*** 192,197 ****
--- 192,202 ----
      encCtx->resultBase64Encoded = 0;
      encCtx->resultReplaced	= 0;
      encCtx->encMethod		= NULL;
+     if (encCtx->replacedNodeList) { 
+ 	  /* should this by done there or is it up to the user to release the nodes ? */
+     	xmlFreeNodeList(encCtx->replacedNodeList);
+     	encCtx->replacedNodeList = NULL;
+     }
      if(encCtx->encKey != NULL) {
  	xmlSecKeyDestroy(encCtx->encKey);
  	encCtx->encKey = NULL;
***************
*** 247,252 ****
--- 252,258 ----
      dst->flags2		= src->flags2;
      dst->defEncMethodId = src->defEncMethodId;
      dst->mode 		= src->mode;
+     dst->nodeReplacementMode = src->nodeReplacementMode;
      
      ret = xmlSecTransformCtxCopyUserPref(&(dst->transformCtx), &(src->transformCtx));
      if(ret < 0) {
***************
*** 450,456 ****
      
      /* now we need to update our original document */
      if((encCtx->type != NULL) && xmlStrEqual(encCtx->type, xmlSecTypeEncElement)) {
! 	ret = xmlSecReplaceNode(node, tmpl);
  	if(ret < 0) {
  	    xmlSecError(XMLSEC_ERRORS_HERE,
  			NULL,
--- 456,462 ----
      
      /* now we need to update our original document */
      if((encCtx->type != NULL) && xmlStrEqual(encCtx->type, xmlSecTypeEncElement)) {
! 	ret = xmlSecReplaceNode(node, tmpl,(encCtx->nodeReplacementMode==xmlEncCtxNodeRelease?NULL:&(encCtx->replacedNodeList)));
  	if(ret < 0) {
  	    xmlSecError(XMLSEC_ERRORS_HERE,
  			NULL,
***************
*** 462,468 ****
  	}
  	encCtx->resultReplaced = 1;			       
      } else if((encCtx->type != NULL) && xmlStrEqual(encCtx->type, xmlSecTypeEncContent)) {
! 	ret = xmlSecReplaceContent(node, tmpl);
  	if(ret < 0) {
  	    xmlSecError(XMLSEC_ERRORS_HERE,
  			NULL,
--- 468,474 ----
  	}
  	encCtx->resultReplaced = 1;			       
      } else if((encCtx->type != NULL) && xmlStrEqual(encCtx->type, xmlSecTypeEncContent)) {
! 	ret = xmlSecReplaceContent(node, tmpl,(encCtx->nodeReplacementMode==xmlEncCtxNodeRelease?NULL:&(encCtx->replacedNodeList)));
  	if(ret < 0) {
  	    xmlSecError(XMLSEC_ERRORS_HERE,
  			NULL,
***************
*** 589,595 ****
      
      /* replace original node if requested */
      if((encCtx->type != NULL) && xmlStrEqual(encCtx->type, xmlSecTypeEncElement)) {
! 	ret = xmlSecReplaceNodeBuffer(node, xmlSecBufferGetData(buffer),  xmlSecBufferGetSize(buffer));
  	if(ret < 0) {
  	    xmlSecError(XMLSEC_ERRORS_HERE,
  			NULL,
--- 595,601 ----
      
      /* replace original node if requested */
      if((encCtx->type != NULL) && xmlStrEqual(encCtx->type, xmlSecTypeEncElement)) {
! 	ret = xmlSecReplaceNodeBuffer(node, xmlSecBufferGetData(buffer),  xmlSecBufferGetSize(buffer),(encCtx->nodeReplacementMode==xmlEncCtxNodeRelease?NULL:&(encCtx->replacedNodeList)));
  	if(ret < 0) {
  	    xmlSecError(XMLSEC_ERRORS_HERE,
  			NULL,
***************
*** 602,608 ****
  	encCtx->resultReplaced = 1;			       
      } else if((encCtx->type != NULL) && xmlStrEqual(encCtx->type, xmlSecTypeEncContent)) {
  	/* replace the node with the buffer */
! 	ret = xmlSecReplaceNodeBuffer(node, xmlSecBufferGetData(buffer), xmlSecBufferGetSize(buffer));
  	if(ret < 0) {
  	    xmlSecError(XMLSEC_ERRORS_HERE,
  			NULL,
--- 608,614 ----
  	encCtx->resultReplaced = 1;			       
      } else if((encCtx->type != NULL) && xmlStrEqual(encCtx->type, xmlSecTypeEncContent)) {
  	/* replace the node with the buffer */
! 	ret = xmlSecReplaceNodeBuffer(node, xmlSecBufferGetData(buffer), xmlSecBufferGetSize(buffer),(encCtx->nodeReplacementMode==xmlEncCtxNodeRelease?NULL:&(encCtx->replacedNodeList)));
  	if(ret < 0) {
  	    xmlSecError(XMLSEC_ERRORS_HERE,
  			NULL,
diff --exclude-from=./exclude -rc xmlsec1-1.2.11/src/xmltree.c 1.2.11/src/src/xmltree.c
*** xmlsec1-1.2.11/src/xmltree.c	Thu Mar  6 18:55:36 2008
--- 1.2.11/src/src/xmltree.c	Thu Mar 13 16:39:31 2008
***************
*** 412,424 ****
   * xmlSecReplaceNode:
   * @node: 		the current node.
   * @newNode: 		the new node.
   * 
   * Swaps the @node and @newNode in the XML tree.
   *
   * Returns 0 on success or a negative value if an error occurs.
   */
  int
! xmlSecReplaceNode(xmlNodePtr node, xmlNodePtr newNode) {
      xmlNodePtr oldNode;
      int restoreRoot = 0;
      
--- 412,425 ----
   * xmlSecReplaceNode:
   * @node: 		the current node.
   * @newNode: 		the new node.
+  * @replaced:   return the replaced node, or release it if NULL is given
   * 
   * Swaps the @node and @newNode in the XML tree.
   *
   * Returns 0 on success or a negative value if an error occurs.
   */
  int
! xmlSecReplaceNode(xmlNodePtr node, xmlNodePtr newNode,xmlNodePtr* replaced) {
      xmlNodePtr oldNode;
      int restoreRoot = 0;
      
***************
*** 448,454 ****
  	xmlDocSetRootElement(oldNode->doc, newNode);
      }
  
!     xmlFreeNode(oldNode);
      return(0);
  }
  
--- 449,461 ----
  	xmlDocSetRootElement(oldNode->doc, newNode);
      }
  
!    /* cannot release node because it could be referenced elsewhere */
!    if (replaced==NULL) {
!      xmlFreeNode(oldNode); 
!    } else {
!      *replaced=oldNode;  	  	
!    }
!    
      return(0);
  }
  
***************
*** 456,474 ****
   * xmlSecReplaceContent
   * @node: 		the current node.
   * @newNode: 		the new node.
   * 
   * Swaps the content of @node and @newNode.
   *
   * Returns 0 on success or a negative value if an error occurs.
   */
  int
! xmlSecReplaceContent(xmlNodePtr node, xmlNodePtr newNode) {
      xmlSecAssert2(node != NULL, -1);
      xmlSecAssert2(newNode != NULL, -1);  
  
      xmlUnlinkNode(newNode);
      xmlSetTreeDoc(newNode, node->doc);
!     xmlNodeSetContent(node, NULL);
      xmlAddChild(node, newNode);
      xmlSetTreeDoc(newNode, node->doc);
  
--- 463,498 ----
   * xmlSecReplaceContent
   * @node: 		the current node.
   * @newNode: 		the new node.
+  * @replaced:   return the replaced nodes, or release them if NULL is given
   * 
   * Swaps the content of @node and @newNode.
   *
   * Returns 0 on success or a negative value if an error occurs.
   */
  int
! xmlSecReplaceContent(xmlNodePtr node, xmlNodePtr newNode,xmlNodePtr* replaced) {
      xmlSecAssert2(node != NULL, -1);
      xmlSecAssert2(newNode != NULL, -1);  
  
      xmlUnlinkNode(newNode);
      xmlSetTreeDoc(newNode, node->doc);
!    /* cannot release nodes because they could be referenced elsewhere */
!     if (replaced==NULL) {
!       xmlNodeSetContent(node, NULL);
!     } else {
!       xmlNodePtr n,next,cur;
!       *replaced=NULL;
!       for (n=node->children;n;n=next) {
!         next=n->next;
!         if (*replaced==NULL) {
!           xmlUnlinkNode(n);
!     	    *replaced=cur=n;    	    
!         } else {
! 					/* n is unlinked in this function */        	
!           xmlAddNextSibling(cur,n); 
!         }
!       }
!     }
      xmlAddChild(node, newNode);
      xmlSetTreeDoc(newNode, node->doc);
  
***************
*** 479,486 ****
  /**
   * xmlSecReplaceNodeBuffer:
   * @node: 		the current node.
!  * @buffer: 		the XML data.
   * @size: 		the XML data size.
   * 
   * Swaps the @node and the parsed XML data from the @buffer in the XML tree.
   *
--- 503,511 ----
  /**
   * xmlSecReplaceNodeBuffer:
   * @node: 		the current node.
!  * @buffer: 	the XML data.
   * @size: 		the XML data size.
+  * @replaced: return the replaced nodes, or release them if NULL is given
   * 
   * Swaps the @node and the parsed XML data from the @buffer in the XML tree.
   *
***************
*** 488,494 ****
   */
  int
  xmlSecReplaceNodeBuffer(xmlNodePtr node, 
! 			const xmlSecByte *buffer, xmlSecSize size) {
      xmlNodePtr results = NULL;
      xmlNodePtr next = NULL;
  
--- 513,519 ----
   */
  int
  xmlSecReplaceNodeBuffer(xmlNodePtr node, 
! 			const xmlSecByte *buffer, xmlSecSize size,xmlNodePtr* replaced) {
      xmlNodePtr results = NULL;
      xmlNodePtr next = NULL;
  
***************
*** 514,521 ****
  
      /* remove old node */
      xmlUnlinkNode(node);
!     xmlFreeNode(node);  
! 
      return(0);
  }
  
--- 539,550 ----
  
      /* remove old node */
      xmlUnlinkNode(node);
!     /* cannot release node because it could be referenced elsewhere */
!     if (replaced==NULL) {
!       xmlFreeNode(node); 
!     } else {
!       *replaced=node;
!     }
      return(0);
  }
  
_______________________________________________
xmlsec mailing list
[email protected]
http://www.aleksey.com/mailman/listinfo/xmlsec

Reply via email to