Setting up a Samba Server with SELinux on RHEL 7

We are going to set up a Samba server and configure a network share suitable for group collaboration. 

The Lab

We have two RHEL 7.0 servers available in our lab:

srv1.rhce.local (10.8.8.71) – will be configured as a Samba server
srv2.rhce.local (10.8.8.72) – will be configured as a Samba client

Both servers have SELinux set to enforcing mode.

Samba Server

All commands in this section are run on the server srv1.

The samba package version used in the article is 4.1.1.

Packages, Services and Firewall

The samba-client package contains the smbpasswd command.

# yum install -y samba samba-client
# systemctl enable smb nmb
# firewall-cmd --permanent --add-service=samba
# firewall-cmd --reload

Prepare Shared Directories

We are going to create two different shares as explained below:

/srv/samba_pub – a public Samba share with r/w for all,
/srv/samba_group – a Samba share for group collaboration.

Create directories:

# mkdir /srv/{samba_pub,samba_group}

Change permissions for the public Samba share:

# chmod 0777 /srv/samba_pub

Configure collaboration for the group share:

# groupadd devops
# chgrp devops /srv/samba_group
# chmod 2775 /srv/samba_group

We want to give read-only privileges for all users who are not members of the devops group.

When a user authenticates to the Samba server, a Samba user account is used, but the Samba user account is mapped to a Linux user account, and that user account needs access permissions.

Note that users with no write permissions on the Linux file system will not have write permissions on a share. If a share is set to writable, all users with write permissions on the Linux file system have write access to the share.

Create a couple of Samba users, dev1 and dev2, where dev1 is a member of the devops Linux group:

# useradd -s /sbin/nologin -G devops dev1
# useradd -s /sbin/nologin dev2
# smbpasswd -a dev1
# smbpasswd -a dev2

Check Samba users’ database:

# pdbedit -L

Apply SELinux Context

Let us check the default SELinux context:

# ls -dZ /srv/samba_*
drwxrwsr-x. root devops unconfined_u:object_r:var_t:s0  /srv/samba_group
drwxrwxrwx. root root   unconfined_u:object_r:var_t:s0  /srv/samba_pub

Apply the samba_share_t context type to the group share:

# semanage fcontext -a -t samba_share_t "/srv/samba_group(/.*)?"

Note that if the shared directory will only be accessed through Samba, then it should be labeled samba_share_t, which gives Samba read and write access.

Samba can also serve files labeled with the SELinux types public_content_t (readonly) and public_content_rw_t (read-write). For the public share, we are going to use the public_content_rw_t type.

Note that files labeled with the public_content_t type allow them to be read by FTP, Apache, Samba and rsync. Files labeled with the public_content_rw_t type require booleans to be set before services can write to files labeled with the public_content_rw_t type.

The boolean that’s require in Samba’s case is smbd_anon_write.

# setsebool -P smbd_anon_write=1
# semanage fcontext -a -t public_content_rw_t "/srv/samba_pub(/.*)?"

Don’t forget to restore SELinux context:

# restorecon -Rv /srv/samba_*

Other SELinux Booleans Worth Mentioning

If we wanted to share any standard directory read-only, we would set the boolean samba_export_all_ro:

# setsebool -P samba_export_all_ro=1

The boolean above would allow Samba to read every file on the system. It is off by default.

Similarly, if we wanted to share all files and directories read/write via Samba, we would set the samba_export_all_rw:

# setsebool -P samba_export_all_rw=1

This boolean would allow Samba to read and write every file on the system. It’s a bad idea in general, as compromised Samba server would become extremelly dangerous. It is off by default.

If wanted to allow samba to create new home directories, we would need to turn on the samba_create_home_dirs boolean:

# setsebool -P samba_create_home_dirs=1

By default SELinux policy turns off SELinux sharing of home directories (the [homes] section defines a special file share which is enabled by default). If we were to set up a VM as a Samba server and wanted to share users home directories, we would need to set the samba_enable_home_dirs boolean:

# setsebool -P samba_enable_home_dirs=1

The above needs to be enabled for [homes] to work.

Note that Samba SELinux policy will not allow any confined applications to access remote samba shares mounted on the server. If we want to use a remote Samba server for the home directories on the server, we must set the use_samba_home_dirs boolean:

# setsebool -P use_samba_home_dirs=1

The above allows remote Samba file shares to be mounted and used as local Linux home directories.

Another important boolean is samba_share_nfs. By default, SELinux prevents Samba daemons from reading and writing NFS shares. If we were using Samba to share NFS file systems, we would need to turn the samba_share_nfs boolean on:

# setsebool -P samba_share_nfs=1

Failure to do so will cause a permission denied mount error, but nothing will be logged in to the log file /var/log/audit/audit.log, what makes it hard to troubleshoot.

Configure Samba

Open the file /etc/samba/smb.conf for editing and add the following:

[global]
;       Most Windows systems default to WORKGROUP
	workgroup = MYGROUP
	server string = Samba Server Version %v
;	netbios name = MYSERVER

	interfaces = lo 10.8.8.0/24
	hosts allow = 127. 10.8.8.

	log file = /var/log/samba/log.%m
	max log size = 50

	security = user
	passdb backend = tdbsam
	map to guest = bad user
	load printers = no

[public]
	comment = Public Share
	path = /srv/samba_pub
	public = yes
	writable = yes
	browseable = yes
	printable = no
	guest ok = yes

[group]
        comment = Group Share
        path = /srv/samba_group
        public = yes
        writable = no
        browseable = yes
	printable = no
        guest ok = no
        write list = @devops
        read list = dev2
        valid users = @devops, dev2

Note the hosts allow parameter, if it’s specified in the [global] section, then it will apply to all shares regardless of whether each share has a different setting. Hosts can be specified by a host name or by a source IP address. Host names are checked by reverse-resolving the IP address of the incoming connection attempt.

If a share is set as read-only (read only = yes, or inverted synonym writable = no), which is the default, users that are listed in the write list still have read-write access to the share. So for the group share, all users who are members of the devops group have read-write access. However, user dev2 can mount the share, but has read-only access.

On the other hand, if a share is writeable (read only = no), users in the read list will not be given write access, no matter what the read only option is set to.

Note that a printable service (printable = yes) will always allow writing to the directory (user privileges permitting), but only via spooling operations. The default is  printable = no.

The valid users parameter specifies a list of users who are allowed to access the share. Users not on the list are not allowed to access the share. Note that leaving the list blank, which is the default, allows all users to access the share.

To summarise, these are the defaults, and can be omitted, unless a change is required:

hosts allow = # none (all hosts permitted access)
read only = yes
writable = no
printable = no
browseable = yes
valid users = # no valid users list (anyone can login)
guest ok = no

Let us test the configuration:

# testparm -s
Load smb config files from /etc/samba/smb.conf
rlimit_max: increasing rlimit_max (1024) to minimum Windows limit (16384)
Processing section "[public]"
Processing section "[group]"
Loaded services file OK.
Server role: ROLE_STANDALONE
[global]
	workgroup = MYGROUP
	server string = Samba Server Version %v
	interfaces = lo, 10.8.8.0/24
	map to guest = Bad User
	log file = /var/log/samba/log.%m
	max log size = 50
	load printers = No
	idmap config * : backend = tdb
	hosts allow = 127., 10.8.8.

[public]
	comment = Public Share
	path = /srv/samba_pub
	read only = No
	guest ok = Yes

[group]
	comment = Group Share
	path = /srv/samba_group
	valid users = @devops, dev2
        read list = dev2
	write list = @devops

Start the services:

# systemctl start smb nmb

Test access locally:

# smbclient //localhost/public -U guest%

Samba Client

All commands in this section are run on the server srv2.

Install Packages

# yum install -y samba-client cifs-utils

Mount Samba Shares

Create mountpoints:

# mkdir /mnt/{samba_pub,samba_group}

Mount Samba shares:

# mount -o username=dev1 //srv1.rhce.local/group /mnt/samba_group
# mount -o username=guest,password= //srv1.rhce.local/public /mnt/samba_pub

Add the following to the file /etc/fstab to mount on boot:

//srv1.rhce.local/group   /mnt/samba_group cifs username=dev1,password=pass 0 0
//srv1.rhce.local/public  /mnt/samba_pub   cifs username=guest,password=  0 0

We can also use the credentials parameter to pass the user details that are stored in a file, for example:

//srv1.rhce.local/group   /mnt/samba_group cifs credentials=/root/creds.txt 0 0

Where the content of the /root/creds.txt file is this:

username=dev1
password=pass

The file should be read by the root user only.

Sander van Vugt recommends that all remote file systems that need to be mounted through /etc/fstab include the _netdev and the x-systemd.automount mount options.

The _netdev mount option ensures that the mount is delayed until the network is fully available. The x-systemd.automount option ensures optimal integration with systemd and will ensure that the mount is made a lot faster.

If we now try to write to the group share, it should work as the user dev1 is a member of the devops group. However, if we remount the group share using the user’s dev2 credentials, we’ll get read-only access and won’t be able to create any files.

On the Samba server srv1, we can check current connections:

# smbstatus
Samba version 4.1.1
PID     Username      Group         Machine                        
-------------------------------------------------------------------
2790      dev1          dev1          10.8.8.72    (ipv4:10.8.8.72:59422)
2790      nobody        nobody        10.8.8.72    (ipv4:10.8.8.72:59422)

Service      pid     machine       Connected at
-------------------------------------------------------
IPC$         2790   10.8.8.72     Tue Jun  7 19:44:27 2016
group        2790   10.8.8.72     Tue Jun  7 19:44:27 2016
public       2790   10.8.8.72     Tue Jun  7 19:40:53 2016
IPC$         2790   10.8.8.72     Tue Jun  7 19:40:53 2016

SMB/CIFS resources can also be accessed with smbclient:

# smbclient -L srv1.rhce.local -N
Domain=[MYGROUP] OS=[Unix] Server=[Samba 4.1.1]

	Sharename       Type      Comment
	---------       ----      -------
	public          Disk      Public Share
	group           Disk      Group Share
	IPC$            IPC       IPC Service (Samba Server Version 4.1.1)
Domain=[MYGROUP] OS=[Unix] Server=[Samba 4.1.1]

	Server               Comment
	---------            -------

	Workgroup            Master
	---------            -------

Multiuser Samba Mount

In RHEL 7 we can use the multiuser mount option to create a multiuser Samba mount.

We mount the share with a user who has minimal permissions on the share. Regular users can then add their own SMB username and password in their current session to elevate their permissions to their own permission level.

Mount the share as a multiuser mount:

# mount -o username=dev2,multiuser,sec=ntlmssp //server1.rhce.local/group /mnt/samba_group

Note that by default the protocol that’s used to authenticate users is NTLM v2 password hashing encapsulated in raw NTLMSSP messages (sec=ntlmssp). It’s for compatibility with Microsoft Windows.

We should get the permission denied error trying to write to the share as the user dev2 doesn’t have write privileges:

# touch /mnt/samba_group/test
touch: cannot touch ‘/mnt/samba_group/test’: Permission denied

On the server srv2, create a local user dev1:

# useradd dev1

Change to the newly created user and check the Samba mount:

# su - dev1
$ ls -l /mnt/
ls: cannot access /mnt/samba_group: Permission denied
total 12
dr-xr-xr-x. 10 root root 4096 May  7  2014 rhel7dvd
d??????????  ? ?    ?       ?            ? samba_group
drwxr-xr-x.  2 root root 4096 Jun  7 19:55 samba_pub

We can use cifscreds command to add authentication credentials to the current session (keyring) of a user:

$ cifscreds add srv1
Password:

Check the Samba mount again:

$ ls -l /mnt/
total 12
dr-xr-xr-x. 10 root root 4096 May  7  2014 rhel7dvd
drwxrwsr-x.  2 root dev1    0 Jun  7 19:57 samba_group
drwxr-xr-x.  2 root root 4096 Jun  7 19:55 samba_pub

We should be able to write now:

$ touch /mnt/samba_group/test
$ ls -l /mnt/samba_group/test
-rw-r--r--. 1 dev1 dev1 0 Jun  7 19:58 /mnt/samba_group/test

And if we check on the Samba server srv1 with smbstatus, we should see active connections for both users dev1 and dev2.

17 thoughts on “Setting up a Samba Server with SELinux on RHEL 7

  1. Hie Tomas

    This line gives me an error on centos 7.2

    //srv1.rhce.local/public /mnt/samba_pub cifs username=guest,password= 0 0

    I am still checking to see if there are other ways of mounting the share using guest access

  2. Let me keep checking ,somehow its giving me a mount error : permission denied error while the other share samba_group is working perfectly with credentials.

  3. @tomas ,i am trying the multiuser option and dont really know what i am missing.

    on the samba server i have this

    [multi]
    comment = Multi Share
    path = /srv/samba_multi
    writable = no
    browseable = yes
    printable = no
    guest ok = no
    write list = @devops
    read list = dev2
    valid users = @devops, dev2

    and on the client i have this
    //rhce.example.com/multi /mnt/samba_multi cifs username=dev2,multiuser,sec=ntlmssp 0 0

    and i created a dev1 local user on the client
    the cifscreds add rhce is not giving me permissions and when i reboot the client ,the multiuser mount option asks me for the dev2 password ,is this normal

  4. Somehow my client doesnt want to mount using any user who isnt in the devops group , will try again with a fresh install and see how it goes.Any user in the devops group is able to mount it with the multiuser option without any issues

  5. @everyone ,i managed to figure this one out after reading Micheal Jang. The multiuser option will work as explained on this blog post but the only caveat for me ,was the multi user mount was refusing to work if i used dev2 ,which isnt part of the devops group.so the only way it worked was for the dev2 user to have r and execute access to the /srv/samba_multiuser share folder via setfacl ………..

    • I don’t mean to sound rude Martin, but it’s all explained in the blog post.

      When a user authenticates to the Samba server, a Samba user account is used, but the Samba user account is mapped to a Linux user account, and that user account needs access permissions.

      Your dev2 user needs access permissions. You can do it with setfacl if you wish, or you can do it as in this article:

      # chmod 2775 /srv/samba_group
  6. its okay @tomas ,its my bad ,i guess i am used to the 2770 group permission where everything is restricted to the users and the groups only but as you explained it above.that works

  7. Hello Tomas,
    I am confused with the booleans.
    If I wanna share a standard directory, say, homedirs, I should enable samba_export_all_rw and samba_enable_home_dirs.
    If I wanna share a non-standard directory only via Samba, I use samba_share_t
    If I wanna share a non-standard directory via Samba and NFS, I use samba_public_content_t or samba_public_content_rw_t.
    Is everything correct?

    • What do you mean by saying “a standard directory”? You need samba_enable_home_dirs=1 if you want to share users home directories.

      If you have a directory that you want to be accessed through Samba, use samba_share_t. If you need that directory to be also accessed through FTP, Apache and rsync, use either public_content_t or public_content_rw_t.

Leave a Reply

Your email address will not be published. Required fields are marked *