From 59818f2f793ecc6349b87ee0debc7dd558272552 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Wed, 14 Oct 2009 20:25:48 +1100 Subject: s4-drs: implement more of DsUpdateRefs The DsUpdateRefs calls takes a set of flags that indicates if the server should ignore specific add/delete error codes. This patch also exposes the core UpdateRefs call into a public function, so that it can be called from DsGetNCChanges --- source4/rpc_server/drsuapi/dcesrv_drsuapi.h | 2 + source4/rpc_server/drsuapi/updaterefs.c | 88 ++++++++++++++++++++--------- 2 files changed, 63 insertions(+), 27 deletions(-) (limited to 'source4') diff --git a/source4/rpc_server/drsuapi/dcesrv_drsuapi.h b/source4/rpc_server/drsuapi/dcesrv_drsuapi.h index 82899c8432..e42d9569e7 100644 --- a/source4/rpc_server/drsuapi/dcesrv_drsuapi.h +++ b/source4/rpc_server/drsuapi/dcesrv_drsuapi.h @@ -39,6 +39,8 @@ struct drsuapi_bind_state { /* prototypes of internal functions */ +WERROR drsuapi_UpdateRefs(struct drsuapi_bind_state *b_state, TALLOC_CTX *mem_ctx, + struct drsuapi_DsReplicaUpdateRefsRequest1 *req); WERROR dcesrv_drsuapi_DsReplicaUpdateRefs(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, struct drsuapi_DsReplicaUpdateRefs *r); WERROR dcesrv_drsuapi_DsGetNCChanges(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, diff --git a/source4/rpc_server/drsuapi/updaterefs.c b/source4/rpc_server/drsuapi/updaterefs.c index d01fabf575..60a70c5032 100644 --- a/source4/rpc_server/drsuapi/updaterefs.c +++ b/source4/rpc_server/drsuapi/updaterefs.c @@ -35,16 +35,29 @@ struct repsTo { add a replication destination for a given partition GUID */ static WERROR uref_add_dest(struct ldb_context *sam_ctx, TALLOC_CTX *mem_ctx, - struct ldb_dn *dn, struct repsFromTo1 *dest) + struct ldb_dn *dn, struct repsFromTo1 *dest, + uint32_t options) { struct repsTo reps; WERROR werr; + int i; werr = dsdb_loadreps(sam_ctx, mem_ctx, dn, "repsTo", &reps.r, &reps.count); if (!W_ERROR_IS_OK(werr)) { return werr; } + for (i=0; isource_dsa_obj_guid, + &reps.r[i].ctr.ctr1.source_dsa_obj_guid) == 0) { + if (options & DRSUAPI_DS_REPLICA_UPDATE_GETCHG_CHECK) { + return WERR_OK; + } else { + return WERR_DS_DRA_REF_ALREADY_EXISTS; + } + } + } + reps.r = talloc_realloc(mem_ctx, reps.r, struct repsFromToBlob, reps.count+1); if (reps.r == NULL) { return WERR_DS_DRA_INTERNAL_ERROR; @@ -66,11 +79,13 @@ static WERROR uref_add_dest(struct ldb_context *sam_ctx, TALLOC_CTX *mem_ctx, delete a replication destination for a given partition GUID */ static WERROR uref_del_dest(struct ldb_context *sam_ctx, TALLOC_CTX *mem_ctx, - struct ldb_dn *dn, struct GUID *dest_guid) + struct ldb_dn *dn, struct GUID *dest_guid, + uint32_t options) { struct repsTo reps; WERROR werr; int i; + bool found = false; werr = dsdb_loadreps(sam_ctx, mem_ctx, dn, "repsTo", &reps.r, &reps.count); if (!W_ERROR_IS_OK(werr)) { @@ -83,6 +98,7 @@ static WERROR uref_del_dest(struct ldb_context *sam_ctx, TALLOC_CTX *mem_ctx, memmove(&reps.r[i], &reps.r[i+1], sizeof(reps.r[i])*(reps.count-(i+1))); } reps.count--; + found = true; } } @@ -91,35 +107,22 @@ static WERROR uref_del_dest(struct ldb_context *sam_ctx, TALLOC_CTX *mem_ctx, return werr; } + if (!found && !(options & DRSUAPI_DS_REPLICA_UPDATE_GETCHG_CHECK)) { + return WERR_DS_DRA_REF_NOT_FOUND; + } + return WERR_OK; } /* - drsuapi_DsReplicaUpdateRefs + drsuapi_DsReplicaUpdateRefs - a non RPC version callable from getncchanges */ -WERROR dcesrv_drsuapi_DsReplicaUpdateRefs(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, - struct drsuapi_DsReplicaUpdateRefs *r) +WERROR drsuapi_UpdateRefs(struct drsuapi_bind_state *b_state, TALLOC_CTX *mem_ctx, + struct drsuapi_DsReplicaUpdateRefsRequest1 *req) { - struct drsuapi_DsReplicaUpdateRefsRequest1 *req; WERROR werr; struct ldb_dn *dn; - struct dcesrv_handle *h; - struct drsuapi_bind_state *b_state; - - DCESRV_PULL_HANDLE_WERR(h, r->in.bind_handle, DRSUAPI_BIND_HANDLE); - b_state = h->data; - - werr = drs_security_level_check(dce_call, "DsReplicaUpdateRefs"); - if (!W_ERROR_IS_OK(werr)) { - return werr; - } - if (r->in.level != 1) { - DEBUG(0,("DrReplicUpdateRefs - unsupported level %u\n", r->in.level)); - return WERR_DS_DRA_INVALID_PARAMETER; - } - - req = &r->in.req.req1; DEBUG(4,("DsReplicaUpdateRefs for host '%s' with GUID %s options 0x%08x nc=%s\n", req->dest_dsa_dns_name, GUID_string(mem_ctx, &req->dest_dsa_guid), req->options, @@ -136,10 +139,10 @@ WERROR dcesrv_drsuapi_DsReplicaUpdateRefs(struct dcesrv_call_state *dce_call, TA } if (req->options & DRSUAPI_DS_REPLICA_UPDATE_DELETE_REFERENCE) { - werr = uref_del_dest(b_state->sam_ctx, mem_ctx, dn, &req->dest_dsa_guid); + werr = uref_del_dest(b_state->sam_ctx, mem_ctx, dn, &req->dest_dsa_guid, req->options); if (!W_ERROR_IS_OK(werr)) { DEBUG(0,("Failed to delete repsTo for %s\n", - GUID_string(dce_call, &req->dest_dsa_guid))); + GUID_string(mem_ctx, &req->dest_dsa_guid))); goto failed; } } @@ -156,10 +159,10 @@ WERROR dcesrv_drsuapi_DsReplicaUpdateRefs(struct dcesrv_call_state *dce_call, TA dest.source_dsa_obj_guid = req->dest_dsa_guid; dest.replica_flags = req->options; - werr = uref_add_dest(b_state->sam_ctx, mem_ctx, dn, &dest); + werr = uref_add_dest(b_state->sam_ctx, mem_ctx, dn, &dest, req->options); if (!W_ERROR_IS_OK(werr)) { - DEBUG(0,("Failed to delete repsTo for %s\n", - GUID_string(dce_call, &dest.source_dsa_obj_guid))); + DEBUG(0,("Failed to add repsTo for %s\n", + GUID_string(mem_ctx, &dest.source_dsa_obj_guid))); goto failed; } } @@ -175,3 +178,34 @@ failed: ldb_transaction_cancel(b_state->sam_ctx); return werr; } + +/* + drsuapi_DsReplicaUpdateRefs +*/ +WERROR dcesrv_drsuapi_DsReplicaUpdateRefs(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, + struct drsuapi_DsReplicaUpdateRefs *r) +{ + struct dcesrv_handle *h; + struct drsuapi_bind_state *b_state; + struct drsuapi_DsReplicaUpdateRefsRequest1 *req; + WERROR werr; + + DCESRV_PULL_HANDLE_WERR(h, r->in.bind_handle, DRSUAPI_BIND_HANDLE); + b_state = h->data; + + werr = drs_security_level_check(dce_call, "DsReplicaUpdateRefs"); + if (!W_ERROR_IS_OK(werr)) { + return werr; + } + + if (r->in.level != 1) { + DEBUG(0,("DrReplicUpdateRefs - unsupported level %u\n", r->in.level)); + return WERR_DS_DRA_INVALID_PARAMETER; + } + + req = &r->in.req.req1; + + return drsuapi_UpdateRefs(b_state, mem_ctx, req); +} + + -- cgit