LCOV - code coverage report
Current view: top level - source3/libsmb - clientgen.c (source / functions) Hit Total Coverage
Test: coverage report for master 2b515b7d Lines: 214 288 74.3 %
Date: 2024-02-28 12:06:22 Functions: 26 28 92.9 %

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

Generated by: LCOV version 1.14