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
This commit is contained in:
pjd 2011-01-28 22:33:47 +00:00
parent b285997797
commit 1d4238ea6d
3 changed files with 74 additions and 0 deletions

View File

@ -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"

View File

@ -38,6 +38,8 @@ __FBSDID("$FreeBSD$");
#include <assert.h>
#include <errno.h>
#include <fcntl.h>
#include <pwd.h>
#include <unistd.h>
#include <pjdlog.h>
@ -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);
}

View File

@ -47,5 +47,6 @@
int provinfo(struct hast_resource *res, bool dowrite);
const char *role2str(int role);
int drop_privs(void);
#endif /* !_SUBR_H_ */