diff options
Diffstat (limited to 'nslcd/nslcd.c')
-rw-r--r-- | nslcd/nslcd.c | 305 |
1 files changed, 30 insertions, 275 deletions
diff --git a/nslcd/nslcd.c b/nslcd/nslcd.c index ea9e4e3..8072b25 100644 --- a/nslcd/nslcd.c +++ b/nslcd/nslcd.c @@ -56,6 +56,7 @@ #include <dlfcn.h> #include <libgen.h> #include <limits.h> +#include <systemd/sd-daemon.h> #include "nslcd.h" #include "log.h" @@ -64,7 +65,6 @@ #include "compat/attrs.h" #include "compat/getpeercred.h" #include "compat/socket.h" -#include "daemonize.h" /* read timeout is half a second because clients should send their request quickly, write timeout is 60 seconds because clients could be taking some @@ -81,12 +81,6 @@ /* flag to indicate if we are in debugging mode */ static int nslcd_debugging = 0; -/* flag to indicate we shouldn't daemonize */ -static int nslcd_nofork = 0; - -/* flag to indicate user requested the --check option */ -static int nslcd_checkonly = 0; - /* the flag to indicate that a signal was received */ static volatile int nslcd_receivedsignal = 0; @@ -96,22 +90,6 @@ static int nslcd_serversocket = -1; /* thread ids of all running threads */ static pthread_t *nslcd_threads; -/* if we don't have clearenv() we have to do this the hard way */ -#ifndef HAVE_CLEARENV - -/* the definition of the environment */ -extern char **environ; - -/* the environment we want to use */ -static char *sane_environment[] = { - "HOME=/", - "TMPDIR=/tmp", - "LDAPNOINIT=1", - NULL -}; - -#endif /* not HAVE_CLEARENV */ - /* display version information */ static void display_version(FILE *fp) { @@ -127,9 +105,7 @@ static void display_usage(FILE *fp, const char *program_name) { fprintf(fp, "Usage: %s [OPTION]...\n", program_name); fprintf(fp, "Name Service LDAP connection daemon.\n"); - fprintf(fp, " -c, --check check if the daemon already is running\n"); - fprintf(fp, " -d, --debug don't fork and print debugging to stderr\n"); - fprintf(fp, " -n, --nofork don't fork\n"); + fprintf(fp, " -d, --debug print debugging to stderr\n"); fprintf(fp, " --help display this help and exit\n"); fprintf(fp, " --version output version information and exit\n"); fprintf(fp, "\n" "Report bugs to <%s>.\n", PACKAGE_BUGREPORT); @@ -137,9 +113,7 @@ static void display_usage(FILE *fp, const char *program_name) /* the definition of options for getopt(). see getopt(2) */ static struct option const nslcd_options[] = { - {"check", no_argument, NULL, 'c'}, {"debug", no_argument, NULL, 'd'}, - {"nofork", no_argument, NULL, 'n'}, {"help", no_argument, NULL, 'h'}, {"version", no_argument, NULL, 'V'}, {NULL, 0, NULL, 0} @@ -154,16 +128,10 @@ static void parse_cmdline(int argc, char *argv[]) { switch (optc) { - case 'c': /* -c, --check check if the daemon already is running */ - nslcd_checkonly = 1; - break; - case 'd': /* -d, --debug don't fork and print debugging to stderr */ + case 'd': /* -d, --debug print debugging to stderr */ nslcd_debugging++; log_setdefaultloglevel(LOG_DEBUG); break; - case 'n': /* -n, --nofork don't fork */ - nslcd_nofork++; - break; case 'h': /* --help display this help and exit */ display_usage(stdout, argv[0]); exit(EXIT_SUCCESS); @@ -203,126 +171,38 @@ static void exithandler(void) log_log(LOG_WARNING, "problem closing server socket (ignored): %s", strerror(errno)); } - /* remove existing named socket */ - if (unlink(NSLCD_SOCKET) < 0) - { - log_log(LOG_DEBUG, "unlink() of " NSLCD_SOCKET " failed (ignored): %s", - strerror(errno)); - } - /* remove pidfile */ - if (unlink(NSLCD_PIDFILE) < 0) - { - log_log(LOG_DEBUG, "unlink() of " NSLCD_PIDFILE " failed (ignored): %s", - strerror(errno)); - } /* log exit */ log_log(LOG_INFO, "version %s bailing out", VERSION); } -/* create the directory for the specified file to reside in */ -static void mkdirname(const char *filename) +static int get_socket() { - char *tmpname, *path; - tmpname = strdup(filename); - if (tmpname == NULL) - return; - path = dirname(tmpname); - if (mkdir(path, (mode_t)0755) == 0) - { - /* if directory was just created, set correct ownership */ - if (lchown(path, nslcd_cfg->uid, nslcd_cfg->gid) < 0) - log_log(LOG_WARNING, "problem setting permissions for %s: %s", - path, strerror(errno)); - } - free(tmpname); -} - -/* returns a socket ready to answer requests from the client, - exit()s on error */ -static int create_socket(const char *filename) -{ - int sock; - int i; - struct sockaddr_un addr; - /* create a socket */ - if ((sock = socket(PF_UNIX, SOCK_STREAM, 0)) < 0) - { - log_log(LOG_ERR, "cannot create socket: %s", strerror(errno)); - exit(EXIT_FAILURE); - } - if (sock >= (int)FD_SETSIZE) - { - log_log(LOG_ERR, "socket file descriptor number too high (%d)", sock); - exit(EXIT_FAILURE); - } - /* remove existing named socket */ - if (unlink(filename) < 0) - { - log_log(LOG_DEBUG, "unlink() of %s failed (ignored): %s", - filename, strerror(errno)); - } - /* do not block on accept() */ - if ((i = fcntl(sock, F_GETFL, 0)) < 0) - { - log_log(LOG_ERR, "fctnl(F_GETFL) failed: %s", strerror(errno)); - if (close(sock)) - log_log(LOG_WARNING, "problem closing socket: %s", strerror(errno)); - exit(EXIT_FAILURE); - } - if (fcntl(sock, F_SETFL, i | O_NONBLOCK) < 0) - { - log_log(LOG_ERR, "fctnl(F_SETFL,O_NONBLOCK) failed: %s", strerror(errno)); - if (close(sock)) - log_log(LOG_WARNING, "problem closing socket: %s", strerror(errno)); - exit(EXIT_FAILURE); - } - /* create the directory if needed */ - mkdirname(filename); - /* create socket address structure */ - memset(&addr, 0, sizeof(struct sockaddr_un)); - addr.sun_family = AF_UNIX; - strncpy(addr.sun_path, filename, sizeof(addr.sun_path)); - addr.sun_path[sizeof(addr.sun_path) - 1] = '\0'; - /* bind to the named socket */ - if (bind(sock, (struct sockaddr *)&addr, SUN_LEN(&addr))) - { - log_log(LOG_ERR, "bind() to %s failed: %s", filename, strerror(errno)); - if (close(sock)) - log_log(LOG_WARNING, "problem closing socket: %s", strerror(errno)); - exit(EXIT_FAILURE); - } - /* close the file descriptor on exec */ - if (fcntl(sock, F_SETFD, FD_CLOEXEC) < 0) - { - log_log(LOG_ERR, "fctnl(F_SETFL,FD_CLOEXEC) on %s failed: %s", - filename, strerror(errno)); - if (close(sock)) - log_log(LOG_WARNING, "problem closing socket: %s", strerror(errno)); - exit(EXIT_FAILURE); - } - /* set permissions of socket so anybody can do requests */ - /* Note: we use chmod() here instead of fchmod() because - fchmod does not work on sockets - http://www.opengroup.org/onlinepubs/009695399/functions/fchmod.html - http://lkml.org/lkml/2005/5/16/11 */ - if (chmod(filename, (mode_t)0666)) - { - log_log(LOG_ERR, "chmod(0666) of %s failed: %s", - filename, strerror(errno)); - if (close(sock)) - log_log(LOG_WARNING, "problem closing socket: %s", strerror(errno)); + int r, fd; + r = sd_listen_fds(1); + if (r != 1) { + if (r < 0) + log_log(LOG_ERR, "failed to aquire sockets from systemd: %s", + strerror(-r)); + else + log_log(LOG_ERR, "wrong number of sockets from systemd: " + "expected %d but got %d", 1, r); exit(EXIT_FAILURE); } - /* start listening for connections */ - if (listen(sock, SOMAXCONN) < 0) + + fd = SD_LISTEN_FDS_START; + + r = sd_is_socket(fd, AF_UNIX, SOCK_STREAM, 1); + if (r < 1) { - log_log(LOG_ERR, "listen() failed: %s", strerror(errno)); - if (close(sock)) - log_log(LOG_WARNING, "problem closing socket: %s", strerror(errno)); + if (r < 0) + log_log(LOG_ERR, "unable to verify socket type:%d: %s", + fd, strerror(-r)); + else + log_log(LOG_ERR, "socket not of the right type:%d", fd); exit(EXIT_FAILURE); } - /* we're done */ - return sock; + + return fd; } /* read the version information and action from the stream @@ -425,69 +305,6 @@ static void handleconnection(int sock, MYLDAP_SESSION *session) return; } -/* test to see if we can lock the specified file */ -static int is_locked(const char *filename) -{ - int fd; - if (filename != NULL) - { - errno = 0; - if ((fd = open(filename, O_RDWR, 0644)) < 0) - { - if (errno == ENOENT) - return 0; /* if file doesn't exist it cannot be locked */ - log_log(LOG_ERR, "cannot open lock file (%s): %s", filename, strerror(errno)); - exit(EXIT_FAILURE); - } - if (lockf(fd, F_TEST, 0) < 0) - { - if (close(fd)) - log_log(LOG_WARNING, "problem closing fd: %s", strerror(errno)); - return -1; - } - if (close(fd)) - log_log(LOG_WARNING, "problem closing fd: %s", strerror(errno)); - } - return 0; -} - -/* write the current process id to the specified file */ -static void create_pidfile(const char *filename) -{ - int fd; - char buffer[20]; - if (filename != NULL) - { - mkdirname(filename); - if ((fd = open(filename, O_RDWR | O_CREAT, 0644)) < 0) - { - log_log(LOG_ERR, "cannot create pid file (%s): %s", - filename, strerror(errno)); - exit(EXIT_FAILURE); - } - if (lockf(fd, F_TLOCK, 0) < 0) - { - log_log(LOG_ERR, "cannot lock pid file (%s): %s", - filename, strerror(errno)); - exit(EXIT_FAILURE); - } - if (ftruncate(fd, 0) < 0) - { - log_log(LOG_ERR, "cannot truncate pid file (%s): %s", - filename, strerror(errno)); - exit(EXIT_FAILURE); - } - mysnprintf(buffer, sizeof(buffer), "%d\n", (int)getpid()); - if (write(fd, buffer, strlen(buffer)) != (int)strlen(buffer)) - { - log_log(LOG_ERR, "error writing pid file (%s): %s", - filename, strerror(errno)); - exit(EXIT_FAILURE); - } - /* we keep the pidfile open so the lock remains valid */ - } -} - /* try to install signal handler and check result */ static void install_sighandler(int signum, void (*handler) (int)) { @@ -648,22 +465,10 @@ int main(int argc, char *argv[]) #ifdef HAVE_PTHREAD_TIMEDJOIN_NP struct timespec ts; #endif /* HAVE_PTHREAD_TIMEDJOIN_NP */ - /* close all file descriptors (except stdin/out/err) */ - daemonize_closefds(); + /* parse the command line */ parse_cmdline(argc, argv); - /* clean the environment */ -#ifdef HAVE_CLEARENV - if (clearenv() || putenv("HOME=/") || putenv("TMPDIR=/tmp") || - putenv("LDAPNOINIT=1")) - { - log_log(LOG_ERR, "clearing environment failed"); - exit(EXIT_FAILURE); - } -#else /* not HAVE_CLEARENV */ - /* this is a bit ugly */ - environ = sane_environment; -#endif /* not HAVE_CLEARENV */ + /* disable the nss_ldap module for this process */ disable_nss_ldap(); /* set LDAP log level */ @@ -671,66 +476,22 @@ int main(int argc, char *argv[]) exit(EXIT_FAILURE); /* read configuration file */ cfg_init(NSLCD_CONF_PATH); - /* set default mode for pidfile and socket */ - (void)umask((mode_t)0022); - /* see if someone already locked the pidfile - if --check option was given exit TRUE if daemon runs - (pidfile locked), FALSE otherwise */ - if (nslcd_checkonly) - { - if (is_locked(NSLCD_PIDFILE)) - { - log_log(LOG_DEBUG, "pidfile (%s) is locked", NSLCD_PIDFILE); - exit(EXIT_SUCCESS); - } - else - { - log_log(LOG_DEBUG, "pidfile (%s) is not locked", NSLCD_PIDFILE); - exit(EXIT_FAILURE); - } - } - /* change directory */ - if (chdir("/") != 0) - { - log_log(LOG_ERR, "chdir failed: %s", strerror(errno)); - exit(EXIT_FAILURE); - } - /* normal check for pidfile locked */ - if (is_locked(NSLCD_PIDFILE)) - { - log_log(LOG_ERR, "nslcd may already be active, cannot acquire lock (%s): %s", - NSLCD_PIDFILE, strerror(errno)); - exit(EXIT_FAILURE); - } - /* daemonize */ - if ((!nslcd_debugging) && (!nslcd_nofork)) - { - errno = 0; - if (daemonize_daemon() != 0) - { - log_log(LOG_ERR, "unable to daemonize: %s", strerror(errno)); - exit(EXIT_FAILURE); - } - } + /* intilialize logging */ if (!nslcd_debugging) { - daemonize_redirect_stdio(); log_startlogging(); } - /* write pidfile */ - create_pidfile(NSLCD_PIDFILE); /* log start */ log_log(LOG_INFO, "version %s starting", VERSION); /* install handler to close stuff off on exit and log notice */ if (atexit(exithandler)) { log_log(LOG_ERR, "atexit() failed: %s", strerror(errno)); - daemonize_ready(EXIT_FAILURE, "atexit() failed\n"); exit(EXIT_FAILURE); } - /* create socket */ - nslcd_serversocket = create_socket(NSLCD_SOCKET); + /* get socket */ + nslcd_serversocket = get_socket(); /* start subprocess to do invalidating if reconnect_invalidate is set */ for (i = 0; i < LM_NONE; i++) if (nslcd_cfg->reconnect_invalidate[i]) @@ -768,7 +529,6 @@ int main(int argc, char *argv[]) { log_log(LOG_ERR, "cannot setgid(%d): %s", (int)nslcd_cfg->gid, strerror(errno)); - daemonize_ready(EXIT_FAILURE, "cannot setgid()\n"); exit(EXIT_FAILURE); } log_log(LOG_DEBUG, "setgid(%d) done", (int)nslcd_cfg->gid); @@ -780,7 +540,6 @@ int main(int argc, char *argv[]) { log_log(LOG_ERR, "cannot setuid(%d): %s", (int)nslcd_cfg->uid, strerror(errno)); - daemonize_ready(EXIT_FAILURE, "cannot setuid()\n"); exit(EXIT_FAILURE); } log_log(LOG_DEBUG, "setuid(%d) done", (int)nslcd_cfg->uid); @@ -802,7 +561,6 @@ int main(int argc, char *argv[]) if (nslcd_threads == NULL) { log_log(LOG_CRIT, "main(): malloc() failed to allocate memory"); - daemonize_ready(EXIT_FAILURE, "malloc() failed to allocate memory\n"); exit(EXIT_FAILURE); } for (i = 0; i < nslcd_cfg->threads; i++) @@ -811,7 +569,6 @@ int main(int argc, char *argv[]) { log_log(LOG_ERR, "unable to start worker thread %d: %s", i, strerror(errno)); - daemonize_ready(EXIT_FAILURE, "unable to start worker thread\n"); exit(EXIT_FAILURE); } } @@ -825,8 +582,6 @@ int main(int argc, char *argv[]) install_sighandler(SIGTERM, sig_handler); install_sighandler(SIGUSR1, sig_handler); install_sighandler(SIGUSR2, SIG_IGN); - /* signal the starting process to exit because we can provide services now */ - daemonize_ready(EXIT_SUCCESS, NULL); /* wait until we received a signal */ while ((nslcd_receivedsignal == 0) || (nslcd_receivedsignal == SIGUSR1)) { |