1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144
|
/*
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
Copyright (C) Anatoliy Atanasov 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"
struct fsmo_role_state {
struct irpc_message *msg;
struct drepl_takeFSMORole *r;
};
static void drepl_role_callback(struct dreplsrv_service *service,
WERROR werr,
enum drsuapi_DsExtendedError ext_err,
void *cb_data)
{
struct fsmo_role_state *fsmo = talloc_get_type_abort(cb_data, struct fsmo_role_state);
if (!W_ERROR_IS_OK(werr)) {
DEBUG(2,(__location__ ": Failed role transfer - %s - extended_ret[0x%X]\n",
win_errstr(werr), ext_err));
} else {
DEBUG(2,(__location__ ": Successful role transfer\n"));
}
fsmo->r->out.result = werr;
irpc_send_reply(fsmo->msg, NT_STATUS_OK);
}
/*
see which role is we are asked to assume, initialize data and send request
*/
NTSTATUS drepl_take_FSMO_role(struct irpc_message *msg,
struct drepl_takeFSMORole *r)
{
struct dreplsrv_service *service = talloc_get_type(msg->private_data,
struct dreplsrv_service);
struct ldb_dn *role_owner_dn, *fsmo_role_dn;
TALLOC_CTX *tmp_ctx = talloc_new(service);
uint64_t fsmo_info = 0;
enum drsuapi_DsExtendedOperation extended_op = DRSUAPI_EXOP_NONE;
WERROR werr;
enum drepl_role_master role = r->in.role;
struct fsmo_role_state *fsmo;
bool is_us;
int ret;
werr = dsdb_get_fsmo_role_info(tmp_ctx, service->samdb, role,
&fsmo_role_dn, &role_owner_dn);
if (!W_ERROR_IS_OK(werr)) {
talloc_free(tmp_ctx);
r->out.result = werr;
return NT_STATUS_OK;
}
switch (role) {
case DREPL_NAMING_MASTER:
case DREPL_INFRASTRUCTURE_MASTER:
case DREPL_SCHEMA_MASTER:
extended_op = DRSUAPI_EXOP_FSMO_REQ_ROLE;
break;
case DREPL_RID_MASTER:
extended_op = DRSUAPI_EXOP_FSMO_RID_REQ_ROLE;
break;
case DREPL_PDC_MASTER:
extended_op = DRSUAPI_EXOP_FSMO_REQ_PDC;
break;
default:
DEBUG(0,("Unknown role %u in role transfer\n",
(unsigned)role));
/* IRPC messages are trusted, so this really should not happen */
smb_panic("Unknown role despite dsdb_get_fsmo_role_info success");
}
ret = samdb_dn_is_our_ntdsa(service->samdb, role_owner_dn, &is_us);
if (ret != LDB_SUCCESS) {
DEBUG(0,("FSMO role check failed (failed to confirm if our ntdsDsa) for DN %s and owner %s \n",
ldb_dn_get_linearized(fsmo_role_dn),
ldb_dn_get_linearized(role_owner_dn)));
talloc_free(tmp_ctx);
r->out.result = WERR_DS_DRA_INTERNAL_ERROR;
return NT_STATUS_OK;
}
if (is_us) {
DEBUG(5,("FSMO role check failed, we already own DN %s with %s\n",
ldb_dn_get_linearized(fsmo_role_dn),
ldb_dn_get_linearized(role_owner_dn)));
r->out.result = WERR_OK;
talloc_free(tmp_ctx);
return NT_STATUS_OK;
}
fsmo = talloc(msg, struct fsmo_role_state);
NT_STATUS_HAVE_NO_MEMORY(fsmo);
fsmo->msg = msg;
fsmo->r = r;
werr = drepl_request_extended_op(service,
fsmo_role_dn,
role_owner_dn,
extended_op,
fsmo_info,
0,
drepl_role_callback,
fsmo);
if (!W_ERROR_IS_OK(werr)) {
r->out.result = werr;
talloc_free(tmp_ctx);
return NT_STATUS_OK;
}
/* mark this message to be answered later */
msg->defer_reply = true;
dreplsrv_run_pending_ops(service);
talloc_free(tmp_ctx);
return NT_STATUS_OK;
}
|