def is_sid_valid(sid): try: security.dom_sid(sid) except TypeError: return False else: return True
def test_getuser(self): user = self.pdb.getsampwnam("root") self.assertEquals(16, user.acct_ctrl) self.assertEquals("", user.acct_desc) self.assertEquals(0, user.bad_password_count) self.assertEquals(0, user.bad_password_time) self.assertEquals(0, user.code_page) self.assertEquals(0, user.country_code) self.assertEquals("", user.dir_drive) self.assertEquals("BEDWYR", user.domain) self.assertEquals("root", user.full_name) self.assertEquals(dom_sid('S-1-5-21-2470180966-3899876309-2637894779-513'), user.group_sid) self.assertEquals("\\\\BEDWYR\\root", user.home_dir) self.assertEquals([-1 for i in range(21)], user.hours) self.assertEquals(21, user.hours_len) self.assertEquals(9223372036854775807, user.kickoff_time) self.assertEquals(None, user.lanman_passwd) self.assertEquals(9223372036854775807, user.logoff_time) self.assertEquals(0, user.logon_count) self.assertEquals(168, user.logon_divs) self.assertEquals("", user.logon_script) self.assertEquals(0, user.logon_time) self.assertEquals("", user.munged_dial) self.assertEquals('\x87\x8d\x80\x14`l\xda)gzD\xef\xa15?\xc7', user.nt_passwd) self.assertEquals("", user.nt_username) self.assertEquals(1125418267, user.pass_can_change_time) self.assertEquals(1125418267, user.pass_last_set_time) self.assertEquals(2125418266, user.pass_must_change_time) self.assertEquals(None, user.plaintext_passwd) self.assertEquals("\\\\BEDWYR\\root\\profile", user.profile_path) self.assertEquals(None, user.pw_history) self.assertEquals(dom_sid("S-1-5-21-2470180966-3899876309-2637894779-1000"), user.user_sid) self.assertEquals("root", user.username) self.assertEquals("", user.workstations)
def test_from_sddl(self): desc = security.descriptor.from_sddl("O:AOG:DAD:(A;;RPWPCCDCLCSWRCWDWOGA;;;S-1-0-0)", security.dom_sid("S-2-0-0")) self.assertEquals(desc.group_sid, security.dom_sid('S-2-0-0-512')) self.assertEquals(desc.owner_sid, security.dom_sid('S-1-5-32-548')) self.assertEquals(desc.revision, 1) self.assertEquals(desc.sacl, None) self.assertEquals(desc.type, 0x8004)
def test_setposixacl_group_getntacl_smbd(self): BA_sid = security.dom_sid(security.SID_BUILTIN_ADMINISTRATORS) s4_passdb = passdb.PDB(self.lp.get("passdb backend")) (BA_gid,BA_type) = s4_passdb.sid_to_id(BA_sid) group_SID = s4_passdb.gid_to_sid(os.stat(self.tempf).st_gid) user_SID = s4_passdb.uid_to_sid(os.stat(self.tempf).st_uid) self.assertEquals(BA_type, idmap.ID_TYPE_BOTH) smbd.set_simple_acl(self.tempf, 0640, BA_gid) facl = getntacl(self.lp, self.tempf, direct_db_access=False) domsid = passdb.get_global_sam_sid() acl = "O:%sG:%sD:(A;;0x001f019f;;;%s)(A;;0x00120089;;;BA)(A;;0x00120089;;;%s)(A;;;;;WD)" % (user_SID, group_SID, user_SID, group_SID) anysid = security.dom_sid(security.SID_NT_SELF) self.assertEquals(acl, facl.as_sddl(anysid))
def run(self, use_ntvfs=False, use_s3fs=False, credopts=None, sambaopts=None, versionopts=None): lp = sambaopts.get_loadparm() path = lp.private_path("secrets.ldb") creds = credopts.get_credentials(lp) creds.set_kerberos_state(DONT_USE_KERBEROS) logger = self.get_logger() netlogon = lp.get("path", "netlogon") sysvol = lp.get("path", "sysvol") try: samdb = SamDB(session_info=system_session(), lp=lp) except Exception as e: raise CommandError("Unable to open samdb:", e) if not use_ntvfs and not use_s3fs: use_ntvfs = "smb" in lp.get("server services") elif use_s3fs: use_ntvfs = False domain_sid = security.dom_sid(samdb.domain_sid) s3conf = s3param.get_context() s3conf.load(lp.configfile) # ensure we are using the right samba_dsdb passdb backend, no matter what s3conf.set("passdb backend", "samba_dsdb:%s" % samdb.url) LA_sid = security.dom_sid(str(domain_sid) +"-"+str(security.DOMAIN_RID_ADMINISTRATOR)) BA_sid = security.dom_sid(security.SID_BUILTIN_ADMINISTRATORS) s4_passdb = passdb.PDB(s3conf.get("passdb backend")) # These assertions correct for current ad_dc selftest # configuration. When other environments have a broad range of # groups mapped via passdb, we can relax some of these checks (LA_uid,LA_type) = s4_passdb.sid_to_id(LA_sid) if (LA_type != idmap.ID_TYPE_UID and LA_type != idmap.ID_TYPE_BOTH): raise CommandError("SID %s is not mapped to a UID" % LA_sid) (BA_gid,BA_type) = s4_passdb.sid_to_id(BA_sid) if (BA_type != idmap.ID_TYPE_GID and BA_type != idmap.ID_TYPE_BOTH): raise CommandError("SID %s is not mapped to a GID" % BA_sid) if use_ntvfs: logger.warning("Please note that POSIX permissions have NOT been changed, only the stored NT ACL") provision.setsysvolacl(samdb, netlogon, sysvol, LA_uid, BA_gid, domain_sid, lp.get("realm").lower(), samdb.domain_dn(), lp, use_ntvfs=use_ntvfs)
def test_setntacl_smbd_setposixacl_group_getntacl_smbd(self): acl = "O:S-1-5-21-2212615479-2695158682-2101375467-512G:S-1-5-21-2212615479-2695158682-2101375467-513D:(A;OICI;0x001f01ff;;;S-1-5-21-2212615479-2695158682-2101375467-512)" BA_sid = security.dom_sid(security.SID_BUILTIN_ADMINISTRATORS) simple_acl_from_posix = "O:S-1-5-21-2212615479-2695158682-2101375467-512G:S-1-5-21-2212615479-2695158682-2101375467-513D:(A;;0x001f019f;;;S-1-5-21-2212615479-2695158682-2101375467-512)(A;;0x00120089;;;BA)(A;;0x00120089;;;S-1-5-21-2212615479-2695158682-2101375467-513)(A;;;;;WD)" setntacl(self.lp, self.tempf, acl, "S-1-5-21-2212615479-2695158682-2101375467", use_ntvfs=False) # This invalidates the hash of the NT acl just set because there is a hook in the posix ACL set code s4_passdb = passdb.PDB(self.lp.get("passdb backend")) (BA_gid,BA_type) = s4_passdb.sid_to_id(BA_sid) smbd.set_simple_acl(self.tempf, 0640, BA_gid) # This should re-calculate an ACL based on the posix details facl = getntacl(self.lp,self.tempf, direct_db_access=False) anysid = security.dom_sid(security.SID_NT_SELF) self.assertEquals(simple_acl_from_posix, facl.as_sddl(anysid))
def run(self, acl, file, use_ntvfs=False, use_s3fs=False, quiet=False,xattr_backend=None,eadb_file=None, credopts=None, sambaopts=None, versionopts=None, service=None): logger = self.get_logger() lp = sambaopts.get_loadparm() try: samdb = SamDB(session_info=system_session(), lp=lp) except Exception as e: raise CommandError("Unable to open samdb:", e) if not use_ntvfs and not use_s3fs: use_ntvfs = "smb" in lp.get("server services") elif use_s3fs: use_ntvfs = False try: domain_sid = security.dom_sid(samdb.domain_sid) except: raise CommandError("Unable to read domain SID from configuration files") s3conf = s3param.get_context() s3conf.load(lp.configfile) # ensure we are using the right samba_dsdb passdb backend, no matter what s3conf.set("passdb backend", "samba_dsdb:%s" % samdb.url) setntacl(lp, file, acl, str(domain_sid), xattr_backend, eadb_file, use_ntvfs=use_ntvfs, service=service) if use_ntvfs: logger.warning("Please note that POSIX permissions have NOT been changed, only the stored NT ACL")
def setUp(self): super(SitesBaseTests, self).setUp() self.ldb = SamDB(ldaphost, credentials=creds, session_info=system_session(lp), lp=lp) self.base_dn = self.ldb.domain_dn() self.domain_sid = security.dom_sid(self.ldb.get_domain_sid()) self.configuration_dn = self.ldb.get_config_basedn().get_linearized()
def test_setntacl_getposixacl(self): acl = "O:S-1-5-21-2212615479-2695158682-2101375467-512G:S-1-5-21-2212615479-2695158682-2101375467-513D:(A;OICI;0x001f01ff;;;S-1-5-21-2212615479-2695158682-2101375467-512)" setntacl(self.lp, self.tempf, acl, "S-1-5-21-2212615479-2695158682-2101375467", use_ntvfs=False) facl = getntacl(self.lp, self.tempf) anysid = security.dom_sid(security.SID_NT_SELF) self.assertEquals(facl.as_sddl(anysid),acl) posix_acl = smbd.get_sys_acl(self.tempf, smb_acl.SMB_ACL_TYPE_ACCESS)
def join_finalise(ctx): """finalise the join, mark us synchronised and setup secrets db""" print "Sending DsReplicateUpdateRefs for all the partitions" ctx.send_DsReplicaUpdateRefs(ctx.schema_dn) ctx.send_DsReplicaUpdateRefs(ctx.config_dn) ctx.send_DsReplicaUpdateRefs(ctx.base_dn) print "Setting isSynchronized and dsServiceName" m = ldb.Message() m.dn = ldb.Dn(ctx.local_samdb, "@ROOTDSE") m["isSynchronized"] = ldb.MessageElement("TRUE", ldb.FLAG_MOD_REPLACE, "isSynchronized") m["dsServiceName"] = ldb.MessageElement("<GUID=%s>" % str(ctx.ntds_guid), ldb.FLAG_MOD_REPLACE, "dsServiceName") ctx.local_samdb.modify(m) if ctx.subdomain: return secrets_ldb = Ldb(ctx.paths.secrets, session_info=system_session(), lp=ctx.lp) print "Setting up secrets database" secretsdb_self_join( secrets_ldb, domain=ctx.domain_name, realm=ctx.realm, dnsdomain=ctx.dnsdomain, netbiosname=ctx.myname, domainsid=security.dom_sid(ctx.domsid), machinepass=ctx.acct_pass, secure_channel_type=ctx.secure_channel_type, key_version_number=ctx.key_version_number, )
def dsacl2fsacl(dssddl, domsid): """ This function takes an the SDDL representation of a DS ACL and return the SDDL representation of this ACL adapted for files. It's used for Policy object provision """ sid = security.dom_sid(domsid) ref = security.descriptor.from_sddl(dssddl, sid) fdescr = security.descriptor() fdescr.owner_sid = ref.owner_sid fdescr.group_sid = ref.group_sid fdescr.type = ref.type fdescr.revision = ref.revision fdescr.sacl = ref.sacl aces = ref.dacl.aces for i in range(0, len(aces)): ace = aces[i] if not ace.type & security.SEC_ACE_TYPE_ACCESS_ALLOWED_OBJECT and str(ace.trustee) != security.SID_BUILTIN_PREW2K: # if fdescr.type & security.SEC_DESC_DACL_AUTO_INHERITED: ace.flags = ace.flags | security.SEC_ACE_FLAG_OBJECT_INHERIT | security.SEC_ACE_FLAG_CONTAINER_INHERIT if str(ace.trustee) == security.SID_CREATOR_OWNER: # For Creator/Owner the IO flag is set as this ACE has only a sense for child objects ace.flags = ace.flags | security.SEC_ACE_FLAG_INHERIT_ONLY ace.access_mask = ldapmask2filemask(ace.access_mask) fdescr.dacl_add(ace) return fdescr.as_sddl(sid)
def establish_trust(self, another_domain, trustdom_secret): """ Establishes trust between our and another domain Input: another_domain -- instance of TrustDomainInstance, initialized with #retrieve call trustdom_secret -- shared secred used for the trust """ if self.info['name'] == another_domain.info['name']: # Check that NetBIOS names do not clash raise errors.ValidationError(name=u'AD Trust Setup', error=_('the IPA server and the remote domain cannot share the same ' 'NetBIOS name: %s') % self.info['name']) self.generate_auth(trustdom_secret) info = lsa.TrustDomainInfoInfoEx() info.domain_name.string = another_domain.info['dns_domain'] info.netbios_name.string = another_domain.info['name'] info.sid = security.dom_sid(another_domain.info['sid']) info.trust_direction = lsa.LSA_TRUST_DIRECTION_INBOUND | lsa.LSA_TRUST_DIRECTION_OUTBOUND info.trust_type = lsa.LSA_TRUST_TYPE_UPLEVEL info.trust_attributes = lsa.LSA_TRUST_ATTRIBUTE_FOREST_TRANSITIVE try: dname = lsa.String() dname.string = another_domain.info['dns_domain'] res = self._pipe.QueryTrustedDomainInfoByName(self._policy_handle, dname, lsa.LSA_TRUSTED_DOMAIN_INFO_FULL_INFO) self._pipe.DeleteTrustedDomain(self._policy_handle, res.info_ex.sid) except RuntimeError, e: pass
def test_duplicate_objectSIDs_not_allowed_on_local_objects(self): dom_sid = self.samdb.get_domain_sid() rid = self.allocate_rid() sid_str = str(dom_sid) + "-" + rid sid = ndr_pack(security.dom_sid(sid_str)) basedn = self.samdb.get_default_basedn() cn = "dsdb_test_01" dn = "cn=%s,cn=Users,%s" % (cn, basedn) self.samdb.add({ "dn": dn, "objectClass": "user", "objectSID": sid}) self.samdb.delete(dn) try: self.samdb.add({ "dn": dn, "objectClass": "user", "objectSID": sid}) self.fail("No exception should get LDB_ERR_CONSTRAINT_VIOLATION") except ldb.LdbError as e: (code, msg) = e.args if code != ldb.ERR_CONSTRAINT_VIOLATION: self.fail("Got %d - %s should have got " "LDB_ERR_CONSTRAINT_VIOLATION" % (code, msg))
def get_trusted_domain_object_sid(self, object_name): result = pysss_nss_idmap.getsidbyname(object_name) if object_name in result and (pysss_nss_idmap.SID_KEY in result[object_name]): object_sid = result[object_name][pysss_nss_idmap.SID_KEY] return object_sid # Else, we are going to contact AD DC LDAP components = normalize_name(object_name) if not ('domain' in components or 'flatname' in components): # No domain or realm specified, ambiguous search raise errors.ValidationError(name=_('trusted domain object'), error= _('Ambiguous search, user domain was not specified')) attrs = ['objectSid'] filter = '(&(sAMAccountName=%(name)s)(|(objectClass=user)(objectClass=group)))' \ % dict(name=components['name']) scope = _ldap.SCOPE_SUBTREE entries = self.get_trusted_domain_objects(components.get('domain'), components.get('flatname'), filter, attrs, scope) if len(entries) > 1: # Treat non-unique entries as invalid raise errors.ValidationError(name=_('trusted domain object'), error= _('Trusted domain did not return a unique object')) sid = self.__sid_to_str(entries[0][1]['objectSid'][0]) try: test_sid = security.dom_sid(sid) return unicode(test_sid) except TypeError, e: raise errors.ValidationError(name=_('trusted domain object'), error= _('Trusted domain did not return a valid SID for the object'))
def join_provision_own_domain(ctx): '''provision the local SAM''' # we now operate exclusively on the local database, which # we need to reopen in order to get the newly created schema print("Reconnecting to local samdb") ctx.samdb = SamDB(url=ctx.local_samdb.url, session_info=system_session(), lp=ctx.local_samdb.lp, global_schema=False) ctx.samdb.set_invocation_id(str(ctx.invocation_id)) ctx.local_samdb = ctx.samdb print("Finding domain GUID from ncName") res = ctx.local_samdb.search(base=ctx.partition_dn, scope=ldb.SCOPE_BASE, attrs=['ncName'], controls=["extended_dn:1:1"]) domguid = str(misc.GUID(ldb.Dn(ctx.samdb, res[0]['ncName'][0]).get_extended_component('GUID'))) print("Got domain GUID %s" % domguid) print("Calling own domain provision") logger = logging.getLogger("provision") logger.addHandler(logging.StreamHandler(sys.stdout)) secrets_ldb = Ldb(ctx.paths.secrets, session_info=system_session(), lp=ctx.lp) presult = provision_fill(ctx.local_samdb, secrets_ldb, logger, ctx.names, ctx.paths, domainsid=security.dom_sid(ctx.domsid), domainguid=domguid, targetdir=ctx.targetdir, samdb_fill=FILL_SUBDOMAIN, machinepass=ctx.acct_pass, serverrole="domain controller", lp=ctx.lp, hostip=ctx.names.hostip, hostip6=ctx.names.hostip6) print("Provision OK for domain %s" % ctx.names.dnsdomain)
def __init__(self, samdb, fix=False, add_update_container=True): """ :param samdb: LDB database :param fix: Apply the update if the container is missing :param add_update_container: Add the container at the end of the change :raise DomainUpdateException: """ self.samdb = samdb self.fix = fix self.add_update_container = add_update_container # TODO: In future we should check for inconsistencies when it claims it has been done self.check_update_applied = False self.config_dn = self.samdb.get_config_basedn() self.domain_dn = self.samdb.domain_dn() self.schema_dn = self.samdb.get_schema_basedn() self.sd_utils = sd_utils.SDUtils(samdb) self.domain_sid = security.dom_sid(samdb.get_domain_sid()) self.domainupdate_container = self.samdb.get_root_basedn() if not self.domainupdate_container.add_child("CN=Operations,CN=DomainUpdates,CN=System"): raise DomainUpdateException("Failed to add domain update container child") self.revision_object = self.samdb.get_root_basedn() if not self.revision_object.add_child("CN=ActiveDirectoryUpdate,CN=DomainUpdates,CN=System"): raise DomainUpdateException("Failed to add revision object child")
def setUp(self): super(SpeedTest, self).setUp() self.ldb_admin = ldb self.base_dn = ldb.domain_dn() self.domain_sid = security.dom_sid(ldb.get_domain_sid()) self.user_pass = "******" print "baseDN: %s" % self.base_dn
def setUp(self): super(UserAccountControlTests, self).setUp() self.admin_creds = creds self.admin_samdb = SamDB(url=ldaphost, session_info=system_session(), credentials=self.admin_creds, lp=lp) self.domain_sid = security.dom_sid(self.admin_samdb.get_domain_sid()) self.base_dn = self.admin_samdb.domain_dn() self.unpriv_user = "******" self.unpriv_user_pw = "samba123@" self.unpriv_creds = self.get_creds(self.unpriv_user, self.unpriv_user_pw) delete_force(self.admin_samdb, "CN=testcomputer-t,OU=test_computer_ou1,%s" % (self.base_dn)) delete_force(self.admin_samdb, "OU=test_computer_ou1,%s" % (self.base_dn)) delete_force(self.admin_samdb, "CN=%s,CN=Users,%s" % (self.unpriv_user, self.base_dn)) self.admin_samdb.newuser(self.unpriv_user, self.unpriv_user_pw) res = self.admin_samdb.search("CN=%s,CN=Users,%s" % (self.unpriv_user, self.admin_samdb.domain_dn()), scope=SCOPE_BASE, attrs=["objectSid"]) self.assertEqual(1, len(res)) self.unpriv_user_sid = ndr_unpack(security.dom_sid, res[0]["objectSid"][0]) self.unpriv_user_dn = res[0].dn self.samdb = SamDB(url=ldaphost, credentials=self.unpriv_creds, lp=lp) self.samr = samr.samr("ncacn_ip_tcp:%s[seal]" % host, lp, self.unpriv_creds) self.samr_handle = self.samr.Connect2(None, security.SEC_FLAG_MAXIMUM_ALLOWED) self.samr_domain = self.samr.OpenDomain(self.samr_handle, security.SEC_FLAG_MAXIMUM_ALLOWED, self.domain_sid) self.sd_utils = sd_utils.SDUtils(self.admin_samdb) self.admin_samdb.create_ou("OU=test_computer_ou1," + self.base_dn) self.unpriv_user_sid = self.sd_utils.get_object_sid(self.unpriv_user_dn) mod = "(OA;;CC;bf967a86-0de6-11d0-a285-00aa003049e2;;%s)" % str(self.unpriv_user_sid) old_sd = self.sd_utils.read_sd_on_dn("OU=test_computer_ou1," + self.base_dn) self.sd_utils.dacl_add_ace("OU=test_computer_ou1," + self.base_dn, mod) self.add_computer_ldap("testcomputer-t") self.sd_utils.modify_sd_on_dn("OU=test_computer_ou1," + self.base_dn, old_sd) self.computernames = ["testcomputer-0"] # Get the SD of the template account, then force it to match # what we expect for SeMachineAccountPrivilege accounts, so we # can confirm we created the accounts correctly self.sd_reference_cc = self.sd_utils.read_sd_on_dn("CN=testcomputer-t,OU=test_computer_ou1,%s" % (self.base_dn)) self.sd_reference_modify = self.sd_utils.read_sd_on_dn("CN=testcomputer-t,OU=test_computer_ou1,%s" % (self.base_dn)) for ace in self.sd_reference_modify.dacl.aces: if ace.type == security.SEC_ACE_TYPE_ACCESS_ALLOWED and ace.trustee == self.unpriv_user_sid: ace.access_mask = ace.access_mask | security.SEC_ADS_SELF_WRITE | security.SEC_ADS_WRITE_PROP # Now reconnect without domain admin rights self.samdb = SamDB(url=ldaphost, credentials=self.unpriv_creds, lp=lp)
def test_setposixacl_group_getposixacl(self): BA_sid = security.dom_sid(security.SID_BUILTIN_ADMINISTRATORS) s4_passdb = passdb.PDB(self.lp.get("passdb backend")) (BA_gid,BA_type) = s4_passdb.sid_to_id(BA_sid) self.assertEquals(BA_type, idmap.ID_TYPE_BOTH) smbd.set_simple_acl(self.tempf, 0670, BA_gid) posix_acl = smbd.get_sys_acl(self.tempf, smb_acl.SMB_ACL_TYPE_ACCESS) self.assertEquals(posix_acl.count, 5, self.print_posix_acl(posix_acl)) self.assertEquals(posix_acl.acl[0].a_type, smb_acl.SMB_ACL_USER_OBJ) self.assertEquals(posix_acl.acl[0].a_perm, 6) self.assertEquals(posix_acl.acl[1].a_type, smb_acl.SMB_ACL_GROUP_OBJ) self.assertEquals(posix_acl.acl[1].a_perm, 7) self.assertEquals(posix_acl.acl[2].a_type, smb_acl.SMB_ACL_OTHER) self.assertEquals(posix_acl.acl[2].a_perm, 0) self.assertEquals(posix_acl.acl[3].a_type, smb_acl.SMB_ACL_GROUP) self.assertEquals(posix_acl.acl[3].a_perm, 7) self.assertEquals(posix_acl.acl[3].info.gid, BA_gid) self.assertEquals(posix_acl.acl[4].a_type, smb_acl.SMB_ACL_MASK) self.assertEquals(posix_acl.acl[4].a_perm, 7)
def import_idmap(idmapdb, samba3_idmap, logger): """Import idmap data. :param samba3_idmap: Samba 3 IDMAP database to import from """ currentxid = max(samba3_idmap.get_user_hwm(), samba3_idmap.get_group_hwm()) lowerbound = currentxid # FIXME: upperbound m = ldb.Message() m.dn = ldb.Dn(idmapdb, "CN=CONFIG") m["lowerbound"] = ldb.MessageElement(str(lowerbound), ldb.FLAG_MOD_REPLACE, "lowerBound") m["xidNumber"] = ldb.MessageElement(str(currentxid), ldb.FLAG_MOD_REPLACE, "xidNumber") idmapdb.modify(m) for id_type, xid in samba3_idmap.ids(): if id_type == "UID": xid_type = "ID_TYPE_UID" elif id_type == "GID": xid_type = "ID_TYPE_GID" else: logger.warn("Wrong type of entry in idmap (%s), Ignoring", id_type) continue sid = samba3_idmap.get_sid(xid, id_type) add_idmap_entry(idmapdb, dom_sid(sid), xid, xid_type, logger)
def get_sid_trusted_domain_object(self, object_name): """Returns SID for the trusted domain object (user or group only)""" if not self.domain: # our domain is not configured or self.is_configured() never run return None if not self._domains: self._domains = self.get_trusted_domains() if len(self._domains) == 0: # Our domain is configured but no trusted domains are configured return None components = normalize_name(object_name) if not ('domain' in components or 'flatname' in components): # No domain or realm specified, ambiguous search return False entry = None if 'domain' in components and components['domain'] in self._domains: # Now we have a name to check against our list of trusted domains entry = self.resolve_against_gc(components['domain'], components['name']) elif 'flatname' in components: # Flatname was specified, traverse through the list of trusted # domains first to find the proper one for domain in self._domains: if self._domains[domain][0] == components['flatname']: entry = self.resolve_against_gc(domain, components['name']) if entry: break if entry: try: test_sid = security.dom_sid(entry) return unicode(test_sid) except TypeError, e: return False
def run(self, file, use_ntvfs=False, use_s3fs=False, as_sddl=False, xattr_backend=None, eadb_file=None, credopts=None, sambaopts=None, versionopts=None, service=None): lp = sambaopts.get_loadparm() try: samdb = SamDB(session_info=system_session(), lp=lp) except Exception as e: raise CommandError("Unable to open samdb:", e) if not use_ntvfs and not use_s3fs: use_ntvfs = "smb" in lp.get("server services") elif use_s3fs: use_ntvfs = False s3conf = s3param.get_context() s3conf.load(lp.configfile) # ensure we are using the right samba_dsdb passdb backend, no matter what s3conf.set("passdb backend", "samba_dsdb:%s" % samdb.url) acl = getntacl(lp, file, xattr_backend, eadb_file, direct_db_access=use_ntvfs, service=service) if as_sddl: try: domain_sid = security.dom_sid(samdb.domain_sid) except: raise CommandError("Unable to read domain SID from configuration files") self.outf.write(acl.as_sddl(domain_sid)+"\n") else: self.outf.write(ndr_print(acl))
def test_setposixacl_dir_getntacl_smbd(self): s4_passdb = passdb.PDB(self.lp.get("passdb backend")) user_SID = s4_passdb.uid_to_sid(os.stat(self.tempdir).st_uid) BA_sid = security.dom_sid(security.SID_BUILTIN_ADMINISTRATORS) s4_passdb = passdb.PDB(self.lp.get("passdb backend")) (BA_id,BA_type) = s4_passdb.sid_to_id(BA_sid) self.assertEquals(BA_type, idmap.ID_TYPE_BOTH) SO_sid = security.dom_sid(security.SID_BUILTIN_SERVER_OPERATORS) (SO_id,SO_type) = s4_passdb.sid_to_id(SO_sid) self.assertEquals(SO_type, idmap.ID_TYPE_BOTH) smbd.chown(self.tempdir, BA_id, SO_id) smbd.set_simple_acl(self.tempdir, 0750) facl = getntacl(self.lp, self.tempdir, direct_db_access=False) acl = "O:BAG:SOD:(A;;0x001f01ff;;;BA)(A;;0x001200a9;;;SO)(A;;;;;WD)(A;OICIIO;0x001f01ff;;;CO)(A;OICIIO;0x001200a9;;;CG)(A;OICIIO;0x001200a9;;;WD)" anysid = security.dom_sid(security.SID_NT_SELF) self.assertEquals(acl, facl.as_sddl(anysid))
def create_tmp_samdb(ctx): '''create a temporary samdb object for schema queries''' ctx.tmp_schema = Schema(security.dom_sid(ctx.domsid), schemadn=ctx.schema_dn) ctx.tmp_samdb = SamDB(session_info=system_session(), url=None, auto_connect=False, credentials=ctx.creds, lp=ctx.lp, global_schema=False, am_rodc=False) ctx.tmp_samdb.set_schema(ctx.tmp_schema)
def sid_to_s4_mapping(s4connector, key, object): ud.debug(ud.LDAP, ud.INFO, "sid_to_s4_mapping") sidAttribute='sambaSID' if s4connector.configRegistry.is_false('connector/s4/mapping/sid', False): ud.debug(ud.LDAP, ud.INFO, 'sid_to_s4: SID mapping is disabled via UCR: connector/s4/mapping/sid') sidAttribute='univentionSamba4SID' sambaSID = object['attributes'][sidAttribute] # Two diffrent cases are possible, the user sid contains the # domain sid or not. if sambaSID[0].startswith('S-'): new_objectSid_ndr = ndr_pack(security.dom_sid('%s' % (sambaSID[0]))) else: new_objectSid_ndr = ndr_pack(security.dom_sid('%s-%s' % (s4connector.s4_sid, sambaSID[0]))) return [new_objectSid_ndr]
def get_wellknown_sd(self, dn): for [sd_dn, descriptor_fn] in self.wellknown_sds: if dn == sd_dn: domain_sid = security.dom_sid(self.samdb.get_domain_sid()) return ndr_unpack(security.descriptor, descriptor_fn(domain_sid, name_map=self.name_map)) raise KeyError
def test_setntacl_smbd_setposixacl_getntacl_smbd(self): acl = "O:S-1-5-21-2212615479-2695158682-2101375467-512G:S-1-5-21-2212615479-2695158682-2101375467-513D:(A;OICI;0x001f01ff;;;S-1-5-21-2212615479-2695158682-2101375467-512)" simple_acl_from_posix = "O:S-1-5-21-2212615479-2695158682-2101375467-512G:S-1-5-21-2212615479-2695158682-2101375467-513D:(A;;0x001f019f;;;S-1-5-21-2212615479-2695158682-2101375467-512)(A;;0x00120089;;;S-1-5-21-2212615479-2695158682-2101375467-513)(A;;;;;WD)" setntacl(self.lp, self.tempf, acl, "S-1-5-21-2212615479-2695158682-2101375467", use_ntvfs=False) # This invalidates the hash of the NT acl just set because there is a hook in the posix ACL set code smbd.set_simple_acl(self.tempf, 0640) facl = getntacl(self.lp, self.tempf, direct_db_access=False) anysid = security.dom_sid(security.SID_NT_SELF) self.assertEquals(simple_acl_from_posix, facl.as_sddl(anysid))
def test_as_sddl_no_domainsid(self): dom = security.dom_sid("S-2-0-0") text = "O:AOG:DAD:(A;;RPWPCCDCLCSWRCWDWOGA;;;S-1-0-0)" desc1 = security.descriptor.from_sddl(text, dom) desc2 = security.descriptor.from_sddl(desc1.as_sddl(), dom) self.assertEquals(desc1.group_sid, desc2.group_sid) self.assertEquals(desc1.owner_sid, desc2.owner_sid) self.assertEquals(desc1.sacl, desc2.sacl) self.assertEquals(desc1.type, desc2.type)
def test_setposixacl_getntacl_smbd(self): s4_passdb = passdb.PDB(self.lp.get("passdb backend")) group_SID = s4_passdb.gid_to_sid(os.stat(self.tempf).st_gid) user_SID = s4_passdb.uid_to_sid(os.stat(self.tempf).st_uid) smbd.set_simple_acl(self.tempf, 0640) facl = getntacl(self.lp, self.tempf, direct_db_access=False) acl = "O:%sG:%sD:(A;;0x001f019f;;;%s)(A;;0x00120089;;;%s)(A;;;;;WD)" % (user_SID, group_SID, user_SID, group_SID) anysid = security.dom_sid(security.SID_NT_SELF) self.assertEquals(acl, facl.as_sddl(anysid))
def test_setntacl_getntacl_param(self): lp = LoadParm() acl = "O:S-1-5-21-2212615479-2695158682-2101375467-512G:S-1-5-21-2212615479-2695158682-2101375467-513D:(A;OICI;0x001f01ff;;;S-1-5-21-2212615479-2695158682-2101375467-512)" open(self.tempf, 'w').write("empty") setntacl(lp,self.tempf,acl,"S-1-5-21-2212615479-2695158682-2101375467","tdb",os.path.join(self.tempdir,"eadbtest.tdb")) facl=getntacl(lp,self.tempf,"tdb",os.path.join(self.tempdir,"eadbtest.tdb")) domsid=security.dom_sid(security.SID_NT_SELF) self.assertEquals(facl.as_sddl(domsid),acl) os.unlink(os.path.join(self.tempdir,"eadbtest.tdb"))
def send_DsReplicaUpdateRefs(ctx, dn): r = drsuapi.DsReplicaUpdateRefsRequest1() r.naming_context = drsuapi.DsReplicaObjectIdentifier() r.naming_context.dn = str(dn) r.naming_context.guid = misc.GUID("00000000-0000-0000-0000-000000000000") r.naming_context.sid = security.dom_sid("S-0-0") r.dest_dsa_guid = ctx.ntds_guid r.dest_dsa_dns_name = "%s._msdcs.%s" % (str(ctx.ntds_guid), ctx.dnsforest) r.options = drsuapi.DRSUAPI_DRS_ADD_REF | drsuapi.DRSUAPI_DRS_DEL_REF if not ctx.RODC: r.options |= drsuapi.DRSUAPI_DRS_WRIT_REP if ctx.drsuapi: ctx.drsuapi.DsReplicaUpdateRefs(ctx.drsuapi_handle, 1, r)
def setUp(self): super(NtaclsBackupRestoreTests, self).setUp() self.server = os.environ["SERVER"] # addc samdb_url = 'ldap://' + self.server self.service = 'test1' # service/share to test # root path for service self.service_root = os.path.join( os.environ["LOCAL_PATH"], self.service) self.smb_conf_path = os.environ['SMB_CONF_PATH'] self.creds = self.insta_creds(template=self.get_credentials()) self.samdb_conn = samdb.SamDB( url=samdb_url, session_info=system_session(), credentials=self.creds, lp=env_loadparm()) self.dom_sid = security.dom_sid(self.samdb_conn.get_domain_sid()) # helper will load conf into lp, that's how smbd can find services. self.ntacls_helper = ntacls.NtaclsHelper(self.service, self.smb_conf_path, self.dom_sid) self.lp = self.ntacls_helper.lp self.smb_conn = libsmb.Conn( self.server, self.service, lp=self.lp, creds=self.creds) self.smb_helper = ntacls.SMBHelper(self.smb_conn, self.dom_sid) self.tarfile_path = os.path.join(self.tempdir, 'ntacls-backup.tar.gz') # an example file tree self.tree = { 'file0.txt': b'test file0', 'dir1': { 'file1.txt': b'test file1', 'dir2': {} # an empty dir in dir }, } self._delete_tarfile() self.smb_helper.delete_tree() self.smb_helper.create_tree(self.tree) self._check_tree() # keep a copy of ntacls after tree just created self.original_ntacls = self.smb_helper.get_ntacls()
def setntacl_file(fpath, fsd_dic): sd = _getntacl(fpath) if sd.type & SEC_DESC_DACL_AUTO_INHERITED == 0 and sd.type & SEC_DESC_SACL_PRESENT != 0: #print "Not set acl", fpath return if sd.type & SEC_DESC_DACL_PROTECTED != 0: #print "Not set acl", fpath return sd_dic = ntacl_parser_from_sd(sd) rsddl = get_update_aces(sd_dic, fsd_dic) smbd_set_ntacl(fpath, security.descriptor.from_sddl(rsddl, security.dom_sid()))
def test_setntacl_smbd_setposixacl_getntacl_smbd(self): acl = ACL simple_acl_from_posix = "O:S-1-5-21-2212615479-2695158682-2101375467-512G:S-1-5-21-2212615479-2695158682-2101375467-513D:(A;;0x001f019f;;;S-1-5-21-2212615479-2695158682-2101375467-512)(A;;0x00120089;;;S-1-5-21-2212615479-2695158682-2101375467-513)(A;;;;;WD)" setntacl(self.lp, self.tempf, acl, DOM_SID, use_ntvfs=False, session_info=self.get_session_info()) # This invalidates the hash of the NT acl just set because there is a hook in the posix ACL set code smbd.set_simple_acl(self.tempf, 0o640) facl = getntacl(self.lp, self.tempf, direct_db_access=False) anysid = security.dom_sid(security.SID_NT_SELF) self.assertEquals(simple_acl_from_posix, facl.as_sddl(anysid))
def setUp(self): super(DirsyncBaseTests, self).setUp() self.ldb_admin = SamDB(ldapshost, credentials=creds, session_info=system_session(lp), lp=lp) self.base_dn = self.ldb_admin.domain_dn() self.domain_sid = security.dom_sid(self.ldb_admin.get_domain_sid()) self.user_pass = samba.generate_random_password(12, 16) self.configuration_dn = self.ldb_admin.get_config_basedn( ).get_linearized() self.sd_utils = sd_utils.SDUtils(self.ldb_admin) # used for anonymous login print("baseDN: %s" % self.base_dn)
def test_setntacl_smbd_getntacl_smbd_gpo(self): acl = "O:DAG:DUD:P(A;OICI;0x001f01ff;;;DA)(A;OICI;0x001f01ff;;;EA)(A;OICIIO;0x001f01ff;;;CO)(A;OICI;0x001f01ff;;;DA)(A;OICI;0x001f01ff;;;SY)(A;OICI;0x001200a9;;;AU)(A;OICI;0x001200a9;;;ED)S:AI(OU;CIIDSA;WP;f30e3bbe-9ff0-11d1-b603-0000f80367c1;bf967aa5-0de6-11d0-a285-00aa003049e2;WD)(OU;CIIDSA;WP;f30e3bbf-9ff0-11d1-b603-0000f80367c1;bf967aa5-0de6-11d0-a285-00aa003049e2;WD)" setntacl(self.lp, self.tempf, acl, DOM_SID, self.get_session_info(), use_ntvfs=False) facl = getntacl(self.lp, self.tempf, self.get_session_info(), direct_db_access=False) domsid = security.dom_sid(DOM_SID) self.assertEquals(facl.as_sddl(domsid), acl)
def test_setntacl_smbd_getntacl(self): acl = ACL setntacl(self.lp, self.tempf, acl, DOM_SID, self.get_session_info(), use_ntvfs=True) facl = getntacl(self.lp, self.tempf, self.get_session_info(), direct_db_access=True) anysid = security.dom_sid(security.SID_NT_SELF) self.assertEquals(facl.as_sddl(anysid), acl)
def backup_online(smb_conn, dest_tarfile_path, dom_sid): """ Backup all files and dirs with ntacl for the serive behind smb_conn. 1. Create a temp dir as container dir 2. Backup all files with dir structure into container dir 3. Generate file.NTACL files for each file and dir in contianer dir 4. Create a tar file from container dir(without top level folder) 5. Delete contianer dir """ if isinstance(dom_sid, str): dom_sid = security.dom_sid(dom_sid) smb_helper = SMBHelper(smb_conn, dom_sid) remotedir = '' # root dir localdir = tempfile.mkdtemp() r_dirs = [remotedir] l_dirs = [localdir] while r_dirs: r_dir = r_dirs.pop() l_dir = l_dirs.pop() for e in smb_helper.list(smb_path=r_dir): r_name = smb_helper.join(r_dir, e['name']) l_name = os.path.join(l_dir, e['name']) if smb_helper.is_dir(e['attrib']): r_dirs.append(r_name) l_dirs.append(l_name) os.mkdir(l_name) else: data = smb_helper.loadfile(r_name) with open(l_name, 'wb') as f: f.write(data) # get ntacl for this entry and save alongside ntacl_sddl_str = smb_helper.get_acl(r_name, as_sddl=True) _create_ntacl_file(l_name, ntacl_sddl_str) with tarfile.open(name=dest_tarfile_path, mode='w:gz') as tar: for name in os.listdir(localdir): path = os.path.join(localdir, name) tar.add(path, arcname=name) shutil.rmtree(localdir)
def backup_restore(src_tarfile_path, dst_service_path, samdb_conn, smb_conf_path): """ Restore files and ntacls from a tarfile to a service """ service = dst_service_path.rstrip('/').rsplit('/', 1)[-1] tempdir = tempfile.mkdtemp() # src files dom_sid_str = samdb_conn.get_domain_sid() dom_sid = security.dom_sid(dom_sid_str) ntacls_helper = NtaclsHelper(service, smb_conf_path, dom_sid) with tarfile.open(src_tarfile_path) as f: f.extractall(path=tempdir) # e.g.: /tmp/tmpRNystY/{dir1,dir1.NTACL,...file1,file1.NTACL} for dirpath, dirnames, filenames in os.walk(tempdir): rel_dirpath = os.path.relpath(dirpath, start=tempdir) dst_dirpath = os.path.normpath( os.path.join(dst_service_path, rel_dirpath)) for dirname in dirnames: if not dirname.endswith('.NTACL'): src = os.path.join(dirpath, dirname) dst = os.path.join(dst_dirpath, dirname) if not os.path.isdir(dst): # dst must be absolute path for smbd API smbd.mkdir(dst, service) ntacl_sddl_str = _read_ntacl_file(src) ntacls_helper.setntacl(dst, ntacl_sddl_str) for filename in filenames: if not filename.endswith('.NTACL'): src = os.path.join(dirpath, filename) dst = os.path.join(dst_dirpath, filename) if not os.path.isfile(dst): # dst must be absolute path for smbd API smbd.create_file(dst, service) ntacl_sddl_str = _read_ntacl_file(src) ntacls_helper.setntacl(dst, ntacl_sddl_str) # now put data in with open(src, 'rb') as src_file: data = src_file.read() with open(dst, 'wb') as dst_file: dst_file.write(data) shutil.rmtree(tempdir)
def join_provision_own_domain(ctx): '''provision the local SAM''' # we now operate exclusively on the local database, which # we need to reopen in order to get the newly created schema print("Reconnecting to local samdb") ctx.samdb = SamDB(url=ctx.local_samdb.url, session_info=system_session(), lp=ctx.local_samdb.lp, global_schema=False) ctx.samdb.set_invocation_id(str(ctx.invocation_id)) ctx.local_samdb = ctx.samdb print("Finding domain GUID from ncName") res = ctx.local_samdb.search(base=ctx.partition_dn, scope=ldb.SCOPE_BASE, attrs=['ncName'], controls=["extended_dn:1:1"]) domguid = str( misc.GUID( ldb.Dn(ctx.samdb, res[0]['ncName'][0]).get_extended_component('GUID'))) print("Got domain GUID %s" % domguid) print("Calling own domain provision") logger = logging.getLogger("provision") logger.addHandler(logging.StreamHandler(sys.stdout)) secrets_ldb = Ldb(ctx.paths.secrets, session_info=system_session(), lp=ctx.lp) presult = provision_fill(ctx.local_samdb, secrets_ldb, logger, ctx.names, ctx.paths, domainsid=security.dom_sid(ctx.domsid), domainguid=domguid, targetdir=ctx.targetdir, samdb_fill=FILL_SUBDOMAIN, machinepass=ctx.acct_pass, serverrole="domain controller", lp=ctx.lp, hostip=ctx.names.hostip, hostip6=ctx.names.hostip6, dns_backend="BIND9_DLZ") print("Provision OK for domain %s" % ctx.names.dnsdomain)
def backup_offline(src_service_path, dest_tarfile_path, samdb_conn, smb_conf_path): """ Backup files and ntacls to a tarfile for a service """ service = src_service_path.rstrip('/').rsplit('/', 1)[-1] tempdir = tempfile.mkdtemp() dom_sid_str = samdb_conn.get_domain_sid() dom_sid = security.dom_sid(dom_sid_str) ntacls_helper = NtaclsHelper(service, smb_conf_path, dom_sid) for dirpath, dirnames, filenames in os.walk(src_service_path): # each dir only cares about its direct children rel_dirpath = os.path.relpath(dirpath, start=src_service_path) dst_dirpath = os.path.join(tempdir, rel_dirpath) # create sub dirs and NTACL file for dirname in dirnames: src = os.path.join(dirpath, dirname) dst = os.path.join(dst_dirpath, dirname) # mkdir with metadata smbd.mkdir(dst, service) ntacl_sddl_str = ntacls_helper.getntacl(src, as_sddl=True) _create_ntacl_file(dst, ntacl_sddl_str) # create files and NTACL file, then copy data for filename in filenames: src = os.path.join(dirpath, filename) dst = os.path.join(dst_dirpath, filename) # create an empty file with metadata smbd.create_file(dst, service) ntacl_sddl_str = ntacls_helper.getntacl(src, as_sddl=True) _create_ntacl_file(dst, ntacl_sddl_str) # now put data in with open(src, 'rb') as src_file: data = src_file.read() with open(dst, 'wb') as dst_file: dst_file.write(data) # add all files in tempdir to tarfile without a top folder with tarfile.open(name=dest_tarfile_path, mode='w:gz') as tar: for name in os.listdir(tempdir): path = os.path.join(tempdir, name) tar.add(path, arcname=name) shutil.rmtree(tempdir)
def get_sid_for_restore(samdb, logger): # Find the DN of the RID set of the server res = samdb.search(base=ldb.Dn(samdb, samdb.get_serverName()), scope=ldb.SCOPE_BASE, attrs=["serverReference"]) server_ref_dn = ldb.Dn(samdb, str(res[0]['serverReference'][0])) res = samdb.search(base=server_ref_dn, scope=ldb.SCOPE_BASE, attrs=['rIDSetReferences']) rid_set_dn = ldb.Dn(samdb, str(res[0]['rIDSetReferences'][0])) # Get the alloc pools and next RID of the RID set res = samdb.search(base=rid_set_dn, scope=ldb.SCOPE_SUBTREE, expression="(rIDNextRID=*)", attrs=['rIDAllocationPool', 'rIDPreviousAllocationPool', 'rIDNextRID']) # Decode the bounds of the RID allocation pools try: rid = int(res[0].get('rIDNextRID')[0]) except IndexError: logger.info("The RID pool for this DC is not initalized " "(e.g. it may be a fairly new DC).") logger.info("To initialize it, create a temporary user on this DC " "(you can delete it later).") raise CommandError("Cannot create backup - " "please initialize this DC's RID pool first.") def split_val(num): high = (0xFFFFFFFF00000000 & int(num)) >> 32 low = 0x00000000FFFFFFFF & int(num) return low, high pool_l, pool_h = split_val(res[0].get('rIDPreviousAllocationPool')[0]) npool_l, npool_h = split_val(res[0].get('rIDAllocationPool')[0]) # Calculate next RID based on pool bounds if rid == npool_h: raise CommandError('Out of RIDs, finished AllocPool') if rid == pool_h: if pool_h == npool_h: raise CommandError('Out of RIDs, finished PrevAllocPool.') rid = npool_l else: rid += 1 # Construct full SID sid = dom_sid(samdb.get_domain_sid()) return str(sid) + '-' + str(rid)
def test_setntacl_smbd_invalidate_getntacl_smbd(self): acl = "O:S-1-5-21-2212615479-2695158682-2101375467-512G:S-1-5-21-2212615479-2695158682-2101375467-513D:(A;OICI;0x001f01ff;;;S-1-5-21-2212615479-2695158682-2101375467-512)" simple_acl_from_posix = "O:S-1-5-21-2212615479-2695158682-2101375467-512G:S-1-5-21-2212615479-2695158682-2101375467-513D:(A;;0x001f01ff;;;S-1-5-21-2212615479-2695158682-2101375467-512)(A;;0x001200a9;;;S-1-5-21-2212615479-2695158682-2101375467-513)(A;;;;;WD)" os.chmod(self.tempf, 0750) setntacl(self.lp, self.tempf, acl, "S-1-5-21-2212615479-2695158682-2101375467", use_ntvfs=False) # This should invalidate the ACL, as we include the posix ACL in the hash (backend_obj, dbname) = checkset_backend(self.lp, None, None) backend_obj.wrap_setxattr(dbname, self.tempf, "system.fake_access_acl", "") #the hash will break, and we return an ACL based only on the mode facl = getntacl(self.lp, self.tempf, direct_db_access=False) anysid = security.dom_sid(security.SID_NT_SELF) self.assertEquals(simple_acl_from_posix, facl.as_sddl(anysid))
def run(self, file, as_sddl=False, xattr_backend=None, eadb_file=None, credopts=None, sambaopts=None, versionopts=None): lp = sambaopts.get_loadparm() acl = getntacl(lp, file, xattr_backend, eadb_file) if as_sddl: anysid = security.dom_sid(security.SID_NT_SELF) self.outf.write(acl.info.as_sddl(anysid) + "\n") else: acl.dump()
def run(self, acl, file, use_ntvfs=False, use_s3fs=False, quiet=False, xattr_backend=None, eadb_file=None, credopts=None, sambaopts=None, versionopts=None, service=None): logger = self.get_logger() lp = sambaopts.get_loadparm() try: samdb = SamDB(session_info=system_session(), lp=lp) except Exception as e: raise CommandError("Unable to open samdb:", e) if not use_ntvfs and not use_s3fs: use_ntvfs = "smb" in lp.get("server services") elif use_s3fs: use_ntvfs = False try: domain_sid = security.dom_sid(samdb.domain_sid) except: raise CommandError( "Unable to read domain SID from configuration files") s3conf = s3param.get_context() s3conf.load(lp.configfile) # ensure we are using the right samba_dsdb passdb backend, no matter what s3conf.set("passdb backend", "samba_dsdb:%s" % samdb.url) setntacl(lp, file, acl, str(domain_sid), xattr_backend, eadb_file, use_ntvfs=use_ntvfs, service=service) if use_ntvfs: logger.warning( "Please note that POSIX permissions have NOT been changed, only the stored NT ACL" )
def run(self, file, use_ntvfs=False, use_s3fs=False, as_sddl=False, xattr_backend=None, eadb_file=None, credopts=None, sambaopts=None, versionopts=None, service=None): lp = sambaopts.get_loadparm() is_ad_dc = False server_role = lp.server_role() if server_role == "ROLE_ACTIVE_DIRECTORY_DC": is_ad_dc = True if not use_ntvfs and not use_s3fs: use_ntvfs = "smb" in lp.get("server services") elif use_s3fs: use_ntvfs = False s3conf = s3param.get_context() s3conf.load(lp.configfile) if is_ad_dc: try: samdb = SamDB(session_info=system_session(), lp=lp) except Exception as e: raise CommandError("Unable to open samdb:", e) # ensure we are using the right samba_dsdb passdb backend, no # matter what s3conf.set("passdb backend", "samba_dsdb:%s" % samdb.url) acl = getntacl(lp, file, xattr_backend, eadb_file, direct_db_access=use_ntvfs, service=service, session_info=system_session_unix()) if as_sddl: try: if is_ad_dc: domain_sid = security.dom_sid(samdb.domain_sid) else: domain_sid = passdb.get_domain_sid() except: raise CommandError("Unable to read domain SID from " "configuration files") self.outf.write(acl.as_sddl(domain_sid) + "\n") else: self.outf.write(ndr_print(acl))
def _setowner(path, uid, recursive): sid = uid_to_sid(uid) sd = _getntacl(path) sddic = ntacl_parser_from_sd(sd) sddic['owner'] = sid sddl = sddic2sddl(sddic) sd = security.descriptor.from_sddl(sddl, security.dom_sid()) smbd_set_ntacl(path, sd) if recursive == 'on': for f in os.listdir(path): subpath = path + "/" + f if os.path.isfile(subpath): _setowner(subpath, uid, 'off') else: _setowner(subpath, uid, recursive) return 0
def test_wbint_Principal_null_name(self): x = winbind.wbint_Principal() x.sid = security.dom_sid(security.SID_NT_SCHANNEL_AUTHENTICATION) x.type = lsa.SID_NAME_USER x.name = None b = ndr.ndr_pack(x) y = ndr.ndr_unpack(winbind.wbint_Principal, b) self.assertEqual(x.sid, y.sid) self.assertEqual(x.type, y.type) self.assertEqual(x.name, y.name)
def test_setntacl_getntacl_param(self): random.seed() lp = LoadParm() acl = "O:S-1-5-21-2212615479-2695158682-2101375467-512G:S-1-5-21-2212615479-2695158682-2101375467-513D:(A;OICI;0x001f01ff;;;S-1-5-21-2212615479-2695158682-2101375467-512)" path = os.environ['SELFTEST_PREFIX'] tempf = os.path.join(path, "pytests" + str(int(100000 * random.random()))) ntacl = xattr.NTACL() ntacl.version = 1 open(tempf, 'w').write("empty") setntacl(lp, tempf, acl, "S-1-5-21-2212615479-2695158682-2101375467", "tdb", os.path.join(path, "eadbtest.tdb")) facl = getntacl(lp, tempf, "tdb", os.path.join(path, "eadbtest.tdb")) domsid = security.dom_sid(security.SID_NT_SELF) self.assertEquals(facl.info.as_sddl(domsid), acl) os.unlink(tempf)
def test_setntacl_smbd_dont_invalidate_getntacl_smbd(self): # set an ACL on a tempfile acl = "O:S-1-5-21-2212615479-2695158682-2101375467-512G:S-1-5-21-2212615479-2695158682-2101375467-513D:(A;OICI;0x001f01ff;;;S-1-5-21-2212615479-2695158682-2101375467-512)" os.chmod(self.tempf, 0750) setntacl(self.lp, self.tempf, acl, "S-1-5-21-2212615479-2695158682-2101375467", use_ntvfs=False) # now influence the POSIX ACL->SD mapping it returns something else than # what was set previously # this should not invalidate the hash and the complete ACL should still # be returned self.lp.set("profile acls", "yes") # we should still get back the ACL (and not one mapped from POSIX ACL) facl = getntacl(self.lp, self.tempf, direct_db_access=False) self.lp.set("profile acls", "no") anysid = security.dom_sid(security.SID_NT_SELF) self.assertEquals(acl, facl.as_sddl(anysid))
def test_get_diff_sds(self): domsid = security.dom_sid('S-1-5-21') sddl = "O:SAG:DUD:AI(A;CI;RPWPCRCCLCLORCWOWDSW;;;SA)\ (A;CI;RP LCLORC;;;AU)(A;CI;RPWPCRCCDCLCLORCWOWDSDDTSW;;;SY)S:AI(AU;CISA;WP;;;WD)" sddl1 = "O:SAG:DUD:AI(A;CI;RPWPCRCCLCLORCWOWDSW;;;SA)\ (A;CI;RP LCLORC;;;AU)(A;CI;RPWPCRCCDCLCLORCWOWDSDDTSW;;;SY)S:AI(AU;CISA;WP;;;WD)" sddl2 = "O:BAG:DUD:AI(A;CI;RPWPCRCCLCLORCWOWDSW;;;SA)\ (A;CI;RP LCLORC;;;AU)(A;CI;RPWPCRCCDCLCLORCWOWDSDDTSW;;;SY)S:AI(AU;CISA;WP;;;WD)" sddl3 = "O:SAG:BAD:AI(A;CI;RPWPCRCCLCLORCWOWDSW;;;SA)\ (A;CI;RP LCLORC;;;AU)(A;CI;RPWPCRCCDCLCLORCWOWDSDDTSW;;;SY)S:AI(AU;CISA;WP;;;WD)" sddl4 = "O:SAG:DUD:AI(A;CI;RPWPCRCCLCLORCWOWDSW;;;BA)\ (A;CI;RP LCLORC;;;AU)(A;CI;RPWPCRCCDCLCLORCWOWDSDDTSW;;;SY)S:AI(AU;CISA;WP;;;WD)" sddl5 = "O:SAG:DUD:AI(A;CI;RPWPCRCCLCLORCWOWDSW;;;SA)\ (A;CI;RP LCLORC;;;AU)(A;CI;RPWPCRCCDCLCLORCWOWDSDDTSW;;;SY)" sddl6 = "O:SAG:DUD:AI(A;CIID;RPWPCRCCLCLORCWOWDSW;;;SA)\ (A;CIID;RP LCLORC;;;AU)(A;CIID;RPWPCRCCDCLCLORCWOWDSDDTSW;;;SY)\ (A;CI;RPWPCRCCLCLORCWOWDSW;;;SA)\ (A;CI;RP LCLORC;;;AU)(A;CI;RPWPCRCCDCLCLORCWOWDSDDTSW;;;SY)S:AI(AU;CISA;WP;;;WD)(AU;CIIDSA;WP;;;WD)" self.assertEquals(get_diff_sds(security.descriptor.from_sddl(sddl, domsid), security.descriptor.from_sddl(sddl1, domsid), domsid), "") txt = get_diff_sds(security.descriptor.from_sddl(sddl, domsid), security.descriptor.from_sddl(sddl2, domsid), domsid) self.assertEquals(txt, "\tOwner mismatch: SA (in ref) BA(in current)\n") txt = get_diff_sds(security.descriptor.from_sddl(sddl, domsid), security.descriptor.from_sddl(sddl3, domsid), domsid) self.assertEquals(txt, "\tGroup mismatch: DU (in ref) BA(in current)\n") txt = get_diff_sds(security.descriptor.from_sddl(sddl, domsid), security.descriptor.from_sddl(sddl4, domsid), domsid) txtmsg = "\tPart dacl is different between reference and current here\ is the detail:\n\t\t(A;CI;RPWPCRCCLCLORCWOWDSW;;;BA) ACE is not present in\ the reference\n\t\t(A;CI;RPWPCRCCLCLORCWOWDSW;;;SA) ACE is not present in\ the current\n" self.assertEquals(txt, txtmsg) txt = get_diff_sds(security.descriptor.from_sddl(sddl, domsid), security.descriptor.from_sddl(sddl5, domsid), domsid) self.assertEquals(txt, "\tCurrent ACL hasn't a sacl part\n") self.assertEquals(get_diff_sds(security.descriptor.from_sddl(sddl, domsid), security.descriptor.from_sddl(sddl6, domsid), domsid), "")
def ntsd_to_ucs(s4connector, key, s4_object): ud.debug(ud.LDAP, ud.INFO, "ntsd_to_ucs S4 object: %s" % s4_object) ud.debug(ud.LDAP, ud.INFO, "ntsd_to_ucs S4 key: %s" % key) # modlist ml = [] # search Samba DS expicitly for hidden attribute # object dn is already mapped to the UCS DN: s4_dn = s4_object.get('dn') if not s4_dn: return # ignore try: s4_attributes = s4connector.lo_s4.get(s4_dn, attr=['nTSecurityDescriptor'], required=True) except ldap.NO_SUCH_OBJECT: ud.debug(ud.LDAP, ud.WARN, 'ntsd_to_ucs: S4 object (%s) not found' % s4_dn) return ntsd_ndr = s4_attributes.get('nTSecurityDescriptor') if not ntsd_ndr: ud.debug(ud.LDAP, ud.INFO, 'ntsd_to_ucs: nTSecurityDescriptor not found in attributes!') return # search in UCS/OpenLDAP DS to determine modify/add ucs_dn = s4_dn try: ucs_attributes = s4connector.lo.get(ucs_dn, attr=['msNTSecurityDescriptor']) except ldap.NO_SUCH_OBJECT: ud.debug(ud.LDAP, ud.WARN, 'sid_to_ucs: UCS object (%s) not found' % ucs_dn) return domain_sid = security.dom_sid(s4connector.s4_sid) s4_ntsd_sddl = decode_sd_in_ndr_to_sddl(domain_sid, ntsd_ndr[0]) ucs_ntsd_sddl = ucs_attributes.get('msNTSecurityDescriptor', [None])[0] if not ucs_ntsd_sddl or ucs_ntsd_sddl != s4_ntsd_sddl: ml.append(('msNTSecurityDescriptor', ucs_ntsd_sddl, s4_ntsd_sddl)) if ml: ud.debug(ud.LDAP, ud.INFO, 'ntsd_to_ucs: modlist = %s' % ml) serverctrls = [PostReadControl(True, ['entryUUID', 'entryCSN'])] response = {} s4connector.lo.lo.modify(ucs_dn, ml, serverctrls=serverctrls, response=response) for c in response.get('ctrls', []): # If the modify actually did something if c.controlType == PostReadControl.controlType: entryUUID = c.entry['entryUUID'][0] entryCSN = c.entry['entryCSN'][0] s4connector._remember_entryCSN_commited_by_connector(entryUUID, entryCSN)
def packet_lsarpc_76(packet, conversation, context): # lsa_LookupSids3 c = context.get_lsarpc_connection() sids = lsa.SidArray() sid = lsa.SidPtr() # Need a set x = dom_sid("S-1-5-7") sid.sid = x sids.sids = [sid] sids.num_sids = 1 names = lsa.TransNameArray2() level = 5 count = 0 lookup_options = 0 client_revision = 2 c.LookupSids3(sids, names, level, count, lookup_options, client_revision) return True
def test_setntacl_invalidate_getntacl_smbd(self): acl = "O:S-1-5-21-2212615479-2695158682-2101375467-512G:S-1-5-21-2212615479-2695158682-2101375467-513D:(A;OICI;0x001f01ff;;;S-1-5-21-2212615479-2695158682-2101375467-512)" setntacl(self.lp, self.tempf, acl, "S-1-5-21-2212615479-2695158682-2101375467", use_ntvfs=False) # This should invalidate the ACL, as we include the posix ACL in the hash (backend_obj, dbname) = checkset_backend(self.lp, None, None) backend_obj.wrap_setxattr(dbname, self.tempf, "system.fake_access_acl", "") #the hash would break, and we return an ACL based only on the mode, except we set the ACL using the 'ntvfs' mode that doesn't include a hash facl = getntacl(self.lp, self.tempf) anysid = security.dom_sid(security.SID_NT_SELF) self.assertEquals(acl, facl.as_sddl(anysid))
def test_setntacl_invalidate_getntacl(self): acl = "O:S-1-5-21-2212615479-2695158682-2101375467-512G:S-1-5-21-2212615479-2695158682-2101375467-513D:(A;OICI;0x001f01ff;;;S-1-5-21-2212615479-2695158682-2101375467-512)" setntacl(self.lp, self.tempf, acl, "S-1-5-21-2212615479-2695158682-2101375467", use_ntvfs=True) # This should invalidate the ACL, as we include the posix ACL in the hash (backend_obj, dbname) = checkset_backend(self.lp, None, None) backend_obj.wrap_setxattr(dbname, self.tempf, "system.fake_access_acl", "") #however, as this is direct DB access, we do not notice it facl = getntacl(self.lp, self.tempf, direct_db_access=True) anysid = security.dom_sid(security.SID_NT_SELF) self.assertEquals(acl, facl.as_sddl(anysid))
def packet_lsarpc_76(packet, conversation, context): # lsa_LookupSids3 c = context.get_lsarpc_connection() sids = lsa.SidArray() sid = lsa.SidPtr() # Need a set x = dom_sid("S-1-5-7") sid.sid = x sids.sids = [sid] sids.num_sids = 1 names = lsa.TransNameArray2() level = lsa.LSA_LOOKUP_NAMES_ALL count = 0 lookup_options = lsa.LSA_LOOKUP_OPTION_SEARCH_ISOLATED_NAMES client_revision = lsa.LSA_CLIENT_REVISION_2 c.LookupSids3(sids, names, level, count, lookup_options, client_revision) return True
def setntacl_file(fpath, fsd_dic): sd = getntacl_util(fpath) if sd.type & SEC_DESC_DACL_AUTO_INHERITED == 0 and sd.type & SEC_DESC_SACL_PRESENT != 0: print "Not set acl", fpath return if sd.type & SEC_DESC_DACL_PROTECTED != 0: print "Not set acl", fpath return sd_dic = ntacl_parser_from_sd(sd) rsddl = get_update_aces(sd_dic, fsd_dic) print "rsddl", rsddl smbd.set_nt_acl(fpath, security.SECINFO_OWNER | security.SECINFO_GROUP | security.SECINFO_DACL | security.SECINFO_SACL, security.descriptor.from_sddl(rsddl, security.dom_sid()), service=None)
def run(self, credopts=None, sambaopts=None, versionopts=None): lp = sambaopts.get_loadparm() creds = credopts.get_credentials(lp) creds.set_kerberos_state(DONT_USE_KERBEROS) logger = self.get_logger() netlogon = lp.get("path", "netlogon") sysvol = lp.get("path", "sysvol") try: samdb = SamDB(session_info=system_session(), lp=lp) except Exception as e: raise CommandError("Unable to open samdb:", e) domain_sid = security.dom_sid(samdb.domain_sid) provision.checksysvolacl(samdb, netlogon, sysvol, domain_sid, lp.get("realm").lower(), samdb.domain_dn(), lp)
def test_setntacl_invalidate_getntacl(self): acl = ACL setntacl(self.lp, self.tempf, acl, DOM_SID, use_ntvfs=True, session_info=self.get_session_info()) # This should invalidate the ACL, as we include the posix ACL in the hash (backend_obj, dbname) = checkset_backend(self.lp, None, None) backend_obj.wrap_setxattr(dbname, self.tempf, "system.fake_access_acl", b"") # however, as this is direct DB access, we do not notice it facl = getntacl(self.lp, self.tempf, direct_db_access=True) anysid = security.dom_sid(security.SID_NT_SELF) self.assertEquals(acl, facl.as_sddl(anysid))
def test_setntacl_invalidate_getntacl_smbd(self): acl = ACL setntacl(self.lp, self.tempf, acl, DOM_SID, use_ntvfs=False, session_info=self.get_session_info()) # This should invalidate the ACL, as we include the posix ACL in the hash (backend_obj, dbname) = checkset_backend(self.lp, None, None) backend_obj.wrap_setxattr(dbname, self.tempf, "system.fake_access_acl", b"") # the hash would break, and we return an ACL based only on the mode, except we set the ACL using the 'ntvfs' mode that doesn't include a hash facl = getntacl(self.lp, self.tempf) anysid = security.dom_sid(security.SID_NT_SELF) self.assertEquals(acl, facl.as_sddl(anysid))