2 Unix SMB/CIFS implementation.
4 server side dcerpc core code
6 Copyright (C) Andrew Tridgell 2003-2005
7 Copyright (C) Stefan (metze) Metzmacher 2004-2005
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 3 of the License, or
12 (at your option) any later version.
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
19 You should have received a copy of the GNU General Public License
20 along with this program. If not, see <http://www.gnu.org/licenses/>.
24 #include "auth/auth.h"
25 #include "auth/gensec/gensec.h"
26 #include "../lib/util/dlinklist.h"
27 #include "rpc_server/dcerpc_server.h"
28 #include "rpc_server/dcerpc_server_proto.h"
29 #include "rpc_server/common/proto.h"
30 #include "librpc/rpc/dcerpc_proto.h"
31 #include "system/filesys.h"
32 #include "libcli/security/security.h"
33 #include "param/param.h"
34 #include "../lib/tsocket/tsocket.h"
35 #include "../libcli/named_pipe_auth/npa_tstream.h"
36 #include "smbd/service_stream.h"
37 #include "../lib/tsocket/tsocket.h"
38 #include "lib/socket/socket.h"
39 #include "smbd/process_model.h"
40 #include "lib/messaging/irpc.h"
41 #include "librpc/rpc/rpc_common.h"
42 #include "lib/util/samba_modules.h"
43 #include "librpc/gen_ndr/ndr_dcerpc.h"
45 /* this is only used when the client asks for an unknown interface */
46 #define DUMMY_ASSOC_GROUP 0x0FFFFFFF
48 extern const struct dcesrv_interface dcesrv_mgmt_interface;
52 find an association group given a assoc_group_id
54 static struct dcesrv_assoc_group *dcesrv_assoc_group_find(struct dcesrv_context *dce_ctx,
59 id_ptr = idr_find(dce_ctx->assoc_groups_idr, id);
63 return talloc_get_type_abort(id_ptr, struct dcesrv_assoc_group);
67 take a reference to an existing association group
69 static struct dcesrv_assoc_group *dcesrv_assoc_group_reference(TALLOC_CTX *mem_ctx,
70 struct dcesrv_context *dce_ctx,
73 struct dcesrv_assoc_group *assoc_group;
75 assoc_group = dcesrv_assoc_group_find(dce_ctx, id);
76 if (assoc_group == NULL) {
77 DEBUG(0,(__location__ ": Failed to find assoc_group 0x%08x\n", id));
80 return talloc_reference(mem_ctx, assoc_group);
83 static int dcesrv_assoc_group_destructor(struct dcesrv_assoc_group *assoc_group)
86 ret = idr_remove(assoc_group->dce_ctx->assoc_groups_idr, assoc_group->id);
88 DEBUG(0,(__location__ ": Failed to remove assoc_group 0x%08x\n",
95 allocate a new association group
97 static struct dcesrv_assoc_group *dcesrv_assoc_group_new(TALLOC_CTX *mem_ctx,
98 struct dcesrv_context *dce_ctx)
100 struct dcesrv_assoc_group *assoc_group;
103 assoc_group = talloc_zero(mem_ctx, struct dcesrv_assoc_group);
104 if (assoc_group == NULL) {
108 id = idr_get_new_random(dce_ctx->assoc_groups_idr, assoc_group, UINT16_MAX);
110 talloc_free(assoc_group);
111 DEBUG(0,(__location__ ": Out of association groups!\n"));
115 assoc_group->id = id;
116 assoc_group->dce_ctx = dce_ctx;
118 talloc_set_destructor(assoc_group, dcesrv_assoc_group_destructor);
125 see if two endpoints match
127 static bool endpoints_match(const struct dcerpc_binding *ep1,
128 const struct dcerpc_binding *ep2)
130 enum dcerpc_transport_t t1;
131 enum dcerpc_transport_t t2;
135 t1 = dcerpc_binding_get_transport(ep1);
136 t2 = dcerpc_binding_get_transport(ep2);
138 e1 = dcerpc_binding_get_string_option(ep1, "endpoint");
139 e2 = dcerpc_binding_get_string_option(ep2, "endpoint");
149 if (strcasecmp(e1, e2) != 0) {
157 find an endpoint in the dcesrv_context
159 static struct dcesrv_endpoint *find_endpoint(struct dcesrv_context *dce_ctx,
160 const struct dcerpc_binding *ep_description)
162 struct dcesrv_endpoint *ep;
163 for (ep=dce_ctx->endpoint_list; ep; ep=ep->next) {
164 if (endpoints_match(ep->ep_description, ep_description)) {
172 find a registered context_id from a bind or alter_context
174 static struct dcesrv_connection_context *dcesrv_find_context(struct dcesrv_connection *conn,
177 struct dcesrv_connection_context *c;
178 for (c=conn->contexts;c;c=c->next) {
179 if (c->context_id == context_id) return c;
185 see if a uuid and if_version match to an interface
187 static bool interface_match(const struct dcesrv_interface *if1,
188 const struct dcesrv_interface *if2)
190 return (if1->syntax_id.if_version == if2->syntax_id.if_version &&
191 GUID_equal(&if1->syntax_id.uuid, &if2->syntax_id.uuid));
195 find the interface operations on an endpoint
197 static const struct dcesrv_interface *find_interface(const struct dcesrv_endpoint *endpoint,
198 const struct dcesrv_interface *iface)
200 struct dcesrv_if_list *ifl;
201 for (ifl=endpoint->interface_list; ifl; ifl=ifl->next) {
202 if (interface_match(&(ifl->iface), iface)) {
203 return &(ifl->iface);
210 see if a uuid and if_version match to an interface
212 static bool interface_match_by_uuid(const struct dcesrv_interface *iface,
213 const struct GUID *uuid, uint32_t if_version)
215 return (iface->syntax_id.if_version == if_version &&
216 GUID_equal(&iface->syntax_id.uuid, uuid));
220 find the interface operations on an endpoint by uuid
222 static const struct dcesrv_interface *find_interface_by_uuid(const struct dcesrv_endpoint *endpoint,
223 const struct GUID *uuid, uint32_t if_version)
225 struct dcesrv_if_list *ifl;
226 for (ifl=endpoint->interface_list; ifl; ifl=ifl->next) {
227 if (interface_match_by_uuid(&(ifl->iface), uuid, if_version)) {
228 return &(ifl->iface);
235 find the earlier parts of a fragmented call awaiting reassembily
237 static struct dcesrv_call_state *dcesrv_find_fragmented_call(struct dcesrv_connection *dce_conn, uint16_t call_id)
239 struct dcesrv_call_state *c;
240 for (c=dce_conn->incoming_fragmented_call_list;c;c=c->next) {
241 if (c->pkt.call_id == call_id) {
249 register an interface on an endpoint
251 _PUBLIC_ NTSTATUS dcesrv_interface_register(struct dcesrv_context *dce_ctx,
253 const struct dcesrv_interface *iface,
254 const struct security_descriptor *sd)
256 struct dcesrv_endpoint *ep;
257 struct dcesrv_if_list *ifl;
258 struct dcerpc_binding *binding;
262 status = dcerpc_parse_binding(dce_ctx, ep_name, &binding);
264 if (NT_STATUS_IS_ERR(status)) {
265 DEBUG(0, ("Trouble parsing binding string '%s'\n", ep_name));
269 /* check if this endpoint exists
271 if ((ep=find_endpoint(dce_ctx, binding))==NULL) {
272 ep = talloc_zero(dce_ctx, struct dcesrv_endpoint);
274 return NT_STATUS_NO_MEMORY;
277 ep->ep_description = talloc_move(ep, &binding);
280 /* add mgmt interface */
281 ifl = talloc_zero(ep, struct dcesrv_if_list);
283 return NT_STATUS_NO_MEMORY;
286 memcpy(&(ifl->iface), &dcesrv_mgmt_interface,
287 sizeof(struct dcesrv_interface));
289 DLIST_ADD(ep->interface_list, ifl);
292 /* see if the interface is already registered on te endpoint */
293 if (find_interface(ep, iface)!=NULL) {
294 DEBUG(0,("dcesrv_interface_register: interface '%s' already registered on endpoint '%s'\n",
295 iface->name, ep_name));
296 return NT_STATUS_OBJECT_NAME_COLLISION;
299 /* talloc a new interface list element */
300 ifl = talloc_zero(ep, struct dcesrv_if_list);
302 return NT_STATUS_NO_MEMORY;
305 /* copy the given interface struct to the one on the endpoints interface list */
306 memcpy(&(ifl->iface),iface, sizeof(struct dcesrv_interface));
308 /* if we have a security descriptor given,
309 * we should see if we can set it up on the endpoint
312 /* if there's currently no security descriptor given on the endpoint
315 if (ep->sd == NULL) {
316 ep->sd = security_descriptor_copy(ep, sd);
319 /* if now there's no security descriptor given on the endpoint
320 * something goes wrong, either we failed to copy the security descriptor
321 * or there was already one on the endpoint
323 if (ep->sd != NULL) {
324 DEBUG(0,("dcesrv_interface_register: interface '%s' failed to setup a security descriptor\n"
325 " on endpoint '%s'\n",
326 iface->name, ep_name));
327 if (add_ep) free(ep);
329 return NT_STATUS_OBJECT_NAME_COLLISION;
333 /* finally add the interface on the endpoint */
334 DLIST_ADD(ep->interface_list, ifl);
336 /* if it's a new endpoint add it to the dcesrv_context */
338 DLIST_ADD(dce_ctx->endpoint_list, ep);
341 DEBUG(4,("dcesrv_interface_register: interface '%s' registered on endpoint '%s'\n",
342 iface->name, ep_name));
347 NTSTATUS dcesrv_inherited_session_key(struct dcesrv_connection *p,
348 DATA_BLOB *session_key)
350 if (p->auth_state.session_info->session_key.length) {
351 *session_key = p->auth_state.session_info->session_key;
354 return NT_STATUS_NO_USER_SESSION_KEY;
358 fetch the user session key - may be default (above) or the SMB session key
360 The key is always truncated to 16 bytes
362 _PUBLIC_ NTSTATUS dcesrv_fetch_session_key(struct dcesrv_connection *p,
363 DATA_BLOB *session_key)
365 NTSTATUS status = p->auth_state.session_key(p, session_key);
366 if (!NT_STATUS_IS_OK(status)) {
370 session_key->length = MIN(session_key->length, 16);
376 connect to a dcerpc endpoint
378 _PUBLIC_ NTSTATUS dcesrv_endpoint_connect(struct dcesrv_context *dce_ctx,
380 const struct dcesrv_endpoint *ep,
381 struct auth_session_info *session_info,
382 struct tevent_context *event_ctx,
383 struct imessaging_context *msg_ctx,
384 struct server_id server_id,
385 uint32_t state_flags,
386 struct dcesrv_connection **_p)
388 struct dcesrv_connection *p;
391 return NT_STATUS_ACCESS_DENIED;
394 p = talloc_zero(mem_ctx, struct dcesrv_connection);
395 NT_STATUS_HAVE_NO_MEMORY(p);
397 if (!talloc_reference(p, session_info)) {
399 return NT_STATUS_NO_MEMORY;
402 p->dce_ctx = dce_ctx;
404 p->packet_log_dir = lpcfg_lock_directory(dce_ctx->lp_ctx);
405 p->auth_state.session_info = session_info;
406 p->auth_state.session_key = dcesrv_generic_session_key;
407 p->event_ctx = event_ctx;
408 p->msg_ctx = msg_ctx;
409 p->server_id = server_id;
410 p->state_flags = state_flags;
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_zero(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 loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
516 const struct dcesrv_endpoint *endpoint = dce_call->conn->endpoint;
517 enum dcerpc_transport_t transport =
518 dcerpc_binding_get_transport(endpoint->ep_description);
519 struct dcesrv_connection_context *context = dce_call->context;
520 const struct dcesrv_interface *iface = context->iface;
522 context->min_auth_level = DCERPC_AUTH_LEVEL_NONE;
524 if (transport == NCALRPC) {
525 context->allow_connect = true;
530 * allow overwrite per interface
531 * allow dcerpc auth level connect:<interface>
533 context->allow_connect = lpcfg_allow_dcerpc_auth_level_connect(lp_ctx);
534 context->allow_connect = lpcfg_parm_bool(lp_ctx, NULL,
535 "allow dcerpc auth level connect",
537 context->allow_connect);
540 NTSTATUS dcesrv_interface_bind_require_integrity(struct dcesrv_call_state *dce_call,
541 const struct dcesrv_interface *iface)
543 if (dce_call->context == NULL) {
544 return NT_STATUS_INTERNAL_ERROR;
547 dce_call->context->min_auth_level = DCERPC_AUTH_LEVEL_INTEGRITY;
551 NTSTATUS dcesrv_interface_bind_require_privacy(struct dcesrv_call_state *dce_call,
552 const struct dcesrv_interface *iface)
554 if (dce_call->context == NULL) {
555 return NT_STATUS_INTERNAL_ERROR;
558 dce_call->context->min_auth_level = DCERPC_AUTH_LEVEL_PRIVACY;
562 _PUBLIC_ NTSTATUS dcesrv_interface_bind_reject_connect(struct dcesrv_call_state *dce_call,
563 const struct dcesrv_interface *iface)
565 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
566 const struct dcesrv_endpoint *endpoint = dce_call->conn->endpoint;
567 enum dcerpc_transport_t transport =
568 dcerpc_binding_get_transport(endpoint->ep_description);
569 struct dcesrv_connection_context *context = dce_call->context;
571 if (context == NULL) {
572 return NT_STATUS_INTERNAL_ERROR;
575 if (transport == NCALRPC) {
576 context->allow_connect = true;
581 * allow overwrite per interface
582 * allow dcerpc auth level connect:<interface>
584 context->allow_connect = false;
585 context->allow_connect = lpcfg_parm_bool(lp_ctx, NULL,
586 "allow dcerpc auth level connect",
588 context->allow_connect);
592 _PUBLIC_ NTSTATUS dcesrv_interface_bind_allow_connect(struct dcesrv_call_state *dce_call,
593 const struct dcesrv_interface *iface)
595 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
596 const struct dcesrv_endpoint *endpoint = dce_call->conn->endpoint;
597 enum dcerpc_transport_t transport =
598 dcerpc_binding_get_transport(endpoint->ep_description);
599 struct dcesrv_connection_context *context = dce_call->context;
601 if (context == NULL) {
602 return NT_STATUS_INTERNAL_ERROR;
605 if (transport == NCALRPC) {
606 context->allow_connect = true;
611 * allow overwrite per interface
612 * allow dcerpc auth level connect:<interface>
614 context->allow_connect = true;
615 context->allow_connect = lpcfg_parm_bool(lp_ctx, NULL,
616 "allow dcerpc auth level connect",
618 context->allow_connect);
623 handle a bind request
625 static NTSTATUS dcesrv_bind(struct dcesrv_call_state *call)
627 uint32_t if_version, transfer_syntax_version;
628 struct GUID uuid, *transfer_syntax_uuid;
629 struct ncacn_packet pkt;
630 struct data_blob_list_item *rep;
632 uint32_t result=0, reason=0;
634 const struct dcesrv_interface *iface;
635 uint32_t extra_flags = 0;
638 if provided, check the assoc_group is valid
640 if (call->pkt.u.bind.assoc_group_id != 0 &&
641 lpcfg_parm_bool(call->conn->dce_ctx->lp_ctx, NULL, "dcesrv","assoc group checking", true) &&
642 dcesrv_assoc_group_find(call->conn->dce_ctx, call->pkt.u.bind.assoc_group_id) == NULL) {
643 return dcesrv_bind_nak(call, 0);
646 if (call->pkt.u.bind.num_contexts < 1 ||
647 call->pkt.u.bind.ctx_list[0].num_transfer_syntaxes < 1) {
648 return dcesrv_bind_nak(call, 0);
651 context_id = call->pkt.u.bind.ctx_list[0].context_id;
653 /* you can't bind twice on one context */
654 if (dcesrv_find_context(call->conn, context_id) != NULL) {
655 return dcesrv_bind_nak(call, 0);
658 if_version = call->pkt.u.bind.ctx_list[0].abstract_syntax.if_version;
659 uuid = call->pkt.u.bind.ctx_list[0].abstract_syntax.uuid;
661 transfer_syntax_version = call->pkt.u.bind.ctx_list[0].transfer_syntaxes[0].if_version;
662 transfer_syntax_uuid = &call->pkt.u.bind.ctx_list[0].transfer_syntaxes[0].uuid;
663 if (!GUID_equal(&ndr_transfer_syntax_ndr.uuid, transfer_syntax_uuid) != 0 ||
664 ndr_transfer_syntax_ndr.if_version != transfer_syntax_version) {
665 char *uuid_str = GUID_string(call, transfer_syntax_uuid);
666 /* we only do NDR encoded dcerpc */
667 DEBUG(0,("Non NDR transfer syntax requested - %s\n", uuid_str));
668 talloc_free(uuid_str);
669 return dcesrv_bind_nak(call, 0);
672 iface = find_interface_by_uuid(call->conn->endpoint, &uuid, if_version);
674 char *uuid_str = GUID_string(call, &uuid);
675 DEBUG(2,("Request for unknown dcerpc interface %s/%d\n", uuid_str, if_version));
676 talloc_free(uuid_str);
678 /* we don't know about that interface */
679 result = DCERPC_BIND_PROVIDER_REJECT;
680 reason = DCERPC_BIND_REASON_ASYNTAX;
684 /* add this context to the list of available context_ids */
685 struct dcesrv_connection_context *context = talloc_zero(call->conn,
686 struct dcesrv_connection_context);
687 if (context == NULL) {
688 return dcesrv_bind_nak(call, 0);
690 context->conn = call->conn;
691 context->iface = iface;
692 context->context_id = context_id;
693 if (call->pkt.u.bind.assoc_group_id != 0) {
694 context->assoc_group = dcesrv_assoc_group_reference(context,
696 call->pkt.u.bind.assoc_group_id);
698 context->assoc_group = dcesrv_assoc_group_new(context, call->conn->dce_ctx);
700 if (context->assoc_group == NULL) {
701 talloc_free(context);
702 return dcesrv_bind_nak(call, 0);
704 context->private_data = NULL;
705 DLIST_ADD(call->conn->contexts, context);
706 call->context = context;
707 talloc_set_destructor(context, dcesrv_connection_context_destructor);
709 dcesrv_prepare_context_auth(call);
711 status = iface->bind(call, iface, if_version);
712 if (!NT_STATUS_IS_OK(status)) {
713 char *uuid_str = GUID_string(call, &uuid);
714 DEBUG(2,("Request for dcerpc interface %s/%d rejected: %s\n",
715 uuid_str, if_version, nt_errstr(status)));
716 talloc_free(uuid_str);
717 /* we don't want to trigger the iface->unbind() hook */
718 context->iface = NULL;
719 talloc_free(call->context);
720 call->context = NULL;
721 return dcesrv_bind_nak(call, 0);
725 if (call->conn->cli_max_recv_frag == 0) {
726 call->conn->cli_max_recv_frag = MIN(0x2000, call->pkt.u.bind.max_recv_frag);
729 if ((call->pkt.pfc_flags & DCERPC_PFC_FLAG_CONC_MPX) &&
730 (call->state_flags & DCESRV_CALL_STATE_FLAG_MULTIPLEXED)) {
731 call->context->conn->state_flags |= DCESRV_CALL_STATE_FLAG_MULTIPLEXED;
732 extra_flags |= DCERPC_PFC_FLAG_CONC_MPX;
735 if (call->state_flags & DCESRV_CALL_STATE_FLAG_PROCESS_PENDING_CALL) {
736 call->context->conn->state_flags |= DCESRV_CALL_STATE_FLAG_PROCESS_PENDING_CALL;
739 /* handle any authentication that is being requested */
740 if (!dcesrv_auth_bind(call)) {
741 talloc_free(call->context);
742 call->context = NULL;
743 return dcesrv_bind_nak(call, DCERPC_BIND_REASON_INVALID_AUTH_TYPE);
746 /* setup a bind_ack */
747 dcesrv_init_hdr(&pkt, lpcfg_rpc_big_endian(call->conn->dce_ctx->lp_ctx));
749 pkt.call_id = call->pkt.call_id;
750 pkt.ptype = DCERPC_PKT_BIND_ACK;
751 pkt.pfc_flags = DCERPC_PFC_FLAG_FIRST | DCERPC_PFC_FLAG_LAST | extra_flags;
752 pkt.u.bind_ack.max_xmit_frag = call->conn->cli_max_recv_frag;
753 pkt.u.bind_ack.max_recv_frag = 0x2000;
756 make it possible for iface->bind() to specify the assoc_group_id
757 This helps the openchange mapiproxy plugin to work correctly.
762 pkt.u.bind_ack.assoc_group_id = call->context->assoc_group->id;
764 pkt.u.bind_ack.assoc_group_id = DUMMY_ASSOC_GROUP;
768 /* FIXME: Use pipe name as specified by endpoint instead of interface name */
769 pkt.u.bind_ack.secondary_address = talloc_asprintf(call, "\\PIPE\\%s", iface->name);
771 pkt.u.bind_ack.secondary_address = "";
773 pkt.u.bind_ack.num_results = 1;
774 pkt.u.bind_ack.ctx_list = talloc_zero(call, struct dcerpc_ack_ctx);
775 if (!pkt.u.bind_ack.ctx_list) {
776 talloc_free(call->context);
777 call->context = NULL;
778 return NT_STATUS_NO_MEMORY;
780 pkt.u.bind_ack.ctx_list[0].result = result;
781 pkt.u.bind_ack.ctx_list[0].reason.value = reason;
782 pkt.u.bind_ack.ctx_list[0].syntax = ndr_transfer_syntax_ndr;
783 pkt.u.bind_ack.auth_info = data_blob(NULL, 0);
785 status = dcesrv_auth_bind_ack(call, &pkt);
786 if (!NT_STATUS_IS_OK(status)) {
787 talloc_free(call->context);
788 call->context = NULL;
789 return dcesrv_bind_nak(call, 0);
792 rep = talloc_zero(call, struct data_blob_list_item);
794 talloc_free(call->context);
795 call->context = NULL;
796 return NT_STATUS_NO_MEMORY;
799 status = ncacn_push_auth(&rep->blob, call, &pkt,
800 call->conn->auth_state.auth_info);
801 if (!NT_STATUS_IS_OK(status)) {
802 talloc_free(call->context);
803 call->context = NULL;
807 dcerpc_set_frag_length(&rep->blob, rep->blob.length);
809 DLIST_ADD_END(call->replies, rep);
810 dcesrv_call_set_list(call, DCESRV_LIST_CALL_LIST);
812 if (call->conn->call_list && call->conn->call_list->replies) {
813 if (call->conn->transport.report_output_data) {
814 call->conn->transport.report_output_data(call->conn);
823 handle a auth3 request
825 static NTSTATUS dcesrv_auth3(struct dcesrv_call_state *call)
827 /* handle the auth3 in the auth code */
828 if (!dcesrv_auth_auth3(call)) {
829 return dcesrv_fault(call, DCERPC_FAULT_OTHER);
834 /* we don't send a reply to a auth3 request, except by a
841 handle a bind request
843 static NTSTATUS dcesrv_alter_new_context(struct dcesrv_call_state *call, uint32_t context_id)
845 uint32_t if_version, transfer_syntax_version;
846 struct dcesrv_connection_context *context;
847 const struct dcesrv_interface *iface;
848 struct GUID uuid, *transfer_syntax_uuid;
851 if_version = call->pkt.u.alter.ctx_list[0].abstract_syntax.if_version;
852 uuid = call->pkt.u.alter.ctx_list[0].abstract_syntax.uuid;
854 transfer_syntax_version = call->pkt.u.alter.ctx_list[0].transfer_syntaxes[0].if_version;
855 transfer_syntax_uuid = &call->pkt.u.alter.ctx_list[0].transfer_syntaxes[0].uuid;
856 if (!GUID_equal(transfer_syntax_uuid, &ndr_transfer_syntax_ndr.uuid) ||
857 ndr_transfer_syntax_ndr.if_version != transfer_syntax_version) {
858 /* we only do NDR encoded dcerpc */
859 return NT_STATUS_RPC_PROTSEQ_NOT_SUPPORTED;
862 iface = find_interface_by_uuid(call->conn->endpoint, &uuid, if_version);
864 char *uuid_str = GUID_string(call, &uuid);
865 DEBUG(2,("Request for unknown dcerpc interface %s/%d\n", uuid_str, if_version));
866 talloc_free(uuid_str);
867 return NT_STATUS_RPC_PROTSEQ_NOT_SUPPORTED;
870 /* add this context to the list of available context_ids */
871 context = talloc_zero(call->conn, struct dcesrv_connection_context);
872 if (context == NULL) {
873 return NT_STATUS_NO_MEMORY;
875 context->conn = call->conn;
876 context->iface = iface;
877 context->context_id = context_id;
878 if (call->pkt.u.alter.assoc_group_id != 0) {
879 context->assoc_group = dcesrv_assoc_group_reference(context,
881 call->pkt.u.alter.assoc_group_id);
883 context->assoc_group = dcesrv_assoc_group_new(context, call->conn->dce_ctx);
885 if (context->assoc_group == NULL) {
886 talloc_free(context);
887 call->context = NULL;
888 return NT_STATUS_NO_MEMORY;
890 context->private_data = NULL;
891 DLIST_ADD(call->conn->contexts, context);
892 call->context = context;
893 talloc_set_destructor(context, dcesrv_connection_context_destructor);
895 dcesrv_prepare_context_auth(call);
897 status = iface->bind(call, iface, if_version);
898 if (!NT_STATUS_IS_OK(status)) {
899 /* we don't want to trigger the iface->unbind() hook */
900 context->iface = NULL;
901 talloc_free(context);
902 call->context = NULL;
909 /* setup and send an alter_resp */
910 static NTSTATUS dcesrv_alter_resp(struct dcesrv_call_state *call,
914 struct ncacn_packet pkt;
915 uint32_t extra_flags = 0;
916 struct data_blob_list_item *rep = NULL;
919 dcesrv_init_hdr(&pkt, lpcfg_rpc_big_endian(call->conn->dce_ctx->lp_ctx));
921 pkt.call_id = call->pkt.call_id;
922 pkt.ptype = DCERPC_PKT_ALTER_RESP;
924 if ((call->pkt.pfc_flags & DCERPC_PFC_FLAG_CONC_MPX) &&
925 call->context->conn->state_flags &
926 DCESRV_CALL_STATE_FLAG_MULTIPLEXED) {
927 extra_flags |= DCERPC_PFC_FLAG_CONC_MPX;
929 if (call->state_flags & DCESRV_CALL_STATE_FLAG_PROCESS_PENDING_CALL) {
930 call->context->conn->state_flags |=
931 DCESRV_CALL_STATE_FLAG_PROCESS_PENDING_CALL;
934 pkt.pfc_flags = DCERPC_PFC_FLAG_FIRST | DCERPC_PFC_FLAG_LAST | extra_flags;
935 pkt.u.alter_resp.max_xmit_frag = 0x2000;
936 pkt.u.alter_resp.max_recv_frag = 0x2000;
938 pkt.u.alter_resp.assoc_group_id = call->context->assoc_group->id;
940 pkt.u.alter_resp.assoc_group_id = 0;
942 pkt.u.alter_resp.num_results = 1;
943 pkt.u.alter_resp.ctx_list = talloc_zero(call, struct dcerpc_ack_ctx);
944 if (!pkt.u.alter_resp.ctx_list) {
945 return NT_STATUS_NO_MEMORY;
947 pkt.u.alter_resp.ctx_list[0].result = result;
948 pkt.u.alter_resp.ctx_list[0].reason.value = reason;
949 pkt.u.alter_resp.ctx_list[0].syntax = ndr_transfer_syntax_ndr;
950 pkt.u.alter_resp.auth_info = data_blob(NULL, 0);
951 pkt.u.alter_resp.secondary_address = "";
953 status = dcesrv_auth_alter_ack(call, &pkt);
954 if (!NT_STATUS_IS_OK(status)) {
955 if (NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)
956 || NT_STATUS_EQUAL(status, NT_STATUS_LOGON_FAILURE)
957 || NT_STATUS_EQUAL(status, NT_STATUS_NO_SUCH_USER)
958 || NT_STATUS_EQUAL(status, NT_STATUS_WRONG_PASSWORD)) {
959 return dcesrv_fault(call, DCERPC_FAULT_ACCESS_DENIED);
961 return dcesrv_fault(call, 0);
964 rep = talloc_zero(call, struct data_blob_list_item);
966 return NT_STATUS_NO_MEMORY;
969 status = ncacn_push_auth(&rep->blob, call, &pkt, call->conn->auth_state.auth_info);
970 if (!NT_STATUS_IS_OK(status)) {
974 dcerpc_set_frag_length(&rep->blob, rep->blob.length);
976 DLIST_ADD_END(call->replies, rep);
977 dcesrv_call_set_list(call, DCESRV_LIST_CALL_LIST);
979 if (call->conn->call_list && call->conn->call_list->replies) {
980 if (call->conn->transport.report_output_data) {
981 call->conn->transport.report_output_data(call->conn);
989 handle a alter context request
991 static NTSTATUS dcesrv_alter(struct dcesrv_call_state *call)
996 /* handle any authentication that is being requested */
997 if (!dcesrv_auth_alter(call)) {
998 /* TODO: work out the right reject code */
999 return dcesrv_alter_resp(call,
1000 DCERPC_BIND_PROVIDER_REJECT,
1001 DCERPC_BIND_REASON_ASYNTAX);
1004 context_id = call->pkt.u.alter.ctx_list[0].context_id;
1006 /* see if they are asking for a new interface */
1007 call->context = dcesrv_find_context(call->conn, context_id);
1008 if (!call->context) {
1009 status = dcesrv_alter_new_context(call, context_id);
1010 if (!NT_STATUS_IS_OK(status)) {
1011 return dcesrv_alter_resp(call,
1012 DCERPC_BIND_PROVIDER_REJECT,
1013 DCERPC_BIND_REASON_ASYNTAX);
1017 if (call->pkt.u.alter.assoc_group_id != 0 &&
1018 lpcfg_parm_bool(call->conn->dce_ctx->lp_ctx, NULL, "dcesrv","assoc group checking", true) &&
1019 call->pkt.u.alter.assoc_group_id != call->context->assoc_group->id) {
1020 DEBUG(0,(__location__ ": Failed attempt to use new assoc_group in alter context (0x%08x 0x%08x)\n",
1021 call->context->assoc_group->id, call->pkt.u.alter.assoc_group_id));
1022 /* TODO: can they ask for a new association group? */
1023 return dcesrv_alter_resp(call,
1024 DCERPC_BIND_PROVIDER_REJECT,
1025 DCERPC_BIND_REASON_ASYNTAX);
1028 return dcesrv_alter_resp(call,
1029 DCERPC_BIND_ACK_RESULT_ACCEPTANCE,
1030 DCERPC_BIND_ACK_REASON_NOT_SPECIFIED);
1034 possibly save the call for inspection with ndrdump
1036 static void dcesrv_save_call(struct dcesrv_call_state *call, const char *why)
1040 const char *dump_dir;
1041 dump_dir = lpcfg_parm_string(call->conn->dce_ctx->lp_ctx, NULL, "dcesrv", "stubs directory");
1045 fname = talloc_asprintf(call, "%s/RPC-%s-%u-%s.dat",
1047 call->context->iface->name,
1048 call->pkt.u.request.opnum,
1050 if (file_save(fname, call->pkt.u.request.stub_and_verifier.data, call->pkt.u.request.stub_and_verifier.length)) {
1051 DEBUG(0,("RPC SAVED %s\n", fname));
1057 static NTSTATUS dcesrv_check_verification_trailer(struct dcesrv_call_state *call)
1059 TALLOC_CTX *frame = talloc_stackframe();
1060 const uint32_t bitmask1 = call->conn->auth_state.client_hdr_signing ?
1061 DCERPC_SEC_VT_CLIENT_SUPPORTS_HEADER_SIGNING : 0;
1062 const struct dcerpc_sec_vt_pcontext pcontext = {
1063 .abstract_syntax = call->context->iface->syntax_id,
1064 .transfer_syntax = ndr_transfer_syntax_ndr,
1066 const struct dcerpc_sec_vt_header2 header2 =
1067 dcerpc_sec_vt_header2_from_ncacn_packet(&call->pkt);
1068 enum ndr_err_code ndr_err;
1069 struct dcerpc_sec_verification_trailer *vt = NULL;
1070 NTSTATUS status = NT_STATUS_OK;
1073 SMB_ASSERT(call->pkt.ptype == DCERPC_PKT_REQUEST);
1075 ndr_err = ndr_pop_dcerpc_sec_verification_trailer(call->ndr_pull,
1077 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
1078 status = ndr_map_error2ntstatus(ndr_err);
1082 ok = dcerpc_sec_verification_trailer_check(vt, &bitmask1,
1083 &pcontext, &header2);
1085 status = NT_STATUS_ACCESS_DENIED;
1094 handle a dcerpc request packet
1096 static NTSTATUS dcesrv_request(struct dcesrv_call_state *call)
1098 const struct dcesrv_endpoint *endpoint = call->conn->endpoint;
1099 enum dcerpc_transport_t transport =
1100 dcerpc_binding_get_transport(endpoint->ep_description);
1101 struct ndr_pull *pull;
1103 struct dcesrv_connection_context *context;
1104 uint32_t auth_type = DCERPC_AUTH_TYPE_NONE;
1105 uint32_t auth_level = DCERPC_AUTH_LEVEL_NONE;
1107 /* if authenticated, and the mech we use can't do async replies, don't use them... */
1108 if (call->conn->auth_state.gensec_security &&
1109 !gensec_have_feature(call->conn->auth_state.gensec_security, GENSEC_FEATURE_ASYNC_REPLIES)) {
1110 call->state_flags &= ~DCESRV_CALL_STATE_FLAG_MAY_ASYNC;
1113 context = dcesrv_find_context(call->conn, call->pkt.u.request.context_id);
1114 if (context == NULL) {
1115 return dcesrv_fault(call, DCERPC_FAULT_UNK_IF);
1118 if (call->conn->auth_state.auth_info != NULL) {
1119 auth_type = call->conn->auth_state.auth_info->auth_type;
1120 auth_level = call->conn->auth_state.auth_info->auth_level;
1123 switch (auth_level) {
1124 case DCERPC_AUTH_LEVEL_NONE:
1125 case DCERPC_AUTH_LEVEL_INTEGRITY:
1126 case DCERPC_AUTH_LEVEL_PRIVACY:
1129 if (!context->allow_connect) {
1132 addr = tsocket_address_string(call->conn->remote_address,
1135 DEBUG(2, ("%s: restrict auth_level_connect access "
1136 "to [%s] with auth[type=0x%x,level=0x%x] "
1137 "on [%s] from [%s]\n",
1138 __func__, context->iface->name,
1139 auth_type, auth_level,
1140 derpc_transport_string_by_transport(transport),
1142 return dcesrv_fault(call, DCERPC_FAULT_ACCESS_DENIED);
1147 if (auth_level < context->min_auth_level) {
1150 addr = tsocket_address_string(call->conn->remote_address, call);
1152 DEBUG(2, ("%s: restrict access by min_auth_level[0x%x] "
1153 "to [%s] with auth[type=0x%x,level=0x%x] "
1154 "on [%s] from [%s]\n",
1156 context->min_auth_level,
1157 context->iface->name,
1158 auth_type, auth_level,
1159 derpc_transport_string_by_transport(transport),
1161 return dcesrv_fault(call, DCERPC_FAULT_ACCESS_DENIED);
1164 pull = ndr_pull_init_blob(&call->pkt.u.request.stub_and_verifier, call);
1165 NT_STATUS_HAVE_NO_MEMORY(pull);
1167 pull->flags |= LIBNDR_FLAG_REF_ALLOC;
1169 call->context = context;
1170 call->ndr_pull = pull;
1172 if (!(call->pkt.drep[0] & DCERPC_DREP_LE)) {
1173 pull->flags |= LIBNDR_FLAG_BIGENDIAN;
1176 status = dcesrv_check_verification_trailer(call);
1177 if (!NT_STATUS_IS_OK(status)) {
1178 uint32_t faultcode = DCERPC_FAULT_OTHER;
1179 if (NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
1180 faultcode = DCERPC_FAULT_ACCESS_DENIED;
1182 DEBUG(10, ("dcesrv_check_verification_trailer failed: %s\n",
1183 nt_errstr(status)));
1184 return dcesrv_fault(call, faultcode);
1187 /* unravel the NDR for the packet */
1188 status = context->iface->ndr_pull(call, call, pull, &call->r);
1189 if (!NT_STATUS_IS_OK(status)) {
1190 if (call->fault_code == DCERPC_FAULT_OP_RNG_ERROR) {
1191 /* we got an unknown call */
1192 DEBUG(3,(__location__ ": Unknown RPC call %u on %s\n",
1193 call->pkt.u.request.opnum, context->iface->name));
1194 dcesrv_save_call(call, "unknown");
1196 dcesrv_save_call(call, "pullfail");
1198 return dcesrv_fault(call, call->fault_code);
1201 if (pull->offset != pull->data_size) {
1202 dcesrv_save_call(call, "extrabytes");
1203 DEBUG(3,("Warning: %d extra bytes in incoming RPC request\n",
1204 pull->data_size - pull->offset));
1207 /* call the dispatch function */
1208 status = context->iface->dispatch(call, call, call->r);
1209 if (!NT_STATUS_IS_OK(status)) {
1210 DEBUG(5,("dcerpc fault in call %s:%02x - %s\n",
1211 context->iface->name,
1212 call->pkt.u.request.opnum,
1213 dcerpc_errstr(pull, call->fault_code)));
1214 return dcesrv_fault(call, call->fault_code);
1217 /* add the call to the pending list */
1218 dcesrv_call_set_list(call, DCESRV_LIST_PENDING_CALL_LIST);
1220 if (call->state_flags & DCESRV_CALL_STATE_FLAG_ASYNC) {
1221 return NT_STATUS_OK;
1224 return dcesrv_reply(call);
1229 remove the call from the right list when freed
1231 static int dcesrv_call_dequeue(struct dcesrv_call_state *call)
1233 dcesrv_call_set_list(call, DCESRV_LIST_NONE);
1237 _PUBLIC_ const struct tsocket_address *dcesrv_connection_get_local_address(struct dcesrv_connection *conn)
1239 return conn->local_address;
1242 _PUBLIC_ const struct tsocket_address *dcesrv_connection_get_remote_address(struct dcesrv_connection *conn)
1244 return conn->remote_address;
1248 process some input to a dcerpc endpoint server.
1250 NTSTATUS dcesrv_process_ncacn_packet(struct dcesrv_connection *dce_conn,
1251 struct ncacn_packet *pkt,
1255 struct dcesrv_call_state *call;
1257 call = talloc_zero(dce_conn, struct dcesrv_call_state);
1259 data_blob_free(&blob);
1261 return NT_STATUS_NO_MEMORY;
1263 call->conn = dce_conn;
1264 call->event_ctx = dce_conn->event_ctx;
1265 call->msg_ctx = dce_conn->msg_ctx;
1266 call->state_flags = call->conn->state_flags;
1267 call->time = timeval_current();
1268 call->list = DCESRV_LIST_NONE;
1270 talloc_steal(call, pkt);
1271 talloc_steal(call, blob.data);
1274 talloc_set_destructor(call, dcesrv_call_dequeue);
1276 /* we have to check the signing here, before combining the
1278 if (call->pkt.ptype == DCERPC_PKT_REQUEST &&
1279 !dcesrv_auth_request(call, &blob)) {
1280 return dcesrv_fault(call, DCERPC_FAULT_ACCESS_DENIED);
1283 /* see if this is a continued packet */
1284 if (call->pkt.ptype == DCERPC_PKT_REQUEST &&
1285 !(call->pkt.pfc_flags & DCERPC_PFC_FLAG_FIRST)) {
1286 struct dcesrv_call_state *call2 = call;
1287 uint32_t alloc_size;
1289 /* we only allow fragmented requests, no other packet types */
1290 if (call->pkt.ptype != DCERPC_PKT_REQUEST) {
1291 return dcesrv_fault(call2, DCERPC_FAULT_OTHER);
1294 /* this is a continuation of an existing call - find the call
1295 then tack it on the end */
1296 call = dcesrv_find_fragmented_call(dce_conn, call2->pkt.call_id);
1298 return dcesrv_fault(call2, DCERPC_FAULT_OTHER);
1301 if (call->pkt.ptype != call2->pkt.ptype) {
1302 /* trying to play silly buggers are we? */
1303 return dcesrv_fault(call2, DCERPC_NCA_S_PROTO_ERROR);
1305 if (memcmp(call->pkt.drep, call2->pkt.drep, sizeof(pkt->drep)) != 0) {
1306 return dcesrv_fault(call2, DCERPC_NCA_S_PROTO_ERROR);
1308 if (call->pkt.call_id != call2->pkt.call_id) {
1309 return dcesrv_fault(call2, DCERPC_NCA_S_PROTO_ERROR);
1311 if (call->pkt.u.request.context_id != call2->pkt.u.request.context_id) {
1312 return dcesrv_fault(call2, DCERPC_NCA_S_PROTO_ERROR);
1314 if (call->pkt.u.request.opnum != call2->pkt.u.request.opnum) {
1315 return dcesrv_fault(call2, DCERPC_NCA_S_PROTO_ERROR);
1318 alloc_size = call->pkt.u.request.stub_and_verifier.length +
1319 call2->pkt.u.request.stub_and_verifier.length;
1320 if (call->pkt.u.request.alloc_hint > alloc_size) {
1321 alloc_size = call->pkt.u.request.alloc_hint;
1324 call->pkt.u.request.stub_and_verifier.data =
1325 talloc_realloc(call,
1326 call->pkt.u.request.stub_and_verifier.data,
1327 uint8_t, alloc_size);
1328 if (!call->pkt.u.request.stub_and_verifier.data) {
1329 return dcesrv_fault(call2, DCERPC_FAULT_OTHER);
1331 memcpy(call->pkt.u.request.stub_and_verifier.data +
1332 call->pkt.u.request.stub_and_verifier.length,
1333 call2->pkt.u.request.stub_and_verifier.data,
1334 call2->pkt.u.request.stub_and_verifier.length);
1335 call->pkt.u.request.stub_and_verifier.length +=
1336 call2->pkt.u.request.stub_and_verifier.length;
1338 call->pkt.pfc_flags |= (call2->pkt.pfc_flags & DCERPC_PFC_FLAG_LAST);
1343 /* this may not be the last pdu in the chain - if its isn't then
1344 just put it on the incoming_fragmented_call_list and wait for the rest */
1345 if (call->pkt.ptype == DCERPC_PKT_REQUEST &&
1346 !(call->pkt.pfc_flags & DCERPC_PFC_FLAG_LAST)) {
1347 dcesrv_call_set_list(call, DCESRV_LIST_FRAGMENTED_CALL_LIST);
1348 return NT_STATUS_OK;
1351 /* This removes any fragments we may have had stashed away */
1352 dcesrv_call_set_list(call, DCESRV_LIST_NONE);
1354 switch (call->pkt.ptype) {
1355 case DCERPC_PKT_BIND:
1356 status = dcesrv_bind(call);
1358 case DCERPC_PKT_AUTH3:
1359 status = dcesrv_auth3(call);
1361 case DCERPC_PKT_ALTER:
1362 status = dcesrv_alter(call);
1364 case DCERPC_PKT_REQUEST:
1365 status = dcesrv_request(call);
1368 status = NT_STATUS_INVALID_PARAMETER;
1372 /* if we are going to be sending a reply then add
1373 it to the list of pending calls. We add it to the end to keep the call
1374 list in the order we will answer */
1375 if (!NT_STATUS_IS_OK(status)) {
1382 _PUBLIC_ NTSTATUS dcesrv_init_context(TALLOC_CTX *mem_ctx,
1383 struct loadparm_context *lp_ctx,
1384 const char **endpoint_servers, struct dcesrv_context **_dce_ctx)
1387 struct dcesrv_context *dce_ctx;
1390 if (!endpoint_servers) {
1391 DEBUG(0,("dcesrv_init_context: no endpoint servers configured\n"));
1392 return NT_STATUS_INTERNAL_ERROR;
1395 dce_ctx = talloc_zero(mem_ctx, struct dcesrv_context);
1396 NT_STATUS_HAVE_NO_MEMORY(dce_ctx);
1398 if (uid_wrapper_enabled()) {
1399 setenv("UID_WRAPPER_MYUID", "1", 1);
1401 dce_ctx->initial_euid = geteuid();
1402 if (uid_wrapper_enabled()) {
1403 unsetenv("UID_WRAPPER_MYUID");
1406 dce_ctx->endpoint_list = NULL;
1407 dce_ctx->lp_ctx = lp_ctx;
1408 dce_ctx->assoc_groups_idr = idr_init(dce_ctx);
1409 NT_STATUS_HAVE_NO_MEMORY(dce_ctx->assoc_groups_idr);
1410 dce_ctx->broken_connections = NULL;
1412 for (i=0;endpoint_servers[i];i++) {
1413 const struct dcesrv_endpoint_server *ep_server;
1415 ep_server = dcesrv_ep_server_byname(endpoint_servers[i]);
1417 DEBUG(0,("dcesrv_init_context: failed to find endpoint server = '%s'\n", endpoint_servers[i]));
1418 return NT_STATUS_INTERNAL_ERROR;
1421 status = ep_server->init_server(dce_ctx, ep_server);
1422 if (!NT_STATUS_IS_OK(status)) {
1423 DEBUG(0,("dcesrv_init_context: failed to init endpoint server = '%s': %s\n", endpoint_servers[i],
1424 nt_errstr(status)));
1429 *_dce_ctx = dce_ctx;
1430 return NT_STATUS_OK;
1433 /* the list of currently registered DCERPC endpoint servers.
1435 static struct ep_server {
1436 struct dcesrv_endpoint_server *ep_server;
1437 } *ep_servers = NULL;
1438 static int num_ep_servers;
1441 register a DCERPC endpoint server.
1443 The 'name' can be later used by other backends to find the operations
1444 structure for this backend.
1446 The 'type' is used to specify whether this is for a disk, printer or IPC$ share
1448 _PUBLIC_ NTSTATUS dcerpc_register_ep_server(const void *_ep_server)
1450 const struct dcesrv_endpoint_server *ep_server = _ep_server;
1452 if (dcesrv_ep_server_byname(ep_server->name) != NULL) {
1453 /* its already registered! */
1454 DEBUG(0,("DCERPC endpoint server '%s' already registered\n",
1456 return NT_STATUS_OBJECT_NAME_COLLISION;
1459 ep_servers = realloc_p(ep_servers, struct ep_server, num_ep_servers+1);
1461 smb_panic("out of memory in dcerpc_register");
1464 ep_servers[num_ep_servers].ep_server = smb_xmemdup(ep_server, sizeof(*ep_server));
1465 ep_servers[num_ep_servers].ep_server->name = smb_xstrdup(ep_server->name);
1469 DEBUG(3,("DCERPC endpoint server '%s' registered\n",
1472 return NT_STATUS_OK;
1476 return the operations structure for a named backend of the specified type
1478 const struct dcesrv_endpoint_server *dcesrv_ep_server_byname(const char *name)
1482 for (i=0;i<num_ep_servers;i++) {
1483 if (strcmp(ep_servers[i].ep_server->name, name) == 0) {
1484 return ep_servers[i].ep_server;
1491 void dcerpc_server_init(struct loadparm_context *lp_ctx)
1493 static bool initialized;
1494 #define _MODULE_PROTO(init) extern NTSTATUS init(void);
1495 STATIC_dcerpc_server_MODULES_PROTO;
1496 init_module_fn static_init[] = { STATIC_dcerpc_server_MODULES };
1497 init_module_fn *shared_init;
1504 shared_init = load_samba_modules(NULL, "dcerpc_server");
1506 run_init_functions(static_init);
1507 run_init_functions(shared_init);
1509 talloc_free(shared_init);
1513 return the DCERPC module version, and the size of some critical types
1514 This can be used by endpoint server modules to either detect compilation errors, or provide
1515 multiple implementations for different smbd compilation options in one module
1517 const struct dcesrv_critical_sizes *dcerpc_module_version(void)
1519 static const struct dcesrv_critical_sizes critical_sizes = {
1520 DCERPC_MODULE_VERSION,
1521 sizeof(struct dcesrv_context),
1522 sizeof(struct dcesrv_endpoint),
1523 sizeof(struct dcesrv_endpoint_server),
1524 sizeof(struct dcesrv_interface),
1525 sizeof(struct dcesrv_if_list),
1526 sizeof(struct dcesrv_connection),
1527 sizeof(struct dcesrv_call_state),
1528 sizeof(struct dcesrv_auth),
1529 sizeof(struct dcesrv_handle)
1532 return &critical_sizes;
1535 static void dcesrv_terminate_connection(struct dcesrv_connection *dce_conn, const char *reason)
1537 struct dcesrv_context *dce_ctx = dce_conn->dce_ctx;
1538 struct stream_connection *srv_conn;
1539 srv_conn = talloc_get_type(dce_conn->transport.private_data,
1540 struct stream_connection);
1542 if (dce_conn->pending_call_list == NULL) {
1543 char *full_reason = talloc_asprintf(dce_conn, "dcesrv: %s", reason);
1545 DLIST_REMOVE(dce_ctx->broken_connections, dce_conn);
1546 stream_terminate_connection(srv_conn, full_reason ? full_reason : reason);
1550 if (dce_conn->terminate != NULL) {
1554 DEBUG(3,("dcesrv: terminating connection due to '%s' defered due to pending calls\n",
1556 dce_conn->terminate = talloc_strdup(dce_conn, reason);
1557 if (dce_conn->terminate == NULL) {
1558 dce_conn->terminate = "dcesrv: defered terminating connection - no memory";
1560 DLIST_ADD_END(dce_ctx->broken_connections, dce_conn);
1563 static void dcesrv_cleanup_broken_connections(struct dcesrv_context *dce_ctx)
1565 struct dcesrv_connection *cur, *next;
1567 next = dce_ctx->broken_connections;
1568 while (next != NULL) {
1572 if (cur->state_flags & DCESRV_CALL_STATE_FLAG_PROCESS_PENDING_CALL) {
1573 struct dcesrv_connection_context *context_cur, *context_next;
1575 context_next = cur->contexts;
1576 while (context_next != NULL) {
1577 context_cur = context_next;
1578 context_next = context_cur->next;
1580 dcesrv_connection_context_destructor(context_cur);
1584 dcesrv_terminate_connection(cur, cur->terminate);
1588 /* We need this include to be able to compile on some plateforms
1589 * (ie. freebsd 7.2) as it seems that <sys/uio.h> is not included
1591 * It has to be that deep because otherwise we have a conflict on
1592 * const struct dcesrv_interface declaration.
1593 * This is mostly due to socket_wrapper defining #define bind swrap_bind
1594 * which conflict with the bind used before.
1596 #include "system/network.h"
1598 struct dcesrv_sock_reply_state {
1599 struct dcesrv_connection *dce_conn;
1600 struct dcesrv_call_state *call;
1604 static void dcesrv_sock_reply_done(struct tevent_req *subreq);
1606 static void dcesrv_sock_report_output_data(struct dcesrv_connection *dce_conn)
1608 struct dcesrv_call_state *call;
1610 call = dce_conn->call_list;
1611 if (!call || !call->replies) {
1615 while (call->replies) {
1616 struct data_blob_list_item *rep = call->replies;
1617 struct dcesrv_sock_reply_state *substate;
1618 struct tevent_req *subreq;
1620 substate = talloc_zero(call, struct dcesrv_sock_reply_state);
1622 dcesrv_terminate_connection(dce_conn, "no memory");
1626 substate->dce_conn = dce_conn;
1627 substate->call = NULL;
1629 DLIST_REMOVE(call->replies, rep);
1631 if (call->replies == NULL) {
1632 substate->call = call;
1635 substate->iov.iov_base = (void *) rep->blob.data;
1636 substate->iov.iov_len = rep->blob.length;
1638 subreq = tstream_writev_queue_send(substate,
1639 dce_conn->event_ctx,
1641 dce_conn->send_queue,
1644 dcesrv_terminate_connection(dce_conn, "no memory");
1647 tevent_req_set_callback(subreq, dcesrv_sock_reply_done,
1651 DLIST_REMOVE(call->conn->call_list, call);
1652 call->list = DCESRV_LIST_NONE;
1655 static void dcesrv_sock_reply_done(struct tevent_req *subreq)
1657 struct dcesrv_sock_reply_state *substate = tevent_req_callback_data(subreq,
1658 struct dcesrv_sock_reply_state);
1662 struct dcesrv_call_state *call = substate->call;
1664 ret = tstream_writev_queue_recv(subreq, &sys_errno);
1665 TALLOC_FREE(subreq);
1667 status = map_nt_error_from_unix_common(sys_errno);
1668 dcesrv_terminate_connection(substate->dce_conn, nt_errstr(status));
1672 talloc_free(substate);
1681 struct dcesrv_socket_context {
1682 const struct dcesrv_endpoint *endpoint;
1683 struct dcesrv_context *dcesrv_ctx;
1687 static void dcesrv_read_fragment_done(struct tevent_req *subreq);
1689 static void dcesrv_sock_accept(struct stream_connection *srv_conn)
1692 struct dcesrv_socket_context *dcesrv_sock =
1693 talloc_get_type(srv_conn->private_data, struct dcesrv_socket_context);
1694 enum dcerpc_transport_t transport =
1695 dcerpc_binding_get_transport(dcesrv_sock->endpoint->ep_description);
1696 struct dcesrv_connection *dcesrv_conn = NULL;
1698 struct tevent_req *subreq;
1699 struct loadparm_context *lp_ctx = dcesrv_sock->dcesrv_ctx->lp_ctx;
1701 dcesrv_cleanup_broken_connections(dcesrv_sock->dcesrv_ctx);
1703 if (!srv_conn->session_info) {
1704 status = auth_anonymous_session_info(srv_conn,
1706 &srv_conn->session_info);
1707 if (!NT_STATUS_IS_OK(status)) {
1708 DEBUG(0,("dcesrv_sock_accept: auth_anonymous_session_info failed: %s\n",
1709 nt_errstr(status)));
1710 stream_terminate_connection(srv_conn, nt_errstr(status));
1715 status = dcesrv_endpoint_connect(dcesrv_sock->dcesrv_ctx,
1717 dcesrv_sock->endpoint,
1718 srv_conn->session_info,
1719 srv_conn->event.ctx,
1721 srv_conn->server_id,
1722 DCESRV_CALL_STATE_FLAG_MAY_ASYNC,
1724 if (!NT_STATUS_IS_OK(status)) {
1725 DEBUG(0,("dcesrv_sock_accept: dcesrv_endpoint_connect failed: %s\n",
1726 nt_errstr(status)));
1727 stream_terminate_connection(srv_conn, nt_errstr(status));
1731 dcesrv_conn->transport.private_data = srv_conn;
1732 dcesrv_conn->transport.report_output_data = dcesrv_sock_report_output_data;
1734 TALLOC_FREE(srv_conn->event.fde);
1736 dcesrv_conn->send_queue = tevent_queue_create(dcesrv_conn, "dcesrv send queue");
1737 if (!dcesrv_conn->send_queue) {
1738 status = NT_STATUS_NO_MEMORY;
1739 DEBUG(0,("dcesrv_sock_accept: tevent_queue_create(%s)\n",
1740 nt_errstr(status)));
1741 stream_terminate_connection(srv_conn, nt_errstr(status));
1745 if (transport == NCACN_NP) {
1746 dcesrv_conn->auth_state.session_key = dcesrv_inherited_session_key;
1747 dcesrv_conn->stream = talloc_move(dcesrv_conn,
1748 &srv_conn->tstream);
1750 ret = tstream_bsd_existing_socket(dcesrv_conn,
1751 socket_get_fd(srv_conn->socket),
1752 &dcesrv_conn->stream);
1754 status = map_nt_error_from_unix_common(errno);
1755 DEBUG(0, ("dcesrv_sock_accept: "
1756 "failed to setup tstream: %s\n",
1757 nt_errstr(status)));
1758 stream_terminate_connection(srv_conn, nt_errstr(status));
1761 socket_set_flags(srv_conn->socket, SOCKET_FLAG_NOCLOSE);
1764 dcesrv_conn->local_address = srv_conn->local_address;
1765 dcesrv_conn->remote_address = srv_conn->remote_address;
1767 if (transport == NCALRPC) {
1771 ret = getpeereid(socket_get_fd(srv_conn->socket), &uid, &gid);
1773 status = map_nt_error_from_unix_common(errno);
1774 DEBUG(0, ("dcesrv_sock_accept: "
1775 "getpeereid() failed for NCALRPC: %s\n",
1776 nt_errstr(status)));
1777 stream_terminate_connection(srv_conn, nt_errstr(status));
1780 if (uid == dcesrv_conn->dce_ctx->initial_euid) {
1781 struct tsocket_address *r = NULL;
1783 ret = tsocket_address_unix_from_path(dcesrv_conn,
1784 "/root/ncalrpc_as_system",
1787 status = map_nt_error_from_unix_common(errno);
1788 DEBUG(0, ("dcesrv_sock_accept: "
1789 "tsocket_address_unix_from_path() failed for NCALRPC: %s\n",
1790 nt_errstr(status)));
1791 stream_terminate_connection(srv_conn, nt_errstr(status));
1794 dcesrv_conn->remote_address = r;
1798 srv_conn->private_data = dcesrv_conn;
1800 irpc_add_name(srv_conn->msg_ctx, "rpc_server");
1802 subreq = dcerpc_read_ncacn_packet_send(dcesrv_conn,
1803 dcesrv_conn->event_ctx,
1804 dcesrv_conn->stream);
1806 status = NT_STATUS_NO_MEMORY;
1807 DEBUG(0,("dcesrv_sock_accept: dcerpc_read_fragment_buffer_send(%s)\n",
1808 nt_errstr(status)));
1809 stream_terminate_connection(srv_conn, nt_errstr(status));
1812 tevent_req_set_callback(subreq, dcesrv_read_fragment_done, dcesrv_conn);
1817 static void dcesrv_read_fragment_done(struct tevent_req *subreq)
1819 struct dcesrv_connection *dce_conn = tevent_req_callback_data(subreq,
1820 struct dcesrv_connection);
1821 struct dcesrv_context *dce_ctx = dce_conn->dce_ctx;
1822 struct ncacn_packet *pkt;
1826 if (dce_conn->terminate) {
1828 * if the current connection is broken
1829 * we need to clean it up before any other connection
1831 dcesrv_terminate_connection(dce_conn, dce_conn->terminate);
1832 dcesrv_cleanup_broken_connections(dce_ctx);
1836 dcesrv_cleanup_broken_connections(dce_ctx);
1838 status = dcerpc_read_ncacn_packet_recv(subreq, dce_conn,
1840 TALLOC_FREE(subreq);
1841 if (!NT_STATUS_IS_OK(status)) {
1842 dcesrv_terminate_connection(dce_conn, nt_errstr(status));
1846 status = dcesrv_process_ncacn_packet(dce_conn, pkt, buffer);
1847 if (!NT_STATUS_IS_OK(status)) {
1848 dcesrv_terminate_connection(dce_conn, nt_errstr(status));
1852 subreq = dcerpc_read_ncacn_packet_send(dce_conn,
1853 dce_conn->event_ctx,
1856 status = NT_STATUS_NO_MEMORY;
1857 dcesrv_terminate_connection(dce_conn, nt_errstr(status));
1860 tevent_req_set_callback(subreq, dcesrv_read_fragment_done, dce_conn);
1863 static void dcesrv_sock_recv(struct stream_connection *conn, uint16_t flags)
1865 struct dcesrv_connection *dce_conn = talloc_get_type(conn->private_data,
1866 struct dcesrv_connection);
1867 dcesrv_terminate_connection(dce_conn, "dcesrv_sock_recv triggered");
1870 static void dcesrv_sock_send(struct stream_connection *conn, uint16_t flags)
1872 struct dcesrv_connection *dce_conn = talloc_get_type(conn->private_data,
1873 struct dcesrv_connection);
1874 dcesrv_terminate_connection(dce_conn, "dcesrv_sock_send triggered");
1878 static const struct stream_server_ops dcesrv_stream_ops = {
1880 .accept_connection = dcesrv_sock_accept,
1881 .recv_handler = dcesrv_sock_recv,
1882 .send_handler = dcesrv_sock_send,
1885 static NTSTATUS dcesrv_add_ep_unix(struct dcesrv_context *dce_ctx,
1886 struct loadparm_context *lp_ctx,
1887 struct dcesrv_endpoint *e,
1888 struct tevent_context *event_ctx, const struct model_ops *model_ops)
1890 struct dcesrv_socket_context *dcesrv_sock;
1893 const char *endpoint;
1895 dcesrv_sock = talloc_zero(event_ctx, struct dcesrv_socket_context);
1896 NT_STATUS_HAVE_NO_MEMORY(dcesrv_sock);
1898 /* remember the endpoint of this socket */
1899 dcesrv_sock->endpoint = e;
1900 dcesrv_sock->dcesrv_ctx = talloc_reference(dcesrv_sock, dce_ctx);
1902 endpoint = dcerpc_binding_get_string_option(e->ep_description, "endpoint");
1904 status = stream_setup_socket(dcesrv_sock, event_ctx, lp_ctx,
1905 model_ops, &dcesrv_stream_ops,
1906 "unix", endpoint, &port,
1907 lpcfg_socket_options(lp_ctx),
1909 if (!NT_STATUS_IS_OK(status)) {
1910 DEBUG(0,("service_setup_stream_socket(path=%s) failed - %s\n",
1911 endpoint, nt_errstr(status)));
1917 static NTSTATUS dcesrv_add_ep_ncalrpc(struct dcesrv_context *dce_ctx,
1918 struct loadparm_context *lp_ctx,
1919 struct dcesrv_endpoint *e,
1920 struct tevent_context *event_ctx, const struct model_ops *model_ops)
1922 struct dcesrv_socket_context *dcesrv_sock;
1926 const char *endpoint;
1928 endpoint = dcerpc_binding_get_string_option(e->ep_description, "endpoint");
1930 if (endpoint == NULL) {
1932 * No identifier specified: use DEFAULT.
1934 * TODO: DO NOT hardcode this value anywhere else. Rather, specify
1935 * no endpoint and let the epmapper worry about it.
1937 endpoint = "DEFAULT";
1938 status = dcerpc_binding_set_string_option(e->ep_description,
1941 if (!NT_STATUS_IS_OK(status)) {
1942 DEBUG(0,("dcerpc_binding_set_string_option() failed - %s\n",
1943 nt_errstr(status)));
1948 full_path = talloc_asprintf(dce_ctx, "%s/%s", lpcfg_ncalrpc_dir(lp_ctx),
1951 dcesrv_sock = talloc_zero(event_ctx, struct dcesrv_socket_context);
1952 NT_STATUS_HAVE_NO_MEMORY(dcesrv_sock);
1954 /* remember the endpoint of this socket */
1955 dcesrv_sock->endpoint = e;
1956 dcesrv_sock->dcesrv_ctx = talloc_reference(dcesrv_sock, dce_ctx);
1958 status = stream_setup_socket(dcesrv_sock, event_ctx, lp_ctx,
1959 model_ops, &dcesrv_stream_ops,
1960 "unix", full_path, &port,
1961 lpcfg_socket_options(lp_ctx),
1963 if (!NT_STATUS_IS_OK(status)) {
1964 DEBUG(0,("service_setup_stream_socket(identifier=%s,path=%s) failed - %s\n",
1965 endpoint, full_path, nt_errstr(status)));
1970 static NTSTATUS dcesrv_add_ep_np(struct dcesrv_context *dce_ctx,
1971 struct loadparm_context *lp_ctx,
1972 struct dcesrv_endpoint *e,
1973 struct tevent_context *event_ctx, const struct model_ops *model_ops)
1975 struct dcesrv_socket_context *dcesrv_sock;
1977 const char *endpoint;
1979 endpoint = dcerpc_binding_get_string_option(e->ep_description, "endpoint");
1980 if (endpoint == NULL) {
1981 DEBUG(0, ("Endpoint mandatory for named pipes\n"));
1982 return NT_STATUS_INVALID_PARAMETER;
1985 dcesrv_sock = talloc_zero(event_ctx, struct dcesrv_socket_context);
1986 NT_STATUS_HAVE_NO_MEMORY(dcesrv_sock);
1988 /* remember the endpoint of this socket */
1989 dcesrv_sock->endpoint = e;
1990 dcesrv_sock->dcesrv_ctx = talloc_reference(dcesrv_sock, dce_ctx);
1992 status = tstream_setup_named_pipe(dce_ctx, event_ctx, lp_ctx,
1993 model_ops, &dcesrv_stream_ops,
1996 if (!NT_STATUS_IS_OK(status)) {
1997 DEBUG(0,("stream_setup_named_pipe(pipe=%s) failed - %s\n",
1998 endpoint, nt_errstr(status)));
2002 return NT_STATUS_OK;
2006 add a socket address to the list of events, one event per dcerpc endpoint
2008 static NTSTATUS add_socket_rpc_tcp_iface(struct dcesrv_context *dce_ctx, struct dcesrv_endpoint *e,
2009 struct tevent_context *event_ctx, const struct model_ops *model_ops,
2010 const char *address)
2012 struct dcesrv_socket_context *dcesrv_sock;
2015 const char *endpoint;
2018 endpoint = dcerpc_binding_get_string_option(e->ep_description, "endpoint");
2019 if (endpoint != NULL) {
2020 port = atoi(endpoint);
2023 dcesrv_sock = talloc_zero(event_ctx, struct dcesrv_socket_context);
2024 NT_STATUS_HAVE_NO_MEMORY(dcesrv_sock);
2026 /* remember the endpoint of this socket */
2027 dcesrv_sock->endpoint = e;
2028 dcesrv_sock->dcesrv_ctx = talloc_reference(dcesrv_sock, dce_ctx);
2030 status = stream_setup_socket(dcesrv_sock, event_ctx, dce_ctx->lp_ctx,
2031 model_ops, &dcesrv_stream_ops,
2032 "ip", address, &port,
2033 lpcfg_socket_options(dce_ctx->lp_ctx),
2035 if (!NT_STATUS_IS_OK(status)) {
2036 DEBUG(0,("service_setup_stream_socket(address=%s,port=%u) failed - %s\n",
2037 address, port, nt_errstr(status)));
2041 snprintf(port_str, sizeof(port_str), "%u", port);
2043 status = dcerpc_binding_set_string_option(e->ep_description,
2044 "endpoint", port_str);
2045 if (!NT_STATUS_IS_OK(status)) {
2046 DEBUG(0,("dcerpc_binding_set_string_option(endpoint, %s) failed - %s\n",
2047 port_str, nt_errstr(status)));
2051 return NT_STATUS_OK;
2054 #include "lib/socket/netif.h" /* Included here to work around the fact that socket_wrapper redefines bind() */
2056 static NTSTATUS dcesrv_add_ep_tcp(struct dcesrv_context *dce_ctx,
2057 struct loadparm_context *lp_ctx,
2058 struct dcesrv_endpoint *e,
2059 struct tevent_context *event_ctx, const struct model_ops *model_ops)
2063 /* Add TCP/IP sockets */
2064 if (lpcfg_interfaces(lp_ctx) && lpcfg_bind_interfaces_only(lp_ctx)) {
2067 struct interface *ifaces;
2069 load_interface_list(dce_ctx, lp_ctx, &ifaces);
2071 num_interfaces = iface_list_count(ifaces);
2072 for(i = 0; i < num_interfaces; i++) {
2073 const char *address = iface_list_n_ip(ifaces, i);
2074 status = add_socket_rpc_tcp_iface(dce_ctx, e, event_ctx, model_ops, address);
2075 NT_STATUS_NOT_OK_RETURN(status);
2081 wcard = iface_list_wildcard(dce_ctx);
2082 NT_STATUS_HAVE_NO_MEMORY(wcard);
2083 for (i=0; wcard[i]; i++) {
2084 status = add_socket_rpc_tcp_iface(dce_ctx, e, event_ctx, model_ops, wcard[i]);
2085 if (NT_STATUS_IS_OK(status)) {
2090 if (num_binds == 0) {
2091 return NT_STATUS_INVALID_PARAMETER_MIX;
2095 return NT_STATUS_OK;
2098 NTSTATUS dcesrv_add_ep(struct dcesrv_context *dce_ctx,
2099 struct loadparm_context *lp_ctx,
2100 struct dcesrv_endpoint *e,
2101 struct tevent_context *event_ctx,
2102 const struct model_ops *model_ops)
2104 enum dcerpc_transport_t transport =
2105 dcerpc_binding_get_transport(e->ep_description);
2107 switch (transport) {
2108 case NCACN_UNIX_STREAM:
2109 return dcesrv_add_ep_unix(dce_ctx, lp_ctx, e, event_ctx, model_ops);
2112 return dcesrv_add_ep_ncalrpc(dce_ctx, lp_ctx, e, event_ctx, model_ops);
2115 return dcesrv_add_ep_tcp(dce_ctx, lp_ctx, e, event_ctx, model_ops);
2118 return dcesrv_add_ep_np(dce_ctx, lp_ctx, e, event_ctx, model_ops);
2121 return NT_STATUS_NOT_SUPPORTED;
2127 * retrieve credentials from a dce_call
2129 _PUBLIC_ struct cli_credentials *dcesrv_call_credentials(struct dcesrv_call_state *dce_call)
2131 return dce_call->conn->auth_state.session_info->credentials;
2135 * returns true if this is an authenticated call
2137 _PUBLIC_ bool dcesrv_call_authenticated(struct dcesrv_call_state *dce_call)
2139 enum security_user_level level;
2140 level = security_session_user_level(dce_call->conn->auth_state.session_info, NULL);
2141 return level >= SECURITY_USER;
2145 * retrieve account_name for a dce_call
2147 _PUBLIC_ const char *dcesrv_call_account_name(struct dcesrv_call_state *dce_call)
2149 return dce_call->context->conn->auth_state.session_info->info->account_name;