Skip to content

Instantly share code, notes, and snippets.

@jas-
Last active February 26, 2024 09:43
Show Gist options
  • Star 4 You must be signed in to star a gist
  • Fork 2 You must be signed in to fork a gist
  • Save jas-/d79bc0c863e1a0336007 to your computer and use it in GitHub Desktop.
Save jas-/d79bc0c863e1a0336007 to your computer and use it in GitHub Desktop.
Samba FS Active Directory Implementation

Samba Configuration for Active Directory

Kerberos realm authentication using LDAP authorization via MS Windows Active Directory

Some details on the SAMBA configuration. Original Samba, ADS, Winbind documention was found http://gentoo-wiki.com/HOWTO_Adding_a_Samba_Server_into_an_existing_AD_Domain.

Pre-Installation for Gentoo using emerge

This particular installation of Samba requires a few additional packages and features to ensure that Active Directory authentication works properly. In this first step we add the necessary use flags to the Gentoo Portage package system.

%> echo net-fs/samba ads acl ldap kerberos pam winbind >> /etc/portage/package.use
%> echo net-nds/openldap sasl samba kerberos >> /etc/portage/package.use
%> echo dev-libs/cyrus-sasl authdaemond -java kerberos pam ldap sasl >> /etc/portage/package.use

Installation for Gentoo using emerge (must be root)

Next we set our use flags prior to emerging the packages Samba requires for our AD authentication type.

%> USE="kerberos acl caps cups ipv6 ldap pam python readline winbind ads async automount doc examples fam quotas selinux swat syslog" /
        emerge mit-krb5 pam_krb5 pam_ldap openldap nss_ldap openssl cyrus-sasl ntp samba -va

Configuration for the /etc/krb5.conf details

Because our primary method of authenticating users is to use the MIT KRB5 protocol we must ensure the configuration is correct which can be set by editing the /etc/krb5.conf. Below is a working example using the UTAH.EDU Kerberos Realm and specifying the allowed domains to use the for the authenticating sources.

[libdefaults]
        default_realm = EXAMPLE.COM

[realms]
        EXAMPLE.COM = {
                kdc = kdc.example.com
        }

[domain_realm]
        .example.com = EXAMPLE.COM
        example.com = EXAMPLE.COM
        example-2.com = EXAMPLE.COm

[loggin]
        default = FILE:/var/log/krb5.log

[appdefaults]
        pam = {
                ticket_lifetime = 365d
                renew_lifetime = 365d
                forwardable = true
                proxiable = false
                retain_after_close = true
                minimum_uid = 0
        }

Configuration for the /etc/nsswitch.conf details

Here we configure the /etc/nsswitch.conf file to allow our Active Directory as an allowed source for looking up domain user accounts using the winbind service daemon which we just installed. As you can also see in the example the nis service is not used because we did not want to run an additional service for user permissions etc.

passwd:      compat winbind
shadow:      compat
group:       compat winbind

# passwd:    db files nis
# shadow:    db files nis
# group:     db files nis

hosts:       files dns wins
networks:    files dns

services:    db files
protocols:   db files
rpc:         db files
ethers:      db files
netmasks:    files
netgroup:    files
bootparams:  files

automount:   files
aliases:     files

Configuration for the /etc/samba/smb.conf details

Now for the bulk of our setup. The /etc/samba/smb.conf file presented here has several features to take note of; (I tried to group similar configuration directives to make it easier to make modifications to later if needed). For details on the available options used in the example below please visit samba.org.

[global]
        workgroup = EXAMPLE
        realm = EXAMPLE.COM
        server string = fs.example.com
        netbios name = fs

        password server = *
        encrypt passwords = true
        security = ads

        lanman auth = no
        ntlm auth = no

        os level = 20

        allow trusted domains = yes
        auth methods = winbind

        interfaces = eth0, lo
        bind interfaces only = yes
        socket options = TCP_NODELAY

        hosts allow = 192.168.0.0/24, 127.0.0.1
        hosts deny = 0.0.0.0/0

        log level = 5 ads:3 auth:3 sam:3
        log level = 1
        log file = /var/log/samba/log.%m
        max log size = 50

        client signing = yes
        client schannel = no
        client use spnego = yes
        client lanman auth = yes
        client NTLMv2 auth = yes
        client plaintext auth = no

        preferred master = no
        local master = no
        domain master = no
        wins proxy = no
        dns proxy = No

        obey pam restrictions = yes

        template shell = /bin/bash
        acl map full control = false
        acl compatibility = Auto
        nt acl support = yes
        inherit permissions = yes
        inherit owner = yes
        create mask = 0755
        inherit acls = yes
        inherit owner = yes
        inherit permissions = yes
        map acl inherit = yes
        template homedir = /home/Authenticated Users/%U

        winbind uid = 1000-2000000
        winbind gid = 500-2000000
        winbind separator = +
        winbind enum users = yes
        winbind enum groups = yes
        winbind nested groups = yes
        winbind use default domain = yes
        winbind offline logon = true
        winbind nss info = rfc2307

        idmap uid = 1000-2000000
        idmap gid = 500-2000000
        idmap domains = SCL
        idmap config SCL:backend = ad
        idmap config SCL:default = yes
        idmap config SCL:schema_mode = rfc2307
        idmap config SCL:range = 1000 - 300000000

[classes]
        comment = Class software
        browsable = yes
        writeable = no
        create mask = 0022
        force create mode = 0022
        directory mask = 0022
        force directory mode = 0022
        inherit permissions = yes
        valid users = shares @EXAMPLE+Users
        path = /fs/classes

[staff]
        comment = Staff folders
        browsable = yes
        writeable = yes
        create mask = 0220
        force create mode = 0220
        directory mask = 0220
        force directory mode = 0220
        valid users = @EXAMPLE+Labstaff
        path = /fs/staff

[images]
        comment = images
        browsable = yes
        writeable = yes
        create mask = 0770
        force create mode = 0770
        directory mask = 0770
        force directory mode = 0770
        inherit permissions = yes
        valid users = SCL+image, @EXAMPLE+PCGroup
        path = /fs/images

[homes]
       comment = %U Home directory
       browsable = yes
       writeable = yes
       create mask = 0220
       force create mode = 0220
       directory mask = 0220
       force directory mode = 0220
       inherit permissions = yes
       valid users = @EXAMPLE+PCGroup
       path = /fs/labrats/%U

Configuration for the /etc/pam.d/system-auth details

Next step is to tell our server how to authenticate users. This is where modifications to the PAM stack is needed. If this is not configured to use the pam_winbind.so authentication module in conjunction with the pam_krb5.so module only local authentication to the passwd database may be used.

#%PAM-1.0

auth       required     pam_mount.so
auth       required     pam_env.so
auth       sufficient   pam_winbind.so
auth       sufficient   pam_unix.so try_first_pass likeauth nullok
auth       sufficient   pam_krb5.so use_first_pass
auth       required     pam_deny.so

account    required     pam_unix.so
account    sufficient   pam_krb5.so ignore_root
account    sufficient   pam_winbind.so

password   optional     pam_krb5.so
password   required     pam_mount.so use_authtok
password   required     pam_cracklib.so difok=2 minlen=8 dcredit=2 ocredit=2 try_first_pass retry=3
password   sufficient   pam_unix.so try_first_pass use_authtok nullok md5 shadow
password   required     pam_deny.so

session    required     pam_mkhomedir.so umask=0022 skel=/etc/skel/
session    required     pam_limits.so
session    required     pam_unix.so
session    optional     pam_mount.so use_authtok
session    optional     pam_krb5.so

Joining Domain (Must have Domain admin access to domain) =

Now that the necessary software, libraries and preliminary configuration has been completed, we will now need to join the server to the domain as a 'member server' role. Below are the steps to take for this process.

Get Kerberized principal for domain admin user

Because Kerberos authentication is to be used we must first obtain a valid TGT for the domain administrator account (if the krb5.conf file was not configured this will fail).

%> kinit Administrator@EXAMPLE.COM
%> klist
Ticket cache: FILE:/tmp/krb5cc_0
Default principal: Administrator@EXAMPLE.COm

Valid starting     Expires            Service principal
05/28/08 05:39:23  05/28/08 15:39:23  krbtgt/Administrator@EXAMPLE.COM
        renew until 06/04/08 05:39:23

Join Samba to the domain with domain admin

Next step is to use the 'net' tool which accompanies the Samba package. Here we use it to join the domain with our recently kerberos authenticated domain administrator account.

%> net ads join -UAdmin@EXAMPLE.COM
Admin@SCL.UTAH.EDU's password:
Using short domain name -- EXAMPLE
Joined 'FS' to realm 'EXAMPLE.COM'

Add the samba service to startup

Because we would like this service to startup each time the machine turns on we must add it to the necessary run levels.

%> rc-update add samba boot

Starting and stopping the Samba service

To start and stop the service the following command will work in Gentoo Linux distributions.

%> /etc/init.d/samba start|stop|restart

Various utilities

Because verification of the above steps is essential to this file sharing service I am going to touch on some of the various tools which can be used to perform this step.

Enumerate groups from the domain

Below are examples of using tools from Samba, winbind and existing linux installations for enumerating local and domain group accounts. These are helpful if you need to quickly test the domain membership server role.

  1. Using the net command `%> net ads groups`
  2. Using winbind `%> wbinfo -g`
  3. Using getent `%> getent group`

Enumerate users from the domain

Here we perform some of the same tests except here we can view existing Active Directory user accounts.

  1. Using the net command `%> net ads users`
  2. Using winbind `%> wbinfo -u`
  3. Using getent `%> getent passwd`

View trusted domains

Another good way to view extended domain membership information in terms of trusted authentication sources is the use of the following command. (example output provided).

%> wbinfo -m

Machine status as domain member server

Using the samba net tool we can view status information in terms of the machines details available as a member server within the active directory OU container.

%> net ads status
objectClass: top
objectClass: person
objectClass: organizationalPerson
objectClass: user
objectClass: computer
cn: valhalla
distinguishedName: CN=fs,CN=Computers,DC=example,DC=com
instanceType: 4
whenCreated: 20080522170259.0Z
whenChanged: 20080528145553.0Z
uSNCreated: 3833727
uSNChanged: 3921781
name: valhalla
objectGUID: 0fcc649c-017c-4cdc-b9df-d8c2f2bba965
userAccountControl: 69632
badPwdCount: 0
codePage: 0
countryCode: 0
badPasswordTime: 0
lastLogoff: 0
lastLogon: 128564610242815317
localPolicyFlags: 0
pwdLastSet: 0
primaryGroupID: 515
objectSid: S-1-5-21-2868754479-89028146-2101856903-111475
accountExpires: 9223372036854775807
logonCount: 282
sAMAccountName: fs$
sAMAccountType: 805306369
dNSHostName: fs.example.com
servicePrincipalName: HOST/fs.example.com
servicePrincipalName: HOST/FS
objectCategory: CN=Computer,CN=Schema,CN=Configuration,DC=example,DC=com
isCriticalSystemObject: FALSE
lastLogonTimestamp: 128559493793593750

Test KRB5 Authentication through Winbind

Once Samba has been installed, configured, joined to the domain and tested you should now test authentication of domain accounts. The wbinfo tool which accompanies the winbind package allows for testing from the local server.

%> wbinfo --krb5auth=username%password
plaintext kerberos password authentication for [username%password] succeeded (requesting cctype: FILE)
credentials were put in: FILE:/tmp/krb5cc_0

Test connection from Windows machine

Next you will want to ensure that valid accounts on the domain may authenticate from windows clients on your network. Here is an example that can be used from the MS-Dos prompt for testing.

%> net use x: \\fs\homes /user:USERNAME
The command completed successfully

Test connection from a linux machine

Next we should test connectivity from linux clients to ensure that they may also use Active Directory accounts to map network shares from our Samba server.

%> mount -t cifs -o username=USERNAME //fs.example.com/homes /mnt/samba

Debugging & Troubleshooting

log files to watch

Depending on the log level used when configuring the global section of the /etc/samba/smb.conf, viewing the contents of the various logs comes in handy when tracking down a problem with the installation, configuration or authentication of AD accounts.

  1. /var/log/samba/log.winbind
  2. /var/log/samba/log.winbind-idmap
  3. /var/log/samba/log.smb

Active Directory / Linux compatibilities

There are several known problems when dealing with Linux to Windows compatibilities. As of this writing the dated POSIX extensions necessary for linux compatible accounts (RFC2307; uid, gid, default shell & home directory) should no longer be an issue with the introduction of the Windows 2008 Server OS. However some

UID/GID Mapping verification if authentication is failing

Because you may run into problems with Windows domain user accounts failing the necessary UID/GID to SID mapping from Windows to Linux here are several methods of detecting the problem. Generally the problem illustrated here stems from creation of user accounts within Active Directory containing a 'space' character within the DN of the user account object.

Obtain the SID from Active Directory

First step that needs to take place is to obtain the users SID located within Active Directory.

%> wbinfo -n USERNAME
S-1-5-21-2868754479-89028146-2101856903-111473 User (1)

Example of failed GID/UID mapping using obtained SID

Once we have obtained the assigned account SID from Active Directory for the users account we can use that to obtain the UID/GID mapping by issuing the wbinfo tool the optional -S and/or -Y options as shown below in these failed examples.

%> wbinfo -i USERNAME
Could not get info for user USERNAME

%> wbinfo -S S-1-5-21-2868754479-89028146-2101856903-111473 User (1)
Could not convert sid S-1-5-21-2868754479-89028146-2101856903-111473 to uid

%> wbinfo -Y S-1-5-21-2868754479-89028146-2101856903-111473 User (1)
Could not convert sid S-1-5-21-2868754479-89028146-2101856903-111473 to gid

The two errors listed here can be verified by obtaining the relevant data from '/var/log/samba/log.winbindd'. Here is an example output indicating a problem with the DN of the account.

[2008/05/28 09:50:04, 10] nsswitch/winbindd_cache.c:cache_retrieve_response(2300)
  Retrieving response for pid 24973
[2008/05/28 09:50:04, 5] nsswitch/winbindd_async.c:winbindd_sid2uid_recv(347)
  sid2uid returned an error

Similar data can also be found in '/var/log/samba/log.winbindd-idmap'.

[2008/05/28 09:50:51, 10] nsswitch/winbindd_dual.c:child_process_request(479)
  process_request: request fn DUAL_SID2UID
[2008/05/28 09:50:51, 3] nsswitch/winbindd_async.c:winbindd_dual_sid2uid(374)
  [24634]: sid to uid S-1-5-21-2868754479-89028146-2101856903-111473
[2008/05/28 09:50:51, 10] nsswitch/idmap_util.c:idmap_sid_to_uid(105)
  idmap_sid_to_uid: sid = [S-1-5-21-2868754479-89028146-2101856903-111473]
[2008/05/28 09:50:51, 10] nsswitch/idmap_util.c:idmap_sid_to_uid(125)
  sid [S-1-5-21-2868754479-89028146-2101856903-111473] not mapped to an uid [2,1,2213796440]

To resolve UID/GID Mapping from Active Directory to the RFC2307 Schema for POSIX accounts

I had a hard time finding methods of resolving this problem so to detail a solution here are the requirements, and steps to take.

Required POSIX (RFC2307) object attributes

As mentioned in RFC2307 linux user accounts are POSIX compliant and Microsoft Windows pre- 2003 Active Directory installations did not contain the necessary schema attributes necessary for interoperability. Here is a simple list of required schema objects necessary for POSIX (RFC2307) compliance in MS Window Active Directory objects.

  1. cn (Common name or username)
  2. uidNumber (UID for POSIX Unix accounts)
  3. gidNumber (GID for POSIX Unix accounts)
  4. loginShell (Default login shell for domain users)
  5. msSFUHomeDirectory (Default Home directory for domain users)

This verification is not necessary is using Windows 2003 Server or later.

Automated testing and repair non POSIX compliant accounts

When this server was first setup the need to fix user accounts en masse' was necessary as individual testing, and repair of 1000's of user accounts was impractical. A simple perl script was written to detect (using the 'wbinfo' commands previously mentioned) to find and repair invalid DN's within any specified OU in Active Directory.

  • Please note that Enterprise Domain Authentication is required for this tool to function properly as modifications of the DN per user object are limited to these permissions.

=#### Wizard example usage with output ####=

This first example of usage with the tool is recommended as it will allow you to make modifications to one 'known' non POSIX compliant account at a time. This is great for testing accounts and tool functionality prior to running a fully automated test on any Active Directory OU.

NOTE: In the example shown below you will see the 'AcceptSecurityContext' error as a result of the importation of the ldif files for the non compliant RCF2307 accounts because in this example we are using a read-only access user type to test the application and show you examples. An enterprise domain administrator account is required for these modifications to work.

%> ./UID2SID.pl
Enter domain : EXAMPLE.COM
Enter username : username
Enter password : password
Enter login name of user : testaccount
Enter OU [Users]: 
Enter object [USER]: 
Searching for 'testaccount', please wait...
SEARCH RESULTS:
	Found: '1' record(s) matching 'testaccount' in 'EXAMPLE.COM'
	Found: '1' record(s) matching 'testaccount' that are not RFC2307 compliant
INVALID ACCOUNTS:
	CN=Test Account
PROCESSING:
	Importing: modify-zz-attribs-10.08.2009-testaccount.ldif
	Importing: modify-dn-10.08.2009-testaccount.ldif
NON-POSIX FIX RESULTS:
	ldap_bind: Invalid credentials (49)
		additional info: 80090308: LdapErr: DSID-0C090334, comment: AcceptSecurityContext error, data 525, vece
	ldap_bind: Invalid credentials (49)
		additional info: 80090308: LdapErr: DSID-0C090334, comment: AcceptSecurityContext error, data 525, vece

=#### Automated example usage with output ####=

The tool has the ability to run in automated mode where it searches a specified OU in Active Directory for all available user accounts which it then tests for the SID to UID/GID mapping (RFC2307 POSIX compatibility) and if found generates a new .ldiff file which is then used to delete and create the account with a new DN.

%> ./UID2SID.pl --domain=DOMAIN.COM --user=USERNAME --pass=PASSWORD --ou="CN=Users,DC=DOMAIN,DC=COM" --obj=user
Searching for 'user' in 'CN=Users,DC=example,DC=com, please wait...
        BIND DN: CN=domain-admin,CN=Users,DC=example,DC=com
        BASE DN: CN=Users,DC=example,DC=com
        Object Class: user
SEARCH RESULTS:
        Found: '44' 'user' records in 'CN=Users,DC=example,DC=com'
        Found: '6' 'user' records that are not RFC2307 compliant
INVALID ACCOUNTS:
        CN=Ron
        CN=mclame
        CN=Joni
        CN=Tonga
        CN=Caroljean
        CN=Matt
PROCESSING:
        modify-dn-06.23.2008-MIrsik.ldif
PROCESSING:
        modify-zz-attribs-06.23.2008-tongak.ldif
PROCESSING:
        modify-dn-06.23.2008-mclame.ldif
PROCESSING:
        modify-dn-06.23.2008-rhansen.ldif
PROCESSING:
        modify-dn-06.23.2008-tongak.ldif
PROCESSING:
        modify-dn-06.23.2008-jclayton.ldif
PROCESSING:
        modify-dn-06.23.2008-chanson.ldif
PROCESSING:
        modify-zz-attribs-06.23.2008-rhansen.ldif
PROCESSING:
        modify-zz-attribs-06.23.2008-jclayton.ldif
PROCESSING:
        modify-zz-attribs-06.23.2008-chanson.ldif
PROCESSING:
        modify-zz-attribs-06.23.2008-MIrsik.ldif
PROCESSING:
        modify-zz-attribs-06.23.2008-mclame.ldif

Testing for RFC2307 compatibility once tool is used.

This section is a duplicate of the UID/GID to SID mapping originally mentioned but this example shows a valid mapping due to the POSIX compliance of the DN from Windows to Linux.

%> wbinfo -i USERNAME
USERNAME:*:1000015:513:USERNAME:/Users/Authenticated Users/USERNAME:/bin/false

%> wbinfo -n USERNAME
S-1-5-21-2868754479-89028146-2101856903-88486 User (1)

%> wbinfo -S S-1-5-21-2868754479-89028146-2101856903-88486
1000015

The source code for the UID2SID tool

This tool was written in perl and requires the wbinfo and ldapsearch tools.

#!/usr/bin/perl

#
# Simple POSIX account fix for non-RFC2307 compliant user
# accounts in active directory or openldap directories
#
# jason.gerfen@gmail.com
#
# last revision: 08.26.2008
#

# grab our modules
use Getopt::Long;
use POSIX qw( strftime );
use Data::Dumper;

# temporary file storage directory
my $dir = ".UID2SID";
my $PATH = "/usr/bin";

# some defaults if schema attributes are missing
$uid = 100001;
$gid = 513;
$homedir = "/home/Authenticated Users";
$shell = "/bin/false";

# some globals
my ( $domain,
     $user,
     $pass,
     $ou,
     $container,
     $obj,
     $date );

# menu system data
GetOptions( "domain=s" => \$domain,
            "user=s" => \$user,
            "pass=s" => \$pass,
            "ou=s" => \$ou,
            "obj=s" => \$obj,
            "verbose" => \$verbose,
            "help" => \$help);

# initialize script sub-routines
$date = &GetDate;
if( ( defined( $domain ) ) && ( defined( $user ) ) && ( defined( $pass ) ) && ( defined( $ou ) ) && ( defined( $obj ) ) ) {
    &MainSub( $domain, $user, $pass, $ou, $obj, $date );
} elsif( defined( $help ) ) {
    &ShowSyntax;
} else {
    &WizardWiz;
}

# get date
sub GetDate
{
    return strftime( '%m.%d.%Y', localtime() );
}

# handle directory and temp files
sub CreateDir
{
    if( -d $dir ) { return; }
    my $dirc = "mkdir $dir";
    `$dirc`;
    return;
}

# Initialize command
sub GetLDAPQuery( $domain, $user, $pass, $ou, $obj, $date )
{
    print "Searching for '$obj' in '$ou', please wait...\n";
    my $cmd = "$PATH/ldapsearch -v -x -h $domain -D \"$user\" -w $pass -b \"$ou\" -s sub \"objectclass=$obj\"";
    print "\tBIND DN: CN=$user,$ou\n";
    print "\tBASE DN: $ou\n";
    print "\tObject Class: $obj\n";
    print "SEARCH RESULTS:\n";
    my @results = `$cmd >> $dir/ldap-lookup-$date.log`;
    if( defined( $verbose ) ) {
	print "CMD: " . $cmd . "\n";
    }
    return @results;
}

# Initialize command
sub GetLDAPQueryEasy( $domain, $user, $pass, $nameOne, $date )
{
    #break up domain
    my @d = split(/\./, $domain);
    my $ou = '';
    for( my $i = 0; $i <= $#d; $i++ ) {
	$ou .= "DC=" . $d[$i] . ",";
    }
    $ou = substr($ou,0,-1);
    print "Searching for '$nameOne', please wait...\n";
    my $cmd = "$PATH/ldapsearch -x -h $domain -D \"$user\" -w $pass -b \"$ou\" \"(sAMAccountName=$nameOne)\"";
    print "SEARCH RESULTS:\n";
    my @results = `$cmd >> $dir/ldap-lookup-$date.log`;
    if( defined( $verbose ) ) {
	print "CMD: " . $cmd . "\n";
    }
    return @results;
}

# Same search but limit to user
sub GetLDAPQueryAttribs( $domain, $uname, $pass, $ou, $obj, $date, $tmpName )
{
    $domain = shift; $uname = shift; $pass = shift; $ou = shift; $obj = shift; $date = shift; $tmpName = shift;
    my $cmd = "$PATH/ldapsearch -x -h $domain -D \"$uname\" -w $pass -b \"$ou\" \"(givenName=$tmpName)\" dn cn msSFUName msSFUHomeDirectory unixHomeDirectory uidNumber gidNumber loginShell sAMAccountName";
    my @results = `$cmd >> $dir/ldap-modify-$date-$tmpName.log`;
    if( defined( $verbose ) ) {
	print $cmd . "\n";
    }
    return @results;
}

# Same search but limit to user through wizard
sub GetLDAPQueryAttribsEasy( $domain, $uname, $pass, $nameOne, $ou, $obj, $date, $tmpName )
{
    $domain = shift; $uname = shift; $pass = shift; $nameOne = shift; $ou = shift; $obj = shift; $date = shift; $tmpName = shift;
    my $cmd = "$PATH/ldapsearch -x -h $domain -D \"$uname\" -w $pass -b \"$ou\" \"(sAMAccountName=$nameOne)\" dn cn msSFUName msSFUHomeDirectory unixHomeDirectory uidNumber gidNumber loginShell sAMAccountName";
    my @results = `$cmd >> $dir/ldap-modify-$date-$tmpName.log`;
    if( defined( $verbose ) ) {
	print $cmd . "\n";
    }
    return @results;
}

# Fix for CN, DN & distinguishedName attribs
sub GetLDAPQueryCNDNAttribs( $domain, $uname, $pass, $ou, $obj, $date, $tmpName )
{
    $domain = shift; $uname = shift; $pass = shift; $ou = shift; $obj = shift; $date = shift; $tmpName = shift; my $a = '';
    if( $tmpName =~ /^(\w+)\s(\w+)$/i ) { $a = $1 . $2; }
    my $cmd = "$PATH/ldapsearch -x -h $domain -D \"$uname\" -w $pass -b \"$ou\" \"(cn=$tmpName)\" dn cn distinguishedName sAMAccountName >> $dir/ldap-modify-$date-" . $a . ".log";
    my @results = `$cmd`;
    if( defined( $verbose ) ) {
	print "CMD: " . $cmd . "\n";
    }
    return @results;
}

# Fix for CN, DN & distinguishedName attribs
sub GetLDAPQueryCNDNAttribsEasy( $domain, $uname, $pass, $nameOne, $ou, $obj, $date, $tmpName )
{
    $domain = shift; $uname = shift; $pass = shift; $nameOne = shift; $ou = shift; $obj = shift; $date = shift; $tmpName = shift; my $a = '';
    if( $tmpName =~ /^(\w+)\s(\w+)$/i ) { $a = $1 . $2; }
    my $cmd = "$PATH/ldapsearch -x -h $domain -D \"$uname\" -w $pass -b \"$ou\" \"(sAMAccountName=$nameOne)\" dn cn distinguishedName sAMAccountName >> $dir/ldap-modify-$date-" . $a . ".log";
    my @results = `$cmd`;
    if( defined( $verbose ) ) {
	print "CMD: " . $cmd . "\n";
    }
    return @results;
}

# Same search but limit to user
sub SetLDAPAttribs( $domain, $uname, $ou, $container,  $pass, $date, $file )
{
    # ldapmodify -x -D "CN=Administrator,CN=Users,DC=SCL,DC=UTAH,DC=EDU" -w "pynn4cl3of3volution" -h scl.utah.edu -p 389 -f
    my $domain = shift; my $uname = shift; my $ou = shift; my $container = shift; my $pass = shift; my $date = shift; my $file = shift;
    #fix domain usernames
    my @u = split(/\w+\\(\w+)/, $uname);
    my $nuser = $u[1];
    #break up domain
    my @d = split(/\./, $domain);
    my $ou1 = '';
    for( my $i = 0; $i <= $#d; $i++ ) {
	$ou1 .= "DC=" . $d[$i] . ",";
    }
    $ou1 = substr($ou1,0,-1);
    if( $container eq "Users" ) { $container = "CN=".$container; } else { $container = "OU=".$container; }
    my $cmd = "$PATH/ldapmodify -x -h $domain -D \"CN=$nuser,$container,$ou1\" -w $pass -f $dir/$file";
    if( defined( $verbose ) ) {
	print "CMD: " . $cmd . "\n";
    }
    `$cmd 2>> $dir/ldif-results-$date.log`;
}

# begin processing our ldif files
sub ProcessLDIF( $domain, $uname, $pass, $date )
{
    my $domain = shift; my $uname = shift; my $pass = shift; my $date = shift; my $file = '';
    opendir( DIR, $dir ) || die "ERROR: Could not open $dir for reading\n";
    while( $file = readdir( DIR ) ) {
	next if( -d $file );
	if( $file =~ /\w+\.ldif$/i ) {
	    print "\tImporting: $file\n";
	    &SetLDAPAttribs( $domain, $uname, $ou, $container, $pass, $date, $file );
	}
    }
    closedir( DIR );
    return;
}

# parse our schema attributes
sub ParseResultsLDAPAttribs( $username )
{
    my $username = shift;
    if( $username =~ /^(\w+)\s(\w+)$/i ) { $username = $1 . $2; }
    # open our temp file
    open( RES, "$dir/ldap-modify-$date-$username.log" ) || die "ERROR: File could not be opened - $dir/ldap-modify-$date-$username.log\n";
    flock( RES, 2 );
    # initialize a new hash for results
    my @res = ();
    # begin looping over results
    my( @lines ) = <RES>;
    foreach my $line ( @lines ) {
	chomp( $line );
	my @userDataDetails = ();
	# get our schema attributes into an array 
	if( $line =~ /^(dn)\:\s(.*)$/i ) { push( @userDataDetails, $1 . "=" . $2 ); }
	if( $line =~ /^(cn)\:\s(.*)$/i ) { push( @userDataDetails, $1 . "=" . $2 ); }
	if( $line =~ /^(msSFUName)\:\s(.*)$/i ) { push( @userDataDetails, $1 . "=" . $2 ); }
	if( $line =~ /^(unixHomeDirectory)\:\s(.*)$/i ) { push( @userDataDetails, $1 . "=" . $2 ); }
	if( $line =~ /^(msSFUHomeDirectory)\:\s(.*)$/i ) { push( @userDataDetails, $1 . "=" . $2 ); }
	if( $line =~ /^(uidNumber)\:\s(.*)$/i ) { push( @userDataDetails, $1 . "=" . $2 ); }
	if( $line =~ /^(gidNumber)\:\s(.*)$/i ) { push( @userDataDetails, $1 . "=" . $2 ); }
	if( $line =~ /^(loginShell)\:\s(.*)$/i ) { push( @userDataDetails, $1 . "=" . $2 ); }
	if( $line =~ /^(sAMAccountName)\:\s(.*)$/i ) { push( @userDataDetails, $1 . "=" . $2 ); }
	push( @res, @userDataDetails );
    }

    # clean it up
    close( RES );
    flock( RES, 8 );
    unlink( "$dir/ldap-modify-$date-$username.log" );

    return \@res;
}

# parse our schema attributes version 2
sub ParseResultsLDAPAttribsTwo( $username )
{
    my $username = shift;
    if( $username =~ /^(\w+)\s(\w+)$/i ) { $username = $1 . $2; }
    # open our temp file
    open( RES, "$dir/ldap-fixdn-$date-$username.log" ) || die "ERROR: File could not be opened - $dir/ldap-modify-$date-$username.log\n";
    flock( RES, 2 );
    # initialize a new hash for results
    my @res = ();
    # begin looping over results
    my( @lines ) = <RES>;
    foreach my $line ( @lines ) {
	chomp( $line );
	my @userDataDetails = ();
	# get our schema attributes into an array 
	if( $line =~ /^(dn)\:\s(.*)$/i ) { push( @userDataDetails, $1 . "=" . $2 ); }
	if( $line =~ /^(cn)\:\s(.*)$/i ) { push( @userDataDetails, $1 . "=" . $2 ); }
	if( $line =~ /^(distinguishedName)\:\s(.*)$/i ) { push( @userDataDetails, $1 . "=" . $2 ); }
	if( $line =~ /^(sAMAccountName)\:\s(.*)$/i ) { push( @userDataDetails, $1 . "=" . $2 ); }
	push( @res, @userDataDetails );
    }

    # clean it up
    close( RES );
    flock( RES, 8 );
    unlink( "$dir/ldap-fixdn-$date-$username.log" );

    return \@res;
}

# create an ldif file from ldap results on schema attributes
sub CreateLDIFOne 
{
    @array = shift; my $string = ''; my $name = ''; my $tmpName = '';
    for my $x ( 0 .. $#array ) {
	for my $y ( 0 .. $#{ $array[$x] } ) {
	    # fix for username shit
	    if( $array[$x][$y] =~ /sAMAccountName=(.*)/i ) {
		$name = $1;
	    }
	}
    }

    for my $x ( 0 .. $#array ) {
	for my $y ( 0 .. $#{ $array[$x] } ) {
	    if( $array[$x][$y] ne '' ) {
		if( $array[$x][$y] =~ /dn=CN=(.*)(,CN=.*)/i ) {
		    $string .= "dn: CN=$1$2\n"; my $tmpName = $1;
		    $string .= "changetype: modify\n";
		}
#		if( $array[$x][$y] =~ /cn=(.*)/i ) {
#		    $string .= "modify: cn\n";
#		    $string .= "cn: $name\n";
#		}
		if( $array[$x][$y] =~ /msSFUName=(.*)/i ) {
		    $string .= "modify: msSFUName\n";
		    $string .= "msSFUName: $name\n";
		}
		if( $array[$x][$y] =~ /unixHomeDirectory=(.*)\/($tmpName)/i ) {
		    $string .= "modify: unixHomeDirectory\n";
		    $string .= "unixHomeDirectory: $1/$name\n";
		}
		if( $array[$x][$y] =~ /msSFUHomeDirectory=(.*)\/($tmpName)/i ) {
		    $string .= "modify: msSFUHomeDirectory\n";
		    $string .= "msSFUHomeDirectory: $1/$name\n";
		}
		if( $array[$x][$y] =~ /uidNumber=(.*)/i ) {
			$string .= "modify: uidNumber\n";
			$string .= "uidNumber: $1\n";
		}
		if( $array[$x][$y] =~ /gidNumber=(.*)/i ) {
		    $string .= "modify: gidNumber\n";
		    $string .= "gidNumber: $1\n";
		}
		if( $array[$x][$y] =~ /loginShell=(.*)/i ) {
			$string .= "modify: loginShell\n";
			$string .= "loginShell: $1\n";
		}
	    }
	}
    }


    # one final check on string
    $string = &CheckAttribs( $string, $name );
    
    # make sure its not empty before creating ldif file
    if( ( $string ne "" ) && ( $name ne "" ) ) {
	open( RES, ">$dir/modify-zz-attribs-$date-$name.ldif" ) || die "ERROR: File could not be opened - $dir/modify-zz-attribs-$date-$name.ldif\n";
	flock( RES, 2 );
	print RES $string;
	close( RES );
	flock( RES, 8 );
    }
} 

# create an ldif file from ldap results on schema attributes
sub CreateLDIFTwo
{
    @array = shift; my $string = ''; my $name = ''; my $tmpName = '';
    for my $x ( 0 .. $#array ) {
	for my $y ( 0 .. $#{ $array[$x] } ) {
	    # fix for username shit
	    if( $array[$x][$y] =~ /sAMAccountName=(.*)/i ) {
		$name = $1;
	    }
	}
    }
    # ensure we have something to fix in AD
    if( ( defined( $name ) ) && ( $name ne "" ) ) {
	for my $x ( 0 .. $#array ) {
	    for my $y ( 0 .. $#{ $array[$x] } ) {
		if( $array[$x][$y] ne '' ) {
		    if( $array[$x][$y] =~ /dn=CN=(.*)(,CN=.*)/i ) {
			$string .= "dn: CN=$1$2\n"; my $tmpName = $1; my $dn = $string;
			$string .= "changetype: modrdn\n";
			$string .= "newrdn: CN=$name\n";
			$string .= "deleteoldrdn: 1\n";
		    }
		}
	    }
	}
    }

    # make sure its not empty before creating ldif file
    if( ( $string ne "" ) && ( $name ne "" ) ) {
	open( RES, ">$dir/modify-dn-$date-$name.ldif" ) || die "ERROR: File could not be opened - $dir/modify-dn-$date-$name.ldif\n";
	flock( RES, 2 );
	print RES $string;
	close( RES );
	flock( RES, 8 );
    }
} 

# apply defaults if some attributes are missing
sub CheckAttribs( $string, $name )
{
    $string = shift; $name = shift;
    if( $string !~ /msSFUName:/ ) { $string .= "modify: msSFUName\nmsSFUName: $name\n"; }
    if( $string !~ /unixHomeDirectory:/ ) { $string .= "modify: unixHomeDirectory\nunixHomeDirectory: $homedir/$name\n"; }
    if( $string !~ /msSFUHomeDirectory:/ ) { $string .= "modify: msSFUHomeDirectory\nmsSFUHomeDirectory: $homedir/$name\n"; }
    if( $string !~ /uidNumber:/ ) { $string .= "modify: uidNumber\nuidNumber: " . $uid++ . "\n"; }
    if( $string !~ /gidNumber:/ ) { $string .= "modify: gidNumber\ngidNumber: " . $gid . "\n"; }
    if( $string !~ /loginShell:/ ) { $string .= "modify: loginShell\nloginShell: $shell\n"; }
    return $string;
}

# parse our results from ldap
sub ParseResultsLDAP
{
    # open our temp file
    open( RES, "$dir/ldap-lookup-$date.log" ) || die "ERROR: File could not be opened - $dir/ldap-lookup-$date.log\n";
    flock( RES, 2 );
    # initialize a new hash for results
    my $iznt = 0; my @schemaAttribs = ''; my %userDataDetails = (); my @data = '';
    # begin looping over results
    my( @lines ) = <RES>;
    foreach my $line ( @lines ) {
	chomp( $line );
	# get our users into an array
	if( $line =~ /^(cn)\:\s(.*)$/i ) {
	    push( @data, $2 );
	}
    }
    # clean it up
    close( RES );
    flock( RES, 8 );
    unlink( "$dir/ldap-lookup-$date.log" );

    return @data;
}

# parse our winbind results and grab the invalids
sub ParseResultsWBINFO
{
    # open our temp file
    open( RES, "$dir/wbinfo-lookup-$date.log" ) || die "ERROR: File could not be opened - $dir/wbinfo-lookup-$date.log\n";
    flock( RES, 2 );
    # initialize a new hash for results
    my @userData = '';
    # begin looping over results
    while( my $line = <RES> ) {
	# look for our common name attribute
	if( $line =~ /Could\snot\sget\sinfo\sfor\suser\s(.*)/i ) { push( @userData, $1 ); }
	if( defined( $verbose ) ) {
	    print "\tERROR: " . $line . "\n";
	}
    }
    # clean it up
    close( RES );
    flock( RES, 8 );
    unlink( "$dir/wbinfo-lookup-$date.log" );

    return @userData;
}

# attempt lookup of users using winbind
sub GetWBInfo( $user, $date )
{
    $user = shift;
    # grab ident of user data
    my $cmd = "wbinfo -i $user 2>> $dir/wbinfo-lookup-$date.log";
    my @results = `$cmd`;
    if( defined( $verbose ) ) {
	print "CMD: " . $cmd . "\n";
    }
    return @results;
}

# remove duplicate array values
sub RemDups
{
    my %hash = map { $_ => 1 } @_;
    my @unique = keys %hash;
    return @unique;
}

# main application
sub MainSub( $domain, $user, $pass, $ou, $obj, $date )
{
    # define our vars
    my ( @wbInfo,
         @userAttrib,
	 @invWBInfo,
	 @cnFix,
         @cnFixRes ) = '';

    my $uname = $user;

    # create our directory data
    &CreateDir;

    # perform our ldap query
    &GetLDAPQuery( \$domain, \$user, \$pass, \$ou, \$obj, \$date );

    # parse the results
    @userAttrib = &ParseResultsLDAP;

    # ensure no duplicates are in results
    @userAttrib = &RemDups( @userAttrib );

    # ensure we found something
    if( $#userAttrib == 0 ) {
	print "\tERROR: Could not find any records... exiting\n";
	exit;
    }

    # give a count to our user
    print "\tFound: '$#userAttrib' '$obj' records in '$ou'\n";

    # Now get our invalid accounts
    for( my $i = 0; $i <= $#userAttrib; $i++ ) {
	if( $userAttrib[$i] ne '' ) {
	    push( @wbInfo, &GetWBInfo( $userAttrib[$i], $date ) );
	}
    }

    # Also provide fix for invalid CN, DN DistinguishedName attributes
    for( my $j = 0; $j <= $#userAttrib; $j++ ) {
	if( $userAttrib[$j] ne '' ) {
	    if( $userAttrib[$j] =~ /(\w+\s\w+)$/i ) {
		$tmpName = $1;
		push( @cnFix, $tmpName );
		&GetLDAPQueryCNDNAttribs( $domain, $uname, $pass, $ou, $obj, $date, $tmpName );
	    }
	}
    }

    # We should have any invalid entries here
    @invWBInfo = &ParseResultsWBINFO;

    # print count of invalid records
    my $a = $#invWBInfo + $#cnFix;
    if( $a >= 1 ) {
	print "\tFound: '$a' '$obj' records that are not RFC2307 compliant\n";

	# loop over results and attempt to set the required attribs
	print "INVALID ACCOUNTS:\n";
	my $tmpName = ''; my @results = ''; my @userDetails = ''; my %resultHash = ();
	for( my $n = 0; $n <= $#invWBInfo; $n++ ) {
	    if( ( defined( $invWBInfo[$n] ) ) && ( $invWBInfo[$n] ne '' ) ) {
		$tmpName = $invWBInfo[$n];
		print "\tCN=$tmpName\n";
		&GetLDAPQueryAttribs( $domain, $uname, $pass, $ou, $obj, $date, $tmpName );
		push( @userDetails, &ParseResultsLDAPAttribs( $tmpName ) );
	    }
	}
	
	# loop over results with strange cn, dn attribs
	for( my $m = 0; $m <= $#cnFix; $m++ ) {
	    if( ( defined( $cnFix[$m] ) ) && ( $cnFix[$m] ne '' ) ) {
		print "\tCN=$cnFix[$m]\n";
		$tmpName = $cnFix[$m];
		if( $tmpName =~ /(\w+)\s(\w+)$/i ) {
		    $tmpName = $1 . $2;
		}
		push( @userDetails, &ParseResultsLDAPAttribs( $tmpName ) );
	    }
	}

	# clean it up a tad
	sort( @userDetails );

	# proceed to create an ldif from data
	for( my $x = 0; $x <= $#userDetails; $x++ ) {
	    &CreateLDIFOne( $userDetails[$x] );
	    &CreateLDIFTwo( $userDetails[$x] );
	}
	
	# Lets finish it up
	print "PROCESSING:\n";
	&ProcessLDIF( $domain, $uname, $pass, $date );
	
	# display log
	if( defined( $verbose ) ) {
	    print "NON-POSIX FIX RESULTS:\n";
	    open( RES, "$dir/ldif-results-$date.log" ) || die "ERROR: File could not be opened - $dir/ldif-results-$date.log\n";
	    flock( RES, 2 );
	    my( @lines ) = <RES>;
	    foreach my $line ( @lines ) {
		chomp( $line );
		print "\t$line\n";
	    }
	    close( RES );
	    flock( RES, 8 );
	}
    } else {
	print "\tFound: '0' '$obj' record(s) that are not RFC2307 compliant\n";
    }
    unlink( "$dir/ldif-results-$date.log" );
    #`rm $dir/*`;
}

# main application
sub MainSubEasy( $domain, $user, $pass, $nameOne, $container, $obj, $date )
{
    # define our vars
    my ( @wbInfo,
         @userAttrib,
	 @invWBInfo,
	 @cnFix,
         @cnFixRes ) = '';

    my $uname = $user;

    #break up domain
    my @d = split(/\./, $domain);
    my $ou = '';
    for( my $i = 0; $i <= $#d; $i++ ) {
	$ou .= "DC=" . $d[$i] . ",";
    }
    $ou = substr($ou,0,-1);

    # create our directory data
    &CreateDir;

    # perform our ldap query
    &GetLDAPQueryEasy( \$domain, \$user, \$pass, \$nameOne, \$date );

    # parse the results
    @userAttrib = &ParseResultsLDAP;

    # ensure no duplicates are in results
    @userAttrib = &RemDups( @userAttrib );

    # ensure we found something
    if( $#userAttrib == 0 ) {
	print "\tERROR: Could not find any records... exiting\n";
	exit;
    }

    # give a count to our user
    print "\tFound: '$#userAttrib' record(s) matching '$nameOne' in '$domain'\n";

    # Now get our invalid accounts
    for( my $i = 0; $i <= $#userAttrib; $i++ ) {
	if( $userAttrib[$i] ne '' ) {
	    push( @wbInfo, &GetWBInfo( $userAttrib[$i], $date ) );
	}
    }

    # Also provide fix for invalid CN, DN DistinguishedName attributes
    for( my $j = 0; $j <= $#userAttrib; $j++ ) {
	if( $userAttrib[$j] ne '' ) {
	    if( $userAttrib[$j] =~ /(\w+\s\w+)$/i ) {
		$tmpName = $1;
		push( @cnFix, $tmpName );
		&GetLDAPQueryCNDNAttribsEasy( $domain, $uname, $pass, $nameOne, $ou, $obj, $date, $tmpName );
	    }
	}
    }

    # We should have any invalid entries here
    @invWBInfo = &ParseResultsWBINFO;

    # print count of invalid records
    my $a = $#invWBInfo + $#cnFix;
    if( $a >= 1 ) {
	print "\tFound: '$a' '$obj' records that are not RFC2307 compliant\n";

	# loop over results and attempt to set the required attribs
	print "INVALID ACCOUNTS:\n";
	my $tmpName = ''; my @results = ''; my @userDetails = ''; my %resultHash = ();
	for( my $n = 0; $n <= $#invWBInfo; $n++ ) {
	    if( ( defined( $invWBInfo[$n] ) ) && ( $invWBInfo[$n] ne '' ) ) {
		$tmpName = $invWBInfo[$n];
		print "\tCN=$tmpName\n";
		&GetLDAPQueryAttribsEasy( $domain, $uname, $pass, $nameOne, $ou, $obj, $date, $tmpName );
		push( @userDetails, &ParseResultsLDAPAttribs( $tmpName ) );
	    }
	}
	
	# loop over results with strange cn, dn attribs
	for( my $m = 0; $m <= $#cnFix; $m++ ) {
	    if( ( defined( $cnFix[$m] ) ) && ( $cnFix[$m] ne '' ) ) {
		print "\tCN=$cnFix[$m]\n";
		$tmpName = $cnFix[$m];
		if( $tmpName =~ /(\w+)\s(\w+)$/i ) {
		    $tmpName = $1 . $2;
		}
		push( @userDetails, &ParseResultsLDAPAttribs( $tmpName ) );
	    }
	}
	
	# clean it up a tad
	sort( @userDetails );

	# proceed to create an ldif from data
	for( my $x = 0; $x <= $#userDetails; $x++ ) {
	    &CreateLDIFOne( $userDetails[$x] );
	    &CreateLDIFTwo( $userDetails[$x] );
	}
	
	# Lets finish it up
	print "PROCESSING:\n";
	&ProcessLDIF( $domain, $uname, $pass, $date );
	
	# display log
	print "NON-POSIX FIX RESULTS:\n";
	open( RES, "$dir/ldif-results-$date.log" ) || die "ERROR: File could not be opened - $dir/ldif-results-$date.log\n";
	flock( RES, 2 );
	my( @lines ) = <RES>;
	foreach my $line ( @lines ) {
	    chomp( $line );
	    print "\t$line\n";
	}
	close( RES );
	flock( RES, 8 );
    } else {
	print "\tFound: '0' '$obj' record(s) that are not RFC2307 compliant\n";
    }
    unlink( "$dir/ldif-results-$date.log" );
    #`rm $dir/*`;
}

# Our simple prompter
sub PromptUser {
    my($prompt, $default) = @_;
    my $defaultValue = $default ? "[$default]" : "";
    print "$prompt $defaultValue: ";
    chomp(my $input = <STDIN>);
    return $input ? $input : $default;
}

# Wizard wiz sub routine
sub WizardWiz
{
    $domain = &PromptUser("Enter domain");
    $user = &PromptUser("Enter username");
    $pass = &PromptUser("Enter password");
    $nameOne = &PromptUser("Enter login name of user");
    $container = &PromptUser("Enter OU", "Users");
    $obj = &PromptUser("Enter object", "USER");
    &MainSubEasy( $domain, $user, $pass, $nameOne, $container, $obj, $date );
}

# menu system
sub ShowSyntax
{
    print <<EOF;

Winbind, Samba & Active Directory UID2SID mapping utility
------------------------------------------------------------
Queries Active directory for list of users and begins mapping of
the UID, GID & SID information to ensure Active Directory 
Authentication is working.

Usage: ./UID2SID.pl --domain=[DOMAIN] 
                    --user=[USERNAME] 
                    --pass=[PASSWORD] 
                    --ou=[DC=DOMAIN,DC=COM] 
                    --obj=[USER|COMPUTER|GROUP]
                    --verbose
                    --help
EOF
exit;
}

NT_STATUS_NO_SUCH_USER errors

Here is a simple method of searching Active directory using the ldapsearch utility.

%> ldapsearch -x -h DOMAIN -D USERNAME -w PASSWORD -b "cn=users,dc=EXAMPLE,dc=COM" "objectclass=user" | grep USERNAME

And the resulting output if an account exists

dn: CN=USERNAME LASTNAME,CN=Users,DC=EXAMPLE,DC=COM
cn: USERNAME LASTNAME
givenName: USERNAME
distinguishedName: CN=USERNAME LASTNAME,CN=Users,DC=DOMAIN,DC=COM
displayName: USERNAME LASTNAME
name: USERNAME LASTNAME
unixHomeDirectory: /Users/Authenticated Users/USERNAME LASTNAME
[global]
workgroup = EXAMPLE
realm = EXAMPLE.COM
server string = example.com
netbios name = example
password server = *
encrypt passwords = yes
security = ADS
lanman auth = no
ntlm auth = no
kerberos method = system keytab
os level = 101
allow trusted domains = yes
auth methods = winbind
interfaces = eth0, lo
bind interfaces only = yes
socket options = TCP_NODELAY
hosts allow = 192.168.10.0/24, 127.0.0.1
hosts deny = 0.0.0.0/0
log level = 4
log file = /var/log/samba/log.%m
max log size = 1024
client signing = yes
client schannel = no
client use spnego = yes
client lanman auth = no
client NTLMv2 auth = yes
client plaintext auth = no
preferred master = no
local master = no
domain master = no
wins proxy = no
dns proxy = No
obey pam restrictions = yes
template shell = /bin/bash
nt acl support = yes
inherit permissions = yes
create mask = 0022
vfs objects = acl_xattr
map acl inherit = Yes
store dos attributes = Yes
winbind separator = +
winbind enum users = yes
winbind enum groups = yes
winbind nested groups = yes
winbind use default domain = yes
winbind offline logon = true
winbind nss info = rfc2307
winbind normalize names = yes
idmap config * : backend = tdb
idmap config * : range = 500-5000000000
idmap config * : default = yes
idmap config * : schema_mode = rfc2307
[example]
comment = example
browsable = yes
writeable = yes
create mask = 0022
force create mode = 0022
directory mask = 0022
force directory mode = 0022
inherit permissions = yes
valid users = @EXAMPLE+GroupName
path = /path/to/test/
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment