2 Unix SMB/CIFS implementation.
4 server side dcerpc core code
6 Copyright (C) Andrew Tridgell 2003-2005
7 Copyright (C) Stefan (metze) Metzmacher 2004-2005
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 3 of the License, or
12 (at your option) any later version.
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
19 You should have received a copy of the GNU General Public License
20 along with this program. If not, see <http://www.gnu.org/licenses/>.
24 #include "auth/auth.h"
25 #include "auth/gensec/gensec.h"
26 #include "../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 /* this is only used when the client asks for an unknown interface */
46 #define DUMMY_ASSOC_GROUP 0x0FFFFFFF
48 extern const struct dcesrv_interface dcesrv_mgmt_interface;
52 find an association group given a assoc_group_id
54 static struct dcesrv_assoc_group *dcesrv_assoc_group_find(struct dcesrv_context *dce_ctx,
59 id_ptr = idr_find(dce_ctx->assoc_groups_idr, id);
63 return talloc_get_type_abort(id_ptr, struct dcesrv_assoc_group);
67 take a reference to an existing association group
69 static struct dcesrv_assoc_group *dcesrv_assoc_group_reference(TALLOC_CTX *mem_ctx,
70 struct dcesrv_context *dce_ctx,
73 struct dcesrv_assoc_group *assoc_group;
75 assoc_group = dcesrv_assoc_group_find(dce_ctx, id);
76 if (assoc_group == NULL) {
77 DEBUG(0,(__location__ ": Failed to find assoc_group 0x%08x\n", id));
80 return talloc_reference(mem_ctx, assoc_group);
83 static int dcesrv_assoc_group_destructor(struct dcesrv_assoc_group *assoc_group)
86 ret = idr_remove(assoc_group->dce_ctx->assoc_groups_idr, assoc_group->id);
88 DEBUG(0,(__location__ ": Failed to remove assoc_group 0x%08x\n",
95 allocate a new association group
97 static struct dcesrv_assoc_group *dcesrv_assoc_group_new(TALLOC_CTX *mem_ctx,
98 struct dcesrv_context *dce_ctx)
100 struct dcesrv_assoc_group *assoc_group;
103 assoc_group = talloc_zero(mem_ctx, struct dcesrv_assoc_group);
104 if (assoc_group == NULL) {
108 id = idr_get_new_random(dce_ctx->assoc_groups_idr, assoc_group, UINT16_MAX);
110 talloc_free(assoc_group);
111 DEBUG(0,(__location__ ": Out of association groups!\n"));
115 assoc_group->id = id;
116 assoc_group->dce_ctx = dce_ctx;
118 talloc_set_destructor(assoc_group, dcesrv_assoc_group_destructor);
125 see if two endpoints match
127 static bool endpoints_match(const struct dcerpc_binding *ep1,
128 const struct dcerpc_binding *ep2)
130 enum dcerpc_transport_t t1;
131 enum dcerpc_transport_t t2;
135 t1 = dcerpc_binding_get_transport(ep1);
136 t2 = dcerpc_binding_get_transport(ep2);
138 e1 = dcerpc_binding_get_string_option(ep1, "endpoint");
139 e2 = dcerpc_binding_get_string_option(ep2, "endpoint");
149 if (strcasecmp(e1, e2) != 0) {
157 find an endpoint in the dcesrv_context
159 static struct dcesrv_endpoint *find_endpoint(struct dcesrv_context *dce_ctx,
160 const struct dcerpc_binding *ep_description)
162 struct dcesrv_endpoint *ep;
163 for (ep=dce_ctx->endpoint_list; ep; ep=ep->next) {
164 if (endpoints_match(ep->ep_description, ep_description)) {
172 find a registered context_id from a bind or alter_context
174 static struct dcesrv_connection_context *dcesrv_find_context(struct dcesrv_connection *conn,
177 struct dcesrv_connection_context *c;
178 for (c=conn->contexts;c;c=c->next) {
179 if (c->context_id == context_id) return c;
185 see if a uuid and if_version match to an interface
187 static bool interface_match(const struct dcesrv_interface *if1,
188 const struct dcesrv_interface *if2)
190 return (if1->syntax_id.if_version == if2->syntax_id.if_version &&
191 GUID_equal(&if1->syntax_id.uuid, &if2->syntax_id.uuid));
195 find the interface operations on an endpoint
197 static const struct dcesrv_interface *find_interface(const struct dcesrv_endpoint *endpoint,
198 const struct dcesrv_interface *iface)
200 struct dcesrv_if_list *ifl;
201 for (ifl=endpoint->interface_list; ifl; ifl=ifl->next) {
202 if (interface_match(&(ifl->iface), iface)) {
203 return &(ifl->iface);
210 see if a uuid and if_version match to an interface
212 static bool interface_match_by_uuid(const struct dcesrv_interface *iface,
213 const struct GUID *uuid, uint32_t if_version)
215 return (iface->syntax_id.if_version == if_version &&
216 GUID_equal(&iface->syntax_id.uuid, uuid));
220 find the interface operations on an endpoint by uuid
222 static const struct dcesrv_interface *find_interface_by_uuid(const struct dcesrv_endpoint *endpoint,
223 const struct GUID *uuid, uint32_t if_version)
225 struct dcesrv_if_list *ifl;
226 for (ifl=endpoint->interface_list; ifl; ifl=ifl->next) {
227 if (interface_match_by_uuid(&(ifl->iface), uuid, if_version)) {
228 return &(ifl->iface);
235 find the earlier parts of a fragmented call awaiting reassembily
237 static struct dcesrv_call_state *dcesrv_find_fragmented_call(struct dcesrv_connection *dce_conn, uint16_t call_id)
239 struct dcesrv_call_state *c;
240 for (c=dce_conn->incoming_fragmented_call_list;c;c=c->next) {
241 if (c->pkt.call_id == call_id) {
249 register an interface on an endpoint
251 _PUBLIC_ NTSTATUS dcesrv_interface_register(struct dcesrv_context *dce_ctx,
253 const struct dcesrv_interface *iface,
254 const struct security_descriptor *sd)
256 struct dcesrv_endpoint *ep;
257 struct dcesrv_if_list *ifl;
258 struct dcerpc_binding *binding;
262 status = dcerpc_parse_binding(dce_ctx, ep_name, &binding);
264 if (NT_STATUS_IS_ERR(status)) {
265 DEBUG(0, ("Trouble parsing binding string '%s'\n", ep_name));
269 /* check if this endpoint exists
271 if ((ep=find_endpoint(dce_ctx, binding))==NULL) {
272 ep = talloc_zero(dce_ctx, struct dcesrv_endpoint);
274 return NT_STATUS_NO_MEMORY;
277 ep->ep_description = talloc_move(ep, &binding);
280 /* add mgmt interface */
281 ifl = talloc_zero(ep, struct dcesrv_if_list);
283 return NT_STATUS_NO_MEMORY;
286 memcpy(&(ifl->iface), &dcesrv_mgmt_interface,
287 sizeof(struct dcesrv_interface));
289 DLIST_ADD(ep->interface_list, ifl);
292 /* see if the interface is already registered on te endpoint */
293 if (find_interface(ep, iface)!=NULL) {
294 DEBUG(0,("dcesrv_interface_register: interface '%s' already registered on endpoint '%s'\n",
295 iface->name, ep_name));
296 return NT_STATUS_OBJECT_NAME_COLLISION;
299 /* talloc a new interface list element */
300 ifl = talloc_zero(ep, struct dcesrv_if_list);
302 return NT_STATUS_NO_MEMORY;
305 /* copy the given interface struct to the one on the endpoints interface list */
306 memcpy(&(ifl->iface),iface, sizeof(struct dcesrv_interface));
308 /* if we have a security descriptor given,
309 * we should see if we can set it up on the endpoint
312 /* if there's currently no security descriptor given on the endpoint
315 if (ep->sd == NULL) {
316 ep->sd = security_descriptor_copy(ep, sd);
319 /* if now there's no security descriptor given on the endpoint
320 * something goes wrong, either we failed to copy the security descriptor
321 * or there was already one on the endpoint
323 if (ep->sd != NULL) {
324 DEBUG(0,("dcesrv_interface_register: interface '%s' failed to setup a security descriptor\n"
325 " on endpoint '%s'\n",
326 iface->name, ep_name));
327 if (add_ep) free(ep);
329 return NT_STATUS_OBJECT_NAME_COLLISION;
333 /* finally add the interface on the endpoint */
334 DLIST_ADD(ep->interface_list, ifl);
336 /* if it's a new endpoint add it to the dcesrv_context */
338 DLIST_ADD(dce_ctx->endpoint_list, ep);
341 DEBUG(4,("dcesrv_interface_register: interface '%s' registered on endpoint '%s'\n",
342 iface->name, ep_name));
347 NTSTATUS dcesrv_inherited_session_key(struct dcesrv_connection *p,
348 DATA_BLOB *session_key)
350 if (p->auth_state.session_info->session_key.length) {
351 *session_key = p->auth_state.session_info->session_key;
354 return NT_STATUS_NO_USER_SESSION_KEY;
358 fetch the user session key - may be default (above) or the SMB session key
360 The key is always truncated to 16 bytes
362 _PUBLIC_ NTSTATUS dcesrv_fetch_session_key(struct dcesrv_connection *p,
363 DATA_BLOB *session_key)
365 NTSTATUS status = p->auth_state.session_key(p, session_key);
366 if (!NT_STATUS_IS_OK(status)) {
370 session_key->length = MIN(session_key->length, 16);
376 connect to a dcerpc endpoint
378 _PUBLIC_ NTSTATUS dcesrv_endpoint_connect(struct dcesrv_context *dce_ctx,
380 const struct dcesrv_endpoint *ep,
381 struct auth_session_info *session_info,
382 struct tevent_context *event_ctx,
383 struct imessaging_context *msg_ctx,
384 struct server_id server_id,
385 uint32_t state_flags,
386 struct dcesrv_connection **_p)
388 struct dcesrv_connection *p;
391 return NT_STATUS_ACCESS_DENIED;
394 p = talloc_zero(mem_ctx, struct dcesrv_connection);
395 NT_STATUS_HAVE_NO_MEMORY(p);
397 if (!talloc_reference(p, session_info)) {
399 return NT_STATUS_NO_MEMORY;
402 p->dce_ctx = dce_ctx;
404 p->packet_log_dir = lpcfg_lock_directory(dce_ctx->lp_ctx);
405 p->auth_state.session_info = session_info;
406 p->auth_state.session_key = dcesrv_generic_session_key;
407 p->event_ctx = event_ctx;
408 p->msg_ctx = msg_ctx;
409 p->server_id = server_id;
410 p->state_flags = state_flags;
411 p->max_recv_frag = 5840;
412 p->max_xmit_frag = 5840;
419 move a call from an existing linked list to the specified list. This
420 prevents bugs where we forget to remove the call from a previous
423 static void dcesrv_call_set_list(struct dcesrv_call_state *call,
424 enum dcesrv_call_list list)
426 switch (call->list) {
427 case DCESRV_LIST_NONE:
429 case DCESRV_LIST_CALL_LIST:
430 DLIST_REMOVE(call->conn->call_list, call);
432 case DCESRV_LIST_FRAGMENTED_CALL_LIST:
433 DLIST_REMOVE(call->conn->incoming_fragmented_call_list, call);
435 case DCESRV_LIST_PENDING_CALL_LIST:
436 DLIST_REMOVE(call->conn->pending_call_list, call);
441 case DCESRV_LIST_NONE:
443 case DCESRV_LIST_CALL_LIST:
444 DLIST_ADD_END(call->conn->call_list, call);
446 case DCESRV_LIST_FRAGMENTED_CALL_LIST:
447 DLIST_ADD_END(call->conn->incoming_fragmented_call_list, call);
449 case DCESRV_LIST_PENDING_CALL_LIST:
450 DLIST_ADD_END(call->conn->pending_call_list, call);
457 return a dcerpc bind_nak
459 static NTSTATUS dcesrv_bind_nak(struct dcesrv_call_state *call, uint32_t reason)
461 struct ncacn_packet pkt;
462 struct dcerpc_bind_nak_version version;
463 struct data_blob_list_item *rep;
465 static const uint8_t _pad[3] = { 0, };
467 /* setup a bind_nak */
468 dcesrv_init_hdr(&pkt, lpcfg_rpc_big_endian(call->conn->dce_ctx->lp_ctx));
470 pkt.call_id = call->pkt.call_id;
471 pkt.ptype = DCERPC_PKT_BIND_NAK;
472 pkt.pfc_flags = DCERPC_PFC_FLAG_FIRST | DCERPC_PFC_FLAG_LAST;
473 pkt.u.bind_nak.reject_reason = reason;
474 version.rpc_vers = 5;
475 version.rpc_vers_minor = 0;
476 pkt.u.bind_nak.num_versions = 1;
477 pkt.u.bind_nak.versions = &version;
478 pkt.u.bind_nak._pad = data_blob_const(_pad, sizeof(_pad));
480 rep = talloc_zero(call, struct data_blob_list_item);
482 return NT_STATUS_NO_MEMORY;
485 status = ncacn_push_auth(&rep->blob, call, &pkt, NULL);
486 if (!NT_STATUS_IS_OK(status)) {
490 dcerpc_set_frag_length(&rep->blob, rep->blob.length);
492 DLIST_ADD_END(call->replies, rep);
493 dcesrv_call_set_list(call, DCESRV_LIST_CALL_LIST);
495 if (call->conn->call_list && call->conn->call_list->replies) {
496 if (call->conn->transport.report_output_data) {
497 call->conn->transport.report_output_data(call->conn);
504 static int dcesrv_connection_context_destructor(struct dcesrv_connection_context *c)
506 DLIST_REMOVE(c->conn->contexts, c);
508 if (c->iface && c->iface->unbind) {
509 c->iface->unbind(c, c->iface);
516 static void dcesrv_prepare_context_auth(struct dcesrv_call_state *dce_call)
518 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
519 const struct dcesrv_endpoint *endpoint = dce_call->conn->endpoint;
520 enum dcerpc_transport_t transport =
521 dcerpc_binding_get_transport(endpoint->ep_description);
522 struct dcesrv_connection_context *context = dce_call->context;
523 const struct dcesrv_interface *iface = context->iface;
525 context->min_auth_level = DCERPC_AUTH_LEVEL_NONE;
527 if (transport == NCALRPC) {
528 context->allow_connect = true;
533 * allow overwrite per interface
534 * allow dcerpc auth level connect:<interface>
536 context->allow_connect = lpcfg_allow_dcerpc_auth_level_connect(lp_ctx);
537 context->allow_connect = lpcfg_parm_bool(lp_ctx, NULL,
538 "allow dcerpc auth level connect",
540 context->allow_connect);
543 NTSTATUS dcesrv_interface_bind_require_integrity(struct dcesrv_call_state *dce_call,
544 const struct dcesrv_interface *iface)
546 if (dce_call->context == NULL) {
547 return NT_STATUS_INTERNAL_ERROR;
550 dce_call->context->min_auth_level = DCERPC_AUTH_LEVEL_INTEGRITY;
554 NTSTATUS dcesrv_interface_bind_require_privacy(struct dcesrv_call_state *dce_call,
555 const struct dcesrv_interface *iface)
557 if (dce_call->context == NULL) {
558 return NT_STATUS_INTERNAL_ERROR;
561 dce_call->context->min_auth_level = DCERPC_AUTH_LEVEL_PRIVACY;
565 _PUBLIC_ NTSTATUS dcesrv_interface_bind_reject_connect(struct dcesrv_call_state *dce_call,
566 const struct dcesrv_interface *iface)
568 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
569 const struct dcesrv_endpoint *endpoint = dce_call->conn->endpoint;
570 enum dcerpc_transport_t transport =
571 dcerpc_binding_get_transport(endpoint->ep_description);
572 struct dcesrv_connection_context *context = dce_call->context;
574 if (context == NULL) {
575 return NT_STATUS_INTERNAL_ERROR;
578 if (transport == NCALRPC) {
579 context->allow_connect = true;
584 * allow overwrite per interface
585 * allow dcerpc auth level connect:<interface>
587 context->allow_connect = false;
588 context->allow_connect = lpcfg_parm_bool(lp_ctx, NULL,
589 "allow dcerpc auth level connect",
591 context->allow_connect);
595 _PUBLIC_ NTSTATUS dcesrv_interface_bind_allow_connect(struct dcesrv_call_state *dce_call,
596 const struct dcesrv_interface *iface)
598 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
599 const struct dcesrv_endpoint *endpoint = dce_call->conn->endpoint;
600 enum dcerpc_transport_t transport =
601 dcerpc_binding_get_transport(endpoint->ep_description);
602 struct dcesrv_connection_context *context = dce_call->context;
604 if (context == NULL) {
605 return NT_STATUS_INTERNAL_ERROR;
608 if (transport == NCALRPC) {
609 context->allow_connect = true;
614 * allow overwrite per interface
615 * allow dcerpc auth level connect:<interface>
617 context->allow_connect = true;
618 context->allow_connect = lpcfg_parm_bool(lp_ctx, NULL,
619 "allow dcerpc auth level connect",
621 context->allow_connect);
626 handle a bind request
628 static NTSTATUS dcesrv_bind(struct dcesrv_call_state *call)
630 uint32_t if_version, transfer_syntax_version;
631 struct GUID uuid, *transfer_syntax_uuid;
632 struct ncacn_packet pkt;
633 struct data_blob_list_item *rep;
635 uint32_t result=0, reason=0;
637 const struct dcesrv_interface *iface;
638 uint32_t extra_flags = 0;
639 uint16_t max_req = 0;
640 uint16_t max_rep = 0;
641 const char *ep_prefix = "";
642 const char *endpoint = NULL;
644 /* max_recv_frag and max_xmit_frag result always in the same value! */
645 max_req = MIN(call->pkt.u.bind.max_xmit_frag,
646 call->pkt.u.bind.max_recv_frag);
648 * The values are between 2048 and 5840 tested against Windows 2012R2
649 * via ncacn_ip_tcp on port 135.
651 max_req = MAX(2048, max_req);
652 max_rep = MIN(max_req, call->conn->max_recv_frag);
653 /* They are truncated to an 8 byte boundary. */
656 /* max_recv_frag and max_xmit_frag result always in the same value! */
657 call->conn->max_recv_frag = max_rep;
658 call->conn->max_xmit_frag = max_rep;
661 if provided, check the assoc_group is valid
663 if (call->pkt.u.bind.assoc_group_id != 0 &&
664 lpcfg_parm_bool(call->conn->dce_ctx->lp_ctx, NULL, "dcesrv","assoc group checking", true) &&
665 dcesrv_assoc_group_find(call->conn->dce_ctx, call->pkt.u.bind.assoc_group_id) == NULL) {
666 return dcesrv_bind_nak(call, 0);
669 if (call->pkt.u.bind.num_contexts < 1 ||
670 call->pkt.u.bind.ctx_list[0].num_transfer_syntaxes < 1) {
671 return dcesrv_bind_nak(call, 0);
674 context_id = call->pkt.u.bind.ctx_list[0].context_id;
676 /* you can't bind twice on one context */
677 if (dcesrv_find_context(call->conn, context_id) != NULL) {
678 return dcesrv_bind_nak(call, 0);
681 if_version = call->pkt.u.bind.ctx_list[0].abstract_syntax.if_version;
682 uuid = call->pkt.u.bind.ctx_list[0].abstract_syntax.uuid;
684 transfer_syntax_version = call->pkt.u.bind.ctx_list[0].transfer_syntaxes[0].if_version;
685 transfer_syntax_uuid = &call->pkt.u.bind.ctx_list[0].transfer_syntaxes[0].uuid;
686 if (!GUID_equal(&ndr_transfer_syntax_ndr.uuid, transfer_syntax_uuid) != 0 ||
687 ndr_transfer_syntax_ndr.if_version != transfer_syntax_version) {
688 char *uuid_str = GUID_string(call, transfer_syntax_uuid);
689 /* we only do NDR encoded dcerpc */
690 DEBUG(0,("Non NDR transfer syntax requested - %s\n", uuid_str));
691 talloc_free(uuid_str);
692 return dcesrv_bind_nak(call, 0);
695 iface = find_interface_by_uuid(call->conn->endpoint, &uuid, if_version);
697 char *uuid_str = GUID_string(call, &uuid);
698 DEBUG(2,("Request for unknown dcerpc interface %s/%d\n", uuid_str, if_version));
699 talloc_free(uuid_str);
701 /* we don't know about that interface */
702 result = DCERPC_BIND_PROVIDER_REJECT;
703 reason = DCERPC_BIND_REASON_ASYNTAX;
707 /* add this context to the list of available context_ids */
708 struct dcesrv_connection_context *context = talloc_zero(call->conn,
709 struct dcesrv_connection_context);
710 if (context == NULL) {
711 return dcesrv_bind_nak(call, 0);
713 context->conn = call->conn;
714 context->iface = iface;
715 context->context_id = context_id;
716 if (call->pkt.u.bind.assoc_group_id != 0) {
717 context->assoc_group = dcesrv_assoc_group_reference(context,
719 call->pkt.u.bind.assoc_group_id);
721 context->assoc_group = dcesrv_assoc_group_new(context, call->conn->dce_ctx);
723 if (context->assoc_group == NULL) {
724 talloc_free(context);
725 return dcesrv_bind_nak(call, 0);
727 context->private_data = NULL;
728 DLIST_ADD(call->conn->contexts, context);
729 call->context = context;
730 talloc_set_destructor(context, dcesrv_connection_context_destructor);
732 dcesrv_prepare_context_auth(call);
734 status = iface->bind(call, iface, if_version);
735 if (!NT_STATUS_IS_OK(status)) {
736 char *uuid_str = GUID_string(call, &uuid);
737 DEBUG(2,("Request for dcerpc interface %s/%d rejected: %s\n",
738 uuid_str, if_version, nt_errstr(status)));
739 talloc_free(uuid_str);
740 /* we don't want to trigger the iface->unbind() hook */
741 context->iface = NULL;
742 talloc_free(call->context);
743 call->context = NULL;
744 return dcesrv_bind_nak(call, 0);
748 if ((call->pkt.pfc_flags & DCERPC_PFC_FLAG_CONC_MPX) &&
749 (call->state_flags & DCESRV_CALL_STATE_FLAG_MULTIPLEXED)) {
750 call->context->conn->state_flags |= DCESRV_CALL_STATE_FLAG_MULTIPLEXED;
751 extra_flags |= DCERPC_PFC_FLAG_CONC_MPX;
754 if (call->state_flags & DCESRV_CALL_STATE_FLAG_PROCESS_PENDING_CALL) {
755 call->context->conn->state_flags |= DCESRV_CALL_STATE_FLAG_PROCESS_PENDING_CALL;
758 /* handle any authentication that is being requested */
759 if (!dcesrv_auth_bind(call)) {
760 talloc_free(call->context);
761 call->context = NULL;
762 return dcesrv_bind_nak(call, DCERPC_BIND_REASON_INVALID_AUTH_TYPE);
765 /* setup a bind_ack */
766 dcesrv_init_hdr(&pkt, lpcfg_rpc_big_endian(call->conn->dce_ctx->lp_ctx));
768 pkt.call_id = call->pkt.call_id;
769 pkt.ptype = DCERPC_PKT_BIND_ACK;
770 pkt.pfc_flags = DCERPC_PFC_FLAG_FIRST | DCERPC_PFC_FLAG_LAST | extra_flags;
771 pkt.u.bind_ack.max_xmit_frag = call->conn->max_xmit_frag;
772 pkt.u.bind_ack.max_recv_frag = call->conn->max_recv_frag;
775 make it possible for iface->bind() to specify the assoc_group_id
776 This helps the openchange mapiproxy plugin to work correctly.
781 pkt.u.bind_ack.assoc_group_id = call->context->assoc_group->id;
783 pkt.u.bind_ack.assoc_group_id = DUMMY_ASSOC_GROUP;
787 endpoint = dcerpc_binding_get_string_option(
788 call->conn->endpoint->ep_description,
792 if (endpoint == NULL) {
796 if (strncasecmp(endpoint, "\\pipe\\", 6) == 0) {
798 * TODO: check if this is really needed
800 * Or if we should fix this in our idl files.
802 ep_prefix = "\\PIPE\\";
806 pkt.u.bind_ack.secondary_address = talloc_asprintf(call, "%s%s",
809 if (pkt.u.bind_ack.secondary_address == NULL) {
810 TALLOC_FREE(call->context);
811 return NT_STATUS_NO_MEMORY;
813 pkt.u.bind_ack.num_results = 1;
814 pkt.u.bind_ack.ctx_list = talloc_zero(call, struct dcerpc_ack_ctx);
815 if (!pkt.u.bind_ack.ctx_list) {
816 talloc_free(call->context);
817 call->context = NULL;
818 return NT_STATUS_NO_MEMORY;
820 pkt.u.bind_ack.ctx_list[0].result = result;
821 pkt.u.bind_ack.ctx_list[0].reason.value = reason;
822 pkt.u.bind_ack.ctx_list[0].syntax = ndr_transfer_syntax_ndr;
823 pkt.u.bind_ack.auth_info = data_blob(NULL, 0);
825 status = dcesrv_auth_bind_ack(call, &pkt);
826 if (!NT_STATUS_IS_OK(status)) {
827 talloc_free(call->context);
828 call->context = NULL;
829 return dcesrv_bind_nak(call, 0);
832 rep = talloc_zero(call, struct data_blob_list_item);
834 talloc_free(call->context);
835 call->context = NULL;
836 return NT_STATUS_NO_MEMORY;
839 status = ncacn_push_auth(&rep->blob, call, &pkt,
840 call->conn->auth_state.auth_info);
841 if (!NT_STATUS_IS_OK(status)) {
842 talloc_free(call->context);
843 call->context = NULL;
847 dcerpc_set_frag_length(&rep->blob, rep->blob.length);
849 DLIST_ADD_END(call->replies, rep);
850 dcesrv_call_set_list(call, DCESRV_LIST_CALL_LIST);
852 if (call->conn->call_list && call->conn->call_list->replies) {
853 if (call->conn->transport.report_output_data) {
854 call->conn->transport.report_output_data(call->conn);
863 handle a auth3 request
865 static NTSTATUS dcesrv_auth3(struct dcesrv_call_state *call)
867 /* handle the auth3 in the auth code */
868 if (!dcesrv_auth_auth3(call)) {
869 return dcesrv_fault(call, DCERPC_FAULT_OTHER);
874 /* we don't send a reply to a auth3 request, except by a
881 handle a bind request
883 static NTSTATUS dcesrv_alter_new_context(struct dcesrv_call_state *call, uint32_t context_id)
885 uint32_t if_version, transfer_syntax_version;
886 struct dcesrv_connection_context *context;
887 const struct dcesrv_interface *iface;
888 struct GUID uuid, *transfer_syntax_uuid;
891 if_version = call->pkt.u.alter.ctx_list[0].abstract_syntax.if_version;
892 uuid = call->pkt.u.alter.ctx_list[0].abstract_syntax.uuid;
894 transfer_syntax_version = call->pkt.u.alter.ctx_list[0].transfer_syntaxes[0].if_version;
895 transfer_syntax_uuid = &call->pkt.u.alter.ctx_list[0].transfer_syntaxes[0].uuid;
896 if (!GUID_equal(transfer_syntax_uuid, &ndr_transfer_syntax_ndr.uuid) ||
897 ndr_transfer_syntax_ndr.if_version != transfer_syntax_version) {
898 /* we only do NDR encoded dcerpc */
899 return NT_STATUS_RPC_PROTSEQ_NOT_SUPPORTED;
902 iface = find_interface_by_uuid(call->conn->endpoint, &uuid, if_version);
904 char *uuid_str = GUID_string(call, &uuid);
905 DEBUG(2,("Request for unknown dcerpc interface %s/%d\n", uuid_str, if_version));
906 talloc_free(uuid_str);
907 return NT_STATUS_RPC_PROTSEQ_NOT_SUPPORTED;
910 /* add this context to the list of available context_ids */
911 context = talloc_zero(call->conn, struct dcesrv_connection_context);
912 if (context == NULL) {
913 return NT_STATUS_NO_MEMORY;
915 context->conn = call->conn;
916 context->iface = iface;
917 context->context_id = context_id;
918 if (call->pkt.u.alter.assoc_group_id != 0) {
919 context->assoc_group = dcesrv_assoc_group_reference(context,
921 call->pkt.u.alter.assoc_group_id);
923 context->assoc_group = dcesrv_assoc_group_new(context, call->conn->dce_ctx);
925 if (context->assoc_group == NULL) {
926 talloc_free(context);
927 call->context = NULL;
928 return NT_STATUS_NO_MEMORY;
930 context->private_data = NULL;
931 DLIST_ADD(call->conn->contexts, context);
932 call->context = context;
933 talloc_set_destructor(context, dcesrv_connection_context_destructor);
935 dcesrv_prepare_context_auth(call);
937 status = iface->bind(call, iface, if_version);
938 if (!NT_STATUS_IS_OK(status)) {
939 /* we don't want to trigger the iface->unbind() hook */
940 context->iface = NULL;
941 talloc_free(context);
942 call->context = NULL;
949 /* setup and send an alter_resp */
950 static NTSTATUS dcesrv_alter_resp(struct dcesrv_call_state *call,
954 struct ncacn_packet pkt;
955 uint32_t extra_flags = 0;
956 struct data_blob_list_item *rep = NULL;
959 dcesrv_init_hdr(&pkt, lpcfg_rpc_big_endian(call->conn->dce_ctx->lp_ctx));
961 pkt.call_id = call->pkt.call_id;
962 pkt.ptype = DCERPC_PKT_ALTER_RESP;
964 if ((call->pkt.pfc_flags & DCERPC_PFC_FLAG_CONC_MPX) &&
965 call->context->conn->state_flags &
966 DCESRV_CALL_STATE_FLAG_MULTIPLEXED) {
967 extra_flags |= DCERPC_PFC_FLAG_CONC_MPX;
969 if (call->state_flags & DCESRV_CALL_STATE_FLAG_PROCESS_PENDING_CALL) {
970 call->context->conn->state_flags |=
971 DCESRV_CALL_STATE_FLAG_PROCESS_PENDING_CALL;
974 pkt.pfc_flags = DCERPC_PFC_FLAG_FIRST | DCERPC_PFC_FLAG_LAST | extra_flags;
975 pkt.u.alter_resp.max_xmit_frag = call->conn->max_xmit_frag;
976 pkt.u.alter_resp.max_recv_frag = call->conn->max_recv_frag;
978 pkt.u.alter_resp.assoc_group_id = call->context->assoc_group->id;
980 pkt.u.alter_resp.assoc_group_id = 0;
982 pkt.u.alter_resp.num_results = 1;
983 pkt.u.alter_resp.ctx_list = talloc_zero(call, struct dcerpc_ack_ctx);
984 if (!pkt.u.alter_resp.ctx_list) {
985 return NT_STATUS_NO_MEMORY;
987 pkt.u.alter_resp.ctx_list[0].result = result;
988 pkt.u.alter_resp.ctx_list[0].reason.value = reason;
989 pkt.u.alter_resp.ctx_list[0].syntax = ndr_transfer_syntax_ndr;
990 pkt.u.alter_resp.auth_info = data_blob(NULL, 0);
991 pkt.u.alter_resp.secondary_address = "";
993 status = dcesrv_auth_alter_ack(call, &pkt);
994 if (!NT_STATUS_IS_OK(status)) {
995 if (NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)
996 || NT_STATUS_EQUAL(status, NT_STATUS_LOGON_FAILURE)
997 || NT_STATUS_EQUAL(status, NT_STATUS_NO_SUCH_USER)
998 || NT_STATUS_EQUAL(status, NT_STATUS_WRONG_PASSWORD)) {
999 return dcesrv_fault(call, DCERPC_FAULT_ACCESS_DENIED);
1001 return dcesrv_fault(call, 0);
1004 rep = talloc_zero(call, struct data_blob_list_item);
1006 return NT_STATUS_NO_MEMORY;
1009 status = ncacn_push_auth(&rep->blob, call, &pkt, call->conn->auth_state.auth_info);
1010 if (!NT_STATUS_IS_OK(status)) {
1014 dcerpc_set_frag_length(&rep->blob, rep->blob.length);
1016 DLIST_ADD_END(call->replies, rep);
1017 dcesrv_call_set_list(call, DCESRV_LIST_CALL_LIST);
1019 if (call->conn->call_list && call->conn->call_list->replies) {
1020 if (call->conn->transport.report_output_data) {
1021 call->conn->transport.report_output_data(call->conn);
1025 return NT_STATUS_OK;
1029 handle a alter context request
1031 static NTSTATUS dcesrv_alter(struct dcesrv_call_state *call)
1034 uint32_t context_id;
1036 /* handle any authentication that is being requested */
1037 if (!dcesrv_auth_alter(call)) {
1038 /* TODO: work out the right reject code */
1039 return dcesrv_alter_resp(call,
1040 DCERPC_BIND_PROVIDER_REJECT,
1041 DCERPC_BIND_REASON_ASYNTAX);
1044 context_id = call->pkt.u.alter.ctx_list[0].context_id;
1046 /* see if they are asking for a new interface */
1047 call->context = dcesrv_find_context(call->conn, context_id);
1048 if (!call->context) {
1049 status = dcesrv_alter_new_context(call, context_id);
1050 if (!NT_STATUS_IS_OK(status)) {
1051 return dcesrv_alter_resp(call,
1052 DCERPC_BIND_PROVIDER_REJECT,
1053 DCERPC_BIND_REASON_ASYNTAX);
1057 if (call->pkt.u.alter.assoc_group_id != 0 &&
1058 lpcfg_parm_bool(call->conn->dce_ctx->lp_ctx, NULL, "dcesrv","assoc group checking", true) &&
1059 call->pkt.u.alter.assoc_group_id != call->context->assoc_group->id) {
1060 DEBUG(0,(__location__ ": Failed attempt to use new assoc_group in alter context (0x%08x 0x%08x)\n",
1061 call->context->assoc_group->id, call->pkt.u.alter.assoc_group_id));
1062 /* TODO: can they ask for a new association group? */
1063 return dcesrv_alter_resp(call,
1064 DCERPC_BIND_PROVIDER_REJECT,
1065 DCERPC_BIND_REASON_ASYNTAX);
1068 return dcesrv_alter_resp(call,
1069 DCERPC_BIND_ACK_RESULT_ACCEPTANCE,
1070 DCERPC_BIND_ACK_REASON_NOT_SPECIFIED);
1074 possibly save the call for inspection with ndrdump
1076 static void dcesrv_save_call(struct dcesrv_call_state *call, const char *why)
1080 const char *dump_dir;
1081 dump_dir = lpcfg_parm_string(call->conn->dce_ctx->lp_ctx, NULL, "dcesrv", "stubs directory");
1085 fname = talloc_asprintf(call, "%s/RPC-%s-%u-%s.dat",
1087 call->context->iface->name,
1088 call->pkt.u.request.opnum,
1090 if (file_save(fname, call->pkt.u.request.stub_and_verifier.data, call->pkt.u.request.stub_and_verifier.length)) {
1091 DEBUG(0,("RPC SAVED %s\n", fname));
1097 static NTSTATUS dcesrv_check_verification_trailer(struct dcesrv_call_state *call)
1099 TALLOC_CTX *frame = talloc_stackframe();
1100 const uint32_t bitmask1 = call->conn->auth_state.client_hdr_signing ?
1101 DCERPC_SEC_VT_CLIENT_SUPPORTS_HEADER_SIGNING : 0;
1102 const struct dcerpc_sec_vt_pcontext pcontext = {
1103 .abstract_syntax = call->context->iface->syntax_id,
1104 .transfer_syntax = ndr_transfer_syntax_ndr,
1106 const struct dcerpc_sec_vt_header2 header2 =
1107 dcerpc_sec_vt_header2_from_ncacn_packet(&call->pkt);
1108 enum ndr_err_code ndr_err;
1109 struct dcerpc_sec_verification_trailer *vt = NULL;
1110 NTSTATUS status = NT_STATUS_OK;
1113 SMB_ASSERT(call->pkt.ptype == DCERPC_PKT_REQUEST);
1115 ndr_err = ndr_pop_dcerpc_sec_verification_trailer(call->ndr_pull,
1117 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
1118 status = ndr_map_error2ntstatus(ndr_err);
1122 ok = dcerpc_sec_verification_trailer_check(vt, &bitmask1,
1123 &pcontext, &header2);
1125 status = NT_STATUS_ACCESS_DENIED;
1134 handle a dcerpc request packet
1136 static NTSTATUS dcesrv_request(struct dcesrv_call_state *call)
1138 const struct dcesrv_endpoint *endpoint = call->conn->endpoint;
1139 enum dcerpc_transport_t transport =
1140 dcerpc_binding_get_transport(endpoint->ep_description);
1141 struct ndr_pull *pull;
1143 struct dcesrv_connection_context *context;
1145 /* if authenticated, and the mech we use can't do async replies, don't use them... */
1146 if (call->conn->auth_state.gensec_security &&
1147 !gensec_have_feature(call->conn->auth_state.gensec_security, GENSEC_FEATURE_ASYNC_REPLIES)) {
1148 call->state_flags &= ~DCESRV_CALL_STATE_FLAG_MAY_ASYNC;
1151 context = dcesrv_find_context(call->conn, call->pkt.u.request.context_id);
1152 if (context == NULL) {
1153 return dcesrv_fault(call, DCERPC_FAULT_UNK_IF);
1156 switch (call->conn->auth_state.auth_level) {
1157 case DCERPC_AUTH_LEVEL_NONE:
1158 case DCERPC_AUTH_LEVEL_INTEGRITY:
1159 case DCERPC_AUTH_LEVEL_PRIVACY:
1162 if (!context->allow_connect) {
1165 addr = tsocket_address_string(call->conn->remote_address,
1168 DEBUG(2, ("%s: restrict auth_level_connect access "
1169 "to [%s] with auth[type=0x%x,level=0x%x] "
1170 "on [%s] from [%s]\n",
1171 __func__, context->iface->name,
1172 call->conn->auth_state.auth_type,
1173 call->conn->auth_state.auth_level,
1174 derpc_transport_string_by_transport(transport),
1176 return dcesrv_fault(call, DCERPC_FAULT_ACCESS_DENIED);
1181 if (call->conn->auth_state.auth_level < context->min_auth_level) {
1184 addr = tsocket_address_string(call->conn->remote_address, call);
1186 DEBUG(2, ("%s: restrict access by min_auth_level[0x%x] "
1187 "to [%s] with auth[type=0x%x,level=0x%x] "
1188 "on [%s] from [%s]\n",
1190 context->min_auth_level,
1191 context->iface->name,
1192 call->conn->auth_state.auth_type,
1193 call->conn->auth_state.auth_level,
1194 derpc_transport_string_by_transport(transport),
1196 return dcesrv_fault(call, DCERPC_FAULT_ACCESS_DENIED);
1199 pull = ndr_pull_init_blob(&call->pkt.u.request.stub_and_verifier, call);
1200 NT_STATUS_HAVE_NO_MEMORY(pull);
1202 pull->flags |= LIBNDR_FLAG_REF_ALLOC;
1204 call->context = context;
1205 call->ndr_pull = pull;
1207 if (!(call->pkt.drep[0] & DCERPC_DREP_LE)) {
1208 pull->flags |= LIBNDR_FLAG_BIGENDIAN;
1211 status = dcesrv_check_verification_trailer(call);
1212 if (!NT_STATUS_IS_OK(status)) {
1213 uint32_t faultcode = DCERPC_FAULT_OTHER;
1214 if (NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
1215 faultcode = DCERPC_FAULT_ACCESS_DENIED;
1217 DEBUG(10, ("dcesrv_check_verification_trailer failed: %s\n",
1218 nt_errstr(status)));
1219 return dcesrv_fault(call, faultcode);
1222 /* unravel the NDR for the packet */
1223 status = context->iface->ndr_pull(call, call, pull, &call->r);
1224 if (!NT_STATUS_IS_OK(status)) {
1225 if (call->fault_code == DCERPC_FAULT_OP_RNG_ERROR) {
1226 /* we got an unknown call */
1227 DEBUG(3,(__location__ ": Unknown RPC call %u on %s\n",
1228 call->pkt.u.request.opnum, context->iface->name));
1229 dcesrv_save_call(call, "unknown");
1231 dcesrv_save_call(call, "pullfail");
1233 return dcesrv_fault(call, call->fault_code);
1236 if (pull->offset != pull->data_size) {
1237 dcesrv_save_call(call, "extrabytes");
1238 DEBUG(3,("Warning: %d extra bytes in incoming RPC request\n",
1239 pull->data_size - pull->offset));
1242 /* call the dispatch function */
1243 status = context->iface->dispatch(call, call, call->r);
1244 if (!NT_STATUS_IS_OK(status)) {
1245 DEBUG(5,("dcerpc fault in call %s:%02x - %s\n",
1246 context->iface->name,
1247 call->pkt.u.request.opnum,
1248 dcerpc_errstr(pull, call->fault_code)));
1249 return dcesrv_fault(call, call->fault_code);
1252 /* add the call to the pending list */
1253 dcesrv_call_set_list(call, DCESRV_LIST_PENDING_CALL_LIST);
1255 if (call->state_flags & DCESRV_CALL_STATE_FLAG_ASYNC) {
1256 return NT_STATUS_OK;
1259 return dcesrv_reply(call);
1264 remove the call from the right list when freed
1266 static int dcesrv_call_dequeue(struct dcesrv_call_state *call)
1268 dcesrv_call_set_list(call, DCESRV_LIST_NONE);
1272 _PUBLIC_ const struct tsocket_address *dcesrv_connection_get_local_address(struct dcesrv_connection *conn)
1274 return conn->local_address;
1277 _PUBLIC_ const struct tsocket_address *dcesrv_connection_get_remote_address(struct dcesrv_connection *conn)
1279 return conn->remote_address;
1283 process some input to a dcerpc endpoint server.
1285 static NTSTATUS dcesrv_process_ncacn_packet(struct dcesrv_connection *dce_conn,
1286 struct ncacn_packet *pkt,
1290 struct dcesrv_call_state *call;
1292 call = talloc_zero(dce_conn, struct dcesrv_call_state);
1294 data_blob_free(&blob);
1296 return NT_STATUS_NO_MEMORY;
1298 call->conn = dce_conn;
1299 call->event_ctx = dce_conn->event_ctx;
1300 call->msg_ctx = dce_conn->msg_ctx;
1301 call->state_flags = call->conn->state_flags;
1302 call->time = timeval_current();
1303 call->list = DCESRV_LIST_NONE;
1305 talloc_steal(call, pkt);
1306 talloc_steal(call, blob.data);
1309 talloc_set_destructor(call, dcesrv_call_dequeue);
1311 /* we have to check the signing here, before combining the
1313 if (call->pkt.ptype == DCERPC_PKT_REQUEST &&
1314 !dcesrv_auth_request(call, &blob)) {
1315 return dcesrv_fault(call, DCERPC_FAULT_ACCESS_DENIED);
1318 /* see if this is a continued packet */
1319 if (call->pkt.ptype == DCERPC_PKT_REQUEST &&
1320 !(call->pkt.pfc_flags & DCERPC_PFC_FLAG_FIRST)) {
1321 struct dcesrv_call_state *call2 = call;
1322 uint32_t alloc_size;
1324 /* we only allow fragmented requests, no other packet types */
1325 if (call->pkt.ptype != DCERPC_PKT_REQUEST) {
1326 return dcesrv_fault(call2, DCERPC_FAULT_OTHER);
1329 /* this is a continuation of an existing call - find the call
1330 then tack it on the end */
1331 call = dcesrv_find_fragmented_call(dce_conn, call2->pkt.call_id);
1333 return dcesrv_fault(call2, DCERPC_FAULT_OTHER);
1336 if (call->pkt.ptype != call2->pkt.ptype) {
1337 /* trying to play silly buggers are we? */
1338 return dcesrv_fault(call2, DCERPC_NCA_S_PROTO_ERROR);
1340 if (memcmp(call->pkt.drep, call2->pkt.drep, sizeof(pkt->drep)) != 0) {
1341 return dcesrv_fault(call2, DCERPC_NCA_S_PROTO_ERROR);
1343 if (call->pkt.call_id != call2->pkt.call_id) {
1344 return dcesrv_fault(call2, DCERPC_NCA_S_PROTO_ERROR);
1346 if (call->pkt.u.request.context_id != call2->pkt.u.request.context_id) {
1347 return dcesrv_fault(call2, DCERPC_NCA_S_PROTO_ERROR);
1349 if (call->pkt.u.request.opnum != call2->pkt.u.request.opnum) {
1350 return dcesrv_fault(call2, DCERPC_NCA_S_PROTO_ERROR);
1353 alloc_size = call->pkt.u.request.stub_and_verifier.length +
1354 call2->pkt.u.request.stub_and_verifier.length;
1355 if (call->pkt.u.request.alloc_hint > alloc_size) {
1356 alloc_size = call->pkt.u.request.alloc_hint;
1359 call->pkt.u.request.stub_and_verifier.data =
1360 talloc_realloc(call,
1361 call->pkt.u.request.stub_and_verifier.data,
1362 uint8_t, alloc_size);
1363 if (!call->pkt.u.request.stub_and_verifier.data) {
1364 return dcesrv_fault(call2, DCERPC_FAULT_OTHER);
1366 memcpy(call->pkt.u.request.stub_and_verifier.data +
1367 call->pkt.u.request.stub_and_verifier.length,
1368 call2->pkt.u.request.stub_and_verifier.data,
1369 call2->pkt.u.request.stub_and_verifier.length);
1370 call->pkt.u.request.stub_and_verifier.length +=
1371 call2->pkt.u.request.stub_and_verifier.length;
1373 call->pkt.pfc_flags |= (call2->pkt.pfc_flags & DCERPC_PFC_FLAG_LAST);
1378 /* this may not be the last pdu in the chain - if its isn't then
1379 just put it on the incoming_fragmented_call_list and wait for the rest */
1380 if (call->pkt.ptype == DCERPC_PKT_REQUEST &&
1381 !(call->pkt.pfc_flags & DCERPC_PFC_FLAG_LAST)) {
1382 dcesrv_call_set_list(call, DCESRV_LIST_FRAGMENTED_CALL_LIST);
1383 return NT_STATUS_OK;
1386 /* This removes any fragments we may have had stashed away */
1387 dcesrv_call_set_list(call, DCESRV_LIST_NONE);
1389 switch (call->pkt.ptype) {
1390 case DCERPC_PKT_BIND:
1391 status = dcesrv_bind(call);
1393 case DCERPC_PKT_AUTH3:
1394 status = dcesrv_auth3(call);
1396 case DCERPC_PKT_ALTER:
1397 status = dcesrv_alter(call);
1399 case DCERPC_PKT_REQUEST:
1400 status = dcesrv_request(call);
1403 status = NT_STATUS_INVALID_PARAMETER;
1407 /* if we are going to be sending a reply then add
1408 it to the list of pending calls. We add it to the end to keep the call
1409 list in the order we will answer */
1410 if (!NT_STATUS_IS_OK(status)) {
1417 _PUBLIC_ NTSTATUS dcesrv_init_context(TALLOC_CTX *mem_ctx,
1418 struct loadparm_context *lp_ctx,
1419 const char **endpoint_servers, struct dcesrv_context **_dce_ctx)
1422 struct dcesrv_context *dce_ctx;
1425 if (!endpoint_servers) {
1426 DEBUG(0,("dcesrv_init_context: no endpoint servers configured\n"));
1427 return NT_STATUS_INTERNAL_ERROR;
1430 dce_ctx = talloc_zero(mem_ctx, struct dcesrv_context);
1431 NT_STATUS_HAVE_NO_MEMORY(dce_ctx);
1433 if (uid_wrapper_enabled()) {
1434 setenv("UID_WRAPPER_MYUID", "1", 1);
1436 dce_ctx->initial_euid = geteuid();
1437 if (uid_wrapper_enabled()) {
1438 unsetenv("UID_WRAPPER_MYUID");
1441 dce_ctx->endpoint_list = NULL;
1442 dce_ctx->lp_ctx = lp_ctx;
1443 dce_ctx->assoc_groups_idr = idr_init(dce_ctx);
1444 NT_STATUS_HAVE_NO_MEMORY(dce_ctx->assoc_groups_idr);
1445 dce_ctx->broken_connections = NULL;
1447 for (i=0;endpoint_servers[i];i++) {
1448 const struct dcesrv_endpoint_server *ep_server;
1450 ep_server = dcesrv_ep_server_byname(endpoint_servers[i]);
1452 DEBUG(0,("dcesrv_init_context: failed to find endpoint server = '%s'\n", endpoint_servers[i]));
1453 return NT_STATUS_INTERNAL_ERROR;
1456 status = ep_server->init_server(dce_ctx, ep_server);
1457 if (!NT_STATUS_IS_OK(status)) {
1458 DEBUG(0,("dcesrv_init_context: failed to init endpoint server = '%s': %s\n", endpoint_servers[i],
1459 nt_errstr(status)));
1464 *_dce_ctx = dce_ctx;
1465 return NT_STATUS_OK;
1468 /* the list of currently registered DCERPC endpoint servers.
1470 static struct ep_server {
1471 struct dcesrv_endpoint_server *ep_server;
1472 } *ep_servers = NULL;
1473 static int num_ep_servers;
1476 register a DCERPC endpoint server.
1478 The 'name' can be later used by other backends to find the operations
1479 structure for this backend.
1481 The 'type' is used to specify whether this is for a disk, printer or IPC$ share
1483 _PUBLIC_ NTSTATUS dcerpc_register_ep_server(const void *_ep_server)
1485 const struct dcesrv_endpoint_server *ep_server = _ep_server;
1487 if (dcesrv_ep_server_byname(ep_server->name) != NULL) {
1488 /* its already registered! */
1489 DEBUG(0,("DCERPC endpoint server '%s' already registered\n",
1491 return NT_STATUS_OBJECT_NAME_COLLISION;
1494 ep_servers = realloc_p(ep_servers, struct ep_server, num_ep_servers+1);
1496 smb_panic("out of memory in dcerpc_register");
1499 ep_servers[num_ep_servers].ep_server = smb_xmemdup(ep_server, sizeof(*ep_server));
1500 ep_servers[num_ep_servers].ep_server->name = smb_xstrdup(ep_server->name);
1504 DEBUG(3,("DCERPC endpoint server '%s' registered\n",
1507 return NT_STATUS_OK;
1511 return the operations structure for a named backend of the specified type
1513 const struct dcesrv_endpoint_server *dcesrv_ep_server_byname(const char *name)
1517 for (i=0;i<num_ep_servers;i++) {
1518 if (strcmp(ep_servers[i].ep_server->name, name) == 0) {
1519 return ep_servers[i].ep_server;
1526 void dcerpc_server_init(struct loadparm_context *lp_ctx)
1528 static bool initialized;
1529 #define _MODULE_PROTO(init) extern NTSTATUS init(void);
1530 STATIC_dcerpc_server_MODULES_PROTO;
1531 init_module_fn static_init[] = { STATIC_dcerpc_server_MODULES };
1532 init_module_fn *shared_init;
1539 shared_init = load_samba_modules(NULL, "dcerpc_server");
1541 run_init_functions(static_init);
1542 run_init_functions(shared_init);
1544 talloc_free(shared_init);
1548 return the DCERPC module version, and the size of some critical types
1549 This can be used by endpoint server modules to either detect compilation errors, or provide
1550 multiple implementations for different smbd compilation options in one module
1552 const struct dcesrv_critical_sizes *dcerpc_module_version(void)
1554 static const struct dcesrv_critical_sizes critical_sizes = {
1555 DCERPC_MODULE_VERSION,
1556 sizeof(struct dcesrv_context),
1557 sizeof(struct dcesrv_endpoint),
1558 sizeof(struct dcesrv_endpoint_server),
1559 sizeof(struct dcesrv_interface),
1560 sizeof(struct dcesrv_if_list),
1561 sizeof(struct dcesrv_connection),
1562 sizeof(struct dcesrv_call_state),
1563 sizeof(struct dcesrv_auth),
1564 sizeof(struct dcesrv_handle)
1567 return &critical_sizes;
1570 static void dcesrv_terminate_connection(struct dcesrv_connection *dce_conn, const char *reason)
1572 struct dcesrv_context *dce_ctx = dce_conn->dce_ctx;
1573 struct stream_connection *srv_conn;
1574 srv_conn = talloc_get_type(dce_conn->transport.private_data,
1575 struct stream_connection);
1577 if (dce_conn->pending_call_list == NULL) {
1578 char *full_reason = talloc_asprintf(dce_conn, "dcesrv: %s", reason);
1580 DLIST_REMOVE(dce_ctx->broken_connections, dce_conn);
1581 stream_terminate_connection(srv_conn, full_reason ? full_reason : reason);
1585 if (dce_conn->terminate != NULL) {
1589 DEBUG(3,("dcesrv: terminating connection due to '%s' defered due to pending calls\n",
1591 dce_conn->terminate = talloc_strdup(dce_conn, reason);
1592 if (dce_conn->terminate == NULL) {
1593 dce_conn->terminate = "dcesrv: defered terminating connection - no memory";
1595 DLIST_ADD_END(dce_ctx->broken_connections, dce_conn);
1598 static void dcesrv_cleanup_broken_connections(struct dcesrv_context *dce_ctx)
1600 struct dcesrv_connection *cur, *next;
1602 next = dce_ctx->broken_connections;
1603 while (next != NULL) {
1607 if (cur->state_flags & DCESRV_CALL_STATE_FLAG_PROCESS_PENDING_CALL) {
1608 struct dcesrv_connection_context *context_cur, *context_next;
1610 context_next = cur->contexts;
1611 while (context_next != NULL) {
1612 context_cur = context_next;
1613 context_next = context_cur->next;
1615 dcesrv_connection_context_destructor(context_cur);
1619 dcesrv_terminate_connection(cur, cur->terminate);
1623 /* We need this include to be able to compile on some plateforms
1624 * (ie. freebsd 7.2) as it seems that <sys/uio.h> is not included
1626 * It has to be that deep because otherwise we have a conflict on
1627 * const struct dcesrv_interface declaration.
1628 * This is mostly due to socket_wrapper defining #define bind swrap_bind
1629 * which conflict with the bind used before.
1631 #include "system/network.h"
1633 struct dcesrv_sock_reply_state {
1634 struct dcesrv_connection *dce_conn;
1635 struct dcesrv_call_state *call;
1639 static void dcesrv_sock_reply_done(struct tevent_req *subreq);
1640 static void dcesrv_call_terminate_step1(struct tevent_req *subreq);
1642 static void dcesrv_sock_report_output_data(struct dcesrv_connection *dce_conn)
1644 struct dcesrv_call_state *call;
1646 call = dce_conn->call_list;
1647 if (!call || !call->replies) {
1651 while (call->replies) {
1652 struct data_blob_list_item *rep = call->replies;
1653 struct dcesrv_sock_reply_state *substate;
1654 struct tevent_req *subreq;
1656 substate = talloc_zero(call, struct dcesrv_sock_reply_state);
1658 dcesrv_terminate_connection(dce_conn, "no memory");
1662 substate->dce_conn = dce_conn;
1663 substate->call = NULL;
1665 DLIST_REMOVE(call->replies, rep);
1667 if (call->replies == NULL && call->terminate_reason == NULL) {
1668 substate->call = call;
1671 substate->iov.iov_base = (void *) rep->blob.data;
1672 substate->iov.iov_len = rep->blob.length;
1674 subreq = tstream_writev_queue_send(substate,
1675 dce_conn->event_ctx,
1677 dce_conn->send_queue,
1680 dcesrv_terminate_connection(dce_conn, "no memory");
1683 tevent_req_set_callback(subreq, dcesrv_sock_reply_done,
1687 if (call->terminate_reason != NULL) {
1688 struct tevent_req *subreq;
1690 subreq = tevent_queue_wait_send(call,
1691 dce_conn->event_ctx,
1692 dce_conn->send_queue);
1694 dcesrv_terminate_connection(dce_conn, __location__);
1697 tevent_req_set_callback(subreq, dcesrv_call_terminate_step1,
1701 DLIST_REMOVE(call->conn->call_list, call);
1702 call->list = DCESRV_LIST_NONE;
1705 static void dcesrv_sock_reply_done(struct tevent_req *subreq)
1707 struct dcesrv_sock_reply_state *substate = tevent_req_callback_data(subreq,
1708 struct dcesrv_sock_reply_state);
1712 struct dcesrv_call_state *call = substate->call;
1714 ret = tstream_writev_queue_recv(subreq, &sys_errno);
1715 TALLOC_FREE(subreq);
1717 status = map_nt_error_from_unix_common(sys_errno);
1718 dcesrv_terminate_connection(substate->dce_conn, nt_errstr(status));
1722 talloc_free(substate);
1728 static void dcesrv_call_terminate_step2(struct tevent_req *subreq);
1730 static void dcesrv_call_terminate_step1(struct tevent_req *subreq)
1732 struct dcesrv_call_state *call = tevent_req_callback_data(subreq,
1733 struct dcesrv_call_state);
1737 /* make sure we stop send queue before removing subreq */
1738 tevent_queue_stop(call->conn->send_queue);
1740 ok = tevent_queue_wait_recv(subreq);
1741 TALLOC_FREE(subreq);
1743 dcesrv_terminate_connection(call->conn, __location__);
1747 /* disconnect after 200 usecs */
1748 tv = timeval_current_ofs_usec(200);
1749 subreq = tevent_wakeup_send(call, call->conn->event_ctx, tv);
1750 if (subreq == NULL) {
1751 dcesrv_terminate_connection(call->conn, __location__);
1754 tevent_req_set_callback(subreq, dcesrv_call_terminate_step2,
1758 static void dcesrv_call_terminate_step2(struct tevent_req *subreq)
1760 struct dcesrv_call_state *call = tevent_req_callback_data(subreq,
1761 struct dcesrv_call_state);
1764 ok = tevent_wakeup_recv(subreq);
1765 TALLOC_FREE(subreq);
1767 dcesrv_terminate_connection(call->conn, __location__);
1771 dcesrv_terminate_connection(call->conn, call->terminate_reason);
1774 struct dcesrv_socket_context {
1775 const struct dcesrv_endpoint *endpoint;
1776 struct dcesrv_context *dcesrv_ctx;
1780 static void dcesrv_read_fragment_done(struct tevent_req *subreq);
1782 static void dcesrv_sock_accept(struct stream_connection *srv_conn)
1785 struct dcesrv_socket_context *dcesrv_sock =
1786 talloc_get_type(srv_conn->private_data, struct dcesrv_socket_context);
1787 enum dcerpc_transport_t transport =
1788 dcerpc_binding_get_transport(dcesrv_sock->endpoint->ep_description);
1789 struct dcesrv_connection *dcesrv_conn = NULL;
1791 struct tevent_req *subreq;
1792 struct loadparm_context *lp_ctx = dcesrv_sock->dcesrv_ctx->lp_ctx;
1794 dcesrv_cleanup_broken_connections(dcesrv_sock->dcesrv_ctx);
1796 if (!srv_conn->session_info) {
1797 status = auth_anonymous_session_info(srv_conn,
1799 &srv_conn->session_info);
1800 if (!NT_STATUS_IS_OK(status)) {
1801 DEBUG(0,("dcesrv_sock_accept: auth_anonymous_session_info failed: %s\n",
1802 nt_errstr(status)));
1803 stream_terminate_connection(srv_conn, nt_errstr(status));
1808 status = dcesrv_endpoint_connect(dcesrv_sock->dcesrv_ctx,
1810 dcesrv_sock->endpoint,
1811 srv_conn->session_info,
1812 srv_conn->event.ctx,
1814 srv_conn->server_id,
1815 DCESRV_CALL_STATE_FLAG_MAY_ASYNC,
1817 if (!NT_STATUS_IS_OK(status)) {
1818 DEBUG(0,("dcesrv_sock_accept: dcesrv_endpoint_connect failed: %s\n",
1819 nt_errstr(status)));
1820 stream_terminate_connection(srv_conn, nt_errstr(status));
1824 dcesrv_conn->transport.private_data = srv_conn;
1825 dcesrv_conn->transport.report_output_data = dcesrv_sock_report_output_data;
1827 TALLOC_FREE(srv_conn->event.fde);
1829 dcesrv_conn->send_queue = tevent_queue_create(dcesrv_conn, "dcesrv send queue");
1830 if (!dcesrv_conn->send_queue) {
1831 status = NT_STATUS_NO_MEMORY;
1832 DEBUG(0,("dcesrv_sock_accept: tevent_queue_create(%s)\n",
1833 nt_errstr(status)));
1834 stream_terminate_connection(srv_conn, nt_errstr(status));
1838 if (transport == NCACN_NP) {
1839 dcesrv_conn->auth_state.session_key = dcesrv_inherited_session_key;
1840 dcesrv_conn->stream = talloc_move(dcesrv_conn,
1841 &srv_conn->tstream);
1843 ret = tstream_bsd_existing_socket(dcesrv_conn,
1844 socket_get_fd(srv_conn->socket),
1845 &dcesrv_conn->stream);
1847 status = map_nt_error_from_unix_common(errno);
1848 DEBUG(0, ("dcesrv_sock_accept: "
1849 "failed to setup tstream: %s\n",
1850 nt_errstr(status)));
1851 stream_terminate_connection(srv_conn, nt_errstr(status));
1854 socket_set_flags(srv_conn->socket, SOCKET_FLAG_NOCLOSE);
1857 dcesrv_conn->local_address = srv_conn->local_address;
1858 dcesrv_conn->remote_address = srv_conn->remote_address;
1860 if (transport == NCALRPC) {
1864 ret = getpeereid(socket_get_fd(srv_conn->socket), &uid, &gid);
1866 status = map_nt_error_from_unix_common(errno);
1867 DEBUG(0, ("dcesrv_sock_accept: "
1868 "getpeereid() failed for NCALRPC: %s\n",
1869 nt_errstr(status)));
1870 stream_terminate_connection(srv_conn, nt_errstr(status));
1873 if (uid == dcesrv_conn->dce_ctx->initial_euid) {
1874 struct tsocket_address *r = NULL;
1876 ret = tsocket_address_unix_from_path(dcesrv_conn,
1877 "/root/ncalrpc_as_system",
1880 status = map_nt_error_from_unix_common(errno);
1881 DEBUG(0, ("dcesrv_sock_accept: "
1882 "tsocket_address_unix_from_path() failed for NCALRPC: %s\n",
1883 nt_errstr(status)));
1884 stream_terminate_connection(srv_conn, nt_errstr(status));
1887 dcesrv_conn->remote_address = r;
1891 srv_conn->private_data = dcesrv_conn;
1893 irpc_add_name(srv_conn->msg_ctx, "rpc_server");
1895 subreq = dcerpc_read_ncacn_packet_send(dcesrv_conn,
1896 dcesrv_conn->event_ctx,
1897 dcesrv_conn->stream);
1899 status = NT_STATUS_NO_MEMORY;
1900 DEBUG(0,("dcesrv_sock_accept: dcerpc_read_fragment_buffer_send(%s)\n",
1901 nt_errstr(status)));
1902 stream_terminate_connection(srv_conn, nt_errstr(status));
1905 tevent_req_set_callback(subreq, dcesrv_read_fragment_done, dcesrv_conn);
1910 static void dcesrv_read_fragment_done(struct tevent_req *subreq)
1912 struct dcesrv_connection *dce_conn = tevent_req_callback_data(subreq,
1913 struct dcesrv_connection);
1914 struct dcesrv_context *dce_ctx = dce_conn->dce_ctx;
1915 struct ncacn_packet *pkt;
1919 if (dce_conn->terminate) {
1921 * if the current connection is broken
1922 * we need to clean it up before any other connection
1924 dcesrv_terminate_connection(dce_conn, dce_conn->terminate);
1925 dcesrv_cleanup_broken_connections(dce_ctx);
1929 dcesrv_cleanup_broken_connections(dce_ctx);
1931 status = dcerpc_read_ncacn_packet_recv(subreq, dce_conn,
1933 TALLOC_FREE(subreq);
1934 if (!NT_STATUS_IS_OK(status)) {
1935 dcesrv_terminate_connection(dce_conn, nt_errstr(status));
1939 status = dcesrv_process_ncacn_packet(dce_conn, pkt, buffer);
1940 if (!NT_STATUS_IS_OK(status)) {
1941 dcesrv_terminate_connection(dce_conn, nt_errstr(status));
1945 subreq = dcerpc_read_ncacn_packet_send(dce_conn,
1946 dce_conn->event_ctx,
1949 status = NT_STATUS_NO_MEMORY;
1950 dcesrv_terminate_connection(dce_conn, nt_errstr(status));
1953 tevent_req_set_callback(subreq, dcesrv_read_fragment_done, dce_conn);
1956 static void dcesrv_sock_recv(struct stream_connection *conn, uint16_t flags)
1958 struct dcesrv_connection *dce_conn = talloc_get_type(conn->private_data,
1959 struct dcesrv_connection);
1960 dcesrv_terminate_connection(dce_conn, "dcesrv_sock_recv triggered");
1963 static void dcesrv_sock_send(struct stream_connection *conn, uint16_t flags)
1965 struct dcesrv_connection *dce_conn = talloc_get_type(conn->private_data,
1966 struct dcesrv_connection);
1967 dcesrv_terminate_connection(dce_conn, "dcesrv_sock_send triggered");
1971 static const struct stream_server_ops dcesrv_stream_ops = {
1973 .accept_connection = dcesrv_sock_accept,
1974 .recv_handler = dcesrv_sock_recv,
1975 .send_handler = dcesrv_sock_send,
1978 static NTSTATUS dcesrv_add_ep_unix(struct dcesrv_context *dce_ctx,
1979 struct loadparm_context *lp_ctx,
1980 struct dcesrv_endpoint *e,
1981 struct tevent_context *event_ctx, const struct model_ops *model_ops)
1983 struct dcesrv_socket_context *dcesrv_sock;
1986 const char *endpoint;
1988 dcesrv_sock = talloc_zero(event_ctx, struct dcesrv_socket_context);
1989 NT_STATUS_HAVE_NO_MEMORY(dcesrv_sock);
1991 /* remember the endpoint of this socket */
1992 dcesrv_sock->endpoint = e;
1993 dcesrv_sock->dcesrv_ctx = talloc_reference(dcesrv_sock, dce_ctx);
1995 endpoint = dcerpc_binding_get_string_option(e->ep_description, "endpoint");
1997 status = stream_setup_socket(dcesrv_sock, event_ctx, lp_ctx,
1998 model_ops, &dcesrv_stream_ops,
1999 "unix", endpoint, &port,
2000 lpcfg_socket_options(lp_ctx),
2002 if (!NT_STATUS_IS_OK(status)) {
2003 DEBUG(0,("service_setup_stream_socket(path=%s) failed - %s\n",
2004 endpoint, nt_errstr(status)));
2010 static NTSTATUS dcesrv_add_ep_ncalrpc(struct dcesrv_context *dce_ctx,
2011 struct loadparm_context *lp_ctx,
2012 struct dcesrv_endpoint *e,
2013 struct tevent_context *event_ctx, const struct model_ops *model_ops)
2015 struct dcesrv_socket_context *dcesrv_sock;
2019 const char *endpoint;
2021 endpoint = dcerpc_binding_get_string_option(e->ep_description, "endpoint");
2023 if (endpoint == NULL) {
2025 * No identifier specified: use DEFAULT.
2027 * TODO: DO NOT hardcode this value anywhere else. Rather, specify
2028 * no endpoint and let the epmapper worry about it.
2030 endpoint = "DEFAULT";
2031 status = dcerpc_binding_set_string_option(e->ep_description,
2034 if (!NT_STATUS_IS_OK(status)) {
2035 DEBUG(0,("dcerpc_binding_set_string_option() failed - %s\n",
2036 nt_errstr(status)));
2041 full_path = talloc_asprintf(dce_ctx, "%s/%s", lpcfg_ncalrpc_dir(lp_ctx),
2044 dcesrv_sock = talloc_zero(event_ctx, struct dcesrv_socket_context);
2045 NT_STATUS_HAVE_NO_MEMORY(dcesrv_sock);
2047 /* remember the endpoint of this socket */
2048 dcesrv_sock->endpoint = e;
2049 dcesrv_sock->dcesrv_ctx = talloc_reference(dcesrv_sock, dce_ctx);
2051 status = stream_setup_socket(dcesrv_sock, event_ctx, lp_ctx,
2052 model_ops, &dcesrv_stream_ops,
2053 "unix", full_path, &port,
2054 lpcfg_socket_options(lp_ctx),
2056 if (!NT_STATUS_IS_OK(status)) {
2057 DEBUG(0,("service_setup_stream_socket(identifier=%s,path=%s) failed - %s\n",
2058 endpoint, full_path, nt_errstr(status)));
2063 static NTSTATUS dcesrv_add_ep_np(struct dcesrv_context *dce_ctx,
2064 struct loadparm_context *lp_ctx,
2065 struct dcesrv_endpoint *e,
2066 struct tevent_context *event_ctx, const struct model_ops *model_ops)
2068 struct dcesrv_socket_context *dcesrv_sock;
2070 const char *endpoint;
2072 endpoint = dcerpc_binding_get_string_option(e->ep_description, "endpoint");
2073 if (endpoint == NULL) {
2074 DEBUG(0, ("Endpoint mandatory for named pipes\n"));
2075 return NT_STATUS_INVALID_PARAMETER;
2078 dcesrv_sock = talloc_zero(event_ctx, struct dcesrv_socket_context);
2079 NT_STATUS_HAVE_NO_MEMORY(dcesrv_sock);
2081 /* remember the endpoint of this socket */
2082 dcesrv_sock->endpoint = e;
2083 dcesrv_sock->dcesrv_ctx = talloc_reference(dcesrv_sock, dce_ctx);
2085 status = tstream_setup_named_pipe(dce_ctx, event_ctx, lp_ctx,
2086 model_ops, &dcesrv_stream_ops,
2089 if (!NT_STATUS_IS_OK(status)) {
2090 DEBUG(0,("stream_setup_named_pipe(pipe=%s) failed - %s\n",
2091 endpoint, nt_errstr(status)));
2095 return NT_STATUS_OK;
2099 add a socket address to the list of events, one event per dcerpc endpoint
2101 static NTSTATUS add_socket_rpc_tcp_iface(struct dcesrv_context *dce_ctx, struct dcesrv_endpoint *e,
2102 struct tevent_context *event_ctx, const struct model_ops *model_ops,
2103 const char *address)
2105 struct dcesrv_socket_context *dcesrv_sock;
2108 const char *endpoint;
2111 endpoint = dcerpc_binding_get_string_option(e->ep_description, "endpoint");
2112 if (endpoint != NULL) {
2113 port = atoi(endpoint);
2116 dcesrv_sock = talloc_zero(event_ctx, struct dcesrv_socket_context);
2117 NT_STATUS_HAVE_NO_MEMORY(dcesrv_sock);
2119 /* remember the endpoint of this socket */
2120 dcesrv_sock->endpoint = e;
2121 dcesrv_sock->dcesrv_ctx = talloc_reference(dcesrv_sock, dce_ctx);
2123 status = stream_setup_socket(dcesrv_sock, event_ctx, dce_ctx->lp_ctx,
2124 model_ops, &dcesrv_stream_ops,
2125 "ip", address, &port,
2126 lpcfg_socket_options(dce_ctx->lp_ctx),
2128 if (!NT_STATUS_IS_OK(status)) {
2129 DEBUG(0,("service_setup_stream_socket(address=%s,port=%u) failed - %s\n",
2130 address, port, nt_errstr(status)));
2134 snprintf(port_str, sizeof(port_str), "%u", port);
2136 status = dcerpc_binding_set_string_option(e->ep_description,
2137 "endpoint", port_str);
2138 if (!NT_STATUS_IS_OK(status)) {
2139 DEBUG(0,("dcerpc_binding_set_string_option(endpoint, %s) failed - %s\n",
2140 port_str, nt_errstr(status)));
2144 return NT_STATUS_OK;
2147 #include "lib/socket/netif.h" /* Included here to work around the fact that socket_wrapper redefines bind() */
2149 static NTSTATUS dcesrv_add_ep_tcp(struct dcesrv_context *dce_ctx,
2150 struct loadparm_context *lp_ctx,
2151 struct dcesrv_endpoint *e,
2152 struct tevent_context *event_ctx, const struct model_ops *model_ops)
2156 /* Add TCP/IP sockets */
2157 if (lpcfg_interfaces(lp_ctx) && lpcfg_bind_interfaces_only(lp_ctx)) {
2160 struct interface *ifaces;
2162 load_interface_list(dce_ctx, lp_ctx, &ifaces);
2164 num_interfaces = iface_list_count(ifaces);
2165 for(i = 0; i < num_interfaces; i++) {
2166 const char *address = iface_list_n_ip(ifaces, i);
2167 status = add_socket_rpc_tcp_iface(dce_ctx, e, event_ctx, model_ops, address);
2168 NT_STATUS_NOT_OK_RETURN(status);
2174 wcard = iface_list_wildcard(dce_ctx);
2175 NT_STATUS_HAVE_NO_MEMORY(wcard);
2176 for (i=0; wcard[i]; i++) {
2177 status = add_socket_rpc_tcp_iface(dce_ctx, e, event_ctx, model_ops, wcard[i]);
2178 if (NT_STATUS_IS_OK(status)) {
2183 if (num_binds == 0) {
2184 return NT_STATUS_INVALID_PARAMETER_MIX;
2188 return NT_STATUS_OK;
2191 NTSTATUS dcesrv_add_ep(struct dcesrv_context *dce_ctx,
2192 struct loadparm_context *lp_ctx,
2193 struct dcesrv_endpoint *e,
2194 struct tevent_context *event_ctx,
2195 const struct model_ops *model_ops)
2197 enum dcerpc_transport_t transport =
2198 dcerpc_binding_get_transport(e->ep_description);
2200 switch (transport) {
2201 case NCACN_UNIX_STREAM:
2202 return dcesrv_add_ep_unix(dce_ctx, lp_ctx, e, event_ctx, model_ops);
2205 return dcesrv_add_ep_ncalrpc(dce_ctx, lp_ctx, e, event_ctx, model_ops);
2208 return dcesrv_add_ep_tcp(dce_ctx, lp_ctx, e, event_ctx, model_ops);
2211 return dcesrv_add_ep_np(dce_ctx, lp_ctx, e, event_ctx, model_ops);
2214 return NT_STATUS_NOT_SUPPORTED;
2220 * retrieve credentials from a dce_call
2222 _PUBLIC_ struct cli_credentials *dcesrv_call_credentials(struct dcesrv_call_state *dce_call)
2224 return dce_call->conn->auth_state.session_info->credentials;
2228 * returns true if this is an authenticated call
2230 _PUBLIC_ bool dcesrv_call_authenticated(struct dcesrv_call_state *dce_call)
2232 enum security_user_level level;
2233 level = security_session_user_level(dce_call->conn->auth_state.session_info, NULL);
2234 return level >= SECURITY_USER;
2238 * retrieve account_name for a dce_call
2240 _PUBLIC_ const char *dcesrv_call_account_name(struct dcesrv_call_state *dce_call)
2242 return dce_call->context->conn->auth_state.session_info->info->account_name;