pidl:NDR/ServerCompat: Retrieve and setup pipes struct before dispatch
authorSamuel Cabrero <scabrero@suse.de>
Wed, 27 Feb 2019 22:28:25 +0000 (23:28 +0100)
committerSamuel Cabrero <scabrero@sn-devel-184>
Fri, 20 Mar 2020 15:36:35 +0000 (15:36 +0000)
Signed-off-by: Samuel Cabrero <scabrero@samba.org>
Reviewed-by: Andrew Bartlett <abartlet@samba.org>
pidl/lib/Parse/Pidl/Samba4/NDR/ServerCompat.pm
source3/rpc_server/rpc_server.c
source3/rpc_server/rpc_server.h

index 14e2cc811daebc1f174c256ba8d6149029148f74..f9e9f6a14fd887c08088981c0965df2ae1b18dea 100644 (file)
@@ -117,9 +117,59 @@ sub boilerplate_iface($)
        $self->pidl("static NTSTATUS $name\__op_bind(struct dcesrv_connection_context *context, const struct dcesrv_interface *iface)");
        $self->pidl("{");
        $self->indent();
-       $self->pidl("/* TODO Retrieve pipes struct */");
-       $self->pidl("/* TODO Init pipe handles */");
-       $self->pidl("/* TODO Init pipe context */");
+       $self->pidl("struct pipes_struct *p = NULL;");
+       $self->pidl("struct pipe_rpc_fns *context_fns = NULL;");
+       $self->pidl("bool ok = false;");
+       $self->pidl("");
+       $self->pidl("/* Retrieve pipes struct */");
+       $self->pidl("p = dcesrv_get_pipes_struct(context->conn);");
+       $self->pidl("/* Init pipe handles */");
+       $self->pidl("ok = init_pipe_handles(p, &iface->syntax_id);");
+       $self->pidl("if (!ok) {");
+       $self->indent();
+       $self->pidl("DBG_ERR(\"Failed to init pipe handles\\n\");");
+       $self->pidl("return NT_STATUS_UNSUCCESSFUL;");
+       $self->deindent();
+       $self->pidl("}");
+       $self->pidl("");
+
+       $self->pidl("/* TODO check loop */");
+
+       $self->pidl("/* Init pipe context */");
+       $self->pidl("p->pipe_bound = true;");
+       $self->pidl("for (context_fns = p->contexts; context_fns != NULL; context_fns = context_fns->next) {");
+       $self->indent();
+       $self->pidl("if (context_fns->context_id != context->context_id) {");
+       $self->indent();
+       $self->pidl("continue;");
+       $self->deindent();
+       $self->pidl("}");
+       $self->pidl("ok = ndr_syntax_id_equal(&context_fns->syntax, &iface->syntax_id);");
+       $self->pidl("if (ok) {");
+       $self->indent();
+       $self->pidl("break;");
+       $self->deindent();
+       $self->pidl("}");
+       $self->pidl("return NT_STATUS_UNSUCCESSFUL;");
+       $self->deindent();
+       $self->pidl("}");
+       $self->pidl("if (context_fns == NULL) {");
+       $self->indent();
+       $self->pidl("context_fns = talloc_zero(p, struct pipe_rpc_fns);");
+       $self->pidl("if (context_fns == NULL) {");
+       $self->indent();
+       $self->pidl("return NT_STATUS_NO_MEMORY;");
+       $self->deindent();
+       $self->pidl("}");
+       $self->pidl("");
+       $self->pidl("context_fns->next = context_fns->prev = NULL;");
+       $self->pidl("context_fns->n_cmds = rpc_srv_get_pipe_num_cmds(&iface->syntax_id);");
+       $self->pidl("context_fns->cmds = rpc_srv_get_pipe_cmds(&iface->syntax_id);");
+       $self->pidl("context_fns->context_id = context->context_id;");
+       $self->pidl("context_fns->syntax = iface->syntax_id;");
+       $self->pidl("DLIST_ADD( p->contexts, context_fns);");
+       $self->deindent();
+       $self->pidl("}");
        $self->pidlnoindent("#ifdef DCESRV_INTERFACE_$uname\_BIND");
        $self->pidl("return DCESRV_INTERFACE_$uname\_BIND(context,iface);");
        $self->pidlnoindent("#else");
@@ -178,13 +228,35 @@ sub boilerplate_iface($)
        $self->indent();
        $self->pidl("uint16_t opnum = dce_call->pkt.u.request.opnum;");
        $self->pidl("struct pipes_struct *p = NULL;");
+       $self->pidl("struct auth_session_info *pipe_session_info = NULL;");
        $self->pidl("NTSTATUS status = NT_STATUS_OK;");
+       $self->pidl("bool impersonated;");
+       $self->pidl("");
+       $self->pidl("/* Retrieve pipes struct */");
+       $self->pidl("p = dcesrv_get_pipes_struct(dce_call->conn);");
+       $self->pidl("/* Update pipes struct opnum */");
+       $self->pidl("p->opnum = opnum;");
+       $self->pidl("/* Update pipes struct session info */");
+       $self->pidl("pipe_session_info = p->session_info;");
+       $self->pidl("p->session_info = dce_call->auth_state->session_info;");
+       $self->pidl("p->auth.auth_type = dce_call->auth_state->auth_type;");
+       $self->pidl("p->auth.auth_level = dce_call->auth_state->auth_level;");
+       $self->pidl("p->auth.auth_context_id = dce_call->auth_state->auth_context_id;");
+       $self->pidl("/* Reset pipes struct fault state */");
+       $self->pidl("p->fault_state = 0;");
+       $self->pidl("");
+
+       $self->pidl("/* Impersonate */");
+       $self->pidl("impersonated = become_authenticated_pipe_user(p->session_info);");
+       $self->pidl("if (!impersonated) {");
+       $self->indent();
+       $self->pidl("dce_call->fault_code = DCERPC_FAULT_ACCESS_DENIED;");
+       $self->pidl("status = NT_STATUS_NET_WRITE_FAULT;");
+       $self->pidl("goto fail;");
+       $self->deindent();
+       $self->pidl("}");
        $self->pidl("");
-       $self->pidl("/* TODO Retrieve pipes struct */");
-       $self->pidl("/* TODO Update pipes struct opnum */");
-       $self->pidl("/* TODO Update pipes struct session info */");
-       $self->pidl("/* TODO Reset pipes struct fault state */");
-       $self->pidl("");
+
        $self->pidl("switch (opnum) {");
        $self->gen_dispatch_switch($interface);
        $self->pidl("default:");
@@ -194,7 +266,27 @@ sub boilerplate_iface($)
        $self->deindent();
        $self->pidl("}");
        $self->pidl("");
-       $self->pidl("/* TODO Check pipes struct fault state */");
+
+       $self->pidlnoindent("fail:");
+       $self->pidl("/* Unimpersonate */");
+       $self->pidl("if (impersonated) {");
+       $self->indent();
+       $self->pidl("unbecome_authenticated_pipe_user();");
+       $self->deindent();
+       $self->pidl("}");
+       $self->pidl("");
+
+       $self->pidl("/* Restore session info */");
+       $self->pidl("p->session_info = pipe_session_info;");
+       $self->pidl("p->auth.auth_type = 0;");
+       $self->pidl("p->auth.auth_level = 0;");
+       $self->pidl("p->auth.auth_context_id = 0;");
+       $self->pidl("/* Check pipes struct fault state */");
+       $self->pidl("if (p->fault_state != 0) {");
+       $self->indent();
+       $self->pidl("dce_call->fault_code = p->fault_state;");
+       $self->deindent();
+       $self->pidl("}");
        $self->pidl("if (dce_call->fault_code != 0) {");
        $self->indent();
        $self->pidl("status = NT_STATUS_NET_WRITE_FAULT;");
@@ -501,9 +593,11 @@ sub Parse($$)
        $self->pidl("#include \"$header\"");
        $self->pidl("#include \"$h_scompat\"");
        $self->pidl("#include <rpc_server/srv_pipe_register.h>");
+       $self->pidl("#include <rpc_server/srv_pipe_internal.h>");
 
        $self->pidl("#include <librpc/rpc/dcesrv_core.h>");
        $self->pidl("#include <rpc_server/rpc_config.h>");
+       $self->pidl("#include <rpc_server/rpc_server.h>");
        $self->pidl("#include <util/debug.h>");
        $self->pidl("");
 
index dbb4ce836d7ceee791af7e42cda8857d05005fdc..704dcb8a5fbec5f7c54d6a05181b859e378dd224 100644 (file)
@@ -1450,4 +1450,13 @@ NTSTATUS dcesrv_endpoint_by_ncacn_np_name(struct dcesrv_context *dce_ctx,
        return NT_STATUS_OBJECT_NAME_NOT_FOUND;
 }
 
+struct pipes_struct *dcesrv_get_pipes_struct(struct dcesrv_connection *conn)
+{
+       struct dcerpc_ncacn_conn *ncacn_conn = talloc_get_type_abort(
+                       conn->transport.private_data,
+                       struct dcerpc_ncacn_conn);
+
+       return ncacn_conn->p;
+}
+
 /* vim: set ts=8 sw=8 noet cindent syntax=c.doxygen: */
index 58d5263b641323d6107dbb833299e224adeb2842..62d219ee7e5946c2f9b54166119b8d63535780a5 100644 (file)
@@ -124,4 +124,6 @@ NTSTATUS dcesrv_endpoint_by_ncacn_np_name(struct dcesrv_context *dce_ctx,
                                          const char *endpoint,
                                          struct dcesrv_endpoint **out);
 
+struct pipes_struct *dcesrv_get_pipes_struct(struct dcesrv_connection *conn);
+
 #endif /* _PRC_SERVER_H_ */