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