LCOV - code coverage report
Current view: top level - source4/dsdb/samdb/ldb_modules - encrypted_secrets.c (source / functions) Hit Total Coverage
Test: coverage report for master 2f515e9b Lines: 394 514 76.7 %
Date: 2024-04-21 15:09:00 Functions: 27 29 93.1 %

          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             : }

Generated by: LCOV version 1.14