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->allow_bind = true;
412 p->max_recv_frag = 5840;
413 p->max_xmit_frag = 5840;
420 move a call from an existing linked list to the specified list. This
421 prevents bugs where we forget to remove the call from a previous
424 static void dcesrv_call_set_list(struct dcesrv_call_state *call,
425 enum dcesrv_call_list list)
427 switch (call->list) {
428 case DCESRV_LIST_NONE:
430 case DCESRV_LIST_CALL_LIST:
431 DLIST_REMOVE(call->conn->call_list, call);
433 case DCESRV_LIST_FRAGMENTED_CALL_LIST:
434 DLIST_REMOVE(call->conn->incoming_fragmented_call_list, call);
436 case DCESRV_LIST_PENDING_CALL_LIST:
437 DLIST_REMOVE(call->conn->pending_call_list, call);
442 case DCESRV_LIST_NONE:
444 case DCESRV_LIST_CALL_LIST:
445 DLIST_ADD_END(call->conn->call_list, call);
447 case DCESRV_LIST_FRAGMENTED_CALL_LIST:
448 DLIST_ADD_END(call->conn->incoming_fragmented_call_list, call);
450 case DCESRV_LIST_PENDING_CALL_LIST:
451 DLIST_ADD_END(call->conn->pending_call_list, call);
456 static void dcesrv_call_disconnect_after(struct dcesrv_call_state *call,
459 if (call->conn->terminate != NULL) {
463 call->conn->allow_bind = false;
464 call->conn->allow_alter = false;
465 call->conn->allow_auth3 = false;
466 call->conn->allow_request = false;
468 call->terminate_reason = talloc_strdup(call, reason);
469 if (call->terminate_reason == NULL) {
470 call->terminate_reason = __location__;
475 return a dcerpc bind_nak
477 static NTSTATUS dcesrv_bind_nak(struct dcesrv_call_state *call, uint32_t reason)
479 struct ncacn_packet pkt;
480 struct dcerpc_bind_nak_version version;
481 struct data_blob_list_item *rep;
483 static const uint8_t _pad[3] = { 0, };
486 * We add the call to the pending_call_list
487 * in order to defer the termination.
489 dcesrv_call_disconnect_after(call, "dcesrv_bind_nak");
491 /* setup a bind_nak */
492 dcesrv_init_hdr(&pkt, lpcfg_rpc_big_endian(call->conn->dce_ctx->lp_ctx));
494 pkt.call_id = call->pkt.call_id;
495 pkt.ptype = DCERPC_PKT_BIND_NAK;
496 pkt.pfc_flags = DCERPC_PFC_FLAG_FIRST | DCERPC_PFC_FLAG_LAST;
497 pkt.u.bind_nak.reject_reason = reason;
498 version.rpc_vers = 5;
499 version.rpc_vers_minor = 0;
500 pkt.u.bind_nak.num_versions = 1;
501 pkt.u.bind_nak.versions = &version;
502 pkt.u.bind_nak._pad = data_blob_const(_pad, sizeof(_pad));
504 rep = talloc_zero(call, struct data_blob_list_item);
506 return NT_STATUS_NO_MEMORY;
509 status = ncacn_push_auth(&rep->blob, call, &pkt, NULL);
510 if (!NT_STATUS_IS_OK(status)) {
514 dcerpc_set_frag_length(&rep->blob, rep->blob.length);
516 DLIST_ADD_END(call->replies, rep);
517 dcesrv_call_set_list(call, DCESRV_LIST_CALL_LIST);
519 if (call->conn->call_list && call->conn->call_list->replies) {
520 if (call->conn->transport.report_output_data) {
521 call->conn->transport.report_output_data(call->conn);
528 static NTSTATUS dcesrv_fault_disconnect(struct dcesrv_call_state *call,
532 * We add the call to the pending_call_list
533 * in order to defer the termination.
535 dcesrv_call_disconnect_after(call, "dcesrv_fault_disconnect");
537 return dcesrv_fault_with_flags(call, fault_code,
538 DCERPC_PFC_FLAG_DID_NOT_EXECUTE);
541 static int dcesrv_connection_context_destructor(struct dcesrv_connection_context *c)
543 DLIST_REMOVE(c->conn->contexts, c);
545 if (c->iface && c->iface->unbind) {
546 c->iface->unbind(c, c->iface);
553 static void dcesrv_prepare_context_auth(struct dcesrv_call_state *dce_call)
555 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
556 const struct dcesrv_endpoint *endpoint = dce_call->conn->endpoint;
557 enum dcerpc_transport_t transport =
558 dcerpc_binding_get_transport(endpoint->ep_description);
559 struct dcesrv_connection_context *context = dce_call->context;
560 const struct dcesrv_interface *iface = context->iface;
562 context->min_auth_level = DCERPC_AUTH_LEVEL_NONE;
564 if (transport == NCALRPC) {
565 context->allow_connect = true;
570 * allow overwrite per interface
571 * allow dcerpc auth level connect:<interface>
573 context->allow_connect = lpcfg_allow_dcerpc_auth_level_connect(lp_ctx);
574 context->allow_connect = lpcfg_parm_bool(lp_ctx, NULL,
575 "allow dcerpc auth level connect",
577 context->allow_connect);
580 NTSTATUS dcesrv_interface_bind_require_integrity(struct dcesrv_call_state *dce_call,
581 const struct dcesrv_interface *iface)
583 if (dce_call->context == NULL) {
584 return NT_STATUS_INTERNAL_ERROR;
587 dce_call->context->min_auth_level = DCERPC_AUTH_LEVEL_INTEGRITY;
591 NTSTATUS dcesrv_interface_bind_require_privacy(struct dcesrv_call_state *dce_call,
592 const struct dcesrv_interface *iface)
594 if (dce_call->context == NULL) {
595 return NT_STATUS_INTERNAL_ERROR;
598 dce_call->context->min_auth_level = DCERPC_AUTH_LEVEL_PRIVACY;
602 _PUBLIC_ NTSTATUS dcesrv_interface_bind_reject_connect(struct dcesrv_call_state *dce_call,
603 const struct dcesrv_interface *iface)
605 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
606 const struct dcesrv_endpoint *endpoint = dce_call->conn->endpoint;
607 enum dcerpc_transport_t transport =
608 dcerpc_binding_get_transport(endpoint->ep_description);
609 struct dcesrv_connection_context *context = dce_call->context;
611 if (context == NULL) {
612 return NT_STATUS_INTERNAL_ERROR;
615 if (transport == NCALRPC) {
616 context->allow_connect = true;
621 * allow overwrite per interface
622 * allow dcerpc auth level connect:<interface>
624 context->allow_connect = false;
625 context->allow_connect = lpcfg_parm_bool(lp_ctx, NULL,
626 "allow dcerpc auth level connect",
628 context->allow_connect);
632 _PUBLIC_ NTSTATUS dcesrv_interface_bind_allow_connect(struct dcesrv_call_state *dce_call,
633 const struct dcesrv_interface *iface)
635 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
636 const struct dcesrv_endpoint *endpoint = dce_call->conn->endpoint;
637 enum dcerpc_transport_t transport =
638 dcerpc_binding_get_transport(endpoint->ep_description);
639 struct dcesrv_connection_context *context = dce_call->context;
641 if (context == NULL) {
642 return NT_STATUS_INTERNAL_ERROR;
645 if (transport == NCALRPC) {
646 context->allow_connect = true;
651 * allow overwrite per interface
652 * allow dcerpc auth level connect:<interface>
654 context->allow_connect = true;
655 context->allow_connect = lpcfg_parm_bool(lp_ctx, NULL,
656 "allow dcerpc auth level connect",
658 context->allow_connect);
663 handle a bind request
665 static NTSTATUS dcesrv_bind(struct dcesrv_call_state *call)
667 uint32_t if_version, transfer_syntax_version;
668 struct GUID uuid, *transfer_syntax_uuid;
669 struct ncacn_packet pkt;
670 struct data_blob_list_item *rep;
672 uint32_t result=0, reason=0;
674 const struct dcesrv_interface *iface;
675 uint32_t extra_flags = 0;
676 uint16_t max_req = 0;
677 uint16_t max_rep = 0;
678 const char *ep_prefix = "";
679 const char *endpoint = NULL;
681 status = dcerpc_verify_ncacn_packet_header(&call->pkt,
683 call->pkt.u.bind.auth_info.length,
684 0, /* required flags */
685 DCERPC_PFC_FLAG_FIRST |
686 DCERPC_PFC_FLAG_LAST |
687 DCERPC_PFC_FLAG_SUPPORT_HEADER_SIGN |
688 0x08 | /* this is not defined, but should be ignored */
689 DCERPC_PFC_FLAG_CONC_MPX |
690 DCERPC_PFC_FLAG_DID_NOT_EXECUTE |
691 DCERPC_PFC_FLAG_MAYBE |
692 DCERPC_PFC_FLAG_OBJECT_UUID);
693 if (!NT_STATUS_IS_OK(status)) {
694 return dcesrv_bind_nak(call,
695 DCERPC_BIND_NAK_REASON_PROTOCOL_VERSION_NOT_SUPPORTED);
698 /* max_recv_frag and max_xmit_frag result always in the same value! */
699 max_req = MIN(call->pkt.u.bind.max_xmit_frag,
700 call->pkt.u.bind.max_recv_frag);
702 * The values are between 2048 and 5840 tested against Windows 2012R2
703 * via ncacn_ip_tcp on port 135.
705 max_req = MAX(2048, max_req);
706 max_rep = MIN(max_req, call->conn->max_recv_frag);
707 /* They are truncated to an 8 byte boundary. */
710 /* max_recv_frag and max_xmit_frag result always in the same value! */
711 call->conn->max_recv_frag = max_rep;
712 call->conn->max_xmit_frag = max_rep;
715 if provided, check the assoc_group is valid
717 if (call->pkt.u.bind.assoc_group_id != 0 &&
718 lpcfg_parm_bool(call->conn->dce_ctx->lp_ctx, NULL, "dcesrv","assoc group checking", true) &&
719 dcesrv_assoc_group_find(call->conn->dce_ctx, call->pkt.u.bind.assoc_group_id) == NULL) {
720 return dcesrv_bind_nak(call, 0);
723 if (call->pkt.u.bind.num_contexts < 1 ||
724 call->pkt.u.bind.ctx_list[0].num_transfer_syntaxes < 1) {
725 return dcesrv_bind_nak(call, 0);
728 context_id = call->pkt.u.bind.ctx_list[0].context_id;
729 if_version = call->pkt.u.bind.ctx_list[0].abstract_syntax.if_version;
730 uuid = call->pkt.u.bind.ctx_list[0].abstract_syntax.uuid;
732 transfer_syntax_version = call->pkt.u.bind.ctx_list[0].transfer_syntaxes[0].if_version;
733 transfer_syntax_uuid = &call->pkt.u.bind.ctx_list[0].transfer_syntaxes[0].uuid;
734 if (!GUID_equal(&ndr_transfer_syntax_ndr.uuid, transfer_syntax_uuid) != 0 ||
735 ndr_transfer_syntax_ndr.if_version != transfer_syntax_version) {
736 char *uuid_str = GUID_string(call, transfer_syntax_uuid);
737 /* we only do NDR encoded dcerpc */
738 DEBUG(0,("Non NDR transfer syntax requested - %s\n", uuid_str));
739 talloc_free(uuid_str);
740 return dcesrv_bind_nak(call, 0);
743 iface = find_interface_by_uuid(call->conn->endpoint, &uuid, if_version);
745 char *uuid_str = GUID_string(call, &uuid);
746 DEBUG(2,("Request for unknown dcerpc interface %s/%d\n", uuid_str, if_version));
747 talloc_free(uuid_str);
749 /* we don't know about that interface */
750 result = DCERPC_BIND_PROVIDER_REJECT;
751 reason = DCERPC_BIND_REASON_ASYNTAX;
755 /* add this context to the list of available context_ids */
756 struct dcesrv_connection_context *context = talloc_zero(call->conn,
757 struct dcesrv_connection_context);
758 if (context == NULL) {
759 return dcesrv_bind_nak(call, 0);
761 context->conn = call->conn;
762 context->iface = iface;
763 context->context_id = context_id;
764 if (call->pkt.u.bind.assoc_group_id != 0) {
765 context->assoc_group = dcesrv_assoc_group_reference(context,
767 call->pkt.u.bind.assoc_group_id);
769 context->assoc_group = dcesrv_assoc_group_new(context, call->conn->dce_ctx);
771 if (context->assoc_group == NULL) {
772 talloc_free(context);
773 return dcesrv_bind_nak(call, 0);
775 context->private_data = NULL;
776 DLIST_ADD(call->conn->contexts, context);
777 call->context = context;
778 talloc_set_destructor(context, dcesrv_connection_context_destructor);
780 dcesrv_prepare_context_auth(call);
782 status = iface->bind(call, iface, if_version);
783 if (!NT_STATUS_IS_OK(status)) {
784 char *uuid_str = GUID_string(call, &uuid);
785 DEBUG(2,("Request for dcerpc interface %s/%d rejected: %s\n",
786 uuid_str, if_version, nt_errstr(status)));
787 talloc_free(uuid_str);
788 /* we don't want to trigger the iface->unbind() hook */
789 context->iface = NULL;
790 talloc_free(call->context);
791 call->context = NULL;
792 return dcesrv_bind_nak(call, 0);
796 if ((call->pkt.pfc_flags & DCERPC_PFC_FLAG_CONC_MPX) &&
797 (call->state_flags & DCESRV_CALL_STATE_FLAG_MULTIPLEXED)) {
798 call->context->conn->state_flags |= DCESRV_CALL_STATE_FLAG_MULTIPLEXED;
799 extra_flags |= DCERPC_PFC_FLAG_CONC_MPX;
802 if (call->state_flags & DCESRV_CALL_STATE_FLAG_PROCESS_PENDING_CALL) {
803 call->context->conn->state_flags |= DCESRV_CALL_STATE_FLAG_PROCESS_PENDING_CALL;
806 /* handle any authentication that is being requested */
807 if (!dcesrv_auth_bind(call)) {
808 talloc_free(call->context);
809 call->context = NULL;
810 return dcesrv_bind_nak(call, DCERPC_BIND_REASON_INVALID_AUTH_TYPE);
813 /* setup a bind_ack */
814 dcesrv_init_hdr(&pkt, lpcfg_rpc_big_endian(call->conn->dce_ctx->lp_ctx));
816 pkt.call_id = call->pkt.call_id;
817 pkt.ptype = DCERPC_PKT_BIND_ACK;
818 pkt.pfc_flags = DCERPC_PFC_FLAG_FIRST | DCERPC_PFC_FLAG_LAST | extra_flags;
819 pkt.u.bind_ack.max_xmit_frag = call->conn->max_xmit_frag;
820 pkt.u.bind_ack.max_recv_frag = call->conn->max_recv_frag;
823 make it possible for iface->bind() to specify the assoc_group_id
824 This helps the openchange mapiproxy plugin to work correctly.
829 pkt.u.bind_ack.assoc_group_id = call->context->assoc_group->id;
831 pkt.u.bind_ack.assoc_group_id = DUMMY_ASSOC_GROUP;
835 endpoint = dcerpc_binding_get_string_option(
836 call->conn->endpoint->ep_description,
840 if (endpoint == NULL) {
844 if (strncasecmp(endpoint, "\\pipe\\", 6) == 0) {
846 * TODO: check if this is really needed
848 * Or if we should fix this in our idl files.
850 ep_prefix = "\\PIPE\\";
854 pkt.u.bind_ack.secondary_address = talloc_asprintf(call, "%s%s",
857 if (pkt.u.bind_ack.secondary_address == NULL) {
858 TALLOC_FREE(call->context);
859 return NT_STATUS_NO_MEMORY;
861 pkt.u.bind_ack.num_results = 1;
862 pkt.u.bind_ack.ctx_list = talloc_zero(call, struct dcerpc_ack_ctx);
863 if (!pkt.u.bind_ack.ctx_list) {
864 talloc_free(call->context);
865 call->context = NULL;
866 return NT_STATUS_NO_MEMORY;
868 pkt.u.bind_ack.ctx_list[0].result = result;
869 pkt.u.bind_ack.ctx_list[0].reason.value = reason;
870 pkt.u.bind_ack.ctx_list[0].syntax = ndr_transfer_syntax_ndr;
871 pkt.u.bind_ack.auth_info = data_blob(NULL, 0);
873 status = dcesrv_auth_bind_ack(call, &pkt);
874 if (!NT_STATUS_IS_OK(status)) {
875 talloc_free(call->context);
876 call->context = NULL;
877 return dcesrv_bind_nak(call, 0);
880 rep = talloc_zero(call, struct data_blob_list_item);
882 talloc_free(call->context);
883 call->context = NULL;
884 return NT_STATUS_NO_MEMORY;
887 status = ncacn_push_auth(&rep->blob, call, &pkt,
888 call->out_auth_info);
889 if (!NT_STATUS_IS_OK(status)) {
890 talloc_free(call->context);
891 call->context = NULL;
895 dcerpc_set_frag_length(&rep->blob, rep->blob.length);
897 DLIST_ADD_END(call->replies, rep);
898 dcesrv_call_set_list(call, DCESRV_LIST_CALL_LIST);
900 if (call->conn->call_list && call->conn->call_list->replies) {
901 if (call->conn->transport.report_output_data) {
902 call->conn->transport.report_output_data(call->conn);
911 handle a auth3 request
913 static NTSTATUS dcesrv_auth3(struct dcesrv_call_state *call)
917 if (!call->conn->allow_auth3) {
918 return dcesrv_fault_disconnect(call, DCERPC_NCA_S_PROTO_ERROR);
921 if (call->conn->auth_state.auth_finished) {
922 return dcesrv_fault_disconnect(call, DCERPC_NCA_S_PROTO_ERROR);
925 status = dcerpc_verify_ncacn_packet_header(&call->pkt,
927 call->pkt.u.auth3.auth_info.length,
928 0, /* required flags */
929 DCERPC_PFC_FLAG_FIRST |
930 DCERPC_PFC_FLAG_LAST |
931 DCERPC_PFC_FLAG_SUPPORT_HEADER_SIGN |
932 0x08 | /* this is not defined, but should be ignored */
933 DCERPC_PFC_FLAG_CONC_MPX |
934 DCERPC_PFC_FLAG_DID_NOT_EXECUTE |
935 DCERPC_PFC_FLAG_MAYBE |
936 DCERPC_PFC_FLAG_OBJECT_UUID);
937 if (!NT_STATUS_IS_OK(status)) {
938 return dcesrv_fault_disconnect(call, DCERPC_NCA_S_PROTO_ERROR);
941 /* handle the auth3 in the auth code */
942 if (!dcesrv_auth_auth3(call)) {
943 call->conn->auth_state.auth_invalid = true;
948 /* we don't send a reply to a auth3 request, except by a
955 handle a bind request
957 static NTSTATUS dcesrv_alter_new_context(struct dcesrv_call_state *call, uint32_t context_id)
959 uint32_t if_version, transfer_syntax_version;
960 struct dcesrv_connection_context *context;
961 const struct dcesrv_interface *iface;
962 struct GUID uuid, *transfer_syntax_uuid;
965 if_version = call->pkt.u.alter.ctx_list[0].abstract_syntax.if_version;
966 uuid = call->pkt.u.alter.ctx_list[0].abstract_syntax.uuid;
968 transfer_syntax_version = call->pkt.u.alter.ctx_list[0].transfer_syntaxes[0].if_version;
969 transfer_syntax_uuid = &call->pkt.u.alter.ctx_list[0].transfer_syntaxes[0].uuid;
970 if (!GUID_equal(transfer_syntax_uuid, &ndr_transfer_syntax_ndr.uuid) ||
971 ndr_transfer_syntax_ndr.if_version != transfer_syntax_version) {
972 /* we only do NDR encoded dcerpc */
973 return NT_STATUS_RPC_PROTSEQ_NOT_SUPPORTED;
976 iface = find_interface_by_uuid(call->conn->endpoint, &uuid, if_version);
978 char *uuid_str = GUID_string(call, &uuid);
979 DEBUG(2,("Request for unknown dcerpc interface %s/%d\n", uuid_str, if_version));
980 talloc_free(uuid_str);
981 return NT_STATUS_RPC_PROTSEQ_NOT_SUPPORTED;
984 /* add this context to the list of available context_ids */
985 context = talloc_zero(call->conn, struct dcesrv_connection_context);
986 if (context == NULL) {
987 return NT_STATUS_NO_MEMORY;
989 context->conn = call->conn;
990 context->iface = iface;
991 context->context_id = context_id;
992 if (call->pkt.u.alter.assoc_group_id != 0) {
993 context->assoc_group = dcesrv_assoc_group_reference(context,
995 call->pkt.u.alter.assoc_group_id);
997 context->assoc_group = dcesrv_assoc_group_new(context, call->conn->dce_ctx);
999 if (context->assoc_group == NULL) {
1000 talloc_free(context);
1001 call->context = NULL;
1002 return NT_STATUS_NO_MEMORY;
1004 context->private_data = NULL;
1005 DLIST_ADD(call->conn->contexts, context);
1006 call->context = context;
1007 talloc_set_destructor(context, dcesrv_connection_context_destructor);
1009 dcesrv_prepare_context_auth(call);
1011 status = iface->bind(call, iface, if_version);
1012 if (!NT_STATUS_IS_OK(status)) {
1013 /* we don't want to trigger the iface->unbind() hook */
1014 context->iface = NULL;
1015 talloc_free(context);
1016 call->context = NULL;
1020 return NT_STATUS_OK;
1023 /* setup and send an alter_resp */
1024 static NTSTATUS dcesrv_alter_resp(struct dcesrv_call_state *call,
1028 struct ncacn_packet pkt;
1029 uint32_t extra_flags = 0;
1030 struct data_blob_list_item *rep = NULL;
1033 dcesrv_init_hdr(&pkt, lpcfg_rpc_big_endian(call->conn->dce_ctx->lp_ctx));
1034 pkt.auth_length = 0;
1035 pkt.call_id = call->pkt.call_id;
1036 pkt.ptype = DCERPC_PKT_ALTER_RESP;
1038 if ((call->pkt.pfc_flags & DCERPC_PFC_FLAG_CONC_MPX) &&
1039 call->context->conn->state_flags &
1040 DCESRV_CALL_STATE_FLAG_MULTIPLEXED) {
1041 extra_flags |= DCERPC_PFC_FLAG_CONC_MPX;
1043 if (call->state_flags & DCESRV_CALL_STATE_FLAG_PROCESS_PENDING_CALL) {
1044 call->context->conn->state_flags |=
1045 DCESRV_CALL_STATE_FLAG_PROCESS_PENDING_CALL;
1048 pkt.pfc_flags = DCERPC_PFC_FLAG_FIRST | DCERPC_PFC_FLAG_LAST | extra_flags;
1049 pkt.u.alter_resp.max_xmit_frag = call->conn->max_xmit_frag;
1050 pkt.u.alter_resp.max_recv_frag = call->conn->max_recv_frag;
1052 pkt.u.alter_resp.assoc_group_id = call->context->assoc_group->id;
1054 pkt.u.alter_resp.assoc_group_id = 0;
1056 pkt.u.alter_resp.num_results = 1;
1057 pkt.u.alter_resp.ctx_list = talloc_zero(call, struct dcerpc_ack_ctx);
1058 if (!pkt.u.alter_resp.ctx_list) {
1059 return NT_STATUS_NO_MEMORY;
1061 pkt.u.alter_resp.ctx_list[0].result = result;
1062 pkt.u.alter_resp.ctx_list[0].reason.value = reason;
1063 pkt.u.alter_resp.ctx_list[0].syntax = ndr_transfer_syntax_ndr;
1064 pkt.u.alter_resp.auth_info = data_blob(NULL, 0);
1065 pkt.u.alter_resp.secondary_address = "";
1067 status = dcesrv_auth_alter_ack(call, &pkt);
1068 if (!NT_STATUS_IS_OK(status)) {
1069 return dcesrv_fault_disconnect(call, DCERPC_FAULT_SEC_PKG_ERROR);
1072 rep = talloc_zero(call, struct data_blob_list_item);
1074 return NT_STATUS_NO_MEMORY;
1077 status = ncacn_push_auth(&rep->blob, call, &pkt, call->out_auth_info);
1078 if (!NT_STATUS_IS_OK(status)) {
1082 dcerpc_set_frag_length(&rep->blob, rep->blob.length);
1084 DLIST_ADD_END(call->replies, rep);
1085 dcesrv_call_set_list(call, DCESRV_LIST_CALL_LIST);
1087 if (call->conn->call_list && call->conn->call_list->replies) {
1088 if (call->conn->transport.report_output_data) {
1089 call->conn->transport.report_output_data(call->conn);
1093 return NT_STATUS_OK;
1097 handle a alter context request
1099 static NTSTATUS dcesrv_alter(struct dcesrv_call_state *call)
1102 const struct dcerpc_ctx_list *ctx = NULL;
1103 bool auth_ok = false;
1105 if (!call->conn->allow_alter) {
1106 return dcesrv_fault_disconnect(call, DCERPC_NCA_S_PROTO_ERROR);
1109 status = dcerpc_verify_ncacn_packet_header(&call->pkt,
1111 call->pkt.u.alter.auth_info.length,
1112 0, /* required flags */
1113 DCERPC_PFC_FLAG_FIRST |
1114 DCERPC_PFC_FLAG_LAST |
1115 DCERPC_PFC_FLAG_SUPPORT_HEADER_SIGN |
1116 0x08 | /* this is not defined, but should be ignored */
1117 DCERPC_PFC_FLAG_CONC_MPX |
1118 DCERPC_PFC_FLAG_DID_NOT_EXECUTE |
1119 DCERPC_PFC_FLAG_MAYBE |
1120 DCERPC_PFC_FLAG_OBJECT_UUID);
1121 if (!NT_STATUS_IS_OK(status)) {
1122 return dcesrv_fault_disconnect(call, DCERPC_NCA_S_PROTO_ERROR);
1125 auth_ok = dcesrv_auth_alter(call);
1127 if (call->in_auth_info.auth_type == DCERPC_AUTH_TYPE_NONE) {
1128 return dcesrv_fault_disconnect(call,
1129 DCERPC_FAULT_ACCESS_DENIED);
1133 if (call->pkt.u.alter.num_contexts < 1) {
1134 return dcesrv_fault_disconnect(call, DCERPC_NCA_S_PROTO_ERROR);
1136 ctx = &call->pkt.u.alter.ctx_list[0];
1137 if (ctx->num_transfer_syntaxes < 1) {
1138 return dcesrv_fault_disconnect(call, DCERPC_NCA_S_PROTO_ERROR);
1141 /* see if they are asking for a new interface */
1142 call->context = dcesrv_find_context(call->conn, ctx->context_id);
1143 if (!call->context) {
1144 status = dcesrv_alter_new_context(call, ctx->context_id);
1145 if (!NT_STATUS_IS_OK(status)) {
1146 return dcesrv_alter_resp(call,
1147 DCERPC_BIND_PROVIDER_REJECT,
1148 DCERPC_BIND_REASON_ASYNTAX);
1153 ok = ndr_syntax_id_equal(&ctx->abstract_syntax,
1154 &call->context->iface->syntax_id);
1156 return dcesrv_fault_disconnect(call,
1157 DCERPC_NCA_S_PROTO_ERROR);
1160 if (ctx->num_transfer_syntaxes != 1) {
1161 return dcesrv_fault_disconnect(call,
1162 DCERPC_NCA_S_PROTO_ERROR);
1165 ok = ndr_syntax_id_equal(&ctx->transfer_syntaxes[0],
1166 &ndr_transfer_syntax_ndr);
1168 return dcesrv_fault_disconnect(call,
1169 DCERPC_NCA_S_PROTO_ERROR);
1173 if (call->pkt.u.alter.assoc_group_id != 0 &&
1174 lpcfg_parm_bool(call->conn->dce_ctx->lp_ctx, NULL, "dcesrv","assoc group checking", true) &&
1175 call->pkt.u.alter.assoc_group_id != call->context->assoc_group->id) {
1176 DEBUG(0,(__location__ ": Failed attempt to use new assoc_group in alter context (0x%08x 0x%08x)\n",
1177 call->context->assoc_group->id, call->pkt.u.alter.assoc_group_id));
1178 /* TODO: can they ask for a new association group? */
1179 return dcesrv_alter_resp(call,
1180 DCERPC_BIND_PROVIDER_REJECT,
1181 DCERPC_BIND_REASON_ASYNTAX);
1184 /* handle any authentication that is being requested */
1186 if (call->in_auth_info.auth_type !=
1187 call->conn->auth_state.auth_type)
1189 return dcesrv_fault_disconnect(call,
1190 DCERPC_FAULT_SEC_PKG_ERROR);
1192 return dcesrv_fault_disconnect(call, DCERPC_FAULT_ACCESS_DENIED);
1195 return dcesrv_alter_resp(call,
1196 DCERPC_BIND_ACK_RESULT_ACCEPTANCE,
1197 DCERPC_BIND_ACK_REASON_NOT_SPECIFIED);
1201 possibly save the call for inspection with ndrdump
1203 static void dcesrv_save_call(struct dcesrv_call_state *call, const char *why)
1207 const char *dump_dir;
1208 dump_dir = lpcfg_parm_string(call->conn->dce_ctx->lp_ctx, NULL, "dcesrv", "stubs directory");
1212 fname = talloc_asprintf(call, "%s/RPC-%s-%u-%s.dat",
1214 call->context->iface->name,
1215 call->pkt.u.request.opnum,
1217 if (file_save(fname, call->pkt.u.request.stub_and_verifier.data, call->pkt.u.request.stub_and_verifier.length)) {
1218 DEBUG(0,("RPC SAVED %s\n", fname));
1224 static NTSTATUS dcesrv_check_verification_trailer(struct dcesrv_call_state *call)
1226 TALLOC_CTX *frame = talloc_stackframe();
1227 const uint32_t bitmask1 = call->conn->auth_state.client_hdr_signing ?
1228 DCERPC_SEC_VT_CLIENT_SUPPORTS_HEADER_SIGNING : 0;
1229 const struct dcerpc_sec_vt_pcontext pcontext = {
1230 .abstract_syntax = call->context->iface->syntax_id,
1231 .transfer_syntax = ndr_transfer_syntax_ndr,
1233 const struct dcerpc_sec_vt_header2 header2 =
1234 dcerpc_sec_vt_header2_from_ncacn_packet(&call->pkt);
1235 enum ndr_err_code ndr_err;
1236 struct dcerpc_sec_verification_trailer *vt = NULL;
1237 NTSTATUS status = NT_STATUS_OK;
1240 SMB_ASSERT(call->pkt.ptype == DCERPC_PKT_REQUEST);
1242 ndr_err = ndr_pop_dcerpc_sec_verification_trailer(call->ndr_pull,
1244 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
1245 status = ndr_map_error2ntstatus(ndr_err);
1249 ok = dcerpc_sec_verification_trailer_check(vt, &bitmask1,
1250 &pcontext, &header2);
1252 status = NT_STATUS_ACCESS_DENIED;
1261 handle a dcerpc request packet
1263 static NTSTATUS dcesrv_request(struct dcesrv_call_state *call)
1265 const struct dcesrv_endpoint *endpoint = call->conn->endpoint;
1266 enum dcerpc_transport_t transport =
1267 dcerpc_binding_get_transport(endpoint->ep_description);
1268 struct ndr_pull *pull;
1270 struct dcesrv_connection_context *context;
1272 if (!call->conn->allow_request) {
1273 return dcesrv_fault_disconnect(call, DCERPC_NCA_S_PROTO_ERROR);
1276 /* if authenticated, and the mech we use can't do async replies, don't use them... */
1277 if (call->conn->auth_state.gensec_security &&
1278 !gensec_have_feature(call->conn->auth_state.gensec_security, GENSEC_FEATURE_ASYNC_REPLIES)) {
1279 call->state_flags &= ~DCESRV_CALL_STATE_FLAG_MAY_ASYNC;
1282 context = dcesrv_find_context(call->conn, call->pkt.u.request.context_id);
1283 if (context == NULL) {
1284 return dcesrv_fault(call, DCERPC_FAULT_UNK_IF);
1287 switch (call->conn->auth_state.auth_level) {
1288 case DCERPC_AUTH_LEVEL_NONE:
1289 case DCERPC_AUTH_LEVEL_INTEGRITY:
1290 case DCERPC_AUTH_LEVEL_PRIVACY:
1293 if (!context->allow_connect) {
1296 addr = tsocket_address_string(call->conn->remote_address,
1299 DEBUG(2, ("%s: restrict auth_level_connect access "
1300 "to [%s] with auth[type=0x%x,level=0x%x] "
1301 "on [%s] from [%s]\n",
1302 __func__, context->iface->name,
1303 call->conn->auth_state.auth_type,
1304 call->conn->auth_state.auth_level,
1305 derpc_transport_string_by_transport(transport),
1307 return dcesrv_fault(call, DCERPC_FAULT_ACCESS_DENIED);
1312 if (call->conn->auth_state.auth_level < context->min_auth_level) {
1315 addr = tsocket_address_string(call->conn->remote_address, call);
1317 DEBUG(2, ("%s: restrict access by min_auth_level[0x%x] "
1318 "to [%s] with auth[type=0x%x,level=0x%x] "
1319 "on [%s] from [%s]\n",
1321 context->min_auth_level,
1322 context->iface->name,
1323 call->conn->auth_state.auth_type,
1324 call->conn->auth_state.auth_level,
1325 derpc_transport_string_by_transport(transport),
1327 return dcesrv_fault(call, DCERPC_FAULT_ACCESS_DENIED);
1330 pull = ndr_pull_init_blob(&call->pkt.u.request.stub_and_verifier, call);
1331 NT_STATUS_HAVE_NO_MEMORY(pull);
1333 pull->flags |= LIBNDR_FLAG_REF_ALLOC;
1335 call->context = context;
1336 call->ndr_pull = pull;
1338 if (!(call->pkt.drep[0] & DCERPC_DREP_LE)) {
1339 pull->flags |= LIBNDR_FLAG_BIGENDIAN;
1342 status = dcesrv_check_verification_trailer(call);
1343 if (!NT_STATUS_IS_OK(status)) {
1344 uint32_t faultcode = DCERPC_FAULT_OTHER;
1345 if (NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
1346 faultcode = DCERPC_FAULT_ACCESS_DENIED;
1348 DEBUG(10, ("dcesrv_check_verification_trailer failed: %s\n",
1349 nt_errstr(status)));
1350 return dcesrv_fault(call, faultcode);
1353 /* unravel the NDR for the packet */
1354 status = context->iface->ndr_pull(call, call, pull, &call->r);
1355 if (!NT_STATUS_IS_OK(status)) {
1356 if (call->fault_code == DCERPC_FAULT_OP_RNG_ERROR) {
1357 /* we got an unknown call */
1358 DEBUG(3,(__location__ ": Unknown RPC call %u on %s\n",
1359 call->pkt.u.request.opnum, context->iface->name));
1360 dcesrv_save_call(call, "unknown");
1362 dcesrv_save_call(call, "pullfail");
1364 return dcesrv_fault(call, call->fault_code);
1367 if (pull->offset != pull->data_size) {
1368 dcesrv_save_call(call, "extrabytes");
1369 DEBUG(3,("Warning: %d extra bytes in incoming RPC request\n",
1370 pull->data_size - pull->offset));
1373 /* call the dispatch function */
1374 status = context->iface->dispatch(call, call, call->r);
1375 if (!NT_STATUS_IS_OK(status)) {
1376 DEBUG(5,("dcerpc fault in call %s:%02x - %s\n",
1377 context->iface->name,
1378 call->pkt.u.request.opnum,
1379 dcerpc_errstr(pull, call->fault_code)));
1380 return dcesrv_fault(call, call->fault_code);
1383 /* add the call to the pending list */
1384 dcesrv_call_set_list(call, DCESRV_LIST_PENDING_CALL_LIST);
1386 if (call->state_flags & DCESRV_CALL_STATE_FLAG_ASYNC) {
1387 return NT_STATUS_OK;
1390 return dcesrv_reply(call);
1395 remove the call from the right list when freed
1397 static int dcesrv_call_dequeue(struct dcesrv_call_state *call)
1399 dcesrv_call_set_list(call, DCESRV_LIST_NONE);
1403 _PUBLIC_ const struct tsocket_address *dcesrv_connection_get_local_address(struct dcesrv_connection *conn)
1405 return conn->local_address;
1408 _PUBLIC_ const struct tsocket_address *dcesrv_connection_get_remote_address(struct dcesrv_connection *conn)
1410 return conn->remote_address;
1414 process some input to a dcerpc endpoint server.
1416 static NTSTATUS dcesrv_process_ncacn_packet(struct dcesrv_connection *dce_conn,
1417 struct ncacn_packet *pkt,
1421 struct dcesrv_call_state *call;
1423 call = talloc_zero(dce_conn, struct dcesrv_call_state);
1425 data_blob_free(&blob);
1427 return NT_STATUS_NO_MEMORY;
1429 call->conn = dce_conn;
1430 call->event_ctx = dce_conn->event_ctx;
1431 call->msg_ctx = dce_conn->msg_ctx;
1432 call->state_flags = call->conn->state_flags;
1433 call->time = timeval_current();
1434 call->list = DCESRV_LIST_NONE;
1436 talloc_steal(call, pkt);
1437 talloc_steal(call, blob.data);
1440 talloc_set_destructor(call, dcesrv_call_dequeue);
1442 if (call->conn->allow_bind) {
1444 * Only one bind is possible per connection
1446 call->conn->allow_bind = false;
1447 return dcesrv_bind(call);
1450 /* we have to check the signing here, before combining the
1452 if (call->pkt.ptype == DCERPC_PKT_REQUEST) {
1453 if (!call->conn->allow_request) {
1454 return dcesrv_fault_disconnect(call,
1455 DCERPC_NCA_S_PROTO_ERROR);
1458 status = dcerpc_verify_ncacn_packet_header(&call->pkt,
1460 call->pkt.u.request.stub_and_verifier.length,
1461 0, /* required_flags */
1462 DCERPC_PFC_FLAG_FIRST |
1463 DCERPC_PFC_FLAG_LAST |
1464 DCERPC_PFC_FLAG_PENDING_CANCEL |
1465 0x08 | /* this is not defined, but should be ignored */
1466 DCERPC_PFC_FLAG_CONC_MPX |
1467 DCERPC_PFC_FLAG_DID_NOT_EXECUTE |
1468 DCERPC_PFC_FLAG_MAYBE |
1469 DCERPC_PFC_FLAG_OBJECT_UUID);
1470 if (!NT_STATUS_IS_OK(status)) {
1471 return dcesrv_fault_disconnect(call,
1472 DCERPC_NCA_S_PROTO_ERROR);
1475 if (!dcesrv_auth_request(call, &blob)) {
1476 return dcesrv_fault(call, DCERPC_FAULT_ACCESS_DENIED);
1480 /* see if this is a continued packet */
1481 if (call->pkt.ptype == DCERPC_PKT_REQUEST &&
1482 !(call->pkt.pfc_flags & DCERPC_PFC_FLAG_FIRST)) {
1483 struct dcesrv_call_state *call2 = call;
1484 uint32_t alloc_size;
1486 /* this is a continuation of an existing call - find the call
1487 then tack it on the end */
1488 call = dcesrv_find_fragmented_call(dce_conn, call2->pkt.call_id);
1490 return dcesrv_fault_disconnect(call2,
1491 DCERPC_NCA_S_PROTO_ERROR);
1494 if (call->pkt.ptype != call2->pkt.ptype) {
1495 /* trying to play silly buggers are we? */
1496 return dcesrv_fault_disconnect(call,
1497 DCERPC_NCA_S_PROTO_ERROR);
1499 if (memcmp(call->pkt.drep, call2->pkt.drep, sizeof(pkt->drep)) != 0) {
1500 return dcesrv_fault_disconnect(call,
1501 DCERPC_NCA_S_PROTO_ERROR);
1503 if (call->pkt.call_id != call2->pkt.call_id) {
1504 return dcesrv_fault_disconnect(call,
1505 DCERPC_NCA_S_PROTO_ERROR);
1507 if (call->pkt.u.request.context_id != call2->pkt.u.request.context_id) {
1508 return dcesrv_fault_disconnect(call,
1509 DCERPC_NCA_S_PROTO_ERROR);
1511 if (call->pkt.u.request.opnum != call2->pkt.u.request.opnum) {
1512 return dcesrv_fault_disconnect(call,
1513 DCERPC_NCA_S_PROTO_ERROR);
1516 alloc_size = call->pkt.u.request.stub_and_verifier.length +
1517 call2->pkt.u.request.stub_and_verifier.length;
1518 if (call->pkt.u.request.alloc_hint > alloc_size) {
1519 alloc_size = call->pkt.u.request.alloc_hint;
1522 call->pkt.u.request.stub_and_verifier.data =
1523 talloc_realloc(call,
1524 call->pkt.u.request.stub_and_verifier.data,
1525 uint8_t, alloc_size);
1526 if (!call->pkt.u.request.stub_and_verifier.data) {
1527 return dcesrv_fault(call2, DCERPC_FAULT_OTHER);
1529 memcpy(call->pkt.u.request.stub_and_verifier.data +
1530 call->pkt.u.request.stub_and_verifier.length,
1531 call2->pkt.u.request.stub_and_verifier.data,
1532 call2->pkt.u.request.stub_and_verifier.length);
1533 call->pkt.u.request.stub_and_verifier.length +=
1534 call2->pkt.u.request.stub_and_verifier.length;
1536 call->pkt.pfc_flags |= (call2->pkt.pfc_flags & DCERPC_PFC_FLAG_LAST);
1541 /* this may not be the last pdu in the chain - if its isn't then
1542 just put it on the incoming_fragmented_call_list and wait for the rest */
1543 if (call->pkt.ptype == DCERPC_PKT_REQUEST &&
1544 !(call->pkt.pfc_flags & DCERPC_PFC_FLAG_LAST)) {
1545 dcesrv_call_set_list(call, DCESRV_LIST_FRAGMENTED_CALL_LIST);
1546 return NT_STATUS_OK;
1549 /* This removes any fragments we may have had stashed away */
1550 dcesrv_call_set_list(call, DCESRV_LIST_NONE);
1552 switch (call->pkt.ptype) {
1553 case DCERPC_PKT_BIND:
1554 status = dcesrv_bind_nak(call,
1555 DCERPC_BIND_NAK_REASON_NOT_SPECIFIED);
1557 case DCERPC_PKT_AUTH3:
1558 status = dcesrv_auth3(call);
1560 case DCERPC_PKT_ALTER:
1561 status = dcesrv_alter(call);
1563 case DCERPC_PKT_REQUEST:
1564 status = dcesrv_request(call);
1567 status = dcesrv_fault_disconnect(call, DCERPC_NCA_S_PROTO_ERROR);
1571 /* if we are going to be sending a reply then add
1572 it to the list of pending calls. We add it to the end to keep the call
1573 list in the order we will answer */
1574 if (!NT_STATUS_IS_OK(status)) {
1581 _PUBLIC_ NTSTATUS dcesrv_init_context(TALLOC_CTX *mem_ctx,
1582 struct loadparm_context *lp_ctx,
1583 const char **endpoint_servers, struct dcesrv_context **_dce_ctx)
1586 struct dcesrv_context *dce_ctx;
1589 if (!endpoint_servers) {
1590 DEBUG(0,("dcesrv_init_context: no endpoint servers configured\n"));
1591 return NT_STATUS_INTERNAL_ERROR;
1594 dce_ctx = talloc_zero(mem_ctx, struct dcesrv_context);
1595 NT_STATUS_HAVE_NO_MEMORY(dce_ctx);
1597 if (uid_wrapper_enabled()) {
1598 setenv("UID_WRAPPER_MYUID", "1", 1);
1600 dce_ctx->initial_euid = geteuid();
1601 if (uid_wrapper_enabled()) {
1602 unsetenv("UID_WRAPPER_MYUID");
1605 dce_ctx->endpoint_list = NULL;
1606 dce_ctx->lp_ctx = lp_ctx;
1607 dce_ctx->assoc_groups_idr = idr_init(dce_ctx);
1608 NT_STATUS_HAVE_NO_MEMORY(dce_ctx->assoc_groups_idr);
1609 dce_ctx->broken_connections = NULL;
1611 for (i=0;endpoint_servers[i];i++) {
1612 const struct dcesrv_endpoint_server *ep_server;
1614 ep_server = dcesrv_ep_server_byname(endpoint_servers[i]);
1616 DEBUG(0,("dcesrv_init_context: failed to find endpoint server = '%s'\n", endpoint_servers[i]));
1617 return NT_STATUS_INTERNAL_ERROR;
1620 status = ep_server->init_server(dce_ctx, ep_server);
1621 if (!NT_STATUS_IS_OK(status)) {
1622 DEBUG(0,("dcesrv_init_context: failed to init endpoint server = '%s': %s\n", endpoint_servers[i],
1623 nt_errstr(status)));
1628 *_dce_ctx = dce_ctx;
1629 return NT_STATUS_OK;
1632 /* the list of currently registered DCERPC endpoint servers.
1634 static struct ep_server {
1635 struct dcesrv_endpoint_server *ep_server;
1636 } *ep_servers = NULL;
1637 static int num_ep_servers;
1640 register a DCERPC endpoint server.
1642 The 'name' can be later used by other backends to find the operations
1643 structure for this backend.
1645 The 'type' is used to specify whether this is for a disk, printer or IPC$ share
1647 _PUBLIC_ NTSTATUS dcerpc_register_ep_server(const void *_ep_server)
1649 const struct dcesrv_endpoint_server *ep_server = _ep_server;
1651 if (dcesrv_ep_server_byname(ep_server->name) != NULL) {
1652 /* its already registered! */
1653 DEBUG(0,("DCERPC endpoint server '%s' already registered\n",
1655 return NT_STATUS_OBJECT_NAME_COLLISION;
1658 ep_servers = realloc_p(ep_servers, struct ep_server, num_ep_servers+1);
1660 smb_panic("out of memory in dcerpc_register");
1663 ep_servers[num_ep_servers].ep_server = smb_xmemdup(ep_server, sizeof(*ep_server));
1664 ep_servers[num_ep_servers].ep_server->name = smb_xstrdup(ep_server->name);
1668 DEBUG(3,("DCERPC endpoint server '%s' registered\n",
1671 return NT_STATUS_OK;
1675 return the operations structure for a named backend of the specified type
1677 const struct dcesrv_endpoint_server *dcesrv_ep_server_byname(const char *name)
1681 for (i=0;i<num_ep_servers;i++) {
1682 if (strcmp(ep_servers[i].ep_server->name, name) == 0) {
1683 return ep_servers[i].ep_server;
1690 void dcerpc_server_init(struct loadparm_context *lp_ctx)
1692 static bool initialized;
1693 #define _MODULE_PROTO(init) extern NTSTATUS init(void);
1694 STATIC_dcerpc_server_MODULES_PROTO;
1695 init_module_fn static_init[] = { STATIC_dcerpc_server_MODULES };
1696 init_module_fn *shared_init;
1703 shared_init = load_samba_modules(NULL, "dcerpc_server");
1705 run_init_functions(static_init);
1706 run_init_functions(shared_init);
1708 talloc_free(shared_init);
1712 return the DCERPC module version, and the size of some critical types
1713 This can be used by endpoint server modules to either detect compilation errors, or provide
1714 multiple implementations for different smbd compilation options in one module
1716 const struct dcesrv_critical_sizes *dcerpc_module_version(void)
1718 static const struct dcesrv_critical_sizes critical_sizes = {
1719 DCERPC_MODULE_VERSION,
1720 sizeof(struct dcesrv_context),
1721 sizeof(struct dcesrv_endpoint),
1722 sizeof(struct dcesrv_endpoint_server),
1723 sizeof(struct dcesrv_interface),
1724 sizeof(struct dcesrv_if_list),
1725 sizeof(struct dcesrv_connection),
1726 sizeof(struct dcesrv_call_state),
1727 sizeof(struct dcesrv_auth),
1728 sizeof(struct dcesrv_handle)
1731 return &critical_sizes;
1734 static void dcesrv_terminate_connection(struct dcesrv_connection *dce_conn, const char *reason)
1736 struct dcesrv_context *dce_ctx = dce_conn->dce_ctx;
1737 struct stream_connection *srv_conn;
1738 srv_conn = talloc_get_type(dce_conn->transport.private_data,
1739 struct stream_connection);
1741 dce_conn->allow_bind = false;
1742 dce_conn->allow_auth3 = false;
1743 dce_conn->allow_alter = false;
1744 dce_conn->allow_request = false;
1746 if (dce_conn->pending_call_list == NULL) {
1747 char *full_reason = talloc_asprintf(dce_conn, "dcesrv: %s", reason);
1749 DLIST_REMOVE(dce_ctx->broken_connections, dce_conn);
1750 stream_terminate_connection(srv_conn, full_reason ? full_reason : reason);
1754 if (dce_conn->terminate != NULL) {
1758 DEBUG(3,("dcesrv: terminating connection due to '%s' defered due to pending calls\n",
1760 dce_conn->terminate = talloc_strdup(dce_conn, reason);
1761 if (dce_conn->terminate == NULL) {
1762 dce_conn->terminate = "dcesrv: defered terminating connection - no memory";
1764 DLIST_ADD_END(dce_ctx->broken_connections, dce_conn);
1767 static void dcesrv_cleanup_broken_connections(struct dcesrv_context *dce_ctx)
1769 struct dcesrv_connection *cur, *next;
1771 next = dce_ctx->broken_connections;
1772 while (next != NULL) {
1776 if (cur->state_flags & DCESRV_CALL_STATE_FLAG_PROCESS_PENDING_CALL) {
1777 struct dcesrv_connection_context *context_cur, *context_next;
1779 context_next = cur->contexts;
1780 while (context_next != NULL) {
1781 context_cur = context_next;
1782 context_next = context_cur->next;
1784 dcesrv_connection_context_destructor(context_cur);
1788 dcesrv_terminate_connection(cur, cur->terminate);
1792 /* We need this include to be able to compile on some plateforms
1793 * (ie. freebsd 7.2) as it seems that <sys/uio.h> is not included
1795 * It has to be that deep because otherwise we have a conflict on
1796 * const struct dcesrv_interface declaration.
1797 * This is mostly due to socket_wrapper defining #define bind swrap_bind
1798 * which conflict with the bind used before.
1800 #include "system/network.h"
1802 struct dcesrv_sock_reply_state {
1803 struct dcesrv_connection *dce_conn;
1804 struct dcesrv_call_state *call;
1808 static void dcesrv_sock_reply_done(struct tevent_req *subreq);
1809 static void dcesrv_call_terminate_step1(struct tevent_req *subreq);
1811 static void dcesrv_sock_report_output_data(struct dcesrv_connection *dce_conn)
1813 struct dcesrv_call_state *call;
1815 call = dce_conn->call_list;
1816 if (!call || !call->replies) {
1820 while (call->replies) {
1821 struct data_blob_list_item *rep = call->replies;
1822 struct dcesrv_sock_reply_state *substate;
1823 struct tevent_req *subreq;
1825 substate = talloc_zero(call, struct dcesrv_sock_reply_state);
1827 dcesrv_terminate_connection(dce_conn, "no memory");
1831 substate->dce_conn = dce_conn;
1832 substate->call = NULL;
1834 DLIST_REMOVE(call->replies, rep);
1836 if (call->replies == NULL && call->terminate_reason == NULL) {
1837 substate->call = call;
1840 substate->iov.iov_base = (void *) rep->blob.data;
1841 substate->iov.iov_len = rep->blob.length;
1843 subreq = tstream_writev_queue_send(substate,
1844 dce_conn->event_ctx,
1846 dce_conn->send_queue,
1849 dcesrv_terminate_connection(dce_conn, "no memory");
1852 tevent_req_set_callback(subreq, dcesrv_sock_reply_done,
1856 if (call->terminate_reason != NULL) {
1857 struct tevent_req *subreq;
1859 subreq = tevent_queue_wait_send(call,
1860 dce_conn->event_ctx,
1861 dce_conn->send_queue);
1863 dcesrv_terminate_connection(dce_conn, __location__);
1866 tevent_req_set_callback(subreq, dcesrv_call_terminate_step1,
1870 DLIST_REMOVE(call->conn->call_list, call);
1871 call->list = DCESRV_LIST_NONE;
1874 static void dcesrv_sock_reply_done(struct tevent_req *subreq)
1876 struct dcesrv_sock_reply_state *substate = tevent_req_callback_data(subreq,
1877 struct dcesrv_sock_reply_state);
1881 struct dcesrv_call_state *call = substate->call;
1883 ret = tstream_writev_queue_recv(subreq, &sys_errno);
1884 TALLOC_FREE(subreq);
1886 status = map_nt_error_from_unix_common(sys_errno);
1887 dcesrv_terminate_connection(substate->dce_conn, nt_errstr(status));
1891 talloc_free(substate);
1897 static void dcesrv_call_terminate_step2(struct tevent_req *subreq);
1899 static void dcesrv_call_terminate_step1(struct tevent_req *subreq)
1901 struct dcesrv_call_state *call = tevent_req_callback_data(subreq,
1902 struct dcesrv_call_state);
1906 /* make sure we stop send queue before removing subreq */
1907 tevent_queue_stop(call->conn->send_queue);
1909 ok = tevent_queue_wait_recv(subreq);
1910 TALLOC_FREE(subreq);
1912 dcesrv_terminate_connection(call->conn, __location__);
1916 /* disconnect after 200 usecs */
1917 tv = timeval_current_ofs_usec(200);
1918 subreq = tevent_wakeup_send(call, call->conn->event_ctx, tv);
1919 if (subreq == NULL) {
1920 dcesrv_terminate_connection(call->conn, __location__);
1923 tevent_req_set_callback(subreq, dcesrv_call_terminate_step2,
1927 static void dcesrv_call_terminate_step2(struct tevent_req *subreq)
1929 struct dcesrv_call_state *call = tevent_req_callback_data(subreq,
1930 struct dcesrv_call_state);
1933 ok = tevent_wakeup_recv(subreq);
1934 TALLOC_FREE(subreq);
1936 dcesrv_terminate_connection(call->conn, __location__);
1940 dcesrv_terminate_connection(call->conn, call->terminate_reason);
1943 struct dcesrv_socket_context {
1944 const struct dcesrv_endpoint *endpoint;
1945 struct dcesrv_context *dcesrv_ctx;
1949 static void dcesrv_read_fragment_done(struct tevent_req *subreq);
1951 static void dcesrv_sock_accept(struct stream_connection *srv_conn)
1954 struct dcesrv_socket_context *dcesrv_sock =
1955 talloc_get_type(srv_conn->private_data, struct dcesrv_socket_context);
1956 enum dcerpc_transport_t transport =
1957 dcerpc_binding_get_transport(dcesrv_sock->endpoint->ep_description);
1958 struct dcesrv_connection *dcesrv_conn = NULL;
1960 struct tevent_req *subreq;
1961 struct loadparm_context *lp_ctx = dcesrv_sock->dcesrv_ctx->lp_ctx;
1963 dcesrv_cleanup_broken_connections(dcesrv_sock->dcesrv_ctx);
1965 if (!srv_conn->session_info) {
1966 status = auth_anonymous_session_info(srv_conn,
1968 &srv_conn->session_info);
1969 if (!NT_STATUS_IS_OK(status)) {
1970 DEBUG(0,("dcesrv_sock_accept: auth_anonymous_session_info failed: %s\n",
1971 nt_errstr(status)));
1972 stream_terminate_connection(srv_conn, nt_errstr(status));
1977 status = dcesrv_endpoint_connect(dcesrv_sock->dcesrv_ctx,
1979 dcesrv_sock->endpoint,
1980 srv_conn->session_info,
1981 srv_conn->event.ctx,
1983 srv_conn->server_id,
1984 DCESRV_CALL_STATE_FLAG_MAY_ASYNC,
1986 if (!NT_STATUS_IS_OK(status)) {
1987 DEBUG(0,("dcesrv_sock_accept: dcesrv_endpoint_connect failed: %s\n",
1988 nt_errstr(status)));
1989 stream_terminate_connection(srv_conn, nt_errstr(status));
1993 dcesrv_conn->transport.private_data = srv_conn;
1994 dcesrv_conn->transport.report_output_data = dcesrv_sock_report_output_data;
1996 TALLOC_FREE(srv_conn->event.fde);
1998 dcesrv_conn->send_queue = tevent_queue_create(dcesrv_conn, "dcesrv send queue");
1999 if (!dcesrv_conn->send_queue) {
2000 status = NT_STATUS_NO_MEMORY;
2001 DEBUG(0,("dcesrv_sock_accept: tevent_queue_create(%s)\n",
2002 nt_errstr(status)));
2003 stream_terminate_connection(srv_conn, nt_errstr(status));
2007 if (transport == NCACN_NP) {
2008 dcesrv_conn->auth_state.session_key = dcesrv_inherited_session_key;
2009 dcesrv_conn->stream = talloc_move(dcesrv_conn,
2010 &srv_conn->tstream);
2012 ret = tstream_bsd_existing_socket(dcesrv_conn,
2013 socket_get_fd(srv_conn->socket),
2014 &dcesrv_conn->stream);
2016 status = map_nt_error_from_unix_common(errno);
2017 DEBUG(0, ("dcesrv_sock_accept: "
2018 "failed to setup tstream: %s\n",
2019 nt_errstr(status)));
2020 stream_terminate_connection(srv_conn, nt_errstr(status));
2023 socket_set_flags(srv_conn->socket, SOCKET_FLAG_NOCLOSE);
2026 dcesrv_conn->local_address = srv_conn->local_address;
2027 dcesrv_conn->remote_address = srv_conn->remote_address;
2029 if (transport == NCALRPC) {
2033 ret = getpeereid(socket_get_fd(srv_conn->socket), &uid, &gid);
2035 status = map_nt_error_from_unix_common(errno);
2036 DEBUG(0, ("dcesrv_sock_accept: "
2037 "getpeereid() failed for NCALRPC: %s\n",
2038 nt_errstr(status)));
2039 stream_terminate_connection(srv_conn, nt_errstr(status));
2042 if (uid == dcesrv_conn->dce_ctx->initial_euid) {
2043 struct tsocket_address *r = NULL;
2045 ret = tsocket_address_unix_from_path(dcesrv_conn,
2046 "/root/ncalrpc_as_system",
2049 status = map_nt_error_from_unix_common(errno);
2050 DEBUG(0, ("dcesrv_sock_accept: "
2051 "tsocket_address_unix_from_path() failed for NCALRPC: %s\n",
2052 nt_errstr(status)));
2053 stream_terminate_connection(srv_conn, nt_errstr(status));
2056 dcesrv_conn->remote_address = r;
2060 srv_conn->private_data = dcesrv_conn;
2062 irpc_add_name(srv_conn->msg_ctx, "rpc_server");
2064 subreq = dcerpc_read_ncacn_packet_send(dcesrv_conn,
2065 dcesrv_conn->event_ctx,
2066 dcesrv_conn->stream);
2068 status = NT_STATUS_NO_MEMORY;
2069 DEBUG(0,("dcesrv_sock_accept: dcerpc_read_fragment_buffer_send(%s)\n",
2070 nt_errstr(status)));
2071 stream_terminate_connection(srv_conn, nt_errstr(status));
2074 tevent_req_set_callback(subreq, dcesrv_read_fragment_done, dcesrv_conn);
2079 static void dcesrv_read_fragment_done(struct tevent_req *subreq)
2081 struct dcesrv_connection *dce_conn = tevent_req_callback_data(subreq,
2082 struct dcesrv_connection);
2083 struct dcesrv_context *dce_ctx = dce_conn->dce_ctx;
2084 struct ncacn_packet *pkt;
2088 if (dce_conn->terminate) {
2090 * if the current connection is broken
2091 * we need to clean it up before any other connection
2093 dcesrv_terminate_connection(dce_conn, dce_conn->terminate);
2094 dcesrv_cleanup_broken_connections(dce_ctx);
2098 dcesrv_cleanup_broken_connections(dce_ctx);
2100 status = dcerpc_read_ncacn_packet_recv(subreq, dce_conn,
2102 TALLOC_FREE(subreq);
2103 if (!NT_STATUS_IS_OK(status)) {
2104 dcesrv_terminate_connection(dce_conn, nt_errstr(status));
2108 status = dcesrv_process_ncacn_packet(dce_conn, pkt, buffer);
2109 if (!NT_STATUS_IS_OK(status)) {
2110 dcesrv_terminate_connection(dce_conn, nt_errstr(status));
2114 subreq = dcerpc_read_ncacn_packet_send(dce_conn,
2115 dce_conn->event_ctx,
2118 status = NT_STATUS_NO_MEMORY;
2119 dcesrv_terminate_connection(dce_conn, nt_errstr(status));
2122 tevent_req_set_callback(subreq, dcesrv_read_fragment_done, dce_conn);
2125 static void dcesrv_sock_recv(struct stream_connection *conn, uint16_t flags)
2127 struct dcesrv_connection *dce_conn = talloc_get_type(conn->private_data,
2128 struct dcesrv_connection);
2129 dcesrv_terminate_connection(dce_conn, "dcesrv_sock_recv triggered");
2132 static void dcesrv_sock_send(struct stream_connection *conn, uint16_t flags)
2134 struct dcesrv_connection *dce_conn = talloc_get_type(conn->private_data,
2135 struct dcesrv_connection);
2136 dcesrv_terminate_connection(dce_conn, "dcesrv_sock_send triggered");
2140 static const struct stream_server_ops dcesrv_stream_ops = {
2142 .accept_connection = dcesrv_sock_accept,
2143 .recv_handler = dcesrv_sock_recv,
2144 .send_handler = dcesrv_sock_send,
2147 static NTSTATUS dcesrv_add_ep_unix(struct dcesrv_context *dce_ctx,
2148 struct loadparm_context *lp_ctx,
2149 struct dcesrv_endpoint *e,
2150 struct tevent_context *event_ctx, const struct model_ops *model_ops)
2152 struct dcesrv_socket_context *dcesrv_sock;
2155 const char *endpoint;
2157 dcesrv_sock = talloc_zero(event_ctx, struct dcesrv_socket_context);
2158 NT_STATUS_HAVE_NO_MEMORY(dcesrv_sock);
2160 /* remember the endpoint of this socket */
2161 dcesrv_sock->endpoint = e;
2162 dcesrv_sock->dcesrv_ctx = talloc_reference(dcesrv_sock, dce_ctx);
2164 endpoint = dcerpc_binding_get_string_option(e->ep_description, "endpoint");
2166 status = stream_setup_socket(dcesrv_sock, event_ctx, lp_ctx,
2167 model_ops, &dcesrv_stream_ops,
2168 "unix", endpoint, &port,
2169 lpcfg_socket_options(lp_ctx),
2171 if (!NT_STATUS_IS_OK(status)) {
2172 DEBUG(0,("service_setup_stream_socket(path=%s) failed - %s\n",
2173 endpoint, nt_errstr(status)));
2179 static NTSTATUS dcesrv_add_ep_ncalrpc(struct dcesrv_context *dce_ctx,
2180 struct loadparm_context *lp_ctx,
2181 struct dcesrv_endpoint *e,
2182 struct tevent_context *event_ctx, const struct model_ops *model_ops)
2184 struct dcesrv_socket_context *dcesrv_sock;
2188 const char *endpoint;
2190 endpoint = dcerpc_binding_get_string_option(e->ep_description, "endpoint");
2192 if (endpoint == NULL) {
2194 * No identifier specified: use DEFAULT.
2196 * TODO: DO NOT hardcode this value anywhere else. Rather, specify
2197 * no endpoint and let the epmapper worry about it.
2199 endpoint = "DEFAULT";
2200 status = dcerpc_binding_set_string_option(e->ep_description,
2203 if (!NT_STATUS_IS_OK(status)) {
2204 DEBUG(0,("dcerpc_binding_set_string_option() failed - %s\n",
2205 nt_errstr(status)));
2210 full_path = talloc_asprintf(dce_ctx, "%s/%s", lpcfg_ncalrpc_dir(lp_ctx),
2213 dcesrv_sock = talloc_zero(event_ctx, struct dcesrv_socket_context);
2214 NT_STATUS_HAVE_NO_MEMORY(dcesrv_sock);
2216 /* remember the endpoint of this socket */
2217 dcesrv_sock->endpoint = e;
2218 dcesrv_sock->dcesrv_ctx = talloc_reference(dcesrv_sock, dce_ctx);
2220 status = stream_setup_socket(dcesrv_sock, event_ctx, lp_ctx,
2221 model_ops, &dcesrv_stream_ops,
2222 "unix", full_path, &port,
2223 lpcfg_socket_options(lp_ctx),
2225 if (!NT_STATUS_IS_OK(status)) {
2226 DEBUG(0,("service_setup_stream_socket(identifier=%s,path=%s) failed - %s\n",
2227 endpoint, full_path, nt_errstr(status)));
2232 static NTSTATUS dcesrv_add_ep_np(struct dcesrv_context *dce_ctx,
2233 struct loadparm_context *lp_ctx,
2234 struct dcesrv_endpoint *e,
2235 struct tevent_context *event_ctx, const struct model_ops *model_ops)
2237 struct dcesrv_socket_context *dcesrv_sock;
2239 const char *endpoint;
2241 endpoint = dcerpc_binding_get_string_option(e->ep_description, "endpoint");
2242 if (endpoint == NULL) {
2243 DEBUG(0, ("Endpoint mandatory for named pipes\n"));
2244 return NT_STATUS_INVALID_PARAMETER;
2247 dcesrv_sock = talloc_zero(event_ctx, struct dcesrv_socket_context);
2248 NT_STATUS_HAVE_NO_MEMORY(dcesrv_sock);
2250 /* remember the endpoint of this socket */
2251 dcesrv_sock->endpoint = e;
2252 dcesrv_sock->dcesrv_ctx = talloc_reference(dcesrv_sock, dce_ctx);
2254 status = tstream_setup_named_pipe(dce_ctx, event_ctx, lp_ctx,
2255 model_ops, &dcesrv_stream_ops,
2258 if (!NT_STATUS_IS_OK(status)) {
2259 DEBUG(0,("stream_setup_named_pipe(pipe=%s) failed - %s\n",
2260 endpoint, nt_errstr(status)));
2264 return NT_STATUS_OK;
2268 add a socket address to the list of events, one event per dcerpc endpoint
2270 static NTSTATUS add_socket_rpc_tcp_iface(struct dcesrv_context *dce_ctx, struct dcesrv_endpoint *e,
2271 struct tevent_context *event_ctx, const struct model_ops *model_ops,
2272 const char *address)
2274 struct dcesrv_socket_context *dcesrv_sock;
2277 const char *endpoint;
2280 endpoint = dcerpc_binding_get_string_option(e->ep_description, "endpoint");
2281 if (endpoint != NULL) {
2282 port = atoi(endpoint);
2285 dcesrv_sock = talloc_zero(event_ctx, struct dcesrv_socket_context);
2286 NT_STATUS_HAVE_NO_MEMORY(dcesrv_sock);
2288 /* remember the endpoint of this socket */
2289 dcesrv_sock->endpoint = e;
2290 dcesrv_sock->dcesrv_ctx = talloc_reference(dcesrv_sock, dce_ctx);
2292 status = stream_setup_socket(dcesrv_sock, event_ctx, dce_ctx->lp_ctx,
2293 model_ops, &dcesrv_stream_ops,
2294 "ip", address, &port,
2295 lpcfg_socket_options(dce_ctx->lp_ctx),
2297 if (!NT_STATUS_IS_OK(status)) {
2298 DEBUG(0,("service_setup_stream_socket(address=%s,port=%u) failed - %s\n",
2299 address, port, nt_errstr(status)));
2303 snprintf(port_str, sizeof(port_str), "%u", port);
2305 status = dcerpc_binding_set_string_option(e->ep_description,
2306 "endpoint", port_str);
2307 if (!NT_STATUS_IS_OK(status)) {
2308 DEBUG(0,("dcerpc_binding_set_string_option(endpoint, %s) failed - %s\n",
2309 port_str, nt_errstr(status)));
2313 return NT_STATUS_OK;
2316 #include "lib/socket/netif.h" /* Included here to work around the fact that socket_wrapper redefines bind() */
2318 static NTSTATUS dcesrv_add_ep_tcp(struct dcesrv_context *dce_ctx,
2319 struct loadparm_context *lp_ctx,
2320 struct dcesrv_endpoint *e,
2321 struct tevent_context *event_ctx, const struct model_ops *model_ops)
2325 /* Add TCP/IP sockets */
2326 if (lpcfg_interfaces(lp_ctx) && lpcfg_bind_interfaces_only(lp_ctx)) {
2329 struct interface *ifaces;
2331 load_interface_list(dce_ctx, lp_ctx, &ifaces);
2333 num_interfaces = iface_list_count(ifaces);
2334 for(i = 0; i < num_interfaces; i++) {
2335 const char *address = iface_list_n_ip(ifaces, i);
2336 status = add_socket_rpc_tcp_iface(dce_ctx, e, event_ctx, model_ops, address);
2337 NT_STATUS_NOT_OK_RETURN(status);
2343 wcard = iface_list_wildcard(dce_ctx);
2344 NT_STATUS_HAVE_NO_MEMORY(wcard);
2345 for (i=0; wcard[i]; i++) {
2346 status = add_socket_rpc_tcp_iface(dce_ctx, e, event_ctx, model_ops, wcard[i]);
2347 if (NT_STATUS_IS_OK(status)) {
2352 if (num_binds == 0) {
2353 return NT_STATUS_INVALID_PARAMETER_MIX;
2357 return NT_STATUS_OK;
2360 NTSTATUS dcesrv_add_ep(struct dcesrv_context *dce_ctx,
2361 struct loadparm_context *lp_ctx,
2362 struct dcesrv_endpoint *e,
2363 struct tevent_context *event_ctx,
2364 const struct model_ops *model_ops)
2366 enum dcerpc_transport_t transport =
2367 dcerpc_binding_get_transport(e->ep_description);
2369 switch (transport) {
2370 case NCACN_UNIX_STREAM:
2371 return dcesrv_add_ep_unix(dce_ctx, lp_ctx, e, event_ctx, model_ops);
2374 return dcesrv_add_ep_ncalrpc(dce_ctx, lp_ctx, e, event_ctx, model_ops);
2377 return dcesrv_add_ep_tcp(dce_ctx, lp_ctx, e, event_ctx, model_ops);
2380 return dcesrv_add_ep_np(dce_ctx, lp_ctx, e, event_ctx, model_ops);
2383 return NT_STATUS_NOT_SUPPORTED;
2389 * retrieve credentials from a dce_call
2391 _PUBLIC_ struct cli_credentials *dcesrv_call_credentials(struct dcesrv_call_state *dce_call)
2393 return dce_call->conn->auth_state.session_info->credentials;
2397 * returns true if this is an authenticated call
2399 _PUBLIC_ bool dcesrv_call_authenticated(struct dcesrv_call_state *dce_call)
2401 enum security_user_level level;
2402 level = security_session_user_level(dce_call->conn->auth_state.session_info, NULL);
2403 return level >= SECURITY_USER;
2407 * retrieve account_name for a dce_call
2409 _PUBLIC_ const char *dcesrv_call_account_name(struct dcesrv_call_state *dce_call)
2411 return dce_call->context->conn->auth_state.session_info->info->account_name;