Configure a Centos 7 Samba Server to Use a Secure LDAP Authentication


I'm in the midst of re-implementing our network. Phase 1 entailed standing up a new OpenLDAP Server. Phase 2 involves setting up a new Samba server that can take user and groups from LDAP and use them to assign share permissions.

This guide will show how to take a Centos 7 Samba installation and configure it to talk securely to an LDAP server for authentication.

I will also cover how to get SMB3 transport encryption setup and working.

I'm in the midst of re-implementing our network. Phase 1 entailed standing up a new OpenLDAP Server. Phase 2 involves setting up a new Samba server that can take user and groups from LDAP and use them to assign share permissions.

This guide will show how to take a Centos 7 Samba installation and configure it to talk securely to an LDAP server for authentication.

I will also cover how to get SMB3 transport encryption setup and working.

References

Install Samba packages

yum install samba samba-client samba-common cifs-utils

 

Configure firewalld to allow samba traffic through

firewall-cmd --permanent --add-service=samba
firewall-cmd --reload

 

Configure SELinux to allow Samba to create shares anywhere

By default SELinux only allows shares out of the /home directory, but I don't want to do that. Enabling these SEBools will allow Samba the ability to create shares from any mounted directory:

setsebool -P samba_export_all_ro=1
setsebool -P samba_export_all_rw=1

 

Setup your smb.conf file

Now for the fun part: configure your /etc/samba/smb.conf file so it has all the necessary settings to allow for secure authentication over LDAP --and-- enables SMB3 wire level encryption. This sample configuration may be a bit terse, but it gets the point across. The options will be explained below in more detail:

[global]
        workgroup = WORKGROUP
        server string = "suitably pithy server string"
        log file = /var/log/samba/log.%m
# For debugging enable the log level of 5
#      log level = 5
        max log size = 50
        idmap config * : backend = tdb

## LDAP Settings
        ldap suffix = dc=domain,dc=tld
        ldap admin dn = cn=Manager,dc=domain,dc=tld
#      ldap ssl = no

        passdb backend = ldapsam:ldaps://dit.domain.tld

# For security
        server signing = mandatory
        smb encrypt = mandatory
        client min protocol = smb3
        client max protocol = smb3

[backup_share]
        path = /backup_path/backups_place
        valid users = @backup_group
        read only = No
        writeable = yes
        browseable = yes
        force group = backup_group
        create mask = 0770
        public = No

 

Options explanation

LDAP Options:

  • idmap config * : backend = tdb   # This was included in a guide and seems to work, so I used it
      
  • ldap suffix = dc=domain,dc=tld  # This is the place in the LDAP tree to look for users (recursively)
      
  • ldap admin dn = cn=Manager,dc=domain,dc=tld  # Required so Samba can connect to LDAP
      
  • passdb backend = ldapsam:ldaps://dit.domain.tld  # Points samba to the correct LDAP server
      

Samba Security Options:

  • server signing = mandatory  # Ensures that SMB2 signing is enabled
  • smb encrypt = mandatory    # Ensures that SMB3 encryption is forced on all connections
  • client min protocol = smb3   # I read that this helps clients negotiate up to SMB3
  • client max protocol = smb3  # An extrapolation of mine: Can I force a minimum protocol?
      

Share Options:

  • valid users = @backup_group  # Configure the list of valid users to members of the 'backup_group'
  • force group = backup_group   # When files/folders are created, force the group to this LDAP group
  • create mask = 0770  # When files are created, allow user/group full access and deny everyone else

Give Samba the LDAP Directory Admin Password

I mean, what could go wrong, right? :P

smbpasswd -w 'password_here_for_admin_root_user' Manager
(This sets the password for the root/base/admin user. In this case the user is named 'Manager')

 

Check the Config File

We want to make sure samba is configured correctly, so run this command to validate the settings: 

testparm
(As long as no errors or warnings come up, you should be good!)

 

Enable and Start Samba 4

So, we should be good to go! Here are the commands to enable and start the samba service:

systemctl enable smb

systemctl start smb

 

Users and Groups

Be sure to use a tool like LDAP Admin to configure your groups and users before setting up your shares (assuming you want to use LDAP to manage users and groups, that is). While you can use command line ldap utilities, they are a huge pain and not really worth the bother once you have your OpenLDAP and Samba servers setup!

 

Add the Samba LDAP Schema

While I did cover this over in the LDAP Configuration Guide, it's worth mentioning again here. In order for Samba to play nice with OpenLDAP you need to install the Samba schema on the OpenLDAP Server. Now this is where it gets fun: The OpenLDAP Server does not ship with the samba schema. You have to copy the samba schema (in .ldif form) to the LDAP Server and apply it manually:

  • File to copy from the samba server: /usr/share/doc/samba-4.2.3/LDAP/samba.ldif
  • Location on LDAP Server to copy the file to: /etc/openldap/schemas/samba.ldif
  • Load the schema like this (on the LDAP Server!):

    ldapadd -Y EXTERNAL -H ldapi:/// -f /etc/openldap/schema/samba.ldif

At this point we have all the LDAP Schemas we need to make things work (yay!)

Troubleshooting

So, things didn't quite pan out the way you expected? Yeah, same thing happened to me. I encountered a couple odd problems that I'll describe here in the hope that my solutions could work for you, though YMMV. These errors were causing my samba server to be unsuccessful when attempting to contact the LDAP server, so ldap users were unable to login

 

Error set 1: /var/log/secure

Jan 17 21:31:27 t320 sshd[557]: Invalid user test from 192.168.3.45
Jan 17 21:31:27 t320 sshd[557]: input_userauth_request: invalid user test [preauth]
Jan 17 21:31:30 t320 sshd[557]: pam_unix(sshd:auth): check pass; user unknown
Jan 17 21:31:30 t320 sshd[557]: pam_unix(sshd:auth): authentication failure; logname= uid=0 euid=0 tty=ssh ruser= rhost=192.168.3.45
Jan 17 21:31:33 t320 sshd[557]: Failed password for invalid user test from 192.168.3.45 port 7310 ssh2
Jan 17 21:31:59 t320 sshd[557]: Connection closed by 192.168.3.45 [preauth]

(While these logs aren't very helpful, odds are you'll see something like them if LDAP Auth isn't quite working right) 

In doing some googling, I stumbled across something known as nslcd which appears to handle the actual 'talking to OpenLDAP' piece. The next set of errors has more actionable information

 

Error set 2: nslcd debug log

To get logs from nslcd, you'll need to run a command like this:

  • systemctl stop nslcd
  • sudo nslcd -d -d -d 2>&1 > nslcd.log

The output on the screen or in the log (depends) will look something like this after you sift around:

attempting to connect:
connect errno: 115
ldap_int_poll: fd: 6 tm: 10
ldap_is_sock_ready: 6
ldap_ndelay_off: 6
ldap_pvt_connect: 0
TLS: certdb config: configDir='/etc/openldap/cacerts' tokenDescription='ldap(0)' certPrefix='' keyPrefix='' flags=readOnly
TLS: cannot open certdb '/etc/openldap/cacerts', error -8018:Unknown PKCS #11 error.
TLS: skipping 'dit.domain.tld.pem' - filename does not have expected format (certificate hash with numeric suffix)

It looks like nslcd has specific naming requirements around the certificates that will load when it tries to authenticate a connection to the OpenLDAP Server. Interestingly enough, it isn't super clear on what that format should be in the log file

To address this, we need to get the openssl hash of the pem certificate, then rename the cert so nslcd recognizes it:

  • openssl x509 -in /etc/openldap/cacerts/dit.domain.tld.pem -hash
    (This will generate a lot of output, just grab the first few characters that get printed out as that's the actual hash) 
  • mv /etc/openldap/cacerts/dit.domain.tld.pem /etc/openldap/cacerts/<hash>.0
    (Yes, that a '.0' [ZERO not The letter 'O']. An example would look like this:
    d4e07e7d.0 )
      
  •  systemctl start nslcd

This should get you to your next blocking problem (or maybe that will be all of them, hooray if so!)

 

Error set 3: TLS already started

Stop the nslcd service like in 'error set 2'

You might see this error in the logs:

TLS already started

If so, it means that you need to tweak your /etc/nslcd.conf file:

  • nano /etc/nslcd.conf
  • remove the ssl start_tls  --or--  ssl no lines from the file
    (You could comment them out if you want to be safe)
  • systemctl start nslcd

Near as I can tell, the authconfig thing I did coupled with the manual edits for LDAPS put things in an inconsistent state at one point during my experimentation. nslcd was trying to elevate to a TLS session over an SSL connection, which doesn't make any sense... so doing this and restarting the service cleaned things up nicely!