LCOV - code coverage report
Current view: top level - source3/libsmb - clientgen.c (source / functions) Hit Total Coverage
Test: coverage report for recycleplus df22b230 Lines: 189 273 69.2 %
Date: 2024-02-14 10:14:15 Functions: 23 27 85.2 %

          Line data    Source code
       1             : /* 
       2             :    Unix SMB/CIFS implementation.
       3             :    SMB client generic functions
       4             :    Copyright (C) Andrew Tridgell 1994-1998
       5             :    Copyright (C) Jeremy Allison 2007.
       6             :    
       7             :    This program is free software; you can redistribute it and/or modify
       8             :    it under the terms of the GNU General Public License as published by
       9             :    the Free Software Foundation; either version 3 of the License, or
      10             :    (at your option) any later version.
      11             :    
      12             :    This program is distributed in the hope that it will be useful,
      13             :    but WITHOUT ANY WARRANTY; without even the implied warranty of
      14             :    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      15             :    GNU General Public License for more details.
      16             :    
      17             :    You should have received a copy of the GNU General Public License
      18             :    along with this program.  If not, see <http://www.gnu.org/licenses/>.
      19             : */
      20             : 
      21             : #include "includes.h"
      22             : #include "libsmb/libsmb.h"
      23             : #include "../lib/util/tevent_ntstatus.h"
      24             : #include "../libcli/smb/smb_signing.h"
      25             : #include "../libcli/smb/smb_seal.h"
      26             : #include "async_smb.h"
      27             : #include "../libcli/smb/smbXcli_base.h"
      28             : #include "../libcli/smb/smb2_negotiate_context.h"
      29             : #include "../librpc/ndr/libndr.h"
      30             : #include "../include/client.h"
      31             : 
      32             : /****************************************************************************
      33             :  Change the timeout (in milliseconds).
      34             : ****************************************************************************/
      35             : 
      36        1702 : unsigned int cli_set_timeout(struct cli_state *cli, unsigned int timeout)
      37             : {
      38        1702 :         unsigned int old_timeout = cli->timeout;
      39        1702 :         cli->timeout = timeout;
      40        1702 :         return old_timeout;
      41             : }
      42             : 
      43             : /****************************************************************************
      44             :  Set the 'backup_intent' flag.
      45             : ****************************************************************************/
      46             : 
      47           4 : bool cli_set_backup_intent(struct cli_state *cli, bool flag)
      48             : {
      49           4 :         bool old_state = cli->backup_intent;
      50           4 :         cli->backup_intent = flag;
      51           4 :         return old_state;
      52             : }
      53             : 
      54             : /****************************************************************************
      55             :  Initialise a client structure. Always returns a talloc'ed struct.
      56             :  Set the signing state (used from the command line).
      57             : ****************************************************************************/
      58             : 
      59             : struct GUID cli_state_client_guid;
      60             : 
      61        2489 : struct cli_state *cli_state_create(TALLOC_CTX *mem_ctx,
      62             :                                    int fd,
      63             :                                    const char *remote_name,
      64             :                                    int signing_state, int flags)
      65             : {
      66        2489 :         struct cli_state *cli = NULL;
      67        2489 :         bool use_spnego = lp_client_use_spnego();
      68        2489 :         bool force_dos_errors = false;
      69        2489 :         bool force_ascii = false;
      70        2489 :         bool use_level_II_oplocks = false;
      71        2489 :         uint32_t smb1_capabilities = 0;
      72        2489 :         uint32_t smb2_capabilities = 0;
      73             :         struct smb311_capabilities smb3_capabilities =
      74        2489 :                 smb311_capabilities_parse("client",
      75        2489 :                         lp_client_smb3_signing_algorithms(),
      76        2489 :                         lp_client_smb3_encryption_algorithms());
      77             :         struct GUID client_guid;
      78             : 
      79        2489 :         if (!GUID_all_zero(&cli_state_client_guid)) {
      80           0 :                 client_guid = cli_state_client_guid;
      81             :         } else {
      82        2489 :                 const char *str = NULL;
      83             : 
      84        2489 :                 str = lp_parm_const_string(-1, "libsmb", "client_guid", NULL);
      85        2489 :                 if (str != NULL) {
      86           0 :                         GUID_from_string(str, &client_guid);
      87             :                 } else {
      88        2489 :                         client_guid = GUID_random();
      89             :                 }
      90             :         }
      91             : 
      92             :         /* Check the effective uid - make sure we are not setuid */
      93        2489 :         if (is_setuid_root()) {
      94           0 :                 DEBUG(0,("libsmb based programs must *NOT* be setuid root.\n"));
      95           0 :                 return NULL;
      96             :         }
      97             : 
      98        2489 :         cli = talloc_zero(mem_ctx, struct cli_state);
      99        2489 :         if (!cli) {
     100           0 :                 return NULL;
     101             :         }
     102             : 
     103        2489 :         cli->server_domain = talloc_strdup(cli, "");
     104        2489 :         if (!cli->server_domain) {
     105           0 :                 goto error;
     106             :         }
     107        2489 :         cli->server_os = talloc_strdup(cli, "");
     108        2489 :         if (!cli->server_os) {
     109           0 :                 goto error;
     110             :         }
     111        2489 :         cli->server_type = talloc_strdup(cli, "");
     112        2489 :         if (!cli->server_type) {
     113           0 :                 goto error;
     114             :         }
     115             : 
     116        2489 :         cli->raw_status = NT_STATUS_INTERNAL_ERROR;
     117        2489 :         cli->map_dos_errors = true; /* remove this */
     118        2489 :         cli->timeout = CLIENT_TIMEOUT;
     119             : 
     120             :         /* Set the CLI_FORCE_DOSERR environment variable to test
     121             :            client routines using DOS errors instead of STATUS32
     122             :            ones.  This intended only as a temporary hack. */    
     123        2489 :         if (getenv("CLI_FORCE_DOSERR")) {
     124           0 :                 force_dos_errors = true;
     125             :         }
     126        2489 :         if (flags & CLI_FULL_CONNECTION_FORCE_DOS_ERRORS) {
     127           0 :                 force_dos_errors = true;
     128             :         }
     129             : 
     130        2489 :         if (getenv("CLI_FORCE_ASCII")) {
     131           0 :                 force_ascii = true;
     132             :         }
     133        2489 :         if (!lp_unicode()) {
     134           0 :                 force_ascii = true;
     135             :         }
     136        2489 :         if (flags & CLI_FULL_CONNECTION_FORCE_ASCII) {
     137           0 :                 force_ascii = true;
     138             :         }
     139             : 
     140        2489 :         if (flags & CLI_FULL_CONNECTION_DONT_SPNEGO) {
     141           0 :                 use_spnego = false;
     142             :         }
     143             : 
     144        2489 :         if (flags & CLI_FULL_CONNECTION_OPLOCKS) {
     145           0 :                 cli->use_oplocks = true;
     146             :         }
     147        2489 :         if (flags & CLI_FULL_CONNECTION_LEVEL_II_OPLOCKS) {
     148           0 :                 use_level_II_oplocks = true;
     149             :         }
     150             : 
     151        2489 :         if (signing_state == SMB_SIGNING_IPC_DEFAULT) {
     152             :                 /*
     153             :                  * Ensure for IPC/RPC the default is to require
     154             :                  * signing unless explicitly turned off by the
     155             :                  * administrator.
     156             :                  */
     157           3 :                 signing_state = lp_client_ipc_signing();
     158             :         }
     159             : 
     160        2489 :         if (signing_state == SMB_SIGNING_DEFAULT) {
     161        1207 :                 signing_state = lp_client_signing();
     162             :         }
     163             : 
     164        2489 :         smb1_capabilities = 0;
     165        2489 :         smb1_capabilities |= CAP_LARGE_FILES;
     166        2489 :         smb1_capabilities |= CAP_NT_SMBS | CAP_RPC_REMOTE_APIS;
     167        2489 :         smb1_capabilities |= CAP_LOCK_AND_READ | CAP_NT_FIND;
     168        2489 :         smb1_capabilities |= CAP_DFS | CAP_W2K_SMBS;
     169        2489 :         smb1_capabilities |= CAP_LARGE_READX|CAP_LARGE_WRITEX;
     170        2489 :         smb1_capabilities |= CAP_LWIO;
     171             : 
     172        2489 :         if (!force_dos_errors) {
     173        2489 :                 smb1_capabilities |= CAP_STATUS32;
     174             :         }
     175             : 
     176        2489 :         if (!force_ascii) {
     177        2489 :                 smb1_capabilities |= CAP_UNICODE;
     178             :         }
     179             : 
     180        2489 :         if (use_spnego) {
     181        2428 :                 smb1_capabilities |= CAP_EXTENDED_SECURITY;
     182             :         }
     183             : 
     184        2489 :         if (use_level_II_oplocks) {
     185           0 :                 smb1_capabilities |= CAP_LEVEL_II_OPLOCKS;
     186             :         }
     187             : 
     188        2489 :         smb2_capabilities = SMB2_CAP_ALL;
     189             : 
     190        2489 :         cli->conn = smbXcli_conn_create(cli, fd, remote_name,
     191             :                                         signing_state,
     192             :                                         smb1_capabilities,
     193             :                                         &client_guid,
     194             :                                         smb2_capabilities,
     195             :                                         &smb3_capabilities);
     196        2489 :         if (cli->conn == NULL) {
     197           0 :                 goto error;
     198             :         }
     199             : 
     200        2489 :         cli->smb1.pid = (uint32_t)getpid();
     201        2489 :         cli->smb1.vc_num = cli->smb1.pid;
     202        2489 :         cli->smb1.session = smbXcli_session_create(cli, cli->conn);
     203        2489 :         if (cli->smb1.session == NULL) {
     204           0 :                 goto error;
     205             :         }
     206             : 
     207        2489 :         cli->initialised = 1;
     208        2489 :         return cli;
     209             : 
     210             :         /* Clean up after malloc() error */
     211             : 
     212           0 :  error:
     213             : 
     214           0 :         TALLOC_FREE(cli);
     215           0 :         return NULL;
     216             : }
     217             : 
     218             : /****************************************************************************
     219             :  Close all pipes open on this session.
     220             : ****************************************************************************/
     221             : 
     222        2367 : static void cli_nt_pipes_close(struct cli_state *cli)
     223             : {
     224        2642 :         while (cli->pipe_list != NULL) {
     225             :                 /*
     226             :                  * No TALLOC_FREE here!
     227             :                  */
     228         275 :                 talloc_free(cli->pipe_list);
     229             :         }
     230        2367 : }
     231             : 
     232             : /****************************************************************************
     233             :  Shutdown a client structure.
     234             : ****************************************************************************/
     235             : 
     236        2367 : static void _cli_shutdown(struct cli_state *cli)
     237             : {
     238        2367 :         cli_nt_pipes_close(cli);
     239             : 
     240             :         /*
     241             :          * tell our peer to free his resources.  Without this, when an
     242             :          * application attempts to do a graceful shutdown and calls
     243             :          * smbc_free_context() to clean up all connections, some connections
     244             :          * can remain active on the peer end, until some (long) timeout period
     245             :          * later.  This tree disconnect forces the peer to clean up, since the
     246             :          * connection will be going away.
     247             :          */
     248        2367 :         if (cli_state_has_tcon(cli)) {
     249        1990 :                 cli_tdis(cli);
     250             :         }
     251             : 
     252        2367 :         smbXcli_conn_disconnect(cli->conn, NT_STATUS_OK);
     253             : 
     254        2367 :         TALLOC_FREE(cli);
     255        2367 : }
     256             : 
     257        2367 : void cli_shutdown(struct cli_state *cli)
     258             : {
     259             :         struct cli_state *cli_head;
     260        2367 :         if (cli == NULL) {
     261           0 :                 return;
     262             :         }
     263        2441 :         DLIST_HEAD(cli, cli_head);
     264        2367 :         if (cli_head == cli) {
     265             :                 /*
     266             :                  * head of a DFS list, shutdown all subsidiary DFS
     267             :                  * connections.
     268             :                  */
     269             :                 struct cli_state *p, *next;
     270             : 
     271        2347 :                 for (p = cli_head->next; p; p = next) {
     272           0 :                         next = p->next;
     273           0 :                         DLIST_REMOVE(cli_head, p);
     274           0 :                         _cli_shutdown(p);
     275             :                 }
     276             :         } else {
     277          20 :                 DLIST_REMOVE(cli_head, cli);
     278             :         }
     279             : 
     280        2367 :         _cli_shutdown(cli);
     281             : }
     282             : 
     283         178 : uint16_t cli_state_get_vc_num(struct cli_state *cli)
     284             : {
     285         178 :         return cli->smb1.vc_num;
     286             : }
     287             : 
     288             : /****************************************************************************
     289             :  Set the PID to use for smb messages. Return the old pid.
     290             : ****************************************************************************/
     291             : 
     292          17 : uint32_t cli_setpid(struct cli_state *cli, uint32_t pid)
     293             : {
     294          17 :         uint32_t ret = cli->smb1.pid;
     295          17 :         cli->smb1.pid = pid;
     296          17 :         return ret;
     297             : }
     298             : 
     299         894 : uint32_t cli_getpid(struct cli_state *cli)
     300             : {
     301         894 :         return cli->smb1.pid;
     302             : }
     303             : 
     304           0 : bool cli_state_is_encryption_on(struct cli_state *cli)
     305             : {
     306           0 :         if (smbXcli_conn_protocol(cli->conn) < PROTOCOL_SMB2_02) {
     307           0 :                 return smb1cli_conn_encryption_on(cli->conn);
     308             :         }
     309             : 
     310           0 :         if (cli->smb2.tcon == NULL) {
     311           0 :                 return false;
     312             :         }
     313             : 
     314           0 :         return smb2cli_tcon_is_encryption_on(cli->smb2.tcon);
     315             : }
     316             : 
     317        3192 : bool cli_state_has_tcon(struct cli_state *cli)
     318             : {
     319             :         uint32_t tid;
     320        3192 :         if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
     321        2924 :                 if (cli->smb2.tcon == NULL) {
     322         959 :                         return false;
     323             :                 }
     324        1965 :                 tid = cli_state_get_tid(cli);
     325        1965 :                 if (tid == UINT32_MAX) {
     326           0 :                         return false;
     327             :                 }
     328             :         } else {
     329         268 :                 if (cli->smb1.tcon == NULL) {
     330         242 :                         return false;
     331             :                 }
     332          26 :                 tid = cli_state_get_tid(cli);
     333          26 :                 if (tid == UINT16_MAX) {
     334           1 :                         return false;
     335             :                 }
     336             :         }
     337        1990 :         return true;
     338             : }
     339             : 
     340        1996 : uint32_t cli_state_get_tid(struct cli_state *cli)
     341             : {
     342        1996 :         if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
     343        1965 :                 return smb2cli_tcon_current_id(cli->smb2.tcon);
     344             :         } else {
     345          31 :                 return (uint32_t)smb1cli_tcon_current_id(cli->smb1.tcon);
     346             :         }
     347             : }
     348             : 
     349          10 : uint32_t cli_state_set_tid(struct cli_state *cli, uint32_t tid)
     350             : {
     351             :         uint32_t ret;
     352          10 :         if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
     353           0 :                 ret = smb2cli_tcon_current_id(cli->smb2.tcon);
     354           0 :                 smb2cli_tcon_set_id(cli->smb2.tcon, tid);
     355             :         } else {
     356          10 :                 ret = smb1cli_tcon_current_id(cli->smb1.tcon);
     357          10 :                 smb1cli_tcon_set_id(cli->smb1.tcon, tid);
     358             :         }
     359          10 :         return ret;
     360             : }
     361             : 
     362           2 : static struct smbXcli_tcon *cli_state_save_tcon(struct cli_state *cli)
     363             : {
     364             :         /*
     365             :          * Note. This used to make a deep copy of either
     366             :          * cli->smb2.tcon or cli->smb1.tcon, but this leaves
     367             :          * the original pointer in place which will then get
     368             :          * TALLOC_FREE()'d when the new connection is made on
     369             :          * this cli_state.
     370             :          *
     371             :          * As there may be pipes open on the old connection with
     372             :          * talloc'ed state allocated using the tcon pointer as a
     373             :          * parent we can't deep copy and then free this as that
     374             :          * closes the open pipes.
     375             :          *
     376             :          * This call is used to temporarily swap out a tcon pointer
     377             :          * to allow a new tcon on the same cli_state.
     378             :          *
     379             :          * Just return the raw pointer and set the old value to NULL.
     380             :          * We know we MUST be calling cli_state_restore_tcon() below
     381             :          * to restore before closing the session.
     382             :          *
     383             :          * See BUG: https://bugzilla.samba.org/show_bug.cgi?id=13992
     384             :          */
     385           2 :         struct smbXcli_tcon *tcon_ret = NULL;
     386             : 
     387           2 :         if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
     388           1 :                 tcon_ret = cli->smb2.tcon;
     389           1 :                 cli->smb2.tcon = NULL; /* *Not* TALLOC_FREE(). */
     390             :         } else {
     391           1 :                 tcon_ret = cli->smb1.tcon;
     392           1 :                 cli->smb1.tcon = NULL; /* *Not* TALLOC_FREE(). */
     393             :         }
     394           2 :         return tcon_ret;
     395             : }
     396             : 
     397           2 : void cli_state_save_tcon_share(struct cli_state *cli,
     398             :                                struct smbXcli_tcon **_tcon_ret,
     399             :                                char **_sharename_ret)
     400             : {
     401           2 :         *_tcon_ret = cli_state_save_tcon(cli);
     402             :         /*
     403             :          * No talloc_copy as cli->share is already
     404             :          * allocated off cli.
     405             :          */
     406           2 :         *_sharename_ret = cli->share;
     407           2 :         cli->share = NULL;
     408           2 : }
     409             : 
     410         827 : static void cli_state_restore_tcon(struct cli_state *cli,
     411             :                                    struct smbXcli_tcon *tcon)
     412             : {
     413         827 :         if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
     414         826 :                 TALLOC_FREE(cli->smb2.tcon);
     415         826 :                 cli->smb2.tcon = tcon;
     416             :         } else {
     417           1 :                 TALLOC_FREE(cli->smb1.tcon);
     418           1 :                 cli->smb1.tcon = tcon;
     419             :         }
     420         827 : }
     421             : 
     422         827 : void cli_state_restore_tcon_share(struct cli_state *cli,
     423             :                                   struct smbXcli_tcon *tcon,
     424             :                                   char *share)
     425             : {
     426             :         /* cli->share will have been replaced by a cli_tree_connect() call. */
     427         827 :         TALLOC_FREE(cli->share);
     428         827 :         cli->share = share;
     429         827 :         cli_state_restore_tcon(cli, tcon);
     430         827 : }
     431             : 
     432           6 : uint16_t cli_state_get_uid(struct cli_state *cli)
     433             : {
     434           6 :         return smb1cli_session_current_id(cli->smb1.session);
     435             : }
     436             : 
     437         308 : uint16_t cli_state_set_uid(struct cli_state *cli, uint16_t uid)
     438             : {
     439         308 :         uint16_t ret = smb1cli_session_current_id(cli->smb1.session);
     440         308 :         smb1cli_session_set_id(cli->smb1.session, uid);
     441         308 :         return ret;
     442             : }
     443             : 
     444             : /****************************************************************************
     445             :  Set the case sensitivity flag on the packets. Returns old state.
     446             : ****************************************************************************/
     447             : 
     448           0 : bool cli_set_case_sensitive(struct cli_state *cli, bool case_sensitive)
     449             : {
     450             :         bool ret;
     451             :         uint32_t fs_attrs;
     452             :         struct smbXcli_tcon *tcon;
     453             : 
     454           0 :         if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
     455           0 :                 tcon = cli->smb2.tcon;
     456             :         } else {
     457           0 :                 tcon = cli->smb1.tcon;
     458             :         }
     459             : 
     460           0 :         fs_attrs = smbXcli_tcon_get_fs_attributes(tcon);
     461           0 :         if (fs_attrs & FILE_CASE_SENSITIVE_SEARCH) {
     462           0 :                 ret = true;
     463             :         } else {
     464           0 :                 ret = false;
     465             :         }
     466           0 :         if (case_sensitive) {
     467           0 :                 fs_attrs |= FILE_CASE_SENSITIVE_SEARCH;
     468             :         } else {
     469           0 :                 fs_attrs &= ~FILE_CASE_SENSITIVE_SEARCH;
     470             :         }
     471           0 :         smbXcli_tcon_set_fs_attributes(tcon, fs_attrs);
     472             : 
     473           0 :         return ret;
     474             : }
     475             : 
     476        1657 : uint32_t cli_state_available_size(struct cli_state *cli, uint32_t ofs)
     477             : {
     478        1657 :         uint32_t ret = smb1cli_conn_max_xmit(cli->conn);
     479             : 
     480        1657 :         if (ofs >= ret) {
     481           0 :                 return 0;
     482             :         }
     483             : 
     484        1657 :         ret -= ofs;
     485             : 
     486        1657 :         return ret;
     487             : }
     488             : 
     489           0 : time_t cli_state_server_time(struct cli_state *cli)
     490             : {
     491             :         NTTIME nt;
     492             :         time_t t;
     493             : 
     494           0 :         nt = smbXcli_conn_server_system_time(cli->conn);
     495           0 :         t = nt_time_to_unix(nt);
     496             : 
     497           0 :         return t;
     498             : }
     499             : 
     500             : struct cli_echo_state {
     501             :         bool is_smb2;
     502             : };
     503             : 
     504             : static void cli_echo_done(struct tevent_req *subreq);
     505             : 
     506          48 : struct tevent_req *cli_echo_send(TALLOC_CTX *mem_ctx, struct tevent_context *ev,
     507             :                                  struct cli_state *cli, uint16_t num_echos,
     508             :                                  DATA_BLOB data)
     509             : {
     510             :         struct tevent_req *req, *subreq;
     511             :         struct cli_echo_state *state;
     512             : 
     513          48 :         req = tevent_req_create(mem_ctx, &state, struct cli_echo_state);
     514          48 :         if (req == NULL) {
     515           0 :                 return NULL;
     516             :         }
     517             : 
     518          48 :         if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
     519          48 :                 state->is_smb2 = true;
     520          48 :                 subreq = smb2cli_echo_send(state, ev,
     521             :                                            cli->conn,
     522          48 :                                            cli->timeout);
     523             :         } else {
     524           0 :                 subreq = smb1cli_echo_send(state, ev,
     525             :                                            cli->conn,
     526           0 :                                            cli->timeout,
     527             :                                            num_echos,
     528             :                                            data);
     529             :         }
     530          48 :         if (tevent_req_nomem(subreq, req)) {
     531           0 :                 return tevent_req_post(req, ev);
     532             :         }
     533          48 :         tevent_req_set_callback(subreq, cli_echo_done, req);
     534             : 
     535          48 :         return req;
     536             : }
     537             : 
     538          48 : static void cli_echo_done(struct tevent_req *subreq)
     539             : {
     540          48 :         struct tevent_req *req = tevent_req_callback_data(
     541             :                 subreq, struct tevent_req);
     542          48 :         struct cli_echo_state *state = tevent_req_data(
     543             :                 req, struct cli_echo_state);
     544             :         NTSTATUS status;
     545             : 
     546          48 :         if (state->is_smb2) {
     547          48 :                 status = smb2cli_echo_recv(subreq);
     548             :         } else {
     549           0 :                 status = smb1cli_echo_recv(subreq);
     550             :         }
     551          48 :         TALLOC_FREE(subreq);
     552          48 :         if (!NT_STATUS_IS_OK(status)) {
     553           0 :                 tevent_req_nterror(req, status);
     554           0 :                 return;
     555             :         }
     556             : 
     557          48 :         tevent_req_done(req);
     558             : }
     559             : 
     560             : /**
     561             :  * Get the result out from an echo request
     562             :  * @param[in] req       The async_req from cli_echo_send
     563             :  * @retval Did the server reply correctly?
     564             :  */
     565             : 
     566          48 : NTSTATUS cli_echo_recv(struct tevent_req *req)
     567             : {
     568          48 :         return tevent_req_simple_recv_ntstatus(req);
     569             : }
     570             : 
     571             : /**
     572             :  * @brief Send/Receive SMBEcho requests
     573             :  * @param[in] mem_ctx   The memory context to put the async_req on
     574             :  * @param[in] ev        The event context that will call us back
     575             :  * @param[in] cli       The connection to send the echo to
     576             :  * @param[in] num_echos How many times do we want to get the reply?
     577             :  * @param[in] data      The data we want to get back
     578             :  * @retval Did the server reply correctly?
     579             :  */
     580             : 
     581           0 : NTSTATUS cli_echo(struct cli_state *cli, uint16_t num_echos, DATA_BLOB data)
     582             : {
     583           0 :         TALLOC_CTX *frame = talloc_stackframe();
     584             :         struct tevent_context *ev;
     585             :         struct tevent_req *req;
     586           0 :         NTSTATUS status = NT_STATUS_OK;
     587             : 
     588           0 :         if (smbXcli_conn_has_async_calls(cli->conn)) {
     589             :                 /*
     590             :                  * Can't use sync call while an async call is in flight
     591             :                  */
     592           0 :                 status = NT_STATUS_INVALID_PARAMETER;
     593           0 :                 goto fail;
     594             :         }
     595             : 
     596           0 :         ev = samba_tevent_context_init(frame);
     597           0 :         if (ev == NULL) {
     598           0 :                 status = NT_STATUS_NO_MEMORY;
     599           0 :                 goto fail;
     600             :         }
     601             : 
     602           0 :         req = cli_echo_send(frame, ev, cli, num_echos, data);
     603           0 :         if (req == NULL) {
     604           0 :                 status = NT_STATUS_NO_MEMORY;
     605           0 :                 goto fail;
     606             :         }
     607             : 
     608           0 :         if (!tevent_req_poll_ntstatus(req, ev, &status)) {
     609           0 :                 goto fail;
     610             :         }
     611             : 
     612           0 :         status = cli_echo_recv(req);
     613           0 :  fail:
     614           0 :         TALLOC_FREE(frame);
     615           0 :         return status;
     616             : }
     617             : 
     618       65548 : NTSTATUS cli_smb(TALLOC_CTX *mem_ctx, struct cli_state *cli,
     619             :                  uint8_t smb_command, uint8_t additional_flags,
     620             :                  uint8_t wct, uint16_t *vwv,
     621             :                  uint32_t num_bytes, const uint8_t *bytes,
     622             :                  struct tevent_req **result_parent,
     623             :                  uint8_t min_wct, uint8_t *pwct, uint16_t **pvwv,
     624             :                  uint32_t *pnum_bytes, uint8_t **pbytes)
     625             : {
     626             :         struct tevent_context *ev;
     627       65548 :         struct tevent_req *req = NULL;
     628       65548 :         NTSTATUS status = NT_STATUS_NO_MEMORY;
     629             : 
     630       65548 :         if (smbXcli_conn_has_async_calls(cli->conn)) {
     631           0 :                 return NT_STATUS_INVALID_PARAMETER;
     632             :         }
     633       65548 :         ev = samba_tevent_context_init(mem_ctx);
     634       65548 :         if (ev == NULL) {
     635           0 :                 goto fail;
     636             :         }
     637       65548 :         req = cli_smb_send(mem_ctx, ev, cli, smb_command, additional_flags, 0,
     638             :                            wct, vwv, num_bytes, bytes);
     639       65548 :         if (req == NULL) {
     640           0 :                 goto fail;
     641             :         }
     642       65548 :         if (!tevent_req_poll_ntstatus(req, ev, &status)) {
     643           0 :                 goto fail;
     644             :         }
     645       65548 :         status = cli_smb_recv(req, NULL, NULL, min_wct, pwct, pvwv,
     646             :                               pnum_bytes, pbytes);
     647       65548 : fail:
     648       65548 :         TALLOC_FREE(ev);
     649       65548 :         if (NT_STATUS_IS_OK(status) && (result_parent != NULL)) {
     650           9 :                 *result_parent = req;
     651             :         }
     652       65548 :         return status;
     653             : }

Generated by: LCOV version 1.14