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, struct dcesrv_call_state *);
444 case DCESRV_LIST_FRAGMENTED_CALL_LIST:
445 DLIST_ADD_END(call->conn->incoming_fragmented_call_list, call, struct dcesrv_call_state *);
447 case DCESRV_LIST_PENDING_CALL_LIST:
448 DLIST_ADD_END(call->conn->pending_call_list, call, struct dcesrv_call_state *);
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, struct data_blob_list_item *);
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);
514 handle a bind request
516 static NTSTATUS dcesrv_bind(struct dcesrv_call_state *call)
518 uint32_t if_version, transfer_syntax_version;
519 struct GUID uuid, *transfer_syntax_uuid;
520 struct ncacn_packet pkt;
521 struct data_blob_list_item *rep;
523 uint32_t result=0, reason=0;
525 const struct dcesrv_interface *iface;
526 uint32_t extra_flags = 0;
529 if provided, check the assoc_group is valid
531 if (call->pkt.u.bind.assoc_group_id != 0 &&
532 lpcfg_parm_bool(call->conn->dce_ctx->lp_ctx, NULL, "dcesrv","assoc group checking", true) &&
533 dcesrv_assoc_group_find(call->conn->dce_ctx, call->pkt.u.bind.assoc_group_id) == NULL) {
534 return dcesrv_bind_nak(call, 0);
537 if (call->pkt.u.bind.num_contexts < 1 ||
538 call->pkt.u.bind.ctx_list[0].num_transfer_syntaxes < 1) {
539 return dcesrv_bind_nak(call, 0);
542 context_id = call->pkt.u.bind.ctx_list[0].context_id;
544 /* you can't bind twice on one context */
545 if (dcesrv_find_context(call->conn, context_id) != NULL) {
546 return dcesrv_bind_nak(call, 0);
549 if_version = call->pkt.u.bind.ctx_list[0].abstract_syntax.if_version;
550 uuid = call->pkt.u.bind.ctx_list[0].abstract_syntax.uuid;
552 transfer_syntax_version = call->pkt.u.bind.ctx_list[0].transfer_syntaxes[0].if_version;
553 transfer_syntax_uuid = &call->pkt.u.bind.ctx_list[0].transfer_syntaxes[0].uuid;
554 if (!GUID_equal(&ndr_transfer_syntax_ndr.uuid, transfer_syntax_uuid) != 0 ||
555 ndr_transfer_syntax_ndr.if_version != transfer_syntax_version) {
556 char *uuid_str = GUID_string(call, transfer_syntax_uuid);
557 /* we only do NDR encoded dcerpc */
558 DEBUG(0,("Non NDR transfer syntax requested - %s\n", uuid_str));
559 talloc_free(uuid_str);
560 return dcesrv_bind_nak(call, 0);
563 iface = find_interface_by_uuid(call->conn->endpoint, &uuid, if_version);
565 char *uuid_str = GUID_string(call, &uuid);
566 DEBUG(2,("Request for unknown dcerpc interface %s/%d\n", uuid_str, if_version));
567 talloc_free(uuid_str);
569 /* we don't know about that interface */
570 result = DCERPC_BIND_PROVIDER_REJECT;
571 reason = DCERPC_BIND_REASON_ASYNTAX;
575 /* add this context to the list of available context_ids */
576 struct dcesrv_connection_context *context = talloc(call->conn,
577 struct dcesrv_connection_context);
578 if (context == NULL) {
579 return dcesrv_bind_nak(call, 0);
581 context->conn = call->conn;
582 context->iface = iface;
583 context->context_id = context_id;
584 if (call->pkt.u.bind.assoc_group_id != 0) {
585 context->assoc_group = dcesrv_assoc_group_reference(context,
587 call->pkt.u.bind.assoc_group_id);
589 context->assoc_group = dcesrv_assoc_group_new(context, call->conn->dce_ctx);
591 if (context->assoc_group == NULL) {
592 talloc_free(context);
593 return dcesrv_bind_nak(call, 0);
595 context->private_data = NULL;
596 DLIST_ADD(call->conn->contexts, context);
597 call->context = context;
598 talloc_set_destructor(context, dcesrv_connection_context_destructor);
600 status = iface->bind(call, iface, if_version);
601 if (!NT_STATUS_IS_OK(status)) {
602 char *uuid_str = GUID_string(call, &uuid);
603 DEBUG(2,("Request for dcerpc interface %s/%d rejected: %s\n",
604 uuid_str, if_version, nt_errstr(status)));
605 talloc_free(uuid_str);
606 /* we don't want to trigger the iface->unbind() hook */
607 context->iface = NULL;
608 talloc_free(call->context);
609 call->context = NULL;
610 return dcesrv_bind_nak(call, 0);
614 if (call->conn->cli_max_recv_frag == 0) {
615 call->conn->cli_max_recv_frag = MIN(0x2000, call->pkt.u.bind.max_recv_frag);
618 if ((call->pkt.pfc_flags & DCERPC_PFC_FLAG_CONC_MPX) &&
619 (call->state_flags & DCESRV_CALL_STATE_FLAG_MULTIPLEXED)) {
620 call->context->conn->state_flags |= DCESRV_CALL_STATE_FLAG_MULTIPLEXED;
621 extra_flags |= DCERPC_PFC_FLAG_CONC_MPX;
624 if (call->state_flags & DCESRV_CALL_STATE_FLAG_PROCESS_PENDING_CALL) {
625 call->context->conn->state_flags |= DCESRV_CALL_STATE_FLAG_PROCESS_PENDING_CALL;
628 /* handle any authentication that is being requested */
629 if (!dcesrv_auth_bind(call)) {
630 talloc_free(call->context);
631 call->context = NULL;
632 return dcesrv_bind_nak(call, DCERPC_BIND_REASON_INVALID_AUTH_TYPE);
635 /* setup a bind_ack */
636 dcesrv_init_hdr(&pkt, lpcfg_rpc_big_endian(call->conn->dce_ctx->lp_ctx));
638 pkt.call_id = call->pkt.call_id;
639 pkt.ptype = DCERPC_PKT_BIND_ACK;
640 pkt.pfc_flags = DCERPC_PFC_FLAG_FIRST | DCERPC_PFC_FLAG_LAST | extra_flags;
641 pkt.u.bind_ack.max_xmit_frag = call->conn->cli_max_recv_frag;
642 pkt.u.bind_ack.max_recv_frag = 0x2000;
645 make it possible for iface->bind() to specify the assoc_group_id
646 This helps the openchange mapiproxy plugin to work correctly.
651 pkt.u.bind_ack.assoc_group_id = call->context->assoc_group->id;
653 pkt.u.bind_ack.assoc_group_id = DUMMY_ASSOC_GROUP;
657 /* FIXME: Use pipe name as specified by endpoint instead of interface name */
658 pkt.u.bind_ack.secondary_address = talloc_asprintf(call, "\\PIPE\\%s", iface->name);
660 pkt.u.bind_ack.secondary_address = "";
662 pkt.u.bind_ack.num_results = 1;
663 pkt.u.bind_ack.ctx_list = talloc(call, struct dcerpc_ack_ctx);
664 if (!pkt.u.bind_ack.ctx_list) {
665 talloc_free(call->context);
666 call->context = NULL;
667 return NT_STATUS_NO_MEMORY;
669 pkt.u.bind_ack.ctx_list[0].result = result;
670 pkt.u.bind_ack.ctx_list[0].reason.value = reason;
671 pkt.u.bind_ack.ctx_list[0].syntax = ndr_transfer_syntax_ndr;
672 pkt.u.bind_ack.auth_info = data_blob(NULL, 0);
674 status = dcesrv_auth_bind_ack(call, &pkt);
675 if (!NT_STATUS_IS_OK(status)) {
676 talloc_free(call->context);
677 call->context = NULL;
678 return dcesrv_bind_nak(call, 0);
681 rep = talloc(call, struct data_blob_list_item);
683 talloc_free(call->context);
684 call->context = NULL;
685 return NT_STATUS_NO_MEMORY;
688 status = ncacn_push_auth(&rep->blob, call, &pkt,
689 call->conn->auth_state.auth_info);
690 if (!NT_STATUS_IS_OK(status)) {
691 talloc_free(call->context);
692 call->context = NULL;
696 dcerpc_set_frag_length(&rep->blob, rep->blob.length);
698 DLIST_ADD_END(call->replies, rep, struct data_blob_list_item *);
699 dcesrv_call_set_list(call, DCESRV_LIST_CALL_LIST);
701 if (call->conn->call_list && call->conn->call_list->replies) {
702 if (call->conn->transport.report_output_data) {
703 call->conn->transport.report_output_data(call->conn);
712 handle a auth3 request
714 static NTSTATUS dcesrv_auth3(struct dcesrv_call_state *call)
716 /* handle the auth3 in the auth code */
717 if (!dcesrv_auth_auth3(call)) {
718 return dcesrv_fault(call, DCERPC_FAULT_OTHER);
723 /* we don't send a reply to a auth3 request, except by a
730 handle a bind request
732 static NTSTATUS dcesrv_alter_new_context(struct dcesrv_call_state *call, uint32_t context_id)
734 uint32_t if_version, transfer_syntax_version;
735 struct dcesrv_connection_context *context;
736 const struct dcesrv_interface *iface;
737 struct GUID uuid, *transfer_syntax_uuid;
740 if_version = call->pkt.u.alter.ctx_list[0].abstract_syntax.if_version;
741 uuid = call->pkt.u.alter.ctx_list[0].abstract_syntax.uuid;
743 transfer_syntax_version = call->pkt.u.alter.ctx_list[0].transfer_syntaxes[0].if_version;
744 transfer_syntax_uuid = &call->pkt.u.alter.ctx_list[0].transfer_syntaxes[0].uuid;
745 if (!GUID_equal(transfer_syntax_uuid, &ndr_transfer_syntax_ndr.uuid) ||
746 ndr_transfer_syntax_ndr.if_version != transfer_syntax_version) {
747 /* we only do NDR encoded dcerpc */
748 return NT_STATUS_RPC_PROTSEQ_NOT_SUPPORTED;
751 iface = find_interface_by_uuid(call->conn->endpoint, &uuid, if_version);
753 char *uuid_str = GUID_string(call, &uuid);
754 DEBUG(2,("Request for unknown dcerpc interface %s/%d\n", uuid_str, if_version));
755 talloc_free(uuid_str);
756 return NT_STATUS_RPC_PROTSEQ_NOT_SUPPORTED;
759 /* add this context to the list of available context_ids */
760 context = talloc(call->conn, struct dcesrv_connection_context);
761 if (context == NULL) {
762 return NT_STATUS_NO_MEMORY;
764 context->conn = call->conn;
765 context->iface = iface;
766 context->context_id = context_id;
767 if (call->pkt.u.alter.assoc_group_id != 0) {
768 context->assoc_group = dcesrv_assoc_group_reference(context,
770 call->pkt.u.alter.assoc_group_id);
772 context->assoc_group = dcesrv_assoc_group_new(context, call->conn->dce_ctx);
774 if (context->assoc_group == NULL) {
775 talloc_free(context);
776 call->context = NULL;
777 return NT_STATUS_NO_MEMORY;
779 context->private_data = NULL;
780 DLIST_ADD(call->conn->contexts, context);
781 call->context = context;
782 talloc_set_destructor(context, dcesrv_connection_context_destructor);
784 status = iface->bind(call, iface, if_version);
785 if (!NT_STATUS_IS_OK(status)) {
786 /* we don't want to trigger the iface->unbind() hook */
787 context->iface = NULL;
788 talloc_free(context);
789 call->context = NULL;
798 handle a alter context request
800 static NTSTATUS dcesrv_alter(struct dcesrv_call_state *call)
802 struct ncacn_packet pkt;
803 struct data_blob_list_item *rep;
805 uint32_t result=0, reason=0;
807 uint32_t extra_flags = 0;
809 /* handle any authentication that is being requested */
810 if (!dcesrv_auth_alter(call)) {
811 /* TODO: work out the right reject code */
812 result = DCERPC_BIND_PROVIDER_REJECT;
813 reason = DCERPC_BIND_REASON_ASYNTAX;
816 context_id = call->pkt.u.alter.ctx_list[0].context_id;
818 /* see if they are asking for a new interface */
820 call->context = dcesrv_find_context(call->conn, context_id);
821 if (!call->context) {
822 status = dcesrv_alter_new_context(call, context_id);
823 if (!NT_STATUS_IS_OK(status)) {
824 result = DCERPC_BIND_PROVIDER_REJECT;
825 reason = DCERPC_BIND_REASON_ASYNTAX;
831 call->pkt.u.alter.assoc_group_id != 0 &&
832 lpcfg_parm_bool(call->conn->dce_ctx->lp_ctx, NULL, "dcesrv","assoc group checking", true) &&
833 call->pkt.u.alter.assoc_group_id != call->context->assoc_group->id) {
834 DEBUG(0,(__location__ ": Failed attempt to use new assoc_group in alter context (0x%08x 0x%08x)\n",
835 call->context->assoc_group->id, call->pkt.u.alter.assoc_group_id));
836 /* TODO: can they ask for a new association group? */
837 result = DCERPC_BIND_PROVIDER_REJECT;
838 reason = DCERPC_BIND_REASON_ASYNTAX;
841 if ((call->pkt.pfc_flags & DCERPC_PFC_FLAG_CONC_MPX)) {
842 if (call->context->conn->state_flags & DCESRV_CALL_STATE_FLAG_MULTIPLEXED) {
843 extra_flags |= DCERPC_PFC_FLAG_CONC_MPX;
847 if (call->state_flags & DCESRV_CALL_STATE_FLAG_PROCESS_PENDING_CALL) {
848 call->context->conn->state_flags |= DCESRV_CALL_STATE_FLAG_PROCESS_PENDING_CALL;
851 /* setup a alter_resp */
852 dcesrv_init_hdr(&pkt, lpcfg_rpc_big_endian(call->conn->dce_ctx->lp_ctx));
854 pkt.call_id = call->pkt.call_id;
855 pkt.ptype = DCERPC_PKT_ALTER_RESP;
856 pkt.pfc_flags = DCERPC_PFC_FLAG_FIRST | DCERPC_PFC_FLAG_LAST | extra_flags;
857 pkt.u.alter_resp.max_xmit_frag = 0x2000;
858 pkt.u.alter_resp.max_recv_frag = 0x2000;
860 pkt.u.alter_resp.assoc_group_id = call->context->assoc_group->id;
862 pkt.u.alter_resp.assoc_group_id = 0;
864 pkt.u.alter_resp.num_results = 1;
865 pkt.u.alter_resp.ctx_list = talloc_array(call, struct dcerpc_ack_ctx, 1);
866 if (!pkt.u.alter_resp.ctx_list) {
867 return NT_STATUS_NO_MEMORY;
869 pkt.u.alter_resp.ctx_list[0].result = result;
870 pkt.u.alter_resp.ctx_list[0].reason.value = reason;
871 pkt.u.alter_resp.ctx_list[0].syntax = ndr_transfer_syntax_ndr;
872 pkt.u.alter_resp.auth_info = data_blob(NULL, 0);
873 pkt.u.alter_resp.secondary_address = "";
875 status = dcesrv_auth_alter_ack(call, &pkt);
876 if (!NT_STATUS_IS_OK(status)) {
877 if (NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)
878 || NT_STATUS_EQUAL(status, NT_STATUS_LOGON_FAILURE)
879 || NT_STATUS_EQUAL(status, NT_STATUS_NO_SUCH_USER)
880 || NT_STATUS_EQUAL(status, NT_STATUS_WRONG_PASSWORD)) {
881 return dcesrv_fault(call, DCERPC_FAULT_ACCESS_DENIED);
883 return dcesrv_fault(call, 0);
886 rep = talloc(call, struct data_blob_list_item);
888 return NT_STATUS_NO_MEMORY;
891 status = ncacn_push_auth(&rep->blob, call, &pkt, call->conn->auth_state.auth_info);
892 if (!NT_STATUS_IS_OK(status)) {
896 dcerpc_set_frag_length(&rep->blob, rep->blob.length);
898 DLIST_ADD_END(call->replies, rep, struct data_blob_list_item *);
899 dcesrv_call_set_list(call, DCESRV_LIST_CALL_LIST);
901 if (call->conn->call_list && call->conn->call_list->replies) {
902 if (call->conn->transport.report_output_data) {
903 call->conn->transport.report_output_data(call->conn);
911 possibly save the call for inspection with ndrdump
913 static void dcesrv_save_call(struct dcesrv_call_state *call, const char *why)
917 const char *dump_dir;
918 dump_dir = lpcfg_parm_string(call->conn->dce_ctx->lp_ctx, NULL, "dcesrv", "stubs directory");
922 fname = talloc_asprintf(call, "%s/RPC-%s-%u-%s.dat",
924 call->context->iface->name,
925 call->pkt.u.request.opnum,
927 if (file_save(fname, call->pkt.u.request.stub_and_verifier.data, call->pkt.u.request.stub_and_verifier.length)) {
928 DEBUG(0,("RPC SAVED %s\n", fname));
934 static NTSTATUS dcesrv_check_verification_trailer(struct dcesrv_call_state *call)
936 TALLOC_CTX *frame = talloc_stackframe();
937 const uint32_t bitmask1 = call->conn->auth_state.client_hdr_signing ?
938 DCERPC_SEC_VT_CLIENT_SUPPORTS_HEADER_SIGNING : 0;
939 const struct dcerpc_sec_vt_pcontext pcontext = {
940 .abstract_syntax = call->context->iface->syntax_id,
941 .transfer_syntax = ndr_transfer_syntax_ndr,
943 const struct dcerpc_sec_vt_header2 header2 =
944 dcerpc_sec_vt_header2_from_ncacn_packet(&call->pkt);
945 enum ndr_err_code ndr_err;
946 struct dcerpc_sec_verification_trailer *vt = NULL;
947 NTSTATUS status = NT_STATUS_OK;
950 SMB_ASSERT(call->pkt.ptype == DCERPC_PKT_REQUEST);
952 ndr_err = ndr_pop_dcerpc_sec_verification_trailer(call->ndr_pull,
954 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
955 status = ndr_map_error2ntstatus(ndr_err);
959 ok = dcerpc_sec_verification_trailer_check(vt, &bitmask1,
960 &pcontext, &header2);
962 status = NT_STATUS_ACCESS_DENIED;
971 handle a dcerpc request packet
973 static NTSTATUS dcesrv_request(struct dcesrv_call_state *call)
975 struct ndr_pull *pull;
977 struct dcesrv_connection_context *context;
979 /* if authenticated, and the mech we use can't do async replies, don't use them... */
980 if (call->conn->auth_state.gensec_security &&
981 !gensec_have_feature(call->conn->auth_state.gensec_security, GENSEC_FEATURE_ASYNC_REPLIES)) {
982 call->state_flags &= ~DCESRV_CALL_STATE_FLAG_MAY_ASYNC;
985 context = dcesrv_find_context(call->conn, call->pkt.u.request.context_id);
986 if (context == NULL) {
987 return dcesrv_fault(call, DCERPC_FAULT_UNK_IF);
990 pull = ndr_pull_init_blob(&call->pkt.u.request.stub_and_verifier, call);
991 NT_STATUS_HAVE_NO_MEMORY(pull);
993 pull->flags |= LIBNDR_FLAG_REF_ALLOC;
995 call->context = context;
996 call->ndr_pull = pull;
998 if (!(call->pkt.drep[0] & DCERPC_DREP_LE)) {
999 pull->flags |= LIBNDR_FLAG_BIGENDIAN;
1002 status = dcesrv_check_verification_trailer(call);
1003 if (!NT_STATUS_IS_OK(status)) {
1004 uint32_t faultcode = DCERPC_FAULT_OTHER;
1005 if (NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
1006 faultcode = DCERPC_FAULT_ACCESS_DENIED;
1008 DEBUG(10, ("dcesrv_check_verification_trailer failed: %s\n",
1009 nt_errstr(status)));
1010 return dcesrv_fault(call, faultcode);
1013 /* unravel the NDR for the packet */
1014 status = context->iface->ndr_pull(call, call, pull, &call->r);
1015 if (!NT_STATUS_IS_OK(status)) {
1016 if (call->fault_code == DCERPC_FAULT_OP_RNG_ERROR) {
1017 /* we got an unknown call */
1018 DEBUG(3,(__location__ ": Unknown RPC call %u on %s\n",
1019 call->pkt.u.request.opnum, context->iface->name));
1020 dcesrv_save_call(call, "unknown");
1022 dcesrv_save_call(call, "pullfail");
1024 return dcesrv_fault(call, call->fault_code);
1027 if (pull->offset != pull->data_size) {
1028 dcesrv_save_call(call, "extrabytes");
1029 DEBUG(3,("Warning: %d extra bytes in incoming RPC request\n",
1030 pull->data_size - pull->offset));
1033 /* call the dispatch function */
1034 status = context->iface->dispatch(call, call, call->r);
1035 if (!NT_STATUS_IS_OK(status)) {
1036 DEBUG(5,("dcerpc fault in call %s:%02x - %s\n",
1037 context->iface->name,
1038 call->pkt.u.request.opnum,
1039 dcerpc_errstr(pull, call->fault_code)));
1040 return dcesrv_fault(call, call->fault_code);
1043 /* add the call to the pending list */
1044 dcesrv_call_set_list(call, DCESRV_LIST_PENDING_CALL_LIST);
1046 if (call->state_flags & DCESRV_CALL_STATE_FLAG_ASYNC) {
1047 return NT_STATUS_OK;
1050 return dcesrv_reply(call);
1055 remove the call from the right list when freed
1057 static int dcesrv_call_dequeue(struct dcesrv_call_state *call)
1059 dcesrv_call_set_list(call, DCESRV_LIST_NONE);
1063 _PUBLIC_ const struct tsocket_address *dcesrv_connection_get_local_address(struct dcesrv_connection *conn)
1065 return conn->local_address;
1068 _PUBLIC_ const struct tsocket_address *dcesrv_connection_get_remote_address(struct dcesrv_connection *conn)
1070 return conn->remote_address;
1074 process some input to a dcerpc endpoint server.
1076 NTSTATUS dcesrv_process_ncacn_packet(struct dcesrv_connection *dce_conn,
1077 struct ncacn_packet *pkt,
1081 struct dcesrv_call_state *call;
1083 call = talloc_zero(dce_conn, struct dcesrv_call_state);
1085 data_blob_free(&blob);
1087 return NT_STATUS_NO_MEMORY;
1089 call->conn = dce_conn;
1090 call->event_ctx = dce_conn->event_ctx;
1091 call->msg_ctx = dce_conn->msg_ctx;
1092 call->state_flags = call->conn->state_flags;
1093 call->time = timeval_current();
1094 call->list = DCESRV_LIST_NONE;
1096 talloc_steal(call, pkt);
1097 talloc_steal(call, blob.data);
1100 talloc_set_destructor(call, dcesrv_call_dequeue);
1102 /* we have to check the signing here, before combining the
1104 if (call->pkt.ptype == DCERPC_PKT_REQUEST &&
1105 !dcesrv_auth_request(call, &blob)) {
1106 return dcesrv_fault(call, DCERPC_FAULT_ACCESS_DENIED);
1109 /* see if this is a continued packet */
1110 if (call->pkt.ptype == DCERPC_PKT_REQUEST &&
1111 !(call->pkt.pfc_flags & DCERPC_PFC_FLAG_FIRST)) {
1112 struct dcesrv_call_state *call2 = call;
1113 uint32_t alloc_size;
1115 /* we only allow fragmented requests, no other packet types */
1116 if (call->pkt.ptype != DCERPC_PKT_REQUEST) {
1117 return dcesrv_fault(call2, DCERPC_FAULT_OTHER);
1120 /* this is a continuation of an existing call - find the call
1121 then tack it on the end */
1122 call = dcesrv_find_fragmented_call(dce_conn, call2->pkt.call_id);
1124 return dcesrv_fault(call2, DCERPC_FAULT_OTHER);
1127 if (call->pkt.ptype != call2->pkt.ptype) {
1128 /* trying to play silly buggers are we? */
1129 return dcesrv_fault(call2, DCERPC_NCA_S_PROTO_ERROR);
1131 if (memcmp(call->pkt.drep, call2->pkt.drep, sizeof(pkt->drep)) != 0) {
1132 return dcesrv_fault(call2, DCERPC_NCA_S_PROTO_ERROR);
1134 if (call->pkt.call_id != call2->pkt.call_id) {
1135 return dcesrv_fault(call2, DCERPC_NCA_S_PROTO_ERROR);
1137 if (call->pkt.u.request.context_id != call2->pkt.u.request.context_id) {
1138 return dcesrv_fault(call2, DCERPC_NCA_S_PROTO_ERROR);
1140 if (call->pkt.u.request.opnum != call2->pkt.u.request.opnum) {
1141 return dcesrv_fault(call2, DCERPC_NCA_S_PROTO_ERROR);
1144 alloc_size = call->pkt.u.request.stub_and_verifier.length +
1145 call2->pkt.u.request.stub_and_verifier.length;
1146 if (call->pkt.u.request.alloc_hint > alloc_size) {
1147 alloc_size = call->pkt.u.request.alloc_hint;
1150 call->pkt.u.request.stub_and_verifier.data =
1151 talloc_realloc(call,
1152 call->pkt.u.request.stub_and_verifier.data,
1153 uint8_t, alloc_size);
1154 if (!call->pkt.u.request.stub_and_verifier.data) {
1155 return dcesrv_fault(call2, DCERPC_FAULT_OTHER);
1157 memcpy(call->pkt.u.request.stub_and_verifier.data +
1158 call->pkt.u.request.stub_and_verifier.length,
1159 call2->pkt.u.request.stub_and_verifier.data,
1160 call2->pkt.u.request.stub_and_verifier.length);
1161 call->pkt.u.request.stub_and_verifier.length +=
1162 call2->pkt.u.request.stub_and_verifier.length;
1164 call->pkt.pfc_flags |= (call2->pkt.pfc_flags & DCERPC_PFC_FLAG_LAST);
1169 /* this may not be the last pdu in the chain - if its isn't then
1170 just put it on the incoming_fragmented_call_list and wait for the rest */
1171 if (call->pkt.ptype == DCERPC_PKT_REQUEST &&
1172 !(call->pkt.pfc_flags & DCERPC_PFC_FLAG_LAST)) {
1173 dcesrv_call_set_list(call, DCESRV_LIST_FRAGMENTED_CALL_LIST);
1174 return NT_STATUS_OK;
1177 /* This removes any fragments we may have had stashed away */
1178 dcesrv_call_set_list(call, DCESRV_LIST_NONE);
1180 switch (call->pkt.ptype) {
1181 case DCERPC_PKT_BIND:
1182 status = dcesrv_bind(call);
1184 case DCERPC_PKT_AUTH3:
1185 status = dcesrv_auth3(call);
1187 case DCERPC_PKT_ALTER:
1188 status = dcesrv_alter(call);
1190 case DCERPC_PKT_REQUEST:
1191 status = dcesrv_request(call);
1194 status = NT_STATUS_INVALID_PARAMETER;
1198 /* if we are going to be sending a reply then add
1199 it to the list of pending calls. We add it to the end to keep the call
1200 list in the order we will answer */
1201 if (!NT_STATUS_IS_OK(status)) {
1208 _PUBLIC_ NTSTATUS dcesrv_init_context(TALLOC_CTX *mem_ctx,
1209 struct loadparm_context *lp_ctx,
1210 const char **endpoint_servers, struct dcesrv_context **_dce_ctx)
1213 struct dcesrv_context *dce_ctx;
1216 if (!endpoint_servers) {
1217 DEBUG(0,("dcesrv_init_context: no endpoint servers configured\n"));
1218 return NT_STATUS_INTERNAL_ERROR;
1221 dce_ctx = talloc(mem_ctx, struct dcesrv_context);
1222 NT_STATUS_HAVE_NO_MEMORY(dce_ctx);
1223 dce_ctx->initial_euid = geteuid();
1224 dce_ctx->endpoint_list = NULL;
1225 dce_ctx->lp_ctx = lp_ctx;
1226 dce_ctx->assoc_groups_idr = idr_init(dce_ctx);
1227 NT_STATUS_HAVE_NO_MEMORY(dce_ctx->assoc_groups_idr);
1228 dce_ctx->broken_connections = NULL;
1230 for (i=0;endpoint_servers[i];i++) {
1231 const struct dcesrv_endpoint_server *ep_server;
1233 ep_server = dcesrv_ep_server_byname(endpoint_servers[i]);
1235 DEBUG(0,("dcesrv_init_context: failed to find endpoint server = '%s'\n", endpoint_servers[i]));
1236 return NT_STATUS_INTERNAL_ERROR;
1239 status = ep_server->init_server(dce_ctx, ep_server);
1240 if (!NT_STATUS_IS_OK(status)) {
1241 DEBUG(0,("dcesrv_init_context: failed to init endpoint server = '%s': %s\n", endpoint_servers[i],
1242 nt_errstr(status)));
1247 *_dce_ctx = dce_ctx;
1248 return NT_STATUS_OK;
1251 /* the list of currently registered DCERPC endpoint servers.
1253 static struct ep_server {
1254 struct dcesrv_endpoint_server *ep_server;
1255 } *ep_servers = NULL;
1256 static int num_ep_servers;
1259 register a DCERPC endpoint server.
1261 The 'name' can be later used by other backends to find the operations
1262 structure for this backend.
1264 The 'type' is used to specify whether this is for a disk, printer or IPC$ share
1266 _PUBLIC_ NTSTATUS dcerpc_register_ep_server(const void *_ep_server)
1268 const struct dcesrv_endpoint_server *ep_server = _ep_server;
1270 if (dcesrv_ep_server_byname(ep_server->name) != NULL) {
1271 /* its already registered! */
1272 DEBUG(0,("DCERPC endpoint server '%s' already registered\n",
1274 return NT_STATUS_OBJECT_NAME_COLLISION;
1277 ep_servers = realloc_p(ep_servers, struct ep_server, num_ep_servers+1);
1279 smb_panic("out of memory in dcerpc_register");
1282 ep_servers[num_ep_servers].ep_server = smb_xmemdup(ep_server, sizeof(*ep_server));
1283 ep_servers[num_ep_servers].ep_server->name = smb_xstrdup(ep_server->name);
1287 DEBUG(3,("DCERPC endpoint server '%s' registered\n",
1290 return NT_STATUS_OK;
1294 return the operations structure for a named backend of the specified type
1296 const struct dcesrv_endpoint_server *dcesrv_ep_server_byname(const char *name)
1300 for (i=0;i<num_ep_servers;i++) {
1301 if (strcmp(ep_servers[i].ep_server->name, name) == 0) {
1302 return ep_servers[i].ep_server;
1309 void dcerpc_server_init(struct loadparm_context *lp_ctx)
1311 static bool initialized;
1312 #define _MODULE_PROTO(init) extern NTSTATUS init(void);
1313 STATIC_dcerpc_server_MODULES_PROTO;
1314 init_module_fn static_init[] = { STATIC_dcerpc_server_MODULES };
1315 init_module_fn *shared_init;
1322 shared_init = load_samba_modules(NULL, "dcerpc_server");
1324 run_init_functions(static_init);
1325 run_init_functions(shared_init);
1327 talloc_free(shared_init);
1331 return the DCERPC module version, and the size of some critical types
1332 This can be used by endpoint server modules to either detect compilation errors, or provide
1333 multiple implementations for different smbd compilation options in one module
1335 const struct dcesrv_critical_sizes *dcerpc_module_version(void)
1337 static const struct dcesrv_critical_sizes critical_sizes = {
1338 DCERPC_MODULE_VERSION,
1339 sizeof(struct dcesrv_context),
1340 sizeof(struct dcesrv_endpoint),
1341 sizeof(struct dcesrv_endpoint_server),
1342 sizeof(struct dcesrv_interface),
1343 sizeof(struct dcesrv_if_list),
1344 sizeof(struct dcesrv_connection),
1345 sizeof(struct dcesrv_call_state),
1346 sizeof(struct dcesrv_auth),
1347 sizeof(struct dcesrv_handle)
1350 return &critical_sizes;
1353 static void dcesrv_terminate_connection(struct dcesrv_connection *dce_conn, const char *reason)
1355 struct dcesrv_context *dce_ctx = dce_conn->dce_ctx;
1356 struct stream_connection *srv_conn;
1357 srv_conn = talloc_get_type(dce_conn->transport.private_data,
1358 struct stream_connection);
1360 if (dce_conn->pending_call_list == NULL) {
1361 char *full_reason = talloc_asprintf(dce_conn, "dcesrv: %s", reason);
1363 DLIST_REMOVE(dce_ctx->broken_connections, dce_conn);
1364 stream_terminate_connection(srv_conn, full_reason ? full_reason : reason);
1368 if (dce_conn->terminate != NULL) {
1372 DEBUG(3,("dcesrv: terminating connection due to '%s' defered due to pending calls\n",
1374 dce_conn->terminate = talloc_strdup(dce_conn, reason);
1375 if (dce_conn->terminate == NULL) {
1376 dce_conn->terminate = "dcesrv: defered terminating connection - no memory";
1378 DLIST_ADD_END(dce_ctx->broken_connections, dce_conn, NULL);
1381 static void dcesrv_cleanup_broken_connections(struct dcesrv_context *dce_ctx)
1383 struct dcesrv_connection *cur, *next;
1385 next = dce_ctx->broken_connections;
1386 while (next != NULL) {
1390 if (cur->state_flags & DCESRV_CALL_STATE_FLAG_PROCESS_PENDING_CALL) {
1391 struct dcesrv_connection_context *context_cur, *context_next;
1393 context_next = cur->contexts;
1394 while (context_next != NULL) {
1395 context_cur = context_next;
1396 context_next = context_cur->next;
1398 dcesrv_connection_context_destructor(context_cur);
1402 dcesrv_terminate_connection(cur, cur->terminate);
1406 /* We need this include to be able to compile on some plateforms
1407 * (ie. freebsd 7.2) as it seems that <sys/uio.h> is not included
1409 * It has to be that deep because otherwise we have a conflict on
1410 * const struct dcesrv_interface declaration.
1411 * This is mostly due to socket_wrapper defining #define bind swrap_bind
1412 * which conflict with the bind used before.
1414 #include "system/network.h"
1416 struct dcesrv_sock_reply_state {
1417 struct dcesrv_connection *dce_conn;
1418 struct dcesrv_call_state *call;
1422 static void dcesrv_sock_reply_done(struct tevent_req *subreq);
1424 static void dcesrv_sock_report_output_data(struct dcesrv_connection *dce_conn)
1426 struct dcesrv_call_state *call;
1428 call = dce_conn->call_list;
1429 if (!call || !call->replies) {
1433 while (call->replies) {
1434 struct data_blob_list_item *rep = call->replies;
1435 struct dcesrv_sock_reply_state *substate;
1436 struct tevent_req *subreq;
1438 substate = talloc(call, struct dcesrv_sock_reply_state);
1440 dcesrv_terminate_connection(dce_conn, "no memory");
1444 substate->dce_conn = dce_conn;
1445 substate->call = NULL;
1447 DLIST_REMOVE(call->replies, rep);
1449 if (call->replies == NULL) {
1450 substate->call = call;
1453 substate->iov.iov_base = (void *) rep->blob.data;
1454 substate->iov.iov_len = rep->blob.length;
1456 subreq = tstream_writev_queue_send(substate,
1457 dce_conn->event_ctx,
1459 dce_conn->send_queue,
1462 dcesrv_terminate_connection(dce_conn, "no memory");
1465 tevent_req_set_callback(subreq, dcesrv_sock_reply_done,
1469 DLIST_REMOVE(call->conn->call_list, call);
1470 call->list = DCESRV_LIST_NONE;
1473 static void dcesrv_sock_reply_done(struct tevent_req *subreq)
1475 struct dcesrv_sock_reply_state *substate = tevent_req_callback_data(subreq,
1476 struct dcesrv_sock_reply_state);
1480 struct dcesrv_call_state *call = substate->call;
1482 ret = tstream_writev_queue_recv(subreq, &sys_errno);
1483 TALLOC_FREE(subreq);
1485 status = map_nt_error_from_unix_common(sys_errno);
1486 dcesrv_terminate_connection(substate->dce_conn, nt_errstr(status));
1490 talloc_free(substate);
1499 struct dcesrv_socket_context {
1500 const struct dcesrv_endpoint *endpoint;
1501 struct dcesrv_context *dcesrv_ctx;
1505 static void dcesrv_read_fragment_done(struct tevent_req *subreq);
1507 static void dcesrv_sock_accept(struct stream_connection *srv_conn)
1510 struct dcesrv_socket_context *dcesrv_sock =
1511 talloc_get_type(srv_conn->private_data, struct dcesrv_socket_context);
1512 enum dcerpc_transport_t transport =
1513 dcerpc_binding_get_transport(dcesrv_sock->endpoint->ep_description);
1514 struct dcesrv_connection *dcesrv_conn = NULL;
1516 struct tevent_req *subreq;
1517 struct loadparm_context *lp_ctx = dcesrv_sock->dcesrv_ctx->lp_ctx;
1519 dcesrv_cleanup_broken_connections(dcesrv_sock->dcesrv_ctx);
1521 if (!srv_conn->session_info) {
1522 status = auth_anonymous_session_info(srv_conn,
1524 &srv_conn->session_info);
1525 if (!NT_STATUS_IS_OK(status)) {
1526 DEBUG(0,("dcesrv_sock_accept: auth_anonymous_session_info failed: %s\n",
1527 nt_errstr(status)));
1528 stream_terminate_connection(srv_conn, nt_errstr(status));
1533 status = dcesrv_endpoint_connect(dcesrv_sock->dcesrv_ctx,
1535 dcesrv_sock->endpoint,
1536 srv_conn->session_info,
1537 srv_conn->event.ctx,
1539 srv_conn->server_id,
1540 DCESRV_CALL_STATE_FLAG_MAY_ASYNC,
1542 if (!NT_STATUS_IS_OK(status)) {
1543 DEBUG(0,("dcesrv_sock_accept: dcesrv_endpoint_connect failed: %s\n",
1544 nt_errstr(status)));
1545 stream_terminate_connection(srv_conn, nt_errstr(status));
1549 dcesrv_conn->transport.private_data = srv_conn;
1550 dcesrv_conn->transport.report_output_data = dcesrv_sock_report_output_data;
1552 TALLOC_FREE(srv_conn->event.fde);
1554 dcesrv_conn->send_queue = tevent_queue_create(dcesrv_conn, "dcesrv send queue");
1555 if (!dcesrv_conn->send_queue) {
1556 status = NT_STATUS_NO_MEMORY;
1557 DEBUG(0,("dcesrv_sock_accept: tevent_queue_create(%s)\n",
1558 nt_errstr(status)));
1559 stream_terminate_connection(srv_conn, nt_errstr(status));
1563 if (transport == NCACN_NP) {
1564 dcesrv_conn->auth_state.session_key = dcesrv_inherited_session_key;
1565 dcesrv_conn->stream = talloc_move(dcesrv_conn,
1566 &srv_conn->tstream);
1568 ret = tstream_bsd_existing_socket(dcesrv_conn,
1569 socket_get_fd(srv_conn->socket),
1570 &dcesrv_conn->stream);
1572 status = map_nt_error_from_unix_common(errno);
1573 DEBUG(0, ("dcesrv_sock_accept: "
1574 "failed to setup tstream: %s\n",
1575 nt_errstr(status)));
1576 stream_terminate_connection(srv_conn, nt_errstr(status));
1579 socket_set_flags(srv_conn->socket, SOCKET_FLAG_NOCLOSE);
1582 dcesrv_conn->local_address = srv_conn->local_address;
1583 dcesrv_conn->remote_address = srv_conn->remote_address;
1585 if (transport == NCALRPC) {
1589 ret = getpeereid(socket_get_fd(srv_conn->socket), &uid, &gid);
1591 status = map_nt_error_from_unix_common(errno);
1592 DEBUG(0, ("dcesrv_sock_accept: "
1593 "getpeereid() failed for NCALRPC: %s\n",
1594 nt_errstr(status)));
1595 stream_terminate_connection(srv_conn, nt_errstr(status));
1598 if (uid == dcesrv_conn->dce_ctx->initial_euid) {
1599 struct tsocket_address *r = NULL;
1601 ret = tsocket_address_unix_from_path(dcesrv_conn,
1602 "/root/ncalrpc_as_system",
1605 status = map_nt_error_from_unix_common(errno);
1606 DEBUG(0, ("dcesrv_sock_accept: "
1607 "tsocket_address_unix_from_path() failed for NCALRPC: %s\n",
1608 nt_errstr(status)));
1609 stream_terminate_connection(srv_conn, nt_errstr(status));
1612 dcesrv_conn->remote_address = r;
1616 srv_conn->private_data = dcesrv_conn;
1618 irpc_add_name(srv_conn->msg_ctx, "rpc_server");
1620 subreq = dcerpc_read_ncacn_packet_send(dcesrv_conn,
1621 dcesrv_conn->event_ctx,
1622 dcesrv_conn->stream);
1624 status = NT_STATUS_NO_MEMORY;
1625 DEBUG(0,("dcesrv_sock_accept: dcerpc_read_fragment_buffer_send(%s)\n",
1626 nt_errstr(status)));
1627 stream_terminate_connection(srv_conn, nt_errstr(status));
1630 tevent_req_set_callback(subreq, dcesrv_read_fragment_done, dcesrv_conn);
1635 static void dcesrv_read_fragment_done(struct tevent_req *subreq)
1637 struct dcesrv_connection *dce_conn = tevent_req_callback_data(subreq,
1638 struct dcesrv_connection);
1639 struct dcesrv_context *dce_ctx = dce_conn->dce_ctx;
1640 struct ncacn_packet *pkt;
1644 if (dce_conn->terminate) {
1646 * if the current connection is broken
1647 * we need to clean it up before any other connection
1649 dcesrv_terminate_connection(dce_conn, dce_conn->terminate);
1650 dcesrv_cleanup_broken_connections(dce_ctx);
1654 dcesrv_cleanup_broken_connections(dce_ctx);
1656 status = dcerpc_read_ncacn_packet_recv(subreq, dce_conn,
1658 TALLOC_FREE(subreq);
1659 if (!NT_STATUS_IS_OK(status)) {
1660 dcesrv_terminate_connection(dce_conn, nt_errstr(status));
1664 status = dcesrv_process_ncacn_packet(dce_conn, pkt, buffer);
1665 if (!NT_STATUS_IS_OK(status)) {
1666 dcesrv_terminate_connection(dce_conn, nt_errstr(status));
1670 subreq = dcerpc_read_ncacn_packet_send(dce_conn,
1671 dce_conn->event_ctx,
1674 status = NT_STATUS_NO_MEMORY;
1675 dcesrv_terminate_connection(dce_conn, nt_errstr(status));
1678 tevent_req_set_callback(subreq, dcesrv_read_fragment_done, dce_conn);
1681 static void dcesrv_sock_recv(struct stream_connection *conn, uint16_t flags)
1683 struct dcesrv_connection *dce_conn = talloc_get_type(conn->private_data,
1684 struct dcesrv_connection);
1685 dcesrv_terminate_connection(dce_conn, "dcesrv_sock_recv triggered");
1688 static void dcesrv_sock_send(struct stream_connection *conn, uint16_t flags)
1690 struct dcesrv_connection *dce_conn = talloc_get_type(conn->private_data,
1691 struct dcesrv_connection);
1692 dcesrv_terminate_connection(dce_conn, "dcesrv_sock_send triggered");
1696 static const struct stream_server_ops dcesrv_stream_ops = {
1698 .accept_connection = dcesrv_sock_accept,
1699 .recv_handler = dcesrv_sock_recv,
1700 .send_handler = dcesrv_sock_send,
1703 static NTSTATUS dcesrv_add_ep_unix(struct dcesrv_context *dce_ctx,
1704 struct loadparm_context *lp_ctx,
1705 struct dcesrv_endpoint *e,
1706 struct tevent_context *event_ctx, const struct model_ops *model_ops)
1708 struct dcesrv_socket_context *dcesrv_sock;
1711 const char *endpoint;
1713 dcesrv_sock = talloc(event_ctx, struct dcesrv_socket_context);
1714 NT_STATUS_HAVE_NO_MEMORY(dcesrv_sock);
1716 /* remember the endpoint of this socket */
1717 dcesrv_sock->endpoint = e;
1718 dcesrv_sock->dcesrv_ctx = talloc_reference(dcesrv_sock, dce_ctx);
1720 endpoint = dcerpc_binding_get_string_option(e->ep_description, "endpoint");
1722 status = stream_setup_socket(dcesrv_sock, event_ctx, lp_ctx,
1723 model_ops, &dcesrv_stream_ops,
1724 "unix", endpoint, &port,
1725 lpcfg_socket_options(lp_ctx),
1727 if (!NT_STATUS_IS_OK(status)) {
1728 DEBUG(0,("service_setup_stream_socket(path=%s) failed - %s\n",
1729 endpoint, nt_errstr(status)));
1735 static NTSTATUS dcesrv_add_ep_ncalrpc(struct dcesrv_context *dce_ctx,
1736 struct loadparm_context *lp_ctx,
1737 struct dcesrv_endpoint *e,
1738 struct tevent_context *event_ctx, const struct model_ops *model_ops)
1740 struct dcesrv_socket_context *dcesrv_sock;
1744 const char *endpoint;
1746 endpoint = dcerpc_binding_get_string_option(e->ep_description, "endpoint");
1748 if (endpoint == NULL) {
1750 * No identifier specified: use DEFAULT.
1752 * TODO: DO NOT hardcode this value anywhere else. Rather, specify
1753 * no endpoint and let the epmapper worry about it.
1755 endpoint = "DEFAULT";
1756 status = dcerpc_binding_set_string_option(e->ep_description,
1759 if (!NT_STATUS_IS_OK(status)) {
1760 DEBUG(0,("dcerpc_binding_set_string_option() failed - %s\n",
1761 nt_errstr(status)));
1766 full_path = talloc_asprintf(dce_ctx, "%s/%s", lpcfg_ncalrpc_dir(lp_ctx),
1769 dcesrv_sock = talloc(event_ctx, struct dcesrv_socket_context);
1770 NT_STATUS_HAVE_NO_MEMORY(dcesrv_sock);
1772 /* remember the endpoint of this socket */
1773 dcesrv_sock->endpoint = e;
1774 dcesrv_sock->dcesrv_ctx = talloc_reference(dcesrv_sock, dce_ctx);
1776 status = stream_setup_socket(dcesrv_sock, event_ctx, lp_ctx,
1777 model_ops, &dcesrv_stream_ops,
1778 "unix", full_path, &port,
1779 lpcfg_socket_options(lp_ctx),
1781 if (!NT_STATUS_IS_OK(status)) {
1782 DEBUG(0,("service_setup_stream_socket(identifier=%s,path=%s) failed - %s\n",
1783 endpoint, full_path, nt_errstr(status)));
1788 static NTSTATUS dcesrv_add_ep_np(struct dcesrv_context *dce_ctx,
1789 struct loadparm_context *lp_ctx,
1790 struct dcesrv_endpoint *e,
1791 struct tevent_context *event_ctx, const struct model_ops *model_ops)
1793 struct dcesrv_socket_context *dcesrv_sock;
1795 const char *endpoint;
1797 endpoint = dcerpc_binding_get_string_option(e->ep_description, "endpoint");
1798 if (endpoint == NULL) {
1799 DEBUG(0, ("Endpoint mandatory for named pipes\n"));
1800 return NT_STATUS_INVALID_PARAMETER;
1803 dcesrv_sock = talloc(event_ctx, struct dcesrv_socket_context);
1804 NT_STATUS_HAVE_NO_MEMORY(dcesrv_sock);
1806 /* remember the endpoint of this socket */
1807 dcesrv_sock->endpoint = e;
1808 dcesrv_sock->dcesrv_ctx = talloc_reference(dcesrv_sock, dce_ctx);
1810 status = tstream_setup_named_pipe(dce_ctx, event_ctx, lp_ctx,
1811 model_ops, &dcesrv_stream_ops,
1814 if (!NT_STATUS_IS_OK(status)) {
1815 DEBUG(0,("stream_setup_named_pipe(pipe=%s) failed - %s\n",
1816 endpoint, nt_errstr(status)));
1820 return NT_STATUS_OK;
1824 add a socket address to the list of events, one event per dcerpc endpoint
1826 static NTSTATUS add_socket_rpc_tcp_iface(struct dcesrv_context *dce_ctx, struct dcesrv_endpoint *e,
1827 struct tevent_context *event_ctx, const struct model_ops *model_ops,
1828 const char *address)
1830 struct dcesrv_socket_context *dcesrv_sock;
1833 const char *endpoint;
1836 endpoint = dcerpc_binding_get_string_option(e->ep_description, "endpoint");
1837 if (endpoint != NULL) {
1838 port = atoi(endpoint);
1841 dcesrv_sock = talloc(event_ctx, struct dcesrv_socket_context);
1842 NT_STATUS_HAVE_NO_MEMORY(dcesrv_sock);
1844 /* remember the endpoint of this socket */
1845 dcesrv_sock->endpoint = e;
1846 dcesrv_sock->dcesrv_ctx = talloc_reference(dcesrv_sock, dce_ctx);
1848 status = stream_setup_socket(dcesrv_sock, event_ctx, dce_ctx->lp_ctx,
1849 model_ops, &dcesrv_stream_ops,
1850 "ip", address, &port,
1851 lpcfg_socket_options(dce_ctx->lp_ctx),
1853 if (!NT_STATUS_IS_OK(status)) {
1854 DEBUG(0,("service_setup_stream_socket(address=%s,port=%u) failed - %s\n",
1855 address, port, nt_errstr(status)));
1859 snprintf(port_str, sizeof(port_str), "%u", port);
1861 status = dcerpc_binding_set_string_option(e->ep_description,
1862 "endpoint", port_str);
1863 if (!NT_STATUS_IS_OK(status)) {
1864 DEBUG(0,("dcerpc_binding_set_string_option(endpoint, %s) failed - %s\n",
1865 port_str, nt_errstr(status)));
1869 return NT_STATUS_OK;
1872 #include "lib/socket/netif.h" /* Included here to work around the fact that socket_wrapper redefines bind() */
1874 static NTSTATUS dcesrv_add_ep_tcp(struct dcesrv_context *dce_ctx,
1875 struct loadparm_context *lp_ctx,
1876 struct dcesrv_endpoint *e,
1877 struct tevent_context *event_ctx, const struct model_ops *model_ops)
1881 /* Add TCP/IP sockets */
1882 if (lpcfg_interfaces(lp_ctx) && lpcfg_bind_interfaces_only(lp_ctx)) {
1885 struct interface *ifaces;
1887 load_interface_list(dce_ctx, lp_ctx, &ifaces);
1889 num_interfaces = iface_list_count(ifaces);
1890 for(i = 0; i < num_interfaces; i++) {
1891 const char *address = iface_list_n_ip(ifaces, i);
1892 status = add_socket_rpc_tcp_iface(dce_ctx, e, event_ctx, model_ops, address);
1893 NT_STATUS_NOT_OK_RETURN(status);
1899 wcard = iface_list_wildcard(dce_ctx);
1900 NT_STATUS_HAVE_NO_MEMORY(wcard);
1901 for (i=0; wcard[i]; i++) {
1902 status = add_socket_rpc_tcp_iface(dce_ctx, e, event_ctx, model_ops, wcard[i]);
1903 if (NT_STATUS_IS_OK(status)) {
1908 if (num_binds == 0) {
1909 return NT_STATUS_INVALID_PARAMETER_MIX;
1913 return NT_STATUS_OK;
1916 NTSTATUS dcesrv_add_ep(struct dcesrv_context *dce_ctx,
1917 struct loadparm_context *lp_ctx,
1918 struct dcesrv_endpoint *e,
1919 struct tevent_context *event_ctx,
1920 const struct model_ops *model_ops)
1922 enum dcerpc_transport_t transport =
1923 dcerpc_binding_get_transport(e->ep_description);
1925 switch (transport) {
1926 case NCACN_UNIX_STREAM:
1927 return dcesrv_add_ep_unix(dce_ctx, lp_ctx, e, event_ctx, model_ops);
1930 return dcesrv_add_ep_ncalrpc(dce_ctx, lp_ctx, e, event_ctx, model_ops);
1933 return dcesrv_add_ep_tcp(dce_ctx, lp_ctx, e, event_ctx, model_ops);
1936 return dcesrv_add_ep_np(dce_ctx, lp_ctx, e, event_ctx, model_ops);
1939 return NT_STATUS_NOT_SUPPORTED;
1945 * retrieve credentials from a dce_call
1947 _PUBLIC_ struct cli_credentials *dcesrv_call_credentials(struct dcesrv_call_state *dce_call)
1949 return dce_call->conn->auth_state.session_info->credentials;
1953 * returns true if this is an authenticated call
1955 _PUBLIC_ bool dcesrv_call_authenticated(struct dcesrv_call_state *dce_call)
1957 enum security_user_level level;
1958 level = security_session_user_level(dce_call->conn->auth_state.session_info, NULL);
1959 return level >= SECURITY_USER;
1963 * retrieve account_name for a dce_call
1965 _PUBLIC_ const char *dcesrv_call_account_name(struct dcesrv_call_state *dce_call)
1967 return dce_call->context->conn->auth_state.session_info->info->account_name;