LCOV - code coverage report
Current view: top level - source4/rpc_server/remote - dcesrv_remote.c (source / functions) Hit Total Coverage
Test: coverage report for abartlet/fix-coverage dd10fb34 Lines: 163 246 66.3 %
Date: 2021-09-23 10:06:22 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             :         const char *user, *pass, *domain;
      64             :         struct cli_credentials *credentials;
      65          62 :         bool must_free_credentials = false;
      66             :         bool machine_account;
      67             :         bool allow_anonymous;
      68             :         struct dcerpc_binding           *b;
      69             :         struct composite_context        *pipe_conn_req;
      70          62 :         uint32_t flags = 0;
      71             :         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             :                 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             :         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             :         const struct ndr_interface_call *call;
     303             :         const char *name;
     304             :         struct tevent_req *subreq;
     305             :         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          93 :         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          31 :         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             :         const struct ndr_interface_call *call;
     354             :         const char *name;
     355             :         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          93 :         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          93 : reply:
     377          62 :         status = dcesrv_reply(dce_call);
     378          62 :         if (!NT_STATUS_IS_OK(status)) {
     379           0 :                 DEBUG(0,("dcesrv_remote: call[%s]: dcesrv_reply() failed - %s\n",
     380             :                         name, nt_errstr(status)));
     381             :         }
     382          62 : }
     383             : 
     384          62 : static NTSTATUS remote_op_ndr_push(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, struct ndr_push *push, const void *r)
     385             : {
     386             :         enum ndr_err_code ndr_err;
     387          62 :         const struct ndr_interface_table *table = dce_call->context->iface->private_data;
     388          62 :         uint16_t opnum = dce_call->pkt.u.request.opnum;
     389             : 
     390             :         /* unravel the NDR for the packet */
     391          62 :         ndr_err = table->calls[opnum].ndr_push(push, NDR_OUT, r);
     392          62 :         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
     393           0 :                 dce_call->fault_code = DCERPC_FAULT_NDR;
     394           0 :                 return NT_STATUS_NET_WRITE_FAULT;
     395             :         }
     396             : 
     397          62 :         return NT_STATUS_OK;
     398             : }
     399             : 
     400           2 : static NTSTATUS remote_register_one_iface(struct dcesrv_context *dce_ctx, const struct dcesrv_interface *iface)
     401             : {
     402             :         unsigned int i;
     403           2 :         const struct ndr_interface_table *table = iface->private_data;
     404             : 
     405           8 :         for (i=0;i<table->endpoints->count;i++) {
     406             :                 NTSTATUS ret;
     407           6 :                 const char *name = table->endpoints->names[i];
     408             : 
     409           6 :                 ret = dcesrv_interface_register(dce_ctx, name, NULL, iface, NULL);
     410           6 :                 if (!NT_STATUS_IS_OK(ret)) {
     411           0 :                         DEBUG(1,("remote_op_init_server: failed to register endpoint '%s'\n",name));
     412           0 :                         return ret;
     413             :                 }
     414             :         }
     415             : 
     416           2 :         return NT_STATUS_OK;
     417             : }
     418             : 
     419           2 : static NTSTATUS remote_op_init_server(struct dcesrv_context *dce_ctx, const struct dcesrv_endpoint_server *ep_server)
     420             : {
     421             :         unsigned int i;
     422           2 :         char **ifaces = str_list_make(dce_ctx, lpcfg_parm_string(dce_ctx->lp_ctx, NULL, "dcerpc_remote", "interfaces"),NULL);
     423             : 
     424           2 :         if (!ifaces) {
     425           0 :                 DEBUG(3,("remote_op_init_server: no interfaces configured\n"));
     426           0 :                 return NT_STATUS_OK;
     427             :         }
     428             : 
     429           6 :         for (i=0;ifaces[i];i++) {
     430             :                 NTSTATUS ret;
     431             :                 struct dcesrv_interface iface;
     432             :                 
     433           2 :                 if (!ep_server->interface_by_name(&iface, ifaces[i])) {
     434           0 :                         DEBUG(0,("remote_op_init_server: failed to find interface = '%s'\n", ifaces[i]));
     435           0 :                         talloc_free(ifaces);
     436           0 :                         return NT_STATUS_UNSUCCESSFUL;
     437             :                 }
     438             : 
     439           2 :                 ret = remote_register_one_iface(dce_ctx, &iface);
     440           2 :                 if (!NT_STATUS_IS_OK(ret)) {
     441           0 :                         DEBUG(0,("remote_op_init_server: failed to register interface = '%s'\n", ifaces[i]));
     442           0 :                         talloc_free(ifaces);
     443           0 :                         return ret;
     444             :                 }
     445             :         }
     446             : 
     447           2 :         talloc_free(ifaces);
     448           2 :         return NT_STATUS_OK;
     449             : }
     450             : 
     451           0 : static NTSTATUS remote_op_shutdown_server(struct dcesrv_context *dce_ctx,
     452             :                                 const struct dcesrv_endpoint_server *ep_server)
     453             : {
     454           0 :         return NT_STATUS_OK;
     455             : }
     456             : 
     457           2 : static bool remote_fill_interface(struct dcesrv_interface *iface, const struct ndr_interface_table *if_tabl)
     458             : {
     459           2 :         iface->name = if_tabl->name;
     460           2 :         iface->syntax_id = if_tabl->syntax_id;
     461             :         
     462           2 :         iface->bind = remote_op_bind;
     463           2 :         iface->unbind = NULL;
     464             : 
     465           2 :         iface->ndr_pull = remote_op_ndr_pull;
     466           2 :         iface->dispatch = remote_op_dispatch;
     467           2 :         iface->reply = remote_op_reply;
     468           2 :         iface->ndr_push = remote_op_ndr_push;
     469             : 
     470           2 :         iface->private_data = if_tabl;
     471           2 :         iface->flags = 0;
     472             : 
     473           2 :         return true;
     474             : }
     475             : 
     476           0 : static bool remote_op_interface_by_uuid(struct dcesrv_interface *iface, const struct GUID *uuid, uint32_t if_version)
     477             : {
     478             :         const struct ndr_interface_list *l;
     479             : 
     480           0 :         for (l=ndr_table_list();l;l=l->next) {
     481           0 :                 if (l->table->syntax_id.if_version == if_version &&
     482           0 :                         GUID_equal(&l->table->syntax_id.uuid, uuid)==0) {
     483           0 :                         return remote_fill_interface(iface, l->table);
     484             :                 }
     485             :         }
     486             : 
     487           0 :         return false;   
     488             : }
     489             : 
     490           2 : static bool remote_op_interface_by_name(struct dcesrv_interface *iface, const char *name)
     491             : {
     492           2 :         const struct ndr_interface_table *tbl = ndr_table_by_name(name);
     493             : 
     494           2 :         if (tbl)
     495           2 :                 return remote_fill_interface(iface, tbl);
     496             : 
     497           0 :         return false;   
     498             : }
     499             : 
     500          64 : NTSTATUS dcerpc_server_remote_init(TALLOC_CTX *ctx)
     501             : {
     502             :         NTSTATUS ret;
     503             :         static const struct dcesrv_endpoint_server ep_server = {
     504             :                 /* fill in our name */
     505             :                 .name = "remote",
     506             : 
     507             :                 .initialized = false,
     508             : 
     509             :                 /* fill in all the operations */
     510             :                 .init_server = remote_op_init_server,
     511             :                 .shutdown_server = remote_op_shutdown_server,
     512             : 
     513             :                 .interface_by_uuid = remote_op_interface_by_uuid,
     514             :                 .interface_by_name = remote_op_interface_by_name
     515             :         };
     516             : 
     517             :         /* register ourselves with the DCERPC subsystem. */
     518          64 :         ret = dcerpc_register_ep_server(&ep_server);
     519          64 :         if (!NT_STATUS_IS_OK(ret)) {
     520           0 :                 DEBUG(0,("Failed to register 'remote' endpoint server!\n"));
     521           0 :                 return ret;
     522             :         }
     523             : 
     524             :         /* We need the full DCE/RPC interface table */
     525          64 :         ndr_table_init();
     526             : 
     527          64 :         return ret;
     528             : }

Generated by: LCOV version 1.13