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