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