/*
* Copyright (C) Sumit Bose 2009
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
* Software Foundation; either version 3 of the License, or (at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see .
*
*/
#define _GNU_SOURCE
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include "util.h"
#include "helpers.h"
int get_file_info(struct file_info *f_info, char *xpath_base) {
return 0;
}
/**
* \brief Open a temporary file in a safe way
*
* Use this function to create a temporary file in a safe way with the help of
* mkstemp and set file properties.
*
* \param name name of the temporary file in the format mkstemp expects, i.e.
* ending with XXXXXX; mkstemp will modify name to contain the name of the
* temporary file
* \param permission string wit hthe octal repesentation of the file access
* permissions
* \param user name of the file owner
* \param group name of the owning group
* \param selinux_context_string string containing the SELinux file context
*
* \return file descriptor or -1 in case of an error
*
*/
int open_temporary_file(char *name, const char *permission, const char *user, const char *group, const char *selinux_context_string) {
int fd;
int ret;
struct passwd *pwd_info;
struct group *grp_info;
pwd_info=getpwnam(user);
CHECK(pwd_info, NULL, ("Cannot find user %s.\n", user), return -1);
grp_info=getgrnam(group);
CHECK(grp_info, NULL, ("Cannot find group %s.\n", group), return -1);
fd=mkstemp(name);
if (fd==-1) {
DEBUG(0,("mkstemp failed with template %s: %s\n",name, strerror(errno)));
return -1;
}
ret=fchmod(fd, (mode_t) strtol(permission, NULL, 8));
CHECK(ret, -1, ("Cannot chmod temporary file to %s: %s\n", permission, strerror(errno)), return -1);
ret=fchown(fd, pwd_info->pw_uid, grp_info->gr_gid);
CHECK(ret, -1, ("Cannot chown temporary file to %s:%s: %s\n", user, group, strerror(errno)), return -1);
if (selinux_context_string != NULL ) {
ret=fsetfilecon(fd, (security_context_t ) selinux_context_string);
CHECK(ret, -1, ("fsetfilecon failed: %s\n",strerror(errno)), return -1);
}
return fd;
}
/**
* \brief run an external command
*
* This is a helper function to run an external command in a different user
* context.
*
* \param command command to run
* \param user name of the user to run the command
* \param group name of the group to run the command
* \param arguments space separated list of arguments, may be NULL
* \param extra_args another space separated list of arguments, useful if you
* have some static and some generated/extracted arguments, may be NULL
*
* \return return code of the external command or -1 in an error occurred
*
*/
int exec_command(const char *command, const char *user, const char *group, char *arguments, char *extra_args) {
char *argv[10]; /* FIXME */
int c=0;
int i;
char *cur;
char *next_arg;
pid_t pid;
int ret;
int status;
int stdout_pipe[2];
int stderr_pipe[2];
char buffer[255];
struct passwd *pwd_info;
struct group *grp_info;
pwd_info=getpwnam(user);
CHECK(pwd_info, NULL, ("Cannot find user %s.\n", user), return -1);
grp_info=getgrnam(group);
CHECK(grp_info, NULL, ("Cannot find group %s.\n", group), return -1);
argv[c++]=strdup(command);
if (arguments!=NULL) {
cur=arguments;
while( (next_arg=strchr(cur, ' '))!=NULL) {
argv[c++]=strndup(cur, next_arg-cur);
cur=next_arg+1;
}
argv[c++]=strdup(cur);
}
if (extra_args!=NULL) {
cur=extra_args;
while( (next_arg=strchr(cur, ' '))!=NULL) {
argv[c++]=strndup(cur, next_arg-cur);
cur=next_arg+1;
}
argv[c++]=strdup(cur);
}
argv[c++]=NULL;
for(i=0;igr_gid);
CHECK(ret, -1, ("setgid failed: %s\n",strerror(errno)), exit(1));
ret=setuid(pwd_info->pw_uid);
CHECK(ret, -1, ("setuid failed: %s\n",strerror(errno)), exit(1));
execv(command, argv);
}
close(stdout_pipe[1]);
close(stderr_pipe[1]);
*buffer='\0';
ret=read(stdout_pipe[0], &buffer, 255);
buffer[ret]='\0';
DEBUG(3,("stdout from child: >>%s<<\n",buffer));
*buffer='\0';
ret=read(stderr_pipe[0], &buffer, 255);
buffer[ret]='\0';
DEBUG(3,("stderr from child: >>%s<<\n",buffer));
close(stdout_pipe[0]);
close(stderr_pipe[0]);
ret = waitpid(pid, & status, 0);
if (WIFEXITED(status)) {
DEBUG(3,("Child terminated normally with exit status %d\n",WEXITSTATUS(status)));
} else {
DEBUG(1,("Child terminated not normally.\n"));
}
for(i=0;i