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