2 Unix SMB/CIFS implementation.
4 server side dcerpc using various kinds of sockets (tcp, unix domain)
6 Copyright (C) Andrew Tridgell 2003
7 Copyright (C) Stefan (metze) Metzmacher 2004-2005
8 Copyright (C) Jelmer Vernooij 2004
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 2 of the License, or
13 (at your option) any later version.
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.
20 You should have received a copy of the GNU General Public License
21 along with this program; if not, write to the Free Software
22 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
26 #include "system/filesys.h"
27 #include "lib/events/events.h"
28 #include "rpc_server/dcerpc_server.h"
29 #include "smbd/service_stream.h"
31 struct dcesrv_socket_context {
32 const struct dcesrv_endpoint *endpoint;
33 struct dcesrv_context *dcesrv_ctx;
37 write_fn callback for dcesrv_output()
39 static ssize_t dcerpc_write_fn(void *private, DATA_BLOB *out)
42 struct socket_context *sock = private;
45 status = socket_send(sock, out, &sendlen, 0);
46 if (NT_STATUS_IS_ERR(status)) {
53 static void dcesrv_terminate_connection(struct dcesrv_connection *dce_conn, const char *reason)
55 stream_terminate_connection(dce_conn->srv_conn, reason);
59 void dcesrv_sock_accept(struct stream_connection *srv_conn)
62 struct dcesrv_socket_context *dcesrv_sock =
63 talloc_get_type(srv_conn->private, struct dcesrv_socket_context);
64 struct dcesrv_connection *dcesrv_conn = NULL;
66 status = dcesrv_endpoint_connect(dcesrv_sock->dcesrv_ctx,
68 dcesrv_sock->endpoint,
71 if (!NT_STATUS_IS_OK(status)) {
72 DEBUG(0,("dcesrv_sock_accept: dcesrv_endpoint_connect failed: %s\n",
77 srv_conn->private = dcesrv_conn;
82 void dcesrv_sock_recv(struct stream_connection *conn, uint16_t flags)
85 struct dcesrv_connection *dce_conn = talloc_get_type(conn->private, struct dcesrv_connection);
89 tmp_blob = data_blob_talloc(conn->socket, NULL, 0x1000);
90 if (tmp_blob.data == NULL) {
91 dcesrv_terminate_connection(dce_conn, "out of memory");
95 status = socket_recv(conn->socket, tmp_blob.data, tmp_blob.length, &nread, 0);
96 if (NT_STATUS_IS_ERR(status)) {
97 dcesrv_terminate_connection(dce_conn, nt_errstr(status));
101 talloc_free(tmp_blob.data);
105 tmp_blob.length = nread;
107 status = dcesrv_input(dce_conn, &tmp_blob);
108 talloc_free(tmp_blob.data);
110 if (!NT_STATUS_IS_OK(status)) {
111 dcesrv_terminate_connection(dce_conn, nt_errstr(status));
115 if (dce_conn->call_list && dce_conn->call_list->replies) {
116 EVENT_FD_WRITEABLE(conn->event.fde);
120 void dcesrv_sock_send(struct stream_connection *conn, uint16_t flags)
122 struct dcesrv_connection *dce_conn = talloc_get_type(conn->private, struct dcesrv_connection);
125 status = dcesrv_output(dce_conn, conn->socket, dcerpc_write_fn);
126 if (!NT_STATUS_IS_OK(status)) {
127 dcesrv_terminate_connection(dce_conn, "eof on socket");
131 if (!dce_conn->call_list || !dce_conn->call_list->replies) {
132 EVENT_FD_NOT_WRITEABLE(conn->event.fde);
137 static const struct stream_server_ops dcesrv_stream_ops = {
139 .accept_connection = dcesrv_sock_accept,
140 .recv_handler = dcesrv_sock_recv,
141 .send_handler = dcesrv_sock_send,
146 static NTSTATUS add_socket_rpc_unix(struct dcesrv_context *dce_ctx, struct dcesrv_endpoint *e,
147 struct event_context *event_ctx, const struct model_ops *model_ops)
149 struct dcesrv_socket_context *dcesrv_sock;
153 dcesrv_sock = talloc(dce_ctx, struct dcesrv_socket_context);
154 NT_STATUS_HAVE_NO_MEMORY(dcesrv_sock);
156 /* remember the endpoint of this socket */
157 dcesrv_sock->endpoint = e;
158 dcesrv_sock->dcesrv_ctx = talloc_reference(dcesrv_sock, dce_ctx);
160 status = stream_setup_socket(event_ctx, model_ops, &dcesrv_stream_ops,
161 "unix", e->ep_description.endpoint, &port,
163 if (!NT_STATUS_IS_OK(status)) {
164 DEBUG(0,("service_setup_stream_socket(path=%s) failed - %s\n",
165 e->ep_description.endpoint, nt_errstr(status)));
171 static NTSTATUS add_socket_rpc_ncalrpc(struct dcesrv_context *dce_ctx, struct dcesrv_endpoint *e,
172 struct event_context *event_ctx, const struct model_ops *model_ops)
174 struct dcesrv_socket_context *dcesrv_sock;
179 if (!e->ep_description.endpoint) {
180 /* No identifier specified: use DEFAULT.
181 * DO NOT hardcode this value anywhere else. Rather, specify
182 * no endpoint and let the epmapper worry about it. */
183 e->ep_description.endpoint = talloc_strdup(dce_ctx, "DEFAULT");
186 full_path = talloc_asprintf(dce_ctx, "%s/%s", lp_ncalrpc_dir(), e->ep_description.endpoint);
188 dcesrv_sock = talloc(dce_ctx, struct dcesrv_socket_context);
189 NT_STATUS_HAVE_NO_MEMORY(dcesrv_sock);
191 /* remember the endpoint of this socket */
192 dcesrv_sock->endpoint = e;
193 dcesrv_sock->dcesrv_ctx = dce_ctx;
195 status = stream_setup_socket(event_ctx, model_ops, &dcesrv_stream_ops,
196 "unix", full_path, &port, dcesrv_sock);
197 if (!NT_STATUS_IS_OK(status)) {
198 DEBUG(0,("service_setup_stream_socket(identifier=%s,path=%s) failed - %s\n",
199 e->ep_description.endpoint, full_path, nt_errstr(status)));
205 add a socket address to the list of events, one event per dcerpc endpoint
207 static NTSTATUS add_socket_rpc_tcp_iface(struct dcesrv_context *dce_ctx, struct dcesrv_endpoint *e,
208 struct event_context *event_ctx, const struct model_ops *model_ops,
211 struct dcesrv_socket_context *dcesrv_sock;
215 if (e->ep_description.endpoint) {
216 port = atoi(e->ep_description.endpoint);
219 dcesrv_sock = talloc(dce_ctx, struct dcesrv_socket_context);
220 NT_STATUS_HAVE_NO_MEMORY(dcesrv_sock);
222 /* remember the endpoint of this socket */
223 dcesrv_sock->endpoint = e;
224 dcesrv_sock->dcesrv_ctx = dce_ctx;
226 status = stream_setup_socket(event_ctx, model_ops, &dcesrv_stream_ops,
227 "ipv4", address, &port, dcesrv_sock);
228 if (!NT_STATUS_IS_OK(status)) {
229 DEBUG(0,("service_setup_stream_socket(address=%s,port=%u) failed - %s\n",
230 address, port, nt_errstr(status)));
233 if (e->ep_description.endpoint == NULL) {
234 e->ep_description.endpoint = talloc_asprintf(dce_ctx, "%d", port);
240 static NTSTATUS add_socket_rpc_tcp(struct dcesrv_context *dce_ctx, struct dcesrv_endpoint *e,
241 struct event_context *event_ctx, const struct model_ops *model_ops)
245 /* Add TCP/IP sockets */
246 if (lp_interfaces() && lp_bind_interfaces_only()) {
247 int num_interfaces = iface_count();
249 for(i = 0; i < num_interfaces; i++) {
250 const char *address = iface_n_ip(i);
251 status = add_socket_rpc_tcp_iface(dce_ctx, e, event_ctx, model_ops, address);
252 NT_STATUS_NOT_OK_RETURN(status);
255 status = add_socket_rpc_tcp_iface(dce_ctx, e, event_ctx, model_ops, lp_socket_address());
256 NT_STATUS_NOT_OK_RETURN(status);
262 /****************************************************************************
263 Open the listening sockets for RPC over NCACN_IP_TCP/NCALRPC/NCACN_UNIX_STREAM
264 ****************************************************************************/
265 NTSTATUS dcesrv_sock_init(struct dcesrv_context *dce_ctx,
266 struct event_context *event_ctx, const struct model_ops *model_ops)
268 struct dcesrv_endpoint *e;
271 /* Make sure the directory for NCALRPC exists */
272 if (!directory_exist(lp_ncalrpc_dir())) {
273 mkdir(lp_ncalrpc_dir(), 0755);
276 for (e=dce_ctx->endpoint_list;e;e=e->next) {
277 switch (e->ep_description.transport) {
278 case NCACN_UNIX_STREAM:
279 status = add_socket_rpc_unix(dce_ctx, e, event_ctx, model_ops);
280 NT_STATUS_NOT_OK_RETURN(status);
284 status = add_socket_rpc_ncalrpc(dce_ctx, e, event_ctx, model_ops);
285 NT_STATUS_NOT_OK_RETURN(status);
289 status = add_socket_rpc_tcp(dce_ctx, e, event_ctx, model_ops);
290 NT_STATUS_NOT_OK_RETURN(status);