s4:librpc/rpc: remove some unused functions and structures from dcerpc_sock.c
[samba.git] / source4 / librpc / rpc / dcerpc_sock.c
1 /* 
2    Unix SMB/CIFS implementation.
3
4    dcerpc over standard sockets transport
5
6    Copyright (C) Andrew Tridgell 2003
7    Copyright (C) Jelmer Vernooij 2004
8    Copyright (C) Rafal Szczesniak 2006
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 "system/filesys.h"
26 #include "lib/events/events.h"
27 #include "lib/socket/socket.h"
28 #include "lib/tsocket/tsocket.h"
29 #include "libcli/composite/composite.h"
30 #include "librpc/rpc/dcerpc.h"
31 #include "librpc/rpc/dcerpc_proto.h"
32 #include "libcli/resolve/resolve.h"
33 #include "librpc/rpc/rpc_common.h"
34
35 struct pipe_open_socket_state {
36         struct dcecli_connection *conn;
37         struct socket_context *socket_ctx;
38         struct socket_address *localaddr;
39         struct socket_address *server;
40         const char *target_hostname;
41         enum dcerpc_transport_t transport;
42         struct socket_address *client;
43 };
44
45
46 static void continue_socket_connect(struct composite_context *ctx)
47 {
48         struct dcecli_connection *conn;
49         struct composite_context *c = talloc_get_type_abort(
50                 ctx->async.private_data, struct composite_context);
51         struct pipe_open_socket_state *s = talloc_get_type_abort(
52                 c->private_data, struct pipe_open_socket_state);
53         int rc;
54         int sock_fd;
55
56         /* make it easier to write a function calls */
57         conn = s->conn;
58
59         c->status = socket_connect_recv(ctx);
60         if (!NT_STATUS_IS_OK(c->status)) {
61                 DEBUG(0, ("Failed to connect host %s on port %d - %s\n", 
62                           s->server->addr, s->server->port,
63                           nt_errstr(c->status)));
64                 composite_error(c, c->status);
65                 return;
66         }
67
68         s->client = socket_get_my_addr(s->socket_ctx, s);
69         if (s->client == NULL) {
70                 TALLOC_FREE(s->socket_ctx);
71                 composite_error(c, NT_STATUS_NO_MEMORY);
72                 return;
73         }
74         sock_fd = socket_get_fd(s->socket_ctx);
75         socket_set_flags(s->socket_ctx, SOCKET_FLAG_NOCLOSE);
76         TALLOC_FREE(s->socket_ctx);
77
78         /*
79           fill in the transport methods
80         */
81         conn->transport.transport       = s->transport;
82         conn->transport.private_data    = NULL;
83
84         /*
85          * Windows uses 5840 for ncacn_ip_tcp,
86          * so we also use it (for every transport which uses bsd sockets)
87          */
88         conn->srv_max_xmit_frag = 5840;
89         conn->srv_max_recv_frag = 5840;
90
91         conn->transport.pending_reads = 0;
92         conn->server_name   = strupper_talloc(conn, s->target_hostname);
93
94         rc = tstream_bsd_existing_socket(conn, sock_fd,
95                                          &conn->transport.stream);
96         if (rc < 0) {
97                 close(sock_fd);
98                 composite_error(c, NT_STATUS_NO_MEMORY);
99                 return;
100         }
101
102         conn->transport.write_queue =
103                 tevent_queue_create(conn, "dcerpc sock write queue");
104         if (conn->transport.write_queue == NULL) {
105                 TALLOC_FREE(conn->transport.stream);
106                 composite_error(c, NT_STATUS_NO_MEMORY);
107                 return;
108         }
109
110         /* ensure we don't get SIGPIPE */
111         BlockSignals(true, SIGPIPE);
112
113         composite_done(c);
114 }
115
116
117 static struct composite_context *dcerpc_pipe_open_socket_send(TALLOC_CTX *mem_ctx,
118                                                        struct dcecli_connection *cn,
119                                                        struct socket_address *localaddr,
120                                                        struct socket_address *server,
121                                                        const char *target_hostname,
122                                                        const char *full_path,
123                                                        enum dcerpc_transport_t transport)
124 {
125         struct composite_context *c;
126         struct pipe_open_socket_state *s;
127         struct composite_context *conn_req;
128
129         c = composite_create(mem_ctx, cn->event_ctx);
130         if (c == NULL) return NULL;
131
132         s = talloc_zero(c, struct pipe_open_socket_state);
133         if (composite_nomem(s, c)) return c;
134         c->private_data = s;
135
136         s->conn      = cn;
137         s->transport = transport;
138         if (localaddr) {
139                 s->localaddr = socket_address_copy(s, localaddr);
140                 if (composite_nomem(s->localaddr, c)) return c;
141         }
142         s->server = socket_address_copy(s, server);
143         if (composite_nomem(s->server, c)) return c;
144         if (target_hostname) {
145                 s->target_hostname = talloc_strdup(s, target_hostname);
146                 if (composite_nomem(s->target_hostname, c)) return c;
147         }
148
149         c->status = socket_create(server->family, SOCKET_TYPE_STREAM, &s->socket_ctx, 0);
150         if (!composite_is_ok(c)) return c;
151
152         talloc_steal(s, s->socket_ctx);
153
154         conn_req = socket_connect_send(s->socket_ctx, s->localaddr, s->server, 0,
155                                        c->event_ctx);
156         composite_continue(c, conn_req, continue_socket_connect, c);
157         return c;
158 }
159
160 static NTSTATUS dcerpc_pipe_open_socket_recv(struct composite_context *c,
161                                              TALLOC_CTX *mem_ctx,
162                                              struct socket_address **localaddr)
163 {
164         NTSTATUS status = composite_wait(c);
165
166         if (NT_STATUS_IS_OK(status)) {
167                 struct pipe_open_socket_state *s =
168                         talloc_get_type_abort(c->private_data,
169                         struct pipe_open_socket_state);
170
171                 if (localaddr != NULL) {
172                         *localaddr = talloc_move(mem_ctx, &s->client);
173                 }
174         }
175
176         talloc_free(c);
177         return status;
178 }
179
180 struct pipe_tcp_state {
181         const char *server;
182         const char *target_hostname;
183         const char **addresses;
184         uint32_t index;
185         uint32_t port;
186         struct socket_address *localaddr;
187         struct socket_address *srvaddr;
188         struct resolve_context *resolve_ctx;
189         struct dcecli_connection *conn;
190         char *local_address;
191         char *remote_address;
192 };
193
194
195 static void continue_ip_open_socket(struct composite_context *ctx);
196 static void continue_ip_resolve_name(struct composite_context *ctx);
197
198 static void continue_ip_resolve_name(struct composite_context *ctx)
199 {
200         struct composite_context *c = talloc_get_type_abort(
201                 ctx->async.private_data, struct composite_context);
202         struct pipe_tcp_state *s = talloc_get_type_abort(
203                 c->private_data, struct pipe_tcp_state);
204         struct composite_context *sock_ip_req;
205
206         c->status = resolve_name_multiple_recv(ctx, s, &s->addresses);
207         if (!composite_is_ok(c)) return;
208
209         /* prepare server address using host ip:port and transport name */
210         s->srvaddr = socket_address_from_strings(s->conn, "ip", s->addresses[s->index], s->port);
211         s->index++;
212         if (composite_nomem(s->srvaddr, c)) return;
213
214         sock_ip_req = dcerpc_pipe_open_socket_send(c, s->conn, s->localaddr,
215                                                      s->srvaddr, s->target_hostname,
216                                                      NULL,
217                                                      NCACN_IP_TCP);
218         composite_continue(c, sock_ip_req, continue_ip_open_socket, c);
219 }
220
221
222 /*
223   Stage 2 of dcerpc_pipe_open_tcp_send: receive result of pipe open request
224   on IP transport.
225 */
226 static void continue_ip_open_socket(struct composite_context *ctx)
227 {
228         struct composite_context *c = talloc_get_type_abort(
229                 ctx->async.private_data, struct composite_context);
230         struct pipe_tcp_state *s = talloc_get_type_abort(
231                 c->private_data, struct pipe_tcp_state);
232         struct socket_address *localaddr = NULL;
233
234         /* receive result socket open request */
235         c->status = dcerpc_pipe_open_socket_recv(ctx, s, &localaddr);
236         if (!NT_STATUS_IS_OK(c->status)) {
237                 /* something went wrong... */
238                 DEBUG(0, ("Failed to connect host %s (%s) on port %d - %s.\n",
239                           s->addresses[s->index - 1], s->target_hostname,
240                           s->port, nt_errstr(c->status)));
241                 if (s->addresses[s->index]) {
242                         struct composite_context *sock_ip_req;
243                         talloc_free(s->srvaddr);
244                         /* prepare server address using host ip:port and transport name */
245                         s->srvaddr = socket_address_from_strings(s->conn, "ip", s->addresses[s->index], s->port);
246                         s->index++;
247                         if (composite_nomem(s->srvaddr, c)) return;
248
249                         sock_ip_req = dcerpc_pipe_open_socket_send(c, s->conn, s->localaddr,
250                                                                 s->srvaddr, s->target_hostname,
251                                                                 NULL,
252                                                                 NCACN_IP_TCP);
253                         composite_continue(c, sock_ip_req, continue_ip_open_socket, c);
254
255                         return;
256                 } else {
257                         composite_error(c, c->status);
258                         return;
259                 }
260         }
261
262         s->local_address = talloc_strdup(s, localaddr->addr);
263         if (composite_nomem(s->local_address, c)) return;
264         s->remote_address = talloc_strdup(s, s->addresses[s->index - 1]);
265         if (composite_nomem(s->remote_address, c)) return;
266
267         composite_done(c);
268 }
269
270 /*
271   Send rpc pipe open request to given host:port using
272   tcp/ip transport
273 */
274 struct composite_context* dcerpc_pipe_open_tcp_send(struct dcecli_connection *conn,
275                                                     const char *localaddr,
276                                                     const char *server,
277                                                     const char *target_hostname,
278                                                     uint32_t port,
279                                                     struct resolve_context *resolve_ctx)
280 {
281         struct composite_context *c;
282         struct pipe_tcp_state *s;
283         struct composite_context *resolve_req;
284         struct nbt_name name;
285
286         /* composite context allocation and setup */
287         c = composite_create(conn, conn->event_ctx);
288         if (c == NULL) return NULL;
289
290         s = talloc_zero(c, struct pipe_tcp_state);
291         if (composite_nomem(s, c)) return c;
292         c->private_data = s;
293
294         /* store input parameters in state structure */
295         s->server          = talloc_strdup(c, server);
296         if (composite_nomem(s->server, c)) return c;
297         if (target_hostname) {
298                 s->target_hostname = talloc_strdup(c, target_hostname);
299                 if (composite_nomem(s->target_hostname, c)) return c;
300         }
301         s->port            = port;
302         s->conn            = conn;
303         s->resolve_ctx     = resolve_ctx;
304         if (localaddr) {
305                 s->localaddr = socket_address_from_strings(s, "ip", localaddr, 0);
306                 /* if there is no localaddr, we pass NULL for
307                    s->localaddr, which is handled by the socket libraries as
308                    meaning no local binding address specified */
309         }
310
311         make_nbt_name_server(&name, server);
312         resolve_req = resolve_name_send(resolve_ctx, s, &name, c->event_ctx);
313         composite_continue(c, resolve_req, continue_ip_resolve_name, c);
314         return c;
315 }
316
317 /*
318   Receive result of pipe open request on tcp/ip
319 */
320 NTSTATUS dcerpc_pipe_open_tcp_recv(struct composite_context *c,
321                                    TALLOC_CTX *mem_ctx,
322                                    char **localaddr,
323                                    char **remoteaddr)
324 {
325         NTSTATUS status;
326         status = composite_wait(c);
327
328         if (NT_STATUS_IS_OK(status)) {
329                 struct pipe_tcp_state *s = talloc_get_type_abort(
330                         c->private_data, struct pipe_tcp_state);
331
332                 if (localaddr != NULL) {
333                         *localaddr = talloc_move(mem_ctx, &s->local_address);
334                 }
335                 if (remoteaddr != NULL) {
336                         *remoteaddr = talloc_move(mem_ctx, &s->remote_address);
337                 }
338         }
339
340         talloc_free(c);
341         return status;
342 }
343
344
345 struct pipe_unix_state {
346         const char *path;
347         struct socket_address *srvaddr;
348         struct dcecli_connection *conn;
349 };
350
351
352 /*
353   Stage 2 of dcerpc_pipe_open_unix_stream_send: receive result of pipe open
354   request on unix socket.
355 */
356 static void continue_unix_open_socket(struct composite_context *ctx)
357 {
358         struct composite_context *c = talloc_get_type_abort(
359                 ctx->async.private_data, struct composite_context);
360
361         c->status = dcerpc_pipe_open_socket_recv(ctx, NULL, NULL);
362         if (NT_STATUS_IS_OK(c->status)) {
363                 composite_done(c);
364                 return;
365         }
366
367         composite_error(c, c->status);
368 }
369
370
371 /*
372   Send pipe open request on unix socket
373 */
374 struct composite_context *dcerpc_pipe_open_unix_stream_send(struct dcecli_connection *conn,
375                                                             const char *path)
376 {
377         struct composite_context *c;
378         struct composite_context *sock_unix_req;
379         struct pipe_unix_state *s;
380
381         /* composite context allocation and setup */
382         c = composite_create(conn, conn->event_ctx);
383         if (c == NULL) return NULL;
384
385         s = talloc_zero(c, struct pipe_unix_state);
386         if (composite_nomem(s, c)) return c;
387         c->private_data = s;
388
389         /* store parameters in state structure */
390         s->path = talloc_strdup(c, path);
391         if (composite_nomem(s->path, c)) return c;
392         s->conn = conn;
393
394         /* prepare server address using socket path and transport name */
395         s->srvaddr = socket_address_from_strings(conn, "unix", s->path, 0);
396         if (composite_nomem(s->srvaddr, c)) return c;
397
398         /* send socket open request */
399         sock_unix_req = dcerpc_pipe_open_socket_send(c, s->conn, NULL,
400                                                      s->srvaddr, NULL,
401                                                      s->path,
402                                                      NCALRPC);
403         composite_continue(c, sock_unix_req, continue_unix_open_socket, c);
404         return c;
405 }
406
407
408 /*
409   Receive result of pipe open request on unix socket
410 */
411 NTSTATUS dcerpc_pipe_open_unix_stream_recv(struct composite_context *c)
412 {
413         NTSTATUS status = composite_wait(c);
414
415         talloc_free(c);
416         return status;
417 }
418
419
420 /*
421   Stage 2 of dcerpc_pipe_open_pipe_send: receive socket open request
422 */
423 static void continue_np_open_socket(struct composite_context *ctx)
424 {
425         struct composite_context *c = talloc_get_type_abort(
426                 ctx->async.private_data, struct composite_context);
427
428         c->status = dcerpc_pipe_open_socket_recv(ctx, NULL, NULL);
429         if (!composite_is_ok(c)) return;
430
431         composite_done(c);
432 }
433
434
435 /*
436   Send pipe open request on ncalrpc
437 */
438 struct composite_context* dcerpc_pipe_open_pipe_send(struct dcecli_connection *conn,
439                                                      const char *ncalrpc_dir,
440                                                      const char *identifier)
441 {
442         char *canon = NULL;
443
444         struct composite_context *c;
445         struct composite_context *sock_np_req;
446         struct pipe_unix_state *s;
447
448         /* composite context allocation and setup */
449         c = composite_create(conn, conn->event_ctx);
450         if (c == NULL) return NULL;
451
452         s = talloc_zero(c, struct pipe_unix_state);
453         if (composite_nomem(s, c)) return c;
454         c->private_data = s;
455
456         /* store parameters in state structure */
457         canon = talloc_strdup(s, identifier);
458         if (composite_nomem(canon, c)) return c;
459         s->conn = conn;
460
461         string_replace(canon, '/', '\\');
462         s->path = talloc_asprintf(canon, "%s/%s", ncalrpc_dir, canon);
463         if (composite_nomem(s->path, c)) return c;
464
465         /* prepare server address using path and transport name */
466         s->srvaddr = socket_address_from_strings(conn, "unix", s->path, 0);
467         if (composite_nomem(s->srvaddr, c)) return c;
468
469         /* send socket open request */
470         sock_np_req = dcerpc_pipe_open_socket_send(c, s->conn, NULL, s->srvaddr, NULL, s->path, NCALRPC);
471         composite_continue(c, sock_np_req, continue_np_open_socket, c);
472         return c;
473 }
474
475
476 /*
477   Receive result of pipe open request on ncalrpc
478 */
479 NTSTATUS dcerpc_pipe_open_pipe_recv(struct composite_context *c)
480 {
481         NTSTATUS status = composite_wait(c);
482         
483         talloc_free(c);
484         return status;
485 }
486
487
488 /*
489   Open a rpc pipe on a named pipe - sync version
490 */
491 NTSTATUS dcerpc_pipe_open_pipe(struct dcecli_connection *conn, const char *ncalrpc_dir, const char *identifier)
492 {
493         struct composite_context *c = dcerpc_pipe_open_pipe_send(conn, ncalrpc_dir, identifier);
494         return dcerpc_pipe_open_pipe_recv(c);
495 }