CVE-2015-5370: s4:rpc_server: let invalid request fragments disconnect the connection...
[sfrench/samba-autobuild/.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
730         /* you can't bind twice on one context */
731         if (dcesrv_find_context(call->conn, context_id) != NULL) {
732                 return dcesrv_bind_nak(call, 0);
733         }
734
735         if_version = call->pkt.u.bind.ctx_list[0].abstract_syntax.if_version;
736         uuid = call->pkt.u.bind.ctx_list[0].abstract_syntax.uuid;
737
738         transfer_syntax_version = call->pkt.u.bind.ctx_list[0].transfer_syntaxes[0].if_version;
739         transfer_syntax_uuid = &call->pkt.u.bind.ctx_list[0].transfer_syntaxes[0].uuid;
740         if (!GUID_equal(&ndr_transfer_syntax_ndr.uuid, transfer_syntax_uuid) != 0 ||
741             ndr_transfer_syntax_ndr.if_version != transfer_syntax_version) {
742                 char *uuid_str = GUID_string(call, transfer_syntax_uuid);
743                 /* we only do NDR encoded dcerpc */
744                 DEBUG(0,("Non NDR transfer syntax requested - %s\n", uuid_str));
745                 talloc_free(uuid_str);
746                 return dcesrv_bind_nak(call, 0);
747         }
748
749         iface = find_interface_by_uuid(call->conn->endpoint, &uuid, if_version);
750         if (iface == NULL) {
751                 char *uuid_str = GUID_string(call, &uuid);
752                 DEBUG(2,("Request for unknown dcerpc interface %s/%d\n", uuid_str, if_version));
753                 talloc_free(uuid_str);
754
755                 /* we don't know about that interface */
756                 result = DCERPC_BIND_PROVIDER_REJECT;
757                 reason = DCERPC_BIND_REASON_ASYNTAX;            
758         }
759
760         if (iface) {
761                 /* add this context to the list of available context_ids */
762                 struct dcesrv_connection_context *context = talloc_zero(call->conn,
763                                                                    struct dcesrv_connection_context);
764                 if (context == NULL) {
765                         return dcesrv_bind_nak(call, 0);
766                 }
767                 context->conn = call->conn;
768                 context->iface = iface;
769                 context->context_id = context_id;
770                 if (call->pkt.u.bind.assoc_group_id != 0) {
771                         context->assoc_group = dcesrv_assoc_group_reference(context,
772                                                                             call->conn->dce_ctx, 
773                                                                             call->pkt.u.bind.assoc_group_id);
774                 } else {
775                         context->assoc_group = dcesrv_assoc_group_new(context, call->conn->dce_ctx);
776                 }
777                 if (context->assoc_group == NULL) {
778                         talloc_free(context);
779                         return dcesrv_bind_nak(call, 0);
780                 }
781                 context->private_data = NULL;
782                 DLIST_ADD(call->conn->contexts, context);
783                 call->context = context;
784                 talloc_set_destructor(context, dcesrv_connection_context_destructor);
785
786                 dcesrv_prepare_context_auth(call);
787
788                 status = iface->bind(call, iface, if_version);
789                 if (!NT_STATUS_IS_OK(status)) {
790                         char *uuid_str = GUID_string(call, &uuid);
791                         DEBUG(2,("Request for dcerpc interface %s/%d rejected: %s\n",
792                                  uuid_str, if_version, nt_errstr(status)));
793                         talloc_free(uuid_str);
794                         /* we don't want to trigger the iface->unbind() hook */
795                         context->iface = NULL;
796                         talloc_free(call->context);
797                         call->context = NULL;
798                         return dcesrv_bind_nak(call, 0);
799                 }
800         }
801
802         if ((call->pkt.pfc_flags & DCERPC_PFC_FLAG_CONC_MPX) &&
803             (call->state_flags & DCESRV_CALL_STATE_FLAG_MULTIPLEXED)) {
804                 call->context->conn->state_flags |= DCESRV_CALL_STATE_FLAG_MULTIPLEXED;
805                 extra_flags |= DCERPC_PFC_FLAG_CONC_MPX;
806         }
807
808         if (call->state_flags & DCESRV_CALL_STATE_FLAG_PROCESS_PENDING_CALL) {
809                 call->context->conn->state_flags |= DCESRV_CALL_STATE_FLAG_PROCESS_PENDING_CALL;
810         }
811
812         /* handle any authentication that is being requested */
813         if (!dcesrv_auth_bind(call)) {
814                 talloc_free(call->context);
815                 call->context = NULL;
816                 return dcesrv_bind_nak(call, DCERPC_BIND_REASON_INVALID_AUTH_TYPE);
817         }
818
819         /* setup a bind_ack */
820         dcesrv_init_hdr(&pkt, lpcfg_rpc_big_endian(call->conn->dce_ctx->lp_ctx));
821         pkt.auth_length = 0;
822         pkt.call_id = call->pkt.call_id;
823         pkt.ptype = DCERPC_PKT_BIND_ACK;
824         pkt.pfc_flags = DCERPC_PFC_FLAG_FIRST | DCERPC_PFC_FLAG_LAST | extra_flags;
825         pkt.u.bind_ack.max_xmit_frag = call->conn->max_xmit_frag;
826         pkt.u.bind_ack.max_recv_frag = call->conn->max_recv_frag;
827
828         /*
829           make it possible for iface->bind() to specify the assoc_group_id
830           This helps the openchange mapiproxy plugin to work correctly.
831           
832           metze
833         */
834         if (call->context) {
835                 pkt.u.bind_ack.assoc_group_id = call->context->assoc_group->id;
836         } else {
837                 pkt.u.bind_ack.assoc_group_id = DUMMY_ASSOC_GROUP;
838         }
839
840         if (iface) {
841                 endpoint = dcerpc_binding_get_string_option(
842                                 call->conn->endpoint->ep_description,
843                                 "endpoint");
844         }
845
846         if (endpoint == NULL) {
847                 endpoint = "";
848         }
849
850         if (strncasecmp(endpoint, "\\pipe\\", 6) == 0) {
851                 /*
852                  * TODO: check if this is really needed
853                  *
854                  * Or if we should fix this in our idl files.
855                  */
856                 ep_prefix = "\\PIPE\\";
857                 endpoint += 6;
858         }
859
860         pkt.u.bind_ack.secondary_address = talloc_asprintf(call, "%s%s",
861                                                            ep_prefix,
862                                                            endpoint);
863         if (pkt.u.bind_ack.secondary_address == NULL) {
864                 TALLOC_FREE(call->context);
865                 return NT_STATUS_NO_MEMORY;
866         }
867         pkt.u.bind_ack.num_results = 1;
868         pkt.u.bind_ack.ctx_list = talloc_zero(call, struct dcerpc_ack_ctx);
869         if (!pkt.u.bind_ack.ctx_list) {
870                 talloc_free(call->context);
871                 call->context = NULL;
872                 return NT_STATUS_NO_MEMORY;
873         }
874         pkt.u.bind_ack.ctx_list[0].result = result;
875         pkt.u.bind_ack.ctx_list[0].reason.value = reason;
876         pkt.u.bind_ack.ctx_list[0].syntax = ndr_transfer_syntax_ndr;
877         pkt.u.bind_ack.auth_info = data_blob(NULL, 0);
878
879         status = dcesrv_auth_bind_ack(call, &pkt);
880         if (!NT_STATUS_IS_OK(status)) {
881                 talloc_free(call->context);
882                 call->context = NULL;
883                 return dcesrv_bind_nak(call, 0);
884         }
885
886         rep = talloc_zero(call, struct data_blob_list_item);
887         if (!rep) {
888                 talloc_free(call->context);
889                 call->context = NULL;
890                 return NT_STATUS_NO_MEMORY;
891         }
892
893         status = ncacn_push_auth(&rep->blob, call, &pkt,
894                                  call->out_auth_info);
895         if (!NT_STATUS_IS_OK(status)) {
896                 talloc_free(call->context);
897                 call->context = NULL;
898                 return status;
899         }
900
901         dcerpc_set_frag_length(&rep->blob, rep->blob.length);
902
903         DLIST_ADD_END(call->replies, rep);
904         dcesrv_call_set_list(call, DCESRV_LIST_CALL_LIST);
905
906         if (call->conn->call_list && call->conn->call_list->replies) {
907                 if (call->conn->transport.report_output_data) {
908                         call->conn->transport.report_output_data(call->conn);
909                 }
910         }
911
912         return NT_STATUS_OK;
913 }
914
915
916 /*
917   handle a auth3 request
918 */
919 static NTSTATUS dcesrv_auth3(struct dcesrv_call_state *call)
920 {
921         NTSTATUS status;
922
923         if (!call->conn->allow_auth3) {
924                 return dcesrv_fault_disconnect(call, DCERPC_NCA_S_PROTO_ERROR);
925         }
926
927         if (call->conn->auth_state.auth_finished) {
928                 return dcesrv_fault_disconnect(call, DCERPC_NCA_S_PROTO_ERROR);
929         }
930
931         status = dcerpc_verify_ncacn_packet_header(&call->pkt,
932                         DCERPC_PKT_AUTH3,
933                         call->pkt.u.auth3.auth_info.length,
934                         0, /* required flags */
935                         DCERPC_PFC_FLAG_FIRST |
936                         DCERPC_PFC_FLAG_LAST |
937                         DCERPC_PFC_FLAG_SUPPORT_HEADER_SIGN |
938                         0x08 | /* this is not defined, but should be ignored */
939                         DCERPC_PFC_FLAG_CONC_MPX |
940                         DCERPC_PFC_FLAG_DID_NOT_EXECUTE |
941                         DCERPC_PFC_FLAG_MAYBE |
942                         DCERPC_PFC_FLAG_OBJECT_UUID);
943         if (!NT_STATUS_IS_OK(status)) {
944                 return dcesrv_fault_disconnect(call, DCERPC_NCA_S_PROTO_ERROR);
945         }
946
947         /* handle the auth3 in the auth code */
948         if (!dcesrv_auth_auth3(call)) {
949                 return dcesrv_fault(call, DCERPC_FAULT_OTHER);
950         }
951
952         talloc_free(call);
953
954         /* we don't send a reply to a auth3 request, except by a
955            fault */
956         return NT_STATUS_OK;
957 }
958
959
960 /*
961   handle a bind request
962 */
963 static NTSTATUS dcesrv_alter_new_context(struct dcesrv_call_state *call, uint32_t context_id)
964 {
965         uint32_t if_version, transfer_syntax_version;
966         struct dcesrv_connection_context *context;
967         const struct dcesrv_interface *iface;
968         struct GUID uuid, *transfer_syntax_uuid;
969         NTSTATUS status;
970
971         if_version = call->pkt.u.alter.ctx_list[0].abstract_syntax.if_version;
972         uuid = call->pkt.u.alter.ctx_list[0].abstract_syntax.uuid;
973
974         transfer_syntax_version = call->pkt.u.alter.ctx_list[0].transfer_syntaxes[0].if_version;
975         transfer_syntax_uuid = &call->pkt.u.alter.ctx_list[0].transfer_syntaxes[0].uuid;
976         if (!GUID_equal(transfer_syntax_uuid, &ndr_transfer_syntax_ndr.uuid) ||
977             ndr_transfer_syntax_ndr.if_version != transfer_syntax_version) {
978                 /* we only do NDR encoded dcerpc */
979                 return NT_STATUS_RPC_PROTSEQ_NOT_SUPPORTED;
980         }
981
982         iface = find_interface_by_uuid(call->conn->endpoint, &uuid, if_version);
983         if (iface == NULL) {
984                 char *uuid_str = GUID_string(call, &uuid);
985                 DEBUG(2,("Request for unknown dcerpc interface %s/%d\n", uuid_str, if_version));
986                 talloc_free(uuid_str);
987                 return NT_STATUS_RPC_PROTSEQ_NOT_SUPPORTED;
988         }
989
990         /* add this context to the list of available context_ids */
991         context = talloc_zero(call->conn, struct dcesrv_connection_context);
992         if (context == NULL) {
993                 return NT_STATUS_NO_MEMORY;
994         }
995         context->conn = call->conn;
996         context->iface = iface;
997         context->context_id = context_id;
998         if (call->pkt.u.alter.assoc_group_id != 0) {
999                 context->assoc_group = dcesrv_assoc_group_reference(context,
1000                                                                     call->conn->dce_ctx, 
1001                                                                     call->pkt.u.alter.assoc_group_id);
1002         } else {
1003                 context->assoc_group = dcesrv_assoc_group_new(context, call->conn->dce_ctx);
1004         }
1005         if (context->assoc_group == NULL) {
1006                 talloc_free(context);
1007                 call->context = NULL;
1008                 return NT_STATUS_NO_MEMORY;
1009         }
1010         context->private_data = NULL;
1011         DLIST_ADD(call->conn->contexts, context);
1012         call->context = context;
1013         talloc_set_destructor(context, dcesrv_connection_context_destructor);
1014
1015         dcesrv_prepare_context_auth(call);
1016
1017         status = iface->bind(call, iface, if_version);
1018         if (!NT_STATUS_IS_OK(status)) {
1019                 /* we don't want to trigger the iface->unbind() hook */
1020                 context->iface = NULL;
1021                 talloc_free(context);
1022                 call->context = NULL;
1023                 return status;
1024         }
1025
1026         return NT_STATUS_OK;
1027 }
1028
1029 /* setup and send an alter_resp */
1030 static NTSTATUS dcesrv_alter_resp(struct dcesrv_call_state *call,
1031                                 uint32_t result,
1032                                 uint32_t reason)
1033 {
1034         struct ncacn_packet pkt;
1035         uint32_t extra_flags = 0;
1036         struct data_blob_list_item *rep = NULL;
1037         NTSTATUS status;
1038
1039         dcesrv_init_hdr(&pkt, lpcfg_rpc_big_endian(call->conn->dce_ctx->lp_ctx));
1040         pkt.auth_length = 0;
1041         pkt.call_id = call->pkt.call_id;
1042         pkt.ptype = DCERPC_PKT_ALTER_RESP;
1043         if (result == 0) {
1044                 if ((call->pkt.pfc_flags & DCERPC_PFC_FLAG_CONC_MPX) &&
1045                                 call->context->conn->state_flags &
1046                                         DCESRV_CALL_STATE_FLAG_MULTIPLEXED) {
1047                         extra_flags |= DCERPC_PFC_FLAG_CONC_MPX;
1048                 }
1049                 if (call->state_flags & DCESRV_CALL_STATE_FLAG_PROCESS_PENDING_CALL) {
1050                         call->context->conn->state_flags |=
1051                                 DCESRV_CALL_STATE_FLAG_PROCESS_PENDING_CALL;
1052                 }
1053         }
1054         pkt.pfc_flags = DCERPC_PFC_FLAG_FIRST | DCERPC_PFC_FLAG_LAST | extra_flags;
1055         pkt.u.alter_resp.max_xmit_frag = call->conn->max_xmit_frag;
1056         pkt.u.alter_resp.max_recv_frag = call->conn->max_recv_frag;
1057         if (result == 0) {
1058                 pkt.u.alter_resp.assoc_group_id = call->context->assoc_group->id;
1059         } else {
1060                 pkt.u.alter_resp.assoc_group_id = 0;
1061         }
1062         pkt.u.alter_resp.num_results = 1;
1063         pkt.u.alter_resp.ctx_list = talloc_zero(call, struct dcerpc_ack_ctx);
1064         if (!pkt.u.alter_resp.ctx_list) {
1065                 return NT_STATUS_NO_MEMORY;
1066         }
1067         pkt.u.alter_resp.ctx_list[0].result = result;
1068         pkt.u.alter_resp.ctx_list[0].reason.value = reason;
1069         pkt.u.alter_resp.ctx_list[0].syntax = ndr_transfer_syntax_ndr;
1070         pkt.u.alter_resp.auth_info = data_blob(NULL, 0);
1071         pkt.u.alter_resp.secondary_address = "";
1072
1073         status = dcesrv_auth_alter_ack(call, &pkt);
1074         if (!NT_STATUS_IS_OK(status)) {
1075                 if (NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)
1076                     || NT_STATUS_EQUAL(status, NT_STATUS_LOGON_FAILURE)
1077                     || NT_STATUS_EQUAL(status, NT_STATUS_NO_SUCH_USER)
1078                     || NT_STATUS_EQUAL(status, NT_STATUS_WRONG_PASSWORD)) {
1079                         return dcesrv_fault(call, DCERPC_FAULT_ACCESS_DENIED);
1080                 }
1081                 return dcesrv_fault(call, 0);
1082         }
1083
1084         rep = talloc_zero(call, struct data_blob_list_item);
1085         if (!rep) {
1086                 return NT_STATUS_NO_MEMORY;
1087         }
1088
1089         status = ncacn_push_auth(&rep->blob, call, &pkt, call->out_auth_info);
1090         if (!NT_STATUS_IS_OK(status)) {
1091                 return status;
1092         }
1093
1094         dcerpc_set_frag_length(&rep->blob, rep->blob.length);
1095
1096         DLIST_ADD_END(call->replies, rep);
1097         dcesrv_call_set_list(call, DCESRV_LIST_CALL_LIST);
1098
1099         if (call->conn->call_list && call->conn->call_list->replies) {
1100                 if (call->conn->transport.report_output_data) {
1101                         call->conn->transport.report_output_data(call->conn);
1102                 }
1103         }
1104
1105         return NT_STATUS_OK;
1106 }
1107
1108 /*
1109   handle a alter context request
1110 */
1111 static NTSTATUS dcesrv_alter(struct dcesrv_call_state *call)
1112 {
1113         NTSTATUS status;
1114         uint32_t context_id;
1115
1116         if (!call->conn->allow_alter) {
1117                 return dcesrv_fault_disconnect(call, DCERPC_NCA_S_PROTO_ERROR);
1118         }
1119
1120         status = dcerpc_verify_ncacn_packet_header(&call->pkt,
1121                         DCERPC_PKT_ALTER,
1122                         call->pkt.u.alter.auth_info.length,
1123                         0, /* required flags */
1124                         DCERPC_PFC_FLAG_FIRST |
1125                         DCERPC_PFC_FLAG_LAST |
1126                         DCERPC_PFC_FLAG_SUPPORT_HEADER_SIGN |
1127                         0x08 | /* this is not defined, but should be ignored */
1128                         DCERPC_PFC_FLAG_CONC_MPX |
1129                         DCERPC_PFC_FLAG_DID_NOT_EXECUTE |
1130                         DCERPC_PFC_FLAG_MAYBE |
1131                         DCERPC_PFC_FLAG_OBJECT_UUID);
1132         if (!NT_STATUS_IS_OK(status)) {
1133                 return dcesrv_fault_disconnect(call, DCERPC_NCA_S_PROTO_ERROR);
1134         }
1135
1136         /* handle any authentication that is being requested */
1137         if (!dcesrv_auth_alter(call)) {
1138                 /* TODO: work out the right reject code */
1139                 return dcesrv_alter_resp(call,
1140                                 DCERPC_BIND_PROVIDER_REJECT,
1141                                 DCERPC_BIND_REASON_ASYNTAX);
1142         }
1143
1144         context_id = call->pkt.u.alter.ctx_list[0].context_id;
1145
1146         /* see if they are asking for a new interface */
1147         call->context = dcesrv_find_context(call->conn, context_id);
1148         if (!call->context) {
1149                 status = dcesrv_alter_new_context(call, context_id);
1150                 if (!NT_STATUS_IS_OK(status)) {
1151                         return dcesrv_alter_resp(call,
1152                                 DCERPC_BIND_PROVIDER_REJECT,
1153                                 DCERPC_BIND_REASON_ASYNTAX);
1154                 }
1155         }
1156
1157         if (call->pkt.u.alter.assoc_group_id != 0 &&
1158             lpcfg_parm_bool(call->conn->dce_ctx->lp_ctx, NULL, "dcesrv","assoc group checking", true) &&
1159             call->pkt.u.alter.assoc_group_id != call->context->assoc_group->id) {
1160                 DEBUG(0,(__location__ ": Failed attempt to use new assoc_group in alter context (0x%08x 0x%08x)\n",
1161                          call->context->assoc_group->id, call->pkt.u.alter.assoc_group_id));
1162                 /* TODO: can they ask for a new association group? */
1163                 return dcesrv_alter_resp(call,
1164                                 DCERPC_BIND_PROVIDER_REJECT,
1165                                 DCERPC_BIND_REASON_ASYNTAX);
1166         }
1167
1168         return dcesrv_alter_resp(call,
1169                                 DCERPC_BIND_ACK_RESULT_ACCEPTANCE,
1170                                 DCERPC_BIND_ACK_REASON_NOT_SPECIFIED);
1171 }
1172
1173 /*
1174   possibly save the call for inspection with ndrdump
1175  */
1176 static void dcesrv_save_call(struct dcesrv_call_state *call, const char *why)
1177 {
1178 #ifdef DEVELOPER
1179         char *fname;
1180         const char *dump_dir;
1181         dump_dir = lpcfg_parm_string(call->conn->dce_ctx->lp_ctx, NULL, "dcesrv", "stubs directory");
1182         if (!dump_dir) {
1183                 return;
1184         }
1185         fname = talloc_asprintf(call, "%s/RPC-%s-%u-%s.dat",
1186                                 dump_dir,
1187                                 call->context->iface->name,
1188                                 call->pkt.u.request.opnum,
1189                                 why);
1190         if (file_save(fname, call->pkt.u.request.stub_and_verifier.data, call->pkt.u.request.stub_and_verifier.length)) {
1191                 DEBUG(0,("RPC SAVED %s\n", fname));
1192         }
1193         talloc_free(fname);
1194 #endif
1195 }
1196
1197 static NTSTATUS dcesrv_check_verification_trailer(struct dcesrv_call_state *call)
1198 {
1199         TALLOC_CTX *frame = talloc_stackframe();
1200         const uint32_t bitmask1 = call->conn->auth_state.client_hdr_signing ?
1201                 DCERPC_SEC_VT_CLIENT_SUPPORTS_HEADER_SIGNING : 0;
1202         const struct dcerpc_sec_vt_pcontext pcontext = {
1203                 .abstract_syntax = call->context->iface->syntax_id,
1204                 .transfer_syntax = ndr_transfer_syntax_ndr,
1205         };
1206         const struct dcerpc_sec_vt_header2 header2 =
1207                 dcerpc_sec_vt_header2_from_ncacn_packet(&call->pkt);
1208         enum ndr_err_code ndr_err;
1209         struct dcerpc_sec_verification_trailer *vt = NULL;
1210         NTSTATUS status = NT_STATUS_OK;
1211         bool ok;
1212
1213         SMB_ASSERT(call->pkt.ptype == DCERPC_PKT_REQUEST);
1214
1215         ndr_err = ndr_pop_dcerpc_sec_verification_trailer(call->ndr_pull,
1216                                                           frame, &vt);
1217         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
1218                 status = ndr_map_error2ntstatus(ndr_err);
1219                 goto done;
1220         }
1221
1222         ok = dcerpc_sec_verification_trailer_check(vt, &bitmask1,
1223                                                    &pcontext, &header2);
1224         if (!ok) {
1225                 status = NT_STATUS_ACCESS_DENIED;
1226                 goto done;
1227         }
1228 done:
1229         TALLOC_FREE(frame);
1230         return status;
1231 }
1232
1233 /*
1234   handle a dcerpc request packet
1235 */
1236 static NTSTATUS dcesrv_request(struct dcesrv_call_state *call)
1237 {
1238         const struct dcesrv_endpoint *endpoint = call->conn->endpoint;
1239         enum dcerpc_transport_t transport =
1240                 dcerpc_binding_get_transport(endpoint->ep_description);
1241         struct ndr_pull *pull;
1242         NTSTATUS status;
1243         struct dcesrv_connection_context *context;
1244
1245         if (!call->conn->allow_request) {
1246                 return dcesrv_fault_disconnect(call, DCERPC_NCA_S_PROTO_ERROR);
1247         }
1248
1249         /* if authenticated, and the mech we use can't do async replies, don't use them... */
1250         if (call->conn->auth_state.gensec_security && 
1251             !gensec_have_feature(call->conn->auth_state.gensec_security, GENSEC_FEATURE_ASYNC_REPLIES)) {
1252                 call->state_flags &= ~DCESRV_CALL_STATE_FLAG_MAY_ASYNC;
1253         }
1254
1255         context = dcesrv_find_context(call->conn, call->pkt.u.request.context_id);
1256         if (context == NULL) {
1257                 return dcesrv_fault(call, DCERPC_FAULT_UNK_IF);
1258         }
1259
1260         switch (call->conn->auth_state.auth_level) {
1261         case DCERPC_AUTH_LEVEL_NONE:
1262         case DCERPC_AUTH_LEVEL_INTEGRITY:
1263         case DCERPC_AUTH_LEVEL_PRIVACY:
1264                 break;
1265         default:
1266                 if (!context->allow_connect) {
1267                         char *addr;
1268
1269                         addr = tsocket_address_string(call->conn->remote_address,
1270                                                       call);
1271
1272                         DEBUG(2, ("%s: restrict auth_level_connect access "
1273                                   "to [%s] with auth[type=0x%x,level=0x%x] "
1274                                   "on [%s] from [%s]\n",
1275                                   __func__, context->iface->name,
1276                                   call->conn->auth_state.auth_type,
1277                                   call->conn->auth_state.auth_level,
1278                                   derpc_transport_string_by_transport(transport),
1279                                   addr));
1280                         return dcesrv_fault(call, DCERPC_FAULT_ACCESS_DENIED);
1281                 }
1282                 break;
1283         }
1284
1285         if (call->conn->auth_state.auth_level < context->min_auth_level) {
1286                 char *addr;
1287
1288                 addr = tsocket_address_string(call->conn->remote_address, call);
1289
1290                 DEBUG(2, ("%s: restrict access by min_auth_level[0x%x] "
1291                           "to [%s] with auth[type=0x%x,level=0x%x] "
1292                           "on [%s] from [%s]\n",
1293                           __func__,
1294                           context->min_auth_level,
1295                           context->iface->name,
1296                           call->conn->auth_state.auth_type,
1297                           call->conn->auth_state.auth_level,
1298                           derpc_transport_string_by_transport(transport),
1299                           addr));
1300                 return dcesrv_fault(call, DCERPC_FAULT_ACCESS_DENIED);
1301         }
1302
1303         pull = ndr_pull_init_blob(&call->pkt.u.request.stub_and_verifier, call);
1304         NT_STATUS_HAVE_NO_MEMORY(pull);
1305
1306         pull->flags |= LIBNDR_FLAG_REF_ALLOC;
1307
1308         call->context   = context;
1309         call->ndr_pull  = pull;
1310
1311         if (!(call->pkt.drep[0] & DCERPC_DREP_LE)) {
1312                 pull->flags |= LIBNDR_FLAG_BIGENDIAN;
1313         }
1314
1315         status = dcesrv_check_verification_trailer(call);
1316         if (!NT_STATUS_IS_OK(status)) {
1317                 uint32_t faultcode = DCERPC_FAULT_OTHER;
1318                 if (NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
1319                         faultcode = DCERPC_FAULT_ACCESS_DENIED;
1320                 }
1321                 DEBUG(10, ("dcesrv_check_verification_trailer failed: %s\n",
1322                            nt_errstr(status)));
1323                 return dcesrv_fault(call, faultcode);
1324         }
1325
1326         /* unravel the NDR for the packet */
1327         status = context->iface->ndr_pull(call, call, pull, &call->r);
1328         if (!NT_STATUS_IS_OK(status)) {
1329                 if (call->fault_code == DCERPC_FAULT_OP_RNG_ERROR) {
1330                         /* we got an unknown call */
1331                         DEBUG(3,(__location__ ": Unknown RPC call %u on %s\n",
1332                                  call->pkt.u.request.opnum, context->iface->name));
1333                         dcesrv_save_call(call, "unknown");
1334                 } else {
1335                         dcesrv_save_call(call, "pullfail");
1336                 }
1337                 return dcesrv_fault(call, call->fault_code);
1338         }
1339
1340         if (pull->offset != pull->data_size) {
1341                 dcesrv_save_call(call, "extrabytes");
1342                 DEBUG(3,("Warning: %d extra bytes in incoming RPC request\n", 
1343                          pull->data_size - pull->offset));
1344         }
1345
1346         /* call the dispatch function */
1347         status = context->iface->dispatch(call, call, call->r);
1348         if (!NT_STATUS_IS_OK(status)) {
1349                 DEBUG(5,("dcerpc fault in call %s:%02x - %s\n",
1350                          context->iface->name, 
1351                          call->pkt.u.request.opnum,
1352                          dcerpc_errstr(pull, call->fault_code)));
1353                 return dcesrv_fault(call, call->fault_code);
1354         }
1355
1356         /* add the call to the pending list */
1357         dcesrv_call_set_list(call, DCESRV_LIST_PENDING_CALL_LIST);
1358
1359         if (call->state_flags & DCESRV_CALL_STATE_FLAG_ASYNC) {
1360                 return NT_STATUS_OK;
1361         }
1362
1363         return dcesrv_reply(call);
1364 }
1365
1366
1367 /*
1368   remove the call from the right list when freed
1369  */
1370 static int dcesrv_call_dequeue(struct dcesrv_call_state *call)
1371 {
1372         dcesrv_call_set_list(call, DCESRV_LIST_NONE);
1373         return 0;
1374 }
1375
1376 _PUBLIC_ const struct tsocket_address *dcesrv_connection_get_local_address(struct dcesrv_connection *conn)
1377 {
1378         return conn->local_address;
1379 }
1380
1381 _PUBLIC_ const struct tsocket_address *dcesrv_connection_get_remote_address(struct dcesrv_connection *conn)
1382 {
1383         return conn->remote_address;
1384 }
1385
1386 /*
1387   process some input to a dcerpc endpoint server.
1388 */
1389 static NTSTATUS dcesrv_process_ncacn_packet(struct dcesrv_connection *dce_conn,
1390                                             struct ncacn_packet *pkt,
1391                                             DATA_BLOB blob)
1392 {
1393         NTSTATUS status;
1394         struct dcesrv_call_state *call;
1395
1396         call = talloc_zero(dce_conn, struct dcesrv_call_state);
1397         if (!call) {
1398                 data_blob_free(&blob);
1399                 talloc_free(pkt);
1400                 return NT_STATUS_NO_MEMORY;
1401         }
1402         call->conn              = dce_conn;
1403         call->event_ctx         = dce_conn->event_ctx;
1404         call->msg_ctx           = dce_conn->msg_ctx;
1405         call->state_flags       = call->conn->state_flags;
1406         call->time              = timeval_current();
1407         call->list              = DCESRV_LIST_NONE;
1408
1409         talloc_steal(call, pkt);
1410         talloc_steal(call, blob.data);
1411         call->pkt = *pkt;
1412
1413         talloc_set_destructor(call, dcesrv_call_dequeue);
1414
1415         if (call->conn->allow_bind) {
1416                 /*
1417                  * Only one bind is possible per connection
1418                  */
1419                 call->conn->allow_bind = false;
1420                 return dcesrv_bind(call);
1421         }
1422
1423         /* we have to check the signing here, before combining the
1424            pdus */
1425         if (call->pkt.ptype == DCERPC_PKT_REQUEST) {
1426                 if (!call->conn->allow_request) {
1427                         return dcesrv_fault_disconnect(call,
1428                                         DCERPC_NCA_S_PROTO_ERROR);
1429                 }
1430
1431                 status = dcerpc_verify_ncacn_packet_header(&call->pkt,
1432                                 DCERPC_PKT_REQUEST,
1433                                 call->pkt.u.request.stub_and_verifier.length,
1434                                 0, /* required_flags */
1435                                 DCERPC_PFC_FLAG_FIRST |
1436                                 DCERPC_PFC_FLAG_LAST |
1437                                 DCERPC_PFC_FLAG_PENDING_CANCEL |
1438                                 0x08 | /* this is not defined, but should be ignored */
1439                                 DCERPC_PFC_FLAG_CONC_MPX |
1440                                 DCERPC_PFC_FLAG_DID_NOT_EXECUTE |
1441                                 DCERPC_PFC_FLAG_MAYBE |
1442                                 DCERPC_PFC_FLAG_OBJECT_UUID);
1443                 if (!NT_STATUS_IS_OK(status)) {
1444                         return dcesrv_fault_disconnect(call,
1445                                         DCERPC_NCA_S_PROTO_ERROR);
1446                 }
1447
1448                 if (!dcesrv_auth_request(call, &blob)) {
1449                         return dcesrv_fault(call, DCERPC_FAULT_ACCESS_DENIED);
1450                 }
1451         }
1452
1453         /* see if this is a continued packet */
1454         if (call->pkt.ptype == DCERPC_PKT_REQUEST &&
1455             !(call->pkt.pfc_flags & DCERPC_PFC_FLAG_FIRST)) {
1456                 struct dcesrv_call_state *call2 = call;
1457                 uint32_t alloc_size;
1458
1459                 /* this is a continuation of an existing call - find the call
1460                    then tack it on the end */
1461                 call = dcesrv_find_fragmented_call(dce_conn, call2->pkt.call_id);
1462                 if (!call) {
1463                         return dcesrv_fault_disconnect(call2,
1464                                         DCERPC_NCA_S_PROTO_ERROR);
1465                 }
1466
1467                 if (call->pkt.ptype != call2->pkt.ptype) {
1468                         /* trying to play silly buggers are we? */
1469                         return dcesrv_fault_disconnect(call,
1470                                         DCERPC_NCA_S_PROTO_ERROR);
1471                 }
1472                 if (memcmp(call->pkt.drep, call2->pkt.drep, sizeof(pkt->drep)) != 0) {
1473                         return dcesrv_fault_disconnect(call,
1474                                         DCERPC_NCA_S_PROTO_ERROR);
1475                 }
1476                 if (call->pkt.call_id != call2->pkt.call_id) {
1477                         return dcesrv_fault_disconnect(call,
1478                                         DCERPC_NCA_S_PROTO_ERROR);
1479                 }
1480                 if (call->pkt.u.request.context_id != call2->pkt.u.request.context_id)  {
1481                         return dcesrv_fault_disconnect(call,
1482                                         DCERPC_NCA_S_PROTO_ERROR);
1483                 }
1484                 if (call->pkt.u.request.opnum != call2->pkt.u.request.opnum)  {
1485                         return dcesrv_fault_disconnect(call,
1486                                         DCERPC_NCA_S_PROTO_ERROR);
1487                 }
1488
1489                 alloc_size = call->pkt.u.request.stub_and_verifier.length +
1490                         call2->pkt.u.request.stub_and_verifier.length;
1491                 if (call->pkt.u.request.alloc_hint > alloc_size) {
1492                         alloc_size = call->pkt.u.request.alloc_hint;
1493                 }
1494
1495                 call->pkt.u.request.stub_and_verifier.data = 
1496                         talloc_realloc(call, 
1497                                        call->pkt.u.request.stub_and_verifier.data, 
1498                                        uint8_t, alloc_size);
1499                 if (!call->pkt.u.request.stub_and_verifier.data) {
1500                         return dcesrv_fault(call2, DCERPC_FAULT_OTHER);
1501                 }
1502                 memcpy(call->pkt.u.request.stub_and_verifier.data +
1503                        call->pkt.u.request.stub_and_verifier.length,
1504                        call2->pkt.u.request.stub_and_verifier.data,
1505                        call2->pkt.u.request.stub_and_verifier.length);
1506                 call->pkt.u.request.stub_and_verifier.length += 
1507                         call2->pkt.u.request.stub_and_verifier.length;
1508
1509                 call->pkt.pfc_flags |= (call2->pkt.pfc_flags & DCERPC_PFC_FLAG_LAST);
1510
1511                 talloc_free(call2);
1512         }
1513
1514         /* this may not be the last pdu in the chain - if its isn't then
1515            just put it on the incoming_fragmented_call_list and wait for the rest */
1516         if (call->pkt.ptype == DCERPC_PKT_REQUEST &&
1517             !(call->pkt.pfc_flags & DCERPC_PFC_FLAG_LAST)) {
1518                 dcesrv_call_set_list(call, DCESRV_LIST_FRAGMENTED_CALL_LIST);
1519                 return NT_STATUS_OK;
1520         } 
1521         
1522         /* This removes any fragments we may have had stashed away */
1523         dcesrv_call_set_list(call, DCESRV_LIST_NONE);
1524
1525         switch (call->pkt.ptype) {
1526         case DCERPC_PKT_BIND:
1527                 status = dcesrv_bind_nak(call,
1528                         DCERPC_BIND_NAK_REASON_NOT_SPECIFIED);
1529                 break;
1530         case DCERPC_PKT_AUTH3:
1531                 status = dcesrv_auth3(call);
1532                 break;
1533         case DCERPC_PKT_ALTER:
1534                 status = dcesrv_alter(call);
1535                 break;
1536         case DCERPC_PKT_REQUEST:
1537                 status = dcesrv_request(call);
1538                 break;
1539         default:
1540                 status = dcesrv_fault_disconnect(call, DCERPC_NCA_S_PROTO_ERROR);
1541                 break;
1542         }
1543
1544         /* if we are going to be sending a reply then add
1545            it to the list of pending calls. We add it to the end to keep the call
1546            list in the order we will answer */
1547         if (!NT_STATUS_IS_OK(status)) {
1548                 talloc_free(call);
1549         }
1550
1551         return status;
1552 }
1553
1554 _PUBLIC_ NTSTATUS dcesrv_init_context(TALLOC_CTX *mem_ctx, 
1555                                       struct loadparm_context *lp_ctx,
1556                                       const char **endpoint_servers, struct dcesrv_context **_dce_ctx)
1557 {
1558         NTSTATUS status;
1559         struct dcesrv_context *dce_ctx;
1560         int i;
1561
1562         if (!endpoint_servers) {
1563                 DEBUG(0,("dcesrv_init_context: no endpoint servers configured\n"));
1564                 return NT_STATUS_INTERNAL_ERROR;
1565         }
1566
1567         dce_ctx = talloc_zero(mem_ctx, struct dcesrv_context);
1568         NT_STATUS_HAVE_NO_MEMORY(dce_ctx);
1569
1570         if (uid_wrapper_enabled()) {
1571                 setenv("UID_WRAPPER_MYUID", "1", 1);
1572         }
1573         dce_ctx->initial_euid = geteuid();
1574         if (uid_wrapper_enabled()) {
1575                 unsetenv("UID_WRAPPER_MYUID");
1576         }
1577
1578         dce_ctx->endpoint_list  = NULL;
1579         dce_ctx->lp_ctx = lp_ctx;
1580         dce_ctx->assoc_groups_idr = idr_init(dce_ctx);
1581         NT_STATUS_HAVE_NO_MEMORY(dce_ctx->assoc_groups_idr);
1582         dce_ctx->broken_connections = NULL;
1583
1584         for (i=0;endpoint_servers[i];i++) {
1585                 const struct dcesrv_endpoint_server *ep_server;
1586
1587                 ep_server = dcesrv_ep_server_byname(endpoint_servers[i]);
1588                 if (!ep_server) {
1589                         DEBUG(0,("dcesrv_init_context: failed to find endpoint server = '%s'\n", endpoint_servers[i]));
1590                         return NT_STATUS_INTERNAL_ERROR;
1591                 }
1592
1593                 status = ep_server->init_server(dce_ctx, ep_server);
1594                 if (!NT_STATUS_IS_OK(status)) {
1595                         DEBUG(0,("dcesrv_init_context: failed to init endpoint server = '%s': %s\n", endpoint_servers[i],
1596                                 nt_errstr(status)));
1597                         return status;
1598                 }
1599         }
1600
1601         *_dce_ctx = dce_ctx;
1602         return NT_STATUS_OK;
1603 }
1604
1605 /* the list of currently registered DCERPC endpoint servers.
1606  */
1607 static struct ep_server {
1608         struct dcesrv_endpoint_server *ep_server;
1609 } *ep_servers = NULL;
1610 static int num_ep_servers;
1611
1612 /*
1613   register a DCERPC endpoint server. 
1614
1615   The 'name' can be later used by other backends to find the operations
1616   structure for this backend.  
1617
1618   The 'type' is used to specify whether this is for a disk, printer or IPC$ share
1619 */
1620 _PUBLIC_ NTSTATUS dcerpc_register_ep_server(const void *_ep_server)
1621 {
1622         const struct dcesrv_endpoint_server *ep_server = _ep_server;
1623         
1624         if (dcesrv_ep_server_byname(ep_server->name) != NULL) {
1625                 /* its already registered! */
1626                 DEBUG(0,("DCERPC endpoint server '%s' already registered\n", 
1627                          ep_server->name));
1628                 return NT_STATUS_OBJECT_NAME_COLLISION;
1629         }
1630
1631         ep_servers = realloc_p(ep_servers, struct ep_server, num_ep_servers+1);
1632         if (!ep_servers) {
1633                 smb_panic("out of memory in dcerpc_register");
1634         }
1635
1636         ep_servers[num_ep_servers].ep_server = smb_xmemdup(ep_server, sizeof(*ep_server));
1637         ep_servers[num_ep_servers].ep_server->name = smb_xstrdup(ep_server->name);
1638
1639         num_ep_servers++;
1640
1641         DEBUG(3,("DCERPC endpoint server '%s' registered\n", 
1642                  ep_server->name));
1643
1644         return NT_STATUS_OK;
1645 }
1646
1647 /*
1648   return the operations structure for a named backend of the specified type
1649 */
1650 const struct dcesrv_endpoint_server *dcesrv_ep_server_byname(const char *name)
1651 {
1652         int i;
1653
1654         for (i=0;i<num_ep_servers;i++) {
1655                 if (strcmp(ep_servers[i].ep_server->name, name) == 0) {
1656                         return ep_servers[i].ep_server;
1657                 }
1658         }
1659
1660         return NULL;
1661 }
1662
1663 void dcerpc_server_init(struct loadparm_context *lp_ctx)
1664 {
1665         static bool initialized;
1666 #define _MODULE_PROTO(init) extern NTSTATUS init(void);
1667         STATIC_dcerpc_server_MODULES_PROTO;
1668         init_module_fn static_init[] = { STATIC_dcerpc_server_MODULES };
1669         init_module_fn *shared_init;
1670
1671         if (initialized) {
1672                 return;
1673         }
1674         initialized = true;
1675
1676         shared_init = load_samba_modules(NULL, "dcerpc_server");
1677
1678         run_init_functions(static_init);
1679         run_init_functions(shared_init);
1680
1681         talloc_free(shared_init);
1682 }
1683
1684 /*
1685   return the DCERPC module version, and the size of some critical types
1686   This can be used by endpoint server modules to either detect compilation errors, or provide
1687   multiple implementations for different smbd compilation options in one module
1688 */
1689 const struct dcesrv_critical_sizes *dcerpc_module_version(void)
1690 {
1691         static const struct dcesrv_critical_sizes critical_sizes = {
1692                 DCERPC_MODULE_VERSION,
1693                 sizeof(struct dcesrv_context),
1694                 sizeof(struct dcesrv_endpoint),
1695                 sizeof(struct dcesrv_endpoint_server),
1696                 sizeof(struct dcesrv_interface),
1697                 sizeof(struct dcesrv_if_list),
1698                 sizeof(struct dcesrv_connection),
1699                 sizeof(struct dcesrv_call_state),
1700                 sizeof(struct dcesrv_auth),
1701                 sizeof(struct dcesrv_handle)
1702         };
1703
1704         return &critical_sizes;
1705 }
1706
1707 static void dcesrv_terminate_connection(struct dcesrv_connection *dce_conn, const char *reason)
1708 {
1709         struct dcesrv_context *dce_ctx = dce_conn->dce_ctx;
1710         struct stream_connection *srv_conn;
1711         srv_conn = talloc_get_type(dce_conn->transport.private_data,
1712                                    struct stream_connection);
1713
1714         dce_conn->allow_bind = false;
1715         dce_conn->allow_auth3 = false;
1716         dce_conn->allow_alter = false;
1717         dce_conn->allow_request = false;
1718
1719         if (dce_conn->pending_call_list == NULL) {
1720                 char *full_reason = talloc_asprintf(dce_conn, "dcesrv: %s", reason);
1721
1722                 DLIST_REMOVE(dce_ctx->broken_connections, dce_conn);
1723                 stream_terminate_connection(srv_conn, full_reason ? full_reason : reason);
1724                 return;
1725         }
1726
1727         if (dce_conn->terminate != NULL) {
1728                 return;
1729         }
1730
1731         DEBUG(3,("dcesrv: terminating connection due to '%s' defered due to pending calls\n",
1732                  reason));
1733         dce_conn->terminate = talloc_strdup(dce_conn, reason);
1734         if (dce_conn->terminate == NULL) {
1735                 dce_conn->terminate = "dcesrv: defered terminating connection - no memory";
1736         }
1737         DLIST_ADD_END(dce_ctx->broken_connections, dce_conn);
1738 }
1739
1740 static void dcesrv_cleanup_broken_connections(struct dcesrv_context *dce_ctx)
1741 {
1742         struct dcesrv_connection *cur, *next;
1743
1744         next = dce_ctx->broken_connections;
1745         while (next != NULL) {
1746                 cur = next;
1747                 next = cur->next;
1748
1749                 if (cur->state_flags & DCESRV_CALL_STATE_FLAG_PROCESS_PENDING_CALL) {
1750                         struct dcesrv_connection_context *context_cur, *context_next;
1751
1752                         context_next = cur->contexts;
1753                         while (context_next != NULL) {
1754                                 context_cur = context_next;
1755                                 context_next = context_cur->next;
1756
1757                                 dcesrv_connection_context_destructor(context_cur);
1758                         }
1759                 }
1760
1761                 dcesrv_terminate_connection(cur, cur->terminate);
1762         }
1763 }
1764
1765 /* We need this include to be able to compile on some plateforms
1766  * (ie. freebsd 7.2) as it seems that <sys/uio.h> is not included
1767  * correctly.
1768  * It has to be that deep because otherwise we have a conflict on
1769  * const struct dcesrv_interface declaration.
1770  * This is mostly due to socket_wrapper defining #define bind swrap_bind
1771  * which conflict with the bind used before.
1772  */
1773 #include "system/network.h"
1774
1775 struct dcesrv_sock_reply_state {
1776         struct dcesrv_connection *dce_conn;
1777         struct dcesrv_call_state *call;
1778         struct iovec iov;
1779 };
1780
1781 static void dcesrv_sock_reply_done(struct tevent_req *subreq);
1782 static void dcesrv_call_terminate_step1(struct tevent_req *subreq);
1783
1784 static void dcesrv_sock_report_output_data(struct dcesrv_connection *dce_conn)
1785 {
1786         struct dcesrv_call_state *call;
1787
1788         call = dce_conn->call_list;
1789         if (!call || !call->replies) {
1790                 return;
1791         }
1792
1793         while (call->replies) {
1794                 struct data_blob_list_item *rep = call->replies;
1795                 struct dcesrv_sock_reply_state *substate;
1796                 struct tevent_req *subreq;
1797
1798                 substate = talloc_zero(call, struct dcesrv_sock_reply_state);
1799                 if (!substate) {
1800                         dcesrv_terminate_connection(dce_conn, "no memory");
1801                         return;
1802                 }
1803
1804                 substate->dce_conn = dce_conn;
1805                 substate->call = NULL;
1806
1807                 DLIST_REMOVE(call->replies, rep);
1808
1809                 if (call->replies == NULL && call->terminate_reason == NULL) {
1810                         substate->call = call;
1811                 }
1812
1813                 substate->iov.iov_base = (void *) rep->blob.data;
1814                 substate->iov.iov_len = rep->blob.length;
1815
1816                 subreq = tstream_writev_queue_send(substate,
1817                                                    dce_conn->event_ctx,
1818                                                    dce_conn->stream,
1819                                                    dce_conn->send_queue,
1820                                                    &substate->iov, 1);
1821                 if (!subreq) {
1822                         dcesrv_terminate_connection(dce_conn, "no memory");
1823                         return;
1824                 }
1825                 tevent_req_set_callback(subreq, dcesrv_sock_reply_done,
1826                                         substate);
1827         }
1828
1829         if (call->terminate_reason != NULL) {
1830                 struct tevent_req *subreq;
1831
1832                 subreq = tevent_queue_wait_send(call,
1833                                                 dce_conn->event_ctx,
1834                                                 dce_conn->send_queue);
1835                 if (!subreq) {
1836                         dcesrv_terminate_connection(dce_conn, __location__);
1837                         return;
1838                 }
1839                 tevent_req_set_callback(subreq, dcesrv_call_terminate_step1,
1840                                         call);
1841         }
1842
1843         DLIST_REMOVE(call->conn->call_list, call);
1844         call->list = DCESRV_LIST_NONE;
1845 }
1846
1847 static void dcesrv_sock_reply_done(struct tevent_req *subreq)
1848 {
1849         struct dcesrv_sock_reply_state *substate = tevent_req_callback_data(subreq,
1850                                                 struct dcesrv_sock_reply_state);
1851         int ret;
1852         int sys_errno;
1853         NTSTATUS status;
1854         struct dcesrv_call_state *call = substate->call;
1855
1856         ret = tstream_writev_queue_recv(subreq, &sys_errno);
1857         TALLOC_FREE(subreq);
1858         if (ret == -1) {
1859                 status = map_nt_error_from_unix_common(sys_errno);
1860                 dcesrv_terminate_connection(substate->dce_conn, nt_errstr(status));
1861                 return;
1862         }
1863
1864         talloc_free(substate);
1865         if (call) {
1866                 talloc_free(call);
1867         }
1868 }
1869
1870 static void dcesrv_call_terminate_step2(struct tevent_req *subreq);
1871
1872 static void dcesrv_call_terminate_step1(struct tevent_req *subreq)
1873 {
1874         struct dcesrv_call_state *call = tevent_req_callback_data(subreq,
1875                                                 struct dcesrv_call_state);
1876         bool ok;
1877         struct timeval tv;
1878
1879         /* make sure we stop send queue before removing subreq */
1880         tevent_queue_stop(call->conn->send_queue);
1881
1882         ok = tevent_queue_wait_recv(subreq);
1883         TALLOC_FREE(subreq);
1884         if (!ok) {
1885                 dcesrv_terminate_connection(call->conn, __location__);
1886                 return;
1887         }
1888
1889         /* disconnect after 200 usecs */
1890         tv = timeval_current_ofs_usec(200);
1891         subreq = tevent_wakeup_send(call, call->conn->event_ctx, tv);
1892         if (subreq == NULL) {
1893                 dcesrv_terminate_connection(call->conn, __location__);
1894                 return;
1895         }
1896         tevent_req_set_callback(subreq, dcesrv_call_terminate_step2,
1897                                 call);
1898 }
1899
1900 static void dcesrv_call_terminate_step2(struct tevent_req *subreq)
1901 {
1902         struct dcesrv_call_state *call = tevent_req_callback_data(subreq,
1903                                                 struct dcesrv_call_state);
1904         bool ok;
1905
1906         ok = tevent_wakeup_recv(subreq);
1907         TALLOC_FREE(subreq);
1908         if (!ok) {
1909                 dcesrv_terminate_connection(call->conn, __location__);
1910                 return;
1911         }
1912
1913         dcesrv_terminate_connection(call->conn, call->terminate_reason);
1914 }
1915
1916 struct dcesrv_socket_context {
1917         const struct dcesrv_endpoint *endpoint;
1918         struct dcesrv_context *dcesrv_ctx;
1919 };
1920
1921
1922 static void dcesrv_read_fragment_done(struct tevent_req *subreq);
1923
1924 static void dcesrv_sock_accept(struct stream_connection *srv_conn)
1925 {
1926         NTSTATUS status;
1927         struct dcesrv_socket_context *dcesrv_sock = 
1928                 talloc_get_type(srv_conn->private_data, struct dcesrv_socket_context);
1929         enum dcerpc_transport_t transport =
1930                 dcerpc_binding_get_transport(dcesrv_sock->endpoint->ep_description);
1931         struct dcesrv_connection *dcesrv_conn = NULL;
1932         int ret;
1933         struct tevent_req *subreq;
1934         struct loadparm_context *lp_ctx = dcesrv_sock->dcesrv_ctx->lp_ctx;
1935
1936         dcesrv_cleanup_broken_connections(dcesrv_sock->dcesrv_ctx);
1937
1938         if (!srv_conn->session_info) {
1939                 status = auth_anonymous_session_info(srv_conn,
1940                                                      lp_ctx,
1941                                                      &srv_conn->session_info);
1942                 if (!NT_STATUS_IS_OK(status)) {
1943                         DEBUG(0,("dcesrv_sock_accept: auth_anonymous_session_info failed: %s\n",
1944                                 nt_errstr(status)));
1945                         stream_terminate_connection(srv_conn, nt_errstr(status));
1946                         return;
1947                 }
1948         }
1949
1950         status = dcesrv_endpoint_connect(dcesrv_sock->dcesrv_ctx,
1951                                          srv_conn,
1952                                          dcesrv_sock->endpoint,
1953                                          srv_conn->session_info,
1954                                          srv_conn->event.ctx,
1955                                          srv_conn->msg_ctx,
1956                                          srv_conn->server_id,
1957                                          DCESRV_CALL_STATE_FLAG_MAY_ASYNC,
1958                                          &dcesrv_conn);
1959         if (!NT_STATUS_IS_OK(status)) {
1960                 DEBUG(0,("dcesrv_sock_accept: dcesrv_endpoint_connect failed: %s\n", 
1961                         nt_errstr(status)));
1962                 stream_terminate_connection(srv_conn, nt_errstr(status));
1963                 return;
1964         }
1965
1966         dcesrv_conn->transport.private_data             = srv_conn;
1967         dcesrv_conn->transport.report_output_data       = dcesrv_sock_report_output_data;
1968
1969         TALLOC_FREE(srv_conn->event.fde);
1970
1971         dcesrv_conn->send_queue = tevent_queue_create(dcesrv_conn, "dcesrv send queue");
1972         if (!dcesrv_conn->send_queue) {
1973                 status = NT_STATUS_NO_MEMORY;
1974                 DEBUG(0,("dcesrv_sock_accept: tevent_queue_create(%s)\n",
1975                         nt_errstr(status)));
1976                 stream_terminate_connection(srv_conn, nt_errstr(status));
1977                 return;
1978         }
1979
1980         if (transport == NCACN_NP) {
1981                 dcesrv_conn->auth_state.session_key = dcesrv_inherited_session_key;
1982                 dcesrv_conn->stream = talloc_move(dcesrv_conn,
1983                                                   &srv_conn->tstream);
1984         } else {
1985                 ret = tstream_bsd_existing_socket(dcesrv_conn,
1986                                                   socket_get_fd(srv_conn->socket),
1987                                                   &dcesrv_conn->stream);
1988                 if (ret == -1) {
1989                         status = map_nt_error_from_unix_common(errno);
1990                         DEBUG(0, ("dcesrv_sock_accept: "
1991                                   "failed to setup tstream: %s\n",
1992                                   nt_errstr(status)));
1993                         stream_terminate_connection(srv_conn, nt_errstr(status));
1994                         return;
1995                 }
1996                 socket_set_flags(srv_conn->socket, SOCKET_FLAG_NOCLOSE);
1997         }
1998
1999         dcesrv_conn->local_address = srv_conn->local_address;
2000         dcesrv_conn->remote_address = srv_conn->remote_address;
2001
2002         if (transport == NCALRPC) {
2003                 uid_t uid;
2004                 gid_t gid;
2005
2006                 ret = getpeereid(socket_get_fd(srv_conn->socket), &uid, &gid);
2007                 if (ret == -1) {
2008                         status = map_nt_error_from_unix_common(errno);
2009                         DEBUG(0, ("dcesrv_sock_accept: "
2010                                   "getpeereid() failed for NCALRPC: %s\n",
2011                                   nt_errstr(status)));
2012                         stream_terminate_connection(srv_conn, nt_errstr(status));
2013                         return;
2014                 }
2015                 if (uid == dcesrv_conn->dce_ctx->initial_euid) {
2016                         struct tsocket_address *r = NULL;
2017
2018                         ret = tsocket_address_unix_from_path(dcesrv_conn,
2019                                                              "/root/ncalrpc_as_system",
2020                                                              &r);
2021                         if (ret == -1) {
2022                                 status = map_nt_error_from_unix_common(errno);
2023                                 DEBUG(0, ("dcesrv_sock_accept: "
2024                                           "tsocket_address_unix_from_path() failed for NCALRPC: %s\n",
2025                                           nt_errstr(status)));
2026                                 stream_terminate_connection(srv_conn, nt_errstr(status));
2027                                 return;
2028                         }
2029                         dcesrv_conn->remote_address = r;
2030                 }
2031         }
2032
2033         srv_conn->private_data = dcesrv_conn;
2034
2035         irpc_add_name(srv_conn->msg_ctx, "rpc_server");
2036
2037         subreq = dcerpc_read_ncacn_packet_send(dcesrv_conn,
2038                                                dcesrv_conn->event_ctx,
2039                                                dcesrv_conn->stream);
2040         if (!subreq) {
2041                 status = NT_STATUS_NO_MEMORY;
2042                 DEBUG(0,("dcesrv_sock_accept: dcerpc_read_fragment_buffer_send(%s)\n",
2043                         nt_errstr(status)));
2044                 stream_terminate_connection(srv_conn, nt_errstr(status));
2045                 return;
2046         }
2047         tevent_req_set_callback(subreq, dcesrv_read_fragment_done, dcesrv_conn);
2048
2049         return;
2050 }
2051
2052 static void dcesrv_read_fragment_done(struct tevent_req *subreq)
2053 {
2054         struct dcesrv_connection *dce_conn = tevent_req_callback_data(subreq,
2055                                              struct dcesrv_connection);
2056         struct dcesrv_context *dce_ctx = dce_conn->dce_ctx;
2057         struct ncacn_packet *pkt;
2058         DATA_BLOB buffer;
2059         NTSTATUS status;
2060
2061         if (dce_conn->terminate) {
2062                 /*
2063                  * if the current connection is broken
2064                  * we need to clean it up before any other connection
2065                  */
2066                 dcesrv_terminate_connection(dce_conn, dce_conn->terminate);
2067                 dcesrv_cleanup_broken_connections(dce_ctx);
2068                 return;
2069         }
2070
2071         dcesrv_cleanup_broken_connections(dce_ctx);
2072
2073         status = dcerpc_read_ncacn_packet_recv(subreq, dce_conn,
2074                                                &pkt, &buffer);
2075         TALLOC_FREE(subreq);
2076         if (!NT_STATUS_IS_OK(status)) {
2077                 dcesrv_terminate_connection(dce_conn, nt_errstr(status));
2078                 return;
2079         }
2080
2081         status = dcesrv_process_ncacn_packet(dce_conn, pkt, buffer);
2082         if (!NT_STATUS_IS_OK(status)) {
2083                 dcesrv_terminate_connection(dce_conn, nt_errstr(status));
2084                 return;
2085         }
2086
2087         subreq = dcerpc_read_ncacn_packet_send(dce_conn,
2088                                                dce_conn->event_ctx,
2089                                                dce_conn->stream);
2090         if (!subreq) {
2091                 status = NT_STATUS_NO_MEMORY;
2092                 dcesrv_terminate_connection(dce_conn, nt_errstr(status));
2093                 return;
2094         }
2095         tevent_req_set_callback(subreq, dcesrv_read_fragment_done, dce_conn);
2096 }
2097
2098 static void dcesrv_sock_recv(struct stream_connection *conn, uint16_t flags)
2099 {
2100         struct dcesrv_connection *dce_conn = talloc_get_type(conn->private_data,
2101                                              struct dcesrv_connection);
2102         dcesrv_terminate_connection(dce_conn, "dcesrv_sock_recv triggered");
2103 }
2104
2105 static void dcesrv_sock_send(struct stream_connection *conn, uint16_t flags)
2106 {
2107         struct dcesrv_connection *dce_conn = talloc_get_type(conn->private_data,
2108                                              struct dcesrv_connection);
2109         dcesrv_terminate_connection(dce_conn, "dcesrv_sock_send triggered");
2110 }
2111
2112
2113 static const struct stream_server_ops dcesrv_stream_ops = {
2114         .name                   = "rpc",
2115         .accept_connection      = dcesrv_sock_accept,
2116         .recv_handler           = dcesrv_sock_recv,
2117         .send_handler           = dcesrv_sock_send,
2118 };
2119
2120 static NTSTATUS dcesrv_add_ep_unix(struct dcesrv_context *dce_ctx, 
2121                                    struct loadparm_context *lp_ctx,
2122                                    struct dcesrv_endpoint *e,
2123                             struct tevent_context *event_ctx, const struct model_ops *model_ops)
2124 {
2125         struct dcesrv_socket_context *dcesrv_sock;
2126         uint16_t port = 1;
2127         NTSTATUS status;
2128         const char *endpoint;
2129
2130         dcesrv_sock = talloc_zero(event_ctx, struct dcesrv_socket_context);
2131         NT_STATUS_HAVE_NO_MEMORY(dcesrv_sock);
2132
2133         /* remember the endpoint of this socket */
2134         dcesrv_sock->endpoint           = e;
2135         dcesrv_sock->dcesrv_ctx         = talloc_reference(dcesrv_sock, dce_ctx);
2136
2137         endpoint = dcerpc_binding_get_string_option(e->ep_description, "endpoint");
2138
2139         status = stream_setup_socket(dcesrv_sock, event_ctx, lp_ctx,
2140                                      model_ops, &dcesrv_stream_ops, 
2141                                      "unix", endpoint, &port,
2142                                      lpcfg_socket_options(lp_ctx),
2143                                      dcesrv_sock);
2144         if (!NT_STATUS_IS_OK(status)) {
2145                 DEBUG(0,("service_setup_stream_socket(path=%s) failed - %s\n",
2146                          endpoint, nt_errstr(status)));
2147         }
2148
2149         return status;
2150 }
2151
2152 static NTSTATUS dcesrv_add_ep_ncalrpc(struct dcesrv_context *dce_ctx, 
2153                                       struct loadparm_context *lp_ctx,
2154                                       struct dcesrv_endpoint *e,
2155                                       struct tevent_context *event_ctx, const struct model_ops *model_ops)
2156 {
2157         struct dcesrv_socket_context *dcesrv_sock;
2158         uint16_t port = 1;
2159         char *full_path;
2160         NTSTATUS status;
2161         const char *endpoint;
2162
2163         endpoint = dcerpc_binding_get_string_option(e->ep_description, "endpoint");
2164
2165         if (endpoint == NULL) {
2166                 /*
2167                  * No identifier specified: use DEFAULT.
2168                  *
2169                  * TODO: DO NOT hardcode this value anywhere else. Rather, specify
2170                  * no endpoint and let the epmapper worry about it.
2171                  */
2172                 endpoint = "DEFAULT";
2173                 status = dcerpc_binding_set_string_option(e->ep_description,
2174                                                           "endpoint",
2175                                                           endpoint);
2176                 if (!NT_STATUS_IS_OK(status)) {
2177                         DEBUG(0,("dcerpc_binding_set_string_option() failed - %s\n",
2178                                   nt_errstr(status)));
2179                         return status;
2180                 }
2181         }
2182
2183         full_path = talloc_asprintf(dce_ctx, "%s/%s", lpcfg_ncalrpc_dir(lp_ctx),
2184                                     endpoint);
2185
2186         dcesrv_sock = talloc_zero(event_ctx, struct dcesrv_socket_context);
2187         NT_STATUS_HAVE_NO_MEMORY(dcesrv_sock);
2188
2189         /* remember the endpoint of this socket */
2190         dcesrv_sock->endpoint           = e;
2191         dcesrv_sock->dcesrv_ctx         = talloc_reference(dcesrv_sock, dce_ctx);
2192
2193         status = stream_setup_socket(dcesrv_sock, event_ctx, lp_ctx,
2194                                      model_ops, &dcesrv_stream_ops, 
2195                                      "unix", full_path, &port, 
2196                                      lpcfg_socket_options(lp_ctx),
2197                                      dcesrv_sock);
2198         if (!NT_STATUS_IS_OK(status)) {
2199                 DEBUG(0,("service_setup_stream_socket(identifier=%s,path=%s) failed - %s\n",
2200                          endpoint, full_path, nt_errstr(status)));
2201         }
2202         return status;
2203 }
2204
2205 static NTSTATUS dcesrv_add_ep_np(struct dcesrv_context *dce_ctx,
2206                                  struct loadparm_context *lp_ctx,
2207                                  struct dcesrv_endpoint *e,
2208                                  struct tevent_context *event_ctx, const struct model_ops *model_ops)
2209 {
2210         struct dcesrv_socket_context *dcesrv_sock;
2211         NTSTATUS status;
2212         const char *endpoint;
2213
2214         endpoint = dcerpc_binding_get_string_option(e->ep_description, "endpoint");
2215         if (endpoint == NULL) {
2216                 DEBUG(0, ("Endpoint mandatory for named pipes\n"));
2217                 return NT_STATUS_INVALID_PARAMETER;
2218         }
2219
2220         dcesrv_sock = talloc_zero(event_ctx, struct dcesrv_socket_context);
2221         NT_STATUS_HAVE_NO_MEMORY(dcesrv_sock);
2222
2223         /* remember the endpoint of this socket */
2224         dcesrv_sock->endpoint           = e;
2225         dcesrv_sock->dcesrv_ctx         = talloc_reference(dcesrv_sock, dce_ctx);
2226
2227         status = tstream_setup_named_pipe(dce_ctx, event_ctx, lp_ctx,
2228                                           model_ops, &dcesrv_stream_ops,
2229                                           endpoint,
2230                                           dcesrv_sock);
2231         if (!NT_STATUS_IS_OK(status)) {
2232                 DEBUG(0,("stream_setup_named_pipe(pipe=%s) failed - %s\n",
2233                          endpoint, nt_errstr(status)));
2234                 return status;
2235         }
2236
2237         return NT_STATUS_OK;
2238 }
2239
2240 /*
2241   add a socket address to the list of events, one event per dcerpc endpoint
2242 */
2243 static NTSTATUS add_socket_rpc_tcp_iface(struct dcesrv_context *dce_ctx, struct dcesrv_endpoint *e,
2244                                          struct tevent_context *event_ctx, const struct model_ops *model_ops,
2245                                          const char *address)
2246 {
2247         struct dcesrv_socket_context *dcesrv_sock;
2248         uint16_t port = 0;
2249         NTSTATUS status;
2250         const char *endpoint;
2251         char port_str[6];
2252
2253         endpoint = dcerpc_binding_get_string_option(e->ep_description, "endpoint");
2254         if (endpoint != NULL) {
2255                 port = atoi(endpoint);
2256         }
2257
2258         dcesrv_sock = talloc_zero(event_ctx, struct dcesrv_socket_context);
2259         NT_STATUS_HAVE_NO_MEMORY(dcesrv_sock);
2260
2261         /* remember the endpoint of this socket */
2262         dcesrv_sock->endpoint           = e;
2263         dcesrv_sock->dcesrv_ctx         = talloc_reference(dcesrv_sock, dce_ctx);
2264
2265         status = stream_setup_socket(dcesrv_sock, event_ctx, dce_ctx->lp_ctx,
2266                                      model_ops, &dcesrv_stream_ops, 
2267                                      "ip", address, &port,
2268                                      lpcfg_socket_options(dce_ctx->lp_ctx),
2269                                      dcesrv_sock);
2270         if (!NT_STATUS_IS_OK(status)) {
2271                 DEBUG(0,("service_setup_stream_socket(address=%s,port=%u) failed - %s\n", 
2272                          address, port, nt_errstr(status)));
2273                 return status;
2274         }
2275
2276         snprintf(port_str, sizeof(port_str), "%u", port);
2277
2278         status = dcerpc_binding_set_string_option(e->ep_description,
2279                                                   "endpoint", port_str);
2280         if (!NT_STATUS_IS_OK(status)) {
2281                 DEBUG(0,("dcerpc_binding_set_string_option(endpoint, %s) failed - %s\n",
2282                          port_str, nt_errstr(status)));
2283                 return status;
2284         }
2285
2286         return NT_STATUS_OK;
2287 }
2288
2289 #include "lib/socket/netif.h" /* Included here to work around the fact that socket_wrapper redefines bind() */
2290
2291 static NTSTATUS dcesrv_add_ep_tcp(struct dcesrv_context *dce_ctx, 
2292                                   struct loadparm_context *lp_ctx,
2293                                   struct dcesrv_endpoint *e,
2294                                   struct tevent_context *event_ctx, const struct model_ops *model_ops)
2295 {
2296         NTSTATUS status;
2297
2298         /* Add TCP/IP sockets */
2299         if (lpcfg_interfaces(lp_ctx) && lpcfg_bind_interfaces_only(lp_ctx)) {
2300                 int num_interfaces;
2301                 int i;
2302                 struct interface *ifaces;
2303
2304                 load_interface_list(dce_ctx, lp_ctx, &ifaces);
2305
2306                 num_interfaces = iface_list_count(ifaces);
2307                 for(i = 0; i < num_interfaces; i++) {
2308                         const char *address = iface_list_n_ip(ifaces, i);
2309                         status = add_socket_rpc_tcp_iface(dce_ctx, e, event_ctx, model_ops, address);
2310                         NT_STATUS_NOT_OK_RETURN(status);
2311                 }
2312         } else {
2313                 char **wcard;
2314                 int i;
2315                 int num_binds = 0;
2316                 wcard = iface_list_wildcard(dce_ctx);
2317                 NT_STATUS_HAVE_NO_MEMORY(wcard);
2318                 for (i=0; wcard[i]; i++) {
2319                         status = add_socket_rpc_tcp_iface(dce_ctx, e, event_ctx, model_ops, wcard[i]);
2320                         if (NT_STATUS_IS_OK(status)) {
2321                                 num_binds++;
2322                         }
2323                 }
2324                 talloc_free(wcard);
2325                 if (num_binds == 0) {
2326                         return NT_STATUS_INVALID_PARAMETER_MIX;
2327                 }
2328         }
2329
2330         return NT_STATUS_OK;
2331 }
2332
2333 NTSTATUS dcesrv_add_ep(struct dcesrv_context *dce_ctx,
2334                        struct loadparm_context *lp_ctx,
2335                        struct dcesrv_endpoint *e,
2336                        struct tevent_context *event_ctx,
2337                        const struct model_ops *model_ops)
2338 {
2339         enum dcerpc_transport_t transport =
2340                 dcerpc_binding_get_transport(e->ep_description);
2341
2342         switch (transport) {
2343         case NCACN_UNIX_STREAM:
2344                 return dcesrv_add_ep_unix(dce_ctx, lp_ctx, e, event_ctx, model_ops);
2345
2346         case NCALRPC:
2347                 return dcesrv_add_ep_ncalrpc(dce_ctx, lp_ctx, e, event_ctx, model_ops);
2348
2349         case NCACN_IP_TCP:
2350                 return dcesrv_add_ep_tcp(dce_ctx, lp_ctx, e, event_ctx, model_ops);
2351
2352         case NCACN_NP:
2353                 return dcesrv_add_ep_np(dce_ctx, lp_ctx, e, event_ctx, model_ops);
2354
2355         default:
2356                 return NT_STATUS_NOT_SUPPORTED;
2357         }
2358 }
2359
2360
2361 /**
2362  * retrieve credentials from a dce_call
2363  */
2364 _PUBLIC_ struct cli_credentials *dcesrv_call_credentials(struct dcesrv_call_state *dce_call)
2365 {
2366         return dce_call->conn->auth_state.session_info->credentials;
2367 }
2368
2369 /**
2370  * returns true if this is an authenticated call
2371  */
2372 _PUBLIC_ bool dcesrv_call_authenticated(struct dcesrv_call_state *dce_call)
2373 {
2374         enum security_user_level level;
2375         level = security_session_user_level(dce_call->conn->auth_state.session_info, NULL);
2376         return level >= SECURITY_USER;
2377 }
2378
2379 /**
2380  * retrieve account_name for a dce_call
2381  */
2382 _PUBLIC_ const char *dcesrv_call_account_name(struct dcesrv_call_state *dce_call)
2383 {
2384         return dce_call->context->conn->auth_state.session_info->info->account_name;
2385 }