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 "rpc_server/dcerpc_server_proto.h"
31 #include "lib/events/events.h"
32 #include "smbd/service_task.h"
33 #include "smbd/service_stream.h"
34 #include "smbd/service.h"
35 #include "system/filesys.h"
36 #include "libcli/security/security.h"
37 #include "lib/socket/socket.h"
38 #include "lib/messaging/irpc.h"
39 #include "system/network.h"
40 #include "lib/socket/netif.h"
41 #include "param/param.h"
43 struct dcesrv_socket_context
{
44 const struct dcesrv_endpoint
*endpoint
;
45 struct dcesrv_context
*dcesrv_ctx
;
49 write_fn callback for dcesrv_output()
51 static NTSTATUS
dcerpc_write_fn(void *private_data
, DATA_BLOB
*out
, size_t *nwritten
)
54 struct socket_context
*sock
= talloc_get_type(private_data
, struct socket_context
);
57 status
= socket_send(sock
, out
, &sendlen
);
58 NT_STATUS_IS_ERR_RETURN(status
);
64 static void dcesrv_terminate_connection(struct dcesrv_connection
*dce_conn
, const char *reason
)
66 struct stream_connection
*srv_conn
;
67 srv_conn
= talloc_get_type(dce_conn
->transport
.private_data
,
68 struct stream_connection
);
70 stream_terminate_connection(srv_conn
, reason
);
73 static void dcesrv_sock_report_output_data(struct dcesrv_connection
*dcesrv_conn
)
75 struct stream_connection
*srv_conn
;
76 srv_conn
= talloc_get_type(dcesrv_conn
->transport
.private_data
,
77 struct stream_connection
);
79 if (srv_conn
&& srv_conn
->event
.fde
) {
80 EVENT_FD_WRITEABLE(srv_conn
->event
.fde
);
84 static struct socket_address
*dcesrv_sock_get_my_addr(struct dcesrv_connection
*dcesrv_conn
, TALLOC_CTX
*mem_ctx
)
86 struct stream_connection
*srv_conn
;
87 srv_conn
= talloc_get_type(dcesrv_conn
->transport
.private_data
,
88 struct stream_connection
);
90 return socket_get_my_addr(srv_conn
->socket
, mem_ctx
);
93 static struct socket_address
*dcesrv_sock_get_peer_addr(struct dcesrv_connection
*dcesrv_conn
, TALLOC_CTX
*mem_ctx
)
95 struct stream_connection
*srv_conn
;
96 srv_conn
= talloc_get_type(dcesrv_conn
->transport
.private_data
,
97 struct stream_connection
);
99 return socket_get_peer_addr(srv_conn
->socket
, mem_ctx
);
102 static void dcesrv_sock_accept(struct stream_connection
*srv_conn
)
105 struct dcesrv_socket_context
*dcesrv_sock
=
106 talloc_get_type(srv_conn
->private_data
, struct dcesrv_socket_context
);
107 struct dcesrv_connection
*dcesrv_conn
= NULL
;
109 if (!srv_conn
->session_info
) {
110 status
= auth_anonymous_session_info(srv_conn
,
113 &srv_conn
->session_info
);
114 if (!NT_STATUS_IS_OK(status
)) {
115 DEBUG(0,("dcesrv_sock_accept: auth_anonymous_session_info failed: %s\n",
117 stream_terminate_connection(srv_conn
, nt_errstr(status
));
122 status
= dcesrv_endpoint_connect(dcesrv_sock
->dcesrv_ctx
,
124 dcesrv_sock
->endpoint
,
125 srv_conn
->session_info
,
129 DCESRV_CALL_STATE_FLAG_MAY_ASYNC
,
131 if (!NT_STATUS_IS_OK(status
)) {
132 DEBUG(0,("dcesrv_sock_accept: dcesrv_endpoint_connect failed: %s\n",
134 stream_terminate_connection(srv_conn
, nt_errstr(status
));
138 dcesrv_conn
->transport
.private_data
= srv_conn
;
139 dcesrv_conn
->transport
.report_output_data
= dcesrv_sock_report_output_data
;
140 dcesrv_conn
->transport
.get_my_addr
= dcesrv_sock_get_my_addr
;
141 dcesrv_conn
->transport
.get_peer_addr
= dcesrv_sock_get_peer_addr
;
143 if (dcesrv_sock
->endpoint
->ep_description
->transport
== NCACN_NP
) {
144 dcesrv_conn
->auth_state
.session_key
= dcesrv_inherited_session_key
;
147 srv_conn
->private_data
= dcesrv_conn
;
149 irpc_add_name(srv_conn
->msg_ctx
, "rpc_server");
154 static void dcesrv_sock_recv(struct stream_connection
*conn
, uint16_t flags
)
157 struct dcesrv_connection
*dce_conn
= talloc_get_type(conn
->private_data
, struct dcesrv_connection
);
161 if (dce_conn
->processing
) {
162 EVENT_FD_NOT_READABLE(conn
->event
.fde
);
166 tmp_blob
= data_blob_talloc(conn
->socket
, NULL
, 0x1000);
167 if (tmp_blob
.data
== NULL
) {
168 dcesrv_terminate_connection(dce_conn
, "out of memory");
172 status
= socket_recv(conn
->socket
, tmp_blob
.data
, tmp_blob
.length
, &nread
);
173 if (NT_STATUS_IS_ERR(status
)) {
174 dcesrv_terminate_connection(dce_conn
, nt_errstr(status
));
178 talloc_free(tmp_blob
.data
);
182 tmp_blob
.length
= nread
;
184 dce_conn
->processing
= true;
185 status
= dcesrv_input(dce_conn
, &tmp_blob
);
186 dce_conn
->processing
= false;
187 talloc_free(tmp_blob
.data
);
189 EVENT_FD_READABLE(conn
->event
.fde
);
191 if (!NT_STATUS_IS_OK(status
)) {
192 dcesrv_terminate_connection(dce_conn
, nt_errstr(status
));
196 if (dce_conn
->call_list
&& dce_conn
->call_list
->replies
) {
197 EVENT_FD_WRITEABLE(conn
->event
.fde
);
201 static void dcesrv_sock_send(struct stream_connection
*conn
, uint16_t flags
)
203 struct dcesrv_connection
*dce_conn
= talloc_get_type(conn
->private_data
, struct dcesrv_connection
);
206 status
= dcesrv_output(dce_conn
, conn
->socket
, dcerpc_write_fn
);
207 if (NT_STATUS_IS_ERR(status
)) {
208 dcesrv_terminate_connection(dce_conn
, "eof on socket");
212 if (!dce_conn
->call_list
|| !dce_conn
->call_list
->replies
) {
213 EVENT_FD_NOT_WRITEABLE(conn
->event
.fde
);
218 static const struct stream_server_ops dcesrv_stream_ops
= {
220 .accept_connection
= dcesrv_sock_accept
,
221 .recv_handler
= dcesrv_sock_recv
,
222 .send_handler
= dcesrv_sock_send
,
227 static NTSTATUS
dcesrv_add_ep_unix(struct dcesrv_context
*dce_ctx
,
228 struct loadparm_context
*lp_ctx
,
229 struct dcesrv_endpoint
*e
,
230 struct tevent_context
*event_ctx
, const struct model_ops
*model_ops
)
232 struct dcesrv_socket_context
*dcesrv_sock
;
236 dcesrv_sock
= talloc(event_ctx
, struct dcesrv_socket_context
);
237 NT_STATUS_HAVE_NO_MEMORY(dcesrv_sock
);
239 /* remember the endpoint of this socket */
240 dcesrv_sock
->endpoint
= e
;
241 dcesrv_sock
->dcesrv_ctx
= talloc_reference(dcesrv_sock
, dce_ctx
);
243 status
= stream_setup_socket(event_ctx
, lp_ctx
,
244 model_ops
, &dcesrv_stream_ops
,
245 "unix", e
->ep_description
->endpoint
, &port
,
246 lp_socket_options(lp_ctx
),
248 if (!NT_STATUS_IS_OK(status
)) {
249 DEBUG(0,("service_setup_stream_socket(path=%s) failed - %s\n",
250 e
->ep_description
->endpoint
, nt_errstr(status
)));
256 static NTSTATUS
dcesrv_add_ep_ncalrpc(struct dcesrv_context
*dce_ctx
,
257 struct loadparm_context
*lp_ctx
,
258 struct dcesrv_endpoint
*e
,
259 struct tevent_context
*event_ctx
, const struct model_ops
*model_ops
)
261 struct dcesrv_socket_context
*dcesrv_sock
;
266 if (!e
->ep_description
->endpoint
) {
267 /* No identifier specified: use DEFAULT.
268 * DO NOT hardcode this value anywhere else. Rather, specify
269 * no endpoint and let the epmapper worry about it. */
270 e
->ep_description
->endpoint
= talloc_strdup(dce_ctx
, "DEFAULT");
273 full_path
= talloc_asprintf(dce_ctx
, "%s/%s", lp_ncalrpc_dir(lp_ctx
),
274 e
->ep_description
->endpoint
);
276 dcesrv_sock
= talloc(event_ctx
, struct dcesrv_socket_context
);
277 NT_STATUS_HAVE_NO_MEMORY(dcesrv_sock
);
279 /* remember the endpoint of this socket */
280 dcesrv_sock
->endpoint
= e
;
281 dcesrv_sock
->dcesrv_ctx
= talloc_reference(dcesrv_sock
, dce_ctx
);
283 status
= stream_setup_socket(event_ctx
, lp_ctx
,
284 model_ops
, &dcesrv_stream_ops
,
285 "unix", full_path
, &port
,
286 lp_socket_options(lp_ctx
),
288 if (!NT_STATUS_IS_OK(status
)) {
289 DEBUG(0,("service_setup_stream_socket(identifier=%s,path=%s) failed - %s\n",
290 e
->ep_description
->endpoint
, full_path
, nt_errstr(status
)));
295 static NTSTATUS
dcesrv_add_ep_np(struct dcesrv_context
*dce_ctx
,
296 struct loadparm_context
*lp_ctx
,
297 struct dcesrv_endpoint
*e
,
298 struct tevent_context
*event_ctx
, const struct model_ops
*model_ops
)
300 struct dcesrv_socket_context
*dcesrv_sock
;
303 if (e
->ep_description
->endpoint
== NULL
) {
304 DEBUG(0, ("Endpoint mandatory for named pipes\n"));
305 return NT_STATUS_INVALID_PARAMETER
;
308 dcesrv_sock
= talloc(event_ctx
, struct dcesrv_socket_context
);
309 NT_STATUS_HAVE_NO_MEMORY(dcesrv_sock
);
311 /* remember the endpoint of this socket */
312 dcesrv_sock
->endpoint
= e
;
313 dcesrv_sock
->dcesrv_ctx
= talloc_reference(dcesrv_sock
, dce_ctx
);
315 status
= stream_setup_named_pipe(event_ctx
, lp_ctx
,
316 model_ops
, &dcesrv_stream_ops
,
317 e
->ep_description
->endpoint
, dcesrv_sock
);
318 if (!NT_STATUS_IS_OK(status
)) {
319 DEBUG(0,("stream_setup_named_pipe(pipe=%s) failed - %s\n",
320 e
->ep_description
->endpoint
, nt_errstr(status
)));
328 add a socket address to the list of events, one event per dcerpc endpoint
330 static NTSTATUS
add_socket_rpc_tcp_iface(struct dcesrv_context
*dce_ctx
, struct dcesrv_endpoint
*e
,
331 struct tevent_context
*event_ctx
, const struct model_ops
*model_ops
,
334 struct dcesrv_socket_context
*dcesrv_sock
;
338 if (e
->ep_description
->endpoint
) {
339 port
= atoi(e
->ep_description
->endpoint
);
342 dcesrv_sock
= talloc(event_ctx
, struct dcesrv_socket_context
);
343 NT_STATUS_HAVE_NO_MEMORY(dcesrv_sock
);
345 /* remember the endpoint of this socket */
346 dcesrv_sock
->endpoint
= e
;
347 dcesrv_sock
->dcesrv_ctx
= talloc_reference(dcesrv_sock
, dce_ctx
);
349 status
= stream_setup_socket(event_ctx
, dce_ctx
->lp_ctx
,
350 model_ops
, &dcesrv_stream_ops
,
351 "ipv4", address
, &port
,
352 lp_socket_options(dce_ctx
->lp_ctx
),
354 if (!NT_STATUS_IS_OK(status
)) {
355 DEBUG(0,("service_setup_stream_socket(address=%s,port=%u) failed - %s\n",
356 address
, port
, nt_errstr(status
)));
359 if (e
->ep_description
->endpoint
== NULL
) {
360 e
->ep_description
->endpoint
= talloc_asprintf(dce_ctx
, "%d", port
);
366 static NTSTATUS
dcesrv_add_ep_tcp(struct dcesrv_context
*dce_ctx
,
367 struct loadparm_context
*lp_ctx
,
368 struct dcesrv_endpoint
*e
,
369 struct tevent_context
*event_ctx
, const struct model_ops
*model_ops
)
373 /* Add TCP/IP sockets */
374 if (lp_interfaces(lp_ctx
) && lp_bind_interfaces_only(lp_ctx
)) {
377 struct interface
*ifaces
;
379 load_interfaces(dce_ctx
, lp_interfaces(lp_ctx
), &ifaces
);
381 num_interfaces
= iface_count(ifaces
);
382 for(i
= 0; i
< num_interfaces
; i
++) {
383 const char *address
= iface_n_ip(ifaces
, i
);
384 status
= add_socket_rpc_tcp_iface(dce_ctx
, e
, event_ctx
, model_ops
, address
);
385 NT_STATUS_NOT_OK_RETURN(status
);
388 status
= add_socket_rpc_tcp_iface(dce_ctx
, e
, event_ctx
, model_ops
,
389 lp_socket_address(lp_ctx
));
390 NT_STATUS_NOT_OK_RETURN(status
);
397 static NTSTATUS
dcesrv_add_ep(struct dcesrv_context
*dce_ctx
,
398 struct loadparm_context
*lp_ctx
,
399 struct dcesrv_endpoint
*e
,
400 struct tevent_context
*event_ctx
, const struct model_ops
*model_ops
)
402 switch (e
->ep_description
->transport
) {
403 case NCACN_UNIX_STREAM
:
404 return dcesrv_add_ep_unix(dce_ctx
, lp_ctx
, e
, event_ctx
, model_ops
);
407 return dcesrv_add_ep_ncalrpc(dce_ctx
, lp_ctx
, e
, event_ctx
, model_ops
);
410 return dcesrv_add_ep_tcp(dce_ctx
, lp_ctx
, e
, event_ctx
, model_ops
);
413 return dcesrv_add_ep_np(dce_ctx
, lp_ctx
, e
, event_ctx
, model_ops
);
416 return NT_STATUS_NOT_SUPPORTED
;
421 open the dcerpc server sockets
423 static void dcesrv_task_init(struct task_server
*task
)
426 struct dcesrv_context
*dce_ctx
;
427 struct dcesrv_endpoint
*e
;
429 dcerpc_server_init(task
->lp_ctx
);
431 task_server_set_title(task
, "task[dcesrv]");
433 status
= dcesrv_init_context(task
->event_ctx
,
435 lp_dcerpc_endpoint_servers(task
->lp_ctx
),
437 if (!NT_STATUS_IS_OK(status
)) goto failed
;
439 /* Make sure the directory for NCALRPC exists */
440 if (!directory_exist(lp_ncalrpc_dir(task
->lp_ctx
))) {
441 mkdir(lp_ncalrpc_dir(task
->lp_ctx
), 0755);
444 for (e
=dce_ctx
->endpoint_list
;e
;e
=e
->next
) {
445 status
= dcesrv_add_ep(dce_ctx
, task
->lp_ctx
, e
, task
->event_ctx
, task
->model_ops
);
446 if (!NT_STATUS_IS_OK(status
)) goto failed
;
451 task_server_terminate(task
, "Failed to startup dcerpc server task");
454 NTSTATUS
server_service_rpc_init(void)
457 return register_server_service("rpc", dcesrv_task_init
);