Beispiel #1
0
def get_clean_sd(sd):
    """Get the SD without any inherited ACEs

    :param sd: SD to strip
    :return: An SD with inherited ACEs stripped
    """

    sd_clean = security.descriptor()
    sd_clean.owner_sid = sd.owner_sid
    sd_clean.group_sid = sd.group_sid
    sd_clean.type = sd.type
    sd_clean.revision = sd.revision

    aces = []
    if sd.sacl is not None:
        aces = sd.sacl.aces
    for i in range(0, len(aces)):
        ace = aces[i]

        if not ace.flags & security.SEC_ACE_FLAG_INHERITED_ACE:
            sd_clean.sacl_add(ace)
            continue

    aces = []
    if sd.dacl is not None:
        aces = sd.dacl.aces
    for i in range(0, len(aces)):
        ace = aces[i]

        if not ace.flags & security.SEC_ACE_FLAG_INHERITED_ACE:
            sd_clean.dacl_add(ace)
            continue
    return sd_clean
Beispiel #2
0
def get_clean_sd(sd):
    """Get the SD without any inherited ACEs

    :param sd: SD to strip
    :return: An SD with inherited ACEs stripped
    """

    sd_clean = security.descriptor()
    sd_clean.owner_sid = sd.owner_sid
    sd_clean.group_sid = sd.group_sid
    sd_clean.type = sd.type
    sd_clean.revision = sd.revision

    aces = []
    if sd.sacl is not None:
        aces = sd.sacl.aces
    for i in range(0, len(aces)):
        ace = aces[i]

        if not ace.flags & security.SEC_ACE_FLAG_INHERITED_ACE:
            sd_clean.sacl_add(ace)
            continue

    aces = []
    if sd.dacl is not None:
        aces = sd.dacl.aces
    for i in range(0, len(aces)):
        ace = aces[i]

        if not ace.flags & security.SEC_ACE_FLAG_INHERITED_ACE:
            sd_clean.dacl_add(ace)
            continue
    return sd_clean
Beispiel #3
0
def dsacl2fsacl(dssddl, sid, as_sddl=True):
    """

    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
    """
    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
    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)

    if not as_sddl:
        return fdescr

    return fdescr.as_sddl(sid)
Beispiel #4
0
def dsacl2fsacl(dssddl,domsid):
	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)
Beispiel #5
0
 def setUp(self):
     self.descriptor = security.descriptor()
Beispiel #6
0
    def run(self,
            computername,
            credopts=None,
            sambaopts=None,
            versionopts=None,
            H=None,
            computerou=None,
            description=None,
            prepare_oldjoin=False,
            ip_address_list=None,
            service_principal_name_list=None):

        if ip_address_list is None:
            ip_address_list = []

        if service_principal_name_list is None:
            service_principal_name_list = []

        # check each IP address if provided
        for ip_address in ip_address_list:
            if not _is_valid_ip(ip_address):
                raise CommandError('Invalid IP address {}'.format(ip_address))

        lp = sambaopts.get_loadparm()
        creds = credopts.get_credentials(lp)

        try:
            samdb = SamDB(url=H,
                          session_info=system_session(),
                          credentials=creds,
                          lp=lp)
            samdb.newcomputer(
                computername,
                computerou=computerou,
                description=description,
                prepare_oldjoin=prepare_oldjoin,
                ip_address_list=ip_address_list,
                service_principal_name_list=service_principal_name_list,
            )

            if ip_address_list:
                # if ip_address_list provided, then we need to create DNS
                # records for this computer.

                hostname = re.sub(r"\$$", "", computername)
                if hostname.count('$'):
                    raise CommandError('Illegal computername "%s"' %
                                       computername)

                filters = '(&(sAMAccountName={}$)(objectclass=computer))'.format(
                    ldb.binary_encode(hostname))

                recs = samdb.search(base=samdb.domain_dn(),
                                    scope=ldb.SCOPE_SUBTREE,
                                    expression=filters,
                                    attrs=['primaryGroupID', 'objectSid'])

                group = recs[0]['primaryGroupID'][0]
                owner = ndr_unpack(security.dom_sid, recs[0]["objectSid"][0])

                dns_conn = dnsserver.dnsserver(
                    "ncacn_ip_tcp:{}[sign]".format(samdb.host_dns_name()), lp,
                    creds)

                change_owner_sd = security.descriptor()
                change_owner_sd.owner_sid = owner
                change_owner_sd.group_sid = security.dom_sid(
                    "{}-{}".format(samdb.get_domain_sid(), group), )

                add_dns_records(samdb, hostname, dns_conn, change_owner_sd,
                                samdb.host_dns_name(), ip_address_list,
                                self.get_logger())
        except Exception as e:
            raise CommandError(
                "Failed to create computer '%s': " % computername, e)

        self.outf.write("Computer '%s' created successfully\n" % computername)
Beispiel #7
0
    def process_sd(self, dn, obj):
        sd_attr = "nTSecurityDescriptor"
        sd_val = obj[sd_attr]

        sd = ndr_unpack(security.descriptor, str(sd_val))

        is_deleted = 'isDeleted' in obj and obj['isDeleted'][0].upper(
        ) == 'TRUE'
        if is_deleted:
            # we don't fix deleted objects
            return (sd, None)

        sd_clean = security.descriptor()
        sd_clean.owner_sid = sd.owner_sid
        sd_clean.group_sid = sd.group_sid
        sd_clean.type = sd.type
        sd_clean.revision = sd.revision

        broken = False
        last_inherited_type = None

        aces = []
        if sd.sacl is not None:
            aces = sd.sacl.aces
        for i in range(0, len(aces)):
            ace = aces[i]

            if not ace.flags & security.SEC_ACE_FLAG_INHERITED_ACE:
                sd_clean.sacl_add(ace)
                continue

            t = self.ace_get_effective_inherited_type(ace)
            if t is None:
                continue

            if last_inherited_type is not None:
                if t != last_inherited_type:
                    # if it inherited from more than
                    # one type it's very likely to be broken
                    #
                    # If not the recalculation will calculate
                    # the same result.
                    broken = True
                continue

            last_inherited_type = t

        aces = []
        if sd.dacl is not None:
            aces = sd.dacl.aces
        for i in range(0, len(aces)):
            ace = aces[i]

            if not ace.flags & security.SEC_ACE_FLAG_INHERITED_ACE:
                sd_clean.dacl_add(ace)
                continue

            t = self.ace_get_effective_inherited_type(ace)
            if t is None:
                continue

            if last_inherited_type is not None:
                if t != last_inherited_type:
                    # if it inherited from more than
                    # one type it's very likely to be broken
                    #
                    # If not the recalculation will calculate
                    # the same result.
                    broken = True
                continue

            last_inherited_type = t

        if broken:
            return (sd_clean, sd)

        if last_inherited_type is None:
            # ok
            return (sd, None)

        cls = None
        try:
            cls = obj["objectClass"][-1]
        except KeyError, e:
            pass
Beispiel #8
0
            m.dn = ldb.Dn(self.samdb, "CN=Machine,%s" % str(gpo_dn))
            m['a01'] = ldb.MessageElement("container", ldb.FLAG_MOD_ADD, "objectClass")
            m['a02'] = ldb.MessageElement("TRUE", ldb.FLAG_MOD_ADD, "showInAdvancedViewOnly")
            self.samdb.add(m)

            # Copy GPO files over SMB
            create_directory_hier(conn, sharepath)
            copy_directory_local_to_remote(conn, gpodir, sharepath)

            # Get new security descriptor
            msg = get_gpo_info(self.samdb, gpo=gpo)[0]
            ds_sd_ndr = msg['ntSecurityDescriptor'][0]
            ds_sd = ndr_unpack(security.descriptor, ds_sd_ndr).as_sddl()

            # Create a file system security descriptor
            fs_sd = security.descriptor(dsacl2fsacl(ds_sd, self.samdb.get_domain_sid()))

            # Set ACL
            conn.set_acl(sharepath, fs_sd)
        except:
            self.samdb.transaction_cancel()
            raise
        else:
            self.samdb.transaction_commit()

        self.outf.write("GPO '%s' created as %s\n" % (displayname, gpo))


class cmd_gpo(SuperCommand):
    """Group Policy Object (GPO) management"""
Beispiel #9
0
 def setUp(self):
     super(SecurityDescriptorTests, self).setUp()
     self.descriptor = security.descriptor()
Beispiel #10
0
 def setUp(self):
     super(SecurityDescriptorTests, self).setUp()
     self.descriptor = security.descriptor()
    def process_sd(self, dn, obj):
        sd_attr = "nTSecurityDescriptor"
        sd_val = obj[sd_attr]

        sd = ndr_unpack(security.descriptor, str(sd_val))

        is_deleted = 'isDeleted' in obj and obj['isDeleted'][0].upper() == 'TRUE'
        if is_deleted:
            # we don't fix deleted objects
            return (sd, None)

        sd_clean = security.descriptor()
        sd_clean.owner_sid = sd.owner_sid
        sd_clean.group_sid = sd.group_sid
        sd_clean.type = sd.type
        sd_clean.revision = sd.revision

        broken = False
        last_inherited_type = None

        aces = []
        if sd.sacl is not None:
            aces = sd.sacl.aces
        for i in range(0, len(aces)):
            ace = aces[i]

            if not ace.flags & security.SEC_ACE_FLAG_INHERITED_ACE:
                sd_clean.sacl_add(ace)
                continue

            t = self.ace_get_effective_inherited_type(ace)
            if t is None:
                continue

            if last_inherited_type is not None:
                if t != last_inherited_type:
                    # if it inherited from more than
                    # one type it's very likely to be broken
                    #
                    # If not the recalculation will calculate
                    # the same result.
                    broken = True
                continue

            last_inherited_type = t

        aces = []
        if sd.dacl is not None:
            aces = sd.dacl.aces
        for i in range(0, len(aces)):
            ace = aces[i]

            if not ace.flags & security.SEC_ACE_FLAG_INHERITED_ACE:
                sd_clean.dacl_add(ace)
                continue

            t = self.ace_get_effective_inherited_type(ace)
            if t is None:
                continue

            if last_inherited_type is not None:
                if t != last_inherited_type:
                    # if it inherited from more than
                    # one type it's very likely to be broken
                    #
                    # If not the recalculation will calculate
                    # the same result.
                    broken = True
                continue

            last_inherited_type = t

        if broken:
            return (sd_clean, sd)

        if last_inherited_type is None:
            # ok
            return (sd, None)

        cls = None
        try:
            cls = obj["objectClass"][-1]
        except KeyError, e:
            pass
Beispiel #12
0
    def run(self, computername, credopts=None, sambaopts=None, versionopts=None,
            H=None, computerou=None, description=None, prepare_oldjoin=False,
            ip_address_list=None, service_principal_name_list=None):

        if ip_address_list is None:
            ip_address_list = []

        if service_principal_name_list is None:
            service_principal_name_list = []

        # check each IP address if provided
        for ip_address in ip_address_list:
            if not _is_valid_ip(ip_address):
                raise CommandError('Invalid IP address {}'.format(ip_address))

        lp = sambaopts.get_loadparm()
        creds = credopts.get_credentials(lp)

        try:
            samdb = SamDB(url=H, session_info=system_session(),
                          credentials=creds, lp=lp)
            samdb.newcomputer(computername, computerou=computerou,
                              description=description,
                              prepare_oldjoin=prepare_oldjoin,
                              ip_address_list=ip_address_list,
                              service_principal_name_list=service_principal_name_list,
                              )

            if ip_address_list:
                # if ip_address_list provided, then we need to create DNS
                # records for this computer.

                hostname = re.sub(r"\$$", "", computername)
                if hostname.count('$'):
                    raise CommandError('Illegal computername "%s"' % computername)

                filters = '(&(sAMAccountName={}$)(objectclass=computer))'.format(
                    ldb.binary_encode(hostname))

                recs = samdb.search(
                    base=samdb.domain_dn(),
                    scope=ldb.SCOPE_SUBTREE,
                    expression=filters,
                    attrs=['primaryGroupID', 'objectSid'])

                group = recs[0]['primaryGroupID'][0]
                owner = ndr_unpack(security.dom_sid, recs[0]["objectSid"][0])

                dns_conn = dnsserver.dnsserver(
                    "ncacn_ip_tcp:{}[sign]".format(samdb.host_dns_name()),
                    lp, creds)

                change_owner_sd = security.descriptor()
                change_owner_sd.owner_sid = owner
                change_owner_sd.group_sid = security.dom_sid(
                    "{}-{}".format(samdb.get_domain_sid(), group),
                )

                add_dns_records(
                    samdb, hostname, dns_conn,
                    change_owner_sd, samdb.host_dns_name(),
                    ip_address_list, self.get_logger())
        except Exception as e:
            raise CommandError("Failed to create computer '%s': " %
                               computername, e)

        self.outf.write("Computer '%s' created successfully\n" % computername)
Beispiel #13
0
                                          "objectClass")
            m['a02'] = ldb.MessageElement("TRUE", ldb.FLAG_MOD_ADD,
                                          "showInAdvancedViewOnly")
            self.samdb.add(m)

            # Copy GPO files over SMB
            create_directory_hier(conn, sharepath)
            copy_directory_local_to_remote(conn, gpodir, sharepath)

            # Get new security descriptor
            msg = get_gpo_info(self.samdb, gpo=gpo)[0]
            ds_sd_ndr = msg['ntSecurityDescriptor'][0]
            ds_sd = ndr_unpack(security.descriptor, ds_sd_ndr).as_sddl()

            # Create a file system security descriptor
            fs_sd = security.descriptor(
                dsacl2fsacl(ds_sd, self.samdb.get_domain_sid()))

            # Set ACL
            conn.set_acl(sharepath, fs_sd)

            self.samdb.transaction_commit()
        except Exception, e:
            self.samdb.transaction_cancel()
            raise RuntimeError("Error adding GPO to AD", e)

        self.outf.write("GPO '%s' created as %s\n" % (displayname, gpo))


class cmd_gpo(SuperCommand):
    """Group Policy Object (GPO) management"""
Beispiel #14
0
 def setUp(self):
     self.descriptor = security.descriptor()
Beispiel #15
0
    def _test_notify_privileged_path(self,
                                     monitor_path=None,
                                     rel_prefix=None):
        self.connect_unpriv()

        domain_sid = security.dom_sid() # we just use S-0-0
        smb_helper = ntacls.SMBHelper(self.smb_conn, domain_sid)

        private_name = "private"
        private_rel = self.make_path(rel_prefix, private_name)
        private_path = self.make_path(test_dir, private_name)
        # create a private test directory
        self.smb_conn.mkdir(private_path)

        # Get the security descriptor and replace it
        # with a one that only grants access to SYSTEM and the
        # owner.
        private_path_sd_old = smb_helper.get_acl(private_path)
        private_path_sd_new = security.descriptor()
        private_path_sd_new.type = private_path_sd_old.type
        private_path_sd_new.revision = private_path_sd_old.revision
        private_path_sd_new = security.descriptor.from_sddl("G:BAD:(A;;0x%x;;;%s)(A;;0x%x;;;%s)" % (
                security.SEC_RIGHTS_DIR_ALL,
                security.SID_NT_SYSTEM,
                security.SEC_RIGHTS_DIR_ALL,
                str(private_path_sd_old.owner_sid)),
                domain_sid)
        private_path_sd_new.type |= security.SEC_DESC_SELF_RELATIVE
        private_path_sd_new.type |= security.SEC_DESC_DACL_PROTECTED
        set_secinfo = security.SECINFO_GROUP | security.SECINFO_DACL | security.SECINFO_PROTECTED_DACL
        smb_helper.set_acl(private_path, private_path_sd_new, sinfo=set_secinfo)

        # setup notification request as priviliged user
        monitor_priv_fnum = self.smb_conn.create(Name=monitor_path, ShareAccess=1)
        notify_priv = self.smb_conn.notify(fnum=monitor_priv_fnum,
                                           buffer_size=0xffff,
                                           completion_filter=libsmb.FILE_NOTIFY_CHANGE_ALL,
                                           recursive=True)

        # setup notification request as unpriviliged user
        monitor_unpriv_fnum = self.smb_conn_unpriv.create(Name=monitor_path, ShareAccess=1)
        notify_unpriv = self.smb_conn_unpriv.notify(fnum=monitor_unpriv_fnum,
                                                    buffer_size=0xffff,
                                                    completion_filter=libsmb.FILE_NOTIFY_CHANGE_ALL,
                                                    recursive=True)

        # make sure we didn't receive any changes yet.
        self.smb_conn.echo()
        changes = notify_priv.get_changes(wait=False)
        self.assertIsNone(changes)
        self.smb_conn_unpriv.echo()
        changes = notify_unpriv.get_changes(wait=False)
        self.assertIsNone(changes)

        # trigger notification in the private dir
        new_name = 'test-new'
        new_rel = self.make_path(private_rel, new_name)
        new_path = self.make_path(private_path, new_name)
        self.smb_conn.mkdir(new_path)

        # check that only the privileged user received the changes
        changes = notify_priv.get_changes(wait=True)
        self.assertIsNotNone(changes)
        self.assertEqual(changes[0]['name'], new_rel)
        self.assertEqual(changes[0]['action'], libsmb.NOTIFY_ACTION_ADDED)
        self.assertEqual(len(changes), 1)
        notify_priv = self.smb_conn.notify(fnum=monitor_priv_fnum,
                                           buffer_size=0xffff,
                                           completion_filter=libsmb.FILE_NOTIFY_CHANGE_ALL,
                                           recursive=True)

        # check that the unprivileged user does not receives the changes
        self.smb_conn_unpriv.echo()
        changes = notify_unpriv.get_changes(wait=False)
        self.assertIsNone(changes)
        # and there's no additional change for the privileged user
        self.smb_conn.echo()
        changes = notify_priv.get_changes(wait=False)
        self.assertIsNone(changes)

        # trigger notification in the private dir
        self.smb_conn.rmdir(new_path)

        # check that only the privileged user received the changes
        changes = notify_priv.get_changes(wait=True)
        self.assertIsNotNone(changes)
        self.assertEqual(changes[0]['name'], new_rel)
        self.assertEqual(changes[0]['action'], libsmb.NOTIFY_ACTION_REMOVED)
        self.assertEqual(len(changes), 1)
        notify_priv = self.smb_conn.notify(fnum=monitor_priv_fnum,
                                           buffer_size=0xffff,
                                           completion_filter=libsmb.FILE_NOTIFY_CHANGE_ALL,
                                           recursive=True)

        # check that the unprivileged user does not receives the changes
        self.smb_conn_unpriv.echo()
        changes = notify_unpriv.get_changes(wait=False)
        self.assertIsNone(changes)
        # and there's no additional change for the privileged user
        self.smb_conn.echo()
        changes = notify_priv.get_changes(wait=False)
        self.assertIsNone(changes)

        # trigger notification for both
        self.smb_conn.rmdir(private_path)

        # check that both get thte notification
        changes = notify_unpriv.get_changes(wait=True)
        self.assertIsNotNone(changes)
        self.assertEqual(changes[0]['name'], private_rel)
        self.assertEqual(changes[0]['action'], libsmb.NOTIFY_ACTION_REMOVED)
        self.assertEqual(len(changes), 1)
        notify_unpriv = self.smb_conn_unpriv.notify(fnum=monitor_unpriv_fnum,
                                                    buffer_size=0xffff,
                                                    completion_filter=libsmb.FILE_NOTIFY_CHANGE_ALL,
                                                    recursive=True)
        changes = notify_priv.get_changes(wait=True)
        self.assertIsNotNone(changes)
        self.assertEqual(changes[0]['name'], private_rel)
        self.assertEqual(changes[0]['action'], libsmb.NOTIFY_ACTION_REMOVED)
        self.assertEqual(len(changes), 1)
        notify_priv = self.smb_conn.notify(fnum=monitor_priv_fnum,
                                           buffer_size=0xffff,
                                           completion_filter=libsmb.FILE_NOTIFY_CHANGE_ALL,
                                           recursive=True)

        # check that the unprivileged user does not receives the changes
        self.smb_conn_unpriv.echo()
        changes = notify_unpriv.get_changes(wait=False)
        self.assertIsNone(changes)
        # and there's no additional change for the privileged user
        self.smb_conn.echo()
        changes = notify_priv.get_changes(wait=False)
        self.assertIsNone(changes)

        # closing the handle on will trigger a NOTIFY_CLEANUP
        self.smb_conn_unpriv.close(monitor_unpriv_fnum)
        try:
            changes = notify_unpriv.get_changes(wait=True)
            self.fail()
        except samba.NTSTATUSError as err:
            self.assertEqual(err.args[0], NT_STATUS_NOTIFY_CLEANUP)

        # there's no additional change for the privileged user
        self.smb_conn.echo()
        changes = notify_priv.get_changes(wait=False)
        self.assertIsNone(changes)

        # closing the handle on will trigger a NOTIFY_CLEANUP
        self.smb_conn.close(monitor_priv_fnum)
        try:
            changes = notify_priv.get_changes(wait=True)
            self.fail()
        except samba.NTSTATUSError as err:
            self.assertEqual(err.args[0], NT_STATUS_NOTIFY_CLEANUP)