s4:dsdb: Add functions for GKDI root key creation
authorJo Sutton <josutton@catalyst.net.nz>
Tue, 13 Feb 2024 03:09:57 +0000 (16:09 +1300)
committerAndrew Bartlett <abartlet@samba.org>
Fri, 1 Mar 2024 00:19:45 +0000 (00:19 +0000)
Signed-off-by: Jo Sutton <josutton@catalyst.net.nz>
Reviewed-by: Andrew Bartlett <abartlet@samba.org>
source4/dsdb/gmsa/gkdi.c [new file with mode: 0644]
source4/dsdb/gmsa/gkdi.h [new file with mode: 0644]
source4/dsdb/samdb/samdb.h
source4/dsdb/wscript_build

diff --git a/source4/dsdb/gmsa/gkdi.c b/source4/dsdb/gmsa/gkdi.c
new file mode 100644 (file)
index 0000000..dfb9be8
--- /dev/null
@@ -0,0 +1,356 @@
+/*
+   Unix SMB/CIFS implementation.
+   Group Key Distribution Protocol functions
+
+   Copyright (C) Catalyst.Net Ltd 2024
+
+   This program is free software: you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation, either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <https://www.gnu.org/licenses/>.
+*/
+
+#include "includes.h"
+#include <ldb.h>
+#include <ldb_errors.h>
+#include <ldb_module.h>
+#include "lib/crypto/gkdi.h"
+#include "lib/util/data_blob.h"
+#include "lib/util/samba_util.h"
+#include "lib/util/util_str_hex.h"
+#include "librpc/ndr/libndr.h"
+#include "dsdb/gmsa/gkdi.h"
+#include "dsdb/samdb/ldb_modules/util.h"
+#include "dsdb/samdb/samdb.h"
+
+static int gkdi_create_root_key(TALLOC_CTX *mem_ctx,
+                               struct ldb_context *const ldb,
+                               const NTTIME current_time,
+                               const NTTIME use_start_time,
+                               struct GUID *const root_key_id_out,
+                               struct ldb_dn **const root_key_dn_out)
+{
+       TALLOC_CTX *tmp_ctx = NULL;
+       struct GUID root_key_id;
+       struct ldb_message *add_msg = NULL;
+       NTSTATUS status = NT_STATUS_OK;
+       int ret = LDB_SUCCESS;
+
+       *root_key_dn_out = NULL;
+
+       tmp_ctx = talloc_new(mem_ctx);
+       if (tmp_ctx == NULL) {
+               ret = ldb_oom(ldb);
+               goto out;
+       }
+
+       add_msg = ldb_msg_new(tmp_ctx);
+       if (add_msg == NULL) {
+               ret = ldb_oom(ldb);
+               goto out;
+       }
+
+       ret = ldb_msg_append_string(add_msg,
+                                   "objectClass",
+                                   "msKds-ProvRootKey",
+                                   LDB_FLAG_MOD_ADD);
+       if (ret) {
+               goto out;
+       }
+
+       {
+               uint8_t root_key_data[GKDI_KEY_LEN];
+               const DATA_BLOB root_key_data_blob = {
+                       .data = root_key_data, .length = sizeof root_key_data};
+
+               generate_secret_buffer(root_key_data, sizeof root_key_data);
+
+               ret = ldb_msg_append_value(add_msg,
+                                          "msKds-RootKeyData",
+                                          &root_key_data_blob,
+                                          LDB_FLAG_MOD_ADD);
+               if (ret) {
+                       goto out;
+               }
+       }
+
+       ret = samdb_msg_append_uint64(ldb,
+                                     tmp_ctx,
+                                     add_msg,
+                                     "msKds-CreateTime",
+                                     current_time,
+                                     LDB_FLAG_MOD_ADD);
+       if (ret) {
+               goto out;
+       }
+
+       ret = samdb_msg_append_uint64(ldb,
+                                     tmp_ctx,
+                                     add_msg,
+                                     "msKds-UseStartTime",
+                                     use_start_time,
+                                     LDB_FLAG_MOD_ADD);
+       if (ret) {
+               goto out;
+       }
+
+       {
+               struct ldb_dn *domain_dn = NULL;
+
+               ret = samdb_server_reference_dn(ldb, tmp_ctx, &domain_dn);
+               if (ret) {
+                       goto out;
+               }
+
+               ret = ldb_msg_append_linearized_dn(add_msg,
+                                                  "msKds-DomainID",
+                                                  domain_dn,
+                                                  LDB_FLAG_MOD_ADD);
+               if (ret) {
+                       goto out;
+               }
+       }
+
+       ret = ldb_msg_append_string(add_msg,
+                                   "msKds-Version",
+                                   "1",
+                                   LDB_FLAG_MOD_ADD);
+       if (ret) {
+               goto out;
+       }
+
+       ret = ldb_msg_append_string(add_msg,
+                                   "msKds-KDFAlgorithmID",
+                                   "SP800_108_CTR_HMAC",
+                                   LDB_FLAG_MOD_ADD);
+       if (ret) {
+               goto out;
+       }
+
+       ret = ldb_msg_append_string(add_msg,
+                                   "msKds-SecretAgreementAlgorithmID",
+                                   "DH",
+                                   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};
+
+               ret = ldb_msg_append_value(add_msg,
+                                          "msKds-SecretAgreementParam",
+                                          &ffc_dh_parameters_blob,
+                                          LDB_FLAG_MOD_ADD);
+               if (ret) {
+                       goto out;
+               }
+       }
+
+       ret = ldb_msg_append_string(add_msg,
+                                   "msKds-PublicKeyLength",
+                                   "2048",
+                                   LDB_FLAG_MOD_ADD);
+       if (ret) {
+               goto out;
+       }
+
+       ret = ldb_msg_append_string(add_msg,
+                                   "msKds-PrivateKeyLength",
+                                   "512",
+                                   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,
+                                            .length = sizeof guid_buf};
+
+               generate_secret_buffer(guid_buf, sizeof guid_buf);
+
+               status = GUID_from_ndr_blob(&guid_blob, &root_key_id);
+               if (!NT_STATUS_IS_OK(status)) {
+                       ret = ldb_operr(ldb);
+                       goto out;
+               }
+       }
+
+       {
+               struct ldb_dn *root_key_dn = NULL;
+
+               root_key_dn = samdb_gkdi_root_key_dn(ldb,
+                                                    tmp_ctx,
+                                                    &root_key_id);
+               if (root_key_dn == NULL) {
+                       ret = ldb_operr(ldb);
+                       goto out;
+               }
+
+               add_msg->dn = root_key_dn;
+       }
+
+       ret = dsdb_add(ldb, add_msg, 0);
+       if (ret) {
+               goto out;
+       }
+
+       *root_key_id_out = root_key_id;
+       *root_key_dn_out = talloc_steal(mem_ctx, add_msg->dn);
+
+out:
+       talloc_free(tmp_ctx);
+       return ret;
+}
+
+/*
+ * The PrivateKey, PublicKey, and SecretAgreement attributes are related to the
+ * public‐key functionality in GKDI. Samba doesn’t try to implement any of that,
+ * so we don’t bother looking at these attributes.
+ */
+static const char *const root_key_attrs[] = {
+       "msKds-CreateTime",
+       "msKds-DomainID",
+       "msKds-KDFAlgorithmID",
+       "msKds-KDFParam",
+       /* "msKds-PrivateKeyLength", */
+       /* "msKds-PublicKeyLength", */
+       "msKds-RootKeyData",
+       /* "msKds-SecretAgreementAlgorithmID", */
+       /* "msKds-SecretAgreementParam", */
+       "msKds-UseStartTime",
+       "msKds-Version",
+       NULL,
+};
+
+/*
+ * Create and return a new GKDI root key.
+ *
+ * This function goes unused.
+ */
+int gkdi_new_root_key(TALLOC_CTX *mem_ctx,
+                     struct ldb_context *const ldb,
+                     const NTTIME current_time,
+                     const NTTIME use_start_time,
+                     struct GUID *const root_key_id_out,
+                     const struct ldb_message **const root_key_out)
+{
+       TALLOC_CTX *tmp_ctx = NULL;
+       struct ldb_dn *root_key_dn = NULL;
+       struct ldb_result *res = NULL;
+       int ret = LDB_SUCCESS;
+
+       *root_key_out = NULL;
+
+       tmp_ctx = talloc_new(mem_ctx);
+       if (tmp_ctx == NULL) {
+               ret = ldb_oom(ldb);
+               goto out;
+       }
+
+       ret = gkdi_create_root_key(tmp_ctx,
+                                  ldb,
+                                  current_time,
+                                  use_start_time,
+                                  root_key_id_out,
+                                  &root_key_dn);
+       if (ret) {
+               goto out;
+       }
+
+       ret = dsdb_search_dn(
+               ldb, tmp_ctx, &res, root_key_dn, root_key_attrs, 0);
+       if (ret) {
+               goto out;
+       }
+
+       if (res->count != 1) {
+               ret = LDB_ERR_NO_SUCH_OBJECT;
+               goto out;
+       }
+
+       *root_key_out = talloc_steal(mem_ctx, res->msgs[0]);
+
+out:
+       talloc_free(tmp_ctx);
+       return ret;
+}
diff --git a/source4/dsdb/gmsa/gkdi.h b/source4/dsdb/gmsa/gkdi.h
new file mode 100644 (file)
index 0000000..e6e3606
--- /dev/null
@@ -0,0 +1,46 @@
+/*
+   Unix SMB/CIFS implementation.
+   Group Key Distribution Protocol functions
+
+   Copyright (C) Catalyst.Net Ltd 2024
+
+   This program is free software: you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation, either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <https://www.gnu.org/licenses/>.
+*/
+
+#ifndef DSDB_GMSA_GKDI_H
+#define DSDB_GMSA_GKDI_H
+
+#include <talloc.h>
+#include "lib/util/data_blob.h"
+#include "lib/util/time.h"
+#include "libcli/util/ntstatus.h"
+#include "librpc/gen_ndr/misc.h"
+
+struct ldb_message;
+
+/*
+ * Create and return a new GKDI root key.
+ *
+ * This function goes unused.
+ */
+struct ldb_context;
+int gkdi_new_root_key(TALLOC_CTX *mem_ctx,
+                     struct ldb_context *const ldb,
+                     const NTTIME current_time,
+                     const NTTIME use_start_time,
+                     struct GUID *const root_key_id_out,
+                     const struct ldb_message **const root_key_out);
+
+
+#endif /* DSDB_GMSA_GKDI_H */
index e2a2d962ec8bcffe31a1e009ed489797e8c7cebd..e3558c127093b87712256c47fb0106a3fe91882f 100644 (file)
@@ -31,6 +31,12 @@ struct loadparm_context;
 struct tevent_context;
 struct tsocket_address;
 struct dsdb_trust_routing_table;
+struct gmsa_update_pwd;
+struct gmsa_update_pwd_part;
+struct gmsa_update;
+struct gmsa_return_pwd;
+struct RootKey;
+struct KeyEnvelope;
 
 enum dsdb_password_checked {
        DSDB_PASSWORD_NOT_CHECKED = 0, /* unused */
index d0d6439b6210a3ec2de42b4aa82713fa9aba88b8..b263c72cc306b4ec86b8f9a34fc536491a30aa4b 100644 (file)
@@ -13,10 +13,10 @@ bld.SAMBA_LIBRARY('samdb',
        )
 
 bld.SAMBA_LIBRARY('samdb-common',
-       source='common/util.c common/util_trusts.c common/util_groups.c common/util_samr.c common/dsdb_dn.c common/dsdb_access.c common/util_links.c common/rodc_helper.c',
+       source='common/util.c common/util_trusts.c common/util_groups.c common/util_samr.c common/dsdb_dn.c common/dsdb_access.c common/util_links.c common/rodc_helper.c gmsa/gkdi.c',
        autoproto='common/proto.h',
        private_library=True,
-       deps='ldb NDR_DRSBLOBS util_ldb LIBCLI_AUTH samba-hostconfig samba_socket cli-ldap-common flag_mapping UTIL_RUNCMD SAMBA_VERSION samba-security'
+       deps='ldb NDR_DRSBLOBS util_ldb LIBCLI_AUTH samba-hostconfig samba_socket cli-ldap-common flag_mapping UTIL_RUNCMD SAMBA_VERSION samba-security gkdi gmsa'
        )