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