|
|
# coding=utf-8
|
|
|
#
|
|
|
# Copyright (C) 2009-2021 Splunk Inc. All Rights Reserved.
|
|
|
|
|
|
from __future__ import absolute_import, division, print_function, unicode_literals
|
|
|
|
|
|
import itertools
|
|
|
import struct
|
|
|
|
|
|
from .six import text_type, PY3
|
|
|
from .six.moves import range, map
|
|
|
|
|
|
|
|
|
# References:
|
|
|
# 1. [Security Descriptor String Format](http://goo.gl/4IEHBc).
|
|
|
# 2. [ACE header](http://goo.gl/v8O4aG).
|
|
|
# 3. [ACE strings](http://goo.gl/Y10RdI).
|
|
|
# 4. [Object-specific ACEs](http://goo.gl/gnrgnY).
|
|
|
# 5. [SID String Format Syntax](http://goo.gl/itojP1)
|
|
|
# 6. [Microsoft Windows SDK 8.1](http://goo.gl/FWc2Ay), especially sddl.h and winnt.h.
|
|
|
# 7. [Operational attributes](http://goo.gl/mlX0GW)
|
|
|
# 8. [RFC 3673: Lightweight Directory Access Protocol version 3 (LDAPv3): All Operational Attributes](http://goo.gl/aOawGy).
|
|
|
|
|
|
_ace_type_strings = {
|
|
|
|
|
|
# Numeric keys are defined in winnt.h and string values are defined in sddl.h
|
|
|
|
|
|
# Documented at [ACE strings](http://goo.gl/Y10RdI)
|
|
|
0x00: 'A', # ACCESS_ALLOWED_ACE_TYPE => SDDL_ACCESS_ALLOWED
|
|
|
0x01: 'D', # ACCESS_DENIED_ACE_TYPE => SDDL_ACCESS_DENIED
|
|
|
0x05: 'OA', # ACCESS_ALLOWED_OBJECT_ACE_TYPE => SDDL_OBJECT_ACCESS_ALLOWED
|
|
|
0x06: 'OD', # ACCESS_DENIED_OBJECT_ACE_TYPE => SDDL_OBJECT_ACCESS_DENIED
|
|
|
0x02: 'AU', # SYSTEM_AUDIT_ACE_TYPE => SDDL_AUDIT
|
|
|
0x03: 'AL', # SYSTEM_ALARM_ACE_TYPE => SDDL_ALARM
|
|
|
0x07: 'OU', # SYSTEM_AUDIT_OBJECT_ACE_TYPE => SDDL_OBJECT_AUDIT
|
|
|
0x08: 'OL', # SYSTEM_ALARM_OBJECT_ACE_TYPE => SDDL_OBJECT_ALARM
|
|
|
0x11: 'ML', # SYSTEM_MANDATORY_LABEL_ACE_TYPE
|
|
|
0x09: 'XA', # ACCESS_ALLOWED_CALLBACK_ACE_TYPE => SDDL_CALLBACK_ACCESS_ALLOWED
|
|
|
0x0A: 'XD', # ACCESS_DENIED_CALLBACK_ACE_TYPE => ACCESS_DENIED_CALLBACK_ACE_TYPE
|
|
|
0x12: 'RA', # SYSTEM_RESOURCE_ATTRIBUTE_ACE_TYPE => SDDL_RESOURCE_ATTRIBUTE
|
|
|
0x13: 'SP', # SYSTEM_SCOPED_POLICY_ID_ACE_TYPE => SDDL_SCOPED_POLICY_ID
|
|
|
0x0D: 'XU', # SYSTEM_AUDIT_CALLBACK_ACE_TYPE => SDDL_CALLBACK_AUDIT
|
|
|
0x0B: 'ZA', # ACCESS_ALLOWED_CALLBACK_OBJECT_ACE_TYPE => SDDL_CALLBACK_OBJECT_ACCESS_ALLOWED
|
|
|
0x0C: 'ZD', # ACCESS_DENIED_CALLBACK_OBJECT_ACE_TYPE => SDDL_CALLBACK_OBJECT_ACCESS_DENIED
|
|
|
|
|
|
# Documented at [ACE_HEADER](http://goo.gl/v8O4aG)
|
|
|
|
|
|
0x04: '', # Reserved for future use: ACCESS_ALLOWED_COMPOUND_ACE_TYPE
|
|
|
0x0E: '', # Reserved for future use: SYSTEM_ALARM_CALLBACK_ACE_TYPE
|
|
|
0x10: '', # Reserved for future use: SYSTEM_ALARM_CALLBACK_OBJECT_ACE_TYPE =>
|
|
|
|
|
|
0x0F: '', # SYSTEM_AUDIT_CALLBACK_OBJECT_ACE_TYPE:
|
|
|
# Object-specific system-audit callback ACE that uses the SYSTEM_AUDIT_CALLBACK_OBJECT_ACE:
|
|
|
}
|
|
|
|
|
|
_attribute_syntaxes = { # Attribute oMSyntax map
|
|
|
# Syntax attributeSyntax ASN 1-Encoded OID Description
|
|
|
'1': 'Boolean', # 2.5.5.8 \x550508 TRUE or FALSE values.
|
|
|
'2': 'Integer', # 2.5.5.9 \x550509 A 32-bit number.
|
|
|
'4': 'String(Octet)', # 2.5.5.10 \x55050A A string of bytes (Octet).
|
|
|
'6': 'String(Object-Identifier)', # 2.5.5.2 \x550502 The object identifier.
|
|
|
'10': 'Enumeration', # 2.5.5.9 \x550509 A 32-bit enumeration.
|
|
|
'18': 'String(Numeric)', # 2.5.5.6 \x550506 A sequence of digits.
|
|
|
'19': 'String(Printable)', # 2.5.5.5 \x550505 Printable case-sensitive string.
|
|
|
'20': 'CaseIgnoreString(Teletex)', # 2.5.5.4 \x550504 Teletex. Does not differentiate upper case
|
|
|
# and lowercase.
|
|
|
'22': 'String(IA5)', # 2.5.5.5 \x550505 IA5-String. Character set is case-
|
|
|
# sensitive.
|
|
|
'23': 'String(UTC-Time)', # 2.5.5.11 \x55050B UTC Time.
|
|
|
'24': 'String(Generalized-Time)', # 2.5.5.11 \x55050B Generalized-Time.
|
|
|
'27': 'Case-Sensitive String', # 2.5.5.3 \x550503 General String. Differentiates uppercase
|
|
|
# and lowercase.
|
|
|
'64': 'String(Unicode)', # 2.5.5.12 \x55050C Unicode string.
|
|
|
'65': 'LargeInteger', # 2.5.5.16 \x550510 A 64-bit number.
|
|
|
'66': 'String(NT-Sec-Desc)', # 2.5.5.15 \x55050F A Microsoft® Windows NT® Security
|
|
|
# descriptor.
|
|
|
'127': 'Object' # 2.5.5.1 \x550501 The fully qualified name of an object in
|
|
|
# the directory.
|
|
|
# 2.5.5.7 \x550507 A distinguished name plus a binary large
|
|
|
# object.
|
|
|
# 2.5.5.13 \x55050D Presentation address.
|
|
|
# 2.5.5.14 \x55050E A DN-String plus a Unicode string.
|
|
|
}
|
|
|
|
|
|
_object_specific_ace_types = {
|
|
|
|
|
|
0x05, # ACCESS_ALLOWED_OBJECT_ACE_TYPE
|
|
|
# Used in a DACL to allow a trustee access to a property or property set on the object, or to limit ACE
|
|
|
# inheritance to a specified type of child object.
|
|
|
|
|
|
0x06, # ACCESS_DENIED_OBJECT_ACE_TYPE
|
|
|
# Used in a DACL to deny a trustee access to a property or property set on the object, or to limit ACE
|
|
|
# inheritance to a specified type of child object.
|
|
|
|
|
|
0x07, # SYSTEM_AUDIT_OBJECT_ACE_TYPE
|
|
|
# Used in a SACL to log a trustee's attempts to access a property or property set on the object, or to limit
|
|
|
# ACE inheritance to a specified type of child object.
|
|
|
}
|
|
|
|
|
|
_well_known_sid_strings = {
|
|
|
|
|
|
0x00000007: 'AN', # SDDL_ANONYMOUS
|
|
|
# Anonymous logon. The corresponding RID is SECURITY_ANONYMOUS_LOGON_RID.
|
|
|
0x00000224: 'AO', # SDDL_ACCOUNT_OPERATORS
|
|
|
# Account operators. The corresponding RID is DOMAIN_ALIAS_RID_ACCOUNT_OPS.
|
|
|
0x0000000B: 'AU', # SDDL_AUTHENTICATED_USERS
|
|
|
# Authenticated users. The corresponding RID is SECURITY_AUTHENTICATED_USER_RID.
|
|
|
0x00000220: 'BA', # SDDL_BUILTIN_ADMINISTRATORS
|
|
|
# Built-in administrators. The corresponding RID is DOMAIN_ALIAS_RID_ADMINS.
|
|
|
0x00000222: 'BG', # SDDL_BUILTIN_GUESTS
|
|
|
# Built-in guests. The corresponding RID is DOMAIN_ALIAS_RID_GUESTS.
|
|
|
0x00000227: 'BO', # SDDL_BACKUP_OPERATORS
|
|
|
# Backup operators. The corresponding RID is DOMAIN_ALIAS_RID_BACKUP_OPS.
|
|
|
0x00000221: 'BU', # SDDL_BUILTIN_USERS
|
|
|
# Built-in users. The corresponding RID is DOMAIN_ALIAS_RID_USERS.
|
|
|
0x00000205: 'CA', # SDDL_CERT_SERV_ADMINISTRATORS
|
|
|
# Certificate publishers. The corresponding RID is DOMAIN_GROUP_RID_CERT_ADMINS.
|
|
|
0x0000023E: 'CD', # SDDL_CERTSVC_DCOM_ACCESS
|
|
|
# Users who can connect to certification authorities using Distributed Component Object Model
|
|
|
# (DCOM). The corresponding RID is DOMAIN_ALIAS_RID_CERTSVC_DCOM_ACCESS_GROUP.
|
|
|
0x00000001: 'CG', # SDDL_CREATOR_GROUP
|
|
|
# Creator group. The corresponding RID is SECURITY_CREATOR_GROUP_RID.
|
|
|
0x00000200: 'DA', # SDDL_DOMAIN_ADMINISTRATORS
|
|
|
# Domain administrators. The corresponding RID is DOMAIN_GROUP_RID_ADMINS.
|
|
|
0x00000203: 'DC', # SDDL_DOMAIN_COMPUTERS
|
|
|
# Domain computers. The corresponding RID is DOMAIN_GROUP_RID_COMPUTERS.
|
|
|
0x00000204: 'DD', # SDDL_DOMAIN_DOMAIN_CONTROLLERS
|
|
|
# Domain controllers. The corresponding RID is DOMAIN_GROUP_RID_CONTROLLERS.
|
|
|
0x00000202: 'DG', # SDDL_DOMAIN_GUESTS
|
|
|
# Domain guests. The corresponding RID is DOMAIN_GROUP_RID_GUESTS.
|
|
|
0x00000201: 'DU', # SDDL_DOMAIN_USERS
|
|
|
# Domain users. The corresponding RID is DOMAIN_GROUP_RID_USERS.
|
|
|
0x00000207: 'EA', # SDDL_ENTERPRISE_ADMINS
|
|
|
# Enterprise administrators. The corresponding RID is DOMAIN_GROUP_RID_ENTERPRISE_ADMINS.
|
|
|
0x00000009: 'ED', # SDDL_ENTERPRISE_DOMAIN_CONTROLLERS
|
|
|
# Enterprise domain controllers. The corresponding RID is SECURITY_SERVER_LOGON_RID.
|
|
|
0x00003000: 'HI', # SDDL_ML_HIGH
|
|
|
# High integrity level. The corresponding RID is SECURITY_MANDATORY_HIGH_RID.
|
|
|
0x00000004: 'IU', # SDDL_INTERACTIVE
|
|
|
# Interactively logged-on user. This is a group identifier added to the token of a process when
|
|
|
# it was logged on interactively. The corresponding logon type is LOGON32_LOGON_INTERACTIVE. The
|
|
|
# corresponding RID is SECURITY_INTERACTIVE_RID.
|
|
|
0x000001F4: 'LA', # SDDL_LOCAL_ADMIN
|
|
|
# Local administrator. The corresponding RID is DOMAIN_USER_RID_ADMIN.
|
|
|
0x000001F5: 'LG', # SDDL_LOCAL_GUEST
|
|
|
# Local guest. The corresponding RID is DOMAIN_USER_RID_GUEST.
|
|
|
0x00000013: 'LS', # SDDL_LOCAL_SERVICE
|
|
|
# Local service account. The corresponding RID is SECURITY_LOCAL_SERVICE_RID.
|
|
|
0x00001000: 'LW', # SDDL_ML_LOW
|
|
|
# Low integrity level. The corresponding RID is SECURITY_MANDATORY_LOW_RID.
|
|
|
0x00002000: 'ME', # SDDL_MLMEDIUM
|
|
|
# Medium integrity level. The corresponding RID is SECURITY_MANDATORY_MEDIUM_RID.
|
|
|
0x0000022F: 'MU', # SDDL_PERFMON_USERS
|
|
|
# Performance Monitor users.
|
|
|
0x0000022C: 'NO', # SDDL_NETWORK_CONFIGURATION_OPS
|
|
|
# Network configuration operators. The corresponding RID is
|
|
|
# DOMAIN_ALIAS_RID_NETWORK_CONFIGURATION_OPS.
|
|
|
0x00000014: 'NS', # SDDL_NETWORK_SERVICE
|
|
|
# Network service account. The corresponding RID is SECURITY_NETWORK_SERVICE_RID.
|
|
|
0x00000002: 'NU', # SDDL_NETWORK
|
|
|
# Network logon user. This is a group identifier added to the token of a process when it was
|
|
|
# logged on across a network. The corresponding logon type is LOGON32_LOGON_NETWORK. The
|
|
|
# corresponding RID is SECURITY_NETWORK_RID.
|
|
|
0x00000208: 'PA', # SDDL_GROUP_POLICY_ADMINS
|
|
|
# Group Policy administrators. The corresponding RID is DOMAIN_GROUP_RID_POLICY_ADMINS.
|
|
|
0x00000226: 'PO', # SDDL_PRINTER_OPERATORS
|
|
|
# Printer operators. The corresponding RID is DOMAIN_ALIAS_RID_PRINT_OPS.
|
|
|
0x0000000A: 'PS', # SDDL_PERSONAL_SELF
|
|
|
# Principal self. The corresponding RID is SECURITY_PRINCIPAL_SELF_RID.
|
|
|
0x00000223: 'PU', # SDDL_POWER_USERS
|
|
|
# Power users. The corresponding RID is DOMAIN_ALIAS_RID_POWER_USERS.
|
|
|
0x0000000C: 'RC', # SDDL_RESTRICTED_CODE
|
|
|
# Restricted code. This is a restricted token created using the CreateRestrictedToken function.
|
|
|
# The corresponding RID is SECURITY_RESTRICTED_CODE_RID.
|
|
|
0x0000022B: 'RD', # SDDL_REMOTE_DESKTOP
|
|
|
# Terminal server users. The corresponding RID is DOMAIN_ALIAS_RID_REMOTE_DESKTOP_USERS.
|
|
|
0x00000228: 'RE', # SDDL_REPLICATOR
|
|
|
# Replicator. The corresponding RID is DOMAIN_ALIAS_RID_REPLICATOR.
|
|
|
0x000001F2: 'RO', # SDDL_ENTERPRISE_RO_DCs
|
|
|
# Enterprise Read-only domain controllers. The corresponding RID is
|
|
|
# DOMAIN_GROUP_RID_ENTERPRISE_READONLY_DOMAIN_CONTROLLERS.
|
|
|
0x00000229: 'RS', # SDDL_RAS_SERVERS
|
|
|
# RAS servers group. The corresponding RID is DOMAIN_ALIAS_RID_RAS_SERVERS.
|
|
|
0x0000022A: 'RU', # SDDL_ALIAS_PREW2KCOMPACC
|
|
|
# Alias to grant permissions to accounts that use applications compatible with operating systems
|
|
|
# previous to Windows 2000. The corresponding RID is DOMAIN_ALIAS_RID_PREW2KCOMPACCESS.
|
|
|
0x00000206: 'SA', # SDDL_SCHEMA_ADMINISTRATORS
|
|
|
# Schema administrators. The corresponding RID is DOMAIN_GROUP_RID_SCHEMA_ADMINS.
|
|
|
0x00004000: 'SI', # SDDL_ML_SYSTEM
|
|
|
# System integrity level. The corresponding RID is SECURITY_MANDATORY_SYSTEM_RID.
|
|
|
0x00000225: 'SO', # SDDL_SERVER_OPERATORS
|
|
|
# Server operators. The corresponding RID is DOMAIN_ALIAS_RID_SYSTEM_OPS.
|
|
|
0x00000006: 'SU', # SDDL_SERVICE
|
|
|
# Service logon user. This is a group identifier added to the token of a process when it was
|
|
|
# logged as a service. The corresponding logon type is LOGON32_LOGON_SERVICE. The corresponding
|
|
|
# RID is SECURITY_SERVICE_RID.
|
|
|
0x00000012: 'SY', # SDDL_LOCAL_SYSTEM
|
|
|
# Local system. The corresponding RID is SECURITY_LOCAL_SYSTEM_RID.
|
|
|
}
|
|
|
|
|
|
|
|
|
def format_acl(value, offset):
|
|
|
"""
|
|
|
:param value:
|
|
|
:param offset:
|
|
|
:return:
|
|
|
|
|
|
"""
|
|
|
acl_start = struct.unpack_from(b'I', value, offset)[0]
|
|
|
acl_size, ace_count = struct.unpack_from(b'HH', value, acl_start + 2)
|
|
|
ace_start = acl_start + 8
|
|
|
|
|
|
text = ''
|
|
|
|
|
|
for i in range(0, ace_count):
|
|
|
|
|
|
ace_type, ace_flags, ace_size, rights = struct.unpack_from(b'BBHI', value, ace_start)
|
|
|
ace_type_string = _ace_type_strings[ace_type]
|
|
|
|
|
|
ace_flags_string = ''.join((
|
|
|
'CI' if ace_flags & 0x02 else '', # CONTAINER_INHERIT_ACE => SDDL_CONTAINER_INHERIT
|
|
|
'OI' if ace_flags & 0x01 else '', # OBJECT_INHERIT_ACE => SDDL_OBJECT_INHERIT
|
|
|
'NP' if ace_flags & 0x04 else '', # NO_PROPAGATE_INHERIT_ACE => SDDL_NO_PROPAGATE
|
|
|
'IO' if ace_flags & 0x08 else '', # INHERIT_ONLY_ACE => SDDL_INHERIT_ONLY
|
|
|
'ID' if ace_flags & 0x10 else '', # INHERITED_ACE => SDDL_INHERITED
|
|
|
'SA' if ace_flags & 0x40 else '', # SUCCESSFUL_ACCESS_ACE_FLAG => SDDL_AUDIT_SUCCESS
|
|
|
'FA' if ace_flags & 0x80 else '', # FAILED_ACCESS_ACE_FLAG => SDDL_AUDIT_FAILURE
|
|
|
))
|
|
|
|
|
|
offset = ace_start + 8
|
|
|
|
|
|
if ace_type in _object_specific_ace_types:
|
|
|
object_guid = format_guid(value, offset)
|
|
|
offset += 16
|
|
|
inherit_object_guid = format_guid(value, offset)
|
|
|
offset += 16
|
|
|
else:
|
|
|
object_guid = inherit_object_guid = ''
|
|
|
|
|
|
account_sid = format_sid(value, offset, _well_known_sid_strings)
|
|
|
|
|
|
if account_sid == 'S-1-0-0':
|
|
|
account_sid = ''
|
|
|
|
|
|
offset += 16
|
|
|
|
|
|
if ace_type == 0x12: # SYSTEM_RESOURCE_ATTRIBUTE_ACE_TYPE
|
|
|
|
|
|
from base64 import b16encode
|
|
|
|
|
|
def unpack_null_terminated_utf16_string(string, start):
|
|
|
end = start
|
|
|
while struct.unpack_from(b'H', string, end) != 0:
|
|
|
pass
|
|
|
return '"' + text_type(struct.unpack_from(str(end - start) + 's', string, start)[0], 'utf-16') + '"'
|
|
|
|
|
|
def unpack_claim_security_attribute_type_int64(string, start):
|
|
|
return text_type(struct.unpack_from(b'l', string, start)[0])
|
|
|
|
|
|
def unpack_claim_security_attribute_type_uint64(string, start):
|
|
|
return text_type(struct.unpack_from(b'L', string, start)[0])
|
|
|
|
|
|
def unpack_claim_security_attribute_type_octet_string(string, start):
|
|
|
# See http://msdn.microsoft.com/en-us/library/windows/desktop/hh448485(v=vs.85).aspx
|
|
|
# TODO: Do not assume 64-bit octet offset as this code does
|
|
|
octet_offset, octet_length = struct.unpack_from(b'LL', string, start)
|
|
|
return b16encode((struct.unpack_from(str(octet_length) + 's', string, start)[0])).decode('utf-8')
|
|
|
|
|
|
def unpack_claim_security_attribute_type_sid(string, start):
|
|
|
# See http://msdn.microsoft.com/en-us/library/windows/desktop/hh448483(v=vs.85).aspx
|
|
|
# TODO: Do not assume a 64-bit name offset as this code does
|
|
|
octet_offset, name_length = struct.unpack_from(b'LL', string, start)
|
|
|
return format_sid(string, octet_offset)
|
|
|
|
|
|
claim_name_offset, claim_type, reserved, claim_flags, claim_count = struct.unpack_from(b'IHHII', value, offset)
|
|
|
offset += 16
|
|
|
|
|
|
claim_value_offsets = struct.unpack_from(str(claim_count) + 'I', value, offset)
|
|
|
claim_name = unpack_null_terminated_utf16_string(value, claim_name_offset)
|
|
|
|
|
|
if claim_type == 0x0001: # CLAIM_SECURITY_ATTRIBUTE_TYPE_INT64
|
|
|
claim_values = [unpack_claim_security_attribute_type_int64(value, x) for x in claim_value_offsets]
|
|
|
claim_type = 'TI'
|
|
|
elif claim_type == 0x02: # CLAIM_SECURITY_ATTRIBUTE_TYPE_UINT64
|
|
|
claim_values = [unpack_claim_security_attribute_type_uint64(value, x) for x in claim_value_offsets]
|
|
|
claim_type = 'TU'
|
|
|
elif claim_type == 0x03: # CLAIM_SECURITY_ATTRIBUTE_TYPE_STRING
|
|
|
claim_values = [unpack_null_terminated_utf16_string(value, x) for x in claim_value_offsets]
|
|
|
claim_type = 'TS'
|
|
|
elif claim_type == 0x05: # CLAIM_SECURITY_ATTRIBUTE_TYPE_SID
|
|
|
claim_values = [unpack_claim_security_attribute_type_octet_string(value, x) for x in claim_value_offsets]
|
|
|
claim_type = 'TD'
|
|
|
elif claim_type == 0x06: # CLAIM_SECURITY_ATTRIBUTE_TYPE_BOOLEAN
|
|
|
claim_values = [unpack_claim_security_attribute_type_uint64(value, x) for x in claim_value_offsets]
|
|
|
claim_type = 'TB'
|
|
|
elif claim_type == 0x10: # CLAIM_SECURITY_ATTRIBUTE_TYPE_OCTET_STRING
|
|
|
claim_values = [unpack_claim_security_attribute_type_octet_string(value, x) for x in claim_value_offsets]
|
|
|
claim_type = 'TX'
|
|
|
else:
|
|
|
# We should never reach this code
|
|
|
# TODO: log (?)
|
|
|
claim_values = ()
|
|
|
claim_type = ''
|
|
|
|
|
|
text += '(' + ';'.join(
|
|
|
(
|
|
|
ace_type_string,
|
|
|
ace_flags_string,
|
|
|
hex(rights),
|
|
|
object_guid,
|
|
|
inherit_object_guid,
|
|
|
account_sid,
|
|
|
'(' + ','.join(
|
|
|
itertools.chain((claim_name, claim_type, text_type(claim_flags)), claim_values)) + ')'
|
|
|
)) + ')'
|
|
|
else:
|
|
|
text += '(' + ';'.join(
|
|
|
(
|
|
|
ace_type_string,
|
|
|
ace_flags_string,
|
|
|
hex(rights),
|
|
|
object_guid,
|
|
|
inherit_object_guid,
|
|
|
account_sid
|
|
|
)) + ')'
|
|
|
|
|
|
ace_start += ace_size
|
|
|
|
|
|
return text
|
|
|
|
|
|
|
|
|
def format_attribute_syntax(value):
|
|
|
""" Converts an oMSyntax attribute value to an LDAP syntax name.
|
|
|
|
|
|
See :data:`attribute_syntaxes` and the MSDN article `LDAP Representations <http://goo.gl/tLZ68s>`_ for a description
|
|
|
of the LDAP syntaxes supported by Microsoft Active Directory.
|
|
|
|
|
|
:param value: Decimal string.
|
|
|
:type value: ``str``
|
|
|
:return: LDAP syntax name.
|
|
|
:rtype unicode:
|
|
|
|
|
|
"""
|
|
|
syntax_name = ' = '.join((value, _attribute_syntaxes.get(value, '')))
|
|
|
return syntax_name
|
|
|
|
|
|
|
|
|
def format_filetime(value):
|
|
|
""" Formats a time interval value as an ISO-8601 date/time string.
|
|
|
|
|
|
**Example:**
|
|
|
|
|
|
.. codeblock::PowerShell
|
|
|
$epochTime = New-Object 'System.DateTime' (1970, 1, 1)
|
|
|
"0x$($epochTime.ToFileTimeUtc().ToString('x8'))"
|
|
|
# Displays: 0x19db1ded53e8000
|
|
|
|
|
|
.. codeblock::python
|
|
|
app.format_time_interval(unicode(0x19db1ded53e8000), 0x))
|
|
|
# Displays: '1970-01-01T00:00:00Z'
|
|
|
|
|
|
**Example:**
|
|
|
|
|
|
.. codeblock::PowerShell
|
|
|
$dateTime = New-Object 'System.DateTime' (2014, 9, 23, 0, 17, 46, 67)
|
|
|
"0x$($dateTime.ToFileTimeUtc().ToString('x8'))"
|
|
|
# Displays: 0x1cfd6c3ccd76a30
|
|
|
|
|
|
.. codeblock::python
|
|
|
app.format_time_interval(unicode(0x1cfd6c3ccd76a30))
|
|
|
# Displays: '2014-09-23T00:17:46.067000Z'
|
|
|
|
|
|
**References:**
|
|
|
|
|
|
1. `Microsoft Windows FILETIME structure <http://goo.gl/dXwCCd>`_
|
|
|
2. `Microsoft Active Directory Interval syntax <http://goo.gl/MOX5ia>`_
|
|
|
|
|
|
"""
|
|
|
|
|
|
file_time = int(value)
|
|
|
|
|
|
if file_time in (0x0000000000000000, 0x7FFFFFFFFFFFFFFF):
|
|
|
return '(never)'
|
|
|
|
|
|
from datetime import datetime
|
|
|
|
|
|
epoch_time = 0x019db1ded53e8000
|
|
|
|
|
|
seconds, hundreds_of_nanoseconds = divmod(file_time - epoch_time, 10000000)
|
|
|
microseconds = hundreds_of_nanoseconds // 10
|
|
|
|
|
|
try:
|
|
|
dt = datetime.utcfromtimestamp(seconds)
|
|
|
except ValueError:
|
|
|
text = ''
|
|
|
else:
|
|
|
dt = dt.replace(microsecond=microseconds)
|
|
|
text = dt.isoformat() + 'Z'
|
|
|
|
|
|
return text
|
|
|
|
|
|
|
|
|
def format_group_type(value):
|
|
|
""" Converts the base 10 string representation of a 32-bit integer to a sorted list of `Group-Type` names.
|
|
|
|
|
|
:param unicode value: Base 10 string representation of a 32-bit integer.
|
|
|
:return list: Sorted list of `Group-Type` names.
|
|
|
|
|
|
**References:**
|
|
|
|
|
|
1. `Group-Type attribute <http://goo.gl/hxY43T>`_
|
|
|
|
|
|
"""
|
|
|
flags = int(value)
|
|
|
names = []
|
|
|
|
|
|
# Confirmed: These names are the same as displayed by Active Directory
|
|
|
#
|
|
|
# 1. BUILTIN_LOCAL_GROUP CN=Hyper-V Administrators,CN=Builtin,DC=msapps,DC=local
|
|
|
# 2. ACCOUNT_GROUP CN=DnsUpdateProxy,CN=Users,DC=msapps,DC=local
|
|
|
# 3. RESOURCE_GROUP CN=DHCP Administrators,CN=Users,DC=msapps,DC=local
|
|
|
# 4. UNIVERSAL_GROUP CN=Enterprise Admins,CN=Users,DC=msapps,DC=local
|
|
|
# 5. SECURITY_ENABLED CN=DHCP Administrators,CN=Users,DC=msapps,DC=local
|
|
|
#
|
|
|
# Unconfirmed but on the web you will find people using these names:
|
|
|
#
|
|
|
# 1. APP_BASIC_GROUP
|
|
|
# 2. APP_QUERY_GROUP
|
|
|
#
|
|
|
# See, for example, http://goo.gl/bReghZ.
|
|
|
|
|
|
if flags & 0x00000001: # Specifies a group that is created by the system.
|
|
|
names.append('BUILTIN_LOCAL_GROUP')
|
|
|
if flags & 0x00000002:
|
|
|
names.append('ACCOUNT_GROUP')
|
|
|
if flags & 0x00000004:
|
|
|
names.append('RESOURCE_GROUP')
|
|
|
if flags & 0x00000008:
|
|
|
names.append('UNIVERSAL_GROUP')
|
|
|
if flags & 0x00000010: # Specifies an APP_BASIC group for Windows Server Authorization Manager.
|
|
|
names.append('APP_BASIC_GROUP')
|
|
|
if flags & 0x00000020: # Specifies an APP_QUERY group for Windows Server Authorization Manager.
|
|
|
names.append('APP_QUERY_GROUP')
|
|
|
if flags & 0x80000000: # Specifies a security group. If this flag is not set, the group is a distribution group.
|
|
|
names.append('SECURITY_ENABLED')
|
|
|
|
|
|
names.sort()
|
|
|
return names
|
|
|
|
|
|
|
|
|
def format_guid(value, offset=0):
|
|
|
""" Converts the binary representation of a GUID structure to string form.
|
|
|
|
|
|
:param bytes value:
|
|
|
:return unicode:
|
|
|
|
|
|
"""
|
|
|
value = struct.unpack_from(b'I2H8B', value, offset)
|
|
|
text = '{0:08x}-{1:04x}-{2:04x}-{3:02x}{4:02x}-{5:02x}{6:02x}{7:02x}{8:02x}{9:02x}{10:02x}'.format(*value)
|
|
|
return text
|
|
|
|
|
|
|
|
|
def format_instance_type(value):
|
|
|
""" Converts the base 10 string representation of a 32-bit integer to a list of `Instance-Type` names.
|
|
|
|
|
|
:param unicode value: Base 10 string representation of a 32-bit integer.
|
|
|
:return list: Sorted list of `Instance-Type` names.
|
|
|
|
|
|
**References:**
|
|
|
|
|
|
1. `Instance-Type attribute <http://goo.gl/vv6wPM>`_
|
|
|
|
|
|
"""
|
|
|
|
|
|
flags = int(value)
|
|
|
names = []
|
|
|
|
|
|
# Confirmed: These are the same values as displayed by Active Directory:
|
|
|
#
|
|
|
# 1. IS_NC_HEAD DC=msapps,DC=local
|
|
|
# 2. WRITE CN=david-noble,OU=Staff,DC=msapps,DC=local
|
|
|
#
|
|
|
# Unconfirmed:
|
|
|
#
|
|
|
# 1. 0x02
|
|
|
# 2. NC_ABOVE Some evidence at http://goo.gl/rzBtFg
|
|
|
# 3. 0x10
|
|
|
# 4. 0x20
|
|
|
|
|
|
if flags & 0x00000001: # The head of naming context.
|
|
|
names.append('IS_NC_HEAD')
|
|
|
if flags & 0x00000002: # This replica is not instantiated.
|
|
|
names.append('0x02')
|
|
|
if flags & 0x00000004: # The object is writable on this directory.
|
|
|
names.append('WRITE')
|
|
|
if flags & 0x00000008: # The naming context above this one on this directory is held.
|
|
|
names.append('NC_ABOVE')
|
|
|
if flags & 0x00000010: # The naming context is under construction for the first time by replication.
|
|
|
names.append('0x10')
|
|
|
if flags & 0x00000020: # The naming context is in the process of being removed from the local DSA.
|
|
|
names.append('0x20')
|
|
|
|
|
|
names.sort()
|
|
|
return names
|
|
|
|
|
|
|
|
|
def format_sam_account_type(value):
|
|
|
""" Converts the base 10 string representation of a 32-bit integer to a `SAM-Account-Type` name sans `SAM_` prefix.
|
|
|
|
|
|
:param unicode value: Base 10 string representation of a 32-bit integer.
|
|
|
:return unicode: `SAM-Account-Type` name sans `SAM_` prefix.
|
|
|
|
|
|
**References:**
|
|
|
|
|
|
1. `SAM-Account-Type attribute <http://goo.gl/Aokhf>`_
|
|
|
2. `ACCOUNT_TYPE Values <http://goo.gl/rdM3dq>`_
|
|
|
|
|
|
"""
|
|
|
code = int(value)
|
|
|
|
|
|
# Confirmed: These names are as displayed by Active Directory:
|
|
|
#
|
|
|
# 1. ALIAS_OBJECT DHCP Administrators,CN=Users,DC=msapps,DC=local
|
|
|
# 2. GROUP_OBJECT CN=DnsUpdateProxy,CN=Users,DC=msapps,DC=local
|
|
|
# 3. MACHINE_ACCOUNT CN=EXCHANGE,CN=Computers,DC=msapps,DC=local
|
|
|
# 4. NORMAL_USER_ACCOUNT CN=Splunker,CN=Users,DC=msapps,DC=local
|
|
|
#
|
|
|
# Unconfirmed:
|
|
|
#
|
|
|
# 1. DOMAIN_OBJECT
|
|
|
# 2. NON_SECURITY_GROUP_OBJECT
|
|
|
# 3. NON_SECURITY_ALIAS_OBJECT
|
|
|
# 4. TRUST_ACCOUNT
|
|
|
# 5. APP_BASIC_GROUP
|
|
|
# 6. APP_QUERY_GROUP
|
|
|
|
|
|
if code == 0x0000000000:
|
|
|
name = 'DOMAIN_OBJECT'
|
|
|
elif code == 0x10000000:
|
|
|
name = 'GROUP_OBJECT'
|
|
|
elif code == 0x10000001:
|
|
|
name = 'NON_SECURITY_GROUP_OBJECT'
|
|
|
elif code == 0x20000000:
|
|
|
name = 'ALIAS_OBJECT'
|
|
|
elif code == 0x20000001:
|
|
|
name = 'NON_SECURITY_ALIAS_OBJECT'
|
|
|
elif code == 0x30000000:
|
|
|
name = 'NORMAL_USER_ACCOUNT'
|
|
|
elif code == 0x30000001:
|
|
|
name = 'MACHINE_ACCOUNT'
|
|
|
elif code == 0x30000002:
|
|
|
name = 'TRUST_ACCOUNT'
|
|
|
elif code == 0x40000000:
|
|
|
name = 'APP_BASIC_GROUP'
|
|
|
elif code == 0x40000001: # SAM_APP_QUERY_GROUP
|
|
|
name = 'APP_QUERY_GROUP'
|
|
|
else:
|
|
|
name = value
|
|
|
|
|
|
return name
|
|
|
|
|
|
|
|
|
def format_sid(value, offset=0, rid_map=None):
|
|
|
""" Converts a SID structure to a SID string.
|
|
|
|
|
|
:param bytes value: A byte buffer.
|
|
|
:param int offset: Offset of a SID structure within :paramref:`value`.
|
|
|
|
|
|
.. codeblock:: c
|
|
|
typedef struct _SID_IDENTIFIER_AUTHORITY {
|
|
|
BYTE Value[6];
|
|
|
} SID_IDENTIFIER_AUTHORITY,*PSID_IDENTIFIER_AUTHORITY,*LPSID_IDENTIFIER_AUTHORITY;
|
|
|
|
|
|
typedef struct _SID {
|
|
|
BYTE Revision;
|
|
|
BYTE SubAuthorityCount;
|
|
|
SID_IDENTIFIER_AUTHORITY IdentifierAuthority;
|
|
|
DWORD SubAuthority[ANYSIZE_ARRAY];
|
|
|
} SID, *PISID;
|
|
|
|
|
|
:return: String representation of the SID starting at `offset` within the `value` buffer. The string format of the
|
|
|
SID type is described in this MSDN article: `SID String Format Syntax <http://goo.gl/itojP1>`_.
|
|
|
|
|
|
"""
|
|
|
|
|
|
def unpack_identifier_authority():
|
|
|
triplet = struct.unpack_from(b'>3H', value, offset + 2)
|
|
|
result = triplet[2] + (triplet[1] << 16) + (triplet[0] << 32)
|
|
|
return result
|
|
|
|
|
|
revision, sub_authority_count = struct.unpack_from(b'BB', value, offset)
|
|
|
sub_authority_count &= 0xFF # upper nibble is reserved for future use
|
|
|
|
|
|
if rid_map is not None:
|
|
|
rid_offset = offset + 8 + 4 * (sub_authority_count - 1)
|
|
|
rid = struct.unpack_from(b'I', value, rid_offset)[0]
|
|
|
try:
|
|
|
if rid == 0x00000000 and sub_authority_count == 1:
|
|
|
identifier_authority = unpack_identifier_authority()
|
|
|
if identifier_authority == 1: # SECURITY_WORLD_SID_AUTHORITY
|
|
|
text = 'WD'
|
|
|
elif identifier_authority == 3: # SECURITY_CREATOR_SID_AUTHORITY
|
|
|
text = 'CO'
|
|
|
else:
|
|
|
text = '-'.join(('S', text_type(revision), text_type(identifier_authority), text_type(rid)))
|
|
|
else:
|
|
|
text = rid_map[rid]
|
|
|
return text
|
|
|
except KeyError:
|
|
|
pass
|
|
|
|
|
|
identifier_authority = unpack_identifier_authority()
|
|
|
sub_authorities = struct.unpack_from(str(sub_authority_count) + 'I', value, offset + 8)
|
|
|
|
|
|
text = '-'.join(itertools.chain(
|
|
|
(
|
|
|
'S',
|
|
|
text_type(revision),
|
|
|
text_type(identifier_authority) if identifier_authority < 0x100000000 else '{0:#014x}'.format(
|
|
|
identifier_authority)
|
|
|
),
|
|
|
map(lambda p: text_type(p), sub_authorities)))
|
|
|
|
|
|
return text
|
|
|
|
|
|
|
|
|
def format_security_descriptor(value):
|
|
|
""" Converts the binary representation of a Windows security descriptor to its string form.
|
|
|
|
|
|
This function uses the `Security Descriptor String Format <http://goo.gl/4IEHBc>`_ to represent security
|
|
|
descriptors.
|
|
|
|
|
|
:param value: The binary representation of a Windows security descriptor.
|
|
|
:return: String form of :paramref:`value`.
|
|
|
|
|
|
"""
|
|
|
start_owner, start_group = struct.unpack_from(b'II', value, 4)
|
|
|
text = ''
|
|
|
|
|
|
if start_owner:
|
|
|
text += 'O:' + format_sid(value, start_owner, _well_known_sid_strings)
|
|
|
|
|
|
if start_group:
|
|
|
text += 'G:' + format_sid(value, start_group, _well_known_sid_strings)
|
|
|
|
|
|
control = struct.unpack_from(b'H', value, 2)[0]
|
|
|
|
|
|
if control & 0x0004: # SE_DACL_PRESENT
|
|
|
text += 'D:'
|
|
|
if control & 0x1000: # SE_DACL_PROTECTED
|
|
|
text += 'P'
|
|
|
if control & 0x0100: # SE_DACL_AUTO_INHERIT_REQ
|
|
|
text += 'AR'
|
|
|
if control & 0x0400: # SE_DACL_AUTO_INHERITED:
|
|
|
text += 'AI'
|
|
|
text += format_acl(value, 16)
|
|
|
|
|
|
if control & 0x0010: # SE_SACL_PRESENT
|
|
|
text += 'S:'
|
|
|
if control & 0x2000: # SE_SACL_PROTECTED
|
|
|
text += 'P'
|
|
|
if control & 0x0200: # SE_SACL_AUTO_INHERIT_REQ
|
|
|
text += 'AR'
|
|
|
if control & 0x0800: # SE_SACL_AUTO_INHERITED:
|
|
|
text += 'AI'
|
|
|
text += format_acl(value, 12)
|
|
|
|
|
|
return text
|
|
|
|
|
|
|
|
|
def format_user_flag_enum(value):
|
|
|
""" Converts the base 10 string representation of a 32-bit integer to a list of ADS_USER_FLAG_ENUM values.
|
|
|
|
|
|
:param value: String representation of a 32-bit integer in base 10.
|
|
|
:return: Sorted list of ADS_USER_FLAG_ENUM values sans `ADS_UF_` prefix.
|
|
|
|
|
|
**References:**
|
|
|
|
|
|
1. `ADS_USER_FLAG_ENUM enumeration <http://goo.gl/LN1KMN>`_
|
|
|
2. `USER_INFO_1008 structure <http://goo.gl/opgkZW>`_
|
|
|
3. `User-Account-Control attribute <http://goo.gl/Uh9XUr>`_
|
|
|
4. `ms-DS-User-Account-Control-Computed attribute <http://goo.gl/puRXGs>`_
|
|
|
|
|
|
"""
|
|
|
flags = int(value)
|
|
|
names = []
|
|
|
|
|
|
# Well documented so confidence is high that these names are correct
|
|
|
|
|
|
# Zero or more these flags may be set
|
|
|
|
|
|
if flags & 0x0000001:
|
|
|
names.append('SCRIPT')
|
|
|
if flags & 0x0000002:
|
|
|
names.append('ACCOUNTDISABLE')
|
|
|
if flags & 0x0000008:
|
|
|
names.append('HOMEDIR_REQUIRED')
|
|
|
if flags & 0x0000010:
|
|
|
names.append('LOCKOUT')
|
|
|
if flags & 0x0000020:
|
|
|
names.append('PASSWD_NOTREQD')
|
|
|
if flags & 0x0000040:
|
|
|
names.append('PASSWD_CANT_CHANGE')
|
|
|
if flags & 0x0000080:
|
|
|
names.append('ENCRYPTED_TEXT_PASSWORD_ALLOWED')
|
|
|
if flags & 0x0010000:
|
|
|
names.append('DONT_EXPIRE_PASSWD')
|
|
|
if flags & 0x0020000:
|
|
|
names.append('MNS_LOGON_ACCOUNT')
|
|
|
if flags & 0x0040000:
|
|
|
names.append('SMARTCARD_REQUIRED')
|
|
|
if flags & 0x0080000:
|
|
|
names.append('TRUSTED_FOR_DELEGATION')
|
|
|
if flags & 0x0100000:
|
|
|
names.append('NOT_DELEGATED')
|
|
|
if flags & 0x0200000:
|
|
|
names.append('USE_DES_KEY_ONLY')
|
|
|
if flags & 0x0400000:
|
|
|
names.append('DONT_REQUIRE_PREAUTH')
|
|
|
if flags & 0x0800000:
|
|
|
names.append('PASSWORD_EXPIRED')
|
|
|
if flags & 0x1000000:
|
|
|
names.append('TRUSTED_TO_AUTHENTICATE_FOR_DELEGATION')
|
|
|
|
|
|
# Zero or one of these flags may be set
|
|
|
|
|
|
if flags & 0x000000100:
|
|
|
names.append('TEMP_DUPLICATE_ACCOUNT')
|
|
|
elif flags & 0x0000200:
|
|
|
names.append('NORMAL_ACCOUNT')
|
|
|
elif flags & 0x0001000:
|
|
|
names.append('WORKSTATION_TRUST_ACCOUNT')
|
|
|
elif flags & 0x0002000:
|
|
|
names.append('SERVER_TRUST_ACCOUNT')
|
|
|
elif flags & 0x0000800:
|
|
|
names.append('INTERDOMAIN_TRUST_ACCOUNT')
|
|
|
|
|
|
names.sort()
|
|
|
|
|
|
return names
|
|
|
|
|
|
def format_unicode(raw_value):
|
|
|
try:
|
|
|
if str is not bytes: # Python 3
|
|
|
return str(raw_value, 'utf-8', errors='strict')
|
|
|
else: # Python 2
|
|
|
return unicode(raw_value, 'utf-8', errors='strict')
|
|
|
except (TypeError, UnicodeDecodeError):
|
|
|
pass
|
|
|
|
|
|
return raw_value
|
|
|
|
|
|
|
|
|
formatting_extensions = {
|
|
|
|
|
|
# attributeId values
|
|
|
|
|
|
'1.2.840.113556.1.2.231': format_attribute_syntax, # oMSyntax
|
|
|
|
|
|
'1.2.840.113556.1.4.159': format_filetime, # Account-Expires
|
|
|
'1.2.840.113556.1.4.49': format_filetime, # Bad-Password-Time
|
|
|
'1.2.840.113556.1.4.13': format_filetime, # Builtin-Creation-Time
|
|
|
'1.2.840.113556.1.4.26': format_filetime, # Creation-Time
|
|
|
'1.2.840.113556.1.4.720': format_filetime, # dhcp-Update-Time
|
|
|
'1.2.840.113556.1.4.519': format_filetime, # Last-Backup-Restoration-Time
|
|
|
'1.2.840.113556.1.4.50': format_filetime, # Last-Content-Indexed
|
|
|
'1.2.840.113556.1.4.51': format_filetime, # Last-Logoff
|
|
|
'1.2.840.113556.1.4.52': format_filetime, # Last-Logon
|
|
|
'1.2.840.113556.1.4.1696': format_filetime, # Last-Logon-Timestamp
|
|
|
'1.2.840.113556.1.4.53': format_filetime, # Last-Set-Time
|
|
|
'1.2.840.113556.1.4.662': format_filetime, # Lockout-Time
|
|
|
'1.2.840.113556.1.4.66': format_filetime, # LSA-Creation-Time
|
|
|
'1.2.840.113556.1.4.2262': format_filetime, # ms-DS-Approximate-Last-Logon-Time-Stamp
|
|
|
'1.2.840.113556.1.4.1442': format_filetime, # ms-DS-Cached-Membership-Time-Stamp
|
|
|
'1.2.840.113556.1.4.1971': format_filetime, # ms-DS-Last-Failed-Interactive-Logon-Time
|
|
|
'1.2.840.113556.1.4.1970': format_filetime, # ms-DS-Last-Successful-Interactive-Logon-Time
|
|
|
'1.2.840.113556.1.4.1996': format_filetime, # ms-DS-User-Password-Expiry-Time-Computed
|
|
|
'1.2.840.113556.1.4.96': format_filetime, # Pwd-Last-Set
|
|
|
'1.2.840.113556.1.4.502': format_filetime, # Time-Vol-Change
|
|
|
|
|
|
'1.2.840.113556.1.4.750': format_group_type, # Group-Type
|
|
|
|
|
|
'1.2.840.113556.1.4.149': format_guid, # Attribute-Security-GUID
|
|
|
'1.2.840.113556.1.4.533': format_guid, # FRS-Replica-Set-GUID
|
|
|
'1.2.840.113556.1.4.43': format_guid, # FRS-Version-GUID
|
|
|
'1.2.840.113556.1.4.1428': format_guid, # ms-COM-ObjectId
|
|
|
'1.2.840.113556.1.4.2032': format_guid, # ms-DFS-Generation-GUID-v2
|
|
|
'1.2.840.113556.1.4.2041': format_guid, # ms-DFS-Link-Identity-GUID-v2
|
|
|
'1.2.840.113556.1.4.2033': format_guid, # ms-DFS-Namespace-Identity-GUID-v2
|
|
|
'1.2.840.113556.1.6.13.3.18': format_guid, # ms-DFSR-ContentSetGuid
|
|
|
'1.2.840.113556.1.6.13.3.23': format_guid, # ms-DFSR-ReplicationGroupGuid
|
|
|
'1.2.840.113556.1.4.1949': format_guid, # ms-DS-Az-Object-Guid
|
|
|
'1.2.840.113556.1.4.1360': format_guid, # MS-DS-Consistency-Guid
|
|
|
'1.2.840.113556.1.4.2062': format_guid, # ms-DS-Optional-Feature-GUID
|
|
|
'1.2.840.113556.1.4.1965': format_guid, # ms-FVE-RecoveryGuid
|
|
|
'1.2.840.113556.1.4.1998': format_guid, # ms-FVE-VolumeGuid
|
|
|
'1.2.840.113556.1.4.359': format_guid, # Netboot-GUID
|
|
|
'1.2.840.113556.1.4.2': format_guid, # Object-Guid
|
|
|
'1.2.840.113556.1.4.505': format_guid, # OMT-Guid
|
|
|
'1.2.840.113556.1.4.333': format_guid, # OMT-Indx-Guid
|
|
|
'1.2.840.113556.1.4.1224': format_guid, # Parent-GUID
|
|
|
'1.2.840.113556.1.4.205': format_guid, # PKT-Guid
|
|
|
'1.2.840.113556.1.4.148': format_guid, # Schema-ID-GUID
|
|
|
'1.2.840.113556.1.4.122': format_guid, # Service-Class-ID
|
|
|
'1.2.840.113556.1.4.362': format_guid, # Site-GUID
|
|
|
'1.2.840.113556.1.4.336': format_guid, # Vol-Table-GUID
|
|
|
'1.2.840.113556.1.4.334': format_guid, # Vol-Table-Idx-GUID
|
|
|
|
|
|
'1.2.840.113556.1.2.1': format_instance_type, # Instance-Type
|
|
|
|
|
|
'1.2.840.113556.1.4.302': format_sam_account_type, # SAM-Account-Type
|
|
|
|
|
|
'1.2.840.113556.1.4.2154': format_sid, # ms-Authz-Central-Access-Policy-ID
|
|
|
'1.2.840.113556.1.4.1410': format_sid, # MS-DS-Creator-SID
|
|
|
'1.2.840.113556.1.4.1844': format_sid, # ms-DS-Quota-Trustee
|
|
|
'1.2.840.113556.1.4.146': format_sid, # Object-Sid
|
|
|
'1.2.840.113556.1.4.121': format_sid, # Security-Identifier
|
|
|
'1.2.840.113556.1.4.609': format_sid, # SID-History
|
|
|
'1.2.840.113556.1.4.667': format_sid, # Sync-With-SID
|
|
|
'1.2.840.113556.1.4.1301': format_sid, # Token-Groups
|
|
|
'1.2.840.113556.1.4.1418': format_sid, # Token-Groups-Global-And-Universal
|
|
|
'1.2.840.113556.1.4.1303': format_sid, # Token-Groups-No-GC-Acceptable
|
|
|
|
|
|
'1.2.840.113556.1.4.8': format_user_flag_enum, # User-Account-Control
|
|
|
|
|
|
# formatter specially for msExchMailboxSecurityDescriptor
|
|
|
'1.2.840.113556.1.4.7000.102.80' : format_security_descriptor, # msExchMailboxSecurityDescriptor
|
|
|
|
|
|
# below formatters are present in standard formatter of ldap3 but for keeping the
|
|
|
# consistency in formatting with the previous versions, this formatters are added here.
|
|
|
'1.2.840.113556.1.4.903': format_unicode, # Object (DN-binary) - Microsoft
|
|
|
'1.2.840.113556.1.4.1221': format_unicode # Object (OR-name) - Microsoft
|
|
|
|
|
|
}
|