[xmlsec] Re: core methods for write of <X509SubjectName/> and <X509IssuerSerial/>

Aleksey Sanin aleksey at aleksey.com
Mon Jul 28 17:39:04 PDT 2003


Skipped content of type multipart/alternative-------------- next part --------------
Index: include/xmlsec/keyinfo.h
===================================================================
RCS file: /cvs/gnome/xmlsec/include/xmlsec/keyinfo.h,v
retrieving revision 1.28
diff -u -r1.28 keyinfo.h
--- include/xmlsec/keyinfo.h	21 Jul 2003 03:12:37 -0000	1.28
+++ include/xmlsec/keyinfo.h	28 Jul 2003 19:01:39 -0000
@@ -137,6 +137,14 @@
  */
 #define XMLSEC_KEYINFO_FLAGS_ENCKEY_DONT_STOP_ON_FAILED_DECRYPTION 0x00001000
 
+/** 
+ * XMLSEC_KEYINFO_FLAGS_STOP_ON_EMPTY_NODE:
+ *
+ * If the flag is set then we'll stop when we found an empty node.
+ * Otherwise we just ignore it.
+ */
+#define XMLSEC_KEYINFO_FLAGS_STOP_ON_EMPTY_NODE			0x00002000
+
 /**		
  * xmlSecKeyInfoCtx:
  * @userData:		the pointer to user data (xmlsec and xmlsec-crypto 
Index: include/xmlsec/xmltree.h
===================================================================
RCS file: /cvs/gnome/xmlsec/include/xmlsec/xmltree.h,v
retrieving revision 1.17
diff -u -r1.17 xmltree.h
--- include/xmlsec/xmltree.h	21 Jul 2003 03:12:37 -0000	1.17
+++ include/xmlsec/xmltree.h	28 Jul 2003 19:01:39 -0000
@@ -67,6 +67,9 @@
 
 XMLSEC_EXPORT xmlDocPtr		xmlSecCreateTree	(const xmlChar* rootNodeName,
 							 const xmlChar* rootNodeNs);
+XMLSEC_EXPORT int		xmlSecIsEmptyNode	(xmlNodePtr node);
+XMLSEC_EXPORT int		xmlSecIsEmptyString	(const xmlChar* str);
+
 /**
  * xmlSecIsHex:
  * @c: 			the character.
Index: src/xmltree.c
===================================================================
RCS file: /cvs/gnome/xmlsec/src/xmltree.c,v
retrieving revision 1.25
diff -u -r1.25 xmltree.c
--- src/xmltree.c	21 Jul 2003 03:12:48 -0000	1.25
+++ src/xmltree.c	28 Jul 2003 19:01:39 -0000
@@ -616,4 +616,48 @@
     return(doc);
 }
 
+/**
+ * xmlSecIsEmptyNode:
+ * @node:		the node to check
+ *
+ * Checks whethere the @node is empty (i.e. has only whitespaces children).
+ *
+ * Returns 1 if @node is empty, 0 otherwise or a negative value if an error occurs.
+ */
+int 
+xmlSecIsEmptyNode(xmlNodePtr node) {
+    xmlChar* content;
+    int res;
+    
+    xmlSecAssert2(node != NULL, -1);
+    
+    content = xmlNodeGetContent(node);
+    if(content == NULL) {
+	return(1);
+    }
+    
+    res = xmlSecIsEmptyString(content);
+    xmlFree(content);
+    return(res);
+}
+
+/**
+ * xmlSecIsEmptyString:
+ * @str:		the string to check
+ *
+ * Checks whethere the @str is empty (i.e. has only whitespaces children).
+ *
+ * Returns 1 if @str is empty, 0 otherwise or a negative value if an error occurs.
+ */
+int 
+xmlSecIsEmptyString(const xmlChar* str) {
+    xmlSecAssert2(str != NULL, -1);
+    
+    for( ;*str != '\0'; ++str) {
+	if(!isspace((int)(*str))) {
+	    return(0);
+	}
+    }
+    return(1);
+}
 
Index: src/openssl/x509.c
===================================================================
RCS file: /cvs/gnome/xmlsec/src/openssl/x509.c,v
retrieving revision 1.37
diff -u -r1.37 x509.c
--- src/openssl/x509.c	21 Jul 2003 03:12:55 -0000	1.37
+++ src/openssl/x509.c	28 Jul 2003 19:01:39 -0000
@@ -45,23 +45,38 @@
  *
  ************************************************************************/
 static int		xmlSecOpenSSLX509DataNodeRead		(xmlSecKeyDataPtr data,
-								 xmlNodePtr node,
+    								 xmlNodePtr node,
 								 xmlSecKeyInfoCtxPtr keyInfoCtx);
 static int		xmlSecOpenSSLX509CertificateNodeRead	(xmlSecKeyDataPtr data,
 								 xmlNodePtr node,
 								 xmlSecKeyInfoCtxPtr keyInfoCtx);
+static int		xmlSecOpenSSLX509CertificateNodeWrite	(X509* cert,
+								 xmlNodePtr node,
+								 xmlSecKeyInfoCtxPtr keyInfoCtx);
 static int		xmlSecOpenSSLX509SubjectNameNodeRead	(xmlSecKeyDataPtr data,
 								 xmlNodePtr node,
 								 xmlSecKeyInfoCtxPtr keyInfoCtx);
+static int		xmlSecOpenSSLX509SubjectNameNodeWrite	(X509* cert,
+								 xmlNodePtr node,
+								 xmlSecKeyInfoCtxPtr keyInfoCtx);
 static int		xmlSecOpenSSLX509IssuerSerialNodeRead	(xmlSecKeyDataPtr data,
 								 xmlNodePtr node,
 								 xmlSecKeyInfoCtxPtr keyInfoCtx);
+static int		xmlSecOpenSSLX509IssuerSerialNodeWrite	(X509* cert,
+								 xmlNodePtr node,
+								 xmlSecKeyInfoCtxPtr keyInfoCtx);
 static int		xmlSecOpenSSLX509SKINodeRead		(xmlSecKeyDataPtr data,
 								 xmlNodePtr node,
 								 xmlSecKeyInfoCtxPtr keyInfoCtx);
+static int		xmlSecOpenSSLX509SKINodeWrite		(X509* cert,
+								 xmlNodePtr node,
+								 xmlSecKeyInfoCtxPtr keyInfoCtx);
 static int		xmlSecOpenSSLX509CRLNodeRead		(xmlSecKeyDataPtr data,
 								 xmlNodePtr node,
 								 xmlSecKeyInfoCtxPtr keyInfoCtx);
+static int		xmlSecOpenSSLX509CRLNodeWrite		(X509_CRL* crl,
+								 xmlNodePtr node,
+								 xmlSecKeyInfoCtxPtr keyInfoCtx);
 static int		xmlSecOpenSSLKeyDataX509VerifyAndExtractKey(xmlSecKeyDataPtr data, 
 								xmlSecKeyPtr key,
 								xmlSecKeyInfoCtxPtr keyInfoCtx);
@@ -76,6 +91,9 @@
 static X509_CRL*	xmlSecOpenSSLX509CrlBase64DerRead	(xmlChar* buf);
 static xmlChar*		xmlSecOpenSSLX509CrlBase64DerWrite	(X509_CRL* crl, 
 								 int base64LineWrap);
+static xmlChar*		xmlSecOpenSSLX509NameWrite		(X509_NAME* nm);
+static xmlChar*		xmlSecOpenSSLASN1IntegerWrite		(ASN1_INTEGER *asni);
+static xmlChar*		xmlSecOpenSSLX509SKIWrite		(X509* cert);
 static void		xmlSecOpenSSLX509CertDebugDump		(X509* cert, 
 								 FILE* output);
 static void		xmlSecOpenSSLX509CertDebugXmlDump	(X509* cert, 
@@ -83,6 +101,12 @@
 static int		xmlSecOpenSSLX509CertGetTime		(ASN1_TIME* t,
 								 time_t* res);
 
+#define XMLSEC_OPENSSL_X509_CERTIFICATE_NODE			0x00000001
+#define XMLSEC_OPENSSL_X509_SUBJECTNAME_NODE			0x00000002
+#define XMLSEC_OPENSSL_X509_ISSUERSERIAL_NODE			0x00000004
+#define XMLSEC_OPENSSL_X509_SKI_NODE				0x00000008
+#define XMLSEC_OPENSSL_X509_CRL_NODE				0x00000010
+
 /*************************************************************************
  *
  * Internal OpenSSL X509 data CTX
@@ -679,22 +703,65 @@
 xmlSecOpenSSLKeyDataX509XmlWrite(xmlSecKeyDataId id, xmlSecKeyPtr key,
 				xmlNodePtr node, xmlSecKeyInfoCtxPtr keyInfoCtx) {
     xmlSecKeyDataPtr data;
-    xmlNodePtr cur;
-    xmlChar* buf;
+    xmlNodePtr cur, next;
     X509* cert;
     X509_CRL* crl;
     xmlSecSize size, pos;
-    				
+    unsigned int content = 0;
+    int deleteCurNode;
+    int ret;
+    			
     xmlSecAssert2(id == xmlSecOpenSSLKeyDataX509Id, -1);
     xmlSecAssert2(key != NULL, -1);
     xmlSecAssert2(node != NULL, -1);
     xmlSecAssert2(keyInfoCtx != NULL, -1);
 
-    /* todo: flag in ctx remove all existing content */
-    if(0) {
-        xmlNodeSetContent(node, NULL);
+    /* determine the current node content */
+    cur = xmlSecGetNextElementNode(node->children); 
+    while(cur != NULL) {
+	deleteCurNode = 0;
+	if(xmlSecCheckNodeName(cur, xmlSecNodeX509Certificate, xmlSecDSigNs)) {
+	    if(xmlSecIsEmptyNode(cur) == 1) {
+		content |= XMLSEC_OPENSSL_X509_CERTIFICATE_NODE;
+		deleteCurNode = 1;
+	    }
+	} else if(xmlSecCheckNodeName(cur, xmlSecNodeX509SubjectName, xmlSecDSigNs)) {
+	    if(xmlSecIsEmptyNode(cur) == 1) {
+    	        content |= XMLSEC_OPENSSL_X509_SUBJECTNAME_NODE;
+		deleteCurNode = 1;
+	    }
+	} else if(xmlSecCheckNodeName(cur, xmlSecNodeX509IssuerSerial, xmlSecDSigNs)) {
+	    if(xmlSecIsEmptyNode(cur) == 1) {
+		content |= XMLSEC_OPENSSL_X509_ISSUERSERIAL_NODE;
+		deleteCurNode = 1;
+	    }
+	} else if(xmlSecCheckNodeName(cur, xmlSecNodeX509SKI, xmlSecDSigNs)) {
+	    if(xmlSecIsEmptyNode(cur) == 1) {
+		content |= XMLSEC_OPENSSL_X509_SKI_NODE;
+		deleteCurNode = 1;
+	    }
+	} else if(xmlSecCheckNodeName(cur, xmlSecNodeX509CRL, xmlSecDSigNs)) {
+	    if(xmlSecIsEmptyNode(cur) == 1) {
+		content |= XMLSEC_OPENSSL_X509_CRL_NODE;
+		deleteCurNode = 1;
+	    }
+	} else {
+	    /* todo: fail on unknown child node? */
+	}
+	next = xmlSecGetNextElementNode(cur->next);
+	if(deleteCurNode) {
+	    /* remove "template" nodes */
+	    xmlUnlinkNode(cur);
+	    xmlFreeNode(cur);
+	}
+	cur = next;
+    }
+    if(content == 0) {
+	/* by default we are writing certificates and crls */
+	content = XMLSEC_OPENSSL_X509_CERTIFICATE_NODE | XMLSEC_OPENSSL_X509_CRL_NODE;
     }
 
+    /* get x509 data */
     data = xmlSecKeyGetData(key, id);
     if(data == NULL) {
 	/* no x509 data in the key */
@@ -714,79 +781,85 @@
 	    return(-1);
 	}
 	
-	/* set base64 lines size from context */
-	buf = xmlSecOpenSSLX509CertBase64DerWrite(cert, keyInfoCtx->base64LineSize); 
-	if(buf == NULL) {
-	    xmlSecError(XMLSEC_ERRORS_HERE,
-			xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
-			"xmlSecOpenSSLX509CertBase64DerWrite",
-			XMLSEC_ERRORS_R_XMLSEC_FAILED,
-			XMLSEC_ERRORS_NO_MESSAGE);
-	    return(-1);
-	}
-	
-	cur = xmlSecAddChild(node, xmlSecNodeX509Certificate, xmlSecDSigNs);
-	if(cur == NULL) {
-	    xmlSecError(XMLSEC_ERRORS_HERE,
-			xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
-			"xmlSecAddChild",
-			XMLSEC_ERRORS_R_XMLSEC_FAILED,
-			"node=%s",
-			xmlSecErrorsSafeString(xmlSecNodeX509Certificate));
-	    xmlFree(buf);
-	    return(-1);	
+	if((content & XMLSEC_OPENSSL_X509_CERTIFICATE_NODE) != 0) {
+	    ret = xmlSecOpenSSLX509CertificateNodeWrite(cert, node, keyInfoCtx);
+	    if(ret < 0) {
+		xmlSecError(XMLSEC_ERRORS_HERE,
+			    xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
+			    "xmlSecOpenSSLX509CertificateNodeWrite",
+			    XMLSEC_ERRORS_R_XMLSEC_FAILED,
+			    "pos=%d", pos);
+		return(-1);
+	    }
 	}
-	/* todo: add \n around base64 data - from context */
-	/* todo: add errors check */
-	xmlNodeSetContent(cur, xmlSecStringCR);
-	xmlNodeSetContent(cur, buf);
-	xmlFree(buf);
-    }    
 
-    /* write crls */
-    size = xmlSecOpenSSLKeyDataX509GetCrlsSize(data);
-    for(pos = 0; pos < size; ++pos) {
-	crl = xmlSecOpenSSLKeyDataX509GetCrl(data, pos);
-	if(crl == NULL) {
-	    xmlSecError(XMLSEC_ERRORS_HERE,
-			xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
-			"xmlSecOpenSSLKeyDataX509GetCrl",
-			XMLSEC_ERRORS_R_XMLSEC_FAILED,
-			"pos=%d", pos);
-	    return(-1);
+	if((content & XMLSEC_OPENSSL_X509_SUBJECTNAME_NODE) != 0) {
+	    ret = xmlSecOpenSSLX509SubjectNameNodeWrite(cert, node, keyInfoCtx);
+	    if(ret < 0) {
+		xmlSecError(XMLSEC_ERRORS_HERE,
+			    xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
+			    "xmlSecOpenSSLX509SubjectNameNodeWrite",
+			    XMLSEC_ERRORS_R_XMLSEC_FAILED,
+			    "pos=%d", pos);
+		return(-1);
+	    }
 	}
-	
-	/* set base64 lines size from context */
-	buf = xmlSecOpenSSLX509CrlBase64DerWrite(crl, keyInfoCtx->base64LineSize); 
-	if(buf == NULL) {
-	    xmlSecError(XMLSEC_ERRORS_HERE,
-			xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
-			"xmlSecOpenSSLX509CrlBase64DerWrite",
-			XMLSEC_ERRORS_R_XMLSEC_FAILED,
-			XMLSEC_ERRORS_NO_MESSAGE);
-	    return(-1);
+
+	if((content & XMLSEC_OPENSSL_X509_ISSUERSERIAL_NODE) != 0) {
+	    ret = xmlSecOpenSSLX509IssuerSerialNodeWrite(cert, node, keyInfoCtx);
+	    if(ret < 0) {
+		xmlSecError(XMLSEC_ERRORS_HERE,
+			    xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
+			    "xmlSecOpenSSLX509IssuerSerialNodeWrite",
+			    XMLSEC_ERRORS_R_XMLSEC_FAILED,
+			    "pos=%d", pos);
+		return(-1);
+	    }
 	}
-	
-	cur = xmlSecAddChild(node, xmlSecNodeX509CRL, xmlSecDSigNs);
-	if(cur == NULL) {
-	    xmlSecError(XMLSEC_ERRORS_HERE,
-			xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
-			"xmlSecAddChild",
-			XMLSEC_ERRORS_R_XMLSEC_FAILED,
-			"new_node=%s",
-			xmlSecErrorsSafeString(xmlSecNodeX509CRL));
-	    xmlFree(buf);
-	    return(-1);	
+
+	if((content & XMLSEC_OPENSSL_X509_SKI_NODE) != 0) {
+	    ret = xmlSecOpenSSLX509SKINodeWrite(cert, node, keyInfoCtx);
+	    if(ret < 0) {
+		xmlSecError(XMLSEC_ERRORS_HERE,
+			    xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
+			    "xmlSecOpenSSLX509SKINodeWrite",
+			    XMLSEC_ERRORS_R_XMLSEC_FAILED,
+			    "pos=%d", pos);
+		return(-1);
+	    }
 	}
-	/* todo: add \n around base64 data - from context */
-	/* todo: add errors check */
-	xmlNodeSetContent(cur, xmlSecStringCR);
-	xmlNodeSetContent(cur, buf);	
     }    
+
+    /* write crls if needed */
+    if((content & XMLSEC_OPENSSL_X509_CRL_NODE) != 0) {
+	size = xmlSecOpenSSLKeyDataX509GetCrlsSize(data);
+	for(pos = 0; pos < size; ++pos) {
+	    crl = xmlSecOpenSSLKeyDataX509GetCrl(data, pos);
+	    if(crl == NULL) {
+		xmlSecError(XMLSEC_ERRORS_HERE,
+			    xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
+			    "xmlSecOpenSSLKeyDataX509GetCrl",
+			    XMLSEC_ERRORS_R_XMLSEC_FAILED,
+			    "pos=%d", pos);
+		return(-1);
+	    }
+	    
+	    ret = xmlSecOpenSSLX509CRLNodeWrite(crl, node, keyInfoCtx);
+	    if(ret < 0) {
+		xmlSecError(XMLSEC_ERRORS_HERE,
+			    xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
+			    "xmlSecOpenSSLX509SKINodeWrite",
+			    XMLSEC_ERRORS_R_XMLSEC_FAILED,
+			    "pos=%d", pos);
+		return(-1);
+	    }
+	}
+    }
     
     return(0);
 }
 
+
 static xmlSecKeyDataType
 xmlSecOpenSSLKeyDataX509GetType(xmlSecKeyDataPtr data) {
     xmlSecAssert2(xmlSecKeyDataCheckId(data, xmlSecOpenSSLKeyDataX509Id), xmlSecKeyDataTypeUnknown);
@@ -928,13 +1001,19 @@
     xmlSecAssert2(keyInfoCtx != NULL, -1);
 
     content = xmlNodeGetContent(node);
-    if(content == NULL){
-	xmlSecError(XMLSEC_ERRORS_HERE,
-		    xmlSecErrorsSafeString(xmlSecKeyDataGetName(data)),
-		    xmlSecErrorsSafeString(xmlSecNodeGetName(node)),
-		    XMLSEC_ERRORS_R_INVALID_NODE_CONTENT,
-		    XMLSEC_ERRORS_NO_MESSAGE);
-	return(-1);
+    if((content == NULL) || (xmlSecIsEmptyString(content) == 1)) {
+	if(content != NULL) {
+	    xmlFree(content);
+	}
+	if((keyInfoCtx->flags & XMLSEC_KEYINFO_FLAGS_STOP_ON_EMPTY_NODE) != 0) {
+	    xmlSecError(XMLSEC_ERRORS_HERE,
+			xmlSecErrorsSafeString(xmlSecKeyDataGetName(data)),
+			xmlSecErrorsSafeString(xmlSecNodeGetName(node)),
+			XMLSEC_ERRORS_R_INVALID_NODE_CONTENT,
+			XMLSEC_ERRORS_NO_MESSAGE);
+	    return(-1);
+	}
+	return(0);
     }
 
     cert = xmlSecOpenSSLX509CertBase64DerRead(content);
@@ -964,6 +1043,46 @@
     return(0);
 }
 
+static int 
+xmlSecOpenSSLX509CertificateNodeWrite(X509* cert, xmlNodePtr node, xmlSecKeyInfoCtxPtr keyInfoCtx) {
+    xmlChar* buf;
+    xmlNodePtr cur;
+    
+    xmlSecAssert2(cert != NULL, -1);
+    xmlSecAssert2(node != NULL, -1);
+    xmlSecAssert2(keyInfoCtx != NULL, -1);
+    
+    /* set base64 lines size from context */
+    buf = xmlSecOpenSSLX509CertBase64DerWrite(cert, keyInfoCtx->base64LineSize); 
+    if(buf == NULL) {
+	xmlSecError(XMLSEC_ERRORS_HERE,
+		    NULL,
+		    "xmlSecOpenSSLX509CertBase64DerWrite",
+		    XMLSEC_ERRORS_R_XMLSEC_FAILED,
+		    XMLSEC_ERRORS_NO_MESSAGE);
+	return(-1);
+    }
+	
+    cur = xmlSecAddChild(node, xmlSecNodeX509Certificate, xmlSecDSigNs);
+    if(cur == NULL) {
+	xmlSecError(XMLSEC_ERRORS_HERE,
+		    NULL,
+		    "xmlSecAddChild",
+		    XMLSEC_ERRORS_R_XMLSEC_FAILED,
+		    "node=%s",
+		    xmlSecErrorsSafeString(xmlSecNodeX509Certificate));
+	xmlFree(buf);
+	return(-1);	
+    }
+
+    /* todo: add \n around base64 data - from context */
+    /* todo: add errors check */
+    xmlNodeSetContent(cur, xmlSecStringCR);
+    xmlNodeSetContent(cur, buf);
+    xmlFree(buf);
+    return(0);
+}
+
 static int		
 xmlSecOpenSSLX509SubjectNameNodeRead(xmlSecKeyDataPtr data, xmlNodePtr node, xmlSecKeyInfoCtxPtr keyInfoCtx) {	
     xmlSecKeyDataStorePtr x509Store;
@@ -988,13 +1107,19 @@
     }
 
     subject = xmlNodeGetContent(node);
-    if(subject == NULL) {
-	xmlSecError(XMLSEC_ERRORS_HERE,
-		    xmlSecErrorsSafeString(xmlSecKeyDataGetName(data)),
-		    xmlSecErrorsSafeString(xmlSecNodeGetName(node)),
-		    XMLSEC_ERRORS_R_INVALID_NODE_CONTENT,
-		    XMLSEC_ERRORS_NO_MESSAGE);
-	return(-1);
+    if((subject == NULL) || (xmlSecIsEmptyString(subject) == 1)) {
+	if(subject != NULL) {
+	    xmlFree(subject);
+	}
+	if((keyInfoCtx->flags & XMLSEC_KEYINFO_FLAGS_STOP_ON_EMPTY_NODE) != 0) {
+	    xmlSecError(XMLSEC_ERRORS_HERE,
+		        xmlSecErrorsSafeString(xmlSecKeyDataGetName(data)),
+			xmlSecErrorsSafeString(xmlSecNodeGetName(node)),
+			XMLSEC_ERRORS_R_INVALID_NODE_CONTENT,
+			XMLSEC_ERRORS_NO_MESSAGE);
+	    return(-1);
+	}
+	return(0);
     }
 
     cert = xmlSecOpenSSLX509StoreFindCert(x509Store, subject, NULL, NULL, NULL, keyInfoCtx);
@@ -1040,6 +1165,40 @@
     return(0);
 }
 
+static int
+xmlSecOpenSSLX509SubjectNameNodeWrite(X509* cert, xmlNodePtr node, xmlSecKeyInfoCtxPtr keyInfoCtx ATTRIBUTE_UNUSED) {
+    xmlChar* buf = NULL;
+    xmlNodePtr cur = NULL;
+
+    xmlSecAssert2(cert != NULL, -1);
+    xmlSecAssert2(node != NULL, -1);
+
+    buf = xmlSecOpenSSLX509NameWrite(X509_get_subject_name(cert));
+    if(buf == NULL) {
+	xmlSecError(XMLSEC_ERRORS_HERE,
+	    NULL,
+	    "xmlSecOpenSSLX509NameWrite(X509_get_subject_name)",
+	    XMLSEC_ERRORS_R_XMLSEC_FAILED,
+	    XMLSEC_ERRORS_NO_MESSAGE);
+	return(-1);
+    }
+
+    cur = xmlSecAddChild(node, xmlSecNodeX509SubjectName, xmlSecDSigNs);
+    if(cur == NULL) {
+	xmlSecError(XMLSEC_ERRORS_HERE,
+	    NULL,
+	    "xmlSecAddChild",
+	    XMLSEC_ERRORS_R_XMLSEC_FAILED,
+	    "node=%s",
+	    xmlSecErrorsSafeString(xmlSecNodeX509SubjectName));
+	xmlFree(buf);
+	return(-1);
+    }
+    xmlNodeSetContent(cur, buf);
+    xmlFree(buf);
+    return(0);
+}
+
 static int 
 xmlSecOpenSSLX509IssuerSerialNodeRead(xmlSecKeyDataPtr data, xmlNodePtr node, xmlSecKeyInfoCtxPtr keyInfoCtx) {
     xmlSecKeyDataStorePtr x509Store;
@@ -1066,9 +1225,21 @@
     }
 
     cur = xmlSecGetNextElementNode(node->children);
-
+    if(cur == NULL) {
+	if((keyInfoCtx->flags & XMLSEC_KEYINFO_FLAGS_STOP_ON_EMPTY_NODE) != 0) {
+	    xmlSecError(XMLSEC_ERRORS_HERE,
+			xmlSecErrorsSafeString(xmlSecKeyDataGetName(data)),
+			xmlSecErrorsSafeString(xmlSecNodeX509IssuerName),
+			XMLSEC_ERRORS_R_NODE_NOT_FOUND,
+			"node=%s",
+			xmlSecErrorsSafeString(xmlSecNodeGetName(cur)));
+	    return(-1);
+	}
+	return(0);
+    }
+    
     /* the first is required node X509IssuerName */
-    if((cur == NULL) || !xmlSecCheckNodeName(cur, xmlSecNodeX509IssuerName, xmlSecDSigNs)) {
+    if(!xmlSecCheckNodeName(cur, xmlSecNodeX509IssuerName, xmlSecDSigNs)) {
 	xmlSecError(XMLSEC_ERRORS_HERE,
 		    xmlSecErrorsSafeString(xmlSecKeyDataGetName(data)),
 		    xmlSecErrorsSafeString(xmlSecNodeX509IssuerName),
@@ -1172,6 +1343,79 @@
     return(0);
 }
 
+static int
+xmlSecOpenSSLX509IssuerSerialNodeWrite(X509* cert, xmlNodePtr node, xmlSecKeyInfoCtxPtr keyInfoCtx ATTRIBUTE_UNUSED) {
+    xmlNodePtr cur;
+    xmlNodePtr issuerNameNode;
+    xmlNodePtr issuerNumberNode;
+    xmlChar* buf;
+    
+    xmlSecAssert2(cert != NULL, -1);
+    xmlSecAssert2(node != NULL, -1);
+
+    /* create xml nodes */
+    cur = xmlSecAddChild(node, xmlSecNodeX509IssuerSerial, xmlSecDSigNs);
+    if(cur == NULL) {
+	xmlSecError(XMLSEC_ERRORS_HERE,
+		    NULL,
+		    "xmlSecAddChild",
+		    XMLSEC_ERRORS_R_XMLSEC_FAILED,
+		    "node=%s",
+		    xmlSecErrorsSafeString(xmlSecNodeX509IssuerSerial));
+	return(-1);
+    }
+
+    issuerNameNode = xmlSecAddChild(cur, xmlSecNodeX509IssuerName, xmlSecDSigNs);
+    if(issuerNameNode == NULL) {
+	xmlSecError(XMLSEC_ERRORS_HERE,
+		    NULL,
+		    "xmlSecAddChild",
+		    XMLSEC_ERRORS_R_XMLSEC_FAILED,
+		    "node=%s",
+		    xmlSecErrorsSafeString(xmlSecNodeX509IssuerName));
+	return(-1);
+    }
+
+    issuerNumberNode = xmlSecAddChild(cur, xmlSecNodeX509SerialNumber, xmlSecDSigNs);
+    if(issuerNumberNode == NULL) {
+	xmlSecError(XMLSEC_ERRORS_HERE,
+		    NULL,
+		    "xmlSecAddChild",
+		    XMLSEC_ERRORS_R_XMLSEC_FAILED,
+		    "node=%s",
+		    xmlSecErrorsSafeString(xmlSecNodeX509SerialNumber));
+	return(-1);
+    }
+
+    /* write data */
+    buf = xmlSecOpenSSLX509NameWrite(X509_get_issuer_name(cert));
+    if(buf == NULL) {
+	xmlSecError(XMLSEC_ERRORS_HERE,
+		    NULL,
+		    "xmlSecOpenSSLX509NameWrite(X509_get_issuer_name)",
+		    XMLSEC_ERRORS_R_XMLSEC_FAILED,
+		    XMLSEC_ERRORS_NO_MESSAGE);
+	return(-1);
+    }
+    xmlNodeSetContent(issuerNameNode, buf);
+    xmlFree(buf);
+
+    buf = xmlSecOpenSSLASN1IntegerWrite(X509_get_serialNumber(cert));
+    if(buf == NULL) {
+	xmlSecError(XMLSEC_ERRORS_HERE,
+		    NULL,
+		    "xmlSecOpenSSLASN1IntegerWrite(X509_get_serialNumber)",
+		    XMLSEC_ERRORS_R_XMLSEC_FAILED,
+		    XMLSEC_ERRORS_NO_MESSAGE);
+	return(-1);
+    }
+    xmlNodeSetContent(issuerNumberNode, buf);
+    xmlFree(buf);
+
+    return(0);
+}
+
+
 static int 
 xmlSecOpenSSLX509SKINodeRead(xmlSecKeyDataPtr data, xmlNodePtr node, xmlSecKeyInfoCtxPtr keyInfoCtx) {
     xmlSecKeyDataStorePtr x509Store;
@@ -1196,14 +1440,20 @@
     }
     
     ski = xmlNodeGetContent(node);
-    if(ski == NULL) {
-	xmlSecError(XMLSEC_ERRORS_HERE,
-		    xmlSecErrorsSafeString(xmlSecKeyDataGetName(data)),
-		    xmlSecErrorsSafeString(xmlSecNodeGetName(node)),
-		    XMLSEC_ERRORS_R_INVALID_NODE_CONTENT,
-		    "node=%s",
-		    xmlSecErrorsSafeString(xmlSecNodeX509SKI));
-	return(-1);
+    if((ski == NULL) || (xmlSecIsEmptyString(ski) == 1)) {
+	if(ski != NULL) {
+	    xmlFree(ski);
+	}
+	if((keyInfoCtx->flags & XMLSEC_KEYINFO_FLAGS_STOP_ON_EMPTY_NODE) != 0) {
+	    xmlSecError(XMLSEC_ERRORS_HERE,
+			xmlSecErrorsSafeString(xmlSecKeyDataGetName(data)),
+			xmlSecErrorsSafeString(xmlSecNodeGetName(node)),
+			XMLSEC_ERRORS_R_INVALID_NODE_CONTENT,
+			"node=%s",
+			xmlSecErrorsSafeString(xmlSecNodeX509SKI));
+	    return(-1);
+	}
+	return(0);
     }
 
     cert = xmlSecOpenSSLX509StoreFindCert(x509Store, NULL, NULL, NULL, ski, keyInfoCtx);
@@ -1249,6 +1499,41 @@
     return(0);
 }
 
+static int
+xmlSecOpenSSLX509SKINodeWrite(X509* cert, xmlNodePtr node, xmlSecKeyInfoCtxPtr keyInfoCtx ATTRIBUTE_UNUSED) {
+    xmlChar *buf = NULL;
+    xmlNodePtr cur = NULL;
+
+    xmlSecAssert2(cert != NULL, -1);
+    xmlSecAssert2(node != NULL, -1);
+
+    buf = xmlSecOpenSSLX509SKIWrite(cert);
+    if(buf == NULL) {
+	xmlSecError(XMLSEC_ERRORS_HERE,
+		    NULL,
+		    "xmlSecOpenSSLX509SKIWrite",
+		    XMLSEC_ERRORS_R_XMLSEC_FAILED,
+		    XMLSEC_ERRORS_NO_MESSAGE);
+	return(-1);
+    }
+
+    cur = xmlSecAddChild(node, xmlSecNodeX509SKI, xmlSecDSigNs);
+    if(cur == NULL) {
+	xmlSecError(XMLSEC_ERRORS_HERE,
+		    NULL,
+		    "xmlSecAddChild",
+		    XMLSEC_ERRORS_R_XMLSEC_FAILED,
+		    "new_node=%s",
+		    xmlSecErrorsSafeString(xmlSecNodeX509SKI));
+	xmlFree(buf);
+	return(-1);
+    }
+    xmlNodeSetContent(cur, buf);
+    xmlFree(buf);
+
+    return(0);
+}
+
 static int 
 xmlSecOpenSSLX509CRLNodeRead(xmlSecKeyDataPtr data, xmlNodePtr node, xmlSecKeyInfoCtxPtr keyInfoCtx) {
     xmlChar *content;
@@ -1260,13 +1545,19 @@
     xmlSecAssert2(keyInfoCtx != NULL, -1);
 
     content = xmlNodeGetContent(node);
-    if(content == NULL){
-	xmlSecError(XMLSEC_ERRORS_HERE,
-		    xmlSecErrorsSafeString(xmlSecKeyDataGetName(data)),
-		    xmlSecErrorsSafeString(xmlSecNodeGetName(node)),
-		    XMLSEC_ERRORS_R_INVALID_NODE_CONTENT,
-		    XMLSEC_ERRORS_NO_MESSAGE);
-	return(-1);
+    if((content == NULL) || (xmlSecIsEmptyString(content) == 1)) {
+	if(content != NULL) {
+	    xmlFree(content);
+	}
+	if((keyInfoCtx->flags & XMLSEC_KEYINFO_FLAGS_STOP_ON_EMPTY_NODE) != 0) {
+	    xmlSecError(XMLSEC_ERRORS_HERE,
+			xmlSecErrorsSafeString(xmlSecKeyDataGetName(data)),
+			xmlSecErrorsSafeString(xmlSecNodeGetName(node)),
+			XMLSEC_ERRORS_R_INVALID_NODE_CONTENT,
+			XMLSEC_ERRORS_NO_MESSAGE);
+	    return(-1);
+	}
+	return(0);
     }
 
     crl = xmlSecOpenSSLX509CrlBase64DerRead(content);
@@ -1297,6 +1588,46 @@
 }
 
 static int
+xmlSecOpenSSLX509CRLNodeWrite(X509_CRL* crl, xmlNodePtr node, xmlSecKeyInfoCtxPtr keyInfoCtx) {
+    xmlChar* buf = NULL;
+    xmlNodePtr cur = NULL;
+
+    xmlSecAssert2(crl != NULL, -1);
+    xmlSecAssert2(node != NULL, -1);
+    xmlSecAssert2(keyInfoCtx != NULL, -1);
+
+    /* set base64 lines size from context */
+    buf = xmlSecOpenSSLX509CrlBase64DerWrite(crl, keyInfoCtx->base64LineSize); 
+    if(buf == NULL) {
+	xmlSecError(XMLSEC_ERRORS_HERE,
+		    NULL,
+		    "xmlSecOpenSSLX509CrlBase64DerWrite",
+		    XMLSEC_ERRORS_R_XMLSEC_FAILED,
+		    XMLSEC_ERRORS_NO_MESSAGE);
+	return(-1);
+    }
+
+    cur = xmlSecAddChild(node, xmlSecNodeX509CRL, xmlSecDSigNs);
+    if(cur == NULL) {
+	xmlSecError(XMLSEC_ERRORS_HERE,
+		    NULL,
+		    "xmlSecAddChild",
+		    XMLSEC_ERRORS_R_XMLSEC_FAILED,
+		    "new_node=%s",
+		    xmlSecErrorsSafeString(xmlSecNodeX509CRL));
+	xmlFree(buf);
+	return(-1);
+    }
+    /* todo: add \n around base64 data - from context */
+    /* todo: add errors check */
+    xmlNodeSetContent(cur, xmlSecStringCR);
+    xmlNodeSetContent(cur, buf);
+    xmlFree(buf);
+
+    return(0);
+}
+
+static int
 xmlSecOpenSSLKeyDataX509VerifyAndExtractKey(xmlSecKeyDataPtr data, xmlSecKeyPtr key,
 				    xmlSecKeyInfoCtxPtr keyInfoCtx) {
     xmlSecOpenSSLX509DataCtxPtr ctx;
@@ -1776,6 +2107,160 @@
     }    
 
     BIO_free_all(mem);    
+    return(res);
+}
+
+static xmlChar*
+xmlSecOpenSSLX509NameWrite(X509_NAME* nm) {
+    xmlChar *res = NULL;
+    BIO *mem = NULL;
+    long size;
+
+    xmlSecAssert2(nm != NULL, NULL);
+
+    mem = BIO_new(BIO_s_mem());
+    if(mem == NULL) {
+        xmlSecError(XMLSEC_ERRORS_HERE,
+        	    NULL,
+        	    "BIO_new",
+        	    XMLSEC_ERRORS_R_CRYPTO_FAILED,
+        	    "BIO_s_mem");
+        return(NULL);
+    }
+
+    if (X509_NAME_print_ex(mem, nm, 0, XN_FLAG_RFC2253) <=0) {
+        xmlSecError(XMLSEC_ERRORS_HERE,
+        	    NULL,
+        	    "X509_NAME_print_ex",
+        	    XMLSEC_ERRORS_R_CRYPTO_FAILED,
+        	    XMLSEC_ERRORS_NO_MESSAGE);
+        BIO_free_all(mem);
+        return(NULL);
+    }
+
+    BIO_flush(mem); /* should call flush ? */
+
+    size = BIO_pending(mem);
+    res = xmlMalloc(size + 1);
+    if(res == NULL) {
+	xmlSecError(XMLSEC_ERRORS_HERE,
+		    NULL,
+		    "ASN1_INTEGER_to_BN",
+		    XMLSEC_ERRORS_R_MALLOC_FAILED,
+		    XMLSEC_ERRORS_NO_MESSAGE);
+	BIO_free_all(mem);
+	return(NULL);
+    }
+
+    size = BIO_read(mem, res, size);
+    res[size] = '\0';
+
+    BIO_free_all(mem);
+    return(res);
+}
+
+static xmlChar*
+xmlSecOpenSSLASN1IntegerWrite(ASN1_INTEGER *asni) {
+    xmlChar *res = NULL;
+    BIGNUM *bn;
+    char *p;
+    
+    xmlSecAssert2(asni != NULL, NULL);
+
+    bn = ASN1_INTEGER_to_BN(asni, NULL);
+    if(bn == NULL) {
+	xmlSecError(XMLSEC_ERRORS_HERE,
+		    NULL,
+		    "ASN1_INTEGER_to_BN",
+		    XMLSEC_ERRORS_R_CRYPTO_FAILED,
+		    XMLSEC_ERRORS_NO_MESSAGE);
+	return(NULL);
+    }
+
+    p = BN_bn2dec(bn);
+    if (p == NULL) {
+	xmlSecError(XMLSEC_ERRORS_HERE,
+		    NULL,
+		    "BN_bn2dec",
+		    XMLSEC_ERRORS_R_XMLSEC_FAILED,
+		    XMLSEC_ERRORS_NO_MESSAGE);
+	BN_free(bn);
+	return(NULL);
+    }
+    BN_free(bn);
+    bn = NULL;
+
+    /* OpenSSL and LibXML2 can have different memory callbacks, i.e.
+       when data is allocated in OpenSSL should be freed with OpenSSL
+       method, not with LibXML2 method.
+     */
+    res = xmlCharStrdup(p);
+    if(res == NULL) {
+	xmlSecError(XMLSEC_ERRORS_HERE,
+		    NULL,
+		    "xmlCharStrdup",
+		    XMLSEC_ERRORS_R_MALLOC_FAILED,
+		    XMLSEC_ERRORS_NO_MESSAGE);
+	OPENSSL_free(p);
+	return(NULL);
+    }
+    OPENSSL_free(p);
+    p = NULL;
+    return(res);
+}
+
+static xmlChar*
+xmlSecOpenSSLX509SKIWrite(X509* cert) {
+    xmlChar *res = NULL;
+    int index;
+    X509_EXTENSION *ext;
+    ASN1_OCTET_STRING *keyId;
+
+    xmlSecAssert2(cert != NULL, NULL);
+
+    index = X509_get_ext_by_NID(cert, NID_subject_key_identifier, -1);
+    if (index < 0) {
+	xmlSecError(XMLSEC_ERRORS_HERE,
+		    NULL,
+		    "Certificate without SubjectKeyIdentifier extension",
+		    XMLSEC_ERRORS_R_CRYPTO_FAILED,
+		    XMLSEC_ERRORS_NO_MESSAGE);
+	return(NULL);
+    }
+    
+    ext = X509_get_ext(cert, index);
+    if (ext == NULL) {
+	xmlSecError(XMLSEC_ERRORS_HERE,
+		    NULL,
+		    "X509_get_ext",
+		    XMLSEC_ERRORS_R_CRYPTO_FAILED,
+		    XMLSEC_ERRORS_NO_MESSAGE);
+	return(NULL);
+    }
+
+    keyId = X509V3_EXT_d2i(ext);
+    if (keyId == NULL) {
+	xmlSecError(XMLSEC_ERRORS_HERE,
+		    NULL,
+		    "X509V3_EXT_d2i",
+	    	    XMLSEC_ERRORS_R_CRYPTO_FAILED,
+		    XMLSEC_ERRORS_NO_MESSAGE);
+	M_ASN1_OCTET_STRING_free(keyId);
+	return(NULL);
+    }
+
+    res = xmlSecBase64Encode(M_ASN1_STRING_data(keyId), M_ASN1_STRING_length(keyId), 0);
+    if(res == NULL) {
+	xmlSecError(XMLSEC_ERRORS_HERE,
+		    NULL,
+		    "xmlSecBase64Encode",
+	    	    XMLSEC_ERRORS_R_XMLSEC_FAILED,
+		    XMLSEC_ERRORS_NO_MESSAGE);
+	M_ASN1_OCTET_STRING_free(keyId);
+	return(NULL);
+    }
+    M_ASN1_OCTET_STRING_free(keyId);
+    
     return(res);
 }
 



More information about the xmlsec mailing list