Coverage for /private/tmp/im/impacket/impacket/ldap/ldaptypes.py : 43%

Hot-keys on this page
r m x p toggle line displays
j k next/prev highlighted chunk
0 (zero) top of page
1 (one) first highlighted chunk
# SECUREAUTH LABS. Copyright 2018 SecureAuth Corporation. All rights reserved. # # This software is provided under under a slightly modified version # of the Apache Software License. See the accompanying LICENSE file # for more information. # # Structures and types used in LDAP # Contains the Structures for the NT Security Descriptor (non-RPC format) and # all ACL related structures # # Author: # Dirk-jan Mollema (@_dirkjan) / Fox-IT (https://www.fox-it.com) # #
# Global constant if the library should recalculate ACE sizes in objects that are decoded/re-encoded. # This defaults to True, but this causes the ACLs to not match on a binary level # since Active Directory for some reason sometimes adds null bytes to the end of ACEs. # This is valid according to the spec (see 2.4.4), but since impacket encodes them more efficiently # this should be turned off if running unit tests.
# LDAP SID structure - based on SAMR_RPC_SID, except the SubAuthority is LE here ('Value','6s'), )
('Revision','<B'), ('SubAuthorityCount','<B'), ('IdentifierAuthority',':',LDAP_SID_IDENTIFIER_AUTHORITY), ('SubLen','_-SubAuthority','self["SubAuthorityCount"]*4'), ('SubAuthority',':'), )
ans = 'S-%d-%d' % (self['Revision'], ord(self['IdentifierAuthority']['Value'][5:6])) for i in range(self['SubAuthorityCount']): ans += '-%d' % ( unpack('<L',self['SubAuthority'][i*4:i*4+4])[0]) return ans
items = canonical.split('-') self['Revision'] = int(items[1]) self['IdentifierAuthority'] = LDAP_SID_IDENTIFIER_AUTHORITY() self['IdentifierAuthority']['Value'] = b'\x00\x00\x00\x00\x00' + pack('B',int(items[2])) self['SubAuthorityCount'] = len(items) - 3 self['SubAuthority'] = b'' for i in range(self['SubAuthorityCount']): self['SubAuthority'] += pack('<L', int(items[i+3]))
""" Self-relative security descriptor as described in 2.4.6 https://msdn.microsoft.com/en-us/library/cc230366.aspx """ ('Revision','c'), ('Sbz1','c'), ('Control','<H'), ('OffsetOwner','<L'), ('OffsetGroup','<L'), ('OffsetSacl','<L'), ('OffsetDacl','<L'), ('Sacl',':'), ('Dacl',':'), ('OwnerSid',':'), ('GroupSid',':'), )
Structure.fromString(self, data) # All these fields are optional, if the offset is 0 they are empty # there are also flags indicating if they are present # TODO: parse those if it adds value if self['OffsetOwner'] != 0: self['OwnerSid'] = LDAP_SID(data=data[self['OffsetOwner']:]) else: self['OwnerSid'] = b''
if self['OffsetGroup'] != 0: self['GroupSid'] = LDAP_SID(data=data[self['OffsetGroup']:]) else: self['GroupSid'] = b''
if self['OffsetSacl'] != 0: self['Sacl'] = ACL(data=data[self['OffsetSacl']:]) else: self['Sacl'] = b''
if self['OffsetDacl'] != 0: self['Dacl'] = ACL(data=data[self['OffsetDacl']:]) else: self['Sacl'] = b''
headerlen = 20 # Reconstruct the security descriptor # flags are currently not set automatically # TODO: do this? datalen = 0 if self['Sacl'] != b'': self['OffsetSacl'] = headerlen + datalen datalen += len(self['Sacl'].getData()) else: self['OffsetSacl'] = 0
if self['Dacl'] != b'': self['OffsetDacl'] = headerlen + datalen datalen += len(self['Dacl'].getData()) else: self['OffsetDacl'] = 0
if self['OwnerSid'] != b'': self['OffsetOwner'] = headerlen + datalen datalen += len(self['OwnerSid'].getData()) else: self['OffsetOwner'] = 0
if self['GroupSid'] != b'': self['OffsetGroup'] = headerlen + datalen datalen += len(self['GroupSid'].getData()) else: self['OffsetGroup'] = 0 return Structure.getData(self)
""" ACE as described in 2.4.4 https://msdn.microsoft.com/en-us/library/cc230295.aspx """ # Flag constants
# # ACE_HEADER as described in 2.4.4.1 # https://msdn.microsoft.com/en-us/library/cc230296.aspx # ('AceType','B'), ('AceFlags','B'), ('AceSize','<H'), # Virtual field to calculate data length from AceSize ('AceLen', '_-Ace', 'self["AceSize"]-4'), # # ACE body, is parsed depending on the type # ('Ace',':') )
# This will parse the header Structure.fromString(self, data) # Now we parse the ACE body according to its type self['TypeName'] = ACE_TYPE_MAP[self['AceType']].__name__ self['Ace'] = ACE_TYPE_MAP[self['AceType']](data=self['Ace'])
if RECALC_ACE_SIZE or 'AceSize' not in self.fields: self['AceSize'] = len(self['Ace'].getData())+4 # Header size (4 bytes) is included if self['AceSize'] % 4 != 0: # Make sure the alignment is correct self['AceSize'] += self['AceSize'] % 4 data = Structure.getData(self) # For some reason ACEs are sometimes longer than they need to be # we fill this space up with null bytes to make sure the object # we create is identical to the original object if len(data) < self['AceSize']: data += '\x00' * (self['AceSize'] - len(data)) return data
return self['AceFlags'] & flag == flag
""" ACCESS_MASK as described in 2.4.3 https://msdn.microsoft.com/en-us/library/cc230294.aspx """ # Flag constants
('Mask', '<L'), )
return self['Mask'] & priv == priv
self['Mask'] |= priv
self['Mask'] ^= priv
""" ACCESS_ALLOWED_ACE as described in 2.4.4.2 https://msdn.microsoft.com/en-us/library/cc230286.aspx """ ('Mask', ':', ACCESS_MASK), ('Sid', ':', LDAP_SID) )
""" ACCESS_ALLOWED_OBJECT_ACE as described in 2.4.4.3 https://msdn.microsoft.com/en-us/library/cc230289.aspx """
# Flag contstants
# ACE type specific mask constants # Note that while not documented, these also seem valid # for ACCESS_ALLOWED_ACE types
('Mask', ':', ACCESS_MASK), ('Flags', '<L'), # Optional field ('ObjectTypeLen','_-ObjectType','self.checkObjectType(self["Flags"])'), ('ObjectType', ':=""'), # Optional field ('InheritedObjectTypeLen','_-InheritedObjectType','self.checkInheritedObjectType(self["Flags"])'), ('InheritedObjectType', ':=""'), ('Sid', ':', LDAP_SID) )
def checkInheritedObjectType(flags): if flags & ACCESS_ALLOWED_OBJECT_ACE.ACE_INHERITED_OBJECT_TYPE_PRESENT: return 16 return 0
def checkObjectType(flags): if flags & ACCESS_ALLOWED_OBJECT_ACE.ACE_OBJECT_TYPE_PRESENT: return 16 return 0
# Set the correct flags if self['ObjectType'] != b'': self['Flags'] |= self.ACE_OBJECT_TYPE_PRESENT if self['InheritedObjectType'] != b'': self['Flags'] |= self.ACE_INHERITED_OBJECT_TYPE_PRESENT return Structure.getData(self)
return self['Flags'] & flag == flag
""" ACCESS_DENIED_ACE as described in 2.4.4.4 https://msdn.microsoft.com/en-us/library/cc230291.aspx Structure is identical to ACCESS_ALLOWED_ACE """
""" ACCESS_DENIED_OBJECT_ACE as described in 2.4.4.5 https://msdn.microsoft.com/en-us/library/gg750297.aspx Structure is identical to ACCESS_ALLOWED_OBJECT_ACE """
""" ACCESS_ALLOWED_CALLBACK_ACE as described in 2.4.4.6 https://msdn.microsoft.com/en-us/library/cc230287.aspx """ ('Mask', ':', ACCESS_MASK), ('Sid', ':', LDAP_SID), ('ApplicationData', ':') )
""" ACCESS_DENIED_OBJECT_ACE as described in 2.4.4.7 https://msdn.microsoft.com/en-us/library/cc230292.aspx Structure is identical to ACCESS_ALLOWED_CALLBACK_ACE """
""" ACCESS_ALLOWED_CALLBACK_OBJECT_ACE as described in 2.4.4.8 https://msdn.microsoft.com/en-us/library/cc230288.aspx """ ('Mask', ':', ACCESS_MASK), ('Flags', '<L'), # Optional field ('ObjectTypeLen','_-ObjectType','self.checkObjectType(self["Flags"])'), ('ObjectType', ':=""'), # Optional field ('InheritedObjectTypeLen','_-InheritedObjectType','self.checkInheritedObjectType(self["Flags"])'), ('InheritedObjectType', ':=""'), ('Sid', ':', LDAP_SID), ('ApplicationData', ':') )
""" ACCESS_DENIED_CALLBACK_OBJECT_ACE as described in 2.4.4.7 https://msdn.microsoft.com/en-us/library/cc230292.aspx Structure is identical to ACCESS_ALLOWED_OBJECT_OBJECT_ACE """
""" SYSTEM_AUDIT_ACE as described in 2.4.4.10 https://msdn.microsoft.com/en-us/library/cc230376.aspx Structure is identical to ACCESS_ALLOWED_ACE """
""" SYSTEM_AUDIT_OBJECT_ACE as described in 2.4.4.11 https://msdn.microsoft.com/en-us/library/gg750298.aspx Structure is identical to ACCESS_ALLOWED_CALLBACK_OBJECT_ACE """
""" SYSTEM_AUDIT_CALLBACK_ACE as described in 2.4.4.12 https://msdn.microsoft.com/en-us/library/cc230377.aspx Structure is identical to ACCESS_ALLOWED_CALLBACK_ACE """
""" SYSTEM_AUDIT_CALLBACK_ACE as described in 2.4.4.13 https://msdn.microsoft.com/en-us/library/cc230379.aspx Structure is identical to ACCESS_ALLOWED_ACE, but with custom masks and meanings. Lets keep it separate for now """ ('Mask', ':', ACCESS_MASK), ('Sid', ':', LDAP_SID) )
""" SYSTEM_AUDIT_CALLBACK_ACE as described in 2.4.4.14 https://msdn.microsoft.com/en-us/library/cc230378.aspx Structure is identical to ACCESS_ALLOWED_CALLBACK_OBJECT_ACE """
""" SYSTEM_RESOURCE_ATTRIBUTE_ACE as described in 2.4.4.15 https://msdn.microsoft.com/en-us/library/hh877837.aspx Structure is identical to ACCESS_ALLOWED_CALLBACK_ACE The application data however is encoded in CLAIM_SECURITY_ATTRIBUTE_RELATIVE_V1 format as described in section 2.4.10.1 Todo: implement this substructure if needed """
""" SYSTEM_SCOPED_POLICY_ID_ACE as described in 2.4.4.16 https://msdn.microsoft.com/en-us/library/hh877846.aspx Structure is identical to ACCESS_ALLOWED_ACE The Sid data MUST match a CAPID of a CentralAccessPolicy contained in the CentralAccessPoliciesList Todo: implement this substructure if needed Also the ACCESS_MASK must always be 0 """
# All the ACE types in a list ACCESS_ALLOWED_ACE, ACCESS_ALLOWED_OBJECT_ACE, ACCESS_DENIED_ACE, ACCESS_DENIED_OBJECT_ACE, ACCESS_ALLOWED_CALLBACK_ACE, ACCESS_DENIED_CALLBACK_ACE, ACCESS_ALLOWED_CALLBACK_OBJECT_ACE, ACCESS_DENIED_CALLBACK_OBJECT_ACE, SYSTEM_AUDIT_ACE, SYSTEM_AUDIT_OBJECT_ACE, SYSTEM_AUDIT_CALLBACK_ACE, SYSTEM_MANDATORY_LABEL_ACE, SYSTEM_AUDIT_CALLBACK_OBJECT_ACE, SYSTEM_RESOURCE_ATTRIBUTE_ACE, SYSTEM_SCOPED_POLICY_ID_ACE ]
# A dict of all the ACE types indexed by their type number
""" ACL as described in 2.4.5 https://msdn.microsoft.com/en-us/library/cc230297.aspx """ ('AclRevision', 'B'), ('Sbz1', 'B'), ('AclSize', '<H'), ('AceCount', '<H'), ('Sbz2', '<H'), # Virtual field to calculate data length from AclSize ('DataLen', '_-Data', 'self["AclSize"]-8'), ('Data', ':'), )
self.aces = [] Structure.fromString(self, data) for i in range(self['AceCount']): # If we don't have any data left, return if len(self['Data']) == 0: raise Exception("ACL header indicated there are more ACLs to unpack, but there is no more data") ace = ACE(data=self['Data']) self.aces.append(ace) self['Data'] = self['Data'][ace['AceSize']:] self['Data'] = self.aces
self['AceCount'] = len(self.aces) # We modify the data field to be able to use the # parent class parsing self['Data'] = b''.join([ace.getData() for ace in self.aces]) self['AclSize'] = len(self['Data'])+8 # Header size (8 bytes) is included data = Structure.getData(self) # Put the ACEs back in data self['Data'] = self.aces return data
""" objectClass mapping to GUID for some common classes (index is the ldapDisplayName). Reference: https://msdn.microsoft.com/en-us/library/ms680938(v=vs.85).aspx Can also be queried from the Schema """ b'group': 'bf967a9c-0de6-11d0-a285-00aa003049e2', b'domain': '19195a5a-6da0-11d0-afd3-00c04fd930c9', b'organizationalUnit': 'bf967aa5-0de6-11d0-a285-00aa003049e2', b'user': 'bf967aba-0de6-11d0-a285-00aa003049e2', b'groupPolicyContainer': 'f30e3bc2-9ff0-11d1-b603-0000f80367c1' } |