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