]> git.ipfire.org Git - thirdparty/ntp.git/commitdiff
[Bug 3121] Drop root privileges for the forked DNS worker
authorJuergen Perlinger <perlinger@ntp.org>
Sat, 14 Apr 2018 06:18:38 +0000 (08:18 +0200)
committerJuergen Perlinger <perlinger@ntp.org>
Sat, 14 Apr 2018 06:18:38 +0000 (08:18 +0200)
bk: 5ad19d3eFgYJ5hqK3V8RCuVU28F74w

ChangeLog
libntp/work_fork.c
ntpd/ntpd.c
sntp/main.c

index 6558787a9a353eb1eb61cc7cd179fb5683ff2566..323c27b8af704f60d37ce77c1a89a088d898c0d3 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -27,6 +27,8 @@
   - initial patch by Hal Murray; also fixed refclock_report() trouble
 * [Bug 3456] Use uintptr_t rather than size_t to store an integer in a pointer
   - According to Brooks Davis, there was only one location <perlinger@ntp.org>
+* [Bug 3121] Drop root privileges for the forked DNS worker <perlinger@ntp.org>
+  - integrated patch by  Reinhard Max
 * [Bug 2821] minor build issues <perlinger@ntp.org>
   - applied patches by Christos Zoulas, including real bug fixes
 
index 2aa2d5cd3046ca4cb6da3e47cab9262b6cb913a7..cce686f239cc246b964d6a24e61650787ae8605b 100644 (file)
@@ -89,6 +89,8 @@ netwrite(
 }
 
 
+int set_user_group_ids(void);
+
 /* === functions === */
 /*
  * exit_worker()
@@ -592,6 +594,8 @@ fork_blocking_child(
        init_logging("ntp_intres", 0, FALSE);
        setup_logfile(NULL);
 
+       (void) set_user_group_ids();
+
        /*
         * And now back to the portable code
         */
index d4204efd8d39ea44a3563d8d3b81f807c812a35c..242d9f19e0bdae6c5b9984ae53633efc6b74cb8a 100644 (file)
@@ -182,7 +182,6 @@ char *group;                /* group to switch to */
 const char *chrootdir; /* directory to chroot to */
 uid_t sw_uid;
 gid_t sw_gid;
-char *endp;
 struct group *gr;
 struct passwd *pw;
 #endif /* HAVE_DROPROOT */
@@ -523,6 +522,217 @@ set_process_priority(void)
 }
 #endif /* !SIM */
 
+#ifndef SIM
+/*
+ * Detach from terminal (much like daemon())
+ * Nothe that this function calls exit()
+ */
+static void
+detach_from_terminal(
+       int pipe_fds[2],
+       long wait_sync,
+       const char *logfilename
+       )
+{
+       int rc;
+       int exit_code;
+#  if !defined(HAVE_SETSID) && !defined (HAVE_SETPGID) && defined(TIOCNOTTY)
+       int             fid;
+#  endif
+#  ifdef _AIX
+       struct sigaction sa;
+#  endif
+
+       rc = fork();
+       if (-1 == rc) {
+               exit_code = (errno) ? errno : -1;
+               msyslog(LOG_ERR, "fork: %m");
+               exit(exit_code);
+       }
+       if (rc > 0) {
+               /* parent */
+               exit_code = wait_child_sync_if(pipe_fds[0],
+                                              wait_sync);
+               exit(exit_code);
+       }
+
+       /*
+        * child/daemon
+        * close all open files excepting waitsync_fd_to_close.
+        * msyslog() unreliable until after init_logging().
+        */
+       closelog();
+       if (syslog_file != NULL) {
+               fclose(syslog_file);
+               syslog_file = NULL;
+               syslogit = TRUE;
+       }
+       close_all_except(waitsync_fd_to_close);
+       INSIST(0 == open("/dev/null", 0) && 1 == dup2(0, 1) \
+               && 2 == dup2(0, 2));
+
+       init_logging(progname, 0, TRUE);
+       /* we lost our logfile (if any) daemonizing */
+       setup_logfile(logfilename);
+
+#  ifdef SYS_DOMAINOS
+       {
+               uid_$t puid;
+               status_$t st;
+
+               proc2_$who_am_i(&puid);
+               proc2_$make_server(&puid, &st);
+       }
+#  endif       /* SYS_DOMAINOS */
+#  ifdef HAVE_SETSID
+       if (setsid() == (pid_t)-1)
+               msyslog(LOG_ERR, "setsid(): %m");
+#  elif defined(HAVE_SETPGID)
+       if (setpgid(0, 0) == -1)
+               msyslog(LOG_ERR, "setpgid(): %m");
+#  else                /* !HAVE_SETSID && !HAVE_SETPGID follows */
+#   ifdef TIOCNOTTY
+       fid = open("/dev/tty", 2);
+       if (fid >= 0) {
+               ioctl(fid, (u_long)TIOCNOTTY, NULL);
+               close(fid);
+       }
+#   endif      /* TIOCNOTTY */
+       ntp_setpgrp(0, getpid());
+#  endif       /* !HAVE_SETSID && !HAVE_SETPGID */
+#  ifdef _AIX
+       /* Don't get killed by low-on-memory signal. */
+       sa.sa_handler = catch_danger;
+       sigemptyset(&sa.sa_mask);
+       sa.sa_flags = SA_RESTART;
+       sigaction(SIGDANGER, &sa, NULL);
+#  endif       /* _AIX */
+
+       return;
+}
+
+/*
+ * Map user name/number to user ID
+*/
+static int
+map_user(
+       )
+{
+       char *endp;
+
+       if (isdigit((unsigned char)*user)) {
+               sw_uid = (uid_t)strtoul(user, &endp, 0);
+               if (*endp != '\0')
+                       goto getuser;
+
+               if ((pw = getpwuid(sw_uid)) != NULL) {
+                       free(user);
+                       user = estrdup(pw->pw_name);
+                       sw_gid = pw->pw_gid;
+               } else {
+                       errno = 0;
+                       msyslog(LOG_ERR, "Cannot find user ID %s", user);
+                       return 0;
+               }
+
+       } else {
+getuser:
+               errno = 0;
+               if ((pw = getpwnam(user)) != NULL) {
+                       sw_uid = pw->pw_uid;
+                       sw_gid = pw->pw_gid;
+               } else {
+                       if (errno)
+                               msyslog(LOG_ERR, "getpwnam(%s) failed: %m", user);
+                       else
+                               msyslog(LOG_ERR, "Cannot find user `%s'", user);
+                       return 0;
+               }
+       }
+
+       return 1;
+}
+
+/*
+ * Map group name/number to group ID
+*/
+static int
+map_group(
+       )
+{
+       char *endp;
+
+       if (isdigit((unsigned char)*group)) {
+               sw_gid = (gid_t)strtoul(group, &endp, 0);
+               if (*endp != '\0')
+                       goto getgroup;
+       } else {
+getgroup:
+               if ((gr = getgrnam(group)) != NULL) {
+                       sw_gid = gr->gr_gid;
+               } else {
+                       errno = 0;
+                       msyslog(LOG_ERR, "Cannot find group `%s'", group);
+                       return 0;
+               }
+       }
+
+       return 1;
+}
+
+/*
+ * Change (effective) user and group IDs, also initialize the supplementary group access list
+ */
+int
+set_user_group_ids(
+       )
+{
+       /* If the the user was already mapped, no need to map it again */
+       if ((NULL != user) && (0 == sw_uid)) {
+               if (0 == map_user())
+                       exit (-1);
+       }
+       /* same applies for the group */
+       if ((NULL != group) && (0 == sw_gid)) {
+               if (0 == map_group())
+                       exit (-1);
+       }
+
+       if (user && initgroups(user, sw_gid)) {
+               msyslog(LOG_ERR, "Cannot initgroups() to user `%s': %m", user);
+               return 0;
+       }
+       if (group && setgid(sw_gid)) {
+               msyslog(LOG_ERR, "Cannot setgid() to group `%s': %m", group);
+               return 0;
+       }
+       if (group && setegid(sw_gid)) {
+               msyslog(LOG_ERR, "Cannot setegid() to group `%s': %m", group);
+               return 0;
+       }
+       if (group) {
+               if (0 != setgroups(1, &sw_gid)) {
+                       msyslog(LOG_ERR, "setgroups(1, %d) failed: %m", sw_gid);
+                       return 0;
+               }
+       }
+       else if (pw)
+               if (0 != initgroups(pw->pw_name, pw->pw_gid)) {
+                       msyslog(LOG_ERR, "initgroups(<%s>, %d) filed: %m", pw->pw_name, pw->pw_gid);
+                       return 0;
+               }
+       if (user && setuid(sw_uid)) {
+               msyslog(LOG_ERR, "Cannot setuid() to user `%s': %m", user);
+               return 0;
+       }
+       if (user && seteuid(sw_uid)) {
+               msyslog(LOG_ERR, "Cannot seteuid() to user `%s': %m", user);
+               return 0;
+       }
+
+       return 1;
+}
+#endif /* !SIM */
 
 /*
  * Main program.  Initialize us, disconnect us from the tty if necessary,
@@ -549,12 +759,6 @@ ntpdmain(
        int             pipe_fds[2];
        int             rc;
        int             exit_code;
-#  ifdef _AIX
-       struct sigaction sa;
-#  endif
-#  if !defined(HAVE_SETSID) && !defined (HAVE_SETPGID) && defined(TIOCNOTTY)
-       int             fid;
-#  endif
 # endif        /* HAVE_WORKING_FORK*/
 # ifdef SCO5_CLOCK
        int             fd;
@@ -736,70 +940,7 @@ ntpdmain(
        if (!nofork) {
 
 # ifdef HAVE_WORKING_FORK
-               rc = fork();
-               if (-1 == rc) {
-                       exit_code = (errno) ? errno : -1;
-                       msyslog(LOG_ERR, "fork: %m");
-                       exit(exit_code);
-               }
-               if (rc > 0) {   
-                       /* parent */
-                       exit_code = wait_child_sync_if(pipe_fds[0],
-                                                      wait_sync);
-                       exit(exit_code);
-               }
-               
-               /*
-                * child/daemon 
-                * close all open files excepting waitsync_fd_to_close.
-                * msyslog() unreliable until after init_logging().
-                */
-               closelog();
-               if (syslog_file != NULL) {
-                       fclose(syslog_file);
-                       syslog_file = NULL;
-                       syslogit = TRUE;
-               }
-               close_all_except(waitsync_fd_to_close);
-               INSIST(0 == open("/dev/null", 0) && 1 == dup2(0, 1) \
-                       && 2 == dup2(0, 2));
-
-               init_logging(progname, 0, TRUE);
-               /* we lost our logfile (if any) daemonizing */
-               setup_logfile(logfilename);
-
-#  ifdef SYS_DOMAINOS
-               {
-                       uid_$t puid;
-                       status_$t st;
-
-                       proc2_$who_am_i(&puid);
-                       proc2_$make_server(&puid, &st);
-               }
-#  endif       /* SYS_DOMAINOS */
-#  ifdef HAVE_SETSID
-               if (setsid() == (pid_t)-1)
-                       msyslog(LOG_ERR, "setsid(): %m");
-#  elif defined(HAVE_SETPGID)
-               if (setpgid(0, 0) == -1)
-                       msyslog(LOG_ERR, "setpgid(): %m");
-#  else                /* !HAVE_SETSID && !HAVE_SETPGID follows */
-#   ifdef TIOCNOTTY
-               fid = open("/dev/tty", 2);
-               if (fid >= 0) {
-                       ioctl(fid, (u_long)TIOCNOTTY, NULL);
-                       close(fid);
-               }
-#   endif      /* TIOCNOTTY */
-               ntp_setpgrp(0, getpid());
-#  endif       /* !HAVE_SETSID && !HAVE_SETPGID */
-#  ifdef _AIX
-               /* Don't get killed by low-on-memory signal. */
-               sa.sa_handler = catch_danger;
-               sigemptyset(&sa.sa_mask);
-               sa.sa_flags = SA_RESTART;
-               sigaction(SIGDANGER, &sa, NULL);
-#  endif       /* _AIX */
+               detach_from_terminal(pipe_fds, wait_sync, logfilename);
 # endif                /* HAVE_WORKING_FORK */
        }
 
@@ -972,51 +1113,12 @@ ntpdmain(
 #  endif       /* HAVE_LINUX_CAPABILITIES || HAVE_SOLARIS_PRIVS */
 
                if (user != NULL) {
-                       if (isdigit((unsigned char)*user)) {
-                               sw_uid = (uid_t)strtoul(user, &endp, 0);
-                               if (*endp != '\0')
-                                       goto getuser;
-
-                               if ((pw = getpwuid(sw_uid)) != NULL) {
-                                       free(user);
-                                       user = estrdup(pw->pw_name);
-                                       sw_gid = pw->pw_gid;
-                               } else {
-                                       errno = 0;
-                                       msyslog(LOG_ERR, "Cannot find user ID %s", user);
-                                       exit (-1);
-                               }
-
-                       } else {
-getuser:
-                               errno = 0;
-                               if ((pw = getpwnam(user)) != NULL) {
-                                       sw_uid = pw->pw_uid;
-                                       sw_gid = pw->pw_gid;
-                               } else {
-                                       if (errno)
-                                               msyslog(LOG_ERR, "getpwnam(%s) failed: %m", user);
-                                       else
-                                               msyslog(LOG_ERR, "Cannot find user `%s'", user);
-                                       exit (-1);
-                               }
-                       }
+                       if (0 == map_user())
+                               exit (-1);
                }
                if (group != NULL) {
-                       if (isdigit((unsigned char)*group)) {
-                               sw_gid = (gid_t)strtoul(group, &endp, 0);
-                               if (*endp != '\0')
-                                       goto getgroup;
-                       } else {
-getgroup:
-                               if ((gr = getgrnam(group)) != NULL) {
-                                       sw_gid = gr->gr_gid;
-                               } else {
-                                       errno = 0;
-                                       msyslog(LOG_ERR, "Cannot find group `%s'", group);
-                                       exit (-1);
-                               }
-                       }
+                       if (0 == map_group())
+                               exit (-1);
                }
 
                if (chrootdir ) {
@@ -1050,37 +1152,8 @@ getgroup:
                        exit(-1);
                }
 #  endif /* HAVE_SOLARIS_PRIVS */
-               if (user && initgroups(user, sw_gid)) {
-                       msyslog(LOG_ERR, "Cannot initgroups() to user `%s': %m", user);
-                       exit (-1);
-               }
-               if (group && setgid(sw_gid)) {
-                       msyslog(LOG_ERR, "Cannot setgid() to group `%s': %m", group);
-                       exit (-1);
-               }
-               if (group && setegid(sw_gid)) {
-                       msyslog(LOG_ERR, "Cannot setegid() to group `%s': %m", group);
-                       exit (-1);
-               }
-               if (group) {
-                       if (0 != setgroups(1, &sw_gid)) {
-                               msyslog(LOG_ERR, "setgroups(1, %d) failed: %m", sw_gid);
-                               exit (-1);
-                       }
-               }
-               else if (pw)
-                       if (0 != initgroups(pw->pw_name, pw->pw_gid)) {
-                               msyslog(LOG_ERR, "initgroups(<%s>, %d) filed: %m", pw->pw_name, pw->pw_gid);
-                               exit (-1);
-                       }
-               if (user && setuid(sw_uid)) {
-                       msyslog(LOG_ERR, "Cannot setuid() to user `%s': %m", user);
-                       exit (-1);
-               }
-               if (user && seteuid(sw_uid)) {
-                       msyslog(LOG_ERR, "Cannot seteuid() to user `%s': %m", user);
-                       exit (-1);
-               }
+               if (0 == set_user_group_ids())
+                       exit(-1);
 
 #  if !defined(HAVE_LINUX_CAPABILITIES) && !defined(HAVE_SOLARIS_PRIVS)
                /*
index 098a696945c280bdce07fe07461a5aa27b5b4088..f0a7650ac718c102cf22b4360eff9d7ee55430ec 100644 (file)
@@ -1608,3 +1608,10 @@ gettimeofday_cached(
 #endif
 }
 
+/* Dummy function to satisfy libntp/work_fork.c */
+int
+set_user_group_ids(
+       )
+{
+    return 1;
+}