s4-modules: get rid of the remaining static prototypes for modules
[sfrench/samba-autobuild/.git] / source4 / rpc_server / dcerpc_server.c
1 /* 
2    Unix SMB/CIFS implementation.
3
4    server side dcerpc core code
5
6    Copyright (C) Andrew Tridgell 2003-2005
7    Copyright (C) Stefan (metze) Metzmacher 2004-2005
8    
9    This program is free software; you can redistribute it and/or modify
10    it under the terms of the GNU General Public License as published by
11    the Free Software Foundation; either version 3 of the License, or
12    (at your option) any later version.
13    
14    This program is distributed in the hope that it will be useful,
15    but WITHOUT ANY WARRANTY; without even the implied warranty of
16    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17    GNU General Public License for more details.
18    
19    You should have received a copy of the GNU General Public License
20    along with this program.  If not, see <http://www.gnu.org/licenses/>.
21 */
22
23 #include "includes.h"
24 #include "auth/auth.h"
25 #include "auth/gensec/gensec.h"
26 #include "../lib/util/dlinklist.h"
27 #include "rpc_server/dcerpc_server.h"
28 #include "rpc_server/dcerpc_server_proto.h"
29 #include "rpc_server/common/proto.h"
30 #include "librpc/rpc/dcerpc_proto.h"
31 #include "system/filesys.h"
32 #include "libcli/security/security.h"
33 #include "param/param.h"
34 #include "../lib/tsocket/tsocket.h"
35 #include "../libcli/named_pipe_auth/npa_tstream.h"
36 #include "smbd/service_stream.h"
37 #include "../lib/tsocket/tsocket.h"
38 #include "lib/socket/socket.h"
39 #include "smbd/process_model.h"
40 #include "lib/messaging/irpc.h"
41
42 /* this is only used when the client asks for an unknown interface */
43 #define DUMMY_ASSOC_GROUP 0x0FFFFFFF
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(0,(__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         if (ep1->transport != ep2->transport) {
128                 return false;
129         }
130
131         if (!ep1->endpoint || !ep2->endpoint) {
132                 return ep1->endpoint == ep2->endpoint;
133         }
134
135         if (strcasecmp(ep1->endpoint, ep2->endpoint) != 0) 
136                 return false;
137
138         return true;
139 }
140
141 /*
142   find an endpoint in the dcesrv_context
143 */
144 static struct dcesrv_endpoint *find_endpoint(struct dcesrv_context *dce_ctx,
145                                              const struct dcerpc_binding *ep_description)
146 {
147         struct dcesrv_endpoint *ep;
148         for (ep=dce_ctx->endpoint_list; ep; ep=ep->next) {
149                 if (endpoints_match(ep->ep_description, ep_description)) {
150                         return ep;
151                 }
152         }
153         return NULL;
154 }
155
156 /*
157   find a registered context_id from a bind or alter_context
158 */
159 static struct dcesrv_connection_context *dcesrv_find_context(struct dcesrv_connection *conn, 
160                                                                    uint32_t context_id)
161 {
162         struct dcesrv_connection_context *c;
163         for (c=conn->contexts;c;c=c->next) {
164                 if (c->context_id == context_id) return c;
165         }
166         return NULL;
167 }
168
169 /*
170   see if a uuid and if_version match to an interface
171 */
172 static bool interface_match(const struct dcesrv_interface *if1,
173                                                         const struct dcesrv_interface *if2)
174 {
175         return (if1->syntax_id.if_version == if2->syntax_id.if_version && 
176                         GUID_equal(&if1->syntax_id.uuid, &if2->syntax_id.uuid));
177 }
178
179 /*
180   find the interface operations on an endpoint
181 */
182 static const struct dcesrv_interface *find_interface(const struct dcesrv_endpoint *endpoint,
183                                                      const struct dcesrv_interface *iface)
184 {
185         struct dcesrv_if_list *ifl;
186         for (ifl=endpoint->interface_list; ifl; ifl=ifl->next) {
187                 if (interface_match(&(ifl->iface), iface)) {
188                         return &(ifl->iface);
189                 }
190         }
191         return NULL;
192 }
193
194 /*
195   see if a uuid and if_version match to an interface
196 */
197 static bool interface_match_by_uuid(const struct dcesrv_interface *iface,
198                                     const struct GUID *uuid, uint32_t if_version)
199 {
200         return (iface->syntax_id.if_version == if_version && 
201                         GUID_equal(&iface->syntax_id.uuid, uuid));
202 }
203
204 /*
205   find the interface operations on an endpoint by uuid
206 */
207 static const struct dcesrv_interface *find_interface_by_uuid(const struct dcesrv_endpoint *endpoint,
208                                                              const struct GUID *uuid, uint32_t if_version)
209 {
210         struct dcesrv_if_list *ifl;
211         for (ifl=endpoint->interface_list; ifl; ifl=ifl->next) {
212                 if (interface_match_by_uuid(&(ifl->iface), uuid, if_version)) {
213                         return &(ifl->iface);
214                 }
215         }
216         return NULL;
217 }
218
219 /*
220   find the earlier parts of a fragmented call awaiting reassembily
221 */
222 static struct dcesrv_call_state *dcesrv_find_fragmented_call(struct dcesrv_connection *dce_conn, uint16_t call_id)
223 {
224         struct dcesrv_call_state *c;
225         for (c=dce_conn->incoming_fragmented_call_list;c;c=c->next) {
226                 if (c->pkt.call_id == call_id) {
227                         return c;
228                 }
229         }
230         return NULL;
231 }
232
233 /*
234   register an interface on an endpoint
235 */
236 _PUBLIC_ NTSTATUS dcesrv_interface_register(struct dcesrv_context *dce_ctx,
237                                    const char *ep_name,
238                                    const struct dcesrv_interface *iface,
239                                    const struct security_descriptor *sd)
240 {
241         struct dcesrv_endpoint *ep;
242         struct dcesrv_if_list *ifl;
243         struct dcerpc_binding *binding;
244         bool add_ep = false;
245         NTSTATUS status;
246         
247         status = dcerpc_parse_binding(dce_ctx, ep_name, &binding);
248
249         if (NT_STATUS_IS_ERR(status)) {
250                 DEBUG(0, ("Trouble parsing binding string '%s'\n", ep_name));
251                 return status;
252         }
253
254         /* check if this endpoint exists
255          */
256         if ((ep=find_endpoint(dce_ctx, binding))==NULL) {
257                 ep = talloc(dce_ctx, struct dcesrv_endpoint);
258                 if (!ep) {
259                         return NT_STATUS_NO_MEMORY;
260                 }
261                 ZERO_STRUCTP(ep);
262                 ep->ep_description = talloc_reference(ep, binding);
263                 add_ep = true;
264
265                 /* add mgmt interface */
266                 ifl = talloc(dce_ctx, struct dcesrv_if_list);
267                 if (!ifl) {
268                         return NT_STATUS_NO_MEMORY;
269                 }
270
271                 memcpy(&(ifl->iface), &dcesrv_mgmt_interface, 
272                            sizeof(struct dcesrv_interface));
273
274                 DLIST_ADD(ep->interface_list, ifl);
275         }
276
277         /* see if the interface is already registered on te endpoint */
278         if (find_interface(ep, iface)!=NULL) {
279                 DEBUG(0,("dcesrv_interface_register: interface '%s' already registered on endpoint '%s'\n",
280                         iface->name, ep_name));
281                 return NT_STATUS_OBJECT_NAME_COLLISION;
282         }
283
284         /* talloc a new interface list element */
285         ifl = talloc(dce_ctx, struct dcesrv_if_list);
286         if (!ifl) {
287                 return NT_STATUS_NO_MEMORY;
288         }
289
290         /* copy the given interface struct to the one on the endpoints interface list */
291         memcpy(&(ifl->iface),iface, sizeof(struct dcesrv_interface));
292
293         /* if we have a security descriptor given,
294          * we should see if we can set it up on the endpoint
295          */
296         if (sd != NULL) {
297                 /* if there's currently no security descriptor given on the endpoint
298                  * we try to set it
299                  */
300                 if (ep->sd == NULL) {
301                         ep->sd = security_descriptor_copy(dce_ctx, sd);
302                 }
303
304                 /* if now there's no security descriptor given on the endpoint
305                  * something goes wrong, either we failed to copy the security descriptor
306                  * or there was already one on the endpoint
307                  */
308                 if (ep->sd != NULL) {
309                         DEBUG(0,("dcesrv_interface_register: interface '%s' failed to setup a security descriptor\n"
310                                  "                           on endpoint '%s'\n",
311                                 iface->name, ep_name));
312                         if (add_ep) free(ep);
313                         free(ifl);
314                         return NT_STATUS_OBJECT_NAME_COLLISION;
315                 }
316         }
317
318         /* finally add the interface on the endpoint */
319         DLIST_ADD(ep->interface_list, ifl);
320
321         /* if it's a new endpoint add it to the dcesrv_context */
322         if (add_ep) {
323                 DLIST_ADD(dce_ctx->endpoint_list, ep);
324         }
325
326         DEBUG(4,("dcesrv_interface_register: interface '%s' registered on endpoint '%s'\n",
327                 iface->name, ep_name));
328
329         return NT_STATUS_OK;
330 }
331
332 NTSTATUS dcesrv_inherited_session_key(struct dcesrv_connection *p,
333                                       DATA_BLOB *session_key)
334 {
335         if (p->auth_state.session_info->session_key.length) {
336                 *session_key = p->auth_state.session_info->session_key;
337                 return NT_STATUS_OK;
338         }
339         return NT_STATUS_NO_USER_SESSION_KEY;
340 }
341
342 /*
343   fetch the user session key - may be default (above) or the SMB session key
344
345   The key is always truncated to 16 bytes 
346 */
347 _PUBLIC_ NTSTATUS dcesrv_fetch_session_key(struct dcesrv_connection *p,
348                                   DATA_BLOB *session_key)
349 {
350         NTSTATUS status = p->auth_state.session_key(p, session_key);
351         if (!NT_STATUS_IS_OK(status)) {
352                 return status;
353         }
354
355         session_key->length = MIN(session_key->length, 16);
356
357         return NT_STATUS_OK;
358 }
359
360 /*
361   connect to a dcerpc endpoint
362 */
363 _PUBLIC_ NTSTATUS dcesrv_endpoint_connect(struct dcesrv_context *dce_ctx,
364                                  TALLOC_CTX *mem_ctx,
365                                  const struct dcesrv_endpoint *ep,
366                                  struct auth_session_info *session_info,
367                                  struct tevent_context *event_ctx,
368                                  struct messaging_context *msg_ctx,
369                                  struct server_id server_id,
370                                  uint32_t state_flags,
371                                  struct dcesrv_connection **_p)
372 {
373         struct dcesrv_connection *p;
374
375         if (!session_info) {
376                 return NT_STATUS_ACCESS_DENIED;
377         }
378
379         p = talloc(mem_ctx, struct dcesrv_connection);
380         NT_STATUS_HAVE_NO_MEMORY(p);
381
382         if (!talloc_reference(p, session_info)) {
383                 talloc_free(p);
384                 return NT_STATUS_NO_MEMORY;
385         }
386
387         p->dce_ctx = dce_ctx;
388         p->endpoint = ep;
389         p->contexts = NULL;
390         p->call_list = NULL;
391         p->packet_log_dir = lpcfg_lockdir(dce_ctx->lp_ctx);
392         p->incoming_fragmented_call_list = NULL;
393         p->pending_call_list = NULL;
394         p->cli_max_recv_frag = 0;
395         p->partial_input = data_blob(NULL, 0);
396         p->auth_state.auth_info = NULL;
397         p->auth_state.gensec_security = NULL;
398         p->auth_state.session_info = session_info;
399         p->auth_state.session_key = dcesrv_generic_session_key;
400         p->event_ctx = event_ctx;
401         p->msg_ctx = msg_ctx;
402         p->server_id = server_id;
403         p->processing = false;
404         p->state_flags = state_flags;
405         ZERO_STRUCT(p->transport);
406
407         *_p = p;
408         return NT_STATUS_OK;
409 }
410
411 /*
412   move a call from an existing linked list to the specified list. This
413   prevents bugs where we forget to remove the call from a previous
414   list when moving it.
415  */
416 static void dcesrv_call_set_list(struct dcesrv_call_state *call, 
417                                  enum dcesrv_call_list list)
418 {
419         switch (call->list) {
420         case DCESRV_LIST_NONE:
421                 break;
422         case DCESRV_LIST_CALL_LIST:
423                 DLIST_REMOVE(call->conn->call_list, call);
424                 break;
425         case DCESRV_LIST_FRAGMENTED_CALL_LIST:
426                 DLIST_REMOVE(call->conn->incoming_fragmented_call_list, call);
427                 break;
428         case DCESRV_LIST_PENDING_CALL_LIST:
429                 DLIST_REMOVE(call->conn->pending_call_list, call);
430                 break;
431         }
432         call->list = list;
433         switch (list) {
434         case DCESRV_LIST_NONE:
435                 break;
436         case DCESRV_LIST_CALL_LIST:
437                 DLIST_ADD_END(call->conn->call_list, call, struct dcesrv_call_state *);
438                 break;
439         case DCESRV_LIST_FRAGMENTED_CALL_LIST:
440                 DLIST_ADD_END(call->conn->incoming_fragmented_call_list, call, struct dcesrv_call_state *);
441                 break;
442         case DCESRV_LIST_PENDING_CALL_LIST:
443                 DLIST_ADD_END(call->conn->pending_call_list, call, struct dcesrv_call_state *);
444                 break;
445         }
446 }
447
448
449 /*
450   return a dcerpc bind_nak
451 */
452 static NTSTATUS dcesrv_bind_nak(struct dcesrv_call_state *call, uint32_t reason)
453 {
454         struct ncacn_packet pkt;
455         struct data_blob_list_item *rep;
456         NTSTATUS status;
457
458         /* setup a bind_nak */
459         dcesrv_init_hdr(&pkt, lpcfg_rpc_big_endian(call->conn->dce_ctx->lp_ctx));
460         pkt.auth_length = 0;
461         pkt.call_id = call->pkt.call_id;
462         pkt.ptype = DCERPC_PKT_BIND_NAK;
463         pkt.pfc_flags = DCERPC_PFC_FLAG_FIRST | DCERPC_PFC_FLAG_LAST;
464         pkt.u.bind_nak.reject_reason = reason;
465         if (pkt.u.bind_nak.reject_reason == DECRPC_BIND_PROTOCOL_VERSION_NOT_SUPPORTED) {
466                 pkt.u.bind_nak.versions.v.num_versions = 0;
467         }
468
469         rep = talloc(call, struct data_blob_list_item);
470         if (!rep) {
471                 return NT_STATUS_NO_MEMORY;
472         }
473
474         status = ncacn_push_auth(&rep->blob, call, &pkt, NULL);
475         if (!NT_STATUS_IS_OK(status)) {
476                 return status;
477         }
478
479         dcerpc_set_frag_length(&rep->blob, rep->blob.length);
480
481         DLIST_ADD_END(call->replies, rep, struct data_blob_list_item *);
482         dcesrv_call_set_list(call, DCESRV_LIST_CALL_LIST);
483
484         if (call->conn->call_list && call->conn->call_list->replies) {
485                 if (call->conn->transport.report_output_data) {
486                         call->conn->transport.report_output_data(call->conn);
487                 }
488         }
489
490         return NT_STATUS_OK;    
491 }
492
493 static int dcesrv_connection_context_destructor(struct dcesrv_connection_context *c)
494 {
495         DLIST_REMOVE(c->conn->contexts, c);
496
497         if (c->iface && c->iface->unbind) {
498                 c->iface->unbind(c, c->iface);
499         }
500
501         return 0;
502 }
503
504 /*
505   handle a bind request
506 */
507 static NTSTATUS dcesrv_bind(struct dcesrv_call_state *call)
508 {
509         uint32_t if_version, transfer_syntax_version;
510         struct GUID uuid, *transfer_syntax_uuid;
511         struct ncacn_packet pkt;
512         struct data_blob_list_item *rep;
513         NTSTATUS status;
514         uint32_t result=0, reason=0;
515         uint32_t context_id;
516         const struct dcesrv_interface *iface;
517         uint32_t extra_flags = 0;
518
519         /*
520           if provided, check the assoc_group is valid
521          */
522         if (call->pkt.u.bind.assoc_group_id != 0 &&
523             lpcfg_parm_bool(call->conn->dce_ctx->lp_ctx, NULL, "dcesrv","assoc group checking", true) &&
524             dcesrv_assoc_group_find(call->conn->dce_ctx, call->pkt.u.bind.assoc_group_id) == NULL) {
525                 return dcesrv_bind_nak(call, 0);        
526         }
527
528         if (call->pkt.u.bind.num_contexts < 1 ||
529             call->pkt.u.bind.ctx_list[0].num_transfer_syntaxes < 1) {
530                 return dcesrv_bind_nak(call, 0);
531         }
532
533         context_id = call->pkt.u.bind.ctx_list[0].context_id;
534
535         /* you can't bind twice on one context */
536         if (dcesrv_find_context(call->conn, context_id) != NULL) {
537                 return dcesrv_bind_nak(call, 0);
538         }
539
540         if_version = call->pkt.u.bind.ctx_list[0].abstract_syntax.if_version;
541         uuid = call->pkt.u.bind.ctx_list[0].abstract_syntax.uuid;
542
543         transfer_syntax_version = call->pkt.u.bind.ctx_list[0].transfer_syntaxes[0].if_version;
544         transfer_syntax_uuid = &call->pkt.u.bind.ctx_list[0].transfer_syntaxes[0].uuid;
545         if (!GUID_equal(&ndr_transfer_syntax.uuid, transfer_syntax_uuid) != 0 ||
546             ndr_transfer_syntax.if_version != transfer_syntax_version) {
547                 char *uuid_str = GUID_string(call, transfer_syntax_uuid);
548                 /* we only do NDR encoded dcerpc */
549                 DEBUG(0,("Non NDR transfer syntax requested - %s\n", uuid_str));
550                 talloc_free(uuid_str);
551                 return dcesrv_bind_nak(call, 0);
552         }
553
554         iface = find_interface_by_uuid(call->conn->endpoint, &uuid, if_version);
555         if (iface == NULL) {
556                 char *uuid_str = GUID_string(call, &uuid);
557                 DEBUG(2,("Request for unknown dcerpc interface %s/%d\n", uuid_str, if_version));
558                 talloc_free(uuid_str);
559
560                 /* we don't know about that interface */
561                 result = DCERPC_BIND_PROVIDER_REJECT;
562                 reason = DCERPC_BIND_REASON_ASYNTAX;            
563         }
564
565         if (iface) {
566                 /* add this context to the list of available context_ids */
567                 struct dcesrv_connection_context *context = talloc(call->conn, 
568                                                                    struct dcesrv_connection_context);
569                 if (context == NULL) {
570                         return dcesrv_bind_nak(call, 0);
571                 }
572                 context->conn = call->conn;
573                 context->iface = iface;
574                 context->context_id = context_id;
575                 if (call->pkt.u.bind.assoc_group_id != 0) {
576                         context->assoc_group = dcesrv_assoc_group_reference(context,
577                                                                             call->conn->dce_ctx, 
578                                                                             call->pkt.u.bind.assoc_group_id);
579                 } else {
580                         context->assoc_group = dcesrv_assoc_group_new(context, call->conn->dce_ctx);
581                 }
582                 if (context->assoc_group == NULL) {
583                         talloc_free(context);
584                         return dcesrv_bind_nak(call, 0);
585                 }
586                 context->private_data = NULL;
587                 DLIST_ADD(call->conn->contexts, context);
588                 call->context = context;
589                 talloc_set_destructor(context, dcesrv_connection_context_destructor);
590
591                 status = iface->bind(call, iface, if_version);
592                 if (!NT_STATUS_IS_OK(status)) {
593                         char *uuid_str = GUID_string(call, &uuid);
594                         DEBUG(2,("Request for dcerpc interface %s/%d rejected: %s\n",
595                                  uuid_str, if_version, nt_errstr(status)));
596                         talloc_free(uuid_str);
597                         /* we don't want to trigger the iface->unbind() hook */
598                         context->iface = NULL;
599                         talloc_free(call->context);
600                         call->context = NULL;
601                         return dcesrv_bind_nak(call, 0);
602                 }
603         }
604
605         if (call->conn->cli_max_recv_frag == 0) {
606                 call->conn->cli_max_recv_frag = MIN(0x2000, call->pkt.u.bind.max_recv_frag);
607         }
608
609         if ((call->pkt.pfc_flags & DCERPC_PFC_FLAG_SUPPORT_HEADER_SIGN) &&
610             lpcfg_parm_bool(call->conn->dce_ctx->lp_ctx, NULL, "dcesrv","header signing", false)) {
611                 call->conn->state_flags |= DCESRV_CALL_STATE_FLAG_HEADER_SIGNING;
612                 extra_flags |= DCERPC_PFC_FLAG_SUPPORT_HEADER_SIGN;
613         }
614
615         /* handle any authentication that is being requested */
616         if (!dcesrv_auth_bind(call)) {
617                 talloc_free(call->context);
618                 call->context = NULL;
619                 return dcesrv_bind_nak(call, DCERPC_BIND_REASON_INVALID_AUTH_TYPE);
620         }
621
622         /* setup a bind_ack */
623         dcesrv_init_hdr(&pkt, lpcfg_rpc_big_endian(call->conn->dce_ctx->lp_ctx));
624         pkt.auth_length = 0;
625         pkt.call_id = call->pkt.call_id;
626         pkt.ptype = DCERPC_PKT_BIND_ACK;
627         pkt.pfc_flags = DCERPC_PFC_FLAG_FIRST | DCERPC_PFC_FLAG_LAST | extra_flags;
628         pkt.u.bind_ack.max_xmit_frag = call->conn->cli_max_recv_frag;
629         pkt.u.bind_ack.max_recv_frag = 0x2000;
630
631         /*
632           make it possible for iface->bind() to specify the assoc_group_id
633           This helps the openchange mapiproxy plugin to work correctly.
634           
635           metze
636         */
637         if (call->context) {
638                 pkt.u.bind_ack.assoc_group_id = call->context->assoc_group->id;
639         } else {
640                 pkt.u.bind_ack.assoc_group_id = DUMMY_ASSOC_GROUP;
641         }
642
643         if (iface) {
644                 /* FIXME: Use pipe name as specified by endpoint instead of interface name */
645                 pkt.u.bind_ack.secondary_address = talloc_asprintf(call, "\\PIPE\\%s", iface->name);
646         } else {
647                 pkt.u.bind_ack.secondary_address = "";
648         }
649         pkt.u.bind_ack.num_results = 1;
650         pkt.u.bind_ack.ctx_list = talloc(call, struct dcerpc_ack_ctx);
651         if (!pkt.u.bind_ack.ctx_list) {
652                 talloc_free(call->context);
653                 call->context = NULL;
654                 return NT_STATUS_NO_MEMORY;
655         }
656         pkt.u.bind_ack.ctx_list[0].result = result;
657         pkt.u.bind_ack.ctx_list[0].reason = reason;
658         pkt.u.bind_ack.ctx_list[0].syntax = ndr_transfer_syntax;
659         pkt.u.bind_ack.auth_info = data_blob(NULL, 0);
660
661         status = dcesrv_auth_bind_ack(call, &pkt);
662         if (!NT_STATUS_IS_OK(status)) {
663                 talloc_free(call->context);
664                 call->context = NULL;
665                 return dcesrv_bind_nak(call, 0);
666         }
667
668         rep = talloc(call, struct data_blob_list_item);
669         if (!rep) {
670                 talloc_free(call->context);
671                 call->context = NULL;
672                 return NT_STATUS_NO_MEMORY;
673         }
674
675         status = ncacn_push_auth(&rep->blob, call, &pkt,
676                                                          call->conn->auth_state.auth_info);
677         if (!NT_STATUS_IS_OK(status)) {
678                 talloc_free(call->context);
679                 call->context = NULL;
680                 return status;
681         }
682
683         dcerpc_set_frag_length(&rep->blob, rep->blob.length);
684
685         DLIST_ADD_END(call->replies, rep, struct data_blob_list_item *);
686         dcesrv_call_set_list(call, DCESRV_LIST_CALL_LIST);
687
688         if (call->conn->call_list && call->conn->call_list->replies) {
689                 if (call->conn->transport.report_output_data) {
690                         call->conn->transport.report_output_data(call->conn);
691                 }
692         }
693
694         return NT_STATUS_OK;
695 }
696
697
698 /*
699   handle a auth3 request
700 */
701 static NTSTATUS dcesrv_auth3(struct dcesrv_call_state *call)
702 {
703         /* handle the auth3 in the auth code */
704         if (!dcesrv_auth_auth3(call)) {
705                 return dcesrv_fault(call, DCERPC_FAULT_OTHER);
706         }
707
708         talloc_free(call);
709
710         /* we don't send a reply to a auth3 request, except by a
711            fault */
712         return NT_STATUS_OK;
713 }
714
715
716 /*
717   handle a bind request
718 */
719 static NTSTATUS dcesrv_alter_new_context(struct dcesrv_call_state *call, uint32_t context_id)
720 {
721         uint32_t if_version, transfer_syntax_version;
722         struct dcesrv_connection_context *context;
723         const struct dcesrv_interface *iface;
724         struct GUID uuid, *transfer_syntax_uuid;
725         NTSTATUS status;
726
727         if_version = call->pkt.u.alter.ctx_list[0].abstract_syntax.if_version;
728         uuid = call->pkt.u.alter.ctx_list[0].abstract_syntax.uuid;
729
730         transfer_syntax_version = call->pkt.u.alter.ctx_list[0].transfer_syntaxes[0].if_version;
731         transfer_syntax_uuid = &call->pkt.u.alter.ctx_list[0].transfer_syntaxes[0].uuid;
732         if (!GUID_equal(transfer_syntax_uuid, &ndr_transfer_syntax.uuid) ||
733             ndr_transfer_syntax.if_version != transfer_syntax_version) {
734                 /* we only do NDR encoded dcerpc */
735                 return NT_STATUS_RPC_PROTSEQ_NOT_SUPPORTED;
736         }
737
738         iface = find_interface_by_uuid(call->conn->endpoint, &uuid, if_version);
739         if (iface == NULL) {
740                 char *uuid_str = GUID_string(call, &uuid);
741                 DEBUG(2,("Request for unknown dcerpc interface %s/%d\n", uuid_str, if_version));
742                 talloc_free(uuid_str);
743                 return NT_STATUS_RPC_PROTSEQ_NOT_SUPPORTED;
744         }
745
746         /* add this context to the list of available context_ids */
747         context = talloc(call->conn, struct dcesrv_connection_context);
748         if (context == NULL) {
749                 return NT_STATUS_NO_MEMORY;
750         }
751         context->conn = call->conn;
752         context->iface = iface;
753         context->context_id = context_id;
754         if (call->pkt.u.alter.assoc_group_id != 0) {
755                 context->assoc_group = dcesrv_assoc_group_reference(context,
756                                                                     call->conn->dce_ctx, 
757                                                                     call->pkt.u.alter.assoc_group_id);
758         } else {
759                 context->assoc_group = dcesrv_assoc_group_new(context, call->conn->dce_ctx);
760         }
761         if (context->assoc_group == NULL) {
762                 talloc_free(context);
763                 call->context = NULL;
764                 return NT_STATUS_NO_MEMORY;
765         }
766         context->private_data = NULL;
767         DLIST_ADD(call->conn->contexts, context);
768         call->context = context;
769         talloc_set_destructor(context, dcesrv_connection_context_destructor);
770
771         status = iface->bind(call, iface, if_version);
772         if (!NT_STATUS_IS_OK(status)) {
773                 /* we don't want to trigger the iface->unbind() hook */
774                 context->iface = NULL;
775                 talloc_free(context);
776                 call->context = NULL;
777                 return status;
778         }
779
780         return NT_STATUS_OK;
781 }
782
783
784 /*
785   handle a alter context request
786 */
787 static NTSTATUS dcesrv_alter(struct dcesrv_call_state *call)
788 {
789         struct ncacn_packet pkt;
790         struct data_blob_list_item *rep;
791         NTSTATUS status;
792         uint32_t result=0, reason=0;
793         uint32_t context_id;
794
795         /* handle any authentication that is being requested */
796         if (!dcesrv_auth_alter(call)) {
797                 /* TODO: work out the right reject code */
798                 result = DCERPC_BIND_PROVIDER_REJECT;
799                 reason = DCERPC_BIND_REASON_ASYNTAX;            
800         }
801
802         context_id = call->pkt.u.alter.ctx_list[0].context_id;
803
804         /* see if they are asking for a new interface */
805         if (result == 0) {
806                 call->context = dcesrv_find_context(call->conn, context_id);
807                 if (!call->context) {
808                         status = dcesrv_alter_new_context(call, context_id);
809                         if (!NT_STATUS_IS_OK(status)) {
810                                 result = DCERPC_BIND_PROVIDER_REJECT;
811                                 reason = DCERPC_BIND_REASON_ASYNTAX;
812                         }
813                 }
814         }
815
816         if (result == 0 &&
817             call->pkt.u.alter.assoc_group_id != 0 &&
818             lpcfg_parm_bool(call->conn->dce_ctx->lp_ctx, NULL, "dcesrv","assoc group checking", true) &&
819             call->pkt.u.alter.assoc_group_id != call->context->assoc_group->id) {
820                 DEBUG(0,(__location__ ": Failed attempt to use new assoc_group in alter context (0x%08x 0x%08x)\n",
821                          call->context->assoc_group->id, call->pkt.u.alter.assoc_group_id));
822                 /* TODO: can they ask for a new association group? */
823                 result = DCERPC_BIND_PROVIDER_REJECT;
824                 reason = DCERPC_BIND_REASON_ASYNTAX;
825         }
826
827         /* setup a alter_resp */
828         dcesrv_init_hdr(&pkt, lpcfg_rpc_big_endian(call->conn->dce_ctx->lp_ctx));
829         pkt.auth_length = 0;
830         pkt.call_id = call->pkt.call_id;
831         pkt.ptype = DCERPC_PKT_ALTER_RESP;
832         pkt.pfc_flags = DCERPC_PFC_FLAG_FIRST | DCERPC_PFC_FLAG_LAST;
833         pkt.u.alter_resp.max_xmit_frag = 0x2000;
834         pkt.u.alter_resp.max_recv_frag = 0x2000;
835         if (result == 0) {
836                 pkt.u.alter_resp.assoc_group_id = call->context->assoc_group->id;
837         } else {
838                 pkt.u.alter_resp.assoc_group_id = 0;
839         }
840         pkt.u.alter_resp.num_results = 1;
841         pkt.u.alter_resp.ctx_list = talloc_array(call, struct dcerpc_ack_ctx, 1);
842         if (!pkt.u.alter_resp.ctx_list) {
843                 return NT_STATUS_NO_MEMORY;
844         }
845         pkt.u.alter_resp.ctx_list[0].result = result;
846         pkt.u.alter_resp.ctx_list[0].reason = reason;
847         pkt.u.alter_resp.ctx_list[0].syntax = ndr_transfer_syntax;
848         pkt.u.alter_resp.auth_info = data_blob(NULL, 0);
849         pkt.u.alter_resp.secondary_address = "";
850
851         status = dcesrv_auth_alter_ack(call, &pkt);
852         if (!NT_STATUS_IS_OK(status)) {
853                 if (NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)
854                     || NT_STATUS_EQUAL(status, NT_STATUS_LOGON_FAILURE)
855                     || NT_STATUS_EQUAL(status, NT_STATUS_NO_SUCH_USER)
856                     || NT_STATUS_EQUAL(status, NT_STATUS_WRONG_PASSWORD)) {
857                         return dcesrv_fault(call, DCERPC_FAULT_ACCESS_DENIED);
858                 }
859                 return dcesrv_fault(call, 0);
860         }
861
862         rep = talloc(call, struct data_blob_list_item);
863         if (!rep) {
864                 return NT_STATUS_NO_MEMORY;
865         }
866
867         status = ncacn_push_auth(&rep->blob, call, &pkt, call->conn->auth_state.auth_info);
868         if (!NT_STATUS_IS_OK(status)) {
869                 return status;
870         }
871
872         dcerpc_set_frag_length(&rep->blob, rep->blob.length);
873
874         DLIST_ADD_END(call->replies, rep, struct data_blob_list_item *);
875         dcesrv_call_set_list(call, DCESRV_LIST_CALL_LIST);
876
877         if (call->conn->call_list && call->conn->call_list->replies) {
878                 if (call->conn->transport.report_output_data) {
879                         call->conn->transport.report_output_data(call->conn);
880                 }
881         }
882
883         return NT_STATUS_OK;
884 }
885
886 /*
887   possibly save the call for inspection with ndrdump
888  */
889 static void dcesrv_save_call(struct dcesrv_call_state *call, const char *why)
890 {
891 #ifdef DEVELOPER
892         char *fname;
893         const char *dump_dir;
894         dump_dir = lpcfg_parm_string(call->conn->dce_ctx->lp_ctx, NULL, "dcesrv", "stubs directory");
895         if (!dump_dir) {
896                 return;
897         }
898         fname = talloc_asprintf(call, "%s/RPC-%s-%u-%s.dat",
899                                 dump_dir,
900                                 call->context->iface->name,
901                                 call->pkt.u.request.opnum,
902                                 why);
903         if (file_save(fname, call->pkt.u.request.stub_and_verifier.data, call->pkt.u.request.stub_and_verifier.length)) {
904                 DEBUG(0,("RPC SAVED %s\n", fname));
905         }
906         talloc_free(fname);
907 #endif
908 }
909
910 /*
911   handle a dcerpc request packet
912 */
913 static NTSTATUS dcesrv_request(struct dcesrv_call_state *call)
914 {
915         struct ndr_pull *pull;
916         NTSTATUS status;
917         struct dcesrv_connection_context *context;
918
919         /* if authenticated, and the mech we use can't do async replies, don't use them... */
920         if (call->conn->auth_state.gensec_security && 
921             !gensec_have_feature(call->conn->auth_state.gensec_security, GENSEC_FEATURE_ASYNC_REPLIES)) {
922                 call->state_flags &= ~DCESRV_CALL_STATE_FLAG_MAY_ASYNC;
923         }
924
925         context = dcesrv_find_context(call->conn, call->pkt.u.request.context_id);
926         if (context == NULL) {
927                 return dcesrv_fault(call, DCERPC_FAULT_UNK_IF);
928         }
929
930         pull = ndr_pull_init_blob(&call->pkt.u.request.stub_and_verifier, call);
931         NT_STATUS_HAVE_NO_MEMORY(pull);
932
933         pull->flags |= LIBNDR_FLAG_REF_ALLOC;
934
935         call->context   = context;
936         call->ndr_pull  = pull;
937
938         if (!(call->pkt.drep[0] & DCERPC_DREP_LE)) {
939                 pull->flags |= LIBNDR_FLAG_BIGENDIAN;
940         }
941
942         /* unravel the NDR for the packet */
943         status = context->iface->ndr_pull(call, call, pull, &call->r);
944         if (!NT_STATUS_IS_OK(status)) {
945                 if (call->fault_code == DCERPC_FAULT_OP_RNG_ERROR) {
946                         /* we got an unknown call */
947                         DEBUG(3,(__location__ ": Unknown RPC call %u on %s\n",
948                                  call->pkt.u.request.opnum, context->iface->name));
949                         dcesrv_save_call(call, "unknown");
950                 } else {
951                         dcesrv_save_call(call, "pullfail");
952                 }
953                 return dcesrv_fault(call, call->fault_code);
954         }
955
956         if (pull->offset != pull->data_size) {
957                 dcesrv_save_call(call, "extrabytes");
958                 DEBUG(3,("Warning: %d extra bytes in incoming RPC request\n", 
959                          pull->data_size - pull->offset));
960         }
961
962         /* call the dispatch function */
963         status = context->iface->dispatch(call, call, call->r);
964         if (!NT_STATUS_IS_OK(status)) {
965                 DEBUG(5,("dcerpc fault in call %s:%02x - %s\n",
966                          context->iface->name, 
967                          call->pkt.u.request.opnum,
968                          dcerpc_errstr(pull, call->fault_code)));
969                 return dcesrv_fault(call, call->fault_code);
970         }
971
972         /* add the call to the pending list */
973         dcesrv_call_set_list(call, DCESRV_LIST_PENDING_CALL_LIST);
974
975         if (call->state_flags & DCESRV_CALL_STATE_FLAG_ASYNC) {
976                 return NT_STATUS_OK;
977         }
978
979         return dcesrv_reply(call);
980 }
981
982
983 /*
984   remove the call from the right list when freed
985  */
986 static int dcesrv_call_dequeue(struct dcesrv_call_state *call)
987 {
988         dcesrv_call_set_list(call, DCESRV_LIST_NONE);
989         return 0;
990 }
991
992 _PUBLIC_ const struct tsocket_address *dcesrv_connection_get_local_address(struct dcesrv_connection *conn)
993 {
994         return conn->local_address;
995 }
996
997 _PUBLIC_ const struct tsocket_address *dcesrv_connection_get_remote_address(struct dcesrv_connection *conn)
998 {
999         return conn->remote_address;
1000 }
1001
1002 /*
1003   process some input to a dcerpc endpoint server.
1004 */
1005 NTSTATUS dcesrv_process_ncacn_packet(struct dcesrv_connection *dce_conn,
1006                                      struct ncacn_packet *pkt,
1007                                      DATA_BLOB blob)
1008 {
1009         NTSTATUS status;
1010         struct dcesrv_call_state *call;
1011
1012         call = talloc_zero(dce_conn, struct dcesrv_call_state);
1013         if (!call) {
1014                 data_blob_free(&blob);
1015                 talloc_free(pkt);
1016                 return NT_STATUS_NO_MEMORY;
1017         }
1018         call->conn              = dce_conn;
1019         call->event_ctx         = dce_conn->event_ctx;
1020         call->msg_ctx           = dce_conn->msg_ctx;
1021         call->state_flags       = call->conn->state_flags;
1022         call->time              = timeval_current();
1023         call->list              = DCESRV_LIST_NONE;
1024
1025         talloc_steal(call, pkt);
1026         talloc_steal(call, blob.data);
1027         call->pkt = *pkt;
1028
1029         talloc_set_destructor(call, dcesrv_call_dequeue);
1030
1031         /* we have to check the signing here, before combining the
1032            pdus */
1033         if (call->pkt.ptype == DCERPC_PKT_REQUEST &&
1034             !dcesrv_auth_request(call, &blob)) {
1035                 return dcesrv_fault(call, DCERPC_FAULT_ACCESS_DENIED);          
1036         }
1037
1038         /* see if this is a continued packet */
1039         if (call->pkt.ptype == DCERPC_PKT_REQUEST &&
1040             !(call->pkt.pfc_flags & DCERPC_PFC_FLAG_FIRST)) {
1041                 struct dcesrv_call_state *call2 = call;
1042                 uint32_t alloc_size;
1043
1044                 /* we only allow fragmented requests, no other packet types */
1045                 if (call->pkt.ptype != DCERPC_PKT_REQUEST) {
1046                         return dcesrv_fault(call2, DCERPC_FAULT_OTHER);
1047                 }
1048
1049                 /* this is a continuation of an existing call - find the call then
1050                    tack it on the end */
1051                 call = dcesrv_find_fragmented_call(dce_conn, call2->pkt.call_id);
1052                 if (!call) {
1053                         return dcesrv_fault(call2, DCERPC_FAULT_OTHER);
1054                 }
1055
1056                 if (call->pkt.ptype != call2->pkt.ptype) {
1057                         /* trying to play silly buggers are we? */
1058                         return dcesrv_fault(call2, DCERPC_FAULT_OTHER);
1059                 }
1060
1061                 alloc_size = call->pkt.u.request.stub_and_verifier.length +
1062                         call2->pkt.u.request.stub_and_verifier.length;
1063                 if (call->pkt.u.request.alloc_hint > alloc_size) {
1064                         alloc_size = call->pkt.u.request.alloc_hint;
1065                 }
1066
1067                 call->pkt.u.request.stub_and_verifier.data = 
1068                         talloc_realloc(call, 
1069                                        call->pkt.u.request.stub_and_verifier.data, 
1070                                        uint8_t, alloc_size);
1071                 if (!call->pkt.u.request.stub_and_verifier.data) {
1072                         return dcesrv_fault(call2, DCERPC_FAULT_OTHER);
1073                 }
1074                 memcpy(call->pkt.u.request.stub_and_verifier.data +
1075                        call->pkt.u.request.stub_and_verifier.length,
1076                        call2->pkt.u.request.stub_and_verifier.data,
1077                        call2->pkt.u.request.stub_and_verifier.length);
1078                 call->pkt.u.request.stub_and_verifier.length += 
1079                         call2->pkt.u.request.stub_and_verifier.length;
1080
1081                 call->pkt.pfc_flags |= (call2->pkt.pfc_flags & DCERPC_PFC_FLAG_LAST);
1082
1083                 talloc_free(call2);
1084         }
1085
1086         /* this may not be the last pdu in the chain - if its isn't then
1087            just put it on the incoming_fragmented_call_list and wait for the rest */
1088         if (call->pkt.ptype == DCERPC_PKT_REQUEST &&
1089             !(call->pkt.pfc_flags & DCERPC_PFC_FLAG_LAST)) {
1090                 dcesrv_call_set_list(call, DCESRV_LIST_FRAGMENTED_CALL_LIST);
1091                 return NT_STATUS_OK;
1092         } 
1093         
1094         /* This removes any fragments we may have had stashed away */
1095         dcesrv_call_set_list(call, DCESRV_LIST_NONE);
1096
1097         switch (call->pkt.ptype) {
1098         case DCERPC_PKT_BIND:
1099                 status = dcesrv_bind(call);
1100                 break;
1101         case DCERPC_PKT_AUTH3:
1102                 status = dcesrv_auth3(call);
1103                 break;
1104         case DCERPC_PKT_ALTER:
1105                 status = dcesrv_alter(call);
1106                 break;
1107         case DCERPC_PKT_REQUEST:
1108                 status = dcesrv_request(call);
1109                 break;
1110         default:
1111                 status = NT_STATUS_INVALID_PARAMETER;
1112                 break;
1113         }
1114
1115         /* if we are going to be sending a reply then add
1116            it to the list of pending calls. We add it to the end to keep the call
1117            list in the order we will answer */
1118         if (!NT_STATUS_IS_OK(status)) {
1119                 talloc_free(call);
1120         }
1121
1122         return status;
1123 }
1124
1125 _PUBLIC_ NTSTATUS dcesrv_init_context(TALLOC_CTX *mem_ctx, 
1126                                       struct loadparm_context *lp_ctx,
1127                                       const char **endpoint_servers, struct dcesrv_context **_dce_ctx)
1128 {
1129         NTSTATUS status;
1130         struct dcesrv_context *dce_ctx;
1131         int i;
1132
1133         if (!endpoint_servers) {
1134                 DEBUG(0,("dcesrv_init_context: no endpoint servers configured\n"));
1135                 return NT_STATUS_INTERNAL_ERROR;
1136         }
1137
1138         dce_ctx = talloc(mem_ctx, struct dcesrv_context);
1139         NT_STATUS_HAVE_NO_MEMORY(dce_ctx);
1140         dce_ctx->endpoint_list  = NULL;
1141         dce_ctx->lp_ctx = lp_ctx;
1142         dce_ctx->assoc_groups_idr = idr_init(dce_ctx);
1143         NT_STATUS_HAVE_NO_MEMORY(dce_ctx->assoc_groups_idr);
1144
1145         for (i=0;endpoint_servers[i];i++) {
1146                 const struct dcesrv_endpoint_server *ep_server;
1147
1148                 ep_server = dcesrv_ep_server_byname(endpoint_servers[i]);
1149                 if (!ep_server) {
1150                         DEBUG(0,("dcesrv_init_context: failed to find endpoint server = '%s'\n", endpoint_servers[i]));
1151                         return NT_STATUS_INTERNAL_ERROR;
1152                 }
1153
1154                 status = ep_server->init_server(dce_ctx, ep_server);
1155                 if (!NT_STATUS_IS_OK(status)) {
1156                         DEBUG(0,("dcesrv_init_context: failed to init endpoint server = '%s': %s\n", endpoint_servers[i],
1157                                 nt_errstr(status)));
1158                         return status;
1159                 }
1160         }
1161
1162         *_dce_ctx = dce_ctx;
1163         return NT_STATUS_OK;
1164 }
1165
1166 /* the list of currently registered DCERPC endpoint servers.
1167  */
1168 static struct ep_server {
1169         struct dcesrv_endpoint_server *ep_server;
1170 } *ep_servers = NULL;
1171 static int num_ep_servers;
1172
1173 /*
1174   register a DCERPC endpoint server. 
1175
1176   The 'name' can be later used by other backends to find the operations
1177   structure for this backend.  
1178
1179   The 'type' is used to specify whether this is for a disk, printer or IPC$ share
1180 */
1181 _PUBLIC_ NTSTATUS dcerpc_register_ep_server(const void *_ep_server)
1182 {
1183         const struct dcesrv_endpoint_server *ep_server = _ep_server;
1184         
1185         if (dcesrv_ep_server_byname(ep_server->name) != NULL) {
1186                 /* its already registered! */
1187                 DEBUG(0,("DCERPC endpoint server '%s' already registered\n", 
1188                          ep_server->name));
1189                 return NT_STATUS_OBJECT_NAME_COLLISION;
1190         }
1191
1192         ep_servers = realloc_p(ep_servers, struct ep_server, num_ep_servers+1);
1193         if (!ep_servers) {
1194                 smb_panic("out of memory in dcerpc_register");
1195         }
1196
1197         ep_servers[num_ep_servers].ep_server = smb_xmemdup(ep_server, sizeof(*ep_server));
1198         ep_servers[num_ep_servers].ep_server->name = smb_xstrdup(ep_server->name);
1199
1200         num_ep_servers++;
1201
1202         DEBUG(3,("DCERPC endpoint server '%s' registered\n", 
1203                  ep_server->name));
1204
1205         return NT_STATUS_OK;
1206 }
1207
1208 /*
1209   return the operations structure for a named backend of the specified type
1210 */
1211 const struct dcesrv_endpoint_server *dcesrv_ep_server_byname(const char *name)
1212 {
1213         int i;
1214
1215         for (i=0;i<num_ep_servers;i++) {
1216                 if (strcmp(ep_servers[i].ep_server->name, name) == 0) {
1217                         return ep_servers[i].ep_server;
1218                 }
1219         }
1220
1221         return NULL;
1222 }
1223
1224 void dcerpc_server_init(struct loadparm_context *lp_ctx)
1225 {
1226         static bool initialized;
1227 #define _MODULE_PROTO(init) extern NTSTATUS init(void);
1228         STATIC_dcerpc_server_MODULES_PROTO;
1229         init_module_fn static_init[] = { STATIC_dcerpc_server_MODULES };
1230         init_module_fn *shared_init;
1231
1232         if (initialized) {
1233                 return;
1234         }
1235         initialized = true;
1236
1237         shared_init = load_samba_modules(NULL, lp_ctx, "dcerpc_server");
1238
1239         run_init_functions(static_init);
1240         run_init_functions(shared_init);
1241
1242         talloc_free(shared_init);
1243 }
1244
1245 /*
1246   return the DCERPC module version, and the size of some critical types
1247   This can be used by endpoint server modules to either detect compilation errors, or provide
1248   multiple implementations for different smbd compilation options in one module
1249 */
1250 const struct dcesrv_critical_sizes *dcerpc_module_version(void)
1251 {
1252         static const struct dcesrv_critical_sizes critical_sizes = {
1253                 DCERPC_MODULE_VERSION,
1254                 sizeof(struct dcesrv_context),
1255                 sizeof(struct dcesrv_endpoint),
1256                 sizeof(struct dcesrv_endpoint_server),
1257                 sizeof(struct dcesrv_interface),
1258                 sizeof(struct dcesrv_if_list),
1259                 sizeof(struct dcesrv_connection),
1260                 sizeof(struct dcesrv_call_state),
1261                 sizeof(struct dcesrv_auth),
1262                 sizeof(struct dcesrv_handle)
1263         };
1264
1265         return &critical_sizes;
1266 }
1267
1268 static void dcesrv_terminate_connection(struct dcesrv_connection *dce_conn, const char *reason)
1269 {
1270         struct stream_connection *srv_conn;
1271         srv_conn = talloc_get_type(dce_conn->transport.private_data,
1272                                    struct stream_connection);
1273
1274         stream_terminate_connection(srv_conn, reason);
1275 }
1276 /* We need this include to be able to compile on some plateforms
1277  * (ie. freebsd 7.2) as it seems that <sys/uio.h> is not included
1278  * correctly.
1279  * It has to be that deep because otherwise we have a conflict on
1280  * const struct dcesrv_interface declaration.
1281  * This is mostly due to socket_wrapper defining #define bind swrap_bind
1282  * which conflict with the bind used before.
1283  */
1284 #include "system/network.h"
1285
1286 struct dcesrv_sock_reply_state {
1287         struct dcesrv_connection *dce_conn;
1288         struct dcesrv_call_state *call;
1289         struct iovec iov;
1290 };
1291
1292 static void dcesrv_sock_reply_done(struct tevent_req *subreq);
1293
1294 static void dcesrv_sock_report_output_data(struct dcesrv_connection *dce_conn)
1295 {
1296         struct dcesrv_call_state *call;
1297
1298         call = dce_conn->call_list;
1299         if (!call || !call->replies) {
1300                 return;
1301         }
1302
1303         while (call->replies) {
1304                 struct data_blob_list_item *rep = call->replies;
1305                 struct dcesrv_sock_reply_state *substate;
1306                 struct tevent_req *subreq;
1307
1308                 substate = talloc(call, struct dcesrv_sock_reply_state);
1309                 if (!substate) {
1310                         dcesrv_terminate_connection(dce_conn, "no memory");
1311                         return;
1312                 }
1313
1314                 substate->dce_conn = dce_conn;
1315                 substate->call = NULL;
1316
1317                 DLIST_REMOVE(call->replies, rep);
1318
1319                 if (call->replies == NULL) {
1320                         substate->call = call;
1321                 }
1322
1323                 substate->iov.iov_base = (void *) rep->blob.data;
1324                 substate->iov.iov_len = rep->blob.length;
1325
1326                 subreq = tstream_writev_queue_send(substate,
1327                                                    dce_conn->event_ctx,
1328                                                    dce_conn->stream,
1329                                                    dce_conn->send_queue,
1330                                                    &substate->iov, 1);
1331                 if (!subreq) {
1332                         dcesrv_terminate_connection(dce_conn, "no memory");
1333                         return;
1334                 }
1335                 tevent_req_set_callback(subreq, dcesrv_sock_reply_done,
1336                                         substate);
1337         }
1338
1339         DLIST_REMOVE(call->conn->call_list, call);
1340         call->list = DCESRV_LIST_NONE;
1341 }
1342
1343 static void dcesrv_sock_reply_done(struct tevent_req *subreq)
1344 {
1345         struct dcesrv_sock_reply_state *substate = tevent_req_callback_data(subreq,
1346                                                 struct dcesrv_sock_reply_state);
1347         int ret;
1348         int sys_errno;
1349         NTSTATUS status;
1350         struct dcesrv_call_state *call = substate->call;
1351
1352         ret = tstream_writev_queue_recv(subreq, &sys_errno);
1353         TALLOC_FREE(subreq);
1354         if (ret == -1) {
1355                 status = map_nt_error_from_unix(sys_errno);
1356                 dcesrv_terminate_connection(substate->dce_conn, nt_errstr(status));
1357                 return;
1358         }
1359
1360         talloc_free(substate);
1361         if (call) {
1362                 talloc_free(call);
1363         }
1364 }
1365
1366
1367
1368
1369 struct dcesrv_socket_context {
1370         const struct dcesrv_endpoint *endpoint;
1371         struct dcesrv_context *dcesrv_ctx;
1372 };
1373
1374
1375 static void dcesrv_read_fragment_done(struct tevent_req *subreq);
1376
1377 static void dcesrv_sock_accept(struct stream_connection *srv_conn)
1378 {
1379         NTSTATUS status;
1380         struct dcesrv_socket_context *dcesrv_sock = 
1381                 talloc_get_type(srv_conn->private_data, struct dcesrv_socket_context);
1382         struct dcesrv_connection *dcesrv_conn = NULL;
1383         int ret;
1384         struct tevent_req *subreq;
1385         struct loadparm_context *lp_ctx = dcesrv_sock->dcesrv_ctx->lp_ctx;
1386
1387         if (!srv_conn->session_info) {
1388                 status = auth_anonymous_session_info(srv_conn,
1389                                                      lp_ctx,
1390                                                      &srv_conn->session_info);
1391                 if (!NT_STATUS_IS_OK(status)) {
1392                         DEBUG(0,("dcesrv_sock_accept: auth_anonymous_session_info failed: %s\n",
1393                                 nt_errstr(status)));
1394                         stream_terminate_connection(srv_conn, nt_errstr(status));
1395                         return;
1396                 }
1397         }
1398
1399         status = dcesrv_endpoint_connect(dcesrv_sock->dcesrv_ctx,
1400                                          srv_conn,
1401                                          dcesrv_sock->endpoint,
1402                                          srv_conn->session_info,
1403                                          srv_conn->event.ctx,
1404                                          srv_conn->msg_ctx,
1405                                          srv_conn->server_id,
1406                                          DCESRV_CALL_STATE_FLAG_MAY_ASYNC,
1407                                          &dcesrv_conn);
1408         if (!NT_STATUS_IS_OK(status)) {
1409                 DEBUG(0,("dcesrv_sock_accept: dcesrv_endpoint_connect failed: %s\n", 
1410                         nt_errstr(status)));
1411                 stream_terminate_connection(srv_conn, nt_errstr(status));
1412                 return;
1413         }
1414
1415         dcesrv_conn->transport.private_data             = srv_conn;
1416         dcesrv_conn->transport.report_output_data       = dcesrv_sock_report_output_data;
1417
1418         TALLOC_FREE(srv_conn->event.fde);
1419
1420         dcesrv_conn->send_queue = tevent_queue_create(dcesrv_conn, "dcesrv send queue");
1421         if (!dcesrv_conn->send_queue) {
1422                 status = NT_STATUS_NO_MEMORY;
1423                 DEBUG(0,("dcesrv_sock_accept: tevent_queue_create(%s)\n",
1424                         nt_errstr(status)));
1425                 stream_terminate_connection(srv_conn, nt_errstr(status));
1426                 return;
1427         }
1428
1429         if (dcesrv_sock->endpoint->ep_description->transport == NCACN_NP) {
1430                 dcesrv_conn->auth_state.session_key = dcesrv_inherited_session_key;
1431                 dcesrv_conn->stream = talloc_move(dcesrv_conn,
1432                                                   &srv_conn->tstream);
1433         } else {
1434                 ret = tstream_bsd_existing_socket(dcesrv_conn,
1435                                                   socket_get_fd(srv_conn->socket),
1436                                                   &dcesrv_conn->stream);
1437                 if (ret == -1) {
1438                         status = map_nt_error_from_unix(errno);
1439                         DEBUG(0, ("dcesrv_sock_accept: "
1440                                   "failed to setup tstream: %s\n",
1441                                   nt_errstr(status)));
1442                         stream_terminate_connection(srv_conn, nt_errstr(status));
1443                         return;
1444                 }
1445                 socket_set_flags(srv_conn->socket, SOCKET_FLAG_NOCLOSE);
1446         }
1447
1448         dcesrv_conn->local_address = srv_conn->local_address;
1449         dcesrv_conn->remote_address = srv_conn->remote_address;
1450
1451         srv_conn->private_data = dcesrv_conn;
1452
1453         irpc_add_name(srv_conn->msg_ctx, "rpc_server");
1454
1455         subreq = dcerpc_read_ncacn_packet_send(dcesrv_conn,
1456                                                dcesrv_conn->event_ctx,
1457                                                dcesrv_conn->stream);
1458         if (!subreq) {
1459                 status = NT_STATUS_NO_MEMORY;
1460                 DEBUG(0,("dcesrv_sock_accept: dcerpc_read_fragment_buffer_send(%s)\n",
1461                         nt_errstr(status)));
1462                 stream_terminate_connection(srv_conn, nt_errstr(status));
1463                 return;
1464         }
1465         tevent_req_set_callback(subreq, dcesrv_read_fragment_done, dcesrv_conn);
1466
1467         return;
1468 }
1469
1470 static void dcesrv_read_fragment_done(struct tevent_req *subreq)
1471 {
1472         struct dcesrv_connection *dce_conn = tevent_req_callback_data(subreq,
1473                                              struct dcesrv_connection);
1474         struct ncacn_packet *pkt;
1475         DATA_BLOB buffer;
1476         NTSTATUS status;
1477
1478         status = dcerpc_read_ncacn_packet_recv(subreq, dce_conn,
1479                                                &pkt, &buffer);
1480         TALLOC_FREE(subreq);
1481         if (!NT_STATUS_IS_OK(status)) {
1482                 dcesrv_terminate_connection(dce_conn, nt_errstr(status));
1483                 return;
1484         }
1485
1486         status = dcesrv_process_ncacn_packet(dce_conn, pkt, buffer);
1487         if (!NT_STATUS_IS_OK(status)) {
1488                 dcesrv_terminate_connection(dce_conn, nt_errstr(status));
1489                 return;
1490         }
1491
1492         subreq = dcerpc_read_ncacn_packet_send(dce_conn,
1493                                                dce_conn->event_ctx,
1494                                                dce_conn->stream);
1495         if (!subreq) {
1496                 status = NT_STATUS_NO_MEMORY;
1497                 dcesrv_terminate_connection(dce_conn, nt_errstr(status));
1498                 return;
1499         }
1500         tevent_req_set_callback(subreq, dcesrv_read_fragment_done, dce_conn);
1501 }
1502
1503 static void dcesrv_sock_recv(struct stream_connection *conn, uint16_t flags)
1504 {
1505         struct dcesrv_connection *dce_conn = talloc_get_type(conn->private_data,
1506                                              struct dcesrv_connection);
1507         dcesrv_terminate_connection(dce_conn, "dcesrv_sock_recv triggered");
1508 }
1509
1510 static void dcesrv_sock_send(struct stream_connection *conn, uint16_t flags)
1511 {
1512         struct dcesrv_connection *dce_conn = talloc_get_type(conn->private_data,
1513                                              struct dcesrv_connection);
1514         dcesrv_terminate_connection(dce_conn, "dcesrv_sock_send triggered");
1515 }
1516
1517
1518 static const struct stream_server_ops dcesrv_stream_ops = {
1519         .name                   = "rpc",
1520         .accept_connection      = dcesrv_sock_accept,
1521         .recv_handler           = dcesrv_sock_recv,
1522         .send_handler           = dcesrv_sock_send,
1523 };
1524
1525 static NTSTATUS dcesrv_add_ep_unix(struct dcesrv_context *dce_ctx, 
1526                                    struct loadparm_context *lp_ctx,
1527                                    struct dcesrv_endpoint *e,
1528                             struct tevent_context *event_ctx, const struct model_ops *model_ops)
1529 {
1530         struct dcesrv_socket_context *dcesrv_sock;
1531         uint16_t port = 1;
1532         NTSTATUS status;
1533
1534         dcesrv_sock = talloc(event_ctx, struct dcesrv_socket_context);
1535         NT_STATUS_HAVE_NO_MEMORY(dcesrv_sock);
1536
1537         /* remember the endpoint of this socket */
1538         dcesrv_sock->endpoint           = e;
1539         dcesrv_sock->dcesrv_ctx         = talloc_reference(dcesrv_sock, dce_ctx);
1540
1541         status = stream_setup_socket(event_ctx, lp_ctx,
1542                                      model_ops, &dcesrv_stream_ops, 
1543                                      "unix", e->ep_description->endpoint, &port, 
1544                                      lpcfg_socket_options(lp_ctx),
1545                                      dcesrv_sock);
1546         if (!NT_STATUS_IS_OK(status)) {
1547                 DEBUG(0,("service_setup_stream_socket(path=%s) failed - %s\n",
1548                          e->ep_description->endpoint, nt_errstr(status)));
1549         }
1550
1551         return status;
1552 }
1553
1554 static NTSTATUS dcesrv_add_ep_ncalrpc(struct dcesrv_context *dce_ctx, 
1555                                       struct loadparm_context *lp_ctx,
1556                                       struct dcesrv_endpoint *e,
1557                                       struct tevent_context *event_ctx, const struct model_ops *model_ops)
1558 {
1559         struct dcesrv_socket_context *dcesrv_sock;
1560         uint16_t port = 1;
1561         char *full_path;
1562         NTSTATUS status;
1563
1564         if (!e->ep_description->endpoint) {
1565                 /* No identifier specified: use DEFAULT. 
1566                  * DO NOT hardcode this value anywhere else. Rather, specify 
1567                  * no endpoint and let the epmapper worry about it. */
1568                 e->ep_description->endpoint = talloc_strdup(dce_ctx, "DEFAULT");
1569         }
1570
1571         full_path = talloc_asprintf(dce_ctx, "%s/%s", lpcfg_ncalrpc_dir(lp_ctx),
1572                                     e->ep_description->endpoint);
1573
1574         dcesrv_sock = talloc(event_ctx, struct dcesrv_socket_context);
1575         NT_STATUS_HAVE_NO_MEMORY(dcesrv_sock);
1576
1577         /* remember the endpoint of this socket */
1578         dcesrv_sock->endpoint           = e;
1579         dcesrv_sock->dcesrv_ctx         = talloc_reference(dcesrv_sock, dce_ctx);
1580
1581         status = stream_setup_socket(event_ctx, lp_ctx,
1582                                      model_ops, &dcesrv_stream_ops, 
1583                                      "unix", full_path, &port, 
1584                                      lpcfg_socket_options(lp_ctx),
1585                                      dcesrv_sock);
1586         if (!NT_STATUS_IS_OK(status)) {
1587                 DEBUG(0,("service_setup_stream_socket(identifier=%s,path=%s) failed - %s\n",
1588                          e->ep_description->endpoint, full_path, nt_errstr(status)));
1589         }
1590         return status;
1591 }
1592
1593 static NTSTATUS dcesrv_add_ep_np(struct dcesrv_context *dce_ctx,
1594                                  struct loadparm_context *lp_ctx,
1595                                  struct dcesrv_endpoint *e,
1596                                  struct tevent_context *event_ctx, const struct model_ops *model_ops)
1597 {
1598         struct dcesrv_socket_context *dcesrv_sock;
1599         NTSTATUS status;
1600                         
1601         if (e->ep_description->endpoint == NULL) {
1602                 DEBUG(0, ("Endpoint mandatory for named pipes\n"));
1603                 return NT_STATUS_INVALID_PARAMETER;
1604         }
1605
1606         dcesrv_sock = talloc(event_ctx, struct dcesrv_socket_context);
1607         NT_STATUS_HAVE_NO_MEMORY(dcesrv_sock);
1608
1609         /* remember the endpoint of this socket */
1610         dcesrv_sock->endpoint           = e;
1611         dcesrv_sock->dcesrv_ctx         = talloc_reference(dcesrv_sock, dce_ctx);
1612
1613         status = tstream_setup_named_pipe(event_ctx, lp_ctx,
1614                                           model_ops, &dcesrv_stream_ops,
1615                                           e->ep_description->endpoint,
1616                                           dcesrv_sock);
1617         if (!NT_STATUS_IS_OK(status)) {
1618                 DEBUG(0,("stream_setup_named_pipe(pipe=%s) failed - %s\n",
1619                          e->ep_description->endpoint, nt_errstr(status)));
1620                 return status;
1621         }
1622
1623         return NT_STATUS_OK;
1624 }
1625
1626 /*
1627   add a socket address to the list of events, one event per dcerpc endpoint
1628 */
1629 static NTSTATUS add_socket_rpc_tcp_iface(struct dcesrv_context *dce_ctx, struct dcesrv_endpoint *e,
1630                                          struct tevent_context *event_ctx, const struct model_ops *model_ops,
1631                                          const char *address)
1632 {
1633         struct dcesrv_socket_context *dcesrv_sock;
1634         uint16_t port = 0;
1635         NTSTATUS status;
1636                         
1637         if (e->ep_description->endpoint) {
1638                 port = atoi(e->ep_description->endpoint);
1639         }
1640
1641         dcesrv_sock = talloc(event_ctx, struct dcesrv_socket_context);
1642         NT_STATUS_HAVE_NO_MEMORY(dcesrv_sock);
1643
1644         /* remember the endpoint of this socket */
1645         dcesrv_sock->endpoint           = e;
1646         dcesrv_sock->dcesrv_ctx         = talloc_reference(dcesrv_sock, dce_ctx);
1647
1648         status = stream_setup_socket(event_ctx, dce_ctx->lp_ctx,
1649                                      model_ops, &dcesrv_stream_ops, 
1650                                      "ipv4", address, &port, 
1651                                      lpcfg_socket_options(dce_ctx->lp_ctx),
1652                                      dcesrv_sock);
1653         if (!NT_STATUS_IS_OK(status)) {
1654                 DEBUG(0,("service_setup_stream_socket(address=%s,port=%u) failed - %s\n", 
1655                          address, port, nt_errstr(status)));
1656         }
1657
1658         if (e->ep_description->endpoint == NULL) {
1659                 e->ep_description->endpoint = talloc_asprintf(dce_ctx, "%d", port);
1660         }
1661
1662         return status;
1663 }
1664
1665 #include "lib/socket/netif.h" /* Included here to work around the fact that socket_wrapper redefines bind() */
1666
1667 static NTSTATUS dcesrv_add_ep_tcp(struct dcesrv_context *dce_ctx, 
1668                                   struct loadparm_context *lp_ctx,
1669                                   struct dcesrv_endpoint *e,
1670                                   struct tevent_context *event_ctx, const struct model_ops *model_ops)
1671 {
1672         NTSTATUS status;
1673
1674         /* Add TCP/IP sockets */
1675         if (lpcfg_interfaces(lp_ctx) && lpcfg_bind_interfaces_only(lp_ctx)) {
1676                 int num_interfaces;
1677                 int i;
1678                 struct interface *ifaces;
1679
1680                 load_interfaces(dce_ctx, lpcfg_interfaces(lp_ctx), &ifaces);
1681
1682                 num_interfaces = iface_count(ifaces);
1683                 for(i = 0; i < num_interfaces; i++) {
1684                         const char *address = iface_n_ip(ifaces, i);
1685                         status = add_socket_rpc_tcp_iface(dce_ctx, e, event_ctx, model_ops, address);
1686                         NT_STATUS_NOT_OK_RETURN(status);
1687                 }
1688         } else {
1689                 status = add_socket_rpc_tcp_iface(dce_ctx, e, event_ctx, model_ops, 
1690                                                   lpcfg_socket_address(lp_ctx));
1691                 NT_STATUS_NOT_OK_RETURN(status);
1692         }
1693
1694         return NT_STATUS_OK;
1695 }
1696
1697 NTSTATUS dcesrv_add_ep(struct dcesrv_context *dce_ctx,
1698                        struct loadparm_context *lp_ctx,
1699                        struct dcesrv_endpoint *e,
1700                        struct tevent_context *event_ctx,
1701                        const struct model_ops *model_ops)
1702 {
1703         switch (e->ep_description->transport) {
1704         case NCACN_UNIX_STREAM:
1705                 return dcesrv_add_ep_unix(dce_ctx, lp_ctx, e, event_ctx, model_ops);
1706
1707         case NCALRPC:
1708                 return dcesrv_add_ep_ncalrpc(dce_ctx, lp_ctx, e, event_ctx, model_ops);
1709
1710         case NCACN_IP_TCP:
1711                 return dcesrv_add_ep_tcp(dce_ctx, lp_ctx, e, event_ctx, model_ops);
1712
1713         case NCACN_NP:
1714                 return dcesrv_add_ep_np(dce_ctx, lp_ctx, e, event_ctx, model_ops);
1715
1716         default:
1717                 return NT_STATUS_NOT_SUPPORTED;
1718         }
1719 }