]> CyberLeo.Net >> Repos - FreeBSD/stable/10.git/blob - usr.sbin/jexec/jexec.c
MFC r322124:
[FreeBSD/stable/10.git] / usr.sbin / jexec / jexec.c
1 /*-
2  * Copyright (c) 2003 Mike Barcroft <mike@FreeBSD.org>
3  * Copyright (c) 2008 Bjoern A. Zeeb <bz@FreeBSD.org>
4  * All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  * 1. Redistributions of source code must retain the above copyright
10  *    notice, this list of conditions and the following disclaimer.
11  * 2. Redistributions in binary form must reproduce the above copyright
12  *    notice, this list of conditions and the following disclaimer in the
13  *    documentation and/or other materials provided with the distribution.
14  *
15  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25  * SUCH DAMAGE.
26  *
27  * $FreeBSD$
28  */
29
30 #include <sys/param.h>
31 #include <sys/jail.h>
32 #include <sys/socket.h>
33 #include <sys/sysctl.h>
34
35 #include <arpa/inet.h>
36 #include <netinet/in.h>
37
38 #include <err.h>
39 #include <errno.h>
40 #include <jail.h>
41 #include <limits.h>
42 #include <login_cap.h>
43 #include <paths.h>
44 #include <pwd.h>
45 #include <stdio.h>
46 #include <stdlib.h>
47 #include <string.h>
48 #include <unistd.h>
49
50 extern char **environ;
51
52 static void     get_user_info(const char *username, const struct passwd **pwdp,
53     login_cap_t **lcapp);
54 static void     usage(void);
55
56 int
57 main(int argc, char *argv[])
58 {
59         int jid;
60         login_cap_t *lcap = NULL;
61         int ch, clean, uflag, Uflag;
62         char *cleanenv;
63         const struct passwd *pwd = NULL;
64         const char *username, *shell, *term;
65
66         ch = clean = uflag = Uflag = 0;
67         username = NULL;
68
69         while ((ch = getopt(argc, argv, "lnu:U:")) != -1) {
70                 switch (ch) {
71                 case 'l':
72                         clean = 1;
73                         break;
74                 case 'n':
75                         /* Specified name, now unused */
76                         break;
77                 case 'u':
78                         username = optarg;
79                         uflag = 1;
80                         break;
81                 case 'U':
82                         username = optarg;
83                         Uflag = 1;
84                         break;
85                 default:
86                         usage();
87                 }
88         }
89         argc -= optind;
90         argv += optind;
91         if (argc < 1)
92                 usage();
93         if (uflag && Uflag)
94                 usage();
95         if (uflag || (clean && !Uflag))
96                 /* User info from the home environment */
97                 get_user_info(username, &pwd, &lcap);
98
99         /* Attach to the jail */
100         jid = jail_getid(argv[0]);
101         if (jid < 0)
102                 errx(1, "%s", jail_errmsg);
103         if (jail_attach(jid) == -1)
104                 err(1, "jail_attach(%d)", jid);
105         if (chdir("/") == -1)
106                 err(1, "chdir(): /");
107
108         /* Set up user environment */
109         if (clean || username != NULL) {
110                 if (Uflag)
111                         /* User info from the jail environment */
112                         get_user_info(username, &pwd, &lcap);
113                 if (clean) {
114                         term = getenv("TERM");
115                         cleanenv = NULL;
116                         environ = &cleanenv;
117                         setenv("PATH", "/bin:/usr/bin", 1);
118                         if (term != NULL)
119                                 setenv("TERM", term, 1);
120                 }
121                 if (setgid(pwd->pw_gid) != 0)
122                         err(1, "setgid");
123                 if (setusercontext(lcap, pwd, pwd->pw_uid, username
124                     ? LOGIN_SETALL & ~LOGIN_SETGROUP & ~LOGIN_SETLOGIN
125                     : LOGIN_SETPATH | LOGIN_SETENV) != 0)
126                         err(1, "setusercontext");
127                 login_close(lcap);
128                 setenv("USER", pwd->pw_name, 1);
129                 setenv("HOME", pwd->pw_dir, 1);
130                 setenv("SHELL",
131                     *pwd->pw_shell ? pwd->pw_shell : _PATH_BSHELL, 1);
132                 if (clean && chdir(pwd->pw_dir) < 0)
133                         err(1, "chdir: %s", pwd->pw_dir);
134                 endpwent();
135         }
136
137         /* Run the specified command, or the shell */
138         if (argc > 1) {
139                 if (execvp(argv[1], argv + 1) < 0)
140                         err(1, "execvp: %s", argv[1]);
141         } else {
142                 if (!(shell = getenv("SHELL")))
143                         shell = _PATH_BSHELL;
144                 if (execlp(shell, shell, "-i", NULL) < 0)
145                         err(1, "execlp: %s", shell);
146         }
147         exit(0);
148 }
149
150 static void
151 get_user_info(const char *username, const struct passwd **pwdp,
152     login_cap_t **lcapp)
153 {
154         uid_t uid;
155         const struct passwd *pwd;
156
157         errno = 0;
158         if (username) {
159                 pwd = getpwnam(username);
160                 if (pwd == NULL) {
161                         if (errno)
162                                 err(1, "getpwnam: %s", username);
163                         else
164                                 errx(1, "%s: no such user", username);
165                 }
166         } else {
167                 uid = getuid();
168                 pwd = getpwuid(uid);
169                 if (pwd == NULL) {
170                         if (errno)
171                                 err(1, "getpwuid: %d", uid);
172                         else
173                                 errx(1, "unknown uid: %d", uid);
174                 }
175         }
176         *pwdp = pwd;
177         *lcapp = login_getpwclass(pwd);
178         if (*lcapp == NULL)
179                 err(1, "getpwclass: %s", pwd->pw_name);
180         if (initgroups(pwd->pw_name, pwd->pw_gid) < 0)
181                 err(1, "initgroups: %s", pwd->pw_name);
182 }
183
184 static void
185 usage(void)
186 {
187
188         fprintf(stderr, "%s\n",
189             "usage: jexec [-l] [-u username | -U username] jail [command ...]");
190         exit(1); 
191 }