Line data Source code
1 : /*
2 : ldb database library
3 :
4 : Copyright (C) Andrew Bartlett <abartlet@samba.org> 2017
5 :
6 : This program is free software; you can redistribute it and/or modify
7 : it under the terms of the GNU General Public License as published by
8 : the Free Software Foundation; either version 3 of the License, or
9 : (at your option) any later version.
10 :
11 : This program is distributed in the hope that it will be useful,
12 : but WITHOUT ANY WARRANTY; without even the implied warranty of
13 : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 : GNU General Public License for more details.
15 :
16 : You should have received a copy of the GNU General Public License
17 : along with this program. If not, see <http://www.gnu.org/licenses/>.
18 : */
19 :
20 : /*
21 : * Encrypt the samba secret attributes on disk. This is intended to
22 : * mitigate the inadvertent disclosure of the sam.ldb file, and to mitigate
23 : * memory read attacks.
24 : *
25 : * Currently the key file is stored in the same directory as sam.ldb but
26 : * this could be changed at a later date to use an HSM or similar mechanism
27 : * to protect the key.
28 : *
29 : * Data is encrypted with AES 128 GCM. The encryption uses gnutls where
30 : * available and if it supports AES 128 GCM AEAD modes, otherwise the
31 : * samba internal implementation is used.
32 : *
33 : */
34 :
35 : #include "includes.h"
36 : #include <ldb_module.h>
37 :
38 : #include "librpc/gen_ndr/ndr_drsblobs.h"
39 : #include "dsdb/samdb/samdb.h"
40 : #include "dsdb/samdb/ldb_modules/util.h"
41 :
42 : #include <gnutls/gnutls.h>
43 : #include <gnutls/crypto.h>
44 :
45 : static const char * const secret_attributes[] = {DSDB_SECRET_ATTRIBUTES};
46 : static const size_t num_secret_attributes = ARRAY_SIZE(secret_attributes);
47 :
48 : #define SECRET_ATTRIBUTE_VERSION 1
49 : #define SECRET_ENCRYPTION_ALGORITHM ENC_SECRET_AES_128_AEAD
50 : #define NUMBER_OF_KEYS 1
51 : #define SECRETS_KEY_FILE "encrypted_secrets.key"
52 :
53 : #undef strcasecmp
54 :
55 : struct es_data {
56 : /*
57 : * Should secret attributes be encrypted and decrypted?
58 : */
59 : bool encrypt_secrets;
60 : /*
61 : * Encryption keys for secret attributes
62 : */
63 : DATA_BLOB keys[NUMBER_OF_KEYS];
64 : /*
65 : * The gnutls algorithm used to encrypt attributes
66 : */
67 : int encryption_algorithm;
68 : };
69 :
70 : /*
71 : * @brief Get the key used to encrypt and decrypt secret attributes on disk.
72 : *
73 : * @param data the private context data for this module.
74 : *
75 : * @return A data blob containing the key.
76 : * This should be treated as read only.
77 : */
78 1066518 : static const DATA_BLOB get_key(const struct es_data *data) {
79 :
80 1066518 : return data->keys[0];
81 : }
82 :
83 : /*
84 : * @brief Get the directory containing the key files.
85 : *
86 : * @param ctx talloc memory context that will own the return value
87 : * @param ldb ldb context, to allow logging
88 : *
89 : * @return zero terminated string, the directory containing the key file
90 : * allocated on ctx.
91 : *
92 : */
93 167173 : static const char* get_key_directory(TALLOC_CTX *ctx, struct ldb_context *ldb)
94 : {
95 :
96 167173 : const char *sam_ldb_path = NULL;
97 167173 : const char *private_dir = NULL;
98 167173 : char *p = NULL;
99 :
100 :
101 : /*
102 : * Work out where *our* key file is. It must be in
103 : * the same directory as sam.ldb
104 : */
105 167173 : sam_ldb_path = ldb_get_opaque(ldb, "ldb_url");
106 167173 : if (sam_ldb_path == NULL) {
107 0 : ldb_set_errstring(ldb, "Unable to get ldb_url\n");
108 0 : return NULL;
109 : }
110 :
111 167173 : if (strncmp("tdb://", sam_ldb_path, 6) == 0) {
112 6659 : sam_ldb_path += 6;
113 : }
114 160514 : else if (strncmp("ldb://", sam_ldb_path, 6) == 0) {
115 52 : sam_ldb_path += 6;
116 : }
117 160462 : else if (strncmp("mdb://", sam_ldb_path, 6) == 0) {
118 12 : sam_ldb_path += 6;
119 : }
120 167173 : private_dir = talloc_strdup(ctx, sam_ldb_path);
121 167173 : if (private_dir == NULL) {
122 0 : ldb_set_errstring(ldb,
123 : "Out of memory building encrypted "
124 : "secrets key\n");
125 0 : return NULL;
126 : }
127 :
128 167173 : p = strrchr(private_dir, '/');
129 167173 : if (p != NULL) {
130 167149 : *p = '\0';
131 : } else {
132 24 : private_dir = talloc_strdup(ctx, ".");
133 : }
134 :
135 161212 : return private_dir;
136 : }
137 :
138 : /*
139 : * @brief log details of an error that set errno
140 : *
141 : * @param ldb ldb context, to allow logging.
142 : * @param err the value of errno.
143 : * @param desc extra text to help describe the error.
144 : *
145 : */
146 0 : static void log_error(struct ldb_context *ldb, int err, const char *desc)
147 : {
148 0 : char buf[1024];
149 0 : int e = strerror_r(err, buf, sizeof(buf));
150 0 : if (e != 0) {
151 0 : strlcpy(buf, "Unknown error", sizeof(buf)-1);
152 : }
153 0 : ldb_asprintf_errstring(ldb, "Error (%d) %s - %s\n", err, buf, desc);
154 0 : }
155 :
156 : /*
157 : * @brief Load the keys into the encrypted secrets module context.
158 : *
159 : * @param module the current ldb module
160 : * @param data the private data for the current module
161 : *
162 : * Currently the keys are stored in a binary file in the same directory
163 : * as the database.
164 : *
165 : * @return an LDB result code.
166 : *
167 : */
168 167173 : static int load_keys(struct ldb_module *module, struct es_data *data)
169 : {
170 :
171 167173 : const char *key_dir = NULL;
172 167173 : const char *key_path = NULL;
173 :
174 167173 : struct ldb_context *ldb = NULL;
175 167173 : FILE *fp = NULL;
176 167173 : const int key_size = 16;
177 5961 : int read;
178 167173 : DATA_BLOB key = data_blob_null;
179 :
180 167173 : TALLOC_CTX *frame = talloc_stackframe();
181 :
182 167173 : ldb = ldb_module_get_ctx(module);
183 167173 : key_dir = get_key_directory(frame, ldb);
184 167173 : if (key_dir == NULL) {
185 0 : TALLOC_FREE(frame);
186 0 : return LDB_ERR_OPERATIONS_ERROR;
187 : }
188 :
189 167173 : key_path = talloc_asprintf(frame, "%s/%s", key_dir, SECRETS_KEY_FILE);
190 167173 : if (key_path == NULL) {
191 0 : TALLOC_FREE(frame);
192 0 : return ldb_oom(ldb);
193 : }
194 :
195 :
196 167173 : key = data_blob_talloc_zero(module, key_size);
197 167173 : key.length = key_size;
198 :
199 167173 : fp = fopen(key_path, "rb");
200 167173 : if (fp == NULL) {
201 28 : TALLOC_FREE(frame);
202 28 : data_blob_free(&key);
203 28 : if (errno == ENOENT) {
204 28 : ldb_debug(ldb,
205 : LDB_DEBUG_WARNING,
206 : "No encrypted secrets key file. "
207 : "Secret attributes will not be encrypted or "
208 : "decrypted\n");
209 28 : data->encrypt_secrets = false;
210 28 : return LDB_SUCCESS;
211 : } else {
212 0 : log_error(ldb,
213 0 : errno,
214 : "Opening encrypted_secrets key file\n");
215 0 : return LDB_ERR_OPERATIONS_ERROR;
216 : }
217 : }
218 :
219 167145 : read = fread(key.data, 1, key.length, fp);
220 167145 : fclose(fp);
221 167145 : if (read == 0) {
222 0 : TALLOC_FREE(frame);
223 0 : ldb_debug(ldb,
224 : LDB_DEBUG_WARNING,
225 : "Zero length encrypted secrets key file. "
226 : "Secret attributes will not be encrypted or "
227 : "decrypted\n");
228 0 : data->encrypt_secrets = false;
229 0 : return LDB_SUCCESS;
230 : }
231 167145 : if (read != key.length) {
232 2 : TALLOC_FREE(frame);
233 2 : if (errno) {
234 0 : log_error(ldb,
235 0 : errno,
236 : "Reading encrypted_secrets key file\n");
237 : } else {
238 2 : ldb_debug(ldb,
239 : LDB_DEBUG_ERROR,
240 : "Invalid encrypted_secrets key file, "
241 : "only %d bytes read should be %d bytes\n",
242 : read,
243 : key_size);
244 : }
245 2 : return LDB_ERR_OPERATIONS_ERROR;
246 : }
247 :
248 167143 : data->keys[0] = key;
249 167143 : data->encrypt_secrets = true;
250 167143 : data->encryption_algorithm = GNUTLS_CIPHER_AES_128_GCM;
251 167143 : TALLOC_FREE(frame);
252 :
253 161186 : return LDB_SUCCESS;
254 :
255 : }
256 :
257 : /*
258 : * @brief should this element be encrypted.
259 : *
260 : * @param el the element to examine
261 : *
262 : * @return true if the element should be encrypted,
263 : * false otherwise.
264 : */
265 21720897 : static bool should_encrypt(const struct ldb_message_element *el)
266 : {
267 1783238 : size_t i;
268 :
269 324919326 : for (i = 0; i < ARRAY_SIZE(secret_attributes); i++) {
270 303351231 : if (strcasecmp(secret_attributes[i], el->name) == 0) {
271 151609 : return true;
272 : }
273 : }
274 19786050 : return false;
275 : }
276 :
277 : /*
278 : * @brief Round a size up to a multiple of the encryption cipher block size.
279 : *
280 : * @param block_size The cipher block size
281 : * @param size The size to round
282 : *
283 : * @return Size rounded up to the nearest multiple of block_size
284 : */
285 58138 : static size_t round_to_block_size(size_t block_size, size_t size)
286 : {
287 58138 : if ((size % block_size) == 0) {
288 37888 : return size;
289 : } else {
290 19831 : return ((int)(size/block_size) + 1) * block_size;
291 : }
292 : }
293 :
294 : /*
295 : * @brief Create an new EncryptedSecret owned by the supplied talloc context.
296 : *
297 : * Create a new encrypted secret and initialise the header.
298 : *
299 : * @param ldb ldb context, to allow logging.
300 : * @param ctx The talloc memory context that will own the new EncryptedSecret
301 : *
302 : * @return pointer to the new encrypted secret, or NULL if there was an error
303 : */
304 58146 : static struct EncryptedSecret *makeEncryptedSecret(struct ldb_context *ldb,
305 : TALLOC_CTX *ctx)
306 : {
307 58146 : struct EncryptedSecret *es = NULL;
308 :
309 58146 : es = talloc_zero_size(ctx, sizeof(struct EncryptedSecret));
310 58146 : if (es == NULL) {
311 0 : ldb_set_errstring(ldb,
312 : "Out of memory, allocating "
313 : "struct EncryptedSecret\n");
314 0 : return NULL;
315 : }
316 58146 : es->header.magic = ENCRYPTED_SECRET_MAGIC_VALUE;
317 58146 : es->header.version = SECRET_ATTRIBUTE_VERSION;
318 58146 : es->header.algorithm = SECRET_ENCRYPTION_ALGORITHM;
319 58146 : es->header.flags = 0;
320 58146 : return es;
321 : }
322 :
323 : /*
324 : * @brief Allocate and populate a data blob with a PlaintextSecret structure.
325 : *
326 : * Allocate a new data blob and populate it with a serialised PlaintextSecret,
327 : * containing the ldb_val
328 : *
329 : * @param ctx The talloc memory context that will own the allocated memory.
330 : * @param ldb ldb context, to allow logging.
331 : * @param val The ldb value to serialise.
332 : *
333 : * @return The populated data blob or data_blob_null if there was an error.
334 : */
335 58138 : static DATA_BLOB makePlainText(TALLOC_CTX *ctx,
336 : struct ldb_context *ldb,
337 : const struct ldb_val val)
338 : {
339 58138 : struct PlaintextSecret ps = { .cleartext = data_blob_null};
340 58138 : DATA_BLOB pt = data_blob_null;
341 654 : int rc;
342 :
343 58138 : ps.cleartext.length = val.length;
344 58138 : ps.cleartext.data = val.data;
345 :
346 58138 : rc = ndr_push_struct_blob(&pt,
347 : ctx,
348 : &ps,
349 : (ndr_push_flags_fn_t)
350 : ndr_push_PlaintextSecret);
351 58138 : if (!NDR_ERR_CODE_IS_SUCCESS(rc)) {
352 0 : ldb_set_errstring(ldb,
353 : "Unable to ndr push PlaintextSecret\n");
354 0 : return data_blob_null;
355 : }
356 58138 : return pt;
357 : }
358 :
359 :
360 : /*
361 : * Helper function converts a data blob to a gnutls_datum_t.
362 : * Note that this does not copy the data.
363 : * So the returned value should be treated as read only.
364 : * And that changes to the length of the underlying DATA_BLOB
365 : * will not be reflected in the returned object.
366 : *
367 : */
368 1066518 : static const gnutls_datum_t convert_from_data_blob(DATA_BLOB blob) {
369 :
370 1066518 : const gnutls_datum_t datum = {
371 1033035 : .size = blob.length,
372 1033035 : .data = blob.data,
373 : };
374 1066518 : return datum;
375 : }
376 :
377 : /*
378 : * @brief Get the gnutls algorithm needed to decrypt the EncryptedSecret
379 : *
380 : * @param ldb ldb context, to allow logging.
381 : * @param es the encrypted secret
382 : *
383 : * @return The gnutls algorithm number, or 0 if there is no match.
384 : *
385 : */
386 1008380 : static int gnutls_get_algorithm(struct ldb_context *ldb,
387 : struct EncryptedSecret *es) {
388 :
389 1008380 : switch (es->header.algorithm) {
390 975551 : case ENC_SECRET_AES_128_AEAD:
391 975551 : return GNUTLS_CIPHER_AES_128_GCM;
392 0 : default:
393 0 : ldb_asprintf_errstring(ldb,
394 : "Unsupported encryption algorithm %d\n",
395 : es->header.algorithm);
396 0 : return 0;
397 : }
398 : }
399 :
400 : /*
401 : *
402 : * @param err Pointer to an error code, set to:
403 : * LDB_SUCESS If the value was successfully encrypted
404 : * LDB_ERR_OPERATIONS_ERROR If there was an error.
405 : *
406 : * @param ctx Talloc memory context the will own the memory allocated
407 : * @param ldb ldb context, to allow logging.
408 : * @param val The ldb value to encrypt, not altered or freed
409 : * @param data The context data for this module.
410 : *
411 : * @return The encrypted ldb_val, or data_blob_null if there was an error.
412 : */
413 58138 : static struct ldb_val gnutls_encrypt_aead(int *err,
414 : TALLOC_CTX *ctx,
415 : struct ldb_context *ldb,
416 : const struct ldb_val val,
417 : const struct es_data *data)
418 : {
419 58138 : struct EncryptedSecret *es = NULL;
420 58138 : struct ldb_val enc = data_blob_null;
421 58138 : DATA_BLOB pt = data_blob_null;
422 654 : gnutls_aead_cipher_hd_t cipher_hnd;
423 654 : int rc;
424 :
425 58138 : TALLOC_CTX *frame = talloc_stackframe();
426 :
427 58138 : es = makeEncryptedSecret(ldb, frame);
428 58138 : if (es == NULL) {
429 0 : goto error_exit;
430 : }
431 :
432 58138 : pt = makePlainText(frame, ldb, val);
433 58138 : if (pt.length == 0) {
434 0 : goto error_exit;
435 : }
436 :
437 : /*
438 : * Set the encryption key and initialize the encryption handle.
439 : */
440 : {
441 58138 : const size_t key_size = gnutls_cipher_get_key_size(
442 58138 : data->encryption_algorithm);
443 654 : gnutls_datum_t cipher_key;
444 58138 : DATA_BLOB key_blob = get_key(data);
445 :
446 58138 : if (key_blob.length != key_size) {
447 0 : ldb_asprintf_errstring(ldb,
448 : "Invalid EncryptedSecrets key "
449 : "size, expected %zu bytes and "
450 : "it is %zu bytes\n",
451 : key_size,
452 : key_blob.length);
453 0 : goto error_exit;
454 : }
455 58138 : cipher_key = convert_from_data_blob(key_blob);
456 :
457 58138 : rc = gnutls_aead_cipher_init(&cipher_hnd,
458 57484 : data->encryption_algorithm,
459 : &cipher_key);
460 58138 : if (rc !=0) {
461 0 : ldb_asprintf_errstring(ldb,
462 : "gnutls_aead_cipher_init failed "
463 : "%s - %s\n",
464 : gnutls_strerror_name(rc),
465 : gnutls_strerror(rc));
466 0 : goto error_exit;
467 : }
468 :
469 : }
470 :
471 : /*
472 : * Set the initialisation vector
473 : */
474 : {
475 58138 : unsigned iv_size = gnutls_cipher_get_iv_size(
476 58138 : data->encryption_algorithm);
477 654 : uint8_t *iv;
478 :
479 58138 : iv = talloc_zero_size(frame, iv_size);
480 58138 : if (iv == NULL) {
481 0 : ldb_set_errstring(ldb,
482 : "Out of memory allocating IV\n");
483 0 : goto error_exit_handle;
484 : }
485 :
486 58138 : rc = gnutls_rnd(GNUTLS_RND_NONCE, iv, iv_size);
487 58138 : if (rc !=0) {
488 0 : ldb_asprintf_errstring(ldb,
489 : "gnutls_rnd failed %s - %s\n",
490 : gnutls_strerror_name(rc),
491 : gnutls_strerror(rc));
492 0 : goto error_exit_handle;
493 : }
494 58138 : es->iv.length = iv_size;
495 58138 : es->iv.data = iv;
496 : }
497 :
498 : /*
499 : * Encrypt the value.
500 : */
501 : {
502 58138 : const unsigned block_size = gnutls_cipher_get_block_size(
503 58138 : data->encryption_algorithm);
504 58138 : const unsigned tag_size = gnutls_cipher_get_tag_size(
505 57484 : data->encryption_algorithm);
506 58792 : const size_t ed_size = round_to_block_size(
507 : block_size,
508 58138 : sizeof(struct PlaintextSecret) + val.length);
509 58138 : const size_t en_size = ed_size + tag_size;
510 58138 : uint8_t *ct = talloc_zero_size(frame, en_size);
511 58138 : size_t el = en_size;
512 :
513 58138 : if (ct == NULL) {
514 0 : ldb_set_errstring(ldb,
515 : "Out of memory allocation cipher "
516 : "text\n");
517 0 : goto error_exit_handle;
518 : }
519 :
520 58792 : rc = gnutls_aead_cipher_encrypt(
521 : cipher_hnd,
522 58138 : es->iv.data,
523 : es->iv.length,
524 58138 : &es->header,
525 : sizeof(struct EncryptedSecretHeader),
526 : tag_size,
527 57484 : pt.data,
528 : pt.length,
529 : ct,
530 : &el);
531 58138 : if (rc !=0) {
532 0 : ldb_asprintf_errstring(ldb,
533 : "gnutls_aead_cipher_encrypt '"
534 : "failed %s - %s\n",
535 : gnutls_strerror_name(rc),
536 : gnutls_strerror(rc));
537 0 : *err = LDB_ERR_OPERATIONS_ERROR;
538 0 : return data_blob_null;
539 : }
540 58138 : es->encrypted.length = el;
541 58138 : es->encrypted.data = ct;
542 58138 : gnutls_aead_cipher_deinit(cipher_hnd);
543 : }
544 :
545 58138 : rc = ndr_push_struct_blob(&enc,
546 : ctx,
547 : es,
548 : (ndr_push_flags_fn_t)
549 : ndr_push_EncryptedSecret);
550 58138 : if (!NDR_ERR_CODE_IS_SUCCESS(rc)) {
551 0 : ldb_set_errstring(ldb,
552 : "Unable to ndr push EncryptedSecret\n");
553 0 : goto error_exit;
554 : }
555 58138 : TALLOC_FREE(frame);
556 58138 : return enc;
557 :
558 0 : error_exit_handle:
559 0 : gnutls_aead_cipher_deinit(cipher_hnd);
560 0 : error_exit:
561 0 : *err = LDB_ERR_OPERATIONS_ERROR;
562 0 : TALLOC_FREE(frame);
563 0 : return data_blob_null;
564 : }
565 :
566 : /*
567 : * @brief Decrypt data encrypted using an aead algorithm.
568 : *
569 : * Decrypt the data in ed and insert it into ev. The data was encrypted
570 : * with one of the gnutls aead compatible algorithms.
571 : *
572 : * @param err Pointer to an error code, set to:
573 : * LDB_SUCESS If the value was successfully decrypted
574 : * LDB_ERR_OPERATIONS_ERROR If there was an error.
575 : *
576 : * @param ctx The talloc context that will own the PlaintextSecret
577 : * @param ldb ldb context, to allow logging.
578 : * @param ev The value to be updated with the decrypted data.
579 : * @param ed The data to decrypt.
580 : * @param data The context data for this module.
581 : *
582 : * @return ev is updated with the unencrypted data.
583 : */
584 1008380 : static void gnutls_decrypt_aead(int *err,
585 : TALLOC_CTX *ctx,
586 : struct ldb_context *ldb,
587 : struct EncryptedSecret *es,
588 : struct PlaintextSecret *ps,
589 : const struct es_data *data)
590 : {
591 :
592 32829 : gnutls_aead_cipher_hd_t cipher_hnd;
593 1008380 : DATA_BLOB pt = data_blob_null;
594 32829 : const unsigned tag_size =
595 1008380 : gnutls_cipher_get_tag_size(es->header.algorithm);
596 32829 : int rc;
597 :
598 : /*
599 : * Get the encryption key and initialise the encryption handle
600 : */
601 : {
602 32829 : gnutls_datum_t cipher_key;
603 32829 : DATA_BLOB key_blob;
604 1008380 : const int algorithm = gnutls_get_algorithm(ldb, es);
605 1008380 : const size_t key_size = gnutls_cipher_get_key_size(algorithm);
606 1008380 : key_blob = get_key(data);
607 :
608 1008380 : if (algorithm == 0) {
609 0 : goto error_exit;
610 : }
611 :
612 1008380 : if (key_blob.length != key_size) {
613 0 : ldb_asprintf_errstring(ldb,
614 : "Invalid EncryptedSecrets key "
615 : "size, expected %zu bytes and "
616 : "it is %zu bytes\n",
617 : key_size,
618 : key_blob.length);
619 0 : goto error_exit;
620 : }
621 1008380 : cipher_key = convert_from_data_blob(key_blob);
622 :
623 1008380 : rc = gnutls_aead_cipher_init(
624 : &cipher_hnd,
625 : algorithm,
626 : &cipher_key);
627 1008380 : if (rc != 0) {
628 0 : ldb_asprintf_errstring(ldb,
629 : "gnutls_aead_cipher_init failed "
630 : "%s - %s\n",
631 : gnutls_strerror_name(rc),
632 : gnutls_strerror(rc));
633 0 : goto error_exit;
634 : }
635 : }
636 :
637 : /*
638 : * Decrypt and validate the encrypted value
639 : */
640 :
641 1008380 : pt.length = es->encrypted.length;
642 1008380 : pt.data = talloc_zero_size(ctx, es->encrypted.length);
643 :
644 1008380 : if (pt.data == NULL) {
645 0 : ldb_set_errstring(ldb,
646 : "Out of memory allocating plain text\n");
647 0 : goto error_exit_handle;
648 : }
649 :
650 1041209 : rc = gnutls_aead_cipher_decrypt(cipher_hnd,
651 1008380 : es->iv.data,
652 : es->iv.length,
653 1008380 : &es->header,
654 : sizeof(struct EncryptedSecretHeader),
655 : tag_size,
656 1008380 : es->encrypted.data,
657 : es->encrypted.length,
658 975551 : pt.data,
659 : &pt.length);
660 1008380 : if (rc != 0) {
661 : /*
662 : * Typically this will indicate that the data has been
663 : * corrupted i.e. the tag comparison has failed.
664 : * At the moment gnutls does not provide a separate
665 : * error code to indicate this
666 : */
667 6 : ldb_asprintf_errstring(ldb,
668 : "gnutls_aead_cipher_decrypt failed "
669 : "%s - %s. Data possibly corrupted or "
670 : "altered\n",
671 : gnutls_strerror_name(rc),
672 : gnutls_strerror(rc));
673 6 : goto error_exit_handle;
674 : }
675 1008374 : gnutls_aead_cipher_deinit(cipher_hnd);
676 :
677 1008374 : rc = ndr_pull_struct_blob(&pt,
678 : ctx,
679 : ps,
680 : (ndr_pull_flags_fn_t)
681 : ndr_pull_PlaintextSecret);
682 1008374 : if(!NDR_ERR_CODE_IS_SUCCESS(rc)) {
683 0 : ldb_asprintf_errstring(ldb,
684 : "Error(%d) unpacking decrypted data, "
685 : "data possibly corrupted or altered\n",
686 : rc);
687 0 : goto error_exit;
688 : }
689 975551 : return;
690 :
691 6 : error_exit_handle:
692 6 : gnutls_aead_cipher_deinit(cipher_hnd);
693 6 : error_exit:
694 6 : *err = LDB_ERR_OPERATIONS_ERROR;
695 6 : return;
696 : }
697 :
698 : /*
699 : * @brief Encrypt an attribute value using the default encryption algorithm.
700 : *
701 : * Returns an encrypted copy of the value, the original value is left intact.
702 : * The original content of val is encrypted and wrapped in an encrypted_value
703 : * structure.
704 : *
705 : * @param err Pointer to an error code, set to:
706 : * LDB_SUCESS If the value was successfully encrypted
707 : * LDB_ERR_OPERATIONS_ERROR If there was an error.
708 : *
709 : * @param ctx Talloc memory context the will own the memory allocated
710 : * @param ldb ldb context, to allow logging.
711 : * @param val The ldb value to encrypt, not altered or freed
712 : * @param data The context data for this module.
713 : *
714 : * @return The encrypted ldb_val, or data_blob_null if there was an error.
715 : */
716 58130 : static struct ldb_val encrypt_value(int *err,
717 : TALLOC_CTX *ctx,
718 : struct ldb_context *ldb,
719 : const struct ldb_val val,
720 : const struct es_data *data)
721 : {
722 58130 : return gnutls_encrypt_aead(err, ctx, ldb, val, data);
723 : }
724 :
725 : /*
726 : * @brief Encrypt all the values on an ldb_message_element
727 : *
728 : * Returns a copy of the original attribute with all values encrypted
729 : * by encrypt_value(), the original attribute is left intact.
730 : *
731 : * @param err Pointer to an error code, set to:
732 : * LDB_SUCESS If the value was successfully encrypted
733 : * LDB_ERR_OPERATIONS_ERROR If there was an error.
734 : *
735 : * @param ctx Talloc memory context the will own the memory allocated
736 : * for the new ldb_message_element.
737 : * @param ldb ldb context, to allow logging.
738 : * @param el The ldb_message_elemen to encrypt, not altered or freed
739 : * @param data The context data for this module.
740 : *
741 : * @return Pointer encrypted lsb_message_element, will be NULL if there was
742 : * an error.
743 : */
744 152802 : static struct ldb_message_element *encrypt_element(
745 : int *err,
746 : TALLOC_CTX *ctx,
747 : struct ldb_context *ldb,
748 : const struct ldb_message_element *el,
749 : const struct es_data *data)
750 : {
751 1193 : struct ldb_message_element* enc;
752 1193 : unsigned int i;
753 :
754 152802 : enc = talloc_zero(ctx, struct ldb_message_element);
755 152802 : if (enc == NULL) {
756 0 : ldb_set_errstring(ldb,
757 : "Out of memory, allocating ldb_message_"
758 : "element\n");
759 0 : *err = LDB_ERR_OPERATIONS_ERROR;
760 0 : return NULL;
761 : }
762 :
763 152802 : enc->flags = el->flags;
764 152802 : enc->num_values = el->num_values;
765 152802 : enc->values = talloc_array(enc, struct ldb_val, enc->num_values);
766 152802 : if (enc->values == NULL) {
767 0 : TALLOC_FREE(enc);
768 0 : ldb_set_errstring(ldb,
769 : "Out of memory, allocating values array\n");
770 0 : *err = LDB_ERR_OPERATIONS_ERROR;
771 0 : return NULL;
772 : }
773 :
774 152802 : enc->name = talloc_strdup(enc, el->name);
775 152802 : if (enc->name == NULL) {
776 0 : TALLOC_FREE(enc);
777 0 : ldb_set_errstring(ldb,
778 : "Out of memory, copying element name\n");
779 0 : *err = LDB_ERR_OPERATIONS_ERROR;
780 0 : return NULL;
781 : }
782 :
783 210932 : for (i = 0; i < el->num_values; i++) {
784 58130 : enc->values[i] =
785 58130 : encrypt_value(
786 : err,
787 58130 : enc->values,
788 : ldb,
789 58130 : el->values[i],
790 : data);
791 58130 : if (*err != LDB_SUCCESS) {
792 0 : TALLOC_FREE(enc);
793 0 : return NULL;
794 : }
795 : }
796 151609 : return enc;
797 : }
798 :
799 : /*
800 : * @brief Encrypt all the secret attributes on an ldb_message
801 : *
802 : * Encrypt all the secret attributes on an ldb_message. Any secret
803 : * attributes are removed from message and encrypted copies of the
804 : * attributes added. In the event of an error the contents of the
805 : * message will be inconsistent.
806 : *
807 : * @param err Pointer to an error code, set to:
808 : * LDB_SUCESS If the value was successfully encrypted
809 : * LDB_ERR_OPERATIONS_ERROR If there was an error.
810 : * @param ldb ldb context, to allow logging.
811 : * @param msg The ldb_message to have it's secret attributes encrypted.
812 : *
813 : * @param data The context data for this module.
814 : */
815 2015344 : static const struct ldb_message *encrypt_secret_attributes(
816 : int *err,
817 : TALLOC_CTX *ctx,
818 : struct ldb_context *ldb,
819 : const struct ldb_message *msg,
820 : const struct es_data *data)
821 : {
822 2015344 : struct ldb_message *encrypted_msg = NULL;
823 :
824 97165 : unsigned int i;
825 :
826 2015344 : if (ldb_dn_is_special(msg->dn)) {
827 204548 : return NULL;
828 : }
829 :
830 23530443 : for (i = 0; i < msg->num_elements; i++) {
831 :
832 21720897 : const struct ldb_message_element *el = &msg->elements[i];
833 21720897 : if (should_encrypt(el)) {
834 152802 : struct ldb_message_element* enc = NULL;
835 152802 : if (encrypted_msg == NULL) {
836 40044 : encrypted_msg = ldb_msg_copy_shallow(ctx, msg);
837 40044 : if (encrypted_msg == NULL) {
838 0 : ldb_set_errstring(
839 : ldb,
840 : "Out of memory, allocating "
841 : "ldb_message_element\n");
842 0 : *err = LDB_ERR_OPERATIONS_ERROR;
843 0 : return NULL;
844 : }
845 40044 : encrypted_msg->dn = msg->dn;
846 : }
847 153995 : enc = encrypt_element(err,
848 152802 : msg->elements,
849 : ldb,
850 : el,
851 : data);
852 152802 : if (*err != LDB_SUCCESS) {
853 0 : return NULL;
854 : }
855 152802 : encrypted_msg->elements[i] = *enc;
856 : }
857 : }
858 1713631 : return encrypted_msg;
859 : }
860 :
861 : /*
862 : * @brief Check the encrypted secret header to ensure it's valid
863 : *
864 : * Check an Encrypted secret and ensure it's header is valid.
865 : * A header is assumed to be valid if it:
866 : * - it starts with the MAGIC_VALUE
867 : * - The version number is valid
868 : * - The algorithm is valid
869 : *
870 : * @param val The EncryptedSecret to check.
871 : *
872 : * @return true if the header is valid, false otherwise.
873 : *
874 : */
875 1008380 : static bool check_header(struct EncryptedSecret *es)
876 : {
877 32829 : struct EncryptedSecretHeader *eh;
878 :
879 1008380 : eh = &es->header;
880 1008322 : if (eh->magic != ENCRYPTED_SECRET_MAGIC_VALUE) {
881 : /*
882 : * Does not start with the magic value so not
883 : * an encrypted_value
884 : */
885 0 : return false;
886 : }
887 :
888 1008378 : if (eh->version > SECRET_ATTRIBUTE_VERSION) {
889 : /*
890 : * Invalid version, so not an encrypted value
891 : */
892 0 : return false;
893 : }
894 :
895 1008376 : if (eh->algorithm != ENC_SECRET_AES_128_AEAD) {
896 : /*
897 : * Invalid algorithm, so not an encrypted value
898 : */
899 2 : return false;
900 : }
901 : /*
902 : * Length looks ok, starts with magic value, and the version and
903 : * algorithm are valid
904 : */
905 975551 : return true;
906 : }
907 : /*
908 : * @brief Decrypt an attribute value.
909 : *
910 : * Returns a decrypted copy of the value, the original value is left intact.
911 : *
912 : * @param err Pointer to an error code, set to:
913 : * LDB_SUCESS If the value was successfully decrypted
914 : * LDB_ERR_OPERATIONS_ERROR If there was an error.
915 : *
916 : * @param ctx Talloc memory context the will own the memory allocated
917 : * @param ldb ldb context, to allow logging.
918 : * @param val The ldb value to decrypt, not altered or freed
919 : * @param data The context data for this module.
920 : *
921 : * @return The decrypted ldb_val, or data_blob_null if there was an error.
922 : */
923 1008366 : static struct ldb_val decrypt_value(int *err,
924 : TALLOC_CTX *ctx,
925 : struct ldb_context *ldb,
926 : const struct ldb_val val,
927 : const struct es_data *data)
928 : {
929 :
930 32815 : struct ldb_val dec;
931 :
932 32815 : struct EncryptedSecret es;
933 1008366 : struct PlaintextSecret ps = { data_blob_null};
934 32815 : int rc;
935 1008366 : TALLOC_CTX *frame = talloc_stackframe();
936 :
937 1008366 : rc = ndr_pull_struct_blob(&val,
938 : frame,
939 : &es,
940 : (ndr_pull_flags_fn_t)
941 : ndr_pull_EncryptedSecret);
942 1008366 : if(!NDR_ERR_CODE_IS_SUCCESS(rc)) {
943 2 : ldb_asprintf_errstring(ldb,
944 : "Error(%d) unpacking encrypted secret, "
945 : "data possibly corrupted or altered\n",
946 : rc);
947 2 : *err = LDB_ERR_OPERATIONS_ERROR;
948 2 : TALLOC_FREE(frame);
949 2 : return data_blob_null;
950 : }
951 1008364 : if (!check_header(&es)) {
952 : /*
953 : * Header is invalid so can't be an encrypted value
954 : */
955 0 : ldb_set_errstring(ldb, "Invalid EncryptedSecrets header\n");
956 0 : *err = LDB_ERR_OPERATIONS_ERROR;
957 0 : return data_blob_null;
958 : }
959 1008364 : gnutls_decrypt_aead(err, frame, ldb, &es, &ps, data);
960 :
961 1008364 : if (*err != LDB_SUCCESS) {
962 0 : TALLOC_FREE(frame);
963 0 : return data_blob_null;
964 : }
965 :
966 1008364 : dec = data_blob_talloc(ctx,
967 : ps.cleartext.data,
968 : ps.cleartext.length);
969 1008364 : if (dec.data == NULL) {
970 0 : TALLOC_FREE(frame);
971 0 : ldb_set_errstring(ldb, "Out of memory, copying value\n");
972 0 : *err = LDB_ERR_OPERATIONS_ERROR;
973 0 : return data_blob_null;
974 : }
975 :
976 1008364 : TALLOC_FREE(frame);
977 1008364 : return dec;
978 : }
979 :
980 : /*
981 : * @brief Decrypt all the encrypted values on an ldb_message_element
982 : *
983 : * Returns a copy of the original attribute with all values decrypted by
984 : * decrypt_value(), the original attribute is left intact.
985 : *
986 : * @param err Pointer to an error code, set to:
987 : * LDB_SUCESS If the value was successfully encrypted
988 : * LDB_ERR_OPERATIONS_ERROR If there was an error.
989 : *
990 : * @param ctx Talloc memory context the will own the memory allocated
991 : * for the new ldb_message_element.
992 : * @param ldb ldb context, to allow logging.
993 : * @param el The ldb_message_elemen to decrypt, not altered or freed
994 : * @param data The context data for this module.
995 : *
996 : * @return Pointer decrypted lsb_message_element, will be NULL if there was
997 : * an error.
998 : */
999 1008336 : static struct ldb_message_element *decrypt_element(
1000 : int *err,
1001 : TALLOC_CTX *ctx,
1002 : struct ldb_context *ldb,
1003 : struct ldb_message_element* el,
1004 : struct es_data *data)
1005 : {
1006 32785 : unsigned int i;
1007 32785 : struct ldb_message_element* dec =
1008 1008336 : talloc_zero(ctx, struct ldb_message_element);
1009 :
1010 1008336 : *err = LDB_SUCCESS;
1011 1008336 : if (dec == NULL) {
1012 0 : ldb_set_errstring(ldb,
1013 : "Out of memory, allocating "
1014 : "ldb_message_element\n");
1015 0 : *err = LDB_ERR_OPERATIONS_ERROR;
1016 0 : return NULL;
1017 : }
1018 1008336 : dec->num_values = el->num_values;
1019 :
1020 1008336 : dec->values = talloc_array(dec, struct ldb_val, dec->num_values);
1021 1008336 : if (dec->values == NULL) {
1022 0 : TALLOC_FREE(dec);
1023 0 : ldb_set_errstring(ldb,
1024 : "Out of memory, allocating values array\n");
1025 0 : *err = LDB_ERR_OPERATIONS_ERROR;
1026 0 : return NULL;
1027 : }
1028 :
1029 1008336 : dec->name = talloc_strdup(dec, el->name);
1030 1008336 : if (dec->name == NULL) {
1031 0 : TALLOC_FREE(dec);
1032 0 : ldb_set_errstring(ldb, "Out of memory, copying element name\n");
1033 0 : *err = LDB_ERR_OPERATIONS_ERROR;
1034 0 : return NULL;
1035 : }
1036 :
1037 2016670 : for (i = 0; i < el->num_values; i++) {
1038 1008336 : dec->values[i] =
1039 1008336 : decrypt_value(err,
1040 975551 : el->values,
1041 : ldb,
1042 1008336 : el->values[i],
1043 : data);
1044 1008336 : if (*err != LDB_SUCCESS) {
1045 2 : TALLOC_FREE(dec);
1046 2 : return NULL;
1047 : }
1048 : }
1049 975551 : return dec;
1050 : }
1051 :
1052 :
1053 : /*
1054 : * @brief Decrypt all the secret attributes on an ldb_message
1055 : *
1056 : * Decrypt all the secret attributes on an ldb_message. Any secret attributes
1057 : * are removed from message and decrypted copies of the attributes added.
1058 : * In the event of an error the contents of the message will be inconsistent.
1059 : *
1060 : * @param ldb ldb context, to allow logging.
1061 : * @param msg The ldb_message to have it's secret attributes encrypted.
1062 : * @param data The context data for this module.
1063 : *
1064 : * @returns ldb status code
1065 : * LDB_SUCESS If the value was successfully encrypted
1066 : * LDB_ERR_OPERATIONS_ERROR If there was an error.
1067 : */
1068 76720112 : static int decrypt_secret_attributes(struct ldb_context *ldb,
1069 : struct ldb_message *msg,
1070 : struct es_data *data)
1071 : {
1072 1718050 : size_t i;
1073 1718050 : int ret;
1074 :
1075 76720112 : if (ldb_dn_is_special(msg->dn)) {
1076 0 : return LDB_SUCCESS;
1077 : }
1078 :
1079 1150801676 : for (i = 0; i < num_secret_attributes; i++) {
1080 24052698 : struct ldb_message_element *el =
1081 1074081566 : ldb_msg_find_element(msg, secret_attributes[i]);
1082 1074081566 : if (el != NULL) {
1083 1008336 : const int flags = el->flags;
1084 32785 : struct ldb_message_element* dec =
1085 1041121 : decrypt_element(&ret,
1086 1008336 : msg->elements,
1087 : ldb,
1088 : el,
1089 : data);
1090 1008336 : if (ret != LDB_SUCCESS) {
1091 2 : return ret;
1092 : }
1093 1008334 : ldb_msg_remove_element(msg, el);
1094 1008334 : ret = ldb_msg_add(msg, dec, flags);
1095 1008334 : if (ret != LDB_SUCCESS) {
1096 0 : return ret;
1097 : }
1098 : }
1099 : }
1100 75002062 : return LDB_SUCCESS;
1101 : }
1102 :
1103 86971537 : static int es_search_post_process(struct ldb_module *module,
1104 : struct ldb_message *msg)
1105 : {
1106 86971537 : struct ldb_context *ldb = ldb_module_get_ctx(module);
1107 2580620 : struct es_data *data =
1108 86971537 : talloc_get_type(ldb_module_get_private(module),
1109 : struct es_data);
1110 :
1111 :
1112 : /*
1113 : * Decrypt any encrypted secret attributes
1114 : */
1115 86971537 : if (data && data->encrypt_secrets) {
1116 76720108 : int err = decrypt_secret_attributes(ldb, msg, data);
1117 76720108 : if (err != LDB_SUCCESS) {
1118 0 : return err;
1119 : }
1120 : }
1121 84390917 : return LDB_SUCCESS;
1122 : }
1123 :
1124 : /*
1125 : hook search operations
1126 : */
1127 : struct es_context {
1128 : struct ldb_module *module;
1129 : struct ldb_request *req;
1130 : };
1131 :
1132 131676561 : static int es_callback(struct ldb_request *req, struct ldb_reply *ares)
1133 : {
1134 4921743 : struct es_context *ec;
1135 4921743 : int ret;
1136 :
1137 :
1138 131676561 : ec = talloc_get_type(req->context, struct es_context);
1139 :
1140 131676561 : if (!ares) {
1141 0 : return ldb_module_done(ec->req, NULL, NULL,
1142 : LDB_ERR_OPERATIONS_ERROR);
1143 : }
1144 131676561 : if (ares->error != LDB_SUCCESS) {
1145 2173495 : return ldb_module_done(ec->req, ares->controls,
1146 : ares->response, ares->error);
1147 : }
1148 :
1149 129503066 : switch (ares->type) {
1150 86971537 : case LDB_REPLY_ENTRY:
1151 : /*
1152 : * for each record returned decrypt any encrypted attributes
1153 : */
1154 86971537 : ret = es_search_post_process(ec->module, ares->message);
1155 86971537 : if (ret != 0) {
1156 0 : return ldb_module_done(ec->req, NULL, NULL,
1157 : LDB_ERR_OPERATIONS_ERROR);
1158 : }
1159 86971537 : return ldb_module_send_entry(ec->req,
1160 : ares->message, ares->controls);
1161 :
1162 4190615 : case LDB_REPLY_REFERRAL:
1163 4190615 : return ldb_module_send_referral(ec->req, ares->referral);
1164 :
1165 38340914 : case LDB_REPLY_DONE:
1166 :
1167 38340914 : return ldb_module_done(ec->req, ares->controls,
1168 : ares->response, LDB_SUCCESS);
1169 : }
1170 :
1171 0 : talloc_free(ares);
1172 0 : return LDB_SUCCESS;
1173 : }
1174 :
1175 42079173 : static int es_search(struct ldb_module *module, struct ldb_request *req)
1176 : {
1177 2286493 : struct ldb_context *ldb;
1178 2286493 : struct es_context *ec;
1179 2286493 : struct ldb_request *down_req;
1180 2286493 : int ret;
1181 :
1182 : /* There are no encrypted attributes on special DNs */
1183 42079173 : if (ldb_dn_is_special(req->op.search.base)) {
1184 1510983 : return ldb_next_request(module, req);
1185 : }
1186 :
1187 40568190 : ldb = ldb_module_get_ctx(module);
1188 :
1189 40568190 : ec = talloc(req, struct es_context);
1190 40568190 : if (ec == NULL) {
1191 0 : return ldb_oom(ldb);
1192 : }
1193 :
1194 40568190 : ec->module = module;
1195 40568190 : ec->req = req;
1196 40568190 : ret = ldb_build_search_req_ex(&down_req,
1197 : ldb,
1198 : ec,
1199 : req->op.search.base,
1200 : req->op.search.scope,
1201 : req->op.search.tree,
1202 : req->op.search.attrs,
1203 : req->controls,
1204 : ec,
1205 : es_callback,
1206 : req);
1207 40568190 : LDB_REQ_SET_LOCATION(down_req);
1208 40568190 : if (ret != LDB_SUCCESS) {
1209 0 : return ldb_operr(ldb);
1210 : }
1211 :
1212 : /* perform the search */
1213 40568190 : return ldb_next_request(module, down_req);
1214 : }
1215 924119 : static int es_add(struct ldb_module *module, struct ldb_request *req)
1216 : {
1217 :
1218 83787 : struct es_data *data =
1219 924119 : talloc_get_type(ldb_module_get_private(module),
1220 : struct es_data);
1221 924119 : const struct ldb_message *encrypted_msg = NULL;
1222 924119 : struct ldb_context *ldb = NULL;
1223 924119 : int rc = LDB_SUCCESS;
1224 :
1225 924119 : if (!data->encrypt_secrets) {
1226 15688 : return ldb_next_request(module, req);
1227 : }
1228 :
1229 908431 : ldb = ldb_module_get_ctx(module);
1230 908431 : encrypted_msg = encrypt_secret_attributes(&rc,
1231 : req,
1232 : ldb,
1233 : req->op.add.message,
1234 : data);
1235 908431 : if (rc != LDB_SUCCESS) {
1236 0 : return rc;
1237 : }
1238 : /*
1239 : * If we did not encrypt any of the attributes
1240 : * continue on to the next module
1241 : */
1242 908431 : if (encrypted_msg == NULL) {
1243 903294 : return ldb_next_request(module, req);
1244 : }
1245 :
1246 : /*
1247 : * Encrypted an attribute, now need to build a copy of the request
1248 : * so that we're not altering the original callers copy
1249 : */
1250 : {
1251 5137 : struct ldb_request* new_req = NULL;
1252 5137 : rc = ldb_build_add_req(&new_req,
1253 : ldb,
1254 : req,
1255 : encrypted_msg,
1256 : req->controls,
1257 : req,
1258 : dsdb_next_callback,
1259 : req);
1260 5137 : if (rc != LDB_SUCCESS) {
1261 0 : return rc;
1262 : }
1263 5137 : return ldb_next_request(module, new_req);
1264 : }
1265 : }
1266 :
1267 1268858 : static int es_modify(struct ldb_module *module, struct ldb_request *req)
1268 : {
1269 30521 : struct es_data *data =
1270 1268858 : talloc_get_type(ldb_module_get_private(module),
1271 : struct es_data);
1272 1268858 : const struct ldb_message *encrypted_msg = NULL;
1273 1268858 : struct ldb_context *ldb = NULL;
1274 1268858 : int rc = LDB_SUCCESS;
1275 :
1276 1268858 : if (!data->encrypt_secrets) {
1277 161947 : return ldb_next_request(module, req);
1278 : }
1279 :
1280 1106911 : ldb = ldb_module_get_ctx(module);
1281 1106911 : encrypted_msg = encrypt_secret_attributes(&rc,
1282 : req,
1283 : ldb,
1284 : req->op.mod.message,
1285 : data);
1286 1106911 : if (rc != LDB_SUCCESS) {
1287 0 : return rc;
1288 : }
1289 : /*
1290 : * If we did not encrypt any of the attributes
1291 : * continue on to the next module
1292 : */
1293 1106911 : if (encrypted_msg == NULL) {
1294 1072006 : return ldb_next_request(module, req);
1295 : }
1296 :
1297 :
1298 : /*
1299 : * Encrypted an attribute, now need to build a copy of the request
1300 : * so that we're not altering the original callers copy
1301 : */
1302 : {
1303 34905 : struct ldb_request* new_req = NULL;
1304 34905 : rc = ldb_build_mod_req(&new_req,
1305 : ldb,
1306 : req,
1307 : encrypted_msg,
1308 : req->controls,
1309 : req,
1310 : dsdb_next_callback,
1311 : req);
1312 34905 : if (rc != LDB_SUCCESS) {
1313 0 : return rc;
1314 : }
1315 34905 : return ldb_next_request(module, new_req);
1316 : }
1317 : }
1318 :
1319 17 : static int es_delete(struct ldb_module *module, struct ldb_request *req)
1320 : {
1321 17 : return ldb_next_request(module, req);
1322 : }
1323 :
1324 80248 : static int es_rename(struct ldb_module *module, struct ldb_request *req)
1325 : {
1326 80248 : return ldb_next_request(module, req);
1327 : }
1328 182028 : static int es_init(struct ldb_module *ctx)
1329 : {
1330 6040 : struct es_data *data;
1331 6040 : int ret;
1332 :
1333 182028 : data = talloc_zero(ctx, struct es_data);
1334 182028 : if (!data) {
1335 0 : return ldb_module_oom(ctx);
1336 : }
1337 :
1338 : {
1339 182028 : struct ldb_context *ldb = ldb_module_get_ctx(ctx);
1340 6040 : struct ldb_dn *samba_dsdb_dn;
1341 6040 : struct ldb_result *res;
1342 6040 : static const char *samba_dsdb_attrs[] = {
1343 : SAMBA_REQUIRED_FEATURES_ATTR,
1344 : NULL
1345 : };
1346 182028 : TALLOC_CTX *frame = talloc_stackframe();
1347 :
1348 182028 : samba_dsdb_dn = ldb_dn_new(frame, ldb, "@SAMBA_DSDB");
1349 182028 : if (!samba_dsdb_dn) {
1350 0 : TALLOC_FREE(frame);
1351 2 : return ldb_oom(ldb);
1352 : }
1353 182028 : ret = dsdb_module_search_dn(ctx,
1354 : frame,
1355 : &res,
1356 : samba_dsdb_dn,
1357 : samba_dsdb_attrs,
1358 : DSDB_FLAG_NEXT_MODULE,
1359 : NULL);
1360 182028 : if (ret != LDB_SUCCESS) {
1361 0 : TALLOC_FREE(frame);
1362 0 : return ret;
1363 : }
1364 188068 : data->encrypt_secrets =
1365 364056 : ldb_msg_check_string_attribute(
1366 182028 : res->msgs[0],
1367 : SAMBA_REQUIRED_FEATURES_ATTR,
1368 : SAMBA_ENCRYPTED_SECRETS_FEATURE);
1369 182028 : if (data->encrypt_secrets) {
1370 167173 : ret = load_keys(ctx, data);
1371 167173 : if (ret != LDB_SUCCESS) {
1372 2 : TALLOC_FREE(frame);
1373 2 : return ret;
1374 : }
1375 : }
1376 182026 : TALLOC_FREE(frame);
1377 : }
1378 182026 : ldb_module_set_private(ctx, data);
1379 :
1380 182026 : ret = ldb_next_init(ctx);
1381 182026 : if (ret != LDB_SUCCESS) {
1382 0 : return ret;
1383 : }
1384 175988 : return LDB_SUCCESS;
1385 : }
1386 :
1387 : static const struct ldb_module_ops ldb_encrypted_secrets_module_ops = {
1388 : .name = "encrypted_secrets",
1389 : .search = es_search,
1390 : .add = es_add,
1391 : .modify = es_modify,
1392 : .del = es_delete,
1393 : .rename = es_rename,
1394 : .init_context = es_init
1395 : };
1396 :
1397 6040 : int ldb_encrypted_secrets_module_init(const char *version)
1398 : {
1399 6040 : LDB_MODULE_CHECK_VERSION(version);
1400 6040 : return ldb_register_module(&ldb_encrypted_secrets_module_ops);
1401 : }
|