s4-rpc_server: Add comments explaining the control flow around dcesrv_bind()
[Samba.git] / source4 / rpc_server / dcerpc_server.c
blob0d39744172e8702f68f2eabfef09f37c3dd2a164
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 "../lib/util/dlinklist.h"
27 #include "rpc_server/dcerpc_server.h"
28 #include "rpc_server/dcerpc_server_proto.h"
29 #include "rpc_server/common/proto.h"
30 #include "librpc/rpc/dcerpc_proto.h"
31 #include "system/filesys.h"
32 #include "libcli/security/security.h"
33 #include "param/param.h"
34 #include "../lib/tsocket/tsocket.h"
35 #include "../libcli/named_pipe_auth/npa_tstream.h"
36 #include "smbd/service_stream.h"
37 #include "../lib/tsocket/tsocket.h"
38 #include "lib/socket/socket.h"
39 #include "smbd/process_model.h"
40 #include "lib/messaging/irpc.h"
41 #include "librpc/rpc/rpc_common.h"
42 #include "lib/util/samba_modules.h"
43 #include "librpc/gen_ndr/ndr_dcerpc.h"
45 static NTSTATUS dcesrv_negotiate_contexts(struct dcesrv_call_state *call,
46 const struct dcerpc_bind *b,
47 struct dcerpc_ack_ctx *ack_ctx_list);
50 find an association group given a assoc_group_id
52 static struct dcesrv_assoc_group *dcesrv_assoc_group_find(struct dcesrv_context *dce_ctx,
53 uint32_t id)
55 void *id_ptr;
57 id_ptr = idr_find(dce_ctx->assoc_groups_idr, id);
58 if (id_ptr == NULL) {
59 return NULL;
61 return talloc_get_type_abort(id_ptr, struct dcesrv_assoc_group);
65 take a reference to an existing association group
67 static struct dcesrv_assoc_group *dcesrv_assoc_group_reference(TALLOC_CTX *mem_ctx,
68 struct dcesrv_context *dce_ctx,
69 uint32_t id)
71 struct dcesrv_assoc_group *assoc_group;
73 assoc_group = dcesrv_assoc_group_find(dce_ctx, id);
74 if (assoc_group == NULL) {
75 DEBUG(2,(__location__ ": Failed to find assoc_group 0x%08x\n", id));
76 return NULL;
78 return talloc_reference(mem_ctx, assoc_group);
81 static int dcesrv_assoc_group_destructor(struct dcesrv_assoc_group *assoc_group)
83 int ret;
84 ret = idr_remove(assoc_group->dce_ctx->assoc_groups_idr, assoc_group->id);
85 if (ret != 0) {
86 DEBUG(0,(__location__ ": Failed to remove assoc_group 0x%08x\n",
87 assoc_group->id));
89 return 0;
93 allocate a new association group
95 static struct dcesrv_assoc_group *dcesrv_assoc_group_new(TALLOC_CTX *mem_ctx,
96 struct dcesrv_context *dce_ctx)
98 struct dcesrv_assoc_group *assoc_group;
99 int id;
101 assoc_group = talloc_zero(mem_ctx, struct dcesrv_assoc_group);
102 if (assoc_group == NULL) {
103 return NULL;
106 id = idr_get_new_random(dce_ctx->assoc_groups_idr, assoc_group, UINT16_MAX);
107 if (id == -1) {
108 talloc_free(assoc_group);
109 DEBUG(0,(__location__ ": Out of association groups!\n"));
110 return NULL;
113 assoc_group->id = id;
114 assoc_group->dce_ctx = dce_ctx;
116 talloc_set_destructor(assoc_group, dcesrv_assoc_group_destructor);
118 return assoc_group;
123 see if two endpoints match
125 static bool endpoints_match(const struct dcerpc_binding *ep1,
126 const struct dcerpc_binding *ep2)
128 enum dcerpc_transport_t t1;
129 enum dcerpc_transport_t t2;
130 const char *e1;
131 const char *e2;
133 t1 = dcerpc_binding_get_transport(ep1);
134 t2 = dcerpc_binding_get_transport(ep2);
136 e1 = dcerpc_binding_get_string_option(ep1, "endpoint");
137 e2 = dcerpc_binding_get_string_option(ep2, "endpoint");
139 if (t1 != t2) {
140 return false;
143 if (!e1 || !e2) {
144 return e1 == e2;
147 if (strcasecmp(e1, e2) != 0) {
148 return false;
151 return true;
155 find an endpoint in the dcesrv_context
157 static struct dcesrv_endpoint *find_endpoint(struct dcesrv_context *dce_ctx,
158 const struct dcerpc_binding *ep_description)
160 struct dcesrv_endpoint *ep;
161 for (ep=dce_ctx->endpoint_list; ep; ep=ep->next) {
162 if (endpoints_match(ep->ep_description, ep_description)) {
163 return ep;
166 return NULL;
170 find a registered context_id from a bind or alter_context
172 static struct dcesrv_connection_context *dcesrv_find_context(struct dcesrv_connection *conn,
173 uint16_t context_id)
175 struct dcesrv_connection_context *c;
176 for (c=conn->contexts;c;c=c->next) {
177 if (c->context_id == context_id) return c;
179 return NULL;
183 see if a uuid and if_version match to an interface
185 static bool interface_match(const struct dcesrv_interface *if1,
186 const struct dcesrv_interface *if2)
188 return (if1->syntax_id.if_version == if2->syntax_id.if_version &&
189 GUID_equal(&if1->syntax_id.uuid, &if2->syntax_id.uuid));
193 find the interface operations on an endpoint
195 static const struct dcesrv_interface *find_interface(const struct dcesrv_endpoint *endpoint,
196 const struct dcesrv_interface *iface)
198 struct dcesrv_if_list *ifl;
199 for (ifl=endpoint->interface_list; ifl; ifl=ifl->next) {
200 if (interface_match(&(ifl->iface), iface)) {
201 return &(ifl->iface);
204 return NULL;
208 see if a uuid and if_version match to an interface
210 static bool interface_match_by_uuid(const struct dcesrv_interface *iface,
211 const struct GUID *uuid, uint32_t if_version)
213 return (iface->syntax_id.if_version == if_version &&
214 GUID_equal(&iface->syntax_id.uuid, uuid));
218 find the interface operations on an endpoint by uuid
220 static const struct dcesrv_interface *find_interface_by_uuid(const struct dcesrv_endpoint *endpoint,
221 const struct GUID *uuid, uint32_t if_version)
223 struct dcesrv_if_list *ifl;
224 for (ifl=endpoint->interface_list; ifl; ifl=ifl->next) {
225 if (interface_match_by_uuid(&(ifl->iface), uuid, if_version)) {
226 return &(ifl->iface);
229 return NULL;
233 find the earlier parts of a fragmented call awaiting reassembily
235 static struct dcesrv_call_state *dcesrv_find_fragmented_call(struct dcesrv_connection *dce_conn, uint16_t call_id)
237 struct dcesrv_call_state *c;
238 for (c=dce_conn->incoming_fragmented_call_list;c;c=c->next) {
239 if (c->pkt.call_id == call_id) {
240 return c;
243 return NULL;
247 register an interface on an endpoint
249 _PUBLIC_ NTSTATUS dcesrv_interface_register(struct dcesrv_context *dce_ctx,
250 const char *ep_name,
251 const struct dcesrv_interface *iface,
252 const struct security_descriptor *sd)
254 struct dcesrv_endpoint *ep;
255 struct dcesrv_if_list *ifl;
256 struct dcerpc_binding *binding;
257 bool add_ep = false;
258 NTSTATUS status;
260 status = dcerpc_parse_binding(dce_ctx, ep_name, &binding);
262 if (NT_STATUS_IS_ERR(status)) {
263 DEBUG(0, ("Trouble parsing binding string '%s'\n", ep_name));
264 return status;
267 /* check if this endpoint exists
269 if ((ep=find_endpoint(dce_ctx, binding))==NULL) {
270 ep = talloc_zero(dce_ctx, struct dcesrv_endpoint);
271 if (!ep) {
272 return NT_STATUS_NO_MEMORY;
274 ZERO_STRUCTP(ep);
275 ep->ep_description = talloc_move(ep, &binding);
276 add_ep = true;
278 /* add mgmt interface */
279 ifl = talloc_zero(ep, struct dcesrv_if_list);
280 if (!ifl) {
281 return NT_STATUS_NO_MEMORY;
284 ifl->iface = dcesrv_get_mgmt_interface();
286 DLIST_ADD(ep->interface_list, ifl);
289 /* see if the interface is already registered on te endpoint */
290 if (find_interface(ep, iface)!=NULL) {
291 DEBUG(0,("dcesrv_interface_register: interface '%s' already registered on endpoint '%s'\n",
292 iface->name, ep_name));
293 return NT_STATUS_OBJECT_NAME_COLLISION;
296 /* talloc a new interface list element */
297 ifl = talloc_zero(ep, struct dcesrv_if_list);
298 if (!ifl) {
299 return NT_STATUS_NO_MEMORY;
302 /* copy the given interface struct to the one on the endpoints interface list */
303 memcpy(&(ifl->iface),iface, sizeof(struct dcesrv_interface));
305 /* if we have a security descriptor given,
306 * we should see if we can set it up on the endpoint
308 if (sd != NULL) {
309 /* if there's currently no security descriptor given on the endpoint
310 * we try to set it
312 if (ep->sd == NULL) {
313 ep->sd = security_descriptor_copy(ep, sd);
316 /* if now there's no security descriptor given on the endpoint
317 * something goes wrong, either we failed to copy the security descriptor
318 * or there was already one on the endpoint
320 if (ep->sd != NULL) {
321 DEBUG(0,("dcesrv_interface_register: interface '%s' failed to setup a security descriptor\n"
322 " on endpoint '%s'\n",
323 iface->name, ep_name));
324 if (add_ep) free(ep);
325 free(ifl);
326 return NT_STATUS_OBJECT_NAME_COLLISION;
330 /* finally add the interface on the endpoint */
331 DLIST_ADD(ep->interface_list, ifl);
333 /* if it's a new endpoint add it to the dcesrv_context */
334 if (add_ep) {
335 DLIST_ADD(dce_ctx->endpoint_list, ep);
338 DEBUG(4,("dcesrv_interface_register: interface '%s' registered on endpoint '%s'\n",
339 iface->name, ep_name));
341 return NT_STATUS_OK;
344 NTSTATUS dcesrv_inherited_session_key(struct dcesrv_connection *p,
345 DATA_BLOB *session_key)
347 if (p->auth_state.session_info->session_key.length) {
348 *session_key = p->auth_state.session_info->session_key;
349 return NT_STATUS_OK;
351 return NT_STATUS_NO_USER_SESSION_KEY;
355 fetch the user session key - may be default (above) or the SMB session key
357 The key is always truncated to 16 bytes
359 _PUBLIC_ NTSTATUS dcesrv_fetch_session_key(struct dcesrv_connection *p,
360 DATA_BLOB *session_key)
362 NTSTATUS status = p->auth_state.session_key(p, session_key);
363 if (!NT_STATUS_IS_OK(status)) {
364 return status;
367 session_key->length = MIN(session_key->length, 16);
369 return NT_STATUS_OK;
373 connect to a dcerpc endpoint
375 _PUBLIC_ NTSTATUS dcesrv_endpoint_connect(struct dcesrv_context *dce_ctx,
376 TALLOC_CTX *mem_ctx,
377 const struct dcesrv_endpoint *ep,
378 struct auth_session_info *session_info,
379 struct tevent_context *event_ctx,
380 struct imessaging_context *msg_ctx,
381 struct server_id server_id,
382 uint32_t state_flags,
383 struct dcesrv_connection **_p)
385 struct dcesrv_connection *p;
387 if (!session_info) {
388 return NT_STATUS_ACCESS_DENIED;
391 p = talloc_zero(mem_ctx, struct dcesrv_connection);
392 NT_STATUS_HAVE_NO_MEMORY(p);
394 if (!talloc_reference(p, session_info)) {
395 talloc_free(p);
396 return NT_STATUS_NO_MEMORY;
399 p->dce_ctx = dce_ctx;
400 p->endpoint = ep;
401 p->packet_log_dir = lpcfg_lock_directory(dce_ctx->lp_ctx);
402 p->auth_state.session_info = session_info;
403 p->auth_state.session_key = dcesrv_generic_session_key;
404 p->event_ctx = event_ctx;
405 p->msg_ctx = msg_ctx;
406 p->server_id = server_id;
407 p->state_flags = state_flags;
408 p->allow_bind = true;
409 p->max_recv_frag = 5840;
410 p->max_xmit_frag = 5840;
411 p->max_total_request_size = DCERPC_NCACN_REQUEST_DEFAULT_MAX_SIZE;
414 * For now we only support NDR32.
416 p->preferred_transfer = &ndr_transfer_syntax_ndr;
418 *_p = p;
419 return NT_STATUS_OK;
423 move a call from an existing linked list to the specified list. This
424 prevents bugs where we forget to remove the call from a previous
425 list when moving it.
427 static void dcesrv_call_set_list(struct dcesrv_call_state *call,
428 enum dcesrv_call_list list)
430 switch (call->list) {
431 case DCESRV_LIST_NONE:
432 break;
433 case DCESRV_LIST_CALL_LIST:
434 DLIST_REMOVE(call->conn->call_list, call);
435 break;
436 case DCESRV_LIST_FRAGMENTED_CALL_LIST:
437 DLIST_REMOVE(call->conn->incoming_fragmented_call_list, call);
438 break;
439 case DCESRV_LIST_PENDING_CALL_LIST:
440 DLIST_REMOVE(call->conn->pending_call_list, call);
441 break;
443 call->list = list;
444 switch (list) {
445 case DCESRV_LIST_NONE:
446 break;
447 case DCESRV_LIST_CALL_LIST:
448 DLIST_ADD_END(call->conn->call_list, call);
449 break;
450 case DCESRV_LIST_FRAGMENTED_CALL_LIST:
451 DLIST_ADD_END(call->conn->incoming_fragmented_call_list, call);
452 break;
453 case DCESRV_LIST_PENDING_CALL_LIST:
454 DLIST_ADD_END(call->conn->pending_call_list, call);
455 break;
459 static void dcesrv_call_disconnect_after(struct dcesrv_call_state *call,
460 const char *reason)
462 if (call->conn->terminate != NULL) {
463 return;
466 call->conn->allow_bind = false;
467 call->conn->allow_alter = false;
468 call->conn->allow_auth3 = false;
469 call->conn->allow_request = false;
471 call->terminate_reason = talloc_strdup(call, reason);
472 if (call->terminate_reason == NULL) {
473 call->terminate_reason = __location__;
478 return a dcerpc bind_nak
480 static NTSTATUS dcesrv_bind_nak(struct dcesrv_call_state *call, uint32_t reason)
482 struct ncacn_packet pkt;
483 struct dcerpc_bind_nak_version version;
484 struct data_blob_list_item *rep;
485 NTSTATUS status;
486 static const uint8_t _pad[3] = { 0, };
489 * We add the call to the pending_call_list
490 * in order to defer the termination.
492 dcesrv_call_disconnect_after(call, "dcesrv_bind_nak");
494 /* setup a bind_nak */
495 dcesrv_init_hdr(&pkt, lpcfg_rpc_big_endian(call->conn->dce_ctx->lp_ctx));
496 pkt.auth_length = 0;
497 pkt.call_id = call->pkt.call_id;
498 pkt.ptype = DCERPC_PKT_BIND_NAK;
499 pkt.pfc_flags = DCERPC_PFC_FLAG_FIRST | DCERPC_PFC_FLAG_LAST;
500 pkt.u.bind_nak.reject_reason = reason;
501 version.rpc_vers = 5;
502 version.rpc_vers_minor = 0;
503 pkt.u.bind_nak.num_versions = 1;
504 pkt.u.bind_nak.versions = &version;
505 pkt.u.bind_nak._pad = data_blob_const(_pad, sizeof(_pad));
507 rep = talloc_zero(call, struct data_blob_list_item);
508 if (!rep) {
509 return NT_STATUS_NO_MEMORY;
512 status = ncacn_push_auth(&rep->blob, call, &pkt, NULL);
513 if (!NT_STATUS_IS_OK(status)) {
514 return status;
517 dcerpc_set_frag_length(&rep->blob, rep->blob.length);
519 DLIST_ADD_END(call->replies, rep);
520 dcesrv_call_set_list(call, DCESRV_LIST_CALL_LIST);
522 if (call->conn->call_list && call->conn->call_list->replies) {
523 if (call->conn->transport.report_output_data) {
524 call->conn->transport.report_output_data(call->conn);
528 return NT_STATUS_OK;
531 static NTSTATUS dcesrv_fault_disconnect(struct dcesrv_call_state *call,
532 uint32_t fault_code)
535 * We add the call to the pending_call_list
536 * in order to defer the termination.
538 dcesrv_call_disconnect_after(call, "dcesrv_fault_disconnect");
540 return dcesrv_fault_with_flags(call, fault_code,
541 DCERPC_PFC_FLAG_DID_NOT_EXECUTE);
544 static int dcesrv_connection_context_destructor(struct dcesrv_connection_context *c)
546 DLIST_REMOVE(c->conn->contexts, c);
548 if (c->iface && c->iface->unbind) {
549 c->iface->unbind(c, c->iface);
550 c->iface = NULL;
553 return 0;
556 static void dcesrv_prepare_context_auth(struct dcesrv_call_state *dce_call)
558 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
559 const struct dcesrv_endpoint *endpoint = dce_call->conn->endpoint;
560 enum dcerpc_transport_t transport =
561 dcerpc_binding_get_transport(endpoint->ep_description);
562 struct dcesrv_connection_context *context = dce_call->context;
563 const struct dcesrv_interface *iface = context->iface;
565 context->min_auth_level = DCERPC_AUTH_LEVEL_NONE;
567 if (transport == NCALRPC) {
568 context->allow_connect = true;
569 return;
573 * allow overwrite per interface
574 * allow dcerpc auth level connect:<interface>
576 context->allow_connect = lpcfg_allow_dcerpc_auth_level_connect(lp_ctx);
577 context->allow_connect = lpcfg_parm_bool(lp_ctx, NULL,
578 "allow dcerpc auth level connect",
579 iface->name,
580 context->allow_connect);
583 NTSTATUS dcesrv_interface_bind_require_integrity(struct dcesrv_call_state *dce_call,
584 const struct dcesrv_interface *iface)
586 if (dce_call->context == NULL) {
587 return NT_STATUS_INTERNAL_ERROR;
591 * For connection oriented DCERPC DCERPC_AUTH_LEVEL_PACKET (4)
592 * has the same behavior as DCERPC_AUTH_LEVEL_INTEGRITY (5).
594 dce_call->context->min_auth_level = DCERPC_AUTH_LEVEL_PACKET;
595 return NT_STATUS_OK;
598 NTSTATUS dcesrv_interface_bind_require_privacy(struct dcesrv_call_state *dce_call,
599 const struct dcesrv_interface *iface)
601 if (dce_call->context == NULL) {
602 return NT_STATUS_INTERNAL_ERROR;
605 dce_call->context->min_auth_level = DCERPC_AUTH_LEVEL_PRIVACY;
606 return NT_STATUS_OK;
609 _PUBLIC_ NTSTATUS dcesrv_interface_bind_reject_connect(struct dcesrv_call_state *dce_call,
610 const struct dcesrv_interface *iface)
612 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
613 const struct dcesrv_endpoint *endpoint = dce_call->conn->endpoint;
614 enum dcerpc_transport_t transport =
615 dcerpc_binding_get_transport(endpoint->ep_description);
616 struct dcesrv_connection_context *context = dce_call->context;
618 if (context == NULL) {
619 return NT_STATUS_INTERNAL_ERROR;
622 if (transport == NCALRPC) {
623 context->allow_connect = true;
624 return NT_STATUS_OK;
628 * allow overwrite per interface
629 * allow dcerpc auth level connect:<interface>
631 context->allow_connect = false;
632 context->allow_connect = lpcfg_parm_bool(lp_ctx, NULL,
633 "allow dcerpc auth level connect",
634 iface->name,
635 context->allow_connect);
636 return NT_STATUS_OK;
639 _PUBLIC_ NTSTATUS dcesrv_interface_bind_allow_connect(struct dcesrv_call_state *dce_call,
640 const struct dcesrv_interface *iface)
642 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
643 const struct dcesrv_endpoint *endpoint = dce_call->conn->endpoint;
644 enum dcerpc_transport_t transport =
645 dcerpc_binding_get_transport(endpoint->ep_description);
646 struct dcesrv_connection_context *context = dce_call->context;
648 if (context == NULL) {
649 return NT_STATUS_INTERNAL_ERROR;
652 if (transport == NCALRPC) {
653 context->allow_connect = true;
654 return NT_STATUS_OK;
658 * allow overwrite per interface
659 * allow dcerpc auth level connect:<interface>
661 context->allow_connect = true;
662 context->allow_connect = lpcfg_parm_bool(lp_ctx, NULL,
663 "allow dcerpc auth level connect",
664 iface->name,
665 context->allow_connect);
666 return NT_STATUS_OK;
670 handle a bind request
672 static NTSTATUS dcesrv_bind(struct dcesrv_call_state *call)
674 struct ncacn_packet pkt;
675 struct data_blob_list_item *rep;
676 NTSTATUS status;
677 uint32_t extra_flags = 0;
678 uint16_t max_req = 0;
679 uint16_t max_rep = 0;
680 const char *ep_prefix = "";
681 const char *endpoint = NULL;
682 struct dcerpc_ack_ctx *ack_ctx_list = NULL;
683 struct dcerpc_ack_ctx *ack_features = NULL;
684 size_t i;
686 status = dcerpc_verify_ncacn_packet_header(&call->pkt,
687 DCERPC_PKT_BIND,
688 call->pkt.u.bind.auth_info.length,
689 0, /* required flags */
690 DCERPC_PFC_FLAG_FIRST |
691 DCERPC_PFC_FLAG_LAST |
692 DCERPC_PFC_FLAG_SUPPORT_HEADER_SIGN |
693 0x08 | /* this is not defined, but should be ignored */
694 DCERPC_PFC_FLAG_CONC_MPX |
695 DCERPC_PFC_FLAG_DID_NOT_EXECUTE |
696 DCERPC_PFC_FLAG_MAYBE |
697 DCERPC_PFC_FLAG_OBJECT_UUID);
698 if (!NT_STATUS_IS_OK(status)) {
699 return dcesrv_bind_nak(call,
700 DCERPC_BIND_NAK_REASON_PROTOCOL_VERSION_NOT_SUPPORTED);
703 /* max_recv_frag and max_xmit_frag result always in the same value! */
704 max_req = MIN(call->pkt.u.bind.max_xmit_frag,
705 call->pkt.u.bind.max_recv_frag);
707 * The values are between 2048 and 5840 tested against Windows 2012R2
708 * via ncacn_ip_tcp on port 135.
710 max_req = MAX(2048, max_req);
711 max_rep = MIN(max_req, call->conn->max_recv_frag);
712 /* They are truncated to an 8 byte boundary. */
713 max_rep &= 0xFFF8;
715 /* max_recv_frag and max_xmit_frag result always in the same value! */
716 call->conn->max_recv_frag = max_rep;
717 call->conn->max_xmit_frag = max_rep;
720 if provided, check the assoc_group is valid
722 if (call->pkt.u.bind.assoc_group_id != 0) {
723 call->conn->assoc_group = dcesrv_assoc_group_reference(call->conn,
724 call->conn->dce_ctx,
725 call->pkt.u.bind.assoc_group_id);
726 } else {
727 call->conn->assoc_group = dcesrv_assoc_group_new(call->conn,
728 call->conn->dce_ctx);
730 if (call->conn->assoc_group == NULL) {
731 return dcesrv_bind_nak(call, 0);
734 if (call->pkt.u.bind.num_contexts < 1) {
735 return dcesrv_bind_nak(call, 0);
738 ack_ctx_list = talloc_zero_array(call, struct dcerpc_ack_ctx,
739 call->pkt.u.bind.num_contexts);
740 if (ack_ctx_list == NULL) {
741 return dcesrv_bind_nak(call, 0);
745 * Set some sane defaults (required by dcesrv_negotiate_contexts()/
746 * dcesrv_check_or_create_context()) and do some protocol validation
747 * and set sane defaults.
749 for (i = 0; i < call->pkt.u.bind.num_contexts; i++) {
750 const struct dcerpc_ctx_list *c = &call->pkt.u.bind.ctx_list[i];
751 struct dcerpc_ack_ctx *a = &ack_ctx_list[i];
752 bool is_feature = false;
753 uint64_t features = 0;
755 if (c->num_transfer_syntaxes == 0) {
756 return dcesrv_bind_nak(call, 0);
759 a->result = DCERPC_BIND_ACK_RESULT_PROVIDER_REJECTION;
760 a->reason.value = DCERPC_BIND_ACK_REASON_ABSTRACT_SYNTAX_NOT_SUPPORTED;
763 * It's only treated as bind time feature request, if the first
764 * transfer_syntax matches, all others are ignored.
766 is_feature = dcerpc_extract_bind_time_features(c->transfer_syntaxes[0],
767 &features);
768 if (!is_feature) {
769 continue;
772 if (ack_features != NULL) {
774 * Only one bind time feature context is allowed.
776 return dcesrv_bind_nak(call, 0);
778 ack_features = a;
780 a->result = DCERPC_BIND_ACK_RESULT_NEGOTIATE_ACK;
781 a->reason.negotiate = 0;
782 if (features & DCERPC_BIND_TIME_SECURITY_CONTEXT_MULTIPLEXING) {
783 /* not supported yet */
785 if (features & DCERPC_BIND_TIME_KEEP_CONNECTION_ON_ORPHAN) {
786 a->reason.negotiate |=
787 DCERPC_BIND_TIME_KEEP_CONNECTION_ON_ORPHAN;
790 call->conn->bind_time_features = a->reason.negotiate;
794 * Try to negotiate one new presentation context.
796 * Deep in here we locate the iface (by uuid) that the client
797 * requested, from the list of interfaces on the
798 * call->conn->endpoint, and call iface->bind() on that iface.
800 * call->conn was set up at the accept() of the socket, and
801 * call->conn->endpoint has a list of interfaces restricted to
802 * this port or pipe.
804 status = dcesrv_negotiate_contexts(call, &call->pkt.u.bind, ack_ctx_list);
805 if (NT_STATUS_EQUAL(status, NT_STATUS_RPC_PROTOCOL_ERROR)) {
806 return dcesrv_bind_nak(call, 0);
808 if (!NT_STATUS_IS_OK(status)) {
809 return status;
813 * At this point we know which interface (eg netlogon, lsa,
814 * drsuapi) the caller requested. This is available on
815 * call->conntext->iface.
818 if ((call->pkt.pfc_flags & DCERPC_PFC_FLAG_CONC_MPX) &&
819 (call->state_flags & DCESRV_CALL_STATE_FLAG_MULTIPLEXED)) {
820 call->conn->state_flags |= DCESRV_CALL_STATE_FLAG_MULTIPLEXED;
821 extra_flags |= DCERPC_PFC_FLAG_CONC_MPX;
824 if (call->state_flags & DCESRV_CALL_STATE_FLAG_PROCESS_PENDING_CALL) {
825 call->conn->state_flags |= DCESRV_CALL_STATE_FLAG_PROCESS_PENDING_CALL;
829 * After finding the interface and setting up the NDR
830 * transport negotiation etc, handle any authentication that
831 * is being requested.
833 if (!dcesrv_auth_bind(call)) {
834 struct dcesrv_auth *auth = &call->conn->auth_state;
836 TALLOC_FREE(call->context);
838 if (auth->auth_level == DCERPC_AUTH_LEVEL_NONE) {
840 * With DCERPC_AUTH_LEVEL_NONE, we get the
841 * reject_reason in auth->auth_context_id.
843 return dcesrv_bind_nak(call, auth->auth_context_id);
847 * This must a be a temporary failure e.g. talloc or invalid
848 * configuration, e.g. no machine account.
850 return dcesrv_bind_nak(call,
851 DCERPC_BIND_NAK_REASON_TEMPORARY_CONGESTION);
854 /* setup a bind_ack */
855 dcesrv_init_hdr(&pkt, lpcfg_rpc_big_endian(call->conn->dce_ctx->lp_ctx));
856 pkt.auth_length = 0;
857 pkt.call_id = call->pkt.call_id;
858 pkt.ptype = DCERPC_PKT_BIND_ACK;
859 pkt.pfc_flags = DCERPC_PFC_FLAG_FIRST | DCERPC_PFC_FLAG_LAST | extra_flags;
860 pkt.u.bind_ack.max_xmit_frag = call->conn->max_xmit_frag;
861 pkt.u.bind_ack.max_recv_frag = call->conn->max_recv_frag;
862 pkt.u.bind_ack.assoc_group_id = call->conn->assoc_group->id;
864 endpoint = dcerpc_binding_get_string_option(
865 call->conn->endpoint->ep_description,
866 "endpoint");
867 if (endpoint == NULL) {
868 endpoint = "";
871 if (strncasecmp(endpoint, "\\pipe\\", 6) == 0) {
873 * TODO: check if this is really needed
875 * Or if we should fix this in our idl files.
877 ep_prefix = "\\PIPE\\";
878 endpoint += 6;
881 pkt.u.bind_ack.secondary_address = talloc_asprintf(call, "%s%s",
882 ep_prefix,
883 endpoint);
884 if (pkt.u.bind_ack.secondary_address == NULL) {
885 TALLOC_FREE(call->context);
886 return NT_STATUS_NO_MEMORY;
888 pkt.u.bind_ack.num_results = call->pkt.u.bind.num_contexts;
889 pkt.u.bind_ack.ctx_list = ack_ctx_list;
890 pkt.u.bind_ack.auth_info = data_blob_null;
892 status = dcesrv_auth_bind_ack(call, &pkt);
893 if (!NT_STATUS_IS_OK(status)) {
894 TALLOC_FREE(call->context);
895 return dcesrv_bind_nak(call, 0);
898 rep = talloc_zero(call, struct data_blob_list_item);
899 if (!rep) {
900 TALLOC_FREE(call->context);
901 return NT_STATUS_NO_MEMORY;
904 status = ncacn_push_auth(&rep->blob, call, &pkt,
905 call->out_auth_info);
906 if (!NT_STATUS_IS_OK(status)) {
907 TALLOC_FREE(call->context);
908 return status;
911 dcerpc_set_frag_length(&rep->blob, rep->blob.length);
913 DLIST_ADD_END(call->replies, rep);
914 dcesrv_call_set_list(call, DCESRV_LIST_CALL_LIST);
916 if (call->conn->call_list && call->conn->call_list->replies) {
917 if (call->conn->transport.report_output_data) {
918 call->conn->transport.report_output_data(call->conn);
922 return NT_STATUS_OK;
927 handle a auth3 request
929 static NTSTATUS dcesrv_auth3(struct dcesrv_call_state *call)
931 NTSTATUS status;
933 if (!call->conn->allow_auth3) {
934 return dcesrv_fault_disconnect(call, DCERPC_NCA_S_PROTO_ERROR);
937 if (call->conn->auth_state.auth_finished) {
938 return dcesrv_fault_disconnect(call, DCERPC_NCA_S_PROTO_ERROR);
941 status = dcerpc_verify_ncacn_packet_header(&call->pkt,
942 DCERPC_PKT_AUTH3,
943 call->pkt.u.auth3.auth_info.length,
944 0, /* required flags */
945 DCERPC_PFC_FLAG_FIRST |
946 DCERPC_PFC_FLAG_LAST |
947 DCERPC_PFC_FLAG_SUPPORT_HEADER_SIGN |
948 0x08 | /* this is not defined, but should be ignored */
949 DCERPC_PFC_FLAG_CONC_MPX |
950 DCERPC_PFC_FLAG_DID_NOT_EXECUTE |
951 DCERPC_PFC_FLAG_MAYBE |
952 DCERPC_PFC_FLAG_OBJECT_UUID);
953 if (!NT_STATUS_IS_OK(status)) {
954 return dcesrv_fault_disconnect(call, DCERPC_NCA_S_PROTO_ERROR);
957 /* handle the auth3 in the auth code */
958 if (!dcesrv_auth_auth3(call)) {
959 call->conn->auth_state.auth_invalid = true;
960 if (call->fault_code != 0) {
961 return dcesrv_fault_disconnect(call, call->fault_code);
965 talloc_free(call);
967 /* we don't send a reply to a auth3 request, except by a
968 fault */
969 return NT_STATUS_OK;
973 static NTSTATUS dcesrv_check_or_create_context(struct dcesrv_call_state *call,
974 const struct dcerpc_bind *b,
975 const struct dcerpc_ctx_list *ctx,
976 struct dcerpc_ack_ctx *ack,
977 bool validate_only,
978 const struct ndr_syntax_id *supported_transfer)
980 uint32_t if_version;
981 struct dcesrv_connection_context *context;
982 const struct dcesrv_interface *iface;
983 struct GUID uuid;
984 NTSTATUS status;
985 const struct ndr_syntax_id *selected_transfer = NULL;
986 size_t i;
987 bool ok;
989 if (b == NULL) {
990 return NT_STATUS_INTERNAL_ERROR;
992 if (ctx == NULL) {
993 return NT_STATUS_INTERNAL_ERROR;
995 if (ctx->num_transfer_syntaxes < 1) {
996 return NT_STATUS_INTERNAL_ERROR;
998 if (ack == NULL) {
999 return NT_STATUS_INTERNAL_ERROR;
1001 if (supported_transfer == NULL) {
1002 return NT_STATUS_INTERNAL_ERROR;
1005 switch (ack->result) {
1006 case DCERPC_BIND_ACK_RESULT_ACCEPTANCE:
1007 case DCERPC_BIND_ACK_RESULT_NEGOTIATE_ACK:
1009 * We is already completed.
1011 return NT_STATUS_OK;
1012 default:
1013 break;
1016 ack->result = DCERPC_BIND_ACK_RESULT_PROVIDER_REJECTION;
1017 ack->reason.value = DCERPC_BIND_ACK_REASON_ABSTRACT_SYNTAX_NOT_SUPPORTED;
1019 if_version = ctx->abstract_syntax.if_version;
1020 uuid = ctx->abstract_syntax.uuid;
1022 iface = find_interface_by_uuid(call->conn->endpoint, &uuid, if_version);
1023 if (iface == NULL) {
1024 char *uuid_str = GUID_string(call, &uuid);
1025 DEBUG(2,("Request for unknown dcerpc interface %s/%d\n", uuid_str, if_version));
1026 talloc_free(uuid_str);
1028 * We report this only via ack->result
1030 return NT_STATUS_OK;
1033 ack->result = DCERPC_BIND_ACK_RESULT_PROVIDER_REJECTION;
1034 ack->reason.value = DCERPC_BIND_ACK_REASON_TRANSFER_SYNTAXES_NOT_SUPPORTED;
1036 if (validate_only) {
1038 * We report this only via ack->result
1040 return NT_STATUS_OK;
1043 for (i = 0; i < ctx->num_transfer_syntaxes; i++) {
1045 * we only do NDR encoded dcerpc for now.
1047 ok = ndr_syntax_id_equal(&ctx->transfer_syntaxes[i],
1048 supported_transfer);
1049 if (ok) {
1050 selected_transfer = supported_transfer;
1051 break;
1055 context = dcesrv_find_context(call->conn, ctx->context_id);
1056 if (context != NULL) {
1057 ok = ndr_syntax_id_equal(&context->iface->syntax_id,
1058 &ctx->abstract_syntax);
1059 if (!ok) {
1060 return NT_STATUS_RPC_PROTOCOL_ERROR;
1063 if (selected_transfer != NULL) {
1064 ok = ndr_syntax_id_equal(&context->transfer_syntax,
1065 selected_transfer);
1066 if (!ok) {
1067 return NT_STATUS_RPC_PROTOCOL_ERROR;
1070 ack->result = DCERPC_BIND_ACK_RESULT_ACCEPTANCE;
1071 ack->reason.value = DCERPC_BIND_ACK_REASON_NOT_SPECIFIED;
1072 ack->syntax = context->transfer_syntax;
1076 * We report this only via ack->result
1078 return NT_STATUS_OK;
1081 if (selected_transfer == NULL) {
1083 * We report this only via ack->result
1085 return NT_STATUS_OK;
1088 ack->result = DCERPC_BIND_ACK_RESULT_USER_REJECTION;
1089 ack->reason.value = DCERPC_BIND_ACK_REASON_LOCAL_LIMIT_EXCEEDED;
1091 /* add this context to the list of available context_ids */
1092 context = talloc_zero(call->conn, struct dcesrv_connection_context);
1093 if (context == NULL) {
1094 return NT_STATUS_NO_MEMORY;
1096 context->conn = call->conn;
1097 context->context_id = ctx->context_id;
1098 context->iface = iface;
1099 context->transfer_syntax = *selected_transfer;
1100 context->private_data = NULL;
1101 DLIST_ADD(call->conn->contexts, context);
1102 call->context = context;
1103 talloc_set_destructor(context, dcesrv_connection_context_destructor);
1105 dcesrv_prepare_context_auth(call);
1108 * Multiplex is supported by default
1110 call->state_flags |= DCESRV_CALL_STATE_FLAG_MULTIPLEXED;
1112 status = iface->bind(call, iface, if_version);
1113 call->context = NULL;
1114 if (!NT_STATUS_IS_OK(status)) {
1115 /* we don't want to trigger the iface->unbind() hook */
1116 context->iface = NULL;
1117 talloc_free(context);
1119 * We report this only via ack->result
1121 return NT_STATUS_OK;
1124 ack->result = DCERPC_BIND_ACK_RESULT_ACCEPTANCE;
1125 ack->reason.value = DCERPC_BIND_ACK_REASON_NOT_SPECIFIED;
1126 ack->syntax = context->transfer_syntax;
1127 return NT_STATUS_OK;
1130 static NTSTATUS dcesrv_negotiate_contexts(struct dcesrv_call_state *call,
1131 const struct dcerpc_bind *b,
1132 struct dcerpc_ack_ctx *ack_ctx_list)
1134 NTSTATUS status;
1135 size_t i;
1136 bool validate_only = false;
1137 bool preferred_ndr32;
1140 * Try to negotiate one new presentation context,
1141 * using our preferred transfer syntax.
1143 for (i = 0; i < b->num_contexts; i++) {
1144 const struct dcerpc_ctx_list *c = &b->ctx_list[i];
1145 struct dcerpc_ack_ctx *a = &ack_ctx_list[i];
1147 status = dcesrv_check_or_create_context(call, b, c, a,
1148 validate_only,
1149 call->conn->preferred_transfer);
1150 if (!NT_STATUS_IS_OK(status)) {
1151 return status;
1154 if (a->result == DCERPC_BIND_ACK_RESULT_ACCEPTANCE) {
1156 * We managed to negotiate one context.
1158 * => we're done.
1160 validate_only = true;
1164 preferred_ndr32 = ndr_syntax_id_equal(&ndr_transfer_syntax_ndr,
1165 call->conn->preferred_transfer);
1166 if (preferred_ndr32) {
1168 * We're done.
1170 return NT_STATUS_OK;
1174 * Try to negotiate one new presentation context,
1175 * using NDR 32 as fallback.
1177 for (i = 0; i < b->num_contexts; i++) {
1178 const struct dcerpc_ctx_list *c = &b->ctx_list[i];
1179 struct dcerpc_ack_ctx *a = &ack_ctx_list[i];
1181 status = dcesrv_check_or_create_context(call, b, c, a,
1182 validate_only,
1183 &ndr_transfer_syntax_ndr);
1184 if (!NT_STATUS_IS_OK(status)) {
1185 return status;
1188 if (a->result == DCERPC_BIND_ACK_RESULT_ACCEPTANCE) {
1190 * We managed to negotiate one context.
1192 * => we're done.
1194 validate_only = true;
1198 return NT_STATUS_OK;
1202 handle a alter context request
1204 static NTSTATUS dcesrv_alter(struct dcesrv_call_state *call)
1206 NTSTATUS status;
1207 bool auth_ok = false;
1208 struct ncacn_packet pkt;
1209 uint32_t extra_flags = 0;
1210 struct data_blob_list_item *rep = NULL;
1211 struct dcerpc_ack_ctx *ack_ctx_list = NULL;
1212 size_t i;
1214 if (!call->conn->allow_alter) {
1215 return dcesrv_fault_disconnect(call, DCERPC_NCA_S_PROTO_ERROR);
1218 status = dcerpc_verify_ncacn_packet_header(&call->pkt,
1219 DCERPC_PKT_ALTER,
1220 call->pkt.u.alter.auth_info.length,
1221 0, /* required flags */
1222 DCERPC_PFC_FLAG_FIRST |
1223 DCERPC_PFC_FLAG_LAST |
1224 DCERPC_PFC_FLAG_SUPPORT_HEADER_SIGN |
1225 0x08 | /* this is not defined, but should be ignored */
1226 DCERPC_PFC_FLAG_CONC_MPX |
1227 DCERPC_PFC_FLAG_DID_NOT_EXECUTE |
1228 DCERPC_PFC_FLAG_MAYBE |
1229 DCERPC_PFC_FLAG_OBJECT_UUID);
1230 if (!NT_STATUS_IS_OK(status)) {
1231 return dcesrv_fault_disconnect(call, DCERPC_NCA_S_PROTO_ERROR);
1234 auth_ok = dcesrv_auth_alter(call);
1235 if (!auth_ok) {
1236 if (call->fault_code != 0) {
1237 return dcesrv_fault_disconnect(call, call->fault_code);
1241 if (call->pkt.u.alter.num_contexts < 1) {
1242 return dcesrv_fault_disconnect(call, DCERPC_NCA_S_PROTO_ERROR);
1245 ack_ctx_list = talloc_zero_array(call, struct dcerpc_ack_ctx,
1246 call->pkt.u.alter.num_contexts);
1247 if (ack_ctx_list == NULL) {
1248 return NT_STATUS_NO_MEMORY;
1252 * Set some sane defaults (required by dcesrv_negotiate_contexts()/
1253 * dcesrv_check_or_create_context()) and do some protocol validation
1254 * and set sane defaults.
1256 for (i = 0; i < call->pkt.u.alter.num_contexts; i++) {
1257 const struct dcerpc_ctx_list *c = &call->pkt.u.alter.ctx_list[i];
1258 struct dcerpc_ack_ctx *a = &ack_ctx_list[i];
1260 if (c->num_transfer_syntaxes == 0) {
1261 return dcesrv_fault_disconnect(call,
1262 DCERPC_NCA_S_PROTO_ERROR);
1265 a->result = DCERPC_BIND_ACK_RESULT_PROVIDER_REJECTION;
1266 a->reason.value = DCERPC_BIND_ACK_REASON_ABSTRACT_SYNTAX_NOT_SUPPORTED;
1270 * Try to negotiate one new presentation context.
1272 status = dcesrv_negotiate_contexts(call, &call->pkt.u.alter, ack_ctx_list);
1273 if (NT_STATUS_EQUAL(status, NT_STATUS_RPC_PROTOCOL_ERROR)) {
1274 return dcesrv_fault_disconnect(call, DCERPC_NCA_S_PROTO_ERROR);
1276 if (!NT_STATUS_IS_OK(status)) {
1277 return status;
1280 if ((call->pkt.pfc_flags & DCERPC_PFC_FLAG_CONC_MPX) &&
1281 (call->state_flags & DCESRV_CALL_STATE_FLAG_MULTIPLEXED)) {
1282 call->conn->state_flags |= DCESRV_CALL_STATE_FLAG_MULTIPLEXED;
1283 extra_flags |= DCERPC_PFC_FLAG_CONC_MPX;
1286 if (call->state_flags & DCESRV_CALL_STATE_FLAG_PROCESS_PENDING_CALL) {
1287 call->conn->state_flags |= DCESRV_CALL_STATE_FLAG_PROCESS_PENDING_CALL;
1290 /* handle any authentication that is being requested */
1291 if (!auth_ok) {
1292 if (call->in_auth_info.auth_type !=
1293 call->conn->auth_state.auth_type)
1295 return dcesrv_fault_disconnect(call,
1296 DCERPC_FAULT_SEC_PKG_ERROR);
1298 return dcesrv_fault_disconnect(call, DCERPC_FAULT_ACCESS_DENIED);
1301 dcesrv_init_hdr(&pkt, lpcfg_rpc_big_endian(call->conn->dce_ctx->lp_ctx));
1302 pkt.auth_length = 0;
1303 pkt.call_id = call->pkt.call_id;
1304 pkt.ptype = DCERPC_PKT_ALTER_RESP;
1305 pkt.pfc_flags = DCERPC_PFC_FLAG_FIRST | DCERPC_PFC_FLAG_LAST | extra_flags;
1306 pkt.u.alter_resp.max_xmit_frag = call->conn->max_xmit_frag;
1307 pkt.u.alter_resp.max_recv_frag = call->conn->max_recv_frag;
1308 pkt.u.alter_resp.assoc_group_id = call->conn->assoc_group->id;
1309 pkt.u.alter_resp.secondary_address = "";
1310 pkt.u.alter_resp.num_results = call->pkt.u.alter.num_contexts;
1311 pkt.u.alter_resp.ctx_list = ack_ctx_list;
1312 pkt.u.alter_resp.auth_info = data_blob_null;
1314 status = dcesrv_auth_alter_ack(call, &pkt);
1315 if (!NT_STATUS_IS_OK(status)) {
1316 return dcesrv_fault_disconnect(call, DCERPC_FAULT_SEC_PKG_ERROR);
1319 rep = talloc_zero(call, struct data_blob_list_item);
1320 if (!rep) {
1321 return NT_STATUS_NO_MEMORY;
1324 status = ncacn_push_auth(&rep->blob, call, &pkt, call->out_auth_info);
1325 if (!NT_STATUS_IS_OK(status)) {
1326 return status;
1329 dcerpc_set_frag_length(&rep->blob, rep->blob.length);
1331 DLIST_ADD_END(call->replies, rep);
1332 dcesrv_call_set_list(call, DCESRV_LIST_CALL_LIST);
1334 if (call->conn->call_list && call->conn->call_list->replies) {
1335 if (call->conn->transport.report_output_data) {
1336 call->conn->transport.report_output_data(call->conn);
1340 return NT_STATUS_OK;
1344 possibly save the call for inspection with ndrdump
1346 static void dcesrv_save_call(struct dcesrv_call_state *call, const char *why)
1348 #ifdef DEVELOPER
1349 char *fname;
1350 const char *dump_dir;
1351 dump_dir = lpcfg_parm_string(call->conn->dce_ctx->lp_ctx, NULL, "dcesrv", "stubs directory");
1352 if (!dump_dir) {
1353 return;
1355 fname = talloc_asprintf(call, "%s/RPC-%s-%u-%s.dat",
1356 dump_dir,
1357 call->context->iface->name,
1358 call->pkt.u.request.opnum,
1359 why);
1360 if (file_save(fname, call->pkt.u.request.stub_and_verifier.data, call->pkt.u.request.stub_and_verifier.length)) {
1361 DEBUG(0,("RPC SAVED %s\n", fname));
1363 talloc_free(fname);
1364 #endif
1367 static NTSTATUS dcesrv_check_verification_trailer(struct dcesrv_call_state *call)
1369 TALLOC_CTX *frame = talloc_stackframe();
1370 const uint32_t bitmask1 = call->conn->auth_state.client_hdr_signing ?
1371 DCERPC_SEC_VT_CLIENT_SUPPORTS_HEADER_SIGNING : 0;
1372 const struct dcerpc_sec_vt_pcontext pcontext = {
1373 .abstract_syntax = call->context->iface->syntax_id,
1374 .transfer_syntax = call->context->transfer_syntax,
1376 const struct dcerpc_sec_vt_header2 header2 =
1377 dcerpc_sec_vt_header2_from_ncacn_packet(&call->pkt);
1378 enum ndr_err_code ndr_err;
1379 struct dcerpc_sec_verification_trailer *vt = NULL;
1380 NTSTATUS status = NT_STATUS_OK;
1381 bool ok;
1383 SMB_ASSERT(call->pkt.ptype == DCERPC_PKT_REQUEST);
1385 ndr_err = ndr_pop_dcerpc_sec_verification_trailer(call->ndr_pull,
1386 frame, &vt);
1387 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
1388 status = ndr_map_error2ntstatus(ndr_err);
1389 goto done;
1392 ok = dcerpc_sec_verification_trailer_check(vt, &bitmask1,
1393 &pcontext, &header2);
1394 if (!ok) {
1395 status = NT_STATUS_ACCESS_DENIED;
1396 goto done;
1398 done:
1399 TALLOC_FREE(frame);
1400 return status;
1404 handle a dcerpc request packet
1406 static NTSTATUS dcesrv_request(struct dcesrv_call_state *call)
1408 const struct dcesrv_endpoint *endpoint = call->conn->endpoint;
1409 enum dcerpc_transport_t transport =
1410 dcerpc_binding_get_transport(endpoint->ep_description);
1411 struct ndr_pull *pull;
1412 NTSTATUS status;
1414 if (!call->conn->allow_request) {
1415 return dcesrv_fault_disconnect(call, DCERPC_NCA_S_PROTO_ERROR);
1418 /* if authenticated, and the mech we use can't do async replies, don't use them... */
1419 if (call->conn->auth_state.gensec_security &&
1420 !gensec_have_feature(call->conn->auth_state.gensec_security, GENSEC_FEATURE_ASYNC_REPLIES)) {
1421 call->state_flags &= ~DCESRV_CALL_STATE_FLAG_MAY_ASYNC;
1424 if (call->context == NULL) {
1425 return dcesrv_fault_with_flags(call, DCERPC_NCA_S_UNKNOWN_IF,
1426 DCERPC_PFC_FLAG_DID_NOT_EXECUTE);
1429 switch (call->conn->auth_state.auth_level) {
1430 case DCERPC_AUTH_LEVEL_NONE:
1431 case DCERPC_AUTH_LEVEL_PACKET:
1432 case DCERPC_AUTH_LEVEL_INTEGRITY:
1433 case DCERPC_AUTH_LEVEL_PRIVACY:
1434 break;
1435 default:
1436 if (!call->context->allow_connect) {
1437 char *addr;
1439 addr = tsocket_address_string(call->conn->remote_address,
1440 call);
1442 DEBUG(2, ("%s: restrict auth_level_connect access "
1443 "to [%s] with auth[type=0x%x,level=0x%x] "
1444 "on [%s] from [%s]\n",
1445 __func__, call->context->iface->name,
1446 call->conn->auth_state.auth_type,
1447 call->conn->auth_state.auth_level,
1448 derpc_transport_string_by_transport(transport),
1449 addr));
1450 return dcesrv_fault(call, DCERPC_FAULT_ACCESS_DENIED);
1452 break;
1455 if (call->conn->auth_state.auth_level < call->context->min_auth_level) {
1456 char *addr;
1458 addr = tsocket_address_string(call->conn->remote_address, call);
1460 DEBUG(2, ("%s: restrict access by min_auth_level[0x%x] "
1461 "to [%s] with auth[type=0x%x,level=0x%x] "
1462 "on [%s] from [%s]\n",
1463 __func__,
1464 call->context->min_auth_level,
1465 call->context->iface->name,
1466 call->conn->auth_state.auth_type,
1467 call->conn->auth_state.auth_level,
1468 derpc_transport_string_by_transport(transport),
1469 addr));
1470 return dcesrv_fault(call, DCERPC_FAULT_ACCESS_DENIED);
1473 pull = ndr_pull_init_blob(&call->pkt.u.request.stub_and_verifier, call);
1474 NT_STATUS_HAVE_NO_MEMORY(pull);
1476 pull->flags |= LIBNDR_FLAG_REF_ALLOC;
1478 call->ndr_pull = pull;
1480 if (!(call->pkt.drep[0] & DCERPC_DREP_LE)) {
1481 pull->flags |= LIBNDR_FLAG_BIGENDIAN;
1484 status = dcesrv_check_verification_trailer(call);
1485 if (!NT_STATUS_IS_OK(status)) {
1486 uint32_t faultcode = DCERPC_FAULT_OTHER;
1487 if (NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
1488 faultcode = DCERPC_FAULT_ACCESS_DENIED;
1490 DEBUG(10, ("dcesrv_check_verification_trailer failed: %s\n",
1491 nt_errstr(status)));
1492 return dcesrv_fault(call, faultcode);
1495 /* unravel the NDR for the packet */
1496 status = call->context->iface->ndr_pull(call, call, pull, &call->r);
1497 if (!NT_STATUS_IS_OK(status)) {
1498 uint8_t extra_flags = 0;
1499 if (call->fault_code == DCERPC_FAULT_OP_RNG_ERROR) {
1500 /* we got an unknown call */
1501 DEBUG(3,(__location__ ": Unknown RPC call %u on %s\n",
1502 call->pkt.u.request.opnum,
1503 call->context->iface->name));
1504 dcesrv_save_call(call, "unknown");
1505 extra_flags |= DCERPC_PFC_FLAG_DID_NOT_EXECUTE;
1506 } else {
1507 dcesrv_save_call(call, "pullfail");
1509 return dcesrv_fault_with_flags(call, call->fault_code, extra_flags);
1512 if (pull->offset != pull->data_size) {
1513 dcesrv_save_call(call, "extrabytes");
1514 DEBUG(3,("Warning: %d extra bytes in incoming RPC request\n",
1515 pull->data_size - pull->offset));
1518 /* call the dispatch function */
1519 status = call->context->iface->dispatch(call, call, call->r);
1520 if (!NT_STATUS_IS_OK(status)) {
1521 DEBUG(5,("dcerpc fault in call %s:%02x - %s\n",
1522 call->context->iface->name,
1523 call->pkt.u.request.opnum,
1524 dcerpc_errstr(pull, call->fault_code)));
1525 return dcesrv_fault(call, call->fault_code);
1528 /* add the call to the pending list */
1529 dcesrv_call_set_list(call, DCESRV_LIST_PENDING_CALL_LIST);
1531 if (call->state_flags & DCESRV_CALL_STATE_FLAG_ASYNC) {
1532 return NT_STATUS_OK;
1535 return dcesrv_reply(call);
1540 remove the call from the right list when freed
1542 static int dcesrv_call_dequeue(struct dcesrv_call_state *call)
1544 dcesrv_call_set_list(call, DCESRV_LIST_NONE);
1545 return 0;
1548 _PUBLIC_ const struct tsocket_address *dcesrv_connection_get_local_address(struct dcesrv_connection *conn)
1550 return conn->local_address;
1553 _PUBLIC_ const struct tsocket_address *dcesrv_connection_get_remote_address(struct dcesrv_connection *conn)
1555 return conn->remote_address;
1559 process some input to a dcerpc endpoint server.
1561 static NTSTATUS dcesrv_process_ncacn_packet(struct dcesrv_connection *dce_conn,
1562 struct ncacn_packet *pkt,
1563 DATA_BLOB blob)
1565 NTSTATUS status;
1566 struct dcesrv_call_state *call;
1567 struct dcesrv_call_state *existing = NULL;
1569 call = talloc_zero(dce_conn, struct dcesrv_call_state);
1570 if (!call) {
1571 data_blob_free(&blob);
1572 talloc_free(pkt);
1573 return NT_STATUS_NO_MEMORY;
1575 call->conn = dce_conn;
1576 call->event_ctx = dce_conn->event_ctx;
1577 call->msg_ctx = dce_conn->msg_ctx;
1578 call->state_flags = call->conn->state_flags;
1579 call->time = timeval_current();
1580 call->list = DCESRV_LIST_NONE;
1582 talloc_steal(call, pkt);
1583 talloc_steal(call, blob.data);
1584 call->pkt = *pkt;
1586 talloc_set_destructor(call, dcesrv_call_dequeue);
1588 if (call->conn->allow_bind) {
1590 * Only one bind is possible per connection
1592 call->conn->allow_bind = false;
1593 return dcesrv_bind(call);
1596 /* we have to check the signing here, before combining the
1597 pdus */
1598 if (call->pkt.ptype == DCERPC_PKT_REQUEST) {
1599 if (!call->conn->allow_request) {
1600 return dcesrv_fault_disconnect(call,
1601 DCERPC_NCA_S_PROTO_ERROR);
1604 status = dcerpc_verify_ncacn_packet_header(&call->pkt,
1605 DCERPC_PKT_REQUEST,
1606 call->pkt.u.request.stub_and_verifier.length,
1607 0, /* required_flags */
1608 DCERPC_PFC_FLAG_FIRST |
1609 DCERPC_PFC_FLAG_LAST |
1610 DCERPC_PFC_FLAG_PENDING_CANCEL |
1611 0x08 | /* this is not defined, but should be ignored */
1612 DCERPC_PFC_FLAG_CONC_MPX |
1613 DCERPC_PFC_FLAG_DID_NOT_EXECUTE |
1614 DCERPC_PFC_FLAG_MAYBE |
1615 DCERPC_PFC_FLAG_OBJECT_UUID);
1616 if (!NT_STATUS_IS_OK(status)) {
1617 return dcesrv_fault_disconnect(call,
1618 DCERPC_NCA_S_PROTO_ERROR);
1621 if (call->pkt.frag_length > DCERPC_FRAG_MAX_SIZE) {
1623 * We don't use dcesrv_fault_disconnect()
1624 * here, because we don't want to set
1625 * DCERPC_PFC_FLAG_DID_NOT_EXECUTE
1627 * Note that we don't check against the negotiated
1628 * max_recv_frag, but a hard coded value.
1630 dcesrv_call_disconnect_after(call,
1631 "dcesrv_auth_request - frag_length too large");
1632 return dcesrv_fault(call,
1633 DCERPC_NCA_S_PROTO_ERROR);
1636 if (call->pkt.pfc_flags & DCERPC_PFC_FLAG_FIRST) {
1637 if (dce_conn->pending_call_list != NULL) {
1639 * concurrent requests are only allowed
1640 * if DCERPC_PFC_FLAG_CONC_MPX was negotiated.
1642 if (!(dce_conn->state_flags & DCESRV_CALL_STATE_FLAG_MULTIPLEXED)) {
1643 dcesrv_call_disconnect_after(call,
1644 "dcesrv_auth_request - "
1645 "existing pending call without CONN_MPX");
1646 return dcesrv_fault(call,
1647 DCERPC_NCA_S_PROTO_ERROR);
1650 /* only one request is possible in the fragmented list */
1651 if (dce_conn->incoming_fragmented_call_list != NULL) {
1652 if (!(dce_conn->state_flags & DCESRV_CALL_STATE_FLAG_MULTIPLEXED)) {
1654 * Without DCERPC_PFC_FLAG_CONC_MPX
1655 * we need to return the FAULT on the
1656 * already existing call.
1658 * This is important to get the
1659 * call_id and context_id right.
1661 TALLOC_FREE(call);
1662 call = dce_conn->incoming_fragmented_call_list;
1664 dcesrv_call_disconnect_after(call,
1665 "dcesrv_auth_request - "
1666 "existing fragmented call");
1667 return dcesrv_fault(call,
1668 DCERPC_NCA_S_PROTO_ERROR);
1670 if (call->pkt.pfc_flags & DCERPC_PFC_FLAG_PENDING_CANCEL) {
1671 return dcesrv_fault_disconnect(call,
1672 DCERPC_FAULT_NO_CALL_ACTIVE);
1674 call->context = dcesrv_find_context(call->conn,
1675 call->pkt.u.request.context_id);
1676 if (call->context == NULL) {
1677 return dcesrv_fault_with_flags(call, DCERPC_NCA_S_UNKNOWN_IF,
1678 DCERPC_PFC_FLAG_DID_NOT_EXECUTE);
1680 } else {
1681 const struct dcerpc_request *nr = &call->pkt.u.request;
1682 const struct dcerpc_request *er = NULL;
1683 int cmp;
1685 existing = dcesrv_find_fragmented_call(dce_conn,
1686 call->pkt.call_id);
1687 if (existing == NULL) {
1688 dcesrv_call_disconnect_after(call,
1689 "dcesrv_auth_request - "
1690 "no existing fragmented call");
1691 return dcesrv_fault(call,
1692 DCERPC_NCA_S_PROTO_ERROR);
1694 er = &existing->pkt.u.request;
1696 if (call->pkt.ptype != existing->pkt.ptype) {
1697 /* trying to play silly buggers are we? */
1698 return dcesrv_fault_disconnect(existing,
1699 DCERPC_NCA_S_PROTO_ERROR);
1701 cmp = memcmp(call->pkt.drep, existing->pkt.drep,
1702 sizeof(pkt->drep));
1703 if (cmp != 0) {
1704 return dcesrv_fault_disconnect(existing,
1705 DCERPC_NCA_S_PROTO_ERROR);
1707 if (nr->context_id != er->context_id) {
1708 return dcesrv_fault_disconnect(existing,
1709 DCERPC_NCA_S_PROTO_ERROR);
1711 if (nr->opnum != er->opnum) {
1712 return dcesrv_fault_disconnect(existing,
1713 DCERPC_NCA_S_PROTO_ERROR);
1718 if (call->pkt.ptype == DCERPC_PKT_REQUEST) {
1719 bool ok;
1720 uint8_t payload_offset = DCERPC_REQUEST_LENGTH;
1722 if (call->pkt.pfc_flags & DCERPC_PFC_FLAG_OBJECT_UUID) {
1723 payload_offset += 16;
1726 ok = dcesrv_auth_pkt_pull(call, &blob,
1727 0, /* required_flags */
1728 DCERPC_PFC_FLAG_FIRST |
1729 DCERPC_PFC_FLAG_LAST |
1730 DCERPC_PFC_FLAG_PENDING_CANCEL |
1731 0x08 | /* this is not defined, but should be ignored */
1732 DCERPC_PFC_FLAG_CONC_MPX |
1733 DCERPC_PFC_FLAG_DID_NOT_EXECUTE |
1734 DCERPC_PFC_FLAG_MAYBE |
1735 DCERPC_PFC_FLAG_OBJECT_UUID,
1736 payload_offset,
1737 &call->pkt.u.request.stub_and_verifier);
1738 if (!ok) {
1740 * We don't use dcesrv_fault_disconnect()
1741 * here, because we don't want to set
1742 * DCERPC_PFC_FLAG_DID_NOT_EXECUTE
1744 dcesrv_call_disconnect_after(call,
1745 "dcesrv_auth_request - failed");
1746 if (call->fault_code == 0) {
1747 call->fault_code = DCERPC_FAULT_ACCESS_DENIED;
1749 return dcesrv_fault(call, call->fault_code);
1753 /* see if this is a continued packet */
1754 if (existing != NULL) {
1755 struct dcerpc_request *er = &existing->pkt.u.request;
1756 const struct dcerpc_request *nr = &call->pkt.u.request;
1757 size_t available;
1758 size_t alloc_size;
1759 size_t alloc_hint;
1762 * Up to 4 MByte are allowed by all fragments
1764 available = dce_conn->max_total_request_size;
1765 if (er->stub_and_verifier.length > available) {
1766 dcesrv_call_disconnect_after(existing,
1767 "dcesrv_auth_request - existing payload too large");
1768 return dcesrv_fault(existing, DCERPC_FAULT_ACCESS_DENIED);
1770 available -= er->stub_and_verifier.length;
1771 if (nr->alloc_hint > available) {
1772 dcesrv_call_disconnect_after(existing,
1773 "dcesrv_auth_request - alloc hint too large");
1774 return dcesrv_fault(existing, DCERPC_FAULT_ACCESS_DENIED);
1776 if (nr->stub_and_verifier.length > available) {
1777 dcesrv_call_disconnect_after(existing,
1778 "dcesrv_auth_request - new payload too large");
1779 return dcesrv_fault(existing, DCERPC_FAULT_ACCESS_DENIED);
1781 alloc_hint = er->stub_and_verifier.length + nr->alloc_hint;
1782 /* allocate at least 1 byte */
1783 alloc_hint = MAX(alloc_hint, 1);
1784 alloc_size = er->stub_and_verifier.length +
1785 nr->stub_and_verifier.length;
1786 alloc_size = MAX(alloc_size, alloc_hint);
1788 er->stub_and_verifier.data =
1789 talloc_realloc(existing,
1790 er->stub_and_verifier.data,
1791 uint8_t, alloc_size);
1792 if (er->stub_and_verifier.data == NULL) {
1793 TALLOC_FREE(call);
1794 return dcesrv_fault_with_flags(existing,
1795 DCERPC_FAULT_OUT_OF_RESOURCES,
1796 DCERPC_PFC_FLAG_DID_NOT_EXECUTE);
1798 memcpy(er->stub_and_verifier.data +
1799 er->stub_and_verifier.length,
1800 nr->stub_and_verifier.data,
1801 nr->stub_and_verifier.length);
1802 er->stub_and_verifier.length += nr->stub_and_verifier.length;
1804 existing->pkt.pfc_flags |= (call->pkt.pfc_flags & DCERPC_PFC_FLAG_LAST);
1806 TALLOC_FREE(call);
1807 call = existing;
1810 /* this may not be the last pdu in the chain - if its isn't then
1811 just put it on the incoming_fragmented_call_list and wait for the rest */
1812 if (call->pkt.ptype == DCERPC_PKT_REQUEST &&
1813 !(call->pkt.pfc_flags & DCERPC_PFC_FLAG_LAST)) {
1815 * Up to 4 MByte are allowed by all fragments
1817 if (call->pkt.u.request.alloc_hint > dce_conn->max_total_request_size) {
1818 dcesrv_call_disconnect_after(call,
1819 "dcesrv_auth_request - initial alloc hint too large");
1820 return dcesrv_fault(call, DCERPC_FAULT_ACCESS_DENIED);
1822 dcesrv_call_set_list(call, DCESRV_LIST_FRAGMENTED_CALL_LIST);
1823 return NT_STATUS_OK;
1826 /* This removes any fragments we may have had stashed away */
1827 dcesrv_call_set_list(call, DCESRV_LIST_NONE);
1829 switch (call->pkt.ptype) {
1830 case DCERPC_PKT_BIND:
1831 status = dcesrv_bind_nak(call,
1832 DCERPC_BIND_NAK_REASON_NOT_SPECIFIED);
1833 break;
1834 case DCERPC_PKT_AUTH3:
1835 status = dcesrv_auth3(call);
1836 break;
1837 case DCERPC_PKT_ALTER:
1838 status = dcesrv_alter(call);
1839 break;
1840 case DCERPC_PKT_REQUEST:
1841 status = dcesrv_request(call);
1842 break;
1843 case DCERPC_PKT_CO_CANCEL:
1844 case DCERPC_PKT_ORPHANED:
1846 * Window just ignores CO_CANCEL and ORPHANED,
1847 * so we do...
1849 status = NT_STATUS_OK;
1850 TALLOC_FREE(call);
1851 break;
1852 case DCERPC_PKT_BIND_ACK:
1853 case DCERPC_PKT_BIND_NAK:
1854 case DCERPC_PKT_ALTER_RESP:
1855 case DCERPC_PKT_RESPONSE:
1856 case DCERPC_PKT_FAULT:
1857 case DCERPC_PKT_SHUTDOWN:
1858 default:
1859 status = dcesrv_fault_disconnect(call, DCERPC_NCA_S_PROTO_ERROR);
1860 break;
1863 /* if we are going to be sending a reply then add
1864 it to the list of pending calls. We add it to the end to keep the call
1865 list in the order we will answer */
1866 if (!NT_STATUS_IS_OK(status)) {
1867 talloc_free(call);
1870 return status;
1873 _PUBLIC_ NTSTATUS dcesrv_init_context(TALLOC_CTX *mem_ctx,
1874 struct loadparm_context *lp_ctx,
1875 const char **endpoint_servers, struct dcesrv_context **_dce_ctx)
1877 NTSTATUS status;
1878 struct dcesrv_context *dce_ctx;
1879 int i;
1881 if (!endpoint_servers) {
1882 DEBUG(0,("dcesrv_init_context: no endpoint servers configured\n"));
1883 return NT_STATUS_INTERNAL_ERROR;
1886 dce_ctx = talloc_zero(mem_ctx, struct dcesrv_context);
1887 NT_STATUS_HAVE_NO_MEMORY(dce_ctx);
1889 if (uid_wrapper_enabled()) {
1890 setenv("UID_WRAPPER_MYUID", "1", 1);
1892 dce_ctx->initial_euid = geteuid();
1893 if (uid_wrapper_enabled()) {
1894 unsetenv("UID_WRAPPER_MYUID");
1897 dce_ctx->endpoint_list = NULL;
1898 dce_ctx->lp_ctx = lp_ctx;
1899 dce_ctx->assoc_groups_idr = idr_init(dce_ctx);
1900 NT_STATUS_HAVE_NO_MEMORY(dce_ctx->assoc_groups_idr);
1901 dce_ctx->broken_connections = NULL;
1903 for (i=0;endpoint_servers[i];i++) {
1904 const struct dcesrv_endpoint_server *ep_server;
1906 ep_server = dcesrv_ep_server_byname(endpoint_servers[i]);
1907 if (!ep_server) {
1908 DEBUG(0,("dcesrv_init_context: failed to find endpoint server = '%s'\n", endpoint_servers[i]));
1909 return NT_STATUS_INTERNAL_ERROR;
1912 status = ep_server->init_server(dce_ctx, ep_server);
1913 if (!NT_STATUS_IS_OK(status)) {
1914 DEBUG(0,("dcesrv_init_context: failed to init endpoint server = '%s': %s\n", endpoint_servers[i],
1915 nt_errstr(status)));
1916 return status;
1920 *_dce_ctx = dce_ctx;
1921 return NT_STATUS_OK;
1924 /* the list of currently registered DCERPC endpoint servers.
1926 static struct ep_server {
1927 struct dcesrv_endpoint_server *ep_server;
1928 } *ep_servers = NULL;
1929 static int num_ep_servers;
1932 register a DCERPC endpoint server.
1934 The 'name' can be later used by other backends to find the operations
1935 structure for this backend.
1938 _PUBLIC_ NTSTATUS dcerpc_register_ep_server(const struct dcesrv_endpoint_server *ep_server)
1941 if (dcesrv_ep_server_byname(ep_server->name) != NULL) {
1942 /* its already registered! */
1943 DEBUG(0,("DCERPC endpoint server '%s' already registered\n",
1944 ep_server->name));
1945 return NT_STATUS_OBJECT_NAME_COLLISION;
1948 ep_servers = realloc_p(ep_servers, struct ep_server, num_ep_servers+1);
1949 if (!ep_servers) {
1950 smb_panic("out of memory in dcerpc_register");
1953 ep_servers[num_ep_servers].ep_server = smb_xmemdup(ep_server, sizeof(*ep_server));
1954 ep_servers[num_ep_servers].ep_server->name = smb_xstrdup(ep_server->name);
1956 num_ep_servers++;
1958 DEBUG(3,("DCERPC endpoint server '%s' registered\n",
1959 ep_server->name));
1961 return NT_STATUS_OK;
1965 return the operations structure for a named backend of the specified type
1967 const struct dcesrv_endpoint_server *dcesrv_ep_server_byname(const char *name)
1969 int i;
1971 for (i=0;i<num_ep_servers;i++) {
1972 if (strcmp(ep_servers[i].ep_server->name, name) == 0) {
1973 return ep_servers[i].ep_server;
1977 return NULL;
1980 void dcerpc_server_init(struct loadparm_context *lp_ctx)
1982 static bool initialized;
1983 #define _MODULE_PROTO(init) extern NTSTATUS init(void);
1984 STATIC_dcerpc_server_MODULES_PROTO;
1985 init_module_fn static_init[] = { STATIC_dcerpc_server_MODULES };
1986 init_module_fn *shared_init;
1988 if (initialized) {
1989 return;
1991 initialized = true;
1993 shared_init = load_samba_modules(NULL, "dcerpc_server");
1995 run_init_functions(static_init);
1996 run_init_functions(shared_init);
1998 talloc_free(shared_init);
2002 return the DCERPC module version, and the size of some critical types
2003 This can be used by endpoint server modules to either detect compilation errors, or provide
2004 multiple implementations for different smbd compilation options in one module
2006 const struct dcesrv_critical_sizes *dcerpc_module_version(void)
2008 static const struct dcesrv_critical_sizes critical_sizes = {
2009 DCERPC_MODULE_VERSION,
2010 sizeof(struct dcesrv_context),
2011 sizeof(struct dcesrv_endpoint),
2012 sizeof(struct dcesrv_endpoint_server),
2013 sizeof(struct dcesrv_interface),
2014 sizeof(struct dcesrv_if_list),
2015 sizeof(struct dcesrv_connection),
2016 sizeof(struct dcesrv_call_state),
2017 sizeof(struct dcesrv_auth),
2018 sizeof(struct dcesrv_handle)
2021 return &critical_sizes;
2024 static void dcesrv_terminate_connection(struct dcesrv_connection *dce_conn, const char *reason)
2026 struct dcesrv_context *dce_ctx = dce_conn->dce_ctx;
2027 struct stream_connection *srv_conn;
2028 srv_conn = talloc_get_type(dce_conn->transport.private_data,
2029 struct stream_connection);
2031 dce_conn->allow_bind = false;
2032 dce_conn->allow_auth3 = false;
2033 dce_conn->allow_alter = false;
2034 dce_conn->allow_request = false;
2036 if (dce_conn->pending_call_list == NULL) {
2037 char *full_reason = talloc_asprintf(dce_conn, "dcesrv: %s", reason);
2039 DLIST_REMOVE(dce_ctx->broken_connections, dce_conn);
2040 stream_terminate_connection(srv_conn, full_reason ? full_reason : reason);
2041 return;
2044 if (dce_conn->terminate != NULL) {
2045 return;
2048 DEBUG(3,("dcesrv: terminating connection due to '%s' defered due to pending calls\n",
2049 reason));
2050 dce_conn->terminate = talloc_strdup(dce_conn, reason);
2051 if (dce_conn->terminate == NULL) {
2052 dce_conn->terminate = "dcesrv: defered terminating connection - no memory";
2054 DLIST_ADD_END(dce_ctx->broken_connections, dce_conn);
2057 static void dcesrv_cleanup_broken_connections(struct dcesrv_context *dce_ctx)
2059 struct dcesrv_connection *cur, *next;
2061 next = dce_ctx->broken_connections;
2062 while (next != NULL) {
2063 cur = next;
2064 next = cur->next;
2066 if (cur->state_flags & DCESRV_CALL_STATE_FLAG_PROCESS_PENDING_CALL) {
2067 struct dcesrv_connection_context *context_cur, *context_next;
2069 context_next = cur->contexts;
2070 while (context_next != NULL) {
2071 context_cur = context_next;
2072 context_next = context_cur->next;
2074 dcesrv_connection_context_destructor(context_cur);
2078 dcesrv_terminate_connection(cur, cur->terminate);
2082 /* We need this include to be able to compile on some plateforms
2083 * (ie. freebsd 7.2) as it seems that <sys/uio.h> is not included
2084 * correctly.
2085 * It has to be that deep because otherwise we have a conflict on
2086 * const struct dcesrv_interface declaration.
2087 * This is mostly due to socket_wrapper defining #define bind swrap_bind
2088 * which conflict with the bind used before.
2090 #include "system/network.h"
2092 struct dcesrv_sock_reply_state {
2093 struct dcesrv_connection *dce_conn;
2094 struct dcesrv_call_state *call;
2095 struct iovec iov;
2098 static void dcesrv_sock_reply_done(struct tevent_req *subreq);
2099 static void dcesrv_call_terminate_step1(struct tevent_req *subreq);
2101 static void dcesrv_sock_report_output_data(struct dcesrv_connection *dce_conn)
2103 struct dcesrv_call_state *call;
2105 call = dce_conn->call_list;
2106 if (!call || !call->replies) {
2107 return;
2110 while (call->replies) {
2111 struct data_blob_list_item *rep = call->replies;
2112 struct dcesrv_sock_reply_state *substate;
2113 struct tevent_req *subreq;
2115 substate = talloc_zero(call, struct dcesrv_sock_reply_state);
2116 if (!substate) {
2117 dcesrv_terminate_connection(dce_conn, "no memory");
2118 return;
2121 substate->dce_conn = dce_conn;
2122 substate->call = NULL;
2124 DLIST_REMOVE(call->replies, rep);
2126 if (call->replies == NULL && call->terminate_reason == NULL) {
2127 substate->call = call;
2130 substate->iov.iov_base = (void *) rep->blob.data;
2131 substate->iov.iov_len = rep->blob.length;
2133 subreq = tstream_writev_queue_send(substate,
2134 dce_conn->event_ctx,
2135 dce_conn->stream,
2136 dce_conn->send_queue,
2137 &substate->iov, 1);
2138 if (!subreq) {
2139 dcesrv_terminate_connection(dce_conn, "no memory");
2140 return;
2142 tevent_req_set_callback(subreq, dcesrv_sock_reply_done,
2143 substate);
2146 if (call->terminate_reason != NULL) {
2147 struct tevent_req *subreq;
2149 subreq = tevent_queue_wait_send(call,
2150 dce_conn->event_ctx,
2151 dce_conn->send_queue);
2152 if (!subreq) {
2153 dcesrv_terminate_connection(dce_conn, __location__);
2154 return;
2156 tevent_req_set_callback(subreq, dcesrv_call_terminate_step1,
2157 call);
2160 DLIST_REMOVE(call->conn->call_list, call);
2161 call->list = DCESRV_LIST_NONE;
2164 static void dcesrv_sock_reply_done(struct tevent_req *subreq)
2166 struct dcesrv_sock_reply_state *substate = tevent_req_callback_data(subreq,
2167 struct dcesrv_sock_reply_state);
2168 int ret;
2169 int sys_errno;
2170 NTSTATUS status;
2171 struct dcesrv_call_state *call = substate->call;
2173 ret = tstream_writev_queue_recv(subreq, &sys_errno);
2174 TALLOC_FREE(subreq);
2175 if (ret == -1) {
2176 status = map_nt_error_from_unix_common(sys_errno);
2177 dcesrv_terminate_connection(substate->dce_conn, nt_errstr(status));
2178 return;
2181 talloc_free(substate);
2182 if (call) {
2183 talloc_free(call);
2187 static void dcesrv_call_terminate_step2(struct tevent_req *subreq);
2189 static void dcesrv_call_terminate_step1(struct tevent_req *subreq)
2191 struct dcesrv_call_state *call = tevent_req_callback_data(subreq,
2192 struct dcesrv_call_state);
2193 bool ok;
2194 struct timeval tv;
2196 /* make sure we stop send queue before removing subreq */
2197 tevent_queue_stop(call->conn->send_queue);
2199 ok = tevent_queue_wait_recv(subreq);
2200 TALLOC_FREE(subreq);
2201 if (!ok) {
2202 dcesrv_terminate_connection(call->conn, __location__);
2203 return;
2206 /* disconnect after 200 usecs */
2207 tv = timeval_current_ofs_usec(200);
2208 subreq = tevent_wakeup_send(call, call->conn->event_ctx, tv);
2209 if (subreq == NULL) {
2210 dcesrv_terminate_connection(call->conn, __location__);
2211 return;
2213 tevent_req_set_callback(subreq, dcesrv_call_terminate_step2,
2214 call);
2217 static void dcesrv_call_terminate_step2(struct tevent_req *subreq)
2219 struct dcesrv_call_state *call = tevent_req_callback_data(subreq,
2220 struct dcesrv_call_state);
2221 bool ok;
2223 ok = tevent_wakeup_recv(subreq);
2224 TALLOC_FREE(subreq);
2225 if (!ok) {
2226 dcesrv_terminate_connection(call->conn, __location__);
2227 return;
2230 dcesrv_terminate_connection(call->conn, call->terminate_reason);
2233 struct dcesrv_socket_context {
2234 const struct dcesrv_endpoint *endpoint;
2235 struct dcesrv_context *dcesrv_ctx;
2239 static void dcesrv_read_fragment_done(struct tevent_req *subreq);
2241 static void dcesrv_sock_accept(struct stream_connection *srv_conn)
2243 NTSTATUS status;
2244 struct dcesrv_socket_context *dcesrv_sock =
2245 talloc_get_type(srv_conn->private_data, struct dcesrv_socket_context);
2246 enum dcerpc_transport_t transport =
2247 dcerpc_binding_get_transport(dcesrv_sock->endpoint->ep_description);
2248 struct dcesrv_connection *dcesrv_conn = NULL;
2249 int ret;
2250 struct tevent_req *subreq;
2251 struct loadparm_context *lp_ctx = dcesrv_sock->dcesrv_ctx->lp_ctx;
2253 dcesrv_cleanup_broken_connections(dcesrv_sock->dcesrv_ctx);
2255 if (!srv_conn->session_info) {
2256 status = auth_anonymous_session_info(srv_conn,
2257 lp_ctx,
2258 &srv_conn->session_info);
2259 if (!NT_STATUS_IS_OK(status)) {
2260 DEBUG(0,("dcesrv_sock_accept: auth_anonymous_session_info failed: %s\n",
2261 nt_errstr(status)));
2262 stream_terminate_connection(srv_conn, nt_errstr(status));
2263 return;
2268 * This fills in dcesrv_conn->endpoint with the endpoint
2269 * associated with the socket. From this point on we know
2270 * which (group of) services we are handling, but not the
2271 * specific interface.
2274 status = dcesrv_endpoint_connect(dcesrv_sock->dcesrv_ctx,
2275 srv_conn,
2276 dcesrv_sock->endpoint,
2277 srv_conn->session_info,
2278 srv_conn->event.ctx,
2279 srv_conn->msg_ctx,
2280 srv_conn->server_id,
2281 DCESRV_CALL_STATE_FLAG_MAY_ASYNC,
2282 &dcesrv_conn);
2283 if (!NT_STATUS_IS_OK(status)) {
2284 DEBUG(0,("dcesrv_sock_accept: dcesrv_endpoint_connect failed: %s\n",
2285 nt_errstr(status)));
2286 stream_terminate_connection(srv_conn, nt_errstr(status));
2287 return;
2290 dcesrv_conn->transport.private_data = srv_conn;
2291 dcesrv_conn->transport.report_output_data = dcesrv_sock_report_output_data;
2293 TALLOC_FREE(srv_conn->event.fde);
2295 dcesrv_conn->send_queue = tevent_queue_create(dcesrv_conn, "dcesrv send queue");
2296 if (!dcesrv_conn->send_queue) {
2297 status = NT_STATUS_NO_MEMORY;
2298 DEBUG(0,("dcesrv_sock_accept: tevent_queue_create(%s)\n",
2299 nt_errstr(status)));
2300 stream_terminate_connection(srv_conn, nt_errstr(status));
2301 return;
2304 if (transport == NCACN_NP) {
2305 dcesrv_conn->auth_state.session_key = dcesrv_inherited_session_key;
2306 dcesrv_conn->stream = talloc_move(dcesrv_conn,
2307 &srv_conn->tstream);
2308 } else {
2309 ret = tstream_bsd_existing_socket(dcesrv_conn,
2310 socket_get_fd(srv_conn->socket),
2311 &dcesrv_conn->stream);
2312 if (ret == -1) {
2313 status = map_nt_error_from_unix_common(errno);
2314 DEBUG(0, ("dcesrv_sock_accept: "
2315 "failed to setup tstream: %s\n",
2316 nt_errstr(status)));
2317 stream_terminate_connection(srv_conn, nt_errstr(status));
2318 return;
2320 socket_set_flags(srv_conn->socket, SOCKET_FLAG_NOCLOSE);
2323 dcesrv_conn->local_address = srv_conn->local_address;
2324 dcesrv_conn->remote_address = srv_conn->remote_address;
2326 if (transport == NCALRPC) {
2327 uid_t uid;
2328 gid_t gid;
2329 int sock_fd;
2331 sock_fd = socket_get_fd(srv_conn->socket);
2332 if (sock_fd == -1) {
2333 stream_terminate_connection(
2334 srv_conn, "socket_get_fd failed\n");
2335 return;
2338 ret = getpeereid(sock_fd, &uid, &gid);
2339 if (ret == -1) {
2340 status = map_nt_error_from_unix_common(errno);
2341 DEBUG(0, ("dcesrv_sock_accept: "
2342 "getpeereid() failed for NCALRPC: %s\n",
2343 nt_errstr(status)));
2344 stream_terminate_connection(srv_conn, nt_errstr(status));
2345 return;
2347 if (uid == dcesrv_conn->dce_ctx->initial_euid) {
2348 struct tsocket_address *r = NULL;
2350 ret = tsocket_address_unix_from_path(dcesrv_conn,
2351 "/root/ncalrpc_as_system",
2352 &r);
2353 if (ret == -1) {
2354 status = map_nt_error_from_unix_common(errno);
2355 DEBUG(0, ("dcesrv_sock_accept: "
2356 "tsocket_address_unix_from_path() failed for NCALRPC: %s\n",
2357 nt_errstr(status)));
2358 stream_terminate_connection(srv_conn, nt_errstr(status));
2359 return;
2361 dcesrv_conn->remote_address = r;
2365 srv_conn->private_data = dcesrv_conn;
2367 irpc_add_name(srv_conn->msg_ctx, "rpc_server");
2369 subreq = dcerpc_read_ncacn_packet_send(dcesrv_conn,
2370 dcesrv_conn->event_ctx,
2371 dcesrv_conn->stream);
2372 if (!subreq) {
2373 status = NT_STATUS_NO_MEMORY;
2374 DEBUG(0,("dcesrv_sock_accept: dcerpc_read_fragment_buffer_send(%s)\n",
2375 nt_errstr(status)));
2376 stream_terminate_connection(srv_conn, nt_errstr(status));
2377 return;
2379 tevent_req_set_callback(subreq, dcesrv_read_fragment_done, dcesrv_conn);
2381 return;
2384 static void dcesrv_read_fragment_done(struct tevent_req *subreq)
2386 struct dcesrv_connection *dce_conn = tevent_req_callback_data(subreq,
2387 struct dcesrv_connection);
2388 struct dcesrv_context *dce_ctx = dce_conn->dce_ctx;
2389 struct ncacn_packet *pkt;
2390 DATA_BLOB buffer;
2391 NTSTATUS status;
2393 if (dce_conn->terminate) {
2395 * if the current connection is broken
2396 * we need to clean it up before any other connection
2398 dcesrv_terminate_connection(dce_conn, dce_conn->terminate);
2399 dcesrv_cleanup_broken_connections(dce_ctx);
2400 return;
2403 dcesrv_cleanup_broken_connections(dce_ctx);
2405 status = dcerpc_read_ncacn_packet_recv(subreq, dce_conn,
2406 &pkt, &buffer);
2407 TALLOC_FREE(subreq);
2408 if (!NT_STATUS_IS_OK(status)) {
2409 dcesrv_terminate_connection(dce_conn, nt_errstr(status));
2410 return;
2413 status = dcesrv_process_ncacn_packet(dce_conn, pkt, buffer);
2414 if (!NT_STATUS_IS_OK(status)) {
2415 dcesrv_terminate_connection(dce_conn, nt_errstr(status));
2416 return;
2419 subreq = dcerpc_read_ncacn_packet_send(dce_conn,
2420 dce_conn->event_ctx,
2421 dce_conn->stream);
2422 if (!subreq) {
2423 status = NT_STATUS_NO_MEMORY;
2424 dcesrv_terminate_connection(dce_conn, nt_errstr(status));
2425 return;
2427 tevent_req_set_callback(subreq, dcesrv_read_fragment_done, dce_conn);
2430 static void dcesrv_sock_recv(struct stream_connection *conn, uint16_t flags)
2432 struct dcesrv_connection *dce_conn = talloc_get_type(conn->private_data,
2433 struct dcesrv_connection);
2434 dcesrv_terminate_connection(dce_conn, "dcesrv_sock_recv triggered");
2437 static void dcesrv_sock_send(struct stream_connection *conn, uint16_t flags)
2439 struct dcesrv_connection *dce_conn = talloc_get_type(conn->private_data,
2440 struct dcesrv_connection);
2441 dcesrv_terminate_connection(dce_conn, "dcesrv_sock_send triggered");
2445 static const struct stream_server_ops dcesrv_stream_ops = {
2446 .name = "rpc",
2447 .accept_connection = dcesrv_sock_accept,
2448 .recv_handler = dcesrv_sock_recv,
2449 .send_handler = dcesrv_sock_send,
2452 static NTSTATUS dcesrv_add_ep_unix(struct dcesrv_context *dce_ctx,
2453 struct loadparm_context *lp_ctx,
2454 struct dcesrv_endpoint *e,
2455 struct tevent_context *event_ctx, const struct model_ops *model_ops)
2457 struct dcesrv_socket_context *dcesrv_sock;
2458 uint16_t port = 1;
2459 NTSTATUS status;
2460 const char *endpoint;
2462 dcesrv_sock = talloc_zero(event_ctx, struct dcesrv_socket_context);
2463 NT_STATUS_HAVE_NO_MEMORY(dcesrv_sock);
2465 /* remember the endpoint of this socket */
2466 dcesrv_sock->endpoint = e;
2467 dcesrv_sock->dcesrv_ctx = talloc_reference(dcesrv_sock, dce_ctx);
2469 endpoint = dcerpc_binding_get_string_option(e->ep_description, "endpoint");
2471 status = stream_setup_socket(dcesrv_sock, event_ctx, lp_ctx,
2472 model_ops, &dcesrv_stream_ops,
2473 "unix", endpoint, &port,
2474 lpcfg_socket_options(lp_ctx),
2475 dcesrv_sock);
2476 if (!NT_STATUS_IS_OK(status)) {
2477 DEBUG(0,("service_setup_stream_socket(path=%s) failed - %s\n",
2478 endpoint, nt_errstr(status)));
2481 return status;
2484 static NTSTATUS dcesrv_add_ep_ncalrpc(struct dcesrv_context *dce_ctx,
2485 struct loadparm_context *lp_ctx,
2486 struct dcesrv_endpoint *e,
2487 struct tevent_context *event_ctx, const struct model_ops *model_ops)
2489 struct dcesrv_socket_context *dcesrv_sock;
2490 uint16_t port = 1;
2491 char *full_path;
2492 NTSTATUS status;
2493 const char *endpoint;
2495 endpoint = dcerpc_binding_get_string_option(e->ep_description, "endpoint");
2497 if (endpoint == NULL) {
2499 * No identifier specified: use DEFAULT.
2501 * TODO: DO NOT hardcode this value anywhere else. Rather, specify
2502 * no endpoint and let the epmapper worry about it.
2504 endpoint = "DEFAULT";
2505 status = dcerpc_binding_set_string_option(e->ep_description,
2506 "endpoint",
2507 endpoint);
2508 if (!NT_STATUS_IS_OK(status)) {
2509 DEBUG(0,("dcerpc_binding_set_string_option() failed - %s\n",
2510 nt_errstr(status)));
2511 return status;
2515 full_path = talloc_asprintf(dce_ctx, "%s/%s", lpcfg_ncalrpc_dir(lp_ctx),
2516 endpoint);
2518 dcesrv_sock = talloc_zero(event_ctx, struct dcesrv_socket_context);
2519 NT_STATUS_HAVE_NO_MEMORY(dcesrv_sock);
2521 /* remember the endpoint of this socket */
2522 dcesrv_sock->endpoint = e;
2523 dcesrv_sock->dcesrv_ctx = talloc_reference(dcesrv_sock, dce_ctx);
2525 status = stream_setup_socket(dcesrv_sock, event_ctx, lp_ctx,
2526 model_ops, &dcesrv_stream_ops,
2527 "unix", full_path, &port,
2528 lpcfg_socket_options(lp_ctx),
2529 dcesrv_sock);
2530 if (!NT_STATUS_IS_OK(status)) {
2531 DEBUG(0,("service_setup_stream_socket(identifier=%s,path=%s) failed - %s\n",
2532 endpoint, full_path, nt_errstr(status)));
2534 return status;
2537 static NTSTATUS dcesrv_add_ep_np(struct dcesrv_context *dce_ctx,
2538 struct loadparm_context *lp_ctx,
2539 struct dcesrv_endpoint *e,
2540 struct tevent_context *event_ctx, const struct model_ops *model_ops)
2542 struct dcesrv_socket_context *dcesrv_sock;
2543 NTSTATUS status;
2544 const char *endpoint;
2546 endpoint = dcerpc_binding_get_string_option(e->ep_description, "endpoint");
2547 if (endpoint == NULL) {
2548 DEBUG(0, ("Endpoint mandatory for named pipes\n"));
2549 return NT_STATUS_INVALID_PARAMETER;
2552 dcesrv_sock = talloc_zero(event_ctx, struct dcesrv_socket_context);
2553 NT_STATUS_HAVE_NO_MEMORY(dcesrv_sock);
2555 /* remember the endpoint of this socket */
2556 dcesrv_sock->endpoint = e;
2557 dcesrv_sock->dcesrv_ctx = talloc_reference(dcesrv_sock, dce_ctx);
2559 status = tstream_setup_named_pipe(dce_ctx, event_ctx, lp_ctx,
2560 model_ops, &dcesrv_stream_ops,
2561 endpoint,
2562 dcesrv_sock);
2563 if (!NT_STATUS_IS_OK(status)) {
2564 DEBUG(0,("stream_setup_named_pipe(pipe=%s) failed - %s\n",
2565 endpoint, nt_errstr(status)));
2566 return status;
2569 return NT_STATUS_OK;
2573 add a socket address to the list of events, one event per dcerpc endpoint
2575 static NTSTATUS add_socket_rpc_tcp_iface(struct dcesrv_context *dce_ctx, struct dcesrv_endpoint *e,
2576 struct tevent_context *event_ctx, const struct model_ops *model_ops,
2577 const char *address)
2579 struct dcesrv_socket_context *dcesrv_sock;
2580 uint16_t port = 0;
2581 NTSTATUS status;
2582 const char *endpoint;
2583 char port_str[6];
2585 endpoint = dcerpc_binding_get_string_option(e->ep_description, "endpoint");
2586 if (endpoint != NULL) {
2587 port = atoi(endpoint);
2590 dcesrv_sock = talloc_zero(event_ctx, struct dcesrv_socket_context);
2591 NT_STATUS_HAVE_NO_MEMORY(dcesrv_sock);
2593 /* remember the endpoint of this socket */
2594 dcesrv_sock->endpoint = e;
2595 dcesrv_sock->dcesrv_ctx = talloc_reference(dcesrv_sock, dce_ctx);
2597 status = stream_setup_socket(dcesrv_sock, event_ctx, dce_ctx->lp_ctx,
2598 model_ops, &dcesrv_stream_ops,
2599 "ip", address, &port,
2600 lpcfg_socket_options(dce_ctx->lp_ctx),
2601 dcesrv_sock);
2602 if (!NT_STATUS_IS_OK(status)) {
2603 DEBUG(0,("service_setup_stream_socket(address=%s,port=%u) failed - %s\n",
2604 address, port, nt_errstr(status)));
2605 return status;
2608 snprintf(port_str, sizeof(port_str), "%u", port);
2610 status = dcerpc_binding_set_string_option(e->ep_description,
2611 "endpoint", port_str);
2612 if (!NT_STATUS_IS_OK(status)) {
2613 DEBUG(0,("dcerpc_binding_set_string_option(endpoint, %s) failed - %s\n",
2614 port_str, nt_errstr(status)));
2615 return status;
2616 } else {
2617 struct dcesrv_if_list *iface;
2618 DEBUG(4,("Successfully listening on ncacn_ip_tcp endpoint [%s]:[%s] for ",
2619 address, port_str));
2620 for (iface = e->interface_list; iface; iface = iface->next) {
2621 DEBUGADD(4, ("%s ", iface->iface.name));
2623 DEBUGADD(4, ("\n"));
2626 return NT_STATUS_OK;
2629 #include "lib/socket/netif.h" /* Included here to work around the fact that socket_wrapper redefines bind() */
2631 static NTSTATUS dcesrv_add_ep_tcp(struct dcesrv_context *dce_ctx,
2632 struct loadparm_context *lp_ctx,
2633 struct dcesrv_endpoint *e,
2634 struct tevent_context *event_ctx, const struct model_ops *model_ops)
2636 NTSTATUS status;
2638 /* Add TCP/IP sockets */
2639 if (lpcfg_interfaces(lp_ctx) && lpcfg_bind_interfaces_only(lp_ctx)) {
2640 int num_interfaces;
2641 int i;
2642 struct interface *ifaces;
2644 load_interface_list(dce_ctx, lp_ctx, &ifaces);
2646 num_interfaces = iface_list_count(ifaces);
2647 for(i = 0; i < num_interfaces; i++) {
2648 const char *address = iface_list_n_ip(ifaces, i);
2649 status = add_socket_rpc_tcp_iface(dce_ctx, e, event_ctx, model_ops, address);
2650 NT_STATUS_NOT_OK_RETURN(status);
2652 } else {
2653 char **wcard;
2654 int i;
2655 int num_binds = 0;
2656 wcard = iface_list_wildcard(dce_ctx);
2657 NT_STATUS_HAVE_NO_MEMORY(wcard);
2658 for (i=0; wcard[i]; i++) {
2659 status = add_socket_rpc_tcp_iface(dce_ctx, e, event_ctx, model_ops, wcard[i]);
2660 if (NT_STATUS_IS_OK(status)) {
2661 num_binds++;
2664 talloc_free(wcard);
2665 if (num_binds == 0) {
2666 return NT_STATUS_INVALID_PARAMETER_MIX;
2670 return NT_STATUS_OK;
2673 NTSTATUS dcesrv_add_ep(struct dcesrv_context *dce_ctx,
2674 struct loadparm_context *lp_ctx,
2675 struct dcesrv_endpoint *e,
2676 struct tevent_context *event_ctx,
2677 const struct model_ops *model_ops)
2679 enum dcerpc_transport_t transport =
2680 dcerpc_binding_get_transport(e->ep_description);
2682 switch (transport) {
2683 case NCACN_UNIX_STREAM:
2684 return dcesrv_add_ep_unix(dce_ctx, lp_ctx, e, event_ctx, model_ops);
2686 case NCALRPC:
2687 return dcesrv_add_ep_ncalrpc(dce_ctx, lp_ctx, e, event_ctx, model_ops);
2689 case NCACN_IP_TCP:
2690 return dcesrv_add_ep_tcp(dce_ctx, lp_ctx, e, event_ctx, model_ops);
2692 case NCACN_NP:
2693 return dcesrv_add_ep_np(dce_ctx, lp_ctx, e, event_ctx, model_ops);
2695 default:
2696 return NT_STATUS_NOT_SUPPORTED;
2702 * retrieve credentials from a dce_call
2704 _PUBLIC_ struct cli_credentials *dcesrv_call_credentials(struct dcesrv_call_state *dce_call)
2706 return dce_call->conn->auth_state.session_info->credentials;
2710 * returns true if this is an authenticated call
2712 _PUBLIC_ bool dcesrv_call_authenticated(struct dcesrv_call_state *dce_call)
2714 enum security_user_level level;
2715 level = security_session_user_level(dce_call->conn->auth_state.session_info, NULL);
2716 return level >= SECURITY_USER;
2720 * retrieve account_name for a dce_call
2722 _PUBLIC_ const char *dcesrv_call_account_name(struct dcesrv_call_state *dce_call)
2724 return dce_call->context->conn->auth_state.session_info->info->account_name;