lib: Remove idtree from samba_util.h
[bbaumbach/samba-autobuild/.git] / source4 / rpc_server / dcerpc_server.c
1 /* 
2    Unix SMB/CIFS implementation.
3
4    server side dcerpc core code
5
6    Copyright (C) Andrew Tridgell 2003-2005
7    Copyright (C) Stefan (metze) Metzmacher 2004-2005
8    
9    This program is free software; you can redistribute it and/or modify
10    it under the terms of the GNU General Public License as published by
11    the Free Software Foundation; either version 3 of the License, or
12    (at your option) any later version.
13    
14    This program is distributed in the hope that it will be useful,
15    but WITHOUT ANY WARRANTY; without even the implied warranty of
16    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17    GNU General Public License for more details.
18    
19    You should have received a copy of the GNU General Public License
20    along with this program.  If not, see <http://www.gnu.org/licenses/>.
21 */
22
23 #include "includes.h"
24 #include "auth/auth.h"
25 #include "auth/gensec/gensec.h"
26 #include "auth/credentials/credentials.h"
27 #include "rpc_server/dcerpc_server.h"
28 #include "rpc_server/dcerpc_server_proto.h"
29 #include "param/param.h"
30 #include "samba/service_stream.h"
31 #include "lib/tsocket/tsocket.h"
32 #include "lib/socket/socket.h"
33 #include "samba/process_model.h"
34 #include "lib/util/samba_modules.h"
35 #include "lib/util/tevent_ntstatus.h"
36 #include "lib/util/idtree_random.h"
37
38 /*
39   take a reference to an existing association group
40  */
41 static struct dcesrv_assoc_group *dcesrv_assoc_group_reference(struct dcesrv_connection *conn,
42                                                                uint32_t id)
43 {
44         const struct dcesrv_endpoint *endpoint = conn->endpoint;
45         enum dcerpc_transport_t transport =
46                 dcerpc_binding_get_transport(endpoint->ep_description);
47         struct dcesrv_assoc_group *assoc_group;
48         void *id_ptr = NULL;
49
50         /* find an association group given a assoc_group_id */
51         id_ptr = idr_find(conn->dce_ctx->assoc_groups_idr, id);
52         if (id_ptr == NULL) {
53                 DBG_NOTICE("Failed to find assoc_group 0x%08x\n", id);
54                 return NULL;
55         }
56         assoc_group = talloc_get_type_abort(id_ptr, struct dcesrv_assoc_group);
57
58         if (assoc_group->transport != transport) {
59                 const char *at =
60                         derpc_transport_string_by_transport(
61                                 assoc_group->transport);
62                 const char *ct =
63                         derpc_transport_string_by_transport(
64                                 transport);
65
66                 DBG_NOTICE("assoc_group 0x%08x (transport %s) "
67                            "is not available on transport %s",
68                            id, at, ct);
69                 return NULL;
70         }
71
72         return talloc_reference(conn, assoc_group);
73 }
74
75 static int dcesrv_assoc_group_destructor(struct dcesrv_assoc_group *assoc_group)
76 {
77         int ret;
78         ret = idr_remove(assoc_group->dce_ctx->assoc_groups_idr, assoc_group->id);
79         if (ret != 0) {
80                 DEBUG(0,(__location__ ": Failed to remove assoc_group 0x%08x\n",
81                          assoc_group->id));
82         }
83         return 0;
84 }
85
86 /*
87   allocate a new association group
88  */
89 static struct dcesrv_assoc_group *dcesrv_assoc_group_new(struct dcesrv_connection *conn)
90 {
91         struct dcesrv_context *dce_ctx = conn->dce_ctx;
92         const struct dcesrv_endpoint *endpoint = conn->endpoint;
93         enum dcerpc_transport_t transport =
94                 dcerpc_binding_get_transport(endpoint->ep_description);
95         struct dcesrv_assoc_group *assoc_group;
96         int id;
97
98         assoc_group = talloc_zero(conn, struct dcesrv_assoc_group);
99         if (assoc_group == NULL) {
100                 return NULL;
101         }
102
103         id = idr_get_new_random(
104                 dce_ctx->assoc_groups_idr, assoc_group, 1, UINT16_MAX);
105         if (id == -1) {
106                 talloc_free(assoc_group);
107                 DEBUG(0,(__location__ ": Out of association groups!\n"));
108                 return NULL;
109         }
110
111         assoc_group->transport = transport;
112         assoc_group->id = id;
113         assoc_group->dce_ctx = dce_ctx;
114
115         talloc_set_destructor(assoc_group, dcesrv_assoc_group_destructor);
116
117         return assoc_group;
118 }
119
120 NTSTATUS dcesrv_assoc_group_find_s4(
121         struct dcesrv_call_state *call,
122         void *private_data)
123 {
124         /*
125           if provided, check the assoc_group is valid
126          */
127         if (call->pkt.u.bind.assoc_group_id != 0) {
128                 call->conn->assoc_group =
129                         dcesrv_assoc_group_reference(call->conn,
130                                         call->pkt.u.bind.assoc_group_id);
131         } else {
132                 call->conn->assoc_group = dcesrv_assoc_group_new(call->conn);
133         }
134
135         /*
136          * The NETLOGON server does not use handles and so
137          * there is no need to support association groups, but
138          * we need to give back a number regardless.
139          *
140          * We have to do this when it is not run as a single process,
141          * because then it can't see the other valid association
142          * groups.  We handle this genericly for all endpoints not
143          * running in single process mode.
144          *
145          * We know which endpoint we are on even before checking the
146          * iface UUID, so for simplicity we enforce the same policy
147          * for all interfaces on the endpoint.
148          *
149          * This means that where NETLOGON
150          * shares an endpoint (such as ncalrpc or if 'lsa over
151          * netlogon' is set) we will still check association groups.
152          *
153          */
154
155         if (call->conn->assoc_group == NULL &&
156             !call->conn->endpoint->use_single_process) {
157                 call->conn->assoc_group
158                         = dcesrv_assoc_group_new(call->conn);
159         }
160
161         if (call->conn->assoc_group == NULL) {
162                 /* TODO Return correct status */
163                 return NT_STATUS_UNSUCCESSFUL;
164         }
165
166         return NT_STATUS_OK;
167 }
168
169 void dcerpc_server_init(struct loadparm_context *lp_ctx)
170 {
171         static bool initialized;
172 #define _MODULE_PROTO(init) extern NTSTATUS init(TALLOC_CTX *);
173         STATIC_dcerpc_server_MODULES_PROTO;
174         init_module_fn static_init[] = { STATIC_dcerpc_server_MODULES };
175         init_module_fn *shared_init;
176
177         if (initialized) {
178                 return;
179         }
180         initialized = true;
181
182         shared_init = load_samba_modules(NULL, "dcerpc_server");
183
184         run_init_functions(NULL, static_init);
185         run_init_functions(NULL, shared_init);
186
187         talloc_free(shared_init);
188 }
189
190 struct dcesrv_socket_context {
191         const struct dcesrv_endpoint *endpoint;
192         struct dcesrv_context *dcesrv_ctx;
193 };
194
195 static void dcesrv_sock_accept(struct stream_connection *srv_conn)
196 {
197         NTSTATUS status;
198         struct dcesrv_socket_context *dcesrv_sock = 
199                 talloc_get_type(srv_conn->private_data, struct dcesrv_socket_context);
200         enum dcerpc_transport_t transport =
201                 dcerpc_binding_get_transport(dcesrv_sock->endpoint->ep_description);
202         struct dcesrv_connection *dcesrv_conn = NULL;
203         int ret;
204         struct loadparm_context *lp_ctx = dcesrv_sock->dcesrv_ctx->lp_ctx;
205
206         dcesrv_cleanup_broken_connections(dcesrv_sock->dcesrv_ctx);
207
208         if (!srv_conn->session_info) {
209                 status = auth_anonymous_session_info(srv_conn,
210                                                      lp_ctx,
211                                                      &srv_conn->session_info);
212                 if (!NT_STATUS_IS_OK(status)) {
213                         DEBUG(0,("dcesrv_sock_accept: auth_anonymous_session_info failed: %s\n",
214                                 nt_errstr(status)));
215                         stream_terminate_connection(srv_conn, nt_errstr(status));
216                         return;
217                 }
218         }
219
220         /*
221          * This fills in dcesrv_conn->endpoint with the endpoint
222          * associated with the socket.  From this point on we know
223          * which (group of) services we are handling, but not the
224          * specific interface.
225          */
226
227         status = dcesrv_endpoint_connect(dcesrv_sock->dcesrv_ctx,
228                                          srv_conn,
229                                          dcesrv_sock->endpoint,
230                                          srv_conn->session_info,
231                                          srv_conn->event.ctx,
232                                          DCESRV_CALL_STATE_FLAG_MAY_ASYNC,
233                                          &dcesrv_conn);
234         if (!NT_STATUS_IS_OK(status)) {
235                 DEBUG(0,("dcesrv_sock_accept: dcesrv_endpoint_connect failed: %s\n", 
236                         nt_errstr(status)));
237                 stream_terminate_connection(srv_conn, nt_errstr(status));
238                 return;
239         }
240
241         dcesrv_conn->transport.private_data             = srv_conn;
242         dcesrv_conn->transport.report_output_data       = dcesrv_sock_report_output_data;
243         dcesrv_conn->transport.terminate_connection     = dcesrv_transport_terminate_connection_s4;
244
245         TALLOC_FREE(srv_conn->event.fde);
246
247         dcesrv_conn->send_queue = tevent_queue_create(dcesrv_conn, "dcesrv send queue");
248         if (!dcesrv_conn->send_queue) {
249                 status = NT_STATUS_NO_MEMORY;
250                 DEBUG(0,("dcesrv_sock_accept: tevent_queue_create(%s)\n",
251                         nt_errstr(status)));
252                 stream_terminate_connection(srv_conn, nt_errstr(status));
253                 return;
254         }
255
256         if (transport == NCACN_NP) {
257                 dcesrv_conn->stream = talloc_move(dcesrv_conn,
258                                                   &srv_conn->tstream);
259         } else {
260                 ret = tstream_bsd_existing_socket(dcesrv_conn,
261                                                   socket_get_fd(srv_conn->socket),
262                                                   &dcesrv_conn->stream);
263                 if (ret == -1) {
264                         status = map_nt_error_from_unix_common(errno);
265                         DEBUG(0, ("dcesrv_sock_accept: "
266                                   "failed to setup tstream: %s\n",
267                                   nt_errstr(status)));
268                         stream_terminate_connection(srv_conn, nt_errstr(status));
269                         return;
270                 }
271                 socket_set_flags(srv_conn->socket, SOCKET_FLAG_NOCLOSE);
272         }
273
274         dcesrv_conn->local_address = srv_conn->local_address;
275         dcesrv_conn->remote_address = srv_conn->remote_address;
276
277         if (transport == NCALRPC) {
278                 uid_t uid;
279                 gid_t gid;
280                 int sock_fd;
281
282                 sock_fd = socket_get_fd(srv_conn->socket);
283                 if (sock_fd == -1) {
284                         stream_terminate_connection(
285                                 srv_conn, "socket_get_fd failed\n");
286                         return;
287                 }
288
289                 ret = getpeereid(sock_fd, &uid, &gid);
290                 if (ret == -1) {
291                         status = map_nt_error_from_unix_common(errno);
292                         DEBUG(0, ("dcesrv_sock_accept: "
293                                   "getpeereid() failed for NCALRPC: %s\n",
294                                   nt_errstr(status)));
295                         stream_terminate_connection(srv_conn, nt_errstr(status));
296                         return;
297                 }
298                 if (uid == dcesrv_conn->dce_ctx->initial_euid) {
299                         struct tsocket_address *r = NULL;
300
301                         ret = tsocket_address_unix_from_path(dcesrv_conn,
302                                                              AS_SYSTEM_MAGIC_PATH_TOKEN,
303                                                              &r);
304                         if (ret == -1) {
305                                 status = map_nt_error_from_unix_common(errno);
306                                 DEBUG(0, ("dcesrv_sock_accept: "
307                                           "tsocket_address_unix_from_path() failed for NCALRPC: %s\n",
308                                           nt_errstr(status)));
309                                 stream_terminate_connection(srv_conn, nt_errstr(status));
310                                 return;
311                         }
312                         dcesrv_conn->remote_address = r;
313                 }
314         }
315
316         srv_conn->private_data = dcesrv_conn;
317
318         status = dcesrv_connection_loop_start(dcesrv_conn);
319         if (!NT_STATUS_IS_OK(status)) {
320                 DEBUG(0,("dcesrv_sock_accept: dcerpc_read_fragment_buffer_send(%s)\n",
321                         nt_errstr(status)));
322                 stream_terminate_connection(srv_conn, nt_errstr(status));
323                 return;
324         }
325
326         return;
327 }
328
329 static void dcesrv_sock_recv(struct stream_connection *conn, uint16_t flags)
330 {
331         struct dcesrv_connection *dce_conn = talloc_get_type(conn->private_data,
332                                              struct dcesrv_connection);
333         dcesrv_terminate_connection(dce_conn, "dcesrv_sock_recv triggered");
334 }
335
336 static void dcesrv_sock_send(struct stream_connection *conn, uint16_t flags)
337 {
338         struct dcesrv_connection *dce_conn = talloc_get_type(conn->private_data,
339                                              struct dcesrv_connection);
340         dcesrv_terminate_connection(dce_conn, "dcesrv_sock_send triggered");
341 }
342
343
344 static const struct stream_server_ops dcesrv_stream_ops = {
345         .name                   = "rpc",
346         .accept_connection      = dcesrv_sock_accept,
347         .recv_handler           = dcesrv_sock_recv,
348         .send_handler           = dcesrv_sock_send,
349 };
350
351 static NTSTATUS dcesrv_add_ep_unix(struct dcesrv_context *dce_ctx, 
352                                    struct loadparm_context *lp_ctx,
353                                    struct dcesrv_endpoint *e,
354                                    struct tevent_context *event_ctx,
355                                    const struct model_ops *model_ops,
356                                    void *process_context)
357 {
358         struct dcesrv_socket_context *dcesrv_sock;
359         uint16_t port = 1;
360         NTSTATUS status;
361         const char *endpoint;
362
363         dcesrv_sock = talloc_zero(event_ctx, struct dcesrv_socket_context);
364         NT_STATUS_HAVE_NO_MEMORY(dcesrv_sock);
365
366         /* remember the endpoint of this socket */
367         dcesrv_sock->endpoint           = e;
368         dcesrv_sock->dcesrv_ctx         = talloc_reference(dcesrv_sock, dce_ctx);
369
370         endpoint = dcerpc_binding_get_string_option(e->ep_description, "endpoint");
371
372         status = stream_setup_socket(dcesrv_sock, event_ctx, lp_ctx,
373                                      model_ops, &dcesrv_stream_ops, 
374                                      "unix", endpoint, &port,
375                                      lpcfg_socket_options(lp_ctx),
376                                      dcesrv_sock, process_context);
377         if (!NT_STATUS_IS_OK(status)) {
378                 DEBUG(0,("service_setup_stream_socket(path=%s) failed - %s\n",
379                          endpoint, nt_errstr(status)));
380         }
381
382         return status;
383 }
384
385 static NTSTATUS dcesrv_add_ep_ncalrpc(struct dcesrv_context *dce_ctx, 
386                                       struct loadparm_context *lp_ctx,
387                                       struct dcesrv_endpoint *e,
388                                       struct tevent_context *event_ctx,
389                                       const struct model_ops *model_ops,
390                                       void *process_context)
391 {
392         struct dcesrv_socket_context *dcesrv_sock;
393         uint16_t port = 1;
394         char *full_path;
395         NTSTATUS status;
396         const char *endpoint;
397
398         endpoint = dcerpc_binding_get_string_option(e->ep_description, "endpoint");
399
400         if (endpoint == NULL) {
401                 /*
402                  * No identifier specified: use DEFAULT.
403                  *
404                  * TODO: DO NOT hardcode this value anywhere else. Rather, specify
405                  * no endpoint and let the epmapper worry about it.
406                  */
407                 endpoint = "DEFAULT";
408                 status = dcerpc_binding_set_string_option(e->ep_description,
409                                                           "endpoint",
410                                                           endpoint);
411                 if (!NT_STATUS_IS_OK(status)) {
412                         DEBUG(0,("dcerpc_binding_set_string_option() failed - %s\n",
413                                   nt_errstr(status)));
414                         return status;
415                 }
416         }
417
418         full_path = talloc_asprintf(dce_ctx, "%s/%s", lpcfg_ncalrpc_dir(lp_ctx),
419                                     endpoint);
420
421         dcesrv_sock = talloc_zero(event_ctx, struct dcesrv_socket_context);
422         NT_STATUS_HAVE_NO_MEMORY(dcesrv_sock);
423
424         /* remember the endpoint of this socket */
425         dcesrv_sock->endpoint           = e;
426         dcesrv_sock->dcesrv_ctx         = talloc_reference(dcesrv_sock, dce_ctx);
427
428         status = stream_setup_socket(dcesrv_sock, event_ctx, lp_ctx,
429                                      model_ops, &dcesrv_stream_ops, 
430                                      "unix", full_path, &port, 
431                                      lpcfg_socket_options(lp_ctx),
432                                      dcesrv_sock, process_context);
433         if (!NT_STATUS_IS_OK(status)) {
434                 DEBUG(0,("service_setup_stream_socket(identifier=%s,path=%s) failed - %s\n",
435                          endpoint, full_path, nt_errstr(status)));
436         }
437         return status;
438 }
439
440 static NTSTATUS dcesrv_add_ep_np(struct dcesrv_context *dce_ctx,
441                                  struct loadparm_context *lp_ctx,
442                                  struct dcesrv_endpoint *e,
443                                  struct tevent_context *event_ctx,
444                                  const struct model_ops *model_ops,
445                                  void *process_context)
446 {
447         struct dcesrv_socket_context *dcesrv_sock;
448         NTSTATUS status;
449         const char *endpoint;
450
451         endpoint = dcerpc_binding_get_string_option(e->ep_description, "endpoint");
452         if (endpoint == NULL) {
453                 DEBUG(0, ("Endpoint mandatory for named pipes\n"));
454                 return NT_STATUS_INVALID_PARAMETER;
455         }
456
457         dcesrv_sock = talloc_zero(event_ctx, struct dcesrv_socket_context);
458         NT_STATUS_HAVE_NO_MEMORY(dcesrv_sock);
459
460         /* remember the endpoint of this socket */
461         dcesrv_sock->endpoint           = e;
462         dcesrv_sock->dcesrv_ctx         = talloc_reference(dcesrv_sock, dce_ctx);
463
464         status = tstream_setup_named_pipe(dce_ctx, event_ctx, lp_ctx,
465                                           model_ops, &dcesrv_stream_ops,
466                                           endpoint,
467                                           dcesrv_sock, process_context);
468         if (!NT_STATUS_IS_OK(status)) {
469                 DEBUG(0,("stream_setup_named_pipe(pipe=%s) failed - %s\n",
470                          endpoint, nt_errstr(status)));
471                 return status;
472         }
473
474         return NT_STATUS_OK;
475 }
476
477 /*
478   add a socket address to the list of events, one event per dcerpc endpoint
479 */
480 static NTSTATUS add_socket_rpc_tcp_iface(struct dcesrv_context *dce_ctx,
481                                          struct dcesrv_endpoint *e,
482                                          struct tevent_context *event_ctx,
483                                          const struct model_ops *model_ops,
484                                          const char *address,
485                                          void *process_context)
486 {
487         struct dcesrv_socket_context *dcesrv_sock;
488         uint16_t port = 0;
489         NTSTATUS status;
490         const char *endpoint;
491         char port_str[6];
492
493         endpoint = dcerpc_binding_get_string_option(e->ep_description, "endpoint");
494         if (endpoint != NULL) {
495                 port = atoi(endpoint);
496         }
497
498         dcesrv_sock = talloc_zero(event_ctx, struct dcesrv_socket_context);
499         NT_STATUS_HAVE_NO_MEMORY(dcesrv_sock);
500
501         /* remember the endpoint of this socket */
502         dcesrv_sock->endpoint           = e;
503         dcesrv_sock->dcesrv_ctx         = talloc_reference(dcesrv_sock, dce_ctx);
504
505         status = stream_setup_socket(dcesrv_sock, event_ctx, dce_ctx->lp_ctx,
506                                      model_ops, &dcesrv_stream_ops, 
507                                      "ip", address, &port,
508                                      lpcfg_socket_options(dce_ctx->lp_ctx),
509                                      dcesrv_sock, process_context);
510         if (!NT_STATUS_IS_OK(status)) {
511                 struct dcesrv_if_list *iface;
512                 DEBUG(0,("service_setup_stream_socket(address=%s,port=%u) for ",
513                          address, port));
514                 for (iface = e->interface_list; iface; iface = iface->next) {
515                         DEBUGADD(0, ("%s ", iface->iface->name));
516                 }
517                 DEBUGADD(0, ("failed - %s\n",
518                              nt_errstr(status)));
519                 return status;
520         }
521
522         snprintf(port_str, sizeof(port_str), "%u", port);
523
524         status = dcerpc_binding_set_string_option(e->ep_description,
525                                                   "endpoint", port_str);
526         if (!NT_STATUS_IS_OK(status)) {
527                 DEBUG(0,("dcerpc_binding_set_string_option(endpoint, %s) failed - %s\n",
528                          port_str, nt_errstr(status)));
529                 return status;
530         } else {
531                 struct dcesrv_if_list *iface;
532                 DEBUG(4,("Successfully listening on ncacn_ip_tcp endpoint [%s]:[%s] for ",
533                          address, port_str));
534                 for (iface = e->interface_list; iface; iface = iface->next) {
535                         DEBUGADD(4, ("%s ", iface->iface->name));
536                 }
537                 DEBUGADD(4, ("\n"));
538         }
539
540         return NT_STATUS_OK;
541 }
542
543 #include "lib/socket/netif.h" /* Included here to work around the fact that socket_wrapper redefines bind() */
544
545 static NTSTATUS dcesrv_add_ep_tcp(struct dcesrv_context *dce_ctx, 
546                                   struct loadparm_context *lp_ctx,
547                                   struct dcesrv_endpoint *e,
548                                   struct tevent_context *event_ctx,
549                                   const struct model_ops *model_ops,
550                                   void *process_context)
551 {
552         NTSTATUS status;
553
554         /* Add TCP/IP sockets */
555         if (lpcfg_interfaces(lp_ctx) && lpcfg_bind_interfaces_only(lp_ctx)) {
556                 int num_interfaces;
557                 int i;
558                 struct interface *ifaces;
559
560                 load_interface_list(dce_ctx, lp_ctx, &ifaces);
561
562                 num_interfaces = iface_list_count(ifaces);
563                 for(i = 0; i < num_interfaces; i++) {
564                         const char *address = iface_list_n_ip(ifaces, i);
565                         status = add_socket_rpc_tcp_iface(dce_ctx, e, event_ctx,
566                                                           model_ops, address,
567                                                           process_context);
568                         NT_STATUS_NOT_OK_RETURN(status);
569                 }
570         } else {
571                 char **wcard;
572                 size_t i;
573                 size_t num_binds = 0;
574                 wcard = iface_list_wildcard(dce_ctx);
575                 NT_STATUS_HAVE_NO_MEMORY(wcard);
576                 for (i=0; wcard[i]; i++) {
577                         status = add_socket_rpc_tcp_iface(dce_ctx, e, event_ctx,
578                                                           model_ops, wcard[i],
579                                                           process_context);
580                         if (NT_STATUS_IS_OK(status)) {
581                                 num_binds++;
582                         }
583                 }
584                 talloc_free(wcard);
585                 if (num_binds == 0) {
586                         return NT_STATUS_INVALID_PARAMETER_MIX;
587                 }
588         }
589
590         return NT_STATUS_OK;
591 }
592
593 NTSTATUS dcesrv_add_ep(struct dcesrv_context *dce_ctx,
594                        struct loadparm_context *lp_ctx,
595                        struct dcesrv_endpoint *e,
596                        struct tevent_context *event_ctx,
597                        const struct model_ops *model_ops,
598                        void *process_context)
599 {
600         enum dcerpc_transport_t transport =
601                 dcerpc_binding_get_transport(e->ep_description);
602
603         switch (transport) {
604         case NCACN_UNIX_STREAM:
605                 return dcesrv_add_ep_unix(dce_ctx, lp_ctx, e, event_ctx,
606                                           model_ops, process_context);
607
608         case NCALRPC:
609                 return dcesrv_add_ep_ncalrpc(dce_ctx, lp_ctx, e, event_ctx,
610                                              model_ops, process_context);
611
612         case NCACN_IP_TCP:
613                 return dcesrv_add_ep_tcp(dce_ctx, lp_ctx, e, event_ctx,
614                                          model_ops, process_context);
615
616         case NCACN_NP:
617                 return dcesrv_add_ep_np(dce_ctx, lp_ctx, e, event_ctx,
618                                         model_ops, process_context);
619
620         default:
621                 return NT_STATUS_NOT_SUPPORTED;
622         }
623 }
624
625 _PUBLIC_ struct imessaging_context *dcesrv_imessaging_context(
626                                         struct dcesrv_connection *conn)
627 {
628         struct stream_connection *srv_conn =
629                 talloc_get_type_abort(conn->transport.private_data,
630                                       struct stream_connection);
631         return srv_conn->msg_ctx;
632 }
633
634 _PUBLIC_ struct server_id dcesrv_server_id(struct dcesrv_connection *conn)
635 {
636         struct stream_connection *srv_conn =
637                 talloc_get_type_abort(conn->transport.private_data,
638                                 struct stream_connection);
639         return srv_conn->server_id;
640 }
641
642 void log_successful_dcesrv_authz_event(
643         struct dcesrv_call_state *call,
644         void *private_data)
645 {
646         struct dcesrv_auth *auth = call->auth_state;
647         enum dcerpc_transport_t transport =
648                 dcerpc_binding_get_transport(call->conn->endpoint->ep_description);
649         struct imessaging_context *imsg_ctx =
650                 dcesrv_imessaging_context(call->conn);
651         const char *auth_type = derpc_transport_string_by_transport(transport);
652         const char *transport_protection = AUTHZ_TRANSPORT_PROTECTION_NONE;
653
654         if (transport == NCACN_NP) {
655                 transport_protection = AUTHZ_TRANSPORT_PROTECTION_SMB;
656         }
657
658         /*
659          * Log the authorization to this RPC interface.  This
660          * covered ncacn_np pass-through auth, and anonymous
661          * DCE/RPC (eg epmapper, netlogon etc)
662          */
663         log_successful_authz_event(imsg_ctx,
664                                    call->conn->dce_ctx->lp_ctx,
665                                    call->conn->remote_address,
666                                    call->conn->local_address,
667                                    "DCE/RPC",
668                                    auth_type,
669                                    transport_protection,
670                                    auth->session_info);
671
672         auth->auth_audited = true;
673 }
674
675 NTSTATUS dcesrv_gensec_prepare(
676         TALLOC_CTX *mem_ctx,
677         struct dcesrv_call_state *call,
678         struct gensec_security **out,
679         void *private_data)
680 {
681         struct cli_credentials *server_creds = NULL;
682         struct imessaging_context *imsg_ctx =
683                 dcesrv_imessaging_context(call->conn);
684         bool ok;
685
686         server_creds = cli_credentials_init_server(call->auth_state,
687                                                    call->conn->dce_ctx->lp_ctx);
688         if (server_creds == NULL) {
689                 DEBUG(1, ("Failed to init server credentials\n"));
690                 return NT_STATUS_NO_MEMORY;
691         }
692         /* This is required for ncalrpc_as_system. */
693         ok = cli_credentials_set_kerberos_state(server_creds,
694                                                 CRED_USE_KERBEROS_DESIRED,
695                                                 CRED_SPECIFIED);
696         if (!ok) {
697                 DBG_WARNING("Failed to set kerberos state\n");
698                 return NT_STATUS_INTERNAL_ERROR;
699         }
700
701         return samba_server_gensec_start(mem_ctx,
702                                          call->event_ctx,
703                                          imsg_ctx,
704                                          call->conn->dce_ctx->lp_ctx,
705                                          server_creds,
706                                          NULL,
707                                          out);
708 }
709
710 void dcesrv_transport_terminate_connection_s4(struct dcesrv_connection *dce_conn,
711                                               const char *reason)
712 {
713         struct stream_connection *srv_conn =
714                 talloc_get_type_abort(dce_conn->transport.private_data,
715                                       struct stream_connection);
716         stream_terminate_connection(srv_conn, reason);
717 }