CVE-2015-5370: s4:rpc_server: only allow one fragmented call_id at a time
[kai/samba-autobuild/.git] / source4 / rpc_server / dcerpc_server.c
1 /* 
2    Unix SMB/CIFS implementation.
3
4    server side dcerpc core code
5
6    Copyright (C) Andrew Tridgell 2003-2005
7    Copyright (C) Stefan (metze) Metzmacher 2004-2005
8    
9    This program is free software; you can redistribute it and/or modify
10    it under the terms of the GNU General Public License as published by
11    the Free Software Foundation; either version 3 of the License, or
12    (at your option) any later version.
13    
14    This program is distributed in the hope that it will be useful,
15    but WITHOUT ANY WARRANTY; without even the implied warranty of
16    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17    GNU General Public License for more details.
18    
19    You should have received a copy of the GNU General Public License
20    along with this program.  If not, see <http://www.gnu.org/licenses/>.
21 */
22
23 #include "includes.h"
24 #include "auth/auth.h"
25 #include "auth/gensec/gensec.h"
26 #include "../lib/util/dlinklist.h"
27 #include "rpc_server/dcerpc_server.h"
28 #include "rpc_server/dcerpc_server_proto.h"
29 #include "rpc_server/common/proto.h"
30 #include "librpc/rpc/dcerpc_proto.h"
31 #include "system/filesys.h"
32 #include "libcli/security/security.h"
33 #include "param/param.h"
34 #include "../lib/tsocket/tsocket.h"
35 #include "../libcli/named_pipe_auth/npa_tstream.h"
36 #include "smbd/service_stream.h"
37 #include "../lib/tsocket/tsocket.h"
38 #include "lib/socket/socket.h"
39 #include "smbd/process_model.h"
40 #include "lib/messaging/irpc.h"
41 #include "librpc/rpc/rpc_common.h"
42 #include "lib/util/samba_modules.h"
43 #include "librpc/gen_ndr/ndr_dcerpc.h"
44
45 /* 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         struct dcesrv_call_state *existing = NULL;
1434
1435         call = talloc_zero(dce_conn, struct dcesrv_call_state);
1436         if (!call) {
1437                 data_blob_free(&blob);
1438                 talloc_free(pkt);
1439                 return NT_STATUS_NO_MEMORY;
1440         }
1441         call->conn              = dce_conn;
1442         call->event_ctx         = dce_conn->event_ctx;
1443         call->msg_ctx           = dce_conn->msg_ctx;
1444         call->state_flags       = call->conn->state_flags;
1445         call->time              = timeval_current();
1446         call->list              = DCESRV_LIST_NONE;
1447
1448         talloc_steal(call, pkt);
1449         talloc_steal(call, blob.data);
1450         call->pkt = *pkt;
1451
1452         talloc_set_destructor(call, dcesrv_call_dequeue);
1453
1454         if (call->conn->allow_bind) {
1455                 /*
1456                  * Only one bind is possible per connection
1457                  */
1458                 call->conn->allow_bind = false;
1459                 return dcesrv_bind(call);
1460         }
1461
1462         /* we have to check the signing here, before combining the
1463            pdus */
1464         if (call->pkt.ptype == DCERPC_PKT_REQUEST) {
1465                 if (!call->conn->allow_request) {
1466                         return dcesrv_fault_disconnect(call,
1467                                         DCERPC_NCA_S_PROTO_ERROR);
1468                 }
1469
1470                 status = dcerpc_verify_ncacn_packet_header(&call->pkt,
1471                                 DCERPC_PKT_REQUEST,
1472                                 call->pkt.u.request.stub_and_verifier.length,
1473                                 0, /* required_flags */
1474                                 DCERPC_PFC_FLAG_FIRST |
1475                                 DCERPC_PFC_FLAG_LAST |
1476                                 DCERPC_PFC_FLAG_PENDING_CANCEL |
1477                                 0x08 | /* this is not defined, but should be ignored */
1478                                 DCERPC_PFC_FLAG_CONC_MPX |
1479                                 DCERPC_PFC_FLAG_DID_NOT_EXECUTE |
1480                                 DCERPC_PFC_FLAG_MAYBE |
1481                                 DCERPC_PFC_FLAG_OBJECT_UUID);
1482                 if (!NT_STATUS_IS_OK(status)) {
1483                         return dcesrv_fault_disconnect(call,
1484                                         DCERPC_NCA_S_PROTO_ERROR);
1485                 }
1486
1487                 if (call->pkt.frag_length > DCERPC_FRAG_MAX_SIZE) {
1488                         /*
1489                          * We don't use dcesrv_fault_disconnect()
1490                          * here, because we don't want to set
1491                          * DCERPC_PFC_FLAG_DID_NOT_EXECUTE
1492                          *
1493                          * Note that we don't check against the negotiated
1494                          * max_recv_frag, but a hard coded value.
1495                          */
1496                         dcesrv_call_disconnect_after(call,
1497                                 "dcesrv_auth_request - frag_length too large");
1498                         return dcesrv_fault(call,
1499                                         DCERPC_NCA_S_PROTO_ERROR);
1500                 }
1501
1502                 if (call->pkt.pfc_flags & DCERPC_PFC_FLAG_FIRST) {
1503                         /* only one request is possible in the fragmented list */
1504                         if (dce_conn->incoming_fragmented_call_list != NULL) {
1505                                 TALLOC_FREE(call);
1506                                 call = dce_conn->incoming_fragmented_call_list;
1507                                 dcesrv_call_disconnect_after(call,
1508                                         "dcesrv_auth_request - "
1509                                         "existing fragmented call");
1510                                 return dcesrv_fault(call,
1511                                                 DCERPC_NCA_S_PROTO_ERROR);
1512                         }
1513                 } else {
1514                         const struct dcerpc_request *nr = &call->pkt.u.request;
1515                         const struct dcerpc_request *er = NULL;
1516                         int cmp;
1517
1518                         existing = dcesrv_find_fragmented_call(dce_conn,
1519                                                         call->pkt.call_id);
1520                         if (existing == NULL) {
1521                                 dcesrv_call_disconnect_after(call,
1522                                         "dcesrv_auth_request - "
1523                                         "no existing fragmented call");
1524                                 return dcesrv_fault(call,
1525                                                 DCERPC_NCA_S_PROTO_ERROR);
1526                         }
1527                         er = &existing->pkt.u.request;
1528
1529                         if (call->pkt.ptype != existing->pkt.ptype) {
1530                                 /* trying to play silly buggers are we? */
1531                                 return dcesrv_fault_disconnect(existing,
1532                                                 DCERPC_NCA_S_PROTO_ERROR);
1533                         }
1534                         cmp = memcmp(call->pkt.drep, existing->pkt.drep,
1535                                      sizeof(pkt->drep));
1536                         if (cmp != 0) {
1537                                 return dcesrv_fault_disconnect(existing,
1538                                                 DCERPC_NCA_S_PROTO_ERROR);
1539                         }
1540                         if (nr->context_id != er->context_id)  {
1541                                 return dcesrv_fault_disconnect(existing,
1542                                                 DCERPC_NCA_S_PROTO_ERROR);
1543                         }
1544                         if (nr->opnum != er->opnum)  {
1545                                 return dcesrv_fault_disconnect(existing,
1546                                                 DCERPC_NCA_S_PROTO_ERROR);
1547                         }
1548                 }
1549
1550                 if (!dcesrv_auth_request(call, &blob)) {
1551                         /*
1552                          * We don't use dcesrv_fault_disconnect()
1553                          * here, because we don't want to set
1554                          * DCERPC_PFC_FLAG_DID_NOT_EXECUTE
1555                          */
1556                         dcesrv_call_disconnect_after(call,
1557                                                 "dcesrv_auth_request - failed");
1558                         return dcesrv_fault(call, DCERPC_FAULT_ACCESS_DENIED);
1559                 }
1560         }
1561
1562         /* see if this is a continued packet */
1563         if (existing != NULL) {
1564                 struct dcerpc_request *er = &existing->pkt.u.request;
1565                 const struct dcerpc_request *nr = &call->pkt.u.request;
1566                 size_t available;
1567                 size_t alloc_size;
1568                 size_t alloc_hint;
1569
1570                 /*
1571                  * Up to 4 MByte are allowed by all fragments
1572                  */
1573                 available = DCERPC_NCACN_PAYLOAD_MAX_SIZE;
1574                 if (er->stub_and_verifier.length > available) {
1575                         dcesrv_call_disconnect_after(existing,
1576                                 "dcesrv_auth_request - existing payload too large");
1577                         return dcesrv_fault(existing, DCERPC_FAULT_ACCESS_DENIED);
1578                 }
1579                 available -= er->stub_and_verifier.length;
1580                 if (nr->alloc_hint > available) {
1581                         dcesrv_call_disconnect_after(existing,
1582                                 "dcesrv_auth_request - alloc hint too large");
1583                         return dcesrv_fault(existing, DCERPC_FAULT_ACCESS_DENIED);
1584                 }
1585                 if (nr->stub_and_verifier.length > available) {
1586                         dcesrv_call_disconnect_after(existing,
1587                                 "dcesrv_auth_request - new payload too large");
1588                         return dcesrv_fault(existing, DCERPC_FAULT_ACCESS_DENIED);
1589                 }
1590                 alloc_hint = er->stub_and_verifier.length + nr->alloc_hint;
1591                 /* allocate at least 1 byte */
1592                 alloc_hint = MAX(alloc_hint, 1);
1593                 alloc_size = er->stub_and_verifier.length +
1594                              nr->stub_and_verifier.length;
1595                 alloc_size = MAX(alloc_size, alloc_hint);
1596
1597                 er->stub_and_verifier.data =
1598                         talloc_realloc(existing,
1599                                        er->stub_and_verifier.data,
1600                                        uint8_t, alloc_size);
1601                 if (er->stub_and_verifier.data == NULL) {
1602                         TALLOC_FREE(call);
1603                         return dcesrv_fault_with_flags(existing,
1604                                                        DCERPC_FAULT_OUT_OF_RESOURCES,
1605                                                        DCERPC_PFC_FLAG_DID_NOT_EXECUTE);
1606                 }
1607                 memcpy(er->stub_and_verifier.data +
1608                        er->stub_and_verifier.length,
1609                        nr->stub_and_verifier.data,
1610                        nr->stub_and_verifier.length);
1611                 er->stub_and_verifier.length += nr->stub_and_verifier.length;
1612
1613                 existing->pkt.pfc_flags |= (call->pkt.pfc_flags & DCERPC_PFC_FLAG_LAST);
1614
1615                 TALLOC_FREE(call);
1616                 call = existing;
1617         }
1618
1619         /* this may not be the last pdu in the chain - if its isn't then
1620            just put it on the incoming_fragmented_call_list and wait for the rest */
1621         if (call->pkt.ptype == DCERPC_PKT_REQUEST &&
1622             !(call->pkt.pfc_flags & DCERPC_PFC_FLAG_LAST)) {
1623                 /*
1624                  * Up to 4 MByte are allowed by all fragments
1625                  */
1626                 if (call->pkt.u.request.alloc_hint > DCERPC_NCACN_PAYLOAD_MAX_SIZE) {
1627                         dcesrv_call_disconnect_after(call,
1628                                 "dcesrv_auth_request - initial alloc hint too large");
1629                         return dcesrv_fault(call, DCERPC_FAULT_ACCESS_DENIED);
1630                 }
1631                 dcesrv_call_set_list(call, DCESRV_LIST_FRAGMENTED_CALL_LIST);
1632                 return NT_STATUS_OK;
1633         } 
1634         
1635         /* This removes any fragments we may have had stashed away */
1636         dcesrv_call_set_list(call, DCESRV_LIST_NONE);
1637
1638         switch (call->pkt.ptype) {
1639         case DCERPC_PKT_BIND:
1640                 status = dcesrv_bind_nak(call,
1641                         DCERPC_BIND_NAK_REASON_NOT_SPECIFIED);
1642                 break;
1643         case DCERPC_PKT_AUTH3:
1644                 status = dcesrv_auth3(call);
1645                 break;
1646         case DCERPC_PKT_ALTER:
1647                 status = dcesrv_alter(call);
1648                 break;
1649         case DCERPC_PKT_REQUEST:
1650                 status = dcesrv_request(call);
1651                 break;
1652         default:
1653                 status = dcesrv_fault_disconnect(call, DCERPC_NCA_S_PROTO_ERROR);
1654                 break;
1655         }
1656
1657         /* if we are going to be sending a reply then add
1658            it to the list of pending calls. We add it to the end to keep the call
1659            list in the order we will answer */
1660         if (!NT_STATUS_IS_OK(status)) {
1661                 talloc_free(call);
1662         }
1663
1664         return status;
1665 }
1666
1667 _PUBLIC_ NTSTATUS dcesrv_init_context(TALLOC_CTX *mem_ctx, 
1668                                       struct loadparm_context *lp_ctx,
1669                                       const char **endpoint_servers, struct dcesrv_context **_dce_ctx)
1670 {
1671         NTSTATUS status;
1672         struct dcesrv_context *dce_ctx;
1673         int i;
1674
1675         if (!endpoint_servers) {
1676                 DEBUG(0,("dcesrv_init_context: no endpoint servers configured\n"));
1677                 return NT_STATUS_INTERNAL_ERROR;
1678         }
1679
1680         dce_ctx = talloc_zero(mem_ctx, struct dcesrv_context);
1681         NT_STATUS_HAVE_NO_MEMORY(dce_ctx);
1682
1683         if (uid_wrapper_enabled()) {
1684                 setenv("UID_WRAPPER_MYUID", "1", 1);
1685         }
1686         dce_ctx->initial_euid = geteuid();
1687         if (uid_wrapper_enabled()) {
1688                 unsetenv("UID_WRAPPER_MYUID");
1689         }
1690
1691         dce_ctx->endpoint_list  = NULL;
1692         dce_ctx->lp_ctx = lp_ctx;
1693         dce_ctx->assoc_groups_idr = idr_init(dce_ctx);
1694         NT_STATUS_HAVE_NO_MEMORY(dce_ctx->assoc_groups_idr);
1695         dce_ctx->broken_connections = NULL;
1696
1697         for (i=0;endpoint_servers[i];i++) {
1698                 const struct dcesrv_endpoint_server *ep_server;
1699
1700                 ep_server = dcesrv_ep_server_byname(endpoint_servers[i]);
1701                 if (!ep_server) {
1702                         DEBUG(0,("dcesrv_init_context: failed to find endpoint server = '%s'\n", endpoint_servers[i]));
1703                         return NT_STATUS_INTERNAL_ERROR;
1704                 }
1705
1706                 status = ep_server->init_server(dce_ctx, ep_server);
1707                 if (!NT_STATUS_IS_OK(status)) {
1708                         DEBUG(0,("dcesrv_init_context: failed to init endpoint server = '%s': %s\n", endpoint_servers[i],
1709                                 nt_errstr(status)));
1710                         return status;
1711                 }
1712         }
1713
1714         *_dce_ctx = dce_ctx;
1715         return NT_STATUS_OK;
1716 }
1717
1718 /* the list of currently registered DCERPC endpoint servers.
1719  */
1720 static struct ep_server {
1721         struct dcesrv_endpoint_server *ep_server;
1722 } *ep_servers = NULL;
1723 static int num_ep_servers;
1724
1725 /*
1726   register a DCERPC endpoint server. 
1727
1728   The 'name' can be later used by other backends to find the operations
1729   structure for this backend.  
1730
1731   The 'type' is used to specify whether this is for a disk, printer or IPC$ share
1732 */
1733 _PUBLIC_ NTSTATUS dcerpc_register_ep_server(const void *_ep_server)
1734 {
1735         const struct dcesrv_endpoint_server *ep_server = _ep_server;
1736         
1737         if (dcesrv_ep_server_byname(ep_server->name) != NULL) {
1738                 /* its already registered! */
1739                 DEBUG(0,("DCERPC endpoint server '%s' already registered\n", 
1740                          ep_server->name));
1741                 return NT_STATUS_OBJECT_NAME_COLLISION;
1742         }
1743
1744         ep_servers = realloc_p(ep_servers, struct ep_server, num_ep_servers+1);
1745         if (!ep_servers) {
1746                 smb_panic("out of memory in dcerpc_register");
1747         }
1748
1749         ep_servers[num_ep_servers].ep_server = smb_xmemdup(ep_server, sizeof(*ep_server));
1750         ep_servers[num_ep_servers].ep_server->name = smb_xstrdup(ep_server->name);
1751
1752         num_ep_servers++;
1753
1754         DEBUG(3,("DCERPC endpoint server '%s' registered\n", 
1755                  ep_server->name));
1756
1757         return NT_STATUS_OK;
1758 }
1759
1760 /*
1761   return the operations structure for a named backend of the specified type
1762 */
1763 const struct dcesrv_endpoint_server *dcesrv_ep_server_byname(const char *name)
1764 {
1765         int i;
1766
1767         for (i=0;i<num_ep_servers;i++) {
1768                 if (strcmp(ep_servers[i].ep_server->name, name) == 0) {
1769                         return ep_servers[i].ep_server;
1770                 }
1771         }
1772
1773         return NULL;
1774 }
1775
1776 void dcerpc_server_init(struct loadparm_context *lp_ctx)
1777 {
1778         static bool initialized;
1779 #define _MODULE_PROTO(init) extern NTSTATUS init(void);
1780         STATIC_dcerpc_server_MODULES_PROTO;
1781         init_module_fn static_init[] = { STATIC_dcerpc_server_MODULES };
1782         init_module_fn *shared_init;
1783
1784         if (initialized) {
1785                 return;
1786         }
1787         initialized = true;
1788
1789         shared_init = load_samba_modules(NULL, "dcerpc_server");
1790
1791         run_init_functions(static_init);
1792         run_init_functions(shared_init);
1793
1794         talloc_free(shared_init);
1795 }
1796
1797 /*
1798   return the DCERPC module version, and the size of some critical types
1799   This can be used by endpoint server modules to either detect compilation errors, or provide
1800   multiple implementations for different smbd compilation options in one module
1801 */
1802 const struct dcesrv_critical_sizes *dcerpc_module_version(void)
1803 {
1804         static const struct dcesrv_critical_sizes critical_sizes = {
1805                 DCERPC_MODULE_VERSION,
1806                 sizeof(struct dcesrv_context),
1807                 sizeof(struct dcesrv_endpoint),
1808                 sizeof(struct dcesrv_endpoint_server),
1809                 sizeof(struct dcesrv_interface),
1810                 sizeof(struct dcesrv_if_list),
1811                 sizeof(struct dcesrv_connection),
1812                 sizeof(struct dcesrv_call_state),
1813                 sizeof(struct dcesrv_auth),
1814                 sizeof(struct dcesrv_handle)
1815         };
1816
1817         return &critical_sizes;
1818 }
1819
1820 static void dcesrv_terminate_connection(struct dcesrv_connection *dce_conn, const char *reason)
1821 {
1822         struct dcesrv_context *dce_ctx = dce_conn->dce_ctx;
1823         struct stream_connection *srv_conn;
1824         srv_conn = talloc_get_type(dce_conn->transport.private_data,
1825                                    struct stream_connection);
1826
1827         dce_conn->allow_bind = false;
1828         dce_conn->allow_auth3 = false;
1829         dce_conn->allow_alter = false;
1830         dce_conn->allow_request = false;
1831
1832         if (dce_conn->pending_call_list == NULL) {
1833                 char *full_reason = talloc_asprintf(dce_conn, "dcesrv: %s", reason);
1834
1835                 DLIST_REMOVE(dce_ctx->broken_connections, dce_conn);
1836                 stream_terminate_connection(srv_conn, full_reason ? full_reason : reason);
1837                 return;
1838         }
1839
1840         if (dce_conn->terminate != NULL) {
1841                 return;
1842         }
1843
1844         DEBUG(3,("dcesrv: terminating connection due to '%s' defered due to pending calls\n",
1845                  reason));
1846         dce_conn->terminate = talloc_strdup(dce_conn, reason);
1847         if (dce_conn->terminate == NULL) {
1848                 dce_conn->terminate = "dcesrv: defered terminating connection - no memory";
1849         }
1850         DLIST_ADD_END(dce_ctx->broken_connections, dce_conn);
1851 }
1852
1853 static void dcesrv_cleanup_broken_connections(struct dcesrv_context *dce_ctx)
1854 {
1855         struct dcesrv_connection *cur, *next;
1856
1857         next = dce_ctx->broken_connections;
1858         while (next != NULL) {
1859                 cur = next;
1860                 next = cur->next;
1861
1862                 if (cur->state_flags & DCESRV_CALL_STATE_FLAG_PROCESS_PENDING_CALL) {
1863                         struct dcesrv_connection_context *context_cur, *context_next;
1864
1865                         context_next = cur->contexts;
1866                         while (context_next != NULL) {
1867                                 context_cur = context_next;
1868                                 context_next = context_cur->next;
1869
1870                                 dcesrv_connection_context_destructor(context_cur);
1871                         }
1872                 }
1873
1874                 dcesrv_terminate_connection(cur, cur->terminate);
1875         }
1876 }
1877
1878 /* We need this include to be able to compile on some plateforms
1879  * (ie. freebsd 7.2) as it seems that <sys/uio.h> is not included
1880  * correctly.
1881  * It has to be that deep because otherwise we have a conflict on
1882  * const struct dcesrv_interface declaration.
1883  * This is mostly due to socket_wrapper defining #define bind swrap_bind
1884  * which conflict with the bind used before.
1885  */
1886 #include "system/network.h"
1887
1888 struct dcesrv_sock_reply_state {
1889         struct dcesrv_connection *dce_conn;
1890         struct dcesrv_call_state *call;
1891         struct iovec iov;
1892 };
1893
1894 static void dcesrv_sock_reply_done(struct tevent_req *subreq);
1895 static void dcesrv_call_terminate_step1(struct tevent_req *subreq);
1896
1897 static void dcesrv_sock_report_output_data(struct dcesrv_connection *dce_conn)
1898 {
1899         struct dcesrv_call_state *call;
1900
1901         call = dce_conn->call_list;
1902         if (!call || !call->replies) {
1903                 return;
1904         }
1905
1906         while (call->replies) {
1907                 struct data_blob_list_item *rep = call->replies;
1908                 struct dcesrv_sock_reply_state *substate;
1909                 struct tevent_req *subreq;
1910
1911                 substate = talloc_zero(call, struct dcesrv_sock_reply_state);
1912                 if (!substate) {
1913                         dcesrv_terminate_connection(dce_conn, "no memory");
1914                         return;
1915                 }
1916
1917                 substate->dce_conn = dce_conn;
1918                 substate->call = NULL;
1919
1920                 DLIST_REMOVE(call->replies, rep);
1921
1922                 if (call->replies == NULL && call->terminate_reason == NULL) {
1923                         substate->call = call;
1924                 }
1925
1926                 substate->iov.iov_base = (void *) rep->blob.data;
1927                 substate->iov.iov_len = rep->blob.length;
1928
1929                 subreq = tstream_writev_queue_send(substate,
1930                                                    dce_conn->event_ctx,
1931                                                    dce_conn->stream,
1932                                                    dce_conn->send_queue,
1933                                                    &substate->iov, 1);
1934                 if (!subreq) {
1935                         dcesrv_terminate_connection(dce_conn, "no memory");
1936                         return;
1937                 }
1938                 tevent_req_set_callback(subreq, dcesrv_sock_reply_done,
1939                                         substate);
1940         }
1941
1942         if (call->terminate_reason != NULL) {
1943                 struct tevent_req *subreq;
1944
1945                 subreq = tevent_queue_wait_send(call,
1946                                                 dce_conn->event_ctx,
1947                                                 dce_conn->send_queue);
1948                 if (!subreq) {
1949                         dcesrv_terminate_connection(dce_conn, __location__);
1950                         return;
1951                 }
1952                 tevent_req_set_callback(subreq, dcesrv_call_terminate_step1,
1953                                         call);
1954         }
1955
1956         DLIST_REMOVE(call->conn->call_list, call);
1957         call->list = DCESRV_LIST_NONE;
1958 }
1959
1960 static void dcesrv_sock_reply_done(struct tevent_req *subreq)
1961 {
1962         struct dcesrv_sock_reply_state *substate = tevent_req_callback_data(subreq,
1963                                                 struct dcesrv_sock_reply_state);
1964         int ret;
1965         int sys_errno;
1966         NTSTATUS status;
1967         struct dcesrv_call_state *call = substate->call;
1968
1969         ret = tstream_writev_queue_recv(subreq, &sys_errno);
1970         TALLOC_FREE(subreq);
1971         if (ret == -1) {
1972                 status = map_nt_error_from_unix_common(sys_errno);
1973                 dcesrv_terminate_connection(substate->dce_conn, nt_errstr(status));
1974                 return;
1975         }
1976
1977         talloc_free(substate);
1978         if (call) {
1979                 talloc_free(call);
1980         }
1981 }
1982
1983 static void dcesrv_call_terminate_step2(struct tevent_req *subreq);
1984
1985 static void dcesrv_call_terminate_step1(struct tevent_req *subreq)
1986 {
1987         struct dcesrv_call_state *call = tevent_req_callback_data(subreq,
1988                                                 struct dcesrv_call_state);
1989         bool ok;
1990         struct timeval tv;
1991
1992         /* make sure we stop send queue before removing subreq */
1993         tevent_queue_stop(call->conn->send_queue);
1994
1995         ok = tevent_queue_wait_recv(subreq);
1996         TALLOC_FREE(subreq);
1997         if (!ok) {
1998                 dcesrv_terminate_connection(call->conn, __location__);
1999                 return;
2000         }
2001
2002         /* disconnect after 200 usecs */
2003         tv = timeval_current_ofs_usec(200);
2004         subreq = tevent_wakeup_send(call, call->conn->event_ctx, tv);
2005         if (subreq == NULL) {
2006                 dcesrv_terminate_connection(call->conn, __location__);
2007                 return;
2008         }
2009         tevent_req_set_callback(subreq, dcesrv_call_terminate_step2,
2010                                 call);
2011 }
2012
2013 static void dcesrv_call_terminate_step2(struct tevent_req *subreq)
2014 {
2015         struct dcesrv_call_state *call = tevent_req_callback_data(subreq,
2016                                                 struct dcesrv_call_state);
2017         bool ok;
2018
2019         ok = tevent_wakeup_recv(subreq);
2020         TALLOC_FREE(subreq);
2021         if (!ok) {
2022                 dcesrv_terminate_connection(call->conn, __location__);
2023                 return;
2024         }
2025
2026         dcesrv_terminate_connection(call->conn, call->terminate_reason);
2027 }
2028
2029 struct dcesrv_socket_context {
2030         const struct dcesrv_endpoint *endpoint;
2031         struct dcesrv_context *dcesrv_ctx;
2032 };
2033
2034
2035 static void dcesrv_read_fragment_done(struct tevent_req *subreq);
2036
2037 static void dcesrv_sock_accept(struct stream_connection *srv_conn)
2038 {
2039         NTSTATUS status;
2040         struct dcesrv_socket_context *dcesrv_sock = 
2041                 talloc_get_type(srv_conn->private_data, struct dcesrv_socket_context);
2042         enum dcerpc_transport_t transport =
2043                 dcerpc_binding_get_transport(dcesrv_sock->endpoint->ep_description);
2044         struct dcesrv_connection *dcesrv_conn = NULL;
2045         int ret;
2046         struct tevent_req *subreq;
2047         struct loadparm_context *lp_ctx = dcesrv_sock->dcesrv_ctx->lp_ctx;
2048
2049         dcesrv_cleanup_broken_connections(dcesrv_sock->dcesrv_ctx);
2050
2051         if (!srv_conn->session_info) {
2052                 status = auth_anonymous_session_info(srv_conn,
2053                                                      lp_ctx,
2054                                                      &srv_conn->session_info);
2055                 if (!NT_STATUS_IS_OK(status)) {
2056                         DEBUG(0,("dcesrv_sock_accept: auth_anonymous_session_info failed: %s\n",
2057                                 nt_errstr(status)));
2058                         stream_terminate_connection(srv_conn, nt_errstr(status));
2059                         return;
2060                 }
2061         }
2062
2063         status = dcesrv_endpoint_connect(dcesrv_sock->dcesrv_ctx,
2064                                          srv_conn,
2065                                          dcesrv_sock->endpoint,
2066                                          srv_conn->session_info,
2067                                          srv_conn->event.ctx,
2068                                          srv_conn->msg_ctx,
2069                                          srv_conn->server_id,
2070                                          DCESRV_CALL_STATE_FLAG_MAY_ASYNC,
2071                                          &dcesrv_conn);
2072         if (!NT_STATUS_IS_OK(status)) {
2073                 DEBUG(0,("dcesrv_sock_accept: dcesrv_endpoint_connect failed: %s\n", 
2074                         nt_errstr(status)));
2075                 stream_terminate_connection(srv_conn, nt_errstr(status));
2076                 return;
2077         }
2078
2079         dcesrv_conn->transport.private_data             = srv_conn;
2080         dcesrv_conn->transport.report_output_data       = dcesrv_sock_report_output_data;
2081
2082         TALLOC_FREE(srv_conn->event.fde);
2083
2084         dcesrv_conn->send_queue = tevent_queue_create(dcesrv_conn, "dcesrv send queue");
2085         if (!dcesrv_conn->send_queue) {
2086                 status = NT_STATUS_NO_MEMORY;
2087                 DEBUG(0,("dcesrv_sock_accept: tevent_queue_create(%s)\n",
2088                         nt_errstr(status)));
2089                 stream_terminate_connection(srv_conn, nt_errstr(status));
2090                 return;
2091         }
2092
2093         if (transport == NCACN_NP) {
2094                 dcesrv_conn->auth_state.session_key = dcesrv_inherited_session_key;
2095                 dcesrv_conn->stream = talloc_move(dcesrv_conn,
2096                                                   &srv_conn->tstream);
2097         } else {
2098                 ret = tstream_bsd_existing_socket(dcesrv_conn,
2099                                                   socket_get_fd(srv_conn->socket),
2100                                                   &dcesrv_conn->stream);
2101                 if (ret == -1) {
2102                         status = map_nt_error_from_unix_common(errno);
2103                         DEBUG(0, ("dcesrv_sock_accept: "
2104                                   "failed to setup tstream: %s\n",
2105                                   nt_errstr(status)));
2106                         stream_terminate_connection(srv_conn, nt_errstr(status));
2107                         return;
2108                 }
2109                 socket_set_flags(srv_conn->socket, SOCKET_FLAG_NOCLOSE);
2110         }
2111
2112         dcesrv_conn->local_address = srv_conn->local_address;
2113         dcesrv_conn->remote_address = srv_conn->remote_address;
2114
2115         if (transport == NCALRPC) {
2116                 uid_t uid;
2117                 gid_t gid;
2118
2119                 ret = getpeereid(socket_get_fd(srv_conn->socket), &uid, &gid);
2120                 if (ret == -1) {
2121                         status = map_nt_error_from_unix_common(errno);
2122                         DEBUG(0, ("dcesrv_sock_accept: "
2123                                   "getpeereid() failed for NCALRPC: %s\n",
2124                                   nt_errstr(status)));
2125                         stream_terminate_connection(srv_conn, nt_errstr(status));
2126                         return;
2127                 }
2128                 if (uid == dcesrv_conn->dce_ctx->initial_euid) {
2129                         struct tsocket_address *r = NULL;
2130
2131                         ret = tsocket_address_unix_from_path(dcesrv_conn,
2132                                                              "/root/ncalrpc_as_system",
2133                                                              &r);
2134                         if (ret == -1) {
2135                                 status = map_nt_error_from_unix_common(errno);
2136                                 DEBUG(0, ("dcesrv_sock_accept: "
2137                                           "tsocket_address_unix_from_path() failed for NCALRPC: %s\n",
2138                                           nt_errstr(status)));
2139                                 stream_terminate_connection(srv_conn, nt_errstr(status));
2140                                 return;
2141                         }
2142                         dcesrv_conn->remote_address = r;
2143                 }
2144         }
2145
2146         srv_conn->private_data = dcesrv_conn;
2147
2148         irpc_add_name(srv_conn->msg_ctx, "rpc_server");
2149
2150         subreq = dcerpc_read_ncacn_packet_send(dcesrv_conn,
2151                                                dcesrv_conn->event_ctx,
2152                                                dcesrv_conn->stream);
2153         if (!subreq) {
2154                 status = NT_STATUS_NO_MEMORY;
2155                 DEBUG(0,("dcesrv_sock_accept: dcerpc_read_fragment_buffer_send(%s)\n",
2156                         nt_errstr(status)));
2157                 stream_terminate_connection(srv_conn, nt_errstr(status));
2158                 return;
2159         }
2160         tevent_req_set_callback(subreq, dcesrv_read_fragment_done, dcesrv_conn);
2161
2162         return;
2163 }
2164
2165 static void dcesrv_read_fragment_done(struct tevent_req *subreq)
2166 {
2167         struct dcesrv_connection *dce_conn = tevent_req_callback_data(subreq,
2168                                              struct dcesrv_connection);
2169         struct dcesrv_context *dce_ctx = dce_conn->dce_ctx;
2170         struct ncacn_packet *pkt;
2171         DATA_BLOB buffer;
2172         NTSTATUS status;
2173
2174         if (dce_conn->terminate) {
2175                 /*
2176                  * if the current connection is broken
2177                  * we need to clean it up before any other connection
2178                  */
2179                 dcesrv_terminate_connection(dce_conn, dce_conn->terminate);
2180                 dcesrv_cleanup_broken_connections(dce_ctx);
2181                 return;
2182         }
2183
2184         dcesrv_cleanup_broken_connections(dce_ctx);
2185
2186         status = dcerpc_read_ncacn_packet_recv(subreq, dce_conn,
2187                                                &pkt, &buffer);
2188         TALLOC_FREE(subreq);
2189         if (!NT_STATUS_IS_OK(status)) {
2190                 dcesrv_terminate_connection(dce_conn, nt_errstr(status));
2191                 return;
2192         }
2193
2194         status = dcesrv_process_ncacn_packet(dce_conn, pkt, buffer);
2195         if (!NT_STATUS_IS_OK(status)) {
2196                 dcesrv_terminate_connection(dce_conn, nt_errstr(status));
2197                 return;
2198         }
2199
2200         subreq = dcerpc_read_ncacn_packet_send(dce_conn,
2201                                                dce_conn->event_ctx,
2202                                                dce_conn->stream);
2203         if (!subreq) {
2204                 status = NT_STATUS_NO_MEMORY;
2205                 dcesrv_terminate_connection(dce_conn, nt_errstr(status));
2206                 return;
2207         }
2208         tevent_req_set_callback(subreq, dcesrv_read_fragment_done, dce_conn);
2209 }
2210
2211 static void dcesrv_sock_recv(struct stream_connection *conn, uint16_t flags)
2212 {
2213         struct dcesrv_connection *dce_conn = talloc_get_type(conn->private_data,
2214                                              struct dcesrv_connection);
2215         dcesrv_terminate_connection(dce_conn, "dcesrv_sock_recv triggered");
2216 }
2217
2218 static void dcesrv_sock_send(struct stream_connection *conn, uint16_t flags)
2219 {
2220         struct dcesrv_connection *dce_conn = talloc_get_type(conn->private_data,
2221                                              struct dcesrv_connection);
2222         dcesrv_terminate_connection(dce_conn, "dcesrv_sock_send triggered");
2223 }
2224
2225
2226 static const struct stream_server_ops dcesrv_stream_ops = {
2227         .name                   = "rpc",
2228         .accept_connection      = dcesrv_sock_accept,
2229         .recv_handler           = dcesrv_sock_recv,
2230         .send_handler           = dcesrv_sock_send,
2231 };
2232
2233 static NTSTATUS dcesrv_add_ep_unix(struct dcesrv_context *dce_ctx, 
2234                                    struct loadparm_context *lp_ctx,
2235                                    struct dcesrv_endpoint *e,
2236                             struct tevent_context *event_ctx, const struct model_ops *model_ops)
2237 {
2238         struct dcesrv_socket_context *dcesrv_sock;
2239         uint16_t port = 1;
2240         NTSTATUS status;
2241         const char *endpoint;
2242
2243         dcesrv_sock = talloc_zero(event_ctx, struct dcesrv_socket_context);
2244         NT_STATUS_HAVE_NO_MEMORY(dcesrv_sock);
2245
2246         /* remember the endpoint of this socket */
2247         dcesrv_sock->endpoint           = e;
2248         dcesrv_sock->dcesrv_ctx         = talloc_reference(dcesrv_sock, dce_ctx);
2249
2250         endpoint = dcerpc_binding_get_string_option(e->ep_description, "endpoint");
2251
2252         status = stream_setup_socket(dcesrv_sock, event_ctx, lp_ctx,
2253                                      model_ops, &dcesrv_stream_ops, 
2254                                      "unix", endpoint, &port,
2255                                      lpcfg_socket_options(lp_ctx),
2256                                      dcesrv_sock);
2257         if (!NT_STATUS_IS_OK(status)) {
2258                 DEBUG(0,("service_setup_stream_socket(path=%s) failed - %s\n",
2259                          endpoint, nt_errstr(status)));
2260         }
2261
2262         return status;
2263 }
2264
2265 static NTSTATUS dcesrv_add_ep_ncalrpc(struct dcesrv_context *dce_ctx, 
2266                                       struct loadparm_context *lp_ctx,
2267                                       struct dcesrv_endpoint *e,
2268                                       struct tevent_context *event_ctx, const struct model_ops *model_ops)
2269 {
2270         struct dcesrv_socket_context *dcesrv_sock;
2271         uint16_t port = 1;
2272         char *full_path;
2273         NTSTATUS status;
2274         const char *endpoint;
2275
2276         endpoint = dcerpc_binding_get_string_option(e->ep_description, "endpoint");
2277
2278         if (endpoint == NULL) {
2279                 /*
2280                  * No identifier specified: use DEFAULT.
2281                  *
2282                  * TODO: DO NOT hardcode this value anywhere else. Rather, specify
2283                  * no endpoint and let the epmapper worry about it.
2284                  */
2285                 endpoint = "DEFAULT";
2286                 status = dcerpc_binding_set_string_option(e->ep_description,
2287                                                           "endpoint",
2288                                                           endpoint);
2289                 if (!NT_STATUS_IS_OK(status)) {
2290                         DEBUG(0,("dcerpc_binding_set_string_option() failed - %s\n",
2291                                   nt_errstr(status)));
2292                         return status;
2293                 }
2294         }
2295
2296         full_path = talloc_asprintf(dce_ctx, "%s/%s", lpcfg_ncalrpc_dir(lp_ctx),
2297                                     endpoint);
2298
2299         dcesrv_sock = talloc_zero(event_ctx, struct dcesrv_socket_context);
2300         NT_STATUS_HAVE_NO_MEMORY(dcesrv_sock);
2301
2302         /* remember the endpoint of this socket */
2303         dcesrv_sock->endpoint           = e;
2304         dcesrv_sock->dcesrv_ctx         = talloc_reference(dcesrv_sock, dce_ctx);
2305
2306         status = stream_setup_socket(dcesrv_sock, event_ctx, lp_ctx,
2307                                      model_ops, &dcesrv_stream_ops, 
2308                                      "unix", full_path, &port, 
2309                                      lpcfg_socket_options(lp_ctx),
2310                                      dcesrv_sock);
2311         if (!NT_STATUS_IS_OK(status)) {
2312                 DEBUG(0,("service_setup_stream_socket(identifier=%s,path=%s) failed - %s\n",
2313                          endpoint, full_path, nt_errstr(status)));
2314         }
2315         return status;
2316 }
2317
2318 static NTSTATUS dcesrv_add_ep_np(struct dcesrv_context *dce_ctx,
2319                                  struct loadparm_context *lp_ctx,
2320                                  struct dcesrv_endpoint *e,
2321                                  struct tevent_context *event_ctx, const struct model_ops *model_ops)
2322 {
2323         struct dcesrv_socket_context *dcesrv_sock;
2324         NTSTATUS status;
2325         const char *endpoint;
2326
2327         endpoint = dcerpc_binding_get_string_option(e->ep_description, "endpoint");
2328         if (endpoint == NULL) {
2329                 DEBUG(0, ("Endpoint mandatory for named pipes\n"));
2330                 return NT_STATUS_INVALID_PARAMETER;
2331         }
2332
2333         dcesrv_sock = talloc_zero(event_ctx, struct dcesrv_socket_context);
2334         NT_STATUS_HAVE_NO_MEMORY(dcesrv_sock);
2335
2336         /* remember the endpoint of this socket */
2337         dcesrv_sock->endpoint           = e;
2338         dcesrv_sock->dcesrv_ctx         = talloc_reference(dcesrv_sock, dce_ctx);
2339
2340         status = tstream_setup_named_pipe(dce_ctx, event_ctx, lp_ctx,
2341                                           model_ops, &dcesrv_stream_ops,
2342                                           endpoint,
2343                                           dcesrv_sock);
2344         if (!NT_STATUS_IS_OK(status)) {
2345                 DEBUG(0,("stream_setup_named_pipe(pipe=%s) failed - %s\n",
2346                          endpoint, nt_errstr(status)));
2347                 return status;
2348         }
2349
2350         return NT_STATUS_OK;
2351 }
2352
2353 /*
2354   add a socket address to the list of events, one event per dcerpc endpoint
2355 */
2356 static NTSTATUS add_socket_rpc_tcp_iface(struct dcesrv_context *dce_ctx, struct dcesrv_endpoint *e,
2357                                          struct tevent_context *event_ctx, const struct model_ops *model_ops,
2358                                          const char *address)
2359 {
2360         struct dcesrv_socket_context *dcesrv_sock;
2361         uint16_t port = 0;
2362         NTSTATUS status;
2363         const char *endpoint;
2364         char port_str[6];
2365
2366         endpoint = dcerpc_binding_get_string_option(e->ep_description, "endpoint");
2367         if (endpoint != NULL) {
2368                 port = atoi(endpoint);
2369         }
2370
2371         dcesrv_sock = talloc_zero(event_ctx, struct dcesrv_socket_context);
2372         NT_STATUS_HAVE_NO_MEMORY(dcesrv_sock);
2373
2374         /* remember the endpoint of this socket */
2375         dcesrv_sock->endpoint           = e;
2376         dcesrv_sock->dcesrv_ctx         = talloc_reference(dcesrv_sock, dce_ctx);
2377
2378         status = stream_setup_socket(dcesrv_sock, event_ctx, dce_ctx->lp_ctx,
2379                                      model_ops, &dcesrv_stream_ops, 
2380                                      "ip", address, &port,
2381                                      lpcfg_socket_options(dce_ctx->lp_ctx),
2382                                      dcesrv_sock);
2383         if (!NT_STATUS_IS_OK(status)) {
2384                 DEBUG(0,("service_setup_stream_socket(address=%s,port=%u) failed - %s\n", 
2385                          address, port, nt_errstr(status)));
2386                 return status;
2387         }
2388
2389         snprintf(port_str, sizeof(port_str), "%u", port);
2390
2391         status = dcerpc_binding_set_string_option(e->ep_description,
2392                                                   "endpoint", port_str);
2393         if (!NT_STATUS_IS_OK(status)) {
2394                 DEBUG(0,("dcerpc_binding_set_string_option(endpoint, %s) failed - %s\n",
2395                          port_str, nt_errstr(status)));
2396                 return status;
2397         }
2398
2399         return NT_STATUS_OK;
2400 }
2401
2402 #include "lib/socket/netif.h" /* Included here to work around the fact that socket_wrapper redefines bind() */
2403
2404 static NTSTATUS dcesrv_add_ep_tcp(struct dcesrv_context *dce_ctx, 
2405                                   struct loadparm_context *lp_ctx,
2406                                   struct dcesrv_endpoint *e,
2407                                   struct tevent_context *event_ctx, const struct model_ops *model_ops)
2408 {
2409         NTSTATUS status;
2410
2411         /* Add TCP/IP sockets */
2412         if (lpcfg_interfaces(lp_ctx) && lpcfg_bind_interfaces_only(lp_ctx)) {
2413                 int num_interfaces;
2414                 int i;
2415                 struct interface *ifaces;
2416
2417                 load_interface_list(dce_ctx, lp_ctx, &ifaces);
2418
2419                 num_interfaces = iface_list_count(ifaces);
2420                 for(i = 0; i < num_interfaces; i++) {
2421                         const char *address = iface_list_n_ip(ifaces, i);
2422                         status = add_socket_rpc_tcp_iface(dce_ctx, e, event_ctx, model_ops, address);
2423                         NT_STATUS_NOT_OK_RETURN(status);
2424                 }
2425         } else {
2426                 char **wcard;
2427                 int i;
2428                 int num_binds = 0;
2429                 wcard = iface_list_wildcard(dce_ctx);
2430                 NT_STATUS_HAVE_NO_MEMORY(wcard);
2431                 for (i=0; wcard[i]; i++) {
2432                         status = add_socket_rpc_tcp_iface(dce_ctx, e, event_ctx, model_ops, wcard[i]);
2433                         if (NT_STATUS_IS_OK(status)) {
2434                                 num_binds++;
2435                         }
2436                 }
2437                 talloc_free(wcard);
2438                 if (num_binds == 0) {
2439                         return NT_STATUS_INVALID_PARAMETER_MIX;
2440                 }
2441         }
2442
2443         return NT_STATUS_OK;
2444 }
2445
2446 NTSTATUS dcesrv_add_ep(struct dcesrv_context *dce_ctx,
2447                        struct loadparm_context *lp_ctx,
2448                        struct dcesrv_endpoint *e,
2449                        struct tevent_context *event_ctx,
2450                        const struct model_ops *model_ops)
2451 {
2452         enum dcerpc_transport_t transport =
2453                 dcerpc_binding_get_transport(e->ep_description);
2454
2455         switch (transport) {
2456         case NCACN_UNIX_STREAM:
2457                 return dcesrv_add_ep_unix(dce_ctx, lp_ctx, e, event_ctx, model_ops);
2458
2459         case NCALRPC:
2460                 return dcesrv_add_ep_ncalrpc(dce_ctx, lp_ctx, e, event_ctx, model_ops);
2461
2462         case NCACN_IP_TCP:
2463                 return dcesrv_add_ep_tcp(dce_ctx, lp_ctx, e, event_ctx, model_ops);
2464
2465         case NCACN_NP:
2466                 return dcesrv_add_ep_np(dce_ctx, lp_ctx, e, event_ctx, model_ops);
2467
2468         default:
2469                 return NT_STATUS_NOT_SUPPORTED;
2470         }
2471 }
2472
2473
2474 /**
2475  * retrieve credentials from a dce_call
2476  */
2477 _PUBLIC_ struct cli_credentials *dcesrv_call_credentials(struct dcesrv_call_state *dce_call)
2478 {
2479         return dce_call->conn->auth_state.session_info->credentials;
2480 }
2481
2482 /**
2483  * returns true if this is an authenticated call
2484  */
2485 _PUBLIC_ bool dcesrv_call_authenticated(struct dcesrv_call_state *dce_call)
2486 {
2487         enum security_user_level level;
2488         level = security_session_user_level(dce_call->conn->auth_state.session_info, NULL);
2489         return level >= SECURITY_USER;
2490 }
2491
2492 /**
2493  * retrieve account_name for a dce_call
2494  */
2495 _PUBLIC_ const char *dcesrv_call_account_name(struct dcesrv_call_state *dce_call)
2496 {
2497         return dce_call->context->conn->auth_state.session_info->info->account_name;
2498 }