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