summaryrefslogtreecommitdiff
path: root/source4/rpc_server/drsuapi/updaterefs.c
diff options
context:
space:
mode:
Diffstat (limited to 'source4/rpc_server/drsuapi/updaterefs.c')
-rw-r--r--source4/rpc_server/drsuapi/updaterefs.c103
1 files changed, 65 insertions, 38 deletions
diff --git a/source4/rpc_server/drsuapi/updaterefs.c b/source4/rpc_server/drsuapi/updaterefs.c
index e12be6f058..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; i<reps.count; i++) {
+ if (GUID_compare(&dest->source_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,60 +107,42 @@ 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;
- struct ldb_context *sam_ctx;
WERROR werr;
struct ldb_dn *dn;
- 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,
drs_ObjectIdentifier_to_string(mem_ctx, req->naming_context)));
- /* TODO: We need to authenticate this operation pretty carefully */
- sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, dce_call->conn->dce_ctx->lp_ctx,
- system_session(mem_ctx, dce_call->conn->dce_ctx->lp_ctx));
- if (!sam_ctx) {
- return WERR_DS_DRA_INTERNAL_ERROR;
- }
-
- dn = ldb_dn_new(mem_ctx, sam_ctx, req->naming_context->dn);
+ dn = ldb_dn_new(mem_ctx, b_state->sam_ctx, req->naming_context->dn);
if (dn == NULL) {
- talloc_free(sam_ctx);
return WERR_DS_INVALID_DN_SYNTAX;
}
- if (ldb_transaction_start(sam_ctx) != LDB_SUCCESS) {
+ if (ldb_transaction_start(b_state->sam_ctx) != LDB_SUCCESS) {
DEBUG(0,(__location__ ": Failed to start transaction on samdb\n"));
- talloc_free(sam_ctx);
return WERR_DS_DRA_INTERNAL_ERROR;
}
if (req->options & DRSUAPI_DS_REPLICA_UPDATE_DELETE_REFERENCE) {
- werr = uref_del_dest(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;
}
}
@@ -161,24 +159,53 @@ 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(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;
}
}
- if (ldb_transaction_commit(sam_ctx) != LDB_SUCCESS) {
+ if (ldb_transaction_commit(b_state->sam_ctx) != LDB_SUCCESS) {
DEBUG(0,(__location__ ": Failed to commit transaction on samdb\n"));
return WERR_DS_DRA_INTERNAL_ERROR;
}
- talloc_free(sam_ctx);
return WERR_OK;
failed:
- ldb_transaction_cancel(sam_ctx);
- talloc_free(sam_ctx);
+ 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);
+}
+
+