587e8259f86466bf422cd34548484e109a1e2d3d
[bbaumbach/samba-autobuild/.git] / source4 / rpc_server / dcerpc_sock.c
1 /* 
2    Unix SMB/CIFS implementation.
3
4    server side dcerpc using various kinds of sockets (tcp, unix domain)
5
6    Copyright (C) Andrew Tridgell 2003
7    Copyright (C) Stefan (metze) Metzmacher 2004-2005  
8    Copyright (C) Jelmer Vernooij 2004
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 2 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, write to the Free Software
22    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23 */
24
25 #include "includes.h"
26 #include "lib/socket/socket.h"
27 #include "lib/events/events.h"
28 #include "rpc_server/dcerpc_server.h"
29 #include "smbd/service_stream.h"
30 #include "smbd/service.h"
31 #include "lib/messaging/irpc.h"
32 #include "system/network.h"
33 #include "netif/netif.h"
34 #include "auth/auth.h"
35
36 struct dcesrv_socket_context {
37         const struct dcesrv_endpoint *endpoint;
38         struct dcesrv_context *dcesrv_ctx;
39 };
40
41 /*
42   write_fn callback for dcesrv_output()
43 */
44 static NTSTATUS dcerpc_write_fn(void *private_data, DATA_BLOB *out, size_t *nwritten)
45 {
46         NTSTATUS status;
47         struct socket_context *sock = talloc_get_type(private_data, struct socket_context);
48         size_t sendlen;
49
50         status = socket_send(sock, out, &sendlen, 0);
51         NT_STATUS_IS_ERR_RETURN(status);
52
53         *nwritten = sendlen;
54         return status;
55 }
56
57 static void dcesrv_terminate_connection(struct dcesrv_connection *dce_conn, const char *reason)
58 {
59         struct stream_connection *srv_conn;
60         srv_conn = talloc_get_type(dce_conn->transport.private_data,
61                                    struct stream_connection);
62
63         stream_terminate_connection(srv_conn, reason);
64 }
65
66 static void dcesrv_sock_report_output_data(struct dcesrv_connection *dcesrv_conn)
67 {
68         struct stream_connection *srv_conn;
69         srv_conn = talloc_get_type(dcesrv_conn->transport.private_data,
70                                    struct stream_connection);
71
72         if (srv_conn && srv_conn->event.fde) {
73                 EVENT_FD_WRITEABLE(srv_conn->event.fde);
74         }
75 }
76
77 static struct socket_address *dcesrv_sock_get_my_addr(struct dcesrv_connection *dcesrv_conn, TALLOC_CTX *mem_ctx)
78 {
79         struct stream_connection *srv_conn;
80         srv_conn = talloc_get_type(dcesrv_conn->transport.private_data,
81                                    struct stream_connection);
82
83         return socket_get_my_addr(srv_conn->socket, mem_ctx);
84 }
85
86 static struct socket_address *dcesrv_sock_get_peer_addr(struct dcesrv_connection *dcesrv_conn, TALLOC_CTX *mem_ctx)
87 {
88         struct stream_connection *srv_conn;
89         srv_conn = talloc_get_type(dcesrv_conn->transport.private_data,
90                                    struct stream_connection);
91
92         return socket_get_peer_addr(srv_conn->socket, mem_ctx);
93 }
94
95 static void dcesrv_sock_accept(struct stream_connection *srv_conn)
96 {
97         NTSTATUS status;
98         struct dcesrv_socket_context *dcesrv_sock = 
99                 talloc_get_type(srv_conn->private, struct dcesrv_socket_context);
100         struct dcesrv_connection *dcesrv_conn = NULL;
101         struct auth_session_info *session_info = NULL;
102
103         status = auth_anonymous_session_info(srv_conn, &session_info);
104         if (!NT_STATUS_IS_OK(status)) {
105                 DEBUG(0,("dcesrv_sock_accept: auth_anonymous_session_info failed: %s\n", 
106                         nt_errstr(status)));
107                 stream_terminate_connection(srv_conn, nt_errstr(status));
108                 return;
109         }
110
111         status = dcesrv_endpoint_connect(dcesrv_sock->dcesrv_ctx,
112                                          srv_conn,
113                                          dcesrv_sock->endpoint,
114                                          session_info,
115                                          srv_conn->event.ctx,
116                                          DCESRV_CALL_STATE_FLAG_MAY_ASYNC,
117                                          &dcesrv_conn);
118         if (!NT_STATUS_IS_OK(status)) {
119                 DEBUG(0,("dcesrv_sock_accept: dcesrv_endpoint_connect failed: %s\n", 
120                         nt_errstr(status)));
121                 stream_terminate_connection(srv_conn, nt_errstr(status));
122                 return;
123         }
124
125         dcesrv_conn->transport.private_data             = srv_conn;
126         dcesrv_conn->transport.report_output_data       = dcesrv_sock_report_output_data;
127         dcesrv_conn->transport.get_my_addr              = dcesrv_sock_get_my_addr;
128         dcesrv_conn->transport.get_peer_addr            = dcesrv_sock_get_peer_addr;
129
130         srv_conn->private = dcesrv_conn;
131
132         irpc_add_name(srv_conn->msg_ctx, "rpc_server");
133
134         return; 
135 }
136
137 static void dcesrv_sock_recv(struct stream_connection *conn, uint16_t flags)
138 {
139         NTSTATUS status;
140         struct dcesrv_connection *dce_conn = talloc_get_type(conn->private, struct dcesrv_connection);
141         DATA_BLOB tmp_blob;
142         size_t nread;
143
144         if (dce_conn->processing) {
145                 EVENT_FD_NOT_READABLE(conn->event.fde);
146                 return;
147         }
148
149         tmp_blob = data_blob_talloc(conn->socket, NULL, 0x1000);
150         if (tmp_blob.data == NULL) {
151                 dcesrv_terminate_connection(dce_conn, "out of memory");
152                 return;
153         }
154
155         status = socket_recv(conn->socket, tmp_blob.data, tmp_blob.length, &nread, 0);
156         if (NT_STATUS_IS_ERR(status)) {
157                 dcesrv_terminate_connection(dce_conn, nt_errstr(status));
158                 return;
159         }
160         if (nread == 0) {
161                 talloc_free(tmp_blob.data);
162                 return;
163         }
164
165         tmp_blob.length = nread;
166
167         dce_conn->processing = True;
168         status = dcesrv_input(dce_conn, &tmp_blob);
169         dce_conn->processing = False;
170         talloc_free(tmp_blob.data);
171
172         EVENT_FD_READABLE(conn->event.fde);
173
174         if (!NT_STATUS_IS_OK(status)) {
175                 dcesrv_terminate_connection(dce_conn, nt_errstr(status));
176                 return;
177         }
178
179         if (dce_conn->call_list && dce_conn->call_list->replies) {
180                 EVENT_FD_WRITEABLE(conn->event.fde);
181         }
182 }
183
184 static void dcesrv_sock_send(struct stream_connection *conn, uint16_t flags)
185 {
186         struct dcesrv_connection *dce_conn = talloc_get_type(conn->private, struct dcesrv_connection);
187         NTSTATUS status;
188
189         status = dcesrv_output(dce_conn, conn->socket, dcerpc_write_fn);
190         if (NT_STATUS_IS_ERR(status)) {
191                 dcesrv_terminate_connection(dce_conn, "eof on socket");
192                 return;
193         }
194
195         if (!dce_conn->call_list || !dce_conn->call_list->replies) {
196                 EVENT_FD_NOT_WRITEABLE(conn->event.fde);
197         }
198 }
199
200
201 static const struct stream_server_ops dcesrv_stream_ops = {
202         .name                   = "rpc",
203         .accept_connection      = dcesrv_sock_accept,
204         .recv_handler           = dcesrv_sock_recv,
205         .send_handler           = dcesrv_sock_send,
206 };
207
208
209
210 NTSTATUS dcesrv_add_ep_unix(struct dcesrv_context *dce_ctx, struct dcesrv_endpoint *e,
211                                     struct event_context *event_ctx, const struct model_ops *model_ops)
212 {
213         struct dcesrv_socket_context *dcesrv_sock;
214         uint16_t port = 1;
215         NTSTATUS status;
216
217         dcesrv_sock = talloc(event_ctx, struct dcesrv_socket_context);
218         NT_STATUS_HAVE_NO_MEMORY(dcesrv_sock);
219
220         /* remember the endpoint of this socket */
221         dcesrv_sock->endpoint           = e;
222         dcesrv_sock->dcesrv_ctx         = talloc_reference(dcesrv_sock, dce_ctx);
223
224         status = stream_setup_socket(event_ctx, model_ops, &dcesrv_stream_ops, 
225                                      "unix", e->ep_description->endpoint, &port, 
226                                      dcesrv_sock);
227         if (!NT_STATUS_IS_OK(status)) {
228                 DEBUG(0,("service_setup_stream_socket(path=%s) failed - %s\n",
229                          e->ep_description->endpoint, nt_errstr(status)));
230         }
231
232         return status;
233 }
234
235 NTSTATUS dcesrv_add_ep_ncalrpc(struct dcesrv_context *dce_ctx, struct dcesrv_endpoint *e,
236                                        struct event_context *event_ctx, const struct model_ops *model_ops)
237 {
238         struct dcesrv_socket_context *dcesrv_sock;
239         uint16_t port = 1;
240         char *full_path;
241         NTSTATUS status;
242
243         if (!e->ep_description->endpoint) {
244                 /* No identifier specified: use DEFAULT. 
245                  * DO NOT hardcode this value anywhere else. Rather, specify 
246                  * no endpoint and let the epmapper worry about it. */
247                 e->ep_description->endpoint = talloc_strdup(dce_ctx, "DEFAULT");
248         }
249
250         full_path = talloc_asprintf(dce_ctx, "%s/%s", lp_ncalrpc_dir(), e->ep_description->endpoint);
251
252         dcesrv_sock = talloc(event_ctx, struct dcesrv_socket_context);
253         NT_STATUS_HAVE_NO_MEMORY(dcesrv_sock);
254
255         /* remember the endpoint of this socket */
256         dcesrv_sock->endpoint           = e;
257         dcesrv_sock->dcesrv_ctx         = talloc_reference(dcesrv_sock, dce_ctx);
258
259         status = stream_setup_socket(event_ctx, model_ops, &dcesrv_stream_ops, 
260                                      "unix", full_path, &port, dcesrv_sock);
261         if (!NT_STATUS_IS_OK(status)) {
262                 DEBUG(0,("service_setup_stream_socket(identifier=%s,path=%s) failed - %s\n",
263                          e->ep_description->endpoint, full_path, nt_errstr(status)));
264         }
265         return status;
266 }
267
268 /*
269   add a socket address to the list of events, one event per dcerpc endpoint
270 */
271 static NTSTATUS add_socket_rpc_tcp_iface(struct dcesrv_context *dce_ctx, struct dcesrv_endpoint *e,
272                                          struct event_context *event_ctx, const struct model_ops *model_ops,
273                                          const char *address)
274 {
275         struct dcesrv_socket_context *dcesrv_sock;
276         uint16_t port = 0;
277         NTSTATUS status;
278                         
279         if (e->ep_description->endpoint) {
280                 port = atoi(e->ep_description->endpoint);
281         }
282
283         dcesrv_sock = talloc(event_ctx, struct dcesrv_socket_context);
284         NT_STATUS_HAVE_NO_MEMORY(dcesrv_sock);
285
286         /* remember the endpoint of this socket */
287         dcesrv_sock->endpoint           = e;
288         dcesrv_sock->dcesrv_ctx         = talloc_reference(dcesrv_sock, dce_ctx);
289
290         status = stream_setup_socket(event_ctx, model_ops, &dcesrv_stream_ops, 
291                                      "ipv4", address, &port, dcesrv_sock);
292         if (!NT_STATUS_IS_OK(status)) {
293                 DEBUG(0,("service_setup_stream_socket(address=%s,port=%u) failed - %s\n", 
294                          address, port, nt_errstr(status)));
295         }
296
297         if (e->ep_description->endpoint == NULL) {
298                 e->ep_description->endpoint = talloc_asprintf(dce_ctx, "%d", port);
299         }
300
301         return status;
302 }
303
304 NTSTATUS dcesrv_add_ep_tcp(struct dcesrv_context *dce_ctx, struct dcesrv_endpoint *e,
305                                    struct event_context *event_ctx, const struct model_ops *model_ops)
306 {
307         NTSTATUS status;
308
309         /* Add TCP/IP sockets */
310         if (lp_interfaces() && lp_bind_interfaces_only()) {
311                 int num_interfaces = iface_count();
312                 int i;
313                 for(i = 0; i < num_interfaces; i++) {
314                         const char *address = iface_n_ip(i);
315                         status = add_socket_rpc_tcp_iface(dce_ctx, e, event_ctx, model_ops, address);
316                         NT_STATUS_NOT_OK_RETURN(status);
317                 }
318         } else {
319                 status = add_socket_rpc_tcp_iface(dce_ctx, e, event_ctx, model_ops, lp_socket_address());
320                 NT_STATUS_NOT_OK_RETURN(status);
321         }
322
323         return NT_STATUS_OK;
324 }
325
326