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