diff options
| author | Benjamin Dauvergne <bdauvergne@entrouvert.com> | 2012-05-05 22:32:48 +0200 |
|---|---|---|
| committer | Benjamin Dauvergne <bdauvergne@entrouvert.com> | 2012-05-05 22:32:48 +0200 |
| commit | c7cf89b387cbc52d7d49d09b65a13af6bd0c47c2 (patch) | |
| tree | eb5e09723323e3480050c68a5ffdfe114f086ca6 /lasso/xml | |
| parent | d3c702e130ab654fd47081c1460f2f8527d10bc8 (diff) | |
| parent | f3409ece4dab64da843f118f2739481c1bff2613 (diff) | |
| download | lasso-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.h | 8 | ||||
| -rw-r--r-- | lasso/xml/tools.c | 120 | ||||
| -rw-r--r-- | lasso/xml/xml.c | 143 | ||||
| -rw-r--r-- | lasso/xml/xml.h | 5 |
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 */ |
