diff options
author | Frederic Peters <fpeters@entrouvert.com> | 2004-12-10 16:13:34 +0000 |
---|---|---|
committer | Frederic Peters <fpeters@entrouvert.com> | 2004-12-10 16:13:34 +0000 |
commit | d1b99b7bbbc74a0824054c0766c96bb15889654e (patch) | |
tree | 0f265f81e081f401e1ac1f52c62392d968704bfb /lasso | |
parent | fad688adebffaab950dad2acf53617a7a4d5e401 (diff) | |
download | lasso-d1b99b7bbbc74a0824054c0766c96bb15889654e.tar.gz lasso-d1b99b7bbbc74a0824054c0766c96bb15889654e.tar.xz lasso-d1b99b7bbbc74a0824054c0766c96bb15889654e.zip |
Added back xmlsec signature check (and disabled it in name identifier mapping
profile since it is buggy there). The signature check requires another call to
xmlParseMemory; this makes them 3 per SOAP message (sign check +
lasso_profile_get_request_type_from_soap_msg and lasso_node_init_from_message).
I'll think further about this.
Diffstat (limited to 'lasso')
-rw-r--r-- | lasso/id-ff/lecp.c | 2 | ||||
-rw-r--r-- | lasso/id-ff/login.c | 31 | ||||
-rw-r--r-- | lasso/id-ff/name_identifier_mapping.c | 6 | ||||
-rw-r--r-- | lasso/id-ff/provider.c | 141 | ||||
-rw-r--r-- | lasso/xml/xml.c | 149 | ||||
-rw-r--r-- | lasso/xml/xml.h | 3 |
6 files changed, 204 insertions, 128 deletions
diff --git a/lasso/id-ff/lecp.c b/lasso/id-ff/lecp.c index ae6efadb..cf60e277 100644 --- a/lasso/id-ff/lecp.c +++ b/lasso/id-ff/lecp.c @@ -124,7 +124,7 @@ lasso_lecp_build_authn_response_msg(LassoLecp *lecp) message(G_LOG_LEVEL_CRITICAL, "AssertionConsumerServiceURL not found"); return -1; } - profile->msg_body = lasso_node_export_to_base64(profile->response); + profile->msg_body = lasso_node_export_to_base64(profile->response, NULL, NULL); if (profile->msg_body == NULL) { message(G_LOG_LEVEL_CRITICAL, "AuthnResponse Base64 msg not found"); return -1; diff --git a/lasso/id-ff/login.c b/lasso/id-ff/login.c index 8397af10..f3055471 100644 --- a/lasso/id-ff/login.c +++ b/lasso/id-ff/login.c @@ -637,12 +637,12 @@ lasso_login_build_authn_request_msg(LassoLogin *login, const gchar *remote_provi } if (login->http_method == LASSO_HTTP_METHOD_POST) { char *private_key = NULL, *certificate = NULL; - if (! must_sign) { + if (must_sign) { private_key = LASSO_PROFILE(login)->server->private_key; certificate = LASSO_PROFILE(login)->server->certificate; } - /* XXX: lareq may need to be signed */ - lareq = lasso_node_export_to_base64(LASSO_PROFILE(login)->request); + lareq = lasso_node_export_to_base64(LASSO_PROFILE(login)->request, + private_key, certificate); if (lareq == NULL) { message(G_LOG_LEVEL_CRITICAL, @@ -756,7 +756,8 @@ lasso_login_build_authn_response_msg(LassoLogin *login, remote_provider = g_hash_table_lookup(profile->server->providers, profile->remote_providerID); /* build an lib:AuthnResponse base64 encoded */ - LASSO_PROFILE(login)->msg_body = lasso_node_export_to_base64(profile->response); + LASSO_PROFILE(login)->msg_body = lasso_node_export_to_base64(profile->response, + NULL, NULL); LASSO_PROFILE(login)->msg_url = lasso_provider_get_metadata_one( remote_provider, "AssertionConsumerServiceURL"); @@ -819,10 +820,6 @@ lasso_login_build_response_msg(LassoLogin *login, gchar *remote_providerID) LASSO_PROFILE(login)->remote_providerID = g_strdup(remote_providerID); remote_provider = g_hash_table_lookup(LASSO_PROFILE(login)->server->providers, LASSO_PROFILE(login)->remote_providerID); - /* FIXME verify the SOAP request signature */ - ret = lasso_node_verify_signature(LASSO_PROFILE(login)->request, - remote_provider->public_key, - remote_provider->ca_cert_chain); /* changed status code into RequestDenied if signature is invalid or not found if an error occurs during verification */ @@ -892,10 +889,9 @@ lasso_login_init_authn_request(LassoLogin *login, lassoHttpMethod http_method) request->ProviderID = g_strdup(LASSO_PROVIDER(LASSO_PROFILE(login)->server)->ProviderID); if (http_method == LASSO_HTTP_METHOD_POST) { - /* XXX: if post sign_type/sign_method - LASSO_SIGNATURE_TYPE_WITHX509, - LASSO_SIGNATURE_METHOD_RSA_SHA1); - */ + LASSO_SAMLP_REQUEST_ABSTRACT(request)->sign_method = + LASSO_SIGNATURE_METHOD_RSA_SHA1; + LASSO_SAMLP_REQUEST_ABSTRACT(request)->sign_type = LASSO_SIGNATURE_TYPE_WITHX509; } LASSO_PROFILE(login)->request = LASSO_NODE(request); @@ -1192,6 +1188,7 @@ lasso_login_process_authn_response_msg(LassoLogin *login, gchar *authn_response_ { gint ret1 = 0, ret2 = 0; LassoMessageFormat format; + LassoProvider *remote_provider; g_return_val_if_fail(LASSO_IS_LOGIN(login), LASSO_PARAM_ERROR_BAD_TYPE_OR_NULL_OBJ); g_return_val_if_fail(authn_response_msg != NULL, LASSO_PARAM_ERROR_INVALID_VALUE); @@ -1210,9 +1207,19 @@ lasso_login_process_authn_response_msg(LassoLogin *login, gchar *authn_response_ message(G_LOG_LEVEL_CRITICAL, "XXX"); } + remote_provider = g_hash_table_lookup(LASSO_PROFILE(login)->server->providers, + LASSO_PROFILE(login)->remote_providerID); + LASSO_PROFILE(login)->msg_relayState = g_strdup(LASSO_LIB_AUTHN_RESPONSE( LASSO_PROFILE(login)->response)->RelayState); +#if 0 /* XXX: disabled signature check; not sure it must be done here */ + rc = lasso_provider_verify_signature(remote_provider, + authn_response_msg, "ResponseID", format); + if (rc) + return rc; +#endif + ret2 = lasso_login_process_response_status_and_assertion(login); return ret2 == 0 ? ret1 : ret2; diff --git a/lasso/id-ff/name_identifier_mapping.c b/lasso/id-ff/name_identifier_mapping.c index 58027cfb..91497e59 100644 --- a/lasso/id-ff/name_identifier_mapping.c +++ b/lasso/id-ff/name_identifier_mapping.c @@ -230,8 +230,11 @@ lasso_name_identifier_mapping_process_request_msg(LassoNameIdentifierMapping *ma } /* verify signature */ +#if 0 /* FIXME: signature is broken in name identifier mapping profile */ profile->signature_status = lasso_provider_verify_signature( remote_provider, request_msg, "RequestID", format); +#endif + profile->signature_status = 0; profile->http_request_method = LASSO_HTTP_METHOD_SOAP; @@ -272,7 +275,10 @@ lasso_name_identifier_mapping_process_response_msg(LassoNameIdentifierMapping *m } /* verify signature */ +#if 0 /* FIXME: signature is broken in name identifier mapping profile */ rc = lasso_provider_verify_signature(remote_provider, response_msg, "ResponseID", format); +#endif + rc = 0; statusCodeValue = LASSO_LIB_NAME_IDENTIFIER_MAPPING_RESPONSE( profile->response)->Status->StatusCode->Value; diff --git a/lasso/id-ff/provider.c b/lasso/id-ff/provider.c index 01527778..f1276299 100644 --- a/lasso/id-ff/provider.c +++ b/lasso/id-ff/provider.c @@ -26,6 +26,7 @@ #include <libxml/xpath.h> #include <libxml/xpathInternals.h> +#include <xmlsec/base64.h> #include <xmlsec/xmldsig.h> #include <xmlsec/xmltree.h> @@ -504,79 +505,113 @@ lasso_provider_new_from_dump(const gchar *dump) int lasso_provider_verify_signature(LassoProvider *provider, const char *message, const char *id_attr_name, LassoMessageFormat format) { + /* this duplicates some code from lasso_node_init_from_message; + * reflection about code reuse is under way... + */ + char *msg; + xmlDoc *doc; + xmlNode *xmlnode = NULL, *sign, *x509data; + xmlSecKeysMngr *keys_mngr = NULL; + xmlSecDSigCtx *dsigCtx; + lassoPemFileType public_key_file_type; + int rc; + + msg = (char*)message; + if (format == LASSO_MESSAGE_FORMAT_ERROR) return -2; if (format == LASSO_MESSAGE_FORMAT_UNKNOWN) return -2; + if (format == LASSO_MESSAGE_FORMAT_QUERY) { + return lasso_query_verify_signature(message, provider->public_key); + } + if (format == LASSO_MESSAGE_FORMAT_BASE64) { - /* XXX: checking signature in base64 mode (probably going back - * to XML mode)*/ - return 0; + msg = g_malloc(strlen(message)); + rc = xmlSecBase64Decode(message, msg, strlen(message)); + if (rc < 0) { + g_free(msg); + return -3; + } } - if (format == LASSO_MESSAGE_FORMAT_XML || format == LASSO_MESSAGE_FORMAT_SOAP) { - xmlDoc *doc; - xmlNode *xmlnode, *sign, *x509data; - xmlSecKeysMngr *keys_mngr = NULL; - xmlSecDSigCtx *dsigCtx; - lassoPemFileType public_key_file_type; + doc = xmlParseMemory(msg, strlen(msg)); + if (format == LASSO_MESSAGE_FORMAT_BASE64) { + g_free(msg); + msg = NULL; + } - return 0; /* XXX: enable back signature check on xml messages */ + if (format == LASSO_MESSAGE_FORMAT_SOAP) { + xmlXPathContext *xpathCtx = NULL; + xmlXPathObject *xpathObj; - doc = xmlParseMemory(message, strlen(message)); - xmlnode = xmlDocGetRootElement(doc); - sign = xmlSecFindNode(xmlnode, xmlSecNodeSignature, xmlSecDSigNs); - if (sign == NULL) { - xmlFreeDoc(doc); - return LASSO_DS_ERROR_SIGNATURE_NOT_FOUND; + xpathCtx = xmlXPathNewContext(doc); + xmlXPathRegisterNs(xpathCtx, "s", LASSO_SOAP_ENV_HREF); + xpathObj = xmlXPathEvalExpression("//s:Body/*", xpathCtx); + if (xpathObj->nodesetval && xpathObj->nodesetval->nodeNr ) { + xmlnode = xpathObj->nodesetval->nodeTab[0]; } + xmlXPathFreeObject(xpathObj); + xmlXPathFreeContext(xpathCtx); + if (xmlnode == NULL) + return -4; + } else { + xmlnode = xmlDocGetRootElement(doc); + } - x509data = xmlSecFindNode(xmlnode, xmlSecNodeX509Data, xmlSecDSigNs); - if (x509data != NULL && provider->ca_cert_chain != NULL) { - keys_mngr = lasso_load_certs_from_pem_certs_chain_file( - provider->ca_cert_chain); - if (keys_mngr == NULL) - return LASSO_DS_ERROR_CA_CERT_CHAIN_LOAD_FAILED; + if (id_attr_name) { + char *id_value = xmlGetProp(xmlnode, id_attr_name); + xmlAttr *id_attr = xmlHasProp(xmlnode, id_attr_name); + if (id_value) { + xmlAddID(NULL, doc, id_value, id_attr); + xmlFree(id_value); } + } + + sign = xmlSecFindNode(xmlnode, xmlSecNodeSignature, xmlSecDSigNs); + if (sign == NULL) { + xmlFreeDoc(doc); + return LASSO_DS_ERROR_SIGNATURE_NOT_FOUND; + } + + x509data = xmlSecFindNode(xmlnode, xmlSecNodeX509Data, xmlSecDSigNs); + if (x509data != NULL && provider->ca_cert_chain != NULL) { + keys_mngr = lasso_load_certs_from_pem_certs_chain_file( + provider->ca_cert_chain); + if (keys_mngr == NULL) + return LASSO_DS_ERROR_CA_CERT_CHAIN_LOAD_FAILED; + } - dsigCtx = xmlSecDSigCtxCreate(keys_mngr); - if (keys_mngr == NULL) { - if (provider->public_key) { - public_key_file_type = lasso_get_pem_file_type( + dsigCtx = xmlSecDSigCtxCreate(keys_mngr); + if (keys_mngr == NULL) { + if (provider->public_key) { + public_key_file_type = lasso_get_pem_file_type( + provider->public_key); + if (public_key_file_type == LASSO_PEM_FILE_TYPE_CERT) { + /* public_key_file is a certificate file + * => get public key in it */ + dsigCtx->signKey = lasso_get_public_key_from_pem_cert_file( provider->public_key); - if (public_key_file_type == LASSO_PEM_FILE_TYPE_CERT) { - /* public_key_file is a certificate file - * => get public key in it */ - dsigCtx->signKey = lasso_get_public_key_from_pem_cert_file( - provider->public_key); - } else { - /* load public key */ - dsigCtx->signKey = xmlSecCryptoAppKeyLoad( - provider->public_key, - xmlSecKeyDataFormatPem, - NULL, NULL, NULL); - } - } - if (dsigCtx->signKey == NULL) { - return LASSO_DS_ERROR_PUBLIC_KEY_LOAD_FAILED; + } else { + /* load public key */ + dsigCtx->signKey = xmlSecCryptoAppKeyLoad( + provider->public_key, + xmlSecKeyDataFormatPem, + NULL, NULL, NULL); } } - - if (xmlSecDSigCtxVerify(dsigCtx, sign) < 0) { - return LASSO_DS_ERROR_SIGNATURE_VERIFICATION_FAILED; + if (dsigCtx->signKey == NULL) { + return LASSO_DS_ERROR_PUBLIC_KEY_LOAD_FAILED; } - if (dsigCtx->status != xmlSecDSigStatusSucceeded) { - return LASSO_DS_ERROR_INVALID_SIGNATURE; - } - - return 0; } - if (format == LASSO_MESSAGE_FORMAT_QUERY) { - return lasso_query_verify_signature(message, provider->public_key); + if (xmlSecDSigCtxVerify(dsigCtx, sign) < 0) { + return LASSO_DS_ERROR_SIGNATURE_VERIFICATION_FAILED; + } + if (dsigCtx->status != xmlSecDSigStatusSucceeded) { + return LASSO_DS_ERROR_INVALID_SIGNATURE; } - return -1; + return 0; } - diff --git a/lasso/xml/xml.c b/lasso/xml/xml.c index af4cb6b1..a04c3ffa 100644 --- a/lasso/xml/xml.c +++ b/lasso/xml/xml.c @@ -111,22 +111,103 @@ lasso_node_destroy(LassoNode *node) } } +static xmlNode* +lasso_node_export_to_signed_xmlnode(LassoNode *node, + const char *private_key_file, const char *certificate_file) +{ + xmlDoc *doc; + xmlNode *message, *sign_tmpl; + xmlSecDSigCtx *dsig_ctx; + char *id_attr_name = NULL; + + message = lasso_node_get_xmlNode(node); + + sign_tmpl = xmlSecFindNode(message, xmlSecNodeSignature, xmlSecDSigNs); + if (sign_tmpl && private_key_file) { + doc = xmlNewDoc("1.0"); + xmlDocSetRootElement(doc, message); + xmlSetTreeDoc(sign_tmpl, doc); + if (LASSO_NODE_GET_CLASS(node)->get_sign_attr_name) + id_attr_name = LASSO_NODE_GET_CLASS(node)->get_sign_attr_name(); + if (id_attr_name) { + char *id_value = xmlGetProp(message, id_attr_name); + xmlAttr *id_attr = xmlHasProp(message, id_attr_name); + if (id_value) { + xmlAddID(NULL, doc, id_value, id_attr); + xmlFree(id_value); + } + } + + dsig_ctx = xmlSecDSigCtxCreate(NULL); + dsig_ctx->signKey = xmlSecCryptoAppKeyLoad(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), + private_key_file); + xmlSecDSigCtxDestroy(dsig_ctx); + return NULL; + } + if (certificate_file != NULL && certificate_file[0] != 0) { + if (xmlSecCryptoAppKeyCertLoad(dsig_ctx->signKey, certificate_file, + xmlSecKeyDataFormatPem) < 0) { + message(G_LOG_LEVEL_CRITICAL, + lasso_strerror(LASSO_DS_ERROR_CERTIFICATE_LOAD_FAILED), + 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), + message->name); + xmlSecDSigCtxDestroy(dsig_ctx); + return NULL; + } + xmlSecDSigCtxDestroy(dsig_ctx); + xmlUnlinkNode(message); + xmlFreeDoc(doc); + } + + return message; +} + + /** * lasso_node_export_to_base64: * @node: a LassoNode + * @private_key_file: path to private key for signature + * @certificate_file: path to certificate for signature * * Base64 XML dump * * Return value: a Base64 encoded export of the LassoNode **/ char* -lasso_node_export_to_base64(LassoNode *node) +lasso_node_export_to_base64(LassoNode *node, + const char *private_key_file, const char *certificate_file) { - char *buffer, *ret; + xmlNode *message; + xmlOutputBufferPtr buf; + xmlCharEncodingHandlerPtr handler = NULL; + char *buffer; + char *ret; + + message = lasso_node_export_to_signed_xmlnode(node, private_key_file, certificate_file); + + handler = xmlFindCharEncodingHandler("utf-8"); + buf = xmlAllocOutputBuffer(handler); + xmlNodeDumpOutput(buf, NULL, message, 0, 0, "utf-8"); + xmlOutputBufferFlush(buf); + buffer = buf->conv ? buf->conv->content : buf->buffer->content; - buffer = lasso_node_dump(node, "utf-8", 0); ret = xmlSecBase64Encode(buffer, strlen(buffer), 0); - g_free(buffer); + xmlOutputBufferClose(buf); + return ret; } @@ -173,68 +254,14 @@ char* lasso_node_export_to_soap(LassoNode *node, const char *private_key_file, const char *certificate_file) { - xmlDoc *doc; - xmlNode *envelope, *body, *message, *sign_tmpl; + xmlNode *envelope, *body, *message; xmlOutputBuffer *buf; xmlCharEncodingHandler *handler; - xmlSecDSigCtx *dsig_ctx; char *ret; - char *id_attr_name = NULL; g_return_val_if_fail (LASSO_IS_NODE(node), NULL); - message = lasso_node_get_xmlNode(node); - - sign_tmpl = xmlSecFindNode(message, xmlSecNodeSignature, xmlSecDSigNs); - if (sign_tmpl && private_key_file) { - doc = xmlNewDoc("1.0"); - xmlDocSetRootElement(doc, message); - xmlSetTreeDoc(sign_tmpl, doc); - if (LASSO_NODE_GET_CLASS(node)->get_sign_attr_name) - id_attr_name = LASSO_NODE_GET_CLASS(node)->get_sign_attr_name(); - if (id_attr_name) { - char *id_value = xmlGetProp(message, id_attr_name); - xmlAttr *id_attr = xmlHasProp(message, id_attr_name); - if (id_value) { - xmlAddID(NULL, doc, id_value, id_attr); - xmlFree(id_value); - } - } - - dsig_ctx = xmlSecDSigCtxCreate(NULL); - dsig_ctx->signKey = xmlSecCryptoAppKeyLoad(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), - private_key_file); - xmlSecDSigCtxDestroy(dsig_ctx); - return NULL; - } - if (certificate_file != NULL && certificate_file[0] != 0) { - if (xmlSecCryptoAppKeyCertLoad(dsig_ctx->signKey, certificate_file, - xmlSecKeyDataFormatPem) < 0) { - message(G_LOG_LEVEL_CRITICAL, - lasso_strerror(LASSO_DS_ERROR_CERTIFICATE_LOAD_FAILED), - 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), - message->name); - xmlSecDSigCtxDestroy(dsig_ctx); - return NULL; - } - xmlSecDSigCtxDestroy(dsig_ctx); - xmlUnlinkNode(message); - xmlFreeDoc(doc); - } + message = lasso_node_export_to_signed_xmlnode(node, private_key_file, certificate_file); envelope = xmlNewNode(NULL, "Envelope"); xmlSetNs(envelope, xmlNewNs(envelope, LASSO_SOAP_ENV_HREF, LASSO_SOAP_ENV_PREFIX)); @@ -244,7 +271,7 @@ lasso_node_export_to_soap(LassoNode *node, handler = xmlFindCharEncodingHandler("utf-8"); buf = xmlAllocOutputBuffer(handler); - xmlNodeDumpOutput(buf, NULL, envelope, 0, 1, "utf-8"); + xmlNodeDumpOutput(buf, NULL, envelope, 0, 0, "utf-8"); xmlOutputBufferFlush(buf); ret = g_strdup( buf->conv ? buf->conv->content : buf->buffer->content ); xmlOutputBufferClose(buf); diff --git a/lasso/xml/xml.h b/lasso/xml/xml.h index 1c2f36f7..7dedb894 100644 --- a/lasso/xml/xml.h +++ b/lasso/xml/xml.h @@ -99,7 +99,8 @@ LASSO_EXPORT LassoNode* lasso_node_new_from_xmlNode(xmlNode* node); LASSO_EXPORT void lasso_node_destroy(LassoNode *node); LASSO_EXPORT char* lasso_node_dump(LassoNode *node, const char *encoding, int format); LASSO_EXPORT char* lasso_node_build_query(LassoNode *node); -LASSO_EXPORT char* lasso_node_export_to_base64(LassoNode *node); +LASSO_EXPORT char* lasso_node_export_to_base64(LassoNode *node, + const char *private_key_file, const char *certificate_file); LASSO_EXPORT char* lasso_node_export_to_query(LassoNode *node, lassoSignatureMethod sign_method, const char *private_key_file); |