LCOV - code coverage report
Current view: top level - source3/rpc_client - cli_pipe.c (source / functions) Hit Total Coverage
Test: coverage report for master 2b515b7d Lines: 1052 1648 63.8 %
Date: 2024-02-28 12:06:22 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         360 : static const char *rpccli_pipe_txt(TALLOC_CTX *mem_ctx,
      54             :                                    struct rpc_pipe_client *cli)
      55             : {
      56         360 :         char *result = talloc_asprintf(mem_ctx, "host %s", cli->desthost);
      57         360 :         if (result == NULL) {
      58           0 :                 return "pipe";
      59             :         }
      60         360 :         return result;
      61             : }
      62             : 
      63             : /********************************************************************
      64             :  Rpc pipe call id.
      65             :  ********************************************************************/
      66             : 
      67      599723 : static uint32_t get_rpc_call_id(void)
      68             : {
      69           0 :         static uint32_t call_id = 0;
      70      599723 :         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      600766 : 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      600766 :         req = tevent_req_create(mem_ctx, &state, struct rpc_read_state);
      97      600766 :         if (req == NULL) {
      98           0 :                 return NULL;
      99             :         }
     100      600766 :         state->ev = ev;
     101      600766 :         state->transport = transport;
     102      600766 :         state->data = data;
     103      600766 :         state->size = size;
     104      600766 :         state->num_read = 0;
     105             : 
     106      600766 :         DBG_INFO("data_to_read: %zu\n", size);
     107             : 
     108      600766 :         subreq = transport->read_send(state, ev, (uint8_t *)data, size,
     109             :                                       transport->priv);
     110      600766 :         if (subreq == NULL) {
     111           0 :                 goto fail;
     112             :         }
     113      600766 :         tevent_req_set_callback(subreq, rpc_read_done, req);
     114      600766 :         return req;
     115             : 
     116           0 :  fail:
     117           0 :         TALLOC_FREE(req);
     118           0 :         return NULL;
     119             : }
     120             : 
     121      600766 : static void rpc_read_done(struct tevent_req *subreq)
     122             : {
     123      600766 :         struct tevent_req *req = tevent_req_callback_data(
     124             :                 subreq, struct tevent_req);
     125      600766 :         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      600766 :         status = state->transport->read_recv(subreq, &received);
     131      600766 :         TALLOC_FREE(subreq);
     132      600766 :         if (tevent_req_nterror(req, status)) {
     133      600766 :                 return;
     134             :         }
     135             : 
     136      600766 :         state->num_read += received;
     137      600766 :         if (state->num_read == state->size) {
     138      600766 :                 tevent_req_done(req);
     139      600766 :                 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      600766 : static NTSTATUS rpc_read_recv(struct tevent_req *req)
     153             : {
     154      600766 :         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      475731 : 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      475731 :         req = tevent_req_create(mem_ctx, &state, struct rpc_write_state);
     176      475731 :         if (req == NULL) {
     177           0 :                 return NULL;
     178             :         }
     179      475731 :         state->ev = ev;
     180      475731 :         state->transport = transport;
     181      475731 :         state->data = data;
     182      475731 :         state->size = size;
     183      475731 :         state->num_written = 0;
     184             : 
     185      475731 :         DBG_INFO("data_to_write: %zu\n", size);
     186             : 
     187      475731 :         subreq = transport->write_send(state, ev, data, size, transport->priv);
     188      475731 :         if (tevent_req_nomem(subreq, req)) {
     189           0 :                 return tevent_req_post(req, ev);
     190             :         }
     191      475731 :         tevent_req_set_callback(subreq, rpc_write_done, req);
     192      475731 :         return req;
     193             : }
     194             : 
     195      475731 : static void rpc_write_done(struct tevent_req *subreq)
     196             : {
     197      475731 :         struct tevent_req *req = tevent_req_callback_data(
     198             :                 subreq, struct tevent_req);
     199      475731 :         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      475731 :         status = state->transport->write_recv(subreq, &written);
     205      475731 :         TALLOC_FREE(subreq);
     206      475731 :         if (tevent_req_nterror(req, status)) {
     207      475731 :                 return;
     208             :         }
     209             : 
     210      475731 :         state->num_written += written;
     211             : 
     212      475731 :         if (state->num_written == state->size) {
     213      475731 :                 tevent_req_done(req);
     214      475731 :                 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      475731 : static NTSTATUS rpc_write_recv(struct tevent_req *req)
     228             : {
     229      475731 :         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      600324 : 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      600324 :         req = tevent_req_create(mem_ctx, &state,
     258             :                                 struct get_complete_frag_state);
     259      600324 :         if (req == NULL) {
     260           0 :                 return NULL;
     261             :         }
     262      600324 :         state->ev = ev;
     263      600324 :         state->cli = cli;
     264      600324 :         state->frag_len = RPC_HEADER_LEN;
     265      600324 :         state->pdu = pdu;
     266             : 
     267      600324 :         received = pdu->length;
     268      600324 :         if (received < RPC_HEADER_LEN) {
     269         442 :                 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         442 :                 subreq = rpc_read_send(state, state->ev,
     274         442 :                                         state->cli->transport,
     275         442 :                                         pdu->data + received,
     276             :                                         RPC_HEADER_LEN - received);
     277         442 :                 if (tevent_req_nomem(subreq, req)) {
     278           0 :                         return tevent_req_post(req, ev);
     279             :                 }
     280         442 :                 tevent_req_set_callback(subreq, get_complete_frag_got_header,
     281             :                                         req);
     282         442 :                 return req;
     283             :         }
     284             : 
     285      599882 :         state->frag_len = dcerpc_get_frag_length(pdu);
     286      599882 :         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      599882 :         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      599882 :         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      599882 :         subreq = rpc_read_send(
     305             :                 state,
     306      599882 :                 state->ev,
     307      599882 :                 state->cli->transport,
     308      599882 :                 pdu->data + received,
     309      599882 :                 state->frag_len - received);
     310      599882 :         if (tevent_req_nomem(subreq, req)) {
     311           0 :                 return tevent_req_post(req, ev);
     312             :         }
     313      599882 :         tevent_req_set_callback(subreq, get_complete_frag_got_rest, req);
     314      599882 :         return req;
     315             : }
     316             : 
     317         442 : static void get_complete_frag_got_header(struct tevent_req *subreq)
     318             : {
     319         442 :         struct tevent_req *req = tevent_req_callback_data(
     320             :                 subreq, struct tevent_req);
     321         442 :         struct get_complete_frag_state *state = tevent_req_data(
     322             :                 req, struct get_complete_frag_state);
     323           0 :         NTSTATUS status;
     324             : 
     325         442 :         status = rpc_read_recv(subreq);
     326         442 :         TALLOC_FREE(subreq);
     327         442 :         if (tevent_req_nterror(req, status)) {
     328           0 :                 return;
     329             :         }
     330             : 
     331         442 :         state->frag_len = dcerpc_get_frag_length(state->pdu);
     332         442 :         if (state->frag_len < RPC_HEADER_LEN) {
     333           0 :                 tevent_req_nterror(req, NT_STATUS_RPC_PROTOCOL_ERROR);
     334           0 :                 return;
     335             :         }
     336             : 
     337         442 :         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         442 :         subreq = rpc_read_send(state, state->ev, state->cli->transport,
     348         442 :                                 state->pdu->data + RPC_HEADER_LEN,
     349         442 :                                 state->frag_len - RPC_HEADER_LEN);
     350         442 :         if (tevent_req_nomem(subreq, req)) {
     351           0 :                 return;
     352             :         }
     353         442 :         tevent_req_set_callback(subreq, get_complete_frag_got_rest, req);
     354             : }
     355             : 
     356      600324 : static void get_complete_frag_got_rest(struct tevent_req *subreq)
     357             : {
     358      600324 :         NTSTATUS status = rpc_read_recv(subreq);
     359      600324 :         return tevent_req_simple_finish_ntstatus(subreq, status);
     360             : }
     361             : 
     362      600324 : static NTSTATUS get_complete_frag_recv(struct tevent_req *req)
     363             : {
     364      600324 :         return tevent_req_simple_recv_ntstatus(req);
     365             : }
     366             : 
     367             : /****************************************************************************
     368             :  Do basic authentication checks on an incoming pdu.
     369             :  ****************************************************************************/
     370             : 
     371      600324 : 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      600324 :         const struct dcerpc_response *r = NULL;
     381      600324 :         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      600324 :         *rdata = *pdu;
     389             : 
     390      600324 :         if ((pkt->ptype == DCERPC_PKT_BIND_ACK) &&
     391       44597 :             !(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      600324 :         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         255 :                         return ret;
     423             :                 }
     424             : 
     425             :                 /* Use this for now... */
     426           0 :                 return NT_STATUS_NETWORK_ACCESS_DENIED;
     427             : 
     428       44597 :         case DCERPC_PKT_BIND_ACK:
     429       44597 :                 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       44597 :                 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       44597 :                 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      555313 :         case DCERPC_PKT_RESPONSE:
     469             : 
     470      555313 :                 r = &pkt->u.response;
     471             : 
     472      555313 :                 ret = dcerpc_verify_ncacn_packet_header(pkt,
     473             :                                                 expected_pkt_type,
     474      555313 :                                                 r->stub_and_verifier.length,
     475             :                                                 0, /* required_flags */
     476             :                                                 DCERPC_PFC_FLAG_FIRST |
     477             :                                                 DCERPC_PFC_FLAG_LAST);
     478      555313 :                 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      555313 :                 tmp_stub.data = r->stub_and_verifier.data;
     489      555313 :                 tmp_stub.length = r->stub_and_verifier.length;
     490             : 
     491             :                 /* Here's where we deal with incoming sign/seal. */
     492      555313 :                 ret = dcerpc_check_auth(cli->auth, pkt,
     493             :                                         &tmp_stub,
     494             :                                         DCERPC_RESPONSE_LENGTH,
     495             :                                         pdu);
     496      555313 :                 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      555313 :                 *rdata = tmp_stub;
     508             : 
     509      555313 :                 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      555313 :                 if ((reply_pdu->length == 0) &&
     520      554871 :                     r->alloc_hint && (r->alloc_hint < 15*1024*1024)) {
     521      554871 :                         if (!data_blob_realloc(mem_ctx, reply_pdu,
     522      554871 :                                                         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      555313 :                 break;
     531             : 
     532         255 :         case DCERPC_PKT_FAULT:
     533             : 
     534         255 :                 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         255 :                 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         255 :                 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         255 :                 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      600069 :         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      600069 :         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      599882 : 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      599882 :         req = tevent_req_create(mem_ctx, &state, struct cli_api_pipe_state);
     603      599882 :         if (req == NULL) {
     604           0 :                 return NULL;
     605             :         }
     606      599882 :         state->ev = ev;
     607      599882 :         state->transport = transport;
     608             : 
     609      599882 :         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      599882 :         if (transport->trans_send != NULL) {
     620      124225 :                 subreq = transport->trans_send(state, ev, data, data_len,
     621             :                                                max_rdata_len, transport->priv);
     622      124225 :                 if (tevent_req_nomem(subreq, req)) {
     623           0 :                         return tevent_req_post(req, ev);
     624             :                 }
     625      124225 :                 tevent_req_set_callback(subreq, cli_api_pipe_trans_done, req);
     626      124225 :                 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      475657 :         subreq = rpc_write_send(state, ev, transport, data, data_len);
     635      475657 :         if (tevent_req_nomem(subreq, req)) {
     636           0 :                 return tevent_req_post(req, ev);
     637             :         }
     638      475657 :         tevent_req_set_callback(subreq, cli_api_pipe_write_done, req);
     639      475657 :         return req;
     640             : }
     641             : 
     642      124225 : static void cli_api_pipe_trans_done(struct tevent_req *subreq)
     643             : {
     644      124225 :         struct tevent_req *req = tevent_req_callback_data(
     645             :                 subreq, struct tevent_req);
     646      124225 :         struct cli_api_pipe_state *state = tevent_req_data(
     647             :                 req, struct cli_api_pipe_state);
     648           0 :         NTSTATUS status;
     649             : 
     650      124225 :         status = state->transport->trans_recv(subreq, state, &state->rdata,
     651             :                                               &state->rdata_len);
     652      124225 :         TALLOC_FREE(subreq);
     653      124225 :         if (tevent_req_nterror(req, status)) {
     654           0 :                 return;
     655             :         }
     656      124225 :         tevent_req_done(req);
     657             : }
     658             : 
     659      475657 : static void cli_api_pipe_write_done(struct tevent_req *subreq)
     660             : {
     661      475657 :         struct tevent_req *req = tevent_req_callback_data(
     662             :                 subreq, struct tevent_req);
     663      475657 :         struct cli_api_pipe_state *state = tevent_req_data(
     664             :                 req, struct cli_api_pipe_state);
     665           0 :         NTSTATUS status;
     666             : 
     667      475657 :         status = rpc_write_recv(subreq);
     668      475657 :         TALLOC_FREE(subreq);
     669      475657 :         if (tevent_req_nterror(req, status)) {
     670           0 :                 return;
     671             :         }
     672             : 
     673      475657 :         state->rdata = talloc_array(state, uint8_t, RPC_HEADER_LEN);
     674      475657 :         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      475657 :         subreq = state->transport->read_send(state, state->ev, state->rdata,
     684             :                                              RPC_HEADER_LEN,
     685      475657 :                                              state->transport->priv);
     686      475657 :         if (tevent_req_nomem(subreq, req)) {
     687           0 :                 return;
     688             :         }
     689      475657 :         tevent_req_set_callback(subreq, cli_api_pipe_read_done, req);
     690             : }
     691             : 
     692      475657 : static void cli_api_pipe_read_done(struct tevent_req *subreq)
     693             : {
     694      475657 :         struct tevent_req *req = tevent_req_callback_data(
     695             :                 subreq, struct tevent_req);
     696      475657 :         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      475657 :         status = state->transport->read_recv(subreq, &received);
     702      475657 :         TALLOC_FREE(subreq);
     703      475657 :         if (tevent_req_nterror(req, status)) {
     704           0 :                 return;
     705             :         }
     706      475657 :         state->rdata_len = received;
     707      475657 :         tevent_req_done(req);
     708             : }
     709             : 
     710      599882 : static NTSTATUS cli_api_pipe_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx,
     711             :                                   uint8_t **prdata, uint32_t *prdata_len)
     712             : {
     713      599882 :         struct cli_api_pipe_state *state = tevent_req_data(
     714             :                 req, struct cli_api_pipe_state);
     715           0 :         NTSTATUS status;
     716             : 
     717      599882 :         if (tevent_req_is_nterror(req, &status)) {
     718           0 :                 return status;
     719             :         }
     720             : 
     721      599882 :         *prdata = talloc_move(mem_ctx, &state->rdata);
     722      599882 :         *prdata_len = state->rdata_len;
     723      599882 :         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      599956 : 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      599956 :         req = tevent_req_create(mem_ctx, &state, struct rpc_api_pipe_state);
     783      599956 :         if (req == NULL) {
     784           0 :                 return NULL;
     785             :         }
     786      599956 :         state->ev = ev;
     787      599956 :         state->cli = cli;
     788      599956 :         state->expected_pkt_type = expected_pkt_type;
     789      599956 :         state->call_id = call_id;
     790      599956 :         state->endianness = DCERPC_DREP_LE;
     791             : 
     792             :         /*
     793             :          * Ensure we're not sending too much.
     794             :          */
     795      599956 :         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      599956 :         DEBUG(5,("rpc_api_pipe: %s\n", rpccli_pipe_txt(talloc_tos(), cli)));
     801             : 
     802      599956 :         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      599882 :         max_recv_frag = RPC_HEADER_LEN;
     815             : 
     816      599882 :         subreq = cli_api_pipe_send(state, ev, cli->transport,
     817             :                                    data->data, data->length, max_recv_frag);
     818      599882 :         if (tevent_req_nomem(subreq, req)) {
     819           0 :                 return tevent_req_post(req, ev);
     820             :         }
     821      599882 :         tevent_req_set_callback(subreq, rpc_api_pipe_trans_done, req);
     822      599882 :         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      599882 : static void rpc_api_pipe_trans_done(struct tevent_req *subreq)
     832             : {
     833      599882 :         struct tevent_req *req = tevent_req_callback_data(
     834             :                 subreq, struct tevent_req);
     835      599882 :         struct rpc_api_pipe_state *state = tevent_req_data(
     836             :                 req, struct rpc_api_pipe_state);
     837           0 :         NTSTATUS status;
     838      599882 :         uint8_t *rdata = NULL;
     839      599882 :         uint32_t rdata_len = 0;
     840             : 
     841      599882 :         status = cli_api_pipe_recv(subreq, state, &rdata, &rdata_len);
     842      599882 :         TALLOC_FREE(subreq);
     843      599882 :         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      599882 :         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      599882 :         state->incoming_frag.data = talloc_move(state, &rdata);
     859      599882 :         state->incoming_frag.length = rdata_len;
     860      599882 :         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      599882 :         subreq = get_complete_frag_send(state, state->ev, state->cli,
     867             :                                         &state->incoming_frag);
     868      599882 :         if (tevent_req_nomem(subreq, req)) {
     869           0 :                 return;
     870             :         }
     871      599882 :         tevent_req_set_callback(subreq, rpc_api_pipe_got_pdu, req);
     872             : }
     873             : 
     874      600324 : static void rpc_api_pipe_got_pdu(struct tevent_req *subreq)
     875             : {
     876      600324 :         struct tevent_req *req = tevent_req_callback_data(
     877             :                 subreq, struct tevent_req);
     878      600324 :         struct rpc_api_pipe_state *state = tevent_req_data(
     879             :                 req, struct rpc_api_pipe_state);
     880           0 :         NTSTATUS status;
     881      600324 :         DATA_BLOB rdata = { .data = NULL };
     882             : 
     883      600324 :         status = get_complete_frag_recv(subreq);
     884      600324 :         TALLOC_FREE(subreq);
     885      600324 :         if (tevent_req_nterror(req, status)) {
     886           0 :                 DEBUG(5, ("get_complete_frag failed: %s\n",
     887             :                           nt_errstr(status)));
     888      599882 :                 return;
     889             :         }
     890             : 
     891      600324 :         state->pkt = talloc(state, struct ncacn_packet);
     892      600324 :         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      600324 :         status = dcerpc_pull_ncacn_packet(state->pkt,
     904      600324 :                                           &state->incoming_frag,
     905             :                                           state->pkt);
     906      600324 :         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      600324 :         if (DEBUGLEVEL >= 10) {
     917          98 :                 NDR_PRINT_DEBUG(ncacn_packet, state->pkt);
     918             :         }
     919             : 
     920      600324 :         status = cli_pipe_validate_current_pdu(state,
     921             :                                                 state->cli, state->pkt,
     922             :                                                 &state->incoming_frag,
     923      600324 :                                                 state->expected_pkt_type,
     924             :                                                 state->call_id,
     925             :                                                 &rdata,
     926             :                                                 &state->reply_pdu);
     927             : 
     928      600324 :         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      600324 :         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      600324 :         } 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      600324 :         } 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      600324 :         if (tevent_req_nterror(req, status)) {
     956         255 :                 return;
     957             :         }
     958             : 
     959      600069 :         if ((state->pkt->pfc_flags & DCERPC_PFC_FLAG_FIRST)
     960      599627 :             && (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      600069 :         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      600069 :         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      600069 :         if (state->reply_pdu.length < state->reply_pdu_offset + rdata.length) {
    1001       44756 :                 if (!data_blob_realloc(NULL, &state->reply_pdu,
    1002       44756 :                                 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      600069 :         memcpy(state->reply_pdu.data + state->reply_pdu_offset,
    1015      600069 :                 rdata.data, rdata.length);
    1016      600069 :         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      600069 :         state->incoming_frag.length = 0;
    1022             : 
    1023      600069 :         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      599627 :                 state->reply_pdu.length = state->reply_pdu_offset;
    1028      599627 :                 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      599627 :                 tevent_req_done(req);
    1032      599627 :                 return;
    1033             :         }
    1034             : 
    1035         442 :         subreq = get_complete_frag_send(state, state->ev, state->cli,
    1036             :                                         &state->incoming_frag);
    1037         442 :         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         442 :         if (tevent_req_nomem(subreq, req)) {
    1046           0 :                 return;
    1047             :         }
    1048         442 :         tevent_req_set_callback(subreq, rpc_api_pipe_got_pdu, req);
    1049             : }
    1050             : 
    1051      599956 : 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      599956 :         struct rpc_api_pipe_state *state = tevent_req_data(
    1056             :                 req, struct rpc_api_pipe_state);
    1057           0 :         NTSTATUS status;
    1058             : 
    1059      599956 :         if (tevent_req_is_nterror(req, &status)) {
    1060         255 :                 return status;
    1061             :         }
    1062             : 
    1063             :         /* return data to caller and assign it ownership of memory */
    1064      599701 :         if (reply_pdu) {
    1065      554871 :                 reply_pdu->data = talloc_move(mem_ctx, &state->reply_pdu.data);
    1066      554871 :                 reply_pdu->length = state->reply_pdu.length;
    1067      554871 :                 state->reply_pdu.length = 0;
    1068             :         } else {
    1069       44830 :                 data_blob_free(&state->reply_pdu);
    1070             :         }
    1071             : 
    1072      599701 :         if (pkt) {
    1073       44830 :                 *pkt = talloc_steal(mem_ctx, state->pkt);
    1074             :         }
    1075             : 
    1076      599701 :         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       44756 : 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       44756 :         uint16_t auth_len = auth_info->length;
    1132           0 :         NTSTATUS status;
    1133       44756 :         struct dcerpc_ctx_list ctx_list = {
    1134             :                 .context_id = 0,
    1135             :                 .num_transfer_syntaxes = 1,
    1136             :                 .abstract_syntax = *abstract,
    1137             :                 .transfer_syntaxes = (struct ndr_syntax_id *)discard_const(transfer),
    1138             :         };
    1139       44756 :         union dcerpc_payload u = {
    1140             :                 .bind.max_xmit_frag     = RPC_MAX_PDU_FRAG_LEN,
    1141             :                 .bind.max_recv_frag     = RPC_MAX_PDU_FRAG_LEN,
    1142             :                 .bind.num_contexts      = 1,
    1143             :                 .bind.ctx_list          = &ctx_list,
    1144             :                 .bind.auth_info         = *auth_info,
    1145             :         };
    1146       44756 :         uint8_t pfc_flags = DCERPC_PFC_FLAG_FIRST | DCERPC_PFC_FLAG_LAST;
    1147             : 
    1148       44756 :         if (auth_len) {
    1149         635 :                 auth_len -= DCERPC_AUTH_TRAILER_LENGTH;
    1150             :         }
    1151             : 
    1152       44756 :         if (client_hdr_signing) {
    1153         310 :                 pfc_flags |= DCERPC_PFC_FLAG_SUPPORT_HEADER_SIGN;
    1154             :         }
    1155             : 
    1156       44756 :         status = dcerpc_push_ncacn_packet(mem_ctx,
    1157             :                                           ptype, pfc_flags,
    1158             :                                           auth_len,
    1159             :                                           rpc_call_id,
    1160             :                                           &u,
    1161             :                                           blob);
    1162       44756 :         if (!NT_STATUS_IS_OK(status)) {
    1163           0 :                 DEBUG(0, ("Failed to marshall bind/alter ncacn_packet.\n"));
    1164           0 :                 return status;
    1165             :         }
    1166             : 
    1167       44756 :         return NT_STATUS_OK;
    1168             : }
    1169             : 
    1170             : /*******************************************************************
    1171             :  Creates a DCE/RPC bind request.
    1172             :  ********************************************************************/
    1173             : 
    1174       44597 : static NTSTATUS create_rpc_bind_req(TALLOC_CTX *mem_ctx,
    1175             :                                     struct rpc_pipe_client *cli,
    1176             :                                     struct pipe_auth_data *auth,
    1177             :                                     uint32_t rpc_call_id,
    1178             :                                     const struct ndr_syntax_id *abstract,
    1179             :                                     const struct ndr_syntax_id *transfer,
    1180             :                                     DATA_BLOB *rpc_out)
    1181             : {
    1182       44597 :         DATA_BLOB auth_token = { .data = NULL };
    1183       44597 :         DATA_BLOB auth_info = { .data = NULL };
    1184           0 :         NTSTATUS ret;
    1185             : 
    1186       44597 :         if (auth->auth_type != DCERPC_AUTH_TYPE_NONE) {
    1187         476 :                 ret = create_generic_auth_rpc_bind_req(
    1188             :                         cli, mem_ctx, &auth_token, &auth->client_hdr_signing);
    1189             : 
    1190         476 :                 if (!NT_STATUS_IS_OK(ret) &&
    1191         476 :                     !NT_STATUS_EQUAL(ret, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
    1192           0 :                         return ret;
    1193             :                 }
    1194             :         }
    1195             : 
    1196       44597 :         if (auth_token.length != 0) {
    1197         476 :                 ret = dcerpc_push_dcerpc_auth(cli,
    1198             :                                                 auth->auth_type,
    1199             :                                                 auth->auth_level,
    1200             :                                                 0, /* auth_pad_length */
    1201             :                                                 auth->auth_context_id,
    1202             :                                                 &auth_token,
    1203             :                                                 &auth_info);
    1204         476 :                 if (!NT_STATUS_IS_OK(ret)) {
    1205           0 :                         return ret;
    1206             :                 }
    1207         476 :                 data_blob_free(&auth_token);
    1208             :         }
    1209             : 
    1210       44597 :         ret = create_bind_or_alt_ctx_internal(mem_ctx,
    1211             :                                               DCERPC_PKT_BIND,
    1212             :                                               rpc_call_id,
    1213             :                                               abstract,
    1214             :                                               transfer,
    1215             :                                               &auth_info,
    1216       44597 :                                               auth->client_hdr_signing,
    1217             :                                               rpc_out);
    1218       44597 :         data_blob_free(&auth_info);
    1219             : 
    1220       44597 :         return ret;
    1221             : }
    1222             : 
    1223             : /*******************************************************************
    1224             :  External interface.
    1225             :  Does an rpc request on a pipe. Incoming data is NDR encoded in in_data.
    1226             :  Reply is NDR encoded in out_data. Splits the data stream into RPC PDU's
    1227             :  and deals with signing/sealing details.
    1228             :  ********************************************************************/
    1229             : 
    1230             : struct rpc_api_pipe_req_state {
    1231             :         struct tevent_context *ev;
    1232             :         struct rpc_pipe_client *cli;
    1233             :         uint8_t op_num;
    1234             :         uint32_t call_id;
    1235             :         const DATA_BLOB *req_data;
    1236             :         const struct GUID *object_uuid;
    1237             :         uint32_t req_data_sent;
    1238             :         DATA_BLOB req_trailer;
    1239             :         uint32_t req_trailer_sent;
    1240             :         bool verify_bitmask1;
    1241             :         bool verify_pcontext;
    1242             :         DATA_BLOB rpc_out;
    1243             :         DATA_BLOB reply_pdu;
    1244             : };
    1245             : 
    1246             : static void rpc_api_pipe_req_write_done(struct tevent_req *subreq);
    1247             : static void rpc_api_pipe_req_done(struct tevent_req *subreq);
    1248             : static NTSTATUS prepare_verification_trailer(struct rpc_api_pipe_req_state *state);
    1249             : static NTSTATUS prepare_next_frag(struct rpc_api_pipe_req_state *state,
    1250             :                                   bool *is_last_frag);
    1251             : 
    1252      555126 : static struct tevent_req *rpc_api_pipe_req_send(TALLOC_CTX *mem_ctx,
    1253             :                                          struct tevent_context *ev,
    1254             :                                          struct rpc_pipe_client *cli,
    1255             :                                          uint8_t op_num,
    1256             :                                          const struct GUID *object_uuid,
    1257             :                                          const DATA_BLOB *req_data)
    1258             : {
    1259           0 :         struct tevent_req *req, *subreq;
    1260           0 :         struct rpc_api_pipe_req_state *state;
    1261           0 :         NTSTATUS status;
    1262           0 :         bool is_last_frag;
    1263             : 
    1264      555126 :         req = tevent_req_create(mem_ctx, &state,
    1265             :                                 struct rpc_api_pipe_req_state);
    1266      555126 :         if (req == NULL) {
    1267           0 :                 return NULL;
    1268             :         }
    1269      555126 :         state->ev = ev;
    1270      555126 :         state->cli = cli;
    1271      555126 :         state->op_num = op_num;
    1272      555126 :         state->object_uuid = object_uuid;
    1273      555126 :         state->req_data = req_data;
    1274      555126 :         state->call_id = get_rpc_call_id();
    1275             : 
    1276      555126 :         if (cli->max_xmit_frag < DCERPC_REQUEST_LENGTH
    1277             :                                         + RPC_MAX_SIGN_SIZE) {
    1278             :                 /* Server is screwed up ! */
    1279           0 :                 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
    1280           0 :                 return tevent_req_post(req, ev);
    1281             :         }
    1282             : 
    1283      555126 :         status = prepare_verification_trailer(state);
    1284      555126 :         if (tevent_req_nterror(req, status)) {
    1285           0 :                 return tevent_req_post(req, ev);
    1286             :         }
    1287             : 
    1288      555126 :         status = prepare_next_frag(state, &is_last_frag);
    1289      555126 :         if (tevent_req_nterror(req, status)) {
    1290           0 :                 return tevent_req_post(req, ev);
    1291             :         }
    1292             : 
    1293      555126 :         if (is_last_frag) {
    1294      555126 :                 subreq = rpc_api_pipe_send(state, ev, state->cli,
    1295      555126 :                                            &state->rpc_out,
    1296             :                                            DCERPC_PKT_RESPONSE,
    1297      555126 :                                            state->call_id);
    1298      555126 :                 if (tevent_req_nomem(subreq, req)) {
    1299           0 :                         return tevent_req_post(req, ev);
    1300             :                 }
    1301      555126 :                 tevent_req_set_callback(subreq, rpc_api_pipe_req_done, req);
    1302             :         } else {
    1303           0 :                 subreq = rpc_write_send(state, ev, cli->transport,
    1304           0 :                                         state->rpc_out.data,
    1305           0 :                                         state->rpc_out.length);
    1306           0 :                 if (tevent_req_nomem(subreq, req)) {
    1307           0 :                         return tevent_req_post(req, ev);
    1308             :                 }
    1309           0 :                 tevent_req_set_callback(subreq, rpc_api_pipe_req_write_done,
    1310             :                                         req);
    1311             :         }
    1312      555126 :         return req;
    1313             : }
    1314             : 
    1315      555126 : static NTSTATUS prepare_verification_trailer(struct rpc_api_pipe_req_state *state)
    1316             : {
    1317      555126 :         struct pipe_auth_data *a = state->cli->auth;
    1318           0 :         struct dcerpc_sec_verification_trailer *t;
    1319      555126 :         struct ndr_push *ndr = NULL;
    1320           0 :         enum ndr_err_code ndr_err;
    1321      555126 :         size_t align = 0;
    1322      555126 :         size_t pad = 0;
    1323             : 
    1324      555126 :         if (a == NULL) {
    1325           0 :                 return NT_STATUS_OK;
    1326             :         }
    1327             : 
    1328      555126 :         if (a->auth_level < DCERPC_AUTH_LEVEL_PACKET) {
    1329      554760 :                 return NT_STATUS_OK;
    1330             :         }
    1331             : 
    1332         366 :         t = talloc_zero(state, struct dcerpc_sec_verification_trailer);
    1333         366 :         if (t == NULL) {
    1334           0 :                 return NT_STATUS_NO_MEMORY;
    1335             :         }
    1336             : 
    1337         366 :         if (!a->verified_bitmask1) {
    1338         310 :                 t->commands = talloc_realloc(t, t->commands,
    1339             :                                              struct dcerpc_sec_vt,
    1340             :                                              t->count.count + 1);
    1341         310 :                 if (t->commands == NULL) {
    1342           0 :                         return NT_STATUS_NO_MEMORY;
    1343             :                 }
    1344         310 :                 t->commands[t->count.count++] = (struct dcerpc_sec_vt) {
    1345             :                         .command = DCERPC_SEC_VT_COMMAND_BITMASK1,
    1346         310 :                         .u.bitmask1 = (a->client_hdr_signing) ?
    1347         310 :                                 DCERPC_SEC_VT_CLIENT_SUPPORTS_HEADER_SIGNING :
    1348             :                                 0,
    1349             :                 };
    1350         310 :                 state->verify_bitmask1 = true;
    1351             :         }
    1352             : 
    1353         366 :         if (!state->cli->verified_pcontext) {
    1354         310 :                 t->commands = talloc_realloc(t, t->commands,
    1355             :                                              struct dcerpc_sec_vt,
    1356             :                                              t->count.count + 1);
    1357         310 :                 if (t->commands == NULL) {
    1358           0 :                         return NT_STATUS_NO_MEMORY;
    1359             :                 }
    1360         310 :                 t->commands[t->count.count++] = (struct dcerpc_sec_vt) {
    1361             :                         .command = DCERPC_SEC_VT_COMMAND_PCONTEXT,
    1362             :                         .u.pcontext.abstract_syntax =
    1363         310 :                                 state->cli->abstract_syntax,
    1364             :                         .u.pcontext.transfer_syntax =
    1365         310 :                                 state->cli->transfer_syntax,
    1366             :                 };
    1367         310 :                 state->verify_pcontext = true;
    1368             :         }
    1369             : 
    1370         366 :         if (!a->hdr_signing) {
    1371           0 :                 t->commands = talloc_realloc(t, t->commands,
    1372             :                                              struct dcerpc_sec_vt,
    1373             :                                              t->count.count + 1);
    1374           0 :                 if (t->commands == NULL) {
    1375           0 :                         return NT_STATUS_NO_MEMORY;
    1376             :                 }
    1377           0 :                 t->commands[t->count.count++] = (struct dcerpc_sec_vt) {
    1378             :                         .command = DCERPC_SEC_VT_COMMAND_HEADER2,
    1379             :                         .u.header2.ptype = DCERPC_PKT_REQUEST,
    1380             :                         .u.header2.drep[0] = DCERPC_DREP_LE,
    1381           0 :                         .u.header2.call_id = state->call_id,
    1382             :                         .u.header2.context_id = 0,
    1383           0 :                         .u.header2.opnum = state->op_num,
    1384             :                 };
    1385             :         }
    1386             : 
    1387         366 :         if (t->count.count == 0) {
    1388          56 :                 TALLOC_FREE(t);
    1389          56 :                 return NT_STATUS_OK;
    1390             :         }
    1391             : 
    1392         310 :         t->commands[t->count.count - 1].command |= DCERPC_SEC_VT_COMMAND_END;
    1393             : 
    1394         310 :         if (DEBUGLEVEL >= 10) {
    1395           0 :                 NDR_PRINT_DEBUG(dcerpc_sec_verification_trailer, t);
    1396             :         }
    1397             : 
    1398         310 :         ndr = ndr_push_init_ctx(state);
    1399         310 :         if (ndr == NULL) {
    1400           0 :                 return NT_STATUS_NO_MEMORY;
    1401             :         }
    1402             : 
    1403         310 :         ndr_err = ndr_push_dcerpc_sec_verification_trailer(ndr,
    1404             :                                                 NDR_SCALARS | NDR_BUFFERS,
    1405             :                                                 t);
    1406         310 :         TALLOC_FREE(t);
    1407         310 :         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
    1408           0 :                 return ndr_map_error2ntstatus(ndr_err);
    1409             :         }
    1410         310 :         state->req_trailer = ndr_push_blob(ndr);
    1411             : 
    1412         310 :         align = state->req_data->length & 0x3;
    1413         310 :         if (align > 0) {
    1414           0 :                 pad = 4 - align;
    1415             :         }
    1416         310 :         if (pad > 0) {
    1417           0 :                 bool ok;
    1418           0 :                 uint8_t *p;
    1419           0 :                 const uint8_t zeros[4] = { 0, };
    1420             : 
    1421           0 :                 ok = data_blob_append(ndr, &state->req_trailer, zeros, pad);
    1422           0 :                 if (!ok) {
    1423           0 :                         return NT_STATUS_NO_MEMORY;
    1424             :                 }
    1425             : 
    1426             :                 /* move the padding to the start */
    1427           0 :                 p = state->req_trailer.data;
    1428           0 :                 memmove(p + pad, p, state->req_trailer.length - pad);
    1429           0 :                 memset(p, 0, pad);
    1430             :         }
    1431             : 
    1432         310 :         return NT_STATUS_OK;
    1433             : }
    1434             : 
    1435      555126 : static NTSTATUS prepare_next_frag(struct rpc_api_pipe_req_state *state,
    1436             :                                   bool *is_last_frag)
    1437             : {
    1438           0 :         size_t auth_len;
    1439           0 :         size_t frag_len;
    1440      555126 :         uint8_t flags = 0;
    1441           0 :         size_t pad_len;
    1442           0 :         size_t data_left;
    1443           0 :         size_t data_thistime;
    1444           0 :         size_t trailer_left;
    1445      555126 :         size_t trailer_thistime = 0;
    1446           0 :         size_t total_left;
    1447           0 :         size_t total_thistime;
    1448           0 :         NTSTATUS status;
    1449           0 :         bool ok;
    1450           0 :         union dcerpc_payload u;
    1451             : 
    1452      555126 :         data_left = state->req_data->length - state->req_data_sent;
    1453      555126 :         trailer_left = state->req_trailer.length - state->req_trailer_sent;
    1454      555126 :         total_left = data_left + trailer_left;
    1455      555126 :         if ((total_left < data_left) || (total_left < trailer_left)) {
    1456             :                 /*
    1457             :                  * overflow
    1458             :                  */
    1459           0 :                 return NT_STATUS_INVALID_PARAMETER_MIX;
    1460             :         }
    1461             : 
    1462      555126 :         status = dcerpc_guess_sizes(state->cli->auth,
    1463             :                                     DCERPC_REQUEST_LENGTH, total_left,
    1464      555126 :                                     state->cli->max_xmit_frag,
    1465             :                                     &total_thistime,
    1466             :                                     &frag_len, &auth_len, &pad_len);
    1467      555126 :         if (!NT_STATUS_IS_OK(status)) {
    1468           0 :                 return status;
    1469             :         }
    1470             : 
    1471      555126 :         if (state->req_data_sent == 0) {
    1472      555126 :                 flags = DCERPC_PFC_FLAG_FIRST;
    1473             :         }
    1474             : 
    1475      555126 :         if (total_thistime == total_left) {
    1476      555126 :                 flags |= DCERPC_PFC_FLAG_LAST;
    1477             :         }
    1478             : 
    1479      555126 :         data_thistime = MIN(total_thistime, data_left);
    1480      555126 :         if (data_thistime < total_thistime) {
    1481         310 :                 trailer_thistime = total_thistime - data_thistime;
    1482             :         }
    1483             : 
    1484      555126 :         data_blob_free(&state->rpc_out);
    1485             : 
    1486      555126 :         u = (union dcerpc_payload) {
    1487             :                 .request.alloc_hint     = total_left,
    1488             :                 .request.context_id     = 0,
    1489      555126 :                 .request.opnum          = state->op_num,
    1490             :         };
    1491             : 
    1492      555126 :         if (state->object_uuid) {
    1493           0 :                 flags |= DCERPC_PFC_FLAG_OBJECT_UUID;
    1494           0 :                 u.request.object.object = *state->object_uuid;
    1495           0 :                 frag_len += ndr_size_GUID(state->object_uuid, 0);
    1496             :         }
    1497             : 
    1498      555126 :         status = dcerpc_push_ncacn_packet(state,
    1499             :                                           DCERPC_PKT_REQUEST,
    1500             :                                           flags,
    1501             :                                           auth_len,
    1502             :                                           state->call_id,
    1503             :                                           &u,
    1504             :                                           &state->rpc_out);
    1505      555126 :         if (!NT_STATUS_IS_OK(status)) {
    1506           0 :                 return status;
    1507             :         }
    1508             : 
    1509             :         /* explicitly set frag_len here as dcerpc_push_ncacn_packet() can't
    1510             :          * compute it right for requests because the auth trailer is missing
    1511             :          * at this stage */
    1512      555126 :         dcerpc_set_frag_length(&state->rpc_out, frag_len);
    1513             : 
    1514      555126 :         if (data_thistime > 0) {
    1515             :                 /* Copy in the data. */
    1516      555123 :                 ok = data_blob_append(NULL, &state->rpc_out,
    1517      555123 :                                 state->req_data->data + state->req_data_sent,
    1518             :                                 data_thistime);
    1519      555123 :                 if (!ok) {
    1520           0 :                         return NT_STATUS_NO_MEMORY;
    1521             :                 }
    1522      555123 :                 state->req_data_sent += data_thistime;
    1523             :         }
    1524             : 
    1525      555126 :         if (trailer_thistime > 0) {
    1526             :                 /* Copy in the verification trailer. */
    1527         310 :                 ok = data_blob_append(NULL, &state->rpc_out,
    1528         310 :                                 state->req_trailer.data + state->req_trailer_sent,
    1529             :                                 trailer_thistime);
    1530         310 :                 if (!ok) {
    1531           0 :                         return NT_STATUS_NO_MEMORY;
    1532             :                 }
    1533         310 :                 state->req_trailer_sent += trailer_thistime;
    1534             :         }
    1535             : 
    1536      555126 :         switch (state->cli->auth->auth_level) {
    1537      554760 :         case DCERPC_AUTH_LEVEL_NONE:
    1538             :         case DCERPC_AUTH_LEVEL_CONNECT:
    1539      554760 :                 break;
    1540         366 :         case DCERPC_AUTH_LEVEL_PACKET:
    1541             :         case DCERPC_AUTH_LEVEL_INTEGRITY:
    1542             :         case DCERPC_AUTH_LEVEL_PRIVACY:
    1543         366 :                 status = dcerpc_add_auth_footer(state->cli->auth, pad_len,
    1544             :                                                 &state->rpc_out);
    1545         366 :                 if (!NT_STATUS_IS_OK(status)) {
    1546           0 :                         return status;
    1547             :                 }
    1548         366 :                 break;
    1549           0 :         default:
    1550           0 :                 return NT_STATUS_INVALID_PARAMETER;
    1551             :         }
    1552             : 
    1553      555126 :         *is_last_frag = ((flags & DCERPC_PFC_FLAG_LAST) != 0);
    1554             : 
    1555      555126 :         return status;
    1556             : }
    1557             : 
    1558           0 : static void rpc_api_pipe_req_write_done(struct tevent_req *subreq)
    1559             : {
    1560           0 :         struct tevent_req *req = tevent_req_callback_data(
    1561             :                 subreq, struct tevent_req);
    1562           0 :         struct rpc_api_pipe_req_state *state = tevent_req_data(
    1563             :                 req, struct rpc_api_pipe_req_state);
    1564           0 :         NTSTATUS status;
    1565           0 :         bool is_last_frag;
    1566             : 
    1567           0 :         status = rpc_write_recv(subreq);
    1568           0 :         TALLOC_FREE(subreq);
    1569           0 :         if (tevent_req_nterror(req, status)) {
    1570           0 :                 return;
    1571             :         }
    1572             : 
    1573           0 :         status = prepare_next_frag(state, &is_last_frag);
    1574           0 :         if (tevent_req_nterror(req, status)) {
    1575           0 :                 return;
    1576             :         }
    1577             : 
    1578           0 :         if (is_last_frag) {
    1579           0 :                 subreq = rpc_api_pipe_send(state, state->ev, state->cli,
    1580             :                                            &state->rpc_out,
    1581             :                                            DCERPC_PKT_RESPONSE,
    1582             :                                            state->call_id);
    1583           0 :                 if (tevent_req_nomem(subreq, req)) {
    1584           0 :                         return;
    1585             :                 }
    1586           0 :                 tevent_req_set_callback(subreq, rpc_api_pipe_req_done, req);
    1587             :         } else {
    1588           0 :                 subreq = rpc_write_send(state, state->ev,
    1589           0 :                                         state->cli->transport,
    1590           0 :                                         state->rpc_out.data,
    1591             :                                         state->rpc_out.length);
    1592           0 :                 if (tevent_req_nomem(subreq, req)) {
    1593           0 :                         return;
    1594             :                 }
    1595           0 :                 tevent_req_set_callback(subreq, rpc_api_pipe_req_write_done,
    1596             :                                         req);
    1597             :         }
    1598             : }
    1599             : 
    1600      555126 : static void rpc_api_pipe_req_done(struct tevent_req *subreq)
    1601             : {
    1602      555126 :         struct tevent_req *req = tevent_req_callback_data(
    1603             :                 subreq, struct tevent_req);
    1604      555126 :         struct rpc_api_pipe_req_state *state = tevent_req_data(
    1605             :                 req, struct rpc_api_pipe_req_state);
    1606           0 :         NTSTATUS status;
    1607             : 
    1608      555126 :         status = rpc_api_pipe_recv(subreq, state, NULL, &state->reply_pdu);
    1609      555126 :         TALLOC_FREE(subreq);
    1610      555126 :         if (tevent_req_nterror(req, status)) {
    1611         255 :                 return;
    1612             :         }
    1613             : 
    1614      554871 :         if (state->cli->auth == NULL) {
    1615           0 :                 tevent_req_done(req);
    1616           0 :                 return;
    1617             :         }
    1618             : 
    1619      554871 :         if (state->verify_bitmask1) {
    1620         310 :                 state->cli->auth->verified_bitmask1 = true;
    1621             :         }
    1622             : 
    1623      554871 :         if (state->verify_pcontext) {
    1624         310 :                 state->cli->verified_pcontext = true;
    1625             :         }
    1626             : 
    1627      554871 :         tevent_req_done(req);
    1628             : }
    1629             : 
    1630      555126 : static NTSTATUS rpc_api_pipe_req_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx,
    1631             :                                DATA_BLOB *reply_pdu)
    1632             : {
    1633      555126 :         struct rpc_api_pipe_req_state *state = tevent_req_data(
    1634             :                 req, struct rpc_api_pipe_req_state);
    1635           0 :         NTSTATUS status;
    1636             : 
    1637      555126 :         if (tevent_req_is_nterror(req, &status)) {
    1638             :                 /*
    1639             :                  * We always have to initialize to reply pdu, even if there is
    1640             :                  * none. The rpccli_* caller routines expect this.
    1641             :                  */
    1642         255 :                 *reply_pdu = data_blob_null;
    1643         255 :                 return status;
    1644             :         }
    1645             : 
    1646             :         /* return data to caller and assign it ownership of memory */
    1647      554871 :         reply_pdu->data = talloc_move(mem_ctx, &state->reply_pdu.data);
    1648      554871 :         reply_pdu->length = state->reply_pdu.length;
    1649      554871 :         state->reply_pdu.length = 0;
    1650             : 
    1651      554871 :         return NT_STATUS_OK;
    1652             : }
    1653             : 
    1654             : /****************************************************************************
    1655             :  Check the rpc bind acknowledge response.
    1656             : ****************************************************************************/
    1657             : 
    1658       44756 : static bool check_bind_response(const struct dcerpc_bind_ack *r,
    1659             :                                 const struct ndr_syntax_id *transfer)
    1660             : {
    1661           0 :         struct dcerpc_ack_ctx ctx;
    1662           0 :         bool equal;
    1663             : 
    1664       44756 :         if (r->secondary_address_size == 0) {
    1665         159 :                 DEBUG(4,("Ignoring length check -- ASU bug (server didn't fill in the pipe name correctly)\n"));
    1666             :         }
    1667             : 
    1668       44756 :         if (r->num_results < 1 || !r->ctx_list) {
    1669           0 :                 return false;
    1670             :         }
    1671             : 
    1672       44756 :         ctx = r->ctx_list[0];
    1673             : 
    1674             :         /* check the transfer syntax */
    1675       44756 :         equal = ndr_syntax_id_equal(&ctx.syntax, transfer);
    1676       44756 :         if (!equal) {
    1677           0 :                 DEBUG(2,("bind_rpc_pipe: transfer syntax differs\n"));
    1678           0 :                 return False;
    1679             :         }
    1680             : 
    1681       44756 :         if (r->num_results != 0x1 || ctx.result != 0) {
    1682           0 :                 DEBUG(2,("bind_rpc_pipe: bind denied results: %d reason: %x\n",
    1683             :                           r->num_results, ctx.reason.value));
    1684             :         }
    1685             : 
    1686       44756 :         DEBUG(5,("check_bind_response: accepted!\n"));
    1687       44756 :         return True;
    1688             : }
    1689             : 
    1690             : /*******************************************************************
    1691             :  Creates a DCE/RPC bind authentication response.
    1692             :  This is the packet that is sent back to the server once we
    1693             :  have received a BIND-ACK, to finish the third leg of
    1694             :  the authentication handshake.
    1695             :  ********************************************************************/
    1696             : 
    1697          74 : static NTSTATUS create_rpc_bind_auth3(TALLOC_CTX *mem_ctx,
    1698             :                                 struct rpc_pipe_client *cli,
    1699             :                                 struct pipe_auth_data *auth,
    1700             :                                 uint32_t rpc_call_id,
    1701             :                                 DATA_BLOB *pauth_blob,
    1702             :                                 DATA_BLOB *rpc_out)
    1703             : {
    1704           0 :         NTSTATUS status;
    1705          74 :         union dcerpc_payload u = { .auth3._pad = 0, };
    1706             : 
    1707          74 :         status = dcerpc_push_dcerpc_auth(mem_ctx,
    1708             :                                          auth->auth_type,
    1709             :                                          auth->auth_level,
    1710             :                                          0, /* auth_pad_length */
    1711             :                                          auth->auth_context_id,
    1712             :                                          pauth_blob,
    1713             :                                          &u.auth3.auth_info);
    1714          74 :         if (!NT_STATUS_IS_OK(status)) {
    1715           0 :                 return status;
    1716             :         }
    1717             : 
    1718          74 :         status = dcerpc_push_ncacn_packet(mem_ctx,
    1719             :                                           DCERPC_PKT_AUTH3,
    1720             :                                           DCERPC_PFC_FLAG_FIRST |
    1721             :                                           DCERPC_PFC_FLAG_LAST,
    1722          74 :                                           pauth_blob->length,
    1723             :                                           rpc_call_id,
    1724             :                                           &u,
    1725             :                                           rpc_out);
    1726          74 :         data_blob_free(&u.auth3.auth_info);
    1727          74 :         if (!NT_STATUS_IS_OK(status)) {
    1728           0 :                 DEBUG(0,("create_bind_or_alt_ctx_internal: failed to marshall RPC_HDR_RB.\n"));
    1729           0 :                 return status;
    1730             :         }
    1731             : 
    1732          74 :         return NT_STATUS_OK;
    1733             : }
    1734             : 
    1735             : /*******************************************************************
    1736             :  Creates a DCE/RPC bind alter context authentication request which
    1737             :  may contain a spnego auth blob
    1738             :  ********************************************************************/
    1739             : 
    1740         159 : static NTSTATUS create_rpc_alter_context(TALLOC_CTX *mem_ctx,
    1741             :                                         struct pipe_auth_data *auth,
    1742             :                                         uint32_t rpc_call_id,
    1743             :                                         const struct ndr_syntax_id *abstract,
    1744             :                                         const struct ndr_syntax_id *transfer,
    1745             :                                         const DATA_BLOB *pauth_blob, /* spnego auth blob already created. */
    1746             :                                         DATA_BLOB *rpc_out)
    1747             : {
    1748           0 :         DATA_BLOB auth_info;
    1749           0 :         NTSTATUS status;
    1750             : 
    1751         159 :         status = dcerpc_push_dcerpc_auth(mem_ctx,
    1752             :                                          auth->auth_type,
    1753             :                                          auth->auth_level,
    1754             :                                          0, /* auth_pad_length */
    1755             :                                          auth->auth_context_id,
    1756             :                                          pauth_blob,
    1757             :                                          &auth_info);
    1758         159 :         if (!NT_STATUS_IS_OK(status)) {
    1759           0 :                 return status;
    1760             :         }
    1761             : 
    1762         159 :         status = create_bind_or_alt_ctx_internal(mem_ctx,
    1763             :                                                  DCERPC_PKT_ALTER,
    1764             :                                                  rpc_call_id,
    1765             :                                                  abstract,
    1766             :                                                  transfer,
    1767             :                                                  &auth_info,
    1768             :                                                  false, /* client_hdr_signing */
    1769             :                                                  rpc_out);
    1770         159 :         data_blob_free(&auth_info);
    1771         159 :         return status;
    1772             : }
    1773             : 
    1774             : /****************************************************************************
    1775             :  Do an rpc bind.
    1776             : ****************************************************************************/
    1777             : 
    1778             : struct rpc_pipe_bind_state {
    1779             :         struct tevent_context *ev;
    1780             :         struct rpc_pipe_client *cli;
    1781             :         DATA_BLOB rpc_out;
    1782             :         bool auth3;
    1783             :         uint32_t rpc_call_id;
    1784             : };
    1785             : 
    1786             : static void rpc_pipe_bind_step_one_done(struct tevent_req *subreq);
    1787             : static NTSTATUS rpc_bind_next_send(struct tevent_req *req,
    1788             :                                    struct rpc_pipe_bind_state *state,
    1789             :                                    DATA_BLOB *credentials);
    1790             : static NTSTATUS rpc_bind_finish_send(struct tevent_req *req,
    1791             :                                      struct rpc_pipe_bind_state *state,
    1792             :                                      DATA_BLOB *credentials);
    1793             : 
    1794       44597 : struct tevent_req *rpc_pipe_bind_send(TALLOC_CTX *mem_ctx,
    1795             :                                       struct tevent_context *ev,
    1796             :                                       struct rpc_pipe_client *cli,
    1797             :                                       struct pipe_auth_data *auth)
    1798             : {
    1799           0 :         struct tevent_req *req, *subreq;
    1800           0 :         struct rpc_pipe_bind_state *state;
    1801           0 :         NTSTATUS status;
    1802             : 
    1803       44597 :         req = tevent_req_create(mem_ctx, &state, struct rpc_pipe_bind_state);
    1804       44597 :         if (req == NULL) {
    1805           0 :                 return NULL;
    1806             :         }
    1807             : 
    1808       44597 :         DEBUG(5,("Bind RPC Pipe: %s auth_type %u, auth_level %u\n",
    1809             :                 rpccli_pipe_txt(talloc_tos(), cli),
    1810             :                 (unsigned int)auth->auth_type,
    1811             :                 (unsigned int)auth->auth_level ));
    1812             : 
    1813       44597 :         state->ev = ev;
    1814       44597 :         state->cli = cli;
    1815       44597 :         state->rpc_call_id = get_rpc_call_id();
    1816             : 
    1817       44597 :         cli->auth = talloc_move(cli, &auth);
    1818             : 
    1819             :         /* Marshall the outgoing data. */
    1820       44597 :         status = create_rpc_bind_req(state, cli,
    1821             :                                      cli->auth,
    1822       44597 :                                      state->rpc_call_id,
    1823       44597 :                                      &cli->abstract_syntax,
    1824       44597 :                                      &cli->transfer_syntax,
    1825       44597 :                                      &state->rpc_out);
    1826             : 
    1827       44597 :         if (!NT_STATUS_IS_OK(status) &&
    1828           0 :             !NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
    1829           0 :                 tevent_req_nterror(req, status);
    1830           0 :                 return tevent_req_post(req, ev);
    1831             :         }
    1832             : 
    1833       44597 :         subreq = rpc_api_pipe_send(state, ev, cli, &state->rpc_out,
    1834       44597 :                                    DCERPC_PKT_BIND_ACK, state->rpc_call_id);
    1835       44597 :         if (tevent_req_nomem(subreq, req)) {
    1836           0 :                 return tevent_req_post(req, ev);
    1837             :         }
    1838       44597 :         tevent_req_set_callback(subreq, rpc_pipe_bind_step_one_done, req);
    1839       44597 :         return req;
    1840             : }
    1841             : 
    1842       44830 : static void rpc_pipe_bind_step_one_done(struct tevent_req *subreq)
    1843             : {
    1844       44830 :         struct tevent_req *req = tevent_req_callback_data(
    1845             :                 subreq, struct tevent_req);
    1846       44830 :         struct rpc_pipe_bind_state *state = tevent_req_data(
    1847             :                 req, struct rpc_pipe_bind_state);
    1848       44830 :         struct pipe_auth_data *pauth = state->cli->auth;
    1849           0 :         struct gensec_security *gensec_security;
    1850       44830 :         struct ncacn_packet *pkt = NULL;
    1851           0 :         struct dcerpc_auth auth;
    1852       44830 :         DATA_BLOB auth_token = { .data = NULL };
    1853           0 :         NTSTATUS status;
    1854             : 
    1855       44830 :         status = rpc_api_pipe_recv(subreq, talloc_tos(), &pkt, NULL);
    1856       44830 :         TALLOC_FREE(subreq);
    1857       44830 :         if (tevent_req_nterror(req, status)) {
    1858           0 :                 DEBUG(3, ("rpc_pipe_bind: %s bind request returned %s\n",
    1859             :                           rpccli_pipe_txt(talloc_tos(), state->cli),
    1860             :                           nt_errstr(status)));
    1861           0 :                 return;
    1862             :         }
    1863             : 
    1864       44830 :         if (state->auth3) {
    1865          74 :                 tevent_req_done(req);
    1866          74 :                 return;
    1867             :         }
    1868             : 
    1869       44756 :         if (!check_bind_response(&pkt->u.bind_ack, &state->cli->transfer_syntax)) {
    1870           0 :                 DEBUG(2, ("rpc_pipe_bind: check_bind_response failed.\n"));
    1871           0 :                 tevent_req_nterror(req, NT_STATUS_BUFFER_TOO_SMALL);
    1872           0 :                 return;
    1873             :         }
    1874             : 
    1875       44756 :         if (pkt->ptype == DCERPC_PKT_BIND_ACK) {
    1876       44597 :                 if (pkt->pfc_flags & DCERPC_PFC_FLAG_SUPPORT_HEADER_SIGN) {
    1877         310 :                         if (pauth->client_hdr_signing) {
    1878         310 :                                 pauth->hdr_signing = true;
    1879             :                         }
    1880             :                 }
    1881             :         }
    1882             : 
    1883       44756 :         state->cli->max_xmit_frag = pkt->u.bind_ack.max_xmit_frag;
    1884             : 
    1885       44756 :         if (pauth->auth_type == DCERPC_AUTH_TYPE_NONE) {
    1886             :                 /* Bind complete. */
    1887       44121 :                 tevent_req_done(req);
    1888       44121 :                 return;
    1889             :         }
    1890             : 
    1891         635 :         if (pkt->auth_length == 0) {
    1892           0 :                 tevent_req_nterror(req, NT_STATUS_RPC_PROTOCOL_ERROR);
    1893           0 :                 return;
    1894             :         }
    1895             : 
    1896             :         /* get auth credentials */
    1897         635 :         status = dcerpc_pull_auth_trailer(pkt, talloc_tos(),
    1898         635 :                                           &pkt->u.bind_ack.auth_info,
    1899             :                                           &auth, NULL, true);
    1900         635 :         if (tevent_req_nterror(req, status)) {
    1901           0 :                 DEBUG(0, ("Failed to pull dcerpc auth: %s.\n",
    1902             :                           nt_errstr(status)));
    1903           0 :                 return;
    1904             :         }
    1905             : 
    1906         635 :         if (auth.auth_type != pauth->auth_type) {
    1907           0 :                 DBG_ERR("Auth type %u mismatch expected %u.\n",
    1908             :                         auth.auth_type, pauth->auth_type);
    1909           0 :                 tevent_req_nterror(req, NT_STATUS_RPC_PROTOCOL_ERROR);
    1910           0 :                 return;
    1911             :         }
    1912             : 
    1913         635 :         if (auth.auth_level != pauth->auth_level) {
    1914           0 :                 DBG_ERR("Auth level %u mismatch expected %u.\n",
    1915             :                         auth.auth_level, pauth->auth_level);
    1916           0 :                 tevent_req_nterror(req, NT_STATUS_RPC_PROTOCOL_ERROR);
    1917           0 :                 return;
    1918             :         }
    1919             : 
    1920         635 :         if (auth.auth_context_id != pauth->auth_context_id) {
    1921           0 :                 DBG_ERR("Auth context id %"PRIu32" mismatch "
    1922             :                         "expected %"PRIu32".\n",
    1923             :                         auth.auth_context_id,
    1924             :                         pauth->auth_context_id);
    1925           0 :                 tevent_req_nterror(req, NT_STATUS_RPC_PROTOCOL_ERROR);
    1926           0 :                 return;
    1927             :         }
    1928             : 
    1929             :         /*
    1930             :          * For authenticated binds we may need to do 3 or 4 leg binds.
    1931             :          */
    1932             : 
    1933         635 :         if (pauth->auth_type == DCERPC_AUTH_TYPE_NONE) {
    1934             :                 /* Bind complete. */
    1935           0 :                 tevent_req_done(req);
    1936           0 :                 return;
    1937             :         }
    1938             : 
    1939         635 :         gensec_security = pauth->auth_ctx;
    1940             : 
    1941         635 :         status = gensec_update(gensec_security, state,
    1942             :                                auth.credentials, &auth_token);
    1943         635 :         if (NT_STATUS_EQUAL(status,
    1944             :                             NT_STATUS_MORE_PROCESSING_REQUIRED)) {
    1945         159 :                 status = rpc_bind_next_send(req, state,
    1946             :                                             &auth_token);
    1947         476 :         } else if (NT_STATUS_IS_OK(status)) {
    1948         476 :                 if (pauth->hdr_signing) {
    1949         310 :                         gensec_want_feature(gensec_security,
    1950             :                                             GENSEC_FEATURE_SIGN_PKT_HEADER);
    1951             :                 }
    1952             : 
    1953         476 :                 if (auth_token.length == 0) {
    1954             :                         /* Bind complete. */
    1955         402 :                         tevent_req_done(req);
    1956         402 :                         return;
    1957             :                 }
    1958          74 :                 status = rpc_bind_finish_send(req, state,
    1959             :                                               &auth_token);
    1960             :         }
    1961             : 
    1962         233 :         if (!NT_STATUS_IS_OK(status)) {
    1963           0 :                 tevent_req_nterror(req, status);
    1964             :         }
    1965         233 :         return;
    1966             : }
    1967             : 
    1968         159 : static NTSTATUS rpc_bind_next_send(struct tevent_req *req,
    1969             :                                    struct rpc_pipe_bind_state *state,
    1970             :                                    DATA_BLOB *auth_token)
    1971             : {
    1972         159 :         struct pipe_auth_data *auth = state->cli->auth;
    1973           0 :         struct tevent_req *subreq;
    1974           0 :         NTSTATUS status;
    1975             : 
    1976             :         /* Now prepare the alter context pdu. */
    1977         159 :         data_blob_free(&state->rpc_out);
    1978             : 
    1979         159 :         status = create_rpc_alter_context(state, auth,
    1980             :                                           state->rpc_call_id,
    1981         159 :                                           &state->cli->abstract_syntax,
    1982         159 :                                           &state->cli->transfer_syntax,
    1983             :                                           auth_token,
    1984             :                                           &state->rpc_out);
    1985         159 :         if (!NT_STATUS_IS_OK(status)) {
    1986           0 :                 return status;
    1987             :         }
    1988             : 
    1989         159 :         subreq = rpc_api_pipe_send(state, state->ev, state->cli,
    1990             :                                    &state->rpc_out, DCERPC_PKT_ALTER_RESP,
    1991             :                                    state->rpc_call_id);
    1992         159 :         if (subreq == NULL) {
    1993           0 :                 return NT_STATUS_NO_MEMORY;
    1994             :         }
    1995         159 :         tevent_req_set_callback(subreq, rpc_pipe_bind_step_one_done, req);
    1996         159 :         return NT_STATUS_OK;
    1997             : }
    1998             : 
    1999          74 : static NTSTATUS rpc_bind_finish_send(struct tevent_req *req,
    2000             :                                      struct rpc_pipe_bind_state *state,
    2001             :                                      DATA_BLOB *auth_token)
    2002             : {
    2003          74 :         struct pipe_auth_data *auth = state->cli->auth;
    2004           0 :         struct tevent_req *subreq;
    2005           0 :         NTSTATUS status;
    2006             : 
    2007          74 :         state->auth3 = true;
    2008             : 
    2009             :         /* Now prepare the auth3 context pdu. */
    2010          74 :         data_blob_free(&state->rpc_out);
    2011             : 
    2012          74 :         status = create_rpc_bind_auth3(state, state->cli, auth,
    2013             :                                         state->rpc_call_id,
    2014             :                                         auth_token,
    2015             :                                         &state->rpc_out);
    2016          74 :         if (!NT_STATUS_IS_OK(status)) {
    2017           0 :                 return status;
    2018             :         }
    2019             : 
    2020          74 :         subreq = rpc_api_pipe_send(state, state->ev, state->cli,
    2021             :                                    &state->rpc_out, DCERPC_PKT_AUTH3,
    2022             :                                    state->rpc_call_id);
    2023          74 :         if (subreq == NULL) {
    2024           0 :                 return NT_STATUS_NO_MEMORY;
    2025             :         }
    2026          74 :         tevent_req_set_callback(subreq, rpc_pipe_bind_step_one_done, req);
    2027          74 :         return NT_STATUS_OK;
    2028             : }
    2029             : 
    2030       44597 : NTSTATUS rpc_pipe_bind_recv(struct tevent_req *req)
    2031             : {
    2032       44597 :         return tevent_req_simple_recv_ntstatus(req);
    2033             : }
    2034             : 
    2035       44597 : NTSTATUS rpc_pipe_bind(struct rpc_pipe_client *cli,
    2036             :                        struct pipe_auth_data *auth)
    2037             : {
    2038       44597 :         TALLOC_CTX *frame = talloc_stackframe();
    2039           0 :         struct tevent_context *ev;
    2040           0 :         struct tevent_req *req;
    2041       44597 :         NTSTATUS status = NT_STATUS_OK;
    2042             : 
    2043       44597 :         ev = samba_tevent_context_init(frame);
    2044       44597 :         if (ev == NULL) {
    2045           0 :                 status = NT_STATUS_NO_MEMORY;
    2046           0 :                 goto fail;
    2047             :         }
    2048             : 
    2049       44597 :         req = rpc_pipe_bind_send(frame, ev, cli, auth);
    2050       44597 :         if (req == NULL) {
    2051           0 :                 status = NT_STATUS_NO_MEMORY;
    2052           0 :                 goto fail;
    2053             :         }
    2054             : 
    2055       44597 :         if (!tevent_req_poll_ntstatus(req, ev, &status)) {
    2056           0 :                 goto fail;
    2057             :         }
    2058             : 
    2059       44597 :         status = rpc_pipe_bind_recv(req);
    2060       44597 :  fail:
    2061       44597 :         TALLOC_FREE(frame);
    2062       44597 :         return status;
    2063             : }
    2064             : 
    2065             : #define RPCCLI_DEFAULT_TIMEOUT 10000 /* 10 seconds. */
    2066             : 
    2067         709 : unsigned int rpccli_set_timeout(struct rpc_pipe_client *rpc_cli,
    2068             :                                 unsigned int timeout)
    2069             : {
    2070         709 :         if (rpc_cli == NULL) {
    2071           0 :                 return RPCCLI_DEFAULT_TIMEOUT;
    2072             :         }
    2073             : 
    2074         709 :         if (rpc_cli->binding_handle == NULL) {
    2075           0 :                 return RPCCLI_DEFAULT_TIMEOUT;
    2076             :         }
    2077             : 
    2078         709 :         return dcerpc_binding_handle_set_timeout(rpc_cli->binding_handle,
    2079             :                                                  timeout);
    2080             : }
    2081             : 
    2082         169 : bool rpccli_is_connected(struct rpc_pipe_client *rpc_cli)
    2083             : {
    2084         169 :         if (rpc_cli == NULL) {
    2085          84 :                 return false;
    2086             :         }
    2087             : 
    2088          85 :         if (rpc_cli->binding_handle == NULL) {
    2089           0 :                 return false;
    2090             :         }
    2091             : 
    2092          85 :         return dcerpc_binding_handle_is_connected(rpc_cli->binding_handle);
    2093             : }
    2094             : 
    2095             : struct rpccli_bh_state {
    2096             :         struct rpc_pipe_client *rpc_cli;
    2097             : };
    2098             : 
    2099      555211 : static bool rpccli_bh_is_connected(struct dcerpc_binding_handle *h)
    2100             : {
    2101      555211 :         struct rpccli_bh_state *hs = dcerpc_binding_handle_data(h,
    2102             :                                      struct rpccli_bh_state);
    2103      555211 :         struct rpc_cli_transport *transport = hs->rpc_cli->transport;
    2104             : 
    2105      555211 :         if (transport == NULL) {
    2106           0 :                 return false;
    2107             :         }
    2108             : 
    2109      555211 :         if (transport->is_connected == NULL) {
    2110           0 :                 return false;
    2111             :         }
    2112             : 
    2113      555211 :         return transport->is_connected(transport->priv);
    2114             : }
    2115             : 
    2116         725 : static uint32_t rpccli_bh_set_timeout(struct dcerpc_binding_handle *h,
    2117             :                                       uint32_t timeout)
    2118             : {
    2119         725 :         struct rpccli_bh_state *hs = dcerpc_binding_handle_data(h,
    2120             :                                      struct rpccli_bh_state);
    2121         725 :         struct rpc_cli_transport *transport = hs->rpc_cli->transport;
    2122           0 :         unsigned int old;
    2123             : 
    2124         725 :         if (transport == NULL) {
    2125           0 :                 return RPCCLI_DEFAULT_TIMEOUT;
    2126             :         }
    2127             : 
    2128         725 :         if (transport->set_timeout == NULL) {
    2129           0 :                 return RPCCLI_DEFAULT_TIMEOUT;
    2130             :         }
    2131             : 
    2132         725 :         old = transport->set_timeout(transport->priv, timeout);
    2133         725 :         if (old == 0) {
    2134           0 :                 return RPCCLI_DEFAULT_TIMEOUT;
    2135             :         }
    2136             : 
    2137         725 :         return old;
    2138             : }
    2139             : 
    2140         171 : static void rpccli_bh_auth_info(struct dcerpc_binding_handle *h,
    2141             :                                 enum dcerpc_AuthType *auth_type,
    2142             :                                 enum dcerpc_AuthLevel *auth_level)
    2143             : {
    2144         171 :         struct rpccli_bh_state *hs = dcerpc_binding_handle_data(h,
    2145             :                                      struct rpccli_bh_state);
    2146             : 
    2147         171 :         if (hs->rpc_cli == NULL) {
    2148           0 :                 return;
    2149             :         }
    2150             : 
    2151         171 :         if (hs->rpc_cli->auth == NULL) {
    2152           0 :                 return;
    2153             :         }
    2154             : 
    2155         171 :         *auth_type = hs->rpc_cli->auth->auth_type;
    2156         171 :         *auth_level = hs->rpc_cli->auth->auth_level;
    2157             : }
    2158             : 
    2159             : struct rpccli_bh_raw_call_state {
    2160             :         DATA_BLOB in_data;
    2161             :         DATA_BLOB out_data;
    2162             :         uint32_t out_flags;
    2163             : };
    2164             : 
    2165             : static void rpccli_bh_raw_call_done(struct tevent_req *subreq);
    2166             : 
    2167      555126 : static struct tevent_req *rpccli_bh_raw_call_send(TALLOC_CTX *mem_ctx,
    2168             :                                                   struct tevent_context *ev,
    2169             :                                                   struct dcerpc_binding_handle *h,
    2170             :                                                   const struct GUID *object,
    2171             :                                                   uint32_t opnum,
    2172             :                                                   uint32_t in_flags,
    2173             :                                                   const uint8_t *in_data,
    2174             :                                                   size_t in_length)
    2175             : {
    2176      555126 :         struct rpccli_bh_state *hs = dcerpc_binding_handle_data(h,
    2177             :                                      struct rpccli_bh_state);
    2178           0 :         struct tevent_req *req;
    2179           0 :         struct rpccli_bh_raw_call_state *state;
    2180           0 :         bool ok;
    2181           0 :         struct tevent_req *subreq;
    2182             : 
    2183      555126 :         req = tevent_req_create(mem_ctx, &state,
    2184             :                                 struct rpccli_bh_raw_call_state);
    2185      555126 :         if (req == NULL) {
    2186           0 :                 return NULL;
    2187             :         }
    2188      555126 :         state->in_data.data = discard_const_p(uint8_t, in_data);
    2189      555126 :         state->in_data.length = in_length;
    2190             : 
    2191      555126 :         ok = rpccli_bh_is_connected(h);
    2192      555126 :         if (!ok) {
    2193           0 :                 tevent_req_nterror(req, NT_STATUS_CONNECTION_DISCONNECTED);
    2194           0 :                 return tevent_req_post(req, ev);
    2195             :         }
    2196             : 
    2197      555126 :         subreq = rpc_api_pipe_req_send(state, ev, hs->rpc_cli,
    2198      555126 :                                        opnum, object, &state->in_data);
    2199      555126 :         if (tevent_req_nomem(subreq, req)) {
    2200           0 :                 return tevent_req_post(req, ev);
    2201             :         }
    2202      555126 :         tevent_req_set_callback(subreq, rpccli_bh_raw_call_done, req);
    2203             : 
    2204      555126 :         return req;
    2205             : }
    2206             : 
    2207      555126 : static void rpccli_bh_raw_call_done(struct tevent_req *subreq)
    2208             : {
    2209           0 :         struct tevent_req *req =
    2210      555126 :                 tevent_req_callback_data(subreq,
    2211             :                 struct tevent_req);
    2212           0 :         struct rpccli_bh_raw_call_state *state =
    2213      555126 :                 tevent_req_data(req,
    2214             :                 struct rpccli_bh_raw_call_state);
    2215           0 :         NTSTATUS status;
    2216             : 
    2217      555126 :         state->out_flags = 0;
    2218             : 
    2219             :         /* TODO: support bigendian responses */
    2220             : 
    2221      555126 :         status = rpc_api_pipe_req_recv(subreq, state, &state->out_data);
    2222      555126 :         TALLOC_FREE(subreq);
    2223      555126 :         if (tevent_req_nterror(req, status)) {
    2224         255 :                 return;
    2225             :         }
    2226             : 
    2227      554871 :         tevent_req_done(req);
    2228             : }
    2229             : 
    2230      555126 : static NTSTATUS rpccli_bh_raw_call_recv(struct tevent_req *req,
    2231             :                                         TALLOC_CTX *mem_ctx,
    2232             :                                         uint8_t **out_data,
    2233             :                                         size_t *out_length,
    2234             :                                         uint32_t *out_flags)
    2235             : {
    2236           0 :         struct rpccli_bh_raw_call_state *state =
    2237      555126 :                 tevent_req_data(req,
    2238             :                 struct rpccli_bh_raw_call_state);
    2239           0 :         NTSTATUS status;
    2240             : 
    2241      555126 :         if (tevent_req_is_nterror(req, &status)) {
    2242         255 :                 tevent_req_received(req);
    2243         255 :                 return status;
    2244             :         }
    2245             : 
    2246      554871 :         *out_data = talloc_move(mem_ctx, &state->out_data.data);
    2247      554871 :         *out_length = state->out_data.length;
    2248      554871 :         *out_flags = state->out_flags;
    2249      554871 :         tevent_req_received(req);
    2250      554871 :         return NT_STATUS_OK;
    2251             : }
    2252             : 
    2253             : struct rpccli_bh_disconnect_state {
    2254             :         uint8_t _dummy;
    2255             : };
    2256             : 
    2257           0 : static struct tevent_req *rpccli_bh_disconnect_send(TALLOC_CTX *mem_ctx,
    2258             :                                                 struct tevent_context *ev,
    2259             :                                                 struct dcerpc_binding_handle *h)
    2260             : {
    2261           0 :         struct rpccli_bh_state *hs = dcerpc_binding_handle_data(h,
    2262             :                                      struct rpccli_bh_state);
    2263           0 :         struct tevent_req *req;
    2264           0 :         struct rpccli_bh_disconnect_state *state;
    2265           0 :         bool ok;
    2266             : 
    2267           0 :         req = tevent_req_create(mem_ctx, &state,
    2268             :                                 struct rpccli_bh_disconnect_state);
    2269           0 :         if (req == NULL) {
    2270           0 :                 return NULL;
    2271             :         }
    2272             : 
    2273           0 :         ok = rpccli_bh_is_connected(h);
    2274           0 :         if (!ok) {
    2275           0 :                 tevent_req_nterror(req, NT_STATUS_CONNECTION_DISCONNECTED);
    2276           0 :                 return tevent_req_post(req, ev);
    2277             :         }
    2278             : 
    2279             :         /*
    2280             :          * TODO: do a real async disconnect ...
    2281             :          *
    2282             :          * For now we do it sync...
    2283             :          */
    2284           0 :         TALLOC_FREE(hs->rpc_cli->transport);
    2285           0 :         hs->rpc_cli = NULL;
    2286             : 
    2287           0 :         tevent_req_done(req);
    2288           0 :         return tevent_req_post(req, ev);
    2289             : }
    2290             : 
    2291           0 : static NTSTATUS rpccli_bh_disconnect_recv(struct tevent_req *req)
    2292             : {
    2293           0 :         return tevent_req_simple_recv_ntstatus(req);
    2294             : }
    2295             : 
    2296      555126 : static bool rpccli_bh_ref_alloc(struct dcerpc_binding_handle *h)
    2297             : {
    2298      555126 :         return true;
    2299             : }
    2300             : 
    2301     1109997 : static void rpccli_bh_do_ndr_print(struct dcerpc_binding_handle *h,
    2302             :                                    ndr_flags_type ndr_flags,
    2303             :                                    const void *_struct_ptr,
    2304             :                                    const struct ndr_interface_call *call)
    2305             : {
    2306     1109997 :         void *struct_ptr = discard_const(_struct_ptr);
    2307             : 
    2308     1109997 :         if (DEBUGLEVEL < 10) {
    2309     1109809 :                 return;
    2310             :         }
    2311             : 
    2312         188 :         if (ndr_flags & NDR_IN) {
    2313          94 :                 ndr_print_function_debug(call->ndr_print,
    2314          94 :                                          call->name,
    2315             :                                          ndr_flags,
    2316             :                                          struct_ptr);
    2317             :         }
    2318         188 :         if (ndr_flags & NDR_OUT) {
    2319          94 :                 ndr_print_function_debug(call->ndr_print,
    2320          94 :                                          call->name,
    2321             :                                          ndr_flags,
    2322             :                                          struct_ptr);
    2323             :         }
    2324             : }
    2325             : 
    2326             : static const struct dcerpc_binding_handle_ops rpccli_bh_ops = {
    2327             :         .name                   = "rpccli",
    2328             :         .is_connected           = rpccli_bh_is_connected,
    2329             :         .set_timeout            = rpccli_bh_set_timeout,
    2330             :         .auth_info              = rpccli_bh_auth_info,
    2331             :         .raw_call_send          = rpccli_bh_raw_call_send,
    2332             :         .raw_call_recv          = rpccli_bh_raw_call_recv,
    2333             :         .disconnect_send        = rpccli_bh_disconnect_send,
    2334             :         .disconnect_recv        = rpccli_bh_disconnect_recv,
    2335             : 
    2336             :         .ref_alloc              = rpccli_bh_ref_alloc,
    2337             :         .do_ndr_print           = rpccli_bh_do_ndr_print,
    2338             : };
    2339             : 
    2340             : /* initialise a rpc_pipe_client binding handle */
    2341       44597 : struct dcerpc_binding_handle *rpccli_bh_create(struct rpc_pipe_client *c,
    2342             :                                         const struct GUID *object,
    2343             :                                         const struct ndr_interface_table *table)
    2344             : {
    2345           0 :         struct dcerpc_binding_handle *h;
    2346           0 :         struct rpccli_bh_state *hs;
    2347             : 
    2348       44597 :         h = dcerpc_binding_handle_create(c,
    2349             :                                          &rpccli_bh_ops,
    2350             :                                          object,
    2351             :                                          table,
    2352             :                                          &hs,
    2353             :                                          struct rpccli_bh_state,
    2354             :                                          __location__);
    2355       44597 :         if (h == NULL) {
    2356           0 :                 return NULL;
    2357             :         }
    2358       44597 :         hs->rpc_cli = c;
    2359             : 
    2360       44597 :         return h;
    2361             : }
    2362             : 
    2363       44121 : NTSTATUS rpccli_anon_bind_data(TALLOC_CTX *mem_ctx,
    2364             :                                struct pipe_auth_data **presult)
    2365             : {
    2366           0 :         struct pipe_auth_data *result;
    2367           0 :         struct auth_generic_state *auth_generic_ctx;
    2368           0 :         NTSTATUS status;
    2369             : 
    2370       44121 :         result = talloc_zero(mem_ctx, struct pipe_auth_data);
    2371       44121 :         if (result == NULL) {
    2372           0 :                 return NT_STATUS_NO_MEMORY;
    2373             :         }
    2374             : 
    2375       44121 :         result->auth_type = DCERPC_AUTH_TYPE_NONE;
    2376       44121 :         result->auth_level = DCERPC_AUTH_LEVEL_NONE;
    2377       44121 :         result->auth_context_id = 0;
    2378             : 
    2379       44121 :         status = auth_generic_client_prepare(result,
    2380             :                                              &auth_generic_ctx);
    2381       44121 :         if (!NT_STATUS_IS_OK(status)) {
    2382           0 :                 DEBUG(1, ("Failed to create auth_generic context: %s\n",
    2383             :                           nt_errstr(status)));
    2384             :         }
    2385             : 
    2386       44121 :         status = auth_generic_set_username(auth_generic_ctx, "");
    2387       44121 :         if (!NT_STATUS_IS_OK(status)) {
    2388           0 :                 DEBUG(1, ("Failed to set username: %s\n",
    2389             :                           nt_errstr(status)));
    2390             :         }
    2391             : 
    2392       44121 :         status = auth_generic_set_domain(auth_generic_ctx, "");
    2393       44121 :         if (!NT_STATUS_IS_OK(status)) {
    2394           0 :                 DEBUG(1, ("Failed to set domain: %s\n",
    2395             :                           nt_errstr(status)));
    2396           0 :                 return status;
    2397             :         }
    2398             : 
    2399       44121 :         status = gensec_set_credentials(auth_generic_ctx->gensec_security,
    2400       44121 :                                         auth_generic_ctx->credentials);
    2401       44121 :         if (!NT_STATUS_IS_OK(status)) {
    2402           0 :                 DEBUG(1, ("Failed to set GENSEC credentials: %s\n",
    2403             :                           nt_errstr(status)));
    2404           0 :                 return status;
    2405             :         }
    2406       44121 :         talloc_unlink(auth_generic_ctx, auth_generic_ctx->credentials);
    2407       44121 :         auth_generic_ctx->credentials = NULL;
    2408             : 
    2409       44121 :         result->auth_ctx = talloc_move(result, &auth_generic_ctx->gensec_security);
    2410       44121 :         talloc_free(auth_generic_ctx);
    2411       44121 :         *presult = result;
    2412       44121 :         return NT_STATUS_OK;
    2413             : }
    2414             : 
    2415         136 : static NTSTATUS rpccli_generic_bind_data(TALLOC_CTX *mem_ctx,
    2416             :                                          enum dcerpc_AuthType auth_type,
    2417             :                                          enum dcerpc_AuthLevel auth_level,
    2418             :                                          const char *server,
    2419             :                                          const char *target_service,
    2420             :                                          const char *domain,
    2421             :                                          const char *username,
    2422             :                                          const char *password,
    2423             :                                          enum credentials_use_kerberos use_kerberos,
    2424             :                                          struct netlogon_creds_CredentialState *creds,
    2425             :                                          struct pipe_auth_data **presult)
    2426             : {
    2427           0 :         struct auth_generic_state *auth_generic_ctx;
    2428           0 :         struct pipe_auth_data *result;
    2429           0 :         NTSTATUS status;
    2430             : 
    2431         136 :         result = talloc_zero(mem_ctx, struct pipe_auth_data);
    2432         136 :         if (result == NULL) {
    2433           0 :                 return NT_STATUS_NO_MEMORY;
    2434             :         }
    2435             : 
    2436         136 :         result->auth_type = auth_type;
    2437         136 :         result->auth_level = auth_level;
    2438         136 :         result->auth_context_id = 1;
    2439             : 
    2440         136 :         status = auth_generic_client_prepare(result,
    2441             :                                              &auth_generic_ctx);
    2442         136 :         if (!NT_STATUS_IS_OK(status)) {
    2443           0 :                 goto fail;
    2444             :         }
    2445             : 
    2446         136 :         status = auth_generic_set_username(auth_generic_ctx, username);
    2447         136 :         if (!NT_STATUS_IS_OK(status)) {
    2448           0 :                 goto fail;
    2449             :         }
    2450             : 
    2451         136 :         status = auth_generic_set_domain(auth_generic_ctx, domain);
    2452         136 :         if (!NT_STATUS_IS_OK(status)) {
    2453           0 :                 goto fail;
    2454             :         }
    2455             : 
    2456         136 :         status = auth_generic_set_password(auth_generic_ctx, password);
    2457         136 :         if (!NT_STATUS_IS_OK(status)) {
    2458           0 :                 goto fail;
    2459             :         }
    2460             : 
    2461         136 :         status = gensec_set_target_service(auth_generic_ctx->gensec_security, target_service);
    2462         136 :         if (!NT_STATUS_IS_OK(status)) {
    2463           0 :                 goto fail;
    2464             :         }
    2465             : 
    2466         136 :         status = gensec_set_target_hostname(auth_generic_ctx->gensec_security, server);
    2467         136 :         if (!NT_STATUS_IS_OK(status)) {
    2468           0 :                 goto fail;
    2469             :         }
    2470             : 
    2471         136 :         cli_credentials_set_kerberos_state(auth_generic_ctx->credentials,
    2472             :                                            use_kerberos,
    2473             :                                            CRED_SPECIFIED);
    2474         136 :         cli_credentials_set_netlogon_creds(auth_generic_ctx->credentials, creds);
    2475             : 
    2476         136 :         status = auth_generic_client_start_by_authtype(auth_generic_ctx, auth_type, auth_level);
    2477         136 :         if (!NT_STATUS_IS_OK(status)) {
    2478           0 :                 goto fail;
    2479             :         }
    2480             : 
    2481         136 :         result->auth_ctx = talloc_move(result, &auth_generic_ctx->gensec_security);
    2482         136 :         talloc_free(auth_generic_ctx);
    2483         136 :         *presult = result;
    2484         136 :         return NT_STATUS_OK;
    2485             : 
    2486           0 :  fail:
    2487           0 :         TALLOC_FREE(result);
    2488           0 :         return status;
    2489             : }
    2490             : 
    2491             : /* This routine steals the creds pointer that is passed in */
    2492         340 : static NTSTATUS rpccli_generic_bind_data_from_creds(TALLOC_CTX *mem_ctx,
    2493             :                                                     enum dcerpc_AuthType auth_type,
    2494             :                                                     enum dcerpc_AuthLevel auth_level,
    2495             :                                                     const char *server,
    2496             :                                                     const char *target_service,
    2497             :                                                     struct cli_credentials *creds,
    2498             :                                                     struct pipe_auth_data **presult)
    2499             : {
    2500           0 :         struct auth_generic_state *auth_generic_ctx;
    2501           0 :         struct pipe_auth_data *result;
    2502           0 :         NTSTATUS status;
    2503             : 
    2504         340 :         result = talloc_zero(mem_ctx, struct pipe_auth_data);
    2505         340 :         if (result == NULL) {
    2506           0 :                 return NT_STATUS_NO_MEMORY;
    2507             :         }
    2508             : 
    2509         340 :         result->auth_type = auth_type;
    2510         340 :         result->auth_level = auth_level;
    2511         340 :         result->auth_context_id = 1;
    2512             : 
    2513         340 :         status = auth_generic_client_prepare(result,
    2514             :                                              &auth_generic_ctx);
    2515         340 :         if (!NT_STATUS_IS_OK(status)) {
    2516           0 :                 goto fail;
    2517             :         }
    2518             : 
    2519         340 :         status = auth_generic_set_creds(auth_generic_ctx, creds);
    2520         340 :         if (!NT_STATUS_IS_OK(status)) {
    2521           0 :                 goto fail;
    2522             :         }
    2523             : 
    2524         340 :         status = gensec_set_target_service(auth_generic_ctx->gensec_security, target_service);
    2525         340 :         if (!NT_STATUS_IS_OK(status)) {
    2526           0 :                 goto fail;
    2527             :         }
    2528             : 
    2529         340 :         status = gensec_set_target_hostname(auth_generic_ctx->gensec_security, server);
    2530         340 :         if (!NT_STATUS_IS_OK(status)) {
    2531           0 :                 goto fail;
    2532             :         }
    2533             : 
    2534         340 :         status = auth_generic_client_start_by_authtype(auth_generic_ctx, auth_type, auth_level);
    2535         340 :         if (!NT_STATUS_IS_OK(status)) {
    2536           0 :                 goto fail;
    2537             :         }
    2538             : 
    2539         340 :         result->auth_ctx = talloc_move(result, &auth_generic_ctx->gensec_security);
    2540         340 :         talloc_free(auth_generic_ctx);
    2541         340 :         *presult = result;
    2542         340 :         return NT_STATUS_OK;
    2543             : 
    2544           0 :  fail:
    2545           0 :         TALLOC_FREE(result);
    2546           0 :         return status;
    2547             : }
    2548             : 
    2549         136 : NTSTATUS rpccli_ncalrpc_bind_data(TALLOC_CTX *mem_ctx,
    2550             :                                   struct pipe_auth_data **presult)
    2551             : {
    2552         136 :         return rpccli_generic_bind_data(mem_ctx,
    2553             :                                         DCERPC_AUTH_TYPE_NCALRPC_AS_SYSTEM,
    2554             :                                         DCERPC_AUTH_LEVEL_CONNECT,
    2555             :                                         NULL, /* server */
    2556             :                                         "host", /* target_service */
    2557             :                                         NAME_NT_AUTHORITY, /* domain */
    2558             :                                         "SYSTEM",
    2559             :                                         NULL, /* password */
    2560             :                                         CRED_USE_KERBEROS_DISABLED,
    2561             :                                         NULL, /* netlogon_creds_CredentialState */
    2562             :                                         presult);
    2563             : }
    2564             : 
    2565             : /**
    2566             :  * Create an rpc pipe client struct, connecting to a tcp port.
    2567             :  */
    2568         100 : static NTSTATUS rpc_pipe_open_tcp_port(TALLOC_CTX *mem_ctx, const char *host,
    2569             :                                        const struct sockaddr_storage *ss_addr,
    2570             :                                        uint16_t port,
    2571             :                                        const struct ndr_interface_table *table,
    2572             :                                        struct rpc_pipe_client **presult)
    2573             : {
    2574           0 :         struct rpc_pipe_client *result;
    2575           0 :         struct sockaddr_storage addr;
    2576           0 :         NTSTATUS status;
    2577           0 :         int fd;
    2578             : 
    2579         100 :         result = talloc_zero(mem_ctx, struct rpc_pipe_client);
    2580         100 :         if (result == NULL) {
    2581           0 :                 return NT_STATUS_NO_MEMORY;
    2582             :         }
    2583             : 
    2584         100 :         result->abstract_syntax = table->syntax_id;
    2585         100 :         result->transfer_syntax = ndr_transfer_syntax_ndr;
    2586             : 
    2587         100 :         result->desthost = talloc_strdup(result, host);
    2588         100 :         if (result->desthost == NULL) {
    2589           0 :                 status = NT_STATUS_NO_MEMORY;
    2590           0 :                 goto fail;
    2591             :         }
    2592             : 
    2593         100 :         result->srv_name_slash = talloc_asprintf_strupper_m(
    2594             :                 result, "\\\\%s", result->desthost);
    2595         100 :         if (result->srv_name_slash == NULL) {
    2596           0 :                 status = NT_STATUS_NO_MEMORY;
    2597           0 :                 goto fail;
    2598             :         }
    2599             : 
    2600         100 :         result->max_xmit_frag = RPC_MAX_PDU_FRAG_LEN;
    2601             : 
    2602         100 :         if (ss_addr == NULL) {
    2603           0 :                 if (!resolve_name(host, &addr, NBT_NAME_SERVER, false)) {
    2604           0 :                         status = NT_STATUS_NOT_FOUND;
    2605           0 :                         goto fail;
    2606             :                 }
    2607             :         } else {
    2608         100 :                 addr = *ss_addr;
    2609             :         }
    2610             : 
    2611         100 :         status = open_socket_out(&addr, port, 60*1000, &fd);
    2612         100 :         if (!NT_STATUS_IS_OK(status)) {
    2613           0 :                 goto fail;
    2614             :         }
    2615         100 :         set_socket_options(fd, lp_socket_options());
    2616             : 
    2617         100 :         status = rpc_transport_sock_init(result, fd, &result->transport);
    2618         100 :         if (!NT_STATUS_IS_OK(status)) {
    2619           0 :                 close(fd);
    2620           0 :                 goto fail;
    2621             :         }
    2622             : 
    2623         100 :         result->transport->transport = NCACN_IP_TCP;
    2624             : 
    2625         100 :         result->binding_handle = rpccli_bh_create(result, NULL, table);
    2626         100 :         if (result->binding_handle == NULL) {
    2627           0 :                 TALLOC_FREE(result);
    2628           0 :                 return NT_STATUS_NO_MEMORY;
    2629             :         }
    2630             : 
    2631         100 :         *presult = result;
    2632         100 :         return NT_STATUS_OK;
    2633             : 
    2634           0 :  fail:
    2635           0 :         TALLOC_FREE(result);
    2636           0 :         return status;
    2637             : }
    2638             : 
    2639           2 : static NTSTATUS rpccli_epm_map_binding(
    2640             :         struct dcerpc_binding_handle *epm_connection,
    2641             :         struct dcerpc_binding *binding,
    2642             :         TALLOC_CTX *mem_ctx,
    2643             :         char **pendpoint)
    2644             : {
    2645           2 :         TALLOC_CTX *frame = talloc_stackframe();
    2646           0 :         enum dcerpc_transport_t transport =
    2647           2 :                 dcerpc_binding_get_transport(binding);
    2648           0 :         enum dcerpc_transport_t res_transport;
    2649           2 :         struct dcerpc_binding *res_binding = NULL;
    2650           2 :         struct epm_twr_t *map_tower = NULL;
    2651           2 :         struct epm_twr_p_t res_towers = { .twr = NULL };
    2652           2 :         struct policy_handle *entry_handle = NULL;
    2653           2 :         uint32_t num_towers = 0;
    2654           2 :         const uint32_t max_towers = 1;
    2655           2 :         const char *endpoint = NULL;
    2656           2 :         char *tmp = NULL;
    2657           0 :         uint32_t result;
    2658           0 :         NTSTATUS status;
    2659             : 
    2660           2 :         map_tower = talloc_zero(frame, struct epm_twr_t);
    2661           2 :         if (map_tower == NULL) {
    2662           0 :                 goto nomem;
    2663             :         }
    2664             : 
    2665           2 :         status = dcerpc_binding_build_tower(
    2666             :                 frame, binding, &(map_tower->tower));
    2667           2 :         if (!NT_STATUS_IS_OK(status)) {
    2668           0 :                 DBG_DEBUG("dcerpc_binding_build_tower failed: %s\n",
    2669             :                           nt_errstr(status));
    2670           0 :                 goto done;
    2671             :         }
    2672             : 
    2673           2 :         res_towers.twr = talloc_array(frame, struct epm_twr_t, max_towers);
    2674           2 :         if (res_towers.twr == NULL) {
    2675           0 :                 goto nomem;
    2676             :         }
    2677             : 
    2678           2 :         entry_handle = talloc_zero(frame, struct policy_handle);
    2679           2 :         if (entry_handle == NULL) {
    2680           0 :                 goto nomem;
    2681             :         }
    2682             : 
    2683           2 :         status = dcerpc_epm_Map(
    2684             :                 epm_connection,
    2685             :                 frame,
    2686             :                 NULL,
    2687             :                 map_tower,
    2688             :                 entry_handle,
    2689             :                 max_towers,
    2690             :                 &num_towers,
    2691             :                 &res_towers,
    2692             :                 &result);
    2693             : 
    2694           2 :         if (!NT_STATUS_IS_OK(status)) {
    2695           0 :                 DBG_DEBUG("dcerpc_epm_Map failed: %s\n", nt_errstr(status));
    2696           0 :                 goto done;
    2697             :         }
    2698             : 
    2699           2 :         if (result != EPMAPPER_STATUS_OK) {
    2700           0 :                 DBG_DEBUG("dcerpc_epm_Map returned %"PRIu32"\n", result);
    2701           0 :                 status = NT_STATUS_NOT_FOUND;
    2702           0 :                 goto done;
    2703             :         }
    2704             : 
    2705           2 :         if (num_towers != 1) {
    2706           0 :                 DBG_DEBUG("dcerpc_epm_Map returned %"PRIu32" towers\n",
    2707             :                           num_towers);
    2708           0 :                 status = NT_STATUS_INVALID_NETWORK_RESPONSE;
    2709           0 :                 goto done;
    2710             :         }
    2711             : 
    2712           2 :         status = dcerpc_binding_from_tower(
    2713           2 :                 frame, &(res_towers.twr->tower), &res_binding);
    2714           2 :         if (!NT_STATUS_IS_OK(status)) {
    2715           0 :                 DBG_DEBUG("dcerpc_binding_from_tower failed: %s\n",
    2716             :                           nt_errstr(status));
    2717           0 :                 goto done;
    2718             :         }
    2719             : 
    2720           2 :         res_transport = dcerpc_binding_get_transport(res_binding);
    2721           2 :         if (res_transport != transport) {
    2722           0 :                 DBG_DEBUG("dcerpc_epm_Map returned transport %d, "
    2723             :                           "expected %d\n",
    2724             :                           (int)res_transport,
    2725             :                           (int)transport);
    2726           0 :                 status = NT_STATUS_INVALID_NETWORK_RESPONSE;
    2727           0 :                 goto done;
    2728             :         }
    2729             : 
    2730           2 :         endpoint = dcerpc_binding_get_string_option(res_binding, "endpoint");
    2731           2 :         if (endpoint == NULL) {
    2732           0 :                 DBG_DEBUG("dcerpc_epm_Map returned no endpoint\n");
    2733           0 :                 status = NT_STATUS_INVALID_NETWORK_RESPONSE;
    2734           0 :                 goto done;
    2735             :         }
    2736             : 
    2737           2 :         tmp = talloc_strdup(mem_ctx, endpoint);
    2738           2 :         if (tmp == NULL) {
    2739           0 :                 goto nomem;
    2740             :         }
    2741           2 :         *pendpoint = tmp;
    2742             : 
    2743           2 :         status = NT_STATUS_OK;
    2744           2 :         goto done;
    2745             : 
    2746           0 : nomem:
    2747           0 :         status = NT_STATUS_NO_MEMORY;
    2748           2 : done:
    2749           2 :         TALLOC_FREE(frame);
    2750           2 :         return status;
    2751             : }
    2752             : 
    2753           2 : static NTSTATUS rpccli_epm_map_interface(
    2754             :         struct dcerpc_binding_handle *epm_connection,
    2755             :         enum dcerpc_transport_t transport,
    2756             :         const struct ndr_syntax_id *iface,
    2757             :         TALLOC_CTX *mem_ctx,
    2758             :         char **pendpoint)
    2759             : {
    2760           2 :         struct dcerpc_binding *binding = NULL;
    2761           2 :         char *endpoint = NULL;
    2762           0 :         NTSTATUS status;
    2763             : 
    2764           2 :         status = dcerpc_parse_binding(mem_ctx, "", &binding);
    2765           2 :         if (!NT_STATUS_IS_OK(status)) {
    2766           0 :                 DBG_DEBUG("dcerpc_parse_binding failed: %s\n",
    2767             :                           nt_errstr(status));
    2768           0 :                 goto done;
    2769             :         }
    2770             : 
    2771           2 :         status = dcerpc_binding_set_transport(binding, transport);
    2772           2 :         if (!NT_STATUS_IS_OK(status)) {
    2773           0 :                 DBG_DEBUG("dcerpc_binding_set_transport failed: %s\n",
    2774             :                           nt_errstr(status));
    2775           0 :                 goto done;
    2776             :         }
    2777             : 
    2778           2 :         status = dcerpc_binding_set_abstract_syntax(binding, iface);
    2779           2 :         if (!NT_STATUS_IS_OK(status)) {
    2780           0 :                 DBG_DEBUG("dcerpc_binding_set_abstract_syntax failed: %s\n",
    2781             :                           nt_errstr(status));
    2782           0 :                 goto done;
    2783             :         }
    2784             : 
    2785           2 :         status = rpccli_epm_map_binding(
    2786             :                 epm_connection, binding, mem_ctx, &endpoint);
    2787           2 :         if (!NT_STATUS_IS_OK(status)) {
    2788           0 :                 DBG_DEBUG("rpccli_epm_map_binding failed: %s\n",
    2789             :                           nt_errstr(status));
    2790           0 :                 goto done;
    2791             :         }
    2792           2 :         *pendpoint = endpoint;
    2793             : 
    2794           2 : done:
    2795           2 :         TALLOC_FREE(binding);
    2796           2 :         return status;
    2797             : }
    2798             : 
    2799             : /**
    2800             :  * Determine the tcp port on which a dcerpc interface is listening
    2801             :  * for the ncacn_ip_tcp transport via the endpoint mapper of the
    2802             :  * target host.
    2803             :  */
    2804          98 : static NTSTATUS rpc_pipe_get_tcp_port(const char *host,
    2805             :                                       const struct sockaddr_storage *addr,
    2806             :                                       const struct ndr_interface_table *table,
    2807             :                                       uint16_t *pport)
    2808             : {
    2809           0 :         NTSTATUS status;
    2810          98 :         struct rpc_pipe_client *epm_pipe = NULL;
    2811          98 :         struct pipe_auth_data *auth = NULL;
    2812          98 :         char *endpoint = NULL;
    2813          98 :         TALLOC_CTX *tmp_ctx = talloc_stackframe();
    2814             : 
    2815          98 :         if (pport == NULL) {
    2816           0 :                 status = NT_STATUS_INVALID_PARAMETER;
    2817           0 :                 goto done;
    2818             :         }
    2819             : 
    2820          98 :         if (ndr_syntax_id_equal(&table->syntax_id,
    2821             :                                 &ndr_table_epmapper.syntax_id)) {
    2822          96 :                 *pport = 135;
    2823          96 :                 status = NT_STATUS_OK;
    2824          96 :                 goto done;
    2825             :         }
    2826             : 
    2827             :         /* open the connection to the endpoint mapper */
    2828           2 :         status = rpc_pipe_open_tcp_port(tmp_ctx, host, addr, 135,
    2829             :                                         &ndr_table_epmapper,
    2830             :                                         &epm_pipe);
    2831             : 
    2832           2 :         if (!NT_STATUS_IS_OK(status)) {
    2833           0 :                 goto done;
    2834             :         }
    2835             : 
    2836           2 :         status = rpccli_anon_bind_data(tmp_ctx, &auth);
    2837           2 :         if (!NT_STATUS_IS_OK(status)) {
    2838           0 :                 goto done;
    2839             :         }
    2840             : 
    2841           2 :         status = rpc_pipe_bind(epm_pipe, auth);
    2842           2 :         if (!NT_STATUS_IS_OK(status)) {
    2843           0 :                 goto done;
    2844             :         }
    2845             : 
    2846           2 :         status = rpccli_epm_map_interface(
    2847           2 :                 epm_pipe->binding_handle,
    2848             :                 NCACN_IP_TCP,
    2849             :                 &table->syntax_id,
    2850             :                 tmp_ctx,
    2851             :                 &endpoint);
    2852           2 :         if (!NT_STATUS_IS_OK(status)) {
    2853           0 :                 DBG_DEBUG("rpccli_epm_map_interface failed: %s\n",
    2854             :                           nt_errstr(status));
    2855           0 :                 goto done;
    2856             :         }
    2857             : 
    2858           2 :         *pport = (uint16_t)atoi(endpoint);
    2859             : 
    2860          98 : done:
    2861          98 :         TALLOC_FREE(tmp_ctx);
    2862          98 :         return status;
    2863             : }
    2864             : 
    2865             : /**
    2866             :  * Create a rpc pipe client struct, connecting to a host via tcp.
    2867             :  * The port is determined by asking the endpoint mapper on the given
    2868             :  * host.
    2869             :  */
    2870          98 : static NTSTATUS rpc_pipe_open_tcp(
    2871             :         TALLOC_CTX *mem_ctx,
    2872             :         const char *host,
    2873             :         const struct sockaddr_storage *addr,
    2874             :         const struct ndr_interface_table *table,
    2875             :         struct rpc_pipe_client **presult)
    2876             : {
    2877           0 :         NTSTATUS status;
    2878          98 :         uint16_t port = 0;
    2879             : 
    2880          98 :         status = rpc_pipe_get_tcp_port(host, addr, table, &port);
    2881          98 :         if (!NT_STATUS_IS_OK(status)) {
    2882           0 :                 return status;
    2883             :         }
    2884             : 
    2885          98 :         return rpc_pipe_open_tcp_port(mem_ctx, host, addr, port,
    2886             :                                       table, presult);
    2887             : }
    2888             : 
    2889         152 : static NTSTATUS rpc_pipe_get_ncalrpc_name(
    2890             :         const struct ndr_syntax_id *iface,
    2891             :         TALLOC_CTX *mem_ctx,
    2892             :         char **psocket_name)
    2893             : {
    2894         152 :         TALLOC_CTX *frame = talloc_stackframe();
    2895         152 :         struct rpc_pipe_client *epm_pipe = NULL;
    2896         152 :         struct pipe_auth_data *auth = NULL;
    2897         152 :         NTSTATUS status = NT_STATUS_OK;
    2898           0 :         bool is_epm;
    2899             : 
    2900         152 :         is_epm = ndr_syntax_id_equal(iface, &ndr_table_epmapper.syntax_id);
    2901         152 :         if (is_epm) {
    2902         152 :                 char *endpoint = talloc_strdup(mem_ctx, "EPMAPPER");
    2903         152 :                 if (endpoint == NULL) {
    2904           0 :                         status = NT_STATUS_NO_MEMORY;
    2905           0 :                         goto done;
    2906             :                 }
    2907         152 :                 *psocket_name = endpoint;
    2908         152 :                 goto done;
    2909             :         }
    2910             : 
    2911           0 :         status = rpc_pipe_open_ncalrpc(
    2912             :                 frame, &ndr_table_epmapper, &epm_pipe);
    2913           0 :         if (!NT_STATUS_IS_OK(status)) {
    2914           0 :                 DBG_DEBUG("rpc_pipe_open_ncalrpc failed: %s\n",
    2915             :                           nt_errstr(status));
    2916           0 :                 goto done;
    2917             :         }
    2918             : 
    2919           0 :         status = rpccli_anon_bind_data(epm_pipe, &auth);
    2920           0 :         if (!NT_STATUS_IS_OK(status)) {
    2921           0 :                 DBG_DEBUG("rpccli_anon_bind_data failed: %s\n",
    2922             :                           nt_errstr(status));
    2923           0 :                 goto done;
    2924             :         }
    2925             : 
    2926           0 :         status = rpc_pipe_bind(epm_pipe, auth);
    2927           0 :         if (!NT_STATUS_IS_OK(status)) {
    2928           0 :                 DBG_DEBUG("rpc_pipe_bind failed: %s\n", nt_errstr(status));
    2929           0 :                 goto done;
    2930             :         }
    2931             : 
    2932           0 :         status = rpccli_epm_map_interface(
    2933           0 :                 epm_pipe->binding_handle,
    2934             :                 NCALRPC,
    2935             :                 iface,
    2936             :                 mem_ctx,
    2937             :                 psocket_name);
    2938           0 :         if (!NT_STATUS_IS_OK(status)) {
    2939           0 :                 DBG_DEBUG("rpccli_epm_map_interface failed: %s\n",
    2940             :                           nt_errstr(status));
    2941             :         }
    2942             : 
    2943           0 : done:
    2944         152 :         TALLOC_FREE(frame);
    2945         152 :         return status;
    2946             : }
    2947             : 
    2948             : /********************************************************************
    2949             :  Create a rpc pipe client struct, connecting to a unix domain socket
    2950             :  ********************************************************************/
    2951         152 : NTSTATUS rpc_pipe_open_ncalrpc(TALLOC_CTX *mem_ctx,
    2952             :                                const struct ndr_interface_table *table,
    2953             :                                struct rpc_pipe_client **presult)
    2954             : {
    2955         152 :         char *socket_name = NULL;
    2956           0 :         struct rpc_pipe_client *result;
    2957         152 :         struct sockaddr_un addr = { .sun_family = AF_UNIX };
    2958         152 :         socklen_t salen = sizeof(addr);
    2959           0 :         int pathlen;
    2960           0 :         NTSTATUS status;
    2961         152 :         int fd = -1;
    2962             : 
    2963         152 :         result = talloc_zero(mem_ctx, struct rpc_pipe_client);
    2964         152 :         if (result == NULL) {
    2965           0 :                 return NT_STATUS_NO_MEMORY;
    2966             :         }
    2967             : 
    2968         152 :         status = rpc_pipe_get_ncalrpc_name(
    2969             :                 &table->syntax_id, result, &socket_name);
    2970         152 :         if (!NT_STATUS_IS_OK(status)) {
    2971           0 :                 DBG_DEBUG("rpc_pipe_get_ncalrpc_name failed: %s\n",
    2972             :                           nt_errstr(status));
    2973           0 :                 goto fail;
    2974             :         }
    2975             : 
    2976         152 :         pathlen = snprintf(
    2977             :                 addr.sun_path,
    2978             :                 sizeof(addr.sun_path),
    2979             :                 "%s/%s",
    2980             :                 lp_ncalrpc_dir(),
    2981             :                 socket_name);
    2982         152 :         if ((pathlen < 0) || ((size_t)pathlen >= sizeof(addr.sun_path))) {
    2983           0 :                 DBG_DEBUG("socket_path for %s too long\n", socket_name);
    2984           0 :                 status = NT_STATUS_NAME_TOO_LONG;
    2985           0 :                 goto fail;
    2986             :         }
    2987         152 :         TALLOC_FREE(socket_name);
    2988             : 
    2989         152 :         result->abstract_syntax = table->syntax_id;
    2990         152 :         result->transfer_syntax = ndr_transfer_syntax_ndr;
    2991             : 
    2992         152 :         result->desthost = get_myname(result);
    2993         152 :         if (result->desthost == NULL) {
    2994           0 :                 status = NT_STATUS_NO_MEMORY;
    2995           0 :                 goto fail;
    2996             :         }
    2997             : 
    2998         152 :         result->srv_name_slash = talloc_asprintf_strupper_m(
    2999             :                 result, "\\\\%s", result->desthost);
    3000         152 :         if (result->srv_name_slash == NULL) {
    3001           0 :                 status = NT_STATUS_NO_MEMORY;
    3002           0 :                 goto fail;
    3003             :         }
    3004             : 
    3005         152 :         result->max_xmit_frag = RPC_MAX_PDU_FRAG_LEN;
    3006             : 
    3007         152 :         fd = socket(AF_UNIX, SOCK_STREAM, 0);
    3008         152 :         if (fd == -1) {
    3009           0 :                 status = map_nt_error_from_unix(errno);
    3010           0 :                 goto fail;
    3011             :         }
    3012             : 
    3013         152 :         if (connect(fd, (struct sockaddr *)(void *)&addr, salen) == -1) {
    3014          16 :                 DBG_WARNING("connect(%s) failed: %s\n",
    3015             :                             addr.sun_path,
    3016             :                             strerror(errno));
    3017          16 :                 status = map_nt_error_from_unix(errno);
    3018          16 :                 goto fail;
    3019             :         }
    3020             : 
    3021         136 :         status = rpc_transport_sock_init(result, fd, &result->transport);
    3022         136 :         if (!NT_STATUS_IS_OK(status)) {
    3023           0 :                 goto fail;
    3024             :         }
    3025         136 :         fd = -1;
    3026             : 
    3027         136 :         result->transport->transport = NCALRPC;
    3028             : 
    3029         136 :         result->binding_handle = rpccli_bh_create(result, NULL, table);
    3030         136 :         if (result->binding_handle == NULL) {
    3031           0 :                 status = NT_STATUS_NO_MEMORY;
    3032           0 :                 goto fail;
    3033             :         }
    3034             : 
    3035         136 :         *presult = result;
    3036         136 :         return NT_STATUS_OK;
    3037             : 
    3038          16 :  fail:
    3039          16 :         if (fd != -1) {
    3040          16 :                 close(fd);
    3041             :         }
    3042          16 :         TALLOC_FREE(result);
    3043          16 :         return status;
    3044             : }
    3045             : 
    3046       30721 : NTSTATUS rpc_pipe_open_local_np(
    3047             :         TALLOC_CTX *mem_ctx,
    3048             :         const struct ndr_interface_table *table,
    3049             :         const char *remote_client_name,
    3050             :         const struct tsocket_address *remote_client_addr,
    3051             :         const char *local_server_name,
    3052             :         const struct tsocket_address *local_server_addr,
    3053             :         const struct auth_session_info *session_info,
    3054             :         struct rpc_pipe_client **presult)
    3055             : {
    3056       30721 :         struct rpc_pipe_client *result = NULL;
    3057       30721 :         struct pipe_auth_data *auth = NULL;
    3058       30721 :         const char *pipe_name = NULL;
    3059       30721 :         struct tstream_context *npa_stream = NULL;
    3060       30721 :         NTSTATUS status = NT_STATUS_NO_MEMORY;
    3061           0 :         int ret;
    3062             : 
    3063       30721 :         result = talloc_zero(mem_ctx, struct rpc_pipe_client);
    3064       30721 :         if (result == NULL) {
    3065           0 :                 goto fail;
    3066             :         }
    3067       30721 :         result->abstract_syntax = table->syntax_id;
    3068       30721 :         result->transfer_syntax = ndr_transfer_syntax_ndr;
    3069       30721 :         result->max_xmit_frag = RPC_MAX_PDU_FRAG_LEN;
    3070             : 
    3071       30721 :         pipe_name = dcerpc_default_transport_endpoint(
    3072             :                 result, NCACN_NP, table);
    3073       30721 :         if (pipe_name == NULL) {
    3074           0 :                 DBG_DEBUG("dcerpc_default_transport_endpoint failed\n");
    3075           0 :                 status = NT_STATUS_OBJECT_NAME_NOT_FOUND;
    3076           0 :                 goto fail;
    3077             :         }
    3078             : 
    3079       30721 :         if (local_server_name == NULL) {
    3080       30721 :                 result->desthost = get_myname(result);
    3081             :         } else {
    3082           0 :                 result->desthost = talloc_strdup(result, local_server_name);
    3083             :         }
    3084       30721 :         if (result->desthost == NULL) {
    3085           0 :                 goto fail;
    3086             :         }
    3087       30721 :         result->srv_name_slash = talloc_asprintf_strupper_m(
    3088             :                 result, "\\\\%s", result->desthost);
    3089       30721 :         if (result->srv_name_slash == NULL) {
    3090           0 :                 goto fail;
    3091             :         }
    3092             : 
    3093       30721 :         ret = local_np_connect(
    3094             :                 pipe_name,
    3095             :                 NCALRPC,
    3096             :                 remote_client_name,
    3097             :                 remote_client_addr,
    3098             :                 local_server_name,
    3099             :                 local_server_addr,
    3100             :                 session_info,
    3101             :                 true,
    3102             :                 result,
    3103             :                 &npa_stream);
    3104       30721 :         if (ret != 0) {
    3105           0 :                 DBG_DEBUG("local_np_connect for %s and "
    3106             :                           "user %s\\%s failed: %s\n",
    3107             :                           pipe_name,
    3108             :                           session_info->info->domain_name,
    3109             :                           session_info->info->account_name,
    3110             :                           strerror(ret));
    3111           0 :                 status = map_nt_error_from_unix(ret);
    3112           0 :                 goto fail;
    3113             :         }
    3114             : 
    3115       30721 :         status = rpc_transport_tstream_init(
    3116             :                 result, &npa_stream, &result->transport);
    3117       30721 :         if (!NT_STATUS_IS_OK(status)) {
    3118           0 :                 DBG_DEBUG("rpc_transport_tstream_init failed: %s\n",
    3119             :                           nt_errstr(status));
    3120           0 :                 goto fail;
    3121             :         }
    3122             : 
    3123       30721 :         result->binding_handle = rpccli_bh_create(result, NULL, table);
    3124       30721 :         if (result->binding_handle == NULL) {
    3125           0 :                 status = NT_STATUS_NO_MEMORY;
    3126           0 :                 DBG_DEBUG("Failed to create binding handle.\n");
    3127           0 :                 goto fail;
    3128             :         }
    3129             : 
    3130       30721 :         status = rpccli_anon_bind_data(result, &auth);
    3131       30721 :         if (!NT_STATUS_IS_OK(status)) {
    3132           0 :                 DBG_DEBUG("rpccli_anon_bind_data failed: %s\n",
    3133             :                           nt_errstr(status));
    3134           0 :                 goto fail;
    3135             :         }
    3136             : 
    3137       30721 :         status = rpc_pipe_bind(result, auth);
    3138       30721 :         if (!NT_STATUS_IS_OK(status)) {
    3139           0 :                 DBG_DEBUG("rpc_pipe_bind failed: %s\n", nt_errstr(status));
    3140           0 :                 goto fail;
    3141             :         }
    3142             : 
    3143       30721 :         *presult = result;
    3144       30721 :         return NT_STATUS_OK;
    3145             : 
    3146           0 : fail:
    3147           0 :         TALLOC_FREE(result);
    3148           0 :         return status;
    3149             : }
    3150             : 
    3151             : struct rpc_pipe_client_np_ref {
    3152             :         struct cli_state *cli;
    3153             :         struct rpc_pipe_client *pipe;
    3154             : };
    3155             : 
    3156       13614 : static int rpc_pipe_client_np_ref_destructor(struct rpc_pipe_client_np_ref *np_ref)
    3157             : {
    3158       13614 :         DLIST_REMOVE(np_ref->cli->pipe_list, np_ref->pipe);
    3159       13614 :         return 0;
    3160             : }
    3161             : 
    3162             : /****************************************************************************
    3163             :  Open a named pipe over SMB to a remote server.
    3164             :  *
    3165             :  * CAVEAT CALLER OF THIS FUNCTION:
    3166             :  *    The returned rpc_pipe_client saves a copy of the cli_state cli pointer,
    3167             :  *    so be sure that this function is called AFTER any structure (vs pointer)
    3168             :  *    assignment of the cli.  In particular, libsmbclient does structure
    3169             :  *    assignments of cli, which invalidates the data in the returned
    3170             :  *    rpc_pipe_client if this function is called before the structure assignment
    3171             :  *    of cli.
    3172             :  *
    3173             :  ****************************************************************************/
    3174             : 
    3175             : struct rpc_pipe_open_np_state {
    3176             :         struct cli_state *cli;
    3177             :         const struct ndr_interface_table *table;
    3178             :         struct rpc_pipe_client *result;
    3179             : };
    3180             : 
    3181             : static void rpc_pipe_open_np_done(struct tevent_req *subreq);
    3182             : 
    3183       13640 : struct tevent_req *rpc_pipe_open_np_send(
    3184             :         TALLOC_CTX *mem_ctx,
    3185             :         struct tevent_context *ev,
    3186             :         struct cli_state *cli,
    3187             :         const struct ndr_interface_table *table)
    3188             : {
    3189       13640 :         struct tevent_req *req = NULL, *subreq = NULL;
    3190       13640 :         struct rpc_pipe_open_np_state *state = NULL;
    3191       13640 :         struct rpc_pipe_client *result = NULL;
    3192             : 
    3193       13640 :         req = tevent_req_create(
    3194             :                 mem_ctx, &state, struct rpc_pipe_open_np_state);
    3195       13640 :         if (req == NULL) {
    3196           0 :                 return NULL;
    3197             :         }
    3198       13640 :         state->cli = cli;
    3199       13640 :         state->table = table;
    3200             : 
    3201       13640 :         state->result = talloc_zero(state, struct rpc_pipe_client);
    3202       13640 :         if (tevent_req_nomem(state->result, req)) {
    3203           0 :                 return tevent_req_post(req, ev);
    3204             :         }
    3205       13640 :         result = state->result;
    3206             : 
    3207       13640 :         result->abstract_syntax = table->syntax_id;
    3208       13640 :         result->transfer_syntax = ndr_transfer_syntax_ndr;
    3209             : 
    3210       13640 :         result->desthost = talloc_strdup(
    3211             :                 result, smbXcli_conn_remote_name(cli->conn));
    3212       13640 :         if (tevent_req_nomem(result->desthost, req)) {
    3213           0 :                 return tevent_req_post(req, ev);
    3214             :         }
    3215             : 
    3216       13640 :         result->srv_name_slash = talloc_asprintf_strupper_m(
    3217             :                 result, "\\\\%s", result->desthost);
    3218       13640 :         if (tevent_req_nomem(result->srv_name_slash, req)) {
    3219           0 :                 return tevent_req_post(req, ev);
    3220             :         }
    3221             : 
    3222       13640 :         result->max_xmit_frag = RPC_MAX_PDU_FRAG_LEN;
    3223             : 
    3224       13640 :         subreq = rpc_transport_np_init_send(state, ev, cli, table);
    3225       13640 :         if (tevent_req_nomem(subreq, req)) {
    3226           0 :                 return tevent_req_post(req, ev);
    3227             :         }
    3228       13640 :         tevent_req_set_callback(subreq, rpc_pipe_open_np_done, req);
    3229       13640 :         return req;
    3230             : }
    3231             : 
    3232       13640 : static void rpc_pipe_open_np_done(struct tevent_req *subreq)
    3233             : {
    3234       13640 :         struct tevent_req *req = tevent_req_callback_data(
    3235             :                 subreq, struct tevent_req);
    3236       13640 :         struct rpc_pipe_open_np_state *state = tevent_req_data(
    3237             :                 req, struct rpc_pipe_open_np_state);
    3238       13640 :         struct rpc_pipe_client *result = state->result;
    3239       13640 :         struct rpc_pipe_client_np_ref *np_ref = NULL;
    3240           0 :         NTSTATUS status;
    3241             : 
    3242       13640 :         status = rpc_transport_np_init_recv(
    3243             :                 subreq, result, &result->transport);
    3244       13640 :         TALLOC_FREE(subreq);
    3245       13640 :         if (tevent_req_nterror(req, status)) {
    3246           0 :                 return;
    3247             :         }
    3248             : 
    3249       13640 :         result->transport->transport = NCACN_NP;
    3250             : 
    3251       13640 :         np_ref = talloc(result->transport, struct rpc_pipe_client_np_ref);
    3252       13640 :         if (tevent_req_nomem(np_ref, req)) {
    3253           0 :                 return;
    3254             :         }
    3255       13640 :         np_ref->cli = state->cli;
    3256       13640 :         np_ref->pipe = result;
    3257             : 
    3258       13640 :         DLIST_ADD(np_ref->cli->pipe_list, np_ref->pipe);
    3259       13640 :         talloc_set_destructor(np_ref, rpc_pipe_client_np_ref_destructor);
    3260             : 
    3261       13640 :         result->binding_handle = rpccli_bh_create(result, NULL, state->table);
    3262       13640 :         if (tevent_req_nomem(result->binding_handle, req)) {
    3263           0 :                 return;
    3264             :         }
    3265             : 
    3266       13640 :         tevent_req_done(req);
    3267             : }
    3268             : 
    3269       13640 : NTSTATUS rpc_pipe_open_np_recv(
    3270             :         struct tevent_req *req,
    3271             :         TALLOC_CTX *mem_ctx,
    3272             :         struct rpc_pipe_client **_result)
    3273             : {
    3274       13640 :         struct rpc_pipe_open_np_state *state = tevent_req_data(
    3275             :                 req, struct rpc_pipe_open_np_state);
    3276           0 :         NTSTATUS status;
    3277             : 
    3278       13640 :         if (tevent_req_is_nterror(req, &status)) {
    3279           0 :                 return status;
    3280             :         }
    3281       13640 :         *_result = talloc_move(mem_ctx, &state->result);
    3282       13640 :         return NT_STATUS_OK;
    3283             : }
    3284             : 
    3285       13640 : NTSTATUS rpc_pipe_open_np(struct cli_state *cli,
    3286             :                           const struct ndr_interface_table *table,
    3287             :                           struct rpc_pipe_client **presult)
    3288             : {
    3289       13640 :         struct tevent_context *ev = NULL;
    3290       13640 :         struct tevent_req *req = NULL;
    3291       13640 :         NTSTATUS status = NT_STATUS_NO_MEMORY;
    3292             : 
    3293       13640 :         ev = samba_tevent_context_init(cli);
    3294       13640 :         if (ev == NULL) {
    3295           0 :                 goto fail;
    3296             :         }
    3297       13640 :         req = rpc_pipe_open_np_send(ev, ev, cli, table);
    3298       13640 :         if (req == NULL) {
    3299           0 :                 goto fail;
    3300             :         }
    3301       13640 :         if (!tevent_req_poll_ntstatus(req, ev, &status)) {
    3302           0 :                 goto fail;
    3303             :         }
    3304       13640 :         status = rpc_pipe_open_np_recv(req, NULL, presult);
    3305       13640 : fail:
    3306       13640 :         TALLOC_FREE(req);
    3307       13640 :         TALLOC_FREE(ev);
    3308       13640 :         return status;
    3309             : }
    3310             : 
    3311             : /****************************************************************************
    3312             :  Open a pipe to a remote server.
    3313             :  ****************************************************************************/
    3314             : 
    3315       13738 : static NTSTATUS cli_rpc_pipe_open(struct cli_state *cli,
    3316             :                                   enum dcerpc_transport_t transport,
    3317             :                                   const struct ndr_interface_table *table,
    3318             :                                   const char *remote_name,
    3319             :                                   const struct sockaddr_storage *remote_sockaddr,
    3320             :                                   struct rpc_pipe_client **presult)
    3321             : {
    3322       13738 :         switch (transport) {
    3323          98 :         case NCACN_IP_TCP:
    3324          98 :                 return rpc_pipe_open_tcp(NULL,
    3325             :                                          remote_name,
    3326             :                                          remote_sockaddr,
    3327             :                                          table, presult);
    3328       13640 :         case NCACN_NP:
    3329       13640 :                 return rpc_pipe_open_np(cli, table, presult);
    3330           0 :         default:
    3331           0 :                 return NT_STATUS_NOT_IMPLEMENTED;
    3332             :         }
    3333             : }
    3334             : 
    3335             : /****************************************************************************
    3336             :  Open a named pipe to an SMB server and bind anonymously.
    3337             :  ****************************************************************************/
    3338             : 
    3339       13398 : NTSTATUS cli_rpc_pipe_open_noauth_transport(struct cli_state *cli,
    3340             :                                             enum dcerpc_transport_t transport,
    3341             :                                             const struct ndr_interface_table *table,
    3342             :                                             const char *remote_name,
    3343             :                                             const struct sockaddr_storage *remote_sockaddr,
    3344             :                                             struct rpc_pipe_client **presult)
    3345             : {
    3346           0 :         struct rpc_pipe_client *result;
    3347           0 :         struct pipe_auth_data *auth;
    3348           0 :         NTSTATUS status;
    3349             : 
    3350       13398 :         status = cli_rpc_pipe_open(cli,
    3351             :                                    transport,
    3352             :                                    table,
    3353             :                                    remote_name,
    3354             :                                    remote_sockaddr,
    3355             :                                    &result);
    3356       13398 :         if (!NT_STATUS_IS_OK(status)) {
    3357           0 :                 return status;
    3358             :         }
    3359             : 
    3360       13398 :         status = rpccli_anon_bind_data(result, &auth);
    3361       13398 :         if (!NT_STATUS_IS_OK(status)) {
    3362           0 :                 DEBUG(0, ("rpccli_anon_bind_data returned %s\n",
    3363             :                           nt_errstr(status)));
    3364           0 :                 TALLOC_FREE(result);
    3365           0 :                 return status;
    3366             :         }
    3367             : 
    3368             :         /*
    3369             :          * This is a bit of an abstraction violation due to the fact that an
    3370             :          * anonymous bind on an authenticated SMB inherits the user/domain
    3371             :          * from the enclosing SMB creds
    3372             :          */
    3373             : 
    3374       13398 :         if (transport == NCACN_NP) {
    3375           0 :                 struct smbXcli_session *session;
    3376             : 
    3377       13390 :                 if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
    3378       13246 :                         session = cli->smb2.session;
    3379             :                 } else {
    3380         144 :                         session = cli->smb1.session;
    3381             :                 }
    3382             : 
    3383       13390 :                 status = smbXcli_session_application_key(session, auth,
    3384       13390 :                                                 &auth->transport_session_key);
    3385       13390 :                 if (!NT_STATUS_IS_OK(status)) {
    3386         168 :                         auth->transport_session_key = data_blob_null;
    3387             :                 }
    3388             :         }
    3389             : 
    3390       13398 :         status = rpc_pipe_bind(result, auth);
    3391       13398 :         if (!NT_STATUS_IS_OK(status)) {
    3392           0 :                 int lvl = 0;
    3393           0 :                 if (ndr_syntax_id_equal(&table->syntax_id,
    3394             :                                         &ndr_table_dssetup.syntax_id)) {
    3395             :                         /* non AD domains just don't have this pipe, avoid
    3396             :                          * level 0 statement in that case - gd */
    3397           0 :                         lvl = 3;
    3398             :                 }
    3399           0 :                 DEBUG(lvl, ("cli_rpc_pipe_open_noauth: rpc_pipe_bind for pipe "
    3400             :                             "%s failed with error %s\n",
    3401             :                             table->name,
    3402             :                             nt_errstr(status) ));
    3403           0 :                 TALLOC_FREE(result);
    3404           0 :                 return status;
    3405             :         }
    3406             : 
    3407       13398 :         DEBUG(10,("cli_rpc_pipe_open_noauth: opened pipe %s to machine "
    3408             :                   "%s and bound anonymously.\n",
    3409             :                   table->name,
    3410             :                   result->desthost));
    3411             : 
    3412       13398 :         *presult = result;
    3413       13398 :         return NT_STATUS_OK;
    3414             : }
    3415             : 
    3416             : /****************************************************************************
    3417             :  ****************************************************************************/
    3418             : 
    3419       12995 : NTSTATUS cli_rpc_pipe_open_noauth(struct cli_state *cli,
    3420             :                                   const struct ndr_interface_table *table,
    3421             :                                   struct rpc_pipe_client **presult)
    3422             : {
    3423       12995 :         const char *remote_name = smbXcli_conn_remote_name(cli->conn);
    3424           0 :         const struct sockaddr_storage *remote_sockaddr =
    3425       12995 :                 smbXcli_conn_remote_sockaddr(cli->conn);
    3426             : 
    3427       12995 :         return cli_rpc_pipe_open_noauth_transport(cli, NCACN_NP,
    3428             :                                                   table,
    3429             :                                                   remote_name,
    3430             :                                                   remote_sockaddr,
    3431             :                                                   presult);
    3432             : }
    3433             : 
    3434             : /****************************************************************************
    3435             :  Open a named pipe to an SMB server and bind using the mech specified
    3436             : 
    3437             :  This routine references the creds pointer that is passed in
    3438             :  ****************************************************************************/
    3439             : 
    3440         233 : NTSTATUS cli_rpc_pipe_open_with_creds(struct cli_state *cli,
    3441             :                                       const struct ndr_interface_table *table,
    3442             :                                       enum dcerpc_transport_t transport,
    3443             :                                       enum dcerpc_AuthType auth_type,
    3444             :                                       enum dcerpc_AuthLevel auth_level,
    3445             :                                       const char *server,
    3446             :                                       const struct sockaddr_storage *remote_sockaddr,
    3447             :                                       struct cli_credentials *creds,
    3448             :                                       struct rpc_pipe_client **presult)
    3449             : {
    3450           0 :         struct rpc_pipe_client *result;
    3451         233 :         struct pipe_auth_data *auth = NULL;
    3452         233 :         const char *target_service = table->authservices->names[0];
    3453           0 :         NTSTATUS status;
    3454             : 
    3455         233 :         status = cli_rpc_pipe_open(cli,
    3456             :                                    transport,
    3457             :                                    table,
    3458             :                                    server,
    3459             :                                    remote_sockaddr,
    3460             :                                    &result);
    3461         233 :         if (!NT_STATUS_IS_OK(status)) {
    3462           0 :                 return status;
    3463             :         }
    3464             : 
    3465         233 :         status = rpccli_generic_bind_data_from_creds(result,
    3466             :                                                      auth_type, auth_level,
    3467             :                                                      server, target_service,
    3468             :                                                      creds,
    3469             :                                                      &auth);
    3470         233 :         if (!NT_STATUS_IS_OK(status)) {
    3471           0 :                 DBG_ERR("rpccli_generic_bind_data_from_creds returned %s\n",
    3472             :                         nt_errstr(status));
    3473           0 :                 goto err;
    3474             :         }
    3475             : 
    3476         233 :         status = rpc_pipe_bind(result, auth);
    3477         233 :         if (!NT_STATUS_IS_OK(status)) {
    3478           0 :                 DBG_ERR("cli_rpc_pipe_bind failed with error %s\n",
    3479             :                         nt_errstr(status));
    3480           0 :                 goto err;
    3481             :         }
    3482             : 
    3483         233 :         DBG_DEBUG("opened pipe %s to machine %s and bound as user %s.\n",
    3484             :                   table->name,
    3485             :                   result->desthost,
    3486             :                   cli_credentials_get_unparsed_name(creds, talloc_tos()));
    3487             : 
    3488         233 :         *presult = result;
    3489         233 :         return NT_STATUS_OK;
    3490             : 
    3491           0 :   err:
    3492             : 
    3493           0 :         TALLOC_FREE(result);
    3494           0 :         return status;
    3495             : }
    3496             : 
    3497         107 : NTSTATUS cli_rpc_pipe_open_bind_schannel(
    3498             :         struct cli_state *cli,
    3499             :         const struct ndr_interface_table *table,
    3500             :         enum dcerpc_transport_t transport,
    3501             :         struct netlogon_creds_cli_context *netlogon_creds,
    3502             :         const char *remote_name,
    3503             :         const struct sockaddr_storage *remote_sockaddr,
    3504             :         struct rpc_pipe_client **_rpccli)
    3505             : {
    3506           0 :         struct rpc_pipe_client *rpccli;
    3507           0 :         struct pipe_auth_data *rpcauth;
    3508         107 :         const char *target_service = table->authservices->names[0];
    3509           0 :         struct cli_credentials *cli_creds;
    3510           0 :         enum dcerpc_AuthLevel auth_level;
    3511           0 :         NTSTATUS status;
    3512             : 
    3513         107 :         status = cli_rpc_pipe_open(cli,
    3514             :                                    transport,
    3515             :                                    table,
    3516             :                                    remote_name,
    3517             :                                    remote_sockaddr,
    3518             :                                    &rpccli);
    3519         107 :         if (!NT_STATUS_IS_OK(status)) {
    3520           0 :                 return status;
    3521             :         }
    3522             : 
    3523         107 :         auth_level = netlogon_creds_cli_auth_level(netlogon_creds);
    3524             : 
    3525         107 :         status = netlogon_creds_bind_cli_credentials(
    3526             :                 netlogon_creds, rpccli, &cli_creds);
    3527         107 :         if (!NT_STATUS_IS_OK(status)) {
    3528           0 :                 DBG_DEBUG("netlogon_creds_bind_cli_credentials failed: %s\n",
    3529             :                           nt_errstr(status));
    3530           0 :                 TALLOC_FREE(rpccli);
    3531           0 :                 return status;
    3532             :         }
    3533             : 
    3534         107 :         status = rpccli_generic_bind_data_from_creds(rpccli,
    3535             :                                                      DCERPC_AUTH_TYPE_SCHANNEL,
    3536             :                                                      auth_level,
    3537         107 :                                                      rpccli->desthost,
    3538             :                                                      target_service,
    3539             :                                                      cli_creds,
    3540             :                                                      &rpcauth);
    3541         107 :         if (!NT_STATUS_IS_OK(status)) {
    3542           0 :                 DEBUG(0, ("rpccli_generic_bind_data_from_creds returned %s\n",
    3543             :                           nt_errstr(status)));
    3544           0 :                 TALLOC_FREE(rpccli);
    3545           0 :                 return status;
    3546             :         }
    3547             : 
    3548         107 :         status = rpc_pipe_bind(rpccli, rpcauth);
    3549             : 
    3550             :         /* No TALLOC_FREE, gensec takes references */
    3551         107 :         talloc_unlink(rpccli, cli_creds);
    3552         107 :         cli_creds = NULL;
    3553             : 
    3554         107 :         if (!NT_STATUS_IS_OK(status)) {
    3555           0 :                 DBG_DEBUG("rpc_pipe_bind failed with error %s\n",
    3556             :                           nt_errstr(status));
    3557           0 :                 TALLOC_FREE(rpccli);
    3558           0 :                 return status;
    3559             :         }
    3560             : 
    3561         107 :         *_rpccli = rpccli;
    3562             : 
    3563         107 :         return NT_STATUS_OK;
    3564             : }
    3565             : 
    3566         107 : NTSTATUS cli_rpc_pipe_open_schannel_with_creds(struct cli_state *cli,
    3567             :                                                const struct ndr_interface_table *table,
    3568             :                                                enum dcerpc_transport_t transport,
    3569             :                                                struct netlogon_creds_cli_context *netlogon_creds,
    3570             :                                                const char *remote_name,
    3571             :                                                const struct sockaddr_storage *remote_sockaddr,
    3572             :                                                struct rpc_pipe_client **_rpccli)
    3573             : {
    3574         107 :         TALLOC_CTX *frame = talloc_stackframe();
    3575           0 :         struct rpc_pipe_client *rpccli;
    3576           0 :         struct netlogon_creds_cli_lck *lck;
    3577           0 :         NTSTATUS status;
    3578             : 
    3579         107 :         status = netlogon_creds_cli_lck(
    3580             :                 netlogon_creds, NETLOGON_CREDS_CLI_LCK_EXCLUSIVE,
    3581             :                 frame, &lck);
    3582         107 :         if (!NT_STATUS_IS_OK(status)) {
    3583           0 :                 DBG_WARNING("netlogon_creds_cli_lck returned %s\n",
    3584             :                             nt_errstr(status));
    3585           0 :                 TALLOC_FREE(frame);
    3586           0 :                 return status;
    3587             :         }
    3588             : 
    3589         107 :         status = cli_rpc_pipe_open_bind_schannel(cli,
    3590             :                                                  table,
    3591             :                                                  transport,
    3592             :                                                  netlogon_creds,
    3593             :                                                  remote_name,
    3594             :                                                  remote_sockaddr,
    3595             :                                                  &rpccli);
    3596         107 :         if (NT_STATUS_EQUAL(status, NT_STATUS_NETWORK_ACCESS_DENIED)) {
    3597           0 :                 netlogon_creds_cli_delete_lck(netlogon_creds);
    3598             :         }
    3599         107 :         if (!NT_STATUS_IS_OK(status)) {
    3600           0 :                 DBG_DEBUG("cli_rpc_pipe_open_bind_schannel failed: %s\n",
    3601             :                           nt_errstr(status));
    3602           0 :                 TALLOC_FREE(frame);
    3603           0 :                 return status;
    3604             :         }
    3605             : 
    3606         107 :         if (ndr_syntax_id_equal(&table->syntax_id,
    3607             :                                 &ndr_table_netlogon.syntax_id)) {
    3608         103 :                 status = netlogon_creds_cli_check(netlogon_creds,
    3609         103 :                                                   rpccli->binding_handle,
    3610             :                                                   NULL);
    3611         103 :                 if (!NT_STATUS_IS_OK(status)) {
    3612           0 :                         DEBUG(0, ("netlogon_creds_cli_check failed with %s\n",
    3613             :                                   nt_errstr(status)));
    3614           0 :                         TALLOC_FREE(frame);
    3615           0 :                         return status;
    3616             :                 }
    3617             :         }
    3618             : 
    3619         107 :         DBG_DEBUG("opened pipe %s to machine %s with key %s "
    3620             :                   "and bound using schannel.\n",
    3621             :                   table->name, rpccli->desthost,
    3622             :                   netlogon_creds_cli_debug_string(netlogon_creds, lck));
    3623             : 
    3624         107 :         TALLOC_FREE(frame);
    3625             : 
    3626         107 :         *_rpccli = rpccli;
    3627         107 :         return NT_STATUS_OK;
    3628             : }
    3629             : 
    3630          21 : NTSTATUS cli_get_session_key(TALLOC_CTX *mem_ctx,
    3631             :                              struct rpc_pipe_client *cli,
    3632             :                              DATA_BLOB *session_key)
    3633             : {
    3634           0 :         NTSTATUS status;
    3635           0 :         struct pipe_auth_data *a;
    3636           0 :         struct gensec_security *gensec_security;
    3637          21 :         DATA_BLOB sk = { .data = NULL };
    3638          21 :         bool make_dup = false;
    3639             : 
    3640          21 :         if (!session_key || !cli) {
    3641           0 :                 return NT_STATUS_INVALID_PARAMETER;
    3642             :         }
    3643             : 
    3644          21 :         a = cli->auth;
    3645             : 
    3646          21 :         if (a == NULL) {
    3647           0 :                 return NT_STATUS_INVALID_PARAMETER;
    3648             :         }
    3649             : 
    3650          21 :         switch (cli->auth->auth_type) {
    3651          21 :         case DCERPC_AUTH_TYPE_NONE:
    3652          21 :                 sk = data_blob_const(a->transport_session_key.data,
    3653             :                                      a->transport_session_key.length);
    3654          21 :                 make_dup = true;
    3655          21 :                 break;
    3656           0 :         default:
    3657           0 :                 gensec_security = a->auth_ctx;
    3658           0 :                 status = gensec_session_key(gensec_security, mem_ctx, &sk);
    3659           0 :                 if (!NT_STATUS_IS_OK(status)) {
    3660           0 :                         return status;
    3661             :                 }
    3662           0 :                 make_dup = false;
    3663           0 :                 break;
    3664             :         }
    3665             : 
    3666          21 :         if (!sk.data) {
    3667           0 :                 return NT_STATUS_NO_USER_SESSION_KEY;
    3668             :         }
    3669             : 
    3670          21 :         if (make_dup) {
    3671          21 :                 *session_key = data_blob_dup_talloc(mem_ctx, sk);
    3672             :         } else {
    3673           0 :                 *session_key = sk;
    3674             :         }
    3675             : 
    3676          21 :         return NT_STATUS_OK;
    3677             : }

Generated by: LCOV version 1.14