2 * Unix SMB/CIFS implementation.
6 * Copyright (c) 2011 Andreas Schneider <asn@samba.org>
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 3 of the License, or
11 * (at your option) any later version.
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, see <http://www.gnu.org/licenses/>.
25 #include "../lib/tsocket/tsocket.h"
26 #include "librpc/rpc/dcesrv_core.h"
27 #include "rpc_server/rpc_sock_helper.h"
28 #include "librpc/ndr/ndr_table.h"
31 #define DBGC_CLASS DBGC_RPC_SRV
33 static NTSTATUS
dcesrv_create_ncacn_np_socket(
34 struct dcerpc_binding
*b
, int *out_fd
)
40 char *endpoint_normalized
= NULL
;
43 endpoint
= dcerpc_binding_get_string_option(b
, "endpoint");
44 if (endpoint
== NULL
) {
45 DBG_ERR("Endpoint mandatory for named pipes\n");
46 return NT_STATUS_INVALID_PARAMETER
;
49 /* The endpoint string from IDL can be mixed uppercase and case is
50 * normalized by smbd on connection */
51 endpoint_normalized
= strlower_talloc(talloc_tos(), endpoint
);
52 if (endpoint_normalized
== NULL
) {
53 return NT_STATUS_NO_MEMORY
;
56 /* The endpoint string from IDL can be prefixed by \pipe\ */
57 p
= endpoint_normalized
;
58 if (strncmp(p
, "\\pipe\\", 6) == 0) {
63 * As lp_ncalrpc_dir() should have 0755, but
64 * lp_ncalrpc_dir()/np should have 0700, we need to
65 * create lp_ncalrpc_dir() first.
67 if (!directory_create_or_exist(lp_ncalrpc_dir(), 0755)) {
68 status
= map_nt_error_from_unix_common(errno
);
69 DBG_ERR("Failed to create pipe directory %s - %s\n",
70 lp_ncalrpc_dir(), strerror(errno
));
74 np_dir
= talloc_asprintf(talloc_tos(), "%s/np", lp_ncalrpc_dir());
76 status
= NT_STATUS_NO_MEMORY
;
77 DBG_ERR("Out of memory\n");
81 if (!directory_create_or_exist_strict(np_dir
, geteuid(), 0700)) {
82 status
= map_nt_error_from_unix_common(errno
);
83 DBG_ERR("Failed to create pipe directory %s - %s\n",
84 np_dir
, strerror(errno
));
88 fd
= create_pipe_sock(np_dir
, p
, 0700);
90 status
= map_nt_error_from_unix_common(errno
);
91 DBG_ERR("Failed to create ncacn_np socket! '%s/%s': %s\n",
92 np_dir
, p
, strerror(errno
));
96 DBG_DEBUG("Opened pipe socket fd %d for %s\n", fd
, p
);
100 status
= NT_STATUS_OK
;
103 TALLOC_FREE(endpoint_normalized
);
108 /********************************************************************
109 * Start listening on the tcp/ip socket
110 ********************************************************************/
112 static NTSTATUS
dcesrv_create_ncacn_ip_tcp_socket(
113 const struct sockaddr_storage
*ifss
, uint16_t *port
, int *out_fd
)
118 static uint16_t low
= 0;
122 low
= lp_rpc_low_port();
125 for (i
= low
; i
<= lp_rpc_high_port(); i
++) {
126 fd
= open_socket_in(SOCK_STREAM
, ifss
, i
, false);
134 fd
= open_socket_in(SOCK_STREAM
, ifss
, *port
, true);
138 DBG_ERR("Failed to create socket on port %u!\n", *port
);
139 return map_nt_error_from_unix(-fd
);
142 /* ready to listen */
143 set_socket_options(fd
, "SO_KEEPALIVE");
144 set_socket_options(fd
, lp_socket_options());
146 DBG_DEBUG("Opened ncacn_ip_tcp socket fd %d for port %u\n", fd
, *port
);
153 static NTSTATUS
dcesrv_create_ncacn_ip_tcp_sockets(
154 struct dcerpc_binding
*b
,
161 const char *endpoint
= NULL
;
162 size_t i
= 0, num_fds
;
164 struct samba_sockaddr
*addrs
= NULL
;
165 NTSTATUS status
= NT_STATUS_INVALID_PARAMETER
;
168 endpoint
= dcerpc_binding_get_string_option(b
, "endpoint");
169 if (endpoint
!= NULL
) {
170 port
= atoi(endpoint
);
173 if (lp_interfaces() && lp_bind_interfaces_only()) {
174 num_fds
= iface_count();
182 addrs
= talloc_array(mem_ctx
, struct samba_sockaddr
, num_fds
);
184 status
= NT_STATUS_NO_MEMORY
;
187 fds
= talloc_array(mem_ctx
, int, num_fds
);
189 status
= NT_STATUS_NO_MEMORY
;
197 if (lp_interfaces() && lp_bind_interfaces_only()) {
198 for (i
=0; i
<num_fds
; i
++) {
199 const struct sockaddr_storage
*ifss
=
200 iface_n_sockaddr_storage(i
);
202 ok
= sockaddr_storage_to_samba_sockaddr(
205 i
= 0; /* nothing to close */
210 struct sockaddr_storage ss
= { .ss_family
= 0 };
213 ok
= interpret_string_addr(
214 &ss
, "::", AI_NUMERICHOST
|AI_PASSIVE
);
218 ok
= sockaddr_storage_to_samba_sockaddr(&addrs
[0], &ss
);
223 ok
= interpret_string_addr(
224 &ss
, "0.0.0.0", AI_NUMERICHOST
|AI_PASSIVE
);
229 /* num_fds set above depending on HAVE_IPV6 */
230 ok
= sockaddr_storage_to_samba_sockaddr(
231 &addrs
[num_fds
-1], &ss
);
237 for (i
=0; i
<num_fds
; i
++) {
238 status
= dcesrv_create_ncacn_ip_tcp_socket(
239 &addrs
[i
].u
.ss
, &port
, &fds
[i
]);
240 if (!NT_STATUS_IS_OK(status
)) {
243 samba_sockaddr_set_port(&addrs
[i
], port
);
246 /* Set the port in the endpoint */
247 snprintf(port_str
, sizeof(port_str
), "%"PRIu16
, port
);
249 status
= dcerpc_binding_set_string_option(b
, "endpoint", port_str
);
250 if (!NT_STATUS_IS_OK(status
)) {
251 DBG_ERR("Failed to set binding endpoint '%s': %s\n",
252 port_str
, nt_errstr(status
));
273 /********************************************************************
274 * Start listening on the ncalrpc socket
275 ********************************************************************/
277 static NTSTATUS
dcesrv_create_ncalrpc_socket(
278 struct dcerpc_binding
*b
, int *out_fd
)
281 const char *endpoint
= NULL
;
284 endpoint
= dcerpc_binding_get_string_option(b
, "endpoint");
285 if (endpoint
== NULL
) {
287 * No identifier specified: use DEFAULT or SMBD.
289 * When role is AD DC we run two rpc server instances, the one
290 * started by 'samba' and the one embedded in 'smbd'.
291 * Avoid listening in DEFAULT socket for NCALRPC as both
292 * servers will race to accept connections. In this case smbd
293 * will listen in SMBD socket and rpcint binding handle
294 * implementation will pick the right socket to use.
296 * TODO: DO NOT hardcode this value anywhere else. Rather,
297 * specify no endpoint and let the epmapper worry about it.
299 if (lp_server_role() == ROLE_ACTIVE_DIRECTORY_DC
) {
302 endpoint
= "DEFAULT";
304 status
= dcerpc_binding_set_string_option(
305 b
, "endpoint", endpoint
);
306 if (!NT_STATUS_IS_OK(status
)) {
307 DBG_ERR("Failed to set ncalrpc 'endpoint' binding "
308 "string option to '%s': %s\n",
309 endpoint
, nt_errstr(status
));
314 if (!directory_create_or_exist(lp_ncalrpc_dir(), 0755)) {
315 status
= map_nt_error_from_unix_common(errno
);
316 DBG_ERR("Failed to create ncalrpc directory '%s': %s\n",
317 lp_ncalrpc_dir(), strerror(errno
));
321 fd
= create_pipe_sock(lp_ncalrpc_dir(), endpoint
, 0755);
323 status
= map_nt_error_from_unix_common(errno
);
324 DBG_ERR("Failed to create ncalrpc socket '%s/%s': %s\n",
325 lp_ncalrpc_dir(), endpoint
, strerror(errno
));
329 DBG_DEBUG("Opened ncalrpc socket fd '%d' for '%s/%s'\n",
330 fd
, lp_ncalrpc_dir(), endpoint
);
340 NTSTATUS
dcesrv_create_binding_sockets(
341 struct dcerpc_binding
*b
,
346 enum dcerpc_transport_t transport
= dcerpc_binding_get_transport(b
);
347 size_t i
, num_fds
= 1;
351 if ((transport
== NCALRPC
) || (transport
== NCACN_NP
)) {
352 fds
= talloc(mem_ctx
, int);
354 return NT_STATUS_NO_MEMORY
;
360 status
= dcesrv_create_ncalrpc_socket(b
, fds
);
363 status
= dcesrv_create_ncacn_np_socket(b
, fds
);
366 status
= dcesrv_create_ncacn_ip_tcp_sockets(
367 b
, talloc_tos(), &num_fds
, &fds
);
370 status
= NT_STATUS_NOT_SUPPORTED
;
374 if (!NT_STATUS_IS_OK(status
)) {
379 for (i
=0; i
<num_fds
; i
++) {
380 bool ok
= smb_set_close_on_exec(fds
[i
]);
382 status
= map_nt_error_from_unix(errno
);
387 for (i
=0; i
<num_fds
; i
++) {
399 /* vim: set ts=8 sw=8 noet cindent syntax=c.doxygen: */