LCOV - code coverage report
Current view: top level - source4/librpc/rpc - dcerpc.c (source / functions) Hit Total Coverage
Test: coverage report for master 6248eab5 Lines: 844 1126 75.0 %
Date: 2021-08-25 13:27:56 Functions: 57 64 89.1 %

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

Generated by: LCOV version 1.13