summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--miavd/daemon.cc96
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);