s3:script: Replace --merge by --merge-by-timestamp in samba-log-parser
[Samba.git] / source4 / rpc_server / dcerpc_server.c
blobb3b114d3746447242a9f0d3b80bfae41d90c1a8b
1 /*
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/>.
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"
39 take a reference to an existing association group
41 static struct dcesrv_assoc_group *dcesrv_assoc_group_reference(struct dcesrv_connection *conn,
42 uint32_t id)
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;
48 void *id_ptr = NULL;
50 /* find an association group given a assoc_group_id */
51 id_ptr = idr_find(conn->dce_ctx->assoc_groups_idr, id);
52 if (id_ptr == NULL) {
53 DBG_NOTICE("Failed to find assoc_group 0x%08x\n", id);
54 return NULL;
56 assoc_group = talloc_get_type_abort(id_ptr, struct dcesrv_assoc_group);
58 if (assoc_group->transport != transport) {
59 const char *at =
60 derpc_transport_string_by_transport(
61 assoc_group->transport);
62 const char *ct =
63 derpc_transport_string_by_transport(
64 transport);
66 DBG_NOTICE("assoc_group 0x%08x (transport %s) "
67 "is not available on transport %s",
68 id, at, ct);
69 return NULL;
72 return talloc_reference(conn, assoc_group);
75 static int dcesrv_assoc_group_destructor(struct dcesrv_assoc_group *assoc_group)
77 int ret;
78 ret = idr_remove(assoc_group->dce_ctx->assoc_groups_idr, assoc_group->id);
79 if (ret != 0) {
80 DEBUG(0,(__location__ ": Failed to remove assoc_group 0x%08x\n",
81 assoc_group->id));
83 return 0;
87 allocate a new association group
89 static struct dcesrv_assoc_group *dcesrv_assoc_group_new(struct dcesrv_connection *conn)
91 struct dcesrv_context *dce_ctx = conn->dce_ctx;
92 const struct dcesrv_endpoint *endpoint = conn->endpoint;
93 enum dcerpc_transport_t transport =
94 dcerpc_binding_get_transport(endpoint->ep_description);
95 struct dcesrv_assoc_group *assoc_group;
96 int id;
98 assoc_group = talloc_zero(conn, struct dcesrv_assoc_group);
99 if (assoc_group == NULL) {
100 return NULL;
103 id = idr_get_new_random(
104 dce_ctx->assoc_groups_idr, assoc_group, 1, UINT16_MAX);
105 if (id == -1) {
106 talloc_free(assoc_group);
107 DEBUG(0,(__location__ ": Out of association groups!\n"));
108 return NULL;
111 assoc_group->transport = transport;
112 assoc_group->id = id;
113 assoc_group->dce_ctx = dce_ctx;
115 talloc_set_destructor(assoc_group, dcesrv_assoc_group_destructor);
117 return assoc_group;
120 NTSTATUS dcesrv_assoc_group_find_s4(
121 struct dcesrv_call_state *call,
122 void *private_data)
125 if provided, check the assoc_group is valid
127 if (call->pkt.u.bind.assoc_group_id != 0) {
128 call->conn->assoc_group =
129 dcesrv_assoc_group_reference(call->conn,
130 call->pkt.u.bind.assoc_group_id);
131 } else {
132 call->conn->assoc_group = dcesrv_assoc_group_new(call->conn);
136 * The NETLOGON server does not use handles and so
137 * there is no need to support association groups, but
138 * we need to give back a number regardless.
140 * We have to do this when it is not run as a single process,
141 * because then it can't see the other valid association
142 * groups. We handle this genericly for all endpoints not
143 * running in single process mode.
145 * We know which endpoint we are on even before checking the
146 * iface UUID, so for simplicity we enforce the same policy
147 * for all interfaces on the endpoint.
149 * This means that where NETLOGON
150 * shares an endpoint (such as ncalrpc or if 'lsa over
151 * netlogon' is set) we will still check association groups.
155 if (call->conn->assoc_group == NULL &&
156 !call->conn->endpoint->use_single_process) {
157 call->conn->assoc_group
158 = dcesrv_assoc_group_new(call->conn);
161 if (call->conn->assoc_group == NULL) {
162 /* TODO Return correct status */
163 return NT_STATUS_UNSUCCESSFUL;
166 return NT_STATUS_OK;
169 void dcerpc_server_init(struct loadparm_context *lp_ctx)
171 static bool initialized;
172 #define _MODULE_PROTO(init) extern NTSTATUS init(TALLOC_CTX *);
173 STATIC_dcerpc_server_MODULES_PROTO;
174 init_module_fn static_init[] = { STATIC_dcerpc_server_MODULES };
175 init_module_fn *shared_init;
177 if (initialized) {
178 return;
180 initialized = true;
182 shared_init = load_samba_modules(NULL, "dcerpc_server");
184 run_init_functions(NULL, static_init);
185 run_init_functions(NULL, shared_init);
187 talloc_free(shared_init);
190 struct dcesrv_socket_context {
191 const struct dcesrv_endpoint *endpoint;
192 struct dcesrv_context *dcesrv_ctx;
195 static void dcesrv_sock_accept(struct stream_connection *srv_conn)
197 NTSTATUS status;
198 struct dcesrv_socket_context *dcesrv_sock =
199 talloc_get_type(srv_conn->private_data, struct dcesrv_socket_context);
200 enum dcerpc_transport_t transport =
201 dcerpc_binding_get_transport(dcesrv_sock->endpoint->ep_description);
202 struct dcesrv_connection *dcesrv_conn = NULL;
203 int ret;
204 struct loadparm_context *lp_ctx = dcesrv_sock->dcesrv_ctx->lp_ctx;
206 dcesrv_cleanup_broken_connections(dcesrv_sock->dcesrv_ctx);
208 if (!srv_conn->session_info) {
209 status = auth_anonymous_session_info(srv_conn,
210 lp_ctx,
211 &srv_conn->session_info);
212 if (!NT_STATUS_IS_OK(status)) {
213 DEBUG(0,("dcesrv_sock_accept: auth_anonymous_session_info failed: %s\n",
214 nt_errstr(status)));
215 stream_terminate_connection(srv_conn, nt_errstr(status));
216 return;
221 * This fills in dcesrv_conn->endpoint with the endpoint
222 * associated with the socket. From this point on we know
223 * which (group of) services we are handling, but not the
224 * specific interface.
227 status = dcesrv_endpoint_connect(dcesrv_sock->dcesrv_ctx,
228 srv_conn,
229 dcesrv_sock->endpoint,
230 srv_conn->session_info,
231 srv_conn->event.ctx,
232 DCESRV_CALL_STATE_FLAG_MAY_ASYNC,
233 &dcesrv_conn);
234 if (!NT_STATUS_IS_OK(status)) {
235 DEBUG(0,("dcesrv_sock_accept: dcesrv_endpoint_connect failed: %s\n",
236 nt_errstr(status)));
237 stream_terminate_connection(srv_conn, nt_errstr(status));
238 return;
241 dcesrv_conn->transport.private_data = srv_conn;
242 dcesrv_conn->transport.report_output_data = dcesrv_sock_report_output_data;
243 dcesrv_conn->transport.terminate_connection = dcesrv_transport_terminate_connection_s4;
245 TALLOC_FREE(srv_conn->event.fde);
247 dcesrv_conn->send_queue = tevent_queue_create(dcesrv_conn, "dcesrv send queue");
248 if (!dcesrv_conn->send_queue) {
249 status = NT_STATUS_NO_MEMORY;
250 DEBUG(0,("dcesrv_sock_accept: tevent_queue_create(%s)\n",
251 nt_errstr(status)));
252 stream_terminate_connection(srv_conn, nt_errstr(status));
253 return;
256 if (transport == NCACN_NP) {
257 dcesrv_conn->stream = talloc_move(dcesrv_conn,
258 &srv_conn->tstream);
259 } else {
260 ret = tstream_bsd_existing_socket(dcesrv_conn,
261 socket_get_fd(srv_conn->socket),
262 &dcesrv_conn->stream);
263 if (ret == -1) {
264 status = map_nt_error_from_unix_common(errno);
265 DEBUG(0, ("dcesrv_sock_accept: "
266 "failed to setup tstream: %s\n",
267 nt_errstr(status)));
268 stream_terminate_connection(srv_conn, nt_errstr(status));
269 return;
271 socket_set_flags(srv_conn->socket, SOCKET_FLAG_NOCLOSE);
274 dcesrv_conn->local_address = srv_conn->local_address;
275 dcesrv_conn->remote_address = srv_conn->remote_address;
277 if (transport == NCALRPC) {
278 uid_t uid;
279 gid_t gid;
280 int sock_fd;
282 sock_fd = socket_get_fd(srv_conn->socket);
283 if (sock_fd == -1) {
284 stream_terminate_connection(
285 srv_conn, "socket_get_fd failed\n");
286 return;
289 ret = getpeereid(sock_fd, &uid, &gid);
290 if (ret == -1) {
291 status = map_nt_error_from_unix_common(errno);
292 DEBUG(0, ("dcesrv_sock_accept: "
293 "getpeereid() failed for NCALRPC: %s\n",
294 nt_errstr(status)));
295 stream_terminate_connection(srv_conn, nt_errstr(status));
296 return;
298 if (uid == dcesrv_conn->dce_ctx->initial_euid) {
299 struct tsocket_address *r = NULL;
301 ret = tsocket_address_unix_from_path(dcesrv_conn,
302 AS_SYSTEM_MAGIC_PATH_TOKEN,
303 &r);
304 if (ret == -1) {
305 status = map_nt_error_from_unix_common(errno);
306 DEBUG(0, ("dcesrv_sock_accept: "
307 "tsocket_address_unix_from_path() failed for NCALRPC: %s\n",
308 nt_errstr(status)));
309 stream_terminate_connection(srv_conn, nt_errstr(status));
310 return;
312 dcesrv_conn->remote_address = r;
316 srv_conn->private_data = dcesrv_conn;
318 status = dcesrv_connection_loop_start(dcesrv_conn);
319 if (!NT_STATUS_IS_OK(status)) {
320 DEBUG(0,("dcesrv_sock_accept: dcerpc_read_fragment_buffer_send(%s)\n",
321 nt_errstr(status)));
322 stream_terminate_connection(srv_conn, nt_errstr(status));
323 return;
326 return;
329 static void dcesrv_sock_recv(struct stream_connection *conn, uint16_t flags)
331 struct dcesrv_connection *dce_conn = talloc_get_type(conn->private_data,
332 struct dcesrv_connection);
333 dcesrv_terminate_connection(dce_conn, "dcesrv_sock_recv triggered");
336 static void dcesrv_sock_send(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_send triggered");
344 static const struct stream_server_ops dcesrv_stream_ops = {
345 .name = "rpc",
346 .accept_connection = dcesrv_sock_accept,
347 .recv_handler = dcesrv_sock_recv,
348 .send_handler = dcesrv_sock_send,
351 static NTSTATUS dcesrv_add_ep_unix(struct dcesrv_context *dce_ctx,
352 struct loadparm_context *lp_ctx,
353 struct dcesrv_endpoint *e,
354 struct tevent_context *event_ctx,
355 const struct model_ops *model_ops,
356 void *process_context)
358 struct dcesrv_socket_context *dcesrv_sock;
359 uint16_t port = 1;
360 NTSTATUS status;
361 const char *endpoint;
363 dcesrv_sock = talloc_zero(event_ctx, struct dcesrv_socket_context);
364 NT_STATUS_HAVE_NO_MEMORY(dcesrv_sock);
366 /* remember the endpoint of this socket */
367 dcesrv_sock->endpoint = e;
368 dcesrv_sock->dcesrv_ctx = talloc_reference(dcesrv_sock, dce_ctx);
370 endpoint = dcerpc_binding_get_string_option(e->ep_description, "endpoint");
372 status = stream_setup_socket(dcesrv_sock, event_ctx, lp_ctx,
373 model_ops, &dcesrv_stream_ops,
374 "unix", endpoint, &port,
375 lpcfg_socket_options(lp_ctx),
376 dcesrv_sock, process_context);
377 if (!NT_STATUS_IS_OK(status)) {
378 DEBUG(0,("service_setup_stream_socket(path=%s) failed - %s\n",
379 endpoint, nt_errstr(status)));
382 return status;
385 static NTSTATUS dcesrv_add_ep_ncalrpc(struct dcesrv_context *dce_ctx,
386 struct loadparm_context *lp_ctx,
387 struct dcesrv_endpoint *e,
388 struct tevent_context *event_ctx,
389 const struct model_ops *model_ops,
390 void *process_context)
392 struct dcesrv_socket_context *dcesrv_sock;
393 uint16_t port = 1;
394 char *full_path;
395 NTSTATUS status;
396 const char *endpoint;
398 endpoint = dcerpc_binding_get_string_option(e->ep_description, "endpoint");
400 if (endpoint == NULL) {
402 * No identifier specified: use DEFAULT.
404 * TODO: DO NOT hardcode this value anywhere else. Rather, specify
405 * no endpoint and let the epmapper worry about it.
407 endpoint = "DEFAULT";
408 status = dcerpc_binding_set_string_option(e->ep_description,
409 "endpoint",
410 endpoint);
411 if (!NT_STATUS_IS_OK(status)) {
412 DEBUG(0,("dcerpc_binding_set_string_option() failed - %s\n",
413 nt_errstr(status)));
414 return status;
418 full_path = talloc_asprintf(dce_ctx, "%s/%s", lpcfg_ncalrpc_dir(lp_ctx),
419 endpoint);
421 dcesrv_sock = talloc_zero(event_ctx, struct dcesrv_socket_context);
422 NT_STATUS_HAVE_NO_MEMORY(dcesrv_sock);
424 /* remember the endpoint of this socket */
425 dcesrv_sock->endpoint = e;
426 dcesrv_sock->dcesrv_ctx = talloc_reference(dcesrv_sock, dce_ctx);
428 status = stream_setup_socket(dcesrv_sock, event_ctx, lp_ctx,
429 model_ops, &dcesrv_stream_ops,
430 "unix", full_path, &port,
431 lpcfg_socket_options(lp_ctx),
432 dcesrv_sock, process_context);
433 if (!NT_STATUS_IS_OK(status)) {
434 DEBUG(0,("service_setup_stream_socket(identifier=%s,path=%s) failed - %s\n",
435 endpoint, full_path, nt_errstr(status)));
437 return status;
440 static NTSTATUS dcesrv_add_ep_np(struct dcesrv_context *dce_ctx,
441 struct loadparm_context *lp_ctx,
442 struct dcesrv_endpoint *e,
443 struct tevent_context *event_ctx,
444 const struct model_ops *model_ops,
445 void *process_context)
447 struct dcesrv_socket_context *dcesrv_sock;
448 NTSTATUS status;
449 const char *endpoint;
451 endpoint = dcerpc_binding_get_string_option(e->ep_description, "endpoint");
452 if (endpoint == NULL) {
453 DEBUG(0, ("Endpoint mandatory for named pipes\n"));
454 return NT_STATUS_INVALID_PARAMETER;
457 dcesrv_sock = talloc_zero(event_ctx, struct dcesrv_socket_context);
458 NT_STATUS_HAVE_NO_MEMORY(dcesrv_sock);
460 /* remember the endpoint of this socket */
461 dcesrv_sock->endpoint = e;
462 dcesrv_sock->dcesrv_ctx = talloc_reference(dcesrv_sock, dce_ctx);
464 status = tstream_setup_named_pipe(dce_ctx, event_ctx, lp_ctx,
465 model_ops, &dcesrv_stream_ops,
466 endpoint,
467 dcesrv_sock, process_context);
468 if (!NT_STATUS_IS_OK(status)) {
469 DEBUG(0,("stream_setup_named_pipe(pipe=%s) failed - %s\n",
470 endpoint, nt_errstr(status)));
471 return status;
474 return NT_STATUS_OK;
478 add a socket address to the list of events, one event per dcerpc endpoint
480 static NTSTATUS add_socket_rpc_tcp_iface(struct dcesrv_context *dce_ctx,
481 struct dcesrv_endpoint *e,
482 struct tevent_context *event_ctx,
483 const struct model_ops *model_ops,
484 const char *address,
485 void *process_context)
487 struct dcesrv_socket_context *dcesrv_sock;
488 uint16_t port = 0;
489 NTSTATUS status;
490 const char *endpoint;
491 char port_str[6];
493 endpoint = dcerpc_binding_get_string_option(e->ep_description, "endpoint");
494 if (endpoint != NULL) {
495 port = atoi(endpoint);
498 dcesrv_sock = talloc_zero(event_ctx, struct dcesrv_socket_context);
499 NT_STATUS_HAVE_NO_MEMORY(dcesrv_sock);
501 /* remember the endpoint of this socket */
502 dcesrv_sock->endpoint = e;
503 dcesrv_sock->dcesrv_ctx = talloc_reference(dcesrv_sock, dce_ctx);
505 status = stream_setup_socket(dcesrv_sock, event_ctx, dce_ctx->lp_ctx,
506 model_ops, &dcesrv_stream_ops,
507 "ip", address, &port,
508 lpcfg_socket_options(dce_ctx->lp_ctx),
509 dcesrv_sock, process_context);
510 if (!NT_STATUS_IS_OK(status)) {
511 struct dcesrv_if_list *iface;
512 DEBUG(0,("service_setup_stream_socket(address=%s,port=%u) for ",
513 address, port));
514 for (iface = e->interface_list; iface; iface = iface->next) {
515 DEBUGADD(0, ("%s ", iface->iface->name));
517 DEBUGADD(0, ("failed - %s\n",
518 nt_errstr(status)));
519 return status;
522 snprintf(port_str, sizeof(port_str), "%u", port);
524 status = dcerpc_binding_set_string_option(e->ep_description,
525 "endpoint", port_str);
526 if (!NT_STATUS_IS_OK(status)) {
527 DEBUG(0,("dcerpc_binding_set_string_option(endpoint, %s) failed - %s\n",
528 port_str, nt_errstr(status)));
529 return status;
530 } else {
531 struct dcesrv_if_list *iface;
532 DEBUG(4,("Successfully listening on ncacn_ip_tcp endpoint [%s]:[%s] for ",
533 address, port_str));
534 for (iface = e->interface_list; iface; iface = iface->next) {
535 DEBUGADD(4, ("%s ", iface->iface->name));
537 DEBUGADD(4, ("\n"));
540 return NT_STATUS_OK;
543 #include "lib/socket/netif.h" /* Included here to work around the fact that socket_wrapper redefines bind() */
545 static NTSTATUS dcesrv_add_ep_tcp(struct dcesrv_context *dce_ctx,
546 struct loadparm_context *lp_ctx,
547 struct dcesrv_endpoint *e,
548 struct tevent_context *event_ctx,
549 const struct model_ops *model_ops,
550 void *process_context)
552 NTSTATUS status;
554 /* Add TCP/IP sockets */
555 if (lpcfg_interfaces(lp_ctx) && lpcfg_bind_interfaces_only(lp_ctx)) {
556 int num_interfaces;
557 int i;
558 struct interface *ifaces;
560 load_interface_list(dce_ctx, lp_ctx, &ifaces);
562 num_interfaces = iface_list_count(ifaces);
563 for(i = 0; i < num_interfaces; i++) {
564 const char *address = iface_list_n_ip(ifaces, i);
565 status = add_socket_rpc_tcp_iface(dce_ctx, e, event_ctx,
566 model_ops, address,
567 process_context);
568 NT_STATUS_NOT_OK_RETURN(status);
570 } else {
571 char **wcard;
572 size_t i;
573 size_t num_binds = 0;
574 wcard = iface_list_wildcard(dce_ctx);
575 NT_STATUS_HAVE_NO_MEMORY(wcard);
576 for (i=0; wcard[i]; i++) {
577 status = add_socket_rpc_tcp_iface(dce_ctx, e, event_ctx,
578 model_ops, wcard[i],
579 process_context);
580 if (NT_STATUS_IS_OK(status)) {
581 num_binds++;
584 talloc_free(wcard);
585 if (num_binds == 0) {
586 return NT_STATUS_INVALID_PARAMETER_MIX;
590 return NT_STATUS_OK;
593 NTSTATUS dcesrv_add_ep(struct dcesrv_context *dce_ctx,
594 struct loadparm_context *lp_ctx,
595 struct dcesrv_endpoint *e,
596 struct tevent_context *event_ctx,
597 const struct model_ops *model_ops,
598 void *process_context)
600 enum dcerpc_transport_t transport =
601 dcerpc_binding_get_transport(e->ep_description);
603 switch (transport) {
604 case NCACN_UNIX_STREAM:
605 return dcesrv_add_ep_unix(dce_ctx, lp_ctx, e, event_ctx,
606 model_ops, process_context);
608 case NCALRPC:
609 return dcesrv_add_ep_ncalrpc(dce_ctx, lp_ctx, e, event_ctx,
610 model_ops, process_context);
612 case NCACN_IP_TCP:
613 return dcesrv_add_ep_tcp(dce_ctx, lp_ctx, e, event_ctx,
614 model_ops, process_context);
616 case NCACN_NP:
617 return dcesrv_add_ep_np(dce_ctx, lp_ctx, e, event_ctx,
618 model_ops, process_context);
620 default:
621 return NT_STATUS_NOT_SUPPORTED;
625 _PUBLIC_ struct imessaging_context *dcesrv_imessaging_context(
626 struct dcesrv_connection *conn)
628 struct stream_connection *srv_conn =
629 talloc_get_type_abort(conn->transport.private_data,
630 struct stream_connection);
631 return srv_conn->msg_ctx;
634 _PUBLIC_ struct server_id dcesrv_server_id(struct dcesrv_connection *conn)
636 struct stream_connection *srv_conn =
637 talloc_get_type_abort(conn->transport.private_data,
638 struct stream_connection);
639 return srv_conn->server_id;
642 void log_successful_dcesrv_authz_event(
643 struct dcesrv_call_state *call,
644 void *private_data)
646 struct dcesrv_auth *auth = call->auth_state;
647 enum dcerpc_transport_t transport =
648 dcerpc_binding_get_transport(call->conn->endpoint->ep_description);
649 struct imessaging_context *imsg_ctx =
650 dcesrv_imessaging_context(call->conn);
651 const char *auth_type = derpc_transport_string_by_transport(transport);
652 const char *transport_protection = AUTHZ_TRANSPORT_PROTECTION_NONE;
654 if (transport == NCACN_NP) {
655 transport_protection = AUTHZ_TRANSPORT_PROTECTION_SMB;
659 * Log the authorization to this RPC interface. This
660 * covered ncacn_np pass-through auth, and anonymous
661 * DCE/RPC (eg epmapper, netlogon etc)
663 log_successful_authz_event(imsg_ctx,
664 call->conn->dce_ctx->lp_ctx,
665 call->conn->remote_address,
666 call->conn->local_address,
667 "DCE/RPC",
668 auth_type,
669 transport_protection,
670 auth->session_info,
671 NULL /* client_audit_info */,
672 NULL /* server_audit_info */);
674 auth->auth_audited = true;
677 NTSTATUS dcesrv_gensec_prepare(
678 TALLOC_CTX *mem_ctx,
679 struct dcesrv_call_state *call,
680 struct gensec_security **out,
681 void *private_data)
683 struct cli_credentials *server_creds = NULL;
684 struct imessaging_context *imsg_ctx =
685 dcesrv_imessaging_context(call->conn);
686 bool ok;
688 server_creds = cli_credentials_init_server(call->auth_state,
689 call->conn->dce_ctx->lp_ctx);
690 if (server_creds == NULL) {
691 DEBUG(1, ("Failed to init server credentials\n"));
692 return NT_STATUS_NO_MEMORY;
694 /* This is required for ncalrpc_as_system. */
695 ok = cli_credentials_set_kerberos_state(server_creds,
696 CRED_USE_KERBEROS_DESIRED,
697 CRED_SPECIFIED);
698 if (!ok) {
699 DBG_WARNING("Failed to set kerberos state\n");
700 return NT_STATUS_INTERNAL_ERROR;
703 return samba_server_gensec_start(mem_ctx,
704 call->event_ctx,
705 imsg_ctx,
706 call->conn->dce_ctx->lp_ctx,
707 server_creds,
708 NULL,
709 out);
712 void dcesrv_transport_terminate_connection_s4(struct dcesrv_connection *dce_conn,
713 const char *reason)
715 struct stream_connection *srv_conn =
716 talloc_get_type_abort(dce_conn->transport.private_data,
717 struct stream_connection);
718 stream_terminate_connection(srv_conn, reason);