Changeset 740 for vendor/current/source4/dsdb/repl
- Timestamp:
- Nov 14, 2012, 12:59:34 PM (13 years ago)
- Location:
- vendor/current/source4/dsdb/repl
- Files:
-
- 5 added
- 8 edited
Legend:
- Unmodified
- Added
- Removed
-
vendor/current/source4/dsdb/repl/drepl_notify.c
r414 r740 27 27 #include "auth/auth.h" 28 28 #include "smbd/service.h" 29 #include "lib/messaging/irpc.h"30 29 #include "dsdb/repl/drepl_service.h" 31 #include "lib/ldb/include/ldb_errors.h"30 #include <ldb_errors.h> 32 31 #include "../lib/util/dlinklist.h" 33 32 #include "librpc/gen_ndr/ndr_misc.h" … … 35 34 #include "librpc/gen_ndr/ndr_drsblobs.h" 36 35 #include "libcli/composite/composite.h" 36 #include "../lib/util/tevent_ntstatus.h" 37 37 38 38 39 39 struct dreplsrv_op_notify_state { 40 struct composite_context *creq; 41 42 struct dreplsrv_out_connection *conn; 43 44 struct dreplsrv_drsuapi_connection *drsuapi; 45 46 struct drsuapi_DsBindInfoCtr bind_info_ctr; 47 struct drsuapi_DsBind bind_r; 40 struct tevent_context *ev; 48 41 struct dreplsrv_notify_operation *op; 42 void *ndr_struct_ptr; 49 43 }; 50 44 51 /* 52 receive a DsReplicaSync reply 53 */ 54 static void dreplsrv_op_notify_replica_sync_recv(struct rpc_request *req) 55 { 56 struct dreplsrv_op_notify_state *st = talloc_get_type(req->async.private_data, 57 struct dreplsrv_op_notify_state); 58 struct composite_context *c = st->creq; 59 struct drsuapi_DsReplicaSync *r = talloc_get_type(req->ndr.struct_ptr, 60 struct drsuapi_DsReplicaSync); 61 62 c->status = dcerpc_ndr_request_recv(req); 63 if (!composite_is_ok(c)) return; 64 65 if (!W_ERROR_IS_OK(r->out.result)) { 66 composite_error(c, werror_to_ntstatus(r->out.result)); 67 return; 68 } 69 70 composite_done(c); 71 } 72 73 /* 74 send a DsReplicaSync 75 */ 76 static void dreplsrv_op_notify_replica_sync_send(struct dreplsrv_op_notify_state *st) 77 { 78 struct composite_context *c = st->creq; 79 struct dreplsrv_partition *partition = st->op->source_dsa->partition; 80 struct dreplsrv_drsuapi_connection *drsuapi = st->op->source_dsa->conn->drsuapi; 81 struct rpc_request *req; 45 static void dreplsrv_op_notify_connect_done(struct tevent_req *subreq); 46 47 /* 48 start the ReplicaSync async call 49 */ 50 static struct tevent_req *dreplsrv_op_notify_send(TALLOC_CTX *mem_ctx, 51 struct tevent_context *ev, 52 struct dreplsrv_notify_operation *op) 53 { 54 struct tevent_req *req; 55 struct dreplsrv_op_notify_state *state; 56 struct tevent_req *subreq; 57 58 req = tevent_req_create(mem_ctx, &state, 59 struct dreplsrv_op_notify_state); 60 if (req == NULL) { 61 return NULL; 62 } 63 state->ev = ev; 64 state->op = op; 65 66 subreq = dreplsrv_out_drsuapi_send(state, 67 ev, 68 op->source_dsa->conn); 69 if (tevent_req_nomem(subreq, req)) { 70 return tevent_req_post(req, ev); 71 } 72 tevent_req_set_callback(subreq, dreplsrv_op_notify_connect_done, req); 73 74 return req; 75 } 76 77 static void dreplsrv_op_notify_replica_sync_trigger(struct tevent_req *req); 78 79 static void dreplsrv_op_notify_connect_done(struct tevent_req *subreq) 80 { 81 struct tevent_req *req = tevent_req_callback_data(subreq, 82 struct tevent_req); 83 NTSTATUS status; 84 85 status = dreplsrv_out_drsuapi_recv(subreq); 86 TALLOC_FREE(subreq); 87 if (tevent_req_nterror(req, status)) { 88 return; 89 } 90 91 dreplsrv_op_notify_replica_sync_trigger(req); 92 } 93 94 static void dreplsrv_op_notify_replica_sync_done(struct tevent_req *subreq); 95 96 static void dreplsrv_op_notify_replica_sync_trigger(struct tevent_req *req) 97 { 98 struct dreplsrv_op_notify_state *state = 99 tevent_req_data(req, 100 struct dreplsrv_op_notify_state); 101 struct dreplsrv_partition *partition = state->op->source_dsa->partition; 102 struct dreplsrv_drsuapi_connection *drsuapi = state->op->source_dsa->conn->drsuapi; 82 103 struct drsuapi_DsReplicaSync *r; 83 84 r = talloc_zero(st, struct drsuapi_DsReplicaSync); 85 if (composite_nomem(r, c)) return; 86 104 struct tevent_req *subreq; 105 106 r = talloc_zero(state, struct drsuapi_DsReplicaSync); 107 if (tevent_req_nomem(r, req)) { 108 return; 109 } 110 r->in.req = talloc_zero(r, union drsuapi_DsReplicaSyncRequest); 111 if (tevent_req_nomem(r, req)) { 112 return; 113 } 87 114 r->in.bind_handle = &drsuapi->bind_handle; 88 115 r->in.level = 1; 89 r->in.req.req1.naming_context = &partition->nc; 90 r->in.req.req1.source_dsa_guid = st->op->service->ntds_guid; 91 r->in.req.req1.options = 92 DRSUAPI_DS_REPLICA_SYNC_ASYNCHRONOUS_OPERATION | 93 DRSUAPI_DS_REPLICA_SYNC_WRITEABLE | 94 DRSUAPI_DS_REPLICA_SYNC_ALL_SOURCES; 95 96 97 req = dcerpc_drsuapi_DsReplicaSync_send(drsuapi->pipe, r, r); 98 composite_continue_rpc(c, req, dreplsrv_op_notify_replica_sync_recv, st); 99 } 100 101 /* 102 called when we have an established connection 103 */ 104 static void dreplsrv_op_notify_connect_recv(struct composite_context *creq) 105 { 106 struct dreplsrv_op_notify_state *st = talloc_get_type(creq->async.private_data, 107 struct dreplsrv_op_notify_state); 108 struct composite_context *c = st->creq; 109 110 c->status = dreplsrv_out_drsuapi_recv(creq); 111 if (!composite_is_ok(c)) return; 112 113 dreplsrv_op_notify_replica_sync_send(st); 114 } 115 116 /* 117 start the ReplicaSync async call 118 */ 119 static struct composite_context *dreplsrv_op_notify_send(struct dreplsrv_notify_operation *op) 120 { 121 struct composite_context *c; 122 struct composite_context *creq; 123 struct dreplsrv_op_notify_state *st; 124 125 c = composite_create(op, op->service->task->event_ctx); 126 if (c == NULL) return NULL; 127 128 st = talloc_zero(c, struct dreplsrv_op_notify_state); 129 if (composite_nomem(st, c)) return c; 130 131 st->creq = c; 132 st->op = op; 133 134 creq = dreplsrv_out_drsuapi_send(op->source_dsa->conn); 135 composite_continue(c, creq, dreplsrv_op_notify_connect_recv, st); 136 137 return c; 138 } 139 140 static void dreplsrv_notify_del_repsTo(struct dreplsrv_notify_operation *op) 141 { 142 uint32_t count; 143 struct repsFromToBlob *reps; 144 WERROR werr; 145 struct dreplsrv_service *s = op->service; 146 int i; 147 148 werr = dsdb_loadreps(s->samdb, op, op->source_dsa->partition->dn, "repsTo", &reps, &count); 149 if (!W_ERROR_IS_OK(werr)) { 150 DEBUG(0,(__location__ ": Failed to load repsTo for %s\n", 151 ldb_dn_get_linearized(op->source_dsa->partition->dn))); 152 return; 153 } 154 155 for (i=0; i<count; i++) { 156 if (GUID_compare(&reps[i].ctr.ctr1.source_dsa_obj_guid, 157 &op->source_dsa->repsFrom1->source_dsa_obj_guid) == 0) { 158 memmove(&reps[i], &reps[i+1], 159 sizeof(reps[i])*(count-(i+1))); 160 count--; 161 } 162 } 163 164 werr = dsdb_savereps(s->samdb, op, op->source_dsa->partition->dn, "repsTo", reps, count); 165 if (!W_ERROR_IS_OK(werr)) { 166 DEBUG(0,(__location__ ": Failed to save repsTo for %s\n", 167 ldb_dn_get_linearized(op->source_dsa->partition->dn))); 168 return; 169 } 116 r->in.req->req1.naming_context = &partition->nc; 117 r->in.req->req1.source_dsa_guid = state->op->service->ntds_guid; 118 r->in.req->req1.options = 119 DRSUAPI_DRS_ASYNC_OP | 120 DRSUAPI_DRS_UPDATE_NOTIFICATION | 121 DRSUAPI_DRS_WRIT_REP; 122 123 if (state->op->is_urgent) { 124 r->in.req->req1.options |= DRSUAPI_DRS_SYNC_URGENT; 125 } 126 127 state->ndr_struct_ptr = r; 128 129 if (DEBUGLVL(10)) { 130 NDR_PRINT_IN_DEBUG(drsuapi_DsReplicaSync, r); 131 } 132 133 subreq = dcerpc_drsuapi_DsReplicaSync_r_send(state, 134 state->ev, 135 drsuapi->drsuapi_handle, 136 r); 137 if (tevent_req_nomem(subreq, req)) { 138 return; 139 } 140 tevent_req_set_callback(subreq, dreplsrv_op_notify_replica_sync_done, req); 141 } 142 143 static void dreplsrv_op_notify_replica_sync_done(struct tevent_req *subreq) 144 { 145 struct tevent_req *req = 146 tevent_req_callback_data(subreq, 147 struct tevent_req); 148 struct dreplsrv_op_notify_state *state = 149 tevent_req_data(req, 150 struct dreplsrv_op_notify_state); 151 struct drsuapi_DsReplicaSync *r = talloc_get_type(state->ndr_struct_ptr, 152 struct drsuapi_DsReplicaSync); 153 NTSTATUS status; 154 155 state->ndr_struct_ptr = NULL; 156 157 status = dcerpc_drsuapi_DsReplicaSync_r_recv(subreq, r); 158 TALLOC_FREE(subreq); 159 if (tevent_req_nterror(req, status)) { 160 return; 161 } 162 163 if (!W_ERROR_IS_OK(r->out.result)) { 164 status = werror_to_ntstatus(r->out.result); 165 tevent_req_nterror(req, status); 166 return; 167 } 168 169 tevent_req_done(req); 170 } 171 172 static NTSTATUS dreplsrv_op_notify_recv(struct tevent_req *req) 173 { 174 return tevent_req_simple_recv_ntstatus(req); 170 175 } 171 176 … … 173 178 called when a notify operation has completed 174 179 */ 175 static void dreplsrv_notify_op_callback(struct dreplsrv_notify_operation *op) 176 { 180 static void dreplsrv_notify_op_callback(struct tevent_req *subreq) 181 { 182 struct dreplsrv_notify_operation *op = 183 tevent_req_callback_data(subreq, 184 struct dreplsrv_notify_operation); 177 185 NTSTATUS status; 178 186 struct dreplsrv_service *s = op->service; 179 180 status = composite_wait(op->creq); 187 WERROR werr; 188 189 status = dreplsrv_op_notify_recv(subreq); 190 werr = ntstatus_to_werror(status); 191 TALLOC_FREE(subreq); 181 192 if (!NT_STATUS_IS_OK(status)) { 182 DEBUG( 0,("dreplsrv_notify: Failed to send DsReplicaSync to %s for %s -%s\n",193 DEBUG(4,("dreplsrv_notify: Failed to send DsReplicaSync to %s for %s - %s : %s\n", 183 194 op->source_dsa->repsFrom1->other_info->dns_name, 184 195 ldb_dn_get_linearized(op->source_dsa->partition->dn), 185 nt_errstr(status) ));196 nt_errstr(status), win_errstr(werr))); 186 197 } else { 187 198 DEBUG(2,("dreplsrv_notify: DsReplicaSync OK for %s\n", 188 199 op->source_dsa->repsFrom1->other_info->dns_name)); 189 200 op->source_dsa->notify_uSN = op->uSN; 190 /* delete the repsTo for this replication partner in the191 partition, as we have successfully told him to sync */ 192 dreplsrv_notify_del_repsTo(op);193 }194 talloc_free(op->creq);201 } 202 203 drepl_reps_update(s, "repsTo", op->source_dsa->partition->dn, 204 &op->source_dsa->repsFrom1->source_dsa_obj_guid, 205 werr); 195 206 196 207 talloc_free(op); 197 208 s->ops.n_current = NULL; 198 dreplsrv_notify_run_ops(s); 199 } 200 201 202 static void dreplsrv_notify_op_callback_creq(struct composite_context *creq) 203 { 204 struct dreplsrv_notify_operation *op = talloc_get_type(creq->async.private_data, 205 struct dreplsrv_notify_operation); 206 dreplsrv_notify_op_callback(op); 209 dreplsrv_run_pending_ops(s); 207 210 } 208 211 … … 213 216 { 214 217 struct dreplsrv_notify_operation *op; 218 struct tevent_req *subreq; 215 219 216 220 if (s->ops.n_current || s->ops.current) { … … 228 232 DLIST_REMOVE(s->ops.notifies, op); 229 233 230 op->creq = dreplsrv_op_notify_send(op); 231 if (!op->creq) { 232 dreplsrv_notify_op_callback(op); 233 return; 234 } 235 236 op->creq->async.fn = dreplsrv_notify_op_callback_creq; 237 op->creq->async.private_data = op; 234 subreq = dreplsrv_op_notify_send(op, s->task->event_ctx, op); 235 if (!subreq) { 236 DEBUG(0,("dreplsrv_notify_run_ops: dreplsrv_op_notify_send[%s][%s] - no memory\n", 237 op->source_dsa->repsFrom1->other_info->dns_name, 238 ldb_dn_get_linearized(op->source_dsa->partition->dn))); 239 return; 240 } 241 tevent_req_set_callback(subreq, dreplsrv_notify_op_callback, op); 242 DEBUG(4,("started DsReplicaSync for %s to %s\n", 243 ldb_dn_get_linearized(op->source_dsa->partition->dn), 244 op->source_dsa->repsFrom1->other_info->dns_name)); 238 245 } 239 246 … … 242 249 find a source_dsa for a given guid 243 250 */ 244 static struct dreplsrv_partition_source_dsa *dreplsrv_find_ source_dsa(struct dreplsrv_partition *p,251 static struct dreplsrv_partition_source_dsa *dreplsrv_find_notify_dsa(struct dreplsrv_partition *p, 245 252 struct GUID *guid) 246 253 { 247 254 struct dreplsrv_partition_source_dsa *s; 248 255 256 /* first check the sources list */ 249 257 for (s=p->sources; s; s=s->next) { 258 if (GUID_compare(&s->repsFrom1->source_dsa_obj_guid, guid) == 0) { 259 return s; 260 } 261 } 262 263 /* then the notifies list */ 264 for (s=p->notifies; s; s=s->next) { 250 265 if (GUID_compare(&s->repsFrom1->source_dsa_obj_guid, guid) == 0) { 251 266 return s; … … 263 278 struct repsFromToBlob *reps, 264 279 TALLOC_CTX *mem_ctx, 265 uint64_t uSN) 280 uint64_t uSN, 281 bool is_urgent, 282 uint32_t replica_flags) 266 283 { 267 284 struct dreplsrv_notify_operation *op; 268 285 struct dreplsrv_partition_source_dsa *s; 269 286 270 s = dreplsrv_find_ source_dsa(p, &reps->ctr.ctr1.source_dsa_obj_guid);287 s = dreplsrv_find_notify_dsa(p, &reps->ctr.ctr1.source_dsa_obj_guid); 271 288 if (s == NULL) { 272 289 DEBUG(0,(__location__ ": Unable to find source_dsa for %s\n", … … 275 292 } 276 293 294 /* first try to find an existing notify operation */ 295 for (op = service->ops.notifies; op; op = op->next) { 296 if (op->source_dsa != s) { 297 continue; 298 } 299 300 if (op->is_urgent != is_urgent) { 301 continue; 302 } 303 304 if (op->replica_flags != replica_flags) { 305 continue; 306 } 307 308 if (op->uSN < uSN) { 309 op->uSN = uSN; 310 } 311 312 /* reuse the notify operation, as it's not yet started */ 313 return WERR_OK; 314 } 315 277 316 op = talloc_zero(mem_ctx, struct dreplsrv_notify_operation); 278 317 W_ERROR_HAVE_NO_MEMORY(op); 279 318 280 op->service = service; 281 op->source_dsa = s; 282 op->uSN = uSN; 319 op->service = service; 320 op->source_dsa = s; 321 op->uSN = uSN; 322 op->is_urgent = is_urgent; 323 op->replica_flags = replica_flags; 324 op->schedule_time = time(NULL); 283 325 284 326 DLIST_ADD_END(service->ops.notifies, op, struct dreplsrv_notify_operation *); … … 298 340 struct repsFromToBlob *reps; 299 341 WERROR werr; 300 uint64_t uSN; 301 int ret, i; 342 uint64_t uSNHighest; 343 uint64_t uSNUrgent; 344 uint32_t i; 345 int ret; 302 346 303 347 werr = dsdb_loadreps(s->samdb, mem_ctx, p->dn, "repsTo", &reps, &count); 304 if (count == 0) {305 werr = dsdb_loadreps(s->samdb, mem_ctx, p->dn, "repsFrom", &reps, &count);306 }307 348 if (!W_ERROR_IS_OK(werr)) { 308 349 DEBUG(0,(__location__ ": Failed to load repsTo for %s\n", … … 311 352 } 312 353 313 /* loads the partition uSNHighest */314 ret = dsdb_load_partition_usn(s->samdb, p->dn, &uSN );315 if (ret != LDB_SUCCESS || uSN == 0) {354 /* loads the partition uSNHighest and uSNUrgent */ 355 ret = dsdb_load_partition_usn(s->samdb, p->dn, &uSNHighest, &uSNUrgent); 356 if (ret != LDB_SUCCESS || uSNHighest == 0) { 316 357 /* nothing to do */ 317 358 return WERR_OK; … … 321 362 for (i=0; i<count; i++) { 322 363 struct dreplsrv_partition_source_dsa *sdsa; 323 sdsa = dreplsrv_find_source_dsa(p, &reps[i].ctr.ctr1.source_dsa_obj_guid); 364 uint32_t replica_flags; 365 sdsa = dreplsrv_find_notify_dsa(p, &reps[i].ctr.ctr1.source_dsa_obj_guid); 366 replica_flags = reps[i].ctr.ctr1.replica_flags; 324 367 if (sdsa == NULL) continue; 325 if (sdsa->notify_uSN < uSN ) {368 if (sdsa->notify_uSN < uSNHighest) { 326 369 /* we need to tell this partner to replicate 327 370 with us */ 328 werr = dreplsrv_schedule_notify_sync(s, p, &reps[i], mem_ctx, uSN); 371 bool is_urgent = sdsa->notify_uSN < uSNUrgent; 372 373 /* check if urgent replication is needed */ 374 werr = dreplsrv_schedule_notify_sync(s, p, &reps[i], mem_ctx, 375 uSNHighest, is_urgent, replica_flags); 329 376 if (!W_ERROR_IS_OK(werr)) { 330 377 DEBUG(0,(__location__ ": Failed to setup notify to %s for %s\n", … … 333 380 return werr; 334 381 } 382 DEBUG(4,("queued DsReplicaSync for %s to %s (urgent=%s) uSN=%llu:%llu\n", 383 ldb_dn_get_linearized(p->dn), 384 reps[i].ctr.ctr1.other_info->dns_name, 385 is_urgent?"true":"false", 386 (unsigned long long)sdsa->notify_uSN, 387 (unsigned long long)uSNHighest)); 335 388 } 336 389 } … … 405 458 406 459 tmp_mem = talloc_new(service); 407 DEBUG( 2,("dreplsrv_notify_schedule(%u) %sscheduled for: %s\n",460 DEBUG(4,("dreplsrv_notify_schedule(%u) %sscheduled for: %s\n", 408 461 next_interval, 409 462 (service->notify.te?"re":""), … … 426 479 427 480 dreplsrv_run_pending_ops(service); 428 dreplsrv_notify_run_ops(service); 429 } 481 } -
vendor/current/source4/dsdb/repl/drepl_out_helpers.c
r414 r740 25 25 #include "smbd/service.h" 26 26 #include "lib/events/events.h" 27 #include "lib/messaging/irpc.h"28 27 #include "dsdb/repl/drepl_service.h" 29 #include "lib/ldb/include/ldb_errors.h"28 #include <ldb_errors.h> 30 29 #include "../lib/util/dlinklist.h" 31 30 #include "librpc/gen_ndr/ndr_misc.h" … … 35 34 #include "auth/gensec/gensec.h" 36 35 #include "param/param.h" 36 #include "../lib/util/tevent_ntstatus.h" 37 #include "libcli/security/security.h" 37 38 38 39 struct dreplsrv_out_drsuapi_state { 39 struct composite_context *creq;40 struct tevent_context *ev; 40 41 41 42 struct dreplsrv_out_connection *conn; … … 47 48 }; 48 49 49 static void dreplsrv_out_drsuapi_connect_recv(struct composite_context *creq); 50 51 struct composite_context *dreplsrv_out_drsuapi_send(struct dreplsrv_out_connection *conn) 52 { 53 struct composite_context *c; 50 static void dreplsrv_out_drsuapi_connect_done(struct composite_context *creq); 51 52 struct tevent_req *dreplsrv_out_drsuapi_send(TALLOC_CTX *mem_ctx, 53 struct tevent_context *ev, 54 struct dreplsrv_out_connection *conn) 55 { 56 struct tevent_req *req; 57 struct dreplsrv_out_drsuapi_state *state; 54 58 struct composite_context *creq; 55 struct dreplsrv_out_drsuapi_state *st; 56 57 c = composite_create(conn, conn->service->task->event_ctx); 58 if (c == NULL) return NULL; 59 60 st = talloc_zero(c, struct dreplsrv_out_drsuapi_state); 61 if (composite_nomem(st, c)) return c; 62 63 c->private_data = st; 64 65 st->creq = c; 66 st->conn = conn; 67 st->drsuapi = conn->drsuapi; 68 69 if (st->drsuapi && !st->drsuapi->pipe->conn->dead) { 70 composite_done(c); 71 return c; 72 } else if (st->drsuapi && st->drsuapi->pipe->conn->dead) { 73 talloc_free(st->drsuapi); 59 60 req = tevent_req_create(mem_ctx, &state, 61 struct dreplsrv_out_drsuapi_state); 62 if (req == NULL) { 63 return NULL; 64 } 65 66 state->ev = ev; 67 state->conn = conn; 68 state->drsuapi = conn->drsuapi; 69 70 if (state->drsuapi && !state->drsuapi->pipe->conn->dead) { 71 tevent_req_done(req); 72 return tevent_req_post(req, ev); 73 } 74 75 if (state->drsuapi && state->drsuapi->pipe->conn->dead) { 76 talloc_free(state->drsuapi); 74 77 conn->drsuapi = NULL; 75 78 } 76 79 77 st->drsuapi = talloc_zero(st, struct dreplsrv_drsuapi_connection); 78 if (composite_nomem(st->drsuapi, c)) return c; 79 80 creq = dcerpc_pipe_connect_b_send(st, conn->binding, &ndr_table_drsuapi, 80 state->drsuapi = talloc_zero(state, struct dreplsrv_drsuapi_connection); 81 if (tevent_req_nomem(state->drsuapi, req)) { 82 return tevent_req_post(req, ev); 83 } 84 85 creq = dcerpc_pipe_connect_b_send(state, conn->binding, &ndr_table_drsuapi, 81 86 conn->service->system_session_info->credentials, 82 c->event_ctx, conn->service->task->lp_ctx); 83 composite_continue(c, creq, dreplsrv_out_drsuapi_connect_recv, st); 84 85 return c; 86 } 87 88 static void dreplsrv_out_drsuapi_bind_send(struct dreplsrv_out_drsuapi_state *st); 89 90 static void dreplsrv_out_drsuapi_connect_recv(struct composite_context *creq) 91 { 92 struct dreplsrv_out_drsuapi_state *st = talloc_get_type(creq->async.private_data, 93 struct dreplsrv_out_drsuapi_state); 94 struct composite_context *c = st->creq; 95 96 c->status = dcerpc_pipe_connect_b_recv(creq, st->drsuapi, &st->drsuapi->pipe); 97 if (!composite_is_ok(c)) return; 98 99 c->status = gensec_session_key(st->drsuapi->pipe->conn->security_state.generic_state, 100 &st->drsuapi->gensec_skey); 101 if (!composite_is_ok(c)) return; 102 103 dreplsrv_out_drsuapi_bind_send(st); 104 } 105 106 static void dreplsrv_out_drsuapi_bind_recv(struct rpc_request *req); 107 108 static void dreplsrv_out_drsuapi_bind_send(struct dreplsrv_out_drsuapi_state *st) 109 { 110 struct composite_context *c = st->creq; 111 struct rpc_request *req; 112 113 st->bind_info_ctr.length = 28; 114 st->bind_info_ctr.info.info28 = st->conn->service->bind_info28; 115 116 st->bind_r.in.bind_guid = &st->conn->service->ntds_guid; 117 st->bind_r.in.bind_info = &st->bind_info_ctr; 118 st->bind_r.out.bind_handle = &st->drsuapi->bind_handle; 119 120 req = dcerpc_drsuapi_DsBind_send(st->drsuapi->pipe, st, &st->bind_r); 121 composite_continue_rpc(c, req, dreplsrv_out_drsuapi_bind_recv, st); 122 } 123 124 static void dreplsrv_out_drsuapi_bind_recv(struct rpc_request *req) 125 { 126 struct dreplsrv_out_drsuapi_state *st = talloc_get_type(req->async.private_data, 127 struct dreplsrv_out_drsuapi_state); 128 struct composite_context *c = st->creq; 129 130 c->status = dcerpc_ndr_request_recv(req); 131 if (!composite_is_ok(c)) return; 132 133 if (!W_ERROR_IS_OK(st->bind_r.out.result)) { 134 composite_error(c, werror_to_ntstatus(st->bind_r.out.result)); 135 return; 136 } 137 138 ZERO_STRUCT(st->drsuapi->remote_info28); 139 if (st->bind_r.out.bind_info) { 140 switch (st->bind_r.out.bind_info->length) { 87 ev, conn->service->task->lp_ctx); 88 if (tevent_req_nomem(creq, req)) { 89 return tevent_req_post(req, ev); 90 } 91 composite_continue(NULL, creq, dreplsrv_out_drsuapi_connect_done, req); 92 93 return req; 94 } 95 96 static void dreplsrv_out_drsuapi_bind_done(struct tevent_req *subreq); 97 98 static void dreplsrv_out_drsuapi_connect_done(struct composite_context *creq) 99 { 100 struct tevent_req *req = talloc_get_type(creq->async.private_data, 101 struct tevent_req); 102 struct dreplsrv_out_drsuapi_state *state = tevent_req_data(req, 103 struct dreplsrv_out_drsuapi_state); 104 NTSTATUS status; 105 struct tevent_req *subreq; 106 107 status = dcerpc_pipe_connect_b_recv(creq, 108 state->drsuapi, 109 &state->drsuapi->pipe); 110 if (tevent_req_nterror(req, status)) { 111 return; 112 } 113 114 state->drsuapi->drsuapi_handle = state->drsuapi->pipe->binding_handle; 115 116 status = gensec_session_key(state->drsuapi->pipe->conn->security_state.generic_state, 117 &state->drsuapi->gensec_skey); 118 if (tevent_req_nterror(req, status)) { 119 return; 120 } 121 122 state->bind_info_ctr.length = 28; 123 state->bind_info_ctr.info.info28 = state->conn->service->bind_info28; 124 125 state->bind_r.in.bind_guid = &state->conn->service->ntds_guid; 126 state->bind_r.in.bind_info = &state->bind_info_ctr; 127 state->bind_r.out.bind_handle = &state->drsuapi->bind_handle; 128 129 subreq = dcerpc_drsuapi_DsBind_r_send(state, 130 state->ev, 131 state->drsuapi->drsuapi_handle, 132 &state->bind_r); 133 if (tevent_req_nomem(subreq, req)) { 134 return; 135 } 136 tevent_req_set_callback(subreq, dreplsrv_out_drsuapi_bind_done, req); 137 } 138 139 static void dreplsrv_out_drsuapi_bind_done(struct tevent_req *subreq) 140 { 141 struct tevent_req *req = tevent_req_callback_data(subreq, 142 struct tevent_req); 143 struct dreplsrv_out_drsuapi_state *state = tevent_req_data(req, 144 struct dreplsrv_out_drsuapi_state); 145 NTSTATUS status; 146 147 status = dcerpc_drsuapi_DsBind_r_recv(subreq, state); 148 TALLOC_FREE(subreq); 149 if (tevent_req_nterror(req, status)) { 150 return; 151 } 152 153 if (!W_ERROR_IS_OK(state->bind_r.out.result)) { 154 status = werror_to_ntstatus(state->bind_r.out.result); 155 tevent_req_nterror(req, status); 156 return; 157 } 158 159 ZERO_STRUCT(state->drsuapi->remote_info28); 160 if (state->bind_r.out.bind_info) { 161 struct drsuapi_DsBindInfo28 *info28; 162 info28 = &state->drsuapi->remote_info28; 163 164 switch (state->bind_r.out.bind_info->length) { 141 165 case 24: { 142 166 struct drsuapi_DsBindInfo24 *info24; 143 info24 = &st->bind_r.out.bind_info->info.info24; 144 st->drsuapi->remote_info28.supported_extensions = info24->supported_extensions; 145 st->drsuapi->remote_info28.site_guid = info24->site_guid; 146 st->drsuapi->remote_info28.pid = info24->pid; 147 st->drsuapi->remote_info28.repl_epoch = 0; 167 info24 = &state->bind_r.out.bind_info->info.info24; 168 169 info28->supported_extensions = info24->supported_extensions; 170 info28->site_guid = info24->site_guid; 171 info28->pid = info24->pid; 172 info28->repl_epoch = 0; 148 173 break; 149 174 } 150 175 case 48: { 151 176 struct drsuapi_DsBindInfo48 *info48; 152 info48 = &st->bind_r.out.bind_info->info.info48; 153 st->drsuapi->remote_info28.supported_extensions = info48->supported_extensions; 154 st->drsuapi->remote_info28.site_guid = info48->site_guid; 155 st->drsuapi->remote_info28.pid = info48->pid; 156 st->drsuapi->remote_info28.repl_epoch = info48->repl_epoch; 177 info48 = &state->bind_r.out.bind_info->info.info48; 178 179 info28->supported_extensions = info48->supported_extensions; 180 info28->site_guid = info48->site_guid; 181 info28->pid = info48->pid; 182 info28->repl_epoch = info48->repl_epoch; 157 183 break; 158 184 } 159 185 case 28: 160 st->drsuapi->remote_info28 = st->bind_r.out.bind_info->info.info28;186 *info28 = state->bind_r.out.bind_info->info.info28; 161 187 break; 162 188 } 163 189 } 164 190 165 composite_done(c); 166 } 167 168 NTSTATUS dreplsrv_out_drsuapi_recv(struct composite_context *c) 169 { 191 tevent_req_done(req); 192 } 193 194 NTSTATUS dreplsrv_out_drsuapi_recv(struct tevent_req *req) 195 { 196 struct dreplsrv_out_drsuapi_state *state = tevent_req_data(req, 197 struct dreplsrv_out_drsuapi_state); 170 198 NTSTATUS status; 171 struct dreplsrv_out_drsuapi_state *st = talloc_get_type(c->private_data, 172 struct dreplsrv_out_drsuapi_state); 173 174 status = composite_wait(c); 175 176 if (NT_STATUS_IS_OK(status)) { 177 st->conn->drsuapi = talloc_steal(st->conn, st->drsuapi); 178 } 179 180 talloc_free(c); 181 return status; 199 200 if (tevent_req_is_nterror(req, &status)) { 201 tevent_req_received(req); 202 return status; 203 } 204 205 state->conn->drsuapi = talloc_move(state->conn, &state->drsuapi); 206 207 tevent_req_received(req); 208 return NT_STATUS_OK; 182 209 } 183 210 184 211 struct dreplsrv_op_pull_source_state { 185 struct composite_context *creq; 186 212 struct tevent_context *ev; 187 213 struct dreplsrv_out_operation *op; 188 189 struct dreplsrv_drsuapi_connection *drsuapi; 190 191 bool have_all; 192 193 uint32_t ctr_level; 194 struct drsuapi_DsGetNCChangesCtr1 *ctr1; 195 struct drsuapi_DsGetNCChangesCtr6 *ctr6; 214 void *ndr_struct_ptr; 196 215 }; 197 216 198 static void dreplsrv_op_pull_source_connect_recv(struct composite_context *creq); 199 200 struct composite_context *dreplsrv_op_pull_source_send(struct dreplsrv_out_operation *op) 201 { 202 struct composite_context *c; 203 struct composite_context *creq; 204 struct dreplsrv_op_pull_source_state *st; 205 206 c = composite_create(op, op->service->task->event_ctx); 207 if (c == NULL) return NULL; 208 209 st = talloc_zero(c, struct dreplsrv_op_pull_source_state); 210 if (composite_nomem(st, c)) return c; 211 212 st->creq = c; 213 st->op = op; 214 215 creq = dreplsrv_out_drsuapi_send(op->source_dsa->conn); 216 composite_continue(c, creq, dreplsrv_op_pull_source_connect_recv, st); 217 218 return c; 219 } 220 221 static void dreplsrv_op_pull_source_get_changes_send(struct dreplsrv_op_pull_source_state *st); 222 223 static void dreplsrv_op_pull_source_connect_recv(struct composite_context *creq) 224 { 225 struct dreplsrv_op_pull_source_state *st = talloc_get_type(creq->async.private_data, 226 struct dreplsrv_op_pull_source_state); 227 struct composite_context *c = st->creq; 228 229 c->status = dreplsrv_out_drsuapi_recv(creq); 230 if (!composite_is_ok(c)) return; 231 232 dreplsrv_op_pull_source_get_changes_send(st); 233 } 234 235 static void dreplsrv_op_pull_source_get_changes_recv(struct rpc_request *req); 236 237 static void dreplsrv_op_pull_source_get_changes_send(struct dreplsrv_op_pull_source_state *st) 238 { 239 struct composite_context *c = st->creq; 240 struct repsFromTo1 *rf1 = st->op->source_dsa->repsFrom1; 241 struct dreplsrv_service *service = st->op->service; 242 struct dreplsrv_partition *partition = st->op->source_dsa->partition; 243 struct dreplsrv_drsuapi_connection *drsuapi = st->op->source_dsa->conn->drsuapi; 244 struct rpc_request *req; 217 static void dreplsrv_op_pull_source_connect_done(struct tevent_req *subreq); 218 219 struct tevent_req *dreplsrv_op_pull_source_send(TALLOC_CTX *mem_ctx, 220 struct tevent_context *ev, 221 struct dreplsrv_out_operation *op) 222 { 223 struct tevent_req *req; 224 struct dreplsrv_op_pull_source_state *state; 225 struct tevent_req *subreq; 226 227 req = tevent_req_create(mem_ctx, &state, 228 struct dreplsrv_op_pull_source_state); 229 if (req == NULL) { 230 return NULL; 231 } 232 state->ev = ev; 233 state->op = op; 234 235 subreq = dreplsrv_out_drsuapi_send(state, ev, op->source_dsa->conn); 236 if (tevent_req_nomem(subreq, req)) { 237 return tevent_req_post(req, ev); 238 } 239 tevent_req_set_callback(subreq, dreplsrv_op_pull_source_connect_done, req); 240 241 return req; 242 } 243 244 static void dreplsrv_op_pull_source_get_changes_trigger(struct tevent_req *req); 245 246 static void dreplsrv_op_pull_source_connect_done(struct tevent_req *subreq) 247 { 248 struct tevent_req *req = tevent_req_callback_data(subreq, 249 struct tevent_req); 250 NTSTATUS status; 251 252 status = dreplsrv_out_drsuapi_recv(subreq); 253 TALLOC_FREE(subreq); 254 if (tevent_req_nterror(req, status)) { 255 return; 256 } 257 258 dreplsrv_op_pull_source_get_changes_trigger(req); 259 } 260 261 static void dreplsrv_op_pull_source_get_changes_done(struct tevent_req *subreq); 262 263 /* 264 get a partial attribute set for a replication call 265 */ 266 static NTSTATUS dreplsrv_get_rodc_partial_attribute_set(struct dreplsrv_service *service, 267 TALLOC_CTX *mem_ctx, 268 struct drsuapi_DsPartialAttributeSet **_pas, 269 bool for_schema) 270 { 271 struct drsuapi_DsPartialAttributeSet *pas; 272 struct dsdb_schema *schema; 273 uint32_t i; 274 275 pas = talloc_zero(mem_ctx, struct drsuapi_DsPartialAttributeSet); 276 NT_STATUS_HAVE_NO_MEMORY(pas); 277 278 schema = dsdb_get_schema(service->samdb, NULL); 279 280 pas->version = 1; 281 pas->attids = talloc_array(pas, enum drsuapi_DsAttributeId, schema->num_attributes); 282 NT_STATUS_HAVE_NO_MEMORY_AND_FREE(pas->attids, pas); 283 284 for (i=0; i<schema->num_attributes; i++) { 285 struct dsdb_attribute *a; 286 a = schema->attributes_by_attributeID_id[i]; 287 if (a->systemFlags & (DS_FLAG_ATTR_NOT_REPLICATED | DS_FLAG_ATTR_IS_CONSTRUCTED)) { 288 continue; 289 } 290 if (a->searchFlags & SEARCH_FLAG_RODC_ATTRIBUTE) { 291 continue; 292 } 293 pas->attids[pas->num_attids] = dsdb_attribute_get_attid(a, for_schema); 294 pas->num_attids++; 295 } 296 *_pas = pas; 297 return NT_STATUS_OK; 298 } 299 300 /* 301 convert from one udv format to the other 302 */ 303 static WERROR udv_convert(TALLOC_CTX *mem_ctx, 304 const struct replUpToDateVectorCtr2 *udv, 305 struct drsuapi_DsReplicaCursorCtrEx *udv_ex) 306 { 307 uint32_t i; 308 309 udv_ex->version = 2; 310 udv_ex->reserved1 = 0; 311 udv_ex->reserved2 = 0; 312 udv_ex->count = udv->count; 313 udv_ex->cursors = talloc_array(mem_ctx, struct drsuapi_DsReplicaCursor, udv->count); 314 W_ERROR_HAVE_NO_MEMORY(udv_ex->cursors); 315 316 for (i=0; i<udv->count; i++) { 317 udv_ex->cursors[i].source_dsa_invocation_id = udv->cursors[i].source_dsa_invocation_id; 318 udv_ex->cursors[i].highest_usn = udv->cursors[i].highest_usn; 319 } 320 321 return WERR_OK; 322 } 323 324 325 static void dreplsrv_op_pull_source_get_changes_trigger(struct tevent_req *req) 326 { 327 struct dreplsrv_op_pull_source_state *state = tevent_req_data(req, 328 struct dreplsrv_op_pull_source_state); 329 struct repsFromTo1 *rf1 = state->op->source_dsa->repsFrom1; 330 struct dreplsrv_service *service = state->op->service; 331 struct dreplsrv_partition *partition = state->op->source_dsa->partition; 332 struct dreplsrv_drsuapi_connection *drsuapi = state->op->source_dsa->conn->drsuapi; 245 333 struct drsuapi_DsGetNCChanges *r; 246 247 r = talloc(st, struct drsuapi_DsGetNCChanges); 248 if (composite_nomem(r, c)) return; 249 250 r->out.level_out = talloc(r, int32_t); 251 if (composite_nomem(r->out.level_out, c)) return; 334 struct drsuapi_DsReplicaCursorCtrEx *uptodateness_vector; 335 struct tevent_req *subreq; 336 struct drsuapi_DsPartialAttributeSet *pas = NULL; 337 NTSTATUS status; 338 uint32_t replica_flags; 339 340 r = talloc(state, struct drsuapi_DsGetNCChanges); 341 if (tevent_req_nomem(r, req)) { 342 return; 343 } 344 345 r->out.level_out = talloc(r, uint32_t); 346 if (tevent_req_nomem(r->out.level_out, req)) { 347 return; 348 } 252 349 r->in.req = talloc(r, union drsuapi_DsGetNCChangesRequest); 253 if (composite_nomem(r->in.req, c)) return; 350 if (tevent_req_nomem(r->in.req, req)) { 351 return; 352 } 254 353 r->out.ctr = talloc(r, union drsuapi_DsGetNCChangesCtr); 255 if (composite_nomem(r->out.ctr, c)) return; 354 if (tevent_req_nomem(r->out.ctr, req)) { 355 return; 356 } 357 358 if (partition->uptodatevector.count != 0 && 359 partition->uptodatevector_ex.count == 0) { 360 WERROR werr; 361 werr = udv_convert(partition, &partition->uptodatevector, &partition->uptodatevector_ex); 362 if (!W_ERROR_IS_OK(werr)) { 363 DEBUG(0,(__location__ ": Failed to convert UDV for %s : %s\n", 364 ldb_dn_get_linearized(partition->dn), win_errstr(werr))); 365 } 366 } 367 368 if (partition->uptodatevector_ex.count == 0) { 369 uptodateness_vector = NULL; 370 } else { 371 uptodateness_vector = &partition->uptodatevector_ex; 372 } 373 374 replica_flags = rf1->replica_flags; 375 376 if (service->am_rodc) { 377 bool for_schema = false; 378 if (ldb_dn_compare_base(ldb_get_schema_basedn(service->samdb), partition->dn) == 0) { 379 for_schema = true; 380 } 381 382 status = dreplsrv_get_rodc_partial_attribute_set(service, r, &pas, for_schema); 383 if (!NT_STATUS_IS_OK(status)) { 384 DEBUG(0,(__location__ ": Failed to construct partial attribute set : %s\n", nt_errstr(status))); 385 return; 386 } 387 if (state->op->extended_op == DRSUAPI_EXOP_REPL_SECRET) { 388 replica_flags &= ~DRSUAPI_DRS_SPECIAL_SECRET_PROCESSING; 389 } 390 } 256 391 257 392 r->in.bind_handle = &drsuapi->bind_handle; … … 262 397 r->in.req->req8.naming_context = &partition->nc; 263 398 r->in.req->req8.highwatermark = rf1->highwatermark; 264 r->in.req->req8.uptodateness_vector = NULL;/*&partition->uptodatevector_ex;*/265 r->in.req->req8.replica_flags = r f1->replica_flags;399 r->in.req->req8.uptodateness_vector = uptodateness_vector; 400 r->in.req->req8.replica_flags = replica_flags; 266 401 r->in.req->req8.max_object_count = 133; 267 402 r->in.req->req8.max_ndr_size = 1336811; 268 r->in.req->req8.extended_op = DRSUAPI_EXOP_NONE;269 r->in.req->req8.fsmo_info = 0;270 r->in.req->req8.partial_attribute_set = NULL;403 r->in.req->req8.extended_op = state->op->extended_op; 404 r->in.req->req8.fsmo_info = state->op->fsmo_info; 405 r->in.req->req8.partial_attribute_set = pas; 271 406 r->in.req->req8.partial_attribute_set_ex= NULL; 272 407 r->in.req->req8.mapping_ctr.num_mappings= 0; … … 278 413 r->in.req->req5.naming_context = &partition->nc; 279 414 r->in.req->req5.highwatermark = rf1->highwatermark; 280 r->in.req->req5.uptodateness_vector = NULL;/*&partition->uptodatevector_ex;*/281 r->in.req->req5.replica_flags = r f1->replica_flags;415 r->in.req->req5.uptodateness_vector = uptodateness_vector; 416 r->in.req->req5.replica_flags = replica_flags; 282 417 r->in.req->req5.max_object_count = 133; 283 418 r->in.req->req5.max_ndr_size = 1336770; 284 r->in.req->req5.extended_op = DRSUAPI_EXOP_NONE; 285 r->in.req->req5.fsmo_info = 0; 286 } 287 288 req = dcerpc_drsuapi_DsGetNCChanges_send(drsuapi->pipe, r, r); 289 composite_continue_rpc(c, req, dreplsrv_op_pull_source_get_changes_recv, st); 290 } 291 292 static void dreplsrv_op_pull_source_apply_changes_send(struct dreplsrv_op_pull_source_state *st, 293 struct drsuapi_DsGetNCChanges *r, 294 uint32_t ctr_level, 295 struct drsuapi_DsGetNCChangesCtr1 *ctr1, 296 struct drsuapi_DsGetNCChangesCtr6 *ctr6); 297 298 static void dreplsrv_op_pull_source_get_changes_recv(struct rpc_request *req) 299 { 300 struct dreplsrv_op_pull_source_state *st = talloc_get_type(req->async.private_data, 301 struct dreplsrv_op_pull_source_state); 302 struct composite_context *c = st->creq; 303 struct drsuapi_DsGetNCChanges *r = talloc_get_type(req->ndr.struct_ptr, 419 r->in.req->req5.extended_op = state->op->extended_op; 420 r->in.req->req5.fsmo_info = state->op->fsmo_info; 421 } 422 423 #if 0 424 NDR_PRINT_IN_DEBUG(drsuapi_DsGetNCChanges, r); 425 #endif 426 427 state->ndr_struct_ptr = r; 428 subreq = dcerpc_drsuapi_DsGetNCChanges_r_send(state, 429 state->ev, 430 drsuapi->drsuapi_handle, 431 r); 432 if (tevent_req_nomem(subreq, req)) { 433 return; 434 } 435 tevent_req_set_callback(subreq, dreplsrv_op_pull_source_get_changes_done, req); 436 } 437 438 static void dreplsrv_op_pull_source_apply_changes_trigger(struct tevent_req *req, 439 struct drsuapi_DsGetNCChanges *r, 440 uint32_t ctr_level, 441 struct drsuapi_DsGetNCChangesCtr1 *ctr1, 442 struct drsuapi_DsGetNCChangesCtr6 *ctr6); 443 444 static void dreplsrv_op_pull_source_get_changes_done(struct tevent_req *subreq) 445 { 446 struct tevent_req *req = tevent_req_callback_data(subreq, 447 struct tevent_req); 448 struct dreplsrv_op_pull_source_state *state = tevent_req_data(req, 449 struct dreplsrv_op_pull_source_state); 450 NTSTATUS status; 451 struct drsuapi_DsGetNCChanges *r = talloc_get_type(state->ndr_struct_ptr, 304 452 struct drsuapi_DsGetNCChanges); 305 453 uint32_t ctr_level = 0; 306 454 struct drsuapi_DsGetNCChangesCtr1 *ctr1 = NULL; 307 455 struct drsuapi_DsGetNCChangesCtr6 *ctr6 = NULL; 308 309 c->status = dcerpc_ndr_request_recv(req); 310 if (!composite_is_ok(c)) return; 456 enum drsuapi_DsExtendedError extended_ret; 457 state->ndr_struct_ptr = NULL; 458 459 status = dcerpc_drsuapi_DsGetNCChanges_r_recv(subreq, r); 460 TALLOC_FREE(subreq); 461 if (tevent_req_nterror(req, status)) { 462 return; 463 } 311 464 312 465 if (!W_ERROR_IS_OK(r->out.result)) { 313 composite_error(c, werror_to_ntstatus(r->out.result)); 466 status = werror_to_ntstatus(r->out.result); 467 tevent_req_nterror(req, status); 314 468 return; 315 469 } … … 338 492 ctr6 = &r->out.ctr->ctr7.ctr.xpress6.ts->ctr6; 339 493 } else { 340 composite_error(c, werror_to_ntstatus(WERR_BAD_NET_RESP)); 494 status = werror_to_ntstatus(WERR_BAD_NET_RESP); 495 tevent_req_nterror(req, status); 341 496 return; 342 497 } 343 498 344 499 if (!ctr1 && !ctr6) { 345 composite_error(c, werror_to_ntstatus(WERR_BAD_NET_RESP)); 500 status = werror_to_ntstatus(WERR_BAD_NET_RESP); 501 tevent_req_nterror(req, status); 346 502 return; 347 503 } … … 349 505 if (ctr_level == 6) { 350 506 if (!W_ERROR_IS_OK(ctr6->drs_error)) { 351 composite_error(c, werror_to_ntstatus(ctr6->drs_error)); 507 status = werror_to_ntstatus(ctr6->drs_error); 508 tevent_req_nterror(req, status); 352 509 return; 353 510 } 354 } 355 356 dreplsrv_op_pull_source_apply_changes_send(st, r, ctr_level, ctr1, ctr6); 357 } 358 359 static void dreplsrv_update_refs_send(struct dreplsrv_op_pull_source_state *st); 360 361 static void dreplsrv_op_pull_source_apply_changes_send(struct dreplsrv_op_pull_source_state *st, 362 struct drsuapi_DsGetNCChanges *r, 363 uint32_t ctr_level, 364 struct drsuapi_DsGetNCChangesCtr1 *ctr1, 365 struct drsuapi_DsGetNCChangesCtr6 *ctr6) 366 { 367 struct composite_context *c = st->creq; 368 struct repsFromTo1 rf1 = *st->op->source_dsa->repsFrom1; 369 struct dreplsrv_service *service = st->op->service; 370 struct dreplsrv_partition *partition = st->op->source_dsa->partition; 371 struct dreplsrv_drsuapi_connection *drsuapi = st->op->source_dsa->conn->drsuapi; 511 extended_ret = ctr6->extended_ret; 512 } 513 514 if (ctr_level == 1) { 515 extended_ret = ctr1->extended_ret; 516 } 517 518 if (state->op->extended_op != DRSUAPI_EXOP_NONE) { 519 state->op->extended_ret = extended_ret; 520 521 if (extended_ret != DRSUAPI_EXOP_ERR_SUCCESS) { 522 status = NT_STATUS_UNSUCCESSFUL; 523 tevent_req_nterror(req, status); 524 return; 525 } 526 } 527 528 dreplsrv_op_pull_source_apply_changes_trigger(req, r, ctr_level, ctr1, ctr6); 529 } 530 531 static void dreplsrv_update_refs_trigger(struct tevent_req *req); 532 533 static void dreplsrv_op_pull_source_apply_changes_trigger(struct tevent_req *req, 534 struct drsuapi_DsGetNCChanges *r, 535 uint32_t ctr_level, 536 struct drsuapi_DsGetNCChangesCtr1 *ctr1, 537 struct drsuapi_DsGetNCChangesCtr6 *ctr6) 538 { 539 struct dreplsrv_op_pull_source_state *state = tevent_req_data(req, 540 struct dreplsrv_op_pull_source_state); 541 struct repsFromTo1 rf1 = *state->op->source_dsa->repsFrom1; 542 struct dreplsrv_service *service = state->op->service; 543 struct dreplsrv_partition *partition = state->op->source_dsa->partition; 544 struct dreplsrv_drsuapi_connection *drsuapi = state->op->source_dsa->conn->drsuapi; 545 struct dsdb_schema *schema; 546 struct dsdb_schema *working_schema = NULL; 372 547 const struct drsuapi_DsReplicaOIDMapping_Ctr *mapping_ctr; 373 548 uint32_t object_count; … … 376 551 struct drsuapi_DsReplicaLinkedAttribute *linked_attributes; 377 552 const struct drsuapi_DsReplicaCursor2CtrEx *uptodateness_vector; 553 struct dsdb_extended_replicated_objects *objects; 378 554 bool more_data = false; 379 555 WERROR status; 556 NTSTATUS nt_status; 380 557 381 558 switch (ctr_level) { … … 401 578 break; 402 579 default: 403 composite_error(c, werror_to_ntstatus(WERR_BAD_NET_RESP)); 404 return; 405 } 406 407 status = dsdb_extended_replicated_objects_commit(service->samdb, 408 partition->nc.dn, 409 mapping_ctr, 410 object_count, 411 first_object, 412 linked_attributes_count, 413 linked_attributes, 414 &rf1, 415 uptodateness_vector, 416 &drsuapi->gensec_skey, 417 st, NULL, 418 &st->op->source_dsa->notify_uSN); 580 nt_status = werror_to_ntstatus(WERR_BAD_NET_RESP); 581 tevent_req_nterror(req, nt_status); 582 return; 583 } 584 585 schema = dsdb_get_schema(service->samdb, NULL); 586 if (!schema) { 587 DEBUG(0,(__location__ ": Schema is not loaded yet!\n")); 588 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR); 589 return; 590 } 591 592 /* 593 * Decide what working schema to use for object conversion. 594 * We won't need a working schema for empty replicas sent. 595 */ 596 if (first_object && ldb_dn_compare(partition->dn, schema->base_dn) == 0) { 597 /* create working schema to convert objects with */ 598 status = dsdb_repl_make_working_schema(service->samdb, 599 schema, 600 mapping_ctr, 601 object_count, 602 first_object, 603 &drsuapi->gensec_skey, 604 state, &working_schema); 605 if (!W_ERROR_IS_OK(status)) { 606 DEBUG(0,("Failed to create working schema: %s\n", 607 win_errstr(status))); 608 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR); 609 return; 610 } 611 } 612 613 status = dsdb_replicated_objects_convert(service->samdb, 614 working_schema ? working_schema : schema, 615 partition->nc.dn, 616 mapping_ctr, 617 object_count, 618 first_object, 619 linked_attributes_count, 620 linked_attributes, 621 &rf1, 622 uptodateness_vector, 623 &drsuapi->gensec_skey, 624 state, &objects); 419 625 if (!W_ERROR_IS_OK(status)) { 420 DEBUG(0,("Failed to commit objects: %s\n", win_errstr(status))); 421 composite_error(c, werror_to_ntstatus(status)); 422 return; 423 } 424 425 /* if it applied fine, we need to update the highwatermark */ 426 *st->op->source_dsa->repsFrom1 = rf1; 427 626 nt_status = werror_to_ntstatus(WERR_BAD_NET_RESP); 627 DEBUG(0,("Failed to convert objects: %s/%s\n", 628 win_errstr(status), nt_errstr(nt_status))); 629 tevent_req_nterror(req, nt_status); 630 return; 631 } 632 633 status = dsdb_replicated_objects_commit(service->samdb, 634 working_schema, 635 objects, 636 &state->op->source_dsa->notify_uSN); 637 talloc_free(objects); 638 if (!W_ERROR_IS_OK(status)) { 639 nt_status = werror_to_ntstatus(WERR_BAD_NET_RESP); 640 DEBUG(0,("Failed to commit objects: %s/%s\n", 641 win_errstr(status), nt_errstr(nt_status))); 642 tevent_req_nterror(req, nt_status); 643 return; 644 } 645 646 if (state->op->extended_op == DRSUAPI_EXOP_NONE) { 647 /* if it applied fine, we need to update the highwatermark */ 648 *state->op->source_dsa->repsFrom1 = rf1; 649 } 428 650 /* 429 651 * TODO: update our uptodatevector! 430 652 */ 431 653 654 /* we don't need this maybe very large structure anymore */ 655 TALLOC_FREE(r); 656 432 657 if (more_data) { 433 dreplsrv_op_pull_source_get_changes_send(st); 658 dreplsrv_op_pull_source_get_changes_trigger(req); 659 return; 660 } 661 662 if (state->op->extended_op != DRSUAPI_EXOP_NONE || 663 state->op->service->am_rodc) { 664 /* 665 we don't do the UpdateRefs for extended ops or if we 666 are a RODC 667 */ 668 tevent_req_done(req); 434 669 return; 435 670 } … … 440 675 so we can use the already established DRSUAPI pipe 441 676 */ 442 dreplsrv_update_refs_send(st); 443 } 444 445 WERROR dreplsrv_op_pull_source_recv(struct composite_context *c) 446 { 447 NTSTATUS status; 448 449 status = composite_wait(c); 450 451 talloc_free(c); 452 return ntstatus_to_werror(status); 453 } 454 455 /* 456 receive a UpdateRefs reply 457 */ 458 static void dreplsrv_update_refs_recv(struct rpc_request *req) 459 { 460 struct dreplsrv_op_pull_source_state *st = talloc_get_type(req->async.private_data, 461 struct dreplsrv_op_pull_source_state); 462 struct composite_context *c = st->creq; 463 struct drsuapi_DsReplicaUpdateRefs *r = talloc_get_type(req->ndr.struct_ptr, 464 struct drsuapi_DsReplicaUpdateRefs); 465 466 c->status = dcerpc_ndr_request_recv(req); 467 if (!composite_is_ok(c)) { 468 DEBUG(0,("UpdateRefs failed with %s\n", 469 nt_errstr(c->status))); 470 return; 471 } 472 473 if (!W_ERROR_IS_OK(r->out.result)) { 474 DEBUG(0,("UpdateRefs failed with %s for %s %s\n", 475 win_errstr(r->out.result), 476 r->in.req.req1.dest_dsa_dns_name, 477 r->in.req.req1.naming_context->dn)); 478 composite_error(c, werror_to_ntstatus(r->out.result)); 479 return; 480 } 481 482 DEBUG(4,("UpdateRefs OK for %s %s\n", 483 r->in.req.req1.dest_dsa_dns_name, 484 r->in.req.req1.naming_context->dn)); 485 486 composite_done(c); 487 } 677 dreplsrv_update_refs_trigger(req); 678 } 679 680 static void dreplsrv_update_refs_done(struct tevent_req *subreq); 488 681 489 682 /* 490 683 send a UpdateRefs request to refresh our repsTo record on the server 491 684 */ 492 static void dreplsrv_update_refs_ send(struct dreplsrv_op_pull_source_state *st)493 { 494 struct composite_context *c = st->creq;495 struct dreplsrv_service *service = st->op->service;496 struct dreplsrv_ partition *partition = st->op->source_dsa->partition;497 struct dreplsrv_ drsuapi_connection *drsuapi = st->op->source_dsa->conn->drsuapi;498 struct rpc_request *req;685 static void dreplsrv_update_refs_trigger(struct tevent_req *req) 686 { 687 struct dreplsrv_op_pull_source_state *state = tevent_req_data(req, 688 struct dreplsrv_op_pull_source_state); 689 struct dreplsrv_service *service = state->op->service; 690 struct dreplsrv_partition *partition = state->op->source_dsa->partition; 691 struct dreplsrv_drsuapi_connection *drsuapi = state->op->source_dsa->conn->drsuapi; 499 692 struct drsuapi_DsReplicaUpdateRefs *r; 500 693 char *ntds_guid_str; 501 694 char *ntds_dns_name; 502 503 r = talloc(st, struct drsuapi_DsReplicaUpdateRefs); 504 if (composite_nomem(r, c)) return; 695 struct tevent_req *subreq; 696 697 r = talloc(state, struct drsuapi_DsReplicaUpdateRefs); 698 if (tevent_req_nomem(r, req)) { 699 return; 700 } 505 701 506 702 ntds_guid_str = GUID_string(r, &service->ntds_guid); 507 if (composite_nomem(ntds_guid_str, c)) return; 508 509 /* lp_realm() is not really right here */ 703 if (tevent_req_nomem(ntds_guid_str, req)) { 704 return; 705 } 706 510 707 ntds_dns_name = talloc_asprintf(r, "%s._msdcs.%s", 511 708 ntds_guid_str, 512 lp_realm(service->task->lp_ctx)); 513 if (composite_nomem(ntds_dns_name, c)) return; 709 lpcfg_dnsdomain(service->task->lp_ctx)); 710 if (tevent_req_nomem(ntds_dns_name, req)) { 711 return; 712 } 514 713 515 714 r->in.bind_handle = &drsuapi->bind_handle; … … 518 717 r->in.req.req1.dest_dsa_dns_name = ntds_dns_name; 519 718 r->in.req.req1.dest_dsa_guid = service->ntds_guid; 520 r->in.req.req1.options = 521 DRSUAPI_DS_REPLICA_UPDATE_ADD_REFERENCE | 522 DRSUAPI_DS_REPLICA_UPDATE_DELETE_REFERENCE; 523 if (!lp_parm_bool(service->task->lp_ctx, NULL, "repl", "RODC", false)) { 524 r->in.req.req1.options |= DRSUAPI_DS_REPLICA_UPDATE_WRITEABLE; 525 } 526 527 req = dcerpc_drsuapi_DsReplicaUpdateRefs_send(drsuapi->pipe, r, r); 528 composite_continue_rpc(c, req, dreplsrv_update_refs_recv, st); 529 } 719 r->in.req.req1.options = DRSUAPI_DRS_ADD_REF | DRSUAPI_DRS_DEL_REF; 720 if (!service->am_rodc) { 721 r->in.req.req1.options |= DRSUAPI_DRS_WRIT_REP; 722 } 723 724 state->ndr_struct_ptr = r; 725 subreq = dcerpc_drsuapi_DsReplicaUpdateRefs_r_send(state, 726 state->ev, 727 drsuapi->drsuapi_handle, 728 r); 729 if (tevent_req_nomem(subreq, req)) { 730 return; 731 } 732 tevent_req_set_callback(subreq, dreplsrv_update_refs_done, req); 733 } 734 735 /* 736 receive a UpdateRefs reply 737 */ 738 static void dreplsrv_update_refs_done(struct tevent_req *subreq) 739 { 740 struct tevent_req *req = tevent_req_callback_data(subreq, 741 struct tevent_req); 742 struct dreplsrv_op_pull_source_state *state = tevent_req_data(req, 743 struct dreplsrv_op_pull_source_state); 744 struct drsuapi_DsReplicaUpdateRefs *r = talloc_get_type(state->ndr_struct_ptr, 745 struct drsuapi_DsReplicaUpdateRefs); 746 NTSTATUS status; 747 748 state->ndr_struct_ptr = NULL; 749 750 status = dcerpc_drsuapi_DsReplicaUpdateRefs_r_recv(subreq, r); 751 TALLOC_FREE(subreq); 752 if (!NT_STATUS_IS_OK(status)) { 753 DEBUG(0,("UpdateRefs failed with %s\n", 754 nt_errstr(status))); 755 tevent_req_nterror(req, status); 756 return; 757 } 758 759 if (!W_ERROR_IS_OK(r->out.result)) { 760 status = werror_to_ntstatus(r->out.result); 761 DEBUG(0,("UpdateRefs failed with %s/%s for %s %s\n", 762 win_errstr(r->out.result), 763 nt_errstr(status), 764 r->in.req.req1.dest_dsa_dns_name, 765 r->in.req.req1.naming_context->dn)); 766 tevent_req_nterror(req, status); 767 return; 768 } 769 770 DEBUG(4,("UpdateRefs OK for %s %s\n", 771 r->in.req.req1.dest_dsa_dns_name, 772 r->in.req.req1.naming_context->dn)); 773 774 tevent_req_done(req); 775 } 776 777 WERROR dreplsrv_op_pull_source_recv(struct tevent_req *req) 778 { 779 NTSTATUS status; 780 781 if (tevent_req_is_nterror(req, &status)) { 782 tevent_req_received(req); 783 return ntstatus_to_werror(status); 784 } 785 786 tevent_req_received(req); 787 return WERR_OK; 788 } 789 -
vendor/current/source4/dsdb/repl/drepl_out_pull.c
r414 r740 25 25 #include "smbd/service.h" 26 26 #include "lib/events/events.h" 27 #include "lib/messaging/irpc.h"28 27 #include "dsdb/repl/drepl_service.h" 29 #include "lib/ldb/include/ldb_errors.h"28 #include <ldb_errors.h> 30 29 #include "../lib/util/dlinklist.h" 31 30 #include "librpc/gen_ndr/ndr_misc.h" … … 33 32 #include "librpc/gen_ndr/ndr_drsblobs.h" 34 33 #include "libcli/composite/composite.h" 35 36 static WERROR dreplsrv_schedule_partition_pull_source(struct dreplsrv_service *s, 37 struct dreplsrv_partition *p, 38 struct dreplsrv_partition_source_dsa *source, 39 TALLOC_CTX *mem_ctx) 34 #include "libcli/security/security.h" 35 36 /* 37 update repsFrom/repsTo error information 38 */ 39 void drepl_reps_update(struct dreplsrv_service *s, const char *reps_attr, 40 struct ldb_dn *dn, 41 struct GUID *source_dsa_obj_guid, WERROR status) 42 { 43 struct repsFromToBlob *reps; 44 uint32_t count, i; 45 WERROR werr; 46 TALLOC_CTX *tmp_ctx = talloc_new(s); 47 time_t t; 48 NTTIME now; 49 50 t = time(NULL); 51 unix_to_nt_time(&now, t); 52 53 werr = dsdb_loadreps(s->samdb, tmp_ctx, dn, reps_attr, &reps, &count); 54 if (!W_ERROR_IS_OK(werr)) { 55 talloc_free(tmp_ctx); 56 return; 57 } 58 59 for (i=0; i<count; i++) { 60 if (GUID_compare(source_dsa_obj_guid, 61 &reps[i].ctr.ctr1.source_dsa_obj_guid) == 0) { 62 break; 63 } 64 } 65 66 if (i == count) { 67 /* no record to update */ 68 talloc_free(tmp_ctx); 69 return; 70 } 71 72 /* only update the status fields */ 73 reps[i].ctr.ctr1.last_attempt = now; 74 reps[i].ctr.ctr1.result_last_attempt = status; 75 if (W_ERROR_IS_OK(status)) { 76 reps[i].ctr.ctr1.last_success = now; 77 reps[i].ctr.ctr1.consecutive_sync_failures = 0; 78 } else { 79 reps[i].ctr.ctr1.consecutive_sync_failures++; 80 } 81 82 werr = dsdb_savereps(s->samdb, tmp_ctx, dn, reps_attr, reps, count); 83 if (!W_ERROR_IS_OK(werr)) { 84 DEBUG(2,("drepl_reps_update: Failed to save %s for %s: %s\n", 85 reps_attr, ldb_dn_get_linearized(dn), win_errstr(werr))); 86 } 87 talloc_free(tmp_ctx); 88 } 89 90 WERROR dreplsrv_schedule_partition_pull_source(struct dreplsrv_service *s, 91 struct dreplsrv_partition_source_dsa *source, 92 uint32_t options, 93 enum drsuapi_DsExtendedOperation extended_op, 94 uint64_t fsmo_info, 95 dreplsrv_extended_callback_t callback, 96 void *cb_data) 40 97 { 41 98 struct dreplsrv_out_operation *op; 42 99 43 op = talloc_zero( mem_ctx, struct dreplsrv_out_operation);100 op = talloc_zero(s, struct dreplsrv_out_operation); 44 101 W_ERROR_HAVE_NO_MEMORY(op); 45 102 46 103 op->service = s; 47 104 op->source_dsa = source; 105 op->options = options; 106 op->extended_op = extended_op; 107 op->fsmo_info = fsmo_info; 108 op->callback = callback; 109 op->cb_data = cb_data; 110 op->schedule_time = time(NULL); 48 111 49 112 DLIST_ADD_END(s->ops.pending, op, struct dreplsrv_out_operation *); 50 talloc_steal(s, op); 113 51 114 return WERR_OK; 52 115 } … … 60 123 61 124 for (cur = p->sources; cur; cur = cur->next) { 62 status = dreplsrv_schedule_partition_pull_source(s, p, cur, mem_ctx); 125 status = dreplsrv_schedule_partition_pull_source(s, cur, 126 0, DRSUAPI_EXOP_NONE, 0, 127 NULL, NULL); 63 128 W_ERROR_NOT_OK_RETURN(status); 64 129 } … … 81 146 82 147 83 /* force an immediate of the specified partition by GUID */ 84 WERROR dreplsrv_schedule_partition_pull_by_guid(struct dreplsrv_service *s, TALLOC_CTX *mem_ctx, 85 struct GUID *guid) 86 { 87 struct dreplsrv_partition *p; 88 89 for (p = s->partitions; p; p = p->next) { 90 if (GUID_compare(&p->nc.guid, guid) == 0) { 91 return dreplsrv_schedule_partition_pull(s, p, mem_ctx); 92 } 93 } 94 95 return WERR_NOT_FOUND; 96 } 97 98 static void dreplsrv_pending_op_callback(struct dreplsrv_out_operation *op) 99 { 148 static void dreplsrv_pending_op_callback(struct tevent_req *subreq) 149 { 150 struct dreplsrv_out_operation *op = tevent_req_callback_data(subreq, 151 struct dreplsrv_out_operation); 100 152 struct repsFromTo1 *rf = op->source_dsa->repsFrom1; 101 153 struct dreplsrv_service *s = op->service; 102 time_t t; 103 NTTIME now; 104 105 t = time(NULL); 106 unix_to_nt_time(&now, t); 107 108 rf->result_last_attempt = dreplsrv_op_pull_source_recv(op->creq); 109 if (W_ERROR_IS_OK(rf->result_last_attempt)) { 110 rf->consecutive_sync_failures = 0; 111 rf->last_success = now; 112 DEBUG(3,("dreplsrv_op_pull_source(%s)\n", 113 win_errstr(rf->result_last_attempt))); 114 goto done; 115 } 116 117 rf->consecutive_sync_failures++; 118 119 DEBUG(1,("dreplsrv_op_pull_source(%s/%s) failures[%u]\n", 120 win_errstr(rf->result_last_attempt), 121 nt_errstr(werror_to_ntstatus(rf->result_last_attempt)), 122 rf->consecutive_sync_failures)); 123 124 done: 154 WERROR werr; 155 156 werr = dreplsrv_op_pull_source_recv(subreq); 157 TALLOC_FREE(subreq); 158 159 DEBUG(4,("dreplsrv_op_pull_source(%s) for %s\n", win_errstr(werr), 160 ldb_dn_get_linearized(op->source_dsa->partition->dn))); 161 162 if (op->extended_op == DRSUAPI_EXOP_NONE) { 163 drepl_reps_update(s, "repsFrom", op->source_dsa->partition->dn, 164 &rf->source_dsa_obj_guid, werr); 165 } 166 167 if (op->callback) { 168 op->callback(s, werr, op->extended_ret, op->cb_data); 169 } 125 170 talloc_free(op); 126 171 s->ops.current = NULL; 127 172 dreplsrv_run_pending_ops(s); 128 dreplsrv_notify_run_ops(s); 129 } 130 131 static void dreplsrv_pending_op_callback_creq(struct composite_context *creq) 132 { 133 struct dreplsrv_out_operation *op = talloc_get_type(creq->async.private_data, 134 struct dreplsrv_out_operation); 135 dreplsrv_pending_op_callback(op); 136 } 137 138 void dreplsrv_run_pending_ops(struct dreplsrv_service *s) 173 } 174 175 void dreplsrv_run_pull_ops(struct dreplsrv_service *s) 139 176 { 140 177 struct dreplsrv_out_operation *op; 141 178 time_t t; 142 179 NTTIME now; 143 144 if (s->ops.current || s->ops.n_current) { 180 struct tevent_req *subreq; 181 WERROR werr; 182 183 if (s->ops.current) { 145 184 /* if there's still one running, we're done */ 146 185 return; … … 161 200 op->source_dsa->repsFrom1->last_attempt = now; 162 201 163 op->creq = dreplsrv_op_pull_source_send(op); 164 if (!op->creq) { 165 dreplsrv_pending_op_callback(op); 166 return; 167 } 168 169 op->creq->async.fn = dreplsrv_pending_op_callback_creq; 170 op->creq->async.private_data = op; 171 } 202 /* check if inbound replication is enabled */ 203 if (!(op->options & DRSUAPI_DRS_SYNC_FORCED)) { 204 uint32_t rep_options; 205 if (samdb_ntds_options(op->service->samdb, &rep_options) != LDB_SUCCESS) { 206 werr = WERR_DS_DRA_INTERNAL_ERROR; 207 goto failed; 208 } 209 210 if ((rep_options & DS_NTDSDSA_OPT_DISABLE_INBOUND_REPL)) { 211 werr = WERR_DS_DRA_SINK_DISABLED; 212 goto failed; 213 } 214 } 215 216 subreq = dreplsrv_op_pull_source_send(op, s->task->event_ctx, op); 217 if (!subreq) { 218 werr = WERR_NOMEM; 219 goto failed; 220 } 221 222 tevent_req_set_callback(subreq, dreplsrv_pending_op_callback, op); 223 return; 224 225 failed: 226 if (op->extended_op == DRSUAPI_EXOP_NONE) { 227 drepl_reps_update(s, "repsFrom", op->source_dsa->partition->dn, 228 &op->source_dsa->repsFrom1->source_dsa_obj_guid, werr); 229 } 230 /* unblock queue processing */ 231 s->ops.current = NULL; 232 /* 233 * let the callback do its job just like in any other failure situation 234 */ 235 if (op->callback) { 236 op->callback(s, werr, op->extended_ret, op->cb_data); 237 } 238 } -
vendor/current/source4/dsdb/repl/drepl_partitions.c
r414 r740 25 25 #include "smbd/service.h" 26 26 #include "lib/events/events.h" 27 #include "lib/messaging/irpc.h"28 27 #include "dsdb/repl/drepl_service.h" 29 #include "lib/ldb/include/ldb_errors.h"28 #include <ldb_errors.h> 30 29 #include "../lib/util/dlinklist.h" 31 30 #include "librpc/gen_ndr/ndr_misc.h" 32 31 #include "librpc/gen_ndr/ndr_drsuapi.h" 33 32 #include "librpc/gen_ndr/ndr_drsblobs.h" 33 #include "libcli/security/security.h" 34 34 #include "param/param.h" 35 35 … … 37 37 { 38 38 WERROR status; 39 struct ldb_dn *basedn; 40 struct ldb_result *r; 39 static const char *attrs[] = { "namingContexts", NULL }; 40 unsigned int i; 41 int ret; 42 TALLOC_CTX *tmp_ctx; 43 struct ldb_result *res; 41 44 struct ldb_message_element *el; 42 static const char *attrs[] = { "namingContexts", NULL }; 43 uint32_t i; 44 int ret; 45 46 basedn = ldb_dn_new(s, s->samdb, NULL); 47 W_ERROR_HAVE_NO_MEMORY(basedn); 48 49 ret = ldb_search(s->samdb, s, &r, basedn, LDB_SCOPE_BASE, attrs, 50 "(objectClass=*)"); 51 talloc_free(basedn); 45 46 tmp_ctx = talloc_new(s); 47 W_ERROR_HAVE_NO_MEMORY(tmp_ctx); 48 49 ret = ldb_search(s->samdb, tmp_ctx, &res, 50 ldb_dn_new(tmp_ctx, s->samdb, ""), LDB_SCOPE_BASE, attrs, NULL); 52 51 if (ret != LDB_SUCCESS) { 53 return WERR_FOOBAR; 54 } else if (r->count != 1) { 55 talloc_free(r); 56 return WERR_FOOBAR; 57 } 58 59 el = ldb_msg_find_element(r->msgs[0], "namingContexts"); 60 if (!el) { 61 return WERR_FOOBAR; 62 } 63 64 for (i=0; el && i < el->num_values; i++) { 65 const char *v = (const char *)el->values[i].data; 66 struct ldb_dn *pdn; 67 struct dreplsrv_partition *p; 68 69 pdn = ldb_dn_new(s, s->samdb, v); 70 if (!ldb_dn_validate(pdn)) { 71 return WERR_FOOBAR; 72 } 73 74 p = talloc_zero(s, struct dreplsrv_partition); 75 W_ERROR_HAVE_NO_MEMORY(p); 76 77 p->dn = talloc_steal(p, pdn); 78 79 DLIST_ADD(s->partitions, p); 80 81 DEBUG(2, ("dreplsrv_partition[%s] loaded\n", v)); 82 } 83 84 talloc_free(r); 52 DEBUG(1,("Searching for namingContexts in rootDSE failed: %s\n", ldb_errstring(s->samdb))); 53 talloc_free(tmp_ctx); 54 return WERR_DS_DRA_INTERNAL_ERROR; 55 } 56 57 el = ldb_msg_find_element(res->msgs[0], "namingContexts"); 58 if (!el) { 59 DEBUG(1,("Finding namingContexts element in root_res failed: %s\n", 60 ldb_errstring(s->samdb))); 61 talloc_free(tmp_ctx); 62 return WERR_DS_DRA_INTERNAL_ERROR; 63 } 64 65 for (i=0; i<el->num_values; i++) { 66 struct ldb_dn *pdn; 67 struct dreplsrv_partition *p; 68 69 pdn = ldb_dn_from_ldb_val(tmp_ctx, s->samdb, &el->values[i]); 70 if (pdn == NULL) { 71 talloc_free(tmp_ctx); 72 return WERR_DS_DRA_INTERNAL_ERROR; 73 } 74 if (!ldb_dn_validate(pdn)) { 75 return WERR_DS_DRA_INTERNAL_ERROR; 76 } 77 78 p = talloc_zero(s, struct dreplsrv_partition); 79 W_ERROR_HAVE_NO_MEMORY(p); 80 81 p->dn = talloc_steal(p, pdn); 82 83 DLIST_ADD(s->partitions, p); 84 85 DEBUG(2, ("dreplsrv_partition[%s] loaded\n", ldb_dn_get_linearized(p->dn))); 86 } 87 88 talloc_free(tmp_ctx); 85 89 86 90 status = dreplsrv_refresh_partitions(s); … … 90 94 } 91 95 92 static WERROR dreplsrv_out_connection_attach(struct dreplsrv_service *s, 93 const struct repsFromTo1 *rft, 94 struct dreplsrv_out_connection **_conn) 96 /* 97 work out the principal to use for DRS replication connections 98 */ 99 NTSTATUS dreplsrv_get_target_principal(struct dreplsrv_service *s, 100 TALLOC_CTX *mem_ctx, 101 const struct repsFromTo1 *rft, 102 const char **target_principal) 103 { 104 TALLOC_CTX *tmp_ctx; 105 struct ldb_result *res; 106 const char *attrs[] = { "dNSHostName", NULL }; 107 int ret; 108 const char *hostname; 109 struct ldb_dn *dn; 110 111 *target_principal = NULL; 112 113 tmp_ctx = talloc_new(mem_ctx); 114 115 /* we need to find their hostname */ 116 ret = dsdb_find_dn_by_guid(s->samdb, tmp_ctx, &rft->source_dsa_obj_guid, &dn); 117 if (ret != LDB_SUCCESS) { 118 talloc_free(tmp_ctx); 119 /* its OK for their NTDSDSA DN not to be in our database */ 120 return NT_STATUS_OK; 121 } 122 123 /* strip off the NTDS Settings */ 124 if (!ldb_dn_remove_child_components(dn, 1)) { 125 talloc_free(tmp_ctx); 126 return NT_STATUS_OK; 127 } 128 129 ret = dsdb_search_dn(s->samdb, tmp_ctx, &res, dn, attrs, 0); 130 if (ret != LDB_SUCCESS) { 131 talloc_free(tmp_ctx); 132 /* its OK for their account DN not to be in our database */ 133 return NT_STATUS_OK; 134 } 135 136 hostname = ldb_msg_find_attr_as_string(res->msgs[0], "dNSHostName", NULL); 137 if (hostname == NULL) { 138 talloc_free(tmp_ctx); 139 /* its OK to not have a dnshostname */ 140 return NT_STATUS_OK; 141 } 142 143 /* All DCs have the GC/hostname/realm name, but if some of the 144 * preconditions are not satisfied, then we will fall back to 145 * the 146 * E3514235-4B06-11D1-AB04-00C04FC2DCD2/${NTDSGUID}/${DNSDOMAIN} 147 * name. This means that if a AD server has a dnsHostName set 148 * on it's record, it must also have GC/hostname/realm 149 * servicePrincipalName */ 150 151 *target_principal = talloc_asprintf(mem_ctx, "GC/%s/%s", 152 hostname, 153 lpcfg_dnsdomain(s->task->lp_ctx)); 154 talloc_free(tmp_ctx); 155 return NT_STATUS_OK; 156 } 157 158 159 WERROR dreplsrv_out_connection_attach(struct dreplsrv_service *s, 160 const struct repsFromTo1 *rft, 161 struct dreplsrv_out_connection **_conn) 95 162 { 96 163 struct dreplsrv_out_connection *cur, *conn = NULL; … … 132 199 } 133 200 201 /* use the GC principal for DRS replication */ 202 nt_status = dreplsrv_get_target_principal(s, conn->binding, 203 rft, &conn->binding->target_principal); 204 if (!NT_STATUS_IS_OK(nt_status)) { 205 return ntstatus_to_werror(nt_status); 206 } 207 134 208 DLIST_ADD_END(s->connections, conn, struct dreplsrv_out_connection *); 135 209 136 DEBUG( 2,("dreplsrv_out_connection_attach(%s): create\n", conn->binding->host));210 DEBUG(4,("dreplsrv_out_connection_attach(%s): create\n", conn->binding->host)); 137 211 } else { 138 DEBUG( 2,("dreplsrv_out_connection_attach(%s): attach\n", conn->binding->host));212 DEBUG(4,("dreplsrv_out_connection_attach(%s): attach\n", conn->binding->host)); 139 213 } 140 214 … … 143 217 } 144 218 219 /* 220 find an existing source dsa in a list 221 */ 222 static struct dreplsrv_partition_source_dsa *dreplsrv_find_source_dsa(struct dreplsrv_partition_source_dsa *list, 223 struct GUID *guid) 224 { 225 struct dreplsrv_partition_source_dsa *s; 226 for (s=list; s; s=s->next) { 227 if (GUID_compare(&s->repsFrom1->source_dsa_obj_guid, guid) == 0) { 228 return s; 229 } 230 } 231 return NULL; 232 } 233 234 235 145 236 static WERROR dreplsrv_partition_add_source_dsa(struct dreplsrv_service *s, 146 237 struct dreplsrv_partition *p, 238 struct dreplsrv_partition_source_dsa **listp, 239 struct dreplsrv_partition_source_dsa *check_list, 147 240 const struct ldb_val *val) 148 241 { … … 155 248 156 249 ndr_err = ndr_pull_struct_blob(val, source, 157 lp_iconv_convenience(s->task->lp_ctx),&source->_repsFromBlob,250 &source->_repsFromBlob, 158 251 (ndr_pull_flags_fn_t)ndr_pull_repsFromToBlob); 159 252 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { … … 174 267 W_ERROR_NOT_OK_RETURN(status); 175 268 176 /* remove any existing source with the same GUID */ 177 for (s2=p->sources; s2; s2=s2->next) { 269 if (check_list && 270 dreplsrv_find_source_dsa(check_list, &source->repsFrom1->source_dsa_obj_guid)) { 271 /* its in the check list, don't add it again */ 272 talloc_free(source); 273 return WERR_OK; 274 } 275 276 /* re-use an existing source if found */ 277 for (s2=*listp; s2; s2=s2->next) { 178 278 if (GUID_compare(&s2->repsFrom1->source_dsa_obj_guid, 179 279 &source->repsFrom1->source_dsa_obj_guid) == 0) { … … 186 286 } 187 287 188 DLIST_ADD_END( p->sources, source, struct dreplsrv_partition_source_dsa *);288 DLIST_ADD_END(*listp, source, struct dreplsrv_partition_source_dsa *); 189 289 return WERR_OK; 190 290 } 291 292 WERROR dreplsrv_partition_find_for_nc(struct dreplsrv_service *s, 293 const struct GUID *nc_guid, 294 const struct dom_sid *nc_sid, 295 const char *nc_dn_str, 296 struct dreplsrv_partition **_p) 297 { 298 struct dreplsrv_partition *p; 299 bool valid_sid, valid_guid; 300 struct dom_sid null_sid; 301 ZERO_STRUCT(null_sid); 302 303 SMB_ASSERT(_p); 304 305 valid_sid = nc_sid && !dom_sid_equal(&null_sid, nc_sid); 306 valid_guid = nc_guid && !GUID_all_zero(nc_guid); 307 308 if (!valid_sid && !valid_guid && !nc_dn_str) { 309 return WERR_DS_DRA_INVALID_PARAMETER; 310 } 311 312 for (p = s->partitions; p; p = p->next) { 313 if ((valid_guid && GUID_equal(&p->nc.guid, nc_guid)) 314 || strequal(p->nc.dn, nc_dn_str) 315 || (valid_sid && dom_sid_equal(&p->nc.sid, nc_sid))) 316 { 317 *_p = p; 318 return WERR_OK; 319 } 320 } 321 322 return WERR_DS_DRA_BAD_NC; 323 } 324 325 WERROR dreplsrv_partition_source_dsa_by_guid(struct dreplsrv_partition *p, 326 const struct GUID *dsa_guid, 327 struct dreplsrv_partition_source_dsa **_dsa) 328 { 329 struct dreplsrv_partition_source_dsa *dsa; 330 331 SMB_ASSERT(dsa_guid != NULL); 332 SMB_ASSERT(!GUID_all_zero(dsa_guid)); 333 SMB_ASSERT(_dsa); 334 335 for (dsa = p->sources; dsa; dsa = dsa->next) { 336 if (GUID_equal(dsa_guid, &dsa->repsFrom1->source_dsa_obj_guid)) { 337 *_dsa = dsa; 338 return WERR_OK; 339 } 340 } 341 342 return WERR_DS_DRA_NO_REPLICA; 343 } 344 345 WERROR dreplsrv_partition_source_dsa_by_dns(const struct dreplsrv_partition *p, 346 const char *dsa_dns, 347 struct dreplsrv_partition_source_dsa **_dsa) 348 { 349 struct dreplsrv_partition_source_dsa *dsa; 350 351 SMB_ASSERT(dsa_dns != NULL); 352 SMB_ASSERT(_dsa); 353 354 for (dsa = p->sources; dsa; dsa = dsa->next) { 355 if (strequal(dsa_dns, dsa->repsFrom1->other_info->dns_name)) { 356 *_dsa = dsa; 357 return WERR_OK; 358 } 359 } 360 361 return WERR_DS_DRA_NO_REPLICA; 362 } 363 191 364 192 365 static WERROR dreplsrv_refresh_partition(struct dreplsrv_service *s, … … 194 367 { 195 368 WERROR status; 196 const struct ldb_val *ouv_value;197 struct replUpToDateVectorBlob ouv;198 369 struct dom_sid *nc_sid; 199 370 struct ldb_message_element *orf_el = NULL; 200 371 struct ldb_result *r; 201 u int32_t i;372 unsigned int i; 202 373 int ret; 203 374 TALLOC_CTX *mem_ctx = talloc_new(p); … … 205 376 "objectSid", 206 377 "objectGUID", 207 "replUpToDateVector",208 378 "repsFrom", 379 "repsTo", 209 380 NULL 210 381 }; 211 382 212 DEBUG( 2, ("dreplsrv_refresh_partition(%s)\n",383 DEBUG(4, ("dreplsrv_refresh_partition(%s)\n", 213 384 ldb_dn_get_linearized(p->dn))); 214 385 … … 216 387 "(objectClass=*)"); 217 388 if (ret != LDB_SUCCESS) { 218 talloc_free(mem_ctx);219 return WERR_FOOBAR;220 } else if (r->count != 1) {221 389 talloc_free(mem_ctx); 222 390 return WERR_FOOBAR; … … 234 402 } 235 403 236 ouv_value = ldb_msg_find_ldb_val(r->msgs[0], "replUpToDateVector"); 237 if (ouv_value) { 238 enum ndr_err_code ndr_err; 239 ndr_err = ndr_pull_struct_blob(ouv_value, mem_ctx, 240 lp_iconv_convenience(s->task->lp_ctx), &ouv, 241 (ndr_pull_flags_fn_t)ndr_pull_replUpToDateVectorBlob); 242 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { 243 NTSTATUS nt_status = ndr_map_error2ntstatus(ndr_err); 244 talloc_free(mem_ctx); 245 return ntstatus_to_werror(nt_status); 246 } 247 /* NDR_PRINT_DEBUG(replUpToDateVectorBlob, &ouv); */ 248 if (ouv.version != 2) { 249 talloc_free(mem_ctx); 250 return WERR_DS_DRA_INTERNAL_ERROR; 251 } 252 253 p->uptodatevector.count = ouv.ctr.ctr2.count; 254 p->uptodatevector.reserved = ouv.ctr.ctr2.reserved; 255 talloc_free(p->uptodatevector.cursors); 256 p->uptodatevector.cursors = talloc_steal(p, ouv.ctr.ctr2.cursors); 257 } 258 259 /* 260 * TODO: add our own uptodatevector cursor 261 */ 262 404 talloc_free(p->uptodatevector.cursors); 405 talloc_free(p->uptodatevector_ex.cursors); 406 ZERO_STRUCT(p->uptodatevector); 407 ZERO_STRUCT(p->uptodatevector_ex); 408 409 ret = dsdb_load_udv_v2(s->samdb, p->dn, p, &p->uptodatevector.cursors, &p->uptodatevector.count); 410 if (ret != LDB_SUCCESS) { 411 DEBUG(4,(__location__ ": no UDV available for %s\n", ldb_dn_get_linearized(p->dn))); 412 } 263 413 264 414 orf_el = ldb_msg_find_element(r->msgs[0], "repsFrom"); 265 415 if (orf_el) { 266 416 for (i=0; i < orf_el->num_values; i++) { 267 status = dreplsrv_partition_add_source_dsa(s, p, &orf_el->values[i]); 417 status = dreplsrv_partition_add_source_dsa(s, p, &p->sources, 418 NULL, &orf_el->values[i]); 419 W_ERROR_NOT_OK_RETURN(status); 420 } 421 } 422 423 orf_el = ldb_msg_find_element(r->msgs[0], "repsTo"); 424 if (orf_el) { 425 for (i=0; i < orf_el->num_values; i++) { 426 status = dreplsrv_partition_add_source_dsa(s, p, &p->notifies, 427 p->sources, &orf_el->values[i]); 268 428 W_ERROR_NOT_OK_RETURN(status); 269 429 } -
vendor/current/source4/dsdb/repl/drepl_periodic.c
r414 r740 25 25 #include "auth/auth.h" 26 26 #include "smbd/service.h" 27 #include "lib/messaging/irpc.h"28 27 #include "dsdb/repl/drepl_service.h" 29 #include "lib/ldb/include/ldb_errors.h"28 #include <ldb_errors.h> 30 29 #include "../lib/util/dlinklist.h" 31 30 #include "librpc/gen_ndr/ndr_misc.h" … … 82 81 83 82 tmp_mem = talloc_new(service); 84 DEBUG( 2,("dreplsrv_periodic_schedule(%u) %sscheduled for: %s\n",83 DEBUG(4,("dreplsrv_periodic_schedule(%u) %sscheduled for: %s\n", 85 84 next_interval, 86 85 (service->periodic.te?"re":""), … … 98 97 TALLOC_CTX *mem_ctx; 99 98 100 DEBUG(2,("dreplsrv_periodic_run(): schedule pull replication\n")); 99 DEBUG(4,("dreplsrv_periodic_run(): schedule pull replication\n")); 100 101 /* 102 * KCC or some administrative tool 103 * might have changed Topology graph 104 * i.e. repsFrom/repsTo 105 */ 106 dreplsrv_refresh_partitions(service); 101 107 102 108 mem_ctx = talloc_new(service); … … 104 110 talloc_free(mem_ctx); 105 111 106 DEBUG( 2,("dreplsrv_periodic_run(): run pending_ops memory=%u\n",112 DEBUG(4,("dreplsrv_periodic_run(): run pending_ops memory=%u\n", 107 113 (unsigned)talloc_total_blocks(service))); 108 114 109 /* the KCC might have changed repsFrom */ 110 dreplsrv_refresh_partitions(service); 115 dreplsrv_ridalloc_check_rid_pool(service); 111 116 112 117 dreplsrv_run_pending_ops(service); 113 dreplsrv_notify_run_ops(service);114 118 } 119 120 /* 121 run the next pending op, either a notify or a pull 122 */ 123 void dreplsrv_run_pending_ops(struct dreplsrv_service *s) 124 { 125 if (!s->ops.notifies && !s->ops.pending) { 126 return; 127 } 128 if (!s->ops.notifies || 129 (s->ops.pending && 130 s->ops.notifies->schedule_time > s->ops.pending->schedule_time)) { 131 dreplsrv_run_pull_ops(s); 132 } else { 133 dreplsrv_notify_run_ops(s); 134 } 135 } -
vendor/current/source4/dsdb/repl/drepl_service.c
r414 r740 1 /* 1 /* 2 2 Unix SMB/CIFS mplementation. 3 3 DSDB replication service 4 4 5 5 Copyright (C) Stefan Metzmacher 2007 6 6 Copyright (C) Kamen Mazdrashki <kamenim@samba.org> 2010 7 7 8 This program is free software; you can redistribute it and/or modify 8 9 it under the terms of the GNU General Public License as published by 9 10 the Free Software Foundation; either version 3 of the License, or 10 11 (at your option) any later version. 11 12 12 13 This program is distributed in the hope that it will be useful, 13 14 but WITHOUT ANY WARRANTY; without even the implied warranty of 14 15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 16 GNU General Public License for more details. 16 17 17 18 You should have received a copy of the GNU General Public License 18 19 along with this program. If not, see <http://www.gnu.org/licenses/>. 19 20 20 21 */ 21 22 … … 25 26 #include "smbd/service.h" 26 27 #include "lib/events/events.h" 27 #include "lib/messaging/irpc.h"28 28 #include "dsdb/repl/drepl_service.h" 29 #include "lib/ldb/include/ldb_errors.h"29 #include <ldb_errors.h> 30 30 #include "../lib/util/dlinklist.h" 31 31 #include "librpc/gen_ndr/ndr_misc.h" 32 32 #include "librpc/gen_ndr/ndr_drsuapi.h" 33 33 #include "librpc/gen_ndr/ndr_drsblobs.h" 34 #include "librpc/gen_ndr/ndr_irpc.h" 34 35 #include "param/param.h" 35 36 37 /** 38 * Call-back data for _drepl_replica_sync_done_cb() 39 */ 40 struct drepl_replica_sync_cb_data { 41 struct irpc_message *msg; 42 struct drsuapi_DsReplicaSync *r; 43 44 /* number of ops left to be completed */ 45 int ops_count; 46 47 /* last failure error code */ 48 WERROR werr_last_failure; 49 }; 50 51 36 52 static WERROR dreplsrv_init_creds(struct dreplsrv_service *service) 37 53 { 38 NTSTATUS status; 39 40 status = auth_system_session_info(service, service->task->lp_ctx, 41 &service->system_session_info); 42 if (!NT_STATUS_IS_OK(status)) { 43 return ntstatus_to_werror(status); 54 service->system_session_info = system_session(service->task->lp_ctx); 55 if (service->system_session_info == NULL) { 56 return WERR_NOMEM; 44 57 } 45 58 … … 52 65 struct drsuapi_DsBindInfo28 *bind_info28; 53 66 54 service->samdb = samdb_connect(service, service->task->event_ctx, lp_ctx, service->system_session_info );67 service->samdb = samdb_connect(service, service->task->event_ctx, lp_ctx, service->system_session_info, 0); 55 68 if (!service->samdb) { 56 69 return WERR_DS_UNAVAILABLE; … … 61 74 return WERR_DS_UNAVAILABLE; 62 75 } 63 64 76 service->ntds_guid = *ntds_guid; 77 78 if (samdb_rodc(service->samdb, &service->am_rodc) != LDB_SUCCESS) { 79 DEBUG(0,(__location__ ": Failed to determine RODC status\n")); 80 return WERR_DS_UNAVAILABLE; 81 } 65 82 66 83 bind_info28 = &service->bind_info28; … … 84 101 bind_info28->supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_ADD_SID_HISTORY; 85 102 bind_info28->supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_POST_BETA3; 86 bind_info28->supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_ 00100000;103 bind_info28->supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_GETCHGREQ_V5; 87 104 bind_info28->supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_GET_MEMBERSHIPS2; 88 105 bind_info28->supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_GETCHGREQ_V6; … … 106 123 } 107 124 125 126 /** 127 * Callback for dreplsrv_out_operation operation completion. 128 * 129 * We just need to complete a waiting IRPC message here. 130 * In case pull operation has failed, 131 * caller of this callback will dump 132 * failure information. 133 * 134 * NOTE: cb_data is allocated in IRPC msg's context 135 * and will be freed during irpc_send_reply() call. 136 */ 137 static void _drepl_replica_sync_done_cb(struct dreplsrv_service *service, 138 WERROR werr, 139 enum drsuapi_DsExtendedError ext_err, 140 void *cb_data) 141 { 142 struct drepl_replica_sync_cb_data *data = talloc_get_type(cb_data, 143 struct drepl_replica_sync_cb_data); 144 struct irpc_message *msg = data->msg; 145 struct drsuapi_DsReplicaSync *r = data->r; 146 147 /* store last bad result */ 148 if (!W_ERROR_IS_OK(werr)) { 149 data->werr_last_failure = werr; 150 } 151 152 /* decrement pending ops count */ 153 data->ops_count--; 154 155 if (data->ops_count == 0) { 156 /* Return result to client */ 157 r->out.result = data->werr_last_failure; 158 159 /* complete IRPC message */ 160 irpc_send_reply(msg, NT_STATUS_OK); 161 } 162 } 163 164 /** 165 * Helper to schedule a replication operation with a source DSA. 166 * If 'data' is valid pointer, then a callback 167 * for the operation is passed and 'data->msg' is 168 * marked as 'deferred' - defer_reply = true 169 */ 170 static WERROR _drepl_schedule_replication(struct dreplsrv_service *service, 171 struct dreplsrv_partition_source_dsa *dsa, 172 struct drsuapi_DsReplicaObjectIdentifier *nc, 173 uint32_t rep_options, 174 struct drepl_replica_sync_cb_data *data, 175 TALLOC_CTX *mem_ctx) 176 { 177 WERROR werr; 178 dreplsrv_extended_callback_t fn_callback = NULL; 179 180 if (data) { 181 fn_callback = _drepl_replica_sync_done_cb; 182 } 183 184 /* schedule replication item */ 185 werr = dreplsrv_schedule_partition_pull_source(service, dsa, rep_options, 186 DRSUAPI_EXOP_NONE, 0, 187 fn_callback, data); 188 if (!W_ERROR_IS_OK(werr)) { 189 DEBUG(0,("%s: failed setup of sync of partition (%s, %s, %s) - %s\n", 190 __FUNCTION__, 191 GUID_string(mem_ctx, &nc->guid), 192 nc->dn, 193 dsa->repsFrom1->other_info->dns_name, 194 win_errstr(werr))); 195 return werr; 196 } 197 /* log we've scheduled a replication item */ 198 DEBUG(3,("%s: forcing sync of partition (%s, %s, %s)\n", 199 __FUNCTION__, 200 GUID_string(mem_ctx, &nc->guid), 201 nc->dn, 202 dsa->repsFrom1->other_info->dns_name)); 203 204 /* mark IRPC message as deferred if necessary */ 205 if (data) { 206 data->ops_count++; 207 data->msg->defer_reply = true; 208 } 209 210 return WERR_OK; 211 } 212 108 213 /* 109 214 DsReplicaSync messages from the DRSUAPI server are forwarded here 110 215 */ 111 static NTSTATUS drepl_replica_sync(struct irpc_message *msg, 216 static NTSTATUS drepl_replica_sync(struct irpc_message *msg, 112 217 struct drsuapi_DsReplicaSync *r) 113 218 { 219 WERROR werr; 220 struct dreplsrv_partition *p; 221 struct drepl_replica_sync_cb_data *cb_data; 222 struct dreplsrv_partition_source_dsa *dsa; 223 struct drsuapi_DsReplicaSyncRequest1 *req1; 224 struct drsuapi_DsReplicaObjectIdentifier *nc; 114 225 struct dreplsrv_service *service = talloc_get_type(msg->private_data, 115 226 struct dreplsrv_service); 116 struct GUID *guid = &r->in.req.req1.naming_context->guid; 117 118 r->out.result = dreplsrv_schedule_partition_pull_by_guid(service, msg, guid); 119 if (W_ERROR_IS_OK(r->out.result)) { 120 DEBUG(3,("drepl_replica_sync: forcing sync of partition %s\n", 121 GUID_string(msg, guid))); 122 dreplsrv_run_pending_ops(service); 227 228 #define REPLICA_SYNC_FAIL(_msg, _werr) do {\ 229 if (!W_ERROR_IS_OK(_werr)) { \ 230 DEBUG(0,(__location__ ": Failure - %s. werr = %s\n", \ 231 _msg, win_errstr(_werr))); \ 232 NDR_PRINT_IN_DEBUG(drsuapi_DsReplicaSync, r); \ 233 } \ 234 r->out.result = _werr; \ 235 goto done;\ 236 } while(0) 237 238 239 if (r->in.level != 1) { 240 REPLICA_SYNC_FAIL("Unsupported level", 241 WERR_DS_DRA_INVALID_PARAMETER); 242 } 243 244 req1 = &r->in.req->req1; 245 nc = req1->naming_context; 246 247 /* Check input parameters */ 248 if (!nc) { 249 REPLICA_SYNC_FAIL("Invalid Naming Context", 250 WERR_DS_DRA_INVALID_PARAMETER); 251 } 252 253 /* Find Naming context to be synchronized */ 254 werr = dreplsrv_partition_find_for_nc(service, 255 &nc->guid, &nc->sid, nc->dn, 256 &p); 257 if (!W_ERROR_IS_OK(werr)) { 258 REPLICA_SYNC_FAIL("Failed to find requested Naming Context", 259 werr); 260 } 261 262 /* should we process it asynchronously? */ 263 if (req1->options & DRSUAPI_DRS_ASYNC_OP) { 264 cb_data = NULL; 123 265 } else { 124 DEBUG(3,("drepl_replica_sync: failed setup of sync of partition %s - %s\n", 125 GUID_string(msg, guid), win_errstr(r->out.result))); 126 } 266 cb_data = talloc_zero(msg, struct drepl_replica_sync_cb_data); 267 if (!cb_data) { 268 REPLICA_SYNC_FAIL("Not enought memory", 269 WERR_DS_DRA_INTERNAL_ERROR); 270 } 271 272 cb_data->msg = msg; 273 cb_data->r = r; 274 cb_data->werr_last_failure = WERR_OK; 275 } 276 277 /* collect source DSAs to sync with */ 278 if (req1->options & DRSUAPI_DRS_SYNC_ALL) { 279 for (dsa = p->sources; dsa; dsa = dsa->next) { 280 /* schedule replication item */ 281 werr = _drepl_schedule_replication(service, dsa, nc, 282 req1->options, cb_data, msg); 283 if (!W_ERROR_IS_OK(werr)) { 284 REPLICA_SYNC_FAIL("_drepl_schedule_replication() failed", 285 werr); 286 } 287 } 288 } else { 289 if (req1->options & DRSUAPI_DRS_SYNC_BYNAME) { 290 /* client should pass at least valid string */ 291 if (!req1->source_dsa_dns) { 292 REPLICA_SYNC_FAIL("'source_dsa_dns' is not valid", 293 WERR_DS_DRA_INVALID_PARAMETER); 294 } 295 296 werr = dreplsrv_partition_source_dsa_by_dns(p, 297 req1->source_dsa_dns, 298 &dsa); 299 } else { 300 /* client should pass at least some GUID */ 301 if (GUID_all_zero(&req1->source_dsa_guid)) { 302 REPLICA_SYNC_FAIL("'source_dsa_guid' is not valid", 303 WERR_DS_DRA_INVALID_PARAMETER); 304 } 305 306 werr = dreplsrv_partition_source_dsa_by_guid(p, 307 &req1->source_dsa_guid, 308 &dsa); 309 } 310 if (!W_ERROR_IS_OK(werr)) { 311 REPLICA_SYNC_FAIL("Failed to locate source DSA for given NC", 312 werr); 313 } 314 315 /* schedule replication item */ 316 werr = _drepl_schedule_replication(service, dsa, nc, 317 req1->options, cb_data, msg); 318 if (!W_ERROR_IS_OK(werr)) { 319 REPLICA_SYNC_FAIL("_drepl_schedule_replication() failed", 320 werr); 321 } 322 } 323 324 /* if we got here, everything is OK */ 325 r->out.result = WERR_OK; 326 327 /* 328 * schedule replication event to force 329 * replication as soon as possible 330 */ 331 dreplsrv_periodic_schedule(service, 0); 332 333 done: 127 334 return NT_STATUS_OK; 128 335 } 336 337 /** 338 * Called when drplsrv should refresh its state. 339 * For example, when KCC change topology, dreplsrv 340 * should update its cache 341 * 342 * @param partition_dn If not empty/NULL, partition to update 343 */ 344 static NTSTATUS dreplsrv_refresh(struct irpc_message *msg, 345 struct dreplsrv_refresh *r) 346 { 347 struct dreplsrv_service *s = talloc_get_type(msg->private_data, 348 struct dreplsrv_service); 349 350 r->out.result = dreplsrv_refresh_partitions(s); 351 352 return NT_STATUS_OK; 353 } 354 355 static NTSTATUS drepl_take_FSMO_role(struct irpc_message *msg, 356 struct drepl_takeFSMORole *r) 357 { 358 struct dreplsrv_service *service = talloc_get_type(msg->private_data, 359 struct dreplsrv_service); 360 r->out.result = dreplsrv_fsmo_role_check(service, r->in.role); 361 return NT_STATUS_OK; 362 } 363 364 /** 365 * Called when the auth code wants us to try and replicate 366 * a users secrets 367 */ 368 static NTSTATUS drepl_trigger_repl_secret(struct irpc_message *msg, 369 struct drepl_trigger_repl_secret *r) 370 { 371 struct dreplsrv_service *service = talloc_get_type(msg->private_data, 372 struct dreplsrv_service); 373 374 375 drepl_repl_secret(service, r->in.user_dn); 376 377 /* we are not going to be sending a reply to this request */ 378 msg->no_reply = true; 379 380 return NT_STATUS_OK; 381 } 382 383 384 /* 385 DsReplicaAdd messages from the DRSUAPI server are forwarded here 386 */ 387 static NTSTATUS dreplsrv_replica_add(struct irpc_message *msg, 388 struct drsuapi_DsReplicaAdd *r) 389 { 390 struct dreplsrv_service *service = talloc_get_type(msg->private_data, 391 struct dreplsrv_service); 392 return drepl_replica_add(service, r); 393 } 394 395 /* 396 DsReplicaDel messages from the DRSUAPI server are forwarded here 397 */ 398 static NTSTATUS dreplsrv_replica_del(struct irpc_message *msg, 399 struct drsuapi_DsReplicaDel *r) 400 { 401 struct dreplsrv_service *service = talloc_get_type(msg->private_data, 402 struct dreplsrv_service); 403 return drepl_replica_del(service, r); 404 } 405 406 /* 407 DsReplicaMod messages from the DRSUAPI server are forwarded here 408 */ 409 static NTSTATUS dreplsrv_replica_mod(struct irpc_message *msg, 410 struct drsuapi_DsReplicaMod *r) 411 { 412 struct dreplsrv_service *service = talloc_get_type(msg->private_data, 413 struct dreplsrv_service); 414 return drepl_replica_mod(service, r); 415 } 416 129 417 130 418 /* … … 137 425 uint32_t periodic_startup_interval; 138 426 139 switch (lp _server_role(task->lp_ctx)) {427 switch (lpcfg_server_role(task->lp_ctx)) { 140 428 case ROLE_STANDALONE: 141 task_server_terminate(task, "dreplsrv: no DSDB replication required in standalone configuration", 429 task_server_terminate(task, "dreplsrv: no DSDB replication required in standalone configuration", 142 430 false); 143 431 return; 144 432 case ROLE_DOMAIN_MEMBER: 145 task_server_terminate(task, "dreplsrv: no DSDB replication required in domain member configuration", 433 task_server_terminate(task, "dreplsrv: no DSDB replication required in domain member configuration", 146 434 false); 147 435 return; … … 186 474 } 187 475 188 periodic_startup_interval = lp _parm_int(task->lp_ctx, NULL, "dreplsrv", "periodic_startup_interval", 15); /* in seconds */189 service->periodic.interval = lp _parm_int(task->lp_ctx, NULL, "dreplsrv", "periodic_interval", 300); /* in seconds */476 periodic_startup_interval = lpcfg_parm_int(task->lp_ctx, NULL, "dreplsrv", "periodic_startup_interval", 15); /* in seconds */ 477 service->periodic.interval = lpcfg_parm_int(task->lp_ctx, NULL, "dreplsrv", "periodic_interval", 300); /* in seconds */ 190 478 191 479 status = dreplsrv_periodic_schedule(service, periodic_startup_interval); … … 197 485 } 198 486 199 service->notify.interval = lp_parm_int(task->lp_ctx, NULL, "dreplsrv", 200 "notify_interval", 5); /* in seconds */ 201 status = dreplsrv_notify_schedule(service, service->notify.interval); 202 if (!W_ERROR_IS_OK(status)) { 203 task_server_terminate(task, talloc_asprintf(task, 204 "dreplsrv: Failed to setup notify schedule: %s\n", 205 win_errstr(status)), true); 206 return; 487 /* if we are a RODC then we do not send DSReplicaSync*/ 488 if (!service->am_rodc) { 489 service->notify.interval = lpcfg_parm_int(task->lp_ctx, NULL, "dreplsrv", 490 "notify_interval", 5); /* in seconds */ 491 status = dreplsrv_notify_schedule(service, service->notify.interval); 492 if (!W_ERROR_IS_OK(status)) { 493 task_server_terminate(task, talloc_asprintf(task, 494 "dreplsrv: Failed to setup notify schedule: %s\n", 495 win_errstr(status)), true); 496 return; 497 } 207 498 } 208 499 209 500 irpc_add_name(task->msg_ctx, "dreplsrv"); 210 501 502 IRPC_REGISTER(task->msg_ctx, irpc, DREPLSRV_REFRESH, dreplsrv_refresh, service); 211 503 IRPC_REGISTER(task->msg_ctx, drsuapi, DRSUAPI_DSREPLICASYNC, drepl_replica_sync, service); 504 IRPC_REGISTER(task->msg_ctx, drsuapi, DRSUAPI_DSREPLICAADD, dreplsrv_replica_add, service); 505 IRPC_REGISTER(task->msg_ctx, drsuapi, DRSUAPI_DSREPLICADEL, dreplsrv_replica_del, service); 506 IRPC_REGISTER(task->msg_ctx, drsuapi, DRSUAPI_DSREPLICAMOD, dreplsrv_replica_mod, service); 507 IRPC_REGISTER(task->msg_ctx, irpc, DREPL_TAKEFSMOROLE, drepl_take_FSMO_role, service); 508 IRPC_REGISTER(task->msg_ctx, irpc, DREPL_TRIGGER_REPL_SECRET, drepl_trigger_repl_secret, service); 509 messaging_register(task->msg_ctx, service, MSG_DREPL_ALLOCATE_RID, dreplsrv_allocate_rid); 212 510 } 213 511 -
vendor/current/source4/dsdb/repl/drepl_service.h
r414 r740 34 34 */ 35 35 struct dcerpc_pipe *pipe; 36 struct dcerpc_binding_handle *drsuapi_handle; 36 37 37 38 DATA_BLOB gensec_skey; … … 52 53 /* the out going connection to the source dsa */ 53 54 struct dreplsrv_drsuapi_connection *drsuapi; 55 56 /* used to force the GC principal name */ 57 const char *principal_name; 54 58 }; 55 59 … … 99 103 */ 100 104 struct dreplsrv_partition_source_dsa *sources; 101 }; 105 106 /* 107 * a linked list of all source dsa's we will notify, 108 * that are not also in sources 109 */ 110 struct dreplsrv_partition_source_dsa *notifies; 111 112 bool incoming_only; 113 }; 114 115 typedef void (*dreplsrv_extended_callback_t)(struct dreplsrv_service *, 116 WERROR, 117 enum drsuapi_DsExtendedError, 118 void *cb_data); 102 119 103 120 struct dreplsrv_out_operation { 104 121 struct dreplsrv_out_operation *prev, *next; 122 time_t schedule_time; 105 123 106 124 struct dreplsrv_service *service; … … 108 126 struct dreplsrv_partition_source_dsa *source_dsa; 109 127 110 struct composite_context *creq; 128 /* replication options - currently used by DsReplicaSync */ 129 uint32_t options; 130 enum drsuapi_DsExtendedOperation extended_op; 131 uint64_t fsmo_info; 132 enum drsuapi_DsExtendedError extended_ret; 133 dreplsrv_extended_callback_t callback; 134 void *cb_data; 111 135 }; 112 136 113 137 struct dreplsrv_notify_operation { 114 138 struct dreplsrv_notify_operation *prev, *next; 139 time_t schedule_time; 115 140 116 141 struct dreplsrv_service *service; … … 118 143 119 144 struct dreplsrv_partition_source_dsa *source_dsa; 120 121 struct composite_context *creq;145 bool is_urgent; 146 uint32_t replica_flags; 122 147 }; 123 148 … … 205 230 struct dreplsrv_notify_operation *n_current; 206 231 } ops; 207 }; 208 232 233 bool rid_alloc_in_progress; 234 235 bool am_rodc; 236 }; 237 238 #include "lib/messaging/irpc.h" 209 239 #include "dsdb/repl/drepl_out_helpers.h" 210 240 #include "dsdb/repl/drepl_service_proto.h" -
vendor/current/source4/dsdb/repl/replicated_objects.c
r414 r740 22 22 #include "includes.h" 23 23 #include "dsdb/samdb/samdb.h" 24 #include "lib/ldb/include/ldb_errors.h"24 #include <ldb_errors.h> 25 25 #include "../lib/util/dlinklist.h" 26 26 #include "librpc/gen_ndr/ndr_misc.h" … … 32 32 #include "param/param.h" 33 33 34 static WERROR dsdb_convert_object_ex(struct ldb_context *ldb, 35 const struct dsdb_schema *schema, 36 const struct drsuapi_DsReplicaObjectListItemEx *in, 34 /** 35 * Multi-pass working schema creation 36 * Function will: 37 * - shallow copy initial schema supplied 38 * - create a working schema in multiple passes 39 * until all objects are resolved 40 * Working schema is a schema with Attributes, Classes 41 * and indexes, but w/o subClassOf, possibleSupperiors etc. 42 * It is to be used just us cache for converting attribute values. 43 */ 44 WERROR dsdb_repl_make_working_schema(struct ldb_context *ldb, 45 const struct dsdb_schema *initial_schema, 46 const struct drsuapi_DsReplicaOIDMapping_Ctr *mapping_ctr, 47 uint32_t object_count, 48 const struct drsuapi_DsReplicaObjectListItemEx *first_object, 37 49 const DATA_BLOB *gensec_skey, 38 50 TALLOC_CTX *mem_ctx, 39 struct dsdb_extended_replicated_object *out) 51 struct dsdb_schema **_schema_out) 52 { 53 struct schema_list { 54 struct schema_list *next, *prev; 55 const struct drsuapi_DsReplicaObjectListItemEx *obj; 56 }; 57 58 WERROR werr; 59 struct dsdb_schema_prefixmap *pfm_remote; 60 struct schema_list *schema_list = NULL, *schema_list_item, *schema_list_next_item; 61 struct dsdb_schema *working_schema; 62 const struct drsuapi_DsReplicaObjectListItemEx *cur; 63 int ret, pass_no; 64 uint32_t ignore_attids[] = { 65 DRSUAPI_ATTID_auxiliaryClass, 66 DRSUAPI_ATTID_mayContain, 67 DRSUAPI_ATTID_mustContain, 68 DRSUAPI_ATTID_possSuperiors, 69 DRSUAPI_ATTID_systemPossSuperiors, 70 DRSUAPI_ATTID_INVALID 71 }; 72 73 /* make a copy of the iniatial_scheam so we don't mess with it */ 74 working_schema = dsdb_schema_copy_shallow(mem_ctx, ldb, initial_schema); 75 if (!working_schema) { 76 DEBUG(0,(__location__ ": schema copy failed!\n")); 77 return WERR_NOMEM; 78 } 79 80 /* we are going to need remote prefixMap for decoding */ 81 werr = dsdb_schema_pfm_from_drsuapi_pfm(mapping_ctr, true, 82 mem_ctx, &pfm_remote, NULL); 83 if (!W_ERROR_IS_OK(werr)) { 84 DEBUG(0,(__location__ ": Failed to decode remote prefixMap: %s", 85 win_errstr(werr))); 86 return werr; 87 } 88 89 /* create a list of objects yet to be converted */ 90 for (cur = first_object; cur; cur = cur->next_object) { 91 schema_list_item = talloc(mem_ctx, struct schema_list); 92 schema_list_item->obj = cur; 93 DLIST_ADD_END(schema_list, schema_list_item, struct schema_list); 94 } 95 96 /* resolve objects until all are resolved and in local schema */ 97 pass_no = 1; 98 99 while (schema_list) { 100 uint32_t converted_obj_count = 0; 101 uint32_t failed_obj_count = 0; 102 TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx); 103 W_ERROR_HAVE_NO_MEMORY(tmp_ctx); 104 105 for (schema_list_item = schema_list; schema_list_item; schema_list_item=schema_list_next_item) { 106 struct dsdb_extended_replicated_object object; 107 108 cur = schema_list_item->obj; 109 110 /* Save the next item, now we have saved out 111 * the current one, so we can DLIST_REMOVE it 112 * safely */ 113 schema_list_next_item = schema_list_item->next; 114 115 /* 116 * Convert the objects into LDB messages using the 117 * schema we have so far. It's ok if we fail to convert 118 * an object. We should convert more objects on next pass. 119 */ 120 werr = dsdb_convert_object_ex(ldb, working_schema, pfm_remote, 121 cur, gensec_skey, 122 ignore_attids, 123 tmp_ctx, &object); 124 if (!W_ERROR_IS_OK(werr)) { 125 DEBUG(1,("Warning: Failed to convert schema object %s into ldb msg\n", 126 cur->object.identifier->dn)); 127 128 failed_obj_count++; 129 } else { 130 /* 131 * Convert the schema from ldb_message format 132 * (OIDs as OID strings) into schema, using 133 * the remote prefixMap 134 */ 135 werr = dsdb_schema_set_el_from_ldb_msg(ldb, 136 working_schema, 137 object.msg); 138 if (!W_ERROR_IS_OK(werr)) { 139 DEBUG(1,("Warning: failed to convert object %s into a schema element: %s\n", 140 ldb_dn_get_linearized(object.msg->dn), 141 win_errstr(werr))); 142 failed_obj_count++; 143 } else { 144 DLIST_REMOVE(schema_list, schema_list_item); 145 talloc_free(schema_list_item); 146 converted_obj_count++; 147 } 148 } 149 } 150 talloc_free(tmp_ctx); 151 152 DEBUG(4,("Schema load pass %d: %d/%d of %d objects left to be converted.\n", 153 pass_no, failed_obj_count, converted_obj_count, object_count)); 154 pass_no++; 155 156 /* check if we converted any objects in this pass */ 157 if (converted_obj_count == 0) { 158 DEBUG(0,("Can't continue Schema load: didn't manage to convert any objects: all %d remaining of %d objects failed to convert\n", failed_obj_count, object_count)); 159 return WERR_INTERNAL_ERROR; 160 } 161 162 /* rebuild indexes */ 163 ret = dsdb_setup_sorted_accessors(ldb, working_schema); 164 if (LDB_SUCCESS != ret) { 165 DEBUG(0,("Failed to create schema-cache indexes!\n")); 166 return WERR_INTERNAL_ERROR; 167 } 168 }; 169 170 *_schema_out = working_schema; 171 172 return WERR_OK; 173 } 174 175 static bool dsdb_attid_in_list(const uint32_t attid_list[], uint32_t attid) 176 { 177 const uint32_t *cur; 178 if (!attid_list) { 179 return false; 180 } 181 for (cur = attid_list; *cur != DRSUAPI_ATTID_INVALID; cur++) { 182 if (*cur == attid) { 183 return true; 184 } 185 } 186 return false; 187 } 188 189 WERROR dsdb_convert_object_ex(struct ldb_context *ldb, 190 const struct dsdb_schema *schema, 191 const struct dsdb_schema_prefixmap *pfm_remote, 192 const struct drsuapi_DsReplicaObjectListItemEx *in, 193 const DATA_BLOB *gensec_skey, 194 const uint32_t *ignore_attids, 195 TALLOC_CTX *mem_ctx, 196 struct dsdb_extended_replicated_object *out) 40 197 { 41 198 NTSTATUS nt_status; 42 enum ndr_err_code ndr_err;43 199 WERROR status; 44 200 uint32_t i; … … 58 214 struct dom_sid *sid = NULL; 59 215 uint32_t rid = 0; 216 uint32_t attr_count; 60 217 int ret; 61 218 … … 112 269 W_ERROR_HAVE_NO_MEMORY(md->ctr.ctr1.array); 113 270 114 for (i=0 ; i < in->meta_data_ctr->count; i++) {271 for (i=0, attr_count=0; i < in->meta_data_ctr->count; i++, attr_count++) { 115 272 struct drsuapi_DsReplicaAttribute *a; 116 273 struct drsuapi_DsReplicaMetaData *d; 117 274 struct replPropertyMetaData1 *m; 118 275 struct ldb_message_element *e; 119 int j;276 uint32_t j; 120 277 121 278 a = &in->object.attribute_ctr.attributes[i]; 122 279 d = &in->meta_data_ctr->meta_data[i]; 123 m = &md->ctr.ctr1.array[i]; 124 e = &msg->elements[i]; 280 m = &md->ctr.ctr1.array[attr_count]; 281 e = &msg->elements[attr_count]; 282 283 if (dsdb_attid_in_list(ignore_attids, a->attid)) { 284 attr_count--; 285 continue; 286 } 125 287 126 288 for (j=0; j<a->value_ctr.num_values; j++) { … … 129 291 } 130 292 131 status = dsdb_attribute_drsuapi_to_ldb(ldb, schema, a, msg->elements, e); 293 status = dsdb_attribute_drsuapi_to_ldb(ldb, schema, pfm_remote, 294 a, msg->elements, e); 132 295 W_ERROR_NOT_OK_RETURN(status); 133 296 … … 143 306 } 144 307 145 if (a->attid == DRSUAPI_ATT RIBUTE_name) {308 if (a->attid == DRSUAPI_ATTID_name) { 146 309 name_a = a; 147 310 name_d = d; 148 rdn_m = &md->ctr.ctr1.array[md->ctr.ctr1.count]; 149 } 311 } 312 } 313 314 msg->num_elements = attr_count; 315 md->ctr.ctr1.count = attr_count; 316 if (name_a) { 317 rdn_m = &md->ctr.ctr1.array[md->ctr.ctr1.count]; 150 318 } 151 319 … … 186 354 W_ERROR_HAVE_NO_MEMORY(whenChanged_s); 187 355 188 ndr_err = ndr_push_struct_blob(&guid_value, msg, 189 lp_iconv_convenience(ldb_get_opaque(ldb, "loadparm")), 190 &in->object.identifier->guid, 191 (ndr_push_flags_fn_t)ndr_push_GUID); 192 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { 193 nt_status = ndr_map_error2ntstatus(ndr_err); 356 nt_status = GUID_to_ndr_blob(&in->object.identifier->guid, msg, &guid_value); 357 if (!NT_STATUS_IS_OK(nt_status)) { 194 358 return ntstatus_to_werror(nt_status); 195 359 } … … 202 366 } 203 367 204 WERROR dsdb_ extended_replicated_objects_commit(struct ldb_context *ldb,205 const char *partition_dn,206 const struct drsuapi_DsReplicaOIDMapping_Ctr *mapping_ctr,207 uint32_t object_count,208 const struct drsuapi_DsReplicaObjectListItemEx *first_object,209 uint32_t linked_attributes_count,210 const struct drsuapi_DsReplicaLinkedAttribute *linked_attributes,211 const struct repsFromTo1 *source_dsa,212 const struct drsuapi_DsReplicaCursor2CtrEx *uptodateness_vector,213 const DATA_BLOB *gensec_skey,214 TALLOC_CTX *mem_ctx,215 struct dsdb_extended_replicated_objects **_out,216 uint64_t *notify_uSN)368 WERROR dsdb_replicated_objects_convert(struct ldb_context *ldb, 369 const struct dsdb_schema *schema, 370 const char *partition_dn_str, 371 const struct drsuapi_DsReplicaOIDMapping_Ctr *mapping_ctr, 372 uint32_t object_count, 373 const struct drsuapi_DsReplicaObjectListItemEx *first_object, 374 uint32_t linked_attributes_count, 375 const struct drsuapi_DsReplicaLinkedAttribute *linked_attributes, 376 const struct repsFromTo1 *source_dsa, 377 const struct drsuapi_DsReplicaCursor2CtrEx *uptodateness_vector, 378 const DATA_BLOB *gensec_skey, 379 TALLOC_CTX *mem_ctx, 380 struct dsdb_extended_replicated_objects **objects) 217 381 { 218 382 WERROR status; 219 const struct dsdb_schema *schema; 383 struct ldb_dn *partition_dn; 384 struct dsdb_schema_prefixmap *pfm_remote; 220 385 struct dsdb_extended_replicated_objects *out; 221 struct ldb_result *ext_res;222 386 const struct drsuapi_DsReplicaObjectListItemEx *cur; 223 387 uint32_t i; 224 int ret;225 uint64_t seq_num1, seq_num2;226 227 schema = dsdb_get_schema(ldb);228 if (!schema) {229 return WERR_DS_SCHEMA_NOT_LOADED;230 }231 232 status = dsdb_verify_oid_mappings_drsuapi(schema, mapping_ctr);233 W_ERROR_NOT_OK_RETURN(status);234 388 235 389 out = talloc_zero(mem_ctx, struct dsdb_extended_replicated_objects); … … 237 391 out->version = DSDB_EXTENDED_REPLICATED_OBJECTS_VERSION; 238 392 239 out->partition_dn = ldb_dn_new(out, ldb, partition_dn); 240 W_ERROR_HAVE_NO_MEMORY(out->partition_dn); 393 /* 394 * Ensure schema is kept valid for as long as 'out' 395 * which may contain pointers to it 396 */ 397 schema = talloc_reference(out, schema); 398 W_ERROR_HAVE_NO_MEMORY(schema); 399 400 partition_dn = ldb_dn_new(out, ldb, partition_dn_str); 401 W_ERROR_HAVE_NO_MEMORY_AND_FREE(partition_dn, out); 402 403 status = dsdb_schema_pfm_from_drsuapi_pfm(mapping_ctr, true, 404 out, &pfm_remote, NULL); 405 if (!W_ERROR_IS_OK(status)) { 406 DEBUG(0,(__location__ ": Failed to decode remote prefixMap: %s", 407 win_errstr(status))); 408 talloc_free(out); 409 return status; 410 } 411 412 if (ldb_dn_compare(partition_dn, ldb_get_schema_basedn(ldb)) != 0) { 413 /* 414 * check for schema changes in case 415 * we are not replicating Schema NC 416 */ 417 status = dsdb_schema_info_cmp(schema, mapping_ctr); 418 if (!W_ERROR_IS_OK(status)) { 419 DEBUG(1,("Remote schema has changed while replicating %s\n", 420 partition_dn_str)); 421 talloc_free(out); 422 return status; 423 } 424 } 425 426 out->partition_dn = partition_dn; 241 427 242 428 out->source_dsa = source_dsa; … … 247 433 struct dsdb_extended_replicated_object, 248 434 out->num_objects); 249 W_ERROR_HAVE_NO_MEMORY (out->objects);435 W_ERROR_HAVE_NO_MEMORY_AND_FREE(out->objects, out); 250 436 251 437 /* pass the linked attributes down to the repl_meta_data … … 256 442 for (i=0, cur = first_object; cur; cur = cur->next_object, i++) { 257 443 if (i == out->num_objects) { 444 talloc_free(out); 258 445 return WERR_FOOBAR; 259 446 } 260 447 261 status = dsdb_convert_object_ex(ldb, schema, 448 status = dsdb_convert_object_ex(ldb, schema, pfm_remote, 262 449 cur, gensec_skey, 450 NULL, 263 451 out->objects, &out->objects[i]); 264 452 if (!W_ERROR_IS_OK(status)) { 265 DEBUG(0,("Failed to convert object %s\n", cur->object.identifier->dn)); 453 talloc_free(out); 454 DEBUG(0,("Failed to convert object %s: %s\n", 455 cur->object.identifier->dn, 456 win_errstr(status))); 266 457 return status; 267 458 } 268 459 } 269 460 if (i != out->num_objects) { 270 return WERR_FOOBAR; 271 } 461 talloc_free(out); 462 return WERR_FOOBAR; 463 } 464 465 /* free pfm_remote, we won't need it anymore */ 466 talloc_free(pfm_remote); 467 468 *objects = out; 469 return WERR_OK; 470 } 471 472 /** 473 * Commits a list of replicated objects. 474 * 475 * @param working_schema dsdb_schema to be used for resolving 476 * Classes/Attributes during Schema replication. If not NULL, 477 * it will be set on ldb and used while committing replicated objects 478 */ 479 WERROR dsdb_replicated_objects_commit(struct ldb_context *ldb, 480 struct dsdb_schema *working_schema, 481 struct dsdb_extended_replicated_objects *objects, 482 uint64_t *notify_uSN) 483 { 484 WERROR werr; 485 struct ldb_result *ext_res; 486 struct dsdb_schema *cur_schema = NULL; 487 int ret; 488 uint64_t seq_num1, seq_num2; 272 489 273 490 /* TODO: handle linked attributes */ … … 279 496 if (ret != LDB_SUCCESS) { 280 497 DEBUG(0,(__location__ " Failed to start transaction\n")); 281 talloc_free(out); 282 return WERR_FOOBAR; 283 } 284 285 ret = dsdb_load_partition_usn(ldb, out->partition_dn, &seq_num1); 498 return WERR_FOOBAR; 499 } 500 501 ret = dsdb_load_partition_usn(ldb, objects->partition_dn, &seq_num1, NULL); 286 502 if (ret != LDB_SUCCESS) { 287 503 DEBUG(0,(__location__ " Failed to load partition uSN\n")); 288 talloc_free(out);289 504 ldb_transaction_cancel(ldb); 290 505 return WERR_FOOBAR; 291 506 } 292 507 293 ret = ldb_extended(ldb, DSDB_EXTENDED_REPLICATED_OBJECTS_OID, out, &ext_res); 508 /* 509 * Set working_schema for ldb in case we are replicating from Schema NC. 510 * Schema won't be reloaded during Replicated Objects commit, as it is 511 * done in a transaction. So we need some way to search for newly 512 * added Classes and Attributes 513 */ 514 if (working_schema) { 515 /* store current schema so we can fall back in case of failure */ 516 cur_schema = dsdb_get_schema(ldb, working_schema); 517 518 ret = dsdb_reference_schema(ldb, working_schema, false); 519 if (ret != LDB_SUCCESS) { 520 DEBUG(0,(__location__ "Failed to reference working schema - %s\n", 521 ldb_strerror(ret))); 522 /* TODO: Map LDB Error to NTSTATUS? */ 523 ldb_transaction_cancel(ldb); 524 return WERR_INTERNAL_ERROR; 525 } 526 } 527 528 ret = ldb_extended(ldb, DSDB_EXTENDED_REPLICATED_OBJECTS_OID, objects, &ext_res); 294 529 if (ret != LDB_SUCCESS) { 530 /* restore previous schema */ 531 if (cur_schema ) { 532 dsdb_reference_schema(ldb, cur_schema, false); 533 dsdb_make_schema_global(ldb, cur_schema); 534 } 535 295 536 DEBUG(0,("Failed to apply records: %s: %s\n", 296 537 ldb_errstring(ldb), ldb_strerror(ret))); 297 talloc_free(out);298 538 ldb_transaction_cancel(ldb); 299 539 return WERR_FOOBAR; 300 540 } 301 541 talloc_free(ext_res); 542 543 /* Save our updated prefixMap */ 544 if (working_schema) { 545 werr = dsdb_write_prefixes_from_schema_to_ldb(working_schema, 546 ldb, 547 working_schema); 548 if (!W_ERROR_IS_OK(werr)) { 549 /* restore previous schema */ 550 if (cur_schema ) { 551 dsdb_reference_schema(ldb, cur_schema, false); 552 dsdb_make_schema_global(ldb, cur_schema); 553 } 554 DEBUG(0,("Failed to save updated prefixMap: %s\n", 555 win_errstr(werr))); 556 return werr; 557 } 558 } 302 559 303 560 ret = ldb_transaction_prepare_commit(ldb); 304 561 if (ret != LDB_SUCCESS) { 305 DEBUG(0,(__location__ " Failed to prepare commit of transaction\n")); 306 talloc_free(out); 307 return WERR_FOOBAR; 308 } 309 310 ret = dsdb_load_partition_usn(ldb, out->partition_dn, &seq_num2); 562 /* restore previous schema */ 563 if (cur_schema ) { 564 dsdb_reference_schema(ldb, cur_schema, false); 565 dsdb_make_schema_global(ldb, cur_schema); 566 } 567 DEBUG(0,(__location__ " Failed to prepare commit of transaction: %s\n", 568 ldb_errstring(ldb))); 569 return WERR_FOOBAR; 570 } 571 572 ret = dsdb_load_partition_usn(ldb, objects->partition_dn, &seq_num2, NULL); 311 573 if (ret != LDB_SUCCESS) { 574 /* restore previous schema */ 575 if (cur_schema ) { 576 dsdb_reference_schema(ldb, cur_schema, false); 577 dsdb_make_schema_global(ldb, cur_schema); 578 } 312 579 DEBUG(0,(__location__ " Failed to load partition uSN\n")); 313 talloc_free(out);314 580 ldb_transaction_cancel(ldb); 315 581 return WERR_FOOBAR; … … 325 591 ret = ldb_transaction_commit(ldb); 326 592 if (ret != LDB_SUCCESS) { 593 /* restore previous schema */ 594 if (cur_schema ) { 595 dsdb_reference_schema(ldb, cur_schema, false); 596 dsdb_make_schema_global(ldb, cur_schema); 597 } 327 598 DEBUG(0,(__location__ " Failed to commit transaction\n")); 328 talloc_free(out); 329 return WERR_FOOBAR; 330 } 331 599 return WERR_FOOBAR; 600 } 601 602 /* 603 * Reset the Schema used by ldb. This will lead to 604 * a schema cache being refreshed from database. 605 */ 606 if (working_schema) { 607 cur_schema = dsdb_get_schema(ldb, NULL); 608 /* TODO: What we do in case dsdb_get_schema() fail? 609 * We can't fallback at this point anymore */ 610 if (cur_schema) { 611 dsdb_make_schema_global(ldb, cur_schema); 612 } 613 } 332 614 333 615 DEBUG(2,("Replicated %u objects (%u linked attributes) for %s\n", 334 o ut->num_objects, out->linked_attributes_count,335 ldb_dn_get_linearized(o ut->partition_dn)));616 objects->num_objects, objects->linked_attributes_count, 617 ldb_dn_get_linearized(objects->partition_dn))); 336 618 337 338 if (_out) {339 *_out = out;340 } else {341 talloc_free(out);342 }343 344 619 return WERR_OK; 345 620 } 346 621 347 static WERROR dsdb_ convert_object(struct ldb_context *ldb,348 349 350 351 622 static WERROR dsdb_origin_object_convert(struct ldb_context *ldb, 623 const struct dsdb_schema *schema, 624 const struct drsuapi_DsReplicaObjectListItem *in, 625 TALLOC_CTX *mem_ctx, 626 struct ldb_message **_msg) 352 627 { 353 628 WERROR status; 354 u int32_t i;629 unsigned int i; 355 630 struct ldb_message *msg; 356 631 … … 381 656 e = &msg->elements[i]; 382 657 383 status = dsdb_attribute_drsuapi_to_ldb(ldb, schema, a, msg->elements, e); 658 status = dsdb_attribute_drsuapi_to_ldb(ldb, schema, schema->prefixmap, 659 a, msg->elements, e); 384 660 W_ERROR_NOT_OK_RETURN(status); 385 661 } … … 412 688 int ret; 413 689 414 schema = dsdb_get_schema(ldb); 690 for (cur = first_object; cur; cur = cur->next_object) { 691 num_objects++; 692 } 693 694 if (num_objects == 0) { 695 return WERR_OK; 696 } 697 698 ret = ldb_transaction_start(ldb); 699 if (ret != LDB_SUCCESS) { 700 return WERR_DS_INTERNAL_FAILURE; 701 } 702 703 objects = talloc_array(mem_ctx, struct ldb_message *, 704 num_objects); 705 if (objects == NULL) { 706 status = WERR_NOMEM; 707 goto cancel; 708 } 709 710 schema = dsdb_get_schema(ldb, objects); 415 711 if (!schema) { 416 712 return WERR_DS_SCHEMA_NOT_LOADED; 417 713 } 418 714 419 for (cur = first_object; cur; cur = cur->next_object) {420 num_objects++;421 }422 423 if (num_objects == 0) {424 return WERR_OK;425 }426 427 objects = talloc_array(mem_ctx, struct ldb_message *,428 num_objects);429 W_ERROR_HAVE_NO_MEMORY(objects);430 431 715 for (i=0, cur = first_object; cur; cur = cur->next_object, i++) { 432 status = dsdb_convert_object(ldb, schema, 433 cur, objects, &objects[i]); 434 W_ERROR_NOT_OK_RETURN(status); 716 status = dsdb_origin_object_convert(ldb, schema, cur, 717 objects, &objects[i]); 718 if (!W_ERROR_IS_OK(status)) { 719 goto cancel; 720 } 435 721 } 436 722 … … 438 724 struct drsuapi_DsReplicaObjectIdentifier2, 439 725 num_objects); 440 W_ERROR_HAVE_NO_MEMORY(objects); 726 if (ids == NULL) { 727 status = WERR_NOMEM; 728 goto cancel; 729 } 441 730 442 731 for (i=0; i < num_objects; i++) { 443 732 struct dom_sid *sid = NULL; 733 struct ldb_request *add_req; 444 734 445 735 DEBUG(6,(__location__ ": adding %s\n", 446 736 ldb_dn_get_linearized(objects[i]->dn))); 737 738 ret = ldb_build_add_req(&add_req, 739 ldb, 740 objects, 741 objects[i], 742 NULL, 743 NULL, 744 ldb_op_default_callback, 745 NULL); 746 if (ret != LDB_SUCCESS) { 747 status = WERR_DS_INTERNAL_FAILURE; 748 goto cancel; 749 } 750 751 ret = ldb_request_add_control(add_req, LDB_CONTROL_RELAX_OID, true, NULL); 752 if (ret != LDB_SUCCESS) { 753 status = WERR_DS_INTERNAL_FAILURE; 754 goto cancel; 755 } 447 756 448 ret = ldb_add(ldb, objects[i]); 449 if (ret != 0) { 757 ret = ldb_request(ldb, add_req); 758 if (ret == LDB_SUCCESS) { 759 ret = ldb_wait(add_req->handle, LDB_WAIT_ALL); 760 } 761 if (ret != LDB_SUCCESS) { 762 DEBUG(0,(__location__ ": Failed add of %s - %s\n", 763 ldb_dn_get_linearized(objects[i]->dn), ldb_errstring(ldb))); 764 status = WERR_DS_INTERNAL_FAILURE; 450 765 goto cancel; 451 766 } 767 768 talloc_free(add_req); 769 452 770 ret = ldb_search(ldb, objects, &res, objects[i]->dn, 453 771 LDB_SCOPE_BASE, attrs, 454 772 "(objectClass=*)"); 455 if (ret != 0) { 773 if (ret != LDB_SUCCESS) { 774 status = WERR_DS_INTERNAL_FAILURE; 456 775 goto cancel; 457 776 } … … 465 784 } 466 785 786 ret = ldb_transaction_commit(ldb); 787 if (ret != LDB_SUCCESS) { 788 return WERR_DS_INTERNAL_FAILURE; 789 } 790 467 791 talloc_free(objects); 468 792 … … 470 794 *_ids = ids; 471 795 return WERR_OK; 796 472 797 cancel: 473 798 talloc_free(objects); 474 799 ldb_transaction_cancel(ldb); 475 return WERR_FOOBAR;800 return status; 476 801 }
Note:
See TracChangeset
for help on using the changeset viewer.