summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorpjd <pjd@FreeBSD.org>2011-01-28 22:33:47 +0000
committerpjd <pjd@FreeBSD.org>2011-01-28 22:33:47 +0000
commit1d4238ea6d7bb3df80ae2d80f0563eb3b688c32f (patch)
tree9e1f37d4547c7063d6f249104a2aa450d7ef0cdb
parentb28599779707d219cdb016a8fbde16168a52faed (diff)
downloadFreeBSD-src-1d4238ea6d7bb3df80ae2d80f0563eb3b688c32f.zip
FreeBSD-src-1d4238ea6d7bb3df80ae2d80f0563eb3b688c32f.tar.gz
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
-rw-r--r--sbin/hastd/hast.h1
-rw-r--r--sbin/hastd/subr.c72
-rw-r--r--sbin/hastd/subr.h1
3 files changed, 74 insertions, 0 deletions
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 <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);
+}
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_ */
OpenPOWER on IntegriCloud