diff options
-rw-r--r-- | miavd/daemon.cc | 96 |
1 files changed, 66 insertions, 30 deletions
diff --git a/miavd/daemon.cc b/miavd/daemon.cc index 6e46bd5..a687d38 100644 --- a/miavd/daemon.cc +++ b/miavd/daemon.cc @@ -30,6 +30,8 @@ #include <fcntl.h> #include <signal.h> #include <stdio.h> +#include <stdlib.h> +#include <errno.h> // For getgrent and getgrent #include <sys/types.h> @@ -39,6 +41,38 @@ // For strcmp #include <string.h> +/* Resolve a group's name or id into a numeric gid */ +static gid_t get_gid(const char *grp) +{ + char *eptr; + gid_t xid = strtoul(grp, &eptr, 10); + struct group *gr; + errno = 0; /* Per getgrnam(3) and getgrgid(3) manual page */ + if(!*eptr) + gr = getgrgid(xid); + else + gr = getgrnam(grp); + return !gr ? 0 : gr->gr_gid; +} + +/* Resolve a user's name or id into a numeric uid with associated gid */ +static uid_t get_uid(const char *usr, gid_t *gid) +{ + char *eptr; + uid_t xid = strtoul(usr, &eptr, 10); + struct passwd *pw; + errno = 0; /* Per getpwnam(3) and getpwuid(3) manual page */ + if(!*eptr) + pw = getpwuid(xid); + else + pw = getpwnam(usr); + if(!pw) + return 0; + if(!gid) + *gid = pw->pw_gid; + return pw->pw_uid; +} + Daemon::Daemon() {} @@ -50,50 +84,50 @@ int Daemon::run(const char *user, const char* group) int f; int fd; - // Fetch user id - int uid = -1; - struct passwd *p = getpwent(); - while(p) { - if(strcmp(p->pw_name, user) == 0) uid = p->pw_uid; - p = getpwent(); - } - if(uid == -1) { - fprintf(stderr, "Could not find user \"%s\" in /etc/passwd file.\n", user); + // Fetch user and group IDs + gid_t gid = 0; + uid_t uid = 0; + if(user && *user) { + uid = get_uid(user, &gid); + if(errno) { + fprintf(stderr, "Could resolve user \"%s\"", user); + perror(""); + } } - // Fetch group id - int gid = -1; - struct group *g = getgrent(); - while(g) { - if(strcmp(g->gr_name, group) == 0) gid = g->gr_gid; - g = getgrent(); - } - if(gid == -1) { - fprintf(stderr, "Could not find group \"%s\" in /etc/group file.\n", group); + if(group && *group) { + gid = get_gid(group); + if(errno) { + fprintf(stderr, "Could not resolve group \"%s\"", group); + perror(""); + } } chdir("/"); umask(0); - f = fork(); - switch(f) { + switch(fork()) { case -1: // Fork error perror("Fork in daemon.cc"); return 1; case 0: // Forked child - // Switch to given group - if(setgid(gid) != 0) { - fprintf(stderr, "Failed to change to group \"%s\" (gid: %d), quitting.\n", group, gid); - perror(""); - fprintf(stderr, "Runnning daemon as current group\n"); + if(gid) { + // Switch to given group + if(setgid(gid) != 0) { + fprintf(stderr, "Failed to change to group \"%s\" (gid: %d), quitting.\n", group, gid); + perror(""); + fprintf(stderr, "Runnning daemon as current group\n"); + } } - // Switch to given user - if(setuid(uid) != 0) { - fprintf(stderr, "Failed to change to user \"%s\" (uid: %d), quitting.\n", user, uid); - perror(""); - fprintf(stderr, "Runnning daemon as current user\n"); + if(uid) { + // Switch to given user + if(setuid(uid) != 0) { + fprintf(stderr, "Failed to change to user \"%s\" (uid: %d), quitting.\n", user, uid); + perror(""); + fprintf(stderr, "Runnning daemon as current user\n"); + } } // Redirect stdin, stdout and stderr to /dev/null @@ -103,6 +137,8 @@ int Daemon::run(const char *user, const char* group) dup2(1, fd); dup2(2, fd); + close(fd); + setsid(); signal (SIGTERM, SIG_IGN); |