LCOV - code coverage report
Current view: top level - source3/rpc_server - srv_pipe_hnd.c (source / functions) Hit Total Coverage
Test: coverage report for master 2f515e9b Lines: 134 160 83.8 %
Date: 2024-04-21 15:09:00 Functions: 11 11 100.0 %

          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      334926 : bool fsp_is_np(struct files_struct *fsp)
      39             : {
      40        7118 :         enum FAKE_FILE_TYPE type;
      41             : 
      42      334926 :         if ((fsp == NULL) || (fsp->fake_file_handle == NULL)) {
      43           0 :                 return false;
      44             :         }
      45             : 
      46      334926 :         type = fsp->fake_file_handle->type;
      47             : 
      48      334926 :         return (type == FAKE_FILE_TYPE_NAMED_PIPE_PROXY);
      49             : }
      50             : 
      51       17050 : 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         620 :         struct fake_file_handle *handle;
      61       17050 :         struct npa_state *npa = NULL;
      62         620 :         int ret;
      63             : 
      64       17050 :         handle = talloc(mem_ctx, struct fake_file_handle);
      65       17050 :         if (handle == NULL) {
      66           0 :                 return NT_STATUS_NO_MEMORY;
      67             :         }
      68             : 
      69       17050 :         npa = npa_state_init(handle);
      70       17050 :         if (npa == NULL) {
      71           0 :                 TALLOC_FREE(handle);
      72           0 :                 return NT_STATUS_NO_MEMORY;
      73             :         }
      74       17050 :         *handle = (struct fake_file_handle) {
      75             :                 .type = FAKE_FILE_TYPE_NAMED_PIPE_PROXY,
      76             :                 .private_data = npa,
      77             :         };
      78             : 
      79       17050 :         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       17050 :         if (ret != 0) {
      91         151 :                 DBG_DEBUG("local_np_connect failed: %s\n",
      92             :                           strerror(ret));
      93         151 :                 TALLOC_FREE(handle);
      94         151 :                 return map_nt_error_from_unix(ret);
      95             :         }
      96             : 
      97       16899 :         *phandle = handle;
      98             : 
      99       16899 :         return NT_STATUS_OK;
     100             : }
     101             : 
     102        1418 : bool np_read_in_progress(struct fake_file_handle *handle)
     103             : {
     104        1418 :         if (handle->type == FAKE_FILE_TYPE_NAMED_PIPE_PROXY) {
     105           0 :                 struct npa_state *p =
     106        1418 :                         talloc_get_type_abort(handle->private_data,
     107             :                                               struct npa_state);
     108           0 :                 size_t read_count;
     109             : 
     110        1418 :                 read_count = tevent_queue_length(p->read_queue);
     111        1418 :                 if (read_count > 0) {
     112           0 :                         return true;
     113             :                 }
     114             : 
     115        1418 :                 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      325984 : 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        7070 :         struct tevent_req *req;
     135        7070 :         struct np_write_state *state;
     136      325984 :         struct npa_state *p = NULL;
     137      325984 :         struct tevent_req *subreq = NULL;
     138             : 
     139      325984 :         DBG_INFO("len: %zu\n", len);
     140      325984 :         dump_data(50, data, len);
     141             : 
     142      325984 :         req = tevent_req_create(mem_ctx, &state, struct np_write_state);
     143      325984 :         if (req == NULL) {
     144           0 :                 return NULL;
     145             :         }
     146             : 
     147      325984 :         if (handle->type != FAKE_FILE_TYPE_NAMED_PIPE_PROXY) {
     148           0 :                 tevent_req_nterror(req, NT_STATUS_INVALID_HANDLE);
     149           0 :                 return tevent_req_post(req, ev);
     150             :         }
     151             : 
     152      325984 :         if (len == 0) {
     153           0 :                 state->nwritten = 0;
     154           0 :                 tevent_req_done(req);
     155           0 :                 return tevent_req_post(req, ev);
     156             :         }
     157             : 
     158      325984 :         p = talloc_get_type_abort(handle->private_data, struct npa_state);
     159             : 
     160      325984 :         state->ev = ev;
     161      325984 :         state->p = p;
     162      325984 :         state->iov.iov_base = discard_const_p(void, data);
     163      325984 :         state->iov.iov_len = len;
     164             : 
     165      333054 :         subreq = tstream_writev_queue_send(
     166      325984 :                 state, ev, p->stream, p->write_queue, &state->iov, 1);
     167      325984 :         if (tevent_req_nomem(subreq, req)) {
     168           0 :                 return tevent_req_post(req, ev);
     169             :         }
     170      325984 :         tevent_req_set_callback(subreq, np_write_done, req);
     171      325984 :         return req;
     172             : }
     173             : 
     174      325984 : static void np_write_done(struct tevent_req *subreq)
     175             : {
     176      325984 :         struct tevent_req *req = tevent_req_callback_data(
     177             :                 subreq, struct tevent_req);
     178      325984 :         struct np_write_state *state = tevent_req_data(
     179             :                 req, struct np_write_state);
     180        7070 :         ssize_t received;
     181        7070 :         int err;
     182             : 
     183      325984 :         received = tstream_writev_queue_recv(subreq, &err);
     184      325984 :         if (received < 0) {
     185           0 :                 tevent_req_nterror(req, map_nt_error_from_unix(err));
     186           0 :                 return;
     187             :         }
     188      325984 :         state->nwritten = received;
     189      325984 :         tevent_req_done(req);
     190             : }
     191             : 
     192      325984 : NTSTATUS np_write_recv(struct tevent_req *req, ssize_t *pnwritten)
     193             : {
     194      325984 :         struct np_write_state *state = tevent_req_data(
     195             :                 req, struct np_write_state);
     196        7070 :         NTSTATUS status;
     197             : 
     198      325984 :         if (tevent_req_is_nterror(req, &status)) {
     199           0 :                 return status;
     200             :         }
     201      325984 :         *pnwritten = state->nwritten;
     202      325984 :         return NT_STATUS_OK;
     203             : }
     204             : 
     205             : struct np_ipc_readv_next_vector_state {
     206             :         uint8_t *buf;
     207             :         size_t len;
     208             :         off_t ofs;
     209             :         size_t remaining;
     210             : };
     211             : 
     212      326333 : static void np_ipc_readv_next_vector_init(struct np_ipc_readv_next_vector_state *s,
     213             :                                           uint8_t *buf, size_t len)
     214             : {
     215      333403 :         ZERO_STRUCTP(s);
     216             : 
     217      326333 :         s->buf = buf;
     218      326333 :         s->len = MIN(len, UINT16_MAX);
     219      319263 : }
     220             : 
     221      978969 : static int np_ipc_readv_next_vector(struct tstream_context *stream,
     222             :                                     void *private_data,
     223             :                                     TALLOC_CTX *mem_ctx,
     224             :                                     struct iovec **_vector,
     225             :                                     size_t *count)
     226             : {
     227      978969 :         struct np_ipc_readv_next_vector_state *state =
     228             :                 (struct np_ipc_readv_next_vector_state *)private_data;
     229       21204 :         struct iovec *vector;
     230       21204 :         ssize_t pending;
     231       21204 :         size_t wanted;
     232             : 
     233      978969 :         if (state->ofs == state->len) {
     234        4055 :                 *_vector = NULL;
     235        4055 :                 *count = 0;
     236        4055 :                 return 0;
     237             :         }
     238             : 
     239      974914 :         pending = tstream_pending_bytes(stream);
     240      974914 :         if (pending == -1) {
     241           0 :                 return -1;
     242             :         }
     243             : 
     244      974914 :         if (pending == 0 && state->ofs != 0) {
     245             :                 /* return a short read */
     246      322263 :                 *_vector = NULL;
     247      322263 :                 *count = 0;
     248      322263 :                 return 0;
     249             :         }
     250             : 
     251      652651 :         if (pending == 0) {
     252             :                 /* we want at least one byte and recheck again */
     253      319263 :                 wanted = 1;
     254             :         } else {
     255      326318 :                 size_t missing = state->len - state->ofs;
     256      326318 :                 if (pending > missing) {
     257             :                         /* there's more available */
     258           0 :                         state->remaining = pending - missing;
     259           0 :                         wanted = missing;
     260             :                 } else {
     261             :                         /* read what we can get and recheck in the next cycle */
     262      319251 :                         wanted = pending;
     263             :                 }
     264             :         }
     265             : 
     266      652651 :         vector = talloc_array(mem_ctx, struct iovec, 1);
     267      652651 :         if (!vector) {
     268           0 :                 return -1;
     269             :         }
     270             : 
     271      652651 :         vector[0].iov_base = state->buf + state->ofs;
     272      652651 :         vector[0].iov_len = wanted;
     273             : 
     274      652651 :         state->ofs += wanted;
     275             : 
     276      652651 :         *_vector = vector;
     277      652651 :         *count = 1;
     278      652651 :         return 0;
     279             : }
     280             : 
     281             : struct np_read_state {
     282             :         struct npa_state *p;
     283             :         struct np_ipc_readv_next_vector_state next_vector;
     284             : 
     285             :         ssize_t nread;
     286             :         bool is_data_outstanding;
     287             : };
     288             : 
     289             : static void np_read_done(struct tevent_req *subreq);
     290             : 
     291      326333 : struct tevent_req *np_read_send(TALLOC_CTX *mem_ctx, struct tevent_context *ev,
     292             :                                 struct fake_file_handle *handle,
     293             :                                 uint8_t *data, size_t len)
     294             : {
     295        7070 :         struct tevent_req *req;
     296        7070 :         struct np_read_state *state;
     297      326333 :         struct npa_state *p = NULL;
     298      326333 :         struct tevent_req *subreq = NULL;
     299             : 
     300      326333 :         req = tevent_req_create(mem_ctx, &state, struct np_read_state);
     301      326333 :         if (req == NULL) {
     302           0 :                 return NULL;
     303             :         }
     304             : 
     305      326333 :         if (handle->type != FAKE_FILE_TYPE_NAMED_PIPE_PROXY) {
     306           0 :                 tevent_req_nterror(req, NT_STATUS_INVALID_HANDLE);
     307           0 :                 return tevent_req_post(req, ev);
     308             :         }
     309             : 
     310      326333 :         p = talloc_get_type_abort(handle->private_data, struct npa_state);
     311             : 
     312      326333 :         np_ipc_readv_next_vector_init(&state->next_vector, data, len);
     313             : 
     314      333403 :         subreq = tstream_readv_pdu_queue_send(
     315             :                 state,
     316             :                 ev,
     317             :                 p->stream,
     318             :                 p->read_queue,
     319             :                 np_ipc_readv_next_vector,
     320      326333 :                 &state->next_vector);
     321      326333 :         if (tevent_req_nomem(subreq, req)) {
     322           0 :                 return tevent_req_post(req, ev);
     323             :         }
     324      326333 :         tevent_req_set_callback(subreq, np_read_done, req);
     325      326333 :         return req;
     326             : }
     327             : 
     328      326333 : static void np_read_done(struct tevent_req *subreq)
     329             : {
     330      326333 :         struct tevent_req *req = tevent_req_callback_data(
     331             :                 subreq, struct tevent_req);
     332      326333 :         struct np_read_state *state = tevent_req_data(
     333             :                 req, struct np_read_state);
     334        7070 :         ssize_t ret;
     335        7070 :         int err;
     336             : 
     337      326333 :         ret = tstream_readv_pdu_queue_recv(subreq, &err);
     338      326333 :         TALLOC_FREE(subreq);
     339      326333 :         if (ret == -1) {
     340          15 :                 tevent_req_nterror(req, map_nt_error_from_unix(err));
     341          15 :                 return;
     342             :         }
     343             : 
     344      326318 :         state->nread = ret;
     345      326318 :         state->is_data_outstanding = (state->next_vector.remaining > 0);
     346             : 
     347      326318 :         tevent_req_done(req);
     348      326318 :         return;
     349             : }
     350             : 
     351      326333 : NTSTATUS np_read_recv(struct tevent_req *req, ssize_t *nread,
     352             :                       bool *is_data_outstanding)
     353             : {
     354      326333 :         struct np_read_state *state = tevent_req_data(
     355             :                 req, struct np_read_state);
     356        7070 :         NTSTATUS status;
     357             : 
     358      326333 :         if (tevent_req_is_nterror(req, &status)) {
     359          15 :                 return status;
     360             :         }
     361             : 
     362      326318 :         DEBUG(10, ("Received %d bytes. There is %smore data outstanding\n",
     363             :                    (int)state->nread, state->is_data_outstanding?"":"no "));
     364             : 
     365      326318 :         *nread = state->nread;
     366      326318 :         *is_data_outstanding = state->is_data_outstanding;
     367      326318 :         return NT_STATUS_OK;
     368             : }

Generated by: LCOV version 1.14