e0fa861781d70dbd99fb2e1c5e7f97430348ce51
[abartlet/samba.git/.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
27 #undef DBGC_CLASS
28 #define DBGC_CLASS DBGC_RPC_SRV
29
30 /****************************************************************************
31  Initialise an outgoing packet.
32 ****************************************************************************/
33
34 static bool pipe_init_outgoing_data(pipes_struct *p)
35 {
36         output_data *o_data = &p->out_data;
37
38         /* Reset the offset counters. */
39         o_data->data_sent_length = 0;
40         o_data->current_pdu_sent = 0;
41
42         prs_mem_free(&o_data->frag);
43
44         /* Free any memory in the current return data buffer. */
45         prs_mem_free(&o_data->rdata);
46
47         /*
48          * Initialize the outgoing RPC data buffer.
49          * we will use this as the raw data area for replying to rpc requests.
50          */     
51         if(!prs_init(&o_data->rdata, 128, p->mem_ctx, MARSHALL)) {
52                 DEBUG(0,("pipe_init_outgoing_data: malloc fail.\n"));
53                 return False;
54         }
55
56         return True;
57 }
58
59 /****************************************************************************
60  Sets the fault state on incoming packets.
61 ****************************************************************************/
62
63 static void set_incoming_fault(pipes_struct *p)
64 {
65         prs_mem_free(&p->in_data.data);
66         p->in_data.pdu_needed_len = 0;
67         p->in_data.pdu_received_len = 0;
68         p->fault_state = True;
69         DEBUG(10, ("set_incoming_fault: Setting fault state on pipe %s\n",
70                    get_pipe_name_from_syntax(talloc_tos(), &p->syntax)));
71 }
72
73 /****************************************************************************
74  Ensures we have at least RPC_HEADER_LEN amount of data in the incoming buffer.
75 ****************************************************************************/
76
77 static ssize_t fill_rpc_header(pipes_struct *p, char *data, size_t data_to_copy)
78 {
79         size_t len_needed_to_complete_hdr = MIN(data_to_copy, RPC_HEADER_LEN - p->in_data.pdu_received_len);
80
81         DEBUG(10,("fill_rpc_header: data_to_copy = %u, len_needed_to_complete_hdr = %u, receive_len = %u\n",
82                         (unsigned int)data_to_copy, (unsigned int)len_needed_to_complete_hdr,
83                         (unsigned int)p->in_data.pdu_received_len ));
84
85         if (p->in_data.current_in_pdu == NULL) {
86                 p->in_data.current_in_pdu = talloc_array(p, uint8_t,
87                                                          RPC_HEADER_LEN);
88         }
89         if (p->in_data.current_in_pdu == NULL) {
90                 DEBUG(0, ("talloc failed\n"));
91                 return -1;
92         }
93
94         memcpy((char *)&p->in_data.current_in_pdu[p->in_data.pdu_received_len], data, len_needed_to_complete_hdr);
95         p->in_data.pdu_received_len += len_needed_to_complete_hdr;
96
97         return (ssize_t)len_needed_to_complete_hdr;
98 }
99
100 /****************************************************************************
101  Unmarshalls a new PDU header. Assumes the raw header data is in current_in_pdu.
102 ****************************************************************************/
103
104 static ssize_t unmarshall_rpc_header(pipes_struct *p)
105 {
106         /*
107          * Unmarshall the header to determine the needed length.
108          */
109
110         prs_struct rpc_in;
111
112         if(p->in_data.pdu_received_len != RPC_HEADER_LEN) {
113                 DEBUG(0,("unmarshall_rpc_header: assert on rpc header length failed.\n"));
114                 set_incoming_fault(p);
115                 return -1;
116         }
117
118         prs_init_empty( &rpc_in, p->mem_ctx, UNMARSHALL);
119         prs_set_endian_data( &rpc_in, p->endian);
120
121         prs_give_memory( &rpc_in, (char *)&p->in_data.current_in_pdu[0],
122                                         p->in_data.pdu_received_len, False);
123
124         /*
125          * Unmarshall the header as this will tell us how much
126          * data we need to read to get the complete pdu.
127          * This also sets the endian flag in rpc_in.
128          */
129
130         if(!smb_io_rpc_hdr("", &p->hdr, &rpc_in, 0)) {
131                 DEBUG(0,("unmarshall_rpc_header: failed to unmarshall RPC_HDR.\n"));
132                 set_incoming_fault(p);
133                 prs_mem_free(&rpc_in);
134                 return -1;
135         }
136
137         /*
138          * Validate the RPC header.
139          */
140
141         if(p->hdr.major != 5 && p->hdr.minor != 0) {
142                 DEBUG(0,("unmarshall_rpc_header: invalid major/minor numbers in RPC_HDR.\n"));
143                 set_incoming_fault(p);
144                 prs_mem_free(&rpc_in);
145                 return -1;
146         }
147
148         /*
149          * If there's not data in the incoming buffer this should be the start of a new RPC.
150          */
151
152         if(prs_offset(&p->in_data.data) == 0) {
153
154                 /*
155                  * AS/U doesn't set FIRST flag in a BIND packet it seems.
156                  */
157
158                 if ((p->hdr.pkt_type == DCERPC_PKT_REQUEST) && !(p->hdr.flags & DCERPC_PFC_FLAG_FIRST)) {
159                         /*
160                          * Ensure that the FIRST flag is set. If not then we have
161                          * a stream missmatch.
162                          */
163
164                         DEBUG(0,("unmarshall_rpc_header: FIRST flag not set in first PDU !\n"));
165                         set_incoming_fault(p);
166                         prs_mem_free(&rpc_in);
167                         return -1;
168                 }
169
170                 /*
171                  * If this is the first PDU then set the endianness
172                  * flag in the pipe. We will need this when parsing all
173                  * data in this RPC.
174                  */
175
176                 p->endian = rpc_in.bigendian_data;
177
178                 DEBUG(5,("unmarshall_rpc_header: using %sendian RPC\n",
179                                 p->endian == RPC_LITTLE_ENDIAN ? "little-" : "big-" ));
180
181         } else {
182
183                 /*
184                  * If this is *NOT* the first PDU then check the endianness
185                  * flag in the pipe is the same as that in the PDU.
186                  */
187
188                 if (p->endian != rpc_in.bigendian_data) {
189                         DEBUG(0,("unmarshall_rpc_header: FIRST endianness flag (%d) different in next PDU !\n", (int)p->endian));
190                         set_incoming_fault(p);
191                         prs_mem_free(&rpc_in);
192                         return -1;
193                 }
194         }
195
196         /*
197          * Ensure that the pdu length is sane.
198          */
199
200         if((p->hdr.frag_len < RPC_HEADER_LEN) || (p->hdr.frag_len > RPC_MAX_PDU_FRAG_LEN)) {
201                 DEBUG(0,("unmarshall_rpc_header: assert on frag length failed.\n"));
202                 set_incoming_fault(p);
203                 prs_mem_free(&rpc_in);
204                 return -1;
205         }
206
207         DEBUG(10,("unmarshall_rpc_header: type = %u, flags = %u\n", (unsigned int)p->hdr.pkt_type,
208                         (unsigned int)p->hdr.flags ));
209
210         p->in_data.pdu_needed_len = (uint32)p->hdr.frag_len - RPC_HEADER_LEN;
211
212         prs_mem_free(&rpc_in);
213
214         p->in_data.current_in_pdu = TALLOC_REALLOC_ARRAY(
215                 p, p->in_data.current_in_pdu, uint8_t, p->hdr.frag_len);
216         if (p->in_data.current_in_pdu == NULL) {
217                 DEBUG(0, ("talloc failed\n"));
218                 set_incoming_fault(p);
219                 return -1;
220         }
221
222         return 0; /* No extra data processed. */
223 }
224
225 /****************************************************************************
226  Call this to free any talloc'ed memory. Do this before and after processing
227  a complete PDU.
228 ****************************************************************************/
229
230 static void free_pipe_context(pipes_struct *p)
231 {
232         if (p->mem_ctx) {
233                 DEBUG(3,("free_pipe_context: destroying talloc pool of size "
234                          "%lu\n", (unsigned long)talloc_total_size(p->mem_ctx) ));
235                 talloc_free_children(p->mem_ctx);
236         } else {
237                 p->mem_ctx = talloc_named(p, 0, "pipe %s %p",
238                                     get_pipe_name_from_syntax(talloc_tos(),
239                                                               &p->syntax), p);
240                 if (p->mem_ctx == NULL) {
241                         p->fault_state = True;
242                 }
243         }
244 }
245
246 /****************************************************************************
247  Processes a request pdu. This will do auth processing if needed, and
248  appends the data into the complete stream if the LAST flag is not set.
249 ****************************************************************************/
250
251 static bool process_request_pdu(pipes_struct *p, prs_struct *rpc_in_p)
252 {
253         uint32 ss_padding_len = 0;
254         size_t data_len = p->hdr.frag_len - RPC_HEADER_LEN - RPC_HDR_REQ_LEN -
255                                 (p->hdr.auth_len ? RPC_HDR_AUTH_LEN : 0) - p->hdr.auth_len;
256
257         if(!p->pipe_bound) {
258                 DEBUG(0,("process_request_pdu: rpc request with no bind.\n"));
259                 set_incoming_fault(p);
260                 return False;
261         }
262
263         /*
264          * Check if we need to do authentication processing.
265          * This is only done on requests, not binds.
266          */
267
268         /*
269          * Read the RPC request header.
270          */
271
272         if(!smb_io_rpc_hdr_req("req", &p->hdr_req, rpc_in_p, 0)) {
273                 DEBUG(0,("process_request_pdu: failed to unmarshall RPC_HDR_REQ.\n"));
274                 set_incoming_fault(p);
275                 return False;
276         }
277
278         switch(p->auth.auth_type) {
279                 case PIPE_AUTH_TYPE_NONE:
280                         break;
281
282                 case PIPE_AUTH_TYPE_SPNEGO_NTLMSSP:
283                 case PIPE_AUTH_TYPE_NTLMSSP:
284                 {
285                         NTSTATUS status;
286                         if(!api_pipe_ntlmssp_auth_process(p, rpc_in_p, &ss_padding_len, &status)) {
287                                 DEBUG(0,("process_request_pdu: failed to do auth processing.\n"));
288                                 DEBUG(0,("process_request_pdu: error was %s.\n", nt_errstr(status) ));
289                                 set_incoming_fault(p);
290                                 return False;
291                         }
292                         break;
293                 }
294
295                 case PIPE_AUTH_TYPE_SCHANNEL:
296                         if (!api_pipe_schannel_process(p, rpc_in_p, &ss_padding_len)) {
297                                 DEBUG(3,("process_request_pdu: failed to do schannel processing.\n"));
298                                 set_incoming_fault(p);
299                                 return False;
300                         }
301                         break;
302
303                 default:
304                         DEBUG(0,("process_request_pdu: unknown auth type %u set.\n", (unsigned int)p->auth.auth_type ));
305                         set_incoming_fault(p);
306                         return False;
307         }
308
309         /* Now we've done the sign/seal we can remove any padding data. */
310         if (data_len > ss_padding_len) {
311                 data_len -= ss_padding_len;
312         }
313
314         /*
315          * Check the data length doesn't go over the 15Mb limit.
316          * increased after observing a bug in the Windows NT 4.0 SP6a
317          * spoolsv.exe when the response to a GETPRINTERDRIVER2 RPC
318          * will not fit in the initial buffer of size 0x1068   --jerry 22/01/2002
319          */
320         
321         if(prs_offset(&p->in_data.data) + data_len > MAX_RPC_DATA_SIZE) {
322                 DEBUG(0,("process_request_pdu: rpc data buffer too large (%u) + (%u)\n",
323                                 (unsigned int)prs_data_size(&p->in_data.data), (unsigned int)data_len ));
324                 set_incoming_fault(p);
325                 return False;
326         }
327
328         /*
329          * Append the data portion into the buffer and return.
330          */
331
332         if(!prs_append_some_prs_data(&p->in_data.data, rpc_in_p, prs_offset(rpc_in_p), data_len)) {
333                 DEBUG(0,("process_request_pdu: Unable to append data size %u to parse buffer of size %u.\n",
334                                 (unsigned int)data_len, (unsigned int)prs_data_size(&p->in_data.data) ));
335                 set_incoming_fault(p);
336                 return False;
337         }
338
339         if(p->hdr.flags & DCERPC_PFC_FLAG_LAST) {
340                 bool ret = False;
341                 /*
342                  * Ok - we finally have a complete RPC stream.
343                  * Call the rpc command to process it.
344                  */
345
346                 /*
347                  * Ensure the internal prs buffer size is *exactly* the same
348                  * size as the current offset.
349                  */
350
351                 if(!prs_set_buffer_size(&p->in_data.data, prs_offset(&p->in_data.data))) {
352                         DEBUG(0,("process_request_pdu: Call to prs_set_buffer_size failed!\n"));
353                         set_incoming_fault(p);
354                         return False;
355                 }
356
357                 /*
358                  * Set the parse offset to the start of the data and set the
359                  * prs_struct to UNMARSHALL.
360                  */
361
362                 prs_set_offset(&p->in_data.data, 0);
363                 prs_switch_type(&p->in_data.data, UNMARSHALL);
364
365                 /*
366                  * Process the complete data stream here.
367                  */
368
369                 free_pipe_context(p);
370
371                 if(pipe_init_outgoing_data(p)) {
372                         ret = api_pipe_request(p);
373                 }
374
375                 free_pipe_context(p);
376
377                 /*
378                  * We have consumed the whole data stream. Set back to
379                  * marshalling and set the offset back to the start of
380                  * the buffer to re-use it (we could also do a prs_mem_free()
381                  * and then re_init on the next start of PDU. Not sure which
382                  * is best here.... JRA.
383                  */
384
385                 prs_switch_type(&p->in_data.data, MARSHALL);
386                 prs_set_offset(&p->in_data.data, 0);
387                 return ret;
388         }
389
390         return True;
391 }
392
393 /****************************************************************************
394  Processes a finished PDU stored in current_in_pdu. The RPC_HEADER has
395  already been parsed and stored in p->hdr.
396 ****************************************************************************/
397
398 static void process_complete_pdu(pipes_struct *p)
399 {
400         prs_struct rpc_in;
401         size_t data_len = p->in_data.pdu_received_len - RPC_HEADER_LEN;
402         char *data_p = (char *)&p->in_data.current_in_pdu[RPC_HEADER_LEN];
403         bool reply = False;
404
405         if(p->fault_state) {
406                 DEBUG(10,("process_complete_pdu: pipe %s in fault state.\n",
407                           get_pipe_name_from_syntax(talloc_tos(), &p->syntax)));
408                 set_incoming_fault(p);
409                 setup_fault_pdu(p, NT_STATUS(DCERPC_FAULT_OP_RNG_ERROR));
410                 return;
411         }
412
413         prs_init_empty( &rpc_in, p->mem_ctx, UNMARSHALL);
414
415         /*
416          * Ensure we're using the corrent endianness for both the 
417          * RPC header flags and the raw data we will be reading from.
418          */
419
420         prs_set_endian_data( &rpc_in, p->endian);
421         prs_set_endian_data( &p->in_data.data, p->endian);
422
423         prs_give_memory( &rpc_in, data_p, (uint32)data_len, False);
424
425         DEBUG(10,("process_complete_pdu: processing packet type %u\n",
426                         (unsigned int)p->hdr.pkt_type ));
427
428         switch (p->hdr.pkt_type) {
429                 case DCERPC_PKT_REQUEST:
430                         reply = process_request_pdu(p, &rpc_in);
431                         break;
432
433                 case DCERPC_PKT_PING: /* CL request - ignore... */
434                         DEBUG(0,("process_complete_pdu: Error. Connectionless packet type %u received on pipe %s.\n",
435                                 (unsigned int)p->hdr.pkt_type,
436                                  get_pipe_name_from_syntax(talloc_tos(),
437                                                            &p->syntax)));
438                         break;
439
440                 case DCERPC_PKT_RESPONSE: /* No responses here. */
441                         DEBUG(0,("process_complete_pdu: Error. DCERPC_PKT_RESPONSE received from client on pipe %s.\n",
442                                  get_pipe_name_from_syntax(talloc_tos(),
443                                                            &p->syntax)));
444                         break;
445
446                 case DCERPC_PKT_FAULT:
447                 case DCERPC_PKT_WORKING: /* CL request - reply to a ping when a call in process. */
448                 case DCERPC_PKT_NOCALL: /* CL - server reply to a ping call. */
449                 case DCERPC_PKT_REJECT:
450                 case DCERPC_PKT_ACK:
451                 case DCERPC_PKT_CL_CANCEL:
452                 case DCERPC_PKT_FACK:
453                 case DCERPC_PKT_CANCEL_ACK:
454                         DEBUG(0,("process_complete_pdu: Error. Connectionless packet type %u received on pipe %s.\n",
455                                 (unsigned int)p->hdr.pkt_type,
456                                  get_pipe_name_from_syntax(talloc_tos(),
457                                                            &p->syntax)));
458                         break;
459
460                 case DCERPC_PKT_BIND:
461                         /*
462                          * We assume that a pipe bind is only in one pdu.
463                          */
464                         if(pipe_init_outgoing_data(p)) {
465                                 reply = api_pipe_bind_req(p, &rpc_in);
466                         }
467                         break;
468
469                 case DCERPC_PKT_BIND_ACK:
470                 case DCERPC_PKT_BIND_NAK:
471                         DEBUG(0,("process_complete_pdu: Error. DCERPC_PKT_BINDACK/DCERPC_PKT_BINDNACK packet type %u received on pipe %s.\n",
472                                 (unsigned int)p->hdr.pkt_type,
473                                  get_pipe_name_from_syntax(talloc_tos(),
474                                                            &p->syntax)));
475                         break;
476
477
478                 case DCERPC_PKT_ALTER:
479                         /*
480                          * We assume that a pipe bind is only in one pdu.
481                          */
482                         if(pipe_init_outgoing_data(p)) {
483                                 reply = api_pipe_alter_context(p, &rpc_in);
484                         }
485                         break;
486
487                 case DCERPC_PKT_ALTER_RESP:
488                         DEBUG(0,("process_complete_pdu: Error. DCERPC_PKT_ALTER_RESP on pipe %s: Should only be server -> client.\n",
489                                  get_pipe_name_from_syntax(talloc_tos(),
490                                                            &p->syntax)));
491                         break;
492
493                 case DCERPC_PKT_AUTH3:
494                         /*
495                          * The third packet in an NTLMSSP auth exchange.
496                          */
497                         if(pipe_init_outgoing_data(p)) {
498                                 reply = api_pipe_bind_auth3(p, &rpc_in);
499                         }
500                         break;
501
502                 case DCERPC_PKT_SHUTDOWN:
503                         DEBUG(0,("process_complete_pdu: Error. DCERPC_PKT_SHUTDOWN on pipe %s: Should only be server -> client.\n",
504                                  get_pipe_name_from_syntax(talloc_tos(),
505                                                            &p->syntax)));
506                         break;
507
508                 case DCERPC_PKT_CO_CANCEL:
509                         /* For now just free all client data and continue processing. */
510                         DEBUG(3,("process_complete_pdu: DCERPC_PKT_CO_CANCEL. Abandoning rpc call.\n"));
511                         /* As we never do asynchronous RPC serving, we can never cancel a
512                            call (as far as I know). If we ever did we'd have to send a cancel_ack
513                            reply. For now, just free all client data and continue processing. */
514                         reply = True;
515                         break;
516 #if 0
517                         /* Enable this if we're doing async rpc. */
518                         /* We must check the call-id matches the outstanding callid. */
519                         if(pipe_init_outgoing_data(p)) {
520                                 /* Send a cancel_ack PDU reply. */
521                                 /* We should probably check the auth-verifier here. */
522                                 reply = setup_cancel_ack_reply(p, &rpc_in);
523                         }
524                         break;
525 #endif
526
527                 case DCERPC_PKT_ORPHANED:
528                         /* We should probably check the auth-verifier here.
529                            For now just free all client data and continue processing. */
530                         DEBUG(3,("process_complete_pdu: DCERPC_PKT_ORPHANED. Abandoning rpc call.\n"));
531                         reply = True;
532                         break;
533
534                 default:
535                         DEBUG(0,("process_complete_pdu: Unknown rpc type = %u received.\n", (unsigned int)p->hdr.pkt_type ));
536                         break;
537         }
538
539         /* Reset to little endian. Probably don't need this but it won't hurt. */
540         prs_set_endian_data( &p->in_data.data, RPC_LITTLE_ENDIAN);
541
542         if (!reply) {
543                 DEBUG(3,("process_complete_pdu: DCE/RPC fault sent on "
544                          "pipe %s\n", get_pipe_name_from_syntax(talloc_tos(),
545                                                                 &p->syntax)));
546                 set_incoming_fault(p);
547                 setup_fault_pdu(p, NT_STATUS(DCERPC_FAULT_OP_RNG_ERROR));
548                 prs_mem_free(&rpc_in);
549         } else {
550                 /*
551                  * Reset the lengths. We're ready for a new pdu.
552                  */
553                 TALLOC_FREE(p->in_data.current_in_pdu);
554                 p->in_data.pdu_needed_len = 0;
555                 p->in_data.pdu_received_len = 0;
556         }
557
558         prs_mem_free(&rpc_in);
559 }
560
561 /****************************************************************************
562  Accepts incoming data on an rpc pipe. Processes the data in pdu sized units.
563 ****************************************************************************/
564
565 static ssize_t process_incoming_data(pipes_struct *p, char *data, size_t n)
566 {
567         size_t data_to_copy = MIN(n, RPC_MAX_PDU_FRAG_LEN - p->in_data.pdu_received_len);
568
569         DEBUG(10,("process_incoming_data: Start: pdu_received_len = %u, pdu_needed_len = %u, incoming data = %u\n",
570                 (unsigned int)p->in_data.pdu_received_len, (unsigned int)p->in_data.pdu_needed_len,
571                 (unsigned int)n ));
572
573         if(data_to_copy == 0) {
574                 /*
575                  * This is an error - data is being received and there is no
576                  * space in the PDU. Free the received data and go into the fault state.
577                  */
578                 DEBUG(0,("process_incoming_data: No space in incoming pdu buffer. Current size = %u \
579 incoming data size = %u\n", (unsigned int)p->in_data.pdu_received_len, (unsigned int)n ));
580                 set_incoming_fault(p);
581                 return -1;
582         }
583
584         /*
585          * If we have no data already, wait until we get at least a RPC_HEADER_LEN
586          * number of bytes before we can do anything.
587          */
588
589         if((p->in_data.pdu_needed_len == 0) && (p->in_data.pdu_received_len < RPC_HEADER_LEN)) {
590                 /*
591                  * Always return here. If we have more data then the RPC_HEADER
592                  * will be processed the next time around the loop.
593                  */
594                 return fill_rpc_header(p, data, data_to_copy);
595         }
596
597         /*
598          * At this point we know we have at least an RPC_HEADER_LEN amount of data
599          * stored in current_in_pdu.
600          */
601
602         /*
603          * If pdu_needed_len is zero this is a new pdu. 
604          * Unmarshall the header so we know how much more
605          * data we need, then loop again.
606          */
607
608         if(p->in_data.pdu_needed_len == 0) {
609                 ssize_t rret = unmarshall_rpc_header(p);
610                 if (rret == -1 || p->in_data.pdu_needed_len > 0) {
611                         return rret;
612                 }
613                 /* If rret == 0 and pdu_needed_len == 0 here we have a PDU that consists
614                    of an RPC_HEADER only. This is a DCERPC_PKT_SHUTDOWN, DCERPC_PKT_CO_CANCEL or DCERPC_PKT_ORPHANED
615                    pdu type. Deal with this in process_complete_pdu(). */
616         }
617
618         /*
619          * Ok - at this point we have a valid RPC_HEADER in p->hdr.
620          * Keep reading until we have a full pdu.
621          */
622
623         data_to_copy = MIN(data_to_copy, p->in_data.pdu_needed_len);
624
625         /*
626          * Copy as much of the data as we need into the current_in_pdu buffer.
627          * pdu_needed_len becomes zero when we have a complete pdu.
628          */
629
630         memcpy( (char *)&p->in_data.current_in_pdu[p->in_data.pdu_received_len], data, data_to_copy);
631         p->in_data.pdu_received_len += data_to_copy;
632         p->in_data.pdu_needed_len -= data_to_copy;
633
634         /*
635          * Do we have a complete PDU ?
636          * (return the number of bytes handled in the call)
637          */
638
639         if(p->in_data.pdu_needed_len == 0) {
640                 process_complete_pdu(p);
641                 return data_to_copy;
642         }
643
644         DEBUG(10,("process_incoming_data: not a complete PDU yet. pdu_received_len = %u, pdu_needed_len = %u\n",
645                 (unsigned int)p->in_data.pdu_received_len, (unsigned int)p->in_data.pdu_needed_len ));
646
647         return (ssize_t)data_to_copy;
648 }
649
650 /****************************************************************************
651  Accepts incoming data on an internal rpc pipe.
652 ****************************************************************************/
653
654 static ssize_t write_to_internal_pipe(struct pipes_struct *p, char *data, size_t n)
655 {
656         size_t data_left = n;
657
658         while(data_left) {
659                 ssize_t data_used;
660
661                 DEBUG(10,("write_to_pipe: data_left = %u\n", (unsigned int)data_left ));
662
663                 data_used = process_incoming_data(p, data, data_left);
664
665                 DEBUG(10,("write_to_pipe: data_used = %d\n", (int)data_used ));
666
667                 if(data_used < 0) {
668                         return -1;
669                 }
670
671                 data_left -= data_used;
672                 data += data_used;
673         }       
674
675         return n;
676 }
677
678 /****************************************************************************
679  Replies to a request to read data from a pipe.
680
681  Headers are interspersed with the data at PDU intervals. By the time
682  this function is called, the start of the data could possibly have been
683  read by an SMBtrans (file_offset != 0).
684
685  Calling create_rpc_reply() here is a hack. The data should already
686  have been prepared into arrays of headers + data stream sections.
687 ****************************************************************************/
688
689 static ssize_t read_from_internal_pipe(struct pipes_struct *p, char *data, size_t n,
690                                        bool *is_data_outstanding)
691 {
692         uint32 pdu_remaining = 0;
693         ssize_t data_returned = 0;
694
695         if (!p) {
696                 DEBUG(0,("read_from_pipe: pipe not open\n"));
697                 return -1;              
698         }
699
700         DEBUG(6,(" name: %s len: %u\n",
701                  get_pipe_name_from_syntax(talloc_tos(), &p->syntax),
702                  (unsigned int)n));
703
704         /*
705          * We cannot return more than one PDU length per
706          * read request.
707          */
708
709         /*
710          * This condition should result in the connection being closed.  
711          * Netapp filers seem to set it to 0xffff which results in domain
712          * authentications failing.  Just ignore it so things work.
713          */
714
715         if(n > RPC_MAX_PDU_FRAG_LEN) {
716                 DEBUG(5,("read_from_pipe: too large read (%u) requested on "
717                          "pipe %s. We can only service %d sized reads.\n",
718                          (unsigned int)n,
719                          get_pipe_name_from_syntax(talloc_tos(), &p->syntax),
720                          RPC_MAX_PDU_FRAG_LEN ));
721                 n = RPC_MAX_PDU_FRAG_LEN;
722         }
723
724         /*
725          * Determine if there is still data to send in the
726          * pipe PDU buffer. Always send this first. Never
727          * send more than is left in the current PDU. The
728          * client should send a new read request for a new
729          * PDU.
730          */
731
732         pdu_remaining = prs_offset(&p->out_data.frag)
733                 - p->out_data.current_pdu_sent;
734
735         if (pdu_remaining > 0) {
736                 data_returned = (ssize_t)MIN(n, pdu_remaining);
737
738                 DEBUG(10,("read_from_pipe: %s: current_pdu_len = %u, "
739                           "current_pdu_sent = %u returning %d bytes.\n",
740                           get_pipe_name_from_syntax(talloc_tos(), &p->syntax),
741                           (unsigned int)prs_offset(&p->out_data.frag),
742                           (unsigned int)p->out_data.current_pdu_sent,
743                           (int)data_returned));
744
745                 memcpy(data,
746                        prs_data_p(&p->out_data.frag)
747                        + p->out_data.current_pdu_sent,
748                        data_returned);
749
750                 p->out_data.current_pdu_sent += (uint32)data_returned;
751                 goto out;
752         }
753
754         /*
755          * At this point p->current_pdu_len == p->current_pdu_sent (which
756          * may of course be zero if this is the first return fragment.
757          */
758
759         DEBUG(10,("read_from_pipe: %s: fault_state = %d : data_sent_length "
760                   "= %u, prs_offset(&p->out_data.rdata) = %u.\n",
761                   get_pipe_name_from_syntax(talloc_tos(), &p->syntax),
762                   (int)p->fault_state,
763                   (unsigned int)p->out_data.data_sent_length,
764                   (unsigned int)prs_offset(&p->out_data.rdata) ));
765
766         if(p->out_data.data_sent_length >= prs_offset(&p->out_data.rdata)) {
767                 /*
768                  * We have sent all possible data, return 0.
769                  */
770                 data_returned = 0;
771                 goto out;
772         }
773
774         /*
775          * We need to create a new PDU from the data left in p->rdata.
776          * Create the header/data/footers. This also sets up the fields
777          * p->current_pdu_len, p->current_pdu_sent, p->data_sent_length
778          * and stores the outgoing PDU in p->current_pdu.
779          */
780
781         if(!create_next_pdu(p)) {
782                 DEBUG(0,("read_from_pipe: %s: create_next_pdu failed.\n",
783                          get_pipe_name_from_syntax(talloc_tos(), &p->syntax)));
784                 return -1;
785         }
786
787         data_returned = MIN(n, prs_offset(&p->out_data.frag));
788
789         memcpy( data, prs_data_p(&p->out_data.frag), (size_t)data_returned);
790         p->out_data.current_pdu_sent += (uint32)data_returned;
791
792   out:
793         (*is_data_outstanding) = prs_offset(&p->out_data.frag) > n;
794
795         if (p->out_data.current_pdu_sent == prs_offset(&p->out_data.frag)) {
796                 /* We've returned everything in the out_data.frag
797                  * so we're done with this pdu. Free it and reset
798                  * current_pdu_sent. */
799                 p->out_data.current_pdu_sent = 0;
800                 prs_mem_free(&p->out_data.frag);
801         }
802         return data_returned;
803 }
804
805 bool fsp_is_np(struct files_struct *fsp)
806 {
807         enum FAKE_FILE_TYPE type;
808
809         if ((fsp == NULL) || (fsp->fake_file_handle == NULL)) {
810                 return false;
811         }
812
813         type = fsp->fake_file_handle->type;
814
815         return ((type == FAKE_FILE_TYPE_NAMED_PIPE)
816                 || (type == FAKE_FILE_TYPE_NAMED_PIPE_PROXY));
817 }
818
819 struct np_proxy_state {
820         uint16_t file_type;
821         uint16_t device_state;
822         uint64_t allocation_size;
823         struct tstream_context *npipe;
824         struct tevent_queue *read_queue;
825         struct tevent_queue *write_queue;
826 };
827
828 static struct np_proxy_state *make_external_rpc_pipe_p(TALLOC_CTX *mem_ctx,
829                                 const char *pipe_name,
830                                 const struct tsocket_address *local_address,
831                                 const struct tsocket_address *remote_address,
832                                 struct auth_serversupplied_info *server_info)
833 {
834         struct np_proxy_state *result;
835         char *socket_np_dir;
836         const char *socket_dir;
837         struct tevent_context *ev;
838         struct tevent_req *subreq;
839         struct netr_SamInfo3 *info3;
840         NTSTATUS status;
841         bool ok;
842         int ret;
843         int sys_errno;
844
845         result = talloc(mem_ctx, struct np_proxy_state);
846         if (result == NULL) {
847                 DEBUG(0, ("talloc failed\n"));
848                 return NULL;
849         }
850
851         result->read_queue = tevent_queue_create(result, "np_read");
852         if (result->read_queue == NULL) {
853                 DEBUG(0, ("tevent_queue_create failed\n"));
854                 goto fail;
855         }
856
857         result->write_queue = tevent_queue_create(result, "np_write");
858         if (result->write_queue == NULL) {
859                 DEBUG(0, ("tevent_queue_create failed\n"));
860                 goto fail;
861         }
862
863         ev = s3_tevent_context_init(talloc_tos());
864         if (ev == NULL) {
865                 DEBUG(0, ("s3_tevent_context_init failed\n"));
866                 goto fail;
867         }
868
869         socket_dir = lp_parm_const_string(
870                 GLOBAL_SECTION_SNUM, "external_rpc_pipe", "socket_dir",
871                 get_dyn_NCALRPCDIR());
872         if (socket_dir == NULL) {
873                 DEBUG(0, ("externan_rpc_pipe:socket_dir not set\n"));
874                 goto fail;
875         }
876         socket_np_dir = talloc_asprintf(talloc_tos(), "%s/np", socket_dir);
877         if (socket_np_dir == NULL) {
878                 DEBUG(0, ("talloc_asprintf failed\n"));
879                 goto fail;
880         }
881
882         info3 = talloc_zero(talloc_tos(), struct netr_SamInfo3);
883         if (info3 == NULL) {
884                 DEBUG(0, ("talloc failed\n"));
885                 goto fail;
886         }
887
888         status = serverinfo_to_SamInfo3(server_info, NULL, 0, info3);
889         if (!NT_STATUS_IS_OK(status)) {
890                 TALLOC_FREE(info3);
891                 DEBUG(0, ("serverinfo_to_SamInfo3 failed: %s\n",
892                           nt_errstr(status)));
893                 goto fail;
894         }
895
896         become_root();
897         subreq = tstream_npa_connect_send(talloc_tos(), ev,
898                                           socket_np_dir,
899                                           pipe_name,
900                                           remote_address, /* client_addr */
901                                           NULL, /* client_name */
902                                           local_address, /* server_addr */
903                                           NULL, /* server_name */
904                                           info3,
905                                           server_info->user_session_key,
906                                           data_blob_null /* delegated_creds */);
907         if (subreq == NULL) {
908                 unbecome_root();
909                 DEBUG(0, ("tstream_npa_connect_send to %s for pipe %s and user %s\\%s failed\n",
910                           socket_np_dir, pipe_name, info3->base.domain.string, info3->base.account_name.string));
911                 goto fail;
912         }
913         ok = tevent_req_poll(subreq, ev);
914         unbecome_root();
915         if (!ok) {
916                 DEBUG(0, ("tevent_req_poll to %s for pipe %s and user %s\\%s failed for tstream_npa_connect: %s\n",
917                           socket_np_dir, pipe_name, info3->base.domain.string, info3->base.account_name.string,
918                           strerror(errno)));
919                 goto fail;
920
921         }
922         ret = tstream_npa_connect_recv(subreq, &sys_errno,
923                                        result,
924                                        &result->npipe,
925                                        &result->file_type,
926                                        &result->device_state,
927                                        &result->allocation_size);
928         TALLOC_FREE(subreq);
929         if (ret != 0) {
930                 DEBUG(0, ("tstream_npa_connect_recv  to %s for pipe %s and user %s\\%s failed: %s\n",
931                           socket_np_dir, pipe_name, info3->base.domain.string, info3->base.account_name.string,
932                           strerror(sys_errno)));
933                 goto fail;
934         }
935
936         return result;
937
938  fail:
939         TALLOC_FREE(result);
940         return NULL;
941 }
942
943 NTSTATUS np_open(TALLOC_CTX *mem_ctx, const char *name,
944                  const struct tsocket_address *local_address,
945                  const struct tsocket_address *remote_address,
946                  struct auth_serversupplied_info *server_info,
947                  struct fake_file_handle **phandle)
948 {
949         const char **proxy_list;
950         struct fake_file_handle *handle;
951
952         proxy_list = lp_parm_string_list(-1, "np", "proxy", NULL);
953
954         handle = talloc(mem_ctx, struct fake_file_handle);
955         if (handle == NULL) {
956                 return NT_STATUS_NO_MEMORY;
957         }
958
959         if ((proxy_list != NULL) && str_list_check_ci(proxy_list, name)) {
960                 struct np_proxy_state *p;
961
962                 p = make_external_rpc_pipe_p(handle, name,
963                                              local_address,
964                                              remote_address,
965                                              server_info);
966
967                 handle->type = FAKE_FILE_TYPE_NAMED_PIPE_PROXY;
968                 handle->private_data = p;
969         } else {
970                 struct pipes_struct *p;
971                 struct ndr_syntax_id syntax;
972                 const char *client_address;
973
974                 if (!is_known_pipename(name, &syntax)) {
975                         TALLOC_FREE(handle);
976                         return NT_STATUS_OBJECT_NAME_NOT_FOUND;
977                 }
978
979                 if (tsocket_address_is_inet(remote_address, "ip")) {
980                         client_address = tsocket_address_inet_addr_string(
981                                                 remote_address,
982                                                 talloc_tos());
983                         if (client_address == NULL) {
984                                 TALLOC_FREE(handle);
985                                 return NT_STATUS_NO_MEMORY;
986                         }
987                 } else {
988                         client_address = "";
989                 }
990
991                 p = make_internal_rpc_pipe_p(handle, &syntax, client_address,
992                                              server_info);
993
994                 handle->type = FAKE_FILE_TYPE_NAMED_PIPE;
995                 handle->private_data = p;
996         }
997
998         if (handle->private_data == NULL) {
999                 TALLOC_FREE(handle);
1000                 return NT_STATUS_PIPE_NOT_AVAILABLE;
1001         }
1002
1003         *phandle = handle;
1004
1005         return NT_STATUS_OK;
1006 }
1007
1008 bool np_read_in_progress(struct fake_file_handle *handle)
1009 {
1010         if (handle->type == FAKE_FILE_TYPE_NAMED_PIPE) {
1011                 return false;
1012         }
1013
1014         if (handle->type == FAKE_FILE_TYPE_NAMED_PIPE_PROXY) {
1015                 struct np_proxy_state *p = talloc_get_type_abort(
1016                         handle->private_data, struct np_proxy_state);
1017                 size_t read_count;
1018
1019                 read_count = tevent_queue_length(p->read_queue);
1020                 if (read_count > 0) {
1021                         return true;
1022                 }
1023
1024                 return false;
1025         }
1026
1027         return false;
1028 }
1029
1030 struct np_write_state {
1031         struct event_context *ev;
1032         struct np_proxy_state *p;
1033         struct iovec iov;
1034         ssize_t nwritten;
1035 };
1036
1037 static void np_write_done(struct tevent_req *subreq);
1038
1039 struct tevent_req *np_write_send(TALLOC_CTX *mem_ctx, struct event_context *ev,
1040                                  struct fake_file_handle *handle,
1041                                  const uint8_t *data, size_t len)
1042 {
1043         struct tevent_req *req;
1044         struct np_write_state *state;
1045         NTSTATUS status;
1046
1047         DEBUG(6, ("np_write_send: len: %d\n", (int)len));
1048         dump_data(50, data, len);
1049
1050         req = tevent_req_create(mem_ctx, &state, struct np_write_state);
1051         if (req == NULL) {
1052                 return NULL;
1053         }
1054
1055         if (len == 0) {
1056                 state->nwritten = 0;
1057                 status = NT_STATUS_OK;
1058                 goto post_status;
1059         }
1060
1061         if (handle->type == FAKE_FILE_TYPE_NAMED_PIPE) {
1062                 struct pipes_struct *p = talloc_get_type_abort(
1063                         handle->private_data, struct pipes_struct);
1064
1065                 state->nwritten = write_to_internal_pipe(p, (char *)data, len);
1066
1067                 status = (state->nwritten >= 0)
1068                         ? NT_STATUS_OK : NT_STATUS_UNEXPECTED_IO_ERROR;
1069                 goto post_status;
1070         }
1071
1072         if (handle->type == FAKE_FILE_TYPE_NAMED_PIPE_PROXY) {
1073                 struct np_proxy_state *p = talloc_get_type_abort(
1074                         handle->private_data, struct np_proxy_state);
1075                 struct tevent_req *subreq;
1076
1077                 state->ev = ev;
1078                 state->p = p;
1079                 state->iov.iov_base = CONST_DISCARD(void *, data);
1080                 state->iov.iov_len = len;
1081
1082                 subreq = tstream_writev_queue_send(state, ev,
1083                                                    p->npipe,
1084                                                    p->write_queue,
1085                                                    &state->iov, 1);
1086                 if (subreq == NULL) {
1087                         goto fail;
1088                 }
1089                 tevent_req_set_callback(subreq, np_write_done, req);
1090                 return req;
1091         }
1092
1093         status = NT_STATUS_INVALID_HANDLE;
1094  post_status:
1095         if (NT_STATUS_IS_OK(status)) {
1096                 tevent_req_done(req);
1097         } else {
1098                 tevent_req_nterror(req, status);
1099         }
1100         return tevent_req_post(req, ev);
1101  fail:
1102         TALLOC_FREE(req);
1103         return NULL;
1104 }
1105
1106 static void np_write_done(struct tevent_req *subreq)
1107 {
1108         struct tevent_req *req = tevent_req_callback_data(
1109                 subreq, struct tevent_req);
1110         struct np_write_state *state = tevent_req_data(
1111                 req, struct np_write_state);
1112         ssize_t received;
1113         int err;
1114
1115         received = tstream_writev_queue_recv(subreq, &err);
1116         if (received < 0) {
1117                 tevent_req_nterror(req, map_nt_error_from_unix(err));
1118                 return;
1119         }
1120         state->nwritten = received;
1121         tevent_req_done(req);
1122 }
1123
1124 NTSTATUS np_write_recv(struct tevent_req *req, ssize_t *pnwritten)
1125 {
1126         struct np_write_state *state = tevent_req_data(
1127                 req, struct np_write_state);
1128         NTSTATUS status;
1129
1130         if (tevent_req_is_nterror(req, &status)) {
1131                 return status;
1132         }
1133         *pnwritten = state->nwritten;
1134         return NT_STATUS_OK;
1135 }
1136
1137 struct np_ipc_readv_next_vector_state {
1138         uint8_t *buf;
1139         size_t len;
1140         off_t ofs;
1141         size_t remaining;
1142 };
1143
1144 static void np_ipc_readv_next_vector_init(struct np_ipc_readv_next_vector_state *s,
1145                                           uint8_t *buf, size_t len)
1146 {
1147         ZERO_STRUCTP(s);
1148
1149         s->buf = buf;
1150         s->len = MIN(len, UINT16_MAX);
1151 }
1152
1153 static int np_ipc_readv_next_vector(struct tstream_context *stream,
1154                                     void *private_data,
1155                                     TALLOC_CTX *mem_ctx,
1156                                     struct iovec **_vector,
1157                                     size_t *count)
1158 {
1159         struct np_ipc_readv_next_vector_state *state =
1160                 (struct np_ipc_readv_next_vector_state *)private_data;
1161         struct iovec *vector;
1162         ssize_t pending;
1163         size_t wanted;
1164
1165         if (state->ofs == state->len) {
1166                 *_vector = NULL;
1167                 *count = 0;
1168                 return 0;
1169         }
1170
1171         pending = tstream_pending_bytes(stream);
1172         if (pending == -1) {
1173                 return -1;
1174         }
1175
1176         if (pending == 0 && state->ofs != 0) {
1177                 /* return a short read */
1178                 *_vector = NULL;
1179                 *count = 0;
1180                 return 0;
1181         }
1182
1183         if (pending == 0) {
1184                 /* we want at least one byte and recheck again */
1185                 wanted = 1;
1186         } else {
1187                 size_t missing = state->len - state->ofs;
1188                 if (pending > missing) {
1189                         /* there's more available */
1190                         state->remaining = pending - missing;
1191                         wanted = missing;
1192                 } else {
1193                         /* read what we can get and recheck in the next cycle */
1194                         wanted = pending;
1195                 }
1196         }
1197
1198         vector = talloc_array(mem_ctx, struct iovec, 1);
1199         if (!vector) {
1200                 return -1;
1201         }
1202
1203         vector[0].iov_base = state->buf + state->ofs;
1204         vector[0].iov_len = wanted;
1205
1206         state->ofs += wanted;
1207
1208         *_vector = vector;
1209         *count = 1;
1210         return 0;
1211 }
1212
1213 struct np_read_state {
1214         struct np_proxy_state *p;
1215         struct np_ipc_readv_next_vector_state next_vector;
1216
1217         size_t nread;
1218         bool is_data_outstanding;
1219 };
1220
1221 static void np_read_done(struct tevent_req *subreq);
1222
1223 struct tevent_req *np_read_send(TALLOC_CTX *mem_ctx, struct event_context *ev,
1224                                 struct fake_file_handle *handle,
1225                                 uint8_t *data, size_t len)
1226 {
1227         struct tevent_req *req;
1228         struct np_read_state *state;
1229         NTSTATUS status;
1230
1231         req = tevent_req_create(mem_ctx, &state, struct np_read_state);
1232         if (req == NULL) {
1233                 return NULL;
1234         }
1235
1236         if (handle->type == FAKE_FILE_TYPE_NAMED_PIPE) {
1237                 struct pipes_struct *p = talloc_get_type_abort(
1238                         handle->private_data, struct pipes_struct);
1239
1240                 state->nread = read_from_internal_pipe(
1241                         p, (char *)data, len, &state->is_data_outstanding);
1242
1243                 status = (state->nread >= 0)
1244                         ? NT_STATUS_OK : NT_STATUS_UNEXPECTED_IO_ERROR;
1245                 goto post_status;
1246         }
1247
1248         if (handle->type == FAKE_FILE_TYPE_NAMED_PIPE_PROXY) {
1249                 struct np_proxy_state *p = talloc_get_type_abort(
1250                         handle->private_data, struct np_proxy_state);
1251                 struct tevent_req *subreq;
1252
1253                 np_ipc_readv_next_vector_init(&state->next_vector,
1254                                               data, len);
1255
1256                 subreq = tstream_readv_pdu_queue_send(state,
1257                                                       ev,
1258                                                       p->npipe,
1259                                                       p->read_queue,
1260                                                       np_ipc_readv_next_vector,
1261                                                       &state->next_vector);
1262                 if (subreq == NULL) {
1263
1264                 }
1265                 tevent_req_set_callback(subreq, np_read_done, req);
1266                 return req;
1267         }
1268
1269         status = NT_STATUS_INVALID_HANDLE;
1270  post_status:
1271         if (NT_STATUS_IS_OK(status)) {
1272                 tevent_req_done(req);
1273         } else {
1274                 tevent_req_nterror(req, status);
1275         }
1276         return tevent_req_post(req, ev);
1277 }
1278
1279 static void np_read_done(struct tevent_req *subreq)
1280 {
1281         struct tevent_req *req = tevent_req_callback_data(
1282                 subreq, struct tevent_req);
1283         struct np_read_state *state = tevent_req_data(
1284                 req, struct np_read_state);
1285         ssize_t ret;
1286         int err;
1287
1288         ret = tstream_readv_pdu_queue_recv(subreq, &err);
1289         TALLOC_FREE(subreq);
1290         if (ret == -1) {
1291                 tevent_req_nterror(req, map_nt_error_from_unix(err));
1292                 return;
1293         }
1294
1295         state->nread = ret;
1296         state->is_data_outstanding = (state->next_vector.remaining > 0);
1297
1298         tevent_req_done(req);
1299         return;
1300 }
1301
1302 NTSTATUS np_read_recv(struct tevent_req *req, ssize_t *nread,
1303                       bool *is_data_outstanding)
1304 {
1305         struct np_read_state *state = tevent_req_data(
1306                 req, struct np_read_state);
1307         NTSTATUS status;
1308
1309         if (tevent_req_is_nterror(req, &status)) {
1310                 return status;
1311         }
1312         *nread = state->nread;
1313         *is_data_outstanding = state->is_data_outstanding;
1314         return NT_STATUS_OK;
1315 }
1316
1317 /**
1318  * @brief Create a new RPC client context which uses a local dispatch function.
1319  *
1320  * @param[in]  conn  The connection struct that will hold the pipe
1321  *
1322  * @param[out] spoolss_pipe  A pointer to the connected rpc client pipe.
1323  *
1324  * @return              NT_STATUS_OK on success, a corresponding NT status if an
1325  *                      error occured.
1326  */
1327 NTSTATUS rpc_connect_spoolss_pipe(connection_struct *conn,
1328                                   struct rpc_pipe_client **spoolss_pipe)
1329 {
1330         NTSTATUS status;
1331
1332         /* TODO: check and handle disconnections */
1333
1334         if (!conn->spoolss_pipe) {
1335                 status = rpc_pipe_open_internal(conn,
1336                                                 &ndr_table_spoolss.syntax_id,
1337                                                 rpc_spoolss_dispatch,
1338                                                 conn->server_info,
1339                                                 &conn->spoolss_pipe);
1340                 if (!NT_STATUS_IS_OK(status)) {
1341                         return status;
1342                 }
1343         }
1344
1345         *spoolss_pipe = conn->spoolss_pipe;
1346         return NT_STATUS_OK;
1347 }