LCOV - code coverage report
Current view: top level - source4/rpc_server/backupkey - dcesrv_backupkey.c (source / functions) Hit Total Coverage
Test: coverage report for v4-17-test 1498b464 Lines: 582 817 71.2 %
Date: 2024-06-13 04:01:37 Functions: 19 19 100.0 %

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

Generated by: LCOV version 1.13