From 06a913a2699627bda45acab7225da1e4dc849d84 Mon Sep 17 00:00:00 2001 From: Samuel Cabrero Date: Wed, 27 Feb 2019 21:36:22 +0100 Subject: [PATCH] s3:rpc_server: Retrieve dcesrv_context from parent context to open NP Get the dcesrv_context from parent context and use it to search the endpoint serving the named pipe. Once we have the endpoint pass it to the make_internal_rpc_pipe_socketpair function. Signed-off-by: Samuel Cabrero Reviewed-by: Andrew Bartlett --- source3/rpc_server/rpc_ncacn_np.c | 12 ++-- source3/rpc_server/rpc_ncacn_np.h | 6 +- source3/rpc_server/rpc_server.c | 34 ++++++++++ source3/rpc_server/rpc_server.h | 4 ++ source3/rpc_server/srv_pipe.c | 12 +++- source3/rpc_server/srv_pipe.h | 7 +- source3/rpc_server/srv_pipe_hnd.c | 9 +-- source3/rpc_server/srv_pipe_hnd.h | 1 + source3/smbd/pipes.c | 1 + testsuite/unittests/test_sambafs_srv_pipe.c | 75 ++++++++++++++------- 10 files changed, 123 insertions(+), 38 deletions(-) diff --git a/source3/rpc_server/rpc_ncacn_np.c b/source3/rpc_server/rpc_ncacn_np.c index 6f28ba13c64..a0a880985e1 100644 --- a/source3/rpc_server/rpc_ncacn_np.c +++ b/source3/rpc_server/rpc_ncacn_np.c @@ -97,8 +97,8 @@ NTSTATUS make_internal_rpc_pipe_socketpair( TALLOC_CTX *mem_ctx, struct tevent_context *ev_ctx, struct messaging_context *msg_ctx, - const char *pipe_name, - const struct ndr_syntax_id *syntax, + struct dcesrv_context *dce_ctx, + struct dcesrv_endpoint *endpoint, const struct tsocket_address *remote_address, const struct tsocket_address *local_address, const struct auth_session_info *session_info, @@ -111,6 +111,10 @@ NTSTATUS make_internal_rpc_pipe_socketpair( NTSTATUS status; int error; int rc; + enum dcerpc_transport_t transport = dcerpc_binding_get_transport( + endpoint->ep_description); + const char *pipe_name = dcerpc_binding_get_string_option( + endpoint->ep_description, "endpoint"); DEBUG(4, ("Create of internal pipe %s requested\n", pipe_name)); @@ -184,8 +188,8 @@ NTSTATUS make_internal_rpc_pipe_socketpair( rc = make_server_pipes_struct(ncacn_conn, ncacn_conn->msg_ctx, - ncacn_conn->name, - ncacn_conn->transport, + pipe_name, + transport, ncacn_conn->remote_client_addr, ncacn_conn->local_server_addr, &ncacn_conn->session_info, diff --git a/source3/rpc_server/rpc_ncacn_np.h b/source3/rpc_server/rpc_ncacn_np.h index 705306c7793..25565f52159 100644 --- a/source3/rpc_server/rpc_ncacn_np.h +++ b/source3/rpc_server/rpc_ncacn_np.h @@ -23,6 +23,8 @@ struct dcerpc_binding_handle; struct ndr_interface_table; struct tsocket_address; +struct dcesrv_context; +struct dcesrv_endpoint; struct npa_state { struct tstream_context *stream; @@ -48,8 +50,8 @@ NTSTATUS make_internal_rpc_pipe_socketpair( TALLOC_CTX *mem_ctx, struct tevent_context *ev_ctx, struct messaging_context *msg_ctx, - const char *pipe_name, - const struct ndr_syntax_id *syntax, + struct dcesrv_context *dce_ctx, + struct dcesrv_endpoint *endpoint, const struct tsocket_address *remote_address, const struct tsocket_address *local_address, const struct auth_session_info *session_info, diff --git a/source3/rpc_server/rpc_server.c b/source3/rpc_server/rpc_server.c index 0a170e96989..713d9cf6342 100644 --- a/source3/rpc_server/rpc_server.c +++ b/source3/rpc_server/rpc_server.c @@ -1419,4 +1419,38 @@ static void ncacn_terminate_connection(struct dcerpc_ncacn_conn *conn, talloc_free(conn); } +NTSTATUS dcesrv_endpoint_by_ncacn_np_name(struct dcesrv_context *dce_ctx, + const char *pipe_name, + struct dcesrv_endpoint **out) +{ + struct dcesrv_endpoint *e = NULL; + + for (e = dce_ctx->endpoint_list; e; e = e->next) { + enum dcerpc_transport_t transport = + dcerpc_binding_get_transport(e->ep_description); + const char *endpoint = NULL; + + if (transport != NCACN_NP) { + continue; + } + + endpoint = dcerpc_binding_get_string_option(e->ep_description, + "endpoint"); + if (endpoint == NULL) { + continue; + } + + if (strncmp(endpoint, "\\pipe\\", 6) == 0) { + endpoint += 6; + } + + if (strequal(endpoint, pipe_name)) { + *out = e; + return NT_STATUS_OK; + } + } + + return NT_STATUS_OBJECT_NAME_NOT_FOUND; +} + /* vim: set ts=8 sw=8 noet cindent syntax=c.doxygen: */ diff --git a/source3/rpc_server/rpc_server.h b/source3/rpc_server/rpc_server.h index 832b6bba423..f91f561dc3c 100644 --- a/source3/rpc_server/rpc_server.h +++ b/source3/rpc_server/rpc_server.h @@ -121,4 +121,8 @@ NTSTATUS dcesrv_auth_gensec_prepare(TALLOC_CTX *mem_ctx, void dcesrv_log_successful_authz(struct dcesrv_call_state *call); NTSTATUS dcesrv_assoc_group_find(struct dcesrv_call_state *call); +NTSTATUS dcesrv_endpoint_by_ncacn_np_name(struct dcesrv_context *dce_ctx, + const char *endpoint, + struct dcesrv_endpoint **out); + #endif /* _PRC_SERVER_H_ */ diff --git a/source3/rpc_server/srv_pipe.c b/source3/rpc_server/srv_pipe.c index 3bc291fb0c9..446ac95e5cc 100644 --- a/source3/rpc_server/srv_pipe.c +++ b/source3/rpc_server/srv_pipe.c @@ -474,10 +474,14 @@ static bool check_bind_req(struct pipes_struct *p, /** * Is a named pipe known? + * @param[in] dce_ctx The rpc server context * @param[in] pipename Just the filename + * @param[out] endpoint The DCERPC endpoint serving the pipe name * @result NT error code */ -NTSTATUS is_known_pipename(const char *pipename, struct ndr_syntax_id *syntax) +NTSTATUS is_known_pipename(struct dcesrv_context *dce_ctx, + const char *pipename, + struct dcesrv_endpoint **ep) { NTSTATUS status; @@ -491,7 +495,8 @@ NTSTATUS is_known_pipename(const char *pipename, struct ndr_syntax_id *syntax) return NT_STATUS_OBJECT_NAME_NOT_FOUND; } - if (rpc_srv_get_pipe_interface_by_cli_name(pipename, syntax)) { + status = dcesrv_endpoint_by_ncacn_np_name(dce_ctx, pipename, ep); + if (NT_STATUS_IS_OK(status)) { return NT_STATUS_OK; } @@ -505,7 +510,8 @@ NTSTATUS is_known_pipename(const char *pipename, struct ndr_syntax_id *syntax) /* * Scan the list again for the interface id */ - if (rpc_srv_get_pipe_interface_by_cli_name(pipename, syntax)) { + status = dcesrv_endpoint_by_ncacn_np_name(dce_ctx, pipename, ep); + if (NT_STATUS_IS_OK(status)) { return NT_STATUS_OK; } diff --git a/source3/rpc_server/srv_pipe.h b/source3/rpc_server/srv_pipe.h index 0a28f72d241..d9d15adbf4e 100644 --- a/source3/rpc_server/srv_pipe.h +++ b/source3/rpc_server/srv_pipe.h @@ -22,13 +22,16 @@ struct ncacn_packet; struct pipes_struct; +struct dcesrv_context; +struct dcesrv_endpoint; /* The following definitions come from rpc_server/srv_pipe.c */ bool create_next_pdu(struct pipes_struct *p); bool api_pipe_bind_auth3(struct pipes_struct *p, struct ncacn_packet *pkt); bool setup_fault_pdu(struct pipes_struct *p, NTSTATUS status); -NTSTATUS is_known_pipename(const char *cli_filename, - struct ndr_syntax_id *syntax); +NTSTATUS is_known_pipename(struct dcesrv_context *dce_ctx, + const char *pipename, + struct dcesrv_endpoint **ep); #endif /* _RPC_SERVER_SRV_PIPE_H_ */ diff --git a/source3/rpc_server/srv_pipe_hnd.c b/source3/rpc_server/srv_pipe_hnd.c index 963af1486a1..29d393b51dc 100644 --- a/source3/rpc_server/srv_pipe_hnd.c +++ b/source3/rpc_server/srv_pipe_hnd.c @@ -54,12 +54,13 @@ NTSTATUS np_open(TALLOC_CTX *mem_ctx, const char *name, struct auth_session_info *session_info, struct tevent_context *ev_ctx, struct messaging_context *msg_ctx, + struct dcesrv_context *dce_ctx, struct fake_file_handle **phandle) { enum rpc_service_mode_e pipe_mode; const char **proxy_list; struct fake_file_handle *handle; - struct ndr_syntax_id syntax; + struct dcesrv_endpoint *endpoint = NULL; struct npa_state *npa = NULL; NTSTATUS status; @@ -98,7 +99,7 @@ NTSTATUS np_open(TALLOC_CTX *mem_ctx, const char *name, break; case RPC_SERVICE_MODE_EMBEDDED: /* Check if we handle this pipe internally */ - status = is_known_pipename(name, &syntax); + status = is_known_pipename(dce_ctx, name, &endpoint); if (!NT_STATUS_IS_OK(status)) { DBG_WARNING("'%s' is not a registered pipe!\n", name); talloc_free(handle); @@ -109,8 +110,8 @@ NTSTATUS np_open(TALLOC_CTX *mem_ctx, const char *name, handle, ev_ctx, msg_ctx, - name, - &syntax, + dce_ctx, + endpoint, remote_client_address, local_server_address, session_info, diff --git a/source3/rpc_server/srv_pipe_hnd.h b/source3/rpc_server/srv_pipe_hnd.h index 26fc351043e..ba351357b69 100644 --- a/source3/rpc_server/srv_pipe_hnd.h +++ b/source3/rpc_server/srv_pipe_hnd.h @@ -34,6 +34,7 @@ NTSTATUS np_open(TALLOC_CTX *mem_ctx, const char *name, struct auth_session_info *session_info, struct tevent_context *ev_ctx, struct messaging_context *msg_ctx, + struct dcesrv_context *dce_ctx, struct fake_file_handle **phandle); bool np_read_in_progress(struct fake_file_handle *handle); struct tevent_req *np_write_send(TALLOC_CTX *mem_ctx, struct tevent_context *ev, diff --git a/source3/smbd/pipes.c b/source3/smbd/pipes.c index 4be57bc2a5f..dd72d163134 100644 --- a/source3/smbd/pipes.c +++ b/source3/smbd/pipes.c @@ -69,6 +69,7 @@ NTSTATUS open_np_file(struct smb_request *smb_req, const char *name, conn->session_info, conn->sconn->ev_ctx, conn->sconn->msg_ctx, + conn->sconn->dce_ctx, &fsp->fake_file_handle); if (!NT_STATUS_IS_OK(status)) { DEBUG(10, ("np_open(%s) returned %s\n", name, diff --git a/testsuite/unittests/test_sambafs_srv_pipe.c b/testsuite/unittests/test_sambafs_srv_pipe.c index 161f7131e8e..40798b588c7 100644 --- a/testsuite/unittests/test_sambafs_srv_pipe.c +++ b/testsuite/unittests/test_sambafs_srv_pipe.c @@ -9,55 +9,86 @@ #include "include/config.h" #include "librpc/gen_ndr/ndr_samr.h" +#include "librpc/gen_ndr/ndr_samr_scompat.h" #include "source3/rpc_server/srv_pipe.h" -#include "librpc/gen_ndr/srv_samr.h" +#include "librpc/rpc/rpc_common.h" +#include "librpc/rpc/dcesrv_core.h" +#include "talloc.h" + +struct test_state { + TALLOC_CTX *mem_ctx; + struct loadparm_context *lp_ctx; + struct dcesrv_context *dce_ctx; +}; static int setup_samr(void **state) { - rpc_samr_init(NULL); + TALLOC_CTX *mem_ctx; + struct test_state *s; + const struct dcesrv_endpoint_server *ep_server; + NTSTATUS status; - return 0; -} + mem_ctx = talloc_new(NULL); + assert_non_null(mem_ctx); -static int teardown(void **state) -{ - unsetenv("UNITTEST_DUMMY_MODULE_LOADED"); + s = talloc_zero(mem_ctx, struct test_state); + assert_non_null(s); + + s->mem_ctx = mem_ctx; + + ep_server = samr_get_ep_server(); + assert_non_null(ep_server); + + status = dcerpc_register_ep_server(ep_server); + assert_true(NT_STATUS_IS_OK(status)); + + status = dcesrv_init_context(s, NULL, NULL, &s->dce_ctx); + assert_true(NT_STATUS_IS_OK(status)); + + status = dcesrv_init_ep_server(s->dce_ctx, "samr"); + assert_true(NT_STATUS_IS_OK(status)); + + *state = s; return 0; } static int teardown_samr(void **state) { - rpc_samr_shutdown(); + struct test_state *s = talloc_get_type_abort(*state, + struct test_state); - teardown(state); + unsetenv("UNITTEST_DUMMY_MODULE_LOADED"); + + dcesrv_shutdown_ep_server(s->dce_ctx, "samr"); + + talloc_free(s->mem_ctx); return 0; } static void test_is_known_pipename(void **state) { - struct ndr_syntax_id syntax_id = ndr_table_samr.syntax_id; - NTSTATUS status; - - status = is_known_pipename("samr", &syntax_id); - assert_true(NT_STATUS_IS_OK(status)); -} - -static void test_is_known_pipename_slash(void **state) -{ - struct ndr_syntax_id syntax_id = ndr_table_samr.syntax_id; + struct test_state *s = talloc_get_type_abort(*state, + struct test_state); + struct dcesrv_endpoint *ep; char dummy_module_path[4096] = {0}; const char *module_env; NTSTATUS status; + status = is_known_pipename(s->dce_ctx, "samr", &ep); + assert_true(NT_STATUS_IS_OK(status)); + + status = is_known_pipename(s->dce_ctx, "SAMR", &ep); + assert_true(NT_STATUS_IS_OK(status)); + snprintf(dummy_module_path, sizeof(dummy_module_path), "%s/bin/modules/rpc/test_dummy_module.so", SRCDIR); - status = is_known_pipename(dummy_module_path, &syntax_id); - assert_true(NT_STATUS_IS_ERR(status)); + status = is_known_pipename(s->dce_ctx, dummy_module_path, &ep); + assert_false(NT_STATUS_IS_OK(status)); module_env = getenv("UNITTEST_DUMMY_MODULE_LOADED"); assert_null(module_env); @@ -68,8 +99,6 @@ int main(void) { cmocka_unit_test_setup_teardown(test_is_known_pipename, setup_samr, teardown_samr), - cmocka_unit_test_teardown(test_is_known_pipename_slash, - teardown), }; cmocka_set_message_output(CM_OUTPUT_SUBUNIT);