summaryrefslogtreecommitdiffstats
path: root/worker/output_handler.c
diff options
context:
space:
mode:
Diffstat (limited to 'worker/output_handler.c')
-rw-r--r--worker/output_handler.c261
1 files changed, 261 insertions, 0 deletions
diff --git a/worker/output_handler.c b/worker/output_handler.c
new file mode 100644
index 0000000..728f53b
--- /dev/null
+++ b/worker/output_handler.c
@@ -0,0 +1,261 @@
+#include <string.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <errno.h>
+#include <libgen.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"
+#include "helpers.h"
+
+char *get_output_handler_parameter(xmlNode *node, const char *name, const char *default_value, const int required) {
+ char *value;
+
+ DEBUG(3,("Search for attribute '%s'.\n",name));
+ value = (char *) xmlGetProp(node, (xmlChar *) name);
+ if (required == 1) {
+ CHECK_NULL_FATAL(value, ("Cannot find required attribute '%s' for output handler.\n", name));
+ DEBUG(3,("Found required attribute '%s' with value '%s'.\n",name, value));
+ } else if (required == 0 ) {
+ if (value == NULL) {
+ DEBUG(3,("Optional attribute '%s' not found, using default '%s'.\n",name, default_value));
+ if (default_value != NULL ) value=strdup(default_value);
+ } else {
+ DEBUG(3,("Found optional attribute '%s' with value '%s'.\n",name, value));
+ }
+ } else {
+ DEBUG(0,("I am not allowed to be here, aborting ...\n"));
+ exit(-1);
+ }
+
+ return value;
+}
+
+int output_handler_file(xmlNode *node, const xmlDocPtr doc, const char *xslt_file_name) {
+ char *name;
+ char *owner;
+ char *group;
+ char *permission;
+ char *param_name;
+ char *param_value;
+ struct stat stat_buffer;
+ char *dir_name;
+ char *tmp_file_name;
+ char *buffer;
+ int ret;
+ int fd;
+ xsltStylesheetPtr parsed_stylesheet = NULL;
+ xmlDocPtr res;
+
+ name=get_output_handler_parameter(node, "name", NULL, 1);
+
+ buffer=strdup(name);
+ CHECK_NULL_RETURN(buffer ,("strdup failed\n"));
+ dir_name=dirname(buffer);
+ if( (ret=stat(dir_name, &stat_buffer)) == -1) {
+ DEBUG(0,("stat on %s failed: %s\n",dir_name, strerror(errno)));
+ free(name);
+ return -1;
+ }
+ if(!S_ISDIR(stat_buffer.st_mode)) {
+ DEBUG(0,("%s is not a directory!\n",dir_name));
+ free(name);
+ return -1;
+ }
+ free(buffer);
+
+ if( (ret=lstat(name, &stat_buffer)) == -1) {
+ DEBUG(0,("stat on %s failed: %s\n",name, strerror(errno)));
+ free(name);
+ return -1;
+ }
+ if(!S_ISREG(stat_buffer.st_mode)) {
+ DEBUG(0,("%s is not a regular file!\n",name));
+ free(name);
+ return -1;
+ }
+
+ owner=get_output_handler_parameter(node, "owner", "root", 0);
+ group=get_output_handler_parameter(node, "group", "root", 0);
+
+ permission=get_output_handler_parameter(node, "permission", "0400", 0);
+ param_name=get_output_handler_parameter(node, "param_name", NULL, 0);
+ param_value=get_output_handler_parameter(node, "param_value", NULL, 0);
+
+ /* TODO: create backup copy */
+
+ tmp_file_name=(char *) malloc(strlen(name)+7);
+ CHECK_NULL_RETURN(tmp_file_name,("malloc failed."));
+ strcpy(tmp_file_name, name);
+ strcat(tmp_file_name, ".XXXXXX");
+ open_temporary_file(tmp_file_name, permission, owner, group, NULL);
+
+ parsed_stylesheet = xsltParseStylesheetFile((xmlChar *) xslt_file_name);
+ CHECK_NULL_FATAL(parsed_stylesheet, ("Cannot parse stylesheet!\n"));
+
+ res = xsltApplyStylesheet(parsed_stylesheet, doc, NULL);
+ CHECK_NULL_FATAL(res, ("Cannot apply stylesheet!\n"));
+ ret = xsltSaveResultToFd(fd, res, parsed_stylesheet);
+ if (ret == -1) {
+ DEBUG(0, ("Cannot save result!\n"));
+ exit(1);
+ }
+ xmlFreeDoc(res);
+ xsltFreeStylesheet(parsed_stylesheet);
+
+ close(fd);
+ ret=rename(tmp_file_name, name);
+ CHECK_MINUS_ONE_RETURN(ret, ("Cannot rename %s to %s: %s\n", tmp_file_name, name, strerror(errno) ));
+
+ free(tmp_file_name);
+
+ free(name);
+ free(owner);
+ free(group);
+ free(permission);
+ free(param_name);
+ free(param_value);
+ return 0;
+}
+
+int output_handler_exec_with_args(xmlNode *node, const xmlDocPtr doc, const char *xslt_file_name) {
+ char *command;
+ char *arguments;
+ char *user;
+ char *group;
+ char *param_name;
+ char *param_value;
+ int ret;
+ struct stat stat_buffer;
+ xsltStylesheetPtr parsed_stylesheet = NULL;
+ xmlDocPtr res;
+ xmlChar *result_string;
+ int result_length;
+ char *cur;
+ char *end_of_line;
+
+ command=get_output_handler_parameter(node, "command", NULL, 1);
+
+ if( (ret=stat(command, &stat_buffer)) == -1) {
+ DEBUG(0,("stat on %s failed: %s\n",command, strerror(errno)));
+ free(command);
+ return -1;
+ }
+
+
+ arguments=get_output_handler_parameter(node, "arguments", NULL, 0);
+
+ user=get_output_handler_parameter(node, "user", "nobody", 0);
+ group=get_output_handler_parameter(node, "group", "nobody", 0);
+
+ param_name=get_output_handler_parameter(node, "param_name", NULL, 0);
+ param_value=get_output_handler_parameter(node, "param_value", NULL, 0);
+
+ parsed_stylesheet = xsltParseStylesheetFile((xmlChar *) xslt_file_name);
+ CHECK_NULL_FATAL(parsed_stylesheet, ("Cannot parse stylesheet!\n"));
+
+ res = xsltApplyStylesheet(parsed_stylesheet, doc, NULL);
+ CHECK_NULL_FATAL(res, ("Cannot apply stylesheet!\n"));
+ ret = xsltSaveResultToString(&result_string, &result_length, res, parsed_stylesheet);
+ if (ret == -1) {
+ DEBUG(0, ("Cannot save result!\n"));
+ exit(1);
+ }
+ xmlFreeDoc(res);
+ xsltFreeStylesheet(parsed_stylesheet);
+
+ cur=(char *)result_string;
+ while ( (end_of_line = strchr(cur, '\n'))!=NULL ) {
+ *end_of_line='\0';
+ DEBUG(3,("found argument to %s: |%s|\n",command, cur));
+ ret=exec_command(command, user, group, arguments, cur);
+ DEBUG(3,("exec_command retrun value: %d\n",ret));
+ cur=end_of_line+1;
+ };
+
+ free(result_string);
+
+ free(command);
+ free(arguments);
+ free(user);
+ free(group);
+ free(param_name);
+ free(param_value);
+ return 0;
+}
+
+int find_output_handler(const char *policy_file_name, const char *xslt_file_name) {
+ int i;
+ xmlXPathContextPtr xpath_context;
+ xmlXPathObjectPtr xpath_obj;
+ xmlDocPtr xslt_doc;
+ xmlDocPtr doc;
+
+ doc = xmlParseFile(policy_file_name);
+ CHECK(doc, NULL, ("Cannot parse file %s!\n", policy_file_name), exit(1));
+
+ xslt_doc = xmlParseFile(xslt_file_name);
+ CHECK(xslt_doc, NULL, ("Cannot parse file %s!\n", xslt_file_name), exit(1));
+
+ xpath_context = xmlXPathNewContext(xslt_doc);
+ CHECK(xpath_context, NULL, ("Error: unable to create new XPath context\n"), exit(1));
+
+ if (xmlXPathRegisterNs(xpath_context, XSLT_METADATA_NAMESPACE_PREFIX, XSLT_METADATA_NAMESPACE) != 0) {
+ DEBUG(0,
+ ("Error: unable to register NS with prefix=\"%s\" and href=\"%s\"\n",
+ XSLT_METADATA_NAMESPACE_PREFIX, XSLT_METADATA_NAMESPACE));
+ xmlXPathFreeContext(xpath_context);
+ return 0;
+ }
+
+ xpath_obj = xmlXPathEvalExpression(XPATH_OUTPUT_HANDLER, xpath_context);
+ if (xpath_obj == NULL) {
+ DEBUG(0,
+ ("Error: unable to evaluate xpath expression \"%s\"\n",
+ XPATH_OUTPUT_HANDLER));
+ xmlXPathFreeContext(xpath_context);
+ return 0;
+ }
+
+ if (xmlXPathNodeSetIsEmpty(xpath_obj->nodesetval)) {
+ DEBUG(0, ("Nothing found for %s\n", XPATH_OUTPUT_HANDLER));
+ xmlXPathFreeObject(xpath_obj);
+ xmlXPathFreeContext(xpath_context);
+ return 0;
+ }
+
+ for (i=0; i<xmlXPathNodeSetGetLength(xpath_obj->nodesetval); i++) {
+ DEBUG(3, ("found output_handler: %s\n",(char *) xpath_obj->nodesetval->nodeTab[i]->name));
+ print_all_attributes(xpath_obj->nodesetval->nodeTab[i]);
+ if ( xmlStrEqual(xpath_obj->nodesetval->nodeTab[i]->name, (xmlChar *) "file" )) {
+ output_handler_file(xpath_obj->nodesetval->nodeTab[i], doc, xslt_file_name);
+ } else if ( xmlStrEqual(xpath_obj->nodesetval->nodeTab[i]->name, (xmlChar *) "exec_with_args" )) {
+ output_handler_exec_with_args(xpath_obj->nodesetval->nodeTab[i], doc, xslt_file_name);
+ } else {
+ DEBUG(0, ("Unknow outout handler '%s'.\n", xpath_obj->nodesetval->nodeTab[i]->name));
+ xmlXPathFreeObject(xpath_obj);
+ xmlXPathFreeContext(xpath_context);
+ return -1;
+ }
+ }
+
+
+ xmlXPathFreeObject(xpath_obj);
+ xmlXPathFreeContext(xpath_context);
+ xmlFreeDoc(xslt_doc);
+ xmlFreeDoc(doc);
+ return 0;
+}