diff options
Diffstat (limited to 'worker/xml_helper.c')
-rw-r--r-- | worker/xml_helper.c | 220 |
1 files changed, 220 insertions, 0 deletions
diff --git a/worker/xml_helper.c b/worker/xml_helper.c new file mode 100644 index 0000000..34a1514 --- /dev/null +++ b/worker/xml_helper.c @@ -0,0 +1,220 @@ +#include <string.h> + +#include <libxml/tree.h> +#include <libxml/parser.h> +#include <libxml/xpath.h> +#include <libxml/xpathInternals.h> +#include <libxml/relaxng.h> + +#include <libxslt/xslt.h> +#include <libxslt/xsltInternals.h> +#include <libxslt/transform.h> +#include <libxslt/xsltutils.h> + +#include "util.h" +#include "xml_helper.h" + +/* If a default namespace is defined + * + * IMPORTANT: XPath 1.0 has no concept of a default namespace. Unprefixed + * names in XPath only match names which have no namespace. So, if the + * document uses a default namespace, it is required to associate a non-empty + * prefix with the default namespace via register-namespace and add that + * prefix to names in XPath expressions intended to match nodes in the default + * namespace. + */ +xmlChar *default_namespace_prefix = (xmlChar *) "def"; + +int validate_policy(const char *policy_file_name, xmlChar **default_namespace, char **ipa_policy_type, char **xslt_file_name) { + xmlDocPtr doc; + xmlNodePtr root_node; + char *rng_file_name; + xmlRelaxNGValidCtxtPtr rng_context; + xmlChar xpath_expr[XMLCHARLEN]; + + + doc = xmlParseFile(policy_file_name); + CHECK(doc, NULL, ("Cannot parse document %s!\n", policy_file_name), exit(1)); + + /* find the default namespace */ + root_node = xmlDocGetRootElement(doc); + CHECK(root_node, NULL, + ("Cannot find root node of document %s!\n", policy_file_name), exit(1)); + if (xmlStrncasecmp(root_node->name, (xmlChar *) "IPA", XMLCHARLEN) != 0) { + DEBUG(0, + ("Name of root node of document %s has to be 'ipa'!\n", policy_file_name)); + exit(1); + } + CHECK(root_node->ns->href, NULL, + ("Root node of document %s must define a namespace!\n", policy_file_name), exit(1)); + *default_namespace = xmlStrndup(root_node->ns->href, XMLCHARLEN); + CHECK(*default_namespace, NULL, ("Cannot copy namespace!\n"), exit(1)); + DEBUG(3, ("Default namespace of %s is %s\n", policy_file_name, *default_namespace)); + + + xmlStrPrintf(xpath_expr, XMLCHARLEN, (xmlChar *) "//%s:ipa/*[2]", + default_namespace_prefix); + *ipa_policy_type = find_name_by_xpath(doc, xpath_expr, default_namespace_prefix, *default_namespace); + CHECK(*ipa_policy_type, NULL, ("Type of IPA policy not found.\n"), exit(1)); + DEBUG(3, ("Found IPA policy type: %s\n", *ipa_policy_type)); + if ( strncmp(*ipa_policy_type, "ipaconfig",9) != 0 && + strncmp(*ipa_policy_type, "iparole",7) != 0 && + strncmp(*ipa_policy_type, "ipaaction",9) != 0) { + DEBUG(0,("unknown IPA ploicy type\n")); + exit(1); + } + + xmlStrPrintf(xpath_expr, XMLCHARLEN, (xmlChar *) "//%s:RNGfile", + default_namespace_prefix); + rng_file_name = + find_value_by_xpath(doc, xpath_expr, default_namespace_prefix, + *default_namespace); + CHECK(rng_file_name, NULL, ("Name of RELANX NG schema file not found.\n"), exit(1)); + DEBUG(3, ("Found name of RELAX NG schema file: %s\n", rng_file_name)); + + + + /* validate the document */ + rng_context = + xmlRelaxNGNewValidCtxt(xmlRelaxNGParse + (xmlRelaxNGNewParserCtxt(rng_file_name))); + CHECK(rng_context, NULL, ("Failed to create RNG context\n"), exit(1)); + if (xmlRelaxNGValidateDoc(rng_context, doc) == 0) { + DEBUG(0, ("The document is valid.\n")); + } else { + DEBUG(0, ("Error during validation.\n")); + exit(1); + } + + xmlRelaxNGFreeValidCtxt(rng_context); + free(rng_file_name); + + + if (strncmp(*ipa_policy_type, "ipaaction", 9)!=0) { + xmlStrPrintf(xpath_expr, XMLCHARLEN, (xmlChar *) "//%s:XSLTfile", default_namespace_prefix); + *xslt_file_name = + find_value_by_xpath(doc, xpath_expr, default_namespace_prefix, *default_namespace); + CHECK(*xslt_file_name, NULL, ("Name of XSLT file not found.\n"), exit(1)); + DEBUG(3, ("Found name of XSLT file: %s\n", *xslt_file_name)); + } + + xmlFreeDoc(doc); + + return 0; +} + +int print_all_attributes(xmlNode *node) { + xmlAttr *cur; + + cur=node->properties; + while(cur!=NULL) { + DEBUG(3, ("found attribute '%s' with value '%s'.\n", cur->name, XML_GET_CONTENT(cur->children))); + cur=cur->next; + } + return 0; +} + +char *find_name_by_xpath(xmlDocPtr doc, xmlChar * xpath_expr, xmlChar * prefix, + xmlChar * namespace) +{ + + xmlXPathContextPtr xpath_context; + xmlXPathObjectPtr xpath_obj; + char *result = NULL; + + /* Create xpath evaluation context */ + xpath_context = xmlXPathNewContext(doc); + CHECK_NULL_FATAL(xpath_context, + ("Error: unable to create new XPath context\n")); + /* Register a namespace */ + if (xmlXPathRegisterNs(xpath_context, prefix, namespace) != 0) { + DEBUG(0, + ("Error: unable to register NS with prefix=\"%s\" and href=\"%s\"\n", + prefix , namespace)); + xmlXPathFreeContext(xpath_context); + return NULL; + } + /* Evaluate xpath expression */ + xpath_obj = xmlXPathEvalExpression(xpath_expr, xpath_context); + if (xpath_obj == NULL) { + DEBUG(0, + ("Error: unable to evaluate xpath expression \"%s\"\n", + xpath_expr)); + xmlXPathFreeContext(xpath_context); + return NULL; + } + + if (xmlXPathNodeSetIsEmpty(xpath_obj->nodesetval)) { + DEBUG(0, ("Nothing found for %s\n", xpath_expr)); + xmlXPathFreeObject(xpath_obj); + xmlXPathFreeContext(xpath_context); + return NULL; + } else if (xmlXPathNodeSetGetLength(xpath_obj->nodesetval) != 1) { + DEBUG(0, ("More than one node found for %s!", xpath_expr)); + xmlXPathFreeObject(xpath_obj); + xmlXPathFreeContext(xpath_context); + return NULL; + } else { + result = strdup((char *) xpath_obj->nodesetval->nodeTab[0]->name); + } + + + xmlXPathFreeObject(xpath_obj); + xmlXPathFreeContext(xpath_context); + return result; + +} + +char *find_value_by_xpath(const xmlDocPtr doc, const xmlChar * xpath_expr, const xmlChar * prefix, + const xmlChar * namespace) +{ + + xmlXPathContextPtr xpath_context; + xmlXPathObjectPtr xpath_obj; + char *result = NULL; + + /* Create xpath evaluation context */ + xpath_context = xmlXPathNewContext(doc); + CHECK_NULL_FATAL(xpath_context, + ("Error: unable to create new XPath context\n")); + /* Register a namespace */ + if (xmlXPathRegisterNs(xpath_context, prefix, namespace) != 0) { + DEBUG(0, + ("Error: unable to register NS with prefix=\"%s\" and href=\"%s\"\n", + prefix , namespace)); + xmlXPathFreeContext(xpath_context); + return NULL; + } + /* Evaluate xpath expression */ + xpath_obj = xmlXPathEvalExpression(xpath_expr, xpath_context); + if (xpath_obj == NULL) { + DEBUG(0, + ("Error: unable to evaluate xpath expression \"%s\"\n", + xpath_expr)); + xmlXPathFreeContext(xpath_context); + return NULL; + } + + if (xmlXPathNodeSetIsEmpty(xpath_obj->nodesetval)) { + DEBUG(0, ("Nothing found for %s\n", xpath_expr)); + xmlXPathFreeObject(xpath_obj); + xmlXPathFreeContext(xpath_context); + return NULL; + } else if (xmlXPathNodeSetGetLength(xpath_obj->nodesetval) != 1) { + DEBUG(0, ("More than one node found for %s!", xpath_expr)); + xmlXPathFreeObject(xpath_obj); + xmlXPathFreeContext(xpath_context); + return NULL; + } else { + result = + (char *) xmlNodeListGetString(doc, + xpath_obj->nodesetval->nodeTab[0]-> + xmlChildrenNode, 1); + } + + + xmlXPathFreeObject(xpath_obj); + xmlXPathFreeContext(xpath_context); + return result; + +} |