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