bd73061333c0aedb3c0e99d0ddd86f4c31ee89ed
[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                 talloc_free(call->context);
809                 call->context = NULL;
810                 return dcesrv_bind_nak(call, DCERPC_BIND_REASON_INVALID_AUTH_TYPE);
811         }
812
813         /* setup a bind_ack */
814         dcesrv_init_hdr(&pkt, lpcfg_rpc_big_endian(call->conn->dce_ctx->lp_ctx));
815         pkt.auth_length = 0;
816         pkt.call_id = call->pkt.call_id;
817         pkt.ptype = DCERPC_PKT_BIND_ACK;
818         pkt.pfc_flags = DCERPC_PFC_FLAG_FIRST | DCERPC_PFC_FLAG_LAST | extra_flags;
819         pkt.u.bind_ack.max_xmit_frag = call->conn->max_xmit_frag;
820         pkt.u.bind_ack.max_recv_frag = call->conn->max_recv_frag;
821
822         /*
823           make it possible for iface->bind() to specify the assoc_group_id
824           This helps the openchange mapiproxy plugin to work correctly.
825           
826           metze
827         */
828         if (call->context) {
829                 pkt.u.bind_ack.assoc_group_id = call->context->assoc_group->id;
830         } else {
831                 pkt.u.bind_ack.assoc_group_id = DUMMY_ASSOC_GROUP;
832         }
833
834         if (iface) {
835                 endpoint = dcerpc_binding_get_string_option(
836                                 call->conn->endpoint->ep_description,
837                                 "endpoint");
838         }
839
840         if (endpoint == NULL) {
841                 endpoint = "";
842         }
843
844         if (strncasecmp(endpoint, "\\pipe\\", 6) == 0) {
845                 /*
846                  * TODO: check if this is really needed
847                  *
848                  * Or if we should fix this in our idl files.
849                  */
850                 ep_prefix = "\\PIPE\\";
851                 endpoint += 6;
852         }
853
854         pkt.u.bind_ack.secondary_address = talloc_asprintf(call, "%s%s",
855                                                            ep_prefix,
856                                                            endpoint);
857         if (pkt.u.bind_ack.secondary_address == NULL) {
858                 TALLOC_FREE(call->context);
859                 return NT_STATUS_NO_MEMORY;
860         }
861         pkt.u.bind_ack.num_results = 1;
862         pkt.u.bind_ack.ctx_list = talloc_zero(call, struct dcerpc_ack_ctx);
863         if (!pkt.u.bind_ack.ctx_list) {
864                 talloc_free(call->context);
865                 call->context = NULL;
866                 return NT_STATUS_NO_MEMORY;
867         }
868         pkt.u.bind_ack.ctx_list[0].result = result;
869         pkt.u.bind_ack.ctx_list[0].reason.value = reason;
870         pkt.u.bind_ack.ctx_list[0].syntax = ndr_transfer_syntax_ndr;
871         pkt.u.bind_ack.auth_info = data_blob(NULL, 0);
872
873         status = dcesrv_auth_bind_ack(call, &pkt);
874         if (!NT_STATUS_IS_OK(status)) {
875                 talloc_free(call->context);
876                 call->context = NULL;
877                 return dcesrv_bind_nak(call, 0);
878         }
879
880         rep = talloc_zero(call, struct data_blob_list_item);
881         if (!rep) {
882                 talloc_free(call->context);
883                 call->context = NULL;
884                 return NT_STATUS_NO_MEMORY;
885         }
886
887         status = ncacn_push_auth(&rep->blob, call, &pkt,
888                                  call->out_auth_info);
889         if (!NT_STATUS_IS_OK(status)) {
890                 talloc_free(call->context);
891                 call->context = NULL;
892                 return status;
893         }
894
895         dcerpc_set_frag_length(&rep->blob, rep->blob.length);
896
897         DLIST_ADD_END(call->replies, rep);
898         dcesrv_call_set_list(call, DCESRV_LIST_CALL_LIST);
899
900         if (call->conn->call_list && call->conn->call_list->replies) {
901                 if (call->conn->transport.report_output_data) {
902                         call->conn->transport.report_output_data(call->conn);
903                 }
904         }
905
906         return NT_STATUS_OK;
907 }
908
909
910 /*
911   handle a auth3 request
912 */
913 static NTSTATUS dcesrv_auth3(struct dcesrv_call_state *call)
914 {
915         NTSTATUS status;
916
917         if (!call->conn->allow_auth3) {
918                 return dcesrv_fault_disconnect(call, DCERPC_NCA_S_PROTO_ERROR);
919         }
920
921         if (call->conn->auth_state.auth_finished) {
922                 return dcesrv_fault_disconnect(call, DCERPC_NCA_S_PROTO_ERROR);
923         }
924
925         status = dcerpc_verify_ncacn_packet_header(&call->pkt,
926                         DCERPC_PKT_AUTH3,
927                         call->pkt.u.auth3.auth_info.length,
928                         0, /* required flags */
929                         DCERPC_PFC_FLAG_FIRST |
930                         DCERPC_PFC_FLAG_LAST |
931                         DCERPC_PFC_FLAG_SUPPORT_HEADER_SIGN |
932                         0x08 | /* this is not defined, but should be ignored */
933                         DCERPC_PFC_FLAG_CONC_MPX |
934                         DCERPC_PFC_FLAG_DID_NOT_EXECUTE |
935                         DCERPC_PFC_FLAG_MAYBE |
936                         DCERPC_PFC_FLAG_OBJECT_UUID);
937         if (!NT_STATUS_IS_OK(status)) {
938                 return dcesrv_fault_disconnect(call, DCERPC_NCA_S_PROTO_ERROR);
939         }
940
941         /* handle the auth3 in the auth code */
942         if (!dcesrv_auth_auth3(call)) {
943                 call->conn->auth_state.auth_invalid = true;
944         }
945
946         talloc_free(call);
947
948         /* we don't send a reply to a auth3 request, except by a
949            fault */
950         return NT_STATUS_OK;
951 }
952
953
954 /*
955   handle a bind request
956 */
957 static NTSTATUS dcesrv_alter_new_context(struct dcesrv_call_state *call, uint32_t context_id)
958 {
959         uint32_t if_version, transfer_syntax_version;
960         struct dcesrv_connection_context *context;
961         const struct dcesrv_interface *iface;
962         struct GUID uuid, *transfer_syntax_uuid;
963         NTSTATUS status;
964
965         if_version = call->pkt.u.alter.ctx_list[0].abstract_syntax.if_version;
966         uuid = call->pkt.u.alter.ctx_list[0].abstract_syntax.uuid;
967
968         transfer_syntax_version = call->pkt.u.alter.ctx_list[0].transfer_syntaxes[0].if_version;
969         transfer_syntax_uuid = &call->pkt.u.alter.ctx_list[0].transfer_syntaxes[0].uuid;
970         if (!GUID_equal(transfer_syntax_uuid, &ndr_transfer_syntax_ndr.uuid) ||
971             ndr_transfer_syntax_ndr.if_version != transfer_syntax_version) {
972                 /* we only do NDR encoded dcerpc */
973                 return NT_STATUS_RPC_PROTSEQ_NOT_SUPPORTED;
974         }
975
976         iface = find_interface_by_uuid(call->conn->endpoint, &uuid, if_version);
977         if (iface == NULL) {
978                 char *uuid_str = GUID_string(call, &uuid);
979                 DEBUG(2,("Request for unknown dcerpc interface %s/%d\n", uuid_str, if_version));
980                 talloc_free(uuid_str);
981                 return NT_STATUS_RPC_PROTSEQ_NOT_SUPPORTED;
982         }
983
984         /* add this context to the list of available context_ids */
985         context = talloc_zero(call->conn, struct dcesrv_connection_context);
986         if (context == NULL) {
987                 return NT_STATUS_NO_MEMORY;
988         }
989         context->conn = call->conn;
990         context->iface = iface;
991         context->context_id = context_id;
992         if (call->pkt.u.alter.assoc_group_id != 0) {
993                 context->assoc_group = dcesrv_assoc_group_reference(context,
994                                                                     call->conn->dce_ctx, 
995                                                                     call->pkt.u.alter.assoc_group_id);
996         } else {
997                 context->assoc_group = dcesrv_assoc_group_new(context, call->conn->dce_ctx);
998         }
999         if (context->assoc_group == NULL) {
1000                 talloc_free(context);
1001                 call->context = NULL;
1002                 return NT_STATUS_NO_MEMORY;
1003         }
1004         context->private_data = NULL;
1005         DLIST_ADD(call->conn->contexts, context);
1006         call->context = context;
1007         talloc_set_destructor(context, dcesrv_connection_context_destructor);
1008
1009         dcesrv_prepare_context_auth(call);
1010
1011         status = iface->bind(call, iface, if_version);
1012         if (!NT_STATUS_IS_OK(status)) {
1013                 /* we don't want to trigger the iface->unbind() hook */
1014                 context->iface = NULL;
1015                 talloc_free(context);
1016                 call->context = NULL;
1017                 return status;
1018         }
1019
1020         return NT_STATUS_OK;
1021 }
1022
1023 /* setup and send an alter_resp */
1024 static NTSTATUS dcesrv_alter_resp(struct dcesrv_call_state *call,
1025                                 uint32_t result,
1026                                 uint32_t reason)
1027 {
1028         struct ncacn_packet pkt;
1029         uint32_t extra_flags = 0;
1030         struct data_blob_list_item *rep = NULL;
1031         NTSTATUS status;
1032
1033         dcesrv_init_hdr(&pkt, lpcfg_rpc_big_endian(call->conn->dce_ctx->lp_ctx));
1034         pkt.auth_length = 0;
1035         pkt.call_id = call->pkt.call_id;
1036         pkt.ptype = DCERPC_PKT_ALTER_RESP;
1037         if (result == 0) {
1038                 if ((call->pkt.pfc_flags & DCERPC_PFC_FLAG_CONC_MPX) &&
1039                                 call->context->conn->state_flags &
1040                                         DCESRV_CALL_STATE_FLAG_MULTIPLEXED) {
1041                         extra_flags |= DCERPC_PFC_FLAG_CONC_MPX;
1042                 }
1043                 if (call->state_flags & DCESRV_CALL_STATE_FLAG_PROCESS_PENDING_CALL) {
1044                         call->context->conn->state_flags |=
1045                                 DCESRV_CALL_STATE_FLAG_PROCESS_PENDING_CALL;
1046                 }
1047         }
1048         pkt.pfc_flags = DCERPC_PFC_FLAG_FIRST | DCERPC_PFC_FLAG_LAST | extra_flags;
1049         pkt.u.alter_resp.max_xmit_frag = call->conn->max_xmit_frag;
1050         pkt.u.alter_resp.max_recv_frag = call->conn->max_recv_frag;
1051         if (result == 0) {
1052                 pkt.u.alter_resp.assoc_group_id = call->context->assoc_group->id;
1053         } else {
1054                 pkt.u.alter_resp.assoc_group_id = 0;
1055         }
1056         pkt.u.alter_resp.num_results = 1;
1057         pkt.u.alter_resp.ctx_list = talloc_zero(call, struct dcerpc_ack_ctx);
1058         if (!pkt.u.alter_resp.ctx_list) {
1059                 return NT_STATUS_NO_MEMORY;
1060         }
1061         pkt.u.alter_resp.ctx_list[0].result = result;
1062         pkt.u.alter_resp.ctx_list[0].reason.value = reason;
1063         pkt.u.alter_resp.ctx_list[0].syntax = ndr_transfer_syntax_ndr;
1064         pkt.u.alter_resp.auth_info = data_blob(NULL, 0);
1065         pkt.u.alter_resp.secondary_address = "";
1066
1067         status = dcesrv_auth_alter_ack(call, &pkt);
1068         if (!NT_STATUS_IS_OK(status)) {
1069                 return dcesrv_fault_disconnect(call, DCERPC_FAULT_SEC_PKG_ERROR);
1070         }
1071
1072         rep = talloc_zero(call, struct data_blob_list_item);
1073         if (!rep) {
1074                 return NT_STATUS_NO_MEMORY;
1075         }
1076
1077         status = ncacn_push_auth(&rep->blob, call, &pkt, call->out_auth_info);
1078         if (!NT_STATUS_IS_OK(status)) {
1079                 return status;
1080         }
1081
1082         dcerpc_set_frag_length(&rep->blob, rep->blob.length);
1083
1084         DLIST_ADD_END(call->replies, rep);
1085         dcesrv_call_set_list(call, DCESRV_LIST_CALL_LIST);
1086
1087         if (call->conn->call_list && call->conn->call_list->replies) {
1088                 if (call->conn->transport.report_output_data) {
1089                         call->conn->transport.report_output_data(call->conn);
1090                 }
1091         }
1092
1093         return NT_STATUS_OK;
1094 }
1095
1096 /*
1097   handle a alter context request
1098 */
1099 static NTSTATUS dcesrv_alter(struct dcesrv_call_state *call)
1100 {
1101         NTSTATUS status;
1102         const struct dcerpc_ctx_list *ctx = NULL;
1103         bool auth_ok = false;
1104
1105         if (!call->conn->allow_alter) {
1106                 return dcesrv_fault_disconnect(call, DCERPC_NCA_S_PROTO_ERROR);
1107         }
1108
1109         status = dcerpc_verify_ncacn_packet_header(&call->pkt,
1110                         DCERPC_PKT_ALTER,
1111                         call->pkt.u.alter.auth_info.length,
1112                         0, /* required flags */
1113                         DCERPC_PFC_FLAG_FIRST |
1114                         DCERPC_PFC_FLAG_LAST |
1115                         DCERPC_PFC_FLAG_SUPPORT_HEADER_SIGN |
1116                         0x08 | /* this is not defined, but should be ignored */
1117                         DCERPC_PFC_FLAG_CONC_MPX |
1118                         DCERPC_PFC_FLAG_DID_NOT_EXECUTE |
1119                         DCERPC_PFC_FLAG_MAYBE |
1120                         DCERPC_PFC_FLAG_OBJECT_UUID);
1121         if (!NT_STATUS_IS_OK(status)) {
1122                 return dcesrv_fault_disconnect(call, DCERPC_NCA_S_PROTO_ERROR);
1123         }
1124
1125         auth_ok = dcesrv_auth_alter(call);
1126         if (!auth_ok) {
1127                 if (call->in_auth_info.auth_type == DCERPC_AUTH_TYPE_NONE) {
1128                         return dcesrv_fault_disconnect(call,
1129                                         DCERPC_FAULT_ACCESS_DENIED);
1130                 }
1131         }
1132
1133         if (call->pkt.u.alter.num_contexts < 1) {
1134                 return dcesrv_fault_disconnect(call, DCERPC_NCA_S_PROTO_ERROR);
1135         }
1136         ctx = &call->pkt.u.alter.ctx_list[0];
1137         if (ctx->num_transfer_syntaxes < 1) {
1138                 return dcesrv_fault_disconnect(call, DCERPC_NCA_S_PROTO_ERROR);
1139         }
1140
1141         /* see if they are asking for a new interface */
1142         call->context = dcesrv_find_context(call->conn, ctx->context_id);
1143         if (!call->context) {
1144                 status = dcesrv_alter_new_context(call, ctx->context_id);
1145                 if (!NT_STATUS_IS_OK(status)) {
1146                         return dcesrv_alter_resp(call,
1147                                 DCERPC_BIND_PROVIDER_REJECT,
1148                                 DCERPC_BIND_REASON_ASYNTAX);
1149                 }
1150         } else {
1151                 bool ok;
1152
1153                 ok = ndr_syntax_id_equal(&ctx->abstract_syntax,
1154                                          &call->context->iface->syntax_id);
1155                 if (!ok) {
1156                         return dcesrv_fault_disconnect(call,
1157                                         DCERPC_NCA_S_PROTO_ERROR);
1158                 }
1159
1160                 if (ctx->num_transfer_syntaxes != 1) {
1161                         return dcesrv_fault_disconnect(call,
1162                                         DCERPC_NCA_S_PROTO_ERROR);
1163                 }
1164
1165                 ok = ndr_syntax_id_equal(&ctx->transfer_syntaxes[0],
1166                                          &ndr_transfer_syntax_ndr);
1167                 if (!ok) {
1168                         return dcesrv_fault_disconnect(call,
1169                                         DCERPC_NCA_S_PROTO_ERROR);
1170                 }
1171         }
1172
1173         if (call->pkt.u.alter.assoc_group_id != 0 &&
1174             lpcfg_parm_bool(call->conn->dce_ctx->lp_ctx, NULL, "dcesrv","assoc group checking", true) &&
1175             call->pkt.u.alter.assoc_group_id != call->context->assoc_group->id) {
1176                 DEBUG(0,(__location__ ": Failed attempt to use new assoc_group in alter context (0x%08x 0x%08x)\n",
1177                          call->context->assoc_group->id, call->pkt.u.alter.assoc_group_id));
1178                 /* TODO: can they ask for a new association group? */
1179                 return dcesrv_alter_resp(call,
1180                                 DCERPC_BIND_PROVIDER_REJECT,
1181                                 DCERPC_BIND_REASON_ASYNTAX);
1182         }
1183
1184         /* handle any authentication that is being requested */
1185         if (!auth_ok) {
1186                 if (call->in_auth_info.auth_type !=
1187                     call->conn->auth_state.auth_type)
1188                 {
1189                         return dcesrv_fault_disconnect(call,
1190                                         DCERPC_FAULT_SEC_PKG_ERROR);
1191                 }
1192                 return dcesrv_fault_disconnect(call, DCERPC_FAULT_ACCESS_DENIED);
1193         }
1194
1195         return dcesrv_alter_resp(call,
1196                                 DCERPC_BIND_ACK_RESULT_ACCEPTANCE,
1197                                 DCERPC_BIND_ACK_REASON_NOT_SPECIFIED);
1198 }
1199
1200 /*
1201   possibly save the call for inspection with ndrdump
1202  */
1203 static void dcesrv_save_call(struct dcesrv_call_state *call, const char *why)
1204 {
1205 #ifdef DEVELOPER
1206         char *fname;
1207         const char *dump_dir;
1208         dump_dir = lpcfg_parm_string(call->conn->dce_ctx->lp_ctx, NULL, "dcesrv", "stubs directory");
1209         if (!dump_dir) {
1210                 return;
1211         }
1212         fname = talloc_asprintf(call, "%s/RPC-%s-%u-%s.dat",
1213                                 dump_dir,
1214                                 call->context->iface->name,
1215                                 call->pkt.u.request.opnum,
1216                                 why);
1217         if (file_save(fname, call->pkt.u.request.stub_and_verifier.data, call->pkt.u.request.stub_and_verifier.length)) {
1218                 DEBUG(0,("RPC SAVED %s\n", fname));
1219         }
1220         talloc_free(fname);
1221 #endif
1222 }
1223
1224 static NTSTATUS dcesrv_check_verification_trailer(struct dcesrv_call_state *call)
1225 {
1226         TALLOC_CTX *frame = talloc_stackframe();
1227         const uint32_t bitmask1 = call->conn->auth_state.client_hdr_signing ?
1228                 DCERPC_SEC_VT_CLIENT_SUPPORTS_HEADER_SIGNING : 0;
1229         const struct dcerpc_sec_vt_pcontext pcontext = {
1230                 .abstract_syntax = call->context->iface->syntax_id,
1231                 .transfer_syntax = ndr_transfer_syntax_ndr,
1232         };
1233         const struct dcerpc_sec_vt_header2 header2 =
1234                 dcerpc_sec_vt_header2_from_ncacn_packet(&call->pkt);
1235         enum ndr_err_code ndr_err;
1236         struct dcerpc_sec_verification_trailer *vt = NULL;
1237         NTSTATUS status = NT_STATUS_OK;
1238         bool ok;
1239
1240         SMB_ASSERT(call->pkt.ptype == DCERPC_PKT_REQUEST);
1241
1242         ndr_err = ndr_pop_dcerpc_sec_verification_trailer(call->ndr_pull,
1243                                                           frame, &vt);
1244         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
1245                 status = ndr_map_error2ntstatus(ndr_err);
1246                 goto done;
1247         }
1248
1249         ok = dcerpc_sec_verification_trailer_check(vt, &bitmask1,
1250                                                    &pcontext, &header2);
1251         if (!ok) {
1252                 status = NT_STATUS_ACCESS_DENIED;
1253                 goto done;
1254         }
1255 done:
1256         TALLOC_FREE(frame);
1257         return status;
1258 }
1259
1260 /*
1261   handle a dcerpc request packet
1262 */
1263 static NTSTATUS dcesrv_request(struct dcesrv_call_state *call)
1264 {
1265         const struct dcesrv_endpoint *endpoint = call->conn->endpoint;
1266         enum dcerpc_transport_t transport =
1267                 dcerpc_binding_get_transport(endpoint->ep_description);
1268         struct ndr_pull *pull;
1269         NTSTATUS status;
1270         struct dcesrv_connection_context *context;
1271
1272         if (!call->conn->allow_request) {
1273                 return dcesrv_fault_disconnect(call, DCERPC_NCA_S_PROTO_ERROR);
1274         }
1275
1276         /* if authenticated, and the mech we use can't do async replies, don't use them... */
1277         if (call->conn->auth_state.gensec_security && 
1278             !gensec_have_feature(call->conn->auth_state.gensec_security, GENSEC_FEATURE_ASYNC_REPLIES)) {
1279                 call->state_flags &= ~DCESRV_CALL_STATE_FLAG_MAY_ASYNC;
1280         }
1281
1282         context = dcesrv_find_context(call->conn, call->pkt.u.request.context_id);
1283         if (context == NULL) {
1284                 return dcesrv_fault(call, DCERPC_FAULT_UNK_IF);
1285         }
1286
1287         switch (call->conn->auth_state.auth_level) {
1288         case DCERPC_AUTH_LEVEL_NONE:
1289         case DCERPC_AUTH_LEVEL_INTEGRITY:
1290         case DCERPC_AUTH_LEVEL_PRIVACY:
1291                 break;
1292         default:
1293                 if (!context->allow_connect) {
1294                         char *addr;
1295
1296                         addr = tsocket_address_string(call->conn->remote_address,
1297                                                       call);
1298
1299                         DEBUG(2, ("%s: restrict auth_level_connect access "
1300                                   "to [%s] with auth[type=0x%x,level=0x%x] "
1301                                   "on [%s] from [%s]\n",
1302                                   __func__, context->iface->name,
1303                                   call->conn->auth_state.auth_type,
1304                                   call->conn->auth_state.auth_level,
1305                                   derpc_transport_string_by_transport(transport),
1306                                   addr));
1307                         return dcesrv_fault(call, DCERPC_FAULT_ACCESS_DENIED);
1308                 }
1309                 break;
1310         }
1311
1312         if (call->conn->auth_state.auth_level < context->min_auth_level) {
1313                 char *addr;
1314
1315                 addr = tsocket_address_string(call->conn->remote_address, call);
1316
1317                 DEBUG(2, ("%s: restrict access by min_auth_level[0x%x] "
1318                           "to [%s] with auth[type=0x%x,level=0x%x] "
1319                           "on [%s] from [%s]\n",
1320                           __func__,
1321                           context->min_auth_level,
1322                           context->iface->name,
1323                           call->conn->auth_state.auth_type,
1324                           call->conn->auth_state.auth_level,
1325                           derpc_transport_string_by_transport(transport),
1326                           addr));
1327                 return dcesrv_fault(call, DCERPC_FAULT_ACCESS_DENIED);
1328         }
1329
1330         pull = ndr_pull_init_blob(&call->pkt.u.request.stub_and_verifier, call);
1331         NT_STATUS_HAVE_NO_MEMORY(pull);
1332
1333         pull->flags |= LIBNDR_FLAG_REF_ALLOC;
1334
1335         call->context   = context;
1336         call->ndr_pull  = pull;
1337
1338         if (!(call->pkt.drep[0] & DCERPC_DREP_LE)) {
1339                 pull->flags |= LIBNDR_FLAG_BIGENDIAN;
1340         }
1341
1342         status = dcesrv_check_verification_trailer(call);
1343         if (!NT_STATUS_IS_OK(status)) {
1344                 uint32_t faultcode = DCERPC_FAULT_OTHER;
1345                 if (NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
1346                         faultcode = DCERPC_FAULT_ACCESS_DENIED;
1347                 }
1348                 DEBUG(10, ("dcesrv_check_verification_trailer failed: %s\n",
1349                            nt_errstr(status)));
1350                 return dcesrv_fault(call, faultcode);
1351         }
1352
1353         /* unravel the NDR for the packet */
1354         status = context->iface->ndr_pull(call, call, pull, &call->r);
1355         if (!NT_STATUS_IS_OK(status)) {
1356                 if (call->fault_code == DCERPC_FAULT_OP_RNG_ERROR) {
1357                         /* we got an unknown call */
1358                         DEBUG(3,(__location__ ": Unknown RPC call %u on %s\n",
1359                                  call->pkt.u.request.opnum, context->iface->name));
1360                         dcesrv_save_call(call, "unknown");
1361                 } else {
1362                         dcesrv_save_call(call, "pullfail");
1363                 }
1364                 return dcesrv_fault(call, call->fault_code);
1365         }
1366
1367         if (pull->offset != pull->data_size) {
1368                 dcesrv_save_call(call, "extrabytes");
1369                 DEBUG(3,("Warning: %d extra bytes in incoming RPC request\n", 
1370                          pull->data_size - pull->offset));
1371         }
1372
1373         /* call the dispatch function */
1374         status = context->iface->dispatch(call, call, call->r);
1375         if (!NT_STATUS_IS_OK(status)) {
1376                 DEBUG(5,("dcerpc fault in call %s:%02x - %s\n",
1377                          context->iface->name, 
1378                          call->pkt.u.request.opnum,
1379                          dcerpc_errstr(pull, call->fault_code)));
1380                 return dcesrv_fault(call, call->fault_code);
1381         }
1382
1383         /* add the call to the pending list */
1384         dcesrv_call_set_list(call, DCESRV_LIST_PENDING_CALL_LIST);
1385
1386         if (call->state_flags & DCESRV_CALL_STATE_FLAG_ASYNC) {
1387                 return NT_STATUS_OK;
1388         }
1389
1390         return dcesrv_reply(call);
1391 }
1392
1393
1394 /*
1395   remove the call from the right list when freed
1396  */
1397 static int dcesrv_call_dequeue(struct dcesrv_call_state *call)
1398 {
1399         dcesrv_call_set_list(call, DCESRV_LIST_NONE);
1400         return 0;
1401 }
1402
1403 _PUBLIC_ const struct tsocket_address *dcesrv_connection_get_local_address(struct dcesrv_connection *conn)
1404 {
1405         return conn->local_address;
1406 }
1407
1408 _PUBLIC_ const struct tsocket_address *dcesrv_connection_get_remote_address(struct dcesrv_connection *conn)
1409 {
1410         return conn->remote_address;
1411 }
1412
1413 /*
1414   process some input to a dcerpc endpoint server.
1415 */
1416 static NTSTATUS dcesrv_process_ncacn_packet(struct dcesrv_connection *dce_conn,
1417                                             struct ncacn_packet *pkt,
1418                                             DATA_BLOB blob)
1419 {
1420         NTSTATUS status;
1421         struct dcesrv_call_state *call;
1422
1423         call = talloc_zero(dce_conn, struct dcesrv_call_state);
1424         if (!call) {
1425                 data_blob_free(&blob);
1426                 talloc_free(pkt);
1427                 return NT_STATUS_NO_MEMORY;
1428         }
1429         call->conn              = dce_conn;
1430         call->event_ctx         = dce_conn->event_ctx;
1431         call->msg_ctx           = dce_conn->msg_ctx;
1432         call->state_flags       = call->conn->state_flags;
1433         call->time              = timeval_current();
1434         call->list              = DCESRV_LIST_NONE;
1435
1436         talloc_steal(call, pkt);
1437         talloc_steal(call, blob.data);
1438         call->pkt = *pkt;
1439
1440         talloc_set_destructor(call, dcesrv_call_dequeue);
1441
1442         if (call->conn->allow_bind) {
1443                 /*
1444                  * Only one bind is possible per connection
1445                  */
1446                 call->conn->allow_bind = false;
1447                 return dcesrv_bind(call);
1448         }
1449
1450         /* we have to check the signing here, before combining the
1451            pdus */
1452         if (call->pkt.ptype == DCERPC_PKT_REQUEST) {
1453                 if (!call->conn->allow_request) {
1454                         return dcesrv_fault_disconnect(call,
1455                                         DCERPC_NCA_S_PROTO_ERROR);
1456                 }
1457
1458                 status = dcerpc_verify_ncacn_packet_header(&call->pkt,
1459                                 DCERPC_PKT_REQUEST,
1460                                 call->pkt.u.request.stub_and_verifier.length,
1461                                 0, /* required_flags */
1462                                 DCERPC_PFC_FLAG_FIRST |
1463                                 DCERPC_PFC_FLAG_LAST |
1464                                 DCERPC_PFC_FLAG_PENDING_CANCEL |
1465                                 0x08 | /* this is not defined, but should be ignored */
1466                                 DCERPC_PFC_FLAG_CONC_MPX |
1467                                 DCERPC_PFC_FLAG_DID_NOT_EXECUTE |
1468                                 DCERPC_PFC_FLAG_MAYBE |
1469                                 DCERPC_PFC_FLAG_OBJECT_UUID);
1470                 if (!NT_STATUS_IS_OK(status)) {
1471                         return dcesrv_fault_disconnect(call,
1472                                         DCERPC_NCA_S_PROTO_ERROR);
1473                 }
1474
1475                 if (!dcesrv_auth_request(call, &blob)) {
1476                         return dcesrv_fault(call, DCERPC_FAULT_ACCESS_DENIED);
1477                 }
1478         }
1479
1480         /* see if this is a continued packet */
1481         if (call->pkt.ptype == DCERPC_PKT_REQUEST &&
1482             !(call->pkt.pfc_flags & DCERPC_PFC_FLAG_FIRST)) {
1483                 struct dcesrv_call_state *call2 = call;
1484                 uint32_t alloc_size;
1485
1486                 /* this is a continuation of an existing call - find the call
1487                    then tack it on the end */
1488                 call = dcesrv_find_fragmented_call(dce_conn, call2->pkt.call_id);
1489                 if (!call) {
1490                         return dcesrv_fault_disconnect(call2,
1491                                         DCERPC_NCA_S_PROTO_ERROR);
1492                 }
1493
1494                 if (call->pkt.ptype != call2->pkt.ptype) {
1495                         /* trying to play silly buggers are we? */
1496                         return dcesrv_fault_disconnect(call,
1497                                         DCERPC_NCA_S_PROTO_ERROR);
1498                 }
1499                 if (memcmp(call->pkt.drep, call2->pkt.drep, sizeof(pkt->drep)) != 0) {
1500                         return dcesrv_fault_disconnect(call,
1501                                         DCERPC_NCA_S_PROTO_ERROR);
1502                 }
1503                 if (call->pkt.call_id != call2->pkt.call_id) {
1504                         return dcesrv_fault_disconnect(call,
1505                                         DCERPC_NCA_S_PROTO_ERROR);
1506                 }
1507                 if (call->pkt.u.request.context_id != call2->pkt.u.request.context_id)  {
1508                         return dcesrv_fault_disconnect(call,
1509                                         DCERPC_NCA_S_PROTO_ERROR);
1510                 }
1511                 if (call->pkt.u.request.opnum != call2->pkt.u.request.opnum)  {
1512                         return dcesrv_fault_disconnect(call,
1513                                         DCERPC_NCA_S_PROTO_ERROR);
1514                 }
1515
1516                 alloc_size = call->pkt.u.request.stub_and_verifier.length +
1517                         call2->pkt.u.request.stub_and_verifier.length;
1518                 if (call->pkt.u.request.alloc_hint > alloc_size) {
1519                         alloc_size = call->pkt.u.request.alloc_hint;
1520                 }
1521
1522                 call->pkt.u.request.stub_and_verifier.data = 
1523                         talloc_realloc(call, 
1524                                        call->pkt.u.request.stub_and_verifier.data, 
1525                                        uint8_t, alloc_size);
1526                 if (!call->pkt.u.request.stub_and_verifier.data) {
1527                         return dcesrv_fault(call2, DCERPC_FAULT_OTHER);
1528                 }
1529                 memcpy(call->pkt.u.request.stub_and_verifier.data +
1530                        call->pkt.u.request.stub_and_verifier.length,
1531                        call2->pkt.u.request.stub_and_verifier.data,
1532                        call2->pkt.u.request.stub_and_verifier.length);
1533                 call->pkt.u.request.stub_and_verifier.length += 
1534                         call2->pkt.u.request.stub_and_verifier.length;
1535
1536                 call->pkt.pfc_flags |= (call2->pkt.pfc_flags & DCERPC_PFC_FLAG_LAST);
1537
1538                 talloc_free(call2);
1539         }
1540
1541         /* this may not be the last pdu in the chain - if its isn't then
1542            just put it on the incoming_fragmented_call_list and wait for the rest */
1543         if (call->pkt.ptype == DCERPC_PKT_REQUEST &&
1544             !(call->pkt.pfc_flags & DCERPC_PFC_FLAG_LAST)) {
1545                 dcesrv_call_set_list(call, DCESRV_LIST_FRAGMENTED_CALL_LIST);
1546                 return NT_STATUS_OK;
1547         } 
1548         
1549         /* This removes any fragments we may have had stashed away */
1550         dcesrv_call_set_list(call, DCESRV_LIST_NONE);
1551
1552         switch (call->pkt.ptype) {
1553         case DCERPC_PKT_BIND:
1554                 status = dcesrv_bind_nak(call,
1555                         DCERPC_BIND_NAK_REASON_NOT_SPECIFIED);
1556                 break;
1557         case DCERPC_PKT_AUTH3:
1558                 status = dcesrv_auth3(call);
1559                 break;
1560         case DCERPC_PKT_ALTER:
1561                 status = dcesrv_alter(call);
1562                 break;
1563         case DCERPC_PKT_REQUEST:
1564                 status = dcesrv_request(call);
1565                 break;
1566         default:
1567                 status = dcesrv_fault_disconnect(call, DCERPC_NCA_S_PROTO_ERROR);
1568                 break;
1569         }
1570
1571         /* if we are going to be sending a reply then add
1572            it to the list of pending calls. We add it to the end to keep the call
1573            list in the order we will answer */
1574         if (!NT_STATUS_IS_OK(status)) {
1575                 talloc_free(call);
1576         }
1577
1578         return status;
1579 }
1580
1581 _PUBLIC_ NTSTATUS dcesrv_init_context(TALLOC_CTX *mem_ctx, 
1582                                       struct loadparm_context *lp_ctx,
1583                                       const char **endpoint_servers, struct dcesrv_context **_dce_ctx)
1584 {
1585         NTSTATUS status;
1586         struct dcesrv_context *dce_ctx;
1587         int i;
1588
1589         if (!endpoint_servers) {
1590                 DEBUG(0,("dcesrv_init_context: no endpoint servers configured\n"));
1591                 return NT_STATUS_INTERNAL_ERROR;
1592         }
1593
1594         dce_ctx = talloc_zero(mem_ctx, struct dcesrv_context);
1595         NT_STATUS_HAVE_NO_MEMORY(dce_ctx);
1596
1597         if (uid_wrapper_enabled()) {
1598                 setenv("UID_WRAPPER_MYUID", "1", 1);
1599         }
1600         dce_ctx->initial_euid = geteuid();
1601         if (uid_wrapper_enabled()) {
1602                 unsetenv("UID_WRAPPER_MYUID");
1603         }
1604
1605         dce_ctx->endpoint_list  = NULL;
1606         dce_ctx->lp_ctx = lp_ctx;
1607         dce_ctx->assoc_groups_idr = idr_init(dce_ctx);
1608         NT_STATUS_HAVE_NO_MEMORY(dce_ctx->assoc_groups_idr);
1609         dce_ctx->broken_connections = NULL;
1610
1611         for (i=0;endpoint_servers[i];i++) {
1612                 const struct dcesrv_endpoint_server *ep_server;
1613
1614                 ep_server = dcesrv_ep_server_byname(endpoint_servers[i]);
1615                 if (!ep_server) {
1616                         DEBUG(0,("dcesrv_init_context: failed to find endpoint server = '%s'\n", endpoint_servers[i]));
1617                         return NT_STATUS_INTERNAL_ERROR;
1618                 }
1619
1620                 status = ep_server->init_server(dce_ctx, ep_server);
1621                 if (!NT_STATUS_IS_OK(status)) {
1622                         DEBUG(0,("dcesrv_init_context: failed to init endpoint server = '%s': %s\n", endpoint_servers[i],
1623                                 nt_errstr(status)));
1624                         return status;
1625                 }
1626         }
1627
1628         *_dce_ctx = dce_ctx;
1629         return NT_STATUS_OK;
1630 }
1631
1632 /* the list of currently registered DCERPC endpoint servers.
1633  */
1634 static struct ep_server {
1635         struct dcesrv_endpoint_server *ep_server;
1636 } *ep_servers = NULL;
1637 static int num_ep_servers;
1638
1639 /*
1640   register a DCERPC endpoint server. 
1641
1642   The 'name' can be later used by other backends to find the operations
1643   structure for this backend.  
1644
1645   The 'type' is used to specify whether this is for a disk, printer or IPC$ share
1646 */
1647 _PUBLIC_ NTSTATUS dcerpc_register_ep_server(const void *_ep_server)
1648 {
1649         const struct dcesrv_endpoint_server *ep_server = _ep_server;
1650         
1651         if (dcesrv_ep_server_byname(ep_server->name) != NULL) {
1652                 /* its already registered! */
1653                 DEBUG(0,("DCERPC endpoint server '%s' already registered\n", 
1654                          ep_server->name));
1655                 return NT_STATUS_OBJECT_NAME_COLLISION;
1656         }
1657
1658         ep_servers = realloc_p(ep_servers, struct ep_server, num_ep_servers+1);
1659         if (!ep_servers) {
1660                 smb_panic("out of memory in dcerpc_register");
1661         }
1662
1663         ep_servers[num_ep_servers].ep_server = smb_xmemdup(ep_server, sizeof(*ep_server));
1664         ep_servers[num_ep_servers].ep_server->name = smb_xstrdup(ep_server->name);
1665
1666         num_ep_servers++;
1667
1668         DEBUG(3,("DCERPC endpoint server '%s' registered\n", 
1669                  ep_server->name));
1670
1671         return NT_STATUS_OK;
1672 }
1673
1674 /*
1675   return the operations structure for a named backend of the specified type
1676 */
1677 const struct dcesrv_endpoint_server *dcesrv_ep_server_byname(const char *name)
1678 {
1679         int i;
1680
1681         for (i=0;i<num_ep_servers;i++) {
1682                 if (strcmp(ep_servers[i].ep_server->name, name) == 0) {
1683                         return ep_servers[i].ep_server;
1684                 }
1685         }
1686
1687         return NULL;
1688 }
1689
1690 void dcerpc_server_init(struct loadparm_context *lp_ctx)
1691 {
1692         static bool initialized;
1693 #define _MODULE_PROTO(init) extern NTSTATUS init(void);
1694         STATIC_dcerpc_server_MODULES_PROTO;
1695         init_module_fn static_init[] = { STATIC_dcerpc_server_MODULES };
1696         init_module_fn *shared_init;
1697
1698         if (initialized) {
1699                 return;
1700         }
1701         initialized = true;
1702
1703         shared_init = load_samba_modules(NULL, "dcerpc_server");
1704
1705         run_init_functions(static_init);
1706         run_init_functions(shared_init);
1707
1708         talloc_free(shared_init);
1709 }
1710
1711 /*
1712   return the DCERPC module version, and the size of some critical types
1713   This can be used by endpoint server modules to either detect compilation errors, or provide
1714   multiple implementations for different smbd compilation options in one module
1715 */
1716 const struct dcesrv_critical_sizes *dcerpc_module_version(void)
1717 {
1718         static const struct dcesrv_critical_sizes critical_sizes = {
1719                 DCERPC_MODULE_VERSION,
1720                 sizeof(struct dcesrv_context),
1721                 sizeof(struct dcesrv_endpoint),
1722                 sizeof(struct dcesrv_endpoint_server),
1723                 sizeof(struct dcesrv_interface),
1724                 sizeof(struct dcesrv_if_list),
1725                 sizeof(struct dcesrv_connection),
1726                 sizeof(struct dcesrv_call_state),
1727                 sizeof(struct dcesrv_auth),
1728                 sizeof(struct dcesrv_handle)
1729         };
1730
1731         return &critical_sizes;
1732 }
1733
1734 static void dcesrv_terminate_connection(struct dcesrv_connection *dce_conn, const char *reason)
1735 {
1736         struct dcesrv_context *dce_ctx = dce_conn->dce_ctx;
1737         struct stream_connection *srv_conn;
1738         srv_conn = talloc_get_type(dce_conn->transport.private_data,
1739                                    struct stream_connection);
1740
1741         dce_conn->allow_bind = false;
1742         dce_conn->allow_auth3 = false;
1743         dce_conn->allow_alter = false;
1744         dce_conn->allow_request = false;
1745
1746         if (dce_conn->pending_call_list == NULL) {
1747                 char *full_reason = talloc_asprintf(dce_conn, "dcesrv: %s", reason);
1748
1749                 DLIST_REMOVE(dce_ctx->broken_connections, dce_conn);
1750                 stream_terminate_connection(srv_conn, full_reason ? full_reason : reason);
1751                 return;
1752         }
1753
1754         if (dce_conn->terminate != NULL) {
1755                 return;
1756         }
1757
1758         DEBUG(3,("dcesrv: terminating connection due to '%s' defered due to pending calls\n",
1759                  reason));
1760         dce_conn->terminate = talloc_strdup(dce_conn, reason);
1761         if (dce_conn->terminate == NULL) {
1762                 dce_conn->terminate = "dcesrv: defered terminating connection - no memory";
1763         }
1764         DLIST_ADD_END(dce_ctx->broken_connections, dce_conn);
1765 }
1766
1767 static void dcesrv_cleanup_broken_connections(struct dcesrv_context *dce_ctx)
1768 {
1769         struct dcesrv_connection *cur, *next;
1770
1771         next = dce_ctx->broken_connections;
1772         while (next != NULL) {
1773                 cur = next;
1774                 next = cur->next;
1775
1776                 if (cur->state_flags & DCESRV_CALL_STATE_FLAG_PROCESS_PENDING_CALL) {
1777                         struct dcesrv_connection_context *context_cur, *context_next;
1778
1779                         context_next = cur->contexts;
1780                         while (context_next != NULL) {
1781                                 context_cur = context_next;
1782                                 context_next = context_cur->next;
1783
1784                                 dcesrv_connection_context_destructor(context_cur);
1785                         }
1786                 }
1787
1788                 dcesrv_terminate_connection(cur, cur->terminate);
1789         }
1790 }
1791
1792 /* We need this include to be able to compile on some plateforms
1793  * (ie. freebsd 7.2) as it seems that <sys/uio.h> is not included
1794  * correctly.
1795  * It has to be that deep because otherwise we have a conflict on
1796  * const struct dcesrv_interface declaration.
1797  * This is mostly due to socket_wrapper defining #define bind swrap_bind
1798  * which conflict with the bind used before.
1799  */
1800 #include "system/network.h"
1801
1802 struct dcesrv_sock_reply_state {
1803         struct dcesrv_connection *dce_conn;
1804         struct dcesrv_call_state *call;
1805         struct iovec iov;
1806 };
1807
1808 static void dcesrv_sock_reply_done(struct tevent_req *subreq);
1809 static void dcesrv_call_terminate_step1(struct tevent_req *subreq);
1810
1811 static void dcesrv_sock_report_output_data(struct dcesrv_connection *dce_conn)
1812 {
1813         struct dcesrv_call_state *call;
1814
1815         call = dce_conn->call_list;
1816         if (!call || !call->replies) {
1817                 return;
1818         }
1819
1820         while (call->replies) {
1821                 struct data_blob_list_item *rep = call->replies;
1822                 struct dcesrv_sock_reply_state *substate;
1823                 struct tevent_req *subreq;
1824
1825                 substate = talloc_zero(call, struct dcesrv_sock_reply_state);
1826                 if (!substate) {
1827                         dcesrv_terminate_connection(dce_conn, "no memory");
1828                         return;
1829                 }
1830
1831                 substate->dce_conn = dce_conn;
1832                 substate->call = NULL;
1833
1834                 DLIST_REMOVE(call->replies, rep);
1835
1836                 if (call->replies == NULL && call->terminate_reason == NULL) {
1837                         substate->call = call;
1838                 }
1839
1840                 substate->iov.iov_base = (void *) rep->blob.data;
1841                 substate->iov.iov_len = rep->blob.length;
1842
1843                 subreq = tstream_writev_queue_send(substate,
1844                                                    dce_conn->event_ctx,
1845                                                    dce_conn->stream,
1846                                                    dce_conn->send_queue,
1847                                                    &substate->iov, 1);
1848                 if (!subreq) {
1849                         dcesrv_terminate_connection(dce_conn, "no memory");
1850                         return;
1851                 }
1852                 tevent_req_set_callback(subreq, dcesrv_sock_reply_done,
1853                                         substate);
1854         }
1855
1856         if (call->terminate_reason != NULL) {
1857                 struct tevent_req *subreq;
1858
1859                 subreq = tevent_queue_wait_send(call,
1860                                                 dce_conn->event_ctx,
1861                                                 dce_conn->send_queue);
1862                 if (!subreq) {
1863                         dcesrv_terminate_connection(dce_conn, __location__);
1864                         return;
1865                 }
1866                 tevent_req_set_callback(subreq, dcesrv_call_terminate_step1,
1867                                         call);
1868         }
1869
1870         DLIST_REMOVE(call->conn->call_list, call);
1871         call->list = DCESRV_LIST_NONE;
1872 }
1873
1874 static void dcesrv_sock_reply_done(struct tevent_req *subreq)
1875 {
1876         struct dcesrv_sock_reply_state *substate = tevent_req_callback_data(subreq,
1877                                                 struct dcesrv_sock_reply_state);
1878         int ret;
1879         int sys_errno;
1880         NTSTATUS status;
1881         struct dcesrv_call_state *call = substate->call;
1882
1883         ret = tstream_writev_queue_recv(subreq, &sys_errno);
1884         TALLOC_FREE(subreq);
1885         if (ret == -1) {
1886                 status = map_nt_error_from_unix_common(sys_errno);
1887                 dcesrv_terminate_connection(substate->dce_conn, nt_errstr(status));
1888                 return;
1889         }
1890
1891         talloc_free(substate);
1892         if (call) {
1893                 talloc_free(call);
1894         }
1895 }
1896
1897 static void dcesrv_call_terminate_step2(struct tevent_req *subreq);
1898
1899 static void dcesrv_call_terminate_step1(struct tevent_req *subreq)
1900 {
1901         struct dcesrv_call_state *call = tevent_req_callback_data(subreq,
1902                                                 struct dcesrv_call_state);
1903         bool ok;
1904         struct timeval tv;
1905
1906         /* make sure we stop send queue before removing subreq */
1907         tevent_queue_stop(call->conn->send_queue);
1908
1909         ok = tevent_queue_wait_recv(subreq);
1910         TALLOC_FREE(subreq);
1911         if (!ok) {
1912                 dcesrv_terminate_connection(call->conn, __location__);
1913                 return;
1914         }
1915
1916         /* disconnect after 200 usecs */
1917         tv = timeval_current_ofs_usec(200);
1918         subreq = tevent_wakeup_send(call, call->conn->event_ctx, tv);
1919         if (subreq == NULL) {
1920                 dcesrv_terminate_connection(call->conn, __location__);
1921                 return;
1922         }
1923         tevent_req_set_callback(subreq, dcesrv_call_terminate_step2,
1924                                 call);
1925 }
1926
1927 static void dcesrv_call_terminate_step2(struct tevent_req *subreq)
1928 {
1929         struct dcesrv_call_state *call = tevent_req_callback_data(subreq,
1930                                                 struct dcesrv_call_state);
1931         bool ok;
1932
1933         ok = tevent_wakeup_recv(subreq);
1934         TALLOC_FREE(subreq);
1935         if (!ok) {
1936                 dcesrv_terminate_connection(call->conn, __location__);
1937                 return;
1938         }
1939
1940         dcesrv_terminate_connection(call->conn, call->terminate_reason);
1941 }
1942
1943 struct dcesrv_socket_context {
1944         const struct dcesrv_endpoint *endpoint;
1945         struct dcesrv_context *dcesrv_ctx;
1946 };
1947
1948
1949 static void dcesrv_read_fragment_done(struct tevent_req *subreq);
1950
1951 static void dcesrv_sock_accept(struct stream_connection *srv_conn)
1952 {
1953         NTSTATUS status;
1954         struct dcesrv_socket_context *dcesrv_sock = 
1955                 talloc_get_type(srv_conn->private_data, struct dcesrv_socket_context);
1956         enum dcerpc_transport_t transport =
1957                 dcerpc_binding_get_transport(dcesrv_sock->endpoint->ep_description);
1958         struct dcesrv_connection *dcesrv_conn = NULL;
1959         int ret;
1960         struct tevent_req *subreq;
1961         struct loadparm_context *lp_ctx = dcesrv_sock->dcesrv_ctx->lp_ctx;
1962
1963         dcesrv_cleanup_broken_connections(dcesrv_sock->dcesrv_ctx);
1964
1965         if (!srv_conn->session_info) {
1966                 status = auth_anonymous_session_info(srv_conn,
1967                                                      lp_ctx,
1968                                                      &srv_conn->session_info);
1969                 if (!NT_STATUS_IS_OK(status)) {
1970                         DEBUG(0,("dcesrv_sock_accept: auth_anonymous_session_info failed: %s\n",
1971                                 nt_errstr(status)));
1972                         stream_terminate_connection(srv_conn, nt_errstr(status));
1973                         return;
1974                 }
1975         }
1976
1977         status = dcesrv_endpoint_connect(dcesrv_sock->dcesrv_ctx,
1978                                          srv_conn,
1979                                          dcesrv_sock->endpoint,
1980                                          srv_conn->session_info,
1981                                          srv_conn->event.ctx,
1982                                          srv_conn->msg_ctx,
1983                                          srv_conn->server_id,
1984                                          DCESRV_CALL_STATE_FLAG_MAY_ASYNC,
1985                                          &dcesrv_conn);
1986         if (!NT_STATUS_IS_OK(status)) {
1987                 DEBUG(0,("dcesrv_sock_accept: dcesrv_endpoint_connect failed: %s\n", 
1988                         nt_errstr(status)));
1989                 stream_terminate_connection(srv_conn, nt_errstr(status));
1990                 return;
1991         }
1992
1993         dcesrv_conn->transport.private_data             = srv_conn;
1994         dcesrv_conn->transport.report_output_data       = dcesrv_sock_report_output_data;
1995
1996         TALLOC_FREE(srv_conn->event.fde);
1997
1998         dcesrv_conn->send_queue = tevent_queue_create(dcesrv_conn, "dcesrv send queue");
1999         if (!dcesrv_conn->send_queue) {
2000                 status = NT_STATUS_NO_MEMORY;
2001                 DEBUG(0,("dcesrv_sock_accept: tevent_queue_create(%s)\n",
2002                         nt_errstr(status)));
2003                 stream_terminate_connection(srv_conn, nt_errstr(status));
2004                 return;
2005         }
2006
2007         if (transport == NCACN_NP) {
2008                 dcesrv_conn->auth_state.session_key = dcesrv_inherited_session_key;
2009                 dcesrv_conn->stream = talloc_move(dcesrv_conn,
2010                                                   &srv_conn->tstream);
2011         } else {
2012                 ret = tstream_bsd_existing_socket(dcesrv_conn,
2013                                                   socket_get_fd(srv_conn->socket),
2014                                                   &dcesrv_conn->stream);
2015                 if (ret == -1) {
2016                         status = map_nt_error_from_unix_common(errno);
2017                         DEBUG(0, ("dcesrv_sock_accept: "
2018                                   "failed to setup tstream: %s\n",
2019                                   nt_errstr(status)));
2020                         stream_terminate_connection(srv_conn, nt_errstr(status));
2021                         return;
2022                 }
2023                 socket_set_flags(srv_conn->socket, SOCKET_FLAG_NOCLOSE);
2024         }
2025
2026         dcesrv_conn->local_address = srv_conn->local_address;
2027         dcesrv_conn->remote_address = srv_conn->remote_address;
2028
2029         if (transport == NCALRPC) {
2030                 uid_t uid;
2031                 gid_t gid;
2032
2033                 ret = getpeereid(socket_get_fd(srv_conn->socket), &uid, &gid);
2034                 if (ret == -1) {
2035                         status = map_nt_error_from_unix_common(errno);
2036                         DEBUG(0, ("dcesrv_sock_accept: "
2037                                   "getpeereid() failed for NCALRPC: %s\n",
2038                                   nt_errstr(status)));
2039                         stream_terminate_connection(srv_conn, nt_errstr(status));
2040                         return;
2041                 }
2042                 if (uid == dcesrv_conn->dce_ctx->initial_euid) {
2043                         struct tsocket_address *r = NULL;
2044
2045                         ret = tsocket_address_unix_from_path(dcesrv_conn,
2046                                                              "/root/ncalrpc_as_system",
2047                                                              &r);
2048                         if (ret == -1) {
2049                                 status = map_nt_error_from_unix_common(errno);
2050                                 DEBUG(0, ("dcesrv_sock_accept: "
2051                                           "tsocket_address_unix_from_path() failed for NCALRPC: %s\n",
2052                                           nt_errstr(status)));
2053                                 stream_terminate_connection(srv_conn, nt_errstr(status));
2054                                 return;
2055                         }
2056                         dcesrv_conn->remote_address = r;
2057                 }
2058         }
2059
2060         srv_conn->private_data = dcesrv_conn;
2061
2062         irpc_add_name(srv_conn->msg_ctx, "rpc_server");
2063
2064         subreq = dcerpc_read_ncacn_packet_send(dcesrv_conn,
2065                                                dcesrv_conn->event_ctx,
2066                                                dcesrv_conn->stream);
2067         if (!subreq) {
2068                 status = NT_STATUS_NO_MEMORY;
2069                 DEBUG(0,("dcesrv_sock_accept: dcerpc_read_fragment_buffer_send(%s)\n",
2070                         nt_errstr(status)));
2071                 stream_terminate_connection(srv_conn, nt_errstr(status));
2072                 return;
2073         }
2074         tevent_req_set_callback(subreq, dcesrv_read_fragment_done, dcesrv_conn);
2075
2076         return;
2077 }
2078
2079 static void dcesrv_read_fragment_done(struct tevent_req *subreq)
2080 {
2081         struct dcesrv_connection *dce_conn = tevent_req_callback_data(subreq,
2082                                              struct dcesrv_connection);
2083         struct dcesrv_context *dce_ctx = dce_conn->dce_ctx;
2084         struct ncacn_packet *pkt;
2085         DATA_BLOB buffer;
2086         NTSTATUS status;
2087
2088         if (dce_conn->terminate) {
2089                 /*
2090                  * if the current connection is broken
2091                  * we need to clean it up before any other connection
2092                  */
2093                 dcesrv_terminate_connection(dce_conn, dce_conn->terminate);
2094                 dcesrv_cleanup_broken_connections(dce_ctx);
2095                 return;
2096         }
2097
2098         dcesrv_cleanup_broken_connections(dce_ctx);
2099
2100         status = dcerpc_read_ncacn_packet_recv(subreq, dce_conn,
2101                                                &pkt, &buffer);
2102         TALLOC_FREE(subreq);
2103         if (!NT_STATUS_IS_OK(status)) {
2104                 dcesrv_terminate_connection(dce_conn, nt_errstr(status));
2105                 return;
2106         }
2107
2108         status = dcesrv_process_ncacn_packet(dce_conn, pkt, buffer);
2109         if (!NT_STATUS_IS_OK(status)) {
2110                 dcesrv_terminate_connection(dce_conn, nt_errstr(status));
2111                 return;
2112         }
2113
2114         subreq = dcerpc_read_ncacn_packet_send(dce_conn,
2115                                                dce_conn->event_ctx,
2116                                                dce_conn->stream);
2117         if (!subreq) {
2118                 status = NT_STATUS_NO_MEMORY;
2119                 dcesrv_terminate_connection(dce_conn, nt_errstr(status));
2120                 return;
2121         }
2122         tevent_req_set_callback(subreq, dcesrv_read_fragment_done, dce_conn);
2123 }
2124
2125 static void dcesrv_sock_recv(struct stream_connection *conn, uint16_t flags)
2126 {
2127         struct dcesrv_connection *dce_conn = talloc_get_type(conn->private_data,
2128                                              struct dcesrv_connection);
2129         dcesrv_terminate_connection(dce_conn, "dcesrv_sock_recv triggered");
2130 }
2131
2132 static void dcesrv_sock_send(struct stream_connection *conn, uint16_t flags)
2133 {
2134         struct dcesrv_connection *dce_conn = talloc_get_type(conn->private_data,
2135                                              struct dcesrv_connection);
2136         dcesrv_terminate_connection(dce_conn, "dcesrv_sock_send triggered");
2137 }
2138
2139
2140 static const struct stream_server_ops dcesrv_stream_ops = {
2141         .name                   = "rpc",
2142         .accept_connection      = dcesrv_sock_accept,
2143         .recv_handler           = dcesrv_sock_recv,
2144         .send_handler           = dcesrv_sock_send,
2145 };
2146
2147 static NTSTATUS dcesrv_add_ep_unix(struct dcesrv_context *dce_ctx, 
2148                                    struct loadparm_context *lp_ctx,
2149                                    struct dcesrv_endpoint *e,
2150                             struct tevent_context *event_ctx, const struct model_ops *model_ops)
2151 {
2152         struct dcesrv_socket_context *dcesrv_sock;
2153         uint16_t port = 1;
2154         NTSTATUS status;
2155         const char *endpoint;
2156
2157         dcesrv_sock = talloc_zero(event_ctx, struct dcesrv_socket_context);
2158         NT_STATUS_HAVE_NO_MEMORY(dcesrv_sock);
2159
2160         /* remember the endpoint of this socket */
2161         dcesrv_sock->endpoint           = e;
2162         dcesrv_sock->dcesrv_ctx         = talloc_reference(dcesrv_sock, dce_ctx);
2163
2164         endpoint = dcerpc_binding_get_string_option(e->ep_description, "endpoint");
2165
2166         status = stream_setup_socket(dcesrv_sock, event_ctx, lp_ctx,
2167                                      model_ops, &dcesrv_stream_ops, 
2168                                      "unix", endpoint, &port,
2169                                      lpcfg_socket_options(lp_ctx),
2170                                      dcesrv_sock);
2171         if (!NT_STATUS_IS_OK(status)) {
2172                 DEBUG(0,("service_setup_stream_socket(path=%s) failed - %s\n",
2173                          endpoint, nt_errstr(status)));
2174         }
2175
2176         return status;
2177 }
2178
2179 static NTSTATUS dcesrv_add_ep_ncalrpc(struct dcesrv_context *dce_ctx, 
2180                                       struct loadparm_context *lp_ctx,
2181                                       struct dcesrv_endpoint *e,
2182                                       struct tevent_context *event_ctx, const struct model_ops *model_ops)
2183 {
2184         struct dcesrv_socket_context *dcesrv_sock;
2185         uint16_t port = 1;
2186         char *full_path;
2187         NTSTATUS status;
2188         const char *endpoint;
2189
2190         endpoint = dcerpc_binding_get_string_option(e->ep_description, "endpoint");
2191
2192         if (endpoint == NULL) {
2193                 /*
2194                  * No identifier specified: use DEFAULT.
2195                  *
2196                  * TODO: DO NOT hardcode this value anywhere else. Rather, specify
2197                  * no endpoint and let the epmapper worry about it.
2198                  */
2199                 endpoint = "DEFAULT";
2200                 status = dcerpc_binding_set_string_option(e->ep_description,
2201                                                           "endpoint",
2202                                                           endpoint);
2203                 if (!NT_STATUS_IS_OK(status)) {
2204                         DEBUG(0,("dcerpc_binding_set_string_option() failed - %s\n",
2205                                   nt_errstr(status)));
2206                         return status;
2207                 }
2208         }
2209
2210         full_path = talloc_asprintf(dce_ctx, "%s/%s", lpcfg_ncalrpc_dir(lp_ctx),
2211                                     endpoint);
2212
2213         dcesrv_sock = talloc_zero(event_ctx, struct dcesrv_socket_context);
2214         NT_STATUS_HAVE_NO_MEMORY(dcesrv_sock);
2215
2216         /* remember the endpoint of this socket */
2217         dcesrv_sock->endpoint           = e;
2218         dcesrv_sock->dcesrv_ctx         = talloc_reference(dcesrv_sock, dce_ctx);
2219
2220         status = stream_setup_socket(dcesrv_sock, event_ctx, lp_ctx,
2221                                      model_ops, &dcesrv_stream_ops, 
2222                                      "unix", full_path, &port, 
2223                                      lpcfg_socket_options(lp_ctx),
2224                                      dcesrv_sock);
2225         if (!NT_STATUS_IS_OK(status)) {
2226                 DEBUG(0,("service_setup_stream_socket(identifier=%s,path=%s) failed - %s\n",
2227                          endpoint, full_path, nt_errstr(status)));
2228         }
2229         return status;
2230 }
2231
2232 static NTSTATUS dcesrv_add_ep_np(struct dcesrv_context *dce_ctx,
2233                                  struct loadparm_context *lp_ctx,
2234                                  struct dcesrv_endpoint *e,
2235                                  struct tevent_context *event_ctx, const struct model_ops *model_ops)
2236 {
2237         struct dcesrv_socket_context *dcesrv_sock;
2238         NTSTATUS status;
2239         const char *endpoint;
2240
2241         endpoint = dcerpc_binding_get_string_option(e->ep_description, "endpoint");
2242         if (endpoint == NULL) {
2243                 DEBUG(0, ("Endpoint mandatory for named pipes\n"));
2244                 return NT_STATUS_INVALID_PARAMETER;
2245         }
2246
2247         dcesrv_sock = talloc_zero(event_ctx, struct dcesrv_socket_context);
2248         NT_STATUS_HAVE_NO_MEMORY(dcesrv_sock);
2249
2250         /* remember the endpoint of this socket */
2251         dcesrv_sock->endpoint           = e;
2252         dcesrv_sock->dcesrv_ctx         = talloc_reference(dcesrv_sock, dce_ctx);
2253
2254         status = tstream_setup_named_pipe(dce_ctx, event_ctx, lp_ctx,
2255                                           model_ops, &dcesrv_stream_ops,
2256                                           endpoint,
2257                                           dcesrv_sock);
2258         if (!NT_STATUS_IS_OK(status)) {
2259                 DEBUG(0,("stream_setup_named_pipe(pipe=%s) failed - %s\n",
2260                          endpoint, nt_errstr(status)));
2261                 return status;
2262         }
2263
2264         return NT_STATUS_OK;
2265 }
2266
2267 /*
2268   add a socket address to the list of events, one event per dcerpc endpoint
2269 */
2270 static NTSTATUS add_socket_rpc_tcp_iface(struct dcesrv_context *dce_ctx, struct dcesrv_endpoint *e,
2271                                          struct tevent_context *event_ctx, const struct model_ops *model_ops,
2272                                          const char *address)
2273 {
2274         struct dcesrv_socket_context *dcesrv_sock;
2275         uint16_t port = 0;
2276         NTSTATUS status;
2277         const char *endpoint;
2278         char port_str[6];
2279
2280         endpoint = dcerpc_binding_get_string_option(e->ep_description, "endpoint");
2281         if (endpoint != NULL) {
2282                 port = atoi(endpoint);
2283         }
2284
2285         dcesrv_sock = talloc_zero(event_ctx, struct dcesrv_socket_context);
2286         NT_STATUS_HAVE_NO_MEMORY(dcesrv_sock);
2287
2288         /* remember the endpoint of this socket */
2289         dcesrv_sock->endpoint           = e;
2290         dcesrv_sock->dcesrv_ctx         = talloc_reference(dcesrv_sock, dce_ctx);
2291
2292         status = stream_setup_socket(dcesrv_sock, event_ctx, dce_ctx->lp_ctx,
2293                                      model_ops, &dcesrv_stream_ops, 
2294                                      "ip", address, &port,
2295                                      lpcfg_socket_options(dce_ctx->lp_ctx),
2296                                      dcesrv_sock);
2297         if (!NT_STATUS_IS_OK(status)) {
2298                 DEBUG(0,("service_setup_stream_socket(address=%s,port=%u) failed - %s\n", 
2299                          address, port, nt_errstr(status)));
2300                 return status;
2301         }
2302
2303         snprintf(port_str, sizeof(port_str), "%u", port);
2304
2305         status = dcerpc_binding_set_string_option(e->ep_description,
2306                                                   "endpoint", port_str);
2307         if (!NT_STATUS_IS_OK(status)) {
2308                 DEBUG(0,("dcerpc_binding_set_string_option(endpoint, %s) failed - %s\n",
2309                          port_str, nt_errstr(status)));
2310                 return status;
2311         }
2312
2313         return NT_STATUS_OK;
2314 }
2315
2316 #include "lib/socket/netif.h" /* Included here to work around the fact that socket_wrapper redefines bind() */
2317
2318 static NTSTATUS dcesrv_add_ep_tcp(struct dcesrv_context *dce_ctx, 
2319                                   struct loadparm_context *lp_ctx,
2320                                   struct dcesrv_endpoint *e,
2321                                   struct tevent_context *event_ctx, const struct model_ops *model_ops)
2322 {
2323         NTSTATUS status;
2324
2325         /* Add TCP/IP sockets */
2326         if (lpcfg_interfaces(lp_ctx) && lpcfg_bind_interfaces_only(lp_ctx)) {
2327                 int num_interfaces;
2328                 int i;
2329                 struct interface *ifaces;
2330
2331                 load_interface_list(dce_ctx, lp_ctx, &ifaces);
2332
2333                 num_interfaces = iface_list_count(ifaces);
2334                 for(i = 0; i < num_interfaces; i++) {
2335                         const char *address = iface_list_n_ip(ifaces, i);
2336                         status = add_socket_rpc_tcp_iface(dce_ctx, e, event_ctx, model_ops, address);
2337                         NT_STATUS_NOT_OK_RETURN(status);
2338                 }
2339         } else {
2340                 char **wcard;
2341                 int i;
2342                 int num_binds = 0;
2343                 wcard = iface_list_wildcard(dce_ctx);
2344                 NT_STATUS_HAVE_NO_MEMORY(wcard);
2345                 for (i=0; wcard[i]; i++) {
2346                         status = add_socket_rpc_tcp_iface(dce_ctx, e, event_ctx, model_ops, wcard[i]);
2347                         if (NT_STATUS_IS_OK(status)) {
2348                                 num_binds++;
2349                         }
2350                 }
2351                 talloc_free(wcard);
2352                 if (num_binds == 0) {
2353                         return NT_STATUS_INVALID_PARAMETER_MIX;
2354                 }
2355         }
2356
2357         return NT_STATUS_OK;
2358 }
2359
2360 NTSTATUS dcesrv_add_ep(struct dcesrv_context *dce_ctx,
2361                        struct loadparm_context *lp_ctx,
2362                        struct dcesrv_endpoint *e,
2363                        struct tevent_context *event_ctx,
2364                        const struct model_ops *model_ops)
2365 {
2366         enum dcerpc_transport_t transport =
2367                 dcerpc_binding_get_transport(e->ep_description);
2368
2369         switch (transport) {
2370         case NCACN_UNIX_STREAM:
2371                 return dcesrv_add_ep_unix(dce_ctx, lp_ctx, e, event_ctx, model_ops);
2372
2373         case NCALRPC:
2374                 return dcesrv_add_ep_ncalrpc(dce_ctx, lp_ctx, e, event_ctx, model_ops);
2375
2376         case NCACN_IP_TCP:
2377                 return dcesrv_add_ep_tcp(dce_ctx, lp_ctx, e, event_ctx, model_ops);
2378
2379         case NCACN_NP:
2380                 return dcesrv_add_ep_np(dce_ctx, lp_ctx, e, event_ctx, model_ops);
2381
2382         default:
2383                 return NT_STATUS_NOT_SUPPORTED;
2384         }
2385 }
2386
2387
2388 /**
2389  * retrieve credentials from a dce_call
2390  */
2391 _PUBLIC_ struct cli_credentials *dcesrv_call_credentials(struct dcesrv_call_state *dce_call)
2392 {
2393         return dce_call->conn->auth_state.session_info->credentials;
2394 }
2395
2396 /**
2397  * returns true if this is an authenticated call
2398  */
2399 _PUBLIC_ bool dcesrv_call_authenticated(struct dcesrv_call_state *dce_call)
2400 {
2401         enum security_user_level level;
2402         level = security_session_user_level(dce_call->conn->auth_state.session_info, NULL);
2403         return level >= SECURITY_USER;
2404 }
2405
2406 /**
2407  * retrieve account_name for a dce_call
2408  */
2409 _PUBLIC_ const char *dcesrv_call_account_name(struct dcesrv_call_state *dce_call)
2410 {
2411         return dce_call->context->conn->auth_state.session_info->info->account_name;
2412 }