]> git.ipfire.org Git - thirdparty/samba.git/commitdiff
python:models: add key credential link DN to domain fields
authorDouglas Bagnall <douglas.bagnall@catalyst.net.nz>
Wed, 6 Aug 2025 02:00:55 +0000 (14:00 +1200)
committerDouglas Bagnall <dbagnall@samba.org>
Wed, 13 Aug 2025 02:53:44 +0000 (02:53 +0000)
This will soon be needed by samba-tool, and is also going to be used
in some tests.

Signed-off-by: Douglas Bagnall <douglas.bagnall@catalyst.net.nz>
Reviewed-by: Gary Lockyer <gary@catalyst.net.nz>
python/samba/domain/models/fields.py
python/samba/domain/models/user.py

index e902b727aec081e05b7e1ce6c34d7b65c6a3365e..cff11661e732db746188837070c9342aeec67f0e 100644 (file)
@@ -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:<hex length>:<binary hex>:<ordinary DN>
+    S:<utf8 length>:<utf8 string>:<ordinary DN>
+
+    <hex length> is the length of <binary hex> (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
index 0ce6cf96d067d330b86ac158155e739b17b257d4..145818094544fd8675f2366a3c90e15255a17222 100644 (file)
@@ -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)