gpo: Test certificate policy without NDES
[Samba.git] / librpc / rpc / dcesrv_core.c
blob09ea68122494211af1bf0c7c32d4a1444f28fa2f
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
8 Copyright (C) Samuel Cabrero <scabrero@samba.org> 2019
10 This program is free software; you can redistribute it and/or modify
11 it under the terms of the GNU General Public License as published by
12 the Free Software Foundation; either version 3 of the License, or
13 (at your option) any later version.
15 This program is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 GNU General Public License for more details.
20 You should have received a copy of the GNU General Public License
21 along with this program. If not, see <http://www.gnu.org/licenses/>.
24 #include "includes.h"
25 #include "librpc/rpc/dcesrv_core.h"
26 #include "librpc/rpc/dcesrv_core_proto.h"
27 #include "librpc/rpc/dcerpc_util.h"
28 #include "librpc/gen_ndr/auth.h"
29 #include "auth/gensec/gensec.h"
30 #include "lib/util/dlinklist.h"
31 #include "libcli/security/security.h"
32 #include "param/param.h"
33 #include "lib/tsocket/tsocket.h"
34 #include "librpc/gen_ndr/ndr_dcerpc.h"
35 #include "lib/util/tevent_ntstatus.h"
36 #include "system/network.h"
37 #include "lib/util/idtree_random.h"
38 #include "nsswitch/winbind_client.h"
40 /**
41 * @file
42 * @brief DCERPC server
45 #undef DBGC_CLASS
46 #define DBGC_CLASS DBGC_RPC_SRV
48 #undef strcasecmp
50 static NTSTATUS dcesrv_negotiate_contexts(struct dcesrv_call_state *call,
51 const struct dcerpc_bind *b,
52 struct dcerpc_ack_ctx *ack_ctx_list);
55 see if two endpoints match
57 static bool endpoints_match(const struct dcerpc_binding *ep1,
58 const struct dcerpc_binding *ep2)
60 enum dcerpc_transport_t t1;
61 enum dcerpc_transport_t t2;
62 const char *e1;
63 const char *e2;
65 t1 = dcerpc_binding_get_transport(ep1);
66 t2 = dcerpc_binding_get_transport(ep2);
68 e1 = dcerpc_binding_get_string_option(ep1, "endpoint");
69 e2 = dcerpc_binding_get_string_option(ep2, "endpoint");
71 if (t1 != t2) {
72 return false;
75 if (!e1 || !e2) {
76 return e1 == e2;
79 if (strcasecmp(e1, e2) != 0) {
80 return false;
83 return true;
87 find an endpoint in the dcesrv_context
89 _PUBLIC_ NTSTATUS dcesrv_find_endpoint(struct dcesrv_context *dce_ctx,
90 const struct dcerpc_binding *ep_description,
91 struct dcesrv_endpoint **_out)
93 struct dcesrv_endpoint *ep = NULL;
94 for (ep=dce_ctx->endpoint_list; ep; ep=ep->next) {
95 if (endpoints_match(ep->ep_description, ep_description)) {
96 *_out = ep;
97 return NT_STATUS_OK;
100 return NT_STATUS_NOT_FOUND;
104 find a registered context_id from a bind or alter_context
106 static struct dcesrv_connection_context *dcesrv_find_context(struct dcesrv_connection *conn,
107 uint16_t context_id)
109 struct dcesrv_connection_context *c;
110 for (c=conn->contexts;c;c=c->next) {
111 if (c->context_id == context_id) return c;
113 return NULL;
117 find the interface operations on any endpoint with this binding
119 static const struct dcesrv_interface *find_interface_by_binding(struct dcesrv_context *dce_ctx,
120 struct dcerpc_binding *binding,
121 const struct dcesrv_interface *iface)
123 struct dcesrv_endpoint *ep;
124 for (ep=dce_ctx->endpoint_list; ep; ep=ep->next) {
125 if (endpoints_match(ep->ep_description, binding)) {
126 const struct dcesrv_interface *ret = NULL;
128 ret = find_interface_by_syntax_id(
129 ep, &iface->syntax_id);
130 if (ret != NULL) {
131 return ret;
135 return NULL;
139 find the interface operations on an endpoint by uuid
141 _PUBLIC_ const struct dcesrv_interface *find_interface_by_syntax_id(
142 const struct dcesrv_endpoint *endpoint,
143 const struct ndr_syntax_id *interface)
145 struct dcesrv_if_list *ifl;
146 for (ifl=endpoint->interface_list; ifl; ifl=ifl->next) {
147 if (ndr_syntax_id_equal(&ifl->iface->syntax_id, interface)) {
148 return ifl->iface;
151 return NULL;
155 find the earlier parts of a fragmented call awaiting reassembly
157 static struct dcesrv_call_state *dcesrv_find_fragmented_call(struct dcesrv_connection *dce_conn, uint32_t call_id)
159 struct dcesrv_call_state *c;
160 for (c=dce_conn->incoming_fragmented_call_list;c;c=c->next) {
161 if (c->pkt.call_id == call_id) {
162 return c;
165 return NULL;
169 register an interface on an endpoint
171 An endpoint is one unix domain socket (for ncalrpc), one TCP port
172 (for ncacn_ip_tcp) or one (forwarded) named pipe (for ncacn_np).
174 Each endpoint can have many interfaces such as netlogon, lsa or
175 samr. Some have essentially the full set.
177 This is driven from the set of interfaces listed in each IDL file
178 via the PIDL generated *__op_init_server() functions.
180 _PUBLIC_ NTSTATUS dcesrv_interface_register(struct dcesrv_context *dce_ctx,
181 const char *ep_name,
182 const char *ncacn_np_secondary_endpoint,
183 const struct dcesrv_interface *iface,
184 const struct security_descriptor *sd)
186 struct dcerpc_binding *binding = NULL;
187 struct dcerpc_binding *binding2 = NULL;
188 NTSTATUS ret;
190 ret = dcerpc_parse_binding(dce_ctx, ep_name, &binding);
191 if (NT_STATUS_IS_ERR(ret)) {
192 DBG_ERR("Trouble parsing binding string '%s'\n", ep_name);
193 goto out;
196 if (ncacn_np_secondary_endpoint != NULL) {
197 ret = dcerpc_parse_binding(dce_ctx,
198 ncacn_np_secondary_endpoint,
199 &binding2);
200 if (NT_STATUS_IS_ERR(ret)) {
201 DBG_ERR("Trouble parsing 2nd binding string '%s'\n",
202 ncacn_np_secondary_endpoint);
203 goto out;
207 ret = dcesrv_interface_register_b(dce_ctx,
208 binding,
209 binding2,
210 iface,
211 sd);
212 out:
213 TALLOC_FREE(binding);
214 TALLOC_FREE(binding2);
215 return ret;
218 _PUBLIC_ NTSTATUS dcesrv_interface_register_b(struct dcesrv_context *dce_ctx,
219 struct dcerpc_binding *binding,
220 struct dcerpc_binding *binding2,
221 const struct dcesrv_interface *iface,
222 const struct security_descriptor *sd)
224 struct dcesrv_endpoint *ep;
225 struct dcesrv_if_list *ifl;
226 bool add_ep = false;
227 NTSTATUS status;
228 enum dcerpc_transport_t transport;
229 char *ep_string = NULL;
230 bool use_single_process = true;
231 const char *ep_process_string;
234 * If we are not using handles, there is no need for force
235 * this service into using a single process.
237 * However, due to the way we listen for RPC packets, we can
238 * only do this if we have a single service per pipe or TCP
239 * port, so we still force a single combined process for
240 * ncalrpc.
242 if (iface->flags & DCESRV_INTERFACE_FLAGS_HANDLES_NOT_USED) {
243 use_single_process = false;
246 transport = dcerpc_binding_get_transport(binding);
247 if (transport == NCACN_IP_TCP) {
248 int port;
251 * First check if there is already a port specified, eg
252 * for epmapper on ncacn_ip_tcp:[135]
254 const char *endpoint
255 = dcerpc_binding_get_string_option(binding,
256 "endpoint");
257 if (endpoint == NULL) {
258 port = lpcfg_parm_int(dce_ctx->lp_ctx, NULL,
259 "rpc server port", iface->name, 0);
262 * For RPC services that are not set to use a single
263 * process, we do not default to using the 'rpc server
264 * port' because that would cause a double-bind on
265 * that port.
267 if (port == 0 && !use_single_process) {
268 port = lpcfg_rpc_server_port(dce_ctx->lp_ctx);
270 if (port != 0) {
271 char port_str[6];
272 snprintf(port_str, sizeof(port_str), "%u", port);
273 status = dcerpc_binding_set_string_option(binding,
274 "endpoint",
275 port_str);
276 if (!NT_STATUS_IS_OK(status)) {
277 return status;
283 if (transport == NCACN_NP && binding2 != NULL) {
284 enum dcerpc_transport_t transport2;
286 transport2 = dcerpc_binding_get_transport(binding2);
287 SMB_ASSERT(transport2 == transport);
290 /* see if the interface is already registered on the endpoint */
291 if (find_interface_by_binding(dce_ctx, binding, iface)!=NULL) {
292 char *binding_string = dcerpc_binding_string(dce_ctx, binding);
293 DBG_ERR("Interface '%s' already registered on endpoint '%s'\n",
294 iface->name, binding_string);
295 TALLOC_FREE(binding_string);
296 return NT_STATUS_OBJECT_NAME_COLLISION;
299 /* check if this endpoint exists
301 status = dcesrv_find_endpoint(dce_ctx, binding, &ep);
302 if (NT_STATUS_IS_OK(status)) {
304 * We want a new port on ncacn_ip_tcp for NETLOGON, so
305 * it can be multi-process. Other processes can also
306 * listen on distinct ports, if they have one forced
307 * in the code above with eg 'rpc server port:drsuapi = 1027'
309 * If we have multiple endpoints on port 0, they each
310 * get an epemeral port (currently by walking up from
311 * 1024).
313 * Because one endpoint can only have one process
314 * model, we add a new IP_TCP endpoint for each model.
316 * This works in conjunction with the forced overwrite
317 * of ep->use_single_process below.
319 if (ep->use_single_process != use_single_process
320 && transport == NCACN_IP_TCP) {
321 add_ep = true;
325 if (NT_STATUS_EQUAL(status, NT_STATUS_NOT_FOUND) || add_ep) {
326 ep = talloc_zero(dce_ctx, struct dcesrv_endpoint);
327 if (!ep) {
328 return NT_STATUS_NO_MEMORY;
330 ep->ep_description = dcerpc_binding_dup(ep, binding);
331 if (transport == NCACN_NP && binding2 != NULL) {
332 ep->ep_2nd_description =
333 dcerpc_binding_dup(ep, binding2);
335 add_ep = true;
337 /* add mgmt interface */
338 ifl = talloc_zero(ep, struct dcesrv_if_list);
339 if (!ifl) {
340 TALLOC_FREE(ep);
341 return NT_STATUS_NO_MEMORY;
344 ifl->iface = talloc_memdup(ifl,
345 dcesrv_get_mgmt_interface(),
346 sizeof(struct dcesrv_interface));
347 if (ifl->iface == NULL) {
348 talloc_free(ep);
349 return NT_STATUS_NO_MEMORY;
352 DLIST_ADD(ep->interface_list, ifl);
353 } else if (!NT_STATUS_IS_OK(status)) {
354 DBG_NOTICE("Failed to find endpoint: %s\n", nt_errstr(status));
355 return status;
359 * By default don't force into a single process, but if any
360 * interface on this endpoint on this service uses handles
361 * (most do), then we must force into single process mode
363 * By overwriting this each time a new interface is added to
364 * this endpoint, we end up with the most restrictive setting.
366 if (use_single_process) {
367 ep->use_single_process = true;
370 /* talloc a new interface list element */
371 ifl = talloc_zero(ep, struct dcesrv_if_list);
372 if (!ifl) {
373 return NT_STATUS_NO_MEMORY;
376 /* copy the given interface struct to the one on the endpoints interface list */
377 ifl->iface = talloc_memdup(ifl,
378 iface,
379 sizeof(struct dcesrv_interface));
380 if (ifl->iface == NULL) {
381 talloc_free(ep);
382 return NT_STATUS_NO_MEMORY;
385 /* if we have a security descriptor given,
386 * we should see if we can set it up on the endpoint
388 if (sd != NULL) {
389 /* if there's currently no security descriptor given on the endpoint
390 * we try to set it
392 if (ep->sd == NULL) {
393 ep->sd = security_descriptor_copy(ep, sd);
396 /* if now there's no security descriptor given on the endpoint
397 * something goes wrong, either we failed to copy the security descriptor
398 * or there was already one on the endpoint
400 if (ep->sd != NULL) {
401 char *binding_string =
402 dcerpc_binding_string(dce_ctx, binding);
403 DBG_ERR("Interface '%s' failed to setup a security "
404 "descriptor on endpoint '%s'\n",
405 iface->name, binding_string);
406 TALLOC_FREE(binding_string);
407 if (add_ep) free(ep);
408 free(ifl);
409 return NT_STATUS_OBJECT_NAME_COLLISION;
413 /* finally add the interface on the endpoint */
414 DLIST_ADD(ep->interface_list, ifl);
416 /* if it's a new endpoint add it to the dcesrv_context */
417 if (add_ep) {
418 DLIST_ADD(dce_ctx->endpoint_list, ep);
421 /* Re-get the string as we may have set a port */
422 ep_string = dcerpc_binding_string(dce_ctx, ep->ep_description);
424 if (use_single_process) {
425 ep_process_string = "single process required";
426 } else {
427 ep_process_string = "multi process compatible";
430 DBG_INFO("Interface '%s' registered on endpoint '%s' (%s)\n",
431 iface->name, ep_string, ep_process_string);
432 TALLOC_FREE(ep_string);
434 return NT_STATUS_OK;
437 static NTSTATUS dcesrv_session_info_session_key(struct dcesrv_auth *auth,
438 DATA_BLOB *session_key)
440 if (auth->session_info == NULL) {
441 return NT_STATUS_NO_USER_SESSION_KEY;
444 if (auth->session_info->session_key.length == 0) {
445 return NT_STATUS_NO_USER_SESSION_KEY;
448 *session_key = auth->session_info->session_key;
449 return NT_STATUS_OK;
452 static NTSTATUS dcesrv_remote_session_key(struct dcesrv_auth *auth,
453 DATA_BLOB *session_key)
455 if (auth->auth_type != DCERPC_AUTH_TYPE_NONE) {
456 return NT_STATUS_NO_USER_SESSION_KEY;
459 return dcesrv_session_info_session_key(auth, session_key);
462 static NTSTATUS dcesrv_local_fixed_session_key(struct dcesrv_auth *auth,
463 DATA_BLOB *session_key)
465 return dcerpc_generic_session_key(session_key);
469 * Fetch the authentication session key if available.
471 * This is the key generated by a gensec authentication.
474 _PUBLIC_ NTSTATUS dcesrv_auth_session_key(struct dcesrv_call_state *call,
475 DATA_BLOB *session_key)
477 struct dcesrv_auth *auth = call->auth_state;
478 SMB_ASSERT(auth->auth_finished);
479 return dcesrv_session_info_session_key(auth, session_key);
483 * Fetch the transport session key if available.
484 * Typically this is the SMB session key
485 * or a fixed key for local transports.
487 * The key is always truncated to 16 bytes.
489 _PUBLIC_ NTSTATUS dcesrv_transport_session_key(struct dcesrv_call_state *call,
490 DATA_BLOB *session_key)
492 struct dcesrv_auth *auth = call->auth_state;
493 NTSTATUS status;
495 SMB_ASSERT(auth->auth_finished);
497 if (auth->session_key_fn == NULL) {
498 return NT_STATUS_NO_USER_SESSION_KEY;
501 status = auth->session_key_fn(auth, session_key);
502 if (!NT_STATUS_IS_OK(status)) {
503 return status;
506 session_key->length = MIN(session_key->length, 16);
508 return NT_STATUS_OK;
511 static struct dcesrv_auth *dcesrv_auth_create(struct dcesrv_connection *conn)
513 const struct dcesrv_endpoint *ep = conn->endpoint;
514 enum dcerpc_transport_t transport =
515 dcerpc_binding_get_transport(ep->ep_description);
516 struct dcesrv_auth *auth = NULL;
518 auth = talloc_zero(conn, struct dcesrv_auth);
519 if (auth == NULL) {
520 return NULL;
523 switch (transport) {
524 case NCACN_NP:
525 auth->session_key_fn = dcesrv_remote_session_key;
526 break;
527 case NCALRPC:
528 case NCACN_UNIX_STREAM:
529 auth->session_key_fn = dcesrv_local_fixed_session_key;
530 break;
531 default:
533 * All other's get a NULL pointer, which
534 * results in NT_STATUS_NO_USER_SESSION_KEY
536 break;
539 return auth;
543 connect to a dcerpc endpoint
545 _PUBLIC_ NTSTATUS dcesrv_endpoint_connect(struct dcesrv_context *dce_ctx,
546 TALLOC_CTX *mem_ctx,
547 const struct dcesrv_endpoint *ep,
548 struct auth_session_info *session_info,
549 struct tevent_context *event_ctx,
550 uint32_t state_flags,
551 struct dcesrv_connection **_p)
553 struct dcesrv_auth *auth = NULL;
554 struct dcesrv_connection *p = NULL;
556 if (!session_info) {
557 return NT_STATUS_ACCESS_DENIED;
560 p = talloc_zero(mem_ctx, struct dcesrv_connection);
561 if (p == NULL) {
562 goto nomem;
565 p->dce_ctx = dce_ctx;
566 p->endpoint = ep;
567 p->packet_log_dir = lpcfg_parm_string(dce_ctx->lp_ctx,
568 NULL,
569 "dcesrv",
570 "stubs directory");
571 p->event_ctx = event_ctx;
572 p->state_flags = state_flags;
573 p->allow_bind = true;
574 p->max_recv_frag = 5840;
575 p->max_xmit_frag = 5840;
576 p->max_total_request_size = DCERPC_NCACN_REQUEST_DEFAULT_MAX_SIZE;
578 p->support_hdr_signing = lpcfg_parm_bool(dce_ctx->lp_ctx,
579 NULL,
580 "dcesrv",
581 "header signing",
582 true);
583 p->max_auth_states = lpcfg_parm_ulong(dce_ctx->lp_ctx,
584 NULL,
585 "dcesrv",
586 "max auth states",
587 2049);
589 auth = dcesrv_auth_create(p);
590 if (auth == NULL) {
591 goto nomem;
594 auth->session_info = talloc_reference(auth, session_info);
595 if (auth->session_info == NULL) {
596 goto nomem;
599 p->default_auth_state = auth;
602 * For now we only support NDR32.
604 p->preferred_transfer = &ndr_transfer_syntax_ndr;
606 *_p = p;
607 return NT_STATUS_OK;
608 nomem:
609 TALLOC_FREE(p);
610 return NT_STATUS_NO_MEMORY;
614 move a call from an existing linked list to the specified list. This
615 prevents bugs where we forget to remove the call from a previous
616 list when moving it.
618 static void dcesrv_call_set_list(struct dcesrv_call_state *call,
619 enum dcesrv_call_list list)
621 switch (call->list) {
622 case DCESRV_LIST_NONE:
623 break;
624 case DCESRV_LIST_CALL_LIST:
625 DLIST_REMOVE(call->conn->call_list, call);
626 break;
627 case DCESRV_LIST_FRAGMENTED_CALL_LIST:
628 DLIST_REMOVE(call->conn->incoming_fragmented_call_list, call);
629 break;
630 case DCESRV_LIST_PENDING_CALL_LIST:
631 DLIST_REMOVE(call->conn->pending_call_list, call);
632 break;
634 call->list = list;
635 switch (list) {
636 case DCESRV_LIST_NONE:
637 break;
638 case DCESRV_LIST_CALL_LIST:
639 DLIST_ADD_END(call->conn->call_list, call);
640 break;
641 case DCESRV_LIST_FRAGMENTED_CALL_LIST:
642 DLIST_ADD_END(call->conn->incoming_fragmented_call_list, call);
643 break;
644 case DCESRV_LIST_PENDING_CALL_LIST:
645 DLIST_ADD_END(call->conn->pending_call_list, call);
646 break;
650 static void dcesrv_call_disconnect_after(struct dcesrv_call_state *call,
651 const char *reason)
653 struct dcesrv_auth *a = NULL;
655 if (call->conn->terminate != NULL) {
656 return;
659 call->conn->allow_bind = false;
660 call->conn->allow_alter = false;
662 call->conn->default_auth_state->auth_invalid = true;
664 for (a = call->conn->auth_states; a != NULL; a = a->next) {
665 a->auth_invalid = true;
668 call->terminate_reason = talloc_strdup(call, reason);
669 if (call->terminate_reason == NULL) {
670 call->terminate_reason = __location__;
675 return a dcerpc bind_nak
677 static NTSTATUS dcesrv_bind_nak(struct dcesrv_call_state *call, uint32_t reason)
679 struct ncacn_packet pkt;
680 struct dcerpc_bind_nak_version version;
681 struct data_blob_list_item *rep;
682 NTSTATUS status;
683 static const uint8_t _pad[3] = { 0, };
686 * We add the call to the pending_call_list
687 * in order to defer the termination.
689 dcesrv_call_disconnect_after(call, "dcesrv_bind_nak");
691 /* setup a bind_nak */
692 dcesrv_init_hdr(&pkt, lpcfg_rpc_big_endian(call->conn->dce_ctx->lp_ctx));
693 pkt.auth_length = 0;
694 pkt.call_id = call->pkt.call_id;
695 pkt.ptype = DCERPC_PKT_BIND_NAK;
696 pkt.pfc_flags = DCERPC_PFC_FLAG_FIRST | DCERPC_PFC_FLAG_LAST;
697 pkt.u.bind_nak.reject_reason = reason;
698 version.rpc_vers = 5;
699 version.rpc_vers_minor = 0;
700 pkt.u.bind_nak.num_versions = 1;
701 pkt.u.bind_nak.versions = &version;
702 pkt.u.bind_nak._pad = data_blob_const(_pad, sizeof(_pad));
704 rep = talloc_zero(call, struct data_blob_list_item);
705 if (!rep) {
706 return NT_STATUS_NO_MEMORY;
709 status = dcerpc_ncacn_push_auth(&rep->blob, call, &pkt, NULL);
710 if (!NT_STATUS_IS_OK(status)) {
711 return status;
714 dcerpc_set_frag_length(&rep->blob, rep->blob.length);
716 DLIST_ADD_END(call->replies, rep);
717 dcesrv_call_set_list(call, DCESRV_LIST_CALL_LIST);
719 if (call->conn->call_list && call->conn->call_list->replies) {
720 if (call->conn->transport.report_output_data) {
721 call->conn->transport.report_output_data(call->conn);
725 return NT_STATUS_OK;
728 static NTSTATUS _dcesrv_fault_disconnect_flags(struct dcesrv_call_state *call,
729 uint32_t fault_code,
730 uint8_t extra_flags,
731 const char *func,
732 const char *location)
734 const char *reason = NULL;
736 reason = talloc_asprintf(call, "%s:%s: fault=%u (%s) flags=0x%x",
737 func, location,
738 fault_code,
739 dcerpc_errstr(call, fault_code),
740 extra_flags);
741 if (reason == NULL) {
742 reason = location;
746 * We add the call to the pending_call_list
747 * in order to defer the termination.
750 dcesrv_call_disconnect_after(call, reason);
752 return dcesrv_fault_with_flags(call, fault_code, extra_flags);
755 #define dcesrv_fault_disconnect(call, fault_code) \
756 _dcesrv_fault_disconnect_flags(call, fault_code, \
757 DCERPC_PFC_FLAG_DID_NOT_EXECUTE, \
758 __func__, __location__)
759 #define dcesrv_fault_disconnect0(call, fault_code) \
760 _dcesrv_fault_disconnect_flags(call, fault_code, 0, \
761 __func__, __location__)
763 static int dcesrv_connection_context_destructor(struct dcesrv_connection_context *c)
765 DLIST_REMOVE(c->conn->contexts, c);
767 if (c->iface && c->iface->unbind) {
768 c->iface->unbind(c, c->iface);
769 c->iface = NULL;
772 return 0;
775 static void dcesrv_prepare_context_auth(struct dcesrv_call_state *dce_call)
777 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
778 const struct dcesrv_endpoint *endpoint = dce_call->conn->endpoint;
779 enum dcerpc_transport_t transport =
780 dcerpc_binding_get_transport(endpoint->ep_description);
781 struct dcesrv_connection_context *context = dce_call->context;
782 const struct dcesrv_interface *iface = context->iface;
784 context->min_auth_level = DCERPC_AUTH_LEVEL_NONE;
786 if (transport == NCALRPC) {
787 context->allow_connect = true;
788 return;
792 * allow overwrite per interface
793 * allow dcerpc auth level connect:<interface>
795 context->allow_connect = lpcfg_allow_dcerpc_auth_level_connect(lp_ctx);
796 context->allow_connect = lpcfg_parm_bool(lp_ctx, NULL,
797 "allow dcerpc auth level connect",
798 iface->name,
799 context->allow_connect);
802 NTSTATUS dcesrv_interface_bind_require_integrity(struct dcesrv_connection_context *context,
803 const struct dcesrv_interface *iface)
806 * For connection oriented DCERPC DCERPC_AUTH_LEVEL_PACKET (4)
807 * has the same behavior as DCERPC_AUTH_LEVEL_INTEGRITY (5).
809 context->min_auth_level = DCERPC_AUTH_LEVEL_PACKET;
810 return NT_STATUS_OK;
813 NTSTATUS dcesrv_interface_bind_require_privacy(struct dcesrv_connection_context *context,
814 const struct dcesrv_interface *iface)
816 context->min_auth_level = DCERPC_AUTH_LEVEL_PRIVACY;
817 return NT_STATUS_OK;
820 _PUBLIC_ NTSTATUS dcesrv_interface_bind_reject_connect(struct dcesrv_connection_context *context,
821 const struct dcesrv_interface *iface)
823 struct loadparm_context *lp_ctx = context->conn->dce_ctx->lp_ctx;
824 const struct dcesrv_endpoint *endpoint = context->conn->endpoint;
825 enum dcerpc_transport_t transport =
826 dcerpc_binding_get_transport(endpoint->ep_description);
828 if (transport == NCALRPC) {
829 context->allow_connect = true;
830 return NT_STATUS_OK;
834 * allow overwrite per interface
835 * allow dcerpc auth level connect:<interface>
837 context->allow_connect = false;
838 context->allow_connect = lpcfg_parm_bool(lp_ctx, NULL,
839 "allow dcerpc auth level connect",
840 iface->name,
841 context->allow_connect);
842 return NT_STATUS_OK;
845 _PUBLIC_ NTSTATUS dcesrv_interface_bind_allow_connect(struct dcesrv_connection_context *context,
846 const struct dcesrv_interface *iface)
848 struct loadparm_context *lp_ctx = context->conn->dce_ctx->lp_ctx;
849 const struct dcesrv_endpoint *endpoint = context->conn->endpoint;
850 enum dcerpc_transport_t transport =
851 dcerpc_binding_get_transport(endpoint->ep_description);
853 if (transport == NCALRPC) {
854 context->allow_connect = true;
855 return NT_STATUS_OK;
859 * allow overwrite per interface
860 * allow dcerpc auth level connect:<interface>
862 context->allow_connect = true;
863 context->allow_connect = lpcfg_parm_bool(lp_ctx, NULL,
864 "allow dcerpc auth level connect",
865 iface->name,
866 context->allow_connect);
867 return NT_STATUS_OK;
870 struct dcesrv_conn_auth_wait_context {
871 struct tevent_req *req;
872 bool done;
873 NTSTATUS status;
876 struct dcesrv_conn_auth_wait_state {
877 uint8_t dummy;
880 static struct tevent_req *dcesrv_conn_auth_wait_send(TALLOC_CTX *mem_ctx,
881 struct tevent_context *ev,
882 void *private_data)
884 struct dcesrv_conn_auth_wait_context *auth_wait =
885 talloc_get_type_abort(private_data,
886 struct dcesrv_conn_auth_wait_context);
887 struct tevent_req *req = NULL;
888 struct dcesrv_conn_auth_wait_state *state = NULL;
890 req = tevent_req_create(mem_ctx, &state,
891 struct dcesrv_conn_auth_wait_state);
892 if (req == NULL) {
893 return NULL;
895 auth_wait->req = req;
897 tevent_req_defer_callback(req, ev);
899 if (!auth_wait->done) {
900 return req;
903 if (tevent_req_nterror(req, auth_wait->status)) {
904 return tevent_req_post(req, ev);
907 tevent_req_done(req);
908 return tevent_req_post(req, ev);
911 static NTSTATUS dcesrv_conn_auth_wait_recv(struct tevent_req *req)
913 return tevent_req_simple_recv_ntstatus(req);
916 static NTSTATUS dcesrv_conn_auth_wait_setup(struct dcesrv_connection *conn)
918 struct dcesrv_conn_auth_wait_context *auth_wait = NULL;
920 if (conn->wait_send != NULL) {
921 return NT_STATUS_INTERNAL_ERROR;
924 auth_wait = talloc_zero(conn, struct dcesrv_conn_auth_wait_context);
925 if (auth_wait == NULL) {
926 return NT_STATUS_NO_MEMORY;
929 conn->wait_private = auth_wait;
930 conn->wait_send = dcesrv_conn_auth_wait_send;
931 conn->wait_recv = dcesrv_conn_auth_wait_recv;
932 return NT_STATUS_OK;
935 static void dcesrv_conn_auth_wait_finished(struct dcesrv_connection *conn,
936 NTSTATUS status)
938 struct dcesrv_conn_auth_wait_context *auth_wait =
939 talloc_get_type_abort(conn->wait_private,
940 struct dcesrv_conn_auth_wait_context);
942 auth_wait->done = true;
943 auth_wait->status = status;
945 if (auth_wait->req == NULL) {
946 return;
949 if (tevent_req_nterror(auth_wait->req, status)) {
950 return;
953 tevent_req_done(auth_wait->req);
956 static NTSTATUS dcesrv_auth_reply(struct dcesrv_call_state *call);
958 static void dcesrv_bind_done(struct tevent_req *subreq);
961 handle a bind request
963 static NTSTATUS dcesrv_bind(struct dcesrv_call_state *call)
965 struct dcesrv_connection *conn = call->conn;
966 struct dcesrv_context *dce_ctx = conn->dce_ctx;
967 struct ncacn_packet *pkt = &call->ack_pkt;
968 NTSTATUS status;
969 uint32_t extra_flags = 0;
970 uint16_t max_req = 0;
971 uint16_t max_rep = 0;
972 struct dcerpc_binding *ep_2nd_description = NULL;
973 const char *endpoint = NULL;
974 struct dcesrv_auth *auth = call->auth_state;
975 struct dcesrv_context_callbacks *cb = call->conn->dce_ctx->callbacks;
976 struct dcerpc_ack_ctx *ack_ctx_list = NULL;
977 struct dcerpc_ack_ctx *ack_features = NULL;
978 struct tevent_req *subreq = NULL;
979 size_t i;
981 status = dcerpc_verify_ncacn_packet_header(&call->pkt,
982 DCERPC_PKT_BIND,
983 call->pkt.u.bind.auth_info.length,
984 0, /* required flags */
985 DCERPC_PFC_FLAG_FIRST |
986 DCERPC_PFC_FLAG_LAST |
987 DCERPC_PFC_FLAG_SUPPORT_HEADER_SIGN |
988 0x08 | /* this is not defined, but should be ignored */
989 DCERPC_PFC_FLAG_CONC_MPX |
990 DCERPC_PFC_FLAG_DID_NOT_EXECUTE |
991 DCERPC_PFC_FLAG_MAYBE |
992 DCERPC_PFC_FLAG_OBJECT_UUID);
993 if (!NT_STATUS_IS_OK(status)) {
994 return dcesrv_bind_nak(call,
995 DCERPC_BIND_NAK_REASON_PROTOCOL_VERSION_NOT_SUPPORTED);
998 /* max_recv_frag and max_xmit_frag result always in the same value! */
999 max_req = MIN(call->pkt.u.bind.max_xmit_frag,
1000 call->pkt.u.bind.max_recv_frag);
1002 * The values are between 2048 and 5840 tested against Windows 2012R2
1003 * via ncacn_ip_tcp on port 135.
1005 max_req = MAX(2048, max_req);
1006 max_rep = MIN(max_req, conn->max_recv_frag);
1007 /* They are truncated to an 8 byte boundary. */
1008 max_rep &= 0xFFF8;
1010 /* max_recv_frag and max_xmit_frag result always in the same value! */
1011 conn->max_recv_frag = max_rep;
1012 conn->max_xmit_frag = max_rep;
1014 status = dce_ctx->callbacks->assoc_group.find(
1015 call, dce_ctx->callbacks->assoc_group.private_data);
1016 if (!NT_STATUS_IS_OK(status)) {
1017 DBG_NOTICE("Failed to find assoc_group 0x%08x: %s\n",
1018 call->pkt.u.bind.assoc_group_id, nt_errstr(status));
1019 return dcesrv_bind_nak(call, 0);
1022 if (call->pkt.u.bind.num_contexts < 1) {
1023 return dcesrv_bind_nak(call, 0);
1026 ack_ctx_list = talloc_zero_array(call, struct dcerpc_ack_ctx,
1027 call->pkt.u.bind.num_contexts);
1028 if (ack_ctx_list == NULL) {
1029 return dcesrv_bind_nak(call, 0);
1033 * Set some sane defaults (required by dcesrv_negotiate_contexts()/
1034 * dcesrv_check_or_create_context()) and do some protocol validation
1035 * and set sane defaults.
1037 for (i = 0; i < call->pkt.u.bind.num_contexts; i++) {
1038 const struct dcerpc_ctx_list *c = &call->pkt.u.bind.ctx_list[i];
1039 struct dcerpc_ack_ctx *a = &ack_ctx_list[i];
1040 bool is_feature = false;
1041 uint64_t features = 0;
1043 if (c->num_transfer_syntaxes == 0) {
1044 return dcesrv_bind_nak(call, 0);
1047 a->result = DCERPC_BIND_ACK_RESULT_PROVIDER_REJECTION;
1048 a->reason.value = DCERPC_BIND_ACK_REASON_ABSTRACT_SYNTAX_NOT_SUPPORTED;
1051 * It's only treated as bind time feature request, if the first
1052 * transfer_syntax matches, all others are ignored.
1054 is_feature = dcerpc_extract_bind_time_features(c->transfer_syntaxes[0],
1055 &features);
1056 if (!is_feature) {
1057 continue;
1060 if (ack_features != NULL) {
1062 * Only one bind time feature context is allowed.
1064 return dcesrv_bind_nak(call, 0);
1066 ack_features = a;
1068 a->result = DCERPC_BIND_ACK_RESULT_NEGOTIATE_ACK;
1069 a->reason.negotiate = 0;
1070 if (features & DCERPC_BIND_TIME_SECURITY_CONTEXT_MULTIPLEXING) {
1071 if (conn->max_auth_states != 0) {
1072 a->reason.negotiate |=
1073 DCERPC_BIND_TIME_SECURITY_CONTEXT_MULTIPLEXING;
1076 if (features & DCERPC_BIND_TIME_KEEP_CONNECTION_ON_ORPHAN) {
1077 a->reason.negotiate |=
1078 DCERPC_BIND_TIME_KEEP_CONNECTION_ON_ORPHAN;
1081 conn->assoc_group->bind_time_features = a->reason.negotiate;
1085 * Try to negotiate one new presentation context.
1087 * Deep in here we locate the iface (by uuid) that the client
1088 * requested, from the list of interfaces on the
1089 * call->conn->endpoint, and call iface->bind() on that iface.
1091 * call->conn was set up at the accept() of the socket, and
1092 * call->conn->endpoint has a list of interfaces restricted to
1093 * this port or pipe.
1095 status = dcesrv_negotiate_contexts(call, &call->pkt.u.bind, ack_ctx_list);
1096 if (NT_STATUS_EQUAL(status, NT_STATUS_RPC_PROTOCOL_ERROR)) {
1097 return dcesrv_bind_nak(call, 0);
1099 if (!NT_STATUS_IS_OK(status)) {
1100 return status;
1104 * At this point we still don't know which interface (eg
1105 * netlogon, lsa, drsuapi) the caller requested in this bind!
1106 * The most recently added context is available as the first
1107 * element in the linked list at call->conn->contexts, that is
1108 * call->conn->contexts->iface, but they may not have
1109 * requested one at all!
1112 if ((call->pkt.pfc_flags & DCERPC_PFC_FLAG_CONC_MPX) &&
1113 (call->state_flags & DCESRV_CALL_STATE_FLAG_MULTIPLEXED)) {
1114 call->conn->state_flags |= DCESRV_CALL_STATE_FLAG_MULTIPLEXED;
1115 extra_flags |= DCERPC_PFC_FLAG_CONC_MPX;
1118 if (call->state_flags & DCESRV_CALL_STATE_FLAG_PROCESS_PENDING_CALL) {
1119 conn->state_flags |= DCESRV_CALL_STATE_FLAG_PROCESS_PENDING_CALL;
1123 * After finding the interface and setting up the NDR
1124 * transport negotiation etc, handle any authentication that
1125 * is being requested.
1127 if (!dcesrv_auth_bind(call)) {
1129 if (auth->auth_level == DCERPC_AUTH_LEVEL_NONE) {
1131 * With DCERPC_AUTH_LEVEL_NONE, we get the
1132 * reject_reason in auth->auth_context_id.
1134 return dcesrv_bind_nak(call, auth->auth_context_id);
1138 * This must a be a temporary failure e.g. talloc or invalid
1139 * configuration, e.g. no machine account.
1141 return dcesrv_bind_nak(call,
1142 DCERPC_BIND_NAK_REASON_TEMPORARY_CONGESTION);
1145 /* setup a bind_ack */
1146 dcesrv_init_hdr(pkt, lpcfg_rpc_big_endian(dce_ctx->lp_ctx));
1147 pkt->auth_length = 0;
1148 pkt->call_id = call->pkt.call_id;
1149 pkt->ptype = DCERPC_PKT_BIND_ACK;
1150 pkt->pfc_flags = DCERPC_PFC_FLAG_FIRST | DCERPC_PFC_FLAG_LAST | extra_flags;
1151 pkt->u.bind_ack.max_xmit_frag = conn->max_xmit_frag;
1152 pkt->u.bind_ack.max_recv_frag = conn->max_recv_frag;
1153 pkt->u.bind_ack.assoc_group_id = conn->assoc_group->id;
1155 ep_2nd_description = conn->endpoint->ep_2nd_description;
1156 if (ep_2nd_description == NULL) {
1157 ep_2nd_description = conn->endpoint->ep_description;
1160 endpoint = dcerpc_binding_get_string_option(
1161 ep_2nd_description,
1162 "endpoint");
1163 if (endpoint == NULL) {
1164 endpoint = "";
1167 pkt->u.bind_ack.secondary_address = endpoint;
1168 pkt->u.bind_ack.num_results = call->pkt.u.bind.num_contexts;
1169 pkt->u.bind_ack.ctx_list = ack_ctx_list;
1170 pkt->u.bind_ack.auth_info = data_blob_null;
1172 status = dcesrv_auth_prepare_bind_ack(call, pkt);
1173 if (!NT_STATUS_IS_OK(status)) {
1174 return dcesrv_bind_nak(call, 0);
1177 if (auth->auth_finished) {
1178 return dcesrv_auth_reply(call);
1181 cb->auth.become_root();
1182 subreq = gensec_update_send(call, call->event_ctx,
1183 auth->gensec_security,
1184 call->in_auth_info.credentials);
1185 cb->auth.unbecome_root();
1186 if (subreq == NULL) {
1187 return NT_STATUS_NO_MEMORY;
1189 tevent_req_set_callback(subreq, dcesrv_bind_done, call);
1191 return dcesrv_conn_auth_wait_setup(conn);
1194 static void dcesrv_bind_done(struct tevent_req *subreq)
1196 struct dcesrv_call_state *call =
1197 tevent_req_callback_data(subreq,
1198 struct dcesrv_call_state);
1199 struct dcesrv_connection *conn = call->conn;
1200 struct dcesrv_context_callbacks *cb = call->conn->dce_ctx->callbacks;
1201 NTSTATUS status;
1203 cb->auth.become_root();
1204 status = gensec_update_recv(subreq, call,
1205 &call->out_auth_info->credentials);
1206 cb->auth.unbecome_root();
1207 TALLOC_FREE(subreq);
1209 status = dcesrv_auth_complete(call, status);
1210 if (!NT_STATUS_IS_OK(status)) {
1211 status = dcesrv_bind_nak(call, 0);
1212 dcesrv_conn_auth_wait_finished(conn, status);
1213 return;
1216 status = dcesrv_auth_reply(call);
1217 dcesrv_conn_auth_wait_finished(conn, status);
1218 return;
1221 static NTSTATUS dcesrv_auth_reply(struct dcesrv_call_state *call)
1223 struct ncacn_packet *pkt = &call->ack_pkt;
1224 struct data_blob_list_item *rep = NULL;
1225 NTSTATUS status;
1227 rep = talloc_zero(call, struct data_blob_list_item);
1228 if (!rep) {
1229 return NT_STATUS_NO_MEMORY;
1232 status = dcerpc_ncacn_push_auth(&rep->blob,
1233 call,
1234 pkt,
1235 call->out_auth_info);
1236 if (!NT_STATUS_IS_OK(status)) {
1237 return status;
1240 dcerpc_set_frag_length(&rep->blob, rep->blob.length);
1242 DLIST_ADD_END(call->replies, rep);
1243 dcesrv_call_set_list(call, DCESRV_LIST_CALL_LIST);
1245 if (call->conn->call_list && call->conn->call_list->replies) {
1246 if (call->conn->transport.report_output_data) {
1247 call->conn->transport.report_output_data(call->conn);
1251 return NT_STATUS_OK;
1255 static void dcesrv_auth3_done(struct tevent_req *subreq);
1258 handle a auth3 request
1260 static NTSTATUS dcesrv_auth3(struct dcesrv_call_state *call)
1262 struct dcesrv_connection *conn = call->conn;
1263 struct dcesrv_auth *auth = call->auth_state;
1264 struct dcesrv_context_callbacks *cb = call->conn->dce_ctx->callbacks;
1265 struct tevent_req *subreq = NULL;
1266 NTSTATUS status;
1268 if (!auth->auth_started) {
1269 return dcesrv_fault_disconnect(call, DCERPC_NCA_S_PROTO_ERROR);
1272 if (auth->auth_finished) {
1273 return dcesrv_fault_disconnect(call, DCERPC_NCA_S_PROTO_ERROR);
1276 status = dcerpc_verify_ncacn_packet_header(&call->pkt,
1277 DCERPC_PKT_AUTH3,
1278 call->pkt.u.auth3.auth_info.length,
1279 0, /* required flags */
1280 DCERPC_PFC_FLAG_FIRST |
1281 DCERPC_PFC_FLAG_LAST |
1282 DCERPC_PFC_FLAG_SUPPORT_HEADER_SIGN |
1283 0x08 | /* this is not defined, but should be ignored */
1284 DCERPC_PFC_FLAG_CONC_MPX |
1285 DCERPC_PFC_FLAG_DID_NOT_EXECUTE |
1286 DCERPC_PFC_FLAG_MAYBE |
1287 DCERPC_PFC_FLAG_OBJECT_UUID);
1288 if (!NT_STATUS_IS_OK(status)) {
1289 return dcesrv_fault_disconnect(call, DCERPC_NCA_S_PROTO_ERROR);
1292 /* handle the auth3 in the auth code */
1293 if (!dcesrv_auth_prepare_auth3(call)) {
1295 * we don't send a reply to a auth3 request,
1296 * except by a fault.
1298 * In anycase we mark the connection as
1299 * invalid.
1301 auth->auth_invalid = true;
1302 if (call->fault_code != 0) {
1303 return dcesrv_fault_disconnect(call, call->fault_code);
1305 TALLOC_FREE(call);
1306 return NT_STATUS_OK;
1309 cb->auth.become_root();
1310 subreq = gensec_update_send(call, call->event_ctx,
1311 auth->gensec_security,
1312 call->in_auth_info.credentials);
1313 cb->auth.unbecome_root();
1314 if (subreq == NULL) {
1315 return NT_STATUS_NO_MEMORY;
1317 tevent_req_set_callback(subreq, dcesrv_auth3_done, call);
1319 return dcesrv_conn_auth_wait_setup(conn);
1322 static void dcesrv_auth3_done(struct tevent_req *subreq)
1324 struct dcesrv_call_state *call =
1325 tevent_req_callback_data(subreq,
1326 struct dcesrv_call_state);
1327 struct dcesrv_connection *conn = call->conn;
1328 struct dcesrv_auth *auth = call->auth_state;
1329 struct dcesrv_context_callbacks *cb = call->conn->dce_ctx->callbacks;
1330 NTSTATUS status;
1332 cb->auth.become_root();
1333 status = gensec_update_recv(subreq, call,
1334 &call->out_auth_info->credentials);
1335 cb->auth.unbecome_root();
1336 TALLOC_FREE(subreq);
1338 status = dcesrv_auth_complete(call, status);
1339 if (!NT_STATUS_IS_OK(status)) {
1341 * we don't send a reply to a auth3 request,
1342 * except by a fault.
1344 * In anycase we mark the connection as
1345 * invalid.
1347 auth->auth_invalid = true;
1348 if (call->fault_code != 0) {
1349 status = dcesrv_fault_disconnect(call, call->fault_code);
1350 dcesrv_conn_auth_wait_finished(conn, status);
1351 return;
1353 TALLOC_FREE(call);
1354 dcesrv_conn_auth_wait_finished(conn, NT_STATUS_OK);
1355 return;
1359 * we don't send a reply to a auth3 request.
1361 TALLOC_FREE(call);
1362 dcesrv_conn_auth_wait_finished(conn, NT_STATUS_OK);
1363 return;
1367 static NTSTATUS dcesrv_check_or_create_context(struct dcesrv_call_state *call,
1368 const struct dcerpc_bind *b,
1369 const struct dcerpc_ctx_list *ctx,
1370 struct dcerpc_ack_ctx *ack,
1371 bool validate_only,
1372 const struct ndr_syntax_id *supported_transfer)
1374 struct dcesrv_connection_context *context;
1375 const struct dcesrv_interface *iface;
1376 NTSTATUS status;
1377 const struct ndr_syntax_id *selected_transfer = NULL;
1378 size_t i;
1379 bool ok;
1381 if (b == NULL) {
1382 return NT_STATUS_INTERNAL_ERROR;
1384 if (ctx == NULL) {
1385 return NT_STATUS_INTERNAL_ERROR;
1387 if (ctx->num_transfer_syntaxes < 1) {
1388 return NT_STATUS_INTERNAL_ERROR;
1390 if (ack == NULL) {
1391 return NT_STATUS_INTERNAL_ERROR;
1393 if (supported_transfer == NULL) {
1394 return NT_STATUS_INTERNAL_ERROR;
1397 switch (ack->result) {
1398 case DCERPC_BIND_ACK_RESULT_ACCEPTANCE:
1399 case DCERPC_BIND_ACK_RESULT_NEGOTIATE_ACK:
1401 * We is already completed.
1403 return NT_STATUS_OK;
1404 default:
1405 break;
1408 ack->result = DCERPC_BIND_ACK_RESULT_PROVIDER_REJECTION;
1409 ack->reason.value = DCERPC_BIND_ACK_REASON_ABSTRACT_SYNTAX_NOT_SUPPORTED;
1411 iface = find_interface_by_syntax_id(
1412 call->conn->endpoint, &ctx->abstract_syntax);
1413 if (iface == NULL) {
1414 struct ndr_syntax_id_buf buf;
1415 DBG_NOTICE("Request for unknown dcerpc interface %s\n",
1416 ndr_syntax_id_buf_string(
1417 &ctx->abstract_syntax, &buf));
1419 * We report this only via ack->result
1421 return NT_STATUS_OK;
1424 ack->result = DCERPC_BIND_ACK_RESULT_PROVIDER_REJECTION;
1425 ack->reason.value = DCERPC_BIND_ACK_REASON_TRANSFER_SYNTAXES_NOT_SUPPORTED;
1427 if (validate_only) {
1429 * We report this only via ack->result
1431 return NT_STATUS_OK;
1434 for (i = 0; i < ctx->num_transfer_syntaxes; i++) {
1436 * we only do NDR encoded dcerpc for now.
1438 ok = ndr_syntax_id_equal(&ctx->transfer_syntaxes[i],
1439 supported_transfer);
1440 if (ok) {
1441 selected_transfer = supported_transfer;
1442 break;
1446 context = dcesrv_find_context(call->conn, ctx->context_id);
1447 if (context != NULL) {
1448 ok = ndr_syntax_id_equal(&context->iface->syntax_id,
1449 &ctx->abstract_syntax);
1450 if (!ok) {
1451 return NT_STATUS_RPC_PROTOCOL_ERROR;
1454 if (selected_transfer != NULL) {
1455 ok = ndr_syntax_id_equal(&context->transfer_syntax,
1456 selected_transfer);
1457 if (!ok) {
1458 return NT_STATUS_RPC_PROTOCOL_ERROR;
1461 ack->result = DCERPC_BIND_ACK_RESULT_ACCEPTANCE;
1462 ack->reason.value = DCERPC_BIND_ACK_REASON_NOT_SPECIFIED;
1463 ack->syntax = context->transfer_syntax;
1467 * We report this only via ack->result
1469 return NT_STATUS_OK;
1472 if (selected_transfer == NULL) {
1474 * We report this only via ack->result
1476 return NT_STATUS_OK;
1479 ack->result = DCERPC_BIND_ACK_RESULT_USER_REJECTION;
1480 ack->reason.value = DCERPC_BIND_ACK_REASON_LOCAL_LIMIT_EXCEEDED;
1482 /* add this context to the list of available context_ids */
1483 context = talloc_zero(call->conn, struct dcesrv_connection_context);
1484 if (context == NULL) {
1485 return NT_STATUS_NO_MEMORY;
1487 context->conn = call->conn;
1488 context->context_id = ctx->context_id;
1489 context->iface = iface;
1490 context->transfer_syntax = *selected_transfer;
1491 DLIST_ADD(call->conn->contexts, context);
1492 call->context = context;
1493 talloc_set_destructor(context, dcesrv_connection_context_destructor);
1495 dcesrv_prepare_context_auth(call);
1498 * Multiplex is supported by default
1500 call->state_flags |= DCESRV_CALL_STATE_FLAG_MULTIPLEXED;
1502 status = iface->bind(context, iface);
1503 call->context = NULL;
1504 if (!NT_STATUS_IS_OK(status)) {
1505 /* we don't want to trigger the iface->unbind() hook */
1506 context->iface = NULL;
1507 talloc_free(context);
1509 * We report this only via ack->result
1511 return NT_STATUS_OK;
1514 ack->result = DCERPC_BIND_ACK_RESULT_ACCEPTANCE;
1515 ack->reason.value = DCERPC_BIND_ACK_REASON_NOT_SPECIFIED;
1516 ack->syntax = context->transfer_syntax;
1517 return NT_STATUS_OK;
1520 static NTSTATUS dcesrv_negotiate_contexts(struct dcesrv_call_state *call,
1521 const struct dcerpc_bind *b,
1522 struct dcerpc_ack_ctx *ack_ctx_list)
1524 NTSTATUS status;
1525 size_t i;
1526 bool validate_only = false;
1527 bool preferred_ndr32;
1530 * Try to negotiate one new presentation context,
1531 * using our preferred transfer syntax.
1533 for (i = 0; i < b->num_contexts; i++) {
1534 const struct dcerpc_ctx_list *c = &b->ctx_list[i];
1535 struct dcerpc_ack_ctx *a = &ack_ctx_list[i];
1537 status = dcesrv_check_or_create_context(call, b, c, a,
1538 validate_only,
1539 call->conn->preferred_transfer);
1540 if (!NT_STATUS_IS_OK(status)) {
1541 return status;
1544 if (a->result == DCERPC_BIND_ACK_RESULT_ACCEPTANCE) {
1546 * We managed to negotiate one context.
1548 * => we're done.
1550 validate_only = true;
1554 preferred_ndr32 = ndr_syntax_id_equal(&ndr_transfer_syntax_ndr,
1555 call->conn->preferred_transfer);
1556 if (preferred_ndr32) {
1558 * We're done.
1560 return NT_STATUS_OK;
1564 * Try to negotiate one new presentation context,
1565 * using NDR 32 as fallback.
1567 for (i = 0; i < b->num_contexts; i++) {
1568 const struct dcerpc_ctx_list *c = &b->ctx_list[i];
1569 struct dcerpc_ack_ctx *a = &ack_ctx_list[i];
1571 status = dcesrv_check_or_create_context(call, b, c, a,
1572 validate_only,
1573 &ndr_transfer_syntax_ndr);
1574 if (!NT_STATUS_IS_OK(status)) {
1575 return status;
1578 if (a->result == DCERPC_BIND_ACK_RESULT_ACCEPTANCE) {
1580 * We managed to negotiate one context.
1582 * => we're done.
1584 validate_only = true;
1588 return NT_STATUS_OK;
1591 static void dcesrv_alter_done(struct tevent_req *subreq);
1594 handle a alter context request
1596 static NTSTATUS dcesrv_alter(struct dcesrv_call_state *call)
1598 struct dcesrv_connection *conn = call->conn;
1599 NTSTATUS status;
1600 bool auth_ok = false;
1601 struct ncacn_packet *pkt = &call->ack_pkt;
1602 uint32_t extra_flags = 0;
1603 struct dcesrv_auth *auth = call->auth_state;
1604 struct dcesrv_context_callbacks *cb = call->conn->dce_ctx->callbacks;
1605 struct dcerpc_ack_ctx *ack_ctx_list = NULL;
1606 struct tevent_req *subreq = NULL;
1607 size_t i;
1609 if (!call->conn->allow_alter) {
1610 return dcesrv_fault_disconnect(call, DCERPC_NCA_S_PROTO_ERROR);
1613 status = dcerpc_verify_ncacn_packet_header(&call->pkt,
1614 DCERPC_PKT_ALTER,
1615 call->pkt.u.alter.auth_info.length,
1616 0, /* required flags */
1617 DCERPC_PFC_FLAG_FIRST |
1618 DCERPC_PFC_FLAG_LAST |
1619 DCERPC_PFC_FLAG_SUPPORT_HEADER_SIGN |
1620 0x08 | /* this is not defined, but should be ignored */
1621 DCERPC_PFC_FLAG_CONC_MPX |
1622 DCERPC_PFC_FLAG_DID_NOT_EXECUTE |
1623 DCERPC_PFC_FLAG_MAYBE |
1624 DCERPC_PFC_FLAG_OBJECT_UUID);
1625 if (!NT_STATUS_IS_OK(status)) {
1626 return dcesrv_fault_disconnect(call, DCERPC_NCA_S_PROTO_ERROR);
1629 auth_ok = dcesrv_auth_alter(call);
1630 if (!auth_ok) {
1631 if (call->fault_code != 0) {
1632 return dcesrv_fault_disconnect(call, call->fault_code);
1636 if (call->pkt.u.alter.num_contexts < 1) {
1637 return dcesrv_fault_disconnect(call, DCERPC_NCA_S_PROTO_ERROR);
1640 ack_ctx_list = talloc_zero_array(call, struct dcerpc_ack_ctx,
1641 call->pkt.u.alter.num_contexts);
1642 if (ack_ctx_list == NULL) {
1643 return NT_STATUS_NO_MEMORY;
1647 * Set some sane defaults (required by dcesrv_negotiate_contexts()/
1648 * dcesrv_check_or_create_context()) and do some protocol validation
1649 * and set sane defaults.
1651 for (i = 0; i < call->pkt.u.alter.num_contexts; i++) {
1652 const struct dcerpc_ctx_list *c = &call->pkt.u.alter.ctx_list[i];
1653 struct dcerpc_ack_ctx *a = &ack_ctx_list[i];
1655 if (c->num_transfer_syntaxes == 0) {
1656 return dcesrv_fault_disconnect(call,
1657 DCERPC_NCA_S_PROTO_ERROR);
1660 a->result = DCERPC_BIND_ACK_RESULT_PROVIDER_REJECTION;
1661 a->reason.value = DCERPC_BIND_ACK_REASON_ABSTRACT_SYNTAX_NOT_SUPPORTED;
1665 * Try to negotiate one new presentation context.
1667 status = dcesrv_negotiate_contexts(call, &call->pkt.u.alter, ack_ctx_list);
1668 if (NT_STATUS_EQUAL(status, NT_STATUS_RPC_PROTOCOL_ERROR)) {
1669 return dcesrv_fault_disconnect(call, DCERPC_NCA_S_PROTO_ERROR);
1671 if (!NT_STATUS_IS_OK(status)) {
1672 return status;
1675 if ((call->pkt.pfc_flags & DCERPC_PFC_FLAG_CONC_MPX) &&
1676 (call->state_flags & DCESRV_CALL_STATE_FLAG_MULTIPLEXED)) {
1677 call->conn->state_flags |= DCESRV_CALL_STATE_FLAG_MULTIPLEXED;
1678 extra_flags |= DCERPC_PFC_FLAG_CONC_MPX;
1681 if (call->state_flags & DCESRV_CALL_STATE_FLAG_PROCESS_PENDING_CALL) {
1682 call->conn->state_flags |= DCESRV_CALL_STATE_FLAG_PROCESS_PENDING_CALL;
1685 /* handle any authentication that is being requested */
1686 if (!auth_ok) {
1687 if (call->in_auth_info.auth_type != auth->auth_type) {
1688 return dcesrv_fault_disconnect(call,
1689 DCERPC_FAULT_SEC_PKG_ERROR);
1691 return dcesrv_fault_disconnect(call, DCERPC_FAULT_ACCESS_DENIED);
1694 dcesrv_init_hdr(pkt, lpcfg_rpc_big_endian(call->conn->dce_ctx->lp_ctx));
1695 pkt->auth_length = 0;
1696 pkt->call_id = call->pkt.call_id;
1697 pkt->ptype = DCERPC_PKT_ALTER_RESP;
1698 pkt->pfc_flags = DCERPC_PFC_FLAG_FIRST | DCERPC_PFC_FLAG_LAST | extra_flags;
1699 pkt->u.alter_resp.max_xmit_frag = call->conn->max_xmit_frag;
1700 pkt->u.alter_resp.max_recv_frag = call->conn->max_recv_frag;
1701 pkt->u.alter_resp.assoc_group_id = call->conn->assoc_group->id;
1702 pkt->u.alter_resp.secondary_address = "";
1703 pkt->u.alter_resp.num_results = call->pkt.u.alter.num_contexts;
1704 pkt->u.alter_resp.ctx_list = ack_ctx_list;
1705 pkt->u.alter_resp.auth_info = data_blob_null;
1707 status = dcesrv_auth_prepare_alter_ack(call, pkt);
1708 if (!NT_STATUS_IS_OK(status)) {
1709 return dcesrv_fault_disconnect(call, DCERPC_FAULT_SEC_PKG_ERROR);
1712 if (auth->auth_finished) {
1713 return dcesrv_auth_reply(call);
1716 cb->auth.become_root();
1717 subreq = gensec_update_send(call, call->event_ctx,
1718 auth->gensec_security,
1719 call->in_auth_info.credentials);
1720 cb->auth.unbecome_root();
1721 if (subreq == NULL) {
1722 return NT_STATUS_NO_MEMORY;
1724 tevent_req_set_callback(subreq, dcesrv_alter_done, call);
1726 return dcesrv_conn_auth_wait_setup(conn);
1729 static void dcesrv_alter_done(struct tevent_req *subreq)
1731 struct dcesrv_call_state *call =
1732 tevent_req_callback_data(subreq,
1733 struct dcesrv_call_state);
1734 struct dcesrv_connection *conn = call->conn;
1735 struct dcesrv_context_callbacks *cb = call->conn->dce_ctx->callbacks;
1736 NTSTATUS status;
1738 cb->auth.become_root();
1739 status = gensec_update_recv(subreq, call,
1740 &call->out_auth_info->credentials);
1741 cb->auth.unbecome_root();
1742 TALLOC_FREE(subreq);
1744 status = dcesrv_auth_complete(call, status);
1745 if (!NT_STATUS_IS_OK(status)) {
1746 status = dcesrv_fault_disconnect(call, DCERPC_FAULT_SEC_PKG_ERROR);
1747 dcesrv_conn_auth_wait_finished(conn, status);
1748 return;
1751 status = dcesrv_auth_reply(call);
1752 dcesrv_conn_auth_wait_finished(conn, status);
1753 return;
1757 possibly save the call for inspection with ndrdump
1759 static void dcesrv_save_call(struct dcesrv_call_state *call, const char *why)
1761 #ifdef DEVELOPER
1762 dcerpc_log_packet(call->conn->packet_log_dir,
1763 call->context->iface->name,
1764 call->pkt.u.request.opnum,
1765 NDR_IN,
1766 &call->pkt.u.request.stub_and_verifier,
1767 why);
1768 #endif
1771 #ifdef DEVELOPER
1773 Save the call for use as a seed for fuzzing.
1775 This is only enabled in a developer build, and only has effect if the
1776 "dcesrv fuzz directory" param is set.
1778 void _dcesrv_save_ndr_fuzz_seed(DATA_BLOB call_blob,
1779 struct dcesrv_call_state *call,
1780 int flags)
1782 const char *dump_dir = lpcfg_parm_string(call->conn->dce_ctx->lp_ctx,
1783 NULL,
1784 "dcesrv", "fuzz directory");
1786 dcerpc_save_ndr_fuzz_seed(call,
1787 call_blob,
1788 dump_dir,
1789 call->context->iface->name,
1790 flags,
1791 call->pkt.u.request.opnum,
1792 call->ndr_pull->flags & LIBNDR_FLAG_NDR64);
1794 #endif /*if DEVELOPER, enveloping _dcesrv_save_ndr_fuzz_seed() */
1797 static NTSTATUS dcesrv_check_verification_trailer(struct dcesrv_call_state *call)
1799 TALLOC_CTX *frame = talloc_stackframe();
1800 const uint32_t bitmask1 = call->conn->client_hdr_signing ?
1801 DCERPC_SEC_VT_CLIENT_SUPPORTS_HEADER_SIGNING : 0;
1802 const struct dcerpc_sec_vt_pcontext pcontext = {
1803 .abstract_syntax = call->context->iface->syntax_id,
1804 .transfer_syntax = call->context->transfer_syntax,
1806 const struct dcerpc_sec_vt_header2 header2 =
1807 dcerpc_sec_vt_header2_from_ncacn_packet(&call->pkt);
1808 enum ndr_err_code ndr_err;
1809 struct dcerpc_sec_verification_trailer *vt = NULL;
1810 NTSTATUS status = NT_STATUS_OK;
1811 bool ok;
1813 SMB_ASSERT(call->pkt.ptype == DCERPC_PKT_REQUEST);
1815 ndr_err = ndr_pop_dcerpc_sec_verification_trailer(call->ndr_pull,
1816 frame, &vt);
1817 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
1818 status = ndr_map_error2ntstatus(ndr_err);
1819 goto done;
1822 ok = dcerpc_sec_verification_trailer_check(vt, &bitmask1,
1823 &pcontext, &header2);
1824 if (!ok) {
1825 status = NT_STATUS_ACCESS_DENIED;
1826 goto done;
1828 done:
1829 TALLOC_FREE(frame);
1830 return status;
1834 handle a dcerpc request packet
1836 static NTSTATUS dcesrv_request(struct dcesrv_call_state *call)
1838 const struct dcesrv_endpoint *endpoint = call->conn->endpoint;
1839 struct dcesrv_auth *auth = call->auth_state;
1840 enum dcerpc_transport_t transport =
1841 dcerpc_binding_get_transport(endpoint->ep_description);
1842 struct ndr_pull *pull;
1843 bool turn_winbind_on = false;
1844 NTSTATUS status;
1846 if (auth->auth_invalid) {
1847 return dcesrv_fault_disconnect(call, DCERPC_NCA_S_PROTO_ERROR);
1850 if (!auth->auth_finished) {
1851 return dcesrv_fault_disconnect(call, DCERPC_NCA_S_PROTO_ERROR);
1854 /* if authenticated, and the mech we use can't do async replies, don't use them... */
1855 if (auth->gensec_security != NULL &&
1856 !gensec_have_feature(auth->gensec_security, GENSEC_FEATURE_ASYNC_REPLIES)) {
1857 call->state_flags &= ~DCESRV_CALL_STATE_FLAG_MAY_ASYNC;
1860 if (call->context == NULL) {
1861 return dcesrv_fault_with_flags(call, DCERPC_NCA_S_UNKNOWN_IF,
1862 DCERPC_PFC_FLAG_DID_NOT_EXECUTE);
1865 switch (auth->auth_level) {
1866 case DCERPC_AUTH_LEVEL_NONE:
1867 case DCERPC_AUTH_LEVEL_PACKET:
1868 case DCERPC_AUTH_LEVEL_INTEGRITY:
1869 case DCERPC_AUTH_LEVEL_PRIVACY:
1870 break;
1871 default:
1872 if (!call->context->allow_connect) {
1873 char *addr;
1875 addr = tsocket_address_string(call->conn->remote_address,
1876 call);
1878 DEBUG(2, ("%s: restrict auth_level_connect access "
1879 "to [%s] with auth[type=0x%x,level=0x%x] "
1880 "on [%s] from [%s]\n",
1881 __func__, call->context->iface->name,
1882 auth->auth_type,
1883 auth->auth_level,
1884 derpc_transport_string_by_transport(transport),
1885 addr));
1886 return dcesrv_fault(call, DCERPC_FAULT_ACCESS_DENIED);
1888 break;
1891 if (auth->auth_level < call->context->min_auth_level) {
1892 char *addr;
1894 addr = tsocket_address_string(call->conn->remote_address, call);
1896 DEBUG(2, ("%s: restrict access by min_auth_level[0x%x] "
1897 "to [%s] with auth[type=0x%x,level=0x%x] "
1898 "on [%s] from [%s]\n",
1899 __func__,
1900 call->context->min_auth_level,
1901 call->context->iface->name,
1902 auth->auth_type,
1903 auth->auth_level,
1904 derpc_transport_string_by_transport(transport),
1905 addr));
1906 return dcesrv_fault(call, DCERPC_FAULT_ACCESS_DENIED);
1909 pull = ndr_pull_init_blob(&call->pkt.u.request.stub_and_verifier, call);
1910 NT_STATUS_HAVE_NO_MEMORY(pull);
1912 pull->flags |= LIBNDR_FLAG_REF_ALLOC;
1914 call->ndr_pull = pull;
1916 if (!(call->pkt.drep[0] & DCERPC_DREP_LE)) {
1917 pull->flags |= LIBNDR_FLAG_BIGENDIAN;
1920 status = dcesrv_check_verification_trailer(call);
1921 if (!NT_STATUS_IS_OK(status)) {
1922 uint32_t faultcode = DCERPC_FAULT_OTHER;
1923 if (NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
1924 faultcode = DCERPC_FAULT_ACCESS_DENIED;
1926 DEBUG(10, ("dcesrv_check_verification_trailer failed: %s\n",
1927 nt_errstr(status)));
1928 return dcesrv_fault(call, faultcode);
1931 /* unravel the NDR for the packet */
1932 status = call->context->iface->ndr_pull(call, call, pull, &call->r);
1933 if (!NT_STATUS_IS_OK(status)) {
1934 uint8_t extra_flags = 0;
1935 if (call->fault_code == DCERPC_FAULT_OP_RNG_ERROR) {
1936 /* we got an unknown call */
1937 DEBUG(3,(__location__ ": Unknown RPC call %u on %s\n",
1938 call->pkt.u.request.opnum,
1939 call->context->iface->name));
1940 dcesrv_save_call(call, "unknown");
1941 extra_flags |= DCERPC_PFC_FLAG_DID_NOT_EXECUTE;
1942 } else {
1943 dcesrv_save_call(call, "pullfail");
1946 return dcesrv_fault_with_flags(call, call->fault_code, extra_flags);
1949 dcesrv_save_ndr_fuzz_seed(call->pkt.u.request.stub_and_verifier,
1950 call,
1951 NDR_IN);
1953 if (pull->offset != pull->data_size) {
1954 dcesrv_save_call(call, "extrabytes");
1955 DEBUG(3,("Warning: %d extra bytes in incoming RPC request\n",
1956 pull->data_size - pull->offset));
1959 if (call->state_flags & DCESRV_CALL_STATE_FLAG_WINBIND_OFF) {
1960 bool winbind_active = !winbind_env_set();
1961 if (winbind_active) {
1962 DBG_DEBUG("turning winbind off\n");
1963 (void)winbind_off();
1964 turn_winbind_on = true;
1968 /* call the dispatch function */
1969 status = call->context->iface->dispatch(call, call, call->r);
1971 if (turn_winbind_on) {
1972 DBG_DEBUG("turning winbind on\n");
1973 (void)winbind_on();
1976 if (!NT_STATUS_IS_OK(status)) {
1977 DEBUG(5,("dcerpc fault in call %s:%02x - %s\n",
1978 call->context->iface->name,
1979 call->pkt.u.request.opnum,
1980 dcerpc_errstr(pull, call->fault_code)));
1981 return dcesrv_fault(call, call->fault_code);
1984 /* add the call to the pending list */
1985 dcesrv_call_set_list(call, DCESRV_LIST_PENDING_CALL_LIST);
1987 if (call->state_flags & DCESRV_CALL_STATE_FLAG_ASYNC) {
1988 return NT_STATUS_OK;
1991 return dcesrv_reply(call);
1996 remove the call from the right list when freed
1998 static int dcesrv_call_dequeue(struct dcesrv_call_state *call)
2000 dcesrv_call_set_list(call, DCESRV_LIST_NONE);
2001 return 0;
2004 _PUBLIC_ const struct tsocket_address *dcesrv_connection_get_local_address(struct dcesrv_connection *conn)
2006 return conn->local_address;
2009 _PUBLIC_ const struct tsocket_address *dcesrv_connection_get_remote_address(struct dcesrv_connection *conn)
2011 return conn->remote_address;
2015 process some input to a dcerpc endpoint server.
2017 static NTSTATUS dcesrv_process_ncacn_packet(struct dcesrv_connection *dce_conn,
2018 struct ncacn_packet *pkt,
2019 DATA_BLOB blob)
2021 NTSTATUS status;
2022 struct dcesrv_call_state *call;
2023 struct dcesrv_call_state *existing = NULL;
2024 size_t num_auth_ctx = 0;
2025 enum dcerpc_AuthType auth_type = 0;
2026 enum dcerpc_AuthLevel auth_level = 0;
2027 uint32_t auth_context_id = 0;
2028 bool auth_invalid = false;
2030 call = talloc_zero(dce_conn, struct dcesrv_call_state);
2031 if (!call) {
2032 data_blob_free(&blob);
2033 talloc_free(pkt);
2034 return NT_STATUS_NO_MEMORY;
2036 call->conn = dce_conn;
2037 call->event_ctx = dce_conn->event_ctx;
2038 call->state_flags = call->conn->state_flags;
2039 call->time = timeval_current();
2040 call->list = DCESRV_LIST_NONE;
2042 talloc_steal(call, pkt);
2043 talloc_steal(call, blob.data);
2044 call->pkt = *pkt;
2046 if (dce_conn->max_auth_states == 0) {
2047 call->auth_state = dce_conn->default_auth_state;
2048 } else if (call->pkt.auth_length == 0) {
2049 if (call->pkt.ptype == DCERPC_PKT_REQUEST &&
2050 dce_conn->default_auth_level_connect != NULL)
2052 call->auth_state = dce_conn->default_auth_level_connect;
2053 } else {
2054 call->auth_state = dce_conn->default_auth_state;
2058 if (call->auth_state == NULL) {
2059 struct dcesrv_auth *a = NULL;
2060 bool check_type_level = true;
2062 auth_type = dcerpc_get_auth_type(&blob);
2063 auth_level = dcerpc_get_auth_level(&blob);
2064 auth_context_id = dcerpc_get_auth_context_id(&blob);
2066 if (call->pkt.ptype == DCERPC_PKT_REQUEST) {
2067 if (!(call->pkt.pfc_flags & DCERPC_PFC_FLAG_FIRST)) {
2068 check_type_level = false;
2070 dce_conn->default_auth_level_connect = NULL;
2071 if (auth_level == DCERPC_AUTH_LEVEL_CONNECT) {
2072 dce_conn->got_explicit_auth_level_connect = true;
2076 for (a = dce_conn->auth_states; a != NULL; a = a->next) {
2077 num_auth_ctx++;
2079 if (a->auth_context_id != auth_context_id) {
2080 continue;
2083 if (a->auth_type != auth_type) {
2084 auth_invalid = true;
2086 if (a->auth_level != auth_level) {
2087 auth_invalid = true;
2090 if (check_type_level && auth_invalid) {
2091 a->auth_invalid = true;
2094 DLIST_PROMOTE(dce_conn->auth_states, a);
2095 call->auth_state = a;
2096 break;
2100 if (call->auth_state == NULL) {
2101 struct dcesrv_auth *a = NULL;
2103 if (num_auth_ctx >= dce_conn->max_auth_states) {
2104 return dcesrv_fault_disconnect(call,
2105 DCERPC_NCA_S_PROTO_ERROR);
2108 a = dcesrv_auth_create(dce_conn);
2109 if (a == NULL) {
2110 talloc_free(call);
2111 return NT_STATUS_NO_MEMORY;
2113 DLIST_ADD(dce_conn->auth_states, a);
2114 if (call->pkt.ptype == DCERPC_PKT_REQUEST) {
2116 * This can never be valid.
2118 auth_invalid = true;
2119 a->auth_invalid = true;
2121 call->auth_state = a;
2124 talloc_set_destructor(call, dcesrv_call_dequeue);
2126 if (call->conn->allow_bind) {
2128 * Only one bind is possible per connection
2130 call->conn->allow_bind = false;
2131 return dcesrv_bind(call);
2134 /* we have to check the signing here, before combining the
2135 pdus */
2136 if (call->pkt.ptype == DCERPC_PKT_REQUEST) {
2137 dcesrv_default_auth_state_prepare_request(call);
2139 if (call->auth_state->auth_started &&
2140 !call->auth_state->auth_finished) {
2141 return dcesrv_fault_disconnect(call,
2142 DCERPC_NCA_S_PROTO_ERROR);
2145 status = dcerpc_verify_ncacn_packet_header(&call->pkt,
2146 DCERPC_PKT_REQUEST,
2147 call->pkt.u.request.stub_and_verifier.length,
2148 0, /* required_flags */
2149 DCERPC_PFC_FLAG_FIRST |
2150 DCERPC_PFC_FLAG_LAST |
2151 DCERPC_PFC_FLAG_PENDING_CANCEL |
2152 0x08 | /* this is not defined, but should be ignored */
2153 DCERPC_PFC_FLAG_CONC_MPX |
2154 DCERPC_PFC_FLAG_DID_NOT_EXECUTE |
2155 DCERPC_PFC_FLAG_MAYBE |
2156 DCERPC_PFC_FLAG_OBJECT_UUID);
2157 if (!NT_STATUS_IS_OK(status)) {
2158 return dcesrv_fault_disconnect(call,
2159 DCERPC_NCA_S_PROTO_ERROR);
2162 if (call->pkt.frag_length > DCERPC_FRAG_MAX_SIZE) {
2164 * We don't use dcesrv_fault_disconnect()
2165 * here, because we don't want to set
2166 * DCERPC_PFC_FLAG_DID_NOT_EXECUTE
2168 * Note that we don't check against the negotiated
2169 * max_recv_frag, but a hard coded value.
2171 return dcesrv_fault_disconnect0(call, DCERPC_NCA_S_PROTO_ERROR);
2174 if (call->pkt.pfc_flags & DCERPC_PFC_FLAG_FIRST) {
2175 if (dce_conn->pending_call_list != NULL) {
2177 * concurrent requests are only allowed
2178 * if DCERPC_PFC_FLAG_CONC_MPX was negotiated.
2180 if (!(dce_conn->state_flags & DCESRV_CALL_STATE_FLAG_MULTIPLEXED)) {
2181 return dcesrv_fault_disconnect0(call,
2182 DCERPC_NCA_S_PROTO_ERROR);
2185 /* only one request is possible in the fragmented list */
2186 if (dce_conn->incoming_fragmented_call_list != NULL) {
2187 call->fault_code = DCERPC_NCA_S_PROTO_ERROR;
2189 existing = dcesrv_find_fragmented_call(dce_conn,
2190 call->pkt.call_id);
2191 if (existing != NULL && call->auth_state != existing->auth_state) {
2192 call->context = dcesrv_find_context(call->conn,
2193 call->pkt.u.request.context_id);
2195 if (call->pkt.auth_length != 0 && existing->context == call->context) {
2196 call->fault_code = DCERPC_FAULT_SEC_PKG_ERROR;
2199 if (!(dce_conn->state_flags & DCESRV_CALL_STATE_FLAG_MULTIPLEXED)) {
2201 * Without DCERPC_PFC_FLAG_CONC_MPX
2202 * we need to return the FAULT on the
2203 * already existing call.
2205 * This is important to get the
2206 * call_id and context_id right.
2208 dce_conn->incoming_fragmented_call_list->fault_code = call->fault_code;
2209 TALLOC_FREE(call);
2210 call = dce_conn->incoming_fragmented_call_list;
2212 if (existing != NULL) {
2213 call->context = existing->context;
2215 return dcesrv_fault_disconnect0(call, call->fault_code);
2217 if (call->pkt.pfc_flags & DCERPC_PFC_FLAG_PENDING_CANCEL) {
2218 return dcesrv_fault_disconnect(call,
2219 DCERPC_FAULT_NO_CALL_ACTIVE);
2221 call->context = dcesrv_find_context(call->conn,
2222 call->pkt.u.request.context_id);
2223 if (call->context == NULL) {
2224 return dcesrv_fault_with_flags(call, DCERPC_NCA_S_UNKNOWN_IF,
2225 DCERPC_PFC_FLAG_DID_NOT_EXECUTE);
2227 } else {
2228 int cmp;
2230 existing = dcesrv_find_fragmented_call(dce_conn,
2231 call->pkt.call_id);
2232 if (existing == NULL) {
2233 if (!(dce_conn->state_flags & DCESRV_CALL_STATE_FLAG_MULTIPLEXED)) {
2235 * Without DCERPC_PFC_FLAG_CONC_MPX
2236 * we need to return the FAULT on the
2237 * already existing call.
2239 * This is important to get the
2240 * call_id and context_id right.
2242 if (dce_conn->incoming_fragmented_call_list != NULL) {
2243 TALLOC_FREE(call);
2244 call = dce_conn->incoming_fragmented_call_list;
2246 return dcesrv_fault_disconnect0(call,
2247 DCERPC_NCA_S_PROTO_ERROR);
2249 if (dce_conn->incoming_fragmented_call_list != NULL) {
2250 return dcesrv_fault_disconnect0(call, DCERPC_NCA_S_PROTO_ERROR);
2252 call->context = dcesrv_find_context(call->conn,
2253 call->pkt.u.request.context_id);
2254 if (call->context == NULL) {
2255 return dcesrv_fault_with_flags(call, DCERPC_NCA_S_UNKNOWN_IF,
2256 DCERPC_PFC_FLAG_DID_NOT_EXECUTE);
2258 if (auth_invalid) {
2259 return dcesrv_fault_disconnect0(call,
2260 DCERPC_FAULT_ACCESS_DENIED);
2262 return dcesrv_fault_disconnect0(call,
2263 DCERPC_NCA_S_PROTO_ERROR);
2266 if (call->pkt.ptype != existing->pkt.ptype) {
2267 /* trying to play silly buggers are we? */
2268 return dcesrv_fault_disconnect(existing,
2269 DCERPC_NCA_S_PROTO_ERROR);
2271 cmp = memcmp(call->pkt.drep, existing->pkt.drep,
2272 sizeof(pkt->drep));
2273 if (cmp != 0) {
2274 return dcesrv_fault_disconnect(existing,
2275 DCERPC_NCA_S_PROTO_ERROR);
2277 call->auth_state = existing->auth_state;
2278 call->context = existing->context;
2282 if (call->pkt.ptype == DCERPC_PKT_REQUEST) {
2283 bool ok;
2284 uint8_t payload_offset = DCERPC_REQUEST_LENGTH;
2286 if (call->pkt.pfc_flags & DCERPC_PFC_FLAG_OBJECT_UUID) {
2287 payload_offset += 16;
2290 ok = dcesrv_auth_pkt_pull(call, &blob,
2291 0, /* required_flags */
2292 DCERPC_PFC_FLAG_FIRST |
2293 DCERPC_PFC_FLAG_LAST |
2294 DCERPC_PFC_FLAG_PENDING_CANCEL |
2295 0x08 | /* this is not defined, but should be ignored */
2296 DCERPC_PFC_FLAG_CONC_MPX |
2297 DCERPC_PFC_FLAG_DID_NOT_EXECUTE |
2298 DCERPC_PFC_FLAG_MAYBE |
2299 DCERPC_PFC_FLAG_OBJECT_UUID,
2300 payload_offset,
2301 &call->pkt.u.request.stub_and_verifier);
2302 if (!ok) {
2304 * We don't use dcesrv_fault_disconnect()
2305 * here, because we don't want to set
2306 * DCERPC_PFC_FLAG_DID_NOT_EXECUTE
2308 if (call->fault_code == 0) {
2309 call->fault_code = DCERPC_FAULT_ACCESS_DENIED;
2311 return dcesrv_fault_disconnect0(call, call->fault_code);
2315 /* see if this is a continued packet */
2316 if (existing != NULL) {
2317 struct dcerpc_request *er = &existing->pkt.u.request;
2318 const struct dcerpc_request *nr = &call->pkt.u.request;
2319 size_t available;
2320 size_t alloc_size;
2321 size_t alloc_hint;
2324 * Up to 4 MByte are allowed by all fragments
2326 available = dce_conn->max_total_request_size;
2327 if (er->stub_and_verifier.length > available) {
2328 return dcesrv_fault_disconnect0(existing,
2329 DCERPC_FAULT_ACCESS_DENIED);
2331 available -= er->stub_and_verifier.length;
2332 if (nr->alloc_hint > available) {
2333 return dcesrv_fault_disconnect0(existing,
2334 DCERPC_FAULT_ACCESS_DENIED);
2336 if (nr->stub_and_verifier.length > available) {
2337 return dcesrv_fault_disconnect0(existing,
2338 DCERPC_FAULT_ACCESS_DENIED);
2340 alloc_hint = er->stub_and_verifier.length + nr->alloc_hint;
2341 /* allocate at least 1 byte */
2342 alloc_hint = MAX(alloc_hint, 1);
2343 alloc_size = er->stub_and_verifier.length +
2344 nr->stub_and_verifier.length;
2345 alloc_size = MAX(alloc_size, alloc_hint);
2347 er->stub_and_verifier.data =
2348 talloc_realloc(existing,
2349 er->stub_and_verifier.data,
2350 uint8_t, alloc_size);
2351 if (er->stub_and_verifier.data == NULL) {
2352 TALLOC_FREE(call);
2353 return dcesrv_fault_with_flags(existing,
2354 DCERPC_FAULT_OUT_OF_RESOURCES,
2355 DCERPC_PFC_FLAG_DID_NOT_EXECUTE);
2357 memcpy(er->stub_and_verifier.data +
2358 er->stub_and_verifier.length,
2359 nr->stub_and_verifier.data,
2360 nr->stub_and_verifier.length);
2361 er->stub_and_verifier.length += nr->stub_and_verifier.length;
2363 existing->pkt.pfc_flags |= (call->pkt.pfc_flags & DCERPC_PFC_FLAG_LAST);
2365 TALLOC_FREE(call);
2366 call = existing;
2369 /* this may not be the last pdu in the chain - if its isn't then
2370 just put it on the incoming_fragmented_call_list and wait for the rest */
2371 if (call->pkt.ptype == DCERPC_PKT_REQUEST &&
2372 !(call->pkt.pfc_flags & DCERPC_PFC_FLAG_LAST)) {
2374 * Up to 4 MByte are allowed by all fragments
2376 if (call->pkt.u.request.alloc_hint > dce_conn->max_total_request_size) {
2377 return dcesrv_fault_disconnect0(call,
2378 DCERPC_FAULT_ACCESS_DENIED);
2380 dcesrv_call_set_list(call, DCESRV_LIST_FRAGMENTED_CALL_LIST);
2381 return NT_STATUS_OK;
2384 /* This removes any fragments we may have had stashed away */
2385 dcesrv_call_set_list(call, DCESRV_LIST_NONE);
2387 switch (call->pkt.ptype) {
2388 case DCERPC_PKT_BIND:
2389 status = dcesrv_bind_nak(call,
2390 DCERPC_BIND_NAK_REASON_NOT_SPECIFIED);
2391 break;
2392 case DCERPC_PKT_AUTH3:
2393 status = dcesrv_auth3(call);
2394 break;
2395 case DCERPC_PKT_ALTER:
2396 status = dcesrv_alter(call);
2397 break;
2398 case DCERPC_PKT_REQUEST:
2399 status = dcesrv_request(call);
2400 break;
2401 case DCERPC_PKT_CO_CANCEL:
2402 case DCERPC_PKT_ORPHANED:
2404 * Window just ignores CO_CANCEL and ORPHANED,
2405 * so we do...
2407 status = NT_STATUS_OK;
2408 TALLOC_FREE(call);
2409 break;
2410 case DCERPC_PKT_BIND_ACK:
2411 case DCERPC_PKT_BIND_NAK:
2412 case DCERPC_PKT_ALTER_RESP:
2413 case DCERPC_PKT_RESPONSE:
2414 case DCERPC_PKT_FAULT:
2415 case DCERPC_PKT_SHUTDOWN:
2416 default:
2417 status = dcesrv_fault_disconnect(call, DCERPC_NCA_S_PROTO_ERROR);
2418 break;
2421 /* if we are going to be sending a reply then add
2422 it to the list of pending calls. We add it to the end to keep the call
2423 list in the order we will answer */
2424 if (!NT_STATUS_IS_OK(status)) {
2425 talloc_free(call);
2428 return status;
2431 _PUBLIC_ NTSTATUS dcesrv_init_context(TALLOC_CTX *mem_ctx,
2432 struct loadparm_context *lp_ctx,
2433 struct dcesrv_context_callbacks *cb,
2434 struct dcesrv_context **_dce_ctx)
2436 struct dcesrv_context *dce_ctx;
2438 if (cb == NULL) {
2439 return NT_STATUS_INVALID_PARAMETER;
2442 dce_ctx = talloc_zero(mem_ctx, struct dcesrv_context);
2443 NT_STATUS_HAVE_NO_MEMORY(dce_ctx);
2445 if (uid_wrapper_enabled()) {
2446 setenv("UID_WRAPPER_MYUID", "1", 1);
2448 dce_ctx->initial_euid = geteuid();
2449 if (uid_wrapper_enabled()) {
2450 unsetenv("UID_WRAPPER_MYUID");
2453 dce_ctx->endpoint_list = NULL;
2454 dce_ctx->lp_ctx = lp_ctx;
2455 dce_ctx->assoc_groups_idr = idr_init(dce_ctx);
2456 if (dce_ctx->assoc_groups_idr == NULL) {
2457 TALLOC_FREE(dce_ctx);
2458 return NT_STATUS_NO_MEMORY;
2460 dce_ctx->broken_connections = NULL;
2461 dce_ctx->callbacks = cb;
2463 *_dce_ctx = dce_ctx;
2464 return NT_STATUS_OK;
2468 * @brief Set callback functions on an existing dcesrv_context
2470 * This allows to reset callbacks initially set via
2471 * dcesrv_init_context()
2473 * @param[in] dce_ctx The context to set the callbacks on
2474 * @param[in] cb The callbacks to set on dce_ctx
2476 _PUBLIC_ void dcesrv_context_set_callbacks(
2477 struct dcesrv_context *dce_ctx,
2478 struct dcesrv_context_callbacks *cb)
2480 dce_ctx->callbacks = cb;
2483 _PUBLIC_ NTSTATUS dcesrv_init_ep_servers(struct dcesrv_context *dce_ctx,
2484 const char **endpoint_servers)
2486 NTSTATUS status;
2487 int i;
2489 if (endpoint_servers == NULL) {
2490 DBG_ERR("No endpoint servers configured\n");
2491 return NT_STATUS_INTERNAL_ERROR;
2494 for (i=0;endpoint_servers[i];i++) {
2495 status = dcesrv_init_ep_server(dce_ctx, endpoint_servers[i]);
2496 if (!NT_STATUS_IS_OK(status)) {
2497 DBG_ERR("failed to init endpoint server = '%s': %s\n",
2498 endpoint_servers[i], nt_errstr(status));
2499 return status;
2503 return NT_STATUS_OK;
2506 /* the list of currently registered DCERPC endpoint servers.
2508 static struct ep_server {
2509 struct dcesrv_endpoint_server *ep_server;
2510 } *ep_servers = NULL;
2511 static int num_ep_servers = 0;
2513 _PUBLIC_ NTSTATUS dcesrv_init_registered_ep_servers(
2514 struct dcesrv_context *dce_ctx)
2516 NTSTATUS status;
2517 int i;
2519 for (i = 0; i < num_ep_servers; i++) {
2520 status = dcesrv_init_ep_server(dce_ctx,
2521 ep_servers[i].ep_server->name);
2522 if (!NT_STATUS_IS_OK(status)) {
2523 return status;
2527 return NT_STATUS_OK;
2530 _PUBLIC_ NTSTATUS dcesrv_init_ep_server(struct dcesrv_context *dce_ctx,
2531 const char *ep_server_name)
2533 struct dcesrv_endpoint_server *ep_server = NULL;
2534 NTSTATUS status;
2536 ep_server = discard_const_p(struct dcesrv_endpoint_server,
2537 dcesrv_ep_server_byname(ep_server_name));
2538 if (ep_server == NULL) {
2539 DBG_ERR("Failed to find endpoint server '%s'\n",
2540 ep_server_name);
2541 return NT_STATUS_INTERNAL_ERROR;
2544 if (ep_server->initialized) {
2545 return NT_STATUS_OK;
2548 status = ep_server->init_server(dce_ctx, ep_server);
2549 if (!NT_STATUS_IS_OK(status)) {
2550 DBG_ERR("Failed to init endpoint server '%s': %s\n",
2551 ep_server_name, nt_errstr(status));
2552 return status;
2555 ep_server->initialized = true;
2557 return NT_STATUS_OK;
2560 _PUBLIC_ NTSTATUS dcesrv_shutdown_registered_ep_servers(
2561 struct dcesrv_context *dce_ctx)
2563 NTSTATUS status;
2564 int i;
2566 for (i = 0; i < num_ep_servers; i++) {
2567 status = dcesrv_shutdown_ep_server(dce_ctx,
2568 ep_servers[i].ep_server->name);
2569 if (!NT_STATUS_IS_OK(status)) {
2570 return status;
2574 return NT_STATUS_OK;
2577 _PUBLIC_ NTSTATUS dcesrv_shutdown_ep_server(struct dcesrv_context *dce_ctx,
2578 const char *ep_server_name)
2580 struct dcesrv_endpoint_server *ep_server = NULL;
2581 NTSTATUS status;
2583 ep_server = discard_const_p(struct dcesrv_endpoint_server,
2584 dcesrv_ep_server_byname(ep_server_name));
2585 if (ep_server == NULL) {
2586 DBG_ERR("Failed to find endpoint server '%s'\n",
2587 ep_server_name);
2588 return NT_STATUS_INTERNAL_ERROR;
2591 if (!ep_server->initialized) {
2592 return NT_STATUS_OK;
2595 DBG_INFO("Shutting down DCE/RPC endpoint server '%s'\n",
2596 ep_server_name);
2598 status = ep_server->shutdown_server(dce_ctx, ep_server);
2599 if (!NT_STATUS_IS_OK(status)) {
2600 DBG_ERR("Failed to shutdown endpoint server '%s': %s\n",
2601 ep_server_name, nt_errstr(status));
2602 return status;
2605 ep_server->initialized = false;
2607 return NT_STATUS_OK;
2611 register a DCERPC endpoint server.
2613 The 'name' can be later used by other backends to find the operations
2614 structure for this backend.
2617 _PUBLIC_ NTSTATUS dcerpc_register_ep_server(const struct dcesrv_endpoint_server *ep_server)
2620 if (dcesrv_ep_server_byname(ep_server->name) != NULL) {
2621 /* its already registered! */
2622 DEBUG(0,("DCERPC endpoint server '%s' already registered\n",
2623 ep_server->name));
2624 return NT_STATUS_OBJECT_NAME_COLLISION;
2627 ep_servers = realloc_p(ep_servers, struct ep_server, num_ep_servers+1);
2628 if (!ep_servers) {
2629 smb_panic("out of memory in dcerpc_register");
2632 ep_servers[num_ep_servers].ep_server = smb_xmemdup(ep_server, sizeof(*ep_server));
2633 ep_servers[num_ep_servers].ep_server->name = smb_xstrdup(ep_server->name);
2635 num_ep_servers++;
2637 DEBUG(3,("DCERPC endpoint server '%s' registered\n",
2638 ep_server->name));
2640 return NT_STATUS_OK;
2644 return the operations structure for a named backend of the specified type
2646 _PUBLIC_ const struct dcesrv_endpoint_server *dcesrv_ep_server_byname(const char *name)
2648 int i;
2650 for (i=0;i<num_ep_servers;i++) {
2651 if (strcmp(ep_servers[i].ep_server->name, name) == 0) {
2652 return ep_servers[i].ep_server;
2656 return NULL;
2660 return the DCERPC module version, and the size of some critical types
2661 This can be used by endpoint server modules to either detect compilation errors, or provide
2662 multiple implementations for different smbd compilation options in one module
2664 const struct dcesrv_critical_sizes *dcerpc_module_version(void)
2666 static const struct dcesrv_critical_sizes critical_sizes = {
2667 DCERPC_MODULE_VERSION,
2668 sizeof(struct dcesrv_context),
2669 sizeof(struct dcesrv_endpoint),
2670 sizeof(struct dcesrv_endpoint_server),
2671 sizeof(struct dcesrv_interface),
2672 sizeof(struct dcesrv_if_list),
2673 sizeof(struct dcesrv_connection),
2674 sizeof(struct dcesrv_call_state),
2675 sizeof(struct dcesrv_auth),
2676 sizeof(struct dcesrv_handle)
2679 return &critical_sizes;
2682 _PUBLIC_ void dcesrv_terminate_connection(struct dcesrv_connection *dce_conn, const char *reason)
2684 struct dcesrv_context *dce_ctx = dce_conn->dce_ctx;
2685 struct dcesrv_auth *a = NULL;
2687 dce_conn->wait_send = NULL;
2688 dce_conn->wait_recv = NULL;
2689 dce_conn->wait_private = NULL;
2691 dce_conn->allow_bind = false;
2692 dce_conn->allow_alter = false;
2694 dce_conn->default_auth_state->auth_invalid = true;
2696 for (a = dce_conn->auth_states; a != NULL; a = a->next) {
2697 a->auth_invalid = true;
2700 if (dce_conn->pending_call_list == NULL) {
2701 char *full_reason = talloc_asprintf(dce_conn, "dcesrv: %s", reason);
2703 DLIST_REMOVE(dce_ctx->broken_connections, dce_conn);
2704 dce_conn->transport.terminate_connection(dce_conn,
2705 full_reason ? full_reason : reason);
2706 return;
2709 if (dce_conn->terminate != NULL) {
2710 return;
2713 DEBUG(3,("dcesrv: terminating connection due to '%s' deferred due to pending calls\n",
2714 reason));
2715 dce_conn->terminate = talloc_strdup(dce_conn, reason);
2716 if (dce_conn->terminate == NULL) {
2717 dce_conn->terminate = "dcesrv: deferred terminating connection - no memory";
2719 DLIST_ADD_END(dce_ctx->broken_connections, dce_conn);
2722 _PUBLIC_ void dcesrv_cleanup_broken_connections(struct dcesrv_context *dce_ctx)
2724 struct dcesrv_connection *cur, *next;
2726 next = dce_ctx->broken_connections;
2727 while (next != NULL) {
2728 cur = next;
2729 next = cur->next;
2731 if (cur->state_flags & DCESRV_CALL_STATE_FLAG_PROCESS_PENDING_CALL) {
2732 struct dcesrv_connection_context *context_cur, *context_next;
2734 context_next = cur->contexts;
2735 while (context_next != NULL) {
2736 context_cur = context_next;
2737 context_next = context_cur->next;
2739 dcesrv_connection_context_destructor(context_cur);
2743 dcesrv_terminate_connection(cur, cur->terminate);
2747 struct dcesrv_sock_reply_state {
2748 struct dcesrv_connection *dce_conn;
2749 struct dcesrv_call_state *call;
2750 struct iovec iov;
2753 static void dcesrv_sock_reply_done(struct tevent_req *subreq);
2754 static void dcesrv_call_terminate_step1(struct tevent_req *subreq);
2756 _PUBLIC_ void dcesrv_sock_report_output_data(struct dcesrv_connection *dce_conn)
2758 struct dcesrv_call_state *call;
2760 call = dce_conn->call_list;
2761 if (!call || !call->replies) {
2762 return;
2765 while (call->replies) {
2766 struct data_blob_list_item *rep = call->replies;
2767 struct dcesrv_sock_reply_state *substate;
2768 struct tevent_req *subreq;
2770 substate = talloc_zero(call, struct dcesrv_sock_reply_state);
2771 if (!substate) {
2772 dcesrv_terminate_connection(dce_conn, "no memory");
2773 return;
2776 substate->dce_conn = dce_conn;
2777 substate->call = NULL;
2779 DLIST_REMOVE(call->replies, rep);
2781 if (call->replies == NULL && call->terminate_reason == NULL) {
2782 substate->call = call;
2785 substate->iov.iov_base = (void *) rep->blob.data;
2786 substate->iov.iov_len = rep->blob.length;
2788 subreq = tstream_writev_queue_send(substate,
2789 dce_conn->event_ctx,
2790 dce_conn->stream,
2791 dce_conn->send_queue,
2792 &substate->iov, 1);
2793 if (!subreq) {
2794 dcesrv_terminate_connection(dce_conn, "no memory");
2795 return;
2797 tevent_req_set_callback(subreq, dcesrv_sock_reply_done,
2798 substate);
2801 if (call->terminate_reason != NULL) {
2802 struct tevent_req *subreq;
2804 subreq = tevent_queue_wait_send(call,
2805 dce_conn->event_ctx,
2806 dce_conn->send_queue);
2807 if (!subreq) {
2808 dcesrv_terminate_connection(dce_conn, __location__);
2809 return;
2811 tevent_req_set_callback(subreq, dcesrv_call_terminate_step1,
2812 call);
2815 DLIST_REMOVE(call->conn->call_list, call);
2816 call->list = DCESRV_LIST_NONE;
2819 static void dcesrv_sock_reply_done(struct tevent_req *subreq)
2821 struct dcesrv_sock_reply_state *substate = tevent_req_callback_data(subreq,
2822 struct dcesrv_sock_reply_state);
2823 int ret;
2824 int sys_errno;
2825 NTSTATUS status;
2826 struct dcesrv_call_state *call = substate->call;
2828 ret = tstream_writev_queue_recv(subreq, &sys_errno);
2829 TALLOC_FREE(subreq);
2830 if (ret == -1) {
2831 status = map_nt_error_from_unix_common(sys_errno);
2832 dcesrv_terminate_connection(substate->dce_conn, nt_errstr(status));
2833 return;
2836 talloc_free(substate);
2837 if (call) {
2838 talloc_free(call);
2842 static void dcesrv_call_terminate_step2(struct tevent_req *subreq);
2844 static void dcesrv_call_terminate_step1(struct tevent_req *subreq)
2846 struct dcesrv_call_state *call = tevent_req_callback_data(subreq,
2847 struct dcesrv_call_state);
2848 bool ok;
2849 struct timeval tv;
2851 /* make sure we stop send queue before removing subreq */
2852 tevent_queue_stop(call->conn->send_queue);
2854 ok = tevent_queue_wait_recv(subreq);
2855 TALLOC_FREE(subreq);
2856 if (!ok) {
2857 dcesrv_terminate_connection(call->conn, __location__);
2858 return;
2861 /* disconnect after 200 usecs */
2862 tv = timeval_current_ofs_usec(200);
2863 subreq = tevent_wakeup_send(call, call->conn->event_ctx, tv);
2864 if (subreq == NULL) {
2865 dcesrv_terminate_connection(call->conn, __location__);
2866 return;
2868 tevent_req_set_callback(subreq, dcesrv_call_terminate_step2,
2869 call);
2872 static void dcesrv_call_terminate_step2(struct tevent_req *subreq)
2874 struct dcesrv_call_state *call = tevent_req_callback_data(subreq,
2875 struct dcesrv_call_state);
2876 bool ok;
2878 ok = tevent_wakeup_recv(subreq);
2879 TALLOC_FREE(subreq);
2880 if (!ok) {
2881 dcesrv_terminate_connection(call->conn, __location__);
2882 return;
2885 dcesrv_terminate_connection(call->conn, call->terminate_reason);
2888 static void dcesrv_conn_wait_done(struct tevent_req *subreq);
2890 static void dcesrv_read_fragment_done(struct tevent_req *subreq)
2892 struct dcesrv_connection *dce_conn = tevent_req_callback_data(subreq,
2893 struct dcesrv_connection);
2894 struct dcesrv_context *dce_ctx = dce_conn->dce_ctx;
2895 struct ncacn_packet *pkt;
2896 DATA_BLOB buffer;
2897 NTSTATUS status;
2899 if (dce_conn->terminate) {
2901 * if the current connection is broken
2902 * we need to clean it up before any other connection
2904 dcesrv_terminate_connection(dce_conn, dce_conn->terminate);
2905 dcesrv_cleanup_broken_connections(dce_ctx);
2906 return;
2909 dcesrv_cleanup_broken_connections(dce_ctx);
2911 status = dcerpc_read_ncacn_packet_recv(subreq, dce_conn,
2912 &pkt, &buffer);
2913 TALLOC_FREE(subreq);
2914 if (!NT_STATUS_IS_OK(status)) {
2915 dcesrv_terminate_connection(dce_conn, nt_errstr(status));
2916 return;
2919 dcesrv_loop_next_packet(dce_conn, pkt, buffer);
2923 * @brief Start the dcesrv loop, inducing the bind as a blob
2925 * Like dcesrv_connection_loop_start() but used from connections
2926 * where the caller has already read the dcerpc bind packet from
2927 * the socket and is available as a DATA_BLOB.
2929 * @param[in] dce_conn The connection to start
2930 * @param[in] pkt The parsed bind packet
2931 * @param[in] buffer The full binary bind including auth data
2933 void dcesrv_loop_next_packet(
2934 struct dcesrv_connection *dce_conn,
2935 struct ncacn_packet *pkt,
2936 DATA_BLOB buffer)
2938 struct tevent_req *subreq = NULL;
2939 NTSTATUS status;
2941 status = dcesrv_process_ncacn_packet(dce_conn, pkt, buffer);
2942 if (!NT_STATUS_IS_OK(status)) {
2943 dcesrv_terminate_connection(dce_conn, nt_errstr(status));
2944 return;
2948 * This is used to block the connection during
2949 * pending authentication.
2951 if (dce_conn->wait_send != NULL) {
2952 subreq = dce_conn->wait_send(dce_conn,
2953 dce_conn->event_ctx,
2954 dce_conn->wait_private);
2955 if (!subreq) {
2956 status = NT_STATUS_NO_MEMORY;
2957 dcesrv_terminate_connection(dce_conn, nt_errstr(status));
2958 return;
2960 tevent_req_set_callback(subreq, dcesrv_conn_wait_done, dce_conn);
2961 return;
2964 subreq = dcerpc_read_ncacn_packet_send(dce_conn,
2965 dce_conn->event_ctx,
2966 dce_conn->stream);
2967 if (!subreq) {
2968 status = NT_STATUS_NO_MEMORY;
2969 dcesrv_terminate_connection(dce_conn, nt_errstr(status));
2970 return;
2972 tevent_req_set_callback(subreq, dcesrv_read_fragment_done, dce_conn);
2975 static void dcesrv_conn_wait_done(struct tevent_req *subreq)
2977 struct dcesrv_connection *dce_conn = tevent_req_callback_data(subreq,
2978 struct dcesrv_connection);
2979 struct dcesrv_context *dce_ctx = dce_conn->dce_ctx;
2980 NTSTATUS status;
2982 if (dce_conn->terminate) {
2984 * if the current connection is broken
2985 * we need to clean it up before any other connection
2987 dcesrv_terminate_connection(dce_conn, dce_conn->terminate);
2988 dcesrv_cleanup_broken_connections(dce_ctx);
2989 return;
2992 dcesrv_cleanup_broken_connections(dce_ctx);
2994 status = dce_conn->wait_recv(subreq);
2995 dce_conn->wait_send = NULL;
2996 dce_conn->wait_recv = NULL;
2997 dce_conn->wait_private = NULL;
2998 TALLOC_FREE(subreq);
2999 if (!NT_STATUS_IS_OK(status)) {
3000 dcesrv_terminate_connection(dce_conn, nt_errstr(status));
3001 return;
3004 status = dcesrv_connection_loop_start(dce_conn);
3005 if (!NT_STATUS_IS_OK(status)) {
3006 dcesrv_terminate_connection(dce_conn, nt_errstr(status));
3007 return;
3012 * retrieve credentials from a dce_call
3014 _PUBLIC_ struct cli_credentials *dcesrv_call_credentials(struct dcesrv_call_state *dce_call)
3016 struct dcesrv_auth *auth = dce_call->auth_state;
3017 SMB_ASSERT(auth->auth_finished);
3018 return auth->session_info->credentials;
3022 * returns true if this is an authenticated call
3024 _PUBLIC_ bool dcesrv_call_authenticated(struct dcesrv_call_state *dce_call)
3026 struct dcesrv_auth *auth = dce_call->auth_state;
3027 enum security_user_level level;
3028 SMB_ASSERT(auth->auth_finished);
3029 level = security_session_user_level(auth->session_info, NULL);
3030 return level >= SECURITY_USER;
3034 * retrieve account_name for a dce_call
3036 _PUBLIC_ const char *dcesrv_call_account_name(struct dcesrv_call_state *dce_call)
3038 struct dcesrv_auth *auth = dce_call->auth_state;
3039 SMB_ASSERT(auth->auth_finished);
3040 return auth->session_info->info->account_name;
3044 * retrieve session_info from a dce_call
3046 _PUBLIC_ struct auth_session_info *dcesrv_call_session_info(struct dcesrv_call_state *dce_call)
3048 struct dcesrv_auth *auth = dce_call->auth_state;
3049 SMB_ASSERT(auth->auth_finished);
3050 return auth->session_info;
3054 * retrieve auth type/level from a dce_call
3056 _PUBLIC_ void dcesrv_call_auth_info(struct dcesrv_call_state *dce_call,
3057 enum dcerpc_AuthType *auth_type,
3058 enum dcerpc_AuthLevel *auth_level)
3060 struct dcesrv_auth *auth = dce_call->auth_state;
3062 SMB_ASSERT(auth->auth_finished);
3064 if (auth_type != NULL) {
3065 *auth_type = auth->auth_type;
3067 if (auth_level != NULL) {
3068 *auth_level = auth->auth_level;
3072 _PUBLIC_ NTSTATUS dcesrv_connection_loop_start(struct dcesrv_connection *conn)
3074 struct tevent_req *subreq;
3076 subreq = dcerpc_read_ncacn_packet_send(conn,
3077 conn->event_ctx,
3078 conn->stream);
3079 if (subreq == NULL) {
3080 return NT_STATUS_NO_MEMORY;
3082 tevent_req_set_callback(subreq, dcesrv_read_fragment_done, conn);
3084 return NT_STATUS_OK;
3087 _PUBLIC_ NTSTATUS dcesrv_call_dispatch_local(struct dcesrv_call_state *call)
3089 NTSTATUS status;
3090 struct ndr_pull *pull = NULL;
3091 struct ndr_push *push = NULL;
3092 struct data_blob_list_item *rep = NULL;
3094 pull = ndr_pull_init_blob(&call->pkt.u.request.stub_and_verifier,
3095 call);
3096 if (pull == NULL) {
3097 return NT_STATUS_NO_MEMORY;
3100 pull->flags |= LIBNDR_FLAG_REF_ALLOC;
3102 call->ndr_pull = pull;
3104 /* unravel the NDR for the packet */
3105 status = call->context->iface->ndr_pull(call, call, pull, &call->r);
3106 if (!NT_STATUS_IS_OK(status)) {
3107 DBG_INFO("DCE/RPC fault in call %s:%02X - %s\n",
3108 call->context->iface->name,
3109 call->pkt.u.request.opnum,
3110 dcerpc_errstr(call, call->fault_code));
3111 return dcerpc_fault_to_nt_status(call->fault_code);
3114 status = call->context->iface->local(call, call, call->r);
3115 if (!NT_STATUS_IS_OK(status)) {
3116 DBG_INFO("DCE/RPC fault in call %s:%02X - %s\n",
3117 call->context->iface->name,
3118 call->pkt.u.request.opnum,
3119 dcerpc_errstr(call, call->fault_code));
3120 return dcerpc_fault_to_nt_status(call->fault_code);
3123 /* This can never go async for now! */
3124 SMB_ASSERT(!(call->state_flags & DCESRV_CALL_STATE_FLAG_ASYNC));
3126 /* call the reply function */
3127 status = call->context->iface->reply(call, call, call->r);
3128 if (!NT_STATUS_IS_OK(status)) {
3129 DBG_INFO("DCE/RPC fault in call %s:%02X - %s\n",
3130 call->context->iface->name,
3131 call->pkt.u.request.opnum,
3132 dcerpc_errstr(call, call->fault_code));
3133 return dcerpc_fault_to_nt_status(call->fault_code);
3136 push = ndr_push_init_ctx(call);
3137 if (push == NULL) {
3138 return NT_STATUS_NO_MEMORY;
3141 push->ptr_count = call->ndr_pull->ptr_count;
3143 status = call->context->iface->ndr_push(call, call, push, call->r);
3144 if (!NT_STATUS_IS_OK(status)) {
3145 DBG_INFO("DCE/RPC fault in call %s:%02X - %s\n",
3146 call->context->iface->name,
3147 call->pkt.u.request.opnum,
3148 dcerpc_errstr(call, call->fault_code));
3149 return dcerpc_fault_to_nt_status(call->fault_code);
3152 rep = talloc_zero(call, struct data_blob_list_item);
3153 if (rep == NULL) {
3154 return NT_STATUS_NO_MEMORY;
3157 rep->blob = ndr_push_blob(push);
3158 DLIST_ADD_END(call->replies, rep);
3160 return NT_STATUS_OK;