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;
417 move a call from an existing linked list to the specified list. This
418 prevents bugs where we forget to remove the call from a previous
421 static void dcesrv_call_set_list(struct dcesrv_call_state *call,
422 enum dcesrv_call_list list)
424 switch (call->list) {
425 case DCESRV_LIST_NONE:
427 case DCESRV_LIST_CALL_LIST:
428 DLIST_REMOVE(call->conn->call_list, call);
430 case DCESRV_LIST_FRAGMENTED_CALL_LIST:
431 DLIST_REMOVE(call->conn->incoming_fragmented_call_list, call);
433 case DCESRV_LIST_PENDING_CALL_LIST:
434 DLIST_REMOVE(call->conn->pending_call_list, call);
439 case DCESRV_LIST_NONE:
441 case DCESRV_LIST_CALL_LIST:
442 DLIST_ADD_END(call->conn->call_list, call);
444 case DCESRV_LIST_FRAGMENTED_CALL_LIST:
445 DLIST_ADD_END(call->conn->incoming_fragmented_call_list, call);
447 case DCESRV_LIST_PENDING_CALL_LIST:
448 DLIST_ADD_END(call->conn->pending_call_list, call);
453 static void dcesrv_call_disconnect_after(struct dcesrv_call_state *call,
456 if (call->conn->terminate != NULL) {
460 call->conn->allow_bind = false;
461 call->conn->allow_alter = false;
462 call->conn->allow_auth3 = false;
463 call->conn->allow_request = false;
465 call->terminate_reason = talloc_strdup(call, reason);
466 if (call->terminate_reason == NULL) {
467 call->terminate_reason = __location__;
472 return a dcerpc bind_nak
474 static NTSTATUS dcesrv_bind_nak(struct dcesrv_call_state *call, uint32_t reason)
476 struct ncacn_packet pkt;
477 struct dcerpc_bind_nak_version version;
478 struct data_blob_list_item *rep;
480 static const uint8_t _pad[3] = { 0, };
483 * We add the call to the pending_call_list
484 * in order to defer the termination.
486 dcesrv_call_disconnect_after(call, "dcesrv_bind_nak");
488 /* setup a bind_nak */
489 dcesrv_init_hdr(&pkt, lpcfg_rpc_big_endian(call->conn->dce_ctx->lp_ctx));
491 pkt.call_id = call->pkt.call_id;
492 pkt.ptype = DCERPC_PKT_BIND_NAK;
493 pkt.pfc_flags = DCERPC_PFC_FLAG_FIRST | DCERPC_PFC_FLAG_LAST;
494 pkt.u.bind_nak.reject_reason = reason;
495 version.rpc_vers = 5;
496 version.rpc_vers_minor = 0;
497 pkt.u.bind_nak.num_versions = 1;
498 pkt.u.bind_nak.versions = &version;
499 pkt.u.bind_nak._pad = data_blob_const(_pad, sizeof(_pad));
501 rep = talloc_zero(call, struct data_blob_list_item);
503 return NT_STATUS_NO_MEMORY;
506 status = ncacn_push_auth(&rep->blob, call, &pkt, NULL);
507 if (!NT_STATUS_IS_OK(status)) {
511 dcerpc_set_frag_length(&rep->blob, rep->blob.length);
513 DLIST_ADD_END(call->replies, rep);
514 dcesrv_call_set_list(call, DCESRV_LIST_CALL_LIST);
516 if (call->conn->call_list && call->conn->call_list->replies) {
517 if (call->conn->transport.report_output_data) {
518 call->conn->transport.report_output_data(call->conn);
525 static NTSTATUS dcesrv_fault_disconnect(struct dcesrv_call_state *call,
529 * We add the call to the pending_call_list
530 * in order to defer the termination.
532 dcesrv_call_disconnect_after(call, "dcesrv_fault_disconnect");
534 return dcesrv_fault_with_flags(call, fault_code,
535 DCERPC_PFC_FLAG_DID_NOT_EXECUTE);
538 static int dcesrv_connection_context_destructor(struct dcesrv_connection_context *c)
540 DLIST_REMOVE(c->conn->contexts, c);
542 if (c->iface && c->iface->unbind) {
543 c->iface->unbind(c, c->iface);
550 static void dcesrv_prepare_context_auth(struct dcesrv_call_state *dce_call)
552 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
553 const struct dcesrv_endpoint *endpoint = dce_call->conn->endpoint;
554 enum dcerpc_transport_t transport =
555 dcerpc_binding_get_transport(endpoint->ep_description);
556 struct dcesrv_connection_context *context = dce_call->context;
557 const struct dcesrv_interface *iface = context->iface;
559 context->min_auth_level = DCERPC_AUTH_LEVEL_NONE;
561 if (transport == NCALRPC) {
562 context->allow_connect = true;
567 * allow overwrite per interface
568 * allow dcerpc auth level connect:<interface>
570 context->allow_connect = lpcfg_allow_dcerpc_auth_level_connect(lp_ctx);
571 context->allow_connect = lpcfg_parm_bool(lp_ctx, NULL,
572 "allow dcerpc auth level connect",
574 context->allow_connect);
577 NTSTATUS dcesrv_interface_bind_require_integrity(struct dcesrv_call_state *dce_call,
578 const struct dcesrv_interface *iface)
580 if (dce_call->context == NULL) {
581 return NT_STATUS_INTERNAL_ERROR;
584 dce_call->context->min_auth_level = DCERPC_AUTH_LEVEL_INTEGRITY;
588 NTSTATUS dcesrv_interface_bind_require_privacy(struct dcesrv_call_state *dce_call,
589 const struct dcesrv_interface *iface)
591 if (dce_call->context == NULL) {
592 return NT_STATUS_INTERNAL_ERROR;
595 dce_call->context->min_auth_level = DCERPC_AUTH_LEVEL_PRIVACY;
599 _PUBLIC_ NTSTATUS dcesrv_interface_bind_reject_connect(struct dcesrv_call_state *dce_call,
600 const struct dcesrv_interface *iface)
602 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
603 const struct dcesrv_endpoint *endpoint = dce_call->conn->endpoint;
604 enum dcerpc_transport_t transport =
605 dcerpc_binding_get_transport(endpoint->ep_description);
606 struct dcesrv_connection_context *context = dce_call->context;
608 if (context == NULL) {
609 return NT_STATUS_INTERNAL_ERROR;
612 if (transport == NCALRPC) {
613 context->allow_connect = true;
618 * allow overwrite per interface
619 * allow dcerpc auth level connect:<interface>
621 context->allow_connect = false;
622 context->allow_connect = lpcfg_parm_bool(lp_ctx, NULL,
623 "allow dcerpc auth level connect",
625 context->allow_connect);
629 _PUBLIC_ NTSTATUS dcesrv_interface_bind_allow_connect(struct dcesrv_call_state *dce_call,
630 const struct dcesrv_interface *iface)
632 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
633 const struct dcesrv_endpoint *endpoint = dce_call->conn->endpoint;
634 enum dcerpc_transport_t transport =
635 dcerpc_binding_get_transport(endpoint->ep_description);
636 struct dcesrv_connection_context *context = dce_call->context;
638 if (context == NULL) {
639 return NT_STATUS_INTERNAL_ERROR;
642 if (transport == NCALRPC) {
643 context->allow_connect = true;
648 * allow overwrite per interface
649 * allow dcerpc auth level connect:<interface>
651 context->allow_connect = true;
652 context->allow_connect = lpcfg_parm_bool(lp_ctx, NULL,
653 "allow dcerpc auth level connect",
655 context->allow_connect);
660 handle a bind request
662 static NTSTATUS dcesrv_bind(struct dcesrv_call_state *call)
664 uint32_t if_version, transfer_syntax_version;
665 struct GUID uuid, *transfer_syntax_uuid;
666 struct ncacn_packet pkt;
667 struct data_blob_list_item *rep;
669 uint32_t result=0, reason=0;
671 const struct dcesrv_interface *iface;
672 uint32_t extra_flags = 0;
673 uint16_t max_req = 0;
674 uint16_t max_rep = 0;
675 const char *ep_prefix = "";
676 const char *endpoint = NULL;
678 status = dcerpc_verify_ncacn_packet_header(&call->pkt,
680 call->pkt.u.bind.auth_info.length,
681 0, /* required flags */
682 DCERPC_PFC_FLAG_FIRST |
683 DCERPC_PFC_FLAG_LAST |
684 DCERPC_PFC_FLAG_SUPPORT_HEADER_SIGN |
685 0x08 | /* this is not defined, but should be ignored */
686 DCERPC_PFC_FLAG_CONC_MPX |
687 DCERPC_PFC_FLAG_DID_NOT_EXECUTE |
688 DCERPC_PFC_FLAG_MAYBE |
689 DCERPC_PFC_FLAG_OBJECT_UUID);
690 if (!NT_STATUS_IS_OK(status)) {
691 return dcesrv_bind_nak(call,
692 DCERPC_BIND_NAK_REASON_PROTOCOL_VERSION_NOT_SUPPORTED);
695 /* max_recv_frag and max_xmit_frag result always in the same value! */
696 max_req = MIN(call->pkt.u.bind.max_xmit_frag,
697 call->pkt.u.bind.max_recv_frag);
699 * The values are between 2048 and 5840 tested against Windows 2012R2
700 * via ncacn_ip_tcp on port 135.
702 max_req = MAX(2048, max_req);
703 max_rep = MIN(max_req, call->conn->max_recv_frag);
704 /* They are truncated to an 8 byte boundary. */
707 /* max_recv_frag and max_xmit_frag result always in the same value! */
708 call->conn->max_recv_frag = max_rep;
709 call->conn->max_xmit_frag = max_rep;
712 if provided, check the assoc_group is valid
714 if (call->pkt.u.bind.assoc_group_id != 0) {
715 call->conn->assoc_group = dcesrv_assoc_group_reference(call->conn,
717 call->pkt.u.bind.assoc_group_id);
719 call->conn->assoc_group = dcesrv_assoc_group_new(call->conn,
720 call->conn->dce_ctx);
722 if (call->conn->assoc_group == NULL) {
723 return dcesrv_bind_nak(call, 0);
726 if (call->pkt.u.bind.num_contexts < 1 ||
727 call->pkt.u.bind.ctx_list[0].num_transfer_syntaxes < 1) {
728 return dcesrv_bind_nak(call, 0);
731 context_id = call->pkt.u.bind.ctx_list[0].context_id;
732 if_version = call->pkt.u.bind.ctx_list[0].abstract_syntax.if_version;
733 uuid = call->pkt.u.bind.ctx_list[0].abstract_syntax.uuid;
735 transfer_syntax_version = call->pkt.u.bind.ctx_list[0].transfer_syntaxes[0].if_version;
736 transfer_syntax_uuid = &call->pkt.u.bind.ctx_list[0].transfer_syntaxes[0].uuid;
737 if (!GUID_equal(&ndr_transfer_syntax_ndr.uuid, transfer_syntax_uuid) != 0 ||
738 ndr_transfer_syntax_ndr.if_version != transfer_syntax_version) {
739 char *uuid_str = GUID_string(call, transfer_syntax_uuid);
740 /* we only do NDR encoded dcerpc */
741 DEBUG(0,("Non NDR transfer syntax requested - %s\n", uuid_str));
742 talloc_free(uuid_str);
743 return dcesrv_bind_nak(call, 0);
746 iface = find_interface_by_uuid(call->conn->endpoint, &uuid, if_version);
748 char *uuid_str = GUID_string(call, &uuid);
749 DEBUG(2,("Request for unknown dcerpc interface %s/%d\n", uuid_str, if_version));
750 talloc_free(uuid_str);
752 /* we don't know about that interface */
753 result = DCERPC_BIND_PROVIDER_REJECT;
754 reason = DCERPC_BIND_REASON_ASYNTAX;
758 /* add this context to the list of available context_ids */
759 struct dcesrv_connection_context *context = talloc_zero(call->conn,
760 struct dcesrv_connection_context);
761 if (context == NULL) {
762 return dcesrv_bind_nak(call, 0);
764 context->conn = call->conn;
765 context->iface = iface;
766 context->context_id = context_id;
767 /* legacy for openchange dcesrv_mapiproxy.c */
768 context->assoc_group = call->conn->assoc_group;
769 context->private_data = NULL;
770 DLIST_ADD(call->conn->contexts, context);
771 call->context = context;
772 talloc_set_destructor(context, dcesrv_connection_context_destructor);
774 dcesrv_prepare_context_auth(call);
776 status = iface->bind(call, iface, if_version);
777 if (!NT_STATUS_IS_OK(status)) {
778 char *uuid_str = GUID_string(call, &uuid);
779 DEBUG(2,("Request for dcerpc interface %s/%d rejected: %s\n",
780 uuid_str, if_version, nt_errstr(status)));
781 talloc_free(uuid_str);
782 /* we don't want to trigger the iface->unbind() hook */
783 context->iface = NULL;
784 talloc_free(call->context);
785 call->context = NULL;
786 return dcesrv_bind_nak(call, 0);
790 if ((call->pkt.pfc_flags & DCERPC_PFC_FLAG_CONC_MPX) &&
791 (call->state_flags & DCESRV_CALL_STATE_FLAG_MULTIPLEXED)) {
792 call->context->conn->state_flags |= DCESRV_CALL_STATE_FLAG_MULTIPLEXED;
793 extra_flags |= DCERPC_PFC_FLAG_CONC_MPX;
796 if (call->state_flags & DCESRV_CALL_STATE_FLAG_PROCESS_PENDING_CALL) {
797 call->context->conn->state_flags |= DCESRV_CALL_STATE_FLAG_PROCESS_PENDING_CALL;
800 /* handle any authentication that is being requested */
801 if (!dcesrv_auth_bind(call)) {
802 struct dcesrv_auth *auth = &call->conn->auth_state;
804 TALLOC_FREE(call->context);
806 if (auth->auth_level != DCERPC_AUTH_LEVEL_NONE) {
808 * We only give INVALID_AUTH_TYPE if the auth_level was
811 return dcesrv_bind_nak(call,
812 DCERPC_BIND_NAK_REASON_INVALID_AUTH_TYPE);
814 return dcesrv_bind_nak(call,
815 DCERPC_BIND_NAK_REASON_NOT_SPECIFIED);
818 /* setup a bind_ack */
819 dcesrv_init_hdr(&pkt, lpcfg_rpc_big_endian(call->conn->dce_ctx->lp_ctx));
821 pkt.call_id = call->pkt.call_id;
822 pkt.ptype = DCERPC_PKT_BIND_ACK;
823 pkt.pfc_flags = DCERPC_PFC_FLAG_FIRST | DCERPC_PFC_FLAG_LAST | extra_flags;
824 pkt.u.bind_ack.max_xmit_frag = call->conn->max_xmit_frag;
825 pkt.u.bind_ack.max_recv_frag = call->conn->max_recv_frag;
826 pkt.u.bind_ack.assoc_group_id = call->conn->assoc_group->id;
829 endpoint = dcerpc_binding_get_string_option(
830 call->conn->endpoint->ep_description,
834 if (endpoint == NULL) {
838 if (strncasecmp(endpoint, "\\pipe\\", 6) == 0) {
840 * TODO: check if this is really needed
842 * Or if we should fix this in our idl files.
844 ep_prefix = "\\PIPE\\";
848 pkt.u.bind_ack.secondary_address = talloc_asprintf(call, "%s%s",
851 if (pkt.u.bind_ack.secondary_address == NULL) {
852 TALLOC_FREE(call->context);
853 return NT_STATUS_NO_MEMORY;
855 pkt.u.bind_ack.num_results = 1;
856 pkt.u.bind_ack.ctx_list = talloc_zero(call, struct dcerpc_ack_ctx);
857 if (!pkt.u.bind_ack.ctx_list) {
858 talloc_free(call->context);
859 call->context = NULL;
860 return NT_STATUS_NO_MEMORY;
862 pkt.u.bind_ack.ctx_list[0].result = result;
863 pkt.u.bind_ack.ctx_list[0].reason.value = reason;
864 pkt.u.bind_ack.ctx_list[0].syntax = ndr_transfer_syntax_ndr;
865 pkt.u.bind_ack.auth_info = data_blob(NULL, 0);
867 status = dcesrv_auth_bind_ack(call, &pkt);
868 if (!NT_STATUS_IS_OK(status)) {
869 talloc_free(call->context);
870 call->context = NULL;
871 return dcesrv_bind_nak(call, 0);
874 rep = talloc_zero(call, struct data_blob_list_item);
876 talloc_free(call->context);
877 call->context = NULL;
878 return NT_STATUS_NO_MEMORY;
881 status = ncacn_push_auth(&rep->blob, call, &pkt,
882 call->out_auth_info);
883 if (!NT_STATUS_IS_OK(status)) {
884 talloc_free(call->context);
885 call->context = NULL;
889 dcerpc_set_frag_length(&rep->blob, rep->blob.length);
891 DLIST_ADD_END(call->replies, rep);
892 dcesrv_call_set_list(call, DCESRV_LIST_CALL_LIST);
894 if (call->conn->call_list && call->conn->call_list->replies) {
895 if (call->conn->transport.report_output_data) {
896 call->conn->transport.report_output_data(call->conn);
905 handle a auth3 request
907 static NTSTATUS dcesrv_auth3(struct dcesrv_call_state *call)
911 if (!call->conn->allow_auth3) {
912 return dcesrv_fault_disconnect(call, DCERPC_NCA_S_PROTO_ERROR);
915 if (call->conn->auth_state.auth_finished) {
916 return dcesrv_fault_disconnect(call, DCERPC_NCA_S_PROTO_ERROR);
919 status = dcerpc_verify_ncacn_packet_header(&call->pkt,
921 call->pkt.u.auth3.auth_info.length,
922 0, /* required flags */
923 DCERPC_PFC_FLAG_FIRST |
924 DCERPC_PFC_FLAG_LAST |
925 DCERPC_PFC_FLAG_SUPPORT_HEADER_SIGN |
926 0x08 | /* this is not defined, but should be ignored */
927 DCERPC_PFC_FLAG_CONC_MPX |
928 DCERPC_PFC_FLAG_DID_NOT_EXECUTE |
929 DCERPC_PFC_FLAG_MAYBE |
930 DCERPC_PFC_FLAG_OBJECT_UUID);
931 if (!NT_STATUS_IS_OK(status)) {
932 return dcesrv_fault_disconnect(call, DCERPC_NCA_S_PROTO_ERROR);
935 /* handle the auth3 in the auth code */
936 if (!dcesrv_auth_auth3(call)) {
937 call->conn->auth_state.auth_invalid = true;
942 /* we don't send a reply to a auth3 request, except by a
949 handle a bind request
951 static NTSTATUS dcesrv_alter_new_context(struct dcesrv_call_state *call, uint32_t context_id)
953 uint32_t if_version, transfer_syntax_version;
954 struct dcesrv_connection_context *context;
955 const struct dcesrv_interface *iface;
956 struct GUID uuid, *transfer_syntax_uuid;
959 if_version = call->pkt.u.alter.ctx_list[0].abstract_syntax.if_version;
960 uuid = call->pkt.u.alter.ctx_list[0].abstract_syntax.uuid;
962 transfer_syntax_version = call->pkt.u.alter.ctx_list[0].transfer_syntaxes[0].if_version;
963 transfer_syntax_uuid = &call->pkt.u.alter.ctx_list[0].transfer_syntaxes[0].uuid;
964 if (!GUID_equal(transfer_syntax_uuid, &ndr_transfer_syntax_ndr.uuid) ||
965 ndr_transfer_syntax_ndr.if_version != transfer_syntax_version) {
966 /* we only do NDR encoded dcerpc */
967 return NT_STATUS_RPC_PROTSEQ_NOT_SUPPORTED;
970 iface = find_interface_by_uuid(call->conn->endpoint, &uuid, if_version);
972 char *uuid_str = GUID_string(call, &uuid);
973 DEBUG(2,("Request for unknown dcerpc interface %s/%d\n", uuid_str, if_version));
974 talloc_free(uuid_str);
975 return NT_STATUS_RPC_PROTSEQ_NOT_SUPPORTED;
978 /* add this context to the list of available context_ids */
979 context = talloc_zero(call->conn, struct dcesrv_connection_context);
980 if (context == NULL) {
981 return NT_STATUS_NO_MEMORY;
983 context->conn = call->conn;
984 context->iface = iface;
985 context->context_id = context_id;
986 /* legacy for openchange dcesrv_mapiproxy.c */
987 context->assoc_group = call->conn->assoc_group;
988 context->private_data = NULL;
989 DLIST_ADD(call->conn->contexts, context);
990 call->context = context;
991 talloc_set_destructor(context, dcesrv_connection_context_destructor);
993 dcesrv_prepare_context_auth(call);
995 status = iface->bind(call, iface, if_version);
996 if (!NT_STATUS_IS_OK(status)) {
997 /* we don't want to trigger the iface->unbind() hook */
998 context->iface = NULL;
999 talloc_free(context);
1000 call->context = NULL;
1004 return NT_STATUS_OK;
1007 /* setup and send an alter_resp */
1008 static NTSTATUS dcesrv_alter_resp(struct dcesrv_call_state *call,
1012 struct ncacn_packet pkt;
1013 uint32_t extra_flags = 0;
1014 struct data_blob_list_item *rep = NULL;
1017 dcesrv_init_hdr(&pkt, lpcfg_rpc_big_endian(call->conn->dce_ctx->lp_ctx));
1018 pkt.auth_length = 0;
1019 pkt.call_id = call->pkt.call_id;
1020 pkt.ptype = DCERPC_PKT_ALTER_RESP;
1022 if ((call->pkt.pfc_flags & DCERPC_PFC_FLAG_CONC_MPX) &&
1023 call->context->conn->state_flags &
1024 DCESRV_CALL_STATE_FLAG_MULTIPLEXED) {
1025 extra_flags |= DCERPC_PFC_FLAG_CONC_MPX;
1027 if (call->state_flags & DCESRV_CALL_STATE_FLAG_PROCESS_PENDING_CALL) {
1028 call->context->conn->state_flags |=
1029 DCESRV_CALL_STATE_FLAG_PROCESS_PENDING_CALL;
1032 pkt.pfc_flags = DCERPC_PFC_FLAG_FIRST | DCERPC_PFC_FLAG_LAST | extra_flags;
1033 pkt.u.alter_resp.max_xmit_frag = call->conn->max_xmit_frag;
1034 pkt.u.alter_resp.max_recv_frag = call->conn->max_recv_frag;
1035 pkt.u.alter_resp.assoc_group_id = call->conn->assoc_group->id;
1036 pkt.u.alter_resp.num_results = 1;
1037 pkt.u.alter_resp.ctx_list = talloc_zero(call, struct dcerpc_ack_ctx);
1038 if (!pkt.u.alter_resp.ctx_list) {
1039 return NT_STATUS_NO_MEMORY;
1041 pkt.u.alter_resp.ctx_list[0].result = result;
1042 pkt.u.alter_resp.ctx_list[0].reason.value = reason;
1043 pkt.u.alter_resp.ctx_list[0].syntax = ndr_transfer_syntax_ndr;
1044 pkt.u.alter_resp.auth_info = data_blob(NULL, 0);
1045 pkt.u.alter_resp.secondary_address = "";
1047 status = dcesrv_auth_alter_ack(call, &pkt);
1048 if (!NT_STATUS_IS_OK(status)) {
1049 return dcesrv_fault_disconnect(call, DCERPC_FAULT_SEC_PKG_ERROR);
1052 rep = talloc_zero(call, struct data_blob_list_item);
1054 return NT_STATUS_NO_MEMORY;
1057 status = ncacn_push_auth(&rep->blob, call, &pkt, call->out_auth_info);
1058 if (!NT_STATUS_IS_OK(status)) {
1062 dcerpc_set_frag_length(&rep->blob, rep->blob.length);
1064 DLIST_ADD_END(call->replies, rep);
1065 dcesrv_call_set_list(call, DCESRV_LIST_CALL_LIST);
1067 if (call->conn->call_list && call->conn->call_list->replies) {
1068 if (call->conn->transport.report_output_data) {
1069 call->conn->transport.report_output_data(call->conn);
1073 return NT_STATUS_OK;
1077 handle a alter context request
1079 static NTSTATUS dcesrv_alter(struct dcesrv_call_state *call)
1082 const struct dcerpc_ctx_list *ctx = NULL;
1083 bool auth_ok = false;
1085 if (!call->conn->allow_alter) {
1086 return dcesrv_fault_disconnect(call, DCERPC_NCA_S_PROTO_ERROR);
1089 status = dcerpc_verify_ncacn_packet_header(&call->pkt,
1091 call->pkt.u.alter.auth_info.length,
1092 0, /* required flags */
1093 DCERPC_PFC_FLAG_FIRST |
1094 DCERPC_PFC_FLAG_LAST |
1095 DCERPC_PFC_FLAG_SUPPORT_HEADER_SIGN |
1096 0x08 | /* this is not defined, but should be ignored */
1097 DCERPC_PFC_FLAG_CONC_MPX |
1098 DCERPC_PFC_FLAG_DID_NOT_EXECUTE |
1099 DCERPC_PFC_FLAG_MAYBE |
1100 DCERPC_PFC_FLAG_OBJECT_UUID);
1101 if (!NT_STATUS_IS_OK(status)) {
1102 return dcesrv_fault_disconnect(call, DCERPC_NCA_S_PROTO_ERROR);
1105 auth_ok = dcesrv_auth_alter(call);
1107 if (call->in_auth_info.auth_type == DCERPC_AUTH_TYPE_NONE) {
1108 return dcesrv_fault_disconnect(call,
1109 DCERPC_FAULT_ACCESS_DENIED);
1113 if (call->pkt.u.alter.num_contexts < 1) {
1114 return dcesrv_fault_disconnect(call, DCERPC_NCA_S_PROTO_ERROR);
1116 ctx = &call->pkt.u.alter.ctx_list[0];
1117 if (ctx->num_transfer_syntaxes < 1) {
1118 return dcesrv_fault_disconnect(call, DCERPC_NCA_S_PROTO_ERROR);
1121 /* see if they are asking for a new interface */
1122 call->context = dcesrv_find_context(call->conn, ctx->context_id);
1123 if (!call->context) {
1124 status = dcesrv_alter_new_context(call, ctx->context_id);
1125 if (!NT_STATUS_IS_OK(status)) {
1126 return dcesrv_alter_resp(call,
1127 DCERPC_BIND_PROVIDER_REJECT,
1128 DCERPC_BIND_REASON_ASYNTAX);
1133 ok = ndr_syntax_id_equal(&ctx->abstract_syntax,
1134 &call->context->iface->syntax_id);
1136 return dcesrv_fault_disconnect(call,
1137 DCERPC_NCA_S_PROTO_ERROR);
1140 if (ctx->num_transfer_syntaxes != 1) {
1141 return dcesrv_fault_disconnect(call,
1142 DCERPC_NCA_S_PROTO_ERROR);
1145 ok = ndr_syntax_id_equal(&ctx->transfer_syntaxes[0],
1146 &ndr_transfer_syntax_ndr);
1148 return dcesrv_fault_disconnect(call,
1149 DCERPC_NCA_S_PROTO_ERROR);
1153 /* handle any authentication that is being requested */
1155 if (call->in_auth_info.auth_type !=
1156 call->conn->auth_state.auth_type)
1158 return dcesrv_fault_disconnect(call,
1159 DCERPC_FAULT_SEC_PKG_ERROR);
1161 return dcesrv_fault_disconnect(call, DCERPC_FAULT_ACCESS_DENIED);
1164 return dcesrv_alter_resp(call,
1165 DCERPC_BIND_ACK_RESULT_ACCEPTANCE,
1166 DCERPC_BIND_ACK_REASON_NOT_SPECIFIED);
1170 possibly save the call for inspection with ndrdump
1172 static void dcesrv_save_call(struct dcesrv_call_state *call, const char *why)
1176 const char *dump_dir;
1177 dump_dir = lpcfg_parm_string(call->conn->dce_ctx->lp_ctx, NULL, "dcesrv", "stubs directory");
1181 fname = talloc_asprintf(call, "%s/RPC-%s-%u-%s.dat",
1183 call->context->iface->name,
1184 call->pkt.u.request.opnum,
1186 if (file_save(fname, call->pkt.u.request.stub_and_verifier.data, call->pkt.u.request.stub_and_verifier.length)) {
1187 DEBUG(0,("RPC SAVED %s\n", fname));
1193 static NTSTATUS dcesrv_check_verification_trailer(struct dcesrv_call_state *call)
1195 TALLOC_CTX *frame = talloc_stackframe();
1196 const uint32_t bitmask1 = call->conn->auth_state.client_hdr_signing ?
1197 DCERPC_SEC_VT_CLIENT_SUPPORTS_HEADER_SIGNING : 0;
1198 const struct dcerpc_sec_vt_pcontext pcontext = {
1199 .abstract_syntax = call->context->iface->syntax_id,
1200 .transfer_syntax = ndr_transfer_syntax_ndr,
1202 const struct dcerpc_sec_vt_header2 header2 =
1203 dcerpc_sec_vt_header2_from_ncacn_packet(&call->pkt);
1204 enum ndr_err_code ndr_err;
1205 struct dcerpc_sec_verification_trailer *vt = NULL;
1206 NTSTATUS status = NT_STATUS_OK;
1209 SMB_ASSERT(call->pkt.ptype == DCERPC_PKT_REQUEST);
1211 ndr_err = ndr_pop_dcerpc_sec_verification_trailer(call->ndr_pull,
1213 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
1214 status = ndr_map_error2ntstatus(ndr_err);
1218 ok = dcerpc_sec_verification_trailer_check(vt, &bitmask1,
1219 &pcontext, &header2);
1221 status = NT_STATUS_ACCESS_DENIED;
1230 handle a dcerpc request packet
1232 static NTSTATUS dcesrv_request(struct dcesrv_call_state *call)
1234 const struct dcesrv_endpoint *endpoint = call->conn->endpoint;
1235 enum dcerpc_transport_t transport =
1236 dcerpc_binding_get_transport(endpoint->ep_description);
1237 struct ndr_pull *pull;
1239 struct dcesrv_connection_context *context;
1241 if (!call->conn->allow_request) {
1242 return dcesrv_fault_disconnect(call, DCERPC_NCA_S_PROTO_ERROR);
1245 /* if authenticated, and the mech we use can't do async replies, don't use them... */
1246 if (call->conn->auth_state.gensec_security &&
1247 !gensec_have_feature(call->conn->auth_state.gensec_security, GENSEC_FEATURE_ASYNC_REPLIES)) {
1248 call->state_flags &= ~DCESRV_CALL_STATE_FLAG_MAY_ASYNC;
1251 context = dcesrv_find_context(call->conn, call->pkt.u.request.context_id);
1252 if (context == NULL) {
1253 return dcesrv_fault(call, DCERPC_FAULT_UNK_IF);
1256 switch (call->conn->auth_state.auth_level) {
1257 case DCERPC_AUTH_LEVEL_NONE:
1258 case DCERPC_AUTH_LEVEL_INTEGRITY:
1259 case DCERPC_AUTH_LEVEL_PRIVACY:
1262 if (!context->allow_connect) {
1265 addr = tsocket_address_string(call->conn->remote_address,
1268 DEBUG(2, ("%s: restrict auth_level_connect access "
1269 "to [%s] with auth[type=0x%x,level=0x%x] "
1270 "on [%s] from [%s]\n",
1271 __func__, context->iface->name,
1272 call->conn->auth_state.auth_type,
1273 call->conn->auth_state.auth_level,
1274 derpc_transport_string_by_transport(transport),
1276 return dcesrv_fault(call, DCERPC_FAULT_ACCESS_DENIED);
1281 if (call->conn->auth_state.auth_level < context->min_auth_level) {
1284 addr = tsocket_address_string(call->conn->remote_address, call);
1286 DEBUG(2, ("%s: restrict access by min_auth_level[0x%x] "
1287 "to [%s] with auth[type=0x%x,level=0x%x] "
1288 "on [%s] from [%s]\n",
1290 context->min_auth_level,
1291 context->iface->name,
1292 call->conn->auth_state.auth_type,
1293 call->conn->auth_state.auth_level,
1294 derpc_transport_string_by_transport(transport),
1296 return dcesrv_fault(call, DCERPC_FAULT_ACCESS_DENIED);
1299 pull = ndr_pull_init_blob(&call->pkt.u.request.stub_and_verifier, call);
1300 NT_STATUS_HAVE_NO_MEMORY(pull);
1302 pull->flags |= LIBNDR_FLAG_REF_ALLOC;
1304 call->context = context;
1305 call->ndr_pull = pull;
1307 if (!(call->pkt.drep[0] & DCERPC_DREP_LE)) {
1308 pull->flags |= LIBNDR_FLAG_BIGENDIAN;
1311 status = dcesrv_check_verification_trailer(call);
1312 if (!NT_STATUS_IS_OK(status)) {
1313 uint32_t faultcode = DCERPC_FAULT_OTHER;
1314 if (NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
1315 faultcode = DCERPC_FAULT_ACCESS_DENIED;
1317 DEBUG(10, ("dcesrv_check_verification_trailer failed: %s\n",
1318 nt_errstr(status)));
1319 return dcesrv_fault(call, faultcode);
1322 /* unravel the NDR for the packet */
1323 status = context->iface->ndr_pull(call, call, pull, &call->r);
1324 if (!NT_STATUS_IS_OK(status)) {
1325 if (call->fault_code == DCERPC_FAULT_OP_RNG_ERROR) {
1326 /* we got an unknown call */
1327 DEBUG(3,(__location__ ": Unknown RPC call %u on %s\n",
1328 call->pkt.u.request.opnum, context->iface->name));
1329 dcesrv_save_call(call, "unknown");
1331 dcesrv_save_call(call, "pullfail");
1333 return dcesrv_fault(call, call->fault_code);
1336 if (pull->offset != pull->data_size) {
1337 dcesrv_save_call(call, "extrabytes");
1338 DEBUG(3,("Warning: %d extra bytes in incoming RPC request\n",
1339 pull->data_size - pull->offset));
1342 /* call the dispatch function */
1343 status = context->iface->dispatch(call, call, call->r);
1344 if (!NT_STATUS_IS_OK(status)) {
1345 DEBUG(5,("dcerpc fault in call %s:%02x - %s\n",
1346 context->iface->name,
1347 call->pkt.u.request.opnum,
1348 dcerpc_errstr(pull, call->fault_code)));
1349 return dcesrv_fault(call, call->fault_code);
1352 /* add the call to the pending list */
1353 dcesrv_call_set_list(call, DCESRV_LIST_PENDING_CALL_LIST);
1355 if (call->state_flags & DCESRV_CALL_STATE_FLAG_ASYNC) {
1356 return NT_STATUS_OK;
1359 return dcesrv_reply(call);
1364 remove the call from the right list when freed
1366 static int dcesrv_call_dequeue(struct dcesrv_call_state *call)
1368 dcesrv_call_set_list(call, DCESRV_LIST_NONE);
1372 _PUBLIC_ const struct tsocket_address *dcesrv_connection_get_local_address(struct dcesrv_connection *conn)
1374 return conn->local_address;
1377 _PUBLIC_ const struct tsocket_address *dcesrv_connection_get_remote_address(struct dcesrv_connection *conn)
1379 return conn->remote_address;
1383 process some input to a dcerpc endpoint server.
1385 static NTSTATUS dcesrv_process_ncacn_packet(struct dcesrv_connection *dce_conn,
1386 struct ncacn_packet *pkt,
1390 struct dcesrv_call_state *call;
1391 struct dcesrv_call_state *existing = NULL;
1393 call = talloc_zero(dce_conn, struct dcesrv_call_state);
1395 data_blob_free(&blob);
1397 return NT_STATUS_NO_MEMORY;
1399 call->conn = dce_conn;
1400 call->event_ctx = dce_conn->event_ctx;
1401 call->msg_ctx = dce_conn->msg_ctx;
1402 call->state_flags = call->conn->state_flags;
1403 call->time = timeval_current();
1404 call->list = DCESRV_LIST_NONE;
1406 talloc_steal(call, pkt);
1407 talloc_steal(call, blob.data);
1410 talloc_set_destructor(call, dcesrv_call_dequeue);
1412 if (call->conn->allow_bind) {
1414 * Only one bind is possible per connection
1416 call->conn->allow_bind = false;
1417 return dcesrv_bind(call);
1420 /* we have to check the signing here, before combining the
1422 if (call->pkt.ptype == DCERPC_PKT_REQUEST) {
1423 if (!call->conn->allow_request) {
1424 return dcesrv_fault_disconnect(call,
1425 DCERPC_NCA_S_PROTO_ERROR);
1428 status = dcerpc_verify_ncacn_packet_header(&call->pkt,
1430 call->pkt.u.request.stub_and_verifier.length,
1431 0, /* required_flags */
1432 DCERPC_PFC_FLAG_FIRST |
1433 DCERPC_PFC_FLAG_LAST |
1434 DCERPC_PFC_FLAG_PENDING_CANCEL |
1435 0x08 | /* this is not defined, but should be ignored */
1436 DCERPC_PFC_FLAG_CONC_MPX |
1437 DCERPC_PFC_FLAG_DID_NOT_EXECUTE |
1438 DCERPC_PFC_FLAG_MAYBE |
1439 DCERPC_PFC_FLAG_OBJECT_UUID);
1440 if (!NT_STATUS_IS_OK(status)) {
1441 return dcesrv_fault_disconnect(call,
1442 DCERPC_NCA_S_PROTO_ERROR);
1445 if (call->pkt.frag_length > DCERPC_FRAG_MAX_SIZE) {
1447 * We don't use dcesrv_fault_disconnect()
1448 * here, because we don't want to set
1449 * DCERPC_PFC_FLAG_DID_NOT_EXECUTE
1451 * Note that we don't check against the negotiated
1452 * max_recv_frag, but a hard coded value.
1454 dcesrv_call_disconnect_after(call,
1455 "dcesrv_auth_request - frag_length too large");
1456 return dcesrv_fault(call,
1457 DCERPC_NCA_S_PROTO_ERROR);
1460 if (call->pkt.pfc_flags & DCERPC_PFC_FLAG_FIRST) {
1461 /* only one request is possible in the fragmented list */
1462 if (dce_conn->incoming_fragmented_call_list != NULL) {
1464 call = dce_conn->incoming_fragmented_call_list;
1465 dcesrv_call_disconnect_after(call,
1466 "dcesrv_auth_request - "
1467 "existing fragmented call");
1468 return dcesrv_fault(call,
1469 DCERPC_NCA_S_PROTO_ERROR);
1472 const struct dcerpc_request *nr = &call->pkt.u.request;
1473 const struct dcerpc_request *er = NULL;
1476 existing = dcesrv_find_fragmented_call(dce_conn,
1478 if (existing == NULL) {
1479 dcesrv_call_disconnect_after(call,
1480 "dcesrv_auth_request - "
1481 "no existing fragmented call");
1482 return dcesrv_fault(call,
1483 DCERPC_NCA_S_PROTO_ERROR);
1485 er = &existing->pkt.u.request;
1487 if (call->pkt.ptype != existing->pkt.ptype) {
1488 /* trying to play silly buggers are we? */
1489 return dcesrv_fault_disconnect(existing,
1490 DCERPC_NCA_S_PROTO_ERROR);
1492 cmp = memcmp(call->pkt.drep, existing->pkt.drep,
1495 return dcesrv_fault_disconnect(existing,
1496 DCERPC_NCA_S_PROTO_ERROR);
1498 if (nr->context_id != er->context_id) {
1499 return dcesrv_fault_disconnect(existing,
1500 DCERPC_NCA_S_PROTO_ERROR);
1502 if (nr->opnum != er->opnum) {
1503 return dcesrv_fault_disconnect(existing,
1504 DCERPC_NCA_S_PROTO_ERROR);
1508 if (!dcesrv_auth_request(call, &blob)) {
1510 * We don't use dcesrv_fault_disconnect()
1511 * here, because we don't want to set
1512 * DCERPC_PFC_FLAG_DID_NOT_EXECUTE
1514 dcesrv_call_disconnect_after(call,
1515 "dcesrv_auth_request - failed");
1516 return dcesrv_fault(call, DCERPC_FAULT_ACCESS_DENIED);
1520 /* see if this is a continued packet */
1521 if (existing != NULL) {
1522 struct dcerpc_request *er = &existing->pkt.u.request;
1523 const struct dcerpc_request *nr = &call->pkt.u.request;
1529 * Up to 4 MByte are allowed by all fragments
1531 available = DCERPC_NCACN_PAYLOAD_MAX_SIZE;
1532 if (er->stub_and_verifier.length > available) {
1533 dcesrv_call_disconnect_after(existing,
1534 "dcesrv_auth_request - existing payload too large");
1535 return dcesrv_fault(existing, DCERPC_FAULT_ACCESS_DENIED);
1537 available -= er->stub_and_verifier.length;
1538 if (nr->alloc_hint > available) {
1539 dcesrv_call_disconnect_after(existing,
1540 "dcesrv_auth_request - alloc hint too large");
1541 return dcesrv_fault(existing, DCERPC_FAULT_ACCESS_DENIED);
1543 if (nr->stub_and_verifier.length > available) {
1544 dcesrv_call_disconnect_after(existing,
1545 "dcesrv_auth_request - new payload too large");
1546 return dcesrv_fault(existing, DCERPC_FAULT_ACCESS_DENIED);
1548 alloc_hint = er->stub_and_verifier.length + nr->alloc_hint;
1549 /* allocate at least 1 byte */
1550 alloc_hint = MAX(alloc_hint, 1);
1551 alloc_size = er->stub_and_verifier.length +
1552 nr->stub_and_verifier.length;
1553 alloc_size = MAX(alloc_size, alloc_hint);
1555 er->stub_and_verifier.data =
1556 talloc_realloc(existing,
1557 er->stub_and_verifier.data,
1558 uint8_t, alloc_size);
1559 if (er->stub_and_verifier.data == NULL) {
1561 return dcesrv_fault_with_flags(existing,
1562 DCERPC_FAULT_OUT_OF_RESOURCES,
1563 DCERPC_PFC_FLAG_DID_NOT_EXECUTE);
1565 memcpy(er->stub_and_verifier.data +
1566 er->stub_and_verifier.length,
1567 nr->stub_and_verifier.data,
1568 nr->stub_and_verifier.length);
1569 er->stub_and_verifier.length += nr->stub_and_verifier.length;
1571 existing->pkt.pfc_flags |= (call->pkt.pfc_flags & DCERPC_PFC_FLAG_LAST);
1577 /* this may not be the last pdu in the chain - if its isn't then
1578 just put it on the incoming_fragmented_call_list and wait for the rest */
1579 if (call->pkt.ptype == DCERPC_PKT_REQUEST &&
1580 !(call->pkt.pfc_flags & DCERPC_PFC_FLAG_LAST)) {
1582 * Up to 4 MByte are allowed by all fragments
1584 if (call->pkt.u.request.alloc_hint > DCERPC_NCACN_PAYLOAD_MAX_SIZE) {
1585 dcesrv_call_disconnect_after(call,
1586 "dcesrv_auth_request - initial alloc hint too large");
1587 return dcesrv_fault(call, DCERPC_FAULT_ACCESS_DENIED);
1589 dcesrv_call_set_list(call, DCESRV_LIST_FRAGMENTED_CALL_LIST);
1590 return NT_STATUS_OK;
1593 /* This removes any fragments we may have had stashed away */
1594 dcesrv_call_set_list(call, DCESRV_LIST_NONE);
1596 switch (call->pkt.ptype) {
1597 case DCERPC_PKT_BIND:
1598 status = dcesrv_bind_nak(call,
1599 DCERPC_BIND_NAK_REASON_NOT_SPECIFIED);
1601 case DCERPC_PKT_AUTH3:
1602 status = dcesrv_auth3(call);
1604 case DCERPC_PKT_ALTER:
1605 status = dcesrv_alter(call);
1607 case DCERPC_PKT_REQUEST:
1608 status = dcesrv_request(call);
1611 status = dcesrv_fault_disconnect(call, DCERPC_NCA_S_PROTO_ERROR);
1615 /* if we are going to be sending a reply then add
1616 it to the list of pending calls. We add it to the end to keep the call
1617 list in the order we will answer */
1618 if (!NT_STATUS_IS_OK(status)) {
1625 _PUBLIC_ NTSTATUS dcesrv_init_context(TALLOC_CTX *mem_ctx,
1626 struct loadparm_context *lp_ctx,
1627 const char **endpoint_servers, struct dcesrv_context **_dce_ctx)
1630 struct dcesrv_context *dce_ctx;
1633 if (!endpoint_servers) {
1634 DEBUG(0,("dcesrv_init_context: no endpoint servers configured\n"));
1635 return NT_STATUS_INTERNAL_ERROR;
1638 dce_ctx = talloc_zero(mem_ctx, struct dcesrv_context);
1639 NT_STATUS_HAVE_NO_MEMORY(dce_ctx);
1641 if (uid_wrapper_enabled()) {
1642 setenv("UID_WRAPPER_MYUID", "1", 1);
1644 dce_ctx->initial_euid = geteuid();
1645 if (uid_wrapper_enabled()) {
1646 unsetenv("UID_WRAPPER_MYUID");
1649 dce_ctx->endpoint_list = NULL;
1650 dce_ctx->lp_ctx = lp_ctx;
1651 dce_ctx->assoc_groups_idr = idr_init(dce_ctx);
1652 NT_STATUS_HAVE_NO_MEMORY(dce_ctx->assoc_groups_idr);
1653 dce_ctx->broken_connections = NULL;
1655 for (i=0;endpoint_servers[i];i++) {
1656 const struct dcesrv_endpoint_server *ep_server;
1658 ep_server = dcesrv_ep_server_byname(endpoint_servers[i]);
1660 DEBUG(0,("dcesrv_init_context: failed to find endpoint server = '%s'\n", endpoint_servers[i]));
1661 return NT_STATUS_INTERNAL_ERROR;
1664 status = ep_server->init_server(dce_ctx, ep_server);
1665 if (!NT_STATUS_IS_OK(status)) {
1666 DEBUG(0,("dcesrv_init_context: failed to init endpoint server = '%s': %s\n", endpoint_servers[i],
1667 nt_errstr(status)));
1672 *_dce_ctx = dce_ctx;
1673 return NT_STATUS_OK;
1676 /* the list of currently registered DCERPC endpoint servers.
1678 static struct ep_server {
1679 struct dcesrv_endpoint_server *ep_server;
1680 } *ep_servers = NULL;
1681 static int num_ep_servers;
1684 register a DCERPC endpoint server.
1686 The 'name' can be later used by other backends to find the operations
1687 structure for this backend.
1689 The 'type' is used to specify whether this is for a disk, printer or IPC$ share
1691 _PUBLIC_ NTSTATUS dcerpc_register_ep_server(const void *_ep_server)
1693 const struct dcesrv_endpoint_server *ep_server = _ep_server;
1695 if (dcesrv_ep_server_byname(ep_server->name) != NULL) {
1696 /* its already registered! */
1697 DEBUG(0,("DCERPC endpoint server '%s' already registered\n",
1699 return NT_STATUS_OBJECT_NAME_COLLISION;
1702 ep_servers = realloc_p(ep_servers, struct ep_server, num_ep_servers+1);
1704 smb_panic("out of memory in dcerpc_register");
1707 ep_servers[num_ep_servers].ep_server = smb_xmemdup(ep_server, sizeof(*ep_server));
1708 ep_servers[num_ep_servers].ep_server->name = smb_xstrdup(ep_server->name);
1712 DEBUG(3,("DCERPC endpoint server '%s' registered\n",
1715 return NT_STATUS_OK;
1719 return the operations structure for a named backend of the specified type
1721 const struct dcesrv_endpoint_server *dcesrv_ep_server_byname(const char *name)
1725 for (i=0;i<num_ep_servers;i++) {
1726 if (strcmp(ep_servers[i].ep_server->name, name) == 0) {
1727 return ep_servers[i].ep_server;
1734 void dcerpc_server_init(struct loadparm_context *lp_ctx)
1736 static bool initialized;
1737 #define _MODULE_PROTO(init) extern NTSTATUS init(void);
1738 STATIC_dcerpc_server_MODULES_PROTO;
1739 init_module_fn static_init[] = { STATIC_dcerpc_server_MODULES };
1740 init_module_fn *shared_init;
1747 shared_init = load_samba_modules(NULL, "dcerpc_server");
1749 run_init_functions(static_init);
1750 run_init_functions(shared_init);
1752 talloc_free(shared_init);
1756 return the DCERPC module version, and the size of some critical types
1757 This can be used by endpoint server modules to either detect compilation errors, or provide
1758 multiple implementations for different smbd compilation options in one module
1760 const struct dcesrv_critical_sizes *dcerpc_module_version(void)
1762 static const struct dcesrv_critical_sizes critical_sizes = {
1763 DCERPC_MODULE_VERSION,
1764 sizeof(struct dcesrv_context),
1765 sizeof(struct dcesrv_endpoint),
1766 sizeof(struct dcesrv_endpoint_server),
1767 sizeof(struct dcesrv_interface),
1768 sizeof(struct dcesrv_if_list),
1769 sizeof(struct dcesrv_connection),
1770 sizeof(struct dcesrv_call_state),
1771 sizeof(struct dcesrv_auth),
1772 sizeof(struct dcesrv_handle)
1775 return &critical_sizes;
1778 static void dcesrv_terminate_connection(struct dcesrv_connection *dce_conn, const char *reason)
1780 struct dcesrv_context *dce_ctx = dce_conn->dce_ctx;
1781 struct stream_connection *srv_conn;
1782 srv_conn = talloc_get_type(dce_conn->transport.private_data,
1783 struct stream_connection);
1785 dce_conn->allow_bind = false;
1786 dce_conn->allow_auth3 = false;
1787 dce_conn->allow_alter = false;
1788 dce_conn->allow_request = false;
1790 if (dce_conn->pending_call_list == NULL) {
1791 char *full_reason = talloc_asprintf(dce_conn, "dcesrv: %s", reason);
1793 DLIST_REMOVE(dce_ctx->broken_connections, dce_conn);
1794 stream_terminate_connection(srv_conn, full_reason ? full_reason : reason);
1798 if (dce_conn->terminate != NULL) {
1802 DEBUG(3,("dcesrv: terminating connection due to '%s' defered due to pending calls\n",
1804 dce_conn->terminate = talloc_strdup(dce_conn, reason);
1805 if (dce_conn->terminate == NULL) {
1806 dce_conn->terminate = "dcesrv: defered terminating connection - no memory";
1808 DLIST_ADD_END(dce_ctx->broken_connections, dce_conn);
1811 static void dcesrv_cleanup_broken_connections(struct dcesrv_context *dce_ctx)
1813 struct dcesrv_connection *cur, *next;
1815 next = dce_ctx->broken_connections;
1816 while (next != NULL) {
1820 if (cur->state_flags & DCESRV_CALL_STATE_FLAG_PROCESS_PENDING_CALL) {
1821 struct dcesrv_connection_context *context_cur, *context_next;
1823 context_next = cur->contexts;
1824 while (context_next != NULL) {
1825 context_cur = context_next;
1826 context_next = context_cur->next;
1828 dcesrv_connection_context_destructor(context_cur);
1832 dcesrv_terminate_connection(cur, cur->terminate);
1836 /* We need this include to be able to compile on some plateforms
1837 * (ie. freebsd 7.2) as it seems that <sys/uio.h> is not included
1839 * It has to be that deep because otherwise we have a conflict on
1840 * const struct dcesrv_interface declaration.
1841 * This is mostly due to socket_wrapper defining #define bind swrap_bind
1842 * which conflict with the bind used before.
1844 #include "system/network.h"
1846 struct dcesrv_sock_reply_state {
1847 struct dcesrv_connection *dce_conn;
1848 struct dcesrv_call_state *call;
1852 static void dcesrv_sock_reply_done(struct tevent_req *subreq);
1853 static void dcesrv_call_terminate_step1(struct tevent_req *subreq);
1855 static void dcesrv_sock_report_output_data(struct dcesrv_connection *dce_conn)
1857 struct dcesrv_call_state *call;
1859 call = dce_conn->call_list;
1860 if (!call || !call->replies) {
1864 while (call->replies) {
1865 struct data_blob_list_item *rep = call->replies;
1866 struct dcesrv_sock_reply_state *substate;
1867 struct tevent_req *subreq;
1869 substate = talloc_zero(call, struct dcesrv_sock_reply_state);
1871 dcesrv_terminate_connection(dce_conn, "no memory");
1875 substate->dce_conn = dce_conn;
1876 substate->call = NULL;
1878 DLIST_REMOVE(call->replies, rep);
1880 if (call->replies == NULL && call->terminate_reason == NULL) {
1881 substate->call = call;
1884 substate->iov.iov_base = (void *) rep->blob.data;
1885 substate->iov.iov_len = rep->blob.length;
1887 subreq = tstream_writev_queue_send(substate,
1888 dce_conn->event_ctx,
1890 dce_conn->send_queue,
1893 dcesrv_terminate_connection(dce_conn, "no memory");
1896 tevent_req_set_callback(subreq, dcesrv_sock_reply_done,
1900 if (call->terminate_reason != NULL) {
1901 struct tevent_req *subreq;
1903 subreq = tevent_queue_wait_send(call,
1904 dce_conn->event_ctx,
1905 dce_conn->send_queue);
1907 dcesrv_terminate_connection(dce_conn, __location__);
1910 tevent_req_set_callback(subreq, dcesrv_call_terminate_step1,
1914 DLIST_REMOVE(call->conn->call_list, call);
1915 call->list = DCESRV_LIST_NONE;
1918 static void dcesrv_sock_reply_done(struct tevent_req *subreq)
1920 struct dcesrv_sock_reply_state *substate = tevent_req_callback_data(subreq,
1921 struct dcesrv_sock_reply_state);
1925 struct dcesrv_call_state *call = substate->call;
1927 ret = tstream_writev_queue_recv(subreq, &sys_errno);
1928 TALLOC_FREE(subreq);
1930 status = map_nt_error_from_unix_common(sys_errno);
1931 dcesrv_terminate_connection(substate->dce_conn, nt_errstr(status));
1935 talloc_free(substate);
1941 static void dcesrv_call_terminate_step2(struct tevent_req *subreq);
1943 static void dcesrv_call_terminate_step1(struct tevent_req *subreq)
1945 struct dcesrv_call_state *call = tevent_req_callback_data(subreq,
1946 struct dcesrv_call_state);
1950 /* make sure we stop send queue before removing subreq */
1951 tevent_queue_stop(call->conn->send_queue);
1953 ok = tevent_queue_wait_recv(subreq);
1954 TALLOC_FREE(subreq);
1956 dcesrv_terminate_connection(call->conn, __location__);
1960 /* disconnect after 200 usecs */
1961 tv = timeval_current_ofs_usec(200);
1962 subreq = tevent_wakeup_send(call, call->conn->event_ctx, tv);
1963 if (subreq == NULL) {
1964 dcesrv_terminate_connection(call->conn, __location__);
1967 tevent_req_set_callback(subreq, dcesrv_call_terminate_step2,
1971 static void dcesrv_call_terminate_step2(struct tevent_req *subreq)
1973 struct dcesrv_call_state *call = tevent_req_callback_data(subreq,
1974 struct dcesrv_call_state);
1977 ok = tevent_wakeup_recv(subreq);
1978 TALLOC_FREE(subreq);
1980 dcesrv_terminate_connection(call->conn, __location__);
1984 dcesrv_terminate_connection(call->conn, call->terminate_reason);
1987 struct dcesrv_socket_context {
1988 const struct dcesrv_endpoint *endpoint;
1989 struct dcesrv_context *dcesrv_ctx;
1993 static void dcesrv_read_fragment_done(struct tevent_req *subreq);
1995 static void dcesrv_sock_accept(struct stream_connection *srv_conn)
1998 struct dcesrv_socket_context *dcesrv_sock =
1999 talloc_get_type(srv_conn->private_data, struct dcesrv_socket_context);
2000 enum dcerpc_transport_t transport =
2001 dcerpc_binding_get_transport(dcesrv_sock->endpoint->ep_description);
2002 struct dcesrv_connection *dcesrv_conn = NULL;
2004 struct tevent_req *subreq;
2005 struct loadparm_context *lp_ctx = dcesrv_sock->dcesrv_ctx->lp_ctx;
2007 dcesrv_cleanup_broken_connections(dcesrv_sock->dcesrv_ctx);
2009 if (!srv_conn->session_info) {
2010 status = auth_anonymous_session_info(srv_conn,
2012 &srv_conn->session_info);
2013 if (!NT_STATUS_IS_OK(status)) {
2014 DEBUG(0,("dcesrv_sock_accept: auth_anonymous_session_info failed: %s\n",
2015 nt_errstr(status)));
2016 stream_terminate_connection(srv_conn, nt_errstr(status));
2021 status = dcesrv_endpoint_connect(dcesrv_sock->dcesrv_ctx,
2023 dcesrv_sock->endpoint,
2024 srv_conn->session_info,
2025 srv_conn->event.ctx,
2027 srv_conn->server_id,
2028 DCESRV_CALL_STATE_FLAG_MAY_ASYNC,
2030 if (!NT_STATUS_IS_OK(status)) {
2031 DEBUG(0,("dcesrv_sock_accept: dcesrv_endpoint_connect failed: %s\n",
2032 nt_errstr(status)));
2033 stream_terminate_connection(srv_conn, nt_errstr(status));
2037 dcesrv_conn->transport.private_data = srv_conn;
2038 dcesrv_conn->transport.report_output_data = dcesrv_sock_report_output_data;
2040 TALLOC_FREE(srv_conn->event.fde);
2042 dcesrv_conn->send_queue = tevent_queue_create(dcesrv_conn, "dcesrv send queue");
2043 if (!dcesrv_conn->send_queue) {
2044 status = NT_STATUS_NO_MEMORY;
2045 DEBUG(0,("dcesrv_sock_accept: tevent_queue_create(%s)\n",
2046 nt_errstr(status)));
2047 stream_terminate_connection(srv_conn, nt_errstr(status));
2051 if (transport == NCACN_NP) {
2052 dcesrv_conn->auth_state.session_key = dcesrv_inherited_session_key;
2053 dcesrv_conn->stream = talloc_move(dcesrv_conn,
2054 &srv_conn->tstream);
2056 ret = tstream_bsd_existing_socket(dcesrv_conn,
2057 socket_get_fd(srv_conn->socket),
2058 &dcesrv_conn->stream);
2060 status = map_nt_error_from_unix_common(errno);
2061 DEBUG(0, ("dcesrv_sock_accept: "
2062 "failed to setup tstream: %s\n",
2063 nt_errstr(status)));
2064 stream_terminate_connection(srv_conn, nt_errstr(status));
2067 socket_set_flags(srv_conn->socket, SOCKET_FLAG_NOCLOSE);
2070 dcesrv_conn->local_address = srv_conn->local_address;
2071 dcesrv_conn->remote_address = srv_conn->remote_address;
2073 if (transport == NCALRPC) {
2077 ret = getpeereid(socket_get_fd(srv_conn->socket), &uid, &gid);
2079 status = map_nt_error_from_unix_common(errno);
2080 DEBUG(0, ("dcesrv_sock_accept: "
2081 "getpeereid() failed for NCALRPC: %s\n",
2082 nt_errstr(status)));
2083 stream_terminate_connection(srv_conn, nt_errstr(status));
2086 if (uid == dcesrv_conn->dce_ctx->initial_euid) {
2087 struct tsocket_address *r = NULL;
2089 ret = tsocket_address_unix_from_path(dcesrv_conn,
2090 "/root/ncalrpc_as_system",
2093 status = map_nt_error_from_unix_common(errno);
2094 DEBUG(0, ("dcesrv_sock_accept: "
2095 "tsocket_address_unix_from_path() failed for NCALRPC: %s\n",
2096 nt_errstr(status)));
2097 stream_terminate_connection(srv_conn, nt_errstr(status));
2100 dcesrv_conn->remote_address = r;
2104 srv_conn->private_data = dcesrv_conn;
2106 irpc_add_name(srv_conn->msg_ctx, "rpc_server");
2108 subreq = dcerpc_read_ncacn_packet_send(dcesrv_conn,
2109 dcesrv_conn->event_ctx,
2110 dcesrv_conn->stream);
2112 status = NT_STATUS_NO_MEMORY;
2113 DEBUG(0,("dcesrv_sock_accept: dcerpc_read_fragment_buffer_send(%s)\n",
2114 nt_errstr(status)));
2115 stream_terminate_connection(srv_conn, nt_errstr(status));
2118 tevent_req_set_callback(subreq, dcesrv_read_fragment_done, dcesrv_conn);
2123 static void dcesrv_read_fragment_done(struct tevent_req *subreq)
2125 struct dcesrv_connection *dce_conn = tevent_req_callback_data(subreq,
2126 struct dcesrv_connection);
2127 struct dcesrv_context *dce_ctx = dce_conn->dce_ctx;
2128 struct ncacn_packet *pkt;
2132 if (dce_conn->terminate) {
2134 * if the current connection is broken
2135 * we need to clean it up before any other connection
2137 dcesrv_terminate_connection(dce_conn, dce_conn->terminate);
2138 dcesrv_cleanup_broken_connections(dce_ctx);
2142 dcesrv_cleanup_broken_connections(dce_ctx);
2144 status = dcerpc_read_ncacn_packet_recv(subreq, dce_conn,
2146 TALLOC_FREE(subreq);
2147 if (!NT_STATUS_IS_OK(status)) {
2148 dcesrv_terminate_connection(dce_conn, nt_errstr(status));
2152 status = dcesrv_process_ncacn_packet(dce_conn, pkt, buffer);
2153 if (!NT_STATUS_IS_OK(status)) {
2154 dcesrv_terminate_connection(dce_conn, nt_errstr(status));
2158 subreq = dcerpc_read_ncacn_packet_send(dce_conn,
2159 dce_conn->event_ctx,
2162 status = NT_STATUS_NO_MEMORY;
2163 dcesrv_terminate_connection(dce_conn, nt_errstr(status));
2166 tevent_req_set_callback(subreq, dcesrv_read_fragment_done, dce_conn);
2169 static void dcesrv_sock_recv(struct stream_connection *conn, uint16_t flags)
2171 struct dcesrv_connection *dce_conn = talloc_get_type(conn->private_data,
2172 struct dcesrv_connection);
2173 dcesrv_terminate_connection(dce_conn, "dcesrv_sock_recv triggered");
2176 static void dcesrv_sock_send(struct stream_connection *conn, uint16_t flags)
2178 struct dcesrv_connection *dce_conn = talloc_get_type(conn->private_data,
2179 struct dcesrv_connection);
2180 dcesrv_terminate_connection(dce_conn, "dcesrv_sock_send triggered");
2184 static const struct stream_server_ops dcesrv_stream_ops = {
2186 .accept_connection = dcesrv_sock_accept,
2187 .recv_handler = dcesrv_sock_recv,
2188 .send_handler = dcesrv_sock_send,
2191 static NTSTATUS dcesrv_add_ep_unix(struct dcesrv_context *dce_ctx,
2192 struct loadparm_context *lp_ctx,
2193 struct dcesrv_endpoint *e,
2194 struct tevent_context *event_ctx, const struct model_ops *model_ops)
2196 struct dcesrv_socket_context *dcesrv_sock;
2199 const char *endpoint;
2201 dcesrv_sock = talloc_zero(event_ctx, struct dcesrv_socket_context);
2202 NT_STATUS_HAVE_NO_MEMORY(dcesrv_sock);
2204 /* remember the endpoint of this socket */
2205 dcesrv_sock->endpoint = e;
2206 dcesrv_sock->dcesrv_ctx = talloc_reference(dcesrv_sock, dce_ctx);
2208 endpoint = dcerpc_binding_get_string_option(e->ep_description, "endpoint");
2210 status = stream_setup_socket(dcesrv_sock, event_ctx, lp_ctx,
2211 model_ops, &dcesrv_stream_ops,
2212 "unix", endpoint, &port,
2213 lpcfg_socket_options(lp_ctx),
2215 if (!NT_STATUS_IS_OK(status)) {
2216 DEBUG(0,("service_setup_stream_socket(path=%s) failed - %s\n",
2217 endpoint, nt_errstr(status)));
2223 static NTSTATUS dcesrv_add_ep_ncalrpc(struct dcesrv_context *dce_ctx,
2224 struct loadparm_context *lp_ctx,
2225 struct dcesrv_endpoint *e,
2226 struct tevent_context *event_ctx, const struct model_ops *model_ops)
2228 struct dcesrv_socket_context *dcesrv_sock;
2232 const char *endpoint;
2234 endpoint = dcerpc_binding_get_string_option(e->ep_description, "endpoint");
2236 if (endpoint == NULL) {
2238 * No identifier specified: use DEFAULT.
2240 * TODO: DO NOT hardcode this value anywhere else. Rather, specify
2241 * no endpoint and let the epmapper worry about it.
2243 endpoint = "DEFAULT";
2244 status = dcerpc_binding_set_string_option(e->ep_description,
2247 if (!NT_STATUS_IS_OK(status)) {
2248 DEBUG(0,("dcerpc_binding_set_string_option() failed - %s\n",
2249 nt_errstr(status)));
2254 full_path = talloc_asprintf(dce_ctx, "%s/%s", lpcfg_ncalrpc_dir(lp_ctx),
2257 dcesrv_sock = talloc_zero(event_ctx, struct dcesrv_socket_context);
2258 NT_STATUS_HAVE_NO_MEMORY(dcesrv_sock);
2260 /* remember the endpoint of this socket */
2261 dcesrv_sock->endpoint = e;
2262 dcesrv_sock->dcesrv_ctx = talloc_reference(dcesrv_sock, dce_ctx);
2264 status = stream_setup_socket(dcesrv_sock, event_ctx, lp_ctx,
2265 model_ops, &dcesrv_stream_ops,
2266 "unix", full_path, &port,
2267 lpcfg_socket_options(lp_ctx),
2269 if (!NT_STATUS_IS_OK(status)) {
2270 DEBUG(0,("service_setup_stream_socket(identifier=%s,path=%s) failed - %s\n",
2271 endpoint, full_path, nt_errstr(status)));
2276 static NTSTATUS dcesrv_add_ep_np(struct dcesrv_context *dce_ctx,
2277 struct loadparm_context *lp_ctx,
2278 struct dcesrv_endpoint *e,
2279 struct tevent_context *event_ctx, const struct model_ops *model_ops)
2281 struct dcesrv_socket_context *dcesrv_sock;
2283 const char *endpoint;
2285 endpoint = dcerpc_binding_get_string_option(e->ep_description, "endpoint");
2286 if (endpoint == NULL) {
2287 DEBUG(0, ("Endpoint mandatory for named pipes\n"));
2288 return NT_STATUS_INVALID_PARAMETER;
2291 dcesrv_sock = talloc_zero(event_ctx, struct dcesrv_socket_context);
2292 NT_STATUS_HAVE_NO_MEMORY(dcesrv_sock);
2294 /* remember the endpoint of this socket */
2295 dcesrv_sock->endpoint = e;
2296 dcesrv_sock->dcesrv_ctx = talloc_reference(dcesrv_sock, dce_ctx);
2298 status = tstream_setup_named_pipe(dce_ctx, event_ctx, lp_ctx,
2299 model_ops, &dcesrv_stream_ops,
2302 if (!NT_STATUS_IS_OK(status)) {
2303 DEBUG(0,("stream_setup_named_pipe(pipe=%s) failed - %s\n",
2304 endpoint, nt_errstr(status)));
2308 return NT_STATUS_OK;
2312 add a socket address to the list of events, one event per dcerpc endpoint
2314 static NTSTATUS add_socket_rpc_tcp_iface(struct dcesrv_context *dce_ctx, struct dcesrv_endpoint *e,
2315 struct tevent_context *event_ctx, const struct model_ops *model_ops,
2316 const char *address)
2318 struct dcesrv_socket_context *dcesrv_sock;
2321 const char *endpoint;
2324 endpoint = dcerpc_binding_get_string_option(e->ep_description, "endpoint");
2325 if (endpoint != NULL) {
2326 port = atoi(endpoint);
2329 dcesrv_sock = talloc_zero(event_ctx, struct dcesrv_socket_context);
2330 NT_STATUS_HAVE_NO_MEMORY(dcesrv_sock);
2332 /* remember the endpoint of this socket */
2333 dcesrv_sock->endpoint = e;
2334 dcesrv_sock->dcesrv_ctx = talloc_reference(dcesrv_sock, dce_ctx);
2336 status = stream_setup_socket(dcesrv_sock, event_ctx, dce_ctx->lp_ctx,
2337 model_ops, &dcesrv_stream_ops,
2338 "ip", address, &port,
2339 lpcfg_socket_options(dce_ctx->lp_ctx),
2341 if (!NT_STATUS_IS_OK(status)) {
2342 DEBUG(0,("service_setup_stream_socket(address=%s,port=%u) failed - %s\n",
2343 address, port, nt_errstr(status)));
2347 snprintf(port_str, sizeof(port_str), "%u", port);
2349 status = dcerpc_binding_set_string_option(e->ep_description,
2350 "endpoint", port_str);
2351 if (!NT_STATUS_IS_OK(status)) {
2352 DEBUG(0,("dcerpc_binding_set_string_option(endpoint, %s) failed - %s\n",
2353 port_str, nt_errstr(status)));
2357 return NT_STATUS_OK;
2360 #include "lib/socket/netif.h" /* Included here to work around the fact that socket_wrapper redefines bind() */
2362 static NTSTATUS dcesrv_add_ep_tcp(struct dcesrv_context *dce_ctx,
2363 struct loadparm_context *lp_ctx,
2364 struct dcesrv_endpoint *e,
2365 struct tevent_context *event_ctx, const struct model_ops *model_ops)
2369 /* Add TCP/IP sockets */
2370 if (lpcfg_interfaces(lp_ctx) && lpcfg_bind_interfaces_only(lp_ctx)) {
2373 struct interface *ifaces;
2375 load_interface_list(dce_ctx, lp_ctx, &ifaces);
2377 num_interfaces = iface_list_count(ifaces);
2378 for(i = 0; i < num_interfaces; i++) {
2379 const char *address = iface_list_n_ip(ifaces, i);
2380 status = add_socket_rpc_tcp_iface(dce_ctx, e, event_ctx, model_ops, address);
2381 NT_STATUS_NOT_OK_RETURN(status);
2387 wcard = iface_list_wildcard(dce_ctx);
2388 NT_STATUS_HAVE_NO_MEMORY(wcard);
2389 for (i=0; wcard[i]; i++) {
2390 status = add_socket_rpc_tcp_iface(dce_ctx, e, event_ctx, model_ops, wcard[i]);
2391 if (NT_STATUS_IS_OK(status)) {
2396 if (num_binds == 0) {
2397 return NT_STATUS_INVALID_PARAMETER_MIX;
2401 return NT_STATUS_OK;
2404 NTSTATUS dcesrv_add_ep(struct dcesrv_context *dce_ctx,
2405 struct loadparm_context *lp_ctx,
2406 struct dcesrv_endpoint *e,
2407 struct tevent_context *event_ctx,
2408 const struct model_ops *model_ops)
2410 enum dcerpc_transport_t transport =
2411 dcerpc_binding_get_transport(e->ep_description);
2413 switch (transport) {
2414 case NCACN_UNIX_STREAM:
2415 return dcesrv_add_ep_unix(dce_ctx, lp_ctx, e, event_ctx, model_ops);
2418 return dcesrv_add_ep_ncalrpc(dce_ctx, lp_ctx, e, event_ctx, model_ops);
2421 return dcesrv_add_ep_tcp(dce_ctx, lp_ctx, e, event_ctx, model_ops);
2424 return dcesrv_add_ep_np(dce_ctx, lp_ctx, e, event_ctx, model_ops);
2427 return NT_STATUS_NOT_SUPPORTED;
2433 * retrieve credentials from a dce_call
2435 _PUBLIC_ struct cli_credentials *dcesrv_call_credentials(struct dcesrv_call_state *dce_call)
2437 return dce_call->conn->auth_state.session_info->credentials;
2441 * returns true if this is an authenticated call
2443 _PUBLIC_ bool dcesrv_call_authenticated(struct dcesrv_call_state *dce_call)
2445 enum security_user_level level;
2446 level = security_session_user_level(dce_call->conn->auth_state.session_info, NULL);
2447 return level >= SECURITY_USER;
2451 * retrieve account_name for a dce_call
2453 _PUBLIC_ const char *dcesrv_call_account_name(struct dcesrv_call_state *dce_call)
2455 return dce_call->context->conn->auth_state.session_info->info->account_name;