s3: libsmbclient: Fix smbc_stat() to return ENOENT on a non-existent file.
[Samba.git] / source4 / rpc_server / dcerpc_server.c
blobc896b3574a2ee410ff48772d7efc266de1dfd3a3
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"
38 take a reference to an existing association group
40 static struct dcesrv_assoc_group *dcesrv_assoc_group_reference(struct dcesrv_connection *conn,
41 uint32_t id)
43 const struct dcesrv_endpoint *endpoint = conn->endpoint;
44 enum dcerpc_transport_t transport =
45 dcerpc_binding_get_transport(endpoint->ep_description);
46 struct dcesrv_assoc_group *assoc_group;
47 void *id_ptr = NULL;
49 /* find an association group given a assoc_group_id */
50 id_ptr = idr_find(conn->dce_ctx->assoc_groups_idr, id);
51 if (id_ptr == NULL) {
52 DBG_NOTICE("Failed to find assoc_group 0x%08x\n", id);
53 return NULL;
55 assoc_group = talloc_get_type_abort(id_ptr, struct dcesrv_assoc_group);
57 if (assoc_group->transport != transport) {
58 const char *at =
59 derpc_transport_string_by_transport(
60 assoc_group->transport);
61 const char *ct =
62 derpc_transport_string_by_transport(
63 transport);
65 DBG_NOTICE("assoc_group 0x%08x (transport %s) "
66 "is not available on transport %s",
67 id, at, ct);
68 return NULL;
71 return talloc_reference(conn, assoc_group);
74 static int dcesrv_assoc_group_destructor(struct dcesrv_assoc_group *assoc_group)
76 int ret;
77 ret = idr_remove(assoc_group->dce_ctx->assoc_groups_idr, assoc_group->id);
78 if (ret != 0) {
79 DEBUG(0,(__location__ ": Failed to remove assoc_group 0x%08x\n",
80 assoc_group->id));
82 return 0;
86 allocate a new association group
88 static struct dcesrv_assoc_group *dcesrv_assoc_group_new(struct dcesrv_connection *conn)
90 struct dcesrv_context *dce_ctx = conn->dce_ctx;
91 const struct dcesrv_endpoint *endpoint = conn->endpoint;
92 enum dcerpc_transport_t transport =
93 dcerpc_binding_get_transport(endpoint->ep_description);
94 struct dcesrv_assoc_group *assoc_group;
95 int id;
97 assoc_group = talloc_zero(conn, struct dcesrv_assoc_group);
98 if (assoc_group == NULL) {
99 return NULL;
102 id = idr_get_new_random(dce_ctx->assoc_groups_idr, assoc_group, UINT16_MAX);
103 if (id == -1) {
104 talloc_free(assoc_group);
105 DEBUG(0,(__location__ ": Out of association groups!\n"));
106 return NULL;
109 assoc_group->transport = transport;
110 assoc_group->id = id;
111 assoc_group->dce_ctx = dce_ctx;
113 talloc_set_destructor(assoc_group, dcesrv_assoc_group_destructor);
115 return assoc_group;
118 NTSTATUS dcesrv_assoc_group_find_s4(
119 struct dcesrv_call_state *call,
120 void *private_data)
123 if provided, check the assoc_group is valid
125 if (call->pkt.u.bind.assoc_group_id != 0) {
126 call->conn->assoc_group =
127 dcesrv_assoc_group_reference(call->conn,
128 call->pkt.u.bind.assoc_group_id);
129 } else {
130 call->conn->assoc_group = dcesrv_assoc_group_new(call->conn);
134 * The NETLOGON server does not use handles and so
135 * there is no need to support association groups, but
136 * we need to give back a number regardless.
138 * We have to do this when it is not run as a single process,
139 * because then it can't see the other valid association
140 * groups. We handle this genericly for all endpoints not
141 * running in single process mode.
143 * We know which endpoint we are on even before checking the
144 * iface UUID, so for simplicity we enforce the same policy
145 * for all interfaces on the endpoint.
147 * This means that where NETLOGON
148 * shares an endpoint (such as ncalrpc or if 'lsa over
149 * netlogon' is set) we will still check association groups.
153 if (call->conn->assoc_group == NULL &&
154 !call->conn->endpoint->use_single_process) {
155 call->conn->assoc_group
156 = dcesrv_assoc_group_new(call->conn);
159 if (call->conn->assoc_group == NULL) {
160 /* TODO Return correct status */
161 return NT_STATUS_UNSUCCESSFUL;
164 return NT_STATUS_OK;
167 void dcerpc_server_init(struct loadparm_context *lp_ctx)
169 static bool initialized;
170 #define _MODULE_PROTO(init) extern NTSTATUS init(TALLOC_CTX *);
171 STATIC_dcerpc_server_MODULES_PROTO;
172 init_module_fn static_init[] = { STATIC_dcerpc_server_MODULES };
173 init_module_fn *shared_init;
175 if (initialized) {
176 return;
178 initialized = true;
180 shared_init = load_samba_modules(NULL, "dcerpc_server");
182 run_init_functions(NULL, static_init);
183 run_init_functions(NULL, shared_init);
185 talloc_free(shared_init);
188 struct dcesrv_socket_context {
189 const struct dcesrv_endpoint *endpoint;
190 struct dcesrv_context *dcesrv_ctx;
193 static void dcesrv_sock_accept(struct stream_connection *srv_conn)
195 NTSTATUS status;
196 struct dcesrv_socket_context *dcesrv_sock =
197 talloc_get_type(srv_conn->private_data, struct dcesrv_socket_context);
198 enum dcerpc_transport_t transport =
199 dcerpc_binding_get_transport(dcesrv_sock->endpoint->ep_description);
200 struct dcesrv_connection *dcesrv_conn = NULL;
201 int ret;
202 struct loadparm_context *lp_ctx = dcesrv_sock->dcesrv_ctx->lp_ctx;
204 dcesrv_cleanup_broken_connections(dcesrv_sock->dcesrv_ctx);
206 if (!srv_conn->session_info) {
207 status = auth_anonymous_session_info(srv_conn,
208 lp_ctx,
209 &srv_conn->session_info);
210 if (!NT_STATUS_IS_OK(status)) {
211 DEBUG(0,("dcesrv_sock_accept: auth_anonymous_session_info failed: %s\n",
212 nt_errstr(status)));
213 stream_terminate_connection(srv_conn, nt_errstr(status));
214 return;
219 * This fills in dcesrv_conn->endpoint with the endpoint
220 * associated with the socket. From this point on we know
221 * which (group of) services we are handling, but not the
222 * specific interface.
225 status = dcesrv_endpoint_connect(dcesrv_sock->dcesrv_ctx,
226 srv_conn,
227 dcesrv_sock->endpoint,
228 srv_conn->session_info,
229 srv_conn->event.ctx,
230 DCESRV_CALL_STATE_FLAG_MAY_ASYNC,
231 &dcesrv_conn);
232 if (!NT_STATUS_IS_OK(status)) {
233 DEBUG(0,("dcesrv_sock_accept: dcesrv_endpoint_connect failed: %s\n",
234 nt_errstr(status)));
235 stream_terminate_connection(srv_conn, nt_errstr(status));
236 return;
239 dcesrv_conn->transport.private_data = srv_conn;
240 dcesrv_conn->transport.report_output_data = dcesrv_sock_report_output_data;
241 dcesrv_conn->transport.terminate_connection = dcesrv_transport_terminate_connection_s4;
243 TALLOC_FREE(srv_conn->event.fde);
245 dcesrv_conn->send_queue = tevent_queue_create(dcesrv_conn, "dcesrv send queue");
246 if (!dcesrv_conn->send_queue) {
247 status = NT_STATUS_NO_MEMORY;
248 DEBUG(0,("dcesrv_sock_accept: tevent_queue_create(%s)\n",
249 nt_errstr(status)));
250 stream_terminate_connection(srv_conn, nt_errstr(status));
251 return;
254 if (transport == NCACN_NP) {
255 dcesrv_conn->stream = talloc_move(dcesrv_conn,
256 &srv_conn->tstream);
257 } else {
258 ret = tstream_bsd_existing_socket(dcesrv_conn,
259 socket_get_fd(srv_conn->socket),
260 &dcesrv_conn->stream);
261 if (ret == -1) {
262 status = map_nt_error_from_unix_common(errno);
263 DEBUG(0, ("dcesrv_sock_accept: "
264 "failed to setup tstream: %s\n",
265 nt_errstr(status)));
266 stream_terminate_connection(srv_conn, nt_errstr(status));
267 return;
269 socket_set_flags(srv_conn->socket, SOCKET_FLAG_NOCLOSE);
272 dcesrv_conn->local_address = srv_conn->local_address;
273 dcesrv_conn->remote_address = srv_conn->remote_address;
275 if (transport == NCALRPC) {
276 uid_t uid;
277 gid_t gid;
278 int sock_fd;
280 sock_fd = socket_get_fd(srv_conn->socket);
281 if (sock_fd == -1) {
282 stream_terminate_connection(
283 srv_conn, "socket_get_fd failed\n");
284 return;
287 ret = getpeereid(sock_fd, &uid, &gid);
288 if (ret == -1) {
289 status = map_nt_error_from_unix_common(errno);
290 DEBUG(0, ("dcesrv_sock_accept: "
291 "getpeereid() failed for NCALRPC: %s\n",
292 nt_errstr(status)));
293 stream_terminate_connection(srv_conn, nt_errstr(status));
294 return;
296 if (uid == dcesrv_conn->dce_ctx->initial_euid) {
297 struct tsocket_address *r = NULL;
299 ret = tsocket_address_unix_from_path(dcesrv_conn,
300 AS_SYSTEM_MAGIC_PATH_TOKEN,
301 &r);
302 if (ret == -1) {
303 status = map_nt_error_from_unix_common(errno);
304 DEBUG(0, ("dcesrv_sock_accept: "
305 "tsocket_address_unix_from_path() failed for NCALRPC: %s\n",
306 nt_errstr(status)));
307 stream_terminate_connection(srv_conn, nt_errstr(status));
308 return;
310 dcesrv_conn->remote_address = r;
314 srv_conn->private_data = dcesrv_conn;
316 status = dcesrv_connection_loop_start(dcesrv_conn);
317 if (!NT_STATUS_IS_OK(status)) {
318 DEBUG(0,("dcesrv_sock_accept: dcerpc_read_fragment_buffer_send(%s)\n",
319 nt_errstr(status)));
320 stream_terminate_connection(srv_conn, nt_errstr(status));
321 return;
324 return;
327 static void dcesrv_sock_recv(struct stream_connection *conn, uint16_t flags)
329 struct dcesrv_connection *dce_conn = talloc_get_type(conn->private_data,
330 struct dcesrv_connection);
331 dcesrv_terminate_connection(dce_conn, "dcesrv_sock_recv triggered");
334 static void dcesrv_sock_send(struct stream_connection *conn, uint16_t flags)
336 struct dcesrv_connection *dce_conn = talloc_get_type(conn->private_data,
337 struct dcesrv_connection);
338 dcesrv_terminate_connection(dce_conn, "dcesrv_sock_send triggered");
342 static const struct stream_server_ops dcesrv_stream_ops = {
343 .name = "rpc",
344 .accept_connection = dcesrv_sock_accept,
345 .recv_handler = dcesrv_sock_recv,
346 .send_handler = dcesrv_sock_send,
349 static NTSTATUS dcesrv_add_ep_unix(struct dcesrv_context *dce_ctx,
350 struct loadparm_context *lp_ctx,
351 struct dcesrv_endpoint *e,
352 struct tevent_context *event_ctx,
353 const struct model_ops *model_ops,
354 void *process_context)
356 struct dcesrv_socket_context *dcesrv_sock;
357 uint16_t port = 1;
358 NTSTATUS status;
359 const char *endpoint;
361 dcesrv_sock = talloc_zero(event_ctx, struct dcesrv_socket_context);
362 NT_STATUS_HAVE_NO_MEMORY(dcesrv_sock);
364 /* remember the endpoint of this socket */
365 dcesrv_sock->endpoint = e;
366 dcesrv_sock->dcesrv_ctx = talloc_reference(dcesrv_sock, dce_ctx);
368 endpoint = dcerpc_binding_get_string_option(e->ep_description, "endpoint");
370 status = stream_setup_socket(dcesrv_sock, event_ctx, lp_ctx,
371 model_ops, &dcesrv_stream_ops,
372 "unix", endpoint, &port,
373 lpcfg_socket_options(lp_ctx),
374 dcesrv_sock, process_context);
375 if (!NT_STATUS_IS_OK(status)) {
376 DEBUG(0,("service_setup_stream_socket(path=%s) failed - %s\n",
377 endpoint, nt_errstr(status)));
380 return status;
383 static NTSTATUS dcesrv_add_ep_ncalrpc(struct dcesrv_context *dce_ctx,
384 struct loadparm_context *lp_ctx,
385 struct dcesrv_endpoint *e,
386 struct tevent_context *event_ctx,
387 const struct model_ops *model_ops,
388 void *process_context)
390 struct dcesrv_socket_context *dcesrv_sock;
391 uint16_t port = 1;
392 char *full_path;
393 NTSTATUS status;
394 const char *endpoint;
396 endpoint = dcerpc_binding_get_string_option(e->ep_description, "endpoint");
398 if (endpoint == NULL) {
400 * No identifier specified: use DEFAULT.
402 * TODO: DO NOT hardcode this value anywhere else. Rather, specify
403 * no endpoint and let the epmapper worry about it.
405 endpoint = "DEFAULT";
406 status = dcerpc_binding_set_string_option(e->ep_description,
407 "endpoint",
408 endpoint);
409 if (!NT_STATUS_IS_OK(status)) {
410 DEBUG(0,("dcerpc_binding_set_string_option() failed - %s\n",
411 nt_errstr(status)));
412 return status;
416 full_path = talloc_asprintf(dce_ctx, "%s/%s", lpcfg_ncalrpc_dir(lp_ctx),
417 endpoint);
419 dcesrv_sock = talloc_zero(event_ctx, struct dcesrv_socket_context);
420 NT_STATUS_HAVE_NO_MEMORY(dcesrv_sock);
422 /* remember the endpoint of this socket */
423 dcesrv_sock->endpoint = e;
424 dcesrv_sock->dcesrv_ctx = talloc_reference(dcesrv_sock, dce_ctx);
426 status = stream_setup_socket(dcesrv_sock, event_ctx, lp_ctx,
427 model_ops, &dcesrv_stream_ops,
428 "unix", full_path, &port,
429 lpcfg_socket_options(lp_ctx),
430 dcesrv_sock, process_context);
431 if (!NT_STATUS_IS_OK(status)) {
432 DEBUG(0,("service_setup_stream_socket(identifier=%s,path=%s) failed - %s\n",
433 endpoint, full_path, nt_errstr(status)));
435 return status;
438 static NTSTATUS dcesrv_add_ep_np(struct dcesrv_context *dce_ctx,
439 struct loadparm_context *lp_ctx,
440 struct dcesrv_endpoint *e,
441 struct tevent_context *event_ctx,
442 const struct model_ops *model_ops,
443 void *process_context)
445 struct dcesrv_socket_context *dcesrv_sock;
446 NTSTATUS status;
447 const char *endpoint;
449 endpoint = dcerpc_binding_get_string_option(e->ep_description, "endpoint");
450 if (endpoint == NULL) {
451 DEBUG(0, ("Endpoint mandatory for named pipes\n"));
452 return NT_STATUS_INVALID_PARAMETER;
455 dcesrv_sock = talloc_zero(event_ctx, struct dcesrv_socket_context);
456 NT_STATUS_HAVE_NO_MEMORY(dcesrv_sock);
458 /* remember the endpoint of this socket */
459 dcesrv_sock->endpoint = e;
460 dcesrv_sock->dcesrv_ctx = talloc_reference(dcesrv_sock, dce_ctx);
462 status = tstream_setup_named_pipe(dce_ctx, event_ctx, lp_ctx,
463 model_ops, &dcesrv_stream_ops,
464 endpoint,
465 dcesrv_sock, process_context);
466 if (!NT_STATUS_IS_OK(status)) {
467 DEBUG(0,("stream_setup_named_pipe(pipe=%s) failed - %s\n",
468 endpoint, nt_errstr(status)));
469 return status;
472 return NT_STATUS_OK;
476 add a socket address to the list of events, one event per dcerpc endpoint
478 static NTSTATUS add_socket_rpc_tcp_iface(struct dcesrv_context *dce_ctx,
479 struct dcesrv_endpoint *e,
480 struct tevent_context *event_ctx,
481 const struct model_ops *model_ops,
482 const char *address,
483 void *process_context)
485 struct dcesrv_socket_context *dcesrv_sock;
486 uint16_t port = 0;
487 NTSTATUS status;
488 const char *endpoint;
489 char port_str[6];
491 endpoint = dcerpc_binding_get_string_option(e->ep_description, "endpoint");
492 if (endpoint != NULL) {
493 port = atoi(endpoint);
496 dcesrv_sock = talloc_zero(event_ctx, struct dcesrv_socket_context);
497 NT_STATUS_HAVE_NO_MEMORY(dcesrv_sock);
499 /* remember the endpoint of this socket */
500 dcesrv_sock->endpoint = e;
501 dcesrv_sock->dcesrv_ctx = talloc_reference(dcesrv_sock, dce_ctx);
503 status = stream_setup_socket(dcesrv_sock, event_ctx, dce_ctx->lp_ctx,
504 model_ops, &dcesrv_stream_ops,
505 "ip", address, &port,
506 lpcfg_socket_options(dce_ctx->lp_ctx),
507 dcesrv_sock, process_context);
508 if (!NT_STATUS_IS_OK(status)) {
509 struct dcesrv_if_list *iface;
510 DEBUG(0,("service_setup_stream_socket(address=%s,port=%u) for ",
511 address, port));
512 for (iface = e->interface_list; iface; iface = iface->next) {
513 DEBUGADD(0, ("%s ", iface->iface->name));
515 DEBUGADD(0, ("failed - %s\n",
516 nt_errstr(status)));
517 return status;
520 snprintf(port_str, sizeof(port_str), "%u", port);
522 status = dcerpc_binding_set_string_option(e->ep_description,
523 "endpoint", port_str);
524 if (!NT_STATUS_IS_OK(status)) {
525 DEBUG(0,("dcerpc_binding_set_string_option(endpoint, %s) failed - %s\n",
526 port_str, nt_errstr(status)));
527 return status;
528 } else {
529 struct dcesrv_if_list *iface;
530 DEBUG(4,("Successfully listening on ncacn_ip_tcp endpoint [%s]:[%s] for ",
531 address, port_str));
532 for (iface = e->interface_list; iface; iface = iface->next) {
533 DEBUGADD(4, ("%s ", iface->iface->name));
535 DEBUGADD(4, ("\n"));
538 return NT_STATUS_OK;
541 #include "lib/socket/netif.h" /* Included here to work around the fact that socket_wrapper redefines bind() */
543 static NTSTATUS dcesrv_add_ep_tcp(struct dcesrv_context *dce_ctx,
544 struct loadparm_context *lp_ctx,
545 struct dcesrv_endpoint *e,
546 struct tevent_context *event_ctx,
547 const struct model_ops *model_ops,
548 void *process_context)
550 NTSTATUS status;
552 /* Add TCP/IP sockets */
553 if (lpcfg_interfaces(lp_ctx) && lpcfg_bind_interfaces_only(lp_ctx)) {
554 int num_interfaces;
555 int i;
556 struct interface *ifaces;
558 load_interface_list(dce_ctx, lp_ctx, &ifaces);
560 num_interfaces = iface_list_count(ifaces);
561 for(i = 0; i < num_interfaces; i++) {
562 const char *address = iface_list_n_ip(ifaces, i);
563 status = add_socket_rpc_tcp_iface(dce_ctx, e, event_ctx,
564 model_ops, address,
565 process_context);
566 NT_STATUS_NOT_OK_RETURN(status);
568 } else {
569 char **wcard;
570 size_t i;
571 size_t num_binds = 0;
572 wcard = iface_list_wildcard(dce_ctx);
573 NT_STATUS_HAVE_NO_MEMORY(wcard);
574 for (i=0; wcard[i]; i++) {
575 status = add_socket_rpc_tcp_iface(dce_ctx, e, event_ctx,
576 model_ops, wcard[i],
577 process_context);
578 if (NT_STATUS_IS_OK(status)) {
579 num_binds++;
582 talloc_free(wcard);
583 if (num_binds == 0) {
584 return NT_STATUS_INVALID_PARAMETER_MIX;
588 return NT_STATUS_OK;
591 NTSTATUS dcesrv_add_ep(struct dcesrv_context *dce_ctx,
592 struct loadparm_context *lp_ctx,
593 struct dcesrv_endpoint *e,
594 struct tevent_context *event_ctx,
595 const struct model_ops *model_ops,
596 void *process_context)
598 enum dcerpc_transport_t transport =
599 dcerpc_binding_get_transport(e->ep_description);
601 switch (transport) {
602 case NCACN_UNIX_STREAM:
603 return dcesrv_add_ep_unix(dce_ctx, lp_ctx, e, event_ctx,
604 model_ops, process_context);
606 case NCALRPC:
607 return dcesrv_add_ep_ncalrpc(dce_ctx, lp_ctx, e, event_ctx,
608 model_ops, process_context);
610 case NCACN_IP_TCP:
611 return dcesrv_add_ep_tcp(dce_ctx, lp_ctx, e, event_ctx,
612 model_ops, process_context);
614 case NCACN_NP:
615 return dcesrv_add_ep_np(dce_ctx, lp_ctx, e, event_ctx,
616 model_ops, process_context);
618 default:
619 return NT_STATUS_NOT_SUPPORTED;
623 _PUBLIC_ struct imessaging_context *dcesrv_imessaging_context(
624 struct dcesrv_connection *conn)
626 struct stream_connection *srv_conn =
627 talloc_get_type_abort(conn->transport.private_data,
628 struct stream_connection);
629 return srv_conn->msg_ctx;
632 _PUBLIC_ struct server_id dcesrv_server_id(struct dcesrv_connection *conn)
634 struct stream_connection *srv_conn =
635 talloc_get_type_abort(conn->transport.private_data,
636 struct stream_connection);
637 return srv_conn->server_id;
640 void log_successful_dcesrv_authz_event(
641 struct dcesrv_call_state *call,
642 void *private_data)
644 struct dcesrv_auth *auth = call->auth_state;
645 enum dcerpc_transport_t transport =
646 dcerpc_binding_get_transport(call->conn->endpoint->ep_description);
647 struct imessaging_context *imsg_ctx =
648 dcesrv_imessaging_context(call->conn);
649 const char *auth_type = derpc_transport_string_by_transport(transport);
650 const char *transport_protection = AUTHZ_TRANSPORT_PROTECTION_NONE;
652 if (transport == NCACN_NP) {
653 transport_protection = AUTHZ_TRANSPORT_PROTECTION_SMB;
657 * Log the authorization to this RPC interface. This
658 * covered ncacn_np pass-through auth, and anonymous
659 * DCE/RPC (eg epmapper, netlogon etc)
661 log_successful_authz_event(imsg_ctx,
662 call->conn->dce_ctx->lp_ctx,
663 call->conn->remote_address,
664 call->conn->local_address,
665 "DCE/RPC",
666 auth_type,
667 transport_protection,
668 auth->session_info);
670 auth->auth_audited = true;
673 NTSTATUS dcesrv_gensec_prepare(
674 TALLOC_CTX *mem_ctx,
675 struct dcesrv_call_state *call,
676 struct gensec_security **out,
677 void *private_data)
679 struct cli_credentials *server_creds = NULL;
680 struct imessaging_context *imsg_ctx =
681 dcesrv_imessaging_context(call->conn);
682 bool ok;
684 server_creds = cli_credentials_init_server(call->auth_state,
685 call->conn->dce_ctx->lp_ctx);
686 if (server_creds == NULL) {
687 DEBUG(1, ("Failed to init server credentials\n"));
688 return NT_STATUS_NO_MEMORY;
690 /* This is required for ncalrpc_as_system. */
691 ok = cli_credentials_set_kerberos_state(server_creds,
692 CRED_USE_KERBEROS_DESIRED,
693 CRED_SPECIFIED);
694 if (!ok) {
695 DBG_WARNING("Failed to set kerberos state\n");
696 return NT_STATUS_INTERNAL_ERROR;
699 return samba_server_gensec_start(mem_ctx,
700 call->event_ctx,
701 imsg_ctx,
702 call->conn->dce_ctx->lp_ctx,
703 server_creds,
704 NULL,
705 out);
708 void dcesrv_transport_terminate_connection_s4(struct dcesrv_connection *dce_conn,
709 const char *reason)
711 struct stream_connection *srv_conn =
712 talloc_get_type_abort(dce_conn->transport.private_data,
713 struct stream_connection);
714 stream_terminate_connection(srv_conn, reason);