Expunge revision histories.
[shells] / chrootsh.c
index 2dfa52b..1a56e00 100644 (file)
@@ -1,39 +1,29 @@
 /* -*-c-*-
  *
- * $Id: chrootsh.c,v 1.1 1999/04/20 00:19:04 mdw Exp $
+ * $Id$
  *
  * Chroot gaol shell
  *
- * (c) 1999 EBI
+ * (c) 1999 Mark Wooding
  */
 
 /*----- Licensing notice --------------------------------------------------* 
  *
- * This file is part of Chroot shell.
- *
- * chrootsh is free software; you can redistribute it and/or modify
+ * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version.
  * 
- * chrootsh is distributed in the hope that it will be useful,
+ * This program is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
  * 
  * You should have received a copy of the GNU General Public License
- * along with chrootsh; if not, write to the Free Software Foundation,
+ * along with this program; if not, write to the Free Software Foundation,
  * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  */
 
-/*----- Revision history --------------------------------------------------* 
- *
- * $Log: chrootsh.c,v $
- * Revision 1.1  1999/04/20 00:19:04  mdw
- * Initial revision
- *
- */
-
 /*----- Header files ------------------------------------------------------*/
 
 #include <errno.h>
@@ -43,6 +33,7 @@
 
 #include <sys/types.h>
 #include <unistd.h>
+#include <syslog.h>
 #include <pwd.h>
 
 extern char **environ;
@@ -59,6 +50,7 @@ static void *xmalloc(size_t sz)
 {
   void *p = malloc(sz);
   if (!p) {
+    setuid(getuid());
     fprintf(stderr, "%s: not enough memory\n", quis);
     exit(EXIT_FAILURE);
   }
@@ -77,6 +69,7 @@ int main(int argc, char *argv[])
 {
   struct passwd *pw;
   uid_t me = getuid();
+  char *myname;
   char **env;
   char **av;
 
@@ -89,21 +82,32 @@ int main(int argc, char *argv[])
       if (*q == '/')
        p = q + 1;
     }
+    if (*p == '-')
+      p++;
     quis = p;
+    openlog(quis, LOG_PID | LOG_NDELAY, LOG_DAEMON);
   }
 
   /* --- Check the user is meant to be chrooted --- */
 
-  pw = getpwuid(me);
-  if (!pw) {
-    fprintf(stderr, "%s: you don't exist.  Go away.\n", quis);
-    exit(EXIT_FAILURE);
-  }
-  if (strcmp(pw->pw_shell, CHROOTSH_PATH) != 0) {
-    fprintf(stderr, "%s: you aren't a chrooted user\n", quis);
-    exit(EXIT_FAILURE);
+  {
+    uid_t eff = geteuid();
+
+    setreuid(eff, me);
+    pw = getpwuid(me);
+    if (!pw) {
+      syslog(LOG_ERR, "executed by non-existant user (uid = %i)", (int)me);
+      fprintf(stderr, "%s: you don't exist.  Go away.\n", quis);
+      exit(EXIT_FAILURE);
+    }
+    if (strcmp(pw->pw_shell, CHROOTSH_PATH) != 0) {
+      syslog(LOG_ERR, "executed by non-chrooted user `%s'", pw->pw_name);
+      fprintf(stderr, "%s: you aren't a chrooted user\n", quis);
+      exit(EXIT_FAILURE);
+    }
+    endpwent();
+    setreuid(me, eff);
   }
-  endpwent();
 
   /* --- Chroot the user --- */
 
@@ -114,7 +118,10 @@ int main(int argc, char *argv[])
       *q = 0;
     
     if (chdir(p) || chroot(p)) {
-      fprintf(stderr, "%s: couldn't call chroot: %s", quis, strerror(errno));
+      int e = errno;
+      syslog(LOG_ERR, "error entering chroot gaol: %m");
+      setuid(me);
+      fprintf(stderr, "%s: couldn't call chroot: %s\n", quis, strerror(e));
       exit(EXIT_FAILURE);
     }
     setuid(me);
@@ -123,21 +130,21 @@ int main(int argc, char *argv[])
 
   /* --- Read the new password block --- */
 
-  {
-    char *p = xstrdup(pw->pw_name);
-    pw = getpwnam(p);
-    free(p);
-    if (!pw) {
-      fprintf(stderr, "%s: you don't exist in the gaol\n", quis);
-      exit(EXIT_FAILURE);
-    }
-    endpwent();
+  myname = xstrdup(pw->pw_name);
+  pw = getpwnam(myname);
+  if (!pw) {
+    syslog(LOG_ERR,
+          "configuration error: user `%s' not defined in gaol", myname);
+    fprintf(stderr, "%s: you don't exist in the gaol\n", quis);
+    exit(EXIT_FAILURE);
   }
+  endpwent();
 
   /* --- Now fiddle with environment strings and suchlike --- */
 
   {
     size_t n;
+    char **homevar = 0;
     for (n = 0; environ[n]; n++)
       ;
     env = xmalloc((n + 1) * sizeof(char *));
@@ -146,6 +153,7 @@ int main(int argc, char *argv[])
       if (strncmp(environ[n], "HOME=", 5) == 0) {
        char *p = xmalloc(6 + strlen(pw->pw_dir));
        sprintf(p, "HOME=%s", pw->pw_dir);
+       homevar = &env[n];
        env[n] = p;
       } else if (strncmp(environ[n], "SHELL=", 6) == 0) {
        char *p = xmalloc(7 + strlen(pw->pw_shell));
@@ -155,6 +163,16 @@ int main(int argc, char *argv[])
        env[n] = environ[n];
     }
     env[n] = 0;
+
+    /* --- Change directory (again) --- */
+
+    if (chdir(pw->pw_dir)) {
+      if (homevar) {
+       free(*homevar);
+       *homevar = "HOME=/";
+      }
+      fprintf(stderr, "No directory, logging in with HOME=/\n");
+    }
   }
 
   /* --- Finally, sort the argument list --- */
@@ -181,17 +199,14 @@ int main(int argc, char *argv[])
       av[i] = argv[i];
   }
 
-  /* --- Change directory (again) --- */
-
-  if (chdir(pw->pw_dir))
-    fprintf(stderr, "No directory, logging in with HOME=/\n");
-
   /* --- Run the real shell --- */
 
+  syslog(LOG_INFO, "chroot user `%s' logged in ok", myname);
+  closelog();
   execve(pw->pw_shell, av, env);
-  fprintf(stderr, "%s: couldn't exec `%s': %s",
+  fprintf(stderr, "%s: couldn't exec `%s': %s\n",
          quis, pw->pw_shell, strerror(errno));
   return (EXIT_FAILURE);
 }
-  
+
 /*----- That's all, folks -------------------------------------------------*/