2 Unix SMB/CIFS implementation.
4 server side dcerpc core code
6 Copyright (C) Andrew Tridgell 2003-2005
7 Copyright (C) Stefan (metze) Metzmacher 2004-2005
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.
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.
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/>.
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"
39 take a reference to an existing association group
41 static struct dcesrv_assoc_group
*dcesrv_assoc_group_reference(struct dcesrv_connection
*conn
,
44 const struct dcesrv_endpoint
*endpoint
= conn
->endpoint
;
45 enum dcerpc_transport_t transport
=
46 dcerpc_binding_get_transport(endpoint
->ep_description
);
47 struct dcesrv_assoc_group
*assoc_group
;
50 /* find an association group given a assoc_group_id */
51 id_ptr
= idr_find(conn
->dce_ctx
->assoc_groups_idr
, id
);
53 DBG_NOTICE("Failed to find assoc_group 0x%08x\n", id
);
56 assoc_group
= talloc_get_type_abort(id_ptr
, struct dcesrv_assoc_group
);
58 if (assoc_group
->transport
!= transport
) {
60 derpc_transport_string_by_transport(
61 assoc_group
->transport
);
63 derpc_transport_string_by_transport(
66 DBG_NOTICE("assoc_group 0x%08x (transport %s) "
67 "is not available on transport %s\n",
72 return talloc_reference(conn
, assoc_group
);
75 static int dcesrv_assoc_group_destructor(struct dcesrv_assoc_group
*assoc_group
)
78 ret
= idr_remove(assoc_group
->dce_ctx
->assoc_groups_idr
, assoc_group
->id
);
80 DEBUG(0,(__location__
": Failed to remove assoc_group 0x%08x\n",
83 SMB_ASSERT(assoc_group
->dce_ctx
->assoc_groups_num
> 0);
84 assoc_group
->dce_ctx
->assoc_groups_num
-= 1;
89 allocate a new association group
91 static struct dcesrv_assoc_group
*dcesrv_assoc_group_new(struct dcesrv_connection
*conn
)
93 struct dcesrv_context
*dce_ctx
= conn
->dce_ctx
;
94 const struct dcesrv_endpoint
*endpoint
= conn
->endpoint
;
95 enum dcerpc_transport_t transport
=
96 dcerpc_binding_get_transport(endpoint
->ep_description
);
97 struct dcesrv_assoc_group
*assoc_group
;
100 assoc_group
= talloc_zero(conn
, struct dcesrv_assoc_group
);
101 if (assoc_group
== NULL
) {
105 id
= idr_get_new_random(
106 dce_ctx
->assoc_groups_idr
, assoc_group
, 1, UINT16_MAX
);
108 talloc_free(assoc_group
);
109 DEBUG(0,(__location__
": Out of association groups!\n"));
113 assoc_group
->transport
= transport
;
114 assoc_group
->id
= id
;
115 assoc_group
->dce_ctx
= dce_ctx
;
117 talloc_set_destructor(assoc_group
, dcesrv_assoc_group_destructor
);
119 SMB_ASSERT(dce_ctx
->assoc_groups_num
< UINT16_MAX
);
120 dce_ctx
->assoc_groups_num
+= 1;
125 NTSTATUS
dcesrv_assoc_group_find_s4(
126 struct dcesrv_call_state
*call
,
130 if provided, check the assoc_group is valid
132 if (call
->pkt
.u
.bind
.assoc_group_id
!= 0) {
133 call
->conn
->assoc_group
=
134 dcesrv_assoc_group_reference(call
->conn
,
135 call
->pkt
.u
.bind
.assoc_group_id
);
137 call
->conn
->assoc_group
= dcesrv_assoc_group_new(call
->conn
);
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.
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.
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.
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.
160 if (call
->conn
->assoc_group
== NULL
&&
161 !call
->conn
->endpoint
->use_single_process
) {
162 call
->conn
->assoc_group
163 = dcesrv_assoc_group_new(call
->conn
);
166 if (call
->conn
->assoc_group
== NULL
) {
167 /* TODO Return correct status */
168 return NT_STATUS_UNSUCCESSFUL
;
174 void dcerpc_server_init(struct loadparm_context
*lp_ctx
)
176 static bool initialized
;
177 #define _MODULE_PROTO(init) extern NTSTATUS init(TALLOC_CTX *);
178 STATIC_dcerpc_server_MODULES_PROTO
;
179 init_module_fn static_init
[] = { STATIC_dcerpc_server_MODULES
};
180 init_module_fn
*shared_init
;
187 shared_init
= load_samba_modules(NULL
, "dcerpc_server");
189 run_init_functions(NULL
, static_init
);
190 run_init_functions(NULL
, shared_init
);
192 talloc_free(shared_init
);
195 struct dcesrv_socket_context
{
196 const struct dcesrv_endpoint
*endpoint
;
197 struct dcesrv_context
*dcesrv_ctx
;
200 static void dcesrv_sock_accept(struct stream_connection
*srv_conn
)
203 struct dcesrv_socket_context
*dcesrv_sock
=
204 talloc_get_type(srv_conn
->private_data
, struct dcesrv_socket_context
);
205 enum dcerpc_transport_t transport
=
206 dcerpc_binding_get_transport(dcesrv_sock
->endpoint
->ep_description
);
207 struct dcesrv_connection
*dcesrv_conn
= NULL
;
209 struct loadparm_context
*lp_ctx
= dcesrv_sock
->dcesrv_ctx
->lp_ctx
;
211 dcesrv_cleanup_broken_connections(dcesrv_sock
->dcesrv_ctx
);
213 if (!srv_conn
->session_info
) {
214 status
= auth_anonymous_session_info(srv_conn
,
216 &srv_conn
->session_info
);
217 if (!NT_STATUS_IS_OK(status
)) {
218 DEBUG(0,("dcesrv_sock_accept: auth_anonymous_session_info failed: %s\n",
220 stream_terminate_connection(srv_conn
, nt_errstr(status
));
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.
232 status
= dcesrv_endpoint_connect(dcesrv_sock
->dcesrv_ctx
,
234 dcesrv_sock
->endpoint
,
235 srv_conn
->session_info
,
237 DCESRV_CALL_STATE_FLAG_MAY_ASYNC
,
239 if (!NT_STATUS_IS_OK(status
)) {
240 DEBUG(0,("dcesrv_sock_accept: dcesrv_endpoint_connect failed: %s\n",
242 stream_terminate_connection(srv_conn
, nt_errstr(status
));
246 dcesrv_conn
->transport
.private_data
= srv_conn
;
247 dcesrv_conn
->transport
.report_output_data
= dcesrv_sock_report_output_data
;
248 dcesrv_conn
->transport
.terminate_connection
= dcesrv_transport_terminate_connection_s4
;
250 TALLOC_FREE(srv_conn
->event
.fde
);
252 dcesrv_conn
->send_queue
= tevent_queue_create(dcesrv_conn
, "dcesrv send queue");
253 if (!dcesrv_conn
->send_queue
) {
254 status
= NT_STATUS_NO_MEMORY
;
255 DEBUG(0,("dcesrv_sock_accept: tevent_queue_create(%s)\n",
257 stream_terminate_connection(srv_conn
, nt_errstr(status
));
261 if (transport
== NCACN_NP
) {
262 dcesrv_conn
->stream
= talloc_move(dcesrv_conn
,
265 ret
= tstream_bsd_existing_socket(dcesrv_conn
,
266 socket_get_fd(srv_conn
->socket
),
267 &dcesrv_conn
->stream
);
269 status
= map_nt_error_from_unix_common(errno
);
270 DEBUG(0, ("dcesrv_sock_accept: "
271 "failed to setup tstream: %s\n",
273 stream_terminate_connection(srv_conn
, nt_errstr(status
));
276 socket_set_flags(srv_conn
->socket
, SOCKET_FLAG_NOCLOSE
);
277 /* as server we want to fail early */
278 tstream_bsd_fail_readv_first_error(dcesrv_conn
->stream
, true);
281 dcesrv_conn
->local_address
= srv_conn
->local_address
;
282 dcesrv_conn
->remote_address
= srv_conn
->remote_address
;
284 if (transport
== NCALRPC
) {
289 sock_fd
= socket_get_fd(srv_conn
->socket
);
291 stream_terminate_connection(
292 srv_conn
, "socket_get_fd failed\n");
296 ret
= getpeereid(sock_fd
, &uid
, &gid
);
298 status
= map_nt_error_from_unix_common(errno
);
299 DEBUG(0, ("dcesrv_sock_accept: "
300 "getpeereid() failed for NCALRPC: %s\n",
302 stream_terminate_connection(srv_conn
, nt_errstr(status
));
305 if (uid
== dcesrv_conn
->dce_ctx
->initial_euid
) {
306 struct tsocket_address
*r
= NULL
;
308 ret
= tsocket_address_unix_from_path(dcesrv_conn
,
309 AS_SYSTEM_MAGIC_PATH_TOKEN
,
312 status
= map_nt_error_from_unix_common(errno
);
313 DEBUG(0, ("dcesrv_sock_accept: "
314 "tsocket_address_unix_from_path() failed for NCALRPC: %s\n",
316 stream_terminate_connection(srv_conn
, nt_errstr(status
));
319 dcesrv_conn
->remote_address
= r
;
323 srv_conn
->private_data
= dcesrv_conn
;
325 status
= dcesrv_connection_loop_start(dcesrv_conn
);
326 if (!NT_STATUS_IS_OK(status
)) {
327 DEBUG(0,("dcesrv_sock_accept: dcerpc_read_fragment_buffer_send(%s)\n",
329 stream_terminate_connection(srv_conn
, nt_errstr(status
));
336 static void dcesrv_sock_recv(struct stream_connection
*conn
, uint16_t flags
)
338 struct dcesrv_connection
*dce_conn
= talloc_get_type(conn
->private_data
,
339 struct dcesrv_connection
);
340 dcesrv_terminate_connection(dce_conn
, "dcesrv_sock_recv triggered");
343 static void dcesrv_sock_send(struct stream_connection
*conn
, uint16_t flags
)
345 struct dcesrv_connection
*dce_conn
= talloc_get_type(conn
->private_data
,
346 struct dcesrv_connection
);
347 dcesrv_terminate_connection(dce_conn
, "dcesrv_sock_send triggered");
351 static const struct stream_server_ops dcesrv_stream_ops
= {
353 .accept_connection
= dcesrv_sock_accept
,
354 .recv_handler
= dcesrv_sock_recv
,
355 .send_handler
= dcesrv_sock_send
,
358 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
)
365 struct dcesrv_socket_context
*dcesrv_sock
;
368 const char *endpoint
;
370 dcesrv_sock
= talloc_zero(event_ctx
, struct dcesrv_socket_context
);
371 NT_STATUS_HAVE_NO_MEMORY(dcesrv_sock
);
373 /* remember the endpoint of this socket */
374 dcesrv_sock
->endpoint
= e
;
375 dcesrv_sock
->dcesrv_ctx
= talloc_reference(dcesrv_sock
, dce_ctx
);
377 endpoint
= dcerpc_binding_get_string_option(e
->ep_description
, "endpoint");
379 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 if (!NT_STATUS_IS_OK(status
)) {
385 DEBUG(0,("service_setup_stream_socket(path=%s) failed - %s\n",
386 endpoint
, nt_errstr(status
)));
392 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
)
399 struct dcesrv_socket_context
*dcesrv_sock
;
403 const char *endpoint
;
405 endpoint
= dcerpc_binding_get_string_option(e
->ep_description
, "endpoint");
407 if (endpoint
== NULL
) {
409 * No identifier specified: use DEFAULT.
411 * TODO: DO NOT hardcode this value anywhere else. Rather, specify
412 * no endpoint and let the epmapper worry about it.
414 endpoint
= "DEFAULT";
415 status
= dcerpc_binding_set_string_option(e
->ep_description
,
418 if (!NT_STATUS_IS_OK(status
)) {
419 DEBUG(0,("dcerpc_binding_set_string_option() failed - %s\n",
425 full_path
= talloc_asprintf(dce_ctx
, "%s/%s", lpcfg_ncalrpc_dir(lp_ctx
),
428 dcesrv_sock
= talloc_zero(event_ctx
, struct dcesrv_socket_context
);
429 NT_STATUS_HAVE_NO_MEMORY(dcesrv_sock
);
431 /* remember the endpoint of this socket */
432 dcesrv_sock
->endpoint
= e
;
433 dcesrv_sock
->dcesrv_ctx
= talloc_reference(dcesrv_sock
, dce_ctx
);
435 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 if (!NT_STATUS_IS_OK(status
)) {
441 DEBUG(0,("service_setup_stream_socket(identifier=%s,path=%s) failed - %s\n",
442 endpoint
, full_path
, nt_errstr(status
)));
447 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
)
454 struct dcesrv_socket_context
*dcesrv_sock
;
456 const char *endpoint
;
458 endpoint
= dcerpc_binding_get_string_option(e
->ep_description
, "endpoint");
459 if (endpoint
== NULL
) {
460 DEBUG(0, ("Endpoint mandatory for named pipes\n"));
461 return NT_STATUS_INVALID_PARAMETER
;
464 dcesrv_sock
= talloc_zero(event_ctx
, struct dcesrv_socket_context
);
465 NT_STATUS_HAVE_NO_MEMORY(dcesrv_sock
);
467 /* remember the endpoint of this socket */
468 dcesrv_sock
->endpoint
= e
;
469 dcesrv_sock
->dcesrv_ctx
= talloc_reference(dcesrv_sock
, dce_ctx
);
471 status
= tstream_setup_named_pipe(dce_ctx
, event_ctx
, lp_ctx
,
472 model_ops
, &dcesrv_stream_ops
,
474 dcesrv_sock
, process_context
);
475 if (!NT_STATUS_IS_OK(status
)) {
476 DEBUG(0,("stream_setup_named_pipe(pipe=%s) failed - %s\n",
477 endpoint
, nt_errstr(status
)));
485 add a socket address to the list of events, one event per dcerpc endpoint
487 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
,
492 void *process_context
)
494 struct dcesrv_socket_context
*dcesrv_sock
;
497 const char *endpoint
;
500 endpoint
= dcerpc_binding_get_string_option(e
->ep_description
, "endpoint");
501 if (endpoint
!= NULL
) {
502 port
= atoi(endpoint
);
505 dcesrv_sock
= talloc_zero(event_ctx
, struct dcesrv_socket_context
);
506 NT_STATUS_HAVE_NO_MEMORY(dcesrv_sock
);
508 /* remember the endpoint of this socket */
509 dcesrv_sock
->endpoint
= e
;
510 dcesrv_sock
->dcesrv_ctx
= talloc_reference(dcesrv_sock
, dce_ctx
);
512 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 if (!NT_STATUS_IS_OK(status
)) {
518 struct dcesrv_if_list
*iface
;
519 DEBUG(0,("service_setup_stream_socket(address=%s,port=%u) for ",
521 for (iface
= e
->interface_list
; iface
; iface
= iface
->next
) {
522 DEBUGADD(0, ("%s ", iface
->iface
->name
));
524 DEBUGADD(0, ("failed - %s\n",
529 snprintf(port_str
, sizeof(port_str
), "%u", port
);
531 status
= dcerpc_binding_set_string_option(e
->ep_description
,
532 "endpoint", port_str
);
533 if (!NT_STATUS_IS_OK(status
)) {
534 DEBUG(0,("dcerpc_binding_set_string_option(endpoint, %s) failed - %s\n",
535 port_str
, nt_errstr(status
)));
538 struct dcesrv_if_list
*iface
;
539 DEBUG(4,("Successfully listening on ncacn_ip_tcp endpoint [%s]:[%s] for ",
541 for (iface
= e
->interface_list
; iface
; iface
= iface
->next
) {
542 DEBUGADD(4, ("%s ", iface
->iface
->name
));
550 #include "lib/socket/netif.h" /* Included here to work around the fact that socket_wrapper redefines bind() */
552 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
)
561 /* Add TCP/IP sockets */
562 if (lpcfg_interfaces(lp_ctx
) && lpcfg_bind_interfaces_only(lp_ctx
)) {
565 struct interface
*ifaces
;
567 load_interface_list(dce_ctx
, lp_ctx
, &ifaces
);
569 num_interfaces
= iface_list_count(ifaces
);
570 for(i
= 0; i
< num_interfaces
; i
++) {
571 const char *address
= iface_list_n_ip(ifaces
, i
);
572 status
= add_socket_rpc_tcp_iface(dce_ctx
, e
, event_ctx
,
575 NT_STATUS_NOT_OK_RETURN(status
);
580 size_t num_binds
= 0;
581 wcard
= iface_list_wildcard(dce_ctx
);
582 NT_STATUS_HAVE_NO_MEMORY(wcard
);
583 for (i
=0; wcard
[i
]; i
++) {
584 status
= add_socket_rpc_tcp_iface(dce_ctx
, e
, event_ctx
,
587 if (NT_STATUS_IS_OK(status
)) {
592 if (num_binds
== 0) {
593 return NT_STATUS_INVALID_PARAMETER_MIX
;
600 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
)
607 enum dcerpc_transport_t transport
=
608 dcerpc_binding_get_transport(e
->ep_description
);
611 case NCACN_UNIX_STREAM
:
612 return dcesrv_add_ep_unix(dce_ctx
, lp_ctx
, e
, event_ctx
,
613 model_ops
, process_context
);
616 return dcesrv_add_ep_ncalrpc(dce_ctx
, lp_ctx
, e
, event_ctx
,
617 model_ops
, process_context
);
620 return dcesrv_add_ep_tcp(dce_ctx
, lp_ctx
, e
, event_ctx
,
621 model_ops
, process_context
);
624 return dcesrv_add_ep_np(dce_ctx
, lp_ctx
, e
, event_ctx
,
625 model_ops
, process_context
);
628 return NT_STATUS_NOT_SUPPORTED
;
632 _PUBLIC_
struct imessaging_context
*dcesrv_imessaging_context(
633 struct dcesrv_connection
*conn
)
635 struct stream_connection
*srv_conn
=
636 talloc_get_type_abort(conn
->transport
.private_data
,
637 struct stream_connection
);
638 return srv_conn
->msg_ctx
;
641 _PUBLIC_
struct server_id
dcesrv_server_id(struct dcesrv_connection
*conn
)
643 struct stream_connection
*srv_conn
=
644 talloc_get_type_abort(conn
->transport
.private_data
,
645 struct stream_connection
);
646 return srv_conn
->server_id
;
649 void log_successful_dcesrv_authz_event(
650 struct dcesrv_call_state
*call
,
653 struct dcesrv_auth
*auth
= call
->auth_state
;
654 enum dcerpc_transport_t transport
=
655 dcerpc_binding_get_transport(call
->conn
->endpoint
->ep_description
);
656 struct imessaging_context
*imsg_ctx
=
657 dcesrv_imessaging_context(call
->conn
);
658 const char *auth_type
= derpc_transport_string_by_transport(transport
);
659 const char *transport_protection
= AUTHZ_TRANSPORT_PROTECTION_NONE
;
661 if (transport
== NCACN_NP
) {
662 transport_protection
= AUTHZ_TRANSPORT_PROTECTION_SMB
;
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)
670 log_successful_authz_event(imsg_ctx
,
671 call
->conn
->dce_ctx
->lp_ctx
,
672 call
->conn
->remote_address
,
673 call
->conn
->local_address
,
676 transport_protection
,
678 NULL
/* client_audit_info */,
679 NULL
/* server_audit_info */);
681 auth
->auth_audited
= true;
684 NTSTATUS
dcesrv_gensec_prepare(
686 struct dcesrv_call_state
*call
,
687 struct gensec_security
**out
,
690 struct cli_credentials
*server_creds
= NULL
;
691 struct imessaging_context
*imsg_ctx
=
692 dcesrv_imessaging_context(call
->conn
);
695 server_creds
= cli_credentials_init_server(call
->auth_state
,
696 call
->conn
->dce_ctx
->lp_ctx
);
697 if (server_creds
== NULL
) {
698 DEBUG(1, ("Failed to init server credentials\n"));
699 return NT_STATUS_NO_MEMORY
;
701 /* This is required for ncalrpc_as_system. */
702 ok
= cli_credentials_set_kerberos_state(server_creds
,
703 CRED_USE_KERBEROS_DESIRED
,
706 DBG_WARNING("Failed to set kerberos state\n");
707 return NT_STATUS_INTERNAL_ERROR
;
710 return samba_server_gensec_start(mem_ctx
,
713 call
->conn
->dce_ctx
->lp_ctx
,
719 void dcesrv_transport_terminate_connection_s4(struct dcesrv_connection
*dce_conn
,
722 struct stream_connection
*srv_conn
=
723 talloc_get_type_abort(dce_conn
->transport
.private_data
,
724 struct stream_connection
);
725 stream_terminate_connection(srv_conn
, reason
);