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