Skip to content

Commit

Permalink
Adjust SMB server configuration for GPOS STIG (#15213)
Browse files Browse the repository at this point in the history
Force client to use kerberos for authentication and disable
NTLM authentication server-side.
  • Loading branch information
anodos325 authored Dec 16, 2024
1 parent 03fd254 commit 409be83
Show file tree
Hide file tree
Showing 3 changed files with 55 additions and 26 deletions.
10 changes: 9 additions & 1 deletion src/middlewared/middlewared/plugins/smb.py
Original file line number Diff line number Diff line change
Expand Up @@ -162,9 +162,17 @@ def generate_smb_configuration(self):
smb_shares = self.middleware.call_sync('sharing.smb.query')
bind_ip_choices = self.middleware.call_sync('smb.bindip_choices')
is_enterprise = self.middleware.call_sync('system.is_enterprise')
security_config = self.middleware.call_sync('system.security.config')

return generate_smb_conf_dict(
ds_type, ds_config, smb_config, smb_shares, bind_ip_choices, idmap_config, is_enterprise
ds_type,
ds_config,
smb_config,
smb_shares,
bind_ip_choices,
idmap_config,
is_enterprise,
security_config,
)

@api_method(SmbServiceBindIPChoicesArgs, SmbServiceBindIPChoicesResult)
Expand Down
11 changes: 10 additions & 1 deletion src/middlewared/middlewared/plugins/smb_/util_smbconf.py
Original file line number Diff line number Diff line change
Expand Up @@ -266,7 +266,8 @@ def generate_smb_conf_dict(
smb_shares: list,
smb_bind_choices: dict,
idmap_settings: list,
is_enterprise: bool = False
is_enterprise: bool,
security_config: dict[str, bool]
):
guest_enabled = any(filter_list(smb_shares, [['guestok', '=', True]]))
fsrvp_enabled = any(filter_list(smb_shares, [['fsrvp', '=', True]]))
Expand Down Expand Up @@ -557,6 +558,14 @@ def generate_smb_conf_dict(
param, value = entry.split('=', 1)
smbconf[param.strip()] = value.strip()

# Ordering here is relevant. Do not permit smb_options to override required
# settings for the STIG.
if security_config['enable_gpos_stig']:
smbconf.update({
'client use kerberos': 'required',
'ntlm auth': 'disabled'
})

# The following parameters must come after processing includes in order to
# prevent auxiliary parameters from overriding them
smbconf.update({
Expand Down
60 changes: 36 additions & 24 deletions tests/unit/test_smb_service.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,8 @@
SMB_ENCRYPTION_NEGOTIATE = BASE_SMB_CONFIG | {'encryption': 'NEGOTIATE'}
SMB_ENCRYPTION_DESIRED = BASE_SMB_CONFIG | {'encryption': 'DESIRED'}
SMB_ENCRYPTION_REQUIRED = BASE_SMB_CONFIG | {'encryption': 'REQUIRED'}
SYSTEM_SECURITY_DEFAULT = {'id': 1, 'enable_fips': False, 'enable_gpos_stig': False}
SYSTEM_SECURITY_GPOS_STIG = {'id': 1, 'enable_fips': True, 'enable_gpos_stig': True}


BASE_SMB_SHARE = {
Expand Down Expand Up @@ -213,7 +215,7 @@
def test__base_smb():
conf = generate_smb_conf_dict(
None, None, BASE_SMB_CONFIG, [],
BIND_IP_CHOICES, BASE_IDMAP
BIND_IP_CHOICES, BASE_IDMAP, False, SYSTEM_SECURITY_DEFAULT
)
assert conf['netbios name'] == 'TESTSERVER'
assert conf['netbios aliases'] == 'BOB LARRY'
Expand All @@ -238,7 +240,7 @@ def test__base_smb():
def test__base_smb_enterprise():
conf = generate_smb_conf_dict(
None, None, BASE_SMB_CONFIG, [],
BIND_IP_CHOICES, BASE_IDMAP, True
BIND_IP_CHOICES, BASE_IDMAP, True, SYSTEM_SECURITY_DEFAULT
)
assert conf['zfs_core:zfs_integrity_streams'] is True
assert conf['zfs_core:zfs_block_cloning'] is True
Expand All @@ -247,55 +249,55 @@ def test__base_smb_enterprise():
def test__syslog():
conf = generate_smb_conf_dict(
None, None, SMB_SYSLOG, [],
BIND_IP_CHOICES, BASE_IDMAP
BIND_IP_CHOICES, BASE_IDMAP, False, SYSTEM_SECURITY_DEFAULT
)
assert conf['logging'] == ('syslog@1 file')


def test__localmaster():
conf = generate_smb_conf_dict(
None, None, SMB_LOCALMASTER, [],
BIND_IP_CHOICES, BASE_IDMAP
BIND_IP_CHOICES, BASE_IDMAP, False, SYSTEM_SECURITY_DEFAULT
)
assert conf['local master'] is True


def test__guestaccount():
conf = generate_smb_conf_dict(
None, None, SMB_GUEST, [],
BIND_IP_CHOICES, BASE_IDMAP
BIND_IP_CHOICES, BASE_IDMAP, False, SYSTEM_SECURITY_DEFAULT
)
assert conf['guest account'] == 'mike'


def test__bindip():
conf = generate_smb_conf_dict(
None, None, SMB_BINDIP, [],
BIND_IP_CHOICES, BASE_IDMAP
BIND_IP_CHOICES, BASE_IDMAP, False, SYSTEM_SECURITY_DEFAULT
)
assert set(conf['interfaces'].split(' ')) == set(['192.168.0.250', '127.0.0.1'])


def test__ntlmv1auth():
conf = generate_smb_conf_dict(
None, None, SMB_NTLMV1, [],
BIND_IP_CHOICES, BASE_IDMAP
BIND_IP_CHOICES, BASE_IDMAP, False, SYSTEM_SECURITY_DEFAULT
)
assert conf['ntlm auth'] is True


def test__smb1_enable():
conf = generate_smb_conf_dict(
None, None, SMB_SMB1, [],
BIND_IP_CHOICES, BASE_IDMAP
BIND_IP_CHOICES, BASE_IDMAP, False, SYSTEM_SECURITY_DEFAULT
)
assert conf['server min protocol'] == 'NT1'


def test__smb_options():
conf = generate_smb_conf_dict(
None, None, SMB_OPTIONS, [],
BIND_IP_CHOICES, BASE_IDMAP
BIND_IP_CHOICES, BASE_IDMAP, False, SYSTEM_SECURITY_DEFAULT
)
assert conf['canary'] == 'bob'
assert conf['canary2'] == 'bob2'
Expand All @@ -304,15 +306,15 @@ def test__smb_options():
def test__multichannel():
conf = generate_smb_conf_dict(
None, None, SMB_MULTICHANNEL, [],
BIND_IP_CHOICES, BASE_IDMAP
BIND_IP_CHOICES, BASE_IDMAP, False, SYSTEM_SECURITY_DEFAULT
)
assert conf['server multichannel support'] is True


def test__homes_share():
conf = generate_smb_conf_dict(
None, None, BASE_SMB_CONFIG, [HOMES_SHARE],
BIND_IP_CHOICES, BASE_IDMAP
BIND_IP_CHOICES, BASE_IDMAP, False, SYSTEM_SECURITY_DEFAULT
)
assert 'obey pam restrictions' in conf
assert conf['obey pam restrictions'] is True
Expand All @@ -321,15 +323,15 @@ def test__homes_share():
def test__guest_share():
conf = generate_smb_conf_dict(
None, None, BASE_SMB_CONFIG, [GUEST_SHARE],
BIND_IP_CHOICES, BASE_IDMAP
BIND_IP_CHOICES, BASE_IDMAP, False, SYSTEM_SECURITY_DEFAULT
)
assert conf['restrict anonymous'] == 0


def test__fsrvp_share():
conf = generate_smb_conf_dict(
None, None, BASE_SMB_CONFIG, [FSRVP_SHARE],
BIND_IP_CHOICES, BASE_IDMAP
BIND_IP_CHOICES, BASE_IDMAP, False, SYSTEM_SECURITY_DEFAULT
)
assert conf['rpc_daemon:fssd'] == 'fork'
assert conf['fss:prune stale'] is True
Expand All @@ -339,7 +341,7 @@ def test__ad_base():
conf = generate_smb_conf_dict(
DSType.AD, BASE_AD_CONFIG,
BASE_SMB_CONFIG, [],
BIND_IP_CHOICES, BASE_IDMAP
BIND_IP_CHOICES, BASE_IDMAP, False, SYSTEM_SECURITY_DEFAULT
)
assert conf['realm'] == 'TESTDOMAIN.IXSYSTEMS.COM'
assert conf['winbind use default domain'] is False
Expand All @@ -359,7 +361,7 @@ def test__ad_homes_share():
conf = generate_smb_conf_dict(
DSType.AD, BASE_AD_CONFIG,
BASE_SMB_CONFIG, [HOMES_SHARE],
BIND_IP_CHOICES, BASE_IDMAP
BIND_IP_CHOICES, BASE_IDMAP, False, SYSTEM_SECURITY_DEFAULT
)
assert 'obey pam restrictions' in conf
assert conf['obey pam restrictions'] is True
Expand All @@ -372,7 +374,7 @@ def test__ad_enumeration():
conf = generate_smb_conf_dict(
DSType.AD, DISABLE_ENUM,
BASE_SMB_CONFIG, [],
BIND_IP_CHOICES, BASE_IDMAP
BIND_IP_CHOICES, BASE_IDMAP, False, SYSTEM_SECURITY_DEFAULT
)
assert conf['winbind enum users'] is False
assert conf['winbind enum groups'] is False
Expand All @@ -382,7 +384,7 @@ def test__ad_trusted_doms():
conf = generate_smb_conf_dict(
DSType.AD, TRUSTED_DOMS,
BASE_SMB_CONFIG, [],
BIND_IP_CHOICES, BASE_IDMAP
BIND_IP_CHOICES, BASE_IDMAP, False, SYSTEM_SECURITY_DEFAULT
)
assert conf['allow trusted domains'] is True

Expand All @@ -391,7 +393,7 @@ def test__ad_default_domain():
conf = generate_smb_conf_dict(
DSType.AD, USE_DEFAULT_DOM,
BASE_SMB_CONFIG, [],
BIND_IP_CHOICES, BASE_IDMAP
BIND_IP_CHOICES, BASE_IDMAP, False, SYSTEM_SECURITY_DEFAULT
)
assert conf['winbind use default domain'] is True

Expand All @@ -400,7 +402,7 @@ def test__ad_additional_domain():
conf = generate_smb_conf_dict(
DSType.AD, TRUSTED_DOMS,
BASE_SMB_CONFIG, [],
BIND_IP_CHOICES, BASE_IDMAP + [ADDITIONAL_DOMAIN]
BIND_IP_CHOICES, BASE_IDMAP + [ADDITIONAL_DOMAIN], False, SYSTEM_SECURITY_DEFAULT
)
assert conf['idmap config BOBDOM : backend'] == 'rid'
assert conf['idmap config BOBDOM : range'] == '200000001 - 300000000'
Expand All @@ -410,7 +412,8 @@ def test__ad_autorid():
conf = generate_smb_conf_dict(
DSType.AD, BASE_AD_CONFIG,
BASE_SMB_CONFIG, [],
BIND_IP_CHOICES, [AUTORID_DOMAIN, BASE_IDMAP[1], BASE_IDMAP[2]]
BIND_IP_CHOICES, [AUTORID_DOMAIN, BASE_IDMAP[1], BASE_IDMAP[2]],
False, SYSTEM_SECURITY_DEFAULT
)
assert conf['idmap config * : backend'] == 'autorid'
assert conf['idmap config * : range'] == '10000 - 200000000'
Expand All @@ -419,23 +422,23 @@ def test__ad_autorid():
def test__encryption_negotiate():
conf = generate_smb_conf_dict(
None, None, SMB_ENCRYPTION_NEGOTIATE, [],
BIND_IP_CHOICES, BASE_IDMAP
BIND_IP_CHOICES, BASE_IDMAP, False, SYSTEM_SECURITY_DEFAULT
)
assert conf['server smb encrypt'] == 'if_required'


def test__encryption_desired():
conf = generate_smb_conf_dict(
None, None, SMB_ENCRYPTION_DESIRED, [],
BIND_IP_CHOICES, BASE_IDMAP
BIND_IP_CHOICES, BASE_IDMAP, False, SYSTEM_SECURITY_DEFAULT
)
assert conf['server smb encrypt'] == 'desired'


def test__encryption_required():
conf = generate_smb_conf_dict(
None, None, SMB_ENCRYPTION_REQUIRED, [],
BIND_IP_CHOICES, BASE_IDMAP
BIND_IP_CHOICES, BASE_IDMAP, False, SYSTEM_SECURITY_DEFAULT
)
assert conf['server smb encrypt'] == 'required'

Expand All @@ -444,7 +447,7 @@ def test__ipa_base():
conf = generate_smb_conf_dict(
DSType.IPA, BASE_IPA_CONFIG,
BASE_SMB_CONFIG, [],
BIND_IP_CHOICES, BASE_IDMAP
BIND_IP_CHOICES, BASE_IDMAP, False, SYSTEM_SECURITY_DEFAULT
)
assert conf['workgroup'] == 'TN'
assert conf['server role'] == 'member server'
Expand All @@ -453,3 +456,12 @@ def test__ipa_base():
assert conf['realm'] == 'TESTDOM.TEST'
assert conf['idmap config TN : backend'] == 'sss'
assert conf['idmap config TN : range'] == '925000000 - 925199999'


def test__enable_stig():
conf = generate_smb_conf_dict(
None, None, BASE_SMB_CONFIG, [],
BIND_IP_CHOICES, BASE_IDMAP, True, SYSTEM_SECURITY_GPOS_STIG
)
assert conf['client use kerberos'] == 'required'
assert conf['ntlm auth'] == 'disabled'

0 comments on commit 409be83

Please sign in to comment.