LCOV - code coverage report
Current view: top level - source4/librpc/rpc - dcerpc.c (source / functions) Hit Total Coverage
Test: coverage report for master 2b515b7d Lines: 912 1224 74.5 %
Date: 2024-02-28 12:06:22 Functions: 55 63 87.3 %

          Line data    Source code
       1             : /* 
       2             :    Unix SMB/CIFS implementation.
       3             :    raw dcerpc operations
       4             : 
       5             :    Copyright (C) Tim Potter 2003
       6             :    Copyright (C) Andrew Tridgell 2003-2005
       7             :    Copyright (C) Jelmer Vernooij 2004-2005
       8             :    
       9             :    This program is free software; you can redistribute it and/or modify
      10             :    it under the terms of the GNU General Public License as published by
      11             :    the Free Software Foundation; either version 3 of the License, or
      12             :    (at your option) any later version.
      13             :    
      14             :    This program is distributed in the hope that it will be useful,
      15             :    but WITHOUT ANY WARRANTY; without even the implied warranty of
      16             :    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      17             :    GNU General Public License for more details.
      18             :    
      19             :    You should have received a copy of the GNU General Public License
      20             :    along with this program.  If not, see <http://www.gnu.org/licenses/>.
      21             : */
      22             : 
      23             : #include "includes.h"
      24             : #include "system/filesys.h"
      25             : #include "../lib/util/dlinklist.h"
      26             : #include "lib/events/events.h"
      27             : #include "librpc/rpc/dcerpc.h"
      28             : #include "librpc/rpc/dcerpc_proto.h"
      29             : #include "librpc/rpc/dcerpc_util.h"
      30             : #include "librpc/rpc/dcerpc_pkt_auth.h"
      31             : #include "librpc/gen_ndr/ndr_misc.h"
      32             : #include "librpc/gen_ndr/ndr_dcerpc.h"
      33             : #include "auth/gensec/gensec.h"
      34             : #include "param/param.h"
      35             : #include "lib/util/tevent_ntstatus.h"
      36             : #include "librpc/rpc/rpc_common.h"
      37             : #include "lib/tsocket/tsocket.h"
      38             : #include "libcli/smb/tstream_smbXcli_np.h"
      39             : 
      40             : 
      41             : enum rpc_request_state {
      42             :         RPC_REQUEST_QUEUED,
      43             :         RPC_REQUEST_PENDING,
      44             :         RPC_REQUEST_DONE
      45             : };
      46             : 
      47             : /*
      48             :   handle for an async dcerpc request
      49             : */
      50             : struct rpc_request {
      51             :         struct rpc_request *next, *prev;
      52             :         struct dcerpc_pipe *p;
      53             :         NTSTATUS status;
      54             :         uint32_t call_id;
      55             :         enum rpc_request_state state;
      56             :         DATA_BLOB payload;
      57             :         uint32_t flags;
      58             :         uint32_t fault_code;
      59             : 
      60             :         /* this is used to distinguish bind and alter_context requests
      61             :            from normal requests */
      62             :         void (*recv_handler)(struct rpc_request *conn, 
      63             :                              DATA_BLOB *blob, struct ncacn_packet *pkt);
      64             : 
      65             :         const struct GUID *object;
      66             :         uint16_t opnum;
      67             :         DATA_BLOB request_data;
      68             :         bool ignore_timeout;
      69             :         bool wait_for_sync;
      70             :         bool verify_bitmask1;
      71             :         bool verify_pcontext;
      72             : 
      73             :         struct {
      74             :                 void (*callback)(struct rpc_request *);
      75             :                 void *private_data;
      76             :         } async;
      77             : };
      78             : 
      79       10637 : _PUBLIC_ NTSTATUS dcerpc_init(void)
      80             : {
      81       10637 :         return gensec_init();
      82             : }
      83             : 
      84             : static void dcerpc_connection_dead(struct dcecli_connection *conn, NTSTATUS status);
      85             : static void dcerpc_schedule_io_trigger(struct dcecli_connection *c);
      86             : 
      87             : static struct rpc_request *dcerpc_request_send(TALLOC_CTX *mem_ctx,
      88             :                                                struct dcerpc_pipe *p,
      89             :                                                const struct GUID *object,
      90             :                                                uint16_t opnum,
      91             :                                                DATA_BLOB *stub_data);
      92             : static NTSTATUS dcerpc_request_recv(struct rpc_request *req,
      93             :                                     TALLOC_CTX *mem_ctx,
      94             :                                     DATA_BLOB *stub_data);
      95             : static NTSTATUS dcerpc_ndr_validate_in(struct dcecli_connection *c,
      96             :                                        TALLOC_CTX *mem_ctx,
      97             :                                        DATA_BLOB blob,
      98             :                                        size_t struct_size,
      99             :                                        ndr_push_flags_fn_t ndr_push,
     100             :                                        ndr_pull_flags_fn_t ndr_pull);
     101             : static NTSTATUS dcerpc_ndr_validate_out(struct dcecli_connection *c,
     102             :                                         struct ndr_pull *pull_in,
     103             :                                         void *struct_ptr,
     104             :                                         size_t struct_size,
     105             :                                         ndr_push_flags_fn_t ndr_push,
     106             :                                         ndr_pull_flags_fn_t ndr_pull,
     107             :                                         ndr_print_function_t ndr_print);
     108             : static NTSTATUS dcerpc_shutdown_pipe(struct dcecli_connection *p, NTSTATUS status);
     109             : static NTSTATUS dcerpc_send_request(struct dcecli_connection *p, DATA_BLOB *data,
     110             :                              bool trigger_read);
     111             : static NTSTATUS dcerpc_send_read(struct dcecli_connection *p);
     112             : 
     113             : /* destroy a dcerpc connection */
     114       31194 : static int dcerpc_connection_destructor(struct dcecli_connection *conn)
     115             : {
     116       31194 :         if (conn->dead) {
     117           0 :                 conn->free_skipped = true;
     118           0 :                 return -1;
     119             :         }
     120       31194 :         dcerpc_connection_dead(conn, NT_STATUS_LOCAL_DISCONNECT);
     121       31194 :         return 0;
     122             : }
     123             : 
     124             : 
     125             : /* initialise a dcerpc connection. 
     126             :    the event context is optional
     127             : */
     128       31243 : static struct dcecli_connection *dcerpc_connection_init(TALLOC_CTX *mem_ctx, 
     129             :                                                  struct tevent_context *ev)
     130             : {
     131         870 :         struct dcecli_connection *c;
     132             : 
     133       31243 :         c = talloc_zero(mem_ctx, struct dcecli_connection);
     134       31243 :         if (!c) {
     135           0 :                 return NULL;
     136             :         }
     137             : 
     138       31243 :         c->event_ctx = ev;
     139             : 
     140       31243 :         if (c->event_ctx == NULL) {
     141           0 :                 talloc_free(c);
     142           0 :                 return NULL;
     143             :         }
     144             : 
     145       31243 :         c->call_id = 1;
     146       31243 :         c->security_state.auth_type = DCERPC_AUTH_TYPE_NONE;
     147       31243 :         c->security_state.auth_level = DCERPC_AUTH_LEVEL_NONE;
     148       31243 :         c->security_state.auth_context_id = 0;
     149       31243 :         c->security_state.session_key = dcecli_generic_session_key;
     150       31243 :         c->security_state.generic_state = NULL;
     151       31243 :         c->flags = 0;
     152             :         /*
     153             :          * Windows uses 5840 for ncacn_ip_tcp,
     154             :          * so we also use it (for every transport)
     155             :          * by default. But we give the transport
     156             :          * the chance to overwrite it.
     157             :          */
     158       31243 :         c->srv_max_xmit_frag = 5840;
     159       31243 :         c->srv_max_recv_frag = 5840;
     160       31243 :         c->max_total_response_size = DCERPC_NCACN_RESPONSE_DEFAULT_MAX_SIZE;
     161       31243 :         c->pending = NULL;
     162             : 
     163       31243 :         c->io_trigger = tevent_create_immediate(c);
     164       31243 :         if (c->io_trigger == NULL) {
     165           0 :                 talloc_free(c);
     166           0 :                 return NULL;
     167             :         }
     168             : 
     169       31243 :         talloc_set_destructor(c, dcerpc_connection_destructor);
     170             : 
     171       31243 :         return c;
     172             : }
     173             : 
     174             : struct dcerpc_bh_state {
     175             :         struct dcerpc_pipe *p;
     176             : };
     177             : 
     178      302152 : static bool dcerpc_bh_is_connected(struct dcerpc_binding_handle *h)
     179             : {
     180      302152 :         struct dcerpc_bh_state *hs = dcerpc_binding_handle_data(h,
     181             :                                      struct dcerpc_bh_state);
     182             : 
     183      302152 :         if (!hs->p) {
     184           0 :                 return false;
     185             :         }
     186             : 
     187      302152 :         if (!hs->p->conn) {
     188           0 :                 return false;
     189             :         }
     190             : 
     191      302152 :         if (hs->p->conn->dead) {
     192          34 :                 return false;
     193             :         }
     194             : 
     195      294983 :         return true;
     196             : }
     197             : 
     198         974 : static uint32_t dcerpc_bh_set_timeout(struct dcerpc_binding_handle *h,
     199             :                                       uint32_t timeout)
     200             : {
     201         974 :         struct dcerpc_bh_state *hs = dcerpc_binding_handle_data(h,
     202             :                                      struct dcerpc_bh_state);
     203           0 :         uint32_t old;
     204             : 
     205         974 :         if (!hs->p) {
     206           0 :                 return DCERPC_REQUEST_TIMEOUT;
     207             :         }
     208             : 
     209         974 :         old = hs->p->request_timeout;
     210         974 :         hs->p->request_timeout = timeout;
     211             : 
     212         974 :         return old;
     213             : }
     214             : 
     215        1617 : static void dcerpc_bh_auth_info(struct dcerpc_binding_handle *h,
     216             :                                 enum dcerpc_AuthType *auth_type,
     217             :                                 enum dcerpc_AuthLevel *auth_level)
     218             : {
     219        1617 :         struct dcerpc_bh_state *hs = dcerpc_binding_handle_data(h,
     220             :                                      struct dcerpc_bh_state);
     221             : 
     222        1617 :         if (hs->p == NULL) {
     223           0 :                 return;
     224             :         }
     225             : 
     226        1617 :         if (hs->p->conn == NULL) {
     227           0 :                 return;
     228             :         }
     229             : 
     230        1617 :         *auth_type = hs->p->conn->security_state.auth_type;
     231        1617 :         *auth_level = hs->p->conn->security_state.auth_level;
     232             : }
     233             : 
     234             : struct dcerpc_bh_raw_call_state {
     235             :         struct tevent_context *ev;
     236             :         struct dcerpc_binding_handle *h;
     237             :         DATA_BLOB in_data;
     238             :         DATA_BLOB out_data;
     239             :         uint32_t out_flags;
     240             : };
     241             : 
     242             : static void dcerpc_bh_raw_call_done(struct rpc_request *subreq);
     243             : 
     244      297239 : static struct tevent_req *dcerpc_bh_raw_call_send(TALLOC_CTX *mem_ctx,
     245             :                                                   struct tevent_context *ev,
     246             :                                                   struct dcerpc_binding_handle *h,
     247             :                                                   const struct GUID *object,
     248             :                                                   uint32_t opnum,
     249             :                                                   uint32_t in_flags,
     250             :                                                   const uint8_t *in_data,
     251             :                                                   size_t in_length)
     252             : {
     253      297239 :         struct dcerpc_bh_state *hs = dcerpc_binding_handle_data(h,
     254             :                                      struct dcerpc_bh_state);
     255        7135 :         struct tevent_req *req;
     256        7135 :         struct dcerpc_bh_raw_call_state *state;
     257        7135 :         bool ok;
     258        7135 :         struct rpc_request *subreq;
     259             : 
     260      297239 :         req = tevent_req_create(mem_ctx, &state,
     261             :                                 struct dcerpc_bh_raw_call_state);
     262      297239 :         if (req == NULL) {
     263           0 :                 return NULL;
     264             :         }
     265      297239 :         state->ev = ev;
     266      297239 :         state->h = h;
     267      297239 :         state->in_data.data = discard_const_p(uint8_t, in_data);
     268      297239 :         state->in_data.length = in_length;
     269             : 
     270      297239 :         ok = dcerpc_bh_is_connected(h);
     271      297239 :         if (!ok) {
     272           0 :                 tevent_req_nterror(req, NT_STATUS_CONNECTION_DISCONNECTED);
     273           0 :                 return tevent_req_post(req, ev);
     274             :         }
     275             : 
     276      304374 :         subreq = dcerpc_request_send(state,
     277             :                                      hs->p,
     278             :                                      object,
     279             :                                      opnum,
     280      297239 :                                      &state->in_data);
     281      297239 :         if (tevent_req_nomem(subreq, req)) {
     282           0 :                 return tevent_req_post(req, ev);
     283             :         }
     284      297239 :         subreq->async.callback = dcerpc_bh_raw_call_done;
     285      297239 :         subreq->async.private_data = req;
     286             : 
     287      297239 :         return req;
     288             : }
     289             : 
     290      297239 : static void dcerpc_bh_raw_call_done(struct rpc_request *subreq)
     291             : {
     292        7135 :         struct tevent_req *req =
     293      297239 :                 talloc_get_type_abort(subreq->async.private_data,
     294             :                 struct tevent_req);
     295        7135 :         struct dcerpc_bh_raw_call_state *state =
     296      297239 :                 tevent_req_data(req,
     297             :                 struct dcerpc_bh_raw_call_state);
     298        7135 :         NTSTATUS status;
     299        7135 :         uint32_t fault_code;
     300             : 
     301      297239 :         state->out_flags = 0;
     302      297239 :         if (subreq->flags & DCERPC_PULL_BIGENDIAN) {
     303           0 :                 state->out_flags |= LIBNDR_FLAG_BIGENDIAN;
     304             :         }
     305             : 
     306      297239 :         fault_code = subreq->fault_code;
     307             : 
     308      297239 :         status = dcerpc_request_recv(subreq, state, &state->out_data);
     309      297239 :         if (NT_STATUS_EQUAL(status, NT_STATUS_NET_WRITE_FAULT)) {
     310        2558 :                 status = dcerpc_fault_to_nt_status(fault_code);
     311             :         }
     312             : 
     313             :         /*
     314             :          * We trigger the callback in the next event run
     315             :          * because the code in this file might trigger
     316             :          * multiple request callbacks from within a single
     317             :          * while loop.
     318             :          *
     319             :          * In order to avoid segfaults from within
     320             :          * dcerpc_connection_dead() we call
     321             :          * tevent_req_defer_callback().
     322             :          */
     323      297239 :         tevent_req_defer_callback(req, state->ev);
     324             : 
     325      297239 :         if (!NT_STATUS_IS_OK(status)) {
     326        2601 :                 tevent_req_nterror(req, status);
     327        2601 :                 return;
     328             :         }
     329             : 
     330      294638 :         tevent_req_done(req);
     331             : }
     332             : 
     333      297239 : static NTSTATUS dcerpc_bh_raw_call_recv(struct tevent_req *req,
     334             :                                         TALLOC_CTX *mem_ctx,
     335             :                                         uint8_t **out_data,
     336             :                                         size_t *out_length,
     337             :                                         uint32_t *out_flags)
     338             : {
     339        7135 :         struct dcerpc_bh_raw_call_state *state =
     340      297239 :                 tevent_req_data(req,
     341             :                 struct dcerpc_bh_raw_call_state);
     342        7135 :         NTSTATUS status;
     343             : 
     344      297239 :         if (tevent_req_is_nterror(req, &status)) {
     345        2601 :                 tevent_req_received(req);
     346        2601 :                 return status;
     347             :         }
     348             : 
     349      294638 :         *out_data = talloc_move(mem_ctx, &state->out_data.data);
     350      294638 :         *out_length = state->out_data.length;
     351      294638 :         *out_flags = state->out_flags;
     352      294638 :         tevent_req_received(req);
     353      294638 :         return NT_STATUS_OK;
     354             : }
     355             : 
     356             : struct dcerpc_bh_disconnect_state {
     357             :         uint8_t _dummy;
     358             : };
     359             : 
     360           0 : static struct tevent_req *dcerpc_bh_disconnect_send(TALLOC_CTX *mem_ctx,
     361             :                                                 struct tevent_context *ev,
     362             :                                                 struct dcerpc_binding_handle *h)
     363             : {
     364           0 :         struct dcerpc_bh_state *hs = dcerpc_binding_handle_data(h,
     365             :                                      struct dcerpc_bh_state);
     366           0 :         struct tevent_req *req;
     367           0 :         struct dcerpc_bh_disconnect_state *state;
     368           0 :         bool ok;
     369             : 
     370           0 :         req = tevent_req_create(mem_ctx, &state,
     371             :                                 struct dcerpc_bh_disconnect_state);
     372           0 :         if (req == NULL) {
     373           0 :                 return NULL;
     374             :         }
     375             : 
     376           0 :         ok = dcerpc_bh_is_connected(h);
     377           0 :         if (!ok) {
     378           0 :                 tevent_req_nterror(req, NT_STATUS_CONNECTION_DISCONNECTED);
     379           0 :                 return tevent_req_post(req, ev);
     380             :         }
     381             : 
     382             :         /* TODO: do a real disconnect ... */
     383           0 :         hs->p = NULL;
     384             : 
     385           0 :         tevent_req_done(req);
     386           0 :         return tevent_req_post(req, ev);
     387             : }
     388             : 
     389           0 : static NTSTATUS dcerpc_bh_disconnect_recv(struct tevent_req *req)
     390             : {
     391           0 :         NTSTATUS status;
     392             : 
     393           0 :         if (tevent_req_is_nterror(req, &status)) {
     394           0 :                 tevent_req_received(req);
     395           0 :                 return status;
     396             :         }
     397             : 
     398           0 :         tevent_req_received(req);
     399           0 :         return NT_STATUS_OK;
     400             : }
     401             : 
     402      297322 : static bool dcerpc_bh_push_bigendian(struct dcerpc_binding_handle *h)
     403             : {
     404      297322 :         struct dcerpc_bh_state *hs = dcerpc_binding_handle_data(h,
     405             :                                      struct dcerpc_bh_state);
     406             : 
     407      297322 :         if (hs->p->conn->flags & DCERPC_PUSH_BIGENDIAN) {
     408       28199 :                 return true;
     409             :         }
     410             : 
     411      263573 :         return false;
     412             : }
     413             : 
     414      297322 : static bool dcerpc_bh_ref_alloc(struct dcerpc_binding_handle *h)
     415             : {
     416      297322 :         struct dcerpc_bh_state *hs = dcerpc_binding_handle_data(h,
     417             :                                      struct dcerpc_bh_state);
     418             : 
     419      297322 :         if (hs->p->conn->flags & DCERPC_NDR_REF_ALLOC) {
     420       23616 :                 return true;
     421             :         }
     422             : 
     423      266581 :         return false;
     424             : }
     425             : 
     426      297322 : static bool dcerpc_bh_use_ndr64(struct dcerpc_binding_handle *h)
     427             : {
     428      297322 :         struct dcerpc_bh_state *hs = dcerpc_binding_handle_data(h,
     429             :                                      struct dcerpc_bh_state);
     430             : 
     431      297322 :         if (hs->p->conn->flags & DCERPC_NDR64) {
     432           0 :                 return true;
     433             :         }
     434             : 
     435      290187 :         return false;
     436             : }
     437             : 
     438      591953 : static void dcerpc_bh_do_ndr_print(struct dcerpc_binding_handle *h,
     439             :                                    ndr_flags_type ndr_flags,
     440             :                                    const void *_struct_ptr,
     441             :                                    const struct ndr_interface_call *call)
     442             : {
     443      591953 :         struct dcerpc_bh_state *hs = dcerpc_binding_handle_data(h,
     444             :                                      struct dcerpc_bh_state);
     445      591953 :         void *struct_ptr = discard_const(_struct_ptr);
     446      591953 :         bool print_in = false;
     447      591953 :         bool print_out = false;
     448             : 
     449      591953 :         if (hs->p->conn->flags & DCERPC_DEBUG_PRINT_IN) {
     450           0 :                 print_in = true;
     451             :         }
     452             : 
     453      591953 :         if (hs->p->conn->flags & DCERPC_DEBUG_PRINT_OUT) {
     454           0 :                 print_out = true;
     455             :         }
     456             : 
     457      591953 :         if (DEBUGLEVEL >= 11) {
     458           0 :                 print_in = true;
     459           0 :                 print_out = true;
     460             :         }
     461             : 
     462      591953 :         if (ndr_flags & NDR_IN) {
     463      297322 :                 if (print_in) {
     464           0 :                         ndr_print_function_debug(call->ndr_print,
     465           0 :                                                  call->name,
     466             :                                                  ndr_flags,
     467             :                                                  struct_ptr);
     468             :                 }
     469             :         }
     470      591953 :         if (ndr_flags & NDR_OUT) {
     471      294631 :                 if (print_out) {
     472           0 :                         ndr_print_function_debug(call->ndr_print,
     473           0 :                                                  call->name,
     474             :                                                  ndr_flags,
     475             :                                                  struct_ptr);
     476             :                 }
     477             :         }
     478      591953 : }
     479             : 
     480          90 : static void dcerpc_bh_ndr_push_failed(struct dcerpc_binding_handle *h,
     481             :                                       NTSTATUS error,
     482             :                                       const void *struct_ptr,
     483             :                                       const struct ndr_interface_call *call)
     484             : {
     485          90 :         DEBUG(2,("Unable to ndr_push structure for %s - %s\n",
     486             :                  call->name, nt_errstr(error)));
     487          90 : }
     488             : 
     489           0 : static void dcerpc_bh_ndr_pull_failed(struct dcerpc_binding_handle *h,
     490             :                                       NTSTATUS error,
     491             :                                       const DATA_BLOB *blob,
     492             :                                       const struct ndr_interface_call *call)
     493             : {
     494           0 :         struct dcerpc_bh_state *hs = dcerpc_binding_handle_data(h,
     495             :                                      struct dcerpc_bh_state);
     496           0 :         const uint32_t num_examples = 20;
     497           0 :         uint32_t i;
     498             : 
     499           0 :         DEBUG(2,("Unable to ndr_pull structure for %s - %s\n",
     500             :                  call->name, nt_errstr(error)));
     501             : 
     502           0 :         if (hs->p->conn->packet_log_dir == NULL) return;
     503             : 
     504           0 :         for (i=0;i<num_examples;i++) {
     505           0 :                 char *name=NULL;
     506           0 :                 int ret;
     507             : 
     508           0 :                 ret = asprintf(&name, "%s/rpclog/%s-out.%d",
     509           0 :                                hs->p->conn->packet_log_dir,
     510           0 :                                call->name, i);
     511           0 :                 if (ret == -1) {
     512           0 :                         return;
     513             :                 }
     514           0 :                 if (!file_exist(name)) {
     515           0 :                         if (file_save(name, blob->data, blob->length)) {
     516           0 :                                 DEBUG(10,("Logged rpc packet to %s\n", name));
     517             :                         }
     518           0 :                         free(name);
     519           0 :                         break;
     520             :                 }
     521           0 :                 free(name);
     522             :         }
     523             : }
     524             : 
     525      297232 : static NTSTATUS dcerpc_bh_ndr_validate_in(struct dcerpc_binding_handle *h,
     526             :                                           TALLOC_CTX *mem_ctx,
     527             :                                           const DATA_BLOB *blob,
     528             :                                           const struct ndr_interface_call *call)
     529             : {
     530      297232 :         struct dcerpc_bh_state *hs = dcerpc_binding_handle_data(h,
     531             :                                      struct dcerpc_bh_state);
     532             : 
     533      297232 :         if (hs->p->conn->flags & DCERPC_DEBUG_VALIDATE_IN) {
     534        1585 :                 NTSTATUS status;
     535             : 
     536       24330 :                 status = dcerpc_ndr_validate_in(hs->p->conn,
     537             :                                                 mem_ctx,
     538             :                                                 *blob,
     539       24330 :                                                 call->struct_size,
     540       24330 :                                                 call->ndr_push,
     541       24330 :                                                 call->ndr_pull);
     542       24330 :                 if (!NT_STATUS_IS_OK(status)) {
     543           0 :                         DEBUG(0,("Validation [in] failed for %s - %s\n",
     544             :                                  call->name, nt_errstr(status)));
     545           0 :                         return status;
     546             :                 }
     547             :         }
     548             : 
     549      297232 :         DEBUG(10,("rpc request data:\n"));
     550      297232 :         dump_data(10, blob->data, blob->length);
     551             : 
     552      297232 :         return NT_STATUS_OK;
     553             : }
     554             : 
     555      294631 : static NTSTATUS dcerpc_bh_ndr_validate_out(struct dcerpc_binding_handle *h,
     556             :                                            struct ndr_pull *pull_in,
     557             :                                            const void *_struct_ptr,
     558             :                                            const struct ndr_interface_call *call)
     559             : {
     560      294631 :         struct dcerpc_bh_state *hs = dcerpc_binding_handle_data(h,
     561             :                                      struct dcerpc_bh_state);
     562      294631 :         void *struct_ptr = discard_const(_struct_ptr);
     563             : 
     564      294631 :         DEBUG(10,("rpc reply data:\n"));
     565      294631 :         dump_data(10, pull_in->data, pull_in->data_size);
     566             : 
     567      294631 :         if (pull_in->offset != pull_in->data_size) {
     568           0 :                 DEBUG(0,("Warning! ignoring %u unread bytes at ofs:%u (0x%08X) for %s!\n",
     569             :                          pull_in->data_size - pull_in->offset,
     570             :                          pull_in->offset, pull_in->offset,
     571             :                          call->name));
     572             :                 /* we used to return NT_STATUS_INFO_LENGTH_MISMATCH here,
     573             :                    but it turns out that early versions of NT
     574             :                    (specifically NT3.1) add junk onto the end of rpc
     575             :                    packets, so if we want to interoperate at all with
     576             :                    those versions then we need to ignore this error */
     577             :         }
     578             : 
     579      294631 :         if (hs->p->conn->flags & DCERPC_DEBUG_VALIDATE_OUT) {
     580        1495 :                 NTSTATUS status;
     581             : 
     582       23724 :                 status = dcerpc_ndr_validate_out(hs->p->conn,
     583             :                                                  pull_in,
     584             :                                                  struct_ptr,
     585       23724 :                                                  call->struct_size,
     586       23724 :                                                  call->ndr_push,
     587       23724 :                                                  call->ndr_pull,
     588       23724 :                                                  call->ndr_print);
     589       23724 :                 if (!NT_STATUS_IS_OK(status)) {
     590           0 :                         DEBUG(2,("Validation [out] failed for %s - %s\n",
     591             :                                  call->name, nt_errstr(status)));
     592           0 :                         return status;
     593             :                 }
     594             :         }
     595             : 
     596      294631 :         return NT_STATUS_OK;
     597             : }
     598             : 
     599             : static const struct dcerpc_binding_handle_ops dcerpc_bh_ops = {
     600             :         .name                   = "dcerpc",
     601             :         .is_connected           = dcerpc_bh_is_connected,
     602             :         .set_timeout            = dcerpc_bh_set_timeout,
     603             :         .auth_info              = dcerpc_bh_auth_info,
     604             :         .raw_call_send          = dcerpc_bh_raw_call_send,
     605             :         .raw_call_recv          = dcerpc_bh_raw_call_recv,
     606             :         .disconnect_send        = dcerpc_bh_disconnect_send,
     607             :         .disconnect_recv        = dcerpc_bh_disconnect_recv,
     608             : 
     609             :         .push_bigendian         = dcerpc_bh_push_bigendian,
     610             :         .ref_alloc              = dcerpc_bh_ref_alloc,
     611             :         .use_ndr64              = dcerpc_bh_use_ndr64,
     612             :         .do_ndr_print           = dcerpc_bh_do_ndr_print,
     613             :         .ndr_push_failed        = dcerpc_bh_ndr_push_failed,
     614             :         .ndr_pull_failed        = dcerpc_bh_ndr_pull_failed,
     615             :         .ndr_validate_in        = dcerpc_bh_ndr_validate_in,
     616             :         .ndr_validate_out       = dcerpc_bh_ndr_validate_out,
     617             : };
     618             : 
     619             : /* initialise a dcerpc pipe. */
     620       20010 : struct dcerpc_binding_handle *dcerpc_pipe_binding_handle(struct dcerpc_pipe *p,
     621             :                                                          const struct GUID *object,
     622             :                                                          const struct ndr_interface_table *table)
     623             : {
     624         876 :         struct dcerpc_binding_handle *h;
     625         876 :         struct dcerpc_bh_state *hs;
     626             : 
     627       20010 :         h = dcerpc_binding_handle_create(p,
     628             :                                          &dcerpc_bh_ops,
     629             :                                          object,
     630             :                                          table,
     631             :                                          &hs,
     632             :                                          struct dcerpc_bh_state,
     633             :                                          __location__);
     634       20010 :         if (h == NULL) {
     635           0 :                 return NULL;
     636             :         }
     637       20010 :         hs->p = p;
     638             : 
     639       20010 :         dcerpc_binding_handle_set_sync_ev(h, p->conn->event_ctx);
     640             : 
     641       20010 :         return h;
     642             : }
     643             : 
     644             : /* initialise a dcerpc pipe. */
     645       31243 : _PUBLIC_ struct dcerpc_pipe *dcerpc_pipe_init(TALLOC_CTX *mem_ctx, struct tevent_context *ev)
     646             : {
     647         870 :         struct dcerpc_pipe *p;
     648             : 
     649       31243 :         p = talloc_zero(mem_ctx, struct dcerpc_pipe);
     650       31243 :         if (!p) {
     651           0 :                 return NULL;
     652             :         }
     653             : 
     654       31243 :         p->conn = dcerpc_connection_init(p, ev);
     655       31243 :         if (p->conn == NULL) {
     656           0 :                 talloc_free(p);
     657           0 :                 return NULL;
     658             :         }
     659             : 
     660       31243 :         p->request_timeout = DCERPC_REQUEST_TIMEOUT;
     661             : 
     662       31243 :         if (DEBUGLVL(100)) {
     663           0 :                 p->conn->flags |= DCERPC_DEBUG_PRINT_BOTH;
     664             :         }
     665             : 
     666       30373 :         return p;
     667             : }
     668             : 
     669             : 
     670             : /* 
     671             :    choose the next call id to use
     672             : */
     673      297424 : static uint32_t next_call_id(struct dcecli_connection *c)
     674             : {
     675      297424 :         c->call_id++;
     676      297424 :         if (c->call_id == 0) {
     677           0 :                 c->call_id++;
     678             :         }
     679      297424 :         return c->call_id;
     680             : }
     681             : 
     682             : /**
     683             :   setup for a ndr pull, also setting up any flags from the binding string
     684             : */
     685       48054 : static struct ndr_pull *ndr_pull_init_flags(struct dcecli_connection *c, 
     686             :                                             DATA_BLOB *blob, TALLOC_CTX *mem_ctx)
     687             : {
     688       48054 :         struct ndr_pull *ndr = ndr_pull_init_blob(blob, mem_ctx);
     689             : 
     690       48054 :         if (ndr == NULL) return ndr;
     691             : 
     692       48054 :         if (c->flags & DCERPC_DEBUG_PAD_CHECK) {
     693           0 :                 ndr->flags |= LIBNDR_FLAG_PAD_CHECK;
     694             :         }
     695             : 
     696       48054 :         if (c->flags & DCERPC_NDR_REF_ALLOC) {
     697           0 :                 ndr->flags |= LIBNDR_FLAG_REF_ALLOC;
     698             :         }
     699             : 
     700       48054 :         if (c->flags & DCERPC_NDR64) {
     701           0 :                 ndr->flags |= LIBNDR_FLAG_NDR64;
     702             :         }
     703             : 
     704       44974 :         return ndr;
     705             : }
     706             : 
     707             : /* 
     708             :    parse the authentication information on a dcerpc response packet
     709             : */
     710      584333 : static NTSTATUS ncacn_pull_pkt_auth(struct dcecli_connection *c,
     711             :                                     TALLOC_CTX *mem_ctx,
     712             :                                     enum dcerpc_pkt_type ptype,
     713             :                                     uint8_t required_flags,
     714             :                                     uint8_t optional_flags,
     715             :                                     uint8_t payload_offset,
     716             :                                     DATA_BLOB *payload_and_verifier,
     717             :                                     DATA_BLOB *raw_packet,
     718             :                                     const struct ncacn_packet *pkt)
     719             : {
     720      584333 :         const struct dcerpc_auth tmp_auth = {
     721      584333 :                 .auth_type = c->security_state.auth_type,
     722      584333 :                 .auth_level = c->security_state.auth_level,
     723      584333 :                 .auth_context_id = c->security_state.auth_context_id,
     724             :         };
     725        6873 :         NTSTATUS status;
     726             : 
     727      584333 :         status = dcerpc_ncacn_pull_pkt_auth(&tmp_auth,
     728             :                                             c->security_state.generic_state,
     729             :                                             true, /* check_pkt_auth_fields */
     730             :                                             mem_ctx,
     731             :                                             ptype,
     732             :                                             required_flags,
     733             :                                             optional_flags,
     734             :                                             payload_offset,
     735             :                                             payload_and_verifier,
     736             :                                             raw_packet,
     737             :                                             pkt);
     738      584333 :         if (NT_STATUS_EQUAL(status, NT_STATUS_RPC_PROTOCOL_ERROR)) {
     739           0 :                 return NT_STATUS_INVALID_NETWORK_RESPONSE;
     740             :         }
     741      584333 :         if (!NT_STATUS_IS_OK(status)) {
     742           0 :                 return status;
     743             :         }
     744             : 
     745      584333 :         return NT_STATUS_OK;
     746             : }
     747             : 
     748             : 
     749             : /* 
     750             :    push a dcerpc request packet into a blob, possibly signing it.
     751             : */
     752      310842 : static NTSTATUS ncacn_push_request_sign(struct dcecli_connection *c, 
     753             :                                          DATA_BLOB *blob, TALLOC_CTX *mem_ctx, 
     754             :                                          size_t sig_size,
     755             :                                          struct ncacn_packet *pkt)
     756             : {
     757      310842 :         const struct dcerpc_auth tmp_auth = {
     758      310842 :                 .auth_type = c->security_state.auth_type,
     759      310842 :                 .auth_level = c->security_state.auth_level,
     760      310842 :                 .auth_context_id = c->security_state.auth_context_id,
     761             :         };
     762        7217 :         NTSTATUS status;
     763      310842 :         uint8_t payload_offset = DCERPC_REQUEST_LENGTH;
     764             : 
     765      310842 :         if (pkt->pfc_flags & DCERPC_PFC_FLAG_OBJECT_UUID) {
     766         672 :                 payload_offset += 16;
     767             :         }
     768             : 
     769      310842 :         status = dcerpc_ncacn_push_pkt_auth(&tmp_auth,
     770             :                                             c->security_state.generic_state,
     771             :                                             mem_ctx, blob,
     772             :                                             sig_size,
     773             :                                             payload_offset,
     774      310842 :                                             &pkt->u.request.stub_and_verifier,
     775             :                                             pkt);
     776      310842 :         if (!NT_STATUS_IS_OK(status)) {
     777           0 :                 return status;
     778             :         }
     779             : 
     780      310842 :         return NT_STATUS_OK;
     781             : }
     782             : 
     783             : 
     784             : /* 
     785             :    fill in the fixed values in a dcerpc header 
     786             : */
     787      323213 : static void init_ncacn_hdr(struct dcecli_connection *c, struct ncacn_packet *pkt)
     788             : {
     789      323213 :         pkt->rpc_vers = 5;
     790      323213 :         pkt->rpc_vers_minor = 0;
     791      323213 :         if (c->flags & DCERPC_PUSH_BIGENDIAN) {
     792       30807 :                 pkt->drep[0] = 0;
     793             :         } else {
     794      292406 :                 pkt->drep[0] = DCERPC_DREP_LE;
     795             :         }
     796      323213 :         pkt->drep[1] = 0;
     797      323213 :         pkt->drep[2] = 0;
     798      323213 :         pkt->drep[3] = 0;
     799      315091 : }
     800             : 
     801             : /*
     802             :   map a bind nak reason to a NTSTATUS
     803             : */
     804          79 : static NTSTATUS dcerpc_map_nak_reason(enum dcerpc_bind_nak_reason reason)
     805             : {
     806          79 :         switch (reason) {
     807           0 :         case DCERPC_BIND_NAK_REASON_PROTOCOL_VERSION_NOT_SUPPORTED:
     808           0 :                 return NT_STATUS_REVISION_MISMATCH;
     809           0 :         case DCERPC_BIND_NAK_REASON_INVALID_AUTH_TYPE:
     810           0 :                 return NT_STATUS_INVALID_PARAMETER;
     811          61 :         default:
     812          79 :                 break;
     813             :         }
     814          79 :         return NT_STATUS_UNSUCCESSFUL;
     815             : }
     816             : 
     817          36 : static NTSTATUS dcerpc_map_ack_reason(const struct dcerpc_ack_ctx *ack)
     818             : {
     819          36 :         if (ack == NULL) {
     820           0 :                 return NT_STATUS_RPC_PROTOCOL_ERROR;
     821             :         }
     822             : 
     823          36 :         switch (ack->result) {
     824           0 :         case DCERPC_BIND_ACK_RESULT_NEGOTIATE_ACK:
     825             :                 /*
     826             :                  * We have not asked for this...
     827             :                  */
     828           0 :                 return NT_STATUS_RPC_PROTOCOL_ERROR;
     829          30 :         default:
     830          36 :                 break;
     831             :         }
     832             : 
     833          36 :         switch (ack->reason.value) {
     834          30 :         case DCERPC_BIND_ACK_REASON_ABSTRACT_SYNTAX_NOT_SUPPORTED:
     835          30 :                 return NT_STATUS_RPC_UNSUPPORTED_NAME_SYNTAX;
     836           0 :         case DCERPC_BIND_ACK_REASON_TRANSFER_SYNTAXES_NOT_SUPPORTED:
     837           0 :                 return NT_STATUS_RPC_UNSUPPORTED_NAME_SYNTAX;
     838           0 :         default:
     839           0 :                 break;
     840             :         }
     841           0 :         return NT_STATUS_UNSUCCESSFUL;
     842             : }
     843             : 
     844             : /*
     845             :   remove requests from the pending or queued queues
     846             :  */
     847      646056 : static int dcerpc_req_dequeue(struct rpc_request *req)
     848             : {
     849      646056 :         switch (req->state) {
     850           0 :         case RPC_REQUEST_QUEUED:
     851           0 :                 DLIST_REMOVE(req->p->conn->request_queue, req);
     852           0 :                 break;
     853      323028 :         case RPC_REQUEST_PENDING:
     854      323028 :                 DLIST_REMOVE(req->p->conn->pending, req);
     855      314906 :                 break;
     856      314906 :         case RPC_REQUEST_DONE:
     857      314906 :                 break;
     858             :         }
     859      646056 :         return 0;
     860             : }
     861             : 
     862             : 
     863             : /*
     864             :   mark the dcerpc connection dead. All outstanding requests get an error
     865             : */
     866       31237 : static void dcerpc_connection_dead(struct dcecli_connection *conn, NTSTATUS status)
     867             : {
     868       31237 :         if (conn->dead) return;
     869             : 
     870       31237 :         conn->dead = true;
     871             : 
     872       31237 :         TALLOC_FREE(conn->io_trigger);
     873       31237 :         conn->io_trigger_pending = false;
     874             : 
     875       31237 :         dcerpc_shutdown_pipe(conn, status);
     876             : 
     877             :         /* all pending requests get the error */
     878       36681 :         while (conn->pending) {
     879          43 :                 struct rpc_request *req = conn->pending;
     880          43 :                 dcerpc_req_dequeue(req);
     881          43 :                 req->state = RPC_REQUEST_DONE;
     882          43 :                 req->status = status;
     883          43 :                 if (req->async.callback) {
     884          43 :                         req->async.callback(req);
     885             :                 }
     886             :         }       
     887             : 
     888             :         /* all requests, which are not shipped */
     889       35768 :         while (conn->request_queue) {
     890           0 :                 struct rpc_request *req = conn->request_queue;
     891           0 :                 dcerpc_req_dequeue(req);
     892           0 :                 req->state = RPC_REQUEST_DONE;
     893           0 :                 req->status = status;
     894           0 :                 if (req->async.callback) {
     895           0 :                         req->async.callback(req);
     896             :                 }
     897             :         }
     898             : 
     899       31237 :         talloc_set_destructor(conn, NULL);
     900       31237 :         if (conn->free_skipped) {
     901           0 :                 talloc_free(conn);
     902             :         }
     903             : }
     904             : 
     905             : /*
     906             :   forward declarations of the recv_data handlers for the types of
     907             :   packets we need to handle
     908             : */
     909             : static void dcerpc_request_recv_data(struct dcecli_connection *c, 
     910             :                                      DATA_BLOB *raw_packet, struct ncacn_packet *pkt);
     911             : 
     912             : /*
     913             :   receive a dcerpc reply from the transport. Here we work out what
     914             :   type of reply it is (normal request, bind or alter context) and
     915             :   dispatch to the appropriate handler
     916             : */
     917      612723 : static void dcerpc_recv_data(struct dcecli_connection *conn, DATA_BLOB *blob, NTSTATUS status)
     918             : {
     919        8203 :         struct ncacn_packet pkt;
     920             : 
     921      612723 :         if (conn->dead) {
     922          34 :                 return;
     923             :         }
     924             : 
     925      612723 :         if (NT_STATUS_IS_OK(status) && blob->length == 0) {
     926           0 :                 status = NT_STATUS_UNEXPECTED_NETWORK_ERROR;
     927             :         }
     928             : 
     929             :         /* the transport may be telling us of a severe error, such as
     930             :            a dropped socket */
     931      612723 :         if (!NT_STATUS_IS_OK(status)) {
     932          34 :                 data_blob_free(blob);
     933          34 :                 dcerpc_connection_dead(conn, status);
     934          34 :                 return;
     935             :         }
     936             : 
     937             :         /* parse the basic packet to work out what type of response this is */
     938      612689 :         status = dcerpc_pull_ncacn_packet(blob->data, blob, &pkt);
     939      612689 :         if (!NT_STATUS_IS_OK(status)) {
     940           0 :                 data_blob_free(blob);
     941           0 :                 dcerpc_connection_dead(conn, status);
     942           0 :                 return;
     943             :         }
     944             : 
     945      612689 :         dcerpc_request_recv_data(conn, blob, &pkt);
     946             : }
     947             : 
     948             : /*
     949             :   handle timeouts of individual dcerpc requests
     950             : */
     951           0 : static void dcerpc_timeout_handler(struct tevent_context *ev, struct tevent_timer *te, 
     952             :                                    struct timeval t, void *private_data)
     953             : {
     954           0 :         struct rpc_request *req = talloc_get_type(private_data, struct rpc_request);
     955             : 
     956           0 :         if (req->ignore_timeout) {
     957           0 :                 dcerpc_req_dequeue(req);
     958           0 :                 req->state = RPC_REQUEST_DONE;
     959           0 :                 req->status = NT_STATUS_IO_TIMEOUT;
     960           0 :                 if (req->async.callback) {
     961           0 :                         req->async.callback(req);
     962             :                 }
     963           0 :                 return;
     964             :         }
     965             : 
     966           0 :         dcerpc_connection_dead(req->p->conn, NT_STATUS_IO_TIMEOUT);
     967             : }
     968             : 
     969             : struct dcerpc_bind_state {
     970             :         struct tevent_context *ev;
     971             :         struct dcerpc_pipe *p;
     972             : };
     973             : 
     974             : static void dcerpc_bind_fail_handler(struct rpc_request *subreq);
     975             : static void dcerpc_bind_recv_handler(struct rpc_request *subreq,
     976             :                                      DATA_BLOB *raw_packet,
     977             :                                      struct ncacn_packet *pkt);
     978             : 
     979       19953 : struct tevent_req *dcerpc_bind_send(TALLOC_CTX *mem_ctx,
     980             :                                     struct tevent_context *ev,
     981             :                                     struct dcerpc_pipe *p,
     982             :                                     const struct ndr_syntax_id *syntax,
     983             :                                     const struct ndr_syntax_id *transfer_syntax)
     984             : {
     985         870 :         struct tevent_req *req;
     986         870 :         struct dcerpc_bind_state *state;
     987         870 :         struct ncacn_packet pkt;
     988         870 :         DATA_BLOB blob;
     989         870 :         NTSTATUS status;
     990         870 :         struct rpc_request *subreq;
     991         870 :         uint32_t flags;
     992         870 :         struct ndr_syntax_id bind_time_features;
     993             : 
     994       19953 :         bind_time_features = dcerpc_construct_bind_time_features(
     995             :                         DCERPC_BIND_TIME_SECURITY_CONTEXT_MULTIPLEXING |
     996             :                         DCERPC_BIND_TIME_KEEP_CONNECTION_ON_ORPHAN);
     997             : 
     998       19953 :         req = tevent_req_create(mem_ctx, &state,
     999             :                                 struct dcerpc_bind_state);
    1000       19953 :         if (req == NULL) {
    1001           0 :                 return NULL;
    1002             :         }
    1003             : 
    1004       19953 :         state->ev = ev;
    1005       19953 :         state->p = p;
    1006             : 
    1007       19953 :         p->syntax = *syntax;
    1008       19953 :         p->transfer_syntax = *transfer_syntax;
    1009             : 
    1010       19953 :         flags = dcerpc_binding_get_flags(p->binding);
    1011             : 
    1012       19953 :         init_ncacn_hdr(p->conn, &pkt);
    1013             : 
    1014       19953 :         pkt.ptype = DCERPC_PKT_BIND;
    1015       19953 :         pkt.pfc_flags = DCERPC_PFC_FLAG_FIRST | DCERPC_PFC_FLAG_LAST;
    1016       19953 :         pkt.call_id = p->conn->call_id;
    1017       19953 :         pkt.auth_length = 0;
    1018             : 
    1019       19953 :         if (flags & DCERPC_CONCURRENT_MULTIPLEX) {
    1020          51 :                 pkt.pfc_flags |= DCERPC_PFC_FLAG_CONC_MPX;
    1021             :         }
    1022             : 
    1023       19953 :         if (p->conn->flags & DCERPC_PROPOSE_HEADER_SIGNING) {
    1024        8195 :                 pkt.pfc_flags |= DCERPC_PFC_FLAG_SUPPORT_HEADER_SIGN;
    1025             :         }
    1026             : 
    1027       19953 :         pkt.u.bind.max_xmit_frag = p->conn->srv_max_xmit_frag;
    1028       19953 :         pkt.u.bind.max_recv_frag = p->conn->srv_max_recv_frag;
    1029       19953 :         pkt.u.bind.assoc_group_id = dcerpc_binding_get_assoc_group_id(p->binding);
    1030       19953 :         pkt.u.bind.num_contexts = 2;
    1031       19953 :         pkt.u.bind.ctx_list = talloc_zero_array(state, struct dcerpc_ctx_list,
    1032             :                                                 pkt.u.bind.num_contexts);
    1033       19953 :         if (tevent_req_nomem(pkt.u.bind.ctx_list, req)) {
    1034           0 :                 return tevent_req_post(req, ev);
    1035             :         }
    1036       19953 :         pkt.u.bind.ctx_list[0].context_id = p->context_id;
    1037       19953 :         pkt.u.bind.ctx_list[0].num_transfer_syntaxes = 1;
    1038       19953 :         pkt.u.bind.ctx_list[0].abstract_syntax = p->syntax;
    1039       19953 :         pkt.u.bind.ctx_list[0].transfer_syntaxes = &p->transfer_syntax;
    1040       19953 :         pkt.u.bind.ctx_list[1].context_id = p->context_id + 1;
    1041       19953 :         pkt.u.bind.ctx_list[1].num_transfer_syntaxes = 1;
    1042       19953 :         pkt.u.bind.ctx_list[1].abstract_syntax = p->syntax;
    1043       19953 :         pkt.u.bind.ctx_list[1].transfer_syntaxes = &bind_time_features;
    1044       19953 :         pkt.u.bind.auth_info = data_blob(NULL, 0);
    1045             : 
    1046             :         /* construct the NDR form of the packet */
    1047       19953 :         status = dcerpc_ncacn_push_auth(&blob,
    1048             :                                 state,
    1049             :                                 &pkt,
    1050       19953 :                                 p->conn->security_state.tmp_auth_info.out);
    1051       19953 :         if (tevent_req_nterror(req, status)) {
    1052           0 :                 return tevent_req_post(req, ev);
    1053             :         }
    1054             : 
    1055             :         /*
    1056             :          * we allocate a dcerpc_request so we can be in the same
    1057             :          * request queue as normal requests
    1058             :          */
    1059       19953 :         subreq = talloc_zero(state, struct rpc_request);
    1060       19953 :         if (tevent_req_nomem(subreq, req)) {
    1061           0 :                 return tevent_req_post(req, ev);
    1062             :         }
    1063             : 
    1064       19953 :         subreq->state = RPC_REQUEST_PENDING;
    1065       19953 :         subreq->call_id = pkt.call_id;
    1066       19953 :         subreq->async.private_data = req;
    1067       19953 :         subreq->async.callback = dcerpc_bind_fail_handler;
    1068       19953 :         subreq->p = p;
    1069       19953 :         subreq->recv_handler = dcerpc_bind_recv_handler;
    1070       19953 :         DLIST_ADD_END(p->conn->pending, subreq);
    1071       19953 :         talloc_set_destructor(subreq, dcerpc_req_dequeue);
    1072             : 
    1073       19953 :         status = dcerpc_send_request(p->conn, &blob, true);
    1074       19953 :         if (tevent_req_nterror(req, status)) {
    1075           0 :                 return tevent_req_post(req, ev);
    1076             :         }
    1077             : 
    1078       19953 :         tevent_add_timer(ev, subreq,
    1079             :                          timeval_current_ofs(DCERPC_REQUEST_TIMEOUT, 0),
    1080             :                          dcerpc_timeout_handler, subreq);
    1081             : 
    1082       19953 :         return req;
    1083             : }
    1084             : 
    1085           0 : static void dcerpc_bind_fail_handler(struct rpc_request *subreq)
    1086             : {
    1087           0 :         struct tevent_req *req =
    1088           0 :                 talloc_get_type_abort(subreq->async.private_data,
    1089             :                 struct tevent_req);
    1090           0 :         struct dcerpc_bind_state *state =
    1091           0 :                 tevent_req_data(req,
    1092             :                 struct dcerpc_bind_state);
    1093           0 :         NTSTATUS status = subreq->status;
    1094             : 
    1095           0 :         TALLOC_FREE(subreq);
    1096             : 
    1097             :         /*
    1098             :          * We trigger the callback in the next event run
    1099             :          * because the code in this file might trigger
    1100             :          * multiple request callbacks from within a single
    1101             :          * while loop.
    1102             :          *
    1103             :          * In order to avoid segfaults from within
    1104             :          * dcerpc_connection_dead() we call
    1105             :          * tevent_req_defer_callback().
    1106             :          */
    1107           0 :         tevent_req_defer_callback(req, state->ev);
    1108             : 
    1109           0 :         tevent_req_nterror(req, status);
    1110           0 : }
    1111             : 
    1112       19953 : static void dcerpc_bind_recv_handler(struct rpc_request *subreq,
    1113             :                                      DATA_BLOB *raw_packet,
    1114             :                                      struct ncacn_packet *pkt)
    1115             : {
    1116         870 :         struct tevent_req *req =
    1117       19953 :                 talloc_get_type_abort(subreq->async.private_data,
    1118             :                 struct tevent_req);
    1119         870 :         struct dcerpc_bind_state *state =
    1120       19953 :                 tevent_req_data(req,
    1121             :                 struct dcerpc_bind_state);
    1122       19953 :         struct dcecli_connection *conn = state->p->conn;
    1123       19953 :         struct dcecli_security *sec = &conn->security_state;
    1124       19953 :         struct dcerpc_binding *b = NULL;
    1125         870 :         NTSTATUS status;
    1126         870 :         uint32_t flags;
    1127             : 
    1128             :         /*
    1129             :          * Note that pkt is allocated under raw_packet->data,
    1130             :          * while raw_packet->data is a child of subreq.
    1131             :          */
    1132       19953 :         talloc_steal(state, raw_packet->data);
    1133       19953 :         TALLOC_FREE(subreq);
    1134             : 
    1135             :         /*
    1136             :          * We trigger the callback in the next event run
    1137             :          * because the code in this file might trigger
    1138             :          * multiple request callbacks from within a single
    1139             :          * while loop.
    1140             :          *
    1141             :          * In order to avoid segfaults from within
    1142             :          * dcerpc_connection_dead() we call
    1143             :          * tevent_req_defer_callback().
    1144             :          */
    1145       19953 :         tevent_req_defer_callback(req, state->ev);
    1146             : 
    1147       19953 :         if (pkt->ptype == DCERPC_PKT_BIND_NAK) {
    1148          79 :                 status = dcerpc_map_nak_reason(pkt->u.bind_nak.reject_reason);
    1149             : 
    1150          79 :                 DEBUG(2,("dcerpc: bind_nak reason %d - %s\n",
    1151             :                          pkt->u.bind_nak.reject_reason, nt_errstr(status)));
    1152             : 
    1153          79 :                 tevent_req_nterror(req, status);
    1154          97 :                 return;
    1155             :         }
    1156             : 
    1157       19874 :         status = dcerpc_verify_ncacn_packet_header(pkt,
    1158             :                                         DCERPC_PKT_BIND_ACK,
    1159             :                                         pkt->u.bind_ack.auth_info.length,
    1160             :                                         DCERPC_PFC_FLAG_FIRST |
    1161             :                                         DCERPC_PFC_FLAG_LAST,
    1162             :                                         DCERPC_PFC_FLAG_CONC_MPX |
    1163             :                                         DCERPC_PFC_FLAG_SUPPORT_HEADER_SIGN);
    1164       19874 :         if (!NT_STATUS_IS_OK(status)) {
    1165           0 :                 state->p->last_fault_code = DCERPC_NCA_S_PROTO_ERROR;
    1166           0 :                 tevent_req_nterror(req, NT_STATUS_NET_WRITE_FAULT);
    1167           0 :                 return;
    1168             :         }
    1169             : 
    1170       19874 :         if (pkt->u.bind_ack.num_results < 1) {
    1171           0 :                 state->p->last_fault_code = DCERPC_NCA_S_PROTO_ERROR;
    1172           0 :                 tevent_req_nterror(req, NT_STATUS_NET_WRITE_FAULT);
    1173           0 :                 return;
    1174             :         }
    1175             : 
    1176       19874 :         if (pkt->u.bind_ack.ctx_list[0].result != 0) {
    1177          21 :                 status = dcerpc_map_ack_reason(&pkt->u.bind_ack.ctx_list[0]);
    1178          21 :                 DEBUG(2,("dcerpc: bind_ack failed - reason %d - %s\n",
    1179             :                          pkt->u.bind_ack.ctx_list[0].reason.value,
    1180             :                          nt_errstr(status)));
    1181          21 :                 tevent_req_nterror(req, status);
    1182          21 :                 return;
    1183             :         }
    1184             : 
    1185       19853 :         if (pkt->u.bind_ack.num_results >= 2) {
    1186       19853 :                 if (pkt->u.bind_ack.ctx_list[1].result == DCERPC_BIND_ACK_RESULT_NEGOTIATE_ACK) {
    1187       19853 :                         conn->bind_time_features = pkt->u.bind_ack.ctx_list[1].reason.negotiate;
    1188             :                 } else {
    1189           0 :                         status = dcerpc_map_ack_reason(&pkt->u.bind_ack.ctx_list[1]);
    1190           0 :                         DEBUG(10,("dcerpc: bind_time_feature failed - reason %d - %s\n",
    1191             :                                  pkt->u.bind_ack.ctx_list[1].reason.value,
    1192             :                                  nt_errstr(status)));
    1193         849 :                         status = NT_STATUS_OK;
    1194             :                 }
    1195             :         }
    1196             : 
    1197             :         /*
    1198             :          * DCE-RPC 1.1 (c706) specifies
    1199             :          * CONST_MUST_RCV_FRAG_SIZE as 1432
    1200             :          */
    1201       19853 :         if (pkt->u.bind_ack.max_xmit_frag < 1432) {
    1202           0 :                 state->p->last_fault_code = DCERPC_NCA_S_PROTO_ERROR;
    1203           0 :                 tevent_req_nterror(req, NT_STATUS_NET_WRITE_FAULT);
    1204           0 :                 return;
    1205             :         }
    1206       19853 :         if (pkt->u.bind_ack.max_recv_frag < 1432) {
    1207           0 :                 state->p->last_fault_code = DCERPC_NCA_S_PROTO_ERROR;
    1208           0 :                 tevent_req_nterror(req, NT_STATUS_NET_WRITE_FAULT);
    1209           0 :                 return;
    1210             :         }
    1211       19853 :         conn->srv_max_xmit_frag = MIN(conn->srv_max_xmit_frag,
    1212             :                                       pkt->u.bind_ack.max_xmit_frag);
    1213       19853 :         conn->srv_max_recv_frag = MIN(conn->srv_max_recv_frag,
    1214             :                                       pkt->u.bind_ack.max_recv_frag);
    1215             : 
    1216       19853 :         flags = dcerpc_binding_get_flags(state->p->binding);
    1217             : 
    1218       19853 :         if (flags & DCERPC_CONCURRENT_MULTIPLEX) {
    1219          51 :                 if (pkt->pfc_flags & DCERPC_PFC_FLAG_CONC_MPX) {
    1220          51 :                         conn->flags |= DCERPC_CONCURRENT_MULTIPLEX;
    1221             :                 } else {
    1222           0 :                         conn->flags &= ~DCERPC_CONCURRENT_MULTIPLEX;
    1223             :                 }
    1224             :         }
    1225             : 
    1226       19853 :         if (!(conn->flags & DCERPC_CONCURRENT_MULTIPLEX)) {
    1227       19802 :                 struct dcerpc_binding *pb =
    1228       19802 :                         discard_const_p(struct dcerpc_binding, state->p->binding);
    1229             :                 /*
    1230             :                  * clear DCERPC_CONCURRENT_MULTIPLEX
    1231             :                  */
    1232       19802 :                 status = dcerpc_binding_set_flags(pb, 0,
    1233             :                                                   DCERPC_CONCURRENT_MULTIPLEX);
    1234       19802 :                 if (tevent_req_nterror(req, status)) {
    1235           0 :                         return;
    1236             :                 }
    1237             :         }
    1238       19853 :         if ((conn->flags & DCERPC_PROPOSE_HEADER_SIGNING) &&
    1239        8164 :             (pkt->pfc_flags & DCERPC_PFC_FLAG_SUPPORT_HEADER_SIGN)) {
    1240        7666 :                 conn->flags |= DCERPC_HEADER_SIGNING;
    1241             :         }
    1242             : 
    1243             :         /* the bind_ack might contain a reply set of credentials */
    1244       19853 :         if (pkt->auth_length != 0 && sec->tmp_auth_info.in != NULL) {
    1245        9064 :                 status = dcerpc_pull_auth_trailer(pkt, sec->tmp_auth_info.mem,
    1246        8640 :                                                   &pkt->u.bind_ack.auth_info,
    1247             :                                                   sec->tmp_auth_info.in,
    1248             :                                                   NULL, true);
    1249        8640 :                 if (tevent_req_nterror(req, status)) {
    1250           0 :                         return;
    1251             :                 }
    1252             :         }
    1253             : 
    1254             :         /*
    1255             :          * We're the owner of the binding, so we're allowed to modify it.
    1256             :          */
    1257       19853 :         b = discard_const_p(struct dcerpc_binding, state->p->binding);
    1258       19853 :         status = dcerpc_binding_set_assoc_group_id(b,
    1259             :                                                    pkt->u.bind_ack.assoc_group_id);
    1260       19853 :         if (tevent_req_nterror(req, status)) {
    1261           0 :                 return;
    1262             :         }
    1263             : 
    1264       19853 :         tevent_req_done(req);
    1265             : }
    1266             : 
    1267       19953 : NTSTATUS dcerpc_bind_recv(struct tevent_req *req)
    1268             : {
    1269       19953 :         return tevent_req_simple_recv_ntstatus(req);
    1270             : }
    1271             : 
    1272             : /* 
    1273             :    perform a continued bind (and auth3)
    1274             : */
    1275         185 : NTSTATUS dcerpc_auth3(struct dcerpc_pipe *p,
    1276             :                       TALLOC_CTX *mem_ctx)
    1277             : {
    1278           0 :         struct ncacn_packet pkt;
    1279           0 :         NTSTATUS status;
    1280           0 :         DATA_BLOB blob;
    1281           0 :         uint32_t flags;
    1282             : 
    1283         185 :         flags = dcerpc_binding_get_flags(p->binding);
    1284             : 
    1285         185 :         init_ncacn_hdr(p->conn, &pkt);
    1286             : 
    1287         185 :         pkt.ptype = DCERPC_PKT_AUTH3;
    1288         185 :         pkt.pfc_flags = DCERPC_PFC_FLAG_FIRST | DCERPC_PFC_FLAG_LAST;
    1289         185 :         pkt.call_id = next_call_id(p->conn);
    1290         185 :         pkt.auth_length = 0;
    1291         185 :         pkt.u.auth3.auth_info = data_blob(NULL, 0);
    1292             : 
    1293         185 :         if (flags & DCERPC_CONCURRENT_MULTIPLEX) {
    1294           4 :                 pkt.pfc_flags |= DCERPC_PFC_FLAG_CONC_MPX;
    1295             :         }
    1296             : 
    1297             :         /* construct the NDR form of the packet */
    1298         185 :         status = dcerpc_ncacn_push_auth(&blob,
    1299             :                                 mem_ctx,
    1300             :                                 &pkt,
    1301         185 :                                 p->conn->security_state.tmp_auth_info.out);
    1302         185 :         if (!NT_STATUS_IS_OK(status)) {
    1303           0 :                 return status;
    1304             :         }
    1305             : 
    1306             :         /* send it on its way */
    1307         185 :         status = dcerpc_send_request(p->conn, &blob, false);
    1308         185 :         if (!NT_STATUS_IS_OK(status)) {
    1309           0 :                 return status;
    1310             :         }
    1311             : 
    1312         185 :         return NT_STATUS_OK;    
    1313             : }
    1314             : 
    1315             : 
    1316             : /*
    1317             :   process a fragment received from the transport layer during a
    1318             :   request
    1319             : 
    1320             :   This function frees the data 
    1321             : */
    1322      612689 : static void dcerpc_request_recv_data(struct dcecli_connection *c, 
    1323             :                                      DATA_BLOB *raw_packet, struct ncacn_packet *pkt)
    1324             : {
    1325        8200 :         struct rpc_request *req;
    1326        8200 :         unsigned int length;
    1327      612689 :         NTSTATUS status = NT_STATUS_OK;
    1328             : 
    1329             :         /*
    1330             :           if this is an authenticated connection then parse and check
    1331             :           the auth info. We have to do this before finding the
    1332             :           matching packet, as the request structure might have been
    1333             :           removed due to a timeout, but if it has been we still need
    1334             :           to run the auth routines so that we don't get the sign/seal
    1335             :           info out of step with the server
    1336             :         */
    1337      612689 :         switch (pkt->ptype) {
    1338      584333 :         case DCERPC_PKT_RESPONSE:
    1339      584333 :                 status = ncacn_pull_pkt_auth(c, raw_packet->data,
    1340             :                                    DCERPC_PKT_RESPONSE,
    1341             :                                    0, /* required_flags */
    1342             :                                    DCERPC_PFC_FLAG_FIRST |
    1343             :                                    DCERPC_PFC_FLAG_LAST,
    1344             :                                    DCERPC_REQUEST_LENGTH,
    1345             :                                    &pkt->u.response.stub_and_verifier,
    1346             :                                    raw_packet, pkt);
    1347      584333 :                 break;
    1348       27029 :         default:
    1349       27029 :                 break;
    1350             :         }
    1351             : 
    1352             :         /* find the matching request */
    1353      629839 :         for (req=c->pending;req;req=req->next) {
    1354      629839 :                 if (pkt->call_id == req->call_id) break;
    1355             :         }
    1356             : 
    1357             : #if 0
    1358             :         /* useful for testing certain vendors RPC servers */
    1359             :         if (req == NULL && c->pending && pkt->call_id == 0) {
    1360             :                 DEBUG(0,("HACK FOR INCORRECT CALL ID\n"));
    1361             :                 req = c->pending;
    1362             :         }
    1363             : #endif
    1364             : 
    1365      612689 :         if (req == NULL) {
    1366           0 :                 DEBUG(2,("dcerpc_request: unmatched call_id %u in response packet\n", pkt->call_id));
    1367           0 :                 data_blob_free(raw_packet);
    1368      314425 :                 return;
    1369             :         }
    1370             : 
    1371      612689 :         talloc_steal(req, raw_packet->data);
    1372             : 
    1373      612689 :         if (req->recv_handler != NULL) {
    1374       25789 :                 dcerpc_req_dequeue(req);
    1375       25789 :                 req->state = RPC_REQUEST_DONE;
    1376             : 
    1377             :                 /*
    1378             :                  * We have to look at shipping further requests before calling
    1379             :                  * the async function, that one might close the pipe
    1380             :                  */
    1381       25789 :                 dcerpc_schedule_io_trigger(c);
    1382             : 
    1383       25789 :                 req->recv_handler(req, raw_packet, pkt);
    1384       25789 :                 return;
    1385             :         }
    1386             : 
    1387      586900 :         if (pkt->ptype == DCERPC_PKT_FAULT) {
    1388        2567 :                 status = dcerpc_fault_to_nt_status(pkt->u.fault.status);
    1389        2567 :                 DEBUG(5,("rpc fault: %s\n", dcerpc_errstr(c, pkt->u.fault.status)));
    1390        2567 :                 if (NT_STATUS_EQUAL(status, NT_STATUS_RPC_PROTOCOL_ERROR)) {
    1391           9 :                         dcerpc_connection_dead(c, status);
    1392           9 :                         return;
    1393             :                 }
    1394        2558 :                 if (NT_STATUS_EQUAL(status, NT_STATUS_RPC_SEC_PKG_ERROR)) {
    1395           0 :                         dcerpc_connection_dead(c, status);
    1396           0 :                         return;
    1397             :                 }
    1398        2558 :                 req->fault_code = pkt->u.fault.status;
    1399        2558 :                 req->status = NT_STATUS_NET_WRITE_FAULT;
    1400        2558 :                 goto req_done;
    1401             :         }
    1402             : 
    1403      584333 :         if (pkt->ptype != DCERPC_PKT_RESPONSE) {
    1404           0 :                 DEBUG(2,("Unexpected packet type %d in dcerpc response\n",
    1405             :                          (int)pkt->ptype)); 
    1406           0 :                 dcerpc_connection_dead(c, NT_STATUS_RPC_PROTOCOL_ERROR);
    1407           0 :                 return;
    1408             :         }
    1409             : 
    1410             :         /* now check the status from the auth routines, and if it failed then fail
    1411             :            this request accordingly */
    1412      584333 :         if (!NT_STATUS_IS_OK(status)) {
    1413           0 :                 dcerpc_connection_dead(c, status);
    1414           0 :                 return;
    1415             :         }
    1416             : 
    1417      584333 :         length = pkt->u.response.stub_and_verifier.length;
    1418             : 
    1419      584333 :         if (req->payload.length + length > c->max_total_response_size) {
    1420           0 :                 DEBUG(2,("Unexpected total payload 0x%X > 0x%X dcerpc response\n",
    1421             :                          (unsigned)req->payload.length + length,
    1422             :                          (unsigned)c->max_total_response_size));
    1423           0 :                 dcerpc_connection_dead(c, NT_STATUS_RPC_PROTOCOL_ERROR);
    1424           0 :                 return;
    1425             :         }
    1426             : 
    1427      584333 :         if (length > 0) {
    1428      584064 :                 req->payload.data = talloc_realloc(req, 
    1429             :                                                    req->payload.data, 
    1430             :                                                    uint8_t,
    1431             :                                                    req->payload.length + length);
    1432      584064 :                 if (!req->payload.data) {
    1433           0 :                         req->status = NT_STATUS_NO_MEMORY;
    1434           0 :                         goto req_done;
    1435             :                 }
    1436      584064 :                 memcpy(req->payload.data+req->payload.length, 
    1437      584064 :                        pkt->u.response.stub_and_verifier.data, length);
    1438      584064 :                 req->payload.length += length;
    1439             :         }
    1440             : 
    1441      584333 :         if (!(pkt->pfc_flags & DCERPC_PFC_FLAG_LAST)) {
    1442      289695 :                 data_blob_free(raw_packet);
    1443      289695 :                 dcerpc_send_read(c);
    1444      289695 :                 return;
    1445             :         }
    1446             : 
    1447      294638 :         if (req->verify_bitmask1) {
    1448        7952 :                 req->p->conn->security_state.verified_bitmask1 = true;
    1449             :         }
    1450      294638 :         if (req->verify_pcontext) {
    1451        7959 :                 req->p->verified_pcontext = true;
    1452             :         }
    1453             : 
    1454      294638 :         if (!(pkt->drep[0] & DCERPC_DREP_LE)) {
    1455           0 :                 req->flags |= DCERPC_PULL_BIGENDIAN;
    1456             :         } else {
    1457      294638 :                 req->flags &= ~DCERPC_PULL_BIGENDIAN;
    1458             :         }
    1459             : 
    1460      297196 : req_done:
    1461      297196 :         data_blob_free(raw_packet);
    1462             : 
    1463             :         /* we've got the full payload */
    1464      297196 :         dcerpc_req_dequeue(req);
    1465      297196 :         req->state = RPC_REQUEST_DONE;
    1466             : 
    1467             :         /*
    1468             :          * We have to look at shipping further requests before calling
    1469             :          * the async function, that one might close the pipe
    1470             :          */
    1471      297196 :         dcerpc_schedule_io_trigger(c);
    1472             : 
    1473      297196 :         if (req->async.callback) {
    1474      297196 :                 req->async.callback(req);
    1475             :         }
    1476             : }
    1477             : 
    1478             : static NTSTATUS dcerpc_request_prepare_vt(struct rpc_request *req);
    1479             : 
    1480             : /*
    1481             :   perform the send side of a async dcerpc request
    1482             : */
    1483      297239 : static struct rpc_request *dcerpc_request_send(TALLOC_CTX *mem_ctx,
    1484             :                                                struct dcerpc_pipe *p,
    1485             :                                                const struct GUID *object,
    1486             :                                                uint16_t opnum,
    1487             :                                                DATA_BLOB *stub_data)
    1488             : {
    1489        7135 :         struct rpc_request *req;
    1490        7135 :         NTSTATUS status;
    1491             : 
    1492      297239 :         req = talloc_zero(mem_ctx, struct rpc_request);
    1493      297239 :         if (req == NULL) {
    1494           0 :                 return NULL;
    1495             :         }
    1496             : 
    1497      297239 :         req->p = p;
    1498      297239 :         req->call_id = next_call_id(p->conn);
    1499      297239 :         req->state = RPC_REQUEST_QUEUED;
    1500             : 
    1501      297239 :         if (object != NULL) {
    1502         262 :                 req->object = (struct GUID *)talloc_memdup(req, (const void *)object, sizeof(*object));
    1503         262 :                 if (req->object == NULL) {
    1504           0 :                         talloc_free(req);
    1505           0 :                         return NULL;
    1506             :                 }
    1507             :         }
    1508             : 
    1509      297239 :         req->opnum = opnum;
    1510      297239 :         req->request_data.length = stub_data->length;
    1511      297239 :         req->request_data.data = stub_data->data;
    1512             : 
    1513      297239 :         status = dcerpc_request_prepare_vt(req);
    1514      297239 :         if (!NT_STATUS_IS_OK(status)) {
    1515           0 :                 talloc_free(req);
    1516           0 :                 return NULL;
    1517             :         }
    1518             : 
    1519      297239 :         DLIST_ADD_END(p->conn->request_queue, req);
    1520      297239 :         talloc_set_destructor(req, dcerpc_req_dequeue);
    1521             : 
    1522      297239 :         dcerpc_schedule_io_trigger(p->conn);
    1523             : 
    1524      297239 :         if (p->request_timeout) {
    1525      297239 :                 tevent_add_timer(p->conn->event_ctx, req,
    1526             :                                 timeval_current_ofs(p->request_timeout, 0), 
    1527             :                                 dcerpc_timeout_handler, req);
    1528             :         }
    1529             : 
    1530      290104 :         return req;
    1531             : }
    1532             : 
    1533      297239 : static NTSTATUS dcerpc_request_prepare_vt(struct rpc_request *req)
    1534             : {
    1535      297239 :         struct dcecli_security *sec = &req->p->conn->security_state;
    1536        7135 :         struct dcerpc_sec_verification_trailer *t;
    1537      297239 :         struct dcerpc_sec_vt *c = NULL;
    1538      297239 :         struct ndr_push *ndr = NULL;
    1539        7135 :         enum ndr_err_code ndr_err;
    1540             : 
    1541      297239 :         if (sec->auth_level < DCERPC_AUTH_LEVEL_PACKET) {
    1542      202220 :                 return NT_STATUS_OK;
    1543             :         }
    1544             : 
    1545       95019 :         t = talloc_zero(req, struct dcerpc_sec_verification_trailer);
    1546       95019 :         if (t == NULL) {
    1547           0 :                 return NT_STATUS_NO_MEMORY;
    1548             :         }
    1549             : 
    1550       95019 :         if (!sec->verified_bitmask1) {
    1551        9142 :                 t->commands = talloc_realloc(t, t->commands,
    1552             :                                              struct dcerpc_sec_vt,
    1553             :                                              t->count.count + 1);
    1554        9142 :                 if (t->commands == NULL) {
    1555           0 :                         return NT_STATUS_NO_MEMORY;
    1556             :                 }
    1557        9142 :                 c = &t->commands[t->count.count++];
    1558        9142 :                 ZERO_STRUCTP(c);
    1559             : 
    1560        9142 :                 c->command = DCERPC_SEC_VT_COMMAND_BITMASK1;
    1561        9142 :                 if (req->p->conn->flags & DCERPC_PROPOSE_HEADER_SIGNING) {
    1562        9142 :                         c->u.bitmask1 = DCERPC_SEC_VT_CLIENT_SUPPORTS_HEADER_SIGNING;
    1563             :                 }
    1564        9142 :                 req->verify_bitmask1 = true;
    1565             :         }
    1566             : 
    1567       95019 :         if (!req->p->verified_pcontext) {
    1568        9149 :                 t->commands = talloc_realloc(t, t->commands,
    1569             :                                              struct dcerpc_sec_vt,
    1570             :                                              t->count.count + 1);
    1571        9149 :                 if (t->commands == NULL) {
    1572           0 :                         return NT_STATUS_NO_MEMORY;
    1573             :                 }
    1574        9149 :                 c = &t->commands[t->count.count++];
    1575        9149 :                 ZERO_STRUCTP(c);
    1576             : 
    1577        9149 :                 c->command = DCERPC_SEC_VT_COMMAND_PCONTEXT;
    1578        9149 :                 c->u.pcontext.abstract_syntax = req->p->syntax;
    1579        9149 :                 c->u.pcontext.transfer_syntax = req->p->transfer_syntax;
    1580             : 
    1581        9149 :                 req->verify_pcontext = true;
    1582             :         }
    1583             : 
    1584       95019 :         if (!(req->p->conn->flags & DCERPC_HEADER_SIGNING)) {
    1585        8166 :                 t->commands = talloc_realloc(t, t->commands,
    1586             :                                              struct dcerpc_sec_vt,
    1587             :                                              t->count.count + 1);
    1588        8166 :                 if (t->commands == NULL) {
    1589           0 :                         return NT_STATUS_NO_MEMORY;
    1590             :                 }
    1591        8166 :                 c = &t->commands[t->count.count++];
    1592        8166 :                 ZERO_STRUCTP(c);
    1593             : 
    1594        8166 :                 c->command = DCERPC_SEC_VT_COMMAND_HEADER2;
    1595        8166 :                 c->u.header2.ptype = DCERPC_PKT_REQUEST;
    1596        8166 :                 if (req->p->conn->flags & DCERPC_PUSH_BIGENDIAN) {
    1597         168 :                         c->u.header2.drep[0] = 0;
    1598             :                 } else {
    1599        7998 :                         c->u.header2.drep[0] = DCERPC_DREP_LE;
    1600             :                 }
    1601        8166 :                 c->u.header2.drep[1] = 0;
    1602        8166 :                 c->u.header2.drep[2] = 0;
    1603        8166 :                 c->u.header2.drep[3] = 0;
    1604        8166 :                 c->u.header2.call_id = req->call_id;
    1605        8166 :                 c->u.header2.context_id = req->p->context_id;
    1606        8166 :                 c->u.header2.opnum = req->opnum;
    1607             :         }
    1608             : 
    1609       95019 :         if (t->count.count == 0) {
    1610       78206 :                 TALLOC_FREE(t);
    1611       78206 :                 return NT_STATUS_OK;
    1612             :         }
    1613             : 
    1614       16813 :         c = &t->commands[t->count.count - 1];
    1615       16813 :         c->command |= DCERPC_SEC_VT_COMMAND_END;
    1616             : 
    1617       16813 :         if (DEBUGLEVEL >= 10) {
    1618           0 :                 NDR_PRINT_DEBUG(dcerpc_sec_verification_trailer, t);
    1619             :         }
    1620             : 
    1621       16813 :         ndr = ndr_push_init_ctx(req);
    1622       16813 :         if (ndr == NULL) {
    1623           0 :                 return NT_STATUS_NO_MEMORY;
    1624             :         }
    1625             : 
    1626             :         /*
    1627             :          * for now we just copy and append
    1628             :          */
    1629             : 
    1630       17421 :         ndr_err = ndr_push_bytes(ndr, req->request_data.data,
    1631       16813 :                                  req->request_data.length);
    1632       16813 :         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
    1633           0 :                 return ndr_map_error2ntstatus(ndr_err);
    1634             :         }
    1635             : 
    1636       16813 :         ndr_err = ndr_push_dcerpc_sec_verification_trailer(ndr,
    1637             :                                                 NDR_SCALARS | NDR_BUFFERS,
    1638             :                                                 t);
    1639       16813 :         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
    1640           0 :                 return ndr_map_error2ntstatus(ndr_err);
    1641             :         }
    1642       16813 :         req->request_data = ndr_push_blob(ndr);
    1643             : 
    1644       16813 :         return NT_STATUS_OK;
    1645             : }
    1646             : 
    1647             : /*
    1648             :   Send a request using the transport
    1649             : */
    1650             : 
    1651      593702 : static void dcerpc_ship_next_request(struct dcecli_connection *c)
    1652             : {
    1653       14270 :         struct rpc_request *req;
    1654       14270 :         struct dcerpc_pipe *p;
    1655       14270 :         DATA_BLOB *stub_data;
    1656       14270 :         struct ncacn_packet pkt;
    1657       14270 :         DATA_BLOB blob;
    1658       14270 :         uint32_t remaining, chunk_size;
    1659      593702 :         bool first_packet = true;
    1660      593702 :         size_t sig_size = 0;
    1661      593702 :         bool need_async = false;
    1662      593702 :         bool can_async = true;
    1663             : 
    1664      593702 :         req = c->request_queue;
    1665      593702 :         if (req == NULL) {
    1666      296463 :                 return;
    1667             :         }
    1668             : 
    1669      297239 :         p = req->p;
    1670      297239 :         stub_data = &req->request_data;
    1671             : 
    1672      297239 :         if (c->pending) {
    1673         780 :                 need_async = true;
    1674             :         }
    1675             : 
    1676      297239 :         if (c->security_state.auth_level >= DCERPC_AUTH_LEVEL_PACKET) {
    1677       95019 :                 can_async = gensec_have_feature(c->security_state.generic_state,
    1678             :                                                 GENSEC_FEATURE_ASYNC_REPLIES);
    1679             :         }
    1680             : 
    1681      297239 :         if (need_async && !can_async) {
    1682           0 :                 req->wait_for_sync = true;
    1683           0 :                 return;
    1684             :         }
    1685             : 
    1686      297239 :         DLIST_REMOVE(c->request_queue, req);
    1687      297239 :         DLIST_ADD(c->pending, req);
    1688      297239 :         req->state = RPC_REQUEST_PENDING;
    1689             : 
    1690      297239 :         init_ncacn_hdr(p->conn, &pkt);
    1691             : 
    1692      297239 :         remaining = stub_data->length;
    1693             : 
    1694             :         /* we can write a full max_recv_frag size, minus the dcerpc
    1695             :            request header size */
    1696      297239 :         chunk_size = p->conn->srv_max_recv_frag;
    1697      297239 :         chunk_size -= DCERPC_REQUEST_LENGTH;
    1698      297239 :         if (c->security_state.auth_level >= DCERPC_AUTH_LEVEL_PACKET) {
    1699       95019 :                 size_t max_payload = chunk_size;
    1700             : 
    1701       95019 :                 max_payload -= DCERPC_AUTH_TRAILER_LENGTH;
    1702       95019 :                 max_payload -= (max_payload % DCERPC_AUTH_PAD_ALIGNMENT);
    1703             : 
    1704       95019 :                 sig_size = gensec_sig_size(c->security_state.generic_state,
    1705             :                                            max_payload);
    1706       95019 :                 if (sig_size) {
    1707       95019 :                         chunk_size -= DCERPC_AUTH_TRAILER_LENGTH;
    1708       95019 :                         chunk_size -= sig_size;
    1709             :                 }
    1710             :         }
    1711      297239 :         chunk_size -= (chunk_size % DCERPC_AUTH_PAD_ALIGNMENT);
    1712             : 
    1713      297239 :         pkt.ptype = DCERPC_PKT_REQUEST;
    1714      297239 :         pkt.call_id = req->call_id;
    1715      297239 :         pkt.auth_length = 0;
    1716      297239 :         pkt.pfc_flags = 0;
    1717      297239 :         pkt.u.request.context_id = p->context_id;
    1718      297239 :         pkt.u.request.opnum = req->opnum;
    1719             : 
    1720      297239 :         if (req->object) {
    1721         262 :                 pkt.u.request.object.object = *req->object;
    1722         262 :                 pkt.pfc_flags |= DCERPC_PFC_FLAG_OBJECT_UUID;
    1723         262 :                 chunk_size -= ndr_size_GUID(req->object,0);
    1724             :         }
    1725             : 
    1726             :         /* we send a series of pdus without waiting for a reply */
    1727      608081 :         while (remaining > 0 || first_packet) {
    1728      310842 :                 uint32_t chunk = MIN(chunk_size, remaining);
    1729      310842 :                 bool last_frag = false;
    1730      310842 :                 bool do_trans = false;
    1731             : 
    1732      310842 :                 first_packet = false;
    1733      310842 :                 pkt.pfc_flags &= ~(DCERPC_PFC_FLAG_FIRST |DCERPC_PFC_FLAG_LAST);
    1734             : 
    1735      310842 :                 if (remaining == stub_data->length) {
    1736      297239 :                         pkt.pfc_flags |= DCERPC_PFC_FLAG_FIRST;
    1737             :                 }
    1738      310842 :                 if (chunk == remaining) {
    1739      297239 :                         pkt.pfc_flags |= DCERPC_PFC_FLAG_LAST;
    1740      297239 :                         last_frag = true;
    1741             :                 }
    1742             : 
    1743      310842 :                 pkt.u.request.alloc_hint = remaining;
    1744      310842 :                 pkt.u.request.stub_and_verifier.data = stub_data->data + 
    1745      310842 :                         (stub_data->length - remaining);
    1746      310842 :                 pkt.u.request.stub_and_verifier.length = chunk;
    1747             : 
    1748      310842 :                 req->status = ncacn_push_request_sign(p->conn, &blob, req, sig_size, &pkt);
    1749      310842 :                 if (!NT_STATUS_IS_OK(req->status)) {
    1750           0 :                         req->state = RPC_REQUEST_DONE;
    1751           0 :                         DLIST_REMOVE(p->conn->pending, req);
    1752           0 :                         return;
    1753             :                 }
    1754             : 
    1755      310842 :                 if (last_frag && !need_async) {
    1756      296459 :                         do_trans = true;
    1757             :                 }
    1758             : 
    1759      310842 :                 req->status = dcerpc_send_request(p->conn, &blob, do_trans);
    1760      310842 :                 if (!NT_STATUS_IS_OK(req->status)) {
    1761           0 :                         req->state = RPC_REQUEST_DONE;
    1762           0 :                         DLIST_REMOVE(p->conn->pending, req);
    1763           0 :                         return;
    1764             :                 }               
    1765             : 
    1766      310842 :                 if (last_frag && !do_trans) {
    1767         780 :                         req->status = dcerpc_send_read(p->conn);
    1768         780 :                         if (!NT_STATUS_IS_OK(req->status)) {
    1769           0 :                                 req->state = RPC_REQUEST_DONE;
    1770           0 :                                 DLIST_REMOVE(p->conn->pending, req);
    1771           0 :                                 return;
    1772             :                         }
    1773             :                 }
    1774             : 
    1775      310842 :                 remaining -= chunk;
    1776             :         }
    1777             : }
    1778             : 
    1779      593702 : static void dcerpc_io_trigger(struct tevent_context *ctx,
    1780             :                               struct tevent_immediate *im,
    1781             :                               void *private_data)
    1782             : {
    1783       14270 :         struct dcecli_connection *c =
    1784      593702 :                 talloc_get_type_abort(private_data,
    1785             :                 struct dcecli_connection);
    1786             : 
    1787      593702 :         c->io_trigger_pending = false;
    1788             : 
    1789      593702 :         dcerpc_schedule_io_trigger(c);
    1790             : 
    1791      593702 :         dcerpc_ship_next_request(c);
    1792      593702 : }
    1793             : 
    1794     1213926 : static void dcerpc_schedule_io_trigger(struct dcecli_connection *c)
    1795             : {
    1796     1213926 :         if (c->dead) {
    1797           0 :                 return;
    1798             :         }
    1799             : 
    1800     1213926 :         if (c->request_queue == NULL) {
    1801      604194 :                 return;
    1802             :         }
    1803             : 
    1804      594478 :         if (c->request_queue->wait_for_sync && c->pending) {
    1805           0 :                 return;
    1806             :         }
    1807             : 
    1808      594478 :         if (c->io_trigger_pending) {
    1809         776 :                 return;
    1810             :         }
    1811             : 
    1812      593702 :         c->io_trigger_pending = true;
    1813             : 
    1814      593702 :         tevent_schedule_immediate(c->io_trigger,
    1815             :                                   c->event_ctx,
    1816             :                                   dcerpc_io_trigger,
    1817       29524 :                                   c);
    1818             : }
    1819             : 
    1820             : /*
    1821             :   perform the receive side of a async dcerpc request
    1822             : */
    1823      297239 : static NTSTATUS dcerpc_request_recv(struct rpc_request *req,
    1824             :                                     TALLOC_CTX *mem_ctx,
    1825             :                                     DATA_BLOB *stub_data)
    1826             : {
    1827        7135 :         NTSTATUS status;
    1828             : 
    1829      297239 :         while (req->state != RPC_REQUEST_DONE) {
    1830           0 :                 struct tevent_context *ctx = req->p->conn->event_ctx;
    1831           0 :                 if (tevent_loop_once(ctx) != 0) {
    1832           0 :                         return NT_STATUS_CONNECTION_DISCONNECTED;
    1833             :                 }
    1834             :         }
    1835      297239 :         *stub_data = req->payload;
    1836      297239 :         status = req->status;
    1837      297239 :         if (stub_data->data) {
    1838      294369 :                 stub_data->data = talloc_steal(mem_ctx, stub_data->data);
    1839             :         }
    1840      297239 :         if (NT_STATUS_EQUAL(status, NT_STATUS_NET_WRITE_FAULT)) {
    1841        2558 :                 req->p->last_fault_code = req->fault_code;
    1842             :         }
    1843      297239 :         talloc_unlink(talloc_parent(req), req);
    1844      297239 :         return status;
    1845             : }
    1846             : 
    1847             : /*
    1848             :   this is a paranoid NDR validator. For every packet we push onto the wire
    1849             :   we pull it back again, then push it again. Then we compare the raw NDR data
    1850             :   for that to the NDR we initially generated. If they don't match then we know
    1851             :   we must have a bug in either the pull or push side of our code
    1852             : */
    1853       24330 : static NTSTATUS dcerpc_ndr_validate_in(struct dcecli_connection *c, 
    1854             :                                        TALLOC_CTX *mem_ctx,
    1855             :                                        DATA_BLOB blob,
    1856             :                                        size_t struct_size,
    1857             :                                        ndr_push_flags_fn_t ndr_push,
    1858             :                                        ndr_pull_flags_fn_t ndr_pull)
    1859             : {
    1860        1585 :         void *st;
    1861        1585 :         struct ndr_pull *pull;
    1862        1585 :         struct ndr_push *push;
    1863        1585 :         DATA_BLOB blob2;
    1864        1585 :         enum ndr_err_code ndr_err;
    1865             : 
    1866       24330 :         st = talloc_size(mem_ctx, struct_size);
    1867       24330 :         if (!st) {
    1868           0 :                 return NT_STATUS_NO_MEMORY;
    1869             :         }
    1870             : 
    1871       24330 :         pull = ndr_pull_init_flags(c, &blob, mem_ctx);
    1872       24330 :         if (!pull) {
    1873           0 :                 return NT_STATUS_NO_MEMORY;
    1874             :         }
    1875       24330 :         pull->flags |= LIBNDR_FLAG_REF_ALLOC;
    1876             : 
    1877       24330 :         if (c->flags & DCERPC_PUSH_BIGENDIAN) {
    1878          12 :                 pull->flags |= LIBNDR_FLAG_BIGENDIAN;
    1879             :         }
    1880             : 
    1881       24330 :         if (c->flags & DCERPC_NDR64) {
    1882           0 :                 pull->flags |= LIBNDR_FLAG_NDR64;
    1883             :         }
    1884             : 
    1885       24330 :         ndr_err = ndr_pull(pull, NDR_IN, st);
    1886       24330 :         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
    1887           0 :                 NTSTATUS status = ndr_map_error2ntstatus(ndr_err);
    1888           0 :                 ndr_err = ndr_pull_error(pull, NDR_ERR_VALIDATE,
    1889             :                                          "failed input validation pull - %s",
    1890             :                                          nt_errstr(status));
    1891           0 :                 return ndr_map_error2ntstatus(ndr_err);
    1892             :         }
    1893             : 
    1894       24330 :         push = ndr_push_init_ctx(mem_ctx);
    1895       24330 :         if (!push) {
    1896           0 :                 return NT_STATUS_NO_MEMORY;
    1897             :         }       
    1898             : 
    1899       24330 :         if (c->flags & DCERPC_PUSH_BIGENDIAN) {
    1900          12 :                 push->flags |= LIBNDR_FLAG_BIGENDIAN;
    1901             :         }
    1902             : 
    1903       24330 :         if (c->flags & DCERPC_NDR64) {
    1904           0 :                 push->flags |= LIBNDR_FLAG_NDR64;
    1905             :         }
    1906             : 
    1907       24330 :         ndr_err = ndr_push(push, NDR_IN, st);
    1908       24330 :         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
    1909           0 :                 NTSTATUS status = ndr_map_error2ntstatus(ndr_err);
    1910           0 :                 ndr_err = ndr_pull_error(pull, NDR_ERR_VALIDATE,
    1911             :                                          "failed input validation push - %s",
    1912             :                                          nt_errstr(status));
    1913           0 :                 return ndr_map_error2ntstatus(ndr_err);
    1914             :         }
    1915             : 
    1916       24330 :         blob2 = ndr_push_blob(push);
    1917             : 
    1918       24330 :         if (data_blob_cmp(&blob, &blob2) != 0) {
    1919           0 :                 DEBUG(3,("original:\n"));
    1920           0 :                 dump_data(3, blob.data, blob.length);
    1921           0 :                 DEBUG(3,("secondary:\n"));
    1922           0 :                 dump_data(3, blob2.data, blob2.length);
    1923           0 :                 ndr_err = ndr_pull_error(pull, NDR_ERR_VALIDATE,
    1924             :                                          "failed input validation blobs doesn't match");
    1925           0 :                 return ndr_map_error2ntstatus(ndr_err);
    1926             :         }
    1927             : 
    1928       24330 :         return NT_STATUS_OK;
    1929             : }
    1930             : 
    1931             : /*
    1932             :   this is a paranoid NDR input validator. For every packet we pull
    1933             :   from the wire we push it back again then pull and push it
    1934             :   again. Then we compare the raw NDR data for that to the NDR we
    1935             :   initially generated. If they don't match then we know we must have a
    1936             :   bug in either the pull or push side of our code
    1937             : */
    1938       23724 : static NTSTATUS dcerpc_ndr_validate_out(struct dcecli_connection *c,
    1939             :                                         struct ndr_pull *pull_in,
    1940             :                                         void *struct_ptr,
    1941             :                                         size_t struct_size,
    1942             :                                         ndr_push_flags_fn_t ndr_push,
    1943             :                                         ndr_pull_flags_fn_t ndr_pull,
    1944             :                                         ndr_print_function_t ndr_print)
    1945             : {
    1946        1495 :         void *st;
    1947        1495 :         struct ndr_pull *pull;
    1948        1495 :         struct ndr_push *push;
    1949        1495 :         DATA_BLOB blob, blob2;
    1950       23724 :         TALLOC_CTX *mem_ctx = pull_in;
    1951        1495 :         char *s1, *s2;
    1952        1495 :         enum ndr_err_code ndr_err;
    1953             : 
    1954       23724 :         st = talloc_size(mem_ctx, struct_size);
    1955       23724 :         if (!st) {
    1956           0 :                 return NT_STATUS_NO_MEMORY;
    1957             :         }
    1958       23724 :         memcpy(st, struct_ptr, struct_size);
    1959             : 
    1960       23724 :         push = ndr_push_init_ctx(mem_ctx);
    1961       23724 :         if (!push) {
    1962           0 :                 return NT_STATUS_NO_MEMORY;
    1963             :         }       
    1964             : 
    1965       23724 :         ndr_err = ndr_push(push, NDR_OUT, struct_ptr);
    1966       23724 :         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
    1967           0 :                 NTSTATUS status = ndr_map_error2ntstatus(ndr_err);
    1968           0 :                 ndr_err = ndr_push_error(push, NDR_ERR_VALIDATE,
    1969             :                                          "failed output validation push - %s",
    1970             :                                          nt_errstr(status));
    1971           0 :                 return ndr_map_error2ntstatus(ndr_err);
    1972             :         }
    1973             : 
    1974       23724 :         blob = ndr_push_blob(push);
    1975             : 
    1976       23724 :         pull = ndr_pull_init_flags(c, &blob, mem_ctx);
    1977       23724 :         if (!pull) {
    1978           0 :                 return NT_STATUS_NO_MEMORY;
    1979             :         }
    1980             : 
    1981       23724 :         pull->flags |= LIBNDR_FLAG_REF_ALLOC;
    1982       23724 :         ndr_err = ndr_pull(pull, NDR_OUT, st);
    1983       23724 :         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
    1984           0 :                 NTSTATUS status = ndr_map_error2ntstatus(ndr_err);
    1985           0 :                 ndr_err = ndr_pull_error(pull, NDR_ERR_VALIDATE,
    1986             :                                          "failed output validation pull - %s",
    1987             :                                          nt_errstr(status));
    1988           0 :                 return ndr_map_error2ntstatus(ndr_err);
    1989             :         }
    1990             : 
    1991       23724 :         push = ndr_push_init_ctx(mem_ctx);
    1992       23724 :         if (!push) {
    1993           0 :                 return NT_STATUS_NO_MEMORY;
    1994             :         }       
    1995             : 
    1996       23724 :         ndr_err = ndr_push(push, NDR_OUT, st);
    1997       23724 :         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
    1998           0 :                 NTSTATUS status = ndr_map_error2ntstatus(ndr_err);
    1999           0 :                 ndr_err = ndr_push_error(push, NDR_ERR_VALIDATE,
    2000             :                                          "failed output validation push2 - %s",
    2001             :                                          nt_errstr(status));
    2002           0 :                 return ndr_map_error2ntstatus(ndr_err);
    2003             :         }
    2004             : 
    2005       23724 :         blob2 = ndr_push_blob(push);
    2006             : 
    2007       23724 :         if (data_blob_cmp(&blob, &blob2) != 0) {
    2008           0 :                 DEBUG(3,("original:\n"));
    2009           0 :                 dump_data(3, blob.data, blob.length);
    2010           0 :                 DEBUG(3,("secondary:\n"));
    2011           0 :                 dump_data(3, blob2.data, blob2.length);
    2012           0 :                 ndr_err = ndr_push_error(push, NDR_ERR_VALIDATE,
    2013             :                                          "failed output validation blobs doesn't match");
    2014           0 :                 return ndr_map_error2ntstatus(ndr_err);
    2015             :         }
    2016             : 
    2017             :         /* this checks the printed forms of the two structures, which effectively
    2018             :            tests all of the value() attributes */
    2019       23724 :         s1 = ndr_print_function_string(mem_ctx, ndr_print, "VALIDATE", 
    2020             :                                        NDR_OUT, struct_ptr);
    2021       23724 :         s2 = ndr_print_function_string(mem_ctx, ndr_print, "VALIDATE", 
    2022             :                                        NDR_OUT, st);
    2023       23724 :         if (strcmp(s1, s2) != 0) {
    2024             : #if 1
    2025           0 :                 DEBUG(3,("VALIDATE ERROR:\nWIRE:\n%s\n GEN:\n%s\n", s1, s2));
    2026             : #else
    2027             :                 /* this is sometimes useful */
    2028             :                 printf("VALIDATE ERROR\n");
    2029             :                 file_save("wire.dat", s1, strlen(s1));
    2030             :                 file_save("gen.dat", s2, strlen(s2));
    2031             :                 system("diff -u wire.dat gen.dat");
    2032             : #endif
    2033           0 :                 ndr_err = ndr_push_error(push, NDR_ERR_VALIDATE,
    2034             :                                          "failed output validation strings doesn't match");
    2035           0 :                 return ndr_map_error2ntstatus(ndr_err);
    2036             :         }
    2037             : 
    2038       23724 :         return NT_STATUS_OK;
    2039             : }
    2040             : 
    2041             : /*
    2042             :   a useful function for retrieving the server name we connected to
    2043             : */
    2044       15667 : _PUBLIC_ const char *dcerpc_server_name(struct dcerpc_pipe *p)
    2045             : {
    2046       15667 :         return p->conn ? p->conn->server_name : NULL;
    2047             : }
    2048             : 
    2049             : 
    2050             : /*
    2051             :   get the dcerpc auth_level for a open connection
    2052             : */
    2053        8227 : uint32_t dcerpc_auth_level(struct dcecli_connection *c) 
    2054             : {
    2055         422 :         uint8_t auth_level;
    2056             : 
    2057        8227 :         if (c->flags & DCERPC_SEAL) {
    2058        4879 :                 auth_level = DCERPC_AUTH_LEVEL_PRIVACY;
    2059        3079 :         } else if (c->flags & DCERPC_SIGN) {
    2060        2808 :                 auth_level = DCERPC_AUTH_LEVEL_INTEGRITY;
    2061         118 :         } else if (c->flags & DCERPC_PACKET) {
    2062          78 :                 auth_level = DCERPC_AUTH_LEVEL_PACKET;
    2063          40 :         } else if (c->flags & DCERPC_CONNECT) {
    2064          36 :                 auth_level = DCERPC_AUTH_LEVEL_CONNECT;
    2065             :         } else {
    2066           4 :                 auth_level = DCERPC_AUTH_LEVEL_NONE;
    2067             :         }
    2068        8227 :         return auth_level;
    2069             : }
    2070             : 
    2071             : struct dcerpc_alter_context_state {
    2072             :         struct tevent_context *ev;
    2073             :         struct dcerpc_pipe *p;
    2074             : };
    2075             : 
    2076             : static void dcerpc_alter_context_fail_handler(struct rpc_request *subreq);
    2077             : static void dcerpc_alter_context_recv_handler(struct rpc_request *req,
    2078             :                                               DATA_BLOB *raw_packet,
    2079             :                                               struct ncacn_packet *pkt);
    2080             : 
    2081        5836 : struct tevent_req *dcerpc_alter_context_send(TALLOC_CTX *mem_ctx,
    2082             :                                              struct tevent_context *ev,
    2083             :                                              struct dcerpc_pipe *p,
    2084             :                                              const struct ndr_syntax_id *syntax,
    2085             :                                              const struct ndr_syntax_id *transfer_syntax)
    2086             : {
    2087         117 :         struct tevent_req *req;
    2088         117 :         struct dcerpc_alter_context_state *state;
    2089         117 :         struct ncacn_packet pkt;
    2090         117 :         DATA_BLOB blob;
    2091         117 :         NTSTATUS status;
    2092         117 :         struct rpc_request *subreq;
    2093         117 :         uint32_t flags;
    2094             : 
    2095        5836 :         req = tevent_req_create(mem_ctx, &state,
    2096             :                                 struct dcerpc_alter_context_state);
    2097        5836 :         if (req == NULL) {
    2098           0 :                 return NULL;
    2099             :         }
    2100             : 
    2101        5836 :         state->ev = ev;
    2102        5836 :         state->p = p;
    2103             : 
    2104        5836 :         p->syntax = *syntax;
    2105        5836 :         p->transfer_syntax = *transfer_syntax;
    2106             : 
    2107        5836 :         flags = dcerpc_binding_get_flags(p->binding);
    2108             : 
    2109        5836 :         init_ncacn_hdr(p->conn, &pkt);
    2110             : 
    2111        5836 :         pkt.ptype = DCERPC_PKT_ALTER;
    2112        5836 :         pkt.pfc_flags = DCERPC_PFC_FLAG_FIRST | DCERPC_PFC_FLAG_LAST;
    2113        5836 :         pkt.call_id = p->conn->call_id;
    2114        5836 :         pkt.auth_length = 0;
    2115             : 
    2116        5836 :         if (flags & DCERPC_CONCURRENT_MULTIPLEX) {
    2117          10 :                 pkt.pfc_flags |= DCERPC_PFC_FLAG_CONC_MPX;
    2118             :         }
    2119             : 
    2120        5836 :         pkt.u.alter.max_xmit_frag = p->conn->srv_max_xmit_frag;
    2121        5836 :         pkt.u.alter.max_recv_frag = p->conn->srv_max_recv_frag;
    2122        5836 :         pkt.u.alter.assoc_group_id = dcerpc_binding_get_assoc_group_id(p->binding);
    2123        5836 :         pkt.u.alter.num_contexts = 1;
    2124        5836 :         pkt.u.alter.ctx_list = talloc_zero_array(state, struct dcerpc_ctx_list,
    2125             :                                                  pkt.u.alter.num_contexts);
    2126        5836 :         if (tevent_req_nomem(pkt.u.alter.ctx_list, req)) {
    2127           0 :                 return tevent_req_post(req, ev);
    2128             :         }
    2129        5836 :         pkt.u.alter.ctx_list[0].context_id = p->context_id;
    2130        5836 :         pkt.u.alter.ctx_list[0].num_transfer_syntaxes = 1;
    2131        5836 :         pkt.u.alter.ctx_list[0].abstract_syntax = p->syntax;
    2132        5836 :         pkt.u.alter.ctx_list[0].transfer_syntaxes = &p->transfer_syntax;
    2133        5836 :         pkt.u.alter.auth_info = data_blob(NULL, 0);
    2134             : 
    2135             :         /* construct the NDR form of the packet */
    2136        5836 :         status = dcerpc_ncacn_push_auth(&blob,
    2137             :                                 state,
    2138             :                                 &pkt,
    2139        5836 :                                 p->conn->security_state.tmp_auth_info.out);
    2140        5836 :         if (tevent_req_nterror(req, status)) {
    2141           0 :                 return tevent_req_post(req, ev);
    2142             :         }
    2143             : 
    2144             :         /*
    2145             :          * we allocate a dcerpc_request so we can be in the same
    2146             :          * request queue as normal requests
    2147             :          */
    2148        5836 :         subreq = talloc_zero(state, struct rpc_request);
    2149        5836 :         if (tevent_req_nomem(subreq, req)) {
    2150           0 :                 return tevent_req_post(req, ev);
    2151             :         }
    2152             : 
    2153        5836 :         subreq->state = RPC_REQUEST_PENDING;
    2154        5836 :         subreq->call_id = pkt.call_id;
    2155        5836 :         subreq->async.private_data = req;
    2156        5836 :         subreq->async.callback = dcerpc_alter_context_fail_handler;
    2157        5836 :         subreq->p = p;
    2158        5836 :         subreq->recv_handler = dcerpc_alter_context_recv_handler;
    2159        5836 :         DLIST_ADD_END(p->conn->pending, subreq);
    2160        5836 :         talloc_set_destructor(subreq, dcerpc_req_dequeue);
    2161             : 
    2162        5836 :         status = dcerpc_send_request(p->conn, &blob, true);
    2163        5836 :         if (tevent_req_nterror(req, status)) {
    2164           0 :                 return tevent_req_post(req, ev);
    2165             :         }
    2166             : 
    2167        5836 :         tevent_add_timer(ev, subreq,
    2168             :                          timeval_current_ofs(DCERPC_REQUEST_TIMEOUT, 0),
    2169             :                          dcerpc_timeout_handler, subreq);
    2170             : 
    2171        5836 :         return req;
    2172             : }
    2173             : 
    2174           0 : static void dcerpc_alter_context_fail_handler(struct rpc_request *subreq)
    2175             : {
    2176           0 :         struct tevent_req *req =
    2177           0 :                 talloc_get_type_abort(subreq->async.private_data,
    2178             :                 struct tevent_req);
    2179           0 :         struct dcerpc_alter_context_state *state =
    2180           0 :                 tevent_req_data(req,
    2181             :                 struct dcerpc_alter_context_state);
    2182           0 :         NTSTATUS status = subreq->status;
    2183             : 
    2184           0 :         TALLOC_FREE(subreq);
    2185             : 
    2186             :         /*
    2187             :          * We trigger the callback in the next event run
    2188             :          * because the code in this file might trigger
    2189             :          * multiple request callbacks from within a single
    2190             :          * while loop.
    2191             :          *
    2192             :          * In order to avoid segfaults from within
    2193             :          * dcerpc_connection_dead() we call
    2194             :          * tevent_req_defer_callback().
    2195             :          */
    2196           0 :         tevent_req_defer_callback(req, state->ev);
    2197             : 
    2198           0 :         tevent_req_nterror(req, status);
    2199           0 : }
    2200             : 
    2201        5836 : static void dcerpc_alter_context_recv_handler(struct rpc_request *subreq,
    2202             :                                               DATA_BLOB *raw_packet,
    2203             :                                               struct ncacn_packet *pkt)
    2204             : {
    2205         117 :         struct tevent_req *req =
    2206        5836 :                 talloc_get_type_abort(subreq->async.private_data,
    2207             :                 struct tevent_req);
    2208         117 :         struct dcerpc_alter_context_state *state =
    2209        5836 :                 tevent_req_data(req,
    2210             :                 struct dcerpc_alter_context_state);
    2211        5836 :         struct dcecli_connection *conn = state->p->conn;
    2212        5836 :         struct dcecli_security *sec = &conn->security_state;
    2213         117 :         NTSTATUS status;
    2214             : 
    2215             :         /*
    2216             :          * Note that pkt is allocated under raw_packet->data,
    2217             :          * while raw_packet->data is a child of subreq.
    2218             :          */
    2219        5836 :         talloc_steal(state, raw_packet->data);
    2220        5836 :         TALLOC_FREE(subreq);
    2221             : 
    2222             :         /*
    2223             :          * We trigger the callback in the next event run
    2224             :          * because the code in this file might trigger
    2225             :          * multiple request callbacks from within a single
    2226             :          * while loop.
    2227             :          *
    2228             :          * In order to avoid segfaults from within
    2229             :          * dcerpc_connection_dead() we call
    2230             :          * tevent_req_defer_callback().
    2231             :          */
    2232        5836 :         tevent_req_defer_callback(req, state->ev);
    2233             : 
    2234        5836 :         if (pkt->ptype == DCERPC_PKT_FAULT) {
    2235          15 :                 DEBUG(5,("dcerpc: alter_resp - rpc fault: %s\n",
    2236             :                          dcerpc_errstr(state, pkt->u.fault.status)));
    2237          15 :                 if (pkt->u.fault.status == DCERPC_FAULT_ACCESS_DENIED) {
    2238           0 :                         state->p->last_fault_code = pkt->u.fault.status;
    2239           0 :                         tevent_req_nterror(req, NT_STATUS_LOGON_FAILURE);
    2240          15 :                 } else if (pkt->u.fault.status == DCERPC_FAULT_SEC_PKG_ERROR) {
    2241           0 :                         state->p->last_fault_code = pkt->u.fault.status;
    2242           0 :                         tevent_req_nterror(req, NT_STATUS_LOGON_FAILURE);
    2243             :                 } else {
    2244          15 :                         state->p->last_fault_code = pkt->u.fault.status;
    2245          15 :                         status = dcerpc_fault_to_nt_status(pkt->u.fault.status);
    2246          15 :                         tevent_req_nterror(req, status);
    2247             :                 }
    2248          27 :                 return;
    2249             :         }
    2250             : 
    2251        5821 :         status = dcerpc_verify_ncacn_packet_header(pkt,
    2252             :                                         DCERPC_PKT_ALTER_RESP,
    2253             :                                         pkt->u.alter_resp.auth_info.length,
    2254             :                                         DCERPC_PFC_FLAG_FIRST |
    2255             :                                         DCERPC_PFC_FLAG_LAST,
    2256             :                                         DCERPC_PFC_FLAG_CONC_MPX |
    2257             :                                         DCERPC_PFC_FLAG_SUPPORT_HEADER_SIGN);
    2258        5821 :         if (!NT_STATUS_IS_OK(status)) {
    2259           0 :                 state->p->last_fault_code = DCERPC_NCA_S_PROTO_ERROR;
    2260           0 :                 tevent_req_nterror(req, NT_STATUS_NET_WRITE_FAULT);
    2261           0 :                 return;
    2262             :         }
    2263             : 
    2264        5821 :         if (pkt->u.alter_resp.num_results != 1) {
    2265           0 :                 state->p->last_fault_code = DCERPC_NCA_S_PROTO_ERROR;
    2266           0 :                 tevent_req_nterror(req, NT_STATUS_NET_WRITE_FAULT);
    2267           0 :                 return;
    2268             :         }
    2269             : 
    2270        5821 :         if (pkt->u.alter_resp.ctx_list[0].result != 0) {
    2271          15 :                 status = dcerpc_map_ack_reason(&pkt->u.alter_resp.ctx_list[0]);
    2272          15 :                 DEBUG(2,("dcerpc: alter_resp failed - reason %d - %s\n",
    2273             :                          pkt->u.alter_resp.ctx_list[0].reason.value,
    2274             :                          nt_errstr(status)));
    2275          15 :                 tevent_req_nterror(req, status);
    2276          15 :                 return;
    2277             :         }
    2278             : 
    2279             :         /* the alter_resp might contain a reply set of credentials */
    2280        5806 :         if (pkt->auth_length != 0 && sec->tmp_auth_info.in != NULL) {
    2281        5824 :                 status = dcerpc_pull_auth_trailer(pkt, sec->tmp_auth_info.mem,
    2282        5728 :                                                   &pkt->u.alter_resp.auth_info,
    2283             :                                                   sec->tmp_auth_info.in,
    2284             :                                                   NULL, true);
    2285        5728 :                 if (tevent_req_nterror(req, status)) {
    2286           0 :                         return;
    2287             :                 }
    2288             :         }
    2289             : 
    2290        5806 :         tevent_req_done(req);
    2291             : }
    2292             : 
    2293        5836 : NTSTATUS dcerpc_alter_context_recv(struct tevent_req *req)
    2294             : {
    2295        5836 :         return tevent_req_simple_recv_ntstatus(req);
    2296             : }
    2297             : 
    2298             : /* 
    2299             :    send a dcerpc alter_context request
    2300             : */
    2301         108 : _PUBLIC_ NTSTATUS dcerpc_alter_context(struct dcerpc_pipe *p, 
    2302             :                               TALLOC_CTX *mem_ctx,
    2303             :                               const struct ndr_syntax_id *syntax,
    2304             :                               const struct ndr_syntax_id *transfer_syntax)
    2305             : {
    2306          21 :         struct tevent_req *subreq;
    2307         108 :         struct tevent_context *ev = p->conn->event_ctx;
    2308          21 :         bool ok;
    2309             : 
    2310             :         /* TODO: create a new event context here */
    2311             : 
    2312         108 :         subreq = dcerpc_alter_context_send(mem_ctx, ev,
    2313             :                                            p, syntax, transfer_syntax);
    2314         108 :         if (subreq == NULL) {
    2315           0 :                 return NT_STATUS_NO_MEMORY;
    2316             :         }
    2317             : 
    2318         108 :         ok = tevent_req_poll(subreq, ev);
    2319         108 :         if (!ok) {
    2320           0 :                 NTSTATUS status;
    2321           0 :                 status = map_nt_error_from_unix_common(errno);
    2322           0 :                 return status;
    2323             :         }
    2324             : 
    2325         108 :         return dcerpc_alter_context_recv(subreq);
    2326             : }
    2327             : 
    2328          34 : static void dcerpc_transport_dead(struct dcecli_connection *c, NTSTATUS status)
    2329             : {
    2330          34 :         if (c->transport.stream == NULL) {
    2331           0 :                 return;
    2332             :         }
    2333             : 
    2334          34 :         tevent_queue_stop(c->transport.write_queue);
    2335          34 :         TALLOC_FREE(c->transport.read_subreq);
    2336          34 :         TALLOC_FREE(c->transport.stream);
    2337             : 
    2338          34 :         if (NT_STATUS_EQUAL(NT_STATUS_UNSUCCESSFUL, status)) {
    2339           0 :                 status = NT_STATUS_UNEXPECTED_NETWORK_ERROR;
    2340             :         }
    2341             : 
    2342          34 :         if (NT_STATUS_EQUAL(NT_STATUS_OK, status)) {
    2343           0 :                 status = NT_STATUS_END_OF_FILE;
    2344             :         }
    2345             : 
    2346          34 :         dcerpc_recv_data(c, NULL, status);
    2347             : }
    2348             : 
    2349             : 
    2350             : /*
    2351             :    shutdown SMB pipe connection
    2352             : */
    2353             : struct dcerpc_shutdown_pipe_state {
    2354             :         struct dcecli_connection *c;
    2355             :         NTSTATUS status;
    2356             : };
    2357             : 
    2358             : static void dcerpc_shutdown_pipe_done(struct tevent_req *subreq);
    2359             : 
    2360       31237 : static NTSTATUS dcerpc_shutdown_pipe(struct dcecli_connection *c, NTSTATUS status)
    2361             : {
    2362         870 :         struct dcerpc_shutdown_pipe_state *state;
    2363         870 :         struct tevent_req *subreq;
    2364             : 
    2365       31237 :         if (c->transport.stream == NULL) {
    2366       11296 :                 return NT_STATUS_OK;
    2367             :         }
    2368             : 
    2369       19941 :         state = talloc_zero(c, struct dcerpc_shutdown_pipe_state);
    2370       19941 :         if (state == NULL) {
    2371           0 :                 return NT_STATUS_NO_MEMORY;
    2372             :         }
    2373       19941 :         state->c = c;
    2374       19941 :         state->status = status;
    2375             : 
    2376       19941 :         subreq = tstream_disconnect_send(state, c->event_ctx, c->transport.stream);
    2377       19941 :         if (subreq == NULL) {
    2378           0 :                 return NT_STATUS_NO_MEMORY;
    2379             :         }
    2380       19941 :         tevent_req_set_callback(subreq, dcerpc_shutdown_pipe_done, state);
    2381             : 
    2382       19941 :         return status;
    2383             : }
    2384             : 
    2385           0 : static void dcerpc_shutdown_pipe_done(struct tevent_req *subreq)
    2386             : {
    2387           0 :         struct dcerpc_shutdown_pipe_state *state =
    2388           0 :                 tevent_req_callback_data(subreq, struct dcerpc_shutdown_pipe_state);
    2389           0 :         struct dcecli_connection *c = state->c;
    2390           0 :         NTSTATUS status = state->status;
    2391           0 :         int error;
    2392             : 
    2393             :         /*
    2394             :          * here we ignore the return values...
    2395             :          */
    2396           0 :         tstream_disconnect_recv(subreq, &error);
    2397           0 :         TALLOC_FREE(subreq);
    2398             : 
    2399           0 :         TALLOC_FREE(state);
    2400             : 
    2401           0 :         dcerpc_transport_dead(c, status);
    2402           0 : }
    2403             : 
    2404             : 
    2405             : 
    2406             : struct dcerpc_send_read_state {
    2407             :         struct dcecli_connection *p;
    2408             : };
    2409             : 
    2410      612723 : static int dcerpc_send_read_state_destructor(struct dcerpc_send_read_state *state)
    2411             : {
    2412      612723 :         struct dcecli_connection *p = state->p;
    2413             : 
    2414      612723 :         p->transport.read_subreq = NULL;
    2415             : 
    2416      612723 :         return 0;
    2417             : }
    2418             : 
    2419             : static void dcerpc_send_read_done(struct tevent_req *subreq);
    2420             : 
    2421      613503 : static NTSTATUS dcerpc_send_read(struct dcecli_connection *p)
    2422             : {
    2423        8203 :         struct dcerpc_send_read_state *state;
    2424             : 
    2425      613503 :         if (p->transport.read_subreq != NULL) {
    2426         780 :                 p->transport.pending_reads++;
    2427         780 :                 return NT_STATUS_OK;
    2428             :         }
    2429             : 
    2430      612723 :         state = talloc_zero(p, struct dcerpc_send_read_state);
    2431      612723 :         if (state == NULL) {
    2432           0 :                 return NT_STATUS_NO_MEMORY;
    2433             :         }
    2434      612723 :         state->p = p;
    2435             : 
    2436      612723 :         talloc_set_destructor(state, dcerpc_send_read_state_destructor);
    2437             : 
    2438      612723 :         p->transport.read_subreq = dcerpc_read_ncacn_packet_send(state,
    2439             :                                                           p->event_ctx,
    2440             :                                                           p->transport.stream);
    2441      612723 :         if (p->transport.read_subreq == NULL) {
    2442           0 :                 return NT_STATUS_NO_MEMORY;
    2443             :         }
    2444      612723 :         tevent_req_set_callback(p->transport.read_subreq, dcerpc_send_read_done, state);
    2445             : 
    2446      612723 :         return NT_STATUS_OK;
    2447             : }
    2448             : 
    2449      612692 : static void dcerpc_send_read_done(struct tevent_req *subreq)
    2450             : {
    2451        8200 :         struct dcerpc_send_read_state *state =
    2452      612692 :                 tevent_req_callback_data(subreq,
    2453             :                                          struct dcerpc_send_read_state);
    2454      612692 :         struct dcecli_connection *p = state->p;
    2455        8200 :         NTSTATUS status;
    2456        8200 :         struct ncacn_packet *pkt;
    2457        8200 :         DATA_BLOB blob;
    2458             : 
    2459      612692 :         status = dcerpc_read_ncacn_packet_recv(subreq, state,
    2460             :                                                &pkt, &blob);
    2461      612692 :         TALLOC_FREE(subreq);
    2462      612692 :         if (!NT_STATUS_IS_OK(status)) {
    2463           3 :                 TALLOC_FREE(state);
    2464           3 :                 dcerpc_transport_dead(p, status);
    2465           3 :                 return;
    2466             :         }
    2467             : 
    2468             :         /*
    2469             :          * here we steal into thet connection context,
    2470             :          * but p->transport.recv_data() will steal or free it again
    2471             :          */
    2472      612689 :         talloc_steal(p, blob.data);
    2473      612689 :         TALLOC_FREE(state);
    2474             : 
    2475      612689 :         if (p->transport.pending_reads > 0) {
    2476         780 :                 p->transport.pending_reads--;
    2477             : 
    2478         780 :                 status = dcerpc_send_read(p);
    2479         780 :                 if (!NT_STATUS_IS_OK(status)) {
    2480           0 :                         dcerpc_transport_dead(p, status);
    2481           0 :                         return;
    2482             :                 }
    2483             :         }
    2484             : 
    2485      612689 :         dcerpc_recv_data(p, &blob, NT_STATUS_OK);
    2486             : }
    2487             : 
    2488             : struct dcerpc_send_request_state {
    2489             :         struct dcecli_connection *p;
    2490             :         DATA_BLOB blob;
    2491             :         struct iovec iov;
    2492             : };
    2493             : 
    2494           0 : static int dcerpc_send_request_state_destructor(struct dcerpc_send_request_state *state)
    2495             : {
    2496           0 :         struct dcecli_connection *p = state->p;
    2497             : 
    2498           0 :         p->transport.read_subreq = NULL;
    2499             : 
    2500           0 :         return 0;
    2501             : }
    2502             : 
    2503             : static void dcerpc_send_request_wait_done(struct tevent_req *subreq);
    2504             : static void dcerpc_send_request_done(struct tevent_req *subreq);
    2505             : 
    2506      336816 : static NTSTATUS dcerpc_send_request(struct dcecli_connection *p, DATA_BLOB *data,
    2507             :                                     bool trigger_read)
    2508             : {
    2509        8204 :         struct dcerpc_send_request_state *state;
    2510        8204 :         struct tevent_req *subreq;
    2511      336816 :         bool use_trans = trigger_read;
    2512             : 
    2513      336816 :         if (p->transport.stream == NULL) {
    2514           0 :                 return NT_STATUS_CONNECTION_DISCONNECTED;
    2515             :         }
    2516             : 
    2517      336816 :         state = talloc_zero(p, struct dcerpc_send_request_state);
    2518      336816 :         if (state == NULL) {
    2519           0 :                 return NT_STATUS_NO_MEMORY;
    2520             :         }
    2521      336816 :         state->p = p;
    2522             : 
    2523      336816 :         state->blob = data_blob_talloc(state, data->data, data->length);
    2524      336816 :         if (state->blob.data == NULL) {
    2525           0 :                 TALLOC_FREE(state);
    2526           0 :                 return NT_STATUS_NO_MEMORY;
    2527             :         }
    2528      336816 :         state->iov.iov_base = (void *)state->blob.data;
    2529      336816 :         state->iov.iov_len = state->blob.length;
    2530             : 
    2531      336816 :         if (p->transport.read_subreq != NULL) {
    2532         780 :                 use_trans = false;
    2533             :         }
    2534             : 
    2535      336816 :         if (!tstream_is_smbXcli_np(p->transport.stream)) {
    2536       78561 :                 use_trans = false;
    2537             :         }
    2538             : 
    2539      335935 :         if (use_trans) {
    2540             :                 /*
    2541             :                  * we need to block reads until our write is
    2542             :                  * the next in the write queue.
    2543             :                  */
    2544      249434 :                 p->transport.read_subreq = tevent_queue_wait_send(state, p->event_ctx,
    2545             :                                                              p->transport.write_queue);
    2546      249434 :                 if (p->transport.read_subreq == NULL) {
    2547           0 :                         TALLOC_FREE(state);
    2548           0 :                         return NT_STATUS_NO_MEMORY;
    2549             :                 }
    2550      249434 :                 tevent_req_set_callback(p->transport.read_subreq,
    2551             :                                         dcerpc_send_request_wait_done,
    2552             :                                         state);
    2553             : 
    2554      249434 :                 talloc_set_destructor(state, dcerpc_send_request_state_destructor);
    2555             : 
    2556      249434 :                 trigger_read = false;
    2557             :         }
    2558             : 
    2559      345020 :         subreq = tstream_writev_queue_send(state, p->event_ctx,
    2560             :                                            p->transport.stream,
    2561             :                                            p->transport.write_queue,
    2562      336816 :                                            &state->iov, 1);
    2563      336816 :         if (subreq == NULL) {
    2564           0 :                 TALLOC_FREE(state);
    2565           0 :                 return NT_STATUS_NO_MEMORY;
    2566             :         }
    2567      336816 :         tevent_req_set_callback(subreq, dcerpc_send_request_done, state);
    2568             : 
    2569      336816 :         if (trigger_read) {
    2570       72814 :                 dcerpc_send_read(p);
    2571             :         }
    2572             : 
    2573      336816 :         return NT_STATUS_OK;
    2574             : }
    2575             : 
    2576      249434 : static void dcerpc_send_request_wait_done(struct tevent_req *subreq)
    2577             : {
    2578        7276 :         struct dcerpc_send_request_state *state =
    2579      249434 :                 tevent_req_callback_data(subreq,
    2580             :                 struct dcerpc_send_request_state);
    2581      249434 :         struct dcecli_connection *p = state->p;
    2582        7276 :         NTSTATUS status;
    2583        7276 :         bool ok;
    2584             : 
    2585      249434 :         p->transport.read_subreq = NULL;
    2586      249434 :         talloc_set_destructor(state, NULL);
    2587             : 
    2588      249434 :         ok = tevent_queue_wait_recv(subreq);
    2589      249434 :         if (!ok) {
    2590           0 :                 TALLOC_FREE(state);
    2591           0 :                 dcerpc_transport_dead(p, NT_STATUS_NO_MEMORY);
    2592           0 :                 return;
    2593             :         }
    2594             : 
    2595      249434 :         if (tevent_queue_length(p->transport.write_queue) <= 2) {
    2596      249388 :                 status = tstream_smbXcli_np_use_trans(p->transport.stream);
    2597      249388 :                 if (!NT_STATUS_IS_OK(status)) {
    2598           0 :                         TALLOC_FREE(state);
    2599           0 :                         dcerpc_transport_dead(p, status);
    2600           0 :                         return;
    2601             :                 }
    2602             :         }
    2603             : 
    2604             :         /* we free subreq after tstream_cli_np_use_trans */
    2605      249434 :         TALLOC_FREE(subreq);
    2606             : 
    2607      249434 :         dcerpc_send_read(p);
    2608             : }
    2609             : 
    2610      336796 : static void dcerpc_send_request_done(struct tevent_req *subreq)
    2611             : {
    2612        8204 :         struct dcerpc_send_request_state *state =
    2613      336796 :                 tevent_req_callback_data(subreq,
    2614             :                 struct dcerpc_send_request_state);
    2615        8204 :         int ret;
    2616        8204 :         int error;
    2617             : 
    2618      336796 :         ret = tstream_writev_queue_recv(subreq, &error);
    2619      336796 :         TALLOC_FREE(subreq);
    2620      336796 :         if (ret == -1) {
    2621          31 :                 struct dcecli_connection *p = state->p;
    2622          31 :                 NTSTATUS status = map_nt_error_from_unix_common(error);
    2623             : 
    2624          31 :                 TALLOC_FREE(state);
    2625          31 :                 dcerpc_transport_dead(p, status);
    2626          31 :                 return;
    2627             :         }
    2628             : 
    2629      336765 :         TALLOC_FREE(state);
    2630             : }

Generated by: LCOV version 1.14