The branch, master has been updated via c174e9ebe71 tests/krb5: Check account name and SID in PAC for S4U tests via 9ac2d5d991d gp: Apply Firewalld Policy via 8f347449190 gp: Test Firewalld Group Policy Apply via 7253405c352 gp: Add Firewalld ADMX templates from 5094d986b76 lib/krb5_wrap: Fix missing error check in new salt code
https://git.samba.org/?p=samba.git;a=shortlog;h=master - Log ----------------------------------------------------------------- commit c174e9ebe715aad6910d53c1f427a0512c09d651 Author: Joseph Sutton <josephsut...@catalyst.net.nz> Date: Thu Oct 21 16:46:56 2021 +1300 tests/krb5: Check account name and SID in PAC for S4U tests Signed-off-by: Joseph Sutton <josephsut...@catalyst.net.nz> Reviewed-by: Andreas Schneider <a...@cryptomilk.org> Autobuild-User(master): Andreas Schneider <a...@cryptomilk.org> Autobuild-Date(master): Mon Oct 25 09:23:35 UTC 2021 on sn-devel-184 commit 9ac2d5d991d16d1957c720fcda3ff6a9ac78dc13 Author: David Mulder <dmul...@suse.com> Date: Thu Oct 14 15:36:52 2021 -0600 gp: Apply Firewalld Policy Signed-off-by: David Mulder <dmul...@suse.com> Reviewed-by: Andreas Schneider <a...@cryptomilk.org> commit 8f347449190c698ec4d2720bbf6ffced853ef797 Author: David Mulder <dmul...@suse.com> Date: Tue Oct 12 12:54:09 2021 -0600 gp: Test Firewalld Group Policy Apply Signed-off-by: David Mulder <dmul...@suse.com> Reviewed-by: Andreas Schneider <a...@cryptomilk.org> commit 7253405c35247dff192e86598b18d524e1602818 Author: David Mulder <dmul...@suse.com> Date: Wed Oct 6 12:46:26 2021 -0600 gp: Add Firewalld ADMX templates Signed-off-by: David Mulder <dmul...@suse.com> Reviewed-by: Andreas Schneider <a...@cryptomilk.org> ----------------------------------------------------------------------- Summary of changes: libgpo/admx/en-US/samba.adml | 105 ++++++++++++++++--- libgpo/admx/samba.admx | 39 +++++-- python/samba/gp_firewalld_ext.py | 154 ++++++++++++++++++++++++++++ python/samba/tests/bin/firewall-cmd | 110 ++++++++++++++++++++ python/samba/tests/gpo.py | 169 +++++++++++++++++++++++++------ python/samba/tests/krb5/kdc_base_test.py | 4 + python/samba/tests/krb5/raw_testcase.py | 26 +++++ python/samba/tests/krb5/s4u_tests.py | 12 +++ source4/scripting/bin/samba-gpupdate | 2 + 9 files changed, 569 insertions(+), 52 deletions(-) create mode 100644 python/samba/gp_firewalld_ext.py create mode 100755 python/samba/tests/bin/firewall-cmd Changeset truncated at 500 lines: diff --git a/libgpo/admx/en-US/samba.adml b/libgpo/admx/en-US/samba.adml index a954c41a7d0..ad3a37ca142 100755 --- a/libgpo/admx/en-US/samba.adml +++ b/libgpo/admx/en-US/samba.adml @@ -3124,12 +3124,84 @@ Example: 192.9.200.1 192.168.2.61</string> u Insert the number of current users logged in. - U Insert the string "1 user" or "<n> users" where <n> is the number of current users logged in. - - v Insert the version of the OS, that is, the build-date and such.</string> - </stringTable> - <presentationTable> - <presentation id="POL_9320E11F_AC80_4A7D_A5C8_1C0F3F727061"> + U Insert the string "1 user" or "<n> users" where <n> is the number of current users logged in. + + v Insert the version of the OS, that is, the build-date and such.</string> + <string id="CAT_371A8FF5_990F_47DD_B200_D436AC28A4F9">Firewalld</string> + <string id="POL_ADABE9E0_FFF9_4FFE_A105_03E646C79978">Zones</string> + <string id="POL_ADABE9E0_FFF9_4FFE_A105_03E646C79978_Help">A list of zones to create. Existing zones on the host will be unaffected. + +Rule creation for zones is handled in the Rules setting.</string> + <string id="POL_B21F349F_4BF6_473E_8452_047D714F156C">Rules</string> + <string id="POL_B21F349F_4BF6_473E_8452_047D714F156C_Help">A JSON dictionary, containing zones paired with a list of rules. + +For example, to create rules for the Work and Home zones, specify the following JSON: + +{ + "work": [ + {"rule": {"family": "ipv4"}, "source address": "172.25.1.7", "service name": "ftp", "reject": {}}, + {"rule": {}, "source address": "172.25.1.8", "service name": "ftp", "reject": {}} + ], + "home": [ + {"rule": {}, "protocol value": "icmp", "reject": {}}, + {"rule": {"family": "ipv4"}, "source address": "192.168.1.2/32", "service name": "telnet", "accept": {"limit value": "1/m"}} + ] +} + +An improperly formatted JSON will be ignored. + +The rule structure loosely follows the Firewalld Rich Language Documentation. + +General rule structure: +{ + "rule": { + "family": "ipv4 | ipv6", + "priority": "priority" + }, + "source [not] address | mac | ipset": "address[/mask] | mac-address | ipset", + "destination [not] adress": "address[/mask]", + "service name": "service name", + "port": { + "port": "port value", + "protocol": "tcp | udp" + } + "protocol value": "protocol value", + "icmp-block name": "icmptype name", + "Masquerade": true|false, + "icmp-type": "icmptype name", + "forward-port": { + "port": "port value", + "protocol": "tcp | udp", + "to-port": "port value", + "to-addr": "address" + }, + "source-port": { + "port": "port value", + "protocol": "tcp | udp" + }, + "log": { + "prefix": "prefix text", + "level": "emerg | alert | crit | error | warning | notice | info | debug", + "limit value": "rate/duration" + }, + "audit": { + "limit value": "rate/duration" + }, + "accept" : { + "limit value": "rate/duration" + } | "reject": { + "type": "reject type", + "limit value": "rate/duration" + } | "drop": { + "limit value": "rate/duration" + } | "mark": { + "set": "mark[/mask]", + "limit value": "rate/duration" + } +}</string> + </stringTable> + <presentationTable> + <presentation id="POL_9320E11F_AC80_4A7D_A5C8_1C0F3F727061"> <listBox refId="LST_2E9A4684_3C0E_415B_8FD6_D4AF68BC8AC6">Script and arguments</listBox> </presentation> <presentation id="POL_825D441F_905E_4C7E_9E4B_03013697C6C1"> @@ -4642,9 +4714,18 @@ Example: 192.9.200.1 192.168.2.61</string> <presentation id="POL_68E9155C_CB49_428E_AFE0_B89316FFD948"> <textBox refId="TXT_8075D9EA_6E15_4B2A_833A_B918EE90856F"> <label>Login Prompt Message</label> - <defaultValue>Welcome to \s \r \l</defaultValue> - </textBox> - </presentation> - </presentationTable> - </resources> -</policyDefinitionResources> + <defaultValue>Welcome to \s \r \l</defaultValue> + </textBox> + </presentation> + <presentation id="POL_ADABE9E0_FFF9_4FFE_A105_03E646C79978"> + <listBox refId="LST_5B9AE80A_6529_4313_A9A1_764DF5320930">Firewalld Zones</listBox> + </presentation> + <presentation id="POL_B21F349F_4BF6_473E_8452_047D714F156C"> + <textBox refId="TXT_76109A0B_AA79_4F69_ADFC_2B3CA52763D2"> + <label>Firewalld Rules</label> + <defaultValue>{}</defaultValue> + </textBox> + </presentation> + </presentationTable> + </resources> +</policyDefinitionResources> diff --git a/libgpo/admx/samba.admx b/libgpo/admx/samba.admx index d09956d5394..877c9f2ba23 100755 --- a/libgpo/admx/samba.admx +++ b/libgpo/admx/samba.admx @@ -17,12 +17,15 @@ <category name="CAT_9DEF582D_447A_47E9_A1F5_363558D03FA9" displayName="$(string.CAT_9DEF582D_447A_47E9_A1F5_363558D03FA9)"> <parentCategory ref="CAT_7D8D7DC8_5A9D_4BE1_8227_F09CDD5AFFC6" /> </category> - <category displayName="$(string.CAT_10827749_64ED_5052_87F7_E81AD421856A)" name="CAT_10827749_64ED_5052_87F7_E81AD421856A"> - <parentCategory ref="CAT_3338C1DD_8A00_4273_8547_158D8B8C19E9"/> - </category> - </categories> - <policies> - <policy name="POL_9320E11F_AC80_4A7D_A5C8_1C0F3F727061" class="Both" displayName="$(string.POL_9320E11F_AC80_4A7D_A5C8_1C0F3F727061)" explainText="$(string.POL_9320E11F_AC80_4A7D_A5C8_1C0F3F727061_Help)" presentation="$(presentation.POL_9320E11F_AC80_4A7D_A5C8_1C0F3F727061)" key="Software\Policies\Samba\Unix Settings"> + <category displayName="$(string.CAT_10827749_64ED_5052_87F7_E81AD421856A)" name="CAT_10827749_64ED_5052_87F7_E81AD421856A"> + <parentCategory ref="CAT_3338C1DD_8A00_4273_8547_158D8B8C19E9"/> + </category> + <category name="CAT_371A8FF5_990F_47DD_B200_D436AC28A4F9" displayName="$(string.CAT_371A8FF5_990F_47DD_B200_D436AC28A4F9)"> + <parentCategory ref="CAT_7D8D7DC8_5A9D_4BE1_8227_F09CDD5AFFC6" /> + </category> + </categories> + <policies> + <policy name="POL_9320E11F_AC80_4A7D_A5C8_1C0F3F727061" class="Both" displayName="$(string.POL_9320E11F_AC80_4A7D_A5C8_1C0F3F727061)" explainText="$(string.POL_9320E11F_AC80_4A7D_A5C8_1C0F3F727061_Help)" presentation="$(presentation.POL_9320E11F_AC80_4A7D_A5C8_1C0F3F727061)" key="Software\Policies\Samba\Unix Settings"> <parentCategory ref="CAT_2B6D622C_5721_4C23_A2D6_5C70D6E059BA" /> <supportedOn ref="windows:SUPPORTED_WindowsVista" /> <elements> @@ -2525,8 +2528,22 @@ <parentCategory ref="CAT_9DEF582D_447A_47E9_A1F5_363558D03FA9" /> <supportedOn ref="windows:SUPPORTED_WindowsVista" /> <elements> - <text id="TXT_8075D9EA_6E15_4B2A_833A_B918EE90856F" key="Software\Policies\Samba\Unix Settings\Messages" valueName="issue" /> - </elements> - </policy> - </policies> -</policyDefinitions> + <text id="TXT_8075D9EA_6E15_4B2A_833A_B918EE90856F" key="Software\Policies\Samba\Unix Settings\Messages" valueName="issue" /> + </elements> + </policy> + <policy name="POL_ADABE9E0_FFF9_4FFE_A105_03E646C79978" class="Machine" displayName="$(string.POL_ADABE9E0_FFF9_4FFE_A105_03E646C79978)" explainText="$(string.POL_ADABE9E0_FFF9_4FFE_A105_03E646C79978_Help)" presentation="$(presentation.POL_ADABE9E0_FFF9_4FFE_A105_03E646C79978)" key="Software\Policies\Samba\Unix Settings\Firewalld" valueName="Zones"> + <parentCategory ref="CAT_371A8FF5_990F_47DD_B200_D436AC28A4F9" /> + <supportedOn ref="SUPPORTED_SAMBA_4_16" /> + <elements> + <list id="LST_5B9AE80A_6529_4313_A9A1_764DF5320930" key="Software\Policies\Samba\Unix Settings\Firewalld\Zones" /> + </elements> + </policy> + <policy name="POL_B21F349F_4BF6_473E_8452_047D714F156C" class="Machine" displayName="$(string.POL_B21F349F_4BF6_473E_8452_047D714F156C)" explainText="$(string.POL_B21F349F_4BF6_473E_8452_047D714F156C_Help)" presentation="$(presentation.POL_B21F349F_4BF6_473E_8452_047D714F156C)" key="Software\Policies\Samba\Unix Settings\Firewalld" valueName="Rules"> + <parentCategory ref="CAT_371A8FF5_990F_47DD_B200_D436AC28A4F9" /> + <supportedOn ref="SUPPORTED_SAMBA_4_16" /> + <elements> + <text id="TXT_76109A0B_AA79_4F69_ADFC_2B3CA52763D2" key="Software\Policies\Samba\Unix Settings\Firewalld\Rules" valueName="Rules" /> + </elements> + </policy> + </policies> +</policyDefinitions> diff --git a/python/samba/gp_firewalld_ext.py b/python/samba/gp_firewalld_ext.py new file mode 100644 index 00000000000..4067d44b610 --- /dev/null +++ b/python/samba/gp_firewalld_ext.py @@ -0,0 +1,154 @@ +# gp_firewalld_ext samba gpo policy +# Copyright (C) David Mulder <dmul...@suse.com> 2021 +# +# 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 3 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, see <http://www.gnu.org/licenses/>. + +from samba.gpclass import gp_pol_ext +import os +from subprocess import Popen, PIPE +from hashlib import blake2b +from shutil import which +import json + +def firewall_cmd(*args): + cmd = [which('firewall-cmd')] + cmd.extend(list(args)) + + p = Popen(cmd, stdout=PIPE, stderr=PIPE) + stdoutdata, stderrdata = p.communicate() + return p.returncode, stdoutdata + +def rule_segment_parse(name, rule_segment): + if type(rule_segment) == str: + return ('%s=%s' % (name, rule_segment)) + ' ' + else: + return '%s %s ' % (name, + ' '.join(['%s=%s' % (k, v) for k, v in rule_segment.items()])) + +class gp_firewalld_ext(gp_pol_ext): + def __str__(self): + return 'Security/Firewalld' + + def apply_zone(self, zone): + ret = firewall_cmd('--permanent', '--new-zone=%s' % zone)[0] + if ret != 0: + self.logger.error('Failed to add new zone %s' % zone) + else: + self.gp_db.store(str(self), 'zone:%s' % zone, zone) + # Default to matching the interface(s) for the default zone + ret, out = firewall_cmd('--list-interfaces') + if ret != 0: + self.logger.error('Failed to set interfaces for zone: %s' % zone) + for interface in out.strip().split(): + ret = firewall_cmd('--permanent', '--zone=%s' % zone, + '--add-interface=%s' % interface.decode()) + if ret != 0: + self.logger.error('Failed to set interfaces for zone: %s' % \ + zone) + + def apply_rules(self, rule_dict): + for zone, rules in rule_dict.items(): + for rule in rules: + if 'rule' in rule: + rule_parsed = rule_segment_parse('rule', rule['rule']) + else: + rule_parsed = 'rule ' + for segment in ['source', 'destination', 'service', 'port', + 'protocol', 'icmp-block', 'masquerade', + 'icmp-type', 'forward-port', 'source-port', + 'log', 'audit']: + names = [s for s in rule.keys() if s.startswith(segment)] + for name in names: + rule_parsed += rule_segment_parse(name, rule[name]) + actions = set(['accept', 'reject', 'drop', 'mark']) + segments = set(rule.keys()) + action = actions.intersection(segments) + if len(action) == 1: + rule_parsed += rule_segment_parse(list(action)[0], + rule[list(action)[0]]) + else: + self.logger.error('Invalid firewall rule syntax') + ret = firewall_cmd('--permanent', '--zone=%s' % zone, + '--add-rich-rule', rule_parsed.strip())[0] + if ret != 0: + self.logger.error('Failed to add firewall rule: %s' % \ + rule_parsed) + else: + rhash = blake2b(rule_parsed.encode()).hexdigest() + self.gp_db.store(str(self), 'rule:%s:%s' % (zone, rhash), + rule_parsed) + + def process_group_policy(self, deleted_gpo_list, changed_gpo_list): + for guid, settings in deleted_gpo_list: + self.gp_db.set_guid(guid) + if str(self) in settings: + for attribute, value in settings[str(self)].items(): + if attribute.startswith('zone'): + ret = firewall_cmd('--permanent', + '--delete-zone=%s' % value)[0] + if ret != 0: + self.logger.error('Failed to remove zone: %s' % \ + value) + else: + self.gp_db.delete(str(self), attribute) + elif attribute.startswith('rule'): + _, zone, _ = attribute.split(':') + ret = firewall_cmd('--permanent', '--zone=%s' % zone, + '--remove-rich-rule', value)[0] + if ret != 0: + self.logger.error('Failed to remove firewall' + ' rule: %s' % value) + else: + self.gp_db.delete(str(self), attribute) + self.gp_db.commit() + + for gpo in changed_gpo_list: + if gpo.file_sys_path: + section = 'Software\\Policies\\Samba\\Unix Settings\\Firewalld' + self.gp_db.set_guid(gpo.name) + pol_file = 'MACHINE/Registry.pol' + path = os.path.join(gpo.file_sys_path, pol_file) + pol_conf = self.parse(path) + if not pol_conf: + continue + for e in pol_conf.entries: + if e.keyname.startswith(section): + if e.keyname.endswith('Rules'): + self.apply_rules(json.loads(e.data)) + elif e.keyname.endswith('Zones'): + if e.valuename == '**delvals.': + continue + self.apply_zone(e.data) + self.gp_db.commit() + + def rsop(self, gpo): + output = {} + pol_file = 'MACHINE/Registry.pol' + section = 'Software\\Policies\\Samba\\Unix Settings\\Firewalld' + if gpo.file_sys_path: + path = os.path.join(gpo.file_sys_path, pol_file) + pol_conf = self.parse(path) + if not pol_conf: + return output + for e in pol_conf.entries: + if e.keyname.startswith(section): + if e.keyname.endswith('Zone'): + if 'Zones' not in output.keys(): + output['Zones'] = [] + output['Zones'].append(e.data) + elif e.keyname.endswith('Rules'): + if 'Rules' not in output.keys(): + output['Rules'] = [] + output['Rules'].append(json.loads(e.data)) + return output diff --git a/python/samba/tests/bin/firewall-cmd b/python/samba/tests/bin/firewall-cmd new file mode 100755 index 00000000000..503ae9a772c --- /dev/null +++ b/python/samba/tests/bin/firewall-cmd @@ -0,0 +1,110 @@ +#!/usr/bin/python3 +import optparse +import os, sys, re +import pickle +try: + from firewall.core.rich import Rich_Rule +except ImportError: + Rich_Rule = None + +sys.path.insert(0, "bin/python") + +if __name__ == "__main__": + parser = optparse.OptionParser('firewall-cmd [options]') + parser.add_option('--list-interfaces', default=False, action="store_true") + parser.add_option('--permanent', default=False, action="store_true") + parser.add_option('--new-zone') + parser.add_option('--get-zones', default=False, action="store_true") + parser.add_option('--delete-zone') + parser.add_option('--zone') + parser.add_option('--add-interface') + parser.add_option('--add-rich-rule') + parser.add_option('--remove-rich-rule') + parser.add_option('--list-rich-rules', default=False, action="store_true") + + (opts, args) = parser.parse_args() + + # Use a dir we can write to in the testenv + if 'LOCAL_PATH' in os.environ: + data_dir = os.path.realpath(os.environ.get('LOCAL_PATH')) + else: + data_dir = os.path.dirname(os.path.realpath(__file__)) + dump_file = os.path.join(data_dir, 'firewall-cmd.dump') + if os.path.exists(dump_file): + with open(dump_file, 'rb') as r: + data = pickle.load(r) + else: + data = {} + + if opts.list_interfaces: + if not opts.zone: # default zone dummy interface + print('eth0') + else: + assert 'zone_interfaces' in data + assert opts.zone in data['zone_interfaces'].keys() + for interface in data['zone_interfaces'][opts.zone]: + sys.stdout.write('%s ' % interface) + print() + elif opts.new_zone: + if 'zones' not in data: + data['zones'] = [] + data['zones'].append(opts.new_zone) + elif opts.get_zones: + if 'zones' in data: + for zone in data['zones']: + sys.stdout.write('%s ' % zone) + print() + elif opts.delete_zone: + assert 'zones' in data + assert opts.delete_zone in data['zones'] + data['zones'].remove(opts.delete_zone) + if len(data['zones']) == 0: + del data['zones'] + if 'zone_interfaces' in data and opts.zone in data['zone_interfaces'].keys(): + del data['zone_interfaces'][opts.zone] + elif opts.add_interface: + assert opts.zone + assert 'zones' in data + assert opts.zone in data['zones'] + if 'zone_interfaces' not in data: + data['zone_interfaces'] = {} + if opts.zone not in data['zone_interfaces'].keys(): + data['zone_interfaces'][opts.zone] = [] + data['zone_interfaces'][opts.zone].append(opts.add_interface) + elif opts.add_rich_rule: + assert opts.zone + if 'rules' not in data: + data['rules'] = {} + if opts.zone not in data['rules']: + data['rules'][opts.zone] = [] + # Test rule parsing if firewalld is installed + if Rich_Rule: + # Parsing failure will throw an exception + data['rules'][opts.zone].append(str(Rich_Rule(rule_str=opts.add_rich_rule))) + else: + data['rules'][opts.zone].append(opts.add_rich_rule) + elif opts.remove_rich_rule: + assert opts.zone + assert 'rules' in data + assert opts.zone in data['rules'].keys() + if Rich_Rule: + rich_rule = str(Rich_Rule(rule_str=opts.remove_rich_rule)) + assert rich_rule in data['rules'][opts.zone] + data['rules'][opts.zone].remove(rich_rule) + else: + assert opts.remove_rich_rule in data['rules'][opts.zone] + data['rules'][opts.zone].remove(opts.remove_rich_rule) + elif opts.list_rich_rules: + assert opts.zone + assert 'rules' in data + assert opts.zone in data['rules'].keys() + for rule in data['rules'][opts.zone]: + print(rule) + + if opts.permanent: + if data == {}: + if os.path.exists(dump_file): + os.unlink(dump_file) + else: + with open(dump_file, 'wb') as w: + pickle.dump(data, w) diff --git a/python/samba/tests/gpo.py b/python/samba/tests/gpo.py index 05f12312c6e..918a7845690 100644 --- a/python/samba/tests/gpo.py +++ b/python/samba/tests/gpo.py @@ -44,6 +44,7 @@ from samba.gp_gnome_settings_ext import gp_gnome_settings_ext from samba.gp_cert_auto_enroll_ext import gp_cert_auto_enroll_ext from samba.gp_firefox_ext import gp_firefox_ext from samba.gp_chromium_ext import gp_chromium_ext +from samba.gp_firewalld_ext import gp_firewalld_ext import logging from samba.credentials import Credentials from samba.gp_msgs_ext import gp_msgs_ext @@ -61,6 +62,7 @@ from samba.gpclass import get_dc_hostname from samba import Ldb from samba.auth import system_session import json +from shutil import which realm = os.environ.get('REALM') policies = realm + '/POLICIES' @@ -6832,6 +6834,43 @@ b""" } """ +firewalld_reg_pol = \ +b""" +<?xml version="1.0" encoding="utf-8"?> +<PolFile num_entries="6" signature="PReg" version="1"> + <Entry type="4" type_name="REG_DWORD"> + <Key>Software\Policies\Samba\Unix Settings\Firewalld</Key> + <ValueName>Zones</ValueName> + <Value>1</Value> + </Entry> + <Entry type="4" type_name="REG_DWORD"> + <Key>Software\Policies\Samba\Unix Settings\Firewalld</Key> + <ValueName>Rules</ValueName> + <Value>1</Value> + </Entry> + <Entry type="1" type_name="REG_SZ"> + <Key>Software\Policies\Samba\Unix Settings\Firewalld\Rules</Key> + <ValueName>Rules</ValueName> + <Value>{"work": [{"rule": {"family": "ipv4"}, "source address": "172.25.1.7", "service name": "ftp", "reject": {}}]}</Value> + </Entry> + <Entry type="1" type_name="REG_SZ"> + <Key>Software\Policies\Samba\Unix Settings\Firewalld\Zones</Key> + <ValueName>**delvals.</ValueName> + <Value> </Value> + </Entry> + <Entry type="1" type_name="REG_SZ"> + <Key>Software\Policies\Samba\Unix Settings\Firewalld\Zones</Key> -- Samba Shared Repository