librpc:core: Make dcesrv_find_endpoint public
[Samba.git] / librpc / rpc / dcesrv_core.c
blob902e82887f7308ac75d2fe75050445a19816f915
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"
36 #undef DBGC_CLASS
37 #define DBGC_CLASS DBGC_RPC_SRV
39 static NTSTATUS dcesrv_negotiate_contexts(struct dcesrv_call_state *call,
40 const struct dcerpc_bind *b,
41 struct dcerpc_ack_ctx *ack_ctx_list);
44 see if two endpoints match
46 static bool endpoints_match(const struct dcerpc_binding *ep1,
47 const struct dcerpc_binding *ep2)
49 enum dcerpc_transport_t t1;
50 enum dcerpc_transport_t t2;
51 const char *e1;
52 const char *e2;
54 t1 = dcerpc_binding_get_transport(ep1);
55 t2 = dcerpc_binding_get_transport(ep2);
57 e1 = dcerpc_binding_get_string_option(ep1, "endpoint");
58 e2 = dcerpc_binding_get_string_option(ep2, "endpoint");
60 if (t1 != t2) {
61 return false;
64 if (!e1 || !e2) {
65 return e1 == e2;
68 if (strcasecmp(e1, e2) != 0) {
69 return false;
72 return true;
76 find an endpoint in the dcesrv_context
78 _PUBLIC_ NTSTATUS dcesrv_find_endpoint(struct dcesrv_context *dce_ctx,
79 const struct dcerpc_binding *ep_description,
80 struct dcesrv_endpoint **_out)
82 struct dcesrv_endpoint *ep = NULL;
83 for (ep=dce_ctx->endpoint_list; ep; ep=ep->next) {
84 if (endpoints_match(ep->ep_description, ep_description)) {
85 *_out = ep;
86 return NT_STATUS_OK;
89 return NT_STATUS_NOT_FOUND;
93 find a registered context_id from a bind or alter_context
95 static struct dcesrv_connection_context *dcesrv_find_context(struct dcesrv_connection *conn,
96 uint16_t context_id)
98 struct dcesrv_connection_context *c;
99 for (c=conn->contexts;c;c=c->next) {
100 if (c->context_id == context_id) return c;
102 return NULL;
106 see if a uuid and if_version match to an interface
108 static bool interface_match(const struct dcesrv_interface *if1,
109 const struct dcesrv_interface *if2)
111 return (if1->syntax_id.if_version == if2->syntax_id.if_version &&
112 GUID_equal(&if1->syntax_id.uuid, &if2->syntax_id.uuid));
116 find the interface operations on any endpoint with this binding
118 static const struct dcesrv_interface *find_interface_by_binding(struct dcesrv_context *dce_ctx,
119 struct dcerpc_binding *binding,
120 const struct dcesrv_interface *iface)
122 struct dcesrv_endpoint *ep;
123 for (ep=dce_ctx->endpoint_list; ep; ep=ep->next) {
124 if (endpoints_match(ep->ep_description, binding)) {
125 struct dcesrv_if_list *ifl;
126 for (ifl=ep->interface_list; ifl; ifl=ifl->next) {
127 if (interface_match(ifl->iface, iface)) {
128 return ifl->iface;
133 return NULL;
137 see if a uuid and if_version match to an interface
139 static bool interface_match_by_uuid(const struct dcesrv_interface *iface,
140 const struct GUID *uuid, uint32_t if_version)
142 return (iface->syntax_id.if_version == if_version &&
143 GUID_equal(&iface->syntax_id.uuid, uuid));
147 find the interface operations on an endpoint by uuid
149 const struct dcesrv_interface *find_interface_by_uuid(const struct dcesrv_endpoint *endpoint,
150 const struct GUID *uuid, uint32_t if_version)
152 struct dcesrv_if_list *ifl;
153 for (ifl=endpoint->interface_list; ifl; ifl=ifl->next) {
154 if (interface_match_by_uuid(ifl->iface, uuid, if_version)) {
155 return ifl->iface;
158 return NULL;
162 find the earlier parts of a fragmented call awaiting reassembily
164 static struct dcesrv_call_state *dcesrv_find_fragmented_call(struct dcesrv_connection *dce_conn, uint32_t call_id)
166 struct dcesrv_call_state *c;
167 for (c=dce_conn->incoming_fragmented_call_list;c;c=c->next) {
168 if (c->pkt.call_id == call_id) {
169 return c;
172 return NULL;
176 register an interface on an endpoint
178 An endpoint is one unix domain socket (for ncalrpc), one TCP port
179 (for ncacn_ip_tcp) or one (forwarded) named pipe (for ncacn_np).
181 Each endpoint can have many interfaces such as netlogon, lsa or
182 samr. Some have essentially the full set.
184 This is driven from the set of interfaces listed in each IDL file
185 via the PIDL generated *__op_init_server() functions.
187 _PUBLIC_ NTSTATUS dcesrv_interface_register(struct dcesrv_context *dce_ctx,
188 const char *ep_name,
189 const char *ncacn_np_secondary_endpoint,
190 const struct dcesrv_interface *iface,
191 const struct security_descriptor *sd)
193 struct dcesrv_endpoint *ep;
194 struct dcesrv_if_list *ifl;
195 struct dcerpc_binding *binding;
196 struct dcerpc_binding *binding2 = NULL;
197 bool add_ep = false;
198 NTSTATUS status;
199 enum dcerpc_transport_t transport;
200 char *ep_string = NULL;
201 bool use_single_process = true;
202 const char *ep_process_string;
205 * If we are not using handles, there is no need for force
206 * this service into using a single process.
208 * However, due to the way we listen for RPC packets, we can
209 * only do this if we have a single service per pipe or TCP
210 * port, so we still force a single combined process for
211 * ncalrpc.
213 if (iface->flags & DCESRV_INTERFACE_FLAGS_HANDLES_NOT_USED) {
214 use_single_process = false;
217 status = dcerpc_parse_binding(dce_ctx, ep_name, &binding);
219 if (NT_STATUS_IS_ERR(status)) {
220 DEBUG(0, ("Trouble parsing binding string '%s'\n", ep_name));
221 return status;
224 transport = dcerpc_binding_get_transport(binding);
225 if (transport == NCACN_IP_TCP) {
226 int port;
227 char port_str[6];
230 * First check if there is already a port specified, eg
231 * for epmapper on ncacn_ip_tcp:[135]
233 const char *endpoint
234 = dcerpc_binding_get_string_option(binding,
235 "endpoint");
236 if (endpoint == NULL) {
237 port = lpcfg_parm_int(dce_ctx->lp_ctx, NULL,
238 "rpc server port", iface->name, 0);
241 * For RPC services that are not set to use a single
242 * process, we do not default to using the 'rpc server
243 * port' because that would cause a double-bind on
244 * that port.
246 if (port == 0 && !use_single_process) {
247 port = lpcfg_rpc_server_port(dce_ctx->lp_ctx);
249 if (port != 0) {
250 snprintf(port_str, sizeof(port_str), "%u", port);
251 status = dcerpc_binding_set_string_option(binding,
252 "endpoint",
253 port_str);
254 if (!NT_STATUS_IS_OK(status)) {
255 return status;
261 if (transport == NCACN_NP && ncacn_np_secondary_endpoint != NULL) {
262 enum dcerpc_transport_t transport2;
264 status = dcerpc_parse_binding(dce_ctx,
265 ncacn_np_secondary_endpoint,
266 &binding2);
267 if (!NT_STATUS_IS_OK(status)) {
268 DEBUG(0, ("Trouble parsing 2nd binding string '%s'\n",
269 ncacn_np_secondary_endpoint));
270 return status;
273 transport2 = dcerpc_binding_get_transport(binding2);
274 SMB_ASSERT(transport2 == transport);
277 /* see if the interface is already registered on the endpoint */
278 if (find_interface_by_binding(dce_ctx, binding, iface)!=NULL) {
279 DEBUG(0,("dcesrv_interface_register: interface '%s' already registered on endpoint '%s'\n",
280 iface->name, ep_name));
281 return NT_STATUS_OBJECT_NAME_COLLISION;
284 /* check if this endpoint exists
286 status = dcesrv_find_endpoint(dce_ctx, binding, &ep);
287 if (NT_STATUS_IS_OK(status)) {
289 * We want a new port on ncacn_ip_tcp for NETLOGON, so
290 * it can be multi-process. Other processes can also
291 * listen on distinct ports, if they have one forced
292 * in the code above with eg 'rpc server port:drsuapi = 1027'
294 * If we have mulitiple endpoints on port 0, they each
295 * get an epemeral port (currently by walking up from
296 * 1024).
298 * Because one endpoint can only have one process
299 * model, we add a new IP_TCP endpoint for each model.
301 * This works in conjunction with the forced overwrite
302 * of ep->use_single_process below.
304 if (ep->use_single_process != use_single_process
305 && transport == NCACN_IP_TCP) {
306 add_ep = true;
310 if (NT_STATUS_EQUAL(status, NT_STATUS_NOT_FOUND) || add_ep) {
311 ep = talloc_zero(dce_ctx, struct dcesrv_endpoint);
312 if (!ep) {
313 return NT_STATUS_NO_MEMORY;
315 ZERO_STRUCTP(ep);
316 ep->ep_description = talloc_move(ep, &binding);
317 ep->ep_2nd_description = talloc_move(ep, &binding2);
318 add_ep = true;
320 /* add mgmt interface */
321 ifl = talloc_zero(ep, struct dcesrv_if_list);
322 if (!ifl) {
323 return NT_STATUS_NO_MEMORY;
326 ifl->iface = talloc_memdup(ifl,
327 dcesrv_get_mgmt_interface(),
328 sizeof(struct dcesrv_interface));
329 if (ifl->iface == NULL) {
330 talloc_free(ep);
331 return NT_STATUS_NO_MEMORY;
334 DLIST_ADD(ep->interface_list, ifl);
335 } else if (!NT_STATUS_IS_OK(status)) {
336 DBG_NOTICE("Failed to find endpoint: %s\n", nt_errstr(status));
337 return status;
341 * By default don't force into a single process, but if any
342 * interface on this endpoint on this service uses handles
343 * (most do), then we must force into single process mode
345 * By overwriting this each time a new interface is added to
346 * this endpoint, we end up with the most restrictive setting.
348 if (use_single_process) {
349 ep->use_single_process = true;
352 /* talloc a new interface list element */
353 ifl = talloc_zero(ep, struct dcesrv_if_list);
354 if (!ifl) {
355 return NT_STATUS_NO_MEMORY;
358 /* copy the given interface struct to the one on the endpoints interface list */
359 ifl->iface = talloc_memdup(ifl,
360 iface,
361 sizeof(struct dcesrv_interface));
362 if (ifl->iface == NULL) {
363 talloc_free(ep);
364 return NT_STATUS_NO_MEMORY;
367 /* if we have a security descriptor given,
368 * we should see if we can set it up on the endpoint
370 if (sd != NULL) {
371 /* if there's currently no security descriptor given on the endpoint
372 * we try to set it
374 if (ep->sd == NULL) {
375 ep->sd = security_descriptor_copy(ep, sd);
378 /* if now there's no security descriptor given on the endpoint
379 * something goes wrong, either we failed to copy the security descriptor
380 * or there was already one on the endpoint
382 if (ep->sd != NULL) {
383 DEBUG(0,("dcesrv_interface_register: interface '%s' failed to setup a security descriptor\n"
384 " on endpoint '%s'\n",
385 iface->name, ep_name));
386 if (add_ep) free(ep);
387 free(ifl);
388 return NT_STATUS_OBJECT_NAME_COLLISION;
392 /* finally add the interface on the endpoint */
393 DLIST_ADD(ep->interface_list, ifl);
395 /* if it's a new endpoint add it to the dcesrv_context */
396 if (add_ep) {
397 DLIST_ADD(dce_ctx->endpoint_list, ep);
400 /* Re-get the string as we may have set a port */
401 ep_string = dcerpc_binding_string(dce_ctx, ep->ep_description);
403 if (use_single_process) {
404 ep_process_string = "single process required";
405 } else {
406 ep_process_string = "multi process compatible";
409 DBG_INFO("Interface '%s' registered on endpoint '%s' (%s)\n",
410 iface->name, ep_string, ep_process_string);
411 TALLOC_FREE(ep_string);
413 return NT_STATUS_OK;
416 static NTSTATUS dcesrv_session_info_session_key(struct dcesrv_auth *auth,
417 DATA_BLOB *session_key)
419 if (auth->session_info == NULL) {
420 return NT_STATUS_NO_USER_SESSION_KEY;
423 if (auth->session_info->session_key.length == 0) {
424 return NT_STATUS_NO_USER_SESSION_KEY;
427 *session_key = auth->session_info->session_key;
428 return NT_STATUS_OK;
431 static NTSTATUS dcesrv_remote_session_key(struct dcesrv_auth *auth,
432 DATA_BLOB *session_key)
434 if (auth->auth_type != DCERPC_AUTH_TYPE_NONE) {
435 return NT_STATUS_NO_USER_SESSION_KEY;
438 return dcesrv_session_info_session_key(auth, session_key);
441 static NTSTATUS dcesrv_local_fixed_session_key(struct dcesrv_auth *auth,
442 DATA_BLOB *session_key)
444 return dcerpc_generic_session_key(session_key);
448 * Fetch the authentication session key if available.
450 * This is the key generated by a gensec authentication.
453 _PUBLIC_ NTSTATUS dcesrv_auth_session_key(struct dcesrv_call_state *call,
454 DATA_BLOB *session_key)
456 struct dcesrv_auth *auth = call->auth_state;
457 SMB_ASSERT(auth->auth_finished);
458 return dcesrv_session_info_session_key(auth, session_key);
462 * Fetch the transport session key if available.
463 * Typically this is the SMB session key
464 * or a fixed key for local transports.
466 * The key is always truncated to 16 bytes.
468 _PUBLIC_ NTSTATUS dcesrv_transport_session_key(struct dcesrv_call_state *call,
469 DATA_BLOB *session_key)
471 struct dcesrv_auth *auth = call->auth_state;
472 NTSTATUS status;
474 SMB_ASSERT(auth->auth_finished);
476 if (auth->session_key_fn == NULL) {
477 return NT_STATUS_NO_USER_SESSION_KEY;
480 status = auth->session_key_fn(auth, session_key);
481 if (!NT_STATUS_IS_OK(status)) {
482 return status;
485 session_key->length = MIN(session_key->length, 16);
487 return NT_STATUS_OK;
490 static struct dcesrv_auth *dcesrv_auth_create(struct dcesrv_connection *conn)
492 const struct dcesrv_endpoint *ep = conn->endpoint;
493 enum dcerpc_transport_t transport =
494 dcerpc_binding_get_transport(ep->ep_description);
495 struct dcesrv_auth *auth = NULL;
497 auth = talloc_zero(conn, struct dcesrv_auth);
498 if (auth == NULL) {
499 return NULL;
502 switch (transport) {
503 case NCACN_NP:
504 auth->session_key_fn = dcesrv_remote_session_key;
505 break;
506 case NCALRPC:
507 case NCACN_UNIX_STREAM:
508 auth->session_key_fn = dcesrv_local_fixed_session_key;
509 break;
510 default:
512 * All other's get a NULL pointer, which
513 * results in NT_STATUS_NO_USER_SESSION_KEY
515 break;
518 return auth;
522 connect to a dcerpc endpoint
524 _PUBLIC_ NTSTATUS dcesrv_endpoint_connect(struct dcesrv_context *dce_ctx,
525 TALLOC_CTX *mem_ctx,
526 const struct dcesrv_endpoint *ep,
527 struct auth_session_info *session_info,
528 struct tevent_context *event_ctx,
529 uint32_t state_flags,
530 struct dcesrv_connection **_p)
532 struct dcesrv_auth *auth = NULL;
533 struct dcesrv_connection *p;
535 if (!session_info) {
536 return NT_STATUS_ACCESS_DENIED;
539 p = talloc_zero(mem_ctx, struct dcesrv_connection);
540 NT_STATUS_HAVE_NO_MEMORY(p);
542 p->dce_ctx = dce_ctx;
543 p->endpoint = ep;
544 p->packet_log_dir = lpcfg_lock_directory(dce_ctx->lp_ctx);
545 p->event_ctx = event_ctx;
546 p->state_flags = state_flags;
547 p->allow_bind = true;
548 p->max_recv_frag = 5840;
549 p->max_xmit_frag = 5840;
550 p->max_total_request_size = DCERPC_NCACN_REQUEST_DEFAULT_MAX_SIZE;
552 p->support_hdr_signing = lpcfg_parm_bool(dce_ctx->lp_ctx,
553 NULL,
554 "dcesrv",
555 "header signing",
556 true);
557 p->max_auth_states = lpcfg_parm_ulong(dce_ctx->lp_ctx,
558 NULL,
559 "dcesrv",
560 "max auth states",
561 2049);
563 auth = dcesrv_auth_create(p);
564 if (auth == NULL) {
565 talloc_free(p);
566 return NT_STATUS_NO_MEMORY;
569 auth->session_info = talloc_reference(auth, session_info);
570 if (auth->session_info == NULL) {
571 talloc_free(p);
572 return NT_STATUS_NO_MEMORY;
575 p->default_auth_state = auth;
578 * For now we only support NDR32.
580 p->preferred_transfer = &ndr_transfer_syntax_ndr;
582 *_p = p;
583 return NT_STATUS_OK;
587 move a call from an existing linked list to the specified list. This
588 prevents bugs where we forget to remove the call from a previous
589 list when moving it.
591 static void dcesrv_call_set_list(struct dcesrv_call_state *call,
592 enum dcesrv_call_list list)
594 switch (call->list) {
595 case DCESRV_LIST_NONE:
596 break;
597 case DCESRV_LIST_CALL_LIST:
598 DLIST_REMOVE(call->conn->call_list, call);
599 break;
600 case DCESRV_LIST_FRAGMENTED_CALL_LIST:
601 DLIST_REMOVE(call->conn->incoming_fragmented_call_list, call);
602 break;
603 case DCESRV_LIST_PENDING_CALL_LIST:
604 DLIST_REMOVE(call->conn->pending_call_list, call);
605 break;
607 call->list = list;
608 switch (list) {
609 case DCESRV_LIST_NONE:
610 break;
611 case DCESRV_LIST_CALL_LIST:
612 DLIST_ADD_END(call->conn->call_list, call);
613 break;
614 case DCESRV_LIST_FRAGMENTED_CALL_LIST:
615 DLIST_ADD_END(call->conn->incoming_fragmented_call_list, call);
616 break;
617 case DCESRV_LIST_PENDING_CALL_LIST:
618 DLIST_ADD_END(call->conn->pending_call_list, call);
619 break;
623 static void dcesrv_call_disconnect_after(struct dcesrv_call_state *call,
624 const char *reason)
626 struct dcesrv_auth *a = NULL;
628 if (call->conn->terminate != NULL) {
629 return;
632 call->conn->allow_bind = false;
633 call->conn->allow_alter = false;
635 call->conn->default_auth_state->auth_invalid = true;
637 for (a = call->conn->auth_states; a != NULL; a = a->next) {
638 a->auth_invalid = true;
641 call->terminate_reason = talloc_strdup(call, reason);
642 if (call->terminate_reason == NULL) {
643 call->terminate_reason = __location__;
648 return a dcerpc bind_nak
650 static NTSTATUS dcesrv_bind_nak(struct dcesrv_call_state *call, uint32_t reason)
652 struct ncacn_packet pkt;
653 struct dcerpc_bind_nak_version version;
654 struct data_blob_list_item *rep;
655 NTSTATUS status;
656 static const uint8_t _pad[3] = { 0, };
659 * We add the call to the pending_call_list
660 * in order to defer the termination.
662 dcesrv_call_disconnect_after(call, "dcesrv_bind_nak");
664 /* setup a bind_nak */
665 dcesrv_init_hdr(&pkt, lpcfg_rpc_big_endian(call->conn->dce_ctx->lp_ctx));
666 pkt.auth_length = 0;
667 pkt.call_id = call->pkt.call_id;
668 pkt.ptype = DCERPC_PKT_BIND_NAK;
669 pkt.pfc_flags = DCERPC_PFC_FLAG_FIRST | DCERPC_PFC_FLAG_LAST;
670 pkt.u.bind_nak.reject_reason = reason;
671 version.rpc_vers = 5;
672 version.rpc_vers_minor = 0;
673 pkt.u.bind_nak.num_versions = 1;
674 pkt.u.bind_nak.versions = &version;
675 pkt.u.bind_nak._pad = data_blob_const(_pad, sizeof(_pad));
677 rep = talloc_zero(call, struct data_blob_list_item);
678 if (!rep) {
679 return NT_STATUS_NO_MEMORY;
682 status = dcerpc_ncacn_push_auth(&rep->blob, call, &pkt, NULL);
683 if (!NT_STATUS_IS_OK(status)) {
684 return status;
687 dcerpc_set_frag_length(&rep->blob, rep->blob.length);
689 DLIST_ADD_END(call->replies, rep);
690 dcesrv_call_set_list(call, DCESRV_LIST_CALL_LIST);
692 if (call->conn->call_list && call->conn->call_list->replies) {
693 if (call->conn->transport.report_output_data) {
694 call->conn->transport.report_output_data(call->conn);
698 return NT_STATUS_OK;
701 static NTSTATUS dcesrv_fault_disconnect(struct dcesrv_call_state *call,
702 uint32_t fault_code)
705 * We add the call to the pending_call_list
706 * in order to defer the termination.
708 dcesrv_call_disconnect_after(call, "dcesrv_fault_disconnect");
710 return dcesrv_fault_with_flags(call, fault_code,
711 DCERPC_PFC_FLAG_DID_NOT_EXECUTE);
714 static int dcesrv_connection_context_destructor(struct dcesrv_connection_context *c)
716 DLIST_REMOVE(c->conn->contexts, c);
718 if (c->iface && c->iface->unbind) {
719 c->iface->unbind(c, c->iface);
720 c->iface = NULL;
723 return 0;
726 static void dcesrv_prepare_context_auth(struct dcesrv_call_state *dce_call)
728 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
729 const struct dcesrv_endpoint *endpoint = dce_call->conn->endpoint;
730 enum dcerpc_transport_t transport =
731 dcerpc_binding_get_transport(endpoint->ep_description);
732 struct dcesrv_connection_context *context = dce_call->context;
733 const struct dcesrv_interface *iface = context->iface;
735 context->min_auth_level = DCERPC_AUTH_LEVEL_NONE;
737 if (transport == NCALRPC) {
738 context->allow_connect = true;
739 return;
743 * allow overwrite per interface
744 * allow dcerpc auth level connect:<interface>
746 context->allow_connect = lpcfg_allow_dcerpc_auth_level_connect(lp_ctx);
747 context->allow_connect = lpcfg_parm_bool(lp_ctx, NULL,
748 "allow dcerpc auth level connect",
749 iface->name,
750 context->allow_connect);
753 NTSTATUS dcesrv_interface_bind_require_integrity(struct dcesrv_connection_context *context,
754 const struct dcesrv_interface *iface)
757 * For connection oriented DCERPC DCERPC_AUTH_LEVEL_PACKET (4)
758 * has the same behavior as DCERPC_AUTH_LEVEL_INTEGRITY (5).
760 context->min_auth_level = DCERPC_AUTH_LEVEL_PACKET;
761 return NT_STATUS_OK;
764 NTSTATUS dcesrv_interface_bind_require_privacy(struct dcesrv_connection_context *context,
765 const struct dcesrv_interface *iface)
767 context->min_auth_level = DCERPC_AUTH_LEVEL_PRIVACY;
768 return NT_STATUS_OK;
771 _PUBLIC_ NTSTATUS dcesrv_interface_bind_reject_connect(struct dcesrv_connection_context *context,
772 const struct dcesrv_interface *iface)
774 struct loadparm_context *lp_ctx = context->conn->dce_ctx->lp_ctx;
775 const struct dcesrv_endpoint *endpoint = context->conn->endpoint;
776 enum dcerpc_transport_t transport =
777 dcerpc_binding_get_transport(endpoint->ep_description);
779 if (transport == NCALRPC) {
780 context->allow_connect = true;
781 return NT_STATUS_OK;
785 * allow overwrite per interface
786 * allow dcerpc auth level connect:<interface>
788 context->allow_connect = false;
789 context->allow_connect = lpcfg_parm_bool(lp_ctx, NULL,
790 "allow dcerpc auth level connect",
791 iface->name,
792 context->allow_connect);
793 return NT_STATUS_OK;
796 _PUBLIC_ NTSTATUS dcesrv_interface_bind_allow_connect(struct dcesrv_connection_context *context,
797 const struct dcesrv_interface *iface)
799 struct loadparm_context *lp_ctx = context->conn->dce_ctx->lp_ctx;
800 const struct dcesrv_endpoint *endpoint = context->conn->endpoint;
801 enum dcerpc_transport_t transport =
802 dcerpc_binding_get_transport(endpoint->ep_description);
804 if (transport == NCALRPC) {
805 context->allow_connect = true;
806 return NT_STATUS_OK;
810 * allow overwrite per interface
811 * allow dcerpc auth level connect:<interface>
813 context->allow_connect = true;
814 context->allow_connect = lpcfg_parm_bool(lp_ctx, NULL,
815 "allow dcerpc auth level connect",
816 iface->name,
817 context->allow_connect);
818 return NT_STATUS_OK;
821 struct dcesrv_conn_auth_wait_context {
822 struct tevent_req *req;
823 bool done;
824 NTSTATUS status;
827 struct dcesrv_conn_auth_wait_state {
828 uint8_t dummy;
831 static struct tevent_req *dcesrv_conn_auth_wait_send(TALLOC_CTX *mem_ctx,
832 struct tevent_context *ev,
833 void *private_data)
835 struct dcesrv_conn_auth_wait_context *auth_wait =
836 talloc_get_type_abort(private_data,
837 struct dcesrv_conn_auth_wait_context);
838 struct tevent_req *req = NULL;
839 struct dcesrv_conn_auth_wait_state *state = NULL;
841 req = tevent_req_create(mem_ctx, &state,
842 struct dcesrv_conn_auth_wait_state);
843 if (req == NULL) {
844 return NULL;
846 auth_wait->req = req;
848 tevent_req_defer_callback(req, ev);
850 if (!auth_wait->done) {
851 return req;
854 if (tevent_req_nterror(req, auth_wait->status)) {
855 return tevent_req_post(req, ev);
858 tevent_req_done(req);
859 return tevent_req_post(req, ev);
862 static NTSTATUS dcesrv_conn_auth_wait_recv(struct tevent_req *req)
864 return tevent_req_simple_recv_ntstatus(req);
867 static NTSTATUS dcesrv_conn_auth_wait_setup(struct dcesrv_connection *conn)
869 struct dcesrv_conn_auth_wait_context *auth_wait = NULL;
871 if (conn->wait_send != NULL) {
872 return NT_STATUS_INTERNAL_ERROR;
875 auth_wait = talloc_zero(conn, struct dcesrv_conn_auth_wait_context);
876 if (auth_wait == NULL) {
877 return NT_STATUS_NO_MEMORY;
880 conn->wait_private = auth_wait;
881 conn->wait_send = dcesrv_conn_auth_wait_send;
882 conn->wait_recv = dcesrv_conn_auth_wait_recv;
883 return NT_STATUS_OK;
886 static void dcesrv_conn_auth_wait_finished(struct dcesrv_connection *conn,
887 NTSTATUS status)
889 struct dcesrv_conn_auth_wait_context *auth_wait =
890 talloc_get_type_abort(conn->wait_private,
891 struct dcesrv_conn_auth_wait_context);
893 auth_wait->done = true;
894 auth_wait->status = status;
896 if (auth_wait->req == NULL) {
897 return;
900 if (tevent_req_nterror(auth_wait->req, status)) {
901 return;
904 tevent_req_done(auth_wait->req);
907 static NTSTATUS dcesrv_auth_reply(struct dcesrv_call_state *call);
909 static void dcesrv_bind_done(struct tevent_req *subreq);
912 handle a bind request
914 static NTSTATUS dcesrv_bind(struct dcesrv_call_state *call)
916 struct dcesrv_connection *conn = call->conn;
917 struct ncacn_packet *pkt = &call->ack_pkt;
918 NTSTATUS status;
919 uint32_t extra_flags = 0;
920 uint16_t max_req = 0;
921 uint16_t max_rep = 0;
922 struct dcerpc_binding *ep_2nd_description = NULL;
923 const char *endpoint = NULL;
924 struct dcesrv_auth *auth = call->auth_state;
925 struct dcerpc_ack_ctx *ack_ctx_list = NULL;
926 struct dcerpc_ack_ctx *ack_features = NULL;
927 struct tevent_req *subreq = NULL;
928 size_t i;
930 status = dcerpc_verify_ncacn_packet_header(&call->pkt,
931 DCERPC_PKT_BIND,
932 call->pkt.u.bind.auth_info.length,
933 0, /* required flags */
934 DCERPC_PFC_FLAG_FIRST |
935 DCERPC_PFC_FLAG_LAST |
936 DCERPC_PFC_FLAG_SUPPORT_HEADER_SIGN |
937 0x08 | /* this is not defined, but should be ignored */
938 DCERPC_PFC_FLAG_CONC_MPX |
939 DCERPC_PFC_FLAG_DID_NOT_EXECUTE |
940 DCERPC_PFC_FLAG_MAYBE |
941 DCERPC_PFC_FLAG_OBJECT_UUID);
942 if (!NT_STATUS_IS_OK(status)) {
943 return dcesrv_bind_nak(call,
944 DCERPC_BIND_NAK_REASON_PROTOCOL_VERSION_NOT_SUPPORTED);
947 /* max_recv_frag and max_xmit_frag result always in the same value! */
948 max_req = MIN(call->pkt.u.bind.max_xmit_frag,
949 call->pkt.u.bind.max_recv_frag);
951 * The values are between 2048 and 5840 tested against Windows 2012R2
952 * via ncacn_ip_tcp on port 135.
954 max_req = MAX(2048, max_req);
955 max_rep = MIN(max_req, call->conn->max_recv_frag);
956 /* They are truncated to an 8 byte boundary. */
957 max_rep &= 0xFFF8;
959 /* max_recv_frag and max_xmit_frag result always in the same value! */
960 call->conn->max_recv_frag = max_rep;
961 call->conn->max_xmit_frag = max_rep;
963 status = call->conn->dce_ctx->callbacks.assoc_group.find(call);
964 if (!NT_STATUS_IS_OK(status)) {
965 DBG_NOTICE("Failed to find assoc_group 0x%08x: %s\n",
966 call->pkt.u.bind.assoc_group_id, nt_errstr(status));
967 return dcesrv_bind_nak(call, 0);
970 if (call->pkt.u.bind.num_contexts < 1) {
971 return dcesrv_bind_nak(call, 0);
974 ack_ctx_list = talloc_zero_array(call, struct dcerpc_ack_ctx,
975 call->pkt.u.bind.num_contexts);
976 if (ack_ctx_list == NULL) {
977 return dcesrv_bind_nak(call, 0);
981 * Set some sane defaults (required by dcesrv_negotiate_contexts()/
982 * dcesrv_check_or_create_context()) and do some protocol validation
983 * and set sane defaults.
985 for (i = 0; i < call->pkt.u.bind.num_contexts; i++) {
986 const struct dcerpc_ctx_list *c = &call->pkt.u.bind.ctx_list[i];
987 struct dcerpc_ack_ctx *a = &ack_ctx_list[i];
988 bool is_feature = false;
989 uint64_t features = 0;
991 if (c->num_transfer_syntaxes == 0) {
992 return dcesrv_bind_nak(call, 0);
995 a->result = DCERPC_BIND_ACK_RESULT_PROVIDER_REJECTION;
996 a->reason.value = DCERPC_BIND_ACK_REASON_ABSTRACT_SYNTAX_NOT_SUPPORTED;
999 * It's only treated as bind time feature request, if the first
1000 * transfer_syntax matches, all others are ignored.
1002 is_feature = dcerpc_extract_bind_time_features(c->transfer_syntaxes[0],
1003 &features);
1004 if (!is_feature) {
1005 continue;
1008 if (ack_features != NULL) {
1010 * Only one bind time feature context is allowed.
1012 return dcesrv_bind_nak(call, 0);
1014 ack_features = a;
1016 a->result = DCERPC_BIND_ACK_RESULT_NEGOTIATE_ACK;
1017 a->reason.negotiate = 0;
1018 if (features & DCERPC_BIND_TIME_SECURITY_CONTEXT_MULTIPLEXING) {
1019 if (call->conn->max_auth_states != 0) {
1020 a->reason.negotiate |=
1021 DCERPC_BIND_TIME_SECURITY_CONTEXT_MULTIPLEXING;
1024 if (features & DCERPC_BIND_TIME_KEEP_CONNECTION_ON_ORPHAN) {
1025 a->reason.negotiate |=
1026 DCERPC_BIND_TIME_KEEP_CONNECTION_ON_ORPHAN;
1029 call->conn->assoc_group->bind_time_features = a->reason.negotiate;
1033 * Try to negotiate one new presentation context.
1035 * Deep in here we locate the iface (by uuid) that the client
1036 * requested, from the list of interfaces on the
1037 * call->conn->endpoint, and call iface->bind() on that iface.
1039 * call->conn was set up at the accept() of the socket, and
1040 * call->conn->endpoint has a list of interfaces restricted to
1041 * this port or pipe.
1043 status = dcesrv_negotiate_contexts(call, &call->pkt.u.bind, ack_ctx_list);
1044 if (NT_STATUS_EQUAL(status, NT_STATUS_RPC_PROTOCOL_ERROR)) {
1045 return dcesrv_bind_nak(call, 0);
1047 if (!NT_STATUS_IS_OK(status)) {
1048 return status;
1052 * At this point we still don't know which interface (eg
1053 * netlogon, lsa, drsuapi) the caller requested in this bind!
1054 * The most recently added context is available as the first
1055 * element in the linked list at call->conn->contexts, that is
1056 * call->conn->contexts->iface, but they may not have
1057 * requested one at all!
1060 if ((call->pkt.pfc_flags & DCERPC_PFC_FLAG_CONC_MPX) &&
1061 (call->state_flags & DCESRV_CALL_STATE_FLAG_MULTIPLEXED)) {
1062 call->conn->state_flags |= DCESRV_CALL_STATE_FLAG_MULTIPLEXED;
1063 extra_flags |= DCERPC_PFC_FLAG_CONC_MPX;
1066 if (call->state_flags & DCESRV_CALL_STATE_FLAG_PROCESS_PENDING_CALL) {
1067 call->conn->state_flags |= DCESRV_CALL_STATE_FLAG_PROCESS_PENDING_CALL;
1071 * After finding the interface and setting up the NDR
1072 * transport negotiation etc, handle any authentication that
1073 * is being requested.
1075 if (!dcesrv_auth_bind(call)) {
1077 if (auth->auth_level == DCERPC_AUTH_LEVEL_NONE) {
1079 * With DCERPC_AUTH_LEVEL_NONE, we get the
1080 * reject_reason in auth->auth_context_id.
1082 return dcesrv_bind_nak(call, auth->auth_context_id);
1086 * This must a be a temporary failure e.g. talloc or invalid
1087 * configuration, e.g. no machine account.
1089 return dcesrv_bind_nak(call,
1090 DCERPC_BIND_NAK_REASON_TEMPORARY_CONGESTION);
1093 /* setup a bind_ack */
1094 dcesrv_init_hdr(pkt, lpcfg_rpc_big_endian(call->conn->dce_ctx->lp_ctx));
1095 pkt->auth_length = 0;
1096 pkt->call_id = call->pkt.call_id;
1097 pkt->ptype = DCERPC_PKT_BIND_ACK;
1098 pkt->pfc_flags = DCERPC_PFC_FLAG_FIRST | DCERPC_PFC_FLAG_LAST | extra_flags;
1099 pkt->u.bind_ack.max_xmit_frag = call->conn->max_xmit_frag;
1100 pkt->u.bind_ack.max_recv_frag = call->conn->max_recv_frag;
1101 pkt->u.bind_ack.assoc_group_id = call->conn->assoc_group->id;
1103 ep_2nd_description = call->conn->endpoint->ep_2nd_description;
1104 if (ep_2nd_description == NULL) {
1105 ep_2nd_description = call->conn->endpoint->ep_description;
1108 endpoint = dcerpc_binding_get_string_option(
1109 ep_2nd_description,
1110 "endpoint");
1111 if (endpoint == NULL) {
1112 endpoint = "";
1115 pkt->u.bind_ack.secondary_address = endpoint;
1116 pkt->u.bind_ack.num_results = call->pkt.u.bind.num_contexts;
1117 pkt->u.bind_ack.ctx_list = ack_ctx_list;
1118 pkt->u.bind_ack.auth_info = data_blob_null;
1120 status = dcesrv_auth_prepare_bind_ack(call, pkt);
1121 if (!NT_STATUS_IS_OK(status)) {
1122 return dcesrv_bind_nak(call, 0);
1125 if (auth->auth_finished) {
1126 return dcesrv_auth_reply(call);
1129 subreq = gensec_update_send(call, call->event_ctx,
1130 auth->gensec_security,
1131 call->in_auth_info.credentials);
1132 if (subreq == NULL) {
1133 return NT_STATUS_NO_MEMORY;
1135 tevent_req_set_callback(subreq, dcesrv_bind_done, call);
1137 return dcesrv_conn_auth_wait_setup(conn);
1140 static void dcesrv_bind_done(struct tevent_req *subreq)
1142 struct dcesrv_call_state *call =
1143 tevent_req_callback_data(subreq,
1144 struct dcesrv_call_state);
1145 struct dcesrv_connection *conn = call->conn;
1146 NTSTATUS status;
1148 status = gensec_update_recv(subreq, call,
1149 &call->out_auth_info->credentials);
1150 TALLOC_FREE(subreq);
1152 status = dcesrv_auth_complete(call, status);
1153 if (!NT_STATUS_IS_OK(status)) {
1154 status = dcesrv_bind_nak(call, 0);
1155 dcesrv_conn_auth_wait_finished(conn, status);
1156 return;
1159 status = dcesrv_auth_reply(call);
1160 dcesrv_conn_auth_wait_finished(conn, status);
1161 return;
1164 static NTSTATUS dcesrv_auth_reply(struct dcesrv_call_state *call)
1166 struct ncacn_packet *pkt = &call->ack_pkt;
1167 struct data_blob_list_item *rep = NULL;
1168 NTSTATUS status;
1170 rep = talloc_zero(call, struct data_blob_list_item);
1171 if (!rep) {
1172 return NT_STATUS_NO_MEMORY;
1175 status = dcerpc_ncacn_push_auth(&rep->blob,
1176 call,
1177 pkt,
1178 call->out_auth_info);
1179 if (!NT_STATUS_IS_OK(status)) {
1180 return status;
1183 dcerpc_set_frag_length(&rep->blob, rep->blob.length);
1185 DLIST_ADD_END(call->replies, rep);
1186 dcesrv_call_set_list(call, DCESRV_LIST_CALL_LIST);
1188 if (call->conn->call_list && call->conn->call_list->replies) {
1189 if (call->conn->transport.report_output_data) {
1190 call->conn->transport.report_output_data(call->conn);
1194 return NT_STATUS_OK;
1198 static void dcesrv_auth3_done(struct tevent_req *subreq);
1201 handle a auth3 request
1203 static NTSTATUS dcesrv_auth3(struct dcesrv_call_state *call)
1205 struct dcesrv_connection *conn = call->conn;
1206 struct dcesrv_auth *auth = call->auth_state;
1207 struct tevent_req *subreq = NULL;
1208 NTSTATUS status;
1210 if (!auth->auth_started) {
1211 return dcesrv_fault_disconnect(call, DCERPC_NCA_S_PROTO_ERROR);
1214 if (auth->auth_finished) {
1215 return dcesrv_fault_disconnect(call, DCERPC_NCA_S_PROTO_ERROR);
1218 status = dcerpc_verify_ncacn_packet_header(&call->pkt,
1219 DCERPC_PKT_AUTH3,
1220 call->pkt.u.auth3.auth_info.length,
1221 0, /* required flags */
1222 DCERPC_PFC_FLAG_FIRST |
1223 DCERPC_PFC_FLAG_LAST |
1224 DCERPC_PFC_FLAG_SUPPORT_HEADER_SIGN |
1225 0x08 | /* this is not defined, but should be ignored */
1226 DCERPC_PFC_FLAG_CONC_MPX |
1227 DCERPC_PFC_FLAG_DID_NOT_EXECUTE |
1228 DCERPC_PFC_FLAG_MAYBE |
1229 DCERPC_PFC_FLAG_OBJECT_UUID);
1230 if (!NT_STATUS_IS_OK(status)) {
1231 return dcesrv_fault_disconnect(call, DCERPC_NCA_S_PROTO_ERROR);
1234 /* handle the auth3 in the auth code */
1235 if (!dcesrv_auth_prepare_auth3(call)) {
1237 * we don't send a reply to a auth3 request,
1238 * except by a fault.
1240 * In anycase we mark the connection as
1241 * invalid.
1243 auth->auth_invalid = true;
1244 if (call->fault_code != 0) {
1245 return dcesrv_fault_disconnect(call, call->fault_code);
1247 TALLOC_FREE(call);
1248 return NT_STATUS_OK;
1251 subreq = gensec_update_send(call, call->event_ctx,
1252 auth->gensec_security,
1253 call->in_auth_info.credentials);
1254 if (subreq == NULL) {
1255 return NT_STATUS_NO_MEMORY;
1257 tevent_req_set_callback(subreq, dcesrv_auth3_done, call);
1259 return dcesrv_conn_auth_wait_setup(conn);
1262 static void dcesrv_auth3_done(struct tevent_req *subreq)
1264 struct dcesrv_call_state *call =
1265 tevent_req_callback_data(subreq,
1266 struct dcesrv_call_state);
1267 struct dcesrv_connection *conn = call->conn;
1268 struct dcesrv_auth *auth = call->auth_state;
1269 NTSTATUS status;
1271 status = gensec_update_recv(subreq, call,
1272 &call->out_auth_info->credentials);
1273 TALLOC_FREE(subreq);
1275 status = dcesrv_auth_complete(call, status);
1276 if (!NT_STATUS_IS_OK(status)) {
1278 * we don't send a reply to a auth3 request,
1279 * except by a fault.
1281 * In anycase we mark the connection as
1282 * invalid.
1284 auth->auth_invalid = true;
1285 if (call->fault_code != 0) {
1286 status = dcesrv_fault_disconnect(call, call->fault_code);
1287 dcesrv_conn_auth_wait_finished(conn, status);
1288 return;
1290 TALLOC_FREE(call);
1291 dcesrv_conn_auth_wait_finished(conn, NT_STATUS_OK);
1292 return;
1296 * we don't send a reply to a auth3 request.
1298 TALLOC_FREE(call);
1299 dcesrv_conn_auth_wait_finished(conn, NT_STATUS_OK);
1300 return;
1304 static NTSTATUS dcesrv_check_or_create_context(struct dcesrv_call_state *call,
1305 const struct dcerpc_bind *b,
1306 const struct dcerpc_ctx_list *ctx,
1307 struct dcerpc_ack_ctx *ack,
1308 bool validate_only,
1309 const struct ndr_syntax_id *supported_transfer)
1311 uint32_t if_version;
1312 struct dcesrv_connection_context *context;
1313 const struct dcesrv_interface *iface;
1314 struct GUID uuid;
1315 NTSTATUS status;
1316 const struct ndr_syntax_id *selected_transfer = NULL;
1317 size_t i;
1318 bool ok;
1320 if (b == NULL) {
1321 return NT_STATUS_INTERNAL_ERROR;
1323 if (ctx == NULL) {
1324 return NT_STATUS_INTERNAL_ERROR;
1326 if (ctx->num_transfer_syntaxes < 1) {
1327 return NT_STATUS_INTERNAL_ERROR;
1329 if (ack == NULL) {
1330 return NT_STATUS_INTERNAL_ERROR;
1332 if (supported_transfer == NULL) {
1333 return NT_STATUS_INTERNAL_ERROR;
1336 switch (ack->result) {
1337 case DCERPC_BIND_ACK_RESULT_ACCEPTANCE:
1338 case DCERPC_BIND_ACK_RESULT_NEGOTIATE_ACK:
1340 * We is already completed.
1342 return NT_STATUS_OK;
1343 default:
1344 break;
1347 ack->result = DCERPC_BIND_ACK_RESULT_PROVIDER_REJECTION;
1348 ack->reason.value = DCERPC_BIND_ACK_REASON_ABSTRACT_SYNTAX_NOT_SUPPORTED;
1350 if_version = ctx->abstract_syntax.if_version;
1351 uuid = ctx->abstract_syntax.uuid;
1353 iface = find_interface_by_uuid(call->conn->endpoint, &uuid, if_version);
1354 if (iface == NULL) {
1355 char *uuid_str = GUID_string(call, &uuid);
1356 DEBUG(2,("Request for unknown dcerpc interface %s/%d\n", uuid_str, if_version));
1357 talloc_free(uuid_str);
1359 * We report this only via ack->result
1361 return NT_STATUS_OK;
1364 ack->result = DCERPC_BIND_ACK_RESULT_PROVIDER_REJECTION;
1365 ack->reason.value = DCERPC_BIND_ACK_REASON_TRANSFER_SYNTAXES_NOT_SUPPORTED;
1367 if (validate_only) {
1369 * We report this only via ack->result
1371 return NT_STATUS_OK;
1374 for (i = 0; i < ctx->num_transfer_syntaxes; i++) {
1376 * we only do NDR encoded dcerpc for now.
1378 ok = ndr_syntax_id_equal(&ctx->transfer_syntaxes[i],
1379 supported_transfer);
1380 if (ok) {
1381 selected_transfer = supported_transfer;
1382 break;
1386 context = dcesrv_find_context(call->conn, ctx->context_id);
1387 if (context != NULL) {
1388 ok = ndr_syntax_id_equal(&context->iface->syntax_id,
1389 &ctx->abstract_syntax);
1390 if (!ok) {
1391 return NT_STATUS_RPC_PROTOCOL_ERROR;
1394 if (selected_transfer != NULL) {
1395 ok = ndr_syntax_id_equal(&context->transfer_syntax,
1396 selected_transfer);
1397 if (!ok) {
1398 return NT_STATUS_RPC_PROTOCOL_ERROR;
1401 ack->result = DCERPC_BIND_ACK_RESULT_ACCEPTANCE;
1402 ack->reason.value = DCERPC_BIND_ACK_REASON_NOT_SPECIFIED;
1403 ack->syntax = context->transfer_syntax;
1407 * We report this only via ack->result
1409 return NT_STATUS_OK;
1412 if (selected_transfer == NULL) {
1414 * We report this only via ack->result
1416 return NT_STATUS_OK;
1419 ack->result = DCERPC_BIND_ACK_RESULT_USER_REJECTION;
1420 ack->reason.value = DCERPC_BIND_ACK_REASON_LOCAL_LIMIT_EXCEEDED;
1422 /* add this context to the list of available context_ids */
1423 context = talloc_zero(call->conn, struct dcesrv_connection_context);
1424 if (context == NULL) {
1425 return NT_STATUS_NO_MEMORY;
1427 context->conn = call->conn;
1428 context->context_id = ctx->context_id;
1429 context->iface = iface;
1430 context->transfer_syntax = *selected_transfer;
1431 DLIST_ADD(call->conn->contexts, context);
1432 call->context = context;
1433 talloc_set_destructor(context, dcesrv_connection_context_destructor);
1435 dcesrv_prepare_context_auth(call);
1438 * Multiplex is supported by default
1440 call->state_flags |= DCESRV_CALL_STATE_FLAG_MULTIPLEXED;
1442 status = iface->bind(context, iface);
1443 call->context = NULL;
1444 if (!NT_STATUS_IS_OK(status)) {
1445 /* we don't want to trigger the iface->unbind() hook */
1446 context->iface = NULL;
1447 talloc_free(context);
1449 * We report this only via ack->result
1451 return NT_STATUS_OK;
1454 ack->result = DCERPC_BIND_ACK_RESULT_ACCEPTANCE;
1455 ack->reason.value = DCERPC_BIND_ACK_REASON_NOT_SPECIFIED;
1456 ack->syntax = context->transfer_syntax;
1457 return NT_STATUS_OK;
1460 static NTSTATUS dcesrv_negotiate_contexts(struct dcesrv_call_state *call,
1461 const struct dcerpc_bind *b,
1462 struct dcerpc_ack_ctx *ack_ctx_list)
1464 NTSTATUS status;
1465 size_t i;
1466 bool validate_only = false;
1467 bool preferred_ndr32;
1470 * Try to negotiate one new presentation context,
1471 * using our preferred transfer syntax.
1473 for (i = 0; i < b->num_contexts; i++) {
1474 const struct dcerpc_ctx_list *c = &b->ctx_list[i];
1475 struct dcerpc_ack_ctx *a = &ack_ctx_list[i];
1477 status = dcesrv_check_or_create_context(call, b, c, a,
1478 validate_only,
1479 call->conn->preferred_transfer);
1480 if (!NT_STATUS_IS_OK(status)) {
1481 return status;
1484 if (a->result == DCERPC_BIND_ACK_RESULT_ACCEPTANCE) {
1486 * We managed to negotiate one context.
1488 * => we're done.
1490 validate_only = true;
1494 preferred_ndr32 = ndr_syntax_id_equal(&ndr_transfer_syntax_ndr,
1495 call->conn->preferred_transfer);
1496 if (preferred_ndr32) {
1498 * We're done.
1500 return NT_STATUS_OK;
1504 * Try to negotiate one new presentation context,
1505 * using NDR 32 as fallback.
1507 for (i = 0; i < b->num_contexts; i++) {
1508 const struct dcerpc_ctx_list *c = &b->ctx_list[i];
1509 struct dcerpc_ack_ctx *a = &ack_ctx_list[i];
1511 status = dcesrv_check_or_create_context(call, b, c, a,
1512 validate_only,
1513 &ndr_transfer_syntax_ndr);
1514 if (!NT_STATUS_IS_OK(status)) {
1515 return status;
1518 if (a->result == DCERPC_BIND_ACK_RESULT_ACCEPTANCE) {
1520 * We managed to negotiate one context.
1522 * => we're done.
1524 validate_only = true;
1528 return NT_STATUS_OK;
1531 static void dcesrv_alter_done(struct tevent_req *subreq);
1534 handle a alter context request
1536 static NTSTATUS dcesrv_alter(struct dcesrv_call_state *call)
1538 struct dcesrv_connection *conn = call->conn;
1539 NTSTATUS status;
1540 bool auth_ok = false;
1541 struct ncacn_packet *pkt = &call->ack_pkt;
1542 uint32_t extra_flags = 0;
1543 struct dcesrv_auth *auth = call->auth_state;
1544 struct dcerpc_ack_ctx *ack_ctx_list = NULL;
1545 struct tevent_req *subreq = NULL;
1546 size_t i;
1548 if (!call->conn->allow_alter) {
1549 return dcesrv_fault_disconnect(call, DCERPC_NCA_S_PROTO_ERROR);
1552 status = dcerpc_verify_ncacn_packet_header(&call->pkt,
1553 DCERPC_PKT_ALTER,
1554 call->pkt.u.alter.auth_info.length,
1555 0, /* required flags */
1556 DCERPC_PFC_FLAG_FIRST |
1557 DCERPC_PFC_FLAG_LAST |
1558 DCERPC_PFC_FLAG_SUPPORT_HEADER_SIGN |
1559 0x08 | /* this is not defined, but should be ignored */
1560 DCERPC_PFC_FLAG_CONC_MPX |
1561 DCERPC_PFC_FLAG_DID_NOT_EXECUTE |
1562 DCERPC_PFC_FLAG_MAYBE |
1563 DCERPC_PFC_FLAG_OBJECT_UUID);
1564 if (!NT_STATUS_IS_OK(status)) {
1565 return dcesrv_fault_disconnect(call, DCERPC_NCA_S_PROTO_ERROR);
1568 auth_ok = dcesrv_auth_alter(call);
1569 if (!auth_ok) {
1570 if (call->fault_code != 0) {
1571 return dcesrv_fault_disconnect(call, call->fault_code);
1575 if (call->pkt.u.alter.num_contexts < 1) {
1576 return dcesrv_fault_disconnect(call, DCERPC_NCA_S_PROTO_ERROR);
1579 ack_ctx_list = talloc_zero_array(call, struct dcerpc_ack_ctx,
1580 call->pkt.u.alter.num_contexts);
1581 if (ack_ctx_list == NULL) {
1582 return NT_STATUS_NO_MEMORY;
1586 * Set some sane defaults (required by dcesrv_negotiate_contexts()/
1587 * dcesrv_check_or_create_context()) and do some protocol validation
1588 * and set sane defaults.
1590 for (i = 0; i < call->pkt.u.alter.num_contexts; i++) {
1591 const struct dcerpc_ctx_list *c = &call->pkt.u.alter.ctx_list[i];
1592 struct dcerpc_ack_ctx *a = &ack_ctx_list[i];
1594 if (c->num_transfer_syntaxes == 0) {
1595 return dcesrv_fault_disconnect(call,
1596 DCERPC_NCA_S_PROTO_ERROR);
1599 a->result = DCERPC_BIND_ACK_RESULT_PROVIDER_REJECTION;
1600 a->reason.value = DCERPC_BIND_ACK_REASON_ABSTRACT_SYNTAX_NOT_SUPPORTED;
1604 * Try to negotiate one new presentation context.
1606 status = dcesrv_negotiate_contexts(call, &call->pkt.u.alter, ack_ctx_list);
1607 if (NT_STATUS_EQUAL(status, NT_STATUS_RPC_PROTOCOL_ERROR)) {
1608 return dcesrv_fault_disconnect(call, DCERPC_NCA_S_PROTO_ERROR);
1610 if (!NT_STATUS_IS_OK(status)) {
1611 return status;
1614 if ((call->pkt.pfc_flags & DCERPC_PFC_FLAG_CONC_MPX) &&
1615 (call->state_flags & DCESRV_CALL_STATE_FLAG_MULTIPLEXED)) {
1616 call->conn->state_flags |= DCESRV_CALL_STATE_FLAG_MULTIPLEXED;
1617 extra_flags |= DCERPC_PFC_FLAG_CONC_MPX;
1620 if (call->state_flags & DCESRV_CALL_STATE_FLAG_PROCESS_PENDING_CALL) {
1621 call->conn->state_flags |= DCESRV_CALL_STATE_FLAG_PROCESS_PENDING_CALL;
1624 /* handle any authentication that is being requested */
1625 if (!auth_ok) {
1626 if (call->in_auth_info.auth_type != auth->auth_type) {
1627 return dcesrv_fault_disconnect(call,
1628 DCERPC_FAULT_SEC_PKG_ERROR);
1630 return dcesrv_fault_disconnect(call, DCERPC_FAULT_ACCESS_DENIED);
1633 dcesrv_init_hdr(pkt, lpcfg_rpc_big_endian(call->conn->dce_ctx->lp_ctx));
1634 pkt->auth_length = 0;
1635 pkt->call_id = call->pkt.call_id;
1636 pkt->ptype = DCERPC_PKT_ALTER_RESP;
1637 pkt->pfc_flags = DCERPC_PFC_FLAG_FIRST | DCERPC_PFC_FLAG_LAST | extra_flags;
1638 pkt->u.alter_resp.max_xmit_frag = call->conn->max_xmit_frag;
1639 pkt->u.alter_resp.max_recv_frag = call->conn->max_recv_frag;
1640 pkt->u.alter_resp.assoc_group_id = call->conn->assoc_group->id;
1641 pkt->u.alter_resp.secondary_address = "";
1642 pkt->u.alter_resp.num_results = call->pkt.u.alter.num_contexts;
1643 pkt->u.alter_resp.ctx_list = ack_ctx_list;
1644 pkt->u.alter_resp.auth_info = data_blob_null;
1646 status = dcesrv_auth_prepare_alter_ack(call, pkt);
1647 if (!NT_STATUS_IS_OK(status)) {
1648 return dcesrv_fault_disconnect(call, DCERPC_FAULT_SEC_PKG_ERROR);
1651 if (auth->auth_finished) {
1652 return dcesrv_auth_reply(call);
1655 subreq = gensec_update_send(call, call->event_ctx,
1656 auth->gensec_security,
1657 call->in_auth_info.credentials);
1658 if (subreq == NULL) {
1659 return NT_STATUS_NO_MEMORY;
1661 tevent_req_set_callback(subreq, dcesrv_alter_done, call);
1663 return dcesrv_conn_auth_wait_setup(conn);
1666 static void dcesrv_alter_done(struct tevent_req *subreq)
1668 struct dcesrv_call_state *call =
1669 tevent_req_callback_data(subreq,
1670 struct dcesrv_call_state);
1671 struct dcesrv_connection *conn = call->conn;
1672 NTSTATUS status;
1674 status = gensec_update_recv(subreq, call,
1675 &call->out_auth_info->credentials);
1676 TALLOC_FREE(subreq);
1678 status = dcesrv_auth_complete(call, status);
1679 if (!NT_STATUS_IS_OK(status)) {
1680 status = dcesrv_fault_disconnect(call, DCERPC_FAULT_SEC_PKG_ERROR);
1681 dcesrv_conn_auth_wait_finished(conn, status);
1682 return;
1685 status = dcesrv_auth_reply(call);
1686 dcesrv_conn_auth_wait_finished(conn, status);
1687 return;
1691 possibly save the call for inspection with ndrdump
1693 static void dcesrv_save_call(struct dcesrv_call_state *call, const char *why)
1695 #ifdef DEVELOPER
1696 char *fname;
1697 const char *dump_dir;
1698 dump_dir = lpcfg_parm_string(call->conn->dce_ctx->lp_ctx, NULL, "dcesrv", "stubs directory");
1699 if (!dump_dir) {
1700 return;
1702 fname = talloc_asprintf(call, "%s/RPC-%s-%u-%s.dat",
1703 dump_dir,
1704 call->context->iface->name,
1705 call->pkt.u.request.opnum,
1706 why);
1707 if (file_save(fname, call->pkt.u.request.stub_and_verifier.data, call->pkt.u.request.stub_and_verifier.length)) {
1708 DEBUG(0,("RPC SAVED %s\n", fname));
1710 talloc_free(fname);
1711 #endif
1714 static NTSTATUS dcesrv_check_verification_trailer(struct dcesrv_call_state *call)
1716 TALLOC_CTX *frame = talloc_stackframe();
1717 const uint32_t bitmask1 = call->conn->client_hdr_signing ?
1718 DCERPC_SEC_VT_CLIENT_SUPPORTS_HEADER_SIGNING : 0;
1719 const struct dcerpc_sec_vt_pcontext pcontext = {
1720 .abstract_syntax = call->context->iface->syntax_id,
1721 .transfer_syntax = call->context->transfer_syntax,
1723 const struct dcerpc_sec_vt_header2 header2 =
1724 dcerpc_sec_vt_header2_from_ncacn_packet(&call->pkt);
1725 enum ndr_err_code ndr_err;
1726 struct dcerpc_sec_verification_trailer *vt = NULL;
1727 NTSTATUS status = NT_STATUS_OK;
1728 bool ok;
1730 SMB_ASSERT(call->pkt.ptype == DCERPC_PKT_REQUEST);
1732 ndr_err = ndr_pop_dcerpc_sec_verification_trailer(call->ndr_pull,
1733 frame, &vt);
1734 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
1735 status = ndr_map_error2ntstatus(ndr_err);
1736 goto done;
1739 ok = dcerpc_sec_verification_trailer_check(vt, &bitmask1,
1740 &pcontext, &header2);
1741 if (!ok) {
1742 status = NT_STATUS_ACCESS_DENIED;
1743 goto done;
1745 done:
1746 TALLOC_FREE(frame);
1747 return status;
1751 handle a dcerpc request packet
1753 static NTSTATUS dcesrv_request(struct dcesrv_call_state *call)
1755 const struct dcesrv_endpoint *endpoint = call->conn->endpoint;
1756 struct dcesrv_auth *auth = call->auth_state;
1757 enum dcerpc_transport_t transport =
1758 dcerpc_binding_get_transport(endpoint->ep_description);
1759 struct ndr_pull *pull;
1760 NTSTATUS status;
1762 if (!auth->auth_finished) {
1763 return dcesrv_fault_disconnect(call, DCERPC_NCA_S_PROTO_ERROR);
1766 /* if authenticated, and the mech we use can't do async replies, don't use them... */
1767 if (auth->gensec_security != NULL &&
1768 !gensec_have_feature(auth->gensec_security, GENSEC_FEATURE_ASYNC_REPLIES)) {
1769 call->state_flags &= ~DCESRV_CALL_STATE_FLAG_MAY_ASYNC;
1772 if (call->context == NULL) {
1773 return dcesrv_fault_with_flags(call, DCERPC_NCA_S_UNKNOWN_IF,
1774 DCERPC_PFC_FLAG_DID_NOT_EXECUTE);
1777 switch (auth->auth_level) {
1778 case DCERPC_AUTH_LEVEL_NONE:
1779 case DCERPC_AUTH_LEVEL_PACKET:
1780 case DCERPC_AUTH_LEVEL_INTEGRITY:
1781 case DCERPC_AUTH_LEVEL_PRIVACY:
1782 break;
1783 default:
1784 if (!call->context->allow_connect) {
1785 char *addr;
1787 addr = tsocket_address_string(call->conn->remote_address,
1788 call);
1790 DEBUG(2, ("%s: restrict auth_level_connect access "
1791 "to [%s] with auth[type=0x%x,level=0x%x] "
1792 "on [%s] from [%s]\n",
1793 __func__, call->context->iface->name,
1794 auth->auth_type,
1795 auth->auth_level,
1796 derpc_transport_string_by_transport(transport),
1797 addr));
1798 return dcesrv_fault(call, DCERPC_FAULT_ACCESS_DENIED);
1800 break;
1803 if (auth->auth_level < call->context->min_auth_level) {
1804 char *addr;
1806 addr = tsocket_address_string(call->conn->remote_address, call);
1808 DEBUG(2, ("%s: restrict access by min_auth_level[0x%x] "
1809 "to [%s] with auth[type=0x%x,level=0x%x] "
1810 "on [%s] from [%s]\n",
1811 __func__,
1812 call->context->min_auth_level,
1813 call->context->iface->name,
1814 auth->auth_type,
1815 auth->auth_level,
1816 derpc_transport_string_by_transport(transport),
1817 addr));
1818 return dcesrv_fault(call, DCERPC_FAULT_ACCESS_DENIED);
1821 pull = ndr_pull_init_blob(&call->pkt.u.request.stub_and_verifier, call);
1822 NT_STATUS_HAVE_NO_MEMORY(pull);
1824 pull->flags |= LIBNDR_FLAG_REF_ALLOC;
1826 call->ndr_pull = pull;
1828 if (!(call->pkt.drep[0] & DCERPC_DREP_LE)) {
1829 pull->flags |= LIBNDR_FLAG_BIGENDIAN;
1832 status = dcesrv_check_verification_trailer(call);
1833 if (!NT_STATUS_IS_OK(status)) {
1834 uint32_t faultcode = DCERPC_FAULT_OTHER;
1835 if (NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
1836 faultcode = DCERPC_FAULT_ACCESS_DENIED;
1838 DEBUG(10, ("dcesrv_check_verification_trailer failed: %s\n",
1839 nt_errstr(status)));
1840 return dcesrv_fault(call, faultcode);
1843 /* unravel the NDR for the packet */
1844 status = call->context->iface->ndr_pull(call, call, pull, &call->r);
1845 if (!NT_STATUS_IS_OK(status)) {
1846 uint8_t extra_flags = 0;
1847 if (call->fault_code == DCERPC_FAULT_OP_RNG_ERROR) {
1848 /* we got an unknown call */
1849 DEBUG(3,(__location__ ": Unknown RPC call %u on %s\n",
1850 call->pkt.u.request.opnum,
1851 call->context->iface->name));
1852 dcesrv_save_call(call, "unknown");
1853 extra_flags |= DCERPC_PFC_FLAG_DID_NOT_EXECUTE;
1854 } else {
1855 dcesrv_save_call(call, "pullfail");
1857 return dcesrv_fault_with_flags(call, call->fault_code, extra_flags);
1860 if (pull->offset != pull->data_size) {
1861 dcesrv_save_call(call, "extrabytes");
1862 DEBUG(3,("Warning: %d extra bytes in incoming RPC request\n",
1863 pull->data_size - pull->offset));
1866 /* call the dispatch function */
1867 status = call->context->iface->dispatch(call, call, call->r);
1868 if (!NT_STATUS_IS_OK(status)) {
1869 DEBUG(5,("dcerpc fault in call %s:%02x - %s\n",
1870 call->context->iface->name,
1871 call->pkt.u.request.opnum,
1872 dcerpc_errstr(pull, call->fault_code)));
1873 return dcesrv_fault(call, call->fault_code);
1876 /* add the call to the pending list */
1877 dcesrv_call_set_list(call, DCESRV_LIST_PENDING_CALL_LIST);
1879 if (call->state_flags & DCESRV_CALL_STATE_FLAG_ASYNC) {
1880 return NT_STATUS_OK;
1883 return dcesrv_reply(call);
1888 remove the call from the right list when freed
1890 static int dcesrv_call_dequeue(struct dcesrv_call_state *call)
1892 dcesrv_call_set_list(call, DCESRV_LIST_NONE);
1893 return 0;
1896 _PUBLIC_ const struct tsocket_address *dcesrv_connection_get_local_address(struct dcesrv_connection *conn)
1898 return conn->local_address;
1901 _PUBLIC_ const struct tsocket_address *dcesrv_connection_get_remote_address(struct dcesrv_connection *conn)
1903 return conn->remote_address;
1907 process some input to a dcerpc endpoint server.
1909 static NTSTATUS dcesrv_process_ncacn_packet(struct dcesrv_connection *dce_conn,
1910 struct ncacn_packet *pkt,
1911 DATA_BLOB blob)
1913 NTSTATUS status;
1914 struct dcesrv_call_state *call;
1915 struct dcesrv_call_state *existing = NULL;
1916 size_t num_auth_ctx = 0;
1917 enum dcerpc_AuthType auth_type = 0;
1918 enum dcerpc_AuthLevel auth_level = 0;
1919 uint32_t auth_context_id = 0;
1921 call = talloc_zero(dce_conn, struct dcesrv_call_state);
1922 if (!call) {
1923 data_blob_free(&blob);
1924 talloc_free(pkt);
1925 return NT_STATUS_NO_MEMORY;
1927 call->conn = dce_conn;
1928 call->event_ctx = dce_conn->event_ctx;
1929 call->state_flags = call->conn->state_flags;
1930 call->time = timeval_current();
1931 call->list = DCESRV_LIST_NONE;
1933 talloc_steal(call, pkt);
1934 talloc_steal(call, blob.data);
1935 call->pkt = *pkt;
1937 if (dce_conn->max_auth_states == 0) {
1938 call->auth_state = dce_conn->default_auth_state;
1939 } else if (call->pkt.auth_length == 0) {
1940 if (call->pkt.ptype == DCERPC_PKT_REQUEST &&
1941 dce_conn->default_auth_level_connect != NULL)
1943 call->auth_state = dce_conn->default_auth_level_connect;
1944 } else {
1945 call->auth_state = dce_conn->default_auth_state;
1949 if (call->auth_state == NULL) {
1950 struct dcesrv_auth *a = NULL;
1952 auth_type = dcerpc_get_auth_type(&blob);
1953 auth_level = dcerpc_get_auth_level(&blob);
1954 auth_context_id = dcerpc_get_auth_context_id(&blob);
1956 if (call->pkt.ptype == DCERPC_PKT_REQUEST) {
1957 dce_conn->default_auth_level_connect = NULL;
1958 if (auth_level == DCERPC_AUTH_LEVEL_CONNECT) {
1959 dce_conn->got_explicit_auth_level_connect = true;
1963 for (a = dce_conn->auth_states; a != NULL; a = a->next) {
1964 num_auth_ctx++;
1966 if (a->auth_type != auth_type) {
1967 continue;
1969 if (a->auth_finished && a->auth_level != auth_level) {
1970 continue;
1972 if (a->auth_context_id != auth_context_id) {
1973 continue;
1976 DLIST_PROMOTE(dce_conn->auth_states, a);
1977 call->auth_state = a;
1978 break;
1982 if (call->auth_state == NULL) {
1983 struct dcesrv_auth *a = NULL;
1985 if (num_auth_ctx >= dce_conn->max_auth_states) {
1986 return dcesrv_fault_disconnect(call,
1987 DCERPC_NCA_S_PROTO_ERROR);
1990 a = dcesrv_auth_create(dce_conn);
1991 if (a == NULL) {
1992 talloc_free(call);
1993 return NT_STATUS_NO_MEMORY;
1995 DLIST_ADD(dce_conn->auth_states, a);
1996 if (call->pkt.ptype == DCERPC_PKT_REQUEST) {
1998 * This can never be valid.
2000 a->auth_invalid = true;
2002 call->auth_state = a;
2005 talloc_set_destructor(call, dcesrv_call_dequeue);
2007 if (call->conn->allow_bind) {
2009 * Only one bind is possible per connection
2011 call->conn->allow_bind = false;
2012 return dcesrv_bind(call);
2015 /* we have to check the signing here, before combining the
2016 pdus */
2017 if (call->pkt.ptype == DCERPC_PKT_REQUEST) {
2018 dcesrv_default_auth_state_prepare_request(call);
2020 if (call->auth_state->auth_started &&
2021 !call->auth_state->auth_finished) {
2022 return dcesrv_fault_disconnect(call,
2023 DCERPC_NCA_S_PROTO_ERROR);
2026 status = dcerpc_verify_ncacn_packet_header(&call->pkt,
2027 DCERPC_PKT_REQUEST,
2028 call->pkt.u.request.stub_and_verifier.length,
2029 0, /* required_flags */
2030 DCERPC_PFC_FLAG_FIRST |
2031 DCERPC_PFC_FLAG_LAST |
2032 DCERPC_PFC_FLAG_PENDING_CANCEL |
2033 0x08 | /* this is not defined, but should be ignored */
2034 DCERPC_PFC_FLAG_CONC_MPX |
2035 DCERPC_PFC_FLAG_DID_NOT_EXECUTE |
2036 DCERPC_PFC_FLAG_MAYBE |
2037 DCERPC_PFC_FLAG_OBJECT_UUID);
2038 if (!NT_STATUS_IS_OK(status)) {
2039 return dcesrv_fault_disconnect(call,
2040 DCERPC_NCA_S_PROTO_ERROR);
2043 if (call->pkt.frag_length > DCERPC_FRAG_MAX_SIZE) {
2045 * We don't use dcesrv_fault_disconnect()
2046 * here, because we don't want to set
2047 * DCERPC_PFC_FLAG_DID_NOT_EXECUTE
2049 * Note that we don't check against the negotiated
2050 * max_recv_frag, but a hard coded value.
2052 dcesrv_call_disconnect_after(call,
2053 "dcesrv_auth_request - frag_length too large");
2054 return dcesrv_fault(call,
2055 DCERPC_NCA_S_PROTO_ERROR);
2058 if (call->pkt.pfc_flags & DCERPC_PFC_FLAG_FIRST) {
2059 if (dce_conn->pending_call_list != NULL) {
2061 * concurrent requests are only allowed
2062 * if DCERPC_PFC_FLAG_CONC_MPX was negotiated.
2064 if (!(dce_conn->state_flags & DCESRV_CALL_STATE_FLAG_MULTIPLEXED)) {
2065 dcesrv_call_disconnect_after(call,
2066 "dcesrv_auth_request - "
2067 "existing pending call without CONN_MPX");
2068 return dcesrv_fault(call,
2069 DCERPC_NCA_S_PROTO_ERROR);
2072 /* only one request is possible in the fragmented list */
2073 if (dce_conn->incoming_fragmented_call_list != NULL) {
2074 if (!(dce_conn->state_flags & DCESRV_CALL_STATE_FLAG_MULTIPLEXED)) {
2076 * Without DCERPC_PFC_FLAG_CONC_MPX
2077 * we need to return the FAULT on the
2078 * already existing call.
2080 * This is important to get the
2081 * call_id and context_id right.
2083 TALLOC_FREE(call);
2084 call = dce_conn->incoming_fragmented_call_list;
2086 dcesrv_call_disconnect_after(call,
2087 "dcesrv_auth_request - "
2088 "existing fragmented call");
2089 return dcesrv_fault(call,
2090 DCERPC_NCA_S_PROTO_ERROR);
2092 if (call->pkt.pfc_flags & DCERPC_PFC_FLAG_PENDING_CANCEL) {
2093 return dcesrv_fault_disconnect(call,
2094 DCERPC_FAULT_NO_CALL_ACTIVE);
2096 call->context = dcesrv_find_context(call->conn,
2097 call->pkt.u.request.context_id);
2098 if (call->context == NULL) {
2099 return dcesrv_fault_with_flags(call, DCERPC_NCA_S_UNKNOWN_IF,
2100 DCERPC_PFC_FLAG_DID_NOT_EXECUTE);
2102 } else {
2103 const struct dcerpc_request *nr = &call->pkt.u.request;
2104 const struct dcerpc_request *er = NULL;
2105 int cmp;
2107 existing = dcesrv_find_fragmented_call(dce_conn,
2108 call->pkt.call_id);
2109 if (existing == NULL) {
2110 dcesrv_call_disconnect_after(call,
2111 "dcesrv_auth_request - "
2112 "no existing fragmented call");
2113 return dcesrv_fault(call,
2114 DCERPC_NCA_S_PROTO_ERROR);
2116 er = &existing->pkt.u.request;
2118 if (call->pkt.ptype != existing->pkt.ptype) {
2119 /* trying to play silly buggers are we? */
2120 return dcesrv_fault_disconnect(existing,
2121 DCERPC_NCA_S_PROTO_ERROR);
2123 cmp = memcmp(call->pkt.drep, existing->pkt.drep,
2124 sizeof(pkt->drep));
2125 if (cmp != 0) {
2126 return dcesrv_fault_disconnect(existing,
2127 DCERPC_NCA_S_PROTO_ERROR);
2129 if (nr->context_id != er->context_id) {
2130 return dcesrv_fault_disconnect(existing,
2131 DCERPC_NCA_S_PROTO_ERROR);
2133 if (nr->opnum != er->opnum) {
2134 return dcesrv_fault_disconnect(existing,
2135 DCERPC_NCA_S_PROTO_ERROR);
2140 if (call->pkt.ptype == DCERPC_PKT_REQUEST) {
2141 bool ok;
2142 uint8_t payload_offset = DCERPC_REQUEST_LENGTH;
2144 if (call->pkt.pfc_flags & DCERPC_PFC_FLAG_OBJECT_UUID) {
2145 payload_offset += 16;
2148 ok = dcesrv_auth_pkt_pull(call, &blob,
2149 0, /* required_flags */
2150 DCERPC_PFC_FLAG_FIRST |
2151 DCERPC_PFC_FLAG_LAST |
2152 DCERPC_PFC_FLAG_PENDING_CANCEL |
2153 0x08 | /* this is not defined, but should be ignored */
2154 DCERPC_PFC_FLAG_CONC_MPX |
2155 DCERPC_PFC_FLAG_DID_NOT_EXECUTE |
2156 DCERPC_PFC_FLAG_MAYBE |
2157 DCERPC_PFC_FLAG_OBJECT_UUID,
2158 payload_offset,
2159 &call->pkt.u.request.stub_and_verifier);
2160 if (!ok) {
2162 * We don't use dcesrv_fault_disconnect()
2163 * here, because we don't want to set
2164 * DCERPC_PFC_FLAG_DID_NOT_EXECUTE
2166 dcesrv_call_disconnect_after(call,
2167 "dcesrv_auth_request - failed");
2168 if (call->fault_code == 0) {
2169 call->fault_code = DCERPC_FAULT_ACCESS_DENIED;
2171 return dcesrv_fault(call, call->fault_code);
2175 /* see if this is a continued packet */
2176 if (existing != NULL) {
2177 struct dcerpc_request *er = &existing->pkt.u.request;
2178 const struct dcerpc_request *nr = &call->pkt.u.request;
2179 size_t available;
2180 size_t alloc_size;
2181 size_t alloc_hint;
2184 * Up to 4 MByte are allowed by all fragments
2186 available = dce_conn->max_total_request_size;
2187 if (er->stub_and_verifier.length > available) {
2188 dcesrv_call_disconnect_after(existing,
2189 "dcesrv_auth_request - existing payload too large");
2190 return dcesrv_fault(existing, DCERPC_FAULT_ACCESS_DENIED);
2192 available -= er->stub_and_verifier.length;
2193 if (nr->alloc_hint > available) {
2194 dcesrv_call_disconnect_after(existing,
2195 "dcesrv_auth_request - alloc hint too large");
2196 return dcesrv_fault(existing, DCERPC_FAULT_ACCESS_DENIED);
2198 if (nr->stub_and_verifier.length > available) {
2199 dcesrv_call_disconnect_after(existing,
2200 "dcesrv_auth_request - new payload too large");
2201 return dcesrv_fault(existing, DCERPC_FAULT_ACCESS_DENIED);
2203 alloc_hint = er->stub_and_verifier.length + nr->alloc_hint;
2204 /* allocate at least 1 byte */
2205 alloc_hint = MAX(alloc_hint, 1);
2206 alloc_size = er->stub_and_verifier.length +
2207 nr->stub_and_verifier.length;
2208 alloc_size = MAX(alloc_size, alloc_hint);
2210 er->stub_and_verifier.data =
2211 talloc_realloc(existing,
2212 er->stub_and_verifier.data,
2213 uint8_t, alloc_size);
2214 if (er->stub_and_verifier.data == NULL) {
2215 TALLOC_FREE(call);
2216 return dcesrv_fault_with_flags(existing,
2217 DCERPC_FAULT_OUT_OF_RESOURCES,
2218 DCERPC_PFC_FLAG_DID_NOT_EXECUTE);
2220 memcpy(er->stub_and_verifier.data +
2221 er->stub_and_verifier.length,
2222 nr->stub_and_verifier.data,
2223 nr->stub_and_verifier.length);
2224 er->stub_and_verifier.length += nr->stub_and_verifier.length;
2226 existing->pkt.pfc_flags |= (call->pkt.pfc_flags & DCERPC_PFC_FLAG_LAST);
2228 TALLOC_FREE(call);
2229 call = existing;
2232 /* this may not be the last pdu in the chain - if its isn't then
2233 just put it on the incoming_fragmented_call_list and wait for the rest */
2234 if (call->pkt.ptype == DCERPC_PKT_REQUEST &&
2235 !(call->pkt.pfc_flags & DCERPC_PFC_FLAG_LAST)) {
2237 * Up to 4 MByte are allowed by all fragments
2239 if (call->pkt.u.request.alloc_hint > dce_conn->max_total_request_size) {
2240 dcesrv_call_disconnect_after(call,
2241 "dcesrv_auth_request - initial alloc hint too large");
2242 return dcesrv_fault(call, DCERPC_FAULT_ACCESS_DENIED);
2244 dcesrv_call_set_list(call, DCESRV_LIST_FRAGMENTED_CALL_LIST);
2245 return NT_STATUS_OK;
2248 /* This removes any fragments we may have had stashed away */
2249 dcesrv_call_set_list(call, DCESRV_LIST_NONE);
2251 switch (call->pkt.ptype) {
2252 case DCERPC_PKT_BIND:
2253 status = dcesrv_bind_nak(call,
2254 DCERPC_BIND_NAK_REASON_NOT_SPECIFIED);
2255 break;
2256 case DCERPC_PKT_AUTH3:
2257 status = dcesrv_auth3(call);
2258 break;
2259 case DCERPC_PKT_ALTER:
2260 status = dcesrv_alter(call);
2261 break;
2262 case DCERPC_PKT_REQUEST:
2263 status = dcesrv_request(call);
2264 break;
2265 case DCERPC_PKT_CO_CANCEL:
2266 case DCERPC_PKT_ORPHANED:
2268 * Window just ignores CO_CANCEL and ORPHANED,
2269 * so we do...
2271 status = NT_STATUS_OK;
2272 TALLOC_FREE(call);
2273 break;
2274 case DCERPC_PKT_BIND_ACK:
2275 case DCERPC_PKT_BIND_NAK:
2276 case DCERPC_PKT_ALTER_RESP:
2277 case DCERPC_PKT_RESPONSE:
2278 case DCERPC_PKT_FAULT:
2279 case DCERPC_PKT_SHUTDOWN:
2280 default:
2281 status = dcesrv_fault_disconnect(call, DCERPC_NCA_S_PROTO_ERROR);
2282 break;
2285 /* if we are going to be sending a reply then add
2286 it to the list of pending calls. We add it to the end to keep the call
2287 list in the order we will answer */
2288 if (!NT_STATUS_IS_OK(status)) {
2289 talloc_free(call);
2292 return status;
2295 _PUBLIC_ NTSTATUS dcesrv_init_context(TALLOC_CTX *mem_ctx,
2296 struct loadparm_context *lp_ctx,
2297 const char **endpoint_servers,
2298 struct dcesrv_context_callbacks *cb,
2299 struct dcesrv_context **_dce_ctx)
2301 NTSTATUS status;
2302 struct dcesrv_context *dce_ctx;
2303 int i;
2305 if (!endpoint_servers) {
2306 DEBUG(0,("dcesrv_init_context: no endpoint servers configured\n"));
2307 return NT_STATUS_INTERNAL_ERROR;
2310 dce_ctx = talloc_zero(mem_ctx, struct dcesrv_context);
2311 NT_STATUS_HAVE_NO_MEMORY(dce_ctx);
2313 if (uid_wrapper_enabled()) {
2314 setenv("UID_WRAPPER_MYUID", "1", 1);
2316 dce_ctx->initial_euid = geteuid();
2317 if (uid_wrapper_enabled()) {
2318 unsetenv("UID_WRAPPER_MYUID");
2321 dce_ctx->endpoint_list = NULL;
2322 dce_ctx->lp_ctx = lp_ctx;
2323 dce_ctx->assoc_groups_idr = idr_init(dce_ctx);
2324 NT_STATUS_HAVE_NO_MEMORY(dce_ctx->assoc_groups_idr);
2325 dce_ctx->broken_connections = NULL;
2326 if (cb != NULL) {
2327 dce_ctx->callbacks = *cb;
2330 for (i=0;endpoint_servers[i];i++) {
2331 const struct dcesrv_endpoint_server *ep_server;
2333 ep_server = dcesrv_ep_server_byname(endpoint_servers[i]);
2334 if (!ep_server) {
2335 DEBUG(0,("dcesrv_init_context: failed to find endpoint server = '%s'\n", endpoint_servers[i]));
2336 return NT_STATUS_INTERNAL_ERROR;
2339 status = ep_server->init_server(dce_ctx, ep_server);
2340 if (!NT_STATUS_IS_OK(status)) {
2341 DEBUG(0,("dcesrv_init_context: failed to init endpoint server = '%s': %s\n", endpoint_servers[i],
2342 nt_errstr(status)));
2343 return status;
2347 *_dce_ctx = dce_ctx;
2348 return NT_STATUS_OK;
2351 /* the list of currently registered DCERPC endpoint servers.
2353 static struct ep_server {
2354 struct dcesrv_endpoint_server *ep_server;
2355 } *ep_servers = NULL;
2356 static int num_ep_servers = 0;
2359 register a DCERPC endpoint server.
2361 The 'name' can be later used by other backends to find the operations
2362 structure for this backend.
2365 _PUBLIC_ NTSTATUS dcerpc_register_ep_server(const struct dcesrv_endpoint_server *ep_server)
2368 if (dcesrv_ep_server_byname(ep_server->name) != NULL) {
2369 /* its already registered! */
2370 DEBUG(0,("DCERPC endpoint server '%s' already registered\n",
2371 ep_server->name));
2372 return NT_STATUS_OBJECT_NAME_COLLISION;
2375 ep_servers = realloc_p(ep_servers, struct ep_server, num_ep_servers+1);
2376 if (!ep_servers) {
2377 smb_panic("out of memory in dcerpc_register");
2380 ep_servers[num_ep_servers].ep_server = smb_xmemdup(ep_server, sizeof(*ep_server));
2381 ep_servers[num_ep_servers].ep_server->name = smb_xstrdup(ep_server->name);
2383 num_ep_servers++;
2385 DEBUG(3,("DCERPC endpoint server '%s' registered\n",
2386 ep_server->name));
2388 return NT_STATUS_OK;
2392 return the operations structure for a named backend of the specified type
2394 _PUBLIC_ const struct dcesrv_endpoint_server *dcesrv_ep_server_byname(const char *name)
2396 int i;
2398 for (i=0;i<num_ep_servers;i++) {
2399 if (strcmp(ep_servers[i].ep_server->name, name) == 0) {
2400 return ep_servers[i].ep_server;
2404 return NULL;
2408 return the DCERPC module version, and the size of some critical types
2409 This can be used by endpoint server modules to either detect compilation errors, or provide
2410 multiple implementations for different smbd compilation options in one module
2412 const struct dcesrv_critical_sizes *dcerpc_module_version(void)
2414 static const struct dcesrv_critical_sizes critical_sizes = {
2415 DCERPC_MODULE_VERSION,
2416 sizeof(struct dcesrv_context),
2417 sizeof(struct dcesrv_endpoint),
2418 sizeof(struct dcesrv_endpoint_server),
2419 sizeof(struct dcesrv_interface),
2420 sizeof(struct dcesrv_if_list),
2421 sizeof(struct dcesrv_connection),
2422 sizeof(struct dcesrv_call_state),
2423 sizeof(struct dcesrv_auth),
2424 sizeof(struct dcesrv_handle)
2427 return &critical_sizes;
2430 _PUBLIC_ void dcesrv_terminate_connection(struct dcesrv_connection *dce_conn, const char *reason)
2432 struct dcesrv_context *dce_ctx = dce_conn->dce_ctx;
2433 struct dcesrv_auth *a = NULL;
2435 dce_conn->wait_send = NULL;
2436 dce_conn->wait_recv = NULL;
2437 dce_conn->wait_private = NULL;
2439 dce_conn->allow_bind = false;
2440 dce_conn->allow_alter = false;
2442 dce_conn->default_auth_state->auth_invalid = true;
2444 for (a = dce_conn->auth_states; a != NULL; a = a->next) {
2445 a->auth_invalid = true;
2448 if (dce_conn->pending_call_list == NULL) {
2449 char *full_reason = talloc_asprintf(dce_conn, "dcesrv: %s", reason);
2451 DLIST_REMOVE(dce_ctx->broken_connections, dce_conn);
2452 dce_conn->transport.terminate_connection(dce_conn,
2453 full_reason ? full_reason : reason);
2454 return;
2457 if (dce_conn->terminate != NULL) {
2458 return;
2461 DEBUG(3,("dcesrv: terminating connection due to '%s' deferred due to pending calls\n",
2462 reason));
2463 dce_conn->terminate = talloc_strdup(dce_conn, reason);
2464 if (dce_conn->terminate == NULL) {
2465 dce_conn->terminate = "dcesrv: deferred terminating connection - no memory";
2467 DLIST_ADD_END(dce_ctx->broken_connections, dce_conn);
2470 _PUBLIC_ void dcesrv_cleanup_broken_connections(struct dcesrv_context *dce_ctx)
2472 struct dcesrv_connection *cur, *next;
2474 next = dce_ctx->broken_connections;
2475 while (next != NULL) {
2476 cur = next;
2477 next = cur->next;
2479 if (cur->state_flags & DCESRV_CALL_STATE_FLAG_PROCESS_PENDING_CALL) {
2480 struct dcesrv_connection_context *context_cur, *context_next;
2482 context_next = cur->contexts;
2483 while (context_next != NULL) {
2484 context_cur = context_next;
2485 context_next = context_cur->next;
2487 dcesrv_connection_context_destructor(context_cur);
2491 dcesrv_terminate_connection(cur, cur->terminate);
2495 /* We need this include to be able to compile on some plateforms
2496 * (ie. freebsd 7.2) as it seems that <sys/uio.h> is not included
2497 * correctly.
2498 * It has to be that deep because otherwise we have a conflict on
2499 * const struct dcesrv_interface declaration.
2500 * This is mostly due to socket_wrapper defining #define bind swrap_bind
2501 * which conflict with the bind used before.
2503 #include "system/network.h"
2505 struct dcesrv_sock_reply_state {
2506 struct dcesrv_connection *dce_conn;
2507 struct dcesrv_call_state *call;
2508 struct iovec iov;
2511 static void dcesrv_sock_reply_done(struct tevent_req *subreq);
2512 static void dcesrv_call_terminate_step1(struct tevent_req *subreq);
2514 _PUBLIC_ void dcesrv_sock_report_output_data(struct dcesrv_connection *dce_conn)
2516 struct dcesrv_call_state *call;
2518 call = dce_conn->call_list;
2519 if (!call || !call->replies) {
2520 return;
2523 while (call->replies) {
2524 struct data_blob_list_item *rep = call->replies;
2525 struct dcesrv_sock_reply_state *substate;
2526 struct tevent_req *subreq;
2528 substate = talloc_zero(call, struct dcesrv_sock_reply_state);
2529 if (!substate) {
2530 dcesrv_terminate_connection(dce_conn, "no memory");
2531 return;
2534 substate->dce_conn = dce_conn;
2535 substate->call = NULL;
2537 DLIST_REMOVE(call->replies, rep);
2539 if (call->replies == NULL && call->terminate_reason == NULL) {
2540 substate->call = call;
2543 substate->iov.iov_base = (void *) rep->blob.data;
2544 substate->iov.iov_len = rep->blob.length;
2546 subreq = tstream_writev_queue_send(substate,
2547 dce_conn->event_ctx,
2548 dce_conn->stream,
2549 dce_conn->send_queue,
2550 &substate->iov, 1);
2551 if (!subreq) {
2552 dcesrv_terminate_connection(dce_conn, "no memory");
2553 return;
2555 tevent_req_set_callback(subreq, dcesrv_sock_reply_done,
2556 substate);
2559 if (call->terminate_reason != NULL) {
2560 struct tevent_req *subreq;
2562 subreq = tevent_queue_wait_send(call,
2563 dce_conn->event_ctx,
2564 dce_conn->send_queue);
2565 if (!subreq) {
2566 dcesrv_terminate_connection(dce_conn, __location__);
2567 return;
2569 tevent_req_set_callback(subreq, dcesrv_call_terminate_step1,
2570 call);
2573 DLIST_REMOVE(call->conn->call_list, call);
2574 call->list = DCESRV_LIST_NONE;
2577 static void dcesrv_sock_reply_done(struct tevent_req *subreq)
2579 struct dcesrv_sock_reply_state *substate = tevent_req_callback_data(subreq,
2580 struct dcesrv_sock_reply_state);
2581 int ret;
2582 int sys_errno;
2583 NTSTATUS status;
2584 struct dcesrv_call_state *call = substate->call;
2586 ret = tstream_writev_queue_recv(subreq, &sys_errno);
2587 TALLOC_FREE(subreq);
2588 if (ret == -1) {
2589 status = map_nt_error_from_unix_common(sys_errno);
2590 dcesrv_terminate_connection(substate->dce_conn, nt_errstr(status));
2591 return;
2594 talloc_free(substate);
2595 if (call) {
2596 talloc_free(call);
2600 static void dcesrv_call_terminate_step2(struct tevent_req *subreq);
2602 static void dcesrv_call_terminate_step1(struct tevent_req *subreq)
2604 struct dcesrv_call_state *call = tevent_req_callback_data(subreq,
2605 struct dcesrv_call_state);
2606 bool ok;
2607 struct timeval tv;
2609 /* make sure we stop send queue before removing subreq */
2610 tevent_queue_stop(call->conn->send_queue);
2612 ok = tevent_queue_wait_recv(subreq);
2613 TALLOC_FREE(subreq);
2614 if (!ok) {
2615 dcesrv_terminate_connection(call->conn, __location__);
2616 return;
2619 /* disconnect after 200 usecs */
2620 tv = timeval_current_ofs_usec(200);
2621 subreq = tevent_wakeup_send(call, call->conn->event_ctx, tv);
2622 if (subreq == NULL) {
2623 dcesrv_terminate_connection(call->conn, __location__);
2624 return;
2626 tevent_req_set_callback(subreq, dcesrv_call_terminate_step2,
2627 call);
2630 static void dcesrv_call_terminate_step2(struct tevent_req *subreq)
2632 struct dcesrv_call_state *call = tevent_req_callback_data(subreq,
2633 struct dcesrv_call_state);
2634 bool ok;
2636 ok = tevent_wakeup_recv(subreq);
2637 TALLOC_FREE(subreq);
2638 if (!ok) {
2639 dcesrv_terminate_connection(call->conn, __location__);
2640 return;
2643 dcesrv_terminate_connection(call->conn, call->terminate_reason);
2646 static void dcesrv_conn_wait_done(struct tevent_req *subreq);
2648 static void dcesrv_read_fragment_done(struct tevent_req *subreq)
2650 struct dcesrv_connection *dce_conn = tevent_req_callback_data(subreq,
2651 struct dcesrv_connection);
2652 struct dcesrv_context *dce_ctx = dce_conn->dce_ctx;
2653 struct ncacn_packet *pkt;
2654 DATA_BLOB buffer;
2655 NTSTATUS status;
2657 if (dce_conn->terminate) {
2659 * if the current connection is broken
2660 * we need to clean it up before any other connection
2662 dcesrv_terminate_connection(dce_conn, dce_conn->terminate);
2663 dcesrv_cleanup_broken_connections(dce_ctx);
2664 return;
2667 dcesrv_cleanup_broken_connections(dce_ctx);
2669 status = dcerpc_read_ncacn_packet_recv(subreq, dce_conn,
2670 &pkt, &buffer);
2671 TALLOC_FREE(subreq);
2672 if (!NT_STATUS_IS_OK(status)) {
2673 dcesrv_terminate_connection(dce_conn, nt_errstr(status));
2674 return;
2677 status = dcesrv_process_ncacn_packet(dce_conn, pkt, buffer);
2678 if (!NT_STATUS_IS_OK(status)) {
2679 dcesrv_terminate_connection(dce_conn, nt_errstr(status));
2680 return;
2684 * This is used to block the connection during
2685 * pending authentication.
2687 if (dce_conn->wait_send != NULL) {
2688 subreq = dce_conn->wait_send(dce_conn,
2689 dce_conn->event_ctx,
2690 dce_conn->wait_private);
2691 if (!subreq) {
2692 status = NT_STATUS_NO_MEMORY;
2693 dcesrv_terminate_connection(dce_conn, nt_errstr(status));
2694 return;
2696 tevent_req_set_callback(subreq, dcesrv_conn_wait_done, dce_conn);
2697 return;
2700 subreq = dcerpc_read_ncacn_packet_send(dce_conn,
2701 dce_conn->event_ctx,
2702 dce_conn->stream);
2703 if (!subreq) {
2704 status = NT_STATUS_NO_MEMORY;
2705 dcesrv_terminate_connection(dce_conn, nt_errstr(status));
2706 return;
2708 tevent_req_set_callback(subreq, dcesrv_read_fragment_done, dce_conn);
2711 static void dcesrv_conn_wait_done(struct tevent_req *subreq)
2713 struct dcesrv_connection *dce_conn = tevent_req_callback_data(subreq,
2714 struct dcesrv_connection);
2715 struct dcesrv_context *dce_ctx = dce_conn->dce_ctx;
2716 NTSTATUS status;
2718 if (dce_conn->terminate) {
2720 * if the current connection is broken
2721 * we need to clean it up before any other connection
2723 dcesrv_terminate_connection(dce_conn, dce_conn->terminate);
2724 dcesrv_cleanup_broken_connections(dce_ctx);
2725 return;
2728 dcesrv_cleanup_broken_connections(dce_ctx);
2730 status = dce_conn->wait_recv(subreq);
2731 dce_conn->wait_send = NULL;
2732 dce_conn->wait_recv = NULL;
2733 dce_conn->wait_private = NULL;
2734 TALLOC_FREE(subreq);
2735 if (!NT_STATUS_IS_OK(status)) {
2736 dcesrv_terminate_connection(dce_conn, nt_errstr(status));
2737 return;
2740 status = dcesrv_connection_loop_start(dce_conn);
2741 if (!NT_STATUS_IS_OK(status)) {
2742 dcesrv_terminate_connection(dce_conn, nt_errstr(status));
2743 return;
2748 * retrieve credentials from a dce_call
2750 _PUBLIC_ struct cli_credentials *dcesrv_call_credentials(struct dcesrv_call_state *dce_call)
2752 struct dcesrv_auth *auth = dce_call->auth_state;
2753 SMB_ASSERT(auth->auth_finished);
2754 return auth->session_info->credentials;
2758 * returns true if this is an authenticated call
2760 _PUBLIC_ bool dcesrv_call_authenticated(struct dcesrv_call_state *dce_call)
2762 struct dcesrv_auth *auth = dce_call->auth_state;
2763 enum security_user_level level;
2764 SMB_ASSERT(auth->auth_finished);
2765 level = security_session_user_level(auth->session_info, NULL);
2766 return level >= SECURITY_USER;
2770 * retrieve account_name for a dce_call
2772 _PUBLIC_ const char *dcesrv_call_account_name(struct dcesrv_call_state *dce_call)
2774 struct dcesrv_auth *auth = dce_call->auth_state;
2775 SMB_ASSERT(auth->auth_finished);
2776 return auth->session_info->info->account_name;
2780 * retrieve session_info from a dce_call
2782 _PUBLIC_ struct auth_session_info *dcesrv_call_session_info(struct dcesrv_call_state *dce_call)
2784 struct dcesrv_auth *auth = dce_call->auth_state;
2785 SMB_ASSERT(auth->auth_finished);
2786 return auth->session_info;
2790 * retrieve auth type/level from a dce_call
2792 _PUBLIC_ void dcesrv_call_auth_info(struct dcesrv_call_state *dce_call,
2793 enum dcerpc_AuthType *auth_type,
2794 enum dcerpc_AuthLevel *auth_level)
2796 struct dcesrv_auth *auth = dce_call->auth_state;
2798 SMB_ASSERT(auth->auth_finished);
2800 if (auth_type != NULL) {
2801 *auth_type = auth->auth_type;
2803 if (auth_level != NULL) {
2804 *auth_level = auth->auth_level;
2808 _PUBLIC_ NTSTATUS dcesrv_connection_loop_start(struct dcesrv_connection *conn)
2810 struct tevent_req *subreq;
2812 subreq = dcerpc_read_ncacn_packet_send(conn,
2813 conn->event_ctx,
2814 conn->stream);
2815 if (subreq == NULL) {
2816 return NT_STATUS_NO_MEMORY;
2818 tevent_req_set_callback(subreq, dcesrv_read_fragment_done, conn);
2820 return NT_STATUS_OK;