s4-drs: open samdb with system credentials when authorised
[ira/wip.git] / source4 / rpc_server / service_rpc.c
1 /* 
2    Unix SMB/CIFS implementation.
3
4    smbd-specific dcerpc server code
5
6    Copyright (C) Andrew Tridgell 2003-2005
7    Copyright (C) Stefan (metze) Metzmacher 2004-2005
8    Copyright (C) Jelmer Vernooij <jelmer@samba.org> 2004,2007
9    
10    This program is free software; you can redistribute it and/or modify
11    it under the terms of the GNU General Public License as published by
12    the Free Software Foundation; either version 3 of the License, or
13    (at your option) any later version.
14    
15    This program is distributed in the hope that it will be useful,
16    but WITHOUT ANY WARRANTY; without even the implied warranty of
17    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18    GNU General Public License for more details.
19    
20    You should have received a copy of the GNU General Public License
21    along with this program.  If not, see <http://www.gnu.org/licenses/>.
22 */
23
24 #include "includes.h"
25 #include "librpc/gen_ndr/ndr_dcerpc.h"
26 #include "auth/auth.h"
27 #include "../lib/util/dlinklist.h"
28 #include "rpc_server/dcerpc_server.h"
29 #include "rpc_server/dcerpc_server_proto.h"
30 #include "smbd/service.h"
31 #include "system/filesys.h"
32 #include "lib/socket/socket.h"
33 #include "lib/messaging/irpc.h"
34 #include "system/network.h"
35 #include "lib/socket/netif.h"
36 #include "param/param.h"
37 #include "../lib/tsocket/tsocket.h"
38 #include "librpc/rpc/dcerpc_proto.h"
39 #include "../lib/util/tevent_ntstatus.h"
40 #include "libcli/raw/smb.h"
41 #include "../libcli/named_pipe_auth/npa_tstream.h"
42 #include "smbd/process_model.h"
43
44 struct dcesrv_socket_context {
45         const struct dcesrv_endpoint *endpoint;
46         struct dcesrv_context *dcesrv_ctx;
47 };
48
49 static void dcesrv_terminate_connection(struct dcesrv_connection *dce_conn, const char *reason)
50 {
51         struct stream_connection *srv_conn;
52         srv_conn = talloc_get_type(dce_conn->transport.private_data,
53                                    struct stream_connection);
54
55         stream_terminate_connection(srv_conn, reason);
56 }
57
58 static void dcesrv_sock_reply_done(struct tevent_req *subreq);
59
60 struct dcesrv_sock_reply_state {
61         struct dcesrv_connection *dce_conn;
62         struct dcesrv_call_state *call;
63         struct iovec iov;
64 };
65
66 static void dcesrv_sock_report_output_data(struct dcesrv_connection *dce_conn)
67 {
68         struct dcesrv_call_state *call;
69
70         call = dce_conn->call_list;
71         if (!call || !call->replies) {
72                 return;
73         }
74
75         while (call->replies) {
76                 struct data_blob_list_item *rep = call->replies;
77                 struct dcesrv_sock_reply_state *substate;
78                 struct tevent_req *subreq;
79
80                 substate = talloc(call, struct dcesrv_sock_reply_state);
81                 if (!substate) {
82                         dcesrv_terminate_connection(dce_conn, "no memory");
83                         return;
84                 }
85
86                 substate->dce_conn = dce_conn;
87                 substate->call = NULL;
88
89                 DLIST_REMOVE(call->replies, rep);
90
91                 if (call->replies == NULL) {
92                         substate->call = call;
93                 }
94
95                 substate->iov.iov_base = rep->blob.data;
96                 substate->iov.iov_len = rep->blob.length;
97
98                 subreq = tstream_writev_queue_send(substate,
99                                                    dce_conn->event_ctx,
100                                                    dce_conn->stream,
101                                                    dce_conn->send_queue,
102                                                    &substate->iov, 1);
103                 if (!subreq) {
104                         dcesrv_terminate_connection(dce_conn, "no memory");
105                         return;
106                 }
107                 tevent_req_set_callback(subreq, dcesrv_sock_reply_done,
108                                         substate);
109         }
110
111         DLIST_REMOVE(call->conn->call_list, call);
112         call->list = DCESRV_LIST_NONE;
113 }
114
115 static void dcesrv_sock_reply_done(struct tevent_req *subreq)
116 {
117         struct dcesrv_sock_reply_state *substate = tevent_req_callback_data(subreq,
118                                                 struct dcesrv_sock_reply_state);
119         int ret;
120         int sys_errno;
121         NTSTATUS status;
122         struct dcesrv_call_state *call = substate->call;
123
124         ret = tstream_writev_queue_recv(subreq, &sys_errno);
125         TALLOC_FREE(subreq);
126         if (ret == -1) {
127                 status = map_nt_error_from_unix(sys_errno);
128                 dcesrv_terminate_connection(substate->dce_conn, nt_errstr(status));
129                 return;
130         }
131
132         talloc_free(substate);
133         if (call) {
134                 talloc_free(call);
135         }
136 }
137
138 static struct socket_address *dcesrv_sock_get_my_addr(struct dcesrv_connection *dcesrv_conn, TALLOC_CTX *mem_ctx)
139 {
140         struct stream_connection *srv_conn;
141         srv_conn = talloc_get_type(dcesrv_conn->transport.private_data,
142                                    struct stream_connection);
143
144         return socket_get_my_addr(srv_conn->socket, mem_ctx);
145 }
146
147 static struct socket_address *dcesrv_sock_get_peer_addr(struct dcesrv_connection *dcesrv_conn, TALLOC_CTX *mem_ctx)
148 {
149         struct stream_connection *srv_conn;
150         srv_conn = talloc_get_type(dcesrv_conn->transport.private_data,
151                                    struct stream_connection);
152
153         return socket_get_peer_addr(srv_conn->socket, mem_ctx);
154 }
155
156 struct dcerpc_read_ncacn_packet_state {
157         struct {
158                 struct smb_iconv_convenience *smb_iconv_c;
159         } caller;
160         DATA_BLOB buffer;
161         struct ncacn_packet *pkt;
162 };
163
164 static int dcerpc_read_ncacn_packet_next_vector(struct tstream_context *stream,
165                                                 void *private_data,
166                                                 TALLOC_CTX *mem_ctx,
167                                                 struct iovec **_vector,
168                                                 size_t *_count);
169 static void dcerpc_read_ncacn_packet_done(struct tevent_req *subreq);
170
171 static struct tevent_req *dcerpc_read_ncacn_packet_send(TALLOC_CTX *mem_ctx,
172                                                  struct tevent_context *ev,
173                                                  struct tstream_context *stream,
174                                                  struct smb_iconv_convenience *ic)
175 {
176         struct tevent_req *req;
177         struct dcerpc_read_ncacn_packet_state *state;
178         struct tevent_req *subreq;
179
180         req = tevent_req_create(mem_ctx, &state,
181                                 struct dcerpc_read_ncacn_packet_state);
182         if (req == NULL) {
183                 return NULL;
184         }
185
186         state->caller.smb_iconv_c = ic;
187         state->buffer = data_blob_const(NULL, 0);
188         state->pkt = talloc(state, struct ncacn_packet);
189         if (tevent_req_nomem(state->pkt, req)) {
190                 goto post;
191         }
192
193         subreq = tstream_readv_pdu_send(state, ev,
194                                         stream,
195                                         dcerpc_read_ncacn_packet_next_vector,
196                                         state);
197         if (tevent_req_nomem(subreq, req)) {
198                 goto post;
199         }
200         tevent_req_set_callback(subreq, dcerpc_read_ncacn_packet_done, req);
201
202         return req;
203  post:
204         tevent_req_post(req, ev);
205         return req;
206 }
207
208 static int dcerpc_read_ncacn_packet_next_vector(struct tstream_context *stream,
209                                                 void *private_data,
210                                                 TALLOC_CTX *mem_ctx,
211                                                 struct iovec **_vector,
212                                                 size_t *_count)
213 {
214         struct dcerpc_read_ncacn_packet_state *state =
215                 talloc_get_type_abort(private_data,
216                 struct dcerpc_read_ncacn_packet_state);
217         struct iovec *vector;
218         off_t ofs = 0;
219
220         if (state->buffer.length == 0) {
221                 /* first get enough to read the fragment length */
222                 ofs = 0;
223                 state->buffer.length = DCERPC_FRAG_LEN_OFFSET + 2;
224                 state->buffer.data = talloc_array(state, uint8_t,
225                                                   state->buffer.length);
226                 if (!state->buffer.data) {
227                         return -1;
228                 }
229         } else if (state->buffer.length == (DCERPC_FRAG_LEN_OFFSET + 2)) {
230                 /* now read the fragment length and allocate the full buffer */
231                 size_t frag_len = dcerpc_get_frag_length(&state->buffer);
232
233                 ofs = state->buffer.length;
234
235                 state->buffer.data = talloc_realloc(state,
236                                                     state->buffer.data,
237                                                     uint8_t, frag_len);
238                 if (!state->buffer.data) {
239                         return -1;
240                 }
241                 state->buffer.length = frag_len;
242         } else {
243                 /* if we reach this we have a full fragment */
244                 *_vector = NULL;
245                 *_count = 0;
246                 return 0;
247         }
248
249         /* now create the vector that we want to be filled */
250         vector = talloc_array(mem_ctx, struct iovec, 1);
251         if (!vector) {
252                 return -1;
253         }
254
255         vector[0].iov_base = state->buffer.data + ofs;
256         vector[0].iov_len = state->buffer.length - ofs;
257
258         *_vector = vector;
259         *_count = 1;
260         return 0;
261 }
262
263 static void dcerpc_read_ncacn_packet_done(struct tevent_req *subreq)
264 {
265         struct tevent_req *req = tevent_req_callback_data(subreq,
266                                  struct tevent_req);
267         struct dcerpc_read_ncacn_packet_state *state = tevent_req_data(req,
268                                         struct dcerpc_read_ncacn_packet_state);
269         int ret;
270         int sys_errno;
271         struct ndr_pull *ndr;
272         enum ndr_err_code ndr_err;
273         NTSTATUS status;
274
275         ret = tstream_readv_pdu_recv(subreq, &sys_errno);
276         TALLOC_FREE(subreq);
277         if (ret == -1) {
278                 status = map_nt_error_from_unix(sys_errno);
279                 tevent_req_nterror(req, status);
280                 return;
281         }
282
283         ndr = ndr_pull_init_blob(&state->buffer,
284                                  state->pkt,
285                                  state->caller.smb_iconv_c);
286         if (tevent_req_nomem(ndr, req)) {
287                 return;
288         }
289
290         if (!(CVAL(ndr->data, DCERPC_DREP_OFFSET) & DCERPC_DREP_LE)) {
291                 ndr->flags |= LIBNDR_FLAG_BIGENDIAN;
292         }
293
294         if (CVAL(ndr->data, DCERPC_PFC_OFFSET) & DCERPC_PFC_FLAG_OBJECT_UUID) {
295                 ndr->flags |= LIBNDR_FLAG_OBJECT_PRESENT;
296         }
297
298         ndr_err = ndr_pull_ncacn_packet(ndr, NDR_SCALARS|NDR_BUFFERS, state->pkt);
299         TALLOC_FREE(ndr);
300         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
301                 status = ndr_map_error2ntstatus(ndr_err);
302                 tevent_req_nterror(req, status);
303                 return;
304         }
305
306         tevent_req_done(req);
307 }
308
309 static NTSTATUS dcerpc_read_ncacn_packet_recv(struct tevent_req *req,
310                                        TALLOC_CTX *mem_ctx,
311                                        struct ncacn_packet **pkt,
312                                        DATA_BLOB *buffer)
313 {
314         struct dcerpc_read_ncacn_packet_state *state = tevent_req_data(req,
315                                         struct dcerpc_read_ncacn_packet_state);
316         NTSTATUS status;
317
318         if (tevent_req_is_nterror(req, &status)) {
319                 tevent_req_received(req);
320                 return status;
321         }
322
323         *pkt = talloc_move(mem_ctx, &state->pkt);
324         if (buffer) {
325                 buffer->data = talloc_move(mem_ctx, &state->buffer.data);
326                 buffer->length = state->buffer.length;
327         }
328
329         tevent_req_received(req);
330         return NT_STATUS_OK;
331 }
332
333 static void dcesrv_read_fragment_done(struct tevent_req *subreq);
334
335 static void dcesrv_sock_accept(struct stream_connection *srv_conn)
336 {
337         NTSTATUS status;
338         struct dcesrv_socket_context *dcesrv_sock = 
339                 talloc_get_type(srv_conn->private_data, struct dcesrv_socket_context);
340         struct dcesrv_connection *dcesrv_conn = NULL;
341         int ret;
342         struct tevent_req *subreq;
343         struct loadparm_context *lp_ctx = dcesrv_sock->dcesrv_ctx->lp_ctx;
344
345         if (!srv_conn->session_info) {
346                 status = auth_anonymous_session_info(srv_conn,
347                                                      srv_conn->event.ctx,
348                                                      lp_ctx,
349                                                      &srv_conn->session_info);
350                 if (!NT_STATUS_IS_OK(status)) {
351                         DEBUG(0,("dcesrv_sock_accept: auth_anonymous_session_info failed: %s\n",
352                                 nt_errstr(status)));
353                         stream_terminate_connection(srv_conn, nt_errstr(status));
354                         return;
355                 }
356         }
357
358         status = dcesrv_endpoint_connect(dcesrv_sock->dcesrv_ctx,
359                                          srv_conn,
360                                          dcesrv_sock->endpoint,
361                                          srv_conn->session_info,
362                                          srv_conn->event.ctx,
363                                          srv_conn->msg_ctx,
364                                          srv_conn->server_id,
365                                          DCESRV_CALL_STATE_FLAG_MAY_ASYNC,
366                                          &dcesrv_conn);
367         if (!NT_STATUS_IS_OK(status)) {
368                 DEBUG(0,("dcesrv_sock_accept: dcesrv_endpoint_connect failed: %s\n", 
369                         nt_errstr(status)));
370                 stream_terminate_connection(srv_conn, nt_errstr(status));
371                 return;
372         }
373
374         dcesrv_conn->transport.private_data             = srv_conn;
375         dcesrv_conn->transport.report_output_data       = dcesrv_sock_report_output_data;
376         dcesrv_conn->transport.get_my_addr              = dcesrv_sock_get_my_addr;
377         dcesrv_conn->transport.get_peer_addr            = dcesrv_sock_get_peer_addr;
378
379         TALLOC_FREE(srv_conn->event.fde);
380
381         dcesrv_conn->send_queue = tevent_queue_create(dcesrv_conn, "dcesrv send queue");
382         if (!dcesrv_conn->send_queue) {
383                 status = NT_STATUS_NO_MEMORY;
384                 DEBUG(0,("dcesrv_sock_accept: tevent_queue_create(%s)\n",
385                         nt_errstr(status)));
386                 stream_terminate_connection(srv_conn, nt_errstr(status));
387                 return;
388         }
389
390         if (dcesrv_sock->endpoint->ep_description->transport == NCACN_NP) {
391                 dcesrv_conn->auth_state.session_key = dcesrv_inherited_session_key;
392                 ret = tstream_npa_existing_socket(dcesrv_conn,
393                                                   socket_get_fd(srv_conn->socket),
394                                                   FILE_TYPE_MESSAGE_MODE_PIPE,
395                                                   &dcesrv_conn->stream);
396         } else {
397                 ret = tstream_bsd_existing_socket(dcesrv_conn,
398                                                   socket_get_fd(srv_conn->socket),
399                                                   &dcesrv_conn->stream);
400         }
401         if (ret == -1) {
402                 status = map_nt_error_from_unix(errno);
403                 DEBUG(0,("dcesrv_sock_accept: failed to setup tstream: %s\n",
404                         nt_errstr(status)));
405                 stream_terminate_connection(srv_conn, nt_errstr(status));
406                 return;
407         }
408
409         srv_conn->private_data = dcesrv_conn;
410
411         irpc_add_name(srv_conn->msg_ctx, "rpc_server");
412
413         subreq = dcerpc_read_ncacn_packet_send(dcesrv_conn,
414                                                dcesrv_conn->event_ctx,
415                                                dcesrv_conn->stream,
416                                                lp_iconv_convenience(lp_ctx));
417         if (!subreq) {
418                 status = NT_STATUS_NO_MEMORY;
419                 DEBUG(0,("dcesrv_sock_accept: dcerpc_read_fragment_buffer_send(%s)\n",
420                         nt_errstr(status)));
421                 stream_terminate_connection(srv_conn, nt_errstr(status));
422                 return;
423         }
424         tevent_req_set_callback(subreq, dcesrv_read_fragment_done, dcesrv_conn);
425
426         return;
427 }
428
429 static void dcesrv_read_fragment_done(struct tevent_req *subreq)
430 {
431         struct dcesrv_connection *dce_conn = tevent_req_callback_data(subreq,
432                                              struct dcesrv_connection);
433         struct ncacn_packet *pkt;
434         DATA_BLOB buffer;
435         NTSTATUS status;
436         struct loadparm_context *lp_ctx = dce_conn->dce_ctx->lp_ctx;
437
438         status = dcerpc_read_ncacn_packet_recv(subreq, dce_conn,
439                                                &pkt, &buffer);
440         TALLOC_FREE(subreq);
441         if (!NT_STATUS_IS_OK(status)) {
442                 dcesrv_terminate_connection(dce_conn, nt_errstr(status));
443                 return;
444         }
445
446         status = dcesrv_process_ncacn_packet(dce_conn, pkt, buffer);
447         if (!NT_STATUS_IS_OK(status)) {
448                 dcesrv_terminate_connection(dce_conn, nt_errstr(status));
449                 return;
450         }
451
452         subreq = dcerpc_read_ncacn_packet_send(dce_conn,
453                                                dce_conn->event_ctx,
454                                                dce_conn->stream,
455                                                lp_iconv_convenience(lp_ctx));
456         if (!subreq) {
457                 status = NT_STATUS_NO_MEMORY;
458                 dcesrv_terminate_connection(dce_conn, nt_errstr(status));
459                 return;
460         }
461         tevent_req_set_callback(subreq, dcesrv_read_fragment_done, dce_conn);
462 }
463
464 static void dcesrv_sock_recv(struct stream_connection *conn, uint16_t flags)
465 {
466         struct dcesrv_connection *dce_conn = talloc_get_type(conn->private_data,
467                                              struct dcesrv_connection);
468         dcesrv_terminate_connection(dce_conn, "dcesrv_sock_recv triggered");
469 }
470
471 static void dcesrv_sock_send(struct stream_connection *conn, uint16_t flags)
472 {
473         struct dcesrv_connection *dce_conn = talloc_get_type(conn->private_data,
474                                              struct dcesrv_connection);
475         dcesrv_terminate_connection(dce_conn, "dcesrv_sock_send triggered");
476 }
477
478
479 static const struct stream_server_ops dcesrv_stream_ops = {
480         .name                   = "rpc",
481         .accept_connection      = dcesrv_sock_accept,
482         .recv_handler           = dcesrv_sock_recv,
483         .send_handler           = dcesrv_sock_send,
484 };
485
486
487
488 static NTSTATUS dcesrv_add_ep_unix(struct dcesrv_context *dce_ctx, 
489                                    struct loadparm_context *lp_ctx,
490                                    struct dcesrv_endpoint *e,
491                             struct tevent_context *event_ctx, const struct model_ops *model_ops)
492 {
493         struct dcesrv_socket_context *dcesrv_sock;
494         uint16_t port = 1;
495         NTSTATUS status;
496
497         dcesrv_sock = talloc(event_ctx, struct dcesrv_socket_context);
498         NT_STATUS_HAVE_NO_MEMORY(dcesrv_sock);
499
500         /* remember the endpoint of this socket */
501         dcesrv_sock->endpoint           = e;
502         dcesrv_sock->dcesrv_ctx         = talloc_reference(dcesrv_sock, dce_ctx);
503
504         status = stream_setup_socket(event_ctx, lp_ctx,
505                                      model_ops, &dcesrv_stream_ops, 
506                                      "unix", e->ep_description->endpoint, &port, 
507                                      lp_socket_options(lp_ctx), 
508                                      dcesrv_sock);
509         if (!NT_STATUS_IS_OK(status)) {
510                 DEBUG(0,("service_setup_stream_socket(path=%s) failed - %s\n",
511                          e->ep_description->endpoint, nt_errstr(status)));
512         }
513
514         return status;
515 }
516
517 static NTSTATUS dcesrv_add_ep_ncalrpc(struct dcesrv_context *dce_ctx, 
518                                       struct loadparm_context *lp_ctx,
519                                       struct dcesrv_endpoint *e,
520                                       struct tevent_context *event_ctx, const struct model_ops *model_ops)
521 {
522         struct dcesrv_socket_context *dcesrv_sock;
523         uint16_t port = 1;
524         char *full_path;
525         NTSTATUS status;
526
527         if (!e->ep_description->endpoint) {
528                 /* No identifier specified: use DEFAULT. 
529                  * DO NOT hardcode this value anywhere else. Rather, specify 
530                  * no endpoint and let the epmapper worry about it. */
531                 e->ep_description->endpoint = talloc_strdup(dce_ctx, "DEFAULT");
532         }
533
534         full_path = talloc_asprintf(dce_ctx, "%s/%s", lp_ncalrpc_dir(lp_ctx), 
535                                     e->ep_description->endpoint);
536
537         dcesrv_sock = talloc(event_ctx, struct dcesrv_socket_context);
538         NT_STATUS_HAVE_NO_MEMORY(dcesrv_sock);
539
540         /* remember the endpoint of this socket */
541         dcesrv_sock->endpoint           = e;
542         dcesrv_sock->dcesrv_ctx         = talloc_reference(dcesrv_sock, dce_ctx);
543
544         status = stream_setup_socket(event_ctx, lp_ctx,
545                                      model_ops, &dcesrv_stream_ops, 
546                                      "unix", full_path, &port, 
547                                      lp_socket_options(lp_ctx), 
548                                      dcesrv_sock);
549         if (!NT_STATUS_IS_OK(status)) {
550                 DEBUG(0,("service_setup_stream_socket(identifier=%s,path=%s) failed - %s\n",
551                          e->ep_description->endpoint, full_path, nt_errstr(status)));
552         }
553         return status;
554 }
555
556 static NTSTATUS dcesrv_add_ep_np(struct dcesrv_context *dce_ctx,
557                                  struct loadparm_context *lp_ctx,
558                                  struct dcesrv_endpoint *e,
559                                  struct tevent_context *event_ctx, const struct model_ops *model_ops)
560 {
561         struct dcesrv_socket_context *dcesrv_sock;
562         NTSTATUS status;
563                         
564         if (e->ep_description->endpoint == NULL) {
565                 DEBUG(0, ("Endpoint mandatory for named pipes\n"));
566                 return NT_STATUS_INVALID_PARAMETER;
567         }
568
569         dcesrv_sock = talloc(event_ctx, struct dcesrv_socket_context);
570         NT_STATUS_HAVE_NO_MEMORY(dcesrv_sock);
571
572         /* remember the endpoint of this socket */
573         dcesrv_sock->endpoint           = e;
574         dcesrv_sock->dcesrv_ctx         = talloc_reference(dcesrv_sock, dce_ctx);
575
576         status = stream_setup_named_pipe(event_ctx, lp_ctx,
577                                          model_ops, &dcesrv_stream_ops,
578                                          e->ep_description->endpoint, dcesrv_sock);
579         if (!NT_STATUS_IS_OK(status)) {
580                 DEBUG(0,("stream_setup_named_pipe(pipe=%s) failed - %s\n",
581                          e->ep_description->endpoint, nt_errstr(status)));
582                 return status;
583         }
584
585         return NT_STATUS_OK;
586 }
587
588 /*
589   add a socket address to the list of events, one event per dcerpc endpoint
590 */
591 static NTSTATUS add_socket_rpc_tcp_iface(struct dcesrv_context *dce_ctx, struct dcesrv_endpoint *e,
592                                          struct tevent_context *event_ctx, const struct model_ops *model_ops,
593                                          const char *address)
594 {
595         struct dcesrv_socket_context *dcesrv_sock;
596         uint16_t port = 0;
597         NTSTATUS status;
598                         
599         if (e->ep_description->endpoint) {
600                 port = atoi(e->ep_description->endpoint);
601         }
602
603         dcesrv_sock = talloc(event_ctx, struct dcesrv_socket_context);
604         NT_STATUS_HAVE_NO_MEMORY(dcesrv_sock);
605
606         /* remember the endpoint of this socket */
607         dcesrv_sock->endpoint           = e;
608         dcesrv_sock->dcesrv_ctx         = talloc_reference(dcesrv_sock, dce_ctx);
609
610         status = stream_setup_socket(event_ctx, dce_ctx->lp_ctx,
611                                      model_ops, &dcesrv_stream_ops, 
612                                      "ipv4", address, &port, 
613                                      lp_socket_options(dce_ctx->lp_ctx), 
614                                      dcesrv_sock);
615         if (!NT_STATUS_IS_OK(status)) {
616                 DEBUG(0,("service_setup_stream_socket(address=%s,port=%u) failed - %s\n", 
617                          address, port, nt_errstr(status)));
618         }
619
620         if (e->ep_description->endpoint == NULL) {
621                 e->ep_description->endpoint = talloc_asprintf(dce_ctx, "%d", port);
622         }
623
624         return status;
625 }
626
627 static NTSTATUS dcesrv_add_ep_tcp(struct dcesrv_context *dce_ctx, 
628                                   struct loadparm_context *lp_ctx,
629                                   struct dcesrv_endpoint *e,
630                                   struct tevent_context *event_ctx, const struct model_ops *model_ops)
631 {
632         NTSTATUS status;
633
634         /* Add TCP/IP sockets */
635         if (lp_interfaces(lp_ctx) && lp_bind_interfaces_only(lp_ctx)) {
636                 int num_interfaces;
637                 int i;
638                 struct interface *ifaces;
639
640                 load_interfaces(dce_ctx, lp_interfaces(lp_ctx), &ifaces);
641
642                 num_interfaces = iface_count(ifaces);
643                 for(i = 0; i < num_interfaces; i++) {
644                         const char *address = iface_n_ip(ifaces, i);
645                         status = add_socket_rpc_tcp_iface(dce_ctx, e, event_ctx, model_ops, address);
646                         NT_STATUS_NOT_OK_RETURN(status);
647                 }
648         } else {
649                 status = add_socket_rpc_tcp_iface(dce_ctx, e, event_ctx, model_ops, 
650                                                   lp_socket_address(lp_ctx));
651                 NT_STATUS_NOT_OK_RETURN(status);
652         }
653
654         return NT_STATUS_OK;
655 }
656
657 NTSTATUS dcesrv_add_ep(struct dcesrv_context *dce_ctx,
658                        struct loadparm_context *lp_ctx,
659                        struct dcesrv_endpoint *e,
660                        struct tevent_context *event_ctx,
661                        const struct model_ops *model_ops)
662 {
663         switch (e->ep_description->transport) {
664         case NCACN_UNIX_STREAM:
665                 return dcesrv_add_ep_unix(dce_ctx, lp_ctx, e, event_ctx, model_ops);
666
667         case NCALRPC:
668                 return dcesrv_add_ep_ncalrpc(dce_ctx, lp_ctx, e, event_ctx, model_ops);
669
670         case NCACN_IP_TCP:
671                 return dcesrv_add_ep_tcp(dce_ctx, lp_ctx, e, event_ctx, model_ops);
672
673         case NCACN_NP:
674                 return dcesrv_add_ep_np(dce_ctx, lp_ctx, e, event_ctx, model_ops);
675
676         default:
677                 return NT_STATUS_NOT_SUPPORTED;
678         }
679 }
680
681 /*
682   open the dcerpc server sockets
683 */
684 static void dcesrv_task_init(struct task_server *task)
685 {
686         NTSTATUS status;
687         struct dcesrv_context *dce_ctx;
688         struct dcesrv_endpoint *e;
689         const struct model_ops *model_ops;
690
691         dcerpc_server_init(task->lp_ctx);
692
693         task_server_set_title(task, "task[dcesrv]");
694
695         /* run the rpc server as a single process to allow for shard
696          * handles, and sharing of ldb contexts */
697         model_ops = process_model_startup(task->event_ctx, "single");
698         if (!model_ops) goto failed;
699
700         status = dcesrv_init_context(task->event_ctx,
701                                      task->lp_ctx,
702                                      lp_dcerpc_endpoint_servers(task->lp_ctx),
703                                      &dce_ctx);
704         if (!NT_STATUS_IS_OK(status)) goto failed;
705
706         /* Make sure the directory for NCALRPC exists */
707         if (!directory_exist(lp_ncalrpc_dir(task->lp_ctx))) {
708                 mkdir(lp_ncalrpc_dir(task->lp_ctx), 0755);
709         }
710
711         for (e=dce_ctx->endpoint_list;e;e=e->next) {
712                 status = dcesrv_add_ep(dce_ctx, task->lp_ctx, e, task->event_ctx, model_ops);
713                 if (!NT_STATUS_IS_OK(status)) goto failed;
714         }
715
716         return;
717 failed:
718         task_server_terminate(task, "Failed to startup dcerpc server task", true);      
719 }
720
721 NTSTATUS server_service_rpc_init(void)
722 {
723
724         return register_server_service("rpc", dcesrv_task_init);
725 }