LCOV - code coverage report
Current view: top level - source4/rpc_server/backupkey - dcesrv_backupkey.c (source / functions) Hit Total Coverage
Test: coverage report for abartlet/fix-coverage dd10fb34 Lines: 583 819 71.2 %
Date: 2021-09-23 10:06:22 Functions: 19 22 86.4 %

          Line data    Source code
       1             : /*
       2             :    Unix SMB/CIFS implementation.
       3             : 
       4             :    endpoint server for the backupkey interface
       5             : 
       6             :    Copyright (C) Matthieu Patou <mat@samba.org> 2010
       7             :    Copyright (C) Andreas Schneider <asn@samba.org> 2015
       8             : 
       9             :    This program is free software; you can redistribute it and/or modify
      10             :    it under the terms of the GNU General Public License as published by
      11             :    the Free Software Foundation; either version 3 of the License, or
      12             :    (at your option) any later version.
      13             : 
      14             :    This program is distributed in the hope that it will be useful,
      15             :    but WITHOUT ANY WARRANTY; without even the implied warranty of
      16             :    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      17             :    GNU General Public License for more details.
      18             : 
      19             :    You should have received a copy of the GNU General Public License
      20             :    along with this program.  If not, see <http://www.gnu.org/licenses/>.
      21             : */
      22             : 
      23             : #include "includes.h"
      24             : #include "rpc_server/dcerpc_server.h"
      25             : #include "rpc_server/common/common.h"
      26             : #include "librpc/gen_ndr/ndr_backupkey.h"
      27             : #include "dsdb/common/util.h"
      28             : #include "dsdb/samdb/samdb.h"
      29             : #include "lib/ldb/include/ldb_errors.h"
      30             : #include "../lib/util/util_ldb.h"
      31             : #include "param/param.h"
      32             : #include "auth/session.h"
      33             : #include "system/network.h"
      34             : 
      35             : #include "../lib/tsocket/tsocket.h"
      36             : #include "../libcli/security/security.h"
      37             : #include "librpc/gen_ndr/ndr_security.h"
      38             : #include "libds/common/roles.h"
      39             : 
      40             : #include <gnutls/gnutls.h>
      41             : #include <gnutls/x509.h>
      42             : #include <gnutls/crypto.h>
      43             : #include <gnutls/abstract.h>
      44             : 
      45             : #include "lib/crypto/gnutls_helpers.h"
      46             : 
      47             : #undef strncasecmp
      48             : 
      49             : #define DCESRV_INTERFACE_BACKUPKEY_BIND(context, iface) \
      50             :         dcesrv_interface_backupkey_bind(context, iface)
      51           5 : static NTSTATUS dcesrv_interface_backupkey_bind(struct dcesrv_connection_context *context,
      52             :                                                 const struct dcesrv_interface *iface)
      53             : {
      54           5 :         return dcesrv_interface_bind_require_privacy(context, iface);
      55             : }
      56             : 
      57           4 : static NTSTATUS set_lsa_secret(TALLOC_CTX *mem_ctx,
      58             :                                struct ldb_context *ldb,
      59             :                                const char *name,
      60             :                                const DATA_BLOB *lsa_secret)
      61             : {
      62             :         struct ldb_message *msg;
      63             :         struct ldb_result *res;
      64             :         struct ldb_dn *domain_dn;
      65             :         struct ldb_dn *system_dn;
      66             :         struct ldb_val val;
      67             :         int ret;
      68             :         char *name2;
      69           4 :         struct timeval now = timeval_current();
      70           4 :         NTTIME nt_now = timeval_to_nttime(&now);
      71           4 :         const char *attrs[] = {
      72             :                 NULL
      73             :         };
      74             : 
      75           4 :         domain_dn = ldb_get_default_basedn(ldb);
      76           4 :         if (!domain_dn) {
      77           0 :                 return NT_STATUS_INTERNAL_ERROR;
      78             :         }
      79             : 
      80           4 :         msg = ldb_msg_new(mem_ctx);
      81           4 :         if (msg == NULL) {
      82           0 :                 return NT_STATUS_NO_MEMORY;
      83             :         }
      84             : 
      85             :         /*
      86             :          * This function is a lot like dcesrv_lsa_CreateSecret
      87             :          * in the rpc_server/lsa directory
      88             :          * The reason why we duplicate the effort here is that:
      89             :          * * we want to keep the former function static
      90             :          * * we want to avoid the burden of doing LSA calls
      91             :          *   when we can just manipulate the secrets directly
      92             :          * * taillor the function to the particular needs of backup protocol
      93             :          */
      94             : 
      95           4 :         system_dn = samdb_search_dn(ldb, msg, domain_dn, "(&(objectClass=container)(cn=System))");
      96           4 :         if (system_dn == NULL) {
      97           0 :                 talloc_free(msg);
      98           0 :                 return NT_STATUS_NO_MEMORY;
      99             :         }
     100             : 
     101           4 :         name2 = talloc_asprintf(msg, "%s Secret", name);
     102           4 :         if (name2 == NULL) {
     103           0 :                 talloc_free(msg);
     104           0 :                 return NT_STATUS_NO_MEMORY;
     105             :         }
     106             : 
     107           4 :         ret = ldb_search(ldb, mem_ctx, &res, system_dn, LDB_SCOPE_SUBTREE, attrs,
     108             :                            "(&(cn=%s)(objectclass=secret))",
     109             :                            ldb_binary_encode_string(mem_ctx, name2));
     110             : 
     111           4 :         if (ret != LDB_SUCCESS ||  res->count != 0 ) {
     112           0 :                 DEBUG(2, ("Secret %s already exists !\n", name2));
     113           0 :                 talloc_free(msg);
     114           0 :                 return NT_STATUS_OBJECT_NAME_COLLISION;
     115             :         }
     116             : 
     117             :         /*
     118             :          * We don't care about previous value as we are
     119             :          * here only if the key didn't exists before
     120             :          */
     121             : 
     122           4 :         msg->dn = ldb_dn_copy(mem_ctx, system_dn);
     123           4 :         if (msg->dn == NULL) {
     124           0 :                 talloc_free(msg);
     125           0 :                 return NT_STATUS_NO_MEMORY;
     126             :         }
     127           4 :         if (!ldb_dn_add_child_fmt(msg->dn, "cn=%s", name2)) {
     128           0 :                 talloc_free(msg);
     129           0 :                 return NT_STATUS_NO_MEMORY;
     130             :         }
     131             : 
     132           4 :         ret = ldb_msg_add_string(msg, "cn", name2);
     133           4 :         if (ret != LDB_SUCCESS) {
     134           0 :                 talloc_free(msg);
     135           0 :                 return NT_STATUS_NO_MEMORY;
     136             :         }
     137           4 :         ret = ldb_msg_add_string(msg, "objectClass", "secret");
     138           4 :         if (ret != LDB_SUCCESS) {
     139           0 :                 talloc_free(msg);
     140           0 :                 return NT_STATUS_NO_MEMORY;
     141             :         }
     142           4 :         ret = samdb_msg_add_uint64(ldb, mem_ctx, msg, "priorSetTime", nt_now);
     143           4 :         if (ret != LDB_SUCCESS) {
     144           0 :                 talloc_free(msg);
     145           0 :                 return NT_STATUS_NO_MEMORY;
     146             :         }
     147           4 :         val.data = lsa_secret->data;
     148           4 :         val.length = lsa_secret->length;
     149           4 :         ret = ldb_msg_add_value(msg, "currentValue", &val, NULL);
     150           4 :         if (ret != LDB_SUCCESS) {
     151           0 :                 talloc_free(msg);
     152           0 :                 return NT_STATUS_NO_MEMORY;
     153             :         }
     154           4 :         ret = samdb_msg_add_uint64(ldb, mem_ctx, msg, "lastSetTime", nt_now);
     155           4 :         if (ret != LDB_SUCCESS) {
     156           0 :                 talloc_free(msg);
     157           0 :                 return NT_STATUS_NO_MEMORY;
     158             :         }
     159             : 
     160             :         /*
     161             :          * create the secret with DSDB_MODIFY_RELAX
     162             :          * otherwise dsdb/samdb/ldb_modules/objectclass.c forbid
     163             :          * the create of LSA secret object
     164             :          */
     165           4 :         ret = dsdb_add(ldb, msg, DSDB_MODIFY_RELAX);
     166           4 :         if (ret != LDB_SUCCESS) {
     167           0 :                 DEBUG(2,("Failed to create secret record %s: %s\n",
     168             :                         ldb_dn_get_linearized(msg->dn),
     169             :                         ldb_errstring(ldb)));
     170           0 :                 talloc_free(msg);
     171           0 :                 return NT_STATUS_ACCESS_DENIED;
     172             :         }
     173             : 
     174           4 :         talloc_free(msg);
     175           4 :         return NT_STATUS_OK;
     176             : }
     177             : 
     178             : /* This function is pretty much like dcesrv_lsa_QuerySecret */
     179          81 : static NTSTATUS get_lsa_secret(TALLOC_CTX *mem_ctx,
     180             :                                struct ldb_context *ldb,
     181             :                                const char *name,
     182             :                                DATA_BLOB *lsa_secret)
     183             : {
     184             :         TALLOC_CTX *tmp_mem;
     185             :         struct ldb_result *res;
     186             :         struct ldb_dn *domain_dn;
     187             :         struct ldb_dn *system_dn;
     188             :         const struct ldb_val *val;
     189             :         uint8_t *data;
     190          81 :         const char *attrs[] = {
     191             :                 "currentValue",
     192             :                 NULL
     193             :         };
     194             :         int ret;
     195             : 
     196          81 :         lsa_secret->data = NULL;
     197          81 :         lsa_secret->length = 0;
     198             : 
     199          81 :         domain_dn = ldb_get_default_basedn(ldb);
     200          81 :         if (!domain_dn) {
     201           0 :                 return NT_STATUS_INTERNAL_ERROR;
     202             :         }
     203             : 
     204          81 :         tmp_mem = talloc_new(mem_ctx);
     205          81 :         if (tmp_mem == NULL) {
     206           0 :                 return NT_STATUS_NO_MEMORY;
     207             :         }
     208             : 
     209          81 :         system_dn = samdb_search_dn(ldb, tmp_mem, domain_dn, "(&(objectClass=container)(cn=System))");
     210          81 :         if (system_dn == NULL) {
     211           0 :                 talloc_free(tmp_mem);
     212           0 :                 return NT_STATUS_NO_MEMORY;
     213             :         }
     214             : 
     215          81 :         ret = ldb_search(ldb, mem_ctx, &res, system_dn, LDB_SCOPE_SUBTREE, attrs,
     216             :                            "(&(cn=%s Secret)(objectclass=secret))",
     217             :                            ldb_binary_encode_string(tmp_mem, name));
     218             : 
     219          81 :         if (ret != LDB_SUCCESS) {
     220           0 :                 talloc_free(tmp_mem);
     221           0 :                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
     222             :         }
     223          81 :         if (res->count == 0) {
     224           5 :                 talloc_free(tmp_mem);
     225           5 :                 return NT_STATUS_RESOURCE_NAME_NOT_FOUND;
     226             :         }
     227          76 :         if (res->count > 1) {
     228           0 :                 DEBUG(2, ("Secret %s collision\n", name));
     229           0 :                 talloc_free(tmp_mem);
     230           0 :                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
     231             :         }
     232             : 
     233          76 :         val = ldb_msg_find_ldb_val(res->msgs[0], "currentValue");
     234          76 :         if (val == NULL) {
     235             :                 /*
     236             :                  * The secret object is here but we don't have the secret value
     237             :                  * The most common case is a RODC
     238             :                  */
     239           0 :                 *lsa_secret = data_blob_null;
     240           0 :                 talloc_free(tmp_mem);
     241           0 :                 return NT_STATUS_OK;
     242             :         }
     243             : 
     244          76 :         data = val->data;
     245          76 :         lsa_secret->data = talloc_move(mem_ctx, &data);
     246          76 :         lsa_secret->length = val->length;
     247             : 
     248          76 :         talloc_free(tmp_mem);
     249          76 :         return NT_STATUS_OK;
     250             : }
     251             : 
     252          64 : static int reverse_and_get_bignum(TALLOC_CTX *mem_ctx,
     253             :                                   DATA_BLOB blob,
     254             :                                   gnutls_datum_t *datum)
     255             : {
     256             :         uint32_t i;
     257             : 
     258          64 :         datum->data = talloc_array(mem_ctx, uint8_t, blob.length);
     259          64 :         if (datum->data == NULL) {
     260           0 :                 return -1;
     261             :         }
     262             : 
     263        9312 :         for(i = 0; i < blob.length; i++) {
     264        9248 :                 datum->data[i] = blob.data[blob.length - i - 1];
     265             :         }
     266          64 :         datum->size = blob.length;
     267             : 
     268          64 :         return 0;
     269             : }
     270             : 
     271           8 : static NTSTATUS get_pk_from_raw_keypair_params(TALLOC_CTX *ctx,
     272             :                                 struct bkrp_exported_RSA_key_pair *keypair,
     273             :                                 gnutls_privkey_t *pk)
     274             : {
     275           8 :         gnutls_x509_privkey_t x509_privkey = NULL;
     276           8 :         gnutls_privkey_t privkey = NULL;
     277             :         gnutls_datum_t m, e, d, p, q, u, e1, e2;
     278             :         int rc;
     279             : 
     280           8 :         rc = reverse_and_get_bignum(ctx, keypair->modulus, &m);
     281           8 :         if (rc != 0) {
     282           0 :                 return NT_STATUS_INVALID_PARAMETER;
     283             :         }
     284           8 :         rc = reverse_and_get_bignum(ctx, keypair->public_exponent, &e);
     285           8 :         if (rc != 0) {
     286           0 :                 return NT_STATUS_INVALID_PARAMETER;
     287             :         }
     288           8 :         rc = reverse_and_get_bignum(ctx, keypair->private_exponent, &d);
     289           8 :         if (rc != 0) {
     290           0 :                 return NT_STATUS_INVALID_PARAMETER;
     291             :         }
     292             : 
     293           8 :         rc = reverse_and_get_bignum(ctx, keypair->prime1, &p);
     294           8 :         if (rc != 0) {
     295           0 :                 return NT_STATUS_INVALID_PARAMETER;
     296             :         }
     297           8 :         rc = reverse_and_get_bignum(ctx, keypair->prime2, &q);
     298           8 :         if (rc != 0) {
     299           0 :                 return NT_STATUS_INVALID_PARAMETER;
     300             :         }
     301             : 
     302           8 :         rc = reverse_and_get_bignum(ctx, keypair->coefficient, &u);
     303           8 :         if (rc != 0) {
     304           0 :                 return NT_STATUS_INVALID_PARAMETER;
     305             :         }
     306             : 
     307           8 :         rc = reverse_and_get_bignum(ctx, keypair->exponent1, &e1);
     308           8 :         if (rc != 0) {
     309           0 :                 return NT_STATUS_INVALID_PARAMETER;
     310             :         }
     311           8 :         rc = reverse_and_get_bignum(ctx, keypair->exponent2, &e2);
     312           8 :         if (rc != 0) {
     313           0 :                 return NT_STATUS_INVALID_PARAMETER;
     314             :         }
     315             : 
     316           8 :         rc = gnutls_x509_privkey_init(&x509_privkey);
     317           8 :         if (rc != GNUTLS_E_SUCCESS) {
     318           0 :                 DBG_ERR("gnutls_x509_privkey_init failed - %s\n",
     319             :                         gnutls_strerror(rc));
     320           0 :                 return NT_STATUS_INTERNAL_ERROR;
     321             :         }
     322             : 
     323           8 :         rc = gnutls_x509_privkey_import_rsa_raw2(x509_privkey,
     324             :                                                  &m,
     325             :                                                  &e,
     326             :                                                  &d,
     327             :                                                  &p,
     328             :                                                  &q,
     329             :                                                  &u,
     330             :                                                  &e1,
     331             :                                                  &e2);
     332           8 :         if (rc != GNUTLS_E_SUCCESS) {
     333           0 :                 DBG_ERR("gnutls_x509_privkey_import_rsa_raw2 failed - %s\n",
     334             :                         gnutls_strerror(rc));
     335           0 :                 return NT_STATUS_INTERNAL_ERROR;
     336             :         }
     337             : 
     338           8 :         rc = gnutls_privkey_init(&privkey);
     339           8 :         if (rc != GNUTLS_E_SUCCESS) {
     340           0 :                 DBG_ERR("gnutls_privkey_init failed - %s\n",
     341             :                         gnutls_strerror(rc));
     342           0 :                 gnutls_x509_privkey_deinit(x509_privkey);
     343           0 :                 return NT_STATUS_INTERNAL_ERROR;
     344             :         }
     345             : 
     346           8 :         rc = gnutls_privkey_import_x509(privkey,
     347             :                                         x509_privkey,
     348             :                                         GNUTLS_PRIVKEY_IMPORT_AUTO_RELEASE);
     349           8 :         if (rc != GNUTLS_E_SUCCESS) {
     350           0 :                 DBG_ERR("gnutls_privkey_import_x509 failed - %s\n",
     351             :                         gnutls_strerror(rc));
     352           0 :                 gnutls_x509_privkey_deinit(x509_privkey);
     353           0 :                 return NT_STATUS_INTERNAL_ERROR;
     354             :         }
     355             : 
     356           8 :         *pk = privkey;
     357             : 
     358           8 :         return NT_STATUS_OK;
     359             : }
     360             : 
     361           6 : static WERROR get_and_verify_access_check(TALLOC_CTX *sub_ctx,
     362             :                                           uint32_t version,
     363             :                                           uint8_t *key_and_iv,
     364             :                                           uint8_t *access_check,
     365             :                                           uint32_t access_check_len,
     366             :                                           struct auth_session_info *session_info)
     367             : {
     368             :         struct bkrp_access_check_v2 uncrypted_accesscheckv2;
     369             :         struct bkrp_access_check_v3 uncrypted_accesscheckv3;
     370           6 :         gnutls_cipher_hd_t cipher_handle = { 0 };
     371             :         gnutls_cipher_algorithm_t cipher_algo;
     372             :         DATA_BLOB blob_us;
     373             :         enum ndr_err_code ndr_err;
     374             :         gnutls_datum_t key;
     375             :         gnutls_datum_t iv;
     376             : 
     377           6 :         struct dom_sid *access_sid = NULL;
     378           6 :         struct dom_sid *caller_sid = NULL;
     379             :         int rc;
     380             : 
     381           6 :         switch (version) {
     382           5 :         case 2:
     383           5 :                 cipher_algo = GNUTLS_CIPHER_3DES_CBC;
     384           5 :                 break;
     385           1 :         case 3:
     386           1 :                 cipher_algo = GNUTLS_CIPHER_AES_256_CBC;
     387           1 :                 break;
     388           0 :         default:
     389           0 :                 return WERR_INVALID_DATA;
     390             :         }
     391             : 
     392           6 :         key.data = key_and_iv;
     393           6 :         key.size = gnutls_cipher_get_key_size(cipher_algo);
     394             : 
     395           6 :         iv.data = key_and_iv + key.size;
     396           6 :         iv.size = gnutls_cipher_get_iv_size(cipher_algo);
     397             : 
     398             :         /* Allocate data structure for the plaintext */
     399           6 :         blob_us = data_blob_talloc_zero(sub_ctx, access_check_len);
     400           6 :         if (blob_us.data == NULL) {
     401           0 :                 return WERR_INVALID_DATA;
     402             :         }
     403             : 
     404           6 :         rc = gnutls_cipher_init(&cipher_handle,
     405             :                                 cipher_algo,
     406             :                                 &key,
     407             :                                 &iv);
     408           6 :         if (rc < 0) {
     409           0 :                 DBG_ERR("gnutls_cipher_init failed: %s\n",
     410             :                         gnutls_strerror(rc));
     411           0 :                 return WERR_INVALID_DATA;
     412             :         }
     413             : 
     414          12 :         rc = gnutls_cipher_decrypt2(cipher_handle,
     415             :                                     access_check,
     416             :                                     access_check_len,
     417           6 :                                     blob_us.data,
     418             :                                     blob_us.length);
     419           6 :         gnutls_cipher_deinit(cipher_handle);
     420           6 :         if (rc < 0) {
     421           0 :                 DBG_ERR("gnutls_cipher_decrypt2 failed: %s\n",
     422             :                         gnutls_strerror(rc));
     423           0 :                 return WERR_INVALID_DATA;
     424             :         }
     425             : 
     426           6 :         switch (version) {
     427           5 :         case 2:
     428           5 :         {
     429           5 :                 uint32_t hash_size = 20;
     430           5 :                 uint8_t hash[hash_size];
     431             :                 gnutls_hash_hd_t dig_ctx;
     432             : 
     433           5 :                 ndr_err = ndr_pull_struct_blob(&blob_us, sub_ctx, &uncrypted_accesscheckv2,
     434             :                                         (ndr_pull_flags_fn_t)ndr_pull_bkrp_access_check_v2);
     435           5 :                 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
     436             :                         /* Unable to unmarshall */
     437           2 :                         return WERR_INVALID_DATA;
     438             :                 }
     439           5 :                 if (uncrypted_accesscheckv2.magic != 0x1) {
     440             :                         /* wrong magic */
     441           1 :                         return WERR_INVALID_DATA;
     442             :                 }
     443             : 
     444           4 :                 gnutls_hash_init(&dig_ctx, GNUTLS_DIG_SHA1);
     445           8 :                 gnutls_hash(dig_ctx,
     446           4 :                             blob_us.data,
     447           4 :                             blob_us.length - hash_size);
     448           4 :                 gnutls_hash_deinit(dig_ctx, hash);
     449             :                 /*
     450             :                  * We free it after the sha1 calculation because blob.data
     451             :                  * point to the same area
     452             :                  */
     453             : 
     454           4 :                 if (memcmp(hash, uncrypted_accesscheckv2.hash, hash_size) != 0) {
     455           1 :                         DEBUG(2, ("Wrong hash value in the access check in backup key remote protocol\n"));
     456           1 :                         return WERR_INVALID_DATA;
     457             :                 }
     458           3 :                 access_sid = &(uncrypted_accesscheckv2.sid);
     459           6 :                 break;
     460             :         }
     461           1 :         case 3:
     462           1 :         {
     463           1 :                 uint32_t hash_size = 64;
     464           1 :                 uint8_t hash[hash_size];
     465             :                 gnutls_hash_hd_t dig_ctx;
     466             : 
     467           1 :                 ndr_err = ndr_pull_struct_blob(&blob_us, sub_ctx, &uncrypted_accesscheckv3,
     468             :                                         (ndr_pull_flags_fn_t)ndr_pull_bkrp_access_check_v3);
     469           1 :                 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
     470             :                         /* Unable to unmarshall */
     471           0 :                         return WERR_INVALID_DATA;
     472             :                 }
     473           1 :                 if (uncrypted_accesscheckv3.magic != 0x1) {
     474             :                         /* wrong magic */
     475           0 :                         return WERR_INVALID_DATA;
     476             :                 }
     477             : 
     478           1 :                 gnutls_hash_init(&dig_ctx, GNUTLS_DIG_SHA512);
     479           2 :                 gnutls_hash(dig_ctx,
     480           1 :                             blob_us.data,
     481           1 :                             blob_us.length - hash_size);
     482           1 :                 gnutls_hash_deinit(dig_ctx, hash);
     483             : 
     484             :                 /*
     485             :                  * We free it after the sha1 calculation because blob.data
     486             :                  * point to the same area
     487             :                  */
     488             : 
     489           1 :                 if (memcmp(hash, uncrypted_accesscheckv3.hash, hash_size) != 0) {
     490           0 :                         DEBUG(2, ("Wrong hash value in the access check in backup key remote protocol\n"));
     491           0 :                         return WERR_INVALID_DATA;
     492             :                 }
     493           1 :                 access_sid = &(uncrypted_accesscheckv3.sid);
     494           2 :                 break;
     495             :         }
     496           0 :         default:
     497             :                 /* Never reached normally as we filtered at the switch / case level */
     498           0 :                 return WERR_INVALID_DATA;
     499             :         }
     500             : 
     501           4 :         caller_sid = &session_info->security_token->sids[PRIMARY_USER_SID_INDEX];
     502             : 
     503           4 :         if (!dom_sid_equal(caller_sid, access_sid)) {
     504           1 :                 return WERR_INVALID_ACCESS;
     505             :         }
     506           3 :         return WERR_OK;
     507             : }
     508             : 
     509             : /*
     510             :  * We have some data, such as saved website or IMAP passwords that the
     511             :  * client has in profile on-disk.  This needs to be decrypted.  This
     512             :  * version gives the server the data over the network (protected by
     513             :  * the X.509 certificate and public key encryption, and asks that it
     514             :  * be decrypted returned for short-term use, protected only by the
     515             :  * negotiated transport encryption.
     516             :  *
     517             :  * The data is NOT stored in the LSA, but a X.509 certificate, public
     518             :  * and private keys used to encrypt the data will be stored.  There is
     519             :  * only one active encryption key pair and certificate per domain, it
     520             :  * is pointed at with G$BCKUPKEY_PREFERRED in the LSA secrets store.
     521             :  *
     522             :  * The potentially multiple valid decrypting key pairs are in turn
     523             :  * stored in the LSA secrets store as G$BCKUPKEY_keyGuidString.
     524             :  *
     525             :  */
     526          10 : static WERROR bkrp_client_wrap_decrypt_data(struct dcesrv_call_state *dce_call,
     527             :                                             TALLOC_CTX *mem_ctx,
     528             :                                             struct bkrp_BackupKey *r,
     529             :                                             struct ldb_context *ldb_ctx)
     530             : {
     531          10 :         struct auth_session_info *session_info =
     532           0 :                 dcesrv_call_session_info(dce_call);
     533             :         struct bkrp_client_side_wrapped uncrypt_request;
     534             :         DATA_BLOB blob;
     535             :         enum ndr_err_code ndr_err;
     536             :         char *guid_string;
     537             :         char *cert_secret_name;
     538             :         DATA_BLOB lsa_secret;
     539          10 :         DATA_BLOB *uncrypted_data = NULL;
     540             :         NTSTATUS status;
     541             :         uint32_t requested_version;
     542             : 
     543          10 :         blob.data = r->in.data_in;
     544          10 :         blob.length = r->in.data_in_len;
     545             : 
     546          10 :         if (r->in.data_in_len < 4 || r->in.data_in == NULL) {
     547           0 :                 return WERR_INVALID_PARAMETER;
     548             :         }
     549             : 
     550             :         /*
     551             :          * We check for the version here, so we can actually print the
     552             :          * message as we are unlikely to parse it with NDR.
     553             :          */
     554          10 :         requested_version = IVAL(r->in.data_in, 0);
     555          10 :         if ((requested_version != BACKUPKEY_CLIENT_WRAP_VERSION2)
     556           4 :             && (requested_version != BACKUPKEY_CLIENT_WRAP_VERSION3)) {
     557           1 :                 DEBUG(1, ("Request for unknown BackupKey sub-protocol %d\n", requested_version));
     558           1 :                 return WERR_INVALID_PARAMETER;
     559             :         }
     560             : 
     561           9 :         ndr_err = ndr_pull_struct_blob(&blob, mem_ctx, &uncrypt_request,
     562             :                                        (ndr_pull_flags_fn_t)ndr_pull_bkrp_client_side_wrapped);
     563           9 :         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
     564           0 :                 return WERR_INVALID_PARAMETER;
     565             :         }
     566             : 
     567           9 :         if ((uncrypt_request.version != BACKUPKEY_CLIENT_WRAP_VERSION2)
     568           3 :             && (uncrypt_request.version != BACKUPKEY_CLIENT_WRAP_VERSION3)) {
     569           0 :                 DEBUG(1, ("Request for unknown BackupKey sub-protocol %d\n", uncrypt_request.version));
     570           0 :                 return WERR_INVALID_PARAMETER;
     571             :         }
     572             : 
     573           9 :         guid_string = GUID_string(mem_ctx, &uncrypt_request.guid);
     574           9 :         if (guid_string == NULL) {
     575           0 :                 return WERR_NOT_ENOUGH_MEMORY;
     576             :         }
     577             : 
     578           9 :         cert_secret_name = talloc_asprintf(mem_ctx,
     579             :                                            "BCKUPKEY_%s",
     580             :                                            guid_string);
     581           9 :         if (cert_secret_name == NULL) {
     582           0 :                 return WERR_NOT_ENOUGH_MEMORY;
     583             :         }
     584             : 
     585           9 :         status = get_lsa_secret(mem_ctx,
     586             :                                 ldb_ctx,
     587             :                                 cert_secret_name,
     588             :                                 &lsa_secret);
     589           9 :         if (!NT_STATUS_IS_OK(status)) {
     590           1 :                 DEBUG(10, ("Error while fetching secret %s\n", cert_secret_name));
     591           1 :                 return WERR_INVALID_DATA;
     592           8 :         } else if (lsa_secret.length == 0) {
     593             :                 /* we do not have the real secret attribute, like if we are an RODC */
     594           0 :                 return WERR_INVALID_PARAMETER;
     595             :         } else {
     596             :                 struct bkrp_exported_RSA_key_pair keypair;
     597           8 :                 gnutls_privkey_t privkey = NULL;
     598             :                 gnutls_datum_t reversed_secret;
     599             :                 gnutls_datum_t uncrypted_secret;
     600             :                 uint32_t i;
     601             :                 DATA_BLOB blob_us;
     602             :                 WERROR werr;
     603             :                 int rc;
     604             : 
     605           8 :                 ndr_err = ndr_pull_struct_blob(&lsa_secret, mem_ctx, &keypair, (ndr_pull_flags_fn_t)ndr_pull_bkrp_exported_RSA_key_pair);
     606           8 :                 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
     607           0 :                         DEBUG(2, ("Unable to parse the ndr encoded cert in key %s\n", cert_secret_name));
     608           5 :                         return WERR_FILE_NOT_FOUND;
     609             :                 }
     610             : 
     611           8 :                 status = get_pk_from_raw_keypair_params(mem_ctx,
     612             :                                                         &keypair,
     613             :                                                         &privkey);
     614           8 :                 if (!NT_STATUS_IS_OK(status)) {
     615           0 :                         return WERR_INTERNAL_ERROR;
     616             :                 }
     617             : 
     618           8 :                 reversed_secret.data = talloc_array(mem_ctx, uint8_t,
     619             :                                                     uncrypt_request.encrypted_secret_len);
     620           8 :                 if (reversed_secret.data == NULL) {
     621           0 :                         gnutls_privkey_deinit(privkey);
     622           0 :                         return WERR_NOT_ENOUGH_MEMORY;
     623             :                 }
     624             : 
     625             :                 /* The secret has to be reversed ... */
     626        2056 :                 for(i=0; i< uncrypt_request.encrypted_secret_len; i++) {
     627        2048 :                         uint8_t *reversed = (uint8_t *)reversed_secret.data;
     628        2048 :                         uint8_t *uncrypt = uncrypt_request.encrypted_secret;
     629        2048 :                         reversed[i] = uncrypt[uncrypt_request.encrypted_secret_len - 1 - i];
     630             :                 }
     631           8 :                 reversed_secret.size = uncrypt_request.encrypted_secret_len;
     632             : 
     633             :                 /*
     634             :                  * Let's try to decrypt the secret now that
     635             :                  * we have the private key ...
     636             :                  */
     637           8 :                 rc = gnutls_privkey_decrypt_data(privkey,
     638             :                                                  0,
     639             :                                                  &reversed_secret,
     640             :                                                  &uncrypted_secret);
     641           8 :                 gnutls_privkey_deinit(privkey);
     642           8 :                 if (rc != GNUTLS_E_SUCCESS) {
     643             :                         /* We are not able to decrypt the secret, looks like something is wrong */
     644           1 :                         return WERR_INVALID_PARAMETER;
     645             :                 }
     646           7 :                 blob_us.data = uncrypted_secret.data;
     647           7 :                 blob_us.length = uncrypted_secret.size;
     648             : 
     649           7 :                 if (uncrypt_request.version == 2) {
     650             :                         struct bkrp_encrypted_secret_v2 uncrypted_secretv2;
     651             : 
     652           5 :                         ndr_err = ndr_pull_struct_blob(&blob_us, mem_ctx, &uncrypted_secretv2,
     653             :                                         (ndr_pull_flags_fn_t)ndr_pull_bkrp_encrypted_secret_v2);
     654           5 :                         gnutls_free(uncrypted_secret.data);
     655           5 :                         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
     656             :                                 /* Unable to unmarshall */
     657           3 :                                 return WERR_INVALID_DATA;
     658             :                         }
     659           5 :                         if (uncrypted_secretv2.magic != 0x20) {
     660             :                                 /* wrong magic */
     661           0 :                                 return WERR_INVALID_DATA;
     662             :                         }
     663             : 
     664           5 :                         werr = get_and_verify_access_check(mem_ctx, 2,
     665             :                                                            uncrypted_secretv2.payload_key,
     666             :                                                            uncrypt_request.access_check,
     667             :                                                            uncrypt_request.access_check_len,
     668             :                                                            session_info);
     669           5 :                         if (!W_ERROR_IS_OK(werr)) {
     670           3 :                                 return werr;
     671             :                         }
     672           2 :                         uncrypted_data = talloc(mem_ctx, DATA_BLOB);
     673           2 :                         if (uncrypted_data == NULL) {
     674           0 :                                 return WERR_INVALID_DATA;
     675             :                         }
     676             : 
     677           2 :                         uncrypted_data->data = uncrypted_secretv2.secret;
     678           2 :                         uncrypted_data->length = uncrypted_secretv2.secret_len;
     679             :                 }
     680           4 :                 if (uncrypt_request.version == 3) {
     681             :                         struct bkrp_encrypted_secret_v3 uncrypted_secretv3;
     682             : 
     683           2 :                         ndr_err = ndr_pull_struct_blob(&blob_us, mem_ctx, &uncrypted_secretv3,
     684             :                                         (ndr_pull_flags_fn_t)ndr_pull_bkrp_encrypted_secret_v3);
     685           2 :                         gnutls_free(uncrypted_secret.data);
     686           2 :                         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
     687             :                                 /* Unable to unmarshall */
     688           1 :                                 return WERR_INVALID_DATA;
     689             :                         }
     690             : 
     691           3 :                         if (uncrypted_secretv3.magic1 != 0x30  ||
     692           2 :                             uncrypted_secretv3.magic2 != 0x6610 ||
     693           1 :                             uncrypted_secretv3.magic3 != 0x800e) {
     694             :                                 /* wrong magic */
     695           1 :                                 return WERR_INVALID_DATA;
     696             :                         }
     697             : 
     698             :                         /*
     699             :                          * Confirm that the caller is permitted to
     700             :                          * read this particular data.  Because one key
     701             :                          * pair is used per domain, the caller could
     702             :                          * have stolen the profile data on-disk and
     703             :                          * would otherwise be able to read the
     704             :                          * passwords.
     705             :                          */
     706             : 
     707           1 :                         werr = get_and_verify_access_check(mem_ctx, 3,
     708             :                                                            uncrypted_secretv3.payload_key,
     709             :                                                            uncrypt_request.access_check,
     710             :                                                            uncrypt_request.access_check_len,
     711             :                                                            session_info);
     712           1 :                         if (!W_ERROR_IS_OK(werr)) {
     713           0 :                                 return werr;
     714             :                         }
     715             : 
     716           1 :                         uncrypted_data = talloc(mem_ctx, DATA_BLOB);
     717           1 :                         if (uncrypted_data == NULL) {
     718           0 :                                 return WERR_INVALID_DATA;
     719             :                         }
     720             : 
     721           1 :                         uncrypted_data->data = uncrypted_secretv3.secret;
     722           1 :                         uncrypted_data->length = uncrypted_secretv3.secret_len;
     723             :                 }
     724             : 
     725             :                 /*
     726             :                  * Yeah if we are here all looks pretty good:
     727             :                  * - hash is ok
     728             :                  * - user sid is the same as the one in access check
     729             :                  * - we were able to decrypt the whole stuff
     730             :                  */
     731             :         }
     732             : 
     733           3 :         if (uncrypted_data->data == NULL) {
     734           0 :                 return WERR_INVALID_DATA;
     735             :         }
     736             : 
     737             :         /* There is a magic value a the beginning of the data
     738             :          * we can use an adhoc structure but as the
     739             :          * parent structure is just an array of bytes it a lot of work
     740             :          * work just prepending 4 bytes
     741             :          */
     742           3 :         *(r->out.data_out) = talloc_zero_array(mem_ctx, uint8_t, uncrypted_data->length + 4);
     743           3 :         W_ERROR_HAVE_NO_MEMORY(*(r->out.data_out));
     744           3 :         memcpy(4+*(r->out.data_out), uncrypted_data->data, uncrypted_data->length);
     745           3 :         *(r->out.data_out_len) = uncrypted_data->length + 4;
     746             : 
     747           3 :         return WERR_OK;
     748             : }
     749             : 
     750           8 : static DATA_BLOB *reverse_and_get_blob(TALLOC_CTX *mem_ctx,
     751             :                                        gnutls_datum_t *datum)
     752             : {
     753             :         DATA_BLOB *blob;
     754             :         size_t i;
     755             : 
     756           8 :         blob = talloc(mem_ctx, DATA_BLOB);
     757           8 :         if (blob == NULL) {
     758           0 :                 return NULL;
     759             :         }
     760             : 
     761           8 :         blob->length = datum->size;
     762           8 :         if (datum->data[0] == '\0') {
     763             :                 /* The datum has a leading byte zero, skip it */
     764           6 :                 blob->length = datum->size - 1;
     765             :         }
     766           8 :         blob->data = talloc_zero_array(mem_ctx, uint8_t, blob->length);
     767           8 :         if (blob->data == NULL) {
     768           0 :                 talloc_free(blob);
     769           0 :                 return NULL;
     770             :         }
     771             : 
     772        1163 :         for (i = 0; i < blob->length; i++) {
     773        1155 :                 blob->data[i] = datum->data[datum->size - i - 1];
     774             :         }
     775             : 
     776           8 :         return blob;
     777             : }
     778             : 
     779           1 : static WERROR create_privkey_rsa(gnutls_privkey_t *pk)
     780             : {
     781           1 :         int bits = 2048;
     782           1 :         gnutls_x509_privkey_t x509_privkey = NULL;
     783           1 :         gnutls_privkey_t privkey = NULL;
     784             :         int rc;
     785             : 
     786           1 :         rc = gnutls_x509_privkey_init(&x509_privkey);
     787           1 :         if (rc != GNUTLS_E_SUCCESS) {
     788           0 :                 DBG_ERR("gnutls_x509_privkey_init failed - %s\n",
     789             :                         gnutls_strerror(rc));
     790           0 :                 return WERR_INTERNAL_ERROR;
     791             :         }
     792             : 
     793           1 :         rc = gnutls_x509_privkey_generate(x509_privkey,
     794             :                                           GNUTLS_PK_RSA,
     795             :                                           bits,
     796             :                                           0);
     797           1 :         if (rc != GNUTLS_E_SUCCESS) {
     798           0 :                 DBG_ERR("gnutls_x509_privkey_generate failed - %s\n",
     799             :                         gnutls_strerror(rc));
     800           0 :                 gnutls_x509_privkey_deinit(x509_privkey);
     801           0 :                 return WERR_INTERNAL_ERROR;
     802             :         }
     803             : 
     804           1 :         rc = gnutls_privkey_init(&privkey);
     805           1 :         if (rc != GNUTLS_E_SUCCESS) {
     806           0 :                 DBG_ERR("gnutls_privkey_init failed - %s\n",
     807             :                         gnutls_strerror(rc));
     808           0 :                 gnutls_x509_privkey_deinit(x509_privkey);
     809           0 :                 return WERR_INTERNAL_ERROR;
     810             :         }
     811             : 
     812           1 :         rc = gnutls_privkey_import_x509(privkey,
     813             :                                         x509_privkey,
     814             :                                         GNUTLS_PRIVKEY_IMPORT_AUTO_RELEASE);
     815           1 :         if (rc != GNUTLS_E_SUCCESS) {
     816           0 :                 DBG_ERR("gnutls_privkey_import_x509 failed - %s\n",
     817             :                         gnutls_strerror(rc));
     818           0 :                 gnutls_x509_privkey_deinit(x509_privkey);
     819           0 :                 return WERR_INTERNAL_ERROR;
     820             :         }
     821             : 
     822           1 :         *pk = privkey;
     823             : 
     824           1 :         return WERR_OK;
     825             : }
     826             : 
     827           1 : static WERROR self_sign_cert(TALLOC_CTX *mem_ctx,
     828             :                              time_t lifetime,
     829             :                              const char *dn,
     830             :                              gnutls_privkey_t issuer_privkey,
     831             :                              gnutls_x509_crt_t *certificate,
     832             :                              DATA_BLOB *guidblob)
     833             : {
     834             :         gnutls_datum_t unique_id;
     835             :         gnutls_datum_t serial_number;
     836             :         gnutls_x509_crt_t issuer_cert;
     837             :         gnutls_x509_privkey_t x509_issuer_privkey;
     838           1 :         time_t activation = time(NULL);
     839           1 :         time_t expiry = activation + lifetime;
     840             :         const char *error_string;
     841             :         uint8_t *reversed;
     842             :         size_t i;
     843             :         int rc;
     844             : 
     845           1 :         unique_id.size = guidblob->length;
     846           1 :         unique_id.data = talloc_memdup(mem_ctx,
     847             :                                        guidblob->data,
     848             :                                        guidblob->length);
     849           1 :         if (unique_id.data == NULL) {
     850           0 :                 return WERR_NOT_ENOUGH_MEMORY;
     851             :         }
     852             : 
     853           1 :         reversed = talloc_array(mem_ctx, uint8_t, guidblob->length);
     854           1 :         if (reversed == NULL) {
     855           0 :                 talloc_free(unique_id.data);
     856           0 :                 return WERR_NOT_ENOUGH_MEMORY;
     857             :         }
     858             : 
     859             :         /* Native AD generates certificates with serialnumber in reversed notation */
     860          17 :         for (i = 0; i < guidblob->length; i++) {
     861          16 :                 uint8_t *uncrypt = guidblob->data;
     862          16 :                 reversed[i] = uncrypt[guidblob->length - i - 1];
     863             :         }
     864           1 :         serial_number.size = guidblob->length;
     865           1 :         serial_number.data = reversed;
     866             : 
     867             :         /* Create certificate to sign */
     868           1 :         rc = gnutls_x509_crt_init(&issuer_cert);
     869           1 :         if (rc != GNUTLS_E_SUCCESS) {
     870           0 :                 DBG_ERR("gnutls_x509_crt_init failed - %s\n",
     871             :                         gnutls_strerror(rc));
     872           0 :                 return WERR_NOT_ENOUGH_MEMORY;
     873             :         }
     874             : 
     875           1 :         rc = gnutls_x509_crt_set_dn(issuer_cert, dn, &error_string);
     876           1 :         if (rc != GNUTLS_E_SUCCESS) {
     877           0 :                 DBG_ERR("gnutls_x509_crt_set_dn failed - %s (%s)\n",
     878             :                         gnutls_strerror(rc),
     879             :                         error_string);
     880           0 :                 gnutls_x509_crt_deinit(issuer_cert);
     881           0 :                 return WERR_INVALID_PARAMETER;
     882             :         }
     883             : 
     884           1 :         rc = gnutls_x509_crt_set_issuer_dn(issuer_cert, dn, &error_string);
     885           1 :         if (rc != GNUTLS_E_SUCCESS) {
     886           0 :                 DBG_ERR("gnutls_x509_crt_set_issuer_dn failed - %s (%s)\n",
     887             :                         gnutls_strerror(rc),
     888             :                         error_string);
     889           0 :                 gnutls_x509_crt_deinit(issuer_cert);
     890           0 :                 return WERR_INVALID_PARAMETER;
     891             :         }
     892             : 
     893             :         /* Get x509 privkey for subjectPublicKeyInfo */
     894           1 :         rc = gnutls_x509_privkey_init(&x509_issuer_privkey);
     895           1 :         if (rc != GNUTLS_E_SUCCESS) {
     896           0 :                 DBG_ERR("gnutls_x509_privkey_init failed - %s\n",
     897             :                         gnutls_strerror(rc));
     898           0 :                 gnutls_x509_crt_deinit(issuer_cert);
     899           0 :                 return WERR_INVALID_PARAMETER;
     900             :         }
     901             : 
     902           1 :         rc = gnutls_privkey_export_x509(issuer_privkey,
     903             :                                         &x509_issuer_privkey);
     904           1 :         if (rc != GNUTLS_E_SUCCESS) {
     905           0 :                 DBG_ERR("gnutls_x509_privkey_init failed - %s\n",
     906             :                         gnutls_strerror(rc));
     907           0 :                 gnutls_x509_privkey_deinit(x509_issuer_privkey);
     908           0 :                 gnutls_x509_crt_deinit(issuer_cert);
     909           0 :                 return WERR_INVALID_PARAMETER;
     910             :         }
     911             : 
     912             :         /* Set subjectPublicKeyInfo */
     913           1 :         rc = gnutls_x509_crt_set_key(issuer_cert, x509_issuer_privkey);
     914           1 :         gnutls_x509_privkey_deinit(x509_issuer_privkey);
     915           1 :         if (rc != GNUTLS_E_SUCCESS) {
     916           0 :                 DBG_ERR("gnutls_x509_crt_set_pubkey failed - %s\n",
     917             :                         gnutls_strerror(rc));
     918           0 :                 gnutls_x509_crt_deinit(issuer_cert);
     919           0 :                 return WERR_INVALID_PARAMETER;
     920             :         }
     921             : 
     922           1 :         rc = gnutls_x509_crt_set_activation_time(issuer_cert, activation);
     923           1 :         if (rc != GNUTLS_E_SUCCESS) {
     924           0 :                 DBG_ERR("gnutls_x509_crt_set_activation_time failed - %s\n",
     925             :                         gnutls_strerror(rc));
     926           0 :                 gnutls_x509_crt_deinit(issuer_cert);
     927           0 :                 return WERR_INVALID_PARAMETER;
     928             :         }
     929             : 
     930           1 :         rc = gnutls_x509_crt_set_expiration_time(issuer_cert, expiry);
     931           1 :         if (rc != GNUTLS_E_SUCCESS) {
     932           0 :                 DBG_ERR("gnutls_x509_crt_set_expiration_time failed - %s\n",
     933             :                         gnutls_strerror(rc));
     934           0 :                 gnutls_x509_crt_deinit(issuer_cert);
     935           0 :                 return WERR_INVALID_PARAMETER;
     936             :         }
     937             : 
     938           1 :         rc = gnutls_x509_crt_set_version(issuer_cert, 3);
     939           1 :         if (rc != GNUTLS_E_SUCCESS) {
     940           0 :                 DBG_ERR("gnutls_x509_crt_set_version failed - %s\n",
     941             :                         gnutls_strerror(rc));
     942           0 :                 gnutls_x509_crt_deinit(issuer_cert);
     943           0 :                 return WERR_INVALID_PARAMETER;
     944             :         }
     945             : 
     946           2 :         rc = gnutls_x509_crt_set_subject_unique_id(issuer_cert,
     947           1 :                                                    unique_id.data,
     948           1 :                                                    unique_id.size);
     949           1 :         if (rc != GNUTLS_E_SUCCESS) {
     950           0 :                 DBG_ERR("gnutls_x509_crt_set_subject_key_id failed - %s\n",
     951             :                         gnutls_strerror(rc));
     952           0 :                 gnutls_x509_crt_deinit(issuer_cert);
     953           0 :                 return WERR_INVALID_PARAMETER;
     954             :         }
     955             : 
     956           2 :         rc = gnutls_x509_crt_set_issuer_unique_id(issuer_cert,
     957           1 :                                                   unique_id.data,
     958           1 :                                                   unique_id.size);
     959           1 :         if (rc != GNUTLS_E_SUCCESS) {
     960           0 :                 DBG_ERR("gnutls_x509_crt_set_issuer_unique_id failed - %s\n",
     961             :                         gnutls_strerror(rc));
     962           0 :                 gnutls_x509_crt_deinit(issuer_cert);
     963           0 :                 return WERR_INVALID_PARAMETER;
     964             :         }
     965             : 
     966           2 :         rc = gnutls_x509_crt_set_serial(issuer_cert,
     967           1 :                                         serial_number.data,
     968           1 :                                         serial_number.size);
     969           1 :         if (rc != GNUTLS_E_SUCCESS) {
     970           0 :                 DBG_ERR("gnutls_x509_crt_set_serial failed - %s\n",
     971             :                         gnutls_strerror(rc));
     972           0 :                 gnutls_x509_crt_deinit(issuer_cert);
     973           0 :                 return WERR_INVALID_PARAMETER;
     974             :         }
     975             : 
     976           1 :         rc = gnutls_x509_crt_privkey_sign(issuer_cert,
     977             :                                           issuer_cert,
     978             :                                           issuer_privkey,
     979             :                                           GNUTLS_DIG_SHA1,
     980             :                                           0);
     981           1 :         if (rc != GNUTLS_E_SUCCESS) {
     982           0 :                 DBG_ERR("gnutls_x509_crt_privkey_sign failed - %s\n",
     983             :                         gnutls_strerror(rc));
     984           0 :                 return WERR_INVALID_PARAMETER;
     985             :         }
     986             : 
     987           1 :         *certificate = issuer_cert;
     988             : 
     989           1 :         return WERR_OK;
     990             : }
     991             : 
     992             : /* Return an error when we fail to generate a certificate */
     993           1 : static WERROR generate_bkrp_cert(TALLOC_CTX *mem_ctx,
     994             :                                  struct dcesrv_call_state *dce_call,
     995             :                                  struct ldb_context *ldb_ctx,
     996             :                                  const char *dn)
     997             : {
     998             :         WERROR werr;
     999           1 :         gnutls_privkey_t issuer_privkey = NULL;
    1000           1 :         gnutls_x509_crt_t cert = NULL;
    1001             :         gnutls_datum_t cert_blob;
    1002             :         gnutls_datum_t m, e, d, p, q, u, e1, e2;
    1003             :         DATA_BLOB blob;
    1004             :         DATA_BLOB blobkeypair;
    1005             :         DATA_BLOB *tmp;
    1006           1 :         bool ok = true;
    1007           1 :         struct GUID guid = GUID_random();
    1008             :         NTSTATUS status;
    1009             :         char *secret_name;
    1010             :         struct bkrp_exported_RSA_key_pair keypair;
    1011             :         enum ndr_err_code ndr_err;
    1012           1 :         time_t nb_seconds_validity = 3600 * 24 * 365;
    1013             :         int rc;
    1014             : 
    1015           1 :         DEBUG(6, ("Trying to generate a certificate\n"));
    1016           1 :         werr = create_privkey_rsa(&issuer_privkey);
    1017           1 :         if (!W_ERROR_IS_OK(werr)) {
    1018           0 :                 return werr;
    1019             :         }
    1020             : 
    1021           1 :         status = GUID_to_ndr_blob(&guid, mem_ctx, &blob);
    1022           1 :         if (!NT_STATUS_IS_OK(status)) {
    1023           0 :                 gnutls_privkey_deinit(issuer_privkey);
    1024           0 :                 return WERR_INVALID_DATA;
    1025             :         }
    1026             : 
    1027           1 :         werr = self_sign_cert(mem_ctx,
    1028             :                               nb_seconds_validity,
    1029             :                               dn,
    1030             :                               issuer_privkey,
    1031             :                               &cert,
    1032             :                               &blob);
    1033           1 :         if (!W_ERROR_IS_OK(werr)) {
    1034           0 :                 gnutls_privkey_deinit(issuer_privkey);
    1035           0 :                 return WERR_INVALID_DATA;
    1036             :         }
    1037             : 
    1038           1 :         rc = gnutls_x509_crt_export2(cert, GNUTLS_X509_FMT_DER, &cert_blob);
    1039           1 :         if (rc != GNUTLS_E_SUCCESS) {
    1040           0 :                 DBG_ERR("gnutls_x509_crt_export2 failed - %s\n",
    1041             :                         gnutls_strerror(rc));
    1042           0 :                 gnutls_privkey_deinit(issuer_privkey);
    1043           0 :                 gnutls_x509_crt_deinit(cert);
    1044           0 :                 return WERR_INVALID_DATA;
    1045             :         }
    1046             : 
    1047           1 :         keypair.cert.length = cert_blob.size;
    1048           1 :         keypair.cert.data = talloc_memdup(mem_ctx, cert_blob.data, cert_blob.size);
    1049           1 :         gnutls_x509_crt_deinit(cert);
    1050           1 :         gnutls_free(cert_blob.data);
    1051           1 :         if (keypair.cert.data == NULL) {
    1052           0 :                 gnutls_privkey_deinit(issuer_privkey);
    1053           0 :                 return WERR_NOT_ENOUGH_MEMORY;
    1054             :         }
    1055             : 
    1056           1 :         rc = gnutls_privkey_export_rsa_raw(issuer_privkey,
    1057             :                                            &m,
    1058             :                                            &e,
    1059             :                                            &d,
    1060             :                                            &p,
    1061             :                                            &q,
    1062             :                                            &u,
    1063             :                                            &e1,
    1064             :                                            &e2);
    1065           1 :         if (rc != GNUTLS_E_SUCCESS) {
    1066           0 :                 gnutls_privkey_deinit(issuer_privkey);
    1067           0 :                 return WERR_INVALID_DATA;
    1068             :         }
    1069             : 
    1070             :         /*
    1071             :          * Heimdal's bignum are big endian and the
    1072             :          * structure expect it to be in little endian
    1073             :          * so we reverse the buffer to make it work
    1074             :          */
    1075           1 :         tmp = reverse_and_get_blob(mem_ctx, &e);
    1076           1 :         if (tmp == NULL) {
    1077           0 :                 ok = false;
    1078             :         } else {
    1079           1 :                 SMB_ASSERT(tmp->length <= 4);
    1080           1 :                 keypair.public_exponent = *tmp;
    1081             :         }
    1082             : 
    1083           1 :         tmp = reverse_and_get_blob(mem_ctx, &d);
    1084           1 :         if (tmp == NULL) {
    1085           0 :                 ok = false;
    1086             :         } else {
    1087           1 :                 keypair.private_exponent = *tmp;
    1088             :         }
    1089             : 
    1090           1 :         tmp = reverse_and_get_blob(mem_ctx, &m);
    1091           1 :         if (tmp == NULL) {
    1092           0 :                 ok = false;
    1093             :         } else {
    1094           1 :                 keypair.modulus = *tmp;
    1095             :         }
    1096             : 
    1097           1 :         tmp = reverse_and_get_blob(mem_ctx, &p);
    1098           1 :         if (tmp == NULL) {
    1099           0 :                 ok = false;
    1100             :         } else {
    1101           1 :                 keypair.prime1 = *tmp;
    1102             :         }
    1103             : 
    1104           1 :         tmp = reverse_and_get_blob(mem_ctx, &q);
    1105           1 :         if (tmp == NULL) {
    1106           0 :                 ok = false;
    1107             :         } else {
    1108           1 :                 keypair.prime2 = *tmp;
    1109             :         }
    1110             : 
    1111           1 :         tmp = reverse_and_get_blob(mem_ctx, &e1);
    1112           1 :         if (tmp == NULL) {
    1113           0 :                 ok = false;
    1114             :         } else {
    1115           1 :                 keypair.exponent1 = *tmp;
    1116             :         }
    1117             : 
    1118           1 :         tmp = reverse_and_get_blob(mem_ctx, &e2);
    1119           1 :         if (tmp == NULL) {
    1120           0 :                 ok = false;
    1121             :         } else {
    1122           1 :                 keypair.exponent2 = *tmp;
    1123             :         }
    1124             : 
    1125           1 :         tmp = reverse_and_get_blob(mem_ctx, &u);
    1126           1 :         if (tmp == NULL) {
    1127           0 :                 ok = false;
    1128             :         } else {
    1129           1 :                 keypair.coefficient = *tmp;
    1130             :         }
    1131             : 
    1132             :         /* One of the keypair allocation was wrong */
    1133           1 :         if (ok == false) {
    1134           0 :                 gnutls_privkey_deinit(issuer_privkey);
    1135           0 :                 return WERR_INVALID_DATA;
    1136             :         }
    1137             : 
    1138           1 :         keypair.certificate_len = keypair.cert.length;
    1139           1 :         ndr_err = ndr_push_struct_blob(&blobkeypair,
    1140             :                                        mem_ctx,
    1141             :                                        &keypair,
    1142             :                                        (ndr_push_flags_fn_t)ndr_push_bkrp_exported_RSA_key_pair);
    1143           1 :         gnutls_privkey_deinit(issuer_privkey);
    1144           1 :         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
    1145           0 :                 return WERR_INVALID_DATA;
    1146             :         }
    1147             : 
    1148           1 :         secret_name = talloc_asprintf(mem_ctx, "BCKUPKEY_%s", GUID_string(mem_ctx, &guid));
    1149           1 :         if (secret_name == NULL) {
    1150           0 :                 return WERR_OUTOFMEMORY;
    1151             :         }
    1152             : 
    1153           1 :         status = set_lsa_secret(mem_ctx, ldb_ctx, secret_name, &blobkeypair);
    1154           1 :         if (!NT_STATUS_IS_OK(status)) {
    1155           0 :                 DEBUG(2, ("Failed to save the secret %s\n", secret_name));
    1156             :         }
    1157           1 :         talloc_free(secret_name);
    1158             : 
    1159           1 :         GUID_to_ndr_blob(&guid, mem_ctx, &blob);
    1160           1 :         status = set_lsa_secret(mem_ctx, ldb_ctx, "BCKUPKEY_PREFERRED", &blob);
    1161           1 :         if (!NT_STATUS_IS_OK(status)) {
    1162           0 :                 DEBUG(2, ("Failed to save the secret BCKUPKEY_PREFERRED\n"));
    1163             :         }
    1164             : 
    1165           1 :         return WERR_OK;
    1166             : }
    1167             : 
    1168          13 : static WERROR bkrp_retrieve_client_wrap_key(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
    1169             :                                             struct bkrp_BackupKey *r, struct ldb_context *ldb_ctx)
    1170             : {
    1171             :         struct GUID guid;
    1172             :         char *guid_string;
    1173             :         DATA_BLOB lsa_secret;
    1174             :         enum ndr_err_code ndr_err;
    1175             :         NTSTATUS status;
    1176             : 
    1177             :         /*
    1178             :          * here we basicaly need to return our certificate
    1179             :          * search for lsa secret BCKUPKEY_PREFERRED first
    1180             :          */
    1181             : 
    1182          13 :         status = get_lsa_secret(mem_ctx,
    1183             :                                 ldb_ctx,
    1184             :                                 "BCKUPKEY_PREFERRED",
    1185             :                                 &lsa_secret);
    1186          13 :         if (NT_STATUS_EQUAL(status, NT_STATUS_RESOURCE_NAME_NOT_FOUND)) {
    1187             :                 /* Ok we can be in this case if there was no certs */
    1188           1 :                 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
    1189           1 :                 char *dn = talloc_asprintf(mem_ctx, "CN=%s",
    1190             :                                            lpcfg_realm(lp_ctx));
    1191             : 
    1192           1 :                 WERROR werr =  generate_bkrp_cert(mem_ctx, dce_call, ldb_ctx, dn);
    1193           1 :                 if (!W_ERROR_IS_OK(werr)) {
    1194           0 :                         return WERR_INVALID_PARAMETER;
    1195             :                 }
    1196           1 :                 status = get_lsa_secret(mem_ctx,
    1197             :                                         ldb_ctx,
    1198             :                                         "BCKUPKEY_PREFERRED",
    1199             :                                         &lsa_secret);
    1200             : 
    1201           1 :                 if (!NT_STATUS_IS_OK(status)) {
    1202             :                         /* Ok we really don't manage to get this certs ...*/
    1203           0 :                         DEBUG(2, ("Unable to locate BCKUPKEY_PREFERRED after cert generation\n"));
    1204           0 :                         return WERR_FILE_NOT_FOUND;
    1205             :                 }
    1206          12 :         } else if (!NT_STATUS_IS_OK(status)) {
    1207           0 :                 return WERR_INTERNAL_ERROR;
    1208             :         }
    1209             : 
    1210          13 :         if (lsa_secret.length == 0) {
    1211           0 :                 DEBUG(1, ("No secret in BCKUPKEY_PREFERRED, are we an undetected RODC?\n"));
    1212           0 :                 return WERR_INTERNAL_ERROR;
    1213             :         } else {
    1214             :                 char *cert_secret_name;
    1215             : 
    1216          13 :                 status = GUID_from_ndr_blob(&lsa_secret, &guid);
    1217          13 :                 if (!NT_STATUS_IS_OK(status)) {
    1218           0 :                         return WERR_FILE_NOT_FOUND;
    1219             :                 }
    1220             : 
    1221          13 :                 guid_string = GUID_string(mem_ctx, &guid);
    1222          13 :                 if (guid_string == NULL) {
    1223             :                         /* We return file not found because the client
    1224             :                          * expect this error
    1225             :                          */
    1226           0 :                         return WERR_FILE_NOT_FOUND;
    1227             :                 }
    1228             : 
    1229          13 :                 cert_secret_name = talloc_asprintf(mem_ctx,
    1230             :                                                         "BCKUPKEY_%s",
    1231             :                                                         guid_string);
    1232          13 :                 status = get_lsa_secret(mem_ctx,
    1233             :                                         ldb_ctx,
    1234             :                                         cert_secret_name,
    1235             :                                         &lsa_secret);
    1236          13 :                 if (!NT_STATUS_IS_OK(status)) {
    1237           0 :                         return WERR_FILE_NOT_FOUND;
    1238             :                 }
    1239             : 
    1240          13 :                 if (lsa_secret.length != 0) {
    1241             :                         struct bkrp_exported_RSA_key_pair keypair;
    1242          13 :                         ndr_err = ndr_pull_struct_blob(&lsa_secret, mem_ctx, &keypair,
    1243             :                                         (ndr_pull_flags_fn_t)ndr_pull_bkrp_exported_RSA_key_pair);
    1244          13 :                         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
    1245           0 :                                 return WERR_FILE_NOT_FOUND;
    1246             :                         }
    1247          13 :                         *(r->out.data_out_len) = keypair.cert.length;
    1248          13 :                         *(r->out.data_out) = talloc_memdup(mem_ctx, keypair.cert.data, keypair.cert.length);
    1249          13 :                         W_ERROR_HAVE_NO_MEMORY(*(r->out.data_out));
    1250          13 :                         return WERR_OK;
    1251             :                 } else {
    1252           0 :                         DEBUG(1, ("No or broken secret called %s\n", cert_secret_name));
    1253           0 :                         return WERR_INTERNAL_ERROR;
    1254             :                 }
    1255             :         }
    1256             : 
    1257             :         return WERR_NOT_SUPPORTED;
    1258             : }
    1259             : 
    1260           1 : static WERROR generate_bkrp_server_wrap_key(TALLOC_CTX *ctx, struct ldb_context *ldb_ctx)
    1261             : {
    1262           1 :         struct GUID guid = GUID_random();
    1263             :         enum ndr_err_code ndr_err;
    1264             :         DATA_BLOB blob_wrap_key, guid_blob;
    1265             :         struct bkrp_dc_serverwrap_key wrap_key;
    1266             :         NTSTATUS status;
    1267             :         char *secret_name;
    1268           1 :         TALLOC_CTX *frame = talloc_stackframe();
    1269             : 
    1270           1 :         generate_random_buffer(wrap_key.key, sizeof(wrap_key.key));
    1271             : 
    1272           1 :         ndr_err = ndr_push_struct_blob(&blob_wrap_key, ctx, &wrap_key, (ndr_push_flags_fn_t)ndr_push_bkrp_dc_serverwrap_key);
    1273           1 :         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
    1274           0 :                 TALLOC_FREE(frame);
    1275           0 :                 return WERR_INVALID_DATA;
    1276             :         }
    1277             : 
    1278           1 :         secret_name = talloc_asprintf(frame, "BCKUPKEY_%s", GUID_string(ctx, &guid));
    1279           1 :         if (secret_name == NULL) {
    1280           0 :                 TALLOC_FREE(frame);
    1281           0 :                 return WERR_NOT_ENOUGH_MEMORY;
    1282             :         }
    1283             : 
    1284           1 :         status = set_lsa_secret(frame, ldb_ctx, secret_name, &blob_wrap_key);
    1285           1 :         if (!NT_STATUS_IS_OK(status)) {
    1286           0 :                 DEBUG(2, ("Failed to save the secret %s\n", secret_name));
    1287           0 :                 TALLOC_FREE(frame);
    1288           0 :                 return WERR_INTERNAL_ERROR;
    1289             :         }
    1290             : 
    1291           1 :         status = GUID_to_ndr_blob(&guid, frame, &guid_blob);
    1292           1 :         if (!NT_STATUS_IS_OK(status)) {
    1293           0 :                 DEBUG(2, ("Failed to save the secret %s\n", secret_name));
    1294           0 :                 TALLOC_FREE(frame);
    1295             :         }
    1296             : 
    1297           1 :         status = set_lsa_secret(frame, ldb_ctx, "BCKUPKEY_P", &guid_blob);
    1298           1 :         if (!NT_STATUS_IS_OK(status)) {
    1299           0 :                 DEBUG(2, ("Failed to save the secret %s\n", secret_name));
    1300           0 :                 TALLOC_FREE(frame);
    1301           0 :                 return WERR_INTERNAL_ERROR;
    1302             :         }
    1303             : 
    1304           1 :         TALLOC_FREE(frame);
    1305             : 
    1306           1 :         return WERR_OK;
    1307             : }
    1308             : 
    1309             : /*
    1310             :  * Find the specified decryption keys from the LSA secrets store as
    1311             :  * G$BCKUPKEY_keyGuidString.
    1312             :  */
    1313             : 
    1314          31 : static WERROR bkrp_do_retrieve_server_wrap_key(TALLOC_CTX *mem_ctx, struct ldb_context *ldb_ctx,
    1315             :                                                struct bkrp_dc_serverwrap_key *server_key,
    1316             :                                                struct GUID *guid)
    1317             : {
    1318             :         NTSTATUS status;
    1319             :         DATA_BLOB lsa_secret;
    1320             :         char *secret_name;
    1321             :         char *guid_string;
    1322             :         enum ndr_err_code ndr_err;
    1323             : 
    1324          31 :         guid_string = GUID_string(mem_ctx, guid);
    1325          31 :         if (guid_string == NULL) {
    1326             :                 /* We return file not found because the client
    1327             :                  * expect this error
    1328             :                  */
    1329           0 :                 return WERR_FILE_NOT_FOUND;
    1330             :         }
    1331             : 
    1332          31 :         secret_name = talloc_asprintf(mem_ctx, "BCKUPKEY_%s", guid_string);
    1333          31 :         if (secret_name == NULL) {
    1334           0 :                 return WERR_NOT_ENOUGH_MEMORY;
    1335             :         }
    1336             : 
    1337          31 :         status = get_lsa_secret(mem_ctx, ldb_ctx, secret_name, &lsa_secret);
    1338          31 :         if (!NT_STATUS_IS_OK(status)) {
    1339           2 :                 DEBUG(10, ("Error while fetching secret %s\n", secret_name));
    1340           2 :                 return WERR_INVALID_DATA;
    1341             :         }
    1342          29 :         if (lsa_secret.length == 0) {
    1343             :                 /* RODC case, we do not have secrets locally */
    1344           0 :                 DEBUG(1, ("Unable to fetch value for secret %s, are we an undetected RODC?\n",
    1345             :                           secret_name));
    1346           0 :                 return WERR_INTERNAL_ERROR;
    1347             :         }
    1348          29 :         ndr_err = ndr_pull_struct_blob(&lsa_secret, mem_ctx, server_key,
    1349             :                                        (ndr_pull_flags_fn_t)ndr_pull_bkrp_dc_serverwrap_key);
    1350          29 :         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
    1351           0 :                 DEBUG(2, ("Unable to parse the ndr encoded server wrap key %s\n", secret_name));
    1352           0 :                 return WERR_INVALID_DATA;
    1353             :         }
    1354             : 
    1355          29 :         return WERR_OK;
    1356             : }
    1357             : 
    1358             : /*
    1359             :  * Find the current, preferred ServerWrap Key by looking at
    1360             :  * G$BCKUPKEY_P in the LSA secrets store.
    1361             :  *
    1362             :  * Then find the current decryption keys from the LSA secrets store as
    1363             :  * G$BCKUPKEY_keyGuidString.
    1364             :  */
    1365             : 
    1366          14 : static WERROR bkrp_do_retrieve_default_server_wrap_key(TALLOC_CTX *mem_ctx,
    1367             :                                                        struct ldb_context *ldb_ctx,
    1368             :                                                        struct bkrp_dc_serverwrap_key *server_key,
    1369             :                                                        struct GUID *returned_guid)
    1370             : {
    1371             :         NTSTATUS status;
    1372             :         DATA_BLOB guid_binary;
    1373             : 
    1374          14 :         status = get_lsa_secret(mem_ctx, ldb_ctx, "BCKUPKEY_P", &guid_binary);
    1375          14 :         if (!NT_STATUS_IS_OK(status)) {
    1376           1 :                 DEBUG(10, ("Error while fetching secret BCKUPKEY_P to find current GUID\n"));
    1377           1 :                 return WERR_FILE_NOT_FOUND;
    1378          13 :         } else if (guid_binary.length == 0) {
    1379             :                 /* RODC case, we do not have secrets locally */
    1380           0 :                 DEBUG(1, ("Unable to fetch value for secret BCKUPKEY_P, are we an undetected RODC?\n"));
    1381           0 :                 return WERR_INTERNAL_ERROR;
    1382             :         }
    1383             : 
    1384          13 :         status = GUID_from_ndr_blob(&guid_binary, returned_guid);
    1385          13 :         if (!NT_STATUS_IS_OK(status)) {
    1386           0 :                 return WERR_FILE_NOT_FOUND;
    1387             :         }
    1388             : 
    1389          13 :         return bkrp_do_retrieve_server_wrap_key(mem_ctx, ldb_ctx,
    1390             :                                                 server_key, returned_guid);
    1391             : }
    1392             : 
    1393          30 : static WERROR bkrp_server_wrap_decrypt_data(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
    1394             :                                             struct bkrp_BackupKey *r ,struct ldb_context *ldb_ctx)
    1395             : {
    1396          30 :         struct auth_session_info *session_info =
    1397           0 :                 dcesrv_call_session_info(dce_call);
    1398             :         WERROR werr;
    1399             :         struct bkrp_server_side_wrapped decrypt_request;
    1400             :         DATA_BLOB sid_blob, encrypted_blob;
    1401             :         DATA_BLOB blob;
    1402             :         enum ndr_err_code ndr_err;
    1403             :         struct bkrp_dc_serverwrap_key server_key;
    1404             :         struct bkrp_rc4encryptedpayload rc4payload;
    1405             :         struct dom_sid *caller_sid;
    1406             :         uint8_t symkey[20]; /* SHA-1 hash len */
    1407             :         uint8_t mackey[20]; /* SHA-1 hash len */
    1408             :         uint8_t mac[20]; /* SHA-1 hash len */
    1409             :         gnutls_hmac_hd_t hmac_hnd;
    1410             :         gnutls_cipher_hd_t cipher_hnd;
    1411             :         gnutls_datum_t cipher_key;
    1412             :         int rc;
    1413             : 
    1414          30 :         blob.data = r->in.data_in;
    1415          30 :         blob.length = r->in.data_in_len;
    1416             : 
    1417          30 :         if (r->in.data_in_len == 0 || r->in.data_in == NULL) {
    1418           1 :                 return WERR_INVALID_PARAMETER;
    1419             :         }
    1420             : 
    1421          29 :         ndr_err = ndr_pull_struct_blob_all(&blob, mem_ctx, &decrypt_request,
    1422             :                                            (ndr_pull_flags_fn_t)ndr_pull_bkrp_server_side_wrapped);
    1423          29 :         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
    1424          10 :                 return WERR_INVALID_PARAMETER;
    1425             :         }
    1426             : 
    1427          19 :         if (decrypt_request.magic != BACKUPKEY_SERVER_WRAP_VERSION) {
    1428           1 :                 return WERR_INVALID_PARAMETER;
    1429             :         }
    1430             : 
    1431          18 :         werr = bkrp_do_retrieve_server_wrap_key(mem_ctx, ldb_ctx, &server_key,
    1432             :                                                 &decrypt_request.guid);
    1433          18 :         if (!W_ERROR_IS_OK(werr)) {
    1434           2 :                 return werr;
    1435             :         }
    1436             : 
    1437          16 :         dump_data_pw("server_key: \n", server_key.key, sizeof(server_key.key));
    1438             : 
    1439          16 :         dump_data_pw("r2: \n", decrypt_request.r2, sizeof(decrypt_request.r2));
    1440             : 
    1441             :         /*
    1442             :          * This is *not* the leading 64 bytes, as indicated in MS-BKRP 3.1.4.1.1
    1443             :          * BACKUPKEY_BACKUP_GUID, it really is the whole key
    1444             :          */
    1445             : 
    1446          16 :         rc = gnutls_hmac_init(&hmac_hnd,
    1447             :                               GNUTLS_MAC_SHA1,
    1448             :                               server_key.key,
    1449             :                               sizeof(server_key.key));
    1450          16 :         if (rc != GNUTLS_E_SUCCESS) {
    1451           0 :                 return gnutls_error_to_werror(rc, WERR_INTERNAL_ERROR);
    1452             :         }
    1453             : 
    1454          16 :         rc = gnutls_hmac(hmac_hnd,
    1455             :                     decrypt_request.r2,
    1456             :                     sizeof(decrypt_request.r2));
    1457             : 
    1458          16 :         if (rc != GNUTLS_E_SUCCESS) {
    1459           0 :                 return gnutls_error_to_werror(rc, WERR_INTERNAL_ERROR);
    1460             :         }
    1461             : 
    1462          16 :         gnutls_hmac_output(hmac_hnd, symkey);
    1463          16 :         dump_data_pw("symkey: \n", symkey, sizeof(symkey));
    1464             : 
    1465             :         /* rc4 decrypt sid and secret using sym key */
    1466          16 :         cipher_key.data = symkey;
    1467          16 :         cipher_key.size = sizeof(symkey);
    1468             : 
    1469          16 :         encrypted_blob = data_blob_const(decrypt_request.rc4encryptedpayload,
    1470          16 :                                          decrypt_request.ciphertext_length);
    1471             : 
    1472          16 :         rc = gnutls_cipher_init(&cipher_hnd,
    1473             :                                 GNUTLS_CIPHER_ARCFOUR_128,
    1474             :                                 &cipher_key,
    1475             :                                 NULL);
    1476          16 :         if (rc != GNUTLS_E_SUCCESS) {
    1477           0 :                 return gnutls_error_to_werror(rc, WERR_INTERNAL_ERROR);
    1478             :         }
    1479          48 :         rc = gnutls_cipher_encrypt2(cipher_hnd,
    1480          16 :                                     encrypted_blob.data,
    1481             :                                     encrypted_blob.length,
    1482          16 :                                     encrypted_blob.data,
    1483             :                                     encrypted_blob.length);
    1484          16 :         gnutls_cipher_deinit(cipher_hnd);
    1485          16 :         if (rc != GNUTLS_E_SUCCESS) {
    1486           0 :                 return gnutls_error_to_werror(rc, WERR_INTERNAL_ERROR);
    1487             :         }
    1488             : 
    1489          16 :         ndr_err = ndr_pull_struct_blob_all(&encrypted_blob, mem_ctx, &rc4payload,
    1490             :                                            (ndr_pull_flags_fn_t)ndr_pull_bkrp_rc4encryptedpayload);
    1491          16 :         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
    1492           4 :                 return WERR_INVALID_PARAMETER;
    1493             :         }
    1494             : 
    1495          12 :         if (decrypt_request.payload_length != rc4payload.secret_data.length) {
    1496           6 :                 return WERR_INVALID_PARAMETER;
    1497             :         }
    1498             : 
    1499           6 :         dump_data_pw("r3: \n", rc4payload.r3, sizeof(rc4payload.r3));
    1500             : 
    1501             :         /*
    1502             :          * This is *not* the leading 64 bytes, as indicated in MS-BKRP 3.1.4.1.1
    1503             :          * BACKUPKEY_BACKUP_GUID, it really is the whole key
    1504             :          */
    1505           6 :         rc = gnutls_hmac(hmac_hnd,
    1506             :                          rc4payload.r3,
    1507             :                          sizeof(rc4payload.r3));
    1508           6 :         if (rc != GNUTLS_E_SUCCESS) {
    1509           0 :                 return gnutls_error_to_werror(rc, WERR_INTERNAL_ERROR);
    1510             :         }
    1511             : 
    1512           6 :         gnutls_hmac_deinit(hmac_hnd, mackey);
    1513             : 
    1514           6 :         dump_data_pw("mackey: \n", mackey, sizeof(mackey));
    1515             : 
    1516           6 :         ndr_err = ndr_push_struct_blob(&sid_blob, mem_ctx, &rc4payload.sid,
    1517             :                                        (ndr_push_flags_fn_t)ndr_push_dom_sid);
    1518           6 :         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
    1519           0 :                 return WERR_INTERNAL_ERROR;
    1520             :         }
    1521             : 
    1522           6 :         rc = gnutls_hmac_init(&hmac_hnd,
    1523             :                               GNUTLS_MAC_SHA1,
    1524             :                               mackey,
    1525             :                               sizeof(mackey));
    1526           6 :         if (rc != GNUTLS_E_SUCCESS) {
    1527           0 :                 return gnutls_error_to_werror(rc, WERR_INTERNAL_ERROR);
    1528             :         }
    1529             : 
    1530             :         /* SID field */
    1531          12 :         rc = gnutls_hmac(hmac_hnd,
    1532           6 :                          sid_blob.data,
    1533             :                          sid_blob.length);
    1534           6 :         if (rc != GNUTLS_E_SUCCESS) {
    1535           0 :                 return gnutls_error_to_werror(rc, WERR_INTERNAL_ERROR);
    1536             :         }
    1537             : 
    1538             :         /* Secret field */
    1539          12 :         rc = gnutls_hmac(hmac_hnd,
    1540           6 :                          rc4payload.secret_data.data,
    1541             :                          rc4payload.secret_data.length);
    1542           6 :         if (rc != GNUTLS_E_SUCCESS) {
    1543           0 :                 return gnutls_error_to_werror(rc, WERR_INTERNAL_ERROR);
    1544             :         }
    1545             : 
    1546           6 :         gnutls_hmac_deinit(hmac_hnd, mac);
    1547           6 :         dump_data_pw("mac: \n", mac, sizeof(mac));
    1548           6 :         dump_data_pw("rc4payload.mac: \n", rc4payload.mac, sizeof(rc4payload.mac));
    1549             : 
    1550           6 :         if (memcmp(mac, rc4payload.mac, sizeof(mac)) != 0) {
    1551           0 :                 return WERR_INVALID_ACCESS;
    1552             :         }
    1553             : 
    1554           6 :         caller_sid = &session_info->security_token->sids[PRIMARY_USER_SID_INDEX];
    1555             : 
    1556           6 :         if (!dom_sid_equal(&rc4payload.sid, caller_sid)) {
    1557           2 :                 return WERR_INVALID_ACCESS;
    1558             :         }
    1559             : 
    1560           4 :         *(r->out.data_out) = rc4payload.secret_data.data;
    1561           4 :         *(r->out.data_out_len) = rc4payload.secret_data.length;
    1562             : 
    1563           4 :         return WERR_OK;
    1564             : }
    1565             : 
    1566             : /*
    1567             :  * For BACKUPKEY_RESTORE_GUID we need to check the first 4 bytes to
    1568             :  * determine what type of restore is wanted.
    1569             :  *
    1570             :  * See MS-BKRP 3.1.4.1.4 BACKUPKEY_RESTORE_GUID point 1.
    1571             :  */
    1572             : 
    1573          27 : static WERROR bkrp_generic_decrypt_data(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
    1574             :                                         struct bkrp_BackupKey *r, struct ldb_context *ldb_ctx)
    1575             : {
    1576          27 :         if (r->in.data_in_len < 4 || r->in.data_in == NULL) {
    1577           3 :                 return WERR_INVALID_PARAMETER;
    1578             :         }
    1579             : 
    1580          24 :         if (IVAL(r->in.data_in, 0) == BACKUPKEY_SERVER_WRAP_VERSION) {
    1581          14 :                 return bkrp_server_wrap_decrypt_data(dce_call, mem_ctx, r, ldb_ctx);
    1582             :         }
    1583             : 
    1584          10 :         return bkrp_client_wrap_decrypt_data(dce_call, mem_ctx, r, ldb_ctx);
    1585             : }
    1586             : 
    1587             : /*
    1588             :  * We have some data, such as saved website or IMAP passwords that the
    1589             :  * client would like to put into the profile on-disk.  This needs to
    1590             :  * be encrypted.  This version gives the server the data over the
    1591             :  * network (protected only by the negotiated transport encryption),
    1592             :  * and asks that it be encrypted and returned for long-term storage.
    1593             :  *
    1594             :  * The data is NOT stored in the LSA, but a key to encrypt the data
    1595             :  * will be stored.  There is only one active encryption key per domain,
    1596             :  * it is pointed at with G$BCKUPKEY_P in the LSA secrets store.
    1597             :  *
    1598             :  * The potentially multiple valid decryptiong keys (and the encryption
    1599             :  * key) are in turn stored in the LSA secrets store as
    1600             :  * G$BCKUPKEY_keyGuidString.
    1601             :  *
    1602             :  */
    1603             : 
    1604          13 : static WERROR bkrp_server_wrap_encrypt_data(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
    1605             :                                             struct bkrp_BackupKey *r ,struct ldb_context *ldb_ctx)
    1606             : {
    1607          13 :         struct auth_session_info *session_info =
    1608           0 :                 dcesrv_call_session_info(dce_call);
    1609             :         DATA_BLOB sid_blob, encrypted_blob, server_wrapped_blob;
    1610             :         WERROR werr;
    1611             :         struct dom_sid *caller_sid;
    1612             :         uint8_t symkey[20]; /* SHA-1 hash len */
    1613             :         uint8_t mackey[20]; /* SHA-1 hash len */
    1614             :         struct bkrp_rc4encryptedpayload rc4payload;
    1615             :         gnutls_hmac_hd_t hmac_hnd;
    1616             :         struct bkrp_dc_serverwrap_key server_key;
    1617             :         enum ndr_err_code ndr_err;
    1618             :         struct bkrp_server_side_wrapped server_side_wrapped;
    1619             :         struct GUID guid;
    1620             :         gnutls_cipher_hd_t cipher_hnd;
    1621             :         gnutls_datum_t cipher_key;
    1622             :         int rc;
    1623             : 
    1624          13 :         if (r->in.data_in_len == 0 || r->in.data_in == NULL) {
    1625           0 :                 return WERR_INVALID_PARAMETER;
    1626             :         }
    1627             : 
    1628          13 :         werr = bkrp_do_retrieve_default_server_wrap_key(mem_ctx,
    1629             :                                                         ldb_ctx, &server_key,
    1630             :                                                         &guid);
    1631             : 
    1632          13 :         if (!W_ERROR_IS_OK(werr)) {
    1633           1 :                 if (W_ERROR_EQUAL(werr, WERR_FILE_NOT_FOUND)) {
    1634             :                         /* Generate the server wrap key since one wasn't found */
    1635           1 :                         werr =  generate_bkrp_server_wrap_key(mem_ctx,
    1636             :                                                               ldb_ctx);
    1637           1 :                         if (!W_ERROR_IS_OK(werr)) {
    1638           0 :                                 return WERR_INVALID_PARAMETER;
    1639             :                         }
    1640           1 :                         werr = bkrp_do_retrieve_default_server_wrap_key(mem_ctx,
    1641             :                                                                         ldb_ctx,
    1642             :                                                                         &server_key,
    1643             :                                                                         &guid);
    1644             : 
    1645           1 :                         if (W_ERROR_EQUAL(werr, WERR_FILE_NOT_FOUND)) {
    1646             :                                 /* Ok we really don't manage to get this secret ...*/
    1647           0 :                                 return WERR_FILE_NOT_FOUND;
    1648             :                         }
    1649             :                 } else {
    1650             :                         /* In theory we should NEVER reach this point as it
    1651             :                            should only appear in a rodc server */
    1652             :                         /* we do not have the real secret attribute */
    1653           0 :                         return WERR_INVALID_PARAMETER;
    1654             :                 }
    1655             :         }
    1656             : 
    1657          13 :         caller_sid = &session_info->security_token->sids[PRIMARY_USER_SID_INDEX];
    1658             : 
    1659          13 :         dump_data_pw("server_key: \n", server_key.key, sizeof(server_key.key));
    1660             : 
    1661             :         /*
    1662             :          * This is the key derivation step, so that the HMAC and RC4
    1663             :          * operations over the user-supplied data are not able to
    1664             :          * disclose the master key.  By using random data, the symkey
    1665             :          * and mackey values are unique for this operation, and
    1666             :          * discovering these (by reversing the RC4 over the
    1667             :          * attacker-controlled data) does not return something able to
    1668             :          * be used to decyrpt the encrypted data of other users
    1669             :          */
    1670          13 :         generate_random_buffer(server_side_wrapped.r2, sizeof(server_side_wrapped.r2));
    1671             : 
    1672          13 :         dump_data_pw("r2: \n", server_side_wrapped.r2, sizeof(server_side_wrapped.r2));
    1673             : 
    1674          13 :         generate_random_buffer(rc4payload.r3, sizeof(rc4payload.r3));
    1675             : 
    1676          13 :         dump_data_pw("r3: \n", rc4payload.r3, sizeof(rc4payload.r3));
    1677             : 
    1678             : 
    1679             :         /*
    1680             :          * This is *not* the leading 64 bytes, as indicated in MS-BKRP 3.1.4.1.1
    1681             :          * BACKUPKEY_BACKUP_GUID, it really is the whole key
    1682             :          */
    1683          13 :         rc = gnutls_hmac_init(&hmac_hnd,
    1684             :                               GNUTLS_MAC_SHA1,
    1685             :                               server_key.key,
    1686             :                               sizeof(server_key.key));
    1687          13 :         if (rc != GNUTLS_E_SUCCESS) {
    1688           0 :                 return gnutls_error_to_werror(rc, WERR_INTERNAL_ERROR);
    1689             :         }
    1690             : 
    1691          13 :         rc = gnutls_hmac(hmac_hnd,
    1692             :                          server_side_wrapped.r2,
    1693             :                          sizeof(server_side_wrapped.r2));
    1694          13 :         if (rc != GNUTLS_E_SUCCESS) {
    1695           0 :                 return gnutls_error_to_werror(rc, WERR_INTERNAL_ERROR);
    1696             :         }
    1697          13 :         gnutls_hmac_output(hmac_hnd, symkey);
    1698          13 :         dump_data_pw("symkey: \n", symkey, sizeof(symkey));
    1699             : 
    1700             :         /*
    1701             :          * This is *not* the leading 64 bytes, as indicated in MS-BKRP 3.1.4.1.1
    1702             :          * BACKUPKEY_BACKUP_GUID, it really is the whole key
    1703             :          */
    1704          13 :         rc = gnutls_hmac(hmac_hnd,
    1705             :                          rc4payload.r3,
    1706             :                          sizeof(rc4payload.r3));
    1707          13 :         if (rc != GNUTLS_E_SUCCESS) {
    1708           0 :                 return gnutls_error_to_werror(rc, WERR_INTERNAL_ERROR);
    1709             :         }
    1710          13 :         gnutls_hmac_deinit(hmac_hnd, mackey);
    1711          13 :         dump_data_pw("mackey: \n", mackey, sizeof(mackey));
    1712             : 
    1713          13 :         ndr_err = ndr_push_struct_blob(&sid_blob, mem_ctx, caller_sid,
    1714             :                                        (ndr_push_flags_fn_t)ndr_push_dom_sid);
    1715          13 :         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
    1716           0 :                 return WERR_INTERNAL_ERROR;
    1717             :         }
    1718             : 
    1719          13 :         rc4payload.secret_data.data = r->in.data_in;
    1720          13 :         rc4payload.secret_data.length = r->in.data_in_len;
    1721             : 
    1722          13 :         rc = gnutls_hmac_init(&hmac_hnd,
    1723             :                               GNUTLS_MAC_SHA1,
    1724             :                               mackey,
    1725             :                               sizeof(mackey));
    1726          13 :         if (rc != GNUTLS_E_SUCCESS) {
    1727           0 :                 return gnutls_error_to_werror(rc, WERR_INTERNAL_ERROR);
    1728             :         }
    1729             : 
    1730             :         /* SID field */
    1731          26 :         rc = gnutls_hmac(hmac_hnd,
    1732          13 :                          sid_blob.data,
    1733             :                          sid_blob.length);
    1734          13 :         if (rc != GNUTLS_E_SUCCESS) {
    1735           0 :                 return gnutls_error_to_werror(rc, WERR_INTERNAL_ERROR);
    1736             :         }
    1737             : 
    1738             :         /* Secret field */
    1739          26 :         rc = gnutls_hmac(hmac_hnd,
    1740          13 :                          rc4payload.secret_data.data,
    1741             :                          rc4payload.secret_data.length);
    1742          13 :         if (rc != GNUTLS_E_SUCCESS) {
    1743           0 :                 return gnutls_error_to_werror(rc, WERR_INTERNAL_ERROR);
    1744             :         }
    1745             : 
    1746          13 :         gnutls_hmac_deinit(hmac_hnd, rc4payload.mac);
    1747          13 :         dump_data_pw("rc4payload.mac: \n", rc4payload.mac, sizeof(rc4payload.mac));
    1748             : 
    1749          13 :         rc4payload.sid = *caller_sid;
    1750             : 
    1751          13 :         ndr_err = ndr_push_struct_blob(&encrypted_blob, mem_ctx, &rc4payload,
    1752             :                                        (ndr_push_flags_fn_t)ndr_push_bkrp_rc4encryptedpayload);
    1753          13 :         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
    1754           0 :                 return WERR_INTERNAL_ERROR;
    1755             :         }
    1756             : 
    1757             :         /* rc4 encrypt sid and secret using sym key */
    1758          13 :         cipher_key.data = symkey;
    1759          13 :         cipher_key.size = sizeof(symkey);
    1760             : 
    1761          13 :         rc = gnutls_cipher_init(&cipher_hnd,
    1762             :                                 GNUTLS_CIPHER_ARCFOUR_128,
    1763             :                                 &cipher_key,
    1764             :                                 NULL);
    1765          13 :         if (rc != GNUTLS_E_SUCCESS) {
    1766           0 :                 return gnutls_error_to_werror(rc, WERR_INTERNAL_ERROR);
    1767             :         }
    1768          39 :         rc = gnutls_cipher_encrypt2(cipher_hnd,
    1769          13 :                                     encrypted_blob.data,
    1770             :                                     encrypted_blob.length,
    1771          13 :                                     encrypted_blob.data,
    1772             :                                     encrypted_blob.length);
    1773          13 :         gnutls_cipher_deinit(cipher_hnd);
    1774          13 :         if (rc != GNUTLS_E_SUCCESS) {
    1775           0 :                 return gnutls_error_to_werror(rc, WERR_INTERNAL_ERROR);
    1776             :         }
    1777             : 
    1778             :         /* create server wrap structure */
    1779             : 
    1780          13 :         server_side_wrapped.payload_length = rc4payload.secret_data.length;
    1781          13 :         server_side_wrapped.ciphertext_length = encrypted_blob.length;
    1782          13 :         server_side_wrapped.guid = guid;
    1783          13 :         server_side_wrapped.rc4encryptedpayload = encrypted_blob.data;
    1784             : 
    1785          13 :         ndr_err = ndr_push_struct_blob(&server_wrapped_blob, mem_ctx, &server_side_wrapped,
    1786             :                                        (ndr_push_flags_fn_t)ndr_push_bkrp_server_side_wrapped);
    1787          13 :         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
    1788           0 :                 return WERR_INTERNAL_ERROR;
    1789             :         }
    1790             : 
    1791          13 :         *(r->out.data_out) = server_wrapped_blob.data;
    1792          13 :         *(r->out.data_out_len) = server_wrapped_blob.length;
    1793             : 
    1794          13 :         return WERR_OK;
    1795             : }
    1796             : 
    1797          69 : static WERROR dcesrv_bkrp_BackupKey(struct dcesrv_call_state *dce_call,
    1798             :                                     TALLOC_CTX *mem_ctx, struct bkrp_BackupKey *r)
    1799             : {
    1800          69 :         WERROR error = WERR_INVALID_PARAMETER;
    1801             :         struct ldb_context *ldb_ctx;
    1802             :         bool is_rodc;
    1803          69 :         const char *addr = "unknown";
    1804             :         /* At which level we start to add more debug of what is done in the protocol */
    1805          69 :         const int debuglevel = 4;
    1806             : 
    1807          69 :         if (DEBUGLVL(debuglevel)) {
    1808             :                 const struct tsocket_address *remote_address;
    1809           0 :                 remote_address = dcesrv_connection_get_remote_address(dce_call->conn);
    1810           0 :                 if (tsocket_address_is_inet(remote_address, "ip")) {
    1811           0 :                         addr = tsocket_address_inet_addr_string(remote_address, mem_ctx);
    1812           0 :                         W_ERROR_HAVE_NO_MEMORY(addr);
    1813             :                 }
    1814             :         }
    1815             : 
    1816          69 :         if (lpcfg_server_role(dce_call->conn->dce_ctx->lp_ctx) != ROLE_ACTIVE_DIRECTORY_DC) {
    1817           0 :                 return WERR_NOT_SUPPORTED;
    1818             :         }
    1819             : 
    1820             :         /*
    1821             :          * Save the current remote session details so they can used by the
    1822             :          * audit logging module. This allows the audit logging to report the
    1823             :          * remote users details, rather than the system users details.
    1824             :          */
    1825          69 :         ldb_ctx = dcesrv_samdb_connect_as_system(mem_ctx, dce_call);
    1826             : 
    1827          69 :         if (samdb_rodc(ldb_ctx, &is_rodc) != LDB_SUCCESS) {
    1828           0 :                 talloc_unlink(mem_ctx, ldb_ctx);
    1829           0 :                 return WERR_INVALID_PARAMETER;
    1830             :         }
    1831             : 
    1832          69 :         if (!is_rodc) {
    1833          69 :                 if(strncasecmp(GUID_string(mem_ctx, r->in.guidActionAgent),
    1834             :                         BACKUPKEY_RESTORE_GUID, strlen(BACKUPKEY_RESTORE_GUID)) == 0) {
    1835          27 :                         DEBUG(debuglevel, ("Client %s requested to decrypt a wrapped secret\n", addr));
    1836          27 :                         error = bkrp_generic_decrypt_data(dce_call, mem_ctx, r, ldb_ctx);
    1837             :                 }
    1838             : 
    1839          69 :                 if (strncasecmp(GUID_string(mem_ctx, r->in.guidActionAgent),
    1840             :                         BACKUPKEY_RETRIEVE_BACKUP_KEY_GUID, strlen(BACKUPKEY_RETRIEVE_BACKUP_KEY_GUID)) == 0) {
    1841          13 :                         DEBUG(debuglevel, ("Client %s requested certificate for client wrapped secret\n", addr));
    1842          13 :                         error = bkrp_retrieve_client_wrap_key(dce_call, mem_ctx, r, ldb_ctx);
    1843             :                 }
    1844             : 
    1845          69 :                 if (strncasecmp(GUID_string(mem_ctx, r->in.guidActionAgent),
    1846             :                         BACKUPKEY_RESTORE_GUID_WIN2K, strlen(BACKUPKEY_RESTORE_GUID_WIN2K)) == 0) {
    1847          16 :                         DEBUG(debuglevel, ("Client %s requested to decrypt a server side wrapped secret\n", addr));
    1848          16 :                         error = bkrp_server_wrap_decrypt_data(dce_call, mem_ctx, r, ldb_ctx);
    1849             :                 }
    1850             : 
    1851          69 :                 if (strncasecmp(GUID_string(mem_ctx, r->in.guidActionAgent),
    1852             :                         BACKUPKEY_BACKUP_GUID, strlen(BACKUPKEY_BACKUP_GUID)) == 0) {
    1853          13 :                         DEBUG(debuglevel, ("Client %s requested a server wrapped secret\n", addr));
    1854          13 :                         error = bkrp_server_wrap_encrypt_data(dce_call, mem_ctx, r, ldb_ctx);
    1855             :                 }
    1856             :         }
    1857             :         /*else: I am a RODC so I don't handle backup key protocol */
    1858             : 
    1859          69 :         talloc_unlink(mem_ctx, ldb_ctx);
    1860          69 :         return error;
    1861             : }
    1862             : 
    1863             : /* include the generated boilerplate */
    1864             : #include "librpc/gen_ndr/ndr_backupkey_s.c"

Generated by: LCOV version 1.13