2 Unix SMB/CIFS implementation.
4 smbd-specific dcerpc server code
6 Copyright (C) Andrew Tridgell 2003-2005
7 Copyright (C) Stefan (metze) Metzmacher 2004-2005
8 Copyright (C) Jelmer Vernooij <jelmer@samba.org> 2004,2007
10 This program is free software; you can redistribute it and/or modify
11 it under the terms of the GNU General Public License as published by
12 the Free Software Foundation; either version 3 of the License, or
13 (at your option) any later version.
15 This program is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 GNU General Public License for more details.
20 You should have received a copy of the GNU General Public License
21 along with this program. If not, see <http://www.gnu.org/licenses/>.
25 #include "librpc/gen_ndr/ndr_dcerpc.h"
26 #include "auth/auth.h"
27 #include "auth/gensec/gensec.h"
28 #include "lib/util/dlinklist.h"
29 #include "rpc_server/dcerpc_server.h"
30 #include "lib/events/events.h"
31 #include "smbd/service_task.h"
32 #include "smbd/service_stream.h"
33 #include "smbd/service.h"
34 #include "system/filesys.h"
35 #include "libcli/security/security.h"
36 #include "lib/socket/socket.h"
37 #include "lib/messaging/irpc.h"
38 #include "system/network.h"
39 #include "lib/socket/netif.h"
40 #include "param/param.h"
42 struct dcesrv_socket_context
{
43 const struct dcesrv_endpoint
*endpoint
;
44 struct dcesrv_context
*dcesrv_ctx
;
48 write_fn callback for dcesrv_output()
50 static NTSTATUS
dcerpc_write_fn(void *private_data
, DATA_BLOB
*out
, size_t *nwritten
)
53 struct socket_context
*sock
= talloc_get_type(private_data
, struct socket_context
);
56 status
= socket_send(sock
, out
, &sendlen
);
57 NT_STATUS_IS_ERR_RETURN(status
);
63 static void dcesrv_terminate_connection(struct dcesrv_connection
*dce_conn
, const char *reason
)
65 struct stream_connection
*srv_conn
;
66 srv_conn
= talloc_get_type(dce_conn
->transport
.private_data
,
67 struct stream_connection
);
69 stream_terminate_connection(srv_conn
, reason
);
72 static void dcesrv_sock_report_output_data(struct dcesrv_connection
*dcesrv_conn
)
74 struct stream_connection
*srv_conn
;
75 srv_conn
= talloc_get_type(dcesrv_conn
->transport
.private_data
,
76 struct stream_connection
);
78 if (srv_conn
&& srv_conn
->event
.fde
) {
79 EVENT_FD_WRITEABLE(srv_conn
->event
.fde
);
83 static struct socket_address
*dcesrv_sock_get_my_addr(struct dcesrv_connection
*dcesrv_conn
, TALLOC_CTX
*mem_ctx
)
85 struct stream_connection
*srv_conn
;
86 srv_conn
= talloc_get_type(dcesrv_conn
->transport
.private_data
,
87 struct stream_connection
);
89 return socket_get_my_addr(srv_conn
->socket
, mem_ctx
);
92 static struct socket_address
*dcesrv_sock_get_peer_addr(struct dcesrv_connection
*dcesrv_conn
, TALLOC_CTX
*mem_ctx
)
94 struct stream_connection
*srv_conn
;
95 srv_conn
= talloc_get_type(dcesrv_conn
->transport
.private_data
,
96 struct stream_connection
);
98 return socket_get_peer_addr(srv_conn
->socket
, mem_ctx
);
101 static void dcesrv_sock_accept(struct stream_connection
*srv_conn
)
104 struct dcesrv_socket_context
*dcesrv_sock
=
105 talloc_get_type(srv_conn
->private, struct dcesrv_socket_context
);
106 struct dcesrv_connection
*dcesrv_conn
= NULL
;
108 if (!srv_conn
->session_info
) {
109 status
= auth_anonymous_session_info(srv_conn
,
112 &srv_conn
->session_info
);
113 if (!NT_STATUS_IS_OK(status
)) {
114 DEBUG(0,("dcesrv_sock_accept: auth_anonymous_session_info failed: %s\n",
116 stream_terminate_connection(srv_conn
, nt_errstr(status
));
121 status
= dcesrv_endpoint_connect(dcesrv_sock
->dcesrv_ctx
,
123 dcesrv_sock
->endpoint
,
124 srv_conn
->session_info
,
128 DCESRV_CALL_STATE_FLAG_MAY_ASYNC
,
130 if (!NT_STATUS_IS_OK(status
)) {
131 DEBUG(0,("dcesrv_sock_accept: dcesrv_endpoint_connect failed: %s\n",
133 stream_terminate_connection(srv_conn
, nt_errstr(status
));
137 dcesrv_conn
->transport
.private_data
= srv_conn
;
138 dcesrv_conn
->transport
.report_output_data
= dcesrv_sock_report_output_data
;
139 dcesrv_conn
->transport
.get_my_addr
= dcesrv_sock_get_my_addr
;
140 dcesrv_conn
->transport
.get_peer_addr
= dcesrv_sock_get_peer_addr
;
142 srv_conn
->private = dcesrv_conn
;
144 irpc_add_name(srv_conn
->msg_ctx
, "rpc_server");
149 static void dcesrv_sock_recv(struct stream_connection
*conn
, uint16_t flags
)
152 struct dcesrv_connection
*dce_conn
= talloc_get_type(conn
->private, struct dcesrv_connection
);
156 if (dce_conn
->processing
) {
157 EVENT_FD_NOT_READABLE(conn
->event
.fde
);
161 tmp_blob
= data_blob_talloc(conn
->socket
, NULL
, 0x1000);
162 if (tmp_blob
.data
== NULL
) {
163 dcesrv_terminate_connection(dce_conn
, "out of memory");
167 status
= socket_recv(conn
->socket
, tmp_blob
.data
, tmp_blob
.length
, &nread
);
168 if (NT_STATUS_IS_ERR(status
)) {
169 dcesrv_terminate_connection(dce_conn
, nt_errstr(status
));
173 talloc_free(tmp_blob
.data
);
177 tmp_blob
.length
= nread
;
179 dce_conn
->processing
= true;
180 status
= dcesrv_input(dce_conn
, &tmp_blob
);
181 dce_conn
->processing
= false;
182 talloc_free(tmp_blob
.data
);
184 EVENT_FD_READABLE(conn
->event
.fde
);
186 if (!NT_STATUS_IS_OK(status
)) {
187 dcesrv_terminate_connection(dce_conn
, nt_errstr(status
));
191 if (dce_conn
->call_list
&& dce_conn
->call_list
->replies
) {
192 EVENT_FD_WRITEABLE(conn
->event
.fde
);
196 static void dcesrv_sock_send(struct stream_connection
*conn
, uint16_t flags
)
198 struct dcesrv_connection
*dce_conn
= talloc_get_type(conn
->private, struct dcesrv_connection
);
201 status
= dcesrv_output(dce_conn
, conn
->socket
, dcerpc_write_fn
);
202 if (NT_STATUS_IS_ERR(status
)) {
203 dcesrv_terminate_connection(dce_conn
, "eof on socket");
207 if (!dce_conn
->call_list
|| !dce_conn
->call_list
->replies
) {
208 EVENT_FD_NOT_WRITEABLE(conn
->event
.fde
);
213 static const struct stream_server_ops dcesrv_stream_ops
= {
215 .accept_connection
= dcesrv_sock_accept
,
216 .recv_handler
= dcesrv_sock_recv
,
217 .send_handler
= dcesrv_sock_send
,
222 static NTSTATUS
dcesrv_add_ep_unix(struct dcesrv_context
*dce_ctx
,
223 struct loadparm_context
*lp_ctx
,
224 struct dcesrv_endpoint
*e
,
225 struct event_context
*event_ctx
, const struct model_ops
*model_ops
)
227 struct dcesrv_socket_context
*dcesrv_sock
;
231 dcesrv_sock
= talloc(event_ctx
, struct dcesrv_socket_context
);
232 NT_STATUS_HAVE_NO_MEMORY(dcesrv_sock
);
234 /* remember the endpoint of this socket */
235 dcesrv_sock
->endpoint
= e
;
236 dcesrv_sock
->dcesrv_ctx
= talloc_reference(dcesrv_sock
, dce_ctx
);
238 status
= stream_setup_socket(event_ctx
, lp_ctx
,
239 model_ops
, &dcesrv_stream_ops
,
240 "unix", e
->ep_description
->endpoint
, &port
,
241 lp_socket_options(lp_ctx
),
243 if (!NT_STATUS_IS_OK(status
)) {
244 DEBUG(0,("service_setup_stream_socket(path=%s) failed - %s\n",
245 e
->ep_description
->endpoint
, nt_errstr(status
)));
251 static NTSTATUS
dcesrv_add_ep_ncalrpc(struct dcesrv_context
*dce_ctx
,
252 struct loadparm_context
*lp_ctx
,
253 struct dcesrv_endpoint
*e
,
254 struct event_context
*event_ctx
, const struct model_ops
*model_ops
)
256 struct dcesrv_socket_context
*dcesrv_sock
;
261 if (!e
->ep_description
->endpoint
) {
262 /* No identifier specified: use DEFAULT.
263 * DO NOT hardcode this value anywhere else. Rather, specify
264 * no endpoint and let the epmapper worry about it. */
265 e
->ep_description
->endpoint
= talloc_strdup(dce_ctx
, "DEFAULT");
268 full_path
= talloc_asprintf(dce_ctx
, "%s/%s", lp_ncalrpc_dir(lp_ctx
),
269 e
->ep_description
->endpoint
);
271 dcesrv_sock
= talloc(event_ctx
, struct dcesrv_socket_context
);
272 NT_STATUS_HAVE_NO_MEMORY(dcesrv_sock
);
274 /* remember the endpoint of this socket */
275 dcesrv_sock
->endpoint
= e
;
276 dcesrv_sock
->dcesrv_ctx
= talloc_reference(dcesrv_sock
, dce_ctx
);
278 status
= stream_setup_socket(event_ctx
, lp_ctx
,
279 model_ops
, &dcesrv_stream_ops
,
280 "unix", full_path
, &port
,
281 lp_socket_options(lp_ctx
),
283 if (!NT_STATUS_IS_OK(status
)) {
284 DEBUG(0,("service_setup_stream_socket(identifier=%s,path=%s) failed - %s\n",
285 e
->ep_description
->endpoint
, full_path
, nt_errstr(status
)));
292 add a socket address to the list of events, one event per dcerpc endpoint
294 static NTSTATUS
add_socket_rpc_pipe_iface(struct dcesrv_context
*dce_ctx
, struct dcesrv_endpoint
*e
,
295 struct event_context
*event_ctx
, const struct model_ops
*model_ops
)
297 struct dcesrv_socket_context
*dcesrv_sock
;
300 if (e
->ep_description
->endpoint
== NULL
) {
301 DEBUG(0, ("Endpoint mandatory for named pipes\n"));
302 return NT_STATUS_INVALID_PARAMETER
;
305 dcesrv_sock
= talloc(event_ctx
, struct dcesrv_socket_context
);
306 NT_STATUS_HAVE_NO_MEMORY(dcesrv_sock
);
308 /* remember the endpoint of this socket */
309 dcesrv_sock
->endpoint
= e
;
310 dcesrv_sock
->dcesrv_ctx
= talloc_reference(dcesrv_sock
, dce_ctx
);
312 status
= NT_STATUS_OK
;
315 status
= stream_setup_smb_pipe(event_ctx
, model_ops
, &dcesrv_stream_ops
,
316 e
->ep_description
->endpoint
, dcesrv_sock
);
317 if (!NT_STATUS_IS_OK(status
)) {
318 DEBUG(0,("service_setup_stream_socket(path=%s) failed - %s\n",
319 e
->ep_description
->endpoint
, nt_errstr(status
)));
325 static NTSTATUS
dcesrv_add_ep_np(struct dcesrv_context
*dce_ctx
,
326 struct loadparm_context
*lp_ctx
,
327 struct dcesrv_endpoint
*e
,
328 struct event_context
*event_ctx
, const struct model_ops
*model_ops
)
332 status
= add_socket_rpc_pipe_iface(dce_ctx
, e
, event_ctx
, model_ops
);
333 NT_STATUS_NOT_OK_RETURN(status
);
339 add a socket address to the list of events, one event per dcerpc endpoint
341 static NTSTATUS
add_socket_rpc_tcp_iface(struct dcesrv_context
*dce_ctx
, struct dcesrv_endpoint
*e
,
342 struct event_context
*event_ctx
, const struct model_ops
*model_ops
,
345 struct dcesrv_socket_context
*dcesrv_sock
;
349 if (e
->ep_description
->endpoint
) {
350 port
= atoi(e
->ep_description
->endpoint
);
353 dcesrv_sock
= talloc(event_ctx
, struct dcesrv_socket_context
);
354 NT_STATUS_HAVE_NO_MEMORY(dcesrv_sock
);
356 /* remember the endpoint of this socket */
357 dcesrv_sock
->endpoint
= e
;
358 dcesrv_sock
->dcesrv_ctx
= talloc_reference(dcesrv_sock
, dce_ctx
);
360 status
= stream_setup_socket(event_ctx
, dce_ctx
->lp_ctx
,
361 model_ops
, &dcesrv_stream_ops
,
362 "ipv4", address
, &port
,
363 lp_socket_options(dce_ctx
->lp_ctx
),
365 if (!NT_STATUS_IS_OK(status
)) {
366 DEBUG(0,("service_setup_stream_socket(address=%s,port=%u) failed - %s\n",
367 address
, port
, nt_errstr(status
)));
370 if (e
->ep_description
->endpoint
== NULL
) {
371 e
->ep_description
->endpoint
= talloc_asprintf(dce_ctx
, "%d", port
);
377 static NTSTATUS
dcesrv_add_ep_tcp(struct dcesrv_context
*dce_ctx
,
378 struct loadparm_context
*lp_ctx
,
379 struct dcesrv_endpoint
*e
,
380 struct event_context
*event_ctx
, const struct model_ops
*model_ops
)
384 /* Add TCP/IP sockets */
385 if (lp_interfaces(lp_ctx
) && lp_bind_interfaces_only(lp_ctx
)) {
388 struct interface
*ifaces
;
390 load_interfaces(dce_ctx
, lp_interfaces(lp_ctx
), &ifaces
);
392 num_interfaces
= iface_count(ifaces
);
393 for(i
= 0; i
< num_interfaces
; i
++) {
394 const char *address
= iface_n_ip(ifaces
, i
);
395 status
= add_socket_rpc_tcp_iface(dce_ctx
, e
, event_ctx
, model_ops
, address
);
396 NT_STATUS_NOT_OK_RETURN(status
);
399 status
= add_socket_rpc_tcp_iface(dce_ctx
, e
, event_ctx
, model_ops
,
400 lp_socket_address(lp_ctx
));
401 NT_STATUS_NOT_OK_RETURN(status
);
408 static NTSTATUS
dcesrv_add_ep(struct dcesrv_context
*dce_ctx
,
409 struct loadparm_context
*lp_ctx
,
410 struct dcesrv_endpoint
*e
,
411 struct event_context
*event_ctx
, const struct model_ops
*model_ops
)
413 switch (e
->ep_description
->transport
) {
414 case NCACN_UNIX_STREAM
:
415 return dcesrv_add_ep_unix(dce_ctx
, lp_ctx
, e
, event_ctx
, model_ops
);
418 return dcesrv_add_ep_ncalrpc(dce_ctx
, lp_ctx
, e
, event_ctx
, model_ops
);
421 return dcesrv_add_ep_tcp(dce_ctx
, lp_ctx
, e
, event_ctx
, model_ops
);
424 return dcesrv_add_ep_np(dce_ctx
, lp_ctx
, e
, event_ctx
, model_ops
);
427 return NT_STATUS_NOT_SUPPORTED
;
432 open the dcerpc server sockets
434 static void dcesrv_task_init(struct task_server
*task
)
437 struct dcesrv_context
*dce_ctx
;
438 struct dcesrv_endpoint
*e
;
440 task_server_set_title(task
, "task[dcesrv]");
442 status
= dcesrv_init_context(task
->event_ctx
,
444 lp_dcerpc_endpoint_servers(task
->lp_ctx
),
446 if (!NT_STATUS_IS_OK(status
)) goto failed
;
448 /* Make sure the directory for NCALRPC exists */
449 if (!directory_exist(lp_ncalrpc_dir(task
->lp_ctx
))) {
450 mkdir(lp_ncalrpc_dir(task
->lp_ctx
), 0755);
453 for (e
=dce_ctx
->endpoint_list
;e
;e
=e
->next
) {
454 status
= dcesrv_add_ep(dce_ctx
, task
->lp_ctx
, e
, task
->event_ctx
, task
->model_ops
);
455 if (!NT_STATUS_IS_OK(status
)) goto failed
;
460 task_server_terminate(task
, "Failed to startup dcerpc server task");
463 NTSTATUS
server_service_rpc_init(void)
465 extern NTSTATUS
dcerpc_server_wkssvc_init(void);
466 extern NTSTATUS
dcerpc_server_drsuapi_init(void);
467 extern NTSTATUS
dcerpc_server_winreg_init(void);
468 extern NTSTATUS
dcerpc_server_spoolss_init(void);
469 extern NTSTATUS
dcerpc_server_epmapper_init(void);
470 extern NTSTATUS
dcerpc_server_srvsvc_init(void);
471 extern NTSTATUS
dcerpc_server_netlogon_init(void);
472 extern NTSTATUS
dcerpc_server_rpcecho_init(void);
473 extern NTSTATUS
dcerpc_server_unixinfo_init(void);
474 extern NTSTATUS
dcerpc_server_samr_init(void);
475 extern NTSTATUS
dcerpc_server_remote_init(void);
476 extern NTSTATUS
dcerpc_server_lsa_init(void);
477 init_module_fn static_init
[] = { STATIC_DCESRV_MODULES
};
478 init_module_fn
*shared_init
= load_samba_modules(NULL
, global_loadparm
, "dcerpc_server");
480 run_init_functions(static_init
);
481 run_init_functions(shared_init
);
483 talloc_free(shared_init
);
485 return register_server_service("rpc", dcesrv_task_init
);