root/source3/rpc_client/rpc_transport_np.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. rpc_transport_np_state_destructor
  2. rpc_np_write_send
  3. rpc_np_write_done
  4. rpc_np_write_recv
  5. rpc_np_read_send
  6. rpc_np_read_done
  7. rpc_np_read_recv
  8. rpc_np_trans_send
  9. rpc_np_trans_done
  10. rpc_np_trans_recv
  11. rpc_transport_np_init_send
  12. rpc_transport_np_init_pipe_open
  13. rpc_transport_np_init_recv
  14. rpc_transport_np_init
  15. rpc_pipe_np_smb_conn
  16. rpccli_close_np_fd

   1 /*
   2  *  Unix SMB/CIFS implementation.
   3  *  RPC client transport over named pipes
   4  *  Copyright (C) Volker Lendecke 2009
   5  *
   6  *  This program is free software; you can redistribute it and/or modify
   7  *  it under the terms of the GNU General Public License as published by
   8  *  the Free Software Foundation; either version 3 of the License, or
   9  *  (at your option) any later version.
  10  *
  11  *  This program is distributed in the hope that it will be useful,
  12  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
  13  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14  *  GNU General Public License for more details.
  15  *
  16  *  You should have received a copy of the GNU General Public License
  17  *  along with this program; if not, see <http://www.gnu.org/licenses/>.
  18  */
  19 
  20 #include "includes.h"
  21 
  22 #undef DBGC_CLASS
  23 #define DBGC_CLASS DBGC_RPC_CLI
  24 
  25 struct rpc_transport_np_state {
  26         struct cli_state *cli;
  27         const char *pipe_name;
  28         uint16_t fnum;
  29 };
  30 
  31 static int rpc_transport_np_state_destructor(struct rpc_transport_np_state *s)
     /* [<][>][^][v][top][bottom][index][help] */
  32 {
  33         bool ret;
  34         ret = cli_close(s->cli, s->fnum);
  35         if (!ret) {
  36                 DEBUG(1, ("rpc_transport_np_state_destructor: cli_close "
  37                           "failed on pipe %s. Error was %s\n", s->pipe_name,
  38                           cli_errstr(s->cli)));
  39         }
  40         DEBUG(10, ("rpc_pipe_destructor: closed %s\n", s->pipe_name));
  41         /*
  42          * We can't do much on failure
  43          */
  44         return 0;
  45 }
  46 
  47 struct rpc_np_write_state {
  48         size_t size;
  49         size_t written;
  50 };
  51 
  52 static void rpc_np_write_done(struct async_req *subreq);
  53 
  54 static struct async_req *rpc_np_write_send(TALLOC_CTX *mem_ctx,
     /* [<][>][^][v][top][bottom][index][help] */
  55                                            struct event_context *ev,
  56                                            const uint8_t *data, size_t size,
  57                                            void *priv)
  58 {
  59         struct rpc_transport_np_state *np_transport = talloc_get_type_abort(
  60                 priv, struct rpc_transport_np_state);
  61         struct async_req *result, *subreq;
  62         struct rpc_np_write_state *state;
  63 
  64         if (!async_req_setup(mem_ctx, &result, &state,
  65                              struct rpc_np_write_state)) {
  66                 return NULL;
  67         }
  68         state->size = size;
  69 
  70         subreq = cli_write_andx_send(mem_ctx, ev, np_transport->cli,
  71                                      np_transport->fnum,
  72                                      8, /* 8 means message mode. */
  73                                      data, 0, size);
  74         if (subreq == NULL) {
  75                 goto fail;
  76         }
  77         subreq->async.fn = rpc_np_write_done;
  78         subreq->async.priv = result;
  79         return result;
  80  fail:
  81         TALLOC_FREE(result);
  82         return NULL;
  83 }
  84 
  85 static void rpc_np_write_done(struct async_req *subreq)
     /* [<][>][^][v][top][bottom][index][help] */
  86 {
  87         struct async_req *req = talloc_get_type_abort(
  88                 subreq->async.priv, struct async_req);
  89         struct rpc_np_write_state *state = talloc_get_type_abort(
  90                 req->private_data, struct rpc_np_write_state);
  91         NTSTATUS status;
  92 
  93         status = cli_write_andx_recv(subreq, &state->written);
  94         TALLOC_FREE(subreq);
  95         if (!NT_STATUS_IS_OK(status)) {
  96                 async_req_nterror(req, status);
  97                 return;
  98         }
  99         async_req_done(req);
 100 }
 101 
 102 static NTSTATUS rpc_np_write_recv(struct async_req *req, ssize_t *pwritten)
     /* [<][>][^][v][top][bottom][index][help] */
 103 {
 104         struct rpc_np_write_state *state = talloc_get_type_abort(
 105                 req->private_data, struct rpc_np_write_state);
 106         NTSTATUS status;
 107 
 108         if (async_req_is_nterror(req, &status)) {
 109                 return status;
 110         }
 111         *pwritten = state->written;
 112         return NT_STATUS_OK;
 113 }
 114 
 115 struct rpc_np_read_state {
 116         uint8_t *data;
 117         size_t size;
 118         ssize_t received;
 119 };
 120 
 121 static void rpc_np_read_done(struct async_req *subreq);
 122 
 123 static struct async_req *rpc_np_read_send(TALLOC_CTX *mem_ctx,
     /* [<][>][^][v][top][bottom][index][help] */
 124                                           struct event_context *ev,
 125                                           uint8_t *data, size_t size,
 126                                           void *priv)
 127 {
 128         struct rpc_transport_np_state *np_transport = talloc_get_type_abort(
 129                 priv, struct rpc_transport_np_state);
 130         struct async_req *result, *subreq;
 131         struct rpc_np_read_state *state;
 132 
 133         if (!async_req_setup(mem_ctx, &result, &state,
 134                              struct rpc_np_read_state)) {
 135                 return NULL;
 136         }
 137         state->data = data;
 138         state->size = size;
 139 
 140         subreq = cli_read_andx_send(mem_ctx, ev, np_transport->cli,
 141                                     np_transport->fnum, 0, size);
 142         if (subreq == NULL) {
 143                 goto fail;
 144         }
 145         subreq->async.fn = rpc_np_read_done;
 146         subreq->async.priv = result;
 147         return result;
 148  fail:
 149         TALLOC_FREE(result);
 150         return NULL;
 151 }
 152 
 153 static void rpc_np_read_done(struct async_req *subreq)
     /* [<][>][^][v][top][bottom][index][help] */
 154 {
 155         struct async_req *req = talloc_get_type_abort(
 156                 subreq->async.priv, struct async_req);
 157         struct rpc_np_read_state *state = talloc_get_type_abort(
 158                 req->private_data, struct rpc_np_read_state);
 159         NTSTATUS status;
 160         uint8_t *rcvbuf;
 161 
 162         status = cli_read_andx_recv(subreq, &state->received, &rcvbuf);
 163         /*
 164          * We can't TALLOC_FREE(subreq) as usual here, as rcvbuf still is a
 165          * child of that.
 166          */
 167         if (NT_STATUS_EQUAL(status, NT_STATUS_BUFFER_TOO_SMALL)) {
 168                 status = NT_STATUS_OK;
 169         }
 170         if (!NT_STATUS_IS_OK(status)) {
 171                 TALLOC_FREE(subreq);
 172                 async_req_nterror(req, status);
 173                 return;
 174         }
 175 
 176         if (state->received > state->size) {
 177                 TALLOC_FREE(subreq);
 178                 async_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
 179                 return;
 180         }
 181 
 182         memcpy(state->data, rcvbuf, state->received);
 183         async_req_done(req);
 184 }
 185 
 186 static NTSTATUS rpc_np_read_recv(struct async_req *req, ssize_t *preceived)
     /* [<][>][^][v][top][bottom][index][help] */
 187 {
 188         struct rpc_np_read_state *state = talloc_get_type_abort(
 189                 req->private_data, struct rpc_np_read_state);
 190         NTSTATUS status;
 191 
 192         if (async_req_is_nterror(req, &status)) {
 193                 return status;
 194         }
 195         *preceived = state->received;
 196         return NT_STATUS_OK;
 197 }
 198 
 199 struct rpc_np_trans_state {
 200         uint16_t setup[2];
 201         uint8_t *rdata;
 202         uint32_t rdata_len;
 203 };
 204 
 205 static void rpc_np_trans_done(struct async_req *subreq);
 206 
 207 static struct async_req *rpc_np_trans_send(TALLOC_CTX *mem_ctx,
     /* [<][>][^][v][top][bottom][index][help] */
 208                                            struct event_context *ev,
 209                                            uint8_t *data, size_t data_len,
 210                                            uint32_t max_rdata_len,
 211                                            void *priv)
 212 {
 213         struct rpc_transport_np_state *np_transport = talloc_get_type_abort(
 214                 priv, struct rpc_transport_np_state);
 215         struct async_req *result, *subreq;
 216         struct rpc_np_trans_state *state;
 217 
 218         if (!async_req_setup(mem_ctx, &result, &state,
 219                              struct rpc_np_trans_state)) {
 220                 return NULL;
 221         }
 222 
 223         SSVAL(state->setup+0, 0, TRANSACT_DCERPCCMD);
 224         SSVAL(state->setup+1, 0, np_transport->fnum);
 225 
 226         subreq = cli_trans_send(
 227                 state, ev, np_transport->cli, SMBtrans,
 228                 "\\PIPE\\", 0, 0, 0, state->setup, 2, 0,
 229                 NULL, 0, 0, data, data_len, max_rdata_len);
 230         if (subreq == NULL) {
 231                 goto fail;
 232         }
 233         subreq->async.fn = rpc_np_trans_done;
 234         subreq->async.priv = result;
 235         return result;
 236 
 237  fail:
 238         TALLOC_FREE(result);
 239         return NULL;
 240 }
 241 
 242 static void rpc_np_trans_done(struct async_req *subreq)
     /* [<][>][^][v][top][bottom][index][help] */
 243 {
 244         struct async_req *req = talloc_get_type_abort(
 245                 subreq->async.priv, struct async_req);
 246         struct rpc_np_trans_state *state = talloc_get_type_abort(
 247                 req->private_data, struct rpc_np_trans_state);
 248         NTSTATUS status;
 249 
 250         status = cli_trans_recv(subreq, state, NULL, NULL, NULL, NULL,
 251                                 &state->rdata, &state->rdata_len);
 252         TALLOC_FREE(subreq);
 253         if (!NT_STATUS_IS_OK(status)) {
 254                 async_req_nterror(req, status);
 255                 return;
 256         }
 257         async_req_done(req);
 258 }
 259 
 260 static NTSTATUS rpc_np_trans_recv(struct async_req *req, TALLOC_CTX *mem_ctx,
     /* [<][>][^][v][top][bottom][index][help] */
 261                                   uint8_t **prdata, uint32_t *prdata_len)
 262 {
 263         struct rpc_np_trans_state *state = talloc_get_type_abort(
 264                 req->private_data, struct rpc_np_trans_state);
 265         NTSTATUS status;
 266 
 267         if (async_req_is_nterror(req, &status)) {
 268                 return status;
 269         }
 270         *prdata = talloc_move(mem_ctx, &state->rdata);
 271         *prdata_len = state->rdata_len;
 272         return NT_STATUS_OK;
 273 }
 274 
 275 struct rpc_transport_np_init_state {
 276         struct rpc_cli_transport *transport;
 277         struct rpc_transport_np_state *transport_np;
 278 };
 279 
 280 static void rpc_transport_np_init_pipe_open(struct async_req *subreq);
 281 
 282 struct async_req *rpc_transport_np_init_send(TALLOC_CTX *mem_ctx,
     /* [<][>][^][v][top][bottom][index][help] */
 283                                              struct event_context *ev,
 284                                              struct cli_state *cli,
 285                                              const struct ndr_syntax_id *abstract_syntax)
 286 {
 287         struct async_req *result, *subreq;
 288         struct rpc_transport_np_init_state *state;
 289 
 290         if (!async_req_setup(mem_ctx, &result, &state,
 291                              struct rpc_transport_np_init_state)) {
 292                 return NULL;
 293         }
 294 
 295         state->transport = talloc(state, struct rpc_cli_transport);
 296         if (state->transport == NULL) {
 297                 goto fail;
 298         }
 299         state->transport_np = talloc(state->transport,
 300                                      struct rpc_transport_np_state);
 301         if (state->transport_np == NULL) {
 302                 goto fail;
 303         }
 304         state->transport->priv = state->transport_np;
 305 
 306         state->transport_np->pipe_name = get_pipe_name_from_iface(
 307                 abstract_syntax);
 308         state->transport_np->cli = cli;
 309 
 310         subreq = cli_ntcreate_send(
 311                 state, ev, cli, state->transport_np->pipe_name, 0,
 312                 DESIRED_ACCESS_PIPE, 0, FILE_SHARE_READ|FILE_SHARE_WRITE,
 313                 FILE_OPEN, 0, 0);
 314         if (subreq == NULL) {
 315                 goto fail;
 316         }
 317         subreq->async.fn = rpc_transport_np_init_pipe_open;
 318         subreq->async.priv = result;
 319         return result;
 320 
 321  fail:
 322         TALLOC_FREE(result);
 323         return NULL;
 324 }
 325 
 326 static void rpc_transport_np_init_pipe_open(struct async_req *subreq)
     /* [<][>][^][v][top][bottom][index][help] */
 327 {
 328         struct async_req *req = talloc_get_type_abort(
 329                 subreq->async.priv, struct async_req);
 330         struct rpc_transport_np_init_state *state = talloc_get_type_abort(
 331                 req->private_data, struct rpc_transport_np_init_state);
 332         NTSTATUS status;
 333 
 334         status = cli_ntcreate_recv(subreq, &state->transport_np->fnum);
 335         TALLOC_FREE(subreq);
 336         if (!NT_STATUS_IS_OK(status)) {
 337                 async_req_nterror(req, status);
 338                 return;
 339         }
 340 
 341         talloc_set_destructor(state->transport_np,
 342                               rpc_transport_np_state_destructor);
 343         async_req_done(req);
 344 }
 345 
 346 NTSTATUS rpc_transport_np_init_recv(struct async_req *req,
     /* [<][>][^][v][top][bottom][index][help] */
 347                                     TALLOC_CTX *mem_ctx,
 348                                     struct rpc_cli_transport **presult)
 349 {
 350         struct rpc_transport_np_init_state *state = talloc_get_type_abort(
 351                 req->private_data, struct rpc_transport_np_init_state);
 352         NTSTATUS status;
 353 
 354         if (async_req_is_nterror(req, &status)) {
 355                 return status;
 356         }
 357 
 358         state->transport->write_send = rpc_np_write_send;
 359         state->transport->write_recv = rpc_np_write_recv;
 360         state->transport->read_send = rpc_np_read_send;
 361         state->transport->read_recv = rpc_np_read_recv;
 362         state->transport->trans_send = rpc_np_trans_send;
 363         state->transport->trans_recv = rpc_np_trans_recv;
 364 
 365         *presult = talloc_move(mem_ctx, &state->transport);
 366         return NT_STATUS_OK;
 367 }
 368 
 369 NTSTATUS rpc_transport_np_init(TALLOC_CTX *mem_ctx, struct cli_state *cli,
     /* [<][>][^][v][top][bottom][index][help] */
 370                                const struct ndr_syntax_id *abstract_syntax,
 371                                struct rpc_cli_transport **presult)
 372 {
 373         TALLOC_CTX *frame = talloc_stackframe();
 374         struct event_context *ev;
 375         struct async_req *req;
 376         NTSTATUS status;
 377 
 378         ev = event_context_init(frame);
 379         if (ev == NULL) {
 380                 status = NT_STATUS_NO_MEMORY;
 381                 goto fail;
 382         }
 383 
 384         req = rpc_transport_np_init_send(frame, ev, cli, abstract_syntax);
 385         if (req == NULL) {
 386                 status = NT_STATUS_NO_MEMORY;
 387                 goto fail;
 388         }
 389 
 390         while (req->state < ASYNC_REQ_DONE) {
 391                 event_loop_once(ev);
 392         }
 393 
 394         status = rpc_transport_np_init_recv(req, mem_ctx, presult);
 395  fail:
 396         TALLOC_FREE(frame);
 397         return status;
 398 }
 399 
 400 struct cli_state *rpc_pipe_np_smb_conn(struct rpc_pipe_client *p)
     /* [<][>][^][v][top][bottom][index][help] */
 401 {
 402         struct rpc_transport_np_state *state = talloc_get_type(
 403                 p->transport->priv, struct rpc_transport_np_state);
 404 
 405         if (state == NULL) {
 406                 return NULL;
 407         }
 408         return state->cli;
 409 }
 410 
 411 void rpccli_close_np_fd(struct rpc_pipe_client *p)
     /* [<][>][^][v][top][bottom][index][help] */
 412 {
 413         struct cli_state *cli = rpc_pipe_np_smb_conn(p);
 414         if (cli) {
 415                 if (cli->fd != -1) {
 416                         close(cli->fd);
 417                         cli->fd = -1;
 418                 }
 419         }
 420         return;
 421 }

/* [<][>][^][v][top][bottom][index][help] */