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 extern const struct dcesrv_interface dcesrv_mgmt_interface;
49 find an association group given a assoc_group_id
51 static struct dcesrv_assoc_group *dcesrv_assoc_group_find(struct dcesrv_context *dce_ctx,
56 id_ptr = idr_find(dce_ctx->assoc_groups_idr, id);
60 return talloc_get_type_abort(id_ptr, struct dcesrv_assoc_group);
64 take a reference to an existing association group
66 static struct dcesrv_assoc_group *dcesrv_assoc_group_reference(TALLOC_CTX *mem_ctx,
67 struct dcesrv_context *dce_ctx,
70 struct dcesrv_assoc_group *assoc_group;
72 assoc_group = dcesrv_assoc_group_find(dce_ctx, id);
73 if (assoc_group == NULL) {
74 DEBUG(2,(__location__ ": Failed to find assoc_group 0x%08x\n", id));
77 return talloc_reference(mem_ctx, assoc_group);
80 static int dcesrv_assoc_group_destructor(struct dcesrv_assoc_group *assoc_group)
83 ret = idr_remove(assoc_group->dce_ctx->assoc_groups_idr, assoc_group->id);
85 DEBUG(0,(__location__ ": Failed to remove assoc_group 0x%08x\n",
92 allocate a new association group
94 static struct dcesrv_assoc_group *dcesrv_assoc_group_new(TALLOC_CTX *mem_ctx,
95 struct dcesrv_context *dce_ctx)
97 struct dcesrv_assoc_group *assoc_group;
100 assoc_group = talloc_zero(mem_ctx, struct dcesrv_assoc_group);
101 if (assoc_group == NULL) {
105 id = idr_get_new_random(dce_ctx->assoc_groups_idr, assoc_group, UINT16_MAX);
107 talloc_free(assoc_group);
108 DEBUG(0,(__location__ ": Out of association groups!\n"));
112 assoc_group->id = id;
113 assoc_group->dce_ctx = dce_ctx;
115 talloc_set_destructor(assoc_group, dcesrv_assoc_group_destructor);
122 see if two endpoints match
124 static bool endpoints_match(const struct dcerpc_binding *ep1,
125 const struct dcerpc_binding *ep2)
127 enum dcerpc_transport_t t1;
128 enum dcerpc_transport_t t2;
132 t1 = dcerpc_binding_get_transport(ep1);
133 t2 = dcerpc_binding_get_transport(ep2);
135 e1 = dcerpc_binding_get_string_option(ep1, "endpoint");
136 e2 = dcerpc_binding_get_string_option(ep2, "endpoint");
146 if (strcasecmp(e1, e2) != 0) {
154 find an endpoint in the dcesrv_context
156 static struct dcesrv_endpoint *find_endpoint(struct dcesrv_context *dce_ctx,
157 const struct dcerpc_binding *ep_description)
159 struct dcesrv_endpoint *ep;
160 for (ep=dce_ctx->endpoint_list; ep; ep=ep->next) {
161 if (endpoints_match(ep->ep_description, ep_description)) {
169 find a registered context_id from a bind or alter_context
171 static struct dcesrv_connection_context *dcesrv_find_context(struct dcesrv_connection *conn,
174 struct dcesrv_connection_context *c;
175 for (c=conn->contexts;c;c=c->next) {
176 if (c->context_id == context_id) return c;
182 see if a uuid and if_version match to an interface
184 static bool interface_match(const struct dcesrv_interface *if1,
185 const struct dcesrv_interface *if2)
187 return (if1->syntax_id.if_version == if2->syntax_id.if_version &&
188 GUID_equal(&if1->syntax_id.uuid, &if2->syntax_id.uuid));
192 find the interface operations on an endpoint
194 static const struct dcesrv_interface *find_interface(const struct dcesrv_endpoint *endpoint,
195 const struct dcesrv_interface *iface)
197 struct dcesrv_if_list *ifl;
198 for (ifl=endpoint->interface_list; ifl; ifl=ifl->next) {
199 if (interface_match(&(ifl->iface), iface)) {
200 return &(ifl->iface);
207 see if a uuid and if_version match to an interface
209 static bool interface_match_by_uuid(const struct dcesrv_interface *iface,
210 const struct GUID *uuid, uint32_t if_version)
212 return (iface->syntax_id.if_version == if_version &&
213 GUID_equal(&iface->syntax_id.uuid, uuid));
217 find the interface operations on an endpoint by uuid
219 static const struct dcesrv_interface *find_interface_by_uuid(const struct dcesrv_endpoint *endpoint,
220 const struct GUID *uuid, uint32_t if_version)
222 struct dcesrv_if_list *ifl;
223 for (ifl=endpoint->interface_list; ifl; ifl=ifl->next) {
224 if (interface_match_by_uuid(&(ifl->iface), uuid, if_version)) {
225 return &(ifl->iface);
232 find the earlier parts of a fragmented call awaiting reassembily
234 static struct dcesrv_call_state *dcesrv_find_fragmented_call(struct dcesrv_connection *dce_conn, uint16_t call_id)
236 struct dcesrv_call_state *c;
237 for (c=dce_conn->incoming_fragmented_call_list;c;c=c->next) {
238 if (c->pkt.call_id == call_id) {
246 register an interface on an endpoint
248 _PUBLIC_ NTSTATUS dcesrv_interface_register(struct dcesrv_context *dce_ctx,
250 const struct dcesrv_interface *iface,
251 const struct security_descriptor *sd)
253 struct dcesrv_endpoint *ep;
254 struct dcesrv_if_list *ifl;
255 struct dcerpc_binding *binding;
259 status = dcerpc_parse_binding(dce_ctx, ep_name, &binding);
261 if (NT_STATUS_IS_ERR(status)) {
262 DEBUG(0, ("Trouble parsing binding string '%s'\n", ep_name));
266 /* check if this endpoint exists
268 if ((ep=find_endpoint(dce_ctx, binding))==NULL) {
269 ep = talloc_zero(dce_ctx, struct dcesrv_endpoint);
271 return NT_STATUS_NO_MEMORY;
274 ep->ep_description = talloc_move(ep, &binding);
277 /* add mgmt interface */
278 ifl = talloc_zero(ep, struct dcesrv_if_list);
280 return NT_STATUS_NO_MEMORY;
283 memcpy(&(ifl->iface), &dcesrv_mgmt_interface,
284 sizeof(struct dcesrv_interface));
286 DLIST_ADD(ep->interface_list, ifl);
289 /* see if the interface is already registered on te endpoint */
290 if (find_interface(ep, iface)!=NULL) {
291 DEBUG(0,("dcesrv_interface_register: interface '%s' already registered on endpoint '%s'\n",
292 iface->name, ep_name));
293 return NT_STATUS_OBJECT_NAME_COLLISION;
296 /* talloc a new interface list element */
297 ifl = talloc_zero(ep, struct dcesrv_if_list);
299 return NT_STATUS_NO_MEMORY;
302 /* copy the given interface struct to the one on the endpoints interface list */
303 memcpy(&(ifl->iface),iface, sizeof(struct dcesrv_interface));
305 /* if we have a security descriptor given,
306 * we should see if we can set it up on the endpoint
309 /* if there's currently no security descriptor given on the endpoint
312 if (ep->sd == NULL) {
313 ep->sd = security_descriptor_copy(ep, sd);
316 /* if now there's no security descriptor given on the endpoint
317 * something goes wrong, either we failed to copy the security descriptor
318 * or there was already one on the endpoint
320 if (ep->sd != NULL) {
321 DEBUG(0,("dcesrv_interface_register: interface '%s' failed to setup a security descriptor\n"
322 " on endpoint '%s'\n",
323 iface->name, ep_name));
324 if (add_ep) free(ep);
326 return NT_STATUS_OBJECT_NAME_COLLISION;
330 /* finally add the interface on the endpoint */
331 DLIST_ADD(ep->interface_list, ifl);
333 /* if it's a new endpoint add it to the dcesrv_context */
335 DLIST_ADD(dce_ctx->endpoint_list, ep);
338 DEBUG(4,("dcesrv_interface_register: interface '%s' registered on endpoint '%s'\n",
339 iface->name, ep_name));
344 NTSTATUS dcesrv_inherited_session_key(struct dcesrv_connection *p,
345 DATA_BLOB *session_key)
347 if (p->auth_state.session_info->session_key.length) {
348 *session_key = p->auth_state.session_info->session_key;
351 return NT_STATUS_NO_USER_SESSION_KEY;
355 fetch the user session key - may be default (above) or the SMB session key
357 The key is always truncated to 16 bytes
359 _PUBLIC_ NTSTATUS dcesrv_fetch_session_key(struct dcesrv_connection *p,
360 DATA_BLOB *session_key)
362 NTSTATUS status = p->auth_state.session_key(p, session_key);
363 if (!NT_STATUS_IS_OK(status)) {
367 session_key->length = MIN(session_key->length, 16);
373 connect to a dcerpc endpoint
375 _PUBLIC_ NTSTATUS dcesrv_endpoint_connect(struct dcesrv_context *dce_ctx,
377 const struct dcesrv_endpoint *ep,
378 struct auth_session_info *session_info,
379 struct tevent_context *event_ctx,
380 struct imessaging_context *msg_ctx,
381 struct server_id server_id,
382 uint32_t state_flags,
383 struct dcesrv_connection **_p)
385 struct dcesrv_connection *p;
388 return NT_STATUS_ACCESS_DENIED;
391 p = talloc_zero(mem_ctx, struct dcesrv_connection);
392 NT_STATUS_HAVE_NO_MEMORY(p);
394 if (!talloc_reference(p, session_info)) {
396 return NT_STATUS_NO_MEMORY;
399 p->dce_ctx = dce_ctx;
401 p->packet_log_dir = lpcfg_lock_directory(dce_ctx->lp_ctx);
402 p->auth_state.session_info = session_info;
403 p->auth_state.session_key = dcesrv_generic_session_key;
404 p->event_ctx = event_ctx;
405 p->msg_ctx = msg_ctx;
406 p->server_id = server_id;
407 p->state_flags = state_flags;
408 p->allow_bind = true;
409 p->max_recv_frag = 5840;
410 p->max_xmit_frag = 5840;
411 p->max_total_request_size = DCERPC_NCACN_REQUEST_DEFAULT_MAX_SIZE;
418 move a call from an existing linked list to the specified list. This
419 prevents bugs where we forget to remove the call from a previous
422 static void dcesrv_call_set_list(struct dcesrv_call_state *call,
423 enum dcesrv_call_list list)
425 switch (call->list) {
426 case DCESRV_LIST_NONE:
428 case DCESRV_LIST_CALL_LIST:
429 DLIST_REMOVE(call->conn->call_list, call);
431 case DCESRV_LIST_FRAGMENTED_CALL_LIST:
432 DLIST_REMOVE(call->conn->incoming_fragmented_call_list, call);
434 case DCESRV_LIST_PENDING_CALL_LIST:
435 DLIST_REMOVE(call->conn->pending_call_list, call);
440 case DCESRV_LIST_NONE:
442 case DCESRV_LIST_CALL_LIST:
443 DLIST_ADD_END(call->conn->call_list, call);
445 case DCESRV_LIST_FRAGMENTED_CALL_LIST:
446 DLIST_ADD_END(call->conn->incoming_fragmented_call_list, call);
448 case DCESRV_LIST_PENDING_CALL_LIST:
449 DLIST_ADD_END(call->conn->pending_call_list, call);
454 static void dcesrv_call_disconnect_after(struct dcesrv_call_state *call,
457 if (call->conn->terminate != NULL) {
461 call->conn->allow_bind = false;
462 call->conn->allow_alter = false;
463 call->conn->allow_auth3 = false;
464 call->conn->allow_request = false;
466 call->terminate_reason = talloc_strdup(call, reason);
467 if (call->terminate_reason == NULL) {
468 call->terminate_reason = __location__;
473 return a dcerpc bind_nak
475 static NTSTATUS dcesrv_bind_nak(struct dcesrv_call_state *call, uint32_t reason)
477 struct ncacn_packet pkt;
478 struct dcerpc_bind_nak_version version;
479 struct data_blob_list_item *rep;
481 static const uint8_t _pad[3] = { 0, };
484 * We add the call to the pending_call_list
485 * in order to defer the termination.
487 dcesrv_call_disconnect_after(call, "dcesrv_bind_nak");
489 /* setup a bind_nak */
490 dcesrv_init_hdr(&pkt, lpcfg_rpc_big_endian(call->conn->dce_ctx->lp_ctx));
492 pkt.call_id = call->pkt.call_id;
493 pkt.ptype = DCERPC_PKT_BIND_NAK;
494 pkt.pfc_flags = DCERPC_PFC_FLAG_FIRST | DCERPC_PFC_FLAG_LAST;
495 pkt.u.bind_nak.reject_reason = reason;
496 version.rpc_vers = 5;
497 version.rpc_vers_minor = 0;
498 pkt.u.bind_nak.num_versions = 1;
499 pkt.u.bind_nak.versions = &version;
500 pkt.u.bind_nak._pad = data_blob_const(_pad, sizeof(_pad));
502 rep = talloc_zero(call, struct data_blob_list_item);
504 return NT_STATUS_NO_MEMORY;
507 status = ncacn_push_auth(&rep->blob, call, &pkt, NULL);
508 if (!NT_STATUS_IS_OK(status)) {
512 dcerpc_set_frag_length(&rep->blob, rep->blob.length);
514 DLIST_ADD_END(call->replies, rep);
515 dcesrv_call_set_list(call, DCESRV_LIST_CALL_LIST);
517 if (call->conn->call_list && call->conn->call_list->replies) {
518 if (call->conn->transport.report_output_data) {
519 call->conn->transport.report_output_data(call->conn);
526 static NTSTATUS dcesrv_fault_disconnect(struct dcesrv_call_state *call,
530 * We add the call to the pending_call_list
531 * in order to defer the termination.
533 dcesrv_call_disconnect_after(call, "dcesrv_fault_disconnect");
535 return dcesrv_fault_with_flags(call, fault_code,
536 DCERPC_PFC_FLAG_DID_NOT_EXECUTE);
539 static int dcesrv_connection_context_destructor(struct dcesrv_connection_context *c)
541 DLIST_REMOVE(c->conn->contexts, c);
543 if (c->iface && c->iface->unbind) {
544 c->iface->unbind(c, c->iface);
551 static void dcesrv_prepare_context_auth(struct dcesrv_call_state *dce_call)
553 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
554 const struct dcesrv_endpoint *endpoint = dce_call->conn->endpoint;
555 enum dcerpc_transport_t transport =
556 dcerpc_binding_get_transport(endpoint->ep_description);
557 struct dcesrv_connection_context *context = dce_call->context;
558 const struct dcesrv_interface *iface = context->iface;
560 context->min_auth_level = DCERPC_AUTH_LEVEL_NONE;
562 if (transport == NCALRPC) {
563 context->allow_connect = true;
568 * allow overwrite per interface
569 * allow dcerpc auth level connect:<interface>
571 context->allow_connect = lpcfg_allow_dcerpc_auth_level_connect(lp_ctx);
572 context->allow_connect = lpcfg_parm_bool(lp_ctx, NULL,
573 "allow dcerpc auth level connect",
575 context->allow_connect);
578 NTSTATUS dcesrv_interface_bind_require_integrity(struct dcesrv_call_state *dce_call,
579 const struct dcesrv_interface *iface)
581 if (dce_call->context == NULL) {
582 return NT_STATUS_INTERNAL_ERROR;
586 * For connection oriented DCERPC DCERPC_AUTH_LEVEL_PACKET (4)
587 * has the same behavior as DCERPC_AUTH_LEVEL_INTEGRITY (5).
589 dce_call->context->min_auth_level = DCERPC_AUTH_LEVEL_PACKET;
593 NTSTATUS dcesrv_interface_bind_require_privacy(struct dcesrv_call_state *dce_call,
594 const struct dcesrv_interface *iface)
596 if (dce_call->context == NULL) {
597 return NT_STATUS_INTERNAL_ERROR;
600 dce_call->context->min_auth_level = DCERPC_AUTH_LEVEL_PRIVACY;
604 _PUBLIC_ NTSTATUS dcesrv_interface_bind_reject_connect(struct dcesrv_call_state *dce_call,
605 const struct dcesrv_interface *iface)
607 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
608 const struct dcesrv_endpoint *endpoint = dce_call->conn->endpoint;
609 enum dcerpc_transport_t transport =
610 dcerpc_binding_get_transport(endpoint->ep_description);
611 struct dcesrv_connection_context *context = dce_call->context;
613 if (context == NULL) {
614 return NT_STATUS_INTERNAL_ERROR;
617 if (transport == NCALRPC) {
618 context->allow_connect = true;
623 * allow overwrite per interface
624 * allow dcerpc auth level connect:<interface>
626 context->allow_connect = false;
627 context->allow_connect = lpcfg_parm_bool(lp_ctx, NULL,
628 "allow dcerpc auth level connect",
630 context->allow_connect);
634 _PUBLIC_ NTSTATUS dcesrv_interface_bind_allow_connect(struct dcesrv_call_state *dce_call,
635 const struct dcesrv_interface *iface)
637 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
638 const struct dcesrv_endpoint *endpoint = dce_call->conn->endpoint;
639 enum dcerpc_transport_t transport =
640 dcerpc_binding_get_transport(endpoint->ep_description);
641 struct dcesrv_connection_context *context = dce_call->context;
643 if (context == NULL) {
644 return NT_STATUS_INTERNAL_ERROR;
647 if (transport == NCALRPC) {
648 context->allow_connect = true;
653 * allow overwrite per interface
654 * allow dcerpc auth level connect:<interface>
656 context->allow_connect = true;
657 context->allow_connect = lpcfg_parm_bool(lp_ctx, NULL,
658 "allow dcerpc auth level connect",
660 context->allow_connect);
665 handle a bind request
667 static NTSTATUS dcesrv_bind(struct dcesrv_call_state *call)
669 uint32_t if_version, transfer_syntax_version;
670 struct GUID uuid, *transfer_syntax_uuid;
671 struct ncacn_packet pkt;
672 struct data_blob_list_item *rep;
674 uint32_t result=0, reason=0;
676 const struct dcesrv_interface *iface;
677 uint32_t extra_flags = 0;
678 uint16_t max_req = 0;
679 uint16_t max_rep = 0;
680 const char *ep_prefix = "";
681 const char *endpoint = NULL;
683 status = dcerpc_verify_ncacn_packet_header(&call->pkt,
685 call->pkt.u.bind.auth_info.length,
686 0, /* required flags */
687 DCERPC_PFC_FLAG_FIRST |
688 DCERPC_PFC_FLAG_LAST |
689 DCERPC_PFC_FLAG_SUPPORT_HEADER_SIGN |
690 0x08 | /* this is not defined, but should be ignored */
691 DCERPC_PFC_FLAG_CONC_MPX |
692 DCERPC_PFC_FLAG_DID_NOT_EXECUTE |
693 DCERPC_PFC_FLAG_MAYBE |
694 DCERPC_PFC_FLAG_OBJECT_UUID);
695 if (!NT_STATUS_IS_OK(status)) {
696 return dcesrv_bind_nak(call,
697 DCERPC_BIND_NAK_REASON_PROTOCOL_VERSION_NOT_SUPPORTED);
700 /* max_recv_frag and max_xmit_frag result always in the same value! */
701 max_req = MIN(call->pkt.u.bind.max_xmit_frag,
702 call->pkt.u.bind.max_recv_frag);
704 * The values are between 2048 and 5840 tested against Windows 2012R2
705 * via ncacn_ip_tcp on port 135.
707 max_req = MAX(2048, max_req);
708 max_rep = MIN(max_req, call->conn->max_recv_frag);
709 /* They are truncated to an 8 byte boundary. */
712 /* max_recv_frag and max_xmit_frag result always in the same value! */
713 call->conn->max_recv_frag = max_rep;
714 call->conn->max_xmit_frag = max_rep;
717 if provided, check the assoc_group is valid
719 if (call->pkt.u.bind.assoc_group_id != 0) {
720 call->conn->assoc_group = dcesrv_assoc_group_reference(call->conn,
722 call->pkt.u.bind.assoc_group_id);
724 call->conn->assoc_group = dcesrv_assoc_group_new(call->conn,
725 call->conn->dce_ctx);
727 if (call->conn->assoc_group == NULL) {
728 return dcesrv_bind_nak(call, 0);
731 if (call->pkt.u.bind.num_contexts < 1 ||
732 call->pkt.u.bind.ctx_list[0].num_transfer_syntaxes < 1) {
733 return dcesrv_bind_nak(call, 0);
736 context_id = call->pkt.u.bind.ctx_list[0].context_id;
737 if_version = call->pkt.u.bind.ctx_list[0].abstract_syntax.if_version;
738 uuid = call->pkt.u.bind.ctx_list[0].abstract_syntax.uuid;
740 transfer_syntax_version = call->pkt.u.bind.ctx_list[0].transfer_syntaxes[0].if_version;
741 transfer_syntax_uuid = &call->pkt.u.bind.ctx_list[0].transfer_syntaxes[0].uuid;
742 if (!GUID_equal(&ndr_transfer_syntax_ndr.uuid, transfer_syntax_uuid) != 0 ||
743 ndr_transfer_syntax_ndr.if_version != transfer_syntax_version) {
744 char *uuid_str = GUID_string(call, transfer_syntax_uuid);
745 /* we only do NDR encoded dcerpc */
746 DEBUG(0,("Non NDR transfer syntax requested - %s\n", uuid_str));
747 talloc_free(uuid_str);
748 return dcesrv_bind_nak(call, 0);
751 iface = find_interface_by_uuid(call->conn->endpoint, &uuid, if_version);
753 char *uuid_str = GUID_string(call, &uuid);
754 DEBUG(2,("Request for unknown dcerpc interface %s/%d\n", uuid_str, if_version));
755 talloc_free(uuid_str);
757 /* we don't know about that interface */
758 result = DCERPC_BIND_PROVIDER_REJECT;
759 reason = DCERPC_BIND_REASON_ASYNTAX;
763 /* add this context to the list of available context_ids */
764 struct dcesrv_connection_context *context = talloc_zero(call->conn,
765 struct dcesrv_connection_context);
766 if (context == NULL) {
767 return dcesrv_bind_nak(call, 0);
769 context->conn = call->conn;
770 context->iface = iface;
771 context->context_id = context_id;
772 context->private_data = NULL;
773 DLIST_ADD(call->conn->contexts, context);
774 call->context = context;
775 talloc_set_destructor(context, dcesrv_connection_context_destructor);
777 dcesrv_prepare_context_auth(call);
779 status = iface->bind(call, iface, if_version);
780 if (!NT_STATUS_IS_OK(status)) {
781 char *uuid_str = GUID_string(call, &uuid);
782 DEBUG(2,("Request for dcerpc interface %s/%d rejected: %s\n",
783 uuid_str, if_version, nt_errstr(status)));
784 talloc_free(uuid_str);
785 /* we don't want to trigger the iface->unbind() hook */
786 context->iface = NULL;
787 talloc_free(call->context);
788 call->context = NULL;
789 return dcesrv_bind_nak(call, 0);
793 if ((call->pkt.pfc_flags & DCERPC_PFC_FLAG_CONC_MPX) &&
794 (call->state_flags & DCESRV_CALL_STATE_FLAG_MULTIPLEXED)) {
795 call->context->conn->state_flags |= DCESRV_CALL_STATE_FLAG_MULTIPLEXED;
796 extra_flags |= DCERPC_PFC_FLAG_CONC_MPX;
799 if (call->state_flags & DCESRV_CALL_STATE_FLAG_PROCESS_PENDING_CALL) {
800 call->context->conn->state_flags |= DCESRV_CALL_STATE_FLAG_PROCESS_PENDING_CALL;
803 /* handle any authentication that is being requested */
804 if (!dcesrv_auth_bind(call)) {
805 struct dcesrv_auth *auth = &call->conn->auth_state;
807 TALLOC_FREE(call->context);
809 if (auth->auth_level == DCERPC_AUTH_LEVEL_NONE) {
811 * With DCERPC_AUTH_LEVEL_NONE, we get the
812 * reject_reason in auth->auth_context_id.
814 return dcesrv_bind_nak(call, auth->auth_context_id);
818 * This must a be a temporary failure e.g. talloc or invalid
819 * configuration, e.g. no machine account.
821 return dcesrv_bind_nak(call,
822 DCERPC_BIND_NAK_REASON_TEMPORARY_CONGESTION);
825 /* setup a bind_ack */
826 dcesrv_init_hdr(&pkt, lpcfg_rpc_big_endian(call->conn->dce_ctx->lp_ctx));
828 pkt.call_id = call->pkt.call_id;
829 pkt.ptype = DCERPC_PKT_BIND_ACK;
830 pkt.pfc_flags = DCERPC_PFC_FLAG_FIRST | DCERPC_PFC_FLAG_LAST | extra_flags;
831 pkt.u.bind_ack.max_xmit_frag = call->conn->max_xmit_frag;
832 pkt.u.bind_ack.max_recv_frag = call->conn->max_recv_frag;
833 pkt.u.bind_ack.assoc_group_id = call->conn->assoc_group->id;
836 endpoint = dcerpc_binding_get_string_option(
837 call->conn->endpoint->ep_description,
841 if (endpoint == NULL) {
845 if (strncasecmp(endpoint, "\\pipe\\", 6) == 0) {
847 * TODO: check if this is really needed
849 * Or if we should fix this in our idl files.
851 ep_prefix = "\\PIPE\\";
855 pkt.u.bind_ack.secondary_address = talloc_asprintf(call, "%s%s",
858 if (pkt.u.bind_ack.secondary_address == NULL) {
859 TALLOC_FREE(call->context);
860 return NT_STATUS_NO_MEMORY;
862 pkt.u.bind_ack.num_results = 1;
863 pkt.u.bind_ack.ctx_list = talloc_zero(call, struct dcerpc_ack_ctx);
864 if (!pkt.u.bind_ack.ctx_list) {
865 talloc_free(call->context);
866 call->context = NULL;
867 return NT_STATUS_NO_MEMORY;
869 pkt.u.bind_ack.ctx_list[0].result = result;
870 pkt.u.bind_ack.ctx_list[0].reason.value = reason;
871 pkt.u.bind_ack.ctx_list[0].syntax = ndr_transfer_syntax_ndr;
872 pkt.u.bind_ack.auth_info = data_blob(NULL, 0);
874 status = dcesrv_auth_bind_ack(call, &pkt);
875 if (!NT_STATUS_IS_OK(status)) {
876 talloc_free(call->context);
877 call->context = NULL;
878 return dcesrv_bind_nak(call, 0);
881 rep = talloc_zero(call, struct data_blob_list_item);
883 talloc_free(call->context);
884 call->context = NULL;
885 return NT_STATUS_NO_MEMORY;
888 status = ncacn_push_auth(&rep->blob, call, &pkt,
889 call->out_auth_info);
890 if (!NT_STATUS_IS_OK(status)) {
891 talloc_free(call->context);
892 call->context = NULL;
896 dcerpc_set_frag_length(&rep->blob, rep->blob.length);
898 DLIST_ADD_END(call->replies, rep);
899 dcesrv_call_set_list(call, DCESRV_LIST_CALL_LIST);
901 if (call->conn->call_list && call->conn->call_list->replies) {
902 if (call->conn->transport.report_output_data) {
903 call->conn->transport.report_output_data(call->conn);
912 handle a auth3 request
914 static NTSTATUS dcesrv_auth3(struct dcesrv_call_state *call)
918 if (!call->conn->allow_auth3) {
919 return dcesrv_fault_disconnect(call, DCERPC_NCA_S_PROTO_ERROR);
922 if (call->conn->auth_state.auth_finished) {
923 return dcesrv_fault_disconnect(call, DCERPC_NCA_S_PROTO_ERROR);
926 status = dcerpc_verify_ncacn_packet_header(&call->pkt,
928 call->pkt.u.auth3.auth_info.length,
929 0, /* required flags */
930 DCERPC_PFC_FLAG_FIRST |
931 DCERPC_PFC_FLAG_LAST |
932 DCERPC_PFC_FLAG_SUPPORT_HEADER_SIGN |
933 0x08 | /* this is not defined, but should be ignored */
934 DCERPC_PFC_FLAG_CONC_MPX |
935 DCERPC_PFC_FLAG_DID_NOT_EXECUTE |
936 DCERPC_PFC_FLAG_MAYBE |
937 DCERPC_PFC_FLAG_OBJECT_UUID);
938 if (!NT_STATUS_IS_OK(status)) {
939 return dcesrv_fault_disconnect(call, DCERPC_NCA_S_PROTO_ERROR);
942 /* handle the auth3 in the auth code */
943 if (!dcesrv_auth_auth3(call)) {
944 call->conn->auth_state.auth_invalid = true;
945 if (call->fault_code != 0) {
946 return dcesrv_fault_disconnect(call, call->fault_code);
952 /* we don't send a reply to a auth3 request, except by a
959 handle a bind request
961 static NTSTATUS dcesrv_alter_new_context(struct dcesrv_call_state *call, uint16_t context_id)
963 uint32_t if_version, transfer_syntax_version;
964 struct dcesrv_connection_context *context;
965 const struct dcesrv_interface *iface;
966 struct GUID uuid, *transfer_syntax_uuid;
969 if_version = call->pkt.u.alter.ctx_list[0].abstract_syntax.if_version;
970 uuid = call->pkt.u.alter.ctx_list[0].abstract_syntax.uuid;
972 transfer_syntax_version = call->pkt.u.alter.ctx_list[0].transfer_syntaxes[0].if_version;
973 transfer_syntax_uuid = &call->pkt.u.alter.ctx_list[0].transfer_syntaxes[0].uuid;
974 if (!GUID_equal(transfer_syntax_uuid, &ndr_transfer_syntax_ndr.uuid) ||
975 ndr_transfer_syntax_ndr.if_version != transfer_syntax_version) {
976 /* we only do NDR encoded dcerpc */
977 return NT_STATUS_RPC_PROTSEQ_NOT_SUPPORTED;
980 iface = find_interface_by_uuid(call->conn->endpoint, &uuid, if_version);
982 char *uuid_str = GUID_string(call, &uuid);
983 DEBUG(2,("Request for unknown dcerpc interface %s/%d\n", uuid_str, if_version));
984 talloc_free(uuid_str);
985 return NT_STATUS_RPC_PROTSEQ_NOT_SUPPORTED;
988 /* add this context to the list of available context_ids */
989 context = talloc_zero(call->conn, struct dcesrv_connection_context);
990 if (context == NULL) {
991 return NT_STATUS_NO_MEMORY;
993 context->conn = call->conn;
994 context->iface = iface;
995 context->context_id = context_id;
996 context->private_data = NULL;
997 DLIST_ADD(call->conn->contexts, context);
998 call->context = context;
999 talloc_set_destructor(context, dcesrv_connection_context_destructor);
1001 dcesrv_prepare_context_auth(call);
1003 status = iface->bind(call, iface, if_version);
1004 if (!NT_STATUS_IS_OK(status)) {
1005 /* we don't want to trigger the iface->unbind() hook */
1006 context->iface = NULL;
1007 talloc_free(context);
1008 call->context = NULL;
1012 return NT_STATUS_OK;
1015 /* setup and send an alter_resp */
1016 static NTSTATUS dcesrv_alter_resp(struct dcesrv_call_state *call,
1020 struct ncacn_packet pkt;
1021 uint32_t extra_flags = 0;
1022 struct data_blob_list_item *rep = NULL;
1025 dcesrv_init_hdr(&pkt, lpcfg_rpc_big_endian(call->conn->dce_ctx->lp_ctx));
1026 pkt.auth_length = 0;
1027 pkt.call_id = call->pkt.call_id;
1028 pkt.ptype = DCERPC_PKT_ALTER_RESP;
1030 if ((call->pkt.pfc_flags & DCERPC_PFC_FLAG_CONC_MPX) &&
1031 call->context->conn->state_flags &
1032 DCESRV_CALL_STATE_FLAG_MULTIPLEXED) {
1033 extra_flags |= DCERPC_PFC_FLAG_CONC_MPX;
1035 if (call->state_flags & DCESRV_CALL_STATE_FLAG_PROCESS_PENDING_CALL) {
1036 call->context->conn->state_flags |=
1037 DCESRV_CALL_STATE_FLAG_PROCESS_PENDING_CALL;
1040 pkt.pfc_flags = DCERPC_PFC_FLAG_FIRST | DCERPC_PFC_FLAG_LAST | extra_flags;
1041 pkt.u.alter_resp.max_xmit_frag = call->conn->max_xmit_frag;
1042 pkt.u.alter_resp.max_recv_frag = call->conn->max_recv_frag;
1043 pkt.u.alter_resp.assoc_group_id = call->conn->assoc_group->id;
1044 pkt.u.alter_resp.num_results = 1;
1045 pkt.u.alter_resp.ctx_list = talloc_zero(call, struct dcerpc_ack_ctx);
1046 if (!pkt.u.alter_resp.ctx_list) {
1047 return NT_STATUS_NO_MEMORY;
1049 pkt.u.alter_resp.ctx_list[0].result = result;
1050 pkt.u.alter_resp.ctx_list[0].reason.value = reason;
1051 pkt.u.alter_resp.ctx_list[0].syntax = ndr_transfer_syntax_ndr;
1052 pkt.u.alter_resp.auth_info = data_blob(NULL, 0);
1053 pkt.u.alter_resp.secondary_address = "";
1055 status = dcesrv_auth_alter_ack(call, &pkt);
1056 if (!NT_STATUS_IS_OK(status)) {
1057 return dcesrv_fault_disconnect(call, DCERPC_FAULT_SEC_PKG_ERROR);
1060 rep = talloc_zero(call, struct data_blob_list_item);
1062 return NT_STATUS_NO_MEMORY;
1065 status = ncacn_push_auth(&rep->blob, call, &pkt, call->out_auth_info);
1066 if (!NT_STATUS_IS_OK(status)) {
1070 dcerpc_set_frag_length(&rep->blob, rep->blob.length);
1072 DLIST_ADD_END(call->replies, rep);
1073 dcesrv_call_set_list(call, DCESRV_LIST_CALL_LIST);
1075 if (call->conn->call_list && call->conn->call_list->replies) {
1076 if (call->conn->transport.report_output_data) {
1077 call->conn->transport.report_output_data(call->conn);
1081 return NT_STATUS_OK;
1085 handle a alter context request
1087 static NTSTATUS dcesrv_alter(struct dcesrv_call_state *call)
1090 const struct dcerpc_ctx_list *ctx = NULL;
1091 bool auth_ok = false;
1093 if (!call->conn->allow_alter) {
1094 return dcesrv_fault_disconnect(call, DCERPC_NCA_S_PROTO_ERROR);
1097 status = dcerpc_verify_ncacn_packet_header(&call->pkt,
1099 call->pkt.u.alter.auth_info.length,
1100 0, /* required flags */
1101 DCERPC_PFC_FLAG_FIRST |
1102 DCERPC_PFC_FLAG_LAST |
1103 DCERPC_PFC_FLAG_SUPPORT_HEADER_SIGN |
1104 0x08 | /* this is not defined, but should be ignored */
1105 DCERPC_PFC_FLAG_CONC_MPX |
1106 DCERPC_PFC_FLAG_DID_NOT_EXECUTE |
1107 DCERPC_PFC_FLAG_MAYBE |
1108 DCERPC_PFC_FLAG_OBJECT_UUID);
1109 if (!NT_STATUS_IS_OK(status)) {
1110 return dcesrv_fault_disconnect(call, DCERPC_NCA_S_PROTO_ERROR);
1113 auth_ok = dcesrv_auth_alter(call);
1115 if (call->fault_code != 0) {
1116 return dcesrv_fault_disconnect(call, call->fault_code);
1120 if (call->pkt.u.alter.num_contexts < 1) {
1121 return dcesrv_fault_disconnect(call, DCERPC_NCA_S_PROTO_ERROR);
1123 ctx = &call->pkt.u.alter.ctx_list[0];
1124 if (ctx->num_transfer_syntaxes < 1) {
1125 return dcesrv_fault_disconnect(call, DCERPC_NCA_S_PROTO_ERROR);
1128 /* see if they are asking for a new interface */
1129 call->context = dcesrv_find_context(call->conn, ctx->context_id);
1130 if (!call->context) {
1131 status = dcesrv_alter_new_context(call, ctx->context_id);
1132 if (!NT_STATUS_IS_OK(status)) {
1133 return dcesrv_alter_resp(call,
1134 DCERPC_BIND_PROVIDER_REJECT,
1135 DCERPC_BIND_REASON_ASYNTAX);
1140 ok = ndr_syntax_id_equal(&ctx->abstract_syntax,
1141 &call->context->iface->syntax_id);
1143 return dcesrv_fault_disconnect(call,
1144 DCERPC_NCA_S_PROTO_ERROR);
1147 if (ctx->num_transfer_syntaxes != 1) {
1148 return dcesrv_fault_disconnect(call,
1149 DCERPC_NCA_S_PROTO_ERROR);
1152 ok = ndr_syntax_id_equal(&ctx->transfer_syntaxes[0],
1153 &ndr_transfer_syntax_ndr);
1155 return dcesrv_fault_disconnect(call,
1156 DCERPC_NCA_S_PROTO_ERROR);
1160 /* handle any authentication that is being requested */
1162 if (call->in_auth_info.auth_type !=
1163 call->conn->auth_state.auth_type)
1165 return dcesrv_fault_disconnect(call,
1166 DCERPC_FAULT_SEC_PKG_ERROR);
1168 return dcesrv_fault_disconnect(call, DCERPC_FAULT_ACCESS_DENIED);
1171 return dcesrv_alter_resp(call,
1172 DCERPC_BIND_ACK_RESULT_ACCEPTANCE,
1173 DCERPC_BIND_ACK_REASON_NOT_SPECIFIED);
1177 possibly save the call for inspection with ndrdump
1179 static void dcesrv_save_call(struct dcesrv_call_state *call, const char *why)
1183 const char *dump_dir;
1184 dump_dir = lpcfg_parm_string(call->conn->dce_ctx->lp_ctx, NULL, "dcesrv", "stubs directory");
1188 fname = talloc_asprintf(call, "%s/RPC-%s-%u-%s.dat",
1190 call->context->iface->name,
1191 call->pkt.u.request.opnum,
1193 if (file_save(fname, call->pkt.u.request.stub_and_verifier.data, call->pkt.u.request.stub_and_verifier.length)) {
1194 DEBUG(0,("RPC SAVED %s\n", fname));
1200 static NTSTATUS dcesrv_check_verification_trailer(struct dcesrv_call_state *call)
1202 TALLOC_CTX *frame = talloc_stackframe();
1203 const uint32_t bitmask1 = call->conn->auth_state.client_hdr_signing ?
1204 DCERPC_SEC_VT_CLIENT_SUPPORTS_HEADER_SIGNING : 0;
1205 const struct dcerpc_sec_vt_pcontext pcontext = {
1206 .abstract_syntax = call->context->iface->syntax_id,
1207 .transfer_syntax = ndr_transfer_syntax_ndr,
1209 const struct dcerpc_sec_vt_header2 header2 =
1210 dcerpc_sec_vt_header2_from_ncacn_packet(&call->pkt);
1211 enum ndr_err_code ndr_err;
1212 struct dcerpc_sec_verification_trailer *vt = NULL;
1213 NTSTATUS status = NT_STATUS_OK;
1216 SMB_ASSERT(call->pkt.ptype == DCERPC_PKT_REQUEST);
1218 ndr_err = ndr_pop_dcerpc_sec_verification_trailer(call->ndr_pull,
1220 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
1221 status = ndr_map_error2ntstatus(ndr_err);
1225 ok = dcerpc_sec_verification_trailer_check(vt, &bitmask1,
1226 &pcontext, &header2);
1228 status = NT_STATUS_ACCESS_DENIED;
1237 handle a dcerpc request packet
1239 static NTSTATUS dcesrv_request(struct dcesrv_call_state *call)
1241 const struct dcesrv_endpoint *endpoint = call->conn->endpoint;
1242 enum dcerpc_transport_t transport =
1243 dcerpc_binding_get_transport(endpoint->ep_description);
1244 struct ndr_pull *pull;
1246 struct dcesrv_connection_context *context;
1248 if (!call->conn->allow_request) {
1249 return dcesrv_fault_disconnect(call, DCERPC_NCA_S_PROTO_ERROR);
1252 /* if authenticated, and the mech we use can't do async replies, don't use them... */
1253 if (call->conn->auth_state.gensec_security &&
1254 !gensec_have_feature(call->conn->auth_state.gensec_security, GENSEC_FEATURE_ASYNC_REPLIES)) {
1255 call->state_flags &= ~DCESRV_CALL_STATE_FLAG_MAY_ASYNC;
1258 context = dcesrv_find_context(call->conn, call->pkt.u.request.context_id);
1259 if (context == NULL) {
1260 return dcesrv_fault_with_flags(call, DCERPC_NCA_S_UNKNOWN_IF,
1261 DCERPC_PFC_FLAG_DID_NOT_EXECUTE);
1264 switch (call->conn->auth_state.auth_level) {
1265 case DCERPC_AUTH_LEVEL_NONE:
1266 case DCERPC_AUTH_LEVEL_PACKET:
1267 case DCERPC_AUTH_LEVEL_INTEGRITY:
1268 case DCERPC_AUTH_LEVEL_PRIVACY:
1271 if (!context->allow_connect) {
1274 addr = tsocket_address_string(call->conn->remote_address,
1277 DEBUG(2, ("%s: restrict auth_level_connect access "
1278 "to [%s] with auth[type=0x%x,level=0x%x] "
1279 "on [%s] from [%s]\n",
1280 __func__, context->iface->name,
1281 call->conn->auth_state.auth_type,
1282 call->conn->auth_state.auth_level,
1283 derpc_transport_string_by_transport(transport),
1285 return dcesrv_fault(call, DCERPC_FAULT_ACCESS_DENIED);
1290 if (call->conn->auth_state.auth_level < context->min_auth_level) {
1293 addr = tsocket_address_string(call->conn->remote_address, call);
1295 DEBUG(2, ("%s: restrict access by min_auth_level[0x%x] "
1296 "to [%s] with auth[type=0x%x,level=0x%x] "
1297 "on [%s] from [%s]\n",
1299 context->min_auth_level,
1300 context->iface->name,
1301 call->conn->auth_state.auth_type,
1302 call->conn->auth_state.auth_level,
1303 derpc_transport_string_by_transport(transport),
1305 return dcesrv_fault(call, DCERPC_FAULT_ACCESS_DENIED);
1308 pull = ndr_pull_init_blob(&call->pkt.u.request.stub_and_verifier, call);
1309 NT_STATUS_HAVE_NO_MEMORY(pull);
1311 pull->flags |= LIBNDR_FLAG_REF_ALLOC;
1313 call->context = context;
1314 call->ndr_pull = pull;
1316 if (!(call->pkt.drep[0] & DCERPC_DREP_LE)) {
1317 pull->flags |= LIBNDR_FLAG_BIGENDIAN;
1320 status = dcesrv_check_verification_trailer(call);
1321 if (!NT_STATUS_IS_OK(status)) {
1322 uint32_t faultcode = DCERPC_FAULT_OTHER;
1323 if (NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
1324 faultcode = DCERPC_FAULT_ACCESS_DENIED;
1326 DEBUG(10, ("dcesrv_check_verification_trailer failed: %s\n",
1327 nt_errstr(status)));
1328 return dcesrv_fault(call, faultcode);
1331 /* unravel the NDR for the packet */
1332 status = context->iface->ndr_pull(call, call, pull, &call->r);
1333 if (!NT_STATUS_IS_OK(status)) {
1334 uint8_t extra_flags = 0;
1335 if (call->fault_code == DCERPC_FAULT_OP_RNG_ERROR) {
1336 /* we got an unknown call */
1337 DEBUG(3,(__location__ ": Unknown RPC call %u on %s\n",
1338 call->pkt.u.request.opnum, context->iface->name));
1339 dcesrv_save_call(call, "unknown");
1340 extra_flags |= DCERPC_PFC_FLAG_DID_NOT_EXECUTE;
1342 dcesrv_save_call(call, "pullfail");
1344 return dcesrv_fault_with_flags(call, call->fault_code, extra_flags);
1347 if (pull->offset != pull->data_size) {
1348 dcesrv_save_call(call, "extrabytes");
1349 DEBUG(3,("Warning: %d extra bytes in incoming RPC request\n",
1350 pull->data_size - pull->offset));
1353 /* call the dispatch function */
1354 status = context->iface->dispatch(call, call, call->r);
1355 if (!NT_STATUS_IS_OK(status)) {
1356 DEBUG(5,("dcerpc fault in call %s:%02x - %s\n",
1357 context->iface->name,
1358 call->pkt.u.request.opnum,
1359 dcerpc_errstr(pull, call->fault_code)));
1360 return dcesrv_fault(call, call->fault_code);
1363 /* add the call to the pending list */
1364 dcesrv_call_set_list(call, DCESRV_LIST_PENDING_CALL_LIST);
1366 if (call->state_flags & DCESRV_CALL_STATE_FLAG_ASYNC) {
1367 return NT_STATUS_OK;
1370 return dcesrv_reply(call);
1375 remove the call from the right list when freed
1377 static int dcesrv_call_dequeue(struct dcesrv_call_state *call)
1379 dcesrv_call_set_list(call, DCESRV_LIST_NONE);
1383 _PUBLIC_ const struct tsocket_address *dcesrv_connection_get_local_address(struct dcesrv_connection *conn)
1385 return conn->local_address;
1388 _PUBLIC_ const struct tsocket_address *dcesrv_connection_get_remote_address(struct dcesrv_connection *conn)
1390 return conn->remote_address;
1394 process some input to a dcerpc endpoint server.
1396 static NTSTATUS dcesrv_process_ncacn_packet(struct dcesrv_connection *dce_conn,
1397 struct ncacn_packet *pkt,
1401 struct dcesrv_call_state *call;
1402 struct dcesrv_call_state *existing = NULL;
1404 call = talloc_zero(dce_conn, struct dcesrv_call_state);
1406 data_blob_free(&blob);
1408 return NT_STATUS_NO_MEMORY;
1410 call->conn = dce_conn;
1411 call->event_ctx = dce_conn->event_ctx;
1412 call->msg_ctx = dce_conn->msg_ctx;
1413 call->state_flags = call->conn->state_flags;
1414 call->time = timeval_current();
1415 call->list = DCESRV_LIST_NONE;
1417 talloc_steal(call, pkt);
1418 talloc_steal(call, blob.data);
1421 talloc_set_destructor(call, dcesrv_call_dequeue);
1423 if (call->conn->allow_bind) {
1425 * Only one bind is possible per connection
1427 call->conn->allow_bind = false;
1428 return dcesrv_bind(call);
1431 /* we have to check the signing here, before combining the
1433 if (call->pkt.ptype == DCERPC_PKT_REQUEST) {
1434 if (!call->conn->allow_request) {
1435 return dcesrv_fault_disconnect(call,
1436 DCERPC_NCA_S_PROTO_ERROR);
1439 status = dcerpc_verify_ncacn_packet_header(&call->pkt,
1441 call->pkt.u.request.stub_and_verifier.length,
1442 0, /* required_flags */
1443 DCERPC_PFC_FLAG_FIRST |
1444 DCERPC_PFC_FLAG_LAST |
1445 DCERPC_PFC_FLAG_PENDING_CANCEL |
1446 0x08 | /* this is not defined, but should be ignored */
1447 DCERPC_PFC_FLAG_CONC_MPX |
1448 DCERPC_PFC_FLAG_DID_NOT_EXECUTE |
1449 DCERPC_PFC_FLAG_MAYBE |
1450 DCERPC_PFC_FLAG_OBJECT_UUID);
1451 if (!NT_STATUS_IS_OK(status)) {
1452 return dcesrv_fault_disconnect(call,
1453 DCERPC_NCA_S_PROTO_ERROR);
1456 if (call->pkt.frag_length > DCERPC_FRAG_MAX_SIZE) {
1458 * We don't use dcesrv_fault_disconnect()
1459 * here, because we don't want to set
1460 * DCERPC_PFC_FLAG_DID_NOT_EXECUTE
1462 * Note that we don't check against the negotiated
1463 * max_recv_frag, but a hard coded value.
1465 dcesrv_call_disconnect_after(call,
1466 "dcesrv_auth_request - frag_length too large");
1467 return dcesrv_fault(call,
1468 DCERPC_NCA_S_PROTO_ERROR);
1471 if (call->pkt.pfc_flags & DCERPC_PFC_FLAG_FIRST) {
1472 /* only one request is possible in the fragmented list */
1473 if (dce_conn->incoming_fragmented_call_list != NULL) {
1475 call = dce_conn->incoming_fragmented_call_list;
1476 dcesrv_call_disconnect_after(call,
1477 "dcesrv_auth_request - "
1478 "existing fragmented call");
1479 return dcesrv_fault(call,
1480 DCERPC_NCA_S_PROTO_ERROR);
1482 if (call->pkt.pfc_flags & DCERPC_PFC_FLAG_PENDING_CANCEL) {
1483 return dcesrv_fault_disconnect(call,
1484 DCERPC_FAULT_NO_CALL_ACTIVE);
1487 const struct dcerpc_request *nr = &call->pkt.u.request;
1488 const struct dcerpc_request *er = NULL;
1491 existing = dcesrv_find_fragmented_call(dce_conn,
1493 if (existing == NULL) {
1494 dcesrv_call_disconnect_after(call,
1495 "dcesrv_auth_request - "
1496 "no existing fragmented call");
1497 return dcesrv_fault(call,
1498 DCERPC_NCA_S_PROTO_ERROR);
1500 er = &existing->pkt.u.request;
1502 if (call->pkt.ptype != existing->pkt.ptype) {
1503 /* trying to play silly buggers are we? */
1504 return dcesrv_fault_disconnect(existing,
1505 DCERPC_NCA_S_PROTO_ERROR);
1507 cmp = memcmp(call->pkt.drep, existing->pkt.drep,
1510 return dcesrv_fault_disconnect(existing,
1511 DCERPC_NCA_S_PROTO_ERROR);
1513 if (nr->context_id != er->context_id) {
1514 return dcesrv_fault_disconnect(existing,
1515 DCERPC_NCA_S_PROTO_ERROR);
1517 if (nr->opnum != er->opnum) {
1518 return dcesrv_fault_disconnect(existing,
1519 DCERPC_NCA_S_PROTO_ERROR);
1523 if (!dcesrv_auth_request(call, &blob)) {
1525 * We don't use dcesrv_fault_disconnect()
1526 * here, because we don't want to set
1527 * DCERPC_PFC_FLAG_DID_NOT_EXECUTE
1529 dcesrv_call_disconnect_after(call,
1530 "dcesrv_auth_request - failed");
1531 if (call->fault_code == 0) {
1532 call->fault_code = DCERPC_FAULT_ACCESS_DENIED;
1534 return dcesrv_fault(call, call->fault_code);
1538 /* see if this is a continued packet */
1539 if (existing != NULL) {
1540 struct dcerpc_request *er = &existing->pkt.u.request;
1541 const struct dcerpc_request *nr = &call->pkt.u.request;
1547 * Up to 4 MByte are allowed by all fragments
1549 available = dce_conn->max_total_request_size;
1550 if (er->stub_and_verifier.length > available) {
1551 dcesrv_call_disconnect_after(existing,
1552 "dcesrv_auth_request - existing payload too large");
1553 return dcesrv_fault(existing, DCERPC_FAULT_ACCESS_DENIED);
1555 available -= er->stub_and_verifier.length;
1556 if (nr->alloc_hint > available) {
1557 dcesrv_call_disconnect_after(existing,
1558 "dcesrv_auth_request - alloc hint too large");
1559 return dcesrv_fault(existing, DCERPC_FAULT_ACCESS_DENIED);
1561 if (nr->stub_and_verifier.length > available) {
1562 dcesrv_call_disconnect_after(existing,
1563 "dcesrv_auth_request - new payload too large");
1564 return dcesrv_fault(existing, DCERPC_FAULT_ACCESS_DENIED);
1566 alloc_hint = er->stub_and_verifier.length + nr->alloc_hint;
1567 /* allocate at least 1 byte */
1568 alloc_hint = MAX(alloc_hint, 1);
1569 alloc_size = er->stub_and_verifier.length +
1570 nr->stub_and_verifier.length;
1571 alloc_size = MAX(alloc_size, alloc_hint);
1573 er->stub_and_verifier.data =
1574 talloc_realloc(existing,
1575 er->stub_and_verifier.data,
1576 uint8_t, alloc_size);
1577 if (er->stub_and_verifier.data == NULL) {
1579 return dcesrv_fault_with_flags(existing,
1580 DCERPC_FAULT_OUT_OF_RESOURCES,
1581 DCERPC_PFC_FLAG_DID_NOT_EXECUTE);
1583 memcpy(er->stub_and_verifier.data +
1584 er->stub_and_verifier.length,
1585 nr->stub_and_verifier.data,
1586 nr->stub_and_verifier.length);
1587 er->stub_and_verifier.length += nr->stub_and_verifier.length;
1589 existing->pkt.pfc_flags |= (call->pkt.pfc_flags & DCERPC_PFC_FLAG_LAST);
1595 /* this may not be the last pdu in the chain - if its isn't then
1596 just put it on the incoming_fragmented_call_list and wait for the rest */
1597 if (call->pkt.ptype == DCERPC_PKT_REQUEST &&
1598 !(call->pkt.pfc_flags & DCERPC_PFC_FLAG_LAST)) {
1600 * Up to 4 MByte are allowed by all fragments
1602 if (call->pkt.u.request.alloc_hint > dce_conn->max_total_request_size) {
1603 dcesrv_call_disconnect_after(call,
1604 "dcesrv_auth_request - initial alloc hint too large");
1605 return dcesrv_fault(call, DCERPC_FAULT_ACCESS_DENIED);
1607 dcesrv_call_set_list(call, DCESRV_LIST_FRAGMENTED_CALL_LIST);
1608 return NT_STATUS_OK;
1611 /* This removes any fragments we may have had stashed away */
1612 dcesrv_call_set_list(call, DCESRV_LIST_NONE);
1614 switch (call->pkt.ptype) {
1615 case DCERPC_PKT_BIND:
1616 status = dcesrv_bind_nak(call,
1617 DCERPC_BIND_NAK_REASON_NOT_SPECIFIED);
1619 case DCERPC_PKT_AUTH3:
1620 status = dcesrv_auth3(call);
1622 case DCERPC_PKT_ALTER:
1623 status = dcesrv_alter(call);
1625 case DCERPC_PKT_REQUEST:
1626 status = dcesrv_request(call);
1629 status = dcesrv_fault_disconnect(call, DCERPC_NCA_S_PROTO_ERROR);
1633 /* if we are going to be sending a reply then add
1634 it to the list of pending calls. We add it to the end to keep the call
1635 list in the order we will answer */
1636 if (!NT_STATUS_IS_OK(status)) {
1643 _PUBLIC_ NTSTATUS dcesrv_init_context(TALLOC_CTX *mem_ctx,
1644 struct loadparm_context *lp_ctx,
1645 const char **endpoint_servers, struct dcesrv_context **_dce_ctx)
1648 struct dcesrv_context *dce_ctx;
1651 if (!endpoint_servers) {
1652 DEBUG(0,("dcesrv_init_context: no endpoint servers configured\n"));
1653 return NT_STATUS_INTERNAL_ERROR;
1656 dce_ctx = talloc_zero(mem_ctx, struct dcesrv_context);
1657 NT_STATUS_HAVE_NO_MEMORY(dce_ctx);
1659 if (uid_wrapper_enabled()) {
1660 setenv("UID_WRAPPER_MYUID", "1", 1);
1662 dce_ctx->initial_euid = geteuid();
1663 if (uid_wrapper_enabled()) {
1664 unsetenv("UID_WRAPPER_MYUID");
1667 dce_ctx->endpoint_list = NULL;
1668 dce_ctx->lp_ctx = lp_ctx;
1669 dce_ctx->assoc_groups_idr = idr_init(dce_ctx);
1670 NT_STATUS_HAVE_NO_MEMORY(dce_ctx->assoc_groups_idr);
1671 dce_ctx->broken_connections = NULL;
1673 for (i=0;endpoint_servers[i];i++) {
1674 const struct dcesrv_endpoint_server *ep_server;
1676 ep_server = dcesrv_ep_server_byname(endpoint_servers[i]);
1678 DEBUG(0,("dcesrv_init_context: failed to find endpoint server = '%s'\n", endpoint_servers[i]));
1679 return NT_STATUS_INTERNAL_ERROR;
1682 status = ep_server->init_server(dce_ctx, ep_server);
1683 if (!NT_STATUS_IS_OK(status)) {
1684 DEBUG(0,("dcesrv_init_context: failed to init endpoint server = '%s': %s\n", endpoint_servers[i],
1685 nt_errstr(status)));
1690 *_dce_ctx = dce_ctx;
1691 return NT_STATUS_OK;
1694 /* the list of currently registered DCERPC endpoint servers.
1696 static struct ep_server {
1697 struct dcesrv_endpoint_server *ep_server;
1698 } *ep_servers = NULL;
1699 static int num_ep_servers;
1702 register a DCERPC endpoint server.
1704 The 'name' can be later used by other backends to find the operations
1705 structure for this backend.
1707 The 'type' is used to specify whether this is for a disk, printer or IPC$ share
1709 _PUBLIC_ NTSTATUS dcerpc_register_ep_server(const void *_ep_server)
1711 const struct dcesrv_endpoint_server *ep_server = _ep_server;
1713 if (dcesrv_ep_server_byname(ep_server->name) != NULL) {
1714 /* its already registered! */
1715 DEBUG(0,("DCERPC endpoint server '%s' already registered\n",
1717 return NT_STATUS_OBJECT_NAME_COLLISION;
1720 ep_servers = realloc_p(ep_servers, struct ep_server, num_ep_servers+1);
1722 smb_panic("out of memory in dcerpc_register");
1725 ep_servers[num_ep_servers].ep_server = smb_xmemdup(ep_server, sizeof(*ep_server));
1726 ep_servers[num_ep_servers].ep_server->name = smb_xstrdup(ep_server->name);
1730 DEBUG(3,("DCERPC endpoint server '%s' registered\n",
1733 return NT_STATUS_OK;
1737 return the operations structure for a named backend of the specified type
1739 const struct dcesrv_endpoint_server *dcesrv_ep_server_byname(const char *name)
1743 for (i=0;i<num_ep_servers;i++) {
1744 if (strcmp(ep_servers[i].ep_server->name, name) == 0) {
1745 return ep_servers[i].ep_server;
1752 void dcerpc_server_init(struct loadparm_context *lp_ctx)
1754 static bool initialized;
1755 #define _MODULE_PROTO(init) extern NTSTATUS init(void);
1756 STATIC_dcerpc_server_MODULES_PROTO;
1757 init_module_fn static_init[] = { STATIC_dcerpc_server_MODULES };
1758 init_module_fn *shared_init;
1765 shared_init = load_samba_modules(NULL, "dcerpc_server");
1767 run_init_functions(static_init);
1768 run_init_functions(shared_init);
1770 talloc_free(shared_init);
1774 return the DCERPC module version, and the size of some critical types
1775 This can be used by endpoint server modules to either detect compilation errors, or provide
1776 multiple implementations for different smbd compilation options in one module
1778 const struct dcesrv_critical_sizes *dcerpc_module_version(void)
1780 static const struct dcesrv_critical_sizes critical_sizes = {
1781 DCERPC_MODULE_VERSION,
1782 sizeof(struct dcesrv_context),
1783 sizeof(struct dcesrv_endpoint),
1784 sizeof(struct dcesrv_endpoint_server),
1785 sizeof(struct dcesrv_interface),
1786 sizeof(struct dcesrv_if_list),
1787 sizeof(struct dcesrv_connection),
1788 sizeof(struct dcesrv_call_state),
1789 sizeof(struct dcesrv_auth),
1790 sizeof(struct dcesrv_handle)
1793 return &critical_sizes;
1796 static void dcesrv_terminate_connection(struct dcesrv_connection *dce_conn, const char *reason)
1798 struct dcesrv_context *dce_ctx = dce_conn->dce_ctx;
1799 struct stream_connection *srv_conn;
1800 srv_conn = talloc_get_type(dce_conn->transport.private_data,
1801 struct stream_connection);
1803 dce_conn->allow_bind = false;
1804 dce_conn->allow_auth3 = false;
1805 dce_conn->allow_alter = false;
1806 dce_conn->allow_request = false;
1808 if (dce_conn->pending_call_list == NULL) {
1809 char *full_reason = talloc_asprintf(dce_conn, "dcesrv: %s", reason);
1811 DLIST_REMOVE(dce_ctx->broken_connections, dce_conn);
1812 stream_terminate_connection(srv_conn, full_reason ? full_reason : reason);
1816 if (dce_conn->terminate != NULL) {
1820 DEBUG(3,("dcesrv: terminating connection due to '%s' defered due to pending calls\n",
1822 dce_conn->terminate = talloc_strdup(dce_conn, reason);
1823 if (dce_conn->terminate == NULL) {
1824 dce_conn->terminate = "dcesrv: defered terminating connection - no memory";
1826 DLIST_ADD_END(dce_ctx->broken_connections, dce_conn);
1829 static void dcesrv_cleanup_broken_connections(struct dcesrv_context *dce_ctx)
1831 struct dcesrv_connection *cur, *next;
1833 next = dce_ctx->broken_connections;
1834 while (next != NULL) {
1838 if (cur->state_flags & DCESRV_CALL_STATE_FLAG_PROCESS_PENDING_CALL) {
1839 struct dcesrv_connection_context *context_cur, *context_next;
1841 context_next = cur->contexts;
1842 while (context_next != NULL) {
1843 context_cur = context_next;
1844 context_next = context_cur->next;
1846 dcesrv_connection_context_destructor(context_cur);
1850 dcesrv_terminate_connection(cur, cur->terminate);
1854 /* We need this include to be able to compile on some plateforms
1855 * (ie. freebsd 7.2) as it seems that <sys/uio.h> is not included
1857 * It has to be that deep because otherwise we have a conflict on
1858 * const struct dcesrv_interface declaration.
1859 * This is mostly due to socket_wrapper defining #define bind swrap_bind
1860 * which conflict with the bind used before.
1862 #include "system/network.h"
1864 struct dcesrv_sock_reply_state {
1865 struct dcesrv_connection *dce_conn;
1866 struct dcesrv_call_state *call;
1870 static void dcesrv_sock_reply_done(struct tevent_req *subreq);
1871 static void dcesrv_call_terminate_step1(struct tevent_req *subreq);
1873 static void dcesrv_sock_report_output_data(struct dcesrv_connection *dce_conn)
1875 struct dcesrv_call_state *call;
1877 call = dce_conn->call_list;
1878 if (!call || !call->replies) {
1882 while (call->replies) {
1883 struct data_blob_list_item *rep = call->replies;
1884 struct dcesrv_sock_reply_state *substate;
1885 struct tevent_req *subreq;
1887 substate = talloc_zero(call, struct dcesrv_sock_reply_state);
1889 dcesrv_terminate_connection(dce_conn, "no memory");
1893 substate->dce_conn = dce_conn;
1894 substate->call = NULL;
1896 DLIST_REMOVE(call->replies, rep);
1898 if (call->replies == NULL && call->terminate_reason == NULL) {
1899 substate->call = call;
1902 substate->iov.iov_base = (void *) rep->blob.data;
1903 substate->iov.iov_len = rep->blob.length;
1905 subreq = tstream_writev_queue_send(substate,
1906 dce_conn->event_ctx,
1908 dce_conn->send_queue,
1911 dcesrv_terminate_connection(dce_conn, "no memory");
1914 tevent_req_set_callback(subreq, dcesrv_sock_reply_done,
1918 if (call->terminate_reason != NULL) {
1919 struct tevent_req *subreq;
1921 subreq = tevent_queue_wait_send(call,
1922 dce_conn->event_ctx,
1923 dce_conn->send_queue);
1925 dcesrv_terminate_connection(dce_conn, __location__);
1928 tevent_req_set_callback(subreq, dcesrv_call_terminate_step1,
1932 DLIST_REMOVE(call->conn->call_list, call);
1933 call->list = DCESRV_LIST_NONE;
1936 static void dcesrv_sock_reply_done(struct tevent_req *subreq)
1938 struct dcesrv_sock_reply_state *substate = tevent_req_callback_data(subreq,
1939 struct dcesrv_sock_reply_state);
1943 struct dcesrv_call_state *call = substate->call;
1945 ret = tstream_writev_queue_recv(subreq, &sys_errno);
1946 TALLOC_FREE(subreq);
1948 status = map_nt_error_from_unix_common(sys_errno);
1949 dcesrv_terminate_connection(substate->dce_conn, nt_errstr(status));
1953 talloc_free(substate);
1959 static void dcesrv_call_terminate_step2(struct tevent_req *subreq);
1961 static void dcesrv_call_terminate_step1(struct tevent_req *subreq)
1963 struct dcesrv_call_state *call = tevent_req_callback_data(subreq,
1964 struct dcesrv_call_state);
1968 /* make sure we stop send queue before removing subreq */
1969 tevent_queue_stop(call->conn->send_queue);
1971 ok = tevent_queue_wait_recv(subreq);
1972 TALLOC_FREE(subreq);
1974 dcesrv_terminate_connection(call->conn, __location__);
1978 /* disconnect after 200 usecs */
1979 tv = timeval_current_ofs_usec(200);
1980 subreq = tevent_wakeup_send(call, call->conn->event_ctx, tv);
1981 if (subreq == NULL) {
1982 dcesrv_terminate_connection(call->conn, __location__);
1985 tevent_req_set_callback(subreq, dcesrv_call_terminate_step2,
1989 static void dcesrv_call_terminate_step2(struct tevent_req *subreq)
1991 struct dcesrv_call_state *call = tevent_req_callback_data(subreq,
1992 struct dcesrv_call_state);
1995 ok = tevent_wakeup_recv(subreq);
1996 TALLOC_FREE(subreq);
1998 dcesrv_terminate_connection(call->conn, __location__);
2002 dcesrv_terminate_connection(call->conn, call->terminate_reason);
2005 struct dcesrv_socket_context {
2006 const struct dcesrv_endpoint *endpoint;
2007 struct dcesrv_context *dcesrv_ctx;
2011 static void dcesrv_read_fragment_done(struct tevent_req *subreq);
2013 static void dcesrv_sock_accept(struct stream_connection *srv_conn)
2016 struct dcesrv_socket_context *dcesrv_sock =
2017 talloc_get_type(srv_conn->private_data, struct dcesrv_socket_context);
2018 enum dcerpc_transport_t transport =
2019 dcerpc_binding_get_transport(dcesrv_sock->endpoint->ep_description);
2020 struct dcesrv_connection *dcesrv_conn = NULL;
2022 struct tevent_req *subreq;
2023 struct loadparm_context *lp_ctx = dcesrv_sock->dcesrv_ctx->lp_ctx;
2025 dcesrv_cleanup_broken_connections(dcesrv_sock->dcesrv_ctx);
2027 if (!srv_conn->session_info) {
2028 status = auth_anonymous_session_info(srv_conn,
2030 &srv_conn->session_info);
2031 if (!NT_STATUS_IS_OK(status)) {
2032 DEBUG(0,("dcesrv_sock_accept: auth_anonymous_session_info failed: %s\n",
2033 nt_errstr(status)));
2034 stream_terminate_connection(srv_conn, nt_errstr(status));
2039 status = dcesrv_endpoint_connect(dcesrv_sock->dcesrv_ctx,
2041 dcesrv_sock->endpoint,
2042 srv_conn->session_info,
2043 srv_conn->event.ctx,
2045 srv_conn->server_id,
2046 DCESRV_CALL_STATE_FLAG_MAY_ASYNC,
2048 if (!NT_STATUS_IS_OK(status)) {
2049 DEBUG(0,("dcesrv_sock_accept: dcesrv_endpoint_connect failed: %s\n",
2050 nt_errstr(status)));
2051 stream_terminate_connection(srv_conn, nt_errstr(status));
2055 dcesrv_conn->transport.private_data = srv_conn;
2056 dcesrv_conn->transport.report_output_data = dcesrv_sock_report_output_data;
2058 TALLOC_FREE(srv_conn->event.fde);
2060 dcesrv_conn->send_queue = tevent_queue_create(dcesrv_conn, "dcesrv send queue");
2061 if (!dcesrv_conn->send_queue) {
2062 status = NT_STATUS_NO_MEMORY;
2063 DEBUG(0,("dcesrv_sock_accept: tevent_queue_create(%s)\n",
2064 nt_errstr(status)));
2065 stream_terminate_connection(srv_conn, nt_errstr(status));
2069 if (transport == NCACN_NP) {
2070 dcesrv_conn->auth_state.session_key = dcesrv_inherited_session_key;
2071 dcesrv_conn->stream = talloc_move(dcesrv_conn,
2072 &srv_conn->tstream);
2074 ret = tstream_bsd_existing_socket(dcesrv_conn,
2075 socket_get_fd(srv_conn->socket),
2076 &dcesrv_conn->stream);
2078 status = map_nt_error_from_unix_common(errno);
2079 DEBUG(0, ("dcesrv_sock_accept: "
2080 "failed to setup tstream: %s\n",
2081 nt_errstr(status)));
2082 stream_terminate_connection(srv_conn, nt_errstr(status));
2085 socket_set_flags(srv_conn->socket, SOCKET_FLAG_NOCLOSE);
2088 dcesrv_conn->local_address = srv_conn->local_address;
2089 dcesrv_conn->remote_address = srv_conn->remote_address;
2091 if (transport == NCALRPC) {
2096 sock_fd = socket_get_fd(srv_conn->socket);
2097 if (sock_fd == -1) {
2098 stream_terminate_connection(
2099 srv_conn, "socket_get_fd failed\n");
2103 ret = getpeereid(sock_fd, &uid, &gid);
2105 status = map_nt_error_from_unix_common(errno);
2106 DEBUG(0, ("dcesrv_sock_accept: "
2107 "getpeereid() failed for NCALRPC: %s\n",
2108 nt_errstr(status)));
2109 stream_terminate_connection(srv_conn, nt_errstr(status));
2112 if (uid == dcesrv_conn->dce_ctx->initial_euid) {
2113 struct tsocket_address *r = NULL;
2115 ret = tsocket_address_unix_from_path(dcesrv_conn,
2116 "/root/ncalrpc_as_system",
2119 status = map_nt_error_from_unix_common(errno);
2120 DEBUG(0, ("dcesrv_sock_accept: "
2121 "tsocket_address_unix_from_path() failed for NCALRPC: %s\n",
2122 nt_errstr(status)));
2123 stream_terminate_connection(srv_conn, nt_errstr(status));
2126 dcesrv_conn->remote_address = r;
2130 srv_conn->private_data = dcesrv_conn;
2132 irpc_add_name(srv_conn->msg_ctx, "rpc_server");
2134 subreq = dcerpc_read_ncacn_packet_send(dcesrv_conn,
2135 dcesrv_conn->event_ctx,
2136 dcesrv_conn->stream);
2138 status = NT_STATUS_NO_MEMORY;
2139 DEBUG(0,("dcesrv_sock_accept: dcerpc_read_fragment_buffer_send(%s)\n",
2140 nt_errstr(status)));
2141 stream_terminate_connection(srv_conn, nt_errstr(status));
2144 tevent_req_set_callback(subreq, dcesrv_read_fragment_done, dcesrv_conn);
2149 static void dcesrv_read_fragment_done(struct tevent_req *subreq)
2151 struct dcesrv_connection *dce_conn = tevent_req_callback_data(subreq,
2152 struct dcesrv_connection);
2153 struct dcesrv_context *dce_ctx = dce_conn->dce_ctx;
2154 struct ncacn_packet *pkt;
2158 if (dce_conn->terminate) {
2160 * if the current connection is broken
2161 * we need to clean it up before any other connection
2163 dcesrv_terminate_connection(dce_conn, dce_conn->terminate);
2164 dcesrv_cleanup_broken_connections(dce_ctx);
2168 dcesrv_cleanup_broken_connections(dce_ctx);
2170 status = dcerpc_read_ncacn_packet_recv(subreq, dce_conn,
2172 TALLOC_FREE(subreq);
2173 if (!NT_STATUS_IS_OK(status)) {
2174 dcesrv_terminate_connection(dce_conn, nt_errstr(status));
2178 status = dcesrv_process_ncacn_packet(dce_conn, pkt, buffer);
2179 if (!NT_STATUS_IS_OK(status)) {
2180 dcesrv_terminate_connection(dce_conn, nt_errstr(status));
2184 subreq = dcerpc_read_ncacn_packet_send(dce_conn,
2185 dce_conn->event_ctx,
2188 status = NT_STATUS_NO_MEMORY;
2189 dcesrv_terminate_connection(dce_conn, nt_errstr(status));
2192 tevent_req_set_callback(subreq, dcesrv_read_fragment_done, dce_conn);
2195 static void dcesrv_sock_recv(struct stream_connection *conn, uint16_t flags)
2197 struct dcesrv_connection *dce_conn = talloc_get_type(conn->private_data,
2198 struct dcesrv_connection);
2199 dcesrv_terminate_connection(dce_conn, "dcesrv_sock_recv triggered");
2202 static void dcesrv_sock_send(struct stream_connection *conn, uint16_t flags)
2204 struct dcesrv_connection *dce_conn = talloc_get_type(conn->private_data,
2205 struct dcesrv_connection);
2206 dcesrv_terminate_connection(dce_conn, "dcesrv_sock_send triggered");
2210 static const struct stream_server_ops dcesrv_stream_ops = {
2212 .accept_connection = dcesrv_sock_accept,
2213 .recv_handler = dcesrv_sock_recv,
2214 .send_handler = dcesrv_sock_send,
2217 static NTSTATUS dcesrv_add_ep_unix(struct dcesrv_context *dce_ctx,
2218 struct loadparm_context *lp_ctx,
2219 struct dcesrv_endpoint *e,
2220 struct tevent_context *event_ctx, const struct model_ops *model_ops)
2222 struct dcesrv_socket_context *dcesrv_sock;
2225 const char *endpoint;
2227 dcesrv_sock = talloc_zero(event_ctx, struct dcesrv_socket_context);
2228 NT_STATUS_HAVE_NO_MEMORY(dcesrv_sock);
2230 /* remember the endpoint of this socket */
2231 dcesrv_sock->endpoint = e;
2232 dcesrv_sock->dcesrv_ctx = talloc_reference(dcesrv_sock, dce_ctx);
2234 endpoint = dcerpc_binding_get_string_option(e->ep_description, "endpoint");
2236 status = stream_setup_socket(dcesrv_sock, event_ctx, lp_ctx,
2237 model_ops, &dcesrv_stream_ops,
2238 "unix", endpoint, &port,
2239 lpcfg_socket_options(lp_ctx),
2241 if (!NT_STATUS_IS_OK(status)) {
2242 DEBUG(0,("service_setup_stream_socket(path=%s) failed - %s\n",
2243 endpoint, nt_errstr(status)));
2249 static NTSTATUS dcesrv_add_ep_ncalrpc(struct dcesrv_context *dce_ctx,
2250 struct loadparm_context *lp_ctx,
2251 struct dcesrv_endpoint *e,
2252 struct tevent_context *event_ctx, const struct model_ops *model_ops)
2254 struct dcesrv_socket_context *dcesrv_sock;
2258 const char *endpoint;
2260 endpoint = dcerpc_binding_get_string_option(e->ep_description, "endpoint");
2262 if (endpoint == NULL) {
2264 * No identifier specified: use DEFAULT.
2266 * TODO: DO NOT hardcode this value anywhere else. Rather, specify
2267 * no endpoint and let the epmapper worry about it.
2269 endpoint = "DEFAULT";
2270 status = dcerpc_binding_set_string_option(e->ep_description,
2273 if (!NT_STATUS_IS_OK(status)) {
2274 DEBUG(0,("dcerpc_binding_set_string_option() failed - %s\n",
2275 nt_errstr(status)));
2280 full_path = talloc_asprintf(dce_ctx, "%s/%s", lpcfg_ncalrpc_dir(lp_ctx),
2283 dcesrv_sock = talloc_zero(event_ctx, struct dcesrv_socket_context);
2284 NT_STATUS_HAVE_NO_MEMORY(dcesrv_sock);
2286 /* remember the endpoint of this socket */
2287 dcesrv_sock->endpoint = e;
2288 dcesrv_sock->dcesrv_ctx = talloc_reference(dcesrv_sock, dce_ctx);
2290 status = stream_setup_socket(dcesrv_sock, event_ctx, lp_ctx,
2291 model_ops, &dcesrv_stream_ops,
2292 "unix", full_path, &port,
2293 lpcfg_socket_options(lp_ctx),
2295 if (!NT_STATUS_IS_OK(status)) {
2296 DEBUG(0,("service_setup_stream_socket(identifier=%s,path=%s) failed - %s\n",
2297 endpoint, full_path, nt_errstr(status)));
2302 static NTSTATUS dcesrv_add_ep_np(struct dcesrv_context *dce_ctx,
2303 struct loadparm_context *lp_ctx,
2304 struct dcesrv_endpoint *e,
2305 struct tevent_context *event_ctx, const struct model_ops *model_ops)
2307 struct dcesrv_socket_context *dcesrv_sock;
2309 const char *endpoint;
2311 endpoint = dcerpc_binding_get_string_option(e->ep_description, "endpoint");
2312 if (endpoint == NULL) {
2313 DEBUG(0, ("Endpoint mandatory for named pipes\n"));
2314 return NT_STATUS_INVALID_PARAMETER;
2317 dcesrv_sock = talloc_zero(event_ctx, struct dcesrv_socket_context);
2318 NT_STATUS_HAVE_NO_MEMORY(dcesrv_sock);
2320 /* remember the endpoint of this socket */
2321 dcesrv_sock->endpoint = e;
2322 dcesrv_sock->dcesrv_ctx = talloc_reference(dcesrv_sock, dce_ctx);
2324 status = tstream_setup_named_pipe(dce_ctx, event_ctx, lp_ctx,
2325 model_ops, &dcesrv_stream_ops,
2328 if (!NT_STATUS_IS_OK(status)) {
2329 DEBUG(0,("stream_setup_named_pipe(pipe=%s) failed - %s\n",
2330 endpoint, nt_errstr(status)));
2334 return NT_STATUS_OK;
2338 add a socket address to the list of events, one event per dcerpc endpoint
2340 static NTSTATUS add_socket_rpc_tcp_iface(struct dcesrv_context *dce_ctx, struct dcesrv_endpoint *e,
2341 struct tevent_context *event_ctx, const struct model_ops *model_ops,
2342 const char *address)
2344 struct dcesrv_socket_context *dcesrv_sock;
2347 const char *endpoint;
2350 endpoint = dcerpc_binding_get_string_option(e->ep_description, "endpoint");
2351 if (endpoint != NULL) {
2352 port = atoi(endpoint);
2355 dcesrv_sock = talloc_zero(event_ctx, struct dcesrv_socket_context);
2356 NT_STATUS_HAVE_NO_MEMORY(dcesrv_sock);
2358 /* remember the endpoint of this socket */
2359 dcesrv_sock->endpoint = e;
2360 dcesrv_sock->dcesrv_ctx = talloc_reference(dcesrv_sock, dce_ctx);
2362 status = stream_setup_socket(dcesrv_sock, event_ctx, dce_ctx->lp_ctx,
2363 model_ops, &dcesrv_stream_ops,
2364 "ip", address, &port,
2365 lpcfg_socket_options(dce_ctx->lp_ctx),
2367 if (!NT_STATUS_IS_OK(status)) {
2368 DEBUG(0,("service_setup_stream_socket(address=%s,port=%u) failed - %s\n",
2369 address, port, nt_errstr(status)));
2373 snprintf(port_str, sizeof(port_str), "%u", port);
2375 status = dcerpc_binding_set_string_option(e->ep_description,
2376 "endpoint", port_str);
2377 if (!NT_STATUS_IS_OK(status)) {
2378 DEBUG(0,("dcerpc_binding_set_string_option(endpoint, %s) failed - %s\n",
2379 port_str, nt_errstr(status)));
2383 return NT_STATUS_OK;
2386 #include "lib/socket/netif.h" /* Included here to work around the fact that socket_wrapper redefines bind() */
2388 static NTSTATUS dcesrv_add_ep_tcp(struct dcesrv_context *dce_ctx,
2389 struct loadparm_context *lp_ctx,
2390 struct dcesrv_endpoint *e,
2391 struct tevent_context *event_ctx, const struct model_ops *model_ops)
2395 /* Add TCP/IP sockets */
2396 if (lpcfg_interfaces(lp_ctx) && lpcfg_bind_interfaces_only(lp_ctx)) {
2399 struct interface *ifaces;
2401 load_interface_list(dce_ctx, lp_ctx, &ifaces);
2403 num_interfaces = iface_list_count(ifaces);
2404 for(i = 0; i < num_interfaces; i++) {
2405 const char *address = iface_list_n_ip(ifaces, i);
2406 status = add_socket_rpc_tcp_iface(dce_ctx, e, event_ctx, model_ops, address);
2407 NT_STATUS_NOT_OK_RETURN(status);
2413 wcard = iface_list_wildcard(dce_ctx);
2414 NT_STATUS_HAVE_NO_MEMORY(wcard);
2415 for (i=0; wcard[i]; i++) {
2416 status = add_socket_rpc_tcp_iface(dce_ctx, e, event_ctx, model_ops, wcard[i]);
2417 if (NT_STATUS_IS_OK(status)) {
2422 if (num_binds == 0) {
2423 return NT_STATUS_INVALID_PARAMETER_MIX;
2427 return NT_STATUS_OK;
2430 NTSTATUS dcesrv_add_ep(struct dcesrv_context *dce_ctx,
2431 struct loadparm_context *lp_ctx,
2432 struct dcesrv_endpoint *e,
2433 struct tevent_context *event_ctx,
2434 const struct model_ops *model_ops)
2436 enum dcerpc_transport_t transport =
2437 dcerpc_binding_get_transport(e->ep_description);
2439 switch (transport) {
2440 case NCACN_UNIX_STREAM:
2441 return dcesrv_add_ep_unix(dce_ctx, lp_ctx, e, event_ctx, model_ops);
2444 return dcesrv_add_ep_ncalrpc(dce_ctx, lp_ctx, e, event_ctx, model_ops);
2447 return dcesrv_add_ep_tcp(dce_ctx, lp_ctx, e, event_ctx, model_ops);
2450 return dcesrv_add_ep_np(dce_ctx, lp_ctx, e, event_ctx, model_ops);
2453 return NT_STATUS_NOT_SUPPORTED;
2459 * retrieve credentials from a dce_call
2461 _PUBLIC_ struct cli_credentials *dcesrv_call_credentials(struct dcesrv_call_state *dce_call)
2463 return dce_call->conn->auth_state.session_info->credentials;
2467 * returns true if this is an authenticated call
2469 _PUBLIC_ bool dcesrv_call_authenticated(struct dcesrv_call_state *dce_call)
2471 enum security_user_level level;
2472 level = security_session_user_level(dce_call->conn->auth_state.session_info, NULL);
2473 return level >= SECURITY_USER;
2477 * retrieve account_name for a dce_call
2479 _PUBLIC_ const char *dcesrv_call_account_name(struct dcesrv_call_state *dce_call)
2481 return dce_call->context->conn->auth_state.session_info->info->account_name;