diff -purN openntpd-3.7p1-orig/configure openntpd-3.7p1/configure --- openntpd-3.7p1-orig/configure Mon May 23 07:25:42 2005 +++ openntpd-3.7p1/configure Thu Jun 23 08:33:57 2005 @@ -8688,7 +8688,7 @@ if test "${with_ssl_dir+set}" = set; the fi; -LIBS="-lcrypto $LIBS" +LIBS="-lcrypto -lcap $LIBS" cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF diff -purN openntpd-3.7p1-orig/ntpd.c openntpd-3.7p1/ntpd.c --- openntpd-3.7p1-orig/ntpd.c Sun Mar 13 07:41:46 2005 +++ openntpd-3.7p1/ntpd.c Thu Jun 23 08:35:02 2005 @@ -23,6 +23,8 @@ RCSID("$Release: OpenNTPD "OPENNTPD_VERS #include #include #include +#include +#include #include #include #include @@ -82,6 +84,64 @@ usage(void) #define POLL_MAX 8 #define PFD_PIPE 0 +static void set_cap(uid_t uid, gid_t gid, char *captxt) +{ + cap_t caps; + + if (!captxt) { + fprintf(stderr, "ntpd: captxt == NULL\n"); + exit(EXIT_FAILURE); + } + + if (prctl(PR_SET_KEEPCAPS, 1)) { + fprintf(stderr, "ntpd: prctl failed\n"); + exit(EXIT_FAILURE); + } + + if (setgroups(0, NULL) == -1) { + fprintf(stderr, "ntpd: setgroups failed\n"); + exit(EXIT_FAILURE); + } + + if (setegid(gid) == -1 || seteuid(uid) == -1) { + fprintf(stderr, "ntpd: seteuid failed\n"); + exit(EXIT_FAILURE); + } + + caps = cap_from_text(captxt); + if (!caps) { + fprintf(stderr, "ntpd: cap_from_text failed\n"); + exit(EXIT_FAILURE); + } + + if (cap_set_proc(caps) == -1) { + fprintf(stderr, "ntpd: cap_set_proc failed\n"); + exit(EXIT_FAILURE); + } + + cap_free(caps); +} + +static void drop_root(uid_t uid, gid_t gid, char *captxt) +{ + if (!captxt) { + fprintf(stderr, "ntpd: captxt == NULL\n"); + exit(EXIT_FAILURE); + } + + if (uid == 0 || gid == 0) { + fprintf(stderr, "ntpd: attempt to drop root to root!!\n"); + exit(EXIT_FAILURE); + } + + set_cap(uid, gid, captxt); + + if (setregid(gid, gid) == -1 || setreuid(uid, uid) == -1) { + fprintf(stderr, "ntpd: failed to drop root!\n"); + exit(EXIT_FAILURE); + } +} + int main(int argc, char *argv[]) { @@ -92,6 +152,7 @@ main(int argc, char *argv[]) int ch, nfds, timeout = INFTIM; int pipe_chld[2]; extern char *__progname; + struct passwd *pw; __progname = _compat_get_progname(argv[0]); @@ -167,6 +228,11 @@ main(int argc, char *argv[]) fatal(NULL); imsg_init(ibuf, pipe_chld[0]); + if ((pw = getpwnam(NTPD_USER)) == NULL) + fatal(NULL); + + drop_root(pw->pw_uid, pw->pw_gid, "cap_sys_time=ep"); + while (quit == 0) { pfd[PFD_PIPE].fd = ibuf->fd; pfd[PFD_PIPE].events = POLLIN;