fb652c5064928d938f40de7aef3a9617ddb890bb
[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(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(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(ep, struct dcesrv_if_list);
301         if (!ifl) {
302                 return NT_STATUS_NO_MEMORY;
303         }
304
305         /* copy the given interface struct to the one on the endpoints interface list */
306         memcpy(&(ifl->iface),iface, sizeof(struct dcesrv_interface));
307
308         /* if we have a security descriptor given,
309          * we should see if we can set it up on the endpoint
310          */
311         if (sd != NULL) {
312                 /* if there's currently no security descriptor given on the endpoint
313                  * we try to set it
314                  */
315                 if (ep->sd == NULL) {
316                         ep->sd = security_descriptor_copy(ep, sd);
317                 }
318
319                 /* if now there's no security descriptor given on the endpoint
320                  * something goes wrong, either we failed to copy the security descriptor
321                  * or there was already one on the endpoint
322                  */
323                 if (ep->sd != NULL) {
324                         DEBUG(0,("dcesrv_interface_register: interface '%s' failed to setup a security descriptor\n"
325                                  "                           on endpoint '%s'\n",
326                                 iface->name, ep_name));
327                         if (add_ep) free(ep);
328                         free(ifl);
329                         return NT_STATUS_OBJECT_NAME_COLLISION;
330                 }
331         }
332
333         /* finally add the interface on the endpoint */
334         DLIST_ADD(ep->interface_list, ifl);
335
336         /* if it's a new endpoint add it to the dcesrv_context */
337         if (add_ep) {
338                 DLIST_ADD(dce_ctx->endpoint_list, ep);
339         }
340
341         DEBUG(4,("dcesrv_interface_register: interface '%s' registered on endpoint '%s'\n",
342                 iface->name, ep_name));
343
344         return NT_STATUS_OK;
345 }
346
347 NTSTATUS dcesrv_inherited_session_key(struct dcesrv_connection *p,
348                                       DATA_BLOB *session_key)
349 {
350         if (p->auth_state.session_info->session_key.length) {
351                 *session_key = p->auth_state.session_info->session_key;
352                 return NT_STATUS_OK;
353         }
354         return NT_STATUS_NO_USER_SESSION_KEY;
355 }
356
357 /*
358   fetch the user session key - may be default (above) or the SMB session key
359
360   The key is always truncated to 16 bytes 
361 */
362 _PUBLIC_ NTSTATUS dcesrv_fetch_session_key(struct dcesrv_connection *p,
363                                   DATA_BLOB *session_key)
364 {
365         NTSTATUS status = p->auth_state.session_key(p, session_key);
366         if (!NT_STATUS_IS_OK(status)) {
367                 return status;
368         }
369
370         session_key->length = MIN(session_key->length, 16);
371
372         return NT_STATUS_OK;
373 }
374
375 /*
376   connect to a dcerpc endpoint
377 */
378 _PUBLIC_ NTSTATUS dcesrv_endpoint_connect(struct dcesrv_context *dce_ctx,
379                                  TALLOC_CTX *mem_ctx,
380                                  const struct dcesrv_endpoint *ep,
381                                  struct auth_session_info *session_info,
382                                  struct tevent_context *event_ctx,
383                                  struct imessaging_context *msg_ctx,
384                                  struct server_id server_id,
385                                  uint32_t state_flags,
386                                  struct dcesrv_connection **_p)
387 {
388         struct dcesrv_connection *p;
389
390         if (!session_info) {
391                 return NT_STATUS_ACCESS_DENIED;
392         }
393
394         p = talloc_zero(mem_ctx, struct dcesrv_connection);
395         NT_STATUS_HAVE_NO_MEMORY(p);
396
397         if (!talloc_reference(p, session_info)) {
398                 talloc_free(p);
399                 return NT_STATUS_NO_MEMORY;
400         }
401
402         p->dce_ctx = dce_ctx;
403         p->endpoint = ep;
404         p->packet_log_dir = lpcfg_lock_directory(dce_ctx->lp_ctx);
405         p->auth_state.session_info = session_info;
406         p->auth_state.session_key = dcesrv_generic_session_key;
407         p->event_ctx = event_ctx;
408         p->msg_ctx = msg_ctx;
409         p->server_id = server_id;
410         p->state_flags = state_flags;
411
412         *_p = p;
413         return NT_STATUS_OK;
414 }
415
416 /*
417   move a call from an existing linked list to the specified list. This
418   prevents bugs where we forget to remove the call from a previous
419   list when moving it.
420  */
421 static void dcesrv_call_set_list(struct dcesrv_call_state *call, 
422                                  enum dcesrv_call_list list)
423 {
424         switch (call->list) {
425         case DCESRV_LIST_NONE:
426                 break;
427         case DCESRV_LIST_CALL_LIST:
428                 DLIST_REMOVE(call->conn->call_list, call);
429                 break;
430         case DCESRV_LIST_FRAGMENTED_CALL_LIST:
431                 DLIST_REMOVE(call->conn->incoming_fragmented_call_list, call);
432                 break;
433         case DCESRV_LIST_PENDING_CALL_LIST:
434                 DLIST_REMOVE(call->conn->pending_call_list, call);
435                 break;
436         }
437         call->list = list;
438         switch (list) {
439         case DCESRV_LIST_NONE:
440                 break;
441         case DCESRV_LIST_CALL_LIST:
442                 DLIST_ADD_END(call->conn->call_list, call, struct dcesrv_call_state *);
443                 break;
444         case DCESRV_LIST_FRAGMENTED_CALL_LIST:
445                 DLIST_ADD_END(call->conn->incoming_fragmented_call_list, call, struct dcesrv_call_state *);
446                 break;
447         case DCESRV_LIST_PENDING_CALL_LIST:
448                 DLIST_ADD_END(call->conn->pending_call_list, call, struct dcesrv_call_state *);
449                 break;
450         }
451 }
452
453
454 /*
455   return a dcerpc bind_nak
456 */
457 static NTSTATUS dcesrv_bind_nak(struct dcesrv_call_state *call, uint32_t reason)
458 {
459         struct ncacn_packet pkt;
460         struct data_blob_list_item *rep;
461         NTSTATUS status;
462
463         /* setup a bind_nak */
464         dcesrv_init_hdr(&pkt, lpcfg_rpc_big_endian(call->conn->dce_ctx->lp_ctx));
465         pkt.auth_length = 0;
466         pkt.call_id = call->pkt.call_id;
467         pkt.ptype = DCERPC_PKT_BIND_NAK;
468         pkt.pfc_flags = DCERPC_PFC_FLAG_FIRST | DCERPC_PFC_FLAG_LAST;
469         pkt.u.bind_nak.reject_reason = reason;
470         if (pkt.u.bind_nak.reject_reason == DECRPC_BIND_PROTOCOL_VERSION_NOT_SUPPORTED) {
471                 pkt.u.bind_nak.versions.v.num_versions = 0;
472         }
473
474         rep = talloc(call, struct data_blob_list_item);
475         if (!rep) {
476                 return NT_STATUS_NO_MEMORY;
477         }
478
479         status = ncacn_push_auth(&rep->blob, call, &pkt, NULL);
480         if (!NT_STATUS_IS_OK(status)) {
481                 return status;
482         }
483
484         dcerpc_set_frag_length(&rep->blob, rep->blob.length);
485
486         DLIST_ADD_END(call->replies, rep, struct data_blob_list_item *);
487         dcesrv_call_set_list(call, DCESRV_LIST_CALL_LIST);
488
489         if (call->conn->call_list && call->conn->call_list->replies) {
490                 if (call->conn->transport.report_output_data) {
491                         call->conn->transport.report_output_data(call->conn);
492                 }
493         }
494
495         return NT_STATUS_OK;    
496 }
497
498 static int dcesrv_connection_context_destructor(struct dcesrv_connection_context *c)
499 {
500         DLIST_REMOVE(c->conn->contexts, c);
501
502         if (c->iface && c->iface->unbind) {
503                 c->iface->unbind(c, c->iface);
504         }
505
506         return 0;
507 }
508
509 /*
510   handle a bind request
511 */
512 static NTSTATUS dcesrv_bind(struct dcesrv_call_state *call)
513 {
514         uint32_t if_version, transfer_syntax_version;
515         struct GUID uuid, *transfer_syntax_uuid;
516         struct ncacn_packet pkt;
517         struct data_blob_list_item *rep;
518         NTSTATUS status;
519         uint32_t result=0, reason=0;
520         uint32_t context_id;
521         const struct dcesrv_interface *iface;
522         uint32_t extra_flags = 0;
523
524         /*
525           if provided, check the assoc_group is valid
526          */
527         if (call->pkt.u.bind.assoc_group_id != 0 &&
528             lpcfg_parm_bool(call->conn->dce_ctx->lp_ctx, NULL, "dcesrv","assoc group checking", true) &&
529             dcesrv_assoc_group_find(call->conn->dce_ctx, call->pkt.u.bind.assoc_group_id) == NULL) {
530                 return dcesrv_bind_nak(call, 0);        
531         }
532
533         if (call->pkt.u.bind.num_contexts < 1 ||
534             call->pkt.u.bind.ctx_list[0].num_transfer_syntaxes < 1) {
535                 return dcesrv_bind_nak(call, 0);
536         }
537
538         context_id = call->pkt.u.bind.ctx_list[0].context_id;
539
540         /* you can't bind twice on one context */
541         if (dcesrv_find_context(call->conn, context_id) != NULL) {
542                 return dcesrv_bind_nak(call, 0);
543         }
544
545         if_version = call->pkt.u.bind.ctx_list[0].abstract_syntax.if_version;
546         uuid = call->pkt.u.bind.ctx_list[0].abstract_syntax.uuid;
547
548         transfer_syntax_version = call->pkt.u.bind.ctx_list[0].transfer_syntaxes[0].if_version;
549         transfer_syntax_uuid = &call->pkt.u.bind.ctx_list[0].transfer_syntaxes[0].uuid;
550         if (!GUID_equal(&ndr_transfer_syntax_ndr.uuid, transfer_syntax_uuid) != 0 ||
551             ndr_transfer_syntax_ndr.if_version != transfer_syntax_version) {
552                 char *uuid_str = GUID_string(call, transfer_syntax_uuid);
553                 /* we only do NDR encoded dcerpc */
554                 DEBUG(0,("Non NDR transfer syntax requested - %s\n", uuid_str));
555                 talloc_free(uuid_str);
556                 return dcesrv_bind_nak(call, 0);
557         }
558
559         iface = find_interface_by_uuid(call->conn->endpoint, &uuid, if_version);
560         if (iface == NULL) {
561                 char *uuid_str = GUID_string(call, &uuid);
562                 DEBUG(2,("Request for unknown dcerpc interface %s/%d\n", uuid_str, if_version));
563                 talloc_free(uuid_str);
564
565                 /* we don't know about that interface */
566                 result = DCERPC_BIND_PROVIDER_REJECT;
567                 reason = DCERPC_BIND_REASON_ASYNTAX;            
568         }
569
570         if (iface) {
571                 /* add this context to the list of available context_ids */
572                 struct dcesrv_connection_context *context = talloc(call->conn, 
573                                                                    struct dcesrv_connection_context);
574                 if (context == NULL) {
575                         return dcesrv_bind_nak(call, 0);
576                 }
577                 context->conn = call->conn;
578                 context->iface = iface;
579                 context->context_id = context_id;
580                 if (call->pkt.u.bind.assoc_group_id != 0) {
581                         context->assoc_group = dcesrv_assoc_group_reference(context,
582                                                                             call->conn->dce_ctx, 
583                                                                             call->pkt.u.bind.assoc_group_id);
584                 } else {
585                         context->assoc_group = dcesrv_assoc_group_new(context, call->conn->dce_ctx);
586                 }
587                 if (context->assoc_group == NULL) {
588                         talloc_free(context);
589                         return dcesrv_bind_nak(call, 0);
590                 }
591                 context->private_data = NULL;
592                 DLIST_ADD(call->conn->contexts, context);
593                 call->context = context;
594                 talloc_set_destructor(context, dcesrv_connection_context_destructor);
595
596                 status = iface->bind(call, iface, if_version);
597                 if (!NT_STATUS_IS_OK(status)) {
598                         char *uuid_str = GUID_string(call, &uuid);
599                         DEBUG(2,("Request for dcerpc interface %s/%d rejected: %s\n",
600                                  uuid_str, if_version, nt_errstr(status)));
601                         talloc_free(uuid_str);
602                         /* we don't want to trigger the iface->unbind() hook */
603                         context->iface = NULL;
604                         talloc_free(call->context);
605                         call->context = NULL;
606                         return dcesrv_bind_nak(call, 0);
607                 }
608         }
609
610         if (call->conn->cli_max_recv_frag == 0) {
611                 call->conn->cli_max_recv_frag = MIN(0x2000, call->pkt.u.bind.max_recv_frag);
612         }
613
614         /* handle any authentication that is being requested */
615         if (!dcesrv_auth_bind(call)) {
616                 talloc_free(call->context);
617                 call->context = NULL;
618                 return dcesrv_bind_nak(call, DCERPC_BIND_REASON_INVALID_AUTH_TYPE);
619         }
620
621         /* setup a bind_ack */
622         dcesrv_init_hdr(&pkt, lpcfg_rpc_big_endian(call->conn->dce_ctx->lp_ctx));
623         pkt.auth_length = 0;
624         pkt.call_id = call->pkt.call_id;
625         pkt.ptype = DCERPC_PKT_BIND_ACK;
626         pkt.pfc_flags = DCERPC_PFC_FLAG_FIRST | DCERPC_PFC_FLAG_LAST | extra_flags;
627         pkt.u.bind_ack.max_xmit_frag = call->conn->cli_max_recv_frag;
628         pkt.u.bind_ack.max_recv_frag = 0x2000;
629
630         /*
631           make it possible for iface->bind() to specify the assoc_group_id
632           This helps the openchange mapiproxy plugin to work correctly.
633           
634           metze
635         */
636         if (call->context) {
637                 pkt.u.bind_ack.assoc_group_id = call->context->assoc_group->id;
638         } else {
639                 pkt.u.bind_ack.assoc_group_id = DUMMY_ASSOC_GROUP;
640         }
641
642         if (iface) {
643                 /* FIXME: Use pipe name as specified by endpoint instead of interface name */
644                 pkt.u.bind_ack.secondary_address = talloc_asprintf(call, "\\PIPE\\%s", iface->name);
645         } else {
646                 pkt.u.bind_ack.secondary_address = "";
647         }
648         pkt.u.bind_ack.num_results = 1;
649         pkt.u.bind_ack.ctx_list = talloc(call, struct dcerpc_ack_ctx);
650         if (!pkt.u.bind_ack.ctx_list) {
651                 talloc_free(call->context);
652                 call->context = NULL;
653                 return NT_STATUS_NO_MEMORY;
654         }
655         pkt.u.bind_ack.ctx_list[0].result = result;
656         pkt.u.bind_ack.ctx_list[0].reason.value = reason;
657         pkt.u.bind_ack.ctx_list[0].syntax = ndr_transfer_syntax_ndr;
658         pkt.u.bind_ack.auth_info = data_blob(NULL, 0);
659
660         status = dcesrv_auth_bind_ack(call, &pkt);
661         if (!NT_STATUS_IS_OK(status)) {
662                 talloc_free(call->context);
663                 call->context = NULL;
664                 return dcesrv_bind_nak(call, 0);
665         }
666
667         rep = talloc(call, struct data_blob_list_item);
668         if (!rep) {
669                 talloc_free(call->context);
670                 call->context = NULL;
671                 return NT_STATUS_NO_MEMORY;
672         }
673
674         status = ncacn_push_auth(&rep->blob, call, &pkt,
675                                                          call->conn->auth_state.auth_info);
676         if (!NT_STATUS_IS_OK(status)) {
677                 talloc_free(call->context);
678                 call->context = NULL;
679                 return status;
680         }
681
682         dcerpc_set_frag_length(&rep->blob, rep->blob.length);
683
684         DLIST_ADD_END(call->replies, rep, struct data_blob_list_item *);
685         dcesrv_call_set_list(call, DCESRV_LIST_CALL_LIST);
686
687         if (call->conn->call_list && call->conn->call_list->replies) {
688                 if (call->conn->transport.report_output_data) {
689                         call->conn->transport.report_output_data(call->conn);
690                 }
691         }
692
693         return NT_STATUS_OK;
694 }
695
696
697 /*
698   handle a auth3 request
699 */
700 static NTSTATUS dcesrv_auth3(struct dcesrv_call_state *call)
701 {
702         /* handle the auth3 in the auth code */
703         if (!dcesrv_auth_auth3(call)) {
704                 return dcesrv_fault(call, DCERPC_FAULT_OTHER);
705         }
706
707         talloc_free(call);
708
709         /* we don't send a reply to a auth3 request, except by a
710            fault */
711         return NT_STATUS_OK;
712 }
713
714
715 /*
716   handle a bind request
717 */
718 static NTSTATUS dcesrv_alter_new_context(struct dcesrv_call_state *call, uint32_t context_id)
719 {
720         uint32_t if_version, transfer_syntax_version;
721         struct dcesrv_connection_context *context;
722         const struct dcesrv_interface *iface;
723         struct GUID uuid, *transfer_syntax_uuid;
724         NTSTATUS status;
725
726         if_version = call->pkt.u.alter.ctx_list[0].abstract_syntax.if_version;
727         uuid = call->pkt.u.alter.ctx_list[0].abstract_syntax.uuid;
728
729         transfer_syntax_version = call->pkt.u.alter.ctx_list[0].transfer_syntaxes[0].if_version;
730         transfer_syntax_uuid = &call->pkt.u.alter.ctx_list[0].transfer_syntaxes[0].uuid;
731         if (!GUID_equal(transfer_syntax_uuid, &ndr_transfer_syntax_ndr.uuid) ||
732             ndr_transfer_syntax_ndr.if_version != transfer_syntax_version) {
733                 /* we only do NDR encoded dcerpc */
734                 return NT_STATUS_RPC_PROTSEQ_NOT_SUPPORTED;
735         }
736
737         iface = find_interface_by_uuid(call->conn->endpoint, &uuid, if_version);
738         if (iface == NULL) {
739                 char *uuid_str = GUID_string(call, &uuid);
740                 DEBUG(2,("Request for unknown dcerpc interface %s/%d\n", uuid_str, if_version));
741                 talloc_free(uuid_str);
742                 return NT_STATUS_RPC_PROTSEQ_NOT_SUPPORTED;
743         }
744
745         /* add this context to the list of available context_ids */
746         context = talloc(call->conn, struct dcesrv_connection_context);
747         if (context == NULL) {
748                 return NT_STATUS_NO_MEMORY;
749         }
750         context->conn = call->conn;
751         context->iface = iface;
752         context->context_id = context_id;
753         if (call->pkt.u.alter.assoc_group_id != 0) {
754                 context->assoc_group = dcesrv_assoc_group_reference(context,
755                                                                     call->conn->dce_ctx, 
756                                                                     call->pkt.u.alter.assoc_group_id);
757         } else {
758                 context->assoc_group = dcesrv_assoc_group_new(context, call->conn->dce_ctx);
759         }
760         if (context->assoc_group == NULL) {
761                 talloc_free(context);
762                 call->context = NULL;
763                 return NT_STATUS_NO_MEMORY;
764         }
765         context->private_data = NULL;
766         DLIST_ADD(call->conn->contexts, context);
767         call->context = context;
768         talloc_set_destructor(context, dcesrv_connection_context_destructor);
769
770         status = iface->bind(call, iface, if_version);
771         if (!NT_STATUS_IS_OK(status)) {
772                 /* we don't want to trigger the iface->unbind() hook */
773                 context->iface = NULL;
774                 talloc_free(context);
775                 call->context = NULL;
776                 return status;
777         }
778
779         return NT_STATUS_OK;
780 }
781
782
783 /*
784   handle a alter context request
785 */
786 static NTSTATUS dcesrv_alter(struct dcesrv_call_state *call)
787 {
788         struct ncacn_packet pkt;
789         struct data_blob_list_item *rep;
790         NTSTATUS status;
791         uint32_t result=0, reason=0;
792         uint32_t context_id;
793
794         /* handle any authentication that is being requested */
795         if (!dcesrv_auth_alter(call)) {
796                 /* TODO: work out the right reject code */
797                 result = DCERPC_BIND_PROVIDER_REJECT;
798                 reason = DCERPC_BIND_REASON_ASYNTAX;            
799         }
800
801         context_id = call->pkt.u.alter.ctx_list[0].context_id;
802
803         /* see if they are asking for a new interface */
804         if (result == 0) {
805                 call->context = dcesrv_find_context(call->conn, context_id);
806                 if (!call->context) {
807                         status = dcesrv_alter_new_context(call, context_id);
808                         if (!NT_STATUS_IS_OK(status)) {
809                                 result = DCERPC_BIND_PROVIDER_REJECT;
810                                 reason = DCERPC_BIND_REASON_ASYNTAX;
811                         }
812                 }
813         }
814
815         if (result == 0 &&
816             call->pkt.u.alter.assoc_group_id != 0 &&
817             lpcfg_parm_bool(call->conn->dce_ctx->lp_ctx, NULL, "dcesrv","assoc group checking", true) &&
818             call->pkt.u.alter.assoc_group_id != call->context->assoc_group->id) {
819                 DEBUG(0,(__location__ ": Failed attempt to use new assoc_group in alter context (0x%08x 0x%08x)\n",
820                          call->context->assoc_group->id, call->pkt.u.alter.assoc_group_id));
821                 /* TODO: can they ask for a new association group? */
822                 result = DCERPC_BIND_PROVIDER_REJECT;
823                 reason = DCERPC_BIND_REASON_ASYNTAX;
824         }
825
826         /* setup a alter_resp */
827         dcesrv_init_hdr(&pkt, lpcfg_rpc_big_endian(call->conn->dce_ctx->lp_ctx));
828         pkt.auth_length = 0;
829         pkt.call_id = call->pkt.call_id;
830         pkt.ptype = DCERPC_PKT_ALTER_RESP;
831         pkt.pfc_flags = DCERPC_PFC_FLAG_FIRST | DCERPC_PFC_FLAG_LAST;
832         pkt.u.alter_resp.max_xmit_frag = 0x2000;
833         pkt.u.alter_resp.max_recv_frag = 0x2000;
834         if (result == 0) {
835                 pkt.u.alter_resp.assoc_group_id = call->context->assoc_group->id;
836         } else {
837                 pkt.u.alter_resp.assoc_group_id = 0;
838         }
839         pkt.u.alter_resp.num_results = 1;
840         pkt.u.alter_resp.ctx_list = talloc_array(call, struct dcerpc_ack_ctx, 1);
841         if (!pkt.u.alter_resp.ctx_list) {
842                 return NT_STATUS_NO_MEMORY;
843         }
844         pkt.u.alter_resp.ctx_list[0].result = result;
845         pkt.u.alter_resp.ctx_list[0].reason.value = reason;
846         pkt.u.alter_resp.ctx_list[0].syntax = ndr_transfer_syntax_ndr;
847         pkt.u.alter_resp.auth_info = data_blob(NULL, 0);
848         pkt.u.alter_resp.secondary_address = "";
849
850         status = dcesrv_auth_alter_ack(call, &pkt);
851         if (!NT_STATUS_IS_OK(status)) {
852                 if (NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)
853                     || NT_STATUS_EQUAL(status, NT_STATUS_LOGON_FAILURE)
854                     || NT_STATUS_EQUAL(status, NT_STATUS_NO_SUCH_USER)
855                     || NT_STATUS_EQUAL(status, NT_STATUS_WRONG_PASSWORD)) {
856                         return dcesrv_fault(call, DCERPC_FAULT_ACCESS_DENIED);
857                 }
858                 return dcesrv_fault(call, 0);
859         }
860
861         rep = talloc(call, struct data_blob_list_item);
862         if (!rep) {
863                 return NT_STATUS_NO_MEMORY;
864         }
865
866         status = ncacn_push_auth(&rep->blob, call, &pkt, call->conn->auth_state.auth_info);
867         if (!NT_STATUS_IS_OK(status)) {
868                 return status;
869         }
870
871         dcerpc_set_frag_length(&rep->blob, rep->blob.length);
872
873         DLIST_ADD_END(call->replies, rep, struct data_blob_list_item *);
874         dcesrv_call_set_list(call, DCESRV_LIST_CALL_LIST);
875
876         if (call->conn->call_list && call->conn->call_list->replies) {
877                 if (call->conn->transport.report_output_data) {
878                         call->conn->transport.report_output_data(call->conn);
879                 }
880         }
881
882         return NT_STATUS_OK;
883 }
884
885 /*
886   possibly save the call for inspection with ndrdump
887  */
888 static void dcesrv_save_call(struct dcesrv_call_state *call, const char *why)
889 {
890 #ifdef DEVELOPER
891         char *fname;
892         const char *dump_dir;
893         dump_dir = lpcfg_parm_string(call->conn->dce_ctx->lp_ctx, NULL, "dcesrv", "stubs directory");
894         if (!dump_dir) {
895                 return;
896         }
897         fname = talloc_asprintf(call, "%s/RPC-%s-%u-%s.dat",
898                                 dump_dir,
899                                 call->context->iface->name,
900                                 call->pkt.u.request.opnum,
901                                 why);
902         if (file_save(fname, call->pkt.u.request.stub_and_verifier.data, call->pkt.u.request.stub_and_verifier.length)) {
903                 DEBUG(0,("RPC SAVED %s\n", fname));
904         }
905         talloc_free(fname);
906 #endif
907 }
908
909 static NTSTATUS dcesrv_check_verification_trailer(struct dcesrv_call_state *call)
910 {
911         TALLOC_CTX *frame = talloc_stackframe();
912         const uint32_t bitmask1 = call->conn->auth_state.client_hdr_signing ?
913                 DCERPC_SEC_VT_CLIENT_SUPPORTS_HEADER_SIGNING : 0;
914         const struct dcerpc_sec_vt_pcontext pcontext = {
915                 .abstract_syntax = call->context->iface->syntax_id,
916                 .transfer_syntax = ndr_transfer_syntax_ndr,
917         };
918         const struct dcerpc_sec_vt_header2 header2 =
919                 dcerpc_sec_vt_header2_from_ncacn_packet(&call->pkt);
920         enum ndr_err_code ndr_err;
921         struct dcerpc_sec_verification_trailer *vt = NULL;
922         NTSTATUS status = NT_STATUS_OK;
923         bool ok;
924
925         SMB_ASSERT(call->pkt.ptype == DCERPC_PKT_REQUEST);
926
927         ndr_err = ndr_pop_dcerpc_sec_verification_trailer(call->ndr_pull,
928                                                           frame, &vt);
929         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
930                 status = ndr_map_error2ntstatus(ndr_err);
931                 goto done;
932         }
933
934         ok = dcerpc_sec_verification_trailer_check(vt, &bitmask1,
935                                                    &pcontext, &header2);
936         if (!ok) {
937                 status = NT_STATUS_ACCESS_DENIED;
938                 goto done;
939         }
940 done:
941         TALLOC_FREE(frame);
942         return status;
943 }
944
945 /*
946   handle a dcerpc request packet
947 */
948 static NTSTATUS dcesrv_request(struct dcesrv_call_state *call)
949 {
950         struct ndr_pull *pull;
951         NTSTATUS status;
952         struct dcesrv_connection_context *context;
953
954         /* if authenticated, and the mech we use can't do async replies, don't use them... */
955         if (call->conn->auth_state.gensec_security && 
956             !gensec_have_feature(call->conn->auth_state.gensec_security, GENSEC_FEATURE_ASYNC_REPLIES)) {
957                 call->state_flags &= ~DCESRV_CALL_STATE_FLAG_MAY_ASYNC;
958         }
959
960         context = dcesrv_find_context(call->conn, call->pkt.u.request.context_id);
961         if (context == NULL) {
962                 return dcesrv_fault(call, DCERPC_FAULT_UNK_IF);
963         }
964
965         pull = ndr_pull_init_blob(&call->pkt.u.request.stub_and_verifier, call);
966         NT_STATUS_HAVE_NO_MEMORY(pull);
967
968         pull->flags |= LIBNDR_FLAG_REF_ALLOC;
969
970         call->context   = context;
971         call->ndr_pull  = pull;
972
973         if (!(call->pkt.drep[0] & DCERPC_DREP_LE)) {
974                 pull->flags |= LIBNDR_FLAG_BIGENDIAN;
975         }
976
977         status = dcesrv_check_verification_trailer(call);
978         if (!NT_STATUS_IS_OK(status)) {
979                 uint32_t faultcode = DCERPC_FAULT_OTHER;
980                 if (NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
981                         faultcode = DCERPC_FAULT_ACCESS_DENIED;
982                 }
983                 DEBUG(10, ("dcesrv_check_verification_trailer failed: %s\n",
984                            nt_errstr(status)));
985                 return dcesrv_fault(call, faultcode);
986         }
987
988         /* unravel the NDR for the packet */
989         status = context->iface->ndr_pull(call, call, pull, &call->r);
990         if (!NT_STATUS_IS_OK(status)) {
991                 if (call->fault_code == DCERPC_FAULT_OP_RNG_ERROR) {
992                         /* we got an unknown call */
993                         DEBUG(3,(__location__ ": Unknown RPC call %u on %s\n",
994                                  call->pkt.u.request.opnum, context->iface->name));
995                         dcesrv_save_call(call, "unknown");
996                 } else {
997                         dcesrv_save_call(call, "pullfail");
998                 }
999                 return dcesrv_fault(call, call->fault_code);
1000         }
1001
1002         if (pull->offset != pull->data_size) {
1003                 dcesrv_save_call(call, "extrabytes");
1004                 DEBUG(3,("Warning: %d extra bytes in incoming RPC request\n", 
1005                          pull->data_size - pull->offset));
1006         }
1007
1008         /* call the dispatch function */
1009         status = context->iface->dispatch(call, call, call->r);
1010         if (!NT_STATUS_IS_OK(status)) {
1011                 DEBUG(5,("dcerpc fault in call %s:%02x - %s\n",
1012                          context->iface->name, 
1013                          call->pkt.u.request.opnum,
1014                          dcerpc_errstr(pull, call->fault_code)));
1015                 return dcesrv_fault(call, call->fault_code);
1016         }
1017
1018         /* add the call to the pending list */
1019         dcesrv_call_set_list(call, DCESRV_LIST_PENDING_CALL_LIST);
1020
1021         if (call->state_flags & DCESRV_CALL_STATE_FLAG_ASYNC) {
1022                 return NT_STATUS_OK;
1023         }
1024
1025         return dcesrv_reply(call);
1026 }
1027
1028
1029 /*
1030   remove the call from the right list when freed
1031  */
1032 static int dcesrv_call_dequeue(struct dcesrv_call_state *call)
1033 {
1034         dcesrv_call_set_list(call, DCESRV_LIST_NONE);
1035         return 0;
1036 }
1037
1038 _PUBLIC_ const struct tsocket_address *dcesrv_connection_get_local_address(struct dcesrv_connection *conn)
1039 {
1040         return conn->local_address;
1041 }
1042
1043 _PUBLIC_ const struct tsocket_address *dcesrv_connection_get_remote_address(struct dcesrv_connection *conn)
1044 {
1045         return conn->remote_address;
1046 }
1047
1048 /*
1049   process some input to a dcerpc endpoint server.
1050 */
1051 NTSTATUS dcesrv_process_ncacn_packet(struct dcesrv_connection *dce_conn,
1052                                      struct ncacn_packet *pkt,
1053                                      DATA_BLOB blob)
1054 {
1055         NTSTATUS status;
1056         struct dcesrv_call_state *call;
1057
1058         call = talloc_zero(dce_conn, struct dcesrv_call_state);
1059         if (!call) {
1060                 data_blob_free(&blob);
1061                 talloc_free(pkt);
1062                 return NT_STATUS_NO_MEMORY;
1063         }
1064         call->conn              = dce_conn;
1065         call->event_ctx         = dce_conn->event_ctx;
1066         call->msg_ctx           = dce_conn->msg_ctx;
1067         call->state_flags       = call->conn->state_flags;
1068         call->time              = timeval_current();
1069         call->list              = DCESRV_LIST_NONE;
1070
1071         talloc_steal(call, pkt);
1072         talloc_steal(call, blob.data);
1073         call->pkt = *pkt;
1074
1075         talloc_set_destructor(call, dcesrv_call_dequeue);
1076
1077         /* we have to check the signing here, before combining the
1078            pdus */
1079         if (call->pkt.ptype == DCERPC_PKT_REQUEST &&
1080             !dcesrv_auth_request(call, &blob)) {
1081                 return dcesrv_fault(call, DCERPC_FAULT_ACCESS_DENIED);          
1082         }
1083
1084         /* see if this is a continued packet */
1085         if (call->pkt.ptype == DCERPC_PKT_REQUEST &&
1086             !(call->pkt.pfc_flags & DCERPC_PFC_FLAG_FIRST)) {
1087                 struct dcesrv_call_state *call2 = call;
1088                 uint32_t alloc_size;
1089
1090                 /* we only allow fragmented requests, no other packet types */
1091                 if (call->pkt.ptype != DCERPC_PKT_REQUEST) {
1092                         return dcesrv_fault(call2, DCERPC_FAULT_OTHER);
1093                 }
1094
1095                 /* this is a continuation of an existing call - find the call
1096                    then tack it on the end */
1097                 call = dcesrv_find_fragmented_call(dce_conn, call2->pkt.call_id);
1098                 if (!call) {
1099                         return dcesrv_fault(call2, DCERPC_FAULT_OTHER);
1100                 }
1101
1102                 if (call->pkt.ptype != call2->pkt.ptype) {
1103                         /* trying to play silly buggers are we? */
1104                         return dcesrv_fault(call2, DCERPC_NCA_S_PROTO_ERROR);
1105                 }
1106                 if (memcmp(call->pkt.drep, call2->pkt.drep, sizeof(pkt->drep)) != 0) {
1107                         return dcesrv_fault(call2, DCERPC_NCA_S_PROTO_ERROR);
1108                 }
1109                 if (call->pkt.call_id != call2->pkt.call_id) {
1110                         return dcesrv_fault(call2, DCERPC_NCA_S_PROTO_ERROR);
1111                 }
1112                 if (call->pkt.u.request.context_id != call2->pkt.u.request.context_id)  {
1113                         return dcesrv_fault(call2, DCERPC_NCA_S_PROTO_ERROR);
1114                 }
1115                 if (call->pkt.u.request.opnum != call2->pkt.u.request.opnum)  {
1116                         return dcesrv_fault(call2, DCERPC_NCA_S_PROTO_ERROR);
1117                 }
1118
1119                 alloc_size = call->pkt.u.request.stub_and_verifier.length +
1120                         call2->pkt.u.request.stub_and_verifier.length;
1121                 if (call->pkt.u.request.alloc_hint > alloc_size) {
1122                         alloc_size = call->pkt.u.request.alloc_hint;
1123                 }
1124
1125                 call->pkt.u.request.stub_and_verifier.data = 
1126                         talloc_realloc(call, 
1127                                        call->pkt.u.request.stub_and_verifier.data, 
1128                                        uint8_t, alloc_size);
1129                 if (!call->pkt.u.request.stub_and_verifier.data) {
1130                         return dcesrv_fault(call2, DCERPC_FAULT_OTHER);
1131                 }
1132                 memcpy(call->pkt.u.request.stub_and_verifier.data +
1133                        call->pkt.u.request.stub_and_verifier.length,
1134                        call2->pkt.u.request.stub_and_verifier.data,
1135                        call2->pkt.u.request.stub_and_verifier.length);
1136                 call->pkt.u.request.stub_and_verifier.length += 
1137                         call2->pkt.u.request.stub_and_verifier.length;
1138
1139                 call->pkt.pfc_flags |= (call2->pkt.pfc_flags & DCERPC_PFC_FLAG_LAST);
1140
1141                 talloc_free(call2);
1142         }
1143
1144         /* this may not be the last pdu in the chain - if its isn't then
1145            just put it on the incoming_fragmented_call_list and wait for the rest */
1146         if (call->pkt.ptype == DCERPC_PKT_REQUEST &&
1147             !(call->pkt.pfc_flags & DCERPC_PFC_FLAG_LAST)) {
1148                 dcesrv_call_set_list(call, DCESRV_LIST_FRAGMENTED_CALL_LIST);
1149                 return NT_STATUS_OK;
1150         } 
1151         
1152         /* This removes any fragments we may have had stashed away */
1153         dcesrv_call_set_list(call, DCESRV_LIST_NONE);
1154
1155         switch (call->pkt.ptype) {
1156         case DCERPC_PKT_BIND:
1157                 status = dcesrv_bind(call);
1158                 break;
1159         case DCERPC_PKT_AUTH3:
1160                 status = dcesrv_auth3(call);
1161                 break;
1162         case DCERPC_PKT_ALTER:
1163                 status = dcesrv_alter(call);
1164                 break;
1165         case DCERPC_PKT_REQUEST:
1166                 status = dcesrv_request(call);
1167                 break;
1168         default:
1169                 status = NT_STATUS_INVALID_PARAMETER;
1170                 break;
1171         }
1172
1173         /* if we are going to be sending a reply then add
1174            it to the list of pending calls. We add it to the end to keep the call
1175            list in the order we will answer */
1176         if (!NT_STATUS_IS_OK(status)) {
1177                 talloc_free(call);
1178         }
1179
1180         return status;
1181 }
1182
1183 _PUBLIC_ NTSTATUS dcesrv_init_context(TALLOC_CTX *mem_ctx, 
1184                                       struct loadparm_context *lp_ctx,
1185                                       const char **endpoint_servers, struct dcesrv_context **_dce_ctx)
1186 {
1187         NTSTATUS status;
1188         struct dcesrv_context *dce_ctx;
1189         int i;
1190
1191         if (!endpoint_servers) {
1192                 DEBUG(0,("dcesrv_init_context: no endpoint servers configured\n"));
1193                 return NT_STATUS_INTERNAL_ERROR;
1194         }
1195
1196         dce_ctx = talloc(mem_ctx, struct dcesrv_context);
1197         NT_STATUS_HAVE_NO_MEMORY(dce_ctx);
1198         dce_ctx->endpoint_list  = NULL;
1199         dce_ctx->lp_ctx = lp_ctx;
1200         dce_ctx->assoc_groups_idr = idr_init(dce_ctx);
1201         NT_STATUS_HAVE_NO_MEMORY(dce_ctx->assoc_groups_idr);
1202         dce_ctx->broken_connections = NULL;
1203
1204         for (i=0;endpoint_servers[i];i++) {
1205                 const struct dcesrv_endpoint_server *ep_server;
1206
1207                 ep_server = dcesrv_ep_server_byname(endpoint_servers[i]);
1208                 if (!ep_server) {
1209                         DEBUG(0,("dcesrv_init_context: failed to find endpoint server = '%s'\n", endpoint_servers[i]));
1210                         return NT_STATUS_INTERNAL_ERROR;
1211                 }
1212
1213                 status = ep_server->init_server(dce_ctx, ep_server);
1214                 if (!NT_STATUS_IS_OK(status)) {
1215                         DEBUG(0,("dcesrv_init_context: failed to init endpoint server = '%s': %s\n", endpoint_servers[i],
1216                                 nt_errstr(status)));
1217                         return status;
1218                 }
1219         }
1220
1221         *_dce_ctx = dce_ctx;
1222         return NT_STATUS_OK;
1223 }
1224
1225 /* the list of currently registered DCERPC endpoint servers.
1226  */
1227 static struct ep_server {
1228         struct dcesrv_endpoint_server *ep_server;
1229 } *ep_servers = NULL;
1230 static int num_ep_servers;
1231
1232 /*
1233   register a DCERPC endpoint server. 
1234
1235   The 'name' can be later used by other backends to find the operations
1236   structure for this backend.  
1237
1238   The 'type' is used to specify whether this is for a disk, printer or IPC$ share
1239 */
1240 _PUBLIC_ NTSTATUS dcerpc_register_ep_server(const void *_ep_server)
1241 {
1242         const struct dcesrv_endpoint_server *ep_server = _ep_server;
1243         
1244         if (dcesrv_ep_server_byname(ep_server->name) != NULL) {
1245                 /* its already registered! */
1246                 DEBUG(0,("DCERPC endpoint server '%s' already registered\n", 
1247                          ep_server->name));
1248                 return NT_STATUS_OBJECT_NAME_COLLISION;
1249         }
1250
1251         ep_servers = realloc_p(ep_servers, struct ep_server, num_ep_servers+1);
1252         if (!ep_servers) {
1253                 smb_panic("out of memory in dcerpc_register");
1254         }
1255
1256         ep_servers[num_ep_servers].ep_server = smb_xmemdup(ep_server, sizeof(*ep_server));
1257         ep_servers[num_ep_servers].ep_server->name = smb_xstrdup(ep_server->name);
1258
1259         num_ep_servers++;
1260
1261         DEBUG(3,("DCERPC endpoint server '%s' registered\n", 
1262                  ep_server->name));
1263
1264         return NT_STATUS_OK;
1265 }
1266
1267 /*
1268   return the operations structure for a named backend of the specified type
1269 */
1270 const struct dcesrv_endpoint_server *dcesrv_ep_server_byname(const char *name)
1271 {
1272         int i;
1273
1274         for (i=0;i<num_ep_servers;i++) {
1275                 if (strcmp(ep_servers[i].ep_server->name, name) == 0) {
1276                         return ep_servers[i].ep_server;
1277                 }
1278         }
1279
1280         return NULL;
1281 }
1282
1283 void dcerpc_server_init(struct loadparm_context *lp_ctx)
1284 {
1285         static bool initialized;
1286 #define _MODULE_PROTO(init) extern NTSTATUS init(void);
1287         STATIC_dcerpc_server_MODULES_PROTO;
1288         init_module_fn static_init[] = { STATIC_dcerpc_server_MODULES };
1289         init_module_fn *shared_init;
1290
1291         if (initialized) {
1292                 return;
1293         }
1294         initialized = true;
1295
1296         shared_init = load_samba_modules(NULL, "dcerpc_server");
1297
1298         run_init_functions(static_init);
1299         run_init_functions(shared_init);
1300
1301         talloc_free(shared_init);
1302 }
1303
1304 /*
1305   return the DCERPC module version, and the size of some critical types
1306   This can be used by endpoint server modules to either detect compilation errors, or provide
1307   multiple implementations for different smbd compilation options in one module
1308 */
1309 const struct dcesrv_critical_sizes *dcerpc_module_version(void)
1310 {
1311         static const struct dcesrv_critical_sizes critical_sizes = {
1312                 DCERPC_MODULE_VERSION,
1313                 sizeof(struct dcesrv_context),
1314                 sizeof(struct dcesrv_endpoint),
1315                 sizeof(struct dcesrv_endpoint_server),
1316                 sizeof(struct dcesrv_interface),
1317                 sizeof(struct dcesrv_if_list),
1318                 sizeof(struct dcesrv_connection),
1319                 sizeof(struct dcesrv_call_state),
1320                 sizeof(struct dcesrv_auth),
1321                 sizeof(struct dcesrv_handle)
1322         };
1323
1324         return &critical_sizes;
1325 }
1326
1327 static void dcesrv_terminate_connection(struct dcesrv_connection *dce_conn, const char *reason)
1328 {
1329         struct dcesrv_context *dce_ctx = dce_conn->dce_ctx;
1330         struct stream_connection *srv_conn;
1331         srv_conn = talloc_get_type(dce_conn->transport.private_data,
1332                                    struct stream_connection);
1333
1334         if (dce_conn->pending_call_list == NULL) {
1335                 char *full_reason = talloc_asprintf(dce_conn, "dcesrv: %s", reason);
1336
1337                 DLIST_REMOVE(dce_ctx->broken_connections, dce_conn);
1338                 stream_terminate_connection(srv_conn, full_reason ? full_reason : reason);
1339                 return;
1340         }
1341
1342         if (dce_conn->terminate != NULL) {
1343                 return;
1344         }
1345
1346         DEBUG(3,("dcesrv: terminating connection due to '%s' defered due to pending calls\n",
1347                  reason));
1348         dce_conn->terminate = talloc_strdup(dce_conn, reason);
1349         if (dce_conn->terminate == NULL) {
1350                 dce_conn->terminate = "dcesrv: defered terminating connection - no memory";
1351         }
1352         DLIST_ADD_END(dce_ctx->broken_connections, dce_conn, NULL);
1353 }
1354
1355 static void dcesrv_cleanup_broken_connections(struct dcesrv_context *dce_ctx)
1356 {
1357         struct dcesrv_connection *cur, *next;
1358
1359         next = dce_ctx->broken_connections;
1360         while (next != NULL) {
1361                 cur = next;
1362                 next = cur->next;
1363
1364                 dcesrv_terminate_connection(cur, cur->terminate);
1365         }
1366 }
1367
1368 /* We need this include to be able to compile on some plateforms
1369  * (ie. freebsd 7.2) as it seems that <sys/uio.h> is not included
1370  * correctly.
1371  * It has to be that deep because otherwise we have a conflict on
1372  * const struct dcesrv_interface declaration.
1373  * This is mostly due to socket_wrapper defining #define bind swrap_bind
1374  * which conflict with the bind used before.
1375  */
1376 #include "system/network.h"
1377
1378 struct dcesrv_sock_reply_state {
1379         struct dcesrv_connection *dce_conn;
1380         struct dcesrv_call_state *call;
1381         struct iovec iov;
1382 };
1383
1384 static void dcesrv_sock_reply_done(struct tevent_req *subreq);
1385
1386 static void dcesrv_sock_report_output_data(struct dcesrv_connection *dce_conn)
1387 {
1388         struct dcesrv_call_state *call;
1389
1390         call = dce_conn->call_list;
1391         if (!call || !call->replies) {
1392                 return;
1393         }
1394
1395         while (call->replies) {
1396                 struct data_blob_list_item *rep = call->replies;
1397                 struct dcesrv_sock_reply_state *substate;
1398                 struct tevent_req *subreq;
1399
1400                 substate = talloc(call, struct dcesrv_sock_reply_state);
1401                 if (!substate) {
1402                         dcesrv_terminate_connection(dce_conn, "no memory");
1403                         return;
1404                 }
1405
1406                 substate->dce_conn = dce_conn;
1407                 substate->call = NULL;
1408
1409                 DLIST_REMOVE(call->replies, rep);
1410
1411                 if (call->replies == NULL) {
1412                         substate->call = call;
1413                 }
1414
1415                 substate->iov.iov_base = (void *) rep->blob.data;
1416                 substate->iov.iov_len = rep->blob.length;
1417
1418                 subreq = tstream_writev_queue_send(substate,
1419                                                    dce_conn->event_ctx,
1420                                                    dce_conn->stream,
1421                                                    dce_conn->send_queue,
1422                                                    &substate->iov, 1);
1423                 if (!subreq) {
1424                         dcesrv_terminate_connection(dce_conn, "no memory");
1425                         return;
1426                 }
1427                 tevent_req_set_callback(subreq, dcesrv_sock_reply_done,
1428                                         substate);
1429         }
1430
1431         DLIST_REMOVE(call->conn->call_list, call);
1432         call->list = DCESRV_LIST_NONE;
1433 }
1434
1435 static void dcesrv_sock_reply_done(struct tevent_req *subreq)
1436 {
1437         struct dcesrv_sock_reply_state *substate = tevent_req_callback_data(subreq,
1438                                                 struct dcesrv_sock_reply_state);
1439         int ret;
1440         int sys_errno;
1441         NTSTATUS status;
1442         struct dcesrv_call_state *call = substate->call;
1443
1444         ret = tstream_writev_queue_recv(subreq, &sys_errno);
1445         TALLOC_FREE(subreq);
1446         if (ret == -1) {
1447                 status = map_nt_error_from_unix_common(sys_errno);
1448                 dcesrv_terminate_connection(substate->dce_conn, nt_errstr(status));
1449                 return;
1450         }
1451
1452         talloc_free(substate);
1453         if (call) {
1454                 talloc_free(call);
1455         }
1456 }
1457
1458
1459
1460
1461 struct dcesrv_socket_context {
1462         const struct dcesrv_endpoint *endpoint;
1463         struct dcesrv_context *dcesrv_ctx;
1464 };
1465
1466
1467 static void dcesrv_read_fragment_done(struct tevent_req *subreq);
1468
1469 static void dcesrv_sock_accept(struct stream_connection *srv_conn)
1470 {
1471         NTSTATUS status;
1472         struct dcesrv_socket_context *dcesrv_sock = 
1473                 talloc_get_type(srv_conn->private_data, struct dcesrv_socket_context);
1474         enum dcerpc_transport_t transport =
1475                 dcerpc_binding_get_transport(dcesrv_sock->endpoint->ep_description);
1476         struct dcesrv_connection *dcesrv_conn = NULL;
1477         int ret;
1478         struct tevent_req *subreq;
1479         struct loadparm_context *lp_ctx = dcesrv_sock->dcesrv_ctx->lp_ctx;
1480
1481         dcesrv_cleanup_broken_connections(dcesrv_sock->dcesrv_ctx);
1482
1483         if (!srv_conn->session_info) {
1484                 status = auth_anonymous_session_info(srv_conn,
1485                                                      lp_ctx,
1486                                                      &srv_conn->session_info);
1487                 if (!NT_STATUS_IS_OK(status)) {
1488                         DEBUG(0,("dcesrv_sock_accept: auth_anonymous_session_info failed: %s\n",
1489                                 nt_errstr(status)));
1490                         stream_terminate_connection(srv_conn, nt_errstr(status));
1491                         return;
1492                 }
1493         }
1494
1495         status = dcesrv_endpoint_connect(dcesrv_sock->dcesrv_ctx,
1496                                          srv_conn,
1497                                          dcesrv_sock->endpoint,
1498                                          srv_conn->session_info,
1499                                          srv_conn->event.ctx,
1500                                          srv_conn->msg_ctx,
1501                                          srv_conn->server_id,
1502                                          DCESRV_CALL_STATE_FLAG_MAY_ASYNC,
1503                                          &dcesrv_conn);
1504         if (!NT_STATUS_IS_OK(status)) {
1505                 DEBUG(0,("dcesrv_sock_accept: dcesrv_endpoint_connect failed: %s\n", 
1506                         nt_errstr(status)));
1507                 stream_terminate_connection(srv_conn, nt_errstr(status));
1508                 return;
1509         }
1510
1511         dcesrv_conn->transport.private_data             = srv_conn;
1512         dcesrv_conn->transport.report_output_data       = dcesrv_sock_report_output_data;
1513
1514         TALLOC_FREE(srv_conn->event.fde);
1515
1516         dcesrv_conn->send_queue = tevent_queue_create(dcesrv_conn, "dcesrv send queue");
1517         if (!dcesrv_conn->send_queue) {
1518                 status = NT_STATUS_NO_MEMORY;
1519                 DEBUG(0,("dcesrv_sock_accept: tevent_queue_create(%s)\n",
1520                         nt_errstr(status)));
1521                 stream_terminate_connection(srv_conn, nt_errstr(status));
1522                 return;
1523         }
1524
1525         if (transport == NCACN_NP) {
1526                 dcesrv_conn->auth_state.session_key = dcesrv_inherited_session_key;
1527                 dcesrv_conn->stream = talloc_move(dcesrv_conn,
1528                                                   &srv_conn->tstream);
1529         } else {
1530                 ret = tstream_bsd_existing_socket(dcesrv_conn,
1531                                                   socket_get_fd(srv_conn->socket),
1532                                                   &dcesrv_conn->stream);
1533                 if (ret == -1) {
1534                         status = map_nt_error_from_unix_common(errno);
1535                         DEBUG(0, ("dcesrv_sock_accept: "
1536                                   "failed to setup tstream: %s\n",
1537                                   nt_errstr(status)));
1538                         stream_terminate_connection(srv_conn, nt_errstr(status));
1539                         return;
1540                 }
1541                 socket_set_flags(srv_conn->socket, SOCKET_FLAG_NOCLOSE);
1542         }
1543
1544         dcesrv_conn->local_address = srv_conn->local_address;
1545         dcesrv_conn->remote_address = srv_conn->remote_address;
1546
1547         srv_conn->private_data = dcesrv_conn;
1548
1549         irpc_add_name(srv_conn->msg_ctx, "rpc_server");
1550
1551         subreq = dcerpc_read_ncacn_packet_send(dcesrv_conn,
1552                                                dcesrv_conn->event_ctx,
1553                                                dcesrv_conn->stream);
1554         if (!subreq) {
1555                 status = NT_STATUS_NO_MEMORY;
1556                 DEBUG(0,("dcesrv_sock_accept: dcerpc_read_fragment_buffer_send(%s)\n",
1557                         nt_errstr(status)));
1558                 stream_terminate_connection(srv_conn, nt_errstr(status));
1559                 return;
1560         }
1561         tevent_req_set_callback(subreq, dcesrv_read_fragment_done, dcesrv_conn);
1562
1563         return;
1564 }
1565
1566 static void dcesrv_read_fragment_done(struct tevent_req *subreq)
1567 {
1568         struct dcesrv_connection *dce_conn = tevent_req_callback_data(subreq,
1569                                              struct dcesrv_connection);
1570         struct dcesrv_context *dce_ctx = dce_conn->dce_ctx;
1571         struct ncacn_packet *pkt;
1572         DATA_BLOB buffer;
1573         NTSTATUS status;
1574
1575         if (dce_conn->terminate) {
1576                 /*
1577                  * if the current connection is broken
1578                  * we need to clean it up before any other connection
1579                  */
1580                 dcesrv_terminate_connection(dce_conn, dce_conn->terminate);
1581                 dcesrv_cleanup_broken_connections(dce_ctx);
1582                 return;
1583         }
1584
1585         dcesrv_cleanup_broken_connections(dce_ctx);
1586
1587         status = dcerpc_read_ncacn_packet_recv(subreq, dce_conn,
1588                                                &pkt, &buffer);
1589         TALLOC_FREE(subreq);
1590         if (!NT_STATUS_IS_OK(status)) {
1591                 dcesrv_terminate_connection(dce_conn, nt_errstr(status));
1592                 return;
1593         }
1594
1595         status = dcesrv_process_ncacn_packet(dce_conn, pkt, buffer);
1596         if (!NT_STATUS_IS_OK(status)) {
1597                 dcesrv_terminate_connection(dce_conn, nt_errstr(status));
1598                 return;
1599         }
1600
1601         subreq = dcerpc_read_ncacn_packet_send(dce_conn,
1602                                                dce_conn->event_ctx,
1603                                                dce_conn->stream);
1604         if (!subreq) {
1605                 status = NT_STATUS_NO_MEMORY;
1606                 dcesrv_terminate_connection(dce_conn, nt_errstr(status));
1607                 return;
1608         }
1609         tevent_req_set_callback(subreq, dcesrv_read_fragment_done, dce_conn);
1610 }
1611
1612 static void dcesrv_sock_recv(struct stream_connection *conn, uint16_t flags)
1613 {
1614         struct dcesrv_connection *dce_conn = talloc_get_type(conn->private_data,
1615                                              struct dcesrv_connection);
1616         dcesrv_terminate_connection(dce_conn, "dcesrv_sock_recv triggered");
1617 }
1618
1619 static void dcesrv_sock_send(struct stream_connection *conn, uint16_t flags)
1620 {
1621         struct dcesrv_connection *dce_conn = talloc_get_type(conn->private_data,
1622                                              struct dcesrv_connection);
1623         dcesrv_terminate_connection(dce_conn, "dcesrv_sock_send triggered");
1624 }
1625
1626
1627 static const struct stream_server_ops dcesrv_stream_ops = {
1628         .name                   = "rpc",
1629         .accept_connection      = dcesrv_sock_accept,
1630         .recv_handler           = dcesrv_sock_recv,
1631         .send_handler           = dcesrv_sock_send,
1632 };
1633
1634 static NTSTATUS dcesrv_add_ep_unix(struct dcesrv_context *dce_ctx, 
1635                                    struct loadparm_context *lp_ctx,
1636                                    struct dcesrv_endpoint *e,
1637                             struct tevent_context *event_ctx, const struct model_ops *model_ops)
1638 {
1639         struct dcesrv_socket_context *dcesrv_sock;
1640         uint16_t port = 1;
1641         NTSTATUS status;
1642         const char *endpoint;
1643
1644         dcesrv_sock = talloc(event_ctx, struct dcesrv_socket_context);
1645         NT_STATUS_HAVE_NO_MEMORY(dcesrv_sock);
1646
1647         /* remember the endpoint of this socket */
1648         dcesrv_sock->endpoint           = e;
1649         dcesrv_sock->dcesrv_ctx         = talloc_reference(dcesrv_sock, dce_ctx);
1650
1651         endpoint = dcerpc_binding_get_string_option(e->ep_description, "endpoint");
1652
1653         status = stream_setup_socket(dcesrv_sock, event_ctx, lp_ctx,
1654                                      model_ops, &dcesrv_stream_ops, 
1655                                      "unix", endpoint, &port,
1656                                      lpcfg_socket_options(lp_ctx),
1657                                      dcesrv_sock);
1658         if (!NT_STATUS_IS_OK(status)) {
1659                 DEBUG(0,("service_setup_stream_socket(path=%s) failed - %s\n",
1660                          endpoint, nt_errstr(status)));
1661         }
1662
1663         return status;
1664 }
1665
1666 static NTSTATUS dcesrv_add_ep_ncalrpc(struct dcesrv_context *dce_ctx, 
1667                                       struct loadparm_context *lp_ctx,
1668                                       struct dcesrv_endpoint *e,
1669                                       struct tevent_context *event_ctx, const struct model_ops *model_ops)
1670 {
1671         struct dcesrv_socket_context *dcesrv_sock;
1672         uint16_t port = 1;
1673         char *full_path;
1674         NTSTATUS status;
1675         const char *endpoint;
1676
1677         endpoint = dcerpc_binding_get_string_option(e->ep_description, "endpoint");
1678
1679         if (endpoint == NULL) {
1680                 /*
1681                  * No identifier specified: use DEFAULT.
1682                  *
1683                  * TODO: DO NOT hardcode this value anywhere else. Rather, specify
1684                  * no endpoint and let the epmapper worry about it.
1685                  */
1686                 endpoint = "DEFAULT";
1687                 status = dcerpc_binding_set_string_option(e->ep_description,
1688                                                           "endpoint",
1689                                                           endpoint);
1690                 if (!NT_STATUS_IS_OK(status)) {
1691                         DEBUG(0,("dcerpc_binding_set_string_option() failed - %s\n",
1692                                   nt_errstr(status)));
1693                         return status;
1694                 }
1695         }
1696
1697         full_path = talloc_asprintf(dce_ctx, "%s/%s", lpcfg_ncalrpc_dir(lp_ctx),
1698                                     endpoint);
1699
1700         dcesrv_sock = talloc(event_ctx, struct dcesrv_socket_context);
1701         NT_STATUS_HAVE_NO_MEMORY(dcesrv_sock);
1702
1703         /* remember the endpoint of this socket */
1704         dcesrv_sock->endpoint           = e;
1705         dcesrv_sock->dcesrv_ctx         = talloc_reference(dcesrv_sock, dce_ctx);
1706
1707         status = stream_setup_socket(dcesrv_sock, event_ctx, lp_ctx,
1708                                      model_ops, &dcesrv_stream_ops, 
1709                                      "unix", full_path, &port, 
1710                                      lpcfg_socket_options(lp_ctx),
1711                                      dcesrv_sock);
1712         if (!NT_STATUS_IS_OK(status)) {
1713                 DEBUG(0,("service_setup_stream_socket(identifier=%s,path=%s) failed - %s\n",
1714                          endpoint, full_path, nt_errstr(status)));
1715         }
1716         return status;
1717 }
1718
1719 static NTSTATUS dcesrv_add_ep_np(struct dcesrv_context *dce_ctx,
1720                                  struct loadparm_context *lp_ctx,
1721                                  struct dcesrv_endpoint *e,
1722                                  struct tevent_context *event_ctx, const struct model_ops *model_ops)
1723 {
1724         struct dcesrv_socket_context *dcesrv_sock;
1725         NTSTATUS status;
1726         const char *endpoint;
1727
1728         endpoint = dcerpc_binding_get_string_option(e->ep_description, "endpoint");
1729         if (endpoint == NULL) {
1730                 DEBUG(0, ("Endpoint mandatory for named pipes\n"));
1731                 return NT_STATUS_INVALID_PARAMETER;
1732         }
1733
1734         dcesrv_sock = talloc(event_ctx, struct dcesrv_socket_context);
1735         NT_STATUS_HAVE_NO_MEMORY(dcesrv_sock);
1736
1737         /* remember the endpoint of this socket */
1738         dcesrv_sock->endpoint           = e;
1739         dcesrv_sock->dcesrv_ctx         = talloc_reference(dcesrv_sock, dce_ctx);
1740
1741         status = tstream_setup_named_pipe(dce_ctx, event_ctx, lp_ctx,
1742                                           model_ops, &dcesrv_stream_ops,
1743                                           endpoint,
1744                                           dcesrv_sock);
1745         if (!NT_STATUS_IS_OK(status)) {
1746                 DEBUG(0,("stream_setup_named_pipe(pipe=%s) failed - %s\n",
1747                          endpoint, nt_errstr(status)));
1748                 return status;
1749         }
1750
1751         return NT_STATUS_OK;
1752 }
1753
1754 /*
1755   add a socket address to the list of events, one event per dcerpc endpoint
1756 */
1757 static NTSTATUS add_socket_rpc_tcp_iface(struct dcesrv_context *dce_ctx, struct dcesrv_endpoint *e,
1758                                          struct tevent_context *event_ctx, const struct model_ops *model_ops,
1759                                          const char *address)
1760 {
1761         struct dcesrv_socket_context *dcesrv_sock;
1762         uint16_t port = 0;
1763         NTSTATUS status;
1764         const char *endpoint;
1765         char port_str[6];
1766
1767         endpoint = dcerpc_binding_get_string_option(e->ep_description, "endpoint");
1768         if (endpoint != NULL) {
1769                 port = atoi(endpoint);
1770         }
1771
1772         dcesrv_sock = talloc(event_ctx, struct dcesrv_socket_context);
1773         NT_STATUS_HAVE_NO_MEMORY(dcesrv_sock);
1774
1775         /* remember the endpoint of this socket */
1776         dcesrv_sock->endpoint           = e;
1777         dcesrv_sock->dcesrv_ctx         = talloc_reference(dcesrv_sock, dce_ctx);
1778
1779         status = stream_setup_socket(dcesrv_sock, event_ctx, dce_ctx->lp_ctx,
1780                                      model_ops, &dcesrv_stream_ops, 
1781                                      "ip", address, &port,
1782                                      lpcfg_socket_options(dce_ctx->lp_ctx),
1783                                      dcesrv_sock);
1784         if (!NT_STATUS_IS_OK(status)) {
1785                 DEBUG(0,("service_setup_stream_socket(address=%s,port=%u) failed - %s\n", 
1786                          address, port, nt_errstr(status)));
1787                 return status;
1788         }
1789
1790         snprintf(port_str, sizeof(port_str), "%u", port);
1791
1792         status = dcerpc_binding_set_string_option(e->ep_description,
1793                                                   "endpoint", port_str);
1794         if (!NT_STATUS_IS_OK(status)) {
1795                 DEBUG(0,("dcerpc_binding_set_string_option(endpoint, %s) failed - %s\n",
1796                          port_str, nt_errstr(status)));
1797                 return status;
1798         }
1799
1800         return NT_STATUS_OK;
1801 }
1802
1803 #include "lib/socket/netif.h" /* Included here to work around the fact that socket_wrapper redefines bind() */
1804
1805 static NTSTATUS dcesrv_add_ep_tcp(struct dcesrv_context *dce_ctx, 
1806                                   struct loadparm_context *lp_ctx,
1807                                   struct dcesrv_endpoint *e,
1808                                   struct tevent_context *event_ctx, const struct model_ops *model_ops)
1809 {
1810         NTSTATUS status;
1811
1812         /* Add TCP/IP sockets */
1813         if (lpcfg_interfaces(lp_ctx) && lpcfg_bind_interfaces_only(lp_ctx)) {
1814                 int num_interfaces;
1815                 int i;
1816                 struct interface *ifaces;
1817
1818                 load_interface_list(dce_ctx, lp_ctx, &ifaces);
1819
1820                 num_interfaces = iface_list_count(ifaces);
1821                 for(i = 0; i < num_interfaces; i++) {
1822                         const char *address = iface_list_n_ip(ifaces, i);
1823                         status = add_socket_rpc_tcp_iface(dce_ctx, e, event_ctx, model_ops, address);
1824                         NT_STATUS_NOT_OK_RETURN(status);
1825                 }
1826         } else {
1827                 const char **wcard;
1828                 int i;
1829                 wcard = iface_list_wildcard(dce_ctx, lp_ctx);
1830                 NT_STATUS_HAVE_NO_MEMORY(wcard);
1831                 for (i=0; wcard[i]; i++) {
1832                         status = add_socket_rpc_tcp_iface(dce_ctx, e, event_ctx, model_ops, wcard[i]);
1833                         NT_STATUS_NOT_OK_RETURN(status);
1834                 }
1835                 talloc_free(wcard);
1836         }
1837
1838         return NT_STATUS_OK;
1839 }
1840
1841 NTSTATUS dcesrv_add_ep(struct dcesrv_context *dce_ctx,
1842                        struct loadparm_context *lp_ctx,
1843                        struct dcesrv_endpoint *e,
1844                        struct tevent_context *event_ctx,
1845                        const struct model_ops *model_ops)
1846 {
1847         enum dcerpc_transport_t transport =
1848                 dcerpc_binding_get_transport(e->ep_description);
1849
1850         switch (transport) {
1851         case NCACN_UNIX_STREAM:
1852                 return dcesrv_add_ep_unix(dce_ctx, lp_ctx, e, event_ctx, model_ops);
1853
1854         case NCALRPC:
1855                 return dcesrv_add_ep_ncalrpc(dce_ctx, lp_ctx, e, event_ctx, model_ops);
1856
1857         case NCACN_IP_TCP:
1858                 return dcesrv_add_ep_tcp(dce_ctx, lp_ctx, e, event_ctx, model_ops);
1859
1860         case NCACN_NP:
1861                 return dcesrv_add_ep_np(dce_ctx, lp_ctx, e, event_ctx, model_ops);
1862
1863         default:
1864                 return NT_STATUS_NOT_SUPPORTED;
1865         }
1866 }
1867
1868
1869 /**
1870  * retrieve credentials from a dce_call
1871  */
1872 _PUBLIC_ struct cli_credentials *dcesrv_call_credentials(struct dcesrv_call_state *dce_call)
1873 {
1874         return dce_call->conn->auth_state.session_info->credentials;
1875 }
1876
1877 /**
1878  * returns true if this is an authenticated call
1879  */
1880 _PUBLIC_ bool dcesrv_call_authenticated(struct dcesrv_call_state *dce_call)
1881 {
1882         enum security_user_level level;
1883         level = security_session_user_level(dce_call->conn->auth_state.session_info, NULL);
1884         return level >= SECURITY_USER;
1885 }
1886
1887 /**
1888  * retrieve account_name for a dce_call
1889  */
1890 _PUBLIC_ const char *dcesrv_call_account_name(struct dcesrv_call_state *dce_call)
1891 {
1892         return dce_call->context->conn->auth_state.session_info->info->account_name;
1893 }