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