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