diff options
| -rw-r--r-- | server/src/Makefile.am | 2 | ||||
| -rw-r--r-- | server/src/daemon.cc | 158 | ||||
| -rw-r--r-- | server/src/daemon.h | 45 | ||||
| -rw-r--r-- | server/src/pracrod.cc | 73 | 
4 files changed, 222 insertions, 56 deletions
| diff --git a/server/src/Makefile.am b/server/src/Makefile.am index 4cee6cf..672b8e7 100644 --- a/server/src/Makefile.am +++ b/server/src/Makefile.am @@ -7,6 +7,7 @@ pracrod_CXXFLAGS = $(PQXX_CXXFLAGS) $(CONFIG_CXXFLAGS)  pracrod_SOURCES = \  	pracrod.cc \ +	daemon.cc \  	database.cc \  	configuration.cc \  	exception.cc \ @@ -21,6 +22,7 @@ pracrod_SOURCES = \  EXTRA_DIST = \  	configuration.h \ +	daemon.h \  	database.h \  	debug.h \  	exception.h \ diff --git a/server/src/daemon.cc b/server/src/daemon.cc new file mode 100644 index 0000000..a88fa39 --- /dev/null +++ b/server/src/daemon.cc @@ -0,0 +1,158 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/*************************************************************************** + *            daemon.cc + * + *  Thu Jun  9 10:27:59 CEST 2005 + *  Copyright  2005 Bent Bisballe + *  deva@aasimon.org + ****************************************************************************/ + +/* + *  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 2 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, write to the Free Software + *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA + */ + +#include "daemon.h" + +#include <sys/stat.h> +#include <unistd.h> +#include <fcntl.h> +#include <signal.h> +#include <stdio.h> +#include <stdlib.h> +#include <errno.h> + +// For getgrent and getgrent +#include <sys/types.h> +#include <grp.h> +#include <pwd.h> + +// 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() +{} + +Daemon::~Daemon() +{} + +int Daemon::run(const char *user, const char* group, bool detach) +{ +  int f; +  int fd; + +  // 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(""); +    } +  } + +  if(group && *group) { +    gid = get_gid(group); +    if(errno) { +      fprintf(stderr, "Could not resolve group \"%s\"", group); +      perror(""); +    } +  } + +  chdir("/"); +  umask(0); + +  if(detach) { +    switch(fork()) { +    case -1: // Fork error +      perror("Fork in daemon.cc"); +      return 1; +       +    case 0:  // Forked child +      break; // Break out of switch +       +    default: // Parent +      // exit(0); +      return 0; +    } +  } + +  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"); +    } +  } +     +  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 +  fd = open("/dev/null", O_NOCTTY | O_RDWR, 0666); +   +  dup2(0, fd); +  dup2(1, fd); +  dup2(2, fd); +     +  close(fd); + +  setsid(); + +  signal (SIGTERM, SIG_IGN); +  signal (SIGHUP, SIG_IGN); +  if(detach) signal (SIGINT, SIG_IGN); // Don't disable Ctrl+c when running in foreground. + +  return daemon_main(); +} diff --git a/server/src/daemon.h b/server/src/daemon.h new file mode 100644 index 0000000..89c3f1c --- /dev/null +++ b/server/src/daemon.h @@ -0,0 +1,45 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/*************************************************************************** + *            daemon.h + * + *  Thu Jun  9 10:27:59 CEST 2005 + *  Copyright  2005 Bent Bisballe + *  deva@aasimon.org + ****************************************************************************/ + +/* + *  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 2 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, write to the Free Software + *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA + */ + +#ifndef __DAEMON_H__ +#define __DAEMON_H__ + +#include <sys/types.h> + +class Daemon { +public: +  Daemon(); +  virtual ~Daemon(); +   +  /** +   * Use NOBODY_GROUP and NOBODY_USER if no privileges are needed to run. +   */ +  int run(const char* user, const char* group, bool detach = true); + +private: +  virtual int daemon_main() = 0; +}; + +#endif/*__DAEMON_H__*/ diff --git a/server/src/pracrod.cc b/server/src/pracrod.cc index cd5bfe7..134b212 100644 --- a/server/src/pracrod.cc +++ b/server/src/pracrod.cc @@ -27,6 +27,8 @@  // For ETC  #include <config.h> +#include "daemon.h" +  // For setuid and setgid  #include <sys/types.h>  #include <unistd.h> @@ -93,6 +95,19 @@ void reload(int fisk)    }  } +class PracroDaemon : public Daemon { +private: +  int daemon_main(); +}; + +int PracroDaemon::daemon_main() +{ +  // Activate the server main loop. +  server(); + +  return 0; +} +  int main(int argc, char *argv[])  {    int c; @@ -152,9 +167,6 @@ int main(int argc, char *argv[])      }    } -  //std::basic_string<_CharT, _Traits, _Alloc>::basic_string(const _CharT*, const _Alloc&) [with _CharT = char, _Traits = std::char_traits<char>, _Alloc = std::allocator<char>] -  //std::basic_string<_CharT, _Traits, _Alloc>::basic_string(const std::basic_string<_CharT, _Traits, _Alloc>&) [with _CharT = char, _Traits = std::char_traits<char>, _Alloc = std::allocator<char>] -    char *cfname = NULL;    if(!configfile) cfname = ETC"/pracrod.conf";    else cfname = configfile; @@ -170,24 +182,6 @@ int main(int argc, char *argv[])      }    } -  if(user) { -    // 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); -      return 1; -    } - -    if(setuid(uid) == -1) { -      fprintf(stderr, "Could not switch to user %s: %s\n", user, strerror(errno)); -      return 1; -    } -  }    if(!group) {      std::string groupstr; @@ -199,41 +193,8 @@ int main(int argc, char *argv[])    } -  if(group) { -    // 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); -      return 1; -    } -     -    if(setgid(gid) == -1) { -      fprintf(stderr, "Could not switch to group %s: %s\n", group, strerror(errno)); -      return 1; -    } -  } - -  if(!foreground) { -    daemon(0,0); -    signal (SIGTERM, SIG_IGN); -    signal (SIGINT, SIG_IGN); -  } else { -    printf("Running in foreground mode.\n"); -  } - -  // Create callback to reload conf files. -  signal (SIGHUP, reload); - -  signal(SIGCLD, SIG_IGN);  // Ved SIGCHILD til IGNORE maa wait/waitpid ikke kaldes  -                            //   (ellers kommer der kernel-brok) - -  // Activate the server main loop. -  server(); +  PracroDaemon daemon; +  daemon.run(user, group, !foreground);    // Clean up    if(configfile) free(configfile); | 
