3 * $Id: chrootsh.c,v 1.4 1999/04/22 00:30:27 mdw Exp $
7 * (c) 1999 Mark Wooding
10 /*----- Licensing notice --------------------------------------------------*
12 * This program is free software; you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License as published by
14 * the Free Software Foundation; either version 2 of the License, or
15 * (at your option) any later version.
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software Foundation,
24 * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
27 /*----- Revision history --------------------------------------------------*
29 * $Log: chrootsh.c,v $
30 * Revision 1.4 1999/04/22 00:30:27 mdw
31 * Miscellanous tidying and security fixes. Lots of thanks due to Clive
34 * Revision 1.3 1999/04/21 22:52:43 mdw
35 * Added a pile of syslog stuff, so that admins can see what this thing is
38 * Revision 1.2 1999/04/21 09:07:55 mdw
39 * Fiddle with copyright messages so that they're correct.
41 * Revision 1.1.1.1 1999/04/20 00:19:04 mdw
46 /*----- Header files ------------------------------------------------------*/
53 #include <sys/types.h>
58 extern char **environ
;
60 /*----- Main code ---------------------------------------------------------*/
63 # define CHROOTSH_PATH "/usr/bin/chrootsh"
66 static const char *quis
= "chrootsh";
68 static void *xmalloc(size_t sz
)
73 fprintf(stderr
, "%s: not enough memory\n", quis
);
79 static char *xstrdup(const char *p
)
81 size_t sz
= strlen(p
) + 1;
82 char *q
= xmalloc(sz
);
87 int main(int argc
, char *argv
[])
95 /* --- Resolve the program name --- */
100 for (q
= argv
[0]; *q
; q
++) {
107 openlog(quis
, LOG_PID
| LOG_NDELAY
, LOG_DAEMON
);
110 /* --- Check the user is meant to be chrooted --- */
113 uid_t eff
= geteuid();
118 syslog(LOG_ERR
, "executed by non-existant user (uid = %i)", (int)me
);
119 fprintf(stderr
, "%s: you don't exist. Go away.\n", quis
);
122 if (strcmp(pw
->pw_shell
, CHROOTSH_PATH
) != 0) {
123 syslog(LOG_ERR
, "executed by non-chrooted user `%s'", pw
->pw_name
);
124 fprintf(stderr
, "%s: you aren't a chrooted user\n", quis
);
131 /* --- Chroot the user --- */
134 char *p
= xstrdup(pw
->pw_dir
);
135 char *q
= strstr(p
, "/./");
139 if (chdir(p
) || chroot(p
)) {
141 syslog(LOG_ERR
, "error entering chroot gaol: %m");
143 fprintf(stderr
, "%s: couldn't call chroot: %s\n", quis
, strerror(e
));
150 /* --- Read the new password block --- */
152 myname
= xstrdup(pw
->pw_name
);
153 pw
= getpwnam(myname
);
156 "configuration error: user `%s' not defined in gaol", myname
);
157 fprintf(stderr
, "%s: you don't exist in the gaol\n", quis
);
162 /* --- Now fiddle with environment strings and suchlike --- */
167 for (n
= 0; environ
[n
]; n
++)
169 env
= xmalloc((n
+ 1) * sizeof(char *));
171 for (n
= 0; environ
[n
]; n
++) {
172 if (strncmp(environ
[n
], "HOME=", 5) == 0) {
173 char *p
= xmalloc(6 + strlen(pw
->pw_dir
));
174 sprintf(p
, "HOME=%s", pw
->pw_dir
);
177 } else if (strncmp(environ
[n
], "SHELL=", 6) == 0) {
178 char *p
= xmalloc(7 + strlen(pw
->pw_shell
));
179 sprintf(p
, "SHELL=%s", pw
->pw_shell
);
186 /* --- Change directory (again) --- */
188 if (chdir(pw
->pw_dir
)) {
193 fprintf(stderr
, "No directory, logging in with HOME=/\n");
197 /* --- Finally, sort the argument list --- */
203 av
= xmalloc((argc
+ 1) * sizeof(char *));
205 for (q
= p
; *q
; q
++) {
209 if (argv
[0][0] == '-') {
210 q
= xmalloc(2 + strlen(p
));
217 for (i
= 1; i
<= argc
; i
++)
221 /* --- Run the real shell --- */
223 syslog(LOG_INFO
, "chroot user `%s' logged in ok", myname
);
225 execve(pw
->pw_shell
, av
, env
);
226 fprintf(stderr
, "%s: couldn't exec `%s': %s\n",
227 quis
, pw
->pw_shell
, strerror(errno
));
228 return (EXIT_FAILURE
);
231 /*----- That's all, folks -------------------------------------------------*/