chiark / gitweb /
Miscellanous tidying and security fixes. Lots of thanks due to Clive
authormdw <mdw>
Thu, 22 Apr 1999 00:30:27 +0000 (00:30 +0000)
committermdw <mdw>
Thu, 22 Apr 1999 00:30:27 +0000 (00:30 +0000)
Jones.

chrootsh.c

index 5b12d0e5a865bc23511f173676717da1c7324937..18980256291dae4c8488d58957e50755a79d6736 100644 (file)
@@ -1,6 +1,6 @@
 /* -*-c-*-
  *
- * $Id: chrootsh.c,v 1.3 1999/04/21 22:52:43 mdw Exp $
+ * $Id: chrootsh.c,v 1.4 1999/04/22 00:30:27 mdw Exp $
  *
  * Chroot gaol shell
  *
 /*----- Revision history --------------------------------------------------* 
  *
  * $Log: chrootsh.c,v $
+ * Revision 1.4  1999/04/22 00:30:27  mdw
+ * Miscellanous tidying and security fixes.  Lots of thanks due to Clive
+ * Jones.
+ *
  * Revision 1.3  1999/04/21 22:52:43  mdw
  * Added a pile of syslog stuff, so that admins can see what this thing is
  * doing.
@@ -65,6 +69,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);
   }
@@ -104,18 +109,24 @@ int main(int argc, char *argv[])
 
   /* --- Check the user is meant to be chrooted --- */
 
-  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);
+  {
+    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 --- */
 
@@ -126,8 +137,10 @@ int main(int argc, char *argv[])
       *q = 0;
     
     if (chdir(p) || chroot(p)) {
+      int e = errno;
       syslog(LOG_ERR, "error entering chroot gaol: %m");
-      fprintf(stderr, "%s: couldn't call chroot: %s", quis, strerror(errno));
+      setuid(me);
+      fprintf(stderr, "%s: couldn't call chroot: %s\n", quis, strerror(e));
       exit(EXIT_FAILURE);
     }
     setuid(me);
@@ -136,22 +149,21 @@ int main(int argc, char *argv[])
 
   /* --- Read the new password block --- */
 
-  {
-    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();
+  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 *));
@@ -160,6 +172,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));
@@ -169,6 +182,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 --- */
@@ -195,19 +218,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 -------------------------------------------------*/