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