updating top 0.8.2-1 of the smbldap tools
authorGerald Carter <jerry@samba.org>
Thu, 4 Dec 2003 21:59:20 +0000 (21:59 +0000)
committerGerald Carter <jerry@samba.org>
Thu, 4 Dec 2003 21:59:20 +0000 (21:59 +0000)
(This used to be commit b798f30f0a83ba00ebbe1b82983ca6690642ad02)

22 files changed:
examples/LDAP/smbldap-tools/CONTRIBUTORS
examples/LDAP/smbldap-tools/ChangeLog
examples/LDAP/smbldap-tools/FILES
examples/LDAP/smbldap-tools/INFRA [new file with mode: 0644]
examples/LDAP/smbldap-tools/INSTALL
examples/LDAP/smbldap-tools/README
examples/LDAP/smbldap-tools/TODO
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-tools.spec
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

index 59dafcc89ef9d3930bc7ae91be5d83f8a2606c58..d080dd020e8ea3f370952fd73f8ad66b4c4e7398 100644 (file)
@@ -1,13 +1,19 @@
+# $Source: /data/src/mirror/cvs/samba/examples/LDAP/smbldap-tools/CONTRIBUTORS,v $
+#
 ## Authors and actives contributors to SMBLDAP-TOOLS
 
 Have contributed directly to this tools, or are always in charge of 
-some aspects of it developments (alphabetical order):
+some aspects of it developments:
+ . Jérôme Tournier <jerome.tournier@IDEALX.com>
  . Terry Davis <terry@terryd.net>
  . David Le Corfec <dlc@freesurf.fr>
  . Olivier Lemaire <olivier.lemaire@IDEALX.com>
- . Jérôme Tournier <jerome.tournier@IDEALX.com>
 
 Many thanks to contributors for bug report and patches:
+ . Marc Schoechlin <ms@LF.net>
+       load the perl-modules without setting environment-variables or making symlinks
+ . Alexander Bergolth <leo@strike.wu-wien.ac.at>
+       more Net::LDAP support
  . Gert-Jan Braas <braas@wyldebeast-wunderliebe.com>
        bug report for 2.2.3 samba.schema
  . Jody Haynes <Jody.Haynes@isunnetworks.com>
index 0994cb493162780f273f27c910ecad47bd07b43e..e6394d1addf0aa4472526078841d16c88c566dca 100644 (file)
@@ -1,28 +1,89 @@
+# $Source: /data/src/mirror/cvs/samba/examples/LDAP/smbldap-tools/ChangeLog,v $
+# $id: $
+#
 ## ChangeLog for SMBLDAP-TOOLS
 
-* 2002-07-24: top and account objectclasses replaced with inetorgperson
-* 2002-06-03: notes to webmin.idealx.org (idxldapaccounts)
-* 2002-06-01: release 0.7. tested with 2.2.4
-* 2002-05-31: fixed smbldap-populate compliance to smbldap_conf 
-              cleaned up smbldap_conf to be more readable 
-              some more documentation
-              bugfixes on smbldap-passwd and smbldap-populate
-* 2002-05-16: modified default mode on homes: now 700
-* 2002-05-13: fixed spec (relocation and reqs)
-* 2002-03-02: fixed 2.2.3 sambaAccount bug with smbldap-useradd.pl
+2003-11-18:
+       . new option '-a' to smbldap-usermod.pl that allow adding the sambaSAMAccount
+         objectclass to an existing posixAccount
+2003-11-07:
+       . patch that allow adding user to a group when the group is in a higher level depth
+          then ou=Groups (for example, ou=grp1,ou=Groups,...)
+        . check the unicity of a group when adding/removing a user to this group
+2003-10-28:
+       . new option '-p' in smbldap-groupadd.pl to 'print' the gidNumber
+         of the group to STDOUT. This is needed by samba (see the man page)
+2003-10-19:
+       . new function does_sid_exist that check if samaSID sttribute is already
+          defined for another use or another group
+2003-10-13:
+       . smbldap-populate.pl now also add the group mapping
+2003-10-01:
+        . one can now comment the two directives '$_userSmbHome' and '$_userProfile'
+          if you want to use the smb.conf directives instead ('logon home' and
+         'logon path' respectively), or if you want to desable roaming profiles
+       . Patch from Alexander Bergolth <leo@strike.wu-wien.ac.at>: the sambaPrimaryGroupSID
+         of a user is now set to the sambaSID of his primary group
+2003-09-29:
+       . added new option '$_defaultMaxPasswordAge' in smbldap_conf.pm to specifie
+         how long a password is valid
+       . The '-B' option was not always valid: to force a user to change his password:
+         . the attribut sambaPwdLastSet must be != 0
+         . the attribut sambaAcctFlags must not match the 'X' flag
+       . logon script is set (for every one) to the default '_userScript' value if it is defined 
+       . Patch from Alexander Bergolth <leo@strike.wu-wien.ac.at>:
+         gid-sid group mapping to smbldap-groupadd.pl and smbldap-groupmod.pl
+2003-09-19: Patch from Marc Schoechlin <ms@LF.net>
+       . load the perl-modules without setting environment-variables or making symlinks
+2003-09-18: Patch from Alexander Bergolth <leo@strike.wu-wien.ac.at>
+       . options "-u", "-g", "-s" and "-c" are now functionnal
+       . the existence of samba account was made on sambaAccount and
+         not sambaSAMAccount as it should be for samba3
+       . new function read_user_entry to smbldap_tools.pm that returns
+         a Net::LDAP:Entry object of the user
+       . Use this object to get the dn and user attributes instead of
+         producing an ldif and searching for attributes within that ldif
+2003-09-15:
+       . change machine account creation to not add the sambaSAMAccount objectclass.
+         It is now added directly by samba when joigning the domain
+       . new option in smbldap-usermod.pl: '-e' to set an expire date
+       . Start_tls support activated when ldapSSL is set to 1
+       . Net::LDAP support more scripts
+       . bugs correction
+2003-09-02:
+       . sambaPwdLastSet is updated when smbldap-passwd.pl is used
+       . add a function is_group_member to test the existence of a
+         user in a particular group
+       . add a function is_unix_user to test if a particular user exist
+       . Net::LDAP support more scripts
+2003-08-15:
+       . Samba3.0 support
+2003-08-01:
+       . Final version for samba 2.2.8a (cvs tag SAMBA-2-2-8a-FINAL)
+       . OpenLDAP 2.1 support (only one structural objectclass allowed)
+2002-07-24: top and account objectclasses replaced with inetorgperson
+2002-06-03: notes to webmin.idealx.org (idxldapaccounts)
+2002-06-01: release 0.7. tested with 2.2.4
+2002-05-31: fixed smbldap-populate compliance to smbldap_conf 
+            cleaned up smbldap_conf to be more readable 
+            some more documentation
+            bugfixes on smbldap-passwd and smbldap-populate
+2002-05-16: modified default mode on homes: now 700
+2002-05-13: fixed spec (relocation and reqs)
+2002-03-02: fixed 2.2.3 sambaAccount bug with smbldap-useradd.pl
               (rid is now mandatory in the sambaAccount objectClass)
-2002-02-14: just modified default populate for Administrator
-2002-02-05: release 0.6. enable/disable user in usermod
-2002-02-04: release 0.5. added smbldap-migrate-groups to migrate NT groups
-              from a net group dump. added samba parameters to smbldap-useradd
-              and smbldap-usermod.
-2002-01-12: added smbldap-migrate-accounts to migrate users/machines
-              accounts from a PWDUMP dump
-2001-12-13: added smbldap-populate to create the initial base
-2001-12-13: initial release 0.1
-2001-12-12: fixed the SPEC file for RedHat
-2001-12-03: cleaned the code and use strict;
-2001-11-20: initial needs (for testing purpose on Samba-2.2.2 an Samba-TNG)
+2002-02-14: just modified default populate for Administrator
+2002-02-05: release 0.6. enable/disable user in usermod
+2002-02-04: release 0.5. added smbldap-migrate-groups to migrate NT groups
+            from a net group dump. added samba parameters to smbldap-useradd
+            and smbldap-usermod.
+2002-01-12: added smbldap-migrate-accounts to migrate users/machines
+            accounts from a PWDUMP dump
+2001-12-13: added smbldap-populate to create the initial base
+2001-12-13: initial release 0.1
+2001-12-12: fixed the SPEC file for RedHat
+2001-12-03: cleaned the code and use strict;
+2001-11-20: initial needs (for testing purpose on Samba-2.2.2 an Samba-TNG)
 
 
 # - The End
index 0343c53d609aeec265e43c95952ec8acec90b8f8..48ee571b29d3c0b8a44646b17c2d949bdd336136 100644 (file)
@@ -1,3 +1,5 @@
+# $Source: /data/src/mirror/cvs/samba/examples/LDAP/smbldap-tools/FILES,v $
+#
 ## File listing for SMBLDAP-TOOLS
 
 CONTRIBUTORS           : authors and contributors
diff --git a/examples/LDAP/smbldap-tools/INFRA b/examples/LDAP/smbldap-tools/INFRA
new file mode 100644 (file)
index 0000000..fe5ce8d
--- /dev/null
@@ -0,0 +1,93 @@
+# $Source: /data/src/mirror/cvs/samba/examples/LDAP/smbldap-tools/Attic/INFRA,v $
+#
+## Some notes about the architecture
+
+
+Global Architecture for smbdlap-tools
+=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+
+smbldap-tools help you manage users and groups for Unix and Samba,
+using LDAP. They may be used in any context, and are kept relatively
+simplier enought to let you customize them to you needs.
+
+They need the following objectClasses to work:
+ . sambaAccount: from samba.schema for Samba 2.2 branch
+ . posixAccount and posixGroup : from nis.schema
+ . organizationalUnit and dcObject: from core.schema
+
+They will probably use in a near future some additional objectClasses
+to support : 
+ . mail features (sendmail/postfix/qmail/courier).
+ . conform to RFC2307 best practices (and so some maps too like merging
+   Netbios computers (sambaAccounts) with ipHosts
+
+For ease of visualization of the LDAP objects by human standards, we
+used a DIT like this one :
+ . dc=IDEALX,dc=org : the company/organization suffix
+       . ou=Users : to store users accounts
+       . ou=Computers : to store computers accounts
+       . ou=Groups : to store system groups
+Of course, you're free to use a different naming scheme and DIT (see
+smbldap_conf.pm).
+
+
+Built in groups initial population 
+=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+
+smbldap-populate.pl populate the LDAP directory with some built in groups 
+using gidNumber according to Well Know RID of Windows NT4 Srv. In fact, As
+far a Samba 2.2.x is concerned, only the 'Domain Admins' (gidNumber 512) have 
+real inpact on the Samba and Windows population. To activate this group as 
+the Domain Administrators Group, use the following smb.conf directive (see 
+man smb.conf for more):
+
+       domain admin group = " @"Domain Admins" "
+
+However, to make pdb_ldap accept bind without being uid=0, a quick and
+dirty patch must be applied to 2.2.4 (see samba-2.2.4-ldapbindnotuid0.patch).
+This patch is Q&D because the check is there because Samba store admin 
+credentials to establish the LDAP connection. The uid == 0 check was to 
+ensure that a normal user could not get write access to the LDAP backend.
+A more logical situation should be done for 2.2.5 by checking if the user
+is a member of the domain admin group (reported to Jerremy and Gerald 
+2002-05-28).
+
+Other built in groups are really cosmetic ones with Samba 2.2.x. We did not
+removed them because one of these days, we whish to use Samba 3.0 where 
+Windows Group Support should be operational.
+
+Why these specific gidNumbers ?
+It's about unix/windows mapping of numerical ids with Samba. Ids below 1024 
+are NT special ids. In fact, 512 is the RID (Windows uid/gid) for the 
+"Domain Administrators" NT group. The magic number is found in Samba sources 
+and possibly other Samba/Windows documentations.
+
+The goal is to have a set of Unix users who are Domain Administrators and can 
+modify Samba datas (eg. LDAP content), with commandline tools or within 
+Windows via Samba.
+
+Say you want to add a NT4 ws to an NT domain (controlled by a samba/ldap  
+server). You give the domain administrator's login and password in the 
+appropriate ws settings, then the ws contacts the samba server, which checks 
+the credentials and use them as unix user to run the smbldap-tools (if I 
+remember). Giving 512 as a RID to a LDAP entry marks it as a domain admin   
+for Samba (thus Windows). Using nss_ldap, you also have an account with
+gid 512.
+
+
+Known BUGS and WORKAROUND used
+=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+
+The 2.2.2 has at least a bug : rid/primaryGroupID are read as hex in LDAP,
+but written as decimal. Fixed in CVS by reading as decimal. By default
+smbldap-useradd.pl writes decimal to LDAP. Use -x to support the odd
+behaviour.
+
+The samba-2.2.4-ldapbindnotuid0.patch is not a perfect solution however
+as the check is there because Samba store admin credentials to establish the 
+LDAP connection. The uid == 0 check was to ensure that a normal user could 
+not get write access to the LDAP backend. A more logical situation should be 
+done for 2.2.5 by checking if the user is a member of the domain admin group 
+(reported to Jerremy and Gerald 2002-05-28).
+
+# - The End
index d5ca07826f4fc3d5bf2c816a0eb2ec131555be6f..f4c72751a75784c0a558d68ce0f8399914261085 100644 (file)
@@ -1,3 +1,5 @@
+# $Source: /data/src/mirror/cvs/samba/examples/LDAP/smbldap-tools/INSTALL,v $
+#
 ## How To Install SMBLDAP-TOOLS
 
 Quick & Dirty:
index 3b4bf2da0dd805aa089aa356ac29cc190e26c7c0..add0175c0cee0b8b2e8db652603f390d236bbcab 100644 (file)
@@ -1,3 +1,6 @@
+# $Source: /data/src/mirror/cvs/samba/examples/LDAP/smbldap-tools/README,v $
+#
+
 Latest version may be found at http://samba.idealx.org/
 
 
index 25cc30c68456c36fe85d0cfa45f0a05642d00723..71e66952997f93f45f2b5e1b2dd63470949b08b5 100644 (file)
@@ -1,3 +1,5 @@
+# $Source: /data/src/mirror/cvs/samba/examples/LDAP/smbldap-tools/TODO,v $
+#
 ## TODO list - First In, Last in the list...
 ## (BF: Bug Report / FR: Feature Request)
 
index 91cd2dad532b428ba4490801808a9293491df65c..a6598004829f4a2ef5f15d20d9a8811396ebd33c 100755 (executable)
@@ -1,5 +1,7 @@
 #!/usr/bin/perl -w
 
+# $Id: smbldap-groupadd.pl,v 1.1.6.3 2003/12/04 21:59:19 jerry Exp $
+#
 #  This code was developped by IDEALX (http://IDEALX.org/) and
 #  contributors (their names can be found in the CONTRIBUTORS file).
 #
@@ -27,33 +29,104 @@ use FindBin;
 use FindBin qw($RealBin);
 use lib "$RealBin/";
 use smbldap_tools;
-
+use smbldap_conf;
 use Getopt::Std;
 my %Options;
 
-my $ok = getopts('og:?', \%Options);
+my $ok = getopts('ag:or:s:t:p?', \%Options);
 if ( (!$ok) || (@ARGV < 1) || ($Options{'?'}) ) {
-       print "Usage: $0 [-go?] groupname\n";
-       print "  -g     gid\n";
-       print "  -o     gid is not unique\n";
-       print "  -?     show this help message\n";
-       exit (1);
+  print "Usage: $0 [-agorst?] groupname\n";
+  print "  -a   add automatic group mapping entry\n";
+  print "  -g   gid\n";
+  print "  -o   gid is not unique\n";
+  print "  -r   group-rid\n";
+  print "  -s   group-sid\n";
+  print "  -t   group-type\n";
+  print "  -p   print the gidNumber to stdout\n";
+  print "  -?   show this help message\n";
+  exit (1);
 }
 
 my $_groupName = $ARGV[0];
 
 if (defined(get_group_dn($_groupName))) {
-    print "$0: group $_groupName exists\n";
-    exit (6);
+  warn "$0: group $_groupName exists\n";
+  exit (6);
 }
 
 my $_groupGidNumber = $Options{'g'};
+if (! defined ($_groupGidNumber = group_add($_groupName, $_groupGidNumber, $Options{'o'}))) {
+  warn "$0: error adding group $_groupName\n";
+  exit (6);
+}
+
+my $group_sid;
+my $tmp;
+if ($tmp= $Options{'s'}) {
+  if ($tmp =~ /^S-(?:\d+-)+\d+$/) {
+    $group_sid = $tmp;
+  } else {
+    warn "$0: illegal group-rid $tmp\n";
+    exit(7);
+  }
+} elsif ($Options{'r'} || $Options{'a'}) {
+  my $group_rid;
+  if ($tmp= $Options{'r'}) {
+    if ($tmp =~ /^\d+$/) {
+      $group_rid = $tmp;
+    } else {
+      warn "$0: illegal group-rid $tmp\n";
+      exit(7);
+    }
+  } else {
+    # algorithmic mapping
+    $group_rid = 2*$_groupGidNumber+1001;
+  }
+  $group_sid = $SID.'-'.$group_rid;
+}
+
+if ($Options{'r'} || $Options{'a'} || $Options{'s'}) {
+  # let's test if this SID already exist
+  my $test_exist_sid=does_sid_exist($group_sid,$groupsdn);
+  if ($test_exist_sid->count == 1) {
+       warn "Group SID already owned by\n";
+       # there should not exist more than one entry, but ...
+       foreach my $entry ($test_exist_sid->all_entries) {
+         my $dn= $entry->dn;
+         chomp($dn);
+         warn "$dn\n";
+       }
+       exit(7);
+  }
+}
 
-if (!group_add($_groupName, $_groupGidNumber, $Options{'o'})) {
-    print "$0: error adding group $_groupName\n";
-    exit (6);
+if ($group_sid) {
+  my $group_type;
+  my $tmp;
+  if ($tmp= $Options{'t'}) {
+    unless (defined($group_type = &group_type_by_name($tmp))) {
+      warn "$0: unknown group type $tmp\n";
+      exit(8);
+    }
+  } else {
+    $group_type = group_type_by_name('domain');
+  }
+  my $ldap_master=connect_ldap_master();
+  my $modify = $ldap_master->modify ( "cn=$_groupName,$groupsdn",
+                                                                         add => {
+                                                                                         'objectClass' => 'sambaGroupMapping',
+                                                                                         'sambaSID' => $group_sid,
+                                                                                         'sambaGroupType' => $group_type
+                                                                                        }
+                                                                       );
+  $modify->code && warn "failed to delete entry: ", $modify->error ;
+  # take down session
+  $ldap_master->unbind
 }
 
+if ($Options{'p'}) {
+  print STDOUT "$_groupGidNumber";
+}
 exit(0);
 
 ########################################
index 89d0d993acfb78d3612ef1fe84f2100648b70e8f..0f5b0998dad07001773f6607355958c423c69505 100755 (executable)
@@ -1,5 +1,7 @@
 #!/usr/bin/perl -w
 
+# $Id: smbldap-groupdel.pl,v 1.1.6.3 2003/12/04 21:59:19 jerry Exp $
+#
 #  This code was developped by IDEALX (http://IDEALX.org/) and
 #  contributors (their names can be found in the CONTRIBUTORS file).
 #
@@ -30,23 +32,22 @@ use smbldap_tools;
 use smbldap_conf;
 
 #####################
-
 use Getopt::Std;
 my %Options;
 
 my $ok = getopts('?', \%Options);
 if ( (!$ok) || (@ARGV < 1) || ($Options{'?'}) ) {
-       print "Usage: $0 groupname\n";
-       print "  -?     show this help message\n";
-       exit (1);
+  print "Usage: $0 groupname\n";
+  print "  -?  show this help message\n";
+  exit (1);
 }
 
 my $_groupName = $ARGV[0];
 
 my $dn_line;
 if (!defined($dn_line = get_group_dn($_groupName))) {
-    print "$0: group $_groupName doesn't exist\n";
-    exit (6);
+  print "$0: group $_groupName doesn't exist\n";
+  exit (6);
 }
 
 my $dn = get_dn_from_line($dn_line);
@@ -56,7 +57,7 @@ group_del($dn);
 my $nscd_status = system "/etc/init.d/nscd status >/dev/null 2>&1";
 
 if ($nscd_status == 0) {
-   system "/etc/init.d/nscd restart > /dev/null 2>&1";
+  system "/etc/init.d/nscd restart > /dev/null 2>&1";
 }
 
 #if (defined($dn_line = get_group_dn($_groupName))) {
index f8971016027f84fc70b052b95295d8031599fca8..eeb67d571234c405bb7f8c87dfe1deadf71a2096 100755 (executable)
@@ -1,4 +1,7 @@
 #!/usr/bin/perl -w
+
+# $Id: smbldap-groupmod.pl,v 1.1.6.6 2003/12/04 21:59:19 jerry Exp $
+#
 #  This code was developped by IDEALX (http://IDEALX.org/) and
 #  contributors (their names can be found in the CONTRIBUTORS file).
 #
@@ -29,29 +32,33 @@ use lib "$RealBin/";
 use smbldap_tools;
 use smbldap_conf;
 
-
 #####################
 
 use Getopt::Std;
 my %Options;
 
-my $ok = getopts('og:n:m:x:?', \%Options);
+my $ok = getopts('ag:n:m:or:s:t:x:?', \%Options);
 if ( (!$ok) || (@ARGV < 1) || ($Options{'?'}) ) {
-       print "Usage: $0 [-g gid [-o]] [-n name] [-m members(,)] [-x members (,)] groupname\n";
-       print "  -g     new gid\n";
-       print "  -o     gid is not unique\n";
-       print "  -n     new group name\n";
-       print "  -m     add members (comma delimited)\n";
-       print "  -x     delete members (comma delimted)\n";
-       print "  -?     show this help message\n";
-       exit (1);
+  print "Usage: $0 [-a] [-g gid [-o]] [-n name] [-m members(,)] [-x members (,)] [-r rid] [-s sid] [-t type] groupname\n";
+  print "  -a   add automatic group mapping entry\n";
+  print "  -g   new gid\n";
+  print "  -o   gid is not unique\n";
+  print "  -n   new group name\n";
+  print "  -m   add members (comma delimited)\n";
+  print "  -r   group-rid\n";
+  print "  -s   group-sid\n";
+  print "  -t   group-type\n"; 
+  print "  -x   delete members (comma delimted)\n";
+  print "  -?   show this help message\n";
+  exit (1);
 }
 
 my $groupName = $ARGV[0];
+my $group_entry;
 
-if (!defined(get_group_dn($groupName))) {
-    print "$0: group $groupName doesn't exist\n";
-    exit (6);
+if (! ($group_entry = read_group_entry($groupName))) {
+  print "$0: group $groupName doesn't exist\n";
+  exit (6);
 }
 
 my $newname = $Options{'n'};
@@ -59,20 +66,24 @@ my $newname = $Options{'n'};
 my $nscd_status = system "/etc/init.d/nscd status >/dev/null 2>&1";
 
 if ($nscd_status == 0) {
-   system "/etc/init.d/nscd restart > /dev/null 2>&1";
+  system "/etc/init.d/nscd restart > /dev/null 2>&1";
 }
 
 my $gid = getgrnam($groupName);
+unless (defined ($gid)) {
+  print "$0: group $groupName not found!\n";
+  exit(6);
+}
 
 my $tmp;
 if (defined($tmp = $Options{'g'}) and $tmp =~ /\d+/) {
-    if (!defined($Options{'o'})) {
+  if (!defined($Options{'o'})) {
        if (defined(getgrgid($tmp))) {
-           print "$0: gid $tmp exists\n";
-           exit (6);
+         print "$0: gid $tmp exists\n";
+         exit (6);
        }
-    }
-    if (!($gid == $tmp)) {
+  }
+  if (!($gid == $tmp)) {
        my $ldap_master=connect_ldap_master();
        my $modify = $ldap_master->modify ( "cn=$groupName,$groupsdn",
                                                                                changes => [
@@ -82,7 +93,7 @@ if (defined($tmp = $Options{'g'}) and $tmp =~ /\d+/) {
        $modify->code && die "failed to modify entry: ", $modify->error ;
        # take down session
        $ldap_master->unbind
-    }
+  }
 }
 
 
@@ -101,17 +112,19 @@ if (defined($newname)) {
 
 # Add members
 if (defined($Options{'m'})) {
-       my $members = $Options{'m'};
-       my @members = split( /,/, $members );
-       my $member;
-       foreach $member ( @members ) {
+  my $members = $Options{'m'};
+  my @members = split( /,/, $members );
+  my $member;
+  foreach $member ( @members ) {
+       my $group_entry=read_group_entry($groupName);
+       $groupsdn=$group_entry->dn;
        if (is_unix_user($member)) {
-         if (is_group_member("cn=$groupName,$groupsdn",$member)) {
+         if (is_group_member($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",
+               my $modify = $ldap_master->modify ($groupsdn,
                                                                                        changes => [
                                                                                                                add => [memberUid => $member]
                                                                                                           ]
@@ -123,19 +136,21 @@ if (defined($Options{'m'})) {
        } else {
          print "User $member does not exist: create it first !\n";
        }
-       }
+  }
 }
 
 # Delete members
 if (defined($Options{'x'})) {
-        my $members = $Options{'x'};
-        my @members = split( /,/, $members );
-        my $member;
-        foreach $member ( @members ) {
-       if (is_group_member("cn=$groupName,$groupsdn",$member)) {
+  my $members = $Options{'x'};
+  my @members = split( /,/, $members );
+  my $member;
+  foreach $member ( @members ) {
+        my $group_entry=read_group_entry($groupName);
+        $groupsdn=$group_entry->dn;
+       if (is_group_member("$groupsdn",$member)) {
          print "deleting user $member from group $groupName\n";
          my $ldap_master=connect_ldap_master();
-         my $modify = $ldap_master->modify ( "cn=$groupName,$groupsdn",
+         my $modify = $ldap_master->modify ($groupsdn,
                                                                                  changes => [
                                                                                                          delete => [memberUid => $member]
                                                                                                         ]
@@ -146,13 +161,73 @@ if (defined($Options{'x'})) {
        } else {
          print "User $member is not in the group $groupName!\n";
        }
-        }
+  }
+}
+
+my $group_sid;
+if ($tmp= $Options{'s'}) {
+  if ($tmp =~ /^S-(?:\d+-)+\d+$/) {
+    $group_sid = $tmp;
+  } else {
+    print "$0: illegal group-rid $tmp\n";
+    exit(7);
+  }
+} elsif ($Options{'r'} || $Options{'a'}) {
+  my $group_rid;
+  if ($tmp= $Options{'r'}) {
+    if ($tmp =~ /^\d+$/) {
+      $group_rid = $tmp;
+    } else {
+      print "$0: illegal group-rid $tmp\n";
+      exit(7);
+    }
+  } else {
+    # algorithmic mapping
+    $group_rid = 2*$gid+1001;
+  }
+  $group_sid = $SID.'-'.$group_rid;
+}
+
+if ($group_sid) {
+  my @adds;
+  my @mods;
+  push(@mods, 'sambaSID' => $group_sid);
+
+  if ($tmp= $Options{'t'}) {
+    my $group_type;
+    if (defined($group_type = &group_type_by_name($tmp))) {
+      push(@mods, 'sambaGroupType' => $group_type);
+    } else {
+      print "$0: unknown group type $tmp\n";
+      exit(8);
+    }
+  } else {
+    if (! defined($group_entry->get_value('sambaGroupType'))) {
+      push(@mods, 'sambaGroupType' => group_type_by_name('domain'));
+    }
+  }
+
+  my @oc = $group_entry->get_value('objectClass');
+  unless (grep($_ =~ /^sambaGroupMapping$/i, @oc)) {
+    push (@adds, 'objectClass' => 'sambaGroupMapping');
+  }
+
+  my $ldap_master=connect_ldap_master();
+  my $modify = $ldap_master->modify ( "cn=$groupName,$groupsdn",
+                                                                         changes => [
+                                                                                                 'add' => [ @adds ],
+                                                                                                 'replace' => [ @mods ]
+                                                                                                ]
+                                                                       );
+  $modify->code && warn "failed to delete 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) {
-   system "/etc/init.d/nscd restart > /dev/null 2>&1";
+  system "/etc/init.d/nscd restart > /dev/null 2>&1";
 }
 
 exit (0);
@@ -161,19 +236,19 @@ exit (0);
 
 =head1 NAME
 
-       smbldap-groupmod.pl - Modify a group
+smbldap-groupmod.pl - Modify a group
 
 =head1 SYNOPSIS
 
-       smbldap-groupmod.pl [-g gid [-o]] [-n group_name ] group
+smbldap-groupmod.pl [-g gid [-o]] [-n group_name ] group
 
 =head1 DESCRIPTION
 
-       The smbldap-groupmod.pl command modifies the system account files to
-       reflect the changes that are specified on the command line.
-       The options which apply to the smbldap-groupmod command are
+The smbldap-groupmod.pl command modifies the system account files to
+  reflect the changes that are specified on the command line.
+  The options which apply to the smbldap-groupmod command are
 
-       -g gid The numerical value of the group's ID. This value must be
+  -g gid The numerical value of the group's ID. This value must be
               unique, unless the -o option is used. The value must be non-
               negative. Any files which the old group ID is the file
               group ID must have the file group ID changed manually.
index 18fe082e665835b0d2cfc62aa2316248ab1a16fc..9c30f0fc12b845280affd85443427684f3233317 100755 (executable)
@@ -1,5 +1,7 @@
 #!/usr/bin/perl -w
 
+# $Id: smbldap-groupshow.pl,v 1.1.6.3 2003/12/04 21:59:19 jerry Exp $
+#
 #  This code was developped by IDEALX (http://IDEALX.org/) and
 #  contributors (their names can be found in the CONTRIBUTORS file).
 #
@@ -36,8 +38,8 @@ my %Options;
 my $ok = getopts('?', \%Options);
 
 if ( (!$ok) || (@ARGV < 1) || ($Options{'?'}) ) {
-       print "Usage: $0 [-?] group\n";
-       print "  -?     show this help message\n";
+  print "Usage: $0 [-?] group\n";
+  print "  -?  show this help message\n";
        exit (1);
 }
 
index 86f52cb53e1b753ac94aac051ff4be8e6637dc84..05f9b276002a39756ba874136f560ff3398aa4a8 100755 (executable)
@@ -1,5 +1,7 @@
 #!/usr/bin/perl -w
 
+# $Id: smbldap-migrate-accounts.pl,v 1.1.6.4 2003/12/04 21:59:19 jerry Exp $
+#
 #  This code was developped by IDEALX (http://IDEALX.org/) and
 #  contributors (their names can be found in the CONTRIBUTORS file).
 #
@@ -39,8 +41,8 @@ use smbldap_conf;
 # Errors, debug and stats are output to stderr.
 
 sub modify_account
-{
-  my ($login, $basedn, $lmpwd, $ntpwd, $gecos, $homedir) = @_;
+  {
+       my ($login, $basedn, $lmpwd, $ntpwd, $gecos, $homedir) = @_;
        # bind to a directory with dn and password
        my $ldap_master=connect_ldap_master();
        my $modify = $ldap_master->modify ("uid=$login,$basedn",
@@ -54,7 +56,7 @@ sub modify_account
        $modify->code && die "failed to modify entry: ", $modify->error ;
        # take down the session
        $ldap_master->unbind;
-}
+  }
 
 #####################
 
@@ -64,15 +66,15 @@ my %Options;
 my $ok = getopts('awA:CUW:?h', \%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";
-        print "  -A <opts>  option string passed verbatim to smbldap-useradd for persons\n";
-        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 "Usage: $0 [-awAWCU?]\n";
+  print "  -a         process only people, ignore computers\n";
+  print "  -w         process only computers, ignore persons\n";
+  print "  -A <opts>  option string passed verbatim to smbldap-useradd for persons\n";
+  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 "  -?|-h      show this help message\n";
-        exit (1);
+  exit (1);
 }
 
 my %processed = ( 'user' => 0, 'machine' => 0);
@@ -90,7 +92,7 @@ while (<>) {
 
   my $entry_type = 'user';
 
-  if ($login =~ m/.*\$$/ ) { # computer
+  if ($login =~ m/.*\$$/ ) {   # computer
     $processed{'machine'}++;
     $entry_type = 'machine';
     if (defined($Options{'a'})) {
@@ -117,14 +119,14 @@ while (<>) {
   }
 
   # normalize homedir
-# uncomment to replace configured share with share from pwdump
-#  if ($homedir eq "") {
-    $homedir = $_userSmbHome;
-#  }
+  # uncomment to replace configured share with share from pwdump
+  #  if ($homedir eq "") {
+  $homedir = $_userSmbHome;
+  #  }
 
   # normalize gecos
   if (!($gecos eq "")) {
-    $gecos =~ tr/ÁÀÂÄáàâäÇçÉÈÊËÆéèêëæÍÌÏÎíìîÏÑñÓÒÔÖóòôöÚÙÜÛúùüûÝýÿ/AAAAaaaaCcEEEEEeeeeeIIIIiiiiNnOOOOooooUUUUuuuuYyy/;
+    $gecos =~ tr/ÁÀÂÄáàâäÇçÉÈÊËÆéèêëæÍÌÏÎíìîÏÑñÓÒÔÖóòôöÚÙÜÛúùüûÝýÿ/AAAAaaaaCcEEEEEeeeeeIIIIiiiiNnOOOOooooUUUUuuuuYyy/;
   } else {
     $gecos = $_userGecos;
   }
@@ -141,12 +143,12 @@ while (<>) {
         print STDERR "error adding $login, skipping\n";
         next;
       }
-       # lem modif... a retirer si pb
+         # lem modif... a retirer si pb
          if ($entry_type eq "user") {
        modify_account($login, $userbasedn, $lmpwd, $ntpwd, $gecos, $homedir);
-       }
+         }
 
-       $created{$entry_type}++;
+         $created{$entry_type}++;
     } else {                                   # uid doesn't exist and no create => log
       print "$_";
       $logged{$entry_type}++;
@@ -187,7 +189,7 @@ print STDERR "special users skipped: $specialskipped\n";
 
 =head1 NAME
 
-       smbldap-migrate.pl - Migrate NT accounts to LDAP
+smbldap-migrate.pl - Migrate NT accounts to LDAP
 
 =head1 SYNOPSIS
 
index c60be18caf8f80c03cd3803c8c4df7a48e6ba87a..37a0286b06a67160bed9f5126db5eed03fb786bb 100644 (file)
@@ -1,5 +1,7 @@
 #!/usr/bin/perl
 
+# $Id: smbldap-migrate-groups.pl,v 1.1.6.3 2003/12/04 21:59:19 jerry Exp $
+#
 #  This code was developped by IDEALX (http://IDEALX.org/) and
 #  contributors (their names can be found in the CONTRIBUTORS file).
 #
@@ -33,52 +35,50 @@ use smbldap_tools;
 use smbldap_conf;
 use Getopt::Std;
 
-
-
 sub process_rec_group
-{
+  {
     my ($group, $mb) = @_;
     my @members;
     
     if (!(@members = group_get_members($group))) {
-       return 0;
+         return 0;
     }
 
     foreach my $m (@members) {
-       if ( !($m =~ m/^\*/) ) {
+         if ( !($m =~ m/^\*/) ) {
            push @{$mb}, $m;
-       } else {
+         } else {
            my $gname = $m;
            $gname =~ s/^.//;
            if (!process_rec_group($gname, $mb)) {
-               print "recursive group not added : $gname\n";
+                 print "recursive group not added : $gname\n";
            }
-       }
+         }
     }
-}
+  }
 
 
 # given a group dn and a list of members, update the group
 sub modify_group
-{
+  {
     my ($group, $dn_line, @members, $recgroup) = @_;
     my $m;
     my @new_mb;
 
     foreach $m (@members) {
-       if ( ($m =~ m/^\*/) ) {
+         if ( ($m =~ m/^\*/) ) {
            my $gname = $m;
            $gname =~ s/^.//;
            if (!$recgroup) {
-               print "recursive group not added : $gname\n";
+                 print "recursive group not added : $gname\n";
            } else {
-               if (!process_rec_group($gname, \@new_mb)) {
+                 if (!process_rec_group($gname, \@new_mb)) {
                    print "recursive group not added : $gname\n";
-               }
+                 }
            }
-       } else {
+         } else {
            push @new_mb, $m;
-       }
+         }
     }
 
     # new_mb contains flat members from group dump
@@ -94,7 +94,7 @@ sub modify_group
     
     my $mbs;
     foreach $m (@new_mb) {
-           $mbs .= "memberUid: $m\n";
+         $mbs .= "memberUid: $m\n";
     }
 
     my $mods="$dn_line
@@ -105,16 +105,16 @@ $mbs
 
     #print "$mods\n";
     my $tmpldif =
-"$mods
+         "$mods
 ";
 
     die "$0: error while modifying group $group\n"
-       unless (do_ldapmodify($tmpldif) == 0);
+         unless (do_ldapmodify($tmpldif) == 0);
     undef $tmpldif;
-}
+  }
 
 sub display_group
-{
+  {
     my ($group, @members) = @_;
 
     print "Group name $group\n";
@@ -122,43 +122,43 @@ sub display_group
     my $m;
     my $i = 0;
     foreach $m (@members) {
-       print "$m ";
-       if ($i % 5 == 0) {
+         print "$m ";
+         if ($i % 5 == 0) {
            print "\n";
-       }
-       $i++;
+         }
+         $i++;
     }
-}
+  }
 
 sub process_group
-{
+  {
     my ($group, @members, $nocreate, $noupdate, $recgroup) = @_;
 
     my $dn_line;
     if (!defined($dn_line = get_group_dn($group))) {
-       # group not found, create it ?
-       if (!$nocreate) {
+         # group not found, create it ?
+         if (!$nocreate) {
            system "/usr/local/sbin/smbldap-groupadd.pl \"$group\"; sleep 5";
            if (!defined($dn_line = get_group_dn($group))) {
-               return 1;
+                 return 1;
            }
            modify_group($group, $dn_line, @members, $recgroup);
-       } else {
+         } else {
            # don't create
            print "not created:\n";
            display_group($group, @members);
-       }
+         }
     } else {
-       # group found, update it ?
-       if (!$noupdate) {
+         # group found, update it ?
+         if (!$noupdate) {
            modify_group($group, $dn_line, @members, $recgroup);
-       } else {
+         } else {
            # don't update
            print "not updated:\n";
            display_group($group, @members);    
-       }
+         }
     }
-}
+  }
 
 ###################################################
 
@@ -166,11 +166,11 @@ my %Options;
 
 my $ok = getopts('CUr?', \%Options);
 if ( (!$ok) || ($Options{'?'}) ) {
-    print "Usage: $0 [-CUr?] < group_dump\n";
-    print "  -C            don't create group if it doesn't exist\n";
-    print "  -U            don't update group if it exists\n";
-    print "  -r            recursively process groups\n";
-    exit(1);
+  print "Usage: $0 [-CUr?] < group_dump\n";
+  print "  -C      don't create group if it doesn't exist\n";
+  print "  -U      don't update group if it exists\n";
+  print "  -r      recursively process groups\n";
+  exit(1);
 }
 
 my $group_name;
@@ -184,13 +184,13 @@ while (<>) {
   next if ( $line =~ m/^\s*$/ );
 
   if ($group_name eq "") {
-      if ( $line =~ m/^Group name\s+(.+).$/ ) {
+       if ( $line =~ m/^Group name\s+(.+).$/ ) {
          $group_name = $1;
          next;
-      }
+       }
   }
   if ($group_desc eq "") {
-      if ( $line =~ m/^Comment\s+(.*)$/ ) {
+       if ( $line =~ m/^Comment\s+(.*)$/ ) {
          $group_desc = $1;
          next;
       }
index 7845e5548e23e0e5bcb4c3f7a52381284904d838..97680dcd46108bb569cacab1a2731969225586a9 100755 (executable)
@@ -1,7 +1,8 @@
 #!/usr/bin/perl -w
 
 # LDAP to unix password sync script for samba
-#
+# $Id: smbldap-passwd.pl,v 1.1.6.4 2003/12/04 21:59:19 jerry Exp $
+
 #  This code was developped by IDEALX (http://IDEALX.org/) and
 #  contributors (their names can be found in the CONTRIBUTORS file).
 #
@@ -23,7 +24,7 @@
 #  USA.
 
 #  Purpose :
-#       . ldap-unix passwd sync for SAMBA-2.2.2 + LDAP
+#       . ldap-unix passwd sync for SAMBA>2.2.2 + LDAP
 #       . may also replace /bin/passwd
 
 use strict;
@@ -40,29 +41,29 @@ my $ret;
 my $arg;
 
 foreach $arg (@ARGV) {
-       if ($< != 0) {
-               die "Only root can specify parameters\n";
-       } else {
-               if ( ($arg eq '-?') || ($arg eq '--help') ) {
-                       print "Usage: $0 [username]\n";
-                       print "  -?, --help                     show this help message\n";
-                       exit (6);
-               } elsif (substr($arg,0) ne '-')  {
-                       $user = $arg;
-               }
-               $oldpass = 1;
+  if ($< != 0) {
+       die "Only root can specify parameters\n";
+  } else {
+       if ( ($arg eq '-?') || ($arg eq '--help') ) {
+         print "Usage: $0 [username]\n";
+         print "  -?, --help                   show this help message\n";
+         exit (6);
+       } elsif (substr($arg,0) ne '-') {
+         $user = $arg;
        }
+       $oldpass = 1;
+  }
 }
 
 if (!defined($user)) {
-       $user=$ENV{"USER"};
+  $user=$ENV{"USER"};
 }
 
 # 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);
+  print "$0: user $user doesn't exist\n";
+  exit (10);
 }
 
 my $dn = get_dn_from_line($dn_line);
@@ -73,17 +74,17 @@ print "Changing password for $user\n";
 
 # non-root user
 if (!defined($oldpass)) {
-    # prompt for current password
-       system "stty -echo";
-       print "(current) UNIX password: ";
-       chomp($oldpass=<STDIN>);
-       print "\n";
-       system "stty echo";
-
-       if (!is_user_valid($user, $dn, $oldpass)) {
-           print "Authentication failure\n";
-           exit (10);
-       }
+  # prompt for current password
+  system "stty -echo";
+  print "(current) UNIX password: ";
+  chomp($oldpass=<STDIN>);
+  print "\n";
+  system "stty echo";
+
+  if (!is_user_valid($user, $dn, $oldpass)) {
+       print "Authentication failure\n";
+       exit (10);
+  }
 }
 
 # prompt for new password
@@ -104,8 +105,8 @@ print "\n";
 system "stty echo";
 
 if ($pass ne $pass2) {
-    print "New passwords don't match!\n";
-    exit (10);
+  print "New passwords don't match!\n";
+  exit (10);
 }
 
 # First, connecting to the directory
@@ -113,59 +114,64 @@ my $ldap_master=connect_ldap_master();
 
 # only modify smb passwords if smb user
 if ($samba == 1) {
-    if (!$with_smbpasswd) {
-# generate LanManager and NT clear text passwords
+  if (!$with_smbpasswd) {
+       # generate LanManager and NT clear text passwords
        if ($mk_ntpasswd eq '') {
-           print "Either set \$with_smbpasswd = 1 or specify \$mk_ntpasswd\n";
-           exit(1);
+         print "Either set \$with_smbpasswd = 1 or specify \$mk_ntpasswd\n";
+         exit(1);
        }
        my $ntpwd = `$mk_ntpasswd '$pass'`;
-        chomp(my $sambaLMPassword = substr($ntpwd, 0, index($ntpwd, ':')));
-        chomp(my $sambaNTPassword = substr($ntpwd, index($ntpwd, ':')+1));
+       chomp(my $sambaLMPassword = substr($ntpwd, 0, index($ntpwd, ':')));
+       chomp(my $sambaNTPassword = substr($ntpwd, index($ntpwd, ':')+1));
        # the sambaPwdLastSet must be updating
        my $date=time;
+       my @mods;
+       push(@mods, 'sambaLMPassword' => $sambaLMPassword);
+       push(@mods, 'sambaNTPassword' => $sambaNTPassword);
+       push(@mods, 'sambaPwdLastSet' => $date);
+       if (defined $_defaultMaxPasswordAge) {
+         my $new_sambaPwdMustChange=$date+$_defaultMaxPasswordAge*24*60*60;
+         push(@mods, 'sambaPwdMustChange' => $new_sambaPwdMustChange);
+         push(@mods, 'sambaAcctFlags' => '[U]');
+       }
        # Let's change nt/lm passwords
        my $modify = $ldap_master->modify ( "$dn",
-                                                                               changes => [
-                                                                                                       replace => [sambaLMPassword => "$sambaLMPassword"],
-                                                                                                       replace => [sambaNTPassword => "$sambaNTPassword"],
-                                                                                                       replace => [sambaPwdLastSet => "$date"]
-                                                                                                  ]
+                                                                               'replace' => { @mods }
                                                                          );
        $modify->code && warn "failed to modify entry: ", $modify->error ;
 
   } else {
        if ($< != 0) {
-           my $FILE="|$smbpasswd -s >/dev/null";
-           open (FILE, $FILE) || die "$!\n";
-           print FILE <<EOF;
+         my $FILE="|$smbpasswd -s >/dev/null";
+         open (FILE, $FILE) || die "$!\n";
+         print FILE <<EOF;
 '$oldpass'
 '$pass'
 '$pass'
 EOF
-    ;
-           close FILE;
+         ;
+         close FILE;
        } else {
-           my $FILE="|$smbpasswd $user -s >/dev/null";
-           open (FILE, $FILE) || die "$!\n";
-           print FILE <<EOF;
+         my $FILE="|$smbpasswd $user -s >/dev/null";
+         open (FILE, $FILE) || die "$!\n";
+         print FILE <<EOF;
 '$pass'
 '$pass'
 EOF
-    ;
-           close FILE;
+         ;
+         close FILE;
        }
-    }
+  }
 }
 
 # change unix password
 my $hash_password = `slappasswd -h {$hash_encrypt} -s '$pass'`;
 chomp($hash_password);
 my $modify = $ldap_master->modify ( "$dn",
-       changes => [
-                       replace => [userPassword => "$hash_password"]
-                  ]
-         );
+                                                                       changes => [
+                                                                                               replace => [userPassword => "$hash_password"]
+                                                                                          ]
+                                                                 );
 $modify->code && warn "Unable to change password : ", $modify->error ;
 
 # take down session
@@ -186,7 +192,7 @@ smbldap-passwd.pl - change user password
 
 =head1 DESCRIPTION
 
-       smbldap-passwd.pl changes passwords for user accounts. A normal user
+smbldap-passwd.pl changes passwords for user accounts. A normal user
        may only change the password for their own account, the super user may
        change the password for any account.
 
index ce497672a96c55e4fbd0a08be27e9f301516e3df..0992c5b75123fb5240a9e757f185b5646a45a56e 100755 (executable)
@@ -2,6 +2,8 @@
 
 # Populate a LDAP base for Samba-LDAP usage
 #
+# $Id: smbldap-populate.pl,v 1.1.6.4 2003/12/04 21:59:19 jerry Exp $
+
 #  This code was developped by IDEALX (http://IDEALX.org/) and
 #  contributors (their names can be found in the CONTRIBUTORS file).
 #
@@ -39,66 +41,66 @@ use vars qw(%oc);
 
 # objectclass of the suffix
 %oc = (
-    "ou" => "organizationalUnit",
-    "o" => "organization",
-    "dc" => "dcObject",
-);
+          "ou" => "organizationalUnit",
+          "o" => "organization",
+          "dc" => "dcObject",
+         );
 
 
 my %Options;
 
 my $ok = getopts('a:b:?', \%Options);
 if ( (!$ok) || ($Options{'?'}) ) {
-       print "Usage: $0 [-ab?] [ldif]\n";
-       print "  -a     administrator login name (default: Administrator)\n";
-       print "  -b     guest login name (default: nobody)\n";
-       print "  -?     show this help message\n";
-       print "  ldif   file to add to ldap (default: suffix, Groups,";
-       print " Users, Computers and builtin users )\n";
-       exit (1);
+  print "Usage: $0 [-ab?] [ldif]\n";
+  print "  -a  administrator login name (default: Administrator)\n";
+  print "  -b  guest login name (default: nobody)\n";
+  print "  -?  show this help message\n";
+  print "  ldif        file to add to ldap (default: suffix, Groups,";
+  print " Users, Computers and builtin users )\n";
+  exit (1);
 }
 
 my $_ldifName;
 my $tmp_ldif_file="/tmp/$$.ldif";
 
 if (@ARGV >= 1) {
-    $_ldifName = $ARGV[0];
+  $_ldifName = $ARGV[0];
 }
 
 my $adminName = $Options{'a'};
 if (!defined($adminName)) {
-    $adminName = "Administrator";
+  $adminName = "Administrator";
 }
 
 my $guestName = $Options{'b'};
 if (!defined($guestName)) {
-    $guestName = "nobody";
+  $guestName = "nobody";
 }
 
 if (!defined($_ldifName)) {
-    my $attr;
-    my $val;
-    my $objcl;
+  my $attr;
+  my $val;
+  my $objcl;
 
   print "Using builtin directory structure\n";
-    if ($suffix =~ m/([^=]+)=([^,]+)/) {
+  if ($suffix =~ m/([^=]+)=([^,]+)/) {
        $attr = $1;
        $val = $2;
        $objcl = $oc{$attr} if (exists $oc{$attr});
        if (!defined($objcl)) {
-           $objcl = "myhardcodedobjectclass";
+         $objcl = "myhardcodedobjectclass";
        }
-    } else {
+  } else {
        die "can't extract first attr and value from suffix $suffix";
-    }
-    #print "$attr=$val\n";
-    my ($organisation,$ext) = ($suffix =~ m/dc=(\w+),dc=(\w+)$/);
+  }
+  #print "$attr=$val\n";
+  my ($organisation,$ext) = ($suffix =~ m/dc=(.*),dc=(.*)$/);
 
-    #my $FILE="|cat";
+  #my $FILE="|cat";
   my $FILE=$tmp_ldif_file;
   open (FILE, ">$FILE") || die "Can't open file $FILE: $!\n";
 
-    print FILE <<EOF;
+  print FILE <<EOF;
 dn: $suffix
 objectClass: $objcl
 objectclass: organization
@@ -172,87 +174,138 @@ loginShell: /bin/false
 
 dn: cn=Domain Admins,$groupsdn
 objectClass: posixGroup
+objectClass: sambaGroupMapping
 gidNumber: 512
 cn: Domain Admins
 memberUid: $adminName
-description: Netbios Domain Administrators (need smb.conf configuration)
+description: Netbios Domain Administrators
+sambaSID: $SID-512
+sambaGroupType: 2
+displayName: Domain Admins
 
 dn: cn=Domain Users,$groupsdn
 objectClass: posixGroup
+objectClass: sambaGroupMapping
 gidNumber: 513
 cn: Domain Users
-description: Netbios Domain Users (not implemented yet)
+description: Netbios Domain Users
+sambaSID: $SID-513
+sambaGroupType: 2
+displayName: Domain Users
 
 dn: cn=Domain Guests,$groupsdn
 objectClass: posixGroup
+objectClass: sambaGroupMapping
 gidNumber: 514
 cn: Domain Guests
-description: Netbios Domain Guests Users (not implemented yet)
+description: Netbios Domain Guests Users
+sambaSID: $SID-514
+sambaGroupType: 2
+displayName: Domain Guests
 
 dn: cn=Administrators,$groupsdn
 objectClass: posixGroup
+objectClass: sambaGroupMapping
 gidNumber: 544
 cn: Administrators
-description: Netbios Domain Members can fully administer the computer/sambaDomainName (not implemented yet)
+description: Netbios Domain Members can fully administer the computer/sambaDomainName
+sambaSID: $SID-544
+sambaGroupType: 2
+displayName: Administrators
 
 dn: cn=Users,$groupsdn
 objectClass: posixGroup
+objectClass: sambaGroupMapping
 gidNumber: 545
 cn: Users
-description: Netbios Domain Ordinary users (not implemented yet)
+description: Netbios Domain Ordinary users
+sambaSID: $SID-545
+sambaGroupType: 2
+displayName: users
 
 dn: cn=Guests,$groupsdn
 objectClass: posixGroup
+objectClass: sambaGroupMapping
 gidNumber: 546
 cn: Guests
 memberUid: $guestName
-description: Netbios Domain Users granted guest access to the computer/sambaDomainName (not implemented yet)
-
+description: Netbios Domain Users granted guest access to the computer/sambaDomainName
+sambaSID: $SID-546
+sambaGroupType: 2
+displayName: Guests
 
 dn: cn=Power Users,$groupsdn
 objectClass: posixGroup
+objectClass: sambaGroupMapping
 gidNumber: 547
 cn: Power Users
-description: Netbios Domain Members can share directories and printers (not implemented yet)
+description: Netbios Domain Members can share directories and printers
+sambaSID: $SID-547
+sambaGroupType: 2
+displayName: Power Users
 
 dn: cn=Account Operators,$groupsdn
 objectClass: posixGroup
+objectClass: sambaGroupMapping
 gidNumber: 548
 cn: Account Operators
-description: Netbios Domain Users to manipulate users accounts (not implemented yet)
+description: Netbios Domain Users to manipulate users accounts
+sambaSID: $SID-548
+sambaGroupType: 2
+displayName: Account Operators
 
 dn: cn=Server Operators,$groupsdn
 objectClass: posixGroup
+objectClass: sambaGroupMapping
 gidNumber: 549
 cn: Server Operators
-description: Netbios Domain Server Operators (need smb.conf configuration)
+description: Netbios Domain Server Operators
+sambaSID: $SID-549
+sambaGroupType: 2
+displayName: Server Operators
 
 dn: cn=Print Operators,$groupsdn
 objectClass: posixGroup
+objectClass: sambaGroupMapping
 gidNumber: 550
 cn: Print Operators
-description: Netbios Domain Print Operators (need smb.conf configuration)
+description: Netbios Domain Print Operators
+sambaSID: $SID-550
+sambaGroupType: 2
+displayName: Print Operators
 
 dn: cn=Backup Operators,$groupsdn
 objectClass: posixGroup
+objectClass: sambaGroupMapping
 gidNumber: 551
 cn: Backup Operators
-description: Netbios Domain Members can bypass file security to back up files (not implemented yet)
+description: Netbios Domain Members can bypass file security to back up files
+sambaSID: $SID-551
+sambaGroupType: 2
+displayName: Backup Operators
 
 dn: cn=Replicator,$groupsdn
 objectClass: posixGroup
+objectClass: sambaGroupMapping
 gidNumber: 552
 cn: Replicator
-description: Netbios Domain Supports file replication in a sambaDomainName (not implemented yet)
+description: Netbios Domain Supports file replication in a sambaDomainName
+sambaSID: $SID-552
+sambaGroupType: 2
+displayName: Replicator
 
 dn: cn=Domain Computers,$groupsdn
 objectClass: posixGroup
+objectClass: sambaGroupMapping
 gidNumber: 553
 cn: Domain Computers
 description: Netbios Domain Computers accounts
+sambaSID: $SID-553
+sambaGroupType: 2
+displayName: Domain Computers
 
 EOF
-    close FILE;
+  close FILE;
 } else {
   $tmp_ldif_file=$_ldifName;
 }
@@ -280,11 +333,11 @@ exit(0);
 
 =head1 NAME
 
-       smbldap-populate.pl - Populate your LDAP database
+smbldap-populate.pl - Populate your LDAP database
 
 =head1 SYNOPSIS
 
-       smbldap-populate.pl [ldif-file]
+  smbldap-populate.pl [ldif-file]
 
 =head1 DESCRIPTION
 
index 7924ae20e27ae5739ca03bf495ac2ea912b38699..0275c8096fc6356d4e9a8d4b07577c8a5bc09841 100755 (executable)
@@ -1,5 +1,6 @@
-%define version        0.8
-%define release        1
+# $Source: /data/src/mirror/cvs/samba/examples/LDAP/smbldap-tools/smbldap-tools.spec,v $
+%define version        0.8.2
+%define release 1
 %define name   smbldap-tools
 %define realname  smbldap-tools
 
@@ -35,6 +36,7 @@ Source18:     smbldap-populate.pl
 Source19:      smbldap-migrate-accounts.pl
 Source20:      smbldap-migrate-groups.pl
 Source21:      INFRA
+Source22:      smb.conf
 BuildRoot:     /%{_tmppath}/%{name}
 Prefix: /usr/local
 BuildRequires: perl >= 5.6
@@ -86,13 +88,21 @@ install -m 644 %{SOURCE14} $RPM_BUILD_ROOT/usr/share/doc/smbldap-tools/FILES
 install -m 644 %{SOURCE15} $RPM_BUILD_ROOT/usr/share/doc/smbldap-tools/README
 install -m 644 %{SOURCE16} $RPM_BUILD_ROOT/usr/share/doc/smbldap-tools/TODO
 install -m 644 %{SOURCE21} $RPM_BUILD_ROOT/usr/share/doc/smbldap-tools/INFRA
+install -m 644 %{SOURCE22} $RPM_BUILD_ROOT/usr/share/doc/smbldap-tools/smb.conf
 
 %clean
 rm -rf $RPM_BUILD_ROOT
 
 %post
-ln -sf %{prefix}/sbin/smbldap_tools.pm /usr/lib/perl5/site_perl/smbldap_tools.pm
-ln -sf %{prefix}/sbin/smbldap_conf.pm /usr/lib/perl5/site_perl/smbldap_conf.pm
+# from smbldap-tools-0.8-2, librairies are loaded with the FindBin perl package
+if [ -f /usr/lib/perl5/site_perl/smbldap_tools.pm ];
+then
+       rm -f /usr/lib/perl5/site_perl/smbldap_tools.pm
+fi
+if [ -f /usr/lib/perl5/site_perl/smbldap_conf.pm ];
+then
+       rm -f /usr/lib/perl5/site_perl/smbldap_conf.pm
+fi
 chgrp 512 %{prefix}/sbin/smbldap-useradd.pl %{prefix}/sbin/smbldap_conf.pm || echo "An error occured while changing groups of smbldap-useradd.pl and smbldap_conf.pm in /usr/local/sbin. For proper operations, please ensure that they have the same posix group as the Samba domain administrator if there's a local Samba PDC."
 perl -i -pe 's/_SLAVELDAP_/localhost/' %{prefix}/sbin/smbldap_conf.pm
 perl -i -pe 's/_MASTERLDAP_/localhost/' %{prefix}/sbin/smbldap_conf.pm
@@ -101,11 +111,11 @@ perl -i -pe 's/_USERS_/Users/' %{prefix}/sbin/smbldap_conf.pm
 perl -i -pe 's/_COMPUTERS_/Computers/' %{prefix}/sbin/smbldap_conf.pm
 perl -i -pe 's/_GROUPS_/Groups/' %{prefix}/sbin/smbldap_conf.pm
 perl -i -pe 's/_LOGINSHELL_/\/bin\/bash/' %{prefix}/sbin/smbldap_conf.pm
-perl -i -pe 's/_HOMEPREFIX_/\/home\//' %{prefix}/sbin/smbldap_conf.pm
+perl -i -pe 's/_HOMEPREFIX_/\/home/' %{prefix}/sbin/smbldap_conf.pm
 perl -i -pe 's/_BINDDN_/cn=Manager,\$suffix/' %{prefix}/sbin/smbldap_conf.pm
 perl -i -pe 's/_BINDPW_/secret/' %{prefix}/sbin/smbldap_conf.pm
 perl -i -pe 's/_PDCNAME_/PDC-SRV/' %{prefix}/sbin/smbldap_conf.pm
-perl -i -pe 's/_HOMEDRIVE_/H/' %{prefix}/sbin/smbldap_conf.pm
+perl -i -pe 's/_HOMEDRIVE_/H:/' %{prefix}/sbin/smbldap_conf.pm
 
 # FIXME: links should not be removed on upgrade
 #%postun
@@ -118,53 +128,13 @@ perl -i -pe 's/_HOMEDRIVE_/H/' %{prefix}/sbin/smbldap_conf.pm
 %defattr(-,root,root)
 %{prefix}/sbin/*.pl
 %{prefix}/sbin/smbldap_tools.pm
-%config %{prefix}/sbin/smbldap_conf.pm
+%config(noreplace) %{prefix}/sbin/smbldap_conf.pm
 %{prefix}/sbin/mkntpwd
 %doc /usr/share/doc/%{name}/
 
 
 %changelog
-* Fri Aug 22 2003 Jerome Tournier <jerome.tournier@idealx.com> 0.8-1
-- support for Samba3.0
+* Fri Nov 28 2003 Jerome Tournier <jerome.tournier@idealx.com> 0.8.2-1
+- new smb.conf file as example configuration file
+- see Changelog file for updates in scripts
 
-* Thu Sep 26 2002 Gérald Macinenti <gmacinenti@IDEALX.com> 0.7-2
-- top and account objectclasses replaced by InetOrgPerson
-
-* Sat Jun  1 2002 Olivier Lemaire <olem@IDEALX.com> 0.7-1
-- some bugfixes about smbldap-populate
-- bugfixed the smbpasswd call in smbldap-useradd
-- cleaned up the smbldap_conf
-- more documentation
-
-* Tue Apr 30 2002 Brad Langhorst <brad@langhorst.com> 0.6-2
-- changed requires samba-common to samba
-- replaced /usr/local with %{prefix} to allow relocation
-
-* Tue Feb 5 2002 David Le Corfec <dlc@IDEALX.com> 0.6-1
-- v0.6
-
-* Mon Feb 4 2002 David Le Corfec <dlc@IDEALX.com> 0.5-1
-- v0.5
-
-* Mon Jan 14 2002 David Le Corfec <dlc@IDEALX.com> 0.3-4
-- internal changes
-- should upgrade smoothly from now on
-
-* Mon Jan 14 2002 David Le Corfec <dlc@IDEALX.com> 0.2-1
-- added migration scripts
-
-* Fri Dec 28 2001 David Le Corfec <dlc@IDEALX.com> 0.1-5
-- numeric group for chmod
-
-* Thu Dec 27 2001 David Le Corfec <dlc@IDEALX.com> 0.1-4
-- misc bugfixes
-
-* Mon Dec 18 2001 David Le Corfec <dlc@IDEALX.com> 0.1-3
-- changed files attrs for domain admins to add users
-- added smbldap-populate.pl
-
-* Fri Dec 14 2001 David Le Corfec <dlc@IDEALX.com>
-- added mkntpwd
-
-* Wed Dec 12 2001 Olivier Lemaire <olivier.lemaire@IDEALX.com>
-- Spec file was generated, and tested atomically.
index a84d9f68b217eeca5c978f6dcd54c7a26ebec780..49086e519b833262f2bf809a34d977b439bf17ca 100755 (executable)
@@ -1,5 +1,7 @@
 #!/usr/bin/perl -w
 
+# $Id: smbldap-useradd.pl,v 1.1.6.4 2003/12/04 21:59:19 jerry Exp $
+#
 #  This code was developped by IDEALX (http://IDEALX.org/) and
 #  contributors (their names can be found in the CONTRIBUTORS file).
 #
@@ -35,102 +37,92 @@ 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:N:S:?', \%Options);
+my $ok = getopts('anmwPG: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";
-       print "  -a     is a Windows User (otherwise, Posix stuff only)\n";
-       print "  -w     is a Windows Workstation (otherwise, Posix stuff only)\n";
-       print "  -x     creates rid and primaryGroupID in hex instead of decimal\n";
-       print "  -u     uid\n";
-       print "  -g     gid\n";
-       print "  -G     supplementary comma-separated groups\n";
-       print "  -n     do not create a group\n";
-       print "  -d     home\n";
-       print "  -s     shell\n";
-       print "  -c     gecos\n";
-       print "  -m     creates home directory and copies /etc/skel\n";
-       print "  -k     skeleton dir (with -m)\n";
-       print "  -P     ends by invoking smbldap-passwd.pl\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";
-       print "  -C     sambaHomePath (SMB home share, like '\\\\PDC-SRV\\homes')\n";
-       print "  -D     sambaHomeDrive (letter associated with home share, like 'H:')\n";
-       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);
+  print "Usage: $0 [-awmugdsckGPABCDEFH?] username\n";
+  print "  -a  is a Windows User (otherwise, Posix stuff only)\n";
+  print "  -w  is a Windows Workstation (otherwise, Posix stuff only)\n";
+  print "  -u  uid\n";
+  print "  -g  gid\n";
+  print "  -G  supplementary comma-separated groups\n";
+  print "  -n  do not create a group\n";
+  print "  -d  home\n";
+  print "  -s  shell\n";
+  print "  -c  gecos\n";
+  print "  -m  creates home directory and copies /etc/skel\n";
+  print "  -k  skeleton dir (with -m)\n";
+  print "  -P  ends by invoking smbldap-passwd.pl\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";
+  print "  -C  sambaHomePath (SMB home share, like '\\\\PDC-SRV\\homes')\n";
+  print "  -D  sambaHomeDrive (letter associated with home share, like 'H:')\n";
+  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);
 }
 
+
 # cause problems when dealing with getpwuid because of the
 # negative ttl and ldap modification
 my $nscd_status = system "/etc/init.d/nscd status >/dev/null 2>&1";
 
 if ($nscd_status == 0) {
-   system "/etc/init.d/nscd stop > /dev/null 2>&1";
+  system "/etc/init.d/nscd stop > /dev/null 2>&1";
 }
 
+
 # Read options
 my $userUidNumber = $Options{'u'};
 if (!defined($userUidNumber)) { 
-       # find first unused uid starting from $UID_START
-       while (defined(getpwuid($UID_START))) {
-               $UID_START++;
-       }
-       $userUidNumber = $UID_START;
+  # find first unused uid starting from $UID_START
+  while (defined(getpwuid($UID_START))) {
+       $UID_START++;
+  }
+  $userUidNumber = $UID_START;
 } elsif (getpwuid($userUidNumber)) {
   die "Uid already exists.\n";
 }
 
 if ($nscd_status == 0) {
-   system "/etc/init.d/nscd start > /dev/null 2>&1";
+  system "/etc/init.d/nscd start > /dev/null 2>&1";
 }
 
 
-# as rid we use 2 * uid + 1000
-my $userRid = 2 * $userUidNumber + 1000;
-if (defined($Options{'x'})) {
-    $userRid= sprint("%x", $userRid);
-}
-
 my $createGroup = 0;
 my $userGidNumber = $Options{'g'};
 # gid not specified ? 
 if (!defined($userGidNumber)) {
-    # windows machine => $_defaultComputerGid
-    if (defined($Options{'w'})) {
+  # windows machine => $_defaultComputerGid
+  if (defined($Options{'w'})) {
        $userGidNumber = $_defaultComputerGid;
-#    } elsif (!defined($Options{'n'})) {
+       #    } elsif (!defined($Options{'n'})) {
        # create new group (redhat style)
        # find first unused gid starting from $GID_START
-#      while (defined(getgrgid($GID_START))) {
-#              $GID_START++;
-#      }
-#      $userGidNumber = $GID_START;
+       #       while (defined(getgrgid($GID_START))) {
+       #               $GID_START++;
+       #       }
+       #       $userGidNumber = $GID_START;
 
-#      $createGroup = 1;
+       #       $createGroup = 1;
 
-    } else {
+  } else {
        # user will have gid = $_defaultUserGid
        $userGidNumber = $_defaultUserGid;
-    }
+  }
 } else {
-    my $gid;
-    if (($gid = parse_group($userGidNumber)) < 0) {
+  my $gid;
+  if (($gid = parse_group($userGidNumber)) < 0) {
        print "$0: unknown group $userGidNumber\n";
        exit (6);
-    }
-    $userGidNumber = $gid;
+  }
+  $userGidNumber = $gid;
 }
 
-# as grouprid we use 2 * gid + 1001
-my $userGroupRid = 2 * $userGidNumber + 1001;
-if (defined($Options{'x'})) {
-    $userGroupRid = sprint("%x", $userGroupRid);
-}
 # Read only first @ARGV
 my $userName = $ARGV[0];
 
@@ -145,18 +137,49 @@ if ($userName =~ /^([\w -]+\$?)$/) {
 # user must not exist in LDAP (should it be nss-wide ?)
 my ($rc, $dn) = get_user_dn2($userName);
 if ($rc and defined($dn)) {
-    print "$0: user $userName exists\n";
-    exit (9);
+  print "$0: user $userName exists\n";
+  exit (9);
 } elsif (!$rc) {
-    print "$0: error in get_user_dn2\n";
-    exit(10);
+  print "$0: error in get_user_dn2\n";
+  exit(10);
+}
+
+my $group_entry;
+my $userGroupSID;
+my $userRid;
+if ($Options{'a'}) {
+       # as grouprid we use the value of the sambaSID attribute for
+       # group of gidNumber=$userGidNumber
+       $group_entry = read_group_entry_gid($userGidNumber);
+       $userGroupSID = $group_entry->get_value('sambaSID');
+       unless ($userGroupSID) {
+         print "$0: unknown group SID not set for unix group $userGidNumber\n";
+         print "check if your unix group is mapped to an NT group\n";
+         exit (7);
+       }
+
+       # as rid we use 2 * uid + 1000
+       $userRid = 2 * $userUidNumber + 1000;
+        # let's test if this SID already exist
+       my $user_sid="$SID-$userRid";
+        my $test_exist_sid=does_sid_exist($user_sid,$usersdn);
+        if ($test_exist_sid->count == 1) {
+                print "User SID already owned by\n";
+                # there should not exist more than one entry, but ...
+                foreach my $entry ($test_exist_sid->all_entries) {
+                        my $dn= $entry->dn;
+                        chomp($dn);
+                        print "$dn\n";
+                }
+                exit(7);
+        }
 }
 
 my $userHomeDirectory;
 my ($userCN, $userSN);
 my $tmp;
 if (!defined($userHomeDirectory = $Options{'d'})) {
-    $userHomeDirectory = $_userHomePrefix."/".$userName;
+  $userHomeDirectory = $_userHomePrefix."/".$userName;
 }
 $_userLoginShell = $tmp if (defined($tmp = $Options{'s'}));
 $_userGecos = $tmp if (defined($tmp = $Options{'c'}));
@@ -174,26 +197,26 @@ my $ldap_master=connect_ldap_master();
 # MACHINE ACCOUNT
 if (defined($tmp = $Options{'w'})) {
    
-    # add a trailing dollar if missing
-    if ($userName =~ /[^\$]$/s) {
+  # add a trailing dollar if missing
+  if ($userName =~ /[^\$]$/s) {
        $userName .= "\$";
-    }
+  }
 
-    #print "About to create machine $userName:\n";
+  #print "About to create machine $userName:\n";
 
-    if (!add_posix_machine ($userName, $userUidNumber, $userGidNumber)) {
+  if (!add_posix_machine ($userName, $userUidNumber, $userGidNumber)) {
        die "$0: error while adding posix account\n";
-    }
+  }
 
-    if (!$with_smbpasswd) {
+  if (!$with_smbpasswd) {
        # (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 {
+  } else {
        if (!add_samba_machine($userName)) {
-           die "$0: error while adding samba account\n";
+         die "$0: error while adding samba account\n";
        }
        my $modify = $ldap_master->modify ( "$dn",
                                                                                changes => [
@@ -201,9 +224,9 @@ if (defined($tmp = $Options{'w'})) {
                                                                                                   ]
                                                                          );
        $modify->code && warn "failed to modify entry: ", $modify->error ;
-    }
+  }
 
-    exit 0;
+  exit 0;
 }
 
 # USER ACCOUNT
@@ -237,56 +260,62 @@ group_add_user($userGidNumber, $userName);
 my $grouplist;
 # adds to supplementary groups
 if (defined($grouplist = $Options{'G'})) {
-    add_grouplist_user($grouplist, $userName);
+  add_grouplist_user($grouplist, $userName);
 }
 
 # If user was created successfully then we should create his/her home dir
 if (defined($tmp = $Options{'m'})) {
-   unless ( $userName =~ /\$$/ ) {
+  unless ( $userName =~ /\$$/ ) {
     if ( !(-e $userHomeDirectory) ) {
-       system "mkdir $userHomeDirectory 2>/dev/null";
-       system "cp -a $_skeletonDir/.[a-z,A-Z]* $_skeletonDir/* $userHomeDirectory 2>/dev/null";
-       system "chown -R $userUidNumber:$userGidNumber $userHomeDirectory 2>/dev/null";
-       system "chmod 700 $userHomeDirectory 2>/dev/null"; 
+         system "mkdir $userHomeDirectory 2>/dev/null";
+         system "cp -a $_skeletonDir/.[a-z,A-Z]* $_skeletonDir/* $userHomeDirectory 2>/dev/null";
+         system "chown -R $userUidNumber:$userGidNumber $userHomeDirectory 2>/dev/null";
+         system "chmod 700 $userHomeDirectory 2>/dev/null"; 
     }
-   }
+  }
 }
 
 
 # Add Samba user infos
 if (defined($Options{'a'})) {
-    if (!$with_smbpasswd) {
+  if (!$with_smbpasswd) {
 
        my $winmagic = 2147483647;
        my $valpwdcanchange = 0;
        my $valpwdmustchange = $winmagic;
+       my $valpwdlastset = 0;
        my $valacctflags = "[UX]";
 
        if (defined($tmp = $Options{'A'})) {
-           if ($tmp != 0) {
+         if ($tmp != 0) {
                $valpwdcanchange = "0";
-           } else {
+         } else {
                $valpwdcanchange = "$winmagic";
-           }
+         }
        }
 
        if (defined($tmp = $Options{'B'})) {
-           if ($tmp != 0) {
+         if ($tmp != 0) {
                $valpwdmustchange = "0";
-           } else {
+               # To force a user to change his password:
+               # . the attribut sambaPwdLastSet must be != 0
+               # . the attribut sambaAcctFlags must not match the 'X' flag
+               $valpwdlastset=$winmagic;
+               $valacctflags = "[U]";
+         } else {
                $valpwdmustchange = "$winmagic";
-           }
+         }
        }
 
        if (defined($tmp = $Options{'H'})) {
-           $valacctflags = "$tmp";
+         $valacctflags = "$tmp";
        }
 
 
        my $modify = $ldap_master->modify ( "uid=$userName,$usersdn",
                                                                                changes => [
                                                                                                        add => [objectClass => 'sambaSAMAccount'],
-                                                                                                       add => [sambaPwdLastSet => '0'],
+                                                                                                       add => [sambaPwdLastSet => "$valpwdlastset"],
                                                                                                        add => [sambaLogonTime => '0'],
                                                                                                        add => [sambaLogoffTime => '2147483647'],
                                                                                                        add => [sambaKickoffTime => '2147483647'],
@@ -300,7 +329,7 @@ if (defined($Options{'a'})) {
        
        $modify->code && die "failed to add entry: ", $modify->error ;
 
-    } else {
+  } else {
        my $FILE="|smbpasswd -s -a $userName >/dev/null" ;
        open (FILE, $FILE) || die "$!\n";
        print FILE <<EOF;
@@ -310,45 +339,64 @@ EOF
     ;
        close FILE;
        if ($?) {
-           print "$0: error adding samba account\n";
-           exit (10);
+         print "$0: error adding samba account\n";
+         exit (10);
        }
-    } # with_smbpasswd
-
-    my $valscriptpath = "$userName.cmd";
-    my $valprofilepath = "$_userProfile$userName";
-    my $valsmbhome = "$_userSmbHome";
-    my $valhomedrive = "$_userHomeDrive";
+  }                                                            # with_smbpasswd
+
+  my @mods;
+  my $valscriptpath;
+  if (defined $_userScript) {
+        $valscriptpath="$_userScript";
+  } else {
+        $valscriptpath = "$userName.cmd";
+  }
+  if (defined($tmp = $Options{'E'})) {
+    $valscriptpath = "$tmp";
+  }
 
-if (defined($tmp = $Options{'C'})) {
+  my $valsmbhome;
+  if (defined $_userSmbHome) {
+       $valsmbhome = "$_userSmbHome";
+  }
+  if (defined($tmp = $Options{'C'})) {
     $valsmbhome = "$tmp";
-}
+  }
+  if (defined $valsmbhome) {
+       push(@mods, 'sambaHomePath', $valsmbhome);
+  }
 
-if (defined($tmp = $Options{'D'})) {
+  my $valhomedrive = "$_userHomeDrive";
+  if (defined($tmp = $Options{'D'})) {
     $tmp = $tmp.":" unless ($tmp =~ /:/);
     $valhomedrive = "$tmp";
-}
+  }
 
-if (defined($tmp = $Options{'E'})) {
-    $valscriptpath = "$tmp";
-}
+  my $valprofilepath;
+  if (defined $_userProfile) {
+       $valprofilepath = "$_userProfile$userName";
+  }
 
-if (defined($tmp = $Options{'F'})) {
+  if (defined($tmp = $Options{'F'})) {
     $valprofilepath = "$tmp";
-}
+  }
+  if (defined $valprofilepath) {
+       push(@mods, 'sambaProfilePath', $valprofilepath);
+  }
 
-       
   my $modify = $ldap_master->modify ( "uid=$userName,$usersdn",
                                                                          changes => [
-                                                                                                 add => [sambaPrimaryGroupSID => "$SID-$userGroupRid"],
+                                                                                                 add => [sambaPrimaryGroupSID => "$userGroupSID"],
                                                                                                  add => [sambaHomeDrive => "$valhomedrive"],
-                                                                                                 add => [sambaHomePath => "$valsmbhome"],
-                                                                                                 add => [sambaProfilePath => "$valprofilepath"],
                                                                                                  add => [sambaLogonScript => "$valscriptpath"],
                                                                                                  add => [sambaLMPassword => 'XXX'],
                                                                                                  add => [sambaNTPassword => 'XXX']
                                                                                                 ]
                                                                        );
+  $modify = $ldap_master->modify ( "uid=$userName,$usersdn",
+                                                                       'replace' => { @mods }
+                                                                       );
+
 
   $modify->code && die "failed to add entry: ", $modify->error ;
 
@@ -357,7 +405,7 @@ $ldap_master->unbind;                       # take down session
 
 
 if (defined($Options{'P'})) {
-    exec "/usr/local/sbin/smbldap-passwd.pl $userName"
+  exec "/usr/local/sbin/smbldap-passwd.pl $userName"
 }
 
 exit 0;
@@ -366,57 +414,57 @@ exit 0;
 
 =head1 NAME
 
-       smbldap-useradd.pl - Create a new user or update default new 
-                            user information
+smbldap-useradd.pl - Create a new user or update default new 
+  user information
 
 =head1 SYNOPSIS
 
-       smbldap-useradd.pl [-c comment] [-d home_dir]
-               [-g initial_group] [-G group[,...]]
-               [-m [-k skeleton_dir]]
-               [-s shell] [-u uid [ -o]] [-P]
-               [-A canchange] [-B mustchange] [-C smbhome]
-               [-D homedrive] [-E scriptpath] [-F profilepath]
-               [-H acctflags] login
+smbldap-useradd.pl [-c comment] [-d home_dir]
+  [-g initial_group] [-G group[,...]]
+  [-m [-k skeleton_dir]]
+  [-s shell] [-u uid [ -o]] [-P]
+  [-A canchange] [-B mustchange] [-C smbhome]
+  [-D homedrive] [-E scriptpath] [-F profilepath]
+  [-H acctflags] login
 
 =head1 DESCRIPTION
 
-   Creating New Users
-       The smbldap-useradd.pl command creates a new user account using
-       the values specified on the  command  line  and  the default
-       values from the system.
-       The new user account will be entered into the system
-       files as needed, the home directory  will  be  created, and 
-       initial  files copied, depending on the command line options.
+Creating New Users
+  The smbldap-useradd.pl command creates a new user account using
+  the values specified on the  command  line  and  the default
+  values from the system.
+  The new user account will be entered into the system
+  files as needed, the home directory  will  be  created, and 
+  initial  files copied, depending on the command line options.
 
-       You have to use smbldap-passwd to set the user password.
-       For Samba users, rid is 2*uidNumber+1000, and primaryGroupID
-       is 2*gidNumber+1001. Thus you may want to use
-       smbldap-useradd.pl -a -g "Domain Admins" -u 500 Administrator
-       to create a sambaDomainName administrator (admin rid is 0x1F4 = 500 and
-       grouprid is 0x200 = 512)
+  You have to use smbldap-passwd to set the user password.
+  For Samba users, rid is 2*uidNumber+1000, and primaryGroupID
+  is 2*gidNumber+1001. Thus you may want to use
+  smbldap-useradd.pl -a -g "Domain Admins" -u 500 Administrator
+  to create a sambaDomainName administrator (admin rid is 0x1F4 = 500 and
+                                                                                        grouprid is 0x200 = 512)
 
-       Without any option, the account created will be an Unix (Posix)
-       account. The following options may be used to add information:
+  Without any option, the account created will be an Unix (Posix)
+  account. The following options may be used to add information:
 
-       -a     The user will have a Samba account (and Unix).
+-a     The user will have a Samba account (and Unix).
 
-       -w     Creates an account for a Samba machine (Workstation), so that 
-              it can join a sambaDomainName.
+  -w     Creates an account for a Samba machine (Workstation), so that 
+  it can join a sambaDomainName.
 
-       -x     Creates rid and primaryGroupID in hex (for Samba 2.2.2 bug). Else
-              decimal (2.2.2 patched from cvs or 2.2.x, x > 2)
+  -x     Creates rid and primaryGroupID in hex (for Samba 2.2.2 bug). Else
+  decimal (2.2.2 patched from cvs or 2.2.x, x > 2)
 
-       -c comment
-              The new user's comment field (gecos).
+  -c comment
+  The new user's comment field (gecos).
 
        -d home_dir
               The new user will be created using home_dir as the value for the
               user's login directory.  The default is to append the login name
-              to default_home and use that as the login directory name.
+  to default_home and use that as the login directory name.
 
-       -g initial_group
-              The group name or number of the user's initial login group.  The
+  -g initial_group
+  The group name or number of the user's initial login group.  The
               group  name must exist.  A group number must refer to an already
               existing group.  The default group number is 1.
 
@@ -428,20 +476,20 @@ exit 0;
               is for the user to belong only to the initial group.
 
        -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­
-              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
+  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­
+  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
               the directory and to not copy any files.
 
        -s shell
               The name of the user's login shell.  The  default  is  to  leave
-              this  field blank, which causes the system to select the default
-              login shell.
+  this  field blank, which causes the system to select the default
+  login shell.
 
-       -u uid The numerical value of  the  user's  ID.   This  value  must  be
+  -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.  The default is to use the smallest ID  value  greater
               than 1000 and greater than every other user.
index 1a1a3214b589d99f0f2a6e4b2cb31373b6201e72..449c56d3d59290a89dee9cbe70a57f31280edebb 100755 (executable)
@@ -1,5 +1,7 @@
 #!/usr/bin/perl
 
+# $Id: smbldap-userdel.pl,v 1.1.6.4 2003/12/04 21:59:19 jerry Exp $
+#
 #  This code was developped by IDEALX (http://IDEALX.org/) and
 #  contributors (their names can be found in the CONTRIBUTORS file).
 #
@@ -37,9 +39,9 @@ my %Options;
 my $ok = getopts('r?', \%Options);
 
 if ( (!$ok) || (@ARGV < 1) || ($Options{'?'}) ) {
-       print "Usage: $0 [-r?] username\n";
-       print "  -r     remove home directory\n";
-       exit (1);
+  print "Usage: $0 [-r?] username\n";
+  print "  -r  remove home directory\n";
+  exit (1);
 }
 
 # Read only first @ARGV
@@ -48,34 +50,34 @@ my $user = $ARGV[0];
 my $dn;
 # user must not exist in LDAP
 if (!defined($dn=get_user_dn($user))) {
-    print "$0: user $user does not exist\n";
-    exit (6);
+  print "$0: user $user does not exist\n";
+  exit (6);
 }
 
 if ($< != 0) {
-    print "You must be root to delete an user\n";
-    exit (1);
+  print "You must be root to delete an user\n";
+  exit (1);
 }
 
 my $homedir;
 if (defined($Options{'r'})) {
-    $homedir=get_homedir($user);
+  $homedir=get_homedir($user);
 }
 
 # remove user from groups
 my $groups = find_groups_of $user;
-my @grplines = split(/\n/, $groups);
+my @grplines = split(/\n/,$groups);
 
 my $grp;
 foreach $grp (@grplines) {
-    my $gname = "";
-    if ( $grp =~ /dn: cn=([^,]+),/) {
+  my $gname = "";
+  if ( $grp =~ /dn: cn=([^,]+),/) {
        $gname = $1;
        #print "xx $gname\n";
-    }
-    if ($gname ne "") {
+  }
+  if ($gname ne "") {
        group_remove_member($gname, $user);
-    }
+  }
 }
 
 # XXX
@@ -83,9 +85,9 @@ delete_user($user);
 
 # delete dir -- be sure that homeDir is not a strange value
 if (defined($Options{'r'})) {
-    if ($homedir !~ /^\/dev/ and $homedir !~ /^\/$/) {
+  if ($homedir !~ /^\/dev/ and $homedir !~ /^\/$/) {
        system "rm -rf $homedir";
-    }
+  }
 }
 
 my $nscd_status = system "/etc/init.d/nscd status >/dev/null 2>&1";
index f25c730fc851172d2033e031c0e51d3dbcd72883..96fc8c38db260c096dd50f7ba2fc73505cd7e17f 100755 (executable)
@@ -1,5 +1,7 @@
-#!/usr/bin/perl 
+#!/usr/bin/perl -w
 
+# $Id: smbldap-usermod.pl,v 1.1.6.4 2003/12/04 21:59:19 jerry Exp $
+#
 #  This code was developped by IDEALX (http://IDEALX.org/) and
 #  contributors (their names can be found in the CONTRIBUTORS file).
 #
@@ -29,48 +31,48 @@ use lib "$RealBin/";
 use smbldap_tools;
 use smbldap_conf;
 
-
 #####################
 
 use Getopt::Std;
 my %Options;
 my $nscd_status;
 
-my $ok = getopts('A:B:C:D:E:F:H:IJN:S:xme:f:u:g:G:d:l:s:c:ok:?h', \%Options);
+my $ok = getopts('A:B:C:D:E:F:H:IJN:S:Pame: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 "  -f    inactive days\n";
-       print "  -u     uid\n";
-       print "  -o     uid can be non unique\n";
-       print "  -g     gid\n";
-       print "  -G     supplementary groups (comma separated)\n";
-       print "  -l     login name\n";
-       print "  -s     shell\n";
+  print "  -c    gecos\n";
+  print "  -d    home directory\n";
+  #print "  -m    move home directory\n";
+  #print "  -f    inactive days\n";
+  print "  -u    uid\n";
+  print "  -o    uid can be non unique\n";
+  print "  -g    gid\n";
+  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 "  -P    ends by invoking smbldap-passwd.pl\n";
   print " For samba users:\n";
+  print "  -a    add sambaSAMAccount objectclass\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";
-       print "  -C     sambaHomePath (SMB home share, like '\\\\PDC-SRV\\homes')\n";
-       print "  -D     sambaHomeDrive (letter associated with home share, like 'H:')\n";
-       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 "  -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 "  -A    can change password ? 0 if no, 1 if yes\n";
+  print "  -B    must change password ? 0 if no, 1 if yes\n";
+  print "  -C    sambaHomePath (SMB home share, like '\\\\PDC-SRV\\homes')\n";
+  print "  -D    sambaHomeDrive (letter associated with home share, like 'H:')\n";
+  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 "  -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 "  -?|-h show this help message\n";
-       exit (1);
+  exit (1);
 }
 
 if ($< != 0) {
-    print "You must be root to modify an user\n";
-    exit (1);
+  print "You must be root to modify an user\n";
+  exit (1);
 }
 
 # Read only first @ARGV
@@ -79,13 +81,13 @@ my $user = $ARGV[0];
 # 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 "$0: user $user doesn't exist\n";
+  exit (1);
 }
 
 my $samba = 0;
 if (grep ($_ =~ /^sambaSamAccount$/i, $user_entry->get_value('objectClass'))) {
-    $samba = 1;
+  $samba = 1;
 }
 
 # get the dn of the user
@@ -93,64 +95,94 @@ my $dn= $user_entry->dn();
 
 my $tmp;
 my @mods;
+if (defined($tmp = $Options{'a'})) {
+       # Let's connect to the directory first
+       my $ldap_master=connect_ldap_master();
+        my $winmagic = 2147483647;
+        my $valpwdcanchange = 0;
+        my $valpwdmustchange = $winmagic;
+        my $valpwdlastset = 0; 
+        my $valacctflags = "[UX]";
+       my $user_entry=read_user_entry($user);
+       my $uidNumber = $user_entry->get_value('uidNumber');
+       my $userRid = 2 * $uidNumber + 1000;
+       # apply changes
+       my $modify = $ldap_master->modify ( "$dn",
+                                                                                changes => [
+                                                                                                        add => [objectClass => 'sambaSAMAccount'],
+                                                                                                        add => [sambaPwdLastSet => "$valpwdlastset"],
+                                                                                                        add => [sambaLogonTime => '0'],
+                                                                                                        add => [sambaLogoffTime => '2147483647'],
+                                                                                                        add => [sambaKickoffTime => '2147483647'],
+                                                                                                        add => [sambaPwdCanChange => "$valpwdcanchange"],
+                                                                                                        add => [sambaPwdMustChange => "$valpwdmustchange"],
+                                                                                                        add => [displayName => "$_userGecos"],
+                                                                                                        add => [sambaSID=> "$SID-$userRid"],
+                                                                                                        add => [sambaAcctFlags => "$valacctflags"],
+                                                                                                   ]
+                                                                 );
+       $modify->code && warn "failed to modify entry: ", $modify->error ;
+}
 
 # Process options
 my $changed_uid;
 my $_userUidNumber;
 my $_userRid;
 if (defined($tmp = $Options{'u'})) {
-    if (defined($Options{'o'})) {
+  if (defined($Options{'o'})) {
        $nscd_status = system "/etc/init.d/nscd status >/dev/null 2>&1";
        
        if ($nscd_status == 0) {
-           system "/etc/init.d/nscd stop > /dev/null 2>&1";
+         system "/etc/init.d/nscd stop > /dev/null 2>&1";
        }
 
        if (getpwuid($tmp)) {
-           if ($nscd_status == 0) {
+         if ($nscd_status == 0) {
                system "/etc/init.d/nscd start > /dev/null 2>&1";
-           }
+         }
 
-           print "$0: uid number $tmp exists\n";
-           exit (6);
+         print "$0: uid number $tmp exists\n";
+         exit (6);
        }
        if ($nscd_status == 0) {
-           system "/etc/init.d/nscd start > /dev/null 2>&1";
+         system "/etc/init.d/nscd start > /dev/null 2>&1";
        }
 
-    }
+  }
   push(@mods, 'uidNumber', $tmp);
-    $_userUidNumber = $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);
+      $_userRid= sprint("%x", $_userRid);
     }
     push(@mods, 'sambaSID', $SID.'-'.$_userRid);
-    }
-    $changed_uid = 1;
+  }
+  $changed_uid = 1;
 }
 
 my $changed_gid;
 my $_userGidNumber;
-my $_userGroupRid;
+my $_userGroupSID;
 if (defined($tmp = $Options{'g'})) {
-    $_userGidNumber = parse_group($tmp);
-    if ($_userGidNumber < 0) {
+  $_userGidNumber = parse_group($tmp);
+  if ($_userGidNumber < 0) {
        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);
-    }
-    push(@mods, 'sambaPrimaryGroupSid', $SID.'-'.$_userGroupRid);
+    # as grouprid we use the sambaSID attribute's value of the group
+    my $group_entry = read_group_entry_gid($_userGidNumber);
+    my $_userGroupSID = $group_entry->get_value('sambaSID');
+    unless ($_userGroupSID) {
+      print "$0: unknown group SID not set for unix group $_userGidNumber\n";
+      exit (7);
     }
-    $changed_gid = 1;
+    push(@mods, 'sambaPrimaryGroupSid', $_userGroupSID);
+  }
+  $changed_gid = 1;
 }
 
 if (defined($tmp = $Options{'s'})) {
@@ -158,7 +190,7 @@ if (defined($tmp = $Options{'s'})) {
 }
 
 
-if (defined($tmp = $Options{'c'})) { 
+if (defined($tmp = $Options{'c'})) {
   push(@mods, 'gecos' => $tmp,
           'description' => $tmp);
   if ($samba == 1) {
@@ -180,24 +212,24 @@ if (defined($tmp = $Options{'S'})) {
 
 if (defined($tmp = $Options{'G'})) {
 
-    # remove user from old groups
-    my $groups = find_groups_of $user;
-    my @grplines = split(/\n/, $groups);
+  # remove user from old groups
+  my $groups = find_groups_of $user;
+  my @grplines = split(/\n/,$groups);
 
-    my $grp;
-    foreach $grp (@grplines) {
+  my $grp;
+  foreach $grp (@grplines) {
        my $gname = "";
        if ( $grp =~ /dn: cn=([^,]+),/) {
-           $gname = $1;
-           #print "xx $gname\n";
+         $gname = $1;
+         #print "xx $gname\n";
        }
        if ($gname ne "") {
-           group_remove_member($gname, $user);
+         group_remove_member($gname, $user);
        }
-    }
+  }
 
-    # add user to new groups
-    add_grouplist_user($tmp, $user);
+  # add user to new groups
+  add_grouplist_user($tmp, $user);
 }
 
 #
@@ -212,7 +244,7 @@ if (defined($tmp = $Options{'G'})) {
 my $attr;
 my $winmagic = 2147483647;
 
-my $samba = is_samba_user($user);
+$samba = is_samba_user($user);
 
 if (defined($tmp = $Options{'e'})) {
   if ($samba == 1) {
@@ -234,9 +266,9 @@ if (defined($tmp = $Options{'A'})) {
       $_sambaPwdCanChange=$winmagic;
     }
     push(@mods, 'sambaPwdCanChange' => $_sambaPwdCanChange);
-    } else {
+  } else {
        print "User $user is not a samba user\n";
-    }
+  }
 }
 
 my $_sambaPwdMustChange;
@@ -244,13 +276,31 @@ if (defined($tmp = $Options{'B'})) {
   if ($samba == 1) {
     if ($tmp != 0) {
       $_sambaPwdMustChange=0;
+      # To force a user to change his password:
+      # . the attribut sambaPwdLastSet must be != 0
+      # . the attribut sambaAcctFlags must not match the 'X' flag
+      my $_sambaAcctFlags;
+      my $flags = $user_entry->get_value('sambaAcctFlags');
+      if ( $flags =~ /X/ ) {
+       my $letters;
+       if ($flags =~ /(\w+)/) {
+               $letters = $1;
+       }
+       $letters =~ s/X//;
+       $_sambaAcctFlags="\[$letters\]";
+       push(@mods, 'sambaAcctFlags' => $_sambaAcctFlags);
+      }
+      my $_sambaPwdLastSet = $user_entry->get_value('sambaPwdLastSet');
+      if ($_sambaPwdLastSet == 0) {
+       push(@mods, 'sambaPwdLastSet' => $winmagic);
+      }
     } else {
       $_sambaPwdMustChange=$winmagic;
     }
     push(@mods, 'sambaPwdMustChange' => $_sambaPwdMustChange);
-    } else {
+  } else {
        print "User $user is not a samba user\n";
-    }
+  }
 }
 
 if (defined($tmp = $Options{'C'})) {
@@ -292,7 +342,7 @@ if (defined($tmp = $Options{'F'})) {
 
 if ($samba == 1 and (defined $Options{'H'} or defined $Options{'I'} or defined $Options{'J'})) {
   my $_sambaAcctFlags;
-if (defined($tmp = $Options{'H'})) {
+  if (defined($tmp = $Options{'H'})) {
     #$tmp =~ s/\\/\\\\/g;
     $_sambaAcctFlags=$tmp;
   } else {
@@ -301,24 +351,24 @@ if (defined($tmp = $Options{'H'})) {
     $flags = $user_entry->get_value('sambaAcctFlags');
 
     if (defined($tmp = $Options{'I'})) {
-    if ( !($flags =~ /D/) ) {
-       my $letters;
-       if ($flags =~ /(\w+)/) {
-           $letters = $1;
-       }
+      if ( !($flags =~ /D/) ) {
+               my $letters;
+               if ($flags =~ /(\w+)/) {
+                 $letters = $1;
+               }
                $_sambaAcctFlags="\[D$letters\]";
-    }
-} elsif (defined($tmp = $Options{'J'})) {
-    if ( $flags =~ /D/ ) {
-       my $letters;
-       if ($flags =~ /(\w+)/) {
-           $letters = $1;
-       }
-       $letters =~ s/D//;
+      }
+    } elsif (defined($tmp = $Options{'J'})) {
+         if ( $flags =~ /D/ ) {
+               my $letters;
+               if ($flags =~ /(\w+)/) {
+                 $letters = $1;
+               }
+               $letters =~ s/D//;
                $_sambaAcctFlags="\[$letters\]";
          }
-    }
-}
+       }
+  }
 
 
   if ("$_sambaAcctFlags" ne '') {
@@ -344,7 +394,11 @@ $ldap_master->unbind;
 $nscd_status = system "/etc/init.d/nscd status >/dev/null 2>&1";
 
 if ($nscd_status == 0) {
-   system "/etc/init.d/nscd restart > /dev/null 2>&1";
+  system "/etc/init.d/nscd restart > /dev/null 2>&1";
+}
+
+if (defined($Options{'P'})) {
+  exec "/usr/local/sbin/smbldap-passwd.pl $user"
 }
 
 
@@ -352,32 +406,32 @@ if ($nscd_status == 0) {
 
 =head1 NAME
 
-       smbldap-usermod.pl - Modify a user account
+smbldap-usermod.pl - Modify a user account
 
 =head1 SYNOPSIS
 
-       smbldap-usermod.pl [-c comment] [-d home_dir]
-               [-g initial_group] [-G group[,...]]
-               [-l login_name] [-p passwd]
-               [-s shell] [-u uid [ -o]] [-x]
-               [-A canchange] [-B mustchange] [-C smbhome]
-               [-D homedrive] [-E scriptpath] [-F profilepath]
-               [-H acctflags] login
+smbldap-usermod.pl [-c comment] [-d home_dir]
+  [-g initial_group] [-G group[,...]]
+  [-l login_name] [-p passwd]
+  [-s shell] [-u uid [ -o]] [-x]
+  [-A canchange] [-B mustchange] [-C smbhome]
+  [-D homedrive] [-E scriptpath] [-F profilepath]
+  [-H acctflags] login
 
 =head1 DESCRIPTION
 
-       The  smbldap-usermod.pl  command  modifies the system account files
-       to reflect the changes that are specified on the  command  line.
-       The  options  which apply to the usermod command are
+The  smbldap-usermod.pl  command  modifies the system account files
+  to reflect the changes that are specified on the  command  line.
+  The  options  which apply to the usermod command are
 
-       -c comment
-              The new value of the user's comment field (gecos).
+  -c comment
+  The new value of the user's comment field (gecos).
 
        -d home_dir
               The user's new login directory.
 
-       -g initial_group
-              The group name or number of the user's new initial login  group.
+  -g initial_group
+  The group name or number of the user's new initial login  group.
               The  group  name  must  exist.   A group number must refer to an
               already existing group.  The default group number is 1.
 
@@ -391,18 +445,18 @@ 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­
-              tory  name  should  probably be changed to reflect the new login
-              name.
+              Nothing else is changed.  In particular, the user's home  direc­
+  tory  name  should  probably be changed to reflect the new login
+  name.
 
-       -s shell
-              The name of the user's new login shell.  Setting this  field  to
+  -s shell
+  The name of the user's new login shell.  Setting this  field  to
               blank causes the system to select the default login shell.
 
        -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­
+  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­
               tory will have the file user ID  changed  automatically.   Files
               outside of the user's home directory must be altered manually.
 
index 555b35ffd817d2232628caea336d91c86234917e..c1e35a5be211986a93455b9c4f651b176f3d796e 100755 (executable)
@@ -1,5 +1,7 @@
 #!/usr/bin/perl -w
 
+# $Id: smbldap-usershow.pl,v 1.1.6.3 2003/12/04 21:59:19 jerry Exp $
+#
 #  This code was developped by IDEALX (http://IDEALX.org/) and
 #  contributors (their names can be found in the CONTRIBUTORS file).
 #
@@ -34,8 +36,8 @@ my %Options;
 my $ok = getopts('?', \%Options);
 
 if ( (!$ok) || (@ARGV < 1) || ($Options{'?'}) ) {
-       print "Usage: $0 [-?] username\n";
-       print "  -?     show this help message\n";
+  print "Usage: $0 [-?] username\n";
+  print "  -?  show this help message\n";
        exit (1);
 }
 
index c3d5c1732c731b2539a458af8a9502abac2e2c84..07961903ca980eeb7c498e9005fc38e4dc97c243 100644 (file)
@@ -2,6 +2,9 @@
 use strict;
 package smbldap_conf;
 
+# $Dource: $
+# $Id: smbldap_conf.pm,v 1.1.6.4 2003/12/04 21:59:19 jerry Exp $
+#
 # smbldap-tools.conf : Q & D configuration file for smbldap-tools
 
 #  This code was developped by IDEALX (http://IDEALX.org/) and
@@ -28,33 +31,33 @@ package smbldap_conf;
 #       . be the configuration file for all smbldap-tools scripts
 
 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 $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 $SID $hash_encrypt
-);
+                       $UID_START $GID_START $smbpasswd $slaveLDAP $masterLDAP
+                       $slavePort $masterPort $ldapSSL $slaveURI $masterURI $with_smbpasswd $mk_ntpasswd
+                       $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 $SID $hash_encrypt $_defaultMaxPasswordAge
+                  );
 
 use Exporter;
 $VERSION = 1.00;
 @ISA = qw(Exporter);
 
 @EXPORT = qw(
-$UID_START $GID_START $smbpasswd $slaveLDAP $masterLDAP
-$slavePort $masterPort $ldapSSL $slaveURI $masterURI $with_smbpasswd $mk_ntpasswd
-$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 $SID $hash_encrypt
-);
+                        $UID_START $GID_START $smbpasswd $slaveLDAP $masterLDAP
+                        $slavePort $masterPort $ldapSSL $slaveURI $masterURI $with_smbpasswd $mk_ntpasswd
+                        $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 $SID $hash_encrypt $_defaultMaxPasswordAge
+                       );
 
 
 ##############################################################################
@@ -101,7 +104,7 @@ $ldapSSL = "0";
 
 # LDAP Suffix
 # Ex: $suffix = "dc=IDEALX,dc=ORG";
-$suffix = "dc=IDEALX,dc=ORG";
+$suffix = "dc=IDEALX,dc=COM";
 
 
 # Where are stored Users
@@ -156,7 +159,7 @@ $masterPw = $bindpasswd;
 $_userLoginShell = q(_LOGINSHELL_);
 
 # Home directory prefix (without username)
-#Ex: $_userHomePrefix = q(/home/);
+# Ex: $_userHomePrefix = q(/home/);
 $_userHomePrefix = q(_HOMEPREFIX_);
 
 # Gecos
@@ -171,6 +174,11 @@ $_defaultComputerGid = 553;
 # Skel dir
 $_skeletonDir = q(/etc/skel);
 
+# Default password validation time (time in days) Comment the next line if
+# you don't want password to be enable for $_defaultMaxPasswordAge days (be
+# careful to the sambaPwdMustChange attribute's value)
+$_defaultMaxPasswordAge = 45;
+
 ##############################################################################
 #
 # SAMBA Configuration
@@ -180,11 +188,15 @@ $_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
+# Just comment this if you want to use the smb.conf 'logon home' directive
+# and/or desabling roaming profiles
 $_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
+# Just comment this if you want to use the smb.conf 'logon path' directive
+# and/or desabling roaming profiles
 $_userProfile = q(\\\\_PDCNAME_\\profiles\\);
 
 # The default Home Drive Letter mapping
@@ -194,7 +206,7 @@ $_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
+# $_userScript = q(startup.cmd); # make sure script file is edited under dos
 
 
 ##############################################################################
@@ -211,13 +223,13 @@ $mk_ntpasswd = "/usr/local/sbin/mkntpwd";
 
 # 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";
+$slaveURI = "ldap://$slaveLDAP:$slavePort";
+$masterURI = "ldap://$masterLDAP:$masterPort";
 
 $ldap_path = "/usr/bin";
 
 if ( $ldapSSL eq "0" ) {
-$ldap_opts = "-x";
+       $ldap_opts = "-x";
 } elsif ( $ldapSSL eq "1" ) {
        $ldap_opts = "-x -Z";
 } else {
index 8001442fe8ff6962381e6f5851832efbf34a5e2a..b7b134f3fd439fea7c3a88f1f5069c2aa97f8d43 100755 (executable)
@@ -4,6 +4,8 @@ package smbldap_tools;
 use smbldap_conf;
 use Net::LDAP;
 
+# $Id: smbldap_tools.pm,v 1.1.6.4 2003/12/04 21:59:20 jerry Exp $
+#
 #  This code was developped by IDEALX (http://IDEALX.org/) and
 #  contributors (their names can be found in the CONTRIBUTORS file).
 #
@@ -34,36 +36,40 @@ $VERSION = 1.00;
 @ISA = qw(Exporter);
 
 @EXPORT = qw(
-get_user_dn
-get_group_dn
+                        get_user_dn
+                        get_group_dn
                         is_group_member
-is_samba_user
+                        is_samba_user
                         is_unix_user
-is_user_valid
-get_dn_from_line
-add_posix_machine
-add_samba_machine
-add_samba_machine_mkntpwd
-group_add_user
-add_grouplist_user
-disable_user
-delete_user
-group_add
+                        is_user_valid
+                        does_sid_exist
+                        get_dn_from_line
+                        add_posix_machine
+                        add_samba_machine
+                        add_samba_machine_mkntpwd
+                        group_add_user
+                        add_grouplist_user
+                        disable_user
+                        delete_user
+                        group_add
                         group_del
-get_homedir
-read_user
+                        get_homedir
+                        read_user
                         read_user_entry
-read_group
-find_groups_of
-parse_group
-group_remove_member
-group_get_members
-do_ldapadd
-do_ldapmodify
-get_user_dn2
+                        read_group
+                        read_group_entry
+                        read_group_entry_gid
+                        find_groups_of
+                        parse_group
+                        group_remove_member
+                        group_get_members
+                        do_ldapadd
+                        do_ldapmodify
+                        get_user_dn2
                         connect_ldap_master
                         connect_ldap_slave
-);
+                        group_type_by_name
+                       );
 
 sub connect_ldap_master
   {
@@ -116,14 +122,14 @@ sub connect_ldap_slave
   }
 
 sub get_user_dn
-{
+  {
     my $user = shift;
     my $dn='';
     my $ldap_slave=connect_ldap_slave();
     my  $mesg = $ldap_slave->search (    base   => $suffix,
-                                  scope => $scope,
-                                  filter => "(&(objectclass=posixAccount)(uid=$user))"
-                              );
+                                                                                scope => $scope,
+                                                                                filter => "(&(objectclass=posixAccount)(uid=$user))"
+                                                                       );
     $mesg->code && die $mesg->error;
     foreach my $entry ($mesg->all_entries) {
          $dn= $entry->dn;
@@ -131,70 +137,70 @@ sub get_user_dn
     $ldap_slave->unbind;
     chomp($dn);
     if ($dn eq '') {
-       return undef;
+         return undef;
     }
     $dn="dn: ".$dn;
     return $dn;
-}
+  }
 
 
 sub get_user_dn2
-{
+  {
     my $user = shift;
     my $dn='';
     my $ldap_slave=connect_ldap_slave();
     my  $mesg = $ldap_slave->search (    base   => $suffix,
-                                  scope => $scope,
-                               filter => "(&(objectclass=posixAccount)(uid=$user))"
-                              );
+                                                                                scope => $scope,
+                                                                                filter => "(&(objectclass=posixAccount)(uid=$user))"
+                                                                       );
     $mesg->code && warn "failed to perform search; ", $mesg->error;
 
     foreach my $entry ($mesg->all_entries) {
-       $dn= $entry->dn;
+         $dn= $entry->dn;
     }
     $ldap_slave->unbind;
     chomp($dn);
     if ($dn eq '') {
-       return (1,undef);
+         return (1,undef);
     }
     $dn="dn: ".$dn;
     return (1,$dn);
-}
+  }
 
 
 sub get_group_dn
   {
-      my $group = shift;
-      my $dn='';
+       my $group = shift;
+       my $dn='';
        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) {
+                                                                                scope => $scope,
+                                                                                filter => "(&(objectclass=posixGroup)(|(cn=$group)(gidNumber=$group)))"
+                                                                       );
+       $mesg->code && die $mesg->error;
+       foreach my $entry ($mesg->all_entries) {
          $dn= $entry->dn;
        }
        $ldap_slave->unbind;
-      chomp($dn);
-      if ($dn eq '') {
+       chomp($dn);
+       if ($dn eq '') {
          return undef;
-      }
-      $dn="dn: ".$dn;
-      return $dn;
+       }
+       $dn="dn: ".$dn;
+       return $dn;
   }
 
 # return (success, dn)
 # bool = is_samba_user($username)
 sub is_samba_user
   {
-      my $user = shift;
+       my $user = shift;
        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;
+                                                                               scope => $scope,
+                                                                               filter => "(&(objectClass=sambaSamAccount)(uid=$user))"
+                                                                  );
+       $mesg->code && die $mesg->error;
        $ldap_slave->unbind;
        return ($mesg->count ne 0);
   }
@@ -217,52 +223,68 @@ 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",
+       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);
+       return ($mesg->count ne 0);
   }
 
+# all entries = does_sid_exist($sid,$scope)
+sub does_sid_exist
+  {
+       my $sid = shift;
+       my $dn_group=shift;
+       my $ldap_slave=connect_ldap_slave();
+       my $mesg = $ldap_slave->search (    base   => $dn_group,
+                                                                               scope => $scope,
+                                                                               filter => "(sambaSID=$sid)"
+                                                                               #filter => "(&(objectClass=sambaSAMAccount|objectClass=sambaGroupMapping)(sambaSID=$sid))"
+                                                                  );
+       $mesg->code && die $mesg->error;
+       $ldap_slave->unbind;
+       return ($mesg);
+  }
 
 # try to bind with user dn and password to validate current password
 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 );
+       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) {
-           $ldap->unbind;
-           return 1;
+         $ldap->unbind;
+         return 1;
        } else {
-           if($ldap->bind()) {
+         if ($ldap->bind()) {
                $ldap->unbind;
                return 0;
-           } else {
+         } else {
                print ("The LDAP directory is not available.\n Check the server, cables ...");
                $ldap->unbind;
                return 0;
          }
          die "Problem : contact your administrator";
        }
-}
+  }
+
 
 # dn = get_dn_from_line ($dn_line)
 # helper to get "a=b,c=d" from "dn: a=b,c=d"
 sub get_dn_from_line
   {
-      my $dn = shift;
-      $dn =~ s/^dn: //;
-      return $dn;
+       my $dn = shift;
+       $dn =~ s/^dn: //;
+       return $dn;
   }
 
+
 # success = add_posix_machine($user, $uid, $gid)
 sub add_posix_machine
   {
-      my ($user, $uid, $gid) = @_;
+       my ($user, $uid, $gid) = @_;
        # bind to a directory with dn and password
        my $ldap_master=connect_ldap_master();
        my $add = $ldap_master->add ( "uid=$user,$computersdn",
@@ -288,27 +310,27 @@ sub add_posix_machine
 
 # success = add_samba_machine($computername)
 sub add_samba_machine
-{
+  {
     my $user = shift;
     system "smbpasswd -a -m $user";
     return 1;
-}
+  }
 
 sub add_samba_machine_mkntpwd
   {
-      my ($user, $uid) = @_;
-      my $sambaSID = 2 * $uid + 1000;
-      my $name = $user;
-      $name =~ s/.$//s;
+       my ($user, $uid) = @_;
+       my $sambaSID = 2 * $uid + 1000;
+       my $name = $user;
+       $name =~ s/.$//s;
 
-      if ($mk_ntpasswd eq '') {
+       if ($mk_ntpasswd eq '') {
          print "Either set \$with_smbpasswd = 1 or specify \$mk_ntpasswd\n";
          return 0;
-      }
+       }
 
-      my $ntpwd = `$mk_ntpasswd '$name'`;
-      chomp(my $lmpassword = substr($ntpwd, 0, index($ntpwd, ':')));
-      chomp(my $ntpassword = substr($ntpwd, index($ntpwd, ':')+1));
+       my $ntpwd = `$mk_ntpasswd '$name'`;
+       chomp(my $lmpassword = substr($ntpwd, 0, index($ntpwd, ':')));
+       chomp(my $ntpassword = substr($ntpwd, index($ntpwd, ':')+1));
 
        my $ldap_master=connect_ldap_master();
        my $modify = $ldap_master->modify ( "uid=$user,$computersdn",
@@ -330,7 +352,7 @@ sub add_samba_machine_mkntpwd
        
        $modify->code && die "failed to add entry: ", $modify->error ;
 
-      return 1;
+       return 1;
        # take down the session
        $ldap_master->unbind;
 
@@ -339,16 +361,16 @@ sub add_samba_machine_mkntpwd
 
 sub group_add_user
   {
-      my ($group, $userid) = @_;
-      my $members='';
-      my $dn_line = get_group_dn($group);
+       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)) {
+       if (!defined($dn_line)) {
          return 1;
-      }
+       }
        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);
@@ -367,8 +389,8 @@ sub group_add_user
          $modify->code && die "failed to modify entry: ", $modify->error ;
          # take down session
          $ldap_master->unbind;
-           }
-      }
+       }
+  }
 
 sub group_del
   {
@@ -383,23 +405,23 @@ sub group_del
 
 sub add_grouplist_user
   {
-      my ($grouplist, $user) = @_;
-      my @array = split(/,/, $grouplist);
-      foreach my $group (@array) {
+       my ($grouplist, $user) = @_;
+       my @array = split(/,/, $grouplist);
+       foreach my $group (@array) {
          group_add_user($group, $user);
-      }
+       }
   }
 
 sub disable_user
   {
-      my $user = shift;
-      my $dn_line;
+       my $user = shift;
+       my $dn_line;
        my $dn = get_dn_from_line($dn_line);
-
-      if (!defined($dn_line = get_user_dn($user))) {
+       
+       if (!defined($dn_line = get_user_dn($user))) {
          print "$0: user $user doesn't exist\n";
          exit (10);
-      }
+       }
        my $ldap_master=connect_ldap_master();
        my $modify = $ldap_master->modify ( "$dn",
                                                                                changes => [
@@ -408,14 +430,14 @@ sub disable_user
                                                                          );
        $modify->code && die "failed to modify entry: ", $modify->error ;
 
-      if (is_samba_user($user)) {
+       if (is_samba_user($user)) {
          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;
   }
@@ -423,43 +445,43 @@ sub disable_user
 # delete_user($user)
 sub delete_user
   {
-      my $user = shift;
-      my $dn_line;
+       my $user = shift;
+       my $dn_line;
 
-      if (!defined($dn_line = get_user_dn($user))) {
+       if (!defined($dn_line = get_user_dn($user))) {
          print "$0: user $user doesn't exist\n";
          exit (10);
-      }
+       }
 
-      my $dn = get_dn_from_line($dn_line);
+       my $dn = get_dn_from_line($dn_line);
        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)
+# $gid = group_add($groupname, $group_gid, $force_using_existing_gid)
 sub group_add
   {
-      my ($gname, $gid, $force) = @_;
-      my $nscd_status = system "/etc/init.d/nscd status >/dev/null 2>&1";
-      if ($nscd_status == 0) {
+       my ($gname, $gid, $force) = @_;
+       my $nscd_status = system "/etc/init.d/nscd status >/dev/null 2>&1";
+       if ($nscd_status == 0) {
          system "/etc/init.d/nscd stop > /dev/null 2>&1";
-      }
-      if (!defined($gid)) {
+       }
+       if (!defined($gid)) {
          while (defined(getgrgid($GID_START))) {
-             $GID_START++;
+               $GID_START++;
          }
          $gid = $GID_START;
-      } else {
+       } else {
          if (!defined($force)) {
-             if (defined(getgrgid($gid))) {
-                 return 0;
-             }
+               if (defined(getgrgid($gid))) {
+                 return undef;
+               }
          }
-      }
-      if ($nscd_status == 0) {
+       }
+       if ($nscd_status == 0) {
          system "/etc/init.d/nscd start > /dev/null 2>&1";
-      }
+       }
        my $ldap_master=connect_ldap_master();
        my $modify = $ldap_master->add ( "cn=$gname,$groupsdn",
                                                                         attrs => [
@@ -472,67 +494,67 @@ sub group_add
        $modify->code && die "failed to add entry: ", $modify->error ;
        # take down session
        $ldap_master->unbind;
-      return 1;
+       return $gid;
   }
 
 # $homedir = get_homedir ($user)
 sub get_homedir
   {
-      my $user = shift;
-      my $homeDir='';
+       my $user = shift;
+       my $homeDir='';
        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){
+       $mesg->code && die $mesg->error;
+       foreach my $entry ($mesg->all_entries) {
          foreach my $attr ($entry->attributes) {
-               if ($attr=~/\bhomeDirectory\b/){
-                   foreach my $ent($entry->get_value($attr)) {
+               if ($attr=~/\bhomeDirectory\b/) {
+                 foreach my $ent ($entry->get_value($attr)) {
                        $homeDir.= $attr.": ".$ent."\n";
-                   }
+                 }
                }
-           }
-      }
+         }
+       }
        $ldap_slave->unbind;
-      chomp $homeDir;
-      if ($homeDir eq '') {
+       chomp $homeDir;
+       if ($homeDir eq '') {
          return undef;
-      }
-      $homeDir =~ s/^homeDirectory: //;
-      return $homeDir;
+       }
+       $homeDir =~ s/^homeDirectory: //;
+       return $homeDir;
   }
 
 # search for an user
 sub read_user
   {
-      my $user = shift;
-      my $lines ='';
+       my $user = shift;
+       my $lines ='';
        my $ldap_slave=connect_ldap_slave();
        my $mesg = $ldap_slave->search ( # perform a search
-                                base   => $suffix,
-                                scope => $scope,
-                                filter => "(&(objectclass=posixAccount)(uid=$user))"
-                               );
+                                                                       base   => $suffix,
+                                                                       scope => $scope,
+                                                                       filter => "(&(objectclass=posixAccount)(uid=$user))"
+                                                                  );
 
-      $mesg->code && die $mesg->error;
-      foreach my $entry ($mesg->all_entries) {
+       $mesg->code && die $mesg->error;
+       foreach my $entry ($mesg->all_entries) {
          $lines.= "dn: " . $entry->dn."\n";
          foreach my $attr ($entry->attributes) {
-             {
+               {
                  $lines.= $attr.": ".join(',', $entry->get_value($attr))."\n";
-             }
+               }
          }
-      }
+       }
        # take down session
        $ldap_slave->unbind;
-      chomp $lines;
-      if ($lines eq '') {
+       chomp $lines;
+       if ($lines eq '') {
          return undef;
-      }
-      return $lines;
+       }
+       return $lines;
   }
 
 # search for a user
@@ -556,86 +578,124 @@ sub read_user_entry
 # search for a group
 sub read_group
   {
-      my $user = shift;
-      my $lines ='';
+       my $user = shift;
+       my $lines ='';
        my $ldap_slave=connect_ldap_slave();
        my  $mesg = $ldap_slave->search ( # perform a search
-                                base   => $groupsdn,
-                                scope => $scope,
-                                filter => "(&(objectclass=posixGroup)(cn=$user))"
-                               );
+                                                                        base   => $groupsdn,
+                                                                        scope => $scope,
+                                                                        filter => "(&(objectclass=posixGroup)(cn=$user))"
+                                                                       );
 
-      $mesg->code && die $mesg->error;
-      foreach my $entry ($mesg->all_entries) {
+       $mesg->code && die $mesg->error;
+       foreach my $entry ($mesg->all_entries) {
          $lines.= "dn: " . $entry->dn."\n";
          foreach my $attr ($entry->attributes) {
-             {
+               {
                  $lines.= $attr.": ".join(',', $entry->get_value($attr))."\n";
-             }
+               }
          }
-      }
+       }
        # take down session
        $ldap_slave->unbind;
-      chomp $lines;
-      if ($lines eq '') {
+       chomp $lines;
+       if ($lines eq '') {
          return undef;
-      }
-      return $lines;
+       }
+       return $lines;
   }
 
 # find groups of a given user
 ##### MODIFIE ########
 sub find_groups_of
   {
-      my $user = shift;
-      my $lines ='';
+       my $user = shift;
+       my $lines ='';
        my $ldap_slave=connect_ldap_slave;
        my  $mesg = $ldap_slave->search ( # perform a search
-                                base   => $groupsdn,
-                                scope => $scope,
-                                filter => "(&(objectclass=posixGroup)(memberuid=$user))"
-                               );
-      $mesg->code && die $mesg->error;
-      foreach my $entry ($mesg->all_entries) {
+                                                                        base   => $groupsdn,
+                                                                        scope => $scope,
+                                                                        filter => "(&(objectclass=posixGroup)(memberuid=$user))"
+                                                                       );
+       $mesg->code && die $mesg->error;
+       foreach my $entry ($mesg->all_entries) {
          $lines.= "dn: ".$entry->dn."\n";
-      }
+       }
        $ldap_slave->unbind;
-      chomp($lines);
+       chomp($lines);
        if ($lines eq '') {
          return undef;
        }
-      return $lines;
+       return $lines;
+  }
+
+sub read_group_entry {
+  my $group = shift;
+  my $entry;
+  my %res;
+  my $ldap_slave=connect_ldap_slave();
+  my  $mesg = $ldap_slave->search ( # perform a search
+                                                                  base   => $groupsdn,
+                                                                  scope => $scope,
+                                                                  filter => "(&(objectclass=posixGroup)(cn=$group))"
+                                                                 );
+
+  $mesg->code && die $mesg->error;
+  my $nb=$mesg->count;
+  if ($nb > 1) {
+    print "Error: $nb groups exist \"cn=$group\"\n";
+    foreach $entry ($mesg->all_entries) { my $dn=$entry->dn; print "  $dn\n"; }
+    exit 11;
+  } else {
+    $entry = $mesg->shift_entry();
   }
+  return $entry;
+}
+
+sub read_group_entry_gid {
+  my $group = shift;
+  my %res;
+  my $ldap_slave=connect_ldap_slave();
+  my  $mesg = $ldap_slave->search ( # perform a search
+                                  base   => $groupsdn,
+                                  scope => $scope,
+                                  filter => "(&(objectclass=posixGroup)(gidNumber=$group))"
+                                 );
+
+  $mesg->code && die $mesg->error;
+  my $entry = $mesg->shift_entry();
+  return $entry;
+}
 
 # return the gidnumber for a group given as name or gid
 # -1 : bad group name
 # -2 : bad gidnumber
 sub parse_group
   {
-      my $userGidNumber = shift;
-      if ($userGidNumber =~ /[^\d]/ ) {
+       my $userGidNumber = shift;
+       if ($userGidNumber =~ /[^\d]/ ) {
          my $gname = $userGidNumber;
          my $gidnum = getgrnam($gname);
          if ($gidnum !~ /\d+/) {
-             return -1;
+               return -1;
          } else {
-             $userGidNumber = $gidnum;
+               $userGidNumber = $gidnum;
          }
-      } elsif (!defined(getgrgid($userGidNumber))) {
+       } elsif (!defined(getgrgid($userGidNumber))) {
          return -2;
-      }
-      return $userGidNumber;
+       }
+       return $userGidNumber;
   }
 
 # remove $user from $group
 sub group_remove_member
   {
-      my ($group, $user) = @_;
-      my $members='';
-      my $grp_line = get_group_dn($group);
-      if (!defined($grp_line)) {
+       my ($group, $user) = @_;
+       my $members='';
+       my $grp_line = get_group_dn($group);
+       if (!defined($grp_line)) {
          return 0;
-      }
+       }
        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);
@@ -646,40 +706,40 @@ sub group_remove_member
                                                                                  changes => [
                                                                                                          delete => [memberUid => ["$user"]]
                                                                                                         ]
-                               );
+                                                                               );
          $modify->code && die "failed to delete entry: ", $modify->error ;
          $ldap_master->unbind;
-               }
-      return 1;
+       }
+       return 1;
   }
 
 sub group_get_members
   {
-      my ($group) = @_;
-      my $members;
-      my @resultat;
-      my $grp_line = get_group_dn($group);
+       my ($group) = @_;
+       my $members;
+       my @resultat;
+       my $grp_line = get_group_dn($group);
        if (!defined($grp_line)) {
          return 0;
        }
 
-      my $ldap = Net::LDAP->new($slaveLDAP) or die "erreur LDAP";
-      $ldap->bind ;
+       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))"
-                               );
-      $mesg->code && die $mesg->error;
-      foreach my $entry ($mesg->all_entries){
-         foreach my $attr ($entry->attributes){
-             if ($attr=~/\bmemberUid\b/){
+                                                          scope => $scope,
+                                                          filter => "(&(objectclass=posixgroup)(cn=$group))"
+                                                         );
+       $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)) {
                        push (@resultat,$ent);
-             }
+                 }
+               }
          }
-      }
-}
+       }
        return @resultat;
   }
 
@@ -697,5 +757,17 @@ EOF
       return $rc;
   }
 
+sub group_type_by_name {
+  my $type_name = shift;
+  my %groupmap = (
+    'domain' => 2,
+    'local' => 4,
+    'builtin' => 5
+  );
+  return $groupmap{$type_name};
+}
+
+
+
 1;