1e2b4cde484769a8ee375d72185a2686178b0090
[bbaumbach/samba-autobuild/.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 "lib/events/events.h"
26 #include "lib/socket/socket.h"
27 #include "lib/stream/packet.h"
28 #include "libcli/composite/composite.h"
29 #include "librpc/rpc/dcerpc.h"
30 #include "librpc/rpc/dcerpc_proto.h"
31 #include "libcli/resolve/resolve.h"
32 #include "param/param.h"
33
34 /* transport private information used by general socket pipe transports */
35 struct sock_private {
36         struct fd_event *fde;
37         struct socket_context *sock;
38         char *server_name;
39
40         struct packet_context *packet;
41         uint32_t pending_reads;
42
43         struct resolve_context *resolve_ctx;
44         const char *path; /* For ncacn_unix_sock and ncalrpc */
45 };
46
47
48 /*
49   mark the socket dead
50 */
51 static void sock_dead(struct dcerpc_connection *p, NTSTATUS status)
52 {
53         struct sock_private *sock = (struct sock_private *)p->transport.private_data;
54
55         if (!sock) return;
56
57         if (sock->packet) {
58                 packet_recv_disable(sock->packet);
59                 packet_set_fde(sock->packet, NULL);
60                 packet_set_socket(sock->packet, NULL);
61         }
62
63         if (sock->fde) {
64                 talloc_free(sock->fde);
65                 sock->fde = NULL;
66         }
67
68         if (sock->sock) {
69                 talloc_free(sock->sock);
70                 sock->sock = NULL;
71         }
72
73         if (NT_STATUS_EQUAL(NT_STATUS_UNSUCCESSFUL, status)) {
74                 status = NT_STATUS_UNEXPECTED_NETWORK_ERROR;
75         }
76
77         if (NT_STATUS_EQUAL(NT_STATUS_OK, status)) {
78                 status = NT_STATUS_END_OF_FILE;
79         }
80
81         if (p->transport.recv_data) {
82                 p->transport.recv_data(p, NULL, status);
83         }
84 }
85
86
87 /*
88   handle socket recv errors
89 */
90 static void sock_error_handler(void *private, NTSTATUS status)
91 {
92         struct dcerpc_connection *p = talloc_get_type(private, 
93                                                       struct dcerpc_connection);
94         sock_dead(p, status);
95 }
96
97 /*
98   check if a blob is a complete packet
99 */
100 static NTSTATUS sock_complete_packet(void *private, DATA_BLOB blob, size_t *size)
101 {
102         if (blob.length < DCERPC_FRAG_LEN_OFFSET+2) {
103                 return STATUS_MORE_ENTRIES;
104         }
105         *size = dcerpc_get_frag_length(&blob);
106         if (*size > blob.length) {
107                 return STATUS_MORE_ENTRIES;
108         }
109         return NT_STATUS_OK;
110 }
111
112 /*
113   process recv requests
114 */
115 static NTSTATUS sock_process_recv(void *private, DATA_BLOB blob)
116 {
117         struct dcerpc_connection *p = talloc_get_type(private, 
118                                                       struct dcerpc_connection);
119         struct sock_private *sock = (struct sock_private *)p->transport.private_data;
120         sock->pending_reads--;
121         if (sock->pending_reads == 0) {
122                 packet_recv_disable(sock->packet);
123         }
124         p->transport.recv_data(p, &blob, NT_STATUS_OK);
125         return NT_STATUS_OK;
126 }
127
128 /*
129   called when a IO is triggered by the events system
130 */
131 static void sock_io_handler(struct event_context *ev, struct fd_event *fde, 
132                             uint16_t flags, void *private)
133 {
134         struct dcerpc_connection *p = talloc_get_type(private, 
135                                                       struct dcerpc_connection);
136         struct sock_private *sock = (struct sock_private *)p->transport.private_data;
137
138         if (flags & EVENT_FD_WRITE) {
139                 packet_queue_run(sock->packet);
140                 return;
141         }
142
143         if (sock->sock == NULL) {
144                 return;
145         }
146
147         if (flags & EVENT_FD_READ) {
148                 packet_recv(sock->packet);
149         }
150 }
151
152 /* 
153    initiate a read request - not needed for dcerpc sockets
154 */
155 static NTSTATUS sock_send_read(struct dcerpc_connection *p)
156 {
157         struct sock_private *sock = (struct sock_private *)p->transport.private_data;
158         sock->pending_reads++;
159         if (sock->pending_reads == 1) {
160                 packet_recv_enable(sock->packet);
161         }
162         return NT_STATUS_OK;
163 }
164
165 /* 
166    send an initial pdu in a multi-pdu sequence
167 */
168 static NTSTATUS sock_send_request(struct dcerpc_connection *p, DATA_BLOB *data, 
169                                   bool trigger_read)
170 {
171         struct sock_private *sock = (struct sock_private *)p->transport.private_data;
172         DATA_BLOB blob;
173         NTSTATUS status;
174
175         if (sock->sock == NULL) {
176                 return NT_STATUS_CONNECTION_DISCONNECTED;
177         }
178
179         blob = data_blob_talloc(sock->packet, data->data, data->length);
180         if (blob.data == NULL) {
181                 return NT_STATUS_NO_MEMORY;
182         }
183
184         status = packet_send(sock->packet, blob);
185         if (!NT_STATUS_IS_OK(status)) {
186                 return status;
187         }
188
189         if (trigger_read) {
190                 sock_send_read(p);
191         }
192
193         return NT_STATUS_OK;
194 }
195
196 /* 
197    shutdown sock pipe connection
198 */
199 static NTSTATUS sock_shutdown_pipe(struct dcerpc_connection *p, NTSTATUS status)
200 {
201         struct sock_private *sock = (struct sock_private *)p->transport.private_data;
202
203         if (sock && sock->sock) {
204                 sock_dead(p, status);
205         }
206
207         return status;
208 }
209
210 /*
211   return sock server name
212 */
213 static const char *sock_peer_name(struct dcerpc_connection *p)
214 {
215         struct sock_private *sock = talloc_get_type(p->transport.private_data, struct sock_private);
216         return sock->server_name;
217 }
218
219 /*
220   return remote name we make the actual connection (good for kerberos) 
221 */
222 static const char *sock_target_hostname(struct dcerpc_connection *p)
223 {
224         struct sock_private *sock = talloc_get_type(p->transport.private_data, struct sock_private);
225         return sock->server_name;
226 }
227
228
229 struct pipe_open_socket_state {
230         struct dcerpc_connection *conn;
231         struct socket_context *socket_ctx;
232         struct sock_private *sock;
233         struct socket_address *server;
234         const char *target_hostname;
235         enum dcerpc_transport_t transport;
236 };
237
238
239 static void continue_socket_connect(struct composite_context *ctx)
240 {
241         struct dcerpc_connection *conn;
242         struct sock_private *sock;
243         struct composite_context *c = talloc_get_type(ctx->async.private_data,
244                                                       struct composite_context);
245         struct pipe_open_socket_state *s = talloc_get_type(c->private_data,
246                                                            struct pipe_open_socket_state);
247
248         /* make it easier to write a function calls */
249         conn = s->conn;
250         sock = s->sock;
251
252         c->status = socket_connect_recv(ctx);
253         if (!NT_STATUS_IS_OK(c->status)) {
254                 DEBUG(0, ("Failed to connect host %s on port %d - %s\n", 
255                           s->server->addr, s->server->port,
256                           nt_errstr(c->status)));
257                 composite_error(c, c->status);
258                 return;
259         }
260
261         /*
262           fill in the transport methods
263         */
264         conn->transport.transport       = s->transport;
265         conn->transport.private_data    = NULL;
266
267         conn->transport.send_request    = sock_send_request;
268         conn->transport.send_read       = sock_send_read;
269         conn->transport.recv_data       = NULL;
270
271         conn->transport.shutdown_pipe   = sock_shutdown_pipe;
272         conn->transport.peer_name       = sock_peer_name;
273         conn->transport.target_hostname = sock_target_hostname;
274
275         sock->sock          = s->socket_ctx;
276         sock->pending_reads = 0;
277         sock->server_name   = strupper_talloc(sock, s->target_hostname);
278
279         sock->fde = event_add_fd(conn->event_ctx, sock->sock, socket_get_fd(sock->sock),
280                                  EVENT_FD_READ, sock_io_handler, conn);
281         
282         conn->transport.private_data = sock;
283
284         sock->packet = packet_init(sock);
285         if (sock->packet == NULL) {
286                 composite_error(c, NT_STATUS_NO_MEMORY);
287                 talloc_free(sock);
288                 return;
289         }
290
291         packet_set_private(sock->packet, conn);
292         packet_set_socket(sock->packet, sock->sock);
293         packet_set_callback(sock->packet, sock_process_recv);
294         packet_set_full_request(sock->packet, sock_complete_packet);
295         packet_set_error_handler(sock->packet, sock_error_handler);
296         packet_set_event_context(sock->packet, conn->event_ctx);
297         packet_set_fde(sock->packet, sock->fde);
298         packet_set_serialise(sock->packet);
299         packet_set_initial_read(sock->packet, 16);
300
301         /* ensure we don't get SIGPIPE */
302         BlockSignals(true, SIGPIPE);
303
304         composite_done(c);
305 }
306
307
308 static struct composite_context *dcerpc_pipe_open_socket_send(TALLOC_CTX *mem_ctx,
309                                                        struct dcerpc_connection *cn,
310                                                        struct resolve_context *resolve_context,
311                                                        struct socket_address *server,
312                                                        const char *target_hostname,
313                                                        const char *full_path,
314                                                        enum dcerpc_transport_t transport)
315 {
316         struct composite_context *c;
317         struct pipe_open_socket_state *s;
318         struct composite_context *conn_req;
319
320         c = composite_create(mem_ctx, cn->event_ctx);
321         if (c == NULL) return NULL;
322
323         s = talloc_zero(c, struct pipe_open_socket_state);
324         if (composite_nomem(s, c)) return c;
325         c->private_data = s;
326
327         s->conn      = cn;
328         s->transport = transport;
329         s->server    = talloc_reference(c, server);
330         if (composite_nomem(s->server, c)) return c;
331         s->target_hostname = talloc_reference(s, target_hostname);
332
333         s->sock = talloc(cn, struct sock_private);
334         if (composite_nomem(s->sock, c)) return c;
335
336         c->status = socket_create(server->family, SOCKET_TYPE_STREAM, &s->socket_ctx, 0);
337         if (!composite_is_ok(c)) return c;
338
339         talloc_steal(s->sock, s->socket_ctx);
340
341         s->sock->resolve_ctx = resolve_context;
342         s->sock->path = talloc_reference(s->sock, full_path);
343
344         conn_req = socket_connect_send(s->socket_ctx, NULL, s->server, 0, 
345                                        resolve_context, 
346                                        c->event_ctx);
347         composite_continue(c, conn_req, continue_socket_connect, c);
348         return c;
349 }
350
351
352 static NTSTATUS dcerpc_pipe_open_socket_recv(struct composite_context *c)
353 {
354         NTSTATUS status = composite_wait(c);
355
356         talloc_free(c);
357         return status;
358 }
359
360 struct pipe_tcp_state {
361         const char *server;
362         const char *target_hostname;
363         const char *address;
364         uint32_t port;
365         struct socket_address *srvaddr;
366         struct resolve_context *resolve_ctx;
367         struct dcerpc_connection *conn;
368 };
369
370
371 #if 0 /* disabled till we can resolve names to ipv6 addresses */
372 static void continue_ipv6_open_socket(struct composite_context *ctx);
373 #endif
374 static void continue_ipv4_open_socket(struct composite_context *ctx);
375 static void continue_ip_resolve_name(struct composite_context *ctx);
376
377 static void continue_ip_resolve_name(struct composite_context *ctx)
378 {
379         struct composite_context *c = talloc_get_type(ctx->async.private_data,
380                                                       struct composite_context);
381         struct pipe_tcp_state *s = talloc_get_type(c->private_data,
382                                                    struct pipe_tcp_state);
383         struct composite_context *sock_ipv4_req;
384
385         c->status = resolve_name_recv(ctx, s, &s->address);
386         if (!composite_is_ok(c)) return;
387
388         /* prepare server address using host ip:port and transport name */
389         s->srvaddr = socket_address_from_strings(s->conn, "ipv4", s->address, s->port);
390         if (composite_nomem(s->srvaddr, c)) return;
391
392         /* resolve_nbt_name gives only ipv4 ... - send socket open request */
393         sock_ipv4_req = dcerpc_pipe_open_socket_send(c, s->conn,
394                                                      s->resolve_ctx,
395                                                      s->srvaddr, s->target_hostname,
396                                                      NULL,
397                                                      NCACN_IP_TCP);
398         composite_continue(c, sock_ipv4_req, continue_ipv4_open_socket, c);
399 }
400
401 /*
402   Stage 2 of dcerpc_pipe_open_tcp_send: receive result of pipe open request
403   on IPv6 and send the request on IPv4 unless IPv6 transport succeeded.
404 */
405 #if 0 /* disabled till we can resolve names to ipv6 addresses */
406 static void continue_ipv6_open_socket(struct composite_context *ctx)
407 {
408         struct composite_context *c = talloc_get_type(ctx->async.private_data,
409                                                       struct composite_context);
410         struct pipe_tcp_state *s = talloc_get_type(c->private_data,
411                                                    struct pipe_tcp_state);
412         struct composite_context *sock_ipv4_req;
413
414         /* receive result of socket open request */
415         c->status = dcerpc_pipe_open_socket_recv(ctx);
416         if (NT_STATUS_IS_OK(c->status)) {
417                 composite_done(c);
418                 return;
419         }
420
421         talloc_free(s->srvaddr);
422
423         /* prepare server address using host:ip and transport name */
424         s->srvaddr = socket_address_from_strings(s->conn, "ipv4", s->address, s->port);
425         if (composite_nomem(s->srvaddr, c)) return;
426
427         /* try IPv4 if IPv6 fails */
428         sock_ipv4_req = dcerpc_pipe_open_socket_send(c, s->conn, 
429                                                      s->srvaddr, s->target_hostname, 
430                                                      NCACN_IP_TCP);
431         composite_continue(c, sock_ipv4_req, continue_ipv4_open_socket, c);
432 }
433 #endif
434
435 /*
436   Stage 2 of dcerpc_pipe_open_tcp_send: receive result of pipe open request
437   on IPv4 transport.
438 */
439 static void continue_ipv4_open_socket(struct composite_context *ctx)
440 {
441         struct composite_context *c = talloc_get_type(ctx->async.private_data,
442                                                       struct composite_context);
443         struct pipe_tcp_state *s = talloc_get_type(c->private_data,
444                                                    struct pipe_tcp_state);
445         
446         /* receive result socket open request */
447         c->status = dcerpc_pipe_open_socket_recv(ctx);
448         if (!NT_STATUS_IS_OK(c->status)) {
449                 /* something went wrong... */
450                 DEBUG(0, ("Failed to connect host %s (%s) on port %d - %s.\n",
451                           s->address, s->target_hostname, 
452                           s->port, nt_errstr(c->status)));
453
454                 composite_error(c, c->status);
455                 return;
456         }
457
458         composite_done(c);
459 }
460
461
462 /*
463   Send rpc pipe open request to given host:port using
464   tcp/ip transport
465 */
466 struct composite_context* dcerpc_pipe_open_tcp_send(struct dcerpc_connection *conn,
467                                                     const char *server,
468                                                     const char *target_hostname,
469                                                     uint32_t port,
470                                                     struct resolve_context *resolve_ctx)
471 {
472         struct composite_context *c;
473         struct pipe_tcp_state *s;
474         struct composite_context *resolve_req;
475         struct nbt_name name;
476
477         /* composite context allocation and setup */
478         c = composite_create(conn, conn->event_ctx);
479         if (c == NULL) return NULL;
480
481         s = talloc_zero(c, struct pipe_tcp_state);
482         if (composite_nomem(s, c)) return c;
483         c->private_data = s;
484
485         /* store input parameters in state structure */
486         s->server          = talloc_strdup(c, server);
487         if (composite_nomem(s->server, c)) return c;
488         if (target_hostname) {
489                 s->target_hostname = talloc_strdup(c, target_hostname);
490                 if (composite_nomem(s->target_hostname, c)) return c;
491         }
492         s->port            = port;
493         s->conn            = conn;
494         s->resolve_ctx     = resolve_ctx;
495
496         make_nbt_name_server(&name, server);
497         resolve_req = resolve_name_send(resolve_ctx, &name, c->event_ctx);
498         composite_continue(c, resolve_req, continue_ip_resolve_name, c);
499         return c;
500 }
501
502 /*
503   Receive result of pipe open request on tcp/ip
504 */
505 NTSTATUS dcerpc_pipe_open_tcp_recv(struct composite_context *c)
506 {
507         NTSTATUS status;
508         status = composite_wait(c);
509
510         talloc_free(c);
511         return status;
512 }
513
514
515 struct pipe_unix_state {
516         const char *path;
517         struct socket_address *srvaddr;
518         struct dcerpc_connection *conn;
519 };
520
521
522 /*
523   Stage 2 of dcerpc_pipe_open_unix_stream_send: receive result of pipe open
524   request on unix socket.
525 */
526 static void continue_unix_open_socket(struct composite_context *ctx)
527 {
528         struct composite_context *c = talloc_get_type(ctx->async.private_data,
529                                                       struct composite_context);
530
531         c->status = dcerpc_pipe_open_socket_recv(ctx);
532         if (NT_STATUS_IS_OK(c->status)) {
533                 composite_done(c);
534                 return;
535         }
536
537         composite_error(c, c->status);
538 }
539
540
541 /*
542   Send pipe open request on unix socket
543 */
544 struct composite_context *dcerpc_pipe_open_unix_stream_send(struct dcerpc_connection *conn,
545                                                             const char *path)
546 {
547         struct composite_context *c;
548         struct composite_context *sock_unix_req;
549         struct pipe_unix_state *s;
550
551         /* composite context allocation and setup */
552         c = composite_create(conn, conn->event_ctx);
553         if (c == NULL) return NULL;
554
555         s = talloc_zero(c, struct pipe_unix_state);
556         if (composite_nomem(s, c)) return c;
557         c->private_data = s;
558
559         /* store parameters in state structure */
560         s->path = talloc_strdup(c, path);
561         if (composite_nomem(s->path, c)) return c;
562         s->conn = conn;
563
564         /* prepare server address using socket path and transport name */
565         s->srvaddr = socket_address_from_strings(conn, "unix", s->path, 0);
566         if (composite_nomem(s->srvaddr, c)) return c;
567
568         /* send socket open request */
569         sock_unix_req = dcerpc_pipe_open_socket_send(c, s->conn, 
570                                                      NULL,
571                                                      s->srvaddr, NULL,
572                                                      s->path,
573                                                      NCALRPC);
574         composite_continue(c, sock_unix_req, continue_unix_open_socket, c);
575         return c;
576 }
577
578
579 /*
580   Receive result of pipe open request on unix socket
581 */
582 NTSTATUS dcerpc_pipe_open_unix_stream_recv(struct composite_context *c)
583 {
584         NTSTATUS status = composite_wait(c);
585
586         talloc_free(c);
587         return status;
588 }
589
590
591 /*
592   Stage 2 of dcerpc_pipe_open_pipe_send: receive socket open request
593 */
594 static void continue_np_open_socket(struct composite_context *ctx)
595 {
596         struct composite_context *c = talloc_get_type(ctx->async.private_data,
597                                                       struct composite_context);
598
599         c->status = dcerpc_pipe_open_socket_recv(ctx);
600         if (!composite_is_ok(c)) return;
601
602         composite_done(c);
603 }
604
605
606 /*
607   Send pipe open request on ncalrpc
608 */
609 struct composite_context* dcerpc_pipe_open_pipe_send(struct dcerpc_connection *conn,
610                                                      const char *ncalrpc_dir,
611                                                      const char *identifier)
612 {
613         char *canon = NULL;
614
615         struct composite_context *c;
616         struct composite_context *sock_np_req;
617         struct pipe_unix_state *s;
618
619         /* composite context allocation and setup */
620         c = composite_create(conn, conn->event_ctx);
621         if (c == NULL) return NULL;
622
623         s = talloc_zero(c, struct pipe_unix_state);
624         if (composite_nomem(s, c)) return c;
625         c->private_data = s;
626
627         /* store parameters in state structure */
628         canon = talloc_strdup(s, identifier);
629         if (composite_nomem(canon, c)) return c;
630         s->conn = conn;
631
632         string_replace(canon, '/', '\\');
633         s->path = talloc_asprintf(canon, "%s/%s", ncalrpc_dir, canon);
634         if (composite_nomem(s->path, c)) return c;
635
636         /* prepare server address using path and transport name */
637         s->srvaddr = socket_address_from_strings(conn, "unix", s->path, 0);
638         if (composite_nomem(s->srvaddr, c)) return c;
639
640         /* send socket open request */
641         sock_np_req = dcerpc_pipe_open_socket_send(c, s->conn, NULL, s->srvaddr, NULL, s->path, NCALRPC);
642         composite_continue(c, sock_np_req, continue_np_open_socket, c);
643         return c;
644 }
645
646
647 /*
648   Receive result of pipe open request on ncalrpc
649 */
650 NTSTATUS dcerpc_pipe_open_pipe_recv(struct composite_context *c)
651 {
652         NTSTATUS status = composite_wait(c);
653         
654         talloc_free(c);
655         return status;
656 }
657
658
659 /*
660   Open a rpc pipe on a named pipe - sync version
661 */
662 NTSTATUS dcerpc_pipe_open_pipe(struct dcerpc_connection *conn, const char *ncalrpc_dir, const char *identifier)
663 {
664         struct composite_context *c = dcerpc_pipe_open_pipe_send(conn, ncalrpc_dir, identifier);
665         return dcerpc_pipe_open_pipe_recv(c);
666 }
667
668 const char *dcerpc_unix_socket_path(struct dcerpc_connection *p)
669 {
670         struct sock_private *sock = (struct sock_private *)p->transport.private_data;
671         return sock->path;
672 }
673
674 struct resolve_context *dcerpc_resolve_ctx(struct dcerpc_connection *p)
675 {
676         struct sock_private *sock = (struct sock_private *)p->transport.private_data;
677         return sock->resolve_ctx;
678 }