From 3687bf22aa1ce2515997b06efb536d5da4294c9a Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Fri, 22 Mar 2024 14:08:22 +1300 Subject: [PATCH] s4-dsdb: Populate new GKDI root keys from the server configuration object This honours MS-GKDI 3.1.4.1.1 Creating a New Root Key Signed-off-by: Andrew Bartlett Reviewed-by: Douglas Bagnall --- lib/crypto/gkdi.h | 2 + selftest/knownfail.d/gkdi | 4 - source4/dsdb/common/util.c | 6 +- source4/dsdb/gmsa/gkdi.c | 316 ++++++++++++++++++++++++++----------- 4 files changed, 231 insertions(+), 97 deletions(-) diff --git a/lib/crypto/gkdi.h b/lib/crypto/gkdi.h index 244563d18b6..ea0f8b9357f 100644 --- a/lib/crypto/gkdi.h +++ b/lib/crypto/gkdi.h @@ -37,6 +37,8 @@ enum KdfAlgorithmId { KDF_ALGORITHM_SP800_108_CTR_HMAC, }; +#define SP800_108_CTR_HMAC "SP800_108_CTR_HMAC" + enum KdfSp800_108Param { KDF_PARAM_SHA1, KDF_PARAM_SHA256, diff --git a/selftest/knownfail.d/gkdi b/selftest/knownfail.d/gkdi index 387bbfa2774..fbea302922f 100644 --- a/selftest/knownfail.d/gkdi +++ b/selftest/knownfail.d/gkdi @@ -17,7 +17,3 @@ ^samba\.tests\.krb5\.gkdi_tests\.samba\.tests\.krb5\.gkdi_tests\.GkdiImplicitRootKeyTests\.test_request_default_seed_key\(ad_dc\)$ ^samba\.tests\.krb5\.gkdi_tests\.samba\.tests\.krb5\.gkdi_tests\.GkdiImplicitRootKeyTests\.test_request_l0_seed_key\(ad_dc\)$ ^samba\.tests\.krb5\.gkdi_tests\.samba\.tests\.krb5\.gkdi_tests\.GkdiImplicitRootKeyTests\.test_request_l1_seed_key\(ad_dc\)$ -^samba.tests.dsdb_quiet_provision_tests.samba.tests.dsdb_quiet_provision_tests.DsdbQuietProvisionTests.test_gkdi_create_root_key_4096 -^samba.tests.dsdb_quiet_provision_tests.samba.tests.dsdb_quiet_provision_tests.DsdbQuietProvisionTests.test_gkdi_create_root_key_bad_alg -^samba.tests.dsdb_quiet_provision_tests.samba.tests.dsdb_quiet_provision_tests.DsdbQuietProvisionTests.test_gkdi_create_root_key_priv_1024 -^samba.tests.dsdb_quiet_provision_tests.samba.tests.dsdb_quiet_provision_tests.DsdbQuietProvisionTests.test_gkdi_create_root_key_wrong_version diff --git a/source4/dsdb/common/util.c b/source4/dsdb/common/util.c index d31d7d94f2d..7cdfca8da19 100644 --- a/source4/dsdb/common/util.c +++ b/source4/dsdb/common/util.c @@ -1325,9 +1325,9 @@ struct ldb_dn *samdb_extended_rights_dn(struct ldb_context *sam_ctx, TALLOC_CTX return new_dn; } -static struct ldb_dn *samdb_configuration_dn(struct ldb_context *sam_ctx, - TALLOC_CTX *mem_ctx, - const char *dn_str) +struct ldb_dn *samdb_configuration_dn(struct ldb_context *sam_ctx, + TALLOC_CTX *mem_ctx, + const char *dn_str) { struct ldb_dn *config_dn = NULL; struct ldb_dn *child_dn = NULL; diff --git a/source4/dsdb/gmsa/gkdi.c b/source4/dsdb/gmsa/gkdi.c index dfb9be89226..49d05801037 100644 --- a/source4/dsdb/gmsa/gkdi.c +++ b/source4/dsdb/gmsa/gkdi.c @@ -30,6 +30,7 @@ #include "dsdb/gmsa/gkdi.h" #include "dsdb/samdb/ldb_modules/util.h" #include "dsdb/samdb/samdb.h" +#include "dsdb/common/proto.h" static int gkdi_create_root_key(TALLOC_CTX *mem_ctx, struct ldb_context *const ldb, @@ -40,10 +41,33 @@ static int gkdi_create_root_key(TALLOC_CTX *mem_ctx, { TALLOC_CTX *tmp_ctx = NULL; struct GUID root_key_id; + struct ldb_dn *server_config_dn = NULL; + struct ldb_result *server_config_res = NULL; + struct ldb_message *server_config_msg = NULL; + uint64_t server_config_version; + const struct ldb_val *server_config_version_val = NULL; + const char *server_config_KDFAlgorithmID = NULL; + const struct ldb_val *server_config_KDFParam = NULL; + const char *server_config_SecretAgreementAlgorithmID = NULL; + const struct ldb_val *server_config_SecretAgreementParam = NULL; + uint64_t server_config_PublicKeyLength; + uint64_t server_config_PrivateKeyLength; + struct KdfAlgorithm kdf_algorithm; struct ldb_message *add_msg = NULL; NTSTATUS status = NT_STATUS_OK; int ret = LDB_SUCCESS; + static const char *server_config_attrs[] = { + "msKds-Version", + "msKds-KDFAlgorithmID", + "msKds-SecretAgreementAlgorithmID", + "msKds-SecretAgreementParam", + "msKds-PublicKeyLength", + "msKds-PrivateKeyLength", + "msKds-KDFParam", + NULL + }; + *root_key_dn_out = NULL; tmp_ctx = talloc_new(mem_ctx); @@ -52,6 +76,179 @@ static int gkdi_create_root_key(TALLOC_CTX *mem_ctx, goto out; } + server_config_dn = samdb_configuration_dn(ldb, + mem_ctx, + "CN=Group Key Distribution Service Server Configuration," + "CN=Server Configuration," + "CN=Group Key Distribution Service," + "CN=Services"); + if (server_config_dn == NULL) { + ret = ldb_oom(ldb); + goto out; + } + + ret = dsdb_search_dn(ldb, + tmp_ctx, + &server_config_res, + server_config_dn, + server_config_attrs, + DSDB_SEARCH_ONE_ONLY); + + if (ret == LDB_ERR_NO_SUCH_OBJECT) { + ldb_asprintf_errstring(ldb, "Unable to create new GKDI root key as we do not have a GKDI server configuration at %s", + ldb_dn_get_linearized(server_config_dn)); + goto out; + } + + if (ret != LDB_SUCCESS) { + goto out; + } + + server_config_msg = server_config_res->msgs[0]; + + server_config_version_val + = ldb_msg_find_ldb_val(server_config_msg, + "msKds-Version"); + server_config_version + = ldb_msg_find_attr_as_uint64(server_config_msg, + "msKds-Version", + 0); + + /* These values we assert on, so we don't create keys we can't use */ + if (server_config_version_val == NULL) { + /* + * The systemMustContain msKds-Version attribute + * cannot be read, so if absent we just fail with + * permission denied, as that is all that this can + * mean + */ + ldb_asprintf_errstring(ldb, + "Unwilling to create new GKDI root key as " + "msKds-Version is not readable on %s\n", + ldb_dn_get_linearized(server_config_dn)); + ret = LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS; + goto out; + } else if (server_config_version != 1) { + ldb_asprintf_errstring(ldb, + "Unwilling to create new GKDI root key as " + "%s has msKds-Version = %s " + "and we only support version 1\n", + ldb_dn_get_linearized(server_config_dn), + ldb_msg_find_attr_as_string(server_config_msg, "msKds-Version", "(missing)")); + ret = LDB_ERR_CONSTRAINT_VIOLATION; + goto out; + } + + server_config_KDFAlgorithmID + = ldb_msg_find_attr_as_string(server_config_msg, + "msKds-KDFAlgorithmID", + SP800_108_CTR_HMAC + ); + + server_config_KDFParam + = ldb_msg_find_ldb_val(server_config_msg, + "msKds-KDFParam"); + if (server_config_KDFParam == NULL) { + static const uint8_t kdf_parameters[] = { + 0, 0, 0, 0, 1, 0, 0, 0, 14, 0, + 0, 0, 0, 0, 0, 0, 'S', 0, 'H', 0, + 'A', 0, '5', 0, '1', 0, '2', 0, 0, 0, + }; + static const DATA_BLOB kdf_parameters_blob = { + discard_const_p(uint8_t, kdf_parameters), + sizeof kdf_parameters}; + server_config_KDFParam = &kdf_parameters_blob; + } + + status = kdf_algorithm_from_params(server_config_KDFAlgorithmID, + server_config_KDFParam, + &kdf_algorithm); + if (!NT_STATUS_IS_OK(status)) { + ldb_asprintf_errstring(ldb, + "Unwilling to create new GKDI root key as " + "%s has an unsupported msKds-KDFAlgorithmID / msKds-KDFParam combination set: %s\n", + ldb_dn_get_linearized(server_config_dn), + nt_errstr(status)); + ret = LDB_ERR_CONSTRAINT_VIOLATION; + goto out; + } + + server_config_SecretAgreementAlgorithmID + = ldb_msg_find_attr_as_string(server_config_msg, + "msKds-SecretAgreementAlgorithmID", + "DH"); + + /* Optional in msKds-ProvRootKey */ + server_config_SecretAgreementParam + = ldb_msg_find_ldb_val(server_config_msg, + "msKds-SecretAgreementParam"); + if (server_config_SecretAgreementParam == NULL) { + static const uint8_t ffc_dh_parameters[] = { + 12, 2, 0, 0, 68, 72, 80, 77, 0, 1, 0, + 0, 135, 168, 230, 29, 180, 182, 102, 60, 255, 187, + 209, 156, 101, 25, 89, 153, 140, 238, 246, 8, 102, + 13, 208, 242, 93, 44, 238, 212, 67, 94, 59, 0, + 224, 13, 248, 241, 214, 25, 87, 212, 250, 247, 223, + 69, 97, 178, 170, 48, 22, 195, 217, 17, 52, 9, + 111, 170, 59, 244, 41, 109, 131, 14, 154, 124, 32, + 158, 12, 100, 151, 81, 122, 189, 90, 138, 157, 48, + 107, 207, 103, 237, 145, 249, 230, 114, 91, 71, 88, + 192, 34, 224, 177, 239, 66, 117, 191, 123, 108, 91, + 252, 17, 212, 95, 144, 136, 185, 65, 245, 78, 177, + 229, 155, 184, 188, 57, 160, 191, 18, 48, 127, 92, + 79, 219, 112, 197, 129, 178, 63, 118, 182, 58, 202, + 225, 202, 166, 183, 144, 45, 82, 82, 103, 53, 72, + 138, 14, 241, 60, 109, 154, 81, 191, 164, 171, 58, + 216, 52, 119, 150, 82, 77, 142, 246, 161, 103, 181, + 164, 24, 37, 217, 103, 225, 68, 229, 20, 5, 100, + 37, 28, 202, 203, 131, 230, 180, 134, 246, 179, 202, + 63, 121, 113, 80, 96, 38, 192, 184, 87, 246, 137, + 150, 40, 86, 222, 212, 1, 10, 189, 11, 230, 33, + 195, 163, 150, 10, 84, 231, 16, 195, 117, 242, 99, + 117, 215, 1, 65, 3, 164, 181, 67, 48, 193, 152, + 175, 18, 97, 22, 210, 39, 110, 17, 113, 95, 105, + 56, 119, 250, 215, 239, 9, 202, 219, 9, 74, 233, + 30, 26, 21, 151, 63, 179, 44, 155, 115, 19, 77, + 11, 46, 119, 80, 102, 96, 237, 189, 72, 76, 167, + 177, 143, 33, 239, 32, 84, 7, 244, 121, 58, 26, + 11, 161, 37, 16, 219, 193, 80, 119, 190, 70, 63, + 255, 79, 237, 74, 172, 11, 181, 85, 190, 58, 108, + 27, 12, 107, 71, 177, 188, 55, 115, 191, 126, 140, + 111, 98, 144, 18, 40, 248, 194, 140, 187, 24, 165, + 90, 227, 19, 65, 0, 10, 101, 1, 150, 249, 49, + 199, 122, 87, 242, 221, 244, 99, 229, 233, 236, 20, + 75, 119, 125, 230, 42, 170, 184, 168, 98, 138, 195, + 118, 210, 130, 214, 237, 56, 100, 230, 121, 130, 66, + 142, 188, 131, 29, 20, 52, 143, 111, 47, 145, 147, + 181, 4, 90, 242, 118, 113, 100, 225, 223, 201, 103, + 193, 251, 63, 46, 85, 164, 189, 27, 255, 232, 59, + 156, 128, 208, 82, 185, 133, 209, 130, 234, 10, 219, + 42, 59, 115, 19, 211, 254, 20, 200, 72, 75, 30, + 5, 37, 136, 185, 183, 210, 187, 210, 223, 1, 97, + 153, 236, 208, 110, 21, 87, 205, 9, 21, 179, 53, + 59, 187, 100, 224, 236, 55, 127, 208, 40, 55, 13, + 249, 43, 82, 199, 137, 20, 40, 205, 198, 126, 182, + 24, 75, 82, 61, 29, 178, 70, 195, 47, 99, 7, + 132, 144, 240, 14, 248, 214, 71, 209, 72, 212, 121, + 84, 81, 94, 35, 39, 207, 239, 152, 197, 130, 102, + 75, 76, 15, 108, 196, 22, 89}; + static const DATA_BLOB ffc_dh_parameters_blob = { + discard_const_p(uint8_t, ffc_dh_parameters), + sizeof ffc_dh_parameters}; + + server_config_SecretAgreementParam = &ffc_dh_parameters_blob; + } + + server_config_PublicKeyLength + = ldb_msg_find_attr_as_uint64(server_config_msg, + "msKds-PublicKeyLength", + 2048); + + server_config_PrivateKeyLength + = ldb_msg_find_attr_as_uint64(server_config_msg, + "msKds-PrivateKeyLength", + 256); + add_msg = ldb_msg_new(tmp_ctx); if (add_msg == NULL) { ret = ldb_oom(ldb); @@ -119,128 +316,67 @@ static int gkdi_create_root_key(TALLOC_CTX *mem_ctx, } } - ret = ldb_msg_append_string(add_msg, - "msKds-Version", - "1", - LDB_FLAG_MOD_ADD); + ret = samdb_msg_append_uint64(ldb, + tmp_ctx, + add_msg, + "msKds-Version", + server_config_version, + LDB_FLAG_MOD_ADD); if (ret) { goto out; } ret = ldb_msg_append_string(add_msg, "msKds-KDFAlgorithmID", - "SP800_108_CTR_HMAC", + server_config_KDFAlgorithmID, LDB_FLAG_MOD_ADD); if (ret) { goto out; } ret = ldb_msg_append_string(add_msg, - "msKds-SecretAgreementAlgorithmID", - "DH", - LDB_FLAG_MOD_ADD); + "msKds-SecretAgreementAlgorithmID", + server_config_SecretAgreementAlgorithmID, + LDB_FLAG_MOD_ADD); if (ret) { goto out; } - { - static const uint8_t ffc_dh_parameters[] = { - 12, 2, 0, 0, 68, 72, 80, 77, 0, 1, 0, - 0, 135, 168, 230, 29, 180, 182, 102, 60, 255, 187, - 209, 156, 101, 25, 89, 153, 140, 238, 246, 8, 102, - 13, 208, 242, 93, 44, 238, 212, 67, 94, 59, 0, - 224, 13, 248, 241, 214, 25, 87, 212, 250, 247, 223, - 69, 97, 178, 170, 48, 22, 195, 217, 17, 52, 9, - 111, 170, 59, 244, 41, 109, 131, 14, 154, 124, 32, - 158, 12, 100, 151, 81, 122, 189, 90, 138, 157, 48, - 107, 207, 103, 237, 145, 249, 230, 114, 91, 71, 88, - 192, 34, 224, 177, 239, 66, 117, 191, 123, 108, 91, - 252, 17, 212, 95, 144, 136, 185, 65, 245, 78, 177, - 229, 155, 184, 188, 57, 160, 191, 18, 48, 127, 92, - 79, 219, 112, 197, 129, 178, 63, 118, 182, 58, 202, - 225, 202, 166, 183, 144, 45, 82, 82, 103, 53, 72, - 138, 14, 241, 60, 109, 154, 81, 191, 164, 171, 58, - 216, 52, 119, 150, 82, 77, 142, 246, 161, 103, 181, - 164, 24, 37, 217, 103, 225, 68, 229, 20, 5, 100, - 37, 28, 202, 203, 131, 230, 180, 134, 246, 179, 202, - 63, 121, 113, 80, 96, 38, 192, 184, 87, 246, 137, - 150, 40, 86, 222, 212, 1, 10, 189, 11, 230, 33, - 195, 163, 150, 10, 84, 231, 16, 195, 117, 242, 99, - 117, 215, 1, 65, 3, 164, 181, 67, 48, 193, 152, - 175, 18, 97, 22, 210, 39, 110, 17, 113, 95, 105, - 56, 119, 250, 215, 239, 9, 202, 219, 9, 74, 233, - 30, 26, 21, 151, 63, 179, 44, 155, 115, 19, 77, - 11, 46, 119, 80, 102, 96, 237, 189, 72, 76, 167, - 177, 143, 33, 239, 32, 84, 7, 244, 121, 58, 26, - 11, 161, 37, 16, 219, 193, 80, 119, 190, 70, 63, - 255, 79, 237, 74, 172, 11, 181, 85, 190, 58, 108, - 27, 12, 107, 71, 177, 188, 55, 115, 191, 126, 140, - 111, 98, 144, 18, 40, 248, 194, 140, 187, 24, 165, - 90, 227, 19, 65, 0, 10, 101, 1, 150, 249, 49, - 199, 122, 87, 242, 221, 244, 99, 229, 233, 236, 20, - 75, 119, 125, 230, 42, 170, 184, 168, 98, 138, 195, - 118, 210, 130, 214, 237, 56, 100, 230, 121, 130, 66, - 142, 188, 131, 29, 20, 52, 143, 111, 47, 145, 147, - 181, 4, 90, 242, 118, 113, 100, 225, 223, 201, 103, - 193, 251, 63, 46, 85, 164, 189, 27, 255, 232, 59, - 156, 128, 208, 82, 185, 133, 209, 130, 234, 10, 219, - 42, 59, 115, 19, 211, 254, 20, 200, 72, 75, 30, - 5, 37, 136, 185, 183, 210, 187, 210, 223, 1, 97, - 153, 236, 208, 110, 21, 87, 205, 9, 21, 179, 53, - 59, 187, 100, 224, 236, 55, 127, 208, 40, 55, 13, - 249, 43, 82, 199, 137, 20, 40, 205, 198, 126, 182, - 24, 75, 82, 61, 29, 178, 70, 195, 47, 99, 7, - 132, 144, 240, 14, 248, 214, 71, 209, 72, 212, 121, - 84, 81, 94, 35, 39, 207, 239, 152, 197, 130, 102, - 75, 76, 15, 108, 196, 22, 89}; - const DATA_BLOB ffc_dh_parameters_blob = { - discard_const_p(uint8_t, ffc_dh_parameters), - sizeof ffc_dh_parameters}; - + if (server_config_SecretAgreementParam != NULL) { ret = ldb_msg_append_value(add_msg, "msKds-SecretAgreementParam", - &ffc_dh_parameters_blob, + server_config_SecretAgreementParam, LDB_FLAG_MOD_ADD); if (ret) { goto out; } } - ret = ldb_msg_append_string(add_msg, - "msKds-PublicKeyLength", - "2048", - LDB_FLAG_MOD_ADD); + ret = samdb_msg_append_uint64(ldb, + tmp_ctx, + add_msg, + "msKds-PublicKeyLength", + server_config_PublicKeyLength, + LDB_FLAG_MOD_ADD); if (ret) { goto out; } - ret = ldb_msg_append_string(add_msg, - "msKds-PrivateKeyLength", - "512", - LDB_FLAG_MOD_ADD); + ret = samdb_msg_append_uint64(ldb, + tmp_ctx, + add_msg, + "msKds-PrivateKeyLength", + server_config_PrivateKeyLength, + LDB_FLAG_MOD_ADD); + + ret = ldb_msg_append_value(add_msg, + "msKds-KDFParam", + server_config_KDFParam, + LDB_FLAG_MOD_ADD); if (ret) { goto out; } - { - static const uint8_t kdf_parameters[] = { - 0, 0, 0, 0, 1, 0, 0, 0, 14, 0, - 0, 0, 0, 0, 0, 0, 'S', 0, 'H', 0, - 'A', 0, '5', 0, '1', 0, '2', 0, 0, 0, - }; - const DATA_BLOB kdf_parameters_blob = { - discard_const_p(uint8_t, kdf_parameters), - sizeof kdf_parameters}; - - ret = ldb_msg_append_value(add_msg, - "msKds-KDFParam", - &kdf_parameters_blob, - LDB_FLAG_MOD_ADD); - if (ret) { - goto out; - } - } - { uint8_t guid_buf[sizeof((struct GUID_ndr_buf){}.buf)]; const DATA_BLOB guid_blob = {.data = guid_buf,