s4:rpc_server: list all connection oriented pdu types explicitly
[Samba.git] / source4 / rpc_server / dcerpc_server.c
blob0f454b5effc70d81381c46acfe09ef61dc96cb4d
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 /* not supported yet */
792 call->conn->bind_time_features = a->reason.negotiate;
796 * Try to negotiate one new presentation context.
798 status = dcesrv_negotiate_contexts(call, &call->pkt.u.bind, ack_ctx_list);
799 if (NT_STATUS_EQUAL(status, NT_STATUS_RPC_PROTOCOL_ERROR)) {
800 return dcesrv_bind_nak(call, 0);
802 if (!NT_STATUS_IS_OK(status)) {
803 return status;
806 if ((call->pkt.pfc_flags & DCERPC_PFC_FLAG_CONC_MPX) &&
807 (call->state_flags & DCESRV_CALL_STATE_FLAG_MULTIPLEXED)) {
808 call->conn->state_flags |= DCESRV_CALL_STATE_FLAG_MULTIPLEXED;
809 extra_flags |= DCERPC_PFC_FLAG_CONC_MPX;
812 if (call->state_flags & DCESRV_CALL_STATE_FLAG_PROCESS_PENDING_CALL) {
813 call->conn->state_flags |= DCESRV_CALL_STATE_FLAG_PROCESS_PENDING_CALL;
816 /* handle any authentication that is being requested */
817 if (!dcesrv_auth_bind(call)) {
818 struct dcesrv_auth *auth = &call->conn->auth_state;
820 TALLOC_FREE(call->context);
822 if (auth->auth_level == DCERPC_AUTH_LEVEL_NONE) {
824 * With DCERPC_AUTH_LEVEL_NONE, we get the
825 * reject_reason in auth->auth_context_id.
827 return dcesrv_bind_nak(call, auth->auth_context_id);
831 * This must a be a temporary failure e.g. talloc or invalid
832 * configuration, e.g. no machine account.
834 return dcesrv_bind_nak(call,
835 DCERPC_BIND_NAK_REASON_TEMPORARY_CONGESTION);
838 /* setup a bind_ack */
839 dcesrv_init_hdr(&pkt, lpcfg_rpc_big_endian(call->conn->dce_ctx->lp_ctx));
840 pkt.auth_length = 0;
841 pkt.call_id = call->pkt.call_id;
842 pkt.ptype = DCERPC_PKT_BIND_ACK;
843 pkt.pfc_flags = DCERPC_PFC_FLAG_FIRST | DCERPC_PFC_FLAG_LAST | extra_flags;
844 pkt.u.bind_ack.max_xmit_frag = call->conn->max_xmit_frag;
845 pkt.u.bind_ack.max_recv_frag = call->conn->max_recv_frag;
846 pkt.u.bind_ack.assoc_group_id = call->conn->assoc_group->id;
848 endpoint = dcerpc_binding_get_string_option(
849 call->conn->endpoint->ep_description,
850 "endpoint");
851 if (endpoint == NULL) {
852 endpoint = "";
855 if (strncasecmp(endpoint, "\\pipe\\", 6) == 0) {
857 * TODO: check if this is really needed
859 * Or if we should fix this in our idl files.
861 ep_prefix = "\\PIPE\\";
862 endpoint += 6;
865 pkt.u.bind_ack.secondary_address = talloc_asprintf(call, "%s%s",
866 ep_prefix,
867 endpoint);
868 if (pkt.u.bind_ack.secondary_address == NULL) {
869 TALLOC_FREE(call->context);
870 return NT_STATUS_NO_MEMORY;
872 pkt.u.bind_ack.num_results = call->pkt.u.bind.num_contexts;
873 pkt.u.bind_ack.ctx_list = ack_ctx_list;
874 pkt.u.bind_ack.auth_info = data_blob_null;
876 status = dcesrv_auth_bind_ack(call, &pkt);
877 if (!NT_STATUS_IS_OK(status)) {
878 TALLOC_FREE(call->context);
879 return dcesrv_bind_nak(call, 0);
882 rep = talloc_zero(call, struct data_blob_list_item);
883 if (!rep) {
884 TALLOC_FREE(call->context);
885 return NT_STATUS_NO_MEMORY;
888 status = ncacn_push_auth(&rep->blob, call, &pkt,
889 call->out_auth_info);
890 if (!NT_STATUS_IS_OK(status)) {
891 TALLOC_FREE(call->context);
892 return status;
895 dcerpc_set_frag_length(&rep->blob, rep->blob.length);
897 DLIST_ADD_END(call->replies, rep);
898 dcesrv_call_set_list(call, DCESRV_LIST_CALL_LIST);
900 if (call->conn->call_list && call->conn->call_list->replies) {
901 if (call->conn->transport.report_output_data) {
902 call->conn->transport.report_output_data(call->conn);
906 return NT_STATUS_OK;
911 handle a auth3 request
913 static NTSTATUS dcesrv_auth3(struct dcesrv_call_state *call)
915 NTSTATUS status;
917 if (!call->conn->allow_auth3) {
918 return dcesrv_fault_disconnect(call, DCERPC_NCA_S_PROTO_ERROR);
921 if (call->conn->auth_state.auth_finished) {
922 return dcesrv_fault_disconnect(call, DCERPC_NCA_S_PROTO_ERROR);
925 status = dcerpc_verify_ncacn_packet_header(&call->pkt,
926 DCERPC_PKT_AUTH3,
927 call->pkt.u.auth3.auth_info.length,
928 0, /* required flags */
929 DCERPC_PFC_FLAG_FIRST |
930 DCERPC_PFC_FLAG_LAST |
931 DCERPC_PFC_FLAG_SUPPORT_HEADER_SIGN |
932 0x08 | /* this is not defined, but should be ignored */
933 DCERPC_PFC_FLAG_CONC_MPX |
934 DCERPC_PFC_FLAG_DID_NOT_EXECUTE |
935 DCERPC_PFC_FLAG_MAYBE |
936 DCERPC_PFC_FLAG_OBJECT_UUID);
937 if (!NT_STATUS_IS_OK(status)) {
938 return dcesrv_fault_disconnect(call, DCERPC_NCA_S_PROTO_ERROR);
941 /* handle the auth3 in the auth code */
942 if (!dcesrv_auth_auth3(call)) {
943 call->conn->auth_state.auth_invalid = true;
944 if (call->fault_code != 0) {
945 return dcesrv_fault_disconnect(call, call->fault_code);
949 talloc_free(call);
951 /* we don't send a reply to a auth3 request, except by a
952 fault */
953 return NT_STATUS_OK;
957 static NTSTATUS dcesrv_check_or_create_context(struct dcesrv_call_state *call,
958 const struct dcerpc_bind *b,
959 const struct dcerpc_ctx_list *ctx,
960 struct dcerpc_ack_ctx *ack,
961 bool validate_only,
962 const struct ndr_syntax_id *supported_transfer)
964 uint32_t if_version;
965 struct dcesrv_connection_context *context;
966 const struct dcesrv_interface *iface;
967 struct GUID uuid;
968 NTSTATUS status;
969 const struct ndr_syntax_id *selected_transfer = NULL;
970 size_t i;
971 bool ok;
973 if (b == NULL) {
974 return NT_STATUS_INTERNAL_ERROR;
976 if (ctx == NULL) {
977 return NT_STATUS_INTERNAL_ERROR;
979 if (ctx->num_transfer_syntaxes < 1) {
980 return NT_STATUS_INTERNAL_ERROR;
982 if (ack == NULL) {
983 return NT_STATUS_INTERNAL_ERROR;
985 if (supported_transfer == NULL) {
986 return NT_STATUS_INTERNAL_ERROR;
989 switch (ack->result) {
990 case DCERPC_BIND_ACK_RESULT_ACCEPTANCE:
991 case DCERPC_BIND_ACK_RESULT_NEGOTIATE_ACK:
993 * We is already completed.
995 return NT_STATUS_OK;
996 default:
997 break;
1000 ack->result = DCERPC_BIND_ACK_RESULT_PROVIDER_REJECTION;
1001 ack->reason.value = DCERPC_BIND_ACK_REASON_ABSTRACT_SYNTAX_NOT_SUPPORTED;
1003 if_version = ctx->abstract_syntax.if_version;
1004 uuid = ctx->abstract_syntax.uuid;
1006 iface = find_interface_by_uuid(call->conn->endpoint, &uuid, if_version);
1007 if (iface == NULL) {
1008 char *uuid_str = GUID_string(call, &uuid);
1009 DEBUG(2,("Request for unknown dcerpc interface %s/%d\n", uuid_str, if_version));
1010 talloc_free(uuid_str);
1012 * We report this only via ack->result
1014 return NT_STATUS_OK;
1017 ack->result = DCERPC_BIND_ACK_RESULT_PROVIDER_REJECTION;
1018 ack->reason.value = DCERPC_BIND_ACK_REASON_TRANSFER_SYNTAXES_NOT_SUPPORTED;
1020 if (validate_only) {
1022 * We report this only via ack->result
1024 return NT_STATUS_OK;
1027 for (i = 0; i < ctx->num_transfer_syntaxes; i++) {
1029 * we only do NDR encoded dcerpc for now.
1031 ok = ndr_syntax_id_equal(&ctx->transfer_syntaxes[i],
1032 supported_transfer);
1033 if (ok) {
1034 selected_transfer = supported_transfer;
1035 break;
1039 context = dcesrv_find_context(call->conn, ctx->context_id);
1040 if (context != NULL) {
1041 ok = ndr_syntax_id_equal(&context->iface->syntax_id,
1042 &ctx->abstract_syntax);
1043 if (!ok) {
1044 return NT_STATUS_RPC_PROTOCOL_ERROR;
1047 if (selected_transfer != NULL) {
1048 ok = ndr_syntax_id_equal(&context->transfer_syntax,
1049 selected_transfer);
1050 if (!ok) {
1051 return NT_STATUS_RPC_PROTOCOL_ERROR;
1054 ack->result = DCERPC_BIND_ACK_RESULT_ACCEPTANCE;
1055 ack->reason.value = DCERPC_BIND_ACK_REASON_NOT_SPECIFIED;
1056 ack->syntax = context->transfer_syntax;
1060 * We report this only via ack->result
1062 return NT_STATUS_OK;
1065 if (selected_transfer == NULL) {
1067 * We report this only via ack->result
1069 return NT_STATUS_OK;
1072 ack->result = DCERPC_BIND_ACK_RESULT_USER_REJECTION;
1073 ack->reason.value = DCERPC_BIND_ACK_REASON_LOCAL_LIMIT_EXCEEDED;
1075 /* add this context to the list of available context_ids */
1076 context = talloc_zero(call->conn, struct dcesrv_connection_context);
1077 if (context == NULL) {
1078 return NT_STATUS_NO_MEMORY;
1080 context->conn = call->conn;
1081 context->context_id = ctx->context_id;
1082 context->iface = iface;
1083 context->transfer_syntax = *selected_transfer;
1084 context->private_data = NULL;
1085 DLIST_ADD(call->conn->contexts, context);
1086 call->context = context;
1087 talloc_set_destructor(context, dcesrv_connection_context_destructor);
1089 dcesrv_prepare_context_auth(call);
1091 status = iface->bind(call, iface, if_version);
1092 call->context = NULL;
1093 if (!NT_STATUS_IS_OK(status)) {
1094 /* we don't want to trigger the iface->unbind() hook */
1095 context->iface = NULL;
1096 talloc_free(context);
1098 * We report this only via ack->result
1100 return NT_STATUS_OK;
1103 ack->result = DCERPC_BIND_ACK_RESULT_ACCEPTANCE;
1104 ack->reason.value = DCERPC_BIND_ACK_REASON_NOT_SPECIFIED;
1105 ack->syntax = context->transfer_syntax;
1106 return NT_STATUS_OK;
1109 static NTSTATUS dcesrv_negotiate_contexts(struct dcesrv_call_state *call,
1110 const struct dcerpc_bind *b,
1111 struct dcerpc_ack_ctx *ack_ctx_list)
1113 NTSTATUS status;
1114 size_t i;
1115 bool validate_only = false;
1116 bool preferred_ndr32;
1119 * Try to negotiate one new presentation context,
1120 * using our preferred transfer syntax.
1122 for (i = 0; i < b->num_contexts; i++) {
1123 const struct dcerpc_ctx_list *c = &b->ctx_list[i];
1124 struct dcerpc_ack_ctx *a = &ack_ctx_list[i];
1126 status = dcesrv_check_or_create_context(call, b, c, a,
1127 validate_only,
1128 call->conn->preferred_transfer);
1129 if (!NT_STATUS_IS_OK(status)) {
1130 return status;
1133 if (a->result == DCERPC_BIND_ACK_RESULT_ACCEPTANCE) {
1135 * We managed to negotiate one context.
1137 * => we're done.
1139 validate_only = true;
1143 preferred_ndr32 = ndr_syntax_id_equal(&ndr_transfer_syntax_ndr,
1144 call->conn->preferred_transfer);
1145 if (preferred_ndr32) {
1147 * We're done.
1149 return NT_STATUS_OK;
1153 * Try to negotiate one new presentation context,
1154 * using NDR 32 as fallback.
1156 for (i = 0; i < b->num_contexts; i++) {
1157 const struct dcerpc_ctx_list *c = &b->ctx_list[i];
1158 struct dcerpc_ack_ctx *a = &ack_ctx_list[i];
1160 status = dcesrv_check_or_create_context(call, b, c, a,
1161 validate_only,
1162 &ndr_transfer_syntax_ndr);
1163 if (!NT_STATUS_IS_OK(status)) {
1164 return status;
1167 if (a->result == DCERPC_BIND_ACK_RESULT_ACCEPTANCE) {
1169 * We managed to negotiate one context.
1171 * => we're done.
1173 validate_only = true;
1177 return NT_STATUS_OK;
1181 handle a alter context request
1183 static NTSTATUS dcesrv_alter(struct dcesrv_call_state *call)
1185 NTSTATUS status;
1186 bool auth_ok = false;
1187 struct ncacn_packet pkt;
1188 uint32_t extra_flags = 0;
1189 struct data_blob_list_item *rep = NULL;
1190 struct dcerpc_ack_ctx *ack_ctx_list = NULL;
1191 size_t i;
1193 if (!call->conn->allow_alter) {
1194 return dcesrv_fault_disconnect(call, DCERPC_NCA_S_PROTO_ERROR);
1197 status = dcerpc_verify_ncacn_packet_header(&call->pkt,
1198 DCERPC_PKT_ALTER,
1199 call->pkt.u.alter.auth_info.length,
1200 0, /* required flags */
1201 DCERPC_PFC_FLAG_FIRST |
1202 DCERPC_PFC_FLAG_LAST |
1203 DCERPC_PFC_FLAG_SUPPORT_HEADER_SIGN |
1204 0x08 | /* this is not defined, but should be ignored */
1205 DCERPC_PFC_FLAG_CONC_MPX |
1206 DCERPC_PFC_FLAG_DID_NOT_EXECUTE |
1207 DCERPC_PFC_FLAG_MAYBE |
1208 DCERPC_PFC_FLAG_OBJECT_UUID);
1209 if (!NT_STATUS_IS_OK(status)) {
1210 return dcesrv_fault_disconnect(call, DCERPC_NCA_S_PROTO_ERROR);
1213 auth_ok = dcesrv_auth_alter(call);
1214 if (!auth_ok) {
1215 if (call->fault_code != 0) {
1216 return dcesrv_fault_disconnect(call, call->fault_code);
1220 if (call->pkt.u.alter.num_contexts < 1) {
1221 return dcesrv_fault_disconnect(call, DCERPC_NCA_S_PROTO_ERROR);
1224 ack_ctx_list = talloc_zero_array(call, struct dcerpc_ack_ctx,
1225 call->pkt.u.alter.num_contexts);
1226 if (ack_ctx_list == NULL) {
1227 return NT_STATUS_NO_MEMORY;
1231 * Set some sane defaults (required by dcesrv_negotiate_contexts()/
1232 * dcesrv_check_or_create_context()) and do some protocol validation
1233 * and set sane defaults.
1235 for (i = 0; i < call->pkt.u.alter.num_contexts; i++) {
1236 const struct dcerpc_ctx_list *c = &call->pkt.u.alter.ctx_list[i];
1237 struct dcerpc_ack_ctx *a = &ack_ctx_list[i];
1239 if (c->num_transfer_syntaxes == 0) {
1240 return dcesrv_fault_disconnect(call,
1241 DCERPC_NCA_S_PROTO_ERROR);
1244 a->result = DCERPC_BIND_ACK_RESULT_PROVIDER_REJECTION;
1245 a->reason.value = DCERPC_BIND_ACK_REASON_ABSTRACT_SYNTAX_NOT_SUPPORTED;
1249 * Try to negotiate one new presentation context.
1251 status = dcesrv_negotiate_contexts(call, &call->pkt.u.alter, ack_ctx_list);
1252 if (NT_STATUS_EQUAL(status, NT_STATUS_RPC_PROTOCOL_ERROR)) {
1253 return dcesrv_fault_disconnect(call, DCERPC_NCA_S_PROTO_ERROR);
1255 if (!NT_STATUS_IS_OK(status)) {
1256 return status;
1259 if ((call->pkt.pfc_flags & DCERPC_PFC_FLAG_CONC_MPX) &&
1260 (call->state_flags & DCESRV_CALL_STATE_FLAG_MULTIPLEXED)) {
1261 call->conn->state_flags |= DCESRV_CALL_STATE_FLAG_MULTIPLEXED;
1262 extra_flags |= DCERPC_PFC_FLAG_CONC_MPX;
1265 if (call->state_flags & DCESRV_CALL_STATE_FLAG_PROCESS_PENDING_CALL) {
1266 call->conn->state_flags |= DCESRV_CALL_STATE_FLAG_PROCESS_PENDING_CALL;
1269 /* handle any authentication that is being requested */
1270 if (!auth_ok) {
1271 if (call->in_auth_info.auth_type !=
1272 call->conn->auth_state.auth_type)
1274 return dcesrv_fault_disconnect(call,
1275 DCERPC_FAULT_SEC_PKG_ERROR);
1277 return dcesrv_fault_disconnect(call, DCERPC_FAULT_ACCESS_DENIED);
1280 dcesrv_init_hdr(&pkt, lpcfg_rpc_big_endian(call->conn->dce_ctx->lp_ctx));
1281 pkt.auth_length = 0;
1282 pkt.call_id = call->pkt.call_id;
1283 pkt.ptype = DCERPC_PKT_ALTER_RESP;
1284 pkt.pfc_flags = DCERPC_PFC_FLAG_FIRST | DCERPC_PFC_FLAG_LAST | extra_flags;
1285 pkt.u.alter_resp.max_xmit_frag = call->conn->max_xmit_frag;
1286 pkt.u.alter_resp.max_recv_frag = call->conn->max_recv_frag;
1287 pkt.u.alter_resp.assoc_group_id = call->conn->assoc_group->id;
1288 pkt.u.alter_resp.secondary_address = "";
1289 pkt.u.alter_resp.num_results = call->pkt.u.alter.num_contexts;
1290 pkt.u.alter_resp.ctx_list = ack_ctx_list;
1291 pkt.u.alter_resp.auth_info = data_blob_null;
1293 status = dcesrv_auth_alter_ack(call, &pkt);
1294 if (!NT_STATUS_IS_OK(status)) {
1295 return dcesrv_fault_disconnect(call, DCERPC_FAULT_SEC_PKG_ERROR);
1298 rep = talloc_zero(call, struct data_blob_list_item);
1299 if (!rep) {
1300 return NT_STATUS_NO_MEMORY;
1303 status = ncacn_push_auth(&rep->blob, call, &pkt, call->out_auth_info);
1304 if (!NT_STATUS_IS_OK(status)) {
1305 return status;
1308 dcerpc_set_frag_length(&rep->blob, rep->blob.length);
1310 DLIST_ADD_END(call->replies, rep);
1311 dcesrv_call_set_list(call, DCESRV_LIST_CALL_LIST);
1313 if (call->conn->call_list && call->conn->call_list->replies) {
1314 if (call->conn->transport.report_output_data) {
1315 call->conn->transport.report_output_data(call->conn);
1319 return NT_STATUS_OK;
1323 possibly save the call for inspection with ndrdump
1325 static void dcesrv_save_call(struct dcesrv_call_state *call, const char *why)
1327 #ifdef DEVELOPER
1328 char *fname;
1329 const char *dump_dir;
1330 dump_dir = lpcfg_parm_string(call->conn->dce_ctx->lp_ctx, NULL, "dcesrv", "stubs directory");
1331 if (!dump_dir) {
1332 return;
1334 fname = talloc_asprintf(call, "%s/RPC-%s-%u-%s.dat",
1335 dump_dir,
1336 call->context->iface->name,
1337 call->pkt.u.request.opnum,
1338 why);
1339 if (file_save(fname, call->pkt.u.request.stub_and_verifier.data, call->pkt.u.request.stub_and_verifier.length)) {
1340 DEBUG(0,("RPC SAVED %s\n", fname));
1342 talloc_free(fname);
1343 #endif
1346 static NTSTATUS dcesrv_check_verification_trailer(struct dcesrv_call_state *call)
1348 TALLOC_CTX *frame = talloc_stackframe();
1349 const uint32_t bitmask1 = call->conn->auth_state.client_hdr_signing ?
1350 DCERPC_SEC_VT_CLIENT_SUPPORTS_HEADER_SIGNING : 0;
1351 const struct dcerpc_sec_vt_pcontext pcontext = {
1352 .abstract_syntax = call->context->iface->syntax_id,
1353 .transfer_syntax = call->context->transfer_syntax,
1355 const struct dcerpc_sec_vt_header2 header2 =
1356 dcerpc_sec_vt_header2_from_ncacn_packet(&call->pkt);
1357 enum ndr_err_code ndr_err;
1358 struct dcerpc_sec_verification_trailer *vt = NULL;
1359 NTSTATUS status = NT_STATUS_OK;
1360 bool ok;
1362 SMB_ASSERT(call->pkt.ptype == DCERPC_PKT_REQUEST);
1364 ndr_err = ndr_pop_dcerpc_sec_verification_trailer(call->ndr_pull,
1365 frame, &vt);
1366 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
1367 status = ndr_map_error2ntstatus(ndr_err);
1368 goto done;
1371 ok = dcerpc_sec_verification_trailer_check(vt, &bitmask1,
1372 &pcontext, &header2);
1373 if (!ok) {
1374 status = NT_STATUS_ACCESS_DENIED;
1375 goto done;
1377 done:
1378 TALLOC_FREE(frame);
1379 return status;
1383 handle a dcerpc request packet
1385 static NTSTATUS dcesrv_request(struct dcesrv_call_state *call)
1387 const struct dcesrv_endpoint *endpoint = call->conn->endpoint;
1388 enum dcerpc_transport_t transport =
1389 dcerpc_binding_get_transport(endpoint->ep_description);
1390 struct ndr_pull *pull;
1391 NTSTATUS status;
1392 struct dcesrv_connection_context *context;
1394 if (!call->conn->allow_request) {
1395 return dcesrv_fault_disconnect(call, DCERPC_NCA_S_PROTO_ERROR);
1398 /* if authenticated, and the mech we use can't do async replies, don't use them... */
1399 if (call->conn->auth_state.gensec_security &&
1400 !gensec_have_feature(call->conn->auth_state.gensec_security, GENSEC_FEATURE_ASYNC_REPLIES)) {
1401 call->state_flags &= ~DCESRV_CALL_STATE_FLAG_MAY_ASYNC;
1404 context = dcesrv_find_context(call->conn, call->pkt.u.request.context_id);
1405 if (context == NULL) {
1406 return dcesrv_fault_with_flags(call, DCERPC_NCA_S_UNKNOWN_IF,
1407 DCERPC_PFC_FLAG_DID_NOT_EXECUTE);
1410 switch (call->conn->auth_state.auth_level) {
1411 case DCERPC_AUTH_LEVEL_NONE:
1412 case DCERPC_AUTH_LEVEL_PACKET:
1413 case DCERPC_AUTH_LEVEL_INTEGRITY:
1414 case DCERPC_AUTH_LEVEL_PRIVACY:
1415 break;
1416 default:
1417 if (!context->allow_connect) {
1418 char *addr;
1420 addr = tsocket_address_string(call->conn->remote_address,
1421 call);
1423 DEBUG(2, ("%s: restrict auth_level_connect access "
1424 "to [%s] with auth[type=0x%x,level=0x%x] "
1425 "on [%s] from [%s]\n",
1426 __func__, context->iface->name,
1427 call->conn->auth_state.auth_type,
1428 call->conn->auth_state.auth_level,
1429 derpc_transport_string_by_transport(transport),
1430 addr));
1431 return dcesrv_fault(call, DCERPC_FAULT_ACCESS_DENIED);
1433 break;
1436 if (call->conn->auth_state.auth_level < context->min_auth_level) {
1437 char *addr;
1439 addr = tsocket_address_string(call->conn->remote_address, call);
1441 DEBUG(2, ("%s: restrict access by min_auth_level[0x%x] "
1442 "to [%s] with auth[type=0x%x,level=0x%x] "
1443 "on [%s] from [%s]\n",
1444 __func__,
1445 context->min_auth_level,
1446 context->iface->name,
1447 call->conn->auth_state.auth_type,
1448 call->conn->auth_state.auth_level,
1449 derpc_transport_string_by_transport(transport),
1450 addr));
1451 return dcesrv_fault(call, DCERPC_FAULT_ACCESS_DENIED);
1454 pull = ndr_pull_init_blob(&call->pkt.u.request.stub_and_verifier, call);
1455 NT_STATUS_HAVE_NO_MEMORY(pull);
1457 pull->flags |= LIBNDR_FLAG_REF_ALLOC;
1459 call->context = context;
1460 call->ndr_pull = pull;
1462 if (!(call->pkt.drep[0] & DCERPC_DREP_LE)) {
1463 pull->flags |= LIBNDR_FLAG_BIGENDIAN;
1466 status = dcesrv_check_verification_trailer(call);
1467 if (!NT_STATUS_IS_OK(status)) {
1468 uint32_t faultcode = DCERPC_FAULT_OTHER;
1469 if (NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
1470 faultcode = DCERPC_FAULT_ACCESS_DENIED;
1472 DEBUG(10, ("dcesrv_check_verification_trailer failed: %s\n",
1473 nt_errstr(status)));
1474 return dcesrv_fault(call, faultcode);
1477 /* unravel the NDR for the packet */
1478 status = context->iface->ndr_pull(call, call, pull, &call->r);
1479 if (!NT_STATUS_IS_OK(status)) {
1480 uint8_t extra_flags = 0;
1481 if (call->fault_code == DCERPC_FAULT_OP_RNG_ERROR) {
1482 /* we got an unknown call */
1483 DEBUG(3,(__location__ ": Unknown RPC call %u on %s\n",
1484 call->pkt.u.request.opnum, context->iface->name));
1485 dcesrv_save_call(call, "unknown");
1486 extra_flags |= DCERPC_PFC_FLAG_DID_NOT_EXECUTE;
1487 } else {
1488 dcesrv_save_call(call, "pullfail");
1490 return dcesrv_fault_with_flags(call, call->fault_code, extra_flags);
1493 if (pull->offset != pull->data_size) {
1494 dcesrv_save_call(call, "extrabytes");
1495 DEBUG(3,("Warning: %d extra bytes in incoming RPC request\n",
1496 pull->data_size - pull->offset));
1499 /* call the dispatch function */
1500 status = context->iface->dispatch(call, call, call->r);
1501 if (!NT_STATUS_IS_OK(status)) {
1502 DEBUG(5,("dcerpc fault in call %s:%02x - %s\n",
1503 context->iface->name,
1504 call->pkt.u.request.opnum,
1505 dcerpc_errstr(pull, call->fault_code)));
1506 return dcesrv_fault(call, call->fault_code);
1509 /* add the call to the pending list */
1510 dcesrv_call_set_list(call, DCESRV_LIST_PENDING_CALL_LIST);
1512 if (call->state_flags & DCESRV_CALL_STATE_FLAG_ASYNC) {
1513 return NT_STATUS_OK;
1516 return dcesrv_reply(call);
1521 remove the call from the right list when freed
1523 static int dcesrv_call_dequeue(struct dcesrv_call_state *call)
1525 dcesrv_call_set_list(call, DCESRV_LIST_NONE);
1526 return 0;
1529 _PUBLIC_ const struct tsocket_address *dcesrv_connection_get_local_address(struct dcesrv_connection *conn)
1531 return conn->local_address;
1534 _PUBLIC_ const struct tsocket_address *dcesrv_connection_get_remote_address(struct dcesrv_connection *conn)
1536 return conn->remote_address;
1540 process some input to a dcerpc endpoint server.
1542 static NTSTATUS dcesrv_process_ncacn_packet(struct dcesrv_connection *dce_conn,
1543 struct ncacn_packet *pkt,
1544 DATA_BLOB blob)
1546 NTSTATUS status;
1547 struct dcesrv_call_state *call;
1548 struct dcesrv_call_state *existing = NULL;
1550 call = talloc_zero(dce_conn, struct dcesrv_call_state);
1551 if (!call) {
1552 data_blob_free(&blob);
1553 talloc_free(pkt);
1554 return NT_STATUS_NO_MEMORY;
1556 call->conn = dce_conn;
1557 call->event_ctx = dce_conn->event_ctx;
1558 call->msg_ctx = dce_conn->msg_ctx;
1559 call->state_flags = call->conn->state_flags;
1560 call->time = timeval_current();
1561 call->list = DCESRV_LIST_NONE;
1563 talloc_steal(call, pkt);
1564 talloc_steal(call, blob.data);
1565 call->pkt = *pkt;
1567 talloc_set_destructor(call, dcesrv_call_dequeue);
1569 if (call->conn->allow_bind) {
1571 * Only one bind is possible per connection
1573 call->conn->allow_bind = false;
1574 return dcesrv_bind(call);
1577 /* we have to check the signing here, before combining the
1578 pdus */
1579 if (call->pkt.ptype == DCERPC_PKT_REQUEST) {
1580 if (!call->conn->allow_request) {
1581 return dcesrv_fault_disconnect(call,
1582 DCERPC_NCA_S_PROTO_ERROR);
1585 status = dcerpc_verify_ncacn_packet_header(&call->pkt,
1586 DCERPC_PKT_REQUEST,
1587 call->pkt.u.request.stub_and_verifier.length,
1588 0, /* required_flags */
1589 DCERPC_PFC_FLAG_FIRST |
1590 DCERPC_PFC_FLAG_LAST |
1591 DCERPC_PFC_FLAG_PENDING_CANCEL |
1592 0x08 | /* this is not defined, but should be ignored */
1593 DCERPC_PFC_FLAG_CONC_MPX |
1594 DCERPC_PFC_FLAG_DID_NOT_EXECUTE |
1595 DCERPC_PFC_FLAG_MAYBE |
1596 DCERPC_PFC_FLAG_OBJECT_UUID);
1597 if (!NT_STATUS_IS_OK(status)) {
1598 return dcesrv_fault_disconnect(call,
1599 DCERPC_NCA_S_PROTO_ERROR);
1602 if (call->pkt.frag_length > DCERPC_FRAG_MAX_SIZE) {
1604 * We don't use dcesrv_fault_disconnect()
1605 * here, because we don't want to set
1606 * DCERPC_PFC_FLAG_DID_NOT_EXECUTE
1608 * Note that we don't check against the negotiated
1609 * max_recv_frag, but a hard coded value.
1611 dcesrv_call_disconnect_after(call,
1612 "dcesrv_auth_request - frag_length too large");
1613 return dcesrv_fault(call,
1614 DCERPC_NCA_S_PROTO_ERROR);
1617 if (call->pkt.pfc_flags & DCERPC_PFC_FLAG_FIRST) {
1618 /* only one request is possible in the fragmented list */
1619 if (dce_conn->incoming_fragmented_call_list != NULL) {
1620 TALLOC_FREE(call);
1621 call = dce_conn->incoming_fragmented_call_list;
1622 dcesrv_call_disconnect_after(call,
1623 "dcesrv_auth_request - "
1624 "existing fragmented call");
1625 return dcesrv_fault(call,
1626 DCERPC_NCA_S_PROTO_ERROR);
1628 if (call->pkt.pfc_flags & DCERPC_PFC_FLAG_PENDING_CANCEL) {
1629 return dcesrv_fault_disconnect(call,
1630 DCERPC_FAULT_NO_CALL_ACTIVE);
1632 } else {
1633 const struct dcerpc_request *nr = &call->pkt.u.request;
1634 const struct dcerpc_request *er = NULL;
1635 int cmp;
1637 existing = dcesrv_find_fragmented_call(dce_conn,
1638 call->pkt.call_id);
1639 if (existing == NULL) {
1640 dcesrv_call_disconnect_after(call,
1641 "dcesrv_auth_request - "
1642 "no existing fragmented call");
1643 return dcesrv_fault(call,
1644 DCERPC_NCA_S_PROTO_ERROR);
1646 er = &existing->pkt.u.request;
1648 if (call->pkt.ptype != existing->pkt.ptype) {
1649 /* trying to play silly buggers are we? */
1650 return dcesrv_fault_disconnect(existing,
1651 DCERPC_NCA_S_PROTO_ERROR);
1653 cmp = memcmp(call->pkt.drep, existing->pkt.drep,
1654 sizeof(pkt->drep));
1655 if (cmp != 0) {
1656 return dcesrv_fault_disconnect(existing,
1657 DCERPC_NCA_S_PROTO_ERROR);
1659 if (nr->context_id != er->context_id) {
1660 return dcesrv_fault_disconnect(existing,
1661 DCERPC_NCA_S_PROTO_ERROR);
1663 if (nr->opnum != er->opnum) {
1664 return dcesrv_fault_disconnect(existing,
1665 DCERPC_NCA_S_PROTO_ERROR);
1670 if (call->pkt.ptype == DCERPC_PKT_REQUEST) {
1671 bool ok;
1672 uint8_t payload_offset = DCERPC_REQUEST_LENGTH;
1674 if (call->pkt.pfc_flags & DCERPC_PFC_FLAG_OBJECT_UUID) {
1675 payload_offset += 16;
1678 ok = dcesrv_auth_pkt_pull(call, &blob,
1679 0, /* required_flags */
1680 DCERPC_PFC_FLAG_FIRST |
1681 DCERPC_PFC_FLAG_LAST |
1682 DCERPC_PFC_FLAG_PENDING_CANCEL |
1683 0x08 | /* this is not defined, but should be ignored */
1684 DCERPC_PFC_FLAG_CONC_MPX |
1685 DCERPC_PFC_FLAG_DID_NOT_EXECUTE |
1686 DCERPC_PFC_FLAG_MAYBE |
1687 DCERPC_PFC_FLAG_OBJECT_UUID,
1688 payload_offset,
1689 &call->pkt.u.request.stub_and_verifier);
1690 if (!ok) {
1692 * We don't use dcesrv_fault_disconnect()
1693 * here, because we don't want to set
1694 * DCERPC_PFC_FLAG_DID_NOT_EXECUTE
1696 dcesrv_call_disconnect_after(call,
1697 "dcesrv_auth_request - failed");
1698 if (call->fault_code == 0) {
1699 call->fault_code = DCERPC_FAULT_ACCESS_DENIED;
1701 return dcesrv_fault(call, call->fault_code);
1705 /* see if this is a continued packet */
1706 if (existing != NULL) {
1707 struct dcerpc_request *er = &existing->pkt.u.request;
1708 const struct dcerpc_request *nr = &call->pkt.u.request;
1709 size_t available;
1710 size_t alloc_size;
1711 size_t alloc_hint;
1714 * Up to 4 MByte are allowed by all fragments
1716 available = dce_conn->max_total_request_size;
1717 if (er->stub_and_verifier.length > available) {
1718 dcesrv_call_disconnect_after(existing,
1719 "dcesrv_auth_request - existing payload too large");
1720 return dcesrv_fault(existing, DCERPC_FAULT_ACCESS_DENIED);
1722 available -= er->stub_and_verifier.length;
1723 if (nr->alloc_hint > available) {
1724 dcesrv_call_disconnect_after(existing,
1725 "dcesrv_auth_request - alloc hint too large");
1726 return dcesrv_fault(existing, DCERPC_FAULT_ACCESS_DENIED);
1728 if (nr->stub_and_verifier.length > available) {
1729 dcesrv_call_disconnect_after(existing,
1730 "dcesrv_auth_request - new payload too large");
1731 return dcesrv_fault(existing, DCERPC_FAULT_ACCESS_DENIED);
1733 alloc_hint = er->stub_and_verifier.length + nr->alloc_hint;
1734 /* allocate at least 1 byte */
1735 alloc_hint = MAX(alloc_hint, 1);
1736 alloc_size = er->stub_and_verifier.length +
1737 nr->stub_and_verifier.length;
1738 alloc_size = MAX(alloc_size, alloc_hint);
1740 er->stub_and_verifier.data =
1741 talloc_realloc(existing,
1742 er->stub_and_verifier.data,
1743 uint8_t, alloc_size);
1744 if (er->stub_and_verifier.data == NULL) {
1745 TALLOC_FREE(call);
1746 return dcesrv_fault_with_flags(existing,
1747 DCERPC_FAULT_OUT_OF_RESOURCES,
1748 DCERPC_PFC_FLAG_DID_NOT_EXECUTE);
1750 memcpy(er->stub_and_verifier.data +
1751 er->stub_and_verifier.length,
1752 nr->stub_and_verifier.data,
1753 nr->stub_and_verifier.length);
1754 er->stub_and_verifier.length += nr->stub_and_verifier.length;
1756 existing->pkt.pfc_flags |= (call->pkt.pfc_flags & DCERPC_PFC_FLAG_LAST);
1758 TALLOC_FREE(call);
1759 call = existing;
1762 /* this may not be the last pdu in the chain - if its isn't then
1763 just put it on the incoming_fragmented_call_list and wait for the rest */
1764 if (call->pkt.ptype == DCERPC_PKT_REQUEST &&
1765 !(call->pkt.pfc_flags & DCERPC_PFC_FLAG_LAST)) {
1767 * Up to 4 MByte are allowed by all fragments
1769 if (call->pkt.u.request.alloc_hint > dce_conn->max_total_request_size) {
1770 dcesrv_call_disconnect_after(call,
1771 "dcesrv_auth_request - initial alloc hint too large");
1772 return dcesrv_fault(call, DCERPC_FAULT_ACCESS_DENIED);
1774 dcesrv_call_set_list(call, DCESRV_LIST_FRAGMENTED_CALL_LIST);
1775 return NT_STATUS_OK;
1778 /* This removes any fragments we may have had stashed away */
1779 dcesrv_call_set_list(call, DCESRV_LIST_NONE);
1781 switch (call->pkt.ptype) {
1782 case DCERPC_PKT_BIND:
1783 status = dcesrv_bind_nak(call,
1784 DCERPC_BIND_NAK_REASON_NOT_SPECIFIED);
1785 break;
1786 case DCERPC_PKT_AUTH3:
1787 status = dcesrv_auth3(call);
1788 break;
1789 case DCERPC_PKT_ALTER:
1790 status = dcesrv_alter(call);
1791 break;
1792 case DCERPC_PKT_REQUEST:
1793 status = dcesrv_request(call);
1794 break;
1795 case DCERPC_PKT_BIND_ACK:
1796 case DCERPC_PKT_BIND_NAK:
1797 case DCERPC_PKT_ALTER_RESP:
1798 case DCERPC_PKT_RESPONSE:
1799 case DCERPC_PKT_FAULT:
1800 case DCERPC_PKT_SHUTDOWN:
1801 case DCERPC_PKT_CO_CANCEL:
1802 case DCERPC_PKT_ORPHANED:
1803 default:
1804 status = dcesrv_fault_disconnect(call, DCERPC_NCA_S_PROTO_ERROR);
1805 break;
1808 /* if we are going to be sending a reply then add
1809 it to the list of pending calls. We add it to the end to keep the call
1810 list in the order we will answer */
1811 if (!NT_STATUS_IS_OK(status)) {
1812 talloc_free(call);
1815 return status;
1818 _PUBLIC_ NTSTATUS dcesrv_init_context(TALLOC_CTX *mem_ctx,
1819 struct loadparm_context *lp_ctx,
1820 const char **endpoint_servers, struct dcesrv_context **_dce_ctx)
1822 NTSTATUS status;
1823 struct dcesrv_context *dce_ctx;
1824 int i;
1826 if (!endpoint_servers) {
1827 DEBUG(0,("dcesrv_init_context: no endpoint servers configured\n"));
1828 return NT_STATUS_INTERNAL_ERROR;
1831 dce_ctx = talloc_zero(mem_ctx, struct dcesrv_context);
1832 NT_STATUS_HAVE_NO_MEMORY(dce_ctx);
1834 if (uid_wrapper_enabled()) {
1835 setenv("UID_WRAPPER_MYUID", "1", 1);
1837 dce_ctx->initial_euid = geteuid();
1838 if (uid_wrapper_enabled()) {
1839 unsetenv("UID_WRAPPER_MYUID");
1842 dce_ctx->endpoint_list = NULL;
1843 dce_ctx->lp_ctx = lp_ctx;
1844 dce_ctx->assoc_groups_idr = idr_init(dce_ctx);
1845 NT_STATUS_HAVE_NO_MEMORY(dce_ctx->assoc_groups_idr);
1846 dce_ctx->broken_connections = NULL;
1848 for (i=0;endpoint_servers[i];i++) {
1849 const struct dcesrv_endpoint_server *ep_server;
1851 ep_server = dcesrv_ep_server_byname(endpoint_servers[i]);
1852 if (!ep_server) {
1853 DEBUG(0,("dcesrv_init_context: failed to find endpoint server = '%s'\n", endpoint_servers[i]));
1854 return NT_STATUS_INTERNAL_ERROR;
1857 status = ep_server->init_server(dce_ctx, ep_server);
1858 if (!NT_STATUS_IS_OK(status)) {
1859 DEBUG(0,("dcesrv_init_context: failed to init endpoint server = '%s': %s\n", endpoint_servers[i],
1860 nt_errstr(status)));
1861 return status;
1865 *_dce_ctx = dce_ctx;
1866 return NT_STATUS_OK;
1869 /* the list of currently registered DCERPC endpoint servers.
1871 static struct ep_server {
1872 struct dcesrv_endpoint_server *ep_server;
1873 } *ep_servers = NULL;
1874 static int num_ep_servers;
1877 register a DCERPC endpoint server.
1879 The 'name' can be later used by other backends to find the operations
1880 structure for this backend.
1882 The 'type' is used to specify whether this is for a disk, printer or IPC$ share
1884 _PUBLIC_ NTSTATUS dcerpc_register_ep_server(const void *_ep_server)
1886 const struct dcesrv_endpoint_server *ep_server = _ep_server;
1888 if (dcesrv_ep_server_byname(ep_server->name) != NULL) {
1889 /* its already registered! */
1890 DEBUG(0,("DCERPC endpoint server '%s' already registered\n",
1891 ep_server->name));
1892 return NT_STATUS_OBJECT_NAME_COLLISION;
1895 ep_servers = realloc_p(ep_servers, struct ep_server, num_ep_servers+1);
1896 if (!ep_servers) {
1897 smb_panic("out of memory in dcerpc_register");
1900 ep_servers[num_ep_servers].ep_server = smb_xmemdup(ep_server, sizeof(*ep_server));
1901 ep_servers[num_ep_servers].ep_server->name = smb_xstrdup(ep_server->name);
1903 num_ep_servers++;
1905 DEBUG(3,("DCERPC endpoint server '%s' registered\n",
1906 ep_server->name));
1908 return NT_STATUS_OK;
1912 return the operations structure for a named backend of the specified type
1914 const struct dcesrv_endpoint_server *dcesrv_ep_server_byname(const char *name)
1916 int i;
1918 for (i=0;i<num_ep_servers;i++) {
1919 if (strcmp(ep_servers[i].ep_server->name, name) == 0) {
1920 return ep_servers[i].ep_server;
1924 return NULL;
1927 void dcerpc_server_init(struct loadparm_context *lp_ctx)
1929 static bool initialized;
1930 #define _MODULE_PROTO(init) extern NTSTATUS init(void);
1931 STATIC_dcerpc_server_MODULES_PROTO;
1932 init_module_fn static_init[] = { STATIC_dcerpc_server_MODULES };
1933 init_module_fn *shared_init;
1935 if (initialized) {
1936 return;
1938 initialized = true;
1940 shared_init = load_samba_modules(NULL, "dcerpc_server");
1942 run_init_functions(static_init);
1943 run_init_functions(shared_init);
1945 talloc_free(shared_init);
1949 return the DCERPC module version, and the size of some critical types
1950 This can be used by endpoint server modules to either detect compilation errors, or provide
1951 multiple implementations for different smbd compilation options in one module
1953 const struct dcesrv_critical_sizes *dcerpc_module_version(void)
1955 static const struct dcesrv_critical_sizes critical_sizes = {
1956 DCERPC_MODULE_VERSION,
1957 sizeof(struct dcesrv_context),
1958 sizeof(struct dcesrv_endpoint),
1959 sizeof(struct dcesrv_endpoint_server),
1960 sizeof(struct dcesrv_interface),
1961 sizeof(struct dcesrv_if_list),
1962 sizeof(struct dcesrv_connection),
1963 sizeof(struct dcesrv_call_state),
1964 sizeof(struct dcesrv_auth),
1965 sizeof(struct dcesrv_handle)
1968 return &critical_sizes;
1971 static void dcesrv_terminate_connection(struct dcesrv_connection *dce_conn, const char *reason)
1973 struct dcesrv_context *dce_ctx = dce_conn->dce_ctx;
1974 struct stream_connection *srv_conn;
1975 srv_conn = talloc_get_type(dce_conn->transport.private_data,
1976 struct stream_connection);
1978 dce_conn->allow_bind = false;
1979 dce_conn->allow_auth3 = false;
1980 dce_conn->allow_alter = false;
1981 dce_conn->allow_request = false;
1983 if (dce_conn->pending_call_list == NULL) {
1984 char *full_reason = talloc_asprintf(dce_conn, "dcesrv: %s", reason);
1986 DLIST_REMOVE(dce_ctx->broken_connections, dce_conn);
1987 stream_terminate_connection(srv_conn, full_reason ? full_reason : reason);
1988 return;
1991 if (dce_conn->terminate != NULL) {
1992 return;
1995 DEBUG(3,("dcesrv: terminating connection due to '%s' defered due to pending calls\n",
1996 reason));
1997 dce_conn->terminate = talloc_strdup(dce_conn, reason);
1998 if (dce_conn->terminate == NULL) {
1999 dce_conn->terminate = "dcesrv: defered terminating connection - no memory";
2001 DLIST_ADD_END(dce_ctx->broken_connections, dce_conn);
2004 static void dcesrv_cleanup_broken_connections(struct dcesrv_context *dce_ctx)
2006 struct dcesrv_connection *cur, *next;
2008 next = dce_ctx->broken_connections;
2009 while (next != NULL) {
2010 cur = next;
2011 next = cur->next;
2013 if (cur->state_flags & DCESRV_CALL_STATE_FLAG_PROCESS_PENDING_CALL) {
2014 struct dcesrv_connection_context *context_cur, *context_next;
2016 context_next = cur->contexts;
2017 while (context_next != NULL) {
2018 context_cur = context_next;
2019 context_next = context_cur->next;
2021 dcesrv_connection_context_destructor(context_cur);
2025 dcesrv_terminate_connection(cur, cur->terminate);
2029 /* We need this include to be able to compile on some plateforms
2030 * (ie. freebsd 7.2) as it seems that <sys/uio.h> is not included
2031 * correctly.
2032 * It has to be that deep because otherwise we have a conflict on
2033 * const struct dcesrv_interface declaration.
2034 * This is mostly due to socket_wrapper defining #define bind swrap_bind
2035 * which conflict with the bind used before.
2037 #include "system/network.h"
2039 struct dcesrv_sock_reply_state {
2040 struct dcesrv_connection *dce_conn;
2041 struct dcesrv_call_state *call;
2042 struct iovec iov;
2045 static void dcesrv_sock_reply_done(struct tevent_req *subreq);
2046 static void dcesrv_call_terminate_step1(struct tevent_req *subreq);
2048 static void dcesrv_sock_report_output_data(struct dcesrv_connection *dce_conn)
2050 struct dcesrv_call_state *call;
2052 call = dce_conn->call_list;
2053 if (!call || !call->replies) {
2054 return;
2057 while (call->replies) {
2058 struct data_blob_list_item *rep = call->replies;
2059 struct dcesrv_sock_reply_state *substate;
2060 struct tevent_req *subreq;
2062 substate = talloc_zero(call, struct dcesrv_sock_reply_state);
2063 if (!substate) {
2064 dcesrv_terminate_connection(dce_conn, "no memory");
2065 return;
2068 substate->dce_conn = dce_conn;
2069 substate->call = NULL;
2071 DLIST_REMOVE(call->replies, rep);
2073 if (call->replies == NULL && call->terminate_reason == NULL) {
2074 substate->call = call;
2077 substate->iov.iov_base = (void *) rep->blob.data;
2078 substate->iov.iov_len = rep->blob.length;
2080 subreq = tstream_writev_queue_send(substate,
2081 dce_conn->event_ctx,
2082 dce_conn->stream,
2083 dce_conn->send_queue,
2084 &substate->iov, 1);
2085 if (!subreq) {
2086 dcesrv_terminate_connection(dce_conn, "no memory");
2087 return;
2089 tevent_req_set_callback(subreq, dcesrv_sock_reply_done,
2090 substate);
2093 if (call->terminate_reason != NULL) {
2094 struct tevent_req *subreq;
2096 subreq = tevent_queue_wait_send(call,
2097 dce_conn->event_ctx,
2098 dce_conn->send_queue);
2099 if (!subreq) {
2100 dcesrv_terminate_connection(dce_conn, __location__);
2101 return;
2103 tevent_req_set_callback(subreq, dcesrv_call_terminate_step1,
2104 call);
2107 DLIST_REMOVE(call->conn->call_list, call);
2108 call->list = DCESRV_LIST_NONE;
2111 static void dcesrv_sock_reply_done(struct tevent_req *subreq)
2113 struct dcesrv_sock_reply_state *substate = tevent_req_callback_data(subreq,
2114 struct dcesrv_sock_reply_state);
2115 int ret;
2116 int sys_errno;
2117 NTSTATUS status;
2118 struct dcesrv_call_state *call = substate->call;
2120 ret = tstream_writev_queue_recv(subreq, &sys_errno);
2121 TALLOC_FREE(subreq);
2122 if (ret == -1) {
2123 status = map_nt_error_from_unix_common(sys_errno);
2124 dcesrv_terminate_connection(substate->dce_conn, nt_errstr(status));
2125 return;
2128 talloc_free(substate);
2129 if (call) {
2130 talloc_free(call);
2134 static void dcesrv_call_terminate_step2(struct tevent_req *subreq);
2136 static void dcesrv_call_terminate_step1(struct tevent_req *subreq)
2138 struct dcesrv_call_state *call = tevent_req_callback_data(subreq,
2139 struct dcesrv_call_state);
2140 bool ok;
2141 struct timeval tv;
2143 /* make sure we stop send queue before removing subreq */
2144 tevent_queue_stop(call->conn->send_queue);
2146 ok = tevent_queue_wait_recv(subreq);
2147 TALLOC_FREE(subreq);
2148 if (!ok) {
2149 dcesrv_terminate_connection(call->conn, __location__);
2150 return;
2153 /* disconnect after 200 usecs */
2154 tv = timeval_current_ofs_usec(200);
2155 subreq = tevent_wakeup_send(call, call->conn->event_ctx, tv);
2156 if (subreq == NULL) {
2157 dcesrv_terminate_connection(call->conn, __location__);
2158 return;
2160 tevent_req_set_callback(subreq, dcesrv_call_terminate_step2,
2161 call);
2164 static void dcesrv_call_terminate_step2(struct tevent_req *subreq)
2166 struct dcesrv_call_state *call = tevent_req_callback_data(subreq,
2167 struct dcesrv_call_state);
2168 bool ok;
2170 ok = tevent_wakeup_recv(subreq);
2171 TALLOC_FREE(subreq);
2172 if (!ok) {
2173 dcesrv_terminate_connection(call->conn, __location__);
2174 return;
2177 dcesrv_terminate_connection(call->conn, call->terminate_reason);
2180 struct dcesrv_socket_context {
2181 const struct dcesrv_endpoint *endpoint;
2182 struct dcesrv_context *dcesrv_ctx;
2186 static void dcesrv_read_fragment_done(struct tevent_req *subreq);
2188 static void dcesrv_sock_accept(struct stream_connection *srv_conn)
2190 NTSTATUS status;
2191 struct dcesrv_socket_context *dcesrv_sock =
2192 talloc_get_type(srv_conn->private_data, struct dcesrv_socket_context);
2193 enum dcerpc_transport_t transport =
2194 dcerpc_binding_get_transport(dcesrv_sock->endpoint->ep_description);
2195 struct dcesrv_connection *dcesrv_conn = NULL;
2196 int ret;
2197 struct tevent_req *subreq;
2198 struct loadparm_context *lp_ctx = dcesrv_sock->dcesrv_ctx->lp_ctx;
2200 dcesrv_cleanup_broken_connections(dcesrv_sock->dcesrv_ctx);
2202 if (!srv_conn->session_info) {
2203 status = auth_anonymous_session_info(srv_conn,
2204 lp_ctx,
2205 &srv_conn->session_info);
2206 if (!NT_STATUS_IS_OK(status)) {
2207 DEBUG(0,("dcesrv_sock_accept: auth_anonymous_session_info failed: %s\n",
2208 nt_errstr(status)));
2209 stream_terminate_connection(srv_conn, nt_errstr(status));
2210 return;
2214 status = dcesrv_endpoint_connect(dcesrv_sock->dcesrv_ctx,
2215 srv_conn,
2216 dcesrv_sock->endpoint,
2217 srv_conn->session_info,
2218 srv_conn->event.ctx,
2219 srv_conn->msg_ctx,
2220 srv_conn->server_id,
2221 DCESRV_CALL_STATE_FLAG_MAY_ASYNC,
2222 &dcesrv_conn);
2223 if (!NT_STATUS_IS_OK(status)) {
2224 DEBUG(0,("dcesrv_sock_accept: dcesrv_endpoint_connect failed: %s\n",
2225 nt_errstr(status)));
2226 stream_terminate_connection(srv_conn, nt_errstr(status));
2227 return;
2230 dcesrv_conn->transport.private_data = srv_conn;
2231 dcesrv_conn->transport.report_output_data = dcesrv_sock_report_output_data;
2233 TALLOC_FREE(srv_conn->event.fde);
2235 dcesrv_conn->send_queue = tevent_queue_create(dcesrv_conn, "dcesrv send queue");
2236 if (!dcesrv_conn->send_queue) {
2237 status = NT_STATUS_NO_MEMORY;
2238 DEBUG(0,("dcesrv_sock_accept: tevent_queue_create(%s)\n",
2239 nt_errstr(status)));
2240 stream_terminate_connection(srv_conn, nt_errstr(status));
2241 return;
2244 if (transport == NCACN_NP) {
2245 dcesrv_conn->auth_state.session_key = dcesrv_inherited_session_key;
2246 dcesrv_conn->stream = talloc_move(dcesrv_conn,
2247 &srv_conn->tstream);
2248 } else {
2249 ret = tstream_bsd_existing_socket(dcesrv_conn,
2250 socket_get_fd(srv_conn->socket),
2251 &dcesrv_conn->stream);
2252 if (ret == -1) {
2253 status = map_nt_error_from_unix_common(errno);
2254 DEBUG(0, ("dcesrv_sock_accept: "
2255 "failed to setup tstream: %s\n",
2256 nt_errstr(status)));
2257 stream_terminate_connection(srv_conn, nt_errstr(status));
2258 return;
2260 socket_set_flags(srv_conn->socket, SOCKET_FLAG_NOCLOSE);
2263 dcesrv_conn->local_address = srv_conn->local_address;
2264 dcesrv_conn->remote_address = srv_conn->remote_address;
2266 if (transport == NCALRPC) {
2267 uid_t uid;
2268 gid_t gid;
2269 int sock_fd;
2271 sock_fd = socket_get_fd(srv_conn->socket);
2272 if (sock_fd == -1) {
2273 stream_terminate_connection(
2274 srv_conn, "socket_get_fd failed\n");
2275 return;
2278 ret = getpeereid(sock_fd, &uid, &gid);
2279 if (ret == -1) {
2280 status = map_nt_error_from_unix_common(errno);
2281 DEBUG(0, ("dcesrv_sock_accept: "
2282 "getpeereid() failed for NCALRPC: %s\n",
2283 nt_errstr(status)));
2284 stream_terminate_connection(srv_conn, nt_errstr(status));
2285 return;
2287 if (uid == dcesrv_conn->dce_ctx->initial_euid) {
2288 struct tsocket_address *r = NULL;
2290 ret = tsocket_address_unix_from_path(dcesrv_conn,
2291 "/root/ncalrpc_as_system",
2292 &r);
2293 if (ret == -1) {
2294 status = map_nt_error_from_unix_common(errno);
2295 DEBUG(0, ("dcesrv_sock_accept: "
2296 "tsocket_address_unix_from_path() failed for NCALRPC: %s\n",
2297 nt_errstr(status)));
2298 stream_terminate_connection(srv_conn, nt_errstr(status));
2299 return;
2301 dcesrv_conn->remote_address = r;
2305 srv_conn->private_data = dcesrv_conn;
2307 irpc_add_name(srv_conn->msg_ctx, "rpc_server");
2309 subreq = dcerpc_read_ncacn_packet_send(dcesrv_conn,
2310 dcesrv_conn->event_ctx,
2311 dcesrv_conn->stream);
2312 if (!subreq) {
2313 status = NT_STATUS_NO_MEMORY;
2314 DEBUG(0,("dcesrv_sock_accept: dcerpc_read_fragment_buffer_send(%s)\n",
2315 nt_errstr(status)));
2316 stream_terminate_connection(srv_conn, nt_errstr(status));
2317 return;
2319 tevent_req_set_callback(subreq, dcesrv_read_fragment_done, dcesrv_conn);
2321 return;
2324 static void dcesrv_read_fragment_done(struct tevent_req *subreq)
2326 struct dcesrv_connection *dce_conn = tevent_req_callback_data(subreq,
2327 struct dcesrv_connection);
2328 struct dcesrv_context *dce_ctx = dce_conn->dce_ctx;
2329 struct ncacn_packet *pkt;
2330 DATA_BLOB buffer;
2331 NTSTATUS status;
2333 if (dce_conn->terminate) {
2335 * if the current connection is broken
2336 * we need to clean it up before any other connection
2338 dcesrv_terminate_connection(dce_conn, dce_conn->terminate);
2339 dcesrv_cleanup_broken_connections(dce_ctx);
2340 return;
2343 dcesrv_cleanup_broken_connections(dce_ctx);
2345 status = dcerpc_read_ncacn_packet_recv(subreq, dce_conn,
2346 &pkt, &buffer);
2347 TALLOC_FREE(subreq);
2348 if (!NT_STATUS_IS_OK(status)) {
2349 dcesrv_terminate_connection(dce_conn, nt_errstr(status));
2350 return;
2353 status = dcesrv_process_ncacn_packet(dce_conn, pkt, buffer);
2354 if (!NT_STATUS_IS_OK(status)) {
2355 dcesrv_terminate_connection(dce_conn, nt_errstr(status));
2356 return;
2359 subreq = dcerpc_read_ncacn_packet_send(dce_conn,
2360 dce_conn->event_ctx,
2361 dce_conn->stream);
2362 if (!subreq) {
2363 status = NT_STATUS_NO_MEMORY;
2364 dcesrv_terminate_connection(dce_conn, nt_errstr(status));
2365 return;
2367 tevent_req_set_callback(subreq, dcesrv_read_fragment_done, dce_conn);
2370 static void dcesrv_sock_recv(struct stream_connection *conn, uint16_t flags)
2372 struct dcesrv_connection *dce_conn = talloc_get_type(conn->private_data,
2373 struct dcesrv_connection);
2374 dcesrv_terminate_connection(dce_conn, "dcesrv_sock_recv triggered");
2377 static void dcesrv_sock_send(struct stream_connection *conn, uint16_t flags)
2379 struct dcesrv_connection *dce_conn = talloc_get_type(conn->private_data,
2380 struct dcesrv_connection);
2381 dcesrv_terminate_connection(dce_conn, "dcesrv_sock_send triggered");
2385 static const struct stream_server_ops dcesrv_stream_ops = {
2386 .name = "rpc",
2387 .accept_connection = dcesrv_sock_accept,
2388 .recv_handler = dcesrv_sock_recv,
2389 .send_handler = dcesrv_sock_send,
2392 static NTSTATUS dcesrv_add_ep_unix(struct dcesrv_context *dce_ctx,
2393 struct loadparm_context *lp_ctx,
2394 struct dcesrv_endpoint *e,
2395 struct tevent_context *event_ctx, const struct model_ops *model_ops)
2397 struct dcesrv_socket_context *dcesrv_sock;
2398 uint16_t port = 1;
2399 NTSTATUS status;
2400 const char *endpoint;
2402 dcesrv_sock = talloc_zero(event_ctx, struct dcesrv_socket_context);
2403 NT_STATUS_HAVE_NO_MEMORY(dcesrv_sock);
2405 /* remember the endpoint of this socket */
2406 dcesrv_sock->endpoint = e;
2407 dcesrv_sock->dcesrv_ctx = talloc_reference(dcesrv_sock, dce_ctx);
2409 endpoint = dcerpc_binding_get_string_option(e->ep_description, "endpoint");
2411 status = stream_setup_socket(dcesrv_sock, event_ctx, lp_ctx,
2412 model_ops, &dcesrv_stream_ops,
2413 "unix", endpoint, &port,
2414 lpcfg_socket_options(lp_ctx),
2415 dcesrv_sock);
2416 if (!NT_STATUS_IS_OK(status)) {
2417 DEBUG(0,("service_setup_stream_socket(path=%s) failed - %s\n",
2418 endpoint, nt_errstr(status)));
2421 return status;
2424 static NTSTATUS dcesrv_add_ep_ncalrpc(struct dcesrv_context *dce_ctx,
2425 struct loadparm_context *lp_ctx,
2426 struct dcesrv_endpoint *e,
2427 struct tevent_context *event_ctx, const struct model_ops *model_ops)
2429 struct dcesrv_socket_context *dcesrv_sock;
2430 uint16_t port = 1;
2431 char *full_path;
2432 NTSTATUS status;
2433 const char *endpoint;
2435 endpoint = dcerpc_binding_get_string_option(e->ep_description, "endpoint");
2437 if (endpoint == NULL) {
2439 * No identifier specified: use DEFAULT.
2441 * TODO: DO NOT hardcode this value anywhere else. Rather, specify
2442 * no endpoint and let the epmapper worry about it.
2444 endpoint = "DEFAULT";
2445 status = dcerpc_binding_set_string_option(e->ep_description,
2446 "endpoint",
2447 endpoint);
2448 if (!NT_STATUS_IS_OK(status)) {
2449 DEBUG(0,("dcerpc_binding_set_string_option() failed - %s\n",
2450 nt_errstr(status)));
2451 return status;
2455 full_path = talloc_asprintf(dce_ctx, "%s/%s", lpcfg_ncalrpc_dir(lp_ctx),
2456 endpoint);
2458 dcesrv_sock = talloc_zero(event_ctx, struct dcesrv_socket_context);
2459 NT_STATUS_HAVE_NO_MEMORY(dcesrv_sock);
2461 /* remember the endpoint of this socket */
2462 dcesrv_sock->endpoint = e;
2463 dcesrv_sock->dcesrv_ctx = talloc_reference(dcesrv_sock, dce_ctx);
2465 status = stream_setup_socket(dcesrv_sock, event_ctx, lp_ctx,
2466 model_ops, &dcesrv_stream_ops,
2467 "unix", full_path, &port,
2468 lpcfg_socket_options(lp_ctx),
2469 dcesrv_sock);
2470 if (!NT_STATUS_IS_OK(status)) {
2471 DEBUG(0,("service_setup_stream_socket(identifier=%s,path=%s) failed - %s\n",
2472 endpoint, full_path, nt_errstr(status)));
2474 return status;
2477 static NTSTATUS dcesrv_add_ep_np(struct dcesrv_context *dce_ctx,
2478 struct loadparm_context *lp_ctx,
2479 struct dcesrv_endpoint *e,
2480 struct tevent_context *event_ctx, const struct model_ops *model_ops)
2482 struct dcesrv_socket_context *dcesrv_sock;
2483 NTSTATUS status;
2484 const char *endpoint;
2486 endpoint = dcerpc_binding_get_string_option(e->ep_description, "endpoint");
2487 if (endpoint == NULL) {
2488 DEBUG(0, ("Endpoint mandatory for named pipes\n"));
2489 return NT_STATUS_INVALID_PARAMETER;
2492 dcesrv_sock = talloc_zero(event_ctx, struct dcesrv_socket_context);
2493 NT_STATUS_HAVE_NO_MEMORY(dcesrv_sock);
2495 /* remember the endpoint of this socket */
2496 dcesrv_sock->endpoint = e;
2497 dcesrv_sock->dcesrv_ctx = talloc_reference(dcesrv_sock, dce_ctx);
2499 status = tstream_setup_named_pipe(dce_ctx, event_ctx, lp_ctx,
2500 model_ops, &dcesrv_stream_ops,
2501 endpoint,
2502 dcesrv_sock);
2503 if (!NT_STATUS_IS_OK(status)) {
2504 DEBUG(0,("stream_setup_named_pipe(pipe=%s) failed - %s\n",
2505 endpoint, nt_errstr(status)));
2506 return status;
2509 return NT_STATUS_OK;
2513 add a socket address to the list of events, one event per dcerpc endpoint
2515 static NTSTATUS add_socket_rpc_tcp_iface(struct dcesrv_context *dce_ctx, struct dcesrv_endpoint *e,
2516 struct tevent_context *event_ctx, const struct model_ops *model_ops,
2517 const char *address)
2519 struct dcesrv_socket_context *dcesrv_sock;
2520 uint16_t port = 0;
2521 NTSTATUS status;
2522 const char *endpoint;
2523 char port_str[6];
2525 endpoint = dcerpc_binding_get_string_option(e->ep_description, "endpoint");
2526 if (endpoint != NULL) {
2527 port = atoi(endpoint);
2530 dcesrv_sock = talloc_zero(event_ctx, struct dcesrv_socket_context);
2531 NT_STATUS_HAVE_NO_MEMORY(dcesrv_sock);
2533 /* remember the endpoint of this socket */
2534 dcesrv_sock->endpoint = e;
2535 dcesrv_sock->dcesrv_ctx = talloc_reference(dcesrv_sock, dce_ctx);
2537 status = stream_setup_socket(dcesrv_sock, event_ctx, dce_ctx->lp_ctx,
2538 model_ops, &dcesrv_stream_ops,
2539 "ip", address, &port,
2540 lpcfg_socket_options(dce_ctx->lp_ctx),
2541 dcesrv_sock);
2542 if (!NT_STATUS_IS_OK(status)) {
2543 DEBUG(0,("service_setup_stream_socket(address=%s,port=%u) failed - %s\n",
2544 address, port, nt_errstr(status)));
2545 return status;
2548 snprintf(port_str, sizeof(port_str), "%u", port);
2550 status = dcerpc_binding_set_string_option(e->ep_description,
2551 "endpoint", port_str);
2552 if (!NT_STATUS_IS_OK(status)) {
2553 DEBUG(0,("dcerpc_binding_set_string_option(endpoint, %s) failed - %s\n",
2554 port_str, nt_errstr(status)));
2555 return status;
2558 return NT_STATUS_OK;
2561 #include "lib/socket/netif.h" /* Included here to work around the fact that socket_wrapper redefines bind() */
2563 static NTSTATUS dcesrv_add_ep_tcp(struct dcesrv_context *dce_ctx,
2564 struct loadparm_context *lp_ctx,
2565 struct dcesrv_endpoint *e,
2566 struct tevent_context *event_ctx, const struct model_ops *model_ops)
2568 NTSTATUS status;
2570 /* Add TCP/IP sockets */
2571 if (lpcfg_interfaces(lp_ctx) && lpcfg_bind_interfaces_only(lp_ctx)) {
2572 int num_interfaces;
2573 int i;
2574 struct interface *ifaces;
2576 load_interface_list(dce_ctx, lp_ctx, &ifaces);
2578 num_interfaces = iface_list_count(ifaces);
2579 for(i = 0; i < num_interfaces; i++) {
2580 const char *address = iface_list_n_ip(ifaces, i);
2581 status = add_socket_rpc_tcp_iface(dce_ctx, e, event_ctx, model_ops, address);
2582 NT_STATUS_NOT_OK_RETURN(status);
2584 } else {
2585 char **wcard;
2586 int i;
2587 int num_binds = 0;
2588 wcard = iface_list_wildcard(dce_ctx);
2589 NT_STATUS_HAVE_NO_MEMORY(wcard);
2590 for (i=0; wcard[i]; i++) {
2591 status = add_socket_rpc_tcp_iface(dce_ctx, e, event_ctx, model_ops, wcard[i]);
2592 if (NT_STATUS_IS_OK(status)) {
2593 num_binds++;
2596 talloc_free(wcard);
2597 if (num_binds == 0) {
2598 return NT_STATUS_INVALID_PARAMETER_MIX;
2602 return NT_STATUS_OK;
2605 NTSTATUS dcesrv_add_ep(struct dcesrv_context *dce_ctx,
2606 struct loadparm_context *lp_ctx,
2607 struct dcesrv_endpoint *e,
2608 struct tevent_context *event_ctx,
2609 const struct model_ops *model_ops)
2611 enum dcerpc_transport_t transport =
2612 dcerpc_binding_get_transport(e->ep_description);
2614 switch (transport) {
2615 case NCACN_UNIX_STREAM:
2616 return dcesrv_add_ep_unix(dce_ctx, lp_ctx, e, event_ctx, model_ops);
2618 case NCALRPC:
2619 return dcesrv_add_ep_ncalrpc(dce_ctx, lp_ctx, e, event_ctx, model_ops);
2621 case NCACN_IP_TCP:
2622 return dcesrv_add_ep_tcp(dce_ctx, lp_ctx, e, event_ctx, model_ops);
2624 case NCACN_NP:
2625 return dcesrv_add_ep_np(dce_ctx, lp_ctx, e, event_ctx, model_ops);
2627 default:
2628 return NT_STATUS_NOT_SUPPORTED;
2634 * retrieve credentials from a dce_call
2636 _PUBLIC_ struct cli_credentials *dcesrv_call_credentials(struct dcesrv_call_state *dce_call)
2638 return dce_call->conn->auth_state.session_info->credentials;
2642 * returns true if this is an authenticated call
2644 _PUBLIC_ bool dcesrv_call_authenticated(struct dcesrv_call_state *dce_call)
2646 enum security_user_level level;
2647 level = security_session_user_level(dce_call->conn->auth_state.session_info, NULL);
2648 return level >= SECURITY_USER;
2652 * retrieve account_name for a dce_call
2654 _PUBLIC_ const char *dcesrv_call_account_name(struct dcesrv_call_state *dce_call)
2656 return dce_call->context->conn->auth_state.session_info->info->account_name;