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:
parent
1b0e519476
commit
49499e981e
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=218048
@ -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"
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -47,5 +47,6 @@
|
||||
|
||||
int provinfo(struct hast_resource *res, bool dowrite);
|
||||
const char *role2str(int role);
|
||||
int drop_privs(void);
|
||||
|
||||
#endif /* !_SUBR_H_ */
|
||||
|
Loading…
Reference in New Issue
Block a user