s3-dcerpc: Move mere processing functions from srv_pipe_hnd.c to srv_pipe.c
[idra/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 "../libcli/auth/schannel.h"
27 #include "../libcli/auth/spnego.h"
28 #include "../libcli/auth/ntlmssp.h"
29 #include "rpc_server.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(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(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(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 static ssize_t process_incoming_data(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                 get_dyn_NCALRPCDIR());
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 auth_serversupplied_info *server_info,
543                  struct fake_file_handle **phandle)
544 {
545         const char **proxy_list;
546         struct fake_file_handle *handle;
547
548         proxy_list = lp_parm_string_list(-1, "np", "proxy", NULL);
549
550         handle = talloc(mem_ctx, struct fake_file_handle);
551         if (handle == NULL) {
552                 return NT_STATUS_NO_MEMORY;
553         }
554
555         if ((proxy_list != NULL) && str_list_check_ci(proxy_list, name)) {
556                 struct np_proxy_state *p;
557
558                 p = make_external_rpc_pipe_p(handle, name,
559                                              local_address,
560                                              remote_address,
561                                              server_info);
562
563                 handle->type = FAKE_FILE_TYPE_NAMED_PIPE_PROXY;
564                 handle->private_data = p;
565         } else {
566                 struct pipes_struct *p;
567                 struct ndr_syntax_id syntax;
568                 const char *client_address;
569
570                 if (!is_known_pipename(name, &syntax)) {
571                         TALLOC_FREE(handle);
572                         return NT_STATUS_OBJECT_NAME_NOT_FOUND;
573                 }
574
575                 if (tsocket_address_is_inet(remote_address, "ip")) {
576                         client_address = tsocket_address_inet_addr_string(
577                                                 remote_address,
578                                                 talloc_tos());
579                         if (client_address == NULL) {
580                                 TALLOC_FREE(handle);
581                                 return NT_STATUS_NO_MEMORY;
582                         }
583                 } else {
584                         client_address = "";
585                 }
586
587                 p = make_internal_rpc_pipe_p(handle, &syntax, client_address,
588                                              server_info);
589
590                 handle->type = FAKE_FILE_TYPE_NAMED_PIPE;
591                 handle->private_data = p;
592         }
593
594         if (handle->private_data == NULL) {
595                 TALLOC_FREE(handle);
596                 return NT_STATUS_PIPE_NOT_AVAILABLE;
597         }
598
599         *phandle = handle;
600
601         return NT_STATUS_OK;
602 }
603
604 bool np_read_in_progress(struct fake_file_handle *handle)
605 {
606         if (handle->type == FAKE_FILE_TYPE_NAMED_PIPE) {
607                 return false;
608         }
609
610         if (handle->type == FAKE_FILE_TYPE_NAMED_PIPE_PROXY) {
611                 struct np_proxy_state *p = talloc_get_type_abort(
612                         handle->private_data, struct np_proxy_state);
613                 size_t read_count;
614
615                 read_count = tevent_queue_length(p->read_queue);
616                 if (read_count > 0) {
617                         return true;
618                 }
619
620                 return false;
621         }
622
623         return false;
624 }
625
626 struct np_write_state {
627         struct event_context *ev;
628         struct np_proxy_state *p;
629         struct iovec iov;
630         ssize_t nwritten;
631 };
632
633 static void np_write_done(struct tevent_req *subreq);
634
635 struct tevent_req *np_write_send(TALLOC_CTX *mem_ctx, struct event_context *ev,
636                                  struct fake_file_handle *handle,
637                                  const uint8_t *data, size_t len)
638 {
639         struct tevent_req *req;
640         struct np_write_state *state;
641         NTSTATUS status;
642
643         DEBUG(6, ("np_write_send: len: %d\n", (int)len));
644         dump_data(50, data, len);
645
646         req = tevent_req_create(mem_ctx, &state, struct np_write_state);
647         if (req == NULL) {
648                 return NULL;
649         }
650
651         if (len == 0) {
652                 state->nwritten = 0;
653                 status = NT_STATUS_OK;
654                 goto post_status;
655         }
656
657         if (handle->type == FAKE_FILE_TYPE_NAMED_PIPE) {
658                 struct pipes_struct *p = talloc_get_type_abort(
659                         handle->private_data, struct pipes_struct);
660
661                 state->nwritten = write_to_internal_pipe(p, (char *)data, len);
662
663                 status = (state->nwritten >= 0)
664                         ? NT_STATUS_OK : NT_STATUS_UNEXPECTED_IO_ERROR;
665                 goto post_status;
666         }
667
668         if (handle->type == FAKE_FILE_TYPE_NAMED_PIPE_PROXY) {
669                 struct np_proxy_state *p = talloc_get_type_abort(
670                         handle->private_data, struct np_proxy_state);
671                 struct tevent_req *subreq;
672
673                 state->ev = ev;
674                 state->p = p;
675                 state->iov.iov_base = CONST_DISCARD(void *, data);
676                 state->iov.iov_len = len;
677
678                 subreq = tstream_writev_queue_send(state, ev,
679                                                    p->npipe,
680                                                    p->write_queue,
681                                                    &state->iov, 1);
682                 if (subreq == NULL) {
683                         goto fail;
684                 }
685                 tevent_req_set_callback(subreq, np_write_done, req);
686                 return req;
687         }
688
689         status = NT_STATUS_INVALID_HANDLE;
690  post_status:
691         if (NT_STATUS_IS_OK(status)) {
692                 tevent_req_done(req);
693         } else {
694                 tevent_req_nterror(req, status);
695         }
696         return tevent_req_post(req, ev);
697  fail:
698         TALLOC_FREE(req);
699         return NULL;
700 }
701
702 static void np_write_done(struct tevent_req *subreq)
703 {
704         struct tevent_req *req = tevent_req_callback_data(
705                 subreq, struct tevent_req);
706         struct np_write_state *state = tevent_req_data(
707                 req, struct np_write_state);
708         ssize_t received;
709         int err;
710
711         received = tstream_writev_queue_recv(subreq, &err);
712         if (received < 0) {
713                 tevent_req_nterror(req, map_nt_error_from_unix(err));
714                 return;
715         }
716         state->nwritten = received;
717         tevent_req_done(req);
718 }
719
720 NTSTATUS np_write_recv(struct tevent_req *req, ssize_t *pnwritten)
721 {
722         struct np_write_state *state = tevent_req_data(
723                 req, struct np_write_state);
724         NTSTATUS status;
725
726         if (tevent_req_is_nterror(req, &status)) {
727                 return status;
728         }
729         *pnwritten = state->nwritten;
730         return NT_STATUS_OK;
731 }
732
733 struct np_ipc_readv_next_vector_state {
734         uint8_t *buf;
735         size_t len;
736         off_t ofs;
737         size_t remaining;
738 };
739
740 static void np_ipc_readv_next_vector_init(struct np_ipc_readv_next_vector_state *s,
741                                           uint8_t *buf, size_t len)
742 {
743         ZERO_STRUCTP(s);
744
745         s->buf = buf;
746         s->len = MIN(len, UINT16_MAX);
747 }
748
749 static int np_ipc_readv_next_vector(struct tstream_context *stream,
750                                     void *private_data,
751                                     TALLOC_CTX *mem_ctx,
752                                     struct iovec **_vector,
753                                     size_t *count)
754 {
755         struct np_ipc_readv_next_vector_state *state =
756                 (struct np_ipc_readv_next_vector_state *)private_data;
757         struct iovec *vector;
758         ssize_t pending;
759         size_t wanted;
760
761         if (state->ofs == state->len) {
762                 *_vector = NULL;
763                 *count = 0;
764                 return 0;
765         }
766
767         pending = tstream_pending_bytes(stream);
768         if (pending == -1) {
769                 return -1;
770         }
771
772         if (pending == 0 && state->ofs != 0) {
773                 /* return a short read */
774                 *_vector = NULL;
775                 *count = 0;
776                 return 0;
777         }
778
779         if (pending == 0) {
780                 /* we want at least one byte and recheck again */
781                 wanted = 1;
782         } else {
783                 size_t missing = state->len - state->ofs;
784                 if (pending > missing) {
785                         /* there's more available */
786                         state->remaining = pending - missing;
787                         wanted = missing;
788                 } else {
789                         /* read what we can get and recheck in the next cycle */
790                         wanted = pending;
791                 }
792         }
793
794         vector = talloc_array(mem_ctx, struct iovec, 1);
795         if (!vector) {
796                 return -1;
797         }
798
799         vector[0].iov_base = state->buf + state->ofs;
800         vector[0].iov_len = wanted;
801
802         state->ofs += wanted;
803
804         *_vector = vector;
805         *count = 1;
806         return 0;
807 }
808
809 struct np_read_state {
810         struct np_proxy_state *p;
811         struct np_ipc_readv_next_vector_state next_vector;
812
813         size_t nread;
814         bool is_data_outstanding;
815 };
816
817 static void np_read_done(struct tevent_req *subreq);
818
819 struct tevent_req *np_read_send(TALLOC_CTX *mem_ctx, struct event_context *ev,
820                                 struct fake_file_handle *handle,
821                                 uint8_t *data, size_t len)
822 {
823         struct tevent_req *req;
824         struct np_read_state *state;
825         NTSTATUS status;
826
827         req = tevent_req_create(mem_ctx, &state, struct np_read_state);
828         if (req == NULL) {
829                 return NULL;
830         }
831
832         if (handle->type == FAKE_FILE_TYPE_NAMED_PIPE) {
833                 struct pipes_struct *p = talloc_get_type_abort(
834                         handle->private_data, struct pipes_struct);
835
836                 state->nread = read_from_internal_pipe(
837                         p, (char *)data, len, &state->is_data_outstanding);
838
839                 status = (state->nread >= 0)
840                         ? NT_STATUS_OK : NT_STATUS_UNEXPECTED_IO_ERROR;
841                 goto post_status;
842         }
843
844         if (handle->type == FAKE_FILE_TYPE_NAMED_PIPE_PROXY) {
845                 struct np_proxy_state *p = talloc_get_type_abort(
846                         handle->private_data, struct np_proxy_state);
847                 struct tevent_req *subreq;
848
849                 np_ipc_readv_next_vector_init(&state->next_vector,
850                                               data, len);
851
852                 subreq = tstream_readv_pdu_queue_send(state,
853                                                       ev,
854                                                       p->npipe,
855                                                       p->read_queue,
856                                                       np_ipc_readv_next_vector,
857                                                       &state->next_vector);
858                 if (subreq == NULL) {
859
860                 }
861                 tevent_req_set_callback(subreq, np_read_done, req);
862                 return req;
863         }
864
865         status = NT_STATUS_INVALID_HANDLE;
866  post_status:
867         if (NT_STATUS_IS_OK(status)) {
868                 tevent_req_done(req);
869         } else {
870                 tevent_req_nterror(req, status);
871         }
872         return tevent_req_post(req, ev);
873 }
874
875 static void np_read_done(struct tevent_req *subreq)
876 {
877         struct tevent_req *req = tevent_req_callback_data(
878                 subreq, struct tevent_req);
879         struct np_read_state *state = tevent_req_data(
880                 req, struct np_read_state);
881         ssize_t ret;
882         int err;
883
884         ret = tstream_readv_pdu_queue_recv(subreq, &err);
885         TALLOC_FREE(subreq);
886         if (ret == -1) {
887                 tevent_req_nterror(req, map_nt_error_from_unix(err));
888                 return;
889         }
890
891         state->nread = ret;
892         state->is_data_outstanding = (state->next_vector.remaining > 0);
893
894         tevent_req_done(req);
895         return;
896 }
897
898 NTSTATUS np_read_recv(struct tevent_req *req, ssize_t *nread,
899                       bool *is_data_outstanding)
900 {
901         struct np_read_state *state = tevent_req_data(
902                 req, struct np_read_state);
903         NTSTATUS status;
904
905         if (tevent_req_is_nterror(req, &status)) {
906                 return status;
907         }
908         *nread = state->nread;
909         *is_data_outstanding = state->is_data_outstanding;
910         return NT_STATUS_OK;
911 }
912
913 /**
914  * @brief Create a new RPC client context which uses a local dispatch function.
915  *
916  * @param[in]  conn  The connection struct that will hold the pipe
917  *
918  * @param[out] spoolss_pipe  A pointer to the connected rpc client pipe.
919  *
920  * @return              NT_STATUS_OK on success, a corresponding NT status if an
921  *                      error occured.
922  */
923 NTSTATUS rpc_connect_spoolss_pipe(connection_struct *conn,
924                                   struct rpc_pipe_client **spoolss_pipe)
925 {
926         NTSTATUS status;
927
928         /* TODO: check and handle disconnections */
929
930         if (!conn->spoolss_pipe) {
931                 status = rpc_pipe_open_internal(conn,
932                                                 &ndr_table_spoolss.syntax_id,
933                                                 conn->server_info,
934                                                 &conn->spoolss_pipe);
935                 if (!NT_STATUS_IS_OK(status)) {
936                         return status;
937                 }
938         }
939
940         *spoolss_pipe = conn->spoolss_pipe;
941         return NT_STATUS_OK;
942 }