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