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