1/*++ 2/* NAME 3/* chroot_uid 3 4/* SUMMARY 5/* limit possible damage a process can do 6/* SYNOPSIS 7/* #include <chroot_uid.h> 8/* 9/* void chroot_uid(root_dir, user_name) 10/* const char *root_dir; 11/* const char *user_name; 12/* DESCRIPTION 13/* \fBchroot_uid\fR changes the process root to \fIroot_dir\fR and 14/* changes process privileges to those of \fIuser_name\fR. 15/* DIAGNOSTICS 16/* System call errors are reported via the msg(3) interface. 17/* All errors are fatal. 18/* LICENSE 19/* .ad 20/* .fi 21/* The Secure Mailer license must be distributed with this software. 22/* AUTHOR(S) 23/* Wietse Venema 24/* IBM T.J. Watson Research 25/* P.O. Box 704 26/* Yorktown Heights, NY 10598, USA 27/*--*/ 28 29/* System library. */ 30 31#include <sys_defs.h> 32#include <pwd.h> 33#include <unistd.h> 34#include <grp.h> 35 36/* Utility library. */ 37 38#include "msg.h" 39#include "chroot_uid.h" 40 41/* chroot_uid - restrict the damage that this program can do */ 42 43void chroot_uid(const char *root_dir, const char *user_name) 44{ 45 struct passwd *pwd; 46 uid_t uid; 47 gid_t gid; 48 49 /* 50 * Look up the uid/gid before entering the jail, and save them so they 51 * can't be clobbered. Set up the primary and secondary groups. 52 */ 53 if (user_name != 0) { 54 if ((pwd = getpwnam(user_name)) == 0) 55 msg_fatal("unknown user: %s", user_name); 56 uid = pwd->pw_uid; 57 gid = pwd->pw_gid; 58 if (setgid(gid) < 0) 59 msg_fatal("setgid(%ld): %m", (long) gid); 60 if (initgroups(user_name, gid) < 0) 61 msg_fatal("initgroups: %m"); 62 } 63 64 /* 65 * Enter the jail. 66 */ 67 if (root_dir) { 68 if (chroot(root_dir)) 69 msg_fatal("chroot(%s): %m", root_dir); 70 if (chdir("/")) 71 msg_fatal("chdir(/): %m"); 72 } 73 74 /* 75 * Drop the user privileges. 76 */ 77 if (user_name != 0) 78 if (setuid(uid) < 0) 79 msg_fatal("setuid(%ld): %m", (long) uid); 80 81 /* 82 * Give the desperate developer a clue of what is happening. 83 */ 84 if (msg_verbose > 1) 85 msg_info("chroot %s user %s", 86 root_dir ? root_dir : "(none)", 87 user_name ? user_name : "(none)"); 88} 89