summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSumit Bose <sbose@redhat.com>2009-01-13 15:23:13 +0100
committerSumit Bose <sbose@redhat.com>2009-01-13 15:23:13 +0100
commit0ffaf86a5587257b67cbc8339c9543481e59ba3a (patch)
tree1874cd52a050241b34478999d63ebc352eb87ffd
parentebb98f6fdf37638794240d255af39e1d34b59953 (diff)
downloadipa_policy-0ffaf86a5587257b67cbc8339c9543481e59ba3a.tar.gz
ipa_policy-0ffaf86a5587257b67cbc8339c9543481e59ba3a.tar.xz
ipa_policy-0ffaf86a5587257b67cbc8339c9543481e59ba3a.zip
added basic backup of modified config files
-rw-r--r--worker/output_handler.c185
-rw-r--r--worker/worker.c1
2 files changed, 175 insertions, 11 deletions
diff --git a/worker/output_handler.c b/worker/output_handler.c
index f082a0f..c77e15c 100644
--- a/worker/output_handler.c
+++ b/worker/output_handler.c
@@ -4,6 +4,11 @@
#include <unistd.h>
#include <errno.h>
#include <libgen.h>
+#include <limits.h>
+#include <fcntl.h>
+#include <sys/mman.h>
+
+
#include <libxml/tree.h>
@@ -21,6 +26,151 @@
#include "xml_helper.h"
#include "helpers.h"
+#define BACKUP_PATH "/var/spool/poliproc"
+#define ORIGINAL_BACKUP_EXTENSION "ipa_original_backup_DO_NOT_DELETE"
+
+static int copy_file(const char *src_name, const char *dest_name) {
+ int src_fd=-1;
+ int dest_fd=-1;
+ int ret=0;
+ struct stat stat_buffer;
+ void *src;
+ void *dest;
+ char *tmp_file_name=NULL;
+
+ tmp_file_name=(char *) malloc(strlen(src_name)+7);
+ CHECK(tmp_file_name, NULL, ("malloc failed."), return -1);
+ strcpy(tmp_file_name, src_name);
+ strcat(tmp_file_name, ".XXXXXX");
+
+ ret=-1;
+ src_fd = open(src_name, O_RDONLY);
+ CHECK(src_fd, -1, ("Failed to open %s read-only.\n", src_name), goto cleanup);
+
+ dest_fd=open_temporary_file(tmp_file_name, "0600", "root", "root", NULL);
+ CHECK(dest_fd, -1, ("Failed to open temporary file %s\n", tmp_file_name), goto cleanup);
+
+ ret=fstat(src_fd, &stat_buffer);
+ CHECK(ret, -1, ("Failed to stat file %s: %s\n", src_name, strerror(errno)), goto cleanup);
+
+ ret = lseek(dest_fd, stat_buffer.st_size - 1, SEEK_SET);
+ CHECK(ret, -1, ("Lseek failed for file %s: %s\n", dest_name, strerror(errno)), goto cleanup);
+
+ ret = write(dest_fd, "", 1);
+ if ( ret != 1 ) {
+ DEBUG(0, ("Failed to write one byte to %s: %s.\n", dest_name, strerror(errno)));
+ goto cleanup;
+ }
+
+ src = mmap(NULL, stat_buffer.st_size, PROT_READ, MAP_SHARED, src_fd, 0);
+ if ( src == MAP_FAILED ) {
+ DEBUG(0, ("Mmap failed for file %s: %s.\n", src_name, strerror(errno)));
+ goto cleanup;
+ }
+
+ dest = mmap(NULL, stat_buffer.st_size, PROT_READ | PROT_WRITE, MAP_SHARED,
+ dest_fd, 0);
+ if ( src == MAP_FAILED ) {
+ DEBUG(0, ("Mmap failed for file %s: %s.\n", src_name, strerror(errno)));
+ munmap(src, stat_buffer.st_size);
+ goto cleanup;
+ }
+
+ memcpy(dest, src, stat_buffer.st_size);
+
+ munmap(dest, stat_buffer.st_size);
+ munmap(src, stat_buffer.st_size);
+
+ close(dest_fd);
+ close(src_fd);
+ ret=rename(tmp_file_name, dest_name);
+ CHECK(ret, -1, ("Cannot rename %s to %s: %s\n", tmp_file_name, dest_name, strerror(errno) ), goto cleanup);
+
+cleanup:
+ if (dest_fd != -1) close(dest_fd);
+ if (src_fd != -1) close(src_fd);
+ free(tmp_file_name);
+
+ return ret;
+}
+static int check_dir_create(const char *name) {
+ int ret;
+ struct stat stat_buffer;
+
+ if( (ret=stat(name, &stat_buffer)) == -1) {
+ DEBUG(0, ("Directory %s does not exist, creating it.\n", name, strerror(errno)));
+ ret=mkdir(name, 0600);
+ CHECK(ret, -1, ("mkdir %s failed: %s\n", name, strerror(errno)), return -1);
+ } else if (!S_ISDIR(stat_buffer.st_mode)) {
+ DEBUG(0,("%s is not a regular file!\n",name));
+ return -1;
+ }
+
+ return 0;
+}
+
+static int safe_config_file(const char *name, const char *app_name) {
+ int ret;
+ struct stat stat_buffer;
+ char backup_dir[PATH_MAX];
+ char backup_file[PATH_MAX];
+ char original_backup[PATH_MAX];
+ char *buffer=NULL;
+ char *base_name=NULL;
+
+ if ( (ret=lstat(name, &stat_buffer)) == -1) {
+ DEBUG(0,("stat on %s failed: %s\n",name, strerror(errno)));
+ goto cleanup;
+ }
+ if (!S_ISREG(stat_buffer.st_mode)) {
+ DEBUG(0,("%s is not a regular file!\n",name));
+ ret=-1;
+ goto cleanup;
+ }
+
+ ret=check_dir_create(BACKUP_PATH);
+ CHECK(ret, -1, ("Failed to create main backup directory %s.\n", BACKUP_PATH), goto cleanup);
+
+ ret=snprintf(backup_dir, PATH_MAX, "%s/%s", BACKUP_PATH, app_name);
+ ret=snprintf(original_backup, PATH_MAX, "%s/%s.%s",backup_dir,base_name,ORIGINAL_BACKUP_EXTENSION);
+ if (ret<0) {
+ DEBUG(0,("snprintf failed.\n"));
+ ret=-1;
+ goto cleanup;
+ }
+ ret=check_dir_create(backup_dir);
+ CHECK(ret, -1, ("Failed to create backup directory %s for application %s.\n", backup_dir, app_name), goto cleanup);
+
+ buffer=strdup(name);
+ base_name=basename(buffer);
+ ret=snprintf(original_backup, PATH_MAX, "%s/%s.%s",backup_dir,base_name,ORIGINAL_BACKUP_EXTENSION);
+ if (ret<0) {
+ DEBUG(0,("snprintf failed.\n"));
+ ret=-1;
+ goto cleanup;
+ }
+
+ if ( (ret=lstat(original_backup, &stat_buffer)) == -1) {
+ DEBUG(0, ("There is no original backup file, I will assume that %s is the original file.\n", name));
+ ret=copy_file(name, original_backup);
+ } else {
+ DEBUG(3, ("Original backup file exists, I will create an ordinary backup file\n", name));
+ ret=snprintf(backup_file, PATH_MAX, "%s/%s.%d",backup_dir,base_name,time(NULL));
+ if (ret<0) {
+ DEBUG(0,("snprintf failed.\n"));
+ ret=-1;
+ goto cleanup;
+ }
+ ret=copy_file(name, backup_file);
+ }
+
+
+cleanup:
+ free(buffer);
+ return ret;
+}
+
+
char *get_output_handler_parameter(xmlNode *node, const char *name, const char *default_value, const int required) {
char *value;
@@ -51,14 +201,15 @@ int output_handler_file(xmlNode *node, const xmlDocPtr doc, const char *xslt_fil
char *permission=NULL;
char *param_name=NULL;
char *param_value=NULL;
+ char *app_name=NULL;
struct stat stat_buffer;
char *dir_name=NULL;
char *tmp_file_name=NULL;
char *buffer=NULL;
- int ret;
+ int ret=0;
int fd;
xsltStylesheetPtr parsed_stylesheet = NULL;
- xmlDocPtr res;
+ xmlDocPtr res=NULL;
name=get_output_handler_parameter(node, "name", NULL, 1);
@@ -67,20 +218,22 @@ int output_handler_file(xmlNode *node, const xmlDocPtr doc, const char *xslt_fil
dir_name=dirname(buffer);
if( (ret=stat(dir_name, &stat_buffer)) == -1) {
DEBUG(0,("stat on %s failed: %s\n",dir_name, strerror(errno)));
- goto failed;
+ goto cleanup;
}
if(!S_ISDIR(stat_buffer.st_mode)) {
DEBUG(0,("%s is not a directory!\n",dir_name));
- goto failed;
+ ret=-1;
+ goto cleanup;
}
if( (ret=lstat(name, &stat_buffer)) == -1) {
DEBUG(0,("stat on %s failed: %s\n",name, strerror(errno)));
- goto failed;
+ goto cleanup;
}
if(!S_ISREG(stat_buffer.st_mode)) {
DEBUG(0,("%s is not a regular file!\n",name));
- goto failed;
+ ret=-1;
+ goto cleanup;
}
owner=get_output_handler_parameter(node, "owner", "root", 0);
@@ -91,6 +244,11 @@ int output_handler_file(xmlNode *node, const xmlDocPtr doc, const char *xslt_fil
param_value=get_output_handler_parameter(node, "param_value", NULL, 0);
/* TODO: create backup copy */
+ app_name = find_by_xpath(doc, "//def:metadata/def:app", FIND_VALUE);
+ CHECK(app_name, NULL, ("Cannot find the name of the application in policy file.\n"), goto failed);
+ DEBUG(3, ("Found application name: %s\n", app_name));
+ ret=safe_config_file(name, app_name);
+ CHECK(ret, -1, ("Failed to safe config file %s of application %s.\n", name, app_name), goto cleanup);
tmp_file_name=(char *) malloc(strlen(name)+7);
CHECK_NULL_RETURN(tmp_file_name,("malloc failed."));
@@ -107,14 +265,17 @@ int output_handler_file(xmlNode *node, const xmlDocPtr doc, const char *xslt_fil
ret = xsltSaveResultToFd(fd, res, parsed_stylesheet);
if (ret == -1) {
DEBUG(0, ("Cannot save result!\n"));
- exit(1);
+ close(fd);
+ goto cleanup;
}
- 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) ));
+ CHECK(ret, -1, ("Cannot rename %s to %s: %s\n", tmp_file_name, name, strerror(errno) ), goto cleanup);
+
+cleanup:
+ xmlFreeDoc(res);
+ xsltFreeStylesheet(parsed_stylesheet);
free(buffer);
free(tmp_file_name);
@@ -125,7 +286,8 @@ int output_handler_file(xmlNode *node, const xmlDocPtr doc, const char *xslt_fil
free(permission);
free(param_name);
free(param_value);
- return 0;
+ free(app_name);
+ return ret;
failed:
free(buffer);
@@ -137,6 +299,7 @@ failed:
free(permission);
free(param_name);
free(param_value);
+ free(app_name);
return -1;
}
diff --git a/worker/worker.c b/worker/worker.c
index 33b3afb..327f948 100644
--- a/worker/worker.c
+++ b/worker/worker.c
@@ -113,6 +113,7 @@ int main(int argc, const char *argv[])
cleanup:
free_xml_search_path();
+ free(policy_file_name);
return ret;
}