LCOV - code coverage report
Current view: top level - source4/librpc/rpc - dcerpc_roh_channel_in.c (source / functions) Hit Total Coverage
Test: coverage report for master 98b443d9 Lines: 0 140 0.0 %
Date: 2024-05-31 13:13:24 Functions: 0 6 0.0 %

          Line data    Source code
       1             : /*
       2             :    Unix SMB/CIFS implementation.
       3             : 
       4             :    [MS-RPCH] - RPC over HTTP client
       5             : 
       6             :    Copyright (C) 2013 Samuel Cabrero <samuelcabrero@kernevil.me>
       7             :    Copyright (C) Julien Kerihuel <j.kerihuel@openchange.org> 2013
       8             : 
       9             :    This program is free software; you can redistribute it and/or modify
      10             :    it under the terms of the GNU General Public License as published by
      11             :    the Free Software Foundation; either version 3 of the License, or
      12             :    (at your option) any later version.
      13             : 
      14             :    This program is distributed in the hope that it will be useful,
      15             :    but WITHOUT ANY WARRANTY; without even the implied warranty of
      16             :    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      17             :    GNU General Public License for more details.
      18             : 
      19             :    You should have received a copy of the GNU General Public License
      20             :    along with this program.  If not, see <http://www.gnu.org/licenses/>.
      21             : */
      22             : 
      23             : #include "includes.h"
      24             : #include <tevent.h>
      25             : #include <talloc.h>
      26             : #include "lib/tsocket/tsocket.h"
      27             : #include "lib/tls/tls.h"
      28             : #include "lib/util/tevent_ntstatus.h"
      29             : #include "lib/util/util_net.h"
      30             : #include "libcli/resolve/resolve.h"
      31             : #include "libcli/composite/composite.h"
      32             : #include "auth/credentials/credentials.h"
      33             : #include "auth/credentials/credentials_internal.h"
      34             : #include <gen_ndr/dcerpc.h>
      35             : #include <gen_ndr/ndr_dcerpc.h>
      36             : 
      37             : #include "librpc/rpc/dcerpc.h"
      38             : #include "librpc/rpc/dcerpc_roh.h"
      39             : #include "librpc/rpc/dcerpc_proto.h"
      40             : #include "libcli/http/http.h"
      41             : 
      42             : struct roh_request_state {
      43             :         struct http_request     *request;
      44             :         struct http_request     *response;
      45             : };
      46             : 
      47             : static void roh_send_RPC_DATA_IN_done(struct tevent_req *subreq);
      48           0 : struct tevent_req *roh_send_RPC_DATA_IN_send(TALLOC_CTX *mem_ctx,
      49             :                                              struct loadparm_context *lp_ctx,
      50             :                                              struct tevent_context *ev,
      51             :                                              struct cli_credentials *credentials,
      52             :                                              struct roh_connection *roh,
      53             :                                              const char *rpc_server,
      54             :                                              uint32_t rpc_server_port,
      55             :                                              const char *rpc_proxy,
      56             :                                              uint8_t http_auth)
      57             : {
      58           0 :         struct tevent_req               *req;
      59           0 :         struct tevent_req               *subreq;
      60           0 :         struct roh_request_state        *state;
      61           0 :         const char                      *path;
      62           0 :         char                            *query;
      63           0 :         char                            *uri;
      64             : 
      65           0 :         DEBUG(8, ("%s: Sending RPC_IN_DATA request\n", __func__));
      66             : 
      67           0 :         req = tevent_req_create(mem_ctx, &state, struct roh_request_state);
      68           0 :         if (req == NULL) {
      69           0 :                 return NULL;
      70             :         }
      71             : 
      72           0 :         state->request = talloc_zero(state, struct http_request);
      73           0 :         if (tevent_req_nomem(state->request, req)) {
      74           0 :                 return tevent_req_post(req, ev);
      75             :         }
      76             : 
      77             :         /* Build URI, as specified in section 2.2.2 */
      78           0 :         query = talloc_asprintf(state, "%s:%d", rpc_server, rpc_server_port);
      79           0 :         if (tevent_req_nomem(query, req)) {
      80           0 :                 return tevent_req_post(req, ev);
      81             :         }
      82             : 
      83             :         /*
      84             :          * TODO This path changes to "/rpcwithcert/rpcproxy.dll" when using
      85             :          * certificates
      86             :          */
      87           0 :         path = "/rpc/rpcproxy.dll";
      88           0 :         uri = talloc_asprintf(state, "%s?%s", path, query);
      89           0 :         if (tevent_req_nomem(uri, req)) {
      90           0 :                 tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
      91           0 :                 return tevent_req_post(req, ev);
      92             :         }
      93           0 :         TALLOC_FREE(query);
      94             : 
      95             :         /*
      96             :          * Create the HTTP channel IN request as specified in the
      97             :          * section 2.1.2.1.1
      98             :          */
      99           0 :         state->request->type = HTTP_REQ_RPC_IN_DATA;
     100           0 :         state->request->uri = uri;
     101           0 :         state->request->body.length = 0;
     102           0 :         state->request->body.data = NULL;
     103           0 :         state->request->major = '1';
     104           0 :         state->request->minor = '0';
     105             : 
     106           0 :         http_add_header(state, &state->request->headers,
     107             :                         "Accept", "application/rpc");
     108           0 :         http_add_header(state, &state->request->headers,
     109             :                         "User-Agent", "MSRPC");
     110           0 :         http_add_header(state, &state->request->headers,
     111             :                         "Host", rpc_proxy);
     112           0 :         http_add_header(state, &state->request->headers,
     113             :                         "Connection", "keep-alive");
     114           0 :         http_add_header(state, &state->request->headers,
     115             :                         "Content-Length", "1073741824");
     116           0 :         http_add_header(state, &state->request->headers,
     117             :                         "Cache-Control", "no-cache");
     118           0 :         http_add_header(state, &state->request->headers,
     119             :                         "Pragma", "no-cache");
     120             : 
     121           0 :         subreq = http_send_auth_request_send(state,
     122             :                                         ev,
     123           0 :                                         roh->default_channel_in->http_conn,
     124           0 :                                         state->request,
     125             :                                         credentials,
     126             :                                         lp_ctx,
     127             :                                         http_auth);
     128           0 :         if (tevent_req_nomem(subreq, req)) {
     129           0 :                 return tevent_req_post(req, ev);
     130             :         }
     131           0 :         tevent_req_set_callback(subreq, roh_send_RPC_DATA_IN_done, req);
     132             : 
     133           0 :         return req;
     134             : }
     135             : 
     136           0 : static void roh_send_RPC_DATA_IN_done(struct tevent_req *subreq)
     137             : {
     138           0 :         NTSTATUS                status;
     139           0 :         struct tevent_req       *req;
     140             : 
     141           0 :         req = tevent_req_callback_data(subreq, struct tevent_req);
     142             : 
     143             :         /* Receive the sent bytes to check if request has been properly sent */
     144           0 :         status = http_send_auth_request_recv(subreq);
     145           0 :         TALLOC_FREE(subreq);
     146           0 :         if (tevent_req_nterror(req, status)) {
     147           0 :                 return;
     148             :         }
     149             : 
     150           0 :         DEBUG(8, ("%s: RPC_IN_DATA sent\n", __func__));
     151             : 
     152           0 :         tevent_req_done(req);
     153             : }
     154             : 
     155           0 : NTSTATUS roh_send_RPC_DATA_IN_recv(struct tevent_req *req)
     156             : {
     157           0 :         NTSTATUS status;
     158             : 
     159           0 :         if (tevent_req_is_nterror(req, &status)) {
     160           0 :                 tevent_req_received(req);
     161           0 :                 return status;
     162             :         }
     163             : 
     164           0 :         tevent_req_received(req);
     165           0 :         return NT_STATUS_OK;
     166             : }
     167             : 
     168             : struct roh_send_pdu_state {
     169             :         DATA_BLOB       buffer;
     170             :         struct iovec    iov;
     171             :         int             bytes_written;
     172             :         int             sys_errno;
     173             : };
     174             : 
     175             : static void roh_send_CONN_B1_done(struct tevent_req *subreq);
     176           0 : struct tevent_req *roh_send_CONN_B1_send(TALLOC_CTX *mem_ctx,
     177             :                                          struct tevent_context *ev,
     178             :                                          struct roh_connection *roh)
     179             : {
     180           0 :         struct tevent_req               *req;
     181           0 :         struct tevent_req               *subreq;
     182           0 :         struct roh_send_pdu_state       *state;
     183           0 :         struct dcerpc_rts               rts;
     184           0 :         struct ncacn_packet             pkt;
     185           0 :         struct ndr_push                 *ndr;
     186           0 :         struct tstream_context          *stream = NULL;
     187           0 :         struct tevent_queue             *send_queue = NULL;
     188             : 
     189           0 :         DEBUG(8, ("%s: Sending CONN/B1 request\n", __func__));
     190             : 
     191           0 :         req = tevent_req_create(mem_ctx, &state, struct roh_send_pdu_state);
     192           0 :         if (req == NULL) {
     193           0 :                 return NULL;
     194             :         }
     195             : 
     196           0 :         rts.Flags = RTS_FLAG_NONE;
     197           0 :         rts.NumberOfCommands = 6;
     198           0 :         rts.Commands = talloc_array(state, struct dcerpc_rts_cmd, 6);
     199             : 
     200             :         /* CONN/B1: Version RTS command */
     201           0 :         rts.Commands[0].CommandType = 0x00000006;
     202           0 :         rts.Commands[0].Command.Version.Version = 0x00000001;
     203             : 
     204             :         /* CONN/B1: VirtualConnectionCookie RTS command */
     205           0 :         rts.Commands[1].CommandType = 0x00000003;
     206           0 :         rts.Commands[1].Command.Cookie.Cookie.Cookie = roh->connection_cookie;
     207             : 
     208             :         /* CONN/B1: InChannelCookie RTS command */
     209           0 :         rts.Commands[2].CommandType = 0x00000003;
     210           0 :         rts.Commands[2].Command.Cookie.Cookie.Cookie =
     211           0 :                         roh->default_channel_in->channel_cookie;
     212             : 
     213             :         /* CONN/B1: ChannelLifetime */
     214           0 :         rts.Commands[3].CommandType = 0x00000004;
     215           0 :         rts.Commands[3].Command.ReceiveWindowSize.ReceiveWindowSize =
     216             :                         0x40000000;
     217             : 
     218             :         /* CONN/B1: ClientKeepAlive */
     219           0 :         rts.Commands[4].CommandType = 0x00000005;
     220           0 :         rts.Commands[4].Command.ClientKeepalive.ClientKeepalive = 0x000493e0;
     221             : 
     222             :         /* CONN/B1: AssociationGroupId */
     223           0 :         rts.Commands[5].CommandType = 0x0000000C;
     224           0 :         rts.Commands[5].Command.AssociationGroupId.AssociationGroupId.Cookie =
     225             :                         roh->association_group_id_cookie;
     226             : 
     227           0 :         pkt.rpc_vers = 5;
     228           0 :         pkt.rpc_vers_minor = 0;
     229           0 :         pkt.ptype = DCERPC_PKT_RTS;
     230           0 :         pkt.pfc_flags = DCERPC_PFC_FLAG_LAST | DCERPC_PFC_FLAG_FIRST;
     231           0 :         pkt.drep[0] = DCERPC_DREP_LE;
     232           0 :         pkt.drep[1] = 0;
     233           0 :         pkt.drep[2] = 0;
     234           0 :         pkt.drep[3] = 0;
     235           0 :         pkt.frag_length = 104;
     236           0 :         pkt.auth_length = 0;
     237           0 :         pkt.call_id = 0;
     238           0 :         pkt.u.rts = rts;
     239             : 
     240           0 :         ndr = ndr_push_init_ctx(state);
     241           0 :         if (ndr == NULL) {
     242           0 :                 return NULL;
     243             :         }
     244           0 :         ndr->offset = 0;
     245           0 :         ndr_push_ncacn_packet(ndr, NDR_SCALARS, &pkt);
     246             : 
     247           0 :         state->buffer = ndr_push_blob(ndr);
     248           0 :         state->iov.iov_base = (char *) state->buffer.data;
     249           0 :         state->iov.iov_len = state->buffer.length;
     250             : 
     251           0 :         stream = http_conn_tstream(roh->default_channel_in->http_conn);
     252           0 :         send_queue = http_conn_send_queue(roh->default_channel_in->http_conn);
     253             : 
     254           0 :         subreq = tstream_writev_queue_send(mem_ctx,
     255             :                                            ev,
     256             :                                            stream,
     257             :                                            send_queue,
     258           0 :                                            &state->iov,
     259             :                                            1);
     260           0 :         if (tevent_req_nomem(subreq, req)) {
     261           0 :                 return tevent_req_post(req, ev);
     262             :         }
     263           0 :         tevent_req_set_callback(subreq, roh_send_CONN_B1_done, req);
     264             : 
     265           0 :         return req;
     266             : }
     267             : 
     268           0 : static void roh_send_CONN_B1_done(struct tevent_req *subreq)
     269             : {
     270           0 :         NTSTATUS                        status;
     271           0 :         struct tevent_req               *req;
     272           0 :         struct roh_send_pdu_state       *state;
     273           0 :         int                             sys_errno;
     274             : 
     275           0 :         req = tevent_req_callback_data(subreq, struct tevent_req);
     276           0 :         state = tevent_req_data(req, struct roh_send_pdu_state);
     277             : 
     278           0 :         state->bytes_written = tstream_writev_queue_recv(subreq, &sys_errno);
     279           0 :         state->sys_errno = sys_errno;
     280           0 :         TALLOC_FREE(subreq);
     281           0 :         if (state->bytes_written <= 0 && state->sys_errno != 0) {
     282           0 :                 status = map_nt_error_from_unix_common(sys_errno);
     283           0 :                 tevent_req_nterror(req, status);
     284           0 :                 return;
     285             :         }
     286           0 :         DEBUG(8, ("%s: CONN/B1 sent (%d bytes written)\n",
     287             :                   __func__, state->bytes_written));
     288             : 
     289           0 :         tevent_req_done(req);
     290             : }
     291             : 
     292           0 : NTSTATUS roh_send_CONN_B1_recv(struct tevent_req *req)
     293             : {
     294           0 :         NTSTATUS status;
     295             : 
     296           0 :         if (tevent_req_is_nterror(req, &status)) {
     297           0 :                 tevent_req_received(req);
     298           0 :                 return status;
     299             :         }
     300             : 
     301           0 :         tevent_req_received(req);
     302           0 :         return NT_STATUS_OK;
     303             : }

Generated by: LCOV version 1.14