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