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