CVE-2015-5370: s4:rpc_server: maintain in and out struct dcerpc_auth per dcesrv_call_...
[gd/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                 /* we only allow fragmented requests, no other packet types */
1460                 if (call->pkt.ptype != DCERPC_PKT_REQUEST) {
1461                         return dcesrv_fault(call2, DCERPC_FAULT_OTHER);
1462                 }
1463
1464                 /* this is a continuation of an existing call - find the call
1465                    then tack it on the end */
1466                 call = dcesrv_find_fragmented_call(dce_conn, call2->pkt.call_id);
1467                 if (!call) {
1468                         return dcesrv_fault(call2, DCERPC_FAULT_OTHER);
1469                 }
1470
1471                 if (call->pkt.ptype != call2->pkt.ptype) {
1472                         /* trying to play silly buggers are we? */
1473                         return dcesrv_fault(call2, DCERPC_NCA_S_PROTO_ERROR);
1474                 }
1475                 if (memcmp(call->pkt.drep, call2->pkt.drep, sizeof(pkt->drep)) != 0) {
1476                         return dcesrv_fault(call2, DCERPC_NCA_S_PROTO_ERROR);
1477                 }
1478                 if (call->pkt.call_id != call2->pkt.call_id) {
1479                         return dcesrv_fault(call2, DCERPC_NCA_S_PROTO_ERROR);
1480                 }
1481                 if (call->pkt.u.request.context_id != call2->pkt.u.request.context_id)  {
1482                         return dcesrv_fault(call2, DCERPC_NCA_S_PROTO_ERROR);
1483                 }
1484                 if (call->pkt.u.request.opnum != call2->pkt.u.request.opnum)  {
1485                         return dcesrv_fault(call2, DCERPC_NCA_S_PROTO_ERROR);
1486                 }
1487
1488                 alloc_size = call->pkt.u.request.stub_and_verifier.length +
1489                         call2->pkt.u.request.stub_and_verifier.length;
1490                 if (call->pkt.u.request.alloc_hint > alloc_size) {
1491                         alloc_size = call->pkt.u.request.alloc_hint;
1492                 }
1493
1494                 call->pkt.u.request.stub_and_verifier.data = 
1495                         talloc_realloc(call, 
1496                                        call->pkt.u.request.stub_and_verifier.data, 
1497                                        uint8_t, alloc_size);
1498                 if (!call->pkt.u.request.stub_and_verifier.data) {
1499                         return dcesrv_fault(call2, DCERPC_FAULT_OTHER);
1500                 }
1501                 memcpy(call->pkt.u.request.stub_and_verifier.data +
1502                        call->pkt.u.request.stub_and_verifier.length,
1503                        call2->pkt.u.request.stub_and_verifier.data,
1504                        call2->pkt.u.request.stub_and_verifier.length);
1505                 call->pkt.u.request.stub_and_verifier.length += 
1506                         call2->pkt.u.request.stub_and_verifier.length;
1507
1508                 call->pkt.pfc_flags |= (call2->pkt.pfc_flags & DCERPC_PFC_FLAG_LAST);
1509
1510                 talloc_free(call2);
1511         }
1512
1513         /* this may not be the last pdu in the chain - if its isn't then
1514            just put it on the incoming_fragmented_call_list and wait for the rest */
1515         if (call->pkt.ptype == DCERPC_PKT_REQUEST &&
1516             !(call->pkt.pfc_flags & DCERPC_PFC_FLAG_LAST)) {
1517                 dcesrv_call_set_list(call, DCESRV_LIST_FRAGMENTED_CALL_LIST);
1518                 return NT_STATUS_OK;
1519         } 
1520         
1521         /* This removes any fragments we may have had stashed away */
1522         dcesrv_call_set_list(call, DCESRV_LIST_NONE);
1523
1524         switch (call->pkt.ptype) {
1525         case DCERPC_PKT_BIND:
1526                 status = dcesrv_bind_nak(call,
1527                         DCERPC_BIND_NAK_REASON_NOT_SPECIFIED);
1528                 break;
1529         case DCERPC_PKT_AUTH3:
1530                 status = dcesrv_auth3(call);
1531                 break;
1532         case DCERPC_PKT_ALTER:
1533                 status = dcesrv_alter(call);
1534                 break;
1535         case DCERPC_PKT_REQUEST:
1536                 status = dcesrv_request(call);
1537                 break;
1538         default:
1539                 status = dcesrv_fault_disconnect(call, DCERPC_NCA_S_PROTO_ERROR);
1540                 break;
1541         }
1542
1543         /* if we are going to be sending a reply then add
1544            it to the list of pending calls. We add it to the end to keep the call
1545            list in the order we will answer */
1546         if (!NT_STATUS_IS_OK(status)) {
1547                 talloc_free(call);
1548         }
1549
1550         return status;
1551 }
1552
1553 _PUBLIC_ NTSTATUS dcesrv_init_context(TALLOC_CTX *mem_ctx, 
1554                                       struct loadparm_context *lp_ctx,
1555                                       const char **endpoint_servers, struct dcesrv_context **_dce_ctx)
1556 {
1557         NTSTATUS status;
1558         struct dcesrv_context *dce_ctx;
1559         int i;
1560
1561         if (!endpoint_servers) {
1562                 DEBUG(0,("dcesrv_init_context: no endpoint servers configured\n"));
1563                 return NT_STATUS_INTERNAL_ERROR;
1564         }
1565
1566         dce_ctx = talloc_zero(mem_ctx, struct dcesrv_context);
1567         NT_STATUS_HAVE_NO_MEMORY(dce_ctx);
1568
1569         if (uid_wrapper_enabled()) {
1570                 setenv("UID_WRAPPER_MYUID", "1", 1);
1571         }
1572         dce_ctx->initial_euid = geteuid();
1573         if (uid_wrapper_enabled()) {
1574                 unsetenv("UID_WRAPPER_MYUID");
1575         }
1576
1577         dce_ctx->endpoint_list  = NULL;
1578         dce_ctx->lp_ctx = lp_ctx;
1579         dce_ctx->assoc_groups_idr = idr_init(dce_ctx);
1580         NT_STATUS_HAVE_NO_MEMORY(dce_ctx->assoc_groups_idr);
1581         dce_ctx->broken_connections = NULL;
1582
1583         for (i=0;endpoint_servers[i];i++) {
1584                 const struct dcesrv_endpoint_server *ep_server;
1585
1586                 ep_server = dcesrv_ep_server_byname(endpoint_servers[i]);
1587                 if (!ep_server) {
1588                         DEBUG(0,("dcesrv_init_context: failed to find endpoint server = '%s'\n", endpoint_servers[i]));
1589                         return NT_STATUS_INTERNAL_ERROR;
1590                 }
1591
1592                 status = ep_server->init_server(dce_ctx, ep_server);
1593                 if (!NT_STATUS_IS_OK(status)) {
1594                         DEBUG(0,("dcesrv_init_context: failed to init endpoint server = '%s': %s\n", endpoint_servers[i],
1595                                 nt_errstr(status)));
1596                         return status;
1597                 }
1598         }
1599
1600         *_dce_ctx = dce_ctx;
1601         return NT_STATUS_OK;
1602 }
1603
1604 /* the list of currently registered DCERPC endpoint servers.
1605  */
1606 static struct ep_server {
1607         struct dcesrv_endpoint_server *ep_server;
1608 } *ep_servers = NULL;
1609 static int num_ep_servers;
1610
1611 /*
1612   register a DCERPC endpoint server. 
1613
1614   The 'name' can be later used by other backends to find the operations
1615   structure for this backend.  
1616
1617   The 'type' is used to specify whether this is for a disk, printer or IPC$ share
1618 */
1619 _PUBLIC_ NTSTATUS dcerpc_register_ep_server(const void *_ep_server)
1620 {
1621         const struct dcesrv_endpoint_server *ep_server = _ep_server;
1622         
1623         if (dcesrv_ep_server_byname(ep_server->name) != NULL) {
1624                 /* its already registered! */
1625                 DEBUG(0,("DCERPC endpoint server '%s' already registered\n", 
1626                          ep_server->name));
1627                 return NT_STATUS_OBJECT_NAME_COLLISION;
1628         }
1629
1630         ep_servers = realloc_p(ep_servers, struct ep_server, num_ep_servers+1);
1631         if (!ep_servers) {
1632                 smb_panic("out of memory in dcerpc_register");
1633         }
1634
1635         ep_servers[num_ep_servers].ep_server = smb_xmemdup(ep_server, sizeof(*ep_server));
1636         ep_servers[num_ep_servers].ep_server->name = smb_xstrdup(ep_server->name);
1637
1638         num_ep_servers++;
1639
1640         DEBUG(3,("DCERPC endpoint server '%s' registered\n", 
1641                  ep_server->name));
1642
1643         return NT_STATUS_OK;
1644 }
1645
1646 /*
1647   return the operations structure for a named backend of the specified type
1648 */
1649 const struct dcesrv_endpoint_server *dcesrv_ep_server_byname(const char *name)
1650 {
1651         int i;
1652
1653         for (i=0;i<num_ep_servers;i++) {
1654                 if (strcmp(ep_servers[i].ep_server->name, name) == 0) {
1655                         return ep_servers[i].ep_server;
1656                 }
1657         }
1658
1659         return NULL;
1660 }
1661
1662 void dcerpc_server_init(struct loadparm_context *lp_ctx)
1663 {
1664         static bool initialized;
1665 #define _MODULE_PROTO(init) extern NTSTATUS init(void);
1666         STATIC_dcerpc_server_MODULES_PROTO;
1667         init_module_fn static_init[] = { STATIC_dcerpc_server_MODULES };
1668         init_module_fn *shared_init;
1669
1670         if (initialized) {
1671                 return;
1672         }
1673         initialized = true;
1674
1675         shared_init = load_samba_modules(NULL, "dcerpc_server");
1676
1677         run_init_functions(static_init);
1678         run_init_functions(shared_init);
1679
1680         talloc_free(shared_init);
1681 }
1682
1683 /*
1684   return the DCERPC module version, and the size of some critical types
1685   This can be used by endpoint server modules to either detect compilation errors, or provide
1686   multiple implementations for different smbd compilation options in one module
1687 */
1688 const struct dcesrv_critical_sizes *dcerpc_module_version(void)
1689 {
1690         static const struct dcesrv_critical_sizes critical_sizes = {
1691                 DCERPC_MODULE_VERSION,
1692                 sizeof(struct dcesrv_context),
1693                 sizeof(struct dcesrv_endpoint),
1694                 sizeof(struct dcesrv_endpoint_server),
1695                 sizeof(struct dcesrv_interface),
1696                 sizeof(struct dcesrv_if_list),
1697                 sizeof(struct dcesrv_connection),
1698                 sizeof(struct dcesrv_call_state),
1699                 sizeof(struct dcesrv_auth),
1700                 sizeof(struct dcesrv_handle)
1701         };
1702
1703         return &critical_sizes;
1704 }
1705
1706 static void dcesrv_terminate_connection(struct dcesrv_connection *dce_conn, const char *reason)
1707 {
1708         struct dcesrv_context *dce_ctx = dce_conn->dce_ctx;
1709         struct stream_connection *srv_conn;
1710         srv_conn = talloc_get_type(dce_conn->transport.private_data,
1711                                    struct stream_connection);
1712
1713         dce_conn->allow_bind = false;
1714         dce_conn->allow_auth3 = false;
1715         dce_conn->allow_alter = false;
1716         dce_conn->allow_request = false;
1717
1718         if (dce_conn->pending_call_list == NULL) {
1719                 char *full_reason = talloc_asprintf(dce_conn, "dcesrv: %s", reason);
1720
1721                 DLIST_REMOVE(dce_ctx->broken_connections, dce_conn);
1722                 stream_terminate_connection(srv_conn, full_reason ? full_reason : reason);
1723                 return;
1724         }
1725
1726         if (dce_conn->terminate != NULL) {
1727                 return;
1728         }
1729
1730         DEBUG(3,("dcesrv: terminating connection due to '%s' defered due to pending calls\n",
1731                  reason));
1732         dce_conn->terminate = talloc_strdup(dce_conn, reason);
1733         if (dce_conn->terminate == NULL) {
1734                 dce_conn->terminate = "dcesrv: defered terminating connection - no memory";
1735         }
1736         DLIST_ADD_END(dce_ctx->broken_connections, dce_conn);
1737 }
1738
1739 static void dcesrv_cleanup_broken_connections(struct dcesrv_context *dce_ctx)
1740 {
1741         struct dcesrv_connection *cur, *next;
1742
1743         next = dce_ctx->broken_connections;
1744         while (next != NULL) {
1745                 cur = next;
1746                 next = cur->next;
1747
1748                 if (cur->state_flags & DCESRV_CALL_STATE_FLAG_PROCESS_PENDING_CALL) {
1749                         struct dcesrv_connection_context *context_cur, *context_next;
1750
1751                         context_next = cur->contexts;
1752                         while (context_next != NULL) {
1753                                 context_cur = context_next;
1754                                 context_next = context_cur->next;
1755
1756                                 dcesrv_connection_context_destructor(context_cur);
1757                         }
1758                 }
1759
1760                 dcesrv_terminate_connection(cur, cur->terminate);
1761         }
1762 }
1763
1764 /* We need this include to be able to compile on some plateforms
1765  * (ie. freebsd 7.2) as it seems that <sys/uio.h> is not included
1766  * correctly.
1767  * It has to be that deep because otherwise we have a conflict on
1768  * const struct dcesrv_interface declaration.
1769  * This is mostly due to socket_wrapper defining #define bind swrap_bind
1770  * which conflict with the bind used before.
1771  */
1772 #include "system/network.h"
1773
1774 struct dcesrv_sock_reply_state {
1775         struct dcesrv_connection *dce_conn;
1776         struct dcesrv_call_state *call;
1777         struct iovec iov;
1778 };
1779
1780 static void dcesrv_sock_reply_done(struct tevent_req *subreq);
1781 static void dcesrv_call_terminate_step1(struct tevent_req *subreq);
1782
1783 static void dcesrv_sock_report_output_data(struct dcesrv_connection *dce_conn)
1784 {
1785         struct dcesrv_call_state *call;
1786
1787         call = dce_conn->call_list;
1788         if (!call || !call->replies) {
1789                 return;
1790         }
1791
1792         while (call->replies) {
1793                 struct data_blob_list_item *rep = call->replies;
1794                 struct dcesrv_sock_reply_state *substate;
1795                 struct tevent_req *subreq;
1796
1797                 substate = talloc_zero(call, struct dcesrv_sock_reply_state);
1798                 if (!substate) {
1799                         dcesrv_terminate_connection(dce_conn, "no memory");
1800                         return;
1801                 }
1802
1803                 substate->dce_conn = dce_conn;
1804                 substate->call = NULL;
1805
1806                 DLIST_REMOVE(call->replies, rep);
1807
1808                 if (call->replies == NULL && call->terminate_reason == NULL) {
1809                         substate->call = call;
1810                 }
1811
1812                 substate->iov.iov_base = (void *) rep->blob.data;
1813                 substate->iov.iov_len = rep->blob.length;
1814
1815                 subreq = tstream_writev_queue_send(substate,
1816                                                    dce_conn->event_ctx,
1817                                                    dce_conn->stream,
1818                                                    dce_conn->send_queue,
1819                                                    &substate->iov, 1);
1820                 if (!subreq) {
1821                         dcesrv_terminate_connection(dce_conn, "no memory");
1822                         return;
1823                 }
1824                 tevent_req_set_callback(subreq, dcesrv_sock_reply_done,
1825                                         substate);
1826         }
1827
1828         if (call->terminate_reason != NULL) {
1829                 struct tevent_req *subreq;
1830
1831                 subreq = tevent_queue_wait_send(call,
1832                                                 dce_conn->event_ctx,
1833                                                 dce_conn->send_queue);
1834                 if (!subreq) {
1835                         dcesrv_terminate_connection(dce_conn, __location__);
1836                         return;
1837                 }
1838                 tevent_req_set_callback(subreq, dcesrv_call_terminate_step1,
1839                                         call);
1840         }
1841
1842         DLIST_REMOVE(call->conn->call_list, call);
1843         call->list = DCESRV_LIST_NONE;
1844 }
1845
1846 static void dcesrv_sock_reply_done(struct tevent_req *subreq)
1847 {
1848         struct dcesrv_sock_reply_state *substate = tevent_req_callback_data(subreq,
1849                                                 struct dcesrv_sock_reply_state);
1850         int ret;
1851         int sys_errno;
1852         NTSTATUS status;
1853         struct dcesrv_call_state *call = substate->call;
1854
1855         ret = tstream_writev_queue_recv(subreq, &sys_errno);
1856         TALLOC_FREE(subreq);
1857         if (ret == -1) {
1858                 status = map_nt_error_from_unix_common(sys_errno);
1859                 dcesrv_terminate_connection(substate->dce_conn, nt_errstr(status));
1860                 return;
1861         }
1862
1863         talloc_free(substate);
1864         if (call) {
1865                 talloc_free(call);
1866         }
1867 }
1868
1869 static void dcesrv_call_terminate_step2(struct tevent_req *subreq);
1870
1871 static void dcesrv_call_terminate_step1(struct tevent_req *subreq)
1872 {
1873         struct dcesrv_call_state *call = tevent_req_callback_data(subreq,
1874                                                 struct dcesrv_call_state);
1875         bool ok;
1876         struct timeval tv;
1877
1878         /* make sure we stop send queue before removing subreq */
1879         tevent_queue_stop(call->conn->send_queue);
1880
1881         ok = tevent_queue_wait_recv(subreq);
1882         TALLOC_FREE(subreq);
1883         if (!ok) {
1884                 dcesrv_terminate_connection(call->conn, __location__);
1885                 return;
1886         }
1887
1888         /* disconnect after 200 usecs */
1889         tv = timeval_current_ofs_usec(200);
1890         subreq = tevent_wakeup_send(call, call->conn->event_ctx, tv);
1891         if (subreq == NULL) {
1892                 dcesrv_terminate_connection(call->conn, __location__);
1893                 return;
1894         }
1895         tevent_req_set_callback(subreq, dcesrv_call_terminate_step2,
1896                                 call);
1897 }
1898
1899 static void dcesrv_call_terminate_step2(struct tevent_req *subreq)
1900 {
1901         struct dcesrv_call_state *call = tevent_req_callback_data(subreq,
1902                                                 struct dcesrv_call_state);
1903         bool ok;
1904
1905         ok = tevent_wakeup_recv(subreq);
1906         TALLOC_FREE(subreq);
1907         if (!ok) {
1908                 dcesrv_terminate_connection(call->conn, __location__);
1909                 return;
1910         }
1911
1912         dcesrv_terminate_connection(call->conn, call->terminate_reason);
1913 }
1914
1915 struct dcesrv_socket_context {
1916         const struct dcesrv_endpoint *endpoint;
1917         struct dcesrv_context *dcesrv_ctx;
1918 };
1919
1920
1921 static void dcesrv_read_fragment_done(struct tevent_req *subreq);
1922
1923 static void dcesrv_sock_accept(struct stream_connection *srv_conn)
1924 {
1925         NTSTATUS status;
1926         struct dcesrv_socket_context *dcesrv_sock = 
1927                 talloc_get_type(srv_conn->private_data, struct dcesrv_socket_context);
1928         enum dcerpc_transport_t transport =
1929                 dcerpc_binding_get_transport(dcesrv_sock->endpoint->ep_description);
1930         struct dcesrv_connection *dcesrv_conn = NULL;
1931         int ret;
1932         struct tevent_req *subreq;
1933         struct loadparm_context *lp_ctx = dcesrv_sock->dcesrv_ctx->lp_ctx;
1934
1935         dcesrv_cleanup_broken_connections(dcesrv_sock->dcesrv_ctx);
1936
1937         if (!srv_conn->session_info) {
1938                 status = auth_anonymous_session_info(srv_conn,
1939                                                      lp_ctx,
1940                                                      &srv_conn->session_info);
1941                 if (!NT_STATUS_IS_OK(status)) {
1942                         DEBUG(0,("dcesrv_sock_accept: auth_anonymous_session_info failed: %s\n",
1943                                 nt_errstr(status)));
1944                         stream_terminate_connection(srv_conn, nt_errstr(status));
1945                         return;
1946                 }
1947         }
1948
1949         status = dcesrv_endpoint_connect(dcesrv_sock->dcesrv_ctx,
1950                                          srv_conn,
1951                                          dcesrv_sock->endpoint,
1952                                          srv_conn->session_info,
1953                                          srv_conn->event.ctx,
1954                                          srv_conn->msg_ctx,
1955                                          srv_conn->server_id,
1956                                          DCESRV_CALL_STATE_FLAG_MAY_ASYNC,
1957                                          &dcesrv_conn);
1958         if (!NT_STATUS_IS_OK(status)) {
1959                 DEBUG(0,("dcesrv_sock_accept: dcesrv_endpoint_connect failed: %s\n", 
1960                         nt_errstr(status)));
1961                 stream_terminate_connection(srv_conn, nt_errstr(status));
1962                 return;
1963         }
1964
1965         dcesrv_conn->transport.private_data             = srv_conn;
1966         dcesrv_conn->transport.report_output_data       = dcesrv_sock_report_output_data;
1967
1968         TALLOC_FREE(srv_conn->event.fde);
1969
1970         dcesrv_conn->send_queue = tevent_queue_create(dcesrv_conn, "dcesrv send queue");
1971         if (!dcesrv_conn->send_queue) {
1972                 status = NT_STATUS_NO_MEMORY;
1973                 DEBUG(0,("dcesrv_sock_accept: tevent_queue_create(%s)\n",
1974                         nt_errstr(status)));
1975                 stream_terminate_connection(srv_conn, nt_errstr(status));
1976                 return;
1977         }
1978
1979         if (transport == NCACN_NP) {
1980                 dcesrv_conn->auth_state.session_key = dcesrv_inherited_session_key;
1981                 dcesrv_conn->stream = talloc_move(dcesrv_conn,
1982                                                   &srv_conn->tstream);
1983         } else {
1984                 ret = tstream_bsd_existing_socket(dcesrv_conn,
1985                                                   socket_get_fd(srv_conn->socket),
1986                                                   &dcesrv_conn->stream);
1987                 if (ret == -1) {
1988                         status = map_nt_error_from_unix_common(errno);
1989                         DEBUG(0, ("dcesrv_sock_accept: "
1990                                   "failed to setup tstream: %s\n",
1991                                   nt_errstr(status)));
1992                         stream_terminate_connection(srv_conn, nt_errstr(status));
1993                         return;
1994                 }
1995                 socket_set_flags(srv_conn->socket, SOCKET_FLAG_NOCLOSE);
1996         }
1997
1998         dcesrv_conn->local_address = srv_conn->local_address;
1999         dcesrv_conn->remote_address = srv_conn->remote_address;
2000
2001         if (transport == NCALRPC) {
2002                 uid_t uid;
2003                 gid_t gid;
2004
2005                 ret = getpeereid(socket_get_fd(srv_conn->socket), &uid, &gid);
2006                 if (ret == -1) {
2007                         status = map_nt_error_from_unix_common(errno);
2008                         DEBUG(0, ("dcesrv_sock_accept: "
2009                                   "getpeereid() failed for NCALRPC: %s\n",
2010                                   nt_errstr(status)));
2011                         stream_terminate_connection(srv_conn, nt_errstr(status));
2012                         return;
2013                 }
2014                 if (uid == dcesrv_conn->dce_ctx->initial_euid) {
2015                         struct tsocket_address *r = NULL;
2016
2017                         ret = tsocket_address_unix_from_path(dcesrv_conn,
2018                                                              "/root/ncalrpc_as_system",
2019                                                              &r);
2020                         if (ret == -1) {
2021                                 status = map_nt_error_from_unix_common(errno);
2022                                 DEBUG(0, ("dcesrv_sock_accept: "
2023                                           "tsocket_address_unix_from_path() failed for NCALRPC: %s\n",
2024                                           nt_errstr(status)));
2025                                 stream_terminate_connection(srv_conn, nt_errstr(status));
2026                                 return;
2027                         }
2028                         dcesrv_conn->remote_address = r;
2029                 }
2030         }
2031
2032         srv_conn->private_data = dcesrv_conn;
2033
2034         irpc_add_name(srv_conn->msg_ctx, "rpc_server");
2035
2036         subreq = dcerpc_read_ncacn_packet_send(dcesrv_conn,
2037                                                dcesrv_conn->event_ctx,
2038                                                dcesrv_conn->stream);
2039         if (!subreq) {
2040                 status = NT_STATUS_NO_MEMORY;
2041                 DEBUG(0,("dcesrv_sock_accept: dcerpc_read_fragment_buffer_send(%s)\n",
2042                         nt_errstr(status)));
2043                 stream_terminate_connection(srv_conn, nt_errstr(status));
2044                 return;
2045         }
2046         tevent_req_set_callback(subreq, dcesrv_read_fragment_done, dcesrv_conn);
2047
2048         return;
2049 }
2050
2051 static void dcesrv_read_fragment_done(struct tevent_req *subreq)
2052 {
2053         struct dcesrv_connection *dce_conn = tevent_req_callback_data(subreq,
2054                                              struct dcesrv_connection);
2055         struct dcesrv_context *dce_ctx = dce_conn->dce_ctx;
2056         struct ncacn_packet *pkt;
2057         DATA_BLOB buffer;
2058         NTSTATUS status;
2059
2060         if (dce_conn->terminate) {
2061                 /*
2062                  * if the current connection is broken
2063                  * we need to clean it up before any other connection
2064                  */
2065                 dcesrv_terminate_connection(dce_conn, dce_conn->terminate);
2066                 dcesrv_cleanup_broken_connections(dce_ctx);
2067                 return;
2068         }
2069
2070         dcesrv_cleanup_broken_connections(dce_ctx);
2071
2072         status = dcerpc_read_ncacn_packet_recv(subreq, dce_conn,
2073                                                &pkt, &buffer);
2074         TALLOC_FREE(subreq);
2075         if (!NT_STATUS_IS_OK(status)) {
2076                 dcesrv_terminate_connection(dce_conn, nt_errstr(status));
2077                 return;
2078         }
2079
2080         status = dcesrv_process_ncacn_packet(dce_conn, pkt, buffer);
2081         if (!NT_STATUS_IS_OK(status)) {
2082                 dcesrv_terminate_connection(dce_conn, nt_errstr(status));
2083                 return;
2084         }
2085
2086         subreq = dcerpc_read_ncacn_packet_send(dce_conn,
2087                                                dce_conn->event_ctx,
2088                                                dce_conn->stream);
2089         if (!subreq) {
2090                 status = NT_STATUS_NO_MEMORY;
2091                 dcesrv_terminate_connection(dce_conn, nt_errstr(status));
2092                 return;
2093         }
2094         tevent_req_set_callback(subreq, dcesrv_read_fragment_done, dce_conn);
2095 }
2096
2097 static void dcesrv_sock_recv(struct stream_connection *conn, uint16_t flags)
2098 {
2099         struct dcesrv_connection *dce_conn = talloc_get_type(conn->private_data,
2100                                              struct dcesrv_connection);
2101         dcesrv_terminate_connection(dce_conn, "dcesrv_sock_recv triggered");
2102 }
2103
2104 static void dcesrv_sock_send(struct stream_connection *conn, uint16_t flags)
2105 {
2106         struct dcesrv_connection *dce_conn = talloc_get_type(conn->private_data,
2107                                              struct dcesrv_connection);
2108         dcesrv_terminate_connection(dce_conn, "dcesrv_sock_send triggered");
2109 }
2110
2111
2112 static const struct stream_server_ops dcesrv_stream_ops = {
2113         .name                   = "rpc",
2114         .accept_connection      = dcesrv_sock_accept,
2115         .recv_handler           = dcesrv_sock_recv,
2116         .send_handler           = dcesrv_sock_send,
2117 };
2118
2119 static NTSTATUS dcesrv_add_ep_unix(struct dcesrv_context *dce_ctx, 
2120                                    struct loadparm_context *lp_ctx,
2121                                    struct dcesrv_endpoint *e,
2122                             struct tevent_context *event_ctx, const struct model_ops *model_ops)
2123 {
2124         struct dcesrv_socket_context *dcesrv_sock;
2125         uint16_t port = 1;
2126         NTSTATUS status;
2127         const char *endpoint;
2128
2129         dcesrv_sock = talloc_zero(event_ctx, struct dcesrv_socket_context);
2130         NT_STATUS_HAVE_NO_MEMORY(dcesrv_sock);
2131
2132         /* remember the endpoint of this socket */
2133         dcesrv_sock->endpoint           = e;
2134         dcesrv_sock->dcesrv_ctx         = talloc_reference(dcesrv_sock, dce_ctx);
2135
2136         endpoint = dcerpc_binding_get_string_option(e->ep_description, "endpoint");
2137
2138         status = stream_setup_socket(dcesrv_sock, event_ctx, lp_ctx,
2139                                      model_ops, &dcesrv_stream_ops, 
2140                                      "unix", endpoint, &port,
2141                                      lpcfg_socket_options(lp_ctx),
2142                                      dcesrv_sock);
2143         if (!NT_STATUS_IS_OK(status)) {
2144                 DEBUG(0,("service_setup_stream_socket(path=%s) failed - %s\n",
2145                          endpoint, nt_errstr(status)));
2146         }
2147
2148         return status;
2149 }
2150
2151 static NTSTATUS dcesrv_add_ep_ncalrpc(struct dcesrv_context *dce_ctx, 
2152                                       struct loadparm_context *lp_ctx,
2153                                       struct dcesrv_endpoint *e,
2154                                       struct tevent_context *event_ctx, const struct model_ops *model_ops)
2155 {
2156         struct dcesrv_socket_context *dcesrv_sock;
2157         uint16_t port = 1;
2158         char *full_path;
2159         NTSTATUS status;
2160         const char *endpoint;
2161
2162         endpoint = dcerpc_binding_get_string_option(e->ep_description, "endpoint");
2163
2164         if (endpoint == NULL) {
2165                 /*
2166                  * No identifier specified: use DEFAULT.
2167                  *
2168                  * TODO: DO NOT hardcode this value anywhere else. Rather, specify
2169                  * no endpoint and let the epmapper worry about it.
2170                  */
2171                 endpoint = "DEFAULT";
2172                 status = dcerpc_binding_set_string_option(e->ep_description,
2173                                                           "endpoint",
2174                                                           endpoint);
2175                 if (!NT_STATUS_IS_OK(status)) {
2176                         DEBUG(0,("dcerpc_binding_set_string_option() failed - %s\n",
2177                                   nt_errstr(status)));
2178                         return status;
2179                 }
2180         }
2181
2182         full_path = talloc_asprintf(dce_ctx, "%s/%s", lpcfg_ncalrpc_dir(lp_ctx),
2183                                     endpoint);
2184
2185         dcesrv_sock = talloc_zero(event_ctx, struct dcesrv_socket_context);
2186         NT_STATUS_HAVE_NO_MEMORY(dcesrv_sock);
2187
2188         /* remember the endpoint of this socket */
2189         dcesrv_sock->endpoint           = e;
2190         dcesrv_sock->dcesrv_ctx         = talloc_reference(dcesrv_sock, dce_ctx);
2191
2192         status = stream_setup_socket(dcesrv_sock, event_ctx, lp_ctx,
2193                                      model_ops, &dcesrv_stream_ops, 
2194                                      "unix", full_path, &port, 
2195                                      lpcfg_socket_options(lp_ctx),
2196                                      dcesrv_sock);
2197         if (!NT_STATUS_IS_OK(status)) {
2198                 DEBUG(0,("service_setup_stream_socket(identifier=%s,path=%s) failed - %s\n",
2199                          endpoint, full_path, nt_errstr(status)));
2200         }
2201         return status;
2202 }
2203
2204 static NTSTATUS dcesrv_add_ep_np(struct dcesrv_context *dce_ctx,
2205                                  struct loadparm_context *lp_ctx,
2206                                  struct dcesrv_endpoint *e,
2207                                  struct tevent_context *event_ctx, const struct model_ops *model_ops)
2208 {
2209         struct dcesrv_socket_context *dcesrv_sock;
2210         NTSTATUS status;
2211         const char *endpoint;
2212
2213         endpoint = dcerpc_binding_get_string_option(e->ep_description, "endpoint");
2214         if (endpoint == NULL) {
2215                 DEBUG(0, ("Endpoint mandatory for named pipes\n"));
2216                 return NT_STATUS_INVALID_PARAMETER;
2217         }
2218
2219         dcesrv_sock = talloc_zero(event_ctx, struct dcesrv_socket_context);
2220         NT_STATUS_HAVE_NO_MEMORY(dcesrv_sock);
2221
2222         /* remember the endpoint of this socket */
2223         dcesrv_sock->endpoint           = e;
2224         dcesrv_sock->dcesrv_ctx         = talloc_reference(dcesrv_sock, dce_ctx);
2225
2226         status = tstream_setup_named_pipe(dce_ctx, event_ctx, lp_ctx,
2227                                           model_ops, &dcesrv_stream_ops,
2228                                           endpoint,
2229                                           dcesrv_sock);
2230         if (!NT_STATUS_IS_OK(status)) {
2231                 DEBUG(0,("stream_setup_named_pipe(pipe=%s) failed - %s\n",
2232                          endpoint, nt_errstr(status)));
2233                 return status;
2234         }
2235
2236         return NT_STATUS_OK;
2237 }
2238
2239 /*
2240   add a socket address to the list of events, one event per dcerpc endpoint
2241 */
2242 static NTSTATUS add_socket_rpc_tcp_iface(struct dcesrv_context *dce_ctx, struct dcesrv_endpoint *e,
2243                                          struct tevent_context *event_ctx, const struct model_ops *model_ops,
2244                                          const char *address)
2245 {
2246         struct dcesrv_socket_context *dcesrv_sock;
2247         uint16_t port = 0;
2248         NTSTATUS status;
2249         const char *endpoint;
2250         char port_str[6];
2251
2252         endpoint = dcerpc_binding_get_string_option(e->ep_description, "endpoint");
2253         if (endpoint != NULL) {
2254                 port = atoi(endpoint);
2255         }
2256
2257         dcesrv_sock = talloc_zero(event_ctx, struct dcesrv_socket_context);
2258         NT_STATUS_HAVE_NO_MEMORY(dcesrv_sock);
2259
2260         /* remember the endpoint of this socket */
2261         dcesrv_sock->endpoint           = e;
2262         dcesrv_sock->dcesrv_ctx         = talloc_reference(dcesrv_sock, dce_ctx);
2263
2264         status = stream_setup_socket(dcesrv_sock, event_ctx, dce_ctx->lp_ctx,
2265                                      model_ops, &dcesrv_stream_ops, 
2266                                      "ip", address, &port,
2267                                      lpcfg_socket_options(dce_ctx->lp_ctx),
2268                                      dcesrv_sock);
2269         if (!NT_STATUS_IS_OK(status)) {
2270                 DEBUG(0,("service_setup_stream_socket(address=%s,port=%u) failed - %s\n", 
2271                          address, port, nt_errstr(status)));
2272                 return status;
2273         }
2274
2275         snprintf(port_str, sizeof(port_str), "%u", port);
2276
2277         status = dcerpc_binding_set_string_option(e->ep_description,
2278                                                   "endpoint", port_str);
2279         if (!NT_STATUS_IS_OK(status)) {
2280                 DEBUG(0,("dcerpc_binding_set_string_option(endpoint, %s) failed - %s\n",
2281                          port_str, nt_errstr(status)));
2282                 return status;
2283         }
2284
2285         return NT_STATUS_OK;
2286 }
2287
2288 #include "lib/socket/netif.h" /* Included here to work around the fact that socket_wrapper redefines bind() */
2289
2290 static NTSTATUS dcesrv_add_ep_tcp(struct dcesrv_context *dce_ctx, 
2291                                   struct loadparm_context *lp_ctx,
2292                                   struct dcesrv_endpoint *e,
2293                                   struct tevent_context *event_ctx, const struct model_ops *model_ops)
2294 {
2295         NTSTATUS status;
2296
2297         /* Add TCP/IP sockets */
2298         if (lpcfg_interfaces(lp_ctx) && lpcfg_bind_interfaces_only(lp_ctx)) {
2299                 int num_interfaces;
2300                 int i;
2301                 struct interface *ifaces;
2302
2303                 load_interface_list(dce_ctx, lp_ctx, &ifaces);
2304
2305                 num_interfaces = iface_list_count(ifaces);
2306                 for(i = 0; i < num_interfaces; i++) {
2307                         const char *address = iface_list_n_ip(ifaces, i);
2308                         status = add_socket_rpc_tcp_iface(dce_ctx, e, event_ctx, model_ops, address);
2309                         NT_STATUS_NOT_OK_RETURN(status);
2310                 }
2311         } else {
2312                 char **wcard;
2313                 int i;
2314                 int num_binds = 0;
2315                 wcard = iface_list_wildcard(dce_ctx);
2316                 NT_STATUS_HAVE_NO_MEMORY(wcard);
2317                 for (i=0; wcard[i]; i++) {
2318                         status = add_socket_rpc_tcp_iface(dce_ctx, e, event_ctx, model_ops, wcard[i]);
2319                         if (NT_STATUS_IS_OK(status)) {
2320                                 num_binds++;
2321                         }
2322                 }
2323                 talloc_free(wcard);
2324                 if (num_binds == 0) {
2325                         return NT_STATUS_INVALID_PARAMETER_MIX;
2326                 }
2327         }
2328
2329         return NT_STATUS_OK;
2330 }
2331
2332 NTSTATUS dcesrv_add_ep(struct dcesrv_context *dce_ctx,
2333                        struct loadparm_context *lp_ctx,
2334                        struct dcesrv_endpoint *e,
2335                        struct tevent_context *event_ctx,
2336                        const struct model_ops *model_ops)
2337 {
2338         enum dcerpc_transport_t transport =
2339                 dcerpc_binding_get_transport(e->ep_description);
2340
2341         switch (transport) {
2342         case NCACN_UNIX_STREAM:
2343                 return dcesrv_add_ep_unix(dce_ctx, lp_ctx, e, event_ctx, model_ops);
2344
2345         case NCALRPC:
2346                 return dcesrv_add_ep_ncalrpc(dce_ctx, lp_ctx, e, event_ctx, model_ops);
2347
2348         case NCACN_IP_TCP:
2349                 return dcesrv_add_ep_tcp(dce_ctx, lp_ctx, e, event_ctx, model_ops);
2350
2351         case NCACN_NP:
2352                 return dcesrv_add_ep_np(dce_ctx, lp_ctx, e, event_ctx, model_ops);
2353
2354         default:
2355                 return NT_STATUS_NOT_SUPPORTED;
2356         }
2357 }
2358
2359
2360 /**
2361  * retrieve credentials from a dce_call
2362  */
2363 _PUBLIC_ struct cli_credentials *dcesrv_call_credentials(struct dcesrv_call_state *dce_call)
2364 {
2365         return dce_call->conn->auth_state.session_info->credentials;
2366 }
2367
2368 /**
2369  * returns true if this is an authenticated call
2370  */
2371 _PUBLIC_ bool dcesrv_call_authenticated(struct dcesrv_call_state *dce_call)
2372 {
2373         enum security_user_level level;
2374         level = security_session_user_level(dce_call->conn->auth_state.session_info, NULL);
2375         return level >= SECURITY_USER;
2376 }
2377
2378 /**
2379  * retrieve account_name for a dce_call
2380  */
2381 _PUBLIC_ const char *dcesrv_call_account_name(struct dcesrv_call_state *dce_call)
2382 {
2383         return dce_call->context->conn->auth_state.session_info->info->account_name;
2384 }