96cac6e1a9bf43d091426711fed6950c572d58c2
[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 extern const struct dcesrv_interface dcesrv_mgmt_interface;
46
47 static NTSTATUS dcesrv_alter_resp(struct dcesrv_call_state *call,
48                                 uint32_t result,
49                                 uint32_t reason);
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(2,(__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                                                              uint16_t context_id)
176 {
177         struct dcesrv_connection_context *c;
178         for (c=conn->contexts;c;c=c->next) {
179                 if (c->context_id == context_id) return c;
180         }
181         return NULL;
182 }
183
184 /*
185   see if a uuid and if_version match to an interface
186 */
187 static bool interface_match(const struct dcesrv_interface *if1,
188                                                         const struct dcesrv_interface *if2)
189 {
190         return (if1->syntax_id.if_version == if2->syntax_id.if_version && 
191                         GUID_equal(&if1->syntax_id.uuid, &if2->syntax_id.uuid));
192 }
193
194 /*
195   find the interface operations on an endpoint
196 */
197 static const struct dcesrv_interface *find_interface(const struct dcesrv_endpoint *endpoint,
198                                                      const struct dcesrv_interface *iface)
199 {
200         struct dcesrv_if_list *ifl;
201         for (ifl=endpoint->interface_list; ifl; ifl=ifl->next) {
202                 if (interface_match(&(ifl->iface), iface)) {
203                         return &(ifl->iface);
204                 }
205         }
206         return NULL;
207 }
208
209 /*
210   see if a uuid and if_version match to an interface
211 */
212 static bool interface_match_by_uuid(const struct dcesrv_interface *iface,
213                                     const struct GUID *uuid, uint32_t if_version)
214 {
215         return (iface->syntax_id.if_version == if_version && 
216                         GUID_equal(&iface->syntax_id.uuid, uuid));
217 }
218
219 /*
220   find the interface operations on an endpoint by uuid
221 */
222 static const struct dcesrv_interface *find_interface_by_uuid(const struct dcesrv_endpoint *endpoint,
223                                                              const struct GUID *uuid, uint32_t if_version)
224 {
225         struct dcesrv_if_list *ifl;
226         for (ifl=endpoint->interface_list; ifl; ifl=ifl->next) {
227                 if (interface_match_by_uuid(&(ifl->iface), uuid, if_version)) {
228                         return &(ifl->iface);
229                 }
230         }
231         return NULL;
232 }
233
234 /*
235   find the earlier parts of a fragmented call awaiting reassembily
236 */
237 static struct dcesrv_call_state *dcesrv_find_fragmented_call(struct dcesrv_connection *dce_conn, uint16_t call_id)
238 {
239         struct dcesrv_call_state *c;
240         for (c=dce_conn->incoming_fragmented_call_list;c;c=c->next) {
241                 if (c->pkt.call_id == call_id) {
242                         return c;
243                 }
244         }
245         return NULL;
246 }
247
248 /*
249   register an interface on an endpoint
250 */
251 _PUBLIC_ NTSTATUS dcesrv_interface_register(struct dcesrv_context *dce_ctx,
252                                    const char *ep_name,
253                                    const struct dcesrv_interface *iface,
254                                    const struct security_descriptor *sd)
255 {
256         struct dcesrv_endpoint *ep;
257         struct dcesrv_if_list *ifl;
258         struct dcerpc_binding *binding;
259         bool add_ep = false;
260         NTSTATUS status;
261         
262         status = dcerpc_parse_binding(dce_ctx, ep_name, &binding);
263
264         if (NT_STATUS_IS_ERR(status)) {
265                 DEBUG(0, ("Trouble parsing binding string '%s'\n", ep_name));
266                 return status;
267         }
268
269         /* check if this endpoint exists
270          */
271         if ((ep=find_endpoint(dce_ctx, binding))==NULL) {
272                 ep = talloc_zero(dce_ctx, struct dcesrv_endpoint);
273                 if (!ep) {
274                         return NT_STATUS_NO_MEMORY;
275                 }
276                 ZERO_STRUCTP(ep);
277                 ep->ep_description = talloc_move(ep, &binding);
278                 add_ep = true;
279
280                 /* add mgmt interface */
281                 ifl = talloc_zero(ep, struct dcesrv_if_list);
282                 if (!ifl) {
283                         return NT_STATUS_NO_MEMORY;
284                 }
285
286                 memcpy(&(ifl->iface), &dcesrv_mgmt_interface, 
287                            sizeof(struct dcesrv_interface));
288
289                 DLIST_ADD(ep->interface_list, ifl);
290         }
291
292         /* see if the interface is already registered on te endpoint */
293         if (find_interface(ep, iface)!=NULL) {
294                 DEBUG(0,("dcesrv_interface_register: interface '%s' already registered on endpoint '%s'\n",
295                         iface->name, ep_name));
296                 return NT_STATUS_OBJECT_NAME_COLLISION;
297         }
298
299         /* talloc a new interface list element */
300         ifl = talloc_zero(ep, struct dcesrv_if_list);
301         if (!ifl) {
302                 return NT_STATUS_NO_MEMORY;
303         }
304
305         /* copy the given interface struct to the one on the endpoints interface list */
306         memcpy(&(ifl->iface),iface, sizeof(struct dcesrv_interface));
307
308         /* if we have a security descriptor given,
309          * we should see if we can set it up on the endpoint
310          */
311         if (sd != NULL) {
312                 /* if there's currently no security descriptor given on the endpoint
313                  * we try to set it
314                  */
315                 if (ep->sd == NULL) {
316                         ep->sd = security_descriptor_copy(ep, sd);
317                 }
318
319                 /* if now there's no security descriptor given on the endpoint
320                  * something goes wrong, either we failed to copy the security descriptor
321                  * or there was already one on the endpoint
322                  */
323                 if (ep->sd != NULL) {
324                         DEBUG(0,("dcesrv_interface_register: interface '%s' failed to setup a security descriptor\n"
325                                  "                           on endpoint '%s'\n",
326                                 iface->name, ep_name));
327                         if (add_ep) free(ep);
328                         free(ifl);
329                         return NT_STATUS_OBJECT_NAME_COLLISION;
330                 }
331         }
332
333         /* finally add the interface on the endpoint */
334         DLIST_ADD(ep->interface_list, ifl);
335
336         /* if it's a new endpoint add it to the dcesrv_context */
337         if (add_ep) {
338                 DLIST_ADD(dce_ctx->endpoint_list, ep);
339         }
340
341         DEBUG(4,("dcesrv_interface_register: interface '%s' registered on endpoint '%s'\n",
342                 iface->name, ep_name));
343
344         return NT_STATUS_OK;
345 }
346
347 NTSTATUS dcesrv_inherited_session_key(struct dcesrv_connection *p,
348                                       DATA_BLOB *session_key)
349 {
350         if (p->auth_state.session_info->session_key.length) {
351                 *session_key = p->auth_state.session_info->session_key;
352                 return NT_STATUS_OK;
353         }
354         return NT_STATUS_NO_USER_SESSION_KEY;
355 }
356
357 /*
358   fetch the user session key - may be default (above) or the SMB session key
359
360   The key is always truncated to 16 bytes 
361 */
362 _PUBLIC_ NTSTATUS dcesrv_fetch_session_key(struct dcesrv_connection *p,
363                                   DATA_BLOB *session_key)
364 {
365         NTSTATUS status = p->auth_state.session_key(p, session_key);
366         if (!NT_STATUS_IS_OK(status)) {
367                 return status;
368         }
369
370         session_key->length = MIN(session_key->length, 16);
371
372         return NT_STATUS_OK;
373 }
374
375 /*
376   connect to a dcerpc endpoint
377 */
378 _PUBLIC_ NTSTATUS dcesrv_endpoint_connect(struct dcesrv_context *dce_ctx,
379                                  TALLOC_CTX *mem_ctx,
380                                  const struct dcesrv_endpoint *ep,
381                                  struct auth_session_info *session_info,
382                                  struct tevent_context *event_ctx,
383                                  struct imessaging_context *msg_ctx,
384                                  struct server_id server_id,
385                                  uint32_t state_flags,
386                                  struct dcesrv_connection **_p)
387 {
388         struct dcesrv_connection *p;
389
390         if (!session_info) {
391                 return NT_STATUS_ACCESS_DENIED;
392         }
393
394         p = talloc_zero(mem_ctx, struct dcesrv_connection);
395         NT_STATUS_HAVE_NO_MEMORY(p);
396
397         if (!talloc_reference(p, session_info)) {
398                 talloc_free(p);
399                 return NT_STATUS_NO_MEMORY;
400         }
401
402         p->dce_ctx = dce_ctx;
403         p->endpoint = ep;
404         p->packet_log_dir = lpcfg_lock_directory(dce_ctx->lp_ctx);
405         p->auth_state.session_info = session_info;
406         p->auth_state.session_key = dcesrv_generic_session_key;
407         p->event_ctx = event_ctx;
408         p->msg_ctx = msg_ctx;
409         p->server_id = server_id;
410         p->state_flags = state_flags;
411         p->allow_bind = true;
412         p->max_recv_frag = 5840;
413         p->max_xmit_frag = 5840;
414         p->max_total_request_size = DCERPC_NCACN_REQUEST_DEFAULT_MAX_SIZE;
415
416         *_p = p;
417         return NT_STATUS_OK;
418 }
419
420 /*
421   move a call from an existing linked list to the specified list. This
422   prevents bugs where we forget to remove the call from a previous
423   list when moving it.
424  */
425 static void dcesrv_call_set_list(struct dcesrv_call_state *call, 
426                                  enum dcesrv_call_list list)
427 {
428         switch (call->list) {
429         case DCESRV_LIST_NONE:
430                 break;
431         case DCESRV_LIST_CALL_LIST:
432                 DLIST_REMOVE(call->conn->call_list, call);
433                 break;
434         case DCESRV_LIST_FRAGMENTED_CALL_LIST:
435                 DLIST_REMOVE(call->conn->incoming_fragmented_call_list, call);
436                 break;
437         case DCESRV_LIST_PENDING_CALL_LIST:
438                 DLIST_REMOVE(call->conn->pending_call_list, call);
439                 break;
440         }
441         call->list = list;
442         switch (list) {
443         case DCESRV_LIST_NONE:
444                 break;
445         case DCESRV_LIST_CALL_LIST:
446                 DLIST_ADD_END(call->conn->call_list, call);
447                 break;
448         case DCESRV_LIST_FRAGMENTED_CALL_LIST:
449                 DLIST_ADD_END(call->conn->incoming_fragmented_call_list, call);
450                 break;
451         case DCESRV_LIST_PENDING_CALL_LIST:
452                 DLIST_ADD_END(call->conn->pending_call_list, call);
453                 break;
454         }
455 }
456
457 static void dcesrv_call_disconnect_after(struct dcesrv_call_state *call,
458                                          const char *reason)
459 {
460         if (call->conn->terminate != NULL) {
461                 return;
462         }
463
464         call->conn->allow_bind = false;
465         call->conn->allow_alter = false;
466         call->conn->allow_auth3 = false;
467         call->conn->allow_request = false;
468
469         call->terminate_reason = talloc_strdup(call, reason);
470         if (call->terminate_reason == NULL) {
471                 call->terminate_reason = __location__;
472         }
473 }
474
475 /*
476   return a dcerpc bind_nak
477 */
478 static NTSTATUS dcesrv_bind_nak(struct dcesrv_call_state *call, uint32_t reason)
479 {
480         struct ncacn_packet pkt;
481         struct dcerpc_bind_nak_version version;
482         struct data_blob_list_item *rep;
483         NTSTATUS status;
484         static const uint8_t _pad[3] = { 0, };
485
486         /*
487          * We add the call to the pending_call_list
488          * in order to defer the termination.
489          */
490         dcesrv_call_disconnect_after(call, "dcesrv_bind_nak");
491
492         /* setup a bind_nak */
493         dcesrv_init_hdr(&pkt, lpcfg_rpc_big_endian(call->conn->dce_ctx->lp_ctx));
494         pkt.auth_length = 0;
495         pkt.call_id = call->pkt.call_id;
496         pkt.ptype = DCERPC_PKT_BIND_NAK;
497         pkt.pfc_flags = DCERPC_PFC_FLAG_FIRST | DCERPC_PFC_FLAG_LAST;
498         pkt.u.bind_nak.reject_reason = reason;
499         version.rpc_vers = 5;
500         version.rpc_vers_minor = 0;
501         pkt.u.bind_nak.num_versions = 1;
502         pkt.u.bind_nak.versions = &version;
503         pkt.u.bind_nak._pad = data_blob_const(_pad, sizeof(_pad));
504
505         rep = talloc_zero(call, struct data_blob_list_item);
506         if (!rep) {
507                 return NT_STATUS_NO_MEMORY;
508         }
509
510         status = ncacn_push_auth(&rep->blob, call, &pkt, NULL);
511         if (!NT_STATUS_IS_OK(status)) {
512                 return status;
513         }
514
515         dcerpc_set_frag_length(&rep->blob, rep->blob.length);
516
517         DLIST_ADD_END(call->replies, rep);
518         dcesrv_call_set_list(call, DCESRV_LIST_CALL_LIST);
519
520         if (call->conn->call_list && call->conn->call_list->replies) {
521                 if (call->conn->transport.report_output_data) {
522                         call->conn->transport.report_output_data(call->conn);
523                 }
524         }
525
526         return NT_STATUS_OK;    
527 }
528
529 static NTSTATUS dcesrv_fault_disconnect(struct dcesrv_call_state *call,
530                                  uint32_t fault_code)
531 {
532         /*
533          * We add the call to the pending_call_list
534          * in order to defer the termination.
535          */
536         dcesrv_call_disconnect_after(call, "dcesrv_fault_disconnect");
537
538         return dcesrv_fault_with_flags(call, fault_code,
539                                        DCERPC_PFC_FLAG_DID_NOT_EXECUTE);
540 }
541
542 static int dcesrv_connection_context_destructor(struct dcesrv_connection_context *c)
543 {
544         DLIST_REMOVE(c->conn->contexts, c);
545
546         if (c->iface && c->iface->unbind) {
547                 c->iface->unbind(c, c->iface);
548                 c->iface = NULL;
549         }
550
551         return 0;
552 }
553
554 static void dcesrv_prepare_context_auth(struct dcesrv_call_state *dce_call)
555 {
556         struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
557         const struct dcesrv_endpoint *endpoint = dce_call->conn->endpoint;
558         enum dcerpc_transport_t transport =
559                 dcerpc_binding_get_transport(endpoint->ep_description);
560         struct dcesrv_connection_context *context = dce_call->context;
561         const struct dcesrv_interface *iface = context->iface;
562
563         context->min_auth_level = DCERPC_AUTH_LEVEL_NONE;
564
565         if (transport == NCALRPC) {
566                 context->allow_connect = true;
567                 return;
568         }
569
570         /*
571          * allow overwrite per interface
572          * allow dcerpc auth level connect:<interface>
573          */
574         context->allow_connect = lpcfg_allow_dcerpc_auth_level_connect(lp_ctx);
575         context->allow_connect = lpcfg_parm_bool(lp_ctx, NULL,
576                                         "allow dcerpc auth level connect",
577                                         iface->name,
578                                         context->allow_connect);
579 }
580
581 NTSTATUS dcesrv_interface_bind_require_integrity(struct dcesrv_call_state *dce_call,
582                                                  const struct dcesrv_interface *iface)
583 {
584         if (dce_call->context == NULL) {
585                 return NT_STATUS_INTERNAL_ERROR;
586         }
587
588         /*
589          * For connection oriented DCERPC DCERPC_AUTH_LEVEL_PACKET (4)
590          * has the same behavior as DCERPC_AUTH_LEVEL_INTEGRITY (5).
591          */
592         dce_call->context->min_auth_level = DCERPC_AUTH_LEVEL_PACKET;
593         return NT_STATUS_OK;
594 }
595
596 NTSTATUS dcesrv_interface_bind_require_privacy(struct dcesrv_call_state *dce_call,
597                                                const struct dcesrv_interface *iface)
598 {
599         if (dce_call->context == NULL) {
600                 return NT_STATUS_INTERNAL_ERROR;
601         }
602
603         dce_call->context->min_auth_level = DCERPC_AUTH_LEVEL_PRIVACY;
604         return NT_STATUS_OK;
605 }
606
607 _PUBLIC_ NTSTATUS dcesrv_interface_bind_reject_connect(struct dcesrv_call_state *dce_call,
608                                                        const struct dcesrv_interface *iface)
609 {
610         struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
611         const struct dcesrv_endpoint *endpoint = dce_call->conn->endpoint;
612         enum dcerpc_transport_t transport =
613                 dcerpc_binding_get_transport(endpoint->ep_description);
614         struct dcesrv_connection_context *context = dce_call->context;
615
616         if (context == NULL) {
617                 return NT_STATUS_INTERNAL_ERROR;
618         }
619
620         if (transport == NCALRPC) {
621                 context->allow_connect = true;
622                 return NT_STATUS_OK;
623         }
624
625         /*
626          * allow overwrite per interface
627          * allow dcerpc auth level connect:<interface>
628          */
629         context->allow_connect = false;
630         context->allow_connect = lpcfg_parm_bool(lp_ctx, NULL,
631                                         "allow dcerpc auth level connect",
632                                         iface->name,
633                                         context->allow_connect);
634         return NT_STATUS_OK;
635 }
636
637 _PUBLIC_ NTSTATUS dcesrv_interface_bind_allow_connect(struct dcesrv_call_state *dce_call,
638                                                       const struct dcesrv_interface *iface)
639 {
640         struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
641         const struct dcesrv_endpoint *endpoint = dce_call->conn->endpoint;
642         enum dcerpc_transport_t transport =
643                 dcerpc_binding_get_transport(endpoint->ep_description);
644         struct dcesrv_connection_context *context = dce_call->context;
645
646         if (context == NULL) {
647                 return NT_STATUS_INTERNAL_ERROR;
648         }
649
650         if (transport == NCALRPC) {
651                 context->allow_connect = true;
652                 return NT_STATUS_OK;
653         }
654
655         /*
656          * allow overwrite per interface
657          * allow dcerpc auth level connect:<interface>
658          */
659         context->allow_connect = true;
660         context->allow_connect = lpcfg_parm_bool(lp_ctx, NULL,
661                                         "allow dcerpc auth level connect",
662                                         iface->name,
663                                         context->allow_connect);
664         return NT_STATUS_OK;
665 }
666
667 /*
668   handle a bind request
669 */
670 static NTSTATUS dcesrv_bind(struct dcesrv_call_state *call)
671 {
672         uint32_t if_version, transfer_syntax_version;
673         struct GUID uuid, *transfer_syntax_uuid;
674         struct ncacn_packet pkt;
675         struct data_blob_list_item *rep;
676         NTSTATUS status;
677         uint32_t result=0, reason=0;
678         uint16_t context_id;
679         const struct dcesrv_interface *iface;
680         uint32_t extra_flags = 0;
681         uint16_t max_req = 0;
682         uint16_t max_rep = 0;
683         const char *ep_prefix = "";
684         const char *endpoint = NULL;
685
686         status = dcerpc_verify_ncacn_packet_header(&call->pkt,
687                         DCERPC_PKT_BIND,
688                         call->pkt.u.bind.auth_info.length,
689                         0, /* required flags */
690                         DCERPC_PFC_FLAG_FIRST |
691                         DCERPC_PFC_FLAG_LAST |
692                         DCERPC_PFC_FLAG_SUPPORT_HEADER_SIGN |
693                         0x08 | /* this is not defined, but should be ignored */
694                         DCERPC_PFC_FLAG_CONC_MPX |
695                         DCERPC_PFC_FLAG_DID_NOT_EXECUTE |
696                         DCERPC_PFC_FLAG_MAYBE |
697                         DCERPC_PFC_FLAG_OBJECT_UUID);
698         if (!NT_STATUS_IS_OK(status)) {
699                 return dcesrv_bind_nak(call,
700                         DCERPC_BIND_NAK_REASON_PROTOCOL_VERSION_NOT_SUPPORTED);
701         }
702
703         /* max_recv_frag and max_xmit_frag result always in the same value! */
704         max_req = MIN(call->pkt.u.bind.max_xmit_frag,
705                       call->pkt.u.bind.max_recv_frag);
706         /*
707          * The values are between 2048 and 5840 tested against Windows 2012R2
708          * via ncacn_ip_tcp on port 135.
709          */
710         max_req = MAX(2048, max_req);
711         max_rep = MIN(max_req, call->conn->max_recv_frag);
712         /* They are truncated to an 8 byte boundary. */
713         max_rep &= 0xFFF8;
714
715         /* max_recv_frag and max_xmit_frag result always in the same value! */
716         call->conn->max_recv_frag = max_rep;
717         call->conn->max_xmit_frag = max_rep;
718
719         /*
720           if provided, check the assoc_group is valid
721          */
722         if (call->pkt.u.bind.assoc_group_id != 0) {
723                 call->conn->assoc_group = dcesrv_assoc_group_reference(call->conn,
724                                                                        call->conn->dce_ctx,
725                                                                        call->pkt.u.bind.assoc_group_id);
726         } else {
727                 call->conn->assoc_group = dcesrv_assoc_group_new(call->conn,
728                                                                  call->conn->dce_ctx);
729         }
730         if (call->conn->assoc_group == NULL) {
731                 return dcesrv_bind_nak(call, 0);
732         }
733
734         if (call->pkt.u.bind.num_contexts < 1 ||
735             call->pkt.u.bind.ctx_list[0].num_transfer_syntaxes < 1) {
736                 return dcesrv_bind_nak(call, 0);
737         }
738
739         context_id = call->pkt.u.bind.ctx_list[0].context_id;
740         if_version = call->pkt.u.bind.ctx_list[0].abstract_syntax.if_version;
741         uuid = call->pkt.u.bind.ctx_list[0].abstract_syntax.uuid;
742
743         transfer_syntax_version = call->pkt.u.bind.ctx_list[0].transfer_syntaxes[0].if_version;
744         transfer_syntax_uuid = &call->pkt.u.bind.ctx_list[0].transfer_syntaxes[0].uuid;
745         if (!GUID_equal(&ndr_transfer_syntax_ndr.uuid, transfer_syntax_uuid) != 0 ||
746             ndr_transfer_syntax_ndr.if_version != transfer_syntax_version) {
747                 char *uuid_str = GUID_string(call, transfer_syntax_uuid);
748                 /* we only do NDR encoded dcerpc */
749                 DEBUG(0,("Non NDR transfer syntax requested - %s\n", uuid_str));
750                 talloc_free(uuid_str);
751                 return dcesrv_bind_nak(call, 0);
752         }
753
754         iface = find_interface_by_uuid(call->conn->endpoint, &uuid, if_version);
755         if (iface == NULL) {
756                 char *uuid_str = GUID_string(call, &uuid);
757                 DEBUG(2,("Request for unknown dcerpc interface %s/%d\n", uuid_str, if_version));
758                 talloc_free(uuid_str);
759
760                 /* we don't know about that interface */
761                 result = DCERPC_BIND_PROVIDER_REJECT;
762                 reason = DCERPC_BIND_REASON_ASYNTAX;            
763         }
764
765         if (iface) {
766                 /* add this context to the list of available context_ids */
767                 struct dcesrv_connection_context *context = talloc_zero(call->conn,
768                                                                    struct dcesrv_connection_context);
769                 if (context == NULL) {
770                         return dcesrv_bind_nak(call, 0);
771                 }
772                 context->conn = call->conn;
773                 context->iface = iface;
774                 context->context_id = context_id;
775                 context->private_data = NULL;
776                 DLIST_ADD(call->conn->contexts, context);
777                 call->context = context;
778                 talloc_set_destructor(context, dcesrv_connection_context_destructor);
779
780                 dcesrv_prepare_context_auth(call);
781
782                 status = iface->bind(call, iface, if_version);
783                 if (!NT_STATUS_IS_OK(status)) {
784                         char *uuid_str = GUID_string(call, &uuid);
785                         DEBUG(2,("Request for dcerpc interface %s/%d rejected: %s\n",
786                                  uuid_str, if_version, nt_errstr(status)));
787                         talloc_free(uuid_str);
788                         /* we don't want to trigger the iface->unbind() hook */
789                         context->iface = NULL;
790                         talloc_free(call->context);
791                         call->context = NULL;
792                         return dcesrv_bind_nak(call, 0);
793                 }
794         }
795
796         if ((call->pkt.pfc_flags & DCERPC_PFC_FLAG_CONC_MPX) &&
797             (call->state_flags & DCESRV_CALL_STATE_FLAG_MULTIPLEXED)) {
798                 call->context->conn->state_flags |= DCESRV_CALL_STATE_FLAG_MULTIPLEXED;
799                 extra_flags |= DCERPC_PFC_FLAG_CONC_MPX;
800         }
801
802         if (call->state_flags & DCESRV_CALL_STATE_FLAG_PROCESS_PENDING_CALL) {
803                 call->context->conn->state_flags |= DCESRV_CALL_STATE_FLAG_PROCESS_PENDING_CALL;
804         }
805
806         /* handle any authentication that is being requested */
807         if (!dcesrv_auth_bind(call)) {
808                 struct dcesrv_auth *auth = &call->conn->auth_state;
809
810                 TALLOC_FREE(call->context);
811
812                 if (auth->auth_level == DCERPC_AUTH_LEVEL_NONE) {
813                         /*
814                          * With DCERPC_AUTH_LEVEL_NONE, we get the
815                          * reject_reason in auth->auth_context_id.
816                          */
817                         return dcesrv_bind_nak(call, auth->auth_context_id);
818                 }
819
820                 /*
821                  * This must a be a temporary failure e.g. talloc or invalid
822                  * configuration, e.g. no machine account.
823                  */
824                 return dcesrv_bind_nak(call,
825                                 DCERPC_BIND_NAK_REASON_TEMPORARY_CONGESTION);
826         }
827
828         /* setup a bind_ack */
829         dcesrv_init_hdr(&pkt, lpcfg_rpc_big_endian(call->conn->dce_ctx->lp_ctx));
830         pkt.auth_length = 0;
831         pkt.call_id = call->pkt.call_id;
832         pkt.ptype = DCERPC_PKT_BIND_ACK;
833         pkt.pfc_flags = DCERPC_PFC_FLAG_FIRST | DCERPC_PFC_FLAG_LAST | extra_flags;
834         pkt.u.bind_ack.max_xmit_frag = call->conn->max_xmit_frag;
835         pkt.u.bind_ack.max_recv_frag = call->conn->max_recv_frag;
836         pkt.u.bind_ack.assoc_group_id = call->conn->assoc_group->id;
837
838         if (iface) {
839                 endpoint = dcerpc_binding_get_string_option(
840                                 call->conn->endpoint->ep_description,
841                                 "endpoint");
842         }
843
844         if (endpoint == NULL) {
845                 endpoint = "";
846         }
847
848         if (strncasecmp(endpoint, "\\pipe\\", 6) == 0) {
849                 /*
850                  * TODO: check if this is really needed
851                  *
852                  * Or if we should fix this in our idl files.
853                  */
854                 ep_prefix = "\\PIPE\\";
855                 endpoint += 6;
856         }
857
858         pkt.u.bind_ack.secondary_address = talloc_asprintf(call, "%s%s",
859                                                            ep_prefix,
860                                                            endpoint);
861         if (pkt.u.bind_ack.secondary_address == NULL) {
862                 TALLOC_FREE(call->context);
863                 return NT_STATUS_NO_MEMORY;
864         }
865         pkt.u.bind_ack.num_results = 1;
866         pkt.u.bind_ack.ctx_list = talloc_zero(call, struct dcerpc_ack_ctx);
867         if (!pkt.u.bind_ack.ctx_list) {
868                 talloc_free(call->context);
869                 call->context = NULL;
870                 return NT_STATUS_NO_MEMORY;
871         }
872         pkt.u.bind_ack.ctx_list[0].result = result;
873         pkt.u.bind_ack.ctx_list[0].reason.value = reason;
874         pkt.u.bind_ack.ctx_list[0].syntax = ndr_transfer_syntax_ndr;
875         pkt.u.bind_ack.auth_info = data_blob(NULL, 0);
876
877         status = dcesrv_auth_bind_ack(call, &pkt);
878         if (!NT_STATUS_IS_OK(status)) {
879                 talloc_free(call->context);
880                 call->context = NULL;
881                 return dcesrv_bind_nak(call, 0);
882         }
883
884         rep = talloc_zero(call, struct data_blob_list_item);
885         if (!rep) {
886                 talloc_free(call->context);
887                 call->context = NULL;
888                 return NT_STATUS_NO_MEMORY;
889         }
890
891         status = ncacn_push_auth(&rep->blob, call, &pkt,
892                                  call->out_auth_info);
893         if (!NT_STATUS_IS_OK(status)) {
894                 talloc_free(call->context);
895                 call->context = NULL;
896                 return status;
897         }
898
899         dcerpc_set_frag_length(&rep->blob, rep->blob.length);
900
901         DLIST_ADD_END(call->replies, rep);
902         dcesrv_call_set_list(call, DCESRV_LIST_CALL_LIST);
903
904         if (call->conn->call_list && call->conn->call_list->replies) {
905                 if (call->conn->transport.report_output_data) {
906                         call->conn->transport.report_output_data(call->conn);
907                 }
908         }
909
910         return NT_STATUS_OK;
911 }
912
913
914 /*
915   handle a auth3 request
916 */
917 static NTSTATUS dcesrv_auth3(struct dcesrv_call_state *call)
918 {
919         NTSTATUS status;
920
921         if (!call->conn->allow_auth3) {
922                 return dcesrv_fault_disconnect(call, DCERPC_NCA_S_PROTO_ERROR);
923         }
924
925         if (call->conn->auth_state.auth_finished) {
926                 return dcesrv_fault_disconnect(call, DCERPC_NCA_S_PROTO_ERROR);
927         }
928
929         status = dcerpc_verify_ncacn_packet_header(&call->pkt,
930                         DCERPC_PKT_AUTH3,
931                         call->pkt.u.auth3.auth_info.length,
932                         0, /* required flags */
933                         DCERPC_PFC_FLAG_FIRST |
934                         DCERPC_PFC_FLAG_LAST |
935                         DCERPC_PFC_FLAG_SUPPORT_HEADER_SIGN |
936                         0x08 | /* this is not defined, but should be ignored */
937                         DCERPC_PFC_FLAG_CONC_MPX |
938                         DCERPC_PFC_FLAG_DID_NOT_EXECUTE |
939                         DCERPC_PFC_FLAG_MAYBE |
940                         DCERPC_PFC_FLAG_OBJECT_UUID);
941         if (!NT_STATUS_IS_OK(status)) {
942                 return dcesrv_fault_disconnect(call, DCERPC_NCA_S_PROTO_ERROR);
943         }
944
945         /* handle the auth3 in the auth code */
946         if (!dcesrv_auth_auth3(call)) {
947                 call->conn->auth_state.auth_invalid = true;
948                 if (call->fault_code != 0) {
949                         return dcesrv_fault_disconnect(call, call->fault_code);
950                 }
951         }
952
953         talloc_free(call);
954
955         /* we don't send a reply to a auth3 request, except by a
956            fault */
957         return NT_STATUS_OK;
958 }
959
960
961 /*
962   handle a bind request
963 */
964 static NTSTATUS dcesrv_alter_new_context(struct dcesrv_call_state *call, uint16_t context_id)
965 {
966         uint32_t if_version, transfer_syntax_version;
967         struct dcesrv_connection_context *context;
968         const struct dcesrv_interface *iface;
969         struct GUID uuid, *transfer_syntax_uuid;
970         NTSTATUS status;
971
972         if_version = call->pkt.u.alter.ctx_list[0].abstract_syntax.if_version;
973         uuid = call->pkt.u.alter.ctx_list[0].abstract_syntax.uuid;
974
975         transfer_syntax_version = call->pkt.u.alter.ctx_list[0].transfer_syntaxes[0].if_version;
976         transfer_syntax_uuid = &call->pkt.u.alter.ctx_list[0].transfer_syntaxes[0].uuid;
977         if (!GUID_equal(transfer_syntax_uuid, &ndr_transfer_syntax_ndr.uuid) ||
978             ndr_transfer_syntax_ndr.if_version != transfer_syntax_version) {
979                 /* we only do NDR encoded dcerpc */
980                 return NT_STATUS_RPC_PROTSEQ_NOT_SUPPORTED;
981         }
982
983         iface = find_interface_by_uuid(call->conn->endpoint, &uuid, if_version);
984         if (iface == NULL) {
985                 char *uuid_str = GUID_string(call, &uuid);
986                 DEBUG(2,("Request for unknown dcerpc interface %s/%d\n", uuid_str, if_version));
987                 talloc_free(uuid_str);
988                 return NT_STATUS_RPC_PROTSEQ_NOT_SUPPORTED;
989         }
990
991         /* add this context to the list of available context_ids */
992         context = talloc_zero(call->conn, struct dcesrv_connection_context);
993         if (context == NULL) {
994                 return NT_STATUS_NO_MEMORY;
995         }
996         context->conn = call->conn;
997         context->iface = iface;
998         context->context_id = context_id;
999         context->private_data = NULL;
1000         DLIST_ADD(call->conn->contexts, context);
1001         call->context = context;
1002         talloc_set_destructor(context, dcesrv_connection_context_destructor);
1003
1004         dcesrv_prepare_context_auth(call);
1005
1006         status = iface->bind(call, iface, if_version);
1007         if (!NT_STATUS_IS_OK(status)) {
1008                 /* we don't want to trigger the iface->unbind() hook */
1009                 context->iface = NULL;
1010                 talloc_free(context);
1011                 call->context = NULL;
1012                 return status;
1013         }
1014
1015         return NT_STATUS_OK;
1016 }
1017
1018 /* setup and send an alter_resp */
1019 /*
1020   handle a alter context request
1021 */
1022 static NTSTATUS dcesrv_alter(struct dcesrv_call_state *call)
1023 {
1024         NTSTATUS status;
1025         const struct dcerpc_ctx_list *ctx = NULL;
1026         bool auth_ok = false;
1027
1028         if (!call->conn->allow_alter) {
1029                 return dcesrv_fault_disconnect(call, DCERPC_NCA_S_PROTO_ERROR);
1030         }
1031
1032         status = dcerpc_verify_ncacn_packet_header(&call->pkt,
1033                         DCERPC_PKT_ALTER,
1034                         call->pkt.u.alter.auth_info.length,
1035                         0, /* required flags */
1036                         DCERPC_PFC_FLAG_FIRST |
1037                         DCERPC_PFC_FLAG_LAST |
1038                         DCERPC_PFC_FLAG_SUPPORT_HEADER_SIGN |
1039                         0x08 | /* this is not defined, but should be ignored */
1040                         DCERPC_PFC_FLAG_CONC_MPX |
1041                         DCERPC_PFC_FLAG_DID_NOT_EXECUTE |
1042                         DCERPC_PFC_FLAG_MAYBE |
1043                         DCERPC_PFC_FLAG_OBJECT_UUID);
1044         if (!NT_STATUS_IS_OK(status)) {
1045                 return dcesrv_fault_disconnect(call, DCERPC_NCA_S_PROTO_ERROR);
1046         }
1047
1048         auth_ok = dcesrv_auth_alter(call);
1049         if (!auth_ok) {
1050                 if (call->fault_code != 0) {
1051                         return dcesrv_fault_disconnect(call, call->fault_code);
1052                 }
1053         }
1054
1055         if (call->pkt.u.alter.num_contexts < 1) {
1056                 return dcesrv_fault_disconnect(call, DCERPC_NCA_S_PROTO_ERROR);
1057         }
1058         ctx = &call->pkt.u.alter.ctx_list[0];
1059         if (ctx->num_transfer_syntaxes < 1) {
1060                 return dcesrv_fault_disconnect(call, DCERPC_NCA_S_PROTO_ERROR);
1061         }
1062
1063         /* see if they are asking for a new interface */
1064         call->context = dcesrv_find_context(call->conn, ctx->context_id);
1065         if (!call->context) {
1066                 status = dcesrv_alter_new_context(call, ctx->context_id);
1067                 if (!NT_STATUS_IS_OK(status)) {
1068                         return dcesrv_alter_resp(call,
1069                                 DCERPC_BIND_PROVIDER_REJECT,
1070                                 DCERPC_BIND_REASON_ASYNTAX);
1071                 }
1072         } else {
1073                 bool ok;
1074
1075                 ok = ndr_syntax_id_equal(&ctx->abstract_syntax,
1076                                          &call->context->iface->syntax_id);
1077                 if (!ok) {
1078                         return dcesrv_fault_disconnect(call,
1079                                         DCERPC_NCA_S_PROTO_ERROR);
1080                 }
1081
1082                 if (ctx->num_transfer_syntaxes != 1) {
1083                         return dcesrv_fault_disconnect(call,
1084                                         DCERPC_NCA_S_PROTO_ERROR);
1085                 }
1086
1087                 ok = ndr_syntax_id_equal(&ctx->transfer_syntaxes[0],
1088                                          &ndr_transfer_syntax_ndr);
1089                 if (!ok) {
1090                         return dcesrv_fault_disconnect(call,
1091                                         DCERPC_NCA_S_PROTO_ERROR);
1092                 }
1093         }
1094
1095         /* handle any authentication that is being requested */
1096         if (!auth_ok) {
1097                 if (call->in_auth_info.auth_type !=
1098                     call->conn->auth_state.auth_type)
1099                 {
1100                         return dcesrv_fault_disconnect(call,
1101                                         DCERPC_FAULT_SEC_PKG_ERROR);
1102                 }
1103                 return dcesrv_fault_disconnect(call, DCERPC_FAULT_ACCESS_DENIED);
1104         }
1105
1106         return dcesrv_alter_resp(call,
1107                                 DCERPC_BIND_ACK_RESULT_ACCEPTANCE,
1108                                 DCERPC_BIND_ACK_REASON_NOT_SPECIFIED);
1109 }
1110
1111 static NTSTATUS dcesrv_alter_resp(struct dcesrv_call_state *call,
1112                                 uint32_t result,
1113                                 uint32_t reason)
1114 {
1115         struct ncacn_packet pkt;
1116         uint32_t extra_flags = 0;
1117         struct data_blob_list_item *rep = NULL;
1118         NTSTATUS status;
1119
1120         dcesrv_init_hdr(&pkt, lpcfg_rpc_big_endian(call->conn->dce_ctx->lp_ctx));
1121         pkt.auth_length = 0;
1122         pkt.call_id = call->pkt.call_id;
1123         pkt.ptype = DCERPC_PKT_ALTER_RESP;
1124         if (result == 0) {
1125                 if ((call->pkt.pfc_flags & DCERPC_PFC_FLAG_CONC_MPX) &&
1126                                 call->context->conn->state_flags &
1127                                         DCESRV_CALL_STATE_FLAG_MULTIPLEXED) {
1128                         extra_flags |= DCERPC_PFC_FLAG_CONC_MPX;
1129                 }
1130                 if (call->state_flags & DCESRV_CALL_STATE_FLAG_PROCESS_PENDING_CALL) {
1131                         call->context->conn->state_flags |=
1132                                 DCESRV_CALL_STATE_FLAG_PROCESS_PENDING_CALL;
1133                 }
1134         }
1135         pkt.pfc_flags = DCERPC_PFC_FLAG_FIRST | DCERPC_PFC_FLAG_LAST | extra_flags;
1136         pkt.u.alter_resp.max_xmit_frag = call->conn->max_xmit_frag;
1137         pkt.u.alter_resp.max_recv_frag = call->conn->max_recv_frag;
1138         pkt.u.alter_resp.assoc_group_id = call->conn->assoc_group->id;
1139         pkt.u.alter_resp.num_results = 1;
1140         pkt.u.alter_resp.ctx_list = talloc_zero(call, struct dcerpc_ack_ctx);
1141         if (!pkt.u.alter_resp.ctx_list) {
1142                 return NT_STATUS_NO_MEMORY;
1143         }
1144         pkt.u.alter_resp.ctx_list[0].result = result;
1145         pkt.u.alter_resp.ctx_list[0].reason.value = reason;
1146         pkt.u.alter_resp.ctx_list[0].syntax = ndr_transfer_syntax_ndr;
1147         pkt.u.alter_resp.auth_info = data_blob(NULL, 0);
1148         pkt.u.alter_resp.secondary_address = "";
1149
1150         status = dcesrv_auth_alter_ack(call, &pkt);
1151         if (!NT_STATUS_IS_OK(status)) {
1152                 return dcesrv_fault_disconnect(call, DCERPC_FAULT_SEC_PKG_ERROR);
1153         }
1154
1155         rep = talloc_zero(call, struct data_blob_list_item);
1156         if (!rep) {
1157                 return NT_STATUS_NO_MEMORY;
1158         }
1159
1160         status = ncacn_push_auth(&rep->blob, call, &pkt, call->out_auth_info);
1161         if (!NT_STATUS_IS_OK(status)) {
1162                 return status;
1163         }
1164
1165         dcerpc_set_frag_length(&rep->blob, rep->blob.length);
1166
1167         DLIST_ADD_END(call->replies, rep);
1168         dcesrv_call_set_list(call, DCESRV_LIST_CALL_LIST);
1169
1170         if (call->conn->call_list && call->conn->call_list->replies) {
1171                 if (call->conn->transport.report_output_data) {
1172                         call->conn->transport.report_output_data(call->conn);
1173                 }
1174         }
1175
1176         return NT_STATUS_OK;
1177 }
1178
1179 /*
1180   possibly save the call for inspection with ndrdump
1181  */
1182 static void dcesrv_save_call(struct dcesrv_call_state *call, const char *why)
1183 {
1184 #ifdef DEVELOPER
1185         char *fname;
1186         const char *dump_dir;
1187         dump_dir = lpcfg_parm_string(call->conn->dce_ctx->lp_ctx, NULL, "dcesrv", "stubs directory");
1188         if (!dump_dir) {
1189                 return;
1190         }
1191         fname = talloc_asprintf(call, "%s/RPC-%s-%u-%s.dat",
1192                                 dump_dir,
1193                                 call->context->iface->name,
1194                                 call->pkt.u.request.opnum,
1195                                 why);
1196         if (file_save(fname, call->pkt.u.request.stub_and_verifier.data, call->pkt.u.request.stub_and_verifier.length)) {
1197                 DEBUG(0,("RPC SAVED %s\n", fname));
1198         }
1199         talloc_free(fname);
1200 #endif
1201 }
1202
1203 static NTSTATUS dcesrv_check_verification_trailer(struct dcesrv_call_state *call)
1204 {
1205         TALLOC_CTX *frame = talloc_stackframe();
1206         const uint32_t bitmask1 = call->conn->auth_state.client_hdr_signing ?
1207                 DCERPC_SEC_VT_CLIENT_SUPPORTS_HEADER_SIGNING : 0;
1208         const struct dcerpc_sec_vt_pcontext pcontext = {
1209                 .abstract_syntax = call->context->iface->syntax_id,
1210                 .transfer_syntax = ndr_transfer_syntax_ndr,
1211         };
1212         const struct dcerpc_sec_vt_header2 header2 =
1213                 dcerpc_sec_vt_header2_from_ncacn_packet(&call->pkt);
1214         enum ndr_err_code ndr_err;
1215         struct dcerpc_sec_verification_trailer *vt = NULL;
1216         NTSTATUS status = NT_STATUS_OK;
1217         bool ok;
1218
1219         SMB_ASSERT(call->pkt.ptype == DCERPC_PKT_REQUEST);
1220
1221         ndr_err = ndr_pop_dcerpc_sec_verification_trailer(call->ndr_pull,
1222                                                           frame, &vt);
1223         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
1224                 status = ndr_map_error2ntstatus(ndr_err);
1225                 goto done;
1226         }
1227
1228         ok = dcerpc_sec_verification_trailer_check(vt, &bitmask1,
1229                                                    &pcontext, &header2);
1230         if (!ok) {
1231                 status = NT_STATUS_ACCESS_DENIED;
1232                 goto done;
1233         }
1234 done:
1235         TALLOC_FREE(frame);
1236         return status;
1237 }
1238
1239 /*
1240   handle a dcerpc request packet
1241 */
1242 static NTSTATUS dcesrv_request(struct dcesrv_call_state *call)
1243 {
1244         const struct dcesrv_endpoint *endpoint = call->conn->endpoint;
1245         enum dcerpc_transport_t transport =
1246                 dcerpc_binding_get_transport(endpoint->ep_description);
1247         struct ndr_pull *pull;
1248         NTSTATUS status;
1249         struct dcesrv_connection_context *context;
1250
1251         if (!call->conn->allow_request) {
1252                 return dcesrv_fault_disconnect(call, DCERPC_NCA_S_PROTO_ERROR);
1253         }
1254
1255         /* if authenticated, and the mech we use can't do async replies, don't use them... */
1256         if (call->conn->auth_state.gensec_security && 
1257             !gensec_have_feature(call->conn->auth_state.gensec_security, GENSEC_FEATURE_ASYNC_REPLIES)) {
1258                 call->state_flags &= ~DCESRV_CALL_STATE_FLAG_MAY_ASYNC;
1259         }
1260
1261         context = dcesrv_find_context(call->conn, call->pkt.u.request.context_id);
1262         if (context == NULL) {
1263                 return dcesrv_fault_with_flags(call, DCERPC_NCA_S_UNKNOWN_IF,
1264                                         DCERPC_PFC_FLAG_DID_NOT_EXECUTE);
1265         }
1266
1267         switch (call->conn->auth_state.auth_level) {
1268         case DCERPC_AUTH_LEVEL_NONE:
1269         case DCERPC_AUTH_LEVEL_PACKET:
1270         case DCERPC_AUTH_LEVEL_INTEGRITY:
1271         case DCERPC_AUTH_LEVEL_PRIVACY:
1272                 break;
1273         default:
1274                 if (!context->allow_connect) {
1275                         char *addr;
1276
1277                         addr = tsocket_address_string(call->conn->remote_address,
1278                                                       call);
1279
1280                         DEBUG(2, ("%s: restrict auth_level_connect access "
1281                                   "to [%s] with auth[type=0x%x,level=0x%x] "
1282                                   "on [%s] from [%s]\n",
1283                                   __func__, context->iface->name,
1284                                   call->conn->auth_state.auth_type,
1285                                   call->conn->auth_state.auth_level,
1286                                   derpc_transport_string_by_transport(transport),
1287                                   addr));
1288                         return dcesrv_fault(call, DCERPC_FAULT_ACCESS_DENIED);
1289                 }
1290                 break;
1291         }
1292
1293         if (call->conn->auth_state.auth_level < context->min_auth_level) {
1294                 char *addr;
1295
1296                 addr = tsocket_address_string(call->conn->remote_address, call);
1297
1298                 DEBUG(2, ("%s: restrict access by min_auth_level[0x%x] "
1299                           "to [%s] with auth[type=0x%x,level=0x%x] "
1300                           "on [%s] from [%s]\n",
1301                           __func__,
1302                           context->min_auth_level,
1303                           context->iface->name,
1304                           call->conn->auth_state.auth_type,
1305                           call->conn->auth_state.auth_level,
1306                           derpc_transport_string_by_transport(transport),
1307                           addr));
1308                 return dcesrv_fault(call, DCERPC_FAULT_ACCESS_DENIED);
1309         }
1310
1311         pull = ndr_pull_init_blob(&call->pkt.u.request.stub_and_verifier, call);
1312         NT_STATUS_HAVE_NO_MEMORY(pull);
1313
1314         pull->flags |= LIBNDR_FLAG_REF_ALLOC;
1315
1316         call->context   = context;
1317         call->ndr_pull  = pull;
1318
1319         if (!(call->pkt.drep[0] & DCERPC_DREP_LE)) {
1320                 pull->flags |= LIBNDR_FLAG_BIGENDIAN;
1321         }
1322
1323         status = dcesrv_check_verification_trailer(call);
1324         if (!NT_STATUS_IS_OK(status)) {
1325                 uint32_t faultcode = DCERPC_FAULT_OTHER;
1326                 if (NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
1327                         faultcode = DCERPC_FAULT_ACCESS_DENIED;
1328                 }
1329                 DEBUG(10, ("dcesrv_check_verification_trailer failed: %s\n",
1330                            nt_errstr(status)));
1331                 return dcesrv_fault(call, faultcode);
1332         }
1333
1334         /* unravel the NDR for the packet */
1335         status = context->iface->ndr_pull(call, call, pull, &call->r);
1336         if (!NT_STATUS_IS_OK(status)) {
1337                 uint8_t extra_flags = 0;
1338                 if (call->fault_code == DCERPC_FAULT_OP_RNG_ERROR) {
1339                         /* we got an unknown call */
1340                         DEBUG(3,(__location__ ": Unknown RPC call %u on %s\n",
1341                                  call->pkt.u.request.opnum, context->iface->name));
1342                         dcesrv_save_call(call, "unknown");
1343                         extra_flags |= DCERPC_PFC_FLAG_DID_NOT_EXECUTE;
1344                 } else {
1345                         dcesrv_save_call(call, "pullfail");
1346                 }
1347                 return dcesrv_fault_with_flags(call, call->fault_code, extra_flags);
1348         }
1349
1350         if (pull->offset != pull->data_size) {
1351                 dcesrv_save_call(call, "extrabytes");
1352                 DEBUG(3,("Warning: %d extra bytes in incoming RPC request\n", 
1353                          pull->data_size - pull->offset));
1354         }
1355
1356         /* call the dispatch function */
1357         status = context->iface->dispatch(call, call, call->r);
1358         if (!NT_STATUS_IS_OK(status)) {
1359                 DEBUG(5,("dcerpc fault in call %s:%02x - %s\n",
1360                          context->iface->name, 
1361                          call->pkt.u.request.opnum,
1362                          dcerpc_errstr(pull, call->fault_code)));
1363                 return dcesrv_fault(call, call->fault_code);
1364         }
1365
1366         /* add the call to the pending list */
1367         dcesrv_call_set_list(call, DCESRV_LIST_PENDING_CALL_LIST);
1368
1369         if (call->state_flags & DCESRV_CALL_STATE_FLAG_ASYNC) {
1370                 return NT_STATUS_OK;
1371         }
1372
1373         return dcesrv_reply(call);
1374 }
1375
1376
1377 /*
1378   remove the call from the right list when freed
1379  */
1380 static int dcesrv_call_dequeue(struct dcesrv_call_state *call)
1381 {
1382         dcesrv_call_set_list(call, DCESRV_LIST_NONE);
1383         return 0;
1384 }
1385
1386 _PUBLIC_ const struct tsocket_address *dcesrv_connection_get_local_address(struct dcesrv_connection *conn)
1387 {
1388         return conn->local_address;
1389 }
1390
1391 _PUBLIC_ const struct tsocket_address *dcesrv_connection_get_remote_address(struct dcesrv_connection *conn)
1392 {
1393         return conn->remote_address;
1394 }
1395
1396 /*
1397   process some input to a dcerpc endpoint server.
1398 */
1399 static NTSTATUS dcesrv_process_ncacn_packet(struct dcesrv_connection *dce_conn,
1400                                             struct ncacn_packet *pkt,
1401                                             DATA_BLOB blob)
1402 {
1403         NTSTATUS status;
1404         struct dcesrv_call_state *call;
1405         struct dcesrv_call_state *existing = NULL;
1406
1407         call = talloc_zero(dce_conn, struct dcesrv_call_state);
1408         if (!call) {
1409                 data_blob_free(&blob);
1410                 talloc_free(pkt);
1411                 return NT_STATUS_NO_MEMORY;
1412         }
1413         call->conn              = dce_conn;
1414         call->event_ctx         = dce_conn->event_ctx;
1415         call->msg_ctx           = dce_conn->msg_ctx;
1416         call->state_flags       = call->conn->state_flags;
1417         call->time              = timeval_current();
1418         call->list              = DCESRV_LIST_NONE;
1419
1420         talloc_steal(call, pkt);
1421         talloc_steal(call, blob.data);
1422         call->pkt = *pkt;
1423
1424         talloc_set_destructor(call, dcesrv_call_dequeue);
1425
1426         if (call->conn->allow_bind) {
1427                 /*
1428                  * Only one bind is possible per connection
1429                  */
1430                 call->conn->allow_bind = false;
1431                 return dcesrv_bind(call);
1432         }
1433
1434         /* we have to check the signing here, before combining the
1435            pdus */
1436         if (call->pkt.ptype == DCERPC_PKT_REQUEST) {
1437                 if (!call->conn->allow_request) {
1438                         return dcesrv_fault_disconnect(call,
1439                                         DCERPC_NCA_S_PROTO_ERROR);
1440                 }
1441
1442                 status = dcerpc_verify_ncacn_packet_header(&call->pkt,
1443                                 DCERPC_PKT_REQUEST,
1444                                 call->pkt.u.request.stub_and_verifier.length,
1445                                 0, /* required_flags */
1446                                 DCERPC_PFC_FLAG_FIRST |
1447                                 DCERPC_PFC_FLAG_LAST |
1448                                 DCERPC_PFC_FLAG_PENDING_CANCEL |
1449                                 0x08 | /* this is not defined, but should be ignored */
1450                                 DCERPC_PFC_FLAG_CONC_MPX |
1451                                 DCERPC_PFC_FLAG_DID_NOT_EXECUTE |
1452                                 DCERPC_PFC_FLAG_MAYBE |
1453                                 DCERPC_PFC_FLAG_OBJECT_UUID);
1454                 if (!NT_STATUS_IS_OK(status)) {
1455                         return dcesrv_fault_disconnect(call,
1456                                         DCERPC_NCA_S_PROTO_ERROR);
1457                 }
1458
1459                 if (call->pkt.frag_length > DCERPC_FRAG_MAX_SIZE) {
1460                         /*
1461                          * We don't use dcesrv_fault_disconnect()
1462                          * here, because we don't want to set
1463                          * DCERPC_PFC_FLAG_DID_NOT_EXECUTE
1464                          *
1465                          * Note that we don't check against the negotiated
1466                          * max_recv_frag, but a hard coded value.
1467                          */
1468                         dcesrv_call_disconnect_after(call,
1469                                 "dcesrv_auth_request - frag_length too large");
1470                         return dcesrv_fault(call,
1471                                         DCERPC_NCA_S_PROTO_ERROR);
1472                 }
1473
1474                 if (call->pkt.pfc_flags & DCERPC_PFC_FLAG_FIRST) {
1475                         /* only one request is possible in the fragmented list */
1476                         if (dce_conn->incoming_fragmented_call_list != NULL) {
1477                                 TALLOC_FREE(call);
1478                                 call = dce_conn->incoming_fragmented_call_list;
1479                                 dcesrv_call_disconnect_after(call,
1480                                         "dcesrv_auth_request - "
1481                                         "existing fragmented call");
1482                                 return dcesrv_fault(call,
1483                                                 DCERPC_NCA_S_PROTO_ERROR);
1484                         }
1485                         if (call->pkt.pfc_flags & DCERPC_PFC_FLAG_PENDING_CANCEL) {
1486                                 return dcesrv_fault_disconnect(call,
1487                                                 DCERPC_FAULT_NO_CALL_ACTIVE);
1488                         }
1489                 } else {
1490                         const struct dcerpc_request *nr = &call->pkt.u.request;
1491                         const struct dcerpc_request *er = NULL;
1492                         int cmp;
1493
1494                         existing = dcesrv_find_fragmented_call(dce_conn,
1495                                                         call->pkt.call_id);
1496                         if (existing == NULL) {
1497                                 dcesrv_call_disconnect_after(call,
1498                                         "dcesrv_auth_request - "
1499                                         "no existing fragmented call");
1500                                 return dcesrv_fault(call,
1501                                                 DCERPC_NCA_S_PROTO_ERROR);
1502                         }
1503                         er = &existing->pkt.u.request;
1504
1505                         if (call->pkt.ptype != existing->pkt.ptype) {
1506                                 /* trying to play silly buggers are we? */
1507                                 return dcesrv_fault_disconnect(existing,
1508                                                 DCERPC_NCA_S_PROTO_ERROR);
1509                         }
1510                         cmp = memcmp(call->pkt.drep, existing->pkt.drep,
1511                                      sizeof(pkt->drep));
1512                         if (cmp != 0) {
1513                                 return dcesrv_fault_disconnect(existing,
1514                                                 DCERPC_NCA_S_PROTO_ERROR);
1515                         }
1516                         if (nr->context_id != er->context_id)  {
1517                                 return dcesrv_fault_disconnect(existing,
1518                                                 DCERPC_NCA_S_PROTO_ERROR);
1519                         }
1520                         if (nr->opnum != er->opnum)  {
1521                                 return dcesrv_fault_disconnect(existing,
1522                                                 DCERPC_NCA_S_PROTO_ERROR);
1523                         }
1524                 }
1525
1526                 if (!dcesrv_auth_request(call, &blob)) {
1527                         /*
1528                          * We don't use dcesrv_fault_disconnect()
1529                          * here, because we don't want to set
1530                          * DCERPC_PFC_FLAG_DID_NOT_EXECUTE
1531                          */
1532                         dcesrv_call_disconnect_after(call,
1533                                                 "dcesrv_auth_request - failed");
1534                         if (call->fault_code == 0) {
1535                                 call->fault_code = DCERPC_FAULT_ACCESS_DENIED;
1536                         }
1537                         return dcesrv_fault(call, call->fault_code);
1538                 }
1539         }
1540
1541         /* see if this is a continued packet */
1542         if (existing != NULL) {
1543                 struct dcerpc_request *er = &existing->pkt.u.request;
1544                 const struct dcerpc_request *nr = &call->pkt.u.request;
1545                 size_t available;
1546                 size_t alloc_size;
1547                 size_t alloc_hint;
1548
1549                 /*
1550                  * Up to 4 MByte are allowed by all fragments
1551                  */
1552                 available = dce_conn->max_total_request_size;
1553                 if (er->stub_and_verifier.length > available) {
1554                         dcesrv_call_disconnect_after(existing,
1555                                 "dcesrv_auth_request - existing payload too large");
1556                         return dcesrv_fault(existing, DCERPC_FAULT_ACCESS_DENIED);
1557                 }
1558                 available -= er->stub_and_verifier.length;
1559                 if (nr->alloc_hint > available) {
1560                         dcesrv_call_disconnect_after(existing,
1561                                 "dcesrv_auth_request - alloc hint too large");
1562                         return dcesrv_fault(existing, DCERPC_FAULT_ACCESS_DENIED);
1563                 }
1564                 if (nr->stub_and_verifier.length > available) {
1565                         dcesrv_call_disconnect_after(existing,
1566                                 "dcesrv_auth_request - new payload too large");
1567                         return dcesrv_fault(existing, DCERPC_FAULT_ACCESS_DENIED);
1568                 }
1569                 alloc_hint = er->stub_and_verifier.length + nr->alloc_hint;
1570                 /* allocate at least 1 byte */
1571                 alloc_hint = MAX(alloc_hint, 1);
1572                 alloc_size = er->stub_and_verifier.length +
1573                              nr->stub_and_verifier.length;
1574                 alloc_size = MAX(alloc_size, alloc_hint);
1575
1576                 er->stub_and_verifier.data =
1577                         talloc_realloc(existing,
1578                                        er->stub_and_verifier.data,
1579                                        uint8_t, alloc_size);
1580                 if (er->stub_and_verifier.data == NULL) {
1581                         TALLOC_FREE(call);
1582                         return dcesrv_fault_with_flags(existing,
1583                                                        DCERPC_FAULT_OUT_OF_RESOURCES,
1584                                                        DCERPC_PFC_FLAG_DID_NOT_EXECUTE);
1585                 }
1586                 memcpy(er->stub_and_verifier.data +
1587                        er->stub_and_verifier.length,
1588                        nr->stub_and_verifier.data,
1589                        nr->stub_and_verifier.length);
1590                 er->stub_and_verifier.length += nr->stub_and_verifier.length;
1591
1592                 existing->pkt.pfc_flags |= (call->pkt.pfc_flags & DCERPC_PFC_FLAG_LAST);
1593
1594                 TALLOC_FREE(call);
1595                 call = existing;
1596         }
1597
1598         /* this may not be the last pdu in the chain - if its isn't then
1599            just put it on the incoming_fragmented_call_list and wait for the rest */
1600         if (call->pkt.ptype == DCERPC_PKT_REQUEST &&
1601             !(call->pkt.pfc_flags & DCERPC_PFC_FLAG_LAST)) {
1602                 /*
1603                  * Up to 4 MByte are allowed by all fragments
1604                  */
1605                 if (call->pkt.u.request.alloc_hint > dce_conn->max_total_request_size) {
1606                         dcesrv_call_disconnect_after(call,
1607                                 "dcesrv_auth_request - initial alloc hint too large");
1608                         return dcesrv_fault(call, DCERPC_FAULT_ACCESS_DENIED);
1609                 }
1610                 dcesrv_call_set_list(call, DCESRV_LIST_FRAGMENTED_CALL_LIST);
1611                 return NT_STATUS_OK;
1612         } 
1613         
1614         /* This removes any fragments we may have had stashed away */
1615         dcesrv_call_set_list(call, DCESRV_LIST_NONE);
1616
1617         switch (call->pkt.ptype) {
1618         case DCERPC_PKT_BIND:
1619                 status = dcesrv_bind_nak(call,
1620                         DCERPC_BIND_NAK_REASON_NOT_SPECIFIED);
1621                 break;
1622         case DCERPC_PKT_AUTH3:
1623                 status = dcesrv_auth3(call);
1624                 break;
1625         case DCERPC_PKT_ALTER:
1626                 status = dcesrv_alter(call);
1627                 break;
1628         case DCERPC_PKT_REQUEST:
1629                 status = dcesrv_request(call);
1630                 break;
1631         default:
1632                 status = dcesrv_fault_disconnect(call, DCERPC_NCA_S_PROTO_ERROR);
1633                 break;
1634         }
1635
1636         /* if we are going to be sending a reply then add
1637            it to the list of pending calls. We add it to the end to keep the call
1638            list in the order we will answer */
1639         if (!NT_STATUS_IS_OK(status)) {
1640                 talloc_free(call);
1641         }
1642
1643         return status;
1644 }
1645
1646 _PUBLIC_ NTSTATUS dcesrv_init_context(TALLOC_CTX *mem_ctx, 
1647                                       struct loadparm_context *lp_ctx,
1648                                       const char **endpoint_servers, struct dcesrv_context **_dce_ctx)
1649 {
1650         NTSTATUS status;
1651         struct dcesrv_context *dce_ctx;
1652         int i;
1653
1654         if (!endpoint_servers) {
1655                 DEBUG(0,("dcesrv_init_context: no endpoint servers configured\n"));
1656                 return NT_STATUS_INTERNAL_ERROR;
1657         }
1658
1659         dce_ctx = talloc_zero(mem_ctx, struct dcesrv_context);
1660         NT_STATUS_HAVE_NO_MEMORY(dce_ctx);
1661
1662         if (uid_wrapper_enabled()) {
1663                 setenv("UID_WRAPPER_MYUID", "1", 1);
1664         }
1665         dce_ctx->initial_euid = geteuid();
1666         if (uid_wrapper_enabled()) {
1667                 unsetenv("UID_WRAPPER_MYUID");
1668         }
1669
1670         dce_ctx->endpoint_list  = NULL;
1671         dce_ctx->lp_ctx = lp_ctx;
1672         dce_ctx->assoc_groups_idr = idr_init(dce_ctx);
1673         NT_STATUS_HAVE_NO_MEMORY(dce_ctx->assoc_groups_idr);
1674         dce_ctx->broken_connections = NULL;
1675
1676         for (i=0;endpoint_servers[i];i++) {
1677                 const struct dcesrv_endpoint_server *ep_server;
1678
1679                 ep_server = dcesrv_ep_server_byname(endpoint_servers[i]);
1680                 if (!ep_server) {
1681                         DEBUG(0,("dcesrv_init_context: failed to find endpoint server = '%s'\n", endpoint_servers[i]));
1682                         return NT_STATUS_INTERNAL_ERROR;
1683                 }
1684
1685                 status = ep_server->init_server(dce_ctx, ep_server);
1686                 if (!NT_STATUS_IS_OK(status)) {
1687                         DEBUG(0,("dcesrv_init_context: failed to init endpoint server = '%s': %s\n", endpoint_servers[i],
1688                                 nt_errstr(status)));
1689                         return status;
1690                 }
1691         }
1692
1693         *_dce_ctx = dce_ctx;
1694         return NT_STATUS_OK;
1695 }
1696
1697 /* the list of currently registered DCERPC endpoint servers.
1698  */
1699 static struct ep_server {
1700         struct dcesrv_endpoint_server *ep_server;
1701 } *ep_servers = NULL;
1702 static int num_ep_servers;
1703
1704 /*
1705   register a DCERPC endpoint server. 
1706
1707   The 'name' can be later used by other backends to find the operations
1708   structure for this backend.  
1709
1710   The 'type' is used to specify whether this is for a disk, printer or IPC$ share
1711 */
1712 _PUBLIC_ NTSTATUS dcerpc_register_ep_server(const void *_ep_server)
1713 {
1714         const struct dcesrv_endpoint_server *ep_server = _ep_server;
1715         
1716         if (dcesrv_ep_server_byname(ep_server->name) != NULL) {
1717                 /* its already registered! */
1718                 DEBUG(0,("DCERPC endpoint server '%s' already registered\n", 
1719                          ep_server->name));
1720                 return NT_STATUS_OBJECT_NAME_COLLISION;
1721         }
1722
1723         ep_servers = realloc_p(ep_servers, struct ep_server, num_ep_servers+1);
1724         if (!ep_servers) {
1725                 smb_panic("out of memory in dcerpc_register");
1726         }
1727
1728         ep_servers[num_ep_servers].ep_server = smb_xmemdup(ep_server, sizeof(*ep_server));
1729         ep_servers[num_ep_servers].ep_server->name = smb_xstrdup(ep_server->name);
1730
1731         num_ep_servers++;
1732
1733         DEBUG(3,("DCERPC endpoint server '%s' registered\n", 
1734                  ep_server->name));
1735
1736         return NT_STATUS_OK;
1737 }
1738
1739 /*
1740   return the operations structure for a named backend of the specified type
1741 */
1742 const struct dcesrv_endpoint_server *dcesrv_ep_server_byname(const char *name)
1743 {
1744         int i;
1745
1746         for (i=0;i<num_ep_servers;i++) {
1747                 if (strcmp(ep_servers[i].ep_server->name, name) == 0) {
1748                         return ep_servers[i].ep_server;
1749                 }
1750         }
1751
1752         return NULL;
1753 }
1754
1755 void dcerpc_server_init(struct loadparm_context *lp_ctx)
1756 {
1757         static bool initialized;
1758 #define _MODULE_PROTO(init) extern NTSTATUS init(void);
1759         STATIC_dcerpc_server_MODULES_PROTO;
1760         init_module_fn static_init[] = { STATIC_dcerpc_server_MODULES };
1761         init_module_fn *shared_init;
1762
1763         if (initialized) {
1764                 return;
1765         }
1766         initialized = true;
1767
1768         shared_init = load_samba_modules(NULL, "dcerpc_server");
1769
1770         run_init_functions(static_init);
1771         run_init_functions(shared_init);
1772
1773         talloc_free(shared_init);
1774 }
1775
1776 /*
1777   return the DCERPC module version, and the size of some critical types
1778   This can be used by endpoint server modules to either detect compilation errors, or provide
1779   multiple implementations for different smbd compilation options in one module
1780 */
1781 const struct dcesrv_critical_sizes *dcerpc_module_version(void)
1782 {
1783         static const struct dcesrv_critical_sizes critical_sizes = {
1784                 DCERPC_MODULE_VERSION,
1785                 sizeof(struct dcesrv_context),
1786                 sizeof(struct dcesrv_endpoint),
1787                 sizeof(struct dcesrv_endpoint_server),
1788                 sizeof(struct dcesrv_interface),
1789                 sizeof(struct dcesrv_if_list),
1790                 sizeof(struct dcesrv_connection),
1791                 sizeof(struct dcesrv_call_state),
1792                 sizeof(struct dcesrv_auth),
1793                 sizeof(struct dcesrv_handle)
1794         };
1795
1796         return &critical_sizes;
1797 }
1798
1799 static void dcesrv_terminate_connection(struct dcesrv_connection *dce_conn, const char *reason)
1800 {
1801         struct dcesrv_context *dce_ctx = dce_conn->dce_ctx;
1802         struct stream_connection *srv_conn;
1803         srv_conn = talloc_get_type(dce_conn->transport.private_data,
1804                                    struct stream_connection);
1805
1806         dce_conn->allow_bind = false;
1807         dce_conn->allow_auth3 = false;
1808         dce_conn->allow_alter = false;
1809         dce_conn->allow_request = false;
1810
1811         if (dce_conn->pending_call_list == NULL) {
1812                 char *full_reason = talloc_asprintf(dce_conn, "dcesrv: %s", reason);
1813
1814                 DLIST_REMOVE(dce_ctx->broken_connections, dce_conn);
1815                 stream_terminate_connection(srv_conn, full_reason ? full_reason : reason);
1816                 return;
1817         }
1818
1819         if (dce_conn->terminate != NULL) {
1820                 return;
1821         }
1822
1823         DEBUG(3,("dcesrv: terminating connection due to '%s' defered due to pending calls\n",
1824                  reason));
1825         dce_conn->terminate = talloc_strdup(dce_conn, reason);
1826         if (dce_conn->terminate == NULL) {
1827                 dce_conn->terminate = "dcesrv: defered terminating connection - no memory";
1828         }
1829         DLIST_ADD_END(dce_ctx->broken_connections, dce_conn);
1830 }
1831
1832 static void dcesrv_cleanup_broken_connections(struct dcesrv_context *dce_ctx)
1833 {
1834         struct dcesrv_connection *cur, *next;
1835
1836         next = dce_ctx->broken_connections;
1837         while (next != NULL) {
1838                 cur = next;
1839                 next = cur->next;
1840
1841                 if (cur->state_flags & DCESRV_CALL_STATE_FLAG_PROCESS_PENDING_CALL) {
1842                         struct dcesrv_connection_context *context_cur, *context_next;
1843
1844                         context_next = cur->contexts;
1845                         while (context_next != NULL) {
1846                                 context_cur = context_next;
1847                                 context_next = context_cur->next;
1848
1849                                 dcesrv_connection_context_destructor(context_cur);
1850                         }
1851                 }
1852
1853                 dcesrv_terminate_connection(cur, cur->terminate);
1854         }
1855 }
1856
1857 /* We need this include to be able to compile on some plateforms
1858  * (ie. freebsd 7.2) as it seems that <sys/uio.h> is not included
1859  * correctly.
1860  * It has to be that deep because otherwise we have a conflict on
1861  * const struct dcesrv_interface declaration.
1862  * This is mostly due to socket_wrapper defining #define bind swrap_bind
1863  * which conflict with the bind used before.
1864  */
1865 #include "system/network.h"
1866
1867 struct dcesrv_sock_reply_state {
1868         struct dcesrv_connection *dce_conn;
1869         struct dcesrv_call_state *call;
1870         struct iovec iov;
1871 };
1872
1873 static void dcesrv_sock_reply_done(struct tevent_req *subreq);
1874 static void dcesrv_call_terminate_step1(struct tevent_req *subreq);
1875
1876 static void dcesrv_sock_report_output_data(struct dcesrv_connection *dce_conn)
1877 {
1878         struct dcesrv_call_state *call;
1879
1880         call = dce_conn->call_list;
1881         if (!call || !call->replies) {
1882                 return;
1883         }
1884
1885         while (call->replies) {
1886                 struct data_blob_list_item *rep = call->replies;
1887                 struct dcesrv_sock_reply_state *substate;
1888                 struct tevent_req *subreq;
1889
1890                 substate = talloc_zero(call, struct dcesrv_sock_reply_state);
1891                 if (!substate) {
1892                         dcesrv_terminate_connection(dce_conn, "no memory");
1893                         return;
1894                 }
1895
1896                 substate->dce_conn = dce_conn;
1897                 substate->call = NULL;
1898
1899                 DLIST_REMOVE(call->replies, rep);
1900
1901                 if (call->replies == NULL && call->terminate_reason == NULL) {
1902                         substate->call = call;
1903                 }
1904
1905                 substate->iov.iov_base = (void *) rep->blob.data;
1906                 substate->iov.iov_len = rep->blob.length;
1907
1908                 subreq = tstream_writev_queue_send(substate,
1909                                                    dce_conn->event_ctx,
1910                                                    dce_conn->stream,
1911                                                    dce_conn->send_queue,
1912                                                    &substate->iov, 1);
1913                 if (!subreq) {
1914                         dcesrv_terminate_connection(dce_conn, "no memory");
1915                         return;
1916                 }
1917                 tevent_req_set_callback(subreq, dcesrv_sock_reply_done,
1918                                         substate);
1919         }
1920
1921         if (call->terminate_reason != NULL) {
1922                 struct tevent_req *subreq;
1923
1924                 subreq = tevent_queue_wait_send(call,
1925                                                 dce_conn->event_ctx,
1926                                                 dce_conn->send_queue);
1927                 if (!subreq) {
1928                         dcesrv_terminate_connection(dce_conn, __location__);
1929                         return;
1930                 }
1931                 tevent_req_set_callback(subreq, dcesrv_call_terminate_step1,
1932                                         call);
1933         }
1934
1935         DLIST_REMOVE(call->conn->call_list, call);
1936         call->list = DCESRV_LIST_NONE;
1937 }
1938
1939 static void dcesrv_sock_reply_done(struct tevent_req *subreq)
1940 {
1941         struct dcesrv_sock_reply_state *substate = tevent_req_callback_data(subreq,
1942                                                 struct dcesrv_sock_reply_state);
1943         int ret;
1944         int sys_errno;
1945         NTSTATUS status;
1946         struct dcesrv_call_state *call = substate->call;
1947
1948         ret = tstream_writev_queue_recv(subreq, &sys_errno);
1949         TALLOC_FREE(subreq);
1950         if (ret == -1) {
1951                 status = map_nt_error_from_unix_common(sys_errno);
1952                 dcesrv_terminate_connection(substate->dce_conn, nt_errstr(status));
1953                 return;
1954         }
1955
1956         talloc_free(substate);
1957         if (call) {
1958                 talloc_free(call);
1959         }
1960 }
1961
1962 static void dcesrv_call_terminate_step2(struct tevent_req *subreq);
1963
1964 static void dcesrv_call_terminate_step1(struct tevent_req *subreq)
1965 {
1966         struct dcesrv_call_state *call = tevent_req_callback_data(subreq,
1967                                                 struct dcesrv_call_state);
1968         bool ok;
1969         struct timeval tv;
1970
1971         /* make sure we stop send queue before removing subreq */
1972         tevent_queue_stop(call->conn->send_queue);
1973
1974         ok = tevent_queue_wait_recv(subreq);
1975         TALLOC_FREE(subreq);
1976         if (!ok) {
1977                 dcesrv_terminate_connection(call->conn, __location__);
1978                 return;
1979         }
1980
1981         /* disconnect after 200 usecs */
1982         tv = timeval_current_ofs_usec(200);
1983         subreq = tevent_wakeup_send(call, call->conn->event_ctx, tv);
1984         if (subreq == NULL) {
1985                 dcesrv_terminate_connection(call->conn, __location__);
1986                 return;
1987         }
1988         tevent_req_set_callback(subreq, dcesrv_call_terminate_step2,
1989                                 call);
1990 }
1991
1992 static void dcesrv_call_terminate_step2(struct tevent_req *subreq)
1993 {
1994         struct dcesrv_call_state *call = tevent_req_callback_data(subreq,
1995                                                 struct dcesrv_call_state);
1996         bool ok;
1997
1998         ok = tevent_wakeup_recv(subreq);
1999         TALLOC_FREE(subreq);
2000         if (!ok) {
2001                 dcesrv_terminate_connection(call->conn, __location__);
2002                 return;
2003         }
2004
2005         dcesrv_terminate_connection(call->conn, call->terminate_reason);
2006 }
2007
2008 struct dcesrv_socket_context {
2009         const struct dcesrv_endpoint *endpoint;
2010         struct dcesrv_context *dcesrv_ctx;
2011 };
2012
2013
2014 static void dcesrv_read_fragment_done(struct tevent_req *subreq);
2015
2016 static void dcesrv_sock_accept(struct stream_connection *srv_conn)
2017 {
2018         NTSTATUS status;
2019         struct dcesrv_socket_context *dcesrv_sock = 
2020                 talloc_get_type(srv_conn->private_data, struct dcesrv_socket_context);
2021         enum dcerpc_transport_t transport =
2022                 dcerpc_binding_get_transport(dcesrv_sock->endpoint->ep_description);
2023         struct dcesrv_connection *dcesrv_conn = NULL;
2024         int ret;
2025         struct tevent_req *subreq;
2026         struct loadparm_context *lp_ctx = dcesrv_sock->dcesrv_ctx->lp_ctx;
2027
2028         dcesrv_cleanup_broken_connections(dcesrv_sock->dcesrv_ctx);
2029
2030         if (!srv_conn->session_info) {
2031                 status = auth_anonymous_session_info(srv_conn,
2032                                                      lp_ctx,
2033                                                      &srv_conn->session_info);
2034                 if (!NT_STATUS_IS_OK(status)) {
2035                         DEBUG(0,("dcesrv_sock_accept: auth_anonymous_session_info failed: %s\n",
2036                                 nt_errstr(status)));
2037                         stream_terminate_connection(srv_conn, nt_errstr(status));
2038                         return;
2039                 }
2040         }
2041
2042         status = dcesrv_endpoint_connect(dcesrv_sock->dcesrv_ctx,
2043                                          srv_conn,
2044                                          dcesrv_sock->endpoint,
2045                                          srv_conn->session_info,
2046                                          srv_conn->event.ctx,
2047                                          srv_conn->msg_ctx,
2048                                          srv_conn->server_id,
2049                                          DCESRV_CALL_STATE_FLAG_MAY_ASYNC,
2050                                          &dcesrv_conn);
2051         if (!NT_STATUS_IS_OK(status)) {
2052                 DEBUG(0,("dcesrv_sock_accept: dcesrv_endpoint_connect failed: %s\n", 
2053                         nt_errstr(status)));
2054                 stream_terminate_connection(srv_conn, nt_errstr(status));
2055                 return;
2056         }
2057
2058         dcesrv_conn->transport.private_data             = srv_conn;
2059         dcesrv_conn->transport.report_output_data       = dcesrv_sock_report_output_data;
2060
2061         TALLOC_FREE(srv_conn->event.fde);
2062
2063         dcesrv_conn->send_queue = tevent_queue_create(dcesrv_conn, "dcesrv send queue");
2064         if (!dcesrv_conn->send_queue) {
2065                 status = NT_STATUS_NO_MEMORY;
2066                 DEBUG(0,("dcesrv_sock_accept: tevent_queue_create(%s)\n",
2067                         nt_errstr(status)));
2068                 stream_terminate_connection(srv_conn, nt_errstr(status));
2069                 return;
2070         }
2071
2072         if (transport == NCACN_NP) {
2073                 dcesrv_conn->auth_state.session_key = dcesrv_inherited_session_key;
2074                 dcesrv_conn->stream = talloc_move(dcesrv_conn,
2075                                                   &srv_conn->tstream);
2076         } else {
2077                 ret = tstream_bsd_existing_socket(dcesrv_conn,
2078                                                   socket_get_fd(srv_conn->socket),
2079                                                   &dcesrv_conn->stream);
2080                 if (ret == -1) {
2081                         status = map_nt_error_from_unix_common(errno);
2082                         DEBUG(0, ("dcesrv_sock_accept: "
2083                                   "failed to setup tstream: %s\n",
2084                                   nt_errstr(status)));
2085                         stream_terminate_connection(srv_conn, nt_errstr(status));
2086                         return;
2087                 }
2088                 socket_set_flags(srv_conn->socket, SOCKET_FLAG_NOCLOSE);
2089         }
2090
2091         dcesrv_conn->local_address = srv_conn->local_address;
2092         dcesrv_conn->remote_address = srv_conn->remote_address;
2093
2094         if (transport == NCALRPC) {
2095                 uid_t uid;
2096                 gid_t gid;
2097                 int sock_fd;
2098
2099                 sock_fd = socket_get_fd(srv_conn->socket);
2100                 if (sock_fd == -1) {
2101                         stream_terminate_connection(
2102                                 srv_conn, "socket_get_fd failed\n");
2103                         return;
2104                 }
2105
2106                 ret = getpeereid(sock_fd, &uid, &gid);
2107                 if (ret == -1) {
2108                         status = map_nt_error_from_unix_common(errno);
2109                         DEBUG(0, ("dcesrv_sock_accept: "
2110                                   "getpeereid() failed for NCALRPC: %s\n",
2111                                   nt_errstr(status)));
2112                         stream_terminate_connection(srv_conn, nt_errstr(status));
2113                         return;
2114                 }
2115                 if (uid == dcesrv_conn->dce_ctx->initial_euid) {
2116                         struct tsocket_address *r = NULL;
2117
2118                         ret = tsocket_address_unix_from_path(dcesrv_conn,
2119                                                              "/root/ncalrpc_as_system",
2120                                                              &r);
2121                         if (ret == -1) {
2122                                 status = map_nt_error_from_unix_common(errno);
2123                                 DEBUG(0, ("dcesrv_sock_accept: "
2124                                           "tsocket_address_unix_from_path() failed for NCALRPC: %s\n",
2125                                           nt_errstr(status)));
2126                                 stream_terminate_connection(srv_conn, nt_errstr(status));
2127                                 return;
2128                         }
2129                         dcesrv_conn->remote_address = r;
2130                 }
2131         }
2132
2133         srv_conn->private_data = dcesrv_conn;
2134
2135         irpc_add_name(srv_conn->msg_ctx, "rpc_server");
2136
2137         subreq = dcerpc_read_ncacn_packet_send(dcesrv_conn,
2138                                                dcesrv_conn->event_ctx,
2139                                                dcesrv_conn->stream);
2140         if (!subreq) {
2141                 status = NT_STATUS_NO_MEMORY;
2142                 DEBUG(0,("dcesrv_sock_accept: dcerpc_read_fragment_buffer_send(%s)\n",
2143                         nt_errstr(status)));
2144                 stream_terminate_connection(srv_conn, nt_errstr(status));
2145                 return;
2146         }
2147         tevent_req_set_callback(subreq, dcesrv_read_fragment_done, dcesrv_conn);
2148
2149         return;
2150 }
2151
2152 static void dcesrv_read_fragment_done(struct tevent_req *subreq)
2153 {
2154         struct dcesrv_connection *dce_conn = tevent_req_callback_data(subreq,
2155                                              struct dcesrv_connection);
2156         struct dcesrv_context *dce_ctx = dce_conn->dce_ctx;
2157         struct ncacn_packet *pkt;
2158         DATA_BLOB buffer;
2159         NTSTATUS status;
2160
2161         if (dce_conn->terminate) {
2162                 /*
2163                  * if the current connection is broken
2164                  * we need to clean it up before any other connection
2165                  */
2166                 dcesrv_terminate_connection(dce_conn, dce_conn->terminate);
2167                 dcesrv_cleanup_broken_connections(dce_ctx);
2168                 return;
2169         }
2170
2171         dcesrv_cleanup_broken_connections(dce_ctx);
2172
2173         status = dcerpc_read_ncacn_packet_recv(subreq, dce_conn,
2174                                                &pkt, &buffer);
2175         TALLOC_FREE(subreq);
2176         if (!NT_STATUS_IS_OK(status)) {
2177                 dcesrv_terminate_connection(dce_conn, nt_errstr(status));
2178                 return;
2179         }
2180
2181         status = dcesrv_process_ncacn_packet(dce_conn, pkt, buffer);
2182         if (!NT_STATUS_IS_OK(status)) {
2183                 dcesrv_terminate_connection(dce_conn, nt_errstr(status));
2184                 return;
2185         }
2186
2187         subreq = dcerpc_read_ncacn_packet_send(dce_conn,
2188                                                dce_conn->event_ctx,
2189                                                dce_conn->stream);
2190         if (!subreq) {
2191                 status = NT_STATUS_NO_MEMORY;
2192                 dcesrv_terminate_connection(dce_conn, nt_errstr(status));
2193                 return;
2194         }
2195         tevent_req_set_callback(subreq, dcesrv_read_fragment_done, dce_conn);
2196 }
2197
2198 static void dcesrv_sock_recv(struct stream_connection *conn, uint16_t flags)
2199 {
2200         struct dcesrv_connection *dce_conn = talloc_get_type(conn->private_data,
2201                                              struct dcesrv_connection);
2202         dcesrv_terminate_connection(dce_conn, "dcesrv_sock_recv triggered");
2203 }
2204
2205 static void dcesrv_sock_send(struct stream_connection *conn, uint16_t flags)
2206 {
2207         struct dcesrv_connection *dce_conn = talloc_get_type(conn->private_data,
2208                                              struct dcesrv_connection);
2209         dcesrv_terminate_connection(dce_conn, "dcesrv_sock_send triggered");
2210 }
2211
2212
2213 static const struct stream_server_ops dcesrv_stream_ops = {
2214         .name                   = "rpc",
2215         .accept_connection      = dcesrv_sock_accept,
2216         .recv_handler           = dcesrv_sock_recv,
2217         .send_handler           = dcesrv_sock_send,
2218 };
2219
2220 static NTSTATUS dcesrv_add_ep_unix(struct dcesrv_context *dce_ctx, 
2221                                    struct loadparm_context *lp_ctx,
2222                                    struct dcesrv_endpoint *e,
2223                             struct tevent_context *event_ctx, const struct model_ops *model_ops)
2224 {
2225         struct dcesrv_socket_context *dcesrv_sock;
2226         uint16_t port = 1;
2227         NTSTATUS status;
2228         const char *endpoint;
2229
2230         dcesrv_sock = talloc_zero(event_ctx, struct dcesrv_socket_context);
2231         NT_STATUS_HAVE_NO_MEMORY(dcesrv_sock);
2232
2233         /* remember the endpoint of this socket */
2234         dcesrv_sock->endpoint           = e;
2235         dcesrv_sock->dcesrv_ctx         = talloc_reference(dcesrv_sock, dce_ctx);
2236
2237         endpoint = dcerpc_binding_get_string_option(e->ep_description, "endpoint");
2238
2239         status = stream_setup_socket(dcesrv_sock, event_ctx, lp_ctx,
2240                                      model_ops, &dcesrv_stream_ops, 
2241                                      "unix", endpoint, &port,
2242                                      lpcfg_socket_options(lp_ctx),
2243                                      dcesrv_sock);
2244         if (!NT_STATUS_IS_OK(status)) {
2245                 DEBUG(0,("service_setup_stream_socket(path=%s) failed - %s\n",
2246                          endpoint, nt_errstr(status)));
2247         }
2248
2249         return status;
2250 }
2251
2252 static NTSTATUS dcesrv_add_ep_ncalrpc(struct dcesrv_context *dce_ctx, 
2253                                       struct loadparm_context *lp_ctx,
2254                                       struct dcesrv_endpoint *e,
2255                                       struct tevent_context *event_ctx, const struct model_ops *model_ops)
2256 {
2257         struct dcesrv_socket_context *dcesrv_sock;
2258         uint16_t port = 1;
2259         char *full_path;
2260         NTSTATUS status;
2261         const char *endpoint;
2262
2263         endpoint = dcerpc_binding_get_string_option(e->ep_description, "endpoint");
2264
2265         if (endpoint == NULL) {
2266                 /*
2267                  * No identifier specified: use DEFAULT.
2268                  *
2269                  * TODO: DO NOT hardcode this value anywhere else. Rather, specify
2270                  * no endpoint and let the epmapper worry about it.
2271                  */
2272                 endpoint = "DEFAULT";
2273                 status = dcerpc_binding_set_string_option(e->ep_description,
2274                                                           "endpoint",
2275                                                           endpoint);
2276                 if (!NT_STATUS_IS_OK(status)) {
2277                         DEBUG(0,("dcerpc_binding_set_string_option() failed - %s\n",
2278                                   nt_errstr(status)));
2279                         return status;
2280                 }
2281         }
2282
2283         full_path = talloc_asprintf(dce_ctx, "%s/%s", lpcfg_ncalrpc_dir(lp_ctx),
2284                                     endpoint);
2285
2286         dcesrv_sock = talloc_zero(event_ctx, struct dcesrv_socket_context);
2287         NT_STATUS_HAVE_NO_MEMORY(dcesrv_sock);
2288
2289         /* remember the endpoint of this socket */
2290         dcesrv_sock->endpoint           = e;
2291         dcesrv_sock->dcesrv_ctx         = talloc_reference(dcesrv_sock, dce_ctx);
2292
2293         status = stream_setup_socket(dcesrv_sock, event_ctx, lp_ctx,
2294                                      model_ops, &dcesrv_stream_ops, 
2295                                      "unix", full_path, &port, 
2296                                      lpcfg_socket_options(lp_ctx),
2297                                      dcesrv_sock);
2298         if (!NT_STATUS_IS_OK(status)) {
2299                 DEBUG(0,("service_setup_stream_socket(identifier=%s,path=%s) failed - %s\n",
2300                          endpoint, full_path, nt_errstr(status)));
2301         }
2302         return status;
2303 }
2304
2305 static NTSTATUS dcesrv_add_ep_np(struct dcesrv_context *dce_ctx,
2306                                  struct loadparm_context *lp_ctx,
2307                                  struct dcesrv_endpoint *e,
2308                                  struct tevent_context *event_ctx, const struct model_ops *model_ops)
2309 {
2310         struct dcesrv_socket_context *dcesrv_sock;
2311         NTSTATUS status;
2312         const char *endpoint;
2313
2314         endpoint = dcerpc_binding_get_string_option(e->ep_description, "endpoint");
2315         if (endpoint == NULL) {
2316                 DEBUG(0, ("Endpoint mandatory for named pipes\n"));
2317                 return NT_STATUS_INVALID_PARAMETER;
2318         }
2319
2320         dcesrv_sock = talloc_zero(event_ctx, struct dcesrv_socket_context);
2321         NT_STATUS_HAVE_NO_MEMORY(dcesrv_sock);
2322
2323         /* remember the endpoint of this socket */
2324         dcesrv_sock->endpoint           = e;
2325         dcesrv_sock->dcesrv_ctx         = talloc_reference(dcesrv_sock, dce_ctx);
2326
2327         status = tstream_setup_named_pipe(dce_ctx, event_ctx, lp_ctx,
2328                                           model_ops, &dcesrv_stream_ops,
2329                                           endpoint,
2330                                           dcesrv_sock);
2331         if (!NT_STATUS_IS_OK(status)) {
2332                 DEBUG(0,("stream_setup_named_pipe(pipe=%s) failed - %s\n",
2333                          endpoint, nt_errstr(status)));
2334                 return status;
2335         }
2336
2337         return NT_STATUS_OK;
2338 }
2339
2340 /*
2341   add a socket address to the list of events, one event per dcerpc endpoint
2342 */
2343 static NTSTATUS add_socket_rpc_tcp_iface(struct dcesrv_context *dce_ctx, struct dcesrv_endpoint *e,
2344                                          struct tevent_context *event_ctx, const struct model_ops *model_ops,
2345                                          const char *address)
2346 {
2347         struct dcesrv_socket_context *dcesrv_sock;
2348         uint16_t port = 0;
2349         NTSTATUS status;
2350         const char *endpoint;
2351         char port_str[6];
2352
2353         endpoint = dcerpc_binding_get_string_option(e->ep_description, "endpoint");
2354         if (endpoint != NULL) {
2355                 port = atoi(endpoint);
2356         }
2357
2358         dcesrv_sock = talloc_zero(event_ctx, struct dcesrv_socket_context);
2359         NT_STATUS_HAVE_NO_MEMORY(dcesrv_sock);
2360
2361         /* remember the endpoint of this socket */
2362         dcesrv_sock->endpoint           = e;
2363         dcesrv_sock->dcesrv_ctx         = talloc_reference(dcesrv_sock, dce_ctx);
2364
2365         status = stream_setup_socket(dcesrv_sock, event_ctx, dce_ctx->lp_ctx,
2366                                      model_ops, &dcesrv_stream_ops, 
2367                                      "ip", address, &port,
2368                                      lpcfg_socket_options(dce_ctx->lp_ctx),
2369                                      dcesrv_sock);
2370         if (!NT_STATUS_IS_OK(status)) {
2371                 DEBUG(0,("service_setup_stream_socket(address=%s,port=%u) failed - %s\n", 
2372                          address, port, nt_errstr(status)));
2373                 return status;
2374         }
2375
2376         snprintf(port_str, sizeof(port_str), "%u", port);
2377
2378         status = dcerpc_binding_set_string_option(e->ep_description,
2379                                                   "endpoint", port_str);
2380         if (!NT_STATUS_IS_OK(status)) {
2381                 DEBUG(0,("dcerpc_binding_set_string_option(endpoint, %s) failed - %s\n",
2382                          port_str, nt_errstr(status)));
2383                 return status;
2384         }
2385
2386         return NT_STATUS_OK;
2387 }
2388
2389 #include "lib/socket/netif.h" /* Included here to work around the fact that socket_wrapper redefines bind() */
2390
2391 static NTSTATUS dcesrv_add_ep_tcp(struct dcesrv_context *dce_ctx, 
2392                                   struct loadparm_context *lp_ctx,
2393                                   struct dcesrv_endpoint *e,
2394                                   struct tevent_context *event_ctx, const struct model_ops *model_ops)
2395 {
2396         NTSTATUS status;
2397
2398         /* Add TCP/IP sockets */
2399         if (lpcfg_interfaces(lp_ctx) && lpcfg_bind_interfaces_only(lp_ctx)) {
2400                 int num_interfaces;
2401                 int i;
2402                 struct interface *ifaces;
2403
2404                 load_interface_list(dce_ctx, lp_ctx, &ifaces);
2405
2406                 num_interfaces = iface_list_count(ifaces);
2407                 for(i = 0; i < num_interfaces; i++) {
2408                         const char *address = iface_list_n_ip(ifaces, i);
2409                         status = add_socket_rpc_tcp_iface(dce_ctx, e, event_ctx, model_ops, address);
2410                         NT_STATUS_NOT_OK_RETURN(status);
2411                 }
2412         } else {
2413                 char **wcard;
2414                 int i;
2415                 int num_binds = 0;
2416                 wcard = iface_list_wildcard(dce_ctx);
2417                 NT_STATUS_HAVE_NO_MEMORY(wcard);
2418                 for (i=0; wcard[i]; i++) {
2419                         status = add_socket_rpc_tcp_iface(dce_ctx, e, event_ctx, model_ops, wcard[i]);
2420                         if (NT_STATUS_IS_OK(status)) {
2421                                 num_binds++;
2422                         }
2423                 }
2424                 talloc_free(wcard);
2425                 if (num_binds == 0) {
2426                         return NT_STATUS_INVALID_PARAMETER_MIX;
2427                 }
2428         }
2429
2430         return NT_STATUS_OK;
2431 }
2432
2433 NTSTATUS dcesrv_add_ep(struct dcesrv_context *dce_ctx,
2434                        struct loadparm_context *lp_ctx,
2435                        struct dcesrv_endpoint *e,
2436                        struct tevent_context *event_ctx,
2437                        const struct model_ops *model_ops)
2438 {
2439         enum dcerpc_transport_t transport =
2440                 dcerpc_binding_get_transport(e->ep_description);
2441
2442         switch (transport) {
2443         case NCACN_UNIX_STREAM:
2444                 return dcesrv_add_ep_unix(dce_ctx, lp_ctx, e, event_ctx, model_ops);
2445
2446         case NCALRPC:
2447                 return dcesrv_add_ep_ncalrpc(dce_ctx, lp_ctx, e, event_ctx, model_ops);
2448
2449         case NCACN_IP_TCP:
2450                 return dcesrv_add_ep_tcp(dce_ctx, lp_ctx, e, event_ctx, model_ops);
2451
2452         case NCACN_NP:
2453                 return dcesrv_add_ep_np(dce_ctx, lp_ctx, e, event_ctx, model_ops);
2454
2455         default:
2456                 return NT_STATUS_NOT_SUPPORTED;
2457         }
2458 }
2459
2460
2461 /**
2462  * retrieve credentials from a dce_call
2463  */
2464 _PUBLIC_ struct cli_credentials *dcesrv_call_credentials(struct dcesrv_call_state *dce_call)
2465 {
2466         return dce_call->conn->auth_state.session_info->credentials;
2467 }
2468
2469 /**
2470  * returns true if this is an authenticated call
2471  */
2472 _PUBLIC_ bool dcesrv_call_authenticated(struct dcesrv_call_state *dce_call)
2473 {
2474         enum security_user_level level;
2475         level = security_session_user_level(dce_call->conn->auth_state.session_info, NULL);
2476         return level >= SECURITY_USER;
2477 }
2478
2479 /**
2480  * retrieve account_name for a dce_call
2481  */
2482 _PUBLIC_ const char *dcesrv_call_account_name(struct dcesrv_call_state *dce_call)
2483 {
2484         return dce_call->context->conn->auth_state.session_info->info->account_name;
2485 }