diff options
Diffstat (limited to 'security/prelude-pflogger/files/run-prelude-pflogger.c')
-rw-r--r-- | security/prelude-pflogger/files/run-prelude-pflogger.c | 166 |
1 files changed, 166 insertions, 0 deletions
diff --git a/security/prelude-pflogger/files/run-prelude-pflogger.c b/security/prelude-pflogger/files/run-prelude-pflogger.c new file mode 100644 index 00000000000..e065663f4b8 --- /dev/null +++ b/security/prelude-pflogger/files/run-prelude-pflogger.c @@ -0,0 +1,166 @@ +#define PRELUDE_PFLOGGER_USER "@PRELUDE_USER@" +#define PRELUDE_PFLOGGER_PATH "@PREFIX@/bin/prelude-pflogger" + +#include <unistd.h> +#include <string.h> +#include <stdio.h> +#include <errno.h> +#include <stdlib.h> +#include <sys/wait.h> +#include <pwd.h> +#include <syslog.h> + +#define MAX_ARGS 40 +#ifndef TRUE +#define TRUE 1 +#endif /* TRUE */ + +#ifndef FALSE +#define FALSE 0 +#endif /* FALSE */ + + +void error_sys(char *str) + +{ + /* Output error message to syslog */ + char msg[1024]; + snprintf(msg, sizeof(msg), "run-prelude-pflogger : %s : %s", str, strerror(errno)); + syslog(LOG_ALERT, msg); + +} + + +int obtainUIDandGID(const char *name, uid_t *pw_uid, gid_t *pw_gid) +{ + /* Obtain UID and GID from passwd entry identified by name */ + struct passwd *pw_entry; + char msg[100]; + + if ((pw_entry = getpwnam(name)) == NULL) + { + snprintf(msg, sizeof(msg), "failed to get password entry for %s", name); + error_sys(msg); + return FALSE; + } + else + { + *pw_uid = pw_entry->pw_uid; + *pw_gid = pw_entry->pw_gid; + return TRUE; + + } +} + + +int main (int argc, char **argv ) + +{ + + pid_t pid; + uid_t UID; + gid_t GID; + pid_t pidwait; + int waitstat; + int s; + int max_fd; + + /* Sanity check */ + if (argc > MAX_ARGS) + { + error_sys("arg buffer too small"); + exit(-1); + } + + if (geteuid() != 0) + { + error_sys("must be called by root"); + exit(-1); + } + + /* fork child that will become prelude-pflogger */ + if ((pid = fork()) < 0) + + error_sys("fork error"); + + else + + { + + if (pid == 0) + + { + + /* We're the child */ + char *args[MAX_ARGS]; + unsigned int i; + + /* Become session leader */ + setsid(); + + /* Change working directory to root directory. + The current working directory could be a mounted + filesystem; if the daemon stays on a mounted + filesystem it could prevent the filesystem from + being umounted. */ + chdir("/"); + + /* Clear out file creation mask */ + umask(0); + + /* Close unneeded file descriptors */ + max_fd = (int) sysconf(_SC_OPEN_MAX); + if (max_fd == -1) + max_fd = getdtablesize(); + for (s = 3; s < max_fd; s++) + (void) close(s); + + if (!obtainUIDandGID(PRELUDE_PFLOGGER_USER, &UID, &GID)) + exit(-1); + + /* Drop privileges immediately */ + if (setgid(GID) < 0) + { + /* It is VERY important to check return + value and not continue if setgid fails + */ + error_sys ("setgid failed"); + exit (-1); + } + + if (setuid(UID) < 0) + { + /* It is VERY important to check return + value and not continue if setuid fails + */ + error_sys ("setuid failed"); + exit (-1); + } + + /* Build calling argv */ + args[0] = PRELUDE_PFLOGGER_PATH; + for (i=1;i<argc;i++) + { + args[i] = argv[i]; + } + args[i++] = NULL; + + /* Finally transform self into prelude-pflogger */ + if (execvp(PRELUDE_PFLOGGER_PATH, args) < 0) + error_sys("execve error"); + else + ; /* avoid if-then ambiguity */ + } + + else + + { + /* We're the parent + Terminate + */ + exit(0); + } + + } + +} |