#include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "util.h" #include "helpers.h" #include "xml_helper.h" #define XPATH_IPAACTION_CONDITION_COMMAND (xmlChar *) "//def:ipa/def:ipaaction/def:condition/def:command" #define XPATH_IPAACTION_CONDITION_USER (xmlChar *) "//def:ipa/def:ipaaction/def:condition/def:user" #define XPATH_IPAACTION_CONDITION_GROUP (xmlChar *) "//def:ipa/def:ipaaction/def:condition/def:group" #define XPATH_IPAACTION_FILE_URL (xmlChar *) "//def:ipa/def:ipaaction/def:file/def:url" #define XPATH_IPAACTION_FILE_DATA (xmlChar *) "//def:ipa/def:ipaaction/def:file/def:data" #define XPATH_IPAACTION_FILE_PATH (xmlChar *) "//def:ipa/def:ipaaction/def:file/def:path" #define XPATH_IPAACTION_FILE_OWNER (xmlChar *) "//def:ipa/def:ipaaction/def:file/def:owner" #define XPATH_IPAACTION_FILE_GROUP (xmlChar *) "//def:ipa/def:ipaaction/def:file/def:group" #define XPATH_IPAACTION_FILE_ACCESS (xmlChar *) "//def:ipa/def:ipaaction/def:file/def:access" #define XPATH_IPAACTION_FILE_SELINUX_CONTEXT (xmlChar *) "//def:ipa/def:ipaaction/def:file/def:selinux_context" #define XPATH_IPAACTION_FILE_CLEANUP (xmlChar *) "//def:ipa/def:ipaaction/def:file/def:cleanup" #define XPATH_IPAACTION_RUN_COMMAND (xmlChar *) "//def:ipa/def:ipaaction/def:run/def:command" #define XPATH_IPAACTION_RUN_USER (xmlChar *) "//def:ipa/def:ipaaction/def:run/def:user" #define XPATH_IPAACTION_RUN_GROUP (xmlChar *) "//def:ipa/def:ipaaction/def:run/def:group" char *find_value(const xmlDocPtr doc, const xmlChar *xpath_expr, const char *default_value) { char *val; val = find_by_xpath(doc, xpath_expr, FIND_VALUE); if (val==NULL) { DEBUG(3, ("No value found with XPath %s.\n", xpath_expr)); if (default_value!=NULL) { DEBUG(3, ("Using default value %s.\n", default_value)); val=strdup(default_value); } } return val; } int check_ipaaction_condition(const xmlDocPtr doc, const xmlChar *default_namespace) { int ret; char *condition; char *user; char *group; char *arguments; condition = find_value(doc, XPATH_IPAACTION_CONDITION_COMMAND, NULL); CHECK(condition, NULL, ("No condition found for current ipaaction.\n"), return 0); DEBUG(3, ("Found condition for current ipaaction: |%s|\n", condition)); user = find_value(doc, XPATH_IPAACTION_CONDITION_USER, "nobody"); DEBUG(3, ("Found user for condition: %s\n", user)); group = find_value(doc, XPATH_IPAACTION_CONDITION_GROUP, "nobody"); DEBUG(3, ("Found group for condition: %s\n", group)); arguments=strchr(condition,' '); if (arguments!=NULL) { *arguments++='\0'; } ret=exec_command(condition, user, group, arguments, NULL); free(arguments); free(group); free(user); free(condition); return ret; } int ipaaction_file(const xmlDocPtr doc, const xmlChar *default_namespace) { char *url; char *data; char *path; char *owner; char *group; char *access; char *selinux_context; //char **acl; char *cleanup; CURL *curl_context; CURLcode curl_result; char *tmp_file_name; FILE *output_file; int fd; int ret; struct stat stat_buffer; url = find_value(doc, XPATH_IPAACTION_FILE_URL, NULL); DEBUG(3, ("Found the following ipaaction file url: |%s|\n", url)); data = find_value(doc, XPATH_IPAACTION_FILE_DATA, NULL); DEBUG(3, ("Found the following ipaaction file data: |%s|\n", data)); if (url==NULL && data==NULL) { DEBUG(0,("Found no url or data element for ipaaction file. This should never happen.\n")); return -1; } if (url!=NULL && data!=NULL) { DEBUG(0,("Only url or data element are allowed for ipaaction file, not both. This should never happen.\n")); return -1; } path = find_value(doc, XPATH_IPAACTION_FILE_PATH, NULL); CHECK(path, NULL, ("Path for ipaaction file not found.\n"), return -1); DEBUG(3, ("Found path for ipaaction file: %s\n", path)); ret=stat(path, &stat_buffer); CHECK(ret, 0, ("Destination file %s alread exists.\n", path), return -1); owner = find_value(doc, XPATH_IPAACTION_FILE_OWNER, "root"); DEBUG(3, ("Found owner for ipaaction file: %s\n", owner)); group = find_value(doc, XPATH_IPAACTION_FILE_GROUP, "root"); DEBUG(3, ("Found group for ipaaction file: %s\n", group)); access = find_value(doc, XPATH_IPAACTION_FILE_ACCESS, "0400"); DEBUG(3, ("Found access permissions for ipaaction file: %s\n", access)); selinux_context = find_value(doc, XPATH_IPAACTION_FILE_SELINUX_CONTEXT, NULL); DEBUG(3, ("Found SELinux file context for ipaaction file: %s\n", selinux_context)); cleanup = find_value(doc, XPATH_IPAACTION_FILE_CLEANUP, "no"); DEBUG(3, ("Found cleanup information for ipaaction file: %s\n", cleanup)); tmp_file_name=(char *) malloc(strlen(path)+7); CHECK(tmp_file_name,NULL, ("malloc failed."), return -1); strcpy(tmp_file_name, path); strcat(tmp_file_name, ".XXXXXX"); fd=open_temporary_file(tmp_file_name, access, owner, group, selinux_context); CHECK(fd, -1, ("Failed to open temporary file.\n"), return -1); output_file=fdopen(fd,"w"); CHECK(output_file, NULL, ("fdopen failed: %s\n", strerror(errno)), return -1); if (url!=NULL) { curl_context=curl_easy_init(); CHECK(curl_context, NULL, ("curl_easy_init failed.\n"), return -1); curl_result=curl_easy_setopt(curl_context, CURLOPT_URL, url); DEBUG(3,("curl result: %d\n",curl_result)); curl_result=curl_easy_setopt(curl_context, CURLOPT_WRITEDATA, output_file); DEBUG(3,("curl result: %d\n",curl_result)); curl_result=curl_easy_perform(curl_context); DEBUG(3,("curl result: %d\n",curl_result)); curl_easy_cleanup(curl_context); } fclose(output_file); /* this should close fd, too */ ret=rename(tmp_file_name, path); CHECK_MINUS_ONE_RETURN(ret, ("Cannot rename %s to %s: %s\n", tmp_file_name, path, strerror(errno) )); free(tmp_file_name); return 0; } int ipaaction_run(const xmlDocPtr doc, const xmlChar *default_namespace) { int ret; char *command; char *user; char *group; char *arguments; command = find_value(doc, XPATH_IPAACTION_RUN_COMMAND, NULL); CHECK(command, NULL, ("No command in ipaaction run section found, this should neven happen.\n"), return -1); DEBUG(3, ("Found command for current ipaaction: |%s|\n", command)); user = find_value(doc, XPATH_IPAACTION_RUN_USER, "nobody"); DEBUG(3, ("Found user for ipaaction run command: %s\n", user)); group = find_value(doc, XPATH_IPAACTION_RUN_GROUP, "nobody"); DEBUG(3, ("Found group for ipaaction run command: %s\n", group)); arguments=strchr(command,' '); if (arguments!=NULL) { *arguments++='\0'; } ret=exec_command(command, user, group, arguments, NULL); free(arguments); free(group); free(user); free(command); return ret; return 0; } int handle_ipaaction(const char *policy_name, const xmlChar *default_namespace) { int ret; xmlDocPtr doc; doc = xmlParseFile(policy_name); CHECK(doc, NULL, ("Cannot parse document %s!\n", policy_name), exit(1)); ret=check_ipaaction_condition(doc, default_namespace); if (ret!=0) { DEBUG(0,("IPA action condition failed\n")); return -1; } ret=ipaaction_file(doc, default_namespace); if (ret!=0) { DEBUG(0,("IPA action file failed\n")); return -1; } ret=ipaaction_run(doc, default_namespace); if (ret!=0) { DEBUG(0,("IPA action run failed\n")); return -1; } xmlFreeDoc(doc); return 0; }