summaryrefslogtreecommitdiff
path: root/source4
diff options
context:
space:
mode:
authorNadezhda Ivanova <nivanova@samba.org>2010-08-25 00:22:16 +0300
committerKamen Mazdrashki <kamenim@samba.org>2010-09-10 13:08:17 +0300
commit657b7039c38e97af9dbacafb5ab7a5966f52eaea (patch)
treefbd25f4c9914089ec4975882de98f1c3366a6bf9 /source4
parentc8794d2625e81b8c11dec7726a42e632854472af (diff)
downloadsamba-657b7039c38e97af9dbacafb5ab7a5966f52eaea.tar.gz
samba-657b7039c38e97af9dbacafb5ab7a5966f52eaea.tar.bz2
samba-657b7039c38e97af9dbacafb5ab7a5966f52eaea.zip
s4-drs: Implementation of GetNCChanges extended op 6 - fsmo role transfer
Basically the candidate owner makes a getncchanges call with extended op 6 when they want to become the new owner. The current owner then updates the corresponding fSMORoleOwner attribute in its database with the new owner, and replicates the change to the candidate, who then becomes the owner. The patch was made in cooperation with Anatoliy Atanasov <anatoliy.atanasov@postpath.com> who kindly helped to debug it.
Diffstat (limited to 'source4')
-rw-r--r--source4/dsdb/config.mk3
-rw-r--r--source4/dsdb/repl/drepl_fsmo.c151
-rw-r--r--source4/dsdb/wscript_build2
-rw-r--r--source4/librpc/idl/irpc.idl16
4 files changed, 170 insertions, 2 deletions
diff --git a/source4/dsdb/config.mk b/source4/dsdb/config.mk
index 1ab0cb2102..e12193d524 100644
--- a/source4/dsdb/config.mk
+++ b/source4/dsdb/config.mk
@@ -68,7 +68,8 @@ DREPL_SRV_OBJ_FILES = $(addprefix $(dsdbsrcdir)/repl/, \
drepl_out_pull.o \
drepl_out_helpers.o \
drepl_notify.o \
- drepl_ridalloc.o)
+ drepl_ridalloc.o \
+ drepl_fsmo.o)
$(eval $(call proto_header_template,$(dsdbsrcdir)/repl/drepl_service_proto.h,$(DREPL_SRV_OBJ_FILES:.o=.c)))
diff --git a/source4/dsdb/repl/drepl_fsmo.c b/source4/dsdb/repl/drepl_fsmo.c
new file mode 100644
index 0000000000..8719967d16
--- /dev/null
+++ b/source4/dsdb/repl/drepl_fsmo.c
@@ -0,0 +1,151 @@
+/*
+ Unix SMB/CIFS mplementation.
+
+ DSDB replication service - FSMO role change
+
+ Copyright (C) Nadezhda Ivanova 2010
+ Copyright (C) Andrew Tridgell 2010
+ Copyright (C) Andrew Bartlett 2010
+
+ based on drepl_ridalloc.c
+
+ 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 "dsdb/samdb/samdb.h"
+#include "smbd/service.h"
+#include "dsdb/repl/drepl_service.h"
+#include "param/param.h"
+#include "lib/messaging/irpc.h"
+#include "librpc/gen_ndr/ndr_irpc.h"
+
+static void drepl_role_callback(struct dreplsrv_service *service,
+ WERROR werr,
+ enum drsuapi_DsExtendedError ext_err)
+{
+ if (!W_ERROR_IS_OK(werr)) {
+ DEBUG(0,(__location__ ": Failed role transfer - %s - extended_ret[0x%X]\n",
+ win_errstr(werr), ext_err));
+ } else {
+ DEBUG(0,(__location__ ": Successful role transfer\n"));
+ }
+ talloc_free(service->ncchanges_extended.role_owner_source_dsa);
+ service->ncchanges_extended.role_owner_source_dsa = NULL;
+ service->ncchanges_extended.in_progress = false;
+}
+
+static bool fsmo_master_cmp(struct ldb_dn *ntds_dn, struct ldb_dn *fsmo_role_dn)
+{
+ if (ldb_dn_compare(ntds_dn, fsmo_role_dn) == 0) {
+ DEBUG(0,("\nWe are the FSMO master.\n"));
+ return true;
+ }
+ return false;
+}
+
+/*
+ see which role is we are asked to assume, initialize data and send request
+ */
+WERROR dreplsrv_fsmo_role_check(struct dreplsrv_service *service,
+ uint32_t role)
+{
+ struct ldb_dn *role_owner_dn, *fsmo_role_dn, *ntds_dn;
+ TALLOC_CTX *tmp_ctx = talloc_new(service);
+ struct ldb_context *ldb = service->samdb;
+ int ret;
+ uint64_t alloc_pool = 0;
+
+ if (service->ncchanges_extended.in_progress) {
+ talloc_free(tmp_ctx);
+ return WERR_OK;
+ }
+
+ ntds_dn = samdb_ntds_settings_dn(ldb);
+ if (!ntds_dn) {
+ return WERR_DS_DRA_INTERNAL_ERROR;
+ }
+ /* work out who is the current owner */
+ switch (role) {
+ case DREPL_NAMING_MASTER:
+ role_owner_dn = samdb_partitions_dn(ldb, tmp_ctx),
+ ret = samdb_reference_dn(ldb, tmp_ctx, role_owner_dn, "fSMORoleOwner", &fsmo_role_dn);
+ if (ret != LDB_SUCCESS) {
+ DEBUG(0,(__location__ ": Failed to find fSMORoleOwner in Naming Master object - %s",
+ ldb_errstring(ldb)));
+ talloc_free(tmp_ctx);
+ return WERR_DS_DRA_INTERNAL_ERROR;
+ }
+ break;
+ case DREPL_INFRASTRUCTURE_MASTER:
+ role_owner_dn = samdb_infrastructure_dn(ldb, tmp_ctx);
+ ret = samdb_reference_dn(ldb, tmp_ctx, role_owner_dn, "fSMORoleOwner", &fsmo_role_dn);
+ if (ret != LDB_SUCCESS) {
+ DEBUG(0,(__location__ ": Failed to find fSMORoleOwner in Schema Master object - %s",
+ ldb_errstring(ldb)));
+ talloc_free(tmp_ctx);
+ return WERR_DS_DRA_INTERNAL_ERROR;
+ }
+ break;
+ case DREPL_RID_MASTER:
+ ret = samdb_rid_manager_dn(ldb, tmp_ctx, &role_owner_dn);
+ if (ret != LDB_SUCCESS) {
+ DEBUG(0, (__location__ ": Failed to find RID Manager object - %s", ldb_errstring(ldb)));
+ talloc_free(tmp_ctx);
+ return WERR_DS_DRA_INTERNAL_ERROR;
+ }
+
+ /* find the DN of the RID Manager */
+ ret = samdb_reference_dn(ldb, tmp_ctx, role_owner_dn, "fSMORoleOwner", &fsmo_role_dn);
+ if (ret != LDB_SUCCESS) {
+ DEBUG(0,(__location__ ": Failed to find fSMORoleOwner in RID Manager object - %s",
+ ldb_errstring(ldb)));
+ talloc_free(tmp_ctx);
+ return WERR_DS_DRA_INTERNAL_ERROR;
+ }
+ break;
+ case DREPL_SCHEMA_MASTER:
+ role_owner_dn = ldb_get_schema_basedn(ldb);
+ ret = samdb_reference_dn(ldb, tmp_ctx, role_owner_dn, "fSMORoleOwner", &fsmo_role_dn);
+ if (ret != LDB_SUCCESS) {
+ DEBUG(0,(__location__ ": Failed to find fSMORoleOwner in Schema Master object - %s",
+ ldb_errstring(ldb)));
+ talloc_free(tmp_ctx);
+ return WERR_DS_DRA_INTERNAL_ERROR;
+ }
+ if (!fsmo_master_cmp(ntds_dn, fsmo_role_dn)) {
+ return drepl_request_extended_op(service,
+ role_owner_dn,
+ fsmo_role_dn,
+ DRSUAPI_EXOP_FSMO_REQ_ROLE,
+ alloc_pool,
+ drepl_role_callback);
+ }
+ break;
+ case DREPL_PDC_MASTER:
+ role_owner_dn = ldb_get_default_basedn(ldb);
+ ret = samdb_reference_dn(ldb, tmp_ctx, role_owner_dn, "fSMORoleOwner", &fsmo_role_dn);
+ if (ret != LDB_SUCCESS) {
+ DEBUG(0,(__location__ ": Failed to find fSMORoleOwner in Pd Master object - %s",
+ ldb_errstring(ldb)));
+ talloc_free(tmp_ctx);
+ return WERR_DS_DRA_INTERNAL_ERROR;
+ }
+ break;
+ default:
+ return WERR_DS_DRA_INTERNAL_ERROR;
+ }
+ return WERR_OK;
+}
diff --git a/source4/dsdb/wscript_build b/source4/dsdb/wscript_build
index d3961f52d5..426b12dc7f 100644
--- a/source4/dsdb/wscript_build
+++ b/source4/dsdb/wscript_build
@@ -25,7 +25,7 @@ bld.SAMBA_SUBSYSTEM('SAMDB_SCHEMA',
bld.SAMBA_MODULE('DREPL_SRV',
- source='repl/drepl_service.c repl/drepl_periodic.c repl/drepl_partitions.c repl/drepl_out_pull.c repl/drepl_out_helpers.c repl/drepl_notify.c repl/drepl_ridalloc.c',
+ source='repl/drepl_service.c repl/drepl_periodic.c repl/drepl_partitions.c repl/drepl_out_pull.c repl/drepl_out_helpers.c repl/drepl_notify.c repl/drepl_ridalloc.c repl/drepl_fsmo.c',
autoproto='repl/drepl_service_proto.h',
subsystem='service',
init_function='server_service_drepl_init',
diff --git a/source4/librpc/idl/irpc.idl b/source4/librpc/idl/irpc.idl
index 35204dbedc..2b88dc749b 100644
--- a/source4/librpc/idl/irpc.idl
+++ b/source4/librpc/idl/irpc.idl
@@ -157,4 +157,20 @@ import "misc.idl", "security.idl", "nbt.idl";
* If empy/NULL, refresh all partitions.
*/
WERROR dreplsrv_refresh();
+
+ /*
+ called when role transfer is requested via LDAP
+ */
+ typedef [v1_enum] enum {
+ DREPL_SCHEMA_MASTER,
+ DREPL_RID_MASTER,
+ DREPL_INFRASTRUCTURE_MASTER,
+ DREPL_NAMING_MASTER,
+ DREPL_PDC_MASTER
+ } drepl_role_master;
+
+ NTSTATUS drepl_takeFSMORole(
+ [in] uint32 role
+ );
+
}