s4-drs: Implementation of GetNCChanges extended op 6 - fsmo role transfer
[metze/samba/wip.git] / source4 / dsdb / repl / drepl_fsmo.c
1 /*
2    Unix SMB/CIFS mplementation.
3
4    DSDB replication service - FSMO role change
5
6    Copyright (C) Nadezhda Ivanova 2010
7    Copyright (C) Andrew Tridgell 2010
8    Copyright (C) Andrew Bartlett 2010
9
10    based on drepl_ridalloc.c
11
12    This program is free software; you can redistribute it and/or modify
13    it under the terms of the GNU General Public License as published by
14    the Free Software Foundation; either version 3 of the License, or
15    (at your option) any later version.
16
17    This program is distributed in the hope that it will be useful,
18    but WITHOUT ANY WARRANTY; without even the implied warranty of
19    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20    GNU General Public License for more details.
21
22    You should have received a copy of the GNU General Public License
23    along with this program.  If not, see <http://www.gnu.org/licenses/>.
24
25 */
26
27 #include "includes.h"
28 #include "dsdb/samdb/samdb.h"
29 #include "smbd/service.h"
30 #include "dsdb/repl/drepl_service.h"
31 #include "param/param.h"
32 #include "lib/messaging/irpc.h"
33 #include "librpc/gen_ndr/ndr_irpc.h"
34
35 static void drepl_role_callback(struct dreplsrv_service *service,
36                                 WERROR werr,
37                                 enum drsuapi_DsExtendedError ext_err)
38 {
39         if (!W_ERROR_IS_OK(werr)) {
40                 DEBUG(0,(__location__ ": Failed role transfer - %s - extended_ret[0x%X]\n",
41                          win_errstr(werr), ext_err));
42         } else {
43                 DEBUG(0,(__location__ ": Successful role transfer\n"));
44         }
45         talloc_free(service->ncchanges_extended.role_owner_source_dsa);
46         service->ncchanges_extended.role_owner_source_dsa = NULL;
47         service->ncchanges_extended.in_progress = false;
48 }
49
50 static bool fsmo_master_cmp(struct ldb_dn *ntds_dn, struct ldb_dn *fsmo_role_dn)
51 {
52         if (ldb_dn_compare(ntds_dn, fsmo_role_dn) == 0) {
53                 DEBUG(0,("\nWe are the FSMO master.\n"));
54                 return true;
55         }
56         return false;
57 }
58
59 /*
60   see which role is we are asked to assume, initialize data and send request
61  */
62 WERROR dreplsrv_fsmo_role_check(struct dreplsrv_service *service,
63                                 uint32_t role)
64 {
65         struct ldb_dn *role_owner_dn, *fsmo_role_dn, *ntds_dn;
66         TALLOC_CTX *tmp_ctx = talloc_new(service);
67         struct ldb_context *ldb = service->samdb;
68         int ret;
69         uint64_t alloc_pool = 0;
70
71         if (service->ncchanges_extended.in_progress) {
72                 talloc_free(tmp_ctx);
73                 return WERR_OK;
74         }
75
76         ntds_dn = samdb_ntds_settings_dn(ldb);
77         if (!ntds_dn) {
78                 return WERR_DS_DRA_INTERNAL_ERROR;
79         }
80         /* work out who is the current owner */
81         switch (role) {
82         case DREPL_NAMING_MASTER:
83                 role_owner_dn = samdb_partitions_dn(ldb, tmp_ctx),
84                 ret = samdb_reference_dn(ldb, tmp_ctx, role_owner_dn, "fSMORoleOwner", &fsmo_role_dn);
85                 if (ret != LDB_SUCCESS) {
86                         DEBUG(0,(__location__ ": Failed to find fSMORoleOwner in Naming Master object - %s",
87                                  ldb_errstring(ldb)));
88                         talloc_free(tmp_ctx);
89                         return WERR_DS_DRA_INTERNAL_ERROR;
90                 }
91                 break;
92         case DREPL_INFRASTRUCTURE_MASTER:
93                 role_owner_dn = samdb_infrastructure_dn(ldb, tmp_ctx);
94                 ret = samdb_reference_dn(ldb, tmp_ctx, role_owner_dn, "fSMORoleOwner", &fsmo_role_dn);
95                 if (ret != LDB_SUCCESS) {
96                         DEBUG(0,(__location__ ": Failed to find fSMORoleOwner in Schema Master object - %s",
97                                  ldb_errstring(ldb)));
98                         talloc_free(tmp_ctx);
99                         return WERR_DS_DRA_INTERNAL_ERROR;
100                 }
101                 break;
102         case DREPL_RID_MASTER:
103                 ret = samdb_rid_manager_dn(ldb, tmp_ctx, &role_owner_dn);
104                 if (ret != LDB_SUCCESS) {
105                         DEBUG(0, (__location__ ": Failed to find RID Manager object - %s", ldb_errstring(ldb)));
106                         talloc_free(tmp_ctx);
107                         return WERR_DS_DRA_INTERNAL_ERROR;
108                 }
109
110                 /* find the DN of the RID Manager */
111                 ret = samdb_reference_dn(ldb, tmp_ctx, role_owner_dn, "fSMORoleOwner", &fsmo_role_dn);
112                 if (ret != LDB_SUCCESS) {
113                         DEBUG(0,(__location__ ": Failed to find fSMORoleOwner in RID Manager object - %s",
114                                  ldb_errstring(ldb)));
115                         talloc_free(tmp_ctx);
116                         return WERR_DS_DRA_INTERNAL_ERROR;
117                 }
118                 break;
119         case DREPL_SCHEMA_MASTER:
120                 role_owner_dn = ldb_get_schema_basedn(ldb);
121                 ret = samdb_reference_dn(ldb, tmp_ctx, role_owner_dn, "fSMORoleOwner", &fsmo_role_dn);
122                 if (ret != LDB_SUCCESS) {
123                         DEBUG(0,(__location__ ": Failed to find fSMORoleOwner in Schema Master object - %s",
124                                  ldb_errstring(ldb)));
125                         talloc_free(tmp_ctx);
126                         return WERR_DS_DRA_INTERNAL_ERROR;
127                 }
128                 if (!fsmo_master_cmp(ntds_dn, fsmo_role_dn)) {
129                         return drepl_request_extended_op(service,
130                                                          role_owner_dn,
131                                                          fsmo_role_dn,
132                                                          DRSUAPI_EXOP_FSMO_REQ_ROLE,
133                                                          alloc_pool,
134                                                          drepl_role_callback);
135                 }
136                 break;
137         case DREPL_PDC_MASTER:
138                 role_owner_dn = ldb_get_default_basedn(ldb);
139                 ret = samdb_reference_dn(ldb, tmp_ctx, role_owner_dn, "fSMORoleOwner", &fsmo_role_dn);
140                 if (ret != LDB_SUCCESS) {
141                         DEBUG(0,(__location__ ": Failed to find fSMORoleOwner in Pd Master object - %s",
142                                  ldb_errstring(ldb)));
143                         talloc_free(tmp_ctx);
144                         return WERR_DS_DRA_INTERNAL_ERROR;
145                 }
146                 break;
147         default:
148                 return WERR_DS_DRA_INTERNAL_ERROR;
149         }
150         return WERR_OK;
151 }