From d055b202985e175a9e6282d9cb9ce767b6202ec1 Mon Sep 17 00:00:00 2001 From: Garming Sam Date: Wed, 29 Mar 2017 11:24:50 +1300 Subject: [PATCH] drepl_server: Allow refresh of partitions on UpdateRef When we call UpdateRef, the push replication will not begin until the drepl_server has done its periodic refresh. If UpdateRefs is called, we should just send an IRPC message to call the refresh. NOTE: This has the same dependencies and issues as repl_secrets in auth_sam.c in terms of IRPC implementation. Signed-off-by: Garming Sam Reviewed-by: Andrew Bartlett --- source4/rpc_server/drsuapi/dcesrv_drsuapi.h | 4 +- source4/rpc_server/drsuapi/getncchanges.c | 4 +- source4/rpc_server/drsuapi/updaterefs.c | 51 +++++++++++++++++++-- 3 files changed, 53 insertions(+), 6 deletions(-) diff --git a/source4/rpc_server/drsuapi/dcesrv_drsuapi.h b/source4/rpc_server/drsuapi/dcesrv_drsuapi.h index d376f7edfb3..38375b5ce58 100644 --- a/source4/rpc_server/drsuapi/dcesrv_drsuapi.h +++ b/source4/rpc_server/drsuapi/dcesrv_drsuapi.h @@ -40,7 +40,9 @@ struct drsuapi_bind_state { /* prototypes of internal functions */ -WERROR drsuapi_UpdateRefs(struct drsuapi_bind_state *b_state, TALLOC_CTX *mem_ctx, +WERROR drsuapi_UpdateRefs(struct imessaging_context *msg_ctx, + struct tevent_context *event_ctx, + 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); diff --git a/source4/rpc_server/drsuapi/getncchanges.c b/source4/rpc_server/drsuapi/getncchanges.c index 3f2ef8d960c..1f02f2c0936 100644 --- a/source4/rpc_server/drsuapi/getncchanges.c +++ b/source4/rpc_server/drsuapi/getncchanges.c @@ -2933,7 +2933,9 @@ allowed: to send notifies using the GC SPN */ ureq.options |= (req10->replica_flags & DRSUAPI_DRS_REF_GCSPN); - werr = drsuapi_UpdateRefs(b_state, mem_ctx, &ureq); + werr = drsuapi_UpdateRefs(dce_call->msg_ctx, + dce_call->event_ctx, b_state, + mem_ctx, &ureq); if (!W_ERROR_IS_OK(werr)) { DEBUG(0,(__location__ ": Failed UpdateRefs on %s for %s in DsGetNCChanges - %s\n", drs_ObjectIdentifier_to_string(mem_ctx, ncRoot), ureq.dest_dsa_dns_name, diff --git a/source4/rpc_server/drsuapi/updaterefs.c b/source4/rpc_server/drsuapi/updaterefs.c index 6fdbf2e04bf..457f393fd9d 100644 --- a/source4/rpc_server/drsuapi/updaterefs.c +++ b/source4/rpc_server/drsuapi/updaterefs.c @@ -27,6 +27,8 @@ #include "rpc_server/drsuapi/dcesrv_drsuapi.h" #include "auth/session.h" #include "librpc/gen_ndr/ndr_drsuapi.h" +#include "librpc/gen_ndr/ndr_irpc_c.h" +#include "lib/messaging/irpc.h" struct repsTo { uint32_t count; @@ -121,6 +123,10 @@ static WERROR uref_del_dest(struct ldb_context *sam_ctx, TALLOC_CTX *mem_ctx, return WERR_OK; } +struct drepl_refresh_state { + struct dreplsrv_refresh r; +}; + /** * @brief Update the references for the given NC and the destination DSA object * @@ -128,6 +134,9 @@ static WERROR uref_del_dest(struct ldb_context *sam_ctx, TALLOC_CTX *mem_ctx, * will validate the request to update reference and then will add/del a repsTo * to the specified server referenced by its DSA GUID in the request. * + * @param[in] msg_ctx Messaging context for sending partition + * refresh in dreplsrv + * * @param[in] b_state A bind_state object * * @param[in] mem_ctx A talloc context for memory allocation @@ -139,7 +148,9 @@ static WERROR uref_del_dest(struct ldb_context *sam_ctx, TALLOC_CTX *mem_ctx, * @return WERR_OK is success, different error * otherwise. */ -WERROR drsuapi_UpdateRefs(struct drsuapi_bind_state *b_state, TALLOC_CTX *mem_ctx, +WERROR drsuapi_UpdateRefs(struct imessaging_context *msg_ctx, + struct tevent_context *event_ctx, + struct drsuapi_bind_state *b_state, TALLOC_CTX *mem_ctx, struct drsuapi_DsReplicaUpdateRefsRequest1 *req) { WERROR werr; @@ -147,6 +158,10 @@ WERROR drsuapi_UpdateRefs(struct drsuapi_bind_state *b_state, TALLOC_CTX *mem_ct struct ldb_dn *dn; struct ldb_dn *nc_root; struct ldb_context *sam_ctx = b_state->sam_ctx_system?b_state->sam_ctx_system:b_state->sam_ctx; + struct dcerpc_binding_handle *irpc_handle; + struct tevent_req *subreq; + struct drepl_refresh_state *state; + 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), @@ -201,7 +216,7 @@ WERROR drsuapi_UpdateRefs(struct drsuapi_bind_state *b_state, TALLOC_CTX *mem_ct if (req->options & DRSUAPI_DRS_ADD_REF) { struct repsFromTo1 dest; struct repsFromTo1OtherInfo oi; - + ZERO_STRUCT(dest); ZERO_STRUCT(oi); @@ -222,9 +237,36 @@ WERROR drsuapi_UpdateRefs(struct drsuapi_bind_state *b_state, TALLOC_CTX *mem_ct if (ldb_transaction_commit(sam_ctx) != LDB_SUCCESS) { DEBUG(0,(__location__ ": Failed to commit transaction on samdb: %s\n", ldb_errstring(sam_ctx))); - return WERR_DS_DRA_INTERNAL_ERROR; + return WERR_DS_DRA_INTERNAL_ERROR; } + state = talloc_zero(mem_ctx, struct drepl_refresh_state); + if (state == NULL) { + return WERR_OK; + } + + irpc_handle = irpc_binding_handle_by_name(mem_ctx, msg_ctx, + "dreplsrv", &ndr_table_irpc); + if (irpc_handle == NULL) { + /* dreplsrv is not running yet */ + TALLOC_FREE(state); + return WERR_OK; + } + + /* + * [Taken from auth_sam_trigger_repl_secret in auth_sam.c] + * + * This seem to rely on the current IRPC implementation, + * which delivers the message in the _send function. + * + * TODO: we need a ONE_WAY IRPC handle and register + * a callback and wait for it to be triggered! + */ + subreq = dcerpc_dreplsrv_refresh_r_send(state, event_ctx, + irpc_handle, &state->r); + TALLOC_FREE(subreq); + TALLOC_FREE(state); + return WERR_OK; failed: @@ -278,7 +320,8 @@ WERROR dcesrv_drsuapi_DsReplicaUpdateRefs(struct dcesrv_call_state *dce_call, TA } } - werr = drsuapi_UpdateRefs(b_state, mem_ctx, req); + werr = drsuapi_UpdateRefs(dce_call->msg_ctx, dce_call->event_ctx, + b_state, mem_ctx, req); #if 0 NDR_PRINT_FUNCTION_DEBUG(drsuapi_DsReplicaUpdateRefs, NDR_BOTH, r); -- 2.25.1