From 3fc428016f81c508a6feec60433816c7903690f8 Mon Sep 17 00:00:00 2001 From: Frederic Peters Date: Sun, 12 Aug 2007 22:19:32 +0000 Subject: [PATCH] added a wrapper around xmlParseMemory to avoid network and DTD --- lasso/id-ff/server.c | 3 +- lasso/id-wsf-2.0/discovery.c | 3 +- lasso/id-wsf/data_service.c | 2 +- lasso/id-wsf/wsf_profile.c | 4 +- lasso/saml-2.0/ecp.c | 4 +- lasso/saml-2.0/login.c | 2 +- lasso/xml/private.h | 2 + lasso/xml/xml.c | 83 +++++++++++++++++++++++++++++++++++- 8 files changed, 91 insertions(+), 12 deletions(-) diff --git a/lasso/id-ff/server.c b/lasso/id-ff/server.c index da8f0ab5..923b6ae1 100644 --- a/lasso/id-ff/server.c +++ b/lasso/id-ff/server.c @@ -165,8 +165,7 @@ lasso_server_get_svc_metadatas_with_id_and_type(LassoServer *server, GList *svcM g_return_val_if_fail(LASSO_IS_SERVER(server), NULL); g_return_val_if_fail(service_type != NULL, NULL); - for (i = g_list_first(server->private_data->svc_metadatas); i != NULL; - i = g_list_next(i)) { + for (i = g_list_first(server->private_data->svc_metadatas); i != NULL; i = g_list_next(i)) { md = LASSO_IDWSF2_DISCO_SVC_METADATA(i->data); /* FIXME: this assumes there is one and only one service * context, and service type, this should be fixed to iterate diff --git a/lasso/id-wsf-2.0/discovery.c b/lasso/id-wsf-2.0/discovery.c index a9b01b44..c35050ad 100644 --- a/lasso/id-wsf-2.0/discovery.c +++ b/lasso/id-wsf-2.0/discovery.c @@ -185,8 +185,7 @@ lasso_idwsf2_discovery_process_metadata_register_msg(LassoIdWsf2Discovery *disco request = LASSO_IDWSF2_DISCO_SVC_MD_REGISTER(LASSO_PROFILE(profile)->request); /* FIXME : foreach on the list instead */ if (request != NULL && request->SvcMD != NULL) { - discovery->metadata = - LASSO_IDWSF2_DISCO_SVC_METADATA(request->SvcMD->data); + discovery->metadata = LASSO_IDWSF2_DISCO_SVC_METADATA(request->SvcMD->data); /* Build a unique SvcMDID */ lasso_build_random_sequence(unique_id, 32); unique_id[32] = 0; diff --git a/lasso/id-wsf/data_service.c b/lasso/id-wsf/data_service.c index af25e27f..8cd166a5 100644 --- a/lasso/id-wsf/data_service.c +++ b/lasso/id-wsf/data_service.c @@ -310,7 +310,7 @@ lasso_data_service_process_query_msg(LassoDataService *service, const char *mess g_return_val_if_fail(message != NULL, LASSO_PARAM_ERROR_INVALID_VALUE); - doc = xmlParseMemory(message, strlen(message)); + doc = lasso_xml_parse_memory(message, strlen(message)); if (doc == NULL) { return critical_error(LASSO_PROFILE_ERROR_INVALID_MSG); } diff --git a/lasso/id-wsf/wsf_profile.c b/lasso/id-wsf/wsf_profile.c index 2991d0c5..0eb67826 100644 --- a/lasso/id-wsf/wsf_profile.c +++ b/lasso/id-wsf/wsf_profile.c @@ -1283,7 +1283,7 @@ lasso_wsf_profile_process_soap_request_msg(LassoWsfProfile *profile, const gchar } } - doc = xmlParseMemory(message, strlen(message)); + doc = lasso_xml_parse_memory(message, strlen(message)); /* Verify authentication mecanisms */ if (lasso_wsf_profile_has_x509_authentication(profile) == TRUE) { @@ -1352,7 +1352,7 @@ lasso_wsf_profile_process_soap_response_msg(LassoWsfProfile *profile, const gcha g_return_val_if_fail(LASSO_IS_WSF_PROFILE(profile), LASSO_PARAM_ERROR_BAD_TYPE_OR_NULL_OBJ); g_return_val_if_fail(message != NULL, LASSO_PARAM_ERROR_INVALID_VALUE); - doc = xmlParseMemory(message, strlen(message)); + doc = lasso_xml_parse_memory(message, strlen(message)); if (lasso_wsf_profile_has_x509_authentication(profile) == TRUE) { xmlNode *xmlnode; diff --git a/lasso/saml-2.0/ecp.c b/lasso/saml-2.0/ecp.c index 8e468f82..1c95426a 100644 --- a/lasso/saml-2.0/ecp.c +++ b/lasso/saml-2.0/ecp.c @@ -130,7 +130,7 @@ lasso_ecp_process_authn_request_msg(LassoEcp *ecp, const char *authn_request_msg profile = LASSO_PROFILE(ecp); - doc = xmlParseMemory(authn_request_msg, strlen(authn_request_msg)); + doc = lasso_xml_parse_memory(authn_request_msg, strlen(authn_request_msg)); xpathCtx = xmlXPathNewContext(doc); xmlXPathRegisterNs(xpathCtx, (xmlChar*)"ecp", (xmlChar*)LASSO_ECP_HREF); @@ -205,7 +205,7 @@ lasso_ecp_process_response_msg(LassoEcp *ecp, const char *response_msg) g_return_val_if_fail(LASSO_IS_ECP(ecp), LASSO_PARAM_ERROR_BAD_TYPE_OR_NULL_OBJ); g_return_val_if_fail(response_msg != NULL, LASSO_PARAM_ERROR_INVALID_VALUE); - doc = xmlParseMemory(response_msg, strlen(response_msg)); + doc = lasso_xml_parse_memory(response_msg, strlen(response_msg)); xpathCtx = xmlXPathNewContext(doc); xmlXPathRegisterNs(xpathCtx, (xmlChar*)"s", (xmlChar*)LASSO_SOAP_ENV_HREF); xpathObj = xmlXPathEvalExpression((xmlChar*)"//s:Body", xpathCtx); diff --git a/lasso/saml-2.0/login.c b/lasso/saml-2.0/login.c index 1e13bc75..c3ffcb79 100644 --- a/lasso/saml-2.0/login.c +++ b/lasso/saml-2.0/login.c @@ -1037,7 +1037,7 @@ lasso_saml20_login_process_paos_response_msg(LassoLogin *login, gchar *msg) return critical_error(LASSO_PROFILE_ERROR_INVALID_MSG); } - doc = xmlParseMemory(msg, strlen(msg)); + doc = lasso_xml_parse_memory(msg, strlen(msg)); xpathCtx = xmlXPathNewContext(doc); /* XXX:BEFORE-LASSO-2.0 */ diff --git a/lasso/xml/private.h b/lasso/xml/private.h index e3477a8a..7b47de44 100644 --- a/lasso/xml/private.h +++ b/lasso/xml/private.h @@ -128,6 +128,8 @@ gboolean lasso_node_init_from_deflated_query_part(LassoNode *node, char *deflate char* lasso_concat_url_query(char *url, char *query); +xmlDocPtr lasso_xml_parse_memory(const char *buffer, int size); + void _debug(GLogLevelFlags level, const char *filename, int line, const char *function, const char *format, ...); diff --git a/lasso/xml/xml.c b/lasso/xml/xml.c index 4cfaa563..f93a148f 100644 --- a/lasso/xml/xml.c +++ b/lasso/xml/xml.c @@ -26,6 +26,8 @@ #include #include +#include +#include #include #include @@ -120,6 +122,83 @@ lasso_get_prefix_for_idwsf2_dst_service_href(const gchar *href) return g_strdup(g_hash_table_lookup(idwsf2_dst_services_by_href, href)); } +/* (almost) straight from libxml2 internal API */ +static void +xmlDetectSAX2(xmlParserCtxtPtr ctxt) { + if (ctxt == NULL) return; +#ifdef LIBXML_SAX1_ENABLED + if ((ctxt->sax) && (ctxt->sax->initialized == XML_SAX2_MAGIC) && + ((ctxt->sax->startElementNs != NULL) || + (ctxt->sax->endElementNs != NULL))) ctxt->sax2 = 1; +#else + ctxt->sax2 = 1; +#endif /* LIBXML_SAX1_ENABLED */ + + ctxt->str_xml = xmlDictLookup(ctxt->dict, BAD_CAST "xml", 3); + ctxt->str_xmlns = xmlDictLookup(ctxt->dict, BAD_CAST "xmlns", 5); + ctxt->str_xml_ns = xmlDictLookup(ctxt->dict, XML_XML_NAMESPACE, 36); + if ((ctxt->str_xml==NULL) || (ctxt->str_xmlns==NULL) || + (ctxt->str_xml_ns == NULL)) { + ctxt->errNo = XML_ERR_NO_MEMORY; + } +} + + +/** + * lasso_xml_parse_memory: + * @buffer: an pointer to a char array + * @size: the size of the array + * + * Parse an XML in-memory block and build a tree; exactly like xmlParseMemory + * safe two exceptions: + * + * + * it won't download anything from the network (XML_PARSE_NONET) + * + * + * it will refuse documents with a DTD (for security reason) + * + * + * + * Return value: the resulting document tree + **/ +xmlDocPtr +lasso_xml_parse_memory(const char *buffer, int size) +{ + xmlDocPtr ret; + xmlParserCtxtPtr ctxt; + + ctxt = xmlCreateMemoryParserCtxt(buffer, size); + if (ctxt == NULL) { + return NULL; + } + xmlDetectSAX2(ctxt); + if (ctxt->errNo == XML_ERR_NO_MEMORY) { + return NULL; + } + ctxt->recovery = 0; + xmlCtxtUseOptions(ctxt, XML_PARSE_NONET); + + xmlParseDocument(ctxt); + + if (ctxt->wellFormed && ctxt->myDoc->intSubset != NULL) { + message(G_LOG_LEVEL_WARNING, "Denied message with DTD content"); + ctxt->wellFormed = 0; + } + + if (ctxt->wellFormed) { + ret = ctxt->myDoc; + } else { + ret = NULL; + xmlFreeDoc(ctxt->myDoc); + ctxt->myDoc = NULL; + } + xmlFreeParserCtxt(ctxt); + + return ret; +} + + /*****************************************************************************/ /* virtual public methods */ /*****************************************************************************/ @@ -1349,7 +1428,7 @@ lasso_node_new_from_dump(const char *dump) if (dump == NULL) return NULL; - doc = xmlParseMemory(dump, strlen(dump)); + doc = lasso_xml_parse_memory(dump, strlen(dump)); if (doc == NULL) return NULL; @@ -1377,7 +1456,7 @@ lasso_node_new_from_soap(const char *soap) xmlNode *xmlnode; LassoNode *node = NULL; - doc = xmlParseMemory(soap, strlen(soap)); + doc = lasso_xml_parse_memory(soap, strlen(soap)); xpathCtx = xmlXPathNewContext(doc); xmlXPathRegisterNs(xpathCtx, (xmlChar*)"s", (xmlChar*)LASSO_SOAP_ENV_HREF); xpathObj = xmlXPathEvalExpression((xmlChar*)"//s:Body/*", xpathCtx);