From 1d4238ea6d7bb3df80ae2d80f0563eb3b688c32f Mon Sep 17 00:00:00 2001 From: pjd Date: Fri, 28 Jan 2011 22:33:47 +0000 Subject: Implement function that drops privileges by: - chrooting to /var/empty (user hast home directory), - setting groups to 'hast' (user hast primary group), - setting real group id, effective group id and saved group id to 'hast', - setting real user id, effective user id and saved user id to 'hast'. At the end verify that those operations where successfull. MFC after: 1 week --- sbin/hastd/hast.h | 1 + sbin/hastd/subr.c | 72 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ sbin/hastd/subr.h | 1 + 3 files changed, 74 insertions(+) (limited to 'sbin') diff --git a/sbin/hastd/hast.h b/sbin/hastd/hast.h index b86ed62..dbbe0da 100644 --- a/sbin/hastd/hast.h +++ b/sbin/hastd/hast.h @@ -81,6 +81,7 @@ #define HIO_FLUSH 4 #define HIO_KEEPALIVE 5 +#define HAST_USER "hast" #define HAST_TIMEOUT 5 #define HAST_CONFIG "/etc/hast.conf" #define HAST_CONTROL "/var/run/hastctl" diff --git a/sbin/hastd/subr.c b/sbin/hastd/subr.c index 16ea93f..ddd4a5b 100644 --- a/sbin/hastd/subr.c +++ b/sbin/hastd/subr.c @@ -38,6 +38,8 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include +#include #include @@ -116,3 +118,73 @@ role2str(int role) } return ("unknown"); } + +int +drop_privs(void) +{ + struct passwd *pw; + uid_t ruid, euid, suid; + gid_t rgid, egid, sgid; + gid_t gidset[1]; + + /* + * According to getpwnam(3) we have to clear errno before calling the + * function to be able to distinguish between an error and missing + * entry (with is not treated as error by getpwnam(3)). + */ + errno = 0; + pw = getpwnam(HAST_USER); + if (pw == NULL) { + if (errno != 0) { + KEEP_ERRNO(pjdlog_errno(LOG_ERR, + "Unable to find info about '%s' user", HAST_USER)); + return (-1); + } else { + pjdlog_error("'%s' user doesn't exist.", HAST_USER); + errno = ENOENT; + return (-1); + } + } + if (chroot(pw->pw_dir) == -1) { + KEEP_ERRNO(pjdlog_errno(LOG_ERR, + "Unable to change root directory to %s", pw->pw_dir)); + return (-1); + } + PJDLOG_VERIFY(chdir("/") == 0); + gidset[0] = pw->pw_gid; + if (setgroups(1, gidset) == -1) { + KEEP_ERRNO(pjdlog_errno(LOG_ERR, + "Unable to set groups to gid %u", + (unsigned int)pw->pw_gid)); + return (-1); + } + if (setgid(pw->pw_gid) == -1) { + KEEP_ERRNO(pjdlog_errno(LOG_ERR, "Unable to set gid to %u", + (unsigned int)pw->pw_gid)); + return (-1); + } + if (setuid(pw->pw_uid) == -1) { + KEEP_ERRNO(pjdlog_errno(LOG_ERR, "Unable to set uid to %u", + (unsigned int)pw->pw_uid)); + return (-1); + } + + /* + * Better be sure that everything succeeded. + */ + PJDLOG_VERIFY(getresuid(&ruid, &euid, &suid) == 0); + PJDLOG_VERIFY(ruid == pw->pw_uid); + PJDLOG_VERIFY(euid == pw->pw_uid); + PJDLOG_VERIFY(suid == pw->pw_uid); + PJDLOG_VERIFY(getresgid(&rgid, &egid, &sgid) == 0); + PJDLOG_VERIFY(rgid == pw->pw_gid); + PJDLOG_VERIFY(egid == pw->pw_gid); + PJDLOG_VERIFY(sgid == pw->pw_gid); + PJDLOG_VERIFY(getgroups(0, NULL) == 1); + PJDLOG_VERIFY(getgroups(1, gidset) == 1); + PJDLOG_VERIFY(gidset[0] == pw->pw_gid); + + pjdlog_info("Privileges successfully dropped."); + + return (0); +} diff --git a/sbin/hastd/subr.h b/sbin/hastd/subr.h index c486f5c..913d2a4 100644 --- a/sbin/hastd/subr.h +++ b/sbin/hastd/subr.h @@ -47,5 +47,6 @@ int provinfo(struct hast_resource *res, bool dowrite); const char *role2str(int role); +int drop_privs(void); #endif /* !_SUBR_H_ */ -- cgit v1.1