From d61fd18a22dbd15cb5eebc90b3a7957570ad0cef Mon Sep 17 00:00:00 2001 From: GabrielNagy Date: Mon, 6 Nov 2023 09:15:21 +0000 Subject: [PATCH] Auto update vendored Samba code --- ...01-Revert-gpclass.py-to-65ab33dffab2.patch | 159 ++++++++++++++++-- .github/samba/python/samba/gp/gpclass.py | 80 ++++++++- .../python/vendor_samba/gp/gpclass.py | 19 +-- 3 files changed, 226 insertions(+), 32 deletions(-) diff --git a/.github/samba/_patches/0001-Revert-gpclass.py-to-65ab33dffab2.patch b/.github/samba/_patches/0001-Revert-gpclass.py-to-65ab33dffab2.patch index cf42b111e..aa9ecb7fe 100644 --- a/.github/samba/_patches/0001-Revert-gpclass.py-to-65ab33dffab2.patch +++ b/.github/samba/_patches/0001-Revert-gpclass.py-to-65ab33dffab2.patch @@ -1,17 +1,17 @@ -From afac4cbfda68d67d49afdd8cf82863023323b33c Mon Sep 17 00:00:00 2001 +From 93b33cdd399cba6530397930f40d5f13a0123f69 Mon Sep 17 00:00:00 2001 From: Gabriel Nagy -Date: Mon, 14 Aug 2023 13:55:27 +0300 +Date: Mon, 6 Nov 2023 11:23:39 +0200 Subject: [PATCH] Revert gpclass.py to 65ab33dffab2 This is to ensure compatibility with older Samba versions such as the one on Jammy. We don't benefit from these changes for our certificate applier use case anyway. --- - python/samba/gp/gpclass.py | 349 +------------------------------------ - 1 file changed, 9 insertions(+), 340 deletions(-) + python/samba/gp/gpclass.py | 436 ++----------------------------------- + 1 file changed, 18 insertions(+), 418 deletions(-) diff --git a/python/samba/gp/gpclass.py b/python/samba/gp/gpclass.py -index c2d612c5952..c6106a30d6e 100644 +index f7228107082..605f94f3317 100644 --- a/python/samba/gp/gpclass.py +++ b/python/samba/gp/gpclass.py @@ -21,7 +21,7 @@ import errno @@ -23,7 +23,19 @@ index c2d612c5952..c6106a30d6e 100644 from configparser import ConfigParser from io import StringIO import traceback -@@ -42,15 +42,6 @@ from samba.gp.util.logging import log +@@ -33,25 +33,17 @@ from samba.net import Net + from samba.dcerpc import nbt + from samba.samba3 import libsmb_samba_internal as libsmb + import samba.gpo as gpo ++from samba.param import LoadParm + from uuid import UUID + from tempfile import NamedTemporaryFile + from samba.dcerpc import preg +-from samba.ndr import ndr_unpack ++from samba.dcerpc import misc ++from samba.ndr import ndr_pack, ndr_unpack + from samba.credentials import SMB_SIGNING_REQUIRED + from samba.gp.util.logging import log from hashlib import blake2b import numbers from samba.common import get_string @@ -35,11 +47,46 @@ index c2d612c5952..c6106a30d6e 100644 -from samba.dcerpc import security -import samba.security -from samba.dcerpc import netlogon +-from datetime import datetime - try: from enum import Enum -@@ -446,7 +437,7 @@ class gp_applier(object): +@@ -358,28 +350,25 @@ class gp_ext(object): + + class gp_inf_ext(gp_ext): + def read(self, data_file): +- with open(data_file, 'rb') as f: +- policy = f.read() ++ policy = open(data_file, 'rb').read() + inf_conf = ConfigParser(interpolation=None) + inf_conf.optionxform = str + try: +- inf_conf.read_file(StringIO(policy.decode())) ++ inf_conf.readfp(StringIO(policy.decode())) + except UnicodeDecodeError: +- inf_conf.read_file(StringIO(policy.decode('utf-16'))) ++ inf_conf.readfp(StringIO(policy.decode('utf-16'))) + return inf_conf + + + class gp_pol_ext(gp_ext): + def read(self, data_file): +- with open(data_file, 'rb') as f: +- raw = f.read() ++ raw = open(data_file, 'rb').read() + return ndr_unpack(preg.file, raw) + + + class gp_xml_ext(gp_ext): + def read(self, data_file): +- with open(data_file, 'rb') as f: +- raw = f.read() ++ raw = open(data_file, 'rb').read() + try: + return etree.fromstring(raw.decode()) + except UnicodeDecodeError: +@@ -447,7 +436,7 @@ class gp_applier(object): The importance here is the digest of the data makes the attribute reproducible and uniquely identifies it. Hashing the name with @@ -48,7 +95,7 @@ index c2d612c5952..c6106a30d6e 100644 text in a different file. Using this attribute generator is optional. ''' data = b''.join([get_bytes(arg) for arg in [*args]]) -@@ -514,33 +505,6 @@ class gp_applier(object): +@@ -515,33 +504,6 @@ class gp_applier(object): self.unapply(guid, attribute, value, **kwargs) @@ -82,7 +129,16 @@ index c2d612c5952..c6106a30d6e 100644 class gp_file_applier(gp_applier): '''Group Policy File Applier/Unapplier/Modifier Subclass of abstract class gp_applier for monitoring policy applied -@@ -610,312 +574,17 @@ def get_dc_hostname(creds, lp): +@@ -588,7 +550,7 @@ class gp_file_applier(gp_applier): + old_val = self.cache_get_attribute_value(guid, attribute) + # Ignore removal if this policy is applied and hasn't changed + old_val_hash, old_val_files = self.__parse_value(old_val, sep) +- if (old_val_hash != value_hash or ++ if (old_val_hash != value_hash or \ + self.cache_get_apply_state() == GPOSTATE.ENFORCE) or \ + not all([os.path.exists(f) for f in old_val_files]): + self.unapply(guid, attribute, old_val_files) +@@ -611,313 +573,17 @@ def get_dc_hostname(creds, lp): nbt.NBT_SERVER_DS)) return cldap_ret.pdc_dns_name @@ -252,12 +308,14 @@ index c2d612c5952..c6106a30d6e 100644 - log.debug("add_gplink_to_gpo_list: added GPLINK #%d %s " - "to GPO list" % (i, gp_link.link_names[i])) - --def merge_nt_token(token_1, token_2): +-def merge_with_system_token(token_1): - sids = token_1.sids -- sids.extend(token_2.sids) +- system_token = system_session().security_token +- sids.extend(system_token.sids) - token_1.sids = sids -- token_1.rights_mask |= token_2.rights_mask -- token_1.privilege_mask |= token_2.privilege_mask +- token_1.rights_mask |= system_token.rights_mask +- token_1.privilege_mask |= system_token.privilege_mask +- # There are no claims in the system token, so it is safe not to merge the claims - return token_1 - -def site_dn_for_machine(samdb, dc_hostname, lp, creds, hostname): @@ -311,8 +369,7 @@ index c2d612c5952..c6106a30d6e 100644 - gpo_list_machine = False - if uac & UF_WORKSTATION_TRUST_ACCOUNT or uac & UF_SERVER_TRUST_ACCOUNT: - gpo_list_machine = True -- token = merge_nt_token(session.security_token, -- system_session().security_token) +- token = merge_with_system_token(session.security_token) - else: - token = session.security_token - @@ -401,7 +458,7 @@ index c2d612c5952..c6106a30d6e 100644 def cache_gpo_dir(conn, cache, sub_dir): -@@ -1010,7 +679,7 @@ def apply_gp(lp, creds, store, gp_extensions, username, target, force=False): +@@ -1012,7 +678,7 @@ def apply_gp(lp, creds, store, gp_extensions, username, target, force=False): if target == 'Computer': ext.process_group_policy(del_gpos, changed_gpos) else: @@ -410,6 +467,76 @@ index c2d612c5952..c6106a30d6e 100644 del_gpos, changed_gpos) except Exception as e: log.error('Failed to apply extension %s' % str(ext)) +@@ -1216,69 +882,3 @@ def drop_privileges(username, func, *args): + raise exc + + return out +- +-def expand_pref_variables(text, gpt_path, lp, username=None): +- utc_dt = datetime.utcnow() +- dt = datetime.now() +- cache_path = lp.cache_path(os.path.join('gpo_cache')) +- # These are all the possible preference variables that MS supports. The +- # variables set to 'None' here are currently unsupported by Samba, and will +- # prevent the individual policy from applying. +- variables = { 'AppDataDir': os.path.expanduser('~/.config'), +- 'BinaryComputerSid': None, +- 'BinaryUserSid': None, +- 'CommonAppdataDir': None, +- 'CommonDesktopDir': None, +- 'CommonFavoritesDir': None, +- 'CommonProgramsDir': None, +- 'CommonStartUpDir': None, +- 'ComputerName': lp.get('netbios name'), +- 'CurrentProccessId': None, +- 'CurrentThreadId': None, +- 'DateTime': utc_dt.strftime('%Y-%m-%d %H:%M:%S UTC'), +- 'DateTimeEx': str(utc_dt), +- 'DesktopDir': os.path.expanduser('~/Desktop'), +- 'DomainName': lp.get('realm'), +- 'FavoritesDir': None, +- 'GphPath': None, +- 'GptPath': os.path.join(cache_path, +- check_safe_path(gpt_path).upper()), +- 'GroupPolicyVersion': None, +- 'LastDriveMapped': None, +- 'LastError': None, +- 'LastErrorText': None, +- 'LdapComputerSid': None, +- 'LdapUserSid': None, +- 'LocalTime': dt.strftime('%H:%M:%S'), +- 'LocalTimeEx': dt.strftime('%H:%M:%S.%f'), +- 'LogonDomain': lp.get('realm'), +- 'LogonServer': None, +- 'LogonUser': username, +- 'LogonUserSid': None, +- 'MacAddress': None, +- 'NetPlacesDir': None, +- 'OsVersion': None, +- 'ProgramFilesDir': None, +- 'ProgramsDir': None, +- 'RecentDocumentsDir': None, +- 'ResultCode': None, +- 'ResultText': None, +- 'ReversedComputerSid': None, +- 'ReversedUserSid': None, +- 'SendToDir': None, +- 'StartMenuDir': None, +- 'StartUpDir': None, +- 'SystemDir': None, +- 'SystemDrive': '/', +- 'TempDir': '/tmp', +- 'TimeStamp': str(datetime.timestamp(dt)), +- 'TraceFile': None, +- 'WindowsDir': None +- } +- for exp_var, val in variables.items(): +- exp_var_fmt = '%%%s%%' % exp_var +- if exp_var_fmt in text: +- if val is None: +- raise NameError('Expansion variable %s is undefined' % exp_var) +- text = text.replace(exp_var_fmt, val) +- return text -- 2.42.0 diff --git a/.github/samba/python/samba/gp/gpclass.py b/.github/samba/python/samba/gp/gpclass.py index c2d612c59..f72281070 100644 --- a/.github/samba/python/samba/gp/gpclass.py +++ b/.github/samba/python/samba/gp/gpclass.py @@ -50,6 +50,7 @@ from samba.dcerpc import security import samba.security from samba.dcerpc import netlogon +from datetime import datetime try: @@ -776,12 +777,14 @@ def add_gplink_to_gpo_list(samdb, gpo_list, forced_gpo_list, link_dn, gp_link, log.debug("add_gplink_to_gpo_list: added GPLINK #%d %s " "to GPO list" % (i, gp_link.link_names[i])) -def merge_nt_token(token_1, token_2): +def merge_with_system_token(token_1): sids = token_1.sids - sids.extend(token_2.sids) + system_token = system_session().security_token + sids.extend(system_token.sids) token_1.sids = sids - token_1.rights_mask |= token_2.rights_mask - token_1.privilege_mask |= token_2.privilege_mask + token_1.rights_mask |= system_token.rights_mask + token_1.privilege_mask |= system_token.privilege_mask + # There are no claims in the system token, so it is safe not to merge the claims return token_1 def site_dn_for_machine(samdb, dc_hostname, lp, creds, hostname): @@ -835,8 +838,7 @@ def get_gpo_list(dc_hostname, creds, lp, username): gpo_list_machine = False if uac & UF_WORKSTATION_TRUST_ACCOUNT or uac & UF_SERVER_TRUST_ACCOUNT: gpo_list_machine = True - token = merge_nt_token(session.security_token, - system_session().security_token) + token = merge_with_system_token(session.security_token) else: token = session.security_token @@ -1214,3 +1216,69 @@ def drop_privileges(username, func, *args): raise exc return out + +def expand_pref_variables(text, gpt_path, lp, username=None): + utc_dt = datetime.utcnow() + dt = datetime.now() + cache_path = lp.cache_path(os.path.join('gpo_cache')) + # These are all the possible preference variables that MS supports. The + # variables set to 'None' here are currently unsupported by Samba, and will + # prevent the individual policy from applying. + variables = { 'AppDataDir': os.path.expanduser('~/.config'), + 'BinaryComputerSid': None, + 'BinaryUserSid': None, + 'CommonAppdataDir': None, + 'CommonDesktopDir': None, + 'CommonFavoritesDir': None, + 'CommonProgramsDir': None, + 'CommonStartUpDir': None, + 'ComputerName': lp.get('netbios name'), + 'CurrentProccessId': None, + 'CurrentThreadId': None, + 'DateTime': utc_dt.strftime('%Y-%m-%d %H:%M:%S UTC'), + 'DateTimeEx': str(utc_dt), + 'DesktopDir': os.path.expanduser('~/Desktop'), + 'DomainName': lp.get('realm'), + 'FavoritesDir': None, + 'GphPath': None, + 'GptPath': os.path.join(cache_path, + check_safe_path(gpt_path).upper()), + 'GroupPolicyVersion': None, + 'LastDriveMapped': None, + 'LastError': None, + 'LastErrorText': None, + 'LdapComputerSid': None, + 'LdapUserSid': None, + 'LocalTime': dt.strftime('%H:%M:%S'), + 'LocalTimeEx': dt.strftime('%H:%M:%S.%f'), + 'LogonDomain': lp.get('realm'), + 'LogonServer': None, + 'LogonUser': username, + 'LogonUserSid': None, + 'MacAddress': None, + 'NetPlacesDir': None, + 'OsVersion': None, + 'ProgramFilesDir': None, + 'ProgramsDir': None, + 'RecentDocumentsDir': None, + 'ResultCode': None, + 'ResultText': None, + 'ReversedComputerSid': None, + 'ReversedUserSid': None, + 'SendToDir': None, + 'StartMenuDir': None, + 'StartUpDir': None, + 'SystemDir': None, + 'SystemDrive': '/', + 'TempDir': '/tmp', + 'TimeStamp': str(datetime.timestamp(dt)), + 'TraceFile': None, + 'WindowsDir': None + } + for exp_var, val in variables.items(): + exp_var_fmt = '%%%s%%' % exp_var + if exp_var_fmt in text: + if val is None: + raise NameError('Expansion variable %s is undefined' % exp_var) + text = text.replace(exp_var_fmt, val) + return text diff --git a/internal/policies/certificate/python/vendor_samba/gp/gpclass.py b/internal/policies/certificate/python/vendor_samba/gp/gpclass.py index bd3887deb..0ef86576d 100644 --- a/internal/policies/certificate/python/vendor_samba/gp/gpclass.py +++ b/internal/policies/certificate/python/vendor_samba/gp/gpclass.py @@ -33,10 +33,12 @@ from samba.dcerpc import nbt from samba.samba3 import libsmb_samba_internal as libsmb import samba.gpo as gpo +from samba.param import LoadParm from uuid import UUID from tempfile import NamedTemporaryFile from samba.dcerpc import preg -from samba.ndr import ndr_unpack +from samba.dcerpc import misc +from samba.ndr import ndr_pack, ndr_unpack from samba.credentials import SMB_SIGNING_REQUIRED from vendor_samba.gp.util.logging import log from hashlib import blake2b @@ -348,28 +350,25 @@ def rsop(self, gpo): class gp_inf_ext(gp_ext): def read(self, data_file): - with open(data_file, 'rb') as f: - policy = f.read() + policy = open(data_file, 'rb').read() inf_conf = ConfigParser(interpolation=None) inf_conf.optionxform = str try: - inf_conf.read_file(StringIO(policy.decode())) + inf_conf.readfp(StringIO(policy.decode())) except UnicodeDecodeError: - inf_conf.read_file(StringIO(policy.decode('utf-16'))) + inf_conf.readfp(StringIO(policy.decode('utf-16'))) return inf_conf class gp_pol_ext(gp_ext): def read(self, data_file): - with open(data_file, 'rb') as f: - raw = f.read() + raw = open(data_file, 'rb').read() return ndr_unpack(preg.file, raw) class gp_xml_ext(gp_ext): def read(self, data_file): - with open(data_file, 'rb') as f: - raw = f.read() + raw = open(data_file, 'rb').read() try: return etree.fromstring(raw.decode()) except UnicodeDecodeError: @@ -551,7 +550,7 @@ def apply(self, guid, attribute, value_hash, applier_func, *args, sep=':'): old_val = self.cache_get_attribute_value(guid, attribute) # Ignore removal if this policy is applied and hasn't changed old_val_hash, old_val_files = self.__parse_value(old_val, sep) - if (old_val_hash != value_hash or + if (old_val_hash != value_hash or \ self.cache_get_apply_state() == GPOSTATE.ENFORCE) or \ not all([os.path.exists(f) for f in old_val_files]): self.unapply(guid, attribute, old_val_files)