syncing examples
authorGerald Carter <jerry@samba.org>
Tue, 9 Sep 2003 03:51:06 +0000 (03:51 +0000)
committerGerald Carter <jerry@samba.org>
Tue, 9 Sep 2003 03:51:06 +0000 (03:51 +0000)
52 files changed:
examples/LDAP/README
examples/LDAP/convertSambaAccount
examples/LDAP/ldapsync.pl
examples/LDAP/samba-nds.schema [new file with mode: 0644]
examples/LDAP/samba-schema-netscapeds4.x
examples/LDAP/samba-schema-netscapeds5.x
examples/LDAP/samba.schema
examples/LDAP/smbldap-tools/AUTHORS [new file with mode: 0644]
examples/LDAP/smbldap-tools/CONTRIBUTORS [new file with mode: 0644]
examples/LDAP/smbldap-tools/COPYING [new file with mode: 0644]
examples/LDAP/smbldap-tools/ChangeLog [new file with mode: 0644]
examples/LDAP/smbldap-tools/FILES [new file with mode: 0644]
examples/LDAP/smbldap-tools/INFRASTRUCTURE [new file with mode: 0644]
examples/LDAP/smbldap-tools/INSTALL [new file with mode: 0644]
examples/LDAP/smbldap-tools/Makefile [new file with mode: 0644]
examples/LDAP/smbldap-tools/NEWS [new file with mode: 0644]
examples/LDAP/smbldap-tools/README [new file with mode: 0644]
examples/LDAP/smbldap-tools/TODO [new file with mode: 0644]
examples/LDAP/smbldap-tools/cgi/README [new file with mode: 0644]
examples/LDAP/smbldap-tools/cgi/ldappass.cgi [new file with mode: 0755]
examples/LDAP/smbldap-tools/mkntpwd/Makefile [new file with mode: 0644]
examples/LDAP/smbldap-tools/mkntpwd/getopt.c [new file with mode: 0644]
examples/LDAP/smbldap-tools/mkntpwd/getopt.h [new file with mode: 0644]
examples/LDAP/smbldap-tools/mkntpwd/md4.c [new file with mode: 0644]
examples/LDAP/smbldap-tools/mkntpwd/mkntpwd.c [new file with mode: 0644]
examples/LDAP/smbldap-tools/mkntpwd/mkntpwd.h [new file with mode: 0644]
examples/LDAP/smbldap-tools/mkntpwd/smbdes.c [new file with mode: 0644]
examples/LDAP/smbldap-tools/smbldap-groupadd.pl [new file with mode: 0755]
examples/LDAP/smbldap-tools/smbldap-groupdel.pl [new file with mode: 0755]
examples/LDAP/smbldap-tools/smbldap-groupmod.pl [new file with mode: 0755]
examples/LDAP/smbldap-tools/smbldap-groupshow.pl [new file with mode: 0755]
examples/LDAP/smbldap-tools/smbldap-migrate-accounts.pl [new file with mode: 0755]
examples/LDAP/smbldap-tools/smbldap-migrate-groups.pl [new file with mode: 0644]
examples/LDAP/smbldap-tools/smbldap-passwd.pl [new file with mode: 0755]
examples/LDAP/smbldap-tools/smbldap-populate.pl [new file with mode: 0755]
examples/LDAP/smbldap-tools/smbldap-tools.spec [new file with mode: 0755]
examples/LDAP/smbldap-tools/smbldap-useradd.pl [new file with mode: 0755]
examples/LDAP/smbldap-tools/smbldap-userdel.pl [new file with mode: 0755]
examples/LDAP/smbldap-tools/smbldap-usermod.pl [new file with mode: 0755]
examples/LDAP/smbldap-tools/smbldap-usershow.pl [new file with mode: 0755]
examples/LDAP/smbldap-tools/smbldap_conf.pm [new file with mode: 0644]
examples/LDAP/smbldap-tools/smbldap_tools.pm [new file with mode: 0755]
examples/VFS/shadow_copy_test.c [new file with mode: 0644]
examples/VFS/skel_opaque.c
examples/VFS/skel_transparent.c
examples/printing/prtpub.c
examples/sam/Makefile.in [deleted file]
examples/sam/README [deleted file]
examples/sam/sam_skel.c [deleted file]
examples/smb.conf.default
examples/wins_hook/README [new file with mode: 0644]
examples/wins_hook/dns_update [new file with mode: 0644]

index c7ff16ad083629c91dda1fe813cc8fc99205f92c..2f4b4f2a056d30877931973b4e9470e170d488fb 100644 (file)
@@ -1,26 +1,11 @@
 !==
-!== README File for storing smbpasswd in LDAP
+!== README File for various LDAP examples
 !==
 !== written by Gerald Carter <jerry@samba.org>
 !==
 
-This is a quick and dirty means of converting smbpasswd entries
-to sambaAccount entriues in an LDAP directory.
-
-
-Pre-requisites for import_smbpasswd.pl & export_smbpasswd.pl
---------------------------------------------------------------
-These two scripts are modified versions of 
-[import|export]_smbpasswd.pl rewritten to use the Net::LDAP
-perl module available from 
-
-       http://perl-ldap.sourceforge.net
-
-
-
-
-OpenLDAP 2.0.x
---------------
+OpenLDAP 2.x
+------------
 
 A sample schema file (samba.schema) has been included for use
 with OpenLDAP 2.0.x.  The OIDs used in this file are owned by
@@ -50,39 +35,31 @@ nis.schema and cosine.schema in your slapd.conf file.
 You must restart the LDAP server for these new included schema files 
 to become active.
 
+SunOne/Netscape DS
+------------------
 
-import_smbpasswd.pl
-----------------------
-
-Make sure you customize the local site variable in the perl script
-(i.e. ldapserver, rootdn, rootpw, etc...).  The script reads from
-standard input and requires that user entries already exist
-in your directories containing the 'objectclass: posixAccount'
-value pair.  For more information on this object and related schema,
-refer to RFC2307 and http://www.padl.com/software.html).
+The schema file has not been updated for the sambaSamAccount
+objectclass.
 
-The following will import an smbpasswd file into an LDAP directory
 
-       $ cat smbpasswd | import_smbpasswd.pl
+Novell eDirectory
+-----------------
 
+The schema file has not been updated for the sambaSamAccount
+objectclass.
 
-export_smbpasswd.pl
-----------------------
 
-Make sure you customize the local site variable in the perl script
-(i.e. ldapserver, rootdn, rootpw, etc...).  You can then generate
-an smbpasswd file by executing
-
-       $ export_smbpasswd.pl > smbpasswd
-
-NOTE: Server side (or client side) search limites may prevent
-all users from being listed.  Check you directory server documentation
-for details.
+smbldap-tools/
+--------------
 
+This is a collection of perl scripts (wrapped around the standard 
+OpenLDAP command line tools) for managing Samba and posix accounts
+in an LDAP directory.  See the README file included with the scripts
+for more details.
 
 
-ldapsync.pl & ldapchgpasswd.pl
-------------------------------
+ldapsync.pl 
+-----------
 For more information on these scripts, see
 
        http://www.mami.net/univr/tng-ldap/howto/
index 223c43eadabc35afba84895cf0476bbf534b497f..d2770c75a687592be7bb1442c1d3e9f544300fe2 100755 (executable)
@@ -5,24 +5,52 @@
 ##
 ## Copyright Gerald (Jerry) Carter     2003
 ##
-## Usage: convertSambaAccount <Domain SID> <input ldif> <output ldif>
+## Usage: convertSambaAccount --sid=<Domain SID> \
+##       --input=<input ldif> --output=<output ldif> \
+##       --changetype=[modify|add]
 ##
 
 
 use strict;
 use Net::LDAP::LDIF;
+use Getopt::Long;
 
-my ( $domain, $domsid );
+
+##############################################################################
+## local variables
+
+my ( $domain, $domsid, $changetype );
 my ( $ldif, $ldif2 );
 my ( $entry, @objclasses, $obj );
 my ( $is_samba_account, $is_samba_group );
 my ( %attr_map, %group_attr_map, $key );
+my ( @dels, $deletion, @adds, $addition );
+my ( $result, %options );
 
-if ( $#ARGV != 2 ) {
-       print "Usage: convertSambaAccount domain_sid input_ldif output_ldif\n";
-       exit 1;
+
+##############################################################################
+## Print the option usage
+
+sub usage {
+
+       print "convertSambaAccount <options>\n";
+       print "Options:\n";
+       print "  --help         print this help message\n";
+       print "  --input        input LDIF filename\n";
+       print "  --output       output LDIF filename\n";
+       print "  --sid          domain SID\n";
+       print "  --changetype   [modify|add] (default is 'add')\n";
 }
 
+
+##############################################################################
+##                               MAIN DRIVER                                ##
+##############################################################################
+
+##
+## hashes to map old attribute names to new ones 
+##
+
 %attr_map = ( 
        lmPassword      => 'sambaLMPassword',
        ntPassword      => 'sambaNTPassword',
@@ -46,12 +74,60 @@ if ( $#ARGV != 2 ) {
        ntGroupType     => 'sambaGroupType',
 );
 
-$domsid = $ARGV[0];
+##
+## process command line args
+##
+
+$result = GetOptions(\%options,
+                       "help", 
+                       "input=s", 
+                       "output=s", 
+                       "sid=s",
+                       "changetype=s");
+
+if (!$result && ($#ARGV != -1)) {
+       usage();
+       exit 1;
+}
+
+if ( defined($options{'help'}) ) {
+       usage();
+       exit 0;
+}
+
+
+if ( !defined( $options{'sid'} ) ) {
+       print "You must provide a domain sid\n";
+       exit 1;
+}
+
+$domsid = $options{'sid'};
 
-$ldif = Net::LDAP::LDIF->new ($ARGV[1], "r")
-       or die $!;
-$ldif2 = Net::LDAP::LDIF->new ($ARGV[2], "w")
-       or die $!;
+$changetype = 'add';
+if ( defined( $options{'changetype'} ) ) {
+       $changetype = $options{'changetype'};
+}
+
+##
+## open files
+##
+
+$ldif = Net::LDAP::LDIF->new ($options{'input'}, "r") or die $!;
+
+if ( "$changetype" eq "add" ) {
+       $ldif2 = Net::LDAP::LDIF->new ($options{'output'}, "w") or die $!;
+}
+elsif ( "$changetype" eq "modify" ) {
+       open( OUTPUT, ">$options{'output'}" ) or die $!;
+}
+else {
+       print "Bad changetype!\n";
+       exit 1;
+}
+
+##
+## process LDIF 
+##
 
 while ( !$ldif->eof ) {
        undef ( $entry );
@@ -71,6 +147,8 @@ while ( !$ldif->eof ) {
        @objclasses = $entry->get_value( "objectClass" );
        undef ( $is_samba_account );
        undef ( $is_samba_group );
+       @adds = ();
+       @dels = ();
        foreach $obj ( @objclasses ) {
                if ( "$obj" eq "sambaAccount" ) {
                        $is_samba_account = 1;
@@ -84,6 +162,8 @@ while ( !$ldif->eof ) {
                ## start editing the sambaAccount
                ##
 
+               @dels = ( 'objectclass: sambaAccount', 'rid' );
+               @adds = ('objectclass: sambaSamAccount', "sambaSID: " .  ${domsid} . "-" . ${entry}->get_value( 'rid' ) );
                $entry->delete( 'objectclass' => [ 'sambaAccount' ] );
                $entry->add( 'objectclass' => 'sambaSamAccount' );
 
@@ -91,6 +171,8 @@ while ( !$ldif->eof ) {
                $entry->delete( 'rid' );
        
                if ( $entry->get_value( "primaryGroupID" ) ) {
+                       push @adds, "sambaPrimaryGroupSID: " . $domsid."-".$entry->get_value( "primaryGroupID" );
+                       push @dels, "primaryGroupID";
                        $entry->add( 'sambaPrimaryGroupSID' => $domsid."-".$entry->get_value( "primaryGroupID" ) );
                        $entry->delete( 'primaryGroupID' );
                }
@@ -98,6 +180,8 @@ while ( !$ldif->eof ) {
 
                foreach $key ( keys %attr_map ) {
                        if ( defined($entry->get_value($key)) ) {
+                               push @adds, "$attr_map{$key}: " . $entry->get_value($key);
+                               push @dels, "$key";
                                $entry->add( $attr_map{$key} => $entry->get_value($key) );
                                $entry->delete( $key );
                        }
@@ -105,13 +189,39 @@ while ( !$ldif->eof ) {
        } elsif ( defined ( $is_samba_group ) ) {
                foreach $key ( keys %group_attr_map ) {
                        if ( defined($entry->get_value($key)) ) {
+                               push @adds, "$group_attr_map{$key}: " . $entry->get_value($key);
+                               push @dels, "$key";
                                $entry->add( $group_attr_map{$key} => $entry->get_value($key) );
                                $entry->delete( $key );
                        }
                }
        }
        
-       $ldif2->write_entry( $entry );
+       ## see if we should write full entries or only the changes
+       
+       if ( "$changetype" eq "add" ) {
+               $ldif2->write_entry( $entry );
+       }
+       else {
+               if ( defined ( $is_samba_account ) || defined ( $is_samba_group ) ){
+                       if ( @adds + @dels > 0 ) {
+                               print OUTPUT "dn: " . $entry->dn . "\n";
+                               foreach $addition (@adds) {
+                                       $addition =~ /(^\w+):/;
+                                       print OUTPUT "add: " . $1  . "\n";
+                                       print OUTPUT "$addition\n-\n";
+                               }
+                               foreach $deletion (@dels) {
+                                       if ( $deletion =~ /^(\w+):\s(.*)/ ) {
+                                               print OUTPUT "delete: $1\n$1: $2\n-\n";
+                                       } else {
+                                               print OUTPUT "delete: $deletion\n-\n"
+                                       }
+                               }
+                               print OUTPUT "\n"
+                       }
+               }
+       }
 }
 
 
index fecc594c2d23e24bd548d18baf19d791e75b4f0e..c112bcc34cb7a1585b4ea3c2636b92c92bada125 100644 (file)
@@ -8,6 +8,11 @@
 #              modified to change lmpassword and ntpassword for samba
 # 05/01/2001   mami@arena.sci.univr.it
 #              modified for being also a /bin/passwd replacement
+#
+# ACHTUNG!!    For servers that support the LDAP Modify password 
+#              extended op (e.g. OpenLDAP), see the "ldap password 
+#              sync" option in smb.conf(5).  
+#
 
 $basedn = "ou=Students,dc=univr, dc=it";
 $binddn = "uid=root,dc=univr,dc=it";
diff --git a/examples/LDAP/samba-nds.schema b/examples/LDAP/samba-nds.schema
new file mode 100644 (file)
index 0000000..8369c84
--- /dev/null
@@ -0,0 +1,151 @@
+##
+## Schema file for Novell eDirectory 8.7.x by Uli Iske
+## Schema for storing Samba's smbpasswd file in LDAP
+## OIDs are owned by the Samba Team
+##
+#######################################################################
+##                Attributes used by Samba 3.0 schema                ##
+#######################################################################
+
+dn: cn=schema
+changetype: modify
+add: attributetypes
+attributeTypes: ( 1.3.6.1.4.1.7165.2.1.24 NAME 'sambaLMPassword' DESC 'LanManager Password' SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE )
+
+dn: cn=schema
+changetype: modify
+add: attributetypes
+attributeTypes: ( 1.3.6.1.4.1.7165.2.1.25 NAME 'sambaNTPassword' DESC 'MD4 hash of the unicode password' SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE )
+
+dn: cn=schema
+changetype: modify
+add: attributetypes
+attributeTypes: ( 1.3.6.1.4.1.7165.2.1.26 NAME 'sambaAcctFlags' DESC 'Account Flags' SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE )
+
+dn: cn=schema
+changetype: modify
+add: attributetypes
+attributeTypes: ( 1.3.6.1.4.1.7165.2.1.27 NAME 'sambaPwdLastSet' DESC 'Timestamp of the last password update' SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 SINGLE-VALUE )
+
+dn: cn=schema
+changetype: modify
+add: attributetypes
+attributeTypes: ( 1.3.6.1.4.1.7165.2.1.28 NAME 'sambaPwdCanChange' DESC 'Timestamp of when the user is allowed to update the password' SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 SINGLE-VALUE )
+
+dn: cn=schema
+changetype: modify
+add: attributetypes
+attributeTypes: ( 1.3.6.1.4.1.7165.2.1.29 NAME 'sambaPwdMustChange' DESC 'Timestamp of when the password will expire' SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 SINGLE-VALUE )
+
+dn: cn=schema
+changetype: modify
+add: attributetypes
+attributeTypes: ( 1.3.6.1.4.1.7165.2.1.30 NAME 'sambaLogonTime' DESC 'Timestamp of last logon' SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 SINGLE-VALUE )
+
+dn: cn=schema
+changetype: modify
+add: attributetypes
+attributeTypes: ( 1.3.6.1.4.1.7165.2.1.31 NAME 'sambaLogoffTime' DESC 'Timestamp of last logoff' SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 SINGLE-VALUE )
+
+dn: cn=schema
+changetype: modify
+add: attributetypes
+attributeTypes: ( 1.3.6.1.4.1.7165.2.1.32 NAME 'sambaKickoffTime' DESC 'Timestamp of when the user will be logged off automatically' SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 SINGLE-VALUE )
+
+dn: cn=schema
+changetype: modify
+add: attributetypes
+attributeTypes: ( 1.3.6.1.4.1.7165.2.1.33 NAME 'sambaHomeDrive' DESC 'Driver letter of home directory mapping' SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE )
+
+dn: cn=schema
+changetype: modify
+add: attributetypes
+attributeTypes: ( 1.3.6.1.4.1.7165.2.1.34 NAME 'sambaLogonScript' DESC 'Logon script path' SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 SINGLE-VALUE )
+
+dn: cn=schema
+changetype: modify
+add: attributetypes
+attributeTypes: ( 1.3.6.1.4.1.7165.2.1.35 NAME 'sambaProfilePath' DESC 'Roaming profile path' SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 SINGLE-VALUE )
+
+dn: cn=schema
+changetype: modify
+add: attributetypes
+attributeTypes: ( 1.3.6.1.4.1.7165.2.1.36 NAME 'sambaUserWorkstations' DESC 'List of user workstations the user is allowed to logon to' SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 SINGLE-VALUE )
+
+dn: cn=schema
+changetype: modify
+add: attributetypes
+attributeTypes: ( 1.3.6.1.4.1.7165.2.1.37 NAME 'sambaHomePath' DESC 'Home directory UNC path' SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )
+
+dn: cn=schema
+changetype: modify
+add: attributetypes
+attributeTypes: ( 1.3.6.1.4.1.7165.2.1.38 NAME 'sambaDomainName' DESC 'Windows NT domain to which the user belongs' SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )
+
+dn: cn=schema
+changetype: modify
+add: attributetypes
+attributeTypes: ( 1.3.6.1.4.1.7165.2.1.20 NAME 'sambaSID' DESC 'Security ID' SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE )
+
+dn: cn=schema
+changetype: modify
+add: attributetypes
+attributeTypes: ( 1.3.6.1.4.1.7165.2.1.23 NAME 'sambaPrimaryGroupSID' DESC 'Primary Group Security ID' SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE )
+
+dn: cn=schema
+changetype: modify
+add: attributetypes
+attributeTypes: ( 1.3.6.1.4.1.7165.2.1.19 NAME 'sambaGroupType' DESC 'NT Group Type' SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 SINGLE-VALUE )
+
+dn: cn=schema
+changetype: modify
+add: attributetypes
+attributeTypes: ( 1.3.6.1.4.1.7165.2.1.21 NAME 'sambaNextUserRid' DESC 'Next NT rid to give our for users' SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 SINGLE-VALUE )
+
+dn: cn=schema
+changetype: modify
+add: attributetypes
+attributeTypes: ( 1.3.6.1.4.1.7165.2.1.22 NAME 'sambaNextGroupRid' DESC 'Next NT rid to give out for groups' SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 SINGLE-VALUE )
+
+dn: cn=schema
+changetype: modify
+add: attributetypes
+attributeTypes: ( 1.3.6.1.4.1.7165.2.1.39 NAME 'sambaNextRid' DESC 'Next NT rid to give out for anything' SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 SINGLE-VALUE )
+
+dn: cn=schema
+changetype: modify
+add: attributetypes
+attributeTypes: ( 1.3.6.1.4.1.7165.2.1.40 NAME 'sambaAlgorithmicRidBase' DESC 'Base at which the samba RID generation algorithm should operate' SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 SINGLE-VALUE )
+
+#######################################################################
+##              objectClasses used by Samba 3.0 schema               ##
+#######################################################################
+dn: cn=schema
+changetype: modify
+add: objectClasses
+objectClasses: ( 1.3.6.1.4.1.7165.2.2.6 NAME 'sambaSamAccount' DESC 'Samba 3.0 Auxilary SAM Account' SUP top AUXILIARY MUST ( uid $ sambaSID ) MAY  ( cn $ sambaLMPassword $ sambaNTPassword $ sambaPwdLastSet $sambaLogonTime $ sambaLogoffTime $sambaKickoffTime $sambaPwdCanChange $ sambaPwdMustChange $ sambaAcctFlags $displayName $ sambaHomePath $ sambaHomeDrive $ sambaLogonScript $sambaProfilePath $ description $ sambaUserWorkstations $sambaPrimaryGroupSID $ sambaDomainName ))
+
+dn: cn=schema
+changetype: modify
+add: objectClasses
+objectClasses: ( 1.3.6.1.4.1.7165.2.2.4 NAME 'sambaGroupMapping' DESC 'Samba Group Mapping' SUP top AUXILIARY MUST ( gidNumber $ sambaSID $ sambaGroupType ) MAY  ( displayName $ description ))
+
+dn: cn=schema
+changetype: modify
+add: objectClasses
+objectClasses: ( 1.3.6.1.4.1.7165.2.2.5 NAME 'sambaDomain' DESC 'Samba Domain Information' SUP top STRUCTURAL MUST ( sambaDomainName $sambaSID ) MAY ( sambaNextRid $ sambaNextGroupRid $ sambaNextUserRid $sambaAlgorithmicRidBase ) )
+
+dn: cn=schema
+changetype: modify
+add: objectClasses
+objectClasses: ( 1.3.6.1.4.1.7165.1.2.2.7 NAME 'sambaUnixIdPool' DESC 'Pool for allocating UNIX uids/gids' SUP top AUXILIARY MUST ( uidNumber $ gidNumber ) )
+
+dn: cn=schema
+changetype: modify
+add: objectClasses
+objectClasses: ( 1.3.6.1.4.1.7165.1.2.2.8 NAME 'sambaIdmapEntry' DESC 'Mapping from a SID to an ID' SUP top AUXILIARY MUST ( sambaSID ) MAY ( uidNumber $ gidNumber ) )
+
+dn: cn=schema
+changetype: modify
+add: objectClasses
+objectClasses: ( 1.3.6.1.4.1.7165.1.2.2.9 NAME 'sambaSidEntry' DESC 'Structural Class for a SID' SUP top STRUCTURAL MUST ( sambaSID ) )
index c5a11b8b66c3a46bfe54b86aff9ed5d3b377f5e5..9f409664187a3583a31a537f396b582d85ffff09 100644 (file)
 #
-# LDAP Schema file for SAMBA attribute storage 
-# This file is suitable for usage with Netscape Directory Server 4.1x
-# Adapted by Scott Lawson with help from Ron Creamer
-#
+# LDAP Schema file for SAMBA 3.0 attribute storage
+# For Netscape Directory Server 4.1x
+# Prepared by Osman Demirhan
+
+attribute      sambaLMPassword                 1.3.6.1.4.1.7165.2.1.24         cis single
+attribute      sambaNTPassword                 1.3.6.1.4.1.7165.2.1.25         cis single
+attribute      sambaAcctFlags                  1.3.6.1.4.1.7165.2.1.26         cis single
+attribute      sambaPwdLastSet                 1.3.6.1.4.1.7165.2.1.27         int single
+attribute      sambaPwdCanChange               1.3.6.1.4.1.7165.2.1.28         int single
+attribute      sambaPwdMustChange              1.3.6.1.4.1.7165.2.1.29         int single
+attribute      sambaLogonTime                  1.3.6.1.4.1.7165.2.1.30         int single
+attribute      sambaLogoffTime                 1.3.6.1.4.1.7165.2.1.31         int single
+attribute      sambaKickoffTime                1.3.6.1.4.1.7165.2.1.32         int single
+attribute      sambaHomeDrive                  1.3.6.1.4.1.7165.2.1.33         cis single
+attribute      sambaLogonScript                1.3.6.1.4.1.7165.2.1.34         cis single
+attribute      sambaProfilePath                1.3.6.1.4.1.7165.2.1.35         cis single
+attribute      sambaUserWorkstations   1.3.6.1.4.1.7165.2.1.36         cis single
+attribute      sambaHomePath                   1.3.6.1.4.1.7165.2.1.37         cis single
+attribute      sambaDomainName                 1.3.6.1.4.1.7165.2.1.38         cis single
+attribute      sambaSID                                1.3.6.1.4.1.7165.2.1.20         cis single
+attribute      sambaPrimaryGroupSID    1.3.6.1.4.1.7165.2.1.23         cis single
+attribute      sambaGroupType                  1.3.6.1.4.1.7165.2.1.19         int single
+attribute      sambaNextUserRid                1.3.6.1.4.1.7165.2.1.21         int single
+attribute      sambaNextGroupRid               1.3.6.1.4.1.7165.2.1.22         int single
+attribute      sambaNextRid                    1.3.6.1.4.1.7165.2.1.39         int single
+attribute      sambaAlgorithmicRidBase 1.3.6.1.4.1.7165.2.1.40         int single
+
+objectclass sambaSamAccount
+               oid
+                               1.3.6.1.4.1.7165.2.2.6
+               superior
+                               top
+               requires
+                               objectClass,
+                               uid,
+                               sambaSID
+               allows
+                               cn,
+                               sambaLMPassword,
+                               sambaNTPassword,
+                               sambaPwdLastSet,
+                               sambaLogonTime,
+                               sambaLogoffTime,
+                               sambaKickoffTime,
+                               sambaPwdCanChange,
+                               sambaPwdMustChange,
+                               sambaAcctFlags,
+                               displayName,
+                               sambaHomePath,
+                               sambaHomeDrive,
+                               sambaLogonScript,
+                               sambaProfilePath,
+                               description,
+                               sambaUserWorkstations,
+                               sambaPrimaryGroupSID,
+                               sambaDomainName
+
+objectclass sambaGroupMapping
+               oid
+                               1.3.6.1.4.1.7165.2.2.4
+               superior
+                               top
+               requires
+                               gidNumber,
+                               sambaSID,
+                               sambaGroupType
+               allows
+                               displayName,
+                               description
+
+objectclass sambaDomain
+               oid
+                               1.3.6.1.4.1.7165.2.2.5
+               superior
+                               top
+               requires
+                               sambaDomainName,
+                               sambaSID
+               allows
+                               sambaNextRid,
+                               sambaNextGroupRid,
+                               sambaNextUserRid,
+                               sambaAlgorithmicRidBase
 
-attribute       lmPassword              1.3.6.1.4.1.7165.2.1.1  cis single
-attribute       ntPassword              1.3.6.1.4.1.7165.2.1.2  cis single
-attribute       acctFlags               1.3.6.1.4.1.7165.2.1.4  cis single
-attribute       pwdLastSet              1.3.6.1.4.1.7165.2.1.3  int single
-attribute       logonTime               1.3.6.1.4.1.7165.2.1.5  int single
-attribute       logoffTime              1.3.6.1.4.1.7165.2.1.6  int single
-attribute       kickoffTime             1.3.6.1.4.1.7165.2.1.7  int single
-attribute       pwdCanChange            1.3.6.1.4.1.7165.2.1.8  int single
-attribute       pwdMustChange           1.3.6.1.4.1.7165.2.1.9  int single
-attribute       homedrive               1.3.6.1.4.1.7165.2.1.10 cis single
-attribute       scriptPath              1.3.6.1.4.1.7165.2.1.11 cis single
-attribute       profilePath             1.3.6.1.4.1.7165.2.1.12 cis single
-attribute       userWorkstations        1.3.6.1.4.1.7165.2.1.13 cis single
-attribute       rid                     1.3.6.1.4.1.7165.2.1.14 int single
-attribute       primaryGroupID          1.3.6.1.4.1.7165.2.1.15 int single
-attribute       smbHome                 1.3.6.1.4.1.7165.2.1.17 cis single
-attribute       domain                  1.3.6.1.4.1.7165.2.1.18 cis single
+objectclass sambaUnixIdPool
+               oid
+                               1.3.6.1.4.1.7165.1.2.2.7
+               superior
+                               top
+               requires
+                               uidNumber,
+                               gidNumber
 
-objectclass sambaAccount
-       oid
-               1.3.1.5.1.4.1.7165.2.2.2
-       superior
-               top
-       requires
-               objectClass,
-               uid,
-               rid
-       allows
-               cn,
-               lmPassword,
-               ntPassword,
-               pwdLastSet,
-               logonTime,
-               logoffTime,
-               KickoffTime,
-               pwdCanChange,
-               pwdMustChange,
-               acctFlags,
-               displayName,
-               smbHome,
-               homeDrive,
-               scriptPath,
-               profilePath,
-               description,
-               userWorkstations,
-               primaryGroupID,
-               domain
+objectclass sambaIdmapEntry
+               oid
+                               1.3.6.1.4.1.7165.1.2.2.8
+               superior
+                               top
+               requires
+                               sambaSID
+               allows
+                               uidNumber,
+                               gidNumber
 
+objectclass sambaSidEntry
+               oid
+                               1.3.6.1.4.1.7165.1.2.2.9
+               superior
+                               top
+               requires
+                               sambaSID
index 0abc9d82e272e6d99a6edadf969b87da33c70ec4..37c3347465a4a390d90837374c2d5a7a0d998852 100644 (file)
@@ -1,74 +1,35 @@
-##\r
-## submitted by Martin.Dehn@comparex.de\r
-##\r
-## Experiement sambaAccount schema file Netscape DS 5.0\r
-##\r
-## INSTALL-DIRECTORY/slapd-your_name/config/schema/samba-schema-netscapeds5.ldif\r
-##\r
-dn: cn=schema\r
-objectClass: top\r
-objectClass: ldapSubentry\r
-objectClass: subschema\r
-cn: schema\r
-aci: (target="ldap:///cn=schema")(targetattr !="aci")(version 3.0;acl "anonymo\r
- us, no acis"; allow (read, search, compare) userdn = "ldap:///anyone";)\r
-aci: (targetattr = "*")(version 3.0; acl "Configuration Administrator"; allow \r
- (all) userdn = "ldap:///uid=admin,ou=Administrators, ou=TopologyManagement, \r
- o=NetscapeRoot";)\r
-aci: (targetattr = "*")(version 3.0; acl "Local Directory Administrators Group\r
- "; allow (all) groupdn = "ldap:///cn=Directory Administrators, dc=samba,dc=org";)\r
-aci: (targetattr = "*")(version 3.0; acl "SIE Group"; allow (all)groupdn = "ld\r
- ap:///cn=slapd-sambaldap, cn=iPlanet Directory Server, cn=Server Group, cn=iPlanetDirectory.samba.org, ou=samba.org, o=NetscapeRoot";)\r
-modifiersName: cn=directory manager\r
-modifyTimestamp: 20020322124844Z\r
-objectClasses: ( 1.3.1.5.1.4.1.7165.2.2.2 NAME 'sambaAccount' SUP top STRUCTUR\r
- AL MAY ( acctFlags $ domain $ homeDrive $ kickoffTime $ lmPassword $ logofft\r
- ime $ logonTime $ ntPassword $ primaryGroupID $ profilePath $ pwdCanChange $\r
-  pwdLastSet $ pwdMustChange $ rid $ scriptPath $ smbHome $ userWorkstations \r
- ) X-ORIGIN 'user defined' )\r
-attributeTypes: ( 1.3.6.1.4.1.7165.2.1.11 NAME 'scriptPath' DESC 'NT script pa\r
- th' SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 SINGLE-VALUE X-ORIGIN 'user defined\r
- ' )\r
-attributeTypes: ( 1.3.6.1.4.1.7165.2.1.5 NAME 'logonTime' DESC 'NT logon time'\r
-  SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 SINGLE-VALUE X-ORIGIN 'user defined' )\r
-attributeTypes: ( 1.3.6.1.4.1.7165.2.1.12 NAME 'profilePath' DESC 'NT profile \r
- path' SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 SINGLE-VALUE X-ORIGIN 'user defin\r
- ed' )\r
-attributeTypes: ( 1.3.6.1.4.1.7165.2.1.8 NAME 'pwdCanChange' DESC 'NT passwd c\r
- an change' SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 SINGLE-VALUE X-ORIGIN 'user \r
- defined' )\r
-attributeTypes: ( 1.3.6.1.4.1.7165.2.1.17 NAME 'smbHome' DESC 'smbHome' SYNTAX\r
-  1.3.6.1.4.1.1466.115.121.1.15 SINGLE-VALUE X-ORIGIN 'user defined' )\r
-attributeTypes: ( 1.3.6.1.4.1.7165.2.1.3 NAME 'pwdLastSet'  SYNTAX 1.3.6.1.4.1\r
- .1466.115.121.1.27 SINGLE-VALUE X-ORIGIN 'user defined' )\r
-attributeTypes: ( 1.3.6.1.4.1.7165.2.1.18 NAME 'domain' DESC 'Windows NT domai\r
- n Samba' SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 SINGLE-VALUE X-ORIGIN 'user de\r
- fined' )\r
-attributeTypes: ( 1.3.6.1.4.1.7165.2.1.10 NAME 'homeDrive' DESC 'NT home drive\r
- ' SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 SINGLE-VALUE X-ORIGIN 'user defined' \r
- )\r
-attributeTypes: ( 1.3.6.1.4.1.7165.2.1.6 NAME 'logofftime' DESC 'logoff Time' \r
- SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 SINGLE-VALUE X-ORIGIN 'user defined' )\r
-attributeTypes: ( 1.3.6.1.4.1.7165.2.1.15 NAME 'primaryGroupID' DESC 'NT Group\r
-  RID' SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 SINGLE-VALUE X-ORIGIN 'user defin\r
- ed' )\r
-attributeTypes: ( 1.3.6.1.4.1.7165.2.1.1 NAME 'lmPassword' DESC 'LanManager Pa\r
- sswd' SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 SINGLE-VALUE X-ORIGIN 'user defin\r
- ed' )\r
-attributeTypes: ( 1.3.6.1.4.1.7165.2.1.9 NAME 'pwdMustChange' DESC 'NT pwdmust\r
- chnage' SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 SINGLE-VALUE X-ORIGIN 'user def\r
- ined' )\r
-attributeTypes: ( 1.3.6.1.4.1.7165.2.1.4 NAME 'acctFlags' DESC 'Account Flags'\r
-  SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 SINGLE-VALUE X-ORIGIN 'user defined' )\r
-attributeTypes: ( 1.3.6.1.4.1.7165.2.1.13 NAME 'userWorkstations' DESC 'userWo\r
- rkstations' SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 SINGLE-VALUE X-ORIGIN 'user\r
-  defined' )\r
-attributeTypes: ( 1.3.6.1.4.1.7165.2.1.7 NAME 'kickoffTime' DESC 'NT kickoff T\r
- ime' SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 SINGLE-VALUE X-ORIGIN 'user define\r
- d' )\r
-attributeTypes: ( 1.3.6.1.4.1.7165.2.1.14 NAME 'rid' DESC 'rid' SYNTAX 1.3.6.1\r
- .4.1.1466.115.121.1.27 SINGLE-VALUE X-ORIGIN 'user defined' )\r
-attributeTypes: ( 1.3.6.1.4.1.7165.2.1.2 NAME 'ntPassword' DESC 'NT Passwd' SY\r
- NTAX 1.3.6.1.4.1.1466.115.121.1.15 SINGLE-VALUE X-ORIGIN 'user defined' )\r
-nsSchemaCSN: 3c9b282c000000000000\r
-\r
+##
+## Garren Chew <darren.chew at vicscouts dot asn dot au>
+##
+## Samba 3.0 schema file for Netscape DS 5.x
+##
+## INSTALL-DIRECTORY/slapd-your_name/config/schema/samba-schema-netscapeds5.ldif
+
+objectClasses: ( 1.3.6.1.4.1.7165.2.2.6 NAME 'sambaSamAccount' SUP top AUXILIARY DESC 'Samba 3.0 Auxilary SAM Account' MUST ( uid $ sambaSID ) MAY  ( cn $ sambaLMPassword $ sambaNTPassword $ sambaPwdLastSet $ sambaLogonTime $ sambaLogoffTime $ sambaKickoffTime $ sambaPwdCanChange $ sambaPwdMustChange $ sambaAcctFlags $ displayName $ sambaHomePath $ sambaHomeDrive $ sambaLogonScript $ sambaProfilePath $ description $ sambaUserWorkstations $ sambaPrimaryGroupSID $ sambaDomainName ) X-ORIGIN 'user defined' )
+objectClasses: ( 1.3.6.1.4.1.7165.2.2.4 NAME 'sambaGroupMapping' SUP top AUXILIARY DESC 'Samba Group Mapping' MUST ( gidNumber $ sambaSID $ sambaGroupType ) MAY  ( displayName $ description ) X-ORIGIN 'user defined' )
+objectClasses: ( 1.3.6.1.4.1.7165.2.2.5 NAME 'sambaDomain' SUP top STRUCTURAL DESC 'Samba Domain Information' MUST ( sambaDomainName $ sambaSID ) MAY ( sambaNextRid $ sambaNextGroupRid $ sambaNextUserRid $ sambaAlgorithmicRidBase ) X-ORIGIN 'user defined' )
+objectClasses: ( 1.3.6.1.4.1.7165.1.2.2.7 NAME 'sambaUnixIdPool' SUP top AUXILIARY DESC 'Pool for allocating UNIX uids/gids' MUST ( uidNumber $ gidNumber ) X-ORIGIN 'user defined' )
+objectClasses: ( 1.3.6.1.4.1.7165.1.2.2.8 NAME 'sambaIdmapEntry' SUP top AUXILIARY DESC 'Mapping from a SID to an ID' MUST ( sambaSID ) MAY ( uidNumber $ gidNumber )  X-ORIGIN 'user defined' )
+objectClasses: ( 1.3.6.1.4.1.7165.1.2.2.9 NAME 'sambaSidEntry' SUP top STRUCTURAL DESC 'Structural Class for a SID' MUST ( sambaSID )  X-ORIGIN 'user defined' )
+attributeTypes: ( 1.3.6.1.4.1.7165.2.1.24 NAME 'sambaLMPassword' DESC 'LanManager Password' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26{32} SINGLE-VALUE X-ORIGIN 'user defined' )
+attributeTypes: ( 1.3.6.1.4.1.7165.2.1.25 NAME 'sambaNTPassword' DESC 'MD4 hash of the unicode password' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26{32} SINGLE-VALUE X-ORIGIN 'user defined' )
+attributeTypes: ( 1.3.6.1.4.1.7165.2.1.26 NAME 'sambaAcctFlags'        DESC 'Account Flags' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26{16} SINGLE-VALUE X-ORIGIN 'user defined' )
+attributeTypes: ( 1.3.6.1.4.1.7165.2.1.27 NAME 'sambaPwdLastSet' DESC 'Timestamp of the last password update'  EQUALITY integerMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 SINGLE-VALUE X-ORIGIN 'user defined' )
+attributeTypes: ( 1.3.6.1.4.1.7165.2.1.28 NAME 'sambaPwdCanChange' DESC 'Timestamp of when the user is allowed to update the password' EQUALITY integerMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 SINGLE-VALUE X-ORIGIN 'user defined' )
+attributeTypes: ( 1.3.6.1.4.1.7165.2.1.29 NAME 'sambaPwdMustChange' DESC 'Timestamp of when the password will expire' EQUALITY integerMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 SINGLE-VALUE X-ORIGIN 'user defined' )
+attributeTypes: ( 1.3.6.1.4.1.7165.2.1.30 NAME 'sambaLogonTime'        DESC 'Timestamp of last logon' EQUALITY integerMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 SINGLE-VALUE X-ORIGIN 'user defined' )
+attributeTypes: ( 1.3.6.1.4.1.7165.2.1.31 NAME 'sambaLogoffTime' DESC 'Timestamp of last logoff' EQUALITY integerMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 SINGLE-VALUE X-ORIGIN 'user defined' )
+attributeTypes: ( 1.3.6.1.4.1.7165.2.1.32 NAME 'sambaKickoffTime' DESC 'Timestamp of when the user will be logged off automatically' EQUALITY integerMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 SINGLE-VALUE X-ORIGIN 'user defined' )
+attributeTypes: ( 1.3.6.1.4.1.7165.2.1.33 NAME 'sambaHomeDrive'        DESC 'Driver letter of home directory mapping' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26{4} SINGLE-VALUE X-ORIGIN 'user defined' )
+attributeTypes: ( 1.3.6.1.4.1.7165.2.1.34 NAME 'sambaLogonScript' DESC 'Logon script path' EQUALITY caseIgnoreMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.15{255} SINGLE-VALUE X-ORIGIN 'user defined' )
+attributeTypes: ( 1.3.6.1.4.1.7165.2.1.35 NAME 'sambaProfilePath' DESC 'Roaming profile path' EQUALITY caseIgnoreMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.15{255} SINGLE-VALUE X-ORIGIN 'user defined' )
+attributeTypes: ( 1.3.6.1.4.1.7165.2.1.36 NAME 'sambaUserWorkstations' DESC 'List of user workstations the user is allowed to logon to' EQUALITY caseIgnoreMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.15{255} SINGLE-VALUE X-ORIGIN 'user defined' )
+attributeTypes: ( 1.3.6.1.4.1.7165.2.1.37 NAME 'sambaHomePath' DESC 'Home directory UNC path' EQUALITY caseIgnoreMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.15{128} )
+attributeTypes: ( 1.3.6.1.4.1.7165.2.1.38 NAME 'sambaDomainName' DESC 'Windows NT domain to which the user belongs' EQUALITY caseIgnoreMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.15{128} )
+attributeTypes: ( 1.3.6.1.4.1.7165.2.1.20 NAME 'sambaSID' DESC 'Security ID' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26{64} SINGLE-VALUE X-ORIGIN 'user defined' )
+attributeTypes: ( 1.3.6.1.4.1.7165.2.1.23 NAME 'sambaPrimaryGroupSID' DESC 'Primary Group Security ID' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26{64} SINGLE-VALUE X-ORIGIN 'user defined' )
+attributeTypes: ( 1.3.6.1.4.1.7165.2.1.19 NAME 'sambaGroupType'        DESC 'NT Group Type' EQUALITY integerMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 SINGLE-VALUE X-ORIGIN 'user defined' )
+attributeTypes: ( 1.3.6.1.4.1.7165.2.1.21 NAME 'sambaNextUserRid' DESC 'Next NT rid to give our for users' EQUALITY integerMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 SINGLE-VALUE X-ORIGIN 'user defined' )
+attributeTypes: ( 1.3.6.1.4.1.7165.2.1.22 NAME 'sambaNextGroupRid' DESC 'Next NT rid to give out for groups' EQUALITY integerMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 SINGLE-VALUE X-ORIGIN 'user defined' )
+attributeTypes: ( 1.3.6.1.4.1.7165.2.1.39 NAME 'sambaNextRid' DESC 'Next NT rid to give out for anything' EQUALITY integerMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 SINGLE-VALUE X-ORIGIN 'user defined' )
+attributeTypes: ( 1.3.6.1.4.1.7165.2.1.40 NAME 'sambaAlgorithmicRidBase' DESC 'Base at which the samba RID generation algorithm should operate' EQUALITY integerMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 SINGLE-VALUE X-ORIGIN 'user defined' )
index 6e8387f16e734420481882ca68a484f4ad2a3b4b..14cd72058803ba0813bb8d033204d5b761eca3f4 100644 (file)
@@ -1,10 +1,11 @@
 ##
-## schema file for OpenLDAP 2.0.x
-## Schema for storing Samba's smbpasswd file in LDAP
+## schema file for OpenLDAP 2.x
+## Schema for storing Samba user accounts and group maps in LDAP
 ## OIDs are owned by the Samba Team
 ##
-## Prerequisite schemas - uid (cosine.schema)
+## Prerequisite schemas - uid         (cosine.schema)
 ##                      - displayName (inetorgperson.schema)
+##                      - gidNumber   (nis.schema)
 ##
 ## 1.3.6.1.4.1.7165.2.1.x - attributetypes
 ## 1.3.6.1.4.1.7165.2.2.x - objectclasses
diff --git a/examples/LDAP/smbldap-tools/AUTHORS b/examples/LDAP/smbldap-tools/AUTHORS
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/examples/LDAP/smbldap-tools/CONTRIBUTORS b/examples/LDAP/smbldap-tools/CONTRIBUTORS
new file mode 100644 (file)
index 0000000..1b308a7
--- /dev/null
@@ -0,0 +1,29 @@
+# $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):
+ . 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:
+ . Gert-Jan Braas <braas@wyldebeast-wunderliebe.com>
+       bug report for 2.2.3 samba.schema
+ . Jody Haynes <Jody.Haynes@isunnetworks.com>
+       originaly passwd.pl
+ . Brad Langhorst <brad@langhorst.com>
+       package relocatability
+ . Mirko Manea <mami@arena.sci.univr.it>
+       originaly useradd.pl
+ . Alain Richard <alain.richard@equation.fr>
+       bug report and Perl tips
+ . Roland Schulz <mail@r2s2.de> 
+       bug report for smbldap-passwd
+ . Xavier Boschian <Xavier.Boschian@rtlgroup.net>
+       bug report for smbldap-populate
+ . Christophe DUBREUIL <christophe.dubreuil@laposte.net>
+       Net::LDAP support in smbldap_tools.pm
+# - The End
diff --git a/examples/LDAP/smbldap-tools/COPYING b/examples/LDAP/smbldap-tools/COPYING
new file mode 100644 (file)
index 0000000..32d0e60
--- /dev/null
@@ -0,0 +1,340 @@
+                   GNU GENERAL PUBLIC LICENSE
+                      Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.
+ 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+                           Preamble
+
+  The licenses for most software are designed to take away your
+freedom to share and change it.  By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users.  This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it.  (Some other Free Software Foundation software is covered by
+the GNU Library General Public License instead.)  You can apply it to
+your programs, too.
+
+  When we speak of free software, we are referring to freedom, not
+price.  Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+  To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+  For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have.  You must make sure that they, too, receive or can get the
+source code.  And you must show them these terms so they know their
+rights.
+
+  We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+  Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software.  If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+  Finally, any free program is threatened constantly by software
+patents.  We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary.  To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+  The precise terms and conditions for copying, distribution and
+modification follow.
+
+                   GNU GENERAL PUBLIC LICENSE
+   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+  0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License.  The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language.  (Hereinafter, translation is included without limitation in
+the term "modification".)  Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope.  The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+  1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+  2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+    a) You must cause the modified files to carry prominent notices
+    stating that you changed the files and the date of any change.
+
+    b) You must cause any work that you distribute or publish, that in
+    whole or in part contains or is derived from the Program or any
+    part thereof, to be licensed as a whole at no charge to all third
+    parties under the terms of this License.
+
+    c) If the modified program normally reads commands interactively
+    when run, you must cause it, when started running for such
+    interactive use in the most ordinary way, to print or display an
+    announcement including an appropriate copyright notice and a
+    notice that there is no warranty (or else, saying that you provide
+    a warranty) and that users may redistribute the program under
+    these conditions, and telling the user how to view a copy of this
+    License.  (Exception: if the Program itself is interactive but
+    does not normally print such an announcement, your work based on
+    the Program is not required to print an announcement.)
+
+These requirements apply to the modified work as a whole.  If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works.  But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+  3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+    a) Accompany it with the complete corresponding machine-readable
+    source code, which must be distributed under the terms of Sections
+    1 and 2 above on a medium customarily used for software interchange; or,
+
+    b) Accompany it with a written offer, valid for at least three
+    years, to give any third party, for a charge no more than your
+    cost of physically performing source distribution, a complete
+    machine-readable copy of the corresponding source code, to be
+    distributed under the terms of Sections 1 and 2 above on a medium
+    customarily used for software interchange; or,
+
+    c) Accompany it with the information you received as to the offer
+    to distribute corresponding source code.  (This alternative is
+    allowed only for noncommercial distribution and only if you
+    received the program in object code or executable form with such
+    an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it.  For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable.  However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+  4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License.  Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+  5. You are not required to accept this License, since you have not
+signed it.  However, nothing else grants you permission to modify or
+distribute the Program or its derivative works.  These actions are
+prohibited by law if you do not accept this License.  Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+  6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions.  You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+  7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License.  If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all.  For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices.  Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+  8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded.  In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+  9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time.  Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number.  If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation.  If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+  10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission.  For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this.  Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+                           NO WARRANTY
+
+  11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.  EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU.  SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+  12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+                    END OF TERMS AND CONDITIONS
+
+           How to Apply These Terms to Your New Programs
+
+  If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+  To do so, attach the following notices to the program.  It is safest
+to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+    <one line to give the program's name and a brief idea of what it does.>
+    Copyright (C) 19yy  <name of author>
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+    Gnomovision version 69, Copyright (C) 19yy name of author
+    Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+    This is free software, and you are welcome to redistribute it
+    under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License.  Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary.  Here is a sample; alter the names:
+
+  Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+  `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+  <signature of Ty Coon>, 1 April 1989
+  Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs.  If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library.  If this is what you want to do, use the GNU Library General
+Public License instead of this License.
diff --git a/examples/LDAP/smbldap-tools/ChangeLog b/examples/LDAP/smbldap-tools/ChangeLog
new file mode 100644 (file)
index 0000000..76b8b3f
--- /dev/null
@@ -0,0 +1,30 @@
+# $Source: /data/src/mirror/cvs/samba/examples/LDAP/smbldap-tools/ChangeLog,v $
+#
+## 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
+              (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)
+
+
+# - The End
diff --git a/examples/LDAP/smbldap-tools/FILES b/examples/LDAP/smbldap-tools/FILES
new file mode 100644 (file)
index 0000000..48ee571
--- /dev/null
@@ -0,0 +1,43 @@
+# $Source: /data/src/mirror/cvs/samba/examples/LDAP/smbldap-tools/FILES,v $
+#
+## File listing for SMBLDAP-TOOLS
+
+CONTRIBUTORS           : authors and contributors
+COPYING                : licence
+FILES                  : this file listing
+README                 : introduction and usage
+TODO                   : feature request and bug report list
+ChangeLog              : changelog
+
+Core:
+=-=-=
+smbldap-groupadd.pl    : to add a new group
+                        (objectclass: posixGroup)
+smbldap-groupdel.pl    : to delete a group
+                        (objectclass: posixGroup)
+smbldap-groupmod.pl    : to modify a group (mostly used to add user to a group)
+                        (objectclass: posixGroup)
+smbldap-groupshow.pl   : to view a group
+                        (objectclass: posixGroup)
+smbldap_conf.pm        : global configuration datas
+smbldap_tools.pm       : functions
+smbldap-useradd.pl     : to add a new user
+                        (objectclass: posixAccount and/or sambaAccount)
+smbldap-userdel.pl     : to delete a user
+                        (objectclass: posixAccount and/or sambaAccount)
+smbldap-usermod.pl     : to modify an user datas
+                        (objectclass: posixAccount and/or sambaAccount)
+smbldap-usershow.pl    : to view an user datas
+                        (objectclass: posixAccount and/or sambaAccount)
+smbldap-passwd.pl      : to sync passwd (Unix and Samba)
+                        (a replacement for the system passwd utility)
+smbldap-populate.pl    : to add a builtin ldif to initialize your LDAP master for
+                         smbldap use, or to add a specified ldif
+smbldap-tools.spec     : SPEC file for RedHat RPM package format
+
+Migration:
+=-=-=-=-=-
+smbldap-migrate-accounts.pl     : add NT sam entries from pwdump to ldap
+smbldap-migrate-groups.pl       : add any LDAP posixGroups from the output of the 'net group' NT command
+
+# - The End
diff --git a/examples/LDAP/smbldap-tools/INFRASTRUCTURE b/examples/LDAP/smbldap-tools/INFRASTRUCTURE
new file mode 100644 (file)
index 0000000..75b80bb
--- /dev/null
@@ -0,0 +1,84 @@
+# $Source: /data/src/mirror/cvs/samba/examples/LDAP/smbldap-tools/INFRASTRUCTURE,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" "
+
+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
diff --git a/examples/LDAP/smbldap-tools/INSTALL b/examples/LDAP/smbldap-tools/INSTALL
new file mode 100644 (file)
index 0000000..f4c7275
--- /dev/null
@@ -0,0 +1,28 @@
+# $Source: /data/src/mirror/cvs/samba/examples/LDAP/smbldap-tools/INSTALL,v $
+#
+## How To Install SMBLDAP-TOOLS
+
+Quick & Dirty:
+=-=-=-=-=-=-=-
+ . Copy all those scripts in /usr/local/sbin/
+ . Modify smbldap_conf.pm to match your configuration
+ . If not already done : "smbpasswd -w secret" to set up
+   the ldap admin password in secrets.tdb
+ . Either add /usr/local/sbin in $PERLLIB or run the scripts
+   from this directory, or make a symlink from /usr/local/sbin/*.pm
+   to /usr/lib/perl5/.
+ . to allow a domain admin to add user using "add user script" in smb.conf :
+   chmod 753 smbldap_conf.pm
+   chmod 750 smbldap-useradd.pl
+   chgrp 512 smbldap_conf.pm smbldap-useradd.pl (512 = 0x200 = Domain Admins)
+   Have your admin belong to this group
+   In smb.conf : domain admin group = " @"Domain Admins" "
+
+RedHat RPM:
+=-=-=-=-=-=
+Install smbldap-tools-0.7-1.i386.rpm
+Modify /usr/local/sbin/smbldap_conf.pm to match you configuration
+If not already done : "smbpasswd -w secret" to set up
+the ldap admin password in secrets.tdb
+
+# - The End
diff --git a/examples/LDAP/smbldap-tools/Makefile b/examples/LDAP/smbldap-tools/Makefile
new file mode 100644 (file)
index 0000000..3e5eac4
--- /dev/null
@@ -0,0 +1,35 @@
+PACKAGE=smbldap-tools
+RELEASE=0.7
+DESTDIR = $(PACKAGE)-$(RELEASE)
+
+dist:  distclean $(DESTDIR).tgz 
+
+$(DESTDIR).tgz:        .diststamp
+       rm -rf $(DESTDIR)
+       mkdir $(DESTDIR)
+       # copy files
+       cp CONTRIBUTORS $(DESTDIR)
+       cp COPYING $(DESTDIR)
+       cp ChangeLog $(DESTDIR)
+       cp FILES $(DESTDIR)
+       cp INSTALL $(DESTDIR)
+       cp README $(DESTDIR)
+       cp TODO $(DESTDIR)
+       cp INFRASTRUCTURE $(DESTDIR)
+       tar cf mkntpwd.tar mkntpwd
+       gzip mkntpwd.tar
+       cp mkntpwd.tar.gz $(DESTDIR)
+       cp smbldap-*.pl $(DESTDIR)
+       cp smbldap_*.pm $(DESTDIR)
+       # copy directories
+       tar cvzf $(DESTDIR).tgz $(DESTDIR)
+       rm -rf $(DESTDIR)
+       touch .diststamp
+
+.diststamp:
+
+distclean:
+       rm -f *~
+       rm -f $(DESTDIR).tgz
+       rm -f mkntpwd.tar.gz
+
diff --git a/examples/LDAP/smbldap-tools/NEWS b/examples/LDAP/smbldap-tools/NEWS
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/examples/LDAP/smbldap-tools/README b/examples/LDAP/smbldap-tools/README
new file mode 100644 (file)
index 0000000..add0175
--- /dev/null
@@ -0,0 +1,87 @@
+# $Source: /data/src/mirror/cvs/samba/examples/LDAP/smbldap-tools/README,v $
+#
+
+Latest version may be found at http://samba.idealx.org/
+
+
+What those tools are for?
+=-=-=-=-=-=-=-=-=-=-=-=-=
+
+A collection of scripts, «over» user{add,del,mod} and group{add,del,mod}
+system tools to manipulate users and groups stored in LDAP directory,
+for DEN system like SAMBA-LDAP and pam/nss_ldap systems.
+
+Additionnaly, some scripts are designed to ease your migration from
+a Windows NT 4.0 PDC Server to a Samba-LDAP PDC Server (Killer?;-):
+smbldap-populate, smbldap-migrate-groups, smbldap-migrate-accounts.
+
+They are currently used with Samba 2.2.4, therefore you may (will) have
+to make some fixes for Samba TNG and Samba 3.0. Hint: contribs welcome :)
+
+In the future, some other function may come (like backup and restore,
+Novell migration tools, samba system activity report, dealing with
+mail functions, compliance to RFC2307...): consult TODO.
+
+
+What do SMBLDAP-TOOLS provide?
+=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+Those tools provide the following functions :
+ . populate LDAP database with a basic LDIF
+ . add a user or group
+ . delete a user or group
+ . modify all users or groups data (all attributes types stored in
+   posixAccount and sambaAccount object class)
+Taking care of :
+ . staying compatible with all standard system tools options
+   (user/group{add,del,mod})
+ . be extensible for future developments
+   (manipulation of shadow account options, for example)
+ . error management, in the way system tools do
+Constraints :
+ . usage of PERL (portability)
+ . all options must be placed in an external configuration file
+ . english localization
+
+The current release uses the "mkntpwd" program, in mkntpwd.tar.gz
+in the current directory. It comes from
+http://www.demog.berkeley.edu/~aperrin/tips/src/mkntpwd.tar.gz
+It allows to not use smbpasswd (if $with_smbpasswd == 0 in smbldap_conf.pm)
+
+What do SMBLDAP-TOOLS deliver?
+=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
+Contents :
+ . scripts (see FILES)
+ . user documentation in pod format, included in the sources
+   (or just use the -? option)
+
+These tools aim at delivering the same functionality as the corresponding
+system tools. However they may not be all implemented yet.
+Current limitations :
+ . no shadow support
+ . cannot change uid with usermod
+ . no UTF-8 support (thus ASCII-7 only)
+
+
+How to generate documentation?
+=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+Just issue the following command:
+ perldoc name_of_script.pl (ex: perldoc smbldap-useradd.pl)
+
+Where can I find the latest release of those scripts?
+=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+
+Just fire any web browser to http://samba.IDEALX.org/
+and/or contact samba@IDEALX.org
+
+Additionnaly, you will find an useful Webmin module
+at http://webmin.IDEALX.org/ if interested in a graphical 
+user interface to manager user and groups accounts via Webmin
+for your Samba+LDAP PDC.
+
+Let us know if these tools helped you, or if we should enhance
+them with some functions you want them to support.
+
+Sincerly,
+       LEM
+
+# - The End
diff --git a/examples/LDAP/smbldap-tools/TODO b/examples/LDAP/smbldap-tools/TODO
new file mode 100644 (file)
index 0000000..71e6695
--- /dev/null
@@ -0,0 +1,28 @@
+# $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)
+
+
+FR * add 'LDAP port' for both slave and master LDAP server in smbldap_conf.pm
+FR * use RFC2307 best practices (Luke, next time you visit Paris, have a 
+     beer at IDEALX'cantina ;-)
+FR * add mail (sendmail/postfix/qmail/courier) support
+FR * bugfix, really : allow non-root users to change passwd
+     (currently the config must be unreadable because of bindpasswd)
+FR * make smbldap-tools to use system configuration files
+     (/etc/login.defs and /etc/ldap.conf for example)
+FR * rewrite smbldap-tools using perl-ldap. In fact, this 0.x
+     release use ldap system tools (ldapadd,ldapdelete,ldapmodify)
+FR * add shadowAccounts manipulation support
+FR * internationalize the SMBLDAP-TOOLS
+FR * add smbldap-sar : Samba System Activity Report to help
+     supporting Samba/LDAP sysadmin activity
+FR * add smbldap-backup/smbldap-restore to backup and restore
+     a SAM (in LDAP) database. No sorcery, just LDIF, but usefull
+     for non-LDAP gurus
+FR * adding migration tools from migration from W2K and NetWare to Samba-LDAP
+FR * adapt smbldap-tools to use Samba 3.0
+
+
+# - The End
diff --git a/examples/LDAP/smbldap-tools/cgi/README b/examples/LDAP/smbldap-tools/cgi/README
new file mode 100644 (file)
index 0000000..7a4fc0c
--- /dev/null
@@ -0,0 +1,27 @@
+Description:
+       A cgi to allow users to change their passwords via a web browser.
+
+Installation:
+       Drop this into a cgi-enabled directory on your webserver.
+       Edit it and change the CONFIGURATION section to suit your environment.
+       READ THE NOTES SECTION.
+
+Notes: This script will run as the user who runs your web server. So, to invoke the smbpasswd call, you must implement sudo.
+       Example of /etc/sudoers:
+
+       # Host alias specification
+       # User alias specification
+       User_Alias     PASSWD = apache
+       # Cmnd alias specification
+       Cmnd_Alias     PASSWD   = /usr/bin/smbpasswd
+       # User privilege specification
+       root    ALL=(ALL) ALL
+       PASSWD  ALL= NOPASSWD: PASSWD
+
+       This concept is probably very insecure and broken. That is why this is a 0.1 release.  :)
+
+
+Feel free to drop me suggestions.   I am a perl learner so I am always open to suggestions.
+
+Terry Davis
+tdavis@approbation.org
diff --git a/examples/LDAP/smbldap-tools/cgi/ldappass.cgi b/examples/LDAP/smbldap-tools/cgi/ldappass.cgi
new file mode 100755 (executable)
index 0000000..4a5ecb8
--- /dev/null
@@ -0,0 +1,202 @@
+#!/usr/bin/perl
+
+################################################################################
+#
+# changepass.pl - A program to allow users to change their passwords
+#                 via a web browser.
+# Terry Davis
+# 
+# URLs
+#      Net::LDAP - http://
+#      usermod and this file - http://www.cloudamster.com/cloudmaster/projects
+#
+# Release History:
+#      Version 0.1 - initial write
+#
+# ToDo:
+#      ... the ToDo section is on the ToDo list...
+#
+# Limitations:
+#      The password cannot contain single and double quotes.....welcome to quoting hell....
+#
+# Notes:
+#       This code is largely based on work done by Danny Sauer - http://www.cloudamster.com/cloudmaster/projects
+#       His work is not licensed and is marked as 'freely distributable'.
+#       Thank you to Danny for his hard work on the initial work.
+#
+################################################################################
+
+use CGI qw(:standard);
+use Net::LDAP;
+
+# CONFIGURATION SECTION
+$masterLDAP = "ldap.idealx.org";
+$basedn = "dc=IDEALX,dc=org";
+$masterPw = "";
+$masterDN = "cn=manager,$basedn";
+$ldap_path = "/usr/bin";
+$ldap_opts = "-x";
+$ldappasswd = "$ldap_path/ldappasswd $ldap_opts -h $masterLDAP -D '$masterDN' -w '$masterPw'";
+$usersdn = "ou=Users,$basedn";
+# END CONFIGURATION
+
+
+
+# DONT EDIT ANYTHING BELOW THIS LINE
+$logtag = "Login:";
+$passtag = "Current password:";
+$npasstag1 = "New password:";
+$npasstag2 = "Retype new pasword:";
+$error = "";
+$color = "<FONT color='red'>";
+$stopcolor = "</FONT>";
+
+if(param()){
+       nologin() unless ($username = param('login'));
+       nopass() unless ($oldpass = param('oldpass'));
+       nonewpass(1) unless ($newpass1 = param('newpass'));
+       nonewpass(2) unless ($newpass2 = param('newpass2'));
+       verifyuser($username) or die "bad user";
+       verifypass($username, $oldpass) or die "bad pass";
+       testnewpass($newpass1, $newpass2) or die "bad new pass";
+       changepass($username, $newpass1) or die "couldn't change pass";
+       printsuccess();
+}else{
+       printpage();
+}
+exit(0);
+
+sub verifyuser{
+       local $user = shift;
+       $ldap = Net::LDAP->new($masterLDAP) or die "can't make new LDAP object: $@";
+       $ldap->bind();
+       if (0 < $ldap->search(base => $basedn, filter => "(uid=$user)")->count){
+               return 1;
+       }
+       $logtag = $color . $logtag . $color;
+       $error = "No such user";
+       printpage();
+       return 0;
+}
+
+sub verifypass{
+       $uid = shift;
+       $pass = shift;
+       $ldap = Net::LDAP->new($masterLDAP) or die "can't make new LDAP object: $@";
+       $binddn = "uid=$uid,ou=People,$basedn";
+       return 1 if($ldap->bind( $binddn, password => $pass)->code == 0);
+       if($ldap->bind()){
+               $passtag = $color . $passtag . $color;
+               $error = "Incorrect password";
+               printpage();
+               return 0;
+       }else{
+               print header, start_html(-title=>"LDAP dead");
+               print h2("<CENTER>The LDAP server is temporarily unavailable."),
+                       p,"Please try again later</CENTER>";
+               return 0;
+       }die "Something (or someone) is defective, contact your friendly Systems Administrator";
+}
+
+sub testnewpass{
+       $p1 = shift; $p2 = shift;
+       if ($p1 ne $p2){
+               $npasstag1 = $color . $npasstag1 . $color;
+               $npasstag2 = $color . $npasstag2 . $color;
+               $error = "Passwords don't match ($p1 vs $p2)";
+               printpage();
+               return 0;
+       }
+        if ($p1 =~ /"/ ){
+                $npasstag1 = $color . $npasstag1 . $color;
+                $npasstag2 = $color . $npasstag2 . $color;
+                $error = "Passwords cannot contain double quotes. Sorry";
+                printpage();
+                return 0;
+        }
+        if ($p1 =~ /'/ ){
+                $npasstag1 = $color . $npasstag1 . $color;
+                $npasstag2 = $color . $npasstag2 . $color;
+                $error = "Passwords cannot contain single quotes. Sorry";
+                printpage();
+                return 0;
+        }
+       return 1;
+}
+
+sub changepass{
+       local $user = shift;
+       local $newpass = shift;
+       local $dn = "uid=$user,$usersdn";
+       system "$ldappasswd $dn -s '$newpass' > /dev/null";
+       `/usr/bin/sudo /usr/bin/smbpasswd $user "$newpass"`;    
+       exit(1);
+}
+
+sub nologin{
+       $logtag = $color . $logtag . $color;
+       $error = "You need to enter a Login Name";
+       printpage();
+       exit(1);
+}
+
+sub nopass{
+       $passtag = $color . $passtag . $color;
+       $error = "Please enter your old password";
+       printpage();
+       exit(1);
+}
+
+sub nonewpass{
+       $f=shift;
+       $npasstag1 = $color . $npasstag1 . $color if($f==1);
+       $npasstag2 = $color . $npasstag2 . $color if($f==2);
+       $error = "You need to enter your new password";
+       $error .= " twice" if($f==2);
+       printpage();
+       exit(1);
+}
+
+sub printpage{
+       print header,
+             start_html(-title=> "Password Change Page",
+                        -author=> 'tdavis@birddog.com',
+                        -BGCOLOR=> 'WHITE'),
+             h3('Password Change Page'),
+             startform(-method=>'POST'),
+             "<TABLE BORDER=0 WIDTH=50%>",
+             "<font size=2>",
+             "<TR><TD>",
+             $logtag,
+             "</TD><TD>",
+             textfield(-name=>'login', -default=>$login, 
+                       -size=>15, -maxlength=>20),
+             "</TD><TR><TD>",
+             $passtag,
+             "</TD><TD>",
+             password_field(-name=>'oldpass', -size=>15, -maxlength=>25),
+             "</TD><TR><TD>",
+             $npasstag1,
+             "</TD><TD>",
+             password_field(-name=>'newpass', -size=>15, -maxlength=>25),
+             "</TD><TR><TD>",
+             $npasstag2,
+             "</TD><TD>",
+             password_field(-name=>'newpass2', -size=>15, -maxlength=>25),
+             "</TD><TR><TD></TD><TD>",
+             submit(-name=>"change"),reset(),
+             "</TD></TR></TABLE>",
+             "</font>",
+             endform(),
+             "<FONT color='red'>$error</FONT>",
+             end_html;
+}
+
+sub printsuccess(){
+       print header,
+             start_html(-title=> "Success",
+                            -BGCOLOR=> 'WHITE'),
+                 h1("Password Succesfully Changed"),
+                 "<br>",
+                 end_html;
+}
diff --git a/examples/LDAP/smbldap-tools/mkntpwd/Makefile b/examples/LDAP/smbldap-tools/mkntpwd/Makefile
new file mode 100644 (file)
index 0000000..23c9d47
--- /dev/null
@@ -0,0 +1,62 @@
+# Makefile for l0phtcrack - mudge@l0pht.com 11/1/96
+
+# C compiler
+#CC=cc
+CC=gcc
+
+# Uncomment the following to add symbols to the code for debugging
+#DEBUG=-g -Wall -D_DEBUG
+#DEBUG=-D_DEBUG
+
+# Optimization for the compiler
+#OPTIMIZE=
+OPTIMIZE=-O2
+
+# Choose your architecture
+#  note that if you are on a big-endian machine like SUN's
+#  I haven't tweaked the mem-cmp's and md4 stuff to be in 
+#  the correct order yet. You're on your own right now.
+#
+# FreeBSD
+ARCH=-DMPU8086 
+STATIC=
+XLIBS=
+#
+# SUNOS
+#ARCH=-DBIGENDIAN
+#STATIC=
+#OPTIMIZE=-O2
+#XLIBS=
+#
+# ULTRA_SPARC w/ native compiler
+#ARCH=-DBIGENDIAN
+#STATIC=
+#OPTIMIZE=-fast -xO4 -xdepend -xchip=ultra -xarch=v8plus
+#XLIBS=
+#
+# SunOS/Solaris w/gcc
+#ARCH=-DBIGENDIAN -DTEST
+#STATIC=
+#OPTIMIZE=-O2
+#XLIBS=
+#
+# NeXTStep 3.2
+#CC=cc
+#ARCH=-DBIGENDIAN
+#STATIC=-Bstatic
+#OPTIMIZE=
+#XLIBS=
+
+CFLAGS= $(DEBUG) $(OPTIMIZE) $(ARCH) $(VISUAL) $(PERMUTE) $(STATIC) 
+
+OBJS = getopt.o        md4.o           mkntpwd.o       smbdes.o
+
+mkntpwd: $(OBJS)
+       $(CC) $(CFLAGS) $(XLIBS) -o mkntpwd $(OBJS)
+
+clean:
+       rm -f core *.o mkntpwd
+
+install: mkntpwd
+       install -m 555 mkntpwd $(PREFIX)/sbin/mkntpwd
+
diff --git a/examples/LDAP/smbldap-tools/mkntpwd/getopt.c b/examples/LDAP/smbldap-tools/mkntpwd/getopt.c
new file mode 100644 (file)
index 0000000..5b2e7a9
--- /dev/null
@@ -0,0 +1,756 @@
+/* Getopt for GNU.
+   NOTE: getopt is now part of the C library, so if you don't know what
+   "Keep this file name-space clean" means, talk to roland@gnu.ai.mit.edu
+   before changing it!
+
+   Copyright (C) 1987, 88, 89, 90, 91, 92, 93, 94
+       Free Software Foundation, Inc.
+
+This file is part of the GNU C Library.  Its master source is NOT part of
+the C library, however.  The master source lives in /gd/gnu/lib.
+
+The GNU C Library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Library General Public License as
+published by the Free Software Foundation; either version 2 of the
+License, or (at your option) any later version.
+
+The GNU C Library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with the GNU C Library; see the file COPYING.LIB.  If
+not, write to the Free Software Foundation, Inc., 675 Mass Ave,
+Cambridge, MA 02139, USA.  */
+\f
+/* This tells Alpha OSF/1 not to define a getopt prototype in <stdio.h>.
+   Ditto for AIX 3.2 and <stdlib.h>.  */
+#ifndef _NO_PROTO
+#define _NO_PROTO
+#endif
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#if !defined (__STDC__) || !__STDC__
+/* This is a separate conditional since some stdc systems
+   reject `defined (const)'.  */
+#ifndef const
+#define const
+#endif
+#endif
+
+#include <stdio.h>
+
+#ifdef WIN32
+#include <string.h>
+#endif
+
+/* Comment out all this code if we are using the GNU C Library, and are not
+   actually compiling the library itself.  This code is part of the GNU C
+   Library, but also included in many other GNU distributions.  Compiling
+   and linking in this code is a waste when using the GNU C library
+   (especially if it is a shared library).  Rather than having every GNU
+   program understand `configure --with-gnu-libc' and omit the object files,
+   it is simpler to just do this in the source for each such file.  */
+
+#if defined (_LIBC) || !defined (__GNU_LIBRARY__)
+
+
+/* This needs to come after some library #include
+   to get __GNU_LIBRARY__ defined.  */
+#ifdef __GNU_LIBRARY__
+/* Don't include stdlib.h for non-GNU C libraries because some of them
+   contain conflicting prototypes for getopt.  */
+#include <stdlib.h>
+#endif /* GNU C library.  */
+
+/* This version of `getopt' appears to the caller like standard Unix `getopt'
+   but it behaves differently for the user, since it allows the user
+   to intersperse the options with the other arguments.
+
+   As `getopt' works, it permutes the elements of ARGV so that,
+   when it is done, all the options precede everything else.  Thus
+   all application programs are extended to handle flexible argument order.
+
+   Setting the environment variable POSIXLY_CORRECT disables permutation.
+   Then the behavior is completely standard.
+
+   GNU application programs can use a third alternative mode in which
+   they can distinguish the relative order of options and other arguments.  */
+
+#include "getopt.h"
+
+/* For communication from `getopt' to the caller.
+   When `getopt' finds an option that takes an argument,
+   the argument value is returned here.
+   Also, when `ordering' is RETURN_IN_ORDER,
+   each non-option ARGV-element is returned here.  */
+
+char *optarg = NULL;
+
+/* Index in ARGV of the next element to be scanned.
+   This is used for communication to and from the caller
+   and for communication between successive calls to `getopt'.
+
+   On entry to `getopt', zero means this is the first call; initialize.
+
+   When `getopt' returns EOF, this is the index of the first of the
+   non-option elements that the caller should itself scan.
+
+   Otherwise, `optind' communicates from one call to the next
+   how much of ARGV has been scanned so far.  */
+
+/* XXX 1003.2 says this must be 1 before any call.  */
+int optind = 0;
+
+/* The next char to be scanned in the option-element
+   in which the last option character we returned was found.
+   This allows us to pick up the scan where we left off.
+
+   If this is zero, or a null string, it means resume the scan
+   by advancing to the next ARGV-element.  */
+
+static char *nextchar;
+
+/* Callers store zero here to inhibit the error message
+   for unrecognized options.  */
+
+int opterr = 1;
+
+/* Set to an option character which was unrecognized.
+   This must be initialized on some systems to avoid linking in the
+   system's own getopt implementation.  */
+
+int optopt = '?';
+
+/* Describe how to deal with options that follow non-option ARGV-elements.
+
+   If the caller did not specify anything,
+   the default is REQUIRE_ORDER if the environment variable
+   POSIXLY_CORRECT is defined, PERMUTE otherwise.
+
+   REQUIRE_ORDER means don't recognize them as options;
+   stop option processing when the first non-option is seen.
+   This is what Unix does.
+   This mode of operation is selected by either setting the environment
+   variable POSIXLY_CORRECT, or using `+' as the first character
+   of the list of option characters.
+
+   PERMUTE is the default.  We permute the contents of ARGV as we scan,
+   so that eventually all the non-options are at the end.  This allows options
+   to be given in any order, even with programs that were not written to
+   expect this.
+
+   RETURN_IN_ORDER is an option available to programs that were written
+   to expect options and other ARGV-elements in any order and that care about
+   the ordering of the two.  We describe each non-option ARGV-element
+   as if it were the argument of an option with character code 1.
+   Using `-' as the first character of the list of option characters
+   selects this mode of operation.
+
+   The special argument `--' forces an end of option-scanning regardless
+   of the value of `ordering'.  In the case of RETURN_IN_ORDER, only
+   `--' can cause `getopt' to return EOF with `optind' != ARGC.  */
+
+static enum
+{
+  REQUIRE_ORDER, PERMUTE, RETURN_IN_ORDER
+} ordering;
+
+/* Value of POSIXLY_CORRECT environment variable.  */
+static char *posixly_correct;
+\f
+#ifdef __GNU_LIBRARY__
+/* We want to avoid inclusion of string.h with non-GNU libraries
+   because there are many ways it can cause trouble.
+   On some systems, it contains special magic macros that don't work
+   in GCC.  */
+#include <string.h>
+#define        my_index        strchr
+#else
+
+/* Avoid depending on library functions or files
+   whose names are inconsistent.  */
+
+char *getenv ();
+
+static char *
+my_index (str, chr)
+     const char *str;
+     int chr;
+{
+  while (*str)
+    {
+      if (*str == chr)
+       return (char *) str;
+      str++;
+    }
+  return 0;
+}
+
+/* If using GCC, we can safely declare strlen this way.
+   If not using GCC, it is ok not to declare it.  */
+#ifdef __GNUC__
+/* Note that Motorola Delta 68k R3V7 comes with GCC but not stddef.h.
+   That was relevant to code that was here before.  */
+#if !defined (__STDC__) || !__STDC__
+/* gcc with -traditional declares the built-in strlen to return int,
+   and has done so at least since version 2.4.5. -- rms.  */
+extern int strlen (const char *);
+#endif /* not __STDC__ */
+#endif /* __GNUC__ */
+
+#endif /* not __GNU_LIBRARY__ */
+\f
+/* Handle permutation of arguments.  */
+
+/* Describe the part of ARGV that contains non-options that have
+   been skipped.  `first_nonopt' is the index in ARGV of the first of them;
+   `last_nonopt' is the index after the last of them.  */
+
+static int first_nonopt;
+static int last_nonopt;
+
+/* Exchange two adjacent subsequences of ARGV.
+   One subsequence is elements [first_nonopt,last_nonopt)
+   which contains all the non-options that have been skipped so far.
+   The other is elements [last_nonopt,optind), which contains all
+   the options processed since those non-options were skipped.
+
+   `first_nonopt' and `last_nonopt' are relocated so that they describe
+   the new indices of the non-options in ARGV after they are moved.  */
+
+static void
+exchange (argv)
+     char **argv;
+{
+  int bottom = first_nonopt;
+  int middle = last_nonopt;
+  int top = optind;
+  char *tem;
+
+  /* Exchange the shorter segment with the far end of the longer segment.
+     That puts the shorter segment into the right place.
+     It leaves the longer segment in the right place overall,
+     but it consists of two parts that need to be swapped next.  */
+
+  while (top > middle && middle > bottom)
+    {
+      if (top - middle > middle - bottom)
+       {
+         /* Bottom segment is the short one.  */
+         int len = middle - bottom;
+         register int i;
+
+         /* Swap it with the top part of the top segment.  */
+         for (i = 0; i < len; i++)
+           {
+             tem = argv[bottom + i];
+             argv[bottom + i] = argv[top - (middle - bottom) + i];
+             argv[top - (middle - bottom) + i] = tem;
+           }
+         /* Exclude the moved bottom segment from further swapping.  */
+         top -= len;
+       }
+      else
+       {
+         /* Top segment is the short one.  */
+         int len = top - middle;
+         register int i;
+
+         /* Swap it with the bottom part of the bottom segment.  */
+         for (i = 0; i < len; i++)
+           {
+             tem = argv[bottom + i];
+             argv[bottom + i] = argv[middle + i];
+             argv[middle + i] = tem;
+           }
+         /* Exclude the moved top segment from further swapping.  */
+         bottom += len;
+       }
+    }
+
+  /* Update records for the slots the non-options now occupy.  */
+
+  first_nonopt += (optind - last_nonopt);
+  last_nonopt = optind;
+}
+
+/* Initialize the internal data when the first call is made.  */
+
+static const char *
+_getopt_initialize (optstring)
+     const char *optstring;
+{
+  /* Start processing options with ARGV-element 1 (since ARGV-element 0
+     is the program name); the sequence of previously skipped
+     non-option ARGV-elements is empty.  */
+
+  first_nonopt = last_nonopt = optind = 1;
+
+  nextchar = NULL;
+
+  posixly_correct = getenv ("POSIXLY_CORRECT");
+
+  /* Determine how to handle the ordering of options and nonoptions.  */
+
+  if (optstring[0] == '-')
+    {
+      ordering = RETURN_IN_ORDER;
+      ++optstring;
+    }
+  else if (optstring[0] == '+')
+    {
+      ordering = REQUIRE_ORDER;
+      ++optstring;
+    }
+  else if (posixly_correct != NULL)
+    ordering = REQUIRE_ORDER;
+  else
+    ordering = PERMUTE;
+
+  return optstring;
+}
+\f
+/* Scan elements of ARGV (whose length is ARGC) for option characters
+   given in OPTSTRING.
+
+   If an element of ARGV starts with '-', and is not exactly "-" or "--",
+   then it is an option element.  The characters of this element
+   (aside from the initial '-') are option characters.  If `getopt'
+   is called repeatedly, it returns successively each of the option characters
+   from each of the option elements.
+
+   If `getopt' finds another option character, it returns that character,
+   updating `optind' and `nextchar' so that the next call to `getopt' can
+   resume the scan with the following option character or ARGV-element.
+
+   If there are no more option characters, `getopt' returns `EOF'.
+   Then `optind' is the index in ARGV of the first ARGV-element
+   that is not an option.  (The ARGV-elements have been permuted
+   so that those that are not options now come last.)
+
+   OPTSTRING is a string containing the legitimate option characters.
+   If an option character is seen that is not listed in OPTSTRING,
+   return '?' after printing an error message.  If you set `opterr' to
+   zero, the error message is suppressed but we still return '?'.
+
+   If a char in OPTSTRING is followed by a colon, that means it wants an arg,
+   so the following text in the same ARGV-element, or the text of the following
+   ARGV-element, is returned in `optarg'.  Two colons mean an option that
+   wants an optional arg; if there is text in the current ARGV-element,
+   it is returned in `optarg', otherwise `optarg' is set to zero.
+
+   If OPTSTRING starts with `-' or `+', it requests different methods of
+   handling the non-option ARGV-elements.
+   See the comments about RETURN_IN_ORDER and REQUIRE_ORDER, above.
+
+   Long-named options begin with `--' instead of `-'.
+   Their names may be abbreviated as long as the abbreviation is unique
+   or is an exact match for some defined option.  If they have an
+   argument, it follows the option name in the same ARGV-element, separated
+   from the option name by a `=', or else the in next ARGV-element.
+   When `getopt' finds a long-named option, it returns 0 if that option's
+   `flag' field is nonzero, the value of the option's `val' field
+   if the `flag' field is zero.
+
+   The elements of ARGV aren't really const, because we permute them.
+   But we pretend they're const in the prototype to be compatible
+   with other systems.
+
+   LONGOPTS is a vector of `struct option' terminated by an
+   element containing a name which is zero.
+
+   LONGIND returns the index in LONGOPT of the long-named option found.
+   It is only valid when a long-named option has been found by the most
+   recent call.
+
+   If LONG_ONLY is nonzero, '-' as well as '--' can introduce
+   long-named options.  */
+
+int
+_getopt_internal (argc, argv, optstring, longopts, longind, long_only)
+     int argc;
+     char *const *argv;
+     const char *optstring;
+     const struct option *longopts;
+     int *longind;
+     int long_only;
+{
+  optarg = NULL;
+
+  if (optind == 0)
+    optstring = _getopt_initialize (optstring);
+
+  if (nextchar == NULL || *nextchar == '\0')
+    {
+      /* Advance to the next ARGV-element.  */
+
+      if (ordering == PERMUTE)
+       {
+         /* If we have just processed some options following some non-options,
+            exchange them so that the options come first.  */
+
+         if (first_nonopt != last_nonopt && last_nonopt != optind)
+           exchange ((char **) argv);
+         else if (last_nonopt != optind)
+           first_nonopt = optind;
+
+         /* Skip any additional non-options
+            and extend the range of non-options previously skipped.  */
+
+         while (optind < argc
+                && (argv[optind][0] != '-' || argv[optind][1] == '\0'))
+           optind++;
+         last_nonopt = optind;
+       }
+
+      /* The special ARGV-element `--' means premature end of options.
+        Skip it like a null option,
+        then exchange with previous non-options as if it were an option,
+        then skip everything else like a non-option.  */
+
+      if (optind != argc && !strcmp (argv[optind], "--"))
+       {
+         optind++;
+
+         if (first_nonopt != last_nonopt && last_nonopt != optind)
+           exchange ((char **) argv);
+         else if (first_nonopt == last_nonopt)
+           first_nonopt = optind;
+         last_nonopt = argc;
+
+         optind = argc;
+       }
+
+      /* If we have done all the ARGV-elements, stop the scan
+        and back over any non-options that we skipped and permuted.  */
+
+      if (optind == argc)
+       {
+         /* Set the next-arg-index to point at the non-options
+            that we previously skipped, so the caller will digest them.  */
+         if (first_nonopt != last_nonopt)
+           optind = first_nonopt;
+         return EOF;
+       }
+
+      /* If we have come to a non-option and did not permute it,
+        either stop the scan or describe it to the caller and pass it by.  */
+
+      if ((argv[optind][0] != '-' || argv[optind][1] == '\0'))
+       {
+         if (ordering == REQUIRE_ORDER)
+           return EOF;
+         optarg = argv[optind++];
+         return 1;
+       }
+
+      /* We have found another option-ARGV-element.
+        Skip the initial punctuation.  */
+
+      nextchar = (argv[optind] + 1
+                 + (longopts != NULL && argv[optind][1] == '-'));
+    }
+
+  /* Decode the current option-ARGV-element.  */
+
+  /* Check whether the ARGV-element is a long option.
+
+     If long_only and the ARGV-element has the form "-f", where f is
+     a valid short option, don't consider it an abbreviated form of
+     a long option that starts with f.  Otherwise there would be no
+     way to give the -f short option.
+
+     On the other hand, if there's a long option "fubar" and
+     the ARGV-element is "-fu", do consider that an abbreviation of
+     the long option, just like "--fu", and not "-f" with arg "u".
+
+     This distinction seems to be the most useful approach.  */
+
+  if (longopts != NULL
+      && (argv[optind][1] == '-'
+         || (long_only && (argv[optind][2] || !my_index (optstring, argv[optind][1])))))
+    {
+      char *nameend;
+      const struct option *p;
+      const struct option *pfound = NULL;
+      int exact = 0;
+      int ambig = 0;
+      int indfound = 0; /* set to zero by Anton */
+      int option_index;
+
+      for (nameend = nextchar; *nameend && *nameend != '='; nameend++)
+       /* Do nothing.  */ ;
+
+      /* Test all long options for either exact match
+        or abbreviated matches.  */
+      for (p = longopts, option_index = 0; p->name; p++, option_index++)
+       if (!strncmp(p->name, nextchar, nameend - nextchar))
+         {
+           if ((unsigned int)(nameend - nextchar) == (unsigned int)strlen (p->name))
+             {
+               /* Exact match found.  */
+               pfound = p;
+               indfound = option_index;
+               exact = 1;
+               break;
+             }
+           else if (pfound == NULL)
+             {
+               /* First nonexact match found.  */
+               pfound = p;
+               indfound = option_index;
+             }
+           else
+             /* Second or later nonexact match found.  */
+             ambig = 1;
+         }
+
+      if (ambig && !exact)
+       {
+         if (opterr)
+           fprintf (stderr, "%s: option `%s' is ambiguous\n",
+                    argv[0], argv[optind]);
+         nextchar += strlen (nextchar);
+         optind++;
+         return '?';
+       }
+
+      if (pfound != NULL)
+       {
+         option_index = indfound;
+         optind++;
+         if (*nameend)
+           {
+             /* Don't test has_arg with >, because some C compilers don't
+                allow it to be used on enums.  */
+             if (pfound->has_arg)
+               optarg = nameend + 1;
+             else
+               {
+                 if (opterr)
+                   {
+                     if (argv[optind - 1][1] == '-')
+                       /* --option */
+                       fprintf (stderr,
+                                "%s: option `--%s' doesn't allow an argument\n",
+                                argv[0], pfound->name);
+                     else
+                       /* +option or -option */
+                       fprintf (stderr,
+                            "%s: option `%c%s' doesn't allow an argument\n",
+                            argv[0], argv[optind - 1][0], pfound->name);
+                   }
+                 nextchar += strlen (nextchar);
+                 return '?';
+               }
+           }
+         else if (pfound->has_arg == 1)
+           {
+             if (optind < argc)
+               optarg = argv[optind++];
+             else
+               {
+                 if (opterr)
+                   fprintf (stderr, "%s: option `%s' requires an argument\n",
+                            argv[0], argv[optind - 1]);
+                 nextchar += strlen (nextchar);
+                 return optstring[0] == ':' ? ':' : '?';
+               }
+           }
+         nextchar += strlen (nextchar);
+         if (longind != NULL)
+           *longind = option_index;
+         if (pfound->flag)
+           {
+             *(pfound->flag) = pfound->val;
+             return 0;
+           }
+         return pfound->val;
+       }
+
+      /* Can't find it as a long option.  If this is not getopt_long_only,
+        or the option starts with '--' or is not a valid short
+        option, then it's an error.
+        Otherwise interpret it as a short option.  */
+      if (!long_only || argv[optind][1] == '-'
+         || my_index (optstring, *nextchar) == NULL)
+       {
+         if (opterr)
+           {
+             if (argv[optind][1] == '-')
+               /* --option */
+               fprintf (stderr, "%s: unrecognized option `--%s'\n",
+                        argv[0], nextchar);
+             else
+               /* +option or -option */
+               fprintf (stderr, "%s: unrecognized option `%c%s'\n",
+                        argv[0], argv[optind][0], nextchar);
+           }
+         nextchar = (char *) "";
+         optind++;
+         return '?';
+       }
+    }
+
+  /* Look at and handle the next short option-character.  */
+
+  {
+    char c = *nextchar++;
+    char *temp = my_index (optstring, c);
+
+    /* Increment `optind' when we start to process its last character.  */
+    if (*nextchar == '\0')
+      ++optind;
+
+    if (temp == NULL || c == ':')
+      {
+       if (opterr)
+         {
+           if (posixly_correct)
+             /* 1003.2 specifies the format of this message.  */
+             fprintf (stderr, "%s: illegal option -- %c\n", argv[0], c);
+           else
+             fprintf (stderr, "%s: invalid option -- %c\n", argv[0], c);
+         }
+       optopt = c;
+       return '?';
+      }
+    if (temp[1] == ':')
+      {
+       if (temp[2] == ':')
+         {
+           /* This is an option that accepts an argument optionally.  */
+           if (*nextchar != '\0')
+             {
+               optarg = nextchar;
+               optind++;
+             }
+           else
+             optarg = NULL;
+           nextchar = NULL;
+         }
+       else
+         {
+           /* This is an option that requires an argument.  */
+           if (*nextchar != '\0')
+             {
+               optarg = nextchar;
+               /* If we end this ARGV-element by taking the rest as an arg,
+                  we must advance to the next element now.  */
+               optind++;
+             }
+           else if (optind == argc)
+             {
+               if (opterr)
+                 {
+                   /* 1003.2 specifies the format of this message.  */
+                   fprintf (stderr, "%s: option requires an argument -- %c\n",
+                            argv[0], c);
+                 }
+               optopt = c;
+               if (optstring[0] == ':')
+                 c = ':';
+               else
+                 c = '?';
+             }
+           else
+             /* We already incremented `optind' once;
+                increment it again when taking next ARGV-elt as argument.  */
+             optarg = argv[optind++];
+           nextchar = NULL;
+         }
+      }
+    return c;
+  }
+}
+
+int
+getopt (argc, argv, optstring)
+     int argc;
+     char *const *argv;
+     const char *optstring;
+{
+  return _getopt_internal (argc, argv, optstring,
+                          (const struct option *) 0,
+                          (int *) 0,
+                          0);
+}
+
+#endif /* _LIBC or not __GNU_LIBRARY__.  */
+\f
+#ifdef TEST
+
+/* Compile with -DTEST to make an executable for use in testing
+   the above definition of `getopt'.  */
+
+int
+main (argc, argv)
+     int argc;
+     char **argv;
+{
+  int c;
+  int digit_optind = 0;
+
+  while (1)
+    {
+      int this_option_optind = optind ? optind : 1;
+
+      c = getopt (argc, argv, "abc:d:0123456789");
+      if (c == EOF)
+       break;
+
+      switch (c)
+       {
+       case '0':
+       case '1':
+       case '2':
+       case '3':
+       case '4':
+       case '5':
+       case '6':
+       case '7':
+       case '8':
+       case '9':
+         if (digit_optind != 0 && digit_optind != this_option_optind)
+           printf ("digits occur in two different argv-elements.\n");
+         digit_optind = this_option_optind;
+         printf ("option %c\n", c);
+         break;
+
+       case 'a':
+         printf ("option a\n");
+         break;
+
+       case 'b':
+         printf ("option b\n");
+         break;
+
+       case 'c':
+         printf ("option c with value `%s'\n", optarg);
+         break;
+
+       case '?':
+         break;
+
+       default:
+         printf ("?? getopt returned character code 0%o ??\n", c);
+       }
+    }
+
+  if (optind < argc)
+    {
+      printf ("non-option ARGV-elements: ");
+      while (optind < argc)
+       printf ("%s ", argv[optind++]);
+      printf ("\n");
+    }
+
+  exit (0);
+}
+
+#endif /* TEST */
diff --git a/examples/LDAP/smbldap-tools/mkntpwd/getopt.h b/examples/LDAP/smbldap-tools/mkntpwd/getopt.h
new file mode 100644 (file)
index 0000000..f3696d9
--- /dev/null
@@ -0,0 +1,133 @@
+/* Declarations for getopt.
+   Copyright (C) 1989, 90, 91, 92, 93, 94 Free Software Foundation, Inc.
+
+This file is part of the GNU C Library.  Its master source is NOT part of
+the C library, however.  The master source lives in /gd/gnu/lib.
+
+The GNU C Library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Library General Public License as
+published by the Free Software Foundation; either version 2 of the
+License, or (at your option) any later version.
+
+The GNU C Library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with the GNU C Library; see the file COPYING.LIB.  If
+not, write to the Free Software Foundation, Inc., 675 Mass Ave,
+Cambridge, MA 02139, USA.  */
+
+#ifndef _GETOPT_H
+#define _GETOPT_H 1
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* For communication from `getopt' to the caller.
+   When `getopt' finds an option that takes an argument,
+   the argument value is returned here.
+   Also, when `ordering' is RETURN_IN_ORDER,
+   each non-option ARGV-element is returned here.  */
+
+extern char *optarg;
+
+/* Index in ARGV of the next element to be scanned.
+   This is used for communication to and from the caller
+   and for communication between successive calls to `getopt'.
+
+   On entry to `getopt', zero means this is the first call; initialize.
+
+   When `getopt' returns EOF, this is the index of the first of the
+   non-option elements that the caller should itself scan.
+
+   Otherwise, `optind' communicates from one call to the next
+   how much of ARGV has been scanned so far.  */
+
+extern int optind;
+
+/* Callers store zero here to inhibit the error message `getopt' prints
+   for unrecognized options.  */
+
+extern int opterr;
+
+/* Set to an option character which was unrecognized.  */
+
+extern int optopt;
+
+/* Describe the long-named options requested by the application.
+   The LONG_OPTIONS argument to getopt_long or getopt_long_only is a vector
+   of `struct option' terminated by an element containing a name which is
+   zero.
+
+   The field `has_arg' is:
+   no_argument         (or 0) if the option does not take an argument,
+   required_argument   (or 1) if the option requires an argument,
+   optional_argument   (or 2) if the option takes an optional argument.
+
+   If the field `flag' is not NULL, it points to a variable that is set
+   to the value given in the field `val' when the option is found, but
+   left unchanged if the option is not found.
+
+   To have a long-named option do something other than set an `int' to
+   a compiled-in constant, such as set a value from `optarg', set the
+   option's `flag' field to zero and its `val' field to a nonzero
+   value (the equivalent single-letter option character, if there is
+   one).  For long options that have a zero `flag' field, `getopt'
+   returns the contents of the `val' field.  */
+
+struct option
+{
+#if defined (__STDC__) && __STDC__
+  const char *name;
+#else
+  char *name;
+#endif
+  /* has_arg can't be an enum because some compilers complain about
+     type mismatches in all the code that assumes it is an int.  */
+  int has_arg;
+  int *flag;
+  int val;
+};
+
+/* Names for the values of the `has_arg' field of `struct option'.  */
+
+#define        no_argument             0
+#define required_argument      1
+#define optional_argument      2
+
+#if defined (__STDC__) && __STDC__
+#ifdef __GNU_LIBRARY__
+/* Many other libraries have conflicting prototypes for getopt, with
+   differences in the consts, in stdlib.h.  To avoid compilation
+   errors, only prototype getopt for the GNU C library.  */
+extern int getopt (int argc, char *const *argv, const char *shortopts);
+#else /* not __GNU_LIBRARY__ */
+extern int getopt ();
+#endif /* __GNU_LIBRARY__ */
+extern int getopt_long (int argc, char *const *argv, const char *shortopts,
+                       const struct option *longopts, int *longind);
+extern int getopt_long_only (int argc, char *const *argv,
+                            const char *shortopts,
+                            const struct option *longopts, int *longind);
+
+/* Internal only.  Users should not call this directly.  */
+extern int _getopt_internal (int argc, char *const *argv,
+                            const char *shortopts,
+                            const struct option *longopts, int *longind,
+                            int long_only);
+#else /* not __STDC__ */
+extern int getopt ();
+extern int getopt_long ();
+extern int getopt_long_only ();
+
+extern int _getopt_internal ();
+#endif /* __STDC__ */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _GETOPT_H */
diff --git a/examples/LDAP/smbldap-tools/mkntpwd/md4.c b/examples/LDAP/smbldap-tools/mkntpwd/md4.c
new file mode 100644 (file)
index 0000000..1c9c2e6
--- /dev/null
@@ -0,0 +1,171 @@
+/* 
+   Unix SMB/Netbios implementation.
+   Version 1.9.
+   a implementation of MD4 designed for use in the SMB authentication protocol
+   Copyright (C) Andrew Tridgell 1997
+   
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2 of the License, or
+   (at your option) any later version.
+   
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+   
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+
+/* NOTE: This code makes no attempt to be fast! 
+
+   It assumes that a int is at least 32 bits long
+*/
+
+typedef unsigned int uint32;
+
+static uint32 A, B, C, D;
+
+static uint32 F(uint32 X, uint32 Y, uint32 Z)
+{
+       return (X&Y) | ((~X)&Z);
+}
+
+static uint32 G(uint32 X, uint32 Y, uint32 Z)
+{
+       return (X&Y) | (X&Z) | (Y&Z); 
+}
+
+static uint32 H(uint32 X, uint32 Y, uint32 Z)
+{
+       return X^Y^Z;
+}
+
+static uint32 lshift(uint32 x, int s)
+{
+       x &= 0xFFFFFFFF;
+       return ((x<<s)&0xFFFFFFFF) | (x>>(32-s));
+}
+
+#define ROUND1(a,b,c,d,k,s) a = lshift(a + F(b,c,d) + X[k], s)
+#define ROUND2(a,b,c,d,k,s) a = lshift(a + G(b,c,d) + X[k] + (uint32)0x5A827999,s)
+#define ROUND3(a,b,c,d,k,s) a = lshift(a + H(b,c,d) + X[k] + (uint32)0x6ED9EBA1,s)
+
+/* this applies md4 to 64 byte chunks */
+static void mdfour64(uint32 *M)
+{
+       int j;
+       uint32 AA, BB, CC, DD;
+       uint32 X[16];
+
+       for (j=0;j<16;j++)
+               X[j] = M[j];
+
+       AA = A; BB = B; CC = C; DD = D;
+
+        ROUND1(A,B,C,D,  0,  3);  ROUND1(D,A,B,C,  1,  7);  
+       ROUND1(C,D,A,B,  2, 11);  ROUND1(B,C,D,A,  3, 19);
+        ROUND1(A,B,C,D,  4,  3);  ROUND1(D,A,B,C,  5,  7);  
+       ROUND1(C,D,A,B,  6, 11);  ROUND1(B,C,D,A,  7, 19);
+        ROUND1(A,B,C,D,  8,  3);  ROUND1(D,A,B,C,  9,  7);  
+       ROUND1(C,D,A,B, 10, 11);  ROUND1(B,C,D,A, 11, 19);
+        ROUND1(A,B,C,D, 12,  3);  ROUND1(D,A,B,C, 13,  7);  
+       ROUND1(C,D,A,B, 14, 11);  ROUND1(B,C,D,A, 15, 19);      
+
+        ROUND2(A,B,C,D,  0,  3);  ROUND2(D,A,B,C,  4,  5);  
+       ROUND2(C,D,A,B,  8,  9);  ROUND2(B,C,D,A, 12, 13);
+        ROUND2(A,B,C,D,  1,  3);  ROUND2(D,A,B,C,  5,  5);  
+       ROUND2(C,D,A,B,  9,  9);  ROUND2(B,C,D,A, 13, 13);
+        ROUND2(A,B,C,D,  2,  3);  ROUND2(D,A,B,C,  6,  5);  
+       ROUND2(C,D,A,B, 10,  9);  ROUND2(B,C,D,A, 14, 13);
+        ROUND2(A,B,C,D,  3,  3);  ROUND2(D,A,B,C,  7,  5);  
+       ROUND2(C,D,A,B, 11,  9);  ROUND2(B,C,D,A, 15, 13);
+
+       ROUND3(A,B,C,D,  0,  3);  ROUND3(D,A,B,C,  8,  9);  
+       ROUND3(C,D,A,B,  4, 11);  ROUND3(B,C,D,A, 12, 15);
+        ROUND3(A,B,C,D,  2,  3);  ROUND3(D,A,B,C, 10,  9);  
+       ROUND3(C,D,A,B,  6, 11);  ROUND3(B,C,D,A, 14, 15);
+        ROUND3(A,B,C,D,  1,  3);  ROUND3(D,A,B,C,  9,  9);  
+       ROUND3(C,D,A,B,  5, 11);  ROUND3(B,C,D,A, 13, 15);
+        ROUND3(A,B,C,D,  3,  3);  ROUND3(D,A,B,C, 11,  9);  
+       ROUND3(C,D,A,B,  7, 11);  ROUND3(B,C,D,A, 15, 15);
+
+       A += AA; B += BB; C += CC; D += DD;
+       
+       A &= 0xFFFFFFFF; B &= 0xFFFFFFFF;
+       C &= 0xFFFFFFFF; D &= 0xFFFFFFFF;
+
+       for (j=0;j<16;j++)
+               X[j] = 0;
+}
+
+static void copy64(uint32 *M, unsigned char *in)
+{
+       int i;
+
+       for (i=0;i<16;i++)
+               M[i] = (in[i*4+3]<<24) | (in[i*4+2]<<16) |
+                       (in[i*4+1]<<8) | (in[i*4+0]<<0);
+}
+
+static void copy4(unsigned char *out,uint32 x)
+{
+       out[0] = x&0xFF;
+       out[1] = (x>>8)&0xFF;
+       out[2] = (x>>16)&0xFF;
+       out[3] = (x>>24)&0xFF;
+}
+
+/* produce a md4 message digest from data of length n bytes */
+void mdfour(unsigned char *out, unsigned char *in, int n)
+{
+       unsigned char buf[128];
+       uint32 M[16];
+       uint32 b = n * 8;
+       int i;
+
+       A = 0x67452301;
+       B = 0xefcdab89;
+       C = 0x98badcfe;
+       D = 0x10325476;
+
+       while (n > 64) {
+               copy64(M, in);
+               mdfour64(M);
+               in += 64;
+               n -= 64;
+       }
+
+       for (i=0;i<128;i++)
+               buf[i] = 0;
+       memcpy(buf, in, n);
+       buf[n] = 0x80;
+       
+       if (n <= 55) {
+               copy4(buf+56, b);
+               copy64(M, buf);
+               mdfour64(M);
+       } else {
+               copy4(buf+120, b); 
+               copy64(M, buf);
+               mdfour64(M);
+               copy64(M, buf+64);
+               mdfour64(M);
+       }
+
+       for (i=0;i<128;i++)
+               buf[i] = 0;
+       copy64(M, buf);
+
+       copy4(out, A);
+       copy4(out+4, B);
+       copy4(out+8, C);
+       copy4(out+12, D);
+
+       A = B = C = D = 0;
+}
+
+
diff --git a/examples/LDAP/smbldap-tools/mkntpwd/mkntpwd.c b/examples/LDAP/smbldap-tools/mkntpwd/mkntpwd.c
new file mode 100644 (file)
index 0000000..0c7d61e
--- /dev/null
@@ -0,0 +1,253 @@
+/*
+       This code is based on work from 
+       L0phtcrack 1.5 06.02.97 mudge@l0pht.com
+
+       The code also contains sources from:
+                . routines from the samba code source
+                 md4.c smbdes.c
+
+       Anton Roeckseisen (anton@genua.de)
+
+*/
+
+/*
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "mkntpwd.h"
+
+void str_to_key(unsigned char *,unsigned char *);
+void usage(char *);
+int PutUniCode(char *dst,char *src);
+void printlanhash(char *tmp);
+void mdfour(unsigned char *out, unsigned char *in, int n);
+void E_P16(unsigned char *p14,unsigned char *p16);
+
+
+void main(int argc, char **argv) {
+       extern char *optarg;
+       int c;
+
+       int printlan = 0;
+       char lanpwd[LMPASSWDLEN+1];
+       int printnt = 0;
+       char inputfile[FILENAMEBUFFER+1] = "";
+       FILE* InputFilePtr;
+       int just_pwd = 0;
+       int i;
+       char hashout[17];
+
+       char ntpasswd[NTPASSWDLEN+1]; 
+       char *hold;
+       unsigned char *p16;
+       int uni_len;
+       char passwd[NTPASSWDLEN+1];
+
+       if (argc==1)
+               usage(argv[0]);
+
+       if (argc==2)
+               just_pwd=1;
+       else
+               just_pwd=0;
+
+       lanpwd[0] = '\0';
+       ntpasswd[0] = '\0';
+
+       while ( (c = getopt(argc, argv, "L:N:f:")) != EOF){
+               switch(c) {
+               case 'L':
+                       printlan++;
+                       strncpy(lanpwd,optarg,LMPASSWDLEN);
+                       lanpwd[LMPASSWDLEN]='\0';
+                       for (i=0;i<LMPASSWDLEN;i++)
+                               lanpwd[i]=toupper(lanpwd[i]);
+                       break;
+               case 'N':
+                       printnt++;
+                       strncpy(passwd,optarg,NTPASSWDLEN);
+                       passwd[NTPASSWDLEN]='\0';
+                       break;
+               case 'f': 
+                       strncpy(inputfile,optarg,FILENAMEBUFFER);
+                       inputfile[FILENAMEBUFFER]='\0';
+                       break;
+               default:
+                       usage(argv[0]);
+               }
+       }
+
+       /* Get password from file or STDIN */
+       if (inputfile[0]!='\0') {
+
+               just_pwd=0; /* make sure no shit is happening... */
+
+               /* get NT-password (longer) */
+               if (strcmp(inputfile,"-")==0) {
+                       fgets(passwd,NTPASSWDLEN,stdin);
+               } else {
+                       if ((InputFilePtr=fopen(inputfile,"r")) == NULL)
+                               fprintf(stderr,"Couldn't open passwordfile: %s",inputfile) ;
+                       fgets(passwd,NTPASSWDLEN,InputFilePtr);
+                       fclose(InputFilePtr);
+               }
+               while (strlen(passwd)>0 && passwd[strlen(passwd)-1]=='\n')
+                       passwd[strlen(passwd)-1]='\0';
+
+               /* create LANMAN-password (shorter) */
+               strncpy(lanpwd,passwd,LMPASSWDLEN);
+               lanpwd[LMPASSWDLEN]='\0';
+               for (i=0;i<LMPASSWDLEN;i++)
+                       lanpwd[i]=toupper(lanpwd[i]);
+               printlan++;
+               printnt++;
+
+       }
+
+
+       /* Assume the one and only Arg is the new password! */
+
+       if (argc>1 && just_pwd==1) { 
+                strncpy(lanpwd,argv[1],LMPASSWDLEN);
+               lanpwd[LMPASSWDLEN]='\0';
+               for (i=0;i<LMPASSWDLEN;i++)
+                       lanpwd[i]=toupper(lanpwd[i]);
+               printlan++;
+
+               strncpy(passwd,argv[1],NTPASSWDLEN);
+               passwd[NTPASSWDLEN]='\0';
+               printnt++;
+       }
+
+       if (printlan >0) {
+               memset(hashout,'\0',17);
+               E_P16((uchar *)lanpwd,hashout);
+               printlanhash(hashout);
+       }
+
+       if (printnt >0) {
+
+               if (printlan>0) printf(":");
+
+               memset(ntpasswd, '\0', sizeof(ntpasswd));
+
+               if (passwd[strlen(passwd)-1] == '\n') /* strip the \n - this 
+                                       is done in LowerString for the case sensitive
+                                       check */
+               passwd[strlen(passwd)-1] = '\0';
+
+               hold = (char *)malloc(NTPASSWDLEN * 2); /* grab space for 
+                                                      unicode */
+               if (hold == NULL){
+                       fprintf(stderr, "out of memory...crackntdialog hold\n");
+                       exit(1);
+               }
+
+               uni_len = PutUniCode(hold, passwd); /* convert to 
+                                                  unicode and return correct 
+                                                  unicode length for md4 */
+
+               p16 = (unsigned char*)malloc(17); /* grab space for md4 hash */
+               if (p16 == NULL){
+                     fprintf(stderr, "out of memory...crackntdialect p16\n");
+                     exit(1);
+               }
+               
+               memset(p16,'\0',17);
+               mdfour(p16,hold, uni_len);
+
+               printlanhash(p16);
+                   
+               free(p16);
+               free(hold);
+       }
+
+       printf("\n");
+
+       exit(0);
+
+}
+
+/*****************************************************************************/
+/*****************************************************************************/
+/*****************************************************************************/
+
+void usage(char *progname){
+   char *p;
+
+   p = strrchr(progname, '\\');
+   if (p == NULL)
+        p = progname;
+   else
+        p++;
+
+   fprintf(stderr, "Usage: %s [-L lanmgrpwd] [-N ntpasswd]\n",p);
+   fprintf(stderr, "       %s password\n",p);
+   fprintf(stderr, "       %s -f [-] [filename]\n\n",p);
+   fprintf(stderr, "     -L lanmgrpasswd  LanManager cleartextpwd <= 14 chars\n");
+   fprintf(stderr, "     -N ntpasswd      NT cleartextpwd <=128 chars (usually <=14)\n\n");
+   fprintf(stderr, "     with both options present the encrypted LanManager-Pwd is \n");
+   fprintf(stderr, "     printed first, followed by a ':' and the encrypted NT-Pwd.\n\n");
+   fprintf(stderr, "     The second usage behaves like %s -L pwd -N pwd\n\n",p);
+   fprintf(stderr, "     The third usage reads the password from STDIN or a File. Printout\n");
+   fprintf(stderr, "     is the same as second.\n\n");
+   fprintf(stderr, "anton@genua.de\n\n");
+   exit(1);
+}
+
+
+/*******************************************************************
+write a string in unicoode format
+********************************************************************/
+int PutUniCode(char *dst,char *src) 
+{                       
+  int ret = 0;  
+  while (*src) {
+    dst[ret++] = src[0];
+    dst[ret++] = 0;
+    src++;
+  }
+  dst[ret++]=0; 
+  dst[ret++]=0; 
+  return(ret-2); /* the way they do the md4 hash they don't represent
+                    the last null. ie 'A' becomes just 0x41 0x00 - not
+                    0x41 0x00 0x00 0x00 */
+}
+
+/*
+  print binary buffer as hex-string
+*/
+void printlanhash(char *tmp) {
+
+       int i;
+       unsigned char c;
+       char outbuffer[33];
+
+
+       /* build string from binary hash */
+       for(i=0;i<16;i++) {
+               c=tmp[i];
+               sprintf(outbuffer+2*i,"%x",(c>>4) & 0x0f);
+               sprintf(outbuffer+2*i+1,"%x",c & 0x0f);
+       }
+
+       /* convert to uppercase */
+       for(i=0;i<32;i++)
+               outbuffer[i] = toupper(outbuffer[i]);
+       outbuffer[32]='\0';
+
+       /* print out hex-string */
+       printf("%s",outbuffer);
+}
+
+
diff --git a/examples/LDAP/smbldap-tools/mkntpwd/mkntpwd.h b/examples/LDAP/smbldap-tools/mkntpwd/mkntpwd.h
new file mode 100644 (file)
index 0000000..9a020b8
--- /dev/null
@@ -0,0 +1,17 @@
+#include <memory.h>
+#include <string.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <ctype.h>
+
+typedef short int16;
+typedef int int32;
+typedef unsigned short uint16;
+typedef unsigned int uint32;
+typedef unsigned char uchar;
+
+#define MAX_STRING 255
+#define MAX_WORD 128
+#define LMPASSWDLEN 14
+#define NTPASSWDLEN 128
+#define FILENAMEBUFFER 128
diff --git a/examples/LDAP/smbldap-tools/mkntpwd/smbdes.c b/examples/LDAP/smbldap-tools/mkntpwd/smbdes.c
new file mode 100644 (file)
index 0000000..e4f8280
--- /dev/null
@@ -0,0 +1,337 @@
+/* 
+   Unix SMB/Netbios implementation.
+   Version 1.9.
+
+   a partial implementation of DES designed for use in the 
+   SMB authentication protocol
+
+   Copyright (C) Andrew Tridgell 1997
+   
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2 of the License, or
+   (at your option) any later version.
+   
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+   
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+
+/* NOTES: 
+
+   This code makes no attempt to be fast! In fact, it is a very
+   slow implementation 
+
+   This code is NOT a complete DES implementation. It implements only
+   the minimum necessary for SMB authentication, as used by all SMB
+   products (including every copy of Microsoft Windows95 ever sold)
+
+   In particular, it can only do a unchained forward DES pass. This
+   means it is not possible to use this code for encryption/decryption
+   of data, instead it is only useful as a "hash" algorithm.
+
+   There is no entry point into this code that allows normal DES operation.
+
+   I believe this means that this code does not come under ITAR
+   regulations but this is NOT a legal opinion. If you are concerned
+   about the applicability of ITAR regulations to this code then you
+   should confirm it for yourself (and maybe let me know if you come
+   up with a different answer to the one above)
+*/
+
+
+
+static int perm1[56] = {57, 49, 41, 33, 25, 17,  9,
+                        1, 58, 50, 42, 34, 26, 18,
+                       10,  2, 59, 51, 43, 35, 27,
+                       19, 11,  3, 60, 52, 44, 36,
+                       63, 55, 47, 39, 31, 23, 15,
+                        7, 62, 54, 46, 38, 30, 22,
+                       14,  6, 61, 53, 45, 37, 29,
+                       21, 13,  5, 28, 20, 12,  4};
+
+static int perm2[48] = {14, 17, 11, 24,  1,  5,
+                         3, 28, 15,  6, 21, 10,
+                        23, 19, 12,  4, 26,  8,
+                        16,  7, 27, 20, 13,  2,
+                        41, 52, 31, 37, 47, 55,
+                        30, 40, 51, 45, 33, 48,
+                        44, 49, 39, 56, 34, 53,
+                        46, 42, 50, 36, 29, 32};
+
+static int perm3[64] = {58, 50, 42, 34, 26, 18, 10,  2,
+                       60, 52, 44, 36, 28, 20, 12,  4,
+                       62, 54, 46, 38, 30, 22, 14,  6,
+                       64, 56, 48, 40, 32, 24, 16,  8,
+                       57, 49, 41, 33, 25, 17,  9,  1,
+                       59, 51, 43, 35, 27, 19, 11,  3,
+                       61, 53, 45, 37, 29, 21, 13,  5,
+                       63, 55, 47, 39, 31, 23, 15,  7};
+
+static int perm4[48] = {   32,  1,  2,  3,  4,  5,
+                            4,  5,  6,  7,  8,  9,
+                            8,  9, 10, 11, 12, 13,
+                           12, 13, 14, 15, 16, 17,
+                           16, 17, 18, 19, 20, 21,
+                           20, 21, 22, 23, 24, 25,
+                           24, 25, 26, 27, 28, 29,
+                           28, 29, 30, 31, 32,  1};
+
+static int perm5[32] = {      16,  7, 20, 21,
+                              29, 12, 28, 17,
+                               1, 15, 23, 26,
+                               5, 18, 31, 10,
+                               2,  8, 24, 14,
+                              32, 27,  3,  9,
+                              19, 13, 30,  6,
+                              22, 11,  4, 25};
+
+
+static int perm6[64] ={ 40,  8, 48, 16, 56, 24, 64, 32,
+                        39,  7, 47, 15, 55, 23, 63, 31,
+                        38,  6, 46, 14, 54, 22, 62, 30,
+                        37,  5, 45, 13, 53, 21, 61, 29,
+                        36,  4, 44, 12, 52, 20, 60, 28,
+                        35,  3, 43, 11, 51, 19, 59, 27,
+                        34,  2, 42, 10, 50, 18, 58, 26,
+                        33,  1, 41,  9, 49, 17, 57, 25};
+
+
+static int sc[16] = {1, 1, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 1};
+
+static int sbox[8][4][16] = {
+       {{14,  4, 13,  1,  2, 15, 11,  8,  3, 10,  6, 12,  5,  9,  0,  7},
+        {0, 15,  7,  4, 14,  2, 13,  1, 10,  6, 12, 11,  9,  5,  3,  8},
+        {4,  1, 14,  8, 13,  6,  2, 11, 15, 12,  9,  7,  3, 10,  5,  0},
+        {15, 12,  8,  2,  4,  9,  1,  7,  5, 11,  3, 14, 10,  0,  6, 13}},
+
+       {{15,  1,  8, 14,  6, 11,  3,  4,  9,  7,  2, 13, 12,  0,  5, 10},
+        {3, 13,  4,  7, 15,  2,  8, 14, 12,  0,  1, 10,  6,  9, 11,  5},
+        {0, 14,  7, 11, 10,  4, 13,  1,  5,  8, 12,  6,  9,  3,  2, 15},
+        {13,  8, 10,  1,  3, 15,  4,  2, 11,  6,  7, 12,  0,  5, 14,  9}},
+
+       {{10,  0,  9, 14,  6,  3, 15,  5,  1, 13, 12,  7, 11,  4,  2,  8},
+        {13,  7,  0,  9,  3,  4,  6, 10,  2,  8,  5, 14, 12, 11, 15,  1},
+        {13,  6,  4,  9,  8, 15,  3,  0, 11,  1,  2, 12,  5, 10, 14,  7},
+        {1, 10, 13,  0,  6,  9,  8,  7,  4, 15, 14,  3, 11,  5,  2, 12}},
+
+       {{7, 13, 14,  3,  0,  6,  9, 10,  1,  2,  8,  5, 11, 12,  4, 15},
+        {13,  8, 11,  5,  6, 15,  0,  3,  4,  7,  2, 12,  1, 10, 14,  9},
+        {10,  6,  9,  0, 12, 11,  7, 13, 15,  1,  3, 14,  5,  2,  8,  4},
+        {3, 15,  0,  6, 10,  1, 13,  8,  9,  4,  5, 11, 12,  7,  2, 14}},
+
+       {{2, 12,  4,  1,  7, 10, 11,  6,  8,  5,  3, 15, 13,  0, 14,  9},
+        {14, 11,  2, 12,  4,  7, 13,  1,  5,  0, 15, 10,  3,  9,  8,  6},
+        {4,  2,  1, 11, 10, 13,  7,  8, 15,  9, 12,  5,  6,  3,  0, 14},
+        {11,  8, 12,  7,  1, 14,  2, 13,  6, 15,  0,  9, 10,  4,  5,  3}},
+
+       {{12,  1, 10, 15,  9,  2,  6,  8,  0, 13,  3,  4, 14,  7,  5, 11},
+        {10, 15,  4,  2,  7, 12,  9,  5,  6,  1, 13, 14,  0, 11,  3,  8},
+        {9, 14, 15,  5,  2,  8, 12,  3,  7,  0,  4, 10,  1, 13, 11,  6},
+        {4,  3,  2, 12,  9,  5, 15, 10, 11, 14,  1,  7,  6,  0,  8, 13}},
+
+       {{4, 11,  2, 14, 15,  0,  8, 13,  3, 12,  9,  7,  5, 10,  6,  1},
+        {13,  0, 11,  7,  4,  9,  1, 10, 14,  3,  5, 12,  2, 15,  8,  6},
+        {1,  4, 11, 13, 12,  3,  7, 14, 10, 15,  6,  8,  0,  5,  9,  2},
+        {6, 11, 13,  8,  1,  4, 10,  7,  9,  5,  0, 15, 14,  2,  3, 12}},
+
+       {{13,  2,  8,  4,  6, 15, 11,  1, 10,  9,  3, 14,  5,  0, 12,  7},
+        {1, 15, 13,  8, 10,  3,  7,  4, 12,  5,  6, 11,  0, 14,  9,  2},
+        {7, 11,  4,  1,  9, 12, 14,  2,  0,  6, 10, 13, 15,  3,  5,  8},
+        {2,  1, 14,  7,  4, 10,  8, 13, 15, 12,  9,  0,  3,  5,  6, 11}}};
+
+static void permute(char *out, char *in, int *p, int n)
+{
+       int i;
+       for (i=0;i<n;i++)
+               out[i] = in[p[i]-1];
+}
+
+static void lshift(char *d, int count, int n)
+{
+       char out[64];
+       int i;
+       for (i=0;i<n;i++)
+               out[i] = d[(i+count)%n];
+       for (i=0;i<n;i++)
+               d[i] = out[i];
+}
+
+static void concat(char *out, char *in1, char *in2, int l1, int l2)
+{
+       while (l1--)
+               *out++ = *in1++;
+       while (l2--)
+               *out++ = *in2++;
+}
+
+static void xor(char *out, char *in1, char *in2, int n)
+{
+       int i;
+       for (i=0;i<n;i++)
+               out[i] = in1[i] ^ in2[i];
+}
+
+static void dohash(char *out, char *in, char *key)
+{
+       int i, j, k;
+       char pk1[56];
+       char c[28];
+       char d[28];
+       char cd[56];
+       char ki[16][48];
+       char pd1[64];
+       char l[32], r[32];
+       char rl[64];
+
+       permute(pk1, key, perm1, 56);
+
+       for (i=0;i<28;i++)
+               c[i] = pk1[i];
+       for (i=0;i<28;i++)
+               d[i] = pk1[i+28];
+
+       for (i=0;i<16;i++) {
+               lshift(c, sc[i], 28);
+               lshift(d, sc[i], 28);
+
+               concat(cd, c, d, 28, 28); 
+               permute(ki[i], cd, perm2, 48); 
+       }
+
+       permute(pd1, in, perm3, 64);
+
+       for (j=0;j<32;j++) {
+               l[j] = pd1[j];
+               r[j] = pd1[j+32];
+       }
+
+       for (i=0;i<16;i++) {
+               char er[48];
+               char erk[48];
+               char b[8][6];
+               char cb[32];
+               char pcb[32];
+               char r2[32];
+
+               permute(er, r, perm4, 48);
+
+               xor(erk, er, ki[i], 48);
+
+               for (j=0;j<8;j++)
+                       for (k=0;k<6;k++)
+                               b[j][k] = erk[j*6 + k];
+
+               for (j=0;j<8;j++) {
+                       int m, n;
+                       m = (b[j][0]<<1) | b[j][5];
+
+                       n = (b[j][1]<<3) | (b[j][2]<<2) | (b[j][3]<<1) | b[j][4]; 
+
+                       for (k=0;k<4;k++) 
+                               b[j][k] = (sbox[j][m][n] & (1<<(3-k)))?1:0; 
+               }
+
+               for (j=0;j<8;j++)
+                       for (k=0;k<4;k++)
+                               cb[j*4+k] = b[j][k];
+               permute(pcb, cb, perm5, 32);
+
+               xor(r2, l, pcb, 32);
+
+               for (j=0;j<32;j++)
+                       l[j] = r[j];
+
+               for (j=0;j<32;j++)
+                       r[j] = r2[j];
+       }
+
+       concat(rl, r, l, 32, 32);
+
+       permute(out, rl, perm6, 64);
+}
+
+static void str_to_key(unsigned char *str,unsigned char *key)
+{
+       int i;
+
+       key[0] = str[0]>>1;
+       key[1] = ((str[0]&0x01)<<6) | (str[1]>>2);
+       key[2] = ((str[1]&0x03)<<5) | (str[2]>>3);
+       key[3] = ((str[2]&0x07)<<4) | (str[3]>>4);
+       key[4] = ((str[3]&0x0F)<<3) | (str[4]>>5);
+       key[5] = ((str[4]&0x1F)<<2) | (str[5]>>6);
+       key[6] = ((str[5]&0x3F)<<1) | (str[6]>>7);
+       key[7] = str[6]&0x7F;
+       for (i=0;i<8;i++) {
+               key[i] = (key[i]<<1);
+       }
+}
+
+
+static void smbhash(unsigned char *out, unsigned char *in, unsigned char *key)
+{
+       int i;
+       char outb[64];
+       char inb[64];
+       char keyb[64];
+       unsigned char key2[8];
+
+       str_to_key(key, key2);
+
+       for (i=0;i<64;i++) {
+               inb[i] = (in[i/8] & (1<<(7-(i%8)))) ? 1 : 0;
+               keyb[i] = (key2[i/8] & (1<<(7-(i%8)))) ? 1 : 0;
+               outb[i] = 0;
+       }
+
+       dohash(outb, inb, keyb);
+
+       for (i=0;i<8;i++) {
+               out[i] = 0;
+       }
+
+       for (i=0;i<64;i++) {
+               if (outb[i])
+                       out[i/8] |= (1<<(7-(i%8)));
+       }
+}
+
+void E_P16(unsigned char *p14,unsigned char *p16)
+{
+       unsigned char sp8[8] = {0x4b, 0x47, 0x53, 0x21, 0x40, 0x23, 0x24, 0x25};
+       smbhash(p16, sp8, p14);
+       smbhash(p16+8, sp8, p14+7);
+}
+
+void E_P24(unsigned char *p21, unsigned char *c8, unsigned char *p24)
+{
+       smbhash(p24, c8, p21);
+       smbhash(p24+8, c8, p21+7);
+       smbhash(p24+16, c8, p21+14);
+}
+
+void cred_hash1(unsigned char *out,unsigned char *in,unsigned char *key)
+{
+       unsigned char buf[8];
+
+       smbhash(buf, in, key);
+       smbhash(out, buf, key+9);
+}
+
+void cred_hash2(unsigned char *out,unsigned char *in,unsigned char *key)
+{
+       unsigned char buf[8];
+       static unsigned char key2[8];
+
+       smbhash(buf, in, key);
+       key2[0] = key[7];
+       smbhash(out, buf, key2);
+}
+
diff --git a/examples/LDAP/smbldap-tools/smbldap-groupadd.pl b/examples/LDAP/smbldap-tools/smbldap-groupadd.pl
new file mode 100755 (executable)
index 0000000..ee804b3
--- /dev/null
@@ -0,0 +1,84 @@
+#!/usr/bin/perl 
+
+#  This code was developped by IDEALX (http://IDEALX.org/) and
+#  contributors (their names can be found in the CONTRIBUTORS file).
+#
+#                 Copyright (C) 2001-2002 IDEALX
+#
+#  This program is free software; you can redistribute it and/or
+#  modify it under the terms of the GNU General Public License
+#  as published by the Free Software Foundation; either version 2
+#  of the License, or (at your option) any later version.
+#
+#  This program is distributed in the hope that it will be useful,
+#  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#  GNU General Public License for more details.
+#
+#  You should have received a copy of the GNU General Public License
+#  along with this program; if not, write to the Free Software
+#  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+#  USA.
+
+# Purpose of smbldap-groupadd : group (posix) add
+
+use strict;
+use smbldap_tools;
+
+use Getopt::Std;
+my %Options;
+
+my $ok = getopts('og:?', \%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);
+}
+
+my $_groupName = $ARGV[0];
+
+if (defined(get_group_dn($_groupName))) {
+    print "$0: group $_groupName exists\n";
+    exit (6);
+}
+
+my $_groupGidNumber = $Options{'g'};
+
+if (!group_add($_groupName, $_groupGidNumber, $Options{'o'})) {
+    print "$0: error adding group $_groupName\n";
+    exit (6);
+}
+
+exit(0);
+
+########################################
+
+=head1 NAME
+
+       smbldap-groupadd.pl - Create a new group
+
+=head1 SYNOPSIS
+
+       smbldap-groupadd.pl [-g gid [-o]] group
+
+=head1 DESCRIPTION
+       The smbldap-groupadd.pl command creates a new group account using
+       the values specified on the command line and the default values
+       from the system. The new group will be entered into the system
+       files as needed. The options which apply to the groupadd command are
+
+       -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. The default is to use the smallest ID value greater
+              than 1000 and greater than every other group.
+
+=head1 SEE ALSO
+
+       groupadd(1)
+
+=cut
+
+#'
+
diff --git a/examples/LDAP/smbldap-tools/smbldap-groupdel.pl b/examples/LDAP/smbldap-tools/smbldap-groupdel.pl
new file mode 100755 (executable)
index 0000000..3d07258
--- /dev/null
@@ -0,0 +1,93 @@
+#!/usr/bin/perl 
+
+#  This code was developped by IDEALX (http://IDEALX.org/) and
+#  contributors (their names can be found in the CONTRIBUTORS file).
+#
+#                 Copyright (C) 2001-2002 IDEALX
+#
+#  This program is free software; you can redistribute it and/or
+#  modify it under the terms of the GNU General Public License
+#  as published by the Free Software Foundation; either version 2
+#  of the License, or (at your option) any later version.
+#
+#  This program is distributed in the hope that it will be useful,
+#  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#  GNU General Public License for more details.
+#
+#  You should have received a copy of the GNU General Public License
+#  along with this program; if not, write to the Free Software
+#  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+#  USA.
+
+# Purpose of smbldap-groupdel : group (posix) deletion
+
+use strict;
+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);
+}
+
+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);
+}
+
+my $dn = get_dn_from_line($dn_line);
+
+my $rc = system "$ldapdelete $dn >/dev/null";
+die "$0: error while deleting group $_groupName\n"
+    unless ($rc == 0);
+
+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";
+}
+
+#if (defined($dn_line = get_group_dn($_groupName))) {
+#    print "$0: failed to delete group\n";
+#    exit (7);
+#}
+
+
+exit (0);
+
+############################################################
+
+=head1 NAME
+
+       smbldap-groupdel.pl - Delete a group
+
+=head1 SYNOPSIS
+
+       smbldap-groupdel.pl group
+
+=head1 DESCRIPTION
+
+       The smbldap-groupdel.pl command modifies the system account files,
+       deleting all entries that refer to group. The named group must exist.
+
+       You must manually check all filesystems to insure that no files remain
+       with the named group as the file group ID.
+
+=head1 SEE ALSO
+
+       groupdel(1)
+
+=cut
+
+#'
diff --git a/examples/LDAP/smbldap-tools/smbldap-groupmod.pl b/examples/LDAP/smbldap-tools/smbldap-groupmod.pl
new file mode 100755 (executable)
index 0000000..7b5a46b
--- /dev/null
@@ -0,0 +1,209 @@
+#  This code was developped by IDEALX (http://IDEALX.org/) and
+#  contributors (their names can be found in the CONTRIBUTORS file).
+#
+#                 Copyright (C) 2001-2002 IDEALX
+#
+#  This program is free software; you can redistribute it and/or
+#  modify it under the terms of the GNU General Public License
+#  as published by the Free Software Foundation; either version 2
+#  of the License, or (at your option) any later version.
+#
+#  This program is distributed in the hope that it will be useful,
+#  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#  GNU General Public License for more details.
+#
+#  You should have received a copy of the GNU General Public License
+#  along with this program; if not, write to the Free Software
+#  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+#  USA.
+
+# Purpose of smbldap-groupmod : group (posix) modification
+
+
+use strict;
+use smbldap_tools;
+use smbldap_conf;
+
+
+#####################
+
+use Getopt::Std;
+my %Options;
+
+my $ok = getopts('og:n:m: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);
+}
+
+my $groupName = $ARGV[0];
+
+if (!defined(get_group_dn($groupName))) {
+    print "$0: group $groupName doesn't exist\n";
+    exit (6);
+}
+
+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";
+}
+
+my $gid = getgrnam($groupName);
+
+my $tmp;
+if (defined($tmp = $Options{'g'}) and $tmp =~ /\d+/) {
+    if (!defined($Options{'o'})) {
+       if (defined(getgrgid($tmp))) {
+           print "$0: gid $tmp exists\n";
+           exit (6);
+       }
+    }
+    if (!($gid == $tmp)) {
+       my $tmpldif =
+"dn: cn=$groupName,$groupsdn
+changetype: modify
+replace: gidNumber
+gidNumber: $tmp
+
+";
+       die "$0: error while modifying group $groupName\n"
+           unless (do_ldapmodify($tmpldif) == 0);
+       undef $tmpldif;
+
+    }
+}
+
+if (defined($newname)) {
+    my $FILE="|$ldapmodrdn >/dev/null";
+    open (FILE, $FILE) || die "$!\n";
+    print FILE <<EOF;
+cn=$groupName,$groupsdn
+cn=$newname
+
+EOF
+    ;
+    close FILE;
+    die "$0: error while modifying group $groupName\n" if ($?);
+
+    my $tmpldif =
+"dn: cn=$newname,$groupsdn
+changetype: modify
+delete: cn
+-
+add: cn
+cn: $newname
+
+";
+    die "$0: error while modifying group $groupName\n"
+       unless (do_ldapmodify($tmpldif) == 0);
+    undef $tmpldif;
+
+}
+
+# Add members
+if (defined($Options{'m'})) {
+       my $members = $Options{'m'};
+       my @members = split( /,/, $members );
+       my $member;
+       foreach $member ( @members ) {
+               my $tmpldif =
+"dn: cn=$groupName,$groupsdn
+changetype: modify
+add: memberUid
+memberUid: $member
+
+";
+               die "$0: error while modifying group $groupName\n"
+                       unless (do_ldapmodify($tmpldif) == 0);
+               undef $tmpldif;
+       }
+}
+
+# Delete members
+if (defined($Options{'x'})) {
+        my $members = $Options{'x'};
+        my @members = split( /,/, $members );
+        my $member;
+        foreach $member ( @members ) {
+                my $tmpldif =
+"dn: cn=$groupName,$groupsdn
+changetype: modify
+delete: memberUid
+memberUid: $member
+
+";
+                die "$0: error while modifying group $groupName\n"
+                        unless (do_ldapmodify($tmpldif) == 0);
+                undef $tmpldif;
+        }
+}
+
+$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";
+}
+
+exit (0);
+
+############################################################
+
+=head1 NAME
+
+       smbldap-groupmod.pl - Modify a group
+
+=head1 SYNOPSIS
+
+       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
+
+       -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.
+
+       -n group_name
+              The name of the group will be changed from group to group_name.
+
+       -m members
+             The members to be added to the group in comma-delimeted form.
+
+       -x members
+             The members to be removed from the group in comma-delimted form.
+
+=head1 EXAMPLES
+
+       smbldap-groupmod.pl -g 253 development
+             This will change the GID of the 'development' group to '253'.
+
+       smbldap-groupmod.pl -n Idiots Managers
+             This will change the name of the 'Managers' group to 'Idiots'.
+
+       smbldap-groupmod.pl -m "jdoe,jsmith" "Domain Admins"
+             This will add 'jdoe' and 'jsmith' to the 'Domain Admins' group.
+
+       smbldap-groupmod.pl -x "jdoe,jsmith" "Domain Admins"
+             This will remove 'jdoe' and 'jsmith' from the 'Domain Admins' group.
+
+=head1 SEE ALSO
+
+       groupmod(1)
+
+=cut
+
+#'
diff --git a/examples/LDAP/smbldap-tools/smbldap-groupshow.pl b/examples/LDAP/smbldap-tools/smbldap-groupshow.pl
new file mode 100755 (executable)
index 0000000..bc5b4d9
--- /dev/null
@@ -0,0 +1,72 @@
+#!/usr/bin/perl 
+
+#  This code was developped by IDEALX (http://IDEALX.org/) and
+#  contributors (their names can be found in the CONTRIBUTORS file).
+#
+#                 Copyright (C) 2001-2002 IDEALX
+#
+#  This program is free software; you can redistribute it and/or
+#  modify it under the terms of the GNU General Public License
+#  as published by the Free Software Foundation; either version 2
+#  of the License, or (at your option) any later version.
+#
+#  This program is distributed in the hope that it will be useful,
+#  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#  GNU General Public License for more details.
+#
+#  You should have received a copy of the GNU General Public License
+#  along with this program; if not, write to the Free Software
+#  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+#  USA.
+
+# Purpose of smbldap-groupshow : user (posix,shadow,samba) display
+#
+# History :
+#       . originally by David Le Corfec <david.le-corfec@IDEALX.com>
+
+use strict;
+use smbldap_tools;
+
+use Getopt::Std;
+my %Options;
+
+my $ok = getopts('?', \%Options);
+
+if ( (!$ok) || (@ARGV < 1) || ($Options{'?'}) ) {
+       print "Usage: $0 [-?] group\n";
+       print "  -?     show this help message\n";
+       exit (1);
+}
+
+# Read only first @ARGV
+my $group = $ARGV[0];
+
+my $lines = read_group($group);
+if (!defined($lines)) {
+    print "$0: group $group doesn't exist\n";
+    exit (1);
+}
+
+print "$lines\n";
+
+exit(0);
+
+############################################################
+
+=head1 NAME
+
+       smbldap-groupshow.pl - Display group informations
+
+=head1 SYNOPSIS
+
+       smbldap-groupshow.pl groupname
+
+=head1 DESCRIPTION
+
+       The smbldap-groupshow.pl command displays informations
+       associated with the given group.
+
+=cut
+
+#'
diff --git a/examples/LDAP/smbldap-tools/smbldap-migrate-accounts.pl b/examples/LDAP/smbldap-tools/smbldap-migrate-accounts.pl
new file mode 100755 (executable)
index 0000000..0d0efa3
--- /dev/null
@@ -0,0 +1,234 @@
+#!/usr/bin/perl
+
+#  This code was developped by IDEALX (http://IDEALX.org/) and
+#  contributors (their names can be found in the CONTRIBUTORS file).
+#
+#                 Copyright (C) 2002 IDEALX
+#
+#  This program is free software; you can redistribute it and/or
+#  modify it under the terms of the GNU General Public License
+#  as published by the Free Software Foundation; either version 2
+#  of the License, or (at your option) any later version.
+#
+#  This program is distributed in the hope that it will be useful,
+#  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#  GNU General Public License for more details.
+#
+#  You should have received a copy of the GNU General Public License
+#  along with this program; if not, write to the Free Software
+#  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+#  USA.
+
+# Purpose of smbldap-migrate-accounts : add NT sam entries from pwdump 
+#                                       to ldap
+
+use strict;
+use Getopt::Std;
+use smbldap_tools;
+use smbldap_conf;
+
+# smbldap-migrate.pl (-? for help)
+#
+# Read pwdump entries on stdin, and add them to the ldap server.
+# Output uncreated/unmodified entries (see parameters -C -U)
+# in pwdump format to stdout.
+# Errors, debug and stats are output to stderr.
+
+sub modify_account
+{
+  my ($login, $basedn, $lmpwd, $ntpwd, $gecos, $homedir) = @_;
+
+  my $tmpldif =
+"dn: uid=$login,$basedn
+changetype: modify
+lmpassword: $lmpwd
+ntpassword: $ntpwd
+gecos: $gecos
+sambaHomePath: $homedir
+
+";
+
+  die "$0: error while modifying user $login\n"
+      unless (do_ldapmodify($tmpldif) == 0);
+  undef $tmpldif;
+}
+
+#####################
+
+
+my %Options;
+
+my $ok = getopts('awA:CUW:?', \%Options);
+
+if ( (!$ok) || ($Options{'?'}) ) {
+        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 "  -?         show this help message\n";
+        exit (1);
+}
+
+my %processed = ( 'user' => 0, 'machine' => 0);
+my %created = ( 'user' => 0, 'machine' => 0);
+my %updated = ( 'user' => 0, 'machine' => 0);
+my %logged = ( 'user' => 0, 'machine' => 0);
+my %errors = ( 'user' => 0, 'machine' => 0);
+my %existing = ( 'user' => 0, 'machine' => 0);
+my $specialskipped = 0;
+
+while (<>)
+{
+  my ($login, $rid, $lmpwd, $ntpwd, $gecos, $homedir, $b) = split(/:/, $_);
+  my $usertype;
+  my $userbasedn;
+
+  my $entry_type = 'user';
+
+  if ($login =~ m/.*\$$/ ) { # computer
+    $processed{'machine'}++;
+    $entry_type = 'machine';
+    if (defined($Options{'a'})) {
+      print STDERR "ignoring $login\n";
+      next;
+    }
+    $usertype = "-w $Options{'W'}";
+    $userbasedn = $computersdn;
+  }
+  else { # people
+    $processed{'user'}++;
+    if (defined($Options{'w'})) {
+      print STDERR "ignoring $login\n";
+      next;
+    }
+    if ($rid < 1000) {
+      $specialskipped++;
+      print STDERR "$login seems to be a special Win account (rid=$rid), skipping\n";
+      next;
+    }
+
+    $usertype = "-a $Options{'A'}";
+    $userbasedn = $usersdn;
+  }
+
+  # normalize homedir
+# uncomment to replace configured share with share from pwdump
+#  if ($homedir eq "") {
+    $homedir = $_userSmbHome;
+#  }
+
+  # normalize gecos
+  if (!($gecos eq "")) {
+    $gecos =~ tr/ÁÀÂÄáàâäÇçÉÈÊËÆéèêëæÍÌÏÎíìîÏÑñÓÒÔÖóòôöÚÙÜÛúùüûÝýÿ/AAAAaaaaCcEEEEEeeeeeIIIIiiiiNnOOOOooooUUUUuuuuYyy/;
+  } else {
+    $gecos = $_userGecos;
+  }
+
+  my $user_exists = is_samba_user($login);
+  if (!$user_exists) {
+    if (!defined($Options{'C'})) {
+      # uid doesn't exist and we want to create it
+      my $addcmd = "/usr/local/sbin/smbldap-useradd.pl $usertype $login > /dev/null";
+      print STDERR "$addcmd\n";
+      my $r = system "$addcmd";
+      if ($r != 0) {
+        print STDERR "error adding $login, skipping\n";
+        next;
+      }
+       # lem modif... a retirer si pb
+       if ($entry_type eq "user")
+       {
+       modify_account($login, $userbasedn, $lmpwd, $ntpwd, $gecos, $homedir);
+       }
+
+       $created{$entry_type}++;
+    }
+    else { # uid doesn't exist and no create => log
+      print "$_";
+      $logged{$entry_type}++;
+    }
+  }
+  else { # account exists
+    $existing{$entry_type}++;
+    if (!defined($Options{'U'})) { # exists and modify 
+      modify_account($login, $userbasedn, $lmpwd, $ntpwd, $gecos, $homedir);
+      $updated{$entry_type}++;
+    }
+    else { # exists and log
+      print "$_";
+      $logged{$entry_type}++;
+    }
+  }
+}
+
+my $sum;
+
+$sum = $processed{'user'} + $processed{'machine'};
+print STDERR "processed: all=$sum user=$processed{'user'} machine=$processed{'machine'}\n";
+
+$sum = $existing{'user'} + $existing{'machine'};
+print STDERR "existing: all=$sum user=$existing{'user'} machine=$existing{'machine'}\n";
+
+$sum = $created{'user'} + $created{'machine'};
+print STDERR "created: all=$sum user=$created{'user'} machine=$created{'machine'}\n";
+
+$sum = $updated{'user'} + $updated{'machine'};
+print STDERR "updated: all=$sum user=$updated{'user'} machine=$updated{'machine'}\n";
+
+$sum = $logged{'user'} + $logged{'machine'};
+print STDERR "logged: all=$sum user=$logged{'user'} machine=$logged{'machine'}\n";
+
+print STDERR "special users skipped: $specialskipped\n";
+
+
+########################################
+
+=head1 NAME
+
+       smbldap-migrate.pl - Migrate NT accounts to LDAP
+
+=head1 SYNOPSIS
+
+       smbldap-migrate.pl [-a] [-w] [-A opts] [-W opts] [-C] [-U] [-?]
+
+=head1 DESCRIPTION
+
+       This command reads from stdin account entries as created by pwdump,
+       a tool to dump an user database on NT.
+       Depending of the options, some account entries may be output on
+       stdout. All errors and informations are sent to stderr.
+
+       -a     process only people, ignore computers
+
+       -w     process only computers, ignore persons
+
+       -A opts
+              a string containing arguments to pass verbatim to
+              smbldap-useradd when adding users, eg "-m -x".
+              You don't have to specify -a in this string.
+
+       -W opts
+              a string containing arguments to pass verbatim to
+              smbldap-useradd when adding computers, eg "-m -x".
+              You don't have to specify -w in this string.
+
+       -C     if NT account not found in LDAP, don't create it and log it to stdout
+              (default: create it)
+
+       -U     if NT account found in LDAP, don't update it and log it to stdout
+              (default: update it)
+
+       -?     show the help message
+
+=cut
+
+#'
+
+# The End
+
diff --git a/examples/LDAP/smbldap-tools/smbldap-migrate-groups.pl b/examples/LDAP/smbldap-tools/smbldap-migrate-groups.pl
new file mode 100644 (file)
index 0000000..0d3dd07
--- /dev/null
@@ -0,0 +1,225 @@
+#!/usr/bin/perl
+
+#  This code was developped by IDEALX (http://IDEALX.org/) and
+#  contributors (their names can be found in the CONTRIBUTORS file).
+#
+#                 Copyright (C) 2002 IDEALX
+#
+#  This program is free software; you can redistribute it and/or
+#  modify it under the terms of the GNU General Public License
+#  as published by the Free Software Foundation; either version 2
+#  of the License, or (at your option) any later version.
+#
+#  This program is distributed in the hope that it will be useful,
+#  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#  GNU General Public License for more details.
+#
+#  You should have received a copy of the GNU General Public License
+#  along with this program; if not, write to the Free Software
+#  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+#  USA.
+
+# Purpose of smbldap-migrate-groups : to parse a Windows
+# group dump and populate Unix groups
+# Reads group dump on stdin
+
+
+use strict;
+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;
+    }
+
+    foreach my $m (@members) {
+       if ( !($m =~ m/^\*/) ) {
+           push @{$mb}, $m;
+       } else {
+           my $gname = $m;
+           $gname =~ s/^.//;
+           if (!process_rec_group($gname, $mb)) {
+               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/^\*/) ) {
+           my $gname = $m;
+           $gname =~ s/^.//;
+           if (!$recgroup) {
+               print "recursive group not added : $gname\n";
+           } else {
+               if (!process_rec_group($gname, \@new_mb)) {
+                   print "recursive group not added : $gname\n";
+               }
+           }
+       } else {
+           push @new_mb, $m;
+       }
+    }
+
+    # new_mb contains flat members from group dump
+    # now append them to existing members
+    push @new_mb, group_get_members($group);
+    # uniq them
+    my %saw;
+    @saw{@new_mb} = ();
+    @new_mb = keys %saw;
+
+    my $nmb = $#new_mb + 1;
+    print STDERR "Group $group now has $nmb member(s)\n"; 
+    
+    my $mbs;
+    foreach $m (@new_mb) {
+           $mbs .= "memberUid: $m\n";
+    }
+
+    my $mods="$dn_line
+changetype: modify
+replace: memberUid
+$mbs
+";
+
+    #print "$mods\n";
+    my $tmpldif =
+"$mods
+";
+
+    die "$0: error while modifying group $group\n"
+       unless (do_ldapmodify($tmpldif) == 0);
+    undef $tmpldif;
+}
+
+sub display_group
+{
+    my ($group, @members) = @_;
+
+    print "Group name $group\n";
+    print "Members\n";
+    my $m;
+    my $i = 0;
+    foreach $m (@members) {
+       print "$m ";
+       if ($i % 5 == 0) {
+           print "\n";
+       }
+       $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) {
+           system "/usr/local/sbin/smbldap-groupadd.pl \"$group\"; sleep 5";
+           if (!defined($dn_line = get_group_dn($group))) {
+               return 1;
+           }
+           modify_group($group, $dn_line, @members, $recgroup);
+       } else {
+           # don't create
+           print "not created:\n";
+           display_group($group, @members);
+       }
+    } else {
+       # group found, update it ?
+       if (!$noupdate) {
+           modify_group($group, $dn_line, @members, $recgroup);
+       } else {
+           # don't update
+           print "not updated:\n";
+           display_group($group, @members);    
+       }
+    }
+}
+
+###################################################
+
+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);
+}
+
+my $group_name;
+my $group_desc;
+my $has_members = 0;
+my @members = ();
+
+while (<>)
+{
+  my $line = $_;
+  chomp($line);
+  next if ( $line =~ m/^\s*$/ );
+
+  if ($group_name eq "") {
+      if ( $line =~ m/^Group name\s+(.+).$/ ) {
+         $group_name = $1;
+         next;
+      }
+  }
+  if ($group_desc eq "") {
+      if ( $line =~ m/^Comment\s+(.*)$/ ) {
+         $group_desc = $1;
+         next;
+      }
+  }
+  next if ( $line =~ m/^-+.$/ );
+  if (!$has_members) {
+      if ( $line =~ m/^Members/ ) {
+         $has_members = 1;
+         next;
+      }
+  } else {
+      if ( $line =~ m/^The command completed successfully/ ) {
+         last;
+      } else {
+         push(@members, split(/\s+/, $line));
+         next;
+      }
+  }
+
+  #print;
+}
+
+if ( $#members > -1) {
+    process_group($group_name, @members, $Options{'C'}, $Options{'U'}, $Options{'r'});
+}
+
+#print "gn=$group_name\n";
+#print "gd=$group_desc\n";
+#my $m;
+#foreach $m (@members)
+#{
+#    print "$m ";
+#}
+#print "\n";
diff --git a/examples/LDAP/smbldap-tools/smbldap-passwd.pl b/examples/LDAP/smbldap-tools/smbldap-passwd.pl
new file mode 100755 (executable)
index 0000000..29aee97
--- /dev/null
@@ -0,0 +1,216 @@
+#!/usr/bin/perl
+
+# LDAP to unix password sync script for samba
+#
+#  This code was developped by IDEALX (http://IDEALX.org/) and
+#  contributors (their names can be found in the CONTRIBUTORS file).
+#
+#                 Copyright (C) 2001-2002 IDEALX
+#
+#  This program is free software; you can redistribute it and/or
+#  modify it under the terms of the GNU General Public License
+#  as published by the Free Software Foundation; either version 2
+#  of the License, or (at your option) any later version.
+#
+#  This program is distributed in the hope that it will be useful,
+#  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#  GNU General Public License for more details.
+#
+#  You should have received a copy of the GNU General Public License
+#  along with this program; if not, write to the Free Software
+#  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+#  USA.
+
+#  Purpose :
+#       . ldap-unix passwd sync for SAMBA-2.2.2 + LDAP
+#       . may also replace /bin/passwd
+
+use strict;
+use smbldap_tools;
+use smbldap_conf;
+
+my $user;
+my $oldpass;
+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 (!defined($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);
+}
+
+my $dn = get_dn_from_line($dn_line);
+
+my $samba = is_samba_user($user);
+
+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 new password
+
+my $pass;
+my $pass2;
+
+system "stty -echo";
+print "New password : ";
+chomp($pass=<STDIN>);
+print "\n";
+system "stty echo";
+
+system "stty -echo";
+print "Retype new password : ";
+chomp($pass2=<STDIN>);
+print "\n";
+system "stty echo";
+
+if ($pass ne $pass2) {
+    print "New passwords don't match!\n";
+    exit (10);
+}
+
+# only modify smb passwords if smb user
+if ($samba == 1) {
+    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);
+       }
+       my $ntpwd = `$mk_ntpasswd '$pass'`;
+        chomp(my $sambaLMPassword = substr($ntpwd, 0, index($ntpwd, ':')));
+        chomp(my $sambaNTPassword = substr($ntpwd, index($ntpwd, ':')+1));
+
+# change nt/lm passwords
+       my $tmpldif =
+"$dn_line
+changetype: modify
+replace: sambaLMPassword
+sambaLMPassword: $sambaLMPassword
+-
+changetype: modify
+replace: sambaNTPassword
+sambaNTPassword: $sambaNTPassword
+-
+
+";
+       die "$0: error while modifying password for $user\n"
+           unless (do_ldapmodify($tmpldif) == 0);
+       undef $tmpldif;
+    }
+    else {
+       if ($< != 0) {
+           my $FILE="|$smbpasswd -s >/dev/null";
+           open (FILE, $FILE) || die "$!\n";
+           print FILE <<EOF;
+'$oldpass'
+'$pass'
+'$pass'
+EOF
+    ;
+           close FILE;
+       } else {
+           my $FILE="|$smbpasswd $user -s >/dev/null";
+           open (FILE, $FILE) || die "$!\n";
+           print FILE <<EOF;
+'$pass'
+'$pass'
+EOF
+    ;
+           close FILE;
+       }
+    }
+}
+# change unix password
+$ret = system "$ldappasswd $dn -s '$pass' > /dev/null";
+if ($ret == 0) {
+    print "all authentication tokens updated successfully\n";
+} else {
+    return $ret;
+}
+
+exit 0;
+
+
+# - The End
+
+=head1 NAME
+       
+smbldap-passwd.pl - change user password
+
+=head1 SYNOPSIS
+       
+  smbldap-passwd.pl [name]
+
+=head1 DESCRIPTION
+
+       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.
+
+   Password Changes
+       The user is first prompted for their old password, if one is present.
+       This password is then tested against the stored password by binding
+       to the server. The user has only one chance to enter the correct pass-
+       word. The super user is permitted to bypass this step so that forgot-
+       ten passwords may be changed.
+
+       The user is then prompted for a replacement password. As a general
+       guideline, passwords should consist of 6 to 8 characters including
+       one or more from each of following sets:
+
+            Lower case alphabetics
+
+            Upper case alphabetics
+
+            Digits 0 thru 9
+
+            Punctuation marks
+
+       passwd will prompt again and compare the second entry against the first.
+       Both entries are require to match in order for the password to be
+       changed.
+
+=head1 SEE ALSO
+
+       passwd(1)
+
+=cut
+
+#'
diff --git a/examples/LDAP/smbldap-tools/smbldap-populate.pl b/examples/LDAP/smbldap-tools/smbldap-populate.pl
new file mode 100755 (executable)
index 0000000..1676017
--- /dev/null
@@ -0,0 +1,301 @@
+#!/usr/bin/perl
+
+# Populate a LDAP base for Samba-LDAP usage
+#
+#  This code was developped by IDEALX (http://IDEALX.org/) and
+#  contributors (their names can be found in the CONTRIBUTORS file).
+#
+#                 Copyright (C) 2001-2002 IDEALX
+#
+#  This program is free software; you can redistribute it and/or
+#  modify it under the terms of the GNU General Public License
+#  as published by the Free Software Foundation; either version 2
+#  of the License, or (at your option) any later version.
+#
+#  This program is distributed in the hope that it will be useful,
+#  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#  GNU General Public License for more details.
+#
+#  You should have received a copy of the GNU General Public License
+#  along with this program; if not, write to the Free Software
+#  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+#  USA.
+
+#  Purpose :
+#       . Create an initial LDAP database suitable for Samba 2.2
+#       . For lazy people, replace ldapadd (with only an ldif parameter)
+
+use strict;
+use smbldap_tools;
+use smbldap_conf;
+
+use Getopt::Std;
+
+use vars qw(%oc);
+
+# objectclass of the suffix
+%oc = (
+    "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);
+}
+
+my $_ldifName;
+
+if (@ARGV >= 1) {
+    $_ldifName = $ARGV[0];
+}
+
+my $adminName = $Options{'a'};
+if (!defined($adminName)) {
+    $adminName = "Administrator";
+}
+
+my $guestName = $Options{'b'};
+if (!defined($guestName)) {
+    $guestName = "nobody";
+}
+
+if (!defined($_ldifName)) {
+    my $attr;
+    my $val;
+    my $objcl;
+
+    if ($suffix =~ m/([^=]+)=([^,]+)/) {
+       $attr = $1;
+       $val = $2;
+       $objcl = $oc{$attr} if (exists $oc{$attr});
+       if (!defined($objcl)) {
+           $objcl = "myhardcodedobjectclass";
+       }
+    } 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+)$/);
+
+    #my $FILE="|cat";
+    my $FILE="|$ldapadd -c";
+    open (FILE, $FILE) || die "$!\n";
+
+    print FILE <<EOF;
+dn: $suffix
+objectClass: $objcl
+objectclass: organization
+$attr: $val
+o: $organisation
+
+dn: $usersdn
+objectClass: organizationalUnit
+ou: $usersou
+
+dn: $groupsdn
+objectClass: organizationalUnit
+ou: $groupsou
+
+dn: $computersdn
+objectClass: organizationalUnit
+ou: $computersou
+
+dn: uid=$adminName,$usersdn
+cn: $adminName
+sn: $adminName
+objectClass: inetOrgPerson
+objectClass: sambaSAMAccount
+objectClass: posixAccount
+gidNumber: 512
+uid: $adminName
+uidNumber: 998
+homeDirectory: $_userHomePrefix
+sambaPwdLastSet: 0
+sambaLogonTime: 0
+sambaLogoffTime: 2147483647
+sambaKickoffTime: 2147483647
+sambaPwdCanChange: 0
+sambaPwdMustChange: 2147483647
+sambaHomePath: $_userSmbHome
+sambaHomeDrive: $_userHomeDrive
+sambaProfilePath: $_userProfile
+sambaPrimaryGroupSID: 512
+sambaLMPassword: XXX
+sambaNTPassword: XXX
+sambaAcctFlags: [U          ]
+sambaSID: $smbldap_conf::SID-2996
+loginShell: /bin/false
+gecos: Netbios Domain Administrator
+
+dn: uid=$guestName,$usersdn
+cn: $guestName
+sn: $guestName
+objectClass: inetOrgPerson
+objectClass: sambaSAMAccount
+objectClass: posixAccount
+gidNumber: 514
+uid: $guestName
+uidNumber: 999
+homeDirectory: /dev/null
+sambaPwdLastSet: 0
+sambaLogonTime: 0
+sambaLogoffTime: 2147483647
+sambaKickoffTime: 2147483647
+sambaPwdCanChange: 0
+sambaPwdMustChange: 2147483647
+sambaHomePath: $_userSmbHome
+sambaHomeDrive: $_userHomeDrive
+sambaProfilePath: $_userProfile
+sambaPrimaryGroupSID: $smbldap_conf::SID-514
+sambaLMPassword: NO PASSWORDXXXXXXXXXXXXXXXXXXXXX
+sambaNTPassword: NO PASSWORDXXXXXXXXXXXXXXXXXXXXX
+sambaAcctFlags: [NU         ]
+sambaSID: $smbldap_conf::SID-2998
+loginShell: /bin/false
+
+dn: cn=Domain Admins,$groupsdn
+objectClass: posixGroup
+gidNumber: 512
+cn: Domain Admins
+memberUid: $adminName
+description: Netbios Domain Administrators (need smb.conf configuration)
+
+dn: cn=Domain Users,$groupsdn
+objectClass: posixGroup
+gidNumber: 513
+cn: Domain Users
+description: Netbios Domain Users (not implemented yet)
+
+dn: cn=Domain Guests,$groupsdn
+objectClass: posixGroup
+gidNumber: 514
+cn: Domain Guests
+description: Netbios Domain Guests Users (not implemented yet)
+
+dn: cn=Administrators,$groupsdn
+objectClass: posixGroup
+gidNumber: 544
+cn: Administrators
+description: Netbios Domain Members can fully administer the computer/sambaDomainName (not implemented yet)
+
+dn: cn=Users,$groupsdn
+objectClass: posixGroup
+gidNumber: 545
+cn: Users
+description: Netbios Domain Ordinary users (not implemented yet)
+
+dn: cn=Guests,$groupsdn
+objectClass: posixGroup
+gidNumber: 546
+cn: Guests
+memberUid: $guestName
+description: Netbios Domain Users granted guest access to the computer/sambaDomainName (not implemented yet)
+
+
+dn: cn=Power Users,$groupsdn
+objectClass: posixGroup
+gidNumber: 547
+cn: Power Users
+description: Netbios Domain Members can share directories and printers (not implemented yet)
+
+dn: cn=Account Operators,$groupsdn
+objectClass: posixGroup
+gidNumber: 548
+cn: Account Operators
+description: Netbios Domain Users to manipulate users accounts (not implemented yet)
+
+dn: cn=Server Operators,$groupsdn
+objectClass: posixGroup
+gidNumber: 549
+cn: Server Operators
+description: Netbios Domain Server Operators (need smb.conf configuration)
+
+dn: cn=Print Operators,$groupsdn
+objectClass: posixGroup
+gidNumber: 550
+cn: Print Operators
+description: Netbios Domain Print Operators (need smb.conf configuration)
+
+dn: cn=Backup Operators,$groupsdn
+objectClass: posixGroup
+gidNumber: 551
+cn: Backup Operators
+description: Netbios Domain Members can bypass file security to back up files (not implemented yet)
+
+dn: cn=Replicator,$groupsdn
+objectClass: posixGroup
+gidNumber: 552
+cn: Replicator
+description: Netbios Domain Supports file replication in a sambaDomainName (not implemented yet)
+
+dn: cn=Domain Computers,$groupsdn
+objectClass: posixGroup
+gidNumber: 553
+cn: Domain Computers
+description: Netbios Domain Computers accounts
+
+EOF
+    close FILE;
+    exit($?)
+
+} else {
+    exec "$ldapadd < $_ldifName";
+}
+
+exit(0);
+
+
+########################################
+
+=head1 NAME
+
+       smbldap-populate.pl - Populate your LDAP database
+
+=head1 SYNOPSIS
+
+       smbldap-populate.pl [ldif-file]
+
+=head1 DESCRIPTION
+
+       The smbldap-populate.pl command helps to populate an LDAP server
+       by adding the necessary entries : base suffix (doesn't abort
+       if already there), organizational units for users, groups and
+       computers, builtin users : Administrator and guest, builtin
+       groups (though posixAccount only, no SambaTNG support).
+
+       -a name  Your local administrator login name (default: Administrator)
+       -b name  Your local guest login name (default: nobody)
+
+       If you give an extra parameter, it is assumed to be the ldif
+       file to use instead of the builtin one. Options -a and -b
+       will be ignored. This usage mode makes the command behave
+       like ldapadd(1) with extra parameters taken from the smbldap-tools
+       config (smbldap_conf.pm).
+
+=head1 FILES
+
+       /usr/lib/perl5/site-perl/smbldap_conf.pm : Global parameters.
+
+=head1 SEE ALSO
+
+       smp(1)
+
+=cut
+
+#'
+
+
+
+# - The End
diff --git a/examples/LDAP/smbldap-tools/smbldap-tools.spec b/examples/LDAP/smbldap-tools/smbldap-tools.spec
new file mode 100755 (executable)
index 0000000..ddaed45
--- /dev/null
@@ -0,0 +1,171 @@
+# $Source: /data/src/mirror/cvs/samba/examples/LDAP/smbldap-tools/smbldap-tools.spec,v $
+%define version        0.8
+%define release        1
+%define name   smbldap-tools
+%define realname  smbldap-tools
+
+Summary:       User & Group administration tools for Samba-OpenLDAP
+Name:          %{name}
+version:       %{version}
+Release:       %{release}
+Group:                 System Environment/Base
+License:       GPL
+
+Vendor:                IDEALX S.A.S.
+URL:           http://samba.IDEALX.org/
+Packager:      Jerome Tournier <jerome.tournier@IDEALX.com>
+Source0:       smbldap-groupadd.pl
+Source1:       smbldap-groupdel.pl
+Source2:       smbldap-groupmod.pl
+Source3:       smbldap-groupshow.pl
+Source4:       smbldap-passwd.pl
+Source5:       smbldap-useradd.pl
+Source6:       smbldap-userdel.pl
+Source7:       smbldap-usermod.pl
+Source8:       smbldap-usershow.pl
+Source9:       smbldap_conf.pm
+Source10:      smbldap_tools.pm
+Source11:      CONTRIBUTORS
+Source12:      COPYING
+Source13:      ChangeLog
+Source14:      FILES
+Source15:      README
+Source16:      TODO
+Source17:       mkntpwd.tar.gz
+Source18:      smbldap-populate.pl
+Source19:      smbldap-migrate-accounts.pl
+Source20:      smbldap-migrate-groups.pl
+Source21:      INFRA
+BuildRoot:     /%{_tmppath}/%{name}
+Prefix: /usr/local
+BuildRequires: perl >= 5.6
+Requires: perl >= 5.6, openldap, openldap-clients, samba
+
+%description
+In settings with OpenLDAP and Samba-LDAP servers, this collection is
+useful to add, modify and delete users and groups, and to change
+Unix and Samba passwords. In those context they replace the system
+tools to manage users, groups and passwords.
+
+%prep
+
+%setup -c -T
+
+%build
+tar zxvf %{SOURCE17}
+cd mkntpwd
+make
+
+%install
+rm -rf $RPM_BUILD_ROOT
+mkdir -p $RPM_BUILD_ROOT/%{prefix}/sbin
+mkdir -p $RPM_BUILD_ROOT/%{prefix}/share
+mkdir -p $RPM_BUILD_ROOT/usr/share/doc
+mkdir -p $RPM_BUILD_ROOT/usr/share/doc/smbldap-tools
+
+cd mkntpwd ; make PREFIX=$RPM_BUILD_ROOT/%{prefix} install
+
+install -m 550 %{SOURCE0} $RPM_BUILD_ROOT/%{prefix}/sbin/smbldap-groupadd.pl
+install -m 550 %{SOURCE1} $RPM_BUILD_ROOT/%{prefix}/sbin/smbldap-groupdel.pl
+install -m 550 %{SOURCE2} $RPM_BUILD_ROOT/%{prefix}/sbin/smbldap-groupmod.pl
+install -m 555 %{SOURCE3} $RPM_BUILD_ROOT/%{prefix}/sbin/smbldap-groupshow.pl
+install -m 555 %{SOURCE4} $RPM_BUILD_ROOT/%{prefix}/sbin/smbldap-passwd.pl
+install -m 550 %{SOURCE5} $RPM_BUILD_ROOT/%{prefix}/sbin/smbldap-useradd.pl
+install -m 550 %{SOURCE6} $RPM_BUILD_ROOT/%{prefix}/sbin/smbldap-userdel.pl
+install -m 550 %{SOURCE7} $RPM_BUILD_ROOT/%{prefix}/sbin/smbldap-usermod.pl
+install -m 555 %{SOURCE8} $RPM_BUILD_ROOT/%{prefix}/sbin/smbldap-usershow.pl
+install -m 550 %{SOURCE18} $RPM_BUILD_ROOT/%{prefix}/sbin/smbldap-populate.pl
+install -m 751 %{SOURCE9} $RPM_BUILD_ROOT/%{prefix}/sbin/smbldap_conf.pm
+install -m 555 %{SOURCE10} $RPM_BUILD_ROOT/%{prefix}/sbin/smbldap_tools.pm
+install -m 550 %{SOURCE19} $RPM_BUILD_ROOT/%{prefix}/sbin/smbldap-migrate-accounts.pl
+install -m 550 %{SOURCE20} $RPM_BUILD_ROOT/%{prefix}/sbin/smbldap-migrate-groups.pl
+
+install -m 644 %{SOURCE11} $RPM_BUILD_ROOT/usr/share/doc/smbldap-tools/CONTRIBUTORS
+install -m 644 %{SOURCE12} $RPM_BUILD_ROOT/usr/share/doc/smbldap-tools/COPYING
+install -m 644 %{SOURCE13} $RPM_BUILD_ROOT/usr/share/doc/smbldap-tools/ChangeLog
+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
+
+%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
+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
+perl -i -pe 's/_SUFFIX_/dc=IDEALX,dc=org/' %{prefix}/sbin/smbldap_conf.pm
+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/_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
+
+# FIXME: links should not be removed on upgrade
+#%postun
+#if [ $1 = 0 ] ; then
+#  rm -f /usr/lib/perl5/site_perl/smbldap_tools.pm
+#  rm -f /usr/lib/perl5/site_perl/smbldap_conf.pm
+#fi
+
+%files
+%defattr(-,root,root)
+%{prefix}/sbin/*.pl
+%{prefix}/sbin/smbldap_tools.pm
+%config %{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
+
+* 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.
diff --git a/examples/LDAP/smbldap-tools/smbldap-useradd.pl b/examples/LDAP/smbldap-tools/smbldap-useradd.pl
new file mode 100755 (executable)
index 0000000..99c9525
--- /dev/null
@@ -0,0 +1,460 @@
+#!/usr/bin/perl 
+
+#  This code was developped by IDEALX (http://IDEALX.org/) and
+#  contributors (their names can be found in the CONTRIBUTORS file).
+#
+#                 Copyright (C) 2002 IDEALX
+#
+#  This program is free software; you can redistribute it and/or
+#  modify it under the terms of the GNU General Public License
+#  as published by the Free Software Foundation; either version 2
+#  of the License, or (at your option) any later version.
+#
+#  This program is distributed in the hope that it will be useful,
+#  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#  GNU General Public License for more details.
+#
+#  You should have received a copy of the GNU General Public License
+#  along with this program; if not, write to the Free Software
+#  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+#  USA.
+
+# Purpose of smbldap-useradd : user (posix,shadow,samba) add
+
+use strict;
+use smbldap_tools;
+use smbldap_conf;
+
+#####################
+
+use Getopt::Std;
+my %Options;
+
+my $ok = getopts('axnmwPG:u:g:d:s:c:k:A:B:C:D:E:F:H:?', \%Options);
+
+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 "  -?     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";
+}
+
+# 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;
+} elsif (getpwuid($userUidNumber)) { die "Uid already exists.\n"; }
+
+if ($nscd_status == 0) {
+   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'})) {
+       $userGidNumber = $_defaultComputerGid;
+#    } 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;
+
+#      $createGroup = 1;
+
+    } else {
+       # user will have gid = $_defaultUserGid
+       $userGidNumber = $_defaultUserGid;
+    }
+} else {
+    my $gid;
+    if (($gid = parse_group($userGidNumber)) < 0) {
+       print "$0: unknown group $userGidNumber\n";
+       exit (6);
+    }
+    $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];
+
+# 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);
+} elsif (!$rc) {
+    print "$0: error in get_user_dn2\n";
+    exit(10);
+}
+
+my $userHomeDirectory;
+my $tmp;
+if (!defined($userHomeDirectory = $Options{'d'}))
+{
+    $userHomeDirectory = $_userHomePrefix."/".$userName;
+}
+$_userLoginShell = $tmp if (defined($tmp = $Options{'s'}));
+$_userGecos = $tmp if (defined($tmp = $Options{'c'}));
+$_skeletonDir = $tmp if (defined($tmp = $Options{'k'}));
+
+########################
+
+# MACHINE ACCOUNT
+if (defined($tmp = $Options{'w'})) {
+   
+    # add a trailing dollar if missing
+    if ($userName =~ /[^\$]$/s) {
+       $userName .= "\$";
+    }
+
+    #print "About to create machine $userName:\n";
+
+    if (!add_posix_machine ($userName, $userUidNumber, $userGidNumber)) {
+       die "$0: error while adding posix account\n";
+    }
+
+    if (!$with_smbpasswd) {
+       if (!add_samba_machine_mkntpwd($userName, $userUidNumber)) {
+           die "$0: error while adding samba account\n";
+       }
+    } else {
+       if (!add_samba_machine($userName)) {
+           die "$0: error while adding samba account\n";
+       }
+
+       my $tmpldif =
+"dn: uid=$userName,$computersdn
+changetype: modify
+sambaAcctFlags: [W          ]
+
+";
+       die "$0: error while modifying accountflags of $userName\n"
+           unless (do_ldapmodify($tmpldif) == 0);
+       undef $tmpldif;
+    }
+
+    exit 0;
+}
+
+#######################
+
+# USER ACCOUNT
+
+# add posix account first
+
+my $tmpldif =
+"dn: uid=$userName,$usersdn
+objectclass: inetOrgPerson
+objectclass: posixAccount
+cn: $userName
+sn: $userName
+uid: $userName
+uidNumber: $userUidNumber
+gidNumber: $userGidNumber
+homeDirectory: $userHomeDirectory
+loginShell: $_userLoginShell
+gecos: $_userGecos
+description: $_userGecos
+userPassword: {crypt}x
+
+";
+
+die "$0: error while adding posix user $userName\n"
+    unless (do_ldapadd($tmpldif) == 0);
+
+undef $tmpldif;
+
+#if ($createGroup) {
+#    group_add($userName, $userGidNumber);
+#}
+
+group_add_user($userGidNumber, $userName);
+
+my $grouplist;
+# adds to supplementary groups
+if (defined($grouplist = $Options{'G'})) {
+    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 =~ /\$$/ ) {
+    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"; 
+    }
+   }
+}
+
+
+# Add Samba user infos
+if (defined($Options{'a'})) {
+    if (!$with_smbpasswd) {
+
+       my $winmagic = 2147483647;
+       my $valpwdcanchange = 0;
+       my $valpwdmustchange = $winmagic;
+       my $valacctflags = "[UX]";
+
+       if (defined($tmp = $Options{'A'})) {
+           if ($tmp != 0) {
+               $valpwdcanchange = "0";
+           } else {
+               $valpwdcanchange = "$winmagic";
+           }
+       }
+
+       if (defined($tmp = $Options{'B'})) {
+           if ($tmp != 0) {
+               $valpwdmustchange = "0";
+           } else {
+               $valpwdmustchange = "$winmagic";
+           }
+       }
+
+       if (defined($tmp = $Options{'H'})) {
+           $valacctflags = "$tmp";
+       }
+
+       my $tmpldif =
+"dn: uid=$userName,$usersdn
+changetype: modify
+objectClass: inetOrgPerson
+objectclass: posixAccount
+objectClass: sambaSAMAccount
+sambaPwdLastSet: 0
+sambaLogonTime: 0
+sambaLogoffTime: 2147483647
+sambaKickoffTime: 2147483647
+sambaPwdCanChange: $valpwdcanchange
+sambaPwdMustChange: $valpwdmustchange
+displayName: $_userGecos
+sambaAcctFlags: $valacctflags
+sambaSID: $smbldap_conf::SID-$userRid
+
+";
+       
+       die "$0: error while adding samba account to posix user $userName\n"
+           unless (do_ldapmodify($tmpldif) == 0);
+
+       undef $tmpldif;
+    } else {
+       my $FILE="|smbpasswd -s -a $userName >/dev/null" ;
+       open (FILE, $FILE) || die "$!\n";
+       print FILE <<EOF;
+x
+x
+EOF
+    ;
+       close FILE;
+       if ($?) {
+           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";
+
+if (defined($tmp = $Options{'C'})) {
+    $valsmbhome = "$tmp";
+}
+
+if (defined($tmp = $Options{'D'})) {
+    $tmp = $tmp.":" unless ($tmp =~ /:/);
+    $valhomedrive = "$tmp";
+}
+
+if (defined($tmp = $Options{'E'})) {
+    $valscriptpath = "$tmp";
+}
+
+if (defined($tmp = $Options{'F'})) {
+    $valprofilepath = "$tmp";
+}
+
+    my $tmpldif =
+"dn: uid=$userName,$usersdn
+changetype: modify
+sambaSID: $smbldap_conf::SID-$userRid
+sambaPrimaryGroupSID: $smbldap_conf::SID-$userGroupRid
+sambaHomeDrive: $valhomedrive
+sambaHomePath: $valsmbhome
+sambaProfilePath: $valprofilepath
+sambaLogonScript: $valscriptpath
+sambaLMPassword: XXX
+sambaNTPassword: XXX
+
+";
+
+    die "$0: error while modifying samba account of user $userName\n"
+           unless (do_ldapmodify($tmpldif) == 0);
+    undef $tmpldif;
+}
+
+if (defined($Options{'P'})) {
+    exec "/usr/local/sbin/smbldap-passwd.pl $userName"
+}
+
+exit 0;
+
+########################################
+
+=head1 NAME
+
+       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
+
+=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.
+
+       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:
+
+       -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.
+
+       -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).
+
+       -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.
+
+       -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.
+
+       -G group,[...]
+              A list of supplementary groups which the user is also  a  member
+              of.   Each  group is separated from the next by a comma, with no
+              intervening whitespace.  The groups  are  subject  to  the  same
+              restrictions as the group given with the -g option.  The default
+              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
+              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.
+
+       -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.
+
+       -P     ends by invoking smbldap-passwd.pl
+
+       -A     can change password ? 0 if no, 1 if yes
+
+       -B     must change password ? 0 if no, 1 if yes
+
+       -C     sambaHomePath (SMB home share, like '\\\\PDC-SRV\\homes')
+
+       -D     sambaHomeDrive (letter associated with home share, like 'H:')
+
+       -E     sambaLogonScript, relative to the [netlogon] share (DOS script to execute on login, like 'foo.bat')
+
+       -F     sambaProfilePath (profile directory, like '\\\\PDC-SRV\\profiles\\foo')
+
+       -H     sambaAcctFlags, spaces and trailing bracket are ignored (samba account control bits like '[NDHTUMWSLKI]')
+
+=head1 SEE ALSO
+
+       useradd(1)
+
+=cut
+
+#'
diff --git a/examples/LDAP/smbldap-tools/smbldap-userdel.pl b/examples/LDAP/smbldap-tools/smbldap-userdel.pl
new file mode 100755 (executable)
index 0000000..435be4f
--- /dev/null
@@ -0,0 +1,122 @@
+#!/usr/bin/perl
+
+#  This code was developped by IDEALX (http://IDEALX.org/) and
+#  contributors (their names can be found in the CONTRIBUTORS file).
+#
+#                 Copyright (C) 2001-2002 IDEALX
+#
+#  This program is free software; you can redistribute it and/or
+#  modify it under the terms of the GNU General Public License
+#  as published by the Free Software Foundation; either version 2
+#  of the License, or (at your option) any later version.
+#
+#  This program is distributed in the hope that it will be useful,
+#  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#  GNU General Public License for more details.
+#
+#  You should have received a copy of the GNU General Public License
+#  along with this program; if not, write to the Free Software
+#  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+#  USA.
+
+# Purpose of smbldap-userdel : user (posix,shadow,samba) deletion
+
+use strict;
+use smbldap_tools;
+
+
+#####################
+
+use Getopt::Std;
+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);
+}
+
+# Read only first @ARGV
+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);
+}
+
+if ($< != 0) {
+    print "You must be root to delete an user\n";
+    exit (1);
+}
+
+my $homedir;
+if (defined($Options{'r'})) {
+    $homedir=get_homedir($user);
+}
+
+# remove user from groups
+my $groups = find_groups_of $user;
+my @grplines = split(/\n/, $groups);
+
+my $grp;
+foreach $grp (@grplines) {
+    my $gname = "";
+    if ( $grp =~ /dn: cn=([^,]+),/) {
+       $gname = $1;
+       #print "xx $gname\n";
+    }
+    if ($gname ne "") {
+       group_remove_member($gname, $user);
+    }
+}
+
+# XXX
+delete_user($user);
+
+# delete dir -- be sure that homeDir is not a strange value
+if (defined($Options{'r'})) {
+    if ($homedir !~ /^\/dev/ and $homedir !~ /^\/$/) {
+       system "rm -rf $homedir";
+    }
+}
+
+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";
+}
+
+exit (0);
+
+############################################################
+
+=head1 NAME
+
+       smbldap-userdel.pl - Delete a user account and related files
+
+=head1 SYNOPSIS
+
+       smbldap-userdel.pl [-r] login
+
+=head1 DESCRIPTION
+
+       The smbldap-userdel.pl command modifies the system
+       account files, deleting all entries that refer to login.
+       The named user must exist.
+
+       -r     Files in the user's home directory will be removed along with
+              the home directory itself. Files located in other file
+              systems will have to be searched for and deleted manually.
+
+=head1 SEE ALSO
+
+       userdel(1)
+
+=cut
+
+#'
diff --git a/examples/LDAP/smbldap-tools/smbldap-usermod.pl b/examples/LDAP/smbldap-tools/smbldap-usermod.pl
new file mode 100755 (executable)
index 0000000..dffb95b
--- /dev/null
@@ -0,0 +1,403 @@
+#!/usr/bin/perl 
+
+#  This code was developped by IDEALX (http://IDEALX.org/) and
+#  contributors (their names can be found in the CONTRIBUTORS file).
+#
+#                 Copyright (C) 2001-2002 IDEALX
+#
+#  This program is free software; you can redistribute it and/or
+#  modify it under the terms of the GNU General Public License
+#  as published by the Free Software Foundation; either version 2
+#  of the License, or (at your option) any later version.
+#
+#  This program is distributed in the hope that it will be useful,
+#  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#  GNU General Public License for more details.
+#
+#  You should have received a copy of the GNU General Public License
+#  along with this program; if not, write to the Free Software
+#  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+#  USA.
+
+# Purpose of smbldap-usermod : user (posix,shadow,samba) modification
+
+use strict;
+use smbldap_tools;
+use smbldap_conf;
+
+
+#####################
+
+use Getopt::Std;
+my %Options;
+my $nscd_status;
+
+my $ok = getopts('A:B:C:D:E:F:H:IJxme:f:u:g:G:d:l:s:c:ok:?', \%Options);
+if ( (!$ok) || (@ARGV < 1) || ($Options{'?'}) ) {
+       print "Usage: $0 [-awmugdsckxABCDEFGHI?] username\n";
+       print "  -c     gecos\n";
+       print "  -d     home directory\n";
+       #print "  -m    move home directory\n";
+       #print "  -e    expire date (YYYY-MM-DD)\n";
+       #print "  -f    inactive days\n";
+       print "  -u     uid\n";
+       print "  -o     uid can be non unique\n";
+       print "  -g     gid\n";
+       print "  -G     supplementary groups (comma separated)\n";
+       print "  -l     login name\n";
+       print "  -s     shell\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 "  -?     show this help message\n";
+       exit (1);
+}
+
+if ($< != 0) {
+    print "You must be root to modify an user\n";
+    exit (1);
+}
+
+# Read only first @ARGV
+my $user = $ARGV[0];
+
+# Read user datas
+my $lines = read_user($user);
+if (!defined($lines)) {
+    print "$0: user $user doesn't exist\n";
+    exit (1);
+}
+
+#print "$lines\n";
+my $dn_line;
+if ( $lines =~ /(^dn: .*)/ ) {
+    $dn_line = $1;
+}
+
+chomp($dn_line);
+
+my $samba = 0;
+if ($lines =~ m/objectClass: sambaAccount/) {
+    $samba = 1;
+}
+
+############
+
+my $tmp;
+my $mods;
+
+# Process options
+my $changed_uid;
+my $_userUidNumber;
+my $_userRid;
+if (defined($tmp = $Options{'u'})) {
+    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";
+       }
+
+       if (getpwuid($tmp)) {
+           if ($nscd_status == 0) {
+               system "/etc/init.d/nscd start > /dev/null 2>&1";
+           }
+
+           print "$0: uid number $tmp exists\n";
+           exit (6);
+       }
+       if ($nscd_status == 0) {
+           system "/etc/init.d/nscd start > /dev/null 2>&1";
+       }
+
+    }
+    $_userUidNumber = $tmp;
+    # as rid we use 2 * uid + 1000
+    my $_userRid = 2 * $_userUidNumber + 1000;
+    if (defined($Options{'x'})) {
+       $_userRid= sprint("%x", $_userRid);
+    }
+    $mods .= "uidNumber: $_userUidNumber\n";
+    if ($samba) {
+       $mods .= "rid: $_userRid\n";
+    }
+    $changed_uid = 1;
+}
+
+my $changed_gid;
+my $_userGidNumber;
+my $_userGroupRid;
+if (defined($tmp = $Options{'g'})) {
+    $_userGidNumber = parse_group($tmp);
+    if ($_userGidNumber < 0) {
+       print "$0: group $tmp doesn't exist\n";
+       exit (6);
+    }
+# as grouprid we use 2 * gid + 1001
+    my $_userGroupRid = 2 * $_userGidNumber + 1001;
+    if (defined($Options{'x'})) {
+       $_userGroupRid = sprint("%x", $_userGroupRid);
+    }
+    $mods .= "gidNumber: $_userGidNumber\n";
+    if ($samba) {
+       $mods .= "primaryGroupID: $_userGroupRid\n";
+    }
+    $changed_gid = 1;
+}
+
+my $changed_shell;
+my $_userLoginShell;
+if (defined($tmp = $Options{'s'})) {
+    $_userLoginShell = $tmp;
+    $mods .= "loginShell: $_userLoginShell\n";
+    $changed_shell = 1;
+}
+
+my $changed_gecos;
+my $_userGecos;
+if (defined($tmp = $Options{'c'})) { 
+    $_userGecos = $tmp;
+    $mods .= "gecos: $_userGecos\n";
+    $changed_gecos = 1;
+}
+
+my $changed_homedir;
+my $newhomedir;
+if (defined($tmp = $Options{'d'})) {
+    $newhomedir = $tmp; 
+    $mods .= "homeDirectory: $newhomedir\n";
+    $changed_homedir = 1;
+}
+
+
+if (defined($tmp = $Options{'G'})) {
+
+    # remove user from old groups
+    my $groups = find_groups_of $user;
+    my @grplines = split(/\n/, $groups);
+
+    my $grp;
+    foreach $grp (@grplines) {
+       my $gname = "";
+       if ( $grp =~ /dn: cn=([^,]+),/) {
+           $gname = $1;
+           #print "xx $gname\n";
+       }
+       if ($gname ne "") {
+           group_remove_member($gname, $user);
+       }
+    }
+
+    # add user to new groups
+    add_grouplist_user($tmp, $user);
+}
+
+#
+# A : sambaPwdCanChange
+# B : sambaPwdMustChange
+# C : sambaHomePath
+# D : sambaHomeDrive
+# E : sambaLogonScript
+# F : sambaProfilePath
+# H : sambaAcctFlags
+
+my $attr;
+my $winmagic = 2147483647;
+
+if (defined($tmp = $Options{'A'})) {
+    $attr = "sambaPwdCanChange";
+    if ($tmp != 0) {
+       $mods .= "$attr: 0\n";
+    } else {
+       $mods .= "$attr: $winmagic\n";
+    }
+}
+
+if (defined($tmp = $Options{'B'})) {
+    $attr = "sambaPwdMustChange";
+    if ($tmp != 0) {
+       $mods .= "$attr: 0\n";
+    } else {
+       $mods .= "$attr: $winmagic\n";
+    }
+}
+
+if (defined($tmp = $Options{'C'})) {
+    $attr = "sambaHomePath";
+    #$tmp =~ s/\\/\\\\/g;
+    $mods .= "$attr: $tmp\n";
+}
+
+if (defined($tmp = $Options{'D'})) {
+    $attr = "sambaHomeDrive";
+    $tmp = $tmp.":" unless ($tmp =~ /:/);
+    $mods .= "$attr: $tmp\n";
+}
+
+if (defined($tmp = $Options{'E'})) {
+    $attr = "sambaLogonScript";
+    #$tmp =~ s/\\/\\\\/g;
+    $mods .= "$attr: $tmp\n";
+}
+
+if (defined($tmp = $Options{'F'})) {
+    $attr = "sambaProfilePath";
+    #$tmp =~ s/\\/\\\\/g;
+    $mods .= "$attr: $tmp\n";
+}
+
+if (defined($tmp = $Options{'H'})) {
+    $attr = "sambaAcctFlags";
+    #$tmp =~ s/\\/\\\\/g;
+    $mods .= "$attr: $tmp\n";
+} elsif (defined($tmp = $Options{'I'})) {
+    my $flags;
+
+    if ( $lines =~ /^sambaAcctFlags: (.*)/m ) {
+       $flags = $1;
+    }
+
+    chomp($flags);
+
+    if ( !($flags =~ /D/) ) {
+       my $letters;
+       if ($flags =~ /(\w+)/) {
+           $letters = $1;
+       }
+       $mods .= "sambaAcctFlags: \[D$letters\]\n";
+    }
+} elsif (defined($tmp = $Options{'J'})) {
+    my $flags;
+
+    if ( $lines =~ /^sambaAcctFlags: (.*)/m ) {
+       $flags = $1;
+    }
+
+    chomp($flags);
+
+    if ( $flags =~ /D/ ) {
+       my $letters;
+       if ($flags =~ /(\w+)/) {
+           $letters = $1;
+       }
+       $letters =~ s/D//;
+       $mods .= "sambaAcctFlags: \[$letters\]\n";
+    }
+}
+
+if ($mods ne '') {
+    #print "----\n$dn_line\n$mods\n----\n";
+
+    my $tmpldif =
+"$dn_line
+changetype: modify
+$mods
+";
+
+    die "$0: error while modifying user $user\n"
+       unless (do_ldapmodify($tmpldif) == 0);
+
+    undef $tmpldif;
+}
+
+$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";
+}
+
+
+############################################################
+
+=head1 NAME
+
+       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
+
+=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
+
+       -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.
+              The  group  name  must  exist.   A group number must refer to an
+              already existing group.  The default group number is 1.
+
+       -G group,[...]
+              A list of supplementary groups which the user is also  a  member
+              of.   Each  group is separated from the next by a comma, with no
+              intervening whitespace.  The groups  are  subject  to  the  same
+              restrictions as the group given with the -g option.  If the user
+              is currently a member of a group which is not listed,  the  user
+              will be removed from the group
+
+       -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.
+
+       -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­
+              tory will have the file user ID  changed  automatically.   Files
+              outside of the user's home directory must be altered manually.
+
+       -x     Creates rid and primaryGroupID in hex instead of decimal (for 
+              Samba 2.2.2 unpatched only - higher versions always use decimal)
+
+       -A     can change password ? 0 if no, 1 if yes
+
+       -B     must change password ? 0 if no, 1 if yes
+
+       -C     sambaHomePath (SMB home share, like '\\\\PDC-SRV\\homes')
+
+       -D     sambaHomeDrive (letter associated with home share, like 'H:')
+
+       -E     sambaLogonScript, relative to the [netlogon] share (DOS script to execute on login, like 'foo.bat')
+
+       -F     sambaProfilePath (profile directory, like '\\\\PDC-SRV\\profiles\\foo')
+
+       -H     sambaAcctFlags, spaces and trailing bracket are ignored (samba account control bits like '[NDHTUMWSLKI]')
+
+       -I     disable user. Can't be used with -H or -J
+
+       -J     enable user. Can't be used with -H or -I
+
+=head1 SEE ALSO
+
+       usermod(1)
+
+=cut
+
+#'
diff --git a/examples/LDAP/smbldap-tools/smbldap-usershow.pl b/examples/LDAP/smbldap-tools/smbldap-usershow.pl
new file mode 100755 (executable)
index 0000000..b05f087
--- /dev/null
@@ -0,0 +1,69 @@
+#!/usr/bin/perl 
+
+#  This code was developped by IDEALX (http://IDEALX.org/) and
+#  contributors (their names can be found in the CONTRIBUTORS file).
+#
+#                 Copyright (C) 2001-2002 IDEALX
+#
+#  This program is free software; you can redistribute it and/or
+#  modify it under the terms of the GNU General Public License
+#  as published by the Free Software Foundation; either version 2
+#  of the License, or (at your option) any later version.
+#
+#  This program is distributed in the hope that it will be useful,
+#  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#  GNU General Public License for more details.
+#
+#  You should have received a copy of the GNU General Public License
+#  along with this program; if not, write to the Free Software
+#  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+#  USA.
+
+# Purpose of smbldap-userdisplay : user (posix,shadow,samba) display
+
+use strict;
+use smbldap_tools;
+
+use Getopt::Std;
+my %Options;
+
+my $ok = getopts('?', \%Options);
+
+if ( (!$ok) || (@ARGV < 1) || ($Options{'?'}) ) {
+       print "Usage: $0 [-?] username\n";
+       print "  -?     show this help message\n";
+       exit (1);
+}
+
+# Read only first @ARGV
+my $user = $ARGV[0];
+
+my $lines = read_user($user);
+if (!defined($lines)) {
+    print "$0: user $user doesn't exist\n";
+    exit (1);
+}
+
+print "$lines\n";
+
+exit(0);
+
+############################################################
+
+=head1 NAME
+
+       smbldap-usershow.pl - Show a user account informations
+
+=head1 SYNOPSIS
+
+       smbldap-usershow.pl login
+
+=head1 DESCRIPTION
+
+       The smbldap-usershow.pl command displays the informations
+       associated with the login. The named user must exist.
+
+=cut
+
+#'
diff --git a/examples/LDAP/smbldap-tools/smbldap_conf.pm b/examples/LDAP/smbldap-tools/smbldap_conf.pm
new file mode 100644 (file)
index 0000000..dd1d772
--- /dev/null
@@ -0,0 +1,281 @@
+#!/usr/bin/perl
+use strict;
+package smbldap_conf;
+
+# smbldap-tools.conf : Q & D configuration file for smbldap-tools
+
+#  This code was developped by IDEALX (http://IDEALX.org/) and
+#  contributors (their names can be found in the CONTRIBUTORS file).
+#
+#                 Copyright (C) 2001-2002 IDEALX
+#
+#  This program is free software; you can redistribute it and/or
+#  modify it under the terms of the GNU General Public License
+#  as published by the Free Software Foundation; either version 2
+#  of the License, or (at your option) any later version.
+#
+#  This program is distributed in the hope that it will be useful,
+#  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#  GNU General Public License for more details.
+#
+#  You should have received a copy of the GNU General Public License
+#  along with this program; if not, write to the Free Software
+#  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+#  USA.
+
+#  Purpose :
+#       . 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 $ldapsearch $ldapsearchnobind
+$ldapmodify $ldappasswd $ldapadd $ldapdelete $ldapmodrdn
+$suffix $usersdn $computersdn
+$groupsdn $scope $binddn $bindpasswd
+$slaveDN $slavePw $masterDN $masterPw
+$_userLoginShell $_userHomePrefix $_userGecos
+$_defaultUserGid $_defaultComputerGid
+$_skeletonDir $_userSmbHome
+$_userProfile $_userHomeDrive
+$_userScript $usersou $computersou $groupsou
+);
+
+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 $ldapsearch $ldapsearchnobind $ldapmodify $ldappasswd
+$ldapadd $ldapdelete $ldapmodrdn $suffix $usersdn
+$computersdn $groupsdn $scope $binddn $bindpasswd
+$slaveDN $slavePw $masterDN $masterPw
+$_userLoginShell $_userHomePrefix $_userGecos
+$_defaultUserGid $_defaultComputerGid $_skeletonDir 
+$_userSmbHome $_userProfile $_userHomeDrive $_userScript
+$usersou $computersou $groupsou
+);
+
+
+##############################################################################
+#
+# General Configuration
+#
+##############################################################################
+
+#
+# UID and GID starting at...
+#
+
+$UID_START = 1000;
+$GID_START = 1000;
+
+# Put your own SID
+# to obtain this number do: # net getlocalsid
+our $SID='S-1-5-21-636805976-1992644568-3666589737';
+
+##############################################################################
+#
+# LDAP Configuration
+#
+##############################################################################
+
+# Notes: to use to dual ldap servers backend for Samba, you must patch
+# Samba with the dual-head patch from IDEALX. If not using this patch
+# just use the same server for slaveLDAP and masterLDAP.
+#
+# Slave LDAP : needed for read operations
+#
+# Ex: $slaveLDAP = "127.0.0.1";
+$slaveLDAP = "127.0.0.1";
+
+$slavePort = "389";
+
+# 
+# Master LDAP : needed for write operations
+#
+# Ex: $masterLDAP = "127.0.0.1";
+$masterLDAP = "127.0.0.1";
+
+
+#
+# Master Port
+# 389 636
+# Ex: $masterPort = "
+$masterPort = "389";
+
+#
+# Use SSL for LDAP
+#
+$ldapSSL = "0";
+
+#
+# LDAP Suffix
+#
+# Ex: $suffix = "dc=IDEALX,dc=ORG";
+$suffix = "dc=IDEALX,dc=ORG";
+
+
+# 
+# Where are stored Users
+#
+# Ex: $usersdn = "ou=Users,$suffix"; for ou=Users,dc=IDEALX,dc=ORG
+$usersou = q(_USERS_);
+
+$usersdn = "ou=$usersou,$suffix";
+
+# 
+# Where are stored Computers
+#
+# Ex: $computersdn = "ou=Computers,$suffix"; for ou=Computers,dc=IDEALX,dc=ORG
+$computersou = q(_COMPUTERS_);
+
+$computersdn = "ou=$computersou,$suffix";
+
+# 
+# Where are stored Groups
+# 
+# Ex $groupsdn = "ou=Groups,$suffix"; for ou=Groups,dc=IDEALX,dc=ORG
+$groupsou = q(_GROUPS_);
+
+$groupsdn = "ou=$groupsou,$suffix";
+
+#
+# Default scope Used
+#
+$scope = "sub";
+
+#
+# Credential Configuration
+#
+# Bind DN used 
+# Ex: $binddn = "cn=Manager,$suffix"; for cn=Manager,dc=IDEALX,dc=org
+$binddn = "cn=Manager,$suffix";
+#
+# Bind DN passwd used
+# Ex: $bindpasswd = 'secret'; for 'secret'
+$bindpasswd = "secret";
+
+#
+# Notes: if using dual ldap patch, you can specify to different configuration
+# By default, we will use the same DN (so it will work for standard Samba 
+# release)
+#
+$slaveDN = $binddn;
+$slavePw = $bindpasswd;
+$masterDN = $binddn;
+$masterPw = $bindpasswd;
+
+##############################################################################
+# 
+# Unix Accounts Configuration
+# 
+##############################################################################
+
+# Login defs
+#
+# Default Login Shell
+#
+# Ex: $_userLoginShell = q(/bin/bash);
+$_userLoginShell = q(_LOGINSHELL_);
+
+#
+# Home directory prefix (without username)
+#
+#Ex: $_userHomePrefix = q(/home/);
+$_userHomePrefix = q(_HOMEPREFIX_);
+
+#
+# Gecos
+#
+$_userGecos = q(System User);
+
+#
+# Default User (POSIX and Samba) GID
+#
+$_defaultUserGid = 100;
+
+#
+# Default Computer (Samba) GID
+#
+$_defaultComputerGid = 553;
+
+#
+# Skel dir
+#
+$_skeletonDir = q(/etc/skel);
+
+##############################################################################
+#
+# SAMBA Configuration
+#
+##############################################################################
+
+#
+# The UNC path to home drives location without the username last extension
+# (will be dynamically prepended)
+# Ex: q(\\\\My-PDC-netbios-name\\homes) for \\My-PDC-netbios-name\homes
+$_userSmbHome = q(\\\\_PDCNAME_\\homes);
+
+#
+# The UNC path to profiles locations without the username last extension
+# (will be dynamically prepended)
+# Ex: q(\\\\My-PDC-netbios-name\\profiles) for \\My-PDC-netbios-name\profiles
+$_userProfile = q(\\\\_PDCNAME_\\profiles\\);
+
+# 
+# The default Home Drive Letter mapping
+# (will be automatically mapped at logon time if home directory exist)
+# Ex: q(U:) for U:
+$_userHomeDrive = q(_HOMEDRIVE_);
+
+#
+# The default user netlogon script name
+# if not used, will be automatically username.cmd
+#
+#$_userScript = q(startup.cmd); # make sure script file is edited under dos
+
+
+##############################################################################
+#
+# SMBLDAP-TOOLS Configuration (default are ok for a RedHat)
+#
+##############################################################################
+
+# Allows not to use smbpasswd (if $with_smbpasswd == 0 in smbldap_conf.pm) but
+# prefer mkntpwd... most of the time, it's a wise choice :-) 
+$with_smbpasswd = 0;
+$smbpasswd = "/usr/bin/smbpasswd";
+$mk_ntpasswd = "/usr/local/sbin/mkntpwd";
+
+if ( $ldapSSL eq "0" ) {
+       $slaveURI = "ldap://$slaveLDAP:$slavePort";
+       $masterURI = "ldap://$masterLDAP:$masterPort";
+}
+elsif ( $ldapSSL eq "1" ) {
+       $slaveURI = "ldaps://$slaveLDAP:$slavePort";
+       $masterURI = "ldaps://$masterLDAP:$masterPort";
+}
+else {
+       die "ldapSSL option must be either 0 or 1.\n";
+}
+       
+
+$ldap_path = "/usr/bin";
+$ldap_opts = "-x";
+$ldapsearch = "$ldap_path/ldapsearch $ldap_opts -H $slaveURI -D '$slaveDN' -w '$slavePw'";
+$ldapsearchnobind = "$ldap_path/ldapsearch $ldap_opts -H $slaveURI";
+$ldapmodify = "$ldap_path/ldapmodify $ldap_opts -H $masterURI -D '$masterDN' -w '$masterPw'";
+$ldappasswd = "$ldap_path/ldappasswd $ldap_opts -H $masterURI -D '$masterDN' -w '$masterPw'";
+$ldapadd = "$ldap_path/ldapadd $ldap_opts -H $masterURI -D '$masterDN' -w '$masterPw'";
+$ldapdelete = "$ldap_path/ldapdelete $ldap_opts -H $masterURI -D '$masterDN' -w '$masterPw'";
+$ldapmodrdn = "$ldap_path/ldapmodrdn $ldap_opts -H $masterURI -D '$masterDN' -w '$masterPw'";
+
+
+
+1;
+
+# - The End
diff --git a/examples/LDAP/smbldap-tools/smbldap_tools.pm b/examples/LDAP/smbldap-tools/smbldap_tools.pm
new file mode 100755 (executable)
index 0000000..ad6ef74
--- /dev/null
@@ -0,0 +1,710 @@
+#! /usr/bin/perl
+use strict;
+package smbldap_tools;
+use smbldap_conf;
+use Net::LDAP;
+
+#  This code was developped by IDEALX (http://IDEALX.org/) and
+#  contributors (their names can be found in the CONTRIBUTORS file).
+#
+#                 Copyright (C) 2001-2002 IDEALX
+#
+#  This program is free software; you can redistribute it and/or
+#  modify it under the terms of the GNU General Public License
+#  as published by the Free Software Foundation; either version 2
+#  of the License, or (at your option) any later version.
+#
+#  This program is distributed in the hope that it will be useful,
+#  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#  GNU General Public License for more details.
+#
+#  You should have received a copy of the GNU General Public License
+#  along with this program; if not, write to the Free Software
+#  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+#  USA.
+
+
+# ugly funcs using global variables and spawning openldap clients
+
+use vars       qw($VERSION @ISA @EXPORT @EXPORT_OK %EXPORT_TAGS);
+use Exporter;
+$VERSION = 1.00;
+
+@ISA = qw(Exporter);
+
+@EXPORT = qw(
+get_user_dn
+get_group_dn
+is_samba_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
+get_homedir
+read_user
+read_group
+find_groups_of
+parse_group
+group_remove_member
+group_get_members
+do_ldapadd
+do_ldapmodify
+get_user_dn2
+);
+
+# dn_line = get_user_dn($username)
+# where dn_line is like "dn: a=b,c=d"
+
+#sub ldap_search
+#{
+#my ($local_base,$local_scope,$local_filtre)=@_;
+#}
+
+
+
+sub get_user_dn
+{
+    my $user = shift;
+    my $dn='';
+    my $ldap = Net::LDAP->new($slaveLDAP) or die "erreur LDAP";
+    $ldap->bind ;
+    my  $mesg = $ldap->search (    base   => $suffix,
+                                  scope => $scope,
+                                  filter => "(&(objectclass=posixAccount)(uid=$user))"
+                              );
+    $mesg->code && die $mesg->error;
+    foreach my $entry ($mesg->all_entries) {
+       $dn= $entry->dn;}
+    $ldap->unbind;
+    chomp($dn);
+    if ($dn eq '') {
+       return undef;
+    }
+    $dn="dn: ".$dn;
+    return $dn;
+}
+
+
+sub get_user_dn2     ## migré
+{
+    my $user = shift;
+    my $dn='';
+    my $ldap = Net::LDAP->new($slaveLDAP) or die "erreur LDAP";
+    $ldap->bind ;
+    my  $mesg = $ldap->search (    base   => $suffix,
+                                  scope => $scope,
+                               filter => "(&(objectclass=posixAccount)(uid=$user))"
+                              );
+    # $mesg->code && warn $mesg->error;
+    if ($mesg->code)
+      {
+         print("Code erreur : ",$mesg->code,"\n");
+         print("Message d'erreur : ",$mesg->error,"\n");
+         return (0,undef);
+      }
+
+    foreach my $entry ($mesg->all_entries) {
+       $dn= $entry->dn;
+    }
+    $ldap->unbind;
+    chomp($dn);
+    if ($dn eq '') {
+       return (1,undef);
+    }
+    $dn="dn: ".$dn;
+    return (1,$dn);
+}
+
+
+sub get_group_dn
+  {
+      my $group = shift;
+      my $dn='';
+      my $ldap = Net::LDAP->new($slaveLDAP) or die "erreur LDAP";
+      $ldap->bind ;
+      my  $mesg = $ldap->search (    base   => $groupsdn,
+                                    scope => $scope,
+                                    filter => "(&(objectclass=posixGroup)(|(cn=$group)(gidNumber=$group)))"
+                               );
+      $mesg->code && die $mesg->error;
+      foreach my $entry ($mesg->all_entries) {
+         $dn= $entry->dn;}
+      $ldap->unbind;
+      chomp($dn);
+      if ($dn eq '') {
+         return undef;
+      }
+      $dn="dn: ".$dn;
+      return $dn;
+  }
+
+# return (success, dn)
+# bool = is_samba_user($username)
+sub is_samba_user
+  {
+      my $user = shift;
+      my $ldap = Net::LDAP->new($slaveLDAP) or die "erreur LDAP";
+      $ldap->bind ;
+      my $mesg = $ldap->search (    base   => $suffix,
+                                   scope => $scope,
+                                   filter => "(&(objectClass=sambaSamAccount)(uid=$user))"
+                              );
+      $mesg->code && die $mesg->error;
+      $ldap->unbind;
+      return ($mesg->count ne 0);
+  }
+
+
+# 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 );
+      if ($mesg->code eq 0)
+       {
+           $ldap->unbind;
+           return 1;
+       }
+      else
+       {
+           if($ldap->bind()) {
+               $ldap->unbind;
+               return 0;
+           } else {
+               print ("Le serveur LDAP est indisponible.\nVérifier le serveur, les câblages, ...");
+               $ldap->unbind;
+               return 0;
+           } die "Problème : Contacter votre administrateur";
+       }
+}
+
+# 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;
+  }
+
+# success = add_posix_machine($user, $uid, $gid)
+sub add_posix_machine
+  {
+      my ($user, $uid, $gid) = @_;
+      my $tmpldif =
+       "dn: uid=$user,$computersdn
+objectclass: inetOrgPerson
+objectclass: posixAccount
+sn: $user
+cn: $user
+uid: $user
+uidNumber: $uid
+gidNumber: $gid
+homeDirectory: /dev/null
+loginShell: /bin/false
+description: Computer
+
+";
+
+      die "$0: error while adding posix account to machine $user\n"
+       unless (do_ldapadd($tmpldif) == 0);
+      undef $tmpldif;
+      return 1;
+  }
+
+# 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;
+
+      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 $tmpldif =
+       "dn: uid=$user,$computersdn
+changetype: modify
+objectclass: inetOrgPerson
+objectclass: posixAccount
+objectClass: sambaSamAccount
+sambaPwdLastSet: 0
+sambaLogonTime: 0
+sambaLogoffTime: 2147483647
+sambaKickoffTime: 2147483647
+sambaPwdCanChange: 0
+sambaPwdMustChange: 2147483647
+sambaAcctFlags: [W          ]
+sambaLMPassword: $lmpassword
+sambaNTPassword: $ntpassword
+sambaSID: $smbldap_conf::SID-$sambaSID
+sambaPrimaryGroupSID: $smbldap_conf::SID-0
+
+";
+
+      die "$0: error while adding samba account to $user\n"
+       unless (do_ldapmodify($tmpldif) == 0);
+      undef $tmpldif;
+
+      return 1;
+  }
+
+
+
+sub group_add_user
+  {
+      my ($group, $userid) = @_;
+      my $members='';
+      my $dn_line = get_group_dn($group);
+      if (!defined($dn_line)) {
+         return 1;
+      }
+      my $dn = get_dn_from_line($dn_line);
+
+      my $ldap = Net::LDAP->new($slaveLDAP) or die "erreur LDAP";
+      $ldap->bind ;
+      my  $mesg = $ldap->search (    base   =>$dn, scope => "base", filter => "(objectClass=*)" );
+      $mesg->code && die $mesg->error;
+      foreach my $entry ($mesg->all_entries){
+         foreach my $attr ($entry->attributes)
+           {
+               if ($attr=~/\bmemberUid\b/){
+                   foreach my $ent($entry->get_value($attr)) { $members.= $attr.": ".$ent."\n"; }
+               }
+           }
+      }
+      $ldap->unbind;
+      chomp($members);
+      # user already member ?
+      if ($members =~ m/^memberUid: $userid/) {
+         return 2;
+      }
+      my $mods = "";
+      if ($members ne '') {
+         $mods="$dn_line
+changetype: modify
+replace: memberUid
+$members
+memberUid: $userid
+
+";
+      } else {
+         $mods="$dn_line
+changetype: modify
+add: memberUid
+memberUid: $userid
+
+";
+      }
+    #print "$mods\n";
+      my $tmpldif =
+       "$mods
+";
+
+      die "$0: error while modifying group $group\n"
+       unless (do_ldapmodify($tmpldif) == 0);
+      undef $tmpldif;
+      return 0;
+  }
+
+sub add_grouplist_user
+  {
+      my ($grouplist, $user) = @_;
+      my @array = split(/,/, $grouplist);
+      foreach my $group (@array) {
+         group_add_user($group, $user);
+      }
+  }
+
+# XXX FIXME : sambaAcctFlags |= D, and not sambaAcctFlags = D
+sub disable_user
+  {
+      my $user = shift;
+      my $dn_line;
+
+      if (!defined($dn_line = get_user_dn($user))) {
+         print "$0: user $user doesn't exist\n";
+         exit (10);
+      }
+
+      my $tmpldif =
+       "dn: $dn_line
+changetype: modify
+replace: userPassword
+userPassword: {crypt}!x
+
+";
+
+      die "$0: error while modifying user $user\n"
+       unless (do_ldapmodify($tmpldif) == 0);
+      undef $tmpldif;
+
+      if (is_samba_user($user)) {
+
+         my $tmpldif =
+           "dn: $dn_line
+changetype: modify
+replace: sambaAcctFlags
+sambaAcctFlags: [D       ]
+
+";
+
+         die "$0: error while modifying user $user\n"
+           unless (do_ldapmodify($tmpldif) == 0);
+         undef $tmpldif;
+      }
+  }
+
+# delete_user($user)
+sub delete_user
+  {
+      my $user = shift;
+      my $dn_line;
+
+      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);
+      system "$ldapdelete $dn >/dev/null";
+  }
+
+# $success = 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) {
+         system "/etc/init.d/nscd stop > /dev/null 2>&1";
+      }
+      if (!defined($gid)) {
+         while (defined(getgrgid($GID_START))) {
+             $GID_START++;
+         }
+         $gid = $GID_START;
+      } else {
+         if (!defined($force)) {
+             if (defined(getgrgid($gid))) {
+                 return 0;
+             }
+         }
+      }
+      if ($nscd_status == 0) {
+         system "/etc/init.d/nscd start > /dev/null 2>&1";
+      }
+      my $tmpldif =
+       "dn: cn=$gname,$groupsdn
+objectclass: posixGroup
+cn: $gname
+gidNumber: $gid
+
+";
+
+      die "$0: error while adding posix group $gname\n"
+       unless (do_ldapadd($tmpldif) == 0);
+      undef $tmpldif;
+      return 1;
+  }
+
+# $homedir = get_homedir ($user)
+sub get_homedir
+  {
+      my $user = shift;
+      my $homeDir='';
+      #  my $homeDir=`$ldapsearch -b '$suffix' -s '$scope' '(&(objectclass=posixAccount)(uid=$user))' | grep "^homeDirectory:"`;
+      my $ldap = Net::LDAP->new($slaveLDAP) or die "erreur LDAP";
+      $ldap->bind ;
+      my  $mesg = $ldap->search (    base   =>$suffix, scope => $scope, filter => "(&(objectclass=posixAccount)(uid=$user))" );
+      $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)) {
+                       $homeDir.= $attr.": ".$ent."\n";
+                   }
+               }
+           }
+      }
+      $ldap->unbind;
+      chomp $homeDir;
+      if ($homeDir eq '') {
+         return undef;
+      }
+      $homeDir =~ s/^homeDirectory: //;
+      return $homeDir;
+  }
+
+# search for an user
+sub read_user
+  {
+      my $user = shift;
+      my $lines ='';
+      my $ldap = Net::LDAP->new($slaveLDAP) or die "erreur LDAP";
+      $ldap->bind ;
+      my  $mesg = $ldap->search (  # perform a search
+                                base   => $suffix,
+                                scope => $scope,
+                                filter => "(&(objectclass=posixAccount)(uid=$user))"
+                               );
+
+      $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";
+             }
+         }
+      }
+      $ldap->unbind;   # take down sessio(n
+      chomp $lines;
+      if ($lines eq '') {
+         return undef;
+      }
+      return $lines;
+  }
+
+# search for a group
+sub read_group
+  {
+      my $user = shift;
+      my $lines ='';
+      my $ldap = Net::LDAP->new($slaveLDAP) or die "erreur LDAP";
+      $ldap->bind ;
+      my  $mesg = $ldap->search (  # perform a search
+                                base   => $groupsdn,
+                                scope => $scope,
+                                filter => "(&(objectclass=posixGroup)(cn=$user))"
+                               );
+
+      $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";
+             }
+         }
+      }
+
+      $ldap->unbind;   # take down sessio(n
+      chomp $lines;
+      if ($lines eq '') {
+         return undef;
+      }
+      return $lines;
+  }
+
+# find groups of a given user
+##### MODIFIE ########
+sub find_groups_of
+  {
+      my $user = shift;
+      my $lines ='';
+      my $ldap = Net::LDAP->new($slaveLDAP) or die "erreur LDAP";
+      $ldap->bind ;
+      my  $mesg = $ldap->search (  # perform a search
+                                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->unbind;
+      chomp($lines);
+      if ($lines eq '') {return undef; }
+      return $lines;
+  }
+
+# 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 $gname = $userGidNumber;
+         my $gidnum = getgrnam($gname);
+         if ($gidnum !~ /\d+/) {
+             return -1;
+         } else {
+             $userGidNumber = $gidnum;
+         }
+      } elsif (!defined(getgrgid($userGidNumber))) {
+         return -2;
+      }
+      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)) {
+         return 0;
+      }
+
+      my $ldap = Net::LDAP->new($slaveLDAP) or die "erreur LDAP";
+      $ldap->bind ;
+      my  $mesg = $ldap->search (    base   => $groupsdn,
+                                    scope => $scope,
+                                    filter => "(&(objectclass=posixgroup)(cn=$group))"
+                               );
+      $mesg->code && die $mesg->error;
+      foreach my $entry ($mesg->all_entries){
+         foreach my $attr ($entry->attributes)
+           {
+               if ($attr=~/\bmemberUid\b/){
+                   foreach my $ent($entry->get_value($attr)) {
+                       $members.= $attr.": ".$ent."\n";
+                   }
+               }
+           }
+      }
+      #print "Valeurs de members :\n$members";
+      $ldap->unbind;
+      #    my $members = `$ldapsearch -b '$groupsdn' -s '$scope' '(&(objectclass=posixgroup)(cn=$group))' | grep -i "^memberUid:"`;
+      # print "avant ---\n$members\n";
+      $members =~ s/memberUid: $user\n//;
+      #print "après ---\n$members\n";
+      chomp($members);
+
+      my $header;
+      if ($members eq '') {
+         $header = "changetype: modify\n";
+         $header .= "delete: memberUid";
+      } else {
+         $header = "changetype: modify\n";
+         $header .= "replace: memberUid";
+      }
+
+      my $tmpldif =
+"$grp_line
+$header
+$members
+";
+
+      #print "Valeur du tmpldif : \n$tmpldif";
+      die "$0: error while modifying group $group\n"
+       unless (do_ldapmodify($tmpldif) == 0);
+      undef $tmpldif;
+
+      $ldap->unbind;
+      return 1;
+  }
+
+sub group_get_members
+  {
+      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  $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/){
+                 foreach my $ent($entry->get_value($attr)) { push (@resultat,$ent); }
+             }
+         }
+      }
+      return @resultat;
+  }
+
+sub file_write {
+    my ($filename, $filecontent) = @_;
+    local *FILE;
+    open (FILE, "> $filename") ||
+      die "Cannot open $filename for writing: $!\n";
+    print FILE $filecontent;
+    close FILE;
+}
+
+# wrapper for ldapadd
+sub do_ldapadd2
+  {
+      my $ldif = shift;
+      my $tempfile = "/tmp/smbldapadd.$$";
+      file_write($tempfile, $ldif);
+
+      my $rc = system "$ldapadd < $tempfile >/dev/null";
+      unlink($tempfile);
+      return $rc;
+  }
+
+sub do_ldapadd
+  {
+      my $ldif = shift;
+      my $FILE = "|$ldapadd >/dev/null";
+      open (FILE, $FILE) || die "$!\n";
+      print FILE <<EOF;
+$ldif
+EOF
+      ;
+      close FILE;
+      my $rc = $?;
+      return $rc;
+  }
+
+# wrapper for ldapmodify
+sub do_ldapmodify2
+  {
+      my $ldif = shift;
+      my $tempfile = "/tmp/smbldapmod.$$";
+      file_write($tempfile, $ldif);
+      my $rc = system "$ldapmodify -r < $tempfile >/dev/null";
+      unlink($tempfile);
+      return $rc;
+  }
+
+sub do_ldapmodify
+  {
+      my $ldif = shift;
+      my $FILE = "|$ldapmodify -r >/dev/null";
+      open (FILE, $FILE) || die "$!\n";
+      print FILE <<EOF;
+$ldif
+EOF
+      ;
+      close FILE;
+      my $rc = $?;
+      return $rc;
+  }
+
+1;
+
diff --git a/examples/VFS/shadow_copy_test.c b/examples/VFS/shadow_copy_test.c
new file mode 100644 (file)
index 0000000..d2b7206
--- /dev/null
@@ -0,0 +1,83 @@
+/* 
+ * TEST implementation of an Shadow Copy module
+ *
+ * Copyright (C) Stefan Metzmacher     2003
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *  
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *  
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include "includes.h"
+
+#undef DBGC_CLASS
+#define DBGC_CLASS DBGC_VFS
+
+/* USE THIS MODULE ONLY FOR TESTING!!!! */
+
+/*    
+    For this share
+    Z:\
+
+    the ShadowCopies are in this directories
+
+    Z:\@GMT-2003.08.05-12.00.00\
+    Z:\@GMT-2003.08.05-12.01.00\
+    Z:\@GMT-2003.08.05-12.02.00\
+
+    e.g.
+    
+    Z:\testfile.txt
+    Z:\@GMT-2003.08.05-12.02.00\testfile.txt
+
+    or:
+
+    Z:\testdir\testfile.txt
+    Z:\@GMT-2003.08.05-12.02.00\testdir\testfile.txt
+
+
+    Note: Files must differ to be displayed via Windows Explorer!
+         Directories are always displayed...    
+*/
+
+static int test_get_shadow_copy_data(vfs_handle_struct *handle, files_struct *fsp, SHADOW_COPY_DATA *shadow_copy_data, BOOL labels)
+{
+       uint32 num = 3;
+       uint32 i;
+       
+       shadow_copy_data->num_volumes = num;
+       
+       if (labels) {   
+               shadow_copy_data->labels = (SHADOW_COPY_LABEL *)talloc_zero(shadow_copy_data->mem_ctx,(num)*sizeof(SHADOW_COPY_LABEL));
+               for (i=0;i<num;i++) {
+                       snprintf(shadow_copy_data->labels[i], sizeof(SHADOW_COPY_LABEL), "@GMT-2003.08.05-12.%02u.00",i);
+               }
+       } else {
+               shadow_copy_data->labels = NULL;
+       }
+
+       return 0;
+}
+
+/* VFS operations structure */
+
+static vfs_op_tuple shadow_copy_test_ops[] = { 
+       {SMB_VFS_OP(test_get_shadow_copy_data), SMB_VFS_OP_GET_SHADOW_COPY_DATA,SMB_VFS_LAYER_OPAQUE},
+
+       {SMB_VFS_OP(NULL),                      SMB_VFS_OP_NOOP,                SMB_VFS_LAYER_NOOP}
+};
+
+NTSTATUS init_module(void)
+{
+       return smb_register_vfs(SMB_VFS_INTERFACE_VERSION, "shadow_copy_test", shadow_copy_test_ops);
+}
index e507dc109488f2af3382baced32b55d2bdf4fea8..de82801d858507b408e0de97afd90725d07a4113 100644 (file)
@@ -66,6 +66,11 @@ static int skel_set_quota(vfs_handle_struct *handle, connection_struct *conn, en
        return vfswrap_set_quota(NULL, conn, qtype, id, dq);
 }
 
+static int skel_get_shadow_copy_data(vfs_handle_struct *handle, files_struct *fsp, SHADOW_COPY_DATA *shadow_copy_data, BOOL labels)
+{
+       return vfswrap_get_shadow_copy_data(NULL, fsp, shadow_copy_data, labels);
+}
+
 static DIR *skel_opendir(vfs_handle_struct *handle, connection_struct *conn, const char *fname)
 {
        return vfswrap_opendir(NULL, conn, fname);
@@ -468,7 +473,8 @@ static vfs_op_tuple skel_op_tuples[] = {
        {SMB_VFS_OP(skel_disk_free),                    SMB_VFS_OP_DISK_FREE,           SMB_VFS_LAYER_OPAQUE},
        {SMB_VFS_OP(skel_get_quota),                    SMB_VFS_OP_GET_QUOTA,           SMB_VFS_LAYER_OPAQUE},
        {SMB_VFS_OP(skel_set_quota),                    SMB_VFS_OP_SET_QUOTA,           SMB_VFS_LAYER_OPAQUE},
-       
+       {SMB_VFS_OP(skel_get_shadow_copy_data),         SMB_VFS_OP_GET_SHADOW_COPY_DATA,SMB_VFS_LAYER_OPAQUE},
+
        /* Directory operations */
 
        {SMB_VFS_OP(skel_opendir),                      SMB_VFS_OP_OPENDIR,             SMB_VFS_LAYER_OPAQUE},
index b2db76c9f9669e9a538f1ab0ddadf6002fbd652b..7a326741c5ba6dc1370b57da4a4060246a863e6e 100644 (file)
@@ -65,6 +65,11 @@ static int skel_set_quota(vfs_handle_struct *handle, connection_struct *conn, en
        return SMB_VFS_NEXT_SET_QUOTA(handle, conn, qtype, id, dq);
 }
 
+static int skel_get_shadow_copy_data(vfs_handle_struct *handle, files_struct *fsp, SHADOW_COPY_DATA *shadow_copy_data, BOOL labels)
+{
+       return SMB_VFS_NEXT_GET_SHADOW_COPY_DATA(handle, fsp, shadow_copy_data, labels);
+}
+
 static DIR *skel_opendir(vfs_handle_struct *handle, connection_struct *conn, const char *fname)
 {
        return SMB_VFS_NEXT_OPENDIR(handle, conn, fname);
@@ -437,7 +442,8 @@ static vfs_op_tuple skel_op_tuples[] = {
        {SMB_VFS_OP(skel_disk_free),                    SMB_VFS_OP_DISK_FREE,           SMB_VFS_LAYER_TRANSPARENT},
        {SMB_VFS_OP(skel_get_quota),                    SMB_VFS_OP_GET_QUOTA,           SMB_VFS_LAYER_TRANSPARENT},
        {SMB_VFS_OP(skel_set_quota),                    SMB_VFS_OP_SET_QUOTA,           SMB_VFS_LAYER_TRANSPARENT},
-       
+       {SMB_VFS_OP(skel_get_shadow_copy_data),         SMB_VFS_OP_GET_SHADOW_COPY_DATA,SMB_VFS_LAYER_TRANSPARENT},
+
        /* Directory operations */
 
        {SMB_VFS_OP(skel_opendir),                      SMB_VFS_OP_OPENDIR,             SMB_VFS_LAYER_TRANSPARENT},
index 0815b1ae66dc0b15453fb6a404394df196c0bd63..ea71e03d073c662e9c5065c2fd2309f12e86b77e 100644 (file)
@@ -1,6 +1,6 @@
 /*
  *  Set printer capabilities in DsDriver Keys on remote printer
- *  Copyright (C) Jim McDonough         2002.
+ *  Copyright (C) Jim McDonough        <jmcd@us.ibm.com> 2002.
  *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
diff --git a/examples/sam/Makefile.in b/examples/sam/Makefile.in
deleted file mode 100644 (file)
index d5df346..0000000
+++ /dev/null
@@ -1,28 +0,0 @@
-CC             = @CC@
-CFLAGS         = @CFLAGS@
-CPPFLAGS       = @CPPFLAGS@
-LDFLAGS                = @LDFLAGS@
-LDSHFLAGS      = -shared
-srcdir         = @builddir@
-FLAGS          =  $(CFLAGS) -Iinclude -I$(srcdir)/include -I$(srcdir)/ubiqx -I$(srcdir)/smbwrapper  -I. $(CPPFLAGS) -I$(srcdir)
-
-SAM_OBJS       = sam_skel.so
-
-# Default target
-
-default: $(SAM_OBJS)
-
-# Pattern rules
-
-%.so: %.o
-       $(CC) $(LDSHFLAGS) $(LDFLAGS) -o $@ $<
-
-%.o: %.c
-       $(CC) $(FLAGS) -c $<
-
-# Misc targets
-
-clean:
-       rm -rf .libs
-       rm -f core *~ *% *.bak \
-       $(SAM_OBJ) $(SAM_OBJS)
diff --git a/examples/sam/README b/examples/sam/README
deleted file mode 100644 (file)
index 9e9fbb2..0000000
+++ /dev/null
@@ -1,29 +0,0 @@
-README for Samba SAM Database examples
-====================================================
-26-08-2002 Stefan (metze) Metzmacher <metze@metzemix.de>
-
-Every module MUST have a sam_version() function.
-
-this is defined in include/sam.h:
-#define SAM_MODULE_VERSIONING_MAGIC \
-int sam_version(void)\
-{\
-       return SAM_INTERFACE_VERSION;\
-}
-
-You MUST add this line inside a module:
-SAM_MODULE_VERSIONING_MAGIC
-
-
-The sam_skel.c file in this directory contains a very basic example of 
-a SAM plugin. It just prints the name of the function that is executed using
-DEBUG. Maybe it's nice to include some of the arguments to the function in the 
-future too..
-
-New SAM plugins should go into the samba lib directory, (/usr/lib/samba/ 
-for most distributions) and should be prefixed with 'sam_' and should go into the 
-subdir sam/. The SAM subsystem will search in /usr/lib/samba/sam and fall back to 
-/usr/lib/samba/ . 
-An example path would be: 
-/usr/lib/samba/sam/sam_skel.so
-
diff --git a/examples/sam/sam_skel.c b/examples/sam/sam_skel.c
deleted file mode 100644 (file)
index da3a375..0000000
+++ /dev/null
@@ -1,250 +0,0 @@
-/*
-   Unix SMB/CIFS implementation.
-   this is a skeleton for SAM backend modules.
-       
-   Copyright (C) Stefan (metze) Metzmacher             2002
-   Copyright (C) Jelmer Vernooij                               2002
-
-   This program is free software; you can redistribute it and/or modify
-   it under the terms of the GNU General Public License as published by
-   the Free Software Foundation; either version 2 of the License, or
-   (at your option) any later version.
-
-   This program is distributed in the hope that it will be useful,
-   but WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-   GNU General Public License for more details.
-
-   You should have received a copy of the GNU General Public License
-   along with this program; if not, write to the Free Software
-   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-*/
-
-#include "includes.h"
-
-static int sam_skel_debug_level = DBGC_SAM;
-
-#undef DBGC_CLASS
-#define DBGC_CLASS sam_skel_debug_level
-
-/* define the version of the SAM interface */ 
-SAM_MODULE_VERSIONING_MAGIC
-
-/* General API */
-
-NTSTATUS sam_skel_get_sec_desc(const SAM_METHODS *sam_methods, const NT_USER_TOKEN *access_token, const DOM_SID *sid, SEC_DESC **sd)
-{
-       DEBUG(0,("sam_skel: %s was called!\n",__FUNCTION__));
-       return NT_STATUS_NOT_IMPLEMENTED;
-}
-
-NTSTATUS sam_skel_set_sec_desc(const SAM_METHODS *sam_methods, const NT_USER_TOKEN *access_token, const DOM_SID *sid, const SEC_DESC *sd)
-{
-       DEBUG(0,("sam_skel: %s was called!\n",__FUNCTION__));
-       return NT_STATUS_NOT_IMPLEMENTED;
-}
-
-       
-NTSTATUS sam_skel_lookup_sid(const SAM_METHODS *sam_methods, const NT_USER_TOKEN *access_token, const DOM_SID *sid, char **name, uint32 *type)
-{
-       DEBUG(0,("sam_skel: %s was called!\n",__FUNCTION__));
-       return NT_STATUS_NOT_IMPLEMENTED;
-}
-
-NTSTATUS sam_skel_lookup_name(const SAM_METHODS *sam_methods, const NT_USER_TOKEN *access_token, const char *name, DOM_SID **sid, uint32 *type)
-{
-       DEBUG(0,("sam_skel: %s was called!\n",__FUNCTION__));
-       return NT_STATUS_NOT_IMPLEMENTED;
-}
-
-       
-/* Domain API */
-
-NTSTATUS sam_skel_update_domain(const SAM_METHODS *sam_methods, const SAM_DOMAIN_HANDLE *domain)
-{
-       DEBUG(0,("sam_skel: %s was called!\n",__FUNCTION__));
-       return NT_STATUS_NOT_IMPLEMENTED;
-}
-
-NTSTATUS sam_skel_get_domain_handle(const SAM_METHODS *sam_methods, const NT_USER_TOKEN *access_token, uint32 access_desired, SAM_DOMAIN_HANDLE **domain)
-{
-       DEBUG(0,("sam_skel: %s was called!\n",__FUNCTION__));
-       return NT_STATUS_NOT_IMPLEMENTED;
-}
-
-
-/* Account API */
-
-NTSTATUS sam_skel_create_account(const SAM_METHODS *sam_methods, const NT_USER_TOKEN *access_token, uint32 access_desired, const char *group_name, uint16 acct_ctrl, SAM_ACCOUNT_HANDLE **account)
-{
-       DEBUG(0,("sam_skel: %s was called!\n",__FUNCTION__));
-       return NT_STATUS_NOT_IMPLEMENTED;
-}
-
-NTSTATUS sam_skel_add_account(const SAM_METHODS *sam_methods, const SAM_ACCOUNT_HANDLE *account)
-{
-       DEBUG(0,("sam_skel: %s was called!\n",__FUNCTION__));
-       return NT_STATUS_NOT_IMPLEMENTED;
-}
-
-NTSTATUS sam_skel_update_account(const SAM_METHODS *sam_methods, const SAM_ACCOUNT_HANDLE *account)
-{
-       DEBUG(0,("sam_skel: %s was called!\n",__FUNCTION__));
-       return NT_STATUS_NOT_IMPLEMENTED;
-}
-
-NTSTATUS sam_skel_delete_account(const SAM_METHODS *sam_methods, const SAM_ACCOUNT_HANDLE *account)
-{
-       DEBUG(0,("sam_skel: %s was called!\n",__FUNCTION__));
-       return NT_STATUS_NOT_IMPLEMENTED;
-}
-
-NTSTATUS sam_skel_enum_accounts(const SAM_METHODS *sam_methods, const NT_USER_TOKEN *access_token, uint16 acct_ctrl, uint32 *account_count, SAM_ACCOUNT_ENUM **accounts)
-{
-       DEBUG(0,("sam_skel: %s was called!\n",__FUNCTION__));
-       return NT_STATUS_NOT_IMPLEMENTED;
-}
-
-
-NTSTATUS sam_skel_get_account_by_sid(const SAM_METHODS *sam_methods, const NT_USER_TOKEN *access_token, uint32 access_desired, const DOM_SID *accountsid, SAM_ACCOUNT_HANDLE **account)
-{
-       DEBUG(0,("sam_skel: %s was called!\n",__FUNCTION__));
-       return NT_STATUS_NOT_IMPLEMENTED;
-}
-
-NTSTATUS sam_skel_get_account_by_name(const SAM_METHODS *sam_methods, const NT_USER_TOKEN *access_token, uint32 access_desired, const char *name, SAM_ACCOUNT_HANDLE **account)
-{
-       DEBUG(0,("sam_skel: %s was called!\n",__FUNCTION__));
-       return NT_STATUS_NOT_IMPLEMENTED;
-}
-
-
-/* Group API */
-
-NTSTATUS sam_skel_create_group(const SAM_METHODS *sam_methods, const NT_USER_TOKEN *access_token, uint32 access_desired, const char *account_name, uint16 group_ctrl, SAM_GROUP_HANDLE **group)
-{
-       DEBUG(0,("sam_skel: %s was called!\n",__FUNCTION__));
-       return NT_STATUS_NOT_IMPLEMENTED;
-}
-
-NTSTATUS sam_skel_add_group(const SAM_METHODS *sam_methods, const SAM_GROUP_HANDLE *group)
-{
-       DEBUG(0,("sam_skel: %s was called!\n",__FUNCTION__));
-       return NT_STATUS_NOT_IMPLEMENTED;
-}
-
-NTSTATUS sam_skel_update_group(const SAM_METHODS *sam_methods, const SAM_GROUP_HANDLE *group)
-{
-       DEBUG(0,("sam_skel: %s was called!\n",__FUNCTION__));
-       return NT_STATUS_NOT_IMPLEMENTED;
-}
-
-NTSTATUS sam_skel_delete_group(const SAM_METHODS *sam_methods, const SAM_GROUP_HANDLE *group)
-{
-       DEBUG(0,("sam_skel: %s was called!\n",__FUNCTION__));
-       return NT_STATUS_NOT_IMPLEMENTED;
-}
-
-NTSTATUS sam_skel_enum_groups(const SAM_METHODS *sam_methods, const NT_USER_TOKEN *access_token, uint16 group_ctrl, uint32 *groups_count, SAM_GROUP_ENUM **groups)
-{
-       DEBUG(0,("sam_skel: %s was called!\n",__FUNCTION__));
-       return NT_STATUS_NOT_IMPLEMENTED;
-}
-
-NTSTATUS sam_skel_get_group_by_sid(const SAM_METHODS *sam_methods, const NT_USER_TOKEN *access_token, uint32 access_desired, const DOM_SID *groupsid, SAM_GROUP_HANDLE **group)
-{
-       DEBUG(0,("sam_skel: %s was called!\n",__FUNCTION__));
-       return NT_STATUS_NOT_IMPLEMENTED;
-}
-
-NTSTATUS sam_skel_get_group_by_name(const SAM_METHODS *sam_methods, const NT_USER_TOKEN *access_token, uint32 access_desired, const char *name, SAM_GROUP_HANDLE **group)
-{
-       DEBUG(0,("sam_skel: %s was called!\n",__FUNCTION__));
-       return NT_STATUS_NOT_IMPLEMENTED;
-}
-
-
-NTSTATUS sam_skel_add_member_to_group(const SAM_METHODS *sam_methods, const SAM_GROUP_HANDLE *group, const SAM_GROUP_MEMBER *member)
-{
-       DEBUG(0,("sam_skel: %s was called!\n",__FUNCTION__));
-       return NT_STATUS_NOT_IMPLEMENTED;
-}
-
-NTSTATUS sam_skel_delete_member_from_group(const SAM_METHODS *sam_methods, const SAM_GROUP_HANDLE *group, const SAM_GROUP_MEMBER *member)
-{
-       DEBUG(0,("sam_skel: %s was called!\n",__FUNCTION__));
-       return NT_STATUS_NOT_IMPLEMENTED;
-}
-
-NTSTATUS sam_skel_enum_groupmembers(const SAM_METHODS *sam_methods, const SAM_GROUP_HANDLE *group, uint32 *members_count, SAM_GROUP_MEMBER **members)
-{
-       DEBUG(0,("sam_skel: %s was called!\n",__FUNCTION__));
-       return NT_STATUS_NOT_IMPLEMENTED;
-}
-
-
-NTSTATUS sam_skel_get_groups_of_sid(const SAM_METHODS *sam_methods, const NT_USER_TOKEN *access_token, const DOM_SID **sids, uint16 group_ctrl, uint32 *group_count, SAM_GROUP_ENUM **groups)
-{
-       DEBUG(0,("sam_skel: %s was called!\n",__FUNCTION__));
-       return NT_STATUS_NOT_IMPLEMENTED;
-}
-
-NTSTATUS sam_init(SAM_METHODS *sam_methods, const char *module_params)
-{
-       /* Functions your SAM module doesn't provide should be set 
-        * to NULL */
-
-       sam_methods->sam_get_sec_desc = sam_skel_get_sec_desc;
-       sam_methods->sam_set_sec_desc = sam_skel_set_sec_desc;
-       
-       sam_methods->sam_lookup_sid = sam_skel_lookup_sid;
-       sam_methods->sam_lookup_name = sam_skel_lookup_name;
-       
-       /* Domain API */
-
-       sam_methods->sam_update_domain = sam_skel_update_domain;
-       sam_methods->sam_get_domain_handle = sam_skel_get_domain_handle;
-
-       /* Account API */
-
-       sam_methods->sam_create_account = sam_skel_create_account;
-       sam_methods->sam_add_account = sam_skel_add_account;
-       sam_methods->sam_update_account = sam_skel_update_account;
-       sam_methods->sam_delete_account = sam_skel_delete_account;
-       sam_methods->sam_enum_accounts = sam_skel_enum_accounts;
-
-       sam_methods->sam_get_account_by_sid = sam_skel_get_account_by_sid;
-       sam_methods->sam_get_account_by_name = sam_skel_get_account_by_name;
-
-       /* Group API */
-
-       sam_methods->sam_create_group = sam_skel_create_group;
-       sam_methods->sam_add_group = sam_skel_add_group;
-       sam_methods->sam_update_group = sam_skel_update_group;
-       sam_methods->sam_delete_group = sam_skel_delete_group;
-       sam_methods->sam_enum_groups = sam_skel_enum_groups;
-       sam_methods->sam_get_group_by_sid = sam_skel_get_group_by_sid;
-       sam_methods->sam_get_group_by_name = sam_skel_get_group_by_name;
-
-       sam_methods->sam_add_member_to_group = sam_skel_add_member_to_group;
-       sam_methods->sam_delete_member_from_group = sam_skel_delete_member_from_group;
-       sam_methods->sam_enum_groupmembers = sam_skel_enum_groupmembers;
-
-       sam_methods->sam_get_groups_of_sid = sam_skel_get_groups_of_sid;
-
-       sam_methods->free_private_data = NULL;
-
-
-       sam_skel_debug_level = debug_add_class("sam_skel");
-       if (sam_skel_debug_level == -1) {
-               sam_skel_debug_level = DBGC_SAM;
-               DEBUG(0, ("sam_skel: Couldn't register custom debugging class!\n"));
-       } else DEBUG(2, ("sam_skel: Debug class number of 'sam_skel': %d\n", sam_skel_debug_level));
-    
-       if(module_params)
-               DEBUG(0, ("Starting 'sam_skel' with parameters '%s' for domain %s\n", module_params, sam_methods->domain_name));
-       else
-               DEBUG(0, ("Starting 'sam_skel' for domain %s without paramters\n", sam_methods->domain_name));
-
-       return NT_STATUS_OK;
-}
index 0603623c28191b7f470e60ccd818185217b9e707..e7fac80884a4fd443bc38a7d474e7936ad5b835c 100644 (file)
 # server string is the equivalent of the NT Description field
    server string = Samba Server
 
+# Security mode. Defines in which mode Samba will operate. Possible 
+# values are share, user, server, domain and ads. Most people will want 
+# user level security. See the HOWTO Collection for details.
+   security = user
+
 # This option is important for security. It allows you to restrict
 # connections to machines which are on your local network. The
 # following example restricts access to two C class networks and
@@ -44,8 +49,8 @@
 
 # It should not be necessary to specify the print system type unless
 # it is non-standard. Currently supported print systems include:
-# bsd, sysv, plp, lprng, aix, hpux, qnx, cups
-;   printing = bsd
+# bsd, cups, sysv, plp, lprng, aix, hpux, qnx
+;   printing = cups
 
 # Uncomment this if you want a guest account, you must add this to /etc/passwd
 # otherwise the user "nobody" is used
 # Put a capping on the size of the log files (in Kb).
    max log size = 50
 
-# Security mode. Most people will want user level security. See
-# security_level.txt for details.
-   security = user
-
 # Use password server option only with security = server
 # The argument list may include:
 #   password server = My_PDC_Name [My_BDC_Name] [My_Next_BDC_Name]
 #   password server = *
 ;   password server = <NT-Server-Name>
 
-# Note: Do NOT use the now deprecated option of "domain controller"
-# This option is no longer implemented.
+# Use the realm option only with security = ads
+# Specifies the Active Directory realm the host is part of
+;   realm = MY_REALM
 
-# You may wish to use password encryption. Please read
-# the 'User database' chapter in the Samba HOWTO Collection
-# Do not enable this option unless you have read those documents
-;  encrypt passwords = yes
+# Backend to store user information in. New installations should 
+# use either tdbsam or ldapsam. smbpasswd is available for backwards 
+# compatibility. tdbsam requires no further configuration.
+;   passdb backend = tdbsam
 
 # Using the following line enables you to customise your configuration
 # on a per machine basis. The %m gets replaced with the netbios name
 ;   wins proxy = yes
 
 # DNS Proxy - tells Samba whether or not to try to resolve NetBIOS names
-# via DNS nslookups. The built-in default for versions 1.9.17 is yes,
-# this has been changed in version 1.9.18 to no.
+# via DNS nslookups. The default is NO.
    dns proxy = no 
 
+# These scripts are used on a domain controller or stand-alone 
+# machine to add or delete corresponding unix accounts
+;  add user script = /usr/sbin/useradd %u
+;  add group script = /usr/sbin/groupadd %g
+;  add machine script = /usr/sbin/adduser -n -g machines -c Machine -d /dev/null -s /bin/false %u
+;  delete user script = /usr/sbin/userdle %u
+;  delete user from group script = /usr/sbin/deluser %u %g
+;  delete group script = /usr/sbin/groupdel %g
+
+
 #============================ Share Definitions ==============================
 [homes]
    comment = Home Directories
diff --git a/examples/wins_hook/README b/examples/wins_hook/README
new file mode 100644 (file)
index 0000000..1147f57
--- /dev/null
@@ -0,0 +1,8 @@
+This is an example script for doing dynamic DNS updates from the WINS
+database. You use this by putting the full path to the script in the
+"wins hook" option in smb.conf. Remember to mark the script executable
+and to set the right domain at the top of the script.
+
+See the BIND documentation for how to enable dynamic DNS
+updates. Remember to restrict the updates as far as you can to reduce
+the security risks inherent in dynamic DNS.
diff --git a/examples/wins_hook/dns_update b/examples/wins_hook/dns_update
new file mode 100644 (file)
index 0000000..a4c1a79
--- /dev/null
@@ -0,0 +1,94 @@
+#!/bin/sh
+#
+# Example script for "wins hook".  This attempts to update the DNS with
+# new A records for the NETBIOS name that Samba passes us. We do this
+# the simple way, by deleting all DNS records for the name and then
+# readding all the expected 'A' records.
+#
+# Written by Stephen Rothwell <sfr@linuxcare.com>
+#
+
+#
+# Configurable things
+#
+# The domain in which to create names
+#   YOU MUST CHANGE THIS
+# N.B. include the trailing dot
+#
+# It is a good idea to use a subdomain of your primary domain to ensure
+# that rogue machines can't take over (or delete) important names on
+# your network.
+DOMAIN=wins.example.com.
+
+#
+# The DNS TTL to give the records (in seconds)
+#
+TTL=3600
+#
+# NETBIOS name types that we want to create DNS records for:
+#      20 is server
+#      00 is workstation
+#      03 is user
+#
+USEFUL_TYPES="20 00 03"
+#
+# The name of a cache file to use to avoid continual updates
+# of the same name and IP addresses.  If you comment this out
+# then the cache is not kept at all.
+#
+#CACHE_FILE=/usr/local/samba/var/wins_update.cache
+
+if [ $# -lt 4 ]; then
+       echo "Usage: $0 op name type ttl [ip_addr ...]" 1>&2
+       echo "       op is one of add, refresh, delete" 1>&2
+       echo "       name is the NETBIOS name" 1>&2
+       echo "       type is the NETBIOS name type" 1>&2
+       echo "       ttl is the NETBIOS time to live" 1>&2
+       echo "       ip_addr's are the remaining IP addresses for this name" 1>&2
+       exit 1
+fi
+
+NSUPDATE=`which nsupdate`
+[ -x "$NSUPDATE" ] || NSUPDATE=/usr/bin/nsupdate
+[ -x "$NSUPDATE" ] || NSUPDATE=/sbin/nsupdate
+[ -x "$NSUPDATE" ] || NSUPDATE=/usr/sbin/nsupdate
+[ -x "$NSUPDATE" ] || {
+       echo "Cannot find nsupdate." 1>&2
+       exit 1
+}
+
+OP=$1
+NAME=$2
+TYPE=$3
+WINS_TTL=$4
+shift 4
+IP_ADDRS="$@"
+
+do_update=0
+for i in $USEFUL_TYPES
+do
+       [ "$TYPE" = "$i" ] && do_update=1
+done
+[ $do_update = 1 ] || exit 0
+
+if [ -n "$CACHE_FILE" ]; then
+       if [ -r "$CACHE_FILE" ]; then
+               fgrep -q -x -i "$NAME $IP_ADDRS" "$CACHE_FILE" &&
+                       exit 0
+               grep -v -i "^$NAME " "$CACHE_FILE" >"$CACHE_FILE".$$
+       fi
+       echo "$NAME $IP_ADDRS" >>"$CACHE_FILE".$$
+       mv "$CACHE_FILE" "$CACHE_FILE".old 2>/dev/null
+       mv "$CACHE_FILE".$$ "$CACHE_FILE"
+fi
+
+{
+       echo update delete $NAME.$DOMAIN
+       for i in $IP_ADDRS
+       do
+               echo update add $NAME.$DOMAIN $TTL A $i
+       done
+       echo
+} 2>/dev/null | $NSUPDATE >/dev/null 2>&1 &
+
+exit 0