LCOV - code coverage report
Current view: top level - source4/librpc/rpc - dcerpc_roh_channel_out.c (source / functions) Hit Total Coverage
Test: coverage report for master 6248eab5 Lines: 0 249 0.0 %
Date: 2021-08-25 13:27:56 Functions: 0 15 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 "librpc/rpc/dcerpc_util.h"
      41             : #include "libcli/http/http.h"
      42             : 
      43             : struct roh_request_state {
      44             :         struct http_request     *request;
      45             :         struct http_request     *response;
      46             : };
      47             : 
      48             : static void roh_send_RPC_DATA_OUT_done(struct tevent_req *subreq);
      49           0 : struct tevent_req *roh_send_RPC_DATA_OUT_send(TALLOC_CTX *mem_ctx,
      50             :                                               struct loadparm_context *lp_ctx,
      51             :                                               struct tevent_context *ev,
      52             :                                               struct cli_credentials *credentials,
      53             :                                               struct roh_connection *roh,
      54             :                                               const char *rpc_server,
      55             :                                               uint32_t rpc_server_port,
      56             :                                               const char *rpc_proxy,
      57             :                                               uint8_t http_auth)
      58             : {
      59             :         struct tevent_req               *req;
      60             :         struct tevent_req               *subreq;
      61             :         struct roh_request_state        *state;
      62             :         const char                      *path;
      63             :         char                            *query;
      64             :         char                            *uri;
      65             : 
      66           0 :         DEBUG(8, ("%s: Sending RPC_OUT_DATA request\n", __func__));
      67             : 
      68           0 :         req = tevent_req_create(mem_ctx, &state, struct roh_request_state);
      69           0 :         if (req == NULL) {
      70           0 :                 return NULL;
      71             :         }
      72             : 
      73           0 :         state->request = talloc_zero(state, struct http_request);
      74           0 :         if (tevent_req_nomem(state->request, req)) {
      75           0 :                 return tevent_req_post(req, ev);
      76             :         }
      77             : 
      78             :         /* Build URI, as specified in section 2.2.2 */
      79           0 :         query = talloc_asprintf(state, "%s:%d", rpc_server, rpc_server_port);
      80           0 :         if (tevent_req_nomem(query, req)) {
      81           0 :                 return tevent_req_post(req, ev);
      82             :         }
      83             : 
      84             :         /*
      85             :          * TODO This path changes to "/rpcwithcert/rpcproxy.dll" when using
      86             :          * certificates
      87             :          */
      88           0 :         path = "/rpc/rpcproxy.dll";
      89           0 :         uri = talloc_asprintf(state, "%s?%s", path, query);
      90           0 :         if (tevent_req_nomem(uri, req)) {
      91           0 :                 tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
      92           0 :                 return tevent_req_post(req, ev);
      93             :         }
      94           0 :         TALLOC_FREE(query);
      95             : 
      96             :         /*
      97             :          * Create the HTTP channel OUT request as specified in the
      98             :          * section 2.1.2.1.2
      99             :          */
     100           0 :         state->request->type = HTTP_REQ_RPC_OUT_DATA;
     101           0 :         state->request->uri = uri;
     102           0 :         state->request->body.length = 0;
     103           0 :         state->request->body.data = NULL;
     104           0 :         state->request->major = '1';
     105           0 :         state->request->minor = '0';
     106             : 
     107           0 :         http_add_header(state, &state->request->headers,
     108             :                         "Accept", "application/rpc");
     109           0 :         http_add_header(state, &state->request->headers,
     110             :                         "User-Agent", "MSRPC");
     111           0 :         http_add_header(state, &state->request->headers,
     112             :                         "Host", rpc_proxy);
     113           0 :         http_add_header(state, &state->request->headers,
     114             :                         "Connection", "keep-alive");
     115           0 :         http_add_header(state, &state->request->headers,
     116             :                         "Content-Length", "76");
     117           0 :         http_add_header(state, &state->request->headers,
     118             :                         "Cache-Control", "no-cache");
     119           0 :         http_add_header(state, &state->request->headers,
     120             :                         "Pragma", "no-cache");
     121             : 
     122           0 :         subreq = http_send_auth_request_send(state,
     123             :                                         ev,
     124           0 :                                         roh->default_channel_out->http_conn,
     125           0 :                                         state->request,
     126             :                                         credentials,
     127             :                                         lp_ctx,
     128             :                                         http_auth);
     129           0 :         if (tevent_req_nomem(subreq, req)) {
     130           0 :                 return tevent_req_post(req, ev);
     131             :         }
     132           0 :         tevent_req_set_callback(subreq, roh_send_RPC_DATA_OUT_done, req);
     133             : 
     134           0 :         return req;
     135             : }
     136             : 
     137           0 : static void roh_send_RPC_DATA_OUT_done(struct tevent_req *subreq)
     138             : {
     139             :         NTSTATUS                status;
     140             :         struct tevent_req       *req;
     141             : 
     142           0 :         req = tevent_req_callback_data(subreq, struct tevent_req);
     143             : 
     144             :         /* Receive the sent bytes to check if request has been properly sent */
     145           0 :         status = http_send_auth_request_recv(subreq);
     146           0 :         TALLOC_FREE(subreq);
     147           0 :         if (tevent_req_nterror(req, status)) {
     148           0 :                 return;
     149             :         }
     150             : 
     151           0 :         DEBUG(8, ("%s: RPC_OUT_DATA sent", __func__));
     152             : 
     153           0 :         tevent_req_done(req);
     154             : }
     155             : 
     156           0 : NTSTATUS roh_send_RPC_DATA_OUT_recv(struct tevent_req *req)
     157             : {
     158             :         NTSTATUS status;
     159             : 
     160           0 :         if (tevent_req_is_nterror(req, &status)) {
     161           0 :                 tevent_req_received(req);
     162           0 :                 return status;
     163             :         }
     164             : 
     165           0 :         tevent_req_received(req);
     166           0 :         return NT_STATUS_OK;
     167             : }
     168             : 
     169             : struct roh_send_pdu_state {
     170             :         DATA_BLOB       buffer;
     171             :         struct iovec    iov;
     172             :         int             bytes_written;
     173             :         int             sys_errno;
     174             : };
     175             : 
     176             : static void roh_send_CONN_A1_done(struct tevent_req *subreq);
     177           0 : struct tevent_req *roh_send_CONN_A1_send(TALLOC_CTX *mem_ctx,
     178             :                                          struct tevent_context *ev,
     179             :                                          struct roh_connection *roh)
     180             : {
     181             :         struct tevent_req               *req;
     182             :         struct tevent_req               *subreq;
     183             :         struct roh_send_pdu_state       *state;
     184             :         struct dcerpc_rts               rts;
     185             :         struct ncacn_packet             pkt;
     186             :         struct ndr_push                 *ndr;
     187           0 :         struct tstream_context          *stream = NULL;
     188           0 :         struct tevent_queue             *send_queue = NULL;
     189             : 
     190           0 :         DEBUG(8, ("%s: Sending CONN/A1 request\n", __func__));
     191             : 
     192           0 :         req = tevent_req_create(mem_ctx, &state, struct roh_send_pdu_state);
     193           0 :         if (req == NULL) {
     194           0 :                 return NULL;
     195             :         }
     196             : 
     197           0 :         rts.Flags = RTS_FLAG_NONE;
     198           0 :         rts.NumberOfCommands = 4;
     199           0 :         rts.Commands = talloc_array(state, struct dcerpc_rts_cmd, 4);
     200             : 
     201             :         /* CONN/A1: Version RTS command */
     202           0 :         rts.Commands[0].CommandType = 0x00000006;
     203           0 :         rts.Commands[0].Command.Version.Version = 0x00000001;
     204             : 
     205             :         /* CONN/A1: VirtualConnectionCookie RTS command */
     206           0 :         rts.Commands[1].CommandType = 0x00000003;
     207           0 :         rts.Commands[1].Command.Cookie.Cookie.Cookie = roh->connection_cookie;
     208             : 
     209             :         /* CONN/A1: OutChannelCookie RTS command */
     210           0 :         rts.Commands[2].CommandType = 0x00000003;
     211           0 :         rts.Commands[2].Command.Cookie.Cookie.Cookie =
     212           0 :                         roh->default_channel_out->channel_cookie;
     213             : 
     214             :         /* CONN/A1: ReceiveWindowSize */
     215           0 :         rts.Commands[3].CommandType = 0x00000000;
     216           0 :         rts.Commands[3].Command.ReceiveWindowSize.ReceiveWindowSize = 0x40000;
     217             : 
     218           0 :         pkt.rpc_vers = 5;
     219           0 :         pkt.rpc_vers_minor = 0;
     220           0 :         pkt.ptype = DCERPC_PKT_RTS;
     221           0 :         pkt.pfc_flags = DCERPC_PFC_FLAG_LAST | DCERPC_PFC_FLAG_FIRST;
     222           0 :         pkt.drep[0] = DCERPC_DREP_LE;
     223           0 :         pkt.drep[1] = 0;
     224           0 :         pkt.drep[2] = 0;
     225           0 :         pkt.drep[3] = 0;
     226           0 :         pkt.frag_length = 76;
     227           0 :         pkt.auth_length = 0;
     228           0 :         pkt.call_id = 0;
     229           0 :         pkt.u.rts = rts;
     230             : 
     231           0 :         ndr = ndr_push_init_ctx(state);
     232           0 :         if (ndr == NULL) {
     233           0 :                 return NULL;
     234             :         }
     235           0 :         ndr->offset = 0;
     236           0 :         ndr_push_ncacn_packet(ndr, NDR_SCALARS, &pkt);
     237             : 
     238           0 :         state->buffer = ndr_push_blob(ndr);
     239           0 :         state->iov.iov_base = (char *) state->buffer.data;
     240           0 :         state->iov.iov_len = state->buffer.length;
     241             : 
     242           0 :         stream = http_conn_tstream(roh->default_channel_out->http_conn);
     243           0 :         send_queue = http_conn_send_queue(roh->default_channel_out->http_conn);
     244             : 
     245           0 :         subreq = tstream_writev_queue_send(mem_ctx,
     246             :                                            ev,
     247             :                                            stream,
     248             :                                            send_queue,
     249           0 :                                            &state->iov,
     250             :                                            1);
     251           0 :         if (tevent_req_nomem(subreq, req)) {
     252           0 :                 return tevent_req_post(req, ev);
     253             :         }
     254           0 :         tevent_req_set_callback(subreq, roh_send_CONN_A1_done, req);
     255             : 
     256           0 :         return req;
     257             : }
     258             : 
     259           0 : static void roh_send_CONN_A1_done(struct tevent_req *subreq)
     260             : {
     261             :         NTSTATUS                        status;
     262             :         struct tevent_req               *req;
     263             :         struct roh_send_pdu_state       *state;
     264             :         int                             sys_errno;
     265             : 
     266           0 :         req = tevent_req_callback_data(subreq, struct tevent_req);
     267           0 :         state = tevent_req_data(req, struct roh_send_pdu_state);
     268             : 
     269           0 :         state->bytes_written = tstream_writev_queue_recv(subreq, &sys_errno);
     270           0 :         state->sys_errno = sys_errno;
     271           0 :         TALLOC_FREE(subreq);
     272           0 :         if (state->bytes_written <= 0 && sys_errno != 0) {
     273           0 :                 status = map_nt_error_from_unix_common(sys_errno);
     274           0 :                 tevent_req_nterror(req, status);
     275           0 :                 return;
     276             :         }
     277           0 :         DEBUG(8, ("%s: CONN/A1 sent (%d bytes written)\n",
     278             :                   __func__, state->bytes_written));
     279             : 
     280           0 :         tevent_req_done(req);
     281             : }
     282             : 
     283           0 : NTSTATUS roh_send_CONN_A1_recv(struct tevent_req *req)
     284             : {
     285             :         NTSTATUS status;
     286             : 
     287           0 :         if (tevent_req_is_nterror(req, &status)) {
     288           0 :                 tevent_req_received(req);
     289           0 :                 return status;
     290             :         }
     291             : 
     292           0 :         tevent_req_received(req);
     293           0 :         return NT_STATUS_OK;
     294             : }
     295             : 
     296             : struct roh_recv_response_state
     297             : {
     298             :         struct http_request     *response;
     299             : };
     300             : 
     301             : static void roh_recv_out_channel_response_done(struct tevent_req *);
     302           0 : struct tevent_req *roh_recv_out_channel_response_send(TALLOC_CTX *mem_ctx,
     303             :                                                       struct tevent_context *ev,
     304             :                                                       struct roh_connection *roh)
     305             : {
     306             :         struct tevent_req               *req;
     307             :         struct tevent_req               *subreq;
     308             :         struct roh_recv_response_state  *state;
     309             : 
     310           0 :         DEBUG(8, ("%s: Waiting for RPC_OUT_DATA response\n", __func__));
     311             : 
     312           0 :         req = tevent_req_create(mem_ctx, &state, struct roh_recv_response_state);
     313           0 :         if (req == NULL) {
     314           0 :                 return NULL;
     315             :         }
     316             : 
     317           0 :         subreq = http_read_response_send(state, ev,
     318           0 :                                          roh->default_channel_out->http_conn,
     319             :                                          0); /* we'll get the content later */
     320           0 :         if (tevent_req_nomem(subreq, req)) {
     321           0 :                 return tevent_req_post(req, ev);
     322             :         }
     323           0 :         tevent_req_set_callback(subreq, roh_recv_out_channel_response_done, req);
     324             : 
     325           0 :         return req;
     326             : }
     327             : 
     328           0 : static void roh_recv_out_channel_response_done(struct tevent_req *subreq)
     329             : {
     330             :         NTSTATUS                        status;
     331             :         struct tevent_req               *req;
     332             :         struct roh_recv_response_state  *state;
     333             : 
     334           0 :         req = tevent_req_callback_data(subreq, struct tevent_req);
     335           0 :         state = tevent_req_data(req, struct roh_recv_response_state);
     336           0 :         status = http_read_response_recv(subreq, state, &state->response);
     337           0 :         TALLOC_FREE(subreq);
     338           0 :         if (tevent_req_nterror(req, status)) {
     339           0 :                 return;
     340             :         }
     341             : 
     342           0 :         DEBUG(8, ("%s: RCP_OUT_DATA response received\n", __func__));
     343             : 
     344             :         /* TODO Map response code to nt error */
     345           0 :         switch (state->response->response_code) {
     346           0 :         case 200:
     347           0 :                 break;
     348           0 :         case 401:
     349           0 :                 DEBUG(0, ("%s: Server response: Access denied\n", __func__));
     350           0 :                 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
     351           0 :                 return;
     352           0 :         case 503:
     353             :                 /* TODO Decode error info as specified in section 2.1.2.1.3 */
     354           0 :                 DEBUG(0, ("%s: Server response: RPC error\n", __func__));
     355           0 :                 tevent_req_nterror(req, NT_STATUS_GENERIC_NOT_MAPPED);
     356           0 :                 return;
     357           0 :         default:
     358           0 :                 DEBUG(0, ("%s: Server response: Unknown error\n", __func__));
     359           0 :                 tevent_req_nterror(req, NT_STATUS_GENERIC_NOT_MAPPED);
     360           0 :                 return;
     361             :         }
     362             : 
     363           0 :         tevent_req_done(req);
     364             : }
     365             : 
     366           0 : NTSTATUS roh_recv_out_channel_response_recv(struct tevent_req *req,
     367             :                 TALLOC_CTX *mem_ctx,
     368             :                 char **response_msg)
     369             : {
     370             :         NTSTATUS status;
     371             : 
     372           0 :         if (tevent_req_is_nterror(req, &status)) {
     373           0 :                 tevent_req_received(req);
     374           0 :                 return status;
     375             :         }
     376             : 
     377           0 :         tevent_req_received(req);
     378           0 :         return NT_STATUS_OK;
     379             : }
     380             : 
     381             : struct roh_recv_pdu_state {
     382             :         struct roh_connection   *roh;
     383             :         uint32_t                connection_timeout;
     384             :         uint32_t                version;
     385             :         uint32_t                recv_window_size;
     386             : };
     387             : 
     388             : static void roh_recv_CONN_A3_done(struct tevent_req *subreq);
     389           0 : struct tevent_req *roh_recv_CONN_A3_send(TALLOC_CTX *mem_ctx,
     390             :                                          struct tevent_context *ev,
     391             :                                          struct roh_connection *roh)
     392             : {
     393             :         struct tevent_req               *req;
     394             :         struct tevent_req               *subreq;
     395             :         struct roh_recv_pdu_state       *state;
     396           0 :         struct tstream_context          *stream = NULL;
     397             : 
     398           0 :         req = tevent_req_create(mem_ctx, &state, struct roh_recv_pdu_state);
     399           0 :         if (req == NULL) {
     400           0 :                 return NULL;
     401             :         }
     402             : 
     403           0 :         DEBUG(8, ("%s: Waiting for CONN/A3\n", __func__));
     404             : 
     405           0 :         stream = http_conn_tstream(roh->default_channel_out->http_conn);
     406             : 
     407           0 :         subreq = dcerpc_read_ncacn_packet_send(state, ev, stream);
     408           0 :         if (tevent_req_nomem(subreq, req)) {
     409           0 :                 return tevent_req_post(req, ev);
     410             :         }
     411           0 :         tevent_req_set_callback(subreq, roh_recv_CONN_A3_done, req);
     412             : 
     413           0 :         return req;
     414             : }
     415             : 
     416           0 : static void roh_recv_CONN_A3_done(struct tevent_req *subreq)
     417             : {
     418             :         NTSTATUS                        status;
     419             :         struct tevent_req               *req;
     420             :         struct roh_recv_pdu_state       *state;
     421             :         struct ncacn_packet             *pkt;
     422             :         DATA_BLOB                       buffer;
     423             :         struct dcerpc_rts               rts;
     424             : 
     425           0 :         req = tevent_req_callback_data(subreq, struct tevent_req);
     426           0 :         state = tevent_req_data(req, struct roh_recv_pdu_state);
     427           0 :         status = dcerpc_read_ncacn_packet_recv(subreq, state, &pkt, &buffer);
     428           0 :         TALLOC_FREE(subreq);
     429             : 
     430           0 :         if (tevent_req_nterror(req, status)) {
     431           0 :                 DEBUG(0, ("%s: Error receiving PDU\n", __func__));
     432           0 :                 return;
     433             :         }
     434             : 
     435             :         /*
     436             :          * Check if it is a CONN/A3 (2.2.4.4) packet and get the connection
     437             :          * timeout
     438             :          */
     439           0 :         rts = pkt->u.rts;
     440           0 :         if (rts.NumberOfCommands != 1) {
     441           0 :                 DEBUG(0, ("%s: Invalid number of commands received\n", __func__));
     442           0 :                 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
     443           0 :                 return;
     444             :         }
     445             : 
     446           0 :         if (rts.Commands[0].CommandType != ROH_CMD_TYPE_CONNECTION_TIMEOUT) {
     447           0 :                 DEBUG(0, ("%s: Invalid command type received\n", __func__));
     448           0 :                 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
     449           0 :                 return;
     450             :         }
     451             : 
     452             :         /* Extract connection timeout */
     453           0 :         state->connection_timeout = rts.Commands[0].Command.ConnectionTimeout.ConnectionTimeout;
     454             : 
     455           0 :         DEBUG(8, ("%s: CONN/A3 received, connection timeout is %u\n",
     456             :                   __func__, state->connection_timeout));
     457           0 :         tevent_req_done(req);
     458             : }
     459             : 
     460           0 : NTSTATUS roh_recv_CONN_A3_recv(struct tevent_req *req,
     461             :                                unsigned int *connection_timeout)
     462             : {
     463             :         NTSTATUS                        status;
     464             :         struct roh_recv_pdu_state       *state;
     465             : 
     466           0 :         state = tevent_req_data(req, struct roh_recv_pdu_state);
     467           0 :         if (tevent_req_is_nterror(req, &status)) {
     468           0 :                 tevent_req_received(req);
     469           0 :                 return status;
     470             :         }
     471             : 
     472           0 :         *connection_timeout = state->connection_timeout;
     473             : 
     474           0 :         tevent_req_received(req);
     475           0 :         return NT_STATUS_OK;
     476             : }
     477             : 
     478             : static void roh_recv_CONN_C2_done(struct tevent_req *subreq);
     479           0 : struct tevent_req *roh_recv_CONN_C2_send(TALLOC_CTX *mem_ctx,
     480             :                                          struct tevent_context *ev,
     481             :                                          struct roh_connection *roh)
     482             : {
     483             :         struct tevent_req               *req;
     484             :         struct tevent_req               *subreq;
     485             :         struct roh_recv_pdu_state       *state;
     486           0 :         struct tstream_context          *stream = NULL;
     487             : 
     488           0 :         req = tevent_req_create(mem_ctx, &state, struct roh_recv_pdu_state);
     489           0 :         if (req == NULL) {
     490           0 :                 return NULL;
     491             :         }
     492             : 
     493           0 :         DEBUG(8, ("%s: Waiting for CONN/C2\n", __func__));
     494           0 :         stream = http_conn_tstream(roh->default_channel_out->http_conn);
     495             : 
     496           0 :         subreq = dcerpc_read_ncacn_packet_send(state, ev, stream);
     497           0 :         if (tevent_req_nomem(subreq, req)) {
     498           0 :                 return tevent_req_post(req, ev);
     499             :         }
     500           0 :         tevent_req_set_callback(subreq, roh_recv_CONN_C2_done, req);
     501             : 
     502           0 :         return req;
     503             : }
     504             : 
     505           0 : static void roh_recv_CONN_C2_done(struct tevent_req *subreq)
     506             : {
     507             :         NTSTATUS                        status;
     508             :         struct tevent_req               *req;
     509             :         struct roh_recv_pdu_state       *state;
     510             :         struct ncacn_packet             *pkt;
     511             :         DATA_BLOB                       buffer;
     512             :         struct dcerpc_rts               rts;
     513             : 
     514           0 :         req = tevent_req_callback_data(subreq, struct tevent_req);
     515           0 :         state = tevent_req_data(req, struct roh_recv_pdu_state);
     516             : 
     517           0 :         status = dcerpc_read_ncacn_packet_recv(subreq, state, &pkt, &buffer);
     518           0 :         TALLOC_FREE(subreq);
     519           0 :         if (tevent_req_nterror(req, status)) {
     520           0 :                 DEBUG(0, ("%s: Error receiving PDU\n", __func__));
     521           0 :                 return;
     522             :         }
     523             : 
     524             :         /*
     525             :          * Check if it is a CONN/C2 packet (2.2.4.9), and get the version, the
     526             :          * receive windows size and the connection timeout for the IN channel
     527             :          */
     528           0 :         rts = pkt->u.rts;
     529           0 :         if (rts.NumberOfCommands != 3) {
     530           0 :                 DEBUG(0, ("%s: Invalid number of commands received\n",
     531             :                           __func__));
     532           0 :                 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
     533           0 :                 return;
     534             :         }
     535           0 :         if (rts.Commands[0].CommandType != ROH_CMD_TYPE_VERSION) {
     536           0 :                 DEBUG(0, ("%s: Invalid command type received\n", __func__));
     537           0 :                 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
     538           0 :                 return;
     539             :         }
     540           0 :         if (rts.Commands[1].CommandType != ROH_CMD_TYPE_RECV_WINDOWS_SIZE) {
     541           0 :                 DEBUG(0, ("%s: Invalid command type received\n", __func__));
     542           0 :                 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
     543           0 :                 return;
     544             :         }
     545           0 :         if (rts.Commands[2].CommandType != ROH_CMD_TYPE_CONNECTION_TIMEOUT) {
     546           0 :                 DEBUG(0, ("%s: Invalid command type received\n", __func__));
     547           0 :                 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
     548           0 :                 return;
     549             :         }
     550             : 
     551             :         /* Extract data */
     552           0 :         state->version = rts.Commands[0].Command.Version.Version;
     553           0 :         state->recv_window_size = rts.Commands[1].Command.ReceiveWindowSize.ReceiveWindowSize;
     554           0 :         state->connection_timeout = rts.Commands[2].Command.ConnectionTimeout.ConnectionTimeout;
     555             : 
     556           0 :         DEBUG(8, ("%s: CONN/C2 received, version is %u, receive windows size is %u, connection timeout is %u\n",
     557             :                   __func__, state->version, state->recv_window_size,
     558             :                   state->connection_timeout));
     559           0 :         tevent_req_done(req);
     560             : }
     561             : 
     562           0 : NTSTATUS roh_recv_CONN_C2_recv(struct tevent_req *req,
     563             :                                unsigned int *version,
     564             :                                unsigned int *recv_window_size,
     565             :                                unsigned int *connection_timeout)
     566             : {
     567             :         NTSTATUS                        status;
     568             :         struct roh_recv_pdu_state       *state;
     569             : 
     570           0 :         if (tevent_req_is_nterror(req, &status)) {
     571           0 :                 tevent_req_received(req);
     572           0 :                 return status;
     573             :         }
     574             : 
     575           0 :         state =  tevent_req_data(req, struct roh_recv_pdu_state);
     576           0 :         *version = state->version;
     577           0 :         *recv_window_size = state->recv_window_size;
     578           0 :         *connection_timeout = state->connection_timeout;
     579             : 
     580           0 :         tevent_req_received(req);
     581           0 :         return NT_STATUS_OK;
     582             : }

Generated by: LCOV version 1.13