2 Unix SMB/CIFS implementation.
4 server side dcerpc core code
6 Copyright (C) Andrew Tridgell 2003-2005
7 Copyright (C) Stefan (metze) Metzmacher 2004-2005
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 3 of the License, or
12 (at your option) any later version.
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
19 You should have received a copy of the GNU General Public License
20 along with this program. If not, see <http://www.gnu.org/licenses/>.
24 #include "auth/auth.h"
25 #include "auth/gensec/gensec.h"
26 #include "../lib/util/dlinklist.h"
27 #include "rpc_server/dcerpc_server.h"
28 #include "rpc_server/dcerpc_server_proto.h"
29 #include "rpc_server/common/proto.h"
30 #include "librpc/rpc/dcerpc_proto.h"
31 #include "system/filesys.h"
32 #include "libcli/security/security.h"
33 #include "param/param.h"
34 #include "../lib/tsocket/tsocket.h"
35 #include "../libcli/named_pipe_auth/npa_tstream.h"
36 #include "smbd/service_stream.h"
37 #include "../lib/tsocket/tsocket.h"
38 #include "lib/socket/socket.h"
39 #include "smbd/process_model.h"
40 #include "lib/messaging/irpc.h"
41 #include "librpc/rpc/rpc_common.h"
42 #include "lib/util/samba_modules.h"
43 #include "librpc/gen_ndr/ndr_dcerpc.h"
45 /* this is only used when the client asks for an unknown interface */
46 #define DUMMY_ASSOC_GROUP 0x0FFFFFFF
48 extern const struct dcesrv_interface dcesrv_mgmt_interface;
52 find an association group given a assoc_group_id
54 static struct dcesrv_assoc_group *dcesrv_assoc_group_find(struct dcesrv_context *dce_ctx,
59 id_ptr = idr_find(dce_ctx->assoc_groups_idr, id);
63 return talloc_get_type_abort(id_ptr, struct dcesrv_assoc_group);
67 take a reference to an existing association group
69 static struct dcesrv_assoc_group *dcesrv_assoc_group_reference(TALLOC_CTX *mem_ctx,
70 struct dcesrv_context *dce_ctx,
73 struct dcesrv_assoc_group *assoc_group;
75 assoc_group = dcesrv_assoc_group_find(dce_ctx, id);
76 if (assoc_group == NULL) {
77 DEBUG(0,(__location__ ": Failed to find assoc_group 0x%08x\n", id));
80 return talloc_reference(mem_ctx, assoc_group);
83 static int dcesrv_assoc_group_destructor(struct dcesrv_assoc_group *assoc_group)
86 ret = idr_remove(assoc_group->dce_ctx->assoc_groups_idr, assoc_group->id);
88 DEBUG(0,(__location__ ": Failed to remove assoc_group 0x%08x\n",
95 allocate a new association group
97 static struct dcesrv_assoc_group *dcesrv_assoc_group_new(TALLOC_CTX *mem_ctx,
98 struct dcesrv_context *dce_ctx)
100 struct dcesrv_assoc_group *assoc_group;
103 assoc_group = talloc_zero(mem_ctx, struct dcesrv_assoc_group);
104 if (assoc_group == NULL) {
108 id = idr_get_new_random(dce_ctx->assoc_groups_idr, assoc_group, UINT16_MAX);
110 talloc_free(assoc_group);
111 DEBUG(0,(__location__ ": Out of association groups!\n"));
115 assoc_group->id = id;
116 assoc_group->dce_ctx = dce_ctx;
118 talloc_set_destructor(assoc_group, dcesrv_assoc_group_destructor);
125 see if two endpoints match
127 static bool endpoints_match(const struct dcerpc_binding *ep1,
128 const struct dcerpc_binding *ep2)
130 enum dcerpc_transport_t t1;
131 enum dcerpc_transport_t t2;
135 t1 = dcerpc_binding_get_transport(ep1);
136 t2 = dcerpc_binding_get_transport(ep2);
138 e1 = dcerpc_binding_get_string_option(ep1, "endpoint");
139 e2 = dcerpc_binding_get_string_option(ep2, "endpoint");
149 if (strcasecmp(e1, e2) != 0) {
157 find an endpoint in the dcesrv_context
159 static struct dcesrv_endpoint *find_endpoint(struct dcesrv_context *dce_ctx,
160 const struct dcerpc_binding *ep_description)
162 struct dcesrv_endpoint *ep;
163 for (ep=dce_ctx->endpoint_list; ep; ep=ep->next) {
164 if (endpoints_match(ep->ep_description, ep_description)) {
172 find a registered context_id from a bind or alter_context
174 static struct dcesrv_connection_context *dcesrv_find_context(struct dcesrv_connection *conn,
177 struct dcesrv_connection_context *c;
178 for (c=conn->contexts;c;c=c->next) {
179 if (c->context_id == context_id) return c;
185 see if a uuid and if_version match to an interface
187 static bool interface_match(const struct dcesrv_interface *if1,
188 const struct dcesrv_interface *if2)
190 return (if1->syntax_id.if_version == if2->syntax_id.if_version &&
191 GUID_equal(&if1->syntax_id.uuid, &if2->syntax_id.uuid));
195 find the interface operations on an endpoint
197 static const struct dcesrv_interface *find_interface(const struct dcesrv_endpoint *endpoint,
198 const struct dcesrv_interface *iface)
200 struct dcesrv_if_list *ifl;
201 for (ifl=endpoint->interface_list; ifl; ifl=ifl->next) {
202 if (interface_match(&(ifl->iface), iface)) {
203 return &(ifl->iface);
210 see if a uuid and if_version match to an interface
212 static bool interface_match_by_uuid(const struct dcesrv_interface *iface,
213 const struct GUID *uuid, uint32_t if_version)
215 return (iface->syntax_id.if_version == if_version &&
216 GUID_equal(&iface->syntax_id.uuid, uuid));
220 find the interface operations on an endpoint by uuid
222 static const struct dcesrv_interface *find_interface_by_uuid(const struct dcesrv_endpoint *endpoint,
223 const struct GUID *uuid, uint32_t if_version)
225 struct dcesrv_if_list *ifl;
226 for (ifl=endpoint->interface_list; ifl; ifl=ifl->next) {
227 if (interface_match_by_uuid(&(ifl->iface), uuid, if_version)) {
228 return &(ifl->iface);
235 find the earlier parts of a fragmented call awaiting reassembily
237 static struct dcesrv_call_state *dcesrv_find_fragmented_call(struct dcesrv_connection *dce_conn, uint16_t call_id)
239 struct dcesrv_call_state *c;
240 for (c=dce_conn->incoming_fragmented_call_list;c;c=c->next) {
241 if (c->pkt.call_id == call_id) {
249 register an interface on an endpoint
251 _PUBLIC_ NTSTATUS dcesrv_interface_register(struct dcesrv_context *dce_ctx,
253 const struct dcesrv_interface *iface,
254 const struct security_descriptor *sd)
256 struct dcesrv_endpoint *ep;
257 struct dcesrv_if_list *ifl;
258 struct dcerpc_binding *binding;
262 status = dcerpc_parse_binding(dce_ctx, ep_name, &binding);
264 if (NT_STATUS_IS_ERR(status)) {
265 DEBUG(0, ("Trouble parsing binding string '%s'\n", ep_name));
269 /* check if this endpoint exists
271 if ((ep=find_endpoint(dce_ctx, binding))==NULL) {
272 ep = talloc_zero(dce_ctx, struct dcesrv_endpoint);
274 return NT_STATUS_NO_MEMORY;
277 ep->ep_description = talloc_move(ep, &binding);
280 /* add mgmt interface */
281 ifl = talloc_zero(ep, struct dcesrv_if_list);
283 return NT_STATUS_NO_MEMORY;
286 memcpy(&(ifl->iface), &dcesrv_mgmt_interface,
287 sizeof(struct dcesrv_interface));
289 DLIST_ADD(ep->interface_list, ifl);
292 /* see if the interface is already registered on te endpoint */
293 if (find_interface(ep, iface)!=NULL) {
294 DEBUG(0,("dcesrv_interface_register: interface '%s' already registered on endpoint '%s'\n",
295 iface->name, ep_name));
296 return NT_STATUS_OBJECT_NAME_COLLISION;
299 /* talloc a new interface list element */
300 ifl = talloc_zero(ep, struct dcesrv_if_list);
302 return NT_STATUS_NO_MEMORY;
305 /* copy the given interface struct to the one on the endpoints interface list */
306 memcpy(&(ifl->iface),iface, sizeof(struct dcesrv_interface));
308 /* if we have a security descriptor given,
309 * we should see if we can set it up on the endpoint
312 /* if there's currently no security descriptor given on the endpoint
315 if (ep->sd == NULL) {
316 ep->sd = security_descriptor_copy(ep, sd);
319 /* if now there's no security descriptor given on the endpoint
320 * something goes wrong, either we failed to copy the security descriptor
321 * or there was already one on the endpoint
323 if (ep->sd != NULL) {
324 DEBUG(0,("dcesrv_interface_register: interface '%s' failed to setup a security descriptor\n"
325 " on endpoint '%s'\n",
326 iface->name, ep_name));
327 if (add_ep) free(ep);
329 return NT_STATUS_OBJECT_NAME_COLLISION;
333 /* finally add the interface on the endpoint */
334 DLIST_ADD(ep->interface_list, ifl);
336 /* if it's a new endpoint add it to the dcesrv_context */
338 DLIST_ADD(dce_ctx->endpoint_list, ep);
341 DEBUG(4,("dcesrv_interface_register: interface '%s' registered on endpoint '%s'\n",
342 iface->name, ep_name));
347 NTSTATUS dcesrv_inherited_session_key(struct dcesrv_connection *p,
348 DATA_BLOB *session_key)
350 if (p->auth_state.session_info->session_key.length) {
351 *session_key = p->auth_state.session_info->session_key;
354 return NT_STATUS_NO_USER_SESSION_KEY;
358 fetch the user session key - may be default (above) or the SMB session key
360 The key is always truncated to 16 bytes
362 _PUBLIC_ NTSTATUS dcesrv_fetch_session_key(struct dcesrv_connection *p,
363 DATA_BLOB *session_key)
365 NTSTATUS status = p->auth_state.session_key(p, session_key);
366 if (!NT_STATUS_IS_OK(status)) {
370 session_key->length = MIN(session_key->length, 16);
376 connect to a dcerpc endpoint
378 _PUBLIC_ NTSTATUS dcesrv_endpoint_connect(struct dcesrv_context *dce_ctx,
380 const struct dcesrv_endpoint *ep,
381 struct auth_session_info *session_info,
382 struct tevent_context *event_ctx,
383 struct imessaging_context *msg_ctx,
384 struct server_id server_id,
385 uint32_t state_flags,
386 struct dcesrv_connection **_p)
388 struct dcesrv_connection *p;
391 return NT_STATUS_ACCESS_DENIED;
394 p = talloc_zero(mem_ctx, struct dcesrv_connection);
395 NT_STATUS_HAVE_NO_MEMORY(p);
397 if (!talloc_reference(p, session_info)) {
399 return NT_STATUS_NO_MEMORY;
402 p->dce_ctx = dce_ctx;
404 p->packet_log_dir = lpcfg_lock_directory(dce_ctx->lp_ctx);
405 p->auth_state.session_info = session_info;
406 p->auth_state.session_key = dcesrv_generic_session_key;
407 p->event_ctx = event_ctx;
408 p->msg_ctx = msg_ctx;
409 p->server_id = server_id;
410 p->state_flags = state_flags;
411 p->allow_bind = true;
412 p->max_recv_frag = 5840;
413 p->max_xmit_frag = 5840;
420 move a call from an existing linked list to the specified list. This
421 prevents bugs where we forget to remove the call from a previous
424 static void dcesrv_call_set_list(struct dcesrv_call_state *call,
425 enum dcesrv_call_list list)
427 switch (call->list) {
428 case DCESRV_LIST_NONE:
430 case DCESRV_LIST_CALL_LIST:
431 DLIST_REMOVE(call->conn->call_list, call);
433 case DCESRV_LIST_FRAGMENTED_CALL_LIST:
434 DLIST_REMOVE(call->conn->incoming_fragmented_call_list, call);
436 case DCESRV_LIST_PENDING_CALL_LIST:
437 DLIST_REMOVE(call->conn->pending_call_list, call);
442 case DCESRV_LIST_NONE:
444 case DCESRV_LIST_CALL_LIST:
445 DLIST_ADD_END(call->conn->call_list, call);
447 case DCESRV_LIST_FRAGMENTED_CALL_LIST:
448 DLIST_ADD_END(call->conn->incoming_fragmented_call_list, call);
450 case DCESRV_LIST_PENDING_CALL_LIST:
451 DLIST_ADD_END(call->conn->pending_call_list, call);
456 static void dcesrv_call_disconnect_after(struct dcesrv_call_state *call,
459 if (call->conn->terminate != NULL) {
463 call->conn->allow_bind = false;
464 call->conn->allow_alter = false;
465 call->conn->allow_auth3 = false;
466 call->conn->allow_request = false;
468 call->terminate_reason = talloc_strdup(call, reason);
469 if (call->terminate_reason == NULL) {
470 call->terminate_reason = __location__;
475 return a dcerpc bind_nak
477 static NTSTATUS dcesrv_bind_nak(struct dcesrv_call_state *call, uint32_t reason)
479 struct ncacn_packet pkt;
480 struct dcerpc_bind_nak_version version;
481 struct data_blob_list_item *rep;
483 static const uint8_t _pad[3] = { 0, };
486 * We add the call to the pending_call_list
487 * in order to defer the termination.
489 dcesrv_call_disconnect_after(call, "dcesrv_bind_nak");
491 /* setup a bind_nak */
492 dcesrv_init_hdr(&pkt, lpcfg_rpc_big_endian(call->conn->dce_ctx->lp_ctx));
494 pkt.call_id = call->pkt.call_id;
495 pkt.ptype = DCERPC_PKT_BIND_NAK;
496 pkt.pfc_flags = DCERPC_PFC_FLAG_FIRST | DCERPC_PFC_FLAG_LAST;
497 pkt.u.bind_nak.reject_reason = reason;
498 version.rpc_vers = 5;
499 version.rpc_vers_minor = 0;
500 pkt.u.bind_nak.num_versions = 1;
501 pkt.u.bind_nak.versions = &version;
502 pkt.u.bind_nak._pad = data_blob_const(_pad, sizeof(_pad));
504 rep = talloc_zero(call, struct data_blob_list_item);
506 return NT_STATUS_NO_MEMORY;
509 status = ncacn_push_auth(&rep->blob, call, &pkt, NULL);
510 if (!NT_STATUS_IS_OK(status)) {
514 dcerpc_set_frag_length(&rep->blob, rep->blob.length);
516 DLIST_ADD_END(call->replies, rep);
517 dcesrv_call_set_list(call, DCESRV_LIST_CALL_LIST);
519 if (call->conn->call_list && call->conn->call_list->replies) {
520 if (call->conn->transport.report_output_data) {
521 call->conn->transport.report_output_data(call->conn);
528 static NTSTATUS dcesrv_fault_disconnect(struct dcesrv_call_state *call,
532 * We add the call to the pending_call_list
533 * in order to defer the termination.
535 dcesrv_call_disconnect_after(call, "dcesrv_fault_disconnect");
537 return dcesrv_fault_with_flags(call, fault_code,
538 DCERPC_PFC_FLAG_DID_NOT_EXECUTE);
541 static int dcesrv_connection_context_destructor(struct dcesrv_connection_context *c)
543 DLIST_REMOVE(c->conn->contexts, c);
545 if (c->iface && c->iface->unbind) {
546 c->iface->unbind(c, c->iface);
553 static void dcesrv_prepare_context_auth(struct dcesrv_call_state *dce_call)
555 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
556 const struct dcesrv_endpoint *endpoint = dce_call->conn->endpoint;
557 enum dcerpc_transport_t transport =
558 dcerpc_binding_get_transport(endpoint->ep_description);
559 struct dcesrv_connection_context *context = dce_call->context;
560 const struct dcesrv_interface *iface = context->iface;
562 context->min_auth_level = DCERPC_AUTH_LEVEL_NONE;
564 if (transport == NCALRPC) {
565 context->allow_connect = true;
570 * allow overwrite per interface
571 * allow dcerpc auth level connect:<interface>
573 context->allow_connect = lpcfg_allow_dcerpc_auth_level_connect(lp_ctx);
574 context->allow_connect = lpcfg_parm_bool(lp_ctx, NULL,
575 "allow dcerpc auth level connect",
577 context->allow_connect);
580 NTSTATUS dcesrv_interface_bind_require_integrity(struct dcesrv_call_state *dce_call,
581 const struct dcesrv_interface *iface)
583 if (dce_call->context == NULL) {
584 return NT_STATUS_INTERNAL_ERROR;
587 dce_call->context->min_auth_level = DCERPC_AUTH_LEVEL_INTEGRITY;
591 NTSTATUS dcesrv_interface_bind_require_privacy(struct dcesrv_call_state *dce_call,
592 const struct dcesrv_interface *iface)
594 if (dce_call->context == NULL) {
595 return NT_STATUS_INTERNAL_ERROR;
598 dce_call->context->min_auth_level = DCERPC_AUTH_LEVEL_PRIVACY;
602 _PUBLIC_ NTSTATUS dcesrv_interface_bind_reject_connect(struct dcesrv_call_state *dce_call,
603 const struct dcesrv_interface *iface)
605 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
606 const struct dcesrv_endpoint *endpoint = dce_call->conn->endpoint;
607 enum dcerpc_transport_t transport =
608 dcerpc_binding_get_transport(endpoint->ep_description);
609 struct dcesrv_connection_context *context = dce_call->context;
611 if (context == NULL) {
612 return NT_STATUS_INTERNAL_ERROR;
615 if (transport == NCALRPC) {
616 context->allow_connect = true;
621 * allow overwrite per interface
622 * allow dcerpc auth level connect:<interface>
624 context->allow_connect = false;
625 context->allow_connect = lpcfg_parm_bool(lp_ctx, NULL,
626 "allow dcerpc auth level connect",
628 context->allow_connect);
632 _PUBLIC_ NTSTATUS dcesrv_interface_bind_allow_connect(struct dcesrv_call_state *dce_call,
633 const struct dcesrv_interface *iface)
635 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
636 const struct dcesrv_endpoint *endpoint = dce_call->conn->endpoint;
637 enum dcerpc_transport_t transport =
638 dcerpc_binding_get_transport(endpoint->ep_description);
639 struct dcesrv_connection_context *context = dce_call->context;
641 if (context == NULL) {
642 return NT_STATUS_INTERNAL_ERROR;
645 if (transport == NCALRPC) {
646 context->allow_connect = true;
651 * allow overwrite per interface
652 * allow dcerpc auth level connect:<interface>
654 context->allow_connect = true;
655 context->allow_connect = lpcfg_parm_bool(lp_ctx, NULL,
656 "allow dcerpc auth level connect",
658 context->allow_connect);
663 handle a bind request
665 static NTSTATUS dcesrv_bind(struct dcesrv_call_state *call)
667 uint32_t if_version, transfer_syntax_version;
668 struct GUID uuid, *transfer_syntax_uuid;
669 struct ncacn_packet pkt;
670 struct data_blob_list_item *rep;
672 uint32_t result=0, reason=0;
674 const struct dcesrv_interface *iface;
675 uint32_t extra_flags = 0;
676 uint16_t max_req = 0;
677 uint16_t max_rep = 0;
678 const char *ep_prefix = "";
679 const char *endpoint = NULL;
681 status = dcerpc_verify_ncacn_packet_header(&call->pkt,
683 call->pkt.u.bind.auth_info.length,
684 0, /* required flags */
685 DCERPC_PFC_FLAG_FIRST |
686 DCERPC_PFC_FLAG_LAST |
687 DCERPC_PFC_FLAG_SUPPORT_HEADER_SIGN |
688 0x08 | /* this is not defined, but should be ignored */
689 DCERPC_PFC_FLAG_CONC_MPX |
690 DCERPC_PFC_FLAG_DID_NOT_EXECUTE |
691 DCERPC_PFC_FLAG_MAYBE |
692 DCERPC_PFC_FLAG_OBJECT_UUID);
693 if (!NT_STATUS_IS_OK(status)) {
694 return dcesrv_bind_nak(call,
695 DCERPC_BIND_NAK_REASON_PROTOCOL_VERSION_NOT_SUPPORTED);
698 /* max_recv_frag and max_xmit_frag result always in the same value! */
699 max_req = MIN(call->pkt.u.bind.max_xmit_frag,
700 call->pkt.u.bind.max_recv_frag);
702 * The values are between 2048 and 5840 tested against Windows 2012R2
703 * via ncacn_ip_tcp on port 135.
705 max_req = MAX(2048, max_req);
706 max_rep = MIN(max_req, call->conn->max_recv_frag);
707 /* They are truncated to an 8 byte boundary. */
710 /* max_recv_frag and max_xmit_frag result always in the same value! */
711 call->conn->max_recv_frag = max_rep;
712 call->conn->max_xmit_frag = max_rep;
715 if provided, check the assoc_group is valid
717 if (call->pkt.u.bind.assoc_group_id != 0 &&
718 lpcfg_parm_bool(call->conn->dce_ctx->lp_ctx, NULL, "dcesrv","assoc group checking", true) &&
719 dcesrv_assoc_group_find(call->conn->dce_ctx, call->pkt.u.bind.assoc_group_id) == NULL) {
720 return dcesrv_bind_nak(call, 0);
723 if (call->pkt.u.bind.num_contexts < 1 ||
724 call->pkt.u.bind.ctx_list[0].num_transfer_syntaxes < 1) {
725 return dcesrv_bind_nak(call, 0);
728 context_id = call->pkt.u.bind.ctx_list[0].context_id;
730 /* you can't bind twice on one context */
731 if (dcesrv_find_context(call->conn, context_id) != NULL) {
732 return dcesrv_bind_nak(call, 0);
735 if_version = call->pkt.u.bind.ctx_list[0].abstract_syntax.if_version;
736 uuid = call->pkt.u.bind.ctx_list[0].abstract_syntax.uuid;
738 transfer_syntax_version = call->pkt.u.bind.ctx_list[0].transfer_syntaxes[0].if_version;
739 transfer_syntax_uuid = &call->pkt.u.bind.ctx_list[0].transfer_syntaxes[0].uuid;
740 if (!GUID_equal(&ndr_transfer_syntax_ndr.uuid, transfer_syntax_uuid) != 0 ||
741 ndr_transfer_syntax_ndr.if_version != transfer_syntax_version) {
742 char *uuid_str = GUID_string(call, transfer_syntax_uuid);
743 /* we only do NDR encoded dcerpc */
744 DEBUG(0,("Non NDR transfer syntax requested - %s\n", uuid_str));
745 talloc_free(uuid_str);
746 return dcesrv_bind_nak(call, 0);
749 iface = find_interface_by_uuid(call->conn->endpoint, &uuid, if_version);
751 char *uuid_str = GUID_string(call, &uuid);
752 DEBUG(2,("Request for unknown dcerpc interface %s/%d\n", uuid_str, if_version));
753 talloc_free(uuid_str);
755 /* we don't know about that interface */
756 result = DCERPC_BIND_PROVIDER_REJECT;
757 reason = DCERPC_BIND_REASON_ASYNTAX;
761 /* add this context to the list of available context_ids */
762 struct dcesrv_connection_context *context = talloc_zero(call->conn,
763 struct dcesrv_connection_context);
764 if (context == NULL) {
765 return dcesrv_bind_nak(call, 0);
767 context->conn = call->conn;
768 context->iface = iface;
769 context->context_id = context_id;
770 if (call->pkt.u.bind.assoc_group_id != 0) {
771 context->assoc_group = dcesrv_assoc_group_reference(context,
773 call->pkt.u.bind.assoc_group_id);
775 context->assoc_group = dcesrv_assoc_group_new(context, call->conn->dce_ctx);
777 if (context->assoc_group == NULL) {
778 talloc_free(context);
779 return dcesrv_bind_nak(call, 0);
781 context->private_data = NULL;
782 DLIST_ADD(call->conn->contexts, context);
783 call->context = context;
784 talloc_set_destructor(context, dcesrv_connection_context_destructor);
786 dcesrv_prepare_context_auth(call);
788 status = iface->bind(call, iface, if_version);
789 if (!NT_STATUS_IS_OK(status)) {
790 char *uuid_str = GUID_string(call, &uuid);
791 DEBUG(2,("Request for dcerpc interface %s/%d rejected: %s\n",
792 uuid_str, if_version, nt_errstr(status)));
793 talloc_free(uuid_str);
794 /* we don't want to trigger the iface->unbind() hook */
795 context->iface = NULL;
796 talloc_free(call->context);
797 call->context = NULL;
798 return dcesrv_bind_nak(call, 0);
802 if ((call->pkt.pfc_flags & DCERPC_PFC_FLAG_CONC_MPX) &&
803 (call->state_flags & DCESRV_CALL_STATE_FLAG_MULTIPLEXED)) {
804 call->context->conn->state_flags |= DCESRV_CALL_STATE_FLAG_MULTIPLEXED;
805 extra_flags |= DCERPC_PFC_FLAG_CONC_MPX;
808 if (call->state_flags & DCESRV_CALL_STATE_FLAG_PROCESS_PENDING_CALL) {
809 call->context->conn->state_flags |= DCESRV_CALL_STATE_FLAG_PROCESS_PENDING_CALL;
812 /* handle any authentication that is being requested */
813 if (!dcesrv_auth_bind(call)) {
814 talloc_free(call->context);
815 call->context = NULL;
816 return dcesrv_bind_nak(call, DCERPC_BIND_REASON_INVALID_AUTH_TYPE);
819 /* setup a bind_ack */
820 dcesrv_init_hdr(&pkt, lpcfg_rpc_big_endian(call->conn->dce_ctx->lp_ctx));
822 pkt.call_id = call->pkt.call_id;
823 pkt.ptype = DCERPC_PKT_BIND_ACK;
824 pkt.pfc_flags = DCERPC_PFC_FLAG_FIRST | DCERPC_PFC_FLAG_LAST | extra_flags;
825 pkt.u.bind_ack.max_xmit_frag = call->conn->max_xmit_frag;
826 pkt.u.bind_ack.max_recv_frag = call->conn->max_recv_frag;
829 make it possible for iface->bind() to specify the assoc_group_id
830 This helps the openchange mapiproxy plugin to work correctly.
835 pkt.u.bind_ack.assoc_group_id = call->context->assoc_group->id;
837 pkt.u.bind_ack.assoc_group_id = DUMMY_ASSOC_GROUP;
841 endpoint = dcerpc_binding_get_string_option(
842 call->conn->endpoint->ep_description,
846 if (endpoint == NULL) {
850 if (strncasecmp(endpoint, "\\pipe\\", 6) == 0) {
852 * TODO: check if this is really needed
854 * Or if we should fix this in our idl files.
856 ep_prefix = "\\PIPE\\";
860 pkt.u.bind_ack.secondary_address = talloc_asprintf(call, "%s%s",
863 if (pkt.u.bind_ack.secondary_address == NULL) {
864 TALLOC_FREE(call->context);
865 return NT_STATUS_NO_MEMORY;
867 pkt.u.bind_ack.num_results = 1;
868 pkt.u.bind_ack.ctx_list = talloc_zero(call, struct dcerpc_ack_ctx);
869 if (!pkt.u.bind_ack.ctx_list) {
870 talloc_free(call->context);
871 call->context = NULL;
872 return NT_STATUS_NO_MEMORY;
874 pkt.u.bind_ack.ctx_list[0].result = result;
875 pkt.u.bind_ack.ctx_list[0].reason.value = reason;
876 pkt.u.bind_ack.ctx_list[0].syntax = ndr_transfer_syntax_ndr;
877 pkt.u.bind_ack.auth_info = data_blob(NULL, 0);
879 status = dcesrv_auth_bind_ack(call, &pkt);
880 if (!NT_STATUS_IS_OK(status)) {
881 talloc_free(call->context);
882 call->context = NULL;
883 return dcesrv_bind_nak(call, 0);
886 rep = talloc_zero(call, struct data_blob_list_item);
888 talloc_free(call->context);
889 call->context = NULL;
890 return NT_STATUS_NO_MEMORY;
893 status = ncacn_push_auth(&rep->blob, call, &pkt,
894 call->out_auth_info);
895 if (!NT_STATUS_IS_OK(status)) {
896 talloc_free(call->context);
897 call->context = NULL;
901 dcerpc_set_frag_length(&rep->blob, rep->blob.length);
903 DLIST_ADD_END(call->replies, rep);
904 dcesrv_call_set_list(call, DCESRV_LIST_CALL_LIST);
906 if (call->conn->call_list && call->conn->call_list->replies) {
907 if (call->conn->transport.report_output_data) {
908 call->conn->transport.report_output_data(call->conn);
917 handle a auth3 request
919 static NTSTATUS dcesrv_auth3(struct dcesrv_call_state *call)
923 if (!call->conn->allow_auth3) {
924 return dcesrv_fault_disconnect(call, DCERPC_NCA_S_PROTO_ERROR);
927 if (call->conn->auth_state.auth_finished) {
928 return dcesrv_fault_disconnect(call, DCERPC_NCA_S_PROTO_ERROR);
931 status = dcerpc_verify_ncacn_packet_header(&call->pkt,
933 call->pkt.u.auth3.auth_info.length,
934 0, /* required flags */
935 DCERPC_PFC_FLAG_FIRST |
936 DCERPC_PFC_FLAG_LAST |
937 DCERPC_PFC_FLAG_SUPPORT_HEADER_SIGN |
938 0x08 | /* this is not defined, but should be ignored */
939 DCERPC_PFC_FLAG_CONC_MPX |
940 DCERPC_PFC_FLAG_DID_NOT_EXECUTE |
941 DCERPC_PFC_FLAG_MAYBE |
942 DCERPC_PFC_FLAG_OBJECT_UUID);
943 if (!NT_STATUS_IS_OK(status)) {
944 return dcesrv_fault_disconnect(call, DCERPC_NCA_S_PROTO_ERROR);
947 /* handle the auth3 in the auth code */
948 if (!dcesrv_auth_auth3(call)) {
949 return dcesrv_fault(call, DCERPC_FAULT_OTHER);
954 /* we don't send a reply to a auth3 request, except by a
961 handle a bind request
963 static NTSTATUS dcesrv_alter_new_context(struct dcesrv_call_state *call, uint32_t context_id)
965 uint32_t if_version, transfer_syntax_version;
966 struct dcesrv_connection_context *context;
967 const struct dcesrv_interface *iface;
968 struct GUID uuid, *transfer_syntax_uuid;
971 if_version = call->pkt.u.alter.ctx_list[0].abstract_syntax.if_version;
972 uuid = call->pkt.u.alter.ctx_list[0].abstract_syntax.uuid;
974 transfer_syntax_version = call->pkt.u.alter.ctx_list[0].transfer_syntaxes[0].if_version;
975 transfer_syntax_uuid = &call->pkt.u.alter.ctx_list[0].transfer_syntaxes[0].uuid;
976 if (!GUID_equal(transfer_syntax_uuid, &ndr_transfer_syntax_ndr.uuid) ||
977 ndr_transfer_syntax_ndr.if_version != transfer_syntax_version) {
978 /* we only do NDR encoded dcerpc */
979 return NT_STATUS_RPC_PROTSEQ_NOT_SUPPORTED;
982 iface = find_interface_by_uuid(call->conn->endpoint, &uuid, if_version);
984 char *uuid_str = GUID_string(call, &uuid);
985 DEBUG(2,("Request for unknown dcerpc interface %s/%d\n", uuid_str, if_version));
986 talloc_free(uuid_str);
987 return NT_STATUS_RPC_PROTSEQ_NOT_SUPPORTED;
990 /* add this context to the list of available context_ids */
991 context = talloc_zero(call->conn, struct dcesrv_connection_context);
992 if (context == NULL) {
993 return NT_STATUS_NO_MEMORY;
995 context->conn = call->conn;
996 context->iface = iface;
997 context->context_id = context_id;
998 if (call->pkt.u.alter.assoc_group_id != 0) {
999 context->assoc_group = dcesrv_assoc_group_reference(context,
1000 call->conn->dce_ctx,
1001 call->pkt.u.alter.assoc_group_id);
1003 context->assoc_group = dcesrv_assoc_group_new(context, call->conn->dce_ctx);
1005 if (context->assoc_group == NULL) {
1006 talloc_free(context);
1007 call->context = NULL;
1008 return NT_STATUS_NO_MEMORY;
1010 context->private_data = NULL;
1011 DLIST_ADD(call->conn->contexts, context);
1012 call->context = context;
1013 talloc_set_destructor(context, dcesrv_connection_context_destructor);
1015 dcesrv_prepare_context_auth(call);
1017 status = iface->bind(call, iface, if_version);
1018 if (!NT_STATUS_IS_OK(status)) {
1019 /* we don't want to trigger the iface->unbind() hook */
1020 context->iface = NULL;
1021 talloc_free(context);
1022 call->context = NULL;
1026 return NT_STATUS_OK;
1029 /* setup and send an alter_resp */
1030 static NTSTATUS dcesrv_alter_resp(struct dcesrv_call_state *call,
1034 struct ncacn_packet pkt;
1035 uint32_t extra_flags = 0;
1036 struct data_blob_list_item *rep = NULL;
1039 dcesrv_init_hdr(&pkt, lpcfg_rpc_big_endian(call->conn->dce_ctx->lp_ctx));
1040 pkt.auth_length = 0;
1041 pkt.call_id = call->pkt.call_id;
1042 pkt.ptype = DCERPC_PKT_ALTER_RESP;
1044 if ((call->pkt.pfc_flags & DCERPC_PFC_FLAG_CONC_MPX) &&
1045 call->context->conn->state_flags &
1046 DCESRV_CALL_STATE_FLAG_MULTIPLEXED) {
1047 extra_flags |= DCERPC_PFC_FLAG_CONC_MPX;
1049 if (call->state_flags & DCESRV_CALL_STATE_FLAG_PROCESS_PENDING_CALL) {
1050 call->context->conn->state_flags |=
1051 DCESRV_CALL_STATE_FLAG_PROCESS_PENDING_CALL;
1054 pkt.pfc_flags = DCERPC_PFC_FLAG_FIRST | DCERPC_PFC_FLAG_LAST | extra_flags;
1055 pkt.u.alter_resp.max_xmit_frag = call->conn->max_xmit_frag;
1056 pkt.u.alter_resp.max_recv_frag = call->conn->max_recv_frag;
1058 pkt.u.alter_resp.assoc_group_id = call->context->assoc_group->id;
1060 pkt.u.alter_resp.assoc_group_id = 0;
1062 pkt.u.alter_resp.num_results = 1;
1063 pkt.u.alter_resp.ctx_list = talloc_zero(call, struct dcerpc_ack_ctx);
1064 if (!pkt.u.alter_resp.ctx_list) {
1065 return NT_STATUS_NO_MEMORY;
1067 pkt.u.alter_resp.ctx_list[0].result = result;
1068 pkt.u.alter_resp.ctx_list[0].reason.value = reason;
1069 pkt.u.alter_resp.ctx_list[0].syntax = ndr_transfer_syntax_ndr;
1070 pkt.u.alter_resp.auth_info = data_blob(NULL, 0);
1071 pkt.u.alter_resp.secondary_address = "";
1073 status = dcesrv_auth_alter_ack(call, &pkt);
1074 if (!NT_STATUS_IS_OK(status)) {
1075 if (NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)
1076 || NT_STATUS_EQUAL(status, NT_STATUS_LOGON_FAILURE)
1077 || NT_STATUS_EQUAL(status, NT_STATUS_NO_SUCH_USER)
1078 || NT_STATUS_EQUAL(status, NT_STATUS_WRONG_PASSWORD)) {
1079 return dcesrv_fault(call, DCERPC_FAULT_ACCESS_DENIED);
1081 return dcesrv_fault(call, 0);
1084 rep = talloc_zero(call, struct data_blob_list_item);
1086 return NT_STATUS_NO_MEMORY;
1089 status = ncacn_push_auth(&rep->blob, call, &pkt, call->out_auth_info);
1090 if (!NT_STATUS_IS_OK(status)) {
1094 dcerpc_set_frag_length(&rep->blob, rep->blob.length);
1096 DLIST_ADD_END(call->replies, rep);
1097 dcesrv_call_set_list(call, DCESRV_LIST_CALL_LIST);
1099 if (call->conn->call_list && call->conn->call_list->replies) {
1100 if (call->conn->transport.report_output_data) {
1101 call->conn->transport.report_output_data(call->conn);
1105 return NT_STATUS_OK;
1109 handle a alter context request
1111 static NTSTATUS dcesrv_alter(struct dcesrv_call_state *call)
1114 uint32_t context_id;
1116 if (!call->conn->allow_alter) {
1117 return dcesrv_fault_disconnect(call, DCERPC_NCA_S_PROTO_ERROR);
1120 status = dcerpc_verify_ncacn_packet_header(&call->pkt,
1122 call->pkt.u.alter.auth_info.length,
1123 0, /* required flags */
1124 DCERPC_PFC_FLAG_FIRST |
1125 DCERPC_PFC_FLAG_LAST |
1126 DCERPC_PFC_FLAG_SUPPORT_HEADER_SIGN |
1127 0x08 | /* this is not defined, but should be ignored */
1128 DCERPC_PFC_FLAG_CONC_MPX |
1129 DCERPC_PFC_FLAG_DID_NOT_EXECUTE |
1130 DCERPC_PFC_FLAG_MAYBE |
1131 DCERPC_PFC_FLAG_OBJECT_UUID);
1132 if (!NT_STATUS_IS_OK(status)) {
1133 return dcesrv_fault_disconnect(call, DCERPC_NCA_S_PROTO_ERROR);
1136 /* handle any authentication that is being requested */
1137 if (!dcesrv_auth_alter(call)) {
1138 /* TODO: work out the right reject code */
1139 return dcesrv_alter_resp(call,
1140 DCERPC_BIND_PROVIDER_REJECT,
1141 DCERPC_BIND_REASON_ASYNTAX);
1144 context_id = call->pkt.u.alter.ctx_list[0].context_id;
1146 /* see if they are asking for a new interface */
1147 call->context = dcesrv_find_context(call->conn, context_id);
1148 if (!call->context) {
1149 status = dcesrv_alter_new_context(call, context_id);
1150 if (!NT_STATUS_IS_OK(status)) {
1151 return dcesrv_alter_resp(call,
1152 DCERPC_BIND_PROVIDER_REJECT,
1153 DCERPC_BIND_REASON_ASYNTAX);
1157 if (call->pkt.u.alter.assoc_group_id != 0 &&
1158 lpcfg_parm_bool(call->conn->dce_ctx->lp_ctx, NULL, "dcesrv","assoc group checking", true) &&
1159 call->pkt.u.alter.assoc_group_id != call->context->assoc_group->id) {
1160 DEBUG(0,(__location__ ": Failed attempt to use new assoc_group in alter context (0x%08x 0x%08x)\n",
1161 call->context->assoc_group->id, call->pkt.u.alter.assoc_group_id));
1162 /* TODO: can they ask for a new association group? */
1163 return dcesrv_alter_resp(call,
1164 DCERPC_BIND_PROVIDER_REJECT,
1165 DCERPC_BIND_REASON_ASYNTAX);
1168 return dcesrv_alter_resp(call,
1169 DCERPC_BIND_ACK_RESULT_ACCEPTANCE,
1170 DCERPC_BIND_ACK_REASON_NOT_SPECIFIED);
1174 possibly save the call for inspection with ndrdump
1176 static void dcesrv_save_call(struct dcesrv_call_state *call, const char *why)
1180 const char *dump_dir;
1181 dump_dir = lpcfg_parm_string(call->conn->dce_ctx->lp_ctx, NULL, "dcesrv", "stubs directory");
1185 fname = talloc_asprintf(call, "%s/RPC-%s-%u-%s.dat",
1187 call->context->iface->name,
1188 call->pkt.u.request.opnum,
1190 if (file_save(fname, call->pkt.u.request.stub_and_verifier.data, call->pkt.u.request.stub_and_verifier.length)) {
1191 DEBUG(0,("RPC SAVED %s\n", fname));
1197 static NTSTATUS dcesrv_check_verification_trailer(struct dcesrv_call_state *call)
1199 TALLOC_CTX *frame = talloc_stackframe();
1200 const uint32_t bitmask1 = call->conn->auth_state.client_hdr_signing ?
1201 DCERPC_SEC_VT_CLIENT_SUPPORTS_HEADER_SIGNING : 0;
1202 const struct dcerpc_sec_vt_pcontext pcontext = {
1203 .abstract_syntax = call->context->iface->syntax_id,
1204 .transfer_syntax = ndr_transfer_syntax_ndr,
1206 const struct dcerpc_sec_vt_header2 header2 =
1207 dcerpc_sec_vt_header2_from_ncacn_packet(&call->pkt);
1208 enum ndr_err_code ndr_err;
1209 struct dcerpc_sec_verification_trailer *vt = NULL;
1210 NTSTATUS status = NT_STATUS_OK;
1213 SMB_ASSERT(call->pkt.ptype == DCERPC_PKT_REQUEST);
1215 ndr_err = ndr_pop_dcerpc_sec_verification_trailer(call->ndr_pull,
1217 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
1218 status = ndr_map_error2ntstatus(ndr_err);
1222 ok = dcerpc_sec_verification_trailer_check(vt, &bitmask1,
1223 &pcontext, &header2);
1225 status = NT_STATUS_ACCESS_DENIED;
1234 handle a dcerpc request packet
1236 static NTSTATUS dcesrv_request(struct dcesrv_call_state *call)
1238 const struct dcesrv_endpoint *endpoint = call->conn->endpoint;
1239 enum dcerpc_transport_t transport =
1240 dcerpc_binding_get_transport(endpoint->ep_description);
1241 struct ndr_pull *pull;
1243 struct dcesrv_connection_context *context;
1245 if (!call->conn->allow_request) {
1246 return dcesrv_fault_disconnect(call, DCERPC_NCA_S_PROTO_ERROR);
1249 /* if authenticated, and the mech we use can't do async replies, don't use them... */
1250 if (call->conn->auth_state.gensec_security &&
1251 !gensec_have_feature(call->conn->auth_state.gensec_security, GENSEC_FEATURE_ASYNC_REPLIES)) {
1252 call->state_flags &= ~DCESRV_CALL_STATE_FLAG_MAY_ASYNC;
1255 context = dcesrv_find_context(call->conn, call->pkt.u.request.context_id);
1256 if (context == NULL) {
1257 return dcesrv_fault(call, DCERPC_FAULT_UNK_IF);
1260 switch (call->conn->auth_state.auth_level) {
1261 case DCERPC_AUTH_LEVEL_NONE:
1262 case DCERPC_AUTH_LEVEL_INTEGRITY:
1263 case DCERPC_AUTH_LEVEL_PRIVACY:
1266 if (!context->allow_connect) {
1269 addr = tsocket_address_string(call->conn->remote_address,
1272 DEBUG(2, ("%s: restrict auth_level_connect access "
1273 "to [%s] with auth[type=0x%x,level=0x%x] "
1274 "on [%s] from [%s]\n",
1275 __func__, context->iface->name,
1276 call->conn->auth_state.auth_type,
1277 call->conn->auth_state.auth_level,
1278 derpc_transport_string_by_transport(transport),
1280 return dcesrv_fault(call, DCERPC_FAULT_ACCESS_DENIED);
1285 if (call->conn->auth_state.auth_level < context->min_auth_level) {
1288 addr = tsocket_address_string(call->conn->remote_address, call);
1290 DEBUG(2, ("%s: restrict access by min_auth_level[0x%x] "
1291 "to [%s] with auth[type=0x%x,level=0x%x] "
1292 "on [%s] from [%s]\n",
1294 context->min_auth_level,
1295 context->iface->name,
1296 call->conn->auth_state.auth_type,
1297 call->conn->auth_state.auth_level,
1298 derpc_transport_string_by_transport(transport),
1300 return dcesrv_fault(call, DCERPC_FAULT_ACCESS_DENIED);
1303 pull = ndr_pull_init_blob(&call->pkt.u.request.stub_and_verifier, call);
1304 NT_STATUS_HAVE_NO_MEMORY(pull);
1306 pull->flags |= LIBNDR_FLAG_REF_ALLOC;
1308 call->context = context;
1309 call->ndr_pull = pull;
1311 if (!(call->pkt.drep[0] & DCERPC_DREP_LE)) {
1312 pull->flags |= LIBNDR_FLAG_BIGENDIAN;
1315 status = dcesrv_check_verification_trailer(call);
1316 if (!NT_STATUS_IS_OK(status)) {
1317 uint32_t faultcode = DCERPC_FAULT_OTHER;
1318 if (NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
1319 faultcode = DCERPC_FAULT_ACCESS_DENIED;
1321 DEBUG(10, ("dcesrv_check_verification_trailer failed: %s\n",
1322 nt_errstr(status)));
1323 return dcesrv_fault(call, faultcode);
1326 /* unravel the NDR for the packet */
1327 status = context->iface->ndr_pull(call, call, pull, &call->r);
1328 if (!NT_STATUS_IS_OK(status)) {
1329 if (call->fault_code == DCERPC_FAULT_OP_RNG_ERROR) {
1330 /* we got an unknown call */
1331 DEBUG(3,(__location__ ": Unknown RPC call %u on %s\n",
1332 call->pkt.u.request.opnum, context->iface->name));
1333 dcesrv_save_call(call, "unknown");
1335 dcesrv_save_call(call, "pullfail");
1337 return dcesrv_fault(call, call->fault_code);
1340 if (pull->offset != pull->data_size) {
1341 dcesrv_save_call(call, "extrabytes");
1342 DEBUG(3,("Warning: %d extra bytes in incoming RPC request\n",
1343 pull->data_size - pull->offset));
1346 /* call the dispatch function */
1347 status = context->iface->dispatch(call, call, call->r);
1348 if (!NT_STATUS_IS_OK(status)) {
1349 DEBUG(5,("dcerpc fault in call %s:%02x - %s\n",
1350 context->iface->name,
1351 call->pkt.u.request.opnum,
1352 dcerpc_errstr(pull, call->fault_code)));
1353 return dcesrv_fault(call, call->fault_code);
1356 /* add the call to the pending list */
1357 dcesrv_call_set_list(call, DCESRV_LIST_PENDING_CALL_LIST);
1359 if (call->state_flags & DCESRV_CALL_STATE_FLAG_ASYNC) {
1360 return NT_STATUS_OK;
1363 return dcesrv_reply(call);
1368 remove the call from the right list when freed
1370 static int dcesrv_call_dequeue(struct dcesrv_call_state *call)
1372 dcesrv_call_set_list(call, DCESRV_LIST_NONE);
1376 _PUBLIC_ const struct tsocket_address *dcesrv_connection_get_local_address(struct dcesrv_connection *conn)
1378 return conn->local_address;
1381 _PUBLIC_ const struct tsocket_address *dcesrv_connection_get_remote_address(struct dcesrv_connection *conn)
1383 return conn->remote_address;
1387 process some input to a dcerpc endpoint server.
1389 static NTSTATUS dcesrv_process_ncacn_packet(struct dcesrv_connection *dce_conn,
1390 struct ncacn_packet *pkt,
1394 struct dcesrv_call_state *call;
1396 call = talloc_zero(dce_conn, struct dcesrv_call_state);
1398 data_blob_free(&blob);
1400 return NT_STATUS_NO_MEMORY;
1402 call->conn = dce_conn;
1403 call->event_ctx = dce_conn->event_ctx;
1404 call->msg_ctx = dce_conn->msg_ctx;
1405 call->state_flags = call->conn->state_flags;
1406 call->time = timeval_current();
1407 call->list = DCESRV_LIST_NONE;
1409 talloc_steal(call, pkt);
1410 talloc_steal(call, blob.data);
1413 talloc_set_destructor(call, dcesrv_call_dequeue);
1415 if (call->conn->allow_bind) {
1417 * Only one bind is possible per connection
1419 call->conn->allow_bind = false;
1420 return dcesrv_bind(call);
1423 /* we have to check the signing here, before combining the
1425 if (call->pkt.ptype == DCERPC_PKT_REQUEST) {
1426 if (!call->conn->allow_request) {
1427 return dcesrv_fault_disconnect(call,
1428 DCERPC_NCA_S_PROTO_ERROR);
1431 status = dcerpc_verify_ncacn_packet_header(&call->pkt,
1433 call->pkt.u.request.stub_and_verifier.length,
1434 0, /* required_flags */
1435 DCERPC_PFC_FLAG_FIRST |
1436 DCERPC_PFC_FLAG_LAST |
1437 DCERPC_PFC_FLAG_PENDING_CANCEL |
1438 0x08 | /* this is not defined, but should be ignored */
1439 DCERPC_PFC_FLAG_CONC_MPX |
1440 DCERPC_PFC_FLAG_DID_NOT_EXECUTE |
1441 DCERPC_PFC_FLAG_MAYBE |
1442 DCERPC_PFC_FLAG_OBJECT_UUID);
1443 if (!NT_STATUS_IS_OK(status)) {
1444 return dcesrv_fault_disconnect(call,
1445 DCERPC_NCA_S_PROTO_ERROR);
1448 if (!dcesrv_auth_request(call, &blob)) {
1449 return dcesrv_fault(call, DCERPC_FAULT_ACCESS_DENIED);
1453 /* see if this is a continued packet */
1454 if (call->pkt.ptype == DCERPC_PKT_REQUEST &&
1455 !(call->pkt.pfc_flags & DCERPC_PFC_FLAG_FIRST)) {
1456 struct dcesrv_call_state *call2 = call;
1457 uint32_t alloc_size;
1459 /* we only allow fragmented requests, no other packet types */
1460 if (call->pkt.ptype != DCERPC_PKT_REQUEST) {
1461 return dcesrv_fault(call2, DCERPC_FAULT_OTHER);
1464 /* this is a continuation of an existing call - find the call
1465 then tack it on the end */
1466 call = dcesrv_find_fragmented_call(dce_conn, call2->pkt.call_id);
1468 return dcesrv_fault(call2, DCERPC_FAULT_OTHER);
1471 if (call->pkt.ptype != call2->pkt.ptype) {
1472 /* trying to play silly buggers are we? */
1473 return dcesrv_fault(call2, DCERPC_NCA_S_PROTO_ERROR);
1475 if (memcmp(call->pkt.drep, call2->pkt.drep, sizeof(pkt->drep)) != 0) {
1476 return dcesrv_fault(call2, DCERPC_NCA_S_PROTO_ERROR);
1478 if (call->pkt.call_id != call2->pkt.call_id) {
1479 return dcesrv_fault(call2, DCERPC_NCA_S_PROTO_ERROR);
1481 if (call->pkt.u.request.context_id != call2->pkt.u.request.context_id) {
1482 return dcesrv_fault(call2, DCERPC_NCA_S_PROTO_ERROR);
1484 if (call->pkt.u.request.opnum != call2->pkt.u.request.opnum) {
1485 return dcesrv_fault(call2, DCERPC_NCA_S_PROTO_ERROR);
1488 alloc_size = call->pkt.u.request.stub_and_verifier.length +
1489 call2->pkt.u.request.stub_and_verifier.length;
1490 if (call->pkt.u.request.alloc_hint > alloc_size) {
1491 alloc_size = call->pkt.u.request.alloc_hint;
1494 call->pkt.u.request.stub_and_verifier.data =
1495 talloc_realloc(call,
1496 call->pkt.u.request.stub_and_verifier.data,
1497 uint8_t, alloc_size);
1498 if (!call->pkt.u.request.stub_and_verifier.data) {
1499 return dcesrv_fault(call2, DCERPC_FAULT_OTHER);
1501 memcpy(call->pkt.u.request.stub_and_verifier.data +
1502 call->pkt.u.request.stub_and_verifier.length,
1503 call2->pkt.u.request.stub_and_verifier.data,
1504 call2->pkt.u.request.stub_and_verifier.length);
1505 call->pkt.u.request.stub_and_verifier.length +=
1506 call2->pkt.u.request.stub_and_verifier.length;
1508 call->pkt.pfc_flags |= (call2->pkt.pfc_flags & DCERPC_PFC_FLAG_LAST);
1513 /* this may not be the last pdu in the chain - if its isn't then
1514 just put it on the incoming_fragmented_call_list and wait for the rest */
1515 if (call->pkt.ptype == DCERPC_PKT_REQUEST &&
1516 !(call->pkt.pfc_flags & DCERPC_PFC_FLAG_LAST)) {
1517 dcesrv_call_set_list(call, DCESRV_LIST_FRAGMENTED_CALL_LIST);
1518 return NT_STATUS_OK;
1521 /* This removes any fragments we may have had stashed away */
1522 dcesrv_call_set_list(call, DCESRV_LIST_NONE);
1524 switch (call->pkt.ptype) {
1525 case DCERPC_PKT_BIND:
1526 status = dcesrv_bind_nak(call,
1527 DCERPC_BIND_NAK_REASON_NOT_SPECIFIED);
1529 case DCERPC_PKT_AUTH3:
1530 status = dcesrv_auth3(call);
1532 case DCERPC_PKT_ALTER:
1533 status = dcesrv_alter(call);
1535 case DCERPC_PKT_REQUEST:
1536 status = dcesrv_request(call);
1539 status = dcesrv_fault_disconnect(call, DCERPC_NCA_S_PROTO_ERROR);
1543 /* if we are going to be sending a reply then add
1544 it to the list of pending calls. We add it to the end to keep the call
1545 list in the order we will answer */
1546 if (!NT_STATUS_IS_OK(status)) {
1553 _PUBLIC_ NTSTATUS dcesrv_init_context(TALLOC_CTX *mem_ctx,
1554 struct loadparm_context *lp_ctx,
1555 const char **endpoint_servers, struct dcesrv_context **_dce_ctx)
1558 struct dcesrv_context *dce_ctx;
1561 if (!endpoint_servers) {
1562 DEBUG(0,("dcesrv_init_context: no endpoint servers configured\n"));
1563 return NT_STATUS_INTERNAL_ERROR;
1566 dce_ctx = talloc_zero(mem_ctx, struct dcesrv_context);
1567 NT_STATUS_HAVE_NO_MEMORY(dce_ctx);
1569 if (uid_wrapper_enabled()) {
1570 setenv("UID_WRAPPER_MYUID", "1", 1);
1572 dce_ctx->initial_euid = geteuid();
1573 if (uid_wrapper_enabled()) {
1574 unsetenv("UID_WRAPPER_MYUID");
1577 dce_ctx->endpoint_list = NULL;
1578 dce_ctx->lp_ctx = lp_ctx;
1579 dce_ctx->assoc_groups_idr = idr_init(dce_ctx);
1580 NT_STATUS_HAVE_NO_MEMORY(dce_ctx->assoc_groups_idr);
1581 dce_ctx->broken_connections = NULL;
1583 for (i=0;endpoint_servers[i];i++) {
1584 const struct dcesrv_endpoint_server *ep_server;
1586 ep_server = dcesrv_ep_server_byname(endpoint_servers[i]);
1588 DEBUG(0,("dcesrv_init_context: failed to find endpoint server = '%s'\n", endpoint_servers[i]));
1589 return NT_STATUS_INTERNAL_ERROR;
1592 status = ep_server->init_server(dce_ctx, ep_server);
1593 if (!NT_STATUS_IS_OK(status)) {
1594 DEBUG(0,("dcesrv_init_context: failed to init endpoint server = '%s': %s\n", endpoint_servers[i],
1595 nt_errstr(status)));
1600 *_dce_ctx = dce_ctx;
1601 return NT_STATUS_OK;
1604 /* the list of currently registered DCERPC endpoint servers.
1606 static struct ep_server {
1607 struct dcesrv_endpoint_server *ep_server;
1608 } *ep_servers = NULL;
1609 static int num_ep_servers;
1612 register a DCERPC endpoint server.
1614 The 'name' can be later used by other backends to find the operations
1615 structure for this backend.
1617 The 'type' is used to specify whether this is for a disk, printer or IPC$ share
1619 _PUBLIC_ NTSTATUS dcerpc_register_ep_server(const void *_ep_server)
1621 const struct dcesrv_endpoint_server *ep_server = _ep_server;
1623 if (dcesrv_ep_server_byname(ep_server->name) != NULL) {
1624 /* its already registered! */
1625 DEBUG(0,("DCERPC endpoint server '%s' already registered\n",
1627 return NT_STATUS_OBJECT_NAME_COLLISION;
1630 ep_servers = realloc_p(ep_servers, struct ep_server, num_ep_servers+1);
1632 smb_panic("out of memory in dcerpc_register");
1635 ep_servers[num_ep_servers].ep_server = smb_xmemdup(ep_server, sizeof(*ep_server));
1636 ep_servers[num_ep_servers].ep_server->name = smb_xstrdup(ep_server->name);
1640 DEBUG(3,("DCERPC endpoint server '%s' registered\n",
1643 return NT_STATUS_OK;
1647 return the operations structure for a named backend of the specified type
1649 const struct dcesrv_endpoint_server *dcesrv_ep_server_byname(const char *name)
1653 for (i=0;i<num_ep_servers;i++) {
1654 if (strcmp(ep_servers[i].ep_server->name, name) == 0) {
1655 return ep_servers[i].ep_server;
1662 void dcerpc_server_init(struct loadparm_context *lp_ctx)
1664 static bool initialized;
1665 #define _MODULE_PROTO(init) extern NTSTATUS init(void);
1666 STATIC_dcerpc_server_MODULES_PROTO;
1667 init_module_fn static_init[] = { STATIC_dcerpc_server_MODULES };
1668 init_module_fn *shared_init;
1675 shared_init = load_samba_modules(NULL, "dcerpc_server");
1677 run_init_functions(static_init);
1678 run_init_functions(shared_init);
1680 talloc_free(shared_init);
1684 return the DCERPC module version, and the size of some critical types
1685 This can be used by endpoint server modules to either detect compilation errors, or provide
1686 multiple implementations for different smbd compilation options in one module
1688 const struct dcesrv_critical_sizes *dcerpc_module_version(void)
1690 static const struct dcesrv_critical_sizes critical_sizes = {
1691 DCERPC_MODULE_VERSION,
1692 sizeof(struct dcesrv_context),
1693 sizeof(struct dcesrv_endpoint),
1694 sizeof(struct dcesrv_endpoint_server),
1695 sizeof(struct dcesrv_interface),
1696 sizeof(struct dcesrv_if_list),
1697 sizeof(struct dcesrv_connection),
1698 sizeof(struct dcesrv_call_state),
1699 sizeof(struct dcesrv_auth),
1700 sizeof(struct dcesrv_handle)
1703 return &critical_sizes;
1706 static void dcesrv_terminate_connection(struct dcesrv_connection *dce_conn, const char *reason)
1708 struct dcesrv_context *dce_ctx = dce_conn->dce_ctx;
1709 struct stream_connection *srv_conn;
1710 srv_conn = talloc_get_type(dce_conn->transport.private_data,
1711 struct stream_connection);
1713 dce_conn->allow_bind = false;
1714 dce_conn->allow_auth3 = false;
1715 dce_conn->allow_alter = false;
1716 dce_conn->allow_request = false;
1718 if (dce_conn->pending_call_list == NULL) {
1719 char *full_reason = talloc_asprintf(dce_conn, "dcesrv: %s", reason);
1721 DLIST_REMOVE(dce_ctx->broken_connections, dce_conn);
1722 stream_terminate_connection(srv_conn, full_reason ? full_reason : reason);
1726 if (dce_conn->terminate != NULL) {
1730 DEBUG(3,("dcesrv: terminating connection due to '%s' defered due to pending calls\n",
1732 dce_conn->terminate = talloc_strdup(dce_conn, reason);
1733 if (dce_conn->terminate == NULL) {
1734 dce_conn->terminate = "dcesrv: defered terminating connection - no memory";
1736 DLIST_ADD_END(dce_ctx->broken_connections, dce_conn);
1739 static void dcesrv_cleanup_broken_connections(struct dcesrv_context *dce_ctx)
1741 struct dcesrv_connection *cur, *next;
1743 next = dce_ctx->broken_connections;
1744 while (next != NULL) {
1748 if (cur->state_flags & DCESRV_CALL_STATE_FLAG_PROCESS_PENDING_CALL) {
1749 struct dcesrv_connection_context *context_cur, *context_next;
1751 context_next = cur->contexts;
1752 while (context_next != NULL) {
1753 context_cur = context_next;
1754 context_next = context_cur->next;
1756 dcesrv_connection_context_destructor(context_cur);
1760 dcesrv_terminate_connection(cur, cur->terminate);
1764 /* We need this include to be able to compile on some plateforms
1765 * (ie. freebsd 7.2) as it seems that <sys/uio.h> is not included
1767 * It has to be that deep because otherwise we have a conflict on
1768 * const struct dcesrv_interface declaration.
1769 * This is mostly due to socket_wrapper defining #define bind swrap_bind
1770 * which conflict with the bind used before.
1772 #include "system/network.h"
1774 struct dcesrv_sock_reply_state {
1775 struct dcesrv_connection *dce_conn;
1776 struct dcesrv_call_state *call;
1780 static void dcesrv_sock_reply_done(struct tevent_req *subreq);
1781 static void dcesrv_call_terminate_step1(struct tevent_req *subreq);
1783 static void dcesrv_sock_report_output_data(struct dcesrv_connection *dce_conn)
1785 struct dcesrv_call_state *call;
1787 call = dce_conn->call_list;
1788 if (!call || !call->replies) {
1792 while (call->replies) {
1793 struct data_blob_list_item *rep = call->replies;
1794 struct dcesrv_sock_reply_state *substate;
1795 struct tevent_req *subreq;
1797 substate = talloc_zero(call, struct dcesrv_sock_reply_state);
1799 dcesrv_terminate_connection(dce_conn, "no memory");
1803 substate->dce_conn = dce_conn;
1804 substate->call = NULL;
1806 DLIST_REMOVE(call->replies, rep);
1808 if (call->replies == NULL && call->terminate_reason == NULL) {
1809 substate->call = call;
1812 substate->iov.iov_base = (void *) rep->blob.data;
1813 substate->iov.iov_len = rep->blob.length;
1815 subreq = tstream_writev_queue_send(substate,
1816 dce_conn->event_ctx,
1818 dce_conn->send_queue,
1821 dcesrv_terminate_connection(dce_conn, "no memory");
1824 tevent_req_set_callback(subreq, dcesrv_sock_reply_done,
1828 if (call->terminate_reason != NULL) {
1829 struct tevent_req *subreq;
1831 subreq = tevent_queue_wait_send(call,
1832 dce_conn->event_ctx,
1833 dce_conn->send_queue);
1835 dcesrv_terminate_connection(dce_conn, __location__);
1838 tevent_req_set_callback(subreq, dcesrv_call_terminate_step1,
1842 DLIST_REMOVE(call->conn->call_list, call);
1843 call->list = DCESRV_LIST_NONE;
1846 static void dcesrv_sock_reply_done(struct tevent_req *subreq)
1848 struct dcesrv_sock_reply_state *substate = tevent_req_callback_data(subreq,
1849 struct dcesrv_sock_reply_state);
1853 struct dcesrv_call_state *call = substate->call;
1855 ret = tstream_writev_queue_recv(subreq, &sys_errno);
1856 TALLOC_FREE(subreq);
1858 status = map_nt_error_from_unix_common(sys_errno);
1859 dcesrv_terminate_connection(substate->dce_conn, nt_errstr(status));
1863 talloc_free(substate);
1869 static void dcesrv_call_terminate_step2(struct tevent_req *subreq);
1871 static void dcesrv_call_terminate_step1(struct tevent_req *subreq)
1873 struct dcesrv_call_state *call = tevent_req_callback_data(subreq,
1874 struct dcesrv_call_state);
1878 /* make sure we stop send queue before removing subreq */
1879 tevent_queue_stop(call->conn->send_queue);
1881 ok = tevent_queue_wait_recv(subreq);
1882 TALLOC_FREE(subreq);
1884 dcesrv_terminate_connection(call->conn, __location__);
1888 /* disconnect after 200 usecs */
1889 tv = timeval_current_ofs_usec(200);
1890 subreq = tevent_wakeup_send(call, call->conn->event_ctx, tv);
1891 if (subreq == NULL) {
1892 dcesrv_terminate_connection(call->conn, __location__);
1895 tevent_req_set_callback(subreq, dcesrv_call_terminate_step2,
1899 static void dcesrv_call_terminate_step2(struct tevent_req *subreq)
1901 struct dcesrv_call_state *call = tevent_req_callback_data(subreq,
1902 struct dcesrv_call_state);
1905 ok = tevent_wakeup_recv(subreq);
1906 TALLOC_FREE(subreq);
1908 dcesrv_terminate_connection(call->conn, __location__);
1912 dcesrv_terminate_connection(call->conn, call->terminate_reason);
1915 struct dcesrv_socket_context {
1916 const struct dcesrv_endpoint *endpoint;
1917 struct dcesrv_context *dcesrv_ctx;
1921 static void dcesrv_read_fragment_done(struct tevent_req *subreq);
1923 static void dcesrv_sock_accept(struct stream_connection *srv_conn)
1926 struct dcesrv_socket_context *dcesrv_sock =
1927 talloc_get_type(srv_conn->private_data, struct dcesrv_socket_context);
1928 enum dcerpc_transport_t transport =
1929 dcerpc_binding_get_transport(dcesrv_sock->endpoint->ep_description);
1930 struct dcesrv_connection *dcesrv_conn = NULL;
1932 struct tevent_req *subreq;
1933 struct loadparm_context *lp_ctx = dcesrv_sock->dcesrv_ctx->lp_ctx;
1935 dcesrv_cleanup_broken_connections(dcesrv_sock->dcesrv_ctx);
1937 if (!srv_conn->session_info) {
1938 status = auth_anonymous_session_info(srv_conn,
1940 &srv_conn->session_info);
1941 if (!NT_STATUS_IS_OK(status)) {
1942 DEBUG(0,("dcesrv_sock_accept: auth_anonymous_session_info failed: %s\n",
1943 nt_errstr(status)));
1944 stream_terminate_connection(srv_conn, nt_errstr(status));
1949 status = dcesrv_endpoint_connect(dcesrv_sock->dcesrv_ctx,
1951 dcesrv_sock->endpoint,
1952 srv_conn->session_info,
1953 srv_conn->event.ctx,
1955 srv_conn->server_id,
1956 DCESRV_CALL_STATE_FLAG_MAY_ASYNC,
1958 if (!NT_STATUS_IS_OK(status)) {
1959 DEBUG(0,("dcesrv_sock_accept: dcesrv_endpoint_connect failed: %s\n",
1960 nt_errstr(status)));
1961 stream_terminate_connection(srv_conn, nt_errstr(status));
1965 dcesrv_conn->transport.private_data = srv_conn;
1966 dcesrv_conn->transport.report_output_data = dcesrv_sock_report_output_data;
1968 TALLOC_FREE(srv_conn->event.fde);
1970 dcesrv_conn->send_queue = tevent_queue_create(dcesrv_conn, "dcesrv send queue");
1971 if (!dcesrv_conn->send_queue) {
1972 status = NT_STATUS_NO_MEMORY;
1973 DEBUG(0,("dcesrv_sock_accept: tevent_queue_create(%s)\n",
1974 nt_errstr(status)));
1975 stream_terminate_connection(srv_conn, nt_errstr(status));
1979 if (transport == NCACN_NP) {
1980 dcesrv_conn->auth_state.session_key = dcesrv_inherited_session_key;
1981 dcesrv_conn->stream = talloc_move(dcesrv_conn,
1982 &srv_conn->tstream);
1984 ret = tstream_bsd_existing_socket(dcesrv_conn,
1985 socket_get_fd(srv_conn->socket),
1986 &dcesrv_conn->stream);
1988 status = map_nt_error_from_unix_common(errno);
1989 DEBUG(0, ("dcesrv_sock_accept: "
1990 "failed to setup tstream: %s\n",
1991 nt_errstr(status)));
1992 stream_terminate_connection(srv_conn, nt_errstr(status));
1995 socket_set_flags(srv_conn->socket, SOCKET_FLAG_NOCLOSE);
1998 dcesrv_conn->local_address = srv_conn->local_address;
1999 dcesrv_conn->remote_address = srv_conn->remote_address;
2001 if (transport == NCALRPC) {
2005 ret = getpeereid(socket_get_fd(srv_conn->socket), &uid, &gid);
2007 status = map_nt_error_from_unix_common(errno);
2008 DEBUG(0, ("dcesrv_sock_accept: "
2009 "getpeereid() failed for NCALRPC: %s\n",
2010 nt_errstr(status)));
2011 stream_terminate_connection(srv_conn, nt_errstr(status));
2014 if (uid == dcesrv_conn->dce_ctx->initial_euid) {
2015 struct tsocket_address *r = NULL;
2017 ret = tsocket_address_unix_from_path(dcesrv_conn,
2018 "/root/ncalrpc_as_system",
2021 status = map_nt_error_from_unix_common(errno);
2022 DEBUG(0, ("dcesrv_sock_accept: "
2023 "tsocket_address_unix_from_path() failed for NCALRPC: %s\n",
2024 nt_errstr(status)));
2025 stream_terminate_connection(srv_conn, nt_errstr(status));
2028 dcesrv_conn->remote_address = r;
2032 srv_conn->private_data = dcesrv_conn;
2034 irpc_add_name(srv_conn->msg_ctx, "rpc_server");
2036 subreq = dcerpc_read_ncacn_packet_send(dcesrv_conn,
2037 dcesrv_conn->event_ctx,
2038 dcesrv_conn->stream);
2040 status = NT_STATUS_NO_MEMORY;
2041 DEBUG(0,("dcesrv_sock_accept: dcerpc_read_fragment_buffer_send(%s)\n",
2042 nt_errstr(status)));
2043 stream_terminate_connection(srv_conn, nt_errstr(status));
2046 tevent_req_set_callback(subreq, dcesrv_read_fragment_done, dcesrv_conn);
2051 static void dcesrv_read_fragment_done(struct tevent_req *subreq)
2053 struct dcesrv_connection *dce_conn = tevent_req_callback_data(subreq,
2054 struct dcesrv_connection);
2055 struct dcesrv_context *dce_ctx = dce_conn->dce_ctx;
2056 struct ncacn_packet *pkt;
2060 if (dce_conn->terminate) {
2062 * if the current connection is broken
2063 * we need to clean it up before any other connection
2065 dcesrv_terminate_connection(dce_conn, dce_conn->terminate);
2066 dcesrv_cleanup_broken_connections(dce_ctx);
2070 dcesrv_cleanup_broken_connections(dce_ctx);
2072 status = dcerpc_read_ncacn_packet_recv(subreq, dce_conn,
2074 TALLOC_FREE(subreq);
2075 if (!NT_STATUS_IS_OK(status)) {
2076 dcesrv_terminate_connection(dce_conn, nt_errstr(status));
2080 status = dcesrv_process_ncacn_packet(dce_conn, pkt, buffer);
2081 if (!NT_STATUS_IS_OK(status)) {
2082 dcesrv_terminate_connection(dce_conn, nt_errstr(status));
2086 subreq = dcerpc_read_ncacn_packet_send(dce_conn,
2087 dce_conn->event_ctx,
2090 status = NT_STATUS_NO_MEMORY;
2091 dcesrv_terminate_connection(dce_conn, nt_errstr(status));
2094 tevent_req_set_callback(subreq, dcesrv_read_fragment_done, dce_conn);
2097 static void dcesrv_sock_recv(struct stream_connection *conn, uint16_t flags)
2099 struct dcesrv_connection *dce_conn = talloc_get_type(conn->private_data,
2100 struct dcesrv_connection);
2101 dcesrv_terminate_connection(dce_conn, "dcesrv_sock_recv triggered");
2104 static void dcesrv_sock_send(struct stream_connection *conn, uint16_t flags)
2106 struct dcesrv_connection *dce_conn = talloc_get_type(conn->private_data,
2107 struct dcesrv_connection);
2108 dcesrv_terminate_connection(dce_conn, "dcesrv_sock_send triggered");
2112 static const struct stream_server_ops dcesrv_stream_ops = {
2114 .accept_connection = dcesrv_sock_accept,
2115 .recv_handler = dcesrv_sock_recv,
2116 .send_handler = dcesrv_sock_send,
2119 static NTSTATUS dcesrv_add_ep_unix(struct dcesrv_context *dce_ctx,
2120 struct loadparm_context *lp_ctx,
2121 struct dcesrv_endpoint *e,
2122 struct tevent_context *event_ctx, const struct model_ops *model_ops)
2124 struct dcesrv_socket_context *dcesrv_sock;
2127 const char *endpoint;
2129 dcesrv_sock = talloc_zero(event_ctx, struct dcesrv_socket_context);
2130 NT_STATUS_HAVE_NO_MEMORY(dcesrv_sock);
2132 /* remember the endpoint of this socket */
2133 dcesrv_sock->endpoint = e;
2134 dcesrv_sock->dcesrv_ctx = talloc_reference(dcesrv_sock, dce_ctx);
2136 endpoint = dcerpc_binding_get_string_option(e->ep_description, "endpoint");
2138 status = stream_setup_socket(dcesrv_sock, event_ctx, lp_ctx,
2139 model_ops, &dcesrv_stream_ops,
2140 "unix", endpoint, &port,
2141 lpcfg_socket_options(lp_ctx),
2143 if (!NT_STATUS_IS_OK(status)) {
2144 DEBUG(0,("service_setup_stream_socket(path=%s) failed - %s\n",
2145 endpoint, nt_errstr(status)));
2151 static NTSTATUS dcesrv_add_ep_ncalrpc(struct dcesrv_context *dce_ctx,
2152 struct loadparm_context *lp_ctx,
2153 struct dcesrv_endpoint *e,
2154 struct tevent_context *event_ctx, const struct model_ops *model_ops)
2156 struct dcesrv_socket_context *dcesrv_sock;
2160 const char *endpoint;
2162 endpoint = dcerpc_binding_get_string_option(e->ep_description, "endpoint");
2164 if (endpoint == NULL) {
2166 * No identifier specified: use DEFAULT.
2168 * TODO: DO NOT hardcode this value anywhere else. Rather, specify
2169 * no endpoint and let the epmapper worry about it.
2171 endpoint = "DEFAULT";
2172 status = dcerpc_binding_set_string_option(e->ep_description,
2175 if (!NT_STATUS_IS_OK(status)) {
2176 DEBUG(0,("dcerpc_binding_set_string_option() failed - %s\n",
2177 nt_errstr(status)));
2182 full_path = talloc_asprintf(dce_ctx, "%s/%s", lpcfg_ncalrpc_dir(lp_ctx),
2185 dcesrv_sock = talloc_zero(event_ctx, struct dcesrv_socket_context);
2186 NT_STATUS_HAVE_NO_MEMORY(dcesrv_sock);
2188 /* remember the endpoint of this socket */
2189 dcesrv_sock->endpoint = e;
2190 dcesrv_sock->dcesrv_ctx = talloc_reference(dcesrv_sock, dce_ctx);
2192 status = stream_setup_socket(dcesrv_sock, event_ctx, lp_ctx,
2193 model_ops, &dcesrv_stream_ops,
2194 "unix", full_path, &port,
2195 lpcfg_socket_options(lp_ctx),
2197 if (!NT_STATUS_IS_OK(status)) {
2198 DEBUG(0,("service_setup_stream_socket(identifier=%s,path=%s) failed - %s\n",
2199 endpoint, full_path, nt_errstr(status)));
2204 static NTSTATUS dcesrv_add_ep_np(struct dcesrv_context *dce_ctx,
2205 struct loadparm_context *lp_ctx,
2206 struct dcesrv_endpoint *e,
2207 struct tevent_context *event_ctx, const struct model_ops *model_ops)
2209 struct dcesrv_socket_context *dcesrv_sock;
2211 const char *endpoint;
2213 endpoint = dcerpc_binding_get_string_option(e->ep_description, "endpoint");
2214 if (endpoint == NULL) {
2215 DEBUG(0, ("Endpoint mandatory for named pipes\n"));
2216 return NT_STATUS_INVALID_PARAMETER;
2219 dcesrv_sock = talloc_zero(event_ctx, struct dcesrv_socket_context);
2220 NT_STATUS_HAVE_NO_MEMORY(dcesrv_sock);
2222 /* remember the endpoint of this socket */
2223 dcesrv_sock->endpoint = e;
2224 dcesrv_sock->dcesrv_ctx = talloc_reference(dcesrv_sock, dce_ctx);
2226 status = tstream_setup_named_pipe(dce_ctx, event_ctx, lp_ctx,
2227 model_ops, &dcesrv_stream_ops,
2230 if (!NT_STATUS_IS_OK(status)) {
2231 DEBUG(0,("stream_setup_named_pipe(pipe=%s) failed - %s\n",
2232 endpoint, nt_errstr(status)));
2236 return NT_STATUS_OK;
2240 add a socket address to the list of events, one event per dcerpc endpoint
2242 static NTSTATUS add_socket_rpc_tcp_iface(struct dcesrv_context *dce_ctx, struct dcesrv_endpoint *e,
2243 struct tevent_context *event_ctx, const struct model_ops *model_ops,
2244 const char *address)
2246 struct dcesrv_socket_context *dcesrv_sock;
2249 const char *endpoint;
2252 endpoint = dcerpc_binding_get_string_option(e->ep_description, "endpoint");
2253 if (endpoint != NULL) {
2254 port = atoi(endpoint);
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, dce_ctx->lp_ctx,
2265 model_ops, &dcesrv_stream_ops,
2266 "ip", address, &port,
2267 lpcfg_socket_options(dce_ctx->lp_ctx),
2269 if (!NT_STATUS_IS_OK(status)) {
2270 DEBUG(0,("service_setup_stream_socket(address=%s,port=%u) failed - %s\n",
2271 address, port, nt_errstr(status)));
2275 snprintf(port_str, sizeof(port_str), "%u", port);
2277 status = dcerpc_binding_set_string_option(e->ep_description,
2278 "endpoint", port_str);
2279 if (!NT_STATUS_IS_OK(status)) {
2280 DEBUG(0,("dcerpc_binding_set_string_option(endpoint, %s) failed - %s\n",
2281 port_str, nt_errstr(status)));
2285 return NT_STATUS_OK;
2288 #include "lib/socket/netif.h" /* Included here to work around the fact that socket_wrapper redefines bind() */
2290 static NTSTATUS dcesrv_add_ep_tcp(struct dcesrv_context *dce_ctx,
2291 struct loadparm_context *lp_ctx,
2292 struct dcesrv_endpoint *e,
2293 struct tevent_context *event_ctx, const struct model_ops *model_ops)
2297 /* Add TCP/IP sockets */
2298 if (lpcfg_interfaces(lp_ctx) && lpcfg_bind_interfaces_only(lp_ctx)) {
2301 struct interface *ifaces;
2303 load_interface_list(dce_ctx, lp_ctx, &ifaces);
2305 num_interfaces = iface_list_count(ifaces);
2306 for(i = 0; i < num_interfaces; i++) {
2307 const char *address = iface_list_n_ip(ifaces, i);
2308 status = add_socket_rpc_tcp_iface(dce_ctx, e, event_ctx, model_ops, address);
2309 NT_STATUS_NOT_OK_RETURN(status);
2315 wcard = iface_list_wildcard(dce_ctx);
2316 NT_STATUS_HAVE_NO_MEMORY(wcard);
2317 for (i=0; wcard[i]; i++) {
2318 status = add_socket_rpc_tcp_iface(dce_ctx, e, event_ctx, model_ops, wcard[i]);
2319 if (NT_STATUS_IS_OK(status)) {
2324 if (num_binds == 0) {
2325 return NT_STATUS_INVALID_PARAMETER_MIX;
2329 return NT_STATUS_OK;
2332 NTSTATUS dcesrv_add_ep(struct dcesrv_context *dce_ctx,
2333 struct loadparm_context *lp_ctx,
2334 struct dcesrv_endpoint *e,
2335 struct tevent_context *event_ctx,
2336 const struct model_ops *model_ops)
2338 enum dcerpc_transport_t transport =
2339 dcerpc_binding_get_transport(e->ep_description);
2341 switch (transport) {
2342 case NCACN_UNIX_STREAM:
2343 return dcesrv_add_ep_unix(dce_ctx, lp_ctx, e, event_ctx, model_ops);
2346 return dcesrv_add_ep_ncalrpc(dce_ctx, lp_ctx, e, event_ctx, model_ops);
2349 return dcesrv_add_ep_tcp(dce_ctx, lp_ctx, e, event_ctx, model_ops);
2352 return dcesrv_add_ep_np(dce_ctx, lp_ctx, e, event_ctx, model_ops);
2355 return NT_STATUS_NOT_SUPPORTED;
2361 * retrieve credentials from a dce_call
2363 _PUBLIC_ struct cli_credentials *dcesrv_call_credentials(struct dcesrv_call_state *dce_call)
2365 return dce_call->conn->auth_state.session_info->credentials;
2369 * returns true if this is an authenticated call
2371 _PUBLIC_ bool dcesrv_call_authenticated(struct dcesrv_call_state *dce_call)
2373 enum security_user_level level;
2374 level = security_session_user_level(dce_call->conn->auth_state.session_info, NULL);
2375 return level >= SECURITY_USER;
2379 * retrieve account_name for a dce_call
2381 _PUBLIC_ const char *dcesrv_call_account_name(struct dcesrv_call_state *dce_call)
2383 return dce_call->context->conn->auth_state.session_info->info->account_name;