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/>.
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 #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
;
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");
68 if (strcasecmp(e1
, e2
) != 0) {
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
)) {
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
,
98 struct dcesrv_connection_context
*c
;
99 for (c
=conn
->contexts
;c
;c
=c
->next
) {
100 if (c
->context_id
== context_id
) return c
;
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
)) {
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
)) {
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
) {
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
,
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
;
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
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
));
224 transport
= dcerpc_binding_get_transport(binding
);
225 if (transport
== NCACN_IP_TCP
) {
230 * First check if there is already a port specified, eg
231 * for epmapper on ncacn_ip_tcp:[135]
234 = dcerpc_binding_get_string_option(binding
,
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
246 if (port
== 0 && !use_single_process
) {
247 port
= lpcfg_rpc_server_port(dce_ctx
->lp_ctx
);
250 snprintf(port_str
, sizeof(port_str
), "%u", port
);
251 status
= dcerpc_binding_set_string_option(binding
,
254 if (!NT_STATUS_IS_OK(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
,
267 if (!NT_STATUS_IS_OK(status
)) {
268 DEBUG(0, ("Trouble parsing 2nd binding string '%s'\n",
269 ncacn_np_secondary_endpoint
));
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
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
) {
310 if (NT_STATUS_EQUAL(status
, NT_STATUS_NOT_FOUND
) || add_ep
) {
311 ep
= talloc_zero(dce_ctx
, struct dcesrv_endpoint
);
313 return NT_STATUS_NO_MEMORY
;
316 ep
->ep_description
= talloc_move(ep
, &binding
);
317 ep
->ep_2nd_description
= talloc_move(ep
, &binding2
);
320 /* add mgmt interface */
321 ifl
= talloc_zero(ep
, struct dcesrv_if_list
);
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
) {
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
));
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
);
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
,
361 sizeof(struct dcesrv_interface
));
362 if (ifl
->iface
== NULL
) {
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
371 /* if there's currently no security descriptor given on the endpoint
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
);
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 */
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";
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
);
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
;
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
;
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
)) {
485 session_key
->length
= MIN(session_key
->length
, 16);
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
);
504 auth
->session_key_fn
= dcesrv_remote_session_key
;
507 case NCACN_UNIX_STREAM
:
508 auth
->session_key_fn
= dcesrv_local_fixed_session_key
;
512 * All other's get a NULL pointer, which
513 * results in NT_STATUS_NO_USER_SESSION_KEY
522 connect to a dcerpc endpoint
524 _PUBLIC_ NTSTATUS
dcesrv_endpoint_connect(struct dcesrv_context
*dce_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
;
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
;
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
,
557 p
->max_auth_states
= lpcfg_parm_ulong(dce_ctx
->lp_ctx
,
563 auth
= dcesrv_auth_create(p
);
566 return NT_STATUS_NO_MEMORY
;
569 auth
->session_info
= talloc_reference(auth
, session_info
);
570 if (auth
->session_info
== NULL
) {
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
;
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
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
:
597 case DCESRV_LIST_CALL_LIST
:
598 DLIST_REMOVE(call
->conn
->call_list
, call
);
600 case DCESRV_LIST_FRAGMENTED_CALL_LIST
:
601 DLIST_REMOVE(call
->conn
->incoming_fragmented_call_list
, call
);
603 case DCESRV_LIST_PENDING_CALL_LIST
:
604 DLIST_REMOVE(call
->conn
->pending_call_list
, call
);
609 case DCESRV_LIST_NONE
:
611 case DCESRV_LIST_CALL_LIST
:
612 DLIST_ADD_END(call
->conn
->call_list
, call
);
614 case DCESRV_LIST_FRAGMENTED_CALL_LIST
:
615 DLIST_ADD_END(call
->conn
->incoming_fragmented_call_list
, call
);
617 case DCESRV_LIST_PENDING_CALL_LIST
:
618 DLIST_ADD_END(call
->conn
->pending_call_list
, call
);
623 static void dcesrv_call_disconnect_after(struct dcesrv_call_state
*call
,
626 struct dcesrv_auth
*a
= NULL
;
628 if (call
->conn
->terminate
!= NULL
) {
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
;
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
));
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
);
679 return NT_STATUS_NO_MEMORY
;
682 status
= dcerpc_ncacn_push_auth(&rep
->blob
, call
, &pkt
, NULL
);
683 if (!NT_STATUS_IS_OK(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
);
701 static NTSTATUS
dcesrv_fault_disconnect(struct dcesrv_call_state
*call
,
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
);
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;
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",
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
;
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
;
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;
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",
792 context
->allow_connect
);
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;
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",
817 context
->allow_connect
);
821 struct dcesrv_conn_auth_wait_context
{
822 struct tevent_req
*req
;
827 struct dcesrv_conn_auth_wait_state
{
831 static struct tevent_req
*dcesrv_conn_auth_wait_send(TALLOC_CTX
*mem_ctx
,
832 struct tevent_context
*ev
,
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
);
846 auth_wait
->req
= req
;
848 tevent_req_defer_callback(req
, ev
);
850 if (!auth_wait
->done
) {
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
;
886 static void dcesrv_conn_auth_wait_finished(struct dcesrv_connection
*conn
,
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
) {
900 if (tevent_req_nterror(auth_wait
->req
, status
)) {
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
;
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
;
930 status
= dcerpc_verify_ncacn_packet_header(&call
->pkt
,
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. */
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],
1008 if (ack_features
!= NULL
) {
1010 * Only one bind time feature context is allowed.
1012 return dcesrv_bind_nak(call
, 0);
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
)) {
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(
1111 if (endpoint
== NULL
) {
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
;
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
);
1159 status
= dcesrv_auth_reply(call
);
1160 dcesrv_conn_auth_wait_finished(conn
, status
);
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
;
1170 rep
= talloc_zero(call
, struct data_blob_list_item
);
1172 return NT_STATUS_NO_MEMORY
;
1175 status
= dcerpc_ncacn_push_auth(&rep
->blob
,
1178 call
->out_auth_info
);
1179 if (!NT_STATUS_IS_OK(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
;
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
,
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
1243 auth
->auth_invalid
= true;
1244 if (call
->fault_code
!= 0) {
1245 return dcesrv_fault_disconnect(call
, call
->fault_code
);
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
;
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
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
);
1291 dcesrv_conn_auth_wait_finished(conn
, NT_STATUS_OK
);
1296 * we don't send a reply to a auth3 request.
1299 dcesrv_conn_auth_wait_finished(conn
, NT_STATUS_OK
);
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
,
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
;
1316 const struct ndr_syntax_id
*selected_transfer
= NULL
;
1321 return NT_STATUS_INTERNAL_ERROR
;
1324 return NT_STATUS_INTERNAL_ERROR
;
1326 if (ctx
->num_transfer_syntaxes
< 1) {
1327 return NT_STATUS_INTERNAL_ERROR
;
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
;
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
);
1381 selected_transfer
= supported_transfer
;
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
);
1391 return NT_STATUS_RPC_PROTOCOL_ERROR
;
1394 if (selected_transfer
!= NULL
) {
1395 ok
= ndr_syntax_id_equal(&context
->transfer_syntax
,
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
)
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
,
1479 call
->conn
->preferred_transfer
);
1480 if (!NT_STATUS_IS_OK(status
)) {
1484 if (a
->result
== DCERPC_BIND_ACK_RESULT_ACCEPTANCE
) {
1486 * We managed to negotiate one context.
1490 validate_only
= true;
1494 preferred_ndr32
= ndr_syntax_id_equal(&ndr_transfer_syntax_ndr
,
1495 call
->conn
->preferred_transfer
);
1496 if (preferred_ndr32
) {
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
,
1513 &ndr_transfer_syntax_ndr
);
1514 if (!NT_STATUS_IS_OK(status
)) {
1518 if (a
->result
== DCERPC_BIND_ACK_RESULT_ACCEPTANCE
) {
1520 * We managed to negotiate one context.
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
;
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
;
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
,
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
);
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
)) {
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 */
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
;
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
);
1685 status
= dcesrv_auth_reply(call
);
1686 dcesrv_conn_auth_wait_finished(conn
, status
);
1691 possibly save the call for inspection with ndrdump
1693 static void dcesrv_save_call(struct dcesrv_call_state
*call
, const char *why
)
1697 const char *dump_dir
;
1698 dump_dir
= lpcfg_parm_string(call
->conn
->dce_ctx
->lp_ctx
, NULL
, "dcesrv", "stubs directory");
1702 fname
= talloc_asprintf(call
, "%s/RPC-%s-%u-%s.dat",
1704 call
->context
->iface
->name
,
1705 call
->pkt
.u
.request
.opnum
,
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
));
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
;
1730 SMB_ASSERT(call
->pkt
.ptype
== DCERPC_PKT_REQUEST
);
1732 ndr_err
= ndr_pop_dcerpc_sec_verification_trailer(call
->ndr_pull
,
1734 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
1735 status
= ndr_map_error2ntstatus(ndr_err
);
1739 ok
= dcerpc_sec_verification_trailer_check(vt
, &bitmask1
,
1740 &pcontext
, &header2
);
1742 status
= NT_STATUS_ACCESS_DENIED
;
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
;
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
:
1784 if (!call
->context
->allow_connect
) {
1787 addr
= tsocket_address_string(call
->conn
->remote_address
,
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
,
1796 derpc_transport_string_by_transport(transport
),
1798 return dcesrv_fault(call
, DCERPC_FAULT_ACCESS_DENIED
);
1803 if (auth
->auth_level
< call
->context
->min_auth_level
) {
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",
1812 call
->context
->min_auth_level
,
1813 call
->context
->iface
->name
,
1816 derpc_transport_string_by_transport(transport
),
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
;
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
);
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
,
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
);
1923 data_blob_free(&blob
);
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
);
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
;
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
) {
1966 if (a
->auth_type
!= auth_type
) {
1969 if (a
->auth_finished
&& a
->auth_level
!= auth_level
) {
1972 if (a
->auth_context_id
!= auth_context_id
) {
1976 DLIST_PROMOTE(dce_conn
->auth_states
, a
);
1977 call
->auth_state
= a
;
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
);
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
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
,
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.
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
);
2103 const struct dcerpc_request
*nr
= &call
->pkt
.u
.request
;
2104 const struct dcerpc_request
*er
= NULL
;
2107 existing
= dcesrv_find_fragmented_call(dce_conn
,
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
,
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
) {
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
,
2159 &call
->pkt
.u
.request
.stub_and_verifier
);
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
;
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
) {
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
);
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
);
2256 case DCERPC_PKT_AUTH3
:
2257 status
= dcesrv_auth3(call
);
2259 case DCERPC_PKT_ALTER
:
2260 status
= dcesrv_alter(call
);
2262 case DCERPC_PKT_REQUEST
:
2263 status
= dcesrv_request(call
);
2265 case DCERPC_PKT_CO_CANCEL
:
2266 case DCERPC_PKT_ORPHANED
:
2268 * Window just ignores CO_CANCEL and ORPHANED,
2271 status
= NT_STATUS_OK
;
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
:
2281 status
= dcesrv_fault_disconnect(call
, DCERPC_NCA_S_PROTO_ERROR
);
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
)) {
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
)
2302 struct dcesrv_context
*dce_ctx
;
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
;
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
]);
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
)));
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",
2372 return NT_STATUS_OBJECT_NAME_COLLISION
;
2375 ep_servers
= realloc_p(ep_servers
, struct ep_server
, num_ep_servers
+1);
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
);
2385 DEBUG(3,("DCERPC endpoint server '%s' registered\n",
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
)
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
;
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
);
2457 if (dce_conn
->terminate
!= NULL
) {
2461 DEBUG(3,("dcesrv: terminating connection due to '%s' deferred due to pending calls\n",
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
) {
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
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
;
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
) {
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
);
2530 dcesrv_terminate_connection(dce_conn
, "no memory");
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
,
2549 dce_conn
->send_queue
,
2552 dcesrv_terminate_connection(dce_conn
, "no memory");
2555 tevent_req_set_callback(subreq
, dcesrv_sock_reply_done
,
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
);
2566 dcesrv_terminate_connection(dce_conn
, __location__
);
2569 tevent_req_set_callback(subreq
, dcesrv_call_terminate_step1
,
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
);
2584 struct dcesrv_call_state
*call
= substate
->call
;
2586 ret
= tstream_writev_queue_recv(subreq
, &sys_errno
);
2587 TALLOC_FREE(subreq
);
2589 status
= map_nt_error_from_unix_common(sys_errno
);
2590 dcesrv_terminate_connection(substate
->dce_conn
, nt_errstr(status
));
2594 talloc_free(substate
);
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
);
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
);
2615 dcesrv_terminate_connection(call
->conn
, __location__
);
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__
);
2626 tevent_req_set_callback(subreq
, dcesrv_call_terminate_step2
,
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
);
2636 ok
= tevent_wakeup_recv(subreq
);
2637 TALLOC_FREE(subreq
);
2639 dcesrv_terminate_connection(call
->conn
, __location__
);
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
;
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
);
2667 dcesrv_cleanup_broken_connections(dce_ctx
);
2669 status
= dcerpc_read_ncacn_packet_recv(subreq
, dce_conn
,
2671 TALLOC_FREE(subreq
);
2672 if (!NT_STATUS_IS_OK(status
)) {
2673 dcesrv_terminate_connection(dce_conn
, nt_errstr(status
));
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
));
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
);
2692 status
= NT_STATUS_NO_MEMORY
;
2693 dcesrv_terminate_connection(dce_conn
, nt_errstr(status
));
2696 tevent_req_set_callback(subreq
, dcesrv_conn_wait_done
, dce_conn
);
2700 subreq
= dcerpc_read_ncacn_packet_send(dce_conn
,
2701 dce_conn
->event_ctx
,
2704 status
= NT_STATUS_NO_MEMORY
;
2705 dcesrv_terminate_connection(dce_conn
, nt_errstr(status
));
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
;
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
);
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
));
2740 status
= dcesrv_connection_loop_start(dce_conn
);
2741 if (!NT_STATUS_IS_OK(status
)) {
2742 dcesrv_terminate_connection(dce_conn
, nt_errstr(status
));
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
,
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
;