[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

Bug#556522: hurd - using the login shell is insecure



tags 556522 patch
thanks

Hi :)

I incorporated some code from util-linuxs getty to make hurds getty ask
for a login name and pass that name to login. This way the login shell
is no longer needed. I also turned on logins --paranoid flag to prevent
it leaking whether a user exists or not.

Cheers,
Justus
--- hurd-20100926/daemons/getty.c	2010-09-26 22:10:52.000000000 +0000
+++ hurd-20100926-mine/daemons/getty.c	2011-01-09 23:35:27.000000000 +0000
@@ -4,6 +4,9 @@
 
    Written by Michael I. Bushnell, p/BSG.
 
+   This file contains parts of the get_logname function from
+   util-linux/getty.c.
+
    This file is part of the GNU Hurd.
 
    The GNU Hurd is free software; you can redistribute it and/or
@@ -34,11 +37,21 @@
 #include <utmp.h>
 #include <sys/ioctl.h>
 #include <termios.h>
+#include <ctype.h>
 
 /* XXX */
 extern char *localhost ();
 
 #define _PATH_LOGIN "/bin/login"
+#define LOGIN " login: "    /* login prompt */
+
+/* Some shorthands for control characters. */
+
+#define CTL(x)  (x ^ 0100)  /* Assumes ASCII dialect */
+#define	CR      CTL('M')    /* carriage return */
+#define	NL      CTL('J')    /* line feed */
+#define	BS      CTL('H')    /* back space */
+#define	DEL     CTL('?')    /* delete */
 
 /* Parse the terminal speed.  */
 static void
@@ -77,6 +90,89 @@
   write (fd, s, cc);
 }
 
+char *
+get_login_name(int fd)
+{
+  size_t max_pw_size;
+  char *result;
+  char *ptr;
+  char c;
+  char done;
+  char *prompt;
+  int prompt_size;
+  char *hostname;
+
+  max_pw_size = sysconf (_SC_GETPW_R_SIZE_MAX);
+
+  if (!(result = malloc (max_pw_size + 1)))
+    {
+      syslog (LOG_ERR, "Failed to allocate memory for login name");
+      exit (EXIT_FAILURE);
+    }
+
+  hostname = localhost ();
+  prompt_size = asprintf (&prompt, "%s%s", hostname, LOGIN);
+  free (hostname);
+  write (fd, prompt, prompt_size);
+  free (prompt);
+
+  /* flush pending input */
+  sleep (1);
+  tcflush (fd, TCIFLUSH);
+
+  for (ptr = result, done = 0; !done; /* void */)
+    {
+      if (read (fd, &c, 1) < 1)
+        {
+          if (errno == EINTR || errno == EIO)
+            exit (EXIT_FAILURE);
+        }
+
+      switch (c)
+        {
+        case CR:
+        case NL:
+          *ptr = 0;                     /* terminate logname */
+          done = 1;
+          break;
+        case BS:
+        case DEL:
+        case '#':
+          if (ptr > result)
+            {
+              write (fd, "\b", 1);
+              ptr--;
+            }
+          break;
+        case CTL('U'):
+        case '@':
+          while (ptr > result)
+            {
+              write (fd, "\b", 1);
+              ptr--;
+            }
+          break;
+        case CTL('D'):
+          exit (EXIT_SUCCESS);
+        default:
+          if (!isascii (c) || !isprint (c))
+            {
+              /* ignore garbage characters */
+            }
+          else if (ptr - result > max_pw_size)
+            {
+              /* input overrun, dropping character */
+            }
+          else
+            {
+              *ptr++ = c;               /* and store it */
+            }
+          break;
+        }
+    }
+  return result;
+}
+
 int
 main (int argc, char **argv)
 {
@@ -84,6 +180,7 @@
   int tty;
   struct ttyent *tt;
   char *arg;
+  char *login_name;
 
   openlog ("getty", LOG_ODELAY|LOG_CONS|LOG_PID, LOG_AUTH);
 
@@ -121,6 +218,7 @@
   set_speed (tty, linespec);
 
   print_banner (tty, ttyname);
+  login_name = get_login_name(tty);
 
   if (login_tty (tty) == -1)
     syslog (LOG_ERR, "cannot set controlling terminal to %s: %m", ttyname);
@@ -129,10 +227,12 @@
 
   if (tt && strcmp (tt->ty_type, "dialup") == 0)
     /* Dialup lines time out (which is login's default).  */
-    execl (_PATH_LOGIN, "login", "-e", arg, NULL);
+    execl (_PATH_LOGIN, "login", "--paranoid", "-e", arg,
+           login_name, NULL);
   else
     /* Hardwired lines don't.  */
-    execl (_PATH_LOGIN, "login", "-e", arg, "-aNOAUTH_TIMEOUT", NULL);
+    execl (_PATH_LOGIN, "login", "--paranoid", "-e", arg,
+           "-aNOAUTH_TIMEOUT", login_name, NULL);
 
   syslog (LOG_ERR, "%s: %m", _PATH_LOGIN);
 

Attachment: signature.asc
Description: PGP signature


Reply to: