diff options
Diffstat (limited to 'examples/LDAP')
43 files changed, 8052 insertions, 0 deletions
diff --git a/examples/LDAP/README b/examples/LDAP/README new file mode 100644 index 00000000000..2f4b4f2a056 --- /dev/null +++ b/examples/LDAP/README @@ -0,0 +1,74 @@ +!== +!== README File for various LDAP examples +!== +!== written by Gerald Carter <jerry@samba.org> +!== + +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 +the Samba team and generated from its own Enterprise number +of 7165 (as issued by IANA). + +Copy the samba.schema file into your /etc/openldap/schema directory, +and add an include for it in the /etc/openldap/slapd.conf file. +Note that samba.schema relies upon the uid and uidNumber attributes +from the RFC2307 schema (i.e. nis.schema) + +If you choose to import /etc/passwd, nis, or nisplus tables +into ldap, you can use migration tools provided by PADL Software +which are located at + + http://www.padl.com/tools.html + +It is not a requirement that a user's /etc/passwd account +is stored in LDAP for the samba.schema file to work (although +the whole point of storing smbpasswd in LDAP is to have a +single location for user accounts, right?) + +The padl tools will leave you with LDIF files which you can import +into OpenLDAP. Before you can import them, you need to include +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 +------------------ + +The schema file has not been updated for the sambaSamAccount +objectclass. + + +Novell eDirectory +----------------- + +The schema file has not been updated for the sambaSamAccount +objectclass. + + +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 +----------- +For more information on these scripts, see + + http://www.mami.net/univr/tng-ldap/howto/ + + +The ldapsync.pl script requires a small command (smbencrypt) +for generating LanMan and NT password hashes which +can be found at ftp://samba.org/pub/samba/contributed/ + +!== +!== end of README +!== diff --git a/examples/LDAP/convertSambaAccount b/examples/LDAP/convertSambaAccount new file mode 100755 index 00000000000..4357dbc8f8d --- /dev/null +++ b/examples/LDAP/convertSambaAccount @@ -0,0 +1,233 @@ +#!/usr/bin/perl -w +## +## Convert an LDIF file containing sambaAccount entries +## to the new sambaSamAccount objectclass +## +## Copyright Gerald (Jerry) Carter 2003 +## +## Usage: convertSambaAccount --sid=<Domain SID> \ +## --input=<input ldif> --output=<output ldif> \ +## --changetype=[modify|add] +## +## You can generate an input ldif file using: +## $ ldapsearch -LL -x -h ldapsrv -D cn=root,dc=company,dc=com \ +## -b dc=copmany,dc=com > /tmp/samba3.alpha23.ldif +## +## Note the "-LL" so no additional comments are generated +## + + +use strict; +use Net::LDAP::LDIF; +use Getopt::Long; + + +############################################################################## +## 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 ); + + +############################################################################## +## 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', + pwdLastSet => 'sambaPwdLastSet', + pwdMustChange => 'sambaPwdMustChange', + pwdCanChange => 'sambaPwdCanChange', + homeDrive => 'sambaHomeDrive', + smbHome => 'sambaHomePath', + scriptPath => 'sambaLogonScript', + profilePath => 'sambaProfilePath', + kickoffTime => 'sambaKickoffTime', + logonTime => 'sambaLogonTime', + logoffTime => 'sambaLogoffTime', + userWorkstations => 'sambaUserWorkstations', + domain => 'sambaDomainName', + acctFlags => 'sambaAcctFlags', +); + +%group_attr_map = ( + ntSid => 'sambaSID', + ntGroupType => 'sambaGroupType', +); + +## +## 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'}; + +$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 ); + $entry = $ldif->read_entry(); + + ## skip entry if we find an error + if ( $ldif->error() ) { + print "Error msg: ",$ldif->error(),"\n"; + print "Error lines:\n",$ldif->error_lines(),"\n"; + next; + } + + ## + ## check to see if we have anything to do on this + ## entry. If not just write it out + ## + @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; + } elsif ( "$obj" eq "sambaGroupMapping" ) { + $is_samba_group = 1; + } + } + + if ( defined ( $is_samba_account ) ) { + ## + ## 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' ); + + $entry->add( 'sambaSID' => $domsid."-".$entry->get_value( "rid" ) ); + $entry->delete( 'rid' ); + + if ( defined($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' ); + } + + + 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 ); + } + } + } 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 ); + } + } + } + + ## 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" + } + } + } +} + + diff --git a/examples/LDAP/ldapsync.pl b/examples/LDAP/ldapsync.pl new file mode 100644 index 00000000000..c112bcc34cb --- /dev/null +++ b/examples/LDAP/ldapsync.pl @@ -0,0 +1,122 @@ +#!/usr/bin/perl -w + +# LDAP to unix password sync script for samba-tng +# originally by Jody Haynes <Jody.Haynes@isunnetworks.com> +# 12/12/2000 milos@interactivesi.com +# modified for use with MD5 passwords +# 12/16/2000 mami@arena.sci.univr.it +# 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"; +$scope = "sub"; +$passwd = "mysecret"; + +foreach $arg (@ARGV) { + if ($< != 0) { + die "Only root can specify parameters\n"; + } else { + if ( ($arg eq '-?') || ($arg eq '--help') ) { + print "Usage: $0 [-o] [username]\n"; + print " -o, --without-old-password do not ask for old password (root only)\n"; + print " -?, --help show this help message\n"; + exit (-1); + } elsif ( ($arg eq '-o') || ($arg eq '--without-old-password') ) { + $oldpass = 1; + } elsif (substr($arg,0) ne '-') { + $user = $arg; + if (!defined(getpwnam($user))) { + die "$0: Unknown user name '$user'\n"; ; + } + } + } +} + +if (!defined($user)) { + $user=$ENV{"USER"}; +} + +if (!defined($oldpass)) { + system "stty -echo"; + print "Old password for user $user: "; + chomp($oldpass=<STDIN>); + print "\n"; + system "stty echo"; + + $ntpwd = `/usr/local/sbin/smbencrypt '$oldpass'`; + $lmpassword = substr($ntpwd, 0, index($ntpwd, ':')); chomp $lmpassword; + $ntpassword = substr($ntpwd, index($ntpwd, ':')+1); chomp $ntpassword; + + # Find dn for user $user (maybe check unix password too?) + $dn=`ldapsearch -b '$basedn' -s '$scope' '(&(uid=$user)(lmpassword=$lmpassword)(ntpassword=$ntpassword))'|head -1`; + chomp $dn; + + if ($dn eq '') { + print "Wrong password for user $user!\n"; + exit (-1); + } +} else { + # Find dn for user $user + $dn=`ldapsearch -b '$basedn' -s '$scope' '(uid=$user)'|head -1`; + chomp $dn; +} + +system "stty -echo"; +print "New password for user $user: "; +chomp($pass=<STDIN>); +print "\n"; +system "stty echo"; + +system "stty -echo"; +print "Retype new password for user $user: "; +chomp($pass2=<STDIN>); +print "\n"; +system "stty echo"; + +if ($pass ne $pass2) { + die "Wrong password!\n"; +} else { +# MD5 password +$random = join '', ('.', '/', 0..9, 'A'..'Z', 'a'..'z')[rand 64, rand 64, rand 64, rand 64, rand 64, rand 64, rand 64, rand 64]; +$bsalt = "\$1\$"; $esalt = "\$"; +$modsalt = $bsalt.$random.$esalt; +$password = crypt($pass, $modsalt); + +# LanManager and NT clear text passwords +$ntpwd = `/usr/local/sbin/smbencrypt '$pass'`; +chomp($lmpassword = substr($ntpwd, 0, index($ntpwd, ':'))); +chomp($ntpassword = substr($ntpwd, index($ntpwd, ':')+1)); + +$FILE="|/usr/bin/ldapmodify -D '$binddn' -w $passwd"; + +open FILE or die; + +print FILE <<EOF; +dn: $dn +changetype: modify +replace: userPassword +userPassword: {crypt}$password +- +changetype: modify +replace: lmpassword +lmpassword: $lmpassword +- +changetype: modify +replace: ntpassword +ntpassword: $ntpassword +- + +EOF +close FILE; + +} + +exit 0; + diff --git a/examples/LDAP/samba-nds.schema b/examples/LDAP/samba-nds.schema new file mode 100644 index 00000000000..8369c8404ec --- /dev/null +++ b/examples/LDAP/samba-nds.schema @@ -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 ) ) diff --git a/examples/LDAP/samba-schema-netscapeds4.x b/examples/LDAP/samba-schema-netscapeds4.x new file mode 100644 index 00000000000..9f409664187 --- /dev/null +++ b/examples/LDAP/samba-schema-netscapeds4.x @@ -0,0 +1,112 @@ +# +# 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 + +objectclass sambaUnixIdPool + oid + 1.3.6.1.4.1.7165.1.2.2.7 + superior + top + requires + uidNumber, + gidNumber + +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 diff --git a/examples/LDAP/samba-schema-netscapeds5.x b/examples/LDAP/samba-schema-netscapeds5.x new file mode 100644 index 00000000000..e750039acbf --- /dev/null +++ b/examples/LDAP/samba-schema-netscapeds5.x @@ -0,0 +1,55 @@ +## +## Darren Chew <darren.chew at vicscouts dot asn dot au> +## Andre Fiebach <andre dot fiebach at stud dot uni-rostock dot de> +## +## Samba 3.0 schema file for Netscape DS 5.x +## +## INSTALL-DIRECTORY/slapd-your_name/config/schema/samba-schema-netscapeds5.ldif +#################################################################### +# Sun One DS do not load the schema without this lines +# André Fiebach <af123@uni-rostock.de> +dn: cn=schema
+objectClass: top
+objectClass: ldapSubentry
+objectClass: subschema
+cn: schema
+aci: (target="ldap:///cn=schema")(targetattr !="aci")(version 3.0;acl "anonymo
+ us, no acis"; allow (read, search, compare) userdn = "ldap:///anyone";)
+aci: (targetattr = "*")(version 3.0; acl "Configuration Administrator"; allow
+ (all) userdn = "ldap:///uid=admin,ou=Administrators, ou=TopologyManagement,
+ o=NetscapeRoot";)
+aci: (targetattr = "*")(version 3.0; acl "Local Directory Administrators Group
+ "; allow (all) groupdn = "ldap:///cn=Directory Administrators, dc=samba,dc=org";)
+aci: (targetattr = "*")(version 3.0; acl "SIE Group"; allow (all)groupdn = "ld
+ ap:///cn=slapd-sambaldap, cn=iPlanet Directory Server, cn=Server Group, cn=iPlanetDirectory.samba.org, ou=samba.org, o=NetscapeRoot";)
+modifiersName: cn=directory manager
+modifyTimestamp: 20020322124844Z +####################################################################
+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' ) diff --git a/examples/LDAP/samba-schema.IBMSecureWay b/examples/LDAP/samba-schema.IBMSecureWay new file mode 100644 index 00000000000..1fca4a749a6 --- /dev/null +++ b/examples/LDAP/samba-schema.IBMSecureWay @@ -0,0 +1,43 @@ +## +## Submitted by Dirk Kastens <Dirk.Kastens@Uni-Osnabrueck.de> +## +## I translated the samba.schema to be used with IBM +## SecureWay directoy server 3.2.2. You have to load +## it in your slapd32.conf with: +## +## dn: cn=IBM SecureWay, cn=Schemas, cn=Configuration +## cn: IBM SecureWay +## ibm-slapdIncludeSchema: /etc/lapschema/samba.schema +## +objectClasses { +( 1.3.1.5.1.4.1.7165.2.2.2 NAME 'sambaAccount' DESC 'Samba Account' SUP top MUST uid $ rid MAY ( acctFlags $ cn $ description $ displayName $ homeDrive $ kickoffTime $ lmPassword $ logoffTime $ logonTime $ ntPassword $ primaryGroupID $ profilePath $ pwdCanChange $ pwdLastSet $ pwdMustChange $ scriptPath $ smbHome $ userWorkstations ) ) +} + +attributeTypes { +( 1.3.6.1.4.1.7165.2.1.1 NAME 'lmPassword' DESC 'LanManager Passwd' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26{32} SINGLE-VALUE ) +( 1.3.6.1.4.1.7165.2.1.10 NAME 'homeDrive' DESC 'NT homeDrive' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26{4} SINGLE-VALUE ) +( 1.3.6.1.4.1.7165.2.1.11 NAME 'scriptPath' DESC 'NT scriptPath' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26{255} SINGLE-VALUE ) +( 1.3.6.1.4.1.7165.2.1.12 NAME 'profilePath' DESC 'NT profilePath' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26{255} SINGLE-VALUE ) +( 1.3.6.1.4.1.7165.2.1.13 NAME 'userWorkstations' DESC 'userWorkstations' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26{255} SINGLE-VALUE ) +( 1.3.6.1.4.1.7165.2.1.14 NAME 'rid' DESC 'NT rid' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26{255} SINGLE-VALUE ) +( 1.3.6.1.4.1.7165.2.1.15 NAME 'primaryGroupID' DESC 'NT Group RID' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26{255} SINGLE-VALUE ) +( 1.3.6.1.4.1.7165.2.1.17 NAME 'smbHome' DESC 'smbHome' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26{128} ) +( 1.3.6.1.4.1.7165.2.1.2 NAME 'ntPassword' DESC 'NT Passwd' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26{32} SINGLE-VALUE ) +( 1.3.6.1.4.1.7165.2.1.3 NAME 'pwdLastSet' DESC 'NT pwdLastSet' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26{32} SINGLE-VALUE ) +( 1.3.6.1.4.1.7165.2.1.4 NAME 'acctFlags' DESC 'Account Flags' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26{16} SINGLE-VALUE ) +( 1.3.6.1.4.1.7165.2.1.5 NAME 'logonTime' DESC 'NT logonTime' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26{32} SINGLE-VALUE ) +( 1.3.6.1.4.1.7165.2.1.6 NAME 'logoffTime' DESC 'NT logoffTime' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26{32} SINGLE-VALUE ) +( 1.3.6.1.4.1.7165.2.1.7 NAME 'kickoffTime' DESC 'NT kickoffTime' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26{32} SINGLE-VALUE ) +( 1.3.6.1.4.1.7165.2.1.8 NAME 'pwdCanChange' DESC 'NT pwdCanChange' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26{32} SINGLE-VALUE ) +( 1.3.6.1.4.1.7165.2.1.9 NAME 'pwdMustChange' DESC 'NT pwdMustChange' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26{32} SINGLE-VALUE ) +} + +IBMattributeTypes { +} + +ldapSyntaxes { +} + +matchingRules { +} + diff --git a/examples/LDAP/samba.schema b/examples/LDAP/samba.schema new file mode 100644 index 00000000000..7d7fe346b2b --- /dev/null +++ b/examples/LDAP/samba.schema @@ -0,0 +1,424 @@ +## +## 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) +## - 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 +## + +######################################################################## +## HISTORICAL ## +######################################################################## + +## +## Password hashes +## +#attributetype ( 1.3.6.1.4.1.7165.2.1.1 NAME 'lmPassword' +# DESC 'LanManager Passwd' +# EQUALITY caseIgnoreIA5Match +# SYNTAX 1.3.6.1.4.1.1466.115.121.1.26{32} SINGLE-VALUE ) + +#attributetype ( 1.3.6.1.4.1.7165.2.1.2 NAME 'ntPassword' +# DESC 'NT Passwd' +# EQUALITY caseIgnoreIA5Match +# SYNTAX 1.3.6.1.4.1.1466.115.121.1.26{32} SINGLE-VALUE ) + +## +## Account flags in string format ([UWDX ]) +## +#attributetype ( 1.3.6.1.4.1.7165.2.1.4 NAME 'acctFlags' +# DESC 'Account Flags' +# EQUALITY caseIgnoreIA5Match +# SYNTAX 1.3.6.1.4.1.1466.115.121.1.26{16} SINGLE-VALUE ) + +## +## Password timestamps & policies +## +#attributetype ( 1.3.6.1.4.1.7165.2.1.3 NAME 'pwdLastSet' +# DESC 'NT pwdLastSet' +# EQUALITY integerMatch +# SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 SINGLE-VALUE ) + +#attributetype ( 1.3.6.1.4.1.7165.2.1.5 NAME 'logonTime' +# DESC 'NT logonTime' +# EQUALITY integerMatch +# SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 SINGLE-VALUE ) + +#attributetype ( 1.3.6.1.4.1.7165.2.1.6 NAME 'logoffTime' +# DESC 'NT logoffTime' +# EQUALITY integerMatch +# SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 SINGLE-VALUE ) + +#attributetype ( 1.3.6.1.4.1.7165.2.1.7 NAME 'kickoffTime' +# DESC 'NT kickoffTime' +# EQUALITY integerMatch +# SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 SINGLE-VALUE ) + +#attributetype ( 1.3.6.1.4.1.7165.2.1.8 NAME 'pwdCanChange' +# DESC 'NT pwdCanChange' +# EQUALITY integerMatch +# SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 SINGLE-VALUE ) + +#attributetype ( 1.3.6.1.4.1.7165.2.1.9 NAME 'pwdMustChange' +# DESC 'NT pwdMustChange' +# EQUALITY integerMatch +# SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 SINGLE-VALUE ) + +## +## string settings +## +#attributetype ( 1.3.6.1.4.1.7165.2.1.10 NAME 'homeDrive' +# DESC 'NT homeDrive' +# EQUALITY caseIgnoreIA5Match +# SYNTAX 1.3.6.1.4.1.1466.115.121.1.26{4} SINGLE-VALUE ) + +#attributetype ( 1.3.6.1.4.1.7165.2.1.11 NAME 'scriptPath' +# DESC 'NT scriptPath' +# EQUALITY caseIgnoreIA5Match +# SYNTAX 1.3.6.1.4.1.1466.115.121.1.26{255} SINGLE-VALUE ) + +#attributetype ( 1.3.6.1.4.1.7165.2.1.12 NAME 'profilePath' +# DESC 'NT profilePath' +# EQUALITY caseIgnoreIA5Match +# SYNTAX 1.3.6.1.4.1.1466.115.121.1.26{255} SINGLE-VALUE ) + +#attributetype ( 1.3.6.1.4.1.7165.2.1.13 NAME 'userWorkstations' +# DESC 'userWorkstations' +# EQUALITY caseIgnoreIA5Match +# SYNTAX 1.3.6.1.4.1.1466.115.121.1.26{255} SINGLE-VALUE ) + +#attributetype ( 1.3.6.1.4.1.7165.2.1.17 NAME 'smbHome' +# DESC 'smbHome' +# EQUALITY caseIgnoreIA5Match +# SYNTAX 1.3.6.1.4.1.1466.115.121.1.26{128} ) + +#attributetype ( 1.3.6.1.4.1.7165.2.1.18 NAME 'domain' +# DESC 'Windows NT domain to which the user belongs' +# EQUALITY caseIgnoreIA5Match +# SYNTAX 1.3.6.1.4.1.1466.115.121.1.26{128} ) + +## +## user and group RID +## +#attributetype ( 1.3.6.1.4.1.7165.2.1.14 NAME 'rid' +# DESC 'NT rid' +# EQUALITY integerMatch +# SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 SINGLE-VALUE ) + +#attributetype ( 1.3.6.1.4.1.7165.2.1.15 NAME 'primaryGroupID' +# DESC 'NT Group RID' +# EQUALITY integerMatch +# SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 SINGLE-VALUE ) + +## +## The smbPasswordEntry objectclass has been depreciated in favor of the +## sambaAccount objectclass +## +#objectclass ( 1.3.6.1.4.1.7165.2.2.1 NAME 'smbPasswordEntry' SUP top AUXILIARY +# DESC 'Samba smbpasswd entry' +# MUST ( uid $ uidNumber ) +# MAY ( lmPassword $ ntPassword $ pwdLastSet $ acctFlags )) + +#objectclass ( 1.3.6.1.4.1.7165.2.2.2 NAME 'sambaAccount' SUP top STRUCTURAL +# DESC 'Samba Account' +# MUST ( uid $ rid ) +# MAY ( cn $ lmPassword $ ntPassword $ pwdLastSet $ logonTime $ +# logoffTime $ kickoffTime $ pwdCanChange $ pwdMustChange $ acctFlags $ +# displayName $ smbHome $ homeDrive $ scriptPath $ profilePath $ +# description $ userWorkstations $ primaryGroupID $ domain )) + +#objectclass ( 1.3.6.1.4.1.7165.2.2.3 NAME 'sambaAccount' SUP top AUXILIARY +# DESC 'Samba Auxiliary Account' +# MUST ( uid $ rid ) +# MAY ( cn $ lmPassword $ ntPassword $ pwdLastSet $ logonTime $ +# logoffTime $ kickoffTime $ pwdCanChange $ pwdMustChange $ acctFlags $ +# displayName $ smbHome $ homeDrive $ scriptPath $ profilePath $ +# description $ userWorkstations $ primaryGroupID $ domain )) + +######################################################################## +## END OF HISTORICAL ## +######################################################################## + +####################################################################### +## Attributes used by Samba 3.0 schema ## +####################################################################### + +## +## Password hashes +## +attributetype ( 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 ) + +attributetype ( 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 ) + +## +## Account flags in string format ([UWDX ]) +## +attributetype ( 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 ) + +## +## Password timestamps & policies +## +attributetype ( 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 ) + +attributetype ( 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 ) + +attributetype ( 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 ) + +attributetype ( 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 ) + +attributetype ( 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 ) + +attributetype ( 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 ) + +attributetype ( 1.3.6.1.4.1.7165.2.1.48 NAME 'sambaBadPasswordCount' + DESC 'Bad password attempt count' + EQUALITY integerMatch + SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 SINGLE-VALUE ) + +attributetype ( 1.3.6.1.4.1.7165.2.1.49 NAME 'sambaBadPasswordTime' + DESC 'Time of the last bad password attempt' + EQUALITY integerMatch + SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 SINGLE-VALUE ) + + +## +## string settings +## +attributetype ( 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 ) + +attributetype ( 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 ) + +attributetype ( 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 ) + +attributetype ( 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 ) + +attributetype ( 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} ) + +attributetype ( 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} ) + +attributetype ( 1.3.6.1.4.1.7165.2.1.47 NAME 'sambaMungedDial' + DESC '' + EQUALITY caseExactMatch + SYNTAX 1.3.6.1.4.1.1466.115.121.1.15{1050} ) + +## +## SID, of any type +## + +attributetype ( 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 ) + + +## +## Primary group SID, compatible with ntSid +## + +attributetype ( 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 ) + +## +## group mapping attributes +## +attributetype ( 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 ) + +## +## Store info on the domain +## + +attributetype ( 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 ) + +attributetype ( 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 ) + +attributetype ( 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 ) + +attributetype ( 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 ) + + + +attributetype ( 1.3.6.1.4.1.7165.2.1.41 NAME 'sambaShareName' + DESC 'Share Name' + EQUALITY caseIgnoreMatch + SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE ) + +attributetype ( 1.3.6.1.4.1.7165.2.1.42 NAME 'sambaOptionName' + DESC 'Option Name' + EQUALITY caseIgnoreMatch + SUBSTR caseIgnoreSubstringsMatch + SYNTAX 1.3.6.1.4.1.1466.115.121.1.15{256} ) + +attributetype ( 1.3.6.1.4.1.7165.2.1.43 NAME 'sambaBoolOption' + DESC 'A boolean option' + EQUALITY booleanMatch + SYNTAX 1.3.6.1.4.1.1466.115.121.1.7 SINGLE-VALUE ) + +attributetype ( 1.3.6.1.4.1.7165.2.1.44 NAME 'sambaIntegerOption' + DESC 'An integer option' + EQUALITY integerMatch + SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 SINGLE-VALUE ) + +attributetype ( 1.3.6.1.4.1.7165.2.1.45 NAME 'sambaStringOption' + DESC 'A string option' + EQUALITY caseExactIA5Match + SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE ) + +attributetype ( 1.3.6.1.4.1.7165.2.1.46 NAME 'sambaStringListOption' + DESC 'A string list option' + EQUALITY caseIgnoreMatch + SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 ) + + +attributetype ( 1.3.6.1.4.1.7165.2.1.50 NAME ( 'sambaPrivName' ) SUP name ) + +attributetype ( 1.3.6.1.4.1.7165.2.1.51 NAME 'sambaSIDList' + DESC 'Security ID List' + EQUALITY caseIgnoreIA5Match + SYNTAX 1.3.6.1.4.1.1466.115.121.1.26{64} ) + +####################################################################### +## objectClasses used by Samba 3.0 schema ## +####################################################################### + +## The X.500 data model (and therefore LDAPv3) says that each entry can +## only have one structural objectclass. OpenLDAP 2.0 does not enforce +## this currently but will in v2.1 + +## +## added new objectclass (and OID) for 3.0 to help us deal with backwards +## compatibility with 2.2 installations (e.g. ldapsam_compat) --jerry +## +objectclass ( 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 $ sambaMungedDial $ + sambaBadPasswordCount $ sambaBadPasswordTime)) + +## +## Group mapping info +## +objectclass ( 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 $ sambaSIDList )) + +## +## Whole-of-domain info +## +objectclass ( 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 ) ) + +## used for idmap_ldap module +objectclass ( 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 ) ) + + +objectclass ( 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 ) ) + +objectclass ( 1.3.6.1.4.1.7165.1.2.2.9 NAME 'sambaSidEntry' SUP top STRUCTURAL + DESC 'Structural Class for a SID' + MUST ( sambaSID ) ) + + + + +objectclass ( 1.3.6.1.4.1.7165.1.2.2.10 NAME 'sambaConfig' SUP top AUXILIARY + DESC 'Samba Configuration Section' + MAY ( description ) ) + +objectclass ( 1.3.6.1.4.1.7165.1.2.2.11 NAME 'sambaShare' SUP top STRUCTURAL + DESC 'Samba Share Section' + MUST ( sambaShareName ) + MAY ( description ) ) + +objectclass ( 1.3.6.1.4.1.7165.1.2.2.12 NAME 'sambaConfigOption' SUP top STRUCTURAL + DESC 'Samba Configuration Option' + MUST ( sambaOptionName ) + MAY ( sambaBoolOption $ sambaIntegerOption $ sambaStringOption $ sambaStringListoption $ description ) ) + + +objectclass ( 1.3.6.1.4.1.7165.1.2.2.13 NAME 'sambaPrivilege' SUP top STRUCTURAL + DESC 'Samba Privilege' + MUST ( sambaPrivName ) + MAY ( sambaSIDList $ description ) ) + diff --git a/examples/LDAP/samba.schema.at.IBM-DS b/examples/LDAP/samba.schema.at.IBM-DS new file mode 100644 index 00000000000..bc39d520fb6 --- /dev/null +++ b/examples/LDAP/samba.schema.at.IBM-DS @@ -0,0 +1,59 @@ +## Samba 3.0 schema for IBM Directory Server 5.1 - object classes only + +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 ) + +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 ) + +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 ) + +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 ) + +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 ) + +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 ) + +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 ) + +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 ) + +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 ) + +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 ) + +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 ) + +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 ) + +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 ) + +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 ) + +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 ) + +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 ) + +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 ) + +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 ) + +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 ) + +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 ) + +attributetypes=( 1.3.6.1.4.1.7165.2.1.41 NAME 'sambaShareName' DESC 'Share Name' EQUALITY caseIgnoreMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE ) + +attributetypes=( 1.3.6.1.4.1.7165.2.1.42 NAME 'sambaOptionName' DESC 'Option Name' EQUALITY caseIgnoreMatch SUBSTR caseIgnoreSubstringsMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.15{256} ) + +attributetypes=( 1.3.6.1.4.1.7165.2.1.43 NAME 'sambaBoolOption' DESC 'A boolean option' EQUALITY booleanMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.7 SINGLE-VALUE ) + +attributetypes=( 1.3.6.1.4.1.7165.2.1.44 NAME 'sambaIntegerOption' DESC 'An integer option' EQUALITY integerMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 SINGLE-VALUE ) + +attributetypes=( 1.3.6.1.4.1.7165.2.1.45 NAME 'sambaStringOption' DESC 'A string option' EQUALITY caseExactIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE ) + +attributetypes=( 1.3.6.1.4.1.7165.2.1.46 NAME 'sambaStringListOption' DESC 'A string list option' EQUALITY caseIgnoreMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 ) + +attributetypes=( 1.3.6.1.4.1.7165.2.1.47 NAME 'sambaMungedDial' DESC '' EQUALITY caseExactMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.15{1050} ) diff --git a/examples/LDAP/samba.schema.oc.IBM-DS b/examples/LDAP/samba.schema.oc.IBM-DS new file mode 100644 index 00000000000..8f556520de9 --- /dev/null +++ b/examples/LDAP/samba.schema.oc.IBM-DS @@ -0,0 +1,19 @@ +## Samba 3.0 schema for IBM Directory Server 5.1 - object classes only + +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 $ sambaMungedDial )) + +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 )) + +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 ) ) + +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 ) ) + +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 ) ) + +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 ) ) + +objectclasses=( 1.3.6.1.4.1.7165.1.2.2.10 NAME 'sambaConfig' SUP top AUXILIARY DESC 'Samba Configuration Section' MAY ( description ) ) + +objectclasses=( 1.3.6.1.4.1.7165.1.2.2.11 NAME 'sambaShare' SUP top STRUCTURAL DESC 'Samba Share Section' MUST ( sambaShareName ) MAY ( description ) ) + +objectclasses=( 1.3.6.1.4.1.7165.1.2.2.12 NAME 'sambaConfigOption' SUP top STRUCTURAL DESC 'Samba Configuration Option' MUST ( sambaOptionName ) MAY ( sambaBoolOption $ sambaIntegerOption $ sambaStringOption $ sambaStringListoption $ description ) ) diff --git a/examples/LDAP/smbldap-tools/CONTRIBUTORS b/examples/LDAP/smbldap-tools/CONTRIBUTORS new file mode 100644 index 00000000000..697f93b7f49 --- /dev/null +++ b/examples/LDAP/smbldap-tools/CONTRIBUTORS @@ -0,0 +1,33 @@ +# $Source: /home/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: + . Jérôme Tournier <jerome.tournier@IDEALX.com> + . Terry Davis <terry@terryd.net> + . David Le Corfec <dlc@freesurf.fr> + . Olivier Lemaire <olivier.lemaire@IDEALX.com> + +Many thanks to contributors for bug report and patches: + . Marc Schoechlin <ms@LF.net> + load the perl-modules without setting environment-variables or making symlinks + . Alexander Bergolth <leo@strike.wu-wien.ac.at> + more Net::LDAP support + . Gert-Jan Braas <braas@wyldebeast-wunderliebe.com> + bug report for 2.2.3 samba.schema + . Jody Haynes <Jody.Haynes@isunnetworks.com> + 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 index 00000000000..32d0e6014a7 --- /dev/null +++ b/examples/LDAP/smbldap-tools/COPYING @@ -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 index 00000000000..54ba1aed66f --- /dev/null +++ b/examples/LDAP/smbldap-tools/ChangeLog @@ -0,0 +1,89 @@ +# $Source: /home/cvs/samba/examples/LDAP/smbldap-tools/ChangeLog,v $ +# $id: $ +# +## ChangeLog for SMBLDAP-TOOLS + +2003-11-18: + . new option '-a' to smbldap-usermod.pl that allow adding the sambaSamAccount + objectclass to an existing posixAccount +2003-11-07: + . patch that allow adding user to a group when the group is in a higher level depth + then ou=Groups (for example, ou=grp1,ou=Groups,...) + . check the unicity of a group when adding/removing a user to this group +2003-10-28: + . new option '-p' in smbldap-groupadd.pl to 'print' the gidNumber + of the group to STDOUT. This is needed by samba (see the man page) +2003-10-19: + . new function does_sid_exist that check if samaSID sttribute is already + defined for another use or another group +2003-10-13: + . smbldap-populate.pl now also add the group mapping +2003-10-01: + . one can now comment the two directives '$_userSmbHome' and '$_userProfile' + if you want to use the smb.conf directives instead ('logon home' and + 'logon path' respectively), or if you want to desable roaming profiles + . Patch from Alexander Bergolth <leo@strike.wu-wien.ac.at>: the sambaPrimaryGroupSID + of a user is now set to the sambaSID of his primary group +2003-09-29: + . added new option '$_defaultMaxPasswordAge' in smbldap_conf.pm to specifie + how long a password is valid + . The '-B' option was not always valid: to force a user to change his password: + . the attribut sambaPwdLastSet must be != 0 + . the attribut sambaAcctFlags must not match the 'X' flag + . logon script is set (for every one) to the default '_userScript' value if it is defined + . Patch from Alexander Bergolth <leo@strike.wu-wien.ac.at>: + gid-sid group mapping to smbldap-groupadd.pl and smbldap-groupmod.pl +2003-09-19: Patch from Marc Schoechlin <ms@LF.net> + . load the perl-modules without setting environment-variables or making symlinks +2003-09-18: Patch from Alexander Bergolth <leo@strike.wu-wien.ac.at> + . options "-u", "-g", "-s" and "-c" are now functionnal + . the existence of samba account was made on sambaAccount and + not sambaSamAccount as it should be for samba3 + . new function read_user_entry to smbldap_tools.pm that returns + a Net::LDAP:Entry object of the user + . Use this object to get the dn and user attributes instead of + producing an ldif and searching for attributes within that ldif +2003-09-15: + . change machine account creation to not add the sambaSamAccount objectclass. + It is now added directly by samba when joigning the domain + . new option in smbldap-usermod.pl: '-e' to set an expire date + . Start_tls support activated when ldapSSL is set to 1 + . Net::LDAP support more scripts + . bugs correction +2003-09-02: + . sambaPwdLastSet is updated when smbldap-passwd.pl is used + . add a function is_group_member to test the existence of a + user in a particular group + . add a function is_unix_user to test if a particular user exist + . Net::LDAP support more scripts +2003-08-15: + . Samba3.0 support +2003-08-01: + . Final version for samba 2.2.8a (cvs tag SAMBA-2-2-8a-FINAL) + . OpenLDAP 2.1 support (only one structural objectclass allowed) +2002-07-24: top and account objectclasses replaced with inetorgperson +2002-06-03: notes to webmin.idealx.org (idxldapaccounts) +2002-06-01: release 0.7. tested with 2.2.4 +2002-05-31: fixed smbldap-populate compliance to smbldap_conf + cleaned up smbldap_conf to be more readable + some more documentation + bugfixes on smbldap-passwd and smbldap-populate +2002-05-16: modified default mode on homes: now 700 +2002-05-13: fixed spec (relocation and reqs) +2002-03-02: fixed 2.2.3 sambaAccount bug with smbldap-useradd.pl + (rid is now mandatory in the sambaAccount objectClass) +2002-02-14: just modified default populate for Administrator +2002-02-05: release 0.6. enable/disable user in usermod +2002-02-04: release 0.5. added smbldap-migrate-groups to migrate NT groups + from a net group dump. added samba parameters to smbldap-useradd + and smbldap-usermod. +2002-01-12: added smbldap-migrate-accounts to migrate users/machines + accounts from a PWDUMP dump +2001-12-13: added smbldap-populate to create the initial base +2001-12-13: initial release 0.1 +2001-12-12: fixed the SPEC file for RedHat +2001-12-03: cleaned the code and use strict; +2001-11-20: initial needs (for testing purpose on Samba-2.2.2 an Samba-TNG) + + +# - The End diff --git a/examples/LDAP/smbldap-tools/FILES b/examples/LDAP/smbldap-tools/FILES new file mode 100644 index 00000000000..2d2dabd93e9 --- /dev/null +++ b/examples/LDAP/smbldap-tools/FILES @@ -0,0 +1,43 @@ +# $Source: /home/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 index 00000000000..8ea07ead44b --- /dev/null +++ b/examples/LDAP/smbldap-tools/INFRASTRUCTURE @@ -0,0 +1,93 @@ +# $Source: /home/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" " + +However, to make pdb_ldap accept bind without being uid=0, a quick and +dirty patch must be applied to 2.2.4 (see samba-2.2.4-ldapbindnotuid0.patch). +This patch is Q&D because the check is there because Samba store admin +credentials to establish the LDAP connection. The uid == 0 check was to +ensure that a normal user could not get write access to the LDAP backend. +A more logical situation should be done for 2.2.5 by checking if the user +is a member of the domain admin group (reported to Jerremy and Gerald +2002-05-28). + +Other built in groups are really cosmetic ones with Samba 2.2.x. We did not +removed them because one of these days, we whish to use Samba 3.0 where +Windows Group Support should be operational. + +Why these specific gidNumbers ? +It's about unix/windows mapping of numerical ids with Samba. Ids below 1024 +are NT special ids. In fact, 512 is the RID (Windows uid/gid) for the +"Domain Administrators" NT group. The magic number is found in Samba sources +and possibly other Samba/Windows documentations. + +The goal is to have a set of Unix users who are Domain Administrators and can +modify Samba datas (eg. LDAP content), with commandline tools or within +Windows via Samba. + +Say you want to add a NT4 ws to an NT domain (controlled by a samba/ldap +server). You give the domain administrator's login and password in the +appropriate ws settings, then the ws contacts the samba server, which checks +the credentials and use them as unix user to run the smbldap-tools (if I +remember). Giving 512 as a RID to a LDAP entry marks it as a domain admin +for Samba (thus Windows). Using nss_ldap, you also have an account with +gid 512. + + +Known BUGS and WORKAROUND used +=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= + +The 2.2.2 has at least a bug : rid/primaryGroupID are read as hex in LDAP, +but written as decimal. Fixed in CVS by reading as decimal. By default +smbldap-useradd.pl writes decimal to LDAP. Use -x to support the odd +behaviour. + +The samba-2.2.4-ldapbindnotuid0.patch is not a perfect solution however +as the check is there because Samba store admin credentials to establish the +LDAP connection. The uid == 0 check was to ensure that a normal user could +not get write access to the LDAP backend. A more logical situation should be +done for 2.2.5 by checking if the user is a member of the domain admin group +(reported to Jerremy and Gerald 2002-05-28). + +# - The End diff --git a/examples/LDAP/smbldap-tools/INSTALL b/examples/LDAP/smbldap-tools/INSTALL new file mode 100644 index 00000000000..38221b12433 --- /dev/null +++ b/examples/LDAP/smbldap-tools/INSTALL @@ -0,0 +1,28 @@ +# $Source: /home/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 index 00000000000..783a3571a99 --- /dev/null +++ b/examples/LDAP/smbldap-tools/Makefile @@ -0,0 +1,35 @@ +PACKAGE=smbldap-tools +RELEASE=0.8.2-1 +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/README b/examples/LDAP/smbldap-tools/README new file mode 100644 index 00000000000..c6133e19692 --- /dev/null +++ b/examples/LDAP/smbldap-tools/README @@ -0,0 +1,87 @@ +# $Source: /home/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 index 00000000000..8fdc2a55994 --- /dev/null +++ b/examples/LDAP/smbldap-tools/TODO @@ -0,0 +1,28 @@ +# $Source: /home/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 index 00000000000..7a4fc0c02b9 --- /dev/null +++ b/examples/LDAP/smbldap-tools/cgi/README @@ -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 index 00000000000..4a5ecb8f3a9 --- /dev/null +++ b/examples/LDAP/smbldap-tools/cgi/ldappass.cgi @@ -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 index 00000000000..23c9d471b0a --- /dev/null +++ b/examples/LDAP/smbldap-tools/mkntpwd/Makefile @@ -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 index 00000000000..5b2e7a9100b --- /dev/null +++ b/examples/LDAP/smbldap-tools/mkntpwd/getopt.c @@ -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. */ + +/* 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; + +#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__ */ + +/* 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; +} + +/* 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__. */ + +#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 index 00000000000..f3696d955dc --- /dev/null +++ b/examples/LDAP/smbldap-tools/mkntpwd/getopt.h @@ -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 index 00000000000..1c9c2e6ecd5 --- /dev/null +++ b/examples/LDAP/smbldap-tools/mkntpwd/md4.c @@ -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 index 00000000000..0c7d61e1341 --- /dev/null +++ b/examples/LDAP/smbldap-tools/mkntpwd/mkntpwd.c @@ -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 index 00000000000..9a020b8d286 --- /dev/null +++ b/examples/LDAP/smbldap-tools/mkntpwd/mkntpwd.h @@ -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 index 00000000000..e4f8280f9bc --- /dev/null +++ b/examples/LDAP/smbldap-tools/mkntpwd/smbdes.c @@ -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 index 00000000000..e242d6e223f --- /dev/null +++ b/examples/LDAP/smbldap-tools/smbldap-groupadd.pl @@ -0,0 +1,158 @@ +#!/usr/bin/perl -w + +# 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 FindBin; +use FindBin qw($RealBin); +use lib "$RealBin/"; +use smbldap_tools; +use smbldap_conf; +use Getopt::Std; +my %Options; + +my $ok = getopts('ag:or:s:t:p?', \%Options); +if ( (!$ok) || (@ARGV < 1) || ($Options{'?'}) ) { + print "Usage: $0 [-agorst?] groupname\n"; + print " -a add automatic group mapping entry\n"; + print " -g gid\n"; + print " -o gid is not unique\n"; + print " -r group-rid\n"; + print " -s group-sid\n"; + print " -t group-type\n"; + print " -p print the gidNumber to stdout\n"; + print " -? show this help message\n"; + exit (1); +} + +my $_groupName = $ARGV[0]; + +if (defined(get_group_dn($_groupName))) { + warn "$0: group $_groupName exists\n"; + exit (6); +} + +my $_groupGidNumber = $Options{'g'}; +if (! defined ($_groupGidNumber = group_add($_groupName, $_groupGidNumber, $Options{'o'}))) { + warn "$0: error adding group $_groupName\n"; + exit (6); +} + +my $group_sid; +my $tmp; +if ($tmp= $Options{'s'}) { + if ($tmp =~ /^S-(?:\d+-)+\d+$/) { + $group_sid = $tmp; + } else { + warn "$0: illegal group-rid $tmp\n"; + exit(7); + } +} elsif ($Options{'r'} || $Options{'a'}) { + my $group_rid; + if ($tmp= $Options{'r'}) { + if ($tmp =~ /^\d+$/) { + $group_rid = $tmp; + } else { + warn "$0: illegal group-rid $tmp\n"; + exit(7); + } + } else { + # algorithmic mapping + $group_rid = 2*$_groupGidNumber+1001; + } + $group_sid = $SID.'-'.$group_rid; +} + +if ($Options{'r'} || $Options{'a'} || $Options{'s'}) { + # let's test if this SID already exist + my $test_exist_sid=does_sid_exist($group_sid,$groupsdn); + if ($test_exist_sid->count == 1) { + warn "Group SID already owned by\n"; + # there should not exist more than one entry, but ... + foreach my $entry ($test_exist_sid->all_entries) { + my $dn= $entry->dn; + chomp($dn); + warn "$dn\n"; + } + exit(7); + } +} + +if ($group_sid) { + my $group_type; + my $tmp; + if ($tmp= $Options{'t'}) { + unless (defined($group_type = &group_type_by_name($tmp))) { + warn "$0: unknown group type $tmp\n"; + exit(8); + } + } else { + $group_type = group_type_by_name('domain'); + } + my $ldap_master=connect_ldap_master(); + my $modify = $ldap_master->modify ( "cn=$_groupName,$groupsdn", + add => { + 'objectClass' => 'sambaGroupMapping', + 'sambaSID' => $group_sid, + 'sambaGroupType' => $group_type + } + ); + $modify->code && warn "failed to delete entry: ", $modify->error ; + # take down session + $ldap_master->unbind +} + +if ($Options{'p'}) { + print STDOUT "$_groupGidNumber"; +} +exit(0); + +######################################## + +=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 index 00000000000..4f6839ebe59 --- /dev/null +++ b/examples/LDAP/smbldap-tools/smbldap-groupdel.pl @@ -0,0 +1,93 @@ +#!/usr/bin/perl -w + +# 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 FindBin; +use FindBin qw($RealBin); +use lib "$RealBin/"; +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); + +group_del($dn); + +my $nscd_status = system "/etc/init.d/nscd status >/dev/null 2>&1"; + +if ($nscd_status == 0) { + system "/etc/init.d/nscd restart > /dev/null 2>&1"; +} + +#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 index 00000000000..3f9741e0152 --- /dev/null +++ b/examples/LDAP/smbldap-tools/smbldap-groupmod.pl @@ -0,0 +1,283 @@ +#!/usr/bin/perl -w + +# 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 FindBin; +use FindBin qw($RealBin); +use lib "$RealBin/"; +use smbldap_tools; +use smbldap_conf; + +##################### + +use Getopt::Std; +my %Options; + +my $ok = getopts('ag:n:m:or:s:t:x:?', \%Options); +if ( (!$ok) || (@ARGV < 1) || ($Options{'?'}) ) { + print "Usage: $0 [-a] [-g gid [-o]] [-n name] [-m members(,)] [-x members (,)] [-r rid] [-s sid] [-t type] groupname\n"; + print " -a add automatic group mapping entry\n"; + print " -g new gid\n"; + print " -o gid is not unique\n"; + print " -n new group name\n"; + print " -m add members (comma delimited)\n"; + print " -r group-rid\n"; + print " -s group-sid\n"; + print " -t group-type\n"; + print " -x delete members (comma delimted)\n"; + print " -? show this help message\n"; + exit (1); +} + +my $groupName = $ARGV[0]; +my $group_entry; + +if (! ($group_entry = read_group_entry($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); +unless (defined ($gid)) { + print "$0: group $groupName not found!\n"; + exit(6); +} + +my $tmp; +if (defined($tmp = $Options{'g'}) and $tmp =~ /\d+/) { + if (!defined($Options{'o'})) { + if (defined(getgrgid($tmp))) { + print "$0: gid $tmp exists\n"; + exit (6); + } + } + if (!($gid == $tmp)) { + my $ldap_master=connect_ldap_master(); + my $modify = $ldap_master->modify ( "cn=$groupName,$groupsdn", + changes => [ + replace => [gidNumber => $tmp] + ] + ); + $modify->code && die "failed to modify entry: ", $modify->error ; + # take down session + $ldap_master->unbind + } +} + + +if (defined($newname)) { + my $ldap_master=connect_ldap_master(); + my $modify = $ldap_master->moddn ( + "cn=$groupName,$groupsdn", + newrdn => "cn=$newname", + deleteoldrdn => "1", + newsuperior => "$groupsdn" + ); + $modify->code && die "failed to modify entry: ", $modify->error ; + # take down session + $ldap_master->unbind +} + +# Add members +if (defined($Options{'m'})) { + my $members = $Options{'m'}; + my @members = split( /,/, $members ); + my $member; + foreach $member ( @members ) { + my $group_entry=read_group_entry($groupName); + $groupsdn=$group_entry->dn; + if (is_unix_user($member)) { + if (is_group_member($groupsdn,$member)) { + print "User $member already in the group\n"; + } else { + print "adding user $member to group $groupName\n"; + my $ldap_master=connect_ldap_master(); + my $modify = $ldap_master->modify ($groupsdn, + changes => [ + add => [memberUid => $member] + ] + ); + $modify->code && warn "failed to add entry: ", $modify->error ; + # take down session + $ldap_master->unbind + } + } else { + print "User $member does not exist: create it first !\n"; + } + } +} + +# Delete members +if (defined($Options{'x'})) { + my $members = $Options{'x'}; + my @members = split( /,/, $members ); + my $member; + foreach $member ( @members ) { + my $group_entry=read_group_entry($groupName); + $groupsdn=$group_entry->dn; + if (is_group_member("$groupsdn",$member)) { + print "deleting user $member from group $groupName\n"; + my $ldap_master=connect_ldap_master(); + my $modify = $ldap_master->modify ($groupsdn, + changes => [ + delete => [memberUid => $member] + ] + ); + $modify->code && warn "failed to delete entry: ", $modify->error ; + # take down session + $ldap_master->unbind + } else { + print "User $member is not in the group $groupName!\n"; + } + } +} + +my $group_sid; +if ($tmp= $Options{'s'}) { + if ($tmp =~ /^S-(?:\d+-)+\d+$/) { + $group_sid = $tmp; + } else { + print "$0: illegal group-rid $tmp\n"; + exit(7); + } +} elsif ($Options{'r'} || $Options{'a'}) { + my $group_rid; + if ($tmp= $Options{'r'}) { + if ($tmp =~ /^\d+$/) { + $group_rid = $tmp; + } else { + print "$0: illegal group-rid $tmp\n"; + exit(7); + } + } else { + # algorithmic mapping + $group_rid = 2*$gid+1001; + } + $group_sid = $SID.'-'.$group_rid; +} + +if ($group_sid) { + my @adds; + my @mods; + push(@mods, 'sambaSID' => $group_sid); + + if ($tmp= $Options{'t'}) { + my $group_type; + if (defined($group_type = &group_type_by_name($tmp))) { + push(@mods, 'sambaGroupType' => $group_type); + } else { + print "$0: unknown group type $tmp\n"; + exit(8); + } + } else { + if (! defined($group_entry->get_value('sambaGroupType'))) { + push(@mods, 'sambaGroupType' => group_type_by_name('domain')); + } + } + + my @oc = $group_entry->get_value('objectClass'); + unless (grep($_ =~ /^sambaGroupMapping$/i, @oc)) { + push (@adds, 'objectClass' => 'sambaGroupMapping'); + } + + my $ldap_master=connect_ldap_master(); + my $modify = $ldap_master->modify ( "cn=$groupName,$groupsdn", + changes => [ + 'add' => [ @adds ], + 'replace' => [ @mods ] + ] + ); + $modify->code && warn "failed to delete entry: ", $modify->error ; + # take down session + $ldap_master->unbind +} + +$nscd_status = system "/etc/init.d/nscd status >/dev/null 2>&1"; + +if ($nscd_status == 0) { + system "/etc/init.d/nscd restart > /dev/null 2>&1"; +} + +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 index 00000000000..a9d368763ee --- /dev/null +++ b/examples/LDAP/smbldap-tools/smbldap-groupshow.pl @@ -0,0 +1,74 @@ +#!/usr/bin/perl -w + +# 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 FindBin; +use FindBin qw($RealBin); +use lib "$RealBin/"; +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 index 00000000000..54e4d7f7e3f --- /dev/null +++ b/examples/LDAP/smbldap-tools/smbldap-migrate-accounts.pl @@ -0,0 +1,230 @@ +#!/usr/bin/perl -w + +# 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 FindBin; +use FindBin qw($RealBin); +use lib "$RealBin/"; +use smbldap_tools; +use smbldap_conf; + +# smbldap-migrate.pl (-? or -h for help) +# +# Read pwdump entries on stdin, and add them to the ldap server. +# Output uncreated/unmodified entries (see parameters -C -U) +# in pwdump format to stdout. +# Errors, debug and stats are output to stderr. + +sub modify_account + { + my ($login, $basedn, $lmpwd, $ntpwd, $gecos, $homedir) = @_; + # bind to a directory with dn and password + my $ldap_master=connect_ldap_master(); + my $modify = $ldap_master->modify ("uid=$login,$basedn", + changes => [ + replace => [sambaLMPassword => "$lmpwd"], + replace => [sambaNTpassword => "$ntpwd"], + replace => [gecos => "$gecos"], + replace => [sambaHomePath => "$homedir"] + ] + ); + $modify->code && die "failed to modify entry: ", $modify->error ; + # take down the session + $ldap_master->unbind; + } + +##################### + + +my %Options; + +my $ok = getopts('awA:CUW:?h', \%Options); + +if ( (!$ok) || ($Options{'?'}) || ($Options{'h'}) ) { + print "Usage: $0 [-awAWCU?]\n"; + print " -a process only people, ignore computers\n"; + print " -w process only computers, ignore persons\n"; + print " -A <opts> option string passed verbatim to smbldap-useradd for persons\n"; + print " -W <opts> option string passed verbatim to smbldap-useradd for computers\n"; + print " -C if entry not found, don't create it and log it to stdout (default: create it)\n"; + print " -U if entry found, don't update it and log it to stdout (default: update it)\n"; + print " -?|-h 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 index 00000000000..a2b07bf817c --- /dev/null +++ b/examples/LDAP/smbldap-tools/smbldap-migrate-groups.pl @@ -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 FindBin; +use FindBin qw($RealBin); +use lib "$RealBin/"; +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 index 00000000000..afbc87a058d --- /dev/null +++ b/examples/LDAP/smbldap-tools/smbldap-passwd.pl @@ -0,0 +1,227 @@ +#!/usr/bin/perl -w + +# 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 FindBin; +use FindBin qw($RealBin); +use lib "$RealBin/"; +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); +} + +# First, connecting to the directory +my $ldap_master=connect_ldap_master(); + +# only modify smb passwords if smb user +if ($samba == 1) { + if (!$with_smbpasswd) { + # generate LanManager and NT clear text passwords + if ($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)); + # the sambaPwdLastSet must be updating + my $date=time; + my @mods; + push(@mods, 'sambaLMPassword' => $sambaLMPassword); + push(@mods, 'sambaNTPassword' => $sambaNTPassword); + push(@mods, 'sambaPwdLastSet' => $date); + if (defined $_defaultMaxPasswordAge) { + my $new_sambaPwdMustChange=$date+$_defaultMaxPasswordAge*24*60*60; + push(@mods, 'sambaPwdMustChange' => $new_sambaPwdMustChange); + push(@mods, 'sambaAcctFlags' => '[U]'); + } + # Let's change nt/lm passwords + my $modify = $ldap_master->modify ( "$dn", + 'replace' => { @mods } + ); + $modify->code && warn "failed to modify entry: ", $modify->error ; + + } else { + if ($< != 0) { + my $FILE="|$smbpasswd -s >/dev/null"; + open (FILE, $FILE) || die "$!\n"; + print FILE <<EOF; +'$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 +my $hash_password = `slappasswd -h {$hash_encrypt} -s '$pass'`; +chomp($hash_password); +my $modify = $ldap_master->modify ( "$dn", + changes => [ + replace => [userPassword => "$hash_password"] + ] + ); +$modify->code && warn "Unable to change password : ", $modify->error ; + +# take down session +$ldap_master->unbind; + +exit 0; + + +# - 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 index 00000000000..b691a848500 --- /dev/null +++ b/examples/LDAP/smbldap-tools/smbldap-populate.pl @@ -0,0 +1,370 @@ +#!/usr/bin/perl -w + +# 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 FindBin; +use FindBin qw($RealBin); +use lib "$RealBin/"; +use smbldap_tools; +use smbldap_conf; +use Getopt::Std; +use Net::LDAP::LDIF; + +use vars qw(%oc); + +# 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; +my $tmp_ldif_file="/tmp/$$.ldif"; + +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; + + print "Using builtin directory structure\n"; + 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=(.*),dc=(.*)$/); + + #my $FILE="|cat"; + my $FILE=$tmp_ldif_file; + open (FILE, ">$FILE") || die "Can't open file $FILE: $!\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: $SID-512 +sambaLMPassword: XXX +sambaNTPassword: XXX +sambaAcctFlags: [U ] +sambaSID: $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: $SID-514 +sambaLMPassword: NO PASSWORDXXXXXXXXXXXXXXXXXXXXX +sambaNTPassword: NO PASSWORDXXXXXXXXXXXXXXXXXXXXX +sambaAcctFlags: [NU ] +sambaSID: $SID-2998 +loginShell: /bin/false + +dn: cn=Domain Admins,$groupsdn +objectClass: posixGroup +objectClass: sambaGroupMapping +gidNumber: 512 +cn: Domain Admins +memberUid: $adminName +description: Netbios Domain Administrators +sambaSID: $SID-512 +sambaGroupType: 2 +displayName: Domain Admins + +dn: cn=Domain Users,$groupsdn +objectClass: posixGroup +objectClass: sambaGroupMapping +gidNumber: 513 +cn: Domain Users +description: Netbios Domain Users +sambaSID: $SID-513 +sambaGroupType: 2 +displayName: Domain Users + +dn: cn=Domain Guests,$groupsdn +objectClass: posixGroup +objectClass: sambaGroupMapping +gidNumber: 514 +cn: Domain Guests +description: Netbios Domain Guests Users +sambaSID: $SID-514 +sambaGroupType: 2 +displayName: Domain Guests + +dn: cn=Administrators,$groupsdn +objectClass: posixGroup +objectClass: sambaGroupMapping +gidNumber: 544 +cn: Administrators +description: Netbios Domain Members can fully administer the computer/sambaDomainName +sambaSID: $SID-544 +sambaGroupType: 2 +displayName: Administrators + +dn: cn=Users,$groupsdn +objectClass: posixGroup +objectClass: sambaGroupMapping +gidNumber: 545 +cn: Users +description: Netbios Domain Ordinary users +sambaSID: $SID-545 +sambaGroupType: 2 +displayName: users + +dn: cn=Guests,$groupsdn +objectClass: posixGroup +objectClass: sambaGroupMapping +gidNumber: 546 +cn: Guests +memberUid: $guestName +description: Netbios Domain Users granted guest access to the computer/sambaDomainName +sambaSID: $SID-546 +sambaGroupType: 2 +displayName: Guests + +dn: cn=Power Users,$groupsdn +objectClass: posixGroup +objectClass: sambaGroupMapping +gidNumber: 547 +cn: Power Users +description: Netbios Domain Members can share directories and printers +sambaSID: $SID-547 +sambaGroupType: 2 +displayName: Power Users + +dn: cn=Account Operators,$groupsdn +objectClass: posixGroup +objectClass: sambaGroupMapping +gidNumber: 548 +cn: Account Operators +description: Netbios Domain Users to manipulate users accounts +sambaSID: $SID-548 +sambaGroupType: 2 +displayName: Account Operators + +dn: cn=Server Operators,$groupsdn +objectClass: posixGroup +objectClass: sambaGroupMapping +gidNumber: 549 +cn: Server Operators +description: Netbios Domain Server Operators +sambaSID: $SID-549 +sambaGroupType: 2 +displayName: Server Operators + +dn: cn=Print Operators,$groupsdn +objectClass: posixGroup +objectClass: sambaGroupMapping +gidNumber: 550 +cn: Print Operators +description: Netbios Domain Print Operators +sambaSID: $SID-550 +sambaGroupType: 2 +displayName: Print Operators + +dn: cn=Backup Operators,$groupsdn +objectClass: posixGroup +objectClass: sambaGroupMapping +gidNumber: 551 +cn: Backup Operators +description: Netbios Domain Members can bypass file security to back up files +sambaSID: $SID-551 +sambaGroupType: 2 +displayName: Backup Operators + +dn: cn=Replicator,$groupsdn +objectClass: posixGroup +objectClass: sambaGroupMapping +gidNumber: 552 +cn: Replicator +description: Netbios Domain Supports file replication in a sambaDomainName +sambaSID: $SID-552 +sambaGroupType: 2 +displayName: Replicator + +dn: cn=Domain Computers,$groupsdn +objectClass: posixGroup +objectClass: sambaGroupMapping +gidNumber: 553 +cn: Domain Computers +description: Netbios Domain Computers accounts +sambaSID: $SID-553 +sambaGroupType: 2 +displayName: Domain Computers + +EOF + close FILE; +} else { + $tmp_ldif_file=$_ldifName; +} + +my $ldap_master=connect_ldap_master(); +my $ldif = Net::LDAP::LDIF->new($tmp_ldif_file, "r", onerror => 'undef' ); +while( not $ldif->eof() ) { + my $entry = $ldif->read_entry(); + if ( $ldif->error() ) { + print "Error msg: ",$ldif->error(),"\n"; + print "Error lines:\n",$ldif->error_lines(),"\n"; + } else { + my $dn = $entry->dn; + print "adding new entry: $dn\n"; + my $result=$ldap_master->add($entry); + $result->code && warn "failed to add entry: ", $result->error ; + } +} +$ldap_master->unbind; +system "rm -f $tmp_ldif_file"; +exit(0); + + +######################################## + +=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. + +=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 index 00000000000..4bd2968defe --- /dev/null +++ b/examples/LDAP/smbldap-tools/smbldap-tools.spec @@ -0,0 +1,140 @@ +# $Source: /home/cvs/samba/examples/LDAP/smbldap-tools/smbldap-tools.spec,v $ +%define version 0.8.2 +%define release 1 +%define name smbldap-tools +%define realname smbldap-tools + +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 +Source22: smb.conf +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 +install -m 644 %{SOURCE22} $RPM_BUILD_ROOT/usr/share/doc/smbldap-tools/smb.conf + +%clean +rm -rf $RPM_BUILD_ROOT + +%post +# from smbldap-tools-0.8-2, librairies are loaded with the FindBin perl package +if [ -f /usr/lib/perl5/site_perl/smbldap_tools.pm ]; +then + rm -f /usr/lib/perl5/site_perl/smbldap_tools.pm +fi +if [ -f /usr/lib/perl5/site_perl/smbldap_conf.pm ]; +then + rm -f /usr/lib/perl5/site_perl/smbldap_conf.pm +fi +chgrp 512 %{prefix}/sbin/smbldap-useradd.pl %{prefix}/sbin/smbldap_conf.pm || echo "An error occured while changing groups of smbldap-useradd.pl and smbldap_conf.pm in /usr/local/sbin. For proper operations, please ensure that they have the same posix group as the Samba domain administrator if there's a local Samba PDC." +perl -i -pe 's/_SLAVELDAP_/localhost/' %{prefix}/sbin/smbldap_conf.pm +perl -i -pe 's/_MASTERLDAP_/localhost/' %{prefix}/sbin/smbldap_conf.pm +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(noreplace) %{prefix}/sbin/smbldap_conf.pm +%{prefix}/sbin/mkntpwd +%doc /usr/share/doc/%{name}/ + + +%changelog +* Fri Nov 28 2003 Jerome Tournier <jerome.tournier@idealx.com> 0.8.2-1 +- new smb.conf file as example configuration file +- see Changelog file for updates in scripts + diff --git a/examples/LDAP/smbldap-tools/smbldap-useradd.pl b/examples/LDAP/smbldap-tools/smbldap-useradd.pl new file mode 100755 index 00000000000..918bd4a4f66 --- /dev/null +++ b/examples/LDAP/smbldap-tools/smbldap-useradd.pl @@ -0,0 +1,522 @@ +#!/usr/bin/perl -w + +# 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 FindBin; +use FindBin qw($RealBin); +use lib "$RealBin/"; +use smbldap_tools; +use smbldap_conf; + +##################### + +use Getopt::Std; +my %Options; + +my $ok = getopts('anmwPG:u:g:d:s:c:k:A:B:C:D:E:F:H:N:S:?', \%Options); + +if ( (!$ok) || (@ARGV < 1) || ($Options{'?'}) ) { + print "Usage: $0 [-awmugdsckGPABCDEFH?] username\n"; + print " -a is a Windows User (otherwise, Posix stuff only)\n"; + print " -w is a Windows Workstation (otherwise, Posix stuff only)\n"; + print " -u uid\n"; + print " -g gid\n"; + print " -G supplementary comma-separated groups\n"; + print " -n do not create a group\n"; + print " -d home\n"; + print " -s shell\n"; + print " -c gecos\n"; + print " -m creates home directory and copies /etc/skel\n"; + print " -k skeleton dir (with -m)\n"; + print " -P ends by invoking smbldap-passwd.pl\n"; + print " -A can change password ? 0 if no, 1 if yes\n"; + print " -B must change password ? 0 if no, 1 if yes\n"; + print " -C sambaHomePath (SMB home share, like '\\\\PDC-SRV\\homes')\n"; + print " -D sambaHomeDrive (letter associated with home share, like 'H:')\n"; + print " -E sambaLogonScript (DOS script to execute on login)\n"; + print " -F sambaProfilePath (profile directory, like '\\\\PDC-SRV\\profiles\\foo')\n"; + print " -H sambaAcctFlags (samba account control bits like '[NDHTUMWSLKI]')\n"; + print " -N canonical name\n"; + print " -S surname\n"; + print " -? show this help message\n"; + exit (1); +} + + +# cause problems when dealing with getpwuid because of the +# negative ttl and ldap modification +my $nscd_status = system "/etc/init.d/nscd status >/dev/null 2>&1"; + +if ($nscd_status == 0) { + system "/etc/init.d/nscd stop > /dev/null 2>&1"; +} + + +# 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"; +} + + +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; +} + +# Read only first @ARGV +my $userName = $ARGV[0]; + +# untaint $userName (can finish with one or two $) +if ($userName =~ /^([\w -]+\$?)$/) { + $userName = $1; +} else { + print "$0: illegal username\n"; + exit (1); +} + +# user must not exist in LDAP (should it be nss-wide ?) +my ($rc, $dn) = get_user_dn2($userName); +if ($rc and defined($dn)) { + print "$0: user $userName exists\n"; + exit (9); +} elsif (!$rc) { + print "$0: error in get_user_dn2\n"; + exit(10); +} + +my $group_entry; +my $userGroupSID; +my $userRid; +if ($Options{'a'}) { + # as grouprid we use the value of the sambaSID attribute for + # group of gidNumber=$userGidNumber + $group_entry = read_group_entry_gid($userGidNumber); + $userGroupSID = $group_entry->get_value('sambaSID'); + unless ($userGroupSID) { + print "$0: unknown group SID not set for unix group $userGidNumber\n"; + print "check if your unix group is mapped to an NT group\n"; + exit (7); + } + + # as rid we use 2 * uid + 1000 + $userRid = 2 * $userUidNumber + 1000; + # let's test if this SID already exist + my $user_sid="$SID-$userRid"; + my $test_exist_sid=does_sid_exist($user_sid,$usersdn); + if ($test_exist_sid->count == 1) { + print "User SID already owned by\n"; + # there should not exist more than one entry, but ... + foreach my $entry ($test_exist_sid->all_entries) { + my $dn= $entry->dn; + chomp($dn); + print "$dn\n"; + } + exit(7); + } +} + +my $userHomeDirectory; +my ($userCN, $userSN); +my $tmp; +if (!defined($userHomeDirectory = $Options{'d'})) { + $userHomeDirectory = $_userHomePrefix."/".$userName; +} +$_userLoginShell = $tmp if (defined($tmp = $Options{'s'})); +$_userGecos = $tmp if (defined($tmp = $Options{'c'})); +$_skeletonDir = $tmp if (defined($tmp = $Options{'k'})); +$userCN = ($Options{'c'} || $userName); +$userCN = $tmp if (defined($tmp = $Options{'N'})); +$userSN = $userName; +$userSN = $tmp if (defined($tmp = $Options{'S'})); + + +######################## + +my $ldap_master=connect_ldap_master(); + +# MACHINE ACCOUNT +if (defined($tmp = $Options{'w'})) { + + # 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) { + # (jtournier) + # Objectclass sambaSamAccount is now added directly by samba when joigning the domain (for samba3) + #if (!add_samba_machine_mkntpwd($userName, $userUidNumber)) { + # die "$0: error while adding samba account\n"; + #} + } else { + if (!add_samba_machine($userName)) { + die "$0: error while adding samba account\n"; + } + my $modify = $ldap_master->modify ( "$dn", + changes => [ + replace => [sambaAcctFlags => '[W ]'] + ] + ); + $modify->code && warn "failed to modify entry: ", $modify->error ; + } + + exit 0; +} + +# USER ACCOUNT +# add posix account first + +my $add = $ldap_master->add ("uid=$userName,$usersdn", + attr => [ + 'objectclass' => ['top','inetOrgPerson', 'posixAccount'], + 'cn' => "$userCN", + 'sn' => "$userSN", + 'uid' => "$userName", + 'uidNumber' => "$userUidNumber", + 'gidNumber' => "$userGidNumber", + 'homeDirectory' => "$userHomeDirectory", + 'loginShell' => "$_userLoginShell", + 'gecos' => "$_userGecos", + 'description' => "$_userGecos", + 'userPassword' => "{crypt}x" + ] + ); + +$add->code && warn "failed to add entry: ", $add->error ; + + +#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 $valpwdlastset = 0; + 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"; + # To force a user to change his password: + # . the attribut sambaPwdLastSet must be != 0 + # . the attribut sambaAcctFlags must not match the 'X' flag + $valpwdlastset=$winmagic; + $valacctflags = "[U]"; + } else { + $valpwdmustchange = "$winmagic"; + } + } + + if (defined($tmp = $Options{'H'})) { + $valacctflags = "$tmp"; + } + + + my $modify = $ldap_master->modify ( "uid=$userName,$usersdn", + changes => [ + add => [objectClass => 'sambaSamAccount'], + add => [sambaPwdLastSet => "$valpwdlastset"], + add => [sambaLogonTime => '0'], + add => [sambaLogoffTime => '2147483647'], + add => [sambaKickoffTime => '2147483647'], + add => [sambaPwdCanChange => "$valpwdcanchange"], + add => [sambaPwdMustChange => "$valpwdmustchange"], + add => [displayName => "$_userGecos"], + add => [sambaAcctFlags => "$valacctflags"], + add => [sambaSID => "$SID-$userRid"] + ] + ); + + $modify->code && die "failed to add entry: ", $modify->error ; + + } 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 @mods; + my $valscriptpath; + if (defined $_userScript) { + $valscriptpath="$_userScript"; + } else { + $valscriptpath = "$userName.cmd"; + } + if (defined($tmp = $Options{'E'})) { + $valscriptpath = "$tmp"; + } + + my $valsmbhome; + if (defined $_userSmbHome) { + $valsmbhome = "$_userSmbHome"; + } + if (defined($tmp = $Options{'C'})) { + $valsmbhome = "$tmp"; + } + if (defined $valsmbhome) { + push(@mods, 'sambaHomePath', $valsmbhome); + } + + my $valhomedrive = "$_userHomeDrive"; + if (defined($tmp = $Options{'D'})) { + $tmp = $tmp.":" unless ($tmp =~ /:/); + $valhomedrive = "$tmp"; + } + + my $valprofilepath; + if (defined $_userProfile) { + $valprofilepath = "$_userProfile$userName"; + } + + if (defined($tmp = $Options{'F'})) { + $valprofilepath = "$tmp"; + } + if (defined $valprofilepath) { + push(@mods, 'sambaProfilePath', $valprofilepath); + } + + my $modify = $ldap_master->modify ( "uid=$userName,$usersdn", + changes => [ + add => [sambaPrimaryGroupSID => "$userGroupSID"], + add => [sambaHomeDrive => "$valhomedrive"], + add => [sambaLogonScript => "$valscriptpath"], + add => [sambaLMPassword => 'XXX'], + add => [sambaNTPassword => 'XXX'] + ] + ); + $modify = $ldap_master->modify ( "uid=$userName,$usersdn", + 'replace' => { @mods } + ); + + + $modify->code && die "failed to add entry: ", $modify->error ; + +} +$ldap_master->unbind; # take down session + + +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]') + + -N canonical name (defaults to gecos or username, if gecos not set) + + -S surname (defaults to username) + + +=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 index 00000000000..f1e69e209c5 --- /dev/null +++ b/examples/LDAP/smbldap-tools/smbldap-userdel.pl @@ -0,0 +1,125 @@ +#!/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 FindBin; +use FindBin qw($RealBin); +use lib "$RealBin/"; +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 index 00000000000..70151b74122 --- /dev/null +++ b/examples/LDAP/smbldap-tools/smbldap-usermod.pl @@ -0,0 +1,488 @@ +#!/usr/bin/perl -w + +# 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 FindBin; +use FindBin qw($RealBin); +use lib "$RealBin/"; +use smbldap_tools; +use smbldap_conf; + +##################### + +use Getopt::Std; +my %Options; +my $nscd_status; + +my $ok = getopts('A:B:C:D:E:F:H:IJN:S:Pame:f:u:g:G:d:l:s:c:ok:?h', \%Options); +if ( (!$ok) || (@ARGV < 1) || ($Options{'?'}) || ($Options{'h'}) ) { + print "Usage: $0 [-awmugdsckxABCDEFGHI?h] username\n"; + print "Available options are:\n"; + print " -c gecos\n"; + print " -d home directory\n"; + #print " -m move home directory\n"; + #print " -f inactive days\n"; + print " -u uid\n"; + print " -o uid can be non unique\n"; + print " -g gid\n"; + print " -G supplementary groups (comma separated)\n"; + print " -l login name\n"; + print " -s shell\n"; + print " -N canonical name\n"; + print " -S surname\n"; + print " -P ends by invoking smbldap-passwd.pl\n"; + print " For samba users:\n"; + print " -a add sambaSamAccount objectclass\n"; + print " -e expire date (\"YYYY-MM-DD HH:MM:SS\")\n"; + print " -A can change password ? 0 if no, 1 if yes\n"; + print " -B must change password ? 0 if no, 1 if yes\n"; + print " -C sambaHomePath (SMB home share, like '\\\\PDC-SRV\\homes')\n"; + print " -D sambaHomeDrive (letter associated with home share, like 'H:')\n"; + print " -E sambaLogonScript (DOS script to execute on login)\n"; + print " -F sambaProfilePath (profile directory, like '\\\\PDC-SRV\\profiles\\foo')\n"; + print " -H sambaAcctFlags (samba account control bits like '[NDHTUMWSLKI]')\n"; + print " -I disable an user. Can't be used with -H or -J\n"; + print " -J enable an user. Can't be used with -H or -I\n"; + print " -?|-h show this help message\n"; + exit (1); +} + +if ($< != 0) { + print "You must be root to modify an user\n"; + exit (1); +} + +# Read only first @ARGV +my $user = $ARGV[0]; + +# Read user data +my $user_entry = read_user_entry($user); +if (!defined($user_entry)) { + print "$0: user $user doesn't exist\n"; + exit (1); +} + +my $samba = 0; +if (grep ($_ =~ /^sambaSamAccount$/i, $user_entry->get_value('objectClass'))) { + $samba = 1; +} + +# get the dn of the user +my $dn= $user_entry->dn(); + +my $tmp; +my @mods; +if (defined($tmp = $Options{'a'})) { + # Let's connect to the directory first + my $ldap_master=connect_ldap_master(); + my $winmagic = 2147483647; + my $valpwdcanchange = 0; + my $valpwdmustchange = $winmagic; + my $valpwdlastset = 0; + my $valacctflags = "[UX]"; + my $user_entry=read_user_entry($user); + my $uidNumber = $user_entry->get_value('uidNumber'); + my $userRid = 2 * $uidNumber + 1000; + # apply changes + my $modify = $ldap_master->modify ( "$dn", + changes => [ + add => [objectClass => 'sambaSamAccount'], + add => [sambaPwdLastSet => "$valpwdlastset"], + add => [sambaLogonTime => '0'], + add => [sambaLogoffTime => '2147483647'], + add => [sambaKickoffTime => '2147483647'], + add => [sambaPwdCanChange => "$valpwdcanchange"], + add => [sambaPwdMustChange => "$valpwdmustchange"], + add => [displayName => "$_userGecos"], + add => [sambaSID=> "$SID-$userRid"], + add => [sambaAcctFlags => "$valacctflags"], + ] + ); + $modify->code && warn "failed to modify entry: ", $modify->error ; +} + +# Process options +my $changed_uid; +my $_userUidNumber; +my $_userRid; +if (defined($tmp = $Options{'u'})) { + if (defined($Options{'o'})) { + $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"; + } + + } + push(@mods, 'uidNumber', $tmp); + $_userUidNumber = $tmp; + if ($samba) { + # as rid we use 2 * uid + 1000 + my $_userRid = 2 * $_userUidNumber + 1000; + if (defined($Options{'x'})) { + $_userRid= sprint("%x", $_userRid); + } + push(@mods, 'sambaSID', $SID.'-'.$_userRid); + } + $changed_uid = 1; +} + +my $changed_gid; +my $_userGidNumber; +my $_userGroupSID; +if (defined($tmp = $Options{'g'})) { + $_userGidNumber = parse_group($tmp); + if ($_userGidNumber < 0) { + print "$0: group $tmp doesn't exist\n"; + exit (6); + } + push(@mods, 'gidNumber', $_userGidNumber); + if ($samba) { + # as grouprid we use the sambaSID attribute's value of the group + my $group_entry = read_group_entry_gid($_userGidNumber); + my $_userGroupSID = $group_entry->get_value('sambaSID'); + unless ($_userGroupSID) { + print "$0: unknown group SID not set for unix group $_userGidNumber\n"; + exit (7); + } + push(@mods, 'sambaPrimaryGroupSid', $_userGroupSID); + } + $changed_gid = 1; +} + +if (defined($tmp = $Options{'s'})) { + push(@mods, 'loginShell' => $tmp); +} + + +if (defined($tmp = $Options{'c'})) { + push(@mods, 'gecos' => $tmp, + 'description' => $tmp); + if ($samba == 1) { + push(@mods, 'displayName' => $tmp); + } +} + +if (defined($tmp = $Options{'d'})) { + push(@mods, 'homeDirectory' => $tmp); +} + +if (defined($tmp = $Options{'N'})) { + push(@mods, 'cn' => $tmp); +} + +if (defined($tmp = $Options{'S'})) { + push(@mods, 'sn' => $tmp); +} + +if (defined($tmp = $Options{'G'})) { + + # 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; + +$samba = is_samba_user($user); + +if (defined($tmp = $Options{'e'})) { + if ($samba == 1) { + my $kickoffTime=`date --date='$tmp' +%s`; + chomp($kickoffTime); + push(@mods, 'sambakickoffTime' => $kickoffTime); + } else { + print "User $user is not a samba user\n"; + } +} + +my $_sambaPwdCanChange; +if (defined($tmp = $Options{'A'})) { + if ($samba == 1) { + $attr = "sambaPwdCanChange"; + if ($tmp != 0) { + $_sambaPwdCanChange=0; + } else { + $_sambaPwdCanChange=$winmagic; + } + push(@mods, 'sambaPwdCanChange' => $_sambaPwdCanChange); + } else { + print "User $user is not a samba user\n"; + } +} + +my $_sambaPwdMustChange; +if (defined($tmp = $Options{'B'})) { + if ($samba == 1) { + if ($tmp != 0) { + $_sambaPwdMustChange=0; + # To force a user to change his password: + # . the attribut sambaPwdLastSet must be != 0 + # . the attribut sambaAcctFlags must not match the 'X' flag + my $_sambaAcctFlags; + my $flags = $user_entry->get_value('sambaAcctFlags'); + if ( $flags =~ /X/ ) { + my $letters; + if ($flags =~ /(\w+)/) { + $letters = $1; + } + $letters =~ s/X//; + $_sambaAcctFlags="\[$letters\]"; + push(@mods, 'sambaAcctFlags' => $_sambaAcctFlags); + } + my $_sambaPwdLastSet = $user_entry->get_value('sambaPwdLastSet'); + if ($_sambaPwdLastSet == 0) { + push(@mods, 'sambaPwdLastSet' => $winmagic); + } + } else { + $_sambaPwdMustChange=$winmagic; + } + push(@mods, 'sambaPwdMustChange' => $_sambaPwdMustChange); + } else { + print "User $user is not a samba user\n"; + } +} + +if (defined($tmp = $Options{'C'})) { + if ($samba == 1) { + #$tmp =~ s/\\/\\\\/g; + push(@mods, 'sambaHomePath' => $tmp); + } else { + print "User $user is not a samba user\n"; + } +} + +my $_sambaHomeDrive; +if (defined($tmp = $Options{'D'})) { + if ($samba == 1) { + $tmp = $tmp.":" unless ($tmp =~ /:/); + push(@mods, 'sambaHomeDrive' => $tmp); + } else { + print "User $user is not a samba user\n"; + } +} + +if (defined($tmp = $Options{'E'})) { + if ($samba == 1) { + #$tmp =~ s/\\/\\\\/g; + push(@mods, 'sambaLogonScript' => $tmp); + } else { + print "User $user is not a samba user\n"; + } +} + +if (defined($tmp = $Options{'F'})) { + if ($samba == 1) { + #$tmp =~ s/\\/\\\\/g; + push(@mods, 'sambaProfilePath' => $tmp); + } else { + print "User $user is not a samba user\n"; + } +} + +if ($samba == 1 and (defined $Options{'H'} or defined $Options{'I'} or defined $Options{'J'})) { + my $_sambaAcctFlags; + if (defined($tmp = $Options{'H'})) { + #$tmp =~ s/\\/\\\\/g; + $_sambaAcctFlags=$tmp; + } else { + # I or J + my $flags; + $flags = $user_entry->get_value('sambaAcctFlags'); + + if (defined($tmp = $Options{'I'})) { + if ( !($flags =~ /D/) ) { + my $letters; + if ($flags =~ /(\w+)/) { + $letters = $1; + } + $_sambaAcctFlags="\[D$letters\]"; + } + } elsif (defined($tmp = $Options{'J'})) { + if ( $flags =~ /D/ ) { + my $letters; + if ($flags =~ /(\w+)/) { + $letters = $1; + } + $letters =~ s/D//; + $_sambaAcctFlags="\[$letters\]"; + } + } + } + + + if ("$_sambaAcctFlags" ne '') { + push(@mods, 'sambaAcctFlags' => $_sambaAcctFlags); + } + +} elsif (!$samba == 1 and (defined $Options{'H'} or defined $Options{'I'} or defined $Options{'J'})) { + print "User $user is not a samba user\n"; +} + +# Let's connect to the directory first +my $ldap_master=connect_ldap_master(); + +# apply changes +my $modify = $ldap_master->modify ( "$dn", + 'replace' => { @mods } + ); +$modify->code && warn "failed to modify entry: ", $modify->error ; + +# take down session +$ldap_master->unbind; + +$nscd_status = system "/etc/init.d/nscd status >/dev/null 2>&1"; + +if ($nscd_status == 0) { + system "/etc/init.d/nscd restart > /dev/null 2>&1"; +} + +if (defined($Options{'P'})) { + exec "/usr/local/sbin/smbldap-passwd.pl $user" +} + + +############################################################ + +=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 index 00000000000..173480d76c2 --- /dev/null +++ b/examples/LDAP/smbldap-tools/smbldap-usershow.pl @@ -0,0 +1,72 @@ +#!/usr/bin/perl -w + +# 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 FindBin; +use FindBin qw($RealBin); +use lib "$RealBin/"; +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 index 00000000000..257c205a2cd --- /dev/null +++ b/examples/LDAP/smbldap-tools/smbldap_conf.pm @@ -0,0 +1,248 @@ +#!/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 $ldapmodify $suffix $usersdn $computersdn + $groupsdn $scope $binddn $bindpasswd + $slaveDN $slavePw $masterDN $masterPw + $_userLoginShell $_userHomePrefix $_userGecos + $_defaultUserGid $_defaultComputerGid + $_skeletonDir $_userSmbHome + $_userProfile $_userHomeDrive + $_userScript $usersou $computersou $groupsou $SID $hash_encrypt $_defaultMaxPasswordAge + ); + +use Exporter; +$VERSION = 1.00; +@ISA = qw(Exporter); + +@EXPORT = qw( + $UID_START $GID_START $smbpasswd $slaveLDAP $masterLDAP + $slavePort $masterPort $ldapSSL $slaveURI $masterURI $with_smbpasswd $mk_ntpasswd + $ldap_path $ldap_opts $ldapmodify $suffix $usersdn + $computersdn $groupsdn $scope $binddn $bindpasswd + $slaveDN $slavePw $masterDN $masterPw + $_userLoginShell $_userHomePrefix $_userGecos + $_defaultUserGid $_defaultComputerGid $_skeletonDir + $_userSmbHome $_userProfile $_userHomeDrive $_userScript + $usersou $computersou $groupsou $SID $hash_encrypt $_defaultMaxPasswordAge + ); + + +############################################################################## +# +# General Configuration +# +############################################################################## + +# UID and GID starting at... +$UID_START = 1000; +$GID_START = 1000; + +# Put your own SID +# to obtain this number do: "net getlocalsid" +$SID='S-1-5-21-3516781642-1962875130-3438800523'; + +############################################################################## +# +# 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. +# Those two servers declarations can also be used when you have +# . one master LDAP server where all writing operations must be done +# . one slave LDAP server where all reading operations must be done +# (typically a replication directory) + +# Ex: $slaveLDAP = "127.0.0.1"; +$slaveLDAP = "127.0.0.1"; +$slavePort = "389"; + +# Master LDAP : needed for write operations +# Ex: $masterLDAP = "127.0.0.1"; +$masterLDAP = "127.0.0.1"; +$masterPort = "389"; + +# Use SSL for LDAP +# If set to "1", this option will use start_tls for connection +# (you should also used the port 389) +$ldapSSL = "0"; + +# LDAP Suffix +# Ex: $suffix = "dc=IDEALX,dc=ORG"; +$suffix = "dc=IDEALX,dc=COM"; + + +# 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"; + +# Unix password encryption (CRYPT, MD5, SMD5, SSHA, SHA) +$hash_encrypt="SSHA"; + +############################ +# Credential Configuration # +############################ +# Bind DN used +# Ex: $binddn = "cn=Manager,$suffix"; for cn=Manager,dc=IDEALX,dc=org +$binddn = "cn=Manager,$suffix"; + +# Bind DN passwd used +# Ex: $bindpasswd = 'secret'; for 'secret' +$bindpasswd = "secret"; + +# Notes: if using dual ldap patch, you can specify to different configuration +# By default, we will use the same DN (so it will work for standard Samba +# release) +$slaveDN = $binddn; +$slavePw = $bindpasswd; +$masterDN = $binddn; +$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 = 513; + +# Default Computer (Samba) GID +$_defaultComputerGid = 553; + +# Skel dir +$_skeletonDir = q(/etc/skel); + +# Default password validation time (time in days) Comment the next line if +# you don't want password to be enable for $_defaultMaxPasswordAge days (be +# careful to the sambaPwdMustChange attribute's value) +$_defaultMaxPasswordAge = 45; + +############################################################################## +# +# SAMBA Configuration +# +############################################################################## + +# The UNC path to home drives location without the username last extension +# (will be dynamically prepended) +# Ex: q(\\\\My-PDC-netbios-name\\homes) for \\My-PDC-netbios-name\homes +# Just comment this if you want to use the smb.conf 'logon home' directive +# and/or desabling roaming profiles +$_userSmbHome = q(\\\\_PDCNAME_\\homes); + +# The UNC path to profiles locations without the username last extension +# (will be dynamically prepended) +# Ex: q(\\\\My-PDC-netbios-name\\profiles\\) for \\My-PDC-netbios-name\profiles +# Just comment this if you want to use the smb.conf 'logon path' directive +# and/or desabling roaming profiles +$_userProfile = q(\\\\_PDCNAME_\\profiles\\); + +# The default Home Drive Letter mapping +# (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"; + +# those next externals commands are kept fot the migration scripts and +# for the populate script: this will be updated as soon as possible +$slaveURI = "ldap://$slaveLDAP:$slavePort"; +$masterURI = "ldap://$masterLDAP:$masterPort"; + +$ldap_path = "/usr/bin"; + +if ( $ldapSSL eq "0" ) { + $ldap_opts = "-x"; +} elsif ( $ldapSSL eq "1" ) { + $ldap_opts = "-x -Z"; +} else { + die "ldapSSL option must be either 0 or 1.\n"; +} + +#$ldapsearch = "$ldap_path/ldapsearch $ldap_opts -H $slaveURI -D '$slaveDN' -w '$slavePw'"; +#$ldapsearchnobind = "$ldap_path/ldapsearch $ldap_opts -H $slaveURI"; +$ldapmodify = "$ldap_path/ldapmodify $ldap_opts -H $masterURI -D '$masterDN' -w '$masterPw'"; +#$ldappasswd = "$ldap_path/ldappasswd $ldap_opts -H $masterURI -D '$masterDN' -w '$masterPw'"; +#$ldapadd = "$ldap_path/ldapadd $ldap_opts -H $masterURI -D '$masterDN' -w '$masterPw'"; +#$ldapdelete = "$ldap_path/ldapdelete $ldap_opts -H $masterURI -D '$masterDN' -w '$masterPw'"; +#$ldapmodrdn = "$ldap_path/ldapmodrdn $ldap_opts -H $masterURI -D '$masterDN' -w '$masterPw'"; + + + +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 index 00000000000..d33a65b7d17 --- /dev/null +++ b/examples/LDAP/smbldap-tools/smbldap_tools.pm @@ -0,0 +1,771 @@ +#! /usr/bin/perl -w +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_group_member + is_samba_user + is_unix_user + is_user_valid + does_sid_exist + get_dn_from_line + add_posix_machine + add_samba_machine + add_samba_machine_mkntpwd + group_add_user + add_grouplist_user + disable_user + delete_user + group_add + group_del + get_homedir + read_user + read_user_entry + read_group + read_group_entry + read_group_entry_gid + find_groups_of + parse_group + group_remove_member + group_get_members + do_ldapadd + do_ldapmodify + get_user_dn2 + connect_ldap_master + connect_ldap_slave + group_type_by_name + ); + +sub connect_ldap_master + { + # bind to a directory with dn and password + my $ldap_master = Net::LDAP->new( + "$masterLDAP", + port => "$masterPort", + version => 3, + # debug => 0xffff, + ) + or die "erreur LDAP: Can't contact master ldap server ($@)"; + if ($ldapSSL == 1) { + $ldap_master->start_tls( + # verify => 'require', + # clientcert => 'mycert.pem', + # clientkey => 'mykey.pem', + # decryptkey => sub { 'secret'; }, + # capath => '/usr/local/cacerts/' + ); + } + $ldap_master->bind ( "$binddn", + password => "$masterPw" + ); + return($ldap_master); + } + +sub connect_ldap_slave + { + # bind to a directory with dn and password + my $ldap_slave = Net::LDAP->new( + "$slaveLDAP", + port => "$slavePort", + version => 3, + # debug => 0xffff, + ) + or die "erreur LDAP: Can't contact slave ldap server ($@)"; + if ($ldapSSL == 1) { + $ldap_slave->start_tls( + # verify => 'require', + # clientcert => 'mycert.pem', + # clientkey => 'mykey.pem', + # decryptkey => sub { 'secret'; }, + # capath => '/usr/local/cacerts/' + ); + } + $ldap_slave->bind ( "$binddn", + password => "$slavePw" + ); + return($ldap_slave); + } + +sub get_user_dn + { + my $user = shift; + my $dn=''; + my $ldap_slave=connect_ldap_slave(); + my $mesg = $ldap_slave->search ( base => $suffix, + scope => $scope, + filter => "(&(objectclass=posixAccount)(uid=$user))" + ); + $mesg->code && die $mesg->error; + foreach my $entry ($mesg->all_entries) { + $dn= $entry->dn; + } + $ldap_slave->unbind; + chomp($dn); + if ($dn eq '') { + return undef; + } + $dn="dn: ".$dn; + return $dn; + } + + +sub get_user_dn2 + { + my $user = shift; + my $dn=''; + my $ldap_slave=connect_ldap_slave(); + my $mesg = $ldap_slave->search ( base => $suffix, + scope => $scope, + filter => "(&(objectclass=posixAccount)(uid=$user))" + ); + $mesg->code && warn "failed to perform search; ", $mesg->error; + + foreach my $entry ($mesg->all_entries) { + $dn= $entry->dn; + } + $ldap_slave->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_slave=connect_ldap_slave(); + my $mesg = $ldap_slave->search ( base => $groupsdn, + scope => $scope, + filter => "(&(objectclass=posixGroup)(|(cn=$group)(gidNumber=$group)))" + ); + $mesg->code && die $mesg->error; + foreach my $entry ($mesg->all_entries) { + $dn= $entry->dn; + } + $ldap_slave->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_slave=connect_ldap_slave(); + my $mesg = $ldap_slave->search ( base => $suffix, + scope => $scope, + filter => "(&(objectClass=sambaSamAccount)(uid=$user))" + ); + $mesg->code && die $mesg->error; + $ldap_slave->unbind; + return ($mesg->count ne 0); + } + +sub is_unix_user + { + my $user = shift; + my $ldap_slave=connect_ldap_slave(); + my $mesg = $ldap_slave->search ( base => $suffix, + scope => $scope, + filter => "(&(objectClass=posixAccount)(uid=$user))" + ); + $mesg->code && die $mesg->error; + $ldap_slave->unbind; + return ($mesg->count ne 0); + } + +sub is_group_member + { + my $dn_group = shift; + my $user = shift; + my $ldap_slave=connect_ldap_slave(); + my $mesg = $ldap_slave->search ( base => $dn_group, + scope => 'base', + filter => "(&(memberUid=$user))" + ); + $mesg->code && die $mesg->error; + $ldap_slave->unbind; + return ($mesg->count ne 0); + } + +# all entries = does_sid_exist($sid,$scope) +sub does_sid_exist + { + my $sid = shift; + my $dn_group=shift; + my $ldap_slave=connect_ldap_slave(); + my $mesg = $ldap_slave->search ( base => $dn_group, + scope => $scope, + filter => "(sambaSID=$sid)" + #filter => "(&(objectClass=sambaSamAccount|objectClass=sambaGroupMapping)(sambaSID=$sid))" + ); + $mesg->code && die $mesg->error; + $ldap_slave->unbind; + return ($mesg); + } + +# try to bind with user dn and password to validate current password +sub is_user_valid + { + my ($user, $dn, $pass) = @_; + my $ldap = Net::LDAP->new($slaveLDAP) or die "erreur LDAP"; + my $mesg= $ldap->bind (dn => $dn, password => $pass ); + if ($mesg->code eq 0) { + $ldap->unbind; + return 1; + } else { + if ($ldap->bind()) { + $ldap->unbind; + return 0; + } else { + print ("The LDAP directory is not available.\n Check the server, cables ..."); + $ldap->unbind; + return 0; + } + die "Problem : contact your administrator"; + } + } + + +# dn = get_dn_from_line ($dn_line) +# helper to get "a=b,c=d" from "dn: a=b,c=d" +sub get_dn_from_line + { + my $dn = shift; + $dn =~ s/^dn: //; + return $dn; + } + + +# success = add_posix_machine($user, $uid, $gid) +sub add_posix_machine + { + my ($user, $uid, $gid) = @_; + # bind to a directory with dn and password + my $ldap_master=connect_ldap_master(); + my $add = $ldap_master->add ( "uid=$user,$computersdn", + attr => [ + 'objectclass' => ['top','inetOrgPerson', 'posixAccount'], + 'cn' => "$user", + 'sn' => "$user", + 'uid' => "$user", + 'uidNumber' => "$uid", + 'gidNumber' => "$gid", + 'homeDirectory' => '/dev/null', + 'loginShell' => '/bin/false', + 'description' => 'Computer', + ] + ); + + $add->code && warn "failed to add entry: ", $add->error ; + # take down the session + $ldap_master->unbind; + + } + + +# success = add_samba_machine($computername) +sub add_samba_machine + { + 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 $ldap_master=connect_ldap_master(); + my $modify = $ldap_master->modify ( "uid=$user,$computersdn", + changes => [ + replace => [objectClass => ['inetOrgPerson', 'posixAccount', 'sambaSamAccount']], + add => [sambaPwdLastSet => '0'], + add => [sambaLogonTime => '0'], + add => [sambaLogoffTime => '2147483647'], + add => [sambaKickoffTime => '2147483647'], + add => [sambaPwdCanChange => '0'], + add => [sambaPwdMustChange => '0'], + add => [sambaAcctFlags => '[W ]'], + add => [sambaLMPassword => "$lmpassword"], + add => [sambaNTPassword => "$ntpassword"], + add => [sambaSID => "$SID-$sambaSID"], + add => [sambaPrimaryGroupSID => "$SID-0"] + ] + ); + + $modify->code && die "failed to add entry: ", $modify->error ; + + return 1; + # take down the session + $ldap_master->unbind; + + } + + +sub group_add_user + { + my ($group, $userid) = @_; + my $members=''; + my $dn_line = get_group_dn($group); + if (!defined(get_group_dn($group))) { + print "$0: group \"$group\" doesn't exist\n"; + exit (6); + } + if (!defined($dn_line)) { + return 1; + } + my $dn = get_dn_from_line("$dn_line"); + # on look if the user is already present in the group + my $is_member=is_group_member($dn,$userid); + if ($is_member == 1) { + print "User \"$userid\" already member of the group \"$group\".\n"; + } else { + # bind to a directory with dn and password + my $ldap_master=connect_ldap_master(); + # It does not matter if the user already exist, Net::LDAP will add the user + # if he does not exist, and ignore him if his already in the directory. + my $modify = $ldap_master->modify ( "$dn", + changes => [ + add => [memberUid => $userid] + ] + ); + $modify->code && die "failed to modify entry: ", $modify->error ; + # take down session + $ldap_master->unbind; + } + } + +sub group_del + { + my $group_dn=shift; + # bind to a directory with dn and password + my $ldap_master=connect_ldap_master(); + my $modify = $ldap_master->delete ($group_dn); + $modify->code && die "failed to delete group : ", $modify->error ; + # take down session + $ldap_master->unbind; + } + +sub add_grouplist_user + { + my ($grouplist, $user) = @_; + my @array = split(/,/, $grouplist); + foreach my $group (@array) { + group_add_user($group, $user); + } + } + +sub disable_user + { + my $user = shift; + my $dn_line; + my $dn = get_dn_from_line($dn_line); + + if (!defined($dn_line = get_user_dn($user))) { + print "$0: user $user doesn't exist\n"; + exit (10); + } + my $ldap_master=connect_ldap_master(); + my $modify = $ldap_master->modify ( "$dn", + changes => [ + replace => [userPassword => '{crypt}!x'] + ] + ); + $modify->code && die "failed to modify entry: ", $modify->error ; + + if (is_samba_user($user)) { + my $modify = $ldap_master->modify ( "$dn", + changes => [ + replace => [sambaAcctFlags => '[D ]'] + ] + ); + $modify->code && die "failed to modify entry: ", $modify->error ; + } + # take down session + $ldap_master->unbind; + } + +# delete_user($user) +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); + my $ldap_master=connect_ldap_master(); + my $modify = $ldap_master->delete($dn); + $ldap_master->unbind; + } + +# $gid = group_add($groupname, $group_gid, $force_using_existing_gid) +sub group_add + { + my ($gname, $gid, $force) = @_; + my $nscd_status = system "/etc/init.d/nscd status >/dev/null 2>&1"; + if ($nscd_status == 0) { + 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 undef; + } + } + } + if ($nscd_status == 0) { + system "/etc/init.d/nscd start > /dev/null 2>&1"; + } + my $ldap_master=connect_ldap_master(); + my $modify = $ldap_master->add ( "cn=$gname,$groupsdn", + attrs => [ + objectClass => 'posixGroup', + cn => "$gname", + gidNumber => "$gid" + ] + ); + + $modify->code && die "failed to add entry: ", $modify->error ; + # take down session + $ldap_master->unbind; + return $gid; + } + +# $homedir = get_homedir ($user) +sub get_homedir + { + my $user = shift; + my $homeDir=''; + my $ldap_slave=connect_ldap_slave(); + my $mesg = $ldap_slave->search ( + base =>$suffix, + scope => $scope, + filter => "(&(objectclass=posixAccount)(uid=$user))" + ); + $mesg->code && die $mesg->error; + foreach my $entry ($mesg->all_entries) { + foreach my $attr ($entry->attributes) { + if ($attr=~/\bhomeDirectory\b/) { + foreach my $ent ($entry->get_value($attr)) { + $homeDir.= $attr.": ".$ent."\n"; + } + } + } + } + $ldap_slave->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_slave=connect_ldap_slave(); + my $mesg = $ldap_slave->search ( # perform a search + base => $suffix, + scope => $scope, + filter => "(&(objectclass=posixAccount)(uid=$user))" + ); + + $mesg->code && die $mesg->error; + foreach my $entry ($mesg->all_entries) { + $lines.= "dn: " . $entry->dn."\n"; + foreach my $attr ($entry->attributes) { + { + $lines.= $attr.": ".join(',', $entry->get_value($attr))."\n"; + } + } + } + # take down session + $ldap_slave->unbind; + chomp $lines; + if ($lines eq '') { + return undef; + } + return $lines; + } + +# search for a user +# return the attributes in an array +sub read_user_entry + { + my $user = shift; + my $ldap_slave=connect_ldap_slave(); + my $mesg = $ldap_slave->search ( # perform a search + base => $suffix, + scope => $scope, + filter => "(&(objectclass=posixAccount)(uid=$user))" + ); + + $mesg->code && die $mesg->error; + my $entry = $mesg->entry(); + $ldap_slave->unbind; + return $entry; + } + +# search for a group +sub read_group + { + my $user = shift; + my $lines =''; + my $ldap_slave=connect_ldap_slave(); + my $mesg = $ldap_slave->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"; + } + } + } + # take down session + $ldap_slave->unbind; + 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_slave=connect_ldap_slave; + my $mesg = $ldap_slave->search ( # perform a search + base => $groupsdn, + scope => $scope, + filter => "(&(objectclass=posixGroup)(memberuid=$user))" + ); + $mesg->code && die $mesg->error; + foreach my $entry ($mesg->all_entries) { + $lines.= "dn: ".$entry->dn."\n"; + } + $ldap_slave->unbind; + chomp($lines); + if ($lines eq '') { + return undef; + } + return $lines; + } + +sub read_group_entry { + my $group = shift; + my $entry; + my %res; + my $ldap_slave=connect_ldap_slave(); + my $mesg = $ldap_slave->search ( # perform a search + base => $groupsdn, + scope => $scope, + filter => "(&(objectclass=posixGroup)(cn=$group))" + ); + + $mesg->code && die $mesg->error; + my $nb=$mesg->count; + if ($nb > 1) { + print "Error: $nb groups exist \"cn=$group\"\n"; + foreach $entry ($mesg->all_entries) { my $dn=$entry->dn; print " $dn\n"; } + exit 11; + } else { + $entry = $mesg->shift_entry(); + } + return $entry; +} + +sub read_group_entry_gid { + my $group = shift; + my %res; + my $ldap_slave=connect_ldap_slave(); + my $mesg = $ldap_slave->search ( # perform a search + base => $groupsdn, + scope => $scope, + filter => "(&(objectclass=posixGroup)(gidNumber=$group))" + ); + + $mesg->code && die $mesg->error; + my $entry = $mesg->shift_entry(); + return $entry; +} + +# return the gidnumber for a group given as name or gid +# -1 : bad group name +# -2 : bad gidnumber +sub parse_group + { + my $userGidNumber = shift; + if ($userGidNumber =~ /[^\d]/ ) { + my $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 $dn = get_dn_from_line($grp_line); + # we test if the user exist in the group + my $is_member=is_group_member($dn,$user); + if ($is_member == 1) { + my $ldap_master=connect_ldap_master(); + # delete only the user from the group + my $modify = $ldap_master->modify ( "$dn", + changes => [ + delete => [memberUid => ["$user"]] + ] + ); + $modify->code && die "failed to delete entry: ", $modify->error ; + $ldap_master->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 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; + } + +sub group_type_by_name { + my $type_name = shift; + my %groupmap = ( + 'domain' => 2, + 'local' => 4, + 'builtin' => 5 + ); + return $groupmap{$type_name}; +} + + + +1; + |