2 * Unix SMB/CIFS implementation.
3 * RPC Pipe client / server routines
4 * Copyright (C) Andrew Tridgell 1992-1998,
5 * Largely re-written : 2005
6 * Copyright (C) Jeremy Allison 1998 - 2005
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 3 of the License, or
11 * (at your option) any later version.
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, see <http://www.gnu.org/licenses/>.
23 #include "rpc_server/srv_pipe_internal.h"
26 #define DBGC_CLASS DBGC_RPC_SRV
28 static int pipes_open
;
30 static struct pipes_struct
*InternalPipes
;
33 * the following prototypes are declared here to avoid
34 * code being moved about too much for a patch to be
35 * disrupted / less obvious.
37 * these functions, and associated functions that they
38 * call, should be moved behind a .so module-loading
39 * system _anyway_. so that's the next step...
42 static int close_internal_rpc_pipe_hnd(struct pipes_struct
*p
);
44 /****************************************************************************
45 Internal Pipe iterator functions.
46 ****************************************************************************/
48 struct pipes_struct
*get_first_internal_pipe(void)
53 struct pipes_struct
*get_next_internal_pipe(struct pipes_struct
*p
)
58 static void free_pipe_rpc_context_internal( PIPE_RPC_FNS
*list
)
60 PIPE_RPC_FNS
*tmp
= list
;
72 bool check_open_pipes(void)
74 struct pipes_struct
*p
;
76 for (p
= InternalPipes
; p
!= NULL
; p
= p
->next
) {
77 if (num_pipe_handles(p
) != 0) {
84 /****************************************************************************
86 ****************************************************************************/
88 static int close_internal_rpc_pipe_hnd(struct pipes_struct
*p
)
91 DEBUG(0,("Invalid pipe in close_internal_rpc_pipe_hnd\n"));
95 if (p
->auth
.auth_data_free_func
) {
96 (*p
->auth
.auth_data_free_func
)(&p
->auth
);
99 free_pipe_rpc_context_internal( p
->contexts
);
101 /* Free the handles database. */
102 close_policy_by_pipe(p
);
104 DLIST_REMOVE(InternalPipes
, p
);
111 /****************************************************************************
112 Make an internal namedpipes structure
113 ****************************************************************************/
115 struct pipes_struct
*make_internal_rpc_pipe_p(TALLOC_CTX
*mem_ctx
,
116 const struct ndr_syntax_id
*syntax
,
117 const char *client_address
,
118 struct auth_serversupplied_info
*server_info
)
120 struct pipes_struct
*p
;
122 DEBUG(4,("Create pipe requested %s\n",
123 get_pipe_name_from_syntax(talloc_tos(), syntax
)));
125 p
= TALLOC_ZERO_P(mem_ctx
, struct pipes_struct
);
128 DEBUG(0,("ERROR! no memory for pipes_struct!\n"));
132 p
->mem_ctx
= talloc_named(p
, 0, "pipe %s %p",
133 get_pipe_name_from_syntax(talloc_tos(),
135 if (p
->mem_ctx
== NULL
) {
136 DEBUG(0,("open_rpc_pipe_p: talloc_init failed.\n"));
141 if (!init_pipe_handles(p
, syntax
)) {
142 DEBUG(0,("open_rpc_pipe_p: init_pipe_handles failed.\n"));
147 p
->server_info
= copy_serverinfo(p
, server_info
);
148 if (p
->server_info
== NULL
) {
149 DEBUG(0, ("open_rpc_pipe_p: copy_serverinfo failed\n"));
150 close_policy_by_pipe(p
);
155 p
->msg_ctx
= smbd_messaging_context();
157 DLIST_ADD(InternalPipes
, p
);
159 strlcpy(p
->client_address
, client_address
, sizeof(p
->client_address
));
161 p
->endian
= RPC_LITTLE_ENDIAN
;
165 DEBUG(4,("Created internal pipe %s (pipes_open=%d)\n",
166 get_pipe_name_from_syntax(talloc_tos(), syntax
), pipes_open
));
168 talloc_set_destructor(p
, close_internal_rpc_pipe_hnd
);
173 /****************************************************************************
174 ****************************************************************************/
176 static NTSTATUS
internal_ndr_push(TALLOC_CTX
*mem_ctx
,
177 struct rpc_pipe_client
*cli
,
178 const struct ndr_interface_table
*table
,
182 const struct ndr_interface_call
*call
;
183 struct ndr_push
*push
;
184 enum ndr_err_code ndr_err
;
186 if (!ndr_syntax_id_equal(&table
->syntax_id
, &cli
->abstract_syntax
) ||
187 (opnum
>= table
->num_calls
)) {
188 return NT_STATUS_INVALID_PARAMETER
;
191 call
= &table
->calls
[opnum
];
193 if (DEBUGLEVEL
>= 10) {
194 ndr_print_function_debug(call
->ndr_print
,
195 call
->name
, NDR_IN
, r
);
198 push
= ndr_push_init_ctx(mem_ctx
);
200 return NT_STATUS_NO_MEMORY
;
203 ndr_err
= call
->ndr_push(push
, NDR_IN
, r
);
204 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
206 return ndr_map_error2ntstatus(ndr_err
);
209 cli
->pipes_struct
->in_data
.data
= ndr_push_blob(push
);
210 talloc_steal(cli
->pipes_struct
->mem_ctx
,
211 cli
->pipes_struct
->in_data
.data
.data
);
217 /****************************************************************************
218 ****************************************************************************/
220 static NTSTATUS
internal_ndr_pull(TALLOC_CTX
*mem_ctx
,
221 struct rpc_pipe_client
*cli
,
222 const struct ndr_interface_table
*table
,
226 const struct ndr_interface_call
*call
;
227 struct ndr_pull
*pull
;
228 enum ndr_err_code ndr_err
;
230 if (!ndr_syntax_id_equal(&table
->syntax_id
, &cli
->abstract_syntax
) ||
231 (opnum
>= table
->num_calls
)) {
232 return NT_STATUS_INVALID_PARAMETER
;
235 call
= &table
->calls
[opnum
];
237 pull
= ndr_pull_init_blob(&cli
->pipes_struct
->out_data
.rdata
,
240 return NT_STATUS_NO_MEMORY
;
243 /* have the ndr parser alloc memory for us */
244 pull
->flags
|= LIBNDR_FLAG_REF_ALLOC
;
245 ndr_err
= call
->ndr_pull(pull
, NDR_OUT
, r
);
248 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
249 return ndr_map_error2ntstatus(ndr_err
);
252 if (DEBUGLEVEL
>= 10) {
253 ndr_print_function_debug(call
->ndr_print
,
254 call
->name
, NDR_OUT
, r
);
260 /****************************************************************************
261 ****************************************************************************/
263 static NTSTATUS
rpc_pipe_internal_dispatch(struct rpc_pipe_client
*cli
,
265 const struct ndr_interface_table
*table
,
266 uint32_t opnum
, void *r
)
269 int num_cmds
= rpc_srv_get_pipe_num_cmds(&table
->syntax_id
);
270 const struct api_struct
*cmds
= rpc_srv_get_pipe_cmds(&table
->syntax_id
);
273 if (cli
->pipes_struct
== NULL
) {
274 return NT_STATUS_INVALID_PARAMETER
;
278 cli
->pipes_struct
->opnum
= opnum
;
280 for (i
= 0; i
< num_cmds
; i
++) {
281 if (cmds
[i
].opnum
== opnum
&& cmds
[i
].fn
!= NULL
) {
287 return NT_STATUS_INVALID_PARAMETER
;
290 status
= internal_ndr_push(mem_ctx
, cli
, table
, opnum
, r
);
291 if (!NT_STATUS_IS_OK(status
)) {
295 if (!cmds
[i
].fn(cli
->pipes_struct
)) {
296 data_blob_free(&cli
->pipes_struct
->in_data
.data
);
297 data_blob_free(&cli
->pipes_struct
->out_data
.rdata
);
298 talloc_free_children(cli
->pipes_struct
->mem_ctx
);
299 return NT_STATUS_UNSUCCESSFUL
;
302 status
= internal_ndr_pull(mem_ctx
, cli
, table
, opnum
, r
);
303 if (!NT_STATUS_IS_OK(status
)) {
304 data_blob_free(&cli
->pipes_struct
->in_data
.data
);
305 data_blob_free(&cli
->pipes_struct
->out_data
.rdata
);
306 talloc_free_children(cli
->pipes_struct
->mem_ctx
);
310 data_blob_free(&cli
->pipes_struct
->in_data
.data
);
311 data_blob_free(&cli
->pipes_struct
->out_data
.rdata
);
312 talloc_free_children(cli
->pipes_struct
->mem_ctx
);
318 * @brief Create a new RPC client context which uses a local dispatch function.
320 * @param[in] mem_ctx The memory context to use.
322 * @param[in] abstract_syntax Normally the syntax_id of the autogenerated
325 * @param[in] dispatch The corresponding autogenerated dispatch function
326 * rpc_<name>_dispatch.
328 * @param[in] serversupplied_info The server supplied authentication function.
330 * @param[out] presult A pointer to store the connected rpc client pipe.
332 * @return NT_STATUS_OK on success, a corresponding NT status if an
336 * struct rpc_pipe_client *winreg_pipe;
339 * status = rpc_pipe_open_internal(tmp_ctx,
340 * &ndr_table_winreg.syntax_id,
341 * rpc_winreg_dispatch,
346 NTSTATUS
rpc_pipe_open_internal(TALLOC_CTX
*mem_ctx
,
347 const struct ndr_syntax_id
*abstract_syntax
,
348 struct auth_serversupplied_info
*serversupplied_info
,
349 struct rpc_pipe_client
**presult
)
351 struct rpc_pipe_client
*result
;
353 result
= TALLOC_ZERO_P(mem_ctx
, struct rpc_pipe_client
);
354 if (result
== NULL
) {
355 return NT_STATUS_NO_MEMORY
;
358 result
->abstract_syntax
= *abstract_syntax
;
359 result
->transfer_syntax
= ndr_transfer_syntax
;
360 result
->dispatch
= rpc_pipe_internal_dispatch
;
362 result
->pipes_struct
= make_internal_rpc_pipe_p(
363 result
, abstract_syntax
, "", serversupplied_info
);
364 if (result
->pipes_struct
== NULL
) {
366 return NT_STATUS_NO_MEMORY
;
369 result
->max_xmit_frag
= -1;
370 result
->max_recv_frag
= -1;