s3: smbd: Move check_fsp_open() and check_fsp() to smb1_reply.c
[Samba.git] / librpc / rpc / dcesrv_core.c
blobd287004624869c4db2fcae72aa6a10a491d6a674
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"
39 /**
40 * @file
41 * @brief DCERPC server
44 #undef DBGC_CLASS
45 #define DBGC_CLASS DBGC_RPC_SRV
47 #undef strcasecmp
49 static NTSTATUS dcesrv_negotiate_contexts(struct dcesrv_call_state *call,
50 const struct dcerpc_bind *b,
51 struct dcerpc_ack_ctx *ack_ctx_list);
54 see if two endpoints match
56 static bool endpoints_match(const struct dcerpc_binding *ep1,
57 const struct dcerpc_binding *ep2)
59 enum dcerpc_transport_t t1;
60 enum dcerpc_transport_t t2;
61 const char *e1;
62 const char *e2;
64 t1 = dcerpc_binding_get_transport(ep1);
65 t2 = dcerpc_binding_get_transport(ep2);
67 e1 = dcerpc_binding_get_string_option(ep1, "endpoint");
68 e2 = dcerpc_binding_get_string_option(ep2, "endpoint");
70 if (t1 != t2) {
71 return false;
74 if (!e1 || !e2) {
75 return e1 == e2;
78 if (strcasecmp(e1, e2) != 0) {
79 return false;
82 return true;
86 find an endpoint in the dcesrv_context
88 _PUBLIC_ NTSTATUS dcesrv_find_endpoint(struct dcesrv_context *dce_ctx,
89 const struct dcerpc_binding *ep_description,
90 struct dcesrv_endpoint **_out)
92 struct dcesrv_endpoint *ep = NULL;
93 for (ep=dce_ctx->endpoint_list; ep; ep=ep->next) {
94 if (endpoints_match(ep->ep_description, ep_description)) {
95 *_out = ep;
96 return NT_STATUS_OK;
99 return NT_STATUS_NOT_FOUND;
103 find a registered context_id from a bind or alter_context
105 static struct dcesrv_connection_context *dcesrv_find_context(struct dcesrv_connection *conn,
106 uint16_t context_id)
108 struct dcesrv_connection_context *c;
109 for (c=conn->contexts;c;c=c->next) {
110 if (c->context_id == context_id) return c;
112 return NULL;
116 find the interface operations on any endpoint with this binding
118 static const struct dcesrv_interface *find_interface_by_binding(struct dcesrv_context *dce_ctx,
119 struct dcerpc_binding *binding,
120 const struct dcesrv_interface *iface)
122 struct dcesrv_endpoint *ep;
123 for (ep=dce_ctx->endpoint_list; ep; ep=ep->next) {
124 if (endpoints_match(ep->ep_description, binding)) {
125 const struct dcesrv_interface *ret = NULL;
127 ret = find_interface_by_syntax_id(
128 ep, &iface->syntax_id);
129 if (ret != NULL) {
130 return ret;
134 return NULL;
138 find the interface operations on an endpoint by uuid
140 _PUBLIC_ const struct dcesrv_interface *find_interface_by_syntax_id(
141 const struct dcesrv_endpoint *endpoint,
142 const struct ndr_syntax_id *interface)
144 struct dcesrv_if_list *ifl;
145 for (ifl=endpoint->interface_list; ifl; ifl=ifl->next) {
146 if (ndr_syntax_id_equal(&ifl->iface->syntax_id, interface)) {
147 return ifl->iface;
150 return NULL;
154 find the earlier parts of a fragmented call awaiting reassembly
156 static struct dcesrv_call_state *dcesrv_find_fragmented_call(struct dcesrv_connection *dce_conn, uint32_t call_id)
158 struct dcesrv_call_state *c;
159 for (c=dce_conn->incoming_fragmented_call_list;c;c=c->next) {
160 if (c->pkt.call_id == call_id) {
161 return c;
164 return NULL;
168 register an interface on an endpoint
170 An endpoint is one unix domain socket (for ncalrpc), one TCP port
171 (for ncacn_ip_tcp) or one (forwarded) named pipe (for ncacn_np).
173 Each endpoint can have many interfaces such as netlogon, lsa or
174 samr. Some have essentially the full set.
176 This is driven from the set of interfaces listed in each IDL file
177 via the PIDL generated *__op_init_server() functions.
179 _PUBLIC_ NTSTATUS dcesrv_interface_register(struct dcesrv_context *dce_ctx,
180 const char *ep_name,
181 const char *ncacn_np_secondary_endpoint,
182 const struct dcesrv_interface *iface,
183 const struct security_descriptor *sd)
185 struct dcerpc_binding *binding = NULL;
186 struct dcerpc_binding *binding2 = NULL;
187 NTSTATUS ret;
189 ret = dcerpc_parse_binding(dce_ctx, ep_name, &binding);
190 if (NT_STATUS_IS_ERR(ret)) {
191 DBG_ERR("Trouble parsing binding string '%s'\n", ep_name);
192 goto out;
195 if (ncacn_np_secondary_endpoint != NULL) {
196 ret = dcerpc_parse_binding(dce_ctx,
197 ncacn_np_secondary_endpoint,
198 &binding2);
199 if (NT_STATUS_IS_ERR(ret)) {
200 DBG_ERR("Trouble parsing 2nd binding string '%s'\n",
201 ncacn_np_secondary_endpoint);
202 goto out;
206 ret = dcesrv_interface_register_b(dce_ctx,
207 binding,
208 binding2,
209 iface,
210 sd);
211 out:
212 TALLOC_FREE(binding);
213 TALLOC_FREE(binding2);
214 return ret;
217 _PUBLIC_ NTSTATUS dcesrv_interface_register_b(struct dcesrv_context *dce_ctx,
218 struct dcerpc_binding *binding,
219 struct dcerpc_binding *binding2,
220 const struct dcesrv_interface *iface,
221 const struct security_descriptor *sd)
223 struct dcesrv_endpoint *ep;
224 struct dcesrv_if_list *ifl;
225 bool add_ep = false;
226 NTSTATUS status;
227 enum dcerpc_transport_t transport;
228 char *ep_string = NULL;
229 bool use_single_process = true;
230 const char *ep_process_string;
233 * If we are not using handles, there is no need for force
234 * this service into using a single process.
236 * However, due to the way we listen for RPC packets, we can
237 * only do this if we have a single service per pipe or TCP
238 * port, so we still force a single combined process for
239 * ncalrpc.
241 if (iface->flags & DCESRV_INTERFACE_FLAGS_HANDLES_NOT_USED) {
242 use_single_process = false;
245 transport = dcerpc_binding_get_transport(binding);
246 if (transport == NCACN_IP_TCP) {
247 int port;
250 * First check if there is already a port specified, eg
251 * for epmapper on ncacn_ip_tcp:[135]
253 const char *endpoint
254 = dcerpc_binding_get_string_option(binding,
255 "endpoint");
256 if (endpoint == NULL) {
257 port = lpcfg_parm_int(dce_ctx->lp_ctx, NULL,
258 "rpc server port", iface->name, 0);
261 * For RPC services that are not set to use a single
262 * process, we do not default to using the 'rpc server
263 * port' because that would cause a double-bind on
264 * that port.
266 if (port == 0 && !use_single_process) {
267 port = lpcfg_rpc_server_port(dce_ctx->lp_ctx);
269 if (port != 0) {
270 char port_str[6];
271 snprintf(port_str, sizeof(port_str), "%u", port);
272 status = dcerpc_binding_set_string_option(binding,
273 "endpoint",
274 port_str);
275 if (!NT_STATUS_IS_OK(status)) {
276 return status;
282 if (transport == NCACN_NP && binding2 != NULL) {
283 enum dcerpc_transport_t transport2;
285 transport2 = dcerpc_binding_get_transport(binding2);
286 SMB_ASSERT(transport2 == transport);
289 /* see if the interface is already registered on the endpoint */
290 if (find_interface_by_binding(dce_ctx, binding, iface)!=NULL) {
291 char *binding_string = dcerpc_binding_string(dce_ctx, binding);
292 DBG_ERR("Interface '%s' already registered on endpoint '%s'\n",
293 iface->name, binding_string);
294 TALLOC_FREE(binding_string);
295 return NT_STATUS_OBJECT_NAME_COLLISION;
298 /* check if this endpoint exists
300 status = dcesrv_find_endpoint(dce_ctx, binding, &ep);
301 if (NT_STATUS_IS_OK(status)) {
303 * We want a new port on ncacn_ip_tcp for NETLOGON, so
304 * it can be multi-process. Other processes can also
305 * listen on distinct ports, if they have one forced
306 * in the code above with eg 'rpc server port:drsuapi = 1027'
308 * If we have mulitiple endpoints on port 0, they each
309 * get an epemeral port (currently by walking up from
310 * 1024).
312 * Because one endpoint can only have one process
313 * model, we add a new IP_TCP endpoint for each model.
315 * This works in conjunction with the forced overwrite
316 * of ep->use_single_process below.
318 if (ep->use_single_process != use_single_process
319 && transport == NCACN_IP_TCP) {
320 add_ep = true;
324 if (NT_STATUS_EQUAL(status, NT_STATUS_NOT_FOUND) || add_ep) {
325 ep = talloc_zero(dce_ctx, struct dcesrv_endpoint);
326 if (!ep) {
327 return NT_STATUS_NO_MEMORY;
329 ep->ep_description = dcerpc_binding_dup(ep, binding);
330 if (transport == NCACN_NP && binding2 != NULL) {
331 ep->ep_2nd_description =
332 dcerpc_binding_dup(ep, binding2);
334 add_ep = true;
336 /* add mgmt interface */
337 ifl = talloc_zero(ep, struct dcesrv_if_list);
338 if (!ifl) {
339 TALLOC_FREE(ep);
340 return NT_STATUS_NO_MEMORY;
343 ifl->iface = talloc_memdup(ifl,
344 dcesrv_get_mgmt_interface(),
345 sizeof(struct dcesrv_interface));
346 if (ifl->iface == NULL) {
347 talloc_free(ep);
348 return NT_STATUS_NO_MEMORY;
351 DLIST_ADD(ep->interface_list, ifl);
352 } else if (!NT_STATUS_IS_OK(status)) {
353 DBG_NOTICE("Failed to find endpoint: %s\n", nt_errstr(status));
354 return status;
358 * By default don't force into a single process, but if any
359 * interface on this endpoint on this service uses handles
360 * (most do), then we must force into single process mode
362 * By overwriting this each time a new interface is added to
363 * this endpoint, we end up with the most restrictive setting.
365 if (use_single_process) {
366 ep->use_single_process = true;
369 /* talloc a new interface list element */
370 ifl = talloc_zero(ep, struct dcesrv_if_list);
371 if (!ifl) {
372 return NT_STATUS_NO_MEMORY;
375 /* copy the given interface struct to the one on the endpoints interface list */
376 ifl->iface = talloc_memdup(ifl,
377 iface,
378 sizeof(struct dcesrv_interface));
379 if (ifl->iface == NULL) {
380 talloc_free(ep);
381 return NT_STATUS_NO_MEMORY;
384 /* if we have a security descriptor given,
385 * we should see if we can set it up on the endpoint
387 if (sd != NULL) {
388 /* if there's currently no security descriptor given on the endpoint
389 * we try to set it
391 if (ep->sd == NULL) {
392 ep->sd = security_descriptor_copy(ep, sd);
395 /* if now there's no security descriptor given on the endpoint
396 * something goes wrong, either we failed to copy the security descriptor
397 * or there was already one on the endpoint
399 if (ep->sd != NULL) {
400 char *binding_string =
401 dcerpc_binding_string(dce_ctx, binding);
402 DBG_ERR("Interface '%s' failed to setup a security "
403 "descriptor on endpoint '%s'\n",
404 iface->name, binding_string);
405 TALLOC_FREE(binding_string);
406 if (add_ep) free(ep);
407 free(ifl);
408 return NT_STATUS_OBJECT_NAME_COLLISION;
412 /* finally add the interface on the endpoint */
413 DLIST_ADD(ep->interface_list, ifl);
415 /* if it's a new endpoint add it to the dcesrv_context */
416 if (add_ep) {
417 DLIST_ADD(dce_ctx->endpoint_list, ep);
420 /* Re-get the string as we may have set a port */
421 ep_string = dcerpc_binding_string(dce_ctx, ep->ep_description);
423 if (use_single_process) {
424 ep_process_string = "single process required";
425 } else {
426 ep_process_string = "multi process compatible";
429 DBG_INFO("Interface '%s' registered on endpoint '%s' (%s)\n",
430 iface->name, ep_string, ep_process_string);
431 TALLOC_FREE(ep_string);
433 return NT_STATUS_OK;
436 static NTSTATUS dcesrv_session_info_session_key(struct dcesrv_auth *auth,
437 DATA_BLOB *session_key)
439 if (auth->session_info == NULL) {
440 return NT_STATUS_NO_USER_SESSION_KEY;
443 if (auth->session_info->session_key.length == 0) {
444 return NT_STATUS_NO_USER_SESSION_KEY;
447 *session_key = auth->session_info->session_key;
448 return NT_STATUS_OK;
451 static NTSTATUS dcesrv_remote_session_key(struct dcesrv_auth *auth,
452 DATA_BLOB *session_key)
454 if (auth->auth_type != DCERPC_AUTH_TYPE_NONE) {
455 return NT_STATUS_NO_USER_SESSION_KEY;
458 return dcesrv_session_info_session_key(auth, session_key);
461 static NTSTATUS dcesrv_local_fixed_session_key(struct dcesrv_auth *auth,
462 DATA_BLOB *session_key)
464 return dcerpc_generic_session_key(session_key);
468 * Fetch the authentication session key if available.
470 * This is the key generated by a gensec authentication.
473 _PUBLIC_ NTSTATUS dcesrv_auth_session_key(struct dcesrv_call_state *call,
474 DATA_BLOB *session_key)
476 struct dcesrv_auth *auth = call->auth_state;
477 SMB_ASSERT(auth->auth_finished);
478 return dcesrv_session_info_session_key(auth, session_key);
482 * Fetch the transport session key if available.
483 * Typically this is the SMB session key
484 * or a fixed key for local transports.
486 * The key is always truncated to 16 bytes.
488 _PUBLIC_ NTSTATUS dcesrv_transport_session_key(struct dcesrv_call_state *call,
489 DATA_BLOB *session_key)
491 struct dcesrv_auth *auth = call->auth_state;
492 NTSTATUS status;
494 SMB_ASSERT(auth->auth_finished);
496 if (auth->session_key_fn == NULL) {
497 return NT_STATUS_NO_USER_SESSION_KEY;
500 status = auth->session_key_fn(auth, session_key);
501 if (!NT_STATUS_IS_OK(status)) {
502 return status;
505 session_key->length = MIN(session_key->length, 16);
507 return NT_STATUS_OK;
510 static struct dcesrv_auth *dcesrv_auth_create(struct dcesrv_connection *conn)
512 const struct dcesrv_endpoint *ep = conn->endpoint;
513 enum dcerpc_transport_t transport =
514 dcerpc_binding_get_transport(ep->ep_description);
515 struct dcesrv_auth *auth = NULL;
517 auth = talloc_zero(conn, struct dcesrv_auth);
518 if (auth == NULL) {
519 return NULL;
522 switch (transport) {
523 case NCACN_NP:
524 auth->session_key_fn = dcesrv_remote_session_key;
525 break;
526 case NCALRPC:
527 case NCACN_UNIX_STREAM:
528 auth->session_key_fn = dcesrv_local_fixed_session_key;
529 break;
530 default:
532 * All other's get a NULL pointer, which
533 * results in NT_STATUS_NO_USER_SESSION_KEY
535 break;
538 return auth;
542 connect to a dcerpc endpoint
544 _PUBLIC_ NTSTATUS dcesrv_endpoint_connect(struct dcesrv_context *dce_ctx,
545 TALLOC_CTX *mem_ctx,
546 const struct dcesrv_endpoint *ep,
547 struct auth_session_info *session_info,
548 struct tevent_context *event_ctx,
549 uint32_t state_flags,
550 struct dcesrv_connection **_p)
552 struct dcesrv_auth *auth = NULL;
553 struct dcesrv_connection *p = NULL;
555 if (!session_info) {
556 return NT_STATUS_ACCESS_DENIED;
559 p = talloc_zero(mem_ctx, struct dcesrv_connection);
560 if (p == NULL) {
561 goto nomem;
564 p->dce_ctx = dce_ctx;
565 p->endpoint = ep;
566 p->packet_log_dir = lpcfg_parm_string(dce_ctx->lp_ctx,
567 NULL,
568 "dcesrv",
569 "stubs directory");
570 p->event_ctx = event_ctx;
571 p->state_flags = state_flags;
572 p->allow_bind = true;
573 p->max_recv_frag = 5840;
574 p->max_xmit_frag = 5840;
575 p->max_total_request_size = DCERPC_NCACN_REQUEST_DEFAULT_MAX_SIZE;
577 p->support_hdr_signing = lpcfg_parm_bool(dce_ctx->lp_ctx,
578 NULL,
579 "dcesrv",
580 "header signing",
581 true);
582 p->max_auth_states = lpcfg_parm_ulong(dce_ctx->lp_ctx,
583 NULL,
584 "dcesrv",
585 "max auth states",
586 2049);
588 auth = dcesrv_auth_create(p);
589 if (auth == NULL) {
590 goto nomem;
593 auth->session_info = talloc_reference(auth, session_info);
594 if (auth->session_info == NULL) {
595 goto nomem;
598 p->default_auth_state = auth;
601 * For now we only support NDR32.
603 p->preferred_transfer = &ndr_transfer_syntax_ndr;
605 *_p = p;
606 return NT_STATUS_OK;
607 nomem:
608 TALLOC_FREE(p);
609 return NT_STATUS_NO_MEMORY;
613 move a call from an existing linked list to the specified list. This
614 prevents bugs where we forget to remove the call from a previous
615 list when moving it.
617 static void dcesrv_call_set_list(struct dcesrv_call_state *call,
618 enum dcesrv_call_list list)
620 switch (call->list) {
621 case DCESRV_LIST_NONE:
622 break;
623 case DCESRV_LIST_CALL_LIST:
624 DLIST_REMOVE(call->conn->call_list, call);
625 break;
626 case DCESRV_LIST_FRAGMENTED_CALL_LIST:
627 DLIST_REMOVE(call->conn->incoming_fragmented_call_list, call);
628 break;
629 case DCESRV_LIST_PENDING_CALL_LIST:
630 DLIST_REMOVE(call->conn->pending_call_list, call);
631 break;
633 call->list = list;
634 switch (list) {
635 case DCESRV_LIST_NONE:
636 break;
637 case DCESRV_LIST_CALL_LIST:
638 DLIST_ADD_END(call->conn->call_list, call);
639 break;
640 case DCESRV_LIST_FRAGMENTED_CALL_LIST:
641 DLIST_ADD_END(call->conn->incoming_fragmented_call_list, call);
642 break;
643 case DCESRV_LIST_PENDING_CALL_LIST:
644 DLIST_ADD_END(call->conn->pending_call_list, call);
645 break;
649 static void dcesrv_call_disconnect_after(struct dcesrv_call_state *call,
650 const char *reason)
652 struct dcesrv_auth *a = NULL;
654 if (call->conn->terminate != NULL) {
655 return;
658 call->conn->allow_bind = false;
659 call->conn->allow_alter = false;
661 call->conn->default_auth_state->auth_invalid = true;
663 for (a = call->conn->auth_states; a != NULL; a = a->next) {
664 a->auth_invalid = true;
667 call->terminate_reason = talloc_strdup(call, reason);
668 if (call->terminate_reason == NULL) {
669 call->terminate_reason = __location__;
674 return a dcerpc bind_nak
676 static NTSTATUS dcesrv_bind_nak(struct dcesrv_call_state *call, uint32_t reason)
678 struct ncacn_packet pkt;
679 struct dcerpc_bind_nak_version version;
680 struct data_blob_list_item *rep;
681 NTSTATUS status;
682 static const uint8_t _pad[3] = { 0, };
685 * We add the call to the pending_call_list
686 * in order to defer the termination.
688 dcesrv_call_disconnect_after(call, "dcesrv_bind_nak");
690 /* setup a bind_nak */
691 dcesrv_init_hdr(&pkt, lpcfg_rpc_big_endian(call->conn->dce_ctx->lp_ctx));
692 pkt.auth_length = 0;
693 pkt.call_id = call->pkt.call_id;
694 pkt.ptype = DCERPC_PKT_BIND_NAK;
695 pkt.pfc_flags = DCERPC_PFC_FLAG_FIRST | DCERPC_PFC_FLAG_LAST;
696 pkt.u.bind_nak.reject_reason = reason;
697 version.rpc_vers = 5;
698 version.rpc_vers_minor = 0;
699 pkt.u.bind_nak.num_versions = 1;
700 pkt.u.bind_nak.versions = &version;
701 pkt.u.bind_nak._pad = data_blob_const(_pad, sizeof(_pad));
703 rep = talloc_zero(call, struct data_blob_list_item);
704 if (!rep) {
705 return NT_STATUS_NO_MEMORY;
708 status = dcerpc_ncacn_push_auth(&rep->blob, call, &pkt, NULL);
709 if (!NT_STATUS_IS_OK(status)) {
710 return status;
713 dcerpc_set_frag_length(&rep->blob, rep->blob.length);
715 DLIST_ADD_END(call->replies, rep);
716 dcesrv_call_set_list(call, DCESRV_LIST_CALL_LIST);
718 if (call->conn->call_list && call->conn->call_list->replies) {
719 if (call->conn->transport.report_output_data) {
720 call->conn->transport.report_output_data(call->conn);
724 return NT_STATUS_OK;
727 static NTSTATUS _dcesrv_fault_disconnect_flags(struct dcesrv_call_state *call,
728 uint32_t fault_code,
729 uint8_t extra_flags,
730 const char *func,
731 const char *location)
733 const char *reason = NULL;
735 reason = talloc_asprintf(call, "%s:%s: fault=%u (%s) flags=0x%x",
736 func, location,
737 fault_code,
738 dcerpc_errstr(call, fault_code),
739 extra_flags);
740 if (reason == NULL) {
741 reason = location;
745 * We add the call to the pending_call_list
746 * in order to defer the termination.
749 dcesrv_call_disconnect_after(call, reason);
751 return dcesrv_fault_with_flags(call, fault_code, extra_flags);
754 #define dcesrv_fault_disconnect(call, fault_code) \
755 _dcesrv_fault_disconnect_flags(call, fault_code, \
756 DCERPC_PFC_FLAG_DID_NOT_EXECUTE, \
757 __func__, __location__)
758 #define dcesrv_fault_disconnect0(call, fault_code) \
759 _dcesrv_fault_disconnect_flags(call, fault_code, 0, \
760 __func__, __location__)
762 static int dcesrv_connection_context_destructor(struct dcesrv_connection_context *c)
764 DLIST_REMOVE(c->conn->contexts, c);
766 if (c->iface && c->iface->unbind) {
767 c->iface->unbind(c, c->iface);
768 c->iface = NULL;
771 return 0;
774 static void dcesrv_prepare_context_auth(struct dcesrv_call_state *dce_call)
776 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
777 const struct dcesrv_endpoint *endpoint = dce_call->conn->endpoint;
778 enum dcerpc_transport_t transport =
779 dcerpc_binding_get_transport(endpoint->ep_description);
780 struct dcesrv_connection_context *context = dce_call->context;
781 const struct dcesrv_interface *iface = context->iface;
783 context->min_auth_level = DCERPC_AUTH_LEVEL_NONE;
785 if (transport == NCALRPC) {
786 context->allow_connect = true;
787 return;
791 * allow overwrite per interface
792 * allow dcerpc auth level connect:<interface>
794 context->allow_connect = lpcfg_allow_dcerpc_auth_level_connect(lp_ctx);
795 context->allow_connect = lpcfg_parm_bool(lp_ctx, NULL,
796 "allow dcerpc auth level connect",
797 iface->name,
798 context->allow_connect);
801 NTSTATUS dcesrv_interface_bind_require_integrity(struct dcesrv_connection_context *context,
802 const struct dcesrv_interface *iface)
805 * For connection oriented DCERPC DCERPC_AUTH_LEVEL_PACKET (4)
806 * has the same behavior as DCERPC_AUTH_LEVEL_INTEGRITY (5).
808 context->min_auth_level = DCERPC_AUTH_LEVEL_PACKET;
809 return NT_STATUS_OK;
812 NTSTATUS dcesrv_interface_bind_require_privacy(struct dcesrv_connection_context *context,
813 const struct dcesrv_interface *iface)
815 context->min_auth_level = DCERPC_AUTH_LEVEL_PRIVACY;
816 return NT_STATUS_OK;
819 _PUBLIC_ NTSTATUS dcesrv_interface_bind_reject_connect(struct dcesrv_connection_context *context,
820 const struct dcesrv_interface *iface)
822 struct loadparm_context *lp_ctx = context->conn->dce_ctx->lp_ctx;
823 const struct dcesrv_endpoint *endpoint = context->conn->endpoint;
824 enum dcerpc_transport_t transport =
825 dcerpc_binding_get_transport(endpoint->ep_description);
827 if (transport == NCALRPC) {
828 context->allow_connect = true;
829 return NT_STATUS_OK;
833 * allow overwrite per interface
834 * allow dcerpc auth level connect:<interface>
836 context->allow_connect = false;
837 context->allow_connect = lpcfg_parm_bool(lp_ctx, NULL,
838 "allow dcerpc auth level connect",
839 iface->name,
840 context->allow_connect);
841 return NT_STATUS_OK;
844 _PUBLIC_ NTSTATUS dcesrv_interface_bind_allow_connect(struct dcesrv_connection_context *context,
845 const struct dcesrv_interface *iface)
847 struct loadparm_context *lp_ctx = context->conn->dce_ctx->lp_ctx;
848 const struct dcesrv_endpoint *endpoint = context->conn->endpoint;
849 enum dcerpc_transport_t transport =
850 dcerpc_binding_get_transport(endpoint->ep_description);
852 if (transport == NCALRPC) {
853 context->allow_connect = true;
854 return NT_STATUS_OK;
858 * allow overwrite per interface
859 * allow dcerpc auth level connect:<interface>
861 context->allow_connect = true;
862 context->allow_connect = lpcfg_parm_bool(lp_ctx, NULL,
863 "allow dcerpc auth level connect",
864 iface->name,
865 context->allow_connect);
866 return NT_STATUS_OK;
869 struct dcesrv_conn_auth_wait_context {
870 struct tevent_req *req;
871 bool done;
872 NTSTATUS status;
875 struct dcesrv_conn_auth_wait_state {
876 uint8_t dummy;
879 static struct tevent_req *dcesrv_conn_auth_wait_send(TALLOC_CTX *mem_ctx,
880 struct tevent_context *ev,
881 void *private_data)
883 struct dcesrv_conn_auth_wait_context *auth_wait =
884 talloc_get_type_abort(private_data,
885 struct dcesrv_conn_auth_wait_context);
886 struct tevent_req *req = NULL;
887 struct dcesrv_conn_auth_wait_state *state = NULL;
889 req = tevent_req_create(mem_ctx, &state,
890 struct dcesrv_conn_auth_wait_state);
891 if (req == NULL) {
892 return NULL;
894 auth_wait->req = req;
896 tevent_req_defer_callback(req, ev);
898 if (!auth_wait->done) {
899 return req;
902 if (tevent_req_nterror(req, auth_wait->status)) {
903 return tevent_req_post(req, ev);
906 tevent_req_done(req);
907 return tevent_req_post(req, ev);
910 static NTSTATUS dcesrv_conn_auth_wait_recv(struct tevent_req *req)
912 return tevent_req_simple_recv_ntstatus(req);
915 static NTSTATUS dcesrv_conn_auth_wait_setup(struct dcesrv_connection *conn)
917 struct dcesrv_conn_auth_wait_context *auth_wait = NULL;
919 if (conn->wait_send != NULL) {
920 return NT_STATUS_INTERNAL_ERROR;
923 auth_wait = talloc_zero(conn, struct dcesrv_conn_auth_wait_context);
924 if (auth_wait == NULL) {
925 return NT_STATUS_NO_MEMORY;
928 conn->wait_private = auth_wait;
929 conn->wait_send = dcesrv_conn_auth_wait_send;
930 conn->wait_recv = dcesrv_conn_auth_wait_recv;
931 return NT_STATUS_OK;
934 static void dcesrv_conn_auth_wait_finished(struct dcesrv_connection *conn,
935 NTSTATUS status)
937 struct dcesrv_conn_auth_wait_context *auth_wait =
938 talloc_get_type_abort(conn->wait_private,
939 struct dcesrv_conn_auth_wait_context);
941 auth_wait->done = true;
942 auth_wait->status = status;
944 if (auth_wait->req == NULL) {
945 return;
948 if (tevent_req_nterror(auth_wait->req, status)) {
949 return;
952 tevent_req_done(auth_wait->req);
955 static NTSTATUS dcesrv_auth_reply(struct dcesrv_call_state *call);
957 static void dcesrv_bind_done(struct tevent_req *subreq);
960 handle a bind request
962 static NTSTATUS dcesrv_bind(struct dcesrv_call_state *call)
964 struct dcesrv_connection *conn = call->conn;
965 struct dcesrv_context *dce_ctx = conn->dce_ctx;
966 struct ncacn_packet *pkt = &call->ack_pkt;
967 NTSTATUS status;
968 uint32_t extra_flags = 0;
969 uint16_t max_req = 0;
970 uint16_t max_rep = 0;
971 struct dcerpc_binding *ep_2nd_description = NULL;
972 const char *endpoint = NULL;
973 struct dcesrv_auth *auth = call->auth_state;
974 struct dcesrv_context_callbacks *cb = call->conn->dce_ctx->callbacks;
975 struct dcerpc_ack_ctx *ack_ctx_list = NULL;
976 struct dcerpc_ack_ctx *ack_features = NULL;
977 struct tevent_req *subreq = NULL;
978 size_t i;
980 status = dcerpc_verify_ncacn_packet_header(&call->pkt,
981 DCERPC_PKT_BIND,
982 call->pkt.u.bind.auth_info.length,
983 0, /* required flags */
984 DCERPC_PFC_FLAG_FIRST |
985 DCERPC_PFC_FLAG_LAST |
986 DCERPC_PFC_FLAG_SUPPORT_HEADER_SIGN |
987 0x08 | /* this is not defined, but should be ignored */
988 DCERPC_PFC_FLAG_CONC_MPX |
989 DCERPC_PFC_FLAG_DID_NOT_EXECUTE |
990 DCERPC_PFC_FLAG_MAYBE |
991 DCERPC_PFC_FLAG_OBJECT_UUID);
992 if (!NT_STATUS_IS_OK(status)) {
993 return dcesrv_bind_nak(call,
994 DCERPC_BIND_NAK_REASON_PROTOCOL_VERSION_NOT_SUPPORTED);
997 /* max_recv_frag and max_xmit_frag result always in the same value! */
998 max_req = MIN(call->pkt.u.bind.max_xmit_frag,
999 call->pkt.u.bind.max_recv_frag);
1001 * The values are between 2048 and 5840 tested against Windows 2012R2
1002 * via ncacn_ip_tcp on port 135.
1004 max_req = MAX(2048, max_req);
1005 max_rep = MIN(max_req, conn->max_recv_frag);
1006 /* They are truncated to an 8 byte boundary. */
1007 max_rep &= 0xFFF8;
1009 /* max_recv_frag and max_xmit_frag result always in the same value! */
1010 conn->max_recv_frag = max_rep;
1011 conn->max_xmit_frag = max_rep;
1013 status = dce_ctx->callbacks->assoc_group.find(
1014 call, dce_ctx->callbacks->assoc_group.private_data);
1015 if (!NT_STATUS_IS_OK(status)) {
1016 DBG_NOTICE("Failed to find assoc_group 0x%08x: %s\n",
1017 call->pkt.u.bind.assoc_group_id, nt_errstr(status));
1018 return dcesrv_bind_nak(call, 0);
1021 if (call->pkt.u.bind.num_contexts < 1) {
1022 return dcesrv_bind_nak(call, 0);
1025 ack_ctx_list = talloc_zero_array(call, struct dcerpc_ack_ctx,
1026 call->pkt.u.bind.num_contexts);
1027 if (ack_ctx_list == NULL) {
1028 return dcesrv_bind_nak(call, 0);
1032 * Set some sane defaults (required by dcesrv_negotiate_contexts()/
1033 * dcesrv_check_or_create_context()) and do some protocol validation
1034 * and set sane defaults.
1036 for (i = 0; i < call->pkt.u.bind.num_contexts; i++) {
1037 const struct dcerpc_ctx_list *c = &call->pkt.u.bind.ctx_list[i];
1038 struct dcerpc_ack_ctx *a = &ack_ctx_list[i];
1039 bool is_feature = false;
1040 uint64_t features = 0;
1042 if (c->num_transfer_syntaxes == 0) {
1043 return dcesrv_bind_nak(call, 0);
1046 a->result = DCERPC_BIND_ACK_RESULT_PROVIDER_REJECTION;
1047 a->reason.value = DCERPC_BIND_ACK_REASON_ABSTRACT_SYNTAX_NOT_SUPPORTED;
1050 * It's only treated as bind time feature request, if the first
1051 * transfer_syntax matches, all others are ignored.
1053 is_feature = dcerpc_extract_bind_time_features(c->transfer_syntaxes[0],
1054 &features);
1055 if (!is_feature) {
1056 continue;
1059 if (ack_features != NULL) {
1061 * Only one bind time feature context is allowed.
1063 return dcesrv_bind_nak(call, 0);
1065 ack_features = a;
1067 a->result = DCERPC_BIND_ACK_RESULT_NEGOTIATE_ACK;
1068 a->reason.negotiate = 0;
1069 if (features & DCERPC_BIND_TIME_SECURITY_CONTEXT_MULTIPLEXING) {
1070 if (conn->max_auth_states != 0) {
1071 a->reason.negotiate |=
1072 DCERPC_BIND_TIME_SECURITY_CONTEXT_MULTIPLEXING;
1075 if (features & DCERPC_BIND_TIME_KEEP_CONNECTION_ON_ORPHAN) {
1076 a->reason.negotiate |=
1077 DCERPC_BIND_TIME_KEEP_CONNECTION_ON_ORPHAN;
1080 conn->assoc_group->bind_time_features = a->reason.negotiate;
1084 * Try to negotiate one new presentation context.
1086 * Deep in here we locate the iface (by uuid) that the client
1087 * requested, from the list of interfaces on the
1088 * call->conn->endpoint, and call iface->bind() on that iface.
1090 * call->conn was set up at the accept() of the socket, and
1091 * call->conn->endpoint has a list of interfaces restricted to
1092 * this port or pipe.
1094 status = dcesrv_negotiate_contexts(call, &call->pkt.u.bind, ack_ctx_list);
1095 if (NT_STATUS_EQUAL(status, NT_STATUS_RPC_PROTOCOL_ERROR)) {
1096 return dcesrv_bind_nak(call, 0);
1098 if (!NT_STATUS_IS_OK(status)) {
1099 return status;
1103 * At this point we still don't know which interface (eg
1104 * netlogon, lsa, drsuapi) the caller requested in this bind!
1105 * The most recently added context is available as the first
1106 * element in the linked list at call->conn->contexts, that is
1107 * call->conn->contexts->iface, but they may not have
1108 * requested one at all!
1111 if ((call->pkt.pfc_flags & DCERPC_PFC_FLAG_CONC_MPX) &&
1112 (call->state_flags & DCESRV_CALL_STATE_FLAG_MULTIPLEXED)) {
1113 call->conn->state_flags |= DCESRV_CALL_STATE_FLAG_MULTIPLEXED;
1114 extra_flags |= DCERPC_PFC_FLAG_CONC_MPX;
1117 if (call->state_flags & DCESRV_CALL_STATE_FLAG_PROCESS_PENDING_CALL) {
1118 conn->state_flags |= DCESRV_CALL_STATE_FLAG_PROCESS_PENDING_CALL;
1122 * After finding the interface and setting up the NDR
1123 * transport negotiation etc, handle any authentication that
1124 * is being requested.
1126 if (!dcesrv_auth_bind(call)) {
1128 if (auth->auth_level == DCERPC_AUTH_LEVEL_NONE) {
1130 * With DCERPC_AUTH_LEVEL_NONE, we get the
1131 * reject_reason in auth->auth_context_id.
1133 return dcesrv_bind_nak(call, auth->auth_context_id);
1137 * This must a be a temporary failure e.g. talloc or invalid
1138 * configuration, e.g. no machine account.
1140 return dcesrv_bind_nak(call,
1141 DCERPC_BIND_NAK_REASON_TEMPORARY_CONGESTION);
1144 /* setup a bind_ack */
1145 dcesrv_init_hdr(pkt, lpcfg_rpc_big_endian(dce_ctx->lp_ctx));
1146 pkt->auth_length = 0;
1147 pkt->call_id = call->pkt.call_id;
1148 pkt->ptype = DCERPC_PKT_BIND_ACK;
1149 pkt->pfc_flags = DCERPC_PFC_FLAG_FIRST | DCERPC_PFC_FLAG_LAST | extra_flags;
1150 pkt->u.bind_ack.max_xmit_frag = conn->max_xmit_frag;
1151 pkt->u.bind_ack.max_recv_frag = conn->max_recv_frag;
1152 pkt->u.bind_ack.assoc_group_id = conn->assoc_group->id;
1154 ep_2nd_description = conn->endpoint->ep_2nd_description;
1155 if (ep_2nd_description == NULL) {
1156 ep_2nd_description = conn->endpoint->ep_description;
1159 endpoint = dcerpc_binding_get_string_option(
1160 ep_2nd_description,
1161 "endpoint");
1162 if (endpoint == NULL) {
1163 endpoint = "";
1166 pkt->u.bind_ack.secondary_address = endpoint;
1167 pkt->u.bind_ack.num_results = call->pkt.u.bind.num_contexts;
1168 pkt->u.bind_ack.ctx_list = ack_ctx_list;
1169 pkt->u.bind_ack.auth_info = data_blob_null;
1171 status = dcesrv_auth_prepare_bind_ack(call, pkt);
1172 if (!NT_STATUS_IS_OK(status)) {
1173 return dcesrv_bind_nak(call, 0);
1176 if (auth->auth_finished) {
1177 return dcesrv_auth_reply(call);
1180 cb->auth.become_root();
1181 subreq = gensec_update_send(call, call->event_ctx,
1182 auth->gensec_security,
1183 call->in_auth_info.credentials);
1184 cb->auth.unbecome_root();
1185 if (subreq == NULL) {
1186 return NT_STATUS_NO_MEMORY;
1188 tevent_req_set_callback(subreq, dcesrv_bind_done, call);
1190 return dcesrv_conn_auth_wait_setup(conn);
1193 static void dcesrv_bind_done(struct tevent_req *subreq)
1195 struct dcesrv_call_state *call =
1196 tevent_req_callback_data(subreq,
1197 struct dcesrv_call_state);
1198 struct dcesrv_connection *conn = call->conn;
1199 struct dcesrv_context_callbacks *cb = call->conn->dce_ctx->callbacks;
1200 NTSTATUS status;
1202 cb->auth.become_root();
1203 status = gensec_update_recv(subreq, call,
1204 &call->out_auth_info->credentials);
1205 cb->auth.unbecome_root();
1206 TALLOC_FREE(subreq);
1208 status = dcesrv_auth_complete(call, status);
1209 if (!NT_STATUS_IS_OK(status)) {
1210 status = dcesrv_bind_nak(call, 0);
1211 dcesrv_conn_auth_wait_finished(conn, status);
1212 return;
1215 status = dcesrv_auth_reply(call);
1216 dcesrv_conn_auth_wait_finished(conn, status);
1217 return;
1220 static NTSTATUS dcesrv_auth_reply(struct dcesrv_call_state *call)
1222 struct ncacn_packet *pkt = &call->ack_pkt;
1223 struct data_blob_list_item *rep = NULL;
1224 NTSTATUS status;
1226 rep = talloc_zero(call, struct data_blob_list_item);
1227 if (!rep) {
1228 return NT_STATUS_NO_MEMORY;
1231 status = dcerpc_ncacn_push_auth(&rep->blob,
1232 call,
1233 pkt,
1234 call->out_auth_info);
1235 if (!NT_STATUS_IS_OK(status)) {
1236 return status;
1239 dcerpc_set_frag_length(&rep->blob, rep->blob.length);
1241 DLIST_ADD_END(call->replies, rep);
1242 dcesrv_call_set_list(call, DCESRV_LIST_CALL_LIST);
1244 if (call->conn->call_list && call->conn->call_list->replies) {
1245 if (call->conn->transport.report_output_data) {
1246 call->conn->transport.report_output_data(call->conn);
1250 return NT_STATUS_OK;
1254 static void dcesrv_auth3_done(struct tevent_req *subreq);
1257 handle a auth3 request
1259 static NTSTATUS dcesrv_auth3(struct dcesrv_call_state *call)
1261 struct dcesrv_connection *conn = call->conn;
1262 struct dcesrv_auth *auth = call->auth_state;
1263 struct dcesrv_context_callbacks *cb = call->conn->dce_ctx->callbacks;
1264 struct tevent_req *subreq = NULL;
1265 NTSTATUS status;
1267 if (!auth->auth_started) {
1268 return dcesrv_fault_disconnect(call, DCERPC_NCA_S_PROTO_ERROR);
1271 if (auth->auth_finished) {
1272 return dcesrv_fault_disconnect(call, DCERPC_NCA_S_PROTO_ERROR);
1275 status = dcerpc_verify_ncacn_packet_header(&call->pkt,
1276 DCERPC_PKT_AUTH3,
1277 call->pkt.u.auth3.auth_info.length,
1278 0, /* required flags */
1279 DCERPC_PFC_FLAG_FIRST |
1280 DCERPC_PFC_FLAG_LAST |
1281 DCERPC_PFC_FLAG_SUPPORT_HEADER_SIGN |
1282 0x08 | /* this is not defined, but should be ignored */
1283 DCERPC_PFC_FLAG_CONC_MPX |
1284 DCERPC_PFC_FLAG_DID_NOT_EXECUTE |
1285 DCERPC_PFC_FLAG_MAYBE |
1286 DCERPC_PFC_FLAG_OBJECT_UUID);
1287 if (!NT_STATUS_IS_OK(status)) {
1288 return dcesrv_fault_disconnect(call, DCERPC_NCA_S_PROTO_ERROR);
1291 /* handle the auth3 in the auth code */
1292 if (!dcesrv_auth_prepare_auth3(call)) {
1294 * we don't send a reply to a auth3 request,
1295 * except by a fault.
1297 * In anycase we mark the connection as
1298 * invalid.
1300 auth->auth_invalid = true;
1301 if (call->fault_code != 0) {
1302 return dcesrv_fault_disconnect(call, call->fault_code);
1304 TALLOC_FREE(call);
1305 return NT_STATUS_OK;
1308 cb->auth.become_root();
1309 subreq = gensec_update_send(call, call->event_ctx,
1310 auth->gensec_security,
1311 call->in_auth_info.credentials);
1312 cb->auth.unbecome_root();
1313 if (subreq == NULL) {
1314 return NT_STATUS_NO_MEMORY;
1316 tevent_req_set_callback(subreq, dcesrv_auth3_done, call);
1318 return dcesrv_conn_auth_wait_setup(conn);
1321 static void dcesrv_auth3_done(struct tevent_req *subreq)
1323 struct dcesrv_call_state *call =
1324 tevent_req_callback_data(subreq,
1325 struct dcesrv_call_state);
1326 struct dcesrv_connection *conn = call->conn;
1327 struct dcesrv_auth *auth = call->auth_state;
1328 struct dcesrv_context_callbacks *cb = call->conn->dce_ctx->callbacks;
1329 NTSTATUS status;
1331 cb->auth.become_root();
1332 status = gensec_update_recv(subreq, call,
1333 &call->out_auth_info->credentials);
1334 cb->auth.unbecome_root();
1335 TALLOC_FREE(subreq);
1337 status = dcesrv_auth_complete(call, status);
1338 if (!NT_STATUS_IS_OK(status)) {
1340 * we don't send a reply to a auth3 request,
1341 * except by a fault.
1343 * In anycase we mark the connection as
1344 * invalid.
1346 auth->auth_invalid = true;
1347 if (call->fault_code != 0) {
1348 status = dcesrv_fault_disconnect(call, call->fault_code);
1349 dcesrv_conn_auth_wait_finished(conn, status);
1350 return;
1352 TALLOC_FREE(call);
1353 dcesrv_conn_auth_wait_finished(conn, NT_STATUS_OK);
1354 return;
1358 * we don't send a reply to a auth3 request.
1360 TALLOC_FREE(call);
1361 dcesrv_conn_auth_wait_finished(conn, NT_STATUS_OK);
1362 return;
1366 static NTSTATUS dcesrv_check_or_create_context(struct dcesrv_call_state *call,
1367 const struct dcerpc_bind *b,
1368 const struct dcerpc_ctx_list *ctx,
1369 struct dcerpc_ack_ctx *ack,
1370 bool validate_only,
1371 const struct ndr_syntax_id *supported_transfer)
1373 struct dcesrv_connection_context *context;
1374 const struct dcesrv_interface *iface;
1375 NTSTATUS status;
1376 const struct ndr_syntax_id *selected_transfer = NULL;
1377 size_t i;
1378 bool ok;
1380 if (b == NULL) {
1381 return NT_STATUS_INTERNAL_ERROR;
1383 if (ctx == NULL) {
1384 return NT_STATUS_INTERNAL_ERROR;
1386 if (ctx->num_transfer_syntaxes < 1) {
1387 return NT_STATUS_INTERNAL_ERROR;
1389 if (ack == NULL) {
1390 return NT_STATUS_INTERNAL_ERROR;
1392 if (supported_transfer == NULL) {
1393 return NT_STATUS_INTERNAL_ERROR;
1396 switch (ack->result) {
1397 case DCERPC_BIND_ACK_RESULT_ACCEPTANCE:
1398 case DCERPC_BIND_ACK_RESULT_NEGOTIATE_ACK:
1400 * We is already completed.
1402 return NT_STATUS_OK;
1403 default:
1404 break;
1407 ack->result = DCERPC_BIND_ACK_RESULT_PROVIDER_REJECTION;
1408 ack->reason.value = DCERPC_BIND_ACK_REASON_ABSTRACT_SYNTAX_NOT_SUPPORTED;
1410 iface = find_interface_by_syntax_id(
1411 call->conn->endpoint, &ctx->abstract_syntax);
1412 if (iface == NULL) {
1413 struct ndr_syntax_id_buf buf;
1414 DBG_NOTICE("Request for unknown dcerpc interface %s\n",
1415 ndr_syntax_id_buf_string(
1416 &ctx->abstract_syntax, &buf));
1418 * We report this only via ack->result
1420 return NT_STATUS_OK;
1423 ack->result = DCERPC_BIND_ACK_RESULT_PROVIDER_REJECTION;
1424 ack->reason.value = DCERPC_BIND_ACK_REASON_TRANSFER_SYNTAXES_NOT_SUPPORTED;
1426 if (validate_only) {
1428 * We report this only via ack->result
1430 return NT_STATUS_OK;
1433 for (i = 0; i < ctx->num_transfer_syntaxes; i++) {
1435 * we only do NDR encoded dcerpc for now.
1437 ok = ndr_syntax_id_equal(&ctx->transfer_syntaxes[i],
1438 supported_transfer);
1439 if (ok) {
1440 selected_transfer = supported_transfer;
1441 break;
1445 context = dcesrv_find_context(call->conn, ctx->context_id);
1446 if (context != NULL) {
1447 ok = ndr_syntax_id_equal(&context->iface->syntax_id,
1448 &ctx->abstract_syntax);
1449 if (!ok) {
1450 return NT_STATUS_RPC_PROTOCOL_ERROR;
1453 if (selected_transfer != NULL) {
1454 ok = ndr_syntax_id_equal(&context->transfer_syntax,
1455 selected_transfer);
1456 if (!ok) {
1457 return NT_STATUS_RPC_PROTOCOL_ERROR;
1460 ack->result = DCERPC_BIND_ACK_RESULT_ACCEPTANCE;
1461 ack->reason.value = DCERPC_BIND_ACK_REASON_NOT_SPECIFIED;
1462 ack->syntax = context->transfer_syntax;
1466 * We report this only via ack->result
1468 return NT_STATUS_OK;
1471 if (selected_transfer == NULL) {
1473 * We report this only via ack->result
1475 return NT_STATUS_OK;
1478 ack->result = DCERPC_BIND_ACK_RESULT_USER_REJECTION;
1479 ack->reason.value = DCERPC_BIND_ACK_REASON_LOCAL_LIMIT_EXCEEDED;
1481 /* add this context to the list of available context_ids */
1482 context = talloc_zero(call->conn, struct dcesrv_connection_context);
1483 if (context == NULL) {
1484 return NT_STATUS_NO_MEMORY;
1486 context->conn = call->conn;
1487 context->context_id = ctx->context_id;
1488 context->iface = iface;
1489 context->transfer_syntax = *selected_transfer;
1490 DLIST_ADD(call->conn->contexts, context);
1491 call->context = context;
1492 talloc_set_destructor(context, dcesrv_connection_context_destructor);
1494 dcesrv_prepare_context_auth(call);
1497 * Multiplex is supported by default
1499 call->state_flags |= DCESRV_CALL_STATE_FLAG_MULTIPLEXED;
1501 status = iface->bind(context, iface);
1502 call->context = NULL;
1503 if (!NT_STATUS_IS_OK(status)) {
1504 /* we don't want to trigger the iface->unbind() hook */
1505 context->iface = NULL;
1506 talloc_free(context);
1508 * We report this only via ack->result
1510 return NT_STATUS_OK;
1513 ack->result = DCERPC_BIND_ACK_RESULT_ACCEPTANCE;
1514 ack->reason.value = DCERPC_BIND_ACK_REASON_NOT_SPECIFIED;
1515 ack->syntax = context->transfer_syntax;
1516 return NT_STATUS_OK;
1519 static NTSTATUS dcesrv_negotiate_contexts(struct dcesrv_call_state *call,
1520 const struct dcerpc_bind *b,
1521 struct dcerpc_ack_ctx *ack_ctx_list)
1523 NTSTATUS status;
1524 size_t i;
1525 bool validate_only = false;
1526 bool preferred_ndr32;
1529 * Try to negotiate one new presentation context,
1530 * using our preferred transfer syntax.
1532 for (i = 0; i < b->num_contexts; i++) {
1533 const struct dcerpc_ctx_list *c = &b->ctx_list[i];
1534 struct dcerpc_ack_ctx *a = &ack_ctx_list[i];
1536 status = dcesrv_check_or_create_context(call, b, c, a,
1537 validate_only,
1538 call->conn->preferred_transfer);
1539 if (!NT_STATUS_IS_OK(status)) {
1540 return status;
1543 if (a->result == DCERPC_BIND_ACK_RESULT_ACCEPTANCE) {
1545 * We managed to negotiate one context.
1547 * => we're done.
1549 validate_only = true;
1553 preferred_ndr32 = ndr_syntax_id_equal(&ndr_transfer_syntax_ndr,
1554 call->conn->preferred_transfer);
1555 if (preferred_ndr32) {
1557 * We're done.
1559 return NT_STATUS_OK;
1563 * Try to negotiate one new presentation context,
1564 * using NDR 32 as fallback.
1566 for (i = 0; i < b->num_contexts; i++) {
1567 const struct dcerpc_ctx_list *c = &b->ctx_list[i];
1568 struct dcerpc_ack_ctx *a = &ack_ctx_list[i];
1570 status = dcesrv_check_or_create_context(call, b, c, a,
1571 validate_only,
1572 &ndr_transfer_syntax_ndr);
1573 if (!NT_STATUS_IS_OK(status)) {
1574 return status;
1577 if (a->result == DCERPC_BIND_ACK_RESULT_ACCEPTANCE) {
1579 * We managed to negotiate one context.
1581 * => we're done.
1583 validate_only = true;
1587 return NT_STATUS_OK;
1590 static void dcesrv_alter_done(struct tevent_req *subreq);
1593 handle a alter context request
1595 static NTSTATUS dcesrv_alter(struct dcesrv_call_state *call)
1597 struct dcesrv_connection *conn = call->conn;
1598 NTSTATUS status;
1599 bool auth_ok = false;
1600 struct ncacn_packet *pkt = &call->ack_pkt;
1601 uint32_t extra_flags = 0;
1602 struct dcesrv_auth *auth = call->auth_state;
1603 struct dcesrv_context_callbacks *cb = call->conn->dce_ctx->callbacks;
1604 struct dcerpc_ack_ctx *ack_ctx_list = NULL;
1605 struct tevent_req *subreq = NULL;
1606 size_t i;
1608 if (!call->conn->allow_alter) {
1609 return dcesrv_fault_disconnect(call, DCERPC_NCA_S_PROTO_ERROR);
1612 status = dcerpc_verify_ncacn_packet_header(&call->pkt,
1613 DCERPC_PKT_ALTER,
1614 call->pkt.u.alter.auth_info.length,
1615 0, /* required flags */
1616 DCERPC_PFC_FLAG_FIRST |
1617 DCERPC_PFC_FLAG_LAST |
1618 DCERPC_PFC_FLAG_SUPPORT_HEADER_SIGN |
1619 0x08 | /* this is not defined, but should be ignored */
1620 DCERPC_PFC_FLAG_CONC_MPX |
1621 DCERPC_PFC_FLAG_DID_NOT_EXECUTE |
1622 DCERPC_PFC_FLAG_MAYBE |
1623 DCERPC_PFC_FLAG_OBJECT_UUID);
1624 if (!NT_STATUS_IS_OK(status)) {
1625 return dcesrv_fault_disconnect(call, DCERPC_NCA_S_PROTO_ERROR);
1628 auth_ok = dcesrv_auth_alter(call);
1629 if (!auth_ok) {
1630 if (call->fault_code != 0) {
1631 return dcesrv_fault_disconnect(call, call->fault_code);
1635 if (call->pkt.u.alter.num_contexts < 1) {
1636 return dcesrv_fault_disconnect(call, DCERPC_NCA_S_PROTO_ERROR);
1639 ack_ctx_list = talloc_zero_array(call, struct dcerpc_ack_ctx,
1640 call->pkt.u.alter.num_contexts);
1641 if (ack_ctx_list == NULL) {
1642 return NT_STATUS_NO_MEMORY;
1646 * Set some sane defaults (required by dcesrv_negotiate_contexts()/
1647 * dcesrv_check_or_create_context()) and do some protocol validation
1648 * and set sane defaults.
1650 for (i = 0; i < call->pkt.u.alter.num_contexts; i++) {
1651 const struct dcerpc_ctx_list *c = &call->pkt.u.alter.ctx_list[i];
1652 struct dcerpc_ack_ctx *a = &ack_ctx_list[i];
1654 if (c->num_transfer_syntaxes == 0) {
1655 return dcesrv_fault_disconnect(call,
1656 DCERPC_NCA_S_PROTO_ERROR);
1659 a->result = DCERPC_BIND_ACK_RESULT_PROVIDER_REJECTION;
1660 a->reason.value = DCERPC_BIND_ACK_REASON_ABSTRACT_SYNTAX_NOT_SUPPORTED;
1664 * Try to negotiate one new presentation context.
1666 status = dcesrv_negotiate_contexts(call, &call->pkt.u.alter, ack_ctx_list);
1667 if (NT_STATUS_EQUAL(status, NT_STATUS_RPC_PROTOCOL_ERROR)) {
1668 return dcesrv_fault_disconnect(call, DCERPC_NCA_S_PROTO_ERROR);
1670 if (!NT_STATUS_IS_OK(status)) {
1671 return status;
1674 if ((call->pkt.pfc_flags & DCERPC_PFC_FLAG_CONC_MPX) &&
1675 (call->state_flags & DCESRV_CALL_STATE_FLAG_MULTIPLEXED)) {
1676 call->conn->state_flags |= DCESRV_CALL_STATE_FLAG_MULTIPLEXED;
1677 extra_flags |= DCERPC_PFC_FLAG_CONC_MPX;
1680 if (call->state_flags & DCESRV_CALL_STATE_FLAG_PROCESS_PENDING_CALL) {
1681 call->conn->state_flags |= DCESRV_CALL_STATE_FLAG_PROCESS_PENDING_CALL;
1684 /* handle any authentication that is being requested */
1685 if (!auth_ok) {
1686 if (call->in_auth_info.auth_type != auth->auth_type) {
1687 return dcesrv_fault_disconnect(call,
1688 DCERPC_FAULT_SEC_PKG_ERROR);
1690 return dcesrv_fault_disconnect(call, DCERPC_FAULT_ACCESS_DENIED);
1693 dcesrv_init_hdr(pkt, lpcfg_rpc_big_endian(call->conn->dce_ctx->lp_ctx));
1694 pkt->auth_length = 0;
1695 pkt->call_id = call->pkt.call_id;
1696 pkt->ptype = DCERPC_PKT_ALTER_RESP;
1697 pkt->pfc_flags = DCERPC_PFC_FLAG_FIRST | DCERPC_PFC_FLAG_LAST | extra_flags;
1698 pkt->u.alter_resp.max_xmit_frag = call->conn->max_xmit_frag;
1699 pkt->u.alter_resp.max_recv_frag = call->conn->max_recv_frag;
1700 pkt->u.alter_resp.assoc_group_id = call->conn->assoc_group->id;
1701 pkt->u.alter_resp.secondary_address = "";
1702 pkt->u.alter_resp.num_results = call->pkt.u.alter.num_contexts;
1703 pkt->u.alter_resp.ctx_list = ack_ctx_list;
1704 pkt->u.alter_resp.auth_info = data_blob_null;
1706 status = dcesrv_auth_prepare_alter_ack(call, pkt);
1707 if (!NT_STATUS_IS_OK(status)) {
1708 return dcesrv_fault_disconnect(call, DCERPC_FAULT_SEC_PKG_ERROR);
1711 if (auth->auth_finished) {
1712 return dcesrv_auth_reply(call);
1715 cb->auth.become_root();
1716 subreq = gensec_update_send(call, call->event_ctx,
1717 auth->gensec_security,
1718 call->in_auth_info.credentials);
1719 cb->auth.unbecome_root();
1720 if (subreq == NULL) {
1721 return NT_STATUS_NO_MEMORY;
1723 tevent_req_set_callback(subreq, dcesrv_alter_done, call);
1725 return dcesrv_conn_auth_wait_setup(conn);
1728 static void dcesrv_alter_done(struct tevent_req *subreq)
1730 struct dcesrv_call_state *call =
1731 tevent_req_callback_data(subreq,
1732 struct dcesrv_call_state);
1733 struct dcesrv_connection *conn = call->conn;
1734 struct dcesrv_context_callbacks *cb = call->conn->dce_ctx->callbacks;
1735 NTSTATUS status;
1737 cb->auth.become_root();
1738 status = gensec_update_recv(subreq, call,
1739 &call->out_auth_info->credentials);
1740 cb->auth.unbecome_root();
1741 TALLOC_FREE(subreq);
1743 status = dcesrv_auth_complete(call, status);
1744 if (!NT_STATUS_IS_OK(status)) {
1745 status = dcesrv_fault_disconnect(call, DCERPC_FAULT_SEC_PKG_ERROR);
1746 dcesrv_conn_auth_wait_finished(conn, status);
1747 return;
1750 status = dcesrv_auth_reply(call);
1751 dcesrv_conn_auth_wait_finished(conn, status);
1752 return;
1756 possibly save the call for inspection with ndrdump
1758 static void dcesrv_save_call(struct dcesrv_call_state *call, const char *why)
1760 #ifdef DEVELOPER
1761 dcerpc_log_packet(call->conn->packet_log_dir,
1762 call->context->iface->name,
1763 call->pkt.u.request.opnum,
1764 NDR_IN,
1765 &call->pkt.u.request.stub_and_verifier,
1766 why);
1767 #endif
1770 #ifdef DEVELOPER
1772 Save the call for use as a seed for fuzzing.
1774 This is only enabled in a developer build, and only has effect if the
1775 "dcesrv fuzz directory" param is set.
1777 void _dcesrv_save_ndr_fuzz_seed(DATA_BLOB call_blob,
1778 struct dcesrv_call_state *call,
1779 int flags)
1781 const char *dump_dir = lpcfg_parm_string(call->conn->dce_ctx->lp_ctx,
1782 NULL,
1783 "dcesrv", "fuzz directory");
1785 dcerpc_save_ndr_fuzz_seed(call,
1786 call_blob,
1787 dump_dir,
1788 call->context->iface->name,
1789 flags,
1790 call->pkt.u.request.opnum,
1791 call->ndr_pull->flags & LIBNDR_FLAG_NDR64);
1793 #endif /*if DEVELOPER, enveloping _dcesrv_save_ndr_fuzz_seed() */
1796 static NTSTATUS dcesrv_check_verification_trailer(struct dcesrv_call_state *call)
1798 TALLOC_CTX *frame = talloc_stackframe();
1799 const uint32_t bitmask1 = call->conn->client_hdr_signing ?
1800 DCERPC_SEC_VT_CLIENT_SUPPORTS_HEADER_SIGNING : 0;
1801 const struct dcerpc_sec_vt_pcontext pcontext = {
1802 .abstract_syntax = call->context->iface->syntax_id,
1803 .transfer_syntax = call->context->transfer_syntax,
1805 const struct dcerpc_sec_vt_header2 header2 =
1806 dcerpc_sec_vt_header2_from_ncacn_packet(&call->pkt);
1807 enum ndr_err_code ndr_err;
1808 struct dcerpc_sec_verification_trailer *vt = NULL;
1809 NTSTATUS status = NT_STATUS_OK;
1810 bool ok;
1812 SMB_ASSERT(call->pkt.ptype == DCERPC_PKT_REQUEST);
1814 ndr_err = ndr_pop_dcerpc_sec_verification_trailer(call->ndr_pull,
1815 frame, &vt);
1816 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
1817 status = ndr_map_error2ntstatus(ndr_err);
1818 goto done;
1821 ok = dcerpc_sec_verification_trailer_check(vt, &bitmask1,
1822 &pcontext, &header2);
1823 if (!ok) {
1824 status = NT_STATUS_ACCESS_DENIED;
1825 goto done;
1827 done:
1828 TALLOC_FREE(frame);
1829 return status;
1833 handle a dcerpc request packet
1835 static NTSTATUS dcesrv_request(struct dcesrv_call_state *call)
1837 const struct dcesrv_endpoint *endpoint = call->conn->endpoint;
1838 struct dcesrv_auth *auth = call->auth_state;
1839 enum dcerpc_transport_t transport =
1840 dcerpc_binding_get_transport(endpoint->ep_description);
1841 struct ndr_pull *pull;
1842 NTSTATUS status;
1844 if (auth->auth_invalid) {
1845 return dcesrv_fault_disconnect(call, DCERPC_NCA_S_PROTO_ERROR);
1848 if (!auth->auth_finished) {
1849 return dcesrv_fault_disconnect(call, DCERPC_NCA_S_PROTO_ERROR);
1852 /* if authenticated, and the mech we use can't do async replies, don't use them... */
1853 if (auth->gensec_security != NULL &&
1854 !gensec_have_feature(auth->gensec_security, GENSEC_FEATURE_ASYNC_REPLIES)) {
1855 call->state_flags &= ~DCESRV_CALL_STATE_FLAG_MAY_ASYNC;
1858 if (call->context == NULL) {
1859 return dcesrv_fault_with_flags(call, DCERPC_NCA_S_UNKNOWN_IF,
1860 DCERPC_PFC_FLAG_DID_NOT_EXECUTE);
1863 switch (auth->auth_level) {
1864 case DCERPC_AUTH_LEVEL_NONE:
1865 case DCERPC_AUTH_LEVEL_PACKET:
1866 case DCERPC_AUTH_LEVEL_INTEGRITY:
1867 case DCERPC_AUTH_LEVEL_PRIVACY:
1868 break;
1869 default:
1870 if (!call->context->allow_connect) {
1871 char *addr;
1873 addr = tsocket_address_string(call->conn->remote_address,
1874 call);
1876 DEBUG(2, ("%s: restrict auth_level_connect access "
1877 "to [%s] with auth[type=0x%x,level=0x%x] "
1878 "on [%s] from [%s]\n",
1879 __func__, call->context->iface->name,
1880 auth->auth_type,
1881 auth->auth_level,
1882 derpc_transport_string_by_transport(transport),
1883 addr));
1884 return dcesrv_fault(call, DCERPC_FAULT_ACCESS_DENIED);
1886 break;
1889 if (auth->auth_level < call->context->min_auth_level) {
1890 char *addr;
1892 addr = tsocket_address_string(call->conn->remote_address, call);
1894 DEBUG(2, ("%s: restrict access by min_auth_level[0x%x] "
1895 "to [%s] with auth[type=0x%x,level=0x%x] "
1896 "on [%s] from [%s]\n",
1897 __func__,
1898 call->context->min_auth_level,
1899 call->context->iface->name,
1900 auth->auth_type,
1901 auth->auth_level,
1902 derpc_transport_string_by_transport(transport),
1903 addr));
1904 return dcesrv_fault(call, DCERPC_FAULT_ACCESS_DENIED);
1907 pull = ndr_pull_init_blob(&call->pkt.u.request.stub_and_verifier, call);
1908 NT_STATUS_HAVE_NO_MEMORY(pull);
1910 pull->flags |= LIBNDR_FLAG_REF_ALLOC;
1912 call->ndr_pull = pull;
1914 if (!(call->pkt.drep[0] & DCERPC_DREP_LE)) {
1915 pull->flags |= LIBNDR_FLAG_BIGENDIAN;
1918 status = dcesrv_check_verification_trailer(call);
1919 if (!NT_STATUS_IS_OK(status)) {
1920 uint32_t faultcode = DCERPC_FAULT_OTHER;
1921 if (NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
1922 faultcode = DCERPC_FAULT_ACCESS_DENIED;
1924 DEBUG(10, ("dcesrv_check_verification_trailer failed: %s\n",
1925 nt_errstr(status)));
1926 return dcesrv_fault(call, faultcode);
1929 /* unravel the NDR for the packet */
1930 status = call->context->iface->ndr_pull(call, call, pull, &call->r);
1931 if (!NT_STATUS_IS_OK(status)) {
1932 uint8_t extra_flags = 0;
1933 if (call->fault_code == DCERPC_FAULT_OP_RNG_ERROR) {
1934 /* we got an unknown call */
1935 DEBUG(3,(__location__ ": Unknown RPC call %u on %s\n",
1936 call->pkt.u.request.opnum,
1937 call->context->iface->name));
1938 dcesrv_save_call(call, "unknown");
1939 extra_flags |= DCERPC_PFC_FLAG_DID_NOT_EXECUTE;
1940 } else {
1941 dcesrv_save_call(call, "pullfail");
1944 return dcesrv_fault_with_flags(call, call->fault_code, extra_flags);
1947 dcesrv_save_ndr_fuzz_seed(call->pkt.u.request.stub_and_verifier,
1948 call,
1949 NDR_IN);
1951 if (pull->offset != pull->data_size) {
1952 dcesrv_save_call(call, "extrabytes");
1953 DEBUG(3,("Warning: %d extra bytes in incoming RPC request\n",
1954 pull->data_size - pull->offset));
1957 /* call the dispatch function */
1958 status = call->context->iface->dispatch(call, call, call->r);
1959 if (!NT_STATUS_IS_OK(status)) {
1960 DEBUG(5,("dcerpc fault in call %s:%02x - %s\n",
1961 call->context->iface->name,
1962 call->pkt.u.request.opnum,
1963 dcerpc_errstr(pull, call->fault_code)));
1964 return dcesrv_fault(call, call->fault_code);
1967 /* add the call to the pending list */
1968 dcesrv_call_set_list(call, DCESRV_LIST_PENDING_CALL_LIST);
1970 if (call->state_flags & DCESRV_CALL_STATE_FLAG_ASYNC) {
1971 return NT_STATUS_OK;
1974 return dcesrv_reply(call);
1979 remove the call from the right list when freed
1981 static int dcesrv_call_dequeue(struct dcesrv_call_state *call)
1983 dcesrv_call_set_list(call, DCESRV_LIST_NONE);
1984 return 0;
1987 _PUBLIC_ const struct tsocket_address *dcesrv_connection_get_local_address(struct dcesrv_connection *conn)
1989 return conn->local_address;
1992 _PUBLIC_ const struct tsocket_address *dcesrv_connection_get_remote_address(struct dcesrv_connection *conn)
1994 return conn->remote_address;
1998 process some input to a dcerpc endpoint server.
2000 static NTSTATUS dcesrv_process_ncacn_packet(struct dcesrv_connection *dce_conn,
2001 struct ncacn_packet *pkt,
2002 DATA_BLOB blob)
2004 NTSTATUS status;
2005 struct dcesrv_call_state *call;
2006 struct dcesrv_call_state *existing = NULL;
2007 size_t num_auth_ctx = 0;
2008 enum dcerpc_AuthType auth_type = 0;
2009 enum dcerpc_AuthLevel auth_level = 0;
2010 uint32_t auth_context_id = 0;
2011 bool auth_invalid = false;
2013 call = talloc_zero(dce_conn, struct dcesrv_call_state);
2014 if (!call) {
2015 data_blob_free(&blob);
2016 talloc_free(pkt);
2017 return NT_STATUS_NO_MEMORY;
2019 call->conn = dce_conn;
2020 call->event_ctx = dce_conn->event_ctx;
2021 call->state_flags = call->conn->state_flags;
2022 call->time = timeval_current();
2023 call->list = DCESRV_LIST_NONE;
2025 talloc_steal(call, pkt);
2026 talloc_steal(call, blob.data);
2027 call->pkt = *pkt;
2029 if (dce_conn->max_auth_states == 0) {
2030 call->auth_state = dce_conn->default_auth_state;
2031 } else if (call->pkt.auth_length == 0) {
2032 if (call->pkt.ptype == DCERPC_PKT_REQUEST &&
2033 dce_conn->default_auth_level_connect != NULL)
2035 call->auth_state = dce_conn->default_auth_level_connect;
2036 } else {
2037 call->auth_state = dce_conn->default_auth_state;
2041 if (call->auth_state == NULL) {
2042 struct dcesrv_auth *a = NULL;
2043 bool check_type_level = true;
2045 auth_type = dcerpc_get_auth_type(&blob);
2046 auth_level = dcerpc_get_auth_level(&blob);
2047 auth_context_id = dcerpc_get_auth_context_id(&blob);
2049 if (call->pkt.ptype == DCERPC_PKT_REQUEST) {
2050 if (!(call->pkt.pfc_flags & DCERPC_PFC_FLAG_FIRST)) {
2051 check_type_level = false;
2053 dce_conn->default_auth_level_connect = NULL;
2054 if (auth_level == DCERPC_AUTH_LEVEL_CONNECT) {
2055 dce_conn->got_explicit_auth_level_connect = true;
2059 for (a = dce_conn->auth_states; a != NULL; a = a->next) {
2060 num_auth_ctx++;
2062 if (a->auth_context_id != auth_context_id) {
2063 continue;
2066 if (a->auth_type != auth_type) {
2067 auth_invalid = true;
2069 if (a->auth_level != auth_level) {
2070 auth_invalid = true;
2073 if (check_type_level && auth_invalid) {
2074 a->auth_invalid = true;
2077 DLIST_PROMOTE(dce_conn->auth_states, a);
2078 call->auth_state = a;
2079 break;
2083 if (call->auth_state == NULL) {
2084 struct dcesrv_auth *a = NULL;
2086 if (num_auth_ctx >= dce_conn->max_auth_states) {
2087 return dcesrv_fault_disconnect(call,
2088 DCERPC_NCA_S_PROTO_ERROR);
2091 a = dcesrv_auth_create(dce_conn);
2092 if (a == NULL) {
2093 talloc_free(call);
2094 return NT_STATUS_NO_MEMORY;
2096 DLIST_ADD(dce_conn->auth_states, a);
2097 if (call->pkt.ptype == DCERPC_PKT_REQUEST) {
2099 * This can never be valid.
2101 auth_invalid = true;
2102 a->auth_invalid = true;
2104 call->auth_state = a;
2107 talloc_set_destructor(call, dcesrv_call_dequeue);
2109 if (call->conn->allow_bind) {
2111 * Only one bind is possible per connection
2113 call->conn->allow_bind = false;
2114 return dcesrv_bind(call);
2117 /* we have to check the signing here, before combining the
2118 pdus */
2119 if (call->pkt.ptype == DCERPC_PKT_REQUEST) {
2120 dcesrv_default_auth_state_prepare_request(call);
2122 if (call->auth_state->auth_started &&
2123 !call->auth_state->auth_finished) {
2124 return dcesrv_fault_disconnect(call,
2125 DCERPC_NCA_S_PROTO_ERROR);
2128 status = dcerpc_verify_ncacn_packet_header(&call->pkt,
2129 DCERPC_PKT_REQUEST,
2130 call->pkt.u.request.stub_and_verifier.length,
2131 0, /* required_flags */
2132 DCERPC_PFC_FLAG_FIRST |
2133 DCERPC_PFC_FLAG_LAST |
2134 DCERPC_PFC_FLAG_PENDING_CANCEL |
2135 0x08 | /* this is not defined, but should be ignored */
2136 DCERPC_PFC_FLAG_CONC_MPX |
2137 DCERPC_PFC_FLAG_DID_NOT_EXECUTE |
2138 DCERPC_PFC_FLAG_MAYBE |
2139 DCERPC_PFC_FLAG_OBJECT_UUID);
2140 if (!NT_STATUS_IS_OK(status)) {
2141 return dcesrv_fault_disconnect(call,
2142 DCERPC_NCA_S_PROTO_ERROR);
2145 if (call->pkt.frag_length > DCERPC_FRAG_MAX_SIZE) {
2147 * We don't use dcesrv_fault_disconnect()
2148 * here, because we don't want to set
2149 * DCERPC_PFC_FLAG_DID_NOT_EXECUTE
2151 * Note that we don't check against the negotiated
2152 * max_recv_frag, but a hard coded value.
2154 return dcesrv_fault_disconnect0(call, DCERPC_NCA_S_PROTO_ERROR);
2157 if (call->pkt.pfc_flags & DCERPC_PFC_FLAG_FIRST) {
2158 if (dce_conn->pending_call_list != NULL) {
2160 * concurrent requests are only allowed
2161 * if DCERPC_PFC_FLAG_CONC_MPX was negotiated.
2163 if (!(dce_conn->state_flags & DCESRV_CALL_STATE_FLAG_MULTIPLEXED)) {
2164 return dcesrv_fault_disconnect0(call,
2165 DCERPC_NCA_S_PROTO_ERROR);
2168 /* only one request is possible in the fragmented list */
2169 if (dce_conn->incoming_fragmented_call_list != NULL) {
2170 call->fault_code = DCERPC_NCA_S_PROTO_ERROR;
2172 existing = dcesrv_find_fragmented_call(dce_conn,
2173 call->pkt.call_id);
2174 if (existing != NULL && call->auth_state != existing->auth_state) {
2175 call->context = dcesrv_find_context(call->conn,
2176 call->pkt.u.request.context_id);
2178 if (call->pkt.auth_length != 0 && existing->context == call->context) {
2179 call->fault_code = DCERPC_FAULT_SEC_PKG_ERROR;
2182 if (!(dce_conn->state_flags & DCESRV_CALL_STATE_FLAG_MULTIPLEXED)) {
2184 * Without DCERPC_PFC_FLAG_CONC_MPX
2185 * we need to return the FAULT on the
2186 * already existing call.
2188 * This is important to get the
2189 * call_id and context_id right.
2191 dce_conn->incoming_fragmented_call_list->fault_code = call->fault_code;
2192 TALLOC_FREE(call);
2193 call = dce_conn->incoming_fragmented_call_list;
2195 if (existing != NULL) {
2196 call->context = existing->context;
2198 return dcesrv_fault_disconnect0(call, call->fault_code);
2200 if (call->pkt.pfc_flags & DCERPC_PFC_FLAG_PENDING_CANCEL) {
2201 return dcesrv_fault_disconnect(call,
2202 DCERPC_FAULT_NO_CALL_ACTIVE);
2204 call->context = dcesrv_find_context(call->conn,
2205 call->pkt.u.request.context_id);
2206 if (call->context == NULL) {
2207 return dcesrv_fault_with_flags(call, DCERPC_NCA_S_UNKNOWN_IF,
2208 DCERPC_PFC_FLAG_DID_NOT_EXECUTE);
2210 } else {
2211 int cmp;
2213 existing = dcesrv_find_fragmented_call(dce_conn,
2214 call->pkt.call_id);
2215 if (existing == NULL) {
2216 if (!(dce_conn->state_flags & DCESRV_CALL_STATE_FLAG_MULTIPLEXED)) {
2218 * Without DCERPC_PFC_FLAG_CONC_MPX
2219 * we need to return the FAULT on the
2220 * already existing call.
2222 * This is important to get the
2223 * call_id and context_id right.
2225 if (dce_conn->incoming_fragmented_call_list != NULL) {
2226 TALLOC_FREE(call);
2227 call = dce_conn->incoming_fragmented_call_list;
2229 return dcesrv_fault_disconnect0(call,
2230 DCERPC_NCA_S_PROTO_ERROR);
2232 if (dce_conn->incoming_fragmented_call_list != NULL) {
2233 return dcesrv_fault_disconnect0(call, DCERPC_NCA_S_PROTO_ERROR);
2235 call->context = dcesrv_find_context(call->conn,
2236 call->pkt.u.request.context_id);
2237 if (call->context == NULL) {
2238 return dcesrv_fault_with_flags(call, DCERPC_NCA_S_UNKNOWN_IF,
2239 DCERPC_PFC_FLAG_DID_NOT_EXECUTE);
2241 if (auth_invalid) {
2242 return dcesrv_fault_disconnect0(call,
2243 DCERPC_FAULT_ACCESS_DENIED);
2245 return dcesrv_fault_disconnect0(call,
2246 DCERPC_NCA_S_PROTO_ERROR);
2249 if (call->pkt.ptype != existing->pkt.ptype) {
2250 /* trying to play silly buggers are we? */
2251 return dcesrv_fault_disconnect(existing,
2252 DCERPC_NCA_S_PROTO_ERROR);
2254 cmp = memcmp(call->pkt.drep, existing->pkt.drep,
2255 sizeof(pkt->drep));
2256 if (cmp != 0) {
2257 return dcesrv_fault_disconnect(existing,
2258 DCERPC_NCA_S_PROTO_ERROR);
2260 call->auth_state = existing->auth_state;
2261 call->context = existing->context;
2265 if (call->pkt.ptype == DCERPC_PKT_REQUEST) {
2266 bool ok;
2267 uint8_t payload_offset = DCERPC_REQUEST_LENGTH;
2269 if (call->pkt.pfc_flags & DCERPC_PFC_FLAG_OBJECT_UUID) {
2270 payload_offset += 16;
2273 ok = dcesrv_auth_pkt_pull(call, &blob,
2274 0, /* required_flags */
2275 DCERPC_PFC_FLAG_FIRST |
2276 DCERPC_PFC_FLAG_LAST |
2277 DCERPC_PFC_FLAG_PENDING_CANCEL |
2278 0x08 | /* this is not defined, but should be ignored */
2279 DCERPC_PFC_FLAG_CONC_MPX |
2280 DCERPC_PFC_FLAG_DID_NOT_EXECUTE |
2281 DCERPC_PFC_FLAG_MAYBE |
2282 DCERPC_PFC_FLAG_OBJECT_UUID,
2283 payload_offset,
2284 &call->pkt.u.request.stub_and_verifier);
2285 if (!ok) {
2287 * We don't use dcesrv_fault_disconnect()
2288 * here, because we don't want to set
2289 * DCERPC_PFC_FLAG_DID_NOT_EXECUTE
2291 if (call->fault_code == 0) {
2292 call->fault_code = DCERPC_FAULT_ACCESS_DENIED;
2294 return dcesrv_fault_disconnect0(call, call->fault_code);
2298 /* see if this is a continued packet */
2299 if (existing != NULL) {
2300 struct dcerpc_request *er = &existing->pkt.u.request;
2301 const struct dcerpc_request *nr = &call->pkt.u.request;
2302 size_t available;
2303 size_t alloc_size;
2304 size_t alloc_hint;
2307 * Up to 4 MByte are allowed by all fragments
2309 available = dce_conn->max_total_request_size;
2310 if (er->stub_and_verifier.length > available) {
2311 return dcesrv_fault_disconnect0(existing,
2312 DCERPC_FAULT_ACCESS_DENIED);
2314 available -= er->stub_and_verifier.length;
2315 if (nr->alloc_hint > available) {
2316 return dcesrv_fault_disconnect0(existing,
2317 DCERPC_FAULT_ACCESS_DENIED);
2319 if (nr->stub_and_verifier.length > available) {
2320 return dcesrv_fault_disconnect0(existing,
2321 DCERPC_FAULT_ACCESS_DENIED);
2323 alloc_hint = er->stub_and_verifier.length + nr->alloc_hint;
2324 /* allocate at least 1 byte */
2325 alloc_hint = MAX(alloc_hint, 1);
2326 alloc_size = er->stub_and_verifier.length +
2327 nr->stub_and_verifier.length;
2328 alloc_size = MAX(alloc_size, alloc_hint);
2330 er->stub_and_verifier.data =
2331 talloc_realloc(existing,
2332 er->stub_and_verifier.data,
2333 uint8_t, alloc_size);
2334 if (er->stub_and_verifier.data == NULL) {
2335 TALLOC_FREE(call);
2336 return dcesrv_fault_with_flags(existing,
2337 DCERPC_FAULT_OUT_OF_RESOURCES,
2338 DCERPC_PFC_FLAG_DID_NOT_EXECUTE);
2340 memcpy(er->stub_and_verifier.data +
2341 er->stub_and_verifier.length,
2342 nr->stub_and_verifier.data,
2343 nr->stub_and_verifier.length);
2344 er->stub_and_verifier.length += nr->stub_and_verifier.length;
2346 existing->pkt.pfc_flags |= (call->pkt.pfc_flags & DCERPC_PFC_FLAG_LAST);
2348 TALLOC_FREE(call);
2349 call = existing;
2352 /* this may not be the last pdu in the chain - if its isn't then
2353 just put it on the incoming_fragmented_call_list and wait for the rest */
2354 if (call->pkt.ptype == DCERPC_PKT_REQUEST &&
2355 !(call->pkt.pfc_flags & DCERPC_PFC_FLAG_LAST)) {
2357 * Up to 4 MByte are allowed by all fragments
2359 if (call->pkt.u.request.alloc_hint > dce_conn->max_total_request_size) {
2360 return dcesrv_fault_disconnect0(call,
2361 DCERPC_FAULT_ACCESS_DENIED);
2363 dcesrv_call_set_list(call, DCESRV_LIST_FRAGMENTED_CALL_LIST);
2364 return NT_STATUS_OK;
2367 /* This removes any fragments we may have had stashed away */
2368 dcesrv_call_set_list(call, DCESRV_LIST_NONE);
2370 switch (call->pkt.ptype) {
2371 case DCERPC_PKT_BIND:
2372 status = dcesrv_bind_nak(call,
2373 DCERPC_BIND_NAK_REASON_NOT_SPECIFIED);
2374 break;
2375 case DCERPC_PKT_AUTH3:
2376 status = dcesrv_auth3(call);
2377 break;
2378 case DCERPC_PKT_ALTER:
2379 status = dcesrv_alter(call);
2380 break;
2381 case DCERPC_PKT_REQUEST:
2382 status = dcesrv_request(call);
2383 break;
2384 case DCERPC_PKT_CO_CANCEL:
2385 case DCERPC_PKT_ORPHANED:
2387 * Window just ignores CO_CANCEL and ORPHANED,
2388 * so we do...
2390 status = NT_STATUS_OK;
2391 TALLOC_FREE(call);
2392 break;
2393 case DCERPC_PKT_BIND_ACK:
2394 case DCERPC_PKT_BIND_NAK:
2395 case DCERPC_PKT_ALTER_RESP:
2396 case DCERPC_PKT_RESPONSE:
2397 case DCERPC_PKT_FAULT:
2398 case DCERPC_PKT_SHUTDOWN:
2399 default:
2400 status = dcesrv_fault_disconnect(call, DCERPC_NCA_S_PROTO_ERROR);
2401 break;
2404 /* if we are going to be sending a reply then add
2405 it to the list of pending calls. We add it to the end to keep the call
2406 list in the order we will answer */
2407 if (!NT_STATUS_IS_OK(status)) {
2408 talloc_free(call);
2411 return status;
2414 _PUBLIC_ NTSTATUS dcesrv_init_context(TALLOC_CTX *mem_ctx,
2415 struct loadparm_context *lp_ctx,
2416 struct dcesrv_context_callbacks *cb,
2417 struct dcesrv_context **_dce_ctx)
2419 struct dcesrv_context *dce_ctx;
2421 if (cb == NULL) {
2422 return NT_STATUS_INVALID_PARAMETER;
2425 dce_ctx = talloc_zero(mem_ctx, struct dcesrv_context);
2426 NT_STATUS_HAVE_NO_MEMORY(dce_ctx);
2428 if (uid_wrapper_enabled()) {
2429 setenv("UID_WRAPPER_MYUID", "1", 1);
2431 dce_ctx->initial_euid = geteuid();
2432 if (uid_wrapper_enabled()) {
2433 unsetenv("UID_WRAPPER_MYUID");
2436 dce_ctx->endpoint_list = NULL;
2437 dce_ctx->lp_ctx = lp_ctx;
2438 dce_ctx->assoc_groups_idr = idr_init(dce_ctx);
2439 if (dce_ctx->assoc_groups_idr == NULL) {
2440 TALLOC_FREE(dce_ctx);
2441 return NT_STATUS_NO_MEMORY;
2443 dce_ctx->broken_connections = NULL;
2444 dce_ctx->callbacks = cb;
2446 *_dce_ctx = dce_ctx;
2447 return NT_STATUS_OK;
2451 * @brief Set callback functions on an existing dcesrv_context
2453 * This allows to reset callbacks initially set via
2454 * dcesrv_init_context()
2456 * @param[in] dce_ctx The context to set the callbacks on
2457 * @param[in] cb The callbacks to set on dce_ctx
2459 _PUBLIC_ void dcesrv_context_set_callbacks(
2460 struct dcesrv_context *dce_ctx,
2461 struct dcesrv_context_callbacks *cb)
2463 dce_ctx->callbacks = cb;
2466 _PUBLIC_ NTSTATUS dcesrv_init_ep_servers(struct dcesrv_context *dce_ctx,
2467 const char **endpoint_servers)
2469 NTSTATUS status;
2470 int i;
2472 if (endpoint_servers == NULL) {
2473 DBG_ERR("No endpoint servers configured\n");
2474 return NT_STATUS_INTERNAL_ERROR;
2477 for (i=0;endpoint_servers[i];i++) {
2478 status = dcesrv_init_ep_server(dce_ctx, endpoint_servers[i]);
2479 if (!NT_STATUS_IS_OK(status)) {
2480 DBG_ERR("failed to init endpoint server = '%s': %s\n",
2481 endpoint_servers[i], nt_errstr(status));
2482 return status;
2486 return NT_STATUS_OK;
2489 /* the list of currently registered DCERPC endpoint servers.
2491 static struct ep_server {
2492 struct dcesrv_endpoint_server *ep_server;
2493 } *ep_servers = NULL;
2494 static int num_ep_servers = 0;
2496 _PUBLIC_ NTSTATUS dcesrv_init_registered_ep_servers(
2497 struct dcesrv_context *dce_ctx)
2499 NTSTATUS status;
2500 int i;
2502 for (i = 0; i < num_ep_servers; i++) {
2503 status = dcesrv_init_ep_server(dce_ctx,
2504 ep_servers[i].ep_server->name);
2505 if (!NT_STATUS_IS_OK(status)) {
2506 return status;
2510 return NT_STATUS_OK;
2513 _PUBLIC_ NTSTATUS dcesrv_init_ep_server(struct dcesrv_context *dce_ctx,
2514 const char *ep_server_name)
2516 struct dcesrv_endpoint_server *ep_server = NULL;
2517 NTSTATUS status;
2519 ep_server = discard_const_p(struct dcesrv_endpoint_server,
2520 dcesrv_ep_server_byname(ep_server_name));
2521 if (ep_server == NULL) {
2522 DBG_ERR("Failed to find endpoint server '%s'\n",
2523 ep_server_name);
2524 return NT_STATUS_INTERNAL_ERROR;
2527 if (ep_server->initialized) {
2528 return NT_STATUS_OK;
2531 status = ep_server->init_server(dce_ctx, ep_server);
2532 if (!NT_STATUS_IS_OK(status)) {
2533 DBG_ERR("Failed to init endpoint server '%s': %s\n",
2534 ep_server_name, nt_errstr(status));
2535 return status;
2538 ep_server->initialized = true;
2540 return NT_STATUS_OK;
2543 _PUBLIC_ NTSTATUS dcesrv_shutdown_registered_ep_servers(
2544 struct dcesrv_context *dce_ctx)
2546 NTSTATUS status;
2547 int i;
2549 for (i = 0; i < num_ep_servers; i++) {
2550 status = dcesrv_shutdown_ep_server(dce_ctx,
2551 ep_servers[i].ep_server->name);
2552 if (!NT_STATUS_IS_OK(status)) {
2553 return status;
2557 return NT_STATUS_OK;
2560 _PUBLIC_ NTSTATUS dcesrv_shutdown_ep_server(struct dcesrv_context *dce_ctx,
2561 const char *ep_server_name)
2563 struct dcesrv_endpoint_server *ep_server = NULL;
2564 NTSTATUS status;
2566 ep_server = discard_const_p(struct dcesrv_endpoint_server,
2567 dcesrv_ep_server_byname(ep_server_name));
2568 if (ep_server == NULL) {
2569 DBG_ERR("Failed to find endpoint server '%s'\n",
2570 ep_server_name);
2571 return NT_STATUS_INTERNAL_ERROR;
2574 if (!ep_server->initialized) {
2575 return NT_STATUS_OK;
2578 DBG_INFO("Shutting down DCE/RPC endpoint server '%s'\n",
2579 ep_server_name);
2581 status = ep_server->shutdown_server(dce_ctx, ep_server);
2582 if (!NT_STATUS_IS_OK(status)) {
2583 DBG_ERR("Failed to shutdown endpoint server '%s': %s\n",
2584 ep_server_name, nt_errstr(status));
2585 return status;
2588 ep_server->initialized = false;
2590 return NT_STATUS_OK;
2594 register a DCERPC endpoint server.
2596 The 'name' can be later used by other backends to find the operations
2597 structure for this backend.
2600 _PUBLIC_ NTSTATUS dcerpc_register_ep_server(const struct dcesrv_endpoint_server *ep_server)
2603 if (dcesrv_ep_server_byname(ep_server->name) != NULL) {
2604 /* its already registered! */
2605 DEBUG(0,("DCERPC endpoint server '%s' already registered\n",
2606 ep_server->name));
2607 return NT_STATUS_OBJECT_NAME_COLLISION;
2610 ep_servers = realloc_p(ep_servers, struct ep_server, num_ep_servers+1);
2611 if (!ep_servers) {
2612 smb_panic("out of memory in dcerpc_register");
2615 ep_servers[num_ep_servers].ep_server = smb_xmemdup(ep_server, sizeof(*ep_server));
2616 ep_servers[num_ep_servers].ep_server->name = smb_xstrdup(ep_server->name);
2618 num_ep_servers++;
2620 DEBUG(3,("DCERPC endpoint server '%s' registered\n",
2621 ep_server->name));
2623 return NT_STATUS_OK;
2627 return the operations structure for a named backend of the specified type
2629 _PUBLIC_ const struct dcesrv_endpoint_server *dcesrv_ep_server_byname(const char *name)
2631 int i;
2633 for (i=0;i<num_ep_servers;i++) {
2634 if (strcmp(ep_servers[i].ep_server->name, name) == 0) {
2635 return ep_servers[i].ep_server;
2639 return NULL;
2643 return the DCERPC module version, and the size of some critical types
2644 This can be used by endpoint server modules to either detect compilation errors, or provide
2645 multiple implementations for different smbd compilation options in one module
2647 const struct dcesrv_critical_sizes *dcerpc_module_version(void)
2649 static const struct dcesrv_critical_sizes critical_sizes = {
2650 DCERPC_MODULE_VERSION,
2651 sizeof(struct dcesrv_context),
2652 sizeof(struct dcesrv_endpoint),
2653 sizeof(struct dcesrv_endpoint_server),
2654 sizeof(struct dcesrv_interface),
2655 sizeof(struct dcesrv_if_list),
2656 sizeof(struct dcesrv_connection),
2657 sizeof(struct dcesrv_call_state),
2658 sizeof(struct dcesrv_auth),
2659 sizeof(struct dcesrv_handle)
2662 return &critical_sizes;
2665 _PUBLIC_ void dcesrv_terminate_connection(struct dcesrv_connection *dce_conn, const char *reason)
2667 struct dcesrv_context *dce_ctx = dce_conn->dce_ctx;
2668 struct dcesrv_auth *a = NULL;
2670 dce_conn->wait_send = NULL;
2671 dce_conn->wait_recv = NULL;
2672 dce_conn->wait_private = NULL;
2674 dce_conn->allow_bind = false;
2675 dce_conn->allow_alter = false;
2677 dce_conn->default_auth_state->auth_invalid = true;
2679 for (a = dce_conn->auth_states; a != NULL; a = a->next) {
2680 a->auth_invalid = true;
2683 if (dce_conn->pending_call_list == NULL) {
2684 char *full_reason = talloc_asprintf(dce_conn, "dcesrv: %s", reason);
2686 DLIST_REMOVE(dce_ctx->broken_connections, dce_conn);
2687 dce_conn->transport.terminate_connection(dce_conn,
2688 full_reason ? full_reason : reason);
2689 return;
2692 if (dce_conn->terminate != NULL) {
2693 return;
2696 DEBUG(3,("dcesrv: terminating connection due to '%s' deferred due to pending calls\n",
2697 reason));
2698 dce_conn->terminate = talloc_strdup(dce_conn, reason);
2699 if (dce_conn->terminate == NULL) {
2700 dce_conn->terminate = "dcesrv: deferred terminating connection - no memory";
2702 DLIST_ADD_END(dce_ctx->broken_connections, dce_conn);
2705 _PUBLIC_ void dcesrv_cleanup_broken_connections(struct dcesrv_context *dce_ctx)
2707 struct dcesrv_connection *cur, *next;
2709 next = dce_ctx->broken_connections;
2710 while (next != NULL) {
2711 cur = next;
2712 next = cur->next;
2714 if (cur->state_flags & DCESRV_CALL_STATE_FLAG_PROCESS_PENDING_CALL) {
2715 struct dcesrv_connection_context *context_cur, *context_next;
2717 context_next = cur->contexts;
2718 while (context_next != NULL) {
2719 context_cur = context_next;
2720 context_next = context_cur->next;
2722 dcesrv_connection_context_destructor(context_cur);
2726 dcesrv_terminate_connection(cur, cur->terminate);
2730 struct dcesrv_sock_reply_state {
2731 struct dcesrv_connection *dce_conn;
2732 struct dcesrv_call_state *call;
2733 struct iovec iov;
2736 static void dcesrv_sock_reply_done(struct tevent_req *subreq);
2737 static void dcesrv_call_terminate_step1(struct tevent_req *subreq);
2739 _PUBLIC_ void dcesrv_sock_report_output_data(struct dcesrv_connection *dce_conn)
2741 struct dcesrv_call_state *call;
2743 call = dce_conn->call_list;
2744 if (!call || !call->replies) {
2745 return;
2748 while (call->replies) {
2749 struct data_blob_list_item *rep = call->replies;
2750 struct dcesrv_sock_reply_state *substate;
2751 struct tevent_req *subreq;
2753 substate = talloc_zero(call, struct dcesrv_sock_reply_state);
2754 if (!substate) {
2755 dcesrv_terminate_connection(dce_conn, "no memory");
2756 return;
2759 substate->dce_conn = dce_conn;
2760 substate->call = NULL;
2762 DLIST_REMOVE(call->replies, rep);
2764 if (call->replies == NULL && call->terminate_reason == NULL) {
2765 substate->call = call;
2768 substate->iov.iov_base = (void *) rep->blob.data;
2769 substate->iov.iov_len = rep->blob.length;
2771 subreq = tstream_writev_queue_send(substate,
2772 dce_conn->event_ctx,
2773 dce_conn->stream,
2774 dce_conn->send_queue,
2775 &substate->iov, 1);
2776 if (!subreq) {
2777 dcesrv_terminate_connection(dce_conn, "no memory");
2778 return;
2780 tevent_req_set_callback(subreq, dcesrv_sock_reply_done,
2781 substate);
2784 if (call->terminate_reason != NULL) {
2785 struct tevent_req *subreq;
2787 subreq = tevent_queue_wait_send(call,
2788 dce_conn->event_ctx,
2789 dce_conn->send_queue);
2790 if (!subreq) {
2791 dcesrv_terminate_connection(dce_conn, __location__);
2792 return;
2794 tevent_req_set_callback(subreq, dcesrv_call_terminate_step1,
2795 call);
2798 DLIST_REMOVE(call->conn->call_list, call);
2799 call->list = DCESRV_LIST_NONE;
2802 static void dcesrv_sock_reply_done(struct tevent_req *subreq)
2804 struct dcesrv_sock_reply_state *substate = tevent_req_callback_data(subreq,
2805 struct dcesrv_sock_reply_state);
2806 int ret;
2807 int sys_errno;
2808 NTSTATUS status;
2809 struct dcesrv_call_state *call = substate->call;
2811 ret = tstream_writev_queue_recv(subreq, &sys_errno);
2812 TALLOC_FREE(subreq);
2813 if (ret == -1) {
2814 status = map_nt_error_from_unix_common(sys_errno);
2815 dcesrv_terminate_connection(substate->dce_conn, nt_errstr(status));
2816 return;
2819 talloc_free(substate);
2820 if (call) {
2821 talloc_free(call);
2825 static void dcesrv_call_terminate_step2(struct tevent_req *subreq);
2827 static void dcesrv_call_terminate_step1(struct tevent_req *subreq)
2829 struct dcesrv_call_state *call = tevent_req_callback_data(subreq,
2830 struct dcesrv_call_state);
2831 bool ok;
2832 struct timeval tv;
2834 /* make sure we stop send queue before removing subreq */
2835 tevent_queue_stop(call->conn->send_queue);
2837 ok = tevent_queue_wait_recv(subreq);
2838 TALLOC_FREE(subreq);
2839 if (!ok) {
2840 dcesrv_terminate_connection(call->conn, __location__);
2841 return;
2844 /* disconnect after 200 usecs */
2845 tv = timeval_current_ofs_usec(200);
2846 subreq = tevent_wakeup_send(call, call->conn->event_ctx, tv);
2847 if (subreq == NULL) {
2848 dcesrv_terminate_connection(call->conn, __location__);
2849 return;
2851 tevent_req_set_callback(subreq, dcesrv_call_terminate_step2,
2852 call);
2855 static void dcesrv_call_terminate_step2(struct tevent_req *subreq)
2857 struct dcesrv_call_state *call = tevent_req_callback_data(subreq,
2858 struct dcesrv_call_state);
2859 bool ok;
2861 ok = tevent_wakeup_recv(subreq);
2862 TALLOC_FREE(subreq);
2863 if (!ok) {
2864 dcesrv_terminate_connection(call->conn, __location__);
2865 return;
2868 dcesrv_terminate_connection(call->conn, call->terminate_reason);
2871 static void dcesrv_conn_wait_done(struct tevent_req *subreq);
2873 static void dcesrv_read_fragment_done(struct tevent_req *subreq)
2875 struct dcesrv_connection *dce_conn = tevent_req_callback_data(subreq,
2876 struct dcesrv_connection);
2877 struct dcesrv_context *dce_ctx = dce_conn->dce_ctx;
2878 struct ncacn_packet *pkt;
2879 DATA_BLOB buffer;
2880 NTSTATUS status;
2882 if (dce_conn->terminate) {
2884 * if the current connection is broken
2885 * we need to clean it up before any other connection
2887 dcesrv_terminate_connection(dce_conn, dce_conn->terminate);
2888 dcesrv_cleanup_broken_connections(dce_ctx);
2889 return;
2892 dcesrv_cleanup_broken_connections(dce_ctx);
2894 status = dcerpc_read_ncacn_packet_recv(subreq, dce_conn,
2895 &pkt, &buffer);
2896 TALLOC_FREE(subreq);
2897 if (!NT_STATUS_IS_OK(status)) {
2898 dcesrv_terminate_connection(dce_conn, nt_errstr(status));
2899 return;
2902 dcesrv_loop_next_packet(dce_conn, pkt, buffer);
2906 * @brief Start the dcesrv loop, inducing the bind as a blob
2908 * Like dcesrv_connection_loop_start() but used from connections
2909 * where the caller has already read the dcerpc bind packet from
2910 * the socket and is available as a DATA_BLOB.
2912 * @param[in] dce_conn The connection to start
2913 * @param[in] pkt The parsed bind packet
2914 * @param[in] buffer The full binary bind including auth data
2916 void dcesrv_loop_next_packet(
2917 struct dcesrv_connection *dce_conn,
2918 struct ncacn_packet *pkt,
2919 DATA_BLOB buffer)
2921 struct tevent_req *subreq = NULL;
2922 NTSTATUS status;
2924 status = dcesrv_process_ncacn_packet(dce_conn, pkt, buffer);
2925 if (!NT_STATUS_IS_OK(status)) {
2926 dcesrv_terminate_connection(dce_conn, nt_errstr(status));
2927 return;
2931 * This is used to block the connection during
2932 * pending authentication.
2934 if (dce_conn->wait_send != NULL) {
2935 subreq = dce_conn->wait_send(dce_conn,
2936 dce_conn->event_ctx,
2937 dce_conn->wait_private);
2938 if (!subreq) {
2939 status = NT_STATUS_NO_MEMORY;
2940 dcesrv_terminate_connection(dce_conn, nt_errstr(status));
2941 return;
2943 tevent_req_set_callback(subreq, dcesrv_conn_wait_done, dce_conn);
2944 return;
2947 subreq = dcerpc_read_ncacn_packet_send(dce_conn,
2948 dce_conn->event_ctx,
2949 dce_conn->stream);
2950 if (!subreq) {
2951 status = NT_STATUS_NO_MEMORY;
2952 dcesrv_terminate_connection(dce_conn, nt_errstr(status));
2953 return;
2955 tevent_req_set_callback(subreq, dcesrv_read_fragment_done, dce_conn);
2958 static void dcesrv_conn_wait_done(struct tevent_req *subreq)
2960 struct dcesrv_connection *dce_conn = tevent_req_callback_data(subreq,
2961 struct dcesrv_connection);
2962 struct dcesrv_context *dce_ctx = dce_conn->dce_ctx;
2963 NTSTATUS status;
2965 if (dce_conn->terminate) {
2967 * if the current connection is broken
2968 * we need to clean it up before any other connection
2970 dcesrv_terminate_connection(dce_conn, dce_conn->terminate);
2971 dcesrv_cleanup_broken_connections(dce_ctx);
2972 return;
2975 dcesrv_cleanup_broken_connections(dce_ctx);
2977 status = dce_conn->wait_recv(subreq);
2978 dce_conn->wait_send = NULL;
2979 dce_conn->wait_recv = NULL;
2980 dce_conn->wait_private = NULL;
2981 TALLOC_FREE(subreq);
2982 if (!NT_STATUS_IS_OK(status)) {
2983 dcesrv_terminate_connection(dce_conn, nt_errstr(status));
2984 return;
2987 status = dcesrv_connection_loop_start(dce_conn);
2988 if (!NT_STATUS_IS_OK(status)) {
2989 dcesrv_terminate_connection(dce_conn, nt_errstr(status));
2990 return;
2995 * retrieve credentials from a dce_call
2997 _PUBLIC_ struct cli_credentials *dcesrv_call_credentials(struct dcesrv_call_state *dce_call)
2999 struct dcesrv_auth *auth = dce_call->auth_state;
3000 SMB_ASSERT(auth->auth_finished);
3001 return auth->session_info->credentials;
3005 * returns true if this is an authenticated call
3007 _PUBLIC_ bool dcesrv_call_authenticated(struct dcesrv_call_state *dce_call)
3009 struct dcesrv_auth *auth = dce_call->auth_state;
3010 enum security_user_level level;
3011 SMB_ASSERT(auth->auth_finished);
3012 level = security_session_user_level(auth->session_info, NULL);
3013 return level >= SECURITY_USER;
3017 * retrieve account_name for a dce_call
3019 _PUBLIC_ const char *dcesrv_call_account_name(struct dcesrv_call_state *dce_call)
3021 struct dcesrv_auth *auth = dce_call->auth_state;
3022 SMB_ASSERT(auth->auth_finished);
3023 return auth->session_info->info->account_name;
3027 * retrieve session_info from a dce_call
3029 _PUBLIC_ struct auth_session_info *dcesrv_call_session_info(struct dcesrv_call_state *dce_call)
3031 struct dcesrv_auth *auth = dce_call->auth_state;
3032 SMB_ASSERT(auth->auth_finished);
3033 return auth->session_info;
3037 * retrieve auth type/level from a dce_call
3039 _PUBLIC_ void dcesrv_call_auth_info(struct dcesrv_call_state *dce_call,
3040 enum dcerpc_AuthType *auth_type,
3041 enum dcerpc_AuthLevel *auth_level)
3043 struct dcesrv_auth *auth = dce_call->auth_state;
3045 SMB_ASSERT(auth->auth_finished);
3047 if (auth_type != NULL) {
3048 *auth_type = auth->auth_type;
3050 if (auth_level != NULL) {
3051 *auth_level = auth->auth_level;
3055 _PUBLIC_ NTSTATUS dcesrv_connection_loop_start(struct dcesrv_connection *conn)
3057 struct tevent_req *subreq;
3059 subreq = dcerpc_read_ncacn_packet_send(conn,
3060 conn->event_ctx,
3061 conn->stream);
3062 if (subreq == NULL) {
3063 return NT_STATUS_NO_MEMORY;
3065 tevent_req_set_callback(subreq, dcesrv_read_fragment_done, conn);
3067 return NT_STATUS_OK;
3070 _PUBLIC_ NTSTATUS dcesrv_call_dispatch_local(struct dcesrv_call_state *call)
3072 NTSTATUS status;
3073 struct ndr_pull *pull = NULL;
3074 struct ndr_push *push = NULL;
3075 struct data_blob_list_item *rep = NULL;
3077 pull = ndr_pull_init_blob(&call->pkt.u.request.stub_and_verifier,
3078 call);
3079 if (pull == NULL) {
3080 return NT_STATUS_NO_MEMORY;
3083 pull->flags |= LIBNDR_FLAG_REF_ALLOC;
3085 call->ndr_pull = pull;
3087 /* unravel the NDR for the packet */
3088 status = call->context->iface->ndr_pull(call, call, pull, &call->r);
3089 if (!NT_STATUS_IS_OK(status)) {
3090 DBG_INFO("DCE/RPC fault in call %s:%02X - %s\n",
3091 call->context->iface->name,
3092 call->pkt.u.request.opnum,
3093 dcerpc_errstr(call, call->fault_code));
3094 return dcerpc_fault_to_nt_status(call->fault_code);
3097 status = call->context->iface->local(call, call, call->r);
3098 if (!NT_STATUS_IS_OK(status)) {
3099 DBG_INFO("DCE/RPC fault in call %s:%02X - %s\n",
3100 call->context->iface->name,
3101 call->pkt.u.request.opnum,
3102 dcerpc_errstr(call, call->fault_code));
3103 return dcerpc_fault_to_nt_status(call->fault_code);
3106 /* This can never go async for now! */
3107 SMB_ASSERT(!(call->state_flags & DCESRV_CALL_STATE_FLAG_ASYNC));
3109 /* call the reply function */
3110 status = call->context->iface->reply(call, call, call->r);
3111 if (!NT_STATUS_IS_OK(status)) {
3112 DBG_INFO("DCE/RPC fault in call %s:%02X - %s\n",
3113 call->context->iface->name,
3114 call->pkt.u.request.opnum,
3115 dcerpc_errstr(call, call->fault_code));
3116 return dcerpc_fault_to_nt_status(call->fault_code);
3119 push = ndr_push_init_ctx(call);
3120 if (push == NULL) {
3121 return NT_STATUS_NO_MEMORY;
3124 push->ptr_count = call->ndr_pull->ptr_count;
3126 status = call->context->iface->ndr_push(call, call, push, call->r);
3127 if (!NT_STATUS_IS_OK(status)) {
3128 DBG_INFO("DCE/RPC fault in call %s:%02X - %s\n",
3129 call->context->iface->name,
3130 call->pkt.u.request.opnum,
3131 dcerpc_errstr(call, call->fault_code));
3132 return dcerpc_fault_to_nt_status(call->fault_code);
3135 rep = talloc_zero(call, struct data_blob_list_item);
3136 if (rep == NULL) {
3137 return NT_STATUS_NO_MEMORY;
3140 rep->blob = ndr_push_blob(push);
3141 DLIST_ADD_END(call->replies, rep);
3143 return NT_STATUS_OK;