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
chroot_uid(const char * root_dir,const char * user_name)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