update smbldap-tool sscripts from Jérôme Tournier
authorGerald Carter <jerry@samba.org>
Tue, 23 Sep 2003 20:39:22 +0000 (20:39 +0000)
committerGerald Carter <jerry@samba.org>
Tue, 23 Sep 2003 20:39:22 +0000 (20:39 +0000)
(This used to be commit c1546a5311a4e9ad2d6566e71e11c6d5f8f120a9)

16 files changed:
examples/LDAP/smbldap-tools/AUTHORS [deleted file]
examples/LDAP/smbldap-tools/NEWS [deleted file]
examples/LDAP/smbldap-tools/smbldap-groupadd.pl
examples/LDAP/smbldap-tools/smbldap-groupdel.pl
examples/LDAP/smbldap-tools/smbldap-groupmod.pl
examples/LDAP/smbldap-tools/smbldap-groupshow.pl
examples/LDAP/smbldap-tools/smbldap-migrate-accounts.pl
examples/LDAP/smbldap-tools/smbldap-migrate-groups.pl
examples/LDAP/smbldap-tools/smbldap-passwd.pl
examples/LDAP/smbldap-tools/smbldap-populate.pl
examples/LDAP/smbldap-tools/smbldap-useradd.pl
examples/LDAP/smbldap-tools/smbldap-userdel.pl
examples/LDAP/smbldap-tools/smbldap-usermod.pl
examples/LDAP/smbldap-tools/smbldap-usershow.pl
examples/LDAP/smbldap-tools/smbldap_conf.pm
examples/LDAP/smbldap-tools/smbldap_tools.pm

diff --git a/examples/LDAP/smbldap-tools/AUTHORS b/examples/LDAP/smbldap-tools/AUTHORS
deleted file mode 100644 (file)
index e69de29..0000000
diff --git a/examples/LDAP/smbldap-tools/NEWS b/examples/LDAP/smbldap-tools/NEWS
deleted file mode 100644 (file)
index e69de29..0000000
index ee804b34d3b781469b86c0c389ee6fb4fecee47b..91cd2dad532b428ba4490801808a9293491df65c 100755 (executable)
@@ -1,4 +1,4 @@
-#!/usr/bin/perl 
+#!/usr/bin/perl -w
 
 #  This code was developped by IDEALX (http://IDEALX.org/) and
 #  contributors (their names can be found in the CONTRIBUTORS file).
@@ -23,6 +23,9 @@
 # Purpose of smbldap-groupadd : group (posix) add
 
 use strict;
+use FindBin;
+use FindBin qw($RealBin);
+use lib "$RealBin/";
 use smbldap_tools;
 
 use Getopt::Std;
index 3d072585b21b60d6200b3d085c43bcec3dfd6d86..89d0d993acfb78d3612ef1fe84f2100648b70e8f 100755 (executable)
@@ -1,4 +1,4 @@
-#!/usr/bin/perl 
+#!/usr/bin/perl -w
 
 #  This code was developped by IDEALX (http://IDEALX.org/) and
 #  contributors (their names can be found in the CONTRIBUTORS file).
@@ -23,6 +23,9 @@
 # Purpose of smbldap-groupdel : group (posix) deletion
 
 use strict;
+use FindBin;
+use FindBin qw($RealBin);
+use lib "$RealBin/";
 use smbldap_tools;
 use smbldap_conf;
 
@@ -48,9 +51,7 @@ if (!defined($dn_line = get_group_dn($_groupName))) {
 
 my $dn = get_dn_from_line($dn_line);
 
-my $rc = system "$ldapdelete $dn >/dev/null";
-die "$0: error while deleting group $_groupName\n"
-    unless ($rc == 0);
+group_del($dn);
 
 my $nscd_status = system "/etc/init.d/nscd status >/dev/null 2>&1";
 
index 4a891a2772fead1e3ebaf57a3f14b7dd8db45f03..f8971016027f84fc70b052b95295d8031599fca8 100755 (executable)
@@ -1,4 +1,4 @@
-#!/usr/bin/perl
+#!/usr/bin/perl -w
 #  This code was developped by IDEALX (http://IDEALX.org/) and
 #  contributors (their names can be found in the CONTRIBUTORS file).
 #
@@ -23,6 +23,9 @@
 
 
 use strict;
+use FindBin;
+use FindBin qw($RealBin);
+use lib "$RealBin/";
 use smbldap_tools;
 use smbldap_conf;
 
@@ -70,45 +73,30 @@ if (defined($tmp = $Options{'g'}) and $tmp =~ /\d+/) {
        }
     }
     if (!($gid == $tmp)) {
-       my $tmpldif =
-"dn: cn=$groupName,$groupsdn
-changetype: modify
-replace: gidNumber
-gidNumber: $tmp
-
-";
-       die "$0: error while modifying group $groupName\n"
-           unless (do_ldapmodify($tmpldif) == 0);
-       undef $tmpldif;
-
+       my $ldap_master=connect_ldap_master();
+       my $modify = $ldap_master->modify ( "cn=$groupName,$groupsdn",
+                                                                               changes => [
+                                                                                                       replace => [gidNumber => $tmp]
+                                                                                                  ]
+                                                                         );
+       $modify->code && die "failed to modify entry: ", $modify->error ;
+       # take down session
+       $ldap_master->unbind
     }
 }
 
-if (defined($newname)) {
-    my $FILE="|$ldapmodrdn >/dev/null";
-    open (FILE, $FILE) || die "$!\n";
-    print FILE <<EOF;
-cn=$groupName,$groupsdn
-cn=$newname
-
-EOF
-    ;
-    close FILE;
-    die "$0: error while modifying group $groupName\n" if ($?);
-
-    my $tmpldif =
-"dn: cn=$newname,$groupsdn
-changetype: modify
-delete: cn
--
-add: cn
-cn: $newname
-
-";
-    die "$0: error while modifying group $groupName\n"
-       unless (do_ldapmodify($tmpldif) == 0);
-    undef $tmpldif;
 
+if (defined($newname)) {
+  my $ldap_master=connect_ldap_master();
+  my $modify = $ldap_master->moddn (
+                                                                       "cn=$groupName,$groupsdn",
+                                                                       newrdn => "cn=$newname",
+                                                                       deleteoldrdn => "1",
+                                                                       newsuperior => "$groupsdn"
+                                                                  );
+  $modify->code && die "failed to modify entry: ", $modify->error ;
+  # take down session
+  $ldap_master->unbind
 }
 
 # Add members
@@ -117,16 +105,24 @@ if (defined($Options{'m'})) {
        my @members = split( /,/, $members );
        my $member;
        foreach $member ( @members ) {
-               my $tmpldif =
-"dn: cn=$groupName,$groupsdn
-changetype: modify
-add: memberUid
-memberUid: $member
-
-";
-               die "$0: error while modifying group $groupName\n"
-                       unless (do_ldapmodify($tmpldif) == 0);
-               undef $tmpldif;
+       if (is_unix_user($member)) {
+         if (is_group_member("cn=$groupName,$groupsdn",$member)) {
+               print "User $member already in the group\n";
+         } else {
+               print "adding user $member to group $groupName\n";
+               my $ldap_master=connect_ldap_master();
+               my $modify = $ldap_master->modify ( "cn=$groupName,$groupsdn",
+                                                                                       changes => [
+                                                                                                               add => [memberUid => $member]
+                                                                                                          ]
+                                                                                 );
+               $modify->code && warn "failed to add entry: ", $modify->error ;
+               # take down session
+               $ldap_master->unbind
+         }
+       } else {
+         print "User $member does not exist: create it first !\n";
+       }
        }
 }
 
@@ -136,16 +132,20 @@ if (defined($Options{'x'})) {
         my @members = split( /,/, $members );
         my $member;
         foreach $member ( @members ) {
-                my $tmpldif =
-"dn: cn=$groupName,$groupsdn
-changetype: modify
-delete: memberUid
-memberUid: $member
-
-";
-                die "$0: error while modifying group $groupName\n"
-                        unless (do_ldapmodify($tmpldif) == 0);
-                undef $tmpldif;
+       if (is_group_member("cn=$groupName,$groupsdn",$member)) {
+         print "deleting user $member from group $groupName\n";
+         my $ldap_master=connect_ldap_master();
+         my $modify = $ldap_master->modify ( "cn=$groupName,$groupsdn",
+                                                                                 changes => [
+                                                                                                         delete => [memberUid => $member]
+                                                                                                        ]
+                                                                               );
+         $modify->code && warn "failed to delete entry: ", $modify->error ;
+         # take down session
+         $ldap_master->unbind
+       } else {
+         print "User $member is not in the group $groupName!\n";
+       }
         }
 }
 
index bc5b4d98fbd40f5cc8f8626466a9914e5a4cf9fc..18fe082e665835b0d2cfc62aa2316248ab1a16fc 100755 (executable)
@@ -1,4 +1,4 @@
-#!/usr/bin/perl 
+#!/usr/bin/perl -w
 
 #  This code was developped by IDEALX (http://IDEALX.org/) and
 #  contributors (their names can be found in the CONTRIBUTORS file).
 #       . originally by David Le Corfec <david.le-corfec@IDEALX.com>
 
 use strict;
+use FindBin;
+use FindBin qw($RealBin);
+use lib "$RealBin/";
 use smbldap_tools;
-
 use Getopt::Std;
 my %Options;
 
index 0d0efa384c674662c8f1283a67f6899490cc3cde..86f52cb53e1b753ac94aac051ff4be8e6637dc84 100755 (executable)
@@ -1,4 +1,4 @@
-#!/usr/bin/perl
+#!/usr/bin/perl -w
 
 #  This code was developped by IDEALX (http://IDEALX.org/) and
 #  contributors (their names can be found in the CONTRIBUTORS file).
 
 use strict;
 use Getopt::Std;
+use FindBin;
+use FindBin qw($RealBin);
+use lib "$RealBin/";
 use smbldap_tools;
 use smbldap_conf;
 
-# smbldap-migrate.pl (-? for help)
+# smbldap-migrate.pl (-? or -h for help)
 #
 # Read pwdump entries on stdin, and add them to the ldap server.
 # Output uncreated/unmodified entries (see parameters -C -U)
@@ -38,20 +41,19 @@ use smbldap_conf;
 sub modify_account
 {
   my ($login, $basedn, $lmpwd, $ntpwd, $gecos, $homedir) = @_;
-
-  my $tmpldif =
-"dn: uid=$login,$basedn
-changetype: modify
-lmpassword: $lmpwd
-ntpassword: $ntpwd
-gecos: $gecos
-sambaHomePath: $homedir
-
-";
-
-  die "$0: error while modifying user $login\n"
-      unless (do_ldapmodify($tmpldif) == 0);
-  undef $tmpldif;
+       # bind to a directory with dn and password
+       my $ldap_master=connect_ldap_master();
+       my $modify = $ldap_master->modify ("uid=$login,$basedn",
+               changes => [
+                       replace => [lmpassword => "$lmpwd"],
+                       replace => [ntpassword => "$ntpwd"],
+                       replace => [gecos => "$gecos"],
+                       replace => [sambaHomePath => "$homedir"]
+               ]
+       );
+       $modify->code && die "failed to modify entry: ", $modify->error ;
+       # take down the session
+       $ldap_master->unbind;
 }
 
 #####################
@@ -59,9 +61,9 @@ sambaHomePath: $homedir
 
 my %Options;
 
-my $ok = getopts('awA:CUW:?', \%Options);
+my $ok = getopts('awA:CUW:?h', \%Options);
 
-if ( (!$ok) || ($Options{'?'}) ) {
+if ( (!$ok) || ($Options{'?'}) || ($Options{'h'}) ) {
         print "Usage: $0 [-awAWCU?]\n";
         print "  -a         process only people, ignore computers\n";
         print "  -w         process only computers, ignore persons\n";
@@ -69,7 +71,7 @@ if ( (!$ok) || ($Options{'?'}) ) {
         print "  -W <opts>  option string passed verbatim to smbldap-useradd for computers\n";
         print "  -C         if entry not found, don't create it and log it to stdout (default: create it)\n";
         print "  -U         if entry found, don't update it and log it to stdout (default: update it)\n";
-        print "  -?         show this help message\n";
+  print "  -?|-h      show this help message\n";
         exit (1);
 }
 
@@ -81,8 +83,7 @@ my %errors = ( 'user' => 0, 'machine' => 0);
 my %existing = ( 'user' => 0, 'machine' => 0);
 my $specialskipped = 0;
 
-while (<>)
-{
+while (<>) {
   my ($login, $rid, $lmpwd, $ntpwd, $gecos, $homedir, $b) = split(/:/, $_);
   my $usertype;
   my $userbasedn;
@@ -99,8 +100,7 @@ while (<>)
  
     $usertype = "-w $Options{'W'}";
     $userbasedn = $computersdn;
-  }
-  else { # people
+  } else {                                             # people
     $processed{'user'}++;
     if (defined($Options{'w'})) {
       print STDERR "ignoring $login\n";
@@ -124,7 +124,7 @@ while (<>)
 
   # normalize gecos
   if (!($gecos eq "")) {
-    $gecos =~ tr/ÁÀÂÄáàâäÇçÉÈÊËÆéèêëæÍÌÏÎíìîÏÑñÓÒÔÖóòôöÚÙÜÛúùüûÝýÿ/AAAAaaaaCcEEEEEeeeeeIIIIiiiiNnOOOOooooUUUUuuuuYyy/;
+    $gecos =~ tr/ÁÀÂÄáàâäÇçÉÈÊËÆéèêëæÍÌÏÎíìîÏÑñÓÒÔÖóòôöÚÙÜÛúùüûÝýÿ/AAAAaaaaCcEEEEEeeeeeIIIIiiiiNnOOOOooooUUUUuuuuYyy/;
   } else {
     $gecos = $_userGecos;
   }
@@ -142,25 +142,21 @@ while (<>)
         next;
       }
        # lem modif... a retirer si pb
-       if ($entry_type eq "user")
-       {
+         if ($entry_type eq "user") {
        modify_account($login, $userbasedn, $lmpwd, $ntpwd, $gecos, $homedir);
        }
 
        $created{$entry_type}++;
-    }
-    else { # uid doesn't exist and no create => log
+    } else {                                   # uid doesn't exist and no create => log
       print "$_";
       $logged{$entry_type}++;
     }
-  }
-  else { # account exists
+  } else {                                             # account exists
     $existing{$entry_type}++;
     if (!defined($Options{'U'})) { # exists and modify 
       modify_account($login, $userbasedn, $lmpwd, $ntpwd, $gecos, $homedir);
       $updated{$entry_type}++;
-    }
-    else { # exists and log
+    } else {                                   # exists and log
       print "$_";
       $logged{$entry_type}++;
     }
index 0d3dd07d505f0747e33cd246a34f871b21bd62fd..c60be18caf8f80c03cd3803c8c4df7a48e6ba87a 100644 (file)
@@ -26,6 +26,9 @@
 
 
 use strict;
+use FindBin;
+use FindBin qw($RealBin);
+use lib "$RealBin/";
 use smbldap_tools;
 use smbldap_conf;
 use Getopt::Std;
@@ -175,8 +178,7 @@ my $group_desc;
 my $has_members = 0;
 my @members = ();
 
-while (<>)
-{
+while (<>) {
   my $line = $_;
   chomp($line);
   next if ( $line =~ m/^\s*$/ );
index 29aee97c50c1f891f7802245eb9e659eddca2979..7845e5548e23e0e5bcb4c3f7a52381284904d838 100755 (executable)
@@ -1,4 +1,4 @@
-#!/usr/bin/perl
+#!/usr/bin/perl -w
 
 # LDAP to unix password sync script for samba
 #
@@ -27,6 +27,9 @@
 #       . may also replace /bin/passwd
 
 use strict;
+use FindBin;
+use FindBin qw($RealBin);
+use lib "$RealBin/";
 use smbldap_tools;
 use smbldap_conf;
 
@@ -105,6 +108,9 @@ if ($pass ne $pass2) {
     exit (10);
 }
 
+# First, connecting to the directory
+my $ldap_master=connect_ldap_master();
+
 # only modify smb passwords if smb user
 if ($samba == 1) {
     if (!$with_smbpasswd) {
@@ -116,25 +122,19 @@ if ($samba == 1) {
        my $ntpwd = `$mk_ntpasswd '$pass'`;
         chomp(my $sambaLMPassword = substr($ntpwd, 0, index($ntpwd, ':')));
         chomp(my $sambaNTPassword = substr($ntpwd, index($ntpwd, ':')+1));
-
-# change nt/lm passwords
-       my $tmpldif =
-"$dn_line
-changetype: modify
-replace: sambaLMPassword
-sambaLMPassword: $sambaLMPassword
--
-changetype: modify
-replace: sambaNTPassword
-sambaNTPassword: $sambaNTPassword
--
-
-";
-       die "$0: error while modifying password for $user\n"
-           unless (do_ldapmodify($tmpldif) == 0);
-       undef $tmpldif;
-    }
-    else {
+       # the sambaPwdLastSet must be updating
+       my $date=time;
+       # Let's change nt/lm passwords
+       my $modify = $ldap_master->modify ( "$dn",
+                                                                               changes => [
+                                                                                                       replace => [sambaLMPassword => "$sambaLMPassword"],
+                                                                                                       replace => [sambaNTPassword => "$sambaNTPassword"],
+                                                                                                       replace => [sambaPwdLastSet => "$date"]
+                                                                                                  ]
+                                                                         );
+       $modify->code && warn "failed to modify entry: ", $modify->error ;
+
+  } else {
        if ($< != 0) {
            my $FILE="|$smbpasswd -s >/dev/null";
            open (FILE, $FILE) || die "$!\n";
@@ -157,13 +157,19 @@ EOF
        }
     }
 }
+
 # change unix password
-$ret = system "$ldappasswd $dn -s '$pass' > /dev/null";
-if ($ret == 0) {
-    print "all authentication tokens updated successfully\n";
-} else {
-    return $ret;
-}
+my $hash_password = `slappasswd -h {$hash_encrypt} -s '$pass'`;
+chomp($hash_password);
+my $modify = $ldap_master->modify ( "$dn",
+       changes => [
+                       replace => [userPassword => "$hash_password"]
+                  ]
+         );
+$modify->code && warn "Unable to change password : ", $modify->error ;
+
+# take down session
+$ldap_master->unbind;
 
 exit 0;
 
index 1676017c67f752f937ab652470ce026f84ab0504..ce497672a96c55e4fbd0a08be27e9f301516e3df 100755 (executable)
@@ -1,4 +1,4 @@
-#!/usr/bin/perl
+#!/usr/bin/perl -w
 
 # Populate a LDAP base for Samba-LDAP usage
 #
 #       . For lazy people, replace ldapadd (with only an ldif parameter)
 
 use strict;
+use FindBin;
+use FindBin qw($RealBin);
+use lib "$RealBin/";
 use smbldap_tools;
 use smbldap_conf;
-
 use Getopt::Std;
+use Net::LDAP::LDIF;
 
 use vars qw(%oc);
 
@@ -56,6 +59,7 @@ if ( (!$ok) || ($Options{'?'}) ) {
 }
 
 my $_ldifName;
+my $tmp_ldif_file="/tmp/$$.ldif";
 
 if (@ARGV >= 1) {
     $_ldifName = $ARGV[0];
@@ -76,6 +80,7 @@ if (!defined($_ldifName)) {
     my $val;
     my $objcl;
 
+  print "Using builtin directory structure\n";
     if ($suffix =~ m/([^=]+)=([^,]+)/) {
        $attr = $1;
        $val = $2;
@@ -90,8 +95,8 @@ if (!defined($_ldifName)) {
     my ($organisation,$ext) = ($suffix =~ m/dc=(\w+),dc=(\w+)$/);
 
     #my $FILE="|cat";
-    my $FILE="|$ldapadd -c";
-    open (FILE, $FILE) || die "$!\n";
+  my $FILE=$tmp_ldif_file;
+  open (FILE, ">$FILE") || die "Can't open file $FILE: $!\n";
 
     print FILE <<EOF;
 dn: $suffix
@@ -131,11 +136,11 @@ sambaPwdMustChange: 2147483647
 sambaHomePath: $_userSmbHome
 sambaHomeDrive: $_userHomeDrive
 sambaProfilePath: $_userProfile
-sambaPrimaryGroupSID: 512
+sambaPrimaryGroupSID: $SID-512
 sambaLMPassword: XXX
 sambaNTPassword: XXX
 sambaAcctFlags: [U          ]
-sambaSID: $smbldap_conf::SID-2996
+sambaSID: $SID-2996
 loginShell: /bin/false
 gecos: Netbios Domain Administrator
 
@@ -158,11 +163,11 @@ sambaPwdMustChange: 2147483647
 sambaHomePath: $_userSmbHome
 sambaHomeDrive: $_userHomeDrive
 sambaProfilePath: $_userProfile
-sambaPrimaryGroupSID: $smbldap_conf::SID-514
+sambaPrimaryGroupSID: $SID-514
 sambaLMPassword: NO PASSWORDXXXXXXXXXXXXXXXXXXXXX
 sambaNTPassword: NO PASSWORDXXXXXXXXXXXXXXXXXXXXX
 sambaAcctFlags: [NU         ]
-sambaSID: $smbldap_conf::SID-2998
+sambaSID: $SID-2998
 loginShell: /bin/false
 
 dn: cn=Domain Admins,$groupsdn
@@ -248,12 +253,26 @@ description: Netbios Domain Computers accounts
 
 EOF
     close FILE;
-    exit($?)
-
 } else {
-    exec "$ldapadd < $_ldifName";
+  $tmp_ldif_file=$_ldifName;
 }
 
+my $ldap_master=connect_ldap_master();
+my $ldif = Net::LDAP::LDIF->new($tmp_ldif_file, "r", onerror => 'undef' );
+while( not $ldif->eof() ) {
+       my $entry = $ldif->read_entry();
+       if ( $ldif->error() ) {
+               print "Error msg: ",$ldif->error(),"\n";
+               print "Error lines:\n",$ldif->error_lines(),"\n";
+       } else {
+               my $dn = $entry->dn;
+               print "adding new entry: $dn\n";
+               my $result=$ldap_master->add($entry);
+               $result->code && warn "failed to add entry: ", $result->error ;
+       }
+}
+$ldap_master->unbind;
+system "rm -f $tmp_ldif_file";
 exit(0);
 
 
@@ -280,9 +299,7 @@ exit(0);
 
        If you give an extra parameter, it is assumed to be the ldif
        file to use instead of the builtin one. Options -a and -b
-       will be ignored. This usage mode makes the command behave
-       like ldapadd(1) with extra parameters taken from the smbldap-tools
-       config (smbldap_conf.pm).
+       will be ignored. 
 
 =head1 FILES
 
index 99c9525e82430d17d572c8868385cb035d610782..a84d9f68b217eeca5c978f6dcd54c7a26ebec780 100755 (executable)
@@ -1,4 +1,4 @@
-#!/usr/bin/perl 
+#!/usr/bin/perl -w
 
 #  This code was developped by IDEALX (http://IDEALX.org/) and
 #  contributors (their names can be found in the CONTRIBUTORS file).
 # Purpose of smbldap-useradd : user (posix,shadow,samba) add
 
 use strict;
+
+use FindBin;
+use FindBin qw($RealBin);
+use lib "$RealBin/";
 use smbldap_tools;
 use smbldap_conf;
 
@@ -31,7 +35,7 @@ use smbldap_conf;
 use Getopt::Std;
 my %Options;
 
-my $ok = getopts('axnmwPG:u:g:d:s:c:k:A:B:C:D:E:F:H:?', \%Options);
+my $ok = getopts('axnmwPG:u:g:d:s:c:k:A:B:C:D:E:F:H:N:S:?', \%Options);
 
 if ( (!$ok) || (@ARGV < 1) || ($Options{'?'}) ) {
        print "Usage: $0 [-awmugdsckGPABCDEFH?] username\n";
@@ -55,6 +59,8 @@ if ( (!$ok) || (@ARGV < 1) || ($Options{'?'}) ) {
        print "  -E     sambaLogonScript (DOS script to execute on login)\n";
        print "  -F     sambaProfilePath (profile directory, like '\\\\PDC-SRV\\profiles\\foo')\n";
        print "  -H     sambaAcctFlags (samba account control bits like '[NDHTUMWSLKI]')\n";
+  print "  -N   canonical name\n";
+  print "  -S   surname\n";
        print "  -?     show this help message\n";
        exit (1);
 }
@@ -75,7 +81,9 @@ if (!defined($userUidNumber)) {
                $UID_START++;
        }
        $userUidNumber = $UID_START;
-} elsif (getpwuid($userUidNumber)) { die "Uid already exists.\n"; }
+} elsif (getpwuid($userUidNumber)) {
+  die "Uid already exists.\n";
+}
 
 if ($nscd_status == 0) {
    system "/etc/init.d/nscd start > /dev/null 2>&1";
@@ -126,6 +134,14 @@ if (defined($Options{'x'})) {
 # Read only first @ARGV
 my $userName = $ARGV[0];
 
+# untaint $userName (can finish with one or two $)
+if ($userName =~ /^([\w -]+\$?)$/) {
+  $userName = $1;
+} else {
+  print "$0: illegal username\n";
+  exit (1);
+}
+
 # user must not exist in LDAP (should it be nss-wide ?)
 my ($rc, $dn) = get_user_dn2($userName);
 if ($rc and defined($dn)) {
@@ -137,17 +153,24 @@ if ($rc and defined($dn)) {
 }
 
 my $userHomeDirectory;
+my ($userCN, $userSN);
 my $tmp;
-if (!defined($userHomeDirectory = $Options{'d'}))
-{
+if (!defined($userHomeDirectory = $Options{'d'})) {
     $userHomeDirectory = $_userHomePrefix."/".$userName;
 }
 $_userLoginShell = $tmp if (defined($tmp = $Options{'s'}));
 $_userGecos = $tmp if (defined($tmp = $Options{'c'}));
 $_skeletonDir = $tmp if (defined($tmp = $Options{'k'}));
+$userCN = ($Options{'c'} || $userName);
+$userCN = $tmp if (defined($tmp = $Options{'N'}));
+$userSN = $userName;
+$userSN = $tmp if (defined($tmp = $Options{'S'}));
+
 
 ########################
 
+my $ldap_master=connect_ldap_master();
+
 # MACHINE ACCOUNT
 if (defined($tmp = $Options{'w'})) {
    
@@ -163,55 +186,47 @@ if (defined($tmp = $Options{'w'})) {
     }
 
     if (!$with_smbpasswd) {
-       if (!add_samba_machine_mkntpwd($userName, $userUidNumber)) {
-           die "$0: error while adding samba account\n";
-       }
+       # (jtournier)
+       # Objectclass sambaSAMAccount is now added directly by samba when joigning the domain (for samba3)
+       #if (!add_samba_machine_mkntpwd($userName, $userUidNumber)) {
+       #  die "$0: error while adding samba account\n";
+       #}
     } else {
        if (!add_samba_machine($userName)) {
            die "$0: error while adding samba account\n";
        }
-
-       my $tmpldif =
-"dn: uid=$userName,$computersdn
-changetype: modify
-sambaAcctFlags: [W          ]
-
-";
-       die "$0: error while modifying accountflags of $userName\n"
-           unless (do_ldapmodify($tmpldif) == 0);
-       undef $tmpldif;
+       my $modify = $ldap_master->modify ( "$dn",
+                                                                               changes => [
+                                                                                                       replace => [sambaAcctFlags => '[W          ]']
+                                                                                                  ]
+                                                                         );
+       $modify->code && warn "failed to modify entry: ", $modify->error ;
     }
 
     exit 0;
 }
 
-#######################
-
 # USER ACCOUNT
-
 # add posix account first
 
-my $tmpldif =
-"dn: uid=$userName,$usersdn
-objectclass: inetOrgPerson
-objectclass: posixAccount
-cn: $userName
-sn: $userName
-uid: $userName
-uidNumber: $userUidNumber
-gidNumber: $userGidNumber
-homeDirectory: $userHomeDirectory
-loginShell: $_userLoginShell
-gecos: $_userGecos
-description: $_userGecos
-userPassword: {crypt}x
-
-";
+my $add = $ldap_master->add ("uid=$userName,$usersdn",
+                                                        attr => [
+                                                                         'objectclass' => ['top','inetOrgPerson', 'posixAccount'],
+                                                                         'cn'   => "$userCN",
+                                                                         'sn'   => "$userSN",
+                                                                         'uid'   => "$userName",
+                                                                         'uidNumber'   => "$userUidNumber",
+                                                                         'gidNumber'   => "$userGidNumber",
+                                                                         'homeDirectory'   => "$userHomeDirectory",
+                                                                         'loginShell'   => "$_userLoginShell",
+                                                                         'gecos'   => "$_userGecos",
+                                                                         'description'   => "$_userGecos",
+                                                                         'userPassword'   => "{crypt}x"
+                                                                        ]
+                                                       );
+
+$add->code && warn "failed to add entry: ", $add->error ;
 
-die "$0: error while adding posix user $userName\n"
-    unless (do_ldapadd($tmpldif) == 0);
-
-undef $tmpldif;
 
 #if ($createGroup) {
 #    group_add($userName, $userGidNumber);
@@ -267,28 +282,24 @@ if (defined($Options{'a'})) {
            $valacctflags = "$tmp";
        }
 
-       my $tmpldif =
-"dn: uid=$userName,$usersdn
-changetype: modify
-objectClass: inetOrgPerson
-objectclass: posixAccount
-objectClass: sambaSAMAccount
-sambaPwdLastSet: 0
-sambaLogonTime: 0
-sambaLogoffTime: 2147483647
-sambaKickoffTime: 2147483647
-sambaPwdCanChange: $valpwdcanchange
-sambaPwdMustChange: $valpwdmustchange
-displayName: $_userGecos
-sambaAcctFlags: $valacctflags
-sambaSID: $smbldap_conf::SID-$userRid
-
-";
+
+       my $modify = $ldap_master->modify ( "uid=$userName,$usersdn",
+                                                                               changes => [
+                                                                                                       add => [objectClass => 'sambaSAMAccount'],
+                                                                                                       add => [sambaPwdLastSet => '0'],
+                                                                                                       add => [sambaLogonTime => '0'],
+                                                                                                       add => [sambaLogoffTime => '2147483647'],
+                                                                                                       add => [sambaKickoffTime => '2147483647'],
+                                                                                                       add => [sambaPwdCanChange => "$valpwdcanchange"],
+                                                                                                       add => [sambaPwdMustChange => "$valpwdmustchange"],
+                                                                                                       add => [displayName => "$_userGecos"],
+                                                                                                       add => [sambaAcctFlags => "$valacctflags"],
+                                                                                                       add => [sambaSID => "$SID-$userRid"]
+                                                                                                  ]
+                                                                         );
        
-       die "$0: error while adding samba account to posix user $userName\n"
-           unless (do_ldapmodify($tmpldif) == 0);
+       $modify->code && die "failed to add entry: ", $modify->error ;
 
-       undef $tmpldif;
     } else {
        my $FILE="|smbpasswd -s -a $userName >/dev/null" ;
        open (FILE, $FILE) || die "$!\n";
@@ -326,24 +337,24 @@ if (defined($tmp = $Options{'F'})) {
     $valprofilepath = "$tmp";
 }
 
-    my $tmpldif =
-"dn: uid=$userName,$usersdn
-changetype: modify
-sambaSID: $smbldap_conf::SID-$userRid
-sambaPrimaryGroupSID: $smbldap_conf::SID-$userGroupRid
-sambaHomeDrive: $valhomedrive
-sambaHomePath: $valsmbhome
-sambaProfilePath: $valprofilepath
-sambaLogonScript: $valscriptpath
-sambaLMPassword: XXX
-sambaNTPassword: XXX
-
-";
-
-    die "$0: error while modifying samba account of user $userName\n"
-           unless (do_ldapmodify($tmpldif) == 0);
-    undef $tmpldif;
+       
+  my $modify = $ldap_master->modify ( "uid=$userName,$usersdn",
+                                                                         changes => [
+                                                                                                 add => [sambaPrimaryGroupSID => "$SID-$userGroupRid"],
+                                                                                                 add => [sambaHomeDrive => "$valhomedrive"],
+                                                                                                 add => [sambaHomePath => "$valsmbhome"],
+                                                                                                 add => [sambaProfilePath => "$valprofilepath"],
+                                                                                                 add => [sambaLogonScript => "$valscriptpath"],
+                                                                                                 add => [sambaLMPassword => 'XXX'],
+                                                                                                 add => [sambaNTPassword => 'XXX']
+                                                                                                ]
+                                                                       );
+
+  $modify->code && die "failed to add entry: ", $modify->error ;
+
 }
+$ldap_master->unbind;                  # take down session
+
 
 if (defined($Options{'P'})) {
     exec "/usr/local/sbin/smbldap-passwd.pl $userName"
@@ -418,8 +429,8 @@ exit 0;
 
        -m     The user's home directory will be created if it does not  exist.
               The  files  contained in skeleton_dir will be copied to the home
-              directory if the -k option is used,  otherwise  the  files  con­
-              tained  in /etc/skel will be used instead.  Any directories con­
+              directory if the -k option is used,  otherwise  the  files  con­
+              tained  in /etc/skel will be used instead.  Any directories con­
               tained in skeleton_dir or  /etc/skel  will  be  created  in  the
               user's  home  directory as well.  The -k option is only valid in
               conjunction with the -m option.  The default is  to  not  create
@@ -451,6 +462,11 @@ exit 0;
 
        -H     sambaAcctFlags, spaces and trailing bracket are ignored (samba account control bits like '[NDHTUMWSLKI]')
 
+       -N     canonical name (defaults to gecos or username, if gecos not set)
+
+       -S     surname (defaults to username)
+
+
 =head1 SEE ALSO
 
        useradd(1)
index 435be4fdd0124f256f999cf7a468609efeae7025..1a1a3214b589d99f0f2a6e4b2cb31373b6201e72 100755 (executable)
@@ -23,6 +23,9 @@
 # Purpose of smbldap-userdel : user (posix,shadow,samba) deletion
 
 use strict;
+use FindBin;
+use FindBin qw($RealBin);
+use lib "$RealBin/";
 use smbldap_tools;
 
 
index dffb95bace79929e9f37fcb8b07fd2ea1d1135cd..f25c730fc851172d2033e031c0e51d3dbcd72883 100755 (executable)
@@ -23,6 +23,9 @@
 # Purpose of smbldap-usermod : user (posix,shadow,samba) modification
 
 use strict;
+use FindBin;
+use FindBin qw($RealBin);
+use lib "$RealBin/";
 use smbldap_tools;
 use smbldap_conf;
 
@@ -33,13 +36,13 @@ use Getopt::Std;
 my %Options;
 my $nscd_status;
 
-my $ok = getopts('A:B:C:D:E:F:H:IJxme:f:u:g:G:d:l:s:c:ok:?', \%Options);
-if ( (!$ok) || (@ARGV < 1) || ($Options{'?'}) ) {
-       print "Usage: $0 [-awmugdsckxABCDEFGHI?] username\n";
+my $ok = getopts('A:B:C:D:E:F:H:IJN:S:xme:f:u:g:G:d:l:s:c:ok:?h', \%Options);
+if ( (!$ok) || (@ARGV < 1) || ($Options{'?'}) || ($Options{'h'}) ) {
+  print "Usage: $0 [-awmugdsckxABCDEFGHI?h] username\n";
+  print "Available options are:\n";
        print "  -c     gecos\n";
        print "  -d     home directory\n";
        #print "  -m    move home directory\n";
-       #print "  -e    expire date (YYYY-MM-DD)\n";
        #print "  -f    inactive days\n";
        print "  -u     uid\n";
        print "  -o     uid can be non unique\n";
@@ -47,6 +50,10 @@ if ( (!$ok) || (@ARGV < 1) || ($Options{'?'}) ) {
        print "  -G     supplementary groups (comma separated)\n";
        print "  -l     login name\n";
        print "  -s     shell\n";
+  print "  -N    canonical name\n";
+  print "  -S    surname\n";
+  print " For samba users:\n";
+  print "  -e    expire date (\"YYYY-MM-DD HH:MM:SS\")\n";
        print "  -x     creates rid and primaryGroupID in hex instead of decimal (for Samba 2.2.2 unpatched only)\n";
        print "  -A     can change password ? 0 if no, 1 if yes\n";
        print "  -B     must change password ? 0 if no, 1 if yes\n";
@@ -57,7 +64,7 @@ if ( (!$ok) || (@ARGV < 1) || ($Options{'?'}) ) {
        print "  -H     sambaAcctFlags (samba account control bits like '[NDHTUMWSLKI]')\n";
        print "  -I     disable an user. Can't be used with -H or -J\n";
        print "  -J     enable an user. Can't be used with -H or -I\n";
-       print "  -?     show this help message\n";
+  print "  -?|-h show this help message\n";
        exit (1);
 }
 
@@ -69,30 +76,23 @@ if ($< != 0) {
 # Read only first @ARGV
 my $user = $ARGV[0];
 
-# Read user datas
-my $lines = read_user($user);
-if (!defined($lines)) {
+# Read user data
+my $user_entry = read_user_entry($user);
+if (!defined($user_entry)) {
     print "$0: user $user doesn't exist\n";
     exit (1);
 }
 
-#print "$lines\n";
-my $dn_line;
-if ( $lines =~ /(^dn: .*)/ ) {
-    $dn_line = $1;
-}
-
-chomp($dn_line);
-
 my $samba = 0;
-if ($lines =~ m/objectClass: sambaAccount/) {
+if (grep ($_ =~ /^sambaSamAccount$/i, $user_entry->get_value('objectClass'))) {
     $samba = 1;
 }
 
-############
+# get the dn of the user
+my $dn= $user_entry->dn();
 
 my $tmp;
-my $mods;
+my @mods;
 
 # Process options
 my $changed_uid;
@@ -119,15 +119,15 @@ if (defined($tmp = $Options{'u'})) {
        }
 
     }
+  push(@mods, 'uidNumber', $tmp);
     $_userUidNumber = $tmp;
+  if ($samba) {
     # as rid we use 2 * uid + 1000
     my $_userRid = 2 * $_userUidNumber + 1000;
     if (defined($Options{'x'})) {
        $_userRid= sprint("%x", $_userRid);
     }
-    $mods .= "uidNumber: $_userUidNumber\n";
-    if ($samba) {
-       $mods .= "rid: $_userRid\n";
+    push(@mods, 'sambaSID', $SID.'-'.$_userRid);
     }
     $changed_uid = 1;
 }
@@ -141,42 +141,42 @@ if (defined($tmp = $Options{'g'})) {
        print "$0: group $tmp doesn't exist\n";
        exit (6);
     }
+  push(@mods, 'gidNumber', $_userGidNumber);
+  if ($samba) {
 # as grouprid we use 2 * gid + 1001
     my $_userGroupRid = 2 * $_userGidNumber + 1001;
     if (defined($Options{'x'})) {
        $_userGroupRid = sprint("%x", $_userGroupRid);
     }
-    $mods .= "gidNumber: $_userGidNumber\n";
-    if ($samba) {
-       $mods .= "primaryGroupID: $_userGroupRid\n";
+    push(@mods, 'sambaPrimaryGroupSid', $SID.'-'.$_userGroupRid);
     }
     $changed_gid = 1;
 }
 
-my $changed_shell;
-my $_userLoginShell;
 if (defined($tmp = $Options{'s'})) {
-    $_userLoginShell = $tmp;
-    $mods .= "loginShell: $_userLoginShell\n";
-    $changed_shell = 1;
+  push(@mods, 'loginShell' => $tmp);
 }
 
-my $changed_gecos;
-my $_userGecos;
+
 if (defined($tmp = $Options{'c'})) { 
-    $_userGecos = $tmp;
-    $mods .= "gecos: $_userGecos\n";
-    $changed_gecos = 1;
+  push(@mods, 'gecos' => $tmp,
+          'description' => $tmp);
+  if ($samba == 1) {
+    push(@mods, 'displayName' => $tmp);
+  }
 }
 
-my $changed_homedir;
-my $newhomedir;
 if (defined($tmp = $Options{'d'})) {
-    $newhomedir = $tmp; 
-    $mods .= "homeDirectory: $newhomedir\n";
-    $changed_homedir = 1;
+  push(@mods, 'homeDirectory' => $tmp);
 }
 
+if (defined($tmp = $Options{'N'})) { 
+  push(@mods, 'cn' => $tmp);
+}
+
+if (defined($tmp = $Options{'S'})) { 
+  push(@mods, 'sn' => $tmp);
+}
 
 if (defined($tmp = $Options{'G'})) {
 
@@ -212,102 +212,135 @@ if (defined($tmp = $Options{'G'})) {
 my $attr;
 my $winmagic = 2147483647;
 
+my $samba = is_samba_user($user);
+
+if (defined($tmp = $Options{'e'})) {
+  if ($samba == 1) {
+       my $kickoffTime=`date --date='$tmp' +%s`;
+       chomp($kickoffTime);
+       push(@mods, 'sambakickoffTime' => $kickoffTime);
+  } else {
+       print "User $user is not a samba user\n";
+  }
+}
+
+my $_sambaPwdCanChange;
 if (defined($tmp = $Options{'A'})) {
+  if ($samba == 1) {
     $attr = "sambaPwdCanChange";
     if ($tmp != 0) {
-       $mods .= "$attr: 0\n";
+      $_sambaPwdCanChange=0;
     } else {
-       $mods .= "$attr: $winmagic\n";
+      $_sambaPwdCanChange=$winmagic;
+    }
+    push(@mods, 'sambaPwdCanChange' => $_sambaPwdCanChange);
+    } else {
+       print "User $user is not a samba user\n";
     }
 }
 
+my $_sambaPwdMustChange;
 if (defined($tmp = $Options{'B'})) {
-    $attr = "sambaPwdMustChange";
+  if ($samba == 1) {
     if ($tmp != 0) {
-       $mods .= "$attr: 0\n";
+      $_sambaPwdMustChange=0;
+    } else {
+      $_sambaPwdMustChange=$winmagic;
+    }
+    push(@mods, 'sambaPwdMustChange' => $_sambaPwdMustChange);
     } else {
-       $mods .= "$attr: $winmagic\n";
+       print "User $user is not a samba user\n";
     }
 }
 
 if (defined($tmp = $Options{'C'})) {
-    $attr = "sambaHomePath";
+  if ($samba == 1) {
     #$tmp =~ s/\\/\\\\/g;
-    $mods .= "$attr: $tmp\n";
+    push(@mods, 'sambaHomePath' => $tmp);
+  } else {
+       print "User $user is not a samba user\n";
+  }
 }
 
+my $_sambaHomeDrive;
 if (defined($tmp = $Options{'D'})) {
-    $attr = "sambaHomeDrive";
+  if ($samba == 1) {
     $tmp = $tmp.":" unless ($tmp =~ /:/);
-    $mods .= "$attr: $tmp\n";
+    push(@mods, 'sambaHomeDrive' => $tmp);
+  } else {
+       print "User $user is not a samba user\n";
+  }
 }
 
 if (defined($tmp = $Options{'E'})) {
-    $attr = "sambaLogonScript";
+  if ($samba == 1) {
     #$tmp =~ s/\\/\\\\/g;
-    $mods .= "$attr: $tmp\n";
+    push(@mods, 'sambaLogonScript' => $tmp);
+  } else {
+       print "User $user is not a samba user\n";
+  }
 }
 
 if (defined($tmp = $Options{'F'})) {
-    $attr = "sambaProfilePath";
+  if ($samba == 1) {
     #$tmp =~ s/\\/\\\\/g;
-    $mods .= "$attr: $tmp\n";
+    push(@mods, 'sambaProfilePath' => $tmp);
+  } else {
+       print "User $user is not a samba user\n";
+  }
 }
 
+if ($samba == 1 and (defined $Options{'H'} or defined $Options{'I'} or defined $Options{'J'})) {
+  my $_sambaAcctFlags;
 if (defined($tmp = $Options{'H'})) {
-    $attr = "sambaAcctFlags";
     #$tmp =~ s/\\/\\\\/g;
-    $mods .= "$attr: $tmp\n";
-} elsif (defined($tmp = $Options{'I'})) {
+    $_sambaAcctFlags=$tmp;
+  } else {
+    # I or J
     my $flags;
+    $flags = $user_entry->get_value('sambaAcctFlags');
 
-    if ( $lines =~ /^sambaAcctFlags: (.*)/m ) {
-       $flags = $1;
-    }
-
-    chomp($flags);
-
+    if (defined($tmp = $Options{'I'})) {
     if ( !($flags =~ /D/) ) {
        my $letters;
        if ($flags =~ /(\w+)/) {
            $letters = $1;
        }
-       $mods .= "sambaAcctFlags: \[D$letters\]\n";
+               $_sambaAcctFlags="\[D$letters\]";
     }
 } elsif (defined($tmp = $Options{'J'})) {
-    my $flags;
-
-    if ( $lines =~ /^sambaAcctFlags: (.*)/m ) {
-       $flags = $1;
-    }
-
-    chomp($flags);
-
     if ( $flags =~ /D/ ) {
        my $letters;
        if ($flags =~ /(\w+)/) {
            $letters = $1;
        }
        $letters =~ s/D//;
-       $mods .= "sambaAcctFlags: \[$letters\]\n";
+               $_sambaAcctFlags="\[$letters\]";
+         }
     }
 }
 
-if ($mods ne '') {
-    #print "----\n$dn_line\n$mods\n----\n";
-
-    my $tmpldif =
-"$dn_line
-changetype: modify
-$mods
-";
 
-    die "$0: error while modifying user $user\n"
-       unless (do_ldapmodify($tmpldif) == 0);
+  if ("$_sambaAcctFlags" ne '') {
+    push(@mods, 'sambaAcctFlags' => $_sambaAcctFlags);
+  }
 
-    undef $tmpldif;
+} elsif (!$samba == 1 and (defined $Options{'H'} or defined $Options{'I'} or defined $Options{'J'})) {
+  print "User $user is not a samba user\n";
 }
 
+# Let's connect to the directory first
+my $ldap_master=connect_ldap_master();
+
+# apply changes
+my $modify = $ldap_master->modify ( "$dn",
+                                                                       'replace' => { @mods }
+                                                                 );
+$modify->code && warn "failed to modify entry: ", $modify->error ;
+
+# take down session
+$ldap_master->unbind;
+
 $nscd_status = system "/etc/init.d/nscd status >/dev/null 2>&1";
 
 if ($nscd_status == 0) {
@@ -358,7 +391,7 @@ if ($nscd_status == 0) {
 
        -l login_name
               The  name  of the user will be changed from login to login_name.
-              Nothing else is changed.  In particular, the user's home  direc­
+              Nothing else is changed.  In particular, the user's home  direc­
               tory  name  should  probably be changed to reflect the new login
               name.
 
@@ -369,7 +402,7 @@ if ($nscd_status == 0) {
        -u uid The  numerical  value  of  the  user's  ID.   This value must be
               unique, unless the -o option is used.  The value  must  be  non-
               negative.  Any files which the user owns  and  which  are
-              located  in  the directory tree rooted at the user's home direc­
+              located  in  the directory tree rooted at the user's home direc­
               tory will have the file user ID  changed  automatically.   Files
               outside of the user's home directory must be altered manually.
 
index b05f08762036261af405e6bebb986243c0264bfe..555b35ffd817d2232628caea336d91c86234917e 100755 (executable)
@@ -1,4 +1,4 @@
-#!/usr/bin/perl 
+#!/usr/bin/perl -w
 
 #  This code was developped by IDEALX (http://IDEALX.org/) and
 #  contributors (their names can be found in the CONTRIBUTORS file).
@@ -23,6 +23,9 @@
 # Purpose of smbldap-userdisplay : user (posix,shadow,samba) display
 
 use strict;
+use FindBin;
+use FindBin qw($RealBin);
+use lib "$RealBin/";
 use smbldap_tools;
 
 use Getopt::Std;
index dd1d772ea71350a155d2e679d060bdd670f56b1e..c3d5c1732c731b2539a458af8a9502abac2e2c84 100644 (file)
@@ -30,16 +30,14 @@ package smbldap_conf;
 use vars qw($VERSION @ISA @EXPORT @EXPORT_OK %EXPORT_TAGS
 $UID_START $GID_START $smbpasswd $slaveLDAP $masterLDAP
 $slavePort $masterPort $ldapSSL $slaveURI $masterURI $with_smbpasswd $mk_ntpasswd
-$ldap_path $ldap_opts $ldapsearch $ldapsearchnobind
-$ldapmodify $ldappasswd $ldapadd $ldapdelete $ldapmodrdn
-$suffix $usersdn $computersdn
+$ldap_path $ldap_opts $ldapmodify $suffix $usersdn $computersdn
 $groupsdn $scope $binddn $bindpasswd
 $slaveDN $slavePw $masterDN $masterPw
 $_userLoginShell $_userHomePrefix $_userGecos
 $_defaultUserGid $_defaultComputerGid
 $_skeletonDir $_userSmbHome
 $_userProfile $_userHomeDrive
-$_userScript $usersou $computersou $groupsou
+$_userScript $usersou $computersou $groupsou $SID $hash_encrypt
 );
 
 use Exporter;
@@ -49,14 +47,13 @@ $VERSION = 1.00;
 @EXPORT = qw(
 $UID_START $GID_START $smbpasswd $slaveLDAP $masterLDAP
 $slavePort $masterPort $ldapSSL $slaveURI $masterURI $with_smbpasswd $mk_ntpasswd
-$ldap_path $ldap_opts $ldapsearch $ldapsearchnobind $ldapmodify $ldappasswd
-$ldapadd $ldapdelete $ldapmodrdn $suffix $usersdn
+$ldap_path $ldap_opts $ldapmodify $suffix $usersdn
 $computersdn $groupsdn $scope $binddn $bindpasswd
 $slaveDN $slavePw $masterDN $masterPw
 $_userLoginShell $_userHomePrefix $_userGecos
 $_defaultUserGid $_defaultComputerGid $_skeletonDir 
 $_userSmbHome $_userProfile $_userHomeDrive $_userScript
-$usersou $computersou $groupsou
+$usersou $computersou $groupsou $SID $hash_encrypt
 );
 
 
@@ -66,16 +63,13 @@ $usersou $computersou $groupsou
 #
 ##############################################################################
 
-#
 # UID and GID starting at...
-#
-
 $UID_START = 1000;
 $GID_START = 1000;
 
 # Put your own SID
-# to obtain this number do: # net getlocalsid
-our $SID='S-1-5-21-636805976-1992644568-3666589737';
+# to obtain this number do: "net getlocalsid"
+$SID='S-1-5-21-3516781642-1962875130-3438800523';
 
 ##############################################################################
 #
@@ -86,84 +80,65 @@ our $SID='S-1-5-21-636805976-1992644568-3666589737';
 # Notes: to use to dual ldap servers backend for Samba, you must patch
 # Samba with the dual-head patch from IDEALX. If not using this patch
 # just use the same server for slaveLDAP and masterLDAP.
-#
-# Slave LDAP : needed for read operations
-#
+# Those two servers declarations can also be used when you have 
+# . one master LDAP server where all writing operations must be done
+# . one slave LDAP server where all reading operations must be done
+#   (typically a replication directory)
+
 # Ex: $slaveLDAP = "127.0.0.1";
 $slaveLDAP = "127.0.0.1";
-
 $slavePort = "389";
 
-# 
 # Master LDAP : needed for write operations
-#
 # Ex: $masterLDAP = "127.0.0.1";
 $masterLDAP = "127.0.0.1";
-
-
-#
-# Master Port
-# 389 636
-# Ex: $masterPort = "
 $masterPort = "389";
 
-#
 # Use SSL for LDAP
-#
+# If set to "1", this option will use start_tls for connection
+# (you should also used the port 389)
 $ldapSSL = "0";
 
-#
 # LDAP Suffix
-#
 # Ex: $suffix = "dc=IDEALX,dc=ORG";
 $suffix = "dc=IDEALX,dc=ORG";
 
 
-# 
 # Where are stored Users
-#
 # Ex: $usersdn = "ou=Users,$suffix"; for ou=Users,dc=IDEALX,dc=ORG
 $usersou = q(_USERS_);
-
 $usersdn = "ou=$usersou,$suffix";
 
-# 
 # Where are stored Computers
-#
 # Ex: $computersdn = "ou=Computers,$suffix"; for ou=Computers,dc=IDEALX,dc=ORG
 $computersou = q(_COMPUTERS_);
-
 $computersdn = "ou=$computersou,$suffix";
 
-# 
 # Where are stored Groups
-# 
 # Ex $groupsdn = "ou=Groups,$suffix"; for ou=Groups,dc=IDEALX,dc=ORG
 $groupsou = q(_GROUPS_);
-
 $groupsdn = "ou=$groupsou,$suffix";
 
-#
 # Default scope Used
-#
 $scope = "sub";
 
-#
-# Credential Configuration
-#
+# Unix password encryption (CRYPT, MD5, SMD5, SSHA, SHA)
+$hash_encrypt="SSHA";
+
+############################
+# Credential Configuration #
+############################
 # Bind DN used 
 # Ex: $binddn = "cn=Manager,$suffix"; for cn=Manager,dc=IDEALX,dc=org
 $binddn = "cn=Manager,$suffix";
-#
+
 # Bind DN passwd used
 # Ex: $bindpasswd = 'secret'; for 'secret'
 $bindpasswd = "secret";
 
-#
 # Notes: if using dual ldap patch, you can specify to different configuration
 # By default, we will use the same DN (so it will work for standard Samba 
 # release)
-#
 $slaveDN = $binddn;
 $slavePw = $bindpasswd;
 $masterDN = $binddn;
@@ -176,36 +151,24 @@ $masterPw = $bindpasswd;
 ##############################################################################
 
 # Login defs
-#
 # Default Login Shell
-#
 # Ex: $_userLoginShell = q(/bin/bash);
 $_userLoginShell = q(_LOGINSHELL_);
 
-#
 # Home directory prefix (without username)
-#
 #Ex: $_userHomePrefix = q(/home/);
 $_userHomePrefix = q(_HOMEPREFIX_);
 
-#
 # Gecos
-#
 $_userGecos = q(System User);
 
-#
 # Default User (POSIX and Samba) GID
-#
-$_defaultUserGid = 100;
+$_defaultUserGid = 513;
 
-#
 # Default Computer (Samba) GID
-#
 $_defaultComputerGid = 553;
 
-#
 # Skel dir
-#
 $_skeletonDir = q(/etc/skel);
 
 ##############################################################################
@@ -214,28 +177,23 @@ $_skeletonDir = q(/etc/skel);
 #
 ##############################################################################
 
-#
 # The UNC path to home drives location without the username last extension
 # (will be dynamically prepended)
 # Ex: q(\\\\My-PDC-netbios-name\\homes) for \\My-PDC-netbios-name\homes
 $_userSmbHome = q(\\\\_PDCNAME_\\homes);
 
-#
 # The UNC path to profiles locations without the username last extension
 # (will be dynamically prepended)
-# Ex: q(\\\\My-PDC-netbios-name\\profiles) for \\My-PDC-netbios-name\profiles
+# Ex: q(\\\\My-PDC-netbios-name\\profiles\\) for \\My-PDC-netbios-name\profiles
 $_userProfile = q(\\\\_PDCNAME_\\profiles\\);
 
-# 
 # The default Home Drive Letter mapping
 # (will be automatically mapped at logon time if home directory exist)
 # Ex: q(U:) for U:
 $_userHomeDrive = q(_HOMEDRIVE_);
 
-#
 # The default user netlogon script name
 # if not used, will be automatically username.cmd
-#
 #$_userScript = q(startup.cmd); # make sure script file is edited under dos
 
 
@@ -251,28 +209,28 @@ $with_smbpasswd = 0;
 $smbpasswd = "/usr/bin/smbpasswd";
 $mk_ntpasswd = "/usr/local/sbin/mkntpwd";
 
-if ( $ldapSSL eq "0" ) {
+# those next externals commands are kept fot the migration scripts and
+# for the populate script: this will be updated as soon as possible
        $slaveURI = "ldap://$slaveLDAP:$slavePort";
        $masterURI = "ldap://$masterLDAP:$masterPort";
-}
-elsif ( $ldapSSL eq "1" ) {
-       $slaveURI = "ldaps://$slaveLDAP:$slavePort";
-       $masterURI = "ldaps://$masterLDAP:$masterPort";
-}
-else {
-       die "ldapSSL option must be either 0 or 1.\n";
-}
-       
 
 $ldap_path = "/usr/bin";
+
+if ( $ldapSSL eq "0" ) {
 $ldap_opts = "-x";
-$ldapsearch = "$ldap_path/ldapsearch $ldap_opts -H $slaveURI -D '$slaveDN' -w '$slavePw'";
-$ldapsearchnobind = "$ldap_path/ldapsearch $ldap_opts -H $slaveURI";
+} elsif ( $ldapSSL eq "1" ) {
+       $ldap_opts = "-x -Z";
+} else {
+       die "ldapSSL option must be either 0 or 1.\n";
+}
+
+#$ldapsearch = "$ldap_path/ldapsearch $ldap_opts -H $slaveURI -D '$slaveDN' -w '$slavePw'";
+#$ldapsearchnobind = "$ldap_path/ldapsearch $ldap_opts -H $slaveURI";
 $ldapmodify = "$ldap_path/ldapmodify $ldap_opts -H $masterURI -D '$masterDN' -w '$masterPw'";
-$ldappasswd = "$ldap_path/ldappasswd $ldap_opts -H $masterURI -D '$masterDN' -w '$masterPw'";
-$ldapadd = "$ldap_path/ldapadd $ldap_opts -H $masterURI -D '$masterDN' -w '$masterPw'";
-$ldapdelete = "$ldap_path/ldapdelete $ldap_opts -H $masterURI -D '$masterDN' -w '$masterPw'";
-$ldapmodrdn = "$ldap_path/ldapmodrdn $ldap_opts -H $masterURI -D '$masterDN' -w '$masterPw'";
+#$ldappasswd = "$ldap_path/ldappasswd $ldap_opts -H $masterURI -D '$masterDN' -w '$masterPw'";
+#$ldapadd = "$ldap_path/ldapadd $ldap_opts -H $masterURI -D '$masterDN' -w '$masterPw'";
+#$ldapdelete = "$ldap_path/ldapdelete $ldap_opts -H $masterURI -D '$masterDN' -w '$masterPw'";
+#$ldapmodrdn = "$ldap_path/ldapmodrdn $ldap_opts -H $masterURI -D '$masterDN' -w '$masterPw'";
 
 
 
index ad6ef74eb646dd08ec9fd38289b1b247467253a8..8001442fe8ff6962381e6f5851832efbf34a5e2a 100755 (executable)
@@ -1,4 +1,4 @@
-#! /usr/bin/perl
+#! /usr/bin/perl -w
 use strict;
 package smbldap_tools;
 use smbldap_conf;
@@ -36,7 +36,9 @@ $VERSION = 1.00;
 @EXPORT = qw(
 get_user_dn
 get_group_dn
+                        is_group_member
 is_samba_user
+                        is_unix_user
 is_user_valid
 get_dn_from_line
 add_posix_machine
@@ -47,8 +49,10 @@ add_grouplist_user
 disable_user
 delete_user
 group_add
+                        group_del
 get_homedir
 read_user
+                        read_user_entry
 read_group
 find_groups_of
 parse_group
@@ -57,32 +61,74 @@ group_get_members
 do_ldapadd
 do_ldapmodify
 get_user_dn2
+                        connect_ldap_master
+                        connect_ldap_slave
 );
 
-# dn_line = get_user_dn($username)
-# where dn_line is like "dn: a=b,c=d"
-
-#sub ldap_search
-#{
-#my ($local_base,$local_scope,$local_filtre)=@_;
-#}
-
+sub connect_ldap_master
+  {
+       # bind to a directory with dn and password
+       my $ldap_master = Net::LDAP->new(
+                                                                        "$masterLDAP",
+                                                                        port => "$masterPort",
+                                                                        version => 3,
+                                                                        # debug => 0xffff,
+                                                                       )
+         or die "erreur LDAP: Can't contact master ldap server ($@)";
+       if ($ldapSSL == 1) {
+         $ldap_master->start_tls(
+                                                         # verify => 'require',
+                                                         # clientcert => 'mycert.pem',
+                                                         # clientkey => 'mykey.pem',
+                                                         # decryptkey => sub { 'secret'; },
+                                                         # capath => '/usr/local/cacerts/'
+                                                        );
+       }
+       $ldap_master->bind ( "$binddn",
+                                                password => "$masterPw"
+                                          );
+       return($ldap_master);
+  }
 
+sub connect_ldap_slave
+  {
+       # bind to a directory with dn and password
+       my $ldap_slave = Net::LDAP->new(
+                                                                       "$slaveLDAP",
+                                                                       port => "$slavePort",
+                                                                       version => 3,
+                                                                       # debug => 0xffff,
+                                                                  )
+         or die "erreur LDAP: Can't contact slave ldap server ($@)";
+       if ($ldapSSL == 1) {
+         $ldap_slave->start_tls(
+                                                        # verify => 'require',
+                                                        # clientcert => 'mycert.pem',
+                                                        # clientkey => 'mykey.pem',
+                                                        # decryptkey => sub { 'secret'; },
+                                                        # capath => '/usr/local/cacerts/'
+                                                       );
+       }
+       $ldap_slave->bind ( "$binddn",
+                                               password => "$slavePw"
+                                         );
+       return($ldap_slave);
+  }
 
 sub get_user_dn
 {
     my $user = shift;
     my $dn='';
-    my $ldap = Net::LDAP->new($slaveLDAP) or die "erreur LDAP";
-    $ldap->bind ;
-    my  $mesg = $ldap->search (    base   => $suffix,
+    my $ldap_slave=connect_ldap_slave();
+    my  $mesg = $ldap_slave->search (    base   => $suffix,
                                   scope => $scope,
                                   filter => "(&(objectclass=posixAccount)(uid=$user))"
                               );
     $mesg->code && die $mesg->error;
     foreach my $entry ($mesg->all_entries) {
-       $dn= $entry->dn;}
-    $ldap->unbind;
+         $dn= $entry->dn;
+       }
+    $ldap_slave->unbind;
     chomp($dn);
     if ($dn eq '') {
        return undef;
@@ -92,28 +138,21 @@ sub get_user_dn
 }
 
 
-sub get_user_dn2     ## migré
+sub get_user_dn2
 {
     my $user = shift;
     my $dn='';
-    my $ldap = Net::LDAP->new($slaveLDAP) or die "erreur LDAP";
-    $ldap->bind ;
-    my  $mesg = $ldap->search (    base   => $suffix,
+    my $ldap_slave=connect_ldap_slave();
+    my  $mesg = $ldap_slave->search (    base   => $suffix,
                                   scope => $scope,
                                filter => "(&(objectclass=posixAccount)(uid=$user))"
                               );
-    # $mesg->code && warn $mesg->error;
-    if ($mesg->code)
-      {
-         print("Code erreur : ",$mesg->code,"\n");
-         print("Message d'erreur : ",$mesg->error,"\n");
-         return (0,undef);
-      }
+    $mesg->code && warn "failed to perform search; ", $mesg->error;
 
     foreach my $entry ($mesg->all_entries) {
        $dn= $entry->dn;
     }
-    $ldap->unbind;
+    $ldap_slave->unbind;
     chomp($dn);
     if ($dn eq '') {
        return (1,undef);
@@ -127,16 +166,16 @@ sub get_group_dn
   {
       my $group = shift;
       my $dn='';
-      my $ldap = Net::LDAP->new($slaveLDAP) or die "erreur LDAP";
-      $ldap->bind ;
-      my  $mesg = $ldap->search (    base   => $groupsdn,
+       my $ldap_slave=connect_ldap_slave();
+       my  $mesg = $ldap_slave->search (    base   => $groupsdn,
                                     scope => $scope,
                                     filter => "(&(objectclass=posixGroup)(|(cn=$group)(gidNumber=$group)))"
                                );
       $mesg->code && die $mesg->error;
       foreach my $entry ($mesg->all_entries) {
-         $dn= $entry->dn;}
-      $ldap->unbind;
+         $dn= $entry->dn;
+       }
+       $ldap_slave->unbind;
       chomp($dn);
       if ($dn eq '') {
          return undef;
@@ -150,14 +189,41 @@ sub get_group_dn
 sub is_samba_user
   {
       my $user = shift;
-      my $ldap = Net::LDAP->new($slaveLDAP) or die "erreur LDAP";
-      $ldap->bind ;
-      my $mesg = $ldap->search (    base   => $suffix,
+       my $ldap_slave=connect_ldap_slave();
+       my $mesg = $ldap_slave->search (    base   => $suffix,
                                    scope => $scope,
                                    filter => "(&(objectClass=sambaSamAccount)(uid=$user))"
                               );
       $mesg->code && die $mesg->error;
-      $ldap->unbind;
+       $ldap_slave->unbind;
+       return ($mesg->count ne 0);
+  }
+
+sub is_unix_user
+  {
+       my $user = shift;
+       my $ldap_slave=connect_ldap_slave();
+       my $mesg = $ldap_slave->search (    base   => $suffix,
+                                                                               scope => $scope,
+                                                                               filter => "(&(objectClass=posixAccount)(uid=$user))"
+                                                                  );
+       $mesg->code && die $mesg->error;
+       $ldap_slave->unbind;
+       return ($mesg->count ne 0);
+  }
+
+sub is_group_member
+  {
+       my $dn_group = shift;
+       my $user = shift;
+       my $ldap_slave=connect_ldap_slave();
+       my $mesg = $ldap_slave->search (
+                                                                       base   => "$dn_group",
+                                                                       scope => 'base',
+                                                                       filter => "(&(memberUid=$user))"
+                                                                  );
+       $mesg->code && die $mesg->error;
+       $ldap_slave->unbind;
       return ($mesg->count ne 0);
   }
 
@@ -168,21 +234,19 @@ sub is_user_valid
       my ($user, $dn, $pass) = @_;
       my $ldap = Net::LDAP->new($slaveLDAP) or die "erreur LDAP";
       my $mesg= $ldap->bind (dn => $dn, password => $pass );
-      if ($mesg->code eq 0)
-       {
+       if ($mesg->code eq 0) {
            $ldap->unbind;
            return 1;
-       }
-      else
-       {
+       } else {
            if($ldap->bind()) {
                $ldap->unbind;
                return 0;
            } else {
-               print ("Le serveur LDAP est indisponible.\nVérifier le serveur, les câblages, ...");
+               print ("The LDAP directory is not available.\n Check the server, cables ...");
                $ldap->unbind;
                return 0;
-           } die "Problème : Contacter votre administrateur";
+         }
+         die "Problem : contact your administrator";
        }
 }
 
@@ -199,27 +263,29 @@ sub get_dn_from_line
 sub add_posix_machine
   {
       my ($user, $uid, $gid) = @_;
-      my $tmpldif =
-       "dn: uid=$user,$computersdn
-objectclass: inetOrgPerson
-objectclass: posixAccount
-sn: $user
-cn: $user
-uid: $user
-uidNumber: $uid
-gidNumber: $gid
-homeDirectory: /dev/null
-loginShell: /bin/false
-description: Computer
-
-";
-
-      die "$0: error while adding posix account to machine $user\n"
-       unless (do_ldapadd($tmpldif) == 0);
-      undef $tmpldif;
-      return 1;
+       # bind to a directory with dn and password
+       my $ldap_master=connect_ldap_master();
+       my $add = $ldap_master->add ( "uid=$user,$computersdn",
+                                                                 attr => [
+                                                                                  'objectclass' => ['top','inetOrgPerson', 'posixAccount'],
+                                                                                  'cn'   => "$user",
+                                                                                  'sn'   => "$user",
+                                                                                  'uid'   => "$user",
+                                                                                  'uidNumber'   => "$uid",
+                                                                                  'gidNumber'   => "$gid",
+                                                                                  'homeDirectory'   => '/dev/null',
+                                                                                  'loginShell'   => '/bin/false',
+                                                                                  'description'   => 'Computer',
+                                                                                 ]
+                                                               );
+       
+       $add->code && warn "failed to add entry: ", $add->error ;
+       # take down the session
+       $ldap_master->unbind;
+
   }
 
+
 # success = add_samba_machine($computername)
 sub add_samba_machine
 {
@@ -244,33 +310,31 @@ sub add_samba_machine_mkntpwd
       chomp(my $lmpassword = substr($ntpwd, 0, index($ntpwd, ':')));
       chomp(my $ntpassword = substr($ntpwd, index($ntpwd, ':')+1));
 
-      my $tmpldif =
-       "dn: uid=$user,$computersdn
-changetype: modify
-objectclass: inetOrgPerson
-objectclass: posixAccount
-objectClass: sambaSamAccount
-sambaPwdLastSet: 0
-sambaLogonTime: 0
-sambaLogoffTime: 2147483647
-sambaKickoffTime: 2147483647
-sambaPwdCanChange: 0
-sambaPwdMustChange: 2147483647
-sambaAcctFlags: [W          ]
-sambaLMPassword: $lmpassword
-sambaNTPassword: $ntpassword
-sambaSID: $smbldap_conf::SID-$sambaSID
-sambaPrimaryGroupSID: $smbldap_conf::SID-0
-
-";
-
-      die "$0: error while adding samba account to $user\n"
-       unless (do_ldapmodify($tmpldif) == 0);
-      undef $tmpldif;
+       my $ldap_master=connect_ldap_master();
+       my $modify = $ldap_master->modify ( "uid=$user,$computersdn",
+                                                                               changes => [
+                                                                                                       replace => [objectClass => ['inetOrgPerson', 'posixAccount', 'sambaSAMAccount']],
+                                                                                                       add => [sambaPwdLastSet => '0'],
+                                                                                                       add => [sambaLogonTime => '0'],
+                                                                                                       add => [sambaLogoffTime => '2147483647'],
+                                                                                                       add => [sambaKickoffTime => '2147483647'],
+                                                                                                       add => [sambaPwdCanChange => '0'],
+                                                                                                       add => [sambaPwdMustChange => '0'],
+                                                                                                       add => [sambaAcctFlags => '[W          ]'],
+                                                                                                       add => [sambaLMPassword => "$lmpassword"],
+                                                                                                       add => [sambaNTPassword => "$ntpassword"],
+                                                                                                       add => [sambaSID => "$SID-$sambaSID"],
+                                                                                                       add => [sambaPrimaryGroupSID => "$SID-0"]
+                                                                                                  ]
+                                                                         );
+       
+       $modify->code && die "failed to add entry: ", $modify->error ;
 
       return 1;
-  }
+       # take down the session
+       $ldap_master->unbind;
 
+  }
 
 
 sub group_add_user
@@ -278,55 +342,43 @@ sub group_add_user
       my ($group, $userid) = @_;
       my $members='';
       my $dn_line = get_group_dn($group);
+       if (!defined(get_group_dn($group))) {
+         print "$0: group \"$group\" doesn't exist\n";
+         exit (6); 
+       }
       if (!defined($dn_line)) {
          return 1;
       }
-      my $dn = get_dn_from_line($dn_line);
-
-      my $ldap = Net::LDAP->new($slaveLDAP) or die "erreur LDAP";
-      $ldap->bind ;
-      my  $mesg = $ldap->search (    base   =>$dn, scope => "base", filter => "(objectClass=*)" );
-      $mesg->code && die $mesg->error;
-      foreach my $entry ($mesg->all_entries){
-         foreach my $attr ($entry->attributes)
-           {
-               if ($attr=~/\bmemberUid\b/){
-                   foreach my $ent($entry->get_value($attr)) { $members.= $attr.": ".$ent."\n"; }
-               }
+       my $dn = get_dn_from_line("$dn_line");
+       # on look if the user is already present in the group
+       my $is_member=is_group_member($dn,$userid);
+       if ($is_member == 1) {
+         print "User \"$userid\" already member of the group \"$group\".\n";
+       } else {
+         # bind to a directory with dn and password
+         my $ldap_master=connect_ldap_master();
+         # It does not matter if the user already exist, Net::LDAP will add the user
+         # if he does not exist, and ignore him if his already in the directory.
+         my $modify = $ldap_master->modify ( "$dn",
+                                                                                 changes => [
+                                                                                                         add => [memberUid => $userid]
+                                                                                                        ]
+                                                                               );
+         $modify->code && die "failed to modify entry: ", $modify->error ;
+         # take down session
+         $ldap_master->unbind;
            }
       }
-      $ldap->unbind;
-      chomp($members);
-      # user already member ?
-      if ($members =~ m/^memberUid: $userid/) {
-         return 2;
-      }
-      my $mods = "";
-      if ($members ne '') {
-         $mods="$dn_line
-changetype: modify
-replace: memberUid
-$members
-memberUid: $userid
-
-";
-      } else {
-         $mods="$dn_line
-changetype: modify
-add: memberUid
-memberUid: $userid
 
-";
-      }
-    #print "$mods\n";
-      my $tmpldif =
-       "$mods
-";
-
-      die "$0: error while modifying group $group\n"
-       unless (do_ldapmodify($tmpldif) == 0);
-      undef $tmpldif;
-      return 0;
+sub group_del
+  {
+       my $group_dn=shift;
+       # bind to a directory with dn and password
+       my $ldap_master=connect_ldap_master();
+       my $modify = $ldap_master->delete ($group_dn);
+       $modify->code && die "failed to delete group : ", $modify->error ;
+       # take down session
+       $ldap_master->unbind;
   }
 
 sub add_grouplist_user
@@ -338,43 +390,34 @@ sub add_grouplist_user
       }
   }
 
-# XXX FIXME : sambaAcctFlags |= D, and not sambaAcctFlags = D
 sub disable_user
   {
       my $user = shift;
       my $dn_line;
+       my $dn = get_dn_from_line($dn_line);
 
       if (!defined($dn_line = get_user_dn($user))) {
          print "$0: user $user doesn't exist\n";
          exit (10);
       }
-
-      my $tmpldif =
-       "dn: $dn_line
-changetype: modify
-replace: userPassword
-userPassword: {crypt}!x
-
-";
-
-      die "$0: error while modifying user $user\n"
-       unless (do_ldapmodify($tmpldif) == 0);
-      undef $tmpldif;
+       my $ldap_master=connect_ldap_master();
+       my $modify = $ldap_master->modify ( "$dn",
+                                                                               changes => [
+                                                                                                       replace => [userPassword => '{crypt}!x']
+                                                                                                  ]
+                                                                         );
+       $modify->code && die "failed to modify entry: ", $modify->error ;
 
       if (is_samba_user($user)) {
-
-         my $tmpldif =
-           "dn: $dn_line
-changetype: modify
-replace: sambaAcctFlags
-sambaAcctFlags: [D       ]
-
-";
-
-         die "$0: error while modifying user $user\n"
-           unless (do_ldapmodify($tmpldif) == 0);
-         undef $tmpldif;
+         my $modify = $ldap_master->modify ( "$dn",
+                                                                                 changes => [
+                                                                                                         replace => [sambaAcctFlags => '[D       ]']
+                                                                                                        ]
+                                                                               );
+         $modify->code && die "failed to modify entry: ", $modify->error ;
       }
+       # take down session
+       $ldap_master->unbind;
   }
 
 # delete_user($user)
@@ -389,7 +432,9 @@ sub delete_user
       }
 
       my $dn = get_dn_from_line($dn_line);
-      system "$ldapdelete $dn >/dev/null";
+       my $ldap_master=connect_ldap_master();
+       my $modify = $ldap_master->delete($dn);
+       $ldap_master->unbind;
   }
 
 # $success = group_add($groupname, $group_gid, $force_using_existing_gid)
@@ -415,17 +460,18 @@ sub group_add
       if ($nscd_status == 0) {
          system "/etc/init.d/nscd start > /dev/null 2>&1";
       }
-      my $tmpldif =
-       "dn: cn=$gname,$groupsdn
-objectclass: posixGroup
-cn: $gname
-gidNumber: $gid
-
-";
-
-      die "$0: error while adding posix group $gname\n"
-       unless (do_ldapadd($tmpldif) == 0);
-      undef $tmpldif;
+       my $ldap_master=connect_ldap_master();
+       my $modify = $ldap_master->add ( "cn=$gname,$groupsdn",
+                                                                        attrs => [
+                                                                                          objectClass => 'posixGroup',
+                                                                                          cn => "$gname",
+                                                                                          gidNumber => "$gid"
+                                                                                         ]
+                                                                  );
+       
+       $modify->code && die "failed to add entry: ", $modify->error ;
+       # take down session
+       $ldap_master->unbind;
       return 1;
   }
 
@@ -434,14 +480,15 @@ sub get_homedir
   {
       my $user = shift;
       my $homeDir='';
-      #  my $homeDir=`$ldapsearch -b '$suffix' -s '$scope' '(&(objectclass=posixAccount)(uid=$user))' | grep "^homeDirectory:"`;
-      my $ldap = Net::LDAP->new($slaveLDAP) or die "erreur LDAP";
-      $ldap->bind ;
-      my  $mesg = $ldap->search (    base   =>$suffix, scope => $scope, filter => "(&(objectclass=posixAccount)(uid=$user))" );
+       my $ldap_slave=connect_ldap_slave();
+       my  $mesg = $ldap_slave->search (
+                                                                        base   =>$suffix,
+                                                                        scope => $scope,
+                                                                        filter => "(&(objectclass=posixAccount)(uid=$user))"
+                                                                       );
       $mesg->code && die $mesg->error;
       foreach my $entry ($mesg->all_entries){
-         foreach my $attr ($entry->attributes)
-           {
+         foreach my $attr ($entry->attributes) {
                if ($attr=~/\bhomeDirectory\b/){
                    foreach my $ent($entry->get_value($attr)) {
                        $homeDir.= $attr.": ".$ent."\n";
@@ -449,7 +496,7 @@ sub get_homedir
                }
            }
       }
-      $ldap->unbind;
+       $ldap_slave->unbind;
       chomp $homeDir;
       if ($homeDir eq '') {
          return undef;
@@ -463,9 +510,8 @@ sub read_user
   {
       my $user = shift;
       my $lines ='';
-      my $ldap = Net::LDAP->new($slaveLDAP) or die "erreur LDAP";
-      $ldap->bind ;
-      my  $mesg = $ldap->search (  # perform a search
+       my $ldap_slave=connect_ldap_slave();
+       my $mesg = $ldap_slave->search ( # perform a search
                                 base   => $suffix,
                                 scope => $scope,
                                 filter => "(&(objectclass=posixAccount)(uid=$user))"
@@ -480,7 +526,8 @@ sub read_user
              }
          }
       }
-      $ldap->unbind;   # take down sessio(n
+       # take down session
+       $ldap_slave->unbind;
       chomp $lines;
       if ($lines eq '') {
          return undef;
@@ -488,14 +535,31 @@ sub read_user
       return $lines;
   }
 
+# search for a user
+# return the attributes in an array
+sub read_user_entry
+  {
+       my $user = shift;
+       my $ldap_slave=connect_ldap_slave();
+       my  $mesg = $ldap_slave->search ( # perform a search
+                                                                        base   => $suffix,
+                                                                        scope => $scope,
+                                                                        filter => "(&(objectclass=posixAccount)(uid=$user))"
+                                                                       );
+
+       $mesg->code && die $mesg->error;
+       my $entry = $mesg->entry();
+       $ldap_slave->unbind;
+       return $entry;
+  }
+
 # search for a group
 sub read_group
   {
       my $user = shift;
       my $lines ='';
-      my $ldap = Net::LDAP->new($slaveLDAP) or die "erreur LDAP";
-      $ldap->bind ;
-      my  $mesg = $ldap->search (  # perform a search
+       my $ldap_slave=connect_ldap_slave();
+       my  $mesg = $ldap_slave->search ( # perform a search
                                 base   => $groupsdn,
                                 scope => $scope,
                                 filter => "(&(objectclass=posixGroup)(cn=$user))"
@@ -510,8 +574,8 @@ sub read_group
              }
          }
       }
-
-      $ldap->unbind;   # take down sessio(n
+       # take down session
+       $ldap_slave->unbind;
       chomp $lines;
       if ($lines eq '') {
          return undef;
@@ -525,9 +589,8 @@ sub find_groups_of
   {
       my $user = shift;
       my $lines ='';
-      my $ldap = Net::LDAP->new($slaveLDAP) or die "erreur LDAP";
-      $ldap->bind ;
-      my  $mesg = $ldap->search (  # perform a search
+       my $ldap_slave=connect_ldap_slave;
+       my  $mesg = $ldap_slave->search ( # perform a search
                                 base   => $groupsdn,
                                 scope => $scope,
                                 filter => "(&(objectclass=posixGroup)(memberuid=$user))"
@@ -536,9 +599,11 @@ sub find_groups_of
       foreach my $entry ($mesg->all_entries) {
          $lines.= "dn: ".$entry->dn."\n";
       }
-      $ldap->unbind;
+       $ldap_slave->unbind;
       chomp($lines);
-      if ($lines eq '') {return undef; }
+       if ($lines eq '') {
+         return undef;
+       }
       return $lines;
   }
 
@@ -571,53 +636,20 @@ sub group_remove_member
       if (!defined($grp_line)) {
          return 0;
       }
-
-      my $ldap = Net::LDAP->new($slaveLDAP) or die "erreur LDAP";
-      $ldap->bind ;
-      my  $mesg = $ldap->search (    base   => $groupsdn,
-                                    scope => $scope,
-                                    filter => "(&(objectclass=posixgroup)(cn=$group))"
+       my $dn = get_dn_from_line($grp_line);
+       # we test if the user exist in the group
+       my $is_member=is_group_member($dn,$user);
+       if ($is_member == 1) {
+         my $ldap_master=connect_ldap_master();
+         # delete only the user from the group
+         my $modify = $ldap_master->modify ( "$dn",
+                                                                                 changes => [
+                                                                                                         delete => [memberUid => ["$user"]]
+                                                                                                        ]
                                );
-      $mesg->code && die $mesg->error;
-      foreach my $entry ($mesg->all_entries){
-         foreach my $attr ($entry->attributes)
-           {
-               if ($attr=~/\bmemberUid\b/){
-                   foreach my $ent($entry->get_value($attr)) {
-                       $members.= $attr.": ".$ent."\n";
-                   }
+         $modify->code && die "failed to delete entry: ", $modify->error ;
+         $ldap_master->unbind;
                }
-           }
-      }
-      #print "Valeurs de members :\n$members";
-      $ldap->unbind;
-      #    my $members = `$ldapsearch -b '$groupsdn' -s '$scope' '(&(objectclass=posixgroup)(cn=$group))' | grep -i "^memberUid:"`;
-      # print "avant ---\n$members\n";
-      $members =~ s/memberUid: $user\n//;
-      #print "après ---\n$members\n";
-      chomp($members);
-
-      my $header;
-      if ($members eq '') {
-         $header = "changetype: modify\n";
-         $header .= "delete: memberUid";
-      } else {
-         $header = "changetype: modify\n";
-         $header .= "replace: memberUid";
-      }
-
-      my $tmpldif =
-"$grp_line
-$header
-$members
-";
-
-      #print "Valeur du tmpldif : \n$tmpldif";
-      die "$0: error while modifying group $group\n"
-       unless (do_ldapmodify($tmpldif) == 0);
-      undef $tmpldif;
-
-      $ldap->unbind;
       return 1;
   }
 
@@ -627,11 +659,14 @@ sub group_get_members
       my $members;
       my @resultat;
       my $grp_line = get_group_dn($group);
-      if (!defined($grp_line)) {       return 0;  }
+       if (!defined($grp_line)) {
+         return 0;
+       }
 
       my $ldap = Net::LDAP->new($slaveLDAP) or die "erreur LDAP";
       $ldap->bind ;
-      my  $mesg = $ldap->search (    base   => $groupsdn,
+       my  $mesg = $ldap->search (
+                                                          base   => $groupsdn,
                                     scope => $scope,
                                     filter => "(&(objectclass=posixgroup)(cn=$group))"
                                );
@@ -639,57 +674,13 @@ sub group_get_members
       foreach my $entry ($mesg->all_entries){
          foreach my $attr ($entry->attributes){
              if ($attr=~/\bmemberUid\b/){
-                 foreach my $ent($entry->get_value($attr)) { push (@resultat,$ent); }
+                 foreach my $ent ($entry->get_value($attr)) {
+                       push (@resultat,$ent);
              }
          }
       }
-      return @resultat;
-  }
-
-sub file_write {
-    my ($filename, $filecontent) = @_;
-    local *FILE;
-    open (FILE, "> $filename") ||
-      die "Cannot open $filename for writing: $!\n";
-    print FILE $filecontent;
-    close FILE;
 }
-
-# wrapper for ldapadd
-sub do_ldapadd2
-  {
-      my $ldif = shift;
-      my $tempfile = "/tmp/smbldapadd.$$";
-      file_write($tempfile, $ldif);
-
-      my $rc = system "$ldapadd < $tempfile >/dev/null";
-      unlink($tempfile);
-      return $rc;
-  }
-
-sub do_ldapadd
-  {
-      my $ldif = shift;
-      my $FILE = "|$ldapadd >/dev/null";
-      open (FILE, $FILE) || die "$!\n";
-      print FILE <<EOF;
-$ldif
-EOF
-      ;
-      close FILE;
-      my $rc = $?;
-      return $rc;
-  }
-
-# wrapper for ldapmodify
-sub do_ldapmodify2
-  {
-      my $ldif = shift;
-      my $tempfile = "/tmp/smbldapmod.$$";
-      file_write($tempfile, $ldif);
-      my $rc = system "$ldapmodify -r < $tempfile >/dev/null";
-      unlink($tempfile);
-      return $rc;
+       return @resultat;
   }
 
 sub do_ldapmodify