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