]> git.ipfire.org Git - thirdparty/samba.git/commitdiff
s4:kdc:db-glue binary dn changes
authorGary Lockyer <gary@catalyst.net.nz>
Mon, 11 Aug 2025 04:09:46 +0000 (16:09 +1200)
committerDouglas Bagnall <dbagnall@samba.org>
Tue, 16 Sep 2025 22:22:34 +0000 (22:22 +0000)
msDS-KeyCredentialLink will be stored as a BinaryDN and not a binary blob.
This commit updates db-glue and it's tests accordingly.

Signed-off-by: Gary Lockyer <gary@catalyst.net.nz>
Reviewed-by: Jennifer Sutton <jennifersutton@catalyst.net.nz>
source4/kdc/db-glue.c
source4/kdc/tests/db-glue-test.c

index a776dc008e6685d1b096fa99d52d0816c3c35cf4..6b95c2026ed62b665f955398404e2ab529d37044 100644 (file)
@@ -1199,7 +1199,9 @@ static krb5_error_code samba_kdc_get_entry_principal(
  *   5) that KeyMaterial can be unpacked
  *
  * @param[in] mem_ctx  talloc memory context, that will own pub_key
- * @param[in] value    ldb value containing the raw KEYCREDENTIALLINK_BLOB
+ * @param[in] ldb      ldb database context
+ * @param[in] value    ldb value containing the KEYCREDENTIALLINK_BLOB
+ *                         BinaryDn
  * @param[out] pub_key the extracted public key
  *
  * @return 0 No error pub_key will be valid
@@ -1208,6 +1210,7 @@ static krb5_error_code samba_kdc_get_entry_principal(
  */
 static krb5_error_code unpack_key_credential_link_blob(
        TALLOC_CTX *mem_ctx,
+       struct ldb_context *ldb,
        struct ldb_val *value,
        struct KeyMaterialInternal **pub_key)
 {
@@ -1216,6 +1219,8 @@ static krb5_error_code unpack_key_credential_link_blob(
        enum ndr_err_code ndr_err = NDR_ERR_SUCCESS;
        struct KEYCREDENTIALLINK_BLOB blob = {};
        DATA_BLOB key_material = data_blob_null;
+       struct dsdb_dn *dsdb_dn = NULL;
+
        int key_usage = 0;
 
        size_t i = 0;
@@ -1227,9 +1232,23 @@ static krb5_error_code unpack_key_credential_link_blob(
        }
        *pub_key = NULL;
 
+       /* Unpack the binary DN */
+       dsdb_dn = dsdb_dn_parse(tmp_ctx, ldb, value, DSDB_SYNTAX_BINARY_DN);
+       if (dsdb_dn == NULL) {
+               DBG_WARNING("Unable to parse KEYCREDENTIALLINK_BLOB, BinaryDn");
+               ret = EINVAL;
+               goto out;
+       }
+       if (dsdb_dn->extra_part.data == NULL ||
+           dsdb_dn->extra_part.length == 0) {
+               DBG_WARNING("KEYCREDENTIALLINK_BLOB, BinaryDn is empty");
+               ret = EINVAL;
+               goto out;
+       }
+
        /* Unpack the KEYCREDENTIALLINK_BLOB */
        ndr_err = ndr_pull_struct_blob_all(
-               value,
+               &dsdb_dn->extra_part,
                tmp_ctx,
                &blob,
                (ndr_pull_flags_fn_t)ndr_pull_KEYCREDENTIALLINK_BLOB);
@@ -1324,6 +1343,7 @@ out:
  * attribute, extracting all the valid public keys.
  *
  * @param mem_ctx[in] talloc memory context
+ * @param ldb[in]     ldb database context
  * @param msg[in]     ldb message containing the public keys
  * @param entry[out]  entry will be updated with the keys
  *
@@ -1335,6 +1355,7 @@ out:
  *         >0 Errors detected
  */
 static krb5_error_code get_key_trust_public_keys(TALLOC_CTX *mem_ctx,
+                                                struct ldb_context *ldb,
                                                 struct ldb_message *msg,
                                                 struct sdb_entry *entry)
 {
@@ -1359,6 +1380,7 @@ static krb5_error_code get_key_trust_public_keys(TALLOC_CTX *mem_ctx,
                struct KeyMaterialInternal *kmi = NULL;
                struct sdb_pub_key pub_key = {};
                r = unpack_key_credential_link_blob(tmp_ctx,
+                                                   ldb,
                                                    &el->values[i],
                                                    &kmi);
                if (r == 0) {
@@ -2163,12 +2185,8 @@ static krb5_error_code samba_kdc_message2entry(krb5_context context,
        p->client_policy = talloc_steal(p, authn_client_policy);
        p->server_policy = talloc_steal(p, authn_server_policy);
 
-       /*
-        * get_key_trust_public_keys will return ENOENT if there are no
-        * public keys loaded for an object, this is not an error condition
-        */
-       ret = get_key_trust_public_keys(tmp_ctx, msg, entry);
-       if (ret != 0 && ret != ENOENT) {
+       ret = get_key_trust_public_keys(tmp_ctx, kdc_db_ctx->samdb, msg, entry);
+       if (ret != 0) {
                goto out;
        }
 
index 4d5f7191414dd35c6a588fc8512ff513e185223f..caf365d1093f48f2f2a78bc68099252639f2d08f 100644 (file)
@@ -59,15 +59,29 @@ int dsdb_functional_level(struct ldb_context *ldb)
 /******************************************************************************
  * Test helper functions
  *****************************************************************************/
-static void add_msDS_KeyCredentialLink(struct ldb_message *msg,
+static void add_msDS_KeyCredentialLink(TALLOC_CTX *mem_ctx,
+                                      struct ldb_message *msg,
                                       size_t size,
                                       uint8_t *data)
 {
-       struct ldb_message_element *el = NULL;
        DATA_BLOB key_cred_val = {.length = size, .data = data};
+       char *hex_value = data_blob_hex_string_upper(mem_ctx, &key_cred_val);
+       size_t hex_len = strlen(hex_value);
+       char *binary_dn = talloc_asprintf(
+               mem_ctx, "B:%zu:%s:DC=EXAMPLE,DC=COM", hex_len, hex_value);
+       TALLOC_FREE(hex_value);
+
+       /* Add the data to msDS-KeyCredentialLink */
+       ldb_msg_add_string(msg, "msDS-KeyCredentialLink", binary_dn);
+}
+
+static void add_empty_msDS_KeyCredentialLink_DN(TALLOC_CTX *mem_ctx,
+                                               struct ldb_message *msg)
+{
+       char *binary_dn = talloc_asprintf(mem_ctx, "B:0::DC=EXAMPLE,DC=COM");
 
        /* Add the data to msDS-KeyCredentialLink */
-       ldb_msg_add_value(msg, "msDS-KeyCredentialLink", &key_cred_val, &el);
+       ldb_msg_add_string(msg, "msDS-KeyCredentialLink", binary_dn);
 }
 
 static struct ldb_message *create_ldb_message(TALLOC_CTX *mem_ctx)
@@ -449,7 +463,6 @@ static void empty_message2entry(void **state)
 
        /* Set up */
        kdc_db_ctx = create_kdc_db_ctx(mem_ctx);
-       ;
        realm_dn = ldb_dn_new(mem_ctx, ldb_ctx, "TEST.SAMBA.ORG");
 
        smb_krb5_init_context_common(&krb5_ctx);
@@ -533,6 +546,63 @@ static void minimal_message2entry(void **state)
        sdb_entry_free(&entry);
        TALLOC_FREE(mem_ctx);
 }
+/*
+ * Test samba_kdc_message2entry mapping of an empty msDS-KeyCredentialLink
+ * binary dn
+ */
+static void empty_binary_dn_message2entry(void **state)
+{
+       TALLOC_CTX *mem_ctx = talloc_new(NULL);
+
+       krb5_context krb5_ctx = NULL;
+       struct samba_kdc_db_context *kdc_db_ctx = create_kdc_db_ctx(mem_ctx);
+       struct ldb_context *ldb_ctx = ldb_init(mem_ctx, NULL);
+       struct ldb_dn *realm_dn = ldb_dn_new(mem_ctx,
+                                            ldb_ctx,
+                                            "TEST.SAMBA.ORG");
+       struct ldb_message *msg = NULL;
+
+       krb5_principal principal = NULL;
+
+       enum samba_kdc_ent_type ent_type = SAMBA_KDC_ENT_TYPE_CLIENT;
+       unsigned int flags = 0;
+       krb5_kvno kvno = 0;
+
+       struct sdb_entry entry = {};
+       krb5_error_code err = 0;
+
+       /* Set up */
+       smb_krb5_init_context_common(&krb5_ctx);
+       kdc_db_ctx->samdb = ldb_ctx;
+       assert_non_null(krb5_ctx);
+       principal = get_principal(mem_ctx,
+                                 krb5_ctx,
+                                 "atestuser@test.samba.org");
+
+       /* Create the ldb_message */
+       msg = create_ldb_message(mem_ctx);
+       add_empty_msDS_KeyCredentialLink_DN(mem_ctx, msg);
+
+       err = samba_kdc_message2entry(krb5_ctx,
+                                     kdc_db_ctx,
+                                     mem_ctx,
+                                     principal,
+                                     ent_type,
+                                     flags,
+                                     kvno,
+                                     realm_dn,
+                                     msg,
+                                     &entry);
+
+       /* Expect the ldb message to be loaded */
+       assert_int_equal(0, err);
+       assert_null(entry.pub_keys.keys);
+       assert_int_equal(0, entry.pub_keys.len);
+
+       krb5_free_principal(krb5_ctx, principal);
+       sdb_entry_free(&entry);
+       TALLOC_FREE(mem_ctx);
+}
 
 /*
  * Test samba_kdc_message2entry mapping of msDS-KeyCredentialLink.
@@ -560,6 +630,7 @@ static void msDS_KeyCredentialLink_message2entry(void **state)
 
        /* Set up */
        smb_krb5_init_context_common(&krb5_ctx);
+       kdc_db_ctx->samdb = ldb_ctx;
        assert_non_null(krb5_ctx);
        principal = get_principal(mem_ctx,
                                  krb5_ctx,
@@ -567,7 +638,8 @@ static void msDS_KeyCredentialLink_message2entry(void **state)
 
        /* Create the ldb_message */
        msg = create_ldb_message(mem_ctx);
-       add_msDS_KeyCredentialLink(msg,
+       add_msDS_KeyCredentialLink(mem_ctx,
+                                  msg,
                                   sizeof(BCRYPT_KEY_CREDENTIAL_LINK),
                                   BCRYPT_KEY_CREDENTIAL_LINK);
 
@@ -627,17 +699,19 @@ static void invalid_version_keycredlink(void **state)
 
        TALLOC_CTX *mem_ctx = talloc_new(NULL);
 
+       struct ldb_context *ldb = ldb_init(mem_ctx, NULL);
        struct ldb_message *msg = NULL;
        krb5_error_code err = 0;
        struct sdb_entry entry = {};
 
        /* Create the ldb_message */
        msg = create_ldb_message(mem_ctx);
-       add_msDS_KeyCredentialLink(msg,
+       add_msDS_KeyCredentialLink(mem_ctx,
+                                  msg,
                                   sizeof(KEY_CREDENTIAL_LINK),
                                   KEY_CREDENTIAL_LINK);
 
-       err = get_key_trust_public_keys(mem_ctx, msg, &entry);
+       err = get_key_trust_public_keys(mem_ctx, ldb, msg,  &entry);
 
        /* Expect the key credential link to be ignored */
        assert_int_equal(0, err);
@@ -674,17 +748,19 @@ static void duplicate_key_material_keycredlink(void **state)
 
        TALLOC_CTX *mem_ctx = talloc_new(NULL);
 
+       struct ldb_context *ldb = ldb_init(mem_ctx, NULL);
        struct ldb_message *msg = NULL;
        krb5_error_code err = 0;
        struct sdb_entry entry = {};
 
        /* Create the ldb_message */
        msg = create_ldb_message(mem_ctx);
-       add_msDS_KeyCredentialLink(msg,
+       add_msDS_KeyCredentialLink(mem_ctx,
+                                  msg,
                                   sizeof(KEY_CREDENTIAL_LINK),
                                   KEY_CREDENTIAL_LINK);
 
-       err = get_key_trust_public_keys(mem_ctx, msg, &entry);
+       err = get_key_trust_public_keys(mem_ctx, ldb, msg, &entry);
 
        /* Expect the key credential link to be ignored */
        assert_int_equal(0, err);
@@ -717,17 +793,19 @@ static void duplicate_key_usage_keycredlink(void **state)
 
        TALLOC_CTX *mem_ctx = talloc_new(NULL);
 
+       struct ldb_context *ldb = ldb_init(mem_ctx, NULL);
        struct ldb_message *msg = NULL;
        krb5_error_code err = 0;
        struct sdb_entry entry = {};
 
        /* Create the ldb_message */
        msg = create_ldb_message(mem_ctx);
-       add_msDS_KeyCredentialLink(msg,
+       add_msDS_KeyCredentialLink(mem_ctx,
+                                  msg,
                                   sizeof(KEY_CREDENTIAL_LINK),
                                   KEY_CREDENTIAL_LINK);
 
-       err = get_key_trust_public_keys(mem_ctx, msg, &entry);
+       err = get_key_trust_public_keys(mem_ctx, ldb, msg, &entry);
 
        /* Expect the key credential link to be ignored */
        assert_int_equal(0, err);
@@ -759,17 +837,19 @@ static void invalid_key_usage_keycredlink(void **state)
 
        TALLOC_CTX *mem_ctx = talloc_new(NULL);
 
+       struct ldb_context *ldb = ldb_init(mem_ctx, NULL);
        struct ldb_message *msg = NULL;
        krb5_error_code err = 0;
        struct sdb_entry entry = {};
 
        /* Create the ldb_message */
        msg = create_ldb_message(mem_ctx);
-       add_msDS_KeyCredentialLink(msg,
+       add_msDS_KeyCredentialLink(mem_ctx,
+                                  msg,
                                   sizeof(KEY_CREDENTIAL_LINK),
                                   KEY_CREDENTIAL_LINK);
 
-       err = get_key_trust_public_keys(mem_ctx, msg, &entry);
+       err = get_key_trust_public_keys(mem_ctx, ldb, msg, &entry);
 
        /* Expect the key credential link to be ignored */
        assert_int_equal(0, err);
@@ -801,17 +881,19 @@ static void invalid_key_material_keycredlink(void **state)
 
        TALLOC_CTX *mem_ctx = talloc_new(NULL);
 
+       struct ldb_context *ldb = ldb_init(mem_ctx, NULL);
        struct ldb_message *msg = NULL;
        krb5_error_code err = 0;
        struct sdb_entry entry = {};
 
        /* Create the ldb_message */
        msg = ldb_msg_new(mem_ctx);
-       add_msDS_KeyCredentialLink(msg,
+       add_msDS_KeyCredentialLink(mem_ctx,
+                                  msg,
                                   sizeof(KEY_CREDENTIAL_LINK),
                                   KEY_CREDENTIAL_LINK);
 
-       err = get_key_trust_public_keys(mem_ctx, msg, &entry);
+       err = get_key_trust_public_keys(mem_ctx, ldb, msg, &entry);
 
        /* Expect the key credential link to be ignored */
        assert_int_equal(0, err);
@@ -832,17 +914,19 @@ static void keycred_bcrypt_key_material(void **state)
 
        TALLOC_CTX *mem_ctx = talloc_new(NULL);
 
+       struct ldb_context *ldb = ldb_init(mem_ctx, NULL);
        struct ldb_message *msg = NULL;
        krb5_error_code err = 0;
        struct sdb_entry entry = {};
 
        /* Create the ldb_message */
        msg = create_ldb_message(mem_ctx);
-       add_msDS_KeyCredentialLink(msg,
+       add_msDS_KeyCredentialLink(mem_ctx,
+                                  msg,
                                   sizeof(BCRYPT_KEY_CREDENTIAL_LINK),
                                   BCRYPT_KEY_CREDENTIAL_LINK);
 
-       err = get_key_trust_public_keys(mem_ctx, msg, &entry);
+       err = get_key_trust_public_keys(mem_ctx, ldb, msg, &entry);
 
        assert_int_equal(0, err);
        assert_non_null(entry.pub_keys.keys);
@@ -875,17 +959,19 @@ static void keycred_tpm_key_material(void **state)
 {
        TALLOC_CTX *mem_ctx = talloc_new(NULL);
 
+       struct ldb_context *ldb = ldb_init(mem_ctx, NULL);
        struct ldb_message *msg = NULL;
        krb5_error_code err = 0;
        struct sdb_entry entry = {};
 
        /* Create the ldb_message */
        msg = create_ldb_message(mem_ctx);
-       add_msDS_KeyCredentialLink(msg,
+       add_msDS_KeyCredentialLink(mem_ctx,
+                                  msg,
                                   sizeof(TPM_KEY_CREDENTIAL_LINK),
                                   TPM_KEY_CREDENTIAL_LINK);
 
-       err = get_key_trust_public_keys(mem_ctx, msg, &entry);
+       err = get_key_trust_public_keys(mem_ctx, ldb, msg, &entry);
 
        assert_int_equal(0, err);
        assert_non_null(entry.pub_keys.keys);
@@ -918,17 +1004,19 @@ static void keycred_der_key_material(void **state)
 {
        TALLOC_CTX *mem_ctx = talloc_new(NULL);
 
+       struct ldb_context *ldb = ldb_init(mem_ctx, NULL);
        struct ldb_message *msg = NULL;
        krb5_error_code err = 0;
        struct sdb_entry entry = {};
 
        /* Create the ldb_message */
        msg = create_ldb_message(mem_ctx);
-       add_msDS_KeyCredentialLink(msg,
+       add_msDS_KeyCredentialLink(mem_ctx,
+                                  msg,
                                   sizeof(DER_KEY_CREDENTIAL_LINK),
                                   DER_KEY_CREDENTIAL_LINK);
 
-       err = get_key_trust_public_keys(mem_ctx, msg, &entry);
+       err = get_key_trust_public_keys(mem_ctx, ldb, msg, &entry);
 
        assert_int_equal(0, err);
        assert_non_null(entry.pub_keys.keys);
@@ -961,23 +1049,27 @@ static void keycred_multiple(void **state)
 {
        TALLOC_CTX *mem_ctx = talloc_new(NULL);
 
+       struct ldb_context *ldb = ldb_init(mem_ctx, NULL);
        struct ldb_message *msg = NULL;
        krb5_error_code err = 0;
        struct sdb_entry entry = {};
 
        /* Create the ldb_message */
        msg = create_ldb_message(mem_ctx);
-       add_msDS_KeyCredentialLink(msg,
+       add_msDS_KeyCredentialLink(mem_ctx,
+                                  msg,
                                   sizeof(DER_KEY_CREDENTIAL_LINK),
                                   DER_KEY_CREDENTIAL_LINK);
-       add_msDS_KeyCredentialLink(msg,
+       add_msDS_KeyCredentialLink(mem_ctx,
+                                  msg,
                                   sizeof(TPM_KEY_CREDENTIAL_LINK),
                                   TPM_KEY_CREDENTIAL_LINK);
-       add_msDS_KeyCredentialLink(msg,
+       add_msDS_KeyCredentialLink(mem_ctx,
+                                  msg,
                                   sizeof(BCRYPT_KEY_CREDENTIAL_LINK),
                                   BCRYPT_KEY_CREDENTIAL_LINK);
 
-       err = get_key_trust_public_keys(mem_ctx, msg, &entry);
+       err = get_key_trust_public_keys(mem_ctx, ldb, msg, &entry);
 
        assert_int_equal(0, err);
        assert_non_null(entry.pub_keys.keys);
@@ -1037,6 +1129,7 @@ int main(int argc, const char **argv)
        const struct CMUnitTest tests[] = {
                cmocka_unit_test(empty_message2entry),
                cmocka_unit_test(minimal_message2entry),
+               cmocka_unit_test(empty_binary_dn_message2entry),
                cmocka_unit_test(msDS_KeyCredentialLink_message2entry),
                cmocka_unit_test(invalid_version_keycredlink),
                cmocka_unit_test(duplicate_key_material_keycredlink),