Line data Source code
1 : /*
2 : Unix SMB/CIFS implementation.
3 : Group Key Distribution Protocol functions
4 :
5 : Copyright (C) Catalyst.Net Ltd 2024
6 :
7 : This program is free software: you can redistribute it and/or modify
8 : it under the terms of the GNU General Public License as published by
9 : the Free Software Foundation, either version 3 of the License, or
10 : (at your option) any later version.
11 :
12 : This program is distributed in the hope that it will be useful,
13 : but WITHOUT ANY WARRANTY; without even the implied warranty of
14 : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 : GNU General Public License for more details.
16 :
17 : You should have received a copy of the GNU General Public License
18 : along with this program. If not, see <https://www.gnu.org/licenses/>.
19 : */
20 :
21 : #include "includes.h"
22 : #include <ldb.h>
23 : #include <ldb_errors.h>
24 : #include <ldb_module.h>
25 : #include "lib/crypto/gkdi.h"
26 : #include "lib/util/data_blob.h"
27 : #include "lib/util/samba_util.h"
28 : #include "lib/util/util_str_hex.h"
29 : #include "librpc/ndr/libndr.h"
30 : #include "dsdb/gmsa/gkdi.h"
31 : #include "dsdb/samdb/ldb_modules/util.h"
32 : #include "dsdb/samdb/samdb.h"
33 :
34 95 : static int gkdi_create_root_key(TALLOC_CTX *mem_ctx,
35 : struct ldb_context *const ldb,
36 : const NTTIME current_time,
37 : const NTTIME use_start_time,
38 : struct GUID *const root_key_id_out,
39 : struct ldb_dn **const root_key_dn_out)
40 : {
41 95 : TALLOC_CTX *tmp_ctx = NULL;
42 22 : struct GUID root_key_id;
43 95 : struct ldb_message *add_msg = NULL;
44 95 : NTSTATUS status = NT_STATUS_OK;
45 95 : int ret = LDB_SUCCESS;
46 :
47 95 : *root_key_dn_out = NULL;
48 :
49 95 : tmp_ctx = talloc_new(mem_ctx);
50 95 : if (tmp_ctx == NULL) {
51 0 : ret = ldb_oom(ldb);
52 0 : goto out;
53 : }
54 :
55 95 : add_msg = ldb_msg_new(tmp_ctx);
56 95 : if (add_msg == NULL) {
57 0 : ret = ldb_oom(ldb);
58 0 : goto out;
59 : }
60 :
61 95 : ret = ldb_msg_append_string(add_msg,
62 : "objectClass",
63 : "msKds-ProvRootKey",
64 : LDB_FLAG_MOD_ADD);
65 95 : if (ret) {
66 0 : goto out;
67 : }
68 :
69 : {
70 22 : uint8_t root_key_data[GKDI_KEY_LEN];
71 95 : const DATA_BLOB root_key_data_blob = {
72 : .data = root_key_data, .length = sizeof root_key_data};
73 :
74 95 : generate_secret_buffer(root_key_data, sizeof root_key_data);
75 :
76 95 : ret = ldb_msg_append_value(add_msg,
77 : "msKds-RootKeyData",
78 : &root_key_data_blob,
79 : LDB_FLAG_MOD_ADD);
80 95 : if (ret) {
81 0 : goto out;
82 : }
83 : }
84 :
85 95 : ret = samdb_msg_append_uint64(ldb,
86 : tmp_ctx,
87 : add_msg,
88 : "msKds-CreateTime",
89 : current_time,
90 : LDB_FLAG_MOD_ADD);
91 95 : if (ret) {
92 0 : goto out;
93 : }
94 :
95 95 : ret = samdb_msg_append_uint64(ldb,
96 : tmp_ctx,
97 : add_msg,
98 : "msKds-UseStartTime",
99 : use_start_time,
100 : LDB_FLAG_MOD_ADD);
101 95 : if (ret) {
102 0 : goto out;
103 : }
104 :
105 : {
106 95 : struct ldb_dn *domain_dn = NULL;
107 :
108 95 : ret = samdb_server_reference_dn(ldb, tmp_ctx, &domain_dn);
109 95 : if (ret) {
110 0 : goto out;
111 : }
112 :
113 95 : ret = ldb_msg_append_linearized_dn(add_msg,
114 : "msKds-DomainID",
115 : domain_dn,
116 : LDB_FLAG_MOD_ADD);
117 95 : if (ret) {
118 0 : goto out;
119 : }
120 : }
121 :
122 95 : ret = ldb_msg_append_string(add_msg,
123 : "msKds-Version",
124 : "1",
125 : LDB_FLAG_MOD_ADD);
126 95 : if (ret) {
127 0 : goto out;
128 : }
129 :
130 95 : ret = ldb_msg_append_string(add_msg,
131 : "msKds-KDFAlgorithmID",
132 : "SP800_108_CTR_HMAC",
133 : LDB_FLAG_MOD_ADD);
134 95 : if (ret) {
135 0 : goto out;
136 : }
137 :
138 95 : ret = ldb_msg_append_string(add_msg,
139 : "msKds-SecretAgreementAlgorithmID",
140 : "DH",
141 : LDB_FLAG_MOD_ADD);
142 95 : if (ret) {
143 0 : goto out;
144 : }
145 :
146 : {
147 22 : static const uint8_t ffc_dh_parameters[] = {
148 : 12, 2, 0, 0, 68, 72, 80, 77, 0, 1, 0,
149 : 0, 135, 168, 230, 29, 180, 182, 102, 60, 255, 187,
150 : 209, 156, 101, 25, 89, 153, 140, 238, 246, 8, 102,
151 : 13, 208, 242, 93, 44, 238, 212, 67, 94, 59, 0,
152 : 224, 13, 248, 241, 214, 25, 87, 212, 250, 247, 223,
153 : 69, 97, 178, 170, 48, 22, 195, 217, 17, 52, 9,
154 : 111, 170, 59, 244, 41, 109, 131, 14, 154, 124, 32,
155 : 158, 12, 100, 151, 81, 122, 189, 90, 138, 157, 48,
156 : 107, 207, 103, 237, 145, 249, 230, 114, 91, 71, 88,
157 : 192, 34, 224, 177, 239, 66, 117, 191, 123, 108, 91,
158 : 252, 17, 212, 95, 144, 136, 185, 65, 245, 78, 177,
159 : 229, 155, 184, 188, 57, 160, 191, 18, 48, 127, 92,
160 : 79, 219, 112, 197, 129, 178, 63, 118, 182, 58, 202,
161 : 225, 202, 166, 183, 144, 45, 82, 82, 103, 53, 72,
162 : 138, 14, 241, 60, 109, 154, 81, 191, 164, 171, 58,
163 : 216, 52, 119, 150, 82, 77, 142, 246, 161, 103, 181,
164 : 164, 24, 37, 217, 103, 225, 68, 229, 20, 5, 100,
165 : 37, 28, 202, 203, 131, 230, 180, 134, 246, 179, 202,
166 : 63, 121, 113, 80, 96, 38, 192, 184, 87, 246, 137,
167 : 150, 40, 86, 222, 212, 1, 10, 189, 11, 230, 33,
168 : 195, 163, 150, 10, 84, 231, 16, 195, 117, 242, 99,
169 : 117, 215, 1, 65, 3, 164, 181, 67, 48, 193, 152,
170 : 175, 18, 97, 22, 210, 39, 110, 17, 113, 95, 105,
171 : 56, 119, 250, 215, 239, 9, 202, 219, 9, 74, 233,
172 : 30, 26, 21, 151, 63, 179, 44, 155, 115, 19, 77,
173 : 11, 46, 119, 80, 102, 96, 237, 189, 72, 76, 167,
174 : 177, 143, 33, 239, 32, 84, 7, 244, 121, 58, 26,
175 : 11, 161, 37, 16, 219, 193, 80, 119, 190, 70, 63,
176 : 255, 79, 237, 74, 172, 11, 181, 85, 190, 58, 108,
177 : 27, 12, 107, 71, 177, 188, 55, 115, 191, 126, 140,
178 : 111, 98, 144, 18, 40, 248, 194, 140, 187, 24, 165,
179 : 90, 227, 19, 65, 0, 10, 101, 1, 150, 249, 49,
180 : 199, 122, 87, 242, 221, 244, 99, 229, 233, 236, 20,
181 : 75, 119, 125, 230, 42, 170, 184, 168, 98, 138, 195,
182 : 118, 210, 130, 214, 237, 56, 100, 230, 121, 130, 66,
183 : 142, 188, 131, 29, 20, 52, 143, 111, 47, 145, 147,
184 : 181, 4, 90, 242, 118, 113, 100, 225, 223, 201, 103,
185 : 193, 251, 63, 46, 85, 164, 189, 27, 255, 232, 59,
186 : 156, 128, 208, 82, 185, 133, 209, 130, 234, 10, 219,
187 : 42, 59, 115, 19, 211, 254, 20, 200, 72, 75, 30,
188 : 5, 37, 136, 185, 183, 210, 187, 210, 223, 1, 97,
189 : 153, 236, 208, 110, 21, 87, 205, 9, 21, 179, 53,
190 : 59, 187, 100, 224, 236, 55, 127, 208, 40, 55, 13,
191 : 249, 43, 82, 199, 137, 20, 40, 205, 198, 126, 182,
192 : 24, 75, 82, 61, 29, 178, 70, 195, 47, 99, 7,
193 : 132, 144, 240, 14, 248, 214, 71, 209, 72, 212, 121,
194 : 84, 81, 94, 35, 39, 207, 239, 152, 197, 130, 102,
195 : 75, 76, 15, 108, 196, 22, 89};
196 95 : const DATA_BLOB ffc_dh_parameters_blob = {
197 : discard_const_p(uint8_t, ffc_dh_parameters),
198 : sizeof ffc_dh_parameters};
199 :
200 95 : ret = ldb_msg_append_value(add_msg,
201 : "msKds-SecretAgreementParam",
202 : &ffc_dh_parameters_blob,
203 : LDB_FLAG_MOD_ADD);
204 95 : if (ret) {
205 0 : goto out;
206 : }
207 : }
208 :
209 95 : ret = ldb_msg_append_string(add_msg,
210 : "msKds-PublicKeyLength",
211 : "2048",
212 : LDB_FLAG_MOD_ADD);
213 95 : if (ret) {
214 0 : goto out;
215 : }
216 :
217 95 : ret = ldb_msg_append_string(add_msg,
218 : "msKds-PrivateKeyLength",
219 : "512",
220 : LDB_FLAG_MOD_ADD);
221 95 : if (ret) {
222 0 : goto out;
223 : }
224 :
225 : {
226 22 : static const uint8_t kdf_parameters[] = {
227 : 0, 0, 0, 0, 1, 0, 0, 0, 14, 0,
228 : 0, 0, 0, 0, 0, 0, 'S', 0, 'H', 0,
229 : 'A', 0, '5', 0, '1', 0, '2', 0, 0, 0,
230 : };
231 95 : const DATA_BLOB kdf_parameters_blob = {
232 : discard_const_p(uint8_t, kdf_parameters),
233 : sizeof kdf_parameters};
234 :
235 95 : ret = ldb_msg_append_value(add_msg,
236 : "msKds-KDFParam",
237 : &kdf_parameters_blob,
238 : LDB_FLAG_MOD_ADD);
239 95 : if (ret) {
240 0 : goto out;
241 : }
242 : }
243 :
244 : {
245 22 : uint8_t guid_buf[sizeof((struct GUID_ndr_buf){}.buf)];
246 95 : const DATA_BLOB guid_blob = {.data = guid_buf,
247 : .length = sizeof guid_buf};
248 :
249 95 : generate_secret_buffer(guid_buf, sizeof guid_buf);
250 :
251 95 : status = GUID_from_ndr_blob(&guid_blob, &root_key_id);
252 95 : if (!NT_STATUS_IS_OK(status)) {
253 0 : ret = ldb_operr(ldb);
254 0 : goto out;
255 : }
256 : }
257 :
258 : {
259 95 : struct ldb_dn *root_key_dn = NULL;
260 :
261 95 : root_key_dn = samdb_gkdi_root_key_dn(ldb,
262 : tmp_ctx,
263 : &root_key_id);
264 95 : if (root_key_dn == NULL) {
265 0 : ret = ldb_operr(ldb);
266 0 : goto out;
267 : }
268 :
269 95 : add_msg->dn = root_key_dn;
270 : }
271 :
272 95 : ret = dsdb_add(ldb, add_msg, 0);
273 95 : if (ret) {
274 1 : goto out;
275 : }
276 :
277 94 : *root_key_id_out = root_key_id;
278 94 : *root_key_dn_out = talloc_steal(mem_ctx, add_msg->dn);
279 :
280 95 : out:
281 95 : talloc_free(tmp_ctx);
282 95 : return ret;
283 : }
284 :
285 : /*
286 : * The PrivateKey, PublicKey, and SecretAgreement attributes are related to the
287 : * public‐key functionality in GKDI. Samba doesn’t try to implement any of that,
288 : * so we don’t bother looking at these attributes.
289 : */
290 : static const char *const root_key_attrs[] = {
291 : "msKds-CreateTime",
292 : "msKds-DomainID",
293 : "msKds-KDFAlgorithmID",
294 : "msKds-KDFParam",
295 : /* "msKds-PrivateKeyLength", */
296 : /* "msKds-PublicKeyLength", */
297 : "msKds-RootKeyData",
298 : /* "msKds-SecretAgreementAlgorithmID", */
299 : /* "msKds-SecretAgreementParam", */
300 : "msKds-UseStartTime",
301 : "msKds-Version",
302 : NULL,
303 : };
304 :
305 : /*
306 : * Create and return a new GKDI root key.
307 : *
308 : * This function goes unused.
309 : */
310 95 : int gkdi_new_root_key(TALLOC_CTX *mem_ctx,
311 : struct ldb_context *const ldb,
312 : const NTTIME current_time,
313 : const NTTIME use_start_time,
314 : struct GUID *const root_key_id_out,
315 : const struct ldb_message **const root_key_out)
316 : {
317 95 : TALLOC_CTX *tmp_ctx = NULL;
318 95 : struct ldb_dn *root_key_dn = NULL;
319 95 : struct ldb_result *res = NULL;
320 95 : int ret = LDB_SUCCESS;
321 :
322 95 : *root_key_out = NULL;
323 :
324 95 : tmp_ctx = talloc_new(mem_ctx);
325 95 : if (tmp_ctx == NULL) {
326 0 : ret = ldb_oom(ldb);
327 0 : goto out;
328 : }
329 :
330 95 : ret = gkdi_create_root_key(tmp_ctx,
331 : ldb,
332 : current_time,
333 : use_start_time,
334 : root_key_id_out,
335 : &root_key_dn);
336 95 : if (ret) {
337 1 : goto out;
338 : }
339 :
340 94 : ret = dsdb_search_dn(
341 : ldb, tmp_ctx, &res, root_key_dn, root_key_attrs, 0);
342 94 : if (ret) {
343 0 : goto out;
344 : }
345 :
346 94 : if (res->count != 1) {
347 0 : ret = LDB_ERR_NO_SUCH_OBJECT;
348 0 : goto out;
349 : }
350 :
351 94 : *root_key_out = talloc_steal(mem_ctx, res->msgs[0]);
352 :
353 95 : out:
354 95 : talloc_free(tmp_ctx);
355 95 : return ret;
356 : }
|