ldb: Fix a signed/unsigned hickup
[Samba.git] / source4 / rpc_server / dcerpc_server.c
blob5ee32d5c0947c65cf1fe9d6c163e86ae0ebe3e88
1 /*
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/>.
23 #include "includes.h"
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 extern const struct dcesrv_interface dcesrv_mgmt_interface;
49 find an association group given a assoc_group_id
51 static struct dcesrv_assoc_group *dcesrv_assoc_group_find(struct dcesrv_context *dce_ctx,
52 uint32_t id)
54 void *id_ptr;
56 id_ptr = idr_find(dce_ctx->assoc_groups_idr, id);
57 if (id_ptr == NULL) {
58 return NULL;
60 return talloc_get_type_abort(id_ptr, struct dcesrv_assoc_group);
64 take a reference to an existing association group
66 static struct dcesrv_assoc_group *dcesrv_assoc_group_reference(TALLOC_CTX *mem_ctx,
67 struct dcesrv_context *dce_ctx,
68 uint32_t id)
70 struct dcesrv_assoc_group *assoc_group;
72 assoc_group = dcesrv_assoc_group_find(dce_ctx, id);
73 if (assoc_group == NULL) {
74 DEBUG(2,(__location__ ": Failed to find assoc_group 0x%08x\n", id));
75 return NULL;
77 return talloc_reference(mem_ctx, assoc_group);
80 static int dcesrv_assoc_group_destructor(struct dcesrv_assoc_group *assoc_group)
82 int ret;
83 ret = idr_remove(assoc_group->dce_ctx->assoc_groups_idr, assoc_group->id);
84 if (ret != 0) {
85 DEBUG(0,(__location__ ": Failed to remove assoc_group 0x%08x\n",
86 assoc_group->id));
88 return 0;
92 allocate a new association group
94 static struct dcesrv_assoc_group *dcesrv_assoc_group_new(TALLOC_CTX *mem_ctx,
95 struct dcesrv_context *dce_ctx)
97 struct dcesrv_assoc_group *assoc_group;
98 int id;
100 assoc_group = talloc_zero(mem_ctx, struct dcesrv_assoc_group);
101 if (assoc_group == NULL) {
102 return NULL;
105 id = idr_get_new_random(dce_ctx->assoc_groups_idr, assoc_group, UINT16_MAX);
106 if (id == -1) {
107 talloc_free(assoc_group);
108 DEBUG(0,(__location__ ": Out of association groups!\n"));
109 return NULL;
112 assoc_group->id = id;
113 assoc_group->dce_ctx = dce_ctx;
115 talloc_set_destructor(assoc_group, dcesrv_assoc_group_destructor);
117 return assoc_group;
122 see if two endpoints match
124 static bool endpoints_match(const struct dcerpc_binding *ep1,
125 const struct dcerpc_binding *ep2)
127 enum dcerpc_transport_t t1;
128 enum dcerpc_transport_t t2;
129 const char *e1;
130 const char *e2;
132 t1 = dcerpc_binding_get_transport(ep1);
133 t2 = dcerpc_binding_get_transport(ep2);
135 e1 = dcerpc_binding_get_string_option(ep1, "endpoint");
136 e2 = dcerpc_binding_get_string_option(ep2, "endpoint");
138 if (t1 != t2) {
139 return false;
142 if (!e1 || !e2) {
143 return e1 == e2;
146 if (strcasecmp(e1, e2) != 0) {
147 return false;
150 return true;
154 find an endpoint in the dcesrv_context
156 static struct dcesrv_endpoint *find_endpoint(struct dcesrv_context *dce_ctx,
157 const struct dcerpc_binding *ep_description)
159 struct dcesrv_endpoint *ep;
160 for (ep=dce_ctx->endpoint_list; ep; ep=ep->next) {
161 if (endpoints_match(ep->ep_description, ep_description)) {
162 return ep;
165 return NULL;
169 find a registered context_id from a bind or alter_context
171 static struct dcesrv_connection_context *dcesrv_find_context(struct dcesrv_connection *conn,
172 uint16_t context_id)
174 struct dcesrv_connection_context *c;
175 for (c=conn->contexts;c;c=c->next) {
176 if (c->context_id == context_id) return c;
178 return NULL;
182 see if a uuid and if_version match to an interface
184 static bool interface_match(const struct dcesrv_interface *if1,
185 const struct dcesrv_interface *if2)
187 return (if1->syntax_id.if_version == if2->syntax_id.if_version &&
188 GUID_equal(&if1->syntax_id.uuid, &if2->syntax_id.uuid));
192 find the interface operations on an endpoint
194 static const struct dcesrv_interface *find_interface(const struct dcesrv_endpoint *endpoint,
195 const struct dcesrv_interface *iface)
197 struct dcesrv_if_list *ifl;
198 for (ifl=endpoint->interface_list; ifl; ifl=ifl->next) {
199 if (interface_match(&(ifl->iface), iface)) {
200 return &(ifl->iface);
203 return NULL;
207 see if a uuid and if_version match to an interface
209 static bool interface_match_by_uuid(const struct dcesrv_interface *iface,
210 const struct GUID *uuid, uint32_t if_version)
212 return (iface->syntax_id.if_version == if_version &&
213 GUID_equal(&iface->syntax_id.uuid, uuid));
217 find the interface operations on an endpoint by uuid
219 static const struct dcesrv_interface *find_interface_by_uuid(const struct dcesrv_endpoint *endpoint,
220 const struct GUID *uuid, uint32_t if_version)
222 struct dcesrv_if_list *ifl;
223 for (ifl=endpoint->interface_list; ifl; ifl=ifl->next) {
224 if (interface_match_by_uuid(&(ifl->iface), uuid, if_version)) {
225 return &(ifl->iface);
228 return NULL;
232 find the earlier parts of a fragmented call awaiting reassembily
234 static struct dcesrv_call_state *dcesrv_find_fragmented_call(struct dcesrv_connection *dce_conn, uint16_t call_id)
236 struct dcesrv_call_state *c;
237 for (c=dce_conn->incoming_fragmented_call_list;c;c=c->next) {
238 if (c->pkt.call_id == call_id) {
239 return c;
242 return NULL;
246 register an interface on an endpoint
248 _PUBLIC_ NTSTATUS dcesrv_interface_register(struct dcesrv_context *dce_ctx,
249 const char *ep_name,
250 const struct dcesrv_interface *iface,
251 const struct security_descriptor *sd)
253 struct dcesrv_endpoint *ep;
254 struct dcesrv_if_list *ifl;
255 struct dcerpc_binding *binding;
256 bool add_ep = false;
257 NTSTATUS status;
259 status = dcerpc_parse_binding(dce_ctx, ep_name, &binding);
261 if (NT_STATUS_IS_ERR(status)) {
262 DEBUG(0, ("Trouble parsing binding string '%s'\n", ep_name));
263 return status;
266 /* check if this endpoint exists
268 if ((ep=find_endpoint(dce_ctx, binding))==NULL) {
269 ep = talloc_zero(dce_ctx, struct dcesrv_endpoint);
270 if (!ep) {
271 return NT_STATUS_NO_MEMORY;
273 ZERO_STRUCTP(ep);
274 ep->ep_description = talloc_move(ep, &binding);
275 add_ep = true;
277 /* add mgmt interface */
278 ifl = talloc_zero(ep, struct dcesrv_if_list);
279 if (!ifl) {
280 return NT_STATUS_NO_MEMORY;
283 memcpy(&(ifl->iface), &dcesrv_mgmt_interface,
284 sizeof(struct dcesrv_interface));
286 DLIST_ADD(ep->interface_list, ifl);
289 /* see if the interface is already registered on te endpoint */
290 if (find_interface(ep, iface)!=NULL) {
291 DEBUG(0,("dcesrv_interface_register: interface '%s' already registered on endpoint '%s'\n",
292 iface->name, ep_name));
293 return NT_STATUS_OBJECT_NAME_COLLISION;
296 /* talloc a new interface list element */
297 ifl = talloc_zero(ep, struct dcesrv_if_list);
298 if (!ifl) {
299 return NT_STATUS_NO_MEMORY;
302 /* copy the given interface struct to the one on the endpoints interface list */
303 memcpy(&(ifl->iface),iface, sizeof(struct dcesrv_interface));
305 /* if we have a security descriptor given,
306 * we should see if we can set it up on the endpoint
308 if (sd != NULL) {
309 /* if there's currently no security descriptor given on the endpoint
310 * we try to set it
312 if (ep->sd == NULL) {
313 ep->sd = security_descriptor_copy(ep, sd);
316 /* if now there's no security descriptor given on the endpoint
317 * something goes wrong, either we failed to copy the security descriptor
318 * or there was already one on the endpoint
320 if (ep->sd != NULL) {
321 DEBUG(0,("dcesrv_interface_register: interface '%s' failed to setup a security descriptor\n"
322 " on endpoint '%s'\n",
323 iface->name, ep_name));
324 if (add_ep) free(ep);
325 free(ifl);
326 return NT_STATUS_OBJECT_NAME_COLLISION;
330 /* finally add the interface on the endpoint */
331 DLIST_ADD(ep->interface_list, ifl);
333 /* if it's a new endpoint add it to the dcesrv_context */
334 if (add_ep) {
335 DLIST_ADD(dce_ctx->endpoint_list, ep);
338 DEBUG(4,("dcesrv_interface_register: interface '%s' registered on endpoint '%s'\n",
339 iface->name, ep_name));
341 return NT_STATUS_OK;
344 NTSTATUS dcesrv_inherited_session_key(struct dcesrv_connection *p,
345 DATA_BLOB *session_key)
347 if (p->auth_state.session_info->session_key.length) {
348 *session_key = p->auth_state.session_info->session_key;
349 return NT_STATUS_OK;
351 return NT_STATUS_NO_USER_SESSION_KEY;
355 fetch the user session key - may be default (above) or the SMB session key
357 The key is always truncated to 16 bytes
359 _PUBLIC_ NTSTATUS dcesrv_fetch_session_key(struct dcesrv_connection *p,
360 DATA_BLOB *session_key)
362 NTSTATUS status = p->auth_state.session_key(p, session_key);
363 if (!NT_STATUS_IS_OK(status)) {
364 return status;
367 session_key->length = MIN(session_key->length, 16);
369 return NT_STATUS_OK;
373 connect to a dcerpc endpoint
375 _PUBLIC_ NTSTATUS dcesrv_endpoint_connect(struct dcesrv_context *dce_ctx,
376 TALLOC_CTX *mem_ctx,
377 const struct dcesrv_endpoint *ep,
378 struct auth_session_info *session_info,
379 struct tevent_context *event_ctx,
380 struct imessaging_context *msg_ctx,
381 struct server_id server_id,
382 uint32_t state_flags,
383 struct dcesrv_connection **_p)
385 struct dcesrv_connection *p;
387 if (!session_info) {
388 return NT_STATUS_ACCESS_DENIED;
391 p = talloc_zero(mem_ctx, struct dcesrv_connection);
392 NT_STATUS_HAVE_NO_MEMORY(p);
394 if (!talloc_reference(p, session_info)) {
395 talloc_free(p);
396 return NT_STATUS_NO_MEMORY;
399 p->dce_ctx = dce_ctx;
400 p->endpoint = ep;
401 p->packet_log_dir = lpcfg_lock_directory(dce_ctx->lp_ctx);
402 p->auth_state.session_info = session_info;
403 p->auth_state.session_key = dcesrv_generic_session_key;
404 p->event_ctx = event_ctx;
405 p->msg_ctx = msg_ctx;
406 p->server_id = server_id;
407 p->state_flags = state_flags;
408 p->allow_bind = true;
409 p->max_recv_frag = 5840;
410 p->max_xmit_frag = 5840;
411 p->max_total_request_size = DCERPC_NCACN_REQUEST_DEFAULT_MAX_SIZE;
413 *_p = p;
414 return NT_STATUS_OK;
418 move a call from an existing linked list to the specified list. This
419 prevents bugs where we forget to remove the call from a previous
420 list when moving it.
422 static void dcesrv_call_set_list(struct dcesrv_call_state *call,
423 enum dcesrv_call_list list)
425 switch (call->list) {
426 case DCESRV_LIST_NONE:
427 break;
428 case DCESRV_LIST_CALL_LIST:
429 DLIST_REMOVE(call->conn->call_list, call);
430 break;
431 case DCESRV_LIST_FRAGMENTED_CALL_LIST:
432 DLIST_REMOVE(call->conn->incoming_fragmented_call_list, call);
433 break;
434 case DCESRV_LIST_PENDING_CALL_LIST:
435 DLIST_REMOVE(call->conn->pending_call_list, call);
436 break;
438 call->list = list;
439 switch (list) {
440 case DCESRV_LIST_NONE:
441 break;
442 case DCESRV_LIST_CALL_LIST:
443 DLIST_ADD_END(call->conn->call_list, call);
444 break;
445 case DCESRV_LIST_FRAGMENTED_CALL_LIST:
446 DLIST_ADD_END(call->conn->incoming_fragmented_call_list, call);
447 break;
448 case DCESRV_LIST_PENDING_CALL_LIST:
449 DLIST_ADD_END(call->conn->pending_call_list, call);
450 break;
454 static void dcesrv_call_disconnect_after(struct dcesrv_call_state *call,
455 const char *reason)
457 if (call->conn->terminate != NULL) {
458 return;
461 call->conn->allow_bind = false;
462 call->conn->allow_alter = false;
463 call->conn->allow_auth3 = false;
464 call->conn->allow_request = false;
466 call->terminate_reason = talloc_strdup(call, reason);
467 if (call->terminate_reason == NULL) {
468 call->terminate_reason = __location__;
473 return a dcerpc bind_nak
475 static NTSTATUS dcesrv_bind_nak(struct dcesrv_call_state *call, uint32_t reason)
477 struct ncacn_packet pkt;
478 struct dcerpc_bind_nak_version version;
479 struct data_blob_list_item *rep;
480 NTSTATUS status;
481 static const uint8_t _pad[3] = { 0, };
484 * We add the call to the pending_call_list
485 * in order to defer the termination.
487 dcesrv_call_disconnect_after(call, "dcesrv_bind_nak");
489 /* setup a bind_nak */
490 dcesrv_init_hdr(&pkt, lpcfg_rpc_big_endian(call->conn->dce_ctx->lp_ctx));
491 pkt.auth_length = 0;
492 pkt.call_id = call->pkt.call_id;
493 pkt.ptype = DCERPC_PKT_BIND_NAK;
494 pkt.pfc_flags = DCERPC_PFC_FLAG_FIRST | DCERPC_PFC_FLAG_LAST;
495 pkt.u.bind_nak.reject_reason = reason;
496 version.rpc_vers = 5;
497 version.rpc_vers_minor = 0;
498 pkt.u.bind_nak.num_versions = 1;
499 pkt.u.bind_nak.versions = &version;
500 pkt.u.bind_nak._pad = data_blob_const(_pad, sizeof(_pad));
502 rep = talloc_zero(call, struct data_blob_list_item);
503 if (!rep) {
504 return NT_STATUS_NO_MEMORY;
507 status = ncacn_push_auth(&rep->blob, call, &pkt, NULL);
508 if (!NT_STATUS_IS_OK(status)) {
509 return status;
512 dcerpc_set_frag_length(&rep->blob, rep->blob.length);
514 DLIST_ADD_END(call->replies, rep);
515 dcesrv_call_set_list(call, DCESRV_LIST_CALL_LIST);
517 if (call->conn->call_list && call->conn->call_list->replies) {
518 if (call->conn->transport.report_output_data) {
519 call->conn->transport.report_output_data(call->conn);
523 return NT_STATUS_OK;
526 static NTSTATUS dcesrv_fault_disconnect(struct dcesrv_call_state *call,
527 uint32_t fault_code)
530 * We add the call to the pending_call_list
531 * in order to defer the termination.
533 dcesrv_call_disconnect_after(call, "dcesrv_fault_disconnect");
535 return dcesrv_fault_with_flags(call, fault_code,
536 DCERPC_PFC_FLAG_DID_NOT_EXECUTE);
539 static int dcesrv_connection_context_destructor(struct dcesrv_connection_context *c)
541 DLIST_REMOVE(c->conn->contexts, c);
543 if (c->iface && c->iface->unbind) {
544 c->iface->unbind(c, c->iface);
545 c->iface = NULL;
548 return 0;
551 static void dcesrv_prepare_context_auth(struct dcesrv_call_state *dce_call)
553 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
554 const struct dcesrv_endpoint *endpoint = dce_call->conn->endpoint;
555 enum dcerpc_transport_t transport =
556 dcerpc_binding_get_transport(endpoint->ep_description);
557 struct dcesrv_connection_context *context = dce_call->context;
558 const struct dcesrv_interface *iface = context->iface;
560 context->min_auth_level = DCERPC_AUTH_LEVEL_NONE;
562 if (transport == NCALRPC) {
563 context->allow_connect = true;
564 return;
568 * allow overwrite per interface
569 * allow dcerpc auth level connect:<interface>
571 context->allow_connect = lpcfg_allow_dcerpc_auth_level_connect(lp_ctx);
572 context->allow_connect = lpcfg_parm_bool(lp_ctx, NULL,
573 "allow dcerpc auth level connect",
574 iface->name,
575 context->allow_connect);
578 NTSTATUS dcesrv_interface_bind_require_integrity(struct dcesrv_call_state *dce_call,
579 const struct dcesrv_interface *iface)
581 if (dce_call->context == NULL) {
582 return NT_STATUS_INTERNAL_ERROR;
585 dce_call->context->min_auth_level = DCERPC_AUTH_LEVEL_INTEGRITY;
586 return NT_STATUS_OK;
589 NTSTATUS dcesrv_interface_bind_require_privacy(struct dcesrv_call_state *dce_call,
590 const struct dcesrv_interface *iface)
592 if (dce_call->context == NULL) {
593 return NT_STATUS_INTERNAL_ERROR;
596 dce_call->context->min_auth_level = DCERPC_AUTH_LEVEL_PRIVACY;
597 return NT_STATUS_OK;
600 _PUBLIC_ NTSTATUS dcesrv_interface_bind_reject_connect(struct dcesrv_call_state *dce_call,
601 const struct dcesrv_interface *iface)
603 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
604 const struct dcesrv_endpoint *endpoint = dce_call->conn->endpoint;
605 enum dcerpc_transport_t transport =
606 dcerpc_binding_get_transport(endpoint->ep_description);
607 struct dcesrv_connection_context *context = dce_call->context;
609 if (context == NULL) {
610 return NT_STATUS_INTERNAL_ERROR;
613 if (transport == NCALRPC) {
614 context->allow_connect = true;
615 return NT_STATUS_OK;
619 * allow overwrite per interface
620 * allow dcerpc auth level connect:<interface>
622 context->allow_connect = false;
623 context->allow_connect = lpcfg_parm_bool(lp_ctx, NULL,
624 "allow dcerpc auth level connect",
625 iface->name,
626 context->allow_connect);
627 return NT_STATUS_OK;
630 _PUBLIC_ NTSTATUS dcesrv_interface_bind_allow_connect(struct dcesrv_call_state *dce_call,
631 const struct dcesrv_interface *iface)
633 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
634 const struct dcesrv_endpoint *endpoint = dce_call->conn->endpoint;
635 enum dcerpc_transport_t transport =
636 dcerpc_binding_get_transport(endpoint->ep_description);
637 struct dcesrv_connection_context *context = dce_call->context;
639 if (context == NULL) {
640 return NT_STATUS_INTERNAL_ERROR;
643 if (transport == NCALRPC) {
644 context->allow_connect = true;
645 return NT_STATUS_OK;
649 * allow overwrite per interface
650 * allow dcerpc auth level connect:<interface>
652 context->allow_connect = true;
653 context->allow_connect = lpcfg_parm_bool(lp_ctx, NULL,
654 "allow dcerpc auth level connect",
655 iface->name,
656 context->allow_connect);
657 return NT_STATUS_OK;
661 handle a bind request
663 static NTSTATUS dcesrv_bind(struct dcesrv_call_state *call)
665 uint32_t if_version, transfer_syntax_version;
666 struct GUID uuid, *transfer_syntax_uuid;
667 struct ncacn_packet pkt;
668 struct data_blob_list_item *rep;
669 NTSTATUS status;
670 uint32_t result=0, reason=0;
671 uint16_t context_id;
672 const struct dcesrv_interface *iface;
673 uint32_t extra_flags = 0;
674 uint16_t max_req = 0;
675 uint16_t max_rep = 0;
676 const char *ep_prefix = "";
677 const char *endpoint = NULL;
679 status = dcerpc_verify_ncacn_packet_header(&call->pkt,
680 DCERPC_PKT_BIND,
681 call->pkt.u.bind.auth_info.length,
682 0, /* required flags */
683 DCERPC_PFC_FLAG_FIRST |
684 DCERPC_PFC_FLAG_LAST |
685 DCERPC_PFC_FLAG_SUPPORT_HEADER_SIGN |
686 0x08 | /* this is not defined, but should be ignored */
687 DCERPC_PFC_FLAG_CONC_MPX |
688 DCERPC_PFC_FLAG_DID_NOT_EXECUTE |
689 DCERPC_PFC_FLAG_MAYBE |
690 DCERPC_PFC_FLAG_OBJECT_UUID);
691 if (!NT_STATUS_IS_OK(status)) {
692 return dcesrv_bind_nak(call,
693 DCERPC_BIND_NAK_REASON_PROTOCOL_VERSION_NOT_SUPPORTED);
696 /* max_recv_frag and max_xmit_frag result always in the same value! */
697 max_req = MIN(call->pkt.u.bind.max_xmit_frag,
698 call->pkt.u.bind.max_recv_frag);
700 * The values are between 2048 and 5840 tested against Windows 2012R2
701 * via ncacn_ip_tcp on port 135.
703 max_req = MAX(2048, max_req);
704 max_rep = MIN(max_req, call->conn->max_recv_frag);
705 /* They are truncated to an 8 byte boundary. */
706 max_rep &= 0xFFF8;
708 /* max_recv_frag and max_xmit_frag result always in the same value! */
709 call->conn->max_recv_frag = max_rep;
710 call->conn->max_xmit_frag = max_rep;
713 if provided, check the assoc_group is valid
715 if (call->pkt.u.bind.assoc_group_id != 0) {
716 call->conn->assoc_group = dcesrv_assoc_group_reference(call->conn,
717 call->conn->dce_ctx,
718 call->pkt.u.bind.assoc_group_id);
719 } else {
720 call->conn->assoc_group = dcesrv_assoc_group_new(call->conn,
721 call->conn->dce_ctx);
723 if (call->conn->assoc_group == NULL) {
724 return dcesrv_bind_nak(call, 0);
727 if (call->pkt.u.bind.num_contexts < 1 ||
728 call->pkt.u.bind.ctx_list[0].num_transfer_syntaxes < 1) {
729 return dcesrv_bind_nak(call, 0);
732 context_id = call->pkt.u.bind.ctx_list[0].context_id;
733 if_version = call->pkt.u.bind.ctx_list[0].abstract_syntax.if_version;
734 uuid = call->pkt.u.bind.ctx_list[0].abstract_syntax.uuid;
736 transfer_syntax_version = call->pkt.u.bind.ctx_list[0].transfer_syntaxes[0].if_version;
737 transfer_syntax_uuid = &call->pkt.u.bind.ctx_list[0].transfer_syntaxes[0].uuid;
738 if (!GUID_equal(&ndr_transfer_syntax_ndr.uuid, transfer_syntax_uuid) != 0 ||
739 ndr_transfer_syntax_ndr.if_version != transfer_syntax_version) {
740 char *uuid_str = GUID_string(call, transfer_syntax_uuid);
741 /* we only do NDR encoded dcerpc */
742 DEBUG(0,("Non NDR transfer syntax requested - %s\n", uuid_str));
743 talloc_free(uuid_str);
744 return dcesrv_bind_nak(call, 0);
747 iface = find_interface_by_uuid(call->conn->endpoint, &uuid, if_version);
748 if (iface == NULL) {
749 char *uuid_str = GUID_string(call, &uuid);
750 DEBUG(2,("Request for unknown dcerpc interface %s/%d\n", uuid_str, if_version));
751 talloc_free(uuid_str);
753 /* we don't know about that interface */
754 result = DCERPC_BIND_PROVIDER_REJECT;
755 reason = DCERPC_BIND_REASON_ASYNTAX;
758 if (iface) {
759 /* add this context to the list of available context_ids */
760 struct dcesrv_connection_context *context = talloc_zero(call->conn,
761 struct dcesrv_connection_context);
762 if (context == NULL) {
763 return dcesrv_bind_nak(call, 0);
765 context->conn = call->conn;
766 context->iface = iface;
767 context->context_id = context_id;
768 context->private_data = NULL;
769 DLIST_ADD(call->conn->contexts, context);
770 call->context = context;
771 talloc_set_destructor(context, dcesrv_connection_context_destructor);
773 dcesrv_prepare_context_auth(call);
775 status = iface->bind(call, iface, if_version);
776 if (!NT_STATUS_IS_OK(status)) {
777 char *uuid_str = GUID_string(call, &uuid);
778 DEBUG(2,("Request for dcerpc interface %s/%d rejected: %s\n",
779 uuid_str, if_version, nt_errstr(status)));
780 talloc_free(uuid_str);
781 /* we don't want to trigger the iface->unbind() hook */
782 context->iface = NULL;
783 talloc_free(call->context);
784 call->context = NULL;
785 return dcesrv_bind_nak(call, 0);
789 if ((call->pkt.pfc_flags & DCERPC_PFC_FLAG_CONC_MPX) &&
790 (call->state_flags & DCESRV_CALL_STATE_FLAG_MULTIPLEXED)) {
791 call->context->conn->state_flags |= DCESRV_CALL_STATE_FLAG_MULTIPLEXED;
792 extra_flags |= DCERPC_PFC_FLAG_CONC_MPX;
795 if (call->state_flags & DCESRV_CALL_STATE_FLAG_PROCESS_PENDING_CALL) {
796 call->context->conn->state_flags |= DCESRV_CALL_STATE_FLAG_PROCESS_PENDING_CALL;
799 /* handle any authentication that is being requested */
800 if (!dcesrv_auth_bind(call)) {
801 struct dcesrv_auth *auth = &call->conn->auth_state;
803 TALLOC_FREE(call->context);
805 if (call->fault_code == DCERPC_NCA_S_PROTO_ERROR) {
806 return dcesrv_bind_nak(call,
807 DCERPC_BIND_NAK_REASON_PROTOCOL_VERSION_NOT_SUPPORTED);
810 if (auth->auth_level != DCERPC_AUTH_LEVEL_NONE) {
812 * We only give INVALID_AUTH_TYPE if the auth_level was
813 * valid.
815 return dcesrv_bind_nak(call,
816 DCERPC_BIND_NAK_REASON_INVALID_AUTH_TYPE);
818 return dcesrv_bind_nak(call,
819 DCERPC_BIND_NAK_REASON_NOT_SPECIFIED);
822 /* setup a bind_ack */
823 dcesrv_init_hdr(&pkt, lpcfg_rpc_big_endian(call->conn->dce_ctx->lp_ctx));
824 pkt.auth_length = 0;
825 pkt.call_id = call->pkt.call_id;
826 pkt.ptype = DCERPC_PKT_BIND_ACK;
827 pkt.pfc_flags = DCERPC_PFC_FLAG_FIRST | DCERPC_PFC_FLAG_LAST | extra_flags;
828 pkt.u.bind_ack.max_xmit_frag = call->conn->max_xmit_frag;
829 pkt.u.bind_ack.max_recv_frag = call->conn->max_recv_frag;
830 pkt.u.bind_ack.assoc_group_id = call->conn->assoc_group->id;
832 if (iface) {
833 endpoint = dcerpc_binding_get_string_option(
834 call->conn->endpoint->ep_description,
835 "endpoint");
838 if (endpoint == NULL) {
839 endpoint = "";
842 if (strncasecmp(endpoint, "\\pipe\\", 6) == 0) {
844 * TODO: check if this is really needed
846 * Or if we should fix this in our idl files.
848 ep_prefix = "\\PIPE\\";
849 endpoint += 6;
852 pkt.u.bind_ack.secondary_address = talloc_asprintf(call, "%s%s",
853 ep_prefix,
854 endpoint);
855 if (pkt.u.bind_ack.secondary_address == NULL) {
856 TALLOC_FREE(call->context);
857 return NT_STATUS_NO_MEMORY;
859 pkt.u.bind_ack.num_results = 1;
860 pkt.u.bind_ack.ctx_list = talloc_zero(call, struct dcerpc_ack_ctx);
861 if (!pkt.u.bind_ack.ctx_list) {
862 talloc_free(call->context);
863 call->context = NULL;
864 return NT_STATUS_NO_MEMORY;
866 pkt.u.bind_ack.ctx_list[0].result = result;
867 pkt.u.bind_ack.ctx_list[0].reason.value = reason;
868 pkt.u.bind_ack.ctx_list[0].syntax = ndr_transfer_syntax_ndr;
869 pkt.u.bind_ack.auth_info = data_blob(NULL, 0);
871 status = dcesrv_auth_bind_ack(call, &pkt);
872 if (!NT_STATUS_IS_OK(status)) {
873 talloc_free(call->context);
874 call->context = NULL;
875 return dcesrv_bind_nak(call, 0);
878 rep = talloc_zero(call, struct data_blob_list_item);
879 if (!rep) {
880 talloc_free(call->context);
881 call->context = NULL;
882 return NT_STATUS_NO_MEMORY;
885 status = ncacn_push_auth(&rep->blob, call, &pkt,
886 call->out_auth_info);
887 if (!NT_STATUS_IS_OK(status)) {
888 talloc_free(call->context);
889 call->context = NULL;
890 return status;
893 dcerpc_set_frag_length(&rep->blob, rep->blob.length);
895 DLIST_ADD_END(call->replies, rep);
896 dcesrv_call_set_list(call, DCESRV_LIST_CALL_LIST);
898 if (call->conn->call_list && call->conn->call_list->replies) {
899 if (call->conn->transport.report_output_data) {
900 call->conn->transport.report_output_data(call->conn);
904 return NT_STATUS_OK;
909 handle a auth3 request
911 static NTSTATUS dcesrv_auth3(struct dcesrv_call_state *call)
913 NTSTATUS status;
915 if (!call->conn->allow_auth3) {
916 return dcesrv_fault_disconnect(call, DCERPC_NCA_S_PROTO_ERROR);
919 if (call->conn->auth_state.auth_finished) {
920 return dcesrv_fault_disconnect(call, DCERPC_NCA_S_PROTO_ERROR);
923 status = dcerpc_verify_ncacn_packet_header(&call->pkt,
924 DCERPC_PKT_AUTH3,
925 call->pkt.u.auth3.auth_info.length,
926 0, /* required flags */
927 DCERPC_PFC_FLAG_FIRST |
928 DCERPC_PFC_FLAG_LAST |
929 DCERPC_PFC_FLAG_SUPPORT_HEADER_SIGN |
930 0x08 | /* this is not defined, but should be ignored */
931 DCERPC_PFC_FLAG_CONC_MPX |
932 DCERPC_PFC_FLAG_DID_NOT_EXECUTE |
933 DCERPC_PFC_FLAG_MAYBE |
934 DCERPC_PFC_FLAG_OBJECT_UUID);
935 if (!NT_STATUS_IS_OK(status)) {
936 return dcesrv_fault_disconnect(call, DCERPC_NCA_S_PROTO_ERROR);
939 /* handle the auth3 in the auth code */
940 if (!dcesrv_auth_auth3(call)) {
941 call->conn->auth_state.auth_invalid = true;
942 if (call->fault_code != 0) {
943 return dcesrv_fault_disconnect(call, call->fault_code);
947 talloc_free(call);
949 /* we don't send a reply to a auth3 request, except by a
950 fault */
951 return NT_STATUS_OK;
956 handle a bind request
958 static NTSTATUS dcesrv_alter_new_context(struct dcesrv_call_state *call, uint16_t context_id)
960 uint32_t if_version, transfer_syntax_version;
961 struct dcesrv_connection_context *context;
962 const struct dcesrv_interface *iface;
963 struct GUID uuid, *transfer_syntax_uuid;
964 NTSTATUS status;
966 if_version = call->pkt.u.alter.ctx_list[0].abstract_syntax.if_version;
967 uuid = call->pkt.u.alter.ctx_list[0].abstract_syntax.uuid;
969 transfer_syntax_version = call->pkt.u.alter.ctx_list[0].transfer_syntaxes[0].if_version;
970 transfer_syntax_uuid = &call->pkt.u.alter.ctx_list[0].transfer_syntaxes[0].uuid;
971 if (!GUID_equal(transfer_syntax_uuid, &ndr_transfer_syntax_ndr.uuid) ||
972 ndr_transfer_syntax_ndr.if_version != transfer_syntax_version) {
973 /* we only do NDR encoded dcerpc */
974 return NT_STATUS_RPC_PROTSEQ_NOT_SUPPORTED;
977 iface = find_interface_by_uuid(call->conn->endpoint, &uuid, if_version);
978 if (iface == NULL) {
979 char *uuid_str = GUID_string(call, &uuid);
980 DEBUG(2,("Request for unknown dcerpc interface %s/%d\n", uuid_str, if_version));
981 talloc_free(uuid_str);
982 return NT_STATUS_RPC_PROTSEQ_NOT_SUPPORTED;
985 /* add this context to the list of available context_ids */
986 context = talloc_zero(call->conn, struct dcesrv_connection_context);
987 if (context == NULL) {
988 return NT_STATUS_NO_MEMORY;
990 context->conn = call->conn;
991 context->iface = iface;
992 context->context_id = context_id;
993 context->private_data = NULL;
994 DLIST_ADD(call->conn->contexts, context);
995 call->context = context;
996 talloc_set_destructor(context, dcesrv_connection_context_destructor);
998 dcesrv_prepare_context_auth(call);
1000 status = iface->bind(call, iface, if_version);
1001 if (!NT_STATUS_IS_OK(status)) {
1002 /* we don't want to trigger the iface->unbind() hook */
1003 context->iface = NULL;
1004 talloc_free(context);
1005 call->context = NULL;
1006 return status;
1009 return NT_STATUS_OK;
1012 /* setup and send an alter_resp */
1013 static NTSTATUS dcesrv_alter_resp(struct dcesrv_call_state *call,
1014 uint32_t result,
1015 uint32_t reason)
1017 struct ncacn_packet pkt;
1018 uint32_t extra_flags = 0;
1019 struct data_blob_list_item *rep = NULL;
1020 NTSTATUS status;
1022 dcesrv_init_hdr(&pkt, lpcfg_rpc_big_endian(call->conn->dce_ctx->lp_ctx));
1023 pkt.auth_length = 0;
1024 pkt.call_id = call->pkt.call_id;
1025 pkt.ptype = DCERPC_PKT_ALTER_RESP;
1026 if (result == 0) {
1027 if ((call->pkt.pfc_flags & DCERPC_PFC_FLAG_CONC_MPX) &&
1028 call->context->conn->state_flags &
1029 DCESRV_CALL_STATE_FLAG_MULTIPLEXED) {
1030 extra_flags |= DCERPC_PFC_FLAG_CONC_MPX;
1032 if (call->state_flags & DCESRV_CALL_STATE_FLAG_PROCESS_PENDING_CALL) {
1033 call->context->conn->state_flags |=
1034 DCESRV_CALL_STATE_FLAG_PROCESS_PENDING_CALL;
1037 pkt.pfc_flags = DCERPC_PFC_FLAG_FIRST | DCERPC_PFC_FLAG_LAST | extra_flags;
1038 pkt.u.alter_resp.max_xmit_frag = call->conn->max_xmit_frag;
1039 pkt.u.alter_resp.max_recv_frag = call->conn->max_recv_frag;
1040 pkt.u.alter_resp.assoc_group_id = call->conn->assoc_group->id;
1041 pkt.u.alter_resp.num_results = 1;
1042 pkt.u.alter_resp.ctx_list = talloc_zero(call, struct dcerpc_ack_ctx);
1043 if (!pkt.u.alter_resp.ctx_list) {
1044 return NT_STATUS_NO_MEMORY;
1046 pkt.u.alter_resp.ctx_list[0].result = result;
1047 pkt.u.alter_resp.ctx_list[0].reason.value = reason;
1048 pkt.u.alter_resp.ctx_list[0].syntax = ndr_transfer_syntax_ndr;
1049 pkt.u.alter_resp.auth_info = data_blob(NULL, 0);
1050 pkt.u.alter_resp.secondary_address = "";
1052 status = dcesrv_auth_alter_ack(call, &pkt);
1053 if (!NT_STATUS_IS_OK(status)) {
1054 return dcesrv_fault_disconnect(call, DCERPC_FAULT_SEC_PKG_ERROR);
1057 rep = talloc_zero(call, struct data_blob_list_item);
1058 if (!rep) {
1059 return NT_STATUS_NO_MEMORY;
1062 status = ncacn_push_auth(&rep->blob, call, &pkt, call->out_auth_info);
1063 if (!NT_STATUS_IS_OK(status)) {
1064 return status;
1067 dcerpc_set_frag_length(&rep->blob, rep->blob.length);
1069 DLIST_ADD_END(call->replies, rep);
1070 dcesrv_call_set_list(call, DCESRV_LIST_CALL_LIST);
1072 if (call->conn->call_list && call->conn->call_list->replies) {
1073 if (call->conn->transport.report_output_data) {
1074 call->conn->transport.report_output_data(call->conn);
1078 return NT_STATUS_OK;
1082 handle a alter context request
1084 static NTSTATUS dcesrv_alter(struct dcesrv_call_state *call)
1086 NTSTATUS status;
1087 const struct dcerpc_ctx_list *ctx = NULL;
1088 bool auth_ok = false;
1090 if (!call->conn->allow_alter) {
1091 return dcesrv_fault_disconnect(call, DCERPC_NCA_S_PROTO_ERROR);
1094 status = dcerpc_verify_ncacn_packet_header(&call->pkt,
1095 DCERPC_PKT_ALTER,
1096 call->pkt.u.alter.auth_info.length,
1097 0, /* required flags */
1098 DCERPC_PFC_FLAG_FIRST |
1099 DCERPC_PFC_FLAG_LAST |
1100 DCERPC_PFC_FLAG_SUPPORT_HEADER_SIGN |
1101 0x08 | /* this is not defined, but should be ignored */
1102 DCERPC_PFC_FLAG_CONC_MPX |
1103 DCERPC_PFC_FLAG_DID_NOT_EXECUTE |
1104 DCERPC_PFC_FLAG_MAYBE |
1105 DCERPC_PFC_FLAG_OBJECT_UUID);
1106 if (!NT_STATUS_IS_OK(status)) {
1107 return dcesrv_fault_disconnect(call, DCERPC_NCA_S_PROTO_ERROR);
1110 auth_ok = dcesrv_auth_alter(call);
1111 if (!auth_ok) {
1112 if (call->fault_code != 0) {
1113 return dcesrv_fault_disconnect(call, call->fault_code);
1117 if (call->pkt.u.alter.num_contexts < 1) {
1118 return dcesrv_fault_disconnect(call, DCERPC_NCA_S_PROTO_ERROR);
1120 ctx = &call->pkt.u.alter.ctx_list[0];
1121 if (ctx->num_transfer_syntaxes < 1) {
1122 return dcesrv_fault_disconnect(call, DCERPC_NCA_S_PROTO_ERROR);
1125 /* see if they are asking for a new interface */
1126 call->context = dcesrv_find_context(call->conn, ctx->context_id);
1127 if (!call->context) {
1128 status = dcesrv_alter_new_context(call, ctx->context_id);
1129 if (!NT_STATUS_IS_OK(status)) {
1130 return dcesrv_alter_resp(call,
1131 DCERPC_BIND_PROVIDER_REJECT,
1132 DCERPC_BIND_REASON_ASYNTAX);
1134 } else {
1135 bool ok;
1137 ok = ndr_syntax_id_equal(&ctx->abstract_syntax,
1138 &call->context->iface->syntax_id);
1139 if (!ok) {
1140 return dcesrv_fault_disconnect(call,
1141 DCERPC_NCA_S_PROTO_ERROR);
1144 if (ctx->num_transfer_syntaxes != 1) {
1145 return dcesrv_fault_disconnect(call,
1146 DCERPC_NCA_S_PROTO_ERROR);
1149 ok = ndr_syntax_id_equal(&ctx->transfer_syntaxes[0],
1150 &ndr_transfer_syntax_ndr);
1151 if (!ok) {
1152 return dcesrv_fault_disconnect(call,
1153 DCERPC_NCA_S_PROTO_ERROR);
1157 /* handle any authentication that is being requested */
1158 if (!auth_ok) {
1159 if (call->in_auth_info.auth_type !=
1160 call->conn->auth_state.auth_type)
1162 return dcesrv_fault_disconnect(call,
1163 DCERPC_FAULT_SEC_PKG_ERROR);
1165 return dcesrv_fault_disconnect(call, DCERPC_FAULT_ACCESS_DENIED);
1168 return dcesrv_alter_resp(call,
1169 DCERPC_BIND_ACK_RESULT_ACCEPTANCE,
1170 DCERPC_BIND_ACK_REASON_NOT_SPECIFIED);
1174 possibly save the call for inspection with ndrdump
1176 static void dcesrv_save_call(struct dcesrv_call_state *call, const char *why)
1178 #ifdef DEVELOPER
1179 char *fname;
1180 const char *dump_dir;
1181 dump_dir = lpcfg_parm_string(call->conn->dce_ctx->lp_ctx, NULL, "dcesrv", "stubs directory");
1182 if (!dump_dir) {
1183 return;
1185 fname = talloc_asprintf(call, "%s/RPC-%s-%u-%s.dat",
1186 dump_dir,
1187 call->context->iface->name,
1188 call->pkt.u.request.opnum,
1189 why);
1190 if (file_save(fname, call->pkt.u.request.stub_and_verifier.data, call->pkt.u.request.stub_and_verifier.length)) {
1191 DEBUG(0,("RPC SAVED %s\n", fname));
1193 talloc_free(fname);
1194 #endif
1197 static NTSTATUS dcesrv_check_verification_trailer(struct dcesrv_call_state *call)
1199 TALLOC_CTX *frame = talloc_stackframe();
1200 const uint32_t bitmask1 = call->conn->auth_state.client_hdr_signing ?
1201 DCERPC_SEC_VT_CLIENT_SUPPORTS_HEADER_SIGNING : 0;
1202 const struct dcerpc_sec_vt_pcontext pcontext = {
1203 .abstract_syntax = call->context->iface->syntax_id,
1204 .transfer_syntax = ndr_transfer_syntax_ndr,
1206 const struct dcerpc_sec_vt_header2 header2 =
1207 dcerpc_sec_vt_header2_from_ncacn_packet(&call->pkt);
1208 enum ndr_err_code ndr_err;
1209 struct dcerpc_sec_verification_trailer *vt = NULL;
1210 NTSTATUS status = NT_STATUS_OK;
1211 bool ok;
1213 SMB_ASSERT(call->pkt.ptype == DCERPC_PKT_REQUEST);
1215 ndr_err = ndr_pop_dcerpc_sec_verification_trailer(call->ndr_pull,
1216 frame, &vt);
1217 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
1218 status = ndr_map_error2ntstatus(ndr_err);
1219 goto done;
1222 ok = dcerpc_sec_verification_trailer_check(vt, &bitmask1,
1223 &pcontext, &header2);
1224 if (!ok) {
1225 status = NT_STATUS_ACCESS_DENIED;
1226 goto done;
1228 done:
1229 TALLOC_FREE(frame);
1230 return status;
1234 handle a dcerpc request packet
1236 static NTSTATUS dcesrv_request(struct dcesrv_call_state *call)
1238 const struct dcesrv_endpoint *endpoint = call->conn->endpoint;
1239 enum dcerpc_transport_t transport =
1240 dcerpc_binding_get_transport(endpoint->ep_description);
1241 struct ndr_pull *pull;
1242 NTSTATUS status;
1243 struct dcesrv_connection_context *context;
1245 if (!call->conn->allow_request) {
1246 return dcesrv_fault_disconnect(call, DCERPC_NCA_S_PROTO_ERROR);
1249 /* if authenticated, and the mech we use can't do async replies, don't use them... */
1250 if (call->conn->auth_state.gensec_security &&
1251 !gensec_have_feature(call->conn->auth_state.gensec_security, GENSEC_FEATURE_ASYNC_REPLIES)) {
1252 call->state_flags &= ~DCESRV_CALL_STATE_FLAG_MAY_ASYNC;
1255 context = dcesrv_find_context(call->conn, call->pkt.u.request.context_id);
1256 if (context == NULL) {
1257 return dcesrv_fault(call, DCERPC_FAULT_UNK_IF);
1260 switch (call->conn->auth_state.auth_level) {
1261 case DCERPC_AUTH_LEVEL_NONE:
1262 case DCERPC_AUTH_LEVEL_INTEGRITY:
1263 case DCERPC_AUTH_LEVEL_PRIVACY:
1264 break;
1265 default:
1266 if (!context->allow_connect) {
1267 char *addr;
1269 addr = tsocket_address_string(call->conn->remote_address,
1270 call);
1272 DEBUG(2, ("%s: restrict auth_level_connect access "
1273 "to [%s] with auth[type=0x%x,level=0x%x] "
1274 "on [%s] from [%s]\n",
1275 __func__, context->iface->name,
1276 call->conn->auth_state.auth_type,
1277 call->conn->auth_state.auth_level,
1278 derpc_transport_string_by_transport(transport),
1279 addr));
1280 return dcesrv_fault(call, DCERPC_FAULT_ACCESS_DENIED);
1282 break;
1285 if (call->conn->auth_state.auth_level < context->min_auth_level) {
1286 char *addr;
1288 addr = tsocket_address_string(call->conn->remote_address, call);
1290 DEBUG(2, ("%s: restrict access by min_auth_level[0x%x] "
1291 "to [%s] with auth[type=0x%x,level=0x%x] "
1292 "on [%s] from [%s]\n",
1293 __func__,
1294 context->min_auth_level,
1295 context->iface->name,
1296 call->conn->auth_state.auth_type,
1297 call->conn->auth_state.auth_level,
1298 derpc_transport_string_by_transport(transport),
1299 addr));
1300 return dcesrv_fault(call, DCERPC_FAULT_ACCESS_DENIED);
1303 pull = ndr_pull_init_blob(&call->pkt.u.request.stub_and_verifier, call);
1304 NT_STATUS_HAVE_NO_MEMORY(pull);
1306 pull->flags |= LIBNDR_FLAG_REF_ALLOC;
1308 call->context = context;
1309 call->ndr_pull = pull;
1311 if (!(call->pkt.drep[0] & DCERPC_DREP_LE)) {
1312 pull->flags |= LIBNDR_FLAG_BIGENDIAN;
1315 status = dcesrv_check_verification_trailer(call);
1316 if (!NT_STATUS_IS_OK(status)) {
1317 uint32_t faultcode = DCERPC_FAULT_OTHER;
1318 if (NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
1319 faultcode = DCERPC_FAULT_ACCESS_DENIED;
1321 DEBUG(10, ("dcesrv_check_verification_trailer failed: %s\n",
1322 nt_errstr(status)));
1323 return dcesrv_fault(call, faultcode);
1326 /* unravel the NDR for the packet */
1327 status = context->iface->ndr_pull(call, call, pull, &call->r);
1328 if (!NT_STATUS_IS_OK(status)) {
1329 if (call->fault_code == DCERPC_FAULT_OP_RNG_ERROR) {
1330 /* we got an unknown call */
1331 DEBUG(3,(__location__ ": Unknown RPC call %u on %s\n",
1332 call->pkt.u.request.opnum, context->iface->name));
1333 dcesrv_save_call(call, "unknown");
1334 } else {
1335 dcesrv_save_call(call, "pullfail");
1337 return dcesrv_fault(call, call->fault_code);
1340 if (pull->offset != pull->data_size) {
1341 dcesrv_save_call(call, "extrabytes");
1342 DEBUG(3,("Warning: %d extra bytes in incoming RPC request\n",
1343 pull->data_size - pull->offset));
1346 /* call the dispatch function */
1347 status = context->iface->dispatch(call, call, call->r);
1348 if (!NT_STATUS_IS_OK(status)) {
1349 DEBUG(5,("dcerpc fault in call %s:%02x - %s\n",
1350 context->iface->name,
1351 call->pkt.u.request.opnum,
1352 dcerpc_errstr(pull, call->fault_code)));
1353 return dcesrv_fault(call, call->fault_code);
1356 /* add the call to the pending list */
1357 dcesrv_call_set_list(call, DCESRV_LIST_PENDING_CALL_LIST);
1359 if (call->state_flags & DCESRV_CALL_STATE_FLAG_ASYNC) {
1360 return NT_STATUS_OK;
1363 return dcesrv_reply(call);
1368 remove the call from the right list when freed
1370 static int dcesrv_call_dequeue(struct dcesrv_call_state *call)
1372 dcesrv_call_set_list(call, DCESRV_LIST_NONE);
1373 return 0;
1376 _PUBLIC_ const struct tsocket_address *dcesrv_connection_get_local_address(struct dcesrv_connection *conn)
1378 return conn->local_address;
1381 _PUBLIC_ const struct tsocket_address *dcesrv_connection_get_remote_address(struct dcesrv_connection *conn)
1383 return conn->remote_address;
1387 process some input to a dcerpc endpoint server.
1389 static NTSTATUS dcesrv_process_ncacn_packet(struct dcesrv_connection *dce_conn,
1390 struct ncacn_packet *pkt,
1391 DATA_BLOB blob)
1393 NTSTATUS status;
1394 struct dcesrv_call_state *call;
1395 struct dcesrv_call_state *existing = NULL;
1397 call = talloc_zero(dce_conn, struct dcesrv_call_state);
1398 if (!call) {
1399 data_blob_free(&blob);
1400 talloc_free(pkt);
1401 return NT_STATUS_NO_MEMORY;
1403 call->conn = dce_conn;
1404 call->event_ctx = dce_conn->event_ctx;
1405 call->msg_ctx = dce_conn->msg_ctx;
1406 call->state_flags = call->conn->state_flags;
1407 call->time = timeval_current();
1408 call->list = DCESRV_LIST_NONE;
1410 talloc_steal(call, pkt);
1411 talloc_steal(call, blob.data);
1412 call->pkt = *pkt;
1414 talloc_set_destructor(call, dcesrv_call_dequeue);
1416 if (call->conn->allow_bind) {
1418 * Only one bind is possible per connection
1420 call->conn->allow_bind = false;
1421 return dcesrv_bind(call);
1424 /* we have to check the signing here, before combining the
1425 pdus */
1426 if (call->pkt.ptype == DCERPC_PKT_REQUEST) {
1427 if (!call->conn->allow_request) {
1428 return dcesrv_fault_disconnect(call,
1429 DCERPC_NCA_S_PROTO_ERROR);
1432 status = dcerpc_verify_ncacn_packet_header(&call->pkt,
1433 DCERPC_PKT_REQUEST,
1434 call->pkt.u.request.stub_and_verifier.length,
1435 0, /* required_flags */
1436 DCERPC_PFC_FLAG_FIRST |
1437 DCERPC_PFC_FLAG_LAST |
1438 DCERPC_PFC_FLAG_PENDING_CANCEL |
1439 0x08 | /* this is not defined, but should be ignored */
1440 DCERPC_PFC_FLAG_CONC_MPX |
1441 DCERPC_PFC_FLAG_DID_NOT_EXECUTE |
1442 DCERPC_PFC_FLAG_MAYBE |
1443 DCERPC_PFC_FLAG_OBJECT_UUID);
1444 if (!NT_STATUS_IS_OK(status)) {
1445 return dcesrv_fault_disconnect(call,
1446 DCERPC_NCA_S_PROTO_ERROR);
1449 if (call->pkt.frag_length > DCERPC_FRAG_MAX_SIZE) {
1451 * We don't use dcesrv_fault_disconnect()
1452 * here, because we don't want to set
1453 * DCERPC_PFC_FLAG_DID_NOT_EXECUTE
1455 * Note that we don't check against the negotiated
1456 * max_recv_frag, but a hard coded value.
1458 dcesrv_call_disconnect_after(call,
1459 "dcesrv_auth_request - frag_length too large");
1460 return dcesrv_fault(call,
1461 DCERPC_NCA_S_PROTO_ERROR);
1464 if (call->pkt.pfc_flags & DCERPC_PFC_FLAG_FIRST) {
1465 /* only one request is possible in the fragmented list */
1466 if (dce_conn->incoming_fragmented_call_list != NULL) {
1467 TALLOC_FREE(call);
1468 call = dce_conn->incoming_fragmented_call_list;
1469 dcesrv_call_disconnect_after(call,
1470 "dcesrv_auth_request - "
1471 "existing fragmented call");
1472 return dcesrv_fault(call,
1473 DCERPC_NCA_S_PROTO_ERROR);
1475 if (call->pkt.pfc_flags & DCERPC_PFC_FLAG_PENDING_CANCEL) {
1476 return dcesrv_fault_disconnect(call,
1477 DCERPC_FAULT_NO_CALL_ACTIVE);
1479 } else {
1480 const struct dcerpc_request *nr = &call->pkt.u.request;
1481 const struct dcerpc_request *er = NULL;
1482 int cmp;
1484 existing = dcesrv_find_fragmented_call(dce_conn,
1485 call->pkt.call_id);
1486 if (existing == NULL) {
1487 dcesrv_call_disconnect_after(call,
1488 "dcesrv_auth_request - "
1489 "no existing fragmented call");
1490 return dcesrv_fault(call,
1491 DCERPC_NCA_S_PROTO_ERROR);
1493 er = &existing->pkt.u.request;
1495 if (call->pkt.ptype != existing->pkt.ptype) {
1496 /* trying to play silly buggers are we? */
1497 return dcesrv_fault_disconnect(existing,
1498 DCERPC_NCA_S_PROTO_ERROR);
1500 cmp = memcmp(call->pkt.drep, existing->pkt.drep,
1501 sizeof(pkt->drep));
1502 if (cmp != 0) {
1503 return dcesrv_fault_disconnect(existing,
1504 DCERPC_NCA_S_PROTO_ERROR);
1506 if (nr->context_id != er->context_id) {
1507 return dcesrv_fault_disconnect(existing,
1508 DCERPC_NCA_S_PROTO_ERROR);
1510 if (nr->opnum != er->opnum) {
1511 return dcesrv_fault_disconnect(existing,
1512 DCERPC_NCA_S_PROTO_ERROR);
1516 if (!dcesrv_auth_request(call, &blob)) {
1518 * We don't use dcesrv_fault_disconnect()
1519 * here, because we don't want to set
1520 * DCERPC_PFC_FLAG_DID_NOT_EXECUTE
1522 dcesrv_call_disconnect_after(call,
1523 "dcesrv_auth_request - failed");
1524 return dcesrv_fault(call, DCERPC_FAULT_ACCESS_DENIED);
1528 /* see if this is a continued packet */
1529 if (existing != NULL) {
1530 struct dcerpc_request *er = &existing->pkt.u.request;
1531 const struct dcerpc_request *nr = &call->pkt.u.request;
1532 size_t available;
1533 size_t alloc_size;
1534 size_t alloc_hint;
1537 * Up to 4 MByte are allowed by all fragments
1539 available = dce_conn->max_total_request_size;
1540 if (er->stub_and_verifier.length > available) {
1541 dcesrv_call_disconnect_after(existing,
1542 "dcesrv_auth_request - existing payload too large");
1543 return dcesrv_fault(existing, DCERPC_FAULT_ACCESS_DENIED);
1545 available -= er->stub_and_verifier.length;
1546 if (nr->alloc_hint > available) {
1547 dcesrv_call_disconnect_after(existing,
1548 "dcesrv_auth_request - alloc hint too large");
1549 return dcesrv_fault(existing, DCERPC_FAULT_ACCESS_DENIED);
1551 if (nr->stub_and_verifier.length > available) {
1552 dcesrv_call_disconnect_after(existing,
1553 "dcesrv_auth_request - new payload too large");
1554 return dcesrv_fault(existing, DCERPC_FAULT_ACCESS_DENIED);
1556 alloc_hint = er->stub_and_verifier.length + nr->alloc_hint;
1557 /* allocate at least 1 byte */
1558 alloc_hint = MAX(alloc_hint, 1);
1559 alloc_size = er->stub_and_verifier.length +
1560 nr->stub_and_verifier.length;
1561 alloc_size = MAX(alloc_size, alloc_hint);
1563 er->stub_and_verifier.data =
1564 talloc_realloc(existing,
1565 er->stub_and_verifier.data,
1566 uint8_t, alloc_size);
1567 if (er->stub_and_verifier.data == NULL) {
1568 TALLOC_FREE(call);
1569 return dcesrv_fault_with_flags(existing,
1570 DCERPC_FAULT_OUT_OF_RESOURCES,
1571 DCERPC_PFC_FLAG_DID_NOT_EXECUTE);
1573 memcpy(er->stub_and_verifier.data +
1574 er->stub_and_verifier.length,
1575 nr->stub_and_verifier.data,
1576 nr->stub_and_verifier.length);
1577 er->stub_and_verifier.length += nr->stub_and_verifier.length;
1579 existing->pkt.pfc_flags |= (call->pkt.pfc_flags & DCERPC_PFC_FLAG_LAST);
1581 TALLOC_FREE(call);
1582 call = existing;
1585 /* this may not be the last pdu in the chain - if its isn't then
1586 just put it on the incoming_fragmented_call_list and wait for the rest */
1587 if (call->pkt.ptype == DCERPC_PKT_REQUEST &&
1588 !(call->pkt.pfc_flags & DCERPC_PFC_FLAG_LAST)) {
1590 * Up to 4 MByte are allowed by all fragments
1592 if (call->pkt.u.request.alloc_hint > dce_conn->max_total_request_size) {
1593 dcesrv_call_disconnect_after(call,
1594 "dcesrv_auth_request - initial alloc hint too large");
1595 return dcesrv_fault(call, DCERPC_FAULT_ACCESS_DENIED);
1597 dcesrv_call_set_list(call, DCESRV_LIST_FRAGMENTED_CALL_LIST);
1598 return NT_STATUS_OK;
1601 /* This removes any fragments we may have had stashed away */
1602 dcesrv_call_set_list(call, DCESRV_LIST_NONE);
1604 switch (call->pkt.ptype) {
1605 case DCERPC_PKT_BIND:
1606 status = dcesrv_bind_nak(call,
1607 DCERPC_BIND_NAK_REASON_NOT_SPECIFIED);
1608 break;
1609 case DCERPC_PKT_AUTH3:
1610 status = dcesrv_auth3(call);
1611 break;
1612 case DCERPC_PKT_ALTER:
1613 status = dcesrv_alter(call);
1614 break;
1615 case DCERPC_PKT_REQUEST:
1616 status = dcesrv_request(call);
1617 break;
1618 default:
1619 status = dcesrv_fault_disconnect(call, DCERPC_NCA_S_PROTO_ERROR);
1620 break;
1623 /* if we are going to be sending a reply then add
1624 it to the list of pending calls. We add it to the end to keep the call
1625 list in the order we will answer */
1626 if (!NT_STATUS_IS_OK(status)) {
1627 talloc_free(call);
1630 return status;
1633 _PUBLIC_ NTSTATUS dcesrv_init_context(TALLOC_CTX *mem_ctx,
1634 struct loadparm_context *lp_ctx,
1635 const char **endpoint_servers, struct dcesrv_context **_dce_ctx)
1637 NTSTATUS status;
1638 struct dcesrv_context *dce_ctx;
1639 int i;
1641 if (!endpoint_servers) {
1642 DEBUG(0,("dcesrv_init_context: no endpoint servers configured\n"));
1643 return NT_STATUS_INTERNAL_ERROR;
1646 dce_ctx = talloc_zero(mem_ctx, struct dcesrv_context);
1647 NT_STATUS_HAVE_NO_MEMORY(dce_ctx);
1649 if (uid_wrapper_enabled()) {
1650 setenv("UID_WRAPPER_MYUID", "1", 1);
1652 dce_ctx->initial_euid = geteuid();
1653 if (uid_wrapper_enabled()) {
1654 unsetenv("UID_WRAPPER_MYUID");
1657 dce_ctx->endpoint_list = NULL;
1658 dce_ctx->lp_ctx = lp_ctx;
1659 dce_ctx->assoc_groups_idr = idr_init(dce_ctx);
1660 NT_STATUS_HAVE_NO_MEMORY(dce_ctx->assoc_groups_idr);
1661 dce_ctx->broken_connections = NULL;
1663 for (i=0;endpoint_servers[i];i++) {
1664 const struct dcesrv_endpoint_server *ep_server;
1666 ep_server = dcesrv_ep_server_byname(endpoint_servers[i]);
1667 if (!ep_server) {
1668 DEBUG(0,("dcesrv_init_context: failed to find endpoint server = '%s'\n", endpoint_servers[i]));
1669 return NT_STATUS_INTERNAL_ERROR;
1672 status = ep_server->init_server(dce_ctx, ep_server);
1673 if (!NT_STATUS_IS_OK(status)) {
1674 DEBUG(0,("dcesrv_init_context: failed to init endpoint server = '%s': %s\n", endpoint_servers[i],
1675 nt_errstr(status)));
1676 return status;
1680 *_dce_ctx = dce_ctx;
1681 return NT_STATUS_OK;
1684 /* the list of currently registered DCERPC endpoint servers.
1686 static struct ep_server {
1687 struct dcesrv_endpoint_server *ep_server;
1688 } *ep_servers = NULL;
1689 static int num_ep_servers;
1692 register a DCERPC endpoint server.
1694 The 'name' can be later used by other backends to find the operations
1695 structure for this backend.
1697 The 'type' is used to specify whether this is for a disk, printer or IPC$ share
1699 _PUBLIC_ NTSTATUS dcerpc_register_ep_server(const void *_ep_server)
1701 const struct dcesrv_endpoint_server *ep_server = _ep_server;
1703 if (dcesrv_ep_server_byname(ep_server->name) != NULL) {
1704 /* its already registered! */
1705 DEBUG(0,("DCERPC endpoint server '%s' already registered\n",
1706 ep_server->name));
1707 return NT_STATUS_OBJECT_NAME_COLLISION;
1710 ep_servers = realloc_p(ep_servers, struct ep_server, num_ep_servers+1);
1711 if (!ep_servers) {
1712 smb_panic("out of memory in dcerpc_register");
1715 ep_servers[num_ep_servers].ep_server = smb_xmemdup(ep_server, sizeof(*ep_server));
1716 ep_servers[num_ep_servers].ep_server->name = smb_xstrdup(ep_server->name);
1718 num_ep_servers++;
1720 DEBUG(3,("DCERPC endpoint server '%s' registered\n",
1721 ep_server->name));
1723 return NT_STATUS_OK;
1727 return the operations structure for a named backend of the specified type
1729 const struct dcesrv_endpoint_server *dcesrv_ep_server_byname(const char *name)
1731 int i;
1733 for (i=0;i<num_ep_servers;i++) {
1734 if (strcmp(ep_servers[i].ep_server->name, name) == 0) {
1735 return ep_servers[i].ep_server;
1739 return NULL;
1742 void dcerpc_server_init(struct loadparm_context *lp_ctx)
1744 static bool initialized;
1745 #define _MODULE_PROTO(init) extern NTSTATUS init(void);
1746 STATIC_dcerpc_server_MODULES_PROTO;
1747 init_module_fn static_init[] = { STATIC_dcerpc_server_MODULES };
1748 init_module_fn *shared_init;
1750 if (initialized) {
1751 return;
1753 initialized = true;
1755 shared_init = load_samba_modules(NULL, "dcerpc_server");
1757 run_init_functions(static_init);
1758 run_init_functions(shared_init);
1760 talloc_free(shared_init);
1764 return the DCERPC module version, and the size of some critical types
1765 This can be used by endpoint server modules to either detect compilation errors, or provide
1766 multiple implementations for different smbd compilation options in one module
1768 const struct dcesrv_critical_sizes *dcerpc_module_version(void)
1770 static const struct dcesrv_critical_sizes critical_sizes = {
1771 DCERPC_MODULE_VERSION,
1772 sizeof(struct dcesrv_context),
1773 sizeof(struct dcesrv_endpoint),
1774 sizeof(struct dcesrv_endpoint_server),
1775 sizeof(struct dcesrv_interface),
1776 sizeof(struct dcesrv_if_list),
1777 sizeof(struct dcesrv_connection),
1778 sizeof(struct dcesrv_call_state),
1779 sizeof(struct dcesrv_auth),
1780 sizeof(struct dcesrv_handle)
1783 return &critical_sizes;
1786 static void dcesrv_terminate_connection(struct dcesrv_connection *dce_conn, const char *reason)
1788 struct dcesrv_context *dce_ctx = dce_conn->dce_ctx;
1789 struct stream_connection *srv_conn;
1790 srv_conn = talloc_get_type(dce_conn->transport.private_data,
1791 struct stream_connection);
1793 dce_conn->allow_bind = false;
1794 dce_conn->allow_auth3 = false;
1795 dce_conn->allow_alter = false;
1796 dce_conn->allow_request = false;
1798 if (dce_conn->pending_call_list == NULL) {
1799 char *full_reason = talloc_asprintf(dce_conn, "dcesrv: %s", reason);
1801 DLIST_REMOVE(dce_ctx->broken_connections, dce_conn);
1802 stream_terminate_connection(srv_conn, full_reason ? full_reason : reason);
1803 return;
1806 if (dce_conn->terminate != NULL) {
1807 return;
1810 DEBUG(3,("dcesrv: terminating connection due to '%s' defered due to pending calls\n",
1811 reason));
1812 dce_conn->terminate = talloc_strdup(dce_conn, reason);
1813 if (dce_conn->terminate == NULL) {
1814 dce_conn->terminate = "dcesrv: defered terminating connection - no memory";
1816 DLIST_ADD_END(dce_ctx->broken_connections, dce_conn);
1819 static void dcesrv_cleanup_broken_connections(struct dcesrv_context *dce_ctx)
1821 struct dcesrv_connection *cur, *next;
1823 next = dce_ctx->broken_connections;
1824 while (next != NULL) {
1825 cur = next;
1826 next = cur->next;
1828 if (cur->state_flags & DCESRV_CALL_STATE_FLAG_PROCESS_PENDING_CALL) {
1829 struct dcesrv_connection_context *context_cur, *context_next;
1831 context_next = cur->contexts;
1832 while (context_next != NULL) {
1833 context_cur = context_next;
1834 context_next = context_cur->next;
1836 dcesrv_connection_context_destructor(context_cur);
1840 dcesrv_terminate_connection(cur, cur->terminate);
1844 /* We need this include to be able to compile on some plateforms
1845 * (ie. freebsd 7.2) as it seems that <sys/uio.h> is not included
1846 * correctly.
1847 * It has to be that deep because otherwise we have a conflict on
1848 * const struct dcesrv_interface declaration.
1849 * This is mostly due to socket_wrapper defining #define bind swrap_bind
1850 * which conflict with the bind used before.
1852 #include "system/network.h"
1854 struct dcesrv_sock_reply_state {
1855 struct dcesrv_connection *dce_conn;
1856 struct dcesrv_call_state *call;
1857 struct iovec iov;
1860 static void dcesrv_sock_reply_done(struct tevent_req *subreq);
1861 static void dcesrv_call_terminate_step1(struct tevent_req *subreq);
1863 static void dcesrv_sock_report_output_data(struct dcesrv_connection *dce_conn)
1865 struct dcesrv_call_state *call;
1867 call = dce_conn->call_list;
1868 if (!call || !call->replies) {
1869 return;
1872 while (call->replies) {
1873 struct data_blob_list_item *rep = call->replies;
1874 struct dcesrv_sock_reply_state *substate;
1875 struct tevent_req *subreq;
1877 substate = talloc_zero(call, struct dcesrv_sock_reply_state);
1878 if (!substate) {
1879 dcesrv_terminate_connection(dce_conn, "no memory");
1880 return;
1883 substate->dce_conn = dce_conn;
1884 substate->call = NULL;
1886 DLIST_REMOVE(call->replies, rep);
1888 if (call->replies == NULL && call->terminate_reason == NULL) {
1889 substate->call = call;
1892 substate->iov.iov_base = (void *) rep->blob.data;
1893 substate->iov.iov_len = rep->blob.length;
1895 subreq = tstream_writev_queue_send(substate,
1896 dce_conn->event_ctx,
1897 dce_conn->stream,
1898 dce_conn->send_queue,
1899 &substate->iov, 1);
1900 if (!subreq) {
1901 dcesrv_terminate_connection(dce_conn, "no memory");
1902 return;
1904 tevent_req_set_callback(subreq, dcesrv_sock_reply_done,
1905 substate);
1908 if (call->terminate_reason != NULL) {
1909 struct tevent_req *subreq;
1911 subreq = tevent_queue_wait_send(call,
1912 dce_conn->event_ctx,
1913 dce_conn->send_queue);
1914 if (!subreq) {
1915 dcesrv_terminate_connection(dce_conn, __location__);
1916 return;
1918 tevent_req_set_callback(subreq, dcesrv_call_terminate_step1,
1919 call);
1922 DLIST_REMOVE(call->conn->call_list, call);
1923 call->list = DCESRV_LIST_NONE;
1926 static void dcesrv_sock_reply_done(struct tevent_req *subreq)
1928 struct dcesrv_sock_reply_state *substate = tevent_req_callback_data(subreq,
1929 struct dcesrv_sock_reply_state);
1930 int ret;
1931 int sys_errno;
1932 NTSTATUS status;
1933 struct dcesrv_call_state *call = substate->call;
1935 ret = tstream_writev_queue_recv(subreq, &sys_errno);
1936 TALLOC_FREE(subreq);
1937 if (ret == -1) {
1938 status = map_nt_error_from_unix_common(sys_errno);
1939 dcesrv_terminate_connection(substate->dce_conn, nt_errstr(status));
1940 return;
1943 talloc_free(substate);
1944 if (call) {
1945 talloc_free(call);
1949 static void dcesrv_call_terminate_step2(struct tevent_req *subreq);
1951 static void dcesrv_call_terminate_step1(struct tevent_req *subreq)
1953 struct dcesrv_call_state *call = tevent_req_callback_data(subreq,
1954 struct dcesrv_call_state);
1955 bool ok;
1956 struct timeval tv;
1958 /* make sure we stop send queue before removing subreq */
1959 tevent_queue_stop(call->conn->send_queue);
1961 ok = tevent_queue_wait_recv(subreq);
1962 TALLOC_FREE(subreq);
1963 if (!ok) {
1964 dcesrv_terminate_connection(call->conn, __location__);
1965 return;
1968 /* disconnect after 200 usecs */
1969 tv = timeval_current_ofs_usec(200);
1970 subreq = tevent_wakeup_send(call, call->conn->event_ctx, tv);
1971 if (subreq == NULL) {
1972 dcesrv_terminate_connection(call->conn, __location__);
1973 return;
1975 tevent_req_set_callback(subreq, dcesrv_call_terminate_step2,
1976 call);
1979 static void dcesrv_call_terminate_step2(struct tevent_req *subreq)
1981 struct dcesrv_call_state *call = tevent_req_callback_data(subreq,
1982 struct dcesrv_call_state);
1983 bool ok;
1985 ok = tevent_wakeup_recv(subreq);
1986 TALLOC_FREE(subreq);
1987 if (!ok) {
1988 dcesrv_terminate_connection(call->conn, __location__);
1989 return;
1992 dcesrv_terminate_connection(call->conn, call->terminate_reason);
1995 struct dcesrv_socket_context {
1996 const struct dcesrv_endpoint *endpoint;
1997 struct dcesrv_context *dcesrv_ctx;
2001 static void dcesrv_read_fragment_done(struct tevent_req *subreq);
2003 static void dcesrv_sock_accept(struct stream_connection *srv_conn)
2005 NTSTATUS status;
2006 struct dcesrv_socket_context *dcesrv_sock =
2007 talloc_get_type(srv_conn->private_data, struct dcesrv_socket_context);
2008 enum dcerpc_transport_t transport =
2009 dcerpc_binding_get_transport(dcesrv_sock->endpoint->ep_description);
2010 struct dcesrv_connection *dcesrv_conn = NULL;
2011 int ret;
2012 struct tevent_req *subreq;
2013 struct loadparm_context *lp_ctx = dcesrv_sock->dcesrv_ctx->lp_ctx;
2015 dcesrv_cleanup_broken_connections(dcesrv_sock->dcesrv_ctx);
2017 if (!srv_conn->session_info) {
2018 status = auth_anonymous_session_info(srv_conn,
2019 lp_ctx,
2020 &srv_conn->session_info);
2021 if (!NT_STATUS_IS_OK(status)) {
2022 DEBUG(0,("dcesrv_sock_accept: auth_anonymous_session_info failed: %s\n",
2023 nt_errstr(status)));
2024 stream_terminate_connection(srv_conn, nt_errstr(status));
2025 return;
2029 status = dcesrv_endpoint_connect(dcesrv_sock->dcesrv_ctx,
2030 srv_conn,
2031 dcesrv_sock->endpoint,
2032 srv_conn->session_info,
2033 srv_conn->event.ctx,
2034 srv_conn->msg_ctx,
2035 srv_conn->server_id,
2036 DCESRV_CALL_STATE_FLAG_MAY_ASYNC,
2037 &dcesrv_conn);
2038 if (!NT_STATUS_IS_OK(status)) {
2039 DEBUG(0,("dcesrv_sock_accept: dcesrv_endpoint_connect failed: %s\n",
2040 nt_errstr(status)));
2041 stream_terminate_connection(srv_conn, nt_errstr(status));
2042 return;
2045 dcesrv_conn->transport.private_data = srv_conn;
2046 dcesrv_conn->transport.report_output_data = dcesrv_sock_report_output_data;
2048 TALLOC_FREE(srv_conn->event.fde);
2050 dcesrv_conn->send_queue = tevent_queue_create(dcesrv_conn, "dcesrv send queue");
2051 if (!dcesrv_conn->send_queue) {
2052 status = NT_STATUS_NO_MEMORY;
2053 DEBUG(0,("dcesrv_sock_accept: tevent_queue_create(%s)\n",
2054 nt_errstr(status)));
2055 stream_terminate_connection(srv_conn, nt_errstr(status));
2056 return;
2059 if (transport == NCACN_NP) {
2060 dcesrv_conn->auth_state.session_key = dcesrv_inherited_session_key;
2061 dcesrv_conn->stream = talloc_move(dcesrv_conn,
2062 &srv_conn->tstream);
2063 } else {
2064 ret = tstream_bsd_existing_socket(dcesrv_conn,
2065 socket_get_fd(srv_conn->socket),
2066 &dcesrv_conn->stream);
2067 if (ret == -1) {
2068 status = map_nt_error_from_unix_common(errno);
2069 DEBUG(0, ("dcesrv_sock_accept: "
2070 "failed to setup tstream: %s\n",
2071 nt_errstr(status)));
2072 stream_terminate_connection(srv_conn, nt_errstr(status));
2073 return;
2075 socket_set_flags(srv_conn->socket, SOCKET_FLAG_NOCLOSE);
2078 dcesrv_conn->local_address = srv_conn->local_address;
2079 dcesrv_conn->remote_address = srv_conn->remote_address;
2081 if (transport == NCALRPC) {
2082 uid_t uid;
2083 gid_t gid;
2084 int sock_fd;
2086 sock_fd = socket_get_fd(srv_conn->socket);
2087 if (sock_fd == -1) {
2088 stream_terminate_connection(
2089 srv_conn, "socket_get_fd failed\n");
2090 return;
2093 ret = getpeereid(sock_fd, &uid, &gid);
2094 if (ret == -1) {
2095 status = map_nt_error_from_unix_common(errno);
2096 DEBUG(0, ("dcesrv_sock_accept: "
2097 "getpeereid() failed for NCALRPC: %s\n",
2098 nt_errstr(status)));
2099 stream_terminate_connection(srv_conn, nt_errstr(status));
2100 return;
2102 if (uid == dcesrv_conn->dce_ctx->initial_euid) {
2103 struct tsocket_address *r = NULL;
2105 ret = tsocket_address_unix_from_path(dcesrv_conn,
2106 "/root/ncalrpc_as_system",
2107 &r);
2108 if (ret == -1) {
2109 status = map_nt_error_from_unix_common(errno);
2110 DEBUG(0, ("dcesrv_sock_accept: "
2111 "tsocket_address_unix_from_path() failed for NCALRPC: %s\n",
2112 nt_errstr(status)));
2113 stream_terminate_connection(srv_conn, nt_errstr(status));
2114 return;
2116 dcesrv_conn->remote_address = r;
2120 srv_conn->private_data = dcesrv_conn;
2122 irpc_add_name(srv_conn->msg_ctx, "rpc_server");
2124 subreq = dcerpc_read_ncacn_packet_send(dcesrv_conn,
2125 dcesrv_conn->event_ctx,
2126 dcesrv_conn->stream);
2127 if (!subreq) {
2128 status = NT_STATUS_NO_MEMORY;
2129 DEBUG(0,("dcesrv_sock_accept: dcerpc_read_fragment_buffer_send(%s)\n",
2130 nt_errstr(status)));
2131 stream_terminate_connection(srv_conn, nt_errstr(status));
2132 return;
2134 tevent_req_set_callback(subreq, dcesrv_read_fragment_done, dcesrv_conn);
2136 return;
2139 static void dcesrv_read_fragment_done(struct tevent_req *subreq)
2141 struct dcesrv_connection *dce_conn = tevent_req_callback_data(subreq,
2142 struct dcesrv_connection);
2143 struct dcesrv_context *dce_ctx = dce_conn->dce_ctx;
2144 struct ncacn_packet *pkt;
2145 DATA_BLOB buffer;
2146 NTSTATUS status;
2148 if (dce_conn->terminate) {
2150 * if the current connection is broken
2151 * we need to clean it up before any other connection
2153 dcesrv_terminate_connection(dce_conn, dce_conn->terminate);
2154 dcesrv_cleanup_broken_connections(dce_ctx);
2155 return;
2158 dcesrv_cleanup_broken_connections(dce_ctx);
2160 status = dcerpc_read_ncacn_packet_recv(subreq, dce_conn,
2161 &pkt, &buffer);
2162 TALLOC_FREE(subreq);
2163 if (!NT_STATUS_IS_OK(status)) {
2164 dcesrv_terminate_connection(dce_conn, nt_errstr(status));
2165 return;
2168 status = dcesrv_process_ncacn_packet(dce_conn, pkt, buffer);
2169 if (!NT_STATUS_IS_OK(status)) {
2170 dcesrv_terminate_connection(dce_conn, nt_errstr(status));
2171 return;
2174 subreq = dcerpc_read_ncacn_packet_send(dce_conn,
2175 dce_conn->event_ctx,
2176 dce_conn->stream);
2177 if (!subreq) {
2178 status = NT_STATUS_NO_MEMORY;
2179 dcesrv_terminate_connection(dce_conn, nt_errstr(status));
2180 return;
2182 tevent_req_set_callback(subreq, dcesrv_read_fragment_done, dce_conn);
2185 static void dcesrv_sock_recv(struct stream_connection *conn, uint16_t flags)
2187 struct dcesrv_connection *dce_conn = talloc_get_type(conn->private_data,
2188 struct dcesrv_connection);
2189 dcesrv_terminate_connection(dce_conn, "dcesrv_sock_recv triggered");
2192 static void dcesrv_sock_send(struct stream_connection *conn, uint16_t flags)
2194 struct dcesrv_connection *dce_conn = talloc_get_type(conn->private_data,
2195 struct dcesrv_connection);
2196 dcesrv_terminate_connection(dce_conn, "dcesrv_sock_send triggered");
2200 static const struct stream_server_ops dcesrv_stream_ops = {
2201 .name = "rpc",
2202 .accept_connection = dcesrv_sock_accept,
2203 .recv_handler = dcesrv_sock_recv,
2204 .send_handler = dcesrv_sock_send,
2207 static NTSTATUS dcesrv_add_ep_unix(struct dcesrv_context *dce_ctx,
2208 struct loadparm_context *lp_ctx,
2209 struct dcesrv_endpoint *e,
2210 struct tevent_context *event_ctx, const struct model_ops *model_ops)
2212 struct dcesrv_socket_context *dcesrv_sock;
2213 uint16_t port = 1;
2214 NTSTATUS status;
2215 const char *endpoint;
2217 dcesrv_sock = talloc_zero(event_ctx, struct dcesrv_socket_context);
2218 NT_STATUS_HAVE_NO_MEMORY(dcesrv_sock);
2220 /* remember the endpoint of this socket */
2221 dcesrv_sock->endpoint = e;
2222 dcesrv_sock->dcesrv_ctx = talloc_reference(dcesrv_sock, dce_ctx);
2224 endpoint = dcerpc_binding_get_string_option(e->ep_description, "endpoint");
2226 status = stream_setup_socket(dcesrv_sock, event_ctx, lp_ctx,
2227 model_ops, &dcesrv_stream_ops,
2228 "unix", endpoint, &port,
2229 lpcfg_socket_options(lp_ctx),
2230 dcesrv_sock);
2231 if (!NT_STATUS_IS_OK(status)) {
2232 DEBUG(0,("service_setup_stream_socket(path=%s) failed - %s\n",
2233 endpoint, nt_errstr(status)));
2236 return status;
2239 static NTSTATUS dcesrv_add_ep_ncalrpc(struct dcesrv_context *dce_ctx,
2240 struct loadparm_context *lp_ctx,
2241 struct dcesrv_endpoint *e,
2242 struct tevent_context *event_ctx, const struct model_ops *model_ops)
2244 struct dcesrv_socket_context *dcesrv_sock;
2245 uint16_t port = 1;
2246 char *full_path;
2247 NTSTATUS status;
2248 const char *endpoint;
2250 endpoint = dcerpc_binding_get_string_option(e->ep_description, "endpoint");
2252 if (endpoint == NULL) {
2254 * No identifier specified: use DEFAULT.
2256 * TODO: DO NOT hardcode this value anywhere else. Rather, specify
2257 * no endpoint and let the epmapper worry about it.
2259 endpoint = "DEFAULT";
2260 status = dcerpc_binding_set_string_option(e->ep_description,
2261 "endpoint",
2262 endpoint);
2263 if (!NT_STATUS_IS_OK(status)) {
2264 DEBUG(0,("dcerpc_binding_set_string_option() failed - %s\n",
2265 nt_errstr(status)));
2266 return status;
2270 full_path = talloc_asprintf(dce_ctx, "%s/%s", lpcfg_ncalrpc_dir(lp_ctx),
2271 endpoint);
2273 dcesrv_sock = talloc_zero(event_ctx, struct dcesrv_socket_context);
2274 NT_STATUS_HAVE_NO_MEMORY(dcesrv_sock);
2276 /* remember the endpoint of this socket */
2277 dcesrv_sock->endpoint = e;
2278 dcesrv_sock->dcesrv_ctx = talloc_reference(dcesrv_sock, dce_ctx);
2280 status = stream_setup_socket(dcesrv_sock, event_ctx, lp_ctx,
2281 model_ops, &dcesrv_stream_ops,
2282 "unix", full_path, &port,
2283 lpcfg_socket_options(lp_ctx),
2284 dcesrv_sock);
2285 if (!NT_STATUS_IS_OK(status)) {
2286 DEBUG(0,("service_setup_stream_socket(identifier=%s,path=%s) failed - %s\n",
2287 endpoint, full_path, nt_errstr(status)));
2289 return status;
2292 static NTSTATUS dcesrv_add_ep_np(struct dcesrv_context *dce_ctx,
2293 struct loadparm_context *lp_ctx,
2294 struct dcesrv_endpoint *e,
2295 struct tevent_context *event_ctx, const struct model_ops *model_ops)
2297 struct dcesrv_socket_context *dcesrv_sock;
2298 NTSTATUS status;
2299 const char *endpoint;
2301 endpoint = dcerpc_binding_get_string_option(e->ep_description, "endpoint");
2302 if (endpoint == NULL) {
2303 DEBUG(0, ("Endpoint mandatory for named pipes\n"));
2304 return NT_STATUS_INVALID_PARAMETER;
2307 dcesrv_sock = talloc_zero(event_ctx, struct dcesrv_socket_context);
2308 NT_STATUS_HAVE_NO_MEMORY(dcesrv_sock);
2310 /* remember the endpoint of this socket */
2311 dcesrv_sock->endpoint = e;
2312 dcesrv_sock->dcesrv_ctx = talloc_reference(dcesrv_sock, dce_ctx);
2314 status = tstream_setup_named_pipe(dce_ctx, event_ctx, lp_ctx,
2315 model_ops, &dcesrv_stream_ops,
2316 endpoint,
2317 dcesrv_sock);
2318 if (!NT_STATUS_IS_OK(status)) {
2319 DEBUG(0,("stream_setup_named_pipe(pipe=%s) failed - %s\n",
2320 endpoint, nt_errstr(status)));
2321 return status;
2324 return NT_STATUS_OK;
2328 add a socket address to the list of events, one event per dcerpc endpoint
2330 static NTSTATUS add_socket_rpc_tcp_iface(struct dcesrv_context *dce_ctx, struct dcesrv_endpoint *e,
2331 struct tevent_context *event_ctx, const struct model_ops *model_ops,
2332 const char *address)
2334 struct dcesrv_socket_context *dcesrv_sock;
2335 uint16_t port = 0;
2336 NTSTATUS status;
2337 const char *endpoint;
2338 char port_str[6];
2340 endpoint = dcerpc_binding_get_string_option(e->ep_description, "endpoint");
2341 if (endpoint != NULL) {
2342 port = atoi(endpoint);
2345 dcesrv_sock = talloc_zero(event_ctx, struct dcesrv_socket_context);
2346 NT_STATUS_HAVE_NO_MEMORY(dcesrv_sock);
2348 /* remember the endpoint of this socket */
2349 dcesrv_sock->endpoint = e;
2350 dcesrv_sock->dcesrv_ctx = talloc_reference(dcesrv_sock, dce_ctx);
2352 status = stream_setup_socket(dcesrv_sock, event_ctx, dce_ctx->lp_ctx,
2353 model_ops, &dcesrv_stream_ops,
2354 "ip", address, &port,
2355 lpcfg_socket_options(dce_ctx->lp_ctx),
2356 dcesrv_sock);
2357 if (!NT_STATUS_IS_OK(status)) {
2358 DEBUG(0,("service_setup_stream_socket(address=%s,port=%u) failed - %s\n",
2359 address, port, nt_errstr(status)));
2360 return status;
2363 snprintf(port_str, sizeof(port_str), "%u", port);
2365 status = dcerpc_binding_set_string_option(e->ep_description,
2366 "endpoint", port_str);
2367 if (!NT_STATUS_IS_OK(status)) {
2368 DEBUG(0,("dcerpc_binding_set_string_option(endpoint, %s) failed - %s\n",
2369 port_str, nt_errstr(status)));
2370 return status;
2373 return NT_STATUS_OK;
2376 #include "lib/socket/netif.h" /* Included here to work around the fact that socket_wrapper redefines bind() */
2378 static NTSTATUS dcesrv_add_ep_tcp(struct dcesrv_context *dce_ctx,
2379 struct loadparm_context *lp_ctx,
2380 struct dcesrv_endpoint *e,
2381 struct tevent_context *event_ctx, const struct model_ops *model_ops)
2383 NTSTATUS status;
2385 /* Add TCP/IP sockets */
2386 if (lpcfg_interfaces(lp_ctx) && lpcfg_bind_interfaces_only(lp_ctx)) {
2387 int num_interfaces;
2388 int i;
2389 struct interface *ifaces;
2391 load_interface_list(dce_ctx, lp_ctx, &ifaces);
2393 num_interfaces = iface_list_count(ifaces);
2394 for(i = 0; i < num_interfaces; i++) {
2395 const char *address = iface_list_n_ip(ifaces, i);
2396 status = add_socket_rpc_tcp_iface(dce_ctx, e, event_ctx, model_ops, address);
2397 NT_STATUS_NOT_OK_RETURN(status);
2399 } else {
2400 char **wcard;
2401 int i;
2402 int num_binds = 0;
2403 wcard = iface_list_wildcard(dce_ctx);
2404 NT_STATUS_HAVE_NO_MEMORY(wcard);
2405 for (i=0; wcard[i]; i++) {
2406 status = add_socket_rpc_tcp_iface(dce_ctx, e, event_ctx, model_ops, wcard[i]);
2407 if (NT_STATUS_IS_OK(status)) {
2408 num_binds++;
2411 talloc_free(wcard);
2412 if (num_binds == 0) {
2413 return NT_STATUS_INVALID_PARAMETER_MIX;
2417 return NT_STATUS_OK;
2420 NTSTATUS dcesrv_add_ep(struct dcesrv_context *dce_ctx,
2421 struct loadparm_context *lp_ctx,
2422 struct dcesrv_endpoint *e,
2423 struct tevent_context *event_ctx,
2424 const struct model_ops *model_ops)
2426 enum dcerpc_transport_t transport =
2427 dcerpc_binding_get_transport(e->ep_description);
2429 switch (transport) {
2430 case NCACN_UNIX_STREAM:
2431 return dcesrv_add_ep_unix(dce_ctx, lp_ctx, e, event_ctx, model_ops);
2433 case NCALRPC:
2434 return dcesrv_add_ep_ncalrpc(dce_ctx, lp_ctx, e, event_ctx, model_ops);
2436 case NCACN_IP_TCP:
2437 return dcesrv_add_ep_tcp(dce_ctx, lp_ctx, e, event_ctx, model_ops);
2439 case NCACN_NP:
2440 return dcesrv_add_ep_np(dce_ctx, lp_ctx, e, event_ctx, model_ops);
2442 default:
2443 return NT_STATUS_NOT_SUPPORTED;
2449 * retrieve credentials from a dce_call
2451 _PUBLIC_ struct cli_credentials *dcesrv_call_credentials(struct dcesrv_call_state *dce_call)
2453 return dce_call->conn->auth_state.session_info->credentials;
2457 * returns true if this is an authenticated call
2459 _PUBLIC_ bool dcesrv_call_authenticated(struct dcesrv_call_state *dce_call)
2461 enum security_user_level level;
2462 level = security_session_user_level(dce_call->conn->auth_state.session_info, NULL);
2463 return level >= SECURITY_USER;
2467 * retrieve account_name for a dce_call
2469 _PUBLIC_ const char *dcesrv_call_account_name(struct dcesrv_call_state *dce_call)
2471 return dce_call->context->conn->auth_state.session_info->info->account_name;