[SCM] Samba Shared Repository - branch master updated

Andrew Bartlett abartlet at samba.org
Sun Feb 13 17:49:01 MST 2011


The branch, master has been updated
       via  b2e126c s4:selftest: add tests with seal and sign for backupkey
       via  7f00aa9 s4: Renable samba4.rpc.backupkey
       via  05ad9d2 s4: load the backupkey endpoint
       via  ac82dbd s4: Add server side implementation of backup key remote protocol
      from  5d63c50 s3: Add "comment" and "description" to pdb_ads

http://gitweb.samba.org/?p=samba.git;a=shortlog;h=master


- Log -----------------------------------------------------------------
commit b2e126cddc8a9f95426fa802b6d66c88629721b3
Author: Matthieu Patou <mat at matws.net>
Date:   Sun Jan 9 15:55:24 2011 +0300

    s4:selftest: add tests with seal and sign for backupkey
    
    We need to specify sign and seal as the protocol operate really only on
    sealed protected connections, in other case we are just checking that
    the server returns something like unwilling to perform due to weak
    security.
    
    Signed-off-by: Stefan Metzmacher <metze at samba.org>
    Signed-off-by: Andrew Bartlett <abartlet at samba.org>
    
    Autobuild-User: Andrew Bartlett <abartlet at samba.org>
    Autobuild-Date: Mon Feb 14 01:48:39 CET 2011 on sn-devel-104

commit 7f00aa9ef7d0eceb0821782750c085cbb1e28ada
Author: Stefan Metzmacher <metze at samba.org>
Date:   Sat Feb 5 12:15:14 2011 +0100

    s4: Renable samba4.rpc.backupkey
    
    This reverts commit 07fd397be7e30849f2c8452154edbee7dceccfe1.
    
    Signed-off-by: Andrew Bartlett <abartlet at samba.org>

commit 05ad9d2be4adc0a8b88472285835a98a6fc2c6fa
Author: Matthieu Patou <mat at matws.net>
Date:   Wed Feb 2 00:31:32 2011 +0300

    s4: load the backupkey endpoint
    
    Signed-off-by: Stefan Metzmacher <metze at samba.org>
    Signed-off-by: Andrew Bartlett <abartlet at samba.org>

commit ac82dbd89704ac20a83736d0327230a46af9eafc
Author: Matthieu Patou <mat at matws.net>
Date:   Wed Jul 28 00:03:49 2010 +0400

    s4: Add server side implementation of backup key remote protocol
    
    Signed-off-by: Andrew Bartlett <abartlet at samba.org>

-----------------------------------------------------------------------

Summary of changes:
 source4/param/loadparm.c                        |    2 +-
 source4/rpc_server/backupkey/dcesrv_backupkey.c | 1306 +++++++++++++++++++++++
 source4/rpc_server/wscript_build                |    9 +
 source4/selftest/skip                           |    1 -
 source4/selftest/tests.py                       |    4 +
 5 files changed, 1320 insertions(+), 2 deletions(-)
 create mode 100644 source4/rpc_server/backupkey/dcesrv_backupkey.c


Changeset truncated at 500 lines:

diff --git a/source4/param/loadparm.c b/source4/param/loadparm.c
index 07759c3..3d87d6f 100644
--- a/source4/param/loadparm.c
+++ b/source4/param/loadparm.c
@@ -2391,7 +2391,7 @@ struct loadparm_context *loadparm_init(TALLOC_CTX *mem_ctx)
 	lpcfg_do_global_parameter(lp_ctx, "ntvfs handler", "unixuid default");
 	lpcfg_do_global_parameter(lp_ctx, "max connections", "-1");
 
-	lpcfg_do_global_parameter(lp_ctx, "dcerpc endpoint servers", "epmapper srvsvc wkssvc rpcecho samr netlogon lsarpc spoolss drsuapi winreg dssetup unixinfo browser eventlog6");
+	lpcfg_do_global_parameter(lp_ctx, "dcerpc endpoint servers", "epmapper srvsvc wkssvc rpcecho samr netlogon lsarpc spoolss drsuapi winreg dssetup unixinfo browser eventlog6 backupkey");
 	lpcfg_do_global_parameter(lp_ctx, "server services", "smb rpc nbt wrepl ldap cldap kdc drepl winbind ntp_signd kcc dnsupdate web");
 	lpcfg_do_global_parameter(lp_ctx, "ntptr providor", "simple_ldb");
 	/* the winbind method for domain controllers is for both RODC
diff --git a/source4/rpc_server/backupkey/dcesrv_backupkey.c b/source4/rpc_server/backupkey/dcesrv_backupkey.c
new file mode 100644
index 0000000..e499128
--- /dev/null
+++ b/source4/rpc_server/backupkey/dcesrv_backupkey.c
@@ -0,0 +1,1306 @@
+/*
+   Unix SMB/CIFS implementation.
+
+   endpoint server for the backupkey interface
+
+   Copyright (C) Matthieu Patou <mat at samba.org> 2010
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include "includes.h"
+#include "rpc_server/dcerpc_server.h"
+#include "librpc/gen_ndr/ndr_backupkey.h"
+#include "dsdb/common/util.h"
+#include "dsdb/samdb/samdb.h"
+#include "lib/ldb/include/ldb_errors.h"
+#include "../lib/util/util_ldb.h"
+#include "param/param.h"
+#include "auth/session.h"
+#include "heimdal/lib/hx509/hx_locl.h"
+#include "heimdal/lib/hcrypto/rsa.h"
+#include "heimdal/lib/hcrypto/bn.h"
+#include "../lib/tsocket/tsocket.h"
+#include "../libcli/security/security.h"
+
+#define BACKUPKEY_MIN_VERSION 2
+#define BACKUPKEY_MAX_VERSION 3
+
+static const unsigned rsa_with_var_num[] = { 1, 2, 840, 113549, 1, 1, 1 };
+/* Equivalent to asn1_oid_id_pkcs1_rsaEncryption*/
+static const AlgorithmIdentifier _hx509_signature_rsa_with_var_num = {
+	{ 7, discard_const_p(unsigned, rsa_with_var_num) }, NULL
+};
+
+static NTSTATUS set_lsa_secret(TALLOC_CTX *mem_ctx,
+			       struct ldb_context *ldb,
+			       const char *name,
+			       const DATA_BLOB *secret)
+{
+	struct ldb_message *msg;
+	struct ldb_result *res;
+	struct ldb_dn *domain_dn;
+	struct ldb_dn *system_dn;
+	struct ldb_val val;
+	int ret;
+	char *name2;
+	struct timeval now = timeval_current();
+	NTTIME nt_now = timeval_to_nttime(&now);
+	const char *attrs[] = {
+		NULL
+	};
+
+	domain_dn = ldb_get_default_basedn(ldb);
+	if (!domain_dn) {
+		return NT_STATUS_INTERNAL_ERROR;
+	}
+
+	msg = ldb_msg_new(mem_ctx);
+	if (msg == NULL) {
+		return NT_STATUS_NO_MEMORY;
+	}
+
+	/*
+	 * This function is a lot like dcesrv_lsa_CreateSecret
+	 * in the rpc_server/lsa directory
+	 * The reason why we duplicate the effort here is that:
+	 * * we want to keep the former function static
+	 * * we want to avoid the burden of doing LSA calls
+	 *   when we can just manipulate the secrets directly
+	 * * taillor the function to the particular needs of backup protocol
+	 */
+
+	system_dn = samdb_search_dn(ldb, msg, domain_dn, "(&(objectClass=container)(cn=System))");
+	if (system_dn == NULL) {
+		talloc_free(msg);
+		return NT_STATUS_NO_MEMORY;
+	}
+
+	name2 = talloc_asprintf(msg, "%s Secret", name);
+	if (name2 == NULL) {
+		talloc_free(msg);
+		return NT_STATUS_NO_MEMORY;
+	}
+
+	ret = ldb_search(ldb, mem_ctx, &res, system_dn, LDB_SCOPE_SUBTREE, attrs,
+			   "(&(cn=%s)(objectclass=secret))",
+			   ldb_binary_encode_string(mem_ctx, name2));
+
+	if (ret != LDB_SUCCESS ||  res->count != 0 ) {
+		DEBUG(0, ("Secret %s already exists !\n", name2));
+		talloc_free(msg);
+		return NT_STATUS_OBJECT_NAME_COLLISION;
+	}
+
+	/*
+	 * We don't care about previous value as we are
+	 * here only if the key didn't exists before
+	 */
+
+	msg->dn = ldb_dn_copy(mem_ctx, system_dn);
+	if (msg->dn == NULL) {
+		talloc_free(msg);
+		return NT_STATUS_NO_MEMORY;
+	}
+	if (!ldb_dn_add_child_fmt(msg->dn, "cn=%s", name2)) {
+		talloc_free(msg);
+		return NT_STATUS_NO_MEMORY;
+	}
+
+	ret = samdb_msg_add_string(ldb, mem_ctx, msg, "cn", name2);
+	if (ret != LDB_SUCCESS) {
+		talloc_free(msg);
+		return NT_STATUS_NO_MEMORY;
+	}
+	ret = samdb_msg_add_string(ldb, mem_ctx, msg, "objectClass", "secret");
+	if (ret != LDB_SUCCESS) {
+		talloc_free(msg);
+		return NT_STATUS_NO_MEMORY;
+	}
+	ret = samdb_msg_add_uint64(ldb, mem_ctx, msg, "priorSetTime", nt_now);
+	if (ret != LDB_SUCCESS) {
+		talloc_free(msg);
+		return NT_STATUS_NO_MEMORY;
+	}
+	val.data = secret->data;
+	val.length = secret->length;
+	ret = ldb_msg_add_value(msg, "currentValue", &val, NULL);
+	if (ret != LDB_SUCCESS) {
+		talloc_free(msg);
+		return NT_STATUS_NO_MEMORY;
+	}
+	ret = samdb_msg_add_uint64(ldb, mem_ctx, msg, "lastSetTime", nt_now);
+	if (ret != LDB_SUCCESS) {
+		talloc_free(msg);
+		return NT_STATUS_NO_MEMORY;
+	}
+
+	/*
+	 * create the secret with DSDB_MODIFY_RELAX
+	 * otherwise dsdb/samdb/ldb_modules/objectclass.c forbid
+	 * the create of LSA secret object
+	 */
+	ret = dsdb_add(ldb, msg, DSDB_MODIFY_RELAX);
+	if (ret != LDB_SUCCESS) {
+		DEBUG(0,("Failed to create secret record %s: %s\n",
+			ldb_dn_get_linearized(msg->dn),
+			ldb_errstring(ldb)));
+		talloc_free(msg);
+		return NT_STATUS_ACCESS_DENIED;
+	}
+
+	talloc_free(msg);
+	return NT_STATUS_OK;
+}
+
+/* This function is pretty much like dcesrv_lsa_QuerySecret */
+static NTSTATUS get_lsa_secret(TALLOC_CTX *mem_ctx,
+			       struct ldb_context *ldb,
+			       const char *name,
+			       DATA_BLOB *secret)
+{
+	TALLOC_CTX *tmp_mem;
+	struct ldb_result *res;
+	struct ldb_dn *domain_dn;
+	struct ldb_dn *system_dn;
+	const struct ldb_val *val;
+	uint8_t *data;
+	const char *attrs[] = {
+		"currentValue",
+		NULL
+	};
+	int ret;
+
+	secret->data = NULL;
+	secret->length = 0;
+
+	domain_dn = ldb_get_default_basedn(ldb);
+	if (!domain_dn) {
+		return NT_STATUS_INTERNAL_ERROR;
+	}
+
+	tmp_mem = talloc_new(mem_ctx);
+	if (tmp_mem == NULL) {
+		return NT_STATUS_NO_MEMORY;
+	}
+
+	system_dn = samdb_search_dn(ldb, tmp_mem, domain_dn, "(&(objectClass=container)(cn=System))");
+	if (system_dn == NULL) {
+		talloc_free(tmp_mem);
+		return NT_STATUS_NO_MEMORY;
+	}
+
+	ret = ldb_search(ldb, mem_ctx, &res, system_dn, LDB_SCOPE_SUBTREE, attrs,
+			   "(&(cn=%s Secret)(objectclass=secret))",
+			   ldb_binary_encode_string(tmp_mem, name));
+
+	if (ret != LDB_SUCCESS || res->count == 0) {
+		talloc_free(tmp_mem);
+		/*
+		 * Important NOT to use NT_STATUS_OBJECT_NAME_NOT_FOUND
+		 * as this return value is used to detect the case
+		 * when we have the secret but without the currentValue
+		 * (case RODC)
+		 */
+		return NT_STATUS_RESOURCE_NAME_NOT_FOUND;
+	}
+
+	if (res->count > 1) {
+		DEBUG(0, ("Secret %s collision\n", name));
+		talloc_free(tmp_mem);
+		return NT_STATUS_INTERNAL_DB_CORRUPTION;
+	}
+
+	val = ldb_msg_find_ldb_val(res->msgs[0], "currentValue");
+	if (val == NULL) {
+		/*
+		 * The secret object is here but we don't have the secret value
+		 * The most common case is a RODC
+		 */
+		talloc_free(tmp_mem);
+		return NT_STATUS_OBJECT_NAME_NOT_FOUND;
+	}
+
+	data = val->data;
+	secret->data = talloc_move(mem_ctx, &data);
+	secret->length = val->length;
+
+	talloc_free(tmp_mem);
+	return NT_STATUS_OK;
+}
+
+static DATA_BLOB *reverse_and_get_blob(TALLOC_CTX *mem_ctx, BIGNUM *bn)
+{
+	DATA_BLOB blob;
+	DATA_BLOB *rev = talloc(mem_ctx, DATA_BLOB);
+	uint32_t i;
+
+	blob.length = BN_num_bytes(bn);
+	blob.data = talloc_array(mem_ctx, uint8_t, blob.length);
+
+	if (blob.data == NULL) {
+		return NULL;
+	}
+
+	BN_bn2bin(bn, blob.data);
+
+	rev->data = talloc_array(mem_ctx, uint8_t, blob.length);
+	if (rev->data == NULL) {
+		return NULL;
+	}
+
+	for(i=0; i < blob.length; i++) {
+		rev->data[i] = blob.data[blob.length - i -1];
+	}
+	rev->length = blob.length;
+	talloc_free(blob.data);
+	return rev;
+}
+
+static BIGNUM *reverse_and_get_bignum(TALLOC_CTX *mem_ctx, DATA_BLOB *blob)
+{
+	BIGNUM *ret;
+	DATA_BLOB rev;
+	uint32_t i;
+
+	rev.data = talloc_array(mem_ctx, uint8_t, blob->length);
+	if (rev.data == NULL) {
+		return NULL;
+	}
+
+	for(i=0; i < blob->length; i++) {
+		rev.data[i] = blob->data[blob->length - i -1];
+	}
+	rev.length = blob->length;
+
+	ret = BN_bin2bn(rev.data, rev.length, NULL);
+	talloc_free(rev.data);
+
+	return ret;
+}
+
+static NTSTATUS get_pk_from_raw_keypair_params(TALLOC_CTX *ctx,
+				struct bkrp_exported_RSA_key_pair *keypair,
+				hx509_private_key *pk)
+{
+	hx509_context hctx;
+	RSA *rsa;
+	struct hx509_private_key_ops *ops;
+
+	hx509_context_init(&hctx);
+	ops = hx509_find_private_alg(&_hx509_signature_rsa_with_var_num.algorithm);
+	if (ops == NULL) {
+		DEBUG(0, ("Not supported algorithm\n"));
+		return NT_STATUS_INTERNAL_ERROR;
+	}
+
+	if (_hx509_private_key_init(pk, ops, NULL) != 0) {
+		hx509_context_free(&hctx);
+		return NT_STATUS_NO_MEMORY;
+	}
+
+	rsa = RSA_new();
+	if (rsa ==NULL) {
+		hx509_context_free(&hctx);
+		return NT_STATUS_INVALID_PARAMETER;
+	}
+
+	rsa->n = reverse_and_get_bignum(ctx, &(keypair->modulus));
+	if (rsa->n == NULL) {
+		RSA_free(rsa);
+		hx509_context_free(&hctx);
+		return NT_STATUS_INVALID_PARAMETER;
+	}
+	rsa->d = reverse_and_get_bignum(ctx, &(keypair->private_exponent));
+	if (rsa->d == NULL) {
+		RSA_free(rsa);
+		hx509_context_free(&hctx);
+		return NT_STATUS_INVALID_PARAMETER;
+	}
+	rsa->p = reverse_and_get_bignum(ctx, &(keypair->prime1));
+	if (rsa->p == NULL) {
+		RSA_free(rsa);
+		hx509_context_free(&hctx);
+		return NT_STATUS_INVALID_PARAMETER;
+	}
+	rsa->q = reverse_and_get_bignum(ctx, &(keypair->prime2));
+	if (rsa->q == NULL) {
+		RSA_free(rsa);
+		hx509_context_free(&hctx);
+		return NT_STATUS_INVALID_PARAMETER;
+	}
+	rsa->dmp1 = reverse_and_get_bignum(ctx, &(keypair->exponent1));
+	if (rsa->dmp1 == NULL) {
+		RSA_free(rsa);
+		hx509_context_free(&hctx);
+		return NT_STATUS_INVALID_PARAMETER;
+	}
+	rsa->dmq1 = reverse_and_get_bignum(ctx, &(keypair->exponent2));
+	if (rsa->dmq1 == NULL) {
+		RSA_free(rsa);
+		hx509_context_free(&hctx);
+		return NT_STATUS_INVALID_PARAMETER;
+	}
+	rsa->iqmp = reverse_and_get_bignum(ctx, &(keypair->coefficient));
+	if (rsa->iqmp == NULL) {
+		RSA_free(rsa);
+		hx509_context_free(&hctx);
+		return NT_STATUS_INVALID_PARAMETER;
+	}
+	rsa->e = reverse_and_get_bignum(ctx, &(keypair->public_exponent));
+	if (rsa->e == NULL) {
+		RSA_free(rsa);
+		hx509_context_free(&hctx);
+		return NT_STATUS_INVALID_PARAMETER;
+	}
+
+	_hx509_private_key_assign_rsa(*pk, rsa);
+
+	hx509_context_free(&hctx);
+	return NT_STATUS_OK;
+}
+
+static WERROR get_and_verify_access_check(TALLOC_CTX *sub_ctx,
+					  uint32_t version,
+					  uint8_t *key_and_iv,
+					  uint8_t *access_check,
+					  uint32_t access_check_len,
+					  struct dom_sid **access_sid)
+{
+	heim_octet_string iv;
+	heim_octet_string access_check_os;
+	hx509_crypto crypto;
+
+	DATA_BLOB blob_us;
+	uint32_t key_len;
+	uint32_t iv_len;
+	int res;
+	enum ndr_err_code ndr_err;
+	hx509_context hctx;
+
+	/* This one should not be freed */
+	const AlgorithmIdentifier *alg;
+
+	*access_sid = NULL;
+	switch (version) {
+	case 2:
+		key_len = 24;
+		iv_len = 8;
+		alg = hx509_crypto_des_rsdi_ede3_cbc();
+		break;
+
+	case 3:
+		key_len = 32;
+		iv_len = 16;
+		alg =hx509_crypto_aes256_cbc();
+		break;
+
+	default:
+		return WERR_INVALID_DATA;
+	}
+
+	hx509_context_init(&hctx);
+	res = hx509_crypto_init(hctx, NULL,
+				&(alg->algorithm),
+				&crypto);
+	hx509_context_free(&hctx);
+
+	if (res != 0) {
+		return WERR_INVALID_DATA;
+	}
+
+	res = hx509_crypto_set_key_data(crypto, key_and_iv, key_len);
+
+	iv.data = talloc_memdup(sub_ctx, key_len + key_and_iv, iv_len);
+	iv.length = iv_len;
+
+	if (res != 0) {
+		hx509_crypto_destroy(crypto);
+		return WERR_INVALID_DATA;
+	}
+
+	hx509_crypto_set_padding(crypto, HX509_CRYPTO_PADDING_NONE);
+	res = hx509_crypto_decrypt(crypto,
+		access_check,
+		access_check_len,
+		&iv,
+		&access_check_os);
+
+	if (res != 0) {
+		hx509_crypto_destroy(crypto);
+		return WERR_INVALID_DATA;
+	}
+
+	blob_us.data = access_check_os.data;
+	blob_us.length = access_check_os.length;
+
+	hx509_crypto_destroy(crypto);
+
+	if (version == 2) {
+		uint32_t hash_size = 20;
+		uint8_t hash[hash_size];
+		struct sha sctx;
+		struct bkrp_access_check_v2 uncrypted_accesscheckv2;
+
+		ndr_err = ndr_pull_struct_blob(&blob_us, sub_ctx, &uncrypted_accesscheckv2,
+					(ndr_pull_flags_fn_t)ndr_pull_bkrp_access_check_v2);
+		if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
+			/* Unable to unmarshall */
+			der_free_octet_string(&access_check_os);
+			return WERR_INVALID_DATA;
+		}
+		if (uncrypted_accesscheckv2.magic != 0x1) {
+			/* wrong magic */
+			der_free_octet_string(&access_check_os);
+			return WERR_INVALID_DATA;
+		}
+
+		SHA1_Init(&sctx);
+		SHA1_Update(&sctx, blob_us.data, blob_us.length - hash_size);
+		SHA1_Final(hash, &sctx);
+		der_free_octet_string(&access_check_os);
+		/*
+		 * We free it after the sha1 calculation because blob.data
+		 * point to the same area
+		 */
+
+		if (memcmp(hash, uncrypted_accesscheckv2.hash, hash_size) != 0) {
+			DEBUG(0, ("Wrong hash value in the access check in backup key remote protocol\n"));
+			return WERR_INVALID_DATA;
+		}


-- 
Samba Shared Repository


More information about the samba-cvs mailing list