home *** CD-ROM | disk | FTP | other *** search
/ The World of Computer Software / World_Of_Computer_Software-02-385-Vol-1of3.iso / c / cops_104.zip / cops_104 / perl / passwd.chk < prev    next >
Text File  |  1992-03-10  |  5KB  |  134 lines

  1. #!/bin/sh -- need to mention perl here to avoid recursion
  2. 'true' || eval 'exec perl -S $0 $argv:q';
  3. eval '(exit $?0)' && eval 'exec perl -S $0 ${1+"$@"}'
  4. & eval 'exec /usr/local/bin/perl -S $0 $argv:q'
  5.         if 0;
  6.  
  7. #
  8. #   passwd.chk
  9. #
  10. # composer@chem.bu.edu
  11. #
  12. # Check password file -- /etc/passwd -- for incorrect number of fields,
  13. # duplicate uid's, non-alphanumeric uids, and non-numeric group id's.
  14. # Mechanism:  This script ensures that each line of the passwd file (in
  15. # $etc, line 47) has 7 fields and is non-blank, as well as examining the
  16. # file for any duplicate users.  It then checks to ensure that the first
  17. # character of the login name is alphanumeric, and that all uid and gid
  18. # numbers are indeed numeric and non-negative.  It also checks the
  19. # validity of the home directory.
  20. # For yellow pages passwords, it does the same checking, but in order to
  21. # get a listing of all members of the password file, it does a "ypcat
  22. # passwd" and uses the output from that as a passwd file.
  23. # The /etc/passwd file has a very specific format, making the task fairly
  24. # simple.  Normally it has lines with 7 fields, each field separated by a
  25. # colon (:).  The first field is the user id, the second field is the
  26. # encrypted password (an asterix (*) means the group has no password,
  27. # otherwise the first two characters are the salt), the third field is the
  28. # user id number, the fourth field is the group id number, the fifth field
  29. # is the GECOS field (basically holds miscellaneous information, varying
  30. # from site to site), the sixth field is the home directory of the user,
  31. # and lastly the seventh field is the login shell of the user.  No blank
  32. # lines should be present.  Uid's will be flagged if over 8 chars, unless
  33. # the $OVER_8 variable (line 45) is set to "YES".
  34. # If a line begins with a plus sign (+), it is a yellow pages entry.  See
  35. # passwd(5) for more information, if this applies to your site.
  36.  
  37. require 'pathconf.pl';
  38. require 'pass.cache.pl';
  39.  
  40. package passwd_chk;
  41.  
  42. #   Used for Sun C2 security group file. 'FALSE' (default) will flag
  43. # valid C2 passwd syntax as an error, 'TRUE' attempts to validate it.
  44. # Thanks to Pete Troxell for pointing this out.
  45. $C2='FALSE' if ! defined($C2);
  46.  
  47. #  Some systems allow long uids; set this to 'TRUE', if so (thanks
  48. # to Pete Shipley (lot of petes around here, eh?)):
  49. $OVER_8='NO' if ! defined($OVER_8);
  50.  
  51. #
  52. # Important files:
  53. $etc_passwd = $'PASSWD || '/etc/passwd';
  54.  
  55. #   Check $etc_passwd for potential problems, or use the alternate method
  56. # set in cops.cf:
  57. if (!"$'GET_PASSWD") {
  58.     open(Passwd, $etc_passwd) ||
  59.         warn "$0: Can't open $etc_passwd: $!\n";
  60.     }
  61. else {
  62.     open(Passwd, "$'GET_PASSWD|") ||
  63.         warn "$0: Can't open $etc_passwd: $!\n";
  64.     }
  65. &chk_passwd_file_format('Passwd');
  66. close Passwd;
  67.  
  68. # check ypcat passwd for potential problems... (same checks)
  69. if (-s $'YPCAT && -x _) {
  70.     open(YPasswd, "$'YPCAT passwd 2>/dev/null |")
  71.     || die "$0: Can't popen $'YPCAT: $!\n";
  72.     &chk_passwd_file_format('YPasswd');
  73.     close YPasswd;
  74. }
  75.   
  76. sub chk_passwd_file_format {
  77.     local($file) = @_;
  78.     local($W) = "Warning!  $file file,";
  79.     undef %users;
  80.   
  81.     while (<$file>) {
  82.     # should really check for correct YP syntax
  83.     next if /^[-+]/;    # skipping YP lines for now
  84.  
  85.     print "$W line $., is blank\n", next if /^\s*$/;
  86.  
  87.     # make code a little more readable .. use names.. 
  88.     ($user,$pass,$uid,$gid,$gcos,$home,$shell) = split(?:?);
  89.     $users{$user}++;    # keep track of dups
  90.     print "$W line $., does not have 7 fields:\n\t$_" if (@_ != 7);
  91.     print "$W line $., nonalphanumeric username:\n\t$_"
  92.         if $user !~ /^[_A-Za-z0-9-]+$/;
  93.     print "$W line $., numeric username:\n\t$_"
  94.         if $user =~ /^\d+$/;
  95.     print "$W line $., login name > 8 characters:\n\t$_"
  96.         if ( ! $OVER_8 && length($user) > 8);
  97.     print "$W line $., no password:\n\t$_" unless $pass;
  98.     print "$W line $., invalid password field for C2:\n\t$_"
  99.         if ($C2 && $pass =~ /^##/ && "##$user" ne $pass);
  100.     if ($uid !~ /^\d+$/) {
  101.         if ($uid < 0) {
  102.         print "$W line $., negative user id (uid):\n\t$_";
  103.         } else {
  104.         print "$W line $., nonnumeric user id (uid):\n\t$_";
  105.         }
  106.     }
  107.     # what about checks for certain ranges of UIDs .. -composer
  108.     print "$W line $., user $user has uid == 0 and is not root\n\t$_"
  109.         if $uid == 0 && $user ne "root";
  110.     print "$W line $., nonnumeric group id (gid):\n\t$_"
  111.         unless $gid =~ /^\d+$/;
  112.     print "$W line $., invalid home directory:\n\t$_"
  113.         unless $home =~ m:^/:;
  114.  
  115.     }
  116.     # find duplicate usernames
  117.     # not the best way, but it works ...
  118.     $dup_warned = 0;
  119.     for (sort keys %users) {
  120.     (print "Warning!  Duplicate username(s) found in $file:\n"),
  121.         $dup_warned++ if !$dup_warned && $users{$_} > 1;
  122.     print "$_ " if $users{$_} > 1;
  123.     }
  124.     print "\n" if $dup_warned;
  125. }
  126.   
  127. 1;
  128. # end of passwd.chk file
  129.