bug-coreutils
[Top][All Lists]
Advanced

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

Modified WHO to guard against DNS cache poisoning


From: Bill Crowell
Subject: Modified WHO to guard against DNS cache poisoning
Date: Wed, 22 Feb 2006 09:14:41 -0500
User-agent: Mozilla Thunderbird 1.0.6 (X11/20050716)

Attached is the diff output of modifications to who.c vs. source from 5.2.1.

Added are the -n and --ipaddr flags and function to return the IP address logged in utmp ut_addr_v6[4] during the socket initialization. This feature provides a mechanism to guard against DNS poisoning as utmp is updated by the incoming socket connection information after password verification.

The method of storing and retrieving IP addresses is consistant with OpenSSH's implementation and consistant with security standards.

The choice of -n was to be syntactically similar to netkit and netutils commands.
The choice of [] was to provide positive delimited parsing boundaries.
The return of 0.0.0.0 indicates that no IP address was stored in utmp.

Functional dependencies. The return of the IP address for telnet connections is predicated by updates to netkit also submitted by Crowell Systems. Updates to telnetd and login to pass and store the inbound socket address information based upon the OpenSSH model.

Please contact me with any questions or comments.

Regards,

Bill

--
William G. Crowell, VP & CTO
Crowell Systems
4235 South Stream Blvd Suite 100
Charlotte  NC 28217
704.665.2000 fax 704.665.2180
If it's your turn to save the world, remember to say "Klatoo borada niktu"

--- who_orig.c  2006-02-17 01:34:48.000000000 -0500
+++ who.c       2006-02-22 09:01:55.000000000 -0500
@@ -17,6 +17,13 @@
 
 /* Written by jla; revised by djm; revised again by mstone */
 
+/* Modified by Mike Isely <address@hidden> & Bill Crowell <address@hidden>
+   for Crowell Systems to add the "-n" and "--ipaddr" flags. These output 
flags close
+   a security hole by returning the IP address unconditionally from 
ut_addr_v6[4]
+   of a connected user that was logged upon socket initialization. This is 
consistent with   OpenSSH security by not relying upon DNS to return an address 
thus avoiding DNS
+   cache poisoning. Use of the -n flag to be consistant with other netutils 
output.
+ */
+
 /* Output format:
    name [state] line time [activity] [pid] [comment] [exit]
    state: -T
@@ -28,6 +35,8 @@
 #include <getopt.h>
 #include <stdio.h>
 
+#include <netdb.h>
+
 #include <sys/types.h>
 #include "system.h"
 
@@ -37,7 +46,7 @@
 /* The official name of this program (e.g., no `g' prefix).  */
 #define PROGRAM_NAME "who"
 
-#define AUTHORS "Joseph Arceneaux", "David MacKenzie", "Michael Stone"
+#define AUTHORS "Joseph Arceneaux", "David MacKenzie", "Michael Stone 
(modified by Crowell Systems)"
 
 #ifndef MAXHOSTNAMELEN
 # define MAXHOSTNAMELEN 64
@@ -167,6 +176,9 @@
 /* If nonzero, display info only for the controlling tty */
 static int my_line_only;
 
+/* If true, display the IPv4 address of the user */
+static int use_ipaddr;
+
 /* for long options with no corresponding short option, use enum */
 enum
 {
@@ -180,6 +192,7 @@
   {"dead", no_argument, NULL, 'd'},
   {"heading", no_argument, NULL, 'H'},
   {"idle", no_argument, NULL, 'i'},
+  {"ipaddr", no_argument, NULL, 'n'},
   {"login", no_argument, NULL, 'l'},
   {"lookup", no_argument, NULL, LOOKUP_OPTION},
   {"message", no_argument, NULL, 'T'},
@@ -319,8 +332,8 @@
   time_t last_change;
   char mesg;
   char idlestr[IDLESTR_LEN];
-  static char *hoststr;
-  static size_t hostlen;
+  static char *hoststr = 0;
+  static size_t hostlen = 0;
 
 #define DEV_DIR_WITH_TRAILING_SLASH "/dev/"
 #define DEV_DIR_LEN (sizeof (DEV_DIR_WITH_TRAILING_SLASH) - 1)
@@ -403,16 +416,67 @@
          sprintf (hoststr, "(%s)", host);
        }
     }
-  else
+#endif
+  if (use_ipaddr)
     {
-      if (hostlen < 1)
-       {
-         hostlen = 1;
-         hoststr = (char *) realloc (hoststr, hostlen);
-       }
-      stpcpy (hoststr, "");
+       char buf[100];
+       unsigned int len1,len2,spc;
+       buf[0] = '[';
+       len2 = 1;
+       if (utmp_ent->ut_addr_v6[1] ||
+           utmp_ent->ut_addr_v6[2] ||
+           utmp_ent->ut_addr_v6[3])
+         {
+             unsigned int idx;
+             unsigned short v;
+             /* Print IPV6 style */
+             for (idx = 0; idx < 8; idx++) {
+                 v = (utmp_ent->ut_addr_v6[(7-idx) >> 1]) >>
+                     (((7-idx) & 1) ? 0 : 16);
+                 v = (v << 8) | (v >> 8);
+                 if (idx)
+                   {
+                       buf[len2] = ':';
+                       len2++;
+                   }
+                 if (v)
+                   {
+                     sprintf(buf+len2,"%x",v);
+                     len2 += strlen(buf+len2);
+                   }
+             }
+         }
+       else
+         {
+             /* Print IPV4 style */
+             sprintf(buf+len2,"%u.%u.%u.%u",
+                     utmp_ent->ut_addr_v6[0] & 0xffu,
+                     (utmp_ent->ut_addr_v6[0] >> 8) & 0xffu,
+                     (utmp_ent->ut_addr_v6[0] >> 16) & 0xffu,
+                     (utmp_ent->ut_addr_v6[0] >> 24) & 0xffu);
+             len2 += strlen(buf+len2);
+         }
+       buf[len2] = ']';
+       len2++;
+       len1 = hoststr ? strlen(hoststr) : 0;
+       spc = len1 ? 1 : 0;
+       if (hostlen < len1+len2+spc+1)
+         {
+             hostlen = len1+len2+spc+1;
+             hoststr = xrealloc(hoststr,len1+len2+spc+1);
+         }
+       if (spc) hoststr[len1] = ' ';
+       len1++;
+       memcpy(hoststr+len1,buf,len2);
+       hoststr[len1+len2] = 0;
+    }
+
+  if (hostlen < 1)
+    {
+       hostlen = 1;
+       hoststr = xrealloc (hoststr, hostlen);
+       stpcpy (hoststr, "");
     }
-#endif
 
   print_line (UT_USER (utmp_ent), mesg, utmp_ent->ut_line,
              time_string (utmp_ent), idlestr, pidstr,
@@ -620,7 +684,7 @@
       printf (_("Usage: %s [OPTION]... [ FILE | ARG1 ARG2 ]\n"), program_name);
       fputs (_("\
 \n\
-  -a, --all         same as -b -d --login -p -r -t -T -u\n\
+  -a, --all         same as -b -d --login -p -r -t -T -u -n\n\
   -b, --boot        time of last system boot\n\
   -d, --dead        print dead processes\n\
   -H, --heading     print line of column headings\n\
@@ -633,6 +697,7 @@
       fputs (_("\
       --lookup      attempt to canonicalize hostnames via DNS\n\
   -m                only hostname and user associated with stdin\n\
+  -n, --ipaddr      return non-canonized IP address from utmp\n\
   -p, --process     print active processes spawned by init\n\
 "), stdout);
       fputs (_("\
@@ -673,7 +738,7 @@
 
   atexit (close_stdout);
 
-  while ((optc = getopt_long (argc, argv, "abdilmpqrstuwHT", longopts,
+  while ((optc = getopt_long (argc, argv, "abdilmnpqrstuwHT", longopts,
                              &longind)) != -1)
     {
       switch (optc)
@@ -689,6 +754,7 @@
          need_runlevel = 1;
          need_clockchange = 1;
          need_users = 1;
+         use_ipaddr = 1;
          include_mesg = 1;
          include_idle = 1;
          include_exit = 1;
@@ -721,6 +787,11 @@
          my_line_only = 1;
          break;
 
+       case 'n':
+         use_ipaddr = 1;
+         include_idle = 1;
+         break;
+
        case 'p':
          need_initspawn = 1;
          assumptions = 0;

reply via email to

[Prev in Thread] Current Thread [Next in Thread]