s4:rpc_server: make use of dcesrv_auth_prepare_alter_ack() in dcesrv_alter()
[Samba.git] / source4 / rpc_server / dcerpc_server.c
blobc650c6397b7b7570e832adbf73e08ec405928abd
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 static NTSTATUS dcesrv_negotiate_contexts(struct dcesrv_call_state *call,
46 const struct dcerpc_bind *b,
47 struct dcerpc_ack_ctx *ack_ctx_list);
50 find an association group given a assoc_group_id
52 static struct dcesrv_assoc_group *dcesrv_assoc_group_find(struct dcesrv_context *dce_ctx,
53 uint32_t id)
55 void *id_ptr;
57 id_ptr = idr_find(dce_ctx->assoc_groups_idr, id);
58 if (id_ptr == NULL) {
59 return NULL;
61 return talloc_get_type_abort(id_ptr, struct dcesrv_assoc_group);
65 take a reference to an existing association group
67 static struct dcesrv_assoc_group *dcesrv_assoc_group_reference(TALLOC_CTX *mem_ctx,
68 struct dcesrv_context *dce_ctx,
69 uint32_t id)
71 struct dcesrv_assoc_group *assoc_group;
73 assoc_group = dcesrv_assoc_group_find(dce_ctx, id);
74 if (assoc_group == NULL) {
75 DEBUG(2,(__location__ ": Failed to find assoc_group 0x%08x\n", id));
76 return NULL;
78 return talloc_reference(mem_ctx, assoc_group);
81 static int dcesrv_assoc_group_destructor(struct dcesrv_assoc_group *assoc_group)
83 int ret;
84 ret = idr_remove(assoc_group->dce_ctx->assoc_groups_idr, assoc_group->id);
85 if (ret != 0) {
86 DEBUG(0,(__location__ ": Failed to remove assoc_group 0x%08x\n",
87 assoc_group->id));
89 return 0;
93 allocate a new association group
95 static struct dcesrv_assoc_group *dcesrv_assoc_group_new(TALLOC_CTX *mem_ctx,
96 struct dcesrv_context *dce_ctx)
98 struct dcesrv_assoc_group *assoc_group;
99 int id;
101 assoc_group = talloc_zero(mem_ctx, struct dcesrv_assoc_group);
102 if (assoc_group == NULL) {
103 return NULL;
106 id = idr_get_new_random(dce_ctx->assoc_groups_idr, assoc_group, UINT16_MAX);
107 if (id == -1) {
108 talloc_free(assoc_group);
109 DEBUG(0,(__location__ ": Out of association groups!\n"));
110 return NULL;
113 assoc_group->id = id;
114 assoc_group->dce_ctx = dce_ctx;
116 talloc_set_destructor(assoc_group, dcesrv_assoc_group_destructor);
118 return assoc_group;
123 see if two endpoints match
125 static bool endpoints_match(const struct dcerpc_binding *ep1,
126 const struct dcerpc_binding *ep2)
128 enum dcerpc_transport_t t1;
129 enum dcerpc_transport_t t2;
130 const char *e1;
131 const char *e2;
133 t1 = dcerpc_binding_get_transport(ep1);
134 t2 = dcerpc_binding_get_transport(ep2);
136 e1 = dcerpc_binding_get_string_option(ep1, "endpoint");
137 e2 = dcerpc_binding_get_string_option(ep2, "endpoint");
139 if (t1 != t2) {
140 return false;
143 if (!e1 || !e2) {
144 return e1 == e2;
147 if (strcasecmp(e1, e2) != 0) {
148 return false;
151 return true;
155 find an endpoint in the dcesrv_context
157 static struct dcesrv_endpoint *find_endpoint(struct dcesrv_context *dce_ctx,
158 const struct dcerpc_binding *ep_description)
160 struct dcesrv_endpoint *ep;
161 for (ep=dce_ctx->endpoint_list; ep; ep=ep->next) {
162 if (endpoints_match(ep->ep_description, ep_description)) {
163 return ep;
166 return NULL;
170 find a registered context_id from a bind or alter_context
172 static struct dcesrv_connection_context *dcesrv_find_context(struct dcesrv_connection *conn,
173 uint16_t context_id)
175 struct dcesrv_connection_context *c;
176 for (c=conn->contexts;c;c=c->next) {
177 if (c->context_id == context_id) return c;
179 return NULL;
183 see if a uuid and if_version match to an interface
185 static bool interface_match(const struct dcesrv_interface *if1,
186 const struct dcesrv_interface *if2)
188 return (if1->syntax_id.if_version == if2->syntax_id.if_version &&
189 GUID_equal(&if1->syntax_id.uuid, &if2->syntax_id.uuid));
193 find the interface operations on any endpoint with this binding
195 static const struct dcesrv_interface *find_interface_by_binding(struct dcesrv_context *dce_ctx,
196 struct dcerpc_binding *binding,
197 const struct dcesrv_interface *iface)
199 struct dcesrv_endpoint *ep;
200 for (ep=dce_ctx->endpoint_list; ep; ep=ep->next) {
201 if (endpoints_match(ep->ep_description, binding)) {
202 struct dcesrv_if_list *ifl;
203 for (ifl=ep->interface_list; ifl; ifl=ifl->next) {
204 if (interface_match(&(ifl->iface), iface)) {
205 return &(ifl->iface);
210 return NULL;
214 see if a uuid and if_version match to an interface
216 static bool interface_match_by_uuid(const struct dcesrv_interface *iface,
217 const struct GUID *uuid, uint32_t if_version)
219 return (iface->syntax_id.if_version == if_version &&
220 GUID_equal(&iface->syntax_id.uuid, uuid));
224 find the interface operations on an endpoint by uuid
226 const struct dcesrv_interface *find_interface_by_uuid(const struct dcesrv_endpoint *endpoint,
227 const struct GUID *uuid, uint32_t if_version)
229 struct dcesrv_if_list *ifl;
230 for (ifl=endpoint->interface_list; ifl; ifl=ifl->next) {
231 if (interface_match_by_uuid(&(ifl->iface), uuid, if_version)) {
232 return &(ifl->iface);
235 return NULL;
239 find the earlier parts of a fragmented call awaiting reassembily
241 static struct dcesrv_call_state *dcesrv_find_fragmented_call(struct dcesrv_connection *dce_conn, uint16_t call_id)
243 struct dcesrv_call_state *c;
244 for (c=dce_conn->incoming_fragmented_call_list;c;c=c->next) {
245 if (c->pkt.call_id == call_id) {
246 return c;
249 return NULL;
253 register an interface on an endpoint
255 An endpoint is one unix domain socket (for ncalrpc), one TCP port
256 (for ncacn_ip_tcp) or one (forwarded) named pipe (for ncacn_np).
258 Each endpoint can have many interfaces such as netlogon, lsa or
259 samr. Some have essentially the full set.
261 This is driven from the set of interfaces listed in each IDL file
262 via the PIDL generated *__op_init_server() functions.
264 _PUBLIC_ NTSTATUS dcesrv_interface_register(struct dcesrv_context *dce_ctx,
265 const char *ep_name,
266 const struct dcesrv_interface *iface,
267 const struct security_descriptor *sd)
269 struct dcesrv_endpoint *ep;
270 struct dcesrv_if_list *ifl;
271 struct dcerpc_binding *binding;
272 bool add_ep = false;
273 NTSTATUS status;
274 enum dcerpc_transport_t transport;
275 char *ep_string = NULL;
276 bool use_single_process = true;
279 * If we are not using handles, there is no need for force
280 * this service into using a single process.
282 * However, due to the way we listen for RPC packets, we can
283 * only do this if we have a single service per pipe or TCP
284 * port, so we still force a single combined process for
285 * ncalrpc.
287 if (iface->flags & DCESRV_INTERFACE_FLAGS_HANDLES_NOT_USED) {
288 use_single_process = false;
291 status = dcerpc_parse_binding(dce_ctx, ep_name, &binding);
293 if (NT_STATUS_IS_ERR(status)) {
294 DEBUG(0, ("Trouble parsing binding string '%s'\n", ep_name));
295 return status;
298 transport = dcerpc_binding_get_transport(binding);
299 if (transport == NCACN_IP_TCP) {
300 int port;
301 char port_str[6];
304 * First check if there is already a port specified, eg
305 * for epmapper on ncacn_ip_tcp:[135]
307 const char *endpoint
308 = dcerpc_binding_get_string_option(binding,
309 "endpoint");
310 if (endpoint == NULL) {
311 port = lpcfg_parm_int(dce_ctx->lp_ctx, NULL,
312 "rpc server port", iface->name, 0);
315 * For RPC services that are not set to use a single
316 * process, we do not default to using the 'rpc server
317 * port' because that would cause a double-bind on
318 * that port.
320 if (port == 0 && !use_single_process) {
321 port = lpcfg_rpc_server_port(dce_ctx->lp_ctx);
323 if (port != 0) {
324 snprintf(port_str, sizeof(port_str), "%u", port);
325 status = dcerpc_binding_set_string_option(binding,
326 "endpoint",
327 port_str);
328 if (!NT_STATUS_IS_OK(status)) {
329 return status;
335 /* see if the interface is already registered on the endpoint */
336 if (find_interface_by_binding(dce_ctx, binding, iface)!=NULL) {
337 DEBUG(0,("dcesrv_interface_register: interface '%s' already registered on endpoint '%s'\n",
338 iface->name, ep_name));
339 return NT_STATUS_OBJECT_NAME_COLLISION;
342 /* check if this endpoint exists
344 ep = find_endpoint(dce_ctx, binding);
346 if (ep != NULL) {
348 * We want a new port on ncacn_ip_tcp for NETLOGON, so
349 * it can be multi-process. Other processes can also
350 * listen on distinct ports, if they have one forced
351 * in the code above with eg 'rpc server port:drsuapi = 1027'
353 * If we have mulitiple endpoints on port 0, they each
354 * get an epemeral port (currently by walking up from
355 * 1024).
357 if (!use_single_process && transport == NCACN_IP_TCP) {
358 add_ep = true;
362 if (ep == NULL || add_ep) {
363 ep = talloc_zero(dce_ctx, struct dcesrv_endpoint);
364 if (!ep) {
365 return NT_STATUS_NO_MEMORY;
367 ZERO_STRUCTP(ep);
368 ep->ep_description = talloc_move(ep, &binding);
369 add_ep = true;
371 /* add mgmt interface */
372 ifl = talloc_zero(ep, struct dcesrv_if_list);
373 if (!ifl) {
374 return NT_STATUS_NO_MEMORY;
377 ifl->iface = dcesrv_get_mgmt_interface();
379 DLIST_ADD(ep->interface_list, ifl);
383 * By default don't force into a single process, but if any
384 * interface on this endpoint on this service uses handles
385 * (most do), then we must force into single process mode
387 * By overwriting this each time a new interface is added to
388 * this endpoint, we end up with the most restrictive setting.
390 if (use_single_process) {
391 ep->use_single_process = true;
394 /* talloc a new interface list element */
395 ifl = talloc_zero(ep, struct dcesrv_if_list);
396 if (!ifl) {
397 return NT_STATUS_NO_MEMORY;
400 /* copy the given interface struct to the one on the endpoints interface list */
401 memcpy(&(ifl->iface),iface, sizeof(struct dcesrv_interface));
403 /* if we have a security descriptor given,
404 * we should see if we can set it up on the endpoint
406 if (sd != NULL) {
407 /* if there's currently no security descriptor given on the endpoint
408 * we try to set it
410 if (ep->sd == NULL) {
411 ep->sd = security_descriptor_copy(ep, sd);
414 /* if now there's no security descriptor given on the endpoint
415 * something goes wrong, either we failed to copy the security descriptor
416 * or there was already one on the endpoint
418 if (ep->sd != NULL) {
419 DEBUG(0,("dcesrv_interface_register: interface '%s' failed to setup a security descriptor\n"
420 " on endpoint '%s'\n",
421 iface->name, ep_name));
422 if (add_ep) free(ep);
423 free(ifl);
424 return NT_STATUS_OBJECT_NAME_COLLISION;
428 /* finally add the interface on the endpoint */
429 DLIST_ADD(ep->interface_list, ifl);
431 /* if it's a new endpoint add it to the dcesrv_context */
432 if (add_ep) {
433 DLIST_ADD(dce_ctx->endpoint_list, ep);
436 /* Re-get the string as we may have set a port */
437 ep_string = dcerpc_binding_string(dce_ctx, ep->ep_description);
439 DEBUG(4,("dcesrv_interface_register: interface '%s' registered on endpoint '%s'\n",
440 iface->name, ep_string));
441 TALLOC_FREE(ep_string);
443 return NT_STATUS_OK;
446 NTSTATUS dcesrv_inherited_session_key(struct dcesrv_connection *p,
447 DATA_BLOB *session_key)
449 if (p->auth_state.session_info->session_key.length) {
450 *session_key = p->auth_state.session_info->session_key;
451 return NT_STATUS_OK;
453 return NT_STATUS_NO_USER_SESSION_KEY;
457 fetch the user session key - may be default (above) or the SMB session key
459 The key is always truncated to 16 bytes
461 _PUBLIC_ NTSTATUS dcesrv_fetch_session_key(struct dcesrv_connection *p,
462 DATA_BLOB *session_key)
464 NTSTATUS status = p->auth_state.session_key(p, session_key);
465 if (!NT_STATUS_IS_OK(status)) {
466 return status;
469 session_key->length = MIN(session_key->length, 16);
471 return NT_STATUS_OK;
475 connect to a dcerpc endpoint
477 _PUBLIC_ NTSTATUS dcesrv_endpoint_connect(struct dcesrv_context *dce_ctx,
478 TALLOC_CTX *mem_ctx,
479 const struct dcesrv_endpoint *ep,
480 struct auth_session_info *session_info,
481 struct tevent_context *event_ctx,
482 struct imessaging_context *msg_ctx,
483 struct server_id server_id,
484 uint32_t state_flags,
485 struct dcesrv_connection **_p)
487 struct dcesrv_connection *p;
489 if (!session_info) {
490 return NT_STATUS_ACCESS_DENIED;
493 p = talloc_zero(mem_ctx, struct dcesrv_connection);
494 NT_STATUS_HAVE_NO_MEMORY(p);
496 if (!talloc_reference(p, session_info)) {
497 talloc_free(p);
498 return NT_STATUS_NO_MEMORY;
501 p->dce_ctx = dce_ctx;
502 p->endpoint = ep;
503 p->packet_log_dir = lpcfg_lock_directory(dce_ctx->lp_ctx);
504 p->auth_state.session_info = session_info;
505 p->auth_state.session_key = dcesrv_generic_session_key;
506 p->event_ctx = event_ctx;
507 p->msg_ctx = msg_ctx;
508 p->server_id = server_id;
509 p->state_flags = state_flags;
510 p->allow_bind = true;
511 p->max_recv_frag = 5840;
512 p->max_xmit_frag = 5840;
513 p->max_total_request_size = DCERPC_NCACN_REQUEST_DEFAULT_MAX_SIZE;
516 * For now we only support NDR32.
518 p->preferred_transfer = &ndr_transfer_syntax_ndr;
520 *_p = p;
521 return NT_STATUS_OK;
525 move a call from an existing linked list to the specified list. This
526 prevents bugs where we forget to remove the call from a previous
527 list when moving it.
529 static void dcesrv_call_set_list(struct dcesrv_call_state *call,
530 enum dcesrv_call_list list)
532 switch (call->list) {
533 case DCESRV_LIST_NONE:
534 break;
535 case DCESRV_LIST_CALL_LIST:
536 DLIST_REMOVE(call->conn->call_list, call);
537 break;
538 case DCESRV_LIST_FRAGMENTED_CALL_LIST:
539 DLIST_REMOVE(call->conn->incoming_fragmented_call_list, call);
540 break;
541 case DCESRV_LIST_PENDING_CALL_LIST:
542 DLIST_REMOVE(call->conn->pending_call_list, call);
543 break;
545 call->list = list;
546 switch (list) {
547 case DCESRV_LIST_NONE:
548 break;
549 case DCESRV_LIST_CALL_LIST:
550 DLIST_ADD_END(call->conn->call_list, call);
551 break;
552 case DCESRV_LIST_FRAGMENTED_CALL_LIST:
553 DLIST_ADD_END(call->conn->incoming_fragmented_call_list, call);
554 break;
555 case DCESRV_LIST_PENDING_CALL_LIST:
556 DLIST_ADD_END(call->conn->pending_call_list, call);
557 break;
561 static void dcesrv_call_disconnect_after(struct dcesrv_call_state *call,
562 const char *reason)
564 if (call->conn->terminate != NULL) {
565 return;
568 call->conn->allow_bind = false;
569 call->conn->allow_alter = false;
570 call->conn->allow_auth3 = false;
571 call->conn->allow_request = false;
573 call->terminate_reason = talloc_strdup(call, reason);
574 if (call->terminate_reason == NULL) {
575 call->terminate_reason = __location__;
580 return a dcerpc bind_nak
582 static NTSTATUS dcesrv_bind_nak(struct dcesrv_call_state *call, uint32_t reason)
584 struct ncacn_packet pkt;
585 struct dcerpc_bind_nak_version version;
586 struct data_blob_list_item *rep;
587 NTSTATUS status;
588 static const uint8_t _pad[3] = { 0, };
591 * We add the call to the pending_call_list
592 * in order to defer the termination.
594 dcesrv_call_disconnect_after(call, "dcesrv_bind_nak");
596 /* setup a bind_nak */
597 dcesrv_init_hdr(&pkt, lpcfg_rpc_big_endian(call->conn->dce_ctx->lp_ctx));
598 pkt.auth_length = 0;
599 pkt.call_id = call->pkt.call_id;
600 pkt.ptype = DCERPC_PKT_BIND_NAK;
601 pkt.pfc_flags = DCERPC_PFC_FLAG_FIRST | DCERPC_PFC_FLAG_LAST;
602 pkt.u.bind_nak.reject_reason = reason;
603 version.rpc_vers = 5;
604 version.rpc_vers_minor = 0;
605 pkt.u.bind_nak.num_versions = 1;
606 pkt.u.bind_nak.versions = &version;
607 pkt.u.bind_nak._pad = data_blob_const(_pad, sizeof(_pad));
609 rep = talloc_zero(call, struct data_blob_list_item);
610 if (!rep) {
611 return NT_STATUS_NO_MEMORY;
614 status = ncacn_push_auth(&rep->blob, call, &pkt, NULL);
615 if (!NT_STATUS_IS_OK(status)) {
616 return status;
619 dcerpc_set_frag_length(&rep->blob, rep->blob.length);
621 DLIST_ADD_END(call->replies, rep);
622 dcesrv_call_set_list(call, DCESRV_LIST_CALL_LIST);
624 if (call->conn->call_list && call->conn->call_list->replies) {
625 if (call->conn->transport.report_output_data) {
626 call->conn->transport.report_output_data(call->conn);
630 return NT_STATUS_OK;
633 static NTSTATUS dcesrv_fault_disconnect(struct dcesrv_call_state *call,
634 uint32_t fault_code)
637 * We add the call to the pending_call_list
638 * in order to defer the termination.
640 dcesrv_call_disconnect_after(call, "dcesrv_fault_disconnect");
642 return dcesrv_fault_with_flags(call, fault_code,
643 DCERPC_PFC_FLAG_DID_NOT_EXECUTE);
646 static int dcesrv_connection_context_destructor(struct dcesrv_connection_context *c)
648 DLIST_REMOVE(c->conn->contexts, c);
650 if (c->iface && c->iface->unbind) {
651 c->iface->unbind(c, c->iface);
652 c->iface = NULL;
655 return 0;
658 static void dcesrv_prepare_context_auth(struct dcesrv_call_state *dce_call)
660 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
661 const struct dcesrv_endpoint *endpoint = dce_call->conn->endpoint;
662 enum dcerpc_transport_t transport =
663 dcerpc_binding_get_transport(endpoint->ep_description);
664 struct dcesrv_connection_context *context = dce_call->context;
665 const struct dcesrv_interface *iface = context->iface;
667 context->min_auth_level = DCERPC_AUTH_LEVEL_NONE;
669 if (transport == NCALRPC) {
670 context->allow_connect = true;
671 return;
675 * allow overwrite per interface
676 * allow dcerpc auth level connect:<interface>
678 context->allow_connect = lpcfg_allow_dcerpc_auth_level_connect(lp_ctx);
679 context->allow_connect = lpcfg_parm_bool(lp_ctx, NULL,
680 "allow dcerpc auth level connect",
681 iface->name,
682 context->allow_connect);
685 NTSTATUS dcesrv_interface_bind_require_integrity(struct dcesrv_call_state *dce_call,
686 const struct dcesrv_interface *iface)
688 if (dce_call->context == NULL) {
689 return NT_STATUS_INTERNAL_ERROR;
693 * For connection oriented DCERPC DCERPC_AUTH_LEVEL_PACKET (4)
694 * has the same behavior as DCERPC_AUTH_LEVEL_INTEGRITY (5).
696 dce_call->context->min_auth_level = DCERPC_AUTH_LEVEL_PACKET;
697 return NT_STATUS_OK;
700 NTSTATUS dcesrv_interface_bind_require_privacy(struct dcesrv_call_state *dce_call,
701 const struct dcesrv_interface *iface)
703 if (dce_call->context == NULL) {
704 return NT_STATUS_INTERNAL_ERROR;
707 dce_call->context->min_auth_level = DCERPC_AUTH_LEVEL_PRIVACY;
708 return NT_STATUS_OK;
711 _PUBLIC_ NTSTATUS dcesrv_interface_bind_reject_connect(struct dcesrv_call_state *dce_call,
712 const struct dcesrv_interface *iface)
714 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
715 const struct dcesrv_endpoint *endpoint = dce_call->conn->endpoint;
716 enum dcerpc_transport_t transport =
717 dcerpc_binding_get_transport(endpoint->ep_description);
718 struct dcesrv_connection_context *context = dce_call->context;
720 if (context == NULL) {
721 return NT_STATUS_INTERNAL_ERROR;
724 if (transport == NCALRPC) {
725 context->allow_connect = true;
726 return NT_STATUS_OK;
730 * allow overwrite per interface
731 * allow dcerpc auth level connect:<interface>
733 context->allow_connect = false;
734 context->allow_connect = lpcfg_parm_bool(lp_ctx, NULL,
735 "allow dcerpc auth level connect",
736 iface->name,
737 context->allow_connect);
738 return NT_STATUS_OK;
741 _PUBLIC_ NTSTATUS dcesrv_interface_bind_allow_connect(struct dcesrv_call_state *dce_call,
742 const struct dcesrv_interface *iface)
744 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
745 const struct dcesrv_endpoint *endpoint = dce_call->conn->endpoint;
746 enum dcerpc_transport_t transport =
747 dcerpc_binding_get_transport(endpoint->ep_description);
748 struct dcesrv_connection_context *context = dce_call->context;
750 if (context == NULL) {
751 return NT_STATUS_INTERNAL_ERROR;
754 if (transport == NCALRPC) {
755 context->allow_connect = true;
756 return NT_STATUS_OK;
760 * allow overwrite per interface
761 * allow dcerpc auth level connect:<interface>
763 context->allow_connect = true;
764 context->allow_connect = lpcfg_parm_bool(lp_ctx, NULL,
765 "allow dcerpc auth level connect",
766 iface->name,
767 context->allow_connect);
768 return NT_STATUS_OK;
771 static NTSTATUS dcesrv_auth_reply(struct dcesrv_call_state *call);
774 handle a bind request
776 static NTSTATUS dcesrv_bind(struct dcesrv_call_state *call)
778 struct ncacn_packet *pkt = &call->ack_pkt;
779 NTSTATUS status;
780 uint32_t extra_flags = 0;
781 uint16_t max_req = 0;
782 uint16_t max_rep = 0;
783 const char *ep_prefix = "";
784 const char *endpoint = NULL;
785 struct dcesrv_auth *auth = &call->conn->auth_state;
786 struct dcerpc_ack_ctx *ack_ctx_list = NULL;
787 struct dcerpc_ack_ctx *ack_features = NULL;
788 size_t i;
790 status = dcerpc_verify_ncacn_packet_header(&call->pkt,
791 DCERPC_PKT_BIND,
792 call->pkt.u.bind.auth_info.length,
793 0, /* required flags */
794 DCERPC_PFC_FLAG_FIRST |
795 DCERPC_PFC_FLAG_LAST |
796 DCERPC_PFC_FLAG_SUPPORT_HEADER_SIGN |
797 0x08 | /* this is not defined, but should be ignored */
798 DCERPC_PFC_FLAG_CONC_MPX |
799 DCERPC_PFC_FLAG_DID_NOT_EXECUTE |
800 DCERPC_PFC_FLAG_MAYBE |
801 DCERPC_PFC_FLAG_OBJECT_UUID);
802 if (!NT_STATUS_IS_OK(status)) {
803 return dcesrv_bind_nak(call,
804 DCERPC_BIND_NAK_REASON_PROTOCOL_VERSION_NOT_SUPPORTED);
807 /* max_recv_frag and max_xmit_frag result always in the same value! */
808 max_req = MIN(call->pkt.u.bind.max_xmit_frag,
809 call->pkt.u.bind.max_recv_frag);
811 * The values are between 2048 and 5840 tested against Windows 2012R2
812 * via ncacn_ip_tcp on port 135.
814 max_req = MAX(2048, max_req);
815 max_rep = MIN(max_req, call->conn->max_recv_frag);
816 /* They are truncated to an 8 byte boundary. */
817 max_rep &= 0xFFF8;
819 /* max_recv_frag and max_xmit_frag result always in the same value! */
820 call->conn->max_recv_frag = max_rep;
821 call->conn->max_xmit_frag = max_rep;
824 if provided, check the assoc_group is valid
826 if (call->pkt.u.bind.assoc_group_id != 0) {
827 call->conn->assoc_group = dcesrv_assoc_group_reference(call->conn,
828 call->conn->dce_ctx,
829 call->pkt.u.bind.assoc_group_id);
830 } else {
831 call->conn->assoc_group = dcesrv_assoc_group_new(call->conn,
832 call->conn->dce_ctx);
836 * The NETLOGON server does not use handles and so
837 * there is no need to support association groups, but
838 * we need to give back a number regardless.
840 * We have to do this when it is not run as a single process,
841 * because then it can't see the other valid association
842 * groups. We handle this genericly for all endpoints not
843 * running in single process mode.
845 * We know which endpoint we are on even before checking the
846 * iface UUID, so for simplicity we enforce the same policy
847 * for all interfaces on the endpoint.
849 * This means that where NETLOGON
850 * shares an endpoint (such as ncalrpc or of 'lsa over
851 * netlogon' is set) we will still check association groups.
855 if (call->conn->assoc_group == NULL &&
856 !call->conn->endpoint->use_single_process) {
857 call->conn->assoc_group
858 = dcesrv_assoc_group_new(call->conn,
859 call->conn->dce_ctx);
861 if (call->conn->assoc_group == NULL) {
862 return dcesrv_bind_nak(call, 0);
865 if (call->pkt.u.bind.num_contexts < 1) {
866 return dcesrv_bind_nak(call, 0);
869 ack_ctx_list = talloc_zero_array(call, struct dcerpc_ack_ctx,
870 call->pkt.u.bind.num_contexts);
871 if (ack_ctx_list == NULL) {
872 return dcesrv_bind_nak(call, 0);
876 * Set some sane defaults (required by dcesrv_negotiate_contexts()/
877 * dcesrv_check_or_create_context()) and do some protocol validation
878 * and set sane defaults.
880 for (i = 0; i < call->pkt.u.bind.num_contexts; i++) {
881 const struct dcerpc_ctx_list *c = &call->pkt.u.bind.ctx_list[i];
882 struct dcerpc_ack_ctx *a = &ack_ctx_list[i];
883 bool is_feature = false;
884 uint64_t features = 0;
886 if (c->num_transfer_syntaxes == 0) {
887 return dcesrv_bind_nak(call, 0);
890 a->result = DCERPC_BIND_ACK_RESULT_PROVIDER_REJECTION;
891 a->reason.value = DCERPC_BIND_ACK_REASON_ABSTRACT_SYNTAX_NOT_SUPPORTED;
894 * It's only treated as bind time feature request, if the first
895 * transfer_syntax matches, all others are ignored.
897 is_feature = dcerpc_extract_bind_time_features(c->transfer_syntaxes[0],
898 &features);
899 if (!is_feature) {
900 continue;
903 if (ack_features != NULL) {
905 * Only one bind time feature context is allowed.
907 return dcesrv_bind_nak(call, 0);
909 ack_features = a;
911 a->result = DCERPC_BIND_ACK_RESULT_NEGOTIATE_ACK;
912 a->reason.negotiate = 0;
913 if (features & DCERPC_BIND_TIME_SECURITY_CONTEXT_MULTIPLEXING) {
914 /* not supported yet */
916 if (features & DCERPC_BIND_TIME_KEEP_CONNECTION_ON_ORPHAN) {
917 a->reason.negotiate |=
918 DCERPC_BIND_TIME_KEEP_CONNECTION_ON_ORPHAN;
921 call->conn->bind_time_features = a->reason.negotiate;
925 * Try to negotiate one new presentation context.
927 * Deep in here we locate the iface (by uuid) that the client
928 * requested, from the list of interfaces on the
929 * call->conn->endpoint, and call iface->bind() on that iface.
931 * call->conn was set up at the accept() of the socket, and
932 * call->conn->endpoint has a list of interfaces restricted to
933 * this port or pipe.
935 status = dcesrv_negotiate_contexts(call, &call->pkt.u.bind, ack_ctx_list);
936 if (NT_STATUS_EQUAL(status, NT_STATUS_RPC_PROTOCOL_ERROR)) {
937 return dcesrv_bind_nak(call, 0);
939 if (!NT_STATUS_IS_OK(status)) {
940 return status;
944 * At this point we still don't know which interface (eg
945 * netlogon, lsa, drsuapi) the caller requested in this bind!
946 * The most recently added context is available as the first
947 * element in the linked list at call->conn->contexts, that is
948 * call->conn->contexts->iface, but they may not have
949 * requested one at all!
952 if ((call->pkt.pfc_flags & DCERPC_PFC_FLAG_CONC_MPX) &&
953 (call->state_flags & DCESRV_CALL_STATE_FLAG_MULTIPLEXED)) {
954 call->conn->state_flags |= DCESRV_CALL_STATE_FLAG_MULTIPLEXED;
955 extra_flags |= DCERPC_PFC_FLAG_CONC_MPX;
958 if (call->state_flags & DCESRV_CALL_STATE_FLAG_PROCESS_PENDING_CALL) {
959 call->conn->state_flags |= DCESRV_CALL_STATE_FLAG_PROCESS_PENDING_CALL;
963 * After finding the interface and setting up the NDR
964 * transport negotiation etc, handle any authentication that
965 * is being requested.
967 if (!dcesrv_auth_bind(call)) {
969 if (auth->auth_level == DCERPC_AUTH_LEVEL_NONE) {
971 * With DCERPC_AUTH_LEVEL_NONE, we get the
972 * reject_reason in auth->auth_context_id.
974 return dcesrv_bind_nak(call, auth->auth_context_id);
978 * This must a be a temporary failure e.g. talloc or invalid
979 * configuration, e.g. no machine account.
981 return dcesrv_bind_nak(call,
982 DCERPC_BIND_NAK_REASON_TEMPORARY_CONGESTION);
985 /* setup a bind_ack */
986 dcesrv_init_hdr(pkt, lpcfg_rpc_big_endian(call->conn->dce_ctx->lp_ctx));
987 pkt->auth_length = 0;
988 pkt->call_id = call->pkt.call_id;
989 pkt->ptype = DCERPC_PKT_BIND_ACK;
990 pkt->pfc_flags = DCERPC_PFC_FLAG_FIRST | DCERPC_PFC_FLAG_LAST | extra_flags;
991 pkt->u.bind_ack.max_xmit_frag = call->conn->max_xmit_frag;
992 pkt->u.bind_ack.max_recv_frag = call->conn->max_recv_frag;
993 pkt->u.bind_ack.assoc_group_id = call->conn->assoc_group->id;
995 endpoint = dcerpc_binding_get_string_option(
996 call->conn->endpoint->ep_description,
997 "endpoint");
998 if (endpoint == NULL) {
999 endpoint = "";
1002 if (strncasecmp(endpoint, "\\pipe\\", 6) == 0) {
1004 * TODO: check if this is really needed
1006 * Or if we should fix this in our idl files.
1008 ep_prefix = "\\PIPE\\";
1009 endpoint += 6;
1012 pkt->u.bind_ack.secondary_address = talloc_asprintf(call, "%s%s",
1013 ep_prefix,
1014 endpoint);
1015 if (pkt->u.bind_ack.secondary_address == NULL) {
1016 return NT_STATUS_NO_MEMORY;
1018 pkt->u.bind_ack.num_results = call->pkt.u.bind.num_contexts;
1019 pkt->u.bind_ack.ctx_list = ack_ctx_list;
1020 pkt->u.bind_ack.auth_info = data_blob_null;
1022 status = dcesrv_auth_prepare_bind_ack(call, pkt);
1023 if (!NT_STATUS_IS_OK(status)) {
1024 return dcesrv_bind_nak(call, 0);
1027 if (auth->auth_finished) {
1028 return dcesrv_auth_reply(call);
1031 status = gensec_update_ev(auth->gensec_security,
1032 call, call->event_ctx,
1033 call->in_auth_info.credentials,
1034 &call->out_auth_info->credentials);
1036 status = dcesrv_auth_complete(call, status);
1037 if (!NT_STATUS_IS_OK(status)) {
1038 return dcesrv_bind_nak(call, 0);
1041 return dcesrv_auth_reply(call);
1044 static NTSTATUS dcesrv_auth_reply(struct dcesrv_call_state *call)
1046 struct ncacn_packet *pkt = &call->ack_pkt;
1047 struct data_blob_list_item *rep = NULL;
1048 NTSTATUS status;
1050 rep = talloc_zero(call, struct data_blob_list_item);
1051 if (!rep) {
1052 return NT_STATUS_NO_MEMORY;
1055 status = ncacn_push_auth(&rep->blob, call, pkt,
1056 call->out_auth_info);
1057 if (!NT_STATUS_IS_OK(status)) {
1058 return status;
1061 dcerpc_set_frag_length(&rep->blob, rep->blob.length);
1063 DLIST_ADD_END(call->replies, rep);
1064 dcesrv_call_set_list(call, DCESRV_LIST_CALL_LIST);
1066 if (call->conn->call_list && call->conn->call_list->replies) {
1067 if (call->conn->transport.report_output_data) {
1068 call->conn->transport.report_output_data(call->conn);
1072 return NT_STATUS_OK;
1077 handle a auth3 request
1079 static NTSTATUS dcesrv_auth3(struct dcesrv_call_state *call)
1081 NTSTATUS status;
1083 if (!call->conn->allow_auth3) {
1084 return dcesrv_fault_disconnect(call, DCERPC_NCA_S_PROTO_ERROR);
1087 if (call->conn->auth_state.auth_finished) {
1088 return dcesrv_fault_disconnect(call, DCERPC_NCA_S_PROTO_ERROR);
1091 status = dcerpc_verify_ncacn_packet_header(&call->pkt,
1092 DCERPC_PKT_AUTH3,
1093 call->pkt.u.auth3.auth_info.length,
1094 0, /* required flags */
1095 DCERPC_PFC_FLAG_FIRST |
1096 DCERPC_PFC_FLAG_LAST |
1097 DCERPC_PFC_FLAG_SUPPORT_HEADER_SIGN |
1098 0x08 | /* this is not defined, but should be ignored */
1099 DCERPC_PFC_FLAG_CONC_MPX |
1100 DCERPC_PFC_FLAG_DID_NOT_EXECUTE |
1101 DCERPC_PFC_FLAG_MAYBE |
1102 DCERPC_PFC_FLAG_OBJECT_UUID);
1103 if (!NT_STATUS_IS_OK(status)) {
1104 return dcesrv_fault_disconnect(call, DCERPC_NCA_S_PROTO_ERROR);
1107 /* handle the auth3 in the auth code */
1108 if (!dcesrv_auth_auth3(call)) {
1109 call->conn->auth_state.auth_invalid = true;
1110 if (call->fault_code != 0) {
1111 return dcesrv_fault_disconnect(call, call->fault_code);
1115 talloc_free(call);
1117 /* we don't send a reply to a auth3 request, except by a
1118 fault */
1119 return NT_STATUS_OK;
1123 static NTSTATUS dcesrv_check_or_create_context(struct dcesrv_call_state *call,
1124 const struct dcerpc_bind *b,
1125 const struct dcerpc_ctx_list *ctx,
1126 struct dcerpc_ack_ctx *ack,
1127 bool validate_only,
1128 const struct ndr_syntax_id *supported_transfer)
1130 uint32_t if_version;
1131 struct dcesrv_connection_context *context;
1132 const struct dcesrv_interface *iface;
1133 struct GUID uuid;
1134 NTSTATUS status;
1135 const struct ndr_syntax_id *selected_transfer = NULL;
1136 size_t i;
1137 bool ok;
1139 if (b == NULL) {
1140 return NT_STATUS_INTERNAL_ERROR;
1142 if (ctx == NULL) {
1143 return NT_STATUS_INTERNAL_ERROR;
1145 if (ctx->num_transfer_syntaxes < 1) {
1146 return NT_STATUS_INTERNAL_ERROR;
1148 if (ack == NULL) {
1149 return NT_STATUS_INTERNAL_ERROR;
1151 if (supported_transfer == NULL) {
1152 return NT_STATUS_INTERNAL_ERROR;
1155 switch (ack->result) {
1156 case DCERPC_BIND_ACK_RESULT_ACCEPTANCE:
1157 case DCERPC_BIND_ACK_RESULT_NEGOTIATE_ACK:
1159 * We is already completed.
1161 return NT_STATUS_OK;
1162 default:
1163 break;
1166 ack->result = DCERPC_BIND_ACK_RESULT_PROVIDER_REJECTION;
1167 ack->reason.value = DCERPC_BIND_ACK_REASON_ABSTRACT_SYNTAX_NOT_SUPPORTED;
1169 if_version = ctx->abstract_syntax.if_version;
1170 uuid = ctx->abstract_syntax.uuid;
1172 iface = find_interface_by_uuid(call->conn->endpoint, &uuid, if_version);
1173 if (iface == NULL) {
1174 char *uuid_str = GUID_string(call, &uuid);
1175 DEBUG(2,("Request for unknown dcerpc interface %s/%d\n", uuid_str, if_version));
1176 talloc_free(uuid_str);
1178 * We report this only via ack->result
1180 return NT_STATUS_OK;
1183 ack->result = DCERPC_BIND_ACK_RESULT_PROVIDER_REJECTION;
1184 ack->reason.value = DCERPC_BIND_ACK_REASON_TRANSFER_SYNTAXES_NOT_SUPPORTED;
1186 if (validate_only) {
1188 * We report this only via ack->result
1190 return NT_STATUS_OK;
1193 for (i = 0; i < ctx->num_transfer_syntaxes; i++) {
1195 * we only do NDR encoded dcerpc for now.
1197 ok = ndr_syntax_id_equal(&ctx->transfer_syntaxes[i],
1198 supported_transfer);
1199 if (ok) {
1200 selected_transfer = supported_transfer;
1201 break;
1205 context = dcesrv_find_context(call->conn, ctx->context_id);
1206 if (context != NULL) {
1207 ok = ndr_syntax_id_equal(&context->iface->syntax_id,
1208 &ctx->abstract_syntax);
1209 if (!ok) {
1210 return NT_STATUS_RPC_PROTOCOL_ERROR;
1213 if (selected_transfer != NULL) {
1214 ok = ndr_syntax_id_equal(&context->transfer_syntax,
1215 selected_transfer);
1216 if (!ok) {
1217 return NT_STATUS_RPC_PROTOCOL_ERROR;
1220 ack->result = DCERPC_BIND_ACK_RESULT_ACCEPTANCE;
1221 ack->reason.value = DCERPC_BIND_ACK_REASON_NOT_SPECIFIED;
1222 ack->syntax = context->transfer_syntax;
1226 * We report this only via ack->result
1228 return NT_STATUS_OK;
1231 if (selected_transfer == NULL) {
1233 * We report this only via ack->result
1235 return NT_STATUS_OK;
1238 ack->result = DCERPC_BIND_ACK_RESULT_USER_REJECTION;
1239 ack->reason.value = DCERPC_BIND_ACK_REASON_LOCAL_LIMIT_EXCEEDED;
1241 /* add this context to the list of available context_ids */
1242 context = talloc_zero(call->conn, struct dcesrv_connection_context);
1243 if (context == NULL) {
1244 return NT_STATUS_NO_MEMORY;
1246 context->conn = call->conn;
1247 context->context_id = ctx->context_id;
1248 context->iface = iface;
1249 context->transfer_syntax = *selected_transfer;
1250 context->private_data = NULL;
1251 DLIST_ADD(call->conn->contexts, context);
1252 call->context = context;
1253 talloc_set_destructor(context, dcesrv_connection_context_destructor);
1255 dcesrv_prepare_context_auth(call);
1258 * Multiplex is supported by default
1260 call->state_flags |= DCESRV_CALL_STATE_FLAG_MULTIPLEXED;
1262 status = iface->bind(call, iface, if_version);
1263 call->context = NULL;
1264 if (!NT_STATUS_IS_OK(status)) {
1265 /* we don't want to trigger the iface->unbind() hook */
1266 context->iface = NULL;
1267 talloc_free(context);
1269 * We report this only via ack->result
1271 return NT_STATUS_OK;
1274 ack->result = DCERPC_BIND_ACK_RESULT_ACCEPTANCE;
1275 ack->reason.value = DCERPC_BIND_ACK_REASON_NOT_SPECIFIED;
1276 ack->syntax = context->transfer_syntax;
1277 return NT_STATUS_OK;
1280 static NTSTATUS dcesrv_negotiate_contexts(struct dcesrv_call_state *call,
1281 const struct dcerpc_bind *b,
1282 struct dcerpc_ack_ctx *ack_ctx_list)
1284 NTSTATUS status;
1285 size_t i;
1286 bool validate_only = false;
1287 bool preferred_ndr32;
1290 * Try to negotiate one new presentation context,
1291 * using our preferred transfer syntax.
1293 for (i = 0; i < b->num_contexts; i++) {
1294 const struct dcerpc_ctx_list *c = &b->ctx_list[i];
1295 struct dcerpc_ack_ctx *a = &ack_ctx_list[i];
1297 status = dcesrv_check_or_create_context(call, b, c, a,
1298 validate_only,
1299 call->conn->preferred_transfer);
1300 if (!NT_STATUS_IS_OK(status)) {
1301 return status;
1304 if (a->result == DCERPC_BIND_ACK_RESULT_ACCEPTANCE) {
1306 * We managed to negotiate one context.
1308 * => we're done.
1310 validate_only = true;
1314 preferred_ndr32 = ndr_syntax_id_equal(&ndr_transfer_syntax_ndr,
1315 call->conn->preferred_transfer);
1316 if (preferred_ndr32) {
1318 * We're done.
1320 return NT_STATUS_OK;
1324 * Try to negotiate one new presentation context,
1325 * using NDR 32 as fallback.
1327 for (i = 0; i < b->num_contexts; i++) {
1328 const struct dcerpc_ctx_list *c = &b->ctx_list[i];
1329 struct dcerpc_ack_ctx *a = &ack_ctx_list[i];
1331 status = dcesrv_check_or_create_context(call, b, c, a,
1332 validate_only,
1333 &ndr_transfer_syntax_ndr);
1334 if (!NT_STATUS_IS_OK(status)) {
1335 return status;
1338 if (a->result == DCERPC_BIND_ACK_RESULT_ACCEPTANCE) {
1340 * We managed to negotiate one context.
1342 * => we're done.
1344 validate_only = true;
1348 return NT_STATUS_OK;
1352 handle a alter context request
1354 static NTSTATUS dcesrv_alter(struct dcesrv_call_state *call)
1356 NTSTATUS status;
1357 bool auth_ok = false;
1358 struct ncacn_packet *pkt = &call->ack_pkt;
1359 uint32_t extra_flags = 0;
1360 struct dcesrv_auth *auth = &call->conn->auth_state;
1361 struct dcerpc_ack_ctx *ack_ctx_list = NULL;
1362 size_t i;
1364 if (!call->conn->allow_alter) {
1365 return dcesrv_fault_disconnect(call, DCERPC_NCA_S_PROTO_ERROR);
1368 status = dcerpc_verify_ncacn_packet_header(&call->pkt,
1369 DCERPC_PKT_ALTER,
1370 call->pkt.u.alter.auth_info.length,
1371 0, /* required flags */
1372 DCERPC_PFC_FLAG_FIRST |
1373 DCERPC_PFC_FLAG_LAST |
1374 DCERPC_PFC_FLAG_SUPPORT_HEADER_SIGN |
1375 0x08 | /* this is not defined, but should be ignored */
1376 DCERPC_PFC_FLAG_CONC_MPX |
1377 DCERPC_PFC_FLAG_DID_NOT_EXECUTE |
1378 DCERPC_PFC_FLAG_MAYBE |
1379 DCERPC_PFC_FLAG_OBJECT_UUID);
1380 if (!NT_STATUS_IS_OK(status)) {
1381 return dcesrv_fault_disconnect(call, DCERPC_NCA_S_PROTO_ERROR);
1384 auth_ok = dcesrv_auth_alter(call);
1385 if (!auth_ok) {
1386 if (call->fault_code != 0) {
1387 return dcesrv_fault_disconnect(call, call->fault_code);
1391 if (call->pkt.u.alter.num_contexts < 1) {
1392 return dcesrv_fault_disconnect(call, DCERPC_NCA_S_PROTO_ERROR);
1395 ack_ctx_list = talloc_zero_array(call, struct dcerpc_ack_ctx,
1396 call->pkt.u.alter.num_contexts);
1397 if (ack_ctx_list == NULL) {
1398 return NT_STATUS_NO_MEMORY;
1402 * Set some sane defaults (required by dcesrv_negotiate_contexts()/
1403 * dcesrv_check_or_create_context()) and do some protocol validation
1404 * and set sane defaults.
1406 for (i = 0; i < call->pkt.u.alter.num_contexts; i++) {
1407 const struct dcerpc_ctx_list *c = &call->pkt.u.alter.ctx_list[i];
1408 struct dcerpc_ack_ctx *a = &ack_ctx_list[i];
1410 if (c->num_transfer_syntaxes == 0) {
1411 return dcesrv_fault_disconnect(call,
1412 DCERPC_NCA_S_PROTO_ERROR);
1415 a->result = DCERPC_BIND_ACK_RESULT_PROVIDER_REJECTION;
1416 a->reason.value = DCERPC_BIND_ACK_REASON_ABSTRACT_SYNTAX_NOT_SUPPORTED;
1420 * Try to negotiate one new presentation context.
1422 status = dcesrv_negotiate_contexts(call, &call->pkt.u.alter, ack_ctx_list);
1423 if (NT_STATUS_EQUAL(status, NT_STATUS_RPC_PROTOCOL_ERROR)) {
1424 return dcesrv_fault_disconnect(call, DCERPC_NCA_S_PROTO_ERROR);
1426 if (!NT_STATUS_IS_OK(status)) {
1427 return status;
1430 if ((call->pkt.pfc_flags & DCERPC_PFC_FLAG_CONC_MPX) &&
1431 (call->state_flags & DCESRV_CALL_STATE_FLAG_MULTIPLEXED)) {
1432 call->conn->state_flags |= DCESRV_CALL_STATE_FLAG_MULTIPLEXED;
1433 extra_flags |= DCERPC_PFC_FLAG_CONC_MPX;
1436 if (call->state_flags & DCESRV_CALL_STATE_FLAG_PROCESS_PENDING_CALL) {
1437 call->conn->state_flags |= DCESRV_CALL_STATE_FLAG_PROCESS_PENDING_CALL;
1440 /* handle any authentication that is being requested */
1441 if (!auth_ok) {
1442 if (call->in_auth_info.auth_type !=
1443 call->conn->auth_state.auth_type)
1445 return dcesrv_fault_disconnect(call,
1446 DCERPC_FAULT_SEC_PKG_ERROR);
1448 return dcesrv_fault_disconnect(call, DCERPC_FAULT_ACCESS_DENIED);
1451 dcesrv_init_hdr(pkt, lpcfg_rpc_big_endian(call->conn->dce_ctx->lp_ctx));
1452 pkt->auth_length = 0;
1453 pkt->call_id = call->pkt.call_id;
1454 pkt->ptype = DCERPC_PKT_ALTER_RESP;
1455 pkt->pfc_flags = DCERPC_PFC_FLAG_FIRST | DCERPC_PFC_FLAG_LAST | extra_flags;
1456 pkt->u.alter_resp.max_xmit_frag = call->conn->max_xmit_frag;
1457 pkt->u.alter_resp.max_recv_frag = call->conn->max_recv_frag;
1458 pkt->u.alter_resp.assoc_group_id = call->conn->assoc_group->id;
1459 pkt->u.alter_resp.secondary_address = "";
1460 pkt->u.alter_resp.num_results = call->pkt.u.alter.num_contexts;
1461 pkt->u.alter_resp.ctx_list = ack_ctx_list;
1462 pkt->u.alter_resp.auth_info = data_blob_null;
1464 status = dcesrv_auth_prepare_alter_ack(call, pkt);
1465 if (!NT_STATUS_IS_OK(status)) {
1466 return dcesrv_fault_disconnect(call, DCERPC_FAULT_SEC_PKG_ERROR);
1469 if (auth->auth_finished) {
1470 return dcesrv_auth_reply(call);
1473 status = gensec_update_ev(auth->gensec_security,
1474 call, call->event_ctx,
1475 call->in_auth_info.credentials,
1476 &call->out_auth_info->credentials);
1478 status = dcesrv_auth_complete(call, status);
1479 if (!NT_STATUS_IS_OK(status)) {
1480 return dcesrv_fault_disconnect(call, DCERPC_FAULT_SEC_PKG_ERROR);
1483 return dcesrv_auth_reply(call);
1487 possibly save the call for inspection with ndrdump
1489 static void dcesrv_save_call(struct dcesrv_call_state *call, const char *why)
1491 #ifdef DEVELOPER
1492 char *fname;
1493 const char *dump_dir;
1494 dump_dir = lpcfg_parm_string(call->conn->dce_ctx->lp_ctx, NULL, "dcesrv", "stubs directory");
1495 if (!dump_dir) {
1496 return;
1498 fname = talloc_asprintf(call, "%s/RPC-%s-%u-%s.dat",
1499 dump_dir,
1500 call->context->iface->name,
1501 call->pkt.u.request.opnum,
1502 why);
1503 if (file_save(fname, call->pkt.u.request.stub_and_verifier.data, call->pkt.u.request.stub_and_verifier.length)) {
1504 DEBUG(0,("RPC SAVED %s\n", fname));
1506 talloc_free(fname);
1507 #endif
1510 static NTSTATUS dcesrv_check_verification_trailer(struct dcesrv_call_state *call)
1512 TALLOC_CTX *frame = talloc_stackframe();
1513 const uint32_t bitmask1 = call->conn->auth_state.client_hdr_signing ?
1514 DCERPC_SEC_VT_CLIENT_SUPPORTS_HEADER_SIGNING : 0;
1515 const struct dcerpc_sec_vt_pcontext pcontext = {
1516 .abstract_syntax = call->context->iface->syntax_id,
1517 .transfer_syntax = call->context->transfer_syntax,
1519 const struct dcerpc_sec_vt_header2 header2 =
1520 dcerpc_sec_vt_header2_from_ncacn_packet(&call->pkt);
1521 enum ndr_err_code ndr_err;
1522 struct dcerpc_sec_verification_trailer *vt = NULL;
1523 NTSTATUS status = NT_STATUS_OK;
1524 bool ok;
1526 SMB_ASSERT(call->pkt.ptype == DCERPC_PKT_REQUEST);
1528 ndr_err = ndr_pop_dcerpc_sec_verification_trailer(call->ndr_pull,
1529 frame, &vt);
1530 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
1531 status = ndr_map_error2ntstatus(ndr_err);
1532 goto done;
1535 ok = dcerpc_sec_verification_trailer_check(vt, &bitmask1,
1536 &pcontext, &header2);
1537 if (!ok) {
1538 status = NT_STATUS_ACCESS_DENIED;
1539 goto done;
1541 done:
1542 TALLOC_FREE(frame);
1543 return status;
1547 handle a dcerpc request packet
1549 static NTSTATUS dcesrv_request(struct dcesrv_call_state *call)
1551 const struct dcesrv_endpoint *endpoint = call->conn->endpoint;
1552 enum dcerpc_transport_t transport =
1553 dcerpc_binding_get_transport(endpoint->ep_description);
1554 struct ndr_pull *pull;
1555 NTSTATUS status;
1557 if (!call->conn->allow_request) {
1558 return dcesrv_fault_disconnect(call, DCERPC_NCA_S_PROTO_ERROR);
1561 /* if authenticated, and the mech we use can't do async replies, don't use them... */
1562 if (call->conn->auth_state.gensec_security &&
1563 !gensec_have_feature(call->conn->auth_state.gensec_security, GENSEC_FEATURE_ASYNC_REPLIES)) {
1564 call->state_flags &= ~DCESRV_CALL_STATE_FLAG_MAY_ASYNC;
1567 if (call->context == NULL) {
1568 return dcesrv_fault_with_flags(call, DCERPC_NCA_S_UNKNOWN_IF,
1569 DCERPC_PFC_FLAG_DID_NOT_EXECUTE);
1572 switch (call->conn->auth_state.auth_level) {
1573 case DCERPC_AUTH_LEVEL_NONE:
1574 case DCERPC_AUTH_LEVEL_PACKET:
1575 case DCERPC_AUTH_LEVEL_INTEGRITY:
1576 case DCERPC_AUTH_LEVEL_PRIVACY:
1577 break;
1578 default:
1579 if (!call->context->allow_connect) {
1580 char *addr;
1582 addr = tsocket_address_string(call->conn->remote_address,
1583 call);
1585 DEBUG(2, ("%s: restrict auth_level_connect access "
1586 "to [%s] with auth[type=0x%x,level=0x%x] "
1587 "on [%s] from [%s]\n",
1588 __func__, call->context->iface->name,
1589 call->conn->auth_state.auth_type,
1590 call->conn->auth_state.auth_level,
1591 derpc_transport_string_by_transport(transport),
1592 addr));
1593 return dcesrv_fault(call, DCERPC_FAULT_ACCESS_DENIED);
1595 break;
1598 if (call->conn->auth_state.auth_level < call->context->min_auth_level) {
1599 char *addr;
1601 addr = tsocket_address_string(call->conn->remote_address, call);
1603 DEBUG(2, ("%s: restrict access by min_auth_level[0x%x] "
1604 "to [%s] with auth[type=0x%x,level=0x%x] "
1605 "on [%s] from [%s]\n",
1606 __func__,
1607 call->context->min_auth_level,
1608 call->context->iface->name,
1609 call->conn->auth_state.auth_type,
1610 call->conn->auth_state.auth_level,
1611 derpc_transport_string_by_transport(transport),
1612 addr));
1613 return dcesrv_fault(call, DCERPC_FAULT_ACCESS_DENIED);
1616 pull = ndr_pull_init_blob(&call->pkt.u.request.stub_and_verifier, call);
1617 NT_STATUS_HAVE_NO_MEMORY(pull);
1619 pull->flags |= LIBNDR_FLAG_REF_ALLOC;
1621 call->ndr_pull = pull;
1623 if (!(call->pkt.drep[0] & DCERPC_DREP_LE)) {
1624 pull->flags |= LIBNDR_FLAG_BIGENDIAN;
1627 status = dcesrv_check_verification_trailer(call);
1628 if (!NT_STATUS_IS_OK(status)) {
1629 uint32_t faultcode = DCERPC_FAULT_OTHER;
1630 if (NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
1631 faultcode = DCERPC_FAULT_ACCESS_DENIED;
1633 DEBUG(10, ("dcesrv_check_verification_trailer failed: %s\n",
1634 nt_errstr(status)));
1635 return dcesrv_fault(call, faultcode);
1638 /* unravel the NDR for the packet */
1639 status = call->context->iface->ndr_pull(call, call, pull, &call->r);
1640 if (!NT_STATUS_IS_OK(status)) {
1641 uint8_t extra_flags = 0;
1642 if (call->fault_code == DCERPC_FAULT_OP_RNG_ERROR) {
1643 /* we got an unknown call */
1644 DEBUG(3,(__location__ ": Unknown RPC call %u on %s\n",
1645 call->pkt.u.request.opnum,
1646 call->context->iface->name));
1647 dcesrv_save_call(call, "unknown");
1648 extra_flags |= DCERPC_PFC_FLAG_DID_NOT_EXECUTE;
1649 } else {
1650 dcesrv_save_call(call, "pullfail");
1652 return dcesrv_fault_with_flags(call, call->fault_code, extra_flags);
1655 if (pull->offset != pull->data_size) {
1656 dcesrv_save_call(call, "extrabytes");
1657 DEBUG(3,("Warning: %d extra bytes in incoming RPC request\n",
1658 pull->data_size - pull->offset));
1661 /* call the dispatch function */
1662 status = call->context->iface->dispatch(call, call, call->r);
1663 if (!NT_STATUS_IS_OK(status)) {
1664 DEBUG(5,("dcerpc fault in call %s:%02x - %s\n",
1665 call->context->iface->name,
1666 call->pkt.u.request.opnum,
1667 dcerpc_errstr(pull, call->fault_code)));
1668 return dcesrv_fault(call, call->fault_code);
1671 /* add the call to the pending list */
1672 dcesrv_call_set_list(call, DCESRV_LIST_PENDING_CALL_LIST);
1674 if (call->state_flags & DCESRV_CALL_STATE_FLAG_ASYNC) {
1675 return NT_STATUS_OK;
1678 return dcesrv_reply(call);
1683 remove the call from the right list when freed
1685 static int dcesrv_call_dequeue(struct dcesrv_call_state *call)
1687 dcesrv_call_set_list(call, DCESRV_LIST_NONE);
1688 return 0;
1691 _PUBLIC_ const struct tsocket_address *dcesrv_connection_get_local_address(struct dcesrv_connection *conn)
1693 return conn->local_address;
1696 _PUBLIC_ const struct tsocket_address *dcesrv_connection_get_remote_address(struct dcesrv_connection *conn)
1698 return conn->remote_address;
1702 process some input to a dcerpc endpoint server.
1704 static NTSTATUS dcesrv_process_ncacn_packet(struct dcesrv_connection *dce_conn,
1705 struct ncacn_packet *pkt,
1706 DATA_BLOB blob)
1708 NTSTATUS status;
1709 struct dcesrv_call_state *call;
1710 struct dcesrv_call_state *existing = NULL;
1712 call = talloc_zero(dce_conn, struct dcesrv_call_state);
1713 if (!call) {
1714 data_blob_free(&blob);
1715 talloc_free(pkt);
1716 return NT_STATUS_NO_MEMORY;
1718 call->conn = dce_conn;
1719 call->event_ctx = dce_conn->event_ctx;
1720 call->msg_ctx = dce_conn->msg_ctx;
1721 call->state_flags = call->conn->state_flags;
1722 call->time = timeval_current();
1723 call->list = DCESRV_LIST_NONE;
1725 talloc_steal(call, pkt);
1726 talloc_steal(call, blob.data);
1727 call->pkt = *pkt;
1729 talloc_set_destructor(call, dcesrv_call_dequeue);
1731 if (call->conn->allow_bind) {
1733 * Only one bind is possible per connection
1735 call->conn->allow_bind = false;
1736 return dcesrv_bind(call);
1739 /* we have to check the signing here, before combining the
1740 pdus */
1741 if (call->pkt.ptype == DCERPC_PKT_REQUEST) {
1742 if (!call->conn->allow_request) {
1743 return dcesrv_fault_disconnect(call,
1744 DCERPC_NCA_S_PROTO_ERROR);
1747 status = dcerpc_verify_ncacn_packet_header(&call->pkt,
1748 DCERPC_PKT_REQUEST,
1749 call->pkt.u.request.stub_and_verifier.length,
1750 0, /* required_flags */
1751 DCERPC_PFC_FLAG_FIRST |
1752 DCERPC_PFC_FLAG_LAST |
1753 DCERPC_PFC_FLAG_PENDING_CANCEL |
1754 0x08 | /* this is not defined, but should be ignored */
1755 DCERPC_PFC_FLAG_CONC_MPX |
1756 DCERPC_PFC_FLAG_DID_NOT_EXECUTE |
1757 DCERPC_PFC_FLAG_MAYBE |
1758 DCERPC_PFC_FLAG_OBJECT_UUID);
1759 if (!NT_STATUS_IS_OK(status)) {
1760 return dcesrv_fault_disconnect(call,
1761 DCERPC_NCA_S_PROTO_ERROR);
1764 if (call->pkt.frag_length > DCERPC_FRAG_MAX_SIZE) {
1766 * We don't use dcesrv_fault_disconnect()
1767 * here, because we don't want to set
1768 * DCERPC_PFC_FLAG_DID_NOT_EXECUTE
1770 * Note that we don't check against the negotiated
1771 * max_recv_frag, but a hard coded value.
1773 dcesrv_call_disconnect_after(call,
1774 "dcesrv_auth_request - frag_length too large");
1775 return dcesrv_fault(call,
1776 DCERPC_NCA_S_PROTO_ERROR);
1779 if (call->pkt.pfc_flags & DCERPC_PFC_FLAG_FIRST) {
1780 if (dce_conn->pending_call_list != NULL) {
1782 * concurrent requests are only allowed
1783 * if DCERPC_PFC_FLAG_CONC_MPX was negotiated.
1785 if (!(dce_conn->state_flags & DCESRV_CALL_STATE_FLAG_MULTIPLEXED)) {
1786 dcesrv_call_disconnect_after(call,
1787 "dcesrv_auth_request - "
1788 "existing pending call without CONN_MPX");
1789 return dcesrv_fault(call,
1790 DCERPC_NCA_S_PROTO_ERROR);
1793 /* only one request is possible in the fragmented list */
1794 if (dce_conn->incoming_fragmented_call_list != NULL) {
1795 if (!(dce_conn->state_flags & DCESRV_CALL_STATE_FLAG_MULTIPLEXED)) {
1797 * Without DCERPC_PFC_FLAG_CONC_MPX
1798 * we need to return the FAULT on the
1799 * already existing call.
1801 * This is important to get the
1802 * call_id and context_id right.
1804 TALLOC_FREE(call);
1805 call = dce_conn->incoming_fragmented_call_list;
1807 dcesrv_call_disconnect_after(call,
1808 "dcesrv_auth_request - "
1809 "existing fragmented call");
1810 return dcesrv_fault(call,
1811 DCERPC_NCA_S_PROTO_ERROR);
1813 if (call->pkt.pfc_flags & DCERPC_PFC_FLAG_PENDING_CANCEL) {
1814 return dcesrv_fault_disconnect(call,
1815 DCERPC_FAULT_NO_CALL_ACTIVE);
1817 call->context = dcesrv_find_context(call->conn,
1818 call->pkt.u.request.context_id);
1819 if (call->context == NULL) {
1820 return dcesrv_fault_with_flags(call, DCERPC_NCA_S_UNKNOWN_IF,
1821 DCERPC_PFC_FLAG_DID_NOT_EXECUTE);
1823 } else {
1824 const struct dcerpc_request *nr = &call->pkt.u.request;
1825 const struct dcerpc_request *er = NULL;
1826 int cmp;
1828 existing = dcesrv_find_fragmented_call(dce_conn,
1829 call->pkt.call_id);
1830 if (existing == NULL) {
1831 dcesrv_call_disconnect_after(call,
1832 "dcesrv_auth_request - "
1833 "no existing fragmented call");
1834 return dcesrv_fault(call,
1835 DCERPC_NCA_S_PROTO_ERROR);
1837 er = &existing->pkt.u.request;
1839 if (call->pkt.ptype != existing->pkt.ptype) {
1840 /* trying to play silly buggers are we? */
1841 return dcesrv_fault_disconnect(existing,
1842 DCERPC_NCA_S_PROTO_ERROR);
1844 cmp = memcmp(call->pkt.drep, existing->pkt.drep,
1845 sizeof(pkt->drep));
1846 if (cmp != 0) {
1847 return dcesrv_fault_disconnect(existing,
1848 DCERPC_NCA_S_PROTO_ERROR);
1850 if (nr->context_id != er->context_id) {
1851 return dcesrv_fault_disconnect(existing,
1852 DCERPC_NCA_S_PROTO_ERROR);
1854 if (nr->opnum != er->opnum) {
1855 return dcesrv_fault_disconnect(existing,
1856 DCERPC_NCA_S_PROTO_ERROR);
1861 if (call->pkt.ptype == DCERPC_PKT_REQUEST) {
1862 bool ok;
1863 uint8_t payload_offset = DCERPC_REQUEST_LENGTH;
1865 if (call->pkt.pfc_flags & DCERPC_PFC_FLAG_OBJECT_UUID) {
1866 payload_offset += 16;
1869 ok = dcesrv_auth_pkt_pull(call, &blob,
1870 0, /* required_flags */
1871 DCERPC_PFC_FLAG_FIRST |
1872 DCERPC_PFC_FLAG_LAST |
1873 DCERPC_PFC_FLAG_PENDING_CANCEL |
1874 0x08 | /* this is not defined, but should be ignored */
1875 DCERPC_PFC_FLAG_CONC_MPX |
1876 DCERPC_PFC_FLAG_DID_NOT_EXECUTE |
1877 DCERPC_PFC_FLAG_MAYBE |
1878 DCERPC_PFC_FLAG_OBJECT_UUID,
1879 payload_offset,
1880 &call->pkt.u.request.stub_and_verifier);
1881 if (!ok) {
1883 * We don't use dcesrv_fault_disconnect()
1884 * here, because we don't want to set
1885 * DCERPC_PFC_FLAG_DID_NOT_EXECUTE
1887 dcesrv_call_disconnect_after(call,
1888 "dcesrv_auth_request - failed");
1889 if (call->fault_code == 0) {
1890 call->fault_code = DCERPC_FAULT_ACCESS_DENIED;
1892 return dcesrv_fault(call, call->fault_code);
1896 /* see if this is a continued packet */
1897 if (existing != NULL) {
1898 struct dcerpc_request *er = &existing->pkt.u.request;
1899 const struct dcerpc_request *nr = &call->pkt.u.request;
1900 size_t available;
1901 size_t alloc_size;
1902 size_t alloc_hint;
1905 * Up to 4 MByte are allowed by all fragments
1907 available = dce_conn->max_total_request_size;
1908 if (er->stub_and_verifier.length > available) {
1909 dcesrv_call_disconnect_after(existing,
1910 "dcesrv_auth_request - existing payload too large");
1911 return dcesrv_fault(existing, DCERPC_FAULT_ACCESS_DENIED);
1913 available -= er->stub_and_verifier.length;
1914 if (nr->alloc_hint > available) {
1915 dcesrv_call_disconnect_after(existing,
1916 "dcesrv_auth_request - alloc hint too large");
1917 return dcesrv_fault(existing, DCERPC_FAULT_ACCESS_DENIED);
1919 if (nr->stub_and_verifier.length > available) {
1920 dcesrv_call_disconnect_after(existing,
1921 "dcesrv_auth_request - new payload too large");
1922 return dcesrv_fault(existing, DCERPC_FAULT_ACCESS_DENIED);
1924 alloc_hint = er->stub_and_verifier.length + nr->alloc_hint;
1925 /* allocate at least 1 byte */
1926 alloc_hint = MAX(alloc_hint, 1);
1927 alloc_size = er->stub_and_verifier.length +
1928 nr->stub_and_verifier.length;
1929 alloc_size = MAX(alloc_size, alloc_hint);
1931 er->stub_and_verifier.data =
1932 talloc_realloc(existing,
1933 er->stub_and_verifier.data,
1934 uint8_t, alloc_size);
1935 if (er->stub_and_verifier.data == NULL) {
1936 TALLOC_FREE(call);
1937 return dcesrv_fault_with_flags(existing,
1938 DCERPC_FAULT_OUT_OF_RESOURCES,
1939 DCERPC_PFC_FLAG_DID_NOT_EXECUTE);
1941 memcpy(er->stub_and_verifier.data +
1942 er->stub_and_verifier.length,
1943 nr->stub_and_verifier.data,
1944 nr->stub_and_verifier.length);
1945 er->stub_and_verifier.length += nr->stub_and_verifier.length;
1947 existing->pkt.pfc_flags |= (call->pkt.pfc_flags & DCERPC_PFC_FLAG_LAST);
1949 TALLOC_FREE(call);
1950 call = existing;
1953 /* this may not be the last pdu in the chain - if its isn't then
1954 just put it on the incoming_fragmented_call_list and wait for the rest */
1955 if (call->pkt.ptype == DCERPC_PKT_REQUEST &&
1956 !(call->pkt.pfc_flags & DCERPC_PFC_FLAG_LAST)) {
1958 * Up to 4 MByte are allowed by all fragments
1960 if (call->pkt.u.request.alloc_hint > dce_conn->max_total_request_size) {
1961 dcesrv_call_disconnect_after(call,
1962 "dcesrv_auth_request - initial alloc hint too large");
1963 return dcesrv_fault(call, DCERPC_FAULT_ACCESS_DENIED);
1965 dcesrv_call_set_list(call, DCESRV_LIST_FRAGMENTED_CALL_LIST);
1966 return NT_STATUS_OK;
1969 /* This removes any fragments we may have had stashed away */
1970 dcesrv_call_set_list(call, DCESRV_LIST_NONE);
1972 switch (call->pkt.ptype) {
1973 case DCERPC_PKT_BIND:
1974 status = dcesrv_bind_nak(call,
1975 DCERPC_BIND_NAK_REASON_NOT_SPECIFIED);
1976 break;
1977 case DCERPC_PKT_AUTH3:
1978 status = dcesrv_auth3(call);
1979 break;
1980 case DCERPC_PKT_ALTER:
1981 status = dcesrv_alter(call);
1982 break;
1983 case DCERPC_PKT_REQUEST:
1984 status = dcesrv_request(call);
1985 break;
1986 case DCERPC_PKT_CO_CANCEL:
1987 case DCERPC_PKT_ORPHANED:
1989 * Window just ignores CO_CANCEL and ORPHANED,
1990 * so we do...
1992 status = NT_STATUS_OK;
1993 TALLOC_FREE(call);
1994 break;
1995 case DCERPC_PKT_BIND_ACK:
1996 case DCERPC_PKT_BIND_NAK:
1997 case DCERPC_PKT_ALTER_RESP:
1998 case DCERPC_PKT_RESPONSE:
1999 case DCERPC_PKT_FAULT:
2000 case DCERPC_PKT_SHUTDOWN:
2001 default:
2002 status = dcesrv_fault_disconnect(call, DCERPC_NCA_S_PROTO_ERROR);
2003 break;
2006 /* if we are going to be sending a reply then add
2007 it to the list of pending calls. We add it to the end to keep the call
2008 list in the order we will answer */
2009 if (!NT_STATUS_IS_OK(status)) {
2010 talloc_free(call);
2013 return status;
2016 _PUBLIC_ NTSTATUS dcesrv_init_context(TALLOC_CTX *mem_ctx,
2017 struct loadparm_context *lp_ctx,
2018 const char **endpoint_servers, struct dcesrv_context **_dce_ctx)
2020 NTSTATUS status;
2021 struct dcesrv_context *dce_ctx;
2022 int i;
2024 if (!endpoint_servers) {
2025 DEBUG(0,("dcesrv_init_context: no endpoint servers configured\n"));
2026 return NT_STATUS_INTERNAL_ERROR;
2029 dce_ctx = talloc_zero(mem_ctx, struct dcesrv_context);
2030 NT_STATUS_HAVE_NO_MEMORY(dce_ctx);
2032 if (uid_wrapper_enabled()) {
2033 setenv("UID_WRAPPER_MYUID", "1", 1);
2035 dce_ctx->initial_euid = geteuid();
2036 if (uid_wrapper_enabled()) {
2037 unsetenv("UID_WRAPPER_MYUID");
2040 dce_ctx->endpoint_list = NULL;
2041 dce_ctx->lp_ctx = lp_ctx;
2042 dce_ctx->assoc_groups_idr = idr_init(dce_ctx);
2043 NT_STATUS_HAVE_NO_MEMORY(dce_ctx->assoc_groups_idr);
2044 dce_ctx->broken_connections = NULL;
2046 for (i=0;endpoint_servers[i];i++) {
2047 const struct dcesrv_endpoint_server *ep_server;
2049 ep_server = dcesrv_ep_server_byname(endpoint_servers[i]);
2050 if (!ep_server) {
2051 DEBUG(0,("dcesrv_init_context: failed to find endpoint server = '%s'\n", endpoint_servers[i]));
2052 return NT_STATUS_INTERNAL_ERROR;
2055 status = ep_server->init_server(dce_ctx, ep_server);
2056 if (!NT_STATUS_IS_OK(status)) {
2057 DEBUG(0,("dcesrv_init_context: failed to init endpoint server = '%s': %s\n", endpoint_servers[i],
2058 nt_errstr(status)));
2059 return status;
2063 *_dce_ctx = dce_ctx;
2064 return NT_STATUS_OK;
2067 /* the list of currently registered DCERPC endpoint servers.
2069 static struct ep_server {
2070 struct dcesrv_endpoint_server *ep_server;
2071 } *ep_servers = NULL;
2072 static int num_ep_servers;
2075 register a DCERPC endpoint server.
2077 The 'name' can be later used by other backends to find the operations
2078 structure for this backend.
2081 _PUBLIC_ NTSTATUS dcerpc_register_ep_server(const struct dcesrv_endpoint_server *ep_server)
2084 if (dcesrv_ep_server_byname(ep_server->name) != NULL) {
2085 /* its already registered! */
2086 DEBUG(0,("DCERPC endpoint server '%s' already registered\n",
2087 ep_server->name));
2088 return NT_STATUS_OBJECT_NAME_COLLISION;
2091 ep_servers = realloc_p(ep_servers, struct ep_server, num_ep_servers+1);
2092 if (!ep_servers) {
2093 smb_panic("out of memory in dcerpc_register");
2096 ep_servers[num_ep_servers].ep_server = smb_xmemdup(ep_server, sizeof(*ep_server));
2097 ep_servers[num_ep_servers].ep_server->name = smb_xstrdup(ep_server->name);
2099 num_ep_servers++;
2101 DEBUG(3,("DCERPC endpoint server '%s' registered\n",
2102 ep_server->name));
2104 return NT_STATUS_OK;
2108 return the operations structure for a named backend of the specified type
2110 const struct dcesrv_endpoint_server *dcesrv_ep_server_byname(const char *name)
2112 int i;
2114 for (i=0;i<num_ep_servers;i++) {
2115 if (strcmp(ep_servers[i].ep_server->name, name) == 0) {
2116 return ep_servers[i].ep_server;
2120 return NULL;
2123 void dcerpc_server_init(struct loadparm_context *lp_ctx)
2125 static bool initialized;
2126 #define _MODULE_PROTO(init) extern NTSTATUS init(TALLOC_CTX *);
2127 STATIC_dcerpc_server_MODULES_PROTO;
2128 init_module_fn static_init[] = { STATIC_dcerpc_server_MODULES };
2129 init_module_fn *shared_init;
2131 if (initialized) {
2132 return;
2134 initialized = true;
2136 shared_init = load_samba_modules(NULL, "dcerpc_server");
2138 run_init_functions(NULL, static_init);
2139 run_init_functions(NULL, shared_init);
2141 talloc_free(shared_init);
2145 return the DCERPC module version, and the size of some critical types
2146 This can be used by endpoint server modules to either detect compilation errors, or provide
2147 multiple implementations for different smbd compilation options in one module
2149 const struct dcesrv_critical_sizes *dcerpc_module_version(void)
2151 static const struct dcesrv_critical_sizes critical_sizes = {
2152 DCERPC_MODULE_VERSION,
2153 sizeof(struct dcesrv_context),
2154 sizeof(struct dcesrv_endpoint),
2155 sizeof(struct dcesrv_endpoint_server),
2156 sizeof(struct dcesrv_interface),
2157 sizeof(struct dcesrv_if_list),
2158 sizeof(struct dcesrv_connection),
2159 sizeof(struct dcesrv_call_state),
2160 sizeof(struct dcesrv_auth),
2161 sizeof(struct dcesrv_handle)
2164 return &critical_sizes;
2167 static void dcesrv_terminate_connection(struct dcesrv_connection *dce_conn, const char *reason)
2169 struct dcesrv_context *dce_ctx = dce_conn->dce_ctx;
2170 struct stream_connection *srv_conn;
2171 srv_conn = talloc_get_type(dce_conn->transport.private_data,
2172 struct stream_connection);
2174 dce_conn->wait_send = NULL;
2175 dce_conn->wait_recv = NULL;
2176 dce_conn->wait_private = NULL;
2178 dce_conn->allow_bind = false;
2179 dce_conn->allow_auth3 = false;
2180 dce_conn->allow_alter = false;
2181 dce_conn->allow_request = false;
2183 if (dce_conn->pending_call_list == NULL) {
2184 char *full_reason = talloc_asprintf(dce_conn, "dcesrv: %s", reason);
2186 DLIST_REMOVE(dce_ctx->broken_connections, dce_conn);
2187 stream_terminate_connection(srv_conn, full_reason ? full_reason : reason);
2188 return;
2191 if (dce_conn->terminate != NULL) {
2192 return;
2195 DEBUG(3,("dcesrv: terminating connection due to '%s' deferred due to pending calls\n",
2196 reason));
2197 dce_conn->terminate = talloc_strdup(dce_conn, reason);
2198 if (dce_conn->terminate == NULL) {
2199 dce_conn->terminate = "dcesrv: deferred terminating connection - no memory";
2201 DLIST_ADD_END(dce_ctx->broken_connections, dce_conn);
2204 static void dcesrv_cleanup_broken_connections(struct dcesrv_context *dce_ctx)
2206 struct dcesrv_connection *cur, *next;
2208 next = dce_ctx->broken_connections;
2209 while (next != NULL) {
2210 cur = next;
2211 next = cur->next;
2213 if (cur->state_flags & DCESRV_CALL_STATE_FLAG_PROCESS_PENDING_CALL) {
2214 struct dcesrv_connection_context *context_cur, *context_next;
2216 context_next = cur->contexts;
2217 while (context_next != NULL) {
2218 context_cur = context_next;
2219 context_next = context_cur->next;
2221 dcesrv_connection_context_destructor(context_cur);
2225 dcesrv_terminate_connection(cur, cur->terminate);
2229 /* We need this include to be able to compile on some plateforms
2230 * (ie. freebsd 7.2) as it seems that <sys/uio.h> is not included
2231 * correctly.
2232 * It has to be that deep because otherwise we have a conflict on
2233 * const struct dcesrv_interface declaration.
2234 * This is mostly due to socket_wrapper defining #define bind swrap_bind
2235 * which conflict with the bind used before.
2237 #include "system/network.h"
2239 struct dcesrv_sock_reply_state {
2240 struct dcesrv_connection *dce_conn;
2241 struct dcesrv_call_state *call;
2242 struct iovec iov;
2245 static void dcesrv_sock_reply_done(struct tevent_req *subreq);
2246 static void dcesrv_call_terminate_step1(struct tevent_req *subreq);
2248 static void dcesrv_sock_report_output_data(struct dcesrv_connection *dce_conn)
2250 struct dcesrv_call_state *call;
2252 call = dce_conn->call_list;
2253 if (!call || !call->replies) {
2254 return;
2257 while (call->replies) {
2258 struct data_blob_list_item *rep = call->replies;
2259 struct dcesrv_sock_reply_state *substate;
2260 struct tevent_req *subreq;
2262 substate = talloc_zero(call, struct dcesrv_sock_reply_state);
2263 if (!substate) {
2264 dcesrv_terminate_connection(dce_conn, "no memory");
2265 return;
2268 substate->dce_conn = dce_conn;
2269 substate->call = NULL;
2271 DLIST_REMOVE(call->replies, rep);
2273 if (call->replies == NULL && call->terminate_reason == NULL) {
2274 substate->call = call;
2277 substate->iov.iov_base = (void *) rep->blob.data;
2278 substate->iov.iov_len = rep->blob.length;
2280 subreq = tstream_writev_queue_send(substate,
2281 dce_conn->event_ctx,
2282 dce_conn->stream,
2283 dce_conn->send_queue,
2284 &substate->iov, 1);
2285 if (!subreq) {
2286 dcesrv_terminate_connection(dce_conn, "no memory");
2287 return;
2289 tevent_req_set_callback(subreq, dcesrv_sock_reply_done,
2290 substate);
2293 if (call->terminate_reason != NULL) {
2294 struct tevent_req *subreq;
2296 subreq = tevent_queue_wait_send(call,
2297 dce_conn->event_ctx,
2298 dce_conn->send_queue);
2299 if (!subreq) {
2300 dcesrv_terminate_connection(dce_conn, __location__);
2301 return;
2303 tevent_req_set_callback(subreq, dcesrv_call_terminate_step1,
2304 call);
2307 DLIST_REMOVE(call->conn->call_list, call);
2308 call->list = DCESRV_LIST_NONE;
2311 static void dcesrv_sock_reply_done(struct tevent_req *subreq)
2313 struct dcesrv_sock_reply_state *substate = tevent_req_callback_data(subreq,
2314 struct dcesrv_sock_reply_state);
2315 int ret;
2316 int sys_errno;
2317 NTSTATUS status;
2318 struct dcesrv_call_state *call = substate->call;
2320 ret = tstream_writev_queue_recv(subreq, &sys_errno);
2321 TALLOC_FREE(subreq);
2322 if (ret == -1) {
2323 status = map_nt_error_from_unix_common(sys_errno);
2324 dcesrv_terminate_connection(substate->dce_conn, nt_errstr(status));
2325 return;
2328 talloc_free(substate);
2329 if (call) {
2330 talloc_free(call);
2334 static void dcesrv_call_terminate_step2(struct tevent_req *subreq);
2336 static void dcesrv_call_terminate_step1(struct tevent_req *subreq)
2338 struct dcesrv_call_state *call = tevent_req_callback_data(subreq,
2339 struct dcesrv_call_state);
2340 bool ok;
2341 struct timeval tv;
2343 /* make sure we stop send queue before removing subreq */
2344 tevent_queue_stop(call->conn->send_queue);
2346 ok = tevent_queue_wait_recv(subreq);
2347 TALLOC_FREE(subreq);
2348 if (!ok) {
2349 dcesrv_terminate_connection(call->conn, __location__);
2350 return;
2353 /* disconnect after 200 usecs */
2354 tv = timeval_current_ofs_usec(200);
2355 subreq = tevent_wakeup_send(call, call->conn->event_ctx, tv);
2356 if (subreq == NULL) {
2357 dcesrv_terminate_connection(call->conn, __location__);
2358 return;
2360 tevent_req_set_callback(subreq, dcesrv_call_terminate_step2,
2361 call);
2364 static void dcesrv_call_terminate_step2(struct tevent_req *subreq)
2366 struct dcesrv_call_state *call = tevent_req_callback_data(subreq,
2367 struct dcesrv_call_state);
2368 bool ok;
2370 ok = tevent_wakeup_recv(subreq);
2371 TALLOC_FREE(subreq);
2372 if (!ok) {
2373 dcesrv_terminate_connection(call->conn, __location__);
2374 return;
2377 dcesrv_terminate_connection(call->conn, call->terminate_reason);
2380 struct dcesrv_socket_context {
2381 const struct dcesrv_endpoint *endpoint;
2382 struct dcesrv_context *dcesrv_ctx;
2386 static void dcesrv_read_fragment_done(struct tevent_req *subreq);
2388 static void dcesrv_sock_accept(struct stream_connection *srv_conn)
2390 NTSTATUS status;
2391 struct dcesrv_socket_context *dcesrv_sock =
2392 talloc_get_type(srv_conn->private_data, struct dcesrv_socket_context);
2393 enum dcerpc_transport_t transport =
2394 dcerpc_binding_get_transport(dcesrv_sock->endpoint->ep_description);
2395 struct dcesrv_connection *dcesrv_conn = NULL;
2396 int ret;
2397 struct tevent_req *subreq;
2398 struct loadparm_context *lp_ctx = dcesrv_sock->dcesrv_ctx->lp_ctx;
2400 dcesrv_cleanup_broken_connections(dcesrv_sock->dcesrv_ctx);
2402 if (!srv_conn->session_info) {
2403 status = auth_anonymous_session_info(srv_conn,
2404 lp_ctx,
2405 &srv_conn->session_info);
2406 if (!NT_STATUS_IS_OK(status)) {
2407 DEBUG(0,("dcesrv_sock_accept: auth_anonymous_session_info failed: %s\n",
2408 nt_errstr(status)));
2409 stream_terminate_connection(srv_conn, nt_errstr(status));
2410 return;
2415 * This fills in dcesrv_conn->endpoint with the endpoint
2416 * associated with the socket. From this point on we know
2417 * which (group of) services we are handling, but not the
2418 * specific interface.
2421 status = dcesrv_endpoint_connect(dcesrv_sock->dcesrv_ctx,
2422 srv_conn,
2423 dcesrv_sock->endpoint,
2424 srv_conn->session_info,
2425 srv_conn->event.ctx,
2426 srv_conn->msg_ctx,
2427 srv_conn->server_id,
2428 DCESRV_CALL_STATE_FLAG_MAY_ASYNC,
2429 &dcesrv_conn);
2430 if (!NT_STATUS_IS_OK(status)) {
2431 DEBUG(0,("dcesrv_sock_accept: dcesrv_endpoint_connect failed: %s\n",
2432 nt_errstr(status)));
2433 stream_terminate_connection(srv_conn, nt_errstr(status));
2434 return;
2437 dcesrv_conn->transport.private_data = srv_conn;
2438 dcesrv_conn->transport.report_output_data = dcesrv_sock_report_output_data;
2440 TALLOC_FREE(srv_conn->event.fde);
2442 dcesrv_conn->send_queue = tevent_queue_create(dcesrv_conn, "dcesrv send queue");
2443 if (!dcesrv_conn->send_queue) {
2444 status = NT_STATUS_NO_MEMORY;
2445 DEBUG(0,("dcesrv_sock_accept: tevent_queue_create(%s)\n",
2446 nt_errstr(status)));
2447 stream_terminate_connection(srv_conn, nt_errstr(status));
2448 return;
2451 if (transport == NCACN_NP) {
2452 dcesrv_conn->auth_state.session_key = dcesrv_inherited_session_key;
2453 dcesrv_conn->stream = talloc_move(dcesrv_conn,
2454 &srv_conn->tstream);
2455 } else {
2456 ret = tstream_bsd_existing_socket(dcesrv_conn,
2457 socket_get_fd(srv_conn->socket),
2458 &dcesrv_conn->stream);
2459 if (ret == -1) {
2460 status = map_nt_error_from_unix_common(errno);
2461 DEBUG(0, ("dcesrv_sock_accept: "
2462 "failed to setup tstream: %s\n",
2463 nt_errstr(status)));
2464 stream_terminate_connection(srv_conn, nt_errstr(status));
2465 return;
2467 socket_set_flags(srv_conn->socket, SOCKET_FLAG_NOCLOSE);
2470 dcesrv_conn->local_address = srv_conn->local_address;
2471 dcesrv_conn->remote_address = srv_conn->remote_address;
2473 if (transport == NCALRPC) {
2474 uid_t uid;
2475 gid_t gid;
2476 int sock_fd;
2478 sock_fd = socket_get_fd(srv_conn->socket);
2479 if (sock_fd == -1) {
2480 stream_terminate_connection(
2481 srv_conn, "socket_get_fd failed\n");
2482 return;
2485 ret = getpeereid(sock_fd, &uid, &gid);
2486 if (ret == -1) {
2487 status = map_nt_error_from_unix_common(errno);
2488 DEBUG(0, ("dcesrv_sock_accept: "
2489 "getpeereid() failed for NCALRPC: %s\n",
2490 nt_errstr(status)));
2491 stream_terminate_connection(srv_conn, nt_errstr(status));
2492 return;
2494 if (uid == dcesrv_conn->dce_ctx->initial_euid) {
2495 struct tsocket_address *r = NULL;
2497 ret = tsocket_address_unix_from_path(dcesrv_conn,
2498 "/root/ncalrpc_as_system",
2499 &r);
2500 if (ret == -1) {
2501 status = map_nt_error_from_unix_common(errno);
2502 DEBUG(0, ("dcesrv_sock_accept: "
2503 "tsocket_address_unix_from_path() failed for NCALRPC: %s\n",
2504 nt_errstr(status)));
2505 stream_terminate_connection(srv_conn, nt_errstr(status));
2506 return;
2508 dcesrv_conn->remote_address = r;
2512 srv_conn->private_data = dcesrv_conn;
2514 irpc_add_name(srv_conn->msg_ctx, "rpc_server");
2516 subreq = dcerpc_read_ncacn_packet_send(dcesrv_conn,
2517 dcesrv_conn->event_ctx,
2518 dcesrv_conn->stream);
2519 if (!subreq) {
2520 status = NT_STATUS_NO_MEMORY;
2521 DEBUG(0,("dcesrv_sock_accept: dcerpc_read_fragment_buffer_send(%s)\n",
2522 nt_errstr(status)));
2523 stream_terminate_connection(srv_conn, nt_errstr(status));
2524 return;
2526 tevent_req_set_callback(subreq, dcesrv_read_fragment_done, dcesrv_conn);
2528 return;
2531 static void dcesrv_conn_wait_done(struct tevent_req *subreq);
2533 static void dcesrv_read_fragment_done(struct tevent_req *subreq)
2535 struct dcesrv_connection *dce_conn = tevent_req_callback_data(subreq,
2536 struct dcesrv_connection);
2537 struct dcesrv_context *dce_ctx = dce_conn->dce_ctx;
2538 struct ncacn_packet *pkt;
2539 DATA_BLOB buffer;
2540 NTSTATUS status;
2542 if (dce_conn->terminate) {
2544 * if the current connection is broken
2545 * we need to clean it up before any other connection
2547 dcesrv_terminate_connection(dce_conn, dce_conn->terminate);
2548 dcesrv_cleanup_broken_connections(dce_ctx);
2549 return;
2552 dcesrv_cleanup_broken_connections(dce_ctx);
2554 status = dcerpc_read_ncacn_packet_recv(subreq, dce_conn,
2555 &pkt, &buffer);
2556 TALLOC_FREE(subreq);
2557 if (!NT_STATUS_IS_OK(status)) {
2558 dcesrv_terminate_connection(dce_conn, nt_errstr(status));
2559 return;
2562 status = dcesrv_process_ncacn_packet(dce_conn, pkt, buffer);
2563 if (!NT_STATUS_IS_OK(status)) {
2564 dcesrv_terminate_connection(dce_conn, nt_errstr(status));
2565 return;
2569 * This is used to block the connection during
2570 * pending authentication.
2572 if (dce_conn->wait_send != NULL) {
2573 subreq = dce_conn->wait_send(dce_conn,
2574 dce_conn->event_ctx,
2575 dce_conn->wait_private);
2576 if (!subreq) {
2577 status = NT_STATUS_NO_MEMORY;
2578 dcesrv_terminate_connection(dce_conn, nt_errstr(status));
2579 return;
2581 tevent_req_set_callback(subreq, dcesrv_conn_wait_done, dce_conn);
2582 return;
2585 subreq = dcerpc_read_ncacn_packet_send(dce_conn,
2586 dce_conn->event_ctx,
2587 dce_conn->stream);
2588 if (!subreq) {
2589 status = NT_STATUS_NO_MEMORY;
2590 dcesrv_terminate_connection(dce_conn, nt_errstr(status));
2591 return;
2593 tevent_req_set_callback(subreq, dcesrv_read_fragment_done, dce_conn);
2596 static void dcesrv_conn_wait_done(struct tevent_req *subreq)
2598 struct dcesrv_connection *dce_conn = tevent_req_callback_data(subreq,
2599 struct dcesrv_connection);
2600 struct dcesrv_context *dce_ctx = dce_conn->dce_ctx;
2601 NTSTATUS status;
2603 if (dce_conn->terminate) {
2605 * if the current connection is broken
2606 * we need to clean it up before any other connection
2608 dcesrv_terminate_connection(dce_conn, dce_conn->terminate);
2609 dcesrv_cleanup_broken_connections(dce_ctx);
2610 return;
2613 dcesrv_cleanup_broken_connections(dce_ctx);
2615 status = dce_conn->wait_recv(subreq);
2616 dce_conn->wait_send = NULL;
2617 dce_conn->wait_recv = NULL;
2618 dce_conn->wait_private = NULL;
2619 TALLOC_FREE(subreq);
2620 if (!NT_STATUS_IS_OK(status)) {
2621 dcesrv_terminate_connection(dce_conn, nt_errstr(status));
2622 return;
2625 subreq = dcerpc_read_ncacn_packet_send(dce_conn,
2626 dce_conn->event_ctx,
2627 dce_conn->stream);
2628 if (!subreq) {
2629 status = NT_STATUS_NO_MEMORY;
2630 dcesrv_terminate_connection(dce_conn, nt_errstr(status));
2631 return;
2633 tevent_req_set_callback(subreq, dcesrv_read_fragment_done, dce_conn);
2636 static void dcesrv_sock_recv(struct stream_connection *conn, uint16_t flags)
2638 struct dcesrv_connection *dce_conn = talloc_get_type(conn->private_data,
2639 struct dcesrv_connection);
2640 dcesrv_terminate_connection(dce_conn, "dcesrv_sock_recv triggered");
2643 static void dcesrv_sock_send(struct stream_connection *conn, uint16_t flags)
2645 struct dcesrv_connection *dce_conn = talloc_get_type(conn->private_data,
2646 struct dcesrv_connection);
2647 dcesrv_terminate_connection(dce_conn, "dcesrv_sock_send triggered");
2651 static const struct stream_server_ops dcesrv_stream_ops = {
2652 .name = "rpc",
2653 .accept_connection = dcesrv_sock_accept,
2654 .recv_handler = dcesrv_sock_recv,
2655 .send_handler = dcesrv_sock_send,
2658 static NTSTATUS dcesrv_add_ep_unix(struct dcesrv_context *dce_ctx,
2659 struct loadparm_context *lp_ctx,
2660 struct dcesrv_endpoint *e,
2661 struct tevent_context *event_ctx, const struct model_ops *model_ops)
2663 struct dcesrv_socket_context *dcesrv_sock;
2664 uint16_t port = 1;
2665 NTSTATUS status;
2666 const char *endpoint;
2668 dcesrv_sock = talloc_zero(event_ctx, struct dcesrv_socket_context);
2669 NT_STATUS_HAVE_NO_MEMORY(dcesrv_sock);
2671 /* remember the endpoint of this socket */
2672 dcesrv_sock->endpoint = e;
2673 dcesrv_sock->dcesrv_ctx = talloc_reference(dcesrv_sock, dce_ctx);
2675 endpoint = dcerpc_binding_get_string_option(e->ep_description, "endpoint");
2677 status = stream_setup_socket(dcesrv_sock, event_ctx, lp_ctx,
2678 model_ops, &dcesrv_stream_ops,
2679 "unix", endpoint, &port,
2680 lpcfg_socket_options(lp_ctx),
2681 dcesrv_sock);
2682 if (!NT_STATUS_IS_OK(status)) {
2683 DEBUG(0,("service_setup_stream_socket(path=%s) failed - %s\n",
2684 endpoint, nt_errstr(status)));
2687 return status;
2690 static NTSTATUS dcesrv_add_ep_ncalrpc(struct dcesrv_context *dce_ctx,
2691 struct loadparm_context *lp_ctx,
2692 struct dcesrv_endpoint *e,
2693 struct tevent_context *event_ctx, const struct model_ops *model_ops)
2695 struct dcesrv_socket_context *dcesrv_sock;
2696 uint16_t port = 1;
2697 char *full_path;
2698 NTSTATUS status;
2699 const char *endpoint;
2701 endpoint = dcerpc_binding_get_string_option(e->ep_description, "endpoint");
2703 if (endpoint == NULL) {
2705 * No identifier specified: use DEFAULT.
2707 * TODO: DO NOT hardcode this value anywhere else. Rather, specify
2708 * no endpoint and let the epmapper worry about it.
2710 endpoint = "DEFAULT";
2711 status = dcerpc_binding_set_string_option(e->ep_description,
2712 "endpoint",
2713 endpoint);
2714 if (!NT_STATUS_IS_OK(status)) {
2715 DEBUG(0,("dcerpc_binding_set_string_option() failed - %s\n",
2716 nt_errstr(status)));
2717 return status;
2721 full_path = talloc_asprintf(dce_ctx, "%s/%s", lpcfg_ncalrpc_dir(lp_ctx),
2722 endpoint);
2724 dcesrv_sock = talloc_zero(event_ctx, struct dcesrv_socket_context);
2725 NT_STATUS_HAVE_NO_MEMORY(dcesrv_sock);
2727 /* remember the endpoint of this socket */
2728 dcesrv_sock->endpoint = e;
2729 dcesrv_sock->dcesrv_ctx = talloc_reference(dcesrv_sock, dce_ctx);
2731 status = stream_setup_socket(dcesrv_sock, event_ctx, lp_ctx,
2732 model_ops, &dcesrv_stream_ops,
2733 "unix", full_path, &port,
2734 lpcfg_socket_options(lp_ctx),
2735 dcesrv_sock);
2736 if (!NT_STATUS_IS_OK(status)) {
2737 DEBUG(0,("service_setup_stream_socket(identifier=%s,path=%s) failed - %s\n",
2738 endpoint, full_path, nt_errstr(status)));
2740 return status;
2743 static NTSTATUS dcesrv_add_ep_np(struct dcesrv_context *dce_ctx,
2744 struct loadparm_context *lp_ctx,
2745 struct dcesrv_endpoint *e,
2746 struct tevent_context *event_ctx, const struct model_ops *model_ops)
2748 struct dcesrv_socket_context *dcesrv_sock;
2749 NTSTATUS status;
2750 const char *endpoint;
2752 endpoint = dcerpc_binding_get_string_option(e->ep_description, "endpoint");
2753 if (endpoint == NULL) {
2754 DEBUG(0, ("Endpoint mandatory for named pipes\n"));
2755 return NT_STATUS_INVALID_PARAMETER;
2758 dcesrv_sock = talloc_zero(event_ctx, struct dcesrv_socket_context);
2759 NT_STATUS_HAVE_NO_MEMORY(dcesrv_sock);
2761 /* remember the endpoint of this socket */
2762 dcesrv_sock->endpoint = e;
2763 dcesrv_sock->dcesrv_ctx = talloc_reference(dcesrv_sock, dce_ctx);
2765 status = tstream_setup_named_pipe(dce_ctx, event_ctx, lp_ctx,
2766 model_ops, &dcesrv_stream_ops,
2767 endpoint,
2768 dcesrv_sock);
2769 if (!NT_STATUS_IS_OK(status)) {
2770 DEBUG(0,("stream_setup_named_pipe(pipe=%s) failed - %s\n",
2771 endpoint, nt_errstr(status)));
2772 return status;
2775 return NT_STATUS_OK;
2779 add a socket address to the list of events, one event per dcerpc endpoint
2781 static NTSTATUS add_socket_rpc_tcp_iface(struct dcesrv_context *dce_ctx, struct dcesrv_endpoint *e,
2782 struct tevent_context *event_ctx, const struct model_ops *model_ops,
2783 const char *address)
2785 struct dcesrv_socket_context *dcesrv_sock;
2786 uint16_t port = 0;
2787 NTSTATUS status;
2788 const char *endpoint;
2789 char port_str[6];
2791 endpoint = dcerpc_binding_get_string_option(e->ep_description, "endpoint");
2792 if (endpoint != NULL) {
2793 port = atoi(endpoint);
2796 dcesrv_sock = talloc_zero(event_ctx, struct dcesrv_socket_context);
2797 NT_STATUS_HAVE_NO_MEMORY(dcesrv_sock);
2799 /* remember the endpoint of this socket */
2800 dcesrv_sock->endpoint = e;
2801 dcesrv_sock->dcesrv_ctx = talloc_reference(dcesrv_sock, dce_ctx);
2803 status = stream_setup_socket(dcesrv_sock, event_ctx, dce_ctx->lp_ctx,
2804 model_ops, &dcesrv_stream_ops,
2805 "ip", address, &port,
2806 lpcfg_socket_options(dce_ctx->lp_ctx),
2807 dcesrv_sock);
2808 if (!NT_STATUS_IS_OK(status)) {
2809 struct dcesrv_if_list *iface;
2810 DEBUG(0,("service_setup_stream_socket(address=%s,port=%u) for ",
2811 address, port));
2812 for (iface = e->interface_list; iface; iface = iface->next) {
2813 DEBUGADD(0, ("%s ", iface->iface.name));
2815 DEBUGADD(0, ("failed - %s",
2816 nt_errstr(status)));
2817 return status;
2820 snprintf(port_str, sizeof(port_str), "%u", port);
2822 status = dcerpc_binding_set_string_option(e->ep_description,
2823 "endpoint", port_str);
2824 if (!NT_STATUS_IS_OK(status)) {
2825 DEBUG(0,("dcerpc_binding_set_string_option(endpoint, %s) failed - %s\n",
2826 port_str, nt_errstr(status)));
2827 return status;
2828 } else {
2829 struct dcesrv_if_list *iface;
2830 DEBUG(4,("Successfully listening on ncacn_ip_tcp endpoint [%s]:[%s] for ",
2831 address, port_str));
2832 for (iface = e->interface_list; iface; iface = iface->next) {
2833 DEBUGADD(4, ("%s ", iface->iface.name));
2835 DEBUGADD(4, ("\n"));
2838 return NT_STATUS_OK;
2841 #include "lib/socket/netif.h" /* Included here to work around the fact that socket_wrapper redefines bind() */
2843 static NTSTATUS dcesrv_add_ep_tcp(struct dcesrv_context *dce_ctx,
2844 struct loadparm_context *lp_ctx,
2845 struct dcesrv_endpoint *e,
2846 struct tevent_context *event_ctx, const struct model_ops *model_ops)
2848 NTSTATUS status;
2850 /* Add TCP/IP sockets */
2851 if (lpcfg_interfaces(lp_ctx) && lpcfg_bind_interfaces_only(lp_ctx)) {
2852 int num_interfaces;
2853 int i;
2854 struct interface *ifaces;
2856 load_interface_list(dce_ctx, lp_ctx, &ifaces);
2858 num_interfaces = iface_list_count(ifaces);
2859 for(i = 0; i < num_interfaces; i++) {
2860 const char *address = iface_list_n_ip(ifaces, i);
2861 status = add_socket_rpc_tcp_iface(dce_ctx, e, event_ctx, model_ops, address);
2862 NT_STATUS_NOT_OK_RETURN(status);
2864 } else {
2865 char **wcard;
2866 int i;
2867 int num_binds = 0;
2868 wcard = iface_list_wildcard(dce_ctx);
2869 NT_STATUS_HAVE_NO_MEMORY(wcard);
2870 for (i=0; wcard[i]; i++) {
2871 status = add_socket_rpc_tcp_iface(dce_ctx, e, event_ctx, model_ops, wcard[i]);
2872 if (NT_STATUS_IS_OK(status)) {
2873 num_binds++;
2876 talloc_free(wcard);
2877 if (num_binds == 0) {
2878 return NT_STATUS_INVALID_PARAMETER_MIX;
2882 return NT_STATUS_OK;
2885 NTSTATUS dcesrv_add_ep(struct dcesrv_context *dce_ctx,
2886 struct loadparm_context *lp_ctx,
2887 struct dcesrv_endpoint *e,
2888 struct tevent_context *event_ctx,
2889 const struct model_ops *model_ops)
2891 enum dcerpc_transport_t transport =
2892 dcerpc_binding_get_transport(e->ep_description);
2894 switch (transport) {
2895 case NCACN_UNIX_STREAM:
2896 return dcesrv_add_ep_unix(dce_ctx, lp_ctx, e, event_ctx, model_ops);
2898 case NCALRPC:
2899 return dcesrv_add_ep_ncalrpc(dce_ctx, lp_ctx, e, event_ctx, model_ops);
2901 case NCACN_IP_TCP:
2902 return dcesrv_add_ep_tcp(dce_ctx, lp_ctx, e, event_ctx, model_ops);
2904 case NCACN_NP:
2905 return dcesrv_add_ep_np(dce_ctx, lp_ctx, e, event_ctx, model_ops);
2907 default:
2908 return NT_STATUS_NOT_SUPPORTED;
2914 * retrieve credentials from a dce_call
2916 _PUBLIC_ struct cli_credentials *dcesrv_call_credentials(struct dcesrv_call_state *dce_call)
2918 return dce_call->conn->auth_state.session_info->credentials;
2922 * returns true if this is an authenticated call
2924 _PUBLIC_ bool dcesrv_call_authenticated(struct dcesrv_call_state *dce_call)
2926 enum security_user_level level;
2927 level = security_session_user_level(dce_call->conn->auth_state.session_info, NULL);
2928 return level >= SECURITY_USER;
2932 * retrieve account_name for a dce_call
2934 _PUBLIC_ const char *dcesrv_call_account_name(struct dcesrv_call_state *dce_call)
2936 return dce_call->context->conn->auth_state.session_info->info->account_name;