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

Generated by: LCOV version 1.13