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
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.
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.
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/>.
23 #include "../librpc/gen_ndr/srv_spoolss.h"
24 #include "librpc/gen_ndr/ndr_named_pipe_auth.h"
25 #include "../libcli/named_pipe_auth/npa_tstream.h"
26 #include "rpc_server.h"
27 #include "smbd/globals.h"
28 #include "fake_file.h"
30 #include "rpc_server/rpc_ncacn_np.h"
32 #include "../lib/tsocket/tsocket.h"
33 #include "../lib/util/tevent_ntstatus.h"
36 #define DBGC_CLASS DBGC_RPC_SRV
38 /****************************************************************************
39 Ensures we have at least RPC_HEADER_LEN amount of data in the incoming buffer.
40 ****************************************************************************/
42 static ssize_t fill_rpc_header(struct pipes_struct *p, char *data, size_t data_to_copy)
44 size_t len_needed_to_complete_hdr =
45 MIN(data_to_copy, RPC_HEADER_LEN - p->in_data.pdu.length);
47 DEBUG(10, ("fill_rpc_header: data_to_copy = %u, "
48 "len_needed_to_complete_hdr = %u, "
50 (unsigned int)data_to_copy,
51 (unsigned int)len_needed_to_complete_hdr,
52 (unsigned int)p->in_data.pdu.length ));
54 if (p->in_data.pdu.data == NULL) {
55 p->in_data.pdu.data = talloc_array(p, uint8_t, RPC_HEADER_LEN);
57 if (p->in_data.pdu.data == NULL) {
58 DEBUG(0, ("talloc failed\n"));
62 memcpy((char *)&p->in_data.pdu.data[p->in_data.pdu.length],
63 data, len_needed_to_complete_hdr);
64 p->in_data.pdu.length += len_needed_to_complete_hdr;
66 return (ssize_t)len_needed_to_complete_hdr;
69 static bool get_pdu_size(struct pipes_struct *p)
72 /* the fill_rpc_header() call insures we copy only
73 * RPC_HEADER_LEN bytes. If this doesn't match then
74 * somethign is very wrong and we can only abort */
75 if (p->in_data.pdu.length != RPC_HEADER_LEN) {
76 DEBUG(0, ("Unexpected RPC Header size! "
77 "got %d, expected %d)\n",
78 (int)p->in_data.pdu.length,
80 set_incoming_fault(p);
84 frag_len = dcerpc_get_frag_length(&p->in_data.pdu);
86 /* verify it is a reasonable value */
87 if ((frag_len < RPC_HEADER_LEN) ||
88 (frag_len > RPC_MAX_PDU_FRAG_LEN)) {
89 DEBUG(0, ("Unexpected RPC Fragment size! (%d)\n",
91 set_incoming_fault(p);
95 p->in_data.pdu_needed_len = frag_len - RPC_HEADER_LEN;
97 /* allocate the space needed to fill the pdu */
98 p->in_data.pdu.data = talloc_realloc(p, p->in_data.pdu.data,
100 if (p->in_data.pdu.data == NULL) {
101 DEBUG(0, ("talloc_realloc failed\n"));
102 set_incoming_fault(p);
109 /****************************************************************************
110 Call this to free any talloc'ed memory. Do this after processing
111 a complete incoming and outgoing request (multiple incoming/outgoing
113 ****************************************************************************/
115 static void free_pipe_context(struct pipes_struct *p)
117 data_blob_free(&p->out_data.frag);
118 data_blob_free(&p->out_data.rdata);
119 data_blob_free(&p->in_data.data);
121 DEBUG(3, ("free_pipe_context: "
122 "destroying talloc pool of size %lu\n",
123 (unsigned long)talloc_total_size(p->mem_ctx)));
124 talloc_free_children(p->mem_ctx);
127 /****************************************************************************
128 Accepts incoming data on an rpc pipe. Processes the data in pdu sized units.
129 ****************************************************************************/
131 ssize_t process_incoming_data(struct pipes_struct *p, char *data, size_t n)
133 size_t data_to_copy = MIN(n, RPC_MAX_PDU_FRAG_LEN
134 - p->in_data.pdu.length);
136 DEBUG(10, ("process_incoming_data: Start: pdu.length = %u, "
137 "pdu_needed_len = %u, incoming data = %u\n",
138 (unsigned int)p->in_data.pdu.length,
139 (unsigned int)p->in_data.pdu_needed_len,
142 if(data_to_copy == 0) {
144 * This is an error - data is being received and there is no
145 * space in the PDU. Free the received data and go into the
148 DEBUG(0, ("process_incoming_data: "
149 "No space in incoming pdu buffer. "
150 "Current size = %u incoming data size = %u\n",
151 (unsigned int)p->in_data.pdu.length,
153 set_incoming_fault(p);
158 * If we have no data already, wait until we get at least
159 * a RPC_HEADER_LEN * number of bytes before we can do anything.
162 if ((p->in_data.pdu_needed_len == 0) &&
163 (p->in_data.pdu.length < RPC_HEADER_LEN)) {
165 * Always return here. If we have more data then the RPC_HEADER
166 * will be processed the next time around the loop.
168 return fill_rpc_header(p, data, data_to_copy);
172 * At this point we know we have at least an RPC_HEADER_LEN amount of
173 * data stored in p->in_data.pdu.
177 * If pdu_needed_len is zero this is a new pdu.
178 * Check how much more data we need, then loop again.
180 if (p->in_data.pdu_needed_len == 0) {
182 bool ok = get_pdu_size(p);
186 if (p->in_data.pdu_needed_len > 0) {
190 /* If rret == 0 and pdu_needed_len == 0 here we have a PDU
191 * that consists of an RPC_HEADER only. This is a
192 * DCERPC_PKT_SHUTDOWN, DCERPC_PKT_CO_CANCEL or
193 * DCERPC_PKT_ORPHANED pdu type.
194 * Deal with this in process_complete_pdu(). */
198 * Ok - at this point we have a valid RPC_HEADER.
199 * Keep reading until we have a full pdu.
202 data_to_copy = MIN(data_to_copy, p->in_data.pdu_needed_len);
205 * Copy as much of the data as we need into the p->in_data.pdu buffer.
206 * pdu_needed_len becomes zero when we have a complete pdu.
209 memcpy((char *)&p->in_data.pdu.data[p->in_data.pdu.length],
211 p->in_data.pdu.length += data_to_copy;
212 p->in_data.pdu_needed_len -= data_to_copy;
215 * Do we have a complete PDU ?
216 * (return the number of bytes handled in the call)
219 if(p->in_data.pdu_needed_len == 0) {
220 process_complete_pdu(p);
224 DEBUG(10, ("process_incoming_data: not a complete PDU yet. "
225 "pdu.length = %u, pdu_needed_len = %u\n",
226 (unsigned int)p->in_data.pdu.length,
227 (unsigned int)p->in_data.pdu_needed_len));
229 return (ssize_t)data_to_copy;
232 /****************************************************************************
233 Accepts incoming data on an internal rpc pipe.
234 ****************************************************************************/
236 static ssize_t write_to_internal_pipe(struct pipes_struct *p, char *data, size_t n)
238 size_t data_left = n;
243 DEBUG(10, ("write_to_pipe: data_left = %u\n",
244 (unsigned int)data_left));
246 data_used = process_incoming_data(p, data, data_left);
248 DEBUG(10, ("write_to_pipe: data_used = %d\n",
255 data_left -= data_used;
262 /****************************************************************************
263 Replies to a request to read data from a pipe.
265 Headers are interspersed with the data at PDU intervals. By the time
266 this function is called, the start of the data could possibly have been
267 read by an SMBtrans (file_offset != 0).
269 Calling create_rpc_reply() here is a hack. The data should already
270 have been prepared into arrays of headers + data stream sections.
271 ****************************************************************************/
273 static ssize_t read_from_internal_pipe(struct pipes_struct *p, char *data,
274 size_t n, bool *is_data_outstanding)
276 uint32 pdu_remaining = 0;
277 ssize_t data_returned = 0;
280 DEBUG(0,("read_from_pipe: pipe not open\n"));
284 DEBUG(6,(" name: %s len: %u\n",
285 get_pipe_name_from_syntax(talloc_tos(), &p->syntax),
289 * We cannot return more than one PDU length per
294 * This condition should result in the connection being closed.
295 * Netapp filers seem to set it to 0xffff which results in domain
296 * authentications failing. Just ignore it so things work.
299 if(n > RPC_MAX_PDU_FRAG_LEN) {
300 DEBUG(5,("read_from_pipe: too large read (%u) requested on "
301 "pipe %s. We can only service %d sized reads.\n",
303 get_pipe_name_from_syntax(talloc_tos(), &p->syntax),
304 RPC_MAX_PDU_FRAG_LEN ));
305 n = RPC_MAX_PDU_FRAG_LEN;
309 * Determine if there is still data to send in the
310 * pipe PDU buffer. Always send this first. Never
311 * send more than is left in the current PDU. The
312 * client should send a new read request for a new
316 pdu_remaining = p->out_data.frag.length
317 - p->out_data.current_pdu_sent;
319 if (pdu_remaining > 0) {
320 data_returned = (ssize_t)MIN(n, pdu_remaining);
322 DEBUG(10,("read_from_pipe: %s: current_pdu_len = %u, "
323 "current_pdu_sent = %u returning %d bytes.\n",
324 get_pipe_name_from_syntax(talloc_tos(), &p->syntax),
325 (unsigned int)p->out_data.frag.length,
326 (unsigned int)p->out_data.current_pdu_sent,
327 (int)data_returned));
330 p->out_data.frag.data
331 + p->out_data.current_pdu_sent,
334 p->out_data.current_pdu_sent += (uint32)data_returned;
339 * At this point p->current_pdu_len == p->current_pdu_sent (which
340 * may of course be zero if this is the first return fragment.
343 DEBUG(10,("read_from_pipe: %s: fault_state = %d : data_sent_length "
344 "= %u, p->out_data.rdata.length = %u.\n",
345 get_pipe_name_from_syntax(talloc_tos(), &p->syntax),
347 (unsigned int)p->out_data.data_sent_length,
348 (unsigned int)p->out_data.rdata.length));
350 if (p->out_data.data_sent_length >= p->out_data.rdata.length) {
352 * We have sent all possible data, return 0.
359 * We need to create a new PDU from the data left in p->rdata.
360 * Create the header/data/footers. This also sets up the fields
361 * p->current_pdu_len, p->current_pdu_sent, p->data_sent_length
362 * and stores the outgoing PDU in p->current_pdu.
365 if(!create_next_pdu(p)) {
366 DEBUG(0,("read_from_pipe: %s: create_next_pdu failed.\n",
367 get_pipe_name_from_syntax(talloc_tos(), &p->syntax)));
371 data_returned = MIN(n, p->out_data.frag.length);
373 memcpy(data, p->out_data.frag.data, (size_t)data_returned);
374 p->out_data.current_pdu_sent += (uint32)data_returned;
377 (*is_data_outstanding) = p->out_data.frag.length > n;
379 if (p->out_data.current_pdu_sent == p->out_data.frag.length) {
380 /* We've returned everything in the out_data.frag
381 * so we're done with this pdu. Free it and reset
382 * current_pdu_sent. */
383 p->out_data.current_pdu_sent = 0;
384 data_blob_free(&p->out_data.frag);
386 if (p->out_data.data_sent_length >= p->out_data.rdata.length) {
388 * We're completely finished with both outgoing and
389 * incoming data streams. It's safe to free all
390 * temporary data from this request.
392 free_pipe_context(p);
396 return data_returned;
399 bool fsp_is_np(struct files_struct *fsp)
401 enum FAKE_FILE_TYPE type;
403 if ((fsp == NULL) || (fsp->fake_file_handle == NULL)) {
407 type = fsp->fake_file_handle->type;
409 return ((type == FAKE_FILE_TYPE_NAMED_PIPE)
410 || (type == FAKE_FILE_TYPE_NAMED_PIPE_PROXY));
413 NTSTATUS np_open(TALLOC_CTX *mem_ctx, const char *name,
414 const struct tsocket_address *local_address,
415 const struct tsocket_address *remote_address,
416 struct client_address *client_id,
417 struct auth_serversupplied_info *session_info,
418 struct messaging_context *msg_ctx,
419 struct fake_file_handle **phandle)
421 const char *rpcsrv_type;
422 const char **proxy_list;
423 struct fake_file_handle *handle;
424 bool external = false;
426 proxy_list = lp_parm_string_list(-1, "np", "proxy", NULL);
428 handle = talloc(mem_ctx, struct fake_file_handle);
429 if (handle == NULL) {
430 return NT_STATUS_NO_MEMORY;
433 /* Check what is the server type for this pipe.
434 Defaults to "embedded" */
435 rpcsrv_type = lp_parm_const_string(GLOBAL_SECTION_SNUM,
438 if (StrCaseCmp(rpcsrv_type, "embedded") != 0) {
442 /* Still support the old method for defining external servers */
443 if ((proxy_list != NULL) && str_list_check_ci(proxy_list, name)) {
448 struct np_proxy_state *p;
450 p = make_external_rpc_pipe_p(handle, name,
455 handle->type = FAKE_FILE_TYPE_NAMED_PIPE_PROXY;
456 handle->private_data = p;
458 struct pipes_struct *p;
459 struct ndr_syntax_id syntax;
461 if (!is_known_pipename(name, &syntax)) {
463 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
466 p = make_internal_rpc_pipe_p(handle, &syntax, client_id,
467 session_info, msg_ctx);
469 handle->type = FAKE_FILE_TYPE_NAMED_PIPE;
470 handle->private_data = p;
473 if (handle->private_data == NULL) {
475 return NT_STATUS_PIPE_NOT_AVAILABLE;
483 bool np_read_in_progress(struct fake_file_handle *handle)
485 if (handle->type == FAKE_FILE_TYPE_NAMED_PIPE) {
489 if (handle->type == FAKE_FILE_TYPE_NAMED_PIPE_PROXY) {
490 struct np_proxy_state *p = talloc_get_type_abort(
491 handle->private_data, struct np_proxy_state);
494 read_count = tevent_queue_length(p->read_queue);
495 if (read_count > 0) {
505 struct np_write_state {
506 struct event_context *ev;
507 struct np_proxy_state *p;
512 static void np_write_done(struct tevent_req *subreq);
514 struct tevent_req *np_write_send(TALLOC_CTX *mem_ctx, struct event_context *ev,
515 struct fake_file_handle *handle,
516 const uint8_t *data, size_t len)
518 struct tevent_req *req;
519 struct np_write_state *state;
522 DEBUG(6, ("np_write_send: len: %d\n", (int)len));
523 dump_data(50, data, len);
525 req = tevent_req_create(mem_ctx, &state, struct np_write_state);
532 status = NT_STATUS_OK;
536 if (handle->type == FAKE_FILE_TYPE_NAMED_PIPE) {
537 struct pipes_struct *p = talloc_get_type_abort(
538 handle->private_data, struct pipes_struct);
540 state->nwritten = write_to_internal_pipe(p, (char *)data, len);
542 status = (state->nwritten >= 0)
543 ? NT_STATUS_OK : NT_STATUS_UNEXPECTED_IO_ERROR;
547 if (handle->type == FAKE_FILE_TYPE_NAMED_PIPE_PROXY) {
548 struct np_proxy_state *p = talloc_get_type_abort(
549 handle->private_data, struct np_proxy_state);
550 struct tevent_req *subreq;
554 state->iov.iov_base = CONST_DISCARD(void *, data);
555 state->iov.iov_len = len;
557 subreq = tstream_writev_queue_send(state, ev,
561 if (subreq == NULL) {
564 tevent_req_set_callback(subreq, np_write_done, req);
568 status = NT_STATUS_INVALID_HANDLE;
570 if (NT_STATUS_IS_OK(status)) {
571 tevent_req_done(req);
573 tevent_req_nterror(req, status);
575 return tevent_req_post(req, ev);
581 static void np_write_done(struct tevent_req *subreq)
583 struct tevent_req *req = tevent_req_callback_data(
584 subreq, struct tevent_req);
585 struct np_write_state *state = tevent_req_data(
586 req, struct np_write_state);
590 received = tstream_writev_queue_recv(subreq, &err);
592 tevent_req_nterror(req, map_nt_error_from_unix(err));
595 state->nwritten = received;
596 tevent_req_done(req);
599 NTSTATUS np_write_recv(struct tevent_req *req, ssize_t *pnwritten)
601 struct np_write_state *state = tevent_req_data(
602 req, struct np_write_state);
605 if (tevent_req_is_nterror(req, &status)) {
608 *pnwritten = state->nwritten;
612 struct np_ipc_readv_next_vector_state {
619 static void np_ipc_readv_next_vector_init(struct np_ipc_readv_next_vector_state *s,
620 uint8_t *buf, size_t len)
625 s->len = MIN(len, UINT16_MAX);
628 static int np_ipc_readv_next_vector(struct tstream_context *stream,
631 struct iovec **_vector,
634 struct np_ipc_readv_next_vector_state *state =
635 (struct np_ipc_readv_next_vector_state *)private_data;
636 struct iovec *vector;
640 if (state->ofs == state->len) {
646 pending = tstream_pending_bytes(stream);
651 if (pending == 0 && state->ofs != 0) {
652 /* return a short read */
659 /* we want at least one byte and recheck again */
662 size_t missing = state->len - state->ofs;
663 if (pending > missing) {
664 /* there's more available */
665 state->remaining = pending - missing;
668 /* read what we can get and recheck in the next cycle */
673 vector = talloc_array(mem_ctx, struct iovec, 1);
678 vector[0].iov_base = state->buf + state->ofs;
679 vector[0].iov_len = wanted;
681 state->ofs += wanted;
688 struct np_read_state {
689 struct np_proxy_state *p;
690 struct np_ipc_readv_next_vector_state next_vector;
693 bool is_data_outstanding;
696 static void np_read_done(struct tevent_req *subreq);
698 struct tevent_req *np_read_send(TALLOC_CTX *mem_ctx, struct event_context *ev,
699 struct fake_file_handle *handle,
700 uint8_t *data, size_t len)
702 struct tevent_req *req;
703 struct np_read_state *state;
706 req = tevent_req_create(mem_ctx, &state, struct np_read_state);
711 if (handle->type == FAKE_FILE_TYPE_NAMED_PIPE) {
712 struct pipes_struct *p = talloc_get_type_abort(
713 handle->private_data, struct pipes_struct);
715 state->nread = read_from_internal_pipe(
716 p, (char *)data, len, &state->is_data_outstanding);
718 status = (state->nread >= 0)
719 ? NT_STATUS_OK : NT_STATUS_UNEXPECTED_IO_ERROR;
723 if (handle->type == FAKE_FILE_TYPE_NAMED_PIPE_PROXY) {
724 struct np_proxy_state *p = talloc_get_type_abort(
725 handle->private_data, struct np_proxy_state);
726 struct tevent_req *subreq;
728 np_ipc_readv_next_vector_init(&state->next_vector,
731 subreq = tstream_readv_pdu_queue_send(state,
735 np_ipc_readv_next_vector,
736 &state->next_vector);
737 if (subreq == NULL) {
738 status = NT_STATUS_NO_MEMORY;
741 tevent_req_set_callback(subreq, np_read_done, req);
745 status = NT_STATUS_INVALID_HANDLE;
747 if (NT_STATUS_IS_OK(status)) {
748 tevent_req_done(req);
750 tevent_req_nterror(req, status);
752 return tevent_req_post(req, ev);
755 static void np_read_done(struct tevent_req *subreq)
757 struct tevent_req *req = tevent_req_callback_data(
758 subreq, struct tevent_req);
759 struct np_read_state *state = tevent_req_data(
760 req, struct np_read_state);
764 ret = tstream_readv_pdu_queue_recv(subreq, &err);
767 tevent_req_nterror(req, map_nt_error_from_unix(err));
772 state->is_data_outstanding = (state->next_vector.remaining > 0);
774 tevent_req_done(req);
778 NTSTATUS np_read_recv(struct tevent_req *req, ssize_t *nread,
779 bool *is_data_outstanding)
781 struct np_read_state *state = tevent_req_data(
782 req, struct np_read_state);
785 if (tevent_req_is_nterror(req, &status)) {
789 DEBUG(10, ("Received %d bytes. There is %smore data outstanding\n",
790 (int)state->nread, state->is_data_outstanding?"":"no "));
792 *nread = state->nread;
793 *is_data_outstanding = state->is_data_outstanding;