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

Generated by: LCOV version 1.14