diff options
Diffstat (limited to 'src/util/chroot_uid.c')
-rw-r--r-- | src/util/chroot_uid.c | 88 |
1 files changed, 88 insertions, 0 deletions
diff --git a/src/util/chroot_uid.c b/src/util/chroot_uid.c new file mode 100644 index 0000000..4a7660f --- /dev/null +++ b/src/util/chroot_uid.c @@ -0,0 +1,88 @@ +/*++ +/* NAME +/* chroot_uid 3 +/* SUMMARY +/* limit possible damage a process can do +/* SYNOPSIS +/* #include <chroot_uid.h> +/* +/* void chroot_uid(root_dir, user_name) +/* const char *root_dir; +/* const char *user_name; +/* DESCRIPTION +/* \fBchroot_uid\fR changes the process root to \fIroot_dir\fR and +/* changes process privileges to those of \fIuser_name\fR. +/* DIAGNOSTICS +/* System call errors are reported via the msg(3) interface. +/* All errors are fatal. +/* LICENSE +/* .ad +/* .fi +/* The Secure Mailer license must be distributed with this software. +/* AUTHOR(S) +/* Wietse Venema +/* IBM T.J. Watson Research +/* P.O. Box 704 +/* Yorktown Heights, NY 10598, USA +/*--*/ + +/* System library. */ + +#include <sys_defs.h> +#include <pwd.h> +#include <unistd.h> +#include <grp.h> + +/* Utility library. */ + +#include "msg.h" +#include "chroot_uid.h" + +/* chroot_uid - restrict the damage that this program can do */ + +void chroot_uid(const char *root_dir, const char *user_name) +{ + struct passwd *pwd; + uid_t uid; + gid_t gid; + + /* + * Look up the uid/gid before entering the jail, and save them so they + * can't be clobbered. Set up the primary and secondary groups. + */ + if (user_name != 0) { + if ((pwd = getpwnam(user_name)) == 0) + msg_fatal("unknown user: %s", user_name); + uid = pwd->pw_uid; + gid = pwd->pw_gid; + if (setgid(gid) < 0) + msg_fatal("setgid(%ld): %m", (long) gid); + if (initgroups(user_name, gid) < 0) + msg_fatal("initgroups: %m"); + } + + /* + * Enter the jail. + */ + if (root_dir) { + if (chroot(root_dir)) + msg_fatal("chroot(%s): %m", root_dir); + if (chdir("/")) + msg_fatal("chdir(/): %m"); + } + + /* + * Drop the user privileges. + */ + if (user_name != 0) + if (setuid(uid) < 0) + msg_fatal("setuid(%ld): %m", (long) uid); + + /* + * Give the desperate developer a clue of what is happening. + */ + if (msg_verbose > 1) + msg_info("chroot %s user %s", + root_dir ? root_dir : "(none)", + user_name ? user_name : "(none)"); +} |