From 95afff30e76e9a0cf32651f726ea932b678c7410 Mon Sep 17 00:00:00 2001 From: Frederic Peters Date: Sun, 19 Dec 2004 20:34:22 +0000 Subject: Added differentiation between creating xmlnode for lasso use (the _dump functions) and creating xmlnode for the wire (export_to_soap...). This was necessary to keep track of private_key_file to use on an Assertion while it was kept in a lasso session dump and restored later. This means the get_xmlNode functions have now a second parameter, gboolean lasso_dump, TRUE when dumping for lasso internal use. On the bright side assertions are now signed (that signature is not yet checked). --- lasso/xml/dst_modify.c | 4 +- lasso/xml/dst_modify_response.c | 4 +- lasso/xml/dst_query.c | 4 +- lasso/xml/dst_query_response.c | 4 +- lasso/xml/internals.h | 3 +- lasso/xml/saml_assertion.c | 99 ++++++++++++++++++++++++++++++++--------- lasso/xml/saml_assertion.h | 11 ++--- lasso/xml/samlp_response.c | 4 +- lasso/xml/xml.c | 37 +++++++++------ lasso/xml/xml.h | 4 +- 10 files changed, 122 insertions(+), 52 deletions(-) (limited to 'lasso/xml') diff --git a/lasso/xml/dst_modify.c b/lasso/xml/dst_modify.c index 545504f6..6681198c 100644 --- a/lasso/xml/dst_modify.c +++ b/lasso/xml/dst_modify.c @@ -93,12 +93,12 @@ insure_namespace(xmlNode *xmlnode, xmlNs *ns) } static xmlNode* -get_xmlNode(LassoNode *node) +get_xmlNode(LassoNode *node, gboolean lasso_dump) { xmlNode *xmlnode; xmlNs *ns; - xmlnode = parent_class->get_xmlNode(node); + xmlnode = parent_class->get_xmlNode(node, lasso_dump); ns = xmlNewNs(xmlnode, LASSO_DST_MODIFY(node)->hrefServiceType, LASSO_DST_MODIFY(node)->prefixServiceType); xmlSetNs(xmlnode, ns); diff --git a/lasso/xml/dst_modify_response.c b/lasso/xml/dst_modify_response.c index 6619dd72..559251e1 100644 --- a/lasso/xml/dst_modify_response.c +++ b/lasso/xml/dst_modify_response.c @@ -74,12 +74,12 @@ insure_namespace(xmlNode *xmlnode, xmlNs *ns) } static xmlNode* -get_xmlNode(LassoNode *node) +get_xmlNode(LassoNode *node, gboolean lasso_dump) { xmlNode *xmlnode; xmlNs *ns; - xmlnode = parent_class->get_xmlNode(node); + xmlnode = parent_class->get_xmlNode(node, lasso_dump); ns = xmlNewNs(xmlnode, LASSO_DST_MODIFY_RESPONSE(node)->hrefServiceType, LASSO_DST_MODIFY_RESPONSE(node)->prefixServiceType); xmlSetNs(xmlnode, ns); diff --git a/lasso/xml/dst_query.c b/lasso/xml/dst_query.c index b71fd401..2b1ba141 100644 --- a/lasso/xml/dst_query.c +++ b/lasso/xml/dst_query.c @@ -83,12 +83,12 @@ insure_namespace(xmlNode *xmlnode, xmlNs *ns) } static xmlNode* -get_xmlNode(LassoNode *node) +get_xmlNode(LassoNode *node, gboolean lasso_dump) { xmlNode *xmlnode; xmlNs *ns; - xmlnode = parent_class->get_xmlNode(node); + xmlnode = parent_class->get_xmlNode(node, lasso_dump); ns = xmlNewNs(xmlnode, LASSO_DST_QUERY(node)->hrefServiceType, LASSO_DST_QUERY(node)->prefixServiceType); xmlSetNs(xmlnode, ns); diff --git a/lasso/xml/dst_query_response.c b/lasso/xml/dst_query_response.c index 280941bb..12e74295 100644 --- a/lasso/xml/dst_query_response.c +++ b/lasso/xml/dst_query_response.c @@ -87,12 +87,12 @@ insure_namespace(xmlNode *xmlnode, xmlNs *ns) } static xmlNode* -get_xmlNode(LassoNode *node) +get_xmlNode(LassoNode *node, gboolean lasso_dump) { xmlNode *xmlnode; xmlNs *ns; - xmlnode = parent_class->get_xmlNode(node); + xmlnode = parent_class->get_xmlNode(node, lasso_dump); ns = xmlNewNs(xmlnode, LASSO_DST_QUERY_RESPONSE(node)->hrefServiceType, LASSO_DST_QUERY_RESPONSE(node)->prefixServiceType); xmlSetNs(xmlnode, ns); diff --git a/lasso/xml/internals.h b/lasso/xml/internals.h index 9e16bb19..a5239ba3 100644 --- a/lasso/xml/internals.h +++ b/lasso/xml/internals.h @@ -45,7 +45,8 @@ typedef enum { /* transformers for content transformation */ SNIPPET_STRING = 1 << 0, /* default, can be omitted */ SNIPPET_BOOLEAN = 1 << 20, - SNIPPET_INTEGER = 1 << 21 + SNIPPET_INTEGER = 1 << 21, + SNIPPET_LASSO_DUMP = 1 << 22, } SnippetType; struct XmlSnippet { diff --git a/lasso/xml/saml_assertion.c b/lasso/xml/saml_assertion.c index 2ad0a7d1..161a55f0 100644 --- a/lasso/xml/saml_assertion.c +++ b/lasso/xml/saml_assertion.c @@ -23,6 +23,10 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ +#include +#include +#include + #include /* @@ -68,6 +72,8 @@ static struct XmlSnippet schema_snippets[] = { G_STRUCT_OFFSET(LassoSamlAssertion, AuthenticationStatement) }, { "AttributeStatement", SNIPPET_NODE, G_STRUCT_OFFSET(LassoSamlAssertion, AttributeStatement) }, + { "Signature", SNIPPET_SIGNATURE, + G_STRUCT_OFFSET(LassoSamlAssertion, AssertionID) }, { "MajorVersion", SNIPPET_ATTRIBUTE | SNIPPET_INTEGER, G_STRUCT_OFFSET(LassoSamlAssertion, MajorVersion) }, { "MinorVersion", SNIPPET_ATTRIBUTE | SNIPPET_INTEGER, @@ -75,6 +81,17 @@ static struct XmlSnippet schema_snippets[] = { { "AssertionID", SNIPPET_ATTRIBUTE, G_STRUCT_OFFSET(LassoSamlAssertion, AssertionID) }, { "Issuer", SNIPPET_ATTRIBUTE, G_STRUCT_OFFSET(LassoSamlAssertion, Issuer) }, { "IssueInstant", SNIPPET_ATTRIBUTE, G_STRUCT_OFFSET(LassoSamlAssertion, IssueInstant) }, + + /* hidden fields; use in lasso dumps */ + { "SignType", SNIPPET_ATTRIBUTE | SNIPPET_INTEGER | SNIPPET_LASSO_DUMP, + G_STRUCT_OFFSET(LassoSamlAssertion, sign_type) }, + { "SignMethod", SNIPPET_ATTRIBUTE | SNIPPET_INTEGER | SNIPPET_LASSO_DUMP, + G_STRUCT_OFFSET(LassoSamlAssertion, sign_method) }, + { "PrivateKeyFile", SNIPPET_CONTENT | SNIPPET_LASSO_DUMP, + G_STRUCT_OFFSET(LassoSamlAssertion, private_key_file) }, + { "CertificateFile", SNIPPET_CONTENT | SNIPPET_LASSO_DUMP, + G_STRUCT_OFFSET(LassoSamlAssertion, certificate_file) }, + { NULL, 0, 0} }; @@ -114,39 +131,77 @@ insure_namespace(xmlNode *xmlnode, xmlNs *ns) static xmlNode* -get_xmlNode(LassoNode *node) +get_xmlNode(LassoNode *node, gboolean lasso_dump) { + LassoSamlAssertion *assertion = LASSO_SAML_ASSERTION(node); xmlNode *xmlnode; xmlNs *ns; - xmlnode = parent_class->get_xmlNode(node); + xmlnode = parent_class->get_xmlNode(node, lasso_dump); ns = xmlSearchNs(NULL, xmlnode, "saml"); insure_namespace(xmlnode, ns); - return xmlnode; -} + if (lasso_dump == FALSE && assertion->sign_type) { + /* sign assertion now */ + /* code could be refactored with lasso_node_export_to_signed_xmlnode */ + xmlDoc *doc; + xmlNode *sign_tmpl; + xmlSecDSigCtx *dsig_ctx; + char *id_value; + xmlAttr *id_attr; -gint -lasso_saml_assertion_set_signature(LassoSamlAssertion *node, - gint sign_method, - const xmlChar *private_key_file, - const xmlChar *certificate_file) -{ - return 0; -#if 0 /* XXX: signatures are done differently */ - gint ret; - LassoNodeClass *class; + sign_tmpl = xmlSecFindNode(xmlnode, xmlSecNodeSignature, xmlSecDSigNs); + if (sign_tmpl == NULL) + return xmlnode; - g_return_val_if_fail(LASSO_IS_SAML_ASSERTION(node), - LASSO_PARAM_ERROR_BAD_TYPE_OR_NULL_OBJ); + doc = xmlNewDoc("1.0"); + xmlDocSetRootElement(doc, xmlnode); + xmlSetTreeDoc(sign_tmpl, doc); - class = LASSO_NODE_GET_CLASS(node); + id_value = xmlGetProp(xmlnode, "AssertionID"); + id_attr = xmlHasProp(xmlnode, "AssertionID"); + if (id_value) { + xmlAddID(NULL, doc, id_value, id_attr); + xmlFree(id_value); + } - ret = class->add_signature(LASSO_NODE (node), sign_method, - private_key_file, certificate_file); + dsig_ctx = xmlSecDSigCtxCreate(NULL); + dsig_ctx->signKey = xmlSecCryptoAppKeyLoad(assertion->private_key_file, + xmlSecKeyDataFormatPem, + NULL, NULL, NULL); + if (dsig_ctx->signKey == NULL) { + /* XXX: file existence should actually be tested on + * LassoServer creation */ + message(G_LOG_LEVEL_CRITICAL, + lasso_strerror(LASSO_DS_ERROR_PRIVATE_KEY_LOAD_FAILED), + assertion->private_key_file); + xmlSecDSigCtxDestroy(dsig_ctx); + return NULL; + } + if (assertion->certificate_file != NULL && assertion->certificate_file[0] != 0) { + if (xmlSecCryptoAppKeyCertLoad(dsig_ctx->signKey, + assertion->certificate_file, + xmlSecKeyDataFormatPem) < 0) { + message(G_LOG_LEVEL_CRITICAL, + lasso_strerror(LASSO_DS_ERROR_CERTIFICATE_LOAD_FAILED), + assertion->certificate_file); + xmlSecDSigCtxDestroy(dsig_ctx); + return NULL; + } + } + if (xmlSecDSigCtxSign(dsig_ctx, sign_tmpl) < 0) { + message(G_LOG_LEVEL_CRITICAL, + lasso_strerror(LASSO_DS_ERROR_SIGNATURE_FAILED), + xmlnode->name); + xmlSecDSigCtxDestroy(dsig_ctx); + return NULL; + } + xmlSecDSigCtxDestroy(dsig_ctx); + xmlUnlinkNode(xmlnode); + xmlFreeDoc(doc); + } - return ret; -#endif + return xmlnode; } /*****************************************************************************/ @@ -169,6 +224,8 @@ class_init(LassoSamlAssertionClass *klass) lasso_node_class_set_nodename(nclass, "Assertion"); lasso_node_class_set_ns(nclass, LASSO_SAML_ASSERTION_HREF, LASSO_SAML_ASSERTION_PREFIX); lasso_node_class_add_snippets(nclass, schema_snippets); + nclass->node_data->sign_type_offset = G_STRUCT_OFFSET(LassoSamlAssertion, sign_type); + nclass->node_data->sign_method_offset = G_STRUCT_OFFSET(LassoSamlAssertion, sign_method); } GType diff --git a/lasso/xml/saml_assertion.h b/lasso/xml/saml_assertion.h index 9b6560cc..1a556af7 100644 --- a/lasso/xml/saml_assertion.h +++ b/lasso/xml/saml_assertion.h @@ -75,6 +75,12 @@ struct _LassoSamlAssertion { char *AssertionID; char *Issuer; char *IssueInstant; + + /* ds:Signature stuff */ + lassoSignatureType sign_type; + lassoSignatureMethod sign_method; + char *private_key_file; + char *certificate_file; }; struct _LassoSamlAssertionClass { @@ -84,11 +90,6 @@ struct _LassoSamlAssertionClass { LASSO_EXPORT GType lasso_saml_assertion_get_type(void); LASSO_EXPORT LassoNode* lasso_saml_assertion_new(void); -LASSO_EXPORT gint lasso_saml_assertion_set_signature(LassoSamlAssertion *node, - gint sign_method, - const xmlChar *private_key_file, - const xmlChar *certificate_file); - #ifdef __cplusplus } #endif /* __cplusplus */ diff --git a/lasso/xml/samlp_response.c b/lasso/xml/samlp_response.c index 27371848..5638538c 100644 --- a/lasso/xml/samlp_response.c +++ b/lasso/xml/samlp_response.c @@ -55,11 +55,11 @@ static struct XmlSnippet schema_snippets[] = { static LassoNodeClass *parent_class = NULL; static xmlNode* -get_xmlNode(LassoNode *node) +get_xmlNode(LassoNode *node, gboolean lasso_dump) { xmlNode *xmlnode, *t; - xmlnode = parent_class->get_xmlNode(node); + xmlnode = parent_class->get_xmlNode(node, lasso_dump); for (t = xmlnode->children; t && strcmp(t->name, "Assertion"); t = t->next) ; diff --git a/lasso/xml/xml.c b/lasso/xml/xml.c index e89ddae1..c93e703b 100644 --- a/lasso/xml/xml.c +++ b/lasso/xml/xml.c @@ -39,8 +39,8 @@ -static void lasso_node_build_xmlNode_from_snippets( - LassoNode *node, xmlNode *xmlnode, struct XmlSnippet *snippets); +static void lasso_node_build_xmlNode_from_snippets(LassoNode *node, xmlNode *xmlnode, + struct XmlSnippet *snippets, gboolean lasso_dump); static struct XmlSnippet* find_xml_snippet_by_name(LassoNode *node, char *name); static int set_value_at_path(LassoNode *node, char *path, char *query_value); static char* get_value_by_path(LassoNode *node, char *path); @@ -84,7 +84,7 @@ lasso_node_dump(LassoNode *node, const char *encoding, int format) if (buf == NULL) { return NULL; } - xmlnode = lasso_node_get_xmlNode(node); + xmlnode = lasso_node_get_xmlNode(node, TRUE); xmlNodeDumpOutput(buf, NULL, xmlnode, 0, format, encoding); xmlOutputBufferFlush(buf); if (buf->conv != NULL) { @@ -129,7 +129,7 @@ lasso_node_export_to_signed_xmlnode(LassoNode *node, xmlSecDSigCtx *dsig_ctx; char *id_attr_name = NULL; - message = lasso_node_get_xmlNode(node); + message = lasso_node_get_xmlNode(node, FALSE); sign_tmpl = xmlSecFindNode(message, xmlSecNodeSignature, xmlSecDSigNs); if (sign_tmpl && private_key_file) { @@ -471,12 +471,12 @@ lasso_node_build_query(LassoNode *node) } xmlNodePtr -lasso_node_get_xmlNode(LassoNode *node) +lasso_node_get_xmlNode(LassoNode *node, gboolean lasso_dump) { LassoNodeClass *class; g_return_val_if_fail (LASSO_IS_NODE(node), NULL); class = LASSO_NODE_GET_CLASS(node); - return class->get_xmlNode(node); + return class->get_xmlNode(node, lasso_dump); } /*****************************************************************************/ @@ -602,7 +602,7 @@ lasso_node_impl_build_query(LassoNode *node) } static xmlNode* -lasso_node_impl_get_xmlNode(LassoNode *node) +lasso_node_impl_get_xmlNode(LassoNode *node, gboolean lasso_dump) { LassoNodeClass *class = LASSO_NODE_GET_CLASS(node); xmlNode *xmlnode; @@ -623,7 +623,8 @@ lasso_node_impl_get_xmlNode(LassoNode *node) t = g_list_last(list_classes); while (t) { class = t->data; - lasso_node_build_xmlNode_from_snippets(node, xmlnode, class->node_data->snippets); + lasso_node_build_xmlNode_from_snippets(node, xmlnode, + class->node_data->snippets, lasso_dump); t = g_list_previous(t); } @@ -1033,7 +1034,7 @@ lasso_node_class_set_ns(LassoNodeClass *klass, char *href, char *prefix) static void lasso_node_build_xmlNode_from_snippets(LassoNode *node, xmlNode *xmlnode, - struct XmlSnippet *snippets) + struct XmlSnippet *snippets, gboolean lasso_dump) { struct XmlSnippet *snippet; SnippetType type; @@ -1046,6 +1047,9 @@ lasso_node_build_xmlNode_from_snippets(LassoNode *node, xmlNode *xmlnode, char *str = value; type = snippet->type & 0xff; + if (lasso_dump == FALSE && snippet->type & SNIPPET_LASSO_DUMP) + continue; + if (value == NULL && ! (snippet->type & SNIPPET_BOOLEAN || snippet->type & SNIPPET_INTEGER) ) continue; @@ -1064,7 +1068,8 @@ lasso_node_build_xmlNode_from_snippets(LassoNode *node, xmlNode *xmlnode, xmlAddChild(xmlnode, xmlNewText(str)); break; case SNIPPET_NODE: - xmlAddChild(xmlnode, lasso_node_get_xmlNode(LASSO_NODE(value))); + xmlAddChild(xmlnode, lasso_node_get_xmlNode( + LASSO_NODE(value), lasso_dump)); break; case SNIPPET_CONTENT: xmlNewTextChild(xmlnode, NULL, snippet->name, str); @@ -1073,19 +1078,21 @@ lasso_node_build_xmlNode_from_snippets(LassoNode *node, xmlNode *xmlnode, xmlns = xmlNewNs(NULL, LASSO_LIB_HREF, LASSO_LIB_PREFIX); t = xmlAddChild(xmlnode, lasso_node_get_xmlNode( - LASSO_NODE(value))); + LASSO_NODE(value), lasso_dump)); xmlNodeSetName(t, snippet->name); xmlSetNs(t, xmlns); break; case SNIPPET_NODE_IN_CHILD: t = xmlNewTextChild(xmlnode, NULL, snippet->name, NULL); - xmlAddChild(t, lasso_node_get_xmlNode(LASSO_NODE(value))); + xmlAddChild(t, lasso_node_get_xmlNode( + LASSO_NODE(value), lasso_dump)); break; case SNIPPET_LIST_NODES: elem = (GList *)value; while (elem) { xmlAddChild(xmlnode, lasso_node_get_xmlNode( - LASSO_NODE(elem->data))); + LASSO_NODE(elem->data), + lasso_dump)); elem = g_list_next(elem); } break; @@ -1115,6 +1122,9 @@ lasso_node_build_xmlNode_from_snippets(LassoNode *node, xmlNode *xmlnode, char *uri; char *id; + if (lasso_dump) + break; /* no signature in lasso dumps */ + while (klass && LASSO_IS_NODE_CLASS(klass) && klass->node_data) { if (klass->node_data->sign_type_offset) break; @@ -1168,6 +1178,7 @@ lasso_node_build_xmlNode_from_snippets(LassoNode *node, xmlNode *xmlnode, } break; case SNIPPET_INTEGER: case SNIPPET_BOOLEAN: + case SNIPPET_LASSO_DUMP: g_assert_not_reached(); } if (snippet->type & SNIPPET_INTEGER) diff --git a/lasso/xml/xml.h b/lasso/xml/xml.h index e3f341a7..1da85f0b 100644 --- a/lasso/xml/xml.h +++ b/lasso/xml/xml.h @@ -89,7 +89,7 @@ struct _LassoNodeClass { char* (* build_query) (LassoNode *node); gboolean (* init_from_query) (LassoNode *node, char **query_fields); int (* init_from_xml) (LassoNode *node, xmlNode *xmlnode); - xmlNode* (* get_xmlNode) (LassoNode *node); + xmlNode* (* get_xmlNode) (LassoNode *node, gboolean lasso_dump); char* (* get_sign_attr_name) (); }; @@ -113,7 +113,7 @@ LASSO_EXPORT char* lasso_node_export_to_query(LassoNode *node, LASSO_EXPORT char* lasso_node_export_to_soap(LassoNode *node, const char *private_key_file, const char *certificate_file); -LASSO_EXPORT xmlNode* lasso_node_get_xmlNode(LassoNode *node); +LASSO_EXPORT xmlNode* lasso_node_get_xmlNode(LassoNode *node, gboolean lasso_dump); LASSO_EXPORT LassoMessageFormat lasso_node_init_from_message(LassoNode *node, const char *message); LASSO_EXPORT gboolean lasso_node_init_from_query(LassoNode *node, const char *query); -- cgit