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