1 /* 2 Unix SMB/CIFS mplementation. 3 4 DSDB replication service - extended operation code 5 6 Copyright (C) Andrew Tridgell 2010 7 Copyright (C) Andrew Bartlett 2010 8 Copyright (C) Nadezhda Ivanova 2010 9 10 based on drepl_notify.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 "ldb_module.h" 29 #include "dsdb/samdb/samdb.h" 30 #include "smbd/service.h" 31 #include "dsdb/repl/drepl_service.h" 32 #include "param/param.h" 33 34 #undef DBGC_CLASS 35 #define DBGC_CLASS DBGC_DRS_REPL 36 37 38 /* 39 create the role owner source dsa structure 40 41 nc_dn: the DN of the subtree being replicated 42 source_dsa_dn: the DN of the server that we are replicating from 43 */ 44 static WERROR drepl_create_extended_source_dsa(struct dreplsrv_service *service, 45 TALLOC_CTX *mem_ctx, 46 struct ldb_dn *nc_dn, 47 struct ldb_dn *source_dsa_dn, 48 uint64_t min_usn, 49 struct dreplsrv_partition_source_dsa **_sdsa) 50 { 51 struct dreplsrv_partition_source_dsa *sdsa; 52 struct ldb_context *ldb = service->samdb; py_ldb_get_exception(void)53 int ret; 54 WERROR werr; 55 struct ldb_dn *nc_root; 56 struct dreplsrv_partition *p; 57 58 sdsa = talloc_zero(service, struct dreplsrv_partition_source_dsa); 59 W_ERROR_HAVE_NO_MEMORY(sdsa); 60 61 sdsa->partition = talloc_zero(sdsa, struct dreplsrv_partition); 62 if (!sdsa->partition) { 63 talloc_free(sdsa); 64 return WERR_NOT_ENOUGH_MEMORY; PyErr_SetLdbError(PyObject * error,int ret,struct ldb_context * ldb_ctx)65 } 66 67 sdsa->partition->dn = ldb_dn_copy(sdsa->partition, nc_dn); 68 if (!sdsa->partition->dn) { 69 talloc_free(sdsa); 70 return WERR_NOT_ENOUGH_MEMORY; 71 } 72 sdsa->partition->nc.dn = ldb_dn_alloc_linearized(sdsa->partition, nc_dn); 73 if (!sdsa->partition->nc.dn) { 74 talloc_free(sdsa); py_samdb_server_site_name(PyObject * self,PyObject * args)75 return WERR_NOT_ENOUGH_MEMORY; 76 } 77 ret = dsdb_find_guid_by_dn(ldb, nc_dn, &sdsa->partition->nc.guid); 78 if (ret != LDB_SUCCESS) { 79 DEBUG(0,(__location__ ": Failed to find GUID for %s\n", 80 ldb_dn_get_linearized(nc_dn))); 81 talloc_free(sdsa); 82 return WERR_DS_DRA_INTERNAL_ERROR; 83 } 84 85 sdsa->repsFrom1 = &sdsa->_repsFromBlob.ctr.ctr1; 86 ret = dsdb_find_guid_by_dn(ldb, source_dsa_dn, &sdsa->repsFrom1->source_dsa_obj_guid); 87 if (ret != LDB_SUCCESS) { 88 DEBUG(0,(__location__ ": Failed to find objectGUID for %s\n", 89 ldb_dn_get_linearized(source_dsa_dn))); 90 talloc_free(sdsa); 91 return WERR_DS_DRA_INTERNAL_ERROR; 92 } 93 94 sdsa->repsFrom1->other_info = talloc_zero(sdsa, struct repsFromTo1OtherInfo); 95 if (!sdsa->repsFrom1->other_info) { 96 talloc_free(sdsa); 97 return WERR_NOT_ENOUGH_MEMORY; 98 } 99 100 sdsa->repsFrom1->other_info->dns_name = samdb_ntds_msdcs_dns_name(ldb, 101 sdsa->repsFrom1->other_info, 102 &sdsa->repsFrom1->source_dsa_obj_guid); 103 if (!sdsa->repsFrom1->other_info->dns_name) { 104 talloc_free(sdsa); py_dsdb_convert_schema_to_openldap(PyObject * self,PyObject * args)105 return WERR_NOT_ENOUGH_MEMORY; 106 } 107 108 werr = dreplsrv_out_connection_attach(service, sdsa->repsFrom1, &sdsa->conn); 109 if (!W_ERROR_IS_OK(werr)) { 110 DEBUG(0,(__location__ ": Failed to attach connection to %s\n", 111 ldb_dn_get_linearized(nc_dn))); 112 talloc_free(sdsa); 113 return werr; 114 } 115 116 ret = dsdb_find_nc_root(service->samdb, sdsa, nc_dn, &nc_root); 117 if (ret != LDB_SUCCESS) { 118 DEBUG(0,(__location__ ": Failed to find nc_root for %s\n", 119 ldb_dn_get_linearized(nc_dn))); 120 talloc_free(sdsa); 121 return WERR_DS_DRA_INTERNAL_ERROR; 122 } 123 124 /* use the partition uptodateness vector */ 125 ret = dsdb_load_udv_v2(service->samdb, nc_root, sdsa->partition, 126 &sdsa->partition->uptodatevector.cursors, 127 &sdsa->partition->uptodatevector.count); 128 if (ret != LDB_SUCCESS) { 129 DEBUG(0,(__location__ ": Failed to load UDV for %s\n", 130 ldb_dn_get_linearized(nc_root))); py_samdb_set_domain_sid(PyLdbObject * self,PyObject * args)131 talloc_free(sdsa); 132 return WERR_DS_DRA_INTERNAL_ERROR; 133 } 134 135 /* find the highwatermark from the partitions list */ 136 for (p=service->partitions; p; p=p->next) { 137 if (ldb_dn_compare(p->dn, nc_root) == 0) { 138 struct dreplsrv_partition_source_dsa *s; 139 werr = dreplsrv_partition_source_dsa_by_guid(p, 140 &sdsa->repsFrom1->source_dsa_obj_guid, 141 &s); 142 if (W_ERROR_IS_OK(werr)) { 143 sdsa->repsFrom1->highwatermark = s->repsFrom1->highwatermark; 144 sdsa->repsFrom1->replica_flags = s->repsFrom1->replica_flags; 145 } 146 } 147 } 148 149 if (!service->am_rodc) { 150 sdsa->repsFrom1->replica_flags |= DRSUAPI_DRS_WRIT_REP; 151 } 152 153 *_sdsa = sdsa; 154 return WERR_OK; 155 } 156 157 struct extended_op_data { 158 dreplsrv_extended_callback_t callback; 159 void *callback_data; 160 struct dreplsrv_partition_source_dsa *sdsa; 161 }; 162 163 /* 164 called when an extended op finishes py_samdb_set_ntds_settings_dn(PyLdbObject * self,PyObject * args)165 */ 166 static void extended_op_callback(struct dreplsrv_service *service, 167 WERROR err, 168 enum drsuapi_DsExtendedError exop_error, 169 void *cb_data) 170 { 171 struct extended_op_data *data = talloc_get_type_abort(cb_data, struct extended_op_data); 172 talloc_unlink(data, data->sdsa); 173 data->callback(service, err, exop_error, data->callback_data); 174 talloc_free(data); 175 } 176 177 /* 178 schedule a getncchanges request to the role owner for an extended operation 179 */ 180 WERROR drepl_request_extended_op(struct dreplsrv_service *service, 181 struct ldb_dn *nc_dn, 182 struct ldb_dn *source_dsa_dn, 183 enum drsuapi_DsExtendedOperation extended_op, 184 uint64_t fsmo_info, 185 uint64_t min_usn, 186 dreplsrv_extended_callback_t callback, 187 void *callback_data) 188 { 189 WERROR werr; 190 struct extended_op_data *data; 191 192 data = talloc(service, struct extended_op_data); 193 W_ERROR_HAVE_NO_MEMORY(data); 194 195 werr = drepl_create_extended_source_dsa(service, data, nc_dn, source_dsa_dn, min_usn, &data->sdsa); 196 W_ERROR_NOT_OK_RETURN(werr); 197 198 data->callback = callback; py_samdb_get_domain_sid(PyLdbObject * self,PyObject * args)199 data->callback_data = callback_data; 200 201 werr = dreplsrv_schedule_partition_pull_source(service, data->sdsa, 202 0, extended_op, fsmo_info, 203 extended_op_callback, data); 204 if (!W_ERROR_IS_OK(werr)) { 205 talloc_free(data); 206 } 207 208 dreplsrv_run_pending_ops(service); 209 210 return werr; 211 } 212