全部博文(1144)
分类: LINUX
2009-12-09 12:09:28
#!/usr/local/bin/perl # passwd replacement for solaris < 10 # try to make users select a stronger password # copyright 2009.05.04 jeremy kister # v2009061901 # to install, simply: # mv /usr/bin/passwd /usr/bin/passwd.orig # chmod 0 /usr/bin/passwd.orig # mv passwd.pl /usr/bin/passwd # chown root:sys /usr/bin/passwd # chmod 6555 /usr/bin/passwd # # set CRYPT_DEFAULT=1 in /etc/security/policy.conf # modify $NIS (below) - 0 if not using NIS, 1 if using NIS use strict; use Crypt::PasswdMD5 qw(unix_md5_crypt); my $NIS = 1; $SIG{INT} = $SIG{QUIT} = $SIG{HUP} = sub { cleanup(); }; foreach my $key (keys %ENV){ # make suid perl safer.. next if($key eq 'USER'); delete $ENV{$key}; } my $user = $ENV{USER}; if(@ARGV >= 1){ if( $< ){ die "I don't support any arguments\n"; }else{ if(@ARGV == 1){ $user = shift; }else{ die "I'll only take a username as an argument\n"; } } } unless($user =~ /^[a-z]{3,12}[0-9]?$/){ die "invalid user: $user\n"; } die "wont change root pw\n" if($user eq 'root'); srand(time() ^($$ + ($$ << 15))); my @set = ('.', '/', '0'..'9', 'A'..'Z', 'a'..'z'); my $salt = join ('', map { $set[ rand ( @set) ] } (1 .. 8)); open(TSTMP, ">/etc/stmp.$$") || die "cannot write to /etc/stmp.$$: $!\n"; close TSTMP; chmod(0600, "/etc/stmp.$$") || die "cannot set file mode on /etc/stmp.$$: $!\n"; my $have_link; for(1..5){ if( link("/etc/stmp.$$", "/etc/stmp") ){ $have_link = 1; last; }else{ sleep 2; } } unless($have_link){ print "passwd: Sorry, could not obtain stmp lock.\n"; exit_evil(); } my $ocrypt; open(SHADOW, "/etc/shadow") || die "cannot read shadow file: $!\n"; my @shadow =; close SHADOW; foreach(@shadow){ if(/^$user:([^:]+):/){ $ocrypt = $1; last; } } unless($user && $ocrypt){ print "passwd: User unknown: $user\n"; exit_evil(); } my $opw; print "passwd: Changing password for $user\n"; if( $< ){ print "Enter existing login password: "; system "stty -echo"; chomp($opw= ); print "\n"; } if( $ocrypt eq crypt($opw, $ocrypt) || $< == 0 ){ my $npw; system "stty -echo"; for my $round (1..3){ print "New Password: "; chomp($npw= ); print "\n"; # check strength my $err; my %types; if($npw =~ /$user/i){ print "passwd: Sorry, can't use your username in your password\n"; $err++; } my $rev = reverse($user); if($npw =~ /$rev/i){ print "passwd: Sorry, can't use the reverse of your username in your password\n"; $err++; } if(length($npw) < 8 || length($npw) > 255){ print "passwd: Sorry, password must be 8 to 255 characters.\n"; $err++; } $types{uc} = 1 if($npw =~ /[A-Z]/); $types{lc} = 1 if($npw =~ /[a-z]/); $types{num} = 1 if($npw =~ /[0-9]/); $types{special} = 1 if($npw =~ /[^A-Z0-9]/i); if(keys %types < 3){ print "Password must contain characters from at least three of the following four classes:\n", " * English Upper Case Letters (A, B, C, .. Z)\n", " * English Lower Case Letters (a, b, c, .. z)\n", " * Westernized Arabic Numerals (0, 1, 2, .. 9)\n", " * Non-alphanumeric (special characters, e.g. punctuation symbols)\n"; $err++; } unless($err){ print "Re-enter new Password: "; chomp(my $rpw= ); if($npw ne $rpw){ print "passwd(SYSTEM): They don't match.\n"; $err++; } } if($err){ if($round == 3){ exit_evil(); }else{ print "\n", "Please try again\n"; } }else{ last; } } system("stty echo"); print "\n"; my $ncrypt = unix_md5_crypt($npw, $salt); my $days = sprintf( '%d', (time() / 86400) ); open(STMP, ">>/etc/stmp") || die "could not append to stmp: $!\n"; foreach(@shadow){ if(/^$user:/){ print STMP "${user}:${ncrypt}:${days}::::::\n"; }else{ print STMP; } } close STMP; rename("/etc/stmp","/etc/shadow") || die "cannot rename stmp to shadow: $!\n"; unlink("/etc/stmp.$$") || die "cannot unlink stmp.$$: $!\n"; chmod(0400, "/etc/shadow") || die "cannot set file mode on /etc/shadow: $!\n"; if($NIS){ system("cd /var/yp ; /usr/local/bin/make >/dev/null 2>&1"); } }else{ print "passwd: Sorry, wrong passwd\n"; exit_evil(); } sub exit_evil { print "Permission denied\n"; cleanup(); exit 1; } sub cleanup { unlink("/etc/stmp.$$"); unlink("/etc/stmp") if($have_link); system("stty echo"); exit; }