LCOV - code coverage report
Current view: top level - source3/rpc_server - srv_pipe_hnd.c (source / functions) Hit Total Coverage
Test: coverage report for v4-17-test 1498b464 Lines: 108 151 71.5 %
Date: 2024-06-13 04:01:37 Functions: 10 11 90.9 %

          Line data    Source code
       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 "fake_file.h"
      24             : #include "rpc_dce.h"
      25             : #include "ntdomain.h"
      26             : #include "rpc_server/rpc_ncacn_np.h"
      27             : #include "rpc_server/srv_pipe_hnd.h"
      28             : #include "rpc_client/local_np.h"
      29             : #include "rpc_server/rpc_server.h"
      30             : #include "rpc_server/rpc_config.h"
      31             : #include "../lib/tsocket/tsocket.h"
      32             : #include "../lib/util/tevent_ntstatus.h"
      33             : #include "librpc/ndr/ndr_table.h"
      34             : 
      35             : #undef DBGC_CLASS
      36             : #define DBGC_CLASS DBGC_RPC_SRV
      37             : 
      38       89481 : bool fsp_is_np(struct files_struct *fsp)
      39             : {
      40             :         enum FAKE_FILE_TYPE type;
      41             : 
      42       89481 :         if ((fsp == NULL) || (fsp->fake_file_handle == NULL)) {
      43           0 :                 return false;
      44             :         }
      45             : 
      46       89481 :         type = fsp->fake_file_handle->type;
      47             : 
      48       89481 :         return (type == FAKE_FILE_TYPE_NAMED_PIPE_PROXY);
      49             : }
      50             : 
      51        3442 : NTSTATUS np_open(TALLOC_CTX *mem_ctx, const char *name,
      52             :                  const struct tsocket_address *remote_client_address,
      53             :                  const struct tsocket_address *local_server_address,
      54             :                  struct auth_session_info *session_info,
      55             :                  struct tevent_context *ev_ctx,
      56             :                  struct messaging_context *msg_ctx,
      57             :                  struct dcesrv_context *dce_ctx,
      58             :                  struct fake_file_handle **phandle)
      59             : {
      60             :         struct fake_file_handle *handle;
      61        3442 :         struct npa_state *npa = NULL;
      62             :         int ret;
      63             : 
      64        3442 :         handle = talloc(mem_ctx, struct fake_file_handle);
      65        3442 :         if (handle == NULL) {
      66           0 :                 return NT_STATUS_NO_MEMORY;
      67             :         }
      68             : 
      69        3442 :         npa = npa_state_init(handle);
      70        3442 :         if (npa == NULL) {
      71           0 :                 TALLOC_FREE(handle);
      72           0 :                 return NT_STATUS_NO_MEMORY;
      73             :         }
      74        3442 :         *handle = (struct fake_file_handle) {
      75             :                 .type = FAKE_FILE_TYPE_NAMED_PIPE_PROXY,
      76             :                 .private_data = npa,
      77             :         };
      78             : 
      79        3442 :         ret = local_np_connect(
      80             :                 name,
      81             :                 NCACN_NP,
      82             :                 NULL,
      83             :                 remote_client_address,
      84             :                 NULL,
      85             :                 local_server_address,
      86             :                 session_info,
      87             :                 false,
      88             :                 npa,
      89             :                 &npa->stream);
      90        3442 :         if (ret != 0) {
      91           5 :                 DBG_DEBUG("local_np_connect failed: %s\n",
      92             :                           strerror(ret));
      93           5 :                 TALLOC_FREE(handle);
      94           5 :                 return map_nt_error_from_unix(ret);
      95             :         }
      96             : 
      97        3437 :         *phandle = handle;
      98             : 
      99        3437 :         return NT_STATUS_OK;
     100             : }
     101             : 
     102           0 : bool np_read_in_progress(struct fake_file_handle *handle)
     103             : {
     104           0 :         if (handle->type == FAKE_FILE_TYPE_NAMED_PIPE_PROXY) {
     105           0 :                 struct npa_state *p =
     106           0 :                         talloc_get_type_abort(handle->private_data,
     107             :                                               struct npa_state);
     108             :                 size_t read_count;
     109             : 
     110           0 :                 read_count = tevent_queue_length(p->read_queue);
     111           0 :                 if (read_count > 0) {
     112           0 :                         return true;
     113             :                 }
     114             : 
     115           0 :                 return false;
     116             :         }
     117             : 
     118           0 :         return false;
     119             : }
     120             : 
     121             : struct np_write_state {
     122             :         struct tevent_context *ev;
     123             :         struct npa_state *p;
     124             :         struct iovec iov;
     125             :         ssize_t nwritten;
     126             : };
     127             : 
     128             : static void np_write_done(struct tevent_req *subreq);
     129             : 
     130       83472 : struct tevent_req *np_write_send(TALLOC_CTX *mem_ctx, struct tevent_context *ev,
     131             :                                  struct fake_file_handle *handle,
     132             :                                  const uint8_t *data, size_t len)
     133             : {
     134             :         struct tevent_req *req;
     135             :         struct np_write_state *state;
     136             :         NTSTATUS status;
     137             : 
     138       83472 :         DBG_INFO("len: %zu\n", len);
     139       83472 :         dump_data(50, data, len);
     140             : 
     141       83472 :         req = tevent_req_create(mem_ctx, &state, struct np_write_state);
     142       83472 :         if (req == NULL) {
     143           0 :                 return NULL;
     144             :         }
     145             : 
     146       83472 :         if (len == 0) {
     147           0 :                 state->nwritten = 0;
     148           0 :                 status = NT_STATUS_OK;
     149           0 :                 goto post_status;
     150             :         }
     151             : 
     152       83472 :         if (handle->type == FAKE_FILE_TYPE_NAMED_PIPE_PROXY) {
     153       83472 :                 struct npa_state *p = talloc_get_type_abort(
     154             :                         handle->private_data, struct npa_state);
     155             :                 struct tevent_req *subreq;
     156             : 
     157       83472 :                 state->ev = ev;
     158       83472 :                 state->p = p;
     159       83472 :                 state->iov.iov_base = discard_const_p(void, data);
     160       83472 :                 state->iov.iov_len = len;
     161             : 
     162       83472 :                 subreq = tstream_writev_queue_send(state, ev,
     163             :                                                    p->stream,
     164             :                                                    p->write_queue,
     165       83472 :                                                    &state->iov, 1);
     166       83472 :                 if (subreq == NULL) {
     167           0 :                         goto fail;
     168             :                 }
     169       83472 :                 tevent_req_set_callback(subreq, np_write_done, req);
     170       83472 :                 return req;
     171             :         }
     172             : 
     173           0 :         status = NT_STATUS_INVALID_HANDLE;
     174           0 :  post_status:
     175           0 :         if (NT_STATUS_IS_OK(status)) {
     176           0 :                 tevent_req_done(req);
     177             :         } else {
     178           0 :                 tevent_req_nterror(req, status);
     179             :         }
     180           0 :         return tevent_req_post(req, ev);
     181           0 :  fail:
     182           0 :         TALLOC_FREE(req);
     183           0 :         return NULL;
     184             : }
     185             : 
     186       83472 : static void np_write_done(struct tevent_req *subreq)
     187             : {
     188       83472 :         struct tevent_req *req = tevent_req_callback_data(
     189             :                 subreq, struct tevent_req);
     190       83472 :         struct np_write_state *state = tevent_req_data(
     191             :                 req, struct np_write_state);
     192             :         ssize_t received;
     193             :         int err;
     194             : 
     195       83472 :         received = tstream_writev_queue_recv(subreq, &err);
     196       83472 :         if (received < 0) {
     197           0 :                 tevent_req_nterror(req, map_nt_error_from_unix(err));
     198           0 :                 return;
     199             :         }
     200       83472 :         state->nwritten = received;
     201       83472 :         tevent_req_done(req);
     202             : }
     203             : 
     204       83472 : NTSTATUS np_write_recv(struct tevent_req *req, ssize_t *pnwritten)
     205             : {
     206       83472 :         struct np_write_state *state = tevent_req_data(
     207             :                 req, struct np_write_state);
     208             :         NTSTATUS status;
     209             : 
     210       83472 :         if (tevent_req_is_nterror(req, &status)) {
     211           0 :                 return status;
     212             :         }
     213       83472 :         *pnwritten = state->nwritten;
     214       83472 :         return NT_STATUS_OK;
     215             : }
     216             : 
     217             : struct np_ipc_readv_next_vector_state {
     218             :         uint8_t *buf;
     219             :         size_t len;
     220             :         off_t ofs;
     221             :         size_t remaining;
     222             : };
     223             : 
     224       83580 : static void np_ipc_readv_next_vector_init(struct np_ipc_readv_next_vector_state *s,
     225             :                                           uint8_t *buf, size_t len)
     226             : {
     227       83580 :         ZERO_STRUCTP(s);
     228             : 
     229       83580 :         s->buf = buf;
     230       83580 :         s->len = MIN(len, UINT16_MAX);
     231       83580 : }
     232             : 
     233      250728 : static int np_ipc_readv_next_vector(struct tstream_context *stream,
     234             :                                     void *private_data,
     235             :                                     TALLOC_CTX *mem_ctx,
     236             :                                     struct iovec **_vector,
     237             :                                     size_t *count)
     238             : {
     239      250728 :         struct np_ipc_readv_next_vector_state *state =
     240             :                 (struct np_ipc_readv_next_vector_state *)private_data;
     241             :         struct iovec *vector;
     242             :         ssize_t pending;
     243             :         size_t wanted;
     244             : 
     245      250728 :         if (state->ofs == state->len) {
     246        2978 :                 *_vector = NULL;
     247        2978 :                 *count = 0;
     248        2978 :                 return 0;
     249             :         }
     250             : 
     251      247750 :         pending = tstream_pending_bytes(stream);
     252      247750 :         if (pending == -1) {
     253           0 :                 return -1;
     254             :         }
     255             : 
     256      247750 :         if (pending == 0 && state->ofs != 0) {
     257             :                 /* return a short read */
     258       80596 :                 *_vector = NULL;
     259       80596 :                 *count = 0;
     260       80596 :                 return 0;
     261             :         }
     262             : 
     263      167154 :         if (pending == 0) {
     264             :                 /* we want at least one byte and recheck again */
     265       83580 :                 wanted = 1;
     266             :         } else {
     267       83574 :                 size_t missing = state->len - state->ofs;
     268       83574 :                 if (pending > missing) {
     269             :                         /* there's more available */
     270           0 :                         state->remaining = pending - missing;
     271           0 :                         wanted = missing;
     272             :                 } else {
     273             :                         /* read what we can get and recheck in the next cycle */
     274       83574 :                         wanted = pending;
     275             :                 }
     276             :         }
     277             : 
     278      167154 :         vector = talloc_array(mem_ctx, struct iovec, 1);
     279      167154 :         if (!vector) {
     280           0 :                 return -1;
     281             :         }
     282             : 
     283      167154 :         vector[0].iov_base = state->buf + state->ofs;
     284      167154 :         vector[0].iov_len = wanted;
     285             : 
     286      167154 :         state->ofs += wanted;
     287             : 
     288      167154 :         *_vector = vector;
     289      167154 :         *count = 1;
     290      167154 :         return 0;
     291             : }
     292             : 
     293             : struct np_read_state {
     294             :         struct npa_state *p;
     295             :         struct np_ipc_readv_next_vector_state next_vector;
     296             : 
     297             :         ssize_t nread;
     298             :         bool is_data_outstanding;
     299             : };
     300             : 
     301             : static void np_read_done(struct tevent_req *subreq);
     302             : 
     303       83580 : struct tevent_req *np_read_send(TALLOC_CTX *mem_ctx, struct tevent_context *ev,
     304             :                                 struct fake_file_handle *handle,
     305             :                                 uint8_t *data, size_t len)
     306             : {
     307             :         struct tevent_req *req;
     308             :         struct np_read_state *state;
     309             :         NTSTATUS status;
     310             : 
     311       83580 :         req = tevent_req_create(mem_ctx, &state, struct np_read_state);
     312       83580 :         if (req == NULL) {
     313           0 :                 return NULL;
     314             :         }
     315             : 
     316       83580 :         if (handle->type == FAKE_FILE_TYPE_NAMED_PIPE_PROXY) {
     317       83580 :                 struct npa_state *p = talloc_get_type_abort(
     318             :                         handle->private_data, struct npa_state);
     319             :                 struct tevent_req *subreq;
     320             : 
     321       83580 :                 np_ipc_readv_next_vector_init(&state->next_vector,
     322             :                                               data, len);
     323             : 
     324       83580 :                 subreq = tstream_readv_pdu_queue_send(state,
     325             :                                                       ev,
     326             :                                                       p->stream,
     327             :                                                       p->read_queue,
     328             :                                                       np_ipc_readv_next_vector,
     329       83580 :                                                       &state->next_vector);
     330       83580 :                 if (subreq == NULL) {
     331           0 :                         status = NT_STATUS_NO_MEMORY;
     332           0 :                         goto post_status;
     333             :                 }
     334       83580 :                 tevent_req_set_callback(subreq, np_read_done, req);
     335       83580 :                 return req;
     336             :         }
     337             : 
     338           0 :         status = NT_STATUS_INVALID_HANDLE;
     339           0 :  post_status:
     340           0 :         if (NT_STATUS_IS_OK(status)) {
     341           0 :                 tevent_req_done(req);
     342             :         } else {
     343           0 :                 tevent_req_nterror(req, status);
     344             :         }
     345           0 :         return tevent_req_post(req, ev);
     346             : }
     347             : 
     348       83580 : static void np_read_done(struct tevent_req *subreq)
     349             : {
     350       83580 :         struct tevent_req *req = tevent_req_callback_data(
     351             :                 subreq, struct tevent_req);
     352       83580 :         struct np_read_state *state = tevent_req_data(
     353             :                 req, struct np_read_state);
     354             :         ssize_t ret;
     355             :         int err;
     356             : 
     357       83580 :         ret = tstream_readv_pdu_queue_recv(subreq, &err);
     358       83580 :         TALLOC_FREE(subreq);
     359       83580 :         if (ret == -1) {
     360           6 :                 tevent_req_nterror(req, map_nt_error_from_unix(err));
     361           6 :                 return;
     362             :         }
     363             : 
     364       83574 :         state->nread = ret;
     365       83574 :         state->is_data_outstanding = (state->next_vector.remaining > 0);
     366             : 
     367       83574 :         tevent_req_done(req);
     368       83574 :         return;
     369             : }
     370             : 
     371       83580 : NTSTATUS np_read_recv(struct tevent_req *req, ssize_t *nread,
     372             :                       bool *is_data_outstanding)
     373             : {
     374       83580 :         struct np_read_state *state = tevent_req_data(
     375             :                 req, struct np_read_state);
     376             :         NTSTATUS status;
     377             : 
     378       83580 :         if (tevent_req_is_nterror(req, &status)) {
     379           6 :                 return status;
     380             :         }
     381             : 
     382       83574 :         DEBUG(10, ("Received %d bytes. There is %smore data outstanding\n",
     383             :                    (int)state->nread, state->is_data_outstanding?"":"no "));
     384             : 
     385       83574 :         *nread = state->nread;
     386       83574 :         *is_data_outstanding = state->is_data_outstanding;
     387       83574 :         return NT_STATUS_OK;
     388             : }

Generated by: LCOV version 1.13