2dfa52b52de9333dc288855d914c342dd7b07990
[shells] / chrootsh.c
1 /* -*-c-*-
2 *
3 * $Id: chrootsh.c,v 1.1 1999/04/20 00:19:04 mdw Exp $
4 *
5 * Chroot gaol shell
6 *
7 * (c) 1999 EBI
8 */
9
10 /*----- Licensing notice --------------------------------------------------*
11 *
12 * This file is part of Chroot shell.
13 *
14 * chrootsh is free software; you can redistribute it and/or modify
15 * it under the terms of the GNU General Public License as published by
16 * the Free Software Foundation; either version 2 of the License, or
17 * (at your option) any later version.
18 *
19 * chrootsh is distributed in the hope that it will be useful,
20 * but WITHOUT ANY WARRANTY; without even the implied warranty of
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 * GNU General Public License for more details.
23 *
24 * You should have received a copy of the GNU General Public License
25 * along with chrootsh; if not, write to the Free Software Foundation,
26 * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
27 */
28
29 /*----- Revision history --------------------------------------------------*
30 *
31 * $Log: chrootsh.c,v $
32 * Revision 1.1 1999/04/20 00:19:04 mdw
33 * Initial revision
34 *
35 */
36
37 /*----- Header files ------------------------------------------------------*/
38
39 #include <errno.h>
40 #include <stdio.h>
41 #include <stdlib.h>
42 #include <string.h>
43
44 #include <sys/types.h>
45 #include <unistd.h>
46 #include <pwd.h>
47
48 extern char **environ;
49
50 /*----- Main code ---------------------------------------------------------*/
51
52 #ifndef CHROOTSH_PATH
53 # define CHROOTSH_PATH "/usr/bin/chrootsh"
54 #endif
55
56 static const char *quis = "chrootsh";
57
58 static void *xmalloc(size_t sz)
59 {
60 void *p = malloc(sz);
61 if (!p) {
62 fprintf(stderr, "%s: not enough memory\n", quis);
63 exit(EXIT_FAILURE);
64 }
65 return (p);
66 }
67
68 static char *xstrdup(const char *p)
69 {
70 size_t sz = strlen(p) + 1;
71 char *q = xmalloc(sz);
72 memcpy(q, p, sz);
73 return (q);
74 }
75
76 int main(int argc, char *argv[])
77 {
78 struct passwd *pw;
79 uid_t me = getuid();
80 char **env;
81 char **av;
82
83 /* --- Resolve the program name --- */
84
85 {
86 char *p, *q;
87 p = argv[0];
88 for (q = argv[0]; *q; q++) {
89 if (*q == '/')
90 p = q + 1;
91 }
92 quis = p;
93 }
94
95 /* --- Check the user is meant to be chrooted --- */
96
97 pw = getpwuid(me);
98 if (!pw) {
99 fprintf(stderr, "%s: you don't exist. Go away.\n", quis);
100 exit(EXIT_FAILURE);
101 }
102 if (strcmp(pw->pw_shell, CHROOTSH_PATH) != 0) {
103 fprintf(stderr, "%s: you aren't a chrooted user\n", quis);
104 exit(EXIT_FAILURE);
105 }
106 endpwent();
107
108 /* --- Chroot the user --- */
109
110 {
111 char *p = xstrdup(pw->pw_dir);
112 char *q = strstr(p, "/./");
113 if (q)
114 *q = 0;
115
116 if (chdir(p) || chroot(p)) {
117 fprintf(stderr, "%s: couldn't call chroot: %s", quis, strerror(errno));
118 exit(EXIT_FAILURE);
119 }
120 setuid(me);
121 free(p);
122 }
123
124 /* --- Read the new password block --- */
125
126 {
127 char *p = xstrdup(pw->pw_name);
128 pw = getpwnam(p);
129 free(p);
130 if (!pw) {
131 fprintf(stderr, "%s: you don't exist in the gaol\n", quis);
132 exit(EXIT_FAILURE);
133 }
134 endpwent();
135 }
136
137 /* --- Now fiddle with environment strings and suchlike --- */
138
139 {
140 size_t n;
141 for (n = 0; environ[n]; n++)
142 ;
143 env = xmalloc((n + 1) * sizeof(char *));
144
145 for (n = 0; environ[n]; n++) {
146 if (strncmp(environ[n], "HOME=", 5) == 0) {
147 char *p = xmalloc(6 + strlen(pw->pw_dir));
148 sprintf(p, "HOME=%s", pw->pw_dir);
149 env[n] = p;
150 } else if (strncmp(environ[n], "SHELL=", 6) == 0) {
151 char *p = xmalloc(7 + strlen(pw->pw_shell));
152 sprintf(p, "SHELL=%s", pw->pw_shell);
153 env[n] = p;
154 } else
155 env[n] = environ[n];
156 }
157 env[n] = 0;
158 }
159
160 /* --- Finally, sort the argument list --- */
161
162 {
163 char *p, *q;
164 int i;
165
166 av = xmalloc((argc + 1) * sizeof(char *));
167 p = pw->pw_shell;
168 for (q = p; *q; q++) {
169 if (*q == '/')
170 p = q + 1;
171 }
172 if (argv[0][0] == '-') {
173 q = xmalloc(2 + strlen(p));
174 *q = '-';
175 strcpy(q + 1, p);
176 av[0] = q;
177 } else
178 av[0] = p;
179
180 for (i = 1; i <= argc; i++)
181 av[i] = argv[i];
182 }
183
184 /* --- Change directory (again) --- */
185
186 if (chdir(pw->pw_dir))
187 fprintf(stderr, "No directory, logging in with HOME=/\n");
188
189 /* --- Run the real shell --- */
190
191 execve(pw->pw_shell, av, env);
192 fprintf(stderr, "%s: couldn't exec `%s': %s",
193 quis, pw->pw_shell, strerror(errno));
194 return (EXIT_FAILURE);
195 }
196
197 /*----- That's all, folks -------------------------------------------------*/