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->max_recv_frag = 5840;
412 p->max_xmit_frag = 5840;
419 move a call from an existing linked list to the specified list. This
420 prevents bugs where we forget to remove the call from a previous
423 static void dcesrv_call_set_list(struct dcesrv_call_state *call,
424 enum dcesrv_call_list list)
426 switch (call->list) {
427 case DCESRV_LIST_NONE:
429 case DCESRV_LIST_CALL_LIST:
430 DLIST_REMOVE(call->conn->call_list, call);
432 case DCESRV_LIST_FRAGMENTED_CALL_LIST:
433 DLIST_REMOVE(call->conn->incoming_fragmented_call_list, call);
435 case DCESRV_LIST_PENDING_CALL_LIST:
436 DLIST_REMOVE(call->conn->pending_call_list, call);
441 case DCESRV_LIST_NONE:
443 case DCESRV_LIST_CALL_LIST:
444 DLIST_ADD_END(call->conn->call_list, call);
446 case DCESRV_LIST_FRAGMENTED_CALL_LIST:
447 DLIST_ADD_END(call->conn->incoming_fragmented_call_list, call);
449 case DCESRV_LIST_PENDING_CALL_LIST:
450 DLIST_ADD_END(call->conn->pending_call_list, call);
455 static void dcesrv_call_disconnect_after(struct dcesrv_call_state *call,
458 if (call->conn->terminate != NULL) {
462 call->terminate_reason = talloc_strdup(call, reason);
463 if (call->terminate_reason == NULL) {
464 call->terminate_reason = __location__;
469 return a dcerpc bind_nak
471 static NTSTATUS dcesrv_bind_nak(struct dcesrv_call_state *call, uint32_t reason)
473 struct ncacn_packet pkt;
474 struct dcerpc_bind_nak_version version;
475 struct data_blob_list_item *rep;
477 static const uint8_t _pad[3] = { 0, };
480 * We add the call to the pending_call_list
481 * in order to defer the termination.
483 dcesrv_call_disconnect_after(call, "dcesrv_bind_nak");
485 /* setup a bind_nak */
486 dcesrv_init_hdr(&pkt, lpcfg_rpc_big_endian(call->conn->dce_ctx->lp_ctx));
488 pkt.call_id = call->pkt.call_id;
489 pkt.ptype = DCERPC_PKT_BIND_NAK;
490 pkt.pfc_flags = DCERPC_PFC_FLAG_FIRST | DCERPC_PFC_FLAG_LAST;
491 pkt.u.bind_nak.reject_reason = reason;
492 version.rpc_vers = 5;
493 version.rpc_vers_minor = 0;
494 pkt.u.bind_nak.num_versions = 1;
495 pkt.u.bind_nak.versions = &version;
496 pkt.u.bind_nak._pad = data_blob_const(_pad, sizeof(_pad));
498 rep = talloc_zero(call, struct data_blob_list_item);
500 return NT_STATUS_NO_MEMORY;
503 status = ncacn_push_auth(&rep->blob, call, &pkt, NULL);
504 if (!NT_STATUS_IS_OK(status)) {
508 dcerpc_set_frag_length(&rep->blob, rep->blob.length);
510 DLIST_ADD_END(call->replies, rep);
511 dcesrv_call_set_list(call, DCESRV_LIST_CALL_LIST);
513 if (call->conn->call_list && call->conn->call_list->replies) {
514 if (call->conn->transport.report_output_data) {
515 call->conn->transport.report_output_data(call->conn);
522 static NTSTATUS dcesrv_fault_disconnect(struct dcesrv_call_state *call,
526 * We add the call to the pending_call_list
527 * in order to defer the termination.
529 dcesrv_call_disconnect_after(call, "dcesrv_fault_disconnect");
531 return dcesrv_fault_with_flags(call, fault_code,
532 DCERPC_PFC_FLAG_DID_NOT_EXECUTE);
535 static int dcesrv_connection_context_destructor(struct dcesrv_connection_context *c)
537 DLIST_REMOVE(c->conn->contexts, c);
539 if (c->iface && c->iface->unbind) {
540 c->iface->unbind(c, c->iface);
547 static void dcesrv_prepare_context_auth(struct dcesrv_call_state *dce_call)
549 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
550 const struct dcesrv_endpoint *endpoint = dce_call->conn->endpoint;
551 enum dcerpc_transport_t transport =
552 dcerpc_binding_get_transport(endpoint->ep_description);
553 struct dcesrv_connection_context *context = dce_call->context;
554 const struct dcesrv_interface *iface = context->iface;
556 context->min_auth_level = DCERPC_AUTH_LEVEL_NONE;
558 if (transport == NCALRPC) {
559 context->allow_connect = true;
564 * allow overwrite per interface
565 * allow dcerpc auth level connect:<interface>
567 context->allow_connect = lpcfg_allow_dcerpc_auth_level_connect(lp_ctx);
568 context->allow_connect = lpcfg_parm_bool(lp_ctx, NULL,
569 "allow dcerpc auth level connect",
571 context->allow_connect);
574 NTSTATUS dcesrv_interface_bind_require_integrity(struct dcesrv_call_state *dce_call,
575 const struct dcesrv_interface *iface)
577 if (dce_call->context == NULL) {
578 return NT_STATUS_INTERNAL_ERROR;
581 dce_call->context->min_auth_level = DCERPC_AUTH_LEVEL_INTEGRITY;
585 NTSTATUS dcesrv_interface_bind_require_privacy(struct dcesrv_call_state *dce_call,
586 const struct dcesrv_interface *iface)
588 if (dce_call->context == NULL) {
589 return NT_STATUS_INTERNAL_ERROR;
592 dce_call->context->min_auth_level = DCERPC_AUTH_LEVEL_PRIVACY;
596 _PUBLIC_ NTSTATUS dcesrv_interface_bind_reject_connect(struct dcesrv_call_state *dce_call,
597 const struct dcesrv_interface *iface)
599 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
600 const struct dcesrv_endpoint *endpoint = dce_call->conn->endpoint;
601 enum dcerpc_transport_t transport =
602 dcerpc_binding_get_transport(endpoint->ep_description);
603 struct dcesrv_connection_context *context = dce_call->context;
605 if (context == NULL) {
606 return NT_STATUS_INTERNAL_ERROR;
609 if (transport == NCALRPC) {
610 context->allow_connect = true;
615 * allow overwrite per interface
616 * allow dcerpc auth level connect:<interface>
618 context->allow_connect = false;
619 context->allow_connect = lpcfg_parm_bool(lp_ctx, NULL,
620 "allow dcerpc auth level connect",
622 context->allow_connect);
626 _PUBLIC_ NTSTATUS dcesrv_interface_bind_allow_connect(struct dcesrv_call_state *dce_call,
627 const struct dcesrv_interface *iface)
629 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
630 const struct dcesrv_endpoint *endpoint = dce_call->conn->endpoint;
631 enum dcerpc_transport_t transport =
632 dcerpc_binding_get_transport(endpoint->ep_description);
633 struct dcesrv_connection_context *context = dce_call->context;
635 if (context == NULL) {
636 return NT_STATUS_INTERNAL_ERROR;
639 if (transport == NCALRPC) {
640 context->allow_connect = true;
645 * allow overwrite per interface
646 * allow dcerpc auth level connect:<interface>
648 context->allow_connect = true;
649 context->allow_connect = lpcfg_parm_bool(lp_ctx, NULL,
650 "allow dcerpc auth level connect",
652 context->allow_connect);
657 handle a bind request
659 static NTSTATUS dcesrv_bind(struct dcesrv_call_state *call)
661 uint32_t if_version, transfer_syntax_version;
662 struct GUID uuid, *transfer_syntax_uuid;
663 struct ncacn_packet pkt;
664 struct data_blob_list_item *rep;
666 uint32_t result=0, reason=0;
668 const struct dcesrv_interface *iface;
669 uint32_t extra_flags = 0;
670 uint16_t max_req = 0;
671 uint16_t max_rep = 0;
672 const char *ep_prefix = "";
673 const char *endpoint = NULL;
675 status = dcerpc_verify_ncacn_packet_header(&call->pkt,
677 call->pkt.u.bind.auth_info.length,
678 0, /* required flags */
679 DCERPC_PFC_FLAG_FIRST |
680 DCERPC_PFC_FLAG_LAST |
681 DCERPC_PFC_FLAG_SUPPORT_HEADER_SIGN |
682 0x08 | /* this is not defined, but should be ignored */
683 DCERPC_PFC_FLAG_CONC_MPX |
684 DCERPC_PFC_FLAG_DID_NOT_EXECUTE |
685 DCERPC_PFC_FLAG_MAYBE |
686 DCERPC_PFC_FLAG_OBJECT_UUID);
687 if (!NT_STATUS_IS_OK(status)) {
688 return dcesrv_bind_nak(call,
689 DCERPC_BIND_NAK_REASON_PROTOCOL_VERSION_NOT_SUPPORTED);
692 /* max_recv_frag and max_xmit_frag result always in the same value! */
693 max_req = MIN(call->pkt.u.bind.max_xmit_frag,
694 call->pkt.u.bind.max_recv_frag);
696 * The values are between 2048 and 5840 tested against Windows 2012R2
697 * via ncacn_ip_tcp on port 135.
699 max_req = MAX(2048, max_req);
700 max_rep = MIN(max_req, call->conn->max_recv_frag);
701 /* They are truncated to an 8 byte boundary. */
704 /* max_recv_frag and max_xmit_frag result always in the same value! */
705 call->conn->max_recv_frag = max_rep;
706 call->conn->max_xmit_frag = max_rep;
709 if provided, check the assoc_group is valid
711 if (call->pkt.u.bind.assoc_group_id != 0 &&
712 lpcfg_parm_bool(call->conn->dce_ctx->lp_ctx, NULL, "dcesrv","assoc group checking", true) &&
713 dcesrv_assoc_group_find(call->conn->dce_ctx, call->pkt.u.bind.assoc_group_id) == NULL) {
714 return dcesrv_bind_nak(call, 0);
717 if (call->pkt.u.bind.num_contexts < 1 ||
718 call->pkt.u.bind.ctx_list[0].num_transfer_syntaxes < 1) {
719 return dcesrv_bind_nak(call, 0);
722 context_id = call->pkt.u.bind.ctx_list[0].context_id;
724 /* you can't bind twice on one context */
725 if (dcesrv_find_context(call->conn, context_id) != NULL) {
726 return dcesrv_bind_nak(call, 0);
729 if_version = call->pkt.u.bind.ctx_list[0].abstract_syntax.if_version;
730 uuid = call->pkt.u.bind.ctx_list[0].abstract_syntax.uuid;
732 transfer_syntax_version = call->pkt.u.bind.ctx_list[0].transfer_syntaxes[0].if_version;
733 transfer_syntax_uuid = &call->pkt.u.bind.ctx_list[0].transfer_syntaxes[0].uuid;
734 if (!GUID_equal(&ndr_transfer_syntax_ndr.uuid, transfer_syntax_uuid) != 0 ||
735 ndr_transfer_syntax_ndr.if_version != transfer_syntax_version) {
736 char *uuid_str = GUID_string(call, transfer_syntax_uuid);
737 /* we only do NDR encoded dcerpc */
738 DEBUG(0,("Non NDR transfer syntax requested - %s\n", uuid_str));
739 talloc_free(uuid_str);
740 return dcesrv_bind_nak(call, 0);
743 iface = find_interface_by_uuid(call->conn->endpoint, &uuid, if_version);
745 char *uuid_str = GUID_string(call, &uuid);
746 DEBUG(2,("Request for unknown dcerpc interface %s/%d\n", uuid_str, if_version));
747 talloc_free(uuid_str);
749 /* we don't know about that interface */
750 result = DCERPC_BIND_PROVIDER_REJECT;
751 reason = DCERPC_BIND_REASON_ASYNTAX;
755 /* add this context to the list of available context_ids */
756 struct dcesrv_connection_context *context = talloc_zero(call->conn,
757 struct dcesrv_connection_context);
758 if (context == NULL) {
759 return dcesrv_bind_nak(call, 0);
761 context->conn = call->conn;
762 context->iface = iface;
763 context->context_id = context_id;
764 if (call->pkt.u.bind.assoc_group_id != 0) {
765 context->assoc_group = dcesrv_assoc_group_reference(context,
767 call->pkt.u.bind.assoc_group_id);
769 context->assoc_group = dcesrv_assoc_group_new(context, call->conn->dce_ctx);
771 if (context->assoc_group == NULL) {
772 talloc_free(context);
773 return dcesrv_bind_nak(call, 0);
775 context->private_data = NULL;
776 DLIST_ADD(call->conn->contexts, context);
777 call->context = context;
778 talloc_set_destructor(context, dcesrv_connection_context_destructor);
780 dcesrv_prepare_context_auth(call);
782 status = iface->bind(call, iface, if_version);
783 if (!NT_STATUS_IS_OK(status)) {
784 char *uuid_str = GUID_string(call, &uuid);
785 DEBUG(2,("Request for dcerpc interface %s/%d rejected: %s\n",
786 uuid_str, if_version, nt_errstr(status)));
787 talloc_free(uuid_str);
788 /* we don't want to trigger the iface->unbind() hook */
789 context->iface = NULL;
790 talloc_free(call->context);
791 call->context = NULL;
792 return dcesrv_bind_nak(call, 0);
796 if ((call->pkt.pfc_flags & DCERPC_PFC_FLAG_CONC_MPX) &&
797 (call->state_flags & DCESRV_CALL_STATE_FLAG_MULTIPLEXED)) {
798 call->context->conn->state_flags |= DCESRV_CALL_STATE_FLAG_MULTIPLEXED;
799 extra_flags |= DCERPC_PFC_FLAG_CONC_MPX;
802 if (call->state_flags & DCESRV_CALL_STATE_FLAG_PROCESS_PENDING_CALL) {
803 call->context->conn->state_flags |= DCESRV_CALL_STATE_FLAG_PROCESS_PENDING_CALL;
806 /* handle any authentication that is being requested */
807 if (!dcesrv_auth_bind(call)) {
808 talloc_free(call->context);
809 call->context = NULL;
810 return dcesrv_bind_nak(call, DCERPC_BIND_REASON_INVALID_AUTH_TYPE);
813 /* setup a bind_ack */
814 dcesrv_init_hdr(&pkt, lpcfg_rpc_big_endian(call->conn->dce_ctx->lp_ctx));
816 pkt.call_id = call->pkt.call_id;
817 pkt.ptype = DCERPC_PKT_BIND_ACK;
818 pkt.pfc_flags = DCERPC_PFC_FLAG_FIRST | DCERPC_PFC_FLAG_LAST | extra_flags;
819 pkt.u.bind_ack.max_xmit_frag = call->conn->max_xmit_frag;
820 pkt.u.bind_ack.max_recv_frag = call->conn->max_recv_frag;
823 make it possible for iface->bind() to specify the assoc_group_id
824 This helps the openchange mapiproxy plugin to work correctly.
829 pkt.u.bind_ack.assoc_group_id = call->context->assoc_group->id;
831 pkt.u.bind_ack.assoc_group_id = DUMMY_ASSOC_GROUP;
835 endpoint = dcerpc_binding_get_string_option(
836 call->conn->endpoint->ep_description,
840 if (endpoint == NULL) {
844 if (strncasecmp(endpoint, "\\pipe\\", 6) == 0) {
846 * TODO: check if this is really needed
848 * Or if we should fix this in our idl files.
850 ep_prefix = "\\PIPE\\";
854 pkt.u.bind_ack.secondary_address = talloc_asprintf(call, "%s%s",
857 if (pkt.u.bind_ack.secondary_address == NULL) {
858 TALLOC_FREE(call->context);
859 return NT_STATUS_NO_MEMORY;
861 pkt.u.bind_ack.num_results = 1;
862 pkt.u.bind_ack.ctx_list = talloc_zero(call, struct dcerpc_ack_ctx);
863 if (!pkt.u.bind_ack.ctx_list) {
864 talloc_free(call->context);
865 call->context = NULL;
866 return NT_STATUS_NO_MEMORY;
868 pkt.u.bind_ack.ctx_list[0].result = result;
869 pkt.u.bind_ack.ctx_list[0].reason.value = reason;
870 pkt.u.bind_ack.ctx_list[0].syntax = ndr_transfer_syntax_ndr;
871 pkt.u.bind_ack.auth_info = data_blob(NULL, 0);
873 status = dcesrv_auth_bind_ack(call, &pkt);
874 if (!NT_STATUS_IS_OK(status)) {
875 talloc_free(call->context);
876 call->context = NULL;
877 return dcesrv_bind_nak(call, 0);
880 rep = talloc_zero(call, struct data_blob_list_item);
882 talloc_free(call->context);
883 call->context = NULL;
884 return NT_STATUS_NO_MEMORY;
887 status = ncacn_push_auth(&rep->blob, call, &pkt,
888 call->conn->auth_state.auth_info);
889 if (!NT_STATUS_IS_OK(status)) {
890 talloc_free(call->context);
891 call->context = NULL;
895 dcerpc_set_frag_length(&rep->blob, rep->blob.length);
897 DLIST_ADD_END(call->replies, rep);
898 dcesrv_call_set_list(call, DCESRV_LIST_CALL_LIST);
900 if (call->conn->call_list && call->conn->call_list->replies) {
901 if (call->conn->transport.report_output_data) {
902 call->conn->transport.report_output_data(call->conn);
911 handle a auth3 request
913 static NTSTATUS dcesrv_auth3(struct dcesrv_call_state *call)
917 status = dcerpc_verify_ncacn_packet_header(&call->pkt,
919 call->pkt.u.auth3.auth_info.length,
920 0, /* required flags */
921 DCERPC_PFC_FLAG_FIRST |
922 DCERPC_PFC_FLAG_LAST |
923 DCERPC_PFC_FLAG_SUPPORT_HEADER_SIGN |
924 0x08 | /* this is not defined, but should be ignored */
925 DCERPC_PFC_FLAG_CONC_MPX |
926 DCERPC_PFC_FLAG_DID_NOT_EXECUTE |
927 DCERPC_PFC_FLAG_MAYBE |
928 DCERPC_PFC_FLAG_OBJECT_UUID);
929 if (!NT_STATUS_IS_OK(status)) {
930 return dcesrv_fault_disconnect(call, DCERPC_NCA_S_PROTO_ERROR);
933 /* handle the auth3 in the auth code */
934 if (!dcesrv_auth_auth3(call)) {
935 return dcesrv_fault(call, DCERPC_FAULT_OTHER);
940 /* we don't send a reply to a auth3 request, except by a
947 handle a bind request
949 static NTSTATUS dcesrv_alter_new_context(struct dcesrv_call_state *call, uint32_t context_id)
951 uint32_t if_version, transfer_syntax_version;
952 struct dcesrv_connection_context *context;
953 const struct dcesrv_interface *iface;
954 struct GUID uuid, *transfer_syntax_uuid;
957 if_version = call->pkt.u.alter.ctx_list[0].abstract_syntax.if_version;
958 uuid = call->pkt.u.alter.ctx_list[0].abstract_syntax.uuid;
960 transfer_syntax_version = call->pkt.u.alter.ctx_list[0].transfer_syntaxes[0].if_version;
961 transfer_syntax_uuid = &call->pkt.u.alter.ctx_list[0].transfer_syntaxes[0].uuid;
962 if (!GUID_equal(transfer_syntax_uuid, &ndr_transfer_syntax_ndr.uuid) ||
963 ndr_transfer_syntax_ndr.if_version != transfer_syntax_version) {
964 /* we only do NDR encoded dcerpc */
965 return NT_STATUS_RPC_PROTSEQ_NOT_SUPPORTED;
968 iface = find_interface_by_uuid(call->conn->endpoint, &uuid, if_version);
970 char *uuid_str = GUID_string(call, &uuid);
971 DEBUG(2,("Request for unknown dcerpc interface %s/%d\n", uuid_str, if_version));
972 talloc_free(uuid_str);
973 return NT_STATUS_RPC_PROTSEQ_NOT_SUPPORTED;
976 /* add this context to the list of available context_ids */
977 context = talloc_zero(call->conn, struct dcesrv_connection_context);
978 if (context == NULL) {
979 return NT_STATUS_NO_MEMORY;
981 context->conn = call->conn;
982 context->iface = iface;
983 context->context_id = context_id;
984 if (call->pkt.u.alter.assoc_group_id != 0) {
985 context->assoc_group = dcesrv_assoc_group_reference(context,
987 call->pkt.u.alter.assoc_group_id);
989 context->assoc_group = dcesrv_assoc_group_new(context, call->conn->dce_ctx);
991 if (context->assoc_group == NULL) {
992 talloc_free(context);
993 call->context = NULL;
994 return NT_STATUS_NO_MEMORY;
996 context->private_data = NULL;
997 DLIST_ADD(call->conn->contexts, context);
998 call->context = context;
999 talloc_set_destructor(context, dcesrv_connection_context_destructor);
1001 dcesrv_prepare_context_auth(call);
1003 status = iface->bind(call, iface, if_version);
1004 if (!NT_STATUS_IS_OK(status)) {
1005 /* we don't want to trigger the iface->unbind() hook */
1006 context->iface = NULL;
1007 talloc_free(context);
1008 call->context = NULL;
1012 return NT_STATUS_OK;
1015 /* setup and send an alter_resp */
1016 static NTSTATUS dcesrv_alter_resp(struct dcesrv_call_state *call,
1020 struct ncacn_packet pkt;
1021 uint32_t extra_flags = 0;
1022 struct data_blob_list_item *rep = NULL;
1025 dcesrv_init_hdr(&pkt, lpcfg_rpc_big_endian(call->conn->dce_ctx->lp_ctx));
1026 pkt.auth_length = 0;
1027 pkt.call_id = call->pkt.call_id;
1028 pkt.ptype = DCERPC_PKT_ALTER_RESP;
1030 if ((call->pkt.pfc_flags & DCERPC_PFC_FLAG_CONC_MPX) &&
1031 call->context->conn->state_flags &
1032 DCESRV_CALL_STATE_FLAG_MULTIPLEXED) {
1033 extra_flags |= DCERPC_PFC_FLAG_CONC_MPX;
1035 if (call->state_flags & DCESRV_CALL_STATE_FLAG_PROCESS_PENDING_CALL) {
1036 call->context->conn->state_flags |=
1037 DCESRV_CALL_STATE_FLAG_PROCESS_PENDING_CALL;
1040 pkt.pfc_flags = DCERPC_PFC_FLAG_FIRST | DCERPC_PFC_FLAG_LAST | extra_flags;
1041 pkt.u.alter_resp.max_xmit_frag = call->conn->max_xmit_frag;
1042 pkt.u.alter_resp.max_recv_frag = call->conn->max_recv_frag;
1044 pkt.u.alter_resp.assoc_group_id = call->context->assoc_group->id;
1046 pkt.u.alter_resp.assoc_group_id = 0;
1048 pkt.u.alter_resp.num_results = 1;
1049 pkt.u.alter_resp.ctx_list = talloc_zero(call, struct dcerpc_ack_ctx);
1050 if (!pkt.u.alter_resp.ctx_list) {
1051 return NT_STATUS_NO_MEMORY;
1053 pkt.u.alter_resp.ctx_list[0].result = result;
1054 pkt.u.alter_resp.ctx_list[0].reason.value = reason;
1055 pkt.u.alter_resp.ctx_list[0].syntax = ndr_transfer_syntax_ndr;
1056 pkt.u.alter_resp.auth_info = data_blob(NULL, 0);
1057 pkt.u.alter_resp.secondary_address = "";
1059 status = dcesrv_auth_alter_ack(call, &pkt);
1060 if (!NT_STATUS_IS_OK(status)) {
1061 if (NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)
1062 || NT_STATUS_EQUAL(status, NT_STATUS_LOGON_FAILURE)
1063 || NT_STATUS_EQUAL(status, NT_STATUS_NO_SUCH_USER)
1064 || NT_STATUS_EQUAL(status, NT_STATUS_WRONG_PASSWORD)) {
1065 return dcesrv_fault(call, DCERPC_FAULT_ACCESS_DENIED);
1067 return dcesrv_fault(call, 0);
1070 rep = talloc_zero(call, struct data_blob_list_item);
1072 return NT_STATUS_NO_MEMORY;
1075 status = ncacn_push_auth(&rep->blob, call, &pkt, call->conn->auth_state.auth_info);
1076 if (!NT_STATUS_IS_OK(status)) {
1080 dcerpc_set_frag_length(&rep->blob, rep->blob.length);
1082 DLIST_ADD_END(call->replies, rep);
1083 dcesrv_call_set_list(call, DCESRV_LIST_CALL_LIST);
1085 if (call->conn->call_list && call->conn->call_list->replies) {
1086 if (call->conn->transport.report_output_data) {
1087 call->conn->transport.report_output_data(call->conn);
1091 return NT_STATUS_OK;
1095 handle a alter context request
1097 static NTSTATUS dcesrv_alter(struct dcesrv_call_state *call)
1100 uint32_t context_id;
1102 status = dcerpc_verify_ncacn_packet_header(&call->pkt,
1104 call->pkt.u.alter.auth_info.length,
1105 0, /* required flags */
1106 DCERPC_PFC_FLAG_FIRST |
1107 DCERPC_PFC_FLAG_LAST |
1108 DCERPC_PFC_FLAG_SUPPORT_HEADER_SIGN |
1109 0x08 | /* this is not defined, but should be ignored */
1110 DCERPC_PFC_FLAG_CONC_MPX |
1111 DCERPC_PFC_FLAG_DID_NOT_EXECUTE |
1112 DCERPC_PFC_FLAG_MAYBE |
1113 DCERPC_PFC_FLAG_OBJECT_UUID);
1114 if (!NT_STATUS_IS_OK(status)) {
1115 return dcesrv_fault_disconnect(call, DCERPC_NCA_S_PROTO_ERROR);
1118 /* handle any authentication that is being requested */
1119 if (!dcesrv_auth_alter(call)) {
1120 /* TODO: work out the right reject code */
1121 return dcesrv_alter_resp(call,
1122 DCERPC_BIND_PROVIDER_REJECT,
1123 DCERPC_BIND_REASON_ASYNTAX);
1126 context_id = call->pkt.u.alter.ctx_list[0].context_id;
1128 /* see if they are asking for a new interface */
1129 call->context = dcesrv_find_context(call->conn, context_id);
1130 if (!call->context) {
1131 status = dcesrv_alter_new_context(call, context_id);
1132 if (!NT_STATUS_IS_OK(status)) {
1133 return dcesrv_alter_resp(call,
1134 DCERPC_BIND_PROVIDER_REJECT,
1135 DCERPC_BIND_REASON_ASYNTAX);
1139 if (call->pkt.u.alter.assoc_group_id != 0 &&
1140 lpcfg_parm_bool(call->conn->dce_ctx->lp_ctx, NULL, "dcesrv","assoc group checking", true) &&
1141 call->pkt.u.alter.assoc_group_id != call->context->assoc_group->id) {
1142 DEBUG(0,(__location__ ": Failed attempt to use new assoc_group in alter context (0x%08x 0x%08x)\n",
1143 call->context->assoc_group->id, call->pkt.u.alter.assoc_group_id));
1144 /* TODO: can they ask for a new association group? */
1145 return dcesrv_alter_resp(call,
1146 DCERPC_BIND_PROVIDER_REJECT,
1147 DCERPC_BIND_REASON_ASYNTAX);
1150 return dcesrv_alter_resp(call,
1151 DCERPC_BIND_ACK_RESULT_ACCEPTANCE,
1152 DCERPC_BIND_ACK_REASON_NOT_SPECIFIED);
1156 possibly save the call for inspection with ndrdump
1158 static void dcesrv_save_call(struct dcesrv_call_state *call, const char *why)
1162 const char *dump_dir;
1163 dump_dir = lpcfg_parm_string(call->conn->dce_ctx->lp_ctx, NULL, "dcesrv", "stubs directory");
1167 fname = talloc_asprintf(call, "%s/RPC-%s-%u-%s.dat",
1169 call->context->iface->name,
1170 call->pkt.u.request.opnum,
1172 if (file_save(fname, call->pkt.u.request.stub_and_verifier.data, call->pkt.u.request.stub_and_verifier.length)) {
1173 DEBUG(0,("RPC SAVED %s\n", fname));
1179 static NTSTATUS dcesrv_check_verification_trailer(struct dcesrv_call_state *call)
1181 TALLOC_CTX *frame = talloc_stackframe();
1182 const uint32_t bitmask1 = call->conn->auth_state.client_hdr_signing ?
1183 DCERPC_SEC_VT_CLIENT_SUPPORTS_HEADER_SIGNING : 0;
1184 const struct dcerpc_sec_vt_pcontext pcontext = {
1185 .abstract_syntax = call->context->iface->syntax_id,
1186 .transfer_syntax = ndr_transfer_syntax_ndr,
1188 const struct dcerpc_sec_vt_header2 header2 =
1189 dcerpc_sec_vt_header2_from_ncacn_packet(&call->pkt);
1190 enum ndr_err_code ndr_err;
1191 struct dcerpc_sec_verification_trailer *vt = NULL;
1192 NTSTATUS status = NT_STATUS_OK;
1195 SMB_ASSERT(call->pkt.ptype == DCERPC_PKT_REQUEST);
1197 ndr_err = ndr_pop_dcerpc_sec_verification_trailer(call->ndr_pull,
1199 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
1200 status = ndr_map_error2ntstatus(ndr_err);
1204 ok = dcerpc_sec_verification_trailer_check(vt, &bitmask1,
1205 &pcontext, &header2);
1207 status = NT_STATUS_ACCESS_DENIED;
1216 handle a dcerpc request packet
1218 static NTSTATUS dcesrv_request(struct dcesrv_call_state *call)
1220 const struct dcesrv_endpoint *endpoint = call->conn->endpoint;
1221 enum dcerpc_transport_t transport =
1222 dcerpc_binding_get_transport(endpoint->ep_description);
1223 struct ndr_pull *pull;
1225 struct dcesrv_connection_context *context;
1227 /* if authenticated, and the mech we use can't do async replies, don't use them... */
1228 if (call->conn->auth_state.gensec_security &&
1229 !gensec_have_feature(call->conn->auth_state.gensec_security, GENSEC_FEATURE_ASYNC_REPLIES)) {
1230 call->state_flags &= ~DCESRV_CALL_STATE_FLAG_MAY_ASYNC;
1233 context = dcesrv_find_context(call->conn, call->pkt.u.request.context_id);
1234 if (context == NULL) {
1235 return dcesrv_fault(call, DCERPC_FAULT_UNK_IF);
1238 switch (call->conn->auth_state.auth_level) {
1239 case DCERPC_AUTH_LEVEL_NONE:
1240 case DCERPC_AUTH_LEVEL_INTEGRITY:
1241 case DCERPC_AUTH_LEVEL_PRIVACY:
1244 if (!context->allow_connect) {
1247 addr = tsocket_address_string(call->conn->remote_address,
1250 DEBUG(2, ("%s: restrict auth_level_connect access "
1251 "to [%s] with auth[type=0x%x,level=0x%x] "
1252 "on [%s] from [%s]\n",
1253 __func__, context->iface->name,
1254 call->conn->auth_state.auth_type,
1255 call->conn->auth_state.auth_level,
1256 derpc_transport_string_by_transport(transport),
1258 return dcesrv_fault(call, DCERPC_FAULT_ACCESS_DENIED);
1263 if (call->conn->auth_state.auth_level < context->min_auth_level) {
1266 addr = tsocket_address_string(call->conn->remote_address, call);
1268 DEBUG(2, ("%s: restrict access by min_auth_level[0x%x] "
1269 "to [%s] with auth[type=0x%x,level=0x%x] "
1270 "on [%s] from [%s]\n",
1272 context->min_auth_level,
1273 context->iface->name,
1274 call->conn->auth_state.auth_type,
1275 call->conn->auth_state.auth_level,
1276 derpc_transport_string_by_transport(transport),
1278 return dcesrv_fault(call, DCERPC_FAULT_ACCESS_DENIED);
1281 pull = ndr_pull_init_blob(&call->pkt.u.request.stub_and_verifier, call);
1282 NT_STATUS_HAVE_NO_MEMORY(pull);
1284 pull->flags |= LIBNDR_FLAG_REF_ALLOC;
1286 call->context = context;
1287 call->ndr_pull = pull;
1289 if (!(call->pkt.drep[0] & DCERPC_DREP_LE)) {
1290 pull->flags |= LIBNDR_FLAG_BIGENDIAN;
1293 status = dcesrv_check_verification_trailer(call);
1294 if (!NT_STATUS_IS_OK(status)) {
1295 uint32_t faultcode = DCERPC_FAULT_OTHER;
1296 if (NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
1297 faultcode = DCERPC_FAULT_ACCESS_DENIED;
1299 DEBUG(10, ("dcesrv_check_verification_trailer failed: %s\n",
1300 nt_errstr(status)));
1301 return dcesrv_fault(call, faultcode);
1304 /* unravel the NDR for the packet */
1305 status = context->iface->ndr_pull(call, call, pull, &call->r);
1306 if (!NT_STATUS_IS_OK(status)) {
1307 if (call->fault_code == DCERPC_FAULT_OP_RNG_ERROR) {
1308 /* we got an unknown call */
1309 DEBUG(3,(__location__ ": Unknown RPC call %u on %s\n",
1310 call->pkt.u.request.opnum, context->iface->name));
1311 dcesrv_save_call(call, "unknown");
1313 dcesrv_save_call(call, "pullfail");
1315 return dcesrv_fault(call, call->fault_code);
1318 if (pull->offset != pull->data_size) {
1319 dcesrv_save_call(call, "extrabytes");
1320 DEBUG(3,("Warning: %d extra bytes in incoming RPC request\n",
1321 pull->data_size - pull->offset));
1324 /* call the dispatch function */
1325 status = context->iface->dispatch(call, call, call->r);
1326 if (!NT_STATUS_IS_OK(status)) {
1327 DEBUG(5,("dcerpc fault in call %s:%02x - %s\n",
1328 context->iface->name,
1329 call->pkt.u.request.opnum,
1330 dcerpc_errstr(pull, call->fault_code)));
1331 return dcesrv_fault(call, call->fault_code);
1334 /* add the call to the pending list */
1335 dcesrv_call_set_list(call, DCESRV_LIST_PENDING_CALL_LIST);
1337 if (call->state_flags & DCESRV_CALL_STATE_FLAG_ASYNC) {
1338 return NT_STATUS_OK;
1341 return dcesrv_reply(call);
1346 remove the call from the right list when freed
1348 static int dcesrv_call_dequeue(struct dcesrv_call_state *call)
1350 dcesrv_call_set_list(call, DCESRV_LIST_NONE);
1354 _PUBLIC_ const struct tsocket_address *dcesrv_connection_get_local_address(struct dcesrv_connection *conn)
1356 return conn->local_address;
1359 _PUBLIC_ const struct tsocket_address *dcesrv_connection_get_remote_address(struct dcesrv_connection *conn)
1361 return conn->remote_address;
1365 process some input to a dcerpc endpoint server.
1367 static NTSTATUS dcesrv_process_ncacn_packet(struct dcesrv_connection *dce_conn,
1368 struct ncacn_packet *pkt,
1372 struct dcesrv_call_state *call;
1374 call = talloc_zero(dce_conn, struct dcesrv_call_state);
1376 data_blob_free(&blob);
1378 return NT_STATUS_NO_MEMORY;
1380 call->conn = dce_conn;
1381 call->event_ctx = dce_conn->event_ctx;
1382 call->msg_ctx = dce_conn->msg_ctx;
1383 call->state_flags = call->conn->state_flags;
1384 call->time = timeval_current();
1385 call->list = DCESRV_LIST_NONE;
1387 talloc_steal(call, pkt);
1388 talloc_steal(call, blob.data);
1391 talloc_set_destructor(call, dcesrv_call_dequeue);
1393 /* we have to check the signing here, before combining the
1395 if (call->pkt.ptype == DCERPC_PKT_REQUEST) {
1396 status = dcerpc_verify_ncacn_packet_header(&call->pkt,
1398 call->pkt.u.request.stub_and_verifier.length,
1399 0, /* required_flags */
1400 DCERPC_PFC_FLAG_FIRST |
1401 DCERPC_PFC_FLAG_LAST |
1402 DCERPC_PFC_FLAG_PENDING_CANCEL |
1403 0x08 | /* this is not defined, but should be ignored */
1404 DCERPC_PFC_FLAG_CONC_MPX |
1405 DCERPC_PFC_FLAG_DID_NOT_EXECUTE |
1406 DCERPC_PFC_FLAG_MAYBE |
1407 DCERPC_PFC_FLAG_OBJECT_UUID);
1408 if (!NT_STATUS_IS_OK(status)) {
1409 return dcesrv_fault_disconnect(call,
1410 DCERPC_NCA_S_PROTO_ERROR);
1413 if (!dcesrv_auth_request(call, &blob)) {
1414 return dcesrv_fault(call, DCERPC_FAULT_ACCESS_DENIED);
1418 /* see if this is a continued packet */
1419 if (call->pkt.ptype == DCERPC_PKT_REQUEST &&
1420 !(call->pkt.pfc_flags & DCERPC_PFC_FLAG_FIRST)) {
1421 struct dcesrv_call_state *call2 = call;
1422 uint32_t alloc_size;
1424 /* we only allow fragmented requests, no other packet types */
1425 if (call->pkt.ptype != DCERPC_PKT_REQUEST) {
1426 return dcesrv_fault(call2, DCERPC_FAULT_OTHER);
1429 /* this is a continuation of an existing call - find the call
1430 then tack it on the end */
1431 call = dcesrv_find_fragmented_call(dce_conn, call2->pkt.call_id);
1433 return dcesrv_fault(call2, DCERPC_FAULT_OTHER);
1436 if (call->pkt.ptype != call2->pkt.ptype) {
1437 /* trying to play silly buggers are we? */
1438 return dcesrv_fault(call2, DCERPC_NCA_S_PROTO_ERROR);
1440 if (memcmp(call->pkt.drep, call2->pkt.drep, sizeof(pkt->drep)) != 0) {
1441 return dcesrv_fault(call2, DCERPC_NCA_S_PROTO_ERROR);
1443 if (call->pkt.call_id != call2->pkt.call_id) {
1444 return dcesrv_fault(call2, DCERPC_NCA_S_PROTO_ERROR);
1446 if (call->pkt.u.request.context_id != call2->pkt.u.request.context_id) {
1447 return dcesrv_fault(call2, DCERPC_NCA_S_PROTO_ERROR);
1449 if (call->pkt.u.request.opnum != call2->pkt.u.request.opnum) {
1450 return dcesrv_fault(call2, DCERPC_NCA_S_PROTO_ERROR);
1453 alloc_size = call->pkt.u.request.stub_and_verifier.length +
1454 call2->pkt.u.request.stub_and_verifier.length;
1455 if (call->pkt.u.request.alloc_hint > alloc_size) {
1456 alloc_size = call->pkt.u.request.alloc_hint;
1459 call->pkt.u.request.stub_and_verifier.data =
1460 talloc_realloc(call,
1461 call->pkt.u.request.stub_and_verifier.data,
1462 uint8_t, alloc_size);
1463 if (!call->pkt.u.request.stub_and_verifier.data) {
1464 return dcesrv_fault(call2, DCERPC_FAULT_OTHER);
1466 memcpy(call->pkt.u.request.stub_and_verifier.data +
1467 call->pkt.u.request.stub_and_verifier.length,
1468 call2->pkt.u.request.stub_and_verifier.data,
1469 call2->pkt.u.request.stub_and_verifier.length);
1470 call->pkt.u.request.stub_and_verifier.length +=
1471 call2->pkt.u.request.stub_and_verifier.length;
1473 call->pkt.pfc_flags |= (call2->pkt.pfc_flags & DCERPC_PFC_FLAG_LAST);
1478 /* this may not be the last pdu in the chain - if its isn't then
1479 just put it on the incoming_fragmented_call_list and wait for the rest */
1480 if (call->pkt.ptype == DCERPC_PKT_REQUEST &&
1481 !(call->pkt.pfc_flags & DCERPC_PFC_FLAG_LAST)) {
1482 dcesrv_call_set_list(call, DCESRV_LIST_FRAGMENTED_CALL_LIST);
1483 return NT_STATUS_OK;
1486 /* This removes any fragments we may have had stashed away */
1487 dcesrv_call_set_list(call, DCESRV_LIST_NONE);
1489 switch (call->pkt.ptype) {
1490 case DCERPC_PKT_BIND:
1491 status = dcesrv_bind(call);
1493 case DCERPC_PKT_AUTH3:
1494 status = dcesrv_auth3(call);
1496 case DCERPC_PKT_ALTER:
1497 status = dcesrv_alter(call);
1499 case DCERPC_PKT_REQUEST:
1500 status = dcesrv_request(call);
1503 status = NT_STATUS_INVALID_PARAMETER;
1507 /* if we are going to be sending a reply then add
1508 it to the list of pending calls. We add it to the end to keep the call
1509 list in the order we will answer */
1510 if (!NT_STATUS_IS_OK(status)) {
1517 _PUBLIC_ NTSTATUS dcesrv_init_context(TALLOC_CTX *mem_ctx,
1518 struct loadparm_context *lp_ctx,
1519 const char **endpoint_servers, struct dcesrv_context **_dce_ctx)
1522 struct dcesrv_context *dce_ctx;
1525 if (!endpoint_servers) {
1526 DEBUG(0,("dcesrv_init_context: no endpoint servers configured\n"));
1527 return NT_STATUS_INTERNAL_ERROR;
1530 dce_ctx = talloc_zero(mem_ctx, struct dcesrv_context);
1531 NT_STATUS_HAVE_NO_MEMORY(dce_ctx);
1533 if (uid_wrapper_enabled()) {
1534 setenv("UID_WRAPPER_MYUID", "1", 1);
1536 dce_ctx->initial_euid = geteuid();
1537 if (uid_wrapper_enabled()) {
1538 unsetenv("UID_WRAPPER_MYUID");
1541 dce_ctx->endpoint_list = NULL;
1542 dce_ctx->lp_ctx = lp_ctx;
1543 dce_ctx->assoc_groups_idr = idr_init(dce_ctx);
1544 NT_STATUS_HAVE_NO_MEMORY(dce_ctx->assoc_groups_idr);
1545 dce_ctx->broken_connections = NULL;
1547 for (i=0;endpoint_servers[i];i++) {
1548 const struct dcesrv_endpoint_server *ep_server;
1550 ep_server = dcesrv_ep_server_byname(endpoint_servers[i]);
1552 DEBUG(0,("dcesrv_init_context: failed to find endpoint server = '%s'\n", endpoint_servers[i]));
1553 return NT_STATUS_INTERNAL_ERROR;
1556 status = ep_server->init_server(dce_ctx, ep_server);
1557 if (!NT_STATUS_IS_OK(status)) {
1558 DEBUG(0,("dcesrv_init_context: failed to init endpoint server = '%s': %s\n", endpoint_servers[i],
1559 nt_errstr(status)));
1564 *_dce_ctx = dce_ctx;
1565 return NT_STATUS_OK;
1568 /* the list of currently registered DCERPC endpoint servers.
1570 static struct ep_server {
1571 struct dcesrv_endpoint_server *ep_server;
1572 } *ep_servers = NULL;
1573 static int num_ep_servers;
1576 register a DCERPC endpoint server.
1578 The 'name' can be later used by other backends to find the operations
1579 structure for this backend.
1581 The 'type' is used to specify whether this is for a disk, printer or IPC$ share
1583 _PUBLIC_ NTSTATUS dcerpc_register_ep_server(const void *_ep_server)
1585 const struct dcesrv_endpoint_server *ep_server = _ep_server;
1587 if (dcesrv_ep_server_byname(ep_server->name) != NULL) {
1588 /* its already registered! */
1589 DEBUG(0,("DCERPC endpoint server '%s' already registered\n",
1591 return NT_STATUS_OBJECT_NAME_COLLISION;
1594 ep_servers = realloc_p(ep_servers, struct ep_server, num_ep_servers+1);
1596 smb_panic("out of memory in dcerpc_register");
1599 ep_servers[num_ep_servers].ep_server = smb_xmemdup(ep_server, sizeof(*ep_server));
1600 ep_servers[num_ep_servers].ep_server->name = smb_xstrdup(ep_server->name);
1604 DEBUG(3,("DCERPC endpoint server '%s' registered\n",
1607 return NT_STATUS_OK;
1611 return the operations structure for a named backend of the specified type
1613 const struct dcesrv_endpoint_server *dcesrv_ep_server_byname(const char *name)
1617 for (i=0;i<num_ep_servers;i++) {
1618 if (strcmp(ep_servers[i].ep_server->name, name) == 0) {
1619 return ep_servers[i].ep_server;
1626 void dcerpc_server_init(struct loadparm_context *lp_ctx)
1628 static bool initialized;
1629 #define _MODULE_PROTO(init) extern NTSTATUS init(void);
1630 STATIC_dcerpc_server_MODULES_PROTO;
1631 init_module_fn static_init[] = { STATIC_dcerpc_server_MODULES };
1632 init_module_fn *shared_init;
1639 shared_init = load_samba_modules(NULL, "dcerpc_server");
1641 run_init_functions(static_init);
1642 run_init_functions(shared_init);
1644 talloc_free(shared_init);
1648 return the DCERPC module version, and the size of some critical types
1649 This can be used by endpoint server modules to either detect compilation errors, or provide
1650 multiple implementations for different smbd compilation options in one module
1652 const struct dcesrv_critical_sizes *dcerpc_module_version(void)
1654 static const struct dcesrv_critical_sizes critical_sizes = {
1655 DCERPC_MODULE_VERSION,
1656 sizeof(struct dcesrv_context),
1657 sizeof(struct dcesrv_endpoint),
1658 sizeof(struct dcesrv_endpoint_server),
1659 sizeof(struct dcesrv_interface),
1660 sizeof(struct dcesrv_if_list),
1661 sizeof(struct dcesrv_connection),
1662 sizeof(struct dcesrv_call_state),
1663 sizeof(struct dcesrv_auth),
1664 sizeof(struct dcesrv_handle)
1667 return &critical_sizes;
1670 static void dcesrv_terminate_connection(struct dcesrv_connection *dce_conn, const char *reason)
1672 struct dcesrv_context *dce_ctx = dce_conn->dce_ctx;
1673 struct stream_connection *srv_conn;
1674 srv_conn = talloc_get_type(dce_conn->transport.private_data,
1675 struct stream_connection);
1677 if (dce_conn->pending_call_list == NULL) {
1678 char *full_reason = talloc_asprintf(dce_conn, "dcesrv: %s", reason);
1680 DLIST_REMOVE(dce_ctx->broken_connections, dce_conn);
1681 stream_terminate_connection(srv_conn, full_reason ? full_reason : reason);
1685 if (dce_conn->terminate != NULL) {
1689 DEBUG(3,("dcesrv: terminating connection due to '%s' defered due to pending calls\n",
1691 dce_conn->terminate = talloc_strdup(dce_conn, reason);
1692 if (dce_conn->terminate == NULL) {
1693 dce_conn->terminate = "dcesrv: defered terminating connection - no memory";
1695 DLIST_ADD_END(dce_ctx->broken_connections, dce_conn);
1698 static void dcesrv_cleanup_broken_connections(struct dcesrv_context *dce_ctx)
1700 struct dcesrv_connection *cur, *next;
1702 next = dce_ctx->broken_connections;
1703 while (next != NULL) {
1707 if (cur->state_flags & DCESRV_CALL_STATE_FLAG_PROCESS_PENDING_CALL) {
1708 struct dcesrv_connection_context *context_cur, *context_next;
1710 context_next = cur->contexts;
1711 while (context_next != NULL) {
1712 context_cur = context_next;
1713 context_next = context_cur->next;
1715 dcesrv_connection_context_destructor(context_cur);
1719 dcesrv_terminate_connection(cur, cur->terminate);
1723 /* We need this include to be able to compile on some plateforms
1724 * (ie. freebsd 7.2) as it seems that <sys/uio.h> is not included
1726 * It has to be that deep because otherwise we have a conflict on
1727 * const struct dcesrv_interface declaration.
1728 * This is mostly due to socket_wrapper defining #define bind swrap_bind
1729 * which conflict with the bind used before.
1731 #include "system/network.h"
1733 struct dcesrv_sock_reply_state {
1734 struct dcesrv_connection *dce_conn;
1735 struct dcesrv_call_state *call;
1739 static void dcesrv_sock_reply_done(struct tevent_req *subreq);
1740 static void dcesrv_call_terminate_step1(struct tevent_req *subreq);
1742 static void dcesrv_sock_report_output_data(struct dcesrv_connection *dce_conn)
1744 struct dcesrv_call_state *call;
1746 call = dce_conn->call_list;
1747 if (!call || !call->replies) {
1751 while (call->replies) {
1752 struct data_blob_list_item *rep = call->replies;
1753 struct dcesrv_sock_reply_state *substate;
1754 struct tevent_req *subreq;
1756 substate = talloc_zero(call, struct dcesrv_sock_reply_state);
1758 dcesrv_terminate_connection(dce_conn, "no memory");
1762 substate->dce_conn = dce_conn;
1763 substate->call = NULL;
1765 DLIST_REMOVE(call->replies, rep);
1767 if (call->replies == NULL && call->terminate_reason == NULL) {
1768 substate->call = call;
1771 substate->iov.iov_base = (void *) rep->blob.data;
1772 substate->iov.iov_len = rep->blob.length;
1774 subreq = tstream_writev_queue_send(substate,
1775 dce_conn->event_ctx,
1777 dce_conn->send_queue,
1780 dcesrv_terminate_connection(dce_conn, "no memory");
1783 tevent_req_set_callback(subreq, dcesrv_sock_reply_done,
1787 if (call->terminate_reason != NULL) {
1788 struct tevent_req *subreq;
1790 subreq = tevent_queue_wait_send(call,
1791 dce_conn->event_ctx,
1792 dce_conn->send_queue);
1794 dcesrv_terminate_connection(dce_conn, __location__);
1797 tevent_req_set_callback(subreq, dcesrv_call_terminate_step1,
1801 DLIST_REMOVE(call->conn->call_list, call);
1802 call->list = DCESRV_LIST_NONE;
1805 static void dcesrv_sock_reply_done(struct tevent_req *subreq)
1807 struct dcesrv_sock_reply_state *substate = tevent_req_callback_data(subreq,
1808 struct dcesrv_sock_reply_state);
1812 struct dcesrv_call_state *call = substate->call;
1814 ret = tstream_writev_queue_recv(subreq, &sys_errno);
1815 TALLOC_FREE(subreq);
1817 status = map_nt_error_from_unix_common(sys_errno);
1818 dcesrv_terminate_connection(substate->dce_conn, nt_errstr(status));
1822 talloc_free(substate);
1828 static void dcesrv_call_terminate_step2(struct tevent_req *subreq);
1830 static void dcesrv_call_terminate_step1(struct tevent_req *subreq)
1832 struct dcesrv_call_state *call = tevent_req_callback_data(subreq,
1833 struct dcesrv_call_state);
1837 /* make sure we stop send queue before removing subreq */
1838 tevent_queue_stop(call->conn->send_queue);
1840 ok = tevent_queue_wait_recv(subreq);
1841 TALLOC_FREE(subreq);
1843 dcesrv_terminate_connection(call->conn, __location__);
1847 /* disconnect after 200 usecs */
1848 tv = timeval_current_ofs_usec(200);
1849 subreq = tevent_wakeup_send(call, call->conn->event_ctx, tv);
1850 if (subreq == NULL) {
1851 dcesrv_terminate_connection(call->conn, __location__);
1854 tevent_req_set_callback(subreq, dcesrv_call_terminate_step2,
1858 static void dcesrv_call_terminate_step2(struct tevent_req *subreq)
1860 struct dcesrv_call_state *call = tevent_req_callback_data(subreq,
1861 struct dcesrv_call_state);
1864 ok = tevent_wakeup_recv(subreq);
1865 TALLOC_FREE(subreq);
1867 dcesrv_terminate_connection(call->conn, __location__);
1871 dcesrv_terminate_connection(call->conn, call->terminate_reason);
1874 struct dcesrv_socket_context {
1875 const struct dcesrv_endpoint *endpoint;
1876 struct dcesrv_context *dcesrv_ctx;
1880 static void dcesrv_read_fragment_done(struct tevent_req *subreq);
1882 static void dcesrv_sock_accept(struct stream_connection *srv_conn)
1885 struct dcesrv_socket_context *dcesrv_sock =
1886 talloc_get_type(srv_conn->private_data, struct dcesrv_socket_context);
1887 enum dcerpc_transport_t transport =
1888 dcerpc_binding_get_transport(dcesrv_sock->endpoint->ep_description);
1889 struct dcesrv_connection *dcesrv_conn = NULL;
1891 struct tevent_req *subreq;
1892 struct loadparm_context *lp_ctx = dcesrv_sock->dcesrv_ctx->lp_ctx;
1894 dcesrv_cleanup_broken_connections(dcesrv_sock->dcesrv_ctx);
1896 if (!srv_conn->session_info) {
1897 status = auth_anonymous_session_info(srv_conn,
1899 &srv_conn->session_info);
1900 if (!NT_STATUS_IS_OK(status)) {
1901 DEBUG(0,("dcesrv_sock_accept: auth_anonymous_session_info failed: %s\n",
1902 nt_errstr(status)));
1903 stream_terminate_connection(srv_conn, nt_errstr(status));
1908 status = dcesrv_endpoint_connect(dcesrv_sock->dcesrv_ctx,
1910 dcesrv_sock->endpoint,
1911 srv_conn->session_info,
1912 srv_conn->event.ctx,
1914 srv_conn->server_id,
1915 DCESRV_CALL_STATE_FLAG_MAY_ASYNC,
1917 if (!NT_STATUS_IS_OK(status)) {
1918 DEBUG(0,("dcesrv_sock_accept: dcesrv_endpoint_connect failed: %s\n",
1919 nt_errstr(status)));
1920 stream_terminate_connection(srv_conn, nt_errstr(status));
1924 dcesrv_conn->transport.private_data = srv_conn;
1925 dcesrv_conn->transport.report_output_data = dcesrv_sock_report_output_data;
1927 TALLOC_FREE(srv_conn->event.fde);
1929 dcesrv_conn->send_queue = tevent_queue_create(dcesrv_conn, "dcesrv send queue");
1930 if (!dcesrv_conn->send_queue) {
1931 status = NT_STATUS_NO_MEMORY;
1932 DEBUG(0,("dcesrv_sock_accept: tevent_queue_create(%s)\n",
1933 nt_errstr(status)));
1934 stream_terminate_connection(srv_conn, nt_errstr(status));
1938 if (transport == NCACN_NP) {
1939 dcesrv_conn->auth_state.session_key = dcesrv_inherited_session_key;
1940 dcesrv_conn->stream = talloc_move(dcesrv_conn,
1941 &srv_conn->tstream);
1943 ret = tstream_bsd_existing_socket(dcesrv_conn,
1944 socket_get_fd(srv_conn->socket),
1945 &dcesrv_conn->stream);
1947 status = map_nt_error_from_unix_common(errno);
1948 DEBUG(0, ("dcesrv_sock_accept: "
1949 "failed to setup tstream: %s\n",
1950 nt_errstr(status)));
1951 stream_terminate_connection(srv_conn, nt_errstr(status));
1954 socket_set_flags(srv_conn->socket, SOCKET_FLAG_NOCLOSE);
1957 dcesrv_conn->local_address = srv_conn->local_address;
1958 dcesrv_conn->remote_address = srv_conn->remote_address;
1960 if (transport == NCALRPC) {
1964 ret = getpeereid(socket_get_fd(srv_conn->socket), &uid, &gid);
1966 status = map_nt_error_from_unix_common(errno);
1967 DEBUG(0, ("dcesrv_sock_accept: "
1968 "getpeereid() failed for NCALRPC: %s\n",
1969 nt_errstr(status)));
1970 stream_terminate_connection(srv_conn, nt_errstr(status));
1973 if (uid == dcesrv_conn->dce_ctx->initial_euid) {
1974 struct tsocket_address *r = NULL;
1976 ret = tsocket_address_unix_from_path(dcesrv_conn,
1977 "/root/ncalrpc_as_system",
1980 status = map_nt_error_from_unix_common(errno);
1981 DEBUG(0, ("dcesrv_sock_accept: "
1982 "tsocket_address_unix_from_path() failed for NCALRPC: %s\n",
1983 nt_errstr(status)));
1984 stream_terminate_connection(srv_conn, nt_errstr(status));
1987 dcesrv_conn->remote_address = r;
1991 srv_conn->private_data = dcesrv_conn;
1993 irpc_add_name(srv_conn->msg_ctx, "rpc_server");
1995 subreq = dcerpc_read_ncacn_packet_send(dcesrv_conn,
1996 dcesrv_conn->event_ctx,
1997 dcesrv_conn->stream);
1999 status = NT_STATUS_NO_MEMORY;
2000 DEBUG(0,("dcesrv_sock_accept: dcerpc_read_fragment_buffer_send(%s)\n",
2001 nt_errstr(status)));
2002 stream_terminate_connection(srv_conn, nt_errstr(status));
2005 tevent_req_set_callback(subreq, dcesrv_read_fragment_done, dcesrv_conn);
2010 static void dcesrv_read_fragment_done(struct tevent_req *subreq)
2012 struct dcesrv_connection *dce_conn = tevent_req_callback_data(subreq,
2013 struct dcesrv_connection);
2014 struct dcesrv_context *dce_ctx = dce_conn->dce_ctx;
2015 struct ncacn_packet *pkt;
2019 if (dce_conn->terminate) {
2021 * if the current connection is broken
2022 * we need to clean it up before any other connection
2024 dcesrv_terminate_connection(dce_conn, dce_conn->terminate);
2025 dcesrv_cleanup_broken_connections(dce_ctx);
2029 dcesrv_cleanup_broken_connections(dce_ctx);
2031 status = dcerpc_read_ncacn_packet_recv(subreq, dce_conn,
2033 TALLOC_FREE(subreq);
2034 if (!NT_STATUS_IS_OK(status)) {
2035 dcesrv_terminate_connection(dce_conn, nt_errstr(status));
2039 status = dcesrv_process_ncacn_packet(dce_conn, pkt, buffer);
2040 if (!NT_STATUS_IS_OK(status)) {
2041 dcesrv_terminate_connection(dce_conn, nt_errstr(status));
2045 subreq = dcerpc_read_ncacn_packet_send(dce_conn,
2046 dce_conn->event_ctx,
2049 status = NT_STATUS_NO_MEMORY;
2050 dcesrv_terminate_connection(dce_conn, nt_errstr(status));
2053 tevent_req_set_callback(subreq, dcesrv_read_fragment_done, dce_conn);
2056 static void dcesrv_sock_recv(struct stream_connection *conn, uint16_t flags)
2058 struct dcesrv_connection *dce_conn = talloc_get_type(conn->private_data,
2059 struct dcesrv_connection);
2060 dcesrv_terminate_connection(dce_conn, "dcesrv_sock_recv triggered");
2063 static void dcesrv_sock_send(struct stream_connection *conn, uint16_t flags)
2065 struct dcesrv_connection *dce_conn = talloc_get_type(conn->private_data,
2066 struct dcesrv_connection);
2067 dcesrv_terminate_connection(dce_conn, "dcesrv_sock_send triggered");
2071 static const struct stream_server_ops dcesrv_stream_ops = {
2073 .accept_connection = dcesrv_sock_accept,
2074 .recv_handler = dcesrv_sock_recv,
2075 .send_handler = dcesrv_sock_send,
2078 static NTSTATUS dcesrv_add_ep_unix(struct dcesrv_context *dce_ctx,
2079 struct loadparm_context *lp_ctx,
2080 struct dcesrv_endpoint *e,
2081 struct tevent_context *event_ctx, const struct model_ops *model_ops)
2083 struct dcesrv_socket_context *dcesrv_sock;
2086 const char *endpoint;
2088 dcesrv_sock = talloc_zero(event_ctx, struct dcesrv_socket_context);
2089 NT_STATUS_HAVE_NO_MEMORY(dcesrv_sock);
2091 /* remember the endpoint of this socket */
2092 dcesrv_sock->endpoint = e;
2093 dcesrv_sock->dcesrv_ctx = talloc_reference(dcesrv_sock, dce_ctx);
2095 endpoint = dcerpc_binding_get_string_option(e->ep_description, "endpoint");
2097 status = stream_setup_socket(dcesrv_sock, event_ctx, lp_ctx,
2098 model_ops, &dcesrv_stream_ops,
2099 "unix", endpoint, &port,
2100 lpcfg_socket_options(lp_ctx),
2102 if (!NT_STATUS_IS_OK(status)) {
2103 DEBUG(0,("service_setup_stream_socket(path=%s) failed - %s\n",
2104 endpoint, nt_errstr(status)));
2110 static NTSTATUS dcesrv_add_ep_ncalrpc(struct dcesrv_context *dce_ctx,
2111 struct loadparm_context *lp_ctx,
2112 struct dcesrv_endpoint *e,
2113 struct tevent_context *event_ctx, const struct model_ops *model_ops)
2115 struct dcesrv_socket_context *dcesrv_sock;
2119 const char *endpoint;
2121 endpoint = dcerpc_binding_get_string_option(e->ep_description, "endpoint");
2123 if (endpoint == NULL) {
2125 * No identifier specified: use DEFAULT.
2127 * TODO: DO NOT hardcode this value anywhere else. Rather, specify
2128 * no endpoint and let the epmapper worry about it.
2130 endpoint = "DEFAULT";
2131 status = dcerpc_binding_set_string_option(e->ep_description,
2134 if (!NT_STATUS_IS_OK(status)) {
2135 DEBUG(0,("dcerpc_binding_set_string_option() failed - %s\n",
2136 nt_errstr(status)));
2141 full_path = talloc_asprintf(dce_ctx, "%s/%s", lpcfg_ncalrpc_dir(lp_ctx),
2144 dcesrv_sock = talloc_zero(event_ctx, struct dcesrv_socket_context);
2145 NT_STATUS_HAVE_NO_MEMORY(dcesrv_sock);
2147 /* remember the endpoint of this socket */
2148 dcesrv_sock->endpoint = e;
2149 dcesrv_sock->dcesrv_ctx = talloc_reference(dcesrv_sock, dce_ctx);
2151 status = stream_setup_socket(dcesrv_sock, event_ctx, lp_ctx,
2152 model_ops, &dcesrv_stream_ops,
2153 "unix", full_path, &port,
2154 lpcfg_socket_options(lp_ctx),
2156 if (!NT_STATUS_IS_OK(status)) {
2157 DEBUG(0,("service_setup_stream_socket(identifier=%s,path=%s) failed - %s\n",
2158 endpoint, full_path, nt_errstr(status)));
2163 static NTSTATUS dcesrv_add_ep_np(struct dcesrv_context *dce_ctx,
2164 struct loadparm_context *lp_ctx,
2165 struct dcesrv_endpoint *e,
2166 struct tevent_context *event_ctx, const struct model_ops *model_ops)
2168 struct dcesrv_socket_context *dcesrv_sock;
2170 const char *endpoint;
2172 endpoint = dcerpc_binding_get_string_option(e->ep_description, "endpoint");
2173 if (endpoint == NULL) {
2174 DEBUG(0, ("Endpoint mandatory for named pipes\n"));
2175 return NT_STATUS_INVALID_PARAMETER;
2178 dcesrv_sock = talloc_zero(event_ctx, struct dcesrv_socket_context);
2179 NT_STATUS_HAVE_NO_MEMORY(dcesrv_sock);
2181 /* remember the endpoint of this socket */
2182 dcesrv_sock->endpoint = e;
2183 dcesrv_sock->dcesrv_ctx = talloc_reference(dcesrv_sock, dce_ctx);
2185 status = tstream_setup_named_pipe(dce_ctx, event_ctx, lp_ctx,
2186 model_ops, &dcesrv_stream_ops,
2189 if (!NT_STATUS_IS_OK(status)) {
2190 DEBUG(0,("stream_setup_named_pipe(pipe=%s) failed - %s\n",
2191 endpoint, nt_errstr(status)));
2195 return NT_STATUS_OK;
2199 add a socket address to the list of events, one event per dcerpc endpoint
2201 static NTSTATUS add_socket_rpc_tcp_iface(struct dcesrv_context *dce_ctx, struct dcesrv_endpoint *e,
2202 struct tevent_context *event_ctx, const struct model_ops *model_ops,
2203 const char *address)
2205 struct dcesrv_socket_context *dcesrv_sock;
2208 const char *endpoint;
2211 endpoint = dcerpc_binding_get_string_option(e->ep_description, "endpoint");
2212 if (endpoint != NULL) {
2213 port = atoi(endpoint);
2216 dcesrv_sock = talloc_zero(event_ctx, struct dcesrv_socket_context);
2217 NT_STATUS_HAVE_NO_MEMORY(dcesrv_sock);
2219 /* remember the endpoint of this socket */
2220 dcesrv_sock->endpoint = e;
2221 dcesrv_sock->dcesrv_ctx = talloc_reference(dcesrv_sock, dce_ctx);
2223 status = stream_setup_socket(dcesrv_sock, event_ctx, dce_ctx->lp_ctx,
2224 model_ops, &dcesrv_stream_ops,
2225 "ip", address, &port,
2226 lpcfg_socket_options(dce_ctx->lp_ctx),
2228 if (!NT_STATUS_IS_OK(status)) {
2229 DEBUG(0,("service_setup_stream_socket(address=%s,port=%u) failed - %s\n",
2230 address, port, nt_errstr(status)));
2234 snprintf(port_str, sizeof(port_str), "%u", port);
2236 status = dcerpc_binding_set_string_option(e->ep_description,
2237 "endpoint", port_str);
2238 if (!NT_STATUS_IS_OK(status)) {
2239 DEBUG(0,("dcerpc_binding_set_string_option(endpoint, %s) failed - %s\n",
2240 port_str, nt_errstr(status)));
2244 return NT_STATUS_OK;
2247 #include "lib/socket/netif.h" /* Included here to work around the fact that socket_wrapper redefines bind() */
2249 static NTSTATUS dcesrv_add_ep_tcp(struct dcesrv_context *dce_ctx,
2250 struct loadparm_context *lp_ctx,
2251 struct dcesrv_endpoint *e,
2252 struct tevent_context *event_ctx, const struct model_ops *model_ops)
2256 /* Add TCP/IP sockets */
2257 if (lpcfg_interfaces(lp_ctx) && lpcfg_bind_interfaces_only(lp_ctx)) {
2260 struct interface *ifaces;
2262 load_interface_list(dce_ctx, lp_ctx, &ifaces);
2264 num_interfaces = iface_list_count(ifaces);
2265 for(i = 0; i < num_interfaces; i++) {
2266 const char *address = iface_list_n_ip(ifaces, i);
2267 status = add_socket_rpc_tcp_iface(dce_ctx, e, event_ctx, model_ops, address);
2268 NT_STATUS_NOT_OK_RETURN(status);
2274 wcard = iface_list_wildcard(dce_ctx);
2275 NT_STATUS_HAVE_NO_MEMORY(wcard);
2276 for (i=0; wcard[i]; i++) {
2277 status = add_socket_rpc_tcp_iface(dce_ctx, e, event_ctx, model_ops, wcard[i]);
2278 if (NT_STATUS_IS_OK(status)) {
2283 if (num_binds == 0) {
2284 return NT_STATUS_INVALID_PARAMETER_MIX;
2288 return NT_STATUS_OK;
2291 NTSTATUS dcesrv_add_ep(struct dcesrv_context *dce_ctx,
2292 struct loadparm_context *lp_ctx,
2293 struct dcesrv_endpoint *e,
2294 struct tevent_context *event_ctx,
2295 const struct model_ops *model_ops)
2297 enum dcerpc_transport_t transport =
2298 dcerpc_binding_get_transport(e->ep_description);
2300 switch (transport) {
2301 case NCACN_UNIX_STREAM:
2302 return dcesrv_add_ep_unix(dce_ctx, lp_ctx, e, event_ctx, model_ops);
2305 return dcesrv_add_ep_ncalrpc(dce_ctx, lp_ctx, e, event_ctx, model_ops);
2308 return dcesrv_add_ep_tcp(dce_ctx, lp_ctx, e, event_ctx, model_ops);
2311 return dcesrv_add_ep_np(dce_ctx, lp_ctx, e, event_ctx, model_ops);
2314 return NT_STATUS_NOT_SUPPORTED;
2320 * retrieve credentials from a dce_call
2322 _PUBLIC_ struct cli_credentials *dcesrv_call_credentials(struct dcesrv_call_state *dce_call)
2324 return dce_call->conn->auth_state.session_info->credentials;
2328 * returns true if this is an authenticated call
2330 _PUBLIC_ bool dcesrv_call_authenticated(struct dcesrv_call_state *dce_call)
2332 enum security_user_level level;
2333 level = security_session_user_level(dce_call->conn->auth_state.session_info, NULL);
2334 return level >= SECURITY_USER;
2338 * retrieve account_name for a dce_call
2340 _PUBLIC_ const char *dcesrv_call_account_name(struct dcesrv_call_state *dce_call)
2342 return dce_call->context->conn->auth_state.session_info->info->account_name;