LCOV - code coverage report
Current view: top level - source4/rpc_server/remote - dcesrv_remote.c (source / functions) Hit Total Coverage
Test: coverage report for master 2f515e9b Lines: 163 269 60.6 %
Date: 2024-04-21 15:09:00 Functions: 12 14 85.7 %

          Line data    Source code
       1             : /* 
       2             :    Unix SMB/CIFS implementation.
       3             :    remote dcerpc operations
       4             : 
       5             :    Copyright (C) Stefan (metze) Metzmacher 2004
       6             :    Copyright (C) Julien Kerihuel 2008-2009
       7             :    Copyright (C) Andrew Bartlett <abartlet@samba.org> 2010
       8             : 
       9             :    This program is free software; you can redistribute it and/or modify
      10             :    it under the terms of the GNU General Public License as published by
      11             :    the Free Software Foundation; either version 3 of the License, or
      12             :    (at your option) any later version.
      13             :    
      14             :    This program is distributed in the hope that it will be useful,
      15             :    but WITHOUT ANY WARRANTY; without even the implied warranty of
      16             :    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      17             :    GNU General Public License for more details.
      18             :    
      19             :    You should have received a copy of the GNU General Public License
      20             :    along with this program.  If not, see <http://www.gnu.org/licenses/>.
      21             : */
      22             : 
      23             : #include "includes.h"
      24             : #include <tevent.h>
      25             : #include "rpc_server/dcerpc_server.h"
      26             : #include "auth/auth.h"
      27             : #include "auth/credentials/credentials.h"
      28             : #include "librpc/rpc/dcerpc.h"
      29             : #include "librpc/ndr/ndr_table.h"
      30             : #include "param/param.h"
      31             : 
      32             : NTSTATUS dcerpc_server_remote_init(TALLOC_CTX *ctx);
      33             : 
      34             : #define DCESRV_REMOTE_ASSOC_MAGIC 0x782f50c4
      35             : struct dcesrv_remote_assoc {
      36             :         uint32_t assoc_group_id;
      37             : };
      38             : 
      39             : #define DCESRV_REMOTE_PRIVATE_MAGIC 0x7eceafa6
      40             : struct dcesrv_remote_private {
      41             :         struct dcerpc_pipe *c_pipe;
      42             : };
      43             : 
      44          62 : static NTSTATUS remote_op_reply(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, void *r)
      45             : {
      46          62 :         return NT_STATUS_OK;
      47             : }
      48             : 
      49           4 : static NTSTATUS remote_op_bind(struct dcesrv_connection_context *context,
      50             :                                const struct dcesrv_interface *iface)
      51             : {
      52           4 :         return NT_STATUS_OK;
      53             : }
      54             : 
      55          62 : static NTSTATUS remote_get_private(struct dcesrv_call_state *dce_call,
      56             :                                    struct dcesrv_remote_private **_priv)
      57             : {
      58          62 :         const struct ndr_interface_table *table =
      59          62 :                 (const struct ndr_interface_table *)dce_call->context->iface->private_data;
      60          62 :         struct dcesrv_remote_private *priv = NULL;
      61          62 :         struct dcesrv_remote_assoc *assoc = NULL;
      62          62 :         const char *binding = NULL;
      63           0 :         const char *user, *pass, *domain;
      64           0 :         struct cli_credentials *credentials;
      65          62 :         bool must_free_credentials = false;
      66           0 :         bool machine_account;
      67           0 :         bool allow_anonymous;
      68           0 :         struct dcerpc_binding           *b;
      69           0 :         struct composite_context        *pipe_conn_req;
      70          62 :         uint32_t flags = 0;
      71           0 :         NTSTATUS status;
      72             : 
      73          62 :         priv = dcesrv_iface_state_find_conn(dce_call,
      74             :                                             DCESRV_REMOTE_PRIVATE_MAGIC,
      75             :                                             struct dcesrv_remote_private);
      76          62 :         if (priv != NULL) {
      77          58 :                 *_priv = priv;
      78          58 :                 return NT_STATUS_OK;
      79             :         }
      80             : 
      81           4 :         priv = talloc_zero(dce_call, struct dcesrv_remote_private);
      82           4 :         if (priv == NULL) {
      83           0 :                 return NT_STATUS_NO_MEMORY;
      84             :         }
      85             : 
      86           4 :         assoc = dcesrv_iface_state_find_assoc(dce_call,
      87             :                                         DCESRV_REMOTE_ASSOC_MAGIC,
      88             :                                         struct dcesrv_remote_assoc);
      89           4 :         if (assoc == NULL) {
      90           2 :                 assoc = talloc_zero(dce_call, struct dcesrv_remote_assoc);
      91           2 :                 if (assoc == NULL) {
      92           0 :                         return NT_STATUS_NO_MEMORY;
      93             :                 }
      94             :         }
      95             : 
      96           4 :         binding = lpcfg_parm_string(dce_call->conn->dce_ctx->lp_ctx,
      97             :                                     NULL,
      98             :                                     "dcerpc_remote",
      99             :                                     "binding");
     100           4 :         if (binding == NULL) {
     101           0 :                 DEBUG(0,("You must specify a DCE/RPC binding string\n"));
     102           0 :                 return NT_STATUS_INVALID_PARAMETER;
     103             :         }
     104             : 
     105           4 :         user = lpcfg_parm_string(dce_call->conn->dce_ctx->lp_ctx, NULL, "dcerpc_remote", "user");
     106           4 :         pass = lpcfg_parm_string(dce_call->conn->dce_ctx->lp_ctx, NULL, "dcerpc_remote", "password");
     107           4 :         domain = lpcfg_parm_string(dce_call->conn->dce_ctx->lp_ctx, NULL, "dceprc_remote", "domain");
     108             : 
     109           4 :         machine_account = lpcfg_parm_bool(dce_call->conn->dce_ctx->lp_ctx,
     110             :                                           NULL,
     111             :                                           "dcerpc_remote",
     112             :                                           "use_machine_account",
     113             :                                           false);
     114           4 :         allow_anonymous = lpcfg_parm_bool(dce_call->conn->dce_ctx->lp_ctx,
     115             :                                           NULL,
     116             :                                           "dcerpc_remote",
     117             :                                           "allow_anonymous_fallback",
     118             :                                           false);
     119             : 
     120           4 :         credentials = dcesrv_call_credentials(dce_call);
     121             : 
     122           4 :         if (user && pass) {
     123           0 :                 bool ok;
     124             : 
     125           0 :                 DEBUG(5, ("dcerpc_remote: RPC Proxy: Using specified account\n"));
     126           0 :                 credentials = cli_credentials_init(priv);
     127           0 :                 if (!credentials) {
     128           0 :                         return NT_STATUS_NO_MEMORY;
     129             :                 }
     130           0 :                 must_free_credentials = true;
     131             : 
     132           0 :                 ok = cli_credentials_set_conf(credentials,
     133           0 :                                               dce_call->conn->dce_ctx->lp_ctx);
     134           0 :                 if (!ok) {
     135           0 :                         return NT_STATUS_INTERNAL_ERROR;
     136             :                 }
     137             : 
     138           0 :                 cli_credentials_set_username(credentials, user, CRED_SPECIFIED);
     139           0 :                 if (domain) {
     140           0 :                         cli_credentials_set_domain(credentials, domain, CRED_SPECIFIED);
     141             :                 }
     142           0 :                 cli_credentials_set_password(credentials, pass, CRED_SPECIFIED);
     143           4 :         } else if (machine_account) {
     144           0 :                 DEBUG(5, ("dcerpc_remote: RPC Proxy: Using machine account\n"));
     145           0 :                 credentials = cli_credentials_init_server(
     146             :                                 priv,
     147           0 :                                 dce_call->conn->dce_ctx->lp_ctx);
     148           0 :                 if (!credentials) {
     149           0 :                         return NT_STATUS_NO_MEMORY;
     150             :                 }
     151           0 :                 must_free_credentials = true;
     152           4 :         } else if (credentials != NULL) {
     153           0 :                 DEBUG(5, ("dcerpc_remote: RPC Proxy: Using delegated credentials\n"));
     154           4 :         } else if (allow_anonymous) {
     155           4 :                 DEBUG(5, ("dcerpc_remote: RPC Proxy: Using anonymous\n"));
     156           4 :                 credentials = cli_credentials_init_anon(priv);
     157           4 :                 if (!credentials) {
     158           0 :                         return NT_STATUS_NO_MEMORY;
     159             :                 }
     160           4 :                 must_free_credentials = true;
     161             :         } else {
     162           0 :                 DEBUG(1,("dcerpc_remote: RPC Proxy: You must supply binding, user and password or have delegated credentials\n"));
     163           0 :                 return NT_STATUS_INVALID_PARAMETER;
     164             :         }
     165             : 
     166             :         /* parse binding string to the structure */
     167           4 :         status = dcerpc_parse_binding(priv, binding, &b);
     168           4 :         if (!NT_STATUS_IS_OK(status)) {
     169           0 :                 DEBUG(0, ("Failed to parse dcerpc binding '%s'\n", binding));
     170           0 :                 return status;
     171             :         }
     172             : 
     173             :         /* If we already have a remote association group ID, then use that */
     174           4 :         if (assoc->assoc_group_id != 0) {
     175           2 :                 status = dcerpc_binding_set_assoc_group_id(b,
     176             :                         assoc->assoc_group_id);
     177           2 :                 if (!NT_STATUS_IS_OK(status)) {
     178           0 :                         DEBUG(0, ("dcerpc_binding_set_assoc_group_id() - %s'\n",
     179             :                                   nt_errstr(status)));
     180           0 :                         return status;
     181             :                 }
     182             :         }
     183             : 
     184           4 :         status = dcerpc_binding_set_abstract_syntax(b, &table->syntax_id);
     185           4 :         if (!NT_STATUS_IS_OK(status)) {
     186           0 :                 DEBUG(0, ("dcerpc_binding_set_abstract_syntax() - %s'\n",
     187             :                           nt_errstr(status)));
     188           0 :                 return status;
     189             :         }
     190             : 
     191           4 :         if (dce_call->conn->state_flags & DCESRV_CALL_STATE_FLAG_MULTIPLEXED) {
     192           2 :                 status = dcerpc_binding_set_flags(b, DCERPC_CONCURRENT_MULTIPLEX, 0);
     193           2 :                 if (!NT_STATUS_IS_OK(status)) {
     194           0 :                         DEBUG(0, ("dcerpc_binding_set_flags(CONC_MPX) - %s'\n",
     195             :                                   nt_errstr(status)));
     196           0 :                         return status;
     197             :                 }
     198             :         }
     199             : 
     200           4 :         DEBUG(3, ("Using binding %s\n", dcerpc_binding_string(dce_call->context, b)));
     201             : 
     202           4 :         pipe_conn_req = dcerpc_pipe_connect_b_send(priv, b, table,
     203           4 :                                                    credentials, dce_call->event_ctx, dce_call->conn->dce_ctx->lp_ctx);
     204           4 :         status = dcerpc_pipe_connect_b_recv(pipe_conn_req, priv, &(priv->c_pipe));
     205             :         
     206           4 :         if (must_free_credentials) {
     207           4 :                 talloc_free(credentials);
     208             :         }
     209             : 
     210           4 :         if (!NT_STATUS_IS_OK(status)) {
     211           0 :                 return status;
     212             :         }
     213             : 
     214           4 :         if (dce_call->conn->state_flags & DCESRV_CALL_STATE_FLAG_MULTIPLEXED) {
     215           2 :                 flags = dcerpc_binding_get_flags(priv->c_pipe->binding);
     216           2 :                 if (!(flags & DCERPC_CONCURRENT_MULTIPLEX)) {
     217           0 :                         DEBUG(1,("dcerpc_remote: RPC Proxy: "
     218             :                                  "Remote server doesn't support MPX\n"));
     219           0 :                         return NT_STATUS_INVALID_NETWORK_RESPONSE;
     220             :                 }
     221             :         }
     222             : 
     223           4 :         if (assoc->assoc_group_id == 0) {
     224           2 :                 assoc->assoc_group_id =
     225           2 :                         dcerpc_binding_get_assoc_group_id(priv->c_pipe->binding);
     226           2 :                 if (assoc->assoc_group_id == 0) {
     227           0 :                         return NT_STATUS_INVALID_NETWORK_RESPONSE;
     228             :                 }
     229             : 
     230           2 :                 status = dcesrv_iface_state_store_assoc(dce_call,
     231             :                                                 DCESRV_REMOTE_ASSOC_MAGIC,
     232             :                                                 assoc);
     233           2 :                 if (!NT_STATUS_IS_OK(status)) {
     234           0 :                         return status;
     235             :                 }
     236             :         }
     237             : 
     238           4 :         status = dcesrv_iface_state_store_conn(dce_call,
     239             :                                         DCESRV_REMOTE_PRIVATE_MAGIC,
     240             :                                         priv);
     241           4 :         if (!NT_STATUS_IS_OK(status)) {
     242           0 :                 return status;
     243             :         }
     244             : 
     245           4 :         *_priv = priv;
     246           4 :         return NT_STATUS_OK;
     247             : }
     248             : 
     249          62 : static NTSTATUS remote_op_ndr_pull(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, struct ndr_pull *pull, void **r)
     250             : {
     251           0 :         enum ndr_err_code ndr_err;
     252          62 :         const struct ndr_interface_table *table = (const struct ndr_interface_table *)dce_call->context->iface->private_data;
     253          62 :         uint16_t opnum = dce_call->pkt.u.request.opnum;
     254             : 
     255          62 :         dce_call->fault_code = 0;
     256             : 
     257          62 :         if (opnum >= table->num_calls) {
     258           0 :                 dce_call->fault_code = DCERPC_FAULT_OP_RNG_ERROR;
     259           0 :                 return NT_STATUS_NET_WRITE_FAULT;
     260             :         }
     261             : 
     262             :         /*
     263             :          * We don't have support for calls with pipes.
     264             :          */
     265          62 :         if (table->calls[opnum].in_pipes.num_pipes != 0) {
     266           0 :                 dce_call->fault_code = DCERPC_FAULT_OP_RNG_ERROR;
     267           0 :                 return NT_STATUS_NET_WRITE_FAULT;
     268             :         }
     269          62 :         if (table->calls[opnum].out_pipes.num_pipes != 0) {
     270           0 :                 dce_call->fault_code = DCERPC_FAULT_OP_RNG_ERROR;
     271           0 :                 return NT_STATUS_NET_WRITE_FAULT;
     272             :         }
     273             : 
     274          62 :         *r = talloc_size(mem_ctx, table->calls[opnum].struct_size);
     275          62 :         if (!*r) {
     276           0 :                 return NT_STATUS_NO_MEMORY;
     277             :         }
     278             : 
     279             :         /* unravel the NDR for the packet */
     280          62 :         ndr_err = table->calls[opnum].ndr_pull(pull, NDR_IN, *r);
     281          62 :         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
     282           0 :                 dce_call->fault_code = DCERPC_FAULT_NDR;
     283           0 :                 return NT_STATUS_NET_WRITE_FAULT;
     284             :         }
     285             : 
     286          62 :         return NT_STATUS_OK;
     287             : }
     288             : 
     289             : static void remote_op_dispatch_done(struct tevent_req *subreq);
     290             : 
     291             : struct dcesrv_remote_call {
     292             :         struct dcesrv_call_state *dce_call;
     293             :         struct dcesrv_remote_private *priv;
     294             : };
     295             : 
     296          62 : static NTSTATUS remote_op_dispatch(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, void *r)
     297             : {
     298          62 :         struct dcesrv_remote_call *rcall = NULL;
     299          62 :         struct dcesrv_remote_private *priv = NULL;
     300          62 :         uint16_t opnum = dce_call->pkt.u.request.opnum;
     301          62 :         const struct ndr_interface_table *table = dce_call->context->iface->private_data;
     302           0 :         const struct ndr_interface_call *call;
     303           0 :         const char *name;
     304           0 :         struct tevent_req *subreq;
     305           0 :         NTSTATUS status;
     306             : 
     307          62 :         name = table->calls[opnum].name;
     308          62 :         call = &table->calls[opnum];
     309             : 
     310          62 :         status = remote_get_private(dce_call, &priv);
     311          62 :         if (!NT_STATUS_IS_OK(status)) {
     312           0 :                 DEBUG(0,("dcesrv_remote: call[%s] %s\n", name, nt_errstr(status)));
     313           0 :                 return status;
     314             :         }
     315             : 
     316          62 :         rcall = talloc_zero(dce_call, struct dcesrv_remote_call);
     317          62 :         if (rcall == NULL) {
     318           0 :                 return NT_STATUS_NO_MEMORY;
     319             :         }
     320          62 :         rcall->dce_call = dce_call;
     321          62 :         rcall->priv = priv;
     322             : 
     323          62 :         if (priv->c_pipe->conn->flags & DCERPC_DEBUG_PRINT_IN) {
     324           0 :                 ndr_print_function_debug(call->ndr_print, name, NDR_IN | NDR_SET_VALUES, r);         
     325             :         }
     326             : 
     327          62 :         priv->c_pipe->conn->flags |= DCERPC_NDR_REF_ALLOC;
     328             : 
     329             :         /* we didn't use the return code of this function as we only check the last_fault_code */
     330          62 :         subreq = dcerpc_binding_handle_call_send(rcall, dce_call->event_ctx,
     331          62 :                                                  priv->c_pipe->binding_handle,
     332             :                                                  NULL, table,
     333             :                                                  opnum, mem_ctx, r);
     334          62 :         if (subreq == NULL) {
     335           0 :                 DEBUG(0,("dcesrv_remote: call[%s] dcerpc_binding_handle_call_send() failed!\n", name));
     336           0 :                 return NT_STATUS_NO_MEMORY;
     337             :         }
     338          62 :         tevent_req_set_callback(subreq, remote_op_dispatch_done, rcall);
     339             : 
     340          62 :         dce_call->state_flags |= DCESRV_CALL_STATE_FLAG_ASYNC;
     341          62 :         return NT_STATUS_OK;
     342             : }
     343             : 
     344          62 : static void remote_op_dispatch_done(struct tevent_req *subreq)
     345             : {
     346           0 :         struct dcesrv_remote_call *rcall =
     347          62 :                 tevent_req_callback_data(subreq,
     348             :                 struct dcesrv_remote_call);
     349          62 :         struct dcesrv_call_state *dce_call = rcall->dce_call;
     350          62 :         struct dcesrv_remote_private *priv = rcall->priv;
     351          62 :         uint16_t opnum = dce_call->pkt.u.request.opnum;
     352          62 :         const struct ndr_interface_table *table = dce_call->context->iface->private_data;
     353           0 :         const struct ndr_interface_call *call;
     354           0 :         const char *name;
     355           0 :         NTSTATUS status;
     356             : 
     357          62 :         name = table->calls[opnum].name;
     358          62 :         call = &table->calls[opnum];
     359             : 
     360             :         /* we didn't use the return code of this function as we only check the last_fault_code */
     361          62 :         status = dcerpc_binding_handle_call_recv(subreq);
     362          62 :         TALLOC_FREE(subreq);
     363             : 
     364          62 :         dce_call->fault_code = priv->c_pipe->last_fault_code;
     365          62 :         if (dce_call->fault_code != 0) {
     366           0 :                 DEBUG(0,("dcesrv_remote: call[%s] failed with: %s!\n",
     367             :                         name, dcerpc_errstr(dce_call, dce_call->fault_code)));
     368           0 :                 goto reply;
     369             :         }
     370             : 
     371          62 :         if (NT_STATUS_IS_OK(status) &&
     372          62 :             (priv->c_pipe->conn->flags & DCERPC_DEBUG_PRINT_OUT)) {
     373           0 :                 ndr_print_function_debug(call->ndr_print, name, NDR_OUT, dce_call->r);
     374             :         }
     375             : 
     376          62 : reply:
     377          62 :         _dcesrv_async_reply(dce_call, __func__, name);
     378          62 : }
     379             : 
     380          62 : static NTSTATUS remote_op_ndr_push(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, struct ndr_push *push, const void *r)
     381             : {
     382           0 :         enum ndr_err_code ndr_err;
     383          62 :         const struct ndr_interface_table *table = dce_call->context->iface->private_data;
     384          62 :         uint16_t opnum = dce_call->pkt.u.request.opnum;
     385             : 
     386             :         /* unravel the NDR for the packet */
     387          62 :         ndr_err = table->calls[opnum].ndr_push(push, NDR_OUT, r);
     388          62 :         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
     389           0 :                 dce_call->fault_code = DCERPC_FAULT_NDR;
     390           0 :                 return NT_STATUS_NET_WRITE_FAULT;
     391             :         }
     392             : 
     393          62 :         return NT_STATUS_OK;
     394             : }
     395             : 
     396           2 : static NTSTATUS remote_register_one_iface(struct dcesrv_context *dce_ctx, const struct dcesrv_interface *iface)
     397             : {
     398           0 :         unsigned int i;
     399           2 :         const struct ndr_interface_table *table = iface->private_data;
     400             : 
     401           8 :         for (i=0;i<table->endpoints->count;i++) {
     402           0 :                 NTSTATUS ret;
     403           6 :                 const char *name = table->endpoints->names[i];
     404             : 
     405           6 :                 ret = dcesrv_interface_register(dce_ctx, name, NULL, iface, NULL);
     406           6 :                 if (!NT_STATUS_IS_OK(ret)) {
     407           0 :                         DEBUG(1,("remote_op_init_server: failed to register endpoint '%s'\n",name));
     408           0 :                         return ret;
     409             :                 }
     410             :         }
     411             : 
     412           2 :         return NT_STATUS_OK;
     413             : }
     414             : 
     415           2 : static NTSTATUS remote_op_init_server(struct dcesrv_context *dce_ctx, const struct dcesrv_endpoint_server *ep_server)
     416             : {
     417           0 :         unsigned int i;
     418           2 :         char **ifaces = str_list_make(dce_ctx, lpcfg_parm_string(dce_ctx->lp_ctx, NULL, "dcerpc_remote", "interfaces"),NULL);
     419             : 
     420           2 :         if (!ifaces) {
     421           0 :                 DEBUG(3,("remote_op_init_server: no interfaces configured\n"));
     422           0 :                 return NT_STATUS_OK;
     423             :         }
     424             : 
     425           4 :         for (i=0;ifaces[i];i++) {
     426           0 :                 NTSTATUS ret;
     427           0 :                 struct dcesrv_interface iface;
     428             :                 
     429           2 :                 if (!ep_server->interface_by_name(&iface, ifaces[i])) {
     430           0 :                         DEBUG(0,("remote_op_init_server: failed to find interface = '%s'\n", ifaces[i]));
     431           0 :                         talloc_free(ifaces);
     432           0 :                         return NT_STATUS_UNSUCCESSFUL;
     433             :                 }
     434             : 
     435           2 :                 ret = remote_register_one_iface(dce_ctx, &iface);
     436           2 :                 if (!NT_STATUS_IS_OK(ret)) {
     437           0 :                         DEBUG(0,("remote_op_init_server: failed to register interface = '%s'\n", ifaces[i]));
     438           0 :                         talloc_free(ifaces);
     439           0 :                         return ret;
     440             :                 }
     441             :         }
     442             : 
     443           2 :         talloc_free(ifaces);
     444           2 :         return NT_STATUS_OK;
     445             : }
     446             : 
     447           0 : static NTSTATUS remote_op_shutdown_server(struct dcesrv_context *dce_ctx,
     448             :                                 const struct dcesrv_endpoint_server *ep_server)
     449             : {
     450           0 :         return NT_STATUS_OK;
     451             : }
     452             : 
     453           2 : static bool remote_fill_interface(struct dcesrv_interface *iface, const struct ndr_interface_table *if_tabl)
     454             : {
     455           2 :         iface->name = if_tabl->name;
     456           2 :         iface->syntax_id = if_tabl->syntax_id;
     457             :         
     458           2 :         iface->bind = remote_op_bind;
     459           2 :         iface->unbind = NULL;
     460             : 
     461           2 :         iface->ndr_pull = remote_op_ndr_pull;
     462           2 :         iface->dispatch = remote_op_dispatch;
     463           2 :         iface->reply = remote_op_reply;
     464           2 :         iface->ndr_push = remote_op_ndr_push;
     465             : 
     466           2 :         iface->private_data = if_tabl;
     467           2 :         iface->flags = 0;
     468             : 
     469           2 :         return true;
     470             : }
     471             : 
     472           0 : static bool remote_op_interface_by_uuid(struct dcesrv_interface *iface, const struct GUID *uuid, uint32_t if_version)
     473             : {
     474           0 :         const struct ndr_interface_list *l;
     475             : 
     476           0 :         for (l=ndr_table_list();l;l=l->next) {
     477           0 :                 if (l->table->syntax_id.if_version == if_version &&
     478           0 :                         GUID_equal(&l->table->syntax_id.uuid, uuid)==0) {
     479           0 :                         return remote_fill_interface(iface, l->table);
     480             :                 }
     481             :         }
     482             : 
     483           0 :         return false;   
     484             : }
     485             : 
     486           2 : static bool remote_op_interface_by_name(struct dcesrv_interface *iface, const char *name)
     487             : {
     488           2 :         const struct ndr_interface_table *tbl = ndr_table_by_name(name);
     489             : 
     490           2 :         if (tbl)
     491           2 :                 return remote_fill_interface(iface, tbl);
     492             : 
     493           0 :         return false;   
     494             : }
     495             : 
     496          66 : NTSTATUS dcerpc_server_remote_init(TALLOC_CTX *ctx)
     497             : {
     498           2 :         NTSTATUS ret;
     499           2 :         static const struct dcesrv_endpoint_server ep_server = {
     500             :                 /* fill in our name */
     501             :                 .name = "remote",
     502             : 
     503             :                 .initialized = false,
     504             : 
     505             :                 /* fill in all the operations */
     506             :                 .init_server = remote_op_init_server,
     507             :                 .shutdown_server = remote_op_shutdown_server,
     508             : 
     509             :                 .interface_by_uuid = remote_op_interface_by_uuid,
     510             :                 .interface_by_name = remote_op_interface_by_name
     511             :         };
     512             : 
     513             :         /* register ourselves with the DCERPC subsystem. */
     514          66 :         ret = dcerpc_register_ep_server(&ep_server);
     515          66 :         if (!NT_STATUS_IS_OK(ret)) {
     516           0 :                 DEBUG(0,("Failed to register 'remote' endpoint server!\n"));
     517           0 :                 return ret;
     518             :         }
     519             : 
     520             :         /* We need the full DCE/RPC interface table */
     521          66 :         ndr_table_init();
     522             : 
     523          66 :         return ret;
     524             : }

Generated by: LCOV version 1.14