mirror of
https://github.com/rub-softsec/onelogon
synced 2026-06-27 13:00:05 +00:00
146 lines
7.3 KiB
Python
146 lines
7.3 KiB
Python
from termcolor import colored
|
|
|
|
|
|
NT35_BDC_CONTINUOUS_UPDATE = 0b10
|
|
RC4_SUPPORT = 0b100
|
|
BDC_HANDLING_CHANGELOGS = 0b10000
|
|
RESTARTING_FULL_DC_SYNC = 0b100000
|
|
NO_VALIDATION_LEVEL_2_FOR_NON_GENERIC_PASSTHROUGH = 0b10000000
|
|
DATABASE_REDO = 0b10000000
|
|
REFUSAL_OF_PASSWORD_CHANGES = 0b100000000
|
|
NETRLOGON_SEND_TO_SAM = 0b1000000000
|
|
GENERIC_PASS_THROUGH = 0b10000000000
|
|
CONCURRENT_RPC_CALLS = 0b100000000000
|
|
AVOID_USER_ACCOUNT_DATABASE_REPLICATION = 0b1000000000000
|
|
AVOID_SECURITY_AUTHORITY_DATABASE_REPLICATION = 0b10000000000000
|
|
STRONG_KEYS = 0b100000000000000
|
|
TRANSITIVE_TRUSTS = 0b1000000000000000
|
|
NETR_SERVER_PASSWORD_SET2 = 0b100000000000000000
|
|
NETR_LOGON_GET_DOMAIN_INFO = 0b1000000000000000000
|
|
CROSS_FOREST_TRUSTS = 0b10000000000000000000
|
|
NO_NT4_EMULATION = 0b100000000000000000000
|
|
RODC_PASS_THROUGH = 0b1000000000000000000000
|
|
AES_128_BIT_CFB_AND_SHA2 = 0b1000000000000000000000000
|
|
AUTHENTICATED_RPC_VIA_LSASS_SUPPORTED = 0b100000000000000000000000000000
|
|
SECURE_RPC_AUTHENTICATION = 0b1000000000000000000000000000000
|
|
KERBEROS_FOR_SECURE_CHANNEL_SETUP = 0b10000000000000000000000000000000
|
|
|
|
|
|
# 3.1.4.2 Netlogon Negotiate Options
|
|
class FLAGS:
|
|
def __init__(self, flag: int):
|
|
self.flag = flag
|
|
if flag < 0 or flag > 0xFFFFFFFF:
|
|
raise ValueError("Flags must be a 32-bit unsigned integer.")
|
|
|
|
self.flag_values = {
|
|
0b1: "A IGNORED (Account lockout)",
|
|
0b10: "B NT3.5 BDC continuous update",
|
|
0b100: "C RC4 support",
|
|
0b1000: "D IGNORED (Promotion count(deprecated))",
|
|
0b10000: "E Supports BDC handling Changelogs",
|
|
0b100000: "F Supports Restarting full DC sync",
|
|
0b1000000: "G Does not require ValidationLevel 2 for nongeneric passthrough",
|
|
0b10000000: "H Supports DatabaseRedo",
|
|
0b100000000: "I Supports refusal of password changes",
|
|
0b1000000000: "J Supports NetrLogonSendToSam",
|
|
0b10000000000: "K Supports generic pass-through",
|
|
0b100000000000: "L Supports concurrent RPC calls",
|
|
0b1000000000000: "M Supports avoid of user account database replication",
|
|
0b10000000000000: "N Supports avoid of Security Authority database replication",
|
|
0b100000000000000: "O Supports Strong keys",
|
|
0b1000000000000000: "P Supports transitive trusts",
|
|
0b10000000000000000: "Q IGNORED (Supports DNS trusts)",
|
|
0b100000000000000000: "R Supports NetrServerPasswordSet2",
|
|
0b1000000000000000000: "S Supports NetrLogonGetDomainInfo",
|
|
0b10000000000000000000: "T Supports cross-forest trusts",
|
|
0b100000000000000000000: "U No NT4 Emulation",
|
|
0b1000000000000000000000: "V Supports RODC pass-through",
|
|
0b10000000000000000000000: "0",
|
|
0b100000000000000000000000: "0",
|
|
0b1000000000000000000000000: "W Supports AES 128-bit CFB and SHA2",
|
|
0b10000000000000000000000000: "0",
|
|
0b100000000000000000000000000: "0",
|
|
0b1000000000000000000000000000: "0",
|
|
0b10000000000000000000000000000: "0",
|
|
0b100000000000000000000000000000: "X IGNORED (Authenticated RPC via lsass supported)",
|
|
0b1000000000000000000000000000000: "Y Supports secure RPC authentication",
|
|
0b10000000000000000000000000000000: "Z Supports Kerberos for secure channel setup",
|
|
}
|
|
|
|
def compare(self, other):
|
|
if not isinstance(other, FLAGS):
|
|
raise TypeError("Comparison is only supported with another FLAGS instance.")
|
|
if self.flag == other.flag:
|
|
return "Equal"
|
|
else:
|
|
out = "Self - Other - Difference:\n"
|
|
for i in range(1, 33):
|
|
if (self.flag & (1 << i)) != (other.flag & (1 << i)):
|
|
out += f"{(self.flag & (1 << i)) >> i} - {(other.flag & (1 << i)) >> i}: {self.flag_values[1 << i]}\n"
|
|
return out
|
|
|
|
def set_bit(self, flag: int):
|
|
if flag < 0 or flag > 0xFFFFFFFF:
|
|
raise ValueError("Flags must be a 32-bit unsigned integer.")
|
|
self.flag |= flag
|
|
|
|
def unset_bit(self, flag: int):
|
|
if flag < 0 or flag > 0xFFFFFFFF:
|
|
raise ValueError("Flags must be a 32-bit unsigned integer.")
|
|
self.flag &= ~flag
|
|
|
|
def __str__(self):
|
|
out = ""
|
|
out += f"{self.flag & 1}: A IGNORED (Account lockout)"
|
|
out += f"\n{(self.flag & 2) >> 1}: B NT3.5 BDC continuous update"
|
|
out += f"\n{(self.flag & 4) >> 2}: C RC4 support"
|
|
out += f"\n{(self.flag & 8) >> 3}: D IGNORED (Promotion count(deprecated))"
|
|
out += f"\n{(self.flag & 0x10) >> 4}: E Supports BDC handling Changelogs"
|
|
out += f"\n{(self.flag & 0x20) >> 5}: F Supports Restarting full DC sync"
|
|
out += f"\n{(self.flag & 0x40) >> 6}: G Does not require ValidationLevel 2 for nongeneric passthrough"
|
|
out += f"\n{(self.flag & 0x80) >> 7}: H Supports DatabaseRedo"
|
|
out += f"\n{(self.flag & 0x100) >> 8}: I Supports refusal of password changes"
|
|
out += f"\n{(self.flag & 0x200) >> 9}: J Supports NetrLogonSendToSam"
|
|
out += f"\n{(self.flag & 0x400) >> 10}: K Supports generic pass-through"
|
|
out += f"\n{(self.flag & 0x800) >> 11}: L Supports concurrent RPC calls"
|
|
out += f"\n{(self.flag & 0x1000) >> 12}: M Supports avoid of user account database replication"
|
|
out += f"\n{(self.flag & 0x2000) >> 13}: N Supports avoid of Security Authority database replication"
|
|
out += f"\n{(self.flag & 0x4000) >> 14}: O Supports Strong keys"
|
|
out += f"\n{(self.flag & 0x8000) >> 15}: P Supports transitive trusts"
|
|
out += f"\n{(self.flag & 0x10000) >> 16}: Q IGNORED (Supports DNS trusts)"
|
|
out += f"\n{(self.flag & 0x20000) >> 17}: R Supports NetrServerPasswordSet2"
|
|
out += f"\n{(self.flag & 0x40000) >> 18}: S Supports NetrLogonGetDomainInfo"
|
|
out += f"\n{(self.flag & 0x80000) >> 19}: T Supports cross-forest trusts"
|
|
out += f"\n{(self.flag & 0x100000) >> 20}: U No NT4 Emulation"
|
|
out += f"\n{(self.flag & 0x200000) >> 21}: V Supports RODC pass-through"
|
|
out += f"\n{(self.flag & 0x400000) >> 22}: 0"
|
|
out += f"\n{(self.flag & 0x800000) >> 23}: 0"
|
|
out += f"\n{(self.flag & 0x1000000) >> 24}: W Supports AES 128-bit CFB and SHA2"
|
|
out += f"\n{(self.flag & 0x2000000) >> 25}: 0"
|
|
out += f"\n{(self.flag & 0x4000000) >> 26}: 0"
|
|
out += f"\n{(self.flag & 0x8000000) >> 27}: 0"
|
|
out += f"\n{(self.flag & 0x10000000) >> 28}: 0"
|
|
out += f"\n{(self.flag & 0x20000000) >> 29}: X IGNORED (Authenticated RPC via lsass supported)"
|
|
out += f"\n{(self.flag & 0x40000000) >> 30}: Y Supports secure RPC authentication"
|
|
out += f"\n{(self.flag & 0x80000000) >> 31}: Z Supports Kerberos for secure channel setup"
|
|
return out
|
|
|
|
def __eq__(self, value):
|
|
if not isinstance(value, FLAGS):
|
|
return NotImplemented
|
|
return self.flag == value.flag
|
|
|
|
|
|
def log(message, color=None):
|
|
"""Simple logging function to print messages."""
|
|
if color:
|
|
if color == "blue":
|
|
print(f"{colored('[*]', 'blue', attrs=['bold'])} {message}")
|
|
elif color == "orange":
|
|
print(f"{colored('[!]', 'yellow', attrs=['bold'])} {message}")
|
|
else:
|
|
print(colored(f"{message}", color, attrs=["bold"]))
|
|
else:
|
|
print(f"{colored('[+]', 'green', attrs=['bold'])} {message}")
|