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;
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 struct dcesrv_auth *auth = &call->conn->auth_state;
810 TALLOC_FREE(call->context);
812 if (auth->auth_level != DCERPC_AUTH_LEVEL_NONE) {
814 * We only give INVALID_AUTH_TYPE if the auth_level was
817 return dcesrv_bind_nak(call,
818 DCERPC_BIND_NAK_REASON_INVALID_AUTH_TYPE);
820 return dcesrv_bind_nak(call,
821 DCERPC_BIND_NAK_REASON_NOT_SPECIFIED);
824 /* setup a bind_ack */
825 dcesrv_init_hdr(&pkt, lpcfg_rpc_big_endian(call->conn->dce_ctx->lp_ctx));
827 pkt.call_id = call->pkt.call_id;
828 pkt.ptype = DCERPC_PKT_BIND_ACK;
829 pkt.pfc_flags = DCERPC_PFC_FLAG_FIRST | DCERPC_PFC_FLAG_LAST | extra_flags;
830 pkt.u.bind_ack.max_xmit_frag = call->conn->max_xmit_frag;
831 pkt.u.bind_ack.max_recv_frag = call->conn->max_recv_frag;
834 make it possible for iface->bind() to specify the assoc_group_id
835 This helps the openchange mapiproxy plugin to work correctly.
840 pkt.u.bind_ack.assoc_group_id = call->context->assoc_group->id;
842 pkt.u.bind_ack.assoc_group_id = DUMMY_ASSOC_GROUP;
846 endpoint = dcerpc_binding_get_string_option(
847 call->conn->endpoint->ep_description,
851 if (endpoint == NULL) {
855 if (strncasecmp(endpoint, "\\pipe\\", 6) == 0) {
857 * TODO: check if this is really needed
859 * Or if we should fix this in our idl files.
861 ep_prefix = "\\PIPE\\";
865 pkt.u.bind_ack.secondary_address = talloc_asprintf(call, "%s%s",
868 if (pkt.u.bind_ack.secondary_address == NULL) {
869 TALLOC_FREE(call->context);
870 return NT_STATUS_NO_MEMORY;
872 pkt.u.bind_ack.num_results = 1;
873 pkt.u.bind_ack.ctx_list = talloc_zero(call, struct dcerpc_ack_ctx);
874 if (!pkt.u.bind_ack.ctx_list) {
875 talloc_free(call->context);
876 call->context = NULL;
877 return NT_STATUS_NO_MEMORY;
879 pkt.u.bind_ack.ctx_list[0].result = result;
880 pkt.u.bind_ack.ctx_list[0].reason.value = reason;
881 pkt.u.bind_ack.ctx_list[0].syntax = ndr_transfer_syntax_ndr;
882 pkt.u.bind_ack.auth_info = data_blob(NULL, 0);
884 status = dcesrv_auth_bind_ack(call, &pkt);
885 if (!NT_STATUS_IS_OK(status)) {
886 talloc_free(call->context);
887 call->context = NULL;
888 return dcesrv_bind_nak(call, 0);
891 rep = talloc_zero(call, struct data_blob_list_item);
893 talloc_free(call->context);
894 call->context = NULL;
895 return NT_STATUS_NO_MEMORY;
898 status = ncacn_push_auth(&rep->blob, call, &pkt,
899 call->out_auth_info);
900 if (!NT_STATUS_IS_OK(status)) {
901 talloc_free(call->context);
902 call->context = NULL;
906 dcerpc_set_frag_length(&rep->blob, rep->blob.length);
908 DLIST_ADD_END(call->replies, rep);
909 dcesrv_call_set_list(call, DCESRV_LIST_CALL_LIST);
911 if (call->conn->call_list && call->conn->call_list->replies) {
912 if (call->conn->transport.report_output_data) {
913 call->conn->transport.report_output_data(call->conn);
922 handle a auth3 request
924 static NTSTATUS dcesrv_auth3(struct dcesrv_call_state *call)
928 if (!call->conn->allow_auth3) {
929 return dcesrv_fault_disconnect(call, DCERPC_NCA_S_PROTO_ERROR);
932 if (call->conn->auth_state.auth_finished) {
933 return dcesrv_fault_disconnect(call, DCERPC_NCA_S_PROTO_ERROR);
936 status = dcerpc_verify_ncacn_packet_header(&call->pkt,
938 call->pkt.u.auth3.auth_info.length,
939 0, /* required flags */
940 DCERPC_PFC_FLAG_FIRST |
941 DCERPC_PFC_FLAG_LAST |
942 DCERPC_PFC_FLAG_SUPPORT_HEADER_SIGN |
943 0x08 | /* this is not defined, but should be ignored */
944 DCERPC_PFC_FLAG_CONC_MPX |
945 DCERPC_PFC_FLAG_DID_NOT_EXECUTE |
946 DCERPC_PFC_FLAG_MAYBE |
947 DCERPC_PFC_FLAG_OBJECT_UUID);
948 if (!NT_STATUS_IS_OK(status)) {
949 return dcesrv_fault_disconnect(call, DCERPC_NCA_S_PROTO_ERROR);
952 /* handle the auth3 in the auth code */
953 if (!dcesrv_auth_auth3(call)) {
954 call->conn->auth_state.auth_invalid = true;
959 /* we don't send a reply to a auth3 request, except by a
966 handle a bind request
968 static NTSTATUS dcesrv_alter_new_context(struct dcesrv_call_state *call, uint32_t context_id)
970 uint32_t if_version, transfer_syntax_version;
971 struct dcesrv_connection_context *context;
972 const struct dcesrv_interface *iface;
973 struct GUID uuid, *transfer_syntax_uuid;
976 if_version = call->pkt.u.alter.ctx_list[0].abstract_syntax.if_version;
977 uuid = call->pkt.u.alter.ctx_list[0].abstract_syntax.uuid;
979 transfer_syntax_version = call->pkt.u.alter.ctx_list[0].transfer_syntaxes[0].if_version;
980 transfer_syntax_uuid = &call->pkt.u.alter.ctx_list[0].transfer_syntaxes[0].uuid;
981 if (!GUID_equal(transfer_syntax_uuid, &ndr_transfer_syntax_ndr.uuid) ||
982 ndr_transfer_syntax_ndr.if_version != transfer_syntax_version) {
983 /* we only do NDR encoded dcerpc */
984 return NT_STATUS_RPC_PROTSEQ_NOT_SUPPORTED;
987 iface = find_interface_by_uuid(call->conn->endpoint, &uuid, if_version);
989 char *uuid_str = GUID_string(call, &uuid);
990 DEBUG(2,("Request for unknown dcerpc interface %s/%d\n", uuid_str, if_version));
991 talloc_free(uuid_str);
992 return NT_STATUS_RPC_PROTSEQ_NOT_SUPPORTED;
995 /* add this context to the list of available context_ids */
996 context = talloc_zero(call->conn, struct dcesrv_connection_context);
997 if (context == NULL) {
998 return NT_STATUS_NO_MEMORY;
1000 context->conn = call->conn;
1001 context->iface = iface;
1002 context->context_id = context_id;
1003 if (call->pkt.u.alter.assoc_group_id != 0) {
1004 context->assoc_group = dcesrv_assoc_group_reference(context,
1005 call->conn->dce_ctx,
1006 call->pkt.u.alter.assoc_group_id);
1008 context->assoc_group = dcesrv_assoc_group_new(context, call->conn->dce_ctx);
1010 if (context->assoc_group == NULL) {
1011 talloc_free(context);
1012 call->context = NULL;
1013 return NT_STATUS_NO_MEMORY;
1015 context->private_data = NULL;
1016 DLIST_ADD(call->conn->contexts, context);
1017 call->context = context;
1018 talloc_set_destructor(context, dcesrv_connection_context_destructor);
1020 dcesrv_prepare_context_auth(call);
1022 status = iface->bind(call, iface, if_version);
1023 if (!NT_STATUS_IS_OK(status)) {
1024 /* we don't want to trigger the iface->unbind() hook */
1025 context->iface = NULL;
1026 talloc_free(context);
1027 call->context = NULL;
1031 return NT_STATUS_OK;
1034 /* setup and send an alter_resp */
1035 static NTSTATUS dcesrv_alter_resp(struct dcesrv_call_state *call,
1039 struct ncacn_packet pkt;
1040 uint32_t extra_flags = 0;
1041 struct data_blob_list_item *rep = NULL;
1044 dcesrv_init_hdr(&pkt, lpcfg_rpc_big_endian(call->conn->dce_ctx->lp_ctx));
1045 pkt.auth_length = 0;
1046 pkt.call_id = call->pkt.call_id;
1047 pkt.ptype = DCERPC_PKT_ALTER_RESP;
1049 if ((call->pkt.pfc_flags & DCERPC_PFC_FLAG_CONC_MPX) &&
1050 call->context->conn->state_flags &
1051 DCESRV_CALL_STATE_FLAG_MULTIPLEXED) {
1052 extra_flags |= DCERPC_PFC_FLAG_CONC_MPX;
1054 if (call->state_flags & DCESRV_CALL_STATE_FLAG_PROCESS_PENDING_CALL) {
1055 call->context->conn->state_flags |=
1056 DCESRV_CALL_STATE_FLAG_PROCESS_PENDING_CALL;
1059 pkt.pfc_flags = DCERPC_PFC_FLAG_FIRST | DCERPC_PFC_FLAG_LAST | extra_flags;
1060 pkt.u.alter_resp.max_xmit_frag = call->conn->max_xmit_frag;
1061 pkt.u.alter_resp.max_recv_frag = call->conn->max_recv_frag;
1063 pkt.u.alter_resp.assoc_group_id = call->context->assoc_group->id;
1065 pkt.u.alter_resp.assoc_group_id = 0;
1067 pkt.u.alter_resp.num_results = 1;
1068 pkt.u.alter_resp.ctx_list = talloc_zero(call, struct dcerpc_ack_ctx);
1069 if (!pkt.u.alter_resp.ctx_list) {
1070 return NT_STATUS_NO_MEMORY;
1072 pkt.u.alter_resp.ctx_list[0].result = result;
1073 pkt.u.alter_resp.ctx_list[0].reason.value = reason;
1074 pkt.u.alter_resp.ctx_list[0].syntax = ndr_transfer_syntax_ndr;
1075 pkt.u.alter_resp.auth_info = data_blob(NULL, 0);
1076 pkt.u.alter_resp.secondary_address = "";
1078 status = dcesrv_auth_alter_ack(call, &pkt);
1079 if (!NT_STATUS_IS_OK(status)) {
1080 return dcesrv_fault_disconnect(call, DCERPC_FAULT_SEC_PKG_ERROR);
1083 rep = talloc_zero(call, struct data_blob_list_item);
1085 return NT_STATUS_NO_MEMORY;
1088 status = ncacn_push_auth(&rep->blob, call, &pkt, call->out_auth_info);
1089 if (!NT_STATUS_IS_OK(status)) {
1093 dcerpc_set_frag_length(&rep->blob, rep->blob.length);
1095 DLIST_ADD_END(call->replies, rep);
1096 dcesrv_call_set_list(call, DCESRV_LIST_CALL_LIST);
1098 if (call->conn->call_list && call->conn->call_list->replies) {
1099 if (call->conn->transport.report_output_data) {
1100 call->conn->transport.report_output_data(call->conn);
1104 return NT_STATUS_OK;
1108 handle a alter context request
1110 static NTSTATUS dcesrv_alter(struct dcesrv_call_state *call)
1113 const struct dcerpc_ctx_list *ctx = NULL;
1114 bool auth_ok = false;
1116 if (!call->conn->allow_alter) {
1117 return dcesrv_fault_disconnect(call, DCERPC_NCA_S_PROTO_ERROR);
1120 status = dcerpc_verify_ncacn_packet_header(&call->pkt,
1122 call->pkt.u.alter.auth_info.length,
1123 0, /* required flags */
1124 DCERPC_PFC_FLAG_FIRST |
1125 DCERPC_PFC_FLAG_LAST |
1126 DCERPC_PFC_FLAG_SUPPORT_HEADER_SIGN |
1127 0x08 | /* this is not defined, but should be ignored */
1128 DCERPC_PFC_FLAG_CONC_MPX |
1129 DCERPC_PFC_FLAG_DID_NOT_EXECUTE |
1130 DCERPC_PFC_FLAG_MAYBE |
1131 DCERPC_PFC_FLAG_OBJECT_UUID);
1132 if (!NT_STATUS_IS_OK(status)) {
1133 return dcesrv_fault_disconnect(call, DCERPC_NCA_S_PROTO_ERROR);
1136 auth_ok = dcesrv_auth_alter(call);
1138 if (call->in_auth_info.auth_type == DCERPC_AUTH_TYPE_NONE) {
1139 return dcesrv_fault_disconnect(call,
1140 DCERPC_FAULT_ACCESS_DENIED);
1144 if (call->pkt.u.alter.num_contexts < 1) {
1145 return dcesrv_fault_disconnect(call, DCERPC_NCA_S_PROTO_ERROR);
1147 ctx = &call->pkt.u.alter.ctx_list[0];
1148 if (ctx->num_transfer_syntaxes < 1) {
1149 return dcesrv_fault_disconnect(call, DCERPC_NCA_S_PROTO_ERROR);
1152 /* see if they are asking for a new interface */
1153 call->context = dcesrv_find_context(call->conn, ctx->context_id);
1154 if (!call->context) {
1155 status = dcesrv_alter_new_context(call, ctx->context_id);
1156 if (!NT_STATUS_IS_OK(status)) {
1157 return dcesrv_alter_resp(call,
1158 DCERPC_BIND_PROVIDER_REJECT,
1159 DCERPC_BIND_REASON_ASYNTAX);
1164 ok = ndr_syntax_id_equal(&ctx->abstract_syntax,
1165 &call->context->iface->syntax_id);
1167 return dcesrv_fault_disconnect(call,
1168 DCERPC_NCA_S_PROTO_ERROR);
1171 if (ctx->num_transfer_syntaxes != 1) {
1172 return dcesrv_fault_disconnect(call,
1173 DCERPC_NCA_S_PROTO_ERROR);
1176 ok = ndr_syntax_id_equal(&ctx->transfer_syntaxes[0],
1177 &ndr_transfer_syntax_ndr);
1179 return dcesrv_fault_disconnect(call,
1180 DCERPC_NCA_S_PROTO_ERROR);
1184 if (call->pkt.u.alter.assoc_group_id != 0 &&
1185 lpcfg_parm_bool(call->conn->dce_ctx->lp_ctx, NULL, "dcesrv","assoc group checking", true) &&
1186 call->pkt.u.alter.assoc_group_id != call->context->assoc_group->id) {
1187 DEBUG(0,(__location__ ": Failed attempt to use new assoc_group in alter context (0x%08x 0x%08x)\n",
1188 call->context->assoc_group->id, call->pkt.u.alter.assoc_group_id));
1189 /* TODO: can they ask for a new association group? */
1190 return dcesrv_alter_resp(call,
1191 DCERPC_BIND_PROVIDER_REJECT,
1192 DCERPC_BIND_REASON_ASYNTAX);
1195 /* handle any authentication that is being requested */
1197 if (call->in_auth_info.auth_type !=
1198 call->conn->auth_state.auth_type)
1200 return dcesrv_fault_disconnect(call,
1201 DCERPC_FAULT_SEC_PKG_ERROR);
1203 return dcesrv_fault_disconnect(call, DCERPC_FAULT_ACCESS_DENIED);
1206 return dcesrv_alter_resp(call,
1207 DCERPC_BIND_ACK_RESULT_ACCEPTANCE,
1208 DCERPC_BIND_ACK_REASON_NOT_SPECIFIED);
1212 possibly save the call for inspection with ndrdump
1214 static void dcesrv_save_call(struct dcesrv_call_state *call, const char *why)
1218 const char *dump_dir;
1219 dump_dir = lpcfg_parm_string(call->conn->dce_ctx->lp_ctx, NULL, "dcesrv", "stubs directory");
1223 fname = talloc_asprintf(call, "%s/RPC-%s-%u-%s.dat",
1225 call->context->iface->name,
1226 call->pkt.u.request.opnum,
1228 if (file_save(fname, call->pkt.u.request.stub_and_verifier.data, call->pkt.u.request.stub_and_verifier.length)) {
1229 DEBUG(0,("RPC SAVED %s\n", fname));
1235 static NTSTATUS dcesrv_check_verification_trailer(struct dcesrv_call_state *call)
1237 TALLOC_CTX *frame = talloc_stackframe();
1238 const uint32_t bitmask1 = call->conn->auth_state.client_hdr_signing ?
1239 DCERPC_SEC_VT_CLIENT_SUPPORTS_HEADER_SIGNING : 0;
1240 const struct dcerpc_sec_vt_pcontext pcontext = {
1241 .abstract_syntax = call->context->iface->syntax_id,
1242 .transfer_syntax = ndr_transfer_syntax_ndr,
1244 const struct dcerpc_sec_vt_header2 header2 =
1245 dcerpc_sec_vt_header2_from_ncacn_packet(&call->pkt);
1246 enum ndr_err_code ndr_err;
1247 struct dcerpc_sec_verification_trailer *vt = NULL;
1248 NTSTATUS status = NT_STATUS_OK;
1251 SMB_ASSERT(call->pkt.ptype == DCERPC_PKT_REQUEST);
1253 ndr_err = ndr_pop_dcerpc_sec_verification_trailer(call->ndr_pull,
1255 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
1256 status = ndr_map_error2ntstatus(ndr_err);
1260 ok = dcerpc_sec_verification_trailer_check(vt, &bitmask1,
1261 &pcontext, &header2);
1263 status = NT_STATUS_ACCESS_DENIED;
1272 handle a dcerpc request packet
1274 static NTSTATUS dcesrv_request(struct dcesrv_call_state *call)
1276 const struct dcesrv_endpoint *endpoint = call->conn->endpoint;
1277 enum dcerpc_transport_t transport =
1278 dcerpc_binding_get_transport(endpoint->ep_description);
1279 struct ndr_pull *pull;
1281 struct dcesrv_connection_context *context;
1283 if (!call->conn->allow_request) {
1284 return dcesrv_fault_disconnect(call, DCERPC_NCA_S_PROTO_ERROR);
1287 /* if authenticated, and the mech we use can't do async replies, don't use them... */
1288 if (call->conn->auth_state.gensec_security &&
1289 !gensec_have_feature(call->conn->auth_state.gensec_security, GENSEC_FEATURE_ASYNC_REPLIES)) {
1290 call->state_flags &= ~DCESRV_CALL_STATE_FLAG_MAY_ASYNC;
1293 context = dcesrv_find_context(call->conn, call->pkt.u.request.context_id);
1294 if (context == NULL) {
1295 return dcesrv_fault(call, DCERPC_FAULT_UNK_IF);
1298 switch (call->conn->auth_state.auth_level) {
1299 case DCERPC_AUTH_LEVEL_NONE:
1300 case DCERPC_AUTH_LEVEL_INTEGRITY:
1301 case DCERPC_AUTH_LEVEL_PRIVACY:
1304 if (!context->allow_connect) {
1307 addr = tsocket_address_string(call->conn->remote_address,
1310 DEBUG(2, ("%s: restrict auth_level_connect access "
1311 "to [%s] with auth[type=0x%x,level=0x%x] "
1312 "on [%s] from [%s]\n",
1313 __func__, context->iface->name,
1314 call->conn->auth_state.auth_type,
1315 call->conn->auth_state.auth_level,
1316 derpc_transport_string_by_transport(transport),
1318 return dcesrv_fault(call, DCERPC_FAULT_ACCESS_DENIED);
1323 if (call->conn->auth_state.auth_level < context->min_auth_level) {
1326 addr = tsocket_address_string(call->conn->remote_address, call);
1328 DEBUG(2, ("%s: restrict access by min_auth_level[0x%x] "
1329 "to [%s] with auth[type=0x%x,level=0x%x] "
1330 "on [%s] from [%s]\n",
1332 context->min_auth_level,
1333 context->iface->name,
1334 call->conn->auth_state.auth_type,
1335 call->conn->auth_state.auth_level,
1336 derpc_transport_string_by_transport(transport),
1338 return dcesrv_fault(call, DCERPC_FAULT_ACCESS_DENIED);
1341 pull = ndr_pull_init_blob(&call->pkt.u.request.stub_and_verifier, call);
1342 NT_STATUS_HAVE_NO_MEMORY(pull);
1344 pull->flags |= LIBNDR_FLAG_REF_ALLOC;
1346 call->context = context;
1347 call->ndr_pull = pull;
1349 if (!(call->pkt.drep[0] & DCERPC_DREP_LE)) {
1350 pull->flags |= LIBNDR_FLAG_BIGENDIAN;
1353 status = dcesrv_check_verification_trailer(call);
1354 if (!NT_STATUS_IS_OK(status)) {
1355 uint32_t faultcode = DCERPC_FAULT_OTHER;
1356 if (NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
1357 faultcode = DCERPC_FAULT_ACCESS_DENIED;
1359 DEBUG(10, ("dcesrv_check_verification_trailer failed: %s\n",
1360 nt_errstr(status)));
1361 return dcesrv_fault(call, faultcode);
1364 /* unravel the NDR for the packet */
1365 status = context->iface->ndr_pull(call, call, pull, &call->r);
1366 if (!NT_STATUS_IS_OK(status)) {
1367 if (call->fault_code == DCERPC_FAULT_OP_RNG_ERROR) {
1368 /* we got an unknown call */
1369 DEBUG(3,(__location__ ": Unknown RPC call %u on %s\n",
1370 call->pkt.u.request.opnum, context->iface->name));
1371 dcesrv_save_call(call, "unknown");
1373 dcesrv_save_call(call, "pullfail");
1375 return dcesrv_fault(call, call->fault_code);
1378 if (pull->offset != pull->data_size) {
1379 dcesrv_save_call(call, "extrabytes");
1380 DEBUG(3,("Warning: %d extra bytes in incoming RPC request\n",
1381 pull->data_size - pull->offset));
1384 /* call the dispatch function */
1385 status = context->iface->dispatch(call, call, call->r);
1386 if (!NT_STATUS_IS_OK(status)) {
1387 DEBUG(5,("dcerpc fault in call %s:%02x - %s\n",
1388 context->iface->name,
1389 call->pkt.u.request.opnum,
1390 dcerpc_errstr(pull, call->fault_code)));
1391 return dcesrv_fault(call, call->fault_code);
1394 /* add the call to the pending list */
1395 dcesrv_call_set_list(call, DCESRV_LIST_PENDING_CALL_LIST);
1397 if (call->state_flags & DCESRV_CALL_STATE_FLAG_ASYNC) {
1398 return NT_STATUS_OK;
1401 return dcesrv_reply(call);
1406 remove the call from the right list when freed
1408 static int dcesrv_call_dequeue(struct dcesrv_call_state *call)
1410 dcesrv_call_set_list(call, DCESRV_LIST_NONE);
1414 _PUBLIC_ const struct tsocket_address *dcesrv_connection_get_local_address(struct dcesrv_connection *conn)
1416 return conn->local_address;
1419 _PUBLIC_ const struct tsocket_address *dcesrv_connection_get_remote_address(struct dcesrv_connection *conn)
1421 return conn->remote_address;
1425 process some input to a dcerpc endpoint server.
1427 static NTSTATUS dcesrv_process_ncacn_packet(struct dcesrv_connection *dce_conn,
1428 struct ncacn_packet *pkt,
1432 struct dcesrv_call_state *call;
1434 call = talloc_zero(dce_conn, struct dcesrv_call_state);
1436 data_blob_free(&blob);
1438 return NT_STATUS_NO_MEMORY;
1440 call->conn = dce_conn;
1441 call->event_ctx = dce_conn->event_ctx;
1442 call->msg_ctx = dce_conn->msg_ctx;
1443 call->state_flags = call->conn->state_flags;
1444 call->time = timeval_current();
1445 call->list = DCESRV_LIST_NONE;
1447 talloc_steal(call, pkt);
1448 talloc_steal(call, blob.data);
1451 talloc_set_destructor(call, dcesrv_call_dequeue);
1453 if (call->conn->allow_bind) {
1455 * Only one bind is possible per connection
1457 call->conn->allow_bind = false;
1458 return dcesrv_bind(call);
1461 /* we have to check the signing here, before combining the
1463 if (call->pkt.ptype == DCERPC_PKT_REQUEST) {
1464 if (!call->conn->allow_request) {
1465 return dcesrv_fault_disconnect(call,
1466 DCERPC_NCA_S_PROTO_ERROR);
1469 status = dcerpc_verify_ncacn_packet_header(&call->pkt,
1471 call->pkt.u.request.stub_and_verifier.length,
1472 0, /* required_flags */
1473 DCERPC_PFC_FLAG_FIRST |
1474 DCERPC_PFC_FLAG_LAST |
1475 DCERPC_PFC_FLAG_PENDING_CANCEL |
1476 0x08 | /* this is not defined, but should be ignored */
1477 DCERPC_PFC_FLAG_CONC_MPX |
1478 DCERPC_PFC_FLAG_DID_NOT_EXECUTE |
1479 DCERPC_PFC_FLAG_MAYBE |
1480 DCERPC_PFC_FLAG_OBJECT_UUID);
1481 if (!NT_STATUS_IS_OK(status)) {
1482 return dcesrv_fault_disconnect(call,
1483 DCERPC_NCA_S_PROTO_ERROR);
1486 if (call->pkt.frag_length > DCERPC_FRAG_MAX_SIZE) {
1488 * We don't use dcesrv_fault_disconnect()
1489 * here, because we don't want to set
1490 * DCERPC_PFC_FLAG_DID_NOT_EXECUTE
1492 * Note that we don't check against the negotiated
1493 * max_recv_frag, but a hard coded value.
1495 dcesrv_call_disconnect_after(call,
1496 "dcesrv_auth_request - frag_length too large");
1497 return dcesrv_fault(call,
1498 DCERPC_NCA_S_PROTO_ERROR);
1501 if (!dcesrv_auth_request(call, &blob)) {
1503 * We don't use dcesrv_fault_disconnect()
1504 * here, because we don't want to set
1505 * DCERPC_PFC_FLAG_DID_NOT_EXECUTE
1507 dcesrv_call_disconnect_after(call,
1508 "dcesrv_auth_request - failed");
1509 return dcesrv_fault(call, DCERPC_FAULT_ACCESS_DENIED);
1513 /* see if this is a continued packet */
1514 if (call->pkt.ptype == DCERPC_PKT_REQUEST &&
1515 !(call->pkt.pfc_flags & DCERPC_PFC_FLAG_FIRST)) {
1516 struct dcesrv_call_state *call2 = call;
1521 /* this is a continuation of an existing call - find the call
1522 then tack it on the end */
1523 call = dcesrv_find_fragmented_call(dce_conn, call2->pkt.call_id);
1525 return dcesrv_fault_disconnect(call2,
1526 DCERPC_NCA_S_PROTO_ERROR);
1529 if (call->pkt.ptype != call2->pkt.ptype) {
1530 /* trying to play silly buggers are we? */
1531 return dcesrv_fault_disconnect(call,
1532 DCERPC_NCA_S_PROTO_ERROR);
1534 if (memcmp(call->pkt.drep, call2->pkt.drep, sizeof(pkt->drep)) != 0) {
1535 return dcesrv_fault_disconnect(call,
1536 DCERPC_NCA_S_PROTO_ERROR);
1538 if (call->pkt.call_id != call2->pkt.call_id) {
1539 return dcesrv_fault_disconnect(call,
1540 DCERPC_NCA_S_PROTO_ERROR);
1542 if (call->pkt.u.request.context_id != call2->pkt.u.request.context_id) {
1543 return dcesrv_fault_disconnect(call,
1544 DCERPC_NCA_S_PROTO_ERROR);
1546 if (call->pkt.u.request.opnum != call2->pkt.u.request.opnum) {
1547 return dcesrv_fault_disconnect(call,
1548 DCERPC_NCA_S_PROTO_ERROR);
1552 * Up to 4 MByte are allowed by all fragments
1554 available = DCERPC_NCACN_PAYLOAD_MAX_SIZE;
1555 if (call->pkt.u.request.stub_and_verifier.length > available) {
1556 dcesrv_call_disconnect_after(call,
1557 "dcesrv_auth_request - current payload too large");
1558 return dcesrv_fault(call, DCERPC_FAULT_ACCESS_DENIED);
1560 available -= call->pkt.u.request.stub_and_verifier.length;
1561 if (call2->pkt.u.request.alloc_hint > available) {
1562 dcesrv_call_disconnect_after(call,
1563 "dcesrv_auth_request - alloc hint too large");
1564 return dcesrv_fault(call, DCERPC_FAULT_ACCESS_DENIED);
1566 if (call2->pkt.u.request.stub_and_verifier.length > available) {
1567 dcesrv_call_disconnect_after(call,
1568 "dcesrv_auth_request - new payload too large");
1569 return dcesrv_fault(call, DCERPC_FAULT_ACCESS_DENIED);
1571 alloc_hint = call->pkt.u.request.stub_and_verifier.length +
1572 call2->pkt.u.request.alloc_hint;
1573 /* allocate at least 1 byte */
1574 alloc_hint = MAX(alloc_hint, 1);
1575 alloc_size = call->pkt.u.request.stub_and_verifier.length +
1576 call2->pkt.u.request.stub_and_verifier.length;
1577 alloc_size = MAX(alloc_size, alloc_hint);
1579 call->pkt.u.request.stub_and_verifier.data =
1580 talloc_realloc(call,
1581 call->pkt.u.request.stub_and_verifier.data,
1582 uint8_t, alloc_size);
1583 if (!call->pkt.u.request.stub_and_verifier.data) {
1585 return dcesrv_fault_with_flags(call,
1586 DCERPC_FAULT_OUT_OF_RESOURCES,
1587 DCERPC_PFC_FLAG_DID_NOT_EXECUTE);
1589 memcpy(call->pkt.u.request.stub_and_verifier.data +
1590 call->pkt.u.request.stub_and_verifier.length,
1591 call2->pkt.u.request.stub_and_verifier.data,
1592 call2->pkt.u.request.stub_and_verifier.length);
1593 call->pkt.u.request.stub_and_verifier.length +=
1594 call2->pkt.u.request.stub_and_verifier.length;
1596 call->pkt.pfc_flags |= (call2->pkt.pfc_flags & DCERPC_PFC_FLAG_LAST);
1601 /* this may not be the last pdu in the chain - if its isn't then
1602 just put it on the incoming_fragmented_call_list and wait for the rest */
1603 if (call->pkt.ptype == DCERPC_PKT_REQUEST &&
1604 !(call->pkt.pfc_flags & DCERPC_PFC_FLAG_LAST)) {
1606 * Up to 4 MByte are allowed by all fragments
1608 if (call->pkt.u.request.alloc_hint > DCERPC_NCACN_PAYLOAD_MAX_SIZE) {
1609 dcesrv_call_disconnect_after(call,
1610 "dcesrv_auth_request - initial alloc hint too large");
1611 return dcesrv_fault(call, DCERPC_FAULT_ACCESS_DENIED);
1613 dcesrv_call_set_list(call, DCESRV_LIST_FRAGMENTED_CALL_LIST);
1614 return NT_STATUS_OK;
1617 /* This removes any fragments we may have had stashed away */
1618 dcesrv_call_set_list(call, DCESRV_LIST_NONE);
1620 switch (call->pkt.ptype) {
1621 case DCERPC_PKT_BIND:
1622 status = dcesrv_bind_nak(call,
1623 DCERPC_BIND_NAK_REASON_NOT_SPECIFIED);
1625 case DCERPC_PKT_AUTH3:
1626 status = dcesrv_auth3(call);
1628 case DCERPC_PKT_ALTER:
1629 status = dcesrv_alter(call);
1631 case DCERPC_PKT_REQUEST:
1632 status = dcesrv_request(call);
1635 status = dcesrv_fault_disconnect(call, DCERPC_NCA_S_PROTO_ERROR);
1639 /* if we are going to be sending a reply then add
1640 it to the list of pending calls. We add it to the end to keep the call
1641 list in the order we will answer */
1642 if (!NT_STATUS_IS_OK(status)) {
1649 _PUBLIC_ NTSTATUS dcesrv_init_context(TALLOC_CTX *mem_ctx,
1650 struct loadparm_context *lp_ctx,
1651 const char **endpoint_servers, struct dcesrv_context **_dce_ctx)
1654 struct dcesrv_context *dce_ctx;
1657 if (!endpoint_servers) {
1658 DEBUG(0,("dcesrv_init_context: no endpoint servers configured\n"));
1659 return NT_STATUS_INTERNAL_ERROR;
1662 dce_ctx = talloc_zero(mem_ctx, struct dcesrv_context);
1663 NT_STATUS_HAVE_NO_MEMORY(dce_ctx);
1665 if (uid_wrapper_enabled()) {
1666 setenv("UID_WRAPPER_MYUID", "1", 1);
1668 dce_ctx->initial_euid = geteuid();
1669 if (uid_wrapper_enabled()) {
1670 unsetenv("UID_WRAPPER_MYUID");
1673 dce_ctx->endpoint_list = NULL;
1674 dce_ctx->lp_ctx = lp_ctx;
1675 dce_ctx->assoc_groups_idr = idr_init(dce_ctx);
1676 NT_STATUS_HAVE_NO_MEMORY(dce_ctx->assoc_groups_idr);
1677 dce_ctx->broken_connections = NULL;
1679 for (i=0;endpoint_servers[i];i++) {
1680 const struct dcesrv_endpoint_server *ep_server;
1682 ep_server = dcesrv_ep_server_byname(endpoint_servers[i]);
1684 DEBUG(0,("dcesrv_init_context: failed to find endpoint server = '%s'\n", endpoint_servers[i]));
1685 return NT_STATUS_INTERNAL_ERROR;
1688 status = ep_server->init_server(dce_ctx, ep_server);
1689 if (!NT_STATUS_IS_OK(status)) {
1690 DEBUG(0,("dcesrv_init_context: failed to init endpoint server = '%s': %s\n", endpoint_servers[i],
1691 nt_errstr(status)));
1696 *_dce_ctx = dce_ctx;
1697 return NT_STATUS_OK;
1700 /* the list of currently registered DCERPC endpoint servers.
1702 static struct ep_server {
1703 struct dcesrv_endpoint_server *ep_server;
1704 } *ep_servers = NULL;
1705 static int num_ep_servers;
1708 register a DCERPC endpoint server.
1710 The 'name' can be later used by other backends to find the operations
1711 structure for this backend.
1713 The 'type' is used to specify whether this is for a disk, printer or IPC$ share
1715 _PUBLIC_ NTSTATUS dcerpc_register_ep_server(const void *_ep_server)
1717 const struct dcesrv_endpoint_server *ep_server = _ep_server;
1719 if (dcesrv_ep_server_byname(ep_server->name) != NULL) {
1720 /* its already registered! */
1721 DEBUG(0,("DCERPC endpoint server '%s' already registered\n",
1723 return NT_STATUS_OBJECT_NAME_COLLISION;
1726 ep_servers = realloc_p(ep_servers, struct ep_server, num_ep_servers+1);
1728 smb_panic("out of memory in dcerpc_register");
1731 ep_servers[num_ep_servers].ep_server = smb_xmemdup(ep_server, sizeof(*ep_server));
1732 ep_servers[num_ep_servers].ep_server->name = smb_xstrdup(ep_server->name);
1736 DEBUG(3,("DCERPC endpoint server '%s' registered\n",
1739 return NT_STATUS_OK;
1743 return the operations structure for a named backend of the specified type
1745 const struct dcesrv_endpoint_server *dcesrv_ep_server_byname(const char *name)
1749 for (i=0;i<num_ep_servers;i++) {
1750 if (strcmp(ep_servers[i].ep_server->name, name) == 0) {
1751 return ep_servers[i].ep_server;
1758 void dcerpc_server_init(struct loadparm_context *lp_ctx)
1760 static bool initialized;
1761 #define _MODULE_PROTO(init) extern NTSTATUS init(void);
1762 STATIC_dcerpc_server_MODULES_PROTO;
1763 init_module_fn static_init[] = { STATIC_dcerpc_server_MODULES };
1764 init_module_fn *shared_init;
1771 shared_init = load_samba_modules(NULL, "dcerpc_server");
1773 run_init_functions(static_init);
1774 run_init_functions(shared_init);
1776 talloc_free(shared_init);
1780 return the DCERPC module version, and the size of some critical types
1781 This can be used by endpoint server modules to either detect compilation errors, or provide
1782 multiple implementations for different smbd compilation options in one module
1784 const struct dcesrv_critical_sizes *dcerpc_module_version(void)
1786 static const struct dcesrv_critical_sizes critical_sizes = {
1787 DCERPC_MODULE_VERSION,
1788 sizeof(struct dcesrv_context),
1789 sizeof(struct dcesrv_endpoint),
1790 sizeof(struct dcesrv_endpoint_server),
1791 sizeof(struct dcesrv_interface),
1792 sizeof(struct dcesrv_if_list),
1793 sizeof(struct dcesrv_connection),
1794 sizeof(struct dcesrv_call_state),
1795 sizeof(struct dcesrv_auth),
1796 sizeof(struct dcesrv_handle)
1799 return &critical_sizes;
1802 static void dcesrv_terminate_connection(struct dcesrv_connection *dce_conn, const char *reason)
1804 struct dcesrv_context *dce_ctx = dce_conn->dce_ctx;
1805 struct stream_connection *srv_conn;
1806 srv_conn = talloc_get_type(dce_conn->transport.private_data,
1807 struct stream_connection);
1809 dce_conn->allow_bind = false;
1810 dce_conn->allow_auth3 = false;
1811 dce_conn->allow_alter = false;
1812 dce_conn->allow_request = false;
1814 if (dce_conn->pending_call_list == NULL) {
1815 char *full_reason = talloc_asprintf(dce_conn, "dcesrv: %s", reason);
1817 DLIST_REMOVE(dce_ctx->broken_connections, dce_conn);
1818 stream_terminate_connection(srv_conn, full_reason ? full_reason : reason);
1822 if (dce_conn->terminate != NULL) {
1826 DEBUG(3,("dcesrv: terminating connection due to '%s' defered due to pending calls\n",
1828 dce_conn->terminate = talloc_strdup(dce_conn, reason);
1829 if (dce_conn->terminate == NULL) {
1830 dce_conn->terminate = "dcesrv: defered terminating connection - no memory";
1832 DLIST_ADD_END(dce_ctx->broken_connections, dce_conn);
1835 static void dcesrv_cleanup_broken_connections(struct dcesrv_context *dce_ctx)
1837 struct dcesrv_connection *cur, *next;
1839 next = dce_ctx->broken_connections;
1840 while (next != NULL) {
1844 if (cur->state_flags & DCESRV_CALL_STATE_FLAG_PROCESS_PENDING_CALL) {
1845 struct dcesrv_connection_context *context_cur, *context_next;
1847 context_next = cur->contexts;
1848 while (context_next != NULL) {
1849 context_cur = context_next;
1850 context_next = context_cur->next;
1852 dcesrv_connection_context_destructor(context_cur);
1856 dcesrv_terminate_connection(cur, cur->terminate);
1860 /* We need this include to be able to compile on some plateforms
1861 * (ie. freebsd 7.2) as it seems that <sys/uio.h> is not included
1863 * It has to be that deep because otherwise we have a conflict on
1864 * const struct dcesrv_interface declaration.
1865 * This is mostly due to socket_wrapper defining #define bind swrap_bind
1866 * which conflict with the bind used before.
1868 #include "system/network.h"
1870 struct dcesrv_sock_reply_state {
1871 struct dcesrv_connection *dce_conn;
1872 struct dcesrv_call_state *call;
1876 static void dcesrv_sock_reply_done(struct tevent_req *subreq);
1877 static void dcesrv_call_terminate_step1(struct tevent_req *subreq);
1879 static void dcesrv_sock_report_output_data(struct dcesrv_connection *dce_conn)
1881 struct dcesrv_call_state *call;
1883 call = dce_conn->call_list;
1884 if (!call || !call->replies) {
1888 while (call->replies) {
1889 struct data_blob_list_item *rep = call->replies;
1890 struct dcesrv_sock_reply_state *substate;
1891 struct tevent_req *subreq;
1893 substate = talloc_zero(call, struct dcesrv_sock_reply_state);
1895 dcesrv_terminate_connection(dce_conn, "no memory");
1899 substate->dce_conn = dce_conn;
1900 substate->call = NULL;
1902 DLIST_REMOVE(call->replies, rep);
1904 if (call->replies == NULL && call->terminate_reason == NULL) {
1905 substate->call = call;
1908 substate->iov.iov_base = (void *) rep->blob.data;
1909 substate->iov.iov_len = rep->blob.length;
1911 subreq = tstream_writev_queue_send(substate,
1912 dce_conn->event_ctx,
1914 dce_conn->send_queue,
1917 dcesrv_terminate_connection(dce_conn, "no memory");
1920 tevent_req_set_callback(subreq, dcesrv_sock_reply_done,
1924 if (call->terminate_reason != NULL) {
1925 struct tevent_req *subreq;
1927 subreq = tevent_queue_wait_send(call,
1928 dce_conn->event_ctx,
1929 dce_conn->send_queue);
1931 dcesrv_terminate_connection(dce_conn, __location__);
1934 tevent_req_set_callback(subreq, dcesrv_call_terminate_step1,
1938 DLIST_REMOVE(call->conn->call_list, call);
1939 call->list = DCESRV_LIST_NONE;
1942 static void dcesrv_sock_reply_done(struct tevent_req *subreq)
1944 struct dcesrv_sock_reply_state *substate = tevent_req_callback_data(subreq,
1945 struct dcesrv_sock_reply_state);
1949 struct dcesrv_call_state *call = substate->call;
1951 ret = tstream_writev_queue_recv(subreq, &sys_errno);
1952 TALLOC_FREE(subreq);
1954 status = map_nt_error_from_unix_common(sys_errno);
1955 dcesrv_terminate_connection(substate->dce_conn, nt_errstr(status));
1959 talloc_free(substate);
1965 static void dcesrv_call_terminate_step2(struct tevent_req *subreq);
1967 static void dcesrv_call_terminate_step1(struct tevent_req *subreq)
1969 struct dcesrv_call_state *call = tevent_req_callback_data(subreq,
1970 struct dcesrv_call_state);
1974 /* make sure we stop send queue before removing subreq */
1975 tevent_queue_stop(call->conn->send_queue);
1977 ok = tevent_queue_wait_recv(subreq);
1978 TALLOC_FREE(subreq);
1980 dcesrv_terminate_connection(call->conn, __location__);
1984 /* disconnect after 200 usecs */
1985 tv = timeval_current_ofs_usec(200);
1986 subreq = tevent_wakeup_send(call, call->conn->event_ctx, tv);
1987 if (subreq == NULL) {
1988 dcesrv_terminate_connection(call->conn, __location__);
1991 tevent_req_set_callback(subreq, dcesrv_call_terminate_step2,
1995 static void dcesrv_call_terminate_step2(struct tevent_req *subreq)
1997 struct dcesrv_call_state *call = tevent_req_callback_data(subreq,
1998 struct dcesrv_call_state);
2001 ok = tevent_wakeup_recv(subreq);
2002 TALLOC_FREE(subreq);
2004 dcesrv_terminate_connection(call->conn, __location__);
2008 dcesrv_terminate_connection(call->conn, call->terminate_reason);
2011 struct dcesrv_socket_context {
2012 const struct dcesrv_endpoint *endpoint;
2013 struct dcesrv_context *dcesrv_ctx;
2017 static void dcesrv_read_fragment_done(struct tevent_req *subreq);
2019 static void dcesrv_sock_accept(struct stream_connection *srv_conn)
2022 struct dcesrv_socket_context *dcesrv_sock =
2023 talloc_get_type(srv_conn->private_data, struct dcesrv_socket_context);
2024 enum dcerpc_transport_t transport =
2025 dcerpc_binding_get_transport(dcesrv_sock->endpoint->ep_description);
2026 struct dcesrv_connection *dcesrv_conn = NULL;
2028 struct tevent_req *subreq;
2029 struct loadparm_context *lp_ctx = dcesrv_sock->dcesrv_ctx->lp_ctx;
2031 dcesrv_cleanup_broken_connections(dcesrv_sock->dcesrv_ctx);
2033 if (!srv_conn->session_info) {
2034 status = auth_anonymous_session_info(srv_conn,
2036 &srv_conn->session_info);
2037 if (!NT_STATUS_IS_OK(status)) {
2038 DEBUG(0,("dcesrv_sock_accept: auth_anonymous_session_info failed: %s\n",
2039 nt_errstr(status)));
2040 stream_terminate_connection(srv_conn, nt_errstr(status));
2045 status = dcesrv_endpoint_connect(dcesrv_sock->dcesrv_ctx,
2047 dcesrv_sock->endpoint,
2048 srv_conn->session_info,
2049 srv_conn->event.ctx,
2051 srv_conn->server_id,
2052 DCESRV_CALL_STATE_FLAG_MAY_ASYNC,
2054 if (!NT_STATUS_IS_OK(status)) {
2055 DEBUG(0,("dcesrv_sock_accept: dcesrv_endpoint_connect failed: %s\n",
2056 nt_errstr(status)));
2057 stream_terminate_connection(srv_conn, nt_errstr(status));
2061 dcesrv_conn->transport.private_data = srv_conn;
2062 dcesrv_conn->transport.report_output_data = dcesrv_sock_report_output_data;
2064 TALLOC_FREE(srv_conn->event.fde);
2066 dcesrv_conn->send_queue = tevent_queue_create(dcesrv_conn, "dcesrv send queue");
2067 if (!dcesrv_conn->send_queue) {
2068 status = NT_STATUS_NO_MEMORY;
2069 DEBUG(0,("dcesrv_sock_accept: tevent_queue_create(%s)\n",
2070 nt_errstr(status)));
2071 stream_terminate_connection(srv_conn, nt_errstr(status));
2075 if (transport == NCACN_NP) {
2076 dcesrv_conn->auth_state.session_key = dcesrv_inherited_session_key;
2077 dcesrv_conn->stream = talloc_move(dcesrv_conn,
2078 &srv_conn->tstream);
2080 ret = tstream_bsd_existing_socket(dcesrv_conn,
2081 socket_get_fd(srv_conn->socket),
2082 &dcesrv_conn->stream);
2084 status = map_nt_error_from_unix_common(errno);
2085 DEBUG(0, ("dcesrv_sock_accept: "
2086 "failed to setup tstream: %s\n",
2087 nt_errstr(status)));
2088 stream_terminate_connection(srv_conn, nt_errstr(status));
2091 socket_set_flags(srv_conn->socket, SOCKET_FLAG_NOCLOSE);
2094 dcesrv_conn->local_address = srv_conn->local_address;
2095 dcesrv_conn->remote_address = srv_conn->remote_address;
2097 if (transport == NCALRPC) {
2101 ret = getpeereid(socket_get_fd(srv_conn->socket), &uid, &gid);
2103 status = map_nt_error_from_unix_common(errno);
2104 DEBUG(0, ("dcesrv_sock_accept: "
2105 "getpeereid() failed for NCALRPC: %s\n",
2106 nt_errstr(status)));
2107 stream_terminate_connection(srv_conn, nt_errstr(status));
2110 if (uid == dcesrv_conn->dce_ctx->initial_euid) {
2111 struct tsocket_address *r = NULL;
2113 ret = tsocket_address_unix_from_path(dcesrv_conn,
2114 "/root/ncalrpc_as_system",
2117 status = map_nt_error_from_unix_common(errno);
2118 DEBUG(0, ("dcesrv_sock_accept: "
2119 "tsocket_address_unix_from_path() failed for NCALRPC: %s\n",
2120 nt_errstr(status)));
2121 stream_terminate_connection(srv_conn, nt_errstr(status));
2124 dcesrv_conn->remote_address = r;
2128 srv_conn->private_data = dcesrv_conn;
2130 irpc_add_name(srv_conn->msg_ctx, "rpc_server");
2132 subreq = dcerpc_read_ncacn_packet_send(dcesrv_conn,
2133 dcesrv_conn->event_ctx,
2134 dcesrv_conn->stream);
2136 status = NT_STATUS_NO_MEMORY;
2137 DEBUG(0,("dcesrv_sock_accept: dcerpc_read_fragment_buffer_send(%s)\n",
2138 nt_errstr(status)));
2139 stream_terminate_connection(srv_conn, nt_errstr(status));
2142 tevent_req_set_callback(subreq, dcesrv_read_fragment_done, dcesrv_conn);
2147 static void dcesrv_read_fragment_done(struct tevent_req *subreq)
2149 struct dcesrv_connection *dce_conn = tevent_req_callback_data(subreq,
2150 struct dcesrv_connection);
2151 struct dcesrv_context *dce_ctx = dce_conn->dce_ctx;
2152 struct ncacn_packet *pkt;
2156 if (dce_conn->terminate) {
2158 * if the current connection is broken
2159 * we need to clean it up before any other connection
2161 dcesrv_terminate_connection(dce_conn, dce_conn->terminate);
2162 dcesrv_cleanup_broken_connections(dce_ctx);
2166 dcesrv_cleanup_broken_connections(dce_ctx);
2168 status = dcerpc_read_ncacn_packet_recv(subreq, dce_conn,
2170 TALLOC_FREE(subreq);
2171 if (!NT_STATUS_IS_OK(status)) {
2172 dcesrv_terminate_connection(dce_conn, nt_errstr(status));
2176 status = dcesrv_process_ncacn_packet(dce_conn, pkt, buffer);
2177 if (!NT_STATUS_IS_OK(status)) {
2178 dcesrv_terminate_connection(dce_conn, nt_errstr(status));
2182 subreq = dcerpc_read_ncacn_packet_send(dce_conn,
2183 dce_conn->event_ctx,
2186 status = NT_STATUS_NO_MEMORY;
2187 dcesrv_terminate_connection(dce_conn, nt_errstr(status));
2190 tevent_req_set_callback(subreq, dcesrv_read_fragment_done, dce_conn);
2193 static void dcesrv_sock_recv(struct stream_connection *conn, uint16_t flags)
2195 struct dcesrv_connection *dce_conn = talloc_get_type(conn->private_data,
2196 struct dcesrv_connection);
2197 dcesrv_terminate_connection(dce_conn, "dcesrv_sock_recv triggered");
2200 static void dcesrv_sock_send(struct stream_connection *conn, uint16_t flags)
2202 struct dcesrv_connection *dce_conn = talloc_get_type(conn->private_data,
2203 struct dcesrv_connection);
2204 dcesrv_terminate_connection(dce_conn, "dcesrv_sock_send triggered");
2208 static const struct stream_server_ops dcesrv_stream_ops = {
2210 .accept_connection = dcesrv_sock_accept,
2211 .recv_handler = dcesrv_sock_recv,
2212 .send_handler = dcesrv_sock_send,
2215 static NTSTATUS dcesrv_add_ep_unix(struct dcesrv_context *dce_ctx,
2216 struct loadparm_context *lp_ctx,
2217 struct dcesrv_endpoint *e,
2218 struct tevent_context *event_ctx, const struct model_ops *model_ops)
2220 struct dcesrv_socket_context *dcesrv_sock;
2223 const char *endpoint;
2225 dcesrv_sock = talloc_zero(event_ctx, struct dcesrv_socket_context);
2226 NT_STATUS_HAVE_NO_MEMORY(dcesrv_sock);
2228 /* remember the endpoint of this socket */
2229 dcesrv_sock->endpoint = e;
2230 dcesrv_sock->dcesrv_ctx = talloc_reference(dcesrv_sock, dce_ctx);
2232 endpoint = dcerpc_binding_get_string_option(e->ep_description, "endpoint");
2234 status = stream_setup_socket(dcesrv_sock, event_ctx, lp_ctx,
2235 model_ops, &dcesrv_stream_ops,
2236 "unix", endpoint, &port,
2237 lpcfg_socket_options(lp_ctx),
2239 if (!NT_STATUS_IS_OK(status)) {
2240 DEBUG(0,("service_setup_stream_socket(path=%s) failed - %s\n",
2241 endpoint, nt_errstr(status)));
2247 static NTSTATUS dcesrv_add_ep_ncalrpc(struct dcesrv_context *dce_ctx,
2248 struct loadparm_context *lp_ctx,
2249 struct dcesrv_endpoint *e,
2250 struct tevent_context *event_ctx, const struct model_ops *model_ops)
2252 struct dcesrv_socket_context *dcesrv_sock;
2256 const char *endpoint;
2258 endpoint = dcerpc_binding_get_string_option(e->ep_description, "endpoint");
2260 if (endpoint == NULL) {
2262 * No identifier specified: use DEFAULT.
2264 * TODO: DO NOT hardcode this value anywhere else. Rather, specify
2265 * no endpoint and let the epmapper worry about it.
2267 endpoint = "DEFAULT";
2268 status = dcerpc_binding_set_string_option(e->ep_description,
2271 if (!NT_STATUS_IS_OK(status)) {
2272 DEBUG(0,("dcerpc_binding_set_string_option() failed - %s\n",
2273 nt_errstr(status)));
2278 full_path = talloc_asprintf(dce_ctx, "%s/%s", lpcfg_ncalrpc_dir(lp_ctx),
2281 dcesrv_sock = talloc_zero(event_ctx, struct dcesrv_socket_context);
2282 NT_STATUS_HAVE_NO_MEMORY(dcesrv_sock);
2284 /* remember the endpoint of this socket */
2285 dcesrv_sock->endpoint = e;
2286 dcesrv_sock->dcesrv_ctx = talloc_reference(dcesrv_sock, dce_ctx);
2288 status = stream_setup_socket(dcesrv_sock, event_ctx, lp_ctx,
2289 model_ops, &dcesrv_stream_ops,
2290 "unix", full_path, &port,
2291 lpcfg_socket_options(lp_ctx),
2293 if (!NT_STATUS_IS_OK(status)) {
2294 DEBUG(0,("service_setup_stream_socket(identifier=%s,path=%s) failed - %s\n",
2295 endpoint, full_path, nt_errstr(status)));
2300 static NTSTATUS dcesrv_add_ep_np(struct dcesrv_context *dce_ctx,
2301 struct loadparm_context *lp_ctx,
2302 struct dcesrv_endpoint *e,
2303 struct tevent_context *event_ctx, const struct model_ops *model_ops)
2305 struct dcesrv_socket_context *dcesrv_sock;
2307 const char *endpoint;
2309 endpoint = dcerpc_binding_get_string_option(e->ep_description, "endpoint");
2310 if (endpoint == NULL) {
2311 DEBUG(0, ("Endpoint mandatory for named pipes\n"));
2312 return NT_STATUS_INVALID_PARAMETER;
2315 dcesrv_sock = talloc_zero(event_ctx, struct dcesrv_socket_context);
2316 NT_STATUS_HAVE_NO_MEMORY(dcesrv_sock);
2318 /* remember the endpoint of this socket */
2319 dcesrv_sock->endpoint = e;
2320 dcesrv_sock->dcesrv_ctx = talloc_reference(dcesrv_sock, dce_ctx);
2322 status = tstream_setup_named_pipe(dce_ctx, event_ctx, lp_ctx,
2323 model_ops, &dcesrv_stream_ops,
2326 if (!NT_STATUS_IS_OK(status)) {
2327 DEBUG(0,("stream_setup_named_pipe(pipe=%s) failed - %s\n",
2328 endpoint, nt_errstr(status)));
2332 return NT_STATUS_OK;
2336 add a socket address to the list of events, one event per dcerpc endpoint
2338 static NTSTATUS add_socket_rpc_tcp_iface(struct dcesrv_context *dce_ctx, struct dcesrv_endpoint *e,
2339 struct tevent_context *event_ctx, const struct model_ops *model_ops,
2340 const char *address)
2342 struct dcesrv_socket_context *dcesrv_sock;
2345 const char *endpoint;
2348 endpoint = dcerpc_binding_get_string_option(e->ep_description, "endpoint");
2349 if (endpoint != NULL) {
2350 port = atoi(endpoint);
2353 dcesrv_sock = talloc_zero(event_ctx, struct dcesrv_socket_context);
2354 NT_STATUS_HAVE_NO_MEMORY(dcesrv_sock);
2356 /* remember the endpoint of this socket */
2357 dcesrv_sock->endpoint = e;
2358 dcesrv_sock->dcesrv_ctx = talloc_reference(dcesrv_sock, dce_ctx);
2360 status = stream_setup_socket(dcesrv_sock, event_ctx, dce_ctx->lp_ctx,
2361 model_ops, &dcesrv_stream_ops,
2362 "ip", address, &port,
2363 lpcfg_socket_options(dce_ctx->lp_ctx),
2365 if (!NT_STATUS_IS_OK(status)) {
2366 DEBUG(0,("service_setup_stream_socket(address=%s,port=%u) failed - %s\n",
2367 address, port, nt_errstr(status)));
2371 snprintf(port_str, sizeof(port_str), "%u", port);
2373 status = dcerpc_binding_set_string_option(e->ep_description,
2374 "endpoint", port_str);
2375 if (!NT_STATUS_IS_OK(status)) {
2376 DEBUG(0,("dcerpc_binding_set_string_option(endpoint, %s) failed - %s\n",
2377 port_str, nt_errstr(status)));
2381 return NT_STATUS_OK;
2384 #include "lib/socket/netif.h" /* Included here to work around the fact that socket_wrapper redefines bind() */
2386 static NTSTATUS dcesrv_add_ep_tcp(struct dcesrv_context *dce_ctx,
2387 struct loadparm_context *lp_ctx,
2388 struct dcesrv_endpoint *e,
2389 struct tevent_context *event_ctx, const struct model_ops *model_ops)
2393 /* Add TCP/IP sockets */
2394 if (lpcfg_interfaces(lp_ctx) && lpcfg_bind_interfaces_only(lp_ctx)) {
2397 struct interface *ifaces;
2399 load_interface_list(dce_ctx, lp_ctx, &ifaces);
2401 num_interfaces = iface_list_count(ifaces);
2402 for(i = 0; i < num_interfaces; i++) {
2403 const char *address = iface_list_n_ip(ifaces, i);
2404 status = add_socket_rpc_tcp_iface(dce_ctx, e, event_ctx, model_ops, address);
2405 NT_STATUS_NOT_OK_RETURN(status);
2411 wcard = iface_list_wildcard(dce_ctx);
2412 NT_STATUS_HAVE_NO_MEMORY(wcard);
2413 for (i=0; wcard[i]; i++) {
2414 status = add_socket_rpc_tcp_iface(dce_ctx, e, event_ctx, model_ops, wcard[i]);
2415 if (NT_STATUS_IS_OK(status)) {
2420 if (num_binds == 0) {
2421 return NT_STATUS_INVALID_PARAMETER_MIX;
2425 return NT_STATUS_OK;
2428 NTSTATUS dcesrv_add_ep(struct dcesrv_context *dce_ctx,
2429 struct loadparm_context *lp_ctx,
2430 struct dcesrv_endpoint *e,
2431 struct tevent_context *event_ctx,
2432 const struct model_ops *model_ops)
2434 enum dcerpc_transport_t transport =
2435 dcerpc_binding_get_transport(e->ep_description);
2437 switch (transport) {
2438 case NCACN_UNIX_STREAM:
2439 return dcesrv_add_ep_unix(dce_ctx, lp_ctx, e, event_ctx, model_ops);
2442 return dcesrv_add_ep_ncalrpc(dce_ctx, lp_ctx, e, event_ctx, model_ops);
2445 return dcesrv_add_ep_tcp(dce_ctx, lp_ctx, e, event_ctx, model_ops);
2448 return dcesrv_add_ep_np(dce_ctx, lp_ctx, e, event_ctx, model_ops);
2451 return NT_STATUS_NOT_SUPPORTED;
2457 * retrieve credentials from a dce_call
2459 _PUBLIC_ struct cli_credentials *dcesrv_call_credentials(struct dcesrv_call_state *dce_call)
2461 return dce_call->conn->auth_state.session_info->credentials;
2465 * returns true if this is an authenticated call
2467 _PUBLIC_ bool dcesrv_call_authenticated(struct dcesrv_call_state *dce_call)
2469 enum security_user_level level;
2470 level = security_session_user_level(dce_call->conn->auth_state.session_info, NULL);
2471 return level >= SECURITY_USER;
2475 * retrieve account_name for a dce_call
2477 _PUBLIC_ const char *dcesrv_call_account_name(struct dcesrv_call_state *dce_call)
2479 return dce_call->context->conn->auth_state.session_info->info->account_name;