summaryrefslogtreecommitdiffstats
path: root/lasso/xml
diff options
context:
space:
mode:
authorBenjamin Dauvergne <bdauvergne@entrouvert.com>2012-05-05 22:32:48 +0200
committerBenjamin Dauvergne <bdauvergne@entrouvert.com>2012-05-05 22:32:48 +0200
commitc7cf89b387cbc52d7d49d09b65a13af6bd0c47c2 (patch)
treeeb5e09723323e3480050c68a5ffdfe114f086ca6 /lasso/xml
parentd3c702e130ab654fd47081c1460f2f8527d10bc8 (diff)
parentf3409ece4dab64da843f118f2739481c1bff2613 (diff)
downloadlasso-c7cf89b387cbc52d7d49d09b65a13af6bd0c47c2.tar.gz
lasso-c7cf89b387cbc52d7d49d09b65a13af6bd0c47c2.tar.xz
lasso-c7cf89b387cbc52d7d49d09b65a13af6bd0c47c2.zip
Merge branch 'release-2.4.0'
Diffstat (limited to 'lasso/xml')
-rw-r--r--lasso/xml/private.h8
-rw-r--r--lasso/xml/tools.c120
-rw-r--r--lasso/xml/xml.c143
-rw-r--r--lasso/xml/xml.h5
4 files changed, 207 insertions, 69 deletions
diff --git a/lasso/xml/private.h b/lasso/xml/private.h
index 009596d8..629d6ca5 100644
--- a/lasso/xml/private.h
+++ b/lasso/xml/private.h
@@ -275,7 +275,7 @@ lasso_create_hmac_key(const xmlSecByte * buf, xmlSecSize size);
lasso_error_t
lasso_get_hmac_key(const xmlSecKey *key, void **buffer, size_t *size);
-LassoSignatureContext lasso_make_signature_context_from_buffer(const char *buffer, size_t length,
+LassoSignatureContext lasso_make_signature_context_from_buffer(const void *buffer, size_t length,
const char *password, LassoSignatureMethod signature_method,
const char *certificate);
@@ -299,6 +299,12 @@ void set_xsi_type(xmlNode *node,
const xmlChar *type_ns_prefix,
const xmlChar *type_ns_href,
const xmlChar *type_name);
+
+void lasso_xmlnode_add_saml2_signature_template(xmlNode *node, LassoSignatureContext context,
+ const char *id);
+
+gchar* lasso_xmlnode_build_deflated_query(xmlNode *xmlnode);
+
#ifdef __cplusplus
}
#endif /* __cplusplus */
diff --git a/lasso/xml/tools.c b/lasso/xml/tools.c
index b31e7187..36c76a05 100644
--- a/lasso/xml/tools.c
+++ b/lasso/xml/tools.c
@@ -1012,6 +1012,17 @@ lasso_node_build_deflated_query(LassoNode *node)
{
/* actually deflated and b64'ed and url-escaped */
xmlNode *xmlnode;
+ gchar *result;
+
+ xmlnode = lasso_node_get_xmlNode(node, FALSE);
+ result = lasso_xmlnode_build_deflated_query(xmlnode);
+ xmlFreeNode(node);
+ return result;
+}
+
+gchar*
+lasso_xmlnode_build_deflated_query(xmlNode *xmlnode)
+{
xmlOutputBufferPtr buf;
xmlCharEncodingHandlerPtr handler = NULL;
xmlChar *buffer;
@@ -1021,17 +1032,12 @@ lasso_node_build_deflated_query(LassoNode *node)
int rc = 0;
z_stream stream;
- xmlnode = lasso_node_get_xmlNode(node, FALSE);
-
handler = xmlFindCharEncodingHandler("utf-8");
buf = xmlAllocOutputBuffer(handler);
xmlNodeDumpOutput(buf, NULL, xmlnode, 0, 0, "utf-8");
xmlOutputBufferFlush(buf);
buffer = buf->conv ? buf->conv->content : buf->buffer->content;
- xmlFreeNode(xmlnode);
- xmlnode = NULL;
-
in_len = strlen((char*)buffer);
ret = g_malloc(in_len * 2);
/* deflating should never increase the required size but we are
@@ -1079,6 +1085,35 @@ lasso_node_build_deflated_query(LassoNode *node)
return rret;
}
+void
+lasso_get_query_string_param_value(const char *qs, const char *param_key, char **value,
+ size_t *length)
+{
+ size_t key_size = strlen(param_key);
+
+ *value = NULL;
+ *length = 0;
+ while (qs) {
+ if (strncmp(qs, param_key, key_size) == 0 &&
+ qs[key_size] == '=')
+ {
+ char *end;
+ *value = qs[key_size+1];
+ end = strchr(*value, '&');
+ if (! end) {
+ end = strchr(*value, ';');
+ }
+ if (end) {
+ *length = (ptrdiff_t)(end - *value)
+ } else {
+ *length = strlen(*value);
+ }
+ return;
+ }
+ qs = strchr(qs, '&');
+ }
+}
+
gboolean
lasso_node_init_from_deflated_query_part(LassoNode *node, char *deflate_string)
{
@@ -2367,7 +2402,7 @@ lasso_get_hmac_key(const xmlSecKey *key, void **buffer, size_t *size)
* successful, LASSO_SIGNATURE_CONTEXT_NONE otherwise. The caller must free the #xmlSecKey.
*/
LassoSignatureContext
-lasso_make_signature_context_from_buffer(const char *buffer, size_t length, const char *password,
+lasso_make_signature_context_from_buffer(const void *buffer, size_t length, const char *password,
LassoSignatureMethod signature_method, const char *certificate) {
LassoSignatureContext context = LASSO_SIGNATURE_CONTEXT_NONE;
@@ -2466,3 +2501,76 @@ set_xsi_type(xmlNode *node,
type_ns_href,
type_name);
}
+
+void
+lasso_xmlnode_add_saml2_signature_template(xmlNode *node, LassoSignatureContext context,
+ const char *id) {
+ xmlSecTransformId transform_id;
+ xmlNode *existing_signature = NULL, *signature = NULL, *reference, *key_info;
+ char *uri;
+
+ if (! lasso_validate_signature_context(context) || ! node)
+ return;
+
+ switch (context.signature_method) {
+ case LASSO_SIGNATURE_METHOD_RSA_SHA1:
+ transform_id = xmlSecTransformRsaSha1Id;
+ break;
+ case LASSO_SIGNATURE_METHOD_DSA_SHA1:
+ transform_id = xmlSecTransformDsaSha1Id;
+ break;
+ case LASSO_SIGNATURE_METHOD_HMAC_SHA1:
+ transform_id = xmlSecTransformHmacSha1Id;
+ break;
+ default:
+ g_assert_not_reached();
+ }
+ existing_signature = xmlSecFindChild(node, xmlSecNodeSignature, xmlSecDSigNs);
+ signature = xmlSecTmplSignatureCreate(NULL,
+ xmlSecTransformExclC14NId,
+ transform_id, NULL);
+ if (existing_signature) {
+ xmlSecReplaceNode(existing_signature, signature);
+ } else {
+ xmlAddChild(node, signature);
+ }
+
+ /* Normally the signature is son of the signed node, which holds an Id attribute, but in
+ * other cases, set snippet->offset to 0 and use xmlSecTmpSignatureAddReference from another
+ * node get_xmlNode virtual method to add the needed reference.
+ */
+ if (id) {
+ uri = g_strdup_printf("#%s", id);
+ reference = xmlSecTmplSignatureAddReference(signature,
+ xmlSecTransformSha1Id, NULL, (xmlChar*)uri, NULL);
+ lasso_release(uri);
+ }
+
+ /* add enveloped transform */
+ xmlSecTmplReferenceAddTransform(reference, xmlSecTransformEnvelopedId);
+ /* add exclusive C14N transform */
+ xmlSecTmplReferenceAddTransform(reference, xmlSecTransformExclC14NId);
+ /* if the key is the public part of an asymetric key, add its certificate or the key itself */
+ switch (context.signature_method) {
+ case LASSO_SIGNATURE_METHOD_RSA_SHA1:
+ case LASSO_SIGNATURE_METHOD_DSA_SHA1:
+ /* asymetric cryptography methods */
+ key_info = xmlSecTmplSignatureEnsureKeyInfo(signature, NULL);
+ if (xmlSecKeyGetData(context.signature_key, xmlSecOpenSSLKeyDataX509Id)) {
+ /* add <dsig:KeyInfo/> */
+ xmlSecTmplKeyInfoAddX509Data(key_info);
+ } else {
+ xmlSecTmplKeyInfoAddKeyValue(key_info);
+ }
+ break;
+ case LASSO_SIGNATURE_METHOD_HMAC_SHA1:
+ if (context.signature_key->name) {
+ key_info = xmlSecTmplSignatureEnsureKeyInfo(signature, NULL);
+ xmlSecTmplKeyInfoAddKeyName(key_info, NULL);
+
+ }
+ break;
+ default:
+ g_assert_not_reached();
+ }
+}
diff --git a/lasso/xml/xml.c b/lasso/xml/xml.c
index fc7100e0..f3ed6e3a 100644
--- a/lasso/xml/xml.c
+++ b/lasso/xml/xml.c
@@ -2810,11 +2810,7 @@ lasso_node_add_signature_template(LassoNode *node, xmlNode *xmlnode,
LassoNodeClass *klass = NULL;
LassoNodeClassData *node_data = NULL;
LassoSignatureContext context;
- xmlSecTransformId transform_id;
- xmlNode *signature = NULL, *reference, *key_info;
- char *uri;
- char *id;
-
+ char *id = NULL;
node_data = lasso_legacy_get_signature_node_data(node, &klass);
if (! node_data)
@@ -2828,66 +2824,11 @@ lasso_node_add_signature_template(LassoNode *node, xmlNode *xmlnode,
if (lasso_legacy_extract_and_copy_signature_parameters(node, node_data))
context = lasso_node_get_signature(node);
- if (! lasso_validate_signature_context(context))
- return;
-
- switch (context.signature_method) {
- case LASSO_SIGNATURE_METHOD_RSA_SHA1:
- transform_id = xmlSecTransformRsaSha1Id;
- break;
- case LASSO_SIGNATURE_METHOD_DSA_SHA1:
- transform_id = xmlSecTransformDsaSha1Id;
- break;
- case LASSO_SIGNATURE_METHOD_HMAC_SHA1:
- transform_id = xmlSecTransformHmacSha1Id;
- break;
- default:
- g_assert_not_reached();
- }
- signature = xmlSecTmplSignatureCreate(NULL,
- xmlSecTransformExclC14NId,
- transform_id, NULL);
- xmlAddChild(xmlnode, signature);
-
- /* Normally the signature is son of the signed node, which holds an Id attribute, but in
- * other cases, set snippet->offset to 0 and use xmlSecTmpSignatureAddReference from another
- * node get_xmlNode virtual method to add the needed reference.
- */
if (snippet_signature->offset) {
id = SNIPPET_STRUCT_MEMBER(char *, node, G_TYPE_FROM_CLASS(klass), snippet_signature);
- uri = g_strdup_printf("#%s", id);
- reference = xmlSecTmplSignatureAddReference(signature,
- xmlSecTransformSha1Id, NULL, (xmlChar*)uri, NULL);
- lasso_release(uri);
- }
-
- /* add enveloped transform */
- xmlSecTmplReferenceAddTransform(reference, xmlSecTransformEnvelopedId);
- /* add exclusive C14N transform */
- xmlSecTmplReferenceAddTransform(reference, xmlSecTransformExclC14NId);
- /* if the key is the public part of a symetric key, add its certificate or the key itself */
- switch (context.signature_method) {
- case LASSO_SIGNATURE_METHOD_RSA_SHA1:
- case LASSO_SIGNATURE_METHOD_DSA_SHA1:
- /* symetric cryptography methods */
- key_info = xmlSecTmplSignatureEnsureKeyInfo(signature, NULL);
- if (xmlSecKeyGetData(context.signature_key, xmlSecOpenSSLKeyDataX509Id)) {
- /* add <dsig:KeyInfo/> */
- xmlSecTmplKeyInfoAddX509Data(key_info);
- } else {
- xmlSecTmplKeyInfoAddKeyValue(key_info);
- }
- break;
- case LASSO_SIGNATURE_METHOD_HMAC_SHA1:
- if (context.signature_key->name) {
- key_info = xmlSecTmplSignatureEnsureKeyInfo(signature, NULL);
- xmlSecTmplKeyInfoAddKeyName(key_info, NULL);
-
- }
- break;
- default:
- g_assert_not_reached();
}
+
+ lasso_xmlnode_add_saml2_signature_template(xmlnode, context, id);
}
static struct XmlSnippet*
@@ -3475,3 +3416,81 @@ lasso_node_get_namespace(LassoNode *node)
return (const char*)klass->node_data->ns->href;
return NULL;
}
+
+
+/**
+ * lasso_node_export_to_saml2_query:
+ * @node: the #LassoNode object to pass as a query
+ * @param_name: the key value for the query string parameter
+ * @url:(allow-none): an optional URL to prepend to the query string
+ * @key:(allow-none): a #LassoKey object
+ *
+ * Export a node as signed query string, the node must support serialization as a query.
+ *
+ * Return value: an HTTP URL or query string if successful, NULL otherwise.
+ */
+char*
+lasso_node_export_to_saml2_query(LassoNode *node, const char *param_name, const char *url,
+ LassoKey *key)
+{
+ char *value = NULL, *query = NULL, *signed_query = NULL, *result = NULL;
+ xmlChar *encoded_param = NULL;
+
+ value = lasso_node_build_deflated_query(xmlnode);
+ if (! value)
+ goto cleanup;
+ encoded_param = xmlURIEscapeStr(BAD_CAST param_name, NULL);
+ if (! encoded_param)
+ goto cleanup;
+ query = g_strdup_printf("%s=%s", encoded_param, value);
+ if (! query)
+ goto cleanup;
+ if (LASSO_IS_KEY(key)) {
+ signed_query = lasso_key_query_sign(key, query);
+ } else {
+ lasso_transfer_string(signed_query, query);
+ }
+ if (! signed_query)
+ goto cleanup;
+ if (url) {
+ result = lasso_concat_url_query(url, signed_query);
+ } else {
+ lasso_transfer_string(result, signed_query);
+ }
+
+cleanup:
+ lasso_release_string(value);
+ lasso_release_xml_string(encoded_param);
+ lasso_release_string(query);
+ lasso_release_string(signed_query);
+ return result;
+}
+
+/**
+ * lasso_node_new_from_saml2_query:
+ * @url_or_qs: an URL containing a query string or a query string only
+ * @param_name: the key value for the query string parameter to extract as a #LassoNode.
+ * @key:(allow-none): a #LassoKey object
+ *
+ * Verify the signature on a SAML-2 encoded query string and return the encoded node.
+ *
+ * Return value: a newly build #LassoNode if successful, NULL otherwise.
+ */
+LassoNode*
+lasso_node_new_from_saml2_query(const char *url_or_qs, const char *param_name, LassoKey *key)
+{
+ char *needle = NULL;
+ LassoNode *result = NULL;
+
+ if (! url_or_qs || ! param_name)
+ return NULL;
+ needle = strchr(url_or_qs, '?');
+ if (needle) {
+ url_or_qs = (const char*)(needle+1);
+ }
+ if (key) {
+ goto_cleanup_if_fail(lasso_key_query_verify(key, url_or_qs) == 0);
+ }
+cleanup:
+ return result;
+}
diff --git a/lasso/xml/xml.h b/lasso/xml/xml.h
index 5407ed5a..5b2ac4c8 100644
--- a/lasso/xml/xml.h
+++ b/lasso/xml/xml.h
@@ -194,6 +194,11 @@ LASSO_EXPORT gchar* lasso_get_prefix_for_idwsf2_dst_service_href(const gchar *hr
LASSO_EXPORT char* lasso_node_debug(LassoNode *node, int level);
+typedef struct _LassoKey LassoKey;
+
+LASSO_EXPORT char* lasso_node_export_to_saml2_query(LassoNode *node, const char *param_name, const
+ char *url, LassoKey *key);
+
#ifdef __cplusplus
}
#endif /* __cplusplus */