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
,
119 struct messaging_context
*msg_ctx
)
121 struct pipes_struct
*p
;
123 DEBUG(4,("Create pipe requested %s\n",
124 get_pipe_name_from_syntax(talloc_tos(), syntax
)));
126 p
= TALLOC_ZERO_P(mem_ctx
, struct pipes_struct
);
129 DEBUG(0,("ERROR! no memory for pipes_struct!\n"));
133 p
->mem_ctx
= talloc_named(p
, 0, "pipe %s %p",
134 get_pipe_name_from_syntax(talloc_tos(),
136 if (p
->mem_ctx
== NULL
) {
137 DEBUG(0,("open_rpc_pipe_p: talloc_init failed.\n"));
142 if (!init_pipe_handles(p
, syntax
)) {
143 DEBUG(0,("open_rpc_pipe_p: init_pipe_handles failed.\n"));
148 p
->server_info
= copy_serverinfo(p
, server_info
);
149 if (p
->server_info
== NULL
) {
150 DEBUG(0, ("open_rpc_pipe_p: copy_serverinfo failed\n"));
151 close_policy_by_pipe(p
);
156 p
->msg_ctx
= msg_ctx
;
158 DLIST_ADD(InternalPipes
, p
);
160 strlcpy(p
->client_address
, client_address
, sizeof(p
->client_address
));
162 p
->endian
= RPC_LITTLE_ENDIAN
;
166 DEBUG(4,("Created internal pipe %s (pipes_open=%d)\n",
167 get_pipe_name_from_syntax(talloc_tos(), syntax
), pipes_open
));
169 talloc_set_destructor(p
, close_internal_rpc_pipe_hnd
);
174 /****************************************************************************
175 ****************************************************************************/
177 static NTSTATUS
internal_ndr_push(TALLOC_CTX
*mem_ctx
,
178 struct rpc_pipe_client
*cli
,
179 const struct ndr_interface_table
*table
,
183 const struct ndr_interface_call
*call
;
184 struct ndr_push
*push
;
185 enum ndr_err_code ndr_err
;
187 if (!ndr_syntax_id_equal(&table
->syntax_id
, &cli
->abstract_syntax
) ||
188 (opnum
>= table
->num_calls
)) {
189 return NT_STATUS_INVALID_PARAMETER
;
192 call
= &table
->calls
[opnum
];
194 if (DEBUGLEVEL
>= 10) {
195 ndr_print_function_debug(call
->ndr_print
,
196 call
->name
, NDR_IN
, r
);
199 push
= ndr_push_init_ctx(mem_ctx
);
201 return NT_STATUS_NO_MEMORY
;
204 ndr_err
= call
->ndr_push(push
, NDR_IN
, r
);
205 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
207 return ndr_map_error2ntstatus(ndr_err
);
210 cli
->pipes_struct
->in_data
.data
= ndr_push_blob(push
);
211 talloc_steal(cli
->pipes_struct
->mem_ctx
,
212 cli
->pipes_struct
->in_data
.data
.data
);
218 /****************************************************************************
219 ****************************************************************************/
221 static NTSTATUS
internal_ndr_pull(TALLOC_CTX
*mem_ctx
,
222 struct rpc_pipe_client
*cli
,
223 const struct ndr_interface_table
*table
,
227 const struct ndr_interface_call
*call
;
228 struct ndr_pull
*pull
;
229 enum ndr_err_code ndr_err
;
231 if (!ndr_syntax_id_equal(&table
->syntax_id
, &cli
->abstract_syntax
) ||
232 (opnum
>= table
->num_calls
)) {
233 return NT_STATUS_INVALID_PARAMETER
;
236 call
= &table
->calls
[opnum
];
238 pull
= ndr_pull_init_blob(&cli
->pipes_struct
->out_data
.rdata
,
241 return NT_STATUS_NO_MEMORY
;
244 /* have the ndr parser alloc memory for us */
245 pull
->flags
|= LIBNDR_FLAG_REF_ALLOC
;
246 ndr_err
= call
->ndr_pull(pull
, NDR_OUT
, r
);
249 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
250 return ndr_map_error2ntstatus(ndr_err
);
253 if (DEBUGLEVEL
>= 10) {
254 ndr_print_function_debug(call
->ndr_print
,
255 call
->name
, NDR_OUT
, r
);
261 /****************************************************************************
262 ****************************************************************************/
264 static NTSTATUS
rpc_pipe_internal_dispatch(struct rpc_pipe_client
*cli
,
266 const struct ndr_interface_table
*table
,
267 uint32_t opnum
, void *r
)
270 int num_cmds
= rpc_srv_get_pipe_num_cmds(&table
->syntax_id
);
271 const struct api_struct
*cmds
= rpc_srv_get_pipe_cmds(&table
->syntax_id
);
274 if (cli
->pipes_struct
== NULL
) {
275 return NT_STATUS_INVALID_PARAMETER
;
279 cli
->pipes_struct
->opnum
= opnum
;
281 for (i
= 0; i
< num_cmds
; i
++) {
282 if (cmds
[i
].opnum
== opnum
&& cmds
[i
].fn
!= NULL
) {
288 return NT_STATUS_INVALID_PARAMETER
;
291 status
= internal_ndr_push(mem_ctx
, cli
, table
, opnum
, r
);
292 if (!NT_STATUS_IS_OK(status
)) {
296 if (!cmds
[i
].fn(cli
->pipes_struct
)) {
297 data_blob_free(&cli
->pipes_struct
->in_data
.data
);
298 data_blob_free(&cli
->pipes_struct
->out_data
.rdata
);
299 talloc_free_children(cli
->pipes_struct
->mem_ctx
);
300 return NT_STATUS_UNSUCCESSFUL
;
303 status
= internal_ndr_pull(mem_ctx
, cli
, table
, opnum
, r
);
304 if (!NT_STATUS_IS_OK(status
)) {
305 data_blob_free(&cli
->pipes_struct
->in_data
.data
);
306 data_blob_free(&cli
->pipes_struct
->out_data
.rdata
);
307 talloc_free_children(cli
->pipes_struct
->mem_ctx
);
311 data_blob_free(&cli
->pipes_struct
->in_data
.data
);
312 data_blob_free(&cli
->pipes_struct
->out_data
.rdata
);
313 talloc_free_children(cli
->pipes_struct
->mem_ctx
);
319 * @brief Create a new RPC client context which uses a local dispatch function.
321 * @param[in] mem_ctx The memory context to use.
323 * @param[in] abstract_syntax Normally the syntax_id of the autogenerated
326 * @param[in] dispatch The corresponding autogenerated dispatch function
327 * rpc_<name>_dispatch.
329 * @param[in] serversupplied_info The server supplied authentication function.
331 * @param[out] presult A pointer to store the connected rpc client pipe.
333 * @return NT_STATUS_OK on success, a corresponding NT status if an
337 * struct rpc_pipe_client *winreg_pipe;
340 * status = rpc_pipe_open_internal(tmp_ctx,
341 * &ndr_table_winreg.syntax_id,
342 * rpc_winreg_dispatch,
347 NTSTATUS
rpc_pipe_open_internal(TALLOC_CTX
*mem_ctx
,
348 const struct ndr_syntax_id
*abstract_syntax
,
349 struct auth_serversupplied_info
*serversupplied_info
,
350 struct messaging_context
*msg_ctx
,
351 struct rpc_pipe_client
**presult
)
353 struct rpc_pipe_client
*result
;
355 result
= TALLOC_ZERO_P(mem_ctx
, struct rpc_pipe_client
);
356 if (result
== NULL
) {
357 return NT_STATUS_NO_MEMORY
;
360 result
->abstract_syntax
= *abstract_syntax
;
361 result
->transfer_syntax
= ndr_transfer_syntax
;
362 result
->dispatch
= rpc_pipe_internal_dispatch
;
364 result
->pipes_struct
= make_internal_rpc_pipe_p(
365 result
, abstract_syntax
, "", serversupplied_info
, msg_ctx
);
366 if (result
->pipes_struct
== NULL
) {
368 return NT_STATUS_NO_MEMORY
;
371 result
->max_xmit_frag
= -1;
372 result
->max_recv_frag
= -1;