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->conn->auth_state.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 status = dcerpc_verify_ncacn_packet_header(&call->pkt,
929 call->pkt.u.auth3.auth_info.length,
930 0, /* required flags */
931 DCERPC_PFC_FLAG_FIRST |
932 DCERPC_PFC_FLAG_LAST |
933 DCERPC_PFC_FLAG_SUPPORT_HEADER_SIGN |
934 0x08 | /* this is not defined, but should be ignored */
935 DCERPC_PFC_FLAG_CONC_MPX |
936 DCERPC_PFC_FLAG_DID_NOT_EXECUTE |
937 DCERPC_PFC_FLAG_MAYBE |
938 DCERPC_PFC_FLAG_OBJECT_UUID);
939 if (!NT_STATUS_IS_OK(status)) {
940 return dcesrv_fault_disconnect(call, DCERPC_NCA_S_PROTO_ERROR);
943 /* handle the auth3 in the auth code */
944 if (!dcesrv_auth_auth3(call)) {
945 return dcesrv_fault(call, DCERPC_FAULT_OTHER);
950 /* we don't send a reply to a auth3 request, except by a
957 handle a bind request
959 static NTSTATUS dcesrv_alter_new_context(struct dcesrv_call_state *call, uint32_t context_id)
961 uint32_t if_version, transfer_syntax_version;
962 struct dcesrv_connection_context *context;
963 const struct dcesrv_interface *iface;
964 struct GUID uuid, *transfer_syntax_uuid;
967 if_version = call->pkt.u.alter.ctx_list[0].abstract_syntax.if_version;
968 uuid = call->pkt.u.alter.ctx_list[0].abstract_syntax.uuid;
970 transfer_syntax_version = call->pkt.u.alter.ctx_list[0].transfer_syntaxes[0].if_version;
971 transfer_syntax_uuid = &call->pkt.u.alter.ctx_list[0].transfer_syntaxes[0].uuid;
972 if (!GUID_equal(transfer_syntax_uuid, &ndr_transfer_syntax_ndr.uuid) ||
973 ndr_transfer_syntax_ndr.if_version != transfer_syntax_version) {
974 /* we only do NDR encoded dcerpc */
975 return NT_STATUS_RPC_PROTSEQ_NOT_SUPPORTED;
978 iface = find_interface_by_uuid(call->conn->endpoint, &uuid, if_version);
980 char *uuid_str = GUID_string(call, &uuid);
981 DEBUG(2,("Request for unknown dcerpc interface %s/%d\n", uuid_str, if_version));
982 talloc_free(uuid_str);
983 return NT_STATUS_RPC_PROTSEQ_NOT_SUPPORTED;
986 /* add this context to the list of available context_ids */
987 context = talloc_zero(call->conn, struct dcesrv_connection_context);
988 if (context == NULL) {
989 return NT_STATUS_NO_MEMORY;
991 context->conn = call->conn;
992 context->iface = iface;
993 context->context_id = context_id;
994 if (call->pkt.u.alter.assoc_group_id != 0) {
995 context->assoc_group = dcesrv_assoc_group_reference(context,
997 call->pkt.u.alter.assoc_group_id);
999 context->assoc_group = dcesrv_assoc_group_new(context, call->conn->dce_ctx);
1001 if (context->assoc_group == NULL) {
1002 talloc_free(context);
1003 call->context = NULL;
1004 return NT_STATUS_NO_MEMORY;
1006 context->private_data = NULL;
1007 DLIST_ADD(call->conn->contexts, context);
1008 call->context = context;
1009 talloc_set_destructor(context, dcesrv_connection_context_destructor);
1011 dcesrv_prepare_context_auth(call);
1013 status = iface->bind(call, iface, if_version);
1014 if (!NT_STATUS_IS_OK(status)) {
1015 /* we don't want to trigger the iface->unbind() hook */
1016 context->iface = NULL;
1017 talloc_free(context);
1018 call->context = NULL;
1022 return NT_STATUS_OK;
1025 /* setup and send an alter_resp */
1026 static NTSTATUS dcesrv_alter_resp(struct dcesrv_call_state *call,
1030 struct ncacn_packet pkt;
1031 uint32_t extra_flags = 0;
1032 struct data_blob_list_item *rep = NULL;
1035 dcesrv_init_hdr(&pkt, lpcfg_rpc_big_endian(call->conn->dce_ctx->lp_ctx));
1036 pkt.auth_length = 0;
1037 pkt.call_id = call->pkt.call_id;
1038 pkt.ptype = DCERPC_PKT_ALTER_RESP;
1040 if ((call->pkt.pfc_flags & DCERPC_PFC_FLAG_CONC_MPX) &&
1041 call->context->conn->state_flags &
1042 DCESRV_CALL_STATE_FLAG_MULTIPLEXED) {
1043 extra_flags |= DCERPC_PFC_FLAG_CONC_MPX;
1045 if (call->state_flags & DCESRV_CALL_STATE_FLAG_PROCESS_PENDING_CALL) {
1046 call->context->conn->state_flags |=
1047 DCESRV_CALL_STATE_FLAG_PROCESS_PENDING_CALL;
1050 pkt.pfc_flags = DCERPC_PFC_FLAG_FIRST | DCERPC_PFC_FLAG_LAST | extra_flags;
1051 pkt.u.alter_resp.max_xmit_frag = call->conn->max_xmit_frag;
1052 pkt.u.alter_resp.max_recv_frag = call->conn->max_recv_frag;
1054 pkt.u.alter_resp.assoc_group_id = call->context->assoc_group->id;
1056 pkt.u.alter_resp.assoc_group_id = 0;
1058 pkt.u.alter_resp.num_results = 1;
1059 pkt.u.alter_resp.ctx_list = talloc_zero(call, struct dcerpc_ack_ctx);
1060 if (!pkt.u.alter_resp.ctx_list) {
1061 return NT_STATUS_NO_MEMORY;
1063 pkt.u.alter_resp.ctx_list[0].result = result;
1064 pkt.u.alter_resp.ctx_list[0].reason.value = reason;
1065 pkt.u.alter_resp.ctx_list[0].syntax = ndr_transfer_syntax_ndr;
1066 pkt.u.alter_resp.auth_info = data_blob(NULL, 0);
1067 pkt.u.alter_resp.secondary_address = "";
1069 status = dcesrv_auth_alter_ack(call, &pkt);
1070 if (!NT_STATUS_IS_OK(status)) {
1071 if (NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)
1072 || NT_STATUS_EQUAL(status, NT_STATUS_LOGON_FAILURE)
1073 || NT_STATUS_EQUAL(status, NT_STATUS_NO_SUCH_USER)
1074 || NT_STATUS_EQUAL(status, NT_STATUS_WRONG_PASSWORD)) {
1075 return dcesrv_fault(call, DCERPC_FAULT_ACCESS_DENIED);
1077 return dcesrv_fault(call, 0);
1080 rep = talloc_zero(call, struct data_blob_list_item);
1082 return NT_STATUS_NO_MEMORY;
1085 status = ncacn_push_auth(&rep->blob, call, &pkt, call->conn->auth_state.auth_info);
1086 if (!NT_STATUS_IS_OK(status)) {
1090 dcerpc_set_frag_length(&rep->blob, rep->blob.length);
1092 DLIST_ADD_END(call->replies, rep);
1093 dcesrv_call_set_list(call, DCESRV_LIST_CALL_LIST);
1095 if (call->conn->call_list && call->conn->call_list->replies) {
1096 if (call->conn->transport.report_output_data) {
1097 call->conn->transport.report_output_data(call->conn);
1101 return NT_STATUS_OK;
1105 handle a alter context request
1107 static NTSTATUS dcesrv_alter(struct dcesrv_call_state *call)
1110 uint32_t context_id;
1112 if (!call->conn->allow_alter) {
1113 return dcesrv_fault_disconnect(call, DCERPC_NCA_S_PROTO_ERROR);
1116 status = dcerpc_verify_ncacn_packet_header(&call->pkt,
1118 call->pkt.u.alter.auth_info.length,
1119 0, /* required flags */
1120 DCERPC_PFC_FLAG_FIRST |
1121 DCERPC_PFC_FLAG_LAST |
1122 DCERPC_PFC_FLAG_SUPPORT_HEADER_SIGN |
1123 0x08 | /* this is not defined, but should be ignored */
1124 DCERPC_PFC_FLAG_CONC_MPX |
1125 DCERPC_PFC_FLAG_DID_NOT_EXECUTE |
1126 DCERPC_PFC_FLAG_MAYBE |
1127 DCERPC_PFC_FLAG_OBJECT_UUID);
1128 if (!NT_STATUS_IS_OK(status)) {
1129 return dcesrv_fault_disconnect(call, DCERPC_NCA_S_PROTO_ERROR);
1132 /* handle any authentication that is being requested */
1133 if (!dcesrv_auth_alter(call)) {
1134 /* TODO: work out the right reject code */
1135 return dcesrv_alter_resp(call,
1136 DCERPC_BIND_PROVIDER_REJECT,
1137 DCERPC_BIND_REASON_ASYNTAX);
1140 context_id = call->pkt.u.alter.ctx_list[0].context_id;
1142 /* see if they are asking for a new interface */
1143 call->context = dcesrv_find_context(call->conn, context_id);
1144 if (!call->context) {
1145 status = dcesrv_alter_new_context(call, context_id);
1146 if (!NT_STATUS_IS_OK(status)) {
1147 return dcesrv_alter_resp(call,
1148 DCERPC_BIND_PROVIDER_REJECT,
1149 DCERPC_BIND_REASON_ASYNTAX);
1153 if (call->pkt.u.alter.assoc_group_id != 0 &&
1154 lpcfg_parm_bool(call->conn->dce_ctx->lp_ctx, NULL, "dcesrv","assoc group checking", true) &&
1155 call->pkt.u.alter.assoc_group_id != call->context->assoc_group->id) {
1156 DEBUG(0,(__location__ ": Failed attempt to use new assoc_group in alter context (0x%08x 0x%08x)\n",
1157 call->context->assoc_group->id, call->pkt.u.alter.assoc_group_id));
1158 /* TODO: can they ask for a new association group? */
1159 return dcesrv_alter_resp(call,
1160 DCERPC_BIND_PROVIDER_REJECT,
1161 DCERPC_BIND_REASON_ASYNTAX);
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;
1392 call = talloc_zero(dce_conn, struct dcesrv_call_state);
1394 data_blob_free(&blob);
1396 return NT_STATUS_NO_MEMORY;
1398 call->conn = dce_conn;
1399 call->event_ctx = dce_conn->event_ctx;
1400 call->msg_ctx = dce_conn->msg_ctx;
1401 call->state_flags = call->conn->state_flags;
1402 call->time = timeval_current();
1403 call->list = DCESRV_LIST_NONE;
1405 talloc_steal(call, pkt);
1406 talloc_steal(call, blob.data);
1409 talloc_set_destructor(call, dcesrv_call_dequeue);
1411 if (call->conn->allow_bind) {
1413 * Only one bind is possible per connection
1415 call->conn->allow_bind = false;
1416 return dcesrv_bind(call);
1419 /* we have to check the signing here, before combining the
1421 if (call->pkt.ptype == DCERPC_PKT_REQUEST) {
1422 if (!call->conn->allow_request) {
1423 return dcesrv_fault_disconnect(call,
1424 DCERPC_NCA_S_PROTO_ERROR);
1427 status = dcerpc_verify_ncacn_packet_header(&call->pkt,
1429 call->pkt.u.request.stub_and_verifier.length,
1430 0, /* required_flags */
1431 DCERPC_PFC_FLAG_FIRST |
1432 DCERPC_PFC_FLAG_LAST |
1433 DCERPC_PFC_FLAG_PENDING_CANCEL |
1434 0x08 | /* this is not defined, but should be ignored */
1435 DCERPC_PFC_FLAG_CONC_MPX |
1436 DCERPC_PFC_FLAG_DID_NOT_EXECUTE |
1437 DCERPC_PFC_FLAG_MAYBE |
1438 DCERPC_PFC_FLAG_OBJECT_UUID);
1439 if (!NT_STATUS_IS_OK(status)) {
1440 return dcesrv_fault_disconnect(call,
1441 DCERPC_NCA_S_PROTO_ERROR);
1444 if (!dcesrv_auth_request(call, &blob)) {
1445 return dcesrv_fault(call, DCERPC_FAULT_ACCESS_DENIED);
1449 /* see if this is a continued packet */
1450 if (call->pkt.ptype == DCERPC_PKT_REQUEST &&
1451 !(call->pkt.pfc_flags & DCERPC_PFC_FLAG_FIRST)) {
1452 struct dcesrv_call_state *call2 = call;
1453 uint32_t alloc_size;
1455 /* we only allow fragmented requests, no other packet types */
1456 if (call->pkt.ptype != DCERPC_PKT_REQUEST) {
1457 return dcesrv_fault(call2, DCERPC_FAULT_OTHER);
1460 /* this is a continuation of an existing call - find the call
1461 then tack it on the end */
1462 call = dcesrv_find_fragmented_call(dce_conn, call2->pkt.call_id);
1464 return dcesrv_fault(call2, DCERPC_FAULT_OTHER);
1467 if (call->pkt.ptype != call2->pkt.ptype) {
1468 /* trying to play silly buggers are we? */
1469 return dcesrv_fault(call2, DCERPC_NCA_S_PROTO_ERROR);
1471 if (memcmp(call->pkt.drep, call2->pkt.drep, sizeof(pkt->drep)) != 0) {
1472 return dcesrv_fault(call2, DCERPC_NCA_S_PROTO_ERROR);
1474 if (call->pkt.call_id != call2->pkt.call_id) {
1475 return dcesrv_fault(call2, DCERPC_NCA_S_PROTO_ERROR);
1477 if (call->pkt.u.request.context_id != call2->pkt.u.request.context_id) {
1478 return dcesrv_fault(call2, DCERPC_NCA_S_PROTO_ERROR);
1480 if (call->pkt.u.request.opnum != call2->pkt.u.request.opnum) {
1481 return dcesrv_fault(call2, DCERPC_NCA_S_PROTO_ERROR);
1484 alloc_size = call->pkt.u.request.stub_and_verifier.length +
1485 call2->pkt.u.request.stub_and_verifier.length;
1486 if (call->pkt.u.request.alloc_hint > alloc_size) {
1487 alloc_size = call->pkt.u.request.alloc_hint;
1490 call->pkt.u.request.stub_and_verifier.data =
1491 talloc_realloc(call,
1492 call->pkt.u.request.stub_and_verifier.data,
1493 uint8_t, alloc_size);
1494 if (!call->pkt.u.request.stub_and_verifier.data) {
1495 return dcesrv_fault(call2, DCERPC_FAULT_OTHER);
1497 memcpy(call->pkt.u.request.stub_and_verifier.data +
1498 call->pkt.u.request.stub_and_verifier.length,
1499 call2->pkt.u.request.stub_and_verifier.data,
1500 call2->pkt.u.request.stub_and_verifier.length);
1501 call->pkt.u.request.stub_and_verifier.length +=
1502 call2->pkt.u.request.stub_and_verifier.length;
1504 call->pkt.pfc_flags |= (call2->pkt.pfc_flags & DCERPC_PFC_FLAG_LAST);
1509 /* this may not be the last pdu in the chain - if its isn't then
1510 just put it on the incoming_fragmented_call_list and wait for the rest */
1511 if (call->pkt.ptype == DCERPC_PKT_REQUEST &&
1512 !(call->pkt.pfc_flags & DCERPC_PFC_FLAG_LAST)) {
1513 dcesrv_call_set_list(call, DCESRV_LIST_FRAGMENTED_CALL_LIST);
1514 return NT_STATUS_OK;
1517 /* This removes any fragments we may have had stashed away */
1518 dcesrv_call_set_list(call, DCESRV_LIST_NONE);
1520 switch (call->pkt.ptype) {
1521 case DCERPC_PKT_BIND:
1522 status = dcesrv_bind_nak(call,
1523 DCERPC_BIND_NAK_REASON_NOT_SPECIFIED);
1525 case DCERPC_PKT_AUTH3:
1526 status = dcesrv_auth3(call);
1528 case DCERPC_PKT_ALTER:
1529 status = dcesrv_alter(call);
1531 case DCERPC_PKT_REQUEST:
1532 status = dcesrv_request(call);
1535 status = dcesrv_fault_disconnect(call, DCERPC_NCA_S_PROTO_ERROR);
1539 /* if we are going to be sending a reply then add
1540 it to the list of pending calls. We add it to the end to keep the call
1541 list in the order we will answer */
1542 if (!NT_STATUS_IS_OK(status)) {
1549 _PUBLIC_ NTSTATUS dcesrv_init_context(TALLOC_CTX *mem_ctx,
1550 struct loadparm_context *lp_ctx,
1551 const char **endpoint_servers, struct dcesrv_context **_dce_ctx)
1554 struct dcesrv_context *dce_ctx;
1557 if (!endpoint_servers) {
1558 DEBUG(0,("dcesrv_init_context: no endpoint servers configured\n"));
1559 return NT_STATUS_INTERNAL_ERROR;
1562 dce_ctx = talloc_zero(mem_ctx, struct dcesrv_context);
1563 NT_STATUS_HAVE_NO_MEMORY(dce_ctx);
1565 if (uid_wrapper_enabled()) {
1566 setenv("UID_WRAPPER_MYUID", "1", 1);
1568 dce_ctx->initial_euid = geteuid();
1569 if (uid_wrapper_enabled()) {
1570 unsetenv("UID_WRAPPER_MYUID");
1573 dce_ctx->endpoint_list = NULL;
1574 dce_ctx->lp_ctx = lp_ctx;
1575 dce_ctx->assoc_groups_idr = idr_init(dce_ctx);
1576 NT_STATUS_HAVE_NO_MEMORY(dce_ctx->assoc_groups_idr);
1577 dce_ctx->broken_connections = NULL;
1579 for (i=0;endpoint_servers[i];i++) {
1580 const struct dcesrv_endpoint_server *ep_server;
1582 ep_server = dcesrv_ep_server_byname(endpoint_servers[i]);
1584 DEBUG(0,("dcesrv_init_context: failed to find endpoint server = '%s'\n", endpoint_servers[i]));
1585 return NT_STATUS_INTERNAL_ERROR;
1588 status = ep_server->init_server(dce_ctx, ep_server);
1589 if (!NT_STATUS_IS_OK(status)) {
1590 DEBUG(0,("dcesrv_init_context: failed to init endpoint server = '%s': %s\n", endpoint_servers[i],
1591 nt_errstr(status)));
1596 *_dce_ctx = dce_ctx;
1597 return NT_STATUS_OK;
1600 /* the list of currently registered DCERPC endpoint servers.
1602 static struct ep_server {
1603 struct dcesrv_endpoint_server *ep_server;
1604 } *ep_servers = NULL;
1605 static int num_ep_servers;
1608 register a DCERPC endpoint server.
1610 The 'name' can be later used by other backends to find the operations
1611 structure for this backend.
1613 The 'type' is used to specify whether this is for a disk, printer or IPC$ share
1615 _PUBLIC_ NTSTATUS dcerpc_register_ep_server(const void *_ep_server)
1617 const struct dcesrv_endpoint_server *ep_server = _ep_server;
1619 if (dcesrv_ep_server_byname(ep_server->name) != NULL) {
1620 /* its already registered! */
1621 DEBUG(0,("DCERPC endpoint server '%s' already registered\n",
1623 return NT_STATUS_OBJECT_NAME_COLLISION;
1626 ep_servers = realloc_p(ep_servers, struct ep_server, num_ep_servers+1);
1628 smb_panic("out of memory in dcerpc_register");
1631 ep_servers[num_ep_servers].ep_server = smb_xmemdup(ep_server, sizeof(*ep_server));
1632 ep_servers[num_ep_servers].ep_server->name = smb_xstrdup(ep_server->name);
1636 DEBUG(3,("DCERPC endpoint server '%s' registered\n",
1639 return NT_STATUS_OK;
1643 return the operations structure for a named backend of the specified type
1645 const struct dcesrv_endpoint_server *dcesrv_ep_server_byname(const char *name)
1649 for (i=0;i<num_ep_servers;i++) {
1650 if (strcmp(ep_servers[i].ep_server->name, name) == 0) {
1651 return ep_servers[i].ep_server;
1658 void dcerpc_server_init(struct loadparm_context *lp_ctx)
1660 static bool initialized;
1661 #define _MODULE_PROTO(init) extern NTSTATUS init(void);
1662 STATIC_dcerpc_server_MODULES_PROTO;
1663 init_module_fn static_init[] = { STATIC_dcerpc_server_MODULES };
1664 init_module_fn *shared_init;
1671 shared_init = load_samba_modules(NULL, "dcerpc_server");
1673 run_init_functions(static_init);
1674 run_init_functions(shared_init);
1676 talloc_free(shared_init);
1680 return the DCERPC module version, and the size of some critical types
1681 This can be used by endpoint server modules to either detect compilation errors, or provide
1682 multiple implementations for different smbd compilation options in one module
1684 const struct dcesrv_critical_sizes *dcerpc_module_version(void)
1686 static const struct dcesrv_critical_sizes critical_sizes = {
1687 DCERPC_MODULE_VERSION,
1688 sizeof(struct dcesrv_context),
1689 sizeof(struct dcesrv_endpoint),
1690 sizeof(struct dcesrv_endpoint_server),
1691 sizeof(struct dcesrv_interface),
1692 sizeof(struct dcesrv_if_list),
1693 sizeof(struct dcesrv_connection),
1694 sizeof(struct dcesrv_call_state),
1695 sizeof(struct dcesrv_auth),
1696 sizeof(struct dcesrv_handle)
1699 return &critical_sizes;
1702 static void dcesrv_terminate_connection(struct dcesrv_connection *dce_conn, const char *reason)
1704 struct dcesrv_context *dce_ctx = dce_conn->dce_ctx;
1705 struct stream_connection *srv_conn;
1706 srv_conn = talloc_get_type(dce_conn->transport.private_data,
1707 struct stream_connection);
1709 dce_conn->allow_bind = false;
1710 dce_conn->allow_auth3 = false;
1711 dce_conn->allow_alter = false;
1712 dce_conn->allow_request = false;
1714 if (dce_conn->pending_call_list == NULL) {
1715 char *full_reason = talloc_asprintf(dce_conn, "dcesrv: %s", reason);
1717 DLIST_REMOVE(dce_ctx->broken_connections, dce_conn);
1718 stream_terminate_connection(srv_conn, full_reason ? full_reason : reason);
1722 if (dce_conn->terminate != NULL) {
1726 DEBUG(3,("dcesrv: terminating connection due to '%s' defered due to pending calls\n",
1728 dce_conn->terminate = talloc_strdup(dce_conn, reason);
1729 if (dce_conn->terminate == NULL) {
1730 dce_conn->terminate = "dcesrv: defered terminating connection - no memory";
1732 DLIST_ADD_END(dce_ctx->broken_connections, dce_conn);
1735 static void dcesrv_cleanup_broken_connections(struct dcesrv_context *dce_ctx)
1737 struct dcesrv_connection *cur, *next;
1739 next = dce_ctx->broken_connections;
1740 while (next != NULL) {
1744 if (cur->state_flags & DCESRV_CALL_STATE_FLAG_PROCESS_PENDING_CALL) {
1745 struct dcesrv_connection_context *context_cur, *context_next;
1747 context_next = cur->contexts;
1748 while (context_next != NULL) {
1749 context_cur = context_next;
1750 context_next = context_cur->next;
1752 dcesrv_connection_context_destructor(context_cur);
1756 dcesrv_terminate_connection(cur, cur->terminate);
1760 /* We need this include to be able to compile on some plateforms
1761 * (ie. freebsd 7.2) as it seems that <sys/uio.h> is not included
1763 * It has to be that deep because otherwise we have a conflict on
1764 * const struct dcesrv_interface declaration.
1765 * This is mostly due to socket_wrapper defining #define bind swrap_bind
1766 * which conflict with the bind used before.
1768 #include "system/network.h"
1770 struct dcesrv_sock_reply_state {
1771 struct dcesrv_connection *dce_conn;
1772 struct dcesrv_call_state *call;
1776 static void dcesrv_sock_reply_done(struct tevent_req *subreq);
1777 static void dcesrv_call_terminate_step1(struct tevent_req *subreq);
1779 static void dcesrv_sock_report_output_data(struct dcesrv_connection *dce_conn)
1781 struct dcesrv_call_state *call;
1783 call = dce_conn->call_list;
1784 if (!call || !call->replies) {
1788 while (call->replies) {
1789 struct data_blob_list_item *rep = call->replies;
1790 struct dcesrv_sock_reply_state *substate;
1791 struct tevent_req *subreq;
1793 substate = talloc_zero(call, struct dcesrv_sock_reply_state);
1795 dcesrv_terminate_connection(dce_conn, "no memory");
1799 substate->dce_conn = dce_conn;
1800 substate->call = NULL;
1802 DLIST_REMOVE(call->replies, rep);
1804 if (call->replies == NULL && call->terminate_reason == NULL) {
1805 substate->call = call;
1808 substate->iov.iov_base = (void *) rep->blob.data;
1809 substate->iov.iov_len = rep->blob.length;
1811 subreq = tstream_writev_queue_send(substate,
1812 dce_conn->event_ctx,
1814 dce_conn->send_queue,
1817 dcesrv_terminate_connection(dce_conn, "no memory");
1820 tevent_req_set_callback(subreq, dcesrv_sock_reply_done,
1824 if (call->terminate_reason != NULL) {
1825 struct tevent_req *subreq;
1827 subreq = tevent_queue_wait_send(call,
1828 dce_conn->event_ctx,
1829 dce_conn->send_queue);
1831 dcesrv_terminate_connection(dce_conn, __location__);
1834 tevent_req_set_callback(subreq, dcesrv_call_terminate_step1,
1838 DLIST_REMOVE(call->conn->call_list, call);
1839 call->list = DCESRV_LIST_NONE;
1842 static void dcesrv_sock_reply_done(struct tevent_req *subreq)
1844 struct dcesrv_sock_reply_state *substate = tevent_req_callback_data(subreq,
1845 struct dcesrv_sock_reply_state);
1849 struct dcesrv_call_state *call = substate->call;
1851 ret = tstream_writev_queue_recv(subreq, &sys_errno);
1852 TALLOC_FREE(subreq);
1854 status = map_nt_error_from_unix_common(sys_errno);
1855 dcesrv_terminate_connection(substate->dce_conn, nt_errstr(status));
1859 talloc_free(substate);
1865 static void dcesrv_call_terminate_step2(struct tevent_req *subreq);
1867 static void dcesrv_call_terminate_step1(struct tevent_req *subreq)
1869 struct dcesrv_call_state *call = tevent_req_callback_data(subreq,
1870 struct dcesrv_call_state);
1874 /* make sure we stop send queue before removing subreq */
1875 tevent_queue_stop(call->conn->send_queue);
1877 ok = tevent_queue_wait_recv(subreq);
1878 TALLOC_FREE(subreq);
1880 dcesrv_terminate_connection(call->conn, __location__);
1884 /* disconnect after 200 usecs */
1885 tv = timeval_current_ofs_usec(200);
1886 subreq = tevent_wakeup_send(call, call->conn->event_ctx, tv);
1887 if (subreq == NULL) {
1888 dcesrv_terminate_connection(call->conn, __location__);
1891 tevent_req_set_callback(subreq, dcesrv_call_terminate_step2,
1895 static void dcesrv_call_terminate_step2(struct tevent_req *subreq)
1897 struct dcesrv_call_state *call = tevent_req_callback_data(subreq,
1898 struct dcesrv_call_state);
1901 ok = tevent_wakeup_recv(subreq);
1902 TALLOC_FREE(subreq);
1904 dcesrv_terminate_connection(call->conn, __location__);
1908 dcesrv_terminate_connection(call->conn, call->terminate_reason);
1911 struct dcesrv_socket_context {
1912 const struct dcesrv_endpoint *endpoint;
1913 struct dcesrv_context *dcesrv_ctx;
1917 static void dcesrv_read_fragment_done(struct tevent_req *subreq);
1919 static void dcesrv_sock_accept(struct stream_connection *srv_conn)
1922 struct dcesrv_socket_context *dcesrv_sock =
1923 talloc_get_type(srv_conn->private_data, struct dcesrv_socket_context);
1924 enum dcerpc_transport_t transport =
1925 dcerpc_binding_get_transport(dcesrv_sock->endpoint->ep_description);
1926 struct dcesrv_connection *dcesrv_conn = NULL;
1928 struct tevent_req *subreq;
1929 struct loadparm_context *lp_ctx = dcesrv_sock->dcesrv_ctx->lp_ctx;
1931 dcesrv_cleanup_broken_connections(dcesrv_sock->dcesrv_ctx);
1933 if (!srv_conn->session_info) {
1934 status = auth_anonymous_session_info(srv_conn,
1936 &srv_conn->session_info);
1937 if (!NT_STATUS_IS_OK(status)) {
1938 DEBUG(0,("dcesrv_sock_accept: auth_anonymous_session_info failed: %s\n",
1939 nt_errstr(status)));
1940 stream_terminate_connection(srv_conn, nt_errstr(status));
1945 status = dcesrv_endpoint_connect(dcesrv_sock->dcesrv_ctx,
1947 dcesrv_sock->endpoint,
1948 srv_conn->session_info,
1949 srv_conn->event.ctx,
1951 srv_conn->server_id,
1952 DCESRV_CALL_STATE_FLAG_MAY_ASYNC,
1954 if (!NT_STATUS_IS_OK(status)) {
1955 DEBUG(0,("dcesrv_sock_accept: dcesrv_endpoint_connect failed: %s\n",
1956 nt_errstr(status)));
1957 stream_terminate_connection(srv_conn, nt_errstr(status));
1961 dcesrv_conn->transport.private_data = srv_conn;
1962 dcesrv_conn->transport.report_output_data = dcesrv_sock_report_output_data;
1964 TALLOC_FREE(srv_conn->event.fde);
1966 dcesrv_conn->send_queue = tevent_queue_create(dcesrv_conn, "dcesrv send queue");
1967 if (!dcesrv_conn->send_queue) {
1968 status = NT_STATUS_NO_MEMORY;
1969 DEBUG(0,("dcesrv_sock_accept: tevent_queue_create(%s)\n",
1970 nt_errstr(status)));
1971 stream_terminate_connection(srv_conn, nt_errstr(status));
1975 if (transport == NCACN_NP) {
1976 dcesrv_conn->auth_state.session_key = dcesrv_inherited_session_key;
1977 dcesrv_conn->stream = talloc_move(dcesrv_conn,
1978 &srv_conn->tstream);
1980 ret = tstream_bsd_existing_socket(dcesrv_conn,
1981 socket_get_fd(srv_conn->socket),
1982 &dcesrv_conn->stream);
1984 status = map_nt_error_from_unix_common(errno);
1985 DEBUG(0, ("dcesrv_sock_accept: "
1986 "failed to setup tstream: %s\n",
1987 nt_errstr(status)));
1988 stream_terminate_connection(srv_conn, nt_errstr(status));
1991 socket_set_flags(srv_conn->socket, SOCKET_FLAG_NOCLOSE);
1994 dcesrv_conn->local_address = srv_conn->local_address;
1995 dcesrv_conn->remote_address = srv_conn->remote_address;
1997 if (transport == NCALRPC) {
2001 ret = getpeereid(socket_get_fd(srv_conn->socket), &uid, &gid);
2003 status = map_nt_error_from_unix_common(errno);
2004 DEBUG(0, ("dcesrv_sock_accept: "
2005 "getpeereid() failed for NCALRPC: %s\n",
2006 nt_errstr(status)));
2007 stream_terminate_connection(srv_conn, nt_errstr(status));
2010 if (uid == dcesrv_conn->dce_ctx->initial_euid) {
2011 struct tsocket_address *r = NULL;
2013 ret = tsocket_address_unix_from_path(dcesrv_conn,
2014 "/root/ncalrpc_as_system",
2017 status = map_nt_error_from_unix_common(errno);
2018 DEBUG(0, ("dcesrv_sock_accept: "
2019 "tsocket_address_unix_from_path() failed for NCALRPC: %s\n",
2020 nt_errstr(status)));
2021 stream_terminate_connection(srv_conn, nt_errstr(status));
2024 dcesrv_conn->remote_address = r;
2028 srv_conn->private_data = dcesrv_conn;
2030 irpc_add_name(srv_conn->msg_ctx, "rpc_server");
2032 subreq = dcerpc_read_ncacn_packet_send(dcesrv_conn,
2033 dcesrv_conn->event_ctx,
2034 dcesrv_conn->stream);
2036 status = NT_STATUS_NO_MEMORY;
2037 DEBUG(0,("dcesrv_sock_accept: dcerpc_read_fragment_buffer_send(%s)\n",
2038 nt_errstr(status)));
2039 stream_terminate_connection(srv_conn, nt_errstr(status));
2042 tevent_req_set_callback(subreq, dcesrv_read_fragment_done, dcesrv_conn);
2047 static void dcesrv_read_fragment_done(struct tevent_req *subreq)
2049 struct dcesrv_connection *dce_conn = tevent_req_callback_data(subreq,
2050 struct dcesrv_connection);
2051 struct dcesrv_context *dce_ctx = dce_conn->dce_ctx;
2052 struct ncacn_packet *pkt;
2056 if (dce_conn->terminate) {
2058 * if the current connection is broken
2059 * we need to clean it up before any other connection
2061 dcesrv_terminate_connection(dce_conn, dce_conn->terminate);
2062 dcesrv_cleanup_broken_connections(dce_ctx);
2066 dcesrv_cleanup_broken_connections(dce_ctx);
2068 status = dcerpc_read_ncacn_packet_recv(subreq, dce_conn,
2070 TALLOC_FREE(subreq);
2071 if (!NT_STATUS_IS_OK(status)) {
2072 dcesrv_terminate_connection(dce_conn, nt_errstr(status));
2076 status = dcesrv_process_ncacn_packet(dce_conn, pkt, buffer);
2077 if (!NT_STATUS_IS_OK(status)) {
2078 dcesrv_terminate_connection(dce_conn, nt_errstr(status));
2082 subreq = dcerpc_read_ncacn_packet_send(dce_conn,
2083 dce_conn->event_ctx,
2086 status = NT_STATUS_NO_MEMORY;
2087 dcesrv_terminate_connection(dce_conn, nt_errstr(status));
2090 tevent_req_set_callback(subreq, dcesrv_read_fragment_done, dce_conn);
2093 static void dcesrv_sock_recv(struct stream_connection *conn, uint16_t flags)
2095 struct dcesrv_connection *dce_conn = talloc_get_type(conn->private_data,
2096 struct dcesrv_connection);
2097 dcesrv_terminate_connection(dce_conn, "dcesrv_sock_recv triggered");
2100 static void dcesrv_sock_send(struct stream_connection *conn, uint16_t flags)
2102 struct dcesrv_connection *dce_conn = talloc_get_type(conn->private_data,
2103 struct dcesrv_connection);
2104 dcesrv_terminate_connection(dce_conn, "dcesrv_sock_send triggered");
2108 static const struct stream_server_ops dcesrv_stream_ops = {
2110 .accept_connection = dcesrv_sock_accept,
2111 .recv_handler = dcesrv_sock_recv,
2112 .send_handler = dcesrv_sock_send,
2115 static NTSTATUS dcesrv_add_ep_unix(struct dcesrv_context *dce_ctx,
2116 struct loadparm_context *lp_ctx,
2117 struct dcesrv_endpoint *e,
2118 struct tevent_context *event_ctx, const struct model_ops *model_ops)
2120 struct dcesrv_socket_context *dcesrv_sock;
2123 const char *endpoint;
2125 dcesrv_sock = talloc_zero(event_ctx, struct dcesrv_socket_context);
2126 NT_STATUS_HAVE_NO_MEMORY(dcesrv_sock);
2128 /* remember the endpoint of this socket */
2129 dcesrv_sock->endpoint = e;
2130 dcesrv_sock->dcesrv_ctx = talloc_reference(dcesrv_sock, dce_ctx);
2132 endpoint = dcerpc_binding_get_string_option(e->ep_description, "endpoint");
2134 status = stream_setup_socket(dcesrv_sock, event_ctx, lp_ctx,
2135 model_ops, &dcesrv_stream_ops,
2136 "unix", endpoint, &port,
2137 lpcfg_socket_options(lp_ctx),
2139 if (!NT_STATUS_IS_OK(status)) {
2140 DEBUG(0,("service_setup_stream_socket(path=%s) failed - %s\n",
2141 endpoint, nt_errstr(status)));
2147 static NTSTATUS dcesrv_add_ep_ncalrpc(struct dcesrv_context *dce_ctx,
2148 struct loadparm_context *lp_ctx,
2149 struct dcesrv_endpoint *e,
2150 struct tevent_context *event_ctx, const struct model_ops *model_ops)
2152 struct dcesrv_socket_context *dcesrv_sock;
2156 const char *endpoint;
2158 endpoint = dcerpc_binding_get_string_option(e->ep_description, "endpoint");
2160 if (endpoint == NULL) {
2162 * No identifier specified: use DEFAULT.
2164 * TODO: DO NOT hardcode this value anywhere else. Rather, specify
2165 * no endpoint and let the epmapper worry about it.
2167 endpoint = "DEFAULT";
2168 status = dcerpc_binding_set_string_option(e->ep_description,
2171 if (!NT_STATUS_IS_OK(status)) {
2172 DEBUG(0,("dcerpc_binding_set_string_option() failed - %s\n",
2173 nt_errstr(status)));
2178 full_path = talloc_asprintf(dce_ctx, "%s/%s", lpcfg_ncalrpc_dir(lp_ctx),
2181 dcesrv_sock = talloc_zero(event_ctx, struct dcesrv_socket_context);
2182 NT_STATUS_HAVE_NO_MEMORY(dcesrv_sock);
2184 /* remember the endpoint of this socket */
2185 dcesrv_sock->endpoint = e;
2186 dcesrv_sock->dcesrv_ctx = talloc_reference(dcesrv_sock, dce_ctx);
2188 status = stream_setup_socket(dcesrv_sock, event_ctx, lp_ctx,
2189 model_ops, &dcesrv_stream_ops,
2190 "unix", full_path, &port,
2191 lpcfg_socket_options(lp_ctx),
2193 if (!NT_STATUS_IS_OK(status)) {
2194 DEBUG(0,("service_setup_stream_socket(identifier=%s,path=%s) failed - %s\n",
2195 endpoint, full_path, nt_errstr(status)));
2200 static NTSTATUS dcesrv_add_ep_np(struct dcesrv_context *dce_ctx,
2201 struct loadparm_context *lp_ctx,
2202 struct dcesrv_endpoint *e,
2203 struct tevent_context *event_ctx, const struct model_ops *model_ops)
2205 struct dcesrv_socket_context *dcesrv_sock;
2207 const char *endpoint;
2209 endpoint = dcerpc_binding_get_string_option(e->ep_description, "endpoint");
2210 if (endpoint == NULL) {
2211 DEBUG(0, ("Endpoint mandatory for named pipes\n"));
2212 return NT_STATUS_INVALID_PARAMETER;
2215 dcesrv_sock = talloc_zero(event_ctx, struct dcesrv_socket_context);
2216 NT_STATUS_HAVE_NO_MEMORY(dcesrv_sock);
2218 /* remember the endpoint of this socket */
2219 dcesrv_sock->endpoint = e;
2220 dcesrv_sock->dcesrv_ctx = talloc_reference(dcesrv_sock, dce_ctx);
2222 status = tstream_setup_named_pipe(dce_ctx, event_ctx, lp_ctx,
2223 model_ops, &dcesrv_stream_ops,
2226 if (!NT_STATUS_IS_OK(status)) {
2227 DEBUG(0,("stream_setup_named_pipe(pipe=%s) failed - %s\n",
2228 endpoint, nt_errstr(status)));
2232 return NT_STATUS_OK;
2236 add a socket address to the list of events, one event per dcerpc endpoint
2238 static NTSTATUS add_socket_rpc_tcp_iface(struct dcesrv_context *dce_ctx, struct dcesrv_endpoint *e,
2239 struct tevent_context *event_ctx, const struct model_ops *model_ops,
2240 const char *address)
2242 struct dcesrv_socket_context *dcesrv_sock;
2245 const char *endpoint;
2248 endpoint = dcerpc_binding_get_string_option(e->ep_description, "endpoint");
2249 if (endpoint != NULL) {
2250 port = atoi(endpoint);
2253 dcesrv_sock = talloc_zero(event_ctx, struct dcesrv_socket_context);
2254 NT_STATUS_HAVE_NO_MEMORY(dcesrv_sock);
2256 /* remember the endpoint of this socket */
2257 dcesrv_sock->endpoint = e;
2258 dcesrv_sock->dcesrv_ctx = talloc_reference(dcesrv_sock, dce_ctx);
2260 status = stream_setup_socket(dcesrv_sock, event_ctx, dce_ctx->lp_ctx,
2261 model_ops, &dcesrv_stream_ops,
2262 "ip", address, &port,
2263 lpcfg_socket_options(dce_ctx->lp_ctx),
2265 if (!NT_STATUS_IS_OK(status)) {
2266 DEBUG(0,("service_setup_stream_socket(address=%s,port=%u) failed - %s\n",
2267 address, port, nt_errstr(status)));
2271 snprintf(port_str, sizeof(port_str), "%u", port);
2273 status = dcerpc_binding_set_string_option(e->ep_description,
2274 "endpoint", port_str);
2275 if (!NT_STATUS_IS_OK(status)) {
2276 DEBUG(0,("dcerpc_binding_set_string_option(endpoint, %s) failed - %s\n",
2277 port_str, nt_errstr(status)));
2281 return NT_STATUS_OK;
2284 #include "lib/socket/netif.h" /* Included here to work around the fact that socket_wrapper redefines bind() */
2286 static NTSTATUS dcesrv_add_ep_tcp(struct dcesrv_context *dce_ctx,
2287 struct loadparm_context *lp_ctx,
2288 struct dcesrv_endpoint *e,
2289 struct tevent_context *event_ctx, const struct model_ops *model_ops)
2293 /* Add TCP/IP sockets */
2294 if (lpcfg_interfaces(lp_ctx) && lpcfg_bind_interfaces_only(lp_ctx)) {
2297 struct interface *ifaces;
2299 load_interface_list(dce_ctx, lp_ctx, &ifaces);
2301 num_interfaces = iface_list_count(ifaces);
2302 for(i = 0; i < num_interfaces; i++) {
2303 const char *address = iface_list_n_ip(ifaces, i);
2304 status = add_socket_rpc_tcp_iface(dce_ctx, e, event_ctx, model_ops, address);
2305 NT_STATUS_NOT_OK_RETURN(status);
2311 wcard = iface_list_wildcard(dce_ctx);
2312 NT_STATUS_HAVE_NO_MEMORY(wcard);
2313 for (i=0; wcard[i]; i++) {
2314 status = add_socket_rpc_tcp_iface(dce_ctx, e, event_ctx, model_ops, wcard[i]);
2315 if (NT_STATUS_IS_OK(status)) {
2320 if (num_binds == 0) {
2321 return NT_STATUS_INVALID_PARAMETER_MIX;
2325 return NT_STATUS_OK;
2328 NTSTATUS dcesrv_add_ep(struct dcesrv_context *dce_ctx,
2329 struct loadparm_context *lp_ctx,
2330 struct dcesrv_endpoint *e,
2331 struct tevent_context *event_ctx,
2332 const struct model_ops *model_ops)
2334 enum dcerpc_transport_t transport =
2335 dcerpc_binding_get_transport(e->ep_description);
2337 switch (transport) {
2338 case NCACN_UNIX_STREAM:
2339 return dcesrv_add_ep_unix(dce_ctx, lp_ctx, e, event_ctx, model_ops);
2342 return dcesrv_add_ep_ncalrpc(dce_ctx, lp_ctx, e, event_ctx, model_ops);
2345 return dcesrv_add_ep_tcp(dce_ctx, lp_ctx, e, event_ctx, model_ops);
2348 return dcesrv_add_ep_np(dce_ctx, lp_ctx, e, event_ctx, model_ops);
2351 return NT_STATUS_NOT_SUPPORTED;
2357 * retrieve credentials from a dce_call
2359 _PUBLIC_ struct cli_credentials *dcesrv_call_credentials(struct dcesrv_call_state *dce_call)
2361 return dce_call->conn->auth_state.session_info->credentials;
2365 * returns true if this is an authenticated call
2367 _PUBLIC_ bool dcesrv_call_authenticated(struct dcesrv_call_state *dce_call)
2369 enum security_user_level level;
2370 level = security_session_user_level(dce_call->conn->auth_state.session_info, NULL);
2371 return level >= SECURITY_USER;
2375 * retrieve account_name for a dce_call
2377 _PUBLIC_ const char *dcesrv_call_account_name(struct dcesrv_call_state *dce_call)
2379 return dce_call->context->conn->auth_state.session_info->info->account_name;