librpc/dcesrv_core: make use of dcerpc_fault_to_nt_status() in dcesrv_call_dispatch_l...
[Samba.git] / librpc / rpc / dcesrv_core.c
blob783d75d5bfe3e84aebd3d3e3bba9371d0fa61cd2
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 #undef strcasecmp
42 static NTSTATUS dcesrv_negotiate_contexts(struct dcesrv_call_state *call,
43 const struct dcerpc_bind *b,
44 struct dcerpc_ack_ctx *ack_ctx_list);
47 see if two endpoints match
49 static bool endpoints_match(const struct dcerpc_binding *ep1,
50 const struct dcerpc_binding *ep2)
52 enum dcerpc_transport_t t1;
53 enum dcerpc_transport_t t2;
54 const char *e1;
55 const char *e2;
57 t1 = dcerpc_binding_get_transport(ep1);
58 t2 = dcerpc_binding_get_transport(ep2);
60 e1 = dcerpc_binding_get_string_option(ep1, "endpoint");
61 e2 = dcerpc_binding_get_string_option(ep2, "endpoint");
63 if (t1 != t2) {
64 return false;
67 if (!e1 || !e2) {
68 return e1 == e2;
71 if (strcasecmp(e1, e2) != 0) {
72 return false;
75 return true;
79 find an endpoint in the dcesrv_context
81 _PUBLIC_ NTSTATUS dcesrv_find_endpoint(struct dcesrv_context *dce_ctx,
82 const struct dcerpc_binding *ep_description,
83 struct dcesrv_endpoint **_out)
85 struct dcesrv_endpoint *ep = NULL;
86 for (ep=dce_ctx->endpoint_list; ep; ep=ep->next) {
87 if (endpoints_match(ep->ep_description, ep_description)) {
88 *_out = ep;
89 return NT_STATUS_OK;
92 return NT_STATUS_NOT_FOUND;
96 find a registered context_id from a bind or alter_context
98 static struct dcesrv_connection_context *dcesrv_find_context(struct dcesrv_connection *conn,
99 uint16_t context_id)
101 struct dcesrv_connection_context *c;
102 for (c=conn->contexts;c;c=c->next) {
103 if (c->context_id == context_id) return c;
105 return NULL;
109 see if a uuid and if_version match to an interface
111 static bool interface_match(const struct dcesrv_interface *if1,
112 const struct dcesrv_interface *if2)
114 return (if1->syntax_id.if_version == if2->syntax_id.if_version &&
115 GUID_equal(&if1->syntax_id.uuid, &if2->syntax_id.uuid));
119 find the interface operations on any endpoint with this binding
121 static const struct dcesrv_interface *find_interface_by_binding(struct dcesrv_context *dce_ctx,
122 struct dcerpc_binding *binding,
123 const struct dcesrv_interface *iface)
125 struct dcesrv_endpoint *ep;
126 for (ep=dce_ctx->endpoint_list; ep; ep=ep->next) {
127 if (endpoints_match(ep->ep_description, binding)) {
128 struct dcesrv_if_list *ifl;
129 for (ifl=ep->interface_list; ifl; ifl=ifl->next) {
130 if (interface_match(ifl->iface, iface)) {
131 return ifl->iface;
136 return NULL;
140 see if a uuid and if_version match to an interface
142 static bool interface_match_by_uuid(const struct dcesrv_interface *iface,
143 const struct GUID *uuid, uint32_t if_version)
145 return (iface->syntax_id.if_version == if_version &&
146 GUID_equal(&iface->syntax_id.uuid, uuid));
150 find the interface operations on an endpoint by uuid
152 _PUBLIC_ const struct dcesrv_interface *find_interface_by_uuid(const struct dcesrv_endpoint *endpoint,
153 const struct GUID *uuid, uint32_t if_version)
155 struct dcesrv_if_list *ifl;
156 for (ifl=endpoint->interface_list; ifl; ifl=ifl->next) {
157 if (interface_match_by_uuid(ifl->iface, uuid, if_version)) {
158 return ifl->iface;
161 return NULL;
165 find the earlier parts of a fragmented call awaiting reassembily
167 static struct dcesrv_call_state *dcesrv_find_fragmented_call(struct dcesrv_connection *dce_conn, uint32_t call_id)
169 struct dcesrv_call_state *c;
170 for (c=dce_conn->incoming_fragmented_call_list;c;c=c->next) {
171 if (c->pkt.call_id == call_id) {
172 return c;
175 return NULL;
179 register an interface on an endpoint
181 An endpoint is one unix domain socket (for ncalrpc), one TCP port
182 (for ncacn_ip_tcp) or one (forwarded) named pipe (for ncacn_np).
184 Each endpoint can have many interfaces such as netlogon, lsa or
185 samr. Some have essentially the full set.
187 This is driven from the set of interfaces listed in each IDL file
188 via the PIDL generated *__op_init_server() functions.
190 _PUBLIC_ NTSTATUS dcesrv_interface_register(struct dcesrv_context *dce_ctx,
191 const char *ep_name,
192 const char *ncacn_np_secondary_endpoint,
193 const struct dcesrv_interface *iface,
194 const struct security_descriptor *sd)
196 struct dcesrv_endpoint *ep;
197 struct dcesrv_if_list *ifl;
198 struct dcerpc_binding *binding;
199 struct dcerpc_binding *binding2 = NULL;
200 bool add_ep = false;
201 NTSTATUS status;
202 enum dcerpc_transport_t transport;
203 char *ep_string = NULL;
204 bool use_single_process = true;
205 const char *ep_process_string;
208 * If we are not using handles, there is no need for force
209 * this service into using a single process.
211 * However, due to the way we listen for RPC packets, we can
212 * only do this if we have a single service per pipe or TCP
213 * port, so we still force a single combined process for
214 * ncalrpc.
216 if (iface->flags & DCESRV_INTERFACE_FLAGS_HANDLES_NOT_USED) {
217 use_single_process = false;
220 status = dcerpc_parse_binding(dce_ctx, ep_name, &binding);
222 if (NT_STATUS_IS_ERR(status)) {
223 DEBUG(0, ("Trouble parsing binding string '%s'\n", ep_name));
224 return status;
227 transport = dcerpc_binding_get_transport(binding);
228 if (transport == NCACN_IP_TCP) {
229 int port;
230 char port_str[6];
233 * First check if there is already a port specified, eg
234 * for epmapper on ncacn_ip_tcp:[135]
236 const char *endpoint
237 = dcerpc_binding_get_string_option(binding,
238 "endpoint");
239 if (endpoint == NULL) {
240 port = lpcfg_parm_int(dce_ctx->lp_ctx, NULL,
241 "rpc server port", iface->name, 0);
244 * For RPC services that are not set to use a single
245 * process, we do not default to using the 'rpc server
246 * port' because that would cause a double-bind on
247 * that port.
249 if (port == 0 && !use_single_process) {
250 port = lpcfg_rpc_server_port(dce_ctx->lp_ctx);
252 if (port != 0) {
253 snprintf(port_str, sizeof(port_str), "%u", port);
254 status = dcerpc_binding_set_string_option(binding,
255 "endpoint",
256 port_str);
257 if (!NT_STATUS_IS_OK(status)) {
258 return status;
264 if (transport == NCACN_NP && ncacn_np_secondary_endpoint != NULL) {
265 enum dcerpc_transport_t transport2;
267 status = dcerpc_parse_binding(dce_ctx,
268 ncacn_np_secondary_endpoint,
269 &binding2);
270 if (!NT_STATUS_IS_OK(status)) {
271 DEBUG(0, ("Trouble parsing 2nd binding string '%s'\n",
272 ncacn_np_secondary_endpoint));
273 return status;
276 transport2 = dcerpc_binding_get_transport(binding2);
277 SMB_ASSERT(transport2 == transport);
280 /* see if the interface is already registered on the endpoint */
281 if (find_interface_by_binding(dce_ctx, binding, iface)!=NULL) {
282 DEBUG(0,("dcesrv_interface_register: interface '%s' already registered on endpoint '%s'\n",
283 iface->name, ep_name));
284 return NT_STATUS_OBJECT_NAME_COLLISION;
287 /* check if this endpoint exists
289 status = dcesrv_find_endpoint(dce_ctx, binding, &ep);
290 if (NT_STATUS_IS_OK(status)) {
292 * We want a new port on ncacn_ip_tcp for NETLOGON, so
293 * it can be multi-process. Other processes can also
294 * listen on distinct ports, if they have one forced
295 * in the code above with eg 'rpc server port:drsuapi = 1027'
297 * If we have mulitiple endpoints on port 0, they each
298 * get an epemeral port (currently by walking up from
299 * 1024).
301 * Because one endpoint can only have one process
302 * model, we add a new IP_TCP endpoint for each model.
304 * This works in conjunction with the forced overwrite
305 * of ep->use_single_process below.
307 if (ep->use_single_process != use_single_process
308 && transport == NCACN_IP_TCP) {
309 add_ep = true;
313 if (NT_STATUS_EQUAL(status, NT_STATUS_NOT_FOUND) || add_ep) {
314 ep = talloc_zero(dce_ctx, struct dcesrv_endpoint);
315 if (!ep) {
316 return NT_STATUS_NO_MEMORY;
318 ZERO_STRUCTP(ep);
319 ep->ep_description = talloc_move(ep, &binding);
320 ep->ep_2nd_description = talloc_move(ep, &binding2);
321 add_ep = true;
323 /* add mgmt interface */
324 ifl = talloc_zero(ep, struct dcesrv_if_list);
325 if (!ifl) {
326 return NT_STATUS_NO_MEMORY;
329 ifl->iface = talloc_memdup(ifl,
330 dcesrv_get_mgmt_interface(),
331 sizeof(struct dcesrv_interface));
332 if (ifl->iface == NULL) {
333 talloc_free(ep);
334 return NT_STATUS_NO_MEMORY;
337 DLIST_ADD(ep->interface_list, ifl);
338 } else if (!NT_STATUS_IS_OK(status)) {
339 DBG_NOTICE("Failed to find endpoint: %s\n", nt_errstr(status));
340 return status;
344 * By default don't force into a single process, but if any
345 * interface on this endpoint on this service uses handles
346 * (most do), then we must force into single process mode
348 * By overwriting this each time a new interface is added to
349 * this endpoint, we end up with the most restrictive setting.
351 if (use_single_process) {
352 ep->use_single_process = true;
355 /* talloc a new interface list element */
356 ifl = talloc_zero(ep, struct dcesrv_if_list);
357 if (!ifl) {
358 return NT_STATUS_NO_MEMORY;
361 /* copy the given interface struct to the one on the endpoints interface list */
362 ifl->iface = talloc_memdup(ifl,
363 iface,
364 sizeof(struct dcesrv_interface));
365 if (ifl->iface == NULL) {
366 talloc_free(ep);
367 return NT_STATUS_NO_MEMORY;
370 /* if we have a security descriptor given,
371 * we should see if we can set it up on the endpoint
373 if (sd != NULL) {
374 /* if there's currently no security descriptor given on the endpoint
375 * we try to set it
377 if (ep->sd == NULL) {
378 ep->sd = security_descriptor_copy(ep, sd);
381 /* if now there's no security descriptor given on the endpoint
382 * something goes wrong, either we failed to copy the security descriptor
383 * or there was already one on the endpoint
385 if (ep->sd != NULL) {
386 DEBUG(0,("dcesrv_interface_register: interface '%s' failed to setup a security descriptor\n"
387 " on endpoint '%s'\n",
388 iface->name, ep_name));
389 if (add_ep) free(ep);
390 free(ifl);
391 return NT_STATUS_OBJECT_NAME_COLLISION;
395 /* finally add the interface on the endpoint */
396 DLIST_ADD(ep->interface_list, ifl);
398 /* if it's a new endpoint add it to the dcesrv_context */
399 if (add_ep) {
400 DLIST_ADD(dce_ctx->endpoint_list, ep);
403 /* Re-get the string as we may have set a port */
404 ep_string = dcerpc_binding_string(dce_ctx, ep->ep_description);
406 if (use_single_process) {
407 ep_process_string = "single process required";
408 } else {
409 ep_process_string = "multi process compatible";
412 DBG_INFO("Interface '%s' registered on endpoint '%s' (%s)\n",
413 iface->name, ep_string, ep_process_string);
414 TALLOC_FREE(ep_string);
416 return NT_STATUS_OK;
419 static NTSTATUS dcesrv_session_info_session_key(struct dcesrv_auth *auth,
420 DATA_BLOB *session_key)
422 if (auth->session_info == NULL) {
423 return NT_STATUS_NO_USER_SESSION_KEY;
426 if (auth->session_info->session_key.length == 0) {
427 return NT_STATUS_NO_USER_SESSION_KEY;
430 *session_key = auth->session_info->session_key;
431 return NT_STATUS_OK;
434 static NTSTATUS dcesrv_remote_session_key(struct dcesrv_auth *auth,
435 DATA_BLOB *session_key)
437 if (auth->auth_type != DCERPC_AUTH_TYPE_NONE) {
438 return NT_STATUS_NO_USER_SESSION_KEY;
441 return dcesrv_session_info_session_key(auth, session_key);
444 static NTSTATUS dcesrv_local_fixed_session_key(struct dcesrv_auth *auth,
445 DATA_BLOB *session_key)
447 return dcerpc_generic_session_key(session_key);
451 * Fetch the authentication session key if available.
453 * This is the key generated by a gensec authentication.
456 _PUBLIC_ NTSTATUS dcesrv_auth_session_key(struct dcesrv_call_state *call,
457 DATA_BLOB *session_key)
459 struct dcesrv_auth *auth = call->auth_state;
460 SMB_ASSERT(auth->auth_finished);
461 return dcesrv_session_info_session_key(auth, session_key);
465 * Fetch the transport session key if available.
466 * Typically this is the SMB session key
467 * or a fixed key for local transports.
469 * The key is always truncated to 16 bytes.
471 _PUBLIC_ NTSTATUS dcesrv_transport_session_key(struct dcesrv_call_state *call,
472 DATA_BLOB *session_key)
474 struct dcesrv_auth *auth = call->auth_state;
475 NTSTATUS status;
477 SMB_ASSERT(auth->auth_finished);
479 if (auth->session_key_fn == NULL) {
480 return NT_STATUS_NO_USER_SESSION_KEY;
483 status = auth->session_key_fn(auth, session_key);
484 if (!NT_STATUS_IS_OK(status)) {
485 return status;
488 session_key->length = MIN(session_key->length, 16);
490 return NT_STATUS_OK;
493 static struct dcesrv_auth *dcesrv_auth_create(struct dcesrv_connection *conn)
495 const struct dcesrv_endpoint *ep = conn->endpoint;
496 enum dcerpc_transport_t transport =
497 dcerpc_binding_get_transport(ep->ep_description);
498 struct dcesrv_auth *auth = NULL;
500 auth = talloc_zero(conn, struct dcesrv_auth);
501 if (auth == NULL) {
502 return NULL;
505 switch (transport) {
506 case NCACN_NP:
507 auth->session_key_fn = dcesrv_remote_session_key;
508 break;
509 case NCALRPC:
510 case NCACN_UNIX_STREAM:
511 auth->session_key_fn = dcesrv_local_fixed_session_key;
512 break;
513 default:
515 * All other's get a NULL pointer, which
516 * results in NT_STATUS_NO_USER_SESSION_KEY
518 break;
521 return auth;
525 connect to a dcerpc endpoint
527 _PUBLIC_ NTSTATUS dcesrv_endpoint_connect(struct dcesrv_context *dce_ctx,
528 TALLOC_CTX *mem_ctx,
529 const struct dcesrv_endpoint *ep,
530 struct auth_session_info *session_info,
531 struct tevent_context *event_ctx,
532 uint32_t state_flags,
533 struct dcesrv_connection **_p)
535 struct dcesrv_auth *auth = NULL;
536 struct dcesrv_connection *p;
538 if (!session_info) {
539 return NT_STATUS_ACCESS_DENIED;
542 p = talloc_zero(mem_ctx, struct dcesrv_connection);
543 NT_STATUS_HAVE_NO_MEMORY(p);
545 p->dce_ctx = dce_ctx;
546 p->endpoint = ep;
547 p->packet_log_dir = lpcfg_parm_string(dce_ctx->lp_ctx,
548 NULL,
549 "dcesrv",
550 "stubs directory");
551 p->event_ctx = event_ctx;
552 p->state_flags = state_flags;
553 p->allow_bind = true;
554 p->max_recv_frag = 5840;
555 p->max_xmit_frag = 5840;
556 p->max_total_request_size = DCERPC_NCACN_REQUEST_DEFAULT_MAX_SIZE;
558 p->support_hdr_signing = lpcfg_parm_bool(dce_ctx->lp_ctx,
559 NULL,
560 "dcesrv",
561 "header signing",
562 true);
563 p->max_auth_states = lpcfg_parm_ulong(dce_ctx->lp_ctx,
564 NULL,
565 "dcesrv",
566 "max auth states",
567 2049);
569 auth = dcesrv_auth_create(p);
570 if (auth == NULL) {
571 talloc_free(p);
572 return NT_STATUS_NO_MEMORY;
575 auth->session_info = talloc_reference(auth, session_info);
576 if (auth->session_info == NULL) {
577 talloc_free(p);
578 return NT_STATUS_NO_MEMORY;
581 p->default_auth_state = auth;
584 * For now we only support NDR32.
586 p->preferred_transfer = &ndr_transfer_syntax_ndr;
588 *_p = p;
589 return NT_STATUS_OK;
593 move a call from an existing linked list to the specified list. This
594 prevents bugs where we forget to remove the call from a previous
595 list when moving it.
597 static void dcesrv_call_set_list(struct dcesrv_call_state *call,
598 enum dcesrv_call_list list)
600 switch (call->list) {
601 case DCESRV_LIST_NONE:
602 break;
603 case DCESRV_LIST_CALL_LIST:
604 DLIST_REMOVE(call->conn->call_list, call);
605 break;
606 case DCESRV_LIST_FRAGMENTED_CALL_LIST:
607 DLIST_REMOVE(call->conn->incoming_fragmented_call_list, call);
608 break;
609 case DCESRV_LIST_PENDING_CALL_LIST:
610 DLIST_REMOVE(call->conn->pending_call_list, call);
611 break;
613 call->list = list;
614 switch (list) {
615 case DCESRV_LIST_NONE:
616 break;
617 case DCESRV_LIST_CALL_LIST:
618 DLIST_ADD_END(call->conn->call_list, call);
619 break;
620 case DCESRV_LIST_FRAGMENTED_CALL_LIST:
621 DLIST_ADD_END(call->conn->incoming_fragmented_call_list, call);
622 break;
623 case DCESRV_LIST_PENDING_CALL_LIST:
624 DLIST_ADD_END(call->conn->pending_call_list, call);
625 break;
629 static void dcesrv_call_disconnect_after(struct dcesrv_call_state *call,
630 const char *reason)
632 struct dcesrv_auth *a = NULL;
634 if (call->conn->terminate != NULL) {
635 return;
638 call->conn->allow_bind = false;
639 call->conn->allow_alter = false;
641 call->conn->default_auth_state->auth_invalid = true;
643 for (a = call->conn->auth_states; a != NULL; a = a->next) {
644 a->auth_invalid = true;
647 call->terminate_reason = talloc_strdup(call, reason);
648 if (call->terminate_reason == NULL) {
649 call->terminate_reason = __location__;
654 return a dcerpc bind_nak
656 static NTSTATUS dcesrv_bind_nak(struct dcesrv_call_state *call, uint32_t reason)
658 struct ncacn_packet pkt;
659 struct dcerpc_bind_nak_version version;
660 struct data_blob_list_item *rep;
661 NTSTATUS status;
662 static const uint8_t _pad[3] = { 0, };
665 * We add the call to the pending_call_list
666 * in order to defer the termination.
668 dcesrv_call_disconnect_after(call, "dcesrv_bind_nak");
670 /* setup a bind_nak */
671 dcesrv_init_hdr(&pkt, lpcfg_rpc_big_endian(call->conn->dce_ctx->lp_ctx));
672 pkt.auth_length = 0;
673 pkt.call_id = call->pkt.call_id;
674 pkt.ptype = DCERPC_PKT_BIND_NAK;
675 pkt.pfc_flags = DCERPC_PFC_FLAG_FIRST | DCERPC_PFC_FLAG_LAST;
676 pkt.u.bind_nak.reject_reason = reason;
677 version.rpc_vers = 5;
678 version.rpc_vers_minor = 0;
679 pkt.u.bind_nak.num_versions = 1;
680 pkt.u.bind_nak.versions = &version;
681 pkt.u.bind_nak._pad = data_blob_const(_pad, sizeof(_pad));
683 rep = talloc_zero(call, struct data_blob_list_item);
684 if (!rep) {
685 return NT_STATUS_NO_MEMORY;
688 status = dcerpc_ncacn_push_auth(&rep->blob, call, &pkt, NULL);
689 if (!NT_STATUS_IS_OK(status)) {
690 return status;
693 dcerpc_set_frag_length(&rep->blob, rep->blob.length);
695 DLIST_ADD_END(call->replies, rep);
696 dcesrv_call_set_list(call, DCESRV_LIST_CALL_LIST);
698 if (call->conn->call_list && call->conn->call_list->replies) {
699 if (call->conn->transport.report_output_data) {
700 call->conn->transport.report_output_data(call->conn);
704 return NT_STATUS_OK;
707 static NTSTATUS dcesrv_fault_disconnect(struct dcesrv_call_state *call,
708 uint32_t fault_code)
711 * We add the call to the pending_call_list
712 * in order to defer the termination.
714 dcesrv_call_disconnect_after(call, "dcesrv_fault_disconnect");
716 return dcesrv_fault_with_flags(call, fault_code,
717 DCERPC_PFC_FLAG_DID_NOT_EXECUTE);
720 static int dcesrv_connection_context_destructor(struct dcesrv_connection_context *c)
722 DLIST_REMOVE(c->conn->contexts, c);
724 if (c->iface && c->iface->unbind) {
725 c->iface->unbind(c, c->iface);
726 c->iface = NULL;
729 return 0;
732 static void dcesrv_prepare_context_auth(struct dcesrv_call_state *dce_call)
734 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
735 const struct dcesrv_endpoint *endpoint = dce_call->conn->endpoint;
736 enum dcerpc_transport_t transport =
737 dcerpc_binding_get_transport(endpoint->ep_description);
738 struct dcesrv_connection_context *context = dce_call->context;
739 const struct dcesrv_interface *iface = context->iface;
741 context->min_auth_level = DCERPC_AUTH_LEVEL_NONE;
743 if (transport == NCALRPC) {
744 context->allow_connect = true;
745 return;
749 * allow overwrite per interface
750 * allow dcerpc auth level connect:<interface>
752 context->allow_connect = lpcfg_allow_dcerpc_auth_level_connect(lp_ctx);
753 context->allow_connect = lpcfg_parm_bool(lp_ctx, NULL,
754 "allow dcerpc auth level connect",
755 iface->name,
756 context->allow_connect);
759 NTSTATUS dcesrv_interface_bind_require_integrity(struct dcesrv_connection_context *context,
760 const struct dcesrv_interface *iface)
763 * For connection oriented DCERPC DCERPC_AUTH_LEVEL_PACKET (4)
764 * has the same behavior as DCERPC_AUTH_LEVEL_INTEGRITY (5).
766 context->min_auth_level = DCERPC_AUTH_LEVEL_PACKET;
767 return NT_STATUS_OK;
770 NTSTATUS dcesrv_interface_bind_require_privacy(struct dcesrv_connection_context *context,
771 const struct dcesrv_interface *iface)
773 context->min_auth_level = DCERPC_AUTH_LEVEL_PRIVACY;
774 return NT_STATUS_OK;
777 _PUBLIC_ NTSTATUS dcesrv_interface_bind_reject_connect(struct dcesrv_connection_context *context,
778 const struct dcesrv_interface *iface)
780 struct loadparm_context *lp_ctx = context->conn->dce_ctx->lp_ctx;
781 const struct dcesrv_endpoint *endpoint = context->conn->endpoint;
782 enum dcerpc_transport_t transport =
783 dcerpc_binding_get_transport(endpoint->ep_description);
785 if (transport == NCALRPC) {
786 context->allow_connect = true;
787 return NT_STATUS_OK;
791 * allow overwrite per interface
792 * allow dcerpc auth level connect:<interface>
794 context->allow_connect = false;
795 context->allow_connect = lpcfg_parm_bool(lp_ctx, NULL,
796 "allow dcerpc auth level connect",
797 iface->name,
798 context->allow_connect);
799 return NT_STATUS_OK;
802 _PUBLIC_ NTSTATUS dcesrv_interface_bind_allow_connect(struct dcesrv_connection_context *context,
803 const struct dcesrv_interface *iface)
805 struct loadparm_context *lp_ctx = context->conn->dce_ctx->lp_ctx;
806 const struct dcesrv_endpoint *endpoint = context->conn->endpoint;
807 enum dcerpc_transport_t transport =
808 dcerpc_binding_get_transport(endpoint->ep_description);
810 if (transport == NCALRPC) {
811 context->allow_connect = true;
812 return NT_STATUS_OK;
816 * allow overwrite per interface
817 * allow dcerpc auth level connect:<interface>
819 context->allow_connect = true;
820 context->allow_connect = lpcfg_parm_bool(lp_ctx, NULL,
821 "allow dcerpc auth level connect",
822 iface->name,
823 context->allow_connect);
824 return NT_STATUS_OK;
827 struct dcesrv_conn_auth_wait_context {
828 struct tevent_req *req;
829 bool done;
830 NTSTATUS status;
833 struct dcesrv_conn_auth_wait_state {
834 uint8_t dummy;
837 static struct tevent_req *dcesrv_conn_auth_wait_send(TALLOC_CTX *mem_ctx,
838 struct tevent_context *ev,
839 void *private_data)
841 struct dcesrv_conn_auth_wait_context *auth_wait =
842 talloc_get_type_abort(private_data,
843 struct dcesrv_conn_auth_wait_context);
844 struct tevent_req *req = NULL;
845 struct dcesrv_conn_auth_wait_state *state = NULL;
847 req = tevent_req_create(mem_ctx, &state,
848 struct dcesrv_conn_auth_wait_state);
849 if (req == NULL) {
850 return NULL;
852 auth_wait->req = req;
854 tevent_req_defer_callback(req, ev);
856 if (!auth_wait->done) {
857 return req;
860 if (tevent_req_nterror(req, auth_wait->status)) {
861 return tevent_req_post(req, ev);
864 tevent_req_done(req);
865 return tevent_req_post(req, ev);
868 static NTSTATUS dcesrv_conn_auth_wait_recv(struct tevent_req *req)
870 return tevent_req_simple_recv_ntstatus(req);
873 static NTSTATUS dcesrv_conn_auth_wait_setup(struct dcesrv_connection *conn)
875 struct dcesrv_conn_auth_wait_context *auth_wait = NULL;
877 if (conn->wait_send != NULL) {
878 return NT_STATUS_INTERNAL_ERROR;
881 auth_wait = talloc_zero(conn, struct dcesrv_conn_auth_wait_context);
882 if (auth_wait == NULL) {
883 return NT_STATUS_NO_MEMORY;
886 conn->wait_private = auth_wait;
887 conn->wait_send = dcesrv_conn_auth_wait_send;
888 conn->wait_recv = dcesrv_conn_auth_wait_recv;
889 return NT_STATUS_OK;
892 static void dcesrv_conn_auth_wait_finished(struct dcesrv_connection *conn,
893 NTSTATUS status)
895 struct dcesrv_conn_auth_wait_context *auth_wait =
896 talloc_get_type_abort(conn->wait_private,
897 struct dcesrv_conn_auth_wait_context);
899 auth_wait->done = true;
900 auth_wait->status = status;
902 if (auth_wait->req == NULL) {
903 return;
906 if (tevent_req_nterror(auth_wait->req, status)) {
907 return;
910 tevent_req_done(auth_wait->req);
913 static NTSTATUS dcesrv_auth_reply(struct dcesrv_call_state *call);
915 static void dcesrv_bind_done(struct tevent_req *subreq);
918 handle a bind request
920 static NTSTATUS dcesrv_bind(struct dcesrv_call_state *call)
922 struct dcesrv_connection *conn = call->conn;
923 struct ncacn_packet *pkt = &call->ack_pkt;
924 NTSTATUS status;
925 uint32_t extra_flags = 0;
926 uint16_t max_req = 0;
927 uint16_t max_rep = 0;
928 struct dcerpc_binding *ep_2nd_description = NULL;
929 const char *endpoint = NULL;
930 struct dcesrv_auth *auth = call->auth_state;
931 struct dcerpc_ack_ctx *ack_ctx_list = NULL;
932 struct dcerpc_ack_ctx *ack_features = NULL;
933 struct tevent_req *subreq = NULL;
934 size_t i;
936 status = dcerpc_verify_ncacn_packet_header(&call->pkt,
937 DCERPC_PKT_BIND,
938 call->pkt.u.bind.auth_info.length,
939 0, /* required flags */
940 DCERPC_PFC_FLAG_FIRST |
941 DCERPC_PFC_FLAG_LAST |
942 DCERPC_PFC_FLAG_SUPPORT_HEADER_SIGN |
943 0x08 | /* this is not defined, but should be ignored */
944 DCERPC_PFC_FLAG_CONC_MPX |
945 DCERPC_PFC_FLAG_DID_NOT_EXECUTE |
946 DCERPC_PFC_FLAG_MAYBE |
947 DCERPC_PFC_FLAG_OBJECT_UUID);
948 if (!NT_STATUS_IS_OK(status)) {
949 return dcesrv_bind_nak(call,
950 DCERPC_BIND_NAK_REASON_PROTOCOL_VERSION_NOT_SUPPORTED);
953 /* max_recv_frag and max_xmit_frag result always in the same value! */
954 max_req = MIN(call->pkt.u.bind.max_xmit_frag,
955 call->pkt.u.bind.max_recv_frag);
957 * The values are between 2048 and 5840 tested against Windows 2012R2
958 * via ncacn_ip_tcp on port 135.
960 max_req = MAX(2048, max_req);
961 max_rep = MIN(max_req, call->conn->max_recv_frag);
962 /* They are truncated to an 8 byte boundary. */
963 max_rep &= 0xFFF8;
965 /* max_recv_frag and max_xmit_frag result always in the same value! */
966 call->conn->max_recv_frag = max_rep;
967 call->conn->max_xmit_frag = max_rep;
969 status = call->conn->dce_ctx->callbacks.assoc_group.find(call);
970 if (!NT_STATUS_IS_OK(status)) {
971 DBG_NOTICE("Failed to find assoc_group 0x%08x: %s\n",
972 call->pkt.u.bind.assoc_group_id, nt_errstr(status));
973 return dcesrv_bind_nak(call, 0);
976 if (call->pkt.u.bind.num_contexts < 1) {
977 return dcesrv_bind_nak(call, 0);
980 ack_ctx_list = talloc_zero_array(call, struct dcerpc_ack_ctx,
981 call->pkt.u.bind.num_contexts);
982 if (ack_ctx_list == NULL) {
983 return dcesrv_bind_nak(call, 0);
987 * Set some sane defaults (required by dcesrv_negotiate_contexts()/
988 * dcesrv_check_or_create_context()) and do some protocol validation
989 * and set sane defaults.
991 for (i = 0; i < call->pkt.u.bind.num_contexts; i++) {
992 const struct dcerpc_ctx_list *c = &call->pkt.u.bind.ctx_list[i];
993 struct dcerpc_ack_ctx *a = &ack_ctx_list[i];
994 bool is_feature = false;
995 uint64_t features = 0;
997 if (c->num_transfer_syntaxes == 0) {
998 return dcesrv_bind_nak(call, 0);
1001 a->result = DCERPC_BIND_ACK_RESULT_PROVIDER_REJECTION;
1002 a->reason.value = DCERPC_BIND_ACK_REASON_ABSTRACT_SYNTAX_NOT_SUPPORTED;
1005 * It's only treated as bind time feature request, if the first
1006 * transfer_syntax matches, all others are ignored.
1008 is_feature = dcerpc_extract_bind_time_features(c->transfer_syntaxes[0],
1009 &features);
1010 if (!is_feature) {
1011 continue;
1014 if (ack_features != NULL) {
1016 * Only one bind time feature context is allowed.
1018 return dcesrv_bind_nak(call, 0);
1020 ack_features = a;
1022 a->result = DCERPC_BIND_ACK_RESULT_NEGOTIATE_ACK;
1023 a->reason.negotiate = 0;
1024 if (features & DCERPC_BIND_TIME_SECURITY_CONTEXT_MULTIPLEXING) {
1025 if (call->conn->max_auth_states != 0) {
1026 a->reason.negotiate |=
1027 DCERPC_BIND_TIME_SECURITY_CONTEXT_MULTIPLEXING;
1030 if (features & DCERPC_BIND_TIME_KEEP_CONNECTION_ON_ORPHAN) {
1031 a->reason.negotiate |=
1032 DCERPC_BIND_TIME_KEEP_CONNECTION_ON_ORPHAN;
1035 call->conn->assoc_group->bind_time_features = a->reason.negotiate;
1039 * Try to negotiate one new presentation context.
1041 * Deep in here we locate the iface (by uuid) that the client
1042 * requested, from the list of interfaces on the
1043 * call->conn->endpoint, and call iface->bind() on that iface.
1045 * call->conn was set up at the accept() of the socket, and
1046 * call->conn->endpoint has a list of interfaces restricted to
1047 * this port or pipe.
1049 status = dcesrv_negotiate_contexts(call, &call->pkt.u.bind, ack_ctx_list);
1050 if (NT_STATUS_EQUAL(status, NT_STATUS_RPC_PROTOCOL_ERROR)) {
1051 return dcesrv_bind_nak(call, 0);
1053 if (!NT_STATUS_IS_OK(status)) {
1054 return status;
1058 * At this point we still don't know which interface (eg
1059 * netlogon, lsa, drsuapi) the caller requested in this bind!
1060 * The most recently added context is available as the first
1061 * element in the linked list at call->conn->contexts, that is
1062 * call->conn->contexts->iface, but they may not have
1063 * requested one at all!
1066 if ((call->pkt.pfc_flags & DCERPC_PFC_FLAG_CONC_MPX) &&
1067 (call->state_flags & DCESRV_CALL_STATE_FLAG_MULTIPLEXED)) {
1068 call->conn->state_flags |= DCESRV_CALL_STATE_FLAG_MULTIPLEXED;
1069 extra_flags |= DCERPC_PFC_FLAG_CONC_MPX;
1072 if (call->state_flags & DCESRV_CALL_STATE_FLAG_PROCESS_PENDING_CALL) {
1073 call->conn->state_flags |= DCESRV_CALL_STATE_FLAG_PROCESS_PENDING_CALL;
1077 * After finding the interface and setting up the NDR
1078 * transport negotiation etc, handle any authentication that
1079 * is being requested.
1081 if (!dcesrv_auth_bind(call)) {
1083 if (auth->auth_level == DCERPC_AUTH_LEVEL_NONE) {
1085 * With DCERPC_AUTH_LEVEL_NONE, we get the
1086 * reject_reason in auth->auth_context_id.
1088 return dcesrv_bind_nak(call, auth->auth_context_id);
1092 * This must a be a temporary failure e.g. talloc or invalid
1093 * configuration, e.g. no machine account.
1095 return dcesrv_bind_nak(call,
1096 DCERPC_BIND_NAK_REASON_TEMPORARY_CONGESTION);
1099 /* setup a bind_ack */
1100 dcesrv_init_hdr(pkt, lpcfg_rpc_big_endian(call->conn->dce_ctx->lp_ctx));
1101 pkt->auth_length = 0;
1102 pkt->call_id = call->pkt.call_id;
1103 pkt->ptype = DCERPC_PKT_BIND_ACK;
1104 pkt->pfc_flags = DCERPC_PFC_FLAG_FIRST | DCERPC_PFC_FLAG_LAST | extra_flags;
1105 pkt->u.bind_ack.max_xmit_frag = call->conn->max_xmit_frag;
1106 pkt->u.bind_ack.max_recv_frag = call->conn->max_recv_frag;
1107 pkt->u.bind_ack.assoc_group_id = call->conn->assoc_group->id;
1109 ep_2nd_description = call->conn->endpoint->ep_2nd_description;
1110 if (ep_2nd_description == NULL) {
1111 ep_2nd_description = call->conn->endpoint->ep_description;
1114 endpoint = dcerpc_binding_get_string_option(
1115 ep_2nd_description,
1116 "endpoint");
1117 if (endpoint == NULL) {
1118 endpoint = "";
1121 pkt->u.bind_ack.secondary_address = endpoint;
1122 pkt->u.bind_ack.num_results = call->pkt.u.bind.num_contexts;
1123 pkt->u.bind_ack.ctx_list = ack_ctx_list;
1124 pkt->u.bind_ack.auth_info = data_blob_null;
1126 status = dcesrv_auth_prepare_bind_ack(call, pkt);
1127 if (!NT_STATUS_IS_OK(status)) {
1128 return dcesrv_bind_nak(call, 0);
1131 if (auth->auth_finished) {
1132 return dcesrv_auth_reply(call);
1135 subreq = gensec_update_send(call, call->event_ctx,
1136 auth->gensec_security,
1137 call->in_auth_info.credentials);
1138 if (subreq == NULL) {
1139 return NT_STATUS_NO_MEMORY;
1141 tevent_req_set_callback(subreq, dcesrv_bind_done, call);
1143 return dcesrv_conn_auth_wait_setup(conn);
1146 static void dcesrv_bind_done(struct tevent_req *subreq)
1148 struct dcesrv_call_state *call =
1149 tevent_req_callback_data(subreq,
1150 struct dcesrv_call_state);
1151 struct dcesrv_connection *conn = call->conn;
1152 NTSTATUS status;
1154 status = gensec_update_recv(subreq, call,
1155 &call->out_auth_info->credentials);
1156 TALLOC_FREE(subreq);
1158 status = dcesrv_auth_complete(call, status);
1159 if (!NT_STATUS_IS_OK(status)) {
1160 status = dcesrv_bind_nak(call, 0);
1161 dcesrv_conn_auth_wait_finished(conn, status);
1162 return;
1165 status = dcesrv_auth_reply(call);
1166 dcesrv_conn_auth_wait_finished(conn, status);
1167 return;
1170 static NTSTATUS dcesrv_auth_reply(struct dcesrv_call_state *call)
1172 struct ncacn_packet *pkt = &call->ack_pkt;
1173 struct data_blob_list_item *rep = NULL;
1174 NTSTATUS status;
1176 rep = talloc_zero(call, struct data_blob_list_item);
1177 if (!rep) {
1178 return NT_STATUS_NO_MEMORY;
1181 status = dcerpc_ncacn_push_auth(&rep->blob,
1182 call,
1183 pkt,
1184 call->out_auth_info);
1185 if (!NT_STATUS_IS_OK(status)) {
1186 return status;
1189 dcerpc_set_frag_length(&rep->blob, rep->blob.length);
1191 DLIST_ADD_END(call->replies, rep);
1192 dcesrv_call_set_list(call, DCESRV_LIST_CALL_LIST);
1194 if (call->conn->call_list && call->conn->call_list->replies) {
1195 if (call->conn->transport.report_output_data) {
1196 call->conn->transport.report_output_data(call->conn);
1200 return NT_STATUS_OK;
1204 static void dcesrv_auth3_done(struct tevent_req *subreq);
1207 handle a auth3 request
1209 static NTSTATUS dcesrv_auth3(struct dcesrv_call_state *call)
1211 struct dcesrv_connection *conn = call->conn;
1212 struct dcesrv_auth *auth = call->auth_state;
1213 struct tevent_req *subreq = NULL;
1214 NTSTATUS status;
1216 if (!auth->auth_started) {
1217 return dcesrv_fault_disconnect(call, DCERPC_NCA_S_PROTO_ERROR);
1220 if (auth->auth_finished) {
1221 return dcesrv_fault_disconnect(call, DCERPC_NCA_S_PROTO_ERROR);
1224 status = dcerpc_verify_ncacn_packet_header(&call->pkt,
1225 DCERPC_PKT_AUTH3,
1226 call->pkt.u.auth3.auth_info.length,
1227 0, /* required flags */
1228 DCERPC_PFC_FLAG_FIRST |
1229 DCERPC_PFC_FLAG_LAST |
1230 DCERPC_PFC_FLAG_SUPPORT_HEADER_SIGN |
1231 0x08 | /* this is not defined, but should be ignored */
1232 DCERPC_PFC_FLAG_CONC_MPX |
1233 DCERPC_PFC_FLAG_DID_NOT_EXECUTE |
1234 DCERPC_PFC_FLAG_MAYBE |
1235 DCERPC_PFC_FLAG_OBJECT_UUID);
1236 if (!NT_STATUS_IS_OK(status)) {
1237 return dcesrv_fault_disconnect(call, DCERPC_NCA_S_PROTO_ERROR);
1240 /* handle the auth3 in the auth code */
1241 if (!dcesrv_auth_prepare_auth3(call)) {
1243 * we don't send a reply to a auth3 request,
1244 * except by a fault.
1246 * In anycase we mark the connection as
1247 * invalid.
1249 auth->auth_invalid = true;
1250 if (call->fault_code != 0) {
1251 return dcesrv_fault_disconnect(call, call->fault_code);
1253 TALLOC_FREE(call);
1254 return NT_STATUS_OK;
1257 subreq = gensec_update_send(call, call->event_ctx,
1258 auth->gensec_security,
1259 call->in_auth_info.credentials);
1260 if (subreq == NULL) {
1261 return NT_STATUS_NO_MEMORY;
1263 tevent_req_set_callback(subreq, dcesrv_auth3_done, call);
1265 return dcesrv_conn_auth_wait_setup(conn);
1268 static void dcesrv_auth3_done(struct tevent_req *subreq)
1270 struct dcesrv_call_state *call =
1271 tevent_req_callback_data(subreq,
1272 struct dcesrv_call_state);
1273 struct dcesrv_connection *conn = call->conn;
1274 struct dcesrv_auth *auth = call->auth_state;
1275 NTSTATUS status;
1277 status = gensec_update_recv(subreq, call,
1278 &call->out_auth_info->credentials);
1279 TALLOC_FREE(subreq);
1281 status = dcesrv_auth_complete(call, status);
1282 if (!NT_STATUS_IS_OK(status)) {
1284 * we don't send a reply to a auth3 request,
1285 * except by a fault.
1287 * In anycase we mark the connection as
1288 * invalid.
1290 auth->auth_invalid = true;
1291 if (call->fault_code != 0) {
1292 status = dcesrv_fault_disconnect(call, call->fault_code);
1293 dcesrv_conn_auth_wait_finished(conn, status);
1294 return;
1296 TALLOC_FREE(call);
1297 dcesrv_conn_auth_wait_finished(conn, NT_STATUS_OK);
1298 return;
1302 * we don't send a reply to a auth3 request.
1304 TALLOC_FREE(call);
1305 dcesrv_conn_auth_wait_finished(conn, NT_STATUS_OK);
1306 return;
1310 static NTSTATUS dcesrv_check_or_create_context(struct dcesrv_call_state *call,
1311 const struct dcerpc_bind *b,
1312 const struct dcerpc_ctx_list *ctx,
1313 struct dcerpc_ack_ctx *ack,
1314 bool validate_only,
1315 const struct ndr_syntax_id *supported_transfer)
1317 uint32_t if_version;
1318 struct dcesrv_connection_context *context;
1319 const struct dcesrv_interface *iface;
1320 struct GUID uuid;
1321 NTSTATUS status;
1322 const struct ndr_syntax_id *selected_transfer = NULL;
1323 size_t i;
1324 bool ok;
1326 if (b == NULL) {
1327 return NT_STATUS_INTERNAL_ERROR;
1329 if (ctx == NULL) {
1330 return NT_STATUS_INTERNAL_ERROR;
1332 if (ctx->num_transfer_syntaxes < 1) {
1333 return NT_STATUS_INTERNAL_ERROR;
1335 if (ack == NULL) {
1336 return NT_STATUS_INTERNAL_ERROR;
1338 if (supported_transfer == NULL) {
1339 return NT_STATUS_INTERNAL_ERROR;
1342 switch (ack->result) {
1343 case DCERPC_BIND_ACK_RESULT_ACCEPTANCE:
1344 case DCERPC_BIND_ACK_RESULT_NEGOTIATE_ACK:
1346 * We is already completed.
1348 return NT_STATUS_OK;
1349 default:
1350 break;
1353 ack->result = DCERPC_BIND_ACK_RESULT_PROVIDER_REJECTION;
1354 ack->reason.value = DCERPC_BIND_ACK_REASON_ABSTRACT_SYNTAX_NOT_SUPPORTED;
1356 if_version = ctx->abstract_syntax.if_version;
1357 uuid = ctx->abstract_syntax.uuid;
1359 iface = find_interface_by_uuid(call->conn->endpoint, &uuid, if_version);
1360 if (iface == NULL) {
1361 char *uuid_str = GUID_string(call, &uuid);
1362 DEBUG(2,("Request for unknown dcerpc interface %s/%d\n", uuid_str, if_version));
1363 talloc_free(uuid_str);
1365 * We report this only via ack->result
1367 return NT_STATUS_OK;
1370 ack->result = DCERPC_BIND_ACK_RESULT_PROVIDER_REJECTION;
1371 ack->reason.value = DCERPC_BIND_ACK_REASON_TRANSFER_SYNTAXES_NOT_SUPPORTED;
1373 if (validate_only) {
1375 * We report this only via ack->result
1377 return NT_STATUS_OK;
1380 for (i = 0; i < ctx->num_transfer_syntaxes; i++) {
1382 * we only do NDR encoded dcerpc for now.
1384 ok = ndr_syntax_id_equal(&ctx->transfer_syntaxes[i],
1385 supported_transfer);
1386 if (ok) {
1387 selected_transfer = supported_transfer;
1388 break;
1392 context = dcesrv_find_context(call->conn, ctx->context_id);
1393 if (context != NULL) {
1394 ok = ndr_syntax_id_equal(&context->iface->syntax_id,
1395 &ctx->abstract_syntax);
1396 if (!ok) {
1397 return NT_STATUS_RPC_PROTOCOL_ERROR;
1400 if (selected_transfer != NULL) {
1401 ok = ndr_syntax_id_equal(&context->transfer_syntax,
1402 selected_transfer);
1403 if (!ok) {
1404 return NT_STATUS_RPC_PROTOCOL_ERROR;
1407 ack->result = DCERPC_BIND_ACK_RESULT_ACCEPTANCE;
1408 ack->reason.value = DCERPC_BIND_ACK_REASON_NOT_SPECIFIED;
1409 ack->syntax = context->transfer_syntax;
1413 * We report this only via ack->result
1415 return NT_STATUS_OK;
1418 if (selected_transfer == NULL) {
1420 * We report this only via ack->result
1422 return NT_STATUS_OK;
1425 ack->result = DCERPC_BIND_ACK_RESULT_USER_REJECTION;
1426 ack->reason.value = DCERPC_BIND_ACK_REASON_LOCAL_LIMIT_EXCEEDED;
1428 /* add this context to the list of available context_ids */
1429 context = talloc_zero(call->conn, struct dcesrv_connection_context);
1430 if (context == NULL) {
1431 return NT_STATUS_NO_MEMORY;
1433 context->conn = call->conn;
1434 context->context_id = ctx->context_id;
1435 context->iface = iface;
1436 context->transfer_syntax = *selected_transfer;
1437 DLIST_ADD(call->conn->contexts, context);
1438 call->context = context;
1439 talloc_set_destructor(context, dcesrv_connection_context_destructor);
1441 dcesrv_prepare_context_auth(call);
1444 * Multiplex is supported by default
1446 call->state_flags |= DCESRV_CALL_STATE_FLAG_MULTIPLEXED;
1448 status = iface->bind(context, iface);
1449 call->context = NULL;
1450 if (!NT_STATUS_IS_OK(status)) {
1451 /* we don't want to trigger the iface->unbind() hook */
1452 context->iface = NULL;
1453 talloc_free(context);
1455 * We report this only via ack->result
1457 return NT_STATUS_OK;
1460 ack->result = DCERPC_BIND_ACK_RESULT_ACCEPTANCE;
1461 ack->reason.value = DCERPC_BIND_ACK_REASON_NOT_SPECIFIED;
1462 ack->syntax = context->transfer_syntax;
1463 return NT_STATUS_OK;
1466 static NTSTATUS dcesrv_negotiate_contexts(struct dcesrv_call_state *call,
1467 const struct dcerpc_bind *b,
1468 struct dcerpc_ack_ctx *ack_ctx_list)
1470 NTSTATUS status;
1471 size_t i;
1472 bool validate_only = false;
1473 bool preferred_ndr32;
1476 * Try to negotiate one new presentation context,
1477 * using our preferred transfer syntax.
1479 for (i = 0; i < b->num_contexts; i++) {
1480 const struct dcerpc_ctx_list *c = &b->ctx_list[i];
1481 struct dcerpc_ack_ctx *a = &ack_ctx_list[i];
1483 status = dcesrv_check_or_create_context(call, b, c, a,
1484 validate_only,
1485 call->conn->preferred_transfer);
1486 if (!NT_STATUS_IS_OK(status)) {
1487 return status;
1490 if (a->result == DCERPC_BIND_ACK_RESULT_ACCEPTANCE) {
1492 * We managed to negotiate one context.
1494 * => we're done.
1496 validate_only = true;
1500 preferred_ndr32 = ndr_syntax_id_equal(&ndr_transfer_syntax_ndr,
1501 call->conn->preferred_transfer);
1502 if (preferred_ndr32) {
1504 * We're done.
1506 return NT_STATUS_OK;
1510 * Try to negotiate one new presentation context,
1511 * using NDR 32 as fallback.
1513 for (i = 0; i < b->num_contexts; i++) {
1514 const struct dcerpc_ctx_list *c = &b->ctx_list[i];
1515 struct dcerpc_ack_ctx *a = &ack_ctx_list[i];
1517 status = dcesrv_check_or_create_context(call, b, c, a,
1518 validate_only,
1519 &ndr_transfer_syntax_ndr);
1520 if (!NT_STATUS_IS_OK(status)) {
1521 return status;
1524 if (a->result == DCERPC_BIND_ACK_RESULT_ACCEPTANCE) {
1526 * We managed to negotiate one context.
1528 * => we're done.
1530 validate_only = true;
1534 return NT_STATUS_OK;
1537 static void dcesrv_alter_done(struct tevent_req *subreq);
1540 handle a alter context request
1542 static NTSTATUS dcesrv_alter(struct dcesrv_call_state *call)
1544 struct dcesrv_connection *conn = call->conn;
1545 NTSTATUS status;
1546 bool auth_ok = false;
1547 struct ncacn_packet *pkt = &call->ack_pkt;
1548 uint32_t extra_flags = 0;
1549 struct dcesrv_auth *auth = call->auth_state;
1550 struct dcerpc_ack_ctx *ack_ctx_list = NULL;
1551 struct tevent_req *subreq = NULL;
1552 size_t i;
1554 if (!call->conn->allow_alter) {
1555 return dcesrv_fault_disconnect(call, DCERPC_NCA_S_PROTO_ERROR);
1558 status = dcerpc_verify_ncacn_packet_header(&call->pkt,
1559 DCERPC_PKT_ALTER,
1560 call->pkt.u.alter.auth_info.length,
1561 0, /* required flags */
1562 DCERPC_PFC_FLAG_FIRST |
1563 DCERPC_PFC_FLAG_LAST |
1564 DCERPC_PFC_FLAG_SUPPORT_HEADER_SIGN |
1565 0x08 | /* this is not defined, but should be ignored */
1566 DCERPC_PFC_FLAG_CONC_MPX |
1567 DCERPC_PFC_FLAG_DID_NOT_EXECUTE |
1568 DCERPC_PFC_FLAG_MAYBE |
1569 DCERPC_PFC_FLAG_OBJECT_UUID);
1570 if (!NT_STATUS_IS_OK(status)) {
1571 return dcesrv_fault_disconnect(call, DCERPC_NCA_S_PROTO_ERROR);
1574 auth_ok = dcesrv_auth_alter(call);
1575 if (!auth_ok) {
1576 if (call->fault_code != 0) {
1577 return dcesrv_fault_disconnect(call, call->fault_code);
1581 if (call->pkt.u.alter.num_contexts < 1) {
1582 return dcesrv_fault_disconnect(call, DCERPC_NCA_S_PROTO_ERROR);
1585 ack_ctx_list = talloc_zero_array(call, struct dcerpc_ack_ctx,
1586 call->pkt.u.alter.num_contexts);
1587 if (ack_ctx_list == NULL) {
1588 return NT_STATUS_NO_MEMORY;
1592 * Set some sane defaults (required by dcesrv_negotiate_contexts()/
1593 * dcesrv_check_or_create_context()) and do some protocol validation
1594 * and set sane defaults.
1596 for (i = 0; i < call->pkt.u.alter.num_contexts; i++) {
1597 const struct dcerpc_ctx_list *c = &call->pkt.u.alter.ctx_list[i];
1598 struct dcerpc_ack_ctx *a = &ack_ctx_list[i];
1600 if (c->num_transfer_syntaxes == 0) {
1601 return dcesrv_fault_disconnect(call,
1602 DCERPC_NCA_S_PROTO_ERROR);
1605 a->result = DCERPC_BIND_ACK_RESULT_PROVIDER_REJECTION;
1606 a->reason.value = DCERPC_BIND_ACK_REASON_ABSTRACT_SYNTAX_NOT_SUPPORTED;
1610 * Try to negotiate one new presentation context.
1612 status = dcesrv_negotiate_contexts(call, &call->pkt.u.alter, ack_ctx_list);
1613 if (NT_STATUS_EQUAL(status, NT_STATUS_RPC_PROTOCOL_ERROR)) {
1614 return dcesrv_fault_disconnect(call, DCERPC_NCA_S_PROTO_ERROR);
1616 if (!NT_STATUS_IS_OK(status)) {
1617 return status;
1620 if ((call->pkt.pfc_flags & DCERPC_PFC_FLAG_CONC_MPX) &&
1621 (call->state_flags & DCESRV_CALL_STATE_FLAG_MULTIPLEXED)) {
1622 call->conn->state_flags |= DCESRV_CALL_STATE_FLAG_MULTIPLEXED;
1623 extra_flags |= DCERPC_PFC_FLAG_CONC_MPX;
1626 if (call->state_flags & DCESRV_CALL_STATE_FLAG_PROCESS_PENDING_CALL) {
1627 call->conn->state_flags |= DCESRV_CALL_STATE_FLAG_PROCESS_PENDING_CALL;
1630 /* handle any authentication that is being requested */
1631 if (!auth_ok) {
1632 if (call->in_auth_info.auth_type != auth->auth_type) {
1633 return dcesrv_fault_disconnect(call,
1634 DCERPC_FAULT_SEC_PKG_ERROR);
1636 return dcesrv_fault_disconnect(call, DCERPC_FAULT_ACCESS_DENIED);
1639 dcesrv_init_hdr(pkt, lpcfg_rpc_big_endian(call->conn->dce_ctx->lp_ctx));
1640 pkt->auth_length = 0;
1641 pkt->call_id = call->pkt.call_id;
1642 pkt->ptype = DCERPC_PKT_ALTER_RESP;
1643 pkt->pfc_flags = DCERPC_PFC_FLAG_FIRST | DCERPC_PFC_FLAG_LAST | extra_flags;
1644 pkt->u.alter_resp.max_xmit_frag = call->conn->max_xmit_frag;
1645 pkt->u.alter_resp.max_recv_frag = call->conn->max_recv_frag;
1646 pkt->u.alter_resp.assoc_group_id = call->conn->assoc_group->id;
1647 pkt->u.alter_resp.secondary_address = "";
1648 pkt->u.alter_resp.num_results = call->pkt.u.alter.num_contexts;
1649 pkt->u.alter_resp.ctx_list = ack_ctx_list;
1650 pkt->u.alter_resp.auth_info = data_blob_null;
1652 status = dcesrv_auth_prepare_alter_ack(call, pkt);
1653 if (!NT_STATUS_IS_OK(status)) {
1654 return dcesrv_fault_disconnect(call, DCERPC_FAULT_SEC_PKG_ERROR);
1657 if (auth->auth_finished) {
1658 return dcesrv_auth_reply(call);
1661 subreq = gensec_update_send(call, call->event_ctx,
1662 auth->gensec_security,
1663 call->in_auth_info.credentials);
1664 if (subreq == NULL) {
1665 return NT_STATUS_NO_MEMORY;
1667 tevent_req_set_callback(subreq, dcesrv_alter_done, call);
1669 return dcesrv_conn_auth_wait_setup(conn);
1672 static void dcesrv_alter_done(struct tevent_req *subreq)
1674 struct dcesrv_call_state *call =
1675 tevent_req_callback_data(subreq,
1676 struct dcesrv_call_state);
1677 struct dcesrv_connection *conn = call->conn;
1678 NTSTATUS status;
1680 status = gensec_update_recv(subreq, call,
1681 &call->out_auth_info->credentials);
1682 TALLOC_FREE(subreq);
1684 status = dcesrv_auth_complete(call, status);
1685 if (!NT_STATUS_IS_OK(status)) {
1686 status = dcesrv_fault_disconnect(call, DCERPC_FAULT_SEC_PKG_ERROR);
1687 dcesrv_conn_auth_wait_finished(conn, status);
1688 return;
1691 status = dcesrv_auth_reply(call);
1692 dcesrv_conn_auth_wait_finished(conn, status);
1693 return;
1697 possibly save the call for inspection with ndrdump
1699 static void dcesrv_save_call(struct dcesrv_call_state *call, const char *why)
1701 #ifdef DEVELOPER
1702 dcerpc_log_packet(call->conn->packet_log_dir,
1703 call->context->iface->name,
1704 call->pkt.u.request.opnum,
1705 NDR_IN,
1706 &call->pkt.u.request.stub_and_verifier,
1707 why);
1708 #endif
1711 #ifdef DEVELOPER
1713 Save the call for use as a seed for fuzzing.
1715 This is only enabled in a developer build, and only has effect if the
1716 "dcesrv fuzz directory" param is set.
1718 void _dcesrv_save_ndr_fuzz_seed(DATA_BLOB call_blob,
1719 struct dcesrv_call_state *call,
1720 int flags)
1722 const char *dump_dir = lpcfg_parm_string(call->conn->dce_ctx->lp_ctx,
1723 NULL,
1724 "dcesrv", "fuzz directory");
1726 dcerpc_save_ndr_fuzz_seed(call,
1727 call_blob,
1728 dump_dir,
1729 call->context->iface->name,
1730 flags,
1731 call->pkt.u.request.opnum,
1732 call->ndr_pull->flags & LIBNDR_FLAG_NDR64);
1734 #endif /*if DEVELOPER, enveloping _dcesrv_save_ndr_fuzz_seed() */
1737 static NTSTATUS dcesrv_check_verification_trailer(struct dcesrv_call_state *call)
1739 TALLOC_CTX *frame = talloc_stackframe();
1740 const uint32_t bitmask1 = call->conn->client_hdr_signing ?
1741 DCERPC_SEC_VT_CLIENT_SUPPORTS_HEADER_SIGNING : 0;
1742 const struct dcerpc_sec_vt_pcontext pcontext = {
1743 .abstract_syntax = call->context->iface->syntax_id,
1744 .transfer_syntax = call->context->transfer_syntax,
1746 const struct dcerpc_sec_vt_header2 header2 =
1747 dcerpc_sec_vt_header2_from_ncacn_packet(&call->pkt);
1748 enum ndr_err_code ndr_err;
1749 struct dcerpc_sec_verification_trailer *vt = NULL;
1750 NTSTATUS status = NT_STATUS_OK;
1751 bool ok;
1753 SMB_ASSERT(call->pkt.ptype == DCERPC_PKT_REQUEST);
1755 ndr_err = ndr_pop_dcerpc_sec_verification_trailer(call->ndr_pull,
1756 frame, &vt);
1757 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
1758 status = ndr_map_error2ntstatus(ndr_err);
1759 goto done;
1762 ok = dcerpc_sec_verification_trailer_check(vt, &bitmask1,
1763 &pcontext, &header2);
1764 if (!ok) {
1765 status = NT_STATUS_ACCESS_DENIED;
1766 goto done;
1768 done:
1769 TALLOC_FREE(frame);
1770 return status;
1774 handle a dcerpc request packet
1776 static NTSTATUS dcesrv_request(struct dcesrv_call_state *call)
1778 const struct dcesrv_endpoint *endpoint = call->conn->endpoint;
1779 struct dcesrv_auth *auth = call->auth_state;
1780 enum dcerpc_transport_t transport =
1781 dcerpc_binding_get_transport(endpoint->ep_description);
1782 struct ndr_pull *pull;
1783 NTSTATUS status;
1785 if (!auth->auth_finished) {
1786 return dcesrv_fault_disconnect(call, DCERPC_NCA_S_PROTO_ERROR);
1789 /* if authenticated, and the mech we use can't do async replies, don't use them... */
1790 if (auth->gensec_security != NULL &&
1791 !gensec_have_feature(auth->gensec_security, GENSEC_FEATURE_ASYNC_REPLIES)) {
1792 call->state_flags &= ~DCESRV_CALL_STATE_FLAG_MAY_ASYNC;
1795 if (call->context == NULL) {
1796 return dcesrv_fault_with_flags(call, DCERPC_NCA_S_UNKNOWN_IF,
1797 DCERPC_PFC_FLAG_DID_NOT_EXECUTE);
1800 switch (auth->auth_level) {
1801 case DCERPC_AUTH_LEVEL_NONE:
1802 case DCERPC_AUTH_LEVEL_PACKET:
1803 case DCERPC_AUTH_LEVEL_INTEGRITY:
1804 case DCERPC_AUTH_LEVEL_PRIVACY:
1805 break;
1806 default:
1807 if (!call->context->allow_connect) {
1808 char *addr;
1810 addr = tsocket_address_string(call->conn->remote_address,
1811 call);
1813 DEBUG(2, ("%s: restrict auth_level_connect access "
1814 "to [%s] with auth[type=0x%x,level=0x%x] "
1815 "on [%s] from [%s]\n",
1816 __func__, call->context->iface->name,
1817 auth->auth_type,
1818 auth->auth_level,
1819 derpc_transport_string_by_transport(transport),
1820 addr));
1821 return dcesrv_fault(call, DCERPC_FAULT_ACCESS_DENIED);
1823 break;
1826 if (auth->auth_level < call->context->min_auth_level) {
1827 char *addr;
1829 addr = tsocket_address_string(call->conn->remote_address, call);
1831 DEBUG(2, ("%s: restrict access by min_auth_level[0x%x] "
1832 "to [%s] with auth[type=0x%x,level=0x%x] "
1833 "on [%s] from [%s]\n",
1834 __func__,
1835 call->context->min_auth_level,
1836 call->context->iface->name,
1837 auth->auth_type,
1838 auth->auth_level,
1839 derpc_transport_string_by_transport(transport),
1840 addr));
1841 return dcesrv_fault(call, DCERPC_FAULT_ACCESS_DENIED);
1844 pull = ndr_pull_init_blob(&call->pkt.u.request.stub_and_verifier, call);
1845 NT_STATUS_HAVE_NO_MEMORY(pull);
1847 pull->flags |= LIBNDR_FLAG_REF_ALLOC;
1849 call->ndr_pull = pull;
1851 if (!(call->pkt.drep[0] & DCERPC_DREP_LE)) {
1852 pull->flags |= LIBNDR_FLAG_BIGENDIAN;
1855 status = dcesrv_check_verification_trailer(call);
1856 if (!NT_STATUS_IS_OK(status)) {
1857 uint32_t faultcode = DCERPC_FAULT_OTHER;
1858 if (NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
1859 faultcode = DCERPC_FAULT_ACCESS_DENIED;
1861 DEBUG(10, ("dcesrv_check_verification_trailer failed: %s\n",
1862 nt_errstr(status)));
1863 return dcesrv_fault(call, faultcode);
1866 /* unravel the NDR for the packet */
1867 status = call->context->iface->ndr_pull(call, call, pull, &call->r);
1868 if (!NT_STATUS_IS_OK(status)) {
1869 uint8_t extra_flags = 0;
1870 if (call->fault_code == DCERPC_FAULT_OP_RNG_ERROR) {
1871 /* we got an unknown call */
1872 DEBUG(3,(__location__ ": Unknown RPC call %u on %s\n",
1873 call->pkt.u.request.opnum,
1874 call->context->iface->name));
1875 dcesrv_save_call(call, "unknown");
1876 extra_flags |= DCERPC_PFC_FLAG_DID_NOT_EXECUTE;
1877 } else {
1878 dcesrv_save_call(call, "pullfail");
1881 return dcesrv_fault_with_flags(call, call->fault_code, extra_flags);
1884 dcesrv_save_ndr_fuzz_seed(call->pkt.u.request.stub_and_verifier,
1885 call,
1886 NDR_IN);
1888 if (pull->offset != pull->data_size) {
1889 dcesrv_save_call(call, "extrabytes");
1890 DEBUG(3,("Warning: %d extra bytes in incoming RPC request\n",
1891 pull->data_size - pull->offset));
1894 /* call the dispatch function */
1895 status = call->context->iface->dispatch(call, call, call->r);
1896 if (!NT_STATUS_IS_OK(status)) {
1897 DEBUG(5,("dcerpc fault in call %s:%02x - %s\n",
1898 call->context->iface->name,
1899 call->pkt.u.request.opnum,
1900 dcerpc_errstr(pull, call->fault_code)));
1901 return dcesrv_fault(call, call->fault_code);
1904 /* add the call to the pending list */
1905 dcesrv_call_set_list(call, DCESRV_LIST_PENDING_CALL_LIST);
1907 if (call->state_flags & DCESRV_CALL_STATE_FLAG_ASYNC) {
1908 return NT_STATUS_OK;
1911 return dcesrv_reply(call);
1916 remove the call from the right list when freed
1918 static int dcesrv_call_dequeue(struct dcesrv_call_state *call)
1920 dcesrv_call_set_list(call, DCESRV_LIST_NONE);
1921 return 0;
1924 _PUBLIC_ const struct tsocket_address *dcesrv_connection_get_local_address(struct dcesrv_connection *conn)
1926 return conn->local_address;
1929 _PUBLIC_ const struct tsocket_address *dcesrv_connection_get_remote_address(struct dcesrv_connection *conn)
1931 return conn->remote_address;
1935 process some input to a dcerpc endpoint server.
1937 static NTSTATUS dcesrv_process_ncacn_packet(struct dcesrv_connection *dce_conn,
1938 struct ncacn_packet *pkt,
1939 DATA_BLOB blob)
1941 NTSTATUS status;
1942 struct dcesrv_call_state *call;
1943 struct dcesrv_call_state *existing = NULL;
1944 size_t num_auth_ctx = 0;
1945 enum dcerpc_AuthType auth_type = 0;
1946 enum dcerpc_AuthLevel auth_level = 0;
1947 uint32_t auth_context_id = 0;
1949 call = talloc_zero(dce_conn, struct dcesrv_call_state);
1950 if (!call) {
1951 data_blob_free(&blob);
1952 talloc_free(pkt);
1953 return NT_STATUS_NO_MEMORY;
1955 call->conn = dce_conn;
1956 call->event_ctx = dce_conn->event_ctx;
1957 call->state_flags = call->conn->state_flags;
1958 call->time = timeval_current();
1959 call->list = DCESRV_LIST_NONE;
1961 talloc_steal(call, pkt);
1962 talloc_steal(call, blob.data);
1963 call->pkt = *pkt;
1965 if (dce_conn->max_auth_states == 0) {
1966 call->auth_state = dce_conn->default_auth_state;
1967 } else if (call->pkt.auth_length == 0) {
1968 if (call->pkt.ptype == DCERPC_PKT_REQUEST &&
1969 dce_conn->default_auth_level_connect != NULL)
1971 call->auth_state = dce_conn->default_auth_level_connect;
1972 } else {
1973 call->auth_state = dce_conn->default_auth_state;
1977 if (call->auth_state == NULL) {
1978 struct dcesrv_auth *a = NULL;
1980 auth_type = dcerpc_get_auth_type(&blob);
1981 auth_level = dcerpc_get_auth_level(&blob);
1982 auth_context_id = dcerpc_get_auth_context_id(&blob);
1984 if (call->pkt.ptype == DCERPC_PKT_REQUEST) {
1985 dce_conn->default_auth_level_connect = NULL;
1986 if (auth_level == DCERPC_AUTH_LEVEL_CONNECT) {
1987 dce_conn->got_explicit_auth_level_connect = true;
1991 for (a = dce_conn->auth_states; a != NULL; a = a->next) {
1992 num_auth_ctx++;
1994 if (a->auth_type != auth_type) {
1995 continue;
1997 if (a->auth_finished && a->auth_level != auth_level) {
1998 continue;
2000 if (a->auth_context_id != auth_context_id) {
2001 continue;
2004 DLIST_PROMOTE(dce_conn->auth_states, a);
2005 call->auth_state = a;
2006 break;
2010 if (call->auth_state == NULL) {
2011 struct dcesrv_auth *a = NULL;
2013 if (num_auth_ctx >= dce_conn->max_auth_states) {
2014 return dcesrv_fault_disconnect(call,
2015 DCERPC_NCA_S_PROTO_ERROR);
2018 a = dcesrv_auth_create(dce_conn);
2019 if (a == NULL) {
2020 talloc_free(call);
2021 return NT_STATUS_NO_MEMORY;
2023 DLIST_ADD(dce_conn->auth_states, a);
2024 if (call->pkt.ptype == DCERPC_PKT_REQUEST) {
2026 * This can never be valid.
2028 a->auth_invalid = true;
2030 call->auth_state = a;
2033 talloc_set_destructor(call, dcesrv_call_dequeue);
2035 if (call->conn->allow_bind) {
2037 * Only one bind is possible per connection
2039 call->conn->allow_bind = false;
2040 return dcesrv_bind(call);
2043 /* we have to check the signing here, before combining the
2044 pdus */
2045 if (call->pkt.ptype == DCERPC_PKT_REQUEST) {
2046 dcesrv_default_auth_state_prepare_request(call);
2048 if (call->auth_state->auth_started &&
2049 !call->auth_state->auth_finished) {
2050 return dcesrv_fault_disconnect(call,
2051 DCERPC_NCA_S_PROTO_ERROR);
2054 status = dcerpc_verify_ncacn_packet_header(&call->pkt,
2055 DCERPC_PKT_REQUEST,
2056 call->pkt.u.request.stub_and_verifier.length,
2057 0, /* required_flags */
2058 DCERPC_PFC_FLAG_FIRST |
2059 DCERPC_PFC_FLAG_LAST |
2060 DCERPC_PFC_FLAG_PENDING_CANCEL |
2061 0x08 | /* this is not defined, but should be ignored */
2062 DCERPC_PFC_FLAG_CONC_MPX |
2063 DCERPC_PFC_FLAG_DID_NOT_EXECUTE |
2064 DCERPC_PFC_FLAG_MAYBE |
2065 DCERPC_PFC_FLAG_OBJECT_UUID);
2066 if (!NT_STATUS_IS_OK(status)) {
2067 return dcesrv_fault_disconnect(call,
2068 DCERPC_NCA_S_PROTO_ERROR);
2071 if (call->pkt.frag_length > DCERPC_FRAG_MAX_SIZE) {
2073 * We don't use dcesrv_fault_disconnect()
2074 * here, because we don't want to set
2075 * DCERPC_PFC_FLAG_DID_NOT_EXECUTE
2077 * Note that we don't check against the negotiated
2078 * max_recv_frag, but a hard coded value.
2080 dcesrv_call_disconnect_after(call,
2081 "dcesrv_auth_request - frag_length too large");
2082 return dcesrv_fault(call,
2083 DCERPC_NCA_S_PROTO_ERROR);
2086 if (call->pkt.pfc_flags & DCERPC_PFC_FLAG_FIRST) {
2087 if (dce_conn->pending_call_list != NULL) {
2089 * concurrent requests are only allowed
2090 * if DCERPC_PFC_FLAG_CONC_MPX was negotiated.
2092 if (!(dce_conn->state_flags & DCESRV_CALL_STATE_FLAG_MULTIPLEXED)) {
2093 dcesrv_call_disconnect_after(call,
2094 "dcesrv_auth_request - "
2095 "existing pending call without CONN_MPX");
2096 return dcesrv_fault(call,
2097 DCERPC_NCA_S_PROTO_ERROR);
2100 /* only one request is possible in the fragmented list */
2101 if (dce_conn->incoming_fragmented_call_list != NULL) {
2102 if (!(dce_conn->state_flags & DCESRV_CALL_STATE_FLAG_MULTIPLEXED)) {
2104 * Without DCERPC_PFC_FLAG_CONC_MPX
2105 * we need to return the FAULT on the
2106 * already existing call.
2108 * This is important to get the
2109 * call_id and context_id right.
2111 TALLOC_FREE(call);
2112 call = dce_conn->incoming_fragmented_call_list;
2114 dcesrv_call_disconnect_after(call,
2115 "dcesrv_auth_request - "
2116 "existing fragmented call");
2117 return dcesrv_fault(call,
2118 DCERPC_NCA_S_PROTO_ERROR);
2120 if (call->pkt.pfc_flags & DCERPC_PFC_FLAG_PENDING_CANCEL) {
2121 return dcesrv_fault_disconnect(call,
2122 DCERPC_FAULT_NO_CALL_ACTIVE);
2124 call->context = dcesrv_find_context(call->conn,
2125 call->pkt.u.request.context_id);
2126 if (call->context == NULL) {
2127 return dcesrv_fault_with_flags(call, DCERPC_NCA_S_UNKNOWN_IF,
2128 DCERPC_PFC_FLAG_DID_NOT_EXECUTE);
2130 } else {
2131 const struct dcerpc_request *nr = &call->pkt.u.request;
2132 const struct dcerpc_request *er = NULL;
2133 int cmp;
2135 existing = dcesrv_find_fragmented_call(dce_conn,
2136 call->pkt.call_id);
2137 if (existing == NULL) {
2138 dcesrv_call_disconnect_after(call,
2139 "dcesrv_auth_request - "
2140 "no existing fragmented call");
2141 return dcesrv_fault(call,
2142 DCERPC_NCA_S_PROTO_ERROR);
2144 er = &existing->pkt.u.request;
2146 if (call->pkt.ptype != existing->pkt.ptype) {
2147 /* trying to play silly buggers are we? */
2148 return dcesrv_fault_disconnect(existing,
2149 DCERPC_NCA_S_PROTO_ERROR);
2151 cmp = memcmp(call->pkt.drep, existing->pkt.drep,
2152 sizeof(pkt->drep));
2153 if (cmp != 0) {
2154 return dcesrv_fault_disconnect(existing,
2155 DCERPC_NCA_S_PROTO_ERROR);
2157 if (nr->context_id != er->context_id) {
2158 return dcesrv_fault_disconnect(existing,
2159 DCERPC_NCA_S_PROTO_ERROR);
2161 if (nr->opnum != er->opnum) {
2162 return dcesrv_fault_disconnect(existing,
2163 DCERPC_NCA_S_PROTO_ERROR);
2168 if (call->pkt.ptype == DCERPC_PKT_REQUEST) {
2169 bool ok;
2170 uint8_t payload_offset = DCERPC_REQUEST_LENGTH;
2172 if (call->pkt.pfc_flags & DCERPC_PFC_FLAG_OBJECT_UUID) {
2173 payload_offset += 16;
2176 ok = dcesrv_auth_pkt_pull(call, &blob,
2177 0, /* required_flags */
2178 DCERPC_PFC_FLAG_FIRST |
2179 DCERPC_PFC_FLAG_LAST |
2180 DCERPC_PFC_FLAG_PENDING_CANCEL |
2181 0x08 | /* this is not defined, but should be ignored */
2182 DCERPC_PFC_FLAG_CONC_MPX |
2183 DCERPC_PFC_FLAG_DID_NOT_EXECUTE |
2184 DCERPC_PFC_FLAG_MAYBE |
2185 DCERPC_PFC_FLAG_OBJECT_UUID,
2186 payload_offset,
2187 &call->pkt.u.request.stub_and_verifier);
2188 if (!ok) {
2190 * We don't use dcesrv_fault_disconnect()
2191 * here, because we don't want to set
2192 * DCERPC_PFC_FLAG_DID_NOT_EXECUTE
2194 dcesrv_call_disconnect_after(call,
2195 "dcesrv_auth_request - failed");
2196 if (call->fault_code == 0) {
2197 call->fault_code = DCERPC_FAULT_ACCESS_DENIED;
2199 return dcesrv_fault(call, call->fault_code);
2203 /* see if this is a continued packet */
2204 if (existing != NULL) {
2205 struct dcerpc_request *er = &existing->pkt.u.request;
2206 const struct dcerpc_request *nr = &call->pkt.u.request;
2207 size_t available;
2208 size_t alloc_size;
2209 size_t alloc_hint;
2212 * Up to 4 MByte are allowed by all fragments
2214 available = dce_conn->max_total_request_size;
2215 if (er->stub_and_verifier.length > available) {
2216 dcesrv_call_disconnect_after(existing,
2217 "dcesrv_auth_request - existing payload too large");
2218 return dcesrv_fault(existing, DCERPC_FAULT_ACCESS_DENIED);
2220 available -= er->stub_and_verifier.length;
2221 if (nr->alloc_hint > available) {
2222 dcesrv_call_disconnect_after(existing,
2223 "dcesrv_auth_request - alloc hint too large");
2224 return dcesrv_fault(existing, DCERPC_FAULT_ACCESS_DENIED);
2226 if (nr->stub_and_verifier.length > available) {
2227 dcesrv_call_disconnect_after(existing,
2228 "dcesrv_auth_request - new payload too large");
2229 return dcesrv_fault(existing, DCERPC_FAULT_ACCESS_DENIED);
2231 alloc_hint = er->stub_and_verifier.length + nr->alloc_hint;
2232 /* allocate at least 1 byte */
2233 alloc_hint = MAX(alloc_hint, 1);
2234 alloc_size = er->stub_and_verifier.length +
2235 nr->stub_and_verifier.length;
2236 alloc_size = MAX(alloc_size, alloc_hint);
2238 er->stub_and_verifier.data =
2239 talloc_realloc(existing,
2240 er->stub_and_verifier.data,
2241 uint8_t, alloc_size);
2242 if (er->stub_and_verifier.data == NULL) {
2243 TALLOC_FREE(call);
2244 return dcesrv_fault_with_flags(existing,
2245 DCERPC_FAULT_OUT_OF_RESOURCES,
2246 DCERPC_PFC_FLAG_DID_NOT_EXECUTE);
2248 memcpy(er->stub_and_verifier.data +
2249 er->stub_and_verifier.length,
2250 nr->stub_and_verifier.data,
2251 nr->stub_and_verifier.length);
2252 er->stub_and_verifier.length += nr->stub_and_verifier.length;
2254 existing->pkt.pfc_flags |= (call->pkt.pfc_flags & DCERPC_PFC_FLAG_LAST);
2256 TALLOC_FREE(call);
2257 call = existing;
2260 /* this may not be the last pdu in the chain - if its isn't then
2261 just put it on the incoming_fragmented_call_list and wait for the rest */
2262 if (call->pkt.ptype == DCERPC_PKT_REQUEST &&
2263 !(call->pkt.pfc_flags & DCERPC_PFC_FLAG_LAST)) {
2265 * Up to 4 MByte are allowed by all fragments
2267 if (call->pkt.u.request.alloc_hint > dce_conn->max_total_request_size) {
2268 dcesrv_call_disconnect_after(call,
2269 "dcesrv_auth_request - initial alloc hint too large");
2270 return dcesrv_fault(call, DCERPC_FAULT_ACCESS_DENIED);
2272 dcesrv_call_set_list(call, DCESRV_LIST_FRAGMENTED_CALL_LIST);
2273 return NT_STATUS_OK;
2276 /* This removes any fragments we may have had stashed away */
2277 dcesrv_call_set_list(call, DCESRV_LIST_NONE);
2279 switch (call->pkt.ptype) {
2280 case DCERPC_PKT_BIND:
2281 status = dcesrv_bind_nak(call,
2282 DCERPC_BIND_NAK_REASON_NOT_SPECIFIED);
2283 break;
2284 case DCERPC_PKT_AUTH3:
2285 status = dcesrv_auth3(call);
2286 break;
2287 case DCERPC_PKT_ALTER:
2288 status = dcesrv_alter(call);
2289 break;
2290 case DCERPC_PKT_REQUEST:
2291 status = dcesrv_request(call);
2292 break;
2293 case DCERPC_PKT_CO_CANCEL:
2294 case DCERPC_PKT_ORPHANED:
2296 * Window just ignores CO_CANCEL and ORPHANED,
2297 * so we do...
2299 status = NT_STATUS_OK;
2300 TALLOC_FREE(call);
2301 break;
2302 case DCERPC_PKT_BIND_ACK:
2303 case DCERPC_PKT_BIND_NAK:
2304 case DCERPC_PKT_ALTER_RESP:
2305 case DCERPC_PKT_RESPONSE:
2306 case DCERPC_PKT_FAULT:
2307 case DCERPC_PKT_SHUTDOWN:
2308 default:
2309 status = dcesrv_fault_disconnect(call, DCERPC_NCA_S_PROTO_ERROR);
2310 break;
2313 /* if we are going to be sending a reply then add
2314 it to the list of pending calls. We add it to the end to keep the call
2315 list in the order we will answer */
2316 if (!NT_STATUS_IS_OK(status)) {
2317 talloc_free(call);
2320 return status;
2323 _PUBLIC_ NTSTATUS dcesrv_init_context(TALLOC_CTX *mem_ctx,
2324 struct loadparm_context *lp_ctx,
2325 struct dcesrv_context_callbacks *cb,
2326 struct dcesrv_context **_dce_ctx)
2328 struct dcesrv_context *dce_ctx;
2330 dce_ctx = talloc_zero(mem_ctx, struct dcesrv_context);
2331 NT_STATUS_HAVE_NO_MEMORY(dce_ctx);
2333 if (uid_wrapper_enabled()) {
2334 setenv("UID_WRAPPER_MYUID", "1", 1);
2336 dce_ctx->initial_euid = geteuid();
2337 if (uid_wrapper_enabled()) {
2338 unsetenv("UID_WRAPPER_MYUID");
2341 dce_ctx->endpoint_list = NULL;
2342 dce_ctx->lp_ctx = lp_ctx;
2343 dce_ctx->assoc_groups_idr = idr_init(dce_ctx);
2344 NT_STATUS_HAVE_NO_MEMORY(dce_ctx->assoc_groups_idr);
2345 dce_ctx->broken_connections = NULL;
2346 if (cb != NULL) {
2347 dce_ctx->callbacks = *cb;
2350 *_dce_ctx = dce_ctx;
2351 return NT_STATUS_OK;
2354 _PUBLIC_ NTSTATUS dcesrv_reinit_context(struct dcesrv_context *dce_ctx)
2356 NTSTATUS status;
2358 status = dcesrv_shutdown_registered_ep_servers(dce_ctx);
2359 if (!NT_STATUS_IS_OK(status)) {
2360 return status;
2363 /* Clear endpoints */
2364 while (dce_ctx->endpoint_list != NULL) {
2365 struct dcesrv_endpoint *e = dce_ctx->endpoint_list;
2366 DLIST_REMOVE(dce_ctx->endpoint_list, e);
2367 TALLOC_FREE(e);
2370 /* Remove broken connections */
2371 dcesrv_cleanup_broken_connections(dce_ctx);
2373 /* Reinit assoc group idr */
2374 TALLOC_FREE(dce_ctx->assoc_groups_idr);
2375 dce_ctx->assoc_groups_idr = idr_init(dce_ctx);
2376 if (dce_ctx->assoc_groups_idr == NULL) {
2377 return NT_STATUS_NO_MEMORY;
2380 return NT_STATUS_OK;
2383 _PUBLIC_ NTSTATUS dcesrv_init_ep_servers(struct dcesrv_context *dce_ctx,
2384 const char **endpoint_servers)
2386 NTSTATUS status;
2387 int i;
2389 if (endpoint_servers == NULL) {
2390 DBG_ERR("No endpoint servers configured\n");
2391 return NT_STATUS_INTERNAL_ERROR;
2394 for (i=0;endpoint_servers[i];i++) {
2395 status = dcesrv_init_ep_server(dce_ctx, endpoint_servers[i]);
2396 if (!NT_STATUS_IS_OK(status)) {
2397 DBG_ERR("failed to init endpoint server = '%s': %s\n",
2398 endpoint_servers[i], nt_errstr(status));
2399 return status;
2403 return NT_STATUS_OK;
2406 /* the list of currently registered DCERPC endpoint servers.
2408 static struct ep_server {
2409 struct dcesrv_endpoint_server *ep_server;
2410 } *ep_servers = NULL;
2411 static int num_ep_servers = 0;
2413 _PUBLIC_ NTSTATUS dcesrv_init_registered_ep_servers(
2414 struct dcesrv_context *dce_ctx)
2416 NTSTATUS status;
2417 int i;
2419 for (i = 0; i < num_ep_servers; i++) {
2420 status = dcesrv_init_ep_server(dce_ctx,
2421 ep_servers[i].ep_server->name);
2422 if (!NT_STATUS_IS_OK(status)) {
2423 return status;
2427 return NT_STATUS_OK;
2430 _PUBLIC_ NTSTATUS dcesrv_init_ep_server(struct dcesrv_context *dce_ctx,
2431 const char *ep_server_name)
2433 struct dcesrv_endpoint_server *ep_server = NULL;
2434 NTSTATUS status;
2436 ep_server = discard_const_p(struct dcesrv_endpoint_server,
2437 dcesrv_ep_server_byname(ep_server_name));
2438 if (ep_server == NULL) {
2439 DBG_ERR("Failed to find endpoint server '%s'\n",
2440 ep_server_name);
2441 return NT_STATUS_INTERNAL_ERROR;
2444 if (ep_server->initialized) {
2445 return NT_STATUS_OK;
2448 status = ep_server->init_server(dce_ctx, ep_server);
2449 if (!NT_STATUS_IS_OK(status)) {
2450 DBG_ERR("Failed to init endpoint server '%s': %s\n",
2451 ep_server_name, nt_errstr(status));
2452 return status;
2455 ep_server->initialized = true;
2457 return NT_STATUS_OK;
2460 _PUBLIC_ NTSTATUS dcesrv_shutdown_registered_ep_servers(
2461 struct dcesrv_context *dce_ctx)
2463 NTSTATUS status;
2464 int i;
2466 for (i = 0; i < num_ep_servers; i++) {
2467 status = dcesrv_shutdown_ep_server(dce_ctx,
2468 ep_servers[i].ep_server->name);
2469 if (!NT_STATUS_IS_OK(status)) {
2470 return status;
2474 return NT_STATUS_OK;
2477 _PUBLIC_ NTSTATUS dcesrv_shutdown_ep_server(struct dcesrv_context *dce_ctx,
2478 const char *ep_server_name)
2480 struct dcesrv_endpoint_server *ep_server = NULL;
2481 NTSTATUS status;
2483 ep_server = discard_const_p(struct dcesrv_endpoint_server,
2484 dcesrv_ep_server_byname(ep_server_name));
2485 if (ep_server == NULL) {
2486 DBG_ERR("Failed to find endpoint server '%s'\n",
2487 ep_server_name);
2488 return NT_STATUS_INTERNAL_ERROR;
2491 if (!ep_server->initialized) {
2492 return NT_STATUS_OK;
2495 DBG_INFO("Shutting down DCE/RPC endpoint server '%s'\n",
2496 ep_server_name);
2498 status = ep_server->shutdown_server(dce_ctx, ep_server);
2499 if (!NT_STATUS_IS_OK(status)) {
2500 DBG_ERR("Failed to shutdown endpoint server '%s': %s\n",
2501 ep_server_name, nt_errstr(status));
2502 return status;
2505 ep_server->initialized = false;
2507 return NT_STATUS_OK;
2511 register a DCERPC endpoint server.
2513 The 'name' can be later used by other backends to find the operations
2514 structure for this backend.
2517 _PUBLIC_ NTSTATUS dcerpc_register_ep_server(const struct dcesrv_endpoint_server *ep_server)
2520 if (dcesrv_ep_server_byname(ep_server->name) != NULL) {
2521 /* its already registered! */
2522 DEBUG(0,("DCERPC endpoint server '%s' already registered\n",
2523 ep_server->name));
2524 return NT_STATUS_OBJECT_NAME_COLLISION;
2527 ep_servers = realloc_p(ep_servers, struct ep_server, num_ep_servers+1);
2528 if (!ep_servers) {
2529 smb_panic("out of memory in dcerpc_register");
2532 ep_servers[num_ep_servers].ep_server = smb_xmemdup(ep_server, sizeof(*ep_server));
2533 ep_servers[num_ep_servers].ep_server->name = smb_xstrdup(ep_server->name);
2535 num_ep_servers++;
2537 DEBUG(3,("DCERPC endpoint server '%s' registered\n",
2538 ep_server->name));
2540 return NT_STATUS_OK;
2544 return the operations structure for a named backend of the specified type
2546 _PUBLIC_ const struct dcesrv_endpoint_server *dcesrv_ep_server_byname(const char *name)
2548 int i;
2550 for (i=0;i<num_ep_servers;i++) {
2551 if (strcmp(ep_servers[i].ep_server->name, name) == 0) {
2552 return ep_servers[i].ep_server;
2556 return NULL;
2560 return the DCERPC module version, and the size of some critical types
2561 This can be used by endpoint server modules to either detect compilation errors, or provide
2562 multiple implementations for different smbd compilation options in one module
2564 const struct dcesrv_critical_sizes *dcerpc_module_version(void)
2566 static const struct dcesrv_critical_sizes critical_sizes = {
2567 DCERPC_MODULE_VERSION,
2568 sizeof(struct dcesrv_context),
2569 sizeof(struct dcesrv_endpoint),
2570 sizeof(struct dcesrv_endpoint_server),
2571 sizeof(struct dcesrv_interface),
2572 sizeof(struct dcesrv_if_list),
2573 sizeof(struct dcesrv_connection),
2574 sizeof(struct dcesrv_call_state),
2575 sizeof(struct dcesrv_auth),
2576 sizeof(struct dcesrv_handle)
2579 return &critical_sizes;
2582 _PUBLIC_ void dcesrv_terminate_connection(struct dcesrv_connection *dce_conn, const char *reason)
2584 struct dcesrv_context *dce_ctx = dce_conn->dce_ctx;
2585 struct dcesrv_auth *a = NULL;
2587 dce_conn->wait_send = NULL;
2588 dce_conn->wait_recv = NULL;
2589 dce_conn->wait_private = NULL;
2591 dce_conn->allow_bind = false;
2592 dce_conn->allow_alter = false;
2594 dce_conn->default_auth_state->auth_invalid = true;
2596 for (a = dce_conn->auth_states; a != NULL; a = a->next) {
2597 a->auth_invalid = true;
2600 if (dce_conn->pending_call_list == NULL) {
2601 char *full_reason = talloc_asprintf(dce_conn, "dcesrv: %s", reason);
2603 DLIST_REMOVE(dce_ctx->broken_connections, dce_conn);
2604 dce_conn->transport.terminate_connection(dce_conn,
2605 full_reason ? full_reason : reason);
2606 return;
2609 if (dce_conn->terminate != NULL) {
2610 return;
2613 DEBUG(3,("dcesrv: terminating connection due to '%s' deferred due to pending calls\n",
2614 reason));
2615 dce_conn->terminate = talloc_strdup(dce_conn, reason);
2616 if (dce_conn->terminate == NULL) {
2617 dce_conn->terminate = "dcesrv: deferred terminating connection - no memory";
2619 DLIST_ADD_END(dce_ctx->broken_connections, dce_conn);
2622 _PUBLIC_ void dcesrv_cleanup_broken_connections(struct dcesrv_context *dce_ctx)
2624 struct dcesrv_connection *cur, *next;
2626 next = dce_ctx->broken_connections;
2627 while (next != NULL) {
2628 cur = next;
2629 next = cur->next;
2631 if (cur->state_flags & DCESRV_CALL_STATE_FLAG_PROCESS_PENDING_CALL) {
2632 struct dcesrv_connection_context *context_cur, *context_next;
2634 context_next = cur->contexts;
2635 while (context_next != NULL) {
2636 context_cur = context_next;
2637 context_next = context_cur->next;
2639 dcesrv_connection_context_destructor(context_cur);
2643 dcesrv_terminate_connection(cur, cur->terminate);
2647 /* We need this include to be able to compile on some plateforms
2648 * (ie. freebsd 7.2) as it seems that <sys/uio.h> is not included
2649 * correctly.
2650 * It has to be that deep because otherwise we have a conflict on
2651 * const struct dcesrv_interface declaration.
2652 * This is mostly due to socket_wrapper defining #define bind swrap_bind
2653 * which conflict with the bind used before.
2655 #include "system/network.h"
2657 struct dcesrv_sock_reply_state {
2658 struct dcesrv_connection *dce_conn;
2659 struct dcesrv_call_state *call;
2660 struct iovec iov;
2663 static void dcesrv_sock_reply_done(struct tevent_req *subreq);
2664 static void dcesrv_call_terminate_step1(struct tevent_req *subreq);
2666 _PUBLIC_ void dcesrv_sock_report_output_data(struct dcesrv_connection *dce_conn)
2668 struct dcesrv_call_state *call;
2670 call = dce_conn->call_list;
2671 if (!call || !call->replies) {
2672 return;
2675 while (call->replies) {
2676 struct data_blob_list_item *rep = call->replies;
2677 struct dcesrv_sock_reply_state *substate;
2678 struct tevent_req *subreq;
2680 substate = talloc_zero(call, struct dcesrv_sock_reply_state);
2681 if (!substate) {
2682 dcesrv_terminate_connection(dce_conn, "no memory");
2683 return;
2686 substate->dce_conn = dce_conn;
2687 substate->call = NULL;
2689 DLIST_REMOVE(call->replies, rep);
2691 if (call->replies == NULL && call->terminate_reason == NULL) {
2692 substate->call = call;
2695 substate->iov.iov_base = (void *) rep->blob.data;
2696 substate->iov.iov_len = rep->blob.length;
2698 subreq = tstream_writev_queue_send(substate,
2699 dce_conn->event_ctx,
2700 dce_conn->stream,
2701 dce_conn->send_queue,
2702 &substate->iov, 1);
2703 if (!subreq) {
2704 dcesrv_terminate_connection(dce_conn, "no memory");
2705 return;
2707 tevent_req_set_callback(subreq, dcesrv_sock_reply_done,
2708 substate);
2711 if (call->terminate_reason != NULL) {
2712 struct tevent_req *subreq;
2714 subreq = tevent_queue_wait_send(call,
2715 dce_conn->event_ctx,
2716 dce_conn->send_queue);
2717 if (!subreq) {
2718 dcesrv_terminate_connection(dce_conn, __location__);
2719 return;
2721 tevent_req_set_callback(subreq, dcesrv_call_terminate_step1,
2722 call);
2725 DLIST_REMOVE(call->conn->call_list, call);
2726 call->list = DCESRV_LIST_NONE;
2729 static void dcesrv_sock_reply_done(struct tevent_req *subreq)
2731 struct dcesrv_sock_reply_state *substate = tevent_req_callback_data(subreq,
2732 struct dcesrv_sock_reply_state);
2733 int ret;
2734 int sys_errno;
2735 NTSTATUS status;
2736 struct dcesrv_call_state *call = substate->call;
2738 ret = tstream_writev_queue_recv(subreq, &sys_errno);
2739 TALLOC_FREE(subreq);
2740 if (ret == -1) {
2741 status = map_nt_error_from_unix_common(sys_errno);
2742 dcesrv_terminate_connection(substate->dce_conn, nt_errstr(status));
2743 return;
2746 talloc_free(substate);
2747 if (call) {
2748 talloc_free(call);
2752 static void dcesrv_call_terminate_step2(struct tevent_req *subreq);
2754 static void dcesrv_call_terminate_step1(struct tevent_req *subreq)
2756 struct dcesrv_call_state *call = tevent_req_callback_data(subreq,
2757 struct dcesrv_call_state);
2758 bool ok;
2759 struct timeval tv;
2761 /* make sure we stop send queue before removing subreq */
2762 tevent_queue_stop(call->conn->send_queue);
2764 ok = tevent_queue_wait_recv(subreq);
2765 TALLOC_FREE(subreq);
2766 if (!ok) {
2767 dcesrv_terminate_connection(call->conn, __location__);
2768 return;
2771 /* disconnect after 200 usecs */
2772 tv = timeval_current_ofs_usec(200);
2773 subreq = tevent_wakeup_send(call, call->conn->event_ctx, tv);
2774 if (subreq == NULL) {
2775 dcesrv_terminate_connection(call->conn, __location__);
2776 return;
2778 tevent_req_set_callback(subreq, dcesrv_call_terminate_step2,
2779 call);
2782 static void dcesrv_call_terminate_step2(struct tevent_req *subreq)
2784 struct dcesrv_call_state *call = tevent_req_callback_data(subreq,
2785 struct dcesrv_call_state);
2786 bool ok;
2788 ok = tevent_wakeup_recv(subreq);
2789 TALLOC_FREE(subreq);
2790 if (!ok) {
2791 dcesrv_terminate_connection(call->conn, __location__);
2792 return;
2795 dcesrv_terminate_connection(call->conn, call->terminate_reason);
2798 static void dcesrv_conn_wait_done(struct tevent_req *subreq);
2800 static void dcesrv_read_fragment_done(struct tevent_req *subreq)
2802 struct dcesrv_connection *dce_conn = tevent_req_callback_data(subreq,
2803 struct dcesrv_connection);
2804 struct dcesrv_context *dce_ctx = dce_conn->dce_ctx;
2805 struct ncacn_packet *pkt;
2806 DATA_BLOB buffer;
2807 NTSTATUS status;
2809 if (dce_conn->terminate) {
2811 * if the current connection is broken
2812 * we need to clean it up before any other connection
2814 dcesrv_terminate_connection(dce_conn, dce_conn->terminate);
2815 dcesrv_cleanup_broken_connections(dce_ctx);
2816 return;
2819 dcesrv_cleanup_broken_connections(dce_ctx);
2821 status = dcerpc_read_ncacn_packet_recv(subreq, dce_conn,
2822 &pkt, &buffer);
2823 TALLOC_FREE(subreq);
2824 if (!NT_STATUS_IS_OK(status)) {
2825 dcesrv_terminate_connection(dce_conn, nt_errstr(status));
2826 return;
2829 status = dcesrv_process_ncacn_packet(dce_conn, pkt, buffer);
2830 if (!NT_STATUS_IS_OK(status)) {
2831 dcesrv_terminate_connection(dce_conn, nt_errstr(status));
2832 return;
2836 * This is used to block the connection during
2837 * pending authentication.
2839 if (dce_conn->wait_send != NULL) {
2840 subreq = dce_conn->wait_send(dce_conn,
2841 dce_conn->event_ctx,
2842 dce_conn->wait_private);
2843 if (!subreq) {
2844 status = NT_STATUS_NO_MEMORY;
2845 dcesrv_terminate_connection(dce_conn, nt_errstr(status));
2846 return;
2848 tevent_req_set_callback(subreq, dcesrv_conn_wait_done, dce_conn);
2849 return;
2852 subreq = dcerpc_read_ncacn_packet_send(dce_conn,
2853 dce_conn->event_ctx,
2854 dce_conn->stream);
2855 if (!subreq) {
2856 status = NT_STATUS_NO_MEMORY;
2857 dcesrv_terminate_connection(dce_conn, nt_errstr(status));
2858 return;
2860 tevent_req_set_callback(subreq, dcesrv_read_fragment_done, dce_conn);
2863 static void dcesrv_conn_wait_done(struct tevent_req *subreq)
2865 struct dcesrv_connection *dce_conn = tevent_req_callback_data(subreq,
2866 struct dcesrv_connection);
2867 struct dcesrv_context *dce_ctx = dce_conn->dce_ctx;
2868 NTSTATUS status;
2870 if (dce_conn->terminate) {
2872 * if the current connection is broken
2873 * we need to clean it up before any other connection
2875 dcesrv_terminate_connection(dce_conn, dce_conn->terminate);
2876 dcesrv_cleanup_broken_connections(dce_ctx);
2877 return;
2880 dcesrv_cleanup_broken_connections(dce_ctx);
2882 status = dce_conn->wait_recv(subreq);
2883 dce_conn->wait_send = NULL;
2884 dce_conn->wait_recv = NULL;
2885 dce_conn->wait_private = NULL;
2886 TALLOC_FREE(subreq);
2887 if (!NT_STATUS_IS_OK(status)) {
2888 dcesrv_terminate_connection(dce_conn, nt_errstr(status));
2889 return;
2892 status = dcesrv_connection_loop_start(dce_conn);
2893 if (!NT_STATUS_IS_OK(status)) {
2894 dcesrv_terminate_connection(dce_conn, nt_errstr(status));
2895 return;
2900 * retrieve credentials from a dce_call
2902 _PUBLIC_ struct cli_credentials *dcesrv_call_credentials(struct dcesrv_call_state *dce_call)
2904 struct dcesrv_auth *auth = dce_call->auth_state;
2905 SMB_ASSERT(auth->auth_finished);
2906 return auth->session_info->credentials;
2910 * returns true if this is an authenticated call
2912 _PUBLIC_ bool dcesrv_call_authenticated(struct dcesrv_call_state *dce_call)
2914 struct dcesrv_auth *auth = dce_call->auth_state;
2915 enum security_user_level level;
2916 SMB_ASSERT(auth->auth_finished);
2917 level = security_session_user_level(auth->session_info, NULL);
2918 return level >= SECURITY_USER;
2922 * retrieve account_name for a dce_call
2924 _PUBLIC_ const char *dcesrv_call_account_name(struct dcesrv_call_state *dce_call)
2926 struct dcesrv_auth *auth = dce_call->auth_state;
2927 SMB_ASSERT(auth->auth_finished);
2928 return auth->session_info->info->account_name;
2932 * retrieve session_info from a dce_call
2934 _PUBLIC_ struct auth_session_info *dcesrv_call_session_info(struct dcesrv_call_state *dce_call)
2936 struct dcesrv_auth *auth = dce_call->auth_state;
2937 SMB_ASSERT(auth->auth_finished);
2938 return auth->session_info;
2942 * retrieve auth type/level from a dce_call
2944 _PUBLIC_ void dcesrv_call_auth_info(struct dcesrv_call_state *dce_call,
2945 enum dcerpc_AuthType *auth_type,
2946 enum dcerpc_AuthLevel *auth_level)
2948 struct dcesrv_auth *auth = dce_call->auth_state;
2950 SMB_ASSERT(auth->auth_finished);
2952 if (auth_type != NULL) {
2953 *auth_type = auth->auth_type;
2955 if (auth_level != NULL) {
2956 *auth_level = auth->auth_level;
2960 _PUBLIC_ NTSTATUS dcesrv_connection_loop_start(struct dcesrv_connection *conn)
2962 struct tevent_req *subreq;
2964 subreq = dcerpc_read_ncacn_packet_send(conn,
2965 conn->event_ctx,
2966 conn->stream);
2967 if (subreq == NULL) {
2968 return NT_STATUS_NO_MEMORY;
2970 tevent_req_set_callback(subreq, dcesrv_read_fragment_done, conn);
2972 return NT_STATUS_OK;
2975 _PUBLIC_ NTSTATUS dcesrv_call_dispatch_local(struct dcesrv_call_state *call)
2977 NTSTATUS status;
2978 struct ndr_pull *pull = NULL;
2979 struct ndr_push *push = NULL;
2980 struct data_blob_list_item *rep = NULL;
2982 pull = ndr_pull_init_blob(&call->pkt.u.request.stub_and_verifier,
2983 call);
2984 if (pull == NULL) {
2985 return NT_STATUS_NO_MEMORY;
2988 pull->flags |= LIBNDR_FLAG_REF_ALLOC;
2990 call->ndr_pull = pull;
2992 /* unravel the NDR for the packet */
2993 status = call->context->iface->ndr_pull(call, call, pull, &call->r);
2994 if (!NT_STATUS_IS_OK(status)) {
2995 DBG_ERR("DCE/RPC fault in call %s:%02X - %s\n",
2996 call->context->iface->name,
2997 call->pkt.u.request.opnum,
2998 dcerpc_errstr(call, call->fault_code));
2999 return dcerpc_fault_to_nt_status(call->fault_code);
3002 status = call->context->iface->local(call, call, call->r);
3003 if (!NT_STATUS_IS_OK(status)) {
3004 DBG_ERR("DCE/RPC fault in call %s:%02X - %s\n",
3005 call->context->iface->name,
3006 call->pkt.u.request.opnum,
3007 dcerpc_errstr(call, call->fault_code));
3008 return dcerpc_fault_to_nt_status(call->fault_code);
3011 push = ndr_push_init_ctx(call);
3012 if (push == NULL) {
3013 return NT_STATUS_NO_MEMORY;
3016 push->ptr_count = call->ndr_pull->ptr_count;
3018 status = call->context->iface->ndr_push(call, call, push, call->r);
3019 if (!NT_STATUS_IS_OK(status)) {
3020 DBG_ERR("DCE/RPC fault in call %s:%02X - %s\n",
3021 call->context->iface->name,
3022 call->pkt.u.request.opnum,
3023 dcerpc_errstr(call, call->fault_code));
3024 return dcerpc_fault_to_nt_status(call->fault_code);
3027 rep = talloc_zero(call, struct data_blob_list_item);
3028 if (rep == NULL) {
3029 return NT_STATUS_NO_MEMORY;
3032 rep->blob = ndr_push_blob(push);
3033 DLIST_ADD_END(call->replies, rep);
3035 return NT_STATUS_OK;