8c59418c3c1122b1bb888f39afc2482621739bc8
[samba.git] / source4 / dsdb / samdb / ldb_modules / encrypted_secrets.c
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 static const DATA_BLOB get_key(const struct es_data *data) {
79
80         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 static const char* get_key_directory(TALLOC_CTX *ctx, struct ldb_context *ldb)
94 {
95
96         const char *sam_ldb_path = NULL;
97         const char *private_dir  = NULL;
98         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         sam_ldb_path = ldb_get_opaque(ldb, "ldb_url");
106         if (sam_ldb_path == NULL) {
107                 ldb_set_errstring(ldb, "Unable to get ldb_url\n");
108                 return NULL;
109         }
110
111         if (strncmp("tdb://", sam_ldb_path, 6) == 0) {
112                 sam_ldb_path += 6;
113         }
114         else if (strncmp("ldb://", sam_ldb_path, 6) == 0) {
115                 sam_ldb_path += 6;
116         }
117         else if (strncmp("mdb://", sam_ldb_path, 6) == 0) {
118                 sam_ldb_path += 6;
119         }
120         private_dir = talloc_strdup(ctx, sam_ldb_path);
121         if (private_dir == NULL) {
122                 ldb_set_errstring(ldb,
123                                   "Out of memory building encrypted "
124                                   "secrets key\n");
125                 return NULL;
126         }
127
128         p = strrchr(private_dir, '/');
129         if (p != NULL) {
130                 *p = '\0';
131         } else {
132                 private_dir = talloc_strdup(ctx, ".");
133         }
134
135         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 static void log_error(struct ldb_context *ldb, int err, const char *desc)
147 {
148         char buf[1024];
149         int e = strerror_r(err, buf, sizeof(buf));
150         if (e != 0) {
151                 strlcpy(buf, "Unknown error", sizeof(buf)-1);
152         }
153         ldb_asprintf_errstring(ldb, "Error (%d) %s - %s\n", err, buf, desc);
154 }
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 static int load_keys(struct ldb_module *module, struct es_data *data)
169 {
170
171         const char *key_dir  = NULL;
172         const char *key_path = NULL;
173
174         struct ldb_context *ldb = NULL;
175         FILE *fp = NULL;
176         const int key_size = 16;
177         int read;
178         DATA_BLOB key = data_blob_null;
179
180         TALLOC_CTX *frame = talloc_stackframe();
181
182         ldb = ldb_module_get_ctx(module);
183         key_dir = get_key_directory(frame, ldb);
184         if (key_dir == NULL) {
185                 TALLOC_FREE(frame);
186                 return LDB_ERR_OPERATIONS_ERROR;
187         }
188
189         key_path = talloc_asprintf(frame, "%s/%s", key_dir, SECRETS_KEY_FILE);
190         if (key_path == NULL) {
191                 TALLOC_FREE(frame);
192                 return ldb_oom(ldb);
193         }
194
195
196         key = data_blob_talloc_zero(module, key_size);
197         key.length = key_size;
198
199         fp = fopen(key_path, "rb");
200         if (fp == NULL) {
201                 TALLOC_FREE(frame);
202                 data_blob_free(&key);
203                 if (errno == ENOENT) {
204                         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                         data->encrypt_secrets = false;
210                         return LDB_SUCCESS;
211                 } else {
212                         log_error(ldb,
213                                   errno,
214                                   "Opening encrypted_secrets key file\n");
215                         return LDB_ERR_OPERATIONS_ERROR;
216                 }
217         }
218
219         read = fread(key.data, 1, key.length, fp);
220         fclose(fp);
221         if (read == 0) {
222                 TALLOC_FREE(frame);
223                 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                 data->encrypt_secrets = false;
229                 return LDB_SUCCESS;
230         }
231         if (read != key.length) {
232                 TALLOC_FREE(frame);
233                 if (errno) {
234                         log_error(ldb,
235                                   errno,
236                                   "Reading encrypted_secrets key file\n");
237                 } else {
238                         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                 return LDB_ERR_OPERATIONS_ERROR;
246         }
247
248         data->keys[0] = key;
249         data->encrypt_secrets = true;
250         data->encryption_algorithm = GNUTLS_CIPHER_AES_128_GCM;
251         TALLOC_FREE(frame);
252
253         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 static bool should_encrypt(const struct ldb_message_element *el)
266 {
267         size_t i;
268
269         for (i = 0; i < ARRAY_SIZE(secret_attributes); i++) {
270                 if (strcasecmp(secret_attributes[i], el->name) == 0) {
271                         return true;
272                 }
273         }
274         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 static size_t round_to_block_size(size_t block_size, size_t size)
286 {
287         if ((size % block_size) == 0) {
288                 return size;
289         } else {
290                 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 static struct EncryptedSecret *makeEncryptedSecret(struct ldb_context *ldb,
305                                                    TALLOC_CTX *ctx)
306 {
307         struct EncryptedSecret *es = NULL;
308
309         es = talloc_zero_size(ctx, sizeof(struct EncryptedSecret));
310         if (es == NULL) {
311                 ldb_set_errstring(ldb,
312                                   "Out of memory, allocating "
313                                    "struct EncryptedSecret\n");
314                 return NULL;
315         }
316         es->header.magic     = ENCRYPTED_SECRET_MAGIC_VALUE;
317         es->header.version   = SECRET_ATTRIBUTE_VERSION;
318         es->header.algorithm = SECRET_ENCRYPTION_ALGORITHM;
319         es->header.flags     = 0;
320         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 static DATA_BLOB makePlainText(TALLOC_CTX *ctx,
336                                struct ldb_context *ldb,
337                                const struct ldb_val val)
338 {
339         struct PlaintextSecret ps = { .cleartext = data_blob_null};
340         DATA_BLOB pt = data_blob_null;
341         int rc;
342
343         ps.cleartext.length = val.length;
344         ps.cleartext.data   = val.data;
345
346         rc = ndr_push_struct_blob(&pt,
347                                   ctx,
348                                   &ps,
349                                   (ndr_push_flags_fn_t)
350                                         ndr_push_PlaintextSecret);
351         if (!NDR_ERR_CODE_IS_SUCCESS(rc)) {
352                 ldb_set_errstring(ldb,
353                                   "Unable to ndr push PlaintextSecret\n");
354                 return data_blob_null;
355         }
356         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 static const gnutls_datum_t convert_from_data_blob(DATA_BLOB blob) {
369
370         const gnutls_datum_t datum = {
371                 .size = blob.length,
372                 .data = blob.data,
373         };
374         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 algoritm number, or 0 if there is no match.
384  *
385  */
386 static int gnutls_get_algorithm(struct ldb_context *ldb,
387                                 struct EncryptedSecret *es) {
388
389         switch (es->header.algorithm) {
390         case ENC_SECRET_AES_128_AEAD:
391                 return GNUTLS_CIPHER_AES_128_GCM;
392         default:
393                 ldb_asprintf_errstring(ldb,
394                                        "Unsupported encryption algorithm %d\n",
395                                        es->header.algorithm);
396                 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 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         struct EncryptedSecret *es = NULL;
420         struct ldb_val enc = data_blob_null;
421         DATA_BLOB pt = data_blob_null;
422         gnutls_aead_cipher_hd_t cipher_hnd;
423         int rc;
424
425         TALLOC_CTX *frame = talloc_stackframe();
426
427         es = makeEncryptedSecret(ldb, frame);
428         if (es == NULL) {
429                 goto error_exit;
430         }
431
432         pt = makePlainText(frame, ldb, val);
433         if (pt.length == 0) {
434                 goto error_exit;
435         }
436
437         /*
438          * Set the encryption key and initialize the encryption handle.
439          */
440         {
441                 const size_t key_size = gnutls_cipher_get_key_size(
442                         data->encryption_algorithm);
443                 gnutls_datum_t cipher_key;
444                 DATA_BLOB key_blob = get_key(data);
445
446                 if (key_blob.length != key_size) {
447                         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                         goto error_exit;
454                 }
455                 cipher_key = convert_from_data_blob(key_blob);
456
457                 rc = gnutls_aead_cipher_init(&cipher_hnd,
458                                              data->encryption_algorithm,
459                                              &cipher_key);
460                 if (rc !=0) {
461                         ldb_asprintf_errstring(ldb,
462                                                "gnutls_aead_cipher_init failed "
463                                                "%s - %s\n",
464                                                gnutls_strerror_name(rc),
465                                                gnutls_strerror(rc));
466                         goto error_exit;
467                 }
468
469         }
470
471         /*
472          * Set the initialisation vector
473          */
474         {
475                 unsigned iv_size = gnutls_cipher_get_iv_size(
476                         data->encryption_algorithm);
477                 uint8_t *iv;
478
479                 iv = talloc_zero_size(frame, iv_size);
480                 if (iv == NULL) {
481                         ldb_set_errstring(ldb,
482                                           "Out of memory allocating IV\n");
483                         goto error_exit_handle;
484                 }
485
486                 rc = gnutls_rnd(GNUTLS_RND_NONCE, iv, iv_size);
487                 if (rc !=0) {
488                         ldb_asprintf_errstring(ldb,
489                                                "gnutls_rnd failed %s - %s\n",
490                                                gnutls_strerror_name(rc),
491                                                gnutls_strerror(rc));
492                         goto error_exit_handle;
493                 }
494                 es->iv.length = iv_size;
495                 es->iv.data   = iv;
496         }
497
498         /*
499          * Encrypt the value.
500          */
501         {
502                 const unsigned block_size = gnutls_cipher_get_block_size(
503                         data->encryption_algorithm);
504                 const unsigned tag_size = gnutls_cipher_get_tag_size(
505                         data->encryption_algorithm);
506                 const size_t ed_size = round_to_block_size(
507                         block_size,
508                         sizeof(struct PlaintextSecret) + val.length);
509                 const size_t en_size = ed_size + tag_size;
510                 uint8_t *ct = talloc_zero_size(frame, en_size);
511                 size_t el = en_size;
512
513                 if (ct == NULL) {
514                         ldb_set_errstring(ldb,
515                                           "Out of memory allocation cipher "
516                                           "text\n");
517                         goto error_exit_handle;
518                 }
519
520                 rc = gnutls_aead_cipher_encrypt(
521                         cipher_hnd,
522                         es->iv.data,
523                         es->iv.length,
524                         &es->header,
525                         sizeof(struct EncryptedSecretHeader),
526                         tag_size,
527                         pt.data,
528                         pt.length,
529                         ct,
530                         &el);
531                 if (rc !=0) {
532                         ldb_asprintf_errstring(ldb,
533                                                "gnutls_aead_cipher_encrypt '"
534                                                "failed %s - %s\n",
535                                                gnutls_strerror_name(rc),
536                                                gnutls_strerror(rc));
537                         *err = LDB_ERR_OPERATIONS_ERROR;
538                         return data_blob_null;
539                 }
540                 es->encrypted.length = el;
541                 es->encrypted.data   = ct;
542                 gnutls_aead_cipher_deinit(cipher_hnd);
543         }
544
545         rc = ndr_push_struct_blob(&enc,
546                                   ctx,
547                                   es,
548                                   (ndr_push_flags_fn_t)
549                                         ndr_push_EncryptedSecret);
550         if (!NDR_ERR_CODE_IS_SUCCESS(rc)) {
551                 ldb_set_errstring(ldb,
552                                   "Unable to ndr push EncryptedSecret\n");
553                 goto error_exit;
554         }
555         TALLOC_FREE(frame);
556         return enc;
557
558 error_exit_handle:
559         gnutls_aead_cipher_deinit(cipher_hnd);
560 error_exit:
561         *err = LDB_ERR_OPERATIONS_ERROR;
562         TALLOC_FREE(frame);
563         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 compatable 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 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         gnutls_aead_cipher_hd_t cipher_hnd;
593         DATA_BLOB pt = data_blob_null;
594         const unsigned tag_size =
595                 gnutls_cipher_get_tag_size(es->header.algorithm);
596         int rc;
597
598         /*
599          * Get the encryption key and initialise the encryption handle
600          */
601         {
602                 gnutls_datum_t cipher_key;
603                 DATA_BLOB key_blob;
604                 const int algorithm = gnutls_get_algorithm(ldb, es);
605                 const size_t key_size = gnutls_cipher_get_key_size(algorithm);
606                 key_blob   = get_key(data);
607
608                 if (algorithm == 0) {
609                         goto error_exit;
610                 }
611
612                 if (key_blob.length != key_size) {
613                         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                         goto error_exit;
620                 }
621                 cipher_key = convert_from_data_blob(key_blob);
622
623                 rc = gnutls_aead_cipher_init(
624                         &cipher_hnd,
625                         algorithm,
626                         &cipher_key);
627                 if (rc != 0) {
628                         ldb_asprintf_errstring(ldb,
629                                                "gnutls_aead_cipher_init failed "
630                                                "%s - %s\n",
631                                                gnutls_strerror_name(rc),
632                                                gnutls_strerror(rc));
633                         goto error_exit;
634                 }
635         }
636
637         /*
638          * Decrypt and validate the encrypted value
639          */
640
641         pt.length = es->encrypted.length;
642         pt.data = talloc_zero_size(ctx, es->encrypted.length);
643
644         if (pt.data == NULL) {
645                 ldb_set_errstring(ldb,
646                                   "Out of memory allocating plain text\n");
647                 goto error_exit_handle;
648         }
649
650         rc = gnutls_aead_cipher_decrypt(cipher_hnd,
651                                         es->iv.data,
652                                         es->iv.length,
653                                         &es->header,
654                                         sizeof(struct EncryptedSecretHeader),
655                                         tag_size,
656                                         es->encrypted.data,
657                                         es->encrypted.length,
658                                         pt.data,
659                                         &pt.length);
660         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                 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                 goto error_exit_handle;
674         }
675         gnutls_aead_cipher_deinit(cipher_hnd);
676
677         rc = ndr_pull_struct_blob(&pt,
678                                   ctx,
679                                   ps,
680                                   (ndr_pull_flags_fn_t)
681                                         ndr_pull_PlaintextSecret);
682         if(!NDR_ERR_CODE_IS_SUCCESS(rc)) {
683                 ldb_asprintf_errstring(ldb,
684                                        "Error(%d) unpacking decrypted data, "
685                                        "data possibly corrupted or altered\n",
686                                        rc);
687                 goto error_exit;
688         }
689         return;
690
691 error_exit_handle:
692         gnutls_aead_cipher_deinit(cipher_hnd);
693 error_exit:
694         *err = LDB_ERR_OPERATIONS_ERROR;
695         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 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         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 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         struct ldb_message_element* enc;
752         unsigned int i;
753
754         enc = talloc_zero(ctx, struct ldb_message_element);
755         if (enc == NULL) {
756                 ldb_set_errstring(ldb,
757                                   "Out of memory, allocating ldb_message_"
758                                   "element\n");
759                 *err = LDB_ERR_OPERATIONS_ERROR;
760                 return NULL;
761         }
762
763         enc->flags      = el->flags;
764         enc->num_values = el->num_values;
765         enc->values     = talloc_array(enc, struct ldb_val, enc->num_values);
766         if (enc->values == NULL) {
767                 TALLOC_FREE(enc);
768                 ldb_set_errstring(ldb,
769                                   "Out of memory, allocating values array\n");
770                 *err = LDB_ERR_OPERATIONS_ERROR;
771                 return NULL;
772         }
773
774         enc->name = talloc_strdup(enc, el->name);
775         if (enc->name == NULL) {
776                 TALLOC_FREE(enc);
777                 ldb_set_errstring(ldb,
778                                   "Out of memory, copying element name\n");
779                 *err = LDB_ERR_OPERATIONS_ERROR;
780                 return NULL;
781         }
782
783         for (i = 0; i < el->num_values; i++) {
784                 enc->values[i] =
785                         encrypt_value(
786                                 err,
787                                 enc->values,
788                                 ldb,
789                                 el->values[i],
790                                 data);
791                 if (*err != LDB_SUCCESS) {
792                         TALLOC_FREE(enc);
793                         return NULL;
794                 }
795         }
796         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 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         struct ldb_message *encrypted_msg = NULL;
823
824         unsigned int i;
825
826         if (ldb_dn_is_special(msg->dn)) {
827                 return NULL;
828         }
829
830         for (i = 0; i < msg->num_elements; i++) {
831
832                 const struct ldb_message_element *el = &msg->elements[i];
833                 if (should_encrypt(el)) {
834                         struct ldb_message_element* enc = NULL;
835                         if (encrypted_msg == NULL) {
836                                 encrypted_msg = ldb_msg_copy_shallow(ctx, msg);
837                                 if (encrypted_msg == NULL) {
838                                         ldb_set_errstring(
839                                                 ldb,
840                                                 "Out of memory, allocating "
841                                                 "ldb_message_element\n");
842                                         *err = LDB_ERR_OPERATIONS_ERROR;
843                                         return NULL;
844                                 }
845                                 encrypted_msg->dn = msg->dn;
846                         }
847                         enc = encrypt_element(err,
848                                               msg->elements,
849                                               ldb,
850                                               el,
851                                               data);
852                         if (*err != LDB_SUCCESS) {
853                                 return NULL;
854                         }
855                         encrypted_msg->elements[i] = *enc;
856                 }
857         }
858         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 static bool check_header(struct EncryptedSecret *es)
876 {
877         struct EncryptedSecretHeader *eh;
878
879         eh = &es->header;
880         if (eh->magic != ENCRYPTED_SECRET_MAGIC_VALUE) {
881                 /*
882                  * Does not start with the magic value so not
883                  * an encrypted_value
884                  */
885                 return false;
886         }
887
888         if (eh->version > SECRET_ATTRIBUTE_VERSION) {
889                 /*
890                  * Invalid version, so not an encrypted value
891                  */
892                 return false;
893         }
894
895         if (eh->algorithm != ENC_SECRET_AES_128_AEAD) {
896                 /*
897                  * Invalid algorithm, so not an encrypted value
898                  */
899                 return false;
900         }
901         /*
902          * Length looks ok, starts with magic value, and the version and
903          * algorithm are valid
904          */
905         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 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         struct ldb_val dec;
931
932         struct EncryptedSecret es;
933         struct PlaintextSecret ps = { data_blob_null};
934         int rc;
935         TALLOC_CTX *frame = talloc_stackframe();
936
937         rc = ndr_pull_struct_blob(&val,
938                                   frame,
939                                   &es,
940                                   (ndr_pull_flags_fn_t)
941                                         ndr_pull_EncryptedSecret);
942         if(!NDR_ERR_CODE_IS_SUCCESS(rc)) {
943                 ldb_asprintf_errstring(ldb,
944                                        "Error(%d)  unpacking encrypted secret, "
945                                        "data possibly corrupted or altered\n",
946                                        rc);
947                 *err = LDB_ERR_OPERATIONS_ERROR;
948                 TALLOC_FREE(frame);
949                 return data_blob_null;
950         }
951         if (!check_header(&es)) {
952                 /*
953                 * Header is invalid so can't be an encrypted value
954                 */
955                 ldb_set_errstring(ldb, "Invalid EncryptedSecrets header\n");
956                 *err = LDB_ERR_OPERATIONS_ERROR;
957                 return data_blob_null;
958         }
959         gnutls_decrypt_aead(err, frame, ldb, &es, &ps, data);
960
961         if (*err != LDB_SUCCESS) {
962                 TALLOC_FREE(frame);
963                 return data_blob_null;
964         }
965
966         dec = data_blob_talloc(ctx,
967                                ps.cleartext.data,
968                                ps.cleartext.length);
969         if (dec.data == NULL) {
970                 TALLOC_FREE(frame);
971                 ldb_set_errstring(ldb, "Out of memory, copying value\n");
972                 *err = LDB_ERR_OPERATIONS_ERROR;
973                 return data_blob_null;
974         }
975
976         TALLOC_FREE(frame);
977         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 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         unsigned int i;
1007         struct ldb_message_element* dec =
1008                 talloc_zero(ctx, struct ldb_message_element);
1009
1010         *err = LDB_SUCCESS;
1011         if (dec == NULL) {
1012                 ldb_set_errstring(ldb,
1013                                   "Out of memory, allocating "
1014                                   "ldb_message_element\n");
1015                 *err = LDB_ERR_OPERATIONS_ERROR;
1016                 return NULL;
1017         }
1018         dec->num_values = el->num_values;
1019
1020         dec->values = talloc_array(dec, struct ldb_val, dec->num_values);
1021         if (dec->values == NULL) {
1022                 TALLOC_FREE(dec);
1023                 ldb_set_errstring(ldb,
1024                                   "Out of memory, allocating values array\n");
1025                 *err = LDB_ERR_OPERATIONS_ERROR;
1026                 return NULL;
1027         }
1028
1029         dec->name = talloc_strdup(dec, el->name);
1030         if (dec->name == NULL) {
1031                 TALLOC_FREE(dec);
1032                 ldb_set_errstring(ldb, "Out of memory, copying element name\n");
1033                 *err = LDB_ERR_OPERATIONS_ERROR;
1034                 return NULL;
1035         }
1036
1037         for (i = 0; i < el->num_values; i++) {
1038                 dec->values[i] =
1039                         decrypt_value(err,
1040                                       el->values,
1041                                       ldb,
1042                                       el->values[i],
1043                                       data);
1044                 if (*err != LDB_SUCCESS) {
1045                         TALLOC_FREE(dec);
1046                         return NULL;
1047                 }
1048         }
1049         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 static int decrypt_secret_attributes(struct ldb_context *ldb,
1069                                       struct ldb_message *msg,
1070                                       struct es_data *data)
1071 {
1072         size_t i;
1073         int ret;
1074
1075         if (ldb_dn_is_special(msg->dn)) {
1076                 return LDB_SUCCESS;
1077         }
1078
1079         for (i = 0; i < num_secret_attributes; i++) {
1080                 struct ldb_message_element *el =
1081                         ldb_msg_find_element(msg, secret_attributes[i]);
1082                 if (el != NULL) {
1083                         const int flags = el->flags;
1084                         struct ldb_message_element* dec =
1085                                 decrypt_element(&ret,
1086                                                 msg->elements,
1087                                                 ldb,
1088                                                 el,
1089                                                 data);
1090                         if (ret != LDB_SUCCESS) {
1091                                 return ret;
1092                         }
1093                         ldb_msg_remove_element(msg, el);
1094                         ret = ldb_msg_add(msg, dec, flags);
1095                         if (ret != LDB_SUCCESS) {
1096                                 return ret;
1097                         }
1098                 }
1099         }
1100         return LDB_SUCCESS;
1101 }
1102
1103 static int es_search_post_process(struct ldb_module *module,
1104                                    struct ldb_message *msg)
1105 {
1106         struct ldb_context *ldb = ldb_module_get_ctx(module);
1107         struct es_data *data =
1108                 talloc_get_type(ldb_module_get_private(module),
1109                                 struct es_data);
1110
1111
1112         /*
1113          * Decrypt any encrypted secret attributes
1114          */
1115         if (data && data->encrypt_secrets) {
1116                 int err = decrypt_secret_attributes(ldb, msg, data);
1117                 if (err !=  LDB_SUCCESS) {
1118                         return err;
1119                 }
1120         }
1121         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 static int es_callback(struct ldb_request *req, struct ldb_reply *ares)
1133 {
1134         struct es_context *ec;
1135         int ret;
1136
1137
1138         ec = talloc_get_type(req->context, struct es_context);
1139
1140         if (!ares) {
1141                 return ldb_module_done(ec->req, NULL, NULL,
1142                                        LDB_ERR_OPERATIONS_ERROR);
1143         }
1144         if (ares->error != LDB_SUCCESS) {
1145                 return ldb_module_done(ec->req, ares->controls,
1146                                        ares->response, ares->error);
1147         }
1148
1149         switch (ares->type) {
1150         case LDB_REPLY_ENTRY:
1151                 /*
1152                  * for each record returned decrypt any encrypted attributes
1153                  */
1154                 ret = es_search_post_process(ec->module, ares->message);
1155                 if (ret != 0) {
1156                         return ldb_module_done(ec->req, NULL, NULL,
1157                                                LDB_ERR_OPERATIONS_ERROR);
1158                 }
1159                 return ldb_module_send_entry(ec->req,
1160                                              ares->message, ares->controls);
1161
1162         case LDB_REPLY_REFERRAL:
1163                 return ldb_module_send_referral(ec->req, ares->referral);
1164
1165         case LDB_REPLY_DONE:
1166
1167                 return ldb_module_done(ec->req, ares->controls,
1168                                        ares->response, LDB_SUCCESS);
1169         }
1170
1171         talloc_free(ares);
1172         return LDB_SUCCESS;
1173 }
1174
1175 static int es_search(struct ldb_module *module, struct ldb_request *req)
1176 {
1177         struct ldb_context *ldb;
1178         struct es_context *ec;
1179         struct ldb_request *down_req;
1180         int ret;
1181
1182         /* There are no encrypted attributes on special DNs */
1183         if (ldb_dn_is_special(req->op.search.base)) {
1184                 return ldb_next_request(module, req);
1185         }
1186
1187         ldb = ldb_module_get_ctx(module);
1188
1189         ec = talloc(req, struct es_context);
1190         if (ec == NULL) {
1191                 return ldb_oom(ldb);
1192         }
1193
1194         ec->module = module;
1195         ec->req = req;
1196         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         LDB_REQ_SET_LOCATION(down_req);
1208         if (ret != LDB_SUCCESS) {
1209                 return ldb_operr(ldb);
1210         }
1211
1212         /* perform the search */
1213         return ldb_next_request(module, down_req);
1214 }
1215 static int es_add(struct ldb_module *module, struct ldb_request *req)
1216 {
1217
1218         struct es_data *data =
1219                 talloc_get_type(ldb_module_get_private(module),
1220                                 struct es_data);
1221         const struct ldb_message *encrypted_msg = NULL;
1222         struct ldb_context *ldb = NULL;
1223         int rc = LDB_SUCCESS;
1224
1225         if (!data->encrypt_secrets) {
1226                 return ldb_next_request(module, req);
1227         }
1228
1229         ldb = ldb_module_get_ctx(module);
1230         encrypted_msg = encrypt_secret_attributes(&rc,
1231                                                   req,
1232                                                   ldb,
1233                                                   req->op.add.message,
1234                                                   data);
1235         if (rc != LDB_SUCCESS) {
1236                 return rc;
1237         }
1238         /*
1239          * If we did not encrypt any of the attributes
1240          * continue on to the next module
1241          */
1242         if (encrypted_msg == NULL) {
1243                 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                 struct ldb_request* new_req = NULL;
1252                 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                 if (rc != LDB_SUCCESS) {
1261                         return rc;
1262                 }
1263                 return ldb_next_request(module, new_req);
1264         }
1265 }
1266
1267 static int es_modify(struct ldb_module *module, struct ldb_request *req)
1268 {
1269         struct es_data *data =
1270                 talloc_get_type(ldb_module_get_private(module),
1271                                 struct es_data);
1272         const struct ldb_message *encrypted_msg = NULL;
1273         struct ldb_context *ldb = NULL;
1274         int rc = LDB_SUCCESS;
1275
1276         if (!data->encrypt_secrets) {
1277                 return ldb_next_request(module, req);
1278         }
1279
1280         ldb = ldb_module_get_ctx(module);
1281         encrypted_msg = encrypt_secret_attributes(&rc,
1282                                                   req,
1283                                                   ldb,
1284                                                   req->op.mod.message,
1285                                                   data);
1286         if (rc != LDB_SUCCESS) {
1287                 return rc;
1288         }
1289         /*
1290          * If we did not encrypt any of the attributes
1291          * continue on to the next module
1292          */
1293         if (encrypted_msg == NULL) {
1294                 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                 struct ldb_request* new_req = NULL;
1304                 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                 if (rc != LDB_SUCCESS) {
1313                         return rc;
1314                 }
1315                 return ldb_next_request(module, new_req);
1316         }
1317 }
1318
1319 static int es_delete(struct ldb_module *module, struct ldb_request *req)
1320 {
1321         return ldb_next_request(module, req);
1322 }
1323
1324 static int es_rename(struct ldb_module *module, struct ldb_request *req)
1325 {
1326         return ldb_next_request(module, req);
1327 }
1328 static int es_init(struct ldb_module *ctx)
1329 {
1330         struct es_data *data;
1331         int ret;
1332
1333         data = talloc_zero(ctx, struct es_data);
1334         if (!data) {
1335                 return ldb_module_oom(ctx);
1336         }
1337
1338         {
1339                 struct ldb_context *ldb = ldb_module_get_ctx(ctx);
1340                 struct ldb_dn *samba_dsdb_dn;
1341                 struct ldb_result *res;
1342                 static const char *samba_dsdb_attrs[] = {
1343                         SAMBA_REQUIRED_FEATURES_ATTR,
1344                         NULL
1345                 };
1346                 TALLOC_CTX *frame = talloc_stackframe();
1347
1348                 samba_dsdb_dn = ldb_dn_new(frame, ldb, "@SAMBA_DSDB");
1349                 if (!samba_dsdb_dn) {
1350                         TALLOC_FREE(frame);
1351                         return ldb_oom(ldb);
1352                 }
1353                 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                 if (ret != LDB_SUCCESS) {
1361                         TALLOC_FREE(frame);
1362                         return ret;
1363                 }
1364                 data->encrypt_secrets =
1365                         ldb_msg_check_string_attribute(
1366                                 res->msgs[0],
1367                                 SAMBA_REQUIRED_FEATURES_ATTR,
1368                                 SAMBA_ENCRYPTED_SECRETS_FEATURE);
1369                 if (data->encrypt_secrets) {
1370                         ret = load_keys(ctx, data);
1371                         if (ret != LDB_SUCCESS) {
1372                                 TALLOC_FREE(frame);
1373                                 return ret;
1374                         }
1375                 }
1376                 TALLOC_FREE(frame);
1377         }
1378         ldb_module_set_private(ctx, data);
1379
1380         ret = ldb_next_init(ctx);
1381         if (ret != LDB_SUCCESS) {
1382                 return ret;
1383         }
1384         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 int ldb_encrypted_secrets_module_init(const char *version)
1398 {
1399         LDB_MODULE_CHECK_VERSION(version);
1400         return ldb_register_module(&ldb_encrypted_secrets_module_ops);
1401 }