LCOV - code coverage report
Current view: top level - source3/rpc_client - cli_pipe.c (source / functions) Hit Total Coverage
Test: coverage report for master 98b443d9 Lines: 1058 1656 63.9 %
Date: 2024-05-31 13:13:24 Functions: 75 78 96.2 %

          Line data    Source code
       1             : /*
       2             :  *  Unix SMB/CIFS implementation.
       3             :  *  RPC Pipe client routines
       4             :  *  Largely rewritten by Jeremy Allison             2005.
       5             :  *  Heavily modified by Simo Sorce                  2010.
       6             :  *  Copyright Andrew Bartlett                       2011.
       7             :  *
       8             :  *  This program is free software; you can redistribute it and/or modify
       9             :  *  it under the terms of the GNU General Public License as published by
      10             :  *  the Free Software Foundation; either version 3 of the License, or
      11             :  *  (at your option) any later version.
      12             :  *
      13             :  *  This program is distributed in the hope that it will be useful,
      14             :  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
      15             :  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      16             :  *  GNU General Public License for more details.
      17             :  *
      18             :  *  You should have received a copy of the GNU General Public License
      19             :  *  along with this program; if not, see <http://www.gnu.org/licenses/>.
      20             :  */
      21             : 
      22             : #include "includes.h"
      23             : #include "libsmb/namequery.h"
      24             : #include "../lib/util/tevent_ntstatus.h"
      25             : #include "librpc/gen_ndr/ndr_epmapper_c.h"
      26             : #include "../librpc/gen_ndr/ndr_dssetup.h"
      27             : #include "../libcli/auth/schannel.h"
      28             : #include "../libcli/auth/netlogon_creds_cli.h"
      29             : #include "auth_generic.h"
      30             : #include "librpc/gen_ndr/ndr_dcerpc.h"
      31             : #include "librpc/gen_ndr/ndr_netlogon_c.h"
      32             : #include "librpc/gen_ndr/auth.h"
      33             : #include "librpc/rpc/dcerpc.h"
      34             : #include "librpc/rpc/dcerpc_util.h"
      35             : #include "rpc_dce.h"
      36             : #include "cli_pipe.h"
      37             : #include "libsmb/libsmb.h"
      38             : #include "auth/gensec/gensec.h"
      39             : #include "auth/credentials/credentials.h"
      40             : #include "auth/auth_util.h"
      41             : #include "../libcli/smb/smbXcli_base.h"
      42             : #include "lib/tsocket/tsocket.h"
      43             : #include "libcli/named_pipe_auth/npa_tstream.h"
      44             : #include "librpc/gen_ndr/ndr_winreg.h"
      45             : #include "local_np.h"
      46             : 
      47             : #undef DBGC_CLASS
      48             : #define DBGC_CLASS DBGC_RPC_CLI
      49             : 
      50             : /********************************************************************
      51             :  Pipe description for a DEBUG
      52             :  ********************************************************************/
      53         328 : static const char *rpccli_pipe_txt(TALLOC_CTX *mem_ctx,
      54             :                                    struct rpc_pipe_client *cli)
      55             : {
      56         328 :         char *result = talloc_asprintf(mem_ctx, "host %s", cli->desthost);
      57         328 :         if (result == NULL) {
      58           0 :                 return "pipe";
      59             :         }
      60         328 :         return result;
      61             : }
      62             : 
      63             : /********************************************************************
      64             :  Rpc pipe call id.
      65             :  ********************************************************************/
      66             : 
      67      590274 : static uint32_t get_rpc_call_id(void)
      68             : {
      69           0 :         static uint32_t call_id = 0;
      70      590274 :         return ++call_id;
      71             : }
      72             : 
      73             : /*******************************************************************
      74             :  Use SMBreadX to get rest of one fragment's worth of rpc data.
      75             :  Reads the whole size or give an error message
      76             :  ********************************************************************/
      77             : 
      78             : struct rpc_read_state {
      79             :         struct tevent_context *ev;
      80             :         struct rpc_cli_transport *transport;
      81             :         uint8_t *data;
      82             :         size_t size;
      83             :         size_t num_read;
      84             : };
      85             : 
      86             : static void rpc_read_done(struct tevent_req *subreq);
      87             : 
      88      591205 : static struct tevent_req *rpc_read_send(TALLOC_CTX *mem_ctx,
      89             :                                         struct tevent_context *ev,
      90             :                                         struct rpc_cli_transport *transport,
      91             :                                         uint8_t *data, size_t size)
      92             : {
      93           0 :         struct tevent_req *req, *subreq;
      94           0 :         struct rpc_read_state *state;
      95             : 
      96      591205 :         req = tevent_req_create(mem_ctx, &state, struct rpc_read_state);
      97      591205 :         if (req == NULL) {
      98           0 :                 return NULL;
      99             :         }
     100      591205 :         state->ev = ev;
     101      591205 :         state->transport = transport;
     102      591205 :         state->data = data;
     103      591205 :         state->size = size;
     104      591205 :         state->num_read = 0;
     105             : 
     106      591205 :         DBG_INFO("data_to_read: %zu\n", size);
     107             : 
     108      591205 :         subreq = transport->read_send(state, ev, (uint8_t *)data, size,
     109             :                                       transport->priv);
     110      591205 :         if (subreq == NULL) {
     111           0 :                 goto fail;
     112             :         }
     113      591205 :         tevent_req_set_callback(subreq, rpc_read_done, req);
     114      591205 :         return req;
     115             : 
     116           0 :  fail:
     117           0 :         TALLOC_FREE(req);
     118           0 :         return NULL;
     119             : }
     120             : 
     121      591205 : static void rpc_read_done(struct tevent_req *subreq)
     122             : {
     123      591205 :         struct tevent_req *req = tevent_req_callback_data(
     124             :                 subreq, struct tevent_req);
     125      591205 :         struct rpc_read_state *state = tevent_req_data(
     126             :                 req, struct rpc_read_state);
     127           0 :         NTSTATUS status;
     128           0 :         ssize_t received;
     129             : 
     130      591205 :         status = state->transport->read_recv(subreq, &received);
     131      591205 :         TALLOC_FREE(subreq);
     132      591205 :         if (tevent_req_nterror(req, status)) {
     133      591205 :                 return;
     134             :         }
     135             : 
     136      591205 :         state->num_read += received;
     137      591205 :         if (state->num_read == state->size) {
     138      591205 :                 tevent_req_done(req);
     139      591205 :                 return;
     140             :         }
     141             : 
     142           0 :         subreq = state->transport->read_send(state, state->ev,
     143           0 :                                              state->data + state->num_read,
     144           0 :                                              state->size - state->num_read,
     145           0 :                                              state->transport->priv);
     146           0 :         if (tevent_req_nomem(subreq, req)) {
     147           0 :                 return;
     148             :         }
     149           0 :         tevent_req_set_callback(subreq, rpc_read_done, req);
     150             : }
     151             : 
     152      591205 : static NTSTATUS rpc_read_recv(struct tevent_req *req)
     153             : {
     154      591205 :         return tevent_req_simple_recv_ntstatus(req);
     155             : }
     156             : 
     157             : struct rpc_write_state {
     158             :         struct tevent_context *ev;
     159             :         struct rpc_cli_transport *transport;
     160             :         const uint8_t *data;
     161             :         size_t size;
     162             :         size_t num_written;
     163             : };
     164             : 
     165             : static void rpc_write_done(struct tevent_req *subreq);
     166             : 
     167      475014 : static struct tevent_req *rpc_write_send(TALLOC_CTX *mem_ctx,
     168             :                                          struct tevent_context *ev,
     169             :                                          struct rpc_cli_transport *transport,
     170             :                                          const uint8_t *data, size_t size)
     171             : {
     172           0 :         struct tevent_req *req, *subreq;
     173           0 :         struct rpc_write_state *state;
     174             : 
     175      475014 :         req = tevent_req_create(mem_ctx, &state, struct rpc_write_state);
     176      475014 :         if (req == NULL) {
     177           0 :                 return NULL;
     178             :         }
     179      475014 :         state->ev = ev;
     180      475014 :         state->transport = transport;
     181      475014 :         state->data = data;
     182      475014 :         state->size = size;
     183      475014 :         state->num_written = 0;
     184             : 
     185      475014 :         DBG_INFO("data_to_write: %zu\n", size);
     186             : 
     187      475014 :         subreq = transport->write_send(state, ev, data, size, transport->priv);
     188      475014 :         if (tevent_req_nomem(subreq, req)) {
     189           0 :                 return tevent_req_post(req, ev);
     190             :         }
     191      475014 :         tevent_req_set_callback(subreq, rpc_write_done, req);
     192      475014 :         return req;
     193             : }
     194             : 
     195      475014 : static void rpc_write_done(struct tevent_req *subreq)
     196             : {
     197      475014 :         struct tevent_req *req = tevent_req_callback_data(
     198             :                 subreq, struct tevent_req);
     199      475014 :         struct rpc_write_state *state = tevent_req_data(
     200             :                 req, struct rpc_write_state);
     201           0 :         NTSTATUS status;
     202           0 :         ssize_t written;
     203             : 
     204      475014 :         status = state->transport->write_recv(subreq, &written);
     205      475014 :         TALLOC_FREE(subreq);
     206      475014 :         if (tevent_req_nterror(req, status)) {
     207      475014 :                 return;
     208             :         }
     209             : 
     210      475014 :         state->num_written += written;
     211             : 
     212      475014 :         if (state->num_written == state->size) {
     213      475014 :                 tevent_req_done(req);
     214      475014 :                 return;
     215             :         }
     216             : 
     217           0 :         subreq = state->transport->write_send(state, state->ev,
     218           0 :                                               state->data + state->num_written,
     219           0 :                                               state->size - state->num_written,
     220           0 :                                               state->transport->priv);
     221           0 :         if (tevent_req_nomem(subreq, req)) {
     222           0 :                 return;
     223             :         }
     224           0 :         tevent_req_set_callback(subreq, rpc_write_done, req);
     225             : }
     226             : 
     227      475014 : static NTSTATUS rpc_write_recv(struct tevent_req *req)
     228             : {
     229      475014 :         return tevent_req_simple_recv_ntstatus(req);
     230             : }
     231             : 
     232             : 
     233             : /****************************************************************************
     234             :  Try and get a PDU's worth of data from current_pdu. If not, then read more
     235             :  from the wire.
     236             :  ****************************************************************************/
     237             : 
     238             : struct get_complete_frag_state {
     239             :         struct tevent_context *ev;
     240             :         struct rpc_pipe_client *cli;
     241             :         uint16_t frag_len;
     242             :         DATA_BLOB *pdu;
     243             : };
     244             : 
     245             : static void get_complete_frag_got_header(struct tevent_req *subreq);
     246             : static void get_complete_frag_got_rest(struct tevent_req *subreq);
     247             : 
     248      590819 : static struct tevent_req *get_complete_frag_send(TALLOC_CTX *mem_ctx,
     249             :                                                  struct tevent_context *ev,
     250             :                                                  struct rpc_pipe_client *cli,
     251             :                                                  DATA_BLOB *pdu)
     252             : {
     253           0 :         struct tevent_req *req, *subreq;
     254           0 :         struct get_complete_frag_state *state;
     255           0 :         size_t received;
     256             : 
     257      590819 :         req = tevent_req_create(mem_ctx, &state,
     258             :                                 struct get_complete_frag_state);
     259      590819 :         if (req == NULL) {
     260           0 :                 return NULL;
     261             :         }
     262      590819 :         state->ev = ev;
     263      590819 :         state->cli = cli;
     264      590819 :         state->frag_len = RPC_HEADER_LEN;
     265      590819 :         state->pdu = pdu;
     266             : 
     267      590819 :         received = pdu->length;
     268      590819 :         if (received < RPC_HEADER_LEN) {
     269         386 :                 if (!data_blob_realloc(mem_ctx, pdu, RPC_HEADER_LEN)) {
     270           0 :                         tevent_req_oom(req);
     271           0 :                         return tevent_req_post(req, ev);
     272             :                 }
     273         386 :                 subreq = rpc_read_send(state, state->ev,
     274         386 :                                         state->cli->transport,
     275         386 :                                         pdu->data + received,
     276             :                                         RPC_HEADER_LEN - received);
     277         386 :                 if (tevent_req_nomem(subreq, req)) {
     278           0 :                         return tevent_req_post(req, ev);
     279             :                 }
     280         386 :                 tevent_req_set_callback(subreq, get_complete_frag_got_header,
     281             :                                         req);
     282         386 :                 return req;
     283             :         }
     284             : 
     285      590433 :         state->frag_len = dcerpc_get_frag_length(pdu);
     286      590433 :         if (state->frag_len < RPC_HEADER_LEN) {
     287           0 :                 tevent_req_nterror(req, NT_STATUS_RPC_PROTOCOL_ERROR);
     288           0 :                 return tevent_req_post(req, ev);
     289             :         }
     290             : 
     291      590433 :         if (received >= state->frag_len) {
     292             :                 /*
     293             :                  * Got the whole fragment
     294             :                  */
     295           0 :                 tevent_req_done(req);
     296           0 :                 return tevent_req_post(req, ev);
     297             :         }
     298             : 
     299      590433 :         if (!data_blob_realloc(NULL, pdu, state->frag_len)) {
     300           0 :                 tevent_req_oom(req);
     301           0 :                 return tevent_req_post(req, ev);
     302             :         }
     303             : 
     304      590433 :         subreq = rpc_read_send(
     305             :                 state,
     306      590433 :                 state->ev,
     307      590433 :                 state->cli->transport,
     308      590433 :                 pdu->data + received,
     309      590433 :                 state->frag_len - received);
     310      590433 :         if (tevent_req_nomem(subreq, req)) {
     311           0 :                 return tevent_req_post(req, ev);
     312             :         }
     313      590433 :         tevent_req_set_callback(subreq, get_complete_frag_got_rest, req);
     314      590433 :         return req;
     315             : }
     316             : 
     317         386 : static void get_complete_frag_got_header(struct tevent_req *subreq)
     318             : {
     319         386 :         struct tevent_req *req = tevent_req_callback_data(
     320             :                 subreq, struct tevent_req);
     321         386 :         struct get_complete_frag_state *state = tevent_req_data(
     322             :                 req, struct get_complete_frag_state);
     323           0 :         NTSTATUS status;
     324             : 
     325         386 :         status = rpc_read_recv(subreq);
     326         386 :         TALLOC_FREE(subreq);
     327         386 :         if (tevent_req_nterror(req, status)) {
     328           0 :                 return;
     329             :         }
     330             : 
     331         386 :         state->frag_len = dcerpc_get_frag_length(state->pdu);
     332         386 :         if (state->frag_len < RPC_HEADER_LEN) {
     333           0 :                 tevent_req_nterror(req, NT_STATUS_RPC_PROTOCOL_ERROR);
     334           0 :                 return;
     335             :         }
     336             : 
     337         386 :         if (!data_blob_realloc(NULL, state->pdu, state->frag_len)) {
     338           0 :                 tevent_req_oom(req);
     339           0 :                 return;
     340             :         }
     341             : 
     342             :         /*
     343             :          * We're here in this piece of code because we've read exactly
     344             :          * RPC_HEADER_LEN bytes into state->pdu.
     345             :          */
     346             : 
     347         386 :         subreq = rpc_read_send(state, state->ev, state->cli->transport,
     348         386 :                                 state->pdu->data + RPC_HEADER_LEN,
     349         386 :                                 state->frag_len - RPC_HEADER_LEN);
     350         386 :         if (tevent_req_nomem(subreq, req)) {
     351           0 :                 return;
     352             :         }
     353         386 :         tevent_req_set_callback(subreq, get_complete_frag_got_rest, req);
     354             : }
     355             : 
     356      590819 : static void get_complete_frag_got_rest(struct tevent_req *subreq)
     357             : {
     358      590819 :         NTSTATUS status = rpc_read_recv(subreq);
     359      590819 :         return tevent_req_simple_finish_ntstatus(subreq, status);
     360             : }
     361             : 
     362      590819 : static NTSTATUS get_complete_frag_recv(struct tevent_req *req)
     363             : {
     364      590819 :         return tevent_req_simple_recv_ntstatus(req);
     365             : }
     366             : 
     367             : /****************************************************************************
     368             :  Do basic authentication checks on an incoming pdu.
     369             :  ****************************************************************************/
     370             : 
     371      590819 : static NTSTATUS cli_pipe_validate_current_pdu(TALLOC_CTX *mem_ctx,
     372             :                                                 struct rpc_pipe_client *cli,
     373             :                                                 struct ncacn_packet *pkt,
     374             :                                                 DATA_BLOB *pdu,
     375             :                                                 uint8_t expected_pkt_type,
     376             :                                                 uint32_t call_id,
     377             :                                                 DATA_BLOB *rdata,
     378             :                                                 DATA_BLOB *reply_pdu)
     379             : {
     380      590819 :         const struct dcerpc_response *r = NULL;
     381      590819 :         DATA_BLOB tmp_stub = { .data = NULL };
     382           0 :         NTSTATUS ret;
     383             : 
     384             :         /*
     385             :          * Point the return values at the real data including the RPC
     386             :          * header. Just in case the caller wants it.
     387             :          */
     388      590819 :         *rdata = *pdu;
     389             : 
     390      590819 :         if ((pkt->ptype == DCERPC_PKT_BIND_ACK) &&
     391       41679 :             !(pkt->pfc_flags & DCERPC_PFC_FLAG_LAST)) {
     392             :                 /*
     393             :                  * TODO: do we still need this hack which was introduced
     394             :                  * in commit a42afcdcc7ab9aa9ed193ae36d3dbb10843447f0.
     395             :                  *
     396             :                  * I don't even know what AS/U might be...
     397             :                  */
     398           0 :                 DEBUG(5, (__location__ ": bug in server (AS/U?), setting "
     399             :                           "fragment first/last ON.\n"));
     400           0 :                 pkt->pfc_flags |= DCERPC_PFC_FLAG_FIRST | DCERPC_PFC_FLAG_LAST;
     401             :         }
     402             : 
     403             :         /* Ensure we have the correct type. */
     404      590819 :         switch (pkt->ptype) {
     405           0 :         case DCERPC_PKT_BIND_NAK:
     406           0 :                 DEBUG(1, (__location__ ": Bind NACK received from %s!\n",
     407             :                           rpccli_pipe_txt(talloc_tos(), cli)));
     408             : 
     409           0 :                 ret = dcerpc_verify_ncacn_packet_header(pkt,
     410             :                                                 DCERPC_PKT_BIND_NAK,
     411             :                                                 0, /* max_auth_info */
     412             :                                                 DCERPC_PFC_FLAG_FIRST |
     413             :                                                 DCERPC_PFC_FLAG_LAST,
     414             :                                                 0); /* optional flags */
     415           0 :                 if (!NT_STATUS_IS_OK(ret)) {
     416           0 :                         DEBUG(1, (__location__ ": Connection to %s got an unexpected "
     417             :                                   "RPC packet type - %u, expected %u: %s\n",
     418             :                                   rpccli_pipe_txt(talloc_tos(), cli),
     419             :                                   pkt->ptype, expected_pkt_type,
     420             :                                   nt_errstr(ret)));
     421           0 :                         NDR_PRINT_DEBUG(ncacn_packet, pkt);
     422         222 :                         return ret;
     423             :                 }
     424             : 
     425             :                 /* Use this for now... */
     426           0 :                 return NT_STATUS_NETWORK_ACCESS_DENIED;
     427             : 
     428       41679 :         case DCERPC_PKT_BIND_ACK:
     429       41679 :                 ret = dcerpc_verify_ncacn_packet_header(pkt,
     430             :                                         expected_pkt_type,
     431             :                                         pkt->u.bind_ack.auth_info.length,
     432             :                                         DCERPC_PFC_FLAG_FIRST |
     433             :                                         DCERPC_PFC_FLAG_LAST,
     434             :                                         DCERPC_PFC_FLAG_CONC_MPX |
     435             :                                         DCERPC_PFC_FLAG_SUPPORT_HEADER_SIGN);
     436       41679 :                 if (!NT_STATUS_IS_OK(ret)) {
     437           0 :                         DEBUG(1, (__location__ ": Connection to %s got an unexpected "
     438             :                                   "RPC packet type - %u, expected %u: %s\n",
     439             :                                   rpccli_pipe_txt(talloc_tos(), cli),
     440             :                                   pkt->ptype, expected_pkt_type,
     441             :                                   nt_errstr(ret)));
     442           0 :                         NDR_PRINT_DEBUG(ncacn_packet, pkt);
     443           0 :                         return ret;
     444             :                 }
     445             : 
     446       41679 :                 break;
     447             : 
     448         159 :         case DCERPC_PKT_ALTER_RESP:
     449         159 :                 ret = dcerpc_verify_ncacn_packet_header(pkt,
     450             :                                         expected_pkt_type,
     451             :                                         pkt->u.alter_resp.auth_info.length,
     452             :                                         DCERPC_PFC_FLAG_FIRST |
     453             :                                         DCERPC_PFC_FLAG_LAST,
     454             :                                         DCERPC_PFC_FLAG_CONC_MPX |
     455             :                                         DCERPC_PFC_FLAG_SUPPORT_HEADER_SIGN);
     456         159 :                 if (!NT_STATUS_IS_OK(ret)) {
     457           0 :                         DEBUG(1, (__location__ ": Connection to %s got an unexpected "
     458             :                                   "RPC packet type - %u, expected %u: %s\n",
     459             :                                   rpccli_pipe_txt(talloc_tos(), cli),
     460             :                                   pkt->ptype, expected_pkt_type,
     461             :                                   nt_errstr(ret)));
     462           0 :                         NDR_PRINT_DEBUG(ncacn_packet, pkt);
     463           0 :                         return ret;
     464             :                 }
     465             : 
     466         159 :                 break;
     467             : 
     468      548759 :         case DCERPC_PKT_RESPONSE:
     469             : 
     470      548759 :                 r = &pkt->u.response;
     471             : 
     472      548759 :                 ret = dcerpc_verify_ncacn_packet_header(pkt,
     473             :                                                 expected_pkt_type,
     474      548759 :                                                 r->stub_and_verifier.length,
     475             :                                                 0, /* required_flags */
     476             :                                                 DCERPC_PFC_FLAG_FIRST |
     477             :                                                 DCERPC_PFC_FLAG_LAST);
     478      548759 :                 if (!NT_STATUS_IS_OK(ret)) {
     479           0 :                         DEBUG(1, (__location__ ": Connection to %s got an unexpected "
     480             :                                   "RPC packet type - %u, expected %u: %s\n",
     481             :                                   rpccli_pipe_txt(talloc_tos(), cli),
     482             :                                   pkt->ptype, expected_pkt_type,
     483             :                                   nt_errstr(ret)));
     484           0 :                         NDR_PRINT_DEBUG(ncacn_packet, pkt);
     485           0 :                         return ret;
     486             :                 }
     487             : 
     488      548759 :                 tmp_stub.data = r->stub_and_verifier.data;
     489      548759 :                 tmp_stub.length = r->stub_and_verifier.length;
     490             : 
     491             :                 /* Here's where we deal with incoming sign/seal. */
     492      548759 :                 ret = dcerpc_check_auth(cli->auth, pkt,
     493             :                                         &tmp_stub,
     494             :                                         DCERPC_RESPONSE_LENGTH,
     495             :                                         pdu);
     496      548759 :                 if (!NT_STATUS_IS_OK(ret)) {
     497           0 :                         DEBUG(1, (__location__ ": Connection to %s got an unexpected "
     498             :                                   "RPC packet type - %u, expected %u: %s\n",
     499             :                                   rpccli_pipe_txt(talloc_tos(), cli),
     500             :                                   pkt->ptype, expected_pkt_type,
     501             :                                   nt_errstr(ret)));
     502           0 :                         NDR_PRINT_DEBUG(ncacn_packet, pkt);
     503           0 :                         return ret;
     504             :                 }
     505             : 
     506             :                 /* Point the return values at the NDR data. */
     507      548759 :                 *rdata = tmp_stub;
     508             : 
     509      548759 :                 DEBUG(10, ("Got pdu len %lu, data_len %lu\n",
     510             :                            (long unsigned int)pdu->length,
     511             :                            (long unsigned int)rdata->length));
     512             : 
     513             :                 /*
     514             :                  * If this is the first reply, and the allocation hint is
     515             :                  * reasonable, try and set up the reply_pdu DATA_BLOB to the
     516             :                  * correct size.
     517             :                  */
     518             : 
     519      548759 :                 if ((reply_pdu->length == 0) &&
     520      548373 :                     r->alloc_hint && (r->alloc_hint < 15*1024*1024)) {
     521      548373 :                         if (!data_blob_realloc(mem_ctx, reply_pdu,
     522      548373 :                                                         r->alloc_hint)) {
     523           0 :                                 DEBUG(0, ("reply alloc hint %d too "
     524             :                                           "large to allocate\n",
     525             :                                           (int)r->alloc_hint));
     526           0 :                                 return NT_STATUS_NO_MEMORY;
     527             :                         }
     528             :                 }
     529             : 
     530      548759 :                 break;
     531             : 
     532         222 :         case DCERPC_PKT_FAULT:
     533             : 
     534         222 :                 ret = dcerpc_verify_ncacn_packet_header(pkt,
     535             :                                                 DCERPC_PKT_FAULT,
     536             :                                                 0, /* max_auth_info */
     537             :                                                 DCERPC_PFC_FLAG_FIRST |
     538             :                                                 DCERPC_PFC_FLAG_LAST,
     539             :                                                 DCERPC_PFC_FLAG_DID_NOT_EXECUTE);
     540         222 :                 if (!NT_STATUS_IS_OK(ret)) {
     541           0 :                         DEBUG(1, (__location__ ": Connection to %s got an unexpected "
     542             :                                   "RPC packet type - %u, expected %u: %s\n",
     543             :                                   rpccli_pipe_txt(talloc_tos(), cli),
     544             :                                   pkt->ptype, expected_pkt_type,
     545             :                                   nt_errstr(ret)));
     546           0 :                         NDR_PRINT_DEBUG(ncacn_packet, pkt);
     547           0 :                         return ret;
     548             :                 }
     549             : 
     550         222 :                 DEBUG(1, (__location__ ": RPC fault code %s received "
     551             :                           "from %s!\n",
     552             :                           dcerpc_errstr(talloc_tos(),
     553             :                           pkt->u.fault.status),
     554             :                           rpccli_pipe_txt(talloc_tos(), cli)));
     555             : 
     556         222 :                 return dcerpc_fault_to_nt_status(pkt->u.fault.status);
     557             : 
     558           0 :         default:
     559           0 :                 DEBUG(0, (__location__ "Unknown packet type %u received "
     560             :                           "from %s!\n",
     561             :                           (unsigned int)pkt->ptype,
     562             :                           rpccli_pipe_txt(talloc_tos(), cli)));
     563           0 :                 return NT_STATUS_RPC_PROTOCOL_ERROR;
     564             :         }
     565             : 
     566             : 
     567      590597 :         if (pkt->call_id != call_id) {
     568           0 :                 DEBUG(3, (__location__ ": Connection to %s got an unexpected "
     569             :                           "RPC call_id - %u, not %u\n",
     570             :                           rpccli_pipe_txt(talloc_tos(), cli),
     571             :                           pkt->call_id, call_id));
     572           0 :                 return NT_STATUS_RPC_PROTOCOL_ERROR;
     573             :         }
     574             : 
     575      590597 :         return NT_STATUS_OK;
     576             : }
     577             : 
     578             : /****************************************************************************
     579             :  Call a remote api on an arbitrary pipe.  takes param, data and setup buffers.
     580             : ****************************************************************************/
     581             : 
     582             : struct cli_api_pipe_state {
     583             :         struct tevent_context *ev;
     584             :         struct rpc_cli_transport *transport;
     585             :         uint8_t *rdata;
     586             :         uint32_t rdata_len;
     587             : };
     588             : 
     589             : static void cli_api_pipe_trans_done(struct tevent_req *subreq);
     590             : static void cli_api_pipe_write_done(struct tevent_req *subreq);
     591             : static void cli_api_pipe_read_done(struct tevent_req *subreq);
     592             : 
     593      590433 : static struct tevent_req *cli_api_pipe_send(TALLOC_CTX *mem_ctx,
     594             :                                             struct tevent_context *ev,
     595             :                                             struct rpc_cli_transport *transport,
     596             :                                             uint8_t *data, size_t data_len,
     597             :                                             uint32_t max_rdata_len)
     598             : {
     599           0 :         struct tevent_req *req, *subreq;
     600           0 :         struct cli_api_pipe_state *state;
     601             : 
     602      590433 :         req = tevent_req_create(mem_ctx, &state, struct cli_api_pipe_state);
     603      590433 :         if (req == NULL) {
     604           0 :                 return NULL;
     605             :         }
     606      590433 :         state->ev = ev;
     607      590433 :         state->transport = transport;
     608             : 
     609      590433 :         if (max_rdata_len < RPC_HEADER_LEN) {
     610             :                 /*
     611             :                  * For a RPC reply we always need at least RPC_HEADER_LEN
     612             :                  * bytes. We check this here because we will receive
     613             :                  * RPC_HEADER_LEN bytes in cli_trans_sock_send_done.
     614             :                  */
     615           0 :                 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
     616           0 :                 return tevent_req_post(req, ev);
     617             :         }
     618             : 
     619      590433 :         if (transport->trans_send != NULL) {
     620      115493 :                 subreq = transport->trans_send(state, ev, data, data_len,
     621             :                                                max_rdata_len, transport->priv);
     622      115493 :                 if (tevent_req_nomem(subreq, req)) {
     623           0 :                         return tevent_req_post(req, ev);
     624             :                 }
     625      115493 :                 tevent_req_set_callback(subreq, cli_api_pipe_trans_done, req);
     626      115493 :                 return req;
     627             :         }
     628             : 
     629             :         /*
     630             :          * If the transport does not provide a "trans" routine, i.e. for
     631             :          * example the ncacn_ip_tcp transport, do the write/read step here.
     632             :          */
     633             : 
     634      474940 :         subreq = rpc_write_send(state, ev, transport, data, data_len);
     635      474940 :         if (tevent_req_nomem(subreq, req)) {
     636           0 :                 return tevent_req_post(req, ev);
     637             :         }
     638      474940 :         tevent_req_set_callback(subreq, cli_api_pipe_write_done, req);
     639      474940 :         return req;
     640             : }
     641             : 
     642      115493 : static void cli_api_pipe_trans_done(struct tevent_req *subreq)
     643             : {
     644      115493 :         struct tevent_req *req = tevent_req_callback_data(
     645             :                 subreq, struct tevent_req);
     646      115493 :         struct cli_api_pipe_state *state = tevent_req_data(
     647             :                 req, struct cli_api_pipe_state);
     648           0 :         NTSTATUS status;
     649             : 
     650      115493 :         status = state->transport->trans_recv(subreq, state, &state->rdata,
     651             :                                               &state->rdata_len);
     652      115493 :         TALLOC_FREE(subreq);
     653      115493 :         if (tevent_req_nterror(req, status)) {
     654           0 :                 return;
     655             :         }
     656      115493 :         tevent_req_done(req);
     657             : }
     658             : 
     659      474940 : static void cli_api_pipe_write_done(struct tevent_req *subreq)
     660             : {
     661      474940 :         struct tevent_req *req = tevent_req_callback_data(
     662             :                 subreq, struct tevent_req);
     663      474940 :         struct cli_api_pipe_state *state = tevent_req_data(
     664             :                 req, struct cli_api_pipe_state);
     665           0 :         NTSTATUS status;
     666             : 
     667      474940 :         status = rpc_write_recv(subreq);
     668      474940 :         TALLOC_FREE(subreq);
     669      474940 :         if (tevent_req_nterror(req, status)) {
     670           0 :                 return;
     671             :         }
     672             : 
     673      474940 :         state->rdata = talloc_array(state, uint8_t, RPC_HEADER_LEN);
     674      474940 :         if (tevent_req_nomem(state->rdata, req)) {
     675           0 :                 return;
     676             :         }
     677             : 
     678             :         /*
     679             :          * We don't need to use rpc_read_send here, the upper layer will cope
     680             :          * with a short read, transport->trans_send could also return less
     681             :          * than state->max_rdata_len.
     682             :          */
     683      474940 :         subreq = state->transport->read_send(state, state->ev, state->rdata,
     684             :                                              RPC_HEADER_LEN,
     685      474940 :                                              state->transport->priv);
     686      474940 :         if (tevent_req_nomem(subreq, req)) {
     687           0 :                 return;
     688             :         }
     689      474940 :         tevent_req_set_callback(subreq, cli_api_pipe_read_done, req);
     690             : }
     691             : 
     692      474940 : static void cli_api_pipe_read_done(struct tevent_req *subreq)
     693             : {
     694      474940 :         struct tevent_req *req = tevent_req_callback_data(
     695             :                 subreq, struct tevent_req);
     696      474940 :         struct cli_api_pipe_state *state = tevent_req_data(
     697             :                 req, struct cli_api_pipe_state);
     698           0 :         NTSTATUS status;
     699           0 :         ssize_t received;
     700             : 
     701      474940 :         status = state->transport->read_recv(subreq, &received);
     702      474940 :         TALLOC_FREE(subreq);
     703      474940 :         if (tevent_req_nterror(req, status)) {
     704           0 :                 return;
     705             :         }
     706      474940 :         state->rdata_len = received;
     707      474940 :         tevent_req_done(req);
     708             : }
     709             : 
     710      590433 : static NTSTATUS cli_api_pipe_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx,
     711             :                                   uint8_t **prdata, uint32_t *prdata_len)
     712             : {
     713      590433 :         struct cli_api_pipe_state *state = tevent_req_data(
     714             :                 req, struct cli_api_pipe_state);
     715           0 :         NTSTATUS status;
     716             : 
     717      590433 :         if (tevent_req_is_nterror(req, &status)) {
     718           0 :                 return status;
     719             :         }
     720             : 
     721      590433 :         *prdata = talloc_move(mem_ctx, &state->rdata);
     722      590433 :         *prdata_len = state->rdata_len;
     723      590433 :         return NT_STATUS_OK;
     724             : }
     725             : 
     726             : /****************************************************************************
     727             :  Send data on an rpc pipe via trans. The data must be the last
     728             :  pdu fragment of an NDR data stream.
     729             : 
     730             :  Receive response data from an rpc pipe, which may be large...
     731             : 
     732             :  Read the first fragment: unfortunately have to use SMBtrans for the first
     733             :  bit, then SMBreadX for subsequent bits.
     734             : 
     735             :  If first fragment received also wasn't the last fragment, continue
     736             :  getting fragments until we _do_ receive the last fragment.
     737             : 
     738             :  Request/Response PDU's look like the following...
     739             : 
     740             :  |<------------------PDU len----------------------------------------------->|
     741             :  |<-HDR_LEN-->|<--REQ LEN------>|.............|<-AUTH_HDRLEN->|<-AUTH_LEN-->|
     742             : 
     743             :  +------------+-----------------+-------------+---------------+-------------+
     744             :  | RPC HEADER | REQ/RESP HEADER | DATA ...... | AUTH_HDR      | AUTH DATA   |
     745             :  +------------+-----------------+-------------+---------------+-------------+
     746             : 
     747             :  Where the presence of the AUTH_HDR and AUTH DATA are dependent on the
     748             :  signing & sealing being negotiated.
     749             : 
     750             :  ****************************************************************************/
     751             : 
     752             : struct rpc_api_pipe_state {
     753             :         struct tevent_context *ev;
     754             :         struct rpc_pipe_client *cli;
     755             :         uint8_t expected_pkt_type;
     756             :         uint32_t call_id;
     757             : 
     758             :         DATA_BLOB incoming_frag;
     759             :         struct ncacn_packet *pkt;
     760             : 
     761             :         /* Incoming reply */
     762             :         DATA_BLOB reply_pdu;
     763             :         size_t reply_pdu_offset;
     764             :         uint8_t endianness;
     765             : };
     766             : 
     767             : static void rpc_api_pipe_trans_done(struct tevent_req *subreq);
     768             : static void rpc_api_pipe_got_pdu(struct tevent_req *subreq);
     769             : static void rpc_api_pipe_auth3_done(struct tevent_req *subreq);
     770             : 
     771      590507 : static struct tevent_req *rpc_api_pipe_send(TALLOC_CTX *mem_ctx,
     772             :                                             struct tevent_context *ev,
     773             :                                             struct rpc_pipe_client *cli,
     774             :                                             DATA_BLOB *data, /* Outgoing PDU */
     775             :                                             uint8_t expected_pkt_type,
     776             :                                             uint32_t call_id)
     777             : {
     778           0 :         struct tevent_req *req, *subreq;
     779           0 :         struct rpc_api_pipe_state *state;
     780           0 :         uint16_t max_recv_frag;
     781             : 
     782      590507 :         req = tevent_req_create(mem_ctx, &state, struct rpc_api_pipe_state);
     783      590507 :         if (req == NULL) {
     784           0 :                 return NULL;
     785             :         }
     786      590507 :         state->ev = ev;
     787      590507 :         state->cli = cli;
     788      590507 :         state->expected_pkt_type = expected_pkt_type;
     789      590507 :         state->call_id = call_id;
     790      590507 :         state->endianness = DCERPC_DREP_LE;
     791             : 
     792             :         /*
     793             :          * Ensure we're not sending too much.
     794             :          */
     795      590507 :         if (data->length > cli->max_xmit_frag) {
     796           0 :                 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
     797           0 :                 return tevent_req_post(req, ev);
     798             :         }
     799             : 
     800      590507 :         DEBUG(5,("rpc_api_pipe: %s\n", rpccli_pipe_txt(talloc_tos(), cli)));
     801             : 
     802      590507 :         if (state->expected_pkt_type == DCERPC_PKT_AUTH3) {
     803          74 :                 subreq = rpc_write_send(state, ev, cli->transport,
     804          74 :                                         data->data, data->length);
     805          74 :                 if (tevent_req_nomem(subreq, req)) {
     806           0 :                         return tevent_req_post(req, ev);
     807             :                 }
     808          74 :                 tevent_req_set_callback(subreq, rpc_api_pipe_auth3_done, req);
     809          74 :                 return req;
     810             :         }
     811             : 
     812             :         /* get the header first, then fetch the rest once we have
     813             :          * the frag_length available */
     814      590433 :         max_recv_frag = RPC_HEADER_LEN;
     815             : 
     816      590433 :         subreq = cli_api_pipe_send(state, ev, cli->transport,
     817             :                                    data->data, data->length, max_recv_frag);
     818      590433 :         if (tevent_req_nomem(subreq, req)) {
     819           0 :                 return tevent_req_post(req, ev);
     820             :         }
     821      590433 :         tevent_req_set_callback(subreq, rpc_api_pipe_trans_done, req);
     822      590433 :         return req;
     823             : }
     824             : 
     825          74 : static void rpc_api_pipe_auth3_done(struct tevent_req *subreq)
     826             : {
     827          74 :         NTSTATUS status = rpc_write_recv(subreq);
     828          74 :         return tevent_req_simple_finish_ntstatus(subreq, status);
     829             : }
     830             : 
     831      590433 : static void rpc_api_pipe_trans_done(struct tevent_req *subreq)
     832             : {
     833      590433 :         struct tevent_req *req = tevent_req_callback_data(
     834             :                 subreq, struct tevent_req);
     835      590433 :         struct rpc_api_pipe_state *state = tevent_req_data(
     836             :                 req, struct rpc_api_pipe_state);
     837           0 :         NTSTATUS status;
     838      590433 :         uint8_t *rdata = NULL;
     839      590433 :         uint32_t rdata_len = 0;
     840             : 
     841      590433 :         status = cli_api_pipe_recv(subreq, state, &rdata, &rdata_len);
     842      590433 :         TALLOC_FREE(subreq);
     843      590433 :         if (tevent_req_nterror(req, status)) {;
     844           0 :                 DEBUG(5, ("cli_api_pipe failed: %s\n", nt_errstr(status)));
     845           0 :                 return;
     846             :         }
     847             : 
     848      590433 :         if (rdata == NULL) {
     849           0 :                 DEBUG(3,("rpc_api_pipe: %s failed to return data.\n",
     850             :                          rpccli_pipe_txt(talloc_tos(), state->cli)));
     851           0 :                 tevent_req_done(req);
     852           0 :                 return;
     853             :         }
     854             : 
     855             :         /*
     856             :          * Move data on state->incoming_frag.
     857             :          */
     858      590433 :         state->incoming_frag.data = talloc_move(state, &rdata);
     859      590433 :         state->incoming_frag.length = rdata_len;
     860      590433 :         if (!state->incoming_frag.data) {
     861           0 :                 tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
     862           0 :                 return;
     863             :         }
     864             : 
     865             :         /* Ensure we have enough data for a pdu. */
     866      590433 :         subreq = get_complete_frag_send(state, state->ev, state->cli,
     867             :                                         &state->incoming_frag);
     868      590433 :         if (tevent_req_nomem(subreq, req)) {
     869           0 :                 return;
     870             :         }
     871      590433 :         tevent_req_set_callback(subreq, rpc_api_pipe_got_pdu, req);
     872             : }
     873             : 
     874      590819 : static void rpc_api_pipe_got_pdu(struct tevent_req *subreq)
     875             : {
     876      590819 :         struct tevent_req *req = tevent_req_callback_data(
     877             :                 subreq, struct tevent_req);
     878      590819 :         struct rpc_api_pipe_state *state = tevent_req_data(
     879             :                 req, struct rpc_api_pipe_state);
     880           0 :         NTSTATUS status;
     881      590819 :         DATA_BLOB rdata = { .data = NULL };
     882             : 
     883      590819 :         status = get_complete_frag_recv(subreq);
     884      590819 :         TALLOC_FREE(subreq);
     885      590819 :         if (tevent_req_nterror(req, status)) {
     886           0 :                 DEBUG(5, ("get_complete_frag failed: %s\n",
     887             :                           nt_errstr(status)));
     888      590433 :                 return;
     889             :         }
     890             : 
     891      590819 :         state->pkt = talloc(state, struct ncacn_packet);
     892      590819 :         if (!state->pkt) {
     893             :                 /*
     894             :                  * TODO: do a real async disconnect ...
     895             :                  *
     896             :                  * For now do it sync...
     897             :                  */
     898           0 :                 TALLOC_FREE(state->cli->transport);
     899           0 :                 tevent_req_oom(req);
     900           0 :                 return;
     901             :         }
     902             : 
     903      590819 :         status = dcerpc_pull_ncacn_packet(state->pkt,
     904      590819 :                                           &state->incoming_frag,
     905             :                                           state->pkt);
     906      590819 :         if (tevent_req_nterror(req, status)) {
     907             :                 /*
     908             :                  * TODO: do a real async disconnect ...
     909             :                  *
     910             :                  * For now do it sync...
     911             :                  */
     912           0 :                 TALLOC_FREE(state->cli->transport);
     913           0 :                 return;
     914             :         }
     915             : 
     916      590819 :         if (DEBUGLEVEL >= 10) {
     917          98 :                 NDR_PRINT_DEBUG(ncacn_packet, state->pkt);
     918             :         }
     919             : 
     920      590819 :         status = cli_pipe_validate_current_pdu(state,
     921             :                                                 state->cli, state->pkt,
     922             :                                                 &state->incoming_frag,
     923      590819 :                                                 state->expected_pkt_type,
     924             :                                                 state->call_id,
     925             :                                                 &rdata,
     926             :                                                 &state->reply_pdu);
     927             : 
     928      590819 :         DBG_DEBUG("got frag len of %zu at offset %zu: %s\n",
     929             :                   state->incoming_frag.length,
     930             :                   state->reply_pdu_offset,
     931             :                   nt_errstr(status));
     932             : 
     933      590819 :         if (state->pkt->ptype != DCERPC_PKT_FAULT && !NT_STATUS_IS_OK(status)) {
     934             :                 /*
     935             :                  * TODO: do a real async disconnect ...
     936             :                  *
     937             :                  * For now do it sync...
     938             :                  */
     939           0 :                 TALLOC_FREE(state->cli->transport);
     940      590819 :         } else if (NT_STATUS_EQUAL(status, NT_STATUS_RPC_PROTOCOL_ERROR)) {
     941             :                 /*
     942             :                  * TODO: do a real async disconnect ...
     943             :                  *
     944             :                  * For now do it sync...
     945             :                  */
     946           0 :                 TALLOC_FREE(state->cli->transport);
     947      590819 :         } else if (NT_STATUS_EQUAL(status, NT_STATUS_RPC_SEC_PKG_ERROR)) {
     948             :                 /*
     949             :                  * TODO: do a real async disconnect ...
     950             :                  *
     951             :                  * For now do it sync...
     952             :                  */
     953           0 :                 TALLOC_FREE(state->cli->transport);
     954             :         }
     955      590819 :         if (tevent_req_nterror(req, status)) {
     956         222 :                 return;
     957             :         }
     958             : 
     959      590597 :         if ((state->pkt->pfc_flags & DCERPC_PFC_FLAG_FIRST)
     960      590211 :             && (state->pkt->drep[0] != DCERPC_DREP_LE)) {
     961             :                 /*
     962             :                  * Set the data type correctly for big-endian data on the
     963             :                  * first packet.
     964             :                  */
     965           0 :                 DEBUG(10,("rpc_api_pipe: On %s PDU data format is "
     966             :                           "big-endian.\n",
     967             :                           rpccli_pipe_txt(talloc_tos(), state->cli)));
     968           0 :                 state->endianness = 0x00; /* BIG ENDIAN */
     969             :         }
     970             :         /*
     971             :          * Check endianness on subsequent packets.
     972             :          */
     973      590597 :         if (state->endianness != state->pkt->drep[0]) {
     974           0 :                 DEBUG(0,("rpc_api_pipe: Error : Endianness changed from %s to "
     975             :                          "%s\n",
     976             :                          state->endianness?"little":"big",
     977             :                          state->pkt->drep[0]?"little":"big"));
     978             :                 /*
     979             :                  * TODO: do a real async disconnect ...
     980             :                  *
     981             :                  * For now do it sync...
     982             :                  */
     983           0 :                 TALLOC_FREE(state->cli->transport);
     984           0 :                 tevent_req_nterror(req, NT_STATUS_RPC_PROTOCOL_ERROR);
     985           0 :                 return;
     986             :         }
     987             : 
     988      590597 :         if (state->reply_pdu_offset + rdata.length > MAX_RPC_DATA_SIZE) {
     989             :                 /*
     990             :                  * TODO: do a real async disconnect ...
     991             :                  *
     992             :                  * For now do it sync...
     993             :                  */
     994           0 :                 TALLOC_FREE(state->cli->transport);
     995           0 :                 tevent_req_nterror(req, NT_STATUS_RPC_PROTOCOL_ERROR);
     996           0 :                 return;
     997             :         }
     998             : 
     999             :         /* Now copy the data portion out of the pdu into rbuf. */
    1000      590597 :         if (state->reply_pdu.length < state->reply_pdu_offset + rdata.length) {
    1001       41838 :                 if (!data_blob_realloc(NULL, &state->reply_pdu,
    1002       41838 :                                 state->reply_pdu_offset + rdata.length)) {
    1003             :                         /*
    1004             :                          * TODO: do a real async disconnect ...
    1005             :                          *
    1006             :                          * For now do it sync...
    1007             :                          */
    1008           0 :                         TALLOC_FREE(state->cli->transport);
    1009           0 :                         tevent_req_oom(req);
    1010           0 :                         return;
    1011             :                 }
    1012             :         }
    1013             : 
    1014      590597 :         memcpy(state->reply_pdu.data + state->reply_pdu_offset,
    1015      590597 :                 rdata.data, rdata.length);
    1016      590597 :         state->reply_pdu_offset += rdata.length;
    1017             : 
    1018             :         /* reset state->incoming_frag, there is no need to free it,
    1019             :          * it will be reallocated to the right size the next time
    1020             :          * it is used */
    1021      590597 :         state->incoming_frag.length = 0;
    1022             : 
    1023      590597 :         if (state->pkt->pfc_flags & DCERPC_PFC_FLAG_LAST) {
    1024             :                 /* make sure the pdu length is right now that we
    1025             :                  * have all the data available (alloc hint may
    1026             :                  * have allocated more than was actually used) */
    1027      590211 :                 state->reply_pdu.length = state->reply_pdu_offset;
    1028      590211 :                 DEBUG(10,("rpc_api_pipe: %s returned %u bytes.\n",
    1029             :                           rpccli_pipe_txt(talloc_tos(), state->cli),
    1030             :                           (unsigned)state->reply_pdu.length));
    1031      590211 :                 tevent_req_done(req);
    1032      590211 :                 return;
    1033             :         }
    1034             : 
    1035         386 :         subreq = get_complete_frag_send(state, state->ev, state->cli,
    1036             :                                         &state->incoming_frag);
    1037         386 :         if (subreq == NULL) {
    1038             :                 /*
    1039             :                  * TODO: do a real async disconnect ...
    1040             :                  *
    1041             :                  * For now do it sync...
    1042             :                  */
    1043           0 :                 TALLOC_FREE(state->cli->transport);
    1044             :         }
    1045         386 :         if (tevent_req_nomem(subreq, req)) {
    1046           0 :                 return;
    1047             :         }
    1048         386 :         tevent_req_set_callback(subreq, rpc_api_pipe_got_pdu, req);
    1049             : }
    1050             : 
    1051      590507 : static NTSTATUS rpc_api_pipe_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx,
    1052             :                                   struct ncacn_packet **pkt,
    1053             :                                   DATA_BLOB *reply_pdu)
    1054             : {
    1055      590507 :         struct rpc_api_pipe_state *state = tevent_req_data(
    1056             :                 req, struct rpc_api_pipe_state);
    1057           0 :         NTSTATUS status;
    1058             : 
    1059      590507 :         if (tevent_req_is_nterror(req, &status)) {
    1060         222 :                 return status;
    1061             :         }
    1062             : 
    1063             :         /* return data to caller and assign it ownership of memory */
    1064      590285 :         if (reply_pdu) {
    1065      548373 :                 reply_pdu->data = talloc_move(mem_ctx, &state->reply_pdu.data);
    1066      548373 :                 reply_pdu->length = state->reply_pdu.length;
    1067      548373 :                 state->reply_pdu.length = 0;
    1068             :         } else {
    1069       41912 :                 data_blob_free(&state->reply_pdu);
    1070             :         }
    1071             : 
    1072      590285 :         if (pkt) {
    1073       41912 :                 *pkt = talloc_steal(mem_ctx, state->pkt);
    1074             :         }
    1075             : 
    1076      590285 :         return NT_STATUS_OK;
    1077             : }
    1078             : 
    1079             : /*******************************************************************
    1080             :  Creates NTLMSSP auth bind.
    1081             :  ********************************************************************/
    1082             : 
    1083         476 : static NTSTATUS create_generic_auth_rpc_bind_req(struct rpc_pipe_client *cli,
    1084             :                                                  TALLOC_CTX *mem_ctx,
    1085             :                                                  DATA_BLOB *auth_token,
    1086             :                                                  bool *client_hdr_signing)
    1087             : {
    1088           0 :         struct gensec_security *gensec_security;
    1089         476 :         DATA_BLOB null_blob = { .data = NULL };
    1090           0 :         NTSTATUS status;
    1091             : 
    1092         476 :         gensec_security = cli->auth->auth_ctx;
    1093             : 
    1094         476 :         DEBUG(5, ("create_generic_auth_rpc_bind_req: generate first token\n"));
    1095         476 :         status = gensec_update(gensec_security, mem_ctx, null_blob, auth_token);
    1096             : 
    1097         476 :         if (!NT_STATUS_IS_OK(status) &&
    1098         476 :             !NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED))
    1099             :         {
    1100           0 :                 return status;
    1101             :         }
    1102             : 
    1103         476 :         if (client_hdr_signing == NULL) {
    1104           0 :                 return status;
    1105             :         }
    1106             : 
    1107         476 :         if (cli->auth->auth_level < DCERPC_AUTH_LEVEL_PACKET) {
    1108         166 :                 *client_hdr_signing = false;
    1109         166 :                 return status;
    1110             :         }
    1111             : 
    1112         310 :         *client_hdr_signing = gensec_have_feature(gensec_security,
    1113             :                                                 GENSEC_FEATURE_SIGN_PKT_HEADER);
    1114             : 
    1115         310 :         return status;
    1116             : }
    1117             : 
    1118             : /*******************************************************************
    1119             :  Creates the internals of a DCE/RPC bind request or alter context PDU.
    1120             :  ********************************************************************/
    1121             : 
    1122       41838 : static NTSTATUS create_bind_or_alt_ctx_internal(TALLOC_CTX *mem_ctx,
    1123             :                                                 enum dcerpc_pkt_type ptype,
    1124             :                                                 uint32_t rpc_call_id,
    1125             :                                                 const struct ndr_syntax_id *abstract,
    1126             :                                                 const struct ndr_syntax_id *transfer,
    1127             :                                                 const DATA_BLOB *auth_info,
    1128             :                                                 bool client_hdr_signing,
    1129             :                                                 DATA_BLOB *blob)
    1130             : {
    1131       41838 :         uint16_t auth_len = auth_info->length;
    1132           0 :         NTSTATUS status;
    1133       41838 :         struct ndr_syntax_id bind_time_features = dcerpc_construct_bind_time_features(
    1134             :                         DCERPC_BIND_TIME_SECURITY_CONTEXT_MULTIPLEXING |
    1135             :                         DCERPC_BIND_TIME_KEEP_CONNECTION_ON_ORPHAN);
    1136       41838 :         struct dcerpc_ctx_list ctx_list[2] = {
    1137             :                 [0] = {
    1138             :                         .context_id = 0,
    1139             :                         .num_transfer_syntaxes = 1,
    1140             :                         .abstract_syntax = *abstract,
    1141             :                         .transfer_syntaxes = (struct ndr_syntax_id *)discard_const(transfer),
    1142             :                 },
    1143             :                 [1] = {
    1144             :                         .context_id = 1,
    1145             :                         .num_transfer_syntaxes = 1,
    1146             :                         .abstract_syntax = *abstract,
    1147             :                         .transfer_syntaxes = &bind_time_features,
    1148             :                 },
    1149             :         };
    1150       41838 :         union dcerpc_payload u = {
    1151             :                 .bind.max_xmit_frag     = RPC_MAX_PDU_FRAG_LEN,
    1152             :                 .bind.max_recv_frag     = RPC_MAX_PDU_FRAG_LEN,
    1153             :                 .bind.num_contexts      = ptype == DCERPC_PKT_BIND ? 2 : 1,
    1154             :                 .bind.ctx_list          = ctx_list,
    1155             :                 .bind.auth_info         = *auth_info,
    1156             :         };
    1157       41838 :         uint8_t pfc_flags = DCERPC_PFC_FLAG_FIRST | DCERPC_PFC_FLAG_LAST;
    1158             : 
    1159       41838 :         if (auth_len) {
    1160         635 :                 auth_len -= DCERPC_AUTH_TRAILER_LENGTH;
    1161             :         }
    1162             : 
    1163       41838 :         if (client_hdr_signing) {
    1164         310 :                 pfc_flags |= DCERPC_PFC_FLAG_SUPPORT_HEADER_SIGN;
    1165             :         }
    1166             : 
    1167       41838 :         status = dcerpc_push_ncacn_packet(mem_ctx,
    1168             :                                           ptype, pfc_flags,
    1169             :                                           auth_len,
    1170             :                                           rpc_call_id,
    1171             :                                           &u,
    1172             :                                           blob);
    1173       41838 :         if (!NT_STATUS_IS_OK(status)) {
    1174           0 :                 DEBUG(0, ("Failed to marshall bind/alter ncacn_packet.\n"));
    1175           0 :                 return status;
    1176             :         }
    1177             : 
    1178       41838 :         return NT_STATUS_OK;
    1179             : }
    1180             : 
    1181             : /*******************************************************************
    1182             :  Creates a DCE/RPC bind request.
    1183             :  ********************************************************************/
    1184             : 
    1185       41679 : static NTSTATUS create_rpc_bind_req(TALLOC_CTX *mem_ctx,
    1186             :                                     struct rpc_pipe_client *cli,
    1187             :                                     struct pipe_auth_data *auth,
    1188             :                                     uint32_t rpc_call_id,
    1189             :                                     const struct ndr_syntax_id *abstract,
    1190             :                                     const struct ndr_syntax_id *transfer,
    1191             :                                     DATA_BLOB *rpc_out)
    1192             : {
    1193       41679 :         DATA_BLOB auth_token = { .data = NULL };
    1194       41679 :         DATA_BLOB auth_info = { .data = NULL };
    1195           0 :         NTSTATUS ret;
    1196             : 
    1197       41679 :         if (auth->auth_type != DCERPC_AUTH_TYPE_NONE) {
    1198         476 :                 ret = create_generic_auth_rpc_bind_req(
    1199             :                         cli, mem_ctx, &auth_token, &auth->client_hdr_signing);
    1200             : 
    1201         476 :                 if (!NT_STATUS_IS_OK(ret) &&
    1202         476 :                     !NT_STATUS_EQUAL(ret, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
    1203           0 :                         return ret;
    1204             :                 }
    1205             :         }
    1206             : 
    1207       41679 :         if (auth_token.length != 0) {
    1208         476 :                 ret = dcerpc_push_dcerpc_auth(cli,
    1209             :                                                 auth->auth_type,
    1210             :                                                 auth->auth_level,
    1211             :                                                 0, /* auth_pad_length */
    1212             :                                                 auth->auth_context_id,
    1213             :                                                 &auth_token,
    1214             :                                                 &auth_info);
    1215         476 :                 if (!NT_STATUS_IS_OK(ret)) {
    1216           0 :                         return ret;
    1217             :                 }
    1218         476 :                 data_blob_free(&auth_token);
    1219             :         }
    1220             : 
    1221       41679 :         ret = create_bind_or_alt_ctx_internal(mem_ctx,
    1222             :                                               DCERPC_PKT_BIND,
    1223             :                                               rpc_call_id,
    1224             :                                               abstract,
    1225             :                                               transfer,
    1226             :                                               &auth_info,
    1227       41679 :                                               auth->client_hdr_signing,
    1228             :                                               rpc_out);
    1229       41679 :         data_blob_free(&auth_info);
    1230             : 
    1231       41679 :         return ret;
    1232             : }
    1233             : 
    1234             : /*******************************************************************
    1235             :  External interface.
    1236             :  Does an rpc request on a pipe. Incoming data is NDR encoded in in_data.
    1237             :  Reply is NDR encoded in out_data. Splits the data stream into RPC PDU's
    1238             :  and deals with signing/sealing details.
    1239             :  ********************************************************************/
    1240             : 
    1241             : struct rpc_api_pipe_req_state {
    1242             :         struct tevent_context *ev;
    1243             :         struct rpc_pipe_client *cli;
    1244             :         uint8_t op_num;
    1245             :         uint32_t call_id;
    1246             :         const DATA_BLOB *req_data;
    1247             :         const struct GUID *object_uuid;
    1248             :         uint32_t req_data_sent;
    1249             :         DATA_BLOB req_trailer;
    1250             :         uint32_t req_trailer_sent;
    1251             :         bool verify_bitmask1;
    1252             :         bool verify_pcontext;
    1253             :         DATA_BLOB rpc_out;
    1254             :         DATA_BLOB reply_pdu;
    1255             : };
    1256             : 
    1257             : static void rpc_api_pipe_req_write_done(struct tevent_req *subreq);
    1258             : static void rpc_api_pipe_req_done(struct tevent_req *subreq);
    1259             : static NTSTATUS prepare_verification_trailer(struct rpc_api_pipe_req_state *state);
    1260             : static NTSTATUS prepare_next_frag(struct rpc_api_pipe_req_state *state,
    1261             :                                   bool *is_last_frag);
    1262             : 
    1263      548595 : static struct tevent_req *rpc_api_pipe_req_send(TALLOC_CTX *mem_ctx,
    1264             :                                          struct tevent_context *ev,
    1265             :                                          struct rpc_pipe_client *cli,
    1266             :                                          uint8_t op_num,
    1267             :                                          const struct GUID *object_uuid,
    1268             :                                          const DATA_BLOB *req_data)
    1269             : {
    1270           0 :         struct tevent_req *req, *subreq;
    1271           0 :         struct rpc_api_pipe_req_state *state;
    1272           0 :         NTSTATUS status;
    1273           0 :         bool is_last_frag;
    1274             : 
    1275      548595 :         req = tevent_req_create(mem_ctx, &state,
    1276             :                                 struct rpc_api_pipe_req_state);
    1277      548595 :         if (req == NULL) {
    1278           0 :                 return NULL;
    1279             :         }
    1280      548595 :         state->ev = ev;
    1281      548595 :         state->cli = cli;
    1282      548595 :         state->op_num = op_num;
    1283      548595 :         state->object_uuid = object_uuid;
    1284      548595 :         state->req_data = req_data;
    1285      548595 :         state->call_id = get_rpc_call_id();
    1286             : 
    1287      548595 :         if (cli->max_xmit_frag < DCERPC_REQUEST_LENGTH
    1288             :                                         + RPC_MAX_SIGN_SIZE) {
    1289             :                 /* Server is screwed up ! */
    1290           0 :                 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
    1291           0 :                 return tevent_req_post(req, ev);
    1292             :         }
    1293             : 
    1294      548595 :         status = prepare_verification_trailer(state);
    1295      548595 :         if (tevent_req_nterror(req, status)) {
    1296           0 :                 return tevent_req_post(req, ev);
    1297             :         }
    1298             : 
    1299      548595 :         status = prepare_next_frag(state, &is_last_frag);
    1300      548595 :         if (tevent_req_nterror(req, status)) {
    1301           0 :                 return tevent_req_post(req, ev);
    1302             :         }
    1303             : 
    1304      548595 :         if (is_last_frag) {
    1305      548595 :                 subreq = rpc_api_pipe_send(state, ev, state->cli,
    1306      548595 :                                            &state->rpc_out,
    1307             :                                            DCERPC_PKT_RESPONSE,
    1308      548595 :                                            state->call_id);
    1309      548595 :                 if (tevent_req_nomem(subreq, req)) {
    1310           0 :                         return tevent_req_post(req, ev);
    1311             :                 }
    1312      548595 :                 tevent_req_set_callback(subreq, rpc_api_pipe_req_done, req);
    1313             :         } else {
    1314           0 :                 subreq = rpc_write_send(state, ev, cli->transport,
    1315           0 :                                         state->rpc_out.data,
    1316           0 :                                         state->rpc_out.length);
    1317           0 :                 if (tevent_req_nomem(subreq, req)) {
    1318           0 :                         return tevent_req_post(req, ev);
    1319             :                 }
    1320           0 :                 tevent_req_set_callback(subreq, rpc_api_pipe_req_write_done,
    1321             :                                         req);
    1322             :         }
    1323      548595 :         return req;
    1324             : }
    1325             : 
    1326      548595 : static NTSTATUS prepare_verification_trailer(struct rpc_api_pipe_req_state *state)
    1327             : {
    1328      548595 :         struct pipe_auth_data *a = state->cli->auth;
    1329           0 :         struct dcerpc_sec_verification_trailer *t;
    1330      548595 :         struct ndr_push *ndr = NULL;
    1331           0 :         enum ndr_err_code ndr_err;
    1332      548595 :         size_t align = 0;
    1333      548595 :         size_t pad = 0;
    1334             : 
    1335      548595 :         if (a == NULL) {
    1336           0 :                 return NT_STATUS_OK;
    1337             :         }
    1338             : 
    1339      548595 :         if (a->auth_level < DCERPC_AUTH_LEVEL_PACKET) {
    1340      548229 :                 return NT_STATUS_OK;
    1341             :         }
    1342             : 
    1343         366 :         t = talloc_zero(state, struct dcerpc_sec_verification_trailer);
    1344         366 :         if (t == NULL) {
    1345           0 :                 return NT_STATUS_NO_MEMORY;
    1346             :         }
    1347             : 
    1348         366 :         if (!a->verified_bitmask1) {
    1349         310 :                 t->commands = talloc_realloc(t, t->commands,
    1350             :                                              struct dcerpc_sec_vt,
    1351             :                                              t->count.count + 1);
    1352         310 :                 if (t->commands == NULL) {
    1353           0 :                         return NT_STATUS_NO_MEMORY;
    1354             :                 }
    1355         310 :                 t->commands[t->count.count++] = (struct dcerpc_sec_vt) {
    1356             :                         .command = DCERPC_SEC_VT_COMMAND_BITMASK1,
    1357         310 :                         .u.bitmask1 = (a->client_hdr_signing) ?
    1358         310 :                                 DCERPC_SEC_VT_CLIENT_SUPPORTS_HEADER_SIGNING :
    1359             :                                 0,
    1360             :                 };
    1361         310 :                 state->verify_bitmask1 = true;
    1362             :         }
    1363             : 
    1364         366 :         if (!state->cli->verified_pcontext) {
    1365         310 :                 t->commands = talloc_realloc(t, t->commands,
    1366             :                                              struct dcerpc_sec_vt,
    1367             :                                              t->count.count + 1);
    1368         310 :                 if (t->commands == NULL) {
    1369           0 :                         return NT_STATUS_NO_MEMORY;
    1370             :                 }
    1371         310 :                 t->commands[t->count.count++] = (struct dcerpc_sec_vt) {
    1372             :                         .command = DCERPC_SEC_VT_COMMAND_PCONTEXT,
    1373             :                         .u.pcontext.abstract_syntax =
    1374         310 :                                 state->cli->abstract_syntax,
    1375             :                         .u.pcontext.transfer_syntax =
    1376         310 :                                 state->cli->transfer_syntax,
    1377             :                 };
    1378         310 :                 state->verify_pcontext = true;
    1379             :         }
    1380             : 
    1381         366 :         if (!a->hdr_signing) {
    1382           0 :                 t->commands = talloc_realloc(t, t->commands,
    1383             :                                              struct dcerpc_sec_vt,
    1384             :                                              t->count.count + 1);
    1385           0 :                 if (t->commands == NULL) {
    1386           0 :                         return NT_STATUS_NO_MEMORY;
    1387             :                 }
    1388           0 :                 t->commands[t->count.count++] = (struct dcerpc_sec_vt) {
    1389             :                         .command = DCERPC_SEC_VT_COMMAND_HEADER2,
    1390             :                         .u.header2.ptype = DCERPC_PKT_REQUEST,
    1391             :                         .u.header2.drep[0] = DCERPC_DREP_LE,
    1392           0 :                         .u.header2.call_id = state->call_id,
    1393             :                         .u.header2.context_id = 0,
    1394           0 :                         .u.header2.opnum = state->op_num,
    1395             :                 };
    1396             :         }
    1397             : 
    1398         366 :         if (t->count.count == 0) {
    1399          56 :                 TALLOC_FREE(t);
    1400          56 :                 return NT_STATUS_OK;
    1401             :         }
    1402             : 
    1403         310 :         t->commands[t->count.count - 1].command |= DCERPC_SEC_VT_COMMAND_END;
    1404             : 
    1405         310 :         if (DEBUGLEVEL >= 10) {
    1406           0 :                 NDR_PRINT_DEBUG(dcerpc_sec_verification_trailer, t);
    1407             :         }
    1408             : 
    1409         310 :         ndr = ndr_push_init_ctx(state);
    1410         310 :         if (ndr == NULL) {
    1411           0 :                 return NT_STATUS_NO_MEMORY;
    1412             :         }
    1413             : 
    1414         310 :         ndr_err = ndr_push_dcerpc_sec_verification_trailer(ndr,
    1415             :                                                 NDR_SCALARS | NDR_BUFFERS,
    1416             :                                                 t);
    1417         310 :         TALLOC_FREE(t);
    1418         310 :         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
    1419           0 :                 return ndr_map_error2ntstatus(ndr_err);
    1420             :         }
    1421         310 :         state->req_trailer = ndr_push_blob(ndr);
    1422             : 
    1423         310 :         align = state->req_data->length & 0x3;
    1424         310 :         if (align > 0) {
    1425           0 :                 pad = 4 - align;
    1426             :         }
    1427         310 :         if (pad > 0) {
    1428           0 :                 bool ok;
    1429           0 :                 uint8_t *p;
    1430           0 :                 const uint8_t zeros[4] = { 0, };
    1431             : 
    1432           0 :                 ok = data_blob_append(ndr, &state->req_trailer, zeros, pad);
    1433           0 :                 if (!ok) {
    1434           0 :                         return NT_STATUS_NO_MEMORY;
    1435             :                 }
    1436             : 
    1437             :                 /* move the padding to the start */
    1438           0 :                 p = state->req_trailer.data;
    1439           0 :                 memmove(p + pad, p, state->req_trailer.length - pad);
    1440           0 :                 memset(p, 0, pad);
    1441             :         }
    1442             : 
    1443         310 :         return NT_STATUS_OK;
    1444             : }
    1445             : 
    1446      548595 : static NTSTATUS prepare_next_frag(struct rpc_api_pipe_req_state *state,
    1447             :                                   bool *is_last_frag)
    1448             : {
    1449           0 :         size_t auth_len;
    1450           0 :         size_t frag_len;
    1451      548595 :         uint8_t flags = 0;
    1452           0 :         size_t pad_len;
    1453           0 :         size_t data_left;
    1454           0 :         size_t data_thistime;
    1455           0 :         size_t trailer_left;
    1456      548595 :         size_t trailer_thistime = 0;
    1457           0 :         size_t total_left;
    1458           0 :         size_t total_thistime;
    1459           0 :         NTSTATUS status;
    1460           0 :         bool ok;
    1461           0 :         union dcerpc_payload u;
    1462             : 
    1463      548595 :         data_left = state->req_data->length - state->req_data_sent;
    1464      548595 :         trailer_left = state->req_trailer.length - state->req_trailer_sent;
    1465      548595 :         total_left = data_left + trailer_left;
    1466      548595 :         if ((total_left < data_left) || (total_left < trailer_left)) {
    1467             :                 /*
    1468             :                  * overflow
    1469             :                  */
    1470           0 :                 return NT_STATUS_INVALID_PARAMETER_MIX;
    1471             :         }
    1472             : 
    1473      548595 :         status = dcerpc_guess_sizes(state->cli->auth,
    1474             :                                     DCERPC_REQUEST_LENGTH, total_left,
    1475      548595 :                                     state->cli->max_xmit_frag,
    1476             :                                     &total_thistime,
    1477             :                                     &frag_len, &auth_len, &pad_len);
    1478      548595 :         if (!NT_STATUS_IS_OK(status)) {
    1479           0 :                 return status;
    1480             :         }
    1481             : 
    1482      548595 :         if (state->req_data_sent == 0) {
    1483      548595 :                 flags = DCERPC_PFC_FLAG_FIRST;
    1484             :         }
    1485             : 
    1486      548595 :         if (total_thistime == total_left) {
    1487      548595 :                 flags |= DCERPC_PFC_FLAG_LAST;
    1488             :         }
    1489             : 
    1490      548595 :         data_thistime = MIN(total_thistime, data_left);
    1491      548595 :         if (data_thistime < total_thistime) {
    1492         310 :                 trailer_thistime = total_thistime - data_thistime;
    1493             :         }
    1494             : 
    1495      548595 :         data_blob_free(&state->rpc_out);
    1496             : 
    1497      548595 :         u = (union dcerpc_payload) {
    1498             :                 .request.alloc_hint     = total_left,
    1499             :                 .request.context_id     = 0,
    1500      548595 :                 .request.opnum          = state->op_num,
    1501             :         };
    1502             : 
    1503      548595 :         if (state->object_uuid) {
    1504           0 :                 flags |= DCERPC_PFC_FLAG_OBJECT_UUID;
    1505           0 :                 u.request.object.object = *state->object_uuid;
    1506           0 :                 frag_len += ndr_size_GUID(state->object_uuid, 0);
    1507             :         }
    1508             : 
    1509      548595 :         status = dcerpc_push_ncacn_packet(state,
    1510             :                                           DCERPC_PKT_REQUEST,
    1511             :                                           flags,
    1512             :                                           auth_len,
    1513             :                                           state->call_id,
    1514             :                                           &u,
    1515             :                                           &state->rpc_out);
    1516      548595 :         if (!NT_STATUS_IS_OK(status)) {
    1517           0 :                 return status;
    1518             :         }
    1519             : 
    1520             :         /* explicitly set frag_len here as dcerpc_push_ncacn_packet() can't
    1521             :          * compute it right for requests because the auth trailer is missing
    1522             :          * at this stage */
    1523      548595 :         dcerpc_set_frag_length(&state->rpc_out, frag_len);
    1524             : 
    1525      548595 :         if (data_thistime > 0) {
    1526             :                 /* Copy in the data. */
    1527      548593 :                 ok = data_blob_append(NULL, &state->rpc_out,
    1528      548593 :                                 state->req_data->data + state->req_data_sent,
    1529             :                                 data_thistime);
    1530      548593 :                 if (!ok) {
    1531           0 :                         return NT_STATUS_NO_MEMORY;
    1532             :                 }
    1533      548593 :                 state->req_data_sent += data_thistime;
    1534             :         }
    1535             : 
    1536      548595 :         if (trailer_thistime > 0) {
    1537             :                 /* Copy in the verification trailer. */
    1538         310 :                 ok = data_blob_append(NULL, &state->rpc_out,
    1539         310 :                                 state->req_trailer.data + state->req_trailer_sent,
    1540             :                                 trailer_thistime);
    1541         310 :                 if (!ok) {
    1542           0 :                         return NT_STATUS_NO_MEMORY;
    1543             :                 }
    1544         310 :                 state->req_trailer_sent += trailer_thistime;
    1545             :         }
    1546             : 
    1547      548595 :         switch (state->cli->auth->auth_level) {
    1548      548229 :         case DCERPC_AUTH_LEVEL_NONE:
    1549             :         case DCERPC_AUTH_LEVEL_CONNECT:
    1550      548229 :                 break;
    1551         366 :         case DCERPC_AUTH_LEVEL_PACKET:
    1552             :         case DCERPC_AUTH_LEVEL_INTEGRITY:
    1553             :         case DCERPC_AUTH_LEVEL_PRIVACY:
    1554         366 :                 status = dcerpc_add_auth_footer(state->cli->auth, pad_len,
    1555             :                                                 &state->rpc_out);
    1556         366 :                 if (!NT_STATUS_IS_OK(status)) {
    1557           0 :                         return status;
    1558             :                 }
    1559         366 :                 break;
    1560           0 :         default:
    1561           0 :                 return NT_STATUS_INVALID_PARAMETER;
    1562             :         }
    1563             : 
    1564      548595 :         *is_last_frag = ((flags & DCERPC_PFC_FLAG_LAST) != 0);
    1565             : 
    1566      548595 :         return status;
    1567             : }
    1568             : 
    1569           0 : static void rpc_api_pipe_req_write_done(struct tevent_req *subreq)
    1570             : {
    1571           0 :         struct tevent_req *req = tevent_req_callback_data(
    1572             :                 subreq, struct tevent_req);
    1573           0 :         struct rpc_api_pipe_req_state *state = tevent_req_data(
    1574             :                 req, struct rpc_api_pipe_req_state);
    1575           0 :         NTSTATUS status;
    1576           0 :         bool is_last_frag;
    1577             : 
    1578           0 :         status = rpc_write_recv(subreq);
    1579           0 :         TALLOC_FREE(subreq);
    1580           0 :         if (tevent_req_nterror(req, status)) {
    1581           0 :                 return;
    1582             :         }
    1583             : 
    1584           0 :         status = prepare_next_frag(state, &is_last_frag);
    1585           0 :         if (tevent_req_nterror(req, status)) {
    1586           0 :                 return;
    1587             :         }
    1588             : 
    1589           0 :         if (is_last_frag) {
    1590           0 :                 subreq = rpc_api_pipe_send(state, state->ev, state->cli,
    1591             :                                            &state->rpc_out,
    1592             :                                            DCERPC_PKT_RESPONSE,
    1593             :                                            state->call_id);
    1594           0 :                 if (tevent_req_nomem(subreq, req)) {
    1595           0 :                         return;
    1596             :                 }
    1597           0 :                 tevent_req_set_callback(subreq, rpc_api_pipe_req_done, req);
    1598             :         } else {
    1599           0 :                 subreq = rpc_write_send(state, state->ev,
    1600           0 :                                         state->cli->transport,
    1601           0 :                                         state->rpc_out.data,
    1602             :                                         state->rpc_out.length);
    1603           0 :                 if (tevent_req_nomem(subreq, req)) {
    1604           0 :                         return;
    1605             :                 }
    1606           0 :                 tevent_req_set_callback(subreq, rpc_api_pipe_req_write_done,
    1607             :                                         req);
    1608             :         }
    1609             : }
    1610             : 
    1611      548595 : static void rpc_api_pipe_req_done(struct tevent_req *subreq)
    1612             : {
    1613      548595 :         struct tevent_req *req = tevent_req_callback_data(
    1614             :                 subreq, struct tevent_req);
    1615      548595 :         struct rpc_api_pipe_req_state *state = tevent_req_data(
    1616             :                 req, struct rpc_api_pipe_req_state);
    1617           0 :         NTSTATUS status;
    1618             : 
    1619      548595 :         status = rpc_api_pipe_recv(subreq, state, NULL, &state->reply_pdu);
    1620      548595 :         TALLOC_FREE(subreq);
    1621      548595 :         if (tevent_req_nterror(req, status)) {
    1622         222 :                 return;
    1623             :         }
    1624             : 
    1625      548373 :         if (state->cli->auth == NULL) {
    1626           0 :                 tevent_req_done(req);
    1627           0 :                 return;
    1628             :         }
    1629             : 
    1630      548373 :         if (state->verify_bitmask1) {
    1631         310 :                 state->cli->auth->verified_bitmask1 = true;
    1632             :         }
    1633             : 
    1634      548373 :         if (state->verify_pcontext) {
    1635         310 :                 state->cli->verified_pcontext = true;
    1636             :         }
    1637             : 
    1638      548373 :         tevent_req_done(req);
    1639             : }
    1640             : 
    1641      548595 : static NTSTATUS rpc_api_pipe_req_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx,
    1642             :                                DATA_BLOB *reply_pdu)
    1643             : {
    1644      548595 :         struct rpc_api_pipe_req_state *state = tevent_req_data(
    1645             :                 req, struct rpc_api_pipe_req_state);
    1646           0 :         NTSTATUS status;
    1647             : 
    1648      548595 :         if (tevent_req_is_nterror(req, &status)) {
    1649             :                 /*
    1650             :                  * We always have to initialize to reply pdu, even if there is
    1651             :                  * none. The rpccli_* caller routines expect this.
    1652             :                  */
    1653         222 :                 *reply_pdu = data_blob_null;
    1654         222 :                 return status;
    1655             :         }
    1656             : 
    1657             :         /* return data to caller and assign it ownership of memory */
    1658      548373 :         reply_pdu->data = talloc_move(mem_ctx, &state->reply_pdu.data);
    1659      548373 :         reply_pdu->length = state->reply_pdu.length;
    1660      548373 :         state->reply_pdu.length = 0;
    1661             : 
    1662      548373 :         return NT_STATUS_OK;
    1663             : }
    1664             : 
    1665             : /****************************************************************************
    1666             :  Check the rpc bind acknowledge response.
    1667             : ****************************************************************************/
    1668             : 
    1669       41838 : static bool check_bind_response(const struct dcerpc_bind_ack *r,
    1670             :                                 struct rpc_pipe_client *cli)
    1671             : {
    1672       41838 :         const struct ndr_syntax_id *transfer = &cli->transfer_syntax;
    1673           0 :         struct dcerpc_ack_ctx ctx;
    1674           0 :         bool equal;
    1675             : 
    1676       41838 :         if (r->secondary_address_size == 0) {
    1677         159 :                 DEBUG(4,("Ignoring length check -- ASU bug (server didn't fill in the pipe name correctly)\n"));
    1678             :         }
    1679             : 
    1680       41838 :         if (r->num_results < 1 || !r->ctx_list) {
    1681           0 :                 return false;
    1682             :         }
    1683             : 
    1684       41838 :         ctx = r->ctx_list[0];
    1685             : 
    1686             :         /* check the transfer syntax */
    1687       41838 :         equal = ndr_syntax_id_equal(&ctx.syntax, transfer);
    1688       41838 :         if (!equal) {
    1689           0 :                 DEBUG(2,("bind_rpc_pipe: transfer syntax differs\n"));
    1690           0 :                 return False;
    1691             :         }
    1692             : 
    1693       41838 :         if (ctx.result != DCERPC_BIND_ACK_RESULT_ACCEPTANCE) {
    1694           0 :                 DBG_NOTICE("bind denied result: %d reason: %x\n",
    1695             :                            ctx.result, ctx.reason.value);
    1696           0 :                 return false;
    1697             :         }
    1698             : 
    1699       41838 :         if (r->num_results >= 2) {
    1700       41679 :                 const struct dcerpc_ack_ctx *neg = &r->ctx_list[1];
    1701             : 
    1702       41679 :                 if (neg->result == DCERPC_BIND_ACK_RESULT_NEGOTIATE_ACK) {
    1703       41679 :                         cli->bind_time_features = neg->reason.negotiate;
    1704             :                 } else {
    1705           0 :                         DBG_DEBUG("bind_time_feature failed - "
    1706             :                                   "result: %d reason %x\n",
    1707             :                                   neg->result, neg->reason.value);
    1708             :                 }
    1709             :         }
    1710             : 
    1711       41838 :         DEBUG(5,("check_bind_response: accepted!\n"));
    1712       41838 :         return True;
    1713             : }
    1714             : 
    1715             : /*******************************************************************
    1716             :  Creates a DCE/RPC bind authentication response.
    1717             :  This is the packet that is sent back to the server once we
    1718             :  have received a BIND-ACK, to finish the third leg of
    1719             :  the authentication handshake.
    1720             :  ********************************************************************/
    1721             : 
    1722          74 : static NTSTATUS create_rpc_bind_auth3(TALLOC_CTX *mem_ctx,
    1723             :                                 struct rpc_pipe_client *cli,
    1724             :                                 struct pipe_auth_data *auth,
    1725             :                                 uint32_t rpc_call_id,
    1726             :                                 DATA_BLOB *pauth_blob,
    1727             :                                 DATA_BLOB *rpc_out)
    1728             : {
    1729           0 :         NTSTATUS status;
    1730          74 :         union dcerpc_payload u = { .auth3._pad = 0, };
    1731             : 
    1732          74 :         status = dcerpc_push_dcerpc_auth(mem_ctx,
    1733             :                                          auth->auth_type,
    1734             :                                          auth->auth_level,
    1735             :                                          0, /* auth_pad_length */
    1736             :                                          auth->auth_context_id,
    1737             :                                          pauth_blob,
    1738             :                                          &u.auth3.auth_info);
    1739          74 :         if (!NT_STATUS_IS_OK(status)) {
    1740           0 :                 return status;
    1741             :         }
    1742             : 
    1743          74 :         status = dcerpc_push_ncacn_packet(mem_ctx,
    1744             :                                           DCERPC_PKT_AUTH3,
    1745             :                                           DCERPC_PFC_FLAG_FIRST |
    1746             :                                           DCERPC_PFC_FLAG_LAST,
    1747          74 :                                           pauth_blob->length,
    1748             :                                           rpc_call_id,
    1749             :                                           &u,
    1750             :                                           rpc_out);
    1751          74 :         data_blob_free(&u.auth3.auth_info);
    1752          74 :         if (!NT_STATUS_IS_OK(status)) {
    1753           0 :                 DEBUG(0,("create_bind_or_alt_ctx_internal: failed to marshall RPC_HDR_RB.\n"));
    1754           0 :                 return status;
    1755             :         }
    1756             : 
    1757          74 :         return NT_STATUS_OK;
    1758             : }
    1759             : 
    1760             : /*******************************************************************
    1761             :  Creates a DCE/RPC bind alter context authentication request which
    1762             :  may contain a spnego auth blob
    1763             :  ********************************************************************/
    1764             : 
    1765         159 : static NTSTATUS create_rpc_alter_context(TALLOC_CTX *mem_ctx,
    1766             :                                         struct pipe_auth_data *auth,
    1767             :                                         uint32_t rpc_call_id,
    1768             :                                         const struct ndr_syntax_id *abstract,
    1769             :                                         const struct ndr_syntax_id *transfer,
    1770             :                                         const DATA_BLOB *pauth_blob, /* spnego auth blob already created. */
    1771             :                                         DATA_BLOB *rpc_out)
    1772             : {
    1773           0 :         DATA_BLOB auth_info;
    1774           0 :         NTSTATUS status;
    1775             : 
    1776         159 :         status = dcerpc_push_dcerpc_auth(mem_ctx,
    1777             :                                          auth->auth_type,
    1778             :                                          auth->auth_level,
    1779             :                                          0, /* auth_pad_length */
    1780             :                                          auth->auth_context_id,
    1781             :                                          pauth_blob,
    1782             :                                          &auth_info);
    1783         159 :         if (!NT_STATUS_IS_OK(status)) {
    1784           0 :                 return status;
    1785             :         }
    1786             : 
    1787         159 :         status = create_bind_or_alt_ctx_internal(mem_ctx,
    1788             :                                                  DCERPC_PKT_ALTER,
    1789             :                                                  rpc_call_id,
    1790             :                                                  abstract,
    1791             :                                                  transfer,
    1792             :                                                  &auth_info,
    1793             :                                                  false, /* client_hdr_signing */
    1794             :                                                  rpc_out);
    1795         159 :         data_blob_free(&auth_info);
    1796         159 :         return status;
    1797             : }
    1798             : 
    1799             : /****************************************************************************
    1800             :  Do an rpc bind.
    1801             : ****************************************************************************/
    1802             : 
    1803             : struct rpc_pipe_bind_state {
    1804             :         struct tevent_context *ev;
    1805             :         struct rpc_pipe_client *cli;
    1806             :         DATA_BLOB rpc_out;
    1807             :         bool auth3;
    1808             :         uint32_t rpc_call_id;
    1809             : };
    1810             : 
    1811             : static void rpc_pipe_bind_step_one_done(struct tevent_req *subreq);
    1812             : static NTSTATUS rpc_bind_next_send(struct tevent_req *req,
    1813             :                                    struct rpc_pipe_bind_state *state,
    1814             :                                    DATA_BLOB *credentials);
    1815             : static NTSTATUS rpc_bind_finish_send(struct tevent_req *req,
    1816             :                                      struct rpc_pipe_bind_state *state,
    1817             :                                      DATA_BLOB *credentials);
    1818             : 
    1819       41679 : struct tevent_req *rpc_pipe_bind_send(TALLOC_CTX *mem_ctx,
    1820             :                                       struct tevent_context *ev,
    1821             :                                       struct rpc_pipe_client *cli,
    1822             :                                       struct pipe_auth_data *auth)
    1823             : {
    1824           0 :         struct tevent_req *req, *subreq;
    1825           0 :         struct rpc_pipe_bind_state *state;
    1826           0 :         NTSTATUS status;
    1827             : 
    1828       41679 :         req = tevent_req_create(mem_ctx, &state, struct rpc_pipe_bind_state);
    1829       41679 :         if (req == NULL) {
    1830           0 :                 return NULL;
    1831             :         }
    1832             : 
    1833       41679 :         DEBUG(5,("Bind RPC Pipe: %s auth_type %u, auth_level %u\n",
    1834             :                 rpccli_pipe_txt(talloc_tos(), cli),
    1835             :                 (unsigned int)auth->auth_type,
    1836             :                 (unsigned int)auth->auth_level ));
    1837             : 
    1838       41679 :         state->ev = ev;
    1839       41679 :         state->cli = cli;
    1840       41679 :         state->rpc_call_id = get_rpc_call_id();
    1841             : 
    1842       41679 :         cli->auth = talloc_move(cli, &auth);
    1843             : 
    1844             :         /* Marshall the outgoing data. */
    1845       41679 :         status = create_rpc_bind_req(state, cli,
    1846             :                                      cli->auth,
    1847       41679 :                                      state->rpc_call_id,
    1848       41679 :                                      &cli->abstract_syntax,
    1849       41679 :                                      &cli->transfer_syntax,
    1850       41679 :                                      &state->rpc_out);
    1851             : 
    1852       41679 :         if (!NT_STATUS_IS_OK(status) &&
    1853           0 :             !NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
    1854           0 :                 tevent_req_nterror(req, status);
    1855           0 :                 return tevent_req_post(req, ev);
    1856             :         }
    1857             : 
    1858       41679 :         subreq = rpc_api_pipe_send(state, ev, cli, &state->rpc_out,
    1859       41679 :                                    DCERPC_PKT_BIND_ACK, state->rpc_call_id);
    1860       41679 :         if (tevent_req_nomem(subreq, req)) {
    1861           0 :                 return tevent_req_post(req, ev);
    1862             :         }
    1863       41679 :         tevent_req_set_callback(subreq, rpc_pipe_bind_step_one_done, req);
    1864       41679 :         return req;
    1865             : }
    1866             : 
    1867       41912 : static void rpc_pipe_bind_step_one_done(struct tevent_req *subreq)
    1868             : {
    1869       41912 :         struct tevent_req *req = tevent_req_callback_data(
    1870             :                 subreq, struct tevent_req);
    1871       41912 :         struct rpc_pipe_bind_state *state = tevent_req_data(
    1872             :                 req, struct rpc_pipe_bind_state);
    1873       41912 :         struct pipe_auth_data *pauth = state->cli->auth;
    1874           0 :         struct gensec_security *gensec_security;
    1875       41912 :         struct ncacn_packet *pkt = NULL;
    1876           0 :         struct dcerpc_auth auth;
    1877       41912 :         DATA_BLOB auth_token = { .data = NULL };
    1878           0 :         NTSTATUS status;
    1879             : 
    1880       41912 :         status = rpc_api_pipe_recv(subreq, talloc_tos(), &pkt, NULL);
    1881       41912 :         TALLOC_FREE(subreq);
    1882       41912 :         if (tevent_req_nterror(req, status)) {
    1883           0 :                 DEBUG(3, ("rpc_pipe_bind: %s bind request returned %s\n",
    1884             :                           rpccli_pipe_txt(talloc_tos(), state->cli),
    1885             :                           nt_errstr(status)));
    1886           0 :                 return;
    1887             :         }
    1888             : 
    1889       41912 :         if (state->auth3) {
    1890          74 :                 tevent_req_done(req);
    1891          74 :                 return;
    1892             :         }
    1893             : 
    1894       41838 :         if (!check_bind_response(&pkt->u.bind_ack, state->cli)) {
    1895           0 :                 DEBUG(2, ("rpc_pipe_bind: check_bind_response failed.\n"));
    1896           0 :                 tevent_req_nterror(req, NT_STATUS_BUFFER_TOO_SMALL);
    1897           0 :                 return;
    1898             :         }
    1899             : 
    1900       41838 :         if (pkt->ptype == DCERPC_PKT_BIND_ACK) {
    1901       41679 :                 if (pkt->pfc_flags & DCERPC_PFC_FLAG_SUPPORT_HEADER_SIGN) {
    1902         310 :                         if (pauth->client_hdr_signing) {
    1903         310 :                                 pauth->hdr_signing = true;
    1904             :                         }
    1905             :                 }
    1906             :         }
    1907             : 
    1908       41838 :         state->cli->max_xmit_frag = pkt->u.bind_ack.max_xmit_frag;
    1909             : 
    1910       41838 :         if (pauth->auth_type == DCERPC_AUTH_TYPE_NONE) {
    1911             :                 /* Bind complete. */
    1912       41203 :                 tevent_req_done(req);
    1913       41203 :                 return;
    1914             :         }
    1915             : 
    1916         635 :         if (pkt->auth_length == 0) {
    1917           0 :                 tevent_req_nterror(req, NT_STATUS_RPC_PROTOCOL_ERROR);
    1918           0 :                 return;
    1919             :         }
    1920             : 
    1921             :         /* get auth credentials */
    1922         635 :         status = dcerpc_pull_auth_trailer(pkt, talloc_tos(),
    1923         635 :                                           &pkt->u.bind_ack.auth_info,
    1924             :                                           &auth, NULL, true);
    1925         635 :         if (tevent_req_nterror(req, status)) {
    1926           0 :                 DEBUG(0, ("Failed to pull dcerpc auth: %s.\n",
    1927             :                           nt_errstr(status)));
    1928           0 :                 return;
    1929             :         }
    1930             : 
    1931         635 :         if (auth.auth_type != pauth->auth_type) {
    1932           0 :                 DBG_ERR("Auth type %u mismatch expected %u.\n",
    1933             :                         auth.auth_type, pauth->auth_type);
    1934           0 :                 tevent_req_nterror(req, NT_STATUS_RPC_PROTOCOL_ERROR);
    1935           0 :                 return;
    1936             :         }
    1937             : 
    1938         635 :         if (auth.auth_level != pauth->auth_level) {
    1939           0 :                 DBG_ERR("Auth level %u mismatch expected %u.\n",
    1940             :                         auth.auth_level, pauth->auth_level);
    1941           0 :                 tevent_req_nterror(req, NT_STATUS_RPC_PROTOCOL_ERROR);
    1942           0 :                 return;
    1943             :         }
    1944             : 
    1945         635 :         if (auth.auth_context_id != pauth->auth_context_id) {
    1946           0 :                 DBG_ERR("Auth context id %"PRIu32" mismatch "
    1947             :                         "expected %"PRIu32".\n",
    1948             :                         auth.auth_context_id,
    1949             :                         pauth->auth_context_id);
    1950           0 :                 tevent_req_nterror(req, NT_STATUS_RPC_PROTOCOL_ERROR);
    1951           0 :                 return;
    1952             :         }
    1953             : 
    1954             :         /*
    1955             :          * For authenticated binds we may need to do 3 or 4 leg binds.
    1956             :          */
    1957             : 
    1958         635 :         if (pauth->auth_type == DCERPC_AUTH_TYPE_NONE) {
    1959             :                 /* Bind complete. */
    1960           0 :                 tevent_req_done(req);
    1961           0 :                 return;
    1962             :         }
    1963             : 
    1964         635 :         gensec_security = pauth->auth_ctx;
    1965             : 
    1966         635 :         status = gensec_update(gensec_security, state,
    1967             :                                auth.credentials, &auth_token);
    1968         635 :         if (NT_STATUS_EQUAL(status,
    1969             :                             NT_STATUS_MORE_PROCESSING_REQUIRED)) {
    1970         159 :                 status = rpc_bind_next_send(req, state,
    1971             :                                             &auth_token);
    1972         476 :         } else if (NT_STATUS_IS_OK(status)) {
    1973         476 :                 if (pauth->hdr_signing) {
    1974         310 :                         gensec_want_feature(gensec_security,
    1975             :                                             GENSEC_FEATURE_SIGN_PKT_HEADER);
    1976             :                 }
    1977             : 
    1978         476 :                 if (auth_token.length == 0) {
    1979             :                         /* Bind complete. */
    1980         402 :                         tevent_req_done(req);
    1981         402 :                         return;
    1982             :                 }
    1983          74 :                 status = rpc_bind_finish_send(req, state,
    1984             :                                               &auth_token);
    1985             :         }
    1986             : 
    1987         233 :         if (!NT_STATUS_IS_OK(status)) {
    1988           0 :                 tevent_req_nterror(req, status);
    1989             :         }
    1990         233 :         return;
    1991             : }
    1992             : 
    1993         159 : static NTSTATUS rpc_bind_next_send(struct tevent_req *req,
    1994             :                                    struct rpc_pipe_bind_state *state,
    1995             :                                    DATA_BLOB *auth_token)
    1996             : {
    1997         159 :         struct pipe_auth_data *auth = state->cli->auth;
    1998           0 :         struct tevent_req *subreq;
    1999           0 :         NTSTATUS status;
    2000             : 
    2001             :         /* Now prepare the alter context pdu. */
    2002         159 :         data_blob_free(&state->rpc_out);
    2003             : 
    2004         159 :         status = create_rpc_alter_context(state, auth,
    2005             :                                           state->rpc_call_id,
    2006         159 :                                           &state->cli->abstract_syntax,
    2007         159 :                                           &state->cli->transfer_syntax,
    2008             :                                           auth_token,
    2009             :                                           &state->rpc_out);
    2010         159 :         if (!NT_STATUS_IS_OK(status)) {
    2011           0 :                 return status;
    2012             :         }
    2013             : 
    2014         159 :         subreq = rpc_api_pipe_send(state, state->ev, state->cli,
    2015             :                                    &state->rpc_out, DCERPC_PKT_ALTER_RESP,
    2016             :                                    state->rpc_call_id);
    2017         159 :         if (subreq == NULL) {
    2018           0 :                 return NT_STATUS_NO_MEMORY;
    2019             :         }
    2020         159 :         tevent_req_set_callback(subreq, rpc_pipe_bind_step_one_done, req);
    2021         159 :         return NT_STATUS_OK;
    2022             : }
    2023             : 
    2024          74 : static NTSTATUS rpc_bind_finish_send(struct tevent_req *req,
    2025             :                                      struct rpc_pipe_bind_state *state,
    2026             :                                      DATA_BLOB *auth_token)
    2027             : {
    2028          74 :         struct pipe_auth_data *auth = state->cli->auth;
    2029           0 :         struct tevent_req *subreq;
    2030           0 :         NTSTATUS status;
    2031             : 
    2032          74 :         state->auth3 = true;
    2033             : 
    2034             :         /* Now prepare the auth3 context pdu. */
    2035          74 :         data_blob_free(&state->rpc_out);
    2036             : 
    2037          74 :         status = create_rpc_bind_auth3(state, state->cli, auth,
    2038             :                                         state->rpc_call_id,
    2039             :                                         auth_token,
    2040             :                                         &state->rpc_out);
    2041          74 :         if (!NT_STATUS_IS_OK(status)) {
    2042           0 :                 return status;
    2043             :         }
    2044             : 
    2045          74 :         subreq = rpc_api_pipe_send(state, state->ev, state->cli,
    2046             :                                    &state->rpc_out, DCERPC_PKT_AUTH3,
    2047             :                                    state->rpc_call_id);
    2048          74 :         if (subreq == NULL) {
    2049           0 :                 return NT_STATUS_NO_MEMORY;
    2050             :         }
    2051          74 :         tevent_req_set_callback(subreq, rpc_pipe_bind_step_one_done, req);
    2052          74 :         return NT_STATUS_OK;
    2053             : }
    2054             : 
    2055       41679 : NTSTATUS rpc_pipe_bind_recv(struct tevent_req *req)
    2056             : {
    2057       41679 :         return tevent_req_simple_recv_ntstatus(req);
    2058             : }
    2059             : 
    2060       41679 : NTSTATUS rpc_pipe_bind(struct rpc_pipe_client *cli,
    2061             :                        struct pipe_auth_data *auth)
    2062             : {
    2063       41679 :         TALLOC_CTX *frame = talloc_stackframe();
    2064           0 :         struct tevent_context *ev;
    2065           0 :         struct tevent_req *req;
    2066       41679 :         NTSTATUS status = NT_STATUS_OK;
    2067             : 
    2068       41679 :         ev = samba_tevent_context_init(frame);
    2069       41679 :         if (ev == NULL) {
    2070           0 :                 status = NT_STATUS_NO_MEMORY;
    2071           0 :                 goto fail;
    2072             :         }
    2073             : 
    2074       41679 :         req = rpc_pipe_bind_send(frame, ev, cli, auth);
    2075       41679 :         if (req == NULL) {
    2076           0 :                 status = NT_STATUS_NO_MEMORY;
    2077           0 :                 goto fail;
    2078             :         }
    2079             : 
    2080       41679 :         if (!tevent_req_poll_ntstatus(req, ev, &status)) {
    2081           0 :                 goto fail;
    2082             :         }
    2083             : 
    2084       41679 :         status = rpc_pipe_bind_recv(req);
    2085       41679 :  fail:
    2086       41679 :         TALLOC_FREE(frame);
    2087       41679 :         return status;
    2088             : }
    2089             : 
    2090             : #define RPCCLI_DEFAULT_TIMEOUT 10000 /* 10 seconds. */
    2091             : 
    2092         700 : unsigned int rpccli_set_timeout(struct rpc_pipe_client *rpc_cli,
    2093             :                                 unsigned int timeout)
    2094             : {
    2095         700 :         if (rpc_cli == NULL) {
    2096           0 :                 return RPCCLI_DEFAULT_TIMEOUT;
    2097             :         }
    2098             : 
    2099         700 :         if (rpc_cli->binding_handle == NULL) {
    2100           0 :                 return RPCCLI_DEFAULT_TIMEOUT;
    2101             :         }
    2102             : 
    2103         700 :         return dcerpc_binding_handle_set_timeout(rpc_cli->binding_handle,
    2104             :                                                  timeout);
    2105             : }
    2106             : 
    2107         169 : bool rpccli_is_connected(struct rpc_pipe_client *rpc_cli)
    2108             : {
    2109         169 :         if (rpc_cli == NULL) {
    2110          84 :                 return false;
    2111             :         }
    2112             : 
    2113          85 :         if (rpc_cli->binding_handle == NULL) {
    2114           0 :                 return false;
    2115             :         }
    2116             : 
    2117          85 :         return dcerpc_binding_handle_is_connected(rpc_cli->binding_handle);
    2118             : }
    2119             : 
    2120             : struct rpccli_bh_state {
    2121             :         struct rpc_pipe_client *rpc_cli;
    2122             : };
    2123             : 
    2124      548680 : static bool rpccli_bh_is_connected(struct dcerpc_binding_handle *h)
    2125             : {
    2126      548680 :         struct rpccli_bh_state *hs = dcerpc_binding_handle_data(h,
    2127             :                                      struct rpccli_bh_state);
    2128      548680 :         struct rpc_cli_transport *transport = hs->rpc_cli->transport;
    2129             : 
    2130      548680 :         if (transport == NULL) {
    2131           0 :                 return false;
    2132             :         }
    2133             : 
    2134      548680 :         if (transport->is_connected == NULL) {
    2135           0 :                 return false;
    2136             :         }
    2137             : 
    2138      548680 :         return transport->is_connected(transport->priv);
    2139             : }
    2140             : 
    2141         716 : static uint32_t rpccli_bh_set_timeout(struct dcerpc_binding_handle *h,
    2142             :                                       uint32_t timeout)
    2143             : {
    2144         716 :         struct rpccli_bh_state *hs = dcerpc_binding_handle_data(h,
    2145             :                                      struct rpccli_bh_state);
    2146         716 :         struct rpc_cli_transport *transport = hs->rpc_cli->transport;
    2147           0 :         unsigned int old;
    2148             : 
    2149         716 :         if (transport == NULL) {
    2150           0 :                 return RPCCLI_DEFAULT_TIMEOUT;
    2151             :         }
    2152             : 
    2153         716 :         if (transport->set_timeout == NULL) {
    2154           0 :                 return RPCCLI_DEFAULT_TIMEOUT;
    2155             :         }
    2156             : 
    2157         716 :         old = transport->set_timeout(transport->priv, timeout);
    2158         716 :         if (old == 0) {
    2159           0 :                 return RPCCLI_DEFAULT_TIMEOUT;
    2160             :         }
    2161             : 
    2162         716 :         return old;
    2163             : }
    2164             : 
    2165         171 : static void rpccli_bh_auth_info(struct dcerpc_binding_handle *h,
    2166             :                                 enum dcerpc_AuthType *auth_type,
    2167             :                                 enum dcerpc_AuthLevel *auth_level)
    2168             : {
    2169         171 :         struct rpccli_bh_state *hs = dcerpc_binding_handle_data(h,
    2170             :                                      struct rpccli_bh_state);
    2171             : 
    2172         171 :         if (hs->rpc_cli == NULL) {
    2173           0 :                 return;
    2174             :         }
    2175             : 
    2176         171 :         if (hs->rpc_cli->auth == NULL) {
    2177           0 :                 return;
    2178             :         }
    2179             : 
    2180         171 :         *auth_type = hs->rpc_cli->auth->auth_type;
    2181         171 :         *auth_level = hs->rpc_cli->auth->auth_level;
    2182             : }
    2183             : 
    2184             : struct rpccli_bh_raw_call_state {
    2185             :         DATA_BLOB in_data;
    2186             :         DATA_BLOB out_data;
    2187             :         uint32_t out_flags;
    2188             : };
    2189             : 
    2190             : static void rpccli_bh_raw_call_done(struct tevent_req *subreq);
    2191             : 
    2192      548595 : static struct tevent_req *rpccli_bh_raw_call_send(TALLOC_CTX *mem_ctx,
    2193             :                                                   struct tevent_context *ev,
    2194             :                                                   struct dcerpc_binding_handle *h,
    2195             :                                                   const struct GUID *object,
    2196             :                                                   uint32_t opnum,
    2197             :                                                   uint32_t in_flags,
    2198             :                                                   const uint8_t *in_data,
    2199             :                                                   size_t in_length)
    2200             : {
    2201      548595 :         struct rpccli_bh_state *hs = dcerpc_binding_handle_data(h,
    2202             :                                      struct rpccli_bh_state);
    2203           0 :         struct tevent_req *req;
    2204           0 :         struct rpccli_bh_raw_call_state *state;
    2205           0 :         bool ok;
    2206           0 :         struct tevent_req *subreq;
    2207             : 
    2208      548595 :         req = tevent_req_create(mem_ctx, &state,
    2209             :                                 struct rpccli_bh_raw_call_state);
    2210      548595 :         if (req == NULL) {
    2211           0 :                 return NULL;
    2212             :         }
    2213      548595 :         state->in_data.data = discard_const_p(uint8_t, in_data);
    2214      548595 :         state->in_data.length = in_length;
    2215             : 
    2216      548595 :         ok = rpccli_bh_is_connected(h);
    2217      548595 :         if (!ok) {
    2218           0 :                 tevent_req_nterror(req, NT_STATUS_CONNECTION_DISCONNECTED);
    2219           0 :                 return tevent_req_post(req, ev);
    2220             :         }
    2221             : 
    2222      548595 :         subreq = rpc_api_pipe_req_send(state, ev, hs->rpc_cli,
    2223      548595 :                                        opnum, object, &state->in_data);
    2224      548595 :         if (tevent_req_nomem(subreq, req)) {
    2225           0 :                 return tevent_req_post(req, ev);
    2226             :         }
    2227      548595 :         tevent_req_set_callback(subreq, rpccli_bh_raw_call_done, req);
    2228             : 
    2229      548595 :         return req;
    2230             : }
    2231             : 
    2232      548595 : static void rpccli_bh_raw_call_done(struct tevent_req *subreq)
    2233             : {
    2234           0 :         struct tevent_req *req =
    2235      548595 :                 tevent_req_callback_data(subreq,
    2236             :                 struct tevent_req);
    2237           0 :         struct rpccli_bh_raw_call_state *state =
    2238      548595 :                 tevent_req_data(req,
    2239             :                 struct rpccli_bh_raw_call_state);
    2240           0 :         NTSTATUS status;
    2241             : 
    2242      548595 :         state->out_flags = 0;
    2243             : 
    2244             :         /* TODO: support bigendian responses */
    2245             : 
    2246      548595 :         status = rpc_api_pipe_req_recv(subreq, state, &state->out_data);
    2247      548595 :         TALLOC_FREE(subreq);
    2248      548595 :         if (tevent_req_nterror(req, status)) {
    2249         222 :                 return;
    2250             :         }
    2251             : 
    2252      548373 :         tevent_req_done(req);
    2253             : }
    2254             : 
    2255      548595 : static NTSTATUS rpccli_bh_raw_call_recv(struct tevent_req *req,
    2256             :                                         TALLOC_CTX *mem_ctx,
    2257             :                                         uint8_t **out_data,
    2258             :                                         size_t *out_length,
    2259             :                                         uint32_t *out_flags)
    2260             : {
    2261           0 :         struct rpccli_bh_raw_call_state *state =
    2262      548595 :                 tevent_req_data(req,
    2263             :                 struct rpccli_bh_raw_call_state);
    2264           0 :         NTSTATUS status;
    2265             : 
    2266      548595 :         if (tevent_req_is_nterror(req, &status)) {
    2267         222 :                 tevent_req_received(req);
    2268         222 :                 return status;
    2269             :         }
    2270             : 
    2271      548373 :         *out_data = talloc_move(mem_ctx, &state->out_data.data);
    2272      548373 :         *out_length = state->out_data.length;
    2273      548373 :         *out_flags = state->out_flags;
    2274      548373 :         tevent_req_received(req);
    2275      548373 :         return NT_STATUS_OK;
    2276             : }
    2277             : 
    2278             : struct rpccli_bh_disconnect_state {
    2279             :         uint8_t _dummy;
    2280             : };
    2281             : 
    2282           0 : static struct tevent_req *rpccli_bh_disconnect_send(TALLOC_CTX *mem_ctx,
    2283             :                                                 struct tevent_context *ev,
    2284             :                                                 struct dcerpc_binding_handle *h)
    2285             : {
    2286           0 :         struct rpccli_bh_state *hs = dcerpc_binding_handle_data(h,
    2287             :                                      struct rpccli_bh_state);
    2288           0 :         struct tevent_req *req;
    2289           0 :         struct rpccli_bh_disconnect_state *state;
    2290           0 :         bool ok;
    2291             : 
    2292           0 :         req = tevent_req_create(mem_ctx, &state,
    2293             :                                 struct rpccli_bh_disconnect_state);
    2294           0 :         if (req == NULL) {
    2295           0 :                 return NULL;
    2296             :         }
    2297             : 
    2298           0 :         ok = rpccli_bh_is_connected(h);
    2299           0 :         if (!ok) {
    2300           0 :                 tevent_req_nterror(req, NT_STATUS_CONNECTION_DISCONNECTED);
    2301           0 :                 return tevent_req_post(req, ev);
    2302             :         }
    2303             : 
    2304             :         /*
    2305             :          * TODO: do a real async disconnect ...
    2306             :          *
    2307             :          * For now we do it sync...
    2308             :          */
    2309           0 :         TALLOC_FREE(hs->rpc_cli->transport);
    2310           0 :         hs->rpc_cli = NULL;
    2311             : 
    2312           0 :         tevent_req_done(req);
    2313           0 :         return tevent_req_post(req, ev);
    2314             : }
    2315             : 
    2316           0 : static NTSTATUS rpccli_bh_disconnect_recv(struct tevent_req *req)
    2317             : {
    2318           0 :         return tevent_req_simple_recv_ntstatus(req);
    2319             : }
    2320             : 
    2321      548595 : static bool rpccli_bh_ref_alloc(struct dcerpc_binding_handle *h)
    2322             : {
    2323      548595 :         return true;
    2324             : }
    2325             : 
    2326     1096968 : static void rpccli_bh_do_ndr_print(struct dcerpc_binding_handle *h,
    2327             :                                    ndr_flags_type ndr_flags,
    2328             :                                    const void *_struct_ptr,
    2329             :                                    const struct ndr_interface_call *call)
    2330             : {
    2331     1096968 :         void *struct_ptr = discard_const(_struct_ptr);
    2332             : 
    2333     1096968 :         if (DEBUGLEVEL < 10) {
    2334     1096780 :                 return;
    2335             :         }
    2336             : 
    2337         188 :         if (ndr_flags & NDR_IN) {
    2338          94 :                 ndr_print_function_debug(call->ndr_print,
    2339          94 :                                          call->name,
    2340             :                                          ndr_flags,
    2341             :                                          struct_ptr);
    2342             :         }
    2343         188 :         if (ndr_flags & NDR_OUT) {
    2344          94 :                 ndr_print_function_debug(call->ndr_print,
    2345          94 :                                          call->name,
    2346             :                                          ndr_flags,
    2347             :                                          struct_ptr);
    2348             :         }
    2349             : }
    2350             : 
    2351             : static const struct dcerpc_binding_handle_ops rpccli_bh_ops = {
    2352             :         .name                   = "rpccli",
    2353             :         .is_connected           = rpccli_bh_is_connected,
    2354             :         .set_timeout            = rpccli_bh_set_timeout,
    2355             :         .auth_info              = rpccli_bh_auth_info,
    2356             :         .raw_call_send          = rpccli_bh_raw_call_send,
    2357             :         .raw_call_recv          = rpccli_bh_raw_call_recv,
    2358             :         .disconnect_send        = rpccli_bh_disconnect_send,
    2359             :         .disconnect_recv        = rpccli_bh_disconnect_recv,
    2360             : 
    2361             :         .ref_alloc              = rpccli_bh_ref_alloc,
    2362             :         .do_ndr_print           = rpccli_bh_do_ndr_print,
    2363             : };
    2364             : 
    2365             : /* initialise a rpc_pipe_client binding handle */
    2366       41679 : struct dcerpc_binding_handle *rpccli_bh_create(struct rpc_pipe_client *c,
    2367             :                                         const struct GUID *object,
    2368             :                                         const struct ndr_interface_table *table)
    2369             : {
    2370           0 :         struct dcerpc_binding_handle *h;
    2371           0 :         struct rpccli_bh_state *hs;
    2372             : 
    2373       41679 :         h = dcerpc_binding_handle_create(c,
    2374             :                                          &rpccli_bh_ops,
    2375             :                                          object,
    2376             :                                          table,
    2377             :                                          &hs,
    2378             :                                          struct rpccli_bh_state,
    2379             :                                          __location__);
    2380       41679 :         if (h == NULL) {
    2381           0 :                 return NULL;
    2382             :         }
    2383       41679 :         hs->rpc_cli = c;
    2384             : 
    2385       41679 :         return h;
    2386             : }
    2387             : 
    2388       41203 : NTSTATUS rpccli_anon_bind_data(TALLOC_CTX *mem_ctx,
    2389             :                                struct pipe_auth_data **presult)
    2390             : {
    2391           0 :         struct pipe_auth_data *result;
    2392           0 :         struct auth_generic_state *auth_generic_ctx;
    2393           0 :         NTSTATUS status;
    2394             : 
    2395       41203 :         result = talloc_zero(mem_ctx, struct pipe_auth_data);
    2396       41203 :         if (result == NULL) {
    2397           0 :                 return NT_STATUS_NO_MEMORY;
    2398             :         }
    2399             : 
    2400       41203 :         result->auth_type = DCERPC_AUTH_TYPE_NONE;
    2401       41203 :         result->auth_level = DCERPC_AUTH_LEVEL_NONE;
    2402       41203 :         result->auth_context_id = 0;
    2403             : 
    2404       41203 :         status = auth_generic_client_prepare(result,
    2405             :                                              &auth_generic_ctx);
    2406       41203 :         if (!NT_STATUS_IS_OK(status)) {
    2407           0 :                 DEBUG(1, ("Failed to create auth_generic context: %s\n",
    2408             :                           nt_errstr(status)));
    2409             :         }
    2410             : 
    2411       41203 :         status = auth_generic_set_username(auth_generic_ctx, "");
    2412       41203 :         if (!NT_STATUS_IS_OK(status)) {
    2413           0 :                 DEBUG(1, ("Failed to set username: %s\n",
    2414             :                           nt_errstr(status)));
    2415             :         }
    2416             : 
    2417       41203 :         status = auth_generic_set_domain(auth_generic_ctx, "");
    2418       41203 :         if (!NT_STATUS_IS_OK(status)) {
    2419           0 :                 DEBUG(1, ("Failed to set domain: %s\n",
    2420             :                           nt_errstr(status)));
    2421           0 :                 return status;
    2422             :         }
    2423             : 
    2424       41203 :         status = gensec_set_credentials(auth_generic_ctx->gensec_security,
    2425       41203 :                                         auth_generic_ctx->credentials);
    2426       41203 :         if (!NT_STATUS_IS_OK(status)) {
    2427           0 :                 DEBUG(1, ("Failed to set GENSEC credentials: %s\n",
    2428             :                           nt_errstr(status)));
    2429           0 :                 return status;
    2430             :         }
    2431       41203 :         talloc_unlink(auth_generic_ctx, auth_generic_ctx->credentials);
    2432       41203 :         auth_generic_ctx->credentials = NULL;
    2433             : 
    2434       41203 :         result->auth_ctx = talloc_move(result, &auth_generic_ctx->gensec_security);
    2435       41203 :         talloc_free(auth_generic_ctx);
    2436       41203 :         *presult = result;
    2437       41203 :         return NT_STATUS_OK;
    2438             : }
    2439             : 
    2440         136 : static NTSTATUS rpccli_generic_bind_data(TALLOC_CTX *mem_ctx,
    2441             :                                          enum dcerpc_AuthType auth_type,
    2442             :                                          enum dcerpc_AuthLevel auth_level,
    2443             :                                          const char *server,
    2444             :                                          const char *target_service,
    2445             :                                          const char *domain,
    2446             :                                          const char *username,
    2447             :                                          const char *password,
    2448             :                                          enum credentials_use_kerberos use_kerberos,
    2449             :                                          struct netlogon_creds_CredentialState *creds,
    2450             :                                          struct pipe_auth_data **presult)
    2451             : {
    2452           0 :         struct auth_generic_state *auth_generic_ctx;
    2453           0 :         struct pipe_auth_data *result;
    2454           0 :         NTSTATUS status;
    2455             : 
    2456         136 :         result = talloc_zero(mem_ctx, struct pipe_auth_data);
    2457         136 :         if (result == NULL) {
    2458           0 :                 return NT_STATUS_NO_MEMORY;
    2459             :         }
    2460             : 
    2461         136 :         result->auth_type = auth_type;
    2462         136 :         result->auth_level = auth_level;
    2463         136 :         result->auth_context_id = 1;
    2464             : 
    2465         136 :         status = auth_generic_client_prepare(result,
    2466             :                                              &auth_generic_ctx);
    2467         136 :         if (!NT_STATUS_IS_OK(status)) {
    2468           0 :                 goto fail;
    2469             :         }
    2470             : 
    2471         136 :         status = auth_generic_set_username(auth_generic_ctx, username);
    2472         136 :         if (!NT_STATUS_IS_OK(status)) {
    2473           0 :                 goto fail;
    2474             :         }
    2475             : 
    2476         136 :         status = auth_generic_set_domain(auth_generic_ctx, domain);
    2477         136 :         if (!NT_STATUS_IS_OK(status)) {
    2478           0 :                 goto fail;
    2479             :         }
    2480             : 
    2481         136 :         status = auth_generic_set_password(auth_generic_ctx, password);
    2482         136 :         if (!NT_STATUS_IS_OK(status)) {
    2483           0 :                 goto fail;
    2484             :         }
    2485             : 
    2486         136 :         status = gensec_set_target_service(auth_generic_ctx->gensec_security, target_service);
    2487         136 :         if (!NT_STATUS_IS_OK(status)) {
    2488           0 :                 goto fail;
    2489             :         }
    2490             : 
    2491         136 :         status = gensec_set_target_hostname(auth_generic_ctx->gensec_security, server);
    2492         136 :         if (!NT_STATUS_IS_OK(status)) {
    2493           0 :                 goto fail;
    2494             :         }
    2495             : 
    2496         136 :         cli_credentials_set_kerberos_state(auth_generic_ctx->credentials,
    2497             :                                            use_kerberos,
    2498             :                                            CRED_SPECIFIED);
    2499         136 :         cli_credentials_set_netlogon_creds(auth_generic_ctx->credentials, creds);
    2500             : 
    2501         136 :         status = auth_generic_client_start_by_authtype(auth_generic_ctx, auth_type, auth_level);
    2502         136 :         if (!NT_STATUS_IS_OK(status)) {
    2503           0 :                 goto fail;
    2504             :         }
    2505             : 
    2506         136 :         result->auth_ctx = talloc_move(result, &auth_generic_ctx->gensec_security);
    2507         136 :         talloc_free(auth_generic_ctx);
    2508         136 :         *presult = result;
    2509         136 :         return NT_STATUS_OK;
    2510             : 
    2511           0 :  fail:
    2512           0 :         TALLOC_FREE(result);
    2513           0 :         return status;
    2514             : }
    2515             : 
    2516             : /* This routine steals the creds pointer that is passed in */
    2517         340 : static NTSTATUS rpccli_generic_bind_data_from_creds(TALLOC_CTX *mem_ctx,
    2518             :                                                     enum dcerpc_AuthType auth_type,
    2519             :                                                     enum dcerpc_AuthLevel auth_level,
    2520             :                                                     const char *server,
    2521             :                                                     const char *target_service,
    2522             :                                                     struct cli_credentials *creds,
    2523             :                                                     struct pipe_auth_data **presult)
    2524             : {
    2525           0 :         struct auth_generic_state *auth_generic_ctx;
    2526           0 :         struct pipe_auth_data *result;
    2527           0 :         NTSTATUS status;
    2528             : 
    2529         340 :         result = talloc_zero(mem_ctx, struct pipe_auth_data);
    2530         340 :         if (result == NULL) {
    2531           0 :                 return NT_STATUS_NO_MEMORY;
    2532             :         }
    2533             : 
    2534         340 :         result->auth_type = auth_type;
    2535         340 :         result->auth_level = auth_level;
    2536         340 :         result->auth_context_id = 1;
    2537             : 
    2538         340 :         status = auth_generic_client_prepare(result,
    2539             :                                              &auth_generic_ctx);
    2540         340 :         if (!NT_STATUS_IS_OK(status)) {
    2541           0 :                 goto fail;
    2542             :         }
    2543             : 
    2544         340 :         status = auth_generic_set_creds(auth_generic_ctx, creds);
    2545         340 :         if (!NT_STATUS_IS_OK(status)) {
    2546           0 :                 goto fail;
    2547             :         }
    2548             : 
    2549         340 :         status = gensec_set_target_service(auth_generic_ctx->gensec_security, target_service);
    2550         340 :         if (!NT_STATUS_IS_OK(status)) {
    2551           0 :                 goto fail;
    2552             :         }
    2553             : 
    2554         340 :         status = gensec_set_target_hostname(auth_generic_ctx->gensec_security, server);
    2555         340 :         if (!NT_STATUS_IS_OK(status)) {
    2556           0 :                 goto fail;
    2557             :         }
    2558             : 
    2559         340 :         status = auth_generic_client_start_by_authtype(auth_generic_ctx, auth_type, auth_level);
    2560         340 :         if (!NT_STATUS_IS_OK(status)) {
    2561           0 :                 goto fail;
    2562             :         }
    2563             : 
    2564         340 :         result->auth_ctx = talloc_move(result, &auth_generic_ctx->gensec_security);
    2565         340 :         talloc_free(auth_generic_ctx);
    2566         340 :         *presult = result;
    2567         340 :         return NT_STATUS_OK;
    2568             : 
    2569           0 :  fail:
    2570           0 :         TALLOC_FREE(result);
    2571           0 :         return status;
    2572             : }
    2573             : 
    2574         136 : NTSTATUS rpccli_ncalrpc_bind_data(TALLOC_CTX *mem_ctx,
    2575             :                                   struct pipe_auth_data **presult)
    2576             : {
    2577         136 :         return rpccli_generic_bind_data(mem_ctx,
    2578             :                                         DCERPC_AUTH_TYPE_NCALRPC_AS_SYSTEM,
    2579             :                                         DCERPC_AUTH_LEVEL_CONNECT,
    2580             :                                         NULL, /* server */
    2581             :                                         "host", /* target_service */
    2582             :                                         NAME_NT_AUTHORITY, /* domain */
    2583             :                                         "SYSTEM",
    2584             :                                         NULL, /* password */
    2585             :                                         CRED_USE_KERBEROS_DISABLED,
    2586             :                                         NULL, /* netlogon_creds_CredentialState */
    2587             :                                         presult);
    2588             : }
    2589             : 
    2590             : /**
    2591             :  * Create an rpc pipe client struct, connecting to a tcp port.
    2592             :  */
    2593         100 : static NTSTATUS rpc_pipe_open_tcp_port(TALLOC_CTX *mem_ctx, const char *host,
    2594             :                                        const struct sockaddr_storage *ss_addr,
    2595             :                                        uint16_t port,
    2596             :                                        const struct ndr_interface_table *table,
    2597             :                                        struct rpc_pipe_client **presult)
    2598             : {
    2599           0 :         struct rpc_pipe_client *result;
    2600           0 :         struct sockaddr_storage addr;
    2601           0 :         NTSTATUS status;
    2602           0 :         int fd;
    2603             : 
    2604         100 :         result = talloc_zero(mem_ctx, struct rpc_pipe_client);
    2605         100 :         if (result == NULL) {
    2606           0 :                 return NT_STATUS_NO_MEMORY;
    2607             :         }
    2608             : 
    2609         100 :         result->abstract_syntax = table->syntax_id;
    2610         100 :         result->transfer_syntax = ndr_transfer_syntax_ndr;
    2611             : 
    2612         100 :         result->desthost = talloc_strdup(result, host);
    2613         100 :         if (result->desthost == NULL) {
    2614           0 :                 status = NT_STATUS_NO_MEMORY;
    2615           0 :                 goto fail;
    2616             :         }
    2617             : 
    2618         100 :         result->srv_name_slash = talloc_asprintf_strupper_m(
    2619             :                 result, "\\\\%s", result->desthost);
    2620         100 :         if (result->srv_name_slash == NULL) {
    2621           0 :                 status = NT_STATUS_NO_MEMORY;
    2622           0 :                 goto fail;
    2623             :         }
    2624             : 
    2625         100 :         result->max_xmit_frag = RPC_MAX_PDU_FRAG_LEN;
    2626             : 
    2627         100 :         if (ss_addr == NULL) {
    2628           0 :                 if (!resolve_name(host, &addr, NBT_NAME_SERVER, false)) {
    2629           0 :                         status = NT_STATUS_NOT_FOUND;
    2630           0 :                         goto fail;
    2631             :                 }
    2632             :         } else {
    2633         100 :                 addr = *ss_addr;
    2634             :         }
    2635             : 
    2636         100 :         status = open_socket_out(&addr, port, 60*1000, &fd);
    2637         100 :         if (!NT_STATUS_IS_OK(status)) {
    2638           0 :                 goto fail;
    2639             :         }
    2640         100 :         set_socket_options(fd, lp_socket_options());
    2641             : 
    2642         100 :         status = rpc_transport_sock_init(result, fd, &result->transport);
    2643         100 :         if (!NT_STATUS_IS_OK(status)) {
    2644           0 :                 close(fd);
    2645           0 :                 goto fail;
    2646             :         }
    2647             : 
    2648         100 :         result->transport->transport = NCACN_IP_TCP;
    2649             : 
    2650         100 :         result->binding_handle = rpccli_bh_create(result, NULL, table);
    2651         100 :         if (result->binding_handle == NULL) {
    2652           0 :                 TALLOC_FREE(result);
    2653           0 :                 return NT_STATUS_NO_MEMORY;
    2654             :         }
    2655             : 
    2656         100 :         *presult = result;
    2657         100 :         return NT_STATUS_OK;
    2658             : 
    2659           0 :  fail:
    2660           0 :         TALLOC_FREE(result);
    2661           0 :         return status;
    2662             : }
    2663             : 
    2664           2 : static NTSTATUS rpccli_epm_map_binding(
    2665             :         struct dcerpc_binding_handle *epm_connection,
    2666             :         struct dcerpc_binding *binding,
    2667             :         TALLOC_CTX *mem_ctx,
    2668             :         char **pendpoint)
    2669             : {
    2670           2 :         TALLOC_CTX *frame = talloc_stackframe();
    2671           0 :         enum dcerpc_transport_t transport =
    2672           2 :                 dcerpc_binding_get_transport(binding);
    2673           0 :         enum dcerpc_transport_t res_transport;
    2674           2 :         struct dcerpc_binding *res_binding = NULL;
    2675           2 :         struct epm_twr_t *map_tower = NULL;
    2676           2 :         struct epm_twr_p_t res_towers = { .twr = NULL };
    2677           2 :         struct policy_handle *entry_handle = NULL;
    2678           2 :         uint32_t num_towers = 0;
    2679           2 :         const uint32_t max_towers = 1;
    2680           2 :         const char *endpoint = NULL;
    2681           2 :         char *tmp = NULL;
    2682           0 :         uint32_t result;
    2683           0 :         NTSTATUS status;
    2684             : 
    2685           2 :         map_tower = talloc_zero(frame, struct epm_twr_t);
    2686           2 :         if (map_tower == NULL) {
    2687           0 :                 goto nomem;
    2688             :         }
    2689             : 
    2690           2 :         status = dcerpc_binding_build_tower(
    2691             :                 frame, binding, &(map_tower->tower));
    2692           2 :         if (!NT_STATUS_IS_OK(status)) {
    2693           0 :                 DBG_DEBUG("dcerpc_binding_build_tower failed: %s\n",
    2694             :                           nt_errstr(status));
    2695           0 :                 goto done;
    2696             :         }
    2697             : 
    2698           2 :         res_towers.twr = talloc_array(frame, struct epm_twr_t, max_towers);
    2699           2 :         if (res_towers.twr == NULL) {
    2700           0 :                 goto nomem;
    2701             :         }
    2702             : 
    2703           2 :         entry_handle = talloc_zero(frame, struct policy_handle);
    2704           2 :         if (entry_handle == NULL) {
    2705           0 :                 goto nomem;
    2706             :         }
    2707             : 
    2708           2 :         status = dcerpc_epm_Map(
    2709             :                 epm_connection,
    2710             :                 frame,
    2711             :                 NULL,
    2712             :                 map_tower,
    2713             :                 entry_handle,
    2714             :                 max_towers,
    2715             :                 &num_towers,
    2716             :                 &res_towers,
    2717             :                 &result);
    2718             : 
    2719           2 :         if (!NT_STATUS_IS_OK(status)) {
    2720           0 :                 DBG_DEBUG("dcerpc_epm_Map failed: %s\n", nt_errstr(status));
    2721           0 :                 goto done;
    2722             :         }
    2723             : 
    2724           2 :         if (result != EPMAPPER_STATUS_OK) {
    2725           0 :                 DBG_DEBUG("dcerpc_epm_Map returned %"PRIu32"\n", result);
    2726           0 :                 status = NT_STATUS_NOT_FOUND;
    2727           0 :                 goto done;
    2728             :         }
    2729             : 
    2730           2 :         if (num_towers != 1) {
    2731           0 :                 DBG_DEBUG("dcerpc_epm_Map returned %"PRIu32" towers\n",
    2732             :                           num_towers);
    2733           0 :                 status = NT_STATUS_INVALID_NETWORK_RESPONSE;
    2734           0 :                 goto done;
    2735             :         }
    2736             : 
    2737           2 :         status = dcerpc_binding_from_tower(
    2738           2 :                 frame, &(res_towers.twr->tower), &res_binding);
    2739           2 :         if (!NT_STATUS_IS_OK(status)) {
    2740           0 :                 DBG_DEBUG("dcerpc_binding_from_tower failed: %s\n",
    2741             :                           nt_errstr(status));
    2742           0 :                 goto done;
    2743             :         }
    2744             : 
    2745           2 :         res_transport = dcerpc_binding_get_transport(res_binding);
    2746           2 :         if (res_transport != transport) {
    2747           0 :                 DBG_DEBUG("dcerpc_epm_Map returned transport %d, "
    2748             :                           "expected %d\n",
    2749             :                           (int)res_transport,
    2750             :                           (int)transport);
    2751           0 :                 status = NT_STATUS_INVALID_NETWORK_RESPONSE;
    2752           0 :                 goto done;
    2753             :         }
    2754             : 
    2755           2 :         endpoint = dcerpc_binding_get_string_option(res_binding, "endpoint");
    2756           2 :         if (endpoint == NULL) {
    2757           0 :                 DBG_DEBUG("dcerpc_epm_Map returned no endpoint\n");
    2758           0 :                 status = NT_STATUS_INVALID_NETWORK_RESPONSE;
    2759           0 :                 goto done;
    2760             :         }
    2761             : 
    2762           2 :         tmp = talloc_strdup(mem_ctx, endpoint);
    2763           2 :         if (tmp == NULL) {
    2764           0 :                 goto nomem;
    2765             :         }
    2766           2 :         *pendpoint = tmp;
    2767             : 
    2768           2 :         status = NT_STATUS_OK;
    2769           2 :         goto done;
    2770             : 
    2771           0 : nomem:
    2772           0 :         status = NT_STATUS_NO_MEMORY;
    2773           2 : done:
    2774           2 :         TALLOC_FREE(frame);
    2775           2 :         return status;
    2776             : }
    2777             : 
    2778           2 : static NTSTATUS rpccli_epm_map_interface(
    2779             :         struct dcerpc_binding_handle *epm_connection,
    2780             :         enum dcerpc_transport_t transport,
    2781             :         const struct ndr_syntax_id *iface,
    2782             :         TALLOC_CTX *mem_ctx,
    2783             :         char **pendpoint)
    2784             : {
    2785           2 :         struct dcerpc_binding *binding = NULL;
    2786           2 :         char *endpoint = NULL;
    2787           0 :         NTSTATUS status;
    2788             : 
    2789           2 :         status = dcerpc_parse_binding(mem_ctx, "", &binding);
    2790           2 :         if (!NT_STATUS_IS_OK(status)) {
    2791           0 :                 DBG_DEBUG("dcerpc_parse_binding failed: %s\n",
    2792             :                           nt_errstr(status));
    2793           0 :                 goto done;
    2794             :         }
    2795             : 
    2796           2 :         status = dcerpc_binding_set_transport(binding, transport);
    2797           2 :         if (!NT_STATUS_IS_OK(status)) {
    2798           0 :                 DBG_DEBUG("dcerpc_binding_set_transport failed: %s\n",
    2799             :                           nt_errstr(status));
    2800           0 :                 goto done;
    2801             :         }
    2802             : 
    2803           2 :         status = dcerpc_binding_set_abstract_syntax(binding, iface);
    2804           2 :         if (!NT_STATUS_IS_OK(status)) {
    2805           0 :                 DBG_DEBUG("dcerpc_binding_set_abstract_syntax failed: %s\n",
    2806             :                           nt_errstr(status));
    2807           0 :                 goto done;
    2808             :         }
    2809             : 
    2810           2 :         status = rpccli_epm_map_binding(
    2811             :                 epm_connection, binding, mem_ctx, &endpoint);
    2812           2 :         if (!NT_STATUS_IS_OK(status)) {
    2813           0 :                 DBG_DEBUG("rpccli_epm_map_binding failed: %s\n",
    2814             :                           nt_errstr(status));
    2815           0 :                 goto done;
    2816             :         }
    2817           2 :         *pendpoint = endpoint;
    2818             : 
    2819           2 : done:
    2820           2 :         TALLOC_FREE(binding);
    2821           2 :         return status;
    2822             : }
    2823             : 
    2824             : /**
    2825             :  * Determine the tcp port on which a dcerpc interface is listening
    2826             :  * for the ncacn_ip_tcp transport via the endpoint mapper of the
    2827             :  * target host.
    2828             :  */
    2829          98 : static NTSTATUS rpc_pipe_get_tcp_port(const char *host,
    2830             :                                       const struct sockaddr_storage *addr,
    2831             :                                       const struct ndr_interface_table *table,
    2832             :                                       uint16_t *pport)
    2833             : {
    2834           0 :         NTSTATUS status;
    2835          98 :         struct rpc_pipe_client *epm_pipe = NULL;
    2836          98 :         struct pipe_auth_data *auth = NULL;
    2837          98 :         char *endpoint = NULL;
    2838          98 :         TALLOC_CTX *tmp_ctx = talloc_stackframe();
    2839             : 
    2840          98 :         if (pport == NULL) {
    2841           0 :                 status = NT_STATUS_INVALID_PARAMETER;
    2842           0 :                 goto done;
    2843             :         }
    2844             : 
    2845          98 :         if (ndr_syntax_id_equal(&table->syntax_id,
    2846             :                                 &ndr_table_epmapper.syntax_id)) {
    2847          96 :                 *pport = 135;
    2848          96 :                 status = NT_STATUS_OK;
    2849          96 :                 goto done;
    2850             :         }
    2851             : 
    2852             :         /* open the connection to the endpoint mapper */
    2853           2 :         status = rpc_pipe_open_tcp_port(tmp_ctx, host, addr, 135,
    2854             :                                         &ndr_table_epmapper,
    2855             :                                         &epm_pipe);
    2856             : 
    2857           2 :         if (!NT_STATUS_IS_OK(status)) {
    2858           0 :                 goto done;
    2859             :         }
    2860             : 
    2861           2 :         status = rpccli_anon_bind_data(tmp_ctx, &auth);
    2862           2 :         if (!NT_STATUS_IS_OK(status)) {
    2863           0 :                 goto done;
    2864             :         }
    2865             : 
    2866           2 :         status = rpc_pipe_bind(epm_pipe, auth);
    2867           2 :         if (!NT_STATUS_IS_OK(status)) {
    2868           0 :                 goto done;
    2869             :         }
    2870             : 
    2871           2 :         status = rpccli_epm_map_interface(
    2872           2 :                 epm_pipe->binding_handle,
    2873             :                 NCACN_IP_TCP,
    2874             :                 &table->syntax_id,
    2875             :                 tmp_ctx,
    2876             :                 &endpoint);
    2877           2 :         if (!NT_STATUS_IS_OK(status)) {
    2878           0 :                 DBG_DEBUG("rpccli_epm_map_interface failed: %s\n",
    2879             :                           nt_errstr(status));
    2880           0 :                 goto done;
    2881             :         }
    2882             : 
    2883           2 :         *pport = (uint16_t)atoi(endpoint);
    2884             : 
    2885          98 : done:
    2886          98 :         TALLOC_FREE(tmp_ctx);
    2887          98 :         return status;
    2888             : }
    2889             : 
    2890             : /**
    2891             :  * Create a rpc pipe client struct, connecting to a host via tcp.
    2892             :  * The port is determined by asking the endpoint mapper on the given
    2893             :  * host.
    2894             :  */
    2895          98 : static NTSTATUS rpc_pipe_open_tcp(
    2896             :         TALLOC_CTX *mem_ctx,
    2897             :         const char *host,
    2898             :         const struct sockaddr_storage *addr,
    2899             :         const struct ndr_interface_table *table,
    2900             :         struct rpc_pipe_client **presult)
    2901             : {
    2902           0 :         NTSTATUS status;
    2903          98 :         uint16_t port = 0;
    2904             : 
    2905          98 :         status = rpc_pipe_get_tcp_port(host, addr, table, &port);
    2906          98 :         if (!NT_STATUS_IS_OK(status)) {
    2907           0 :                 return status;
    2908             :         }
    2909             : 
    2910          98 :         return rpc_pipe_open_tcp_port(mem_ctx, host, addr, port,
    2911             :                                       table, presult);
    2912             : }
    2913             : 
    2914         152 : static NTSTATUS rpc_pipe_get_ncalrpc_name(
    2915             :         const struct ndr_syntax_id *iface,
    2916             :         TALLOC_CTX *mem_ctx,
    2917             :         char **psocket_name)
    2918             : {
    2919         152 :         TALLOC_CTX *frame = talloc_stackframe();
    2920         152 :         struct rpc_pipe_client *epm_pipe = NULL;
    2921         152 :         struct pipe_auth_data *auth = NULL;
    2922         152 :         NTSTATUS status = NT_STATUS_OK;
    2923           0 :         bool is_epm;
    2924             : 
    2925         152 :         is_epm = ndr_syntax_id_equal(iface, &ndr_table_epmapper.syntax_id);
    2926         152 :         if (is_epm) {
    2927         152 :                 char *endpoint = talloc_strdup(mem_ctx, "EPMAPPER");
    2928         152 :                 if (endpoint == NULL) {
    2929           0 :                         status = NT_STATUS_NO_MEMORY;
    2930           0 :                         goto done;
    2931             :                 }
    2932         152 :                 *psocket_name = endpoint;
    2933         152 :                 goto done;
    2934             :         }
    2935             : 
    2936           0 :         status = rpc_pipe_open_ncalrpc(
    2937             :                 frame, &ndr_table_epmapper, &epm_pipe);
    2938           0 :         if (!NT_STATUS_IS_OK(status)) {
    2939           0 :                 DBG_DEBUG("rpc_pipe_open_ncalrpc failed: %s\n",
    2940             :                           nt_errstr(status));
    2941           0 :                 goto done;
    2942             :         }
    2943             : 
    2944           0 :         status = rpccli_anon_bind_data(epm_pipe, &auth);
    2945           0 :         if (!NT_STATUS_IS_OK(status)) {
    2946           0 :                 DBG_DEBUG("rpccli_anon_bind_data failed: %s\n",
    2947             :                           nt_errstr(status));
    2948           0 :                 goto done;
    2949             :         }
    2950             : 
    2951           0 :         status = rpc_pipe_bind(epm_pipe, auth);
    2952           0 :         if (!NT_STATUS_IS_OK(status)) {
    2953           0 :                 DBG_DEBUG("rpc_pipe_bind failed: %s\n", nt_errstr(status));
    2954           0 :                 goto done;
    2955             :         }
    2956             : 
    2957           0 :         status = rpccli_epm_map_interface(
    2958           0 :                 epm_pipe->binding_handle,
    2959             :                 NCALRPC,
    2960             :                 iface,
    2961             :                 mem_ctx,
    2962             :                 psocket_name);
    2963           0 :         if (!NT_STATUS_IS_OK(status)) {
    2964           0 :                 DBG_DEBUG("rpccli_epm_map_interface failed: %s\n",
    2965             :                           nt_errstr(status));
    2966             :         }
    2967             : 
    2968           0 : done:
    2969         152 :         TALLOC_FREE(frame);
    2970         152 :         return status;
    2971             : }
    2972             : 
    2973             : /********************************************************************
    2974             :  Create a rpc pipe client struct, connecting to a unix domain socket
    2975             :  ********************************************************************/
    2976         152 : NTSTATUS rpc_pipe_open_ncalrpc(TALLOC_CTX *mem_ctx,
    2977             :                                const struct ndr_interface_table *table,
    2978             :                                struct rpc_pipe_client **presult)
    2979             : {
    2980         152 :         char *socket_name = NULL;
    2981           0 :         struct rpc_pipe_client *result;
    2982         152 :         struct sockaddr_un addr = { .sun_family = AF_UNIX };
    2983         152 :         socklen_t salen = sizeof(addr);
    2984           0 :         int pathlen;
    2985           0 :         NTSTATUS status;
    2986         152 :         int fd = -1;
    2987             : 
    2988         152 :         result = talloc_zero(mem_ctx, struct rpc_pipe_client);
    2989         152 :         if (result == NULL) {
    2990           0 :                 return NT_STATUS_NO_MEMORY;
    2991             :         }
    2992             : 
    2993         152 :         status = rpc_pipe_get_ncalrpc_name(
    2994             :                 &table->syntax_id, result, &socket_name);
    2995         152 :         if (!NT_STATUS_IS_OK(status)) {
    2996           0 :                 DBG_DEBUG("rpc_pipe_get_ncalrpc_name failed: %s\n",
    2997             :                           nt_errstr(status));
    2998           0 :                 goto fail;
    2999             :         }
    3000             : 
    3001         152 :         pathlen = snprintf(
    3002             :                 addr.sun_path,
    3003             :                 sizeof(addr.sun_path),
    3004             :                 "%s/%s",
    3005             :                 lp_ncalrpc_dir(),
    3006             :                 socket_name);
    3007         152 :         if ((pathlen < 0) || ((size_t)pathlen >= sizeof(addr.sun_path))) {
    3008           0 :                 DBG_DEBUG("socket_path for %s too long\n", socket_name);
    3009           0 :                 status = NT_STATUS_NAME_TOO_LONG;
    3010           0 :                 goto fail;
    3011             :         }
    3012         152 :         TALLOC_FREE(socket_name);
    3013             : 
    3014         152 :         result->abstract_syntax = table->syntax_id;
    3015         152 :         result->transfer_syntax = ndr_transfer_syntax_ndr;
    3016             : 
    3017         152 :         result->desthost = get_myname(result);
    3018         152 :         if (result->desthost == NULL) {
    3019           0 :                 status = NT_STATUS_NO_MEMORY;
    3020           0 :                 goto fail;
    3021             :         }
    3022             : 
    3023         152 :         result->srv_name_slash = talloc_asprintf_strupper_m(
    3024             :                 result, "\\\\%s", result->desthost);
    3025         152 :         if (result->srv_name_slash == NULL) {
    3026           0 :                 status = NT_STATUS_NO_MEMORY;
    3027           0 :                 goto fail;
    3028             :         }
    3029             : 
    3030         152 :         result->max_xmit_frag = RPC_MAX_PDU_FRAG_LEN;
    3031             : 
    3032         152 :         fd = socket(AF_UNIX, SOCK_STREAM, 0);
    3033         152 :         if (fd == -1) {
    3034           0 :                 status = map_nt_error_from_unix(errno);
    3035           0 :                 goto fail;
    3036             :         }
    3037             : 
    3038         152 :         if (connect(fd, (struct sockaddr *)(void *)&addr, salen) == -1) {
    3039          16 :                 DBG_WARNING("connect(%s) failed: %s\n",
    3040             :                             addr.sun_path,
    3041             :                             strerror(errno));
    3042          16 :                 status = map_nt_error_from_unix(errno);
    3043          16 :                 goto fail;
    3044             :         }
    3045             : 
    3046         136 :         status = rpc_transport_sock_init(result, fd, &result->transport);
    3047         136 :         if (!NT_STATUS_IS_OK(status)) {
    3048           0 :                 goto fail;
    3049             :         }
    3050         136 :         fd = -1;
    3051             : 
    3052         136 :         result->transport->transport = NCALRPC;
    3053             : 
    3054         136 :         result->binding_handle = rpccli_bh_create(result, NULL, table);
    3055         136 :         if (result->binding_handle == NULL) {
    3056           0 :                 status = NT_STATUS_NO_MEMORY;
    3057           0 :                 goto fail;
    3058             :         }
    3059             : 
    3060         136 :         *presult = result;
    3061         136 :         return NT_STATUS_OK;
    3062             : 
    3063          16 :  fail:
    3064          16 :         if (fd != -1) {
    3065          16 :                 close(fd);
    3066             :         }
    3067          16 :         TALLOC_FREE(result);
    3068          16 :         return status;
    3069             : }
    3070             : 
    3071       30671 : NTSTATUS rpc_pipe_open_local_np(
    3072             :         TALLOC_CTX *mem_ctx,
    3073             :         const struct ndr_interface_table *table,
    3074             :         const char *remote_client_name,
    3075             :         const struct tsocket_address *remote_client_addr,
    3076             :         const char *local_server_name,
    3077             :         const struct tsocket_address *local_server_addr,
    3078             :         const struct auth_session_info *session_info,
    3079             :         struct rpc_pipe_client **presult)
    3080             : {
    3081       30671 :         struct rpc_pipe_client *result = NULL;
    3082       30671 :         struct pipe_auth_data *auth = NULL;
    3083       30671 :         const char *pipe_name = NULL;
    3084       30671 :         struct tstream_context *npa_stream = NULL;
    3085       30671 :         NTSTATUS status = NT_STATUS_NO_MEMORY;
    3086           0 :         int ret;
    3087             : 
    3088       30671 :         result = talloc_zero(mem_ctx, struct rpc_pipe_client);
    3089       30671 :         if (result == NULL) {
    3090           0 :                 goto fail;
    3091             :         }
    3092       30671 :         result->abstract_syntax = table->syntax_id;
    3093       30671 :         result->transfer_syntax = ndr_transfer_syntax_ndr;
    3094       30671 :         result->max_xmit_frag = RPC_MAX_PDU_FRAG_LEN;
    3095             : 
    3096       30671 :         pipe_name = dcerpc_default_transport_endpoint(
    3097             :                 result, NCACN_NP, table);
    3098       30671 :         if (pipe_name == NULL) {
    3099           0 :                 DBG_DEBUG("dcerpc_default_transport_endpoint failed\n");
    3100           0 :                 status = NT_STATUS_OBJECT_NAME_NOT_FOUND;
    3101           0 :                 goto fail;
    3102             :         }
    3103             : 
    3104       30671 :         if (local_server_name == NULL) {
    3105       30671 :                 result->desthost = get_myname(result);
    3106             :         } else {
    3107           0 :                 result->desthost = talloc_strdup(result, local_server_name);
    3108             :         }
    3109       30671 :         if (result->desthost == NULL) {
    3110           0 :                 goto fail;
    3111             :         }
    3112       30671 :         result->srv_name_slash = talloc_asprintf_strupper_m(
    3113             :                 result, "\\\\%s", result->desthost);
    3114       30671 :         if (result->srv_name_slash == NULL) {
    3115           0 :                 goto fail;
    3116             :         }
    3117             : 
    3118       30671 :         ret = local_np_connect(
    3119             :                 pipe_name,
    3120             :                 NCALRPC,
    3121             :                 remote_client_name,
    3122             :                 remote_client_addr,
    3123             :                 local_server_name,
    3124             :                 local_server_addr,
    3125             :                 session_info,
    3126             :                 true,
    3127             :                 result,
    3128             :                 &npa_stream);
    3129       30671 :         if (ret != 0) {
    3130           0 :                 DBG_DEBUG("local_np_connect for %s and "
    3131             :                           "user %s\\%s failed: %s\n",
    3132             :                           pipe_name,
    3133             :                           session_info->info->domain_name,
    3134             :                           session_info->info->account_name,
    3135             :                           strerror(ret));
    3136           0 :                 status = map_nt_error_from_unix(ret);
    3137           0 :                 goto fail;
    3138             :         }
    3139             : 
    3140       30671 :         status = rpc_transport_tstream_init(
    3141             :                 result, &npa_stream, &result->transport);
    3142       30671 :         if (!NT_STATUS_IS_OK(status)) {
    3143           0 :                 DBG_DEBUG("rpc_transport_tstream_init failed: %s\n",
    3144             :                           nt_errstr(status));
    3145           0 :                 goto fail;
    3146             :         }
    3147             : 
    3148       30671 :         result->binding_handle = rpccli_bh_create(result, NULL, table);
    3149       30671 :         if (result->binding_handle == NULL) {
    3150           0 :                 status = NT_STATUS_NO_MEMORY;
    3151           0 :                 DBG_DEBUG("Failed to create binding handle.\n");
    3152           0 :                 goto fail;
    3153             :         }
    3154             : 
    3155       30671 :         status = rpccli_anon_bind_data(result, &auth);
    3156       30671 :         if (!NT_STATUS_IS_OK(status)) {
    3157           0 :                 DBG_DEBUG("rpccli_anon_bind_data failed: %s\n",
    3158             :                           nt_errstr(status));
    3159           0 :                 goto fail;
    3160             :         }
    3161             : 
    3162       30671 :         status = rpc_pipe_bind(result, auth);
    3163       30671 :         if (!NT_STATUS_IS_OK(status)) {
    3164           0 :                 DBG_DEBUG("rpc_pipe_bind failed: %s\n", nt_errstr(status));
    3165           0 :                 goto fail;
    3166             :         }
    3167             : 
    3168       30671 :         *presult = result;
    3169       30671 :         return NT_STATUS_OK;
    3170             : 
    3171           0 : fail:
    3172           0 :         TALLOC_FREE(result);
    3173           0 :         return status;
    3174             : }
    3175             : 
    3176             : struct rpc_pipe_client_np_ref {
    3177             :         struct cli_state *cli;
    3178             :         struct rpc_pipe_client *pipe;
    3179             : };
    3180             : 
    3181       10754 : static int rpc_pipe_client_np_ref_destructor(struct rpc_pipe_client_np_ref *np_ref)
    3182             : {
    3183       10754 :         DLIST_REMOVE(np_ref->cli->pipe_list, np_ref->pipe);
    3184       10754 :         return 0;
    3185             : }
    3186             : 
    3187             : /****************************************************************************
    3188             :  Open a named pipe over SMB to a remote server.
    3189             :  *
    3190             :  * CAVEAT CALLER OF THIS FUNCTION:
    3191             :  *    The returned rpc_pipe_client saves a copy of the cli_state cli pointer,
    3192             :  *    so be sure that this function is called AFTER any structure (vs pointer)
    3193             :  *    assignment of the cli.  In particular, libsmbclient does structure
    3194             :  *    assignments of cli, which invalidates the data in the returned
    3195             :  *    rpc_pipe_client if this function is called before the structure assignment
    3196             :  *    of cli.
    3197             :  *
    3198             :  ****************************************************************************/
    3199             : 
    3200             : struct rpc_pipe_open_np_state {
    3201             :         struct cli_state *cli;
    3202             :         const struct ndr_interface_table *table;
    3203             :         struct rpc_pipe_client *result;
    3204             : };
    3205             : 
    3206             : static void rpc_pipe_open_np_done(struct tevent_req *subreq);
    3207             : 
    3208       10772 : struct tevent_req *rpc_pipe_open_np_send(
    3209             :         TALLOC_CTX *mem_ctx,
    3210             :         struct tevent_context *ev,
    3211             :         struct cli_state *cli,
    3212             :         const struct ndr_interface_table *table)
    3213             : {
    3214       10772 :         struct tevent_req *req = NULL, *subreq = NULL;
    3215       10772 :         struct rpc_pipe_open_np_state *state = NULL;
    3216       10772 :         struct rpc_pipe_client *result = NULL;
    3217             : 
    3218       10772 :         req = tevent_req_create(
    3219             :                 mem_ctx, &state, struct rpc_pipe_open_np_state);
    3220       10772 :         if (req == NULL) {
    3221           0 :                 return NULL;
    3222             :         }
    3223       10772 :         state->cli = cli;
    3224       10772 :         state->table = table;
    3225             : 
    3226       10772 :         state->result = talloc_zero(state, struct rpc_pipe_client);
    3227       10772 :         if (tevent_req_nomem(state->result, req)) {
    3228           0 :                 return tevent_req_post(req, ev);
    3229             :         }
    3230       10772 :         result = state->result;
    3231             : 
    3232       10772 :         result->abstract_syntax = table->syntax_id;
    3233       10772 :         result->transfer_syntax = ndr_transfer_syntax_ndr;
    3234             : 
    3235       10772 :         result->desthost = talloc_strdup(
    3236             :                 result, smbXcli_conn_remote_name(cli->conn));
    3237       10772 :         if (tevent_req_nomem(result->desthost, req)) {
    3238           0 :                 return tevent_req_post(req, ev);
    3239             :         }
    3240             : 
    3241       10772 :         result->srv_name_slash = talloc_asprintf_strupper_m(
    3242             :                 result, "\\\\%s", result->desthost);
    3243       10772 :         if (tevent_req_nomem(result->srv_name_slash, req)) {
    3244           0 :                 return tevent_req_post(req, ev);
    3245             :         }
    3246             : 
    3247       10772 :         result->max_xmit_frag = RPC_MAX_PDU_FRAG_LEN;
    3248             : 
    3249       10772 :         subreq = rpc_transport_np_init_send(state, ev, cli, table);
    3250       10772 :         if (tevent_req_nomem(subreq, req)) {
    3251           0 :                 return tevent_req_post(req, ev);
    3252             :         }
    3253       10772 :         tevent_req_set_callback(subreq, rpc_pipe_open_np_done, req);
    3254       10772 :         return req;
    3255             : }
    3256             : 
    3257       10772 : static void rpc_pipe_open_np_done(struct tevent_req *subreq)
    3258             : {
    3259       10772 :         struct tevent_req *req = tevent_req_callback_data(
    3260             :                 subreq, struct tevent_req);
    3261       10772 :         struct rpc_pipe_open_np_state *state = tevent_req_data(
    3262             :                 req, struct rpc_pipe_open_np_state);
    3263       10772 :         struct rpc_pipe_client *result = state->result;
    3264       10772 :         struct rpc_pipe_client_np_ref *np_ref = NULL;
    3265           0 :         NTSTATUS status;
    3266             : 
    3267       10772 :         status = rpc_transport_np_init_recv(
    3268             :                 subreq, result, &result->transport);
    3269       10772 :         TALLOC_FREE(subreq);
    3270       10772 :         if (tevent_req_nterror(req, status)) {
    3271           0 :                 return;
    3272             :         }
    3273             : 
    3274       10772 :         result->transport->transport = NCACN_NP;
    3275             : 
    3276       10772 :         np_ref = talloc(result->transport, struct rpc_pipe_client_np_ref);
    3277       10772 :         if (tevent_req_nomem(np_ref, req)) {
    3278           0 :                 return;
    3279             :         }
    3280       10772 :         np_ref->cli = state->cli;
    3281       10772 :         np_ref->pipe = result;
    3282             : 
    3283       10772 :         DLIST_ADD(np_ref->cli->pipe_list, np_ref->pipe);
    3284       10772 :         talloc_set_destructor(np_ref, rpc_pipe_client_np_ref_destructor);
    3285             : 
    3286       10772 :         result->binding_handle = rpccli_bh_create(result, NULL, state->table);
    3287       10772 :         if (tevent_req_nomem(result->binding_handle, req)) {
    3288           0 :                 return;
    3289             :         }
    3290             : 
    3291       10772 :         tevent_req_done(req);
    3292             : }
    3293             : 
    3294       10772 : NTSTATUS rpc_pipe_open_np_recv(
    3295             :         struct tevent_req *req,
    3296             :         TALLOC_CTX *mem_ctx,
    3297             :         struct rpc_pipe_client **_result)
    3298             : {
    3299       10772 :         struct rpc_pipe_open_np_state *state = tevent_req_data(
    3300             :                 req, struct rpc_pipe_open_np_state);
    3301           0 :         NTSTATUS status;
    3302             : 
    3303       10772 :         if (tevent_req_is_nterror(req, &status)) {
    3304           0 :                 return status;
    3305             :         }
    3306       10772 :         *_result = talloc_move(mem_ctx, &state->result);
    3307       10772 :         return NT_STATUS_OK;
    3308             : }
    3309             : 
    3310       10772 : NTSTATUS rpc_pipe_open_np(struct cli_state *cli,
    3311             :                           const struct ndr_interface_table *table,
    3312             :                           struct rpc_pipe_client **presult)
    3313             : {
    3314       10772 :         struct tevent_context *ev = NULL;
    3315       10772 :         struct tevent_req *req = NULL;
    3316       10772 :         NTSTATUS status = NT_STATUS_NO_MEMORY;
    3317             : 
    3318       10772 :         ev = samba_tevent_context_init(cli);
    3319       10772 :         if (ev == NULL) {
    3320           0 :                 goto fail;
    3321             :         }
    3322       10772 :         req = rpc_pipe_open_np_send(ev, ev, cli, table);
    3323       10772 :         if (req == NULL) {
    3324           0 :                 goto fail;
    3325             :         }
    3326       10772 :         if (!tevent_req_poll_ntstatus(req, ev, &status)) {
    3327           0 :                 goto fail;
    3328             :         }
    3329       10772 :         status = rpc_pipe_open_np_recv(req, NULL, presult);
    3330       10772 : fail:
    3331       10772 :         TALLOC_FREE(req);
    3332       10772 :         TALLOC_FREE(ev);
    3333       10772 :         return status;
    3334             : }
    3335             : 
    3336             : /****************************************************************************
    3337             :  Open a pipe to a remote server.
    3338             :  ****************************************************************************/
    3339             : 
    3340       10870 : static NTSTATUS cli_rpc_pipe_open(struct cli_state *cli,
    3341             :                                   enum dcerpc_transport_t transport,
    3342             :                                   const struct ndr_interface_table *table,
    3343             :                                   const char *remote_name,
    3344             :                                   const struct sockaddr_storage *remote_sockaddr,
    3345             :                                   struct rpc_pipe_client **presult)
    3346             : {
    3347       10870 :         switch (transport) {
    3348          98 :         case NCACN_IP_TCP:
    3349          98 :                 return rpc_pipe_open_tcp(NULL,
    3350             :                                          remote_name,
    3351             :                                          remote_sockaddr,
    3352             :                                          table, presult);
    3353       10772 :         case NCACN_NP:
    3354       10772 :                 return rpc_pipe_open_np(cli, table, presult);
    3355           0 :         default:
    3356           0 :                 return NT_STATUS_NOT_IMPLEMENTED;
    3357             :         }
    3358             : }
    3359             : 
    3360             : /****************************************************************************
    3361             :  Open a named pipe to an SMB server and bind anonymously.
    3362             :  ****************************************************************************/
    3363             : 
    3364       10530 : NTSTATUS cli_rpc_pipe_open_noauth_transport(struct cli_state *cli,
    3365             :                                             enum dcerpc_transport_t transport,
    3366             :                                             const struct ndr_interface_table *table,
    3367             :                                             const char *remote_name,
    3368             :                                             const struct sockaddr_storage *remote_sockaddr,
    3369             :                                             struct rpc_pipe_client **presult)
    3370             : {
    3371           0 :         struct rpc_pipe_client *result;
    3372           0 :         struct pipe_auth_data *auth;
    3373           0 :         NTSTATUS status;
    3374             : 
    3375       10530 :         status = cli_rpc_pipe_open(cli,
    3376             :                                    transport,
    3377             :                                    table,
    3378             :                                    remote_name,
    3379             :                                    remote_sockaddr,
    3380             :                                    &result);
    3381       10530 :         if (!NT_STATUS_IS_OK(status)) {
    3382           0 :                 return status;
    3383             :         }
    3384             : 
    3385       10530 :         status = rpccli_anon_bind_data(result, &auth);
    3386       10530 :         if (!NT_STATUS_IS_OK(status)) {
    3387           0 :                 DEBUG(0, ("rpccli_anon_bind_data returned %s\n",
    3388             :                           nt_errstr(status)));
    3389           0 :                 TALLOC_FREE(result);
    3390           0 :                 return status;
    3391             :         }
    3392             : 
    3393             :         /*
    3394             :          * This is a bit of an abstraction violation due to the fact that an
    3395             :          * anonymous bind on an authenticated SMB inherits the user/domain
    3396             :          * from the enclosing SMB creds
    3397             :          */
    3398             : 
    3399       10530 :         if (transport == NCACN_NP) {
    3400           0 :                 struct smbXcli_session *session;
    3401             : 
    3402       10522 :                 if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
    3403       10378 :                         session = cli->smb2.session;
    3404             :                 } else {
    3405         144 :                         session = cli->smb1.session;
    3406             :                 }
    3407             : 
    3408       10522 :                 status = smbXcli_session_application_key(session, auth,
    3409       10522 :                                                 &auth->transport_session_key);
    3410       10522 :                 if (!NT_STATUS_IS_OK(status)) {
    3411         167 :                         auth->transport_session_key = data_blob_null;
    3412             :                 }
    3413             :         }
    3414             : 
    3415       10530 :         status = rpc_pipe_bind(result, auth);
    3416       10530 :         if (!NT_STATUS_IS_OK(status)) {
    3417           0 :                 int lvl = 0;
    3418           0 :                 if (ndr_syntax_id_equal(&table->syntax_id,
    3419             :                                         &ndr_table_dssetup.syntax_id)) {
    3420             :                         /* non AD domains just don't have this pipe, avoid
    3421             :                          * level 0 statement in that case - gd */
    3422           0 :                         lvl = 3;
    3423             :                 }
    3424           0 :                 DEBUG(lvl, ("cli_rpc_pipe_open_noauth: rpc_pipe_bind for pipe "
    3425             :                             "%s failed with error %s\n",
    3426             :                             table->name,
    3427             :                             nt_errstr(status) ));
    3428           0 :                 TALLOC_FREE(result);
    3429           0 :                 return status;
    3430             :         }
    3431             : 
    3432       10530 :         DEBUG(10,("cli_rpc_pipe_open_noauth: opened pipe %s to machine "
    3433             :                   "%s and bound anonymously.\n",
    3434             :                   table->name,
    3435             :                   result->desthost));
    3436             : 
    3437       10530 :         *presult = result;
    3438       10530 :         return NT_STATUS_OK;
    3439             : }
    3440             : 
    3441             : /****************************************************************************
    3442             :  ****************************************************************************/
    3443             : 
    3444       10136 : NTSTATUS cli_rpc_pipe_open_noauth(struct cli_state *cli,
    3445             :                                   const struct ndr_interface_table *table,
    3446             :                                   struct rpc_pipe_client **presult)
    3447             : {
    3448       10136 :         const char *remote_name = smbXcli_conn_remote_name(cli->conn);
    3449           0 :         const struct sockaddr_storage *remote_sockaddr =
    3450       10136 :                 smbXcli_conn_remote_sockaddr(cli->conn);
    3451             : 
    3452       10136 :         return cli_rpc_pipe_open_noauth_transport(cli, NCACN_NP,
    3453             :                                                   table,
    3454             :                                                   remote_name,
    3455             :                                                   remote_sockaddr,
    3456             :                                                   presult);
    3457             : }
    3458             : 
    3459             : /****************************************************************************
    3460             :  Open a named pipe to an SMB server and bind using the mech specified
    3461             : 
    3462             :  This routine references the creds pointer that is passed in
    3463             :  ****************************************************************************/
    3464             : 
    3465         233 : NTSTATUS cli_rpc_pipe_open_with_creds(struct cli_state *cli,
    3466             :                                       const struct ndr_interface_table *table,
    3467             :                                       enum dcerpc_transport_t transport,
    3468             :                                       enum dcerpc_AuthType auth_type,
    3469             :                                       enum dcerpc_AuthLevel auth_level,
    3470             :                                       const char *server,
    3471             :                                       const struct sockaddr_storage *remote_sockaddr,
    3472             :                                       struct cli_credentials *creds,
    3473             :                                       struct rpc_pipe_client **presult)
    3474             : {
    3475           0 :         struct rpc_pipe_client *result;
    3476         233 :         struct pipe_auth_data *auth = NULL;
    3477         233 :         const char *target_service = table->authservices->names[0];
    3478           0 :         NTSTATUS status;
    3479             : 
    3480         233 :         status = cli_rpc_pipe_open(cli,
    3481             :                                    transport,
    3482             :                                    table,
    3483             :                                    server,
    3484             :                                    remote_sockaddr,
    3485             :                                    &result);
    3486         233 :         if (!NT_STATUS_IS_OK(status)) {
    3487           0 :                 return status;
    3488             :         }
    3489             : 
    3490         233 :         status = rpccli_generic_bind_data_from_creds(result,
    3491             :                                                      auth_type, auth_level,
    3492             :                                                      server, target_service,
    3493             :                                                      creds,
    3494             :                                                      &auth);
    3495         233 :         if (!NT_STATUS_IS_OK(status)) {
    3496           0 :                 DBG_ERR("rpccli_generic_bind_data_from_creds returned %s\n",
    3497             :                         nt_errstr(status));
    3498           0 :                 goto err;
    3499             :         }
    3500             : 
    3501         233 :         status = rpc_pipe_bind(result, auth);
    3502         233 :         if (!NT_STATUS_IS_OK(status)) {
    3503           0 :                 DBG_ERR("cli_rpc_pipe_bind failed with error %s\n",
    3504             :                         nt_errstr(status));
    3505           0 :                 goto err;
    3506             :         }
    3507             : 
    3508         233 :         DBG_DEBUG("opened pipe %s to machine %s and bound as user %s.\n",
    3509             :                   table->name,
    3510             :                   result->desthost,
    3511             :                   cli_credentials_get_unparsed_name(creds, talloc_tos()));
    3512             : 
    3513         233 :         *presult = result;
    3514         233 :         return NT_STATUS_OK;
    3515             : 
    3516           0 :   err:
    3517             : 
    3518           0 :         TALLOC_FREE(result);
    3519           0 :         return status;
    3520             : }
    3521             : 
    3522         107 : NTSTATUS cli_rpc_pipe_open_bind_schannel(
    3523             :         struct cli_state *cli,
    3524             :         const struct ndr_interface_table *table,
    3525             :         enum dcerpc_transport_t transport,
    3526             :         struct netlogon_creds_cli_context *netlogon_creds,
    3527             :         const char *remote_name,
    3528             :         const struct sockaddr_storage *remote_sockaddr,
    3529             :         struct rpc_pipe_client **_rpccli)
    3530             : {
    3531           0 :         struct rpc_pipe_client *rpccli;
    3532           0 :         struct pipe_auth_data *rpcauth;
    3533         107 :         const char *target_service = table->authservices->names[0];
    3534           0 :         struct cli_credentials *cli_creds;
    3535           0 :         enum dcerpc_AuthLevel auth_level;
    3536           0 :         NTSTATUS status;
    3537             : 
    3538         107 :         status = cli_rpc_pipe_open(cli,
    3539             :                                    transport,
    3540             :                                    table,
    3541             :                                    remote_name,
    3542             :                                    remote_sockaddr,
    3543             :                                    &rpccli);
    3544         107 :         if (!NT_STATUS_IS_OK(status)) {
    3545           0 :                 return status;
    3546             :         }
    3547             : 
    3548         107 :         auth_level = netlogon_creds_cli_auth_level(netlogon_creds);
    3549             : 
    3550         107 :         status = netlogon_creds_bind_cli_credentials(
    3551             :                 netlogon_creds, rpccli, &cli_creds);
    3552         107 :         if (!NT_STATUS_IS_OK(status)) {
    3553           0 :                 DBG_DEBUG("netlogon_creds_bind_cli_credentials failed: %s\n",
    3554             :                           nt_errstr(status));
    3555           0 :                 TALLOC_FREE(rpccli);
    3556           0 :                 return status;
    3557             :         }
    3558             : 
    3559         107 :         status = rpccli_generic_bind_data_from_creds(rpccli,
    3560             :                                                      DCERPC_AUTH_TYPE_SCHANNEL,
    3561             :                                                      auth_level,
    3562         107 :                                                      rpccli->desthost,
    3563             :                                                      target_service,
    3564             :                                                      cli_creds,
    3565             :                                                      &rpcauth);
    3566         107 :         if (!NT_STATUS_IS_OK(status)) {
    3567           0 :                 DEBUG(0, ("rpccli_generic_bind_data_from_creds returned %s\n",
    3568             :                           nt_errstr(status)));
    3569           0 :                 TALLOC_FREE(rpccli);
    3570           0 :                 return status;
    3571             :         }
    3572             : 
    3573         107 :         status = rpc_pipe_bind(rpccli, rpcauth);
    3574             : 
    3575             :         /* No TALLOC_FREE, gensec takes references */
    3576         107 :         talloc_unlink(rpccli, cli_creds);
    3577         107 :         cli_creds = NULL;
    3578             : 
    3579         107 :         if (!NT_STATUS_IS_OK(status)) {
    3580           0 :                 DBG_DEBUG("rpc_pipe_bind failed with error %s\n",
    3581             :                           nt_errstr(status));
    3582           0 :                 TALLOC_FREE(rpccli);
    3583           0 :                 return status;
    3584             :         }
    3585             : 
    3586         107 :         *_rpccli = rpccli;
    3587             : 
    3588         107 :         return NT_STATUS_OK;
    3589             : }
    3590             : 
    3591         107 : NTSTATUS cli_rpc_pipe_open_schannel_with_creds(struct cli_state *cli,
    3592             :                                                const struct ndr_interface_table *table,
    3593             :                                                enum dcerpc_transport_t transport,
    3594             :                                                struct netlogon_creds_cli_context *netlogon_creds,
    3595             :                                                const char *remote_name,
    3596             :                                                const struct sockaddr_storage *remote_sockaddr,
    3597             :                                                struct rpc_pipe_client **_rpccli)
    3598             : {
    3599         107 :         TALLOC_CTX *frame = talloc_stackframe();
    3600           0 :         struct rpc_pipe_client *rpccli;
    3601           0 :         struct netlogon_creds_cli_lck *lck;
    3602           0 :         NTSTATUS status;
    3603             : 
    3604         107 :         status = netlogon_creds_cli_lck(
    3605             :                 netlogon_creds, NETLOGON_CREDS_CLI_LCK_EXCLUSIVE,
    3606             :                 frame, &lck);
    3607         107 :         if (!NT_STATUS_IS_OK(status)) {
    3608           0 :                 DBG_WARNING("netlogon_creds_cli_lck returned %s\n",
    3609             :                             nt_errstr(status));
    3610           0 :                 TALLOC_FREE(frame);
    3611           0 :                 return status;
    3612             :         }
    3613             : 
    3614         107 :         status = cli_rpc_pipe_open_bind_schannel(cli,
    3615             :                                                  table,
    3616             :                                                  transport,
    3617             :                                                  netlogon_creds,
    3618             :                                                  remote_name,
    3619             :                                                  remote_sockaddr,
    3620             :                                                  &rpccli);
    3621         107 :         if (NT_STATUS_EQUAL(status, NT_STATUS_NETWORK_ACCESS_DENIED)) {
    3622           0 :                 netlogon_creds_cli_delete_lck(netlogon_creds);
    3623             :         }
    3624         107 :         if (!NT_STATUS_IS_OK(status)) {
    3625           0 :                 DBG_DEBUG("cli_rpc_pipe_open_bind_schannel failed: %s\n",
    3626             :                           nt_errstr(status));
    3627           0 :                 TALLOC_FREE(frame);
    3628           0 :                 return status;
    3629             :         }
    3630             : 
    3631         107 :         if (ndr_syntax_id_equal(&table->syntax_id,
    3632             :                                 &ndr_table_netlogon.syntax_id)) {
    3633         103 :                 status = netlogon_creds_cli_check(netlogon_creds,
    3634         103 :                                                   rpccli->binding_handle,
    3635             :                                                   NULL);
    3636         103 :                 if (!NT_STATUS_IS_OK(status)) {
    3637           0 :                         DEBUG(0, ("netlogon_creds_cli_check failed with %s\n",
    3638             :                                   nt_errstr(status)));
    3639           0 :                         TALLOC_FREE(frame);
    3640           0 :                         return status;
    3641             :                 }
    3642             :         }
    3643             : 
    3644         107 :         DBG_DEBUG("opened pipe %s to machine %s with key %s "
    3645             :                   "and bound using schannel.\n",
    3646             :                   table->name, rpccli->desthost,
    3647             :                   netlogon_creds_cli_debug_string(netlogon_creds, lck));
    3648             : 
    3649         107 :         TALLOC_FREE(frame);
    3650             : 
    3651         107 :         *_rpccli = rpccli;
    3652         107 :         return NT_STATUS_OK;
    3653             : }
    3654             : 
    3655          21 : NTSTATUS cli_get_session_key(TALLOC_CTX *mem_ctx,
    3656             :                              struct rpc_pipe_client *cli,
    3657             :                              DATA_BLOB *session_key)
    3658             : {
    3659           0 :         NTSTATUS status;
    3660           0 :         struct pipe_auth_data *a;
    3661           0 :         struct gensec_security *gensec_security;
    3662          21 :         DATA_BLOB sk = { .data = NULL };
    3663          21 :         bool make_dup = false;
    3664             : 
    3665          21 :         if (!session_key || !cli) {
    3666           0 :                 return NT_STATUS_INVALID_PARAMETER;
    3667             :         }
    3668             : 
    3669          21 :         a = cli->auth;
    3670             : 
    3671          21 :         if (a == NULL) {
    3672           0 :                 return NT_STATUS_INVALID_PARAMETER;
    3673             :         }
    3674             : 
    3675          21 :         switch (cli->auth->auth_type) {
    3676          21 :         case DCERPC_AUTH_TYPE_NONE:
    3677          21 :                 sk = data_blob_const(a->transport_session_key.data,
    3678             :                                      a->transport_session_key.length);
    3679          21 :                 make_dup = true;
    3680          21 :                 break;
    3681           0 :         default:
    3682           0 :                 gensec_security = a->auth_ctx;
    3683           0 :                 status = gensec_session_key(gensec_security, mem_ctx, &sk);
    3684           0 :                 if (!NT_STATUS_IS_OK(status)) {
    3685           0 :                         return status;
    3686             :                 }
    3687           0 :                 make_dup = false;
    3688           0 :                 break;
    3689             :         }
    3690             : 
    3691          21 :         if (!sk.data) {
    3692           0 :                 return NT_STATUS_NO_USER_SESSION_KEY;
    3693             :         }
    3694             : 
    3695          21 :         if (make_dup) {
    3696          21 :                 *session_key = data_blob_dup_talloc(mem_ctx, sk);
    3697             :         } else {
    3698           0 :                 *session_key = sk;
    3699             :         }
    3700             : 
    3701          21 :         return NT_STATUS_OK;
    3702             : }

Generated by: LCOV version 1.14