From: Douglas Bagnall Date: Wed, 6 Aug 2025 02:00:55 +0000 (+1200) Subject: python:models: add key credential link DN to domain fields X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=6a1dc25421ba1e927bf758c0ea80e2c08e350113;p=thirdparty%2Fsamba.git python:models: add key credential link DN to domain fields This will soon be needed by samba-tool, and is also going to be used in some tests. Signed-off-by: Douglas Bagnall Reviewed-by: Gary Lockyer --- diff --git a/python/samba/domain/models/fields.py b/python/samba/domain/models/fields.py index e902b727aec..cff11661e73 100644 --- a/python/samba/domain/models/fields.py +++ b/python/samba/domain/models/fields.py @@ -27,6 +27,7 @@ from enum import IntEnum, IntFlag from xml.etree import ElementTree from ldb import Dn, MessageElement, binary_encode, string_to_time, timestring +from samba.key_credential_link import KeyCredentialLinkDn from samba.dcerpc import security from samba.dcerpc.misc import GUID from samba.ndr import ndr_pack, ndr_unpack @@ -550,3 +551,44 @@ class PossibleClaimValuesField(Field): # Back to str as that is what MessageElement needs. return MessageElement(out.getvalue().decode("utf-16"), flags, self.name) + + +class BaseDsdbDnField(Field): + """Generic DN + Binary field or DN + String field. + + These have this form: + + B::: + S::: + + is the length of (in decimal), i.e. + twice the length of the encoded value. + + Subclasses should set dsdb_dn to a BaseDsdbDn subtype. + """ + dsdb_dn = NotImplemented + + def from_db_value(self, samdb, value): + """Convert MessageElement to a Dn object or list of Dn objects.""" + if value is None: + return + elif isinstance(value, self.dsdb_dn): + return value + elif len(value) > 1 or self.many: + return [self.dsdb_dn(samdb, str(item)) for item in value] + else: + return self.dsdb_dn(samdb, str(value)) + + def to_db_value(self, samdb, value, flags): + """Convert Dn object or list of Dn objects into a MessageElement.""" + if value is None: + return + elif isinstance(value, list): + return MessageElement( + [str(item) for item in value], flags, self.name) + else: + return MessageElement(str(value), flags, self.name) + + +class KeyCredentialLinkDnField(BaseDsdbDnField): + dsdb_dn = KeyCredentialLinkDn diff --git a/python/samba/domain/models/user.py b/python/samba/domain/models/user.py index 0ce6cf96d06..14581809454 100644 --- a/python/samba/domain/models/user.py +++ b/python/samba/domain/models/user.py @@ -27,6 +27,7 @@ from samba.dsdb import DS_GUID_USERS_CONTAINER from .exceptions import NotFound from .fields import DnField, EnumField, IntegerField, NtTimeField, StringField +from .fields import KeyCredentialLinkDnField from .group import Group from .org import OrganizationalPerson from .types import AccountType, UserAccountControl @@ -41,6 +42,8 @@ class User(OrganizationalPerson): bad_pwd_count = IntegerField("badPwdCount", readonly=True) code_page = IntegerField("codePage") display_name = StringField("displayName") + key_credential_link = KeyCredentialLinkDnField("msDS-KeyCredentialLink", + many=True) last_logoff = NtTimeField("lastLogoff", readonly=True) last_logon = NtTimeField("lastLogon", readonly=True) logon_count = IntegerField("logonCount", readonly=True)