r4358: At metze's request, the Christmas elves have removed gensec_end in
[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
7    Copyright (C) Stefan (metze) Metzmacher 2004
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 2 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, write to the Free Software
21    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
22 */
23
24 #include "includes.h"
25 #include "librpc/gen_ndr/ndr_epmapper.h"
26 #include "librpc/gen_ndr/ndr_oxidresolver.h"
27 #include "auth/auth.h"
28 #include "dlinklist.h"
29 #include "rpc_server/dcerpc_server.h"
30
31 /*
32   see if two endpoints match
33 */
34 static BOOL endpoints_match(const struct dcerpc_binding *ep1,
35                             const struct dcerpc_binding *ep2)
36 {
37         if (ep1->transport != ep2->transport) {
38                 return False;
39         }
40
41         if (!ep1->endpoint || !ep2->endpoint) {
42                 return ep1->endpoint == ep2->endpoint;
43         }
44
45         if (strcasecmp(ep1->endpoint, ep2->endpoint) != 0) 
46                 return False;
47
48         return True;
49 }
50
51 /*
52   find an endpoint in the dcesrv_context
53 */
54 static struct dcesrv_endpoint *find_endpoint(struct dcesrv_context *dce_ctx,
55                                              const struct dcerpc_binding *ep_description)
56 {
57         struct dcesrv_endpoint *ep;
58         for (ep=dce_ctx->endpoint_list; ep; ep=ep->next) {
59                 if (endpoints_match(&ep->ep_description, ep_description)) {
60                         return ep;
61                 }
62         }
63         return NULL;
64 }
65
66 /*
67   see if a uuid and if_version match to an interface
68 */
69 static BOOL interface_match(const struct dcesrv_interface *if1,
70                                                         const struct dcesrv_interface *if2)
71 {
72         if (if1->if_version != if2->if_version) {
73                 return False;
74         }
75
76         if (strcmp(if1->uuid, if2->uuid)==0) {
77                 return True;
78         }                       
79
80         return False;
81 }
82
83 /*
84   find the interface operations on an endpoint
85 */
86 static const struct dcesrv_interface *find_interface(const struct dcesrv_endpoint *endpoint,
87                                                        const struct dcesrv_interface *iface)
88 {
89         struct dcesrv_if_list *ifl;
90         for (ifl=endpoint->interface_list; ifl; ifl=ifl->next) {
91                 if (interface_match(&(ifl->iface), iface)) {
92                         return &(ifl->iface);
93                 }
94         }
95         return NULL;
96 }
97
98 /*
99   see if a uuid and if_version match to an interface
100 */
101 static BOOL interface_match_by_uuid(const struct dcesrv_interface *iface,
102                                     const char *uuid, uint32_t if_version)
103 {
104         if (iface->if_version != if_version) {
105                 return False;
106         }
107
108         if (strcmp(iface->uuid, uuid)==0) {
109                 return True;
110         }                       
111
112         return False;
113 }
114
115 /*
116   find the interface operations on an endpoint by uuid
117 */
118 static const struct dcesrv_interface *find_interface_by_uuid(const struct dcesrv_endpoint *endpoint,
119                                                              const char *uuid, uint32_t if_version)
120 {
121         struct dcesrv_if_list *ifl;
122         for (ifl=endpoint->interface_list; ifl; ifl=ifl->next) {
123                 if (interface_match_by_uuid(&(ifl->iface), uuid, if_version)) {
124                         return &(ifl->iface);
125                 }
126         }
127         return NULL;
128 }
129
130 /*
131   find a call that is pending in our call list
132 */
133 static struct dcesrv_call_state *dcesrv_find_call(struct dcesrv_connection *dce_conn, uint16_t call_id)
134 {
135         struct dcesrv_call_state *c;
136         for (c=dce_conn->call_list;c;c=c->next) {
137                 if (c->pkt.call_id == call_id) {
138                         return c;
139                 }
140         }
141         return NULL;
142 }
143
144 /*
145   register an interface on an endpoint
146 */
147 NTSTATUS dcesrv_interface_register(struct dcesrv_context *dce_ctx,
148                                    const char *ep_name,
149                                    const struct dcesrv_interface *iface,
150                                    const struct security_descriptor *sd)
151 {
152         struct dcesrv_endpoint *ep;
153         struct dcesrv_if_list *ifl;
154         struct dcerpc_binding binding;
155         BOOL add_ep = False;
156         NTSTATUS status;
157         
158         status = dcerpc_parse_binding(dce_ctx, ep_name, &binding);
159
160         if (NT_STATUS_IS_ERR(status)) {
161                 DEBUG(0, ("Trouble parsing binding string '%s'\n", ep_name));
162                 return status;
163         }
164
165         /* check if this endpoint exists
166          */
167         if ((ep=find_endpoint(dce_ctx, &binding))==NULL) {
168                 ep = talloc_p(dce_ctx, struct dcesrv_endpoint);
169                 if (!ep) {
170                         return NT_STATUS_NO_MEMORY;
171                 }
172                 ZERO_STRUCTP(ep);
173                 ep->ep_description = binding;
174                 add_ep = True;
175         }
176
177         /* see if the interface is already registered on te endpoint */
178         if (find_interface(ep, iface)!=NULL) {
179                 DEBUG(0,("dcesrv_interface_register: interface '%s' already registered on endpoint '%s'\n",
180                         iface->name, ep_name));
181                 return NT_STATUS_OBJECT_NAME_COLLISION;
182         }
183
184         /* talloc a new interface list element */
185         ifl = talloc_p(dce_ctx, struct dcesrv_if_list);
186         if (!ifl) {
187                 return NT_STATUS_NO_MEMORY;
188         }
189
190         /* copy the given interface struct to the one on the endpoints interface list */
191         memcpy(&(ifl->iface),iface, sizeof(struct dcesrv_interface));
192
193         /* if we have a security descriptor given,
194          * we should see if we can set it up on the endpoint
195          */
196         if (sd != NULL) {
197                 /* if there's currently no security descriptor given on the endpoint
198                  * we try to set it
199                  */
200                 if (ep->sd == NULL) {
201                         ep->sd = security_descriptor_copy(dce_ctx, sd);
202                 }
203
204                 /* if now there's no security descriptor given on the endpoint
205                  * something goes wrong, either we failed to copy the security descriptor
206                  * or there was already one on the endpoint
207                  */
208                 if (ep->sd != NULL) {
209                         DEBUG(0,("dcesrv_interface_register: interface '%s' failed to setup a security descriptor\n"
210                                  "                           on endpoint '%s'\n",
211                                 iface->name, ep_name));
212                         if (add_ep) free(ep);
213                         free(ifl);
214                         return NT_STATUS_OBJECT_NAME_COLLISION;
215                 }
216         }
217
218         /* finally add the interface on the endpoint */
219         DLIST_ADD(ep->interface_list, ifl);
220
221         /* if it's a new endpoint add it to the dcesrv_context */
222         if (add_ep) {
223                 DLIST_ADD(dce_ctx->endpoint_list, ep);
224         }
225
226         DEBUG(4,("dcesrv_interface_register: interface '%s' registered on endpoint '%s'\n",
227                 iface->name, ep_name));
228
229         return NT_STATUS_OK;
230 }
231
232 static NTSTATUS dcesrv_inherited_session_key(struct dcesrv_connection *p,
233                                               DATA_BLOB *session_key)
234 {
235         if (p->auth_state.session_info->session_key.length) {
236                 *session_key = p->auth_state.session_info->session_key;
237                 return NT_STATUS_OK;
238         }
239         return NT_STATUS_NO_USER_SESSION_KEY;
240 }
241
242 NTSTATUS dcesrv_generic_session_key(struct dcesrv_connection *p,
243                                     DATA_BLOB *session_key)
244 {
245         /* this took quite a few CPU cycles to find ... */
246         session_key->data = discard_const_p(uint8_t, "SystemLibraryDTC");
247         session_key->length = 16;
248         return NT_STATUS_OK;
249 }
250
251 /*
252   fetch the user session key - may be default (above) or the SMB session key
253 */
254 NTSTATUS dcesrv_fetch_session_key(struct dcesrv_connection *p,
255                                   DATA_BLOB *session_key)
256 {
257         return p->auth_state.session_key(p, session_key);
258 }
259
260
261 /*
262   destroy a link to an endpoint
263 */
264 static int dcesrv_endpoint_destructor(void *ptr)
265 {
266         struct dcesrv_connection *p = ptr;
267         if (p->iface) {
268                 p->iface->unbind(p, p->iface);
269         }
270
271         /* destroy any handles */
272         while (p->handles) {
273                 dcesrv_handle_destroy(p, p->handles);
274         }
275
276         if (p->auth_state.gensec_security) {
277                 talloc_free(p->auth_state.gensec_security);
278                 p->auth_state.gensec_security = NULL;
279         }
280
281         return 0;
282 }
283
284
285 /*
286   connect to a dcerpc endpoint
287 */
288 NTSTATUS dcesrv_endpoint_connect(struct dcesrv_context *dce_ctx,
289                                  const struct dcesrv_endpoint *ep,
290                                  struct dcesrv_connection **p)
291 {
292         *p = talloc_p(dce_ctx, struct dcesrv_connection);
293         if (! *p) {
294                 return NT_STATUS_NO_MEMORY;
295         }
296
297         (*p)->dce_ctx = dce_ctx;
298         (*p)->endpoint = ep;
299         (*p)->iface = NULL;
300         (*p)->private = NULL;
301         (*p)->call_list = NULL;
302         (*p)->cli_max_recv_frag = 0;
303         (*p)->handles = NULL;
304         (*p)->partial_input = data_blob(NULL, 0);
305         (*p)->auth_state.auth_info = NULL;
306         (*p)->auth_state.gensec_security = NULL;
307         (*p)->auth_state.session_info = NULL;
308         (*p)->auth_state.session_key = dcesrv_generic_session_key;
309         (*p)->srv_conn = NULL;
310
311         talloc_set_destructor(*p, dcesrv_endpoint_destructor);
312
313         return NT_STATUS_OK;
314 }
315
316 /*
317   search and connect to a dcerpc endpoint
318 */
319 NTSTATUS dcesrv_endpoint_search_connect(struct dcesrv_context *dce_ctx,
320                                         const struct dcerpc_binding *ep_description,
321                                         struct auth_session_info *session_info,
322                                         struct dcesrv_connection **dce_conn_p)
323 {
324         NTSTATUS status;
325         const struct dcesrv_endpoint *ep;
326
327         /* make sure this endpoint exists */
328         ep = find_endpoint(dce_ctx, ep_description);
329         if (!ep) {
330                 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
331         }
332
333         status = dcesrv_endpoint_connect(dce_ctx, ep, dce_conn_p);
334         if (!NT_STATUS_IS_OK(status)) {
335                 return status;
336         }
337
338         session_info->refcount++;
339         (*dce_conn_p)->auth_state.session_info = session_info;
340         (*dce_conn_p)->auth_state.session_key = dcesrv_inherited_session_key;
341
342         /* TODO: check security descriptor of the endpoint here 
343          *       if it's a smb named pipe
344          *       if it's failed free dce_conn_p
345          */
346
347         return NT_STATUS_OK;
348 }
349
350
351 static void dcesrv_init_hdr(struct dcerpc_packet *pkt)
352 {
353         pkt->rpc_vers = 5;
354         pkt->rpc_vers_minor = 0;
355         if (lp_rpc_big_endian()) {
356                 pkt->drep[0] = 0;
357         } else {
358                 pkt->drep[0] = DCERPC_DREP_LE;
359         }
360         pkt->drep[1] = 0;
361         pkt->drep[2] = 0;
362         pkt->drep[3] = 0;
363 }
364
365 /*
366   return a dcerpc fault
367 */
368 static NTSTATUS dcesrv_fault(struct dcesrv_call_state *call, uint32_t fault_code)
369 {
370         struct dcerpc_packet pkt;
371         struct dcesrv_call_reply *rep;
372         NTSTATUS status;
373
374         /* setup a bind_ack */
375         dcesrv_init_hdr(&pkt);
376         pkt.auth_length = 0;
377         pkt.call_id = call->pkt.call_id;
378         pkt.ptype = DCERPC_PKT_FAULT;
379         pkt.pfc_flags = DCERPC_PFC_FLAG_FIRST | DCERPC_PFC_FLAG_LAST;
380         pkt.u.fault.alloc_hint = 0;
381         pkt.u.fault.context_id = 0;
382         pkt.u.fault.cancel_count = 0;
383         pkt.u.fault.status = fault_code;
384
385         rep = talloc_p(call, struct dcesrv_call_reply);
386         if (!rep) {
387                 return NT_STATUS_NO_MEMORY;
388         }
389
390         status = dcerpc_push_auth(&rep->data, call, &pkt, NULL);
391         if (!NT_STATUS_IS_OK(status)) {
392                 return status;
393         }
394
395         dcerpc_set_frag_length(&rep->data, rep->data.length);
396
397         DLIST_ADD_END(call->replies, rep, struct dcesrv_call_reply *);
398         DLIST_ADD_END(call->conn->call_list, call, struct dcesrv_call_state *);
399
400         return NT_STATUS_OK;    
401 }
402
403
404 /*
405   return a dcerpc bind_nak
406 */
407 static NTSTATUS dcesrv_bind_nak(struct dcesrv_call_state *call, uint32_t reason)
408 {
409         struct dcerpc_packet pkt;
410         struct dcesrv_call_reply *rep;
411         NTSTATUS status;
412
413         /* setup a bind_nak */
414         dcesrv_init_hdr(&pkt);
415         pkt.auth_length = 0;
416         pkt.call_id = call->pkt.call_id;
417         pkt.ptype = DCERPC_PKT_BIND_NAK;
418         pkt.pfc_flags = DCERPC_PFC_FLAG_FIRST | DCERPC_PFC_FLAG_LAST;
419         pkt.u.bind_nak.reject_reason = reason;
420         pkt.u.bind_nak.num_versions = 0;
421
422         rep = talloc_p(call, struct dcesrv_call_reply);
423         if (!rep) {
424                 return NT_STATUS_NO_MEMORY;
425         }
426
427         status = dcerpc_push_auth(&rep->data, call, &pkt, NULL);
428         if (!NT_STATUS_IS_OK(status)) {
429                 return status;
430         }
431
432         dcerpc_set_frag_length(&rep->data, rep->data.length);
433
434         DLIST_ADD_END(call->replies, rep, struct dcesrv_call_reply *);
435         DLIST_ADD_END(call->conn->call_list, call, struct dcesrv_call_state *);
436
437         return NT_STATUS_OK;    
438 }
439
440
441 /*
442   handle a bind request
443 */
444 static NTSTATUS dcesrv_bind(struct dcesrv_call_state *call)
445 {
446         const char *uuid, *transfer_syntax;
447         uint32_t if_version, transfer_syntax_version;
448         struct dcerpc_packet pkt;
449         struct dcesrv_call_reply *rep;
450         NTSTATUS status;
451         uint32_t result=0, reason=0;
452
453         if (call->pkt.u.bind.num_contexts != 1 ||
454             call->pkt.u.bind.ctx_list[0].num_transfer_syntaxes < 1) {
455                 return dcesrv_bind_nak(call, 0);
456         }
457
458         if_version = call->pkt.u.bind.ctx_list[0].abstract_syntax.if_version;
459         uuid = GUID_string(call, &call->pkt.u.bind.ctx_list[0].abstract_syntax.uuid);
460         if (!uuid) {
461                 return dcesrv_bind_nak(call, 0);
462         }
463
464         transfer_syntax_version = call->pkt.u.bind.ctx_list[0].transfer_syntaxes[0].if_version;
465         transfer_syntax = GUID_string(call, 
466                                       &call->pkt.u.bind.ctx_list[0].transfer_syntaxes[0].uuid);
467         if (!transfer_syntax ||
468             strcasecmp(NDR_GUID, transfer_syntax) != 0 ||
469             NDR_GUID_VERSION != transfer_syntax_version) {
470                 /* we only do NDR encoded dcerpc */
471                 return dcesrv_bind_nak(call, 0);
472         }
473
474         call->conn->iface = find_interface_by_uuid(call->conn->endpoint, uuid, if_version);
475         if (!call->conn->iface) {
476                 DEBUG(2,("Request for unknown dcerpc interface %s/%d\n", uuid, if_version));
477                 /* we don't know about that interface */
478                 result = DCERPC_BIND_PROVIDER_REJECT;
479                 reason = DCERPC_BIND_REASON_ASYNTAX;            
480         }
481
482         if (call->conn->cli_max_recv_frag == 0) {
483                 call->conn->cli_max_recv_frag = call->pkt.u.bind.max_recv_frag;
484         }
485
486         /* handle any authentication that is being requested */
487         if (!dcesrv_auth_bind(call)) {
488                 /* TODO: work out the right reject code */
489                 return dcesrv_bind_nak(call, 0);
490         }
491
492         /* setup a bind_ack */
493         dcesrv_init_hdr(&pkt);
494         pkt.auth_length = 0;
495         pkt.call_id = call->pkt.call_id;
496         pkt.ptype = DCERPC_PKT_BIND_ACK;
497         pkt.pfc_flags = DCERPC_PFC_FLAG_FIRST | DCERPC_PFC_FLAG_LAST;
498         pkt.u.bind_ack.max_xmit_frag = 0x2000;
499         pkt.u.bind_ack.max_recv_frag = 0x2000;
500         pkt.u.bind_ack.assoc_group_id = call->pkt.u.bind.assoc_group_id;
501         if (call->conn->iface) {
502                 /* FIXME: Use pipe name as specified by endpoint instead of interface name */
503                 pkt.u.bind_ack.secondary_address = talloc_asprintf(call, "\\PIPE\\%s", 
504                                                                    call->conn->iface->name);
505         } else {
506                 pkt.u.bind_ack.secondary_address = "";
507         }
508         pkt.u.bind_ack.num_results = 1;
509         pkt.u.bind_ack.ctx_list = talloc_p(call, struct dcerpc_ack_ctx);
510         if (!pkt.u.bind_ack.ctx_list) {
511                 return NT_STATUS_NO_MEMORY;
512         }
513         pkt.u.bind_ack.ctx_list[0].result = result;
514         pkt.u.bind_ack.ctx_list[0].reason = reason;
515         GUID_from_string(NDR_GUID, &pkt.u.bind_ack.ctx_list[0].syntax.uuid);
516         pkt.u.bind_ack.ctx_list[0].syntax.if_version = NDR_GUID_VERSION;
517         pkt.u.bind_ack.auth_info = data_blob(NULL, 0);
518
519         if (!dcesrv_auth_bind_ack(call, &pkt)) {
520                 return dcesrv_bind_nak(call, 0);
521         }
522
523         if (call->conn->iface) {
524                 status = call->conn->iface->bind(call, call->conn->iface);
525                 if (!NT_STATUS_IS_OK(status)) {
526                         DEBUG(2,("Request for dcerpc interface %s/%d rejected: %s\n", uuid, if_version, nt_errstr(status)));
527                         return dcesrv_bind_nak(call, 0);
528                 }
529         }
530
531         rep = talloc_p(call, struct dcesrv_call_reply);
532         if (!rep) {
533                 return NT_STATUS_NO_MEMORY;
534         }
535
536         status = dcerpc_push_auth(&rep->data, call, &pkt, 
537                                   call->conn->auth_state.auth_info);
538         if (!NT_STATUS_IS_OK(status)) {
539                 return status;
540         }
541
542         dcerpc_set_frag_length(&rep->data, rep->data.length);
543
544         DLIST_ADD_END(call->replies, rep, struct dcesrv_call_reply *);
545         DLIST_ADD_END(call->conn->call_list, call, struct dcesrv_call_state *);
546
547         return NT_STATUS_OK;
548 }
549
550
551 /*
552   handle a auth3 request
553 */
554 static NTSTATUS dcesrv_auth3(struct dcesrv_call_state *call)
555 {
556         /* handle the auth3 in the auth code */
557         if (!dcesrv_auth_auth3(call)) {
558                 return dcesrv_fault(call, DCERPC_FAULT_OTHER);
559         }
560
561         talloc_free(call);
562
563         /* we don't send a reply to a auth3 request, except by a
564            fault */
565         return NT_STATUS_OK;
566 }
567
568 /*
569   handle a bind request
570 */
571 static NTSTATUS dcesrv_alter(struct dcesrv_call_state *call)
572 {
573         struct dcerpc_packet pkt;
574         struct dcesrv_call_reply *rep;
575         NTSTATUS status;
576         uint32_t result=0, reason=0;
577
578         /* handle any authentication that is being requested */
579         if (!dcesrv_auth_alter(call)) {
580                 /* TODO: work out the right reject code */
581                 return dcesrv_bind_nak(call, 0);
582         }
583
584         /* setup a alter_ack */
585         dcesrv_init_hdr(&pkt);
586         pkt.auth_length = 0;
587         pkt.call_id = call->pkt.call_id;
588         pkt.ptype = DCERPC_PKT_ALTER_ACK;
589         pkt.pfc_flags = DCERPC_PFC_FLAG_FIRST | DCERPC_PFC_FLAG_LAST;
590         pkt.u.alter_ack.max_xmit_frag = 0x2000;
591         pkt.u.alter_ack.max_recv_frag = 0x2000;
592         pkt.u.alter_ack.assoc_group_id = call->pkt.u.bind.assoc_group_id;
593         pkt.u.alter_ack.secondary_address = NULL;
594         pkt.u.alter_ack.num_results = 1;
595         pkt.u.alter_ack.ctx_list = talloc_p(call, struct dcerpc_ack_ctx);
596         if (!pkt.u.alter_ack.ctx_list) {
597                 return NT_STATUS_NO_MEMORY;
598         }
599         pkt.u.alter_ack.ctx_list[0].result = result;
600         pkt.u.alter_ack.ctx_list[0].reason = reason;
601         GUID_from_string(NDR_GUID, &pkt.u.alter_ack.ctx_list[0].syntax.uuid);
602         pkt.u.alter_ack.ctx_list[0].syntax.if_version = NDR_GUID_VERSION;
603         pkt.u.alter_ack.auth_info = data_blob(NULL, 0);
604
605         if (!dcesrv_auth_alter_ack(call, &pkt)) {
606                 return dcesrv_bind_nak(call, 0);
607         }
608
609         rep = talloc_p(call, struct dcesrv_call_reply);
610         if (!rep) {
611                 return NT_STATUS_NO_MEMORY;
612         }
613
614         status = dcerpc_push_auth(&rep->data, call, &pkt, 
615                                   call->conn->auth_state.auth_info);
616         if (!NT_STATUS_IS_OK(status)) {
617                 return status;
618         }
619
620         dcerpc_set_frag_length(&rep->data, rep->data.length);
621
622         DLIST_ADD_END(call->replies, rep, struct dcesrv_call_reply *);
623         DLIST_ADD_END(call->conn->call_list, call, struct dcesrv_call_state *);
624
625         return NT_STATUS_OK;
626 }
627
628 /*
629   handle a dcerpc request packet
630 */
631 static NTSTATUS dcesrv_request(struct dcesrv_call_state *call)
632 {
633         struct ndr_pull *pull;
634         struct ndr_push *push;
635         void *r;
636         NTSTATUS status;
637         DATA_BLOB stub;
638         uint32_t total_length;
639
640         call->fault_code = 0;
641
642         if (!call->conn->iface) {
643                 return dcesrv_fault(call, DCERPC_FAULT_UNK_IF);
644         }
645
646         pull = ndr_pull_init_blob(&call->pkt.u.request.stub_and_verifier, call);
647         if (!pull) {
648                 return NT_STATUS_NO_MEMORY;
649         }
650
651         if (call->pkt.pfc_flags & DCERPC_PFC_FLAG_ORPC) {
652                 pull->flags |= LIBNDR_FLAG_OBJECT_PRESENT;
653         }
654
655         if (!(call->pkt.drep[0] & DCERPC_DREP_LE)) {
656                 pull->flags |= LIBNDR_FLAG_BIGENDIAN;
657         }
658
659         /* unravel the NDR for the packet */
660         status = call->conn->iface->ndr_pull(call, call, pull, &r);
661         if (!NT_STATUS_IS_OK(status)) {
662                 return dcesrv_fault(call, call->fault_code);
663         }
664
665         if (pull->offset != pull->data_size) {
666                 DEBUG(3,("Warning: %d extra bytes in incoming RPC request\n", 
667                          pull->data_size - pull->offset));
668                 dump_data(10, pull->data+pull->offset, pull->data_size - pull->offset);
669         }
670
671         /* call the dispatch function */
672         status = call->conn->iface->dispatch(call, call, r);
673         if (!NT_STATUS_IS_OK(status)) {
674                 return dcesrv_fault(call, call->fault_code);
675         }
676
677         /* form the reply NDR */
678         push = ndr_push_init_ctx(call);
679         if (!push) {
680                 return NT_STATUS_NO_MEMORY;
681         }
682
683         /* carry over the pointer count to the reply in case we are
684            using full pointer. See NDR specification for full
685            pointers */
686         push->ptr_count = pull->ptr_count;
687
688         if (lp_rpc_big_endian()) {
689                 push->flags |= LIBNDR_FLAG_BIGENDIAN;
690         }
691
692         status = call->conn->iface->ndr_push(call, call, push, r);
693         if (!NT_STATUS_IS_OK(status)) {
694                 return dcesrv_fault(call, call->fault_code);
695         }
696
697         stub = ndr_push_blob(push);
698
699         total_length = stub.length;
700
701         do {
702                 uint32_t length;
703                 struct dcesrv_call_reply *rep;
704                 struct dcerpc_packet pkt;
705
706                 rep = talloc_p(call, struct dcesrv_call_reply);
707                 if (!rep) {
708                         return NT_STATUS_NO_MEMORY;
709                 }
710
711                 length = stub.length;
712                 if (length + DCERPC_RESPONSE_LENGTH > call->conn->cli_max_recv_frag) {
713                         /* the 32 is to cope with signing data */
714                         length = call->conn->cli_max_recv_frag - 
715                                 (DCERPC_MAX_SIGN_SIZE+DCERPC_RESPONSE_LENGTH);
716                 }
717
718                 /* form the dcerpc response packet */
719                 dcesrv_init_hdr(&pkt);
720                 pkt.auth_length = 0;
721                 pkt.call_id = call->pkt.call_id;
722                 pkt.ptype = DCERPC_PKT_RESPONSE;
723                 pkt.pfc_flags = 0;
724                 if (stub.length == total_length) {
725                         pkt.pfc_flags |= DCERPC_PFC_FLAG_FIRST;
726                 }
727                 if (length == stub.length) {
728                         pkt.pfc_flags |= DCERPC_PFC_FLAG_LAST;
729                 }
730                 pkt.u.response.alloc_hint = stub.length;
731                 pkt.u.response.context_id = call->pkt.u.request.context_id;
732                 pkt.u.response.cancel_count = 0;
733                 pkt.u.response.stub_and_verifier.data = stub.data;
734                 pkt.u.response.stub_and_verifier.length = length;
735
736                 if (!dcesrv_auth_response(call, &rep->data, &pkt)) {
737                         return dcesrv_fault(call, DCERPC_FAULT_OTHER);          
738                 }
739
740                 dcerpc_set_frag_length(&rep->data, rep->data.length);
741
742                 DLIST_ADD_END(call->replies, rep, struct dcesrv_call_reply *);
743                 
744                 stub.data += length;
745                 stub.length -= length;
746         } while (stub.length != 0);
747
748         DLIST_ADD_END(call->conn->call_list, call, struct dcesrv_call_state *);
749
750         return NT_STATUS_OK;
751 }
752
753
754 /*
755   work out if we have a full packet yet
756 */
757 static BOOL dce_full_packet(const DATA_BLOB *data)
758 {
759         if (data->length < DCERPC_FRAG_LEN_OFFSET+2) {
760                 return False;
761         }
762         if (dcerpc_get_frag_length(data) > data->length) {
763                 return False;
764         }
765         return True;
766 }
767
768 /*
769   we might have consumed only part of our input - advance past that part
770 */
771 static void dce_partial_advance(struct dcesrv_connection *dce_conn, uint32_t offset)
772 {
773         DATA_BLOB blob;
774
775         if (dce_conn->partial_input.length == offset) {
776                 data_blob_free(&dce_conn->partial_input);
777                 return;
778         }
779
780         blob = dce_conn->partial_input;
781         dce_conn->partial_input = data_blob(blob.data + offset,
782                                             blob.length - offset);
783         data_blob_free(&blob);
784 }
785
786 /*
787   process some input to a dcerpc endpoint server.
788 */
789 NTSTATUS dcesrv_input_process(struct dcesrv_connection *dce_conn)
790 {
791         struct ndr_pull *ndr;
792         NTSTATUS status;
793         struct dcesrv_call_state *call;
794         DATA_BLOB blob;
795
796         call = talloc_p(dce_conn, struct dcesrv_call_state);
797         if (!call) {
798                 talloc_free(dce_conn->partial_input.data);
799                 return NT_STATUS_NO_MEMORY;
800         }
801         call->conn = dce_conn;
802         call->replies = NULL;
803
804         blob = dce_conn->partial_input;
805         blob.length = dcerpc_get_frag_length(&blob);
806
807         ndr = ndr_pull_init_blob(&blob, call);
808         if (!ndr) {
809                 talloc_free(dce_conn->partial_input.data);
810                 talloc_free(call);
811                 return NT_STATUS_NO_MEMORY;
812         }
813
814         if (!(CVAL(blob.data, DCERPC_DREP_OFFSET) & DCERPC_DREP_LE)) {
815                 ndr->flags |= LIBNDR_FLAG_BIGENDIAN;
816         }
817
818         status = ndr_pull_dcerpc_packet(ndr, NDR_SCALARS|NDR_BUFFERS, &call->pkt);
819         if (!NT_STATUS_IS_OK(status)) {
820                 talloc_free(dce_conn->partial_input.data);
821                 talloc_free(call);
822                 return status;
823         }
824
825         /* we have to check the signing here, before combining the
826            pdus */
827         if (call->pkt.ptype == DCERPC_PKT_REQUEST &&
828             !dcesrv_auth_request(call, &blob)) {
829                 dce_partial_advance(dce_conn, blob.length);
830                 return dcesrv_fault(call, DCERPC_FAULT_LOGON_FAILURE);          
831         }
832
833         dce_partial_advance(dce_conn, blob.length);
834
835         /* see if this is a continued packet */
836         if (call->pkt.ptype == DCERPC_PKT_REQUEST &&
837             !(call->pkt.pfc_flags & DCERPC_PFC_FLAG_FIRST)) {
838                 struct dcesrv_call_state *call2 = call;
839                 uint32_t alloc_size;
840
841                 /* we only allow fragmented requests, no other packet types */
842                 if (call->pkt.ptype != DCERPC_PKT_REQUEST) {
843                         return dcesrv_fault(call2, DCERPC_FAULT_OTHER);
844                 }
845
846                 /* this is a continuation of an existing call - find the call then
847                    tack it on the end */
848                 call = dcesrv_find_call(dce_conn, call2->pkt.call_id);
849                 if (!call) {
850                         return dcesrv_fault(call2, DCERPC_FAULT_OTHER);
851                 }
852
853                 if (call->pkt.ptype != call2->pkt.ptype) {
854                         /* trying to play silly buggers are we? */
855                         return dcesrv_fault(call2, DCERPC_FAULT_OTHER);
856                 }
857
858                 alloc_size = call->pkt.u.request.stub_and_verifier.length +
859                         call2->pkt.u.request.stub_and_verifier.length;
860                 if (call->pkt.u.request.alloc_hint > alloc_size) {
861                         alloc_size = call->pkt.u.request.alloc_hint;
862                 }
863
864                 call->pkt.u.request.stub_and_verifier.data = 
865                         talloc_realloc(call, call->pkt.u.request.stub_and_verifier.data, alloc_size);
866                 if (!call->pkt.u.request.stub_and_verifier.data) {
867                         return dcesrv_fault(call2, DCERPC_FAULT_OTHER);
868                 }
869                 memcpy(call->pkt.u.request.stub_and_verifier.data +
870                        call->pkt.u.request.stub_and_verifier.length,
871                        call2->pkt.u.request.stub_and_verifier.data,
872                        call2->pkt.u.request.stub_and_verifier.length);
873                 call->pkt.u.request.stub_and_verifier.length += 
874                         call2->pkt.u.request.stub_and_verifier.length;
875
876                 call->pkt.pfc_flags |= (call2->pkt.pfc_flags & DCERPC_PFC_FLAG_LAST);
877
878                 talloc_free(call2);
879         }
880
881         /* this may not be the last pdu in the chain - if its isn't then
882            just put it on the call_list and wait for the rest */
883         if (call->pkt.ptype == DCERPC_PKT_REQUEST &&
884             !(call->pkt.pfc_flags & DCERPC_PFC_FLAG_LAST)) {
885                 DLIST_ADD_END(dce_conn->call_list, call, struct dcesrv_call_state *);
886                 return NT_STATUS_OK;
887         }
888
889         switch (call->pkt.ptype) {
890         case DCERPC_PKT_BIND:
891                 status = dcesrv_bind(call);
892                 break;
893         case DCERPC_PKT_AUTH3:
894                 status = dcesrv_auth3(call);
895                 break;
896         case DCERPC_PKT_ALTER:
897                 status = dcesrv_alter(call);
898                 break;
899         case DCERPC_PKT_REQUEST:
900                 status = dcesrv_request(call);
901                 break;
902         default:
903                 status = NT_STATUS_INVALID_PARAMETER;
904                 break;
905         }
906
907         /* if we are going to be sending a reply then add
908            it to the list of pending calls. We add it to the end to keep the call
909            list in the order we will answer */
910         if (!NT_STATUS_IS_OK(status)) {
911                 talloc_free(call);
912         }
913
914         return status;
915 }
916
917
918 /*
919   provide some input to a dcerpc endpoint server. This passes data
920   from a dcerpc client into the server
921 */
922 NTSTATUS dcesrv_input(struct dcesrv_connection *dce_conn, const DATA_BLOB *data)
923 {
924         NTSTATUS status;
925
926         dce_conn->partial_input.data = talloc_realloc(dce_conn,
927                                                       dce_conn->partial_input.data,
928                                                       dce_conn->partial_input.length + data->length);
929         if (!dce_conn->partial_input.data) {
930                 return NT_STATUS_NO_MEMORY;
931         }
932         memcpy(dce_conn->partial_input.data + dce_conn->partial_input.length,
933                data->data, data->length);
934         dce_conn->partial_input.length += data->length;
935
936         while (dce_full_packet(&dce_conn->partial_input)) {
937                 status = dcesrv_input_process(dce_conn);
938                 if (!NT_STATUS_IS_OK(status)) {
939                         return status;
940                 }
941         }
942
943         return NT_STATUS_OK;
944 }
945
946 /*
947   retrieve some output from a dcerpc server
948   The caller supplies a function that will be called to do the
949   actual output. 
950
951   The first argument to write_fn() will be 'private', the second will
952   be a pointer to a buffer containing the data to be sent and the 3rd
953   will be the number of bytes to be sent.
954
955   write_fn() should return the number of bytes successfully written.
956
957   this will return STATUS_BUFFER_OVERFLOW if there is more to be read
958   from the current fragment
959 */
960 NTSTATUS dcesrv_output(struct dcesrv_connection *dce_conn, 
961                        void *private,
962                        ssize_t (*write_fn)(void *, DATA_BLOB *))
963 {
964         struct dcesrv_call_state *call;
965         struct dcesrv_call_reply *rep;
966         ssize_t nwritten;
967
968         call = dce_conn->call_list;
969         if (!call || !call->replies) {
970                 return NT_STATUS_FOOBAR;
971         }
972         rep = call->replies;
973
974         nwritten = write_fn(private, &rep->data);
975         if (nwritten == -1) {
976                 /* TODO: hmm, how do we cope with this? destroy the
977                    connection perhaps? */
978                 return NT_STATUS_UNSUCCESSFUL;
979         }
980
981         rep->data.length -= nwritten;
982         rep->data.data += nwritten;
983
984         if (rep->data.length == 0) {
985                 /* we're done with this section of the call */
986                 DLIST_REMOVE(call->replies, rep);
987         } else {
988                 return STATUS_BUFFER_OVERFLOW;
989         }
990
991         if (call->replies == NULL) {
992                 /* we're done with the whole call */
993                 DLIST_REMOVE(dce_conn->call_list, call);
994                 talloc_free(call);
995         }
996
997         return NT_STATUS_OK;
998 }
999
1000
1001 /*
1002   write_fn() for dcesrv_output_blob()
1003 */
1004 static ssize_t dcesrv_output_blob_write_fn(void *private, DATA_BLOB *out)
1005 {
1006         DATA_BLOB *blob = private;
1007         if (out->length < blob->length) {
1008                 blob->length = out->length;
1009         }
1010         memcpy(blob->data, out->data, blob->length);
1011         return blob->length;
1012 }
1013
1014 /*
1015   a simple wrapper for dcesrv_output() for when we want to output
1016   into a data blob
1017 */
1018 NTSTATUS dcesrv_output_blob(struct dcesrv_connection *dce_conn, 
1019                             DATA_BLOB *blob)
1020 {
1021         return dcesrv_output(dce_conn, blob, dcesrv_output_blob_write_fn);
1022 }
1023
1024 /*
1025   initialise the dcerpc server context
1026 */
1027 NTSTATUS dcesrv_init_context(TALLOC_CTX *mem_ctx, struct dcesrv_context **dce_ctx)
1028 {
1029         int i;
1030         const char **endpoint_servers = lp_dcerpc_endpoint_servers();
1031
1032         (*dce_ctx) = talloc_p(mem_ctx, struct dcesrv_context);
1033         if (! *dce_ctx) {
1034                 return NT_STATUS_NO_MEMORY;
1035         }
1036
1037         (*dce_ctx)->endpoint_list = NULL;
1038
1039         if (!endpoint_servers) {
1040                 DEBUG(3,("dcesrv_init_context: no endpoint servers configured\n"));
1041                 return NT_STATUS_OK;
1042         }
1043
1044         for (i=0;endpoint_servers[i];i++) {
1045                 NTSTATUS ret;
1046                 const struct dcesrv_endpoint_server *ep_server;
1047                 
1048                 ep_server = dcesrv_ep_server_byname(endpoint_servers[i]);
1049                 if (!ep_server) {
1050                         DEBUG(0,("dcesrv_init_context: failed to find endpoint server = '%s'\n", endpoint_servers[i]));
1051                         return NT_STATUS_UNSUCCESSFUL;
1052                 }
1053
1054                 ret = ep_server->init_server(*dce_ctx, ep_server);
1055                 if (!NT_STATUS_IS_OK(ret)) {
1056                         DEBUG(0,("dcesrv_init_context: failed to init endpoint server = '%s'\n", endpoint_servers[i]));
1057                         return ret;
1058                 }
1059         }
1060
1061         return NT_STATUS_OK;
1062 }
1063
1064 static void dcesrv_init(struct server_service *service, const struct model_ops *model_ops)
1065 {
1066         struct dcesrv_context *dce_ctx;
1067         int i;
1068         const char **endpoint_servers = lp_dcerpc_endpoint_servers();
1069
1070         DEBUG(1,("dcesrv_init\n"));
1071
1072         if (!endpoint_servers) {
1073                 DEBUG(0,("dcesrv_init_context: no endpoint servers configured\n"));
1074                 return;
1075         }
1076
1077         dce_ctx = talloc_p(service, struct dcesrv_context);
1078         if (!dce_ctx) {
1079                 DEBUG(0,("talloc_p(mem_ctx, struct dcesrv_context) failed\n"));
1080                 return;
1081         }
1082
1083         ZERO_STRUCTP(dce_ctx);
1084         dce_ctx->endpoint_list  = NULL;
1085
1086         for (i=0;endpoint_servers[i];i++) {
1087                 NTSTATUS ret;
1088                 const struct dcesrv_endpoint_server *ep_server;
1089                 
1090                 ep_server = dcesrv_ep_server_byname(endpoint_servers[i]);
1091                 if (!ep_server) {
1092                         DEBUG(0,("dcesrv_init_context: failed to find endpoint server = '%s'\n", endpoint_servers[i]));
1093                         return;
1094                 }
1095
1096                 ret = ep_server->init_server(dce_ctx, ep_server);
1097                 if (!NT_STATUS_IS_OK(ret)) {
1098                         DEBUG(0,("dcesrv_init_context: failed to init endpoint server = '%s'\n", endpoint_servers[i]));
1099                         return;
1100                 }
1101         }
1102
1103         dcesrv_sock_init(service, model_ops, dce_ctx);
1104
1105         return; 
1106 }
1107
1108 static void dcesrv_accept(struct server_connection *srv_conn)
1109 {
1110         dcesrv_sock_accept(srv_conn);
1111 }
1112
1113 static void dcesrv_recv(struct server_connection *srv_conn, 
1114                         struct timeval t, uint16_t flags)
1115 {
1116         dcesrv_sock_recv(srv_conn, t, flags);
1117 }
1118
1119 static void dcesrv_send(struct server_connection *srv_conn, 
1120                         struct timeval t, uint16_t flags)
1121 {
1122         dcesrv_sock_send(srv_conn, t, flags);
1123 }
1124
1125 static void dcesrv_close(struct server_connection *srv_conn, const char *reason)
1126 {
1127         dcesrv_sock_close(srv_conn, reason);
1128         return; 
1129 }
1130
1131 static void dcesrv_exit(struct server_service *service, const char *reason)
1132 {
1133         dcesrv_sock_exit(service, reason);
1134         return; 
1135 }
1136
1137 /* the list of currently registered DCERPC endpoint servers.
1138  */
1139 static struct ep_server {
1140         struct dcesrv_endpoint_server *ep_server;
1141 } *ep_servers = NULL;
1142 static int num_ep_servers;
1143
1144 /*
1145   register a DCERPC endpoint server. 
1146
1147   The 'name' can be later used by other backends to find the operations
1148   structure for this backend.  
1149
1150   The 'type' is used to specify whether this is for a disk, printer or IPC$ share
1151 */
1152 NTSTATUS dcerpc_register_ep_server(const void *_ep_server)
1153 {
1154         const struct dcesrv_endpoint_server *ep_server = _ep_server;
1155         
1156         if (dcesrv_ep_server_byname(ep_server->name) != NULL) {
1157                 /* its already registered! */
1158                 DEBUG(0,("DCERPC endpoint server '%s' already registered\n", 
1159                          ep_server->name));
1160                 return NT_STATUS_OBJECT_NAME_COLLISION;
1161         }
1162
1163         ep_servers = realloc_p(ep_servers, struct ep_server, num_ep_servers+1);
1164         if (!ep_servers) {
1165                 smb_panic("out of memory in dcerpc_register");
1166         }
1167
1168         ep_servers[num_ep_servers].ep_server = smb_xmemdup(ep_server, sizeof(*ep_server));
1169         ep_servers[num_ep_servers].ep_server->name = smb_xstrdup(ep_server->name);
1170
1171         num_ep_servers++;
1172
1173         DEBUG(3,("DCERPC endpoint server '%s' registered\n", 
1174                  ep_server->name));
1175
1176         return NT_STATUS_OK;
1177 }
1178
1179 /*
1180   return the operations structure for a named backend of the specified type
1181 */
1182 const struct dcesrv_endpoint_server *dcesrv_ep_server_byname(const char *name)
1183 {
1184         int i;
1185
1186         for (i=0;i<num_ep_servers;i++) {
1187                 if (strcmp(ep_servers[i].ep_server->name, name) == 0) {
1188                         return ep_servers[i].ep_server;
1189                 }
1190         }
1191
1192         return NULL;
1193 }
1194
1195 /*
1196   return the DCERPC module version, and the size of some critical types
1197   This can be used by endpoint server modules to either detect compilation errors, or provide
1198   multiple implementations for different smbd compilation options in one module
1199 */
1200 const struct dcesrv_critical_sizes *dcerpc_module_version(void)
1201 {
1202         static const struct dcesrv_critical_sizes critical_sizes = {
1203                 DCERPC_MODULE_VERSION,
1204                 sizeof(struct dcesrv_context),
1205                 sizeof(struct dcesrv_endpoint),
1206                 sizeof(struct dcesrv_endpoint_server),
1207                 sizeof(struct dcesrv_interface),
1208                 sizeof(struct dcesrv_if_list),
1209                 sizeof(struct dcesrv_connection),
1210                 sizeof(struct dcesrv_call_state),
1211                 sizeof(struct dcesrv_auth),
1212                 sizeof(struct dcesrv_handle)
1213         };
1214
1215         return &critical_sizes;
1216 }
1217
1218 static const struct server_service_ops dcesrv_ops = {
1219         .name                   = "rpc",
1220         .service_init           = dcesrv_init,
1221         .accept_connection      = dcesrv_accept,
1222         .recv_handler           = dcesrv_recv,
1223         .send_handler           = dcesrv_send,
1224         .idle_handler           = NULL,
1225         .close_connection       = dcesrv_close,
1226         .service_exit           = dcesrv_exit,  
1227 };
1228
1229 const struct server_service_ops *dcesrv_get_ops(void)
1230 {
1231         return &dcesrv_ops;
1232 }
1233
1234 NTSTATUS server_service_rpc_init(void)
1235 {
1236         return NT_STATUS_OK;    
1237 }