From a8790d673d79fad1ff31b1c53ccf722b180757be Mon Sep 17 00:00:00 2001 From: Stefan Becker Date: Thu, 10 Nov 2011 14:12:49 +0200 Subject: [PATCH] xml: add function for "Exclusive XML Canonicalization" This is required to calculate XML signatures in sipe-certificate.c. --- src/core/sipe-certificate.c | 89 ++++++++++++++++++++++++--------------------- src/core/sipe-xml.c | 49 +++++++++++++++++++++++++ src/core/sipe-xml.h | 12 ++++++ 3 files changed, 109 insertions(+), 41 deletions(-) diff --git a/src/core/sipe-certificate.c b/src/core/sipe-certificate.c index 715465b7..0c1c33bd 100644 --- a/src/core/sipe-certificate.c +++ b/src/core/sipe-certificate.c @@ -207,7 +207,7 @@ static gchar *generate_sha1_proof_wsse(const gchar *raw, guchar digest[SIPE_DIGEST_SHA1_LENGTH]; gchar *base64; gchar *signed_info; - gchar *signature; + gchar *canon; /* Digest over reference element (#timestamp -> wsu:Timestamp) */ sipe_digest_sha1((guchar *) timestamp, @@ -231,48 +231,55 @@ static gchar *generate_sha1_proof_wsse(const gchar *raw, base64); g_free(base64); - /* SignatureValue calculation */ - /* Temporary. We need to - a) extract the wrapped key from keydata - b) unwrap the key (kw-aes256) - c) use the key as input to HMAC(SHA-1) of signed_info - - TODO: signed_info probably needs to be in canonical form - */ - { - guchar key[32]; - (void)entropy; - memset(key, 0, sizeof(key)); - sipe_digest_hmac_sha1(key, sizeof(key), - (guchar *)signed_info, - strlen(signed_info), - digest); - } - base64 = g_base64_encode(digest, - SIPE_DIGEST_HMAC_SHA1_LENGTH); - - /* XML-Sig: Signature from SignedInfo + Key */ - signature = g_strdup_printf("" - " %s" - " %s" - " " - " " - " %s" - " " - " " - "", - signed_info, - base64, - assertionID); - g_free(base64); + /* XML-Sig: SignedInfo in canonical form */ + canon = sipe_xml_exc_c14n(signed_info); g_free(signed_info); - g_free(assertionID); - wsse_security = g_strconcat(timestamp, - keydata, - signature, - NULL); - g_free(signature); + if (canon) { + gchar *signature; + + /* SignatureValue calculation */ + /* Temporary. We need to + a) extract the wrapped key from keydata + b) unwrap the key (kw-aes256) + c) use the key as input to HMAC(SHA-1) of canon + */ + { + guchar key[32]; + (void)entropy; + memset(key, 0, sizeof(key)); + sipe_digest_hmac_sha1(key, sizeof(key), + (guchar *)canon, + strlen(canon), + digest); + } + base64 = g_base64_encode(digest, + SIPE_DIGEST_HMAC_SHA1_LENGTH); + + /* XML-Sig: Signature from SignedInfo + Key */ + signature = g_strdup_printf("" + " %s" + " %s" + " " + " " + " %s" + " " + " " + "", + canon, + base64, + assertionID); + g_free(base64); + g_free(canon); + + wsse_security = g_strconcat(timestamp, + keydata, + signature, + NULL); + g_free(signature); + } + + g_free(assertionID); } } diff --git a/src/core/sipe-xml.c b/src/core/sipe-xml.c index 4fa80bcf..79ec677f 100644 --- a/src/core/sipe-xml.c +++ b/src/core/sipe-xml.c @@ -29,6 +29,9 @@ #include #include "libxml/parser.h" +#include "libxml/c14n.h" +#include "libxml/xmlversion.h" + #include "glib.h" #include "sipe-backend.h" @@ -383,6 +386,52 @@ void sipe_xml_dump(const sipe_xml *node, const gchar *path) #endif /* + * Other XML convenience functions not based on libpurple xmlnode.c + */ + +gchar *sipe_xml_exc_c14n(const gchar *string) +{ + /* Parse string to XML document */ + xmlDocPtr doc = xmlReadMemory(string, strlen(string), "", NULL, 0); + gchar *canon = NULL; + + if (doc) { + xmlChar *buffer; + int size; + + /* Apply canonicalization */ + size = xmlC14NDocDumpMemory(doc, + NULL, +#if LIBXML_VERSION > 20703 + /* new API: int mode (a xmlC14NMode) */ + XML_C14N_EXCLUSIVE_1_0, +#else + /* old API: int exclusive */ + 1, +#endif + NULL, + 0, + &buffer); + xmlFreeDoc(doc); + + if (size >= 0) { + SIPE_DEBUG_INFO("sipe_xml_exc_c14n:\noriginal: %s\ncanonicalized: %s", + string, buffer); + canon = g_strndup((gchar *) buffer, size); + xmlFree(buffer); + } else { + SIPE_DEBUG_ERROR("sipe_xml_exc_c14n: failed to canonicalize xml string:\n%s", + string); + } + } else { + SIPE_DEBUG_ERROR("sipe_xml_exc_c14n: error parsing xml string:\n%s", + string); + } + + return(canon); +} + +/* Local Variables: mode: c c-file-style: "bsd" diff --git a/src/core/sipe-xml.h b/src/core/sipe-xml.h index 40054df4..00fbee01 100644 --- a/src/core/sipe-xml.h +++ b/src/core/sipe-xml.h @@ -116,3 +116,15 @@ gchar *sipe_xml_data(const sipe_xml *node); * @param path The path to this node (can be NULL) */ void sipe_xml_dump(const sipe_xml *node, const gchar *path); + +/* Other XML convenience functions */ + +/** + * Apply "Exclusive XML Canonicalization" to a XML string + * See also http://www.w3.org/TR/xml-exc-c14n/ + * + * @param string String with the XML to be canonicalized. + * + * @return canonicalized XML string. Must be @c g_free()'d. + */ +gchar *sipe_xml_exc_c14n(const gchar *string); -- 2.11.4.GIT