c049e641ef4c82c06c53d3a7df7fce6fb0185176
[kamenim/samba.git] / source3 / rpc_server / srv_pipe_hnd.c
1 /*
2  *  Unix SMB/CIFS implementation.
3  *  RPC Pipe client / server routines
4  *  Copyright (C) Andrew Tridgell              1992-1998,
5  *  Largely re-written : 2005
6  *  Copyright (C) Jeremy Allison                1998 - 2005
7  *
8  *  This program is free software; you can redistribute it and/or modify
9  *  it under the terms of the GNU General Public License as published by
10  *  the Free Software Foundation; either version 3 of the License, or
11  *  (at your option) any later version.
12  *
13  *  This program is distributed in the hope that it will be useful,
14  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
15  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  *  GNU General Public License for more details.
17  *
18  *  You should have received a copy of the GNU General Public License
19  *  along with this program; if not, see <http://www.gnu.org/licenses/>.
20  */
21
22 #include "includes.h"
23 #include "../librpc/gen_ndr/srv_spoolss.h"
24 #include "librpc/gen_ndr/ndr_named_pipe_auth.h"
25 #include "../libcli/named_pipe_auth/npa_tstream.h"
26 #include "rpc_server.h"
27 #include "smbd/globals.h"
28 #include "fake_file.h"
29 #include "rpc_dce.h"
30
31 #undef DBGC_CLASS
32 #define DBGC_CLASS DBGC_RPC_SRV
33
34 /****************************************************************************
35  Ensures we have at least RPC_HEADER_LEN amount of data in the incoming buffer.
36 ****************************************************************************/
37
38 static ssize_t fill_rpc_header(struct pipes_struct *p, char *data, size_t data_to_copy)
39 {
40         size_t len_needed_to_complete_hdr =
41                 MIN(data_to_copy, RPC_HEADER_LEN - p->in_data.pdu.length);
42
43         DEBUG(10, ("fill_rpc_header: data_to_copy = %u, "
44                    "len_needed_to_complete_hdr = %u, "
45                    "receive_len = %u\n",
46                    (unsigned int)data_to_copy,
47                    (unsigned int)len_needed_to_complete_hdr,
48                    (unsigned int)p->in_data.pdu.length ));
49
50         if (p->in_data.pdu.data == NULL) {
51                 p->in_data.pdu.data = talloc_array(p, uint8_t, RPC_HEADER_LEN);
52         }
53         if (p->in_data.pdu.data == NULL) {
54                 DEBUG(0, ("talloc failed\n"));
55                 return -1;
56         }
57
58         memcpy((char *)&p->in_data.pdu.data[p->in_data.pdu.length],
59                 data, len_needed_to_complete_hdr);
60         p->in_data.pdu.length += len_needed_to_complete_hdr;
61
62         return (ssize_t)len_needed_to_complete_hdr;
63 }
64
65 static bool get_pdu_size(struct pipes_struct *p)
66 {
67         uint16_t frag_len;
68         /* the fill_rpc_header() call insures we copy only
69          * RPC_HEADER_LEN bytes. If this doesn't match then
70          * somethign is very wrong and we can only abort */
71         if (p->in_data.pdu.length != RPC_HEADER_LEN) {
72                 DEBUG(0, ("Unexpected RPC Header size! "
73                           "got %d, expected %d)\n",
74                           (int)p->in_data.pdu.length,
75                           RPC_HEADER_LEN));
76                 set_incoming_fault(p);
77                 return false;
78         }
79
80         frag_len = dcerpc_get_frag_length(&p->in_data.pdu);
81
82         /* verify it is a reasonable value */
83         if ((frag_len < RPC_HEADER_LEN) ||
84             (frag_len > RPC_MAX_PDU_FRAG_LEN)) {
85                 DEBUG(0, ("Unexpected RPC Fragment size! (%d)\n",
86                           frag_len));
87                 set_incoming_fault(p);
88                 return false;
89         }
90
91         p->in_data.pdu_needed_len = frag_len - RPC_HEADER_LEN;
92
93         /* allocate the space needed to fill the pdu */
94         p->in_data.pdu.data = talloc_realloc(p, p->in_data.pdu.data,
95                                                 uint8_t, frag_len);
96         if (p->in_data.pdu.data == NULL) {
97                 DEBUG(0, ("talloc_realloc failed\n"));
98                 set_incoming_fault(p);
99                 return false;
100         }
101
102         return true;
103 }
104
105 /****************************************************************************
106   Call this to free any talloc'ed memory. Do this after processing
107   a complete incoming and outgoing request (multiple incoming/outgoing
108   PDU's).
109 ****************************************************************************/
110
111 static void free_pipe_context(struct pipes_struct *p)
112 {
113         data_blob_free(&p->out_data.frag);
114         data_blob_free(&p->out_data.rdata);
115         data_blob_free(&p->in_data.data);
116
117         DEBUG(3, ("free_pipe_context: "
118                 "destroying talloc pool of size %lu\n",
119                 (unsigned long)talloc_total_size(p->mem_ctx)));
120         talloc_free_children(p->mem_ctx);
121 }
122
123 /****************************************************************************
124  Accepts incoming data on an rpc pipe. Processes the data in pdu sized units.
125 ****************************************************************************/
126
127 ssize_t process_incoming_data(struct pipes_struct *p, char *data, size_t n)
128 {
129         size_t data_to_copy = MIN(n, RPC_MAX_PDU_FRAG_LEN
130                                         - p->in_data.pdu.length);
131
132         DEBUG(10, ("process_incoming_data: Start: pdu.length = %u, "
133                    "pdu_needed_len = %u, incoming data = %u\n",
134                    (unsigned int)p->in_data.pdu.length,
135                    (unsigned int)p->in_data.pdu_needed_len,
136                    (unsigned int)n ));
137
138         if(data_to_copy == 0) {
139                 /*
140                  * This is an error - data is being received and there is no
141                  * space in the PDU. Free the received data and go into the
142                  * fault state.
143                  */
144                 DEBUG(0, ("process_incoming_data: "
145                           "No space in incoming pdu buffer. "
146                           "Current size = %u incoming data size = %u\n",
147                           (unsigned int)p->in_data.pdu.length,
148                           (unsigned int)n));
149                 set_incoming_fault(p);
150                 return -1;
151         }
152
153         /*
154          * If we have no data already, wait until we get at least
155          * a RPC_HEADER_LEN * number of bytes before we can do anything.
156          */
157
158         if ((p->in_data.pdu_needed_len == 0) &&
159             (p->in_data.pdu.length < RPC_HEADER_LEN)) {
160                 /*
161                  * Always return here. If we have more data then the RPC_HEADER
162                  * will be processed the next time around the loop.
163                  */
164                 return fill_rpc_header(p, data, data_to_copy);
165         }
166
167         /*
168          * At this point we know we have at least an RPC_HEADER_LEN amount of
169          * data stored in p->in_data.pdu.
170          */
171
172         /*
173          * If pdu_needed_len is zero this is a new pdu.
174          * Check how much more data we need, then loop again.
175          */
176         if (p->in_data.pdu_needed_len == 0) {
177
178                 bool ok = get_pdu_size(p);
179                 if (!ok) {
180                         return -1;
181                 }
182                 if (p->in_data.pdu_needed_len > 0) {
183                         return 0;
184                 }
185
186                 /* If rret == 0 and pdu_needed_len == 0 here we have a PDU
187                  * that consists of an RPC_HEADER only. This is a
188                  * DCERPC_PKT_SHUTDOWN, DCERPC_PKT_CO_CANCEL or
189                  * DCERPC_PKT_ORPHANED pdu type.
190                  * Deal with this in process_complete_pdu(). */
191         }
192
193         /*
194          * Ok - at this point we have a valid RPC_HEADER.
195          * Keep reading until we have a full pdu.
196          */
197
198         data_to_copy = MIN(data_to_copy, p->in_data.pdu_needed_len);
199
200         /*
201          * Copy as much of the data as we need into the p->in_data.pdu buffer.
202          * pdu_needed_len becomes zero when we have a complete pdu.
203          */
204
205         memcpy((char *)&p->in_data.pdu.data[p->in_data.pdu.length],
206                 data, data_to_copy);
207         p->in_data.pdu.length += data_to_copy;
208         p->in_data.pdu_needed_len -= data_to_copy;
209
210         /*
211          * Do we have a complete PDU ?
212          * (return the number of bytes handled in the call)
213          */
214
215         if(p->in_data.pdu_needed_len == 0) {
216                 process_complete_pdu(p);
217                 return data_to_copy;
218         }
219
220         DEBUG(10, ("process_incoming_data: not a complete PDU yet. "
221                    "pdu.length = %u, pdu_needed_len = %u\n",
222                    (unsigned int)p->in_data.pdu.length,
223                    (unsigned int)p->in_data.pdu_needed_len));
224
225         return (ssize_t)data_to_copy;
226 }
227
228 /****************************************************************************
229  Accepts incoming data on an internal rpc pipe.
230 ****************************************************************************/
231
232 static ssize_t write_to_internal_pipe(struct pipes_struct *p, char *data, size_t n)
233 {
234         size_t data_left = n;
235
236         while(data_left) {
237                 ssize_t data_used;
238
239                 DEBUG(10, ("write_to_pipe: data_left = %u\n",
240                           (unsigned int)data_left));
241
242                 data_used = process_incoming_data(p, data, data_left);
243
244                 DEBUG(10, ("write_to_pipe: data_used = %d\n",
245                            (int)data_used));
246
247                 if(data_used < 0) {
248                         return -1;
249                 }
250
251                 data_left -= data_used;
252                 data += data_used;
253         }
254
255         return n;
256 }
257
258 /****************************************************************************
259  Replies to a request to read data from a pipe.
260
261  Headers are interspersed with the data at PDU intervals. By the time
262  this function is called, the start of the data could possibly have been
263  read by an SMBtrans (file_offset != 0).
264
265  Calling create_rpc_reply() here is a hack. The data should already
266  have been prepared into arrays of headers + data stream sections.
267 ****************************************************************************/
268
269 static ssize_t read_from_internal_pipe(struct pipes_struct *p, char *data,
270                                        size_t n, bool *is_data_outstanding)
271 {
272         uint32 pdu_remaining = 0;
273         ssize_t data_returned = 0;
274
275         if (!p) {
276                 DEBUG(0,("read_from_pipe: pipe not open\n"));
277                 return -1;
278         }
279
280         DEBUG(6,(" name: %s len: %u\n",
281                  get_pipe_name_from_syntax(talloc_tos(), &p->syntax),
282                  (unsigned int)n));
283
284         /*
285          * We cannot return more than one PDU length per
286          * read request.
287          */
288
289         /*
290          * This condition should result in the connection being closed.
291          * Netapp filers seem to set it to 0xffff which results in domain
292          * authentications failing.  Just ignore it so things work.
293          */
294
295         if(n > RPC_MAX_PDU_FRAG_LEN) {
296                 DEBUG(5,("read_from_pipe: too large read (%u) requested on "
297                          "pipe %s. We can only service %d sized reads.\n",
298                          (unsigned int)n,
299                          get_pipe_name_from_syntax(talloc_tos(), &p->syntax),
300                          RPC_MAX_PDU_FRAG_LEN ));
301                 n = RPC_MAX_PDU_FRAG_LEN;
302         }
303
304         /*
305          * Determine if there is still data to send in the
306          * pipe PDU buffer. Always send this first. Never
307          * send more than is left in the current PDU. The
308          * client should send a new read request for a new
309          * PDU.
310          */
311
312         pdu_remaining = p->out_data.frag.length
313                 - p->out_data.current_pdu_sent;
314
315         if (pdu_remaining > 0) {
316                 data_returned = (ssize_t)MIN(n, pdu_remaining);
317
318                 DEBUG(10,("read_from_pipe: %s: current_pdu_len = %u, "
319                           "current_pdu_sent = %u returning %d bytes.\n",
320                           get_pipe_name_from_syntax(talloc_tos(), &p->syntax),
321                           (unsigned int)p->out_data.frag.length,
322                           (unsigned int)p->out_data.current_pdu_sent,
323                           (int)data_returned));
324
325                 memcpy(data,
326                        p->out_data.frag.data
327                        + p->out_data.current_pdu_sent,
328                        data_returned);
329
330                 p->out_data.current_pdu_sent += (uint32)data_returned;
331                 goto out;
332         }
333
334         /*
335          * At this point p->current_pdu_len == p->current_pdu_sent (which
336          * may of course be zero if this is the first return fragment.
337          */
338
339         DEBUG(10,("read_from_pipe: %s: fault_state = %d : data_sent_length "
340                   "= %u, p->out_data.rdata.length = %u.\n",
341                   get_pipe_name_from_syntax(talloc_tos(), &p->syntax),
342                   (int)p->fault_state,
343                   (unsigned int)p->out_data.data_sent_length,
344                   (unsigned int)p->out_data.rdata.length));
345
346         if (p->out_data.data_sent_length >= p->out_data.rdata.length) {
347                 /*
348                  * We have sent all possible data, return 0.
349                  */
350                 data_returned = 0;
351                 goto out;
352         }
353
354         /*
355          * We need to create a new PDU from the data left in p->rdata.
356          * Create the header/data/footers. This also sets up the fields
357          * p->current_pdu_len, p->current_pdu_sent, p->data_sent_length
358          * and stores the outgoing PDU in p->current_pdu.
359          */
360
361         if(!create_next_pdu(p)) {
362                 DEBUG(0,("read_from_pipe: %s: create_next_pdu failed.\n",
363                          get_pipe_name_from_syntax(talloc_tos(), &p->syntax)));
364                 return -1;
365         }
366
367         data_returned = MIN(n, p->out_data.frag.length);
368
369         memcpy(data, p->out_data.frag.data, (size_t)data_returned);
370         p->out_data.current_pdu_sent += (uint32)data_returned;
371
372   out:
373         (*is_data_outstanding) = p->out_data.frag.length > n;
374
375         if (p->out_data.current_pdu_sent == p->out_data.frag.length) {
376                 /* We've returned everything in the out_data.frag
377                  * so we're done with this pdu. Free it and reset
378                  * current_pdu_sent. */
379                 p->out_data.current_pdu_sent = 0;
380                 data_blob_free(&p->out_data.frag);
381
382                 if (p->out_data.data_sent_length >= p->out_data.rdata.length) {
383                         /*
384                          * We're completely finished with both outgoing and
385                          * incoming data streams. It's safe to free all
386                          * temporary data from this request.
387                          */
388                         free_pipe_context(p);
389                 }
390         }
391
392         return data_returned;
393 }
394
395 bool fsp_is_np(struct files_struct *fsp)
396 {
397         enum FAKE_FILE_TYPE type;
398
399         if ((fsp == NULL) || (fsp->fake_file_handle == NULL)) {
400                 return false;
401         }
402
403         type = fsp->fake_file_handle->type;
404
405         return ((type == FAKE_FILE_TYPE_NAMED_PIPE)
406                 || (type == FAKE_FILE_TYPE_NAMED_PIPE_PROXY));
407 }
408
409 struct np_proxy_state {
410         uint16_t file_type;
411         uint16_t device_state;
412         uint64_t allocation_size;
413         struct tstream_context *npipe;
414         struct tevent_queue *read_queue;
415         struct tevent_queue *write_queue;
416 };
417
418 static struct np_proxy_state *make_external_rpc_pipe_p(TALLOC_CTX *mem_ctx,
419                                 const char *pipe_name,
420                                 const struct tsocket_address *local_address,
421                                 const struct tsocket_address *remote_address,
422                                 struct auth_serversupplied_info *server_info)
423 {
424         struct np_proxy_state *result;
425         char *socket_np_dir;
426         const char *socket_dir;
427         struct tevent_context *ev;
428         struct tevent_req *subreq;
429         struct netr_SamInfo3 *info3;
430         NTSTATUS status;
431         bool ok;
432         int ret;
433         int sys_errno;
434
435         result = talloc(mem_ctx, struct np_proxy_state);
436         if (result == NULL) {
437                 DEBUG(0, ("talloc failed\n"));
438                 return NULL;
439         }
440
441         result->read_queue = tevent_queue_create(result, "np_read");
442         if (result->read_queue == NULL) {
443                 DEBUG(0, ("tevent_queue_create failed\n"));
444                 goto fail;
445         }
446
447         result->write_queue = tevent_queue_create(result, "np_write");
448         if (result->write_queue == NULL) {
449                 DEBUG(0, ("tevent_queue_create failed\n"));
450                 goto fail;
451         }
452
453         ev = s3_tevent_context_init(talloc_tos());
454         if (ev == NULL) {
455                 DEBUG(0, ("s3_tevent_context_init failed\n"));
456                 goto fail;
457         }
458
459         socket_dir = lp_parm_const_string(
460                 GLOBAL_SECTION_SNUM, "external_rpc_pipe", "socket_dir",
461                 lp_ncalrpc_dir());
462         if (socket_dir == NULL) {
463                 DEBUG(0, ("externan_rpc_pipe:socket_dir not set\n"));
464                 goto fail;
465         }
466         socket_np_dir = talloc_asprintf(talloc_tos(), "%s/np", socket_dir);
467         if (socket_np_dir == NULL) {
468                 DEBUG(0, ("talloc_asprintf failed\n"));
469                 goto fail;
470         }
471
472         info3 = talloc_zero(talloc_tos(), struct netr_SamInfo3);
473         if (info3 == NULL) {
474                 DEBUG(0, ("talloc failed\n"));
475                 goto fail;
476         }
477
478         status = serverinfo_to_SamInfo3(server_info, NULL, 0, info3);
479         if (!NT_STATUS_IS_OK(status)) {
480                 TALLOC_FREE(info3);
481                 DEBUG(0, ("serverinfo_to_SamInfo3 failed: %s\n",
482                           nt_errstr(status)));
483                 goto fail;
484         }
485
486         become_root();
487         subreq = tstream_npa_connect_send(talloc_tos(), ev,
488                                           socket_np_dir,
489                                           pipe_name,
490                                           remote_address, /* client_addr */
491                                           NULL, /* client_name */
492                                           local_address, /* server_addr */
493                                           NULL, /* server_name */
494                                           info3,
495                                           server_info->user_session_key,
496                                           data_blob_null /* delegated_creds */);
497         if (subreq == NULL) {
498                 unbecome_root();
499                 DEBUG(0, ("tstream_npa_connect_send to %s for pipe %s and "
500                           "user %s\\%s failed\n",
501                           socket_np_dir, pipe_name, info3->base.domain.string,
502                           info3->base.account_name.string));
503                 goto fail;
504         }
505         ok = tevent_req_poll(subreq, ev);
506         unbecome_root();
507         if (!ok) {
508                 DEBUG(0, ("tevent_req_poll to %s for pipe %s and user %s\\%s "
509                           "failed for tstream_npa_connect: %s\n",
510                           socket_np_dir, pipe_name, info3->base.domain.string,
511                           info3->base.account_name.string,
512                           strerror(errno)));
513                 goto fail;
514
515         }
516         ret = tstream_npa_connect_recv(subreq, &sys_errno,
517                                        result,
518                                        &result->npipe,
519                                        &result->file_type,
520                                        &result->device_state,
521                                        &result->allocation_size);
522         TALLOC_FREE(subreq);
523         if (ret != 0) {
524                 DEBUG(0, ("tstream_npa_connect_recv  to %s for pipe %s and "
525                           "user %s\\%s failed: %s\n",
526                           socket_np_dir, pipe_name, info3->base.domain.string,
527                           info3->base.account_name.string,
528                           strerror(sys_errno)));
529                 goto fail;
530         }
531
532         return result;
533
534  fail:
535         TALLOC_FREE(result);
536         return NULL;
537 }
538
539 NTSTATUS np_open(TALLOC_CTX *mem_ctx, const char *name,
540                  const struct tsocket_address *local_address,
541                  const struct tsocket_address *remote_address,
542                  struct client_address *client_id,
543                  struct auth_serversupplied_info *server_info,
544                  struct messaging_context *msg_ctx,
545                  struct fake_file_handle **phandle)
546 {
547         const char *rpcsrv_type;
548         const char **proxy_list;
549         struct fake_file_handle *handle;
550         bool external = false;
551
552         proxy_list = lp_parm_string_list(-1, "np", "proxy", NULL);
553
554         handle = talloc(mem_ctx, struct fake_file_handle);
555         if (handle == NULL) {
556                 return NT_STATUS_NO_MEMORY;
557         }
558
559         /* Check what is the server type for this pipe.
560            Defaults to "embedded" */
561         rpcsrv_type = lp_parm_const_string(GLOBAL_SECTION_SNUM,
562                                            "rpc_server", name,
563                                            "embedded");
564         if (StrCaseCmp(rpcsrv_type, "embedded") != 0) {
565                 external = true;
566         }
567
568         /* Still support the old method for defining external servers */
569         if ((proxy_list != NULL) && str_list_check_ci(proxy_list, name)) {
570                 external = true;
571         }
572
573         if (external) {
574                 struct np_proxy_state *p;
575
576                 p = make_external_rpc_pipe_p(handle, name,
577                                              local_address,
578                                              remote_address,
579                                              server_info);
580
581                 handle->type = FAKE_FILE_TYPE_NAMED_PIPE_PROXY;
582                 handle->private_data = p;
583         } else {
584                 struct pipes_struct *p;
585                 struct ndr_syntax_id syntax;
586
587                 if (!is_known_pipename(name, &syntax)) {
588                         TALLOC_FREE(handle);
589                         return NT_STATUS_OBJECT_NAME_NOT_FOUND;
590                 }
591
592                 p = make_internal_rpc_pipe_p(handle, &syntax, client_id,
593                                              server_info, msg_ctx);
594
595                 handle->type = FAKE_FILE_TYPE_NAMED_PIPE;
596                 handle->private_data = p;
597         }
598
599         if (handle->private_data == NULL) {
600                 TALLOC_FREE(handle);
601                 return NT_STATUS_PIPE_NOT_AVAILABLE;
602         }
603
604         *phandle = handle;
605
606         return NT_STATUS_OK;
607 }
608
609 bool np_read_in_progress(struct fake_file_handle *handle)
610 {
611         if (handle->type == FAKE_FILE_TYPE_NAMED_PIPE) {
612                 return false;
613         }
614
615         if (handle->type == FAKE_FILE_TYPE_NAMED_PIPE_PROXY) {
616                 struct np_proxy_state *p = talloc_get_type_abort(
617                         handle->private_data, struct np_proxy_state);
618                 size_t read_count;
619
620                 read_count = tevent_queue_length(p->read_queue);
621                 if (read_count > 0) {
622                         return true;
623                 }
624
625                 return false;
626         }
627
628         return false;
629 }
630
631 struct np_write_state {
632         struct event_context *ev;
633         struct np_proxy_state *p;
634         struct iovec iov;
635         ssize_t nwritten;
636 };
637
638 static void np_write_done(struct tevent_req *subreq);
639
640 struct tevent_req *np_write_send(TALLOC_CTX *mem_ctx, struct event_context *ev,
641                                  struct fake_file_handle *handle,
642                                  const uint8_t *data, size_t len)
643 {
644         struct tevent_req *req;
645         struct np_write_state *state;
646         NTSTATUS status;
647
648         DEBUG(6, ("np_write_send: len: %d\n", (int)len));
649         dump_data(50, data, len);
650
651         req = tevent_req_create(mem_ctx, &state, struct np_write_state);
652         if (req == NULL) {
653                 return NULL;
654         }
655
656         if (len == 0) {
657                 state->nwritten = 0;
658                 status = NT_STATUS_OK;
659                 goto post_status;
660         }
661
662         if (handle->type == FAKE_FILE_TYPE_NAMED_PIPE) {
663                 struct pipes_struct *p = talloc_get_type_abort(
664                         handle->private_data, struct pipes_struct);
665
666                 state->nwritten = write_to_internal_pipe(p, (char *)data, len);
667
668                 status = (state->nwritten >= 0)
669                         ? NT_STATUS_OK : NT_STATUS_UNEXPECTED_IO_ERROR;
670                 goto post_status;
671         }
672
673         if (handle->type == FAKE_FILE_TYPE_NAMED_PIPE_PROXY) {
674                 struct np_proxy_state *p = talloc_get_type_abort(
675                         handle->private_data, struct np_proxy_state);
676                 struct tevent_req *subreq;
677
678                 state->ev = ev;
679                 state->p = p;
680                 state->iov.iov_base = CONST_DISCARD(void *, data);
681                 state->iov.iov_len = len;
682
683                 subreq = tstream_writev_queue_send(state, ev,
684                                                    p->npipe,
685                                                    p->write_queue,
686                                                    &state->iov, 1);
687                 if (subreq == NULL) {
688                         goto fail;
689                 }
690                 tevent_req_set_callback(subreq, np_write_done, req);
691                 return req;
692         }
693
694         status = NT_STATUS_INVALID_HANDLE;
695  post_status:
696         if (NT_STATUS_IS_OK(status)) {
697                 tevent_req_done(req);
698         } else {
699                 tevent_req_nterror(req, status);
700         }
701         return tevent_req_post(req, ev);
702  fail:
703         TALLOC_FREE(req);
704         return NULL;
705 }
706
707 static void np_write_done(struct tevent_req *subreq)
708 {
709         struct tevent_req *req = tevent_req_callback_data(
710                 subreq, struct tevent_req);
711         struct np_write_state *state = tevent_req_data(
712                 req, struct np_write_state);
713         ssize_t received;
714         int err;
715
716         received = tstream_writev_queue_recv(subreq, &err);
717         if (received < 0) {
718                 tevent_req_nterror(req, map_nt_error_from_unix(err));
719                 return;
720         }
721         state->nwritten = received;
722         tevent_req_done(req);
723 }
724
725 NTSTATUS np_write_recv(struct tevent_req *req, ssize_t *pnwritten)
726 {
727         struct np_write_state *state = tevent_req_data(
728                 req, struct np_write_state);
729         NTSTATUS status;
730
731         if (tevent_req_is_nterror(req, &status)) {
732                 return status;
733         }
734         *pnwritten = state->nwritten;
735         return NT_STATUS_OK;
736 }
737
738 struct np_ipc_readv_next_vector_state {
739         uint8_t *buf;
740         size_t len;
741         off_t ofs;
742         size_t remaining;
743 };
744
745 static void np_ipc_readv_next_vector_init(struct np_ipc_readv_next_vector_state *s,
746                                           uint8_t *buf, size_t len)
747 {
748         ZERO_STRUCTP(s);
749
750         s->buf = buf;
751         s->len = MIN(len, UINT16_MAX);
752 }
753
754 static int np_ipc_readv_next_vector(struct tstream_context *stream,
755                                     void *private_data,
756                                     TALLOC_CTX *mem_ctx,
757                                     struct iovec **_vector,
758                                     size_t *count)
759 {
760         struct np_ipc_readv_next_vector_state *state =
761                 (struct np_ipc_readv_next_vector_state *)private_data;
762         struct iovec *vector;
763         ssize_t pending;
764         size_t wanted;
765
766         if (state->ofs == state->len) {
767                 *_vector = NULL;
768                 *count = 0;
769                 return 0;
770         }
771
772         pending = tstream_pending_bytes(stream);
773         if (pending == -1) {
774                 return -1;
775         }
776
777         if (pending == 0 && state->ofs != 0) {
778                 /* return a short read */
779                 *_vector = NULL;
780                 *count = 0;
781                 return 0;
782         }
783
784         if (pending == 0) {
785                 /* we want at least one byte and recheck again */
786                 wanted = 1;
787         } else {
788                 size_t missing = state->len - state->ofs;
789                 if (pending > missing) {
790                         /* there's more available */
791                         state->remaining = pending - missing;
792                         wanted = missing;
793                 } else {
794                         /* read what we can get and recheck in the next cycle */
795                         wanted = pending;
796                 }
797         }
798
799         vector = talloc_array(mem_ctx, struct iovec, 1);
800         if (!vector) {
801                 return -1;
802         }
803
804         vector[0].iov_base = state->buf + state->ofs;
805         vector[0].iov_len = wanted;
806
807         state->ofs += wanted;
808
809         *_vector = vector;
810         *count = 1;
811         return 0;
812 }
813
814 struct np_read_state {
815         struct np_proxy_state *p;
816         struct np_ipc_readv_next_vector_state next_vector;
817
818         size_t nread;
819         bool is_data_outstanding;
820 };
821
822 static void np_read_done(struct tevent_req *subreq);
823
824 struct tevent_req *np_read_send(TALLOC_CTX *mem_ctx, struct event_context *ev,
825                                 struct fake_file_handle *handle,
826                                 uint8_t *data, size_t len)
827 {
828         struct tevent_req *req;
829         struct np_read_state *state;
830         NTSTATUS status;
831
832         req = tevent_req_create(mem_ctx, &state, struct np_read_state);
833         if (req == NULL) {
834                 return NULL;
835         }
836
837         if (handle->type == FAKE_FILE_TYPE_NAMED_PIPE) {
838                 struct pipes_struct *p = talloc_get_type_abort(
839                         handle->private_data, struct pipes_struct);
840
841                 state->nread = read_from_internal_pipe(
842                         p, (char *)data, len, &state->is_data_outstanding);
843
844                 status = (state->nread >= 0)
845                         ? NT_STATUS_OK : NT_STATUS_UNEXPECTED_IO_ERROR;
846                 goto post_status;
847         }
848
849         if (handle->type == FAKE_FILE_TYPE_NAMED_PIPE_PROXY) {
850                 struct np_proxy_state *p = talloc_get_type_abort(
851                         handle->private_data, struct np_proxy_state);
852                 struct tevent_req *subreq;
853
854                 np_ipc_readv_next_vector_init(&state->next_vector,
855                                               data, len);
856
857                 subreq = tstream_readv_pdu_queue_send(state,
858                                                       ev,
859                                                       p->npipe,
860                                                       p->read_queue,
861                                                       np_ipc_readv_next_vector,
862                                                       &state->next_vector);
863                 if (subreq == NULL) {
864                         status = NT_STATUS_NO_MEMORY;
865                         goto post_status;
866                 }
867                 tevent_req_set_callback(subreq, np_read_done, req);
868                 return req;
869         }
870
871         status = NT_STATUS_INVALID_HANDLE;
872  post_status:
873         if (NT_STATUS_IS_OK(status)) {
874                 tevent_req_done(req);
875         } else {
876                 tevent_req_nterror(req, status);
877         }
878         return tevent_req_post(req, ev);
879 }
880
881 static void np_read_done(struct tevent_req *subreq)
882 {
883         struct tevent_req *req = tevent_req_callback_data(
884                 subreq, struct tevent_req);
885         struct np_read_state *state = tevent_req_data(
886                 req, struct np_read_state);
887         ssize_t ret;
888         int err;
889
890         ret = tstream_readv_pdu_queue_recv(subreq, &err);
891         TALLOC_FREE(subreq);
892         if (ret == -1) {
893                 tevent_req_nterror(req, map_nt_error_from_unix(err));
894                 return;
895         }
896
897         state->nread = ret;
898         state->is_data_outstanding = (state->next_vector.remaining > 0);
899
900         tevent_req_done(req);
901         return;
902 }
903
904 NTSTATUS np_read_recv(struct tevent_req *req, ssize_t *nread,
905                       bool *is_data_outstanding)
906 {
907         struct np_read_state *state = tevent_req_data(
908                 req, struct np_read_state);
909         NTSTATUS status;
910
911         if (tevent_req_is_nterror(req, &status)) {
912                 return status;
913         }
914
915         DEBUG(10, ("Received %d bytes. There is %smore data outstanding\n",
916                    (int)state->nread, state->is_data_outstanding?"":"no "));
917
918         *nread = state->nread;
919         *is_data_outstanding = state->is_data_outstanding;
920         return NT_STATUS_OK;
921 }
922
923
924 static NTSTATUS rpc_pipe_open_external(TALLOC_CTX *mem_ctx,
925                                 const char *pipe_name,
926                                 const struct ndr_syntax_id *abstract_syntax,
927                                 struct auth_serversupplied_info *server_info,
928                                 struct rpc_pipe_client **_result)
929 {
930         struct tsocket_address *local, *remote;
931         struct rpc_pipe_client *result = NULL;
932         struct np_proxy_state *proxy_state = NULL;
933         struct pipe_auth_data *auth;
934         NTSTATUS status;
935         int ret;
936
937         /* this is an internal connection, fake up ip addresses */
938         ret = tsocket_address_inet_from_strings(talloc_tos(), "ip",
939                                                 NULL, 0, &local);
940         if (ret) {
941                 return NT_STATUS_NO_MEMORY;
942         }
943         ret = tsocket_address_inet_from_strings(talloc_tos(), "ip",
944                                                 NULL, 0, &remote);
945         if (ret) {
946                 return NT_STATUS_NO_MEMORY;
947         }
948
949         proxy_state = make_external_rpc_pipe_p(mem_ctx, pipe_name,
950                                                 local, remote, server_info);
951         if (!proxy_state) {
952                 return NT_STATUS_UNSUCCESSFUL;
953         }
954
955         result = talloc_zero(mem_ctx, struct rpc_pipe_client);
956         if (result == NULL) {
957                 status = NT_STATUS_NO_MEMORY;
958                 goto done;
959         }
960
961         result->abstract_syntax = *abstract_syntax;
962         result->transfer_syntax = ndr_transfer_syntax;
963
964         result->desthost = get_myname(result);
965         result->srv_name_slash = talloc_asprintf_strupper_m(
966                 result, "\\\\%s", result->desthost);
967         if ((result->desthost == NULL) || (result->srv_name_slash == NULL)) {
968                 status = NT_STATUS_NO_MEMORY;
969                 goto done;
970         }
971
972         result->max_xmit_frag = RPC_MAX_PDU_FRAG_LEN;
973         result->max_recv_frag = RPC_MAX_PDU_FRAG_LEN;
974
975         status = rpc_transport_tstream_init(result,
976                                             proxy_state->npipe,
977                                             proxy_state->read_queue,
978                                             proxy_state->write_queue,
979                                             &result->transport);
980         if (!NT_STATUS_IS_OK(status)) {
981                 goto done;
982         }
983
984         result->auth = talloc_zero(result, struct pipe_auth_data);
985         if (!result->auth) {
986                 status = NT_STATUS_NO_MEMORY;
987                 goto done;
988         }
989         result->auth->auth_type = DCERPC_AUTH_TYPE_NONE;
990         result->auth->auth_level = DCERPC_AUTH_LEVEL_NONE;
991
992         status = rpccli_anon_bind_data(result, &auth);
993         if (!NT_STATUS_IS_OK(status)) {
994                 DEBUG(0, ("Failed to initialize anonymous bind.\n"));
995                 goto done;
996         }
997
998         status = rpc_pipe_bind(result, auth);
999         if (!NT_STATUS_IS_OK(status)) {
1000                 DEBUG(0, ("Failed to bind spoolss pipe.\n"));
1001                 goto done;
1002         }
1003 done:
1004         if (!NT_STATUS_IS_OK(status)) {
1005                 TALLOC_FREE(result);
1006         }
1007         TALLOC_FREE(proxy_state);
1008         *_result = result;
1009         return status;
1010 }
1011
1012 /**
1013  * @brief Create a new RPC client context which uses a local dispatch function.
1014  *
1015  * @param mem_ctx       The memory context on which thje pipe will ultimately
1016  *                      be allocated
1017  * @param name          The pipe name to connect to.
1018  * @param server_info   Credentials to use for the connection.
1019  * @param pipe          [in|out] Checks if a pipe is connected, and connects it
1020  *                               if not
1021  *
1022  * @return              NT_STATUS_OK on success, a corresponding NT status if
1023  *                      an error occured.
1024  */
1025
1026 NTSTATUS rpc_pipe_open_interface(TALLOC_CTX *mem_ctx,
1027                                  const struct ndr_syntax_id *syntax,
1028                                  struct auth_serversupplied_info *server_info,
1029                                  struct client_address *client_id,
1030                                  struct messaging_context *msg_ctx,
1031                                  struct rpc_pipe_client **cli_pipe)
1032 {
1033         TALLOC_CTX *tmpctx;
1034         const char *server_type;
1035         const char *pipe_name;
1036         NTSTATUS status;
1037
1038         if (rpccli_is_connected(*cli_pipe)) {
1039                 return NT_STATUS_OK;
1040         } else {
1041                 TALLOC_FREE(*cli_pipe);
1042         }
1043
1044         tmpctx = talloc_new(mem_ctx);
1045         if (!tmpctx) {
1046                 return NT_STATUS_NO_MEMORY;
1047         }
1048
1049         pipe_name = get_pipe_name_from_syntax(tmpctx, syntax);
1050         if (!pipe_name) {
1051                 TALLOC_FREE(tmpctx);
1052                 return NT_STATUS_INVALID_PARAMETER;
1053         }
1054
1055         DEBUG(10, ("Connecting to %s pipe.\n", pipe_name));
1056
1057         server_type = lp_parm_const_string(GLOBAL_SECTION_SNUM,
1058                                            "rpc_server", pipe_name,
1059                                            "embedded");
1060         if (StrCaseCmp(server_type, "embedded") == 0) {
1061                 status = rpc_pipe_open_internal(tmpctx,
1062                                                 syntax, server_info,
1063                                                 client_id, msg_ctx,
1064                                                 cli_pipe);
1065                 if (!NT_STATUS_IS_OK(status)) {
1066                         goto done;
1067                 }
1068         } else {
1069                 /* It would be nice to just use rpc_pipe_open_ncalrpc() but
1070                  * for now we need to use the special proxy setup to connect
1071                  * to spoolssd. */
1072
1073                 status = rpc_pipe_open_external(tmpctx,
1074                                                 pipe_name, syntax,
1075                                                 server_info,
1076                                                 cli_pipe);
1077                 if (!NT_STATUS_IS_OK(status)) {
1078                         goto done;
1079                 }
1080         }
1081
1082         status = NT_STATUS_OK;
1083 done:
1084         if (NT_STATUS_IS_OK(status)) {
1085                 talloc_steal(mem_ctx, *cli_pipe);
1086         }
1087         TALLOC_FREE(tmpctx);
1088         return status;
1089 }