CVE-2015-5370: s4:rpc_server: remove pointless dcesrv_find_context() from dcesrv_bind()
[samba.git] / source4 / rpc_server / dcerpc_server.c
1 /* 
2    Unix SMB/CIFS implementation.
3
4    server side dcerpc core code
5
6    Copyright (C) Andrew Tridgell 2003-2005
7    Copyright (C) Stefan (metze) Metzmacher 2004-2005
8    
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.
13    
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.
18    
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/>.
21 */
22
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"
44
45 /* this is only used when the client asks for an unknown interface */
46 #define DUMMY_ASSOC_GROUP 0x0FFFFFFF
47
48 extern const struct dcesrv_interface dcesrv_mgmt_interface;
49
50
51 /*
52   find an association group given a assoc_group_id
53  */
54 static struct dcesrv_assoc_group *dcesrv_assoc_group_find(struct dcesrv_context *dce_ctx,
55                                                           uint32_t id)
56 {
57         void *id_ptr;
58
59         id_ptr = idr_find(dce_ctx->assoc_groups_idr, id);
60         if (id_ptr == NULL) {
61                 return NULL;
62         }
63         return talloc_get_type_abort(id_ptr, struct dcesrv_assoc_group);
64 }
65
66 /*
67   take a reference to an existing association group
68  */
69 static struct dcesrv_assoc_group *dcesrv_assoc_group_reference(TALLOC_CTX *mem_ctx,
70                                                                struct dcesrv_context *dce_ctx,
71                                                                uint32_t id)
72 {
73         struct dcesrv_assoc_group *assoc_group;
74
75         assoc_group = dcesrv_assoc_group_find(dce_ctx, id);
76         if (assoc_group == NULL) {
77                 DEBUG(0,(__location__ ": Failed to find assoc_group 0x%08x\n", id));
78                 return NULL;
79         }
80         return talloc_reference(mem_ctx, assoc_group);
81 }
82
83 static int dcesrv_assoc_group_destructor(struct dcesrv_assoc_group *assoc_group)
84 {
85         int ret;
86         ret = idr_remove(assoc_group->dce_ctx->assoc_groups_idr, assoc_group->id);
87         if (ret != 0) {
88                 DEBUG(0,(__location__ ": Failed to remove assoc_group 0x%08x\n",
89                          assoc_group->id));
90         }
91         return 0;
92 }
93
94 /*
95   allocate a new association group
96  */
97 static struct dcesrv_assoc_group *dcesrv_assoc_group_new(TALLOC_CTX *mem_ctx,
98                                                          struct dcesrv_context *dce_ctx)
99 {
100         struct dcesrv_assoc_group *assoc_group;
101         int id;
102
103         assoc_group = talloc_zero(mem_ctx, struct dcesrv_assoc_group);
104         if (assoc_group == NULL) {
105                 return NULL;
106         }
107         
108         id = idr_get_new_random(dce_ctx->assoc_groups_idr, assoc_group, UINT16_MAX);
109         if (id == -1) {
110                 talloc_free(assoc_group);
111                 DEBUG(0,(__location__ ": Out of association groups!\n"));
112                 return NULL;
113         }
114
115         assoc_group->id = id;
116         assoc_group->dce_ctx = dce_ctx;
117
118         talloc_set_destructor(assoc_group, dcesrv_assoc_group_destructor);
119
120         return assoc_group;
121 }
122
123
124 /*
125   see if two endpoints match
126 */
127 static bool endpoints_match(const struct dcerpc_binding *ep1,
128                             const struct dcerpc_binding *ep2)
129 {
130         enum dcerpc_transport_t t1;
131         enum dcerpc_transport_t t2;
132         const char *e1;
133         const char *e2;
134
135         t1 = dcerpc_binding_get_transport(ep1);
136         t2 = dcerpc_binding_get_transport(ep2);
137
138         e1 = dcerpc_binding_get_string_option(ep1, "endpoint");
139         e2 = dcerpc_binding_get_string_option(ep2, "endpoint");
140
141         if (t1 != t2) {
142                 return false;
143         }
144
145         if (!e1 || !e2) {
146                 return e1 == e2;
147         }
148
149         if (strcasecmp(e1, e2) != 0) {
150                 return false;
151         }
152
153         return true;
154 }
155
156 /*
157   find an endpoint in the dcesrv_context
158 */
159 static struct dcesrv_endpoint *find_endpoint(struct dcesrv_context *dce_ctx,
160                                              const struct dcerpc_binding *ep_description)
161 {
162         struct dcesrv_endpoint *ep;
163         for (ep=dce_ctx->endpoint_list; ep; ep=ep->next) {
164                 if (endpoints_match(ep->ep_description, ep_description)) {
165                         return ep;
166                 }
167         }
168         return NULL;
169 }
170
171 /*
172   find a registered context_id from a bind or alter_context
173 */
174 static struct dcesrv_connection_context *dcesrv_find_context(struct dcesrv_connection *conn, 
175                                                                    uint32_t context_id)
176 {
177         struct dcesrv_connection_context *c;
178         for (c=conn->contexts;c;c=c->next) {
179                 if (c->context_id == context_id) return c;
180         }
181         return NULL;
182 }
183
184 /*
185   see if a uuid and if_version match to an interface
186 */
187 static bool interface_match(const struct dcesrv_interface *if1,
188                                                         const struct dcesrv_interface *if2)
189 {
190         return (if1->syntax_id.if_version == if2->syntax_id.if_version && 
191                         GUID_equal(&if1->syntax_id.uuid, &if2->syntax_id.uuid));
192 }
193
194 /*
195   find the interface operations on an endpoint
196 */
197 static const struct dcesrv_interface *find_interface(const struct dcesrv_endpoint *endpoint,
198                                                      const struct dcesrv_interface *iface)
199 {
200         struct dcesrv_if_list *ifl;
201         for (ifl=endpoint->interface_list; ifl; ifl=ifl->next) {
202                 if (interface_match(&(ifl->iface), iface)) {
203                         return &(ifl->iface);
204                 }
205         }
206         return NULL;
207 }
208
209 /*
210   see if a uuid and if_version match to an interface
211 */
212 static bool interface_match_by_uuid(const struct dcesrv_interface *iface,
213                                     const struct GUID *uuid, uint32_t if_version)
214 {
215         return (iface->syntax_id.if_version == if_version && 
216                         GUID_equal(&iface->syntax_id.uuid, uuid));
217 }
218
219 /*
220   find the interface operations on an endpoint by uuid
221 */
222 static const struct dcesrv_interface *find_interface_by_uuid(const struct dcesrv_endpoint *endpoint,
223                                                              const struct GUID *uuid, uint32_t if_version)
224 {
225         struct dcesrv_if_list *ifl;
226         for (ifl=endpoint->interface_list; ifl; ifl=ifl->next) {
227                 if (interface_match_by_uuid(&(ifl->iface), uuid, if_version)) {
228                         return &(ifl->iface);
229                 }
230         }
231         return NULL;
232 }
233
234 /*
235   find the earlier parts of a fragmented call awaiting reassembily
236 */
237 static struct dcesrv_call_state *dcesrv_find_fragmented_call(struct dcesrv_connection *dce_conn, uint16_t call_id)
238 {
239         struct dcesrv_call_state *c;
240         for (c=dce_conn->incoming_fragmented_call_list;c;c=c->next) {
241                 if (c->pkt.call_id == call_id) {
242                         return c;
243                 }
244         }
245         return NULL;
246 }
247
248 /*
249   register an interface on an endpoint
250 */
251 _PUBLIC_ NTSTATUS dcesrv_interface_register(struct dcesrv_context *dce_ctx,
252                                    const char *ep_name,
253                                    const struct dcesrv_interface *iface,
254                                    const struct security_descriptor *sd)
255 {
256         struct dcesrv_endpoint *ep;
257         struct dcesrv_if_list *ifl;
258         struct dcerpc_binding *binding;
259         bool add_ep = false;
260         NTSTATUS status;
261         
262         status = dcerpc_parse_binding(dce_ctx, ep_name, &binding);
263
264         if (NT_STATUS_IS_ERR(status)) {
265                 DEBUG(0, ("Trouble parsing binding string '%s'\n", ep_name));
266                 return status;
267         }
268
269         /* check if this endpoint exists
270          */
271         if ((ep=find_endpoint(dce_ctx, binding))==NULL) {
272                 ep = talloc_zero(dce_ctx, struct dcesrv_endpoint);
273                 if (!ep) {
274                         return NT_STATUS_NO_MEMORY;
275                 }
276                 ZERO_STRUCTP(ep);
277                 ep->ep_description = talloc_move(ep, &binding);
278                 add_ep = true;
279
280                 /* add mgmt interface */
281                 ifl = talloc_zero(ep, struct dcesrv_if_list);
282                 if (!ifl) {
283                         return NT_STATUS_NO_MEMORY;
284                 }
285
286                 memcpy(&(ifl->iface), &dcesrv_mgmt_interface, 
287                            sizeof(struct dcesrv_interface));
288
289                 DLIST_ADD(ep->interface_list, ifl);
290         }
291
292         /* see if the interface is already registered on te endpoint */
293         if (find_interface(ep, iface)!=NULL) {
294                 DEBUG(0,("dcesrv_interface_register: interface '%s' already registered on endpoint '%s'\n",
295                         iface->name, ep_name));
296                 return NT_STATUS_OBJECT_NAME_COLLISION;
297         }
298
299         /* talloc a new interface list element */
300         ifl = talloc_zero(ep, struct dcesrv_if_list);
301         if (!ifl) {
302                 return NT_STATUS_NO_MEMORY;
303         }
304
305         /* copy the given interface struct to the one on the endpoints interface list */
306         memcpy(&(ifl->iface),iface, sizeof(struct dcesrv_interface));
307
308         /* if we have a security descriptor given,
309          * we should see if we can set it up on the endpoint
310          */
311         if (sd != NULL) {
312                 /* if there's currently no security descriptor given on the endpoint
313                  * we try to set it
314                  */
315                 if (ep->sd == NULL) {
316                         ep->sd = security_descriptor_copy(ep, sd);
317                 }
318
319                 /* if now there's no security descriptor given on the endpoint
320                  * something goes wrong, either we failed to copy the security descriptor
321                  * or there was already one on the endpoint
322                  */
323                 if (ep->sd != NULL) {
324                         DEBUG(0,("dcesrv_interface_register: interface '%s' failed to setup a security descriptor\n"
325                                  "                           on endpoint '%s'\n",
326                                 iface->name, ep_name));
327                         if (add_ep) free(ep);
328                         free(ifl);
329                         return NT_STATUS_OBJECT_NAME_COLLISION;
330                 }
331         }
332
333         /* finally add the interface on the endpoint */
334         DLIST_ADD(ep->interface_list, ifl);
335
336         /* if it's a new endpoint add it to the dcesrv_context */
337         if (add_ep) {
338                 DLIST_ADD(dce_ctx->endpoint_list, ep);
339         }
340
341         DEBUG(4,("dcesrv_interface_register: interface '%s' registered on endpoint '%s'\n",
342                 iface->name, ep_name));
343
344         return NT_STATUS_OK;
345 }
346
347 NTSTATUS dcesrv_inherited_session_key(struct dcesrv_connection *p,
348                                       DATA_BLOB *session_key)
349 {
350         if (p->auth_state.session_info->session_key.length) {
351                 *session_key = p->auth_state.session_info->session_key;
352                 return NT_STATUS_OK;
353         }
354         return NT_STATUS_NO_USER_SESSION_KEY;
355 }
356
357 /*
358   fetch the user session key - may be default (above) or the SMB session key
359
360   The key is always truncated to 16 bytes 
361 */
362 _PUBLIC_ NTSTATUS dcesrv_fetch_session_key(struct dcesrv_connection *p,
363                                   DATA_BLOB *session_key)
364 {
365         NTSTATUS status = p->auth_state.session_key(p, session_key);
366         if (!NT_STATUS_IS_OK(status)) {
367                 return status;
368         }
369
370         session_key->length = MIN(session_key->length, 16);
371
372         return NT_STATUS_OK;
373 }
374
375 /*
376   connect to a dcerpc endpoint
377 */
378 _PUBLIC_ NTSTATUS dcesrv_endpoint_connect(struct dcesrv_context *dce_ctx,
379                                  TALLOC_CTX *mem_ctx,
380                                  const struct dcesrv_endpoint *ep,
381                                  struct auth_session_info *session_info,
382                                  struct tevent_context *event_ctx,
383                                  struct imessaging_context *msg_ctx,
384                                  struct server_id server_id,
385                                  uint32_t state_flags,
386                                  struct dcesrv_connection **_p)
387 {
388         struct dcesrv_connection *p;
389
390         if (!session_info) {
391                 return NT_STATUS_ACCESS_DENIED;
392         }
393
394         p = talloc_zero(mem_ctx, struct dcesrv_connection);
395         NT_STATUS_HAVE_NO_MEMORY(p);
396
397         if (!talloc_reference(p, session_info)) {
398                 talloc_free(p);
399                 return NT_STATUS_NO_MEMORY;
400         }
401
402         p->dce_ctx = dce_ctx;
403         p->endpoint = ep;
404         p->packet_log_dir = lpcfg_lock_directory(dce_ctx->lp_ctx);
405         p->auth_state.session_info = session_info;
406         p->auth_state.session_key = dcesrv_generic_session_key;
407         p->event_ctx = event_ctx;
408         p->msg_ctx = msg_ctx;
409         p->server_id = server_id;
410         p->state_flags = state_flags;
411         p->allow_bind = true;
412         p->max_recv_frag = 5840;
413         p->max_xmit_frag = 5840;
414
415         *_p = p;
416         return NT_STATUS_OK;
417 }
418
419 /*
420   move a call from an existing linked list to the specified list. This
421   prevents bugs where we forget to remove the call from a previous
422   list when moving it.
423  */
424 static void dcesrv_call_set_list(struct dcesrv_call_state *call, 
425                                  enum dcesrv_call_list list)
426 {
427         switch (call->list) {
428         case DCESRV_LIST_NONE:
429                 break;
430         case DCESRV_LIST_CALL_LIST:
431                 DLIST_REMOVE(call->conn->call_list, call);
432                 break;
433         case DCESRV_LIST_FRAGMENTED_CALL_LIST:
434                 DLIST_REMOVE(call->conn->incoming_fragmented_call_list, call);
435                 break;
436         case DCESRV_LIST_PENDING_CALL_LIST:
437                 DLIST_REMOVE(call->conn->pending_call_list, call);
438                 break;
439         }
440         call->list = list;
441         switch (list) {
442         case DCESRV_LIST_NONE:
443                 break;
444         case DCESRV_LIST_CALL_LIST:
445                 DLIST_ADD_END(call->conn->call_list, call);
446                 break;
447         case DCESRV_LIST_FRAGMENTED_CALL_LIST:
448                 DLIST_ADD_END(call->conn->incoming_fragmented_call_list, call);
449                 break;
450         case DCESRV_LIST_PENDING_CALL_LIST:
451                 DLIST_ADD_END(call->conn->pending_call_list, call);
452                 break;
453         }
454 }
455
456 static void dcesrv_call_disconnect_after(struct dcesrv_call_state *call,
457                                          const char *reason)
458 {
459         if (call->conn->terminate != NULL) {
460                 return;
461         }
462
463         call->conn->allow_bind = false;
464         call->conn->allow_alter = false;
465         call->conn->allow_auth3 = false;
466         call->conn->allow_request = false;
467
468         call->terminate_reason = talloc_strdup(call, reason);
469         if (call->terminate_reason == NULL) {
470                 call->terminate_reason = __location__;
471         }
472 }
473
474 /*
475   return a dcerpc bind_nak
476 */
477 static NTSTATUS dcesrv_bind_nak(struct dcesrv_call_state *call, uint32_t reason)
478 {
479         struct ncacn_packet pkt;
480         struct dcerpc_bind_nak_version version;
481         struct data_blob_list_item *rep;
482         NTSTATUS status;
483         static const uint8_t _pad[3] = { 0, };
484
485         /*
486          * We add the call to the pending_call_list
487          * in order to defer the termination.
488          */
489         dcesrv_call_disconnect_after(call, "dcesrv_bind_nak");
490
491         /* setup a bind_nak */
492         dcesrv_init_hdr(&pkt, lpcfg_rpc_big_endian(call->conn->dce_ctx->lp_ctx));
493         pkt.auth_length = 0;
494         pkt.call_id = call->pkt.call_id;
495         pkt.ptype = DCERPC_PKT_BIND_NAK;
496         pkt.pfc_flags = DCERPC_PFC_FLAG_FIRST | DCERPC_PFC_FLAG_LAST;
497         pkt.u.bind_nak.reject_reason = reason;
498         version.rpc_vers = 5;
499         version.rpc_vers_minor = 0;
500         pkt.u.bind_nak.num_versions = 1;
501         pkt.u.bind_nak.versions = &version;
502         pkt.u.bind_nak._pad = data_blob_const(_pad, sizeof(_pad));
503
504         rep = talloc_zero(call, struct data_blob_list_item);
505         if (!rep) {
506                 return NT_STATUS_NO_MEMORY;
507         }
508
509         status = ncacn_push_auth(&rep->blob, call, &pkt, NULL);
510         if (!NT_STATUS_IS_OK(status)) {
511                 return status;
512         }
513
514         dcerpc_set_frag_length(&rep->blob, rep->blob.length);
515
516         DLIST_ADD_END(call->replies, rep);
517         dcesrv_call_set_list(call, DCESRV_LIST_CALL_LIST);
518
519         if (call->conn->call_list && call->conn->call_list->replies) {
520                 if (call->conn->transport.report_output_data) {
521                         call->conn->transport.report_output_data(call->conn);
522                 }
523         }
524
525         return NT_STATUS_OK;    
526 }
527
528 static NTSTATUS dcesrv_fault_disconnect(struct dcesrv_call_state *call,
529                                  uint32_t fault_code)
530 {
531         /*
532          * We add the call to the pending_call_list
533          * in order to defer the termination.
534          */
535         dcesrv_call_disconnect_after(call, "dcesrv_fault_disconnect");
536
537         return dcesrv_fault_with_flags(call, fault_code,
538                                        DCERPC_PFC_FLAG_DID_NOT_EXECUTE);
539 }
540
541 static int dcesrv_connection_context_destructor(struct dcesrv_connection_context *c)
542 {
543         DLIST_REMOVE(c->conn->contexts, c);
544
545         if (c->iface && c->iface->unbind) {
546                 c->iface->unbind(c, c->iface);
547                 c->iface = NULL;
548         }
549
550         return 0;
551 }
552
553 static void dcesrv_prepare_context_auth(struct dcesrv_call_state *dce_call)
554 {
555         struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
556         const struct dcesrv_endpoint *endpoint = dce_call->conn->endpoint;
557         enum dcerpc_transport_t transport =
558                 dcerpc_binding_get_transport(endpoint->ep_description);
559         struct dcesrv_connection_context *context = dce_call->context;
560         const struct dcesrv_interface *iface = context->iface;
561
562         context->min_auth_level = DCERPC_AUTH_LEVEL_NONE;
563
564         if (transport == NCALRPC) {
565                 context->allow_connect = true;
566                 return;
567         }
568
569         /*
570          * allow overwrite per interface
571          * allow dcerpc auth level connect:<interface>
572          */
573         context->allow_connect = lpcfg_allow_dcerpc_auth_level_connect(lp_ctx);
574         context->allow_connect = lpcfg_parm_bool(lp_ctx, NULL,
575                                         "allow dcerpc auth level connect",
576                                         iface->name,
577                                         context->allow_connect);
578 }
579
580 NTSTATUS dcesrv_interface_bind_require_integrity(struct dcesrv_call_state *dce_call,
581                                                  const struct dcesrv_interface *iface)
582 {
583         if (dce_call->context == NULL) {
584                 return NT_STATUS_INTERNAL_ERROR;
585         }
586
587         dce_call->context->min_auth_level = DCERPC_AUTH_LEVEL_INTEGRITY;
588         return NT_STATUS_OK;
589 }
590
591 NTSTATUS dcesrv_interface_bind_require_privacy(struct dcesrv_call_state *dce_call,
592                                                const struct dcesrv_interface *iface)
593 {
594         if (dce_call->context == NULL) {
595                 return NT_STATUS_INTERNAL_ERROR;
596         }
597
598         dce_call->context->min_auth_level = DCERPC_AUTH_LEVEL_PRIVACY;
599         return NT_STATUS_OK;
600 }
601
602 _PUBLIC_ NTSTATUS dcesrv_interface_bind_reject_connect(struct dcesrv_call_state *dce_call,
603                                                        const struct dcesrv_interface *iface)
604 {
605         struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
606         const struct dcesrv_endpoint *endpoint = dce_call->conn->endpoint;
607         enum dcerpc_transport_t transport =
608                 dcerpc_binding_get_transport(endpoint->ep_description);
609         struct dcesrv_connection_context *context = dce_call->context;
610
611         if (context == NULL) {
612                 return NT_STATUS_INTERNAL_ERROR;
613         }
614
615         if (transport == NCALRPC) {
616                 context->allow_connect = true;
617                 return NT_STATUS_OK;
618         }
619
620         /*
621          * allow overwrite per interface
622          * allow dcerpc auth level connect:<interface>
623          */
624         context->allow_connect = false;
625         context->allow_connect = lpcfg_parm_bool(lp_ctx, NULL,
626                                         "allow dcerpc auth level connect",
627                                         iface->name,
628                                         context->allow_connect);
629         return NT_STATUS_OK;
630 }
631
632 _PUBLIC_ NTSTATUS dcesrv_interface_bind_allow_connect(struct dcesrv_call_state *dce_call,
633                                                       const struct dcesrv_interface *iface)
634 {
635         struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
636         const struct dcesrv_endpoint *endpoint = dce_call->conn->endpoint;
637         enum dcerpc_transport_t transport =
638                 dcerpc_binding_get_transport(endpoint->ep_description);
639         struct dcesrv_connection_context *context = dce_call->context;
640
641         if (context == NULL) {
642                 return NT_STATUS_INTERNAL_ERROR;
643         }
644
645         if (transport == NCALRPC) {
646                 context->allow_connect = true;
647                 return NT_STATUS_OK;
648         }
649
650         /*
651          * allow overwrite per interface
652          * allow dcerpc auth level connect:<interface>
653          */
654         context->allow_connect = true;
655         context->allow_connect = lpcfg_parm_bool(lp_ctx, NULL,
656                                         "allow dcerpc auth level connect",
657                                         iface->name,
658                                         context->allow_connect);
659         return NT_STATUS_OK;
660 }
661
662 /*
663   handle a bind request
664 */
665 static NTSTATUS dcesrv_bind(struct dcesrv_call_state *call)
666 {
667         uint32_t if_version, transfer_syntax_version;
668         struct GUID uuid, *transfer_syntax_uuid;
669         struct ncacn_packet pkt;
670         struct data_blob_list_item *rep;
671         NTSTATUS status;
672         uint32_t result=0, reason=0;
673         uint32_t context_id;
674         const struct dcesrv_interface *iface;
675         uint32_t extra_flags = 0;
676         uint16_t max_req = 0;
677         uint16_t max_rep = 0;
678         const char *ep_prefix = "";
679         const char *endpoint = NULL;
680
681         status = dcerpc_verify_ncacn_packet_header(&call->pkt,
682                         DCERPC_PKT_BIND,
683                         call->pkt.u.bind.auth_info.length,
684                         0, /* required flags */
685                         DCERPC_PFC_FLAG_FIRST |
686                         DCERPC_PFC_FLAG_LAST |
687                         DCERPC_PFC_FLAG_SUPPORT_HEADER_SIGN |
688                         0x08 | /* this is not defined, but should be ignored */
689                         DCERPC_PFC_FLAG_CONC_MPX |
690                         DCERPC_PFC_FLAG_DID_NOT_EXECUTE |
691                         DCERPC_PFC_FLAG_MAYBE |
692                         DCERPC_PFC_FLAG_OBJECT_UUID);
693         if (!NT_STATUS_IS_OK(status)) {
694                 return dcesrv_bind_nak(call,
695                         DCERPC_BIND_NAK_REASON_PROTOCOL_VERSION_NOT_SUPPORTED);
696         }
697
698         /* max_recv_frag and max_xmit_frag result always in the same value! */
699         max_req = MIN(call->pkt.u.bind.max_xmit_frag,
700                       call->pkt.u.bind.max_recv_frag);
701         /*
702          * The values are between 2048 and 5840 tested against Windows 2012R2
703          * via ncacn_ip_tcp on port 135.
704          */
705         max_req = MAX(2048, max_req);
706         max_rep = MIN(max_req, call->conn->max_recv_frag);
707         /* They are truncated to an 8 byte boundary. */
708         max_rep &= 0xFFF8;
709
710         /* max_recv_frag and max_xmit_frag result always in the same value! */
711         call->conn->max_recv_frag = max_rep;
712         call->conn->max_xmit_frag = max_rep;
713
714         /*
715           if provided, check the assoc_group is valid
716          */
717         if (call->pkt.u.bind.assoc_group_id != 0 &&
718             lpcfg_parm_bool(call->conn->dce_ctx->lp_ctx, NULL, "dcesrv","assoc group checking", true) &&
719             dcesrv_assoc_group_find(call->conn->dce_ctx, call->pkt.u.bind.assoc_group_id) == NULL) {
720                 return dcesrv_bind_nak(call, 0);        
721         }
722
723         if (call->pkt.u.bind.num_contexts < 1 ||
724             call->pkt.u.bind.ctx_list[0].num_transfer_syntaxes < 1) {
725                 return dcesrv_bind_nak(call, 0);
726         }
727
728         context_id = call->pkt.u.bind.ctx_list[0].context_id;
729         if_version = call->pkt.u.bind.ctx_list[0].abstract_syntax.if_version;
730         uuid = call->pkt.u.bind.ctx_list[0].abstract_syntax.uuid;
731
732         transfer_syntax_version = call->pkt.u.bind.ctx_list[0].transfer_syntaxes[0].if_version;
733         transfer_syntax_uuid = &call->pkt.u.bind.ctx_list[0].transfer_syntaxes[0].uuid;
734         if (!GUID_equal(&ndr_transfer_syntax_ndr.uuid, transfer_syntax_uuid) != 0 ||
735             ndr_transfer_syntax_ndr.if_version != transfer_syntax_version) {
736                 char *uuid_str = GUID_string(call, transfer_syntax_uuid);
737                 /* we only do NDR encoded dcerpc */
738                 DEBUG(0,("Non NDR transfer syntax requested - %s\n", uuid_str));
739                 talloc_free(uuid_str);
740                 return dcesrv_bind_nak(call, 0);
741         }
742
743         iface = find_interface_by_uuid(call->conn->endpoint, &uuid, if_version);
744         if (iface == NULL) {
745                 char *uuid_str = GUID_string(call, &uuid);
746                 DEBUG(2,("Request for unknown dcerpc interface %s/%d\n", uuid_str, if_version));
747                 talloc_free(uuid_str);
748
749                 /* we don't know about that interface */
750                 result = DCERPC_BIND_PROVIDER_REJECT;
751                 reason = DCERPC_BIND_REASON_ASYNTAX;            
752         }
753
754         if (iface) {
755                 /* add this context to the list of available context_ids */
756                 struct dcesrv_connection_context *context = talloc_zero(call->conn,
757                                                                    struct dcesrv_connection_context);
758                 if (context == NULL) {
759                         return dcesrv_bind_nak(call, 0);
760                 }
761                 context->conn = call->conn;
762                 context->iface = iface;
763                 context->context_id = context_id;
764                 if (call->pkt.u.bind.assoc_group_id != 0) {
765                         context->assoc_group = dcesrv_assoc_group_reference(context,
766                                                                             call->conn->dce_ctx, 
767                                                                             call->pkt.u.bind.assoc_group_id);
768                 } else {
769                         context->assoc_group = dcesrv_assoc_group_new(context, call->conn->dce_ctx);
770                 }
771                 if (context->assoc_group == NULL) {
772                         talloc_free(context);
773                         return dcesrv_bind_nak(call, 0);
774                 }
775                 context->private_data = NULL;
776                 DLIST_ADD(call->conn->contexts, context);
777                 call->context = context;
778                 talloc_set_destructor(context, dcesrv_connection_context_destructor);
779
780                 dcesrv_prepare_context_auth(call);
781
782                 status = iface->bind(call, iface, if_version);
783                 if (!NT_STATUS_IS_OK(status)) {
784                         char *uuid_str = GUID_string(call, &uuid);
785                         DEBUG(2,("Request for dcerpc interface %s/%d rejected: %s\n",
786                                  uuid_str, if_version, nt_errstr(status)));
787                         talloc_free(uuid_str);
788                         /* we don't want to trigger the iface->unbind() hook */
789                         context->iface = NULL;
790                         talloc_free(call->context);
791                         call->context = NULL;
792                         return dcesrv_bind_nak(call, 0);
793                 }
794         }
795
796         if ((call->pkt.pfc_flags & DCERPC_PFC_FLAG_CONC_MPX) &&
797             (call->state_flags & DCESRV_CALL_STATE_FLAG_MULTIPLEXED)) {
798                 call->context->conn->state_flags |= DCESRV_CALL_STATE_FLAG_MULTIPLEXED;
799                 extra_flags |= DCERPC_PFC_FLAG_CONC_MPX;
800         }
801
802         if (call->state_flags & DCESRV_CALL_STATE_FLAG_PROCESS_PENDING_CALL) {
803                 call->context->conn->state_flags |= DCESRV_CALL_STATE_FLAG_PROCESS_PENDING_CALL;
804         }
805
806         /* handle any authentication that is being requested */
807         if (!dcesrv_auth_bind(call)) {
808                 talloc_free(call->context);
809                 call->context = NULL;
810                 return dcesrv_bind_nak(call, DCERPC_BIND_REASON_INVALID_AUTH_TYPE);
811         }
812
813         /* setup a bind_ack */
814         dcesrv_init_hdr(&pkt, lpcfg_rpc_big_endian(call->conn->dce_ctx->lp_ctx));
815         pkt.auth_length = 0;
816         pkt.call_id = call->pkt.call_id;
817         pkt.ptype = DCERPC_PKT_BIND_ACK;
818         pkt.pfc_flags = DCERPC_PFC_FLAG_FIRST | DCERPC_PFC_FLAG_LAST | extra_flags;
819         pkt.u.bind_ack.max_xmit_frag = call->conn->max_xmit_frag;
820         pkt.u.bind_ack.max_recv_frag = call->conn->max_recv_frag;
821
822         /*
823           make it possible for iface->bind() to specify the assoc_group_id
824           This helps the openchange mapiproxy plugin to work correctly.
825           
826           metze
827         */
828         if (call->context) {
829                 pkt.u.bind_ack.assoc_group_id = call->context->assoc_group->id;
830         } else {
831                 pkt.u.bind_ack.assoc_group_id = DUMMY_ASSOC_GROUP;
832         }
833
834         if (iface) {
835                 endpoint = dcerpc_binding_get_string_option(
836                                 call->conn->endpoint->ep_description,
837                                 "endpoint");
838         }
839
840         if (endpoint == NULL) {
841                 endpoint = "";
842         }
843
844         if (strncasecmp(endpoint, "\\pipe\\", 6) == 0) {
845                 /*
846                  * TODO: check if this is really needed
847                  *
848                  * Or if we should fix this in our idl files.
849                  */
850                 ep_prefix = "\\PIPE\\";
851                 endpoint += 6;
852         }
853
854         pkt.u.bind_ack.secondary_address = talloc_asprintf(call, "%s%s",
855                                                            ep_prefix,
856                                                            endpoint);
857         if (pkt.u.bind_ack.secondary_address == NULL) {
858                 TALLOC_FREE(call->context);
859                 return NT_STATUS_NO_MEMORY;
860         }
861         pkt.u.bind_ack.num_results = 1;
862         pkt.u.bind_ack.ctx_list = talloc_zero(call, struct dcerpc_ack_ctx);
863         if (!pkt.u.bind_ack.ctx_list) {
864                 talloc_free(call->context);
865                 call->context = NULL;
866                 return NT_STATUS_NO_MEMORY;
867         }
868         pkt.u.bind_ack.ctx_list[0].result = result;
869         pkt.u.bind_ack.ctx_list[0].reason.value = reason;
870         pkt.u.bind_ack.ctx_list[0].syntax = ndr_transfer_syntax_ndr;
871         pkt.u.bind_ack.auth_info = data_blob(NULL, 0);
872
873         status = dcesrv_auth_bind_ack(call, &pkt);
874         if (!NT_STATUS_IS_OK(status)) {
875                 talloc_free(call->context);
876                 call->context = NULL;
877                 return dcesrv_bind_nak(call, 0);
878         }
879
880         rep = talloc_zero(call, struct data_blob_list_item);
881         if (!rep) {
882                 talloc_free(call->context);
883                 call->context = NULL;
884                 return NT_STATUS_NO_MEMORY;
885         }
886
887         status = ncacn_push_auth(&rep->blob, call, &pkt,
888                                  call->out_auth_info);
889         if (!NT_STATUS_IS_OK(status)) {
890                 talloc_free(call->context);
891                 call->context = NULL;
892                 return status;
893         }
894
895         dcerpc_set_frag_length(&rep->blob, rep->blob.length);
896
897         DLIST_ADD_END(call->replies, rep);
898         dcesrv_call_set_list(call, DCESRV_LIST_CALL_LIST);
899
900         if (call->conn->call_list && call->conn->call_list->replies) {
901                 if (call->conn->transport.report_output_data) {
902                         call->conn->transport.report_output_data(call->conn);
903                 }
904         }
905
906         return NT_STATUS_OK;
907 }
908
909
910 /*
911   handle a auth3 request
912 */
913 static NTSTATUS dcesrv_auth3(struct dcesrv_call_state *call)
914 {
915         NTSTATUS status;
916
917         if (!call->conn->allow_auth3) {
918                 return dcesrv_fault_disconnect(call, DCERPC_NCA_S_PROTO_ERROR);
919         }
920
921         if (call->conn->auth_state.auth_finished) {
922                 return dcesrv_fault_disconnect(call, DCERPC_NCA_S_PROTO_ERROR);
923         }
924
925         status = dcerpc_verify_ncacn_packet_header(&call->pkt,
926                         DCERPC_PKT_AUTH3,
927                         call->pkt.u.auth3.auth_info.length,
928                         0, /* required flags */
929                         DCERPC_PFC_FLAG_FIRST |
930                         DCERPC_PFC_FLAG_LAST |
931                         DCERPC_PFC_FLAG_SUPPORT_HEADER_SIGN |
932                         0x08 | /* this is not defined, but should be ignored */
933                         DCERPC_PFC_FLAG_CONC_MPX |
934                         DCERPC_PFC_FLAG_DID_NOT_EXECUTE |
935                         DCERPC_PFC_FLAG_MAYBE |
936                         DCERPC_PFC_FLAG_OBJECT_UUID);
937         if (!NT_STATUS_IS_OK(status)) {
938                 return dcesrv_fault_disconnect(call, DCERPC_NCA_S_PROTO_ERROR);
939         }
940
941         /* handle the auth3 in the auth code */
942         if (!dcesrv_auth_auth3(call)) {
943                 return dcesrv_fault(call, DCERPC_FAULT_OTHER);
944         }
945
946         talloc_free(call);
947
948         /* we don't send a reply to a auth3 request, except by a
949            fault */
950         return NT_STATUS_OK;
951 }
952
953
954 /*
955   handle a bind request
956 */
957 static NTSTATUS dcesrv_alter_new_context(struct dcesrv_call_state *call, uint32_t context_id)
958 {
959         uint32_t if_version, transfer_syntax_version;
960         struct dcesrv_connection_context *context;
961         const struct dcesrv_interface *iface;
962         struct GUID uuid, *transfer_syntax_uuid;
963         NTSTATUS status;
964
965         if_version = call->pkt.u.alter.ctx_list[0].abstract_syntax.if_version;
966         uuid = call->pkt.u.alter.ctx_list[0].abstract_syntax.uuid;
967
968         transfer_syntax_version = call->pkt.u.alter.ctx_list[0].transfer_syntaxes[0].if_version;
969         transfer_syntax_uuid = &call->pkt.u.alter.ctx_list[0].transfer_syntaxes[0].uuid;
970         if (!GUID_equal(transfer_syntax_uuid, &ndr_transfer_syntax_ndr.uuid) ||
971             ndr_transfer_syntax_ndr.if_version != transfer_syntax_version) {
972                 /* we only do NDR encoded dcerpc */
973                 return NT_STATUS_RPC_PROTSEQ_NOT_SUPPORTED;
974         }
975
976         iface = find_interface_by_uuid(call->conn->endpoint, &uuid, if_version);
977         if (iface == NULL) {
978                 char *uuid_str = GUID_string(call, &uuid);
979                 DEBUG(2,("Request for unknown dcerpc interface %s/%d\n", uuid_str, if_version));
980                 talloc_free(uuid_str);
981                 return NT_STATUS_RPC_PROTSEQ_NOT_SUPPORTED;
982         }
983
984         /* add this context to the list of available context_ids */
985         context = talloc_zero(call->conn, struct dcesrv_connection_context);
986         if (context == NULL) {
987                 return NT_STATUS_NO_MEMORY;
988         }
989         context->conn = call->conn;
990         context->iface = iface;
991         context->context_id = context_id;
992         if (call->pkt.u.alter.assoc_group_id != 0) {
993                 context->assoc_group = dcesrv_assoc_group_reference(context,
994                                                                     call->conn->dce_ctx, 
995                                                                     call->pkt.u.alter.assoc_group_id);
996         } else {
997                 context->assoc_group = dcesrv_assoc_group_new(context, call->conn->dce_ctx);
998         }
999         if (context->assoc_group == NULL) {
1000                 talloc_free(context);
1001                 call->context = NULL;
1002                 return NT_STATUS_NO_MEMORY;
1003         }
1004         context->private_data = NULL;
1005         DLIST_ADD(call->conn->contexts, context);
1006         call->context = context;
1007         talloc_set_destructor(context, dcesrv_connection_context_destructor);
1008
1009         dcesrv_prepare_context_auth(call);
1010
1011         status = iface->bind(call, iface, if_version);
1012         if (!NT_STATUS_IS_OK(status)) {
1013                 /* we don't want to trigger the iface->unbind() hook */
1014                 context->iface = NULL;
1015                 talloc_free(context);
1016                 call->context = NULL;
1017                 return status;
1018         }
1019
1020         return NT_STATUS_OK;
1021 }
1022
1023 /* setup and send an alter_resp */
1024 static NTSTATUS dcesrv_alter_resp(struct dcesrv_call_state *call,
1025                                 uint32_t result,
1026                                 uint32_t reason)
1027 {
1028         struct ncacn_packet pkt;
1029         uint32_t extra_flags = 0;
1030         struct data_blob_list_item *rep = NULL;
1031         NTSTATUS status;
1032
1033         dcesrv_init_hdr(&pkt, lpcfg_rpc_big_endian(call->conn->dce_ctx->lp_ctx));
1034         pkt.auth_length = 0;
1035         pkt.call_id = call->pkt.call_id;
1036         pkt.ptype = DCERPC_PKT_ALTER_RESP;
1037         if (result == 0) {
1038                 if ((call->pkt.pfc_flags & DCERPC_PFC_FLAG_CONC_MPX) &&
1039                                 call->context->conn->state_flags &
1040                                         DCESRV_CALL_STATE_FLAG_MULTIPLEXED) {
1041                         extra_flags |= DCERPC_PFC_FLAG_CONC_MPX;
1042                 }
1043                 if (call->state_flags & DCESRV_CALL_STATE_FLAG_PROCESS_PENDING_CALL) {
1044                         call->context->conn->state_flags |=
1045                                 DCESRV_CALL_STATE_FLAG_PROCESS_PENDING_CALL;
1046                 }
1047         }
1048         pkt.pfc_flags = DCERPC_PFC_FLAG_FIRST | DCERPC_PFC_FLAG_LAST | extra_flags;
1049         pkt.u.alter_resp.max_xmit_frag = call->conn->max_xmit_frag;
1050         pkt.u.alter_resp.max_recv_frag = call->conn->max_recv_frag;
1051         if (result == 0) {
1052                 pkt.u.alter_resp.assoc_group_id = call->context->assoc_group->id;
1053         } else {
1054                 pkt.u.alter_resp.assoc_group_id = 0;
1055         }
1056         pkt.u.alter_resp.num_results = 1;
1057         pkt.u.alter_resp.ctx_list = talloc_zero(call, struct dcerpc_ack_ctx);
1058         if (!pkt.u.alter_resp.ctx_list) {
1059                 return NT_STATUS_NO_MEMORY;
1060         }
1061         pkt.u.alter_resp.ctx_list[0].result = result;
1062         pkt.u.alter_resp.ctx_list[0].reason.value = reason;
1063         pkt.u.alter_resp.ctx_list[0].syntax = ndr_transfer_syntax_ndr;
1064         pkt.u.alter_resp.auth_info = data_blob(NULL, 0);
1065         pkt.u.alter_resp.secondary_address = "";
1066
1067         status = dcesrv_auth_alter_ack(call, &pkt);
1068         if (!NT_STATUS_IS_OK(status)) {
1069                 if (NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)
1070                     || NT_STATUS_EQUAL(status, NT_STATUS_LOGON_FAILURE)
1071                     || NT_STATUS_EQUAL(status, NT_STATUS_NO_SUCH_USER)
1072                     || NT_STATUS_EQUAL(status, NT_STATUS_WRONG_PASSWORD)) {
1073                         return dcesrv_fault(call, DCERPC_FAULT_ACCESS_DENIED);
1074                 }
1075                 return dcesrv_fault(call, 0);
1076         }
1077
1078         rep = talloc_zero(call, struct data_blob_list_item);
1079         if (!rep) {
1080                 return NT_STATUS_NO_MEMORY;
1081         }
1082
1083         status = ncacn_push_auth(&rep->blob, call, &pkt, call->out_auth_info);
1084         if (!NT_STATUS_IS_OK(status)) {
1085                 return status;
1086         }
1087
1088         dcerpc_set_frag_length(&rep->blob, rep->blob.length);
1089
1090         DLIST_ADD_END(call->replies, rep);
1091         dcesrv_call_set_list(call, DCESRV_LIST_CALL_LIST);
1092
1093         if (call->conn->call_list && call->conn->call_list->replies) {
1094                 if (call->conn->transport.report_output_data) {
1095                         call->conn->transport.report_output_data(call->conn);
1096                 }
1097         }
1098
1099         return NT_STATUS_OK;
1100 }
1101
1102 /*
1103   handle a alter context request
1104 */
1105 static NTSTATUS dcesrv_alter(struct dcesrv_call_state *call)
1106 {
1107         NTSTATUS status;
1108         uint32_t context_id;
1109
1110         if (!call->conn->allow_alter) {
1111                 return dcesrv_fault_disconnect(call, DCERPC_NCA_S_PROTO_ERROR);
1112         }
1113
1114         status = dcerpc_verify_ncacn_packet_header(&call->pkt,
1115                         DCERPC_PKT_ALTER,
1116                         call->pkt.u.alter.auth_info.length,
1117                         0, /* required flags */
1118                         DCERPC_PFC_FLAG_FIRST |
1119                         DCERPC_PFC_FLAG_LAST |
1120                         DCERPC_PFC_FLAG_SUPPORT_HEADER_SIGN |
1121                         0x08 | /* this is not defined, but should be ignored */
1122                         DCERPC_PFC_FLAG_CONC_MPX |
1123                         DCERPC_PFC_FLAG_DID_NOT_EXECUTE |
1124                         DCERPC_PFC_FLAG_MAYBE |
1125                         DCERPC_PFC_FLAG_OBJECT_UUID);
1126         if (!NT_STATUS_IS_OK(status)) {
1127                 return dcesrv_fault_disconnect(call, DCERPC_NCA_S_PROTO_ERROR);
1128         }
1129
1130         /* handle any authentication that is being requested */
1131         if (!dcesrv_auth_alter(call)) {
1132                 /* TODO: work out the right reject code */
1133                 return dcesrv_alter_resp(call,
1134                                 DCERPC_BIND_PROVIDER_REJECT,
1135                                 DCERPC_BIND_REASON_ASYNTAX);
1136         }
1137
1138         context_id = call->pkt.u.alter.ctx_list[0].context_id;
1139
1140         /* see if they are asking for a new interface */
1141         call->context = dcesrv_find_context(call->conn, context_id);
1142         if (!call->context) {
1143                 status = dcesrv_alter_new_context(call, context_id);
1144                 if (!NT_STATUS_IS_OK(status)) {
1145                         return dcesrv_alter_resp(call,
1146                                 DCERPC_BIND_PROVIDER_REJECT,
1147                                 DCERPC_BIND_REASON_ASYNTAX);
1148                 }
1149         }
1150
1151         if (call->pkt.u.alter.assoc_group_id != 0 &&
1152             lpcfg_parm_bool(call->conn->dce_ctx->lp_ctx, NULL, "dcesrv","assoc group checking", true) &&
1153             call->pkt.u.alter.assoc_group_id != call->context->assoc_group->id) {
1154                 DEBUG(0,(__location__ ": Failed attempt to use new assoc_group in alter context (0x%08x 0x%08x)\n",
1155                          call->context->assoc_group->id, call->pkt.u.alter.assoc_group_id));
1156                 /* TODO: can they ask for a new association group? */
1157                 return dcesrv_alter_resp(call,
1158                                 DCERPC_BIND_PROVIDER_REJECT,
1159                                 DCERPC_BIND_REASON_ASYNTAX);
1160         }
1161
1162         return dcesrv_alter_resp(call,
1163                                 DCERPC_BIND_ACK_RESULT_ACCEPTANCE,
1164                                 DCERPC_BIND_ACK_REASON_NOT_SPECIFIED);
1165 }
1166
1167 /*
1168   possibly save the call for inspection with ndrdump
1169  */
1170 static void dcesrv_save_call(struct dcesrv_call_state *call, const char *why)
1171 {
1172 #ifdef DEVELOPER
1173         char *fname;
1174         const char *dump_dir;
1175         dump_dir = lpcfg_parm_string(call->conn->dce_ctx->lp_ctx, NULL, "dcesrv", "stubs directory");
1176         if (!dump_dir) {
1177                 return;
1178         }
1179         fname = talloc_asprintf(call, "%s/RPC-%s-%u-%s.dat",
1180                                 dump_dir,
1181                                 call->context->iface->name,
1182                                 call->pkt.u.request.opnum,
1183                                 why);
1184         if (file_save(fname, call->pkt.u.request.stub_and_verifier.data, call->pkt.u.request.stub_and_verifier.length)) {
1185                 DEBUG(0,("RPC SAVED %s\n", fname));
1186         }
1187         talloc_free(fname);
1188 #endif
1189 }
1190
1191 static NTSTATUS dcesrv_check_verification_trailer(struct dcesrv_call_state *call)
1192 {
1193         TALLOC_CTX *frame = talloc_stackframe();
1194         const uint32_t bitmask1 = call->conn->auth_state.client_hdr_signing ?
1195                 DCERPC_SEC_VT_CLIENT_SUPPORTS_HEADER_SIGNING : 0;
1196         const struct dcerpc_sec_vt_pcontext pcontext = {
1197                 .abstract_syntax = call->context->iface->syntax_id,
1198                 .transfer_syntax = ndr_transfer_syntax_ndr,
1199         };
1200         const struct dcerpc_sec_vt_header2 header2 =
1201                 dcerpc_sec_vt_header2_from_ncacn_packet(&call->pkt);
1202         enum ndr_err_code ndr_err;
1203         struct dcerpc_sec_verification_trailer *vt = NULL;
1204         NTSTATUS status = NT_STATUS_OK;
1205         bool ok;
1206
1207         SMB_ASSERT(call->pkt.ptype == DCERPC_PKT_REQUEST);
1208
1209         ndr_err = ndr_pop_dcerpc_sec_verification_trailer(call->ndr_pull,
1210                                                           frame, &vt);
1211         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
1212                 status = ndr_map_error2ntstatus(ndr_err);
1213                 goto done;
1214         }
1215
1216         ok = dcerpc_sec_verification_trailer_check(vt, &bitmask1,
1217                                                    &pcontext, &header2);
1218         if (!ok) {
1219                 status = NT_STATUS_ACCESS_DENIED;
1220                 goto done;
1221         }
1222 done:
1223         TALLOC_FREE(frame);
1224         return status;
1225 }
1226
1227 /*
1228   handle a dcerpc request packet
1229 */
1230 static NTSTATUS dcesrv_request(struct dcesrv_call_state *call)
1231 {
1232         const struct dcesrv_endpoint *endpoint = call->conn->endpoint;
1233         enum dcerpc_transport_t transport =
1234                 dcerpc_binding_get_transport(endpoint->ep_description);
1235         struct ndr_pull *pull;
1236         NTSTATUS status;
1237         struct dcesrv_connection_context *context;
1238
1239         if (!call->conn->allow_request) {
1240                 return dcesrv_fault_disconnect(call, DCERPC_NCA_S_PROTO_ERROR);
1241         }
1242
1243         /* if authenticated, and the mech we use can't do async replies, don't use them... */
1244         if (call->conn->auth_state.gensec_security && 
1245             !gensec_have_feature(call->conn->auth_state.gensec_security, GENSEC_FEATURE_ASYNC_REPLIES)) {
1246                 call->state_flags &= ~DCESRV_CALL_STATE_FLAG_MAY_ASYNC;
1247         }
1248
1249         context = dcesrv_find_context(call->conn, call->pkt.u.request.context_id);
1250         if (context == NULL) {
1251                 return dcesrv_fault(call, DCERPC_FAULT_UNK_IF);
1252         }
1253
1254         switch (call->conn->auth_state.auth_level) {
1255         case DCERPC_AUTH_LEVEL_NONE:
1256         case DCERPC_AUTH_LEVEL_INTEGRITY:
1257         case DCERPC_AUTH_LEVEL_PRIVACY:
1258                 break;
1259         default:
1260                 if (!context->allow_connect) {
1261                         char *addr;
1262
1263                         addr = tsocket_address_string(call->conn->remote_address,
1264                                                       call);
1265
1266                         DEBUG(2, ("%s: restrict auth_level_connect access "
1267                                   "to [%s] with auth[type=0x%x,level=0x%x] "
1268                                   "on [%s] from [%s]\n",
1269                                   __func__, context->iface->name,
1270                                   call->conn->auth_state.auth_type,
1271                                   call->conn->auth_state.auth_level,
1272                                   derpc_transport_string_by_transport(transport),
1273                                   addr));
1274                         return dcesrv_fault(call, DCERPC_FAULT_ACCESS_DENIED);
1275                 }
1276                 break;
1277         }
1278
1279         if (call->conn->auth_state.auth_level < context->min_auth_level) {
1280                 char *addr;
1281
1282                 addr = tsocket_address_string(call->conn->remote_address, call);
1283
1284                 DEBUG(2, ("%s: restrict access by min_auth_level[0x%x] "
1285                           "to [%s] with auth[type=0x%x,level=0x%x] "
1286                           "on [%s] from [%s]\n",
1287                           __func__,
1288                           context->min_auth_level,
1289                           context->iface->name,
1290                           call->conn->auth_state.auth_type,
1291                           call->conn->auth_state.auth_level,
1292                           derpc_transport_string_by_transport(transport),
1293                           addr));
1294                 return dcesrv_fault(call, DCERPC_FAULT_ACCESS_DENIED);
1295         }
1296
1297         pull = ndr_pull_init_blob(&call->pkt.u.request.stub_and_verifier, call);
1298         NT_STATUS_HAVE_NO_MEMORY(pull);
1299
1300         pull->flags |= LIBNDR_FLAG_REF_ALLOC;
1301
1302         call->context   = context;
1303         call->ndr_pull  = pull;
1304
1305         if (!(call->pkt.drep[0] & DCERPC_DREP_LE)) {
1306                 pull->flags |= LIBNDR_FLAG_BIGENDIAN;
1307         }
1308
1309         status = dcesrv_check_verification_trailer(call);
1310         if (!NT_STATUS_IS_OK(status)) {
1311                 uint32_t faultcode = DCERPC_FAULT_OTHER;
1312                 if (NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
1313                         faultcode = DCERPC_FAULT_ACCESS_DENIED;
1314                 }
1315                 DEBUG(10, ("dcesrv_check_verification_trailer failed: %s\n",
1316                            nt_errstr(status)));
1317                 return dcesrv_fault(call, faultcode);
1318         }
1319
1320         /* unravel the NDR for the packet */
1321         status = context->iface->ndr_pull(call, call, pull, &call->r);
1322         if (!NT_STATUS_IS_OK(status)) {
1323                 if (call->fault_code == DCERPC_FAULT_OP_RNG_ERROR) {
1324                         /* we got an unknown call */
1325                         DEBUG(3,(__location__ ": Unknown RPC call %u on %s\n",
1326                                  call->pkt.u.request.opnum, context->iface->name));
1327                         dcesrv_save_call(call, "unknown");
1328                 } else {
1329                         dcesrv_save_call(call, "pullfail");
1330                 }
1331                 return dcesrv_fault(call, call->fault_code);
1332         }
1333
1334         if (pull->offset != pull->data_size) {
1335                 dcesrv_save_call(call, "extrabytes");
1336                 DEBUG(3,("Warning: %d extra bytes in incoming RPC request\n", 
1337                          pull->data_size - pull->offset));
1338         }
1339
1340         /* call the dispatch function */
1341         status = context->iface->dispatch(call, call, call->r);
1342         if (!NT_STATUS_IS_OK(status)) {
1343                 DEBUG(5,("dcerpc fault in call %s:%02x - %s\n",
1344                          context->iface->name, 
1345                          call->pkt.u.request.opnum,
1346                          dcerpc_errstr(pull, call->fault_code)));
1347                 return dcesrv_fault(call, call->fault_code);
1348         }
1349
1350         /* add the call to the pending list */
1351         dcesrv_call_set_list(call, DCESRV_LIST_PENDING_CALL_LIST);
1352
1353         if (call->state_flags & DCESRV_CALL_STATE_FLAG_ASYNC) {
1354                 return NT_STATUS_OK;
1355         }
1356
1357         return dcesrv_reply(call);
1358 }
1359
1360
1361 /*
1362   remove the call from the right list when freed
1363  */
1364 static int dcesrv_call_dequeue(struct dcesrv_call_state *call)
1365 {
1366         dcesrv_call_set_list(call, DCESRV_LIST_NONE);
1367         return 0;
1368 }
1369
1370 _PUBLIC_ const struct tsocket_address *dcesrv_connection_get_local_address(struct dcesrv_connection *conn)
1371 {
1372         return conn->local_address;
1373 }
1374
1375 _PUBLIC_ const struct tsocket_address *dcesrv_connection_get_remote_address(struct dcesrv_connection *conn)
1376 {
1377         return conn->remote_address;
1378 }
1379
1380 /*
1381   process some input to a dcerpc endpoint server.
1382 */
1383 static NTSTATUS dcesrv_process_ncacn_packet(struct dcesrv_connection *dce_conn,
1384                                             struct ncacn_packet *pkt,
1385                                             DATA_BLOB blob)
1386 {
1387         NTSTATUS status;
1388         struct dcesrv_call_state *call;
1389
1390         call = talloc_zero(dce_conn, struct dcesrv_call_state);
1391         if (!call) {
1392                 data_blob_free(&blob);
1393                 talloc_free(pkt);
1394                 return NT_STATUS_NO_MEMORY;
1395         }
1396         call->conn              = dce_conn;
1397         call->event_ctx         = dce_conn->event_ctx;
1398         call->msg_ctx           = dce_conn->msg_ctx;
1399         call->state_flags       = call->conn->state_flags;
1400         call->time              = timeval_current();
1401         call->list              = DCESRV_LIST_NONE;
1402
1403         talloc_steal(call, pkt);
1404         talloc_steal(call, blob.data);
1405         call->pkt = *pkt;
1406
1407         talloc_set_destructor(call, dcesrv_call_dequeue);
1408
1409         if (call->conn->allow_bind) {
1410                 /*
1411                  * Only one bind is possible per connection
1412                  */
1413                 call->conn->allow_bind = false;
1414                 return dcesrv_bind(call);
1415         }
1416
1417         /* we have to check the signing here, before combining the
1418            pdus */
1419         if (call->pkt.ptype == DCERPC_PKT_REQUEST) {
1420                 if (!call->conn->allow_request) {
1421                         return dcesrv_fault_disconnect(call,
1422                                         DCERPC_NCA_S_PROTO_ERROR);
1423                 }
1424
1425                 status = dcerpc_verify_ncacn_packet_header(&call->pkt,
1426                                 DCERPC_PKT_REQUEST,
1427                                 call->pkt.u.request.stub_and_verifier.length,
1428                                 0, /* required_flags */
1429                                 DCERPC_PFC_FLAG_FIRST |
1430                                 DCERPC_PFC_FLAG_LAST |
1431                                 DCERPC_PFC_FLAG_PENDING_CANCEL |
1432                                 0x08 | /* this is not defined, but should be ignored */
1433                                 DCERPC_PFC_FLAG_CONC_MPX |
1434                                 DCERPC_PFC_FLAG_DID_NOT_EXECUTE |
1435                                 DCERPC_PFC_FLAG_MAYBE |
1436                                 DCERPC_PFC_FLAG_OBJECT_UUID);
1437                 if (!NT_STATUS_IS_OK(status)) {
1438                         return dcesrv_fault_disconnect(call,
1439                                         DCERPC_NCA_S_PROTO_ERROR);
1440                 }
1441
1442                 if (!dcesrv_auth_request(call, &blob)) {
1443                         return dcesrv_fault(call, DCERPC_FAULT_ACCESS_DENIED);
1444                 }
1445         }
1446
1447         /* see if this is a continued packet */
1448         if (call->pkt.ptype == DCERPC_PKT_REQUEST &&
1449             !(call->pkt.pfc_flags & DCERPC_PFC_FLAG_FIRST)) {
1450                 struct dcesrv_call_state *call2 = call;
1451                 uint32_t alloc_size;
1452
1453                 /* this is a continuation of an existing call - find the call
1454                    then tack it on the end */
1455                 call = dcesrv_find_fragmented_call(dce_conn, call2->pkt.call_id);
1456                 if (!call) {
1457                         return dcesrv_fault_disconnect(call2,
1458                                         DCERPC_NCA_S_PROTO_ERROR);
1459                 }
1460
1461                 if (call->pkt.ptype != call2->pkt.ptype) {
1462                         /* trying to play silly buggers are we? */
1463                         return dcesrv_fault_disconnect(call,
1464                                         DCERPC_NCA_S_PROTO_ERROR);
1465                 }
1466                 if (memcmp(call->pkt.drep, call2->pkt.drep, sizeof(pkt->drep)) != 0) {
1467                         return dcesrv_fault_disconnect(call,
1468                                         DCERPC_NCA_S_PROTO_ERROR);
1469                 }
1470                 if (call->pkt.call_id != call2->pkt.call_id) {
1471                         return dcesrv_fault_disconnect(call,
1472                                         DCERPC_NCA_S_PROTO_ERROR);
1473                 }
1474                 if (call->pkt.u.request.context_id != call2->pkt.u.request.context_id)  {
1475                         return dcesrv_fault_disconnect(call,
1476                                         DCERPC_NCA_S_PROTO_ERROR);
1477                 }
1478                 if (call->pkt.u.request.opnum != call2->pkt.u.request.opnum)  {
1479                         return dcesrv_fault_disconnect(call,
1480                                         DCERPC_NCA_S_PROTO_ERROR);
1481                 }
1482
1483                 alloc_size = call->pkt.u.request.stub_and_verifier.length +
1484                         call2->pkt.u.request.stub_and_verifier.length;
1485                 if (call->pkt.u.request.alloc_hint > alloc_size) {
1486                         alloc_size = call->pkt.u.request.alloc_hint;
1487                 }
1488
1489                 call->pkt.u.request.stub_and_verifier.data = 
1490                         talloc_realloc(call, 
1491                                        call->pkt.u.request.stub_and_verifier.data, 
1492                                        uint8_t, alloc_size);
1493                 if (!call->pkt.u.request.stub_and_verifier.data) {
1494                         return dcesrv_fault(call2, DCERPC_FAULT_OTHER);
1495                 }
1496                 memcpy(call->pkt.u.request.stub_and_verifier.data +
1497                        call->pkt.u.request.stub_and_verifier.length,
1498                        call2->pkt.u.request.stub_and_verifier.data,
1499                        call2->pkt.u.request.stub_and_verifier.length);
1500                 call->pkt.u.request.stub_and_verifier.length += 
1501                         call2->pkt.u.request.stub_and_verifier.length;
1502
1503                 call->pkt.pfc_flags |= (call2->pkt.pfc_flags & DCERPC_PFC_FLAG_LAST);
1504
1505                 talloc_free(call2);
1506         }
1507
1508         /* this may not be the last pdu in the chain - if its isn't then
1509            just put it on the incoming_fragmented_call_list and wait for the rest */
1510         if (call->pkt.ptype == DCERPC_PKT_REQUEST &&
1511             !(call->pkt.pfc_flags & DCERPC_PFC_FLAG_LAST)) {
1512                 dcesrv_call_set_list(call, DCESRV_LIST_FRAGMENTED_CALL_LIST);
1513                 return NT_STATUS_OK;
1514         } 
1515         
1516         /* This removes any fragments we may have had stashed away */
1517         dcesrv_call_set_list(call, DCESRV_LIST_NONE);
1518
1519         switch (call->pkt.ptype) {
1520         case DCERPC_PKT_BIND:
1521                 status = dcesrv_bind_nak(call,
1522                         DCERPC_BIND_NAK_REASON_NOT_SPECIFIED);
1523                 break;
1524         case DCERPC_PKT_AUTH3:
1525                 status = dcesrv_auth3(call);
1526                 break;
1527         case DCERPC_PKT_ALTER:
1528                 status = dcesrv_alter(call);
1529                 break;
1530         case DCERPC_PKT_REQUEST:
1531                 status = dcesrv_request(call);
1532                 break;
1533         default:
1534                 status = dcesrv_fault_disconnect(call, DCERPC_NCA_S_PROTO_ERROR);
1535                 break;
1536         }
1537
1538         /* if we are going to be sending a reply then add
1539            it to the list of pending calls. We add it to the end to keep the call
1540            list in the order we will answer */
1541         if (!NT_STATUS_IS_OK(status)) {
1542                 talloc_free(call);
1543         }
1544
1545         return status;
1546 }
1547
1548 _PUBLIC_ NTSTATUS dcesrv_init_context(TALLOC_CTX *mem_ctx, 
1549                                       struct loadparm_context *lp_ctx,
1550                                       const char **endpoint_servers, struct dcesrv_context **_dce_ctx)
1551 {
1552         NTSTATUS status;
1553         struct dcesrv_context *dce_ctx;
1554         int i;
1555
1556         if (!endpoint_servers) {
1557                 DEBUG(0,("dcesrv_init_context: no endpoint servers configured\n"));
1558                 return NT_STATUS_INTERNAL_ERROR;
1559         }
1560
1561         dce_ctx = talloc_zero(mem_ctx, struct dcesrv_context);
1562         NT_STATUS_HAVE_NO_MEMORY(dce_ctx);
1563
1564         if (uid_wrapper_enabled()) {
1565                 setenv("UID_WRAPPER_MYUID", "1", 1);
1566         }
1567         dce_ctx->initial_euid = geteuid();
1568         if (uid_wrapper_enabled()) {
1569                 unsetenv("UID_WRAPPER_MYUID");
1570         }
1571
1572         dce_ctx->endpoint_list  = NULL;
1573         dce_ctx->lp_ctx = lp_ctx;
1574         dce_ctx->assoc_groups_idr = idr_init(dce_ctx);
1575         NT_STATUS_HAVE_NO_MEMORY(dce_ctx->assoc_groups_idr);
1576         dce_ctx->broken_connections = NULL;
1577
1578         for (i=0;endpoint_servers[i];i++) {
1579                 const struct dcesrv_endpoint_server *ep_server;
1580
1581                 ep_server = dcesrv_ep_server_byname(endpoint_servers[i]);
1582                 if (!ep_server) {
1583                         DEBUG(0,("dcesrv_init_context: failed to find endpoint server = '%s'\n", endpoint_servers[i]));
1584                         return NT_STATUS_INTERNAL_ERROR;
1585                 }
1586
1587                 status = ep_server->init_server(dce_ctx, ep_server);
1588                 if (!NT_STATUS_IS_OK(status)) {
1589                         DEBUG(0,("dcesrv_init_context: failed to init endpoint server = '%s': %s\n", endpoint_servers[i],
1590                                 nt_errstr(status)));
1591                         return status;
1592                 }
1593         }
1594
1595         *_dce_ctx = dce_ctx;
1596         return NT_STATUS_OK;
1597 }
1598
1599 /* the list of currently registered DCERPC endpoint servers.
1600  */
1601 static struct ep_server {
1602         struct dcesrv_endpoint_server *ep_server;
1603 } *ep_servers = NULL;
1604 static int num_ep_servers;
1605
1606 /*
1607   register a DCERPC endpoint server. 
1608
1609   The 'name' can be later used by other backends to find the operations
1610   structure for this backend.  
1611
1612   The 'type' is used to specify whether this is for a disk, printer or IPC$ share
1613 */
1614 _PUBLIC_ NTSTATUS dcerpc_register_ep_server(const void *_ep_server)
1615 {
1616         const struct dcesrv_endpoint_server *ep_server = _ep_server;
1617         
1618         if (dcesrv_ep_server_byname(ep_server->name) != NULL) {
1619                 /* its already registered! */
1620                 DEBUG(0,("DCERPC endpoint server '%s' already registered\n", 
1621                          ep_server->name));
1622                 return NT_STATUS_OBJECT_NAME_COLLISION;
1623         }
1624
1625         ep_servers = realloc_p(ep_servers, struct ep_server, num_ep_servers+1);
1626         if (!ep_servers) {
1627                 smb_panic("out of memory in dcerpc_register");
1628         }
1629
1630         ep_servers[num_ep_servers].ep_server = smb_xmemdup(ep_server, sizeof(*ep_server));
1631         ep_servers[num_ep_servers].ep_server->name = smb_xstrdup(ep_server->name);
1632
1633         num_ep_servers++;
1634
1635         DEBUG(3,("DCERPC endpoint server '%s' registered\n", 
1636                  ep_server->name));
1637
1638         return NT_STATUS_OK;
1639 }
1640
1641 /*
1642   return the operations structure for a named backend of the specified type
1643 */
1644 const struct dcesrv_endpoint_server *dcesrv_ep_server_byname(const char *name)
1645 {
1646         int i;
1647
1648         for (i=0;i<num_ep_servers;i++) {
1649                 if (strcmp(ep_servers[i].ep_server->name, name) == 0) {
1650                         return ep_servers[i].ep_server;
1651                 }
1652         }
1653
1654         return NULL;
1655 }
1656
1657 void dcerpc_server_init(struct loadparm_context *lp_ctx)
1658 {
1659         static bool initialized;
1660 #define _MODULE_PROTO(init) extern NTSTATUS init(void);
1661         STATIC_dcerpc_server_MODULES_PROTO;
1662         init_module_fn static_init[] = { STATIC_dcerpc_server_MODULES };
1663         init_module_fn *shared_init;
1664
1665         if (initialized) {
1666                 return;
1667         }
1668         initialized = true;
1669
1670         shared_init = load_samba_modules(NULL, "dcerpc_server");
1671
1672         run_init_functions(static_init);
1673         run_init_functions(shared_init);
1674
1675         talloc_free(shared_init);
1676 }
1677
1678 /*
1679   return the DCERPC module version, and the size of some critical types
1680   This can be used by endpoint server modules to either detect compilation errors, or provide
1681   multiple implementations for different smbd compilation options in one module
1682 */
1683 const struct dcesrv_critical_sizes *dcerpc_module_version(void)
1684 {
1685         static const struct dcesrv_critical_sizes critical_sizes = {
1686                 DCERPC_MODULE_VERSION,
1687                 sizeof(struct dcesrv_context),
1688                 sizeof(struct dcesrv_endpoint),
1689                 sizeof(struct dcesrv_endpoint_server),
1690                 sizeof(struct dcesrv_interface),
1691                 sizeof(struct dcesrv_if_list),
1692                 sizeof(struct dcesrv_connection),
1693                 sizeof(struct dcesrv_call_state),
1694                 sizeof(struct dcesrv_auth),
1695                 sizeof(struct dcesrv_handle)
1696         };
1697
1698         return &critical_sizes;
1699 }
1700
1701 static void dcesrv_terminate_connection(struct dcesrv_connection *dce_conn, const char *reason)
1702 {
1703         struct dcesrv_context *dce_ctx = dce_conn->dce_ctx;
1704         struct stream_connection *srv_conn;
1705         srv_conn = talloc_get_type(dce_conn->transport.private_data,
1706                                    struct stream_connection);
1707
1708         dce_conn->allow_bind = false;
1709         dce_conn->allow_auth3 = false;
1710         dce_conn->allow_alter = false;
1711         dce_conn->allow_request = false;
1712
1713         if (dce_conn->pending_call_list == NULL) {
1714                 char *full_reason = talloc_asprintf(dce_conn, "dcesrv: %s", reason);
1715
1716                 DLIST_REMOVE(dce_ctx->broken_connections, dce_conn);
1717                 stream_terminate_connection(srv_conn, full_reason ? full_reason : reason);
1718                 return;
1719         }
1720
1721         if (dce_conn->terminate != NULL) {
1722                 return;
1723         }
1724
1725         DEBUG(3,("dcesrv: terminating connection due to '%s' defered due to pending calls\n",
1726                  reason));
1727         dce_conn->terminate = talloc_strdup(dce_conn, reason);
1728         if (dce_conn->terminate == NULL) {
1729                 dce_conn->terminate = "dcesrv: defered terminating connection - no memory";
1730         }
1731         DLIST_ADD_END(dce_ctx->broken_connections, dce_conn);
1732 }
1733
1734 static void dcesrv_cleanup_broken_connections(struct dcesrv_context *dce_ctx)
1735 {
1736         struct dcesrv_connection *cur, *next;
1737
1738         next = dce_ctx->broken_connections;
1739         while (next != NULL) {
1740                 cur = next;
1741                 next = cur->next;
1742
1743                 if (cur->state_flags & DCESRV_CALL_STATE_FLAG_PROCESS_PENDING_CALL) {
1744                         struct dcesrv_connection_context *context_cur, *context_next;
1745
1746                         context_next = cur->contexts;
1747                         while (context_next != NULL) {
1748                                 context_cur = context_next;
1749                                 context_next = context_cur->next;
1750
1751                                 dcesrv_connection_context_destructor(context_cur);
1752                         }
1753                 }
1754
1755                 dcesrv_terminate_connection(cur, cur->terminate);
1756         }
1757 }
1758
1759 /* We need this include to be able to compile on some plateforms
1760  * (ie. freebsd 7.2) as it seems that <sys/uio.h> is not included
1761  * correctly.
1762  * It has to be that deep because otherwise we have a conflict on
1763  * const struct dcesrv_interface declaration.
1764  * This is mostly due to socket_wrapper defining #define bind swrap_bind
1765  * which conflict with the bind used before.
1766  */
1767 #include "system/network.h"
1768
1769 struct dcesrv_sock_reply_state {
1770         struct dcesrv_connection *dce_conn;
1771         struct dcesrv_call_state *call;
1772         struct iovec iov;
1773 };
1774
1775 static void dcesrv_sock_reply_done(struct tevent_req *subreq);
1776 static void dcesrv_call_terminate_step1(struct tevent_req *subreq);
1777
1778 static void dcesrv_sock_report_output_data(struct dcesrv_connection *dce_conn)
1779 {
1780         struct dcesrv_call_state *call;
1781
1782         call = dce_conn->call_list;
1783         if (!call || !call->replies) {
1784                 return;
1785         }
1786
1787         while (call->replies) {
1788                 struct data_blob_list_item *rep = call->replies;
1789                 struct dcesrv_sock_reply_state *substate;
1790                 struct tevent_req *subreq;
1791
1792                 substate = talloc_zero(call, struct dcesrv_sock_reply_state);
1793                 if (!substate) {
1794                         dcesrv_terminate_connection(dce_conn, "no memory");
1795                         return;
1796                 }
1797
1798                 substate->dce_conn = dce_conn;
1799                 substate->call = NULL;
1800
1801                 DLIST_REMOVE(call->replies, rep);
1802
1803                 if (call->replies == NULL && call->terminate_reason == NULL) {
1804                         substate->call = call;
1805                 }
1806
1807                 substate->iov.iov_base = (void *) rep->blob.data;
1808                 substate->iov.iov_len = rep->blob.length;
1809
1810                 subreq = tstream_writev_queue_send(substate,
1811                                                    dce_conn->event_ctx,
1812                                                    dce_conn->stream,
1813                                                    dce_conn->send_queue,
1814                                                    &substate->iov, 1);
1815                 if (!subreq) {
1816                         dcesrv_terminate_connection(dce_conn, "no memory");
1817                         return;
1818                 }
1819                 tevent_req_set_callback(subreq, dcesrv_sock_reply_done,
1820                                         substate);
1821         }
1822
1823         if (call->terminate_reason != NULL) {
1824                 struct tevent_req *subreq;
1825
1826                 subreq = tevent_queue_wait_send(call,
1827                                                 dce_conn->event_ctx,
1828                                                 dce_conn->send_queue);
1829                 if (!subreq) {
1830                         dcesrv_terminate_connection(dce_conn, __location__);
1831                         return;
1832                 }
1833                 tevent_req_set_callback(subreq, dcesrv_call_terminate_step1,
1834                                         call);
1835         }
1836
1837         DLIST_REMOVE(call->conn->call_list, call);
1838         call->list = DCESRV_LIST_NONE;
1839 }
1840
1841 static void dcesrv_sock_reply_done(struct tevent_req *subreq)
1842 {
1843         struct dcesrv_sock_reply_state *substate = tevent_req_callback_data(subreq,
1844                                                 struct dcesrv_sock_reply_state);
1845         int ret;
1846         int sys_errno;
1847         NTSTATUS status;
1848         struct dcesrv_call_state *call = substate->call;
1849
1850         ret = tstream_writev_queue_recv(subreq, &sys_errno);
1851         TALLOC_FREE(subreq);
1852         if (ret == -1) {
1853                 status = map_nt_error_from_unix_common(sys_errno);
1854                 dcesrv_terminate_connection(substate->dce_conn, nt_errstr(status));
1855                 return;
1856         }
1857
1858         talloc_free(substate);
1859         if (call) {
1860                 talloc_free(call);
1861         }
1862 }
1863
1864 static void dcesrv_call_terminate_step2(struct tevent_req *subreq);
1865
1866 static void dcesrv_call_terminate_step1(struct tevent_req *subreq)
1867 {
1868         struct dcesrv_call_state *call = tevent_req_callback_data(subreq,
1869                                                 struct dcesrv_call_state);
1870         bool ok;
1871         struct timeval tv;
1872
1873         /* make sure we stop send queue before removing subreq */
1874         tevent_queue_stop(call->conn->send_queue);
1875
1876         ok = tevent_queue_wait_recv(subreq);
1877         TALLOC_FREE(subreq);
1878         if (!ok) {
1879                 dcesrv_terminate_connection(call->conn, __location__);
1880                 return;
1881         }
1882
1883         /* disconnect after 200 usecs */
1884         tv = timeval_current_ofs_usec(200);
1885         subreq = tevent_wakeup_send(call, call->conn->event_ctx, tv);
1886         if (subreq == NULL) {
1887                 dcesrv_terminate_connection(call->conn, __location__);
1888                 return;
1889         }
1890         tevent_req_set_callback(subreq, dcesrv_call_terminate_step2,
1891                                 call);
1892 }
1893
1894 static void dcesrv_call_terminate_step2(struct tevent_req *subreq)
1895 {
1896         struct dcesrv_call_state *call = tevent_req_callback_data(subreq,
1897                                                 struct dcesrv_call_state);
1898         bool ok;
1899
1900         ok = tevent_wakeup_recv(subreq);
1901         TALLOC_FREE(subreq);
1902         if (!ok) {
1903                 dcesrv_terminate_connection(call->conn, __location__);
1904                 return;
1905         }
1906
1907         dcesrv_terminate_connection(call->conn, call->terminate_reason);
1908 }
1909
1910 struct dcesrv_socket_context {
1911         const struct dcesrv_endpoint *endpoint;
1912         struct dcesrv_context *dcesrv_ctx;
1913 };
1914
1915
1916 static void dcesrv_read_fragment_done(struct tevent_req *subreq);
1917
1918 static void dcesrv_sock_accept(struct stream_connection *srv_conn)
1919 {
1920         NTSTATUS status;
1921         struct dcesrv_socket_context *dcesrv_sock = 
1922                 talloc_get_type(srv_conn->private_data, struct dcesrv_socket_context);
1923         enum dcerpc_transport_t transport =
1924                 dcerpc_binding_get_transport(dcesrv_sock->endpoint->ep_description);
1925         struct dcesrv_connection *dcesrv_conn = NULL;
1926         int ret;
1927         struct tevent_req *subreq;
1928         struct loadparm_context *lp_ctx = dcesrv_sock->dcesrv_ctx->lp_ctx;
1929
1930         dcesrv_cleanup_broken_connections(dcesrv_sock->dcesrv_ctx);
1931
1932         if (!srv_conn->session_info) {
1933                 status = auth_anonymous_session_info(srv_conn,
1934                                                      lp_ctx,
1935                                                      &srv_conn->session_info);
1936                 if (!NT_STATUS_IS_OK(status)) {
1937                         DEBUG(0,("dcesrv_sock_accept: auth_anonymous_session_info failed: %s\n",
1938                                 nt_errstr(status)));
1939                         stream_terminate_connection(srv_conn, nt_errstr(status));
1940                         return;
1941                 }
1942         }
1943
1944         status = dcesrv_endpoint_connect(dcesrv_sock->dcesrv_ctx,
1945                                          srv_conn,
1946                                          dcesrv_sock->endpoint,
1947                                          srv_conn->session_info,
1948                                          srv_conn->event.ctx,
1949                                          srv_conn->msg_ctx,
1950                                          srv_conn->server_id,
1951                                          DCESRV_CALL_STATE_FLAG_MAY_ASYNC,
1952                                          &dcesrv_conn);
1953         if (!NT_STATUS_IS_OK(status)) {
1954                 DEBUG(0,("dcesrv_sock_accept: dcesrv_endpoint_connect failed: %s\n", 
1955                         nt_errstr(status)));
1956                 stream_terminate_connection(srv_conn, nt_errstr(status));
1957                 return;
1958         }
1959
1960         dcesrv_conn->transport.private_data             = srv_conn;
1961         dcesrv_conn->transport.report_output_data       = dcesrv_sock_report_output_data;
1962
1963         TALLOC_FREE(srv_conn->event.fde);
1964
1965         dcesrv_conn->send_queue = tevent_queue_create(dcesrv_conn, "dcesrv send queue");
1966         if (!dcesrv_conn->send_queue) {
1967                 status = NT_STATUS_NO_MEMORY;
1968                 DEBUG(0,("dcesrv_sock_accept: tevent_queue_create(%s)\n",
1969                         nt_errstr(status)));
1970                 stream_terminate_connection(srv_conn, nt_errstr(status));
1971                 return;
1972         }
1973
1974         if (transport == NCACN_NP) {
1975                 dcesrv_conn->auth_state.session_key = dcesrv_inherited_session_key;
1976                 dcesrv_conn->stream = talloc_move(dcesrv_conn,
1977                                                   &srv_conn->tstream);
1978         } else {
1979                 ret = tstream_bsd_existing_socket(dcesrv_conn,
1980                                                   socket_get_fd(srv_conn->socket),
1981                                                   &dcesrv_conn->stream);
1982                 if (ret == -1) {
1983                         status = map_nt_error_from_unix_common(errno);
1984                         DEBUG(0, ("dcesrv_sock_accept: "
1985                                   "failed to setup tstream: %s\n",
1986                                   nt_errstr(status)));
1987                         stream_terminate_connection(srv_conn, nt_errstr(status));
1988                         return;
1989                 }
1990                 socket_set_flags(srv_conn->socket, SOCKET_FLAG_NOCLOSE);
1991         }
1992
1993         dcesrv_conn->local_address = srv_conn->local_address;
1994         dcesrv_conn->remote_address = srv_conn->remote_address;
1995
1996         if (transport == NCALRPC) {
1997                 uid_t uid;
1998                 gid_t gid;
1999
2000                 ret = getpeereid(socket_get_fd(srv_conn->socket), &uid, &gid);
2001                 if (ret == -1) {
2002                         status = map_nt_error_from_unix_common(errno);
2003                         DEBUG(0, ("dcesrv_sock_accept: "
2004                                   "getpeereid() failed for NCALRPC: %s\n",
2005                                   nt_errstr(status)));
2006                         stream_terminate_connection(srv_conn, nt_errstr(status));
2007                         return;
2008                 }
2009                 if (uid == dcesrv_conn->dce_ctx->initial_euid) {
2010                         struct tsocket_address *r = NULL;
2011
2012                         ret = tsocket_address_unix_from_path(dcesrv_conn,
2013                                                              "/root/ncalrpc_as_system",
2014                                                              &r);
2015                         if (ret == -1) {
2016                                 status = map_nt_error_from_unix_common(errno);
2017                                 DEBUG(0, ("dcesrv_sock_accept: "
2018                                           "tsocket_address_unix_from_path() failed for NCALRPC: %s\n",
2019                                           nt_errstr(status)));
2020                                 stream_terminate_connection(srv_conn, nt_errstr(status));
2021                                 return;
2022                         }
2023                         dcesrv_conn->remote_address = r;
2024                 }
2025         }
2026
2027         srv_conn->private_data = dcesrv_conn;
2028
2029         irpc_add_name(srv_conn->msg_ctx, "rpc_server");
2030
2031         subreq = dcerpc_read_ncacn_packet_send(dcesrv_conn,
2032                                                dcesrv_conn->event_ctx,
2033                                                dcesrv_conn->stream);
2034         if (!subreq) {
2035                 status = NT_STATUS_NO_MEMORY;
2036                 DEBUG(0,("dcesrv_sock_accept: dcerpc_read_fragment_buffer_send(%s)\n",
2037                         nt_errstr(status)));
2038                 stream_terminate_connection(srv_conn, nt_errstr(status));
2039                 return;
2040         }
2041         tevent_req_set_callback(subreq, dcesrv_read_fragment_done, dcesrv_conn);
2042
2043         return;
2044 }
2045
2046 static void dcesrv_read_fragment_done(struct tevent_req *subreq)
2047 {
2048         struct dcesrv_connection *dce_conn = tevent_req_callback_data(subreq,
2049                                              struct dcesrv_connection);
2050         struct dcesrv_context *dce_ctx = dce_conn->dce_ctx;
2051         struct ncacn_packet *pkt;
2052         DATA_BLOB buffer;
2053         NTSTATUS status;
2054
2055         if (dce_conn->terminate) {
2056                 /*
2057                  * if the current connection is broken
2058                  * we need to clean it up before any other connection
2059                  */
2060                 dcesrv_terminate_connection(dce_conn, dce_conn->terminate);
2061                 dcesrv_cleanup_broken_connections(dce_ctx);
2062                 return;
2063         }
2064
2065         dcesrv_cleanup_broken_connections(dce_ctx);
2066
2067         status = dcerpc_read_ncacn_packet_recv(subreq, dce_conn,
2068                                                &pkt, &buffer);
2069         TALLOC_FREE(subreq);
2070         if (!NT_STATUS_IS_OK(status)) {
2071                 dcesrv_terminate_connection(dce_conn, nt_errstr(status));
2072                 return;
2073         }
2074
2075         status = dcesrv_process_ncacn_packet(dce_conn, pkt, buffer);
2076         if (!NT_STATUS_IS_OK(status)) {
2077                 dcesrv_terminate_connection(dce_conn, nt_errstr(status));
2078                 return;
2079         }
2080
2081         subreq = dcerpc_read_ncacn_packet_send(dce_conn,
2082                                                dce_conn->event_ctx,
2083                                                dce_conn->stream);
2084         if (!subreq) {
2085                 status = NT_STATUS_NO_MEMORY;
2086                 dcesrv_terminate_connection(dce_conn, nt_errstr(status));
2087                 return;
2088         }
2089         tevent_req_set_callback(subreq, dcesrv_read_fragment_done, dce_conn);
2090 }
2091
2092 static void dcesrv_sock_recv(struct stream_connection *conn, uint16_t flags)
2093 {
2094         struct dcesrv_connection *dce_conn = talloc_get_type(conn->private_data,
2095                                              struct dcesrv_connection);
2096         dcesrv_terminate_connection(dce_conn, "dcesrv_sock_recv triggered");
2097 }
2098
2099 static void dcesrv_sock_send(struct stream_connection *conn, uint16_t flags)
2100 {
2101         struct dcesrv_connection *dce_conn = talloc_get_type(conn->private_data,
2102                                              struct dcesrv_connection);
2103         dcesrv_terminate_connection(dce_conn, "dcesrv_sock_send triggered");
2104 }
2105
2106
2107 static const struct stream_server_ops dcesrv_stream_ops = {
2108         .name                   = "rpc",
2109         .accept_connection      = dcesrv_sock_accept,
2110         .recv_handler           = dcesrv_sock_recv,
2111         .send_handler           = dcesrv_sock_send,
2112 };
2113
2114 static NTSTATUS dcesrv_add_ep_unix(struct dcesrv_context *dce_ctx, 
2115                                    struct loadparm_context *lp_ctx,
2116                                    struct dcesrv_endpoint *e,
2117                             struct tevent_context *event_ctx, const struct model_ops *model_ops)
2118 {
2119         struct dcesrv_socket_context *dcesrv_sock;
2120         uint16_t port = 1;
2121         NTSTATUS status;
2122         const char *endpoint;
2123
2124         dcesrv_sock = talloc_zero(event_ctx, struct dcesrv_socket_context);
2125         NT_STATUS_HAVE_NO_MEMORY(dcesrv_sock);
2126
2127         /* remember the endpoint of this socket */
2128         dcesrv_sock->endpoint           = e;
2129         dcesrv_sock->dcesrv_ctx         = talloc_reference(dcesrv_sock, dce_ctx);
2130
2131         endpoint = dcerpc_binding_get_string_option(e->ep_description, "endpoint");
2132
2133         status = stream_setup_socket(dcesrv_sock, event_ctx, lp_ctx,
2134                                      model_ops, &dcesrv_stream_ops, 
2135                                      "unix", endpoint, &port,
2136                                      lpcfg_socket_options(lp_ctx),
2137                                      dcesrv_sock);
2138         if (!NT_STATUS_IS_OK(status)) {
2139                 DEBUG(0,("service_setup_stream_socket(path=%s) failed - %s\n",
2140                          endpoint, nt_errstr(status)));
2141         }
2142
2143         return status;
2144 }
2145
2146 static NTSTATUS dcesrv_add_ep_ncalrpc(struct dcesrv_context *dce_ctx, 
2147                                       struct loadparm_context *lp_ctx,
2148                                       struct dcesrv_endpoint *e,
2149                                       struct tevent_context *event_ctx, const struct model_ops *model_ops)
2150 {
2151         struct dcesrv_socket_context *dcesrv_sock;
2152         uint16_t port = 1;
2153         char *full_path;
2154         NTSTATUS status;
2155         const char *endpoint;
2156
2157         endpoint = dcerpc_binding_get_string_option(e->ep_description, "endpoint");
2158
2159         if (endpoint == NULL) {
2160                 /*
2161                  * No identifier specified: use DEFAULT.
2162                  *
2163                  * TODO: DO NOT hardcode this value anywhere else. Rather, specify
2164                  * no endpoint and let the epmapper worry about it.
2165                  */
2166                 endpoint = "DEFAULT";
2167                 status = dcerpc_binding_set_string_option(e->ep_description,
2168                                                           "endpoint",
2169                                                           endpoint);
2170                 if (!NT_STATUS_IS_OK(status)) {
2171                         DEBUG(0,("dcerpc_binding_set_string_option() failed - %s\n",
2172                                   nt_errstr(status)));
2173                         return status;
2174                 }
2175         }
2176
2177         full_path = talloc_asprintf(dce_ctx, "%s/%s", lpcfg_ncalrpc_dir(lp_ctx),
2178                                     endpoint);
2179
2180         dcesrv_sock = talloc_zero(event_ctx, struct dcesrv_socket_context);
2181         NT_STATUS_HAVE_NO_MEMORY(dcesrv_sock);
2182
2183         /* remember the endpoint of this socket */
2184         dcesrv_sock->endpoint           = e;
2185         dcesrv_sock->dcesrv_ctx         = talloc_reference(dcesrv_sock, dce_ctx);
2186
2187         status = stream_setup_socket(dcesrv_sock, event_ctx, lp_ctx,
2188                                      model_ops, &dcesrv_stream_ops, 
2189                                      "unix", full_path, &port, 
2190                                      lpcfg_socket_options(lp_ctx),
2191                                      dcesrv_sock);
2192         if (!NT_STATUS_IS_OK(status)) {
2193                 DEBUG(0,("service_setup_stream_socket(identifier=%s,path=%s) failed - %s\n",
2194                          endpoint, full_path, nt_errstr(status)));
2195         }
2196         return status;
2197 }
2198
2199 static NTSTATUS dcesrv_add_ep_np(struct dcesrv_context *dce_ctx,
2200                                  struct loadparm_context *lp_ctx,
2201                                  struct dcesrv_endpoint *e,
2202                                  struct tevent_context *event_ctx, const struct model_ops *model_ops)
2203 {
2204         struct dcesrv_socket_context *dcesrv_sock;
2205         NTSTATUS status;
2206         const char *endpoint;
2207
2208         endpoint = dcerpc_binding_get_string_option(e->ep_description, "endpoint");
2209         if (endpoint == NULL) {
2210                 DEBUG(0, ("Endpoint mandatory for named pipes\n"));
2211                 return NT_STATUS_INVALID_PARAMETER;
2212         }
2213
2214         dcesrv_sock = talloc_zero(event_ctx, struct dcesrv_socket_context);
2215         NT_STATUS_HAVE_NO_MEMORY(dcesrv_sock);
2216
2217         /* remember the endpoint of this socket */
2218         dcesrv_sock->endpoint           = e;
2219         dcesrv_sock->dcesrv_ctx         = talloc_reference(dcesrv_sock, dce_ctx);
2220
2221         status = tstream_setup_named_pipe(dce_ctx, event_ctx, lp_ctx,
2222                                           model_ops, &dcesrv_stream_ops,
2223                                           endpoint,
2224                                           dcesrv_sock);
2225         if (!NT_STATUS_IS_OK(status)) {
2226                 DEBUG(0,("stream_setup_named_pipe(pipe=%s) failed - %s\n",
2227                          endpoint, nt_errstr(status)));
2228                 return status;
2229         }
2230
2231         return NT_STATUS_OK;
2232 }
2233
2234 /*
2235   add a socket address to the list of events, one event per dcerpc endpoint
2236 */
2237 static NTSTATUS add_socket_rpc_tcp_iface(struct dcesrv_context *dce_ctx, struct dcesrv_endpoint *e,
2238                                          struct tevent_context *event_ctx, const struct model_ops *model_ops,
2239                                          const char *address)
2240 {
2241         struct dcesrv_socket_context *dcesrv_sock;
2242         uint16_t port = 0;
2243         NTSTATUS status;
2244         const char *endpoint;
2245         char port_str[6];
2246
2247         endpoint = dcerpc_binding_get_string_option(e->ep_description, "endpoint");
2248         if (endpoint != NULL) {
2249                 port = atoi(endpoint);
2250         }
2251
2252         dcesrv_sock = talloc_zero(event_ctx, struct dcesrv_socket_context);
2253         NT_STATUS_HAVE_NO_MEMORY(dcesrv_sock);
2254
2255         /* remember the endpoint of this socket */
2256         dcesrv_sock->endpoint           = e;
2257         dcesrv_sock->dcesrv_ctx         = talloc_reference(dcesrv_sock, dce_ctx);
2258
2259         status = stream_setup_socket(dcesrv_sock, event_ctx, dce_ctx->lp_ctx,
2260                                      model_ops, &dcesrv_stream_ops, 
2261                                      "ip", address, &port,
2262                                      lpcfg_socket_options(dce_ctx->lp_ctx),
2263                                      dcesrv_sock);
2264         if (!NT_STATUS_IS_OK(status)) {
2265                 DEBUG(0,("service_setup_stream_socket(address=%s,port=%u) failed - %s\n", 
2266                          address, port, nt_errstr(status)));
2267                 return status;
2268         }
2269
2270         snprintf(port_str, sizeof(port_str), "%u", port);
2271
2272         status = dcerpc_binding_set_string_option(e->ep_description,
2273                                                   "endpoint", port_str);
2274         if (!NT_STATUS_IS_OK(status)) {
2275                 DEBUG(0,("dcerpc_binding_set_string_option(endpoint, %s) failed - %s\n",
2276                          port_str, nt_errstr(status)));
2277                 return status;
2278         }
2279
2280         return NT_STATUS_OK;
2281 }
2282
2283 #include "lib/socket/netif.h" /* Included here to work around the fact that socket_wrapper redefines bind() */
2284
2285 static NTSTATUS dcesrv_add_ep_tcp(struct dcesrv_context *dce_ctx, 
2286                                   struct loadparm_context *lp_ctx,
2287                                   struct dcesrv_endpoint *e,
2288                                   struct tevent_context *event_ctx, const struct model_ops *model_ops)
2289 {
2290         NTSTATUS status;
2291
2292         /* Add TCP/IP sockets */
2293         if (lpcfg_interfaces(lp_ctx) && lpcfg_bind_interfaces_only(lp_ctx)) {
2294                 int num_interfaces;
2295                 int i;
2296                 struct interface *ifaces;
2297
2298                 load_interface_list(dce_ctx, lp_ctx, &ifaces);
2299
2300                 num_interfaces = iface_list_count(ifaces);
2301                 for(i = 0; i < num_interfaces; i++) {
2302                         const char *address = iface_list_n_ip(ifaces, i);
2303                         status = add_socket_rpc_tcp_iface(dce_ctx, e, event_ctx, model_ops, address);
2304                         NT_STATUS_NOT_OK_RETURN(status);
2305                 }
2306         } else {
2307                 char **wcard;
2308                 int i;
2309                 int num_binds = 0;
2310                 wcard = iface_list_wildcard(dce_ctx);
2311                 NT_STATUS_HAVE_NO_MEMORY(wcard);
2312                 for (i=0; wcard[i]; i++) {
2313                         status = add_socket_rpc_tcp_iface(dce_ctx, e, event_ctx, model_ops, wcard[i]);
2314                         if (NT_STATUS_IS_OK(status)) {
2315                                 num_binds++;
2316                         }
2317                 }
2318                 talloc_free(wcard);
2319                 if (num_binds == 0) {
2320                         return NT_STATUS_INVALID_PARAMETER_MIX;
2321                 }
2322         }
2323
2324         return NT_STATUS_OK;
2325 }
2326
2327 NTSTATUS dcesrv_add_ep(struct dcesrv_context *dce_ctx,
2328                        struct loadparm_context *lp_ctx,
2329                        struct dcesrv_endpoint *e,
2330                        struct tevent_context *event_ctx,
2331                        const struct model_ops *model_ops)
2332 {
2333         enum dcerpc_transport_t transport =
2334                 dcerpc_binding_get_transport(e->ep_description);
2335
2336         switch (transport) {
2337         case NCACN_UNIX_STREAM:
2338                 return dcesrv_add_ep_unix(dce_ctx, lp_ctx, e, event_ctx, model_ops);
2339
2340         case NCALRPC:
2341                 return dcesrv_add_ep_ncalrpc(dce_ctx, lp_ctx, e, event_ctx, model_ops);
2342
2343         case NCACN_IP_TCP:
2344                 return dcesrv_add_ep_tcp(dce_ctx, lp_ctx, e, event_ctx, model_ops);
2345
2346         case NCACN_NP:
2347                 return dcesrv_add_ep_np(dce_ctx, lp_ctx, e, event_ctx, model_ops);
2348
2349         default:
2350                 return NT_STATUS_NOT_SUPPORTED;
2351         }
2352 }
2353
2354
2355 /**
2356  * retrieve credentials from a dce_call
2357  */
2358 _PUBLIC_ struct cli_credentials *dcesrv_call_credentials(struct dcesrv_call_state *dce_call)
2359 {
2360         return dce_call->conn->auth_state.session_info->credentials;
2361 }
2362
2363 /**
2364  * returns true if this is an authenticated call
2365  */
2366 _PUBLIC_ bool dcesrv_call_authenticated(struct dcesrv_call_state *dce_call)
2367 {
2368         enum security_user_level level;
2369         level = security_session_user_level(dce_call->conn->auth_state.session_info, NULL);
2370         return level >= SECURITY_USER;
2371 }
2372
2373 /**
2374  * retrieve account_name for a dce_call
2375  */
2376 _PUBLIC_ const char *dcesrv_call_account_name(struct dcesrv_call_state *dce_call)
2377 {
2378         return dce_call->context->conn->auth_state.session_info->info->account_name;
2379 }