summaryrefslogtreecommitdiffstats
path: root/worker/xml_helper.c
diff options
context:
space:
mode:
Diffstat (limited to 'worker/xml_helper.c')
-rw-r--r--worker/xml_helper.c220
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;
+
+}