s3: modules: vfs_glusterfs: Fix leak of char **lines onto mem_ctx on return.
[Samba.git] / librpc / rpc / dcesrv_core.c
blob88838121f2fb5ac31a62b80fb0d078a1c00ea310
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/gen_ndr/auth.h"
28 #include "auth/gensec/gensec.h"
29 #include "lib/util/dlinklist.h"
30 #include "libcli/security/security.h"
31 #include "param/param.h"
32 #include "lib/tsocket/tsocket.h"
33 #include "librpc/gen_ndr/ndr_dcerpc.h"
34 #include "lib/util/tevent_ntstatus.h"
37 #undef DBGC_CLASS
38 #define DBGC_CLASS DBGC_RPC_SRV
40 static NTSTATUS dcesrv_negotiate_contexts(struct dcesrv_call_state *call,
41 const struct dcerpc_bind *b,
42 struct dcerpc_ack_ctx *ack_ctx_list);
45 see if two endpoints match
47 static bool endpoints_match(const struct dcerpc_binding *ep1,
48 const struct dcerpc_binding *ep2)
50 enum dcerpc_transport_t t1;
51 enum dcerpc_transport_t t2;
52 const char *e1;
53 const char *e2;
55 t1 = dcerpc_binding_get_transport(ep1);
56 t2 = dcerpc_binding_get_transport(ep2);
58 e1 = dcerpc_binding_get_string_option(ep1, "endpoint");
59 e2 = dcerpc_binding_get_string_option(ep2, "endpoint");
61 if (t1 != t2) {
62 return false;
65 if (!e1 || !e2) {
66 return e1 == e2;
69 if (strcasecmp(e1, e2) != 0) {
70 return false;
73 return true;
77 find an endpoint in the dcesrv_context
79 _PUBLIC_ NTSTATUS dcesrv_find_endpoint(struct dcesrv_context *dce_ctx,
80 const struct dcerpc_binding *ep_description,
81 struct dcesrv_endpoint **_out)
83 struct dcesrv_endpoint *ep = NULL;
84 for (ep=dce_ctx->endpoint_list; ep; ep=ep->next) {
85 if (endpoints_match(ep->ep_description, ep_description)) {
86 *_out = ep;
87 return NT_STATUS_OK;
90 return NT_STATUS_NOT_FOUND;
94 find a registered context_id from a bind or alter_context
96 static struct dcesrv_connection_context *dcesrv_find_context(struct dcesrv_connection *conn,
97 uint16_t context_id)
99 struct dcesrv_connection_context *c;
100 for (c=conn->contexts;c;c=c->next) {
101 if (c->context_id == context_id) return c;
103 return NULL;
107 see if a uuid and if_version match to an interface
109 static bool interface_match(const struct dcesrv_interface *if1,
110 const struct dcesrv_interface *if2)
112 return (if1->syntax_id.if_version == if2->syntax_id.if_version &&
113 GUID_equal(&if1->syntax_id.uuid, &if2->syntax_id.uuid));
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 struct dcesrv_if_list *ifl;
127 for (ifl=ep->interface_list; ifl; ifl=ifl->next) {
128 if (interface_match(ifl->iface, iface)) {
129 return ifl->iface;
134 return NULL;
138 see if a uuid and if_version match to an interface
140 static bool interface_match_by_uuid(const struct dcesrv_interface *iface,
141 const struct GUID *uuid, uint32_t if_version)
143 return (iface->syntax_id.if_version == if_version &&
144 GUID_equal(&iface->syntax_id.uuid, uuid));
148 find the interface operations on an endpoint by uuid
150 _PUBLIC_ const struct dcesrv_interface *find_interface_by_uuid(const struct dcesrv_endpoint *endpoint,
151 const struct GUID *uuid, uint32_t if_version)
153 struct dcesrv_if_list *ifl;
154 for (ifl=endpoint->interface_list; ifl; ifl=ifl->next) {
155 if (interface_match_by_uuid(ifl->iface, uuid, if_version)) {
156 return ifl->iface;
159 return NULL;
163 find the earlier parts of a fragmented call awaiting reassembily
165 static struct dcesrv_call_state *dcesrv_find_fragmented_call(struct dcesrv_connection *dce_conn, uint32_t call_id)
167 struct dcesrv_call_state *c;
168 for (c=dce_conn->incoming_fragmented_call_list;c;c=c->next) {
169 if (c->pkt.call_id == call_id) {
170 return c;
173 return NULL;
177 register an interface on an endpoint
179 An endpoint is one unix domain socket (for ncalrpc), one TCP port
180 (for ncacn_ip_tcp) or one (forwarded) named pipe (for ncacn_np).
182 Each endpoint can have many interfaces such as netlogon, lsa or
183 samr. Some have essentially the full set.
185 This is driven from the set of interfaces listed in each IDL file
186 via the PIDL generated *__op_init_server() functions.
188 _PUBLIC_ NTSTATUS dcesrv_interface_register(struct dcesrv_context *dce_ctx,
189 const char *ep_name,
190 const char *ncacn_np_secondary_endpoint,
191 const struct dcesrv_interface *iface,
192 const struct security_descriptor *sd)
194 struct dcesrv_endpoint *ep;
195 struct dcesrv_if_list *ifl;
196 struct dcerpc_binding *binding;
197 struct dcerpc_binding *binding2 = NULL;
198 bool add_ep = false;
199 NTSTATUS status;
200 enum dcerpc_transport_t transport;
201 char *ep_string = NULL;
202 bool use_single_process = true;
203 const char *ep_process_string;
206 * If we are not using handles, there is no need for force
207 * this service into using a single process.
209 * However, due to the way we listen for RPC packets, we can
210 * only do this if we have a single service per pipe or TCP
211 * port, so we still force a single combined process for
212 * ncalrpc.
214 if (iface->flags & DCESRV_INTERFACE_FLAGS_HANDLES_NOT_USED) {
215 use_single_process = false;
218 status = dcerpc_parse_binding(dce_ctx, ep_name, &binding);
220 if (NT_STATUS_IS_ERR(status)) {
221 DEBUG(0, ("Trouble parsing binding string '%s'\n", ep_name));
222 return status;
225 transport = dcerpc_binding_get_transport(binding);
226 if (transport == NCACN_IP_TCP) {
227 int port;
228 char port_str[6];
231 * First check if there is already a port specified, eg
232 * for epmapper on ncacn_ip_tcp:[135]
234 const char *endpoint
235 = dcerpc_binding_get_string_option(binding,
236 "endpoint");
237 if (endpoint == NULL) {
238 port = lpcfg_parm_int(dce_ctx->lp_ctx, NULL,
239 "rpc server port", iface->name, 0);
242 * For RPC services that are not set to use a single
243 * process, we do not default to using the 'rpc server
244 * port' because that would cause a double-bind on
245 * that port.
247 if (port == 0 && !use_single_process) {
248 port = lpcfg_rpc_server_port(dce_ctx->lp_ctx);
250 if (port != 0) {
251 snprintf(port_str, sizeof(port_str), "%u", port);
252 status = dcerpc_binding_set_string_option(binding,
253 "endpoint",
254 port_str);
255 if (!NT_STATUS_IS_OK(status)) {
256 return status;
262 if (transport == NCACN_NP && ncacn_np_secondary_endpoint != NULL) {
263 enum dcerpc_transport_t transport2;
265 status = dcerpc_parse_binding(dce_ctx,
266 ncacn_np_secondary_endpoint,
267 &binding2);
268 if (!NT_STATUS_IS_OK(status)) {
269 DEBUG(0, ("Trouble parsing 2nd binding string '%s'\n",
270 ncacn_np_secondary_endpoint));
271 return status;
274 transport2 = dcerpc_binding_get_transport(binding2);
275 SMB_ASSERT(transport2 == transport);
278 /* see if the interface is already registered on the endpoint */
279 if (find_interface_by_binding(dce_ctx, binding, iface)!=NULL) {
280 DEBUG(0,("dcesrv_interface_register: interface '%s' already registered on endpoint '%s'\n",
281 iface->name, ep_name));
282 return NT_STATUS_OBJECT_NAME_COLLISION;
285 /* check if this endpoint exists
287 status = dcesrv_find_endpoint(dce_ctx, binding, &ep);
288 if (NT_STATUS_IS_OK(status)) {
290 * We want a new port on ncacn_ip_tcp for NETLOGON, so
291 * it can be multi-process. Other processes can also
292 * listen on distinct ports, if they have one forced
293 * in the code above with eg 'rpc server port:drsuapi = 1027'
295 * If we have mulitiple endpoints on port 0, they each
296 * get an epemeral port (currently by walking up from
297 * 1024).
299 * Because one endpoint can only have one process
300 * model, we add a new IP_TCP endpoint for each model.
302 * This works in conjunction with the forced overwrite
303 * of ep->use_single_process below.
305 if (ep->use_single_process != use_single_process
306 && transport == NCACN_IP_TCP) {
307 add_ep = true;
311 if (NT_STATUS_EQUAL(status, NT_STATUS_NOT_FOUND) || add_ep) {
312 ep = talloc_zero(dce_ctx, struct dcesrv_endpoint);
313 if (!ep) {
314 return NT_STATUS_NO_MEMORY;
316 ZERO_STRUCTP(ep);
317 ep->ep_description = talloc_move(ep, &binding);
318 ep->ep_2nd_description = talloc_move(ep, &binding2);
319 add_ep = true;
321 /* add mgmt interface */
322 ifl = talloc_zero(ep, struct dcesrv_if_list);
323 if (!ifl) {
324 return NT_STATUS_NO_MEMORY;
327 ifl->iface = talloc_memdup(ifl,
328 dcesrv_get_mgmt_interface(),
329 sizeof(struct dcesrv_interface));
330 if (ifl->iface == NULL) {
331 talloc_free(ep);
332 return NT_STATUS_NO_MEMORY;
335 DLIST_ADD(ep->interface_list, ifl);
336 } else if (!NT_STATUS_IS_OK(status)) {
337 DBG_NOTICE("Failed to find endpoint: %s\n", nt_errstr(status));
338 return status;
342 * By default don't force into a single process, but if any
343 * interface on this endpoint on this service uses handles
344 * (most do), then we must force into single process mode
346 * By overwriting this each time a new interface is added to
347 * this endpoint, we end up with the most restrictive setting.
349 if (use_single_process) {
350 ep->use_single_process = true;
353 /* talloc a new interface list element */
354 ifl = talloc_zero(ep, struct dcesrv_if_list);
355 if (!ifl) {
356 return NT_STATUS_NO_MEMORY;
359 /* copy the given interface struct to the one on the endpoints interface list */
360 ifl->iface = talloc_memdup(ifl,
361 iface,
362 sizeof(struct dcesrv_interface));
363 if (ifl->iface == NULL) {
364 talloc_free(ep);
365 return NT_STATUS_NO_MEMORY;
368 /* if we have a security descriptor given,
369 * we should see if we can set it up on the endpoint
371 if (sd != NULL) {
372 /* if there's currently no security descriptor given on the endpoint
373 * we try to set it
375 if (ep->sd == NULL) {
376 ep->sd = security_descriptor_copy(ep, sd);
379 /* if now there's no security descriptor given on the endpoint
380 * something goes wrong, either we failed to copy the security descriptor
381 * or there was already one on the endpoint
383 if (ep->sd != NULL) {
384 DEBUG(0,("dcesrv_interface_register: interface '%s' failed to setup a security descriptor\n"
385 " on endpoint '%s'\n",
386 iface->name, ep_name));
387 if (add_ep) free(ep);
388 free(ifl);
389 return NT_STATUS_OBJECT_NAME_COLLISION;
393 /* finally add the interface on the endpoint */
394 DLIST_ADD(ep->interface_list, ifl);
396 /* if it's a new endpoint add it to the dcesrv_context */
397 if (add_ep) {
398 DLIST_ADD(dce_ctx->endpoint_list, ep);
401 /* Re-get the string as we may have set a port */
402 ep_string = dcerpc_binding_string(dce_ctx, ep->ep_description);
404 if (use_single_process) {
405 ep_process_string = "single process required";
406 } else {
407 ep_process_string = "multi process compatible";
410 DBG_INFO("Interface '%s' registered on endpoint '%s' (%s)\n",
411 iface->name, ep_string, ep_process_string);
412 TALLOC_FREE(ep_string);
414 return NT_STATUS_OK;
417 static NTSTATUS dcesrv_session_info_session_key(struct dcesrv_auth *auth,
418 DATA_BLOB *session_key)
420 if (auth->session_info == NULL) {
421 return NT_STATUS_NO_USER_SESSION_KEY;
424 if (auth->session_info->session_key.length == 0) {
425 return NT_STATUS_NO_USER_SESSION_KEY;
428 *session_key = auth->session_info->session_key;
429 return NT_STATUS_OK;
432 static NTSTATUS dcesrv_remote_session_key(struct dcesrv_auth *auth,
433 DATA_BLOB *session_key)
435 if (auth->auth_type != DCERPC_AUTH_TYPE_NONE) {
436 return NT_STATUS_NO_USER_SESSION_KEY;
439 return dcesrv_session_info_session_key(auth, session_key);
442 static NTSTATUS dcesrv_local_fixed_session_key(struct dcesrv_auth *auth,
443 DATA_BLOB *session_key)
445 return dcerpc_generic_session_key(session_key);
449 * Fetch the authentication session key if available.
451 * This is the key generated by a gensec authentication.
454 _PUBLIC_ NTSTATUS dcesrv_auth_session_key(struct dcesrv_call_state *call,
455 DATA_BLOB *session_key)
457 struct dcesrv_auth *auth = call->auth_state;
458 SMB_ASSERT(auth->auth_finished);
459 return dcesrv_session_info_session_key(auth, session_key);
463 * Fetch the transport session key if available.
464 * Typically this is the SMB session key
465 * or a fixed key for local transports.
467 * The key is always truncated to 16 bytes.
469 _PUBLIC_ NTSTATUS dcesrv_transport_session_key(struct dcesrv_call_state *call,
470 DATA_BLOB *session_key)
472 struct dcesrv_auth *auth = call->auth_state;
473 NTSTATUS status;
475 SMB_ASSERT(auth->auth_finished);
477 if (auth->session_key_fn == NULL) {
478 return NT_STATUS_NO_USER_SESSION_KEY;
481 status = auth->session_key_fn(auth, session_key);
482 if (!NT_STATUS_IS_OK(status)) {
483 return status;
486 session_key->length = MIN(session_key->length, 16);
488 return NT_STATUS_OK;
491 static struct dcesrv_auth *dcesrv_auth_create(struct dcesrv_connection *conn)
493 const struct dcesrv_endpoint *ep = conn->endpoint;
494 enum dcerpc_transport_t transport =
495 dcerpc_binding_get_transport(ep->ep_description);
496 struct dcesrv_auth *auth = NULL;
498 auth = talloc_zero(conn, struct dcesrv_auth);
499 if (auth == NULL) {
500 return NULL;
503 switch (transport) {
504 case NCACN_NP:
505 auth->session_key_fn = dcesrv_remote_session_key;
506 break;
507 case NCALRPC:
508 case NCACN_UNIX_STREAM:
509 auth->session_key_fn = dcesrv_local_fixed_session_key;
510 break;
511 default:
513 * All other's get a NULL pointer, which
514 * results in NT_STATUS_NO_USER_SESSION_KEY
516 break;
519 return auth;
523 connect to a dcerpc endpoint
525 _PUBLIC_ NTSTATUS dcesrv_endpoint_connect(struct dcesrv_context *dce_ctx,
526 TALLOC_CTX *mem_ctx,
527 const struct dcesrv_endpoint *ep,
528 struct auth_session_info *session_info,
529 struct tevent_context *event_ctx,
530 uint32_t state_flags,
531 struct dcesrv_connection **_p)
533 struct dcesrv_auth *auth = NULL;
534 struct dcesrv_connection *p;
536 if (!session_info) {
537 return NT_STATUS_ACCESS_DENIED;
540 p = talloc_zero(mem_ctx, struct dcesrv_connection);
541 NT_STATUS_HAVE_NO_MEMORY(p);
543 p->dce_ctx = dce_ctx;
544 p->endpoint = ep;
545 p->packet_log_dir = lpcfg_parm_string(dce_ctx->lp_ctx,
546 NULL,
547 "dcesrv",
548 "stubs directory");
549 p->event_ctx = event_ctx;
550 p->state_flags = state_flags;
551 p->allow_bind = true;
552 p->max_recv_frag = 5840;
553 p->max_xmit_frag = 5840;
554 p->max_total_request_size = DCERPC_NCACN_REQUEST_DEFAULT_MAX_SIZE;
556 p->support_hdr_signing = lpcfg_parm_bool(dce_ctx->lp_ctx,
557 NULL,
558 "dcesrv",
559 "header signing",
560 true);
561 p->max_auth_states = lpcfg_parm_ulong(dce_ctx->lp_ctx,
562 NULL,
563 "dcesrv",
564 "max auth states",
565 2049);
567 auth = dcesrv_auth_create(p);
568 if (auth == NULL) {
569 talloc_free(p);
570 return NT_STATUS_NO_MEMORY;
573 auth->session_info = talloc_reference(auth, session_info);
574 if (auth->session_info == NULL) {
575 talloc_free(p);
576 return NT_STATUS_NO_MEMORY;
579 p->default_auth_state = auth;
582 * For now we only support NDR32.
584 p->preferred_transfer = &ndr_transfer_syntax_ndr;
586 *_p = p;
587 return NT_STATUS_OK;
591 move a call from an existing linked list to the specified list. This
592 prevents bugs where we forget to remove the call from a previous
593 list when moving it.
595 static void dcesrv_call_set_list(struct dcesrv_call_state *call,
596 enum dcesrv_call_list list)
598 switch (call->list) {
599 case DCESRV_LIST_NONE:
600 break;
601 case DCESRV_LIST_CALL_LIST:
602 DLIST_REMOVE(call->conn->call_list, call);
603 break;
604 case DCESRV_LIST_FRAGMENTED_CALL_LIST:
605 DLIST_REMOVE(call->conn->incoming_fragmented_call_list, call);
606 break;
607 case DCESRV_LIST_PENDING_CALL_LIST:
608 DLIST_REMOVE(call->conn->pending_call_list, call);
609 break;
611 call->list = list;
612 switch (list) {
613 case DCESRV_LIST_NONE:
614 break;
615 case DCESRV_LIST_CALL_LIST:
616 DLIST_ADD_END(call->conn->call_list, call);
617 break;
618 case DCESRV_LIST_FRAGMENTED_CALL_LIST:
619 DLIST_ADD_END(call->conn->incoming_fragmented_call_list, call);
620 break;
621 case DCESRV_LIST_PENDING_CALL_LIST:
622 DLIST_ADD_END(call->conn->pending_call_list, call);
623 break;
627 static void dcesrv_call_disconnect_after(struct dcesrv_call_state *call,
628 const char *reason)
630 struct dcesrv_auth *a = NULL;
632 if (call->conn->terminate != NULL) {
633 return;
636 call->conn->allow_bind = false;
637 call->conn->allow_alter = false;
639 call->conn->default_auth_state->auth_invalid = true;
641 for (a = call->conn->auth_states; a != NULL; a = a->next) {
642 a->auth_invalid = true;
645 call->terminate_reason = talloc_strdup(call, reason);
646 if (call->terminate_reason == NULL) {
647 call->terminate_reason = __location__;
652 return a dcerpc bind_nak
654 static NTSTATUS dcesrv_bind_nak(struct dcesrv_call_state *call, uint32_t reason)
656 struct ncacn_packet pkt;
657 struct dcerpc_bind_nak_version version;
658 struct data_blob_list_item *rep;
659 NTSTATUS status;
660 static const uint8_t _pad[3] = { 0, };
663 * We add the call to the pending_call_list
664 * in order to defer the termination.
666 dcesrv_call_disconnect_after(call, "dcesrv_bind_nak");
668 /* setup a bind_nak */
669 dcesrv_init_hdr(&pkt, lpcfg_rpc_big_endian(call->conn->dce_ctx->lp_ctx));
670 pkt.auth_length = 0;
671 pkt.call_id = call->pkt.call_id;
672 pkt.ptype = DCERPC_PKT_BIND_NAK;
673 pkt.pfc_flags = DCERPC_PFC_FLAG_FIRST | DCERPC_PFC_FLAG_LAST;
674 pkt.u.bind_nak.reject_reason = reason;
675 version.rpc_vers = 5;
676 version.rpc_vers_minor = 0;
677 pkt.u.bind_nak.num_versions = 1;
678 pkt.u.bind_nak.versions = &version;
679 pkt.u.bind_nak._pad = data_blob_const(_pad, sizeof(_pad));
681 rep = talloc_zero(call, struct data_blob_list_item);
682 if (!rep) {
683 return NT_STATUS_NO_MEMORY;
686 status = dcerpc_ncacn_push_auth(&rep->blob, call, &pkt, NULL);
687 if (!NT_STATUS_IS_OK(status)) {
688 return status;
691 dcerpc_set_frag_length(&rep->blob, rep->blob.length);
693 DLIST_ADD_END(call->replies, rep);
694 dcesrv_call_set_list(call, DCESRV_LIST_CALL_LIST);
696 if (call->conn->call_list && call->conn->call_list->replies) {
697 if (call->conn->transport.report_output_data) {
698 call->conn->transport.report_output_data(call->conn);
702 return NT_STATUS_OK;
705 static NTSTATUS dcesrv_fault_disconnect(struct dcesrv_call_state *call,
706 uint32_t fault_code)
709 * We add the call to the pending_call_list
710 * in order to defer the termination.
712 dcesrv_call_disconnect_after(call, "dcesrv_fault_disconnect");
714 return dcesrv_fault_with_flags(call, fault_code,
715 DCERPC_PFC_FLAG_DID_NOT_EXECUTE);
718 static int dcesrv_connection_context_destructor(struct dcesrv_connection_context *c)
720 DLIST_REMOVE(c->conn->contexts, c);
722 if (c->iface && c->iface->unbind) {
723 c->iface->unbind(c, c->iface);
724 c->iface = NULL;
727 return 0;
730 static void dcesrv_prepare_context_auth(struct dcesrv_call_state *dce_call)
732 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
733 const struct dcesrv_endpoint *endpoint = dce_call->conn->endpoint;
734 enum dcerpc_transport_t transport =
735 dcerpc_binding_get_transport(endpoint->ep_description);
736 struct dcesrv_connection_context *context = dce_call->context;
737 const struct dcesrv_interface *iface = context->iface;
739 context->min_auth_level = DCERPC_AUTH_LEVEL_NONE;
741 if (transport == NCALRPC) {
742 context->allow_connect = true;
743 return;
747 * allow overwrite per interface
748 * allow dcerpc auth level connect:<interface>
750 context->allow_connect = lpcfg_allow_dcerpc_auth_level_connect(lp_ctx);
751 context->allow_connect = lpcfg_parm_bool(lp_ctx, NULL,
752 "allow dcerpc auth level connect",
753 iface->name,
754 context->allow_connect);
757 NTSTATUS dcesrv_interface_bind_require_integrity(struct dcesrv_connection_context *context,
758 const struct dcesrv_interface *iface)
761 * For connection oriented DCERPC DCERPC_AUTH_LEVEL_PACKET (4)
762 * has the same behavior as DCERPC_AUTH_LEVEL_INTEGRITY (5).
764 context->min_auth_level = DCERPC_AUTH_LEVEL_PACKET;
765 return NT_STATUS_OK;
768 NTSTATUS dcesrv_interface_bind_require_privacy(struct dcesrv_connection_context *context,
769 const struct dcesrv_interface *iface)
771 context->min_auth_level = DCERPC_AUTH_LEVEL_PRIVACY;
772 return NT_STATUS_OK;
775 _PUBLIC_ NTSTATUS dcesrv_interface_bind_reject_connect(struct dcesrv_connection_context *context,
776 const struct dcesrv_interface *iface)
778 struct loadparm_context *lp_ctx = context->conn->dce_ctx->lp_ctx;
779 const struct dcesrv_endpoint *endpoint = context->conn->endpoint;
780 enum dcerpc_transport_t transport =
781 dcerpc_binding_get_transport(endpoint->ep_description);
783 if (transport == NCALRPC) {
784 context->allow_connect = true;
785 return NT_STATUS_OK;
789 * allow overwrite per interface
790 * allow dcerpc auth level connect:<interface>
792 context->allow_connect = false;
793 context->allow_connect = lpcfg_parm_bool(lp_ctx, NULL,
794 "allow dcerpc auth level connect",
795 iface->name,
796 context->allow_connect);
797 return NT_STATUS_OK;
800 _PUBLIC_ NTSTATUS dcesrv_interface_bind_allow_connect(struct dcesrv_connection_context *context,
801 const struct dcesrv_interface *iface)
803 struct loadparm_context *lp_ctx = context->conn->dce_ctx->lp_ctx;
804 const struct dcesrv_endpoint *endpoint = context->conn->endpoint;
805 enum dcerpc_transport_t transport =
806 dcerpc_binding_get_transport(endpoint->ep_description);
808 if (transport == NCALRPC) {
809 context->allow_connect = true;
810 return NT_STATUS_OK;
814 * allow overwrite per interface
815 * allow dcerpc auth level connect:<interface>
817 context->allow_connect = true;
818 context->allow_connect = lpcfg_parm_bool(lp_ctx, NULL,
819 "allow dcerpc auth level connect",
820 iface->name,
821 context->allow_connect);
822 return NT_STATUS_OK;
825 struct dcesrv_conn_auth_wait_context {
826 struct tevent_req *req;
827 bool done;
828 NTSTATUS status;
831 struct dcesrv_conn_auth_wait_state {
832 uint8_t dummy;
835 static struct tevent_req *dcesrv_conn_auth_wait_send(TALLOC_CTX *mem_ctx,
836 struct tevent_context *ev,
837 void *private_data)
839 struct dcesrv_conn_auth_wait_context *auth_wait =
840 talloc_get_type_abort(private_data,
841 struct dcesrv_conn_auth_wait_context);
842 struct tevent_req *req = NULL;
843 struct dcesrv_conn_auth_wait_state *state = NULL;
845 req = tevent_req_create(mem_ctx, &state,
846 struct dcesrv_conn_auth_wait_state);
847 if (req == NULL) {
848 return NULL;
850 auth_wait->req = req;
852 tevent_req_defer_callback(req, ev);
854 if (!auth_wait->done) {
855 return req;
858 if (tevent_req_nterror(req, auth_wait->status)) {
859 return tevent_req_post(req, ev);
862 tevent_req_done(req);
863 return tevent_req_post(req, ev);
866 static NTSTATUS dcesrv_conn_auth_wait_recv(struct tevent_req *req)
868 return tevent_req_simple_recv_ntstatus(req);
871 static NTSTATUS dcesrv_conn_auth_wait_setup(struct dcesrv_connection *conn)
873 struct dcesrv_conn_auth_wait_context *auth_wait = NULL;
875 if (conn->wait_send != NULL) {
876 return NT_STATUS_INTERNAL_ERROR;
879 auth_wait = talloc_zero(conn, struct dcesrv_conn_auth_wait_context);
880 if (auth_wait == NULL) {
881 return NT_STATUS_NO_MEMORY;
884 conn->wait_private = auth_wait;
885 conn->wait_send = dcesrv_conn_auth_wait_send;
886 conn->wait_recv = dcesrv_conn_auth_wait_recv;
887 return NT_STATUS_OK;
890 static void dcesrv_conn_auth_wait_finished(struct dcesrv_connection *conn,
891 NTSTATUS status)
893 struct dcesrv_conn_auth_wait_context *auth_wait =
894 talloc_get_type_abort(conn->wait_private,
895 struct dcesrv_conn_auth_wait_context);
897 auth_wait->done = true;
898 auth_wait->status = status;
900 if (auth_wait->req == NULL) {
901 return;
904 if (tevent_req_nterror(auth_wait->req, status)) {
905 return;
908 tevent_req_done(auth_wait->req);
911 static NTSTATUS dcesrv_auth_reply(struct dcesrv_call_state *call);
913 static void dcesrv_bind_done(struct tevent_req *subreq);
916 handle a bind request
918 static NTSTATUS dcesrv_bind(struct dcesrv_call_state *call)
920 struct dcesrv_connection *conn = call->conn;
921 struct ncacn_packet *pkt = &call->ack_pkt;
922 NTSTATUS status;
923 uint32_t extra_flags = 0;
924 uint16_t max_req = 0;
925 uint16_t max_rep = 0;
926 struct dcerpc_binding *ep_2nd_description = NULL;
927 const char *endpoint = NULL;
928 struct dcesrv_auth *auth = call->auth_state;
929 struct dcerpc_ack_ctx *ack_ctx_list = NULL;
930 struct dcerpc_ack_ctx *ack_features = NULL;
931 struct tevent_req *subreq = NULL;
932 size_t i;
934 status = dcerpc_verify_ncacn_packet_header(&call->pkt,
935 DCERPC_PKT_BIND,
936 call->pkt.u.bind.auth_info.length,
937 0, /* required flags */
938 DCERPC_PFC_FLAG_FIRST |
939 DCERPC_PFC_FLAG_LAST |
940 DCERPC_PFC_FLAG_SUPPORT_HEADER_SIGN |
941 0x08 | /* this is not defined, but should be ignored */
942 DCERPC_PFC_FLAG_CONC_MPX |
943 DCERPC_PFC_FLAG_DID_NOT_EXECUTE |
944 DCERPC_PFC_FLAG_MAYBE |
945 DCERPC_PFC_FLAG_OBJECT_UUID);
946 if (!NT_STATUS_IS_OK(status)) {
947 return dcesrv_bind_nak(call,
948 DCERPC_BIND_NAK_REASON_PROTOCOL_VERSION_NOT_SUPPORTED);
951 /* max_recv_frag and max_xmit_frag result always in the same value! */
952 max_req = MIN(call->pkt.u.bind.max_xmit_frag,
953 call->pkt.u.bind.max_recv_frag);
955 * The values are between 2048 and 5840 tested against Windows 2012R2
956 * via ncacn_ip_tcp on port 135.
958 max_req = MAX(2048, max_req);
959 max_rep = MIN(max_req, call->conn->max_recv_frag);
960 /* They are truncated to an 8 byte boundary. */
961 max_rep &= 0xFFF8;
963 /* max_recv_frag and max_xmit_frag result always in the same value! */
964 call->conn->max_recv_frag = max_rep;
965 call->conn->max_xmit_frag = max_rep;
967 status = call->conn->dce_ctx->callbacks.assoc_group.find(call);
968 if (!NT_STATUS_IS_OK(status)) {
969 DBG_NOTICE("Failed to find assoc_group 0x%08x: %s\n",
970 call->pkt.u.bind.assoc_group_id, nt_errstr(status));
971 return dcesrv_bind_nak(call, 0);
974 if (call->pkt.u.bind.num_contexts < 1) {
975 return dcesrv_bind_nak(call, 0);
978 ack_ctx_list = talloc_zero_array(call, struct dcerpc_ack_ctx,
979 call->pkt.u.bind.num_contexts);
980 if (ack_ctx_list == NULL) {
981 return dcesrv_bind_nak(call, 0);
985 * Set some sane defaults (required by dcesrv_negotiate_contexts()/
986 * dcesrv_check_or_create_context()) and do some protocol validation
987 * and set sane defaults.
989 for (i = 0; i < call->pkt.u.bind.num_contexts; i++) {
990 const struct dcerpc_ctx_list *c = &call->pkt.u.bind.ctx_list[i];
991 struct dcerpc_ack_ctx *a = &ack_ctx_list[i];
992 bool is_feature = false;
993 uint64_t features = 0;
995 if (c->num_transfer_syntaxes == 0) {
996 return dcesrv_bind_nak(call, 0);
999 a->result = DCERPC_BIND_ACK_RESULT_PROVIDER_REJECTION;
1000 a->reason.value = DCERPC_BIND_ACK_REASON_ABSTRACT_SYNTAX_NOT_SUPPORTED;
1003 * It's only treated as bind time feature request, if the first
1004 * transfer_syntax matches, all others are ignored.
1006 is_feature = dcerpc_extract_bind_time_features(c->transfer_syntaxes[0],
1007 &features);
1008 if (!is_feature) {
1009 continue;
1012 if (ack_features != NULL) {
1014 * Only one bind time feature context is allowed.
1016 return dcesrv_bind_nak(call, 0);
1018 ack_features = a;
1020 a->result = DCERPC_BIND_ACK_RESULT_NEGOTIATE_ACK;
1021 a->reason.negotiate = 0;
1022 if (features & DCERPC_BIND_TIME_SECURITY_CONTEXT_MULTIPLEXING) {
1023 if (call->conn->max_auth_states != 0) {
1024 a->reason.negotiate |=
1025 DCERPC_BIND_TIME_SECURITY_CONTEXT_MULTIPLEXING;
1028 if (features & DCERPC_BIND_TIME_KEEP_CONNECTION_ON_ORPHAN) {
1029 a->reason.negotiate |=
1030 DCERPC_BIND_TIME_KEEP_CONNECTION_ON_ORPHAN;
1033 call->conn->assoc_group->bind_time_features = a->reason.negotiate;
1037 * Try to negotiate one new presentation context.
1039 * Deep in here we locate the iface (by uuid) that the client
1040 * requested, from the list of interfaces on the
1041 * call->conn->endpoint, and call iface->bind() on that iface.
1043 * call->conn was set up at the accept() of the socket, and
1044 * call->conn->endpoint has a list of interfaces restricted to
1045 * this port or pipe.
1047 status = dcesrv_negotiate_contexts(call, &call->pkt.u.bind, ack_ctx_list);
1048 if (NT_STATUS_EQUAL(status, NT_STATUS_RPC_PROTOCOL_ERROR)) {
1049 return dcesrv_bind_nak(call, 0);
1051 if (!NT_STATUS_IS_OK(status)) {
1052 return status;
1056 * At this point we still don't know which interface (eg
1057 * netlogon, lsa, drsuapi) the caller requested in this bind!
1058 * The most recently added context is available as the first
1059 * element in the linked list at call->conn->contexts, that is
1060 * call->conn->contexts->iface, but they may not have
1061 * requested one at all!
1064 if ((call->pkt.pfc_flags & DCERPC_PFC_FLAG_CONC_MPX) &&
1065 (call->state_flags & DCESRV_CALL_STATE_FLAG_MULTIPLEXED)) {
1066 call->conn->state_flags |= DCESRV_CALL_STATE_FLAG_MULTIPLEXED;
1067 extra_flags |= DCERPC_PFC_FLAG_CONC_MPX;
1070 if (call->state_flags & DCESRV_CALL_STATE_FLAG_PROCESS_PENDING_CALL) {
1071 call->conn->state_flags |= DCESRV_CALL_STATE_FLAG_PROCESS_PENDING_CALL;
1075 * After finding the interface and setting up the NDR
1076 * transport negotiation etc, handle any authentication that
1077 * is being requested.
1079 if (!dcesrv_auth_bind(call)) {
1081 if (auth->auth_level == DCERPC_AUTH_LEVEL_NONE) {
1083 * With DCERPC_AUTH_LEVEL_NONE, we get the
1084 * reject_reason in auth->auth_context_id.
1086 return dcesrv_bind_nak(call, auth->auth_context_id);
1090 * This must a be a temporary failure e.g. talloc or invalid
1091 * configuration, e.g. no machine account.
1093 return dcesrv_bind_nak(call,
1094 DCERPC_BIND_NAK_REASON_TEMPORARY_CONGESTION);
1097 /* setup a bind_ack */
1098 dcesrv_init_hdr(pkt, lpcfg_rpc_big_endian(call->conn->dce_ctx->lp_ctx));
1099 pkt->auth_length = 0;
1100 pkt->call_id = call->pkt.call_id;
1101 pkt->ptype = DCERPC_PKT_BIND_ACK;
1102 pkt->pfc_flags = DCERPC_PFC_FLAG_FIRST | DCERPC_PFC_FLAG_LAST | extra_flags;
1103 pkt->u.bind_ack.max_xmit_frag = call->conn->max_xmit_frag;
1104 pkt->u.bind_ack.max_recv_frag = call->conn->max_recv_frag;
1105 pkt->u.bind_ack.assoc_group_id = call->conn->assoc_group->id;
1107 ep_2nd_description = call->conn->endpoint->ep_2nd_description;
1108 if (ep_2nd_description == NULL) {
1109 ep_2nd_description = call->conn->endpoint->ep_description;
1112 endpoint = dcerpc_binding_get_string_option(
1113 ep_2nd_description,
1114 "endpoint");
1115 if (endpoint == NULL) {
1116 endpoint = "";
1119 pkt->u.bind_ack.secondary_address = endpoint;
1120 pkt->u.bind_ack.num_results = call->pkt.u.bind.num_contexts;
1121 pkt->u.bind_ack.ctx_list = ack_ctx_list;
1122 pkt->u.bind_ack.auth_info = data_blob_null;
1124 status = dcesrv_auth_prepare_bind_ack(call, pkt);
1125 if (!NT_STATUS_IS_OK(status)) {
1126 return dcesrv_bind_nak(call, 0);
1129 if (auth->auth_finished) {
1130 return dcesrv_auth_reply(call);
1133 subreq = gensec_update_send(call, call->event_ctx,
1134 auth->gensec_security,
1135 call->in_auth_info.credentials);
1136 if (subreq == NULL) {
1137 return NT_STATUS_NO_MEMORY;
1139 tevent_req_set_callback(subreq, dcesrv_bind_done, call);
1141 return dcesrv_conn_auth_wait_setup(conn);
1144 static void dcesrv_bind_done(struct tevent_req *subreq)
1146 struct dcesrv_call_state *call =
1147 tevent_req_callback_data(subreq,
1148 struct dcesrv_call_state);
1149 struct dcesrv_connection *conn = call->conn;
1150 NTSTATUS status;
1152 status = gensec_update_recv(subreq, call,
1153 &call->out_auth_info->credentials);
1154 TALLOC_FREE(subreq);
1156 status = dcesrv_auth_complete(call, status);
1157 if (!NT_STATUS_IS_OK(status)) {
1158 status = dcesrv_bind_nak(call, 0);
1159 dcesrv_conn_auth_wait_finished(conn, status);
1160 return;
1163 status = dcesrv_auth_reply(call);
1164 dcesrv_conn_auth_wait_finished(conn, status);
1165 return;
1168 static NTSTATUS dcesrv_auth_reply(struct dcesrv_call_state *call)
1170 struct ncacn_packet *pkt = &call->ack_pkt;
1171 struct data_blob_list_item *rep = NULL;
1172 NTSTATUS status;
1174 rep = talloc_zero(call, struct data_blob_list_item);
1175 if (!rep) {
1176 return NT_STATUS_NO_MEMORY;
1179 status = dcerpc_ncacn_push_auth(&rep->blob,
1180 call,
1181 pkt,
1182 call->out_auth_info);
1183 if (!NT_STATUS_IS_OK(status)) {
1184 return status;
1187 dcerpc_set_frag_length(&rep->blob, rep->blob.length);
1189 DLIST_ADD_END(call->replies, rep);
1190 dcesrv_call_set_list(call, DCESRV_LIST_CALL_LIST);
1192 if (call->conn->call_list && call->conn->call_list->replies) {
1193 if (call->conn->transport.report_output_data) {
1194 call->conn->transport.report_output_data(call->conn);
1198 return NT_STATUS_OK;
1202 static void dcesrv_auth3_done(struct tevent_req *subreq);
1205 handle a auth3 request
1207 static NTSTATUS dcesrv_auth3(struct dcesrv_call_state *call)
1209 struct dcesrv_connection *conn = call->conn;
1210 struct dcesrv_auth *auth = call->auth_state;
1211 struct tevent_req *subreq = NULL;
1212 NTSTATUS status;
1214 if (!auth->auth_started) {
1215 return dcesrv_fault_disconnect(call, DCERPC_NCA_S_PROTO_ERROR);
1218 if (auth->auth_finished) {
1219 return dcesrv_fault_disconnect(call, DCERPC_NCA_S_PROTO_ERROR);
1222 status = dcerpc_verify_ncacn_packet_header(&call->pkt,
1223 DCERPC_PKT_AUTH3,
1224 call->pkt.u.auth3.auth_info.length,
1225 0, /* required flags */
1226 DCERPC_PFC_FLAG_FIRST |
1227 DCERPC_PFC_FLAG_LAST |
1228 DCERPC_PFC_FLAG_SUPPORT_HEADER_SIGN |
1229 0x08 | /* this is not defined, but should be ignored */
1230 DCERPC_PFC_FLAG_CONC_MPX |
1231 DCERPC_PFC_FLAG_DID_NOT_EXECUTE |
1232 DCERPC_PFC_FLAG_MAYBE |
1233 DCERPC_PFC_FLAG_OBJECT_UUID);
1234 if (!NT_STATUS_IS_OK(status)) {
1235 return dcesrv_fault_disconnect(call, DCERPC_NCA_S_PROTO_ERROR);
1238 /* handle the auth3 in the auth code */
1239 if (!dcesrv_auth_prepare_auth3(call)) {
1241 * we don't send a reply to a auth3 request,
1242 * except by a fault.
1244 * In anycase we mark the connection as
1245 * invalid.
1247 auth->auth_invalid = true;
1248 if (call->fault_code != 0) {
1249 return dcesrv_fault_disconnect(call, call->fault_code);
1251 TALLOC_FREE(call);
1252 return NT_STATUS_OK;
1255 subreq = gensec_update_send(call, call->event_ctx,
1256 auth->gensec_security,
1257 call->in_auth_info.credentials);
1258 if (subreq == NULL) {
1259 return NT_STATUS_NO_MEMORY;
1261 tevent_req_set_callback(subreq, dcesrv_auth3_done, call);
1263 return dcesrv_conn_auth_wait_setup(conn);
1266 static void dcesrv_auth3_done(struct tevent_req *subreq)
1268 struct dcesrv_call_state *call =
1269 tevent_req_callback_data(subreq,
1270 struct dcesrv_call_state);
1271 struct dcesrv_connection *conn = call->conn;
1272 struct dcesrv_auth *auth = call->auth_state;
1273 NTSTATUS status;
1275 status = gensec_update_recv(subreq, call,
1276 &call->out_auth_info->credentials);
1277 TALLOC_FREE(subreq);
1279 status = dcesrv_auth_complete(call, status);
1280 if (!NT_STATUS_IS_OK(status)) {
1282 * we don't send a reply to a auth3 request,
1283 * except by a fault.
1285 * In anycase we mark the connection as
1286 * invalid.
1288 auth->auth_invalid = true;
1289 if (call->fault_code != 0) {
1290 status = dcesrv_fault_disconnect(call, call->fault_code);
1291 dcesrv_conn_auth_wait_finished(conn, status);
1292 return;
1294 TALLOC_FREE(call);
1295 dcesrv_conn_auth_wait_finished(conn, NT_STATUS_OK);
1296 return;
1300 * we don't send a reply to a auth3 request.
1302 TALLOC_FREE(call);
1303 dcesrv_conn_auth_wait_finished(conn, NT_STATUS_OK);
1304 return;
1308 static NTSTATUS dcesrv_check_or_create_context(struct dcesrv_call_state *call,
1309 const struct dcerpc_bind *b,
1310 const struct dcerpc_ctx_list *ctx,
1311 struct dcerpc_ack_ctx *ack,
1312 bool validate_only,
1313 const struct ndr_syntax_id *supported_transfer)
1315 uint32_t if_version;
1316 struct dcesrv_connection_context *context;
1317 const struct dcesrv_interface *iface;
1318 struct GUID uuid;
1319 NTSTATUS status;
1320 const struct ndr_syntax_id *selected_transfer = NULL;
1321 size_t i;
1322 bool ok;
1324 if (b == NULL) {
1325 return NT_STATUS_INTERNAL_ERROR;
1327 if (ctx == NULL) {
1328 return NT_STATUS_INTERNAL_ERROR;
1330 if (ctx->num_transfer_syntaxes < 1) {
1331 return NT_STATUS_INTERNAL_ERROR;
1333 if (ack == NULL) {
1334 return NT_STATUS_INTERNAL_ERROR;
1336 if (supported_transfer == NULL) {
1337 return NT_STATUS_INTERNAL_ERROR;
1340 switch (ack->result) {
1341 case DCERPC_BIND_ACK_RESULT_ACCEPTANCE:
1342 case DCERPC_BIND_ACK_RESULT_NEGOTIATE_ACK:
1344 * We is already completed.
1346 return NT_STATUS_OK;
1347 default:
1348 break;
1351 ack->result = DCERPC_BIND_ACK_RESULT_PROVIDER_REJECTION;
1352 ack->reason.value = DCERPC_BIND_ACK_REASON_ABSTRACT_SYNTAX_NOT_SUPPORTED;
1354 if_version = ctx->abstract_syntax.if_version;
1355 uuid = ctx->abstract_syntax.uuid;
1357 iface = find_interface_by_uuid(call->conn->endpoint, &uuid, if_version);
1358 if (iface == NULL) {
1359 char *uuid_str = GUID_string(call, &uuid);
1360 DEBUG(2,("Request for unknown dcerpc interface %s/%d\n", uuid_str, if_version));
1361 talloc_free(uuid_str);
1363 * We report this only via ack->result
1365 return NT_STATUS_OK;
1368 ack->result = DCERPC_BIND_ACK_RESULT_PROVIDER_REJECTION;
1369 ack->reason.value = DCERPC_BIND_ACK_REASON_TRANSFER_SYNTAXES_NOT_SUPPORTED;
1371 if (validate_only) {
1373 * We report this only via ack->result
1375 return NT_STATUS_OK;
1378 for (i = 0; i < ctx->num_transfer_syntaxes; i++) {
1380 * we only do NDR encoded dcerpc for now.
1382 ok = ndr_syntax_id_equal(&ctx->transfer_syntaxes[i],
1383 supported_transfer);
1384 if (ok) {
1385 selected_transfer = supported_transfer;
1386 break;
1390 context = dcesrv_find_context(call->conn, ctx->context_id);
1391 if (context != NULL) {
1392 ok = ndr_syntax_id_equal(&context->iface->syntax_id,
1393 &ctx->abstract_syntax);
1394 if (!ok) {
1395 return NT_STATUS_RPC_PROTOCOL_ERROR;
1398 if (selected_transfer != NULL) {
1399 ok = ndr_syntax_id_equal(&context->transfer_syntax,
1400 selected_transfer);
1401 if (!ok) {
1402 return NT_STATUS_RPC_PROTOCOL_ERROR;
1405 ack->result = DCERPC_BIND_ACK_RESULT_ACCEPTANCE;
1406 ack->reason.value = DCERPC_BIND_ACK_REASON_NOT_SPECIFIED;
1407 ack->syntax = context->transfer_syntax;
1411 * We report this only via ack->result
1413 return NT_STATUS_OK;
1416 if (selected_transfer == NULL) {
1418 * We report this only via ack->result
1420 return NT_STATUS_OK;
1423 ack->result = DCERPC_BIND_ACK_RESULT_USER_REJECTION;
1424 ack->reason.value = DCERPC_BIND_ACK_REASON_LOCAL_LIMIT_EXCEEDED;
1426 /* add this context to the list of available context_ids */
1427 context = talloc_zero(call->conn, struct dcesrv_connection_context);
1428 if (context == NULL) {
1429 return NT_STATUS_NO_MEMORY;
1431 context->conn = call->conn;
1432 context->context_id = ctx->context_id;
1433 context->iface = iface;
1434 context->transfer_syntax = *selected_transfer;
1435 DLIST_ADD(call->conn->contexts, context);
1436 call->context = context;
1437 talloc_set_destructor(context, dcesrv_connection_context_destructor);
1439 dcesrv_prepare_context_auth(call);
1442 * Multiplex is supported by default
1444 call->state_flags |= DCESRV_CALL_STATE_FLAG_MULTIPLEXED;
1446 status = iface->bind(context, iface);
1447 call->context = NULL;
1448 if (!NT_STATUS_IS_OK(status)) {
1449 /* we don't want to trigger the iface->unbind() hook */
1450 context->iface = NULL;
1451 talloc_free(context);
1453 * We report this only via ack->result
1455 return NT_STATUS_OK;
1458 ack->result = DCERPC_BIND_ACK_RESULT_ACCEPTANCE;
1459 ack->reason.value = DCERPC_BIND_ACK_REASON_NOT_SPECIFIED;
1460 ack->syntax = context->transfer_syntax;
1461 return NT_STATUS_OK;
1464 static NTSTATUS dcesrv_negotiate_contexts(struct dcesrv_call_state *call,
1465 const struct dcerpc_bind *b,
1466 struct dcerpc_ack_ctx *ack_ctx_list)
1468 NTSTATUS status;
1469 size_t i;
1470 bool validate_only = false;
1471 bool preferred_ndr32;
1474 * Try to negotiate one new presentation context,
1475 * using our preferred transfer syntax.
1477 for (i = 0; i < b->num_contexts; i++) {
1478 const struct dcerpc_ctx_list *c = &b->ctx_list[i];
1479 struct dcerpc_ack_ctx *a = &ack_ctx_list[i];
1481 status = dcesrv_check_or_create_context(call, b, c, a,
1482 validate_only,
1483 call->conn->preferred_transfer);
1484 if (!NT_STATUS_IS_OK(status)) {
1485 return status;
1488 if (a->result == DCERPC_BIND_ACK_RESULT_ACCEPTANCE) {
1490 * We managed to negotiate one context.
1492 * => we're done.
1494 validate_only = true;
1498 preferred_ndr32 = ndr_syntax_id_equal(&ndr_transfer_syntax_ndr,
1499 call->conn->preferred_transfer);
1500 if (preferred_ndr32) {
1502 * We're done.
1504 return NT_STATUS_OK;
1508 * Try to negotiate one new presentation context,
1509 * using NDR 32 as fallback.
1511 for (i = 0; i < b->num_contexts; i++) {
1512 const struct dcerpc_ctx_list *c = &b->ctx_list[i];
1513 struct dcerpc_ack_ctx *a = &ack_ctx_list[i];
1515 status = dcesrv_check_or_create_context(call, b, c, a,
1516 validate_only,
1517 &ndr_transfer_syntax_ndr);
1518 if (!NT_STATUS_IS_OK(status)) {
1519 return status;
1522 if (a->result == DCERPC_BIND_ACK_RESULT_ACCEPTANCE) {
1524 * We managed to negotiate one context.
1526 * => we're done.
1528 validate_only = true;
1532 return NT_STATUS_OK;
1535 static void dcesrv_alter_done(struct tevent_req *subreq);
1538 handle a alter context request
1540 static NTSTATUS dcesrv_alter(struct dcesrv_call_state *call)
1542 struct dcesrv_connection *conn = call->conn;
1543 NTSTATUS status;
1544 bool auth_ok = false;
1545 struct ncacn_packet *pkt = &call->ack_pkt;
1546 uint32_t extra_flags = 0;
1547 struct dcesrv_auth *auth = call->auth_state;
1548 struct dcerpc_ack_ctx *ack_ctx_list = NULL;
1549 struct tevent_req *subreq = NULL;
1550 size_t i;
1552 if (!call->conn->allow_alter) {
1553 return dcesrv_fault_disconnect(call, DCERPC_NCA_S_PROTO_ERROR);
1556 status = dcerpc_verify_ncacn_packet_header(&call->pkt,
1557 DCERPC_PKT_ALTER,
1558 call->pkt.u.alter.auth_info.length,
1559 0, /* required flags */
1560 DCERPC_PFC_FLAG_FIRST |
1561 DCERPC_PFC_FLAG_LAST |
1562 DCERPC_PFC_FLAG_SUPPORT_HEADER_SIGN |
1563 0x08 | /* this is not defined, but should be ignored */
1564 DCERPC_PFC_FLAG_CONC_MPX |
1565 DCERPC_PFC_FLAG_DID_NOT_EXECUTE |
1566 DCERPC_PFC_FLAG_MAYBE |
1567 DCERPC_PFC_FLAG_OBJECT_UUID);
1568 if (!NT_STATUS_IS_OK(status)) {
1569 return dcesrv_fault_disconnect(call, DCERPC_NCA_S_PROTO_ERROR);
1572 auth_ok = dcesrv_auth_alter(call);
1573 if (!auth_ok) {
1574 if (call->fault_code != 0) {
1575 return dcesrv_fault_disconnect(call, call->fault_code);
1579 if (call->pkt.u.alter.num_contexts < 1) {
1580 return dcesrv_fault_disconnect(call, DCERPC_NCA_S_PROTO_ERROR);
1583 ack_ctx_list = talloc_zero_array(call, struct dcerpc_ack_ctx,
1584 call->pkt.u.alter.num_contexts);
1585 if (ack_ctx_list == NULL) {
1586 return NT_STATUS_NO_MEMORY;
1590 * Set some sane defaults (required by dcesrv_negotiate_contexts()/
1591 * dcesrv_check_or_create_context()) and do some protocol validation
1592 * and set sane defaults.
1594 for (i = 0; i < call->pkt.u.alter.num_contexts; i++) {
1595 const struct dcerpc_ctx_list *c = &call->pkt.u.alter.ctx_list[i];
1596 struct dcerpc_ack_ctx *a = &ack_ctx_list[i];
1598 if (c->num_transfer_syntaxes == 0) {
1599 return dcesrv_fault_disconnect(call,
1600 DCERPC_NCA_S_PROTO_ERROR);
1603 a->result = DCERPC_BIND_ACK_RESULT_PROVIDER_REJECTION;
1604 a->reason.value = DCERPC_BIND_ACK_REASON_ABSTRACT_SYNTAX_NOT_SUPPORTED;
1608 * Try to negotiate one new presentation context.
1610 status = dcesrv_negotiate_contexts(call, &call->pkt.u.alter, ack_ctx_list);
1611 if (NT_STATUS_EQUAL(status, NT_STATUS_RPC_PROTOCOL_ERROR)) {
1612 return dcesrv_fault_disconnect(call, DCERPC_NCA_S_PROTO_ERROR);
1614 if (!NT_STATUS_IS_OK(status)) {
1615 return status;
1618 if ((call->pkt.pfc_flags & DCERPC_PFC_FLAG_CONC_MPX) &&
1619 (call->state_flags & DCESRV_CALL_STATE_FLAG_MULTIPLEXED)) {
1620 call->conn->state_flags |= DCESRV_CALL_STATE_FLAG_MULTIPLEXED;
1621 extra_flags |= DCERPC_PFC_FLAG_CONC_MPX;
1624 if (call->state_flags & DCESRV_CALL_STATE_FLAG_PROCESS_PENDING_CALL) {
1625 call->conn->state_flags |= DCESRV_CALL_STATE_FLAG_PROCESS_PENDING_CALL;
1628 /* handle any authentication that is being requested */
1629 if (!auth_ok) {
1630 if (call->in_auth_info.auth_type != auth->auth_type) {
1631 return dcesrv_fault_disconnect(call,
1632 DCERPC_FAULT_SEC_PKG_ERROR);
1634 return dcesrv_fault_disconnect(call, DCERPC_FAULT_ACCESS_DENIED);
1637 dcesrv_init_hdr(pkt, lpcfg_rpc_big_endian(call->conn->dce_ctx->lp_ctx));
1638 pkt->auth_length = 0;
1639 pkt->call_id = call->pkt.call_id;
1640 pkt->ptype = DCERPC_PKT_ALTER_RESP;
1641 pkt->pfc_flags = DCERPC_PFC_FLAG_FIRST | DCERPC_PFC_FLAG_LAST | extra_flags;
1642 pkt->u.alter_resp.max_xmit_frag = call->conn->max_xmit_frag;
1643 pkt->u.alter_resp.max_recv_frag = call->conn->max_recv_frag;
1644 pkt->u.alter_resp.assoc_group_id = call->conn->assoc_group->id;
1645 pkt->u.alter_resp.secondary_address = "";
1646 pkt->u.alter_resp.num_results = call->pkt.u.alter.num_contexts;
1647 pkt->u.alter_resp.ctx_list = ack_ctx_list;
1648 pkt->u.alter_resp.auth_info = data_blob_null;
1650 status = dcesrv_auth_prepare_alter_ack(call, pkt);
1651 if (!NT_STATUS_IS_OK(status)) {
1652 return dcesrv_fault_disconnect(call, DCERPC_FAULT_SEC_PKG_ERROR);
1655 if (auth->auth_finished) {
1656 return dcesrv_auth_reply(call);
1659 subreq = gensec_update_send(call, call->event_ctx,
1660 auth->gensec_security,
1661 call->in_auth_info.credentials);
1662 if (subreq == NULL) {
1663 return NT_STATUS_NO_MEMORY;
1665 tevent_req_set_callback(subreq, dcesrv_alter_done, call);
1667 return dcesrv_conn_auth_wait_setup(conn);
1670 static void dcesrv_alter_done(struct tevent_req *subreq)
1672 struct dcesrv_call_state *call =
1673 tevent_req_callback_data(subreq,
1674 struct dcesrv_call_state);
1675 struct dcesrv_connection *conn = call->conn;
1676 NTSTATUS status;
1678 status = gensec_update_recv(subreq, call,
1679 &call->out_auth_info->credentials);
1680 TALLOC_FREE(subreq);
1682 status = dcesrv_auth_complete(call, status);
1683 if (!NT_STATUS_IS_OK(status)) {
1684 status = dcesrv_fault_disconnect(call, DCERPC_FAULT_SEC_PKG_ERROR);
1685 dcesrv_conn_auth_wait_finished(conn, status);
1686 return;
1689 status = dcesrv_auth_reply(call);
1690 dcesrv_conn_auth_wait_finished(conn, status);
1691 return;
1695 possibly save the call for inspection with ndrdump
1697 static void dcesrv_save_call(struct dcesrv_call_state *call, const char *why)
1699 #ifdef DEVELOPER
1700 dcerpc_log_packet(call->conn->packet_log_dir,
1701 call->context->iface->name,
1702 call->pkt.u.request.opnum,
1703 NDR_IN,
1704 &call->pkt.u.request.stub_and_verifier,
1705 why);
1706 #endif
1709 #ifdef DEVELOPER
1711 Save the call for use as a seed for fuzzing.
1713 This is only enabled in a developer build, and only has effect if the
1714 "dcesrv fuzz directory" param is set.
1716 void _dcesrv_save_ndr_fuzz_seed(DATA_BLOB call_blob,
1717 struct dcesrv_call_state *call,
1718 int flags)
1720 const char *dump_dir = lpcfg_parm_string(call->conn->dce_ctx->lp_ctx,
1721 NULL,
1722 "dcesrv", "fuzz directory");
1724 dcerpc_save_ndr_fuzz_seed(call,
1725 call_blob,
1726 dump_dir,
1727 call->context->iface->name,
1728 flags,
1729 call->pkt.u.request.opnum,
1730 call->ndr_pull->flags & LIBNDR_FLAG_NDR64);
1732 #endif /*if DEVELOPER, enveloping _dcesrv_save_ndr_fuzz_seed() */
1735 static NTSTATUS dcesrv_check_verification_trailer(struct dcesrv_call_state *call)
1737 TALLOC_CTX *frame = talloc_stackframe();
1738 const uint32_t bitmask1 = call->conn->client_hdr_signing ?
1739 DCERPC_SEC_VT_CLIENT_SUPPORTS_HEADER_SIGNING : 0;
1740 const struct dcerpc_sec_vt_pcontext pcontext = {
1741 .abstract_syntax = call->context->iface->syntax_id,
1742 .transfer_syntax = call->context->transfer_syntax,
1744 const struct dcerpc_sec_vt_header2 header2 =
1745 dcerpc_sec_vt_header2_from_ncacn_packet(&call->pkt);
1746 enum ndr_err_code ndr_err;
1747 struct dcerpc_sec_verification_trailer *vt = NULL;
1748 NTSTATUS status = NT_STATUS_OK;
1749 bool ok;
1751 SMB_ASSERT(call->pkt.ptype == DCERPC_PKT_REQUEST);
1753 ndr_err = ndr_pop_dcerpc_sec_verification_trailer(call->ndr_pull,
1754 frame, &vt);
1755 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
1756 status = ndr_map_error2ntstatus(ndr_err);
1757 goto done;
1760 ok = dcerpc_sec_verification_trailer_check(vt, &bitmask1,
1761 &pcontext, &header2);
1762 if (!ok) {
1763 status = NT_STATUS_ACCESS_DENIED;
1764 goto done;
1766 done:
1767 TALLOC_FREE(frame);
1768 return status;
1772 handle a dcerpc request packet
1774 static NTSTATUS dcesrv_request(struct dcesrv_call_state *call)
1776 const struct dcesrv_endpoint *endpoint = call->conn->endpoint;
1777 struct dcesrv_auth *auth = call->auth_state;
1778 enum dcerpc_transport_t transport =
1779 dcerpc_binding_get_transport(endpoint->ep_description);
1780 struct ndr_pull *pull;
1781 NTSTATUS status;
1783 if (!auth->auth_finished) {
1784 return dcesrv_fault_disconnect(call, DCERPC_NCA_S_PROTO_ERROR);
1787 /* if authenticated, and the mech we use can't do async replies, don't use them... */
1788 if (auth->gensec_security != NULL &&
1789 !gensec_have_feature(auth->gensec_security, GENSEC_FEATURE_ASYNC_REPLIES)) {
1790 call->state_flags &= ~DCESRV_CALL_STATE_FLAG_MAY_ASYNC;
1793 if (call->context == NULL) {
1794 return dcesrv_fault_with_flags(call, DCERPC_NCA_S_UNKNOWN_IF,
1795 DCERPC_PFC_FLAG_DID_NOT_EXECUTE);
1798 switch (auth->auth_level) {
1799 case DCERPC_AUTH_LEVEL_NONE:
1800 case DCERPC_AUTH_LEVEL_PACKET:
1801 case DCERPC_AUTH_LEVEL_INTEGRITY:
1802 case DCERPC_AUTH_LEVEL_PRIVACY:
1803 break;
1804 default:
1805 if (!call->context->allow_connect) {
1806 char *addr;
1808 addr = tsocket_address_string(call->conn->remote_address,
1809 call);
1811 DEBUG(2, ("%s: restrict auth_level_connect access "
1812 "to [%s] with auth[type=0x%x,level=0x%x] "
1813 "on [%s] from [%s]\n",
1814 __func__, call->context->iface->name,
1815 auth->auth_type,
1816 auth->auth_level,
1817 derpc_transport_string_by_transport(transport),
1818 addr));
1819 return dcesrv_fault(call, DCERPC_FAULT_ACCESS_DENIED);
1821 break;
1824 if (auth->auth_level < call->context->min_auth_level) {
1825 char *addr;
1827 addr = tsocket_address_string(call->conn->remote_address, call);
1829 DEBUG(2, ("%s: restrict access by min_auth_level[0x%x] "
1830 "to [%s] with auth[type=0x%x,level=0x%x] "
1831 "on [%s] from [%s]\n",
1832 __func__,
1833 call->context->min_auth_level,
1834 call->context->iface->name,
1835 auth->auth_type,
1836 auth->auth_level,
1837 derpc_transport_string_by_transport(transport),
1838 addr));
1839 return dcesrv_fault(call, DCERPC_FAULT_ACCESS_DENIED);
1842 pull = ndr_pull_init_blob(&call->pkt.u.request.stub_and_verifier, call);
1843 NT_STATUS_HAVE_NO_MEMORY(pull);
1845 pull->flags |= LIBNDR_FLAG_REF_ALLOC;
1847 call->ndr_pull = pull;
1849 if (!(call->pkt.drep[0] & DCERPC_DREP_LE)) {
1850 pull->flags |= LIBNDR_FLAG_BIGENDIAN;
1853 status = dcesrv_check_verification_trailer(call);
1854 if (!NT_STATUS_IS_OK(status)) {
1855 uint32_t faultcode = DCERPC_FAULT_OTHER;
1856 if (NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
1857 faultcode = DCERPC_FAULT_ACCESS_DENIED;
1859 DEBUG(10, ("dcesrv_check_verification_trailer failed: %s\n",
1860 nt_errstr(status)));
1861 return dcesrv_fault(call, faultcode);
1864 /* unravel the NDR for the packet */
1865 status = call->context->iface->ndr_pull(call, call, pull, &call->r);
1866 if (!NT_STATUS_IS_OK(status)) {
1867 uint8_t extra_flags = 0;
1868 if (call->fault_code == DCERPC_FAULT_OP_RNG_ERROR) {
1869 /* we got an unknown call */
1870 DEBUG(3,(__location__ ": Unknown RPC call %u on %s\n",
1871 call->pkt.u.request.opnum,
1872 call->context->iface->name));
1873 dcesrv_save_call(call, "unknown");
1874 extra_flags |= DCERPC_PFC_FLAG_DID_NOT_EXECUTE;
1875 } else {
1876 dcesrv_save_call(call, "pullfail");
1879 return dcesrv_fault_with_flags(call, call->fault_code, extra_flags);
1882 dcesrv_save_ndr_fuzz_seed(call->pkt.u.request.stub_and_verifier,
1883 call,
1884 NDR_IN);
1886 if (pull->offset != pull->data_size) {
1887 dcesrv_save_call(call, "extrabytes");
1888 DEBUG(3,("Warning: %d extra bytes in incoming RPC request\n",
1889 pull->data_size - pull->offset));
1892 /* call the dispatch function */
1893 status = call->context->iface->dispatch(call, call, call->r);
1894 if (!NT_STATUS_IS_OK(status)) {
1895 DEBUG(5,("dcerpc fault in call %s:%02x - %s\n",
1896 call->context->iface->name,
1897 call->pkt.u.request.opnum,
1898 dcerpc_errstr(pull, call->fault_code)));
1899 return dcesrv_fault(call, call->fault_code);
1902 /* add the call to the pending list */
1903 dcesrv_call_set_list(call, DCESRV_LIST_PENDING_CALL_LIST);
1905 if (call->state_flags & DCESRV_CALL_STATE_FLAG_ASYNC) {
1906 return NT_STATUS_OK;
1909 return dcesrv_reply(call);
1914 remove the call from the right list when freed
1916 static int dcesrv_call_dequeue(struct dcesrv_call_state *call)
1918 dcesrv_call_set_list(call, DCESRV_LIST_NONE);
1919 return 0;
1922 _PUBLIC_ const struct tsocket_address *dcesrv_connection_get_local_address(struct dcesrv_connection *conn)
1924 return conn->local_address;
1927 _PUBLIC_ const struct tsocket_address *dcesrv_connection_get_remote_address(struct dcesrv_connection *conn)
1929 return conn->remote_address;
1933 process some input to a dcerpc endpoint server.
1935 static NTSTATUS dcesrv_process_ncacn_packet(struct dcesrv_connection *dce_conn,
1936 struct ncacn_packet *pkt,
1937 DATA_BLOB blob)
1939 NTSTATUS status;
1940 struct dcesrv_call_state *call;
1941 struct dcesrv_call_state *existing = NULL;
1942 size_t num_auth_ctx = 0;
1943 enum dcerpc_AuthType auth_type = 0;
1944 enum dcerpc_AuthLevel auth_level = 0;
1945 uint32_t auth_context_id = 0;
1947 call = talloc_zero(dce_conn, struct dcesrv_call_state);
1948 if (!call) {
1949 data_blob_free(&blob);
1950 talloc_free(pkt);
1951 return NT_STATUS_NO_MEMORY;
1953 call->conn = dce_conn;
1954 call->event_ctx = dce_conn->event_ctx;
1955 call->state_flags = call->conn->state_flags;
1956 call->time = timeval_current();
1957 call->list = DCESRV_LIST_NONE;
1959 talloc_steal(call, pkt);
1960 talloc_steal(call, blob.data);
1961 call->pkt = *pkt;
1963 if (dce_conn->max_auth_states == 0) {
1964 call->auth_state = dce_conn->default_auth_state;
1965 } else if (call->pkt.auth_length == 0) {
1966 if (call->pkt.ptype == DCERPC_PKT_REQUEST &&
1967 dce_conn->default_auth_level_connect != NULL)
1969 call->auth_state = dce_conn->default_auth_level_connect;
1970 } else {
1971 call->auth_state = dce_conn->default_auth_state;
1975 if (call->auth_state == NULL) {
1976 struct dcesrv_auth *a = NULL;
1978 auth_type = dcerpc_get_auth_type(&blob);
1979 auth_level = dcerpc_get_auth_level(&blob);
1980 auth_context_id = dcerpc_get_auth_context_id(&blob);
1982 if (call->pkt.ptype == DCERPC_PKT_REQUEST) {
1983 dce_conn->default_auth_level_connect = NULL;
1984 if (auth_level == DCERPC_AUTH_LEVEL_CONNECT) {
1985 dce_conn->got_explicit_auth_level_connect = true;
1989 for (a = dce_conn->auth_states; a != NULL; a = a->next) {
1990 num_auth_ctx++;
1992 if (a->auth_type != auth_type) {
1993 continue;
1995 if (a->auth_finished && a->auth_level != auth_level) {
1996 continue;
1998 if (a->auth_context_id != auth_context_id) {
1999 continue;
2002 DLIST_PROMOTE(dce_conn->auth_states, a);
2003 call->auth_state = a;
2004 break;
2008 if (call->auth_state == NULL) {
2009 struct dcesrv_auth *a = NULL;
2011 if (num_auth_ctx >= dce_conn->max_auth_states) {
2012 return dcesrv_fault_disconnect(call,
2013 DCERPC_NCA_S_PROTO_ERROR);
2016 a = dcesrv_auth_create(dce_conn);
2017 if (a == NULL) {
2018 talloc_free(call);
2019 return NT_STATUS_NO_MEMORY;
2021 DLIST_ADD(dce_conn->auth_states, a);
2022 if (call->pkt.ptype == DCERPC_PKT_REQUEST) {
2024 * This can never be valid.
2026 a->auth_invalid = true;
2028 call->auth_state = a;
2031 talloc_set_destructor(call, dcesrv_call_dequeue);
2033 if (call->conn->allow_bind) {
2035 * Only one bind is possible per connection
2037 call->conn->allow_bind = false;
2038 return dcesrv_bind(call);
2041 /* we have to check the signing here, before combining the
2042 pdus */
2043 if (call->pkt.ptype == DCERPC_PKT_REQUEST) {
2044 dcesrv_default_auth_state_prepare_request(call);
2046 if (call->auth_state->auth_started &&
2047 !call->auth_state->auth_finished) {
2048 return dcesrv_fault_disconnect(call,
2049 DCERPC_NCA_S_PROTO_ERROR);
2052 status = dcerpc_verify_ncacn_packet_header(&call->pkt,
2053 DCERPC_PKT_REQUEST,
2054 call->pkt.u.request.stub_and_verifier.length,
2055 0, /* required_flags */
2056 DCERPC_PFC_FLAG_FIRST |
2057 DCERPC_PFC_FLAG_LAST |
2058 DCERPC_PFC_FLAG_PENDING_CANCEL |
2059 0x08 | /* this is not defined, but should be ignored */
2060 DCERPC_PFC_FLAG_CONC_MPX |
2061 DCERPC_PFC_FLAG_DID_NOT_EXECUTE |
2062 DCERPC_PFC_FLAG_MAYBE |
2063 DCERPC_PFC_FLAG_OBJECT_UUID);
2064 if (!NT_STATUS_IS_OK(status)) {
2065 return dcesrv_fault_disconnect(call,
2066 DCERPC_NCA_S_PROTO_ERROR);
2069 if (call->pkt.frag_length > DCERPC_FRAG_MAX_SIZE) {
2071 * We don't use dcesrv_fault_disconnect()
2072 * here, because we don't want to set
2073 * DCERPC_PFC_FLAG_DID_NOT_EXECUTE
2075 * Note that we don't check against the negotiated
2076 * max_recv_frag, but a hard coded value.
2078 dcesrv_call_disconnect_after(call,
2079 "dcesrv_auth_request - frag_length too large");
2080 return dcesrv_fault(call,
2081 DCERPC_NCA_S_PROTO_ERROR);
2084 if (call->pkt.pfc_flags & DCERPC_PFC_FLAG_FIRST) {
2085 if (dce_conn->pending_call_list != NULL) {
2087 * concurrent requests are only allowed
2088 * if DCERPC_PFC_FLAG_CONC_MPX was negotiated.
2090 if (!(dce_conn->state_flags & DCESRV_CALL_STATE_FLAG_MULTIPLEXED)) {
2091 dcesrv_call_disconnect_after(call,
2092 "dcesrv_auth_request - "
2093 "existing pending call without CONN_MPX");
2094 return dcesrv_fault(call,
2095 DCERPC_NCA_S_PROTO_ERROR);
2098 /* only one request is possible in the fragmented list */
2099 if (dce_conn->incoming_fragmented_call_list != NULL) {
2100 if (!(dce_conn->state_flags & DCESRV_CALL_STATE_FLAG_MULTIPLEXED)) {
2102 * Without DCERPC_PFC_FLAG_CONC_MPX
2103 * we need to return the FAULT on the
2104 * already existing call.
2106 * This is important to get the
2107 * call_id and context_id right.
2109 TALLOC_FREE(call);
2110 call = dce_conn->incoming_fragmented_call_list;
2112 dcesrv_call_disconnect_after(call,
2113 "dcesrv_auth_request - "
2114 "existing fragmented call");
2115 return dcesrv_fault(call,
2116 DCERPC_NCA_S_PROTO_ERROR);
2118 if (call->pkt.pfc_flags & DCERPC_PFC_FLAG_PENDING_CANCEL) {
2119 return dcesrv_fault_disconnect(call,
2120 DCERPC_FAULT_NO_CALL_ACTIVE);
2122 call->context = dcesrv_find_context(call->conn,
2123 call->pkt.u.request.context_id);
2124 if (call->context == NULL) {
2125 return dcesrv_fault_with_flags(call, DCERPC_NCA_S_UNKNOWN_IF,
2126 DCERPC_PFC_FLAG_DID_NOT_EXECUTE);
2128 } else {
2129 const struct dcerpc_request *nr = &call->pkt.u.request;
2130 const struct dcerpc_request *er = NULL;
2131 int cmp;
2133 existing = dcesrv_find_fragmented_call(dce_conn,
2134 call->pkt.call_id);
2135 if (existing == NULL) {
2136 dcesrv_call_disconnect_after(call,
2137 "dcesrv_auth_request - "
2138 "no existing fragmented call");
2139 return dcesrv_fault(call,
2140 DCERPC_NCA_S_PROTO_ERROR);
2142 er = &existing->pkt.u.request;
2144 if (call->pkt.ptype != existing->pkt.ptype) {
2145 /* trying to play silly buggers are we? */
2146 return dcesrv_fault_disconnect(existing,
2147 DCERPC_NCA_S_PROTO_ERROR);
2149 cmp = memcmp(call->pkt.drep, existing->pkt.drep,
2150 sizeof(pkt->drep));
2151 if (cmp != 0) {
2152 return dcesrv_fault_disconnect(existing,
2153 DCERPC_NCA_S_PROTO_ERROR);
2155 if (nr->context_id != er->context_id) {
2156 return dcesrv_fault_disconnect(existing,
2157 DCERPC_NCA_S_PROTO_ERROR);
2159 if (nr->opnum != er->opnum) {
2160 return dcesrv_fault_disconnect(existing,
2161 DCERPC_NCA_S_PROTO_ERROR);
2166 if (call->pkt.ptype == DCERPC_PKT_REQUEST) {
2167 bool ok;
2168 uint8_t payload_offset = DCERPC_REQUEST_LENGTH;
2170 if (call->pkt.pfc_flags & DCERPC_PFC_FLAG_OBJECT_UUID) {
2171 payload_offset += 16;
2174 ok = dcesrv_auth_pkt_pull(call, &blob,
2175 0, /* required_flags */
2176 DCERPC_PFC_FLAG_FIRST |
2177 DCERPC_PFC_FLAG_LAST |
2178 DCERPC_PFC_FLAG_PENDING_CANCEL |
2179 0x08 | /* this is not defined, but should be ignored */
2180 DCERPC_PFC_FLAG_CONC_MPX |
2181 DCERPC_PFC_FLAG_DID_NOT_EXECUTE |
2182 DCERPC_PFC_FLAG_MAYBE |
2183 DCERPC_PFC_FLAG_OBJECT_UUID,
2184 payload_offset,
2185 &call->pkt.u.request.stub_and_verifier);
2186 if (!ok) {
2188 * We don't use dcesrv_fault_disconnect()
2189 * here, because we don't want to set
2190 * DCERPC_PFC_FLAG_DID_NOT_EXECUTE
2192 dcesrv_call_disconnect_after(call,
2193 "dcesrv_auth_request - failed");
2194 if (call->fault_code == 0) {
2195 call->fault_code = DCERPC_FAULT_ACCESS_DENIED;
2197 return dcesrv_fault(call, call->fault_code);
2201 /* see if this is a continued packet */
2202 if (existing != NULL) {
2203 struct dcerpc_request *er = &existing->pkt.u.request;
2204 const struct dcerpc_request *nr = &call->pkt.u.request;
2205 size_t available;
2206 size_t alloc_size;
2207 size_t alloc_hint;
2210 * Up to 4 MByte are allowed by all fragments
2212 available = dce_conn->max_total_request_size;
2213 if (er->stub_and_verifier.length > available) {
2214 dcesrv_call_disconnect_after(existing,
2215 "dcesrv_auth_request - existing payload too large");
2216 return dcesrv_fault(existing, DCERPC_FAULT_ACCESS_DENIED);
2218 available -= er->stub_and_verifier.length;
2219 if (nr->alloc_hint > available) {
2220 dcesrv_call_disconnect_after(existing,
2221 "dcesrv_auth_request - alloc hint too large");
2222 return dcesrv_fault(existing, DCERPC_FAULT_ACCESS_DENIED);
2224 if (nr->stub_and_verifier.length > available) {
2225 dcesrv_call_disconnect_after(existing,
2226 "dcesrv_auth_request - new payload too large");
2227 return dcesrv_fault(existing, DCERPC_FAULT_ACCESS_DENIED);
2229 alloc_hint = er->stub_and_verifier.length + nr->alloc_hint;
2230 /* allocate at least 1 byte */
2231 alloc_hint = MAX(alloc_hint, 1);
2232 alloc_size = er->stub_and_verifier.length +
2233 nr->stub_and_verifier.length;
2234 alloc_size = MAX(alloc_size, alloc_hint);
2236 er->stub_and_verifier.data =
2237 talloc_realloc(existing,
2238 er->stub_and_verifier.data,
2239 uint8_t, alloc_size);
2240 if (er->stub_and_verifier.data == NULL) {
2241 TALLOC_FREE(call);
2242 return dcesrv_fault_with_flags(existing,
2243 DCERPC_FAULT_OUT_OF_RESOURCES,
2244 DCERPC_PFC_FLAG_DID_NOT_EXECUTE);
2246 memcpy(er->stub_and_verifier.data +
2247 er->stub_and_verifier.length,
2248 nr->stub_and_verifier.data,
2249 nr->stub_and_verifier.length);
2250 er->stub_and_verifier.length += nr->stub_and_verifier.length;
2252 existing->pkt.pfc_flags |= (call->pkt.pfc_flags & DCERPC_PFC_FLAG_LAST);
2254 TALLOC_FREE(call);
2255 call = existing;
2258 /* this may not be the last pdu in the chain - if its isn't then
2259 just put it on the incoming_fragmented_call_list and wait for the rest */
2260 if (call->pkt.ptype == DCERPC_PKT_REQUEST &&
2261 !(call->pkt.pfc_flags & DCERPC_PFC_FLAG_LAST)) {
2263 * Up to 4 MByte are allowed by all fragments
2265 if (call->pkt.u.request.alloc_hint > dce_conn->max_total_request_size) {
2266 dcesrv_call_disconnect_after(call,
2267 "dcesrv_auth_request - initial alloc hint too large");
2268 return dcesrv_fault(call, DCERPC_FAULT_ACCESS_DENIED);
2270 dcesrv_call_set_list(call, DCESRV_LIST_FRAGMENTED_CALL_LIST);
2271 return NT_STATUS_OK;
2274 /* This removes any fragments we may have had stashed away */
2275 dcesrv_call_set_list(call, DCESRV_LIST_NONE);
2277 switch (call->pkt.ptype) {
2278 case DCERPC_PKT_BIND:
2279 status = dcesrv_bind_nak(call,
2280 DCERPC_BIND_NAK_REASON_NOT_SPECIFIED);
2281 break;
2282 case DCERPC_PKT_AUTH3:
2283 status = dcesrv_auth3(call);
2284 break;
2285 case DCERPC_PKT_ALTER:
2286 status = dcesrv_alter(call);
2287 break;
2288 case DCERPC_PKT_REQUEST:
2289 status = dcesrv_request(call);
2290 break;
2291 case DCERPC_PKT_CO_CANCEL:
2292 case DCERPC_PKT_ORPHANED:
2294 * Window just ignores CO_CANCEL and ORPHANED,
2295 * so we do...
2297 status = NT_STATUS_OK;
2298 TALLOC_FREE(call);
2299 break;
2300 case DCERPC_PKT_BIND_ACK:
2301 case DCERPC_PKT_BIND_NAK:
2302 case DCERPC_PKT_ALTER_RESP:
2303 case DCERPC_PKT_RESPONSE:
2304 case DCERPC_PKT_FAULT:
2305 case DCERPC_PKT_SHUTDOWN:
2306 default:
2307 status = dcesrv_fault_disconnect(call, DCERPC_NCA_S_PROTO_ERROR);
2308 break;
2311 /* if we are going to be sending a reply then add
2312 it to the list of pending calls. We add it to the end to keep the call
2313 list in the order we will answer */
2314 if (!NT_STATUS_IS_OK(status)) {
2315 talloc_free(call);
2318 return status;
2321 _PUBLIC_ NTSTATUS dcesrv_init_context(TALLOC_CTX *mem_ctx,
2322 struct loadparm_context *lp_ctx,
2323 struct dcesrv_context_callbacks *cb,
2324 struct dcesrv_context **_dce_ctx)
2326 struct dcesrv_context *dce_ctx;
2328 dce_ctx = talloc_zero(mem_ctx, struct dcesrv_context);
2329 NT_STATUS_HAVE_NO_MEMORY(dce_ctx);
2331 if (uid_wrapper_enabled()) {
2332 setenv("UID_WRAPPER_MYUID", "1", 1);
2334 dce_ctx->initial_euid = geteuid();
2335 if (uid_wrapper_enabled()) {
2336 unsetenv("UID_WRAPPER_MYUID");
2339 dce_ctx->endpoint_list = NULL;
2340 dce_ctx->lp_ctx = lp_ctx;
2341 dce_ctx->assoc_groups_idr = idr_init(dce_ctx);
2342 NT_STATUS_HAVE_NO_MEMORY(dce_ctx->assoc_groups_idr);
2343 dce_ctx->broken_connections = NULL;
2344 if (cb != NULL) {
2345 dce_ctx->callbacks = *cb;
2348 *_dce_ctx = dce_ctx;
2349 return NT_STATUS_OK;
2352 _PUBLIC_ NTSTATUS dcesrv_reinit_context(struct dcesrv_context *dce_ctx)
2354 NTSTATUS status;
2356 status = dcesrv_shutdown_registered_ep_servers(dce_ctx);
2357 if (!NT_STATUS_IS_OK(status)) {
2358 return status;
2361 /* Clear endpoints */
2362 while (dce_ctx->endpoint_list != NULL) {
2363 struct dcesrv_endpoint *e = dce_ctx->endpoint_list;
2364 DLIST_REMOVE(dce_ctx->endpoint_list, e);
2365 TALLOC_FREE(e);
2368 /* Remove broken connections */
2369 dcesrv_cleanup_broken_connections(dce_ctx);
2371 /* Reinit assoc group idr */
2372 TALLOC_FREE(dce_ctx->assoc_groups_idr);
2373 dce_ctx->assoc_groups_idr = idr_init(dce_ctx);
2374 if (dce_ctx->assoc_groups_idr == NULL) {
2375 return NT_STATUS_NO_MEMORY;
2378 return NT_STATUS_OK;
2381 _PUBLIC_ NTSTATUS dcesrv_init_ep_servers(struct dcesrv_context *dce_ctx,
2382 const char **endpoint_servers)
2384 NTSTATUS status;
2385 int i;
2387 if (endpoint_servers == NULL) {
2388 DBG_ERR("No endpoint servers configured\n");
2389 return NT_STATUS_INTERNAL_ERROR;
2392 for (i=0;endpoint_servers[i];i++) {
2393 status = dcesrv_init_ep_server(dce_ctx, endpoint_servers[i]);
2394 if (!NT_STATUS_IS_OK(status)) {
2395 DBG_ERR("failed to init endpoint server = '%s': %s\n",
2396 endpoint_servers[i], nt_errstr(status));
2397 return status;
2401 return NT_STATUS_OK;
2404 /* the list of currently registered DCERPC endpoint servers.
2406 static struct ep_server {
2407 struct dcesrv_endpoint_server *ep_server;
2408 } *ep_servers = NULL;
2409 static int num_ep_servers = 0;
2411 _PUBLIC_ NTSTATUS dcesrv_init_registered_ep_servers(
2412 struct dcesrv_context *dce_ctx)
2414 NTSTATUS status;
2415 int i;
2417 for (i = 0; i < num_ep_servers; i++) {
2418 status = dcesrv_init_ep_server(dce_ctx,
2419 ep_servers[i].ep_server->name);
2420 if (!NT_STATUS_IS_OK(status)) {
2421 return status;
2425 return NT_STATUS_OK;
2428 _PUBLIC_ NTSTATUS dcesrv_init_ep_server(struct dcesrv_context *dce_ctx,
2429 const char *ep_server_name)
2431 struct dcesrv_endpoint_server *ep_server = NULL;
2432 NTSTATUS status;
2434 ep_server = discard_const_p(struct dcesrv_endpoint_server,
2435 dcesrv_ep_server_byname(ep_server_name));
2436 if (ep_server == NULL) {
2437 DBG_ERR("Failed to find endpoint server '%s'\n",
2438 ep_server_name);
2439 return NT_STATUS_INTERNAL_ERROR;
2442 if (ep_server->initialized) {
2443 return NT_STATUS_OK;
2446 status = ep_server->init_server(dce_ctx, ep_server);
2447 if (!NT_STATUS_IS_OK(status)) {
2448 DBG_ERR("Failed to init endpoint server '%s': %s\n",
2449 ep_server_name, nt_errstr(status));
2450 return status;
2453 ep_server->initialized = true;
2455 return NT_STATUS_OK;
2458 _PUBLIC_ NTSTATUS dcesrv_shutdown_registered_ep_servers(
2459 struct dcesrv_context *dce_ctx)
2461 NTSTATUS status;
2462 int i;
2464 for (i = 0; i < num_ep_servers; i++) {
2465 status = dcesrv_shutdown_ep_server(dce_ctx,
2466 ep_servers[i].ep_server->name);
2467 if (!NT_STATUS_IS_OK(status)) {
2468 return status;
2472 return NT_STATUS_OK;
2475 _PUBLIC_ NTSTATUS dcesrv_shutdown_ep_server(struct dcesrv_context *dce_ctx,
2476 const char *ep_server_name)
2478 struct dcesrv_endpoint_server *ep_server = NULL;
2479 NTSTATUS status;
2481 ep_server = discard_const_p(struct dcesrv_endpoint_server,
2482 dcesrv_ep_server_byname(ep_server_name));
2483 if (ep_server == NULL) {
2484 DBG_ERR("Failed to find endpoint server '%s'\n",
2485 ep_server_name);
2486 return NT_STATUS_INTERNAL_ERROR;
2489 if (!ep_server->initialized) {
2490 return NT_STATUS_OK;
2493 DBG_INFO("Shutting down DCE/RPC endpoint server '%s'\n",
2494 ep_server_name);
2496 status = ep_server->shutdown_server(dce_ctx, ep_server);
2497 if (!NT_STATUS_IS_OK(status)) {
2498 DBG_ERR("Failed to shutdown endpoint server '%s': %s\n",
2499 ep_server_name, nt_errstr(status));
2500 return status;
2503 ep_server->initialized = false;
2505 return NT_STATUS_OK;
2509 register a DCERPC endpoint server.
2511 The 'name' can be later used by other backends to find the operations
2512 structure for this backend.
2515 _PUBLIC_ NTSTATUS dcerpc_register_ep_server(const struct dcesrv_endpoint_server *ep_server)
2518 if (dcesrv_ep_server_byname(ep_server->name) != NULL) {
2519 /* its already registered! */
2520 DEBUG(0,("DCERPC endpoint server '%s' already registered\n",
2521 ep_server->name));
2522 return NT_STATUS_OBJECT_NAME_COLLISION;
2525 ep_servers = realloc_p(ep_servers, struct ep_server, num_ep_servers+1);
2526 if (!ep_servers) {
2527 smb_panic("out of memory in dcerpc_register");
2530 ep_servers[num_ep_servers].ep_server = smb_xmemdup(ep_server, sizeof(*ep_server));
2531 ep_servers[num_ep_servers].ep_server->name = smb_xstrdup(ep_server->name);
2533 num_ep_servers++;
2535 DEBUG(3,("DCERPC endpoint server '%s' registered\n",
2536 ep_server->name));
2538 return NT_STATUS_OK;
2542 return the operations structure for a named backend of the specified type
2544 _PUBLIC_ const struct dcesrv_endpoint_server *dcesrv_ep_server_byname(const char *name)
2546 int i;
2548 for (i=0;i<num_ep_servers;i++) {
2549 if (strcmp(ep_servers[i].ep_server->name, name) == 0) {
2550 return ep_servers[i].ep_server;
2554 return NULL;
2558 return the DCERPC module version, and the size of some critical types
2559 This can be used by endpoint server modules to either detect compilation errors, or provide
2560 multiple implementations for different smbd compilation options in one module
2562 const struct dcesrv_critical_sizes *dcerpc_module_version(void)
2564 static const struct dcesrv_critical_sizes critical_sizes = {
2565 DCERPC_MODULE_VERSION,
2566 sizeof(struct dcesrv_context),
2567 sizeof(struct dcesrv_endpoint),
2568 sizeof(struct dcesrv_endpoint_server),
2569 sizeof(struct dcesrv_interface),
2570 sizeof(struct dcesrv_if_list),
2571 sizeof(struct dcesrv_connection),
2572 sizeof(struct dcesrv_call_state),
2573 sizeof(struct dcesrv_auth),
2574 sizeof(struct dcesrv_handle)
2577 return &critical_sizes;
2580 _PUBLIC_ void dcesrv_terminate_connection(struct dcesrv_connection *dce_conn, const char *reason)
2582 struct dcesrv_context *dce_ctx = dce_conn->dce_ctx;
2583 struct dcesrv_auth *a = NULL;
2585 dce_conn->wait_send = NULL;
2586 dce_conn->wait_recv = NULL;
2587 dce_conn->wait_private = NULL;
2589 dce_conn->allow_bind = false;
2590 dce_conn->allow_alter = false;
2592 dce_conn->default_auth_state->auth_invalid = true;
2594 for (a = dce_conn->auth_states; a != NULL; a = a->next) {
2595 a->auth_invalid = true;
2598 if (dce_conn->pending_call_list == NULL) {
2599 char *full_reason = talloc_asprintf(dce_conn, "dcesrv: %s", reason);
2601 DLIST_REMOVE(dce_ctx->broken_connections, dce_conn);
2602 dce_conn->transport.terminate_connection(dce_conn,
2603 full_reason ? full_reason : reason);
2604 return;
2607 if (dce_conn->terminate != NULL) {
2608 return;
2611 DEBUG(3,("dcesrv: terminating connection due to '%s' deferred due to pending calls\n",
2612 reason));
2613 dce_conn->terminate = talloc_strdup(dce_conn, reason);
2614 if (dce_conn->terminate == NULL) {
2615 dce_conn->terminate = "dcesrv: deferred terminating connection - no memory";
2617 DLIST_ADD_END(dce_ctx->broken_connections, dce_conn);
2620 _PUBLIC_ void dcesrv_cleanup_broken_connections(struct dcesrv_context *dce_ctx)
2622 struct dcesrv_connection *cur, *next;
2624 next = dce_ctx->broken_connections;
2625 while (next != NULL) {
2626 cur = next;
2627 next = cur->next;
2629 if (cur->state_flags & DCESRV_CALL_STATE_FLAG_PROCESS_PENDING_CALL) {
2630 struct dcesrv_connection_context *context_cur, *context_next;
2632 context_next = cur->contexts;
2633 while (context_next != NULL) {
2634 context_cur = context_next;
2635 context_next = context_cur->next;
2637 dcesrv_connection_context_destructor(context_cur);
2641 dcesrv_terminate_connection(cur, cur->terminate);
2645 /* We need this include to be able to compile on some plateforms
2646 * (ie. freebsd 7.2) as it seems that <sys/uio.h> is not included
2647 * correctly.
2648 * It has to be that deep because otherwise we have a conflict on
2649 * const struct dcesrv_interface declaration.
2650 * This is mostly due to socket_wrapper defining #define bind swrap_bind
2651 * which conflict with the bind used before.
2653 #include "system/network.h"
2655 struct dcesrv_sock_reply_state {
2656 struct dcesrv_connection *dce_conn;
2657 struct dcesrv_call_state *call;
2658 struct iovec iov;
2661 static void dcesrv_sock_reply_done(struct tevent_req *subreq);
2662 static void dcesrv_call_terminate_step1(struct tevent_req *subreq);
2664 _PUBLIC_ void dcesrv_sock_report_output_data(struct dcesrv_connection *dce_conn)
2666 struct dcesrv_call_state *call;
2668 call = dce_conn->call_list;
2669 if (!call || !call->replies) {
2670 return;
2673 while (call->replies) {
2674 struct data_blob_list_item *rep = call->replies;
2675 struct dcesrv_sock_reply_state *substate;
2676 struct tevent_req *subreq;
2678 substate = talloc_zero(call, struct dcesrv_sock_reply_state);
2679 if (!substate) {
2680 dcesrv_terminate_connection(dce_conn, "no memory");
2681 return;
2684 substate->dce_conn = dce_conn;
2685 substate->call = NULL;
2687 DLIST_REMOVE(call->replies, rep);
2689 if (call->replies == NULL && call->terminate_reason == NULL) {
2690 substate->call = call;
2693 substate->iov.iov_base = (void *) rep->blob.data;
2694 substate->iov.iov_len = rep->blob.length;
2696 subreq = tstream_writev_queue_send(substate,
2697 dce_conn->event_ctx,
2698 dce_conn->stream,
2699 dce_conn->send_queue,
2700 &substate->iov, 1);
2701 if (!subreq) {
2702 dcesrv_terminate_connection(dce_conn, "no memory");
2703 return;
2705 tevent_req_set_callback(subreq, dcesrv_sock_reply_done,
2706 substate);
2709 if (call->terminate_reason != NULL) {
2710 struct tevent_req *subreq;
2712 subreq = tevent_queue_wait_send(call,
2713 dce_conn->event_ctx,
2714 dce_conn->send_queue);
2715 if (!subreq) {
2716 dcesrv_terminate_connection(dce_conn, __location__);
2717 return;
2719 tevent_req_set_callback(subreq, dcesrv_call_terminate_step1,
2720 call);
2723 DLIST_REMOVE(call->conn->call_list, call);
2724 call->list = DCESRV_LIST_NONE;
2727 static void dcesrv_sock_reply_done(struct tevent_req *subreq)
2729 struct dcesrv_sock_reply_state *substate = tevent_req_callback_data(subreq,
2730 struct dcesrv_sock_reply_state);
2731 int ret;
2732 int sys_errno;
2733 NTSTATUS status;
2734 struct dcesrv_call_state *call = substate->call;
2736 ret = tstream_writev_queue_recv(subreq, &sys_errno);
2737 TALLOC_FREE(subreq);
2738 if (ret == -1) {
2739 status = map_nt_error_from_unix_common(sys_errno);
2740 dcesrv_terminate_connection(substate->dce_conn, nt_errstr(status));
2741 return;
2744 talloc_free(substate);
2745 if (call) {
2746 talloc_free(call);
2750 static void dcesrv_call_terminate_step2(struct tevent_req *subreq);
2752 static void dcesrv_call_terminate_step1(struct tevent_req *subreq)
2754 struct dcesrv_call_state *call = tevent_req_callback_data(subreq,
2755 struct dcesrv_call_state);
2756 bool ok;
2757 struct timeval tv;
2759 /* make sure we stop send queue before removing subreq */
2760 tevent_queue_stop(call->conn->send_queue);
2762 ok = tevent_queue_wait_recv(subreq);
2763 TALLOC_FREE(subreq);
2764 if (!ok) {
2765 dcesrv_terminate_connection(call->conn, __location__);
2766 return;
2769 /* disconnect after 200 usecs */
2770 tv = timeval_current_ofs_usec(200);
2771 subreq = tevent_wakeup_send(call, call->conn->event_ctx, tv);
2772 if (subreq == NULL) {
2773 dcesrv_terminate_connection(call->conn, __location__);
2774 return;
2776 tevent_req_set_callback(subreq, dcesrv_call_terminate_step2,
2777 call);
2780 static void dcesrv_call_terminate_step2(struct tevent_req *subreq)
2782 struct dcesrv_call_state *call = tevent_req_callback_data(subreq,
2783 struct dcesrv_call_state);
2784 bool ok;
2786 ok = tevent_wakeup_recv(subreq);
2787 TALLOC_FREE(subreq);
2788 if (!ok) {
2789 dcesrv_terminate_connection(call->conn, __location__);
2790 return;
2793 dcesrv_terminate_connection(call->conn, call->terminate_reason);
2796 static void dcesrv_conn_wait_done(struct tevent_req *subreq);
2798 static void dcesrv_read_fragment_done(struct tevent_req *subreq)
2800 struct dcesrv_connection *dce_conn = tevent_req_callback_data(subreq,
2801 struct dcesrv_connection);
2802 struct dcesrv_context *dce_ctx = dce_conn->dce_ctx;
2803 struct ncacn_packet *pkt;
2804 DATA_BLOB buffer;
2805 NTSTATUS status;
2807 if (dce_conn->terminate) {
2809 * if the current connection is broken
2810 * we need to clean it up before any other connection
2812 dcesrv_terminate_connection(dce_conn, dce_conn->terminate);
2813 dcesrv_cleanup_broken_connections(dce_ctx);
2814 return;
2817 dcesrv_cleanup_broken_connections(dce_ctx);
2819 status = dcerpc_read_ncacn_packet_recv(subreq, dce_conn,
2820 &pkt, &buffer);
2821 TALLOC_FREE(subreq);
2822 if (!NT_STATUS_IS_OK(status)) {
2823 dcesrv_terminate_connection(dce_conn, nt_errstr(status));
2824 return;
2827 status = dcesrv_process_ncacn_packet(dce_conn, pkt, buffer);
2828 if (!NT_STATUS_IS_OK(status)) {
2829 dcesrv_terminate_connection(dce_conn, nt_errstr(status));
2830 return;
2834 * This is used to block the connection during
2835 * pending authentication.
2837 if (dce_conn->wait_send != NULL) {
2838 subreq = dce_conn->wait_send(dce_conn,
2839 dce_conn->event_ctx,
2840 dce_conn->wait_private);
2841 if (!subreq) {
2842 status = NT_STATUS_NO_MEMORY;
2843 dcesrv_terminate_connection(dce_conn, nt_errstr(status));
2844 return;
2846 tevent_req_set_callback(subreq, dcesrv_conn_wait_done, dce_conn);
2847 return;
2850 subreq = dcerpc_read_ncacn_packet_send(dce_conn,
2851 dce_conn->event_ctx,
2852 dce_conn->stream);
2853 if (!subreq) {
2854 status = NT_STATUS_NO_MEMORY;
2855 dcesrv_terminate_connection(dce_conn, nt_errstr(status));
2856 return;
2858 tevent_req_set_callback(subreq, dcesrv_read_fragment_done, dce_conn);
2861 static void dcesrv_conn_wait_done(struct tevent_req *subreq)
2863 struct dcesrv_connection *dce_conn = tevent_req_callback_data(subreq,
2864 struct dcesrv_connection);
2865 struct dcesrv_context *dce_ctx = dce_conn->dce_ctx;
2866 NTSTATUS status;
2868 if (dce_conn->terminate) {
2870 * if the current connection is broken
2871 * we need to clean it up before any other connection
2873 dcesrv_terminate_connection(dce_conn, dce_conn->terminate);
2874 dcesrv_cleanup_broken_connections(dce_ctx);
2875 return;
2878 dcesrv_cleanup_broken_connections(dce_ctx);
2880 status = dce_conn->wait_recv(subreq);
2881 dce_conn->wait_send = NULL;
2882 dce_conn->wait_recv = NULL;
2883 dce_conn->wait_private = NULL;
2884 TALLOC_FREE(subreq);
2885 if (!NT_STATUS_IS_OK(status)) {
2886 dcesrv_terminate_connection(dce_conn, nt_errstr(status));
2887 return;
2890 status = dcesrv_connection_loop_start(dce_conn);
2891 if (!NT_STATUS_IS_OK(status)) {
2892 dcesrv_terminate_connection(dce_conn, nt_errstr(status));
2893 return;
2898 * retrieve credentials from a dce_call
2900 _PUBLIC_ struct cli_credentials *dcesrv_call_credentials(struct dcesrv_call_state *dce_call)
2902 struct dcesrv_auth *auth = dce_call->auth_state;
2903 SMB_ASSERT(auth->auth_finished);
2904 return auth->session_info->credentials;
2908 * returns true if this is an authenticated call
2910 _PUBLIC_ bool dcesrv_call_authenticated(struct dcesrv_call_state *dce_call)
2912 struct dcesrv_auth *auth = dce_call->auth_state;
2913 enum security_user_level level;
2914 SMB_ASSERT(auth->auth_finished);
2915 level = security_session_user_level(auth->session_info, NULL);
2916 return level >= SECURITY_USER;
2920 * retrieve account_name for a dce_call
2922 _PUBLIC_ const char *dcesrv_call_account_name(struct dcesrv_call_state *dce_call)
2924 struct dcesrv_auth *auth = dce_call->auth_state;
2925 SMB_ASSERT(auth->auth_finished);
2926 return auth->session_info->info->account_name;
2930 * retrieve session_info from a dce_call
2932 _PUBLIC_ struct auth_session_info *dcesrv_call_session_info(struct dcesrv_call_state *dce_call)
2934 struct dcesrv_auth *auth = dce_call->auth_state;
2935 SMB_ASSERT(auth->auth_finished);
2936 return auth->session_info;
2940 * retrieve auth type/level from a dce_call
2942 _PUBLIC_ void dcesrv_call_auth_info(struct dcesrv_call_state *dce_call,
2943 enum dcerpc_AuthType *auth_type,
2944 enum dcerpc_AuthLevel *auth_level)
2946 struct dcesrv_auth *auth = dce_call->auth_state;
2948 SMB_ASSERT(auth->auth_finished);
2950 if (auth_type != NULL) {
2951 *auth_type = auth->auth_type;
2953 if (auth_level != NULL) {
2954 *auth_level = auth->auth_level;
2958 _PUBLIC_ NTSTATUS dcesrv_connection_loop_start(struct dcesrv_connection *conn)
2960 struct tevent_req *subreq;
2962 subreq = dcerpc_read_ncacn_packet_send(conn,
2963 conn->event_ctx,
2964 conn->stream);
2965 if (subreq == NULL) {
2966 return NT_STATUS_NO_MEMORY;
2968 tevent_req_set_callback(subreq, dcesrv_read_fragment_done, conn);
2970 return NT_STATUS_OK;