Benutzer:Kirmse/delixs-userpasswd

Aus Delixs
Version vom 22. Juni 2009, 19:45 Uhr von Kirmse (Diskussion | Beiträge) (Script zum Ändern der Passworte eines Users)
(Unterschied) ← Nächstältere Version | Aktuelle Version (Unterschied) | Nächstjüngere Version → (Unterschied)
Zur Navigation springen Zur Suche springen

delixs-userpasswd

  • dieses Script ändert das Linux- und Sambapasswortes von Usern. Aufruf ist nur als root möglich
  • Parameter: --help oder -h, --user oder -u, --pass oder -p
  • Aufruf: delixs-userpasswd -u mmustermann -p geheim

Hinweis: Dieses Script ist eine Modifikation des Scripts 'smbldap-passwd'. Es wurden die Parameter des Originalscripts "stillgelegt" und "neue" Parameter in der Art der anderen Scripte für Delixs ergänzt. Zudem wurden Teil des Codes entfernt, der nur als "normaler" User ausgeführt wurde.


das Script

<source lang="perl">

  1. !/usr/bin/perl -w
  1. untaint environment

$ENV{'PATH'}= '/bin:/usr/bin'; $ENV{'SHELL'}= '/bin/sh'; delete @ENV{qw(IFS CDPATH ENV BASH_ENV)};

use strict; use FindBin; use FindBin qw($RealBin); use lib "$RealBin/"; use smbldap_tools;

use Crypt::SmbHash; use Digest::MD5 qw(md5); use Digest::SHA1 qw(sha1); use MIME::Base64 qw(encode_base64);

  1. ergaenzt

use Getopt::Long;

  1. function declaration

sub make_hash; sub make_salt;

  1. my $user= undef;

my $oldpass= undef;

my $arg; my $update_samba_passwd= 1; my $update_unix_passwd= 1; my $force_update_samba_passwd=0;

  1. die Original-Behandlung der Parameter wurde komplett entfernt und
  2. durch die delixs-typische Parameterabfrage ersetzt
  1. Initialisieren der Variablen fuer die Parameter

my $user = ; my $password = ; my $pass;

  1. wir holen uns zuerst die Parameter,
  2. falls --help, dann Ausgabe der Hilfe (siehe &help) und beenden

GetOptions('user=s' => \$user,

          'pass=s'   => \$password,
          'help'     => \&help);


  1. Wenn kein Parameter -u oder --user uebergeben wurde, dann Abbruch

if ($user eq ) {

 die "Abbruch: es wurde der Parameter --user nicht uebergeben!\n";

}

  1. Wenn der User nicht den/meinen Konventionen entspricht, dann Abbruch

unless ($user =~ /^[a-zA-Z]\w{1,13}$/) {

 die "Abbruch: Der Name fuer den User $user ist nicht korrekt!\n";

}

  1. Wenn kein Parameter -p oder --pass uebergeben wurde, dann Abbruch

if ($password eq ) {

 die "Abbruch: es wurde der Parameter --pass nicht uebergeben!\n";

}


  1. -------------- jetzt wieder im Original weiter
  1. check if $user variable is not tainted
  2. [TODO] create proper user mask

$user =~ /^([-\@\ \w.]+\$?)$/ and $user = $1 or

   die "$0: username '$user' is tainted\n";


my ($dn,$ldap_master);

  1. First, connecting to the directory

if ($< == 0) {

   # root user
   $ldap_master=connect_ldap_master();
   # test existence of user in LDAP
   my $dn_line;
   if (!defined($dn_line = get_user_dn($user))) {

print "$0: user $user doesn't exist\n"; exit (10);

   }
   $dn = get_dn_from_line($dn_line);

}

my $samba = is_samba_user($user);


  1. prompt for new password

my $pass1; my $pass2;

  1. um die Stuktur des Originals zu erhalten, sollte einfach die Variable des
  2. Parameter hier zugewiesen werden

$pass1 = $password; $pass2 = $pass1; $pass = $password;

  1. hier wurden etliche Zeilen geloescht
  1. Prepare '$hash_password' for 'userPassword'

my $hash_password;

  1. Generate password hash

if ($config{with_slappasswd}) {

   # checking if password is tainted: nothing is changed!!!!
   # essential for perl 5.8
   ($pass =~ /^(.*)$/ and $pass=$1) or

die "$0: user password is tainted\n";

   # use slappasswd to generate hash
   if ( $config{hash_encrypt} eq "CRYPT" && defined($config{crypt_salt_format}) ) {

open BUF, "-|" or exec "$config{slappasswd}", "-h","{$config{hash_encrypt}}", "-c","$config{crypt_salt_format}", "-s","$pass"; $hash_password = <BUF>; close BUF;

   } else {

open(BUF, "-|") or exec "$config{slappasswd}", "-h","{$config{hash_encrypt}}", "-s","$pass"; $hash_password = <BUF>; close BUF;

   }

} else {

   # use perl libraries to generate hash
   $hash_password = make_hash($pass,$config{hash_encrypt},$config{crypt_salt_format});

}

  1. check if a hash was generated, otherwise die

defined($hash_password) or

   die "I cannot generate the proper hash!\n";

chomp($hash_password);


  1. only modify smb passwords if smb user

if ( $samba and $update_samba_passwd ) {

   if (!$config{with_smbpasswd}) {

# generate LanManager and NT clear text passwords my ($sambaLMPassword,$sambaNTPassword) = ntlmgen $pass; # the sambaPwdLastSet must be updating my $date=time; my @mods; push(@mods, 'sambaLMPassword' => $sambaLMPassword); push(@mods, 'sambaNTPassword' => $sambaNTPassword); push(@mods, 'sambaPwdLastSet' => $date); if (defined $config{defaultMaxPasswordAge}) { my $new_sambaPwdMustChange=$date+$config{defaultMaxPasswordAge}*24*60*60; push(@mods, 'sambaPwdMustChange' => $new_sambaPwdMustChange); if ($< ==0) { push(@mods, 'sambaAcctFlags' => '[U]'); } } if ($force_update_samba_passwd == 1) { # To force a user to change his password: # . the attribut sambaPwdLastSet must be != 0 # . the attribut sambaAcctFlags must not match the 'X' flag my $winmagic = 2147483647; my $valacctflags = "[U]"; push(@mods, 'sambaPwdMustChange' => 0); push(@mods, 'sambaPwdLastSet' => $winmagic); push(@mods, 'sambaAcctFlags' => $valacctflags); } # Let's change nt/lm passwords my $modify = $ldap_master->modify ( "$dn", 'replace' => { @mods } ); $modify->code && warn "Failed to modify SMB password: ", $modify->error ;

   } else {

if ($< != 0) { my $FILE="|$config{smbpasswd} -s >/dev/null"; open (FILE, $FILE) || die "$!\n"; print FILE <<EOF; $oldpass $pass $pass EOF ; close FILE; } else { open FILE,"|-" or exec "$config{smbpasswd}","$user","-s"; local $SIG{PIPE} = sub {die "buffer pipe terminated" }; print FILE <<EOF; $pass $pass EOF ; close FILE; }

   }

}

  1. Update 'userPassword' field

if ( $update_unix_passwd ) {

   my $shadowLastChange=int(time()/86400);
   my $modify;
   if ($< != 0) {

$modify = $ldap_master->modify ( "$dn", changes => [ replace => [userPassword => "$hash_password"], replace => [shadowLastChange => "$shadowLastChange"] ] );

   } else {

$modify = $ldap_master->modify ( "$dn", changes => [ replace => [userPassword => "$hash_password"], replace => [shadowLastChange => "$shadowLastChange"], replace => [shadowMax => "$config{defaultMaxPasswordAge}"] ] );

   }
   $modify->code && warn "Failed to modify UNIX password: ", $modify->error ;

}

  1. take down session

$ldap_master->unbind;

exit 0;

                                      1. Programm-Ende #####################################


  1. Generates hash to be one of the following RFC 2307 schemes:
  2. CRYPT, MD5, SMD5, SHA, SSHA, and CLEARTEXT
  3. SSHA is default
  4. '%s' is a default crypt_salt_format
  5. A substitute for slappasswd tool

sub make_hash {

   my $hash_encrypt;
   my $crypt_salt_format;
   my $clear_pass=$_[0] or return undef;
   $hash_encrypt='{' . $_[1] . '}' or $hash_encrypt = "{SSHA}";
   $crypt_salt_format=$_[2] or $crypt_salt_format = '%s';
   my $hash_pass;
   if ($hash_encrypt eq "{CRYPT}" && defined($crypt_salt_format)) {

# Generate CRYPT hash # for unix md5crypt $crypt_salt_format = '$1$%.8s' my $salt = sprintf($crypt_salt_format,make_salt()); $hash_pass = "{CRYPT}" . crypt($clear_pass,$salt);

   } elsif ($hash_encrypt eq "{MD5}") {

# Generate MD5 hash $hash_pass = "{MD5}" . encode_base64( md5($clear_pass), );

   } elsif ($hash_encrypt eq "{SMD5}") {

# Generate SMD5 hash (MD5 with salt) my $salt = make_salt(4); $hash_pass = "{SMD5}" . encode_base64( md5($clear_pass . $salt) . $salt,);

   } elsif ($hash_encrypt eq "{SHA}") {

# Generate SHA1 hash $hash_pass = "{SHA}" . encode_base64( sha1($clear_pass), );

   } elsif ($hash_encrypt eq "{SSHA}") {

# Generate SSHA hash (SHA1 with salt) my $salt = make_salt(4); $hash_pass = "{SSHA}" . encode_base64( sha1($clear_pass . $salt) . $salt, );

   } elsif ($hash_encrypt eq "{CLEARTEXT}") {

$hash_pass=$clear_pass;

   } else {

$hash_pass=undef;

   }
   return $hash_pass;

}

  1. Generates salt
  2. Similar to Crypt::Salt module from CPAN

sub make_salt {

   my $length=32;
   $length = $_[0] if exists($_[0]);
   
   my @tab = ('.', '/', 0..9, 'A'..'Z', 'a'..'z');
   return join "",@tab[map {rand 64} (1..$length)];

}

  1. - The End


  1. Wenn Parameter -h uebergeben wurde, dann Hilfe ausgegeben und beenden

sub help {

  print "Hilfe muss noch erstellt werden.\n";
  exit (0);

}


</source>