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(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(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(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;
417 move a call from an existing linked list to the specified list. This
418 prevents bugs where we forget to remove the call from a previous
421 static void dcesrv_call_set_list(struct dcesrv_call_state *call,
422 enum dcesrv_call_list list)
424 switch (call->list) {
425 case DCESRV_LIST_NONE:
427 case DCESRV_LIST_CALL_LIST:
428 DLIST_REMOVE(call->conn->call_list, call);
430 case DCESRV_LIST_FRAGMENTED_CALL_LIST:
431 DLIST_REMOVE(call->conn->incoming_fragmented_call_list, call);
433 case DCESRV_LIST_PENDING_CALL_LIST:
434 DLIST_REMOVE(call->conn->pending_call_list, call);
439 case DCESRV_LIST_NONE:
441 case DCESRV_LIST_CALL_LIST:
442 DLIST_ADD_END(call->conn->call_list, call);
444 case DCESRV_LIST_FRAGMENTED_CALL_LIST:
445 DLIST_ADD_END(call->conn->incoming_fragmented_call_list, call);
447 case DCESRV_LIST_PENDING_CALL_LIST:
448 DLIST_ADD_END(call->conn->pending_call_list, call);
455 return a dcerpc bind_nak
457 static NTSTATUS dcesrv_bind_nak(struct dcesrv_call_state *call, uint32_t reason)
459 struct ncacn_packet pkt;
460 struct dcerpc_bind_nak_version version;
461 struct data_blob_list_item *rep;
464 /* setup a bind_nak */
465 dcesrv_init_hdr(&pkt, lpcfg_rpc_big_endian(call->conn->dce_ctx->lp_ctx));
467 pkt.call_id = call->pkt.call_id;
468 pkt.ptype = DCERPC_PKT_BIND_NAK;
469 pkt.pfc_flags = DCERPC_PFC_FLAG_FIRST | DCERPC_PFC_FLAG_LAST;
470 pkt.u.bind_nak.reject_reason = reason;
471 version.rpc_vers = 5;
472 version.rpc_vers_minor = 0;
473 pkt.u.bind_nak.num_versions = 1;
474 pkt.u.bind_nak.versions = &version;
475 pkt.u.bind_nak._pad = data_blob_null;
477 rep = talloc(call, struct data_blob_list_item);
479 return NT_STATUS_NO_MEMORY;
482 status = ncacn_push_auth(&rep->blob, call, &pkt, NULL);
483 if (!NT_STATUS_IS_OK(status)) {
487 dcerpc_set_frag_length(&rep->blob, rep->blob.length);
489 DLIST_ADD_END(call->replies, rep);
490 dcesrv_call_set_list(call, DCESRV_LIST_CALL_LIST);
492 if (call->conn->call_list && call->conn->call_list->replies) {
493 if (call->conn->transport.report_output_data) {
494 call->conn->transport.report_output_data(call->conn);
501 static int dcesrv_connection_context_destructor(struct dcesrv_connection_context *c)
503 DLIST_REMOVE(c->conn->contexts, c);
505 if (c->iface && c->iface->unbind) {
506 c->iface->unbind(c, c->iface);
513 static void dcesrv_prepare_context_auth(struct dcesrv_call_state *dce_call)
515 struct dcesrv_connection_context *context = dce_call->context;
517 context->min_auth_level = DCERPC_AUTH_LEVEL_NONE;
520 NTSTATUS dcesrv_interface_bind_require_integrity(struct dcesrv_call_state *dce_call,
521 const struct dcesrv_interface *iface)
523 if (dce_call->context == NULL) {
524 return NT_STATUS_INTERNAL_ERROR;
527 dce_call->context->min_auth_level = DCERPC_AUTH_LEVEL_INTEGRITY;
531 NTSTATUS dcesrv_interface_bind_require_privacy(struct dcesrv_call_state *dce_call,
532 const struct dcesrv_interface *iface)
534 if (dce_call->context == NULL) {
535 return NT_STATUS_INTERNAL_ERROR;
538 dce_call->context->min_auth_level = DCERPC_AUTH_LEVEL_PRIVACY;
543 handle a bind request
545 static NTSTATUS dcesrv_bind(struct dcesrv_call_state *call)
547 uint32_t if_version, transfer_syntax_version;
548 struct GUID uuid, *transfer_syntax_uuid;
549 struct ncacn_packet pkt;
550 struct data_blob_list_item *rep;
552 uint32_t result=0, reason=0;
554 const struct dcesrv_interface *iface;
555 uint32_t extra_flags = 0;
558 if provided, check the assoc_group is valid
560 if (call->pkt.u.bind.assoc_group_id != 0 &&
561 lpcfg_parm_bool(call->conn->dce_ctx->lp_ctx, NULL, "dcesrv","assoc group checking", true) &&
562 dcesrv_assoc_group_find(call->conn->dce_ctx, call->pkt.u.bind.assoc_group_id) == NULL) {
563 return dcesrv_bind_nak(call, 0);
566 if (call->pkt.u.bind.num_contexts < 1 ||
567 call->pkt.u.bind.ctx_list[0].num_transfer_syntaxes < 1) {
568 return dcesrv_bind_nak(call, 0);
571 context_id = call->pkt.u.bind.ctx_list[0].context_id;
573 /* you can't bind twice on one context */
574 if (dcesrv_find_context(call->conn, context_id) != NULL) {
575 return dcesrv_bind_nak(call, 0);
578 if_version = call->pkt.u.bind.ctx_list[0].abstract_syntax.if_version;
579 uuid = call->pkt.u.bind.ctx_list[0].abstract_syntax.uuid;
581 transfer_syntax_version = call->pkt.u.bind.ctx_list[0].transfer_syntaxes[0].if_version;
582 transfer_syntax_uuid = &call->pkt.u.bind.ctx_list[0].transfer_syntaxes[0].uuid;
583 if (!GUID_equal(&ndr_transfer_syntax_ndr.uuid, transfer_syntax_uuid) != 0 ||
584 ndr_transfer_syntax_ndr.if_version != transfer_syntax_version) {
585 char *uuid_str = GUID_string(call, transfer_syntax_uuid);
586 /* we only do NDR encoded dcerpc */
587 DEBUG(0,("Non NDR transfer syntax requested - %s\n", uuid_str));
588 talloc_free(uuid_str);
589 return dcesrv_bind_nak(call, 0);
592 iface = find_interface_by_uuid(call->conn->endpoint, &uuid, if_version);
594 char *uuid_str = GUID_string(call, &uuid);
595 DEBUG(2,("Request for unknown dcerpc interface %s/%d\n", uuid_str, if_version));
596 talloc_free(uuid_str);
598 /* we don't know about that interface */
599 result = DCERPC_BIND_PROVIDER_REJECT;
600 reason = DCERPC_BIND_REASON_ASYNTAX;
604 /* add this context to the list of available context_ids */
605 struct dcesrv_connection_context *context = talloc(call->conn,
606 struct dcesrv_connection_context);
607 if (context == NULL) {
608 return dcesrv_bind_nak(call, 0);
610 context->conn = call->conn;
611 context->iface = iface;
612 context->context_id = context_id;
613 if (call->pkt.u.bind.assoc_group_id != 0) {
614 context->assoc_group = dcesrv_assoc_group_reference(context,
616 call->pkt.u.bind.assoc_group_id);
618 context->assoc_group = dcesrv_assoc_group_new(context, call->conn->dce_ctx);
620 if (context->assoc_group == NULL) {
621 talloc_free(context);
622 return dcesrv_bind_nak(call, 0);
624 context->private_data = NULL;
625 DLIST_ADD(call->conn->contexts, context);
626 call->context = context;
627 talloc_set_destructor(context, dcesrv_connection_context_destructor);
629 dcesrv_prepare_context_auth(call);
631 status = iface->bind(call, iface, if_version);
632 if (!NT_STATUS_IS_OK(status)) {
633 char *uuid_str = GUID_string(call, &uuid);
634 DEBUG(2,("Request for dcerpc interface %s/%d rejected: %s\n",
635 uuid_str, if_version, nt_errstr(status)));
636 talloc_free(uuid_str);
637 /* we don't want to trigger the iface->unbind() hook */
638 context->iface = NULL;
639 talloc_free(call->context);
640 call->context = NULL;
641 return dcesrv_bind_nak(call, 0);
645 if (call->conn->cli_max_recv_frag == 0) {
646 call->conn->cli_max_recv_frag = MIN(0x2000, call->pkt.u.bind.max_recv_frag);
649 if ((call->pkt.pfc_flags & DCERPC_PFC_FLAG_CONC_MPX) &&
650 (call->state_flags & DCESRV_CALL_STATE_FLAG_MULTIPLEXED)) {
651 call->context->conn->state_flags |= DCESRV_CALL_STATE_FLAG_MULTIPLEXED;
652 extra_flags |= DCERPC_PFC_FLAG_CONC_MPX;
655 if (call->state_flags & DCESRV_CALL_STATE_FLAG_PROCESS_PENDING_CALL) {
656 call->context->conn->state_flags |= DCESRV_CALL_STATE_FLAG_PROCESS_PENDING_CALL;
659 /* handle any authentication that is being requested */
660 if (!dcesrv_auth_bind(call)) {
661 talloc_free(call->context);
662 call->context = NULL;
663 return dcesrv_bind_nak(call, DCERPC_BIND_REASON_INVALID_AUTH_TYPE);
666 /* setup a bind_ack */
667 dcesrv_init_hdr(&pkt, lpcfg_rpc_big_endian(call->conn->dce_ctx->lp_ctx));
669 pkt.call_id = call->pkt.call_id;
670 pkt.ptype = DCERPC_PKT_BIND_ACK;
671 pkt.pfc_flags = DCERPC_PFC_FLAG_FIRST | DCERPC_PFC_FLAG_LAST | extra_flags;
672 pkt.u.bind_ack.max_xmit_frag = call->conn->cli_max_recv_frag;
673 pkt.u.bind_ack.max_recv_frag = 0x2000;
676 make it possible for iface->bind() to specify the assoc_group_id
677 This helps the openchange mapiproxy plugin to work correctly.
682 pkt.u.bind_ack.assoc_group_id = call->context->assoc_group->id;
684 pkt.u.bind_ack.assoc_group_id = DUMMY_ASSOC_GROUP;
688 /* FIXME: Use pipe name as specified by endpoint instead of interface name */
689 pkt.u.bind_ack.secondary_address = talloc_asprintf(call, "\\PIPE\\%s", iface->name);
691 pkt.u.bind_ack.secondary_address = "";
693 pkt.u.bind_ack.num_results = 1;
694 pkt.u.bind_ack.ctx_list = talloc(call, struct dcerpc_ack_ctx);
695 if (!pkt.u.bind_ack.ctx_list) {
696 talloc_free(call->context);
697 call->context = NULL;
698 return NT_STATUS_NO_MEMORY;
700 pkt.u.bind_ack.ctx_list[0].result = result;
701 pkt.u.bind_ack.ctx_list[0].reason.value = reason;
702 pkt.u.bind_ack.ctx_list[0].syntax = ndr_transfer_syntax_ndr;
703 pkt.u.bind_ack.auth_info = data_blob(NULL, 0);
705 status = dcesrv_auth_bind_ack(call, &pkt);
706 if (!NT_STATUS_IS_OK(status)) {
707 talloc_free(call->context);
708 call->context = NULL;
709 return dcesrv_bind_nak(call, 0);
712 rep = talloc(call, struct data_blob_list_item);
714 talloc_free(call->context);
715 call->context = NULL;
716 return NT_STATUS_NO_MEMORY;
719 status = ncacn_push_auth(&rep->blob, call, &pkt,
720 call->conn->auth_state.auth_info);
721 if (!NT_STATUS_IS_OK(status)) {
722 talloc_free(call->context);
723 call->context = NULL;
727 dcerpc_set_frag_length(&rep->blob, rep->blob.length);
729 DLIST_ADD_END(call->replies, rep);
730 dcesrv_call_set_list(call, DCESRV_LIST_CALL_LIST);
732 if (call->conn->call_list && call->conn->call_list->replies) {
733 if (call->conn->transport.report_output_data) {
734 call->conn->transport.report_output_data(call->conn);
743 handle a auth3 request
745 static NTSTATUS dcesrv_auth3(struct dcesrv_call_state *call)
747 /* handle the auth3 in the auth code */
748 if (!dcesrv_auth_auth3(call)) {
749 return dcesrv_fault(call, DCERPC_FAULT_OTHER);
754 /* we don't send a reply to a auth3 request, except by a
761 handle a bind request
763 static NTSTATUS dcesrv_alter_new_context(struct dcesrv_call_state *call, uint32_t context_id)
765 uint32_t if_version, transfer_syntax_version;
766 struct dcesrv_connection_context *context;
767 const struct dcesrv_interface *iface;
768 struct GUID uuid, *transfer_syntax_uuid;
771 if_version = call->pkt.u.alter.ctx_list[0].abstract_syntax.if_version;
772 uuid = call->pkt.u.alter.ctx_list[0].abstract_syntax.uuid;
774 transfer_syntax_version = call->pkt.u.alter.ctx_list[0].transfer_syntaxes[0].if_version;
775 transfer_syntax_uuid = &call->pkt.u.alter.ctx_list[0].transfer_syntaxes[0].uuid;
776 if (!GUID_equal(transfer_syntax_uuid, &ndr_transfer_syntax_ndr.uuid) ||
777 ndr_transfer_syntax_ndr.if_version != transfer_syntax_version) {
778 /* we only do NDR encoded dcerpc */
779 return NT_STATUS_RPC_PROTSEQ_NOT_SUPPORTED;
782 iface = find_interface_by_uuid(call->conn->endpoint, &uuid, if_version);
784 char *uuid_str = GUID_string(call, &uuid);
785 DEBUG(2,("Request for unknown dcerpc interface %s/%d\n", uuid_str, if_version));
786 talloc_free(uuid_str);
787 return NT_STATUS_RPC_PROTSEQ_NOT_SUPPORTED;
790 /* add this context to the list of available context_ids */
791 context = talloc(call->conn, struct dcesrv_connection_context);
792 if (context == NULL) {
793 return NT_STATUS_NO_MEMORY;
795 context->conn = call->conn;
796 context->iface = iface;
797 context->context_id = context_id;
798 if (call->pkt.u.alter.assoc_group_id != 0) {
799 context->assoc_group = dcesrv_assoc_group_reference(context,
801 call->pkt.u.alter.assoc_group_id);
803 context->assoc_group = dcesrv_assoc_group_new(context, call->conn->dce_ctx);
805 if (context->assoc_group == NULL) {
806 talloc_free(context);
807 call->context = NULL;
808 return NT_STATUS_NO_MEMORY;
810 context->private_data = NULL;
811 DLIST_ADD(call->conn->contexts, context);
812 call->context = context;
813 talloc_set_destructor(context, dcesrv_connection_context_destructor);
815 dcesrv_prepare_context_auth(call);
817 status = iface->bind(call, iface, if_version);
818 if (!NT_STATUS_IS_OK(status)) {
819 /* we don't want to trigger the iface->unbind() hook */
820 context->iface = NULL;
821 talloc_free(context);
822 call->context = NULL;
829 /* setup and send an alter_resp */
830 static NTSTATUS dcesrv_alter_resp(struct dcesrv_call_state *call,
834 struct ncacn_packet pkt;
835 uint32_t extra_flags = 0;
836 struct data_blob_list_item *rep = NULL;
839 dcesrv_init_hdr(&pkt, lpcfg_rpc_big_endian(call->conn->dce_ctx->lp_ctx));
841 pkt.call_id = call->pkt.call_id;
842 pkt.ptype = DCERPC_PKT_ALTER_RESP;
844 if ((call->pkt.pfc_flags & DCERPC_PFC_FLAG_CONC_MPX) &&
845 call->context->conn->state_flags &
846 DCESRV_CALL_STATE_FLAG_MULTIPLEXED) {
847 extra_flags |= DCERPC_PFC_FLAG_CONC_MPX;
849 if (call->state_flags & DCESRV_CALL_STATE_FLAG_PROCESS_PENDING_CALL) {
850 call->context->conn->state_flags |=
851 DCESRV_CALL_STATE_FLAG_PROCESS_PENDING_CALL;
854 pkt.pfc_flags = DCERPC_PFC_FLAG_FIRST | DCERPC_PFC_FLAG_LAST | extra_flags;
855 pkt.u.alter_resp.max_xmit_frag = 0x2000;
856 pkt.u.alter_resp.max_recv_frag = 0x2000;
858 pkt.u.alter_resp.assoc_group_id = call->context->assoc_group->id;
860 pkt.u.alter_resp.assoc_group_id = 0;
862 pkt.u.alter_resp.num_results = 1;
863 pkt.u.alter_resp.ctx_list = talloc_array(call, struct dcerpc_ack_ctx, 1);
864 if (!pkt.u.alter_resp.ctx_list) {
865 return NT_STATUS_NO_MEMORY;
867 pkt.u.alter_resp.ctx_list[0].result = result;
868 pkt.u.alter_resp.ctx_list[0].reason.value = reason;
869 pkt.u.alter_resp.ctx_list[0].syntax = ndr_transfer_syntax_ndr;
870 pkt.u.alter_resp.auth_info = data_blob(NULL, 0);
871 pkt.u.alter_resp.secondary_address = "";
873 status = dcesrv_auth_alter_ack(call, &pkt);
874 if (!NT_STATUS_IS_OK(status)) {
875 if (NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)
876 || NT_STATUS_EQUAL(status, NT_STATUS_LOGON_FAILURE)
877 || NT_STATUS_EQUAL(status, NT_STATUS_NO_SUCH_USER)
878 || NT_STATUS_EQUAL(status, NT_STATUS_WRONG_PASSWORD)) {
879 return dcesrv_fault(call, DCERPC_FAULT_ACCESS_DENIED);
881 return dcesrv_fault(call, 0);
884 rep = talloc(call, struct data_blob_list_item);
886 return NT_STATUS_NO_MEMORY;
889 status = ncacn_push_auth(&rep->blob, call, &pkt, call->conn->auth_state.auth_info);
890 if (!NT_STATUS_IS_OK(status)) {
894 dcerpc_set_frag_length(&rep->blob, rep->blob.length);
896 DLIST_ADD_END(call->replies, rep);
897 dcesrv_call_set_list(call, DCESRV_LIST_CALL_LIST);
899 if (call->conn->call_list && call->conn->call_list->replies) {
900 if (call->conn->transport.report_output_data) {
901 call->conn->transport.report_output_data(call->conn);
909 handle a alter context request
911 static NTSTATUS dcesrv_alter(struct dcesrv_call_state *call)
916 /* handle any authentication that is being requested */
917 if (!dcesrv_auth_alter(call)) {
918 /* TODO: work out the right reject code */
919 return dcesrv_alter_resp(call,
920 DCERPC_BIND_PROVIDER_REJECT,
921 DCERPC_BIND_REASON_ASYNTAX);
924 context_id = call->pkt.u.alter.ctx_list[0].context_id;
926 /* see if they are asking for a new interface */
927 call->context = dcesrv_find_context(call->conn, context_id);
928 if (!call->context) {
929 status = dcesrv_alter_new_context(call, context_id);
930 if (!NT_STATUS_IS_OK(status)) {
931 return dcesrv_alter_resp(call,
932 DCERPC_BIND_PROVIDER_REJECT,
933 DCERPC_BIND_REASON_ASYNTAX);
937 if (call->pkt.u.alter.assoc_group_id != 0 &&
938 lpcfg_parm_bool(call->conn->dce_ctx->lp_ctx, NULL, "dcesrv","assoc group checking", true) &&
939 call->pkt.u.alter.assoc_group_id != call->context->assoc_group->id) {
940 DEBUG(0,(__location__ ": Failed attempt to use new assoc_group in alter context (0x%08x 0x%08x)\n",
941 call->context->assoc_group->id, call->pkt.u.alter.assoc_group_id));
942 /* TODO: can they ask for a new association group? */
943 return dcesrv_alter_resp(call,
944 DCERPC_BIND_PROVIDER_REJECT,
945 DCERPC_BIND_REASON_ASYNTAX);
948 return dcesrv_alter_resp(call,
949 DCERPC_BIND_ACK_RESULT_ACCEPTANCE,
950 DCERPC_BIND_ACK_REASON_NOT_SPECIFIED);
954 possibly save the call for inspection with ndrdump
956 static void dcesrv_save_call(struct dcesrv_call_state *call, const char *why)
960 const char *dump_dir;
961 dump_dir = lpcfg_parm_string(call->conn->dce_ctx->lp_ctx, NULL, "dcesrv", "stubs directory");
965 fname = talloc_asprintf(call, "%s/RPC-%s-%u-%s.dat",
967 call->context->iface->name,
968 call->pkt.u.request.opnum,
970 if (file_save(fname, call->pkt.u.request.stub_and_verifier.data, call->pkt.u.request.stub_and_verifier.length)) {
971 DEBUG(0,("RPC SAVED %s\n", fname));
977 static NTSTATUS dcesrv_check_verification_trailer(struct dcesrv_call_state *call)
979 TALLOC_CTX *frame = talloc_stackframe();
980 const uint32_t bitmask1 = call->conn->auth_state.client_hdr_signing ?
981 DCERPC_SEC_VT_CLIENT_SUPPORTS_HEADER_SIGNING : 0;
982 const struct dcerpc_sec_vt_pcontext pcontext = {
983 .abstract_syntax = call->context->iface->syntax_id,
984 .transfer_syntax = ndr_transfer_syntax_ndr,
986 const struct dcerpc_sec_vt_header2 header2 =
987 dcerpc_sec_vt_header2_from_ncacn_packet(&call->pkt);
988 enum ndr_err_code ndr_err;
989 struct dcerpc_sec_verification_trailer *vt = NULL;
990 NTSTATUS status = NT_STATUS_OK;
993 SMB_ASSERT(call->pkt.ptype == DCERPC_PKT_REQUEST);
995 ndr_err = ndr_pop_dcerpc_sec_verification_trailer(call->ndr_pull,
997 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
998 status = ndr_map_error2ntstatus(ndr_err);
1002 ok = dcerpc_sec_verification_trailer_check(vt, &bitmask1,
1003 &pcontext, &header2);
1005 status = NT_STATUS_ACCESS_DENIED;
1014 handle a dcerpc request packet
1016 static NTSTATUS dcesrv_request(struct dcesrv_call_state *call)
1018 const struct dcesrv_endpoint *endpoint = call->conn->endpoint;
1019 enum dcerpc_transport_t transport =
1020 dcerpc_binding_get_transport(endpoint->ep_description);
1021 struct ndr_pull *pull;
1023 struct dcesrv_connection_context *context;
1024 uint32_t auth_type = DCERPC_AUTH_TYPE_NONE;
1025 uint32_t auth_level = DCERPC_AUTH_LEVEL_NONE;
1027 /* if authenticated, and the mech we use can't do async replies, don't use them... */
1028 if (call->conn->auth_state.gensec_security &&
1029 !gensec_have_feature(call->conn->auth_state.gensec_security, GENSEC_FEATURE_ASYNC_REPLIES)) {
1030 call->state_flags &= ~DCESRV_CALL_STATE_FLAG_MAY_ASYNC;
1033 context = dcesrv_find_context(call->conn, call->pkt.u.request.context_id);
1034 if (context == NULL) {
1035 return dcesrv_fault(call, DCERPC_FAULT_UNK_IF);
1038 if (call->conn->auth_state.auth_info != NULL) {
1039 auth_type = call->conn->auth_state.auth_info->auth_type;
1040 auth_level = call->conn->auth_state.auth_info->auth_level;
1043 if (auth_level < context->min_auth_level) {
1046 addr = tsocket_address_string(call->conn->remote_address, call);
1048 DEBUG(2, ("%s: restrict access by min_auth_level[0x%x] "
1049 "to [%s] with auth[type=0x%x,level=0x%x] "
1050 "on [%s] from [%s]\n",
1052 context->min_auth_level,
1053 context->iface->name,
1054 auth_type, auth_level,
1055 derpc_transport_string_by_transport(transport),
1057 return dcesrv_fault(call, DCERPC_FAULT_ACCESS_DENIED);
1060 pull = ndr_pull_init_blob(&call->pkt.u.request.stub_and_verifier, call);
1061 NT_STATUS_HAVE_NO_MEMORY(pull);
1063 pull->flags |= LIBNDR_FLAG_REF_ALLOC;
1065 call->context = context;
1066 call->ndr_pull = pull;
1068 if (!(call->pkt.drep[0] & DCERPC_DREP_LE)) {
1069 pull->flags |= LIBNDR_FLAG_BIGENDIAN;
1072 status = dcesrv_check_verification_trailer(call);
1073 if (!NT_STATUS_IS_OK(status)) {
1074 uint32_t faultcode = DCERPC_FAULT_OTHER;
1075 if (NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
1076 faultcode = DCERPC_FAULT_ACCESS_DENIED;
1078 DEBUG(10, ("dcesrv_check_verification_trailer failed: %s\n",
1079 nt_errstr(status)));
1080 return dcesrv_fault(call, faultcode);
1083 /* unravel the NDR for the packet */
1084 status = context->iface->ndr_pull(call, call, pull, &call->r);
1085 if (!NT_STATUS_IS_OK(status)) {
1086 if (call->fault_code == DCERPC_FAULT_OP_RNG_ERROR) {
1087 /* we got an unknown call */
1088 DEBUG(3,(__location__ ": Unknown RPC call %u on %s\n",
1089 call->pkt.u.request.opnum, context->iface->name));
1090 dcesrv_save_call(call, "unknown");
1092 dcesrv_save_call(call, "pullfail");
1094 return dcesrv_fault(call, call->fault_code);
1097 if (pull->offset != pull->data_size) {
1098 dcesrv_save_call(call, "extrabytes");
1099 DEBUG(3,("Warning: %d extra bytes in incoming RPC request\n",
1100 pull->data_size - pull->offset));
1103 /* call the dispatch function */
1104 status = context->iface->dispatch(call, call, call->r);
1105 if (!NT_STATUS_IS_OK(status)) {
1106 DEBUG(5,("dcerpc fault in call %s:%02x - %s\n",
1107 context->iface->name,
1108 call->pkt.u.request.opnum,
1109 dcerpc_errstr(pull, call->fault_code)));
1110 return dcesrv_fault(call, call->fault_code);
1113 /* add the call to the pending list */
1114 dcesrv_call_set_list(call, DCESRV_LIST_PENDING_CALL_LIST);
1116 if (call->state_flags & DCESRV_CALL_STATE_FLAG_ASYNC) {
1117 return NT_STATUS_OK;
1120 return dcesrv_reply(call);
1125 remove the call from the right list when freed
1127 static int dcesrv_call_dequeue(struct dcesrv_call_state *call)
1129 dcesrv_call_set_list(call, DCESRV_LIST_NONE);
1133 _PUBLIC_ const struct tsocket_address *dcesrv_connection_get_local_address(struct dcesrv_connection *conn)
1135 return conn->local_address;
1138 _PUBLIC_ const struct tsocket_address *dcesrv_connection_get_remote_address(struct dcesrv_connection *conn)
1140 return conn->remote_address;
1144 process some input to a dcerpc endpoint server.
1146 NTSTATUS dcesrv_process_ncacn_packet(struct dcesrv_connection *dce_conn,
1147 struct ncacn_packet *pkt,
1151 struct dcesrv_call_state *call;
1153 call = talloc_zero(dce_conn, struct dcesrv_call_state);
1155 data_blob_free(&blob);
1157 return NT_STATUS_NO_MEMORY;
1159 call->conn = dce_conn;
1160 call->event_ctx = dce_conn->event_ctx;
1161 call->msg_ctx = dce_conn->msg_ctx;
1162 call->state_flags = call->conn->state_flags;
1163 call->time = timeval_current();
1164 call->list = DCESRV_LIST_NONE;
1166 talloc_steal(call, pkt);
1167 talloc_steal(call, blob.data);
1170 talloc_set_destructor(call, dcesrv_call_dequeue);
1172 /* we have to check the signing here, before combining the
1174 if (call->pkt.ptype == DCERPC_PKT_REQUEST &&
1175 !dcesrv_auth_request(call, &blob)) {
1176 return dcesrv_fault(call, DCERPC_FAULT_ACCESS_DENIED);
1179 /* see if this is a continued packet */
1180 if (call->pkt.ptype == DCERPC_PKT_REQUEST &&
1181 !(call->pkt.pfc_flags & DCERPC_PFC_FLAG_FIRST)) {
1182 struct dcesrv_call_state *call2 = call;
1183 uint32_t alloc_size;
1185 /* we only allow fragmented requests, no other packet types */
1186 if (call->pkt.ptype != DCERPC_PKT_REQUEST) {
1187 return dcesrv_fault(call2, DCERPC_FAULT_OTHER);
1190 /* this is a continuation of an existing call - find the call
1191 then tack it on the end */
1192 call = dcesrv_find_fragmented_call(dce_conn, call2->pkt.call_id);
1194 return dcesrv_fault(call2, DCERPC_FAULT_OTHER);
1197 if (call->pkt.ptype != call2->pkt.ptype) {
1198 /* trying to play silly buggers are we? */
1199 return dcesrv_fault(call2, DCERPC_NCA_S_PROTO_ERROR);
1201 if (memcmp(call->pkt.drep, call2->pkt.drep, sizeof(pkt->drep)) != 0) {
1202 return dcesrv_fault(call2, DCERPC_NCA_S_PROTO_ERROR);
1204 if (call->pkt.call_id != call2->pkt.call_id) {
1205 return dcesrv_fault(call2, DCERPC_NCA_S_PROTO_ERROR);
1207 if (call->pkt.u.request.context_id != call2->pkt.u.request.context_id) {
1208 return dcesrv_fault(call2, DCERPC_NCA_S_PROTO_ERROR);
1210 if (call->pkt.u.request.opnum != call2->pkt.u.request.opnum) {
1211 return dcesrv_fault(call2, DCERPC_NCA_S_PROTO_ERROR);
1214 alloc_size = call->pkt.u.request.stub_and_verifier.length +
1215 call2->pkt.u.request.stub_and_verifier.length;
1216 if (call->pkt.u.request.alloc_hint > alloc_size) {
1217 alloc_size = call->pkt.u.request.alloc_hint;
1220 call->pkt.u.request.stub_and_verifier.data =
1221 talloc_realloc(call,
1222 call->pkt.u.request.stub_and_verifier.data,
1223 uint8_t, alloc_size);
1224 if (!call->pkt.u.request.stub_and_verifier.data) {
1225 return dcesrv_fault(call2, DCERPC_FAULT_OTHER);
1227 memcpy(call->pkt.u.request.stub_and_verifier.data +
1228 call->pkt.u.request.stub_and_verifier.length,
1229 call2->pkt.u.request.stub_and_verifier.data,
1230 call2->pkt.u.request.stub_and_verifier.length);
1231 call->pkt.u.request.stub_and_verifier.length +=
1232 call2->pkt.u.request.stub_and_verifier.length;
1234 call->pkt.pfc_flags |= (call2->pkt.pfc_flags & DCERPC_PFC_FLAG_LAST);
1239 /* this may not be the last pdu in the chain - if its isn't then
1240 just put it on the incoming_fragmented_call_list and wait for the rest */
1241 if (call->pkt.ptype == DCERPC_PKT_REQUEST &&
1242 !(call->pkt.pfc_flags & DCERPC_PFC_FLAG_LAST)) {
1243 dcesrv_call_set_list(call, DCESRV_LIST_FRAGMENTED_CALL_LIST);
1244 return NT_STATUS_OK;
1247 /* This removes any fragments we may have had stashed away */
1248 dcesrv_call_set_list(call, DCESRV_LIST_NONE);
1250 switch (call->pkt.ptype) {
1251 case DCERPC_PKT_BIND:
1252 status = dcesrv_bind(call);
1254 case DCERPC_PKT_AUTH3:
1255 status = dcesrv_auth3(call);
1257 case DCERPC_PKT_ALTER:
1258 status = dcesrv_alter(call);
1260 case DCERPC_PKT_REQUEST:
1261 status = dcesrv_request(call);
1264 status = NT_STATUS_INVALID_PARAMETER;
1268 /* if we are going to be sending a reply then add
1269 it to the list of pending calls. We add it to the end to keep the call
1270 list in the order we will answer */
1271 if (!NT_STATUS_IS_OK(status)) {
1278 _PUBLIC_ NTSTATUS dcesrv_init_context(TALLOC_CTX *mem_ctx,
1279 struct loadparm_context *lp_ctx,
1280 const char **endpoint_servers, struct dcesrv_context **_dce_ctx)
1283 struct dcesrv_context *dce_ctx;
1286 if (!endpoint_servers) {
1287 DEBUG(0,("dcesrv_init_context: no endpoint servers configured\n"));
1288 return NT_STATUS_INTERNAL_ERROR;
1291 dce_ctx = talloc(mem_ctx, struct dcesrv_context);
1292 NT_STATUS_HAVE_NO_MEMORY(dce_ctx);
1294 if (uid_wrapper_enabled()) {
1295 setenv("UID_WRAPPER_MYUID", "1", 1);
1297 dce_ctx->initial_euid = geteuid();
1298 if (uid_wrapper_enabled()) {
1299 unsetenv("UID_WRAPPER_MYUID");
1302 dce_ctx->endpoint_list = NULL;
1303 dce_ctx->lp_ctx = lp_ctx;
1304 dce_ctx->assoc_groups_idr = idr_init(dce_ctx);
1305 NT_STATUS_HAVE_NO_MEMORY(dce_ctx->assoc_groups_idr);
1306 dce_ctx->broken_connections = NULL;
1308 for (i=0;endpoint_servers[i];i++) {
1309 const struct dcesrv_endpoint_server *ep_server;
1311 ep_server = dcesrv_ep_server_byname(endpoint_servers[i]);
1313 DEBUG(0,("dcesrv_init_context: failed to find endpoint server = '%s'\n", endpoint_servers[i]));
1314 return NT_STATUS_INTERNAL_ERROR;
1317 status = ep_server->init_server(dce_ctx, ep_server);
1318 if (!NT_STATUS_IS_OK(status)) {
1319 DEBUG(0,("dcesrv_init_context: failed to init endpoint server = '%s': %s\n", endpoint_servers[i],
1320 nt_errstr(status)));
1325 *_dce_ctx = dce_ctx;
1326 return NT_STATUS_OK;
1329 /* the list of currently registered DCERPC endpoint servers.
1331 static struct ep_server {
1332 struct dcesrv_endpoint_server *ep_server;
1333 } *ep_servers = NULL;
1334 static int num_ep_servers;
1337 register a DCERPC endpoint server.
1339 The 'name' can be later used by other backends to find the operations
1340 structure for this backend.
1342 The 'type' is used to specify whether this is for a disk, printer or IPC$ share
1344 _PUBLIC_ NTSTATUS dcerpc_register_ep_server(const void *_ep_server)
1346 const struct dcesrv_endpoint_server *ep_server = _ep_server;
1348 if (dcesrv_ep_server_byname(ep_server->name) != NULL) {
1349 /* its already registered! */
1350 DEBUG(0,("DCERPC endpoint server '%s' already registered\n",
1352 return NT_STATUS_OBJECT_NAME_COLLISION;
1355 ep_servers = realloc_p(ep_servers, struct ep_server, num_ep_servers+1);
1357 smb_panic("out of memory in dcerpc_register");
1360 ep_servers[num_ep_servers].ep_server = smb_xmemdup(ep_server, sizeof(*ep_server));
1361 ep_servers[num_ep_servers].ep_server->name = smb_xstrdup(ep_server->name);
1365 DEBUG(3,("DCERPC endpoint server '%s' registered\n",
1368 return NT_STATUS_OK;
1372 return the operations structure for a named backend of the specified type
1374 const struct dcesrv_endpoint_server *dcesrv_ep_server_byname(const char *name)
1378 for (i=0;i<num_ep_servers;i++) {
1379 if (strcmp(ep_servers[i].ep_server->name, name) == 0) {
1380 return ep_servers[i].ep_server;
1387 void dcerpc_server_init(struct loadparm_context *lp_ctx)
1389 static bool initialized;
1390 #define _MODULE_PROTO(init) extern NTSTATUS init(void);
1391 STATIC_dcerpc_server_MODULES_PROTO;
1392 init_module_fn static_init[] = { STATIC_dcerpc_server_MODULES };
1393 init_module_fn *shared_init;
1400 shared_init = load_samba_modules(NULL, "dcerpc_server");
1402 run_init_functions(static_init);
1403 run_init_functions(shared_init);
1405 talloc_free(shared_init);
1409 return the DCERPC module version, and the size of some critical types
1410 This can be used by endpoint server modules to either detect compilation errors, or provide
1411 multiple implementations for different smbd compilation options in one module
1413 const struct dcesrv_critical_sizes *dcerpc_module_version(void)
1415 static const struct dcesrv_critical_sizes critical_sizes = {
1416 DCERPC_MODULE_VERSION,
1417 sizeof(struct dcesrv_context),
1418 sizeof(struct dcesrv_endpoint),
1419 sizeof(struct dcesrv_endpoint_server),
1420 sizeof(struct dcesrv_interface),
1421 sizeof(struct dcesrv_if_list),
1422 sizeof(struct dcesrv_connection),
1423 sizeof(struct dcesrv_call_state),
1424 sizeof(struct dcesrv_auth),
1425 sizeof(struct dcesrv_handle)
1428 return &critical_sizes;
1431 static void dcesrv_terminate_connection(struct dcesrv_connection *dce_conn, const char *reason)
1433 struct dcesrv_context *dce_ctx = dce_conn->dce_ctx;
1434 struct stream_connection *srv_conn;
1435 srv_conn = talloc_get_type(dce_conn->transport.private_data,
1436 struct stream_connection);
1438 if (dce_conn->pending_call_list == NULL) {
1439 char *full_reason = talloc_asprintf(dce_conn, "dcesrv: %s", reason);
1441 DLIST_REMOVE(dce_ctx->broken_connections, dce_conn);
1442 stream_terminate_connection(srv_conn, full_reason ? full_reason : reason);
1446 if (dce_conn->terminate != NULL) {
1450 DEBUG(3,("dcesrv: terminating connection due to '%s' defered due to pending calls\n",
1452 dce_conn->terminate = talloc_strdup(dce_conn, reason);
1453 if (dce_conn->terminate == NULL) {
1454 dce_conn->terminate = "dcesrv: defered terminating connection - no memory";
1456 DLIST_ADD_END(dce_ctx->broken_connections, dce_conn);
1459 static void dcesrv_cleanup_broken_connections(struct dcesrv_context *dce_ctx)
1461 struct dcesrv_connection *cur, *next;
1463 next = dce_ctx->broken_connections;
1464 while (next != NULL) {
1468 if (cur->state_flags & DCESRV_CALL_STATE_FLAG_PROCESS_PENDING_CALL) {
1469 struct dcesrv_connection_context *context_cur, *context_next;
1471 context_next = cur->contexts;
1472 while (context_next != NULL) {
1473 context_cur = context_next;
1474 context_next = context_cur->next;
1476 dcesrv_connection_context_destructor(context_cur);
1480 dcesrv_terminate_connection(cur, cur->terminate);
1484 /* We need this include to be able to compile on some plateforms
1485 * (ie. freebsd 7.2) as it seems that <sys/uio.h> is not included
1487 * It has to be that deep because otherwise we have a conflict on
1488 * const struct dcesrv_interface declaration.
1489 * This is mostly due to socket_wrapper defining #define bind swrap_bind
1490 * which conflict with the bind used before.
1492 #include "system/network.h"
1494 struct dcesrv_sock_reply_state {
1495 struct dcesrv_connection *dce_conn;
1496 struct dcesrv_call_state *call;
1500 static void dcesrv_sock_reply_done(struct tevent_req *subreq);
1502 static void dcesrv_sock_report_output_data(struct dcesrv_connection *dce_conn)
1504 struct dcesrv_call_state *call;
1506 call = dce_conn->call_list;
1507 if (!call || !call->replies) {
1511 while (call->replies) {
1512 struct data_blob_list_item *rep = call->replies;
1513 struct dcesrv_sock_reply_state *substate;
1514 struct tevent_req *subreq;
1516 substate = talloc(call, struct dcesrv_sock_reply_state);
1518 dcesrv_terminate_connection(dce_conn, "no memory");
1522 substate->dce_conn = dce_conn;
1523 substate->call = NULL;
1525 DLIST_REMOVE(call->replies, rep);
1527 if (call->replies == NULL) {
1528 substate->call = call;
1531 substate->iov.iov_base = (void *) rep->blob.data;
1532 substate->iov.iov_len = rep->blob.length;
1534 subreq = tstream_writev_queue_send(substate,
1535 dce_conn->event_ctx,
1537 dce_conn->send_queue,
1540 dcesrv_terminate_connection(dce_conn, "no memory");
1543 tevent_req_set_callback(subreq, dcesrv_sock_reply_done,
1547 DLIST_REMOVE(call->conn->call_list, call);
1548 call->list = DCESRV_LIST_NONE;
1551 static void dcesrv_sock_reply_done(struct tevent_req *subreq)
1553 struct dcesrv_sock_reply_state *substate = tevent_req_callback_data(subreq,
1554 struct dcesrv_sock_reply_state);
1558 struct dcesrv_call_state *call = substate->call;
1560 ret = tstream_writev_queue_recv(subreq, &sys_errno);
1561 TALLOC_FREE(subreq);
1563 status = map_nt_error_from_unix_common(sys_errno);
1564 dcesrv_terminate_connection(substate->dce_conn, nt_errstr(status));
1568 talloc_free(substate);
1577 struct dcesrv_socket_context {
1578 const struct dcesrv_endpoint *endpoint;
1579 struct dcesrv_context *dcesrv_ctx;
1583 static void dcesrv_read_fragment_done(struct tevent_req *subreq);
1585 static void dcesrv_sock_accept(struct stream_connection *srv_conn)
1588 struct dcesrv_socket_context *dcesrv_sock =
1589 talloc_get_type(srv_conn->private_data, struct dcesrv_socket_context);
1590 enum dcerpc_transport_t transport =
1591 dcerpc_binding_get_transport(dcesrv_sock->endpoint->ep_description);
1592 struct dcesrv_connection *dcesrv_conn = NULL;
1594 struct tevent_req *subreq;
1595 struct loadparm_context *lp_ctx = dcesrv_sock->dcesrv_ctx->lp_ctx;
1597 dcesrv_cleanup_broken_connections(dcesrv_sock->dcesrv_ctx);
1599 if (!srv_conn->session_info) {
1600 status = auth_anonymous_session_info(srv_conn,
1602 &srv_conn->session_info);
1603 if (!NT_STATUS_IS_OK(status)) {
1604 DEBUG(0,("dcesrv_sock_accept: auth_anonymous_session_info failed: %s\n",
1605 nt_errstr(status)));
1606 stream_terminate_connection(srv_conn, nt_errstr(status));
1611 status = dcesrv_endpoint_connect(dcesrv_sock->dcesrv_ctx,
1613 dcesrv_sock->endpoint,
1614 srv_conn->session_info,
1615 srv_conn->event.ctx,
1617 srv_conn->server_id,
1618 DCESRV_CALL_STATE_FLAG_MAY_ASYNC,
1620 if (!NT_STATUS_IS_OK(status)) {
1621 DEBUG(0,("dcesrv_sock_accept: dcesrv_endpoint_connect failed: %s\n",
1622 nt_errstr(status)));
1623 stream_terminate_connection(srv_conn, nt_errstr(status));
1627 dcesrv_conn->transport.private_data = srv_conn;
1628 dcesrv_conn->transport.report_output_data = dcesrv_sock_report_output_data;
1630 TALLOC_FREE(srv_conn->event.fde);
1632 dcesrv_conn->send_queue = tevent_queue_create(dcesrv_conn, "dcesrv send queue");
1633 if (!dcesrv_conn->send_queue) {
1634 status = NT_STATUS_NO_MEMORY;
1635 DEBUG(0,("dcesrv_sock_accept: tevent_queue_create(%s)\n",
1636 nt_errstr(status)));
1637 stream_terminate_connection(srv_conn, nt_errstr(status));
1641 if (transport == NCACN_NP) {
1642 dcesrv_conn->auth_state.session_key = dcesrv_inherited_session_key;
1643 dcesrv_conn->stream = talloc_move(dcesrv_conn,
1644 &srv_conn->tstream);
1646 ret = tstream_bsd_existing_socket(dcesrv_conn,
1647 socket_get_fd(srv_conn->socket),
1648 &dcesrv_conn->stream);
1650 status = map_nt_error_from_unix_common(errno);
1651 DEBUG(0, ("dcesrv_sock_accept: "
1652 "failed to setup tstream: %s\n",
1653 nt_errstr(status)));
1654 stream_terminate_connection(srv_conn, nt_errstr(status));
1657 socket_set_flags(srv_conn->socket, SOCKET_FLAG_NOCLOSE);
1660 dcesrv_conn->local_address = srv_conn->local_address;
1661 dcesrv_conn->remote_address = srv_conn->remote_address;
1663 if (transport == NCALRPC) {
1667 ret = getpeereid(socket_get_fd(srv_conn->socket), &uid, &gid);
1669 status = map_nt_error_from_unix_common(errno);
1670 DEBUG(0, ("dcesrv_sock_accept: "
1671 "getpeereid() failed for NCALRPC: %s\n",
1672 nt_errstr(status)));
1673 stream_terminate_connection(srv_conn, nt_errstr(status));
1676 if (uid == dcesrv_conn->dce_ctx->initial_euid) {
1677 struct tsocket_address *r = NULL;
1679 ret = tsocket_address_unix_from_path(dcesrv_conn,
1680 "/root/ncalrpc_as_system",
1683 status = map_nt_error_from_unix_common(errno);
1684 DEBUG(0, ("dcesrv_sock_accept: "
1685 "tsocket_address_unix_from_path() failed for NCALRPC: %s\n",
1686 nt_errstr(status)));
1687 stream_terminate_connection(srv_conn, nt_errstr(status));
1690 dcesrv_conn->remote_address = r;
1694 srv_conn->private_data = dcesrv_conn;
1696 irpc_add_name(srv_conn->msg_ctx, "rpc_server");
1698 subreq = dcerpc_read_ncacn_packet_send(dcesrv_conn,
1699 dcesrv_conn->event_ctx,
1700 dcesrv_conn->stream);
1702 status = NT_STATUS_NO_MEMORY;
1703 DEBUG(0,("dcesrv_sock_accept: dcerpc_read_fragment_buffer_send(%s)\n",
1704 nt_errstr(status)));
1705 stream_terminate_connection(srv_conn, nt_errstr(status));
1708 tevent_req_set_callback(subreq, dcesrv_read_fragment_done, dcesrv_conn);
1713 static void dcesrv_read_fragment_done(struct tevent_req *subreq)
1715 struct dcesrv_connection *dce_conn = tevent_req_callback_data(subreq,
1716 struct dcesrv_connection);
1717 struct dcesrv_context *dce_ctx = dce_conn->dce_ctx;
1718 struct ncacn_packet *pkt;
1722 if (dce_conn->terminate) {
1724 * if the current connection is broken
1725 * we need to clean it up before any other connection
1727 dcesrv_terminate_connection(dce_conn, dce_conn->terminate);
1728 dcesrv_cleanup_broken_connections(dce_ctx);
1732 dcesrv_cleanup_broken_connections(dce_ctx);
1734 status = dcerpc_read_ncacn_packet_recv(subreq, dce_conn,
1736 TALLOC_FREE(subreq);
1737 if (!NT_STATUS_IS_OK(status)) {
1738 dcesrv_terminate_connection(dce_conn, nt_errstr(status));
1742 status = dcesrv_process_ncacn_packet(dce_conn, pkt, buffer);
1743 if (!NT_STATUS_IS_OK(status)) {
1744 dcesrv_terminate_connection(dce_conn, nt_errstr(status));
1748 subreq = dcerpc_read_ncacn_packet_send(dce_conn,
1749 dce_conn->event_ctx,
1752 status = NT_STATUS_NO_MEMORY;
1753 dcesrv_terminate_connection(dce_conn, nt_errstr(status));
1756 tevent_req_set_callback(subreq, dcesrv_read_fragment_done, dce_conn);
1759 static void dcesrv_sock_recv(struct stream_connection *conn, uint16_t flags)
1761 struct dcesrv_connection *dce_conn = talloc_get_type(conn->private_data,
1762 struct dcesrv_connection);
1763 dcesrv_terminate_connection(dce_conn, "dcesrv_sock_recv triggered");
1766 static void dcesrv_sock_send(struct stream_connection *conn, uint16_t flags)
1768 struct dcesrv_connection *dce_conn = talloc_get_type(conn->private_data,
1769 struct dcesrv_connection);
1770 dcesrv_terminate_connection(dce_conn, "dcesrv_sock_send triggered");
1774 static const struct stream_server_ops dcesrv_stream_ops = {
1776 .accept_connection = dcesrv_sock_accept,
1777 .recv_handler = dcesrv_sock_recv,
1778 .send_handler = dcesrv_sock_send,
1781 static NTSTATUS dcesrv_add_ep_unix(struct dcesrv_context *dce_ctx,
1782 struct loadparm_context *lp_ctx,
1783 struct dcesrv_endpoint *e,
1784 struct tevent_context *event_ctx, const struct model_ops *model_ops)
1786 struct dcesrv_socket_context *dcesrv_sock;
1789 const char *endpoint;
1791 dcesrv_sock = talloc(event_ctx, struct dcesrv_socket_context);
1792 NT_STATUS_HAVE_NO_MEMORY(dcesrv_sock);
1794 /* remember the endpoint of this socket */
1795 dcesrv_sock->endpoint = e;
1796 dcesrv_sock->dcesrv_ctx = talloc_reference(dcesrv_sock, dce_ctx);
1798 endpoint = dcerpc_binding_get_string_option(e->ep_description, "endpoint");
1800 status = stream_setup_socket(dcesrv_sock, event_ctx, lp_ctx,
1801 model_ops, &dcesrv_stream_ops,
1802 "unix", endpoint, &port,
1803 lpcfg_socket_options(lp_ctx),
1805 if (!NT_STATUS_IS_OK(status)) {
1806 DEBUG(0,("service_setup_stream_socket(path=%s) failed - %s\n",
1807 endpoint, nt_errstr(status)));
1813 static NTSTATUS dcesrv_add_ep_ncalrpc(struct dcesrv_context *dce_ctx,
1814 struct loadparm_context *lp_ctx,
1815 struct dcesrv_endpoint *e,
1816 struct tevent_context *event_ctx, const struct model_ops *model_ops)
1818 struct dcesrv_socket_context *dcesrv_sock;
1822 const char *endpoint;
1824 endpoint = dcerpc_binding_get_string_option(e->ep_description, "endpoint");
1826 if (endpoint == NULL) {
1828 * No identifier specified: use DEFAULT.
1830 * TODO: DO NOT hardcode this value anywhere else. Rather, specify
1831 * no endpoint and let the epmapper worry about it.
1833 endpoint = "DEFAULT";
1834 status = dcerpc_binding_set_string_option(e->ep_description,
1837 if (!NT_STATUS_IS_OK(status)) {
1838 DEBUG(0,("dcerpc_binding_set_string_option() failed - %s\n",
1839 nt_errstr(status)));
1844 full_path = talloc_asprintf(dce_ctx, "%s/%s", lpcfg_ncalrpc_dir(lp_ctx),
1847 dcesrv_sock = talloc(event_ctx, struct dcesrv_socket_context);
1848 NT_STATUS_HAVE_NO_MEMORY(dcesrv_sock);
1850 /* remember the endpoint of this socket */
1851 dcesrv_sock->endpoint = e;
1852 dcesrv_sock->dcesrv_ctx = talloc_reference(dcesrv_sock, dce_ctx);
1854 status = stream_setup_socket(dcesrv_sock, event_ctx, lp_ctx,
1855 model_ops, &dcesrv_stream_ops,
1856 "unix", full_path, &port,
1857 lpcfg_socket_options(lp_ctx),
1859 if (!NT_STATUS_IS_OK(status)) {
1860 DEBUG(0,("service_setup_stream_socket(identifier=%s,path=%s) failed - %s\n",
1861 endpoint, full_path, nt_errstr(status)));
1866 static NTSTATUS dcesrv_add_ep_np(struct dcesrv_context *dce_ctx,
1867 struct loadparm_context *lp_ctx,
1868 struct dcesrv_endpoint *e,
1869 struct tevent_context *event_ctx, const struct model_ops *model_ops)
1871 struct dcesrv_socket_context *dcesrv_sock;
1873 const char *endpoint;
1875 endpoint = dcerpc_binding_get_string_option(e->ep_description, "endpoint");
1876 if (endpoint == NULL) {
1877 DEBUG(0, ("Endpoint mandatory for named pipes\n"));
1878 return NT_STATUS_INVALID_PARAMETER;
1881 dcesrv_sock = talloc(event_ctx, struct dcesrv_socket_context);
1882 NT_STATUS_HAVE_NO_MEMORY(dcesrv_sock);
1884 /* remember the endpoint of this socket */
1885 dcesrv_sock->endpoint = e;
1886 dcesrv_sock->dcesrv_ctx = talloc_reference(dcesrv_sock, dce_ctx);
1888 status = tstream_setup_named_pipe(dce_ctx, event_ctx, lp_ctx,
1889 model_ops, &dcesrv_stream_ops,
1892 if (!NT_STATUS_IS_OK(status)) {
1893 DEBUG(0,("stream_setup_named_pipe(pipe=%s) failed - %s\n",
1894 endpoint, nt_errstr(status)));
1898 return NT_STATUS_OK;
1902 add a socket address to the list of events, one event per dcerpc endpoint
1904 static NTSTATUS add_socket_rpc_tcp_iface(struct dcesrv_context *dce_ctx, struct dcesrv_endpoint *e,
1905 struct tevent_context *event_ctx, const struct model_ops *model_ops,
1906 const char *address)
1908 struct dcesrv_socket_context *dcesrv_sock;
1911 const char *endpoint;
1914 endpoint = dcerpc_binding_get_string_option(e->ep_description, "endpoint");
1915 if (endpoint != NULL) {
1916 port = atoi(endpoint);
1919 dcesrv_sock = talloc(event_ctx, struct dcesrv_socket_context);
1920 NT_STATUS_HAVE_NO_MEMORY(dcesrv_sock);
1922 /* remember the endpoint of this socket */
1923 dcesrv_sock->endpoint = e;
1924 dcesrv_sock->dcesrv_ctx = talloc_reference(dcesrv_sock, dce_ctx);
1926 status = stream_setup_socket(dcesrv_sock, event_ctx, dce_ctx->lp_ctx,
1927 model_ops, &dcesrv_stream_ops,
1928 "ip", address, &port,
1929 lpcfg_socket_options(dce_ctx->lp_ctx),
1931 if (!NT_STATUS_IS_OK(status)) {
1932 DEBUG(0,("service_setup_stream_socket(address=%s,port=%u) failed - %s\n",
1933 address, port, nt_errstr(status)));
1937 snprintf(port_str, sizeof(port_str), "%u", port);
1939 status = dcerpc_binding_set_string_option(e->ep_description,
1940 "endpoint", port_str);
1941 if (!NT_STATUS_IS_OK(status)) {
1942 DEBUG(0,("dcerpc_binding_set_string_option(endpoint, %s) failed - %s\n",
1943 port_str, nt_errstr(status)));
1947 return NT_STATUS_OK;
1950 #include "lib/socket/netif.h" /* Included here to work around the fact that socket_wrapper redefines bind() */
1952 static NTSTATUS dcesrv_add_ep_tcp(struct dcesrv_context *dce_ctx,
1953 struct loadparm_context *lp_ctx,
1954 struct dcesrv_endpoint *e,
1955 struct tevent_context *event_ctx, const struct model_ops *model_ops)
1959 /* Add TCP/IP sockets */
1960 if (lpcfg_interfaces(lp_ctx) && lpcfg_bind_interfaces_only(lp_ctx)) {
1963 struct interface *ifaces;
1965 load_interface_list(dce_ctx, lp_ctx, &ifaces);
1967 num_interfaces = iface_list_count(ifaces);
1968 for(i = 0; i < num_interfaces; i++) {
1969 const char *address = iface_list_n_ip(ifaces, i);
1970 status = add_socket_rpc_tcp_iface(dce_ctx, e, event_ctx, model_ops, address);
1971 NT_STATUS_NOT_OK_RETURN(status);
1977 wcard = iface_list_wildcard(dce_ctx);
1978 NT_STATUS_HAVE_NO_MEMORY(wcard);
1979 for (i=0; wcard[i]; i++) {
1980 status = add_socket_rpc_tcp_iface(dce_ctx, e, event_ctx, model_ops, wcard[i]);
1981 if (NT_STATUS_IS_OK(status)) {
1986 if (num_binds == 0) {
1987 return NT_STATUS_INVALID_PARAMETER_MIX;
1991 return NT_STATUS_OK;
1994 NTSTATUS dcesrv_add_ep(struct dcesrv_context *dce_ctx,
1995 struct loadparm_context *lp_ctx,
1996 struct dcesrv_endpoint *e,
1997 struct tevent_context *event_ctx,
1998 const struct model_ops *model_ops)
2000 enum dcerpc_transport_t transport =
2001 dcerpc_binding_get_transport(e->ep_description);
2003 switch (transport) {
2004 case NCACN_UNIX_STREAM:
2005 return dcesrv_add_ep_unix(dce_ctx, lp_ctx, e, event_ctx, model_ops);
2008 return dcesrv_add_ep_ncalrpc(dce_ctx, lp_ctx, e, event_ctx, model_ops);
2011 return dcesrv_add_ep_tcp(dce_ctx, lp_ctx, e, event_ctx, model_ops);
2014 return dcesrv_add_ep_np(dce_ctx, lp_ctx, e, event_ctx, model_ops);
2017 return NT_STATUS_NOT_SUPPORTED;
2023 * retrieve credentials from a dce_call
2025 _PUBLIC_ struct cli_credentials *dcesrv_call_credentials(struct dcesrv_call_state *dce_call)
2027 return dce_call->conn->auth_state.session_info->credentials;
2031 * returns true if this is an authenticated call
2033 _PUBLIC_ bool dcesrv_call_authenticated(struct dcesrv_call_state *dce_call)
2035 enum security_user_level level;
2036 level = security_session_user_level(dce_call->conn->auth_state.session_info, NULL);
2037 return level >= SECURITY_USER;
2041 * retrieve account_name for a dce_call
2043 _PUBLIC_ const char *dcesrv_call_account_name(struct dcesrv_call_state *dce_call)
2045 return dce_call->context->conn->auth_state.session_info->info->account_name;