s3:torture:delete: remove an else, reducing indentation
[Samba/gebeck_regimport.git] / source4 / rpc_server / dcerpc_server.c
blob389cbe36660b5afd76e5fcdb21d0535c30acaaa4
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"
44 /* this is only used when the client asks for an unknown interface */
45 #define DUMMY_ASSOC_GROUP 0x0FFFFFFF
47 extern const struct dcesrv_interface dcesrv_mgmt_interface;
51 find an association group given a assoc_group_id
53 static struct dcesrv_assoc_group *dcesrv_assoc_group_find(struct dcesrv_context *dce_ctx,
54 uint32_t id)
56 void *id_ptr;
58 id_ptr = idr_find(dce_ctx->assoc_groups_idr, id);
59 if (id_ptr == NULL) {
60 return NULL;
62 return talloc_get_type_abort(id_ptr, struct dcesrv_assoc_group);
66 take a reference to an existing association group
68 static struct dcesrv_assoc_group *dcesrv_assoc_group_reference(TALLOC_CTX *mem_ctx,
69 struct dcesrv_context *dce_ctx,
70 uint32_t id)
72 struct dcesrv_assoc_group *assoc_group;
74 assoc_group = dcesrv_assoc_group_find(dce_ctx, id);
75 if (assoc_group == NULL) {
76 DEBUG(0,(__location__ ": Failed to find assoc_group 0x%08x\n", id));
77 return NULL;
79 return talloc_reference(mem_ctx, assoc_group);
82 static int dcesrv_assoc_group_destructor(struct dcesrv_assoc_group *assoc_group)
84 int ret;
85 ret = idr_remove(assoc_group->dce_ctx->assoc_groups_idr, assoc_group->id);
86 if (ret != 0) {
87 DEBUG(0,(__location__ ": Failed to remove assoc_group 0x%08x\n",
88 assoc_group->id));
90 return 0;
94 allocate a new association group
96 static struct dcesrv_assoc_group *dcesrv_assoc_group_new(TALLOC_CTX *mem_ctx,
97 struct dcesrv_context *dce_ctx)
99 struct dcesrv_assoc_group *assoc_group;
100 int id;
102 assoc_group = talloc_zero(mem_ctx, struct dcesrv_assoc_group);
103 if (assoc_group == NULL) {
104 return NULL;
107 id = idr_get_new_random(dce_ctx->assoc_groups_idr, assoc_group, UINT16_MAX);
108 if (id == -1) {
109 talloc_free(assoc_group);
110 DEBUG(0,(__location__ ": Out of association groups!\n"));
111 return NULL;
114 assoc_group->id = id;
115 assoc_group->dce_ctx = dce_ctx;
117 talloc_set_destructor(assoc_group, dcesrv_assoc_group_destructor);
119 return assoc_group;
124 see if two endpoints match
126 static bool endpoints_match(const struct dcerpc_binding *ep1,
127 const struct dcerpc_binding *ep2)
129 if (ep1->transport != ep2->transport) {
130 return false;
133 if (!ep1->endpoint || !ep2->endpoint) {
134 return ep1->endpoint == ep2->endpoint;
137 if (strcasecmp(ep1->endpoint, ep2->endpoint) != 0)
138 return false;
140 return true;
144 find an endpoint in the dcesrv_context
146 static struct dcesrv_endpoint *find_endpoint(struct dcesrv_context *dce_ctx,
147 const struct dcerpc_binding *ep_description)
149 struct dcesrv_endpoint *ep;
150 for (ep=dce_ctx->endpoint_list; ep; ep=ep->next) {
151 if (endpoints_match(ep->ep_description, ep_description)) {
152 return ep;
155 return NULL;
159 find a registered context_id from a bind or alter_context
161 static struct dcesrv_connection_context *dcesrv_find_context(struct dcesrv_connection *conn,
162 uint32_t context_id)
164 struct dcesrv_connection_context *c;
165 for (c=conn->contexts;c;c=c->next) {
166 if (c->context_id == context_id) return c;
168 return NULL;
172 see if a uuid and if_version match to an interface
174 static bool interface_match(const struct dcesrv_interface *if1,
175 const struct dcesrv_interface *if2)
177 return (if1->syntax_id.if_version == if2->syntax_id.if_version &&
178 GUID_equal(&if1->syntax_id.uuid, &if2->syntax_id.uuid));
182 find the interface operations on an endpoint
184 static const struct dcesrv_interface *find_interface(const struct dcesrv_endpoint *endpoint,
185 const struct dcesrv_interface *iface)
187 struct dcesrv_if_list *ifl;
188 for (ifl=endpoint->interface_list; ifl; ifl=ifl->next) {
189 if (interface_match(&(ifl->iface), iface)) {
190 return &(ifl->iface);
193 return NULL;
197 see if a uuid and if_version match to an interface
199 static bool interface_match_by_uuid(const struct dcesrv_interface *iface,
200 const struct GUID *uuid, uint32_t if_version)
202 return (iface->syntax_id.if_version == if_version &&
203 GUID_equal(&iface->syntax_id.uuid, uuid));
207 find the interface operations on an endpoint by uuid
209 static const struct dcesrv_interface *find_interface_by_uuid(const struct dcesrv_endpoint *endpoint,
210 const struct GUID *uuid, uint32_t if_version)
212 struct dcesrv_if_list *ifl;
213 for (ifl=endpoint->interface_list; ifl; ifl=ifl->next) {
214 if (interface_match_by_uuid(&(ifl->iface), uuid, if_version)) {
215 return &(ifl->iface);
218 return NULL;
222 find the earlier parts of a fragmented call awaiting reassembily
224 static struct dcesrv_call_state *dcesrv_find_fragmented_call(struct dcesrv_connection *dce_conn, uint16_t call_id)
226 struct dcesrv_call_state *c;
227 for (c=dce_conn->incoming_fragmented_call_list;c;c=c->next) {
228 if (c->pkt.call_id == call_id) {
229 return c;
232 return NULL;
236 register an interface on an endpoint
238 _PUBLIC_ NTSTATUS dcesrv_interface_register(struct dcesrv_context *dce_ctx,
239 const char *ep_name,
240 const struct dcesrv_interface *iface,
241 const struct security_descriptor *sd)
243 struct dcesrv_endpoint *ep;
244 struct dcesrv_if_list *ifl;
245 struct dcerpc_binding *binding;
246 bool add_ep = false;
247 NTSTATUS status;
249 status = dcerpc_parse_binding(dce_ctx, ep_name, &binding);
251 if (NT_STATUS_IS_ERR(status)) {
252 DEBUG(0, ("Trouble parsing binding string '%s'\n", ep_name));
253 return status;
256 /* check if this endpoint exists
258 if ((ep=find_endpoint(dce_ctx, binding))==NULL) {
259 ep = talloc(dce_ctx, struct dcesrv_endpoint);
260 if (!ep) {
261 return NT_STATUS_NO_MEMORY;
263 ZERO_STRUCTP(ep);
264 ep->ep_description = talloc_reference(ep, binding);
265 add_ep = true;
267 /* add mgmt interface */
268 ifl = talloc(dce_ctx, struct dcesrv_if_list);
269 if (!ifl) {
270 return NT_STATUS_NO_MEMORY;
273 memcpy(&(ifl->iface), &dcesrv_mgmt_interface,
274 sizeof(struct dcesrv_interface));
276 DLIST_ADD(ep->interface_list, ifl);
279 /* see if the interface is already registered on te endpoint */
280 if (find_interface(ep, iface)!=NULL) {
281 DEBUG(0,("dcesrv_interface_register: interface '%s' already registered on endpoint '%s'\n",
282 iface->name, ep_name));
283 return NT_STATUS_OBJECT_NAME_COLLISION;
286 /* talloc a new interface list element */
287 ifl = talloc(dce_ctx, struct dcesrv_if_list);
288 if (!ifl) {
289 return NT_STATUS_NO_MEMORY;
292 /* copy the given interface struct to the one on the endpoints interface list */
293 memcpy(&(ifl->iface),iface, sizeof(struct dcesrv_interface));
295 /* if we have a security descriptor given,
296 * we should see if we can set it up on the endpoint
298 if (sd != NULL) {
299 /* if there's currently no security descriptor given on the endpoint
300 * we try to set it
302 if (ep->sd == NULL) {
303 ep->sd = security_descriptor_copy(dce_ctx, sd);
306 /* if now there's no security descriptor given on the endpoint
307 * something goes wrong, either we failed to copy the security descriptor
308 * or there was already one on the endpoint
310 if (ep->sd != NULL) {
311 DEBUG(0,("dcesrv_interface_register: interface '%s' failed to setup a security descriptor\n"
312 " on endpoint '%s'\n",
313 iface->name, ep_name));
314 if (add_ep) free(ep);
315 free(ifl);
316 return NT_STATUS_OBJECT_NAME_COLLISION;
320 /* finally add the interface on the endpoint */
321 DLIST_ADD(ep->interface_list, ifl);
323 /* if it's a new endpoint add it to the dcesrv_context */
324 if (add_ep) {
325 DLIST_ADD(dce_ctx->endpoint_list, ep);
328 DEBUG(4,("dcesrv_interface_register: interface '%s' registered on endpoint '%s'\n",
329 iface->name, ep_name));
331 return NT_STATUS_OK;
334 NTSTATUS dcesrv_inherited_session_key(struct dcesrv_connection *p,
335 DATA_BLOB *session_key)
337 if (p->auth_state.session_info->session_key.length) {
338 *session_key = p->auth_state.session_info->session_key;
339 return NT_STATUS_OK;
341 return NT_STATUS_NO_USER_SESSION_KEY;
345 fetch the user session key - may be default (above) or the SMB session key
347 The key is always truncated to 16 bytes
349 _PUBLIC_ NTSTATUS dcesrv_fetch_session_key(struct dcesrv_connection *p,
350 DATA_BLOB *session_key)
352 NTSTATUS status = p->auth_state.session_key(p, session_key);
353 if (!NT_STATUS_IS_OK(status)) {
354 return status;
357 session_key->length = MIN(session_key->length, 16);
359 return NT_STATUS_OK;
363 connect to a dcerpc endpoint
365 _PUBLIC_ NTSTATUS dcesrv_endpoint_connect(struct dcesrv_context *dce_ctx,
366 TALLOC_CTX *mem_ctx,
367 const struct dcesrv_endpoint *ep,
368 struct auth_session_info *session_info,
369 struct tevent_context *event_ctx,
370 struct imessaging_context *msg_ctx,
371 struct server_id server_id,
372 uint32_t state_flags,
373 struct dcesrv_connection **_p)
375 struct dcesrv_connection *p;
377 if (!session_info) {
378 return NT_STATUS_ACCESS_DENIED;
381 p = talloc(mem_ctx, struct dcesrv_connection);
382 NT_STATUS_HAVE_NO_MEMORY(p);
384 if (!talloc_reference(p, session_info)) {
385 talloc_free(p);
386 return NT_STATUS_NO_MEMORY;
389 p->dce_ctx = dce_ctx;
390 p->endpoint = ep;
391 p->contexts = NULL;
392 p->call_list = NULL;
393 p->packet_log_dir = lpcfg_lockdir(dce_ctx->lp_ctx);
394 p->incoming_fragmented_call_list = NULL;
395 p->pending_call_list = NULL;
396 p->cli_max_recv_frag = 0;
397 p->partial_input = data_blob(NULL, 0);
398 p->auth_state.auth_info = NULL;
399 p->auth_state.gensec_security = NULL;
400 p->auth_state.session_info = session_info;
401 p->auth_state.session_key = dcesrv_generic_session_key;
402 p->event_ctx = event_ctx;
403 p->msg_ctx = msg_ctx;
404 p->server_id = server_id;
405 p->processing = false;
406 p->state_flags = state_flags;
407 ZERO_STRUCT(p->transport);
409 *_p = p;
410 return NT_STATUS_OK;
414 move a call from an existing linked list to the specified list. This
415 prevents bugs where we forget to remove the call from a previous
416 list when moving it.
418 static void dcesrv_call_set_list(struct dcesrv_call_state *call,
419 enum dcesrv_call_list list)
421 switch (call->list) {
422 case DCESRV_LIST_NONE:
423 break;
424 case DCESRV_LIST_CALL_LIST:
425 DLIST_REMOVE(call->conn->call_list, call);
426 break;
427 case DCESRV_LIST_FRAGMENTED_CALL_LIST:
428 DLIST_REMOVE(call->conn->incoming_fragmented_call_list, call);
429 break;
430 case DCESRV_LIST_PENDING_CALL_LIST:
431 DLIST_REMOVE(call->conn->pending_call_list, call);
432 break;
434 call->list = list;
435 switch (list) {
436 case DCESRV_LIST_NONE:
437 break;
438 case DCESRV_LIST_CALL_LIST:
439 DLIST_ADD_END(call->conn->call_list, call, struct dcesrv_call_state *);
440 break;
441 case DCESRV_LIST_FRAGMENTED_CALL_LIST:
442 DLIST_ADD_END(call->conn->incoming_fragmented_call_list, call, struct dcesrv_call_state *);
443 break;
444 case DCESRV_LIST_PENDING_CALL_LIST:
445 DLIST_ADD_END(call->conn->pending_call_list, call, struct dcesrv_call_state *);
446 break;
452 return a dcerpc bind_nak
454 static NTSTATUS dcesrv_bind_nak(struct dcesrv_call_state *call, uint32_t reason)
456 struct ncacn_packet pkt;
457 struct data_blob_list_item *rep;
458 NTSTATUS status;
460 /* setup a bind_nak */
461 dcesrv_init_hdr(&pkt, lpcfg_rpc_big_endian(call->conn->dce_ctx->lp_ctx));
462 pkt.auth_length = 0;
463 pkt.call_id = call->pkt.call_id;
464 pkt.ptype = DCERPC_PKT_BIND_NAK;
465 pkt.pfc_flags = DCERPC_PFC_FLAG_FIRST | DCERPC_PFC_FLAG_LAST;
466 pkt.u.bind_nak.reject_reason = reason;
467 if (pkt.u.bind_nak.reject_reason == DECRPC_BIND_PROTOCOL_VERSION_NOT_SUPPORTED) {
468 pkt.u.bind_nak.versions.v.num_versions = 0;
471 rep = talloc(call, struct data_blob_list_item);
472 if (!rep) {
473 return NT_STATUS_NO_MEMORY;
476 status = ncacn_push_auth(&rep->blob, call, &pkt, NULL);
477 if (!NT_STATUS_IS_OK(status)) {
478 return status;
481 dcerpc_set_frag_length(&rep->blob, rep->blob.length);
483 DLIST_ADD_END(call->replies, rep, struct data_blob_list_item *);
484 dcesrv_call_set_list(call, DCESRV_LIST_CALL_LIST);
486 if (call->conn->call_list && call->conn->call_list->replies) {
487 if (call->conn->transport.report_output_data) {
488 call->conn->transport.report_output_data(call->conn);
492 return NT_STATUS_OK;
495 static int dcesrv_connection_context_destructor(struct dcesrv_connection_context *c)
497 DLIST_REMOVE(c->conn->contexts, c);
499 if (c->iface && c->iface->unbind) {
500 c->iface->unbind(c, c->iface);
503 return 0;
507 handle a bind request
509 static NTSTATUS dcesrv_bind(struct dcesrv_call_state *call)
511 uint32_t if_version, transfer_syntax_version;
512 struct GUID uuid, *transfer_syntax_uuid;
513 struct ncacn_packet pkt;
514 struct data_blob_list_item *rep;
515 NTSTATUS status;
516 uint32_t result=0, reason=0;
517 uint32_t context_id;
518 const struct dcesrv_interface *iface;
519 uint32_t extra_flags = 0;
522 if provided, check the assoc_group is valid
524 if (call->pkt.u.bind.assoc_group_id != 0 &&
525 lpcfg_parm_bool(call->conn->dce_ctx->lp_ctx, NULL, "dcesrv","assoc group checking", true) &&
526 dcesrv_assoc_group_find(call->conn->dce_ctx, call->pkt.u.bind.assoc_group_id) == NULL) {
527 return dcesrv_bind_nak(call, 0);
530 if (call->pkt.u.bind.num_contexts < 1 ||
531 call->pkt.u.bind.ctx_list[0].num_transfer_syntaxes < 1) {
532 return dcesrv_bind_nak(call, 0);
535 context_id = call->pkt.u.bind.ctx_list[0].context_id;
537 /* you can't bind twice on one context */
538 if (dcesrv_find_context(call->conn, context_id) != NULL) {
539 return dcesrv_bind_nak(call, 0);
542 if_version = call->pkt.u.bind.ctx_list[0].abstract_syntax.if_version;
543 uuid = call->pkt.u.bind.ctx_list[0].abstract_syntax.uuid;
545 transfer_syntax_version = call->pkt.u.bind.ctx_list[0].transfer_syntaxes[0].if_version;
546 transfer_syntax_uuid = &call->pkt.u.bind.ctx_list[0].transfer_syntaxes[0].uuid;
547 if (!GUID_equal(&ndr_transfer_syntax_ndr.uuid, transfer_syntax_uuid) != 0 ||
548 ndr_transfer_syntax_ndr.if_version != transfer_syntax_version) {
549 char *uuid_str = GUID_string(call, transfer_syntax_uuid);
550 /* we only do NDR encoded dcerpc */
551 DEBUG(0,("Non NDR transfer syntax requested - %s\n", uuid_str));
552 talloc_free(uuid_str);
553 return dcesrv_bind_nak(call, 0);
556 iface = find_interface_by_uuid(call->conn->endpoint, &uuid, if_version);
557 if (iface == NULL) {
558 char *uuid_str = GUID_string(call, &uuid);
559 DEBUG(2,("Request for unknown dcerpc interface %s/%d\n", uuid_str, if_version));
560 talloc_free(uuid_str);
562 /* we don't know about that interface */
563 result = DCERPC_BIND_PROVIDER_REJECT;
564 reason = DCERPC_BIND_REASON_ASYNTAX;
567 if (iface) {
568 /* add this context to the list of available context_ids */
569 struct dcesrv_connection_context *context = talloc(call->conn,
570 struct dcesrv_connection_context);
571 if (context == NULL) {
572 return dcesrv_bind_nak(call, 0);
574 context->conn = call->conn;
575 context->iface = iface;
576 context->context_id = context_id;
577 if (call->pkt.u.bind.assoc_group_id != 0) {
578 context->assoc_group = dcesrv_assoc_group_reference(context,
579 call->conn->dce_ctx,
580 call->pkt.u.bind.assoc_group_id);
581 } else {
582 context->assoc_group = dcesrv_assoc_group_new(context, call->conn->dce_ctx);
584 if (context->assoc_group == NULL) {
585 talloc_free(context);
586 return dcesrv_bind_nak(call, 0);
588 context->private_data = NULL;
589 DLIST_ADD(call->conn->contexts, context);
590 call->context = context;
591 talloc_set_destructor(context, dcesrv_connection_context_destructor);
593 status = iface->bind(call, iface, if_version);
594 if (!NT_STATUS_IS_OK(status)) {
595 char *uuid_str = GUID_string(call, &uuid);
596 DEBUG(2,("Request for dcerpc interface %s/%d rejected: %s\n",
597 uuid_str, if_version, nt_errstr(status)));
598 talloc_free(uuid_str);
599 /* we don't want to trigger the iface->unbind() hook */
600 context->iface = NULL;
601 talloc_free(call->context);
602 call->context = NULL;
603 return dcesrv_bind_nak(call, 0);
607 if (call->conn->cli_max_recv_frag == 0) {
608 call->conn->cli_max_recv_frag = MIN(0x2000, call->pkt.u.bind.max_recv_frag);
611 if ((call->pkt.pfc_flags & DCERPC_PFC_FLAG_SUPPORT_HEADER_SIGN) &&
612 lpcfg_parm_bool(call->conn->dce_ctx->lp_ctx, NULL, "dcesrv","header signing", false)) {
613 call->conn->state_flags |= DCESRV_CALL_STATE_FLAG_HEADER_SIGNING;
614 extra_flags |= DCERPC_PFC_FLAG_SUPPORT_HEADER_SIGN;
617 /* handle any authentication that is being requested */
618 if (!dcesrv_auth_bind(call)) {
619 talloc_free(call->context);
620 call->context = NULL;
621 return dcesrv_bind_nak(call, DCERPC_BIND_REASON_INVALID_AUTH_TYPE);
624 /* setup a bind_ack */
625 dcesrv_init_hdr(&pkt, lpcfg_rpc_big_endian(call->conn->dce_ctx->lp_ctx));
626 pkt.auth_length = 0;
627 pkt.call_id = call->pkt.call_id;
628 pkt.ptype = DCERPC_PKT_BIND_ACK;
629 pkt.pfc_flags = DCERPC_PFC_FLAG_FIRST | DCERPC_PFC_FLAG_LAST | extra_flags;
630 pkt.u.bind_ack.max_xmit_frag = call->conn->cli_max_recv_frag;
631 pkt.u.bind_ack.max_recv_frag = 0x2000;
634 make it possible for iface->bind() to specify the assoc_group_id
635 This helps the openchange mapiproxy plugin to work correctly.
637 metze
639 if (call->context) {
640 pkt.u.bind_ack.assoc_group_id = call->context->assoc_group->id;
641 } else {
642 pkt.u.bind_ack.assoc_group_id = DUMMY_ASSOC_GROUP;
645 if (iface) {
646 /* FIXME: Use pipe name as specified by endpoint instead of interface name */
647 pkt.u.bind_ack.secondary_address = talloc_asprintf(call, "\\PIPE\\%s", iface->name);
648 } else {
649 pkt.u.bind_ack.secondary_address = "";
651 pkt.u.bind_ack.num_results = 1;
652 pkt.u.bind_ack.ctx_list = talloc(call, struct dcerpc_ack_ctx);
653 if (!pkt.u.bind_ack.ctx_list) {
654 talloc_free(call->context);
655 call->context = NULL;
656 return NT_STATUS_NO_MEMORY;
658 pkt.u.bind_ack.ctx_list[0].result = result;
659 pkt.u.bind_ack.ctx_list[0].reason = reason;
660 pkt.u.bind_ack.ctx_list[0].syntax = ndr_transfer_syntax_ndr;
661 pkt.u.bind_ack.auth_info = data_blob(NULL, 0);
663 status = dcesrv_auth_bind_ack(call, &pkt);
664 if (!NT_STATUS_IS_OK(status)) {
665 talloc_free(call->context);
666 call->context = NULL;
667 return dcesrv_bind_nak(call, 0);
670 rep = talloc(call, struct data_blob_list_item);
671 if (!rep) {
672 talloc_free(call->context);
673 call->context = NULL;
674 return NT_STATUS_NO_MEMORY;
677 status = ncacn_push_auth(&rep->blob, call, &pkt,
678 call->conn->auth_state.auth_info);
679 if (!NT_STATUS_IS_OK(status)) {
680 talloc_free(call->context);
681 call->context = NULL;
682 return status;
685 dcerpc_set_frag_length(&rep->blob, rep->blob.length);
687 DLIST_ADD_END(call->replies, rep, struct data_blob_list_item *);
688 dcesrv_call_set_list(call, DCESRV_LIST_CALL_LIST);
690 if (call->conn->call_list && call->conn->call_list->replies) {
691 if (call->conn->transport.report_output_data) {
692 call->conn->transport.report_output_data(call->conn);
696 return NT_STATUS_OK;
701 handle a auth3 request
703 static NTSTATUS dcesrv_auth3(struct dcesrv_call_state *call)
705 /* handle the auth3 in the auth code */
706 if (!dcesrv_auth_auth3(call)) {
707 return dcesrv_fault(call, DCERPC_FAULT_OTHER);
710 talloc_free(call);
712 /* we don't send a reply to a auth3 request, except by a
713 fault */
714 return NT_STATUS_OK;
719 handle a bind request
721 static NTSTATUS dcesrv_alter_new_context(struct dcesrv_call_state *call, uint32_t context_id)
723 uint32_t if_version, transfer_syntax_version;
724 struct dcesrv_connection_context *context;
725 const struct dcesrv_interface *iface;
726 struct GUID uuid, *transfer_syntax_uuid;
727 NTSTATUS status;
729 if_version = call->pkt.u.alter.ctx_list[0].abstract_syntax.if_version;
730 uuid = call->pkt.u.alter.ctx_list[0].abstract_syntax.uuid;
732 transfer_syntax_version = call->pkt.u.alter.ctx_list[0].transfer_syntaxes[0].if_version;
733 transfer_syntax_uuid = &call->pkt.u.alter.ctx_list[0].transfer_syntaxes[0].uuid;
734 if (!GUID_equal(transfer_syntax_uuid, &ndr_transfer_syntax_ndr.uuid) ||
735 ndr_transfer_syntax_ndr.if_version != transfer_syntax_version) {
736 /* we only do NDR encoded dcerpc */
737 return NT_STATUS_RPC_PROTSEQ_NOT_SUPPORTED;
740 iface = find_interface_by_uuid(call->conn->endpoint, &uuid, if_version);
741 if (iface == NULL) {
742 char *uuid_str = GUID_string(call, &uuid);
743 DEBUG(2,("Request for unknown dcerpc interface %s/%d\n", uuid_str, if_version));
744 talloc_free(uuid_str);
745 return NT_STATUS_RPC_PROTSEQ_NOT_SUPPORTED;
748 /* add this context to the list of available context_ids */
749 context = talloc(call->conn, struct dcesrv_connection_context);
750 if (context == NULL) {
751 return NT_STATUS_NO_MEMORY;
753 context->conn = call->conn;
754 context->iface = iface;
755 context->context_id = context_id;
756 if (call->pkt.u.alter.assoc_group_id != 0) {
757 context->assoc_group = dcesrv_assoc_group_reference(context,
758 call->conn->dce_ctx,
759 call->pkt.u.alter.assoc_group_id);
760 } else {
761 context->assoc_group = dcesrv_assoc_group_new(context, call->conn->dce_ctx);
763 if (context->assoc_group == NULL) {
764 talloc_free(context);
765 call->context = NULL;
766 return NT_STATUS_NO_MEMORY;
768 context->private_data = NULL;
769 DLIST_ADD(call->conn->contexts, context);
770 call->context = context;
771 talloc_set_destructor(context, dcesrv_connection_context_destructor);
773 status = iface->bind(call, iface, if_version);
774 if (!NT_STATUS_IS_OK(status)) {
775 /* we don't want to trigger the iface->unbind() hook */
776 context->iface = NULL;
777 talloc_free(context);
778 call->context = NULL;
779 return status;
782 return NT_STATUS_OK;
787 handle a alter context request
789 static NTSTATUS dcesrv_alter(struct dcesrv_call_state *call)
791 struct ncacn_packet pkt;
792 struct data_blob_list_item *rep;
793 NTSTATUS status;
794 uint32_t result=0, reason=0;
795 uint32_t context_id;
797 /* handle any authentication that is being requested */
798 if (!dcesrv_auth_alter(call)) {
799 /* TODO: work out the right reject code */
800 result = DCERPC_BIND_PROVIDER_REJECT;
801 reason = DCERPC_BIND_REASON_ASYNTAX;
804 context_id = call->pkt.u.alter.ctx_list[0].context_id;
806 /* see if they are asking for a new interface */
807 if (result == 0) {
808 call->context = dcesrv_find_context(call->conn, context_id);
809 if (!call->context) {
810 status = dcesrv_alter_new_context(call, context_id);
811 if (!NT_STATUS_IS_OK(status)) {
812 result = DCERPC_BIND_PROVIDER_REJECT;
813 reason = DCERPC_BIND_REASON_ASYNTAX;
818 if (result == 0 &&
819 call->pkt.u.alter.assoc_group_id != 0 &&
820 lpcfg_parm_bool(call->conn->dce_ctx->lp_ctx, NULL, "dcesrv","assoc group checking", true) &&
821 call->pkt.u.alter.assoc_group_id != call->context->assoc_group->id) {
822 DEBUG(0,(__location__ ": Failed attempt to use new assoc_group in alter context (0x%08x 0x%08x)\n",
823 call->context->assoc_group->id, call->pkt.u.alter.assoc_group_id));
824 /* TODO: can they ask for a new association group? */
825 result = DCERPC_BIND_PROVIDER_REJECT;
826 reason = DCERPC_BIND_REASON_ASYNTAX;
829 /* setup a alter_resp */
830 dcesrv_init_hdr(&pkt, lpcfg_rpc_big_endian(call->conn->dce_ctx->lp_ctx));
831 pkt.auth_length = 0;
832 pkt.call_id = call->pkt.call_id;
833 pkt.ptype = DCERPC_PKT_ALTER_RESP;
834 pkt.pfc_flags = DCERPC_PFC_FLAG_FIRST | DCERPC_PFC_FLAG_LAST;
835 pkt.u.alter_resp.max_xmit_frag = 0x2000;
836 pkt.u.alter_resp.max_recv_frag = 0x2000;
837 if (result == 0) {
838 pkt.u.alter_resp.assoc_group_id = call->context->assoc_group->id;
839 } else {
840 pkt.u.alter_resp.assoc_group_id = 0;
842 pkt.u.alter_resp.num_results = 1;
843 pkt.u.alter_resp.ctx_list = talloc_array(call, struct dcerpc_ack_ctx, 1);
844 if (!pkt.u.alter_resp.ctx_list) {
845 return NT_STATUS_NO_MEMORY;
847 pkt.u.alter_resp.ctx_list[0].result = result;
848 pkt.u.alter_resp.ctx_list[0].reason = reason;
849 pkt.u.alter_resp.ctx_list[0].syntax = ndr_transfer_syntax_ndr;
850 pkt.u.alter_resp.auth_info = data_blob(NULL, 0);
851 pkt.u.alter_resp.secondary_address = "";
853 status = dcesrv_auth_alter_ack(call, &pkt);
854 if (!NT_STATUS_IS_OK(status)) {
855 if (NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)
856 || NT_STATUS_EQUAL(status, NT_STATUS_LOGON_FAILURE)
857 || NT_STATUS_EQUAL(status, NT_STATUS_NO_SUCH_USER)
858 || NT_STATUS_EQUAL(status, NT_STATUS_WRONG_PASSWORD)) {
859 return dcesrv_fault(call, DCERPC_FAULT_ACCESS_DENIED);
861 return dcesrv_fault(call, 0);
864 rep = talloc(call, struct data_blob_list_item);
865 if (!rep) {
866 return NT_STATUS_NO_MEMORY;
869 status = ncacn_push_auth(&rep->blob, call, &pkt, call->conn->auth_state.auth_info);
870 if (!NT_STATUS_IS_OK(status)) {
871 return status;
874 dcerpc_set_frag_length(&rep->blob, rep->blob.length);
876 DLIST_ADD_END(call->replies, rep, struct data_blob_list_item *);
877 dcesrv_call_set_list(call, DCESRV_LIST_CALL_LIST);
879 if (call->conn->call_list && call->conn->call_list->replies) {
880 if (call->conn->transport.report_output_data) {
881 call->conn->transport.report_output_data(call->conn);
885 return NT_STATUS_OK;
889 possibly save the call for inspection with ndrdump
891 static void dcesrv_save_call(struct dcesrv_call_state *call, const char *why)
893 #ifdef DEVELOPER
894 char *fname;
895 const char *dump_dir;
896 dump_dir = lpcfg_parm_string(call->conn->dce_ctx->lp_ctx, NULL, "dcesrv", "stubs directory");
897 if (!dump_dir) {
898 return;
900 fname = talloc_asprintf(call, "%s/RPC-%s-%u-%s.dat",
901 dump_dir,
902 call->context->iface->name,
903 call->pkt.u.request.opnum,
904 why);
905 if (file_save(fname, call->pkt.u.request.stub_and_verifier.data, call->pkt.u.request.stub_and_verifier.length)) {
906 DEBUG(0,("RPC SAVED %s\n", fname));
908 talloc_free(fname);
909 #endif
913 handle a dcerpc request packet
915 static NTSTATUS dcesrv_request(struct dcesrv_call_state *call)
917 struct ndr_pull *pull;
918 NTSTATUS status;
919 struct dcesrv_connection_context *context;
921 /* if authenticated, and the mech we use can't do async replies, don't use them... */
922 if (call->conn->auth_state.gensec_security &&
923 !gensec_have_feature(call->conn->auth_state.gensec_security, GENSEC_FEATURE_ASYNC_REPLIES)) {
924 call->state_flags &= ~DCESRV_CALL_STATE_FLAG_MAY_ASYNC;
927 context = dcesrv_find_context(call->conn, call->pkt.u.request.context_id);
928 if (context == NULL) {
929 return dcesrv_fault(call, DCERPC_FAULT_UNK_IF);
932 pull = ndr_pull_init_blob(&call->pkt.u.request.stub_and_verifier, call);
933 NT_STATUS_HAVE_NO_MEMORY(pull);
935 pull->flags |= LIBNDR_FLAG_REF_ALLOC;
937 call->context = context;
938 call->ndr_pull = pull;
940 if (!(call->pkt.drep[0] & DCERPC_DREP_LE)) {
941 pull->flags |= LIBNDR_FLAG_BIGENDIAN;
944 /* unravel the NDR for the packet */
945 status = context->iface->ndr_pull(call, call, pull, &call->r);
946 if (!NT_STATUS_IS_OK(status)) {
947 if (call->fault_code == DCERPC_FAULT_OP_RNG_ERROR) {
948 /* we got an unknown call */
949 DEBUG(3,(__location__ ": Unknown RPC call %u on %s\n",
950 call->pkt.u.request.opnum, context->iface->name));
951 dcesrv_save_call(call, "unknown");
952 } else {
953 dcesrv_save_call(call, "pullfail");
955 return dcesrv_fault(call, call->fault_code);
958 if (pull->offset != pull->data_size) {
959 dcesrv_save_call(call, "extrabytes");
960 DEBUG(3,("Warning: %d extra bytes in incoming RPC request\n",
961 pull->data_size - pull->offset));
964 /* call the dispatch function */
965 status = context->iface->dispatch(call, call, call->r);
966 if (!NT_STATUS_IS_OK(status)) {
967 DEBUG(5,("dcerpc fault in call %s:%02x - %s\n",
968 context->iface->name,
969 call->pkt.u.request.opnum,
970 dcerpc_errstr(pull, call->fault_code)));
971 return dcesrv_fault(call, call->fault_code);
974 /* add the call to the pending list */
975 dcesrv_call_set_list(call, DCESRV_LIST_PENDING_CALL_LIST);
977 if (call->state_flags & DCESRV_CALL_STATE_FLAG_ASYNC) {
978 return NT_STATUS_OK;
981 return dcesrv_reply(call);
986 remove the call from the right list when freed
988 static int dcesrv_call_dequeue(struct dcesrv_call_state *call)
990 dcesrv_call_set_list(call, DCESRV_LIST_NONE);
991 return 0;
994 _PUBLIC_ const struct tsocket_address *dcesrv_connection_get_local_address(struct dcesrv_connection *conn)
996 return conn->local_address;
999 _PUBLIC_ const struct tsocket_address *dcesrv_connection_get_remote_address(struct dcesrv_connection *conn)
1001 return conn->remote_address;
1005 process some input to a dcerpc endpoint server.
1007 NTSTATUS dcesrv_process_ncacn_packet(struct dcesrv_connection *dce_conn,
1008 struct ncacn_packet *pkt,
1009 DATA_BLOB blob)
1011 NTSTATUS status;
1012 struct dcesrv_call_state *call;
1014 call = talloc_zero(dce_conn, struct dcesrv_call_state);
1015 if (!call) {
1016 data_blob_free(&blob);
1017 talloc_free(pkt);
1018 return NT_STATUS_NO_MEMORY;
1020 call->conn = dce_conn;
1021 call->event_ctx = dce_conn->event_ctx;
1022 call->msg_ctx = dce_conn->msg_ctx;
1023 call->state_flags = call->conn->state_flags;
1024 call->time = timeval_current();
1025 call->list = DCESRV_LIST_NONE;
1027 talloc_steal(call, pkt);
1028 talloc_steal(call, blob.data);
1029 call->pkt = *pkt;
1031 talloc_set_destructor(call, dcesrv_call_dequeue);
1033 /* we have to check the signing here, before combining the
1034 pdus */
1035 if (call->pkt.ptype == DCERPC_PKT_REQUEST &&
1036 !dcesrv_auth_request(call, &blob)) {
1037 return dcesrv_fault(call, DCERPC_FAULT_ACCESS_DENIED);
1040 /* see if this is a continued packet */
1041 if (call->pkt.ptype == DCERPC_PKT_REQUEST &&
1042 !(call->pkt.pfc_flags & DCERPC_PFC_FLAG_FIRST)) {
1043 struct dcesrv_call_state *call2 = call;
1044 uint32_t alloc_size;
1046 /* we only allow fragmented requests, no other packet types */
1047 if (call->pkt.ptype != DCERPC_PKT_REQUEST) {
1048 return dcesrv_fault(call2, DCERPC_FAULT_OTHER);
1051 /* this is a continuation of an existing call - find the call
1052 then tack it on the end */
1053 call = dcesrv_find_fragmented_call(dce_conn, call2->pkt.call_id);
1054 if (!call) {
1055 return dcesrv_fault(call2, DCERPC_FAULT_OTHER);
1058 if (call->pkt.ptype != call2->pkt.ptype) {
1059 /* trying to play silly buggers are we? */
1060 return dcesrv_fault(call2, DCERPC_FAULT_OTHER);
1063 alloc_size = call->pkt.u.request.stub_and_verifier.length +
1064 call2->pkt.u.request.stub_and_verifier.length;
1065 if (call->pkt.u.request.alloc_hint > alloc_size) {
1066 alloc_size = call->pkt.u.request.alloc_hint;
1069 call->pkt.u.request.stub_and_verifier.data =
1070 talloc_realloc(call,
1071 call->pkt.u.request.stub_and_verifier.data,
1072 uint8_t, alloc_size);
1073 if (!call->pkt.u.request.stub_and_verifier.data) {
1074 return dcesrv_fault(call2, DCERPC_FAULT_OTHER);
1076 memcpy(call->pkt.u.request.stub_and_verifier.data +
1077 call->pkt.u.request.stub_and_verifier.length,
1078 call2->pkt.u.request.stub_and_verifier.data,
1079 call2->pkt.u.request.stub_and_verifier.length);
1080 call->pkt.u.request.stub_and_verifier.length +=
1081 call2->pkt.u.request.stub_and_verifier.length;
1083 call->pkt.pfc_flags |= (call2->pkt.pfc_flags & DCERPC_PFC_FLAG_LAST);
1085 talloc_free(call2);
1088 /* this may not be the last pdu in the chain - if its isn't then
1089 just put it on the incoming_fragmented_call_list and wait for the rest */
1090 if (call->pkt.ptype == DCERPC_PKT_REQUEST &&
1091 !(call->pkt.pfc_flags & DCERPC_PFC_FLAG_LAST)) {
1092 dcesrv_call_set_list(call, DCESRV_LIST_FRAGMENTED_CALL_LIST);
1093 return NT_STATUS_OK;
1096 /* This removes any fragments we may have had stashed away */
1097 dcesrv_call_set_list(call, DCESRV_LIST_NONE);
1099 switch (call->pkt.ptype) {
1100 case DCERPC_PKT_BIND:
1101 status = dcesrv_bind(call);
1102 break;
1103 case DCERPC_PKT_AUTH3:
1104 status = dcesrv_auth3(call);
1105 break;
1106 case DCERPC_PKT_ALTER:
1107 status = dcesrv_alter(call);
1108 break;
1109 case DCERPC_PKT_REQUEST:
1110 status = dcesrv_request(call);
1111 break;
1112 default:
1113 status = NT_STATUS_INVALID_PARAMETER;
1114 break;
1117 /* if we are going to be sending a reply then add
1118 it to the list of pending calls. We add it to the end to keep the call
1119 list in the order we will answer */
1120 if (!NT_STATUS_IS_OK(status)) {
1121 talloc_free(call);
1124 return status;
1127 _PUBLIC_ NTSTATUS dcesrv_init_context(TALLOC_CTX *mem_ctx,
1128 struct loadparm_context *lp_ctx,
1129 const char **endpoint_servers, struct dcesrv_context **_dce_ctx)
1131 NTSTATUS status;
1132 struct dcesrv_context *dce_ctx;
1133 int i;
1135 if (!endpoint_servers) {
1136 DEBUG(0,("dcesrv_init_context: no endpoint servers configured\n"));
1137 return NT_STATUS_INTERNAL_ERROR;
1140 dce_ctx = talloc(mem_ctx, struct dcesrv_context);
1141 NT_STATUS_HAVE_NO_MEMORY(dce_ctx);
1142 dce_ctx->endpoint_list = NULL;
1143 dce_ctx->lp_ctx = lp_ctx;
1144 dce_ctx->assoc_groups_idr = idr_init(dce_ctx);
1145 NT_STATUS_HAVE_NO_MEMORY(dce_ctx->assoc_groups_idr);
1147 for (i=0;endpoint_servers[i];i++) {
1148 const struct dcesrv_endpoint_server *ep_server;
1150 ep_server = dcesrv_ep_server_byname(endpoint_servers[i]);
1151 if (!ep_server) {
1152 DEBUG(0,("dcesrv_init_context: failed to find endpoint server = '%s'\n", endpoint_servers[i]));
1153 return NT_STATUS_INTERNAL_ERROR;
1156 status = ep_server->init_server(dce_ctx, ep_server);
1157 if (!NT_STATUS_IS_OK(status)) {
1158 DEBUG(0,("dcesrv_init_context: failed to init endpoint server = '%s': %s\n", endpoint_servers[i],
1159 nt_errstr(status)));
1160 return status;
1164 *_dce_ctx = dce_ctx;
1165 return NT_STATUS_OK;
1168 /* the list of currently registered DCERPC endpoint servers.
1170 static struct ep_server {
1171 struct dcesrv_endpoint_server *ep_server;
1172 } *ep_servers = NULL;
1173 static int num_ep_servers;
1176 register a DCERPC endpoint server.
1178 The 'name' can be later used by other backends to find the operations
1179 structure for this backend.
1181 The 'type' is used to specify whether this is for a disk, printer or IPC$ share
1183 _PUBLIC_ NTSTATUS dcerpc_register_ep_server(const void *_ep_server)
1185 const struct dcesrv_endpoint_server *ep_server = _ep_server;
1187 if (dcesrv_ep_server_byname(ep_server->name) != NULL) {
1188 /* its already registered! */
1189 DEBUG(0,("DCERPC endpoint server '%s' already registered\n",
1190 ep_server->name));
1191 return NT_STATUS_OBJECT_NAME_COLLISION;
1194 ep_servers = realloc_p(ep_servers, struct ep_server, num_ep_servers+1);
1195 if (!ep_servers) {
1196 smb_panic("out of memory in dcerpc_register");
1199 ep_servers[num_ep_servers].ep_server = smb_xmemdup(ep_server, sizeof(*ep_server));
1200 ep_servers[num_ep_servers].ep_server->name = smb_xstrdup(ep_server->name);
1202 num_ep_servers++;
1204 DEBUG(3,("DCERPC endpoint server '%s' registered\n",
1205 ep_server->name));
1207 return NT_STATUS_OK;
1211 return the operations structure for a named backend of the specified type
1213 const struct dcesrv_endpoint_server *dcesrv_ep_server_byname(const char *name)
1215 int i;
1217 for (i=0;i<num_ep_servers;i++) {
1218 if (strcmp(ep_servers[i].ep_server->name, name) == 0) {
1219 return ep_servers[i].ep_server;
1223 return NULL;
1226 void dcerpc_server_init(struct loadparm_context *lp_ctx)
1228 static bool initialized;
1229 #define _MODULE_PROTO(init) extern NTSTATUS init(void);
1230 STATIC_dcerpc_server_MODULES_PROTO;
1231 init_module_fn static_init[] = { STATIC_dcerpc_server_MODULES };
1232 init_module_fn *shared_init;
1234 if (initialized) {
1235 return;
1237 initialized = true;
1239 shared_init = load_samba_modules(NULL, "dcerpc_server");
1241 run_init_functions(static_init);
1242 run_init_functions(shared_init);
1244 talloc_free(shared_init);
1248 return the DCERPC module version, and the size of some critical types
1249 This can be used by endpoint server modules to either detect compilation errors, or provide
1250 multiple implementations for different smbd compilation options in one module
1252 const struct dcesrv_critical_sizes *dcerpc_module_version(void)
1254 static const struct dcesrv_critical_sizes critical_sizes = {
1255 DCERPC_MODULE_VERSION,
1256 sizeof(struct dcesrv_context),
1257 sizeof(struct dcesrv_endpoint),
1258 sizeof(struct dcesrv_endpoint_server),
1259 sizeof(struct dcesrv_interface),
1260 sizeof(struct dcesrv_if_list),
1261 sizeof(struct dcesrv_connection),
1262 sizeof(struct dcesrv_call_state),
1263 sizeof(struct dcesrv_auth),
1264 sizeof(struct dcesrv_handle)
1267 return &critical_sizes;
1270 static void dcesrv_terminate_connection(struct dcesrv_connection *dce_conn, const char *reason)
1272 struct stream_connection *srv_conn;
1273 srv_conn = talloc_get_type(dce_conn->transport.private_data,
1274 struct stream_connection);
1276 stream_terminate_connection(srv_conn, reason);
1278 /* We need this include to be able to compile on some plateforms
1279 * (ie. freebsd 7.2) as it seems that <sys/uio.h> is not included
1280 * correctly.
1281 * It has to be that deep because otherwise we have a conflict on
1282 * const struct dcesrv_interface declaration.
1283 * This is mostly due to socket_wrapper defining #define bind swrap_bind
1284 * which conflict with the bind used before.
1286 #include "system/network.h"
1288 struct dcesrv_sock_reply_state {
1289 struct dcesrv_connection *dce_conn;
1290 struct dcesrv_call_state *call;
1291 struct iovec iov;
1294 static void dcesrv_sock_reply_done(struct tevent_req *subreq);
1296 static void dcesrv_sock_report_output_data(struct dcesrv_connection *dce_conn)
1298 struct dcesrv_call_state *call;
1300 call = dce_conn->call_list;
1301 if (!call || !call->replies) {
1302 return;
1305 while (call->replies) {
1306 struct data_blob_list_item *rep = call->replies;
1307 struct dcesrv_sock_reply_state *substate;
1308 struct tevent_req *subreq;
1310 substate = talloc(call, struct dcesrv_sock_reply_state);
1311 if (!substate) {
1312 dcesrv_terminate_connection(dce_conn, "no memory");
1313 return;
1316 substate->dce_conn = dce_conn;
1317 substate->call = NULL;
1319 DLIST_REMOVE(call->replies, rep);
1321 if (call->replies == NULL) {
1322 substate->call = call;
1325 substate->iov.iov_base = (void *) rep->blob.data;
1326 substate->iov.iov_len = rep->blob.length;
1328 subreq = tstream_writev_queue_send(substate,
1329 dce_conn->event_ctx,
1330 dce_conn->stream,
1331 dce_conn->send_queue,
1332 &substate->iov, 1);
1333 if (!subreq) {
1334 dcesrv_terminate_connection(dce_conn, "no memory");
1335 return;
1337 tevent_req_set_callback(subreq, dcesrv_sock_reply_done,
1338 substate);
1341 DLIST_REMOVE(call->conn->call_list, call);
1342 call->list = DCESRV_LIST_NONE;
1345 static void dcesrv_sock_reply_done(struct tevent_req *subreq)
1347 struct dcesrv_sock_reply_state *substate = tevent_req_callback_data(subreq,
1348 struct dcesrv_sock_reply_state);
1349 int ret;
1350 int sys_errno;
1351 NTSTATUS status;
1352 struct dcesrv_call_state *call = substate->call;
1354 ret = tstream_writev_queue_recv(subreq, &sys_errno);
1355 TALLOC_FREE(subreq);
1356 if (ret == -1) {
1357 status = map_nt_error_from_unix_common(sys_errno);
1358 dcesrv_terminate_connection(substate->dce_conn, nt_errstr(status));
1359 return;
1362 talloc_free(substate);
1363 if (call) {
1364 talloc_free(call);
1371 struct dcesrv_socket_context {
1372 const struct dcesrv_endpoint *endpoint;
1373 struct dcesrv_context *dcesrv_ctx;
1377 static void dcesrv_read_fragment_done(struct tevent_req *subreq);
1379 static void dcesrv_sock_accept(struct stream_connection *srv_conn)
1381 NTSTATUS status;
1382 struct dcesrv_socket_context *dcesrv_sock =
1383 talloc_get_type(srv_conn->private_data, struct dcesrv_socket_context);
1384 struct dcesrv_connection *dcesrv_conn = NULL;
1385 int ret;
1386 struct tevent_req *subreq;
1387 struct loadparm_context *lp_ctx = dcesrv_sock->dcesrv_ctx->lp_ctx;
1389 if (!srv_conn->session_info) {
1390 status = auth_anonymous_session_info(srv_conn,
1391 lp_ctx,
1392 &srv_conn->session_info);
1393 if (!NT_STATUS_IS_OK(status)) {
1394 DEBUG(0,("dcesrv_sock_accept: auth_anonymous_session_info failed: %s\n",
1395 nt_errstr(status)));
1396 stream_terminate_connection(srv_conn, nt_errstr(status));
1397 return;
1401 status = dcesrv_endpoint_connect(dcesrv_sock->dcesrv_ctx,
1402 srv_conn,
1403 dcesrv_sock->endpoint,
1404 srv_conn->session_info,
1405 srv_conn->event.ctx,
1406 srv_conn->msg_ctx,
1407 srv_conn->server_id,
1408 DCESRV_CALL_STATE_FLAG_MAY_ASYNC,
1409 &dcesrv_conn);
1410 if (!NT_STATUS_IS_OK(status)) {
1411 DEBUG(0,("dcesrv_sock_accept: dcesrv_endpoint_connect failed: %s\n",
1412 nt_errstr(status)));
1413 stream_terminate_connection(srv_conn, nt_errstr(status));
1414 return;
1417 dcesrv_conn->transport.private_data = srv_conn;
1418 dcesrv_conn->transport.report_output_data = dcesrv_sock_report_output_data;
1420 TALLOC_FREE(srv_conn->event.fde);
1422 dcesrv_conn->send_queue = tevent_queue_create(dcesrv_conn, "dcesrv send queue");
1423 if (!dcesrv_conn->send_queue) {
1424 status = NT_STATUS_NO_MEMORY;
1425 DEBUG(0,("dcesrv_sock_accept: tevent_queue_create(%s)\n",
1426 nt_errstr(status)));
1427 stream_terminate_connection(srv_conn, nt_errstr(status));
1428 return;
1431 if (dcesrv_sock->endpoint->ep_description->transport == NCACN_NP) {
1432 dcesrv_conn->auth_state.session_key = dcesrv_inherited_session_key;
1433 dcesrv_conn->stream = talloc_move(dcesrv_conn,
1434 &srv_conn->tstream);
1435 } else {
1436 ret = tstream_bsd_existing_socket(dcesrv_conn,
1437 socket_get_fd(srv_conn->socket),
1438 &dcesrv_conn->stream);
1439 if (ret == -1) {
1440 status = map_nt_error_from_unix_common(errno);
1441 DEBUG(0, ("dcesrv_sock_accept: "
1442 "failed to setup tstream: %s\n",
1443 nt_errstr(status)));
1444 stream_terminate_connection(srv_conn, nt_errstr(status));
1445 return;
1447 socket_set_flags(srv_conn->socket, SOCKET_FLAG_NOCLOSE);
1450 dcesrv_conn->local_address = srv_conn->local_address;
1451 dcesrv_conn->remote_address = srv_conn->remote_address;
1453 srv_conn->private_data = dcesrv_conn;
1455 irpc_add_name(srv_conn->msg_ctx, "rpc_server");
1457 subreq = dcerpc_read_ncacn_packet_send(dcesrv_conn,
1458 dcesrv_conn->event_ctx,
1459 dcesrv_conn->stream);
1460 if (!subreq) {
1461 status = NT_STATUS_NO_MEMORY;
1462 DEBUG(0,("dcesrv_sock_accept: dcerpc_read_fragment_buffer_send(%s)\n",
1463 nt_errstr(status)));
1464 stream_terminate_connection(srv_conn, nt_errstr(status));
1465 return;
1467 tevent_req_set_callback(subreq, dcesrv_read_fragment_done, dcesrv_conn);
1469 return;
1472 static void dcesrv_read_fragment_done(struct tevent_req *subreq)
1474 struct dcesrv_connection *dce_conn = tevent_req_callback_data(subreq,
1475 struct dcesrv_connection);
1476 struct ncacn_packet *pkt;
1477 DATA_BLOB buffer;
1478 NTSTATUS status;
1480 status = dcerpc_read_ncacn_packet_recv(subreq, dce_conn,
1481 &pkt, &buffer);
1482 TALLOC_FREE(subreq);
1483 if (!NT_STATUS_IS_OK(status)) {
1484 dcesrv_terminate_connection(dce_conn, nt_errstr(status));
1485 return;
1488 status = dcesrv_process_ncacn_packet(dce_conn, pkt, buffer);
1489 if (!NT_STATUS_IS_OK(status)) {
1490 dcesrv_terminate_connection(dce_conn, nt_errstr(status));
1491 return;
1494 subreq = dcerpc_read_ncacn_packet_send(dce_conn,
1495 dce_conn->event_ctx,
1496 dce_conn->stream);
1497 if (!subreq) {
1498 status = NT_STATUS_NO_MEMORY;
1499 dcesrv_terminate_connection(dce_conn, nt_errstr(status));
1500 return;
1502 tevent_req_set_callback(subreq, dcesrv_read_fragment_done, dce_conn);
1505 static void dcesrv_sock_recv(struct stream_connection *conn, uint16_t flags)
1507 struct dcesrv_connection *dce_conn = talloc_get_type(conn->private_data,
1508 struct dcesrv_connection);
1509 dcesrv_terminate_connection(dce_conn, "dcesrv_sock_recv triggered");
1512 static void dcesrv_sock_send(struct stream_connection *conn, uint16_t flags)
1514 struct dcesrv_connection *dce_conn = talloc_get_type(conn->private_data,
1515 struct dcesrv_connection);
1516 dcesrv_terminate_connection(dce_conn, "dcesrv_sock_send triggered");
1520 static const struct stream_server_ops dcesrv_stream_ops = {
1521 .name = "rpc",
1522 .accept_connection = dcesrv_sock_accept,
1523 .recv_handler = dcesrv_sock_recv,
1524 .send_handler = dcesrv_sock_send,
1527 static NTSTATUS dcesrv_add_ep_unix(struct dcesrv_context *dce_ctx,
1528 struct loadparm_context *lp_ctx,
1529 struct dcesrv_endpoint *e,
1530 struct tevent_context *event_ctx, const struct model_ops *model_ops)
1532 struct dcesrv_socket_context *dcesrv_sock;
1533 uint16_t port = 1;
1534 NTSTATUS status;
1536 dcesrv_sock = talloc(event_ctx, struct dcesrv_socket_context);
1537 NT_STATUS_HAVE_NO_MEMORY(dcesrv_sock);
1539 /* remember the endpoint of this socket */
1540 dcesrv_sock->endpoint = e;
1541 dcesrv_sock->dcesrv_ctx = talloc_reference(dcesrv_sock, dce_ctx);
1543 status = stream_setup_socket(dcesrv_sock, event_ctx, lp_ctx,
1544 model_ops, &dcesrv_stream_ops,
1545 "unix", e->ep_description->endpoint, &port,
1546 lpcfg_socket_options(lp_ctx),
1547 dcesrv_sock);
1548 if (!NT_STATUS_IS_OK(status)) {
1549 DEBUG(0,("service_setup_stream_socket(path=%s) failed - %s\n",
1550 e->ep_description->endpoint, nt_errstr(status)));
1553 return status;
1556 static NTSTATUS dcesrv_add_ep_ncalrpc(struct dcesrv_context *dce_ctx,
1557 struct loadparm_context *lp_ctx,
1558 struct dcesrv_endpoint *e,
1559 struct tevent_context *event_ctx, const struct model_ops *model_ops)
1561 struct dcesrv_socket_context *dcesrv_sock;
1562 uint16_t port = 1;
1563 char *full_path;
1564 NTSTATUS status;
1566 if (!e->ep_description->endpoint) {
1567 /* No identifier specified: use DEFAULT.
1568 * DO NOT hardcode this value anywhere else. Rather, specify
1569 * no endpoint and let the epmapper worry about it. */
1570 e->ep_description->endpoint = talloc_strdup(dce_ctx, "DEFAULT");
1573 full_path = talloc_asprintf(dce_ctx, "%s/%s", lpcfg_ncalrpc_dir(lp_ctx),
1574 e->ep_description->endpoint);
1576 dcesrv_sock = talloc(event_ctx, struct dcesrv_socket_context);
1577 NT_STATUS_HAVE_NO_MEMORY(dcesrv_sock);
1579 /* remember the endpoint of this socket */
1580 dcesrv_sock->endpoint = e;
1581 dcesrv_sock->dcesrv_ctx = talloc_reference(dcesrv_sock, dce_ctx);
1583 status = stream_setup_socket(dcesrv_sock, event_ctx, lp_ctx,
1584 model_ops, &dcesrv_stream_ops,
1585 "unix", full_path, &port,
1586 lpcfg_socket_options(lp_ctx),
1587 dcesrv_sock);
1588 if (!NT_STATUS_IS_OK(status)) {
1589 DEBUG(0,("service_setup_stream_socket(identifier=%s,path=%s) failed - %s\n",
1590 e->ep_description->endpoint, full_path, nt_errstr(status)));
1592 return status;
1595 static NTSTATUS dcesrv_add_ep_np(struct dcesrv_context *dce_ctx,
1596 struct loadparm_context *lp_ctx,
1597 struct dcesrv_endpoint *e,
1598 struct tevent_context *event_ctx, const struct model_ops *model_ops)
1600 struct dcesrv_socket_context *dcesrv_sock;
1601 NTSTATUS status;
1603 if (e->ep_description->endpoint == NULL) {
1604 DEBUG(0, ("Endpoint mandatory for named pipes\n"));
1605 return NT_STATUS_INVALID_PARAMETER;
1608 dcesrv_sock = talloc(event_ctx, struct dcesrv_socket_context);
1609 NT_STATUS_HAVE_NO_MEMORY(dcesrv_sock);
1611 /* remember the endpoint of this socket */
1612 dcesrv_sock->endpoint = e;
1613 dcesrv_sock->dcesrv_ctx = talloc_reference(dcesrv_sock, dce_ctx);
1615 status = tstream_setup_named_pipe(dce_ctx, event_ctx, lp_ctx,
1616 model_ops, &dcesrv_stream_ops,
1617 e->ep_description->endpoint,
1618 dcesrv_sock);
1619 if (!NT_STATUS_IS_OK(status)) {
1620 DEBUG(0,("stream_setup_named_pipe(pipe=%s) failed - %s\n",
1621 e->ep_description->endpoint, nt_errstr(status)));
1622 return status;
1625 return NT_STATUS_OK;
1629 add a socket address to the list of events, one event per dcerpc endpoint
1631 static NTSTATUS add_socket_rpc_tcp_iface(struct dcesrv_context *dce_ctx, struct dcesrv_endpoint *e,
1632 struct tevent_context *event_ctx, const struct model_ops *model_ops,
1633 const char *address)
1635 struct dcesrv_socket_context *dcesrv_sock;
1636 uint16_t port = 0;
1637 NTSTATUS status;
1639 if (e->ep_description->endpoint) {
1640 port = atoi(e->ep_description->endpoint);
1643 dcesrv_sock = talloc(event_ctx, struct dcesrv_socket_context);
1644 NT_STATUS_HAVE_NO_MEMORY(dcesrv_sock);
1646 /* remember the endpoint of this socket */
1647 dcesrv_sock->endpoint = e;
1648 dcesrv_sock->dcesrv_ctx = talloc_reference(dcesrv_sock, dce_ctx);
1650 status = stream_setup_socket(dcesrv_sock, event_ctx, dce_ctx->lp_ctx,
1651 model_ops, &dcesrv_stream_ops,
1652 "ip", address, &port,
1653 lpcfg_socket_options(dce_ctx->lp_ctx),
1654 dcesrv_sock);
1655 if (!NT_STATUS_IS_OK(status)) {
1656 DEBUG(0,("service_setup_stream_socket(address=%s,port=%u) failed - %s\n",
1657 address, port, nt_errstr(status)));
1660 if (e->ep_description->endpoint == NULL) {
1661 e->ep_description->endpoint = talloc_asprintf(dce_ctx, "%d", port);
1664 return status;
1667 #include "lib/socket/netif.h" /* Included here to work around the fact that socket_wrapper redefines bind() */
1669 static NTSTATUS dcesrv_add_ep_tcp(struct dcesrv_context *dce_ctx,
1670 struct loadparm_context *lp_ctx,
1671 struct dcesrv_endpoint *e,
1672 struct tevent_context *event_ctx, const struct model_ops *model_ops)
1674 NTSTATUS status;
1676 /* Add TCP/IP sockets */
1677 if (lpcfg_interfaces(lp_ctx) && lpcfg_bind_interfaces_only(lp_ctx)) {
1678 int num_interfaces;
1679 int i;
1680 struct interface *ifaces;
1682 load_interface_list(dce_ctx, lp_ctx, &ifaces);
1684 num_interfaces = iface_list_count(ifaces);
1685 for(i = 0; i < num_interfaces; i++) {
1686 const char *address = iface_list_n_ip(ifaces, i);
1687 status = add_socket_rpc_tcp_iface(dce_ctx, e, event_ctx, model_ops, address);
1688 NT_STATUS_NOT_OK_RETURN(status);
1690 } else {
1691 const char **wcard;
1692 int i;
1693 wcard = iface_list_wildcard(dce_ctx, lp_ctx);
1694 NT_STATUS_HAVE_NO_MEMORY(wcard);
1695 for (i=0; wcard[i]; i++) {
1696 status = add_socket_rpc_tcp_iface(dce_ctx, e, event_ctx, model_ops, wcard[i]);
1697 NT_STATUS_NOT_OK_RETURN(status);
1699 talloc_free(wcard);
1702 return NT_STATUS_OK;
1705 NTSTATUS dcesrv_add_ep(struct dcesrv_context *dce_ctx,
1706 struct loadparm_context *lp_ctx,
1707 struct dcesrv_endpoint *e,
1708 struct tevent_context *event_ctx,
1709 const struct model_ops *model_ops)
1711 switch (e->ep_description->transport) {
1712 case NCACN_UNIX_STREAM:
1713 return dcesrv_add_ep_unix(dce_ctx, lp_ctx, e, event_ctx, model_ops);
1715 case NCALRPC:
1716 return dcesrv_add_ep_ncalrpc(dce_ctx, lp_ctx, e, event_ctx, model_ops);
1718 case NCACN_IP_TCP:
1719 return dcesrv_add_ep_tcp(dce_ctx, lp_ctx, e, event_ctx, model_ops);
1721 case NCACN_NP:
1722 return dcesrv_add_ep_np(dce_ctx, lp_ctx, e, event_ctx, model_ops);
1724 default:
1725 return NT_STATUS_NOT_SUPPORTED;
1731 * retrieve credentials from a dce_call
1733 _PUBLIC_ struct cli_credentials *dcesrv_call_credentials(struct dcesrv_call_state *dce_call)
1735 return dce_call->conn->auth_state.session_info->credentials;
1739 * returns true if this is an authenticated call
1741 _PUBLIC_ bool dcesrv_call_authenticated(struct dcesrv_call_state *dce_call)
1743 enum security_user_level level;
1744 level = security_session_user_level(dce_call->conn->auth_state.session_info, NULL);
1745 return level >= SECURITY_USER;
1749 * retrieve account_name for a dce_call
1751 _PUBLIC_ const char *dcesrv_call_account_name(struct dcesrv_call_state *dce_call)
1753 return dce_call->context->conn->auth_state.session_info->info->account_name;