Line data Source code
1 : /*
2 : Unix SMB/CIFS implementation.
3 :
4 : server side dcerpc core code
5 :
6 : Copyright (C) Andrew Tridgell 2003-2005
7 : Copyright (C) Stefan (metze) Metzmacher 2004-2005
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 "auth/auth.h"
25 : #include "auth/gensec/gensec.h"
26 : #include "auth/credentials/credentials.h"
27 : #include "rpc_server/dcerpc_server.h"
28 : #include "rpc_server/dcerpc_server_proto.h"
29 : #include "param/param.h"
30 : #include "samba/service_stream.h"
31 : #include "lib/tsocket/tsocket.h"
32 : #include "lib/socket/socket.h"
33 : #include "samba/process_model.h"
34 : #include "lib/util/samba_modules.h"
35 : #include "lib/util/tevent_ntstatus.h"
36 : #include "lib/util/idtree_random.h"
37 :
38 : /*
39 : take a reference to an existing association group
40 : */
41 712 : static struct dcesrv_assoc_group *dcesrv_assoc_group_reference(struct dcesrv_connection *conn,
42 : uint32_t id)
43 : {
44 712 : const struct dcesrv_endpoint *endpoint = conn->endpoint;
45 72 : enum dcerpc_transport_t transport =
46 712 : dcerpc_binding_get_transport(endpoint->ep_description);
47 72 : struct dcesrv_assoc_group *assoc_group;
48 712 : void *id_ptr = NULL;
49 :
50 : /* find an association group given a assoc_group_id */
51 712 : id_ptr = idr_find(conn->dce_ctx->assoc_groups_idr, id);
52 712 : if (id_ptr == NULL) {
53 364 : DBG_NOTICE("Failed to find assoc_group 0x%08x\n", id);
54 364 : return NULL;
55 : }
56 348 : assoc_group = talloc_get_type_abort(id_ptr, struct dcesrv_assoc_group);
57 :
58 348 : if (assoc_group->transport != transport) {
59 0 : const char *at =
60 1 : derpc_transport_string_by_transport(
61 : assoc_group->transport);
62 0 : const char *ct =
63 1 : derpc_transport_string_by_transport(
64 : transport);
65 :
66 1 : DBG_NOTICE("assoc_group 0x%08x (transport %s) "
67 : "is not available on transport %s\n",
68 : id, at, ct);
69 1 : return NULL;
70 : }
71 :
72 347 : return talloc_reference(conn, assoc_group);
73 : }
74 :
75 21513 : static int dcesrv_assoc_group_destructor(struct dcesrv_assoc_group *assoc_group)
76 : {
77 838 : int ret;
78 21513 : ret = idr_remove(assoc_group->dce_ctx->assoc_groups_idr, assoc_group->id);
79 21513 : if (ret != 0) {
80 0 : DEBUG(0,(__location__ ": Failed to remove assoc_group 0x%08x\n",
81 : assoc_group->id));
82 : }
83 21513 : SMB_ASSERT(assoc_group->dce_ctx->assoc_groups_num > 0);
84 21513 : assoc_group->dce_ctx->assoc_groups_num -= 1;
85 21513 : return 0;
86 : }
87 :
88 : /*
89 : allocate a new association group
90 : */
91 20140 : static struct dcesrv_assoc_group *dcesrv_assoc_group_new(struct dcesrv_connection *conn)
92 : {
93 20140 : struct dcesrv_context *dce_ctx = conn->dce_ctx;
94 20140 : const struct dcesrv_endpoint *endpoint = conn->endpoint;
95 838 : enum dcerpc_transport_t transport =
96 20140 : dcerpc_binding_get_transport(endpoint->ep_description);
97 838 : struct dcesrv_assoc_group *assoc_group;
98 838 : int id;
99 :
100 20140 : assoc_group = talloc_zero(conn, struct dcesrv_assoc_group);
101 20140 : if (assoc_group == NULL) {
102 0 : return NULL;
103 : }
104 :
105 20140 : id = idr_get_new_random(
106 : dce_ctx->assoc_groups_idr, assoc_group, 1, UINT16_MAX);
107 20140 : if (id == -1) {
108 0 : talloc_free(assoc_group);
109 0 : DEBUG(0,(__location__ ": Out of association groups!\n"));
110 0 : return NULL;
111 : }
112 :
113 20140 : assoc_group->transport = transport;
114 20140 : assoc_group->id = id;
115 20140 : assoc_group->dce_ctx = dce_ctx;
116 :
117 20140 : talloc_set_destructor(assoc_group, dcesrv_assoc_group_destructor);
118 :
119 20140 : SMB_ASSERT(dce_ctx->assoc_groups_num < UINT16_MAX);
120 20140 : dce_ctx->assoc_groups_num += 1;
121 :
122 20140 : return assoc_group;
123 : }
124 :
125 20568 : NTSTATUS dcesrv_assoc_group_find_s4(
126 : struct dcesrv_call_state *call,
127 : void *private_data)
128 : {
129 : /*
130 : if provided, check the assoc_group is valid
131 : */
132 20568 : if (call->pkt.u.bind.assoc_group_id != 0) {
133 712 : call->conn->assoc_group =
134 712 : dcesrv_assoc_group_reference(call->conn,
135 : call->pkt.u.bind.assoc_group_id);
136 : } else {
137 19856 : call->conn->assoc_group = dcesrv_assoc_group_new(call->conn);
138 : }
139 :
140 : /*
141 : * The NETLOGON server does not use handles and so
142 : * there is no need to support association groups, but
143 : * we need to give back a number regardless.
144 : *
145 : * We have to do this when it is not run as a single process,
146 : * because then it can't see the other valid association
147 : * groups. We handle this generically for all endpoints not
148 : * running in single process mode.
149 : *
150 : * We know which endpoint we are on even before checking the
151 : * iface UUID, so for simplicity we enforce the same policy
152 : * for all interfaces on the endpoint.
153 : *
154 : * This means that where NETLOGON
155 : * shares an endpoint (such as ncalrpc or if 'lsa over
156 : * netlogon' is set) we will still check association groups.
157 : *
158 : */
159 :
160 20568 : if (call->conn->assoc_group == NULL &&
161 365 : !call->conn->endpoint->use_single_process) {
162 284 : call->conn->assoc_group
163 284 : = dcesrv_assoc_group_new(call->conn);
164 : }
165 :
166 20568 : if (call->conn->assoc_group == NULL) {
167 : /* TODO Return correct status */
168 81 : return NT_STATUS_UNSUCCESSFUL;
169 : }
170 :
171 20487 : return NT_STATUS_OK;
172 : }
173 :
174 66 : void dcerpc_server_init(struct loadparm_context *lp_ctx)
175 : {
176 2 : static bool initialized;
177 : #define _MODULE_PROTO(init) extern NTSTATUS init(TALLOC_CTX *);
178 2 : STATIC_dcerpc_server_MODULES_PROTO;
179 66 : init_module_fn static_init[] = { STATIC_dcerpc_server_MODULES };
180 2 : init_module_fn *shared_init;
181 :
182 66 : if (initialized) {
183 0 : return;
184 : }
185 66 : initialized = true;
186 :
187 66 : shared_init = load_samba_modules(NULL, "dcerpc_server");
188 :
189 66 : run_init_functions(NULL, static_init);
190 66 : run_init_functions(NULL, shared_init);
191 :
192 66 : talloc_free(shared_init);
193 : }
194 :
195 : struct dcesrv_socket_context {
196 : const struct dcesrv_endpoint *endpoint;
197 : struct dcesrv_context *dcesrv_ctx;
198 : };
199 :
200 20594 : static void dcesrv_sock_accept(struct stream_connection *srv_conn)
201 : {
202 878 : NTSTATUS status;
203 878 : struct dcesrv_socket_context *dcesrv_sock =
204 20594 : talloc_get_type(srv_conn->private_data, struct dcesrv_socket_context);
205 878 : enum dcerpc_transport_t transport =
206 20594 : dcerpc_binding_get_transport(dcesrv_sock->endpoint->ep_description);
207 20594 : struct dcesrv_connection *dcesrv_conn = NULL;
208 878 : int ret;
209 20594 : struct loadparm_context *lp_ctx = dcesrv_sock->dcesrv_ctx->lp_ctx;
210 :
211 20594 : dcesrv_cleanup_broken_connections(dcesrv_sock->dcesrv_ctx);
212 :
213 20594 : if (!srv_conn->session_info) {
214 12781 : status = auth_anonymous_session_info(srv_conn,
215 : lp_ctx,
216 : &srv_conn->session_info);
217 12781 : if (!NT_STATUS_IS_OK(status)) {
218 0 : DEBUG(0,("dcesrv_sock_accept: auth_anonymous_session_info failed: %s\n",
219 : nt_errstr(status)));
220 0 : stream_terminate_connection(srv_conn, nt_errstr(status));
221 0 : return;
222 : }
223 : }
224 :
225 : /*
226 : * This fills in dcesrv_conn->endpoint with the endpoint
227 : * associated with the socket. From this point on we know
228 : * which (group of) services we are handling, but not the
229 : * specific interface.
230 : */
231 :
232 20594 : status = dcesrv_endpoint_connect(dcesrv_sock->dcesrv_ctx,
233 : srv_conn,
234 : dcesrv_sock->endpoint,
235 : srv_conn->session_info,
236 : srv_conn->event.ctx,
237 : DCESRV_CALL_STATE_FLAG_MAY_ASYNC,
238 : &dcesrv_conn);
239 20594 : if (!NT_STATUS_IS_OK(status)) {
240 0 : DEBUG(0,("dcesrv_sock_accept: dcesrv_endpoint_connect failed: %s\n",
241 : nt_errstr(status)));
242 0 : stream_terminate_connection(srv_conn, nt_errstr(status));
243 0 : return;
244 : }
245 :
246 20594 : dcesrv_conn->transport.private_data = srv_conn;
247 20594 : dcesrv_conn->transport.report_output_data = dcesrv_sock_report_output_data;
248 20594 : dcesrv_conn->transport.terminate_connection = dcesrv_transport_terminate_connection_s4;
249 :
250 20594 : TALLOC_FREE(srv_conn->event.fde);
251 :
252 20594 : dcesrv_conn->send_queue = tevent_queue_create(dcesrv_conn, "dcesrv send queue");
253 20594 : if (!dcesrv_conn->send_queue) {
254 0 : status = NT_STATUS_NO_MEMORY;
255 0 : DEBUG(0,("dcesrv_sock_accept: tevent_queue_create(%s)\n",
256 : nt_errstr(status)));
257 0 : stream_terminate_connection(srv_conn, nt_errstr(status));
258 0 : return;
259 : }
260 :
261 20594 : if (transport == NCACN_NP) {
262 7813 : dcesrv_conn->stream = talloc_move(dcesrv_conn,
263 : &srv_conn->tstream);
264 : } else {
265 12781 : ret = tstream_bsd_existing_socket(dcesrv_conn,
266 : socket_get_fd(srv_conn->socket),
267 : &dcesrv_conn->stream);
268 12781 : if (ret == -1) {
269 0 : status = map_nt_error_from_unix_common(errno);
270 0 : DEBUG(0, ("dcesrv_sock_accept: "
271 : "failed to setup tstream: %s\n",
272 : nt_errstr(status)));
273 0 : stream_terminate_connection(srv_conn, nt_errstr(status));
274 0 : return;
275 : }
276 12781 : socket_set_flags(srv_conn->socket, SOCKET_FLAG_NOCLOSE);
277 : /* as server we want to fail early */
278 12781 : tstream_bsd_fail_readv_first_error(dcesrv_conn->stream, true);
279 : }
280 :
281 20594 : dcesrv_conn->local_address = srv_conn->local_address;
282 20594 : dcesrv_conn->remote_address = srv_conn->remote_address;
283 :
284 20594 : if (transport == NCALRPC) {
285 8 : uid_t uid;
286 8 : gid_t gid;
287 8 : int sock_fd;
288 :
289 1450 : sock_fd = socket_get_fd(srv_conn->socket);
290 1450 : if (sock_fd == -1) {
291 0 : stream_terminate_connection(
292 : srv_conn, "socket_get_fd failed\n");
293 0 : return;
294 : }
295 :
296 1450 : ret = getpeereid(sock_fd, &uid, &gid);
297 1450 : if (ret == -1) {
298 0 : status = map_nt_error_from_unix_common(errno);
299 0 : DEBUG(0, ("dcesrv_sock_accept: "
300 : "getpeereid() failed for NCALRPC: %s\n",
301 : nt_errstr(status)));
302 0 : stream_terminate_connection(srv_conn, nt_errstr(status));
303 0 : return;
304 : }
305 1450 : if (uid == dcesrv_conn->dce_ctx->initial_euid) {
306 1450 : struct tsocket_address *r = NULL;
307 :
308 1450 : ret = tsocket_address_unix_from_path(dcesrv_conn,
309 : AS_SYSTEM_MAGIC_PATH_TOKEN,
310 : &r);
311 1450 : if (ret == -1) {
312 0 : status = map_nt_error_from_unix_common(errno);
313 0 : DEBUG(0, ("dcesrv_sock_accept: "
314 : "tsocket_address_unix_from_path() failed for NCALRPC: %s\n",
315 : nt_errstr(status)));
316 0 : stream_terminate_connection(srv_conn, nt_errstr(status));
317 0 : return;
318 : }
319 1450 : dcesrv_conn->remote_address = r;
320 : }
321 : }
322 :
323 20594 : srv_conn->private_data = dcesrv_conn;
324 :
325 20594 : status = dcesrv_connection_loop_start(dcesrv_conn);
326 20594 : if (!NT_STATUS_IS_OK(status)) {
327 0 : DEBUG(0,("dcesrv_sock_accept: dcerpc_read_fragment_buffer_send(%s)\n",
328 : nt_errstr(status)));
329 0 : stream_terminate_connection(srv_conn, nt_errstr(status));
330 0 : return;
331 : }
332 :
333 19716 : return;
334 : }
335 :
336 0 : static void dcesrv_sock_recv(struct stream_connection *conn, uint16_t flags)
337 : {
338 0 : struct dcesrv_connection *dce_conn = talloc_get_type(conn->private_data,
339 : struct dcesrv_connection);
340 0 : dcesrv_terminate_connection(dce_conn, "dcesrv_sock_recv triggered");
341 0 : }
342 :
343 0 : static void dcesrv_sock_send(struct stream_connection *conn, uint16_t flags)
344 : {
345 0 : struct dcesrv_connection *dce_conn = talloc_get_type(conn->private_data,
346 : struct dcesrv_connection);
347 0 : dcesrv_terminate_connection(dce_conn, "dcesrv_sock_send triggered");
348 0 : }
349 :
350 :
351 : static const struct stream_server_ops dcesrv_stream_ops = {
352 : .name = "rpc",
353 : .accept_connection = dcesrv_sock_accept,
354 : .recv_handler = dcesrv_sock_recv,
355 : .send_handler = dcesrv_sock_send,
356 : };
357 :
358 0 : static NTSTATUS dcesrv_add_ep_unix(struct dcesrv_context *dce_ctx,
359 : struct loadparm_context *lp_ctx,
360 : struct dcesrv_endpoint *e,
361 : struct tevent_context *event_ctx,
362 : const struct model_ops *model_ops,
363 : void *process_context)
364 : {
365 0 : struct dcesrv_socket_context *dcesrv_sock;
366 0 : uint16_t port = 1;
367 0 : NTSTATUS status;
368 0 : const char *endpoint;
369 :
370 0 : dcesrv_sock = talloc_zero(event_ctx, struct dcesrv_socket_context);
371 0 : NT_STATUS_HAVE_NO_MEMORY(dcesrv_sock);
372 :
373 : /* remember the endpoint of this socket */
374 0 : dcesrv_sock->endpoint = e;
375 0 : dcesrv_sock->dcesrv_ctx = talloc_reference(dcesrv_sock, dce_ctx);
376 :
377 0 : endpoint = dcerpc_binding_get_string_option(e->ep_description, "endpoint");
378 :
379 0 : status = stream_setup_socket(dcesrv_sock, event_ctx, lp_ctx,
380 : model_ops, &dcesrv_stream_ops,
381 : "unix", endpoint, &port,
382 : lpcfg_socket_options(lp_ctx),
383 : dcesrv_sock, process_context);
384 0 : if (!NT_STATUS_IS_OK(status)) {
385 0 : DEBUG(0,("service_setup_stream_socket(path=%s) failed - %s\n",
386 : endpoint, nt_errstr(status)));
387 : }
388 :
389 0 : return status;
390 : }
391 :
392 138 : static NTSTATUS dcesrv_add_ep_ncalrpc(struct dcesrv_context *dce_ctx,
393 : struct loadparm_context *lp_ctx,
394 : struct dcesrv_endpoint *e,
395 : struct tevent_context *event_ctx,
396 : const struct model_ops *model_ops,
397 : void *process_context)
398 : {
399 4 : struct dcesrv_socket_context *dcesrv_sock;
400 138 : uint16_t port = 1;
401 4 : char *full_path;
402 4 : NTSTATUS status;
403 4 : const char *endpoint;
404 :
405 138 : endpoint = dcerpc_binding_get_string_option(e->ep_description, "endpoint");
406 :
407 138 : if (endpoint == NULL) {
408 : /*
409 : * No identifier specified: use DEFAULT.
410 : *
411 : * TODO: DO NOT hardcode this value anywhere else. Rather, specify
412 : * no endpoint and let the epmapper worry about it.
413 : */
414 70 : endpoint = "DEFAULT";
415 70 : status = dcerpc_binding_set_string_option(e->ep_description,
416 : "endpoint",
417 : endpoint);
418 70 : if (!NT_STATUS_IS_OK(status)) {
419 0 : DEBUG(0,("dcerpc_binding_set_string_option() failed - %s\n",
420 : nt_errstr(status)));
421 0 : return status;
422 : }
423 : }
424 :
425 138 : full_path = talloc_asprintf(dce_ctx, "%s/%s", lpcfg_ncalrpc_dir(lp_ctx),
426 : endpoint);
427 :
428 138 : dcesrv_sock = talloc_zero(event_ctx, struct dcesrv_socket_context);
429 138 : NT_STATUS_HAVE_NO_MEMORY(dcesrv_sock);
430 :
431 : /* remember the endpoint of this socket */
432 138 : dcesrv_sock->endpoint = e;
433 138 : dcesrv_sock->dcesrv_ctx = talloc_reference(dcesrv_sock, dce_ctx);
434 :
435 138 : status = stream_setup_socket(dcesrv_sock, event_ctx, lp_ctx,
436 : model_ops, &dcesrv_stream_ops,
437 : "unix", full_path, &port,
438 : lpcfg_socket_options(lp_ctx),
439 : dcesrv_sock, process_context);
440 138 : if (!NT_STATUS_IS_OK(status)) {
441 0 : DEBUG(0,("service_setup_stream_socket(identifier=%s,path=%s) failed - %s\n",
442 : endpoint, full_path, nt_errstr(status)));
443 : }
444 138 : return status;
445 : }
446 :
447 802 : static NTSTATUS dcesrv_add_ep_np(struct dcesrv_context *dce_ctx,
448 : struct loadparm_context *lp_ctx,
449 : struct dcesrv_endpoint *e,
450 : struct tevent_context *event_ctx,
451 : const struct model_ops *model_ops,
452 : void *process_context)
453 : {
454 22 : struct dcesrv_socket_context *dcesrv_sock;
455 22 : NTSTATUS status;
456 22 : const char *endpoint;
457 :
458 802 : endpoint = dcerpc_binding_get_string_option(e->ep_description, "endpoint");
459 802 : if (endpoint == NULL) {
460 0 : DEBUG(0, ("Endpoint mandatory for named pipes\n"));
461 0 : return NT_STATUS_INVALID_PARAMETER;
462 : }
463 :
464 802 : dcesrv_sock = talloc_zero(event_ctx, struct dcesrv_socket_context);
465 802 : NT_STATUS_HAVE_NO_MEMORY(dcesrv_sock);
466 :
467 : /* remember the endpoint of this socket */
468 802 : dcesrv_sock->endpoint = e;
469 802 : dcesrv_sock->dcesrv_ctx = talloc_reference(dcesrv_sock, dce_ctx);
470 :
471 802 : status = tstream_setup_named_pipe(dce_ctx, event_ctx, lp_ctx,
472 : model_ops, &dcesrv_stream_ops,
473 : endpoint,
474 : dcesrv_sock, process_context);
475 802 : if (!NT_STATUS_IS_OK(status)) {
476 0 : DEBUG(0,("stream_setup_named_pipe(pipe=%s) failed - %s\n",
477 : endpoint, nt_errstr(status)));
478 0 : return status;
479 : }
480 :
481 802 : return NT_STATUS_OK;
482 : }
483 :
484 : /*
485 : add a socket address to the list of events, one event per dcerpc endpoint
486 : */
487 400 : static NTSTATUS add_socket_rpc_tcp_iface(struct dcesrv_context *dce_ctx,
488 : struct dcesrv_endpoint *e,
489 : struct tevent_context *event_ctx,
490 : const struct model_ops *model_ops,
491 : const char *address,
492 : void *process_context)
493 : {
494 12 : struct dcesrv_socket_context *dcesrv_sock;
495 400 : uint16_t port = 0;
496 12 : NTSTATUS status;
497 12 : const char *endpoint;
498 12 : char port_str[6];
499 :
500 400 : endpoint = dcerpc_binding_get_string_option(e->ep_description, "endpoint");
501 400 : if (endpoint != NULL) {
502 332 : port = atoi(endpoint);
503 : }
504 :
505 400 : dcesrv_sock = talloc_zero(event_ctx, struct dcesrv_socket_context);
506 400 : NT_STATUS_HAVE_NO_MEMORY(dcesrv_sock);
507 :
508 : /* remember the endpoint of this socket */
509 400 : dcesrv_sock->endpoint = e;
510 400 : dcesrv_sock->dcesrv_ctx = talloc_reference(dcesrv_sock, dce_ctx);
511 :
512 400 : status = stream_setup_socket(dcesrv_sock, event_ctx, dce_ctx->lp_ctx,
513 : model_ops, &dcesrv_stream_ops,
514 : "ip", address, &port,
515 : lpcfg_socket_options(dce_ctx->lp_ctx),
516 : dcesrv_sock, process_context);
517 400 : if (!NT_STATUS_IS_OK(status)) {
518 0 : struct dcesrv_if_list *iface;
519 0 : DEBUG(0,("service_setup_stream_socket(address=%s,port=%u) for ",
520 : address, port));
521 0 : for (iface = e->interface_list; iface; iface = iface->next) {
522 0 : DEBUGADD(0, ("%s ", iface->iface->name));
523 : }
524 0 : DEBUGADD(0, ("failed - %s\n",
525 : nt_errstr(status)));
526 0 : return status;
527 : }
528 :
529 400 : snprintf(port_str, sizeof(port_str), "%u", port);
530 :
531 400 : status = dcerpc_binding_set_string_option(e->ep_description,
532 : "endpoint", port_str);
533 400 : if (!NT_STATUS_IS_OK(status)) {
534 0 : DEBUG(0,("dcerpc_binding_set_string_option(endpoint, %s) failed - %s\n",
535 : port_str, nt_errstr(status)));
536 0 : return status;
537 : } else {
538 12 : struct dcesrv_if_list *iface;
539 400 : DEBUG(4,("Successfully listening on ncacn_ip_tcp endpoint [%s]:[%s] for ",
540 : address, port_str));
541 2664 : for (iface = e->interface_list; iface; iface = iface->next) {
542 2264 : DEBUGADD(4, ("%s ", iface->iface->name));
543 : }
544 400 : DEBUGADD(4, ("\n"));
545 : }
546 :
547 400 : return NT_STATUS_OK;
548 : }
549 :
550 : #include "lib/socket/netif.h" /* Included here to work around the fact that socket_wrapper redefines bind() */
551 :
552 200 : static NTSTATUS dcesrv_add_ep_tcp(struct dcesrv_context *dce_ctx,
553 : struct loadparm_context *lp_ctx,
554 : struct dcesrv_endpoint *e,
555 : struct tevent_context *event_ctx,
556 : const struct model_ops *model_ops,
557 : void *process_context)
558 : {
559 6 : NTSTATUS status;
560 :
561 : /* Add TCP/IP sockets */
562 200 : if (lpcfg_interfaces(lp_ctx) && lpcfg_bind_interfaces_only(lp_ctx)) {
563 0 : int num_interfaces;
564 0 : int i;
565 0 : struct interface *ifaces;
566 :
567 0 : load_interface_list(dce_ctx, lp_ctx, &ifaces);
568 :
569 0 : num_interfaces = iface_list_count(ifaces);
570 0 : for(i = 0; i < num_interfaces; i++) {
571 0 : const char *address = iface_list_n_ip(ifaces, i);
572 0 : status = add_socket_rpc_tcp_iface(dce_ctx, e, event_ctx,
573 : model_ops, address,
574 : process_context);
575 0 : NT_STATUS_NOT_OK_RETURN(status);
576 : }
577 : } else {
578 6 : char **wcard;
579 6 : size_t i;
580 200 : size_t num_binds = 0;
581 200 : wcard = iface_list_wildcard(dce_ctx);
582 200 : NT_STATUS_HAVE_NO_MEMORY(wcard);
583 600 : for (i=0; wcard[i]; i++) {
584 400 : status = add_socket_rpc_tcp_iface(dce_ctx, e, event_ctx,
585 388 : model_ops, wcard[i],
586 : process_context);
587 400 : if (NT_STATUS_IS_OK(status)) {
588 400 : num_binds++;
589 : }
590 : }
591 200 : talloc_free(wcard);
592 200 : if (num_binds == 0) {
593 0 : return NT_STATUS_INVALID_PARAMETER_MIX;
594 : }
595 : }
596 :
597 200 : return NT_STATUS_OK;
598 : }
599 :
600 1140 : NTSTATUS dcesrv_add_ep(struct dcesrv_context *dce_ctx,
601 : struct loadparm_context *lp_ctx,
602 : struct dcesrv_endpoint *e,
603 : struct tevent_context *event_ctx,
604 : const struct model_ops *model_ops,
605 : void *process_context)
606 : {
607 32 : enum dcerpc_transport_t transport =
608 1140 : dcerpc_binding_get_transport(e->ep_description);
609 :
610 1140 : switch (transport) {
611 0 : case NCACN_UNIX_STREAM:
612 0 : return dcesrv_add_ep_unix(dce_ctx, lp_ctx, e, event_ctx,
613 : model_ops, process_context);
614 :
615 138 : case NCALRPC:
616 138 : return dcesrv_add_ep_ncalrpc(dce_ctx, lp_ctx, e, event_ctx,
617 : model_ops, process_context);
618 :
619 200 : case NCACN_IP_TCP:
620 200 : return dcesrv_add_ep_tcp(dce_ctx, lp_ctx, e, event_ctx,
621 : model_ops, process_context);
622 :
623 802 : case NCACN_NP:
624 802 : return dcesrv_add_ep_np(dce_ctx, lp_ctx, e, event_ctx,
625 : model_ops, process_context);
626 :
627 0 : default:
628 0 : return NT_STATUS_NOT_SUPPORTED;
629 : }
630 : }
631 :
632 61633 : _PUBLIC_ struct imessaging_context *dcesrv_imessaging_context(
633 : struct dcesrv_connection *conn)
634 : {
635 3553 : struct stream_connection *srv_conn =
636 61633 : talloc_get_type_abort(conn->transport.private_data,
637 : struct stream_connection);
638 61633 : return srv_conn->msg_ctx;
639 : }
640 :
641 0 : _PUBLIC_ struct server_id dcesrv_server_id(struct dcesrv_connection *conn)
642 : {
643 0 : struct stream_connection *srv_conn =
644 0 : talloc_get_type_abort(conn->transport.private_data,
645 : struct stream_connection);
646 0 : return srv_conn->server_id;
647 : }
648 :
649 12654 : void log_successful_dcesrv_authz_event(
650 : struct dcesrv_call_state *call,
651 : void *private_data)
652 : {
653 12654 : struct dcesrv_auth *auth = call->auth_state;
654 436 : enum dcerpc_transport_t transport =
655 12654 : dcerpc_binding_get_transport(call->conn->endpoint->ep_description);
656 436 : struct imessaging_context *imsg_ctx =
657 12654 : dcesrv_imessaging_context(call->conn);
658 12654 : const char *auth_type = derpc_transport_string_by_transport(transport);
659 12654 : const char *transport_protection = AUTHZ_TRANSPORT_PROTECTION_NONE;
660 :
661 12654 : if (transport == NCACN_NP) {
662 5681 : transport_protection = AUTHZ_TRANSPORT_PROTECTION_SMB;
663 : }
664 :
665 : /*
666 : * Log the authorization to this RPC interface. This
667 : * covered ncacn_np pass-through auth, and anonymous
668 : * DCE/RPC (eg epmapper, netlogon etc)
669 : */
670 12654 : log_successful_authz_event(imsg_ctx,
671 12654 : call->conn->dce_ctx->lp_ctx,
672 12218 : call->conn->remote_address,
673 12654 : call->conn->local_address,
674 : "DCE/RPC",
675 : auth_type,
676 : transport_protection,
677 : auth->session_info,
678 : NULL /* client_audit_info */,
679 : NULL /* server_audit_info */);
680 :
681 12654 : auth->auth_audited = true;
682 12654 : }
683 :
684 8473 : NTSTATUS dcesrv_gensec_prepare(
685 : TALLOC_CTX *mem_ctx,
686 : struct dcesrv_call_state *call,
687 : struct gensec_security **out,
688 : void *private_data)
689 : {
690 8473 : struct cli_credentials *server_creds = NULL;
691 424 : struct imessaging_context *imsg_ctx =
692 8473 : dcesrv_imessaging_context(call->conn);
693 424 : bool ok;
694 :
695 8897 : server_creds = cli_credentials_init_server(call->auth_state,
696 8473 : call->conn->dce_ctx->lp_ctx);
697 8473 : if (server_creds == NULL) {
698 0 : DEBUG(1, ("Failed to init server credentials\n"));
699 0 : return NT_STATUS_NO_MEMORY;
700 : }
701 : /* This is required for ncalrpc_as_system. */
702 8473 : ok = cli_credentials_set_kerberos_state(server_creds,
703 : CRED_USE_KERBEROS_DESIRED,
704 : CRED_SPECIFIED);
705 8473 : if (!ok) {
706 0 : DBG_WARNING("Failed to set kerberos state\n");
707 0 : return NT_STATUS_INTERNAL_ERROR;
708 : }
709 :
710 8473 : return samba_server_gensec_start(mem_ctx,
711 : call->event_ctx,
712 : imsg_ctx,
713 8473 : call->conn->dce_ctx->lp_ctx,
714 : server_creds,
715 : NULL,
716 : out);
717 : }
718 :
719 20572 : void dcesrv_transport_terminate_connection_s4(struct dcesrv_connection *dce_conn,
720 : const char *reason)
721 : {
722 878 : struct stream_connection *srv_conn =
723 20572 : talloc_get_type_abort(dce_conn->transport.private_data,
724 : struct stream_connection);
725 20572 : stream_terminate_connection(srv_conn, reason);
726 20186 : }
|