Author: pjd
Date: Fri Jan 28 22:33:47 2011
New Revision: 218048
URL: http://svn.freebsd.org/changeset/base/218048

Log:
  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

Modified:
  head/sbin/hastd/hast.h
  head/sbin/hastd/subr.c
  head/sbin/hastd/subr.h

Modified: head/sbin/hastd/hast.h
==============================================================================
--- head/sbin/hastd/hast.h      Fri Jan 28 22:29:38 2011        (r218047)
+++ head/sbin/hastd/hast.h      Fri Jan 28 22:33:47 2011        (r218048)
@@ -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"

Modified: head/sbin/hastd/subr.c
==============================================================================
--- head/sbin/hastd/subr.c      Fri Jan 28 22:29:38 2011        (r218047)
+++ head/sbin/hastd/subr.c      Fri Jan 28 22:33:47 2011        (r218048)
@@ -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);
+}

Modified: head/sbin/hastd/subr.h
==============================================================================
--- head/sbin/hastd/subr.h      Fri Jan 28 22:29:38 2011        (r218047)
+++ head/sbin/hastd/subr.h      Fri Jan 28 22:33:47 2011        (r218048)
@@ -47,5 +47,6 @@
 
 int provinfo(struct hast_resource *res, bool dowrite);
 const char *role2str(int role);
+int drop_privs(void);
 
 #endif /* !_SUBR_H_ */
_______________________________________________
svn-src-head@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-head
To unsubscribe, send any mail to "svn-src-head-unsubscr...@freebsd.org"

Reply via email to