diff options
Diffstat (limited to 'source3')
-rw-r--r-- | source3/librpc/rpc/dcerpc_ep.c | 2 | ||||
-rw-r--r-- | source3/rpc_server/rpc_ep_setup.c | 114 |
2 files changed, 114 insertions, 2 deletions
diff --git a/source3/librpc/rpc/dcerpc_ep.c b/source3/librpc/rpc/dcerpc_ep.c index 92c01a32bb..1fce63acd2 100644 --- a/source3/librpc/rpc/dcerpc_ep.c +++ b/source3/librpc/rpc/dcerpc_ep.c @@ -289,7 +289,7 @@ static NTSTATUS ep_register(TALLOC_CTX *mem_ctx, if (pbh != NULL) { *pbh = talloc_move(mem_ctx, &h); - talloc_steal(mem_ctx, cli); + talloc_steal(*pbh, cli); } done: diff --git a/source3/rpc_server/rpc_ep_setup.c b/source3/rpc_server/rpc_ep_setup.c index ddc655cb67..836ef30242 100644 --- a/source3/rpc_server/rpc_ep_setup.c +++ b/source3/rpc_server/rpc_ep_setup.c @@ -21,6 +21,7 @@ #include "includes.h" +#include "../librpc/gen_ndr/ndr_epmapper_c.h" #include "../librpc/gen_ndr/srv_epmapper.h" #include "../librpc/gen_ndr/srv_srvsvc.h" #include "../librpc/gen_ndr/srv_winreg.h" @@ -215,6 +216,9 @@ static NTSTATUS rpc_ep_setup_register(struct tevent_context *ev_ctx, return NT_STATUS_OK; } +#define MONITOR_WAIT_TIME 15 +static void rpc_ep_setup_monitor_loop(struct tevent_req *subreq); + static void rpc_ep_setup_register_loop(struct tevent_req *req) { struct rpc_ep_regsiter_state *state = @@ -237,7 +241,16 @@ static void rpc_ep_setup_register_loop(struct tevent_req *req) state->port, &state->h); if (NT_STATUS_IS_OK(status)) { - talloc_free(state); + /* endpoint registered, monitor the connnection. */ + req = tevent_wakeup_send(state->mem_ctx, + state->ev_ctx, + timeval_current_ofs(MONITOR_WAIT_TIME, 0)); + if (tevent_req_nomem(state->mem_ctx, req)) { + talloc_free(state); + return; + } + + tevent_req_set_callback(req, rpc_ep_setup_monitor_loop, state); return; } @@ -293,6 +306,105 @@ static NTSTATUS rpc_ep_setup_try_register(TALLOC_CTX *mem_ctx, return status; } +/* + * Monitor the connection to the endpoint mapper and if it goes away, try to + * register the endpoint. + */ +static void rpc_ep_setup_monitor_loop(struct tevent_req *subreq) +{ + struct rpc_ep_regsiter_state *state = + tevent_req_callback_data(subreq, struct rpc_ep_regsiter_state); + struct policy_handle entry_handle; + struct dcerpc_binding map_binding; + struct epm_twr_p_t towers[10]; + struct epm_twr_t *map_tower; + uint32_t num_towers = 0; + struct GUID object; + NTSTATUS status; + uint32_t result = EPMAPPER_STATUS_CANT_PERFORM_OP; + TALLOC_CTX *tmp_ctx; + bool ok; + + ZERO_STRUCT(object); + ZERO_STRUCT(entry_handle); + + tmp_ctx = talloc_stackframe(); + if (tmp_ctx == NULL) { + talloc_free(state); + return; + } + + ok = tevent_wakeup_recv(subreq); + TALLOC_FREE(subreq); + if (!ok) { + talloc_free(state); + return; + } + + /* Create map tower */ + map_binding.transport = NCACN_NP; + map_binding.object = state->iface->syntax_id; + map_binding.host = ""; + map_binding.endpoint = ""; + + map_tower = talloc_zero(tmp_ctx, struct epm_twr_t); + if (map_tower == NULL) { + talloc_free(tmp_ctx); + talloc_free(state); + return; + } + + status = dcerpc_binding_build_tower(map_tower, &map_binding, + &map_tower->tower); + if (!NT_STATUS_IS_OK(status)) { + talloc_free(tmp_ctx); + talloc_free(state); + return; + } + + ok = false; + status = dcerpc_epm_Map(state->h, + tmp_ctx, + &object, + map_tower, + &entry_handle, + 10, + &num_towers, + towers, + &result); + if (NT_STATUS_IS_OK(status)) { + ok = true; + } + if (result == EPMAPPER_STATUS_OK || + result == EPMAPPER_STATUS_NO_MORE_ENTRIES) { + ok = true; + } + if (num_towers == 0) { + ok = false; + } + + talloc_free(tmp_ctx); + + subreq = tevent_wakeup_send(state->mem_ctx, + state->ev_ctx, + timeval_current_ofs(MONITOR_WAIT_TIME, 0)); + if (tevent_req_nomem(state->mem_ctx, subreq)) { + talloc_free(state); + return; + } + + if (ok) { + tevent_req_set_callback(subreq, rpc_ep_setup_monitor_loop, state); + } else { + TALLOC_FREE(state->h); + state->wait_time = 1; + + tevent_req_set_callback(subreq, rpc_ep_setup_register_loop, state); + } + + return; +} + static bool epmapper_init_cb(void *ptr) { struct dcesrv_ep_context *ep_ctx = |