s4:rpc_server/remote: pass through DCERPC_PFC_FLAG_CONC_MPX if it was used by the...
[Samba.git] / source4 / rpc_server / dcerpc_server.c
blob9f6c8dc444d3e0a8c629b6a22456b6e3d910a326
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
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 3 of the License, or
12 (at your option) any later version.
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
19 You should have received a copy of the GNU General Public License
20 along with this program. If not, see <http://www.gnu.org/licenses/>.
23 #include "includes.h"
24 #include "auth/auth.h"
25 #include "auth/gensec/gensec.h"
26 #include "../lib/util/dlinklist.h"
27 #include "rpc_server/dcerpc_server.h"
28 #include "rpc_server/dcerpc_server_proto.h"
29 #include "rpc_server/common/proto.h"
30 #include "librpc/rpc/dcerpc_proto.h"
31 #include "system/filesys.h"
32 #include "libcli/security/security.h"
33 #include "param/param.h"
34 #include "../lib/tsocket/tsocket.h"
35 #include "../libcli/named_pipe_auth/npa_tstream.h"
36 #include "smbd/service_stream.h"
37 #include "../lib/tsocket/tsocket.h"
38 #include "lib/socket/socket.h"
39 #include "smbd/process_model.h"
40 #include "lib/messaging/irpc.h"
41 #include "librpc/rpc/rpc_common.h"
42 #include "lib/util/samba_modules.h"
43 #include "librpc/gen_ndr/ndr_dcerpc.h"
45 extern const struct dcesrv_interface dcesrv_mgmt_interface;
47 static NTSTATUS dcesrv_negotiate_contexts(struct dcesrv_call_state *call,
48 const struct dcerpc_bind *b,
49 struct dcerpc_ack_ctx *ack_ctx_list);
52 find an association group given a assoc_group_id
54 static struct dcesrv_assoc_group *dcesrv_assoc_group_find(struct dcesrv_context *dce_ctx,
55 uint32_t id)
57 void *id_ptr;
59 id_ptr = idr_find(dce_ctx->assoc_groups_idr, id);
60 if (id_ptr == NULL) {
61 return NULL;
63 return talloc_get_type_abort(id_ptr, struct dcesrv_assoc_group);
67 take a reference to an existing association group
69 static struct dcesrv_assoc_group *dcesrv_assoc_group_reference(TALLOC_CTX *mem_ctx,
70 struct dcesrv_context *dce_ctx,
71 uint32_t id)
73 struct dcesrv_assoc_group *assoc_group;
75 assoc_group = dcesrv_assoc_group_find(dce_ctx, id);
76 if (assoc_group == NULL) {
77 DEBUG(2,(__location__ ": Failed to find assoc_group 0x%08x\n", id));
78 return NULL;
80 return talloc_reference(mem_ctx, assoc_group);
83 static int dcesrv_assoc_group_destructor(struct dcesrv_assoc_group *assoc_group)
85 int ret;
86 ret = idr_remove(assoc_group->dce_ctx->assoc_groups_idr, assoc_group->id);
87 if (ret != 0) {
88 DEBUG(0,(__location__ ": Failed to remove assoc_group 0x%08x\n",
89 assoc_group->id));
91 return 0;
95 allocate a new association group
97 static struct dcesrv_assoc_group *dcesrv_assoc_group_new(TALLOC_CTX *mem_ctx,
98 struct dcesrv_context *dce_ctx)
100 struct dcesrv_assoc_group *assoc_group;
101 int id;
103 assoc_group = talloc_zero(mem_ctx, struct dcesrv_assoc_group);
104 if (assoc_group == NULL) {
105 return NULL;
108 id = idr_get_new_random(dce_ctx->assoc_groups_idr, assoc_group, UINT16_MAX);
109 if (id == -1) {
110 talloc_free(assoc_group);
111 DEBUG(0,(__location__ ": Out of association groups!\n"));
112 return NULL;
115 assoc_group->id = id;
116 assoc_group->dce_ctx = dce_ctx;
118 talloc_set_destructor(assoc_group, dcesrv_assoc_group_destructor);
120 return assoc_group;
125 see if two endpoints match
127 static bool endpoints_match(const struct dcerpc_binding *ep1,
128 const struct dcerpc_binding *ep2)
130 enum dcerpc_transport_t t1;
131 enum dcerpc_transport_t t2;
132 const char *e1;
133 const char *e2;
135 t1 = dcerpc_binding_get_transport(ep1);
136 t2 = dcerpc_binding_get_transport(ep2);
138 e1 = dcerpc_binding_get_string_option(ep1, "endpoint");
139 e2 = dcerpc_binding_get_string_option(ep2, "endpoint");
141 if (t1 != t2) {
142 return false;
145 if (!e1 || !e2) {
146 return e1 == e2;
149 if (strcasecmp(e1, e2) != 0) {
150 return false;
153 return true;
157 find an endpoint in the dcesrv_context
159 static struct dcesrv_endpoint *find_endpoint(struct dcesrv_context *dce_ctx,
160 const struct dcerpc_binding *ep_description)
162 struct dcesrv_endpoint *ep;
163 for (ep=dce_ctx->endpoint_list; ep; ep=ep->next) {
164 if (endpoints_match(ep->ep_description, ep_description)) {
165 return ep;
168 return NULL;
172 find a registered context_id from a bind or alter_context
174 static struct dcesrv_connection_context *dcesrv_find_context(struct dcesrv_connection *conn,
175 uint16_t context_id)
177 struct dcesrv_connection_context *c;
178 for (c=conn->contexts;c;c=c->next) {
179 if (c->context_id == context_id) return c;
181 return NULL;
185 see if a uuid and if_version match to an interface
187 static bool interface_match(const struct dcesrv_interface *if1,
188 const struct dcesrv_interface *if2)
190 return (if1->syntax_id.if_version == if2->syntax_id.if_version &&
191 GUID_equal(&if1->syntax_id.uuid, &if2->syntax_id.uuid));
195 find the interface operations on an endpoint
197 static const struct dcesrv_interface *find_interface(const struct dcesrv_endpoint *endpoint,
198 const struct dcesrv_interface *iface)
200 struct dcesrv_if_list *ifl;
201 for (ifl=endpoint->interface_list; ifl; ifl=ifl->next) {
202 if (interface_match(&(ifl->iface), iface)) {
203 return &(ifl->iface);
206 return NULL;
210 see if a uuid and if_version match to an interface
212 static bool interface_match_by_uuid(const struct dcesrv_interface *iface,
213 const struct GUID *uuid, uint32_t if_version)
215 return (iface->syntax_id.if_version == if_version &&
216 GUID_equal(&iface->syntax_id.uuid, uuid));
220 find the interface operations on an endpoint by uuid
222 static const struct dcesrv_interface *find_interface_by_uuid(const struct dcesrv_endpoint *endpoint,
223 const struct GUID *uuid, uint32_t if_version)
225 struct dcesrv_if_list *ifl;
226 for (ifl=endpoint->interface_list; ifl; ifl=ifl->next) {
227 if (interface_match_by_uuid(&(ifl->iface), uuid, if_version)) {
228 return &(ifl->iface);
231 return NULL;
235 find the earlier parts of a fragmented call awaiting reassembily
237 static struct dcesrv_call_state *dcesrv_find_fragmented_call(struct dcesrv_connection *dce_conn, uint16_t call_id)
239 struct dcesrv_call_state *c;
240 for (c=dce_conn->incoming_fragmented_call_list;c;c=c->next) {
241 if (c->pkt.call_id == call_id) {
242 return c;
245 return NULL;
249 register an interface on an endpoint
251 _PUBLIC_ NTSTATUS dcesrv_interface_register(struct dcesrv_context *dce_ctx,
252 const char *ep_name,
253 const struct dcesrv_interface *iface,
254 const struct security_descriptor *sd)
256 struct dcesrv_endpoint *ep;
257 struct dcesrv_if_list *ifl;
258 struct dcerpc_binding *binding;
259 bool add_ep = false;
260 NTSTATUS status;
262 status = dcerpc_parse_binding(dce_ctx, ep_name, &binding);
264 if (NT_STATUS_IS_ERR(status)) {
265 DEBUG(0, ("Trouble parsing binding string '%s'\n", ep_name));
266 return status;
269 /* check if this endpoint exists
271 if ((ep=find_endpoint(dce_ctx, binding))==NULL) {
272 ep = talloc_zero(dce_ctx, struct dcesrv_endpoint);
273 if (!ep) {
274 return NT_STATUS_NO_MEMORY;
276 ZERO_STRUCTP(ep);
277 ep->ep_description = talloc_move(ep, &binding);
278 add_ep = true;
280 /* add mgmt interface */
281 ifl = talloc_zero(ep, struct dcesrv_if_list);
282 if (!ifl) {
283 return NT_STATUS_NO_MEMORY;
286 memcpy(&(ifl->iface), &dcesrv_mgmt_interface,
287 sizeof(struct dcesrv_interface));
289 DLIST_ADD(ep->interface_list, ifl);
292 /* see if the interface is already registered on te endpoint */
293 if (find_interface(ep, iface)!=NULL) {
294 DEBUG(0,("dcesrv_interface_register: interface '%s' already registered on endpoint '%s'\n",
295 iface->name, ep_name));
296 return NT_STATUS_OBJECT_NAME_COLLISION;
299 /* talloc a new interface list element */
300 ifl = talloc_zero(ep, struct dcesrv_if_list);
301 if (!ifl) {
302 return NT_STATUS_NO_MEMORY;
305 /* copy the given interface struct to the one on the endpoints interface list */
306 memcpy(&(ifl->iface),iface, sizeof(struct dcesrv_interface));
308 /* if we have a security descriptor given,
309 * we should see if we can set it up on the endpoint
311 if (sd != NULL) {
312 /* if there's currently no security descriptor given on the endpoint
313 * we try to set it
315 if (ep->sd == NULL) {
316 ep->sd = security_descriptor_copy(ep, sd);
319 /* if now there's no security descriptor given on the endpoint
320 * something goes wrong, either we failed to copy the security descriptor
321 * or there was already one on the endpoint
323 if (ep->sd != NULL) {
324 DEBUG(0,("dcesrv_interface_register: interface '%s' failed to setup a security descriptor\n"
325 " on endpoint '%s'\n",
326 iface->name, ep_name));
327 if (add_ep) free(ep);
328 free(ifl);
329 return NT_STATUS_OBJECT_NAME_COLLISION;
333 /* finally add the interface on the endpoint */
334 DLIST_ADD(ep->interface_list, ifl);
336 /* if it's a new endpoint add it to the dcesrv_context */
337 if (add_ep) {
338 DLIST_ADD(dce_ctx->endpoint_list, ep);
341 DEBUG(4,("dcesrv_interface_register: interface '%s' registered on endpoint '%s'\n",
342 iface->name, ep_name));
344 return NT_STATUS_OK;
347 NTSTATUS dcesrv_inherited_session_key(struct dcesrv_connection *p,
348 DATA_BLOB *session_key)
350 if (p->auth_state.session_info->session_key.length) {
351 *session_key = p->auth_state.session_info->session_key;
352 return NT_STATUS_OK;
354 return NT_STATUS_NO_USER_SESSION_KEY;
358 fetch the user session key - may be default (above) or the SMB session key
360 The key is always truncated to 16 bytes
362 _PUBLIC_ NTSTATUS dcesrv_fetch_session_key(struct dcesrv_connection *p,
363 DATA_BLOB *session_key)
365 NTSTATUS status = p->auth_state.session_key(p, session_key);
366 if (!NT_STATUS_IS_OK(status)) {
367 return status;
370 session_key->length = MIN(session_key->length, 16);
372 return NT_STATUS_OK;
376 connect to a dcerpc endpoint
378 _PUBLIC_ NTSTATUS dcesrv_endpoint_connect(struct dcesrv_context *dce_ctx,
379 TALLOC_CTX *mem_ctx,
380 const struct dcesrv_endpoint *ep,
381 struct auth_session_info *session_info,
382 struct tevent_context *event_ctx,
383 struct imessaging_context *msg_ctx,
384 struct server_id server_id,
385 uint32_t state_flags,
386 struct dcesrv_connection **_p)
388 struct dcesrv_connection *p;
390 if (!session_info) {
391 return NT_STATUS_ACCESS_DENIED;
394 p = talloc_zero(mem_ctx, struct dcesrv_connection);
395 NT_STATUS_HAVE_NO_MEMORY(p);
397 if (!talloc_reference(p, session_info)) {
398 talloc_free(p);
399 return NT_STATUS_NO_MEMORY;
402 p->dce_ctx = dce_ctx;
403 p->endpoint = ep;
404 p->packet_log_dir = lpcfg_lock_directory(dce_ctx->lp_ctx);
405 p->auth_state.session_info = session_info;
406 p->auth_state.session_key = dcesrv_generic_session_key;
407 p->event_ctx = event_ctx;
408 p->msg_ctx = msg_ctx;
409 p->server_id = server_id;
410 p->state_flags = state_flags;
411 p->allow_bind = true;
412 p->max_recv_frag = 5840;
413 p->max_xmit_frag = 5840;
414 p->max_total_request_size = DCERPC_NCACN_REQUEST_DEFAULT_MAX_SIZE;
417 * For now we only support NDR32.
419 p->preferred_transfer = &ndr_transfer_syntax_ndr;
421 *_p = p;
422 return NT_STATUS_OK;
426 move a call from an existing linked list to the specified list. This
427 prevents bugs where we forget to remove the call from a previous
428 list when moving it.
430 static void dcesrv_call_set_list(struct dcesrv_call_state *call,
431 enum dcesrv_call_list list)
433 switch (call->list) {
434 case DCESRV_LIST_NONE:
435 break;
436 case DCESRV_LIST_CALL_LIST:
437 DLIST_REMOVE(call->conn->call_list, call);
438 break;
439 case DCESRV_LIST_FRAGMENTED_CALL_LIST:
440 DLIST_REMOVE(call->conn->incoming_fragmented_call_list, call);
441 break;
442 case DCESRV_LIST_PENDING_CALL_LIST:
443 DLIST_REMOVE(call->conn->pending_call_list, call);
444 break;
446 call->list = list;
447 switch (list) {
448 case DCESRV_LIST_NONE:
449 break;
450 case DCESRV_LIST_CALL_LIST:
451 DLIST_ADD_END(call->conn->call_list, call);
452 break;
453 case DCESRV_LIST_FRAGMENTED_CALL_LIST:
454 DLIST_ADD_END(call->conn->incoming_fragmented_call_list, call);
455 break;
456 case DCESRV_LIST_PENDING_CALL_LIST:
457 DLIST_ADD_END(call->conn->pending_call_list, call);
458 break;
462 static void dcesrv_call_disconnect_after(struct dcesrv_call_state *call,
463 const char *reason)
465 if (call->conn->terminate != NULL) {
466 return;
469 call->conn->allow_bind = false;
470 call->conn->allow_alter = false;
471 call->conn->allow_auth3 = false;
472 call->conn->allow_request = false;
474 call->terminate_reason = talloc_strdup(call, reason);
475 if (call->terminate_reason == NULL) {
476 call->terminate_reason = __location__;
481 return a dcerpc bind_nak
483 static NTSTATUS dcesrv_bind_nak(struct dcesrv_call_state *call, uint32_t reason)
485 struct ncacn_packet pkt;
486 struct dcerpc_bind_nak_version version;
487 struct data_blob_list_item *rep;
488 NTSTATUS status;
489 static const uint8_t _pad[3] = { 0, };
492 * We add the call to the pending_call_list
493 * in order to defer the termination.
495 dcesrv_call_disconnect_after(call, "dcesrv_bind_nak");
497 /* setup a bind_nak */
498 dcesrv_init_hdr(&pkt, lpcfg_rpc_big_endian(call->conn->dce_ctx->lp_ctx));
499 pkt.auth_length = 0;
500 pkt.call_id = call->pkt.call_id;
501 pkt.ptype = DCERPC_PKT_BIND_NAK;
502 pkt.pfc_flags = DCERPC_PFC_FLAG_FIRST | DCERPC_PFC_FLAG_LAST;
503 pkt.u.bind_nak.reject_reason = reason;
504 version.rpc_vers = 5;
505 version.rpc_vers_minor = 0;
506 pkt.u.bind_nak.num_versions = 1;
507 pkt.u.bind_nak.versions = &version;
508 pkt.u.bind_nak._pad = data_blob_const(_pad, sizeof(_pad));
510 rep = talloc_zero(call, struct data_blob_list_item);
511 if (!rep) {
512 return NT_STATUS_NO_MEMORY;
515 status = ncacn_push_auth(&rep->blob, call, &pkt, NULL);
516 if (!NT_STATUS_IS_OK(status)) {
517 return status;
520 dcerpc_set_frag_length(&rep->blob, rep->blob.length);
522 DLIST_ADD_END(call->replies, rep);
523 dcesrv_call_set_list(call, DCESRV_LIST_CALL_LIST);
525 if (call->conn->call_list && call->conn->call_list->replies) {
526 if (call->conn->transport.report_output_data) {
527 call->conn->transport.report_output_data(call->conn);
531 return NT_STATUS_OK;
534 static NTSTATUS dcesrv_fault_disconnect(struct dcesrv_call_state *call,
535 uint32_t fault_code)
538 * We add the call to the pending_call_list
539 * in order to defer the termination.
541 dcesrv_call_disconnect_after(call, "dcesrv_fault_disconnect");
543 return dcesrv_fault_with_flags(call, fault_code,
544 DCERPC_PFC_FLAG_DID_NOT_EXECUTE);
547 static int dcesrv_connection_context_destructor(struct dcesrv_connection_context *c)
549 DLIST_REMOVE(c->conn->contexts, c);
551 if (c->iface && c->iface->unbind) {
552 c->iface->unbind(c, c->iface);
553 c->iface = NULL;
556 return 0;
559 static void dcesrv_prepare_context_auth(struct dcesrv_call_state *dce_call)
561 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
562 const struct dcesrv_endpoint *endpoint = dce_call->conn->endpoint;
563 enum dcerpc_transport_t transport =
564 dcerpc_binding_get_transport(endpoint->ep_description);
565 struct dcesrv_connection_context *context = dce_call->context;
566 const struct dcesrv_interface *iface = context->iface;
568 context->min_auth_level = DCERPC_AUTH_LEVEL_NONE;
570 if (transport == NCALRPC) {
571 context->allow_connect = true;
572 return;
576 * allow overwrite per interface
577 * allow dcerpc auth level connect:<interface>
579 context->allow_connect = lpcfg_allow_dcerpc_auth_level_connect(lp_ctx);
580 context->allow_connect = lpcfg_parm_bool(lp_ctx, NULL,
581 "allow dcerpc auth level connect",
582 iface->name,
583 context->allow_connect);
586 NTSTATUS dcesrv_interface_bind_require_integrity(struct dcesrv_call_state *dce_call,
587 const struct dcesrv_interface *iface)
589 if (dce_call->context == NULL) {
590 return NT_STATUS_INTERNAL_ERROR;
594 * For connection oriented DCERPC DCERPC_AUTH_LEVEL_PACKET (4)
595 * has the same behavior as DCERPC_AUTH_LEVEL_INTEGRITY (5).
597 dce_call->context->min_auth_level = DCERPC_AUTH_LEVEL_PACKET;
598 return NT_STATUS_OK;
601 NTSTATUS dcesrv_interface_bind_require_privacy(struct dcesrv_call_state *dce_call,
602 const struct dcesrv_interface *iface)
604 if (dce_call->context == NULL) {
605 return NT_STATUS_INTERNAL_ERROR;
608 dce_call->context->min_auth_level = DCERPC_AUTH_LEVEL_PRIVACY;
609 return NT_STATUS_OK;
612 _PUBLIC_ NTSTATUS dcesrv_interface_bind_reject_connect(struct dcesrv_call_state *dce_call,
613 const struct dcesrv_interface *iface)
615 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
616 const struct dcesrv_endpoint *endpoint = dce_call->conn->endpoint;
617 enum dcerpc_transport_t transport =
618 dcerpc_binding_get_transport(endpoint->ep_description);
619 struct dcesrv_connection_context *context = dce_call->context;
621 if (context == NULL) {
622 return NT_STATUS_INTERNAL_ERROR;
625 if (transport == NCALRPC) {
626 context->allow_connect = true;
627 return NT_STATUS_OK;
631 * allow overwrite per interface
632 * allow dcerpc auth level connect:<interface>
634 context->allow_connect = false;
635 context->allow_connect = lpcfg_parm_bool(lp_ctx, NULL,
636 "allow dcerpc auth level connect",
637 iface->name,
638 context->allow_connect);
639 return NT_STATUS_OK;
642 _PUBLIC_ NTSTATUS dcesrv_interface_bind_allow_connect(struct dcesrv_call_state *dce_call,
643 const struct dcesrv_interface *iface)
645 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
646 const struct dcesrv_endpoint *endpoint = dce_call->conn->endpoint;
647 enum dcerpc_transport_t transport =
648 dcerpc_binding_get_transport(endpoint->ep_description);
649 struct dcesrv_connection_context *context = dce_call->context;
651 if (context == NULL) {
652 return NT_STATUS_INTERNAL_ERROR;
655 if (transport == NCALRPC) {
656 context->allow_connect = true;
657 return NT_STATUS_OK;
661 * allow overwrite per interface
662 * allow dcerpc auth level connect:<interface>
664 context->allow_connect = true;
665 context->allow_connect = lpcfg_parm_bool(lp_ctx, NULL,
666 "allow dcerpc auth level connect",
667 iface->name,
668 context->allow_connect);
669 return NT_STATUS_OK;
673 handle a bind request
675 static NTSTATUS dcesrv_bind(struct dcesrv_call_state *call)
677 struct ncacn_packet pkt;
678 struct data_blob_list_item *rep;
679 NTSTATUS status;
680 uint32_t extra_flags = 0;
681 uint16_t max_req = 0;
682 uint16_t max_rep = 0;
683 const char *ep_prefix = "";
684 const char *endpoint = NULL;
685 struct dcerpc_ack_ctx *ack_ctx_list = NULL;
686 struct dcerpc_ack_ctx *ack_features = NULL;
687 size_t i;
689 status = dcerpc_verify_ncacn_packet_header(&call->pkt,
690 DCERPC_PKT_BIND,
691 call->pkt.u.bind.auth_info.length,
692 0, /* required flags */
693 DCERPC_PFC_FLAG_FIRST |
694 DCERPC_PFC_FLAG_LAST |
695 DCERPC_PFC_FLAG_SUPPORT_HEADER_SIGN |
696 0x08 | /* this is not defined, but should be ignored */
697 DCERPC_PFC_FLAG_CONC_MPX |
698 DCERPC_PFC_FLAG_DID_NOT_EXECUTE |
699 DCERPC_PFC_FLAG_MAYBE |
700 DCERPC_PFC_FLAG_OBJECT_UUID);
701 if (!NT_STATUS_IS_OK(status)) {
702 return dcesrv_bind_nak(call,
703 DCERPC_BIND_NAK_REASON_PROTOCOL_VERSION_NOT_SUPPORTED);
706 /* max_recv_frag and max_xmit_frag result always in the same value! */
707 max_req = MIN(call->pkt.u.bind.max_xmit_frag,
708 call->pkt.u.bind.max_recv_frag);
710 * The values are between 2048 and 5840 tested against Windows 2012R2
711 * via ncacn_ip_tcp on port 135.
713 max_req = MAX(2048, max_req);
714 max_rep = MIN(max_req, call->conn->max_recv_frag);
715 /* They are truncated to an 8 byte boundary. */
716 max_rep &= 0xFFF8;
718 /* max_recv_frag and max_xmit_frag result always in the same value! */
719 call->conn->max_recv_frag = max_rep;
720 call->conn->max_xmit_frag = max_rep;
723 if provided, check the assoc_group is valid
725 if (call->pkt.u.bind.assoc_group_id != 0) {
726 call->conn->assoc_group = dcesrv_assoc_group_reference(call->conn,
727 call->conn->dce_ctx,
728 call->pkt.u.bind.assoc_group_id);
729 } else {
730 call->conn->assoc_group = dcesrv_assoc_group_new(call->conn,
731 call->conn->dce_ctx);
733 if (call->conn->assoc_group == NULL) {
734 return dcesrv_bind_nak(call, 0);
737 if (call->pkt.u.bind.num_contexts < 1) {
738 return dcesrv_bind_nak(call, 0);
741 ack_ctx_list = talloc_zero_array(call, struct dcerpc_ack_ctx,
742 call->pkt.u.bind.num_contexts);
743 if (ack_ctx_list == NULL) {
744 return dcesrv_bind_nak(call, 0);
748 * Set some sane defaults (required by dcesrv_negotiate_contexts()/
749 * dcesrv_check_or_create_context()) and do some protocol validation
750 * and set sane defaults.
752 for (i = 0; i < call->pkt.u.bind.num_contexts; i++) {
753 const struct dcerpc_ctx_list *c = &call->pkt.u.bind.ctx_list[i];
754 struct dcerpc_ack_ctx *a = &ack_ctx_list[i];
755 bool is_feature = false;
756 uint64_t features = 0;
758 if (c->num_transfer_syntaxes == 0) {
759 return dcesrv_bind_nak(call, 0);
762 a->result = DCERPC_BIND_ACK_RESULT_PROVIDER_REJECTION;
763 a->reason.value = DCERPC_BIND_ACK_REASON_ABSTRACT_SYNTAX_NOT_SUPPORTED;
766 * It's only treated as bind time feature request, if the first
767 * transfer_syntax matches, all others are ignored.
769 is_feature = dcerpc_extract_bind_time_features(c->transfer_syntaxes[0],
770 &features);
771 if (!is_feature) {
772 continue;
775 if (ack_features != NULL) {
777 * Only one bind time feature context is allowed.
779 return dcesrv_bind_nak(call, 0);
781 ack_features = a;
783 a->result = DCERPC_BIND_ACK_RESULT_NEGOTIATE_ACK;
784 a->reason.negotiate = 0;
785 if (features & DCERPC_BIND_TIME_SECURITY_CONTEXT_MULTIPLEXING) {
786 /* not supported yet */
788 if (features & DCERPC_BIND_TIME_KEEP_CONNECTION_ON_ORPHAN) {
789 a->reason.negotiate |=
790 DCERPC_BIND_TIME_KEEP_CONNECTION_ON_ORPHAN;
793 call->conn->bind_time_features = a->reason.negotiate;
797 * Try to negotiate one new presentation context.
799 status = dcesrv_negotiate_contexts(call, &call->pkt.u.bind, ack_ctx_list);
800 if (NT_STATUS_EQUAL(status, NT_STATUS_RPC_PROTOCOL_ERROR)) {
801 return dcesrv_bind_nak(call, 0);
803 if (!NT_STATUS_IS_OK(status)) {
804 return status;
807 if ((call->pkt.pfc_flags & DCERPC_PFC_FLAG_CONC_MPX) &&
808 (call->state_flags & DCESRV_CALL_STATE_FLAG_MULTIPLEXED)) {
809 call->conn->state_flags |= DCESRV_CALL_STATE_FLAG_MULTIPLEXED;
810 extra_flags |= DCERPC_PFC_FLAG_CONC_MPX;
813 if (call->state_flags & DCESRV_CALL_STATE_FLAG_PROCESS_PENDING_CALL) {
814 call->conn->state_flags |= DCESRV_CALL_STATE_FLAG_PROCESS_PENDING_CALL;
817 /* handle any authentication that is being requested */
818 if (!dcesrv_auth_bind(call)) {
819 struct dcesrv_auth *auth = &call->conn->auth_state;
821 TALLOC_FREE(call->context);
823 if (auth->auth_level == DCERPC_AUTH_LEVEL_NONE) {
825 * With DCERPC_AUTH_LEVEL_NONE, we get the
826 * reject_reason in auth->auth_context_id.
828 return dcesrv_bind_nak(call, auth->auth_context_id);
832 * This must a be a temporary failure e.g. talloc or invalid
833 * configuration, e.g. no machine account.
835 return dcesrv_bind_nak(call,
836 DCERPC_BIND_NAK_REASON_TEMPORARY_CONGESTION);
839 /* setup a bind_ack */
840 dcesrv_init_hdr(&pkt, lpcfg_rpc_big_endian(call->conn->dce_ctx->lp_ctx));
841 pkt.auth_length = 0;
842 pkt.call_id = call->pkt.call_id;
843 pkt.ptype = DCERPC_PKT_BIND_ACK;
844 pkt.pfc_flags = DCERPC_PFC_FLAG_FIRST | DCERPC_PFC_FLAG_LAST | extra_flags;
845 pkt.u.bind_ack.max_xmit_frag = call->conn->max_xmit_frag;
846 pkt.u.bind_ack.max_recv_frag = call->conn->max_recv_frag;
847 pkt.u.bind_ack.assoc_group_id = call->conn->assoc_group->id;
849 endpoint = dcerpc_binding_get_string_option(
850 call->conn->endpoint->ep_description,
851 "endpoint");
852 if (endpoint == NULL) {
853 endpoint = "";
856 if (strncasecmp(endpoint, "\\pipe\\", 6) == 0) {
858 * TODO: check if this is really needed
860 * Or if we should fix this in our idl files.
862 ep_prefix = "\\PIPE\\";
863 endpoint += 6;
866 pkt.u.bind_ack.secondary_address = talloc_asprintf(call, "%s%s",
867 ep_prefix,
868 endpoint);
869 if (pkt.u.bind_ack.secondary_address == NULL) {
870 TALLOC_FREE(call->context);
871 return NT_STATUS_NO_MEMORY;
873 pkt.u.bind_ack.num_results = call->pkt.u.bind.num_contexts;
874 pkt.u.bind_ack.ctx_list = ack_ctx_list;
875 pkt.u.bind_ack.auth_info = data_blob_null;
877 status = dcesrv_auth_bind_ack(call, &pkt);
878 if (!NT_STATUS_IS_OK(status)) {
879 TALLOC_FREE(call->context);
880 return dcesrv_bind_nak(call, 0);
883 rep = talloc_zero(call, struct data_blob_list_item);
884 if (!rep) {
885 TALLOC_FREE(call->context);
886 return NT_STATUS_NO_MEMORY;
889 status = ncacn_push_auth(&rep->blob, call, &pkt,
890 call->out_auth_info);
891 if (!NT_STATUS_IS_OK(status)) {
892 TALLOC_FREE(call->context);
893 return status;
896 dcerpc_set_frag_length(&rep->blob, rep->blob.length);
898 DLIST_ADD_END(call->replies, rep);
899 dcesrv_call_set_list(call, DCESRV_LIST_CALL_LIST);
901 if (call->conn->call_list && call->conn->call_list->replies) {
902 if (call->conn->transport.report_output_data) {
903 call->conn->transport.report_output_data(call->conn);
907 return NT_STATUS_OK;
912 handle a auth3 request
914 static NTSTATUS dcesrv_auth3(struct dcesrv_call_state *call)
916 NTSTATUS status;
918 if (!call->conn->allow_auth3) {
919 return dcesrv_fault_disconnect(call, DCERPC_NCA_S_PROTO_ERROR);
922 if (call->conn->auth_state.auth_finished) {
923 return dcesrv_fault_disconnect(call, DCERPC_NCA_S_PROTO_ERROR);
926 status = dcerpc_verify_ncacn_packet_header(&call->pkt,
927 DCERPC_PKT_AUTH3,
928 call->pkt.u.auth3.auth_info.length,
929 0, /* required flags */
930 DCERPC_PFC_FLAG_FIRST |
931 DCERPC_PFC_FLAG_LAST |
932 DCERPC_PFC_FLAG_SUPPORT_HEADER_SIGN |
933 0x08 | /* this is not defined, but should be ignored */
934 DCERPC_PFC_FLAG_CONC_MPX |
935 DCERPC_PFC_FLAG_DID_NOT_EXECUTE |
936 DCERPC_PFC_FLAG_MAYBE |
937 DCERPC_PFC_FLAG_OBJECT_UUID);
938 if (!NT_STATUS_IS_OK(status)) {
939 return dcesrv_fault_disconnect(call, DCERPC_NCA_S_PROTO_ERROR);
942 /* handle the auth3 in the auth code */
943 if (!dcesrv_auth_auth3(call)) {
944 call->conn->auth_state.auth_invalid = true;
945 if (call->fault_code != 0) {
946 return dcesrv_fault_disconnect(call, call->fault_code);
950 talloc_free(call);
952 /* we don't send a reply to a auth3 request, except by a
953 fault */
954 return NT_STATUS_OK;
958 static NTSTATUS dcesrv_check_or_create_context(struct dcesrv_call_state *call,
959 const struct dcerpc_bind *b,
960 const struct dcerpc_ctx_list *ctx,
961 struct dcerpc_ack_ctx *ack,
962 bool validate_only,
963 const struct ndr_syntax_id *supported_transfer)
965 uint32_t if_version;
966 struct dcesrv_connection_context *context;
967 const struct dcesrv_interface *iface;
968 struct GUID uuid;
969 NTSTATUS status;
970 const struct ndr_syntax_id *selected_transfer = NULL;
971 size_t i;
972 bool ok;
974 if (b == NULL) {
975 return NT_STATUS_INTERNAL_ERROR;
977 if (ctx == NULL) {
978 return NT_STATUS_INTERNAL_ERROR;
980 if (ctx->num_transfer_syntaxes < 1) {
981 return NT_STATUS_INTERNAL_ERROR;
983 if (ack == NULL) {
984 return NT_STATUS_INTERNAL_ERROR;
986 if (supported_transfer == NULL) {
987 return NT_STATUS_INTERNAL_ERROR;
990 switch (ack->result) {
991 case DCERPC_BIND_ACK_RESULT_ACCEPTANCE:
992 case DCERPC_BIND_ACK_RESULT_NEGOTIATE_ACK:
994 * We is already completed.
996 return NT_STATUS_OK;
997 default:
998 break;
1001 ack->result = DCERPC_BIND_ACK_RESULT_PROVIDER_REJECTION;
1002 ack->reason.value = DCERPC_BIND_ACK_REASON_ABSTRACT_SYNTAX_NOT_SUPPORTED;
1004 if_version = ctx->abstract_syntax.if_version;
1005 uuid = ctx->abstract_syntax.uuid;
1007 iface = find_interface_by_uuid(call->conn->endpoint, &uuid, if_version);
1008 if (iface == NULL) {
1009 char *uuid_str = GUID_string(call, &uuid);
1010 DEBUG(2,("Request for unknown dcerpc interface %s/%d\n", uuid_str, if_version));
1011 talloc_free(uuid_str);
1013 * We report this only via ack->result
1015 return NT_STATUS_OK;
1018 ack->result = DCERPC_BIND_ACK_RESULT_PROVIDER_REJECTION;
1019 ack->reason.value = DCERPC_BIND_ACK_REASON_TRANSFER_SYNTAXES_NOT_SUPPORTED;
1021 if (validate_only) {
1023 * We report this only via ack->result
1025 return NT_STATUS_OK;
1028 for (i = 0; i < ctx->num_transfer_syntaxes; i++) {
1030 * we only do NDR encoded dcerpc for now.
1032 ok = ndr_syntax_id_equal(&ctx->transfer_syntaxes[i],
1033 supported_transfer);
1034 if (ok) {
1035 selected_transfer = supported_transfer;
1036 break;
1040 context = dcesrv_find_context(call->conn, ctx->context_id);
1041 if (context != NULL) {
1042 ok = ndr_syntax_id_equal(&context->iface->syntax_id,
1043 &ctx->abstract_syntax);
1044 if (!ok) {
1045 return NT_STATUS_RPC_PROTOCOL_ERROR;
1048 if (selected_transfer != NULL) {
1049 ok = ndr_syntax_id_equal(&context->transfer_syntax,
1050 selected_transfer);
1051 if (!ok) {
1052 return NT_STATUS_RPC_PROTOCOL_ERROR;
1055 ack->result = DCERPC_BIND_ACK_RESULT_ACCEPTANCE;
1056 ack->reason.value = DCERPC_BIND_ACK_REASON_NOT_SPECIFIED;
1057 ack->syntax = context->transfer_syntax;
1061 * We report this only via ack->result
1063 return NT_STATUS_OK;
1066 if (selected_transfer == NULL) {
1068 * We report this only via ack->result
1070 return NT_STATUS_OK;
1073 ack->result = DCERPC_BIND_ACK_RESULT_USER_REJECTION;
1074 ack->reason.value = DCERPC_BIND_ACK_REASON_LOCAL_LIMIT_EXCEEDED;
1076 /* add this context to the list of available context_ids */
1077 context = talloc_zero(call->conn, struct dcesrv_connection_context);
1078 if (context == NULL) {
1079 return NT_STATUS_NO_MEMORY;
1081 context->conn = call->conn;
1082 context->context_id = ctx->context_id;
1083 context->iface = iface;
1084 context->transfer_syntax = *selected_transfer;
1085 context->private_data = NULL;
1086 DLIST_ADD(call->conn->contexts, context);
1087 call->context = context;
1088 talloc_set_destructor(context, dcesrv_connection_context_destructor);
1090 dcesrv_prepare_context_auth(call);
1093 * Multiplex is supported by default
1095 call->state_flags |= DCESRV_CALL_STATE_FLAG_MULTIPLEXED;
1097 status = iface->bind(call, iface, if_version);
1098 call->context = NULL;
1099 if (!NT_STATUS_IS_OK(status)) {
1100 /* we don't want to trigger the iface->unbind() hook */
1101 context->iface = NULL;
1102 talloc_free(context);
1104 * We report this only via ack->result
1106 return NT_STATUS_OK;
1109 ack->result = DCERPC_BIND_ACK_RESULT_ACCEPTANCE;
1110 ack->reason.value = DCERPC_BIND_ACK_REASON_NOT_SPECIFIED;
1111 ack->syntax = context->transfer_syntax;
1112 return NT_STATUS_OK;
1115 static NTSTATUS dcesrv_negotiate_contexts(struct dcesrv_call_state *call,
1116 const struct dcerpc_bind *b,
1117 struct dcerpc_ack_ctx *ack_ctx_list)
1119 NTSTATUS status;
1120 size_t i;
1121 bool validate_only = false;
1122 bool preferred_ndr32;
1125 * Try to negotiate one new presentation context,
1126 * using our preferred transfer syntax.
1128 for (i = 0; i < b->num_contexts; i++) {
1129 const struct dcerpc_ctx_list *c = &b->ctx_list[i];
1130 struct dcerpc_ack_ctx *a = &ack_ctx_list[i];
1132 status = dcesrv_check_or_create_context(call, b, c, a,
1133 validate_only,
1134 call->conn->preferred_transfer);
1135 if (!NT_STATUS_IS_OK(status)) {
1136 return status;
1139 if (a->result == DCERPC_BIND_ACK_RESULT_ACCEPTANCE) {
1141 * We managed to negotiate one context.
1143 * => we're done.
1145 validate_only = true;
1149 preferred_ndr32 = ndr_syntax_id_equal(&ndr_transfer_syntax_ndr,
1150 call->conn->preferred_transfer);
1151 if (preferred_ndr32) {
1153 * We're done.
1155 return NT_STATUS_OK;
1159 * Try to negotiate one new presentation context,
1160 * using NDR 32 as fallback.
1162 for (i = 0; i < b->num_contexts; i++) {
1163 const struct dcerpc_ctx_list *c = &b->ctx_list[i];
1164 struct dcerpc_ack_ctx *a = &ack_ctx_list[i];
1166 status = dcesrv_check_or_create_context(call, b, c, a,
1167 validate_only,
1168 &ndr_transfer_syntax_ndr);
1169 if (!NT_STATUS_IS_OK(status)) {
1170 return status;
1173 if (a->result == DCERPC_BIND_ACK_RESULT_ACCEPTANCE) {
1175 * We managed to negotiate one context.
1177 * => we're done.
1179 validate_only = true;
1183 return NT_STATUS_OK;
1187 handle a alter context request
1189 static NTSTATUS dcesrv_alter(struct dcesrv_call_state *call)
1191 NTSTATUS status;
1192 bool auth_ok = false;
1193 struct ncacn_packet pkt;
1194 uint32_t extra_flags = 0;
1195 struct data_blob_list_item *rep = NULL;
1196 struct dcerpc_ack_ctx *ack_ctx_list = NULL;
1197 size_t i;
1199 if (!call->conn->allow_alter) {
1200 return dcesrv_fault_disconnect(call, DCERPC_NCA_S_PROTO_ERROR);
1203 status = dcerpc_verify_ncacn_packet_header(&call->pkt,
1204 DCERPC_PKT_ALTER,
1205 call->pkt.u.alter.auth_info.length,
1206 0, /* required flags */
1207 DCERPC_PFC_FLAG_FIRST |
1208 DCERPC_PFC_FLAG_LAST |
1209 DCERPC_PFC_FLAG_SUPPORT_HEADER_SIGN |
1210 0x08 | /* this is not defined, but should be ignored */
1211 DCERPC_PFC_FLAG_CONC_MPX |
1212 DCERPC_PFC_FLAG_DID_NOT_EXECUTE |
1213 DCERPC_PFC_FLAG_MAYBE |
1214 DCERPC_PFC_FLAG_OBJECT_UUID);
1215 if (!NT_STATUS_IS_OK(status)) {
1216 return dcesrv_fault_disconnect(call, DCERPC_NCA_S_PROTO_ERROR);
1219 auth_ok = dcesrv_auth_alter(call);
1220 if (!auth_ok) {
1221 if (call->fault_code != 0) {
1222 return dcesrv_fault_disconnect(call, call->fault_code);
1226 if (call->pkt.u.alter.num_contexts < 1) {
1227 return dcesrv_fault_disconnect(call, DCERPC_NCA_S_PROTO_ERROR);
1230 ack_ctx_list = talloc_zero_array(call, struct dcerpc_ack_ctx,
1231 call->pkt.u.alter.num_contexts);
1232 if (ack_ctx_list == NULL) {
1233 return NT_STATUS_NO_MEMORY;
1237 * Set some sane defaults (required by dcesrv_negotiate_contexts()/
1238 * dcesrv_check_or_create_context()) and do some protocol validation
1239 * and set sane defaults.
1241 for (i = 0; i < call->pkt.u.alter.num_contexts; i++) {
1242 const struct dcerpc_ctx_list *c = &call->pkt.u.alter.ctx_list[i];
1243 struct dcerpc_ack_ctx *a = &ack_ctx_list[i];
1245 if (c->num_transfer_syntaxes == 0) {
1246 return dcesrv_fault_disconnect(call,
1247 DCERPC_NCA_S_PROTO_ERROR);
1250 a->result = DCERPC_BIND_ACK_RESULT_PROVIDER_REJECTION;
1251 a->reason.value = DCERPC_BIND_ACK_REASON_ABSTRACT_SYNTAX_NOT_SUPPORTED;
1255 * Try to negotiate one new presentation context.
1257 status = dcesrv_negotiate_contexts(call, &call->pkt.u.alter, ack_ctx_list);
1258 if (NT_STATUS_EQUAL(status, NT_STATUS_RPC_PROTOCOL_ERROR)) {
1259 return dcesrv_fault_disconnect(call, DCERPC_NCA_S_PROTO_ERROR);
1261 if (!NT_STATUS_IS_OK(status)) {
1262 return status;
1265 if ((call->pkt.pfc_flags & DCERPC_PFC_FLAG_CONC_MPX) &&
1266 (call->state_flags & DCESRV_CALL_STATE_FLAG_MULTIPLEXED)) {
1267 call->conn->state_flags |= DCESRV_CALL_STATE_FLAG_MULTIPLEXED;
1268 extra_flags |= DCERPC_PFC_FLAG_CONC_MPX;
1271 if (call->state_flags & DCESRV_CALL_STATE_FLAG_PROCESS_PENDING_CALL) {
1272 call->conn->state_flags |= DCESRV_CALL_STATE_FLAG_PROCESS_PENDING_CALL;
1275 /* handle any authentication that is being requested */
1276 if (!auth_ok) {
1277 if (call->in_auth_info.auth_type !=
1278 call->conn->auth_state.auth_type)
1280 return dcesrv_fault_disconnect(call,
1281 DCERPC_FAULT_SEC_PKG_ERROR);
1283 return dcesrv_fault_disconnect(call, DCERPC_FAULT_ACCESS_DENIED);
1286 dcesrv_init_hdr(&pkt, lpcfg_rpc_big_endian(call->conn->dce_ctx->lp_ctx));
1287 pkt.auth_length = 0;
1288 pkt.call_id = call->pkt.call_id;
1289 pkt.ptype = DCERPC_PKT_ALTER_RESP;
1290 pkt.pfc_flags = DCERPC_PFC_FLAG_FIRST | DCERPC_PFC_FLAG_LAST | extra_flags;
1291 pkt.u.alter_resp.max_xmit_frag = call->conn->max_xmit_frag;
1292 pkt.u.alter_resp.max_recv_frag = call->conn->max_recv_frag;
1293 pkt.u.alter_resp.assoc_group_id = call->conn->assoc_group->id;
1294 pkt.u.alter_resp.secondary_address = "";
1295 pkt.u.alter_resp.num_results = call->pkt.u.alter.num_contexts;
1296 pkt.u.alter_resp.ctx_list = ack_ctx_list;
1297 pkt.u.alter_resp.auth_info = data_blob_null;
1299 status = dcesrv_auth_alter_ack(call, &pkt);
1300 if (!NT_STATUS_IS_OK(status)) {
1301 return dcesrv_fault_disconnect(call, DCERPC_FAULT_SEC_PKG_ERROR);
1304 rep = talloc_zero(call, struct data_blob_list_item);
1305 if (!rep) {
1306 return NT_STATUS_NO_MEMORY;
1309 status = ncacn_push_auth(&rep->blob, call, &pkt, call->out_auth_info);
1310 if (!NT_STATUS_IS_OK(status)) {
1311 return status;
1314 dcerpc_set_frag_length(&rep->blob, rep->blob.length);
1316 DLIST_ADD_END(call->replies, rep);
1317 dcesrv_call_set_list(call, DCESRV_LIST_CALL_LIST);
1319 if (call->conn->call_list && call->conn->call_list->replies) {
1320 if (call->conn->transport.report_output_data) {
1321 call->conn->transport.report_output_data(call->conn);
1325 return NT_STATUS_OK;
1329 possibly save the call for inspection with ndrdump
1331 static void dcesrv_save_call(struct dcesrv_call_state *call, const char *why)
1333 #ifdef DEVELOPER
1334 char *fname;
1335 const char *dump_dir;
1336 dump_dir = lpcfg_parm_string(call->conn->dce_ctx->lp_ctx, NULL, "dcesrv", "stubs directory");
1337 if (!dump_dir) {
1338 return;
1340 fname = talloc_asprintf(call, "%s/RPC-%s-%u-%s.dat",
1341 dump_dir,
1342 call->context->iface->name,
1343 call->pkt.u.request.opnum,
1344 why);
1345 if (file_save(fname, call->pkt.u.request.stub_and_verifier.data, call->pkt.u.request.stub_and_verifier.length)) {
1346 DEBUG(0,("RPC SAVED %s\n", fname));
1348 talloc_free(fname);
1349 #endif
1352 static NTSTATUS dcesrv_check_verification_trailer(struct dcesrv_call_state *call)
1354 TALLOC_CTX *frame = talloc_stackframe();
1355 const uint32_t bitmask1 = call->conn->auth_state.client_hdr_signing ?
1356 DCERPC_SEC_VT_CLIENT_SUPPORTS_HEADER_SIGNING : 0;
1357 const struct dcerpc_sec_vt_pcontext pcontext = {
1358 .abstract_syntax = call->context->iface->syntax_id,
1359 .transfer_syntax = call->context->transfer_syntax,
1361 const struct dcerpc_sec_vt_header2 header2 =
1362 dcerpc_sec_vt_header2_from_ncacn_packet(&call->pkt);
1363 enum ndr_err_code ndr_err;
1364 struct dcerpc_sec_verification_trailer *vt = NULL;
1365 NTSTATUS status = NT_STATUS_OK;
1366 bool ok;
1368 SMB_ASSERT(call->pkt.ptype == DCERPC_PKT_REQUEST);
1370 ndr_err = ndr_pop_dcerpc_sec_verification_trailer(call->ndr_pull,
1371 frame, &vt);
1372 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
1373 status = ndr_map_error2ntstatus(ndr_err);
1374 goto done;
1377 ok = dcerpc_sec_verification_trailer_check(vt, &bitmask1,
1378 &pcontext, &header2);
1379 if (!ok) {
1380 status = NT_STATUS_ACCESS_DENIED;
1381 goto done;
1383 done:
1384 TALLOC_FREE(frame);
1385 return status;
1389 handle a dcerpc request packet
1391 static NTSTATUS dcesrv_request(struct dcesrv_call_state *call)
1393 const struct dcesrv_endpoint *endpoint = call->conn->endpoint;
1394 enum dcerpc_transport_t transport =
1395 dcerpc_binding_get_transport(endpoint->ep_description);
1396 struct ndr_pull *pull;
1397 NTSTATUS status;
1399 if (!call->conn->allow_request) {
1400 return dcesrv_fault_disconnect(call, DCERPC_NCA_S_PROTO_ERROR);
1403 /* if authenticated, and the mech we use can't do async replies, don't use them... */
1404 if (call->conn->auth_state.gensec_security &&
1405 !gensec_have_feature(call->conn->auth_state.gensec_security, GENSEC_FEATURE_ASYNC_REPLIES)) {
1406 call->state_flags &= ~DCESRV_CALL_STATE_FLAG_MAY_ASYNC;
1409 if (call->context == NULL) {
1410 return dcesrv_fault_with_flags(call, DCERPC_NCA_S_UNKNOWN_IF,
1411 DCERPC_PFC_FLAG_DID_NOT_EXECUTE);
1414 switch (call->conn->auth_state.auth_level) {
1415 case DCERPC_AUTH_LEVEL_NONE:
1416 case DCERPC_AUTH_LEVEL_PACKET:
1417 case DCERPC_AUTH_LEVEL_INTEGRITY:
1418 case DCERPC_AUTH_LEVEL_PRIVACY:
1419 break;
1420 default:
1421 if (!call->context->allow_connect) {
1422 char *addr;
1424 addr = tsocket_address_string(call->conn->remote_address,
1425 call);
1427 DEBUG(2, ("%s: restrict auth_level_connect access "
1428 "to [%s] with auth[type=0x%x,level=0x%x] "
1429 "on [%s] from [%s]\n",
1430 __func__, call->context->iface->name,
1431 call->conn->auth_state.auth_type,
1432 call->conn->auth_state.auth_level,
1433 derpc_transport_string_by_transport(transport),
1434 addr));
1435 return dcesrv_fault(call, DCERPC_FAULT_ACCESS_DENIED);
1437 break;
1440 if (call->conn->auth_state.auth_level < call->context->min_auth_level) {
1441 char *addr;
1443 addr = tsocket_address_string(call->conn->remote_address, call);
1445 DEBUG(2, ("%s: restrict access by min_auth_level[0x%x] "
1446 "to [%s] with auth[type=0x%x,level=0x%x] "
1447 "on [%s] from [%s]\n",
1448 __func__,
1449 call->context->min_auth_level,
1450 call->context->iface->name,
1451 call->conn->auth_state.auth_type,
1452 call->conn->auth_state.auth_level,
1453 derpc_transport_string_by_transport(transport),
1454 addr));
1455 return dcesrv_fault(call, DCERPC_FAULT_ACCESS_DENIED);
1458 pull = ndr_pull_init_blob(&call->pkt.u.request.stub_and_verifier, call);
1459 NT_STATUS_HAVE_NO_MEMORY(pull);
1461 pull->flags |= LIBNDR_FLAG_REF_ALLOC;
1463 call->ndr_pull = pull;
1465 if (!(call->pkt.drep[0] & DCERPC_DREP_LE)) {
1466 pull->flags |= LIBNDR_FLAG_BIGENDIAN;
1469 status = dcesrv_check_verification_trailer(call);
1470 if (!NT_STATUS_IS_OK(status)) {
1471 uint32_t faultcode = DCERPC_FAULT_OTHER;
1472 if (NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
1473 faultcode = DCERPC_FAULT_ACCESS_DENIED;
1475 DEBUG(10, ("dcesrv_check_verification_trailer failed: %s\n",
1476 nt_errstr(status)));
1477 return dcesrv_fault(call, faultcode);
1480 /* unravel the NDR for the packet */
1481 status = call->context->iface->ndr_pull(call, call, pull, &call->r);
1482 if (!NT_STATUS_IS_OK(status)) {
1483 uint8_t extra_flags = 0;
1484 if (call->fault_code == DCERPC_FAULT_OP_RNG_ERROR) {
1485 /* we got an unknown call */
1486 DEBUG(3,(__location__ ": Unknown RPC call %u on %s\n",
1487 call->pkt.u.request.opnum,
1488 call->context->iface->name));
1489 dcesrv_save_call(call, "unknown");
1490 extra_flags |= DCERPC_PFC_FLAG_DID_NOT_EXECUTE;
1491 } else {
1492 dcesrv_save_call(call, "pullfail");
1494 return dcesrv_fault_with_flags(call, call->fault_code, extra_flags);
1497 if (pull->offset != pull->data_size) {
1498 dcesrv_save_call(call, "extrabytes");
1499 DEBUG(3,("Warning: %d extra bytes in incoming RPC request\n",
1500 pull->data_size - pull->offset));
1503 /* call the dispatch function */
1504 status = call->context->iface->dispatch(call, call, call->r);
1505 if (!NT_STATUS_IS_OK(status)) {
1506 DEBUG(5,("dcerpc fault in call %s:%02x - %s\n",
1507 call->context->iface->name,
1508 call->pkt.u.request.opnum,
1509 dcerpc_errstr(pull, call->fault_code)));
1510 return dcesrv_fault(call, call->fault_code);
1513 /* add the call to the pending list */
1514 dcesrv_call_set_list(call, DCESRV_LIST_PENDING_CALL_LIST);
1516 if (call->state_flags & DCESRV_CALL_STATE_FLAG_ASYNC) {
1517 return NT_STATUS_OK;
1520 return dcesrv_reply(call);
1525 remove the call from the right list when freed
1527 static int dcesrv_call_dequeue(struct dcesrv_call_state *call)
1529 dcesrv_call_set_list(call, DCESRV_LIST_NONE);
1530 return 0;
1533 _PUBLIC_ const struct tsocket_address *dcesrv_connection_get_local_address(struct dcesrv_connection *conn)
1535 return conn->local_address;
1538 _PUBLIC_ const struct tsocket_address *dcesrv_connection_get_remote_address(struct dcesrv_connection *conn)
1540 return conn->remote_address;
1544 process some input to a dcerpc endpoint server.
1546 static NTSTATUS dcesrv_process_ncacn_packet(struct dcesrv_connection *dce_conn,
1547 struct ncacn_packet *pkt,
1548 DATA_BLOB blob)
1550 NTSTATUS status;
1551 struct dcesrv_call_state *call;
1552 struct dcesrv_call_state *existing = NULL;
1554 call = talloc_zero(dce_conn, struct dcesrv_call_state);
1555 if (!call) {
1556 data_blob_free(&blob);
1557 talloc_free(pkt);
1558 return NT_STATUS_NO_MEMORY;
1560 call->conn = dce_conn;
1561 call->event_ctx = dce_conn->event_ctx;
1562 call->msg_ctx = dce_conn->msg_ctx;
1563 call->state_flags = call->conn->state_flags;
1564 call->time = timeval_current();
1565 call->list = DCESRV_LIST_NONE;
1567 talloc_steal(call, pkt);
1568 talloc_steal(call, blob.data);
1569 call->pkt = *pkt;
1571 talloc_set_destructor(call, dcesrv_call_dequeue);
1573 if (call->conn->allow_bind) {
1575 * Only one bind is possible per connection
1577 call->conn->allow_bind = false;
1578 return dcesrv_bind(call);
1581 /* we have to check the signing here, before combining the
1582 pdus */
1583 if (call->pkt.ptype == DCERPC_PKT_REQUEST) {
1584 if (!call->conn->allow_request) {
1585 return dcesrv_fault_disconnect(call,
1586 DCERPC_NCA_S_PROTO_ERROR);
1589 status = dcerpc_verify_ncacn_packet_header(&call->pkt,
1590 DCERPC_PKT_REQUEST,
1591 call->pkt.u.request.stub_and_verifier.length,
1592 0, /* required_flags */
1593 DCERPC_PFC_FLAG_FIRST |
1594 DCERPC_PFC_FLAG_LAST |
1595 DCERPC_PFC_FLAG_PENDING_CANCEL |
1596 0x08 | /* this is not defined, but should be ignored */
1597 DCERPC_PFC_FLAG_CONC_MPX |
1598 DCERPC_PFC_FLAG_DID_NOT_EXECUTE |
1599 DCERPC_PFC_FLAG_MAYBE |
1600 DCERPC_PFC_FLAG_OBJECT_UUID);
1601 if (!NT_STATUS_IS_OK(status)) {
1602 return dcesrv_fault_disconnect(call,
1603 DCERPC_NCA_S_PROTO_ERROR);
1606 if (call->pkt.frag_length > DCERPC_FRAG_MAX_SIZE) {
1608 * We don't use dcesrv_fault_disconnect()
1609 * here, because we don't want to set
1610 * DCERPC_PFC_FLAG_DID_NOT_EXECUTE
1612 * Note that we don't check against the negotiated
1613 * max_recv_frag, but a hard coded value.
1615 dcesrv_call_disconnect_after(call,
1616 "dcesrv_auth_request - frag_length too large");
1617 return dcesrv_fault(call,
1618 DCERPC_NCA_S_PROTO_ERROR);
1621 if (call->pkt.pfc_flags & DCERPC_PFC_FLAG_FIRST) {
1622 /* only one request is possible in the fragmented list */
1623 if (dce_conn->incoming_fragmented_call_list != NULL) {
1624 TALLOC_FREE(call);
1625 call = dce_conn->incoming_fragmented_call_list;
1626 dcesrv_call_disconnect_after(call,
1627 "dcesrv_auth_request - "
1628 "existing fragmented call");
1629 return dcesrv_fault(call,
1630 DCERPC_NCA_S_PROTO_ERROR);
1632 if (call->pkt.pfc_flags & DCERPC_PFC_FLAG_PENDING_CANCEL) {
1633 return dcesrv_fault_disconnect(call,
1634 DCERPC_FAULT_NO_CALL_ACTIVE);
1636 call->context = dcesrv_find_context(call->conn,
1637 call->pkt.u.request.context_id);
1638 if (call->context == NULL) {
1639 return dcesrv_fault_with_flags(call, DCERPC_NCA_S_UNKNOWN_IF,
1640 DCERPC_PFC_FLAG_DID_NOT_EXECUTE);
1642 } else {
1643 const struct dcerpc_request *nr = &call->pkt.u.request;
1644 const struct dcerpc_request *er = NULL;
1645 int cmp;
1647 existing = dcesrv_find_fragmented_call(dce_conn,
1648 call->pkt.call_id);
1649 if (existing == NULL) {
1650 dcesrv_call_disconnect_after(call,
1651 "dcesrv_auth_request - "
1652 "no existing fragmented call");
1653 return dcesrv_fault(call,
1654 DCERPC_NCA_S_PROTO_ERROR);
1656 er = &existing->pkt.u.request;
1658 if (call->pkt.ptype != existing->pkt.ptype) {
1659 /* trying to play silly buggers are we? */
1660 return dcesrv_fault_disconnect(existing,
1661 DCERPC_NCA_S_PROTO_ERROR);
1663 cmp = memcmp(call->pkt.drep, existing->pkt.drep,
1664 sizeof(pkt->drep));
1665 if (cmp != 0) {
1666 return dcesrv_fault_disconnect(existing,
1667 DCERPC_NCA_S_PROTO_ERROR);
1669 if (nr->context_id != er->context_id) {
1670 return dcesrv_fault_disconnect(existing,
1671 DCERPC_NCA_S_PROTO_ERROR);
1673 if (nr->opnum != er->opnum) {
1674 return dcesrv_fault_disconnect(existing,
1675 DCERPC_NCA_S_PROTO_ERROR);
1680 if (call->pkt.ptype == DCERPC_PKT_REQUEST) {
1681 bool ok;
1682 uint8_t payload_offset = DCERPC_REQUEST_LENGTH;
1684 if (call->pkt.pfc_flags & DCERPC_PFC_FLAG_OBJECT_UUID) {
1685 payload_offset += 16;
1688 ok = dcesrv_auth_pkt_pull(call, &blob,
1689 0, /* required_flags */
1690 DCERPC_PFC_FLAG_FIRST |
1691 DCERPC_PFC_FLAG_LAST |
1692 DCERPC_PFC_FLAG_PENDING_CANCEL |
1693 0x08 | /* this is not defined, but should be ignored */
1694 DCERPC_PFC_FLAG_CONC_MPX |
1695 DCERPC_PFC_FLAG_DID_NOT_EXECUTE |
1696 DCERPC_PFC_FLAG_MAYBE |
1697 DCERPC_PFC_FLAG_OBJECT_UUID,
1698 payload_offset,
1699 &call->pkt.u.request.stub_and_verifier);
1700 if (!ok) {
1702 * We don't use dcesrv_fault_disconnect()
1703 * here, because we don't want to set
1704 * DCERPC_PFC_FLAG_DID_NOT_EXECUTE
1706 dcesrv_call_disconnect_after(call,
1707 "dcesrv_auth_request - failed");
1708 if (call->fault_code == 0) {
1709 call->fault_code = DCERPC_FAULT_ACCESS_DENIED;
1711 return dcesrv_fault(call, call->fault_code);
1715 /* see if this is a continued packet */
1716 if (existing != NULL) {
1717 struct dcerpc_request *er = &existing->pkt.u.request;
1718 const struct dcerpc_request *nr = &call->pkt.u.request;
1719 size_t available;
1720 size_t alloc_size;
1721 size_t alloc_hint;
1724 * Up to 4 MByte are allowed by all fragments
1726 available = dce_conn->max_total_request_size;
1727 if (er->stub_and_verifier.length > available) {
1728 dcesrv_call_disconnect_after(existing,
1729 "dcesrv_auth_request - existing payload too large");
1730 return dcesrv_fault(existing, DCERPC_FAULT_ACCESS_DENIED);
1732 available -= er->stub_and_verifier.length;
1733 if (nr->alloc_hint > available) {
1734 dcesrv_call_disconnect_after(existing,
1735 "dcesrv_auth_request - alloc hint too large");
1736 return dcesrv_fault(existing, DCERPC_FAULT_ACCESS_DENIED);
1738 if (nr->stub_and_verifier.length > available) {
1739 dcesrv_call_disconnect_after(existing,
1740 "dcesrv_auth_request - new payload too large");
1741 return dcesrv_fault(existing, DCERPC_FAULT_ACCESS_DENIED);
1743 alloc_hint = er->stub_and_verifier.length + nr->alloc_hint;
1744 /* allocate at least 1 byte */
1745 alloc_hint = MAX(alloc_hint, 1);
1746 alloc_size = er->stub_and_verifier.length +
1747 nr->stub_and_verifier.length;
1748 alloc_size = MAX(alloc_size, alloc_hint);
1750 er->stub_and_verifier.data =
1751 talloc_realloc(existing,
1752 er->stub_and_verifier.data,
1753 uint8_t, alloc_size);
1754 if (er->stub_and_verifier.data == NULL) {
1755 TALLOC_FREE(call);
1756 return dcesrv_fault_with_flags(existing,
1757 DCERPC_FAULT_OUT_OF_RESOURCES,
1758 DCERPC_PFC_FLAG_DID_NOT_EXECUTE);
1760 memcpy(er->stub_and_verifier.data +
1761 er->stub_and_verifier.length,
1762 nr->stub_and_verifier.data,
1763 nr->stub_and_verifier.length);
1764 er->stub_and_verifier.length += nr->stub_and_verifier.length;
1766 existing->pkt.pfc_flags |= (call->pkt.pfc_flags & DCERPC_PFC_FLAG_LAST);
1768 TALLOC_FREE(call);
1769 call = existing;
1772 /* this may not be the last pdu in the chain - if its isn't then
1773 just put it on the incoming_fragmented_call_list and wait for the rest */
1774 if (call->pkt.ptype == DCERPC_PKT_REQUEST &&
1775 !(call->pkt.pfc_flags & DCERPC_PFC_FLAG_LAST)) {
1777 * Up to 4 MByte are allowed by all fragments
1779 if (call->pkt.u.request.alloc_hint > dce_conn->max_total_request_size) {
1780 dcesrv_call_disconnect_after(call,
1781 "dcesrv_auth_request - initial alloc hint too large");
1782 return dcesrv_fault(call, DCERPC_FAULT_ACCESS_DENIED);
1784 dcesrv_call_set_list(call, DCESRV_LIST_FRAGMENTED_CALL_LIST);
1785 return NT_STATUS_OK;
1788 /* This removes any fragments we may have had stashed away */
1789 dcesrv_call_set_list(call, DCESRV_LIST_NONE);
1791 switch (call->pkt.ptype) {
1792 case DCERPC_PKT_BIND:
1793 status = dcesrv_bind_nak(call,
1794 DCERPC_BIND_NAK_REASON_NOT_SPECIFIED);
1795 break;
1796 case DCERPC_PKT_AUTH3:
1797 status = dcesrv_auth3(call);
1798 break;
1799 case DCERPC_PKT_ALTER:
1800 status = dcesrv_alter(call);
1801 break;
1802 case DCERPC_PKT_REQUEST:
1803 status = dcesrv_request(call);
1804 break;
1805 case DCERPC_PKT_CO_CANCEL:
1806 case DCERPC_PKT_ORPHANED:
1808 * Window just ignores CO_CANCEL and ORPHANED,
1809 * so we do...
1811 status = NT_STATUS_OK;
1812 TALLOC_FREE(call);
1813 break;
1814 case DCERPC_PKT_BIND_ACK:
1815 case DCERPC_PKT_BIND_NAK:
1816 case DCERPC_PKT_ALTER_RESP:
1817 case DCERPC_PKT_RESPONSE:
1818 case DCERPC_PKT_FAULT:
1819 case DCERPC_PKT_SHUTDOWN:
1820 default:
1821 status = dcesrv_fault_disconnect(call, DCERPC_NCA_S_PROTO_ERROR);
1822 break;
1825 /* if we are going to be sending a reply then add
1826 it to the list of pending calls. We add it to the end to keep the call
1827 list in the order we will answer */
1828 if (!NT_STATUS_IS_OK(status)) {
1829 talloc_free(call);
1832 return status;
1835 _PUBLIC_ NTSTATUS dcesrv_init_context(TALLOC_CTX *mem_ctx,
1836 struct loadparm_context *lp_ctx,
1837 const char **endpoint_servers, struct dcesrv_context **_dce_ctx)
1839 NTSTATUS status;
1840 struct dcesrv_context *dce_ctx;
1841 int i;
1843 if (!endpoint_servers) {
1844 DEBUG(0,("dcesrv_init_context: no endpoint servers configured\n"));
1845 return NT_STATUS_INTERNAL_ERROR;
1848 dce_ctx = talloc_zero(mem_ctx, struct dcesrv_context);
1849 NT_STATUS_HAVE_NO_MEMORY(dce_ctx);
1851 if (uid_wrapper_enabled()) {
1852 setenv("UID_WRAPPER_MYUID", "1", 1);
1854 dce_ctx->initial_euid = geteuid();
1855 if (uid_wrapper_enabled()) {
1856 unsetenv("UID_WRAPPER_MYUID");
1859 dce_ctx->endpoint_list = NULL;
1860 dce_ctx->lp_ctx = lp_ctx;
1861 dce_ctx->assoc_groups_idr = idr_init(dce_ctx);
1862 NT_STATUS_HAVE_NO_MEMORY(dce_ctx->assoc_groups_idr);
1863 dce_ctx->broken_connections = NULL;
1865 for (i=0;endpoint_servers[i];i++) {
1866 const struct dcesrv_endpoint_server *ep_server;
1868 ep_server = dcesrv_ep_server_byname(endpoint_servers[i]);
1869 if (!ep_server) {
1870 DEBUG(0,("dcesrv_init_context: failed to find endpoint server = '%s'\n", endpoint_servers[i]));
1871 return NT_STATUS_INTERNAL_ERROR;
1874 status = ep_server->init_server(dce_ctx, ep_server);
1875 if (!NT_STATUS_IS_OK(status)) {
1876 DEBUG(0,("dcesrv_init_context: failed to init endpoint server = '%s': %s\n", endpoint_servers[i],
1877 nt_errstr(status)));
1878 return status;
1882 *_dce_ctx = dce_ctx;
1883 return NT_STATUS_OK;
1886 /* the list of currently registered DCERPC endpoint servers.
1888 static struct ep_server {
1889 struct dcesrv_endpoint_server *ep_server;
1890 } *ep_servers = NULL;
1891 static int num_ep_servers;
1894 register a DCERPC endpoint server.
1896 The 'name' can be later used by other backends to find the operations
1897 structure for this backend.
1899 The 'type' is used to specify whether this is for a disk, printer or IPC$ share
1901 _PUBLIC_ NTSTATUS dcerpc_register_ep_server(const void *_ep_server)
1903 const struct dcesrv_endpoint_server *ep_server = _ep_server;
1905 if (dcesrv_ep_server_byname(ep_server->name) != NULL) {
1906 /* its already registered! */
1907 DEBUG(0,("DCERPC endpoint server '%s' already registered\n",
1908 ep_server->name));
1909 return NT_STATUS_OBJECT_NAME_COLLISION;
1912 ep_servers = realloc_p(ep_servers, struct ep_server, num_ep_servers+1);
1913 if (!ep_servers) {
1914 smb_panic("out of memory in dcerpc_register");
1917 ep_servers[num_ep_servers].ep_server = smb_xmemdup(ep_server, sizeof(*ep_server));
1918 ep_servers[num_ep_servers].ep_server->name = smb_xstrdup(ep_server->name);
1920 num_ep_servers++;
1922 DEBUG(3,("DCERPC endpoint server '%s' registered\n",
1923 ep_server->name));
1925 return NT_STATUS_OK;
1929 return the operations structure for a named backend of the specified type
1931 const struct dcesrv_endpoint_server *dcesrv_ep_server_byname(const char *name)
1933 int i;
1935 for (i=0;i<num_ep_servers;i++) {
1936 if (strcmp(ep_servers[i].ep_server->name, name) == 0) {
1937 return ep_servers[i].ep_server;
1941 return NULL;
1944 void dcerpc_server_init(struct loadparm_context *lp_ctx)
1946 static bool initialized;
1947 #define _MODULE_PROTO(init) extern NTSTATUS init(void);
1948 STATIC_dcerpc_server_MODULES_PROTO;
1949 init_module_fn static_init[] = { STATIC_dcerpc_server_MODULES };
1950 init_module_fn *shared_init;
1952 if (initialized) {
1953 return;
1955 initialized = true;
1957 shared_init = load_samba_modules(NULL, "dcerpc_server");
1959 run_init_functions(static_init);
1960 run_init_functions(shared_init);
1962 talloc_free(shared_init);
1966 return the DCERPC module version, and the size of some critical types
1967 This can be used by endpoint server modules to either detect compilation errors, or provide
1968 multiple implementations for different smbd compilation options in one module
1970 const struct dcesrv_critical_sizes *dcerpc_module_version(void)
1972 static const struct dcesrv_critical_sizes critical_sizes = {
1973 DCERPC_MODULE_VERSION,
1974 sizeof(struct dcesrv_context),
1975 sizeof(struct dcesrv_endpoint),
1976 sizeof(struct dcesrv_endpoint_server),
1977 sizeof(struct dcesrv_interface),
1978 sizeof(struct dcesrv_if_list),
1979 sizeof(struct dcesrv_connection),
1980 sizeof(struct dcesrv_call_state),
1981 sizeof(struct dcesrv_auth),
1982 sizeof(struct dcesrv_handle)
1985 return &critical_sizes;
1988 static void dcesrv_terminate_connection(struct dcesrv_connection *dce_conn, const char *reason)
1990 struct dcesrv_context *dce_ctx = dce_conn->dce_ctx;
1991 struct stream_connection *srv_conn;
1992 srv_conn = talloc_get_type(dce_conn->transport.private_data,
1993 struct stream_connection);
1995 dce_conn->allow_bind = false;
1996 dce_conn->allow_auth3 = false;
1997 dce_conn->allow_alter = false;
1998 dce_conn->allow_request = false;
2000 if (dce_conn->pending_call_list == NULL) {
2001 char *full_reason = talloc_asprintf(dce_conn, "dcesrv: %s", reason);
2003 DLIST_REMOVE(dce_ctx->broken_connections, dce_conn);
2004 stream_terminate_connection(srv_conn, full_reason ? full_reason : reason);
2005 return;
2008 if (dce_conn->terminate != NULL) {
2009 return;
2012 DEBUG(3,("dcesrv: terminating connection due to '%s' defered due to pending calls\n",
2013 reason));
2014 dce_conn->terminate = talloc_strdup(dce_conn, reason);
2015 if (dce_conn->terminate == NULL) {
2016 dce_conn->terminate = "dcesrv: defered terminating connection - no memory";
2018 DLIST_ADD_END(dce_ctx->broken_connections, dce_conn);
2021 static void dcesrv_cleanup_broken_connections(struct dcesrv_context *dce_ctx)
2023 struct dcesrv_connection *cur, *next;
2025 next = dce_ctx->broken_connections;
2026 while (next != NULL) {
2027 cur = next;
2028 next = cur->next;
2030 if (cur->state_flags & DCESRV_CALL_STATE_FLAG_PROCESS_PENDING_CALL) {
2031 struct dcesrv_connection_context *context_cur, *context_next;
2033 context_next = cur->contexts;
2034 while (context_next != NULL) {
2035 context_cur = context_next;
2036 context_next = context_cur->next;
2038 dcesrv_connection_context_destructor(context_cur);
2042 dcesrv_terminate_connection(cur, cur->terminate);
2046 /* We need this include to be able to compile on some plateforms
2047 * (ie. freebsd 7.2) as it seems that <sys/uio.h> is not included
2048 * correctly.
2049 * It has to be that deep because otherwise we have a conflict on
2050 * const struct dcesrv_interface declaration.
2051 * This is mostly due to socket_wrapper defining #define bind swrap_bind
2052 * which conflict with the bind used before.
2054 #include "system/network.h"
2056 struct dcesrv_sock_reply_state {
2057 struct dcesrv_connection *dce_conn;
2058 struct dcesrv_call_state *call;
2059 struct iovec iov;
2062 static void dcesrv_sock_reply_done(struct tevent_req *subreq);
2063 static void dcesrv_call_terminate_step1(struct tevent_req *subreq);
2065 static void dcesrv_sock_report_output_data(struct dcesrv_connection *dce_conn)
2067 struct dcesrv_call_state *call;
2069 call = dce_conn->call_list;
2070 if (!call || !call->replies) {
2071 return;
2074 while (call->replies) {
2075 struct data_blob_list_item *rep = call->replies;
2076 struct dcesrv_sock_reply_state *substate;
2077 struct tevent_req *subreq;
2079 substate = talloc_zero(call, struct dcesrv_sock_reply_state);
2080 if (!substate) {
2081 dcesrv_terminate_connection(dce_conn, "no memory");
2082 return;
2085 substate->dce_conn = dce_conn;
2086 substate->call = NULL;
2088 DLIST_REMOVE(call->replies, rep);
2090 if (call->replies == NULL && call->terminate_reason == NULL) {
2091 substate->call = call;
2094 substate->iov.iov_base = (void *) rep->blob.data;
2095 substate->iov.iov_len = rep->blob.length;
2097 subreq = tstream_writev_queue_send(substate,
2098 dce_conn->event_ctx,
2099 dce_conn->stream,
2100 dce_conn->send_queue,
2101 &substate->iov, 1);
2102 if (!subreq) {
2103 dcesrv_terminate_connection(dce_conn, "no memory");
2104 return;
2106 tevent_req_set_callback(subreq, dcesrv_sock_reply_done,
2107 substate);
2110 if (call->terminate_reason != NULL) {
2111 struct tevent_req *subreq;
2113 subreq = tevent_queue_wait_send(call,
2114 dce_conn->event_ctx,
2115 dce_conn->send_queue);
2116 if (!subreq) {
2117 dcesrv_terminate_connection(dce_conn, __location__);
2118 return;
2120 tevent_req_set_callback(subreq, dcesrv_call_terminate_step1,
2121 call);
2124 DLIST_REMOVE(call->conn->call_list, call);
2125 call->list = DCESRV_LIST_NONE;
2128 static void dcesrv_sock_reply_done(struct tevent_req *subreq)
2130 struct dcesrv_sock_reply_state *substate = tevent_req_callback_data(subreq,
2131 struct dcesrv_sock_reply_state);
2132 int ret;
2133 int sys_errno;
2134 NTSTATUS status;
2135 struct dcesrv_call_state *call = substate->call;
2137 ret = tstream_writev_queue_recv(subreq, &sys_errno);
2138 TALLOC_FREE(subreq);
2139 if (ret == -1) {
2140 status = map_nt_error_from_unix_common(sys_errno);
2141 dcesrv_terminate_connection(substate->dce_conn, nt_errstr(status));
2142 return;
2145 talloc_free(substate);
2146 if (call) {
2147 talloc_free(call);
2151 static void dcesrv_call_terminate_step2(struct tevent_req *subreq);
2153 static void dcesrv_call_terminate_step1(struct tevent_req *subreq)
2155 struct dcesrv_call_state *call = tevent_req_callback_data(subreq,
2156 struct dcesrv_call_state);
2157 bool ok;
2158 struct timeval tv;
2160 /* make sure we stop send queue before removing subreq */
2161 tevent_queue_stop(call->conn->send_queue);
2163 ok = tevent_queue_wait_recv(subreq);
2164 TALLOC_FREE(subreq);
2165 if (!ok) {
2166 dcesrv_terminate_connection(call->conn, __location__);
2167 return;
2170 /* disconnect after 200 usecs */
2171 tv = timeval_current_ofs_usec(200);
2172 subreq = tevent_wakeup_send(call, call->conn->event_ctx, tv);
2173 if (subreq == NULL) {
2174 dcesrv_terminate_connection(call->conn, __location__);
2175 return;
2177 tevent_req_set_callback(subreq, dcesrv_call_terminate_step2,
2178 call);
2181 static void dcesrv_call_terminate_step2(struct tevent_req *subreq)
2183 struct dcesrv_call_state *call = tevent_req_callback_data(subreq,
2184 struct dcesrv_call_state);
2185 bool ok;
2187 ok = tevent_wakeup_recv(subreq);
2188 TALLOC_FREE(subreq);
2189 if (!ok) {
2190 dcesrv_terminate_connection(call->conn, __location__);
2191 return;
2194 dcesrv_terminate_connection(call->conn, call->terminate_reason);
2197 struct dcesrv_socket_context {
2198 const struct dcesrv_endpoint *endpoint;
2199 struct dcesrv_context *dcesrv_ctx;
2203 static void dcesrv_read_fragment_done(struct tevent_req *subreq);
2205 static void dcesrv_sock_accept(struct stream_connection *srv_conn)
2207 NTSTATUS status;
2208 struct dcesrv_socket_context *dcesrv_sock =
2209 talloc_get_type(srv_conn->private_data, struct dcesrv_socket_context);
2210 enum dcerpc_transport_t transport =
2211 dcerpc_binding_get_transport(dcesrv_sock->endpoint->ep_description);
2212 struct dcesrv_connection *dcesrv_conn = NULL;
2213 int ret;
2214 struct tevent_req *subreq;
2215 struct loadparm_context *lp_ctx = dcesrv_sock->dcesrv_ctx->lp_ctx;
2217 dcesrv_cleanup_broken_connections(dcesrv_sock->dcesrv_ctx);
2219 if (!srv_conn->session_info) {
2220 status = auth_anonymous_session_info(srv_conn,
2221 lp_ctx,
2222 &srv_conn->session_info);
2223 if (!NT_STATUS_IS_OK(status)) {
2224 DEBUG(0,("dcesrv_sock_accept: auth_anonymous_session_info failed: %s\n",
2225 nt_errstr(status)));
2226 stream_terminate_connection(srv_conn, nt_errstr(status));
2227 return;
2231 status = dcesrv_endpoint_connect(dcesrv_sock->dcesrv_ctx,
2232 srv_conn,
2233 dcesrv_sock->endpoint,
2234 srv_conn->session_info,
2235 srv_conn->event.ctx,
2236 srv_conn->msg_ctx,
2237 srv_conn->server_id,
2238 DCESRV_CALL_STATE_FLAG_MAY_ASYNC,
2239 &dcesrv_conn);
2240 if (!NT_STATUS_IS_OK(status)) {
2241 DEBUG(0,("dcesrv_sock_accept: dcesrv_endpoint_connect failed: %s\n",
2242 nt_errstr(status)));
2243 stream_terminate_connection(srv_conn, nt_errstr(status));
2244 return;
2247 dcesrv_conn->transport.private_data = srv_conn;
2248 dcesrv_conn->transport.report_output_data = dcesrv_sock_report_output_data;
2250 TALLOC_FREE(srv_conn->event.fde);
2252 dcesrv_conn->send_queue = tevent_queue_create(dcesrv_conn, "dcesrv send queue");
2253 if (!dcesrv_conn->send_queue) {
2254 status = NT_STATUS_NO_MEMORY;
2255 DEBUG(0,("dcesrv_sock_accept: tevent_queue_create(%s)\n",
2256 nt_errstr(status)));
2257 stream_terminate_connection(srv_conn, nt_errstr(status));
2258 return;
2261 if (transport == NCACN_NP) {
2262 dcesrv_conn->auth_state.session_key = dcesrv_inherited_session_key;
2263 dcesrv_conn->stream = talloc_move(dcesrv_conn,
2264 &srv_conn->tstream);
2265 } else {
2266 ret = tstream_bsd_existing_socket(dcesrv_conn,
2267 socket_get_fd(srv_conn->socket),
2268 &dcesrv_conn->stream);
2269 if (ret == -1) {
2270 status = map_nt_error_from_unix_common(errno);
2271 DEBUG(0, ("dcesrv_sock_accept: "
2272 "failed to setup tstream: %s\n",
2273 nt_errstr(status)));
2274 stream_terminate_connection(srv_conn, nt_errstr(status));
2275 return;
2277 socket_set_flags(srv_conn->socket, SOCKET_FLAG_NOCLOSE);
2280 dcesrv_conn->local_address = srv_conn->local_address;
2281 dcesrv_conn->remote_address = srv_conn->remote_address;
2283 if (transport == NCALRPC) {
2284 uid_t uid;
2285 gid_t gid;
2286 int sock_fd;
2288 sock_fd = socket_get_fd(srv_conn->socket);
2289 if (sock_fd == -1) {
2290 stream_terminate_connection(
2291 srv_conn, "socket_get_fd failed\n");
2292 return;
2295 ret = getpeereid(sock_fd, &uid, &gid);
2296 if (ret == -1) {
2297 status = map_nt_error_from_unix_common(errno);
2298 DEBUG(0, ("dcesrv_sock_accept: "
2299 "getpeereid() failed for NCALRPC: %s\n",
2300 nt_errstr(status)));
2301 stream_terminate_connection(srv_conn, nt_errstr(status));
2302 return;
2304 if (uid == dcesrv_conn->dce_ctx->initial_euid) {
2305 struct tsocket_address *r = NULL;
2307 ret = tsocket_address_unix_from_path(dcesrv_conn,
2308 "/root/ncalrpc_as_system",
2309 &r);
2310 if (ret == -1) {
2311 status = map_nt_error_from_unix_common(errno);
2312 DEBUG(0, ("dcesrv_sock_accept: "
2313 "tsocket_address_unix_from_path() failed for NCALRPC: %s\n",
2314 nt_errstr(status)));
2315 stream_terminate_connection(srv_conn, nt_errstr(status));
2316 return;
2318 dcesrv_conn->remote_address = r;
2322 srv_conn->private_data = dcesrv_conn;
2324 irpc_add_name(srv_conn->msg_ctx, "rpc_server");
2326 subreq = dcerpc_read_ncacn_packet_send(dcesrv_conn,
2327 dcesrv_conn->event_ctx,
2328 dcesrv_conn->stream);
2329 if (!subreq) {
2330 status = NT_STATUS_NO_MEMORY;
2331 DEBUG(0,("dcesrv_sock_accept: dcerpc_read_fragment_buffer_send(%s)\n",
2332 nt_errstr(status)));
2333 stream_terminate_connection(srv_conn, nt_errstr(status));
2334 return;
2336 tevent_req_set_callback(subreq, dcesrv_read_fragment_done, dcesrv_conn);
2338 return;
2341 static void dcesrv_read_fragment_done(struct tevent_req *subreq)
2343 struct dcesrv_connection *dce_conn = tevent_req_callback_data(subreq,
2344 struct dcesrv_connection);
2345 struct dcesrv_context *dce_ctx = dce_conn->dce_ctx;
2346 struct ncacn_packet *pkt;
2347 DATA_BLOB buffer;
2348 NTSTATUS status;
2350 if (dce_conn->terminate) {
2352 * if the current connection is broken
2353 * we need to clean it up before any other connection
2355 dcesrv_terminate_connection(dce_conn, dce_conn->terminate);
2356 dcesrv_cleanup_broken_connections(dce_ctx);
2357 return;
2360 dcesrv_cleanup_broken_connections(dce_ctx);
2362 status = dcerpc_read_ncacn_packet_recv(subreq, dce_conn,
2363 &pkt, &buffer);
2364 TALLOC_FREE(subreq);
2365 if (!NT_STATUS_IS_OK(status)) {
2366 dcesrv_terminate_connection(dce_conn, nt_errstr(status));
2367 return;
2370 status = dcesrv_process_ncacn_packet(dce_conn, pkt, buffer);
2371 if (!NT_STATUS_IS_OK(status)) {
2372 dcesrv_terminate_connection(dce_conn, nt_errstr(status));
2373 return;
2376 subreq = dcerpc_read_ncacn_packet_send(dce_conn,
2377 dce_conn->event_ctx,
2378 dce_conn->stream);
2379 if (!subreq) {
2380 status = NT_STATUS_NO_MEMORY;
2381 dcesrv_terminate_connection(dce_conn, nt_errstr(status));
2382 return;
2384 tevent_req_set_callback(subreq, dcesrv_read_fragment_done, dce_conn);
2387 static void dcesrv_sock_recv(struct stream_connection *conn, uint16_t flags)
2389 struct dcesrv_connection *dce_conn = talloc_get_type(conn->private_data,
2390 struct dcesrv_connection);
2391 dcesrv_terminate_connection(dce_conn, "dcesrv_sock_recv triggered");
2394 static void dcesrv_sock_send(struct stream_connection *conn, uint16_t flags)
2396 struct dcesrv_connection *dce_conn = talloc_get_type(conn->private_data,
2397 struct dcesrv_connection);
2398 dcesrv_terminate_connection(dce_conn, "dcesrv_sock_send triggered");
2402 static const struct stream_server_ops dcesrv_stream_ops = {
2403 .name = "rpc",
2404 .accept_connection = dcesrv_sock_accept,
2405 .recv_handler = dcesrv_sock_recv,
2406 .send_handler = dcesrv_sock_send,
2409 static NTSTATUS dcesrv_add_ep_unix(struct dcesrv_context *dce_ctx,
2410 struct loadparm_context *lp_ctx,
2411 struct dcesrv_endpoint *e,
2412 struct tevent_context *event_ctx, const struct model_ops *model_ops)
2414 struct dcesrv_socket_context *dcesrv_sock;
2415 uint16_t port = 1;
2416 NTSTATUS status;
2417 const char *endpoint;
2419 dcesrv_sock = talloc_zero(event_ctx, struct dcesrv_socket_context);
2420 NT_STATUS_HAVE_NO_MEMORY(dcesrv_sock);
2422 /* remember the endpoint of this socket */
2423 dcesrv_sock->endpoint = e;
2424 dcesrv_sock->dcesrv_ctx = talloc_reference(dcesrv_sock, dce_ctx);
2426 endpoint = dcerpc_binding_get_string_option(e->ep_description, "endpoint");
2428 status = stream_setup_socket(dcesrv_sock, event_ctx, lp_ctx,
2429 model_ops, &dcesrv_stream_ops,
2430 "unix", endpoint, &port,
2431 lpcfg_socket_options(lp_ctx),
2432 dcesrv_sock);
2433 if (!NT_STATUS_IS_OK(status)) {
2434 DEBUG(0,("service_setup_stream_socket(path=%s) failed - %s\n",
2435 endpoint, nt_errstr(status)));
2438 return status;
2441 static NTSTATUS dcesrv_add_ep_ncalrpc(struct dcesrv_context *dce_ctx,
2442 struct loadparm_context *lp_ctx,
2443 struct dcesrv_endpoint *e,
2444 struct tevent_context *event_ctx, const struct model_ops *model_ops)
2446 struct dcesrv_socket_context *dcesrv_sock;
2447 uint16_t port = 1;
2448 char *full_path;
2449 NTSTATUS status;
2450 const char *endpoint;
2452 endpoint = dcerpc_binding_get_string_option(e->ep_description, "endpoint");
2454 if (endpoint == NULL) {
2456 * No identifier specified: use DEFAULT.
2458 * TODO: DO NOT hardcode this value anywhere else. Rather, specify
2459 * no endpoint and let the epmapper worry about it.
2461 endpoint = "DEFAULT";
2462 status = dcerpc_binding_set_string_option(e->ep_description,
2463 "endpoint",
2464 endpoint);
2465 if (!NT_STATUS_IS_OK(status)) {
2466 DEBUG(0,("dcerpc_binding_set_string_option() failed - %s\n",
2467 nt_errstr(status)));
2468 return status;
2472 full_path = talloc_asprintf(dce_ctx, "%s/%s", lpcfg_ncalrpc_dir(lp_ctx),
2473 endpoint);
2475 dcesrv_sock = talloc_zero(event_ctx, struct dcesrv_socket_context);
2476 NT_STATUS_HAVE_NO_MEMORY(dcesrv_sock);
2478 /* remember the endpoint of this socket */
2479 dcesrv_sock->endpoint = e;
2480 dcesrv_sock->dcesrv_ctx = talloc_reference(dcesrv_sock, dce_ctx);
2482 status = stream_setup_socket(dcesrv_sock, event_ctx, lp_ctx,
2483 model_ops, &dcesrv_stream_ops,
2484 "unix", full_path, &port,
2485 lpcfg_socket_options(lp_ctx),
2486 dcesrv_sock);
2487 if (!NT_STATUS_IS_OK(status)) {
2488 DEBUG(0,("service_setup_stream_socket(identifier=%s,path=%s) failed - %s\n",
2489 endpoint, full_path, nt_errstr(status)));
2491 return status;
2494 static NTSTATUS dcesrv_add_ep_np(struct dcesrv_context *dce_ctx,
2495 struct loadparm_context *lp_ctx,
2496 struct dcesrv_endpoint *e,
2497 struct tevent_context *event_ctx, const struct model_ops *model_ops)
2499 struct dcesrv_socket_context *dcesrv_sock;
2500 NTSTATUS status;
2501 const char *endpoint;
2503 endpoint = dcerpc_binding_get_string_option(e->ep_description, "endpoint");
2504 if (endpoint == NULL) {
2505 DEBUG(0, ("Endpoint mandatory for named pipes\n"));
2506 return NT_STATUS_INVALID_PARAMETER;
2509 dcesrv_sock = talloc_zero(event_ctx, struct dcesrv_socket_context);
2510 NT_STATUS_HAVE_NO_MEMORY(dcesrv_sock);
2512 /* remember the endpoint of this socket */
2513 dcesrv_sock->endpoint = e;
2514 dcesrv_sock->dcesrv_ctx = talloc_reference(dcesrv_sock, dce_ctx);
2516 status = tstream_setup_named_pipe(dce_ctx, event_ctx, lp_ctx,
2517 model_ops, &dcesrv_stream_ops,
2518 endpoint,
2519 dcesrv_sock);
2520 if (!NT_STATUS_IS_OK(status)) {
2521 DEBUG(0,("stream_setup_named_pipe(pipe=%s) failed - %s\n",
2522 endpoint, nt_errstr(status)));
2523 return status;
2526 return NT_STATUS_OK;
2530 add a socket address to the list of events, one event per dcerpc endpoint
2532 static NTSTATUS add_socket_rpc_tcp_iface(struct dcesrv_context *dce_ctx, struct dcesrv_endpoint *e,
2533 struct tevent_context *event_ctx, const struct model_ops *model_ops,
2534 const char *address)
2536 struct dcesrv_socket_context *dcesrv_sock;
2537 uint16_t port = 0;
2538 NTSTATUS status;
2539 const char *endpoint;
2540 char port_str[6];
2542 endpoint = dcerpc_binding_get_string_option(e->ep_description, "endpoint");
2543 if (endpoint != NULL) {
2544 port = atoi(endpoint);
2547 dcesrv_sock = talloc_zero(event_ctx, struct dcesrv_socket_context);
2548 NT_STATUS_HAVE_NO_MEMORY(dcesrv_sock);
2550 /* remember the endpoint of this socket */
2551 dcesrv_sock->endpoint = e;
2552 dcesrv_sock->dcesrv_ctx = talloc_reference(dcesrv_sock, dce_ctx);
2554 status = stream_setup_socket(dcesrv_sock, event_ctx, dce_ctx->lp_ctx,
2555 model_ops, &dcesrv_stream_ops,
2556 "ip", address, &port,
2557 lpcfg_socket_options(dce_ctx->lp_ctx),
2558 dcesrv_sock);
2559 if (!NT_STATUS_IS_OK(status)) {
2560 DEBUG(0,("service_setup_stream_socket(address=%s,port=%u) failed - %s\n",
2561 address, port, nt_errstr(status)));
2562 return status;
2565 snprintf(port_str, sizeof(port_str), "%u", port);
2567 status = dcerpc_binding_set_string_option(e->ep_description,
2568 "endpoint", port_str);
2569 if (!NT_STATUS_IS_OK(status)) {
2570 DEBUG(0,("dcerpc_binding_set_string_option(endpoint, %s) failed - %s\n",
2571 port_str, nt_errstr(status)));
2572 return status;
2575 return NT_STATUS_OK;
2578 #include "lib/socket/netif.h" /* Included here to work around the fact that socket_wrapper redefines bind() */
2580 static NTSTATUS dcesrv_add_ep_tcp(struct dcesrv_context *dce_ctx,
2581 struct loadparm_context *lp_ctx,
2582 struct dcesrv_endpoint *e,
2583 struct tevent_context *event_ctx, const struct model_ops *model_ops)
2585 NTSTATUS status;
2587 /* Add TCP/IP sockets */
2588 if (lpcfg_interfaces(lp_ctx) && lpcfg_bind_interfaces_only(lp_ctx)) {
2589 int num_interfaces;
2590 int i;
2591 struct interface *ifaces;
2593 load_interface_list(dce_ctx, lp_ctx, &ifaces);
2595 num_interfaces = iface_list_count(ifaces);
2596 for(i = 0; i < num_interfaces; i++) {
2597 const char *address = iface_list_n_ip(ifaces, i);
2598 status = add_socket_rpc_tcp_iface(dce_ctx, e, event_ctx, model_ops, address);
2599 NT_STATUS_NOT_OK_RETURN(status);
2601 } else {
2602 char **wcard;
2603 int i;
2604 int num_binds = 0;
2605 wcard = iface_list_wildcard(dce_ctx);
2606 NT_STATUS_HAVE_NO_MEMORY(wcard);
2607 for (i=0; wcard[i]; i++) {
2608 status = add_socket_rpc_tcp_iface(dce_ctx, e, event_ctx, model_ops, wcard[i]);
2609 if (NT_STATUS_IS_OK(status)) {
2610 num_binds++;
2613 talloc_free(wcard);
2614 if (num_binds == 0) {
2615 return NT_STATUS_INVALID_PARAMETER_MIX;
2619 return NT_STATUS_OK;
2622 NTSTATUS dcesrv_add_ep(struct dcesrv_context *dce_ctx,
2623 struct loadparm_context *lp_ctx,
2624 struct dcesrv_endpoint *e,
2625 struct tevent_context *event_ctx,
2626 const struct model_ops *model_ops)
2628 enum dcerpc_transport_t transport =
2629 dcerpc_binding_get_transport(e->ep_description);
2631 switch (transport) {
2632 case NCACN_UNIX_STREAM:
2633 return dcesrv_add_ep_unix(dce_ctx, lp_ctx, e, event_ctx, model_ops);
2635 case NCALRPC:
2636 return dcesrv_add_ep_ncalrpc(dce_ctx, lp_ctx, e, event_ctx, model_ops);
2638 case NCACN_IP_TCP:
2639 return dcesrv_add_ep_tcp(dce_ctx, lp_ctx, e, event_ctx, model_ops);
2641 case NCACN_NP:
2642 return dcesrv_add_ep_np(dce_ctx, lp_ctx, e, event_ctx, model_ops);
2644 default:
2645 return NT_STATUS_NOT_SUPPORTED;
2651 * retrieve credentials from a dce_call
2653 _PUBLIC_ struct cli_credentials *dcesrv_call_credentials(struct dcesrv_call_state *dce_call)
2655 return dce_call->conn->auth_state.session_info->credentials;
2659 * returns true if this is an authenticated call
2661 _PUBLIC_ bool dcesrv_call_authenticated(struct dcesrv_call_state *dce_call)
2663 enum security_user_level level;
2664 level = security_session_user_level(dce_call->conn->auth_state.session_info, NULL);
2665 return level >= SECURITY_USER;
2669 * retrieve account_name for a dce_call
2671 _PUBLIC_ const char *dcesrv_call_account_name(struct dcesrv_call_state *dce_call)
2673 return dce_call->context->conn->auth_state.session_info->info->account_name;