LCOV - code coverage report
Current view: top level - libcli/smb - smb2cli_tcon.c (source / functions) Hit Total Coverage
Test: coverage report for master 2f515e9b Lines: 150 206 72.8 %
Date: 2024-04-21 15:09:00 Functions: 12 13 92.3 %

          Line data    Source code
       1             : /*
       2             :    Unix SMB/CIFS implementation.
       3             :    smb2 lib
       4             :    Copyright (C) Volker Lendecke 2011
       5             : 
       6             :    This program is free software; you can redistribute it and/or modify
       7             :    it under the terms of the GNU General Public License as published by
       8             :    the Free Software Foundation; either version 3 of the License, or
       9             :    (at your option) any later version.
      10             : 
      11             :    This program is distributed in the hope that it will be useful,
      12             :    but WITHOUT ANY WARRANTY; without even the implied warranty of
      13             :    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      14             :    GNU General Public License for more details.
      15             : 
      16             :    You should have received a copy of the GNU General Public License
      17             :    along with this program.  If not, see <http://www.gnu.org/licenses/>.
      18             : */
      19             : 
      20             : #include "includes.h"
      21             : #include "system/network.h"
      22             : #include "../lib/util/tevent_ntstatus.h"
      23             : #include "../libcli/smb/smb_common.h"
      24             : #include "../libcli/smb/smbXcli_base.h"
      25             : 
      26             : struct smb2cli_raw_tcon_state {
      27             :         struct smbXcli_session *session;
      28             :         struct smbXcli_tcon *tcon;
      29             :         uint8_t fixed[8];
      30             :         uint8_t dyn_pad[1];
      31             : };
      32             : 
      33             : static void smb2cli_raw_tcon_done(struct tevent_req *subreq);
      34             : 
      35       41008 : struct tevent_req *smb2cli_raw_tcon_send(TALLOC_CTX *mem_ctx,
      36             :                                          struct tevent_context *ev,
      37             :                                          struct smbXcli_conn *conn,
      38             :                                          uint32_t additional_flags,
      39             :                                          uint32_t clear_flags,
      40             :                                          uint32_t timeout_msec,
      41             :                                          struct smbXcli_session *session,
      42             :                                          struct smbXcli_tcon *tcon,
      43             :                                          uint16_t tcon_flags,
      44             :                                          const char *unc)
      45             : {
      46       41008 :         struct tevent_req *req = NULL;
      47       41008 :         struct smb2cli_raw_tcon_state *state = NULL;
      48       41008 :         struct tevent_req *subreq = NULL;
      49       41008 :         uint8_t *fixed = NULL;
      50       41008 :         uint8_t *dyn = NULL;
      51         623 :         size_t dyn_len;
      52             : 
      53       41008 :         req = tevent_req_create(mem_ctx, &state,
      54             :                                 struct smb2cli_raw_tcon_state);
      55       41008 :         if (req == NULL) {
      56           0 :                 return NULL;
      57             :         }
      58       41008 :         state->session = session;
      59       41008 :         state->tcon = tcon;
      60             : 
      61       41008 :         if (!convert_string_talloc(state, CH_UNIX, CH_UTF16,
      62             :                                    unc, strlen(unc),
      63             :                                    &dyn, &dyn_len)) {
      64           0 :                 tevent_req_oom(req);
      65           0 :                 return tevent_req_post(req, ev);
      66             :         }
      67             : 
      68       41008 :         if (strlen(unc) == 0) {
      69           0 :                 TALLOC_FREE(dyn);
      70           0 :                 dyn_len = 0;
      71             :         }
      72             : 
      73       41008 :         fixed = state->fixed;
      74       41008 :         SSVAL(fixed, 0, 9);
      75       41008 :         if (smbXcli_conn_protocol(conn) >= PROTOCOL_SMB3_11) {
      76       36638 :                 SSVAL(fixed, 2, tcon_flags);
      77             :         } else {
      78        4370 :                 SSVAL(fixed, 2, 0); /* Reserved */
      79             :         }
      80       41008 :         SSVAL(fixed, 4, SMB2_HDR_BODY + 8);
      81       41008 :         SSVAL(fixed, 6, dyn_len);
      82             : 
      83       41008 :         if (dyn_len == 0) {
      84           0 :                 dyn = state->dyn_pad;
      85           0 :                 dyn_len = sizeof(state->dyn_pad);
      86             :         }
      87             : 
      88       41631 :         subreq = smb2cli_req_send(state, ev, conn, SMB2_OP_TCON,
      89             :                                   additional_flags, clear_flags,
      90             :                                   timeout_msec,
      91             :                                   NULL, /* tcon */
      92             :                                   session,
      93       41008 :                                   state->fixed, sizeof(state->fixed),
      94             :                                   dyn, dyn_len,
      95             :                                   0); /* max_dyn_len */
      96       41008 :         if (tevent_req_nomem(subreq, req)) {
      97           0 :                 return tevent_req_post(req, ev);
      98             :         }
      99       41008 :         tevent_req_set_callback(subreq, smb2cli_raw_tcon_done, req);
     100             : 
     101       41008 :         return req;
     102             : }
     103             : 
     104       41008 : static void smb2cli_raw_tcon_done(struct tevent_req *subreq)
     105             : {
     106       41008 :         struct tevent_req *req = tevent_req_callback_data(
     107             :                 subreq, struct tevent_req);
     108       41008 :         struct smb2cli_raw_tcon_state *state = tevent_req_data(
     109             :                 req, struct smb2cli_raw_tcon_state);
     110         623 :         NTSTATUS status;
     111         623 :         struct iovec *iov;
     112         623 :         uint8_t *body;
     113         623 :         uint32_t tcon_id;
     114         623 :         uint8_t share_type;
     115         623 :         uint32_t share_flags;
     116         623 :         uint32_t share_capabilities;
     117         623 :         uint32_t maximal_access;
     118         623 :         static const struct smb2cli_req_expected_response expected[] = {
     119             :         {
     120             :                 .status = NT_STATUS_OK,
     121             :                 .body_size = 0x10
     122             :         }
     123             :         };
     124             : 
     125       41008 :         status = smb2cli_req_recv(subreq, state, &iov,
     126             :                                   expected, ARRAY_SIZE(expected));
     127       41008 :         TALLOC_FREE(subreq);
     128       41008 :         if (!NT_STATUS_IS_OK(status)) {
     129         120 :                 tevent_req_nterror(req, status);
     130         120 :                 return;
     131             :         }
     132             : 
     133       40888 :         tcon_id = IVAL(iov[0].iov_base, SMB2_HDR_TID);
     134             : 
     135       40888 :         body = (uint8_t *)iov[1].iov_base;
     136       40888 :         share_type              = CVAL(body, 0x02);
     137       40888 :         share_flags             = IVAL(body, 0x04);
     138       40888 :         share_capabilities      = IVAL(body, 0x08);
     139       40888 :         maximal_access          = IVAL(body, 0x0C);
     140             : 
     141       40888 :         smb2cli_tcon_set_values(state->tcon,
     142             :                                 state->session,
     143             :                                 tcon_id,
     144             :                                 share_type,
     145             :                                 share_flags,
     146             :                                 share_capabilities,
     147             :                                 maximal_access);
     148             : 
     149       40888 :         tevent_req_done(req);
     150             : }
     151             : 
     152       41008 : NTSTATUS smb2cli_raw_tcon_recv(struct tevent_req *req)
     153             : {
     154       41008 :         return tevent_req_simple_recv_ntstatus(req);
     155             : }
     156             : 
     157          16 : NTSTATUS smb2cli_raw_tcon(struct smbXcli_conn *conn,
     158             :                           uint32_t additional_flags,
     159             :                           uint32_t clear_flags,
     160             :                           uint32_t timeout_msec,
     161             :                           struct smbXcli_session *session,
     162             :                           struct smbXcli_tcon *tcon,
     163             :                           uint16_t tcon_flags,
     164             :                           const char *unc)
     165             : {
     166          16 :         TALLOC_CTX *frame = talloc_stackframe();
     167           0 :         struct tevent_context *ev;
     168           0 :         struct tevent_req *req;
     169          16 :         NTSTATUS status = NT_STATUS_NO_MEMORY;
     170             : 
     171          16 :         if (smbXcli_conn_has_async_calls(conn)) {
     172             :                 /*
     173             :                  * Can't use sync call while an async call is in flight
     174             :                  */
     175           0 :                 status = NT_STATUS_INVALID_PARAMETER;
     176           0 :                 goto fail;
     177             :         }
     178          16 :         ev = samba_tevent_context_init(frame);
     179          16 :         if (ev == NULL) {
     180           0 :                 goto fail;
     181             :         }
     182          16 :         req = smb2cli_raw_tcon_send(frame, ev, conn,
     183             :                                     additional_flags, clear_flags,
     184             :                                     timeout_msec, session, tcon,
     185             :                                     tcon_flags, unc);
     186          16 :         if (req == NULL) {
     187           0 :                 goto fail;
     188             :         }
     189          16 :         if (!tevent_req_poll_ntstatus(req, ev, &status)) {
     190           0 :                 goto fail;
     191             :         }
     192          16 :         status = smb2cli_raw_tcon_recv(req);
     193          16 :  fail:
     194          16 :         TALLOC_FREE(frame);
     195          16 :         return status;
     196             : }
     197             : 
     198             : struct smb2cli_tcon_state {
     199             :         struct tevent_context *ev;
     200             :         struct smbXcli_conn *conn;
     201             :         uint32_t timeout_msec;
     202             :         struct smbXcli_session *session;
     203             :         struct smbXcli_tcon *tcon;
     204             :         uint8_t fixed[8];
     205             :         uint8_t dyn_pad[1];
     206             : };
     207             : 
     208             : static void smb2cli_tcon_done(struct tevent_req *subreq);
     209             : 
     210       40992 : struct tevent_req *smb2cli_tcon_send(TALLOC_CTX *mem_ctx,
     211             :                                      struct tevent_context *ev,
     212             :                                      struct smbXcli_conn *conn,
     213             :                                      uint32_t timeout_msec,
     214             :                                      struct smbXcli_session *session,
     215             :                                      struct smbXcli_tcon *tcon,
     216             :                                      uint16_t flags,
     217             :                                      const char *unc)
     218             : {
     219         623 :         struct tevent_req *req, *subreq;
     220         623 :         struct smb2cli_tcon_state *state;
     221       40992 :         uint32_t additional_flags = 0;
     222       40992 :         uint32_t clear_flags = 0;
     223             : 
     224       40992 :         req = tevent_req_create(mem_ctx, &state, struct smb2cli_tcon_state);
     225       40992 :         if (req == NULL) {
     226           0 :                 return NULL;
     227             :         }
     228       40992 :         state->ev = ev;
     229       40992 :         state->conn = conn;
     230       40992 :         state->timeout_msec = timeout_msec;
     231       40992 :         state->session = session;
     232       40992 :         state->tcon = tcon;
     233             : 
     234       40992 :         if (smbXcli_session_is_authenticated(state->session)) {
     235       39883 :                 additional_flags |= SMB2_HDR_FLAG_SIGNED;
     236             :         }
     237             : 
     238       41615 :         subreq = smb2cli_raw_tcon_send(state,
     239       40369 :                                        state->ev,
     240       40369 :                                        state->conn,
     241             :                                        additional_flags,
     242             :                                        clear_flags,
     243       40369 :                                        state->timeout_msec,
     244       40369 :                                        state->session,
     245       40992 :                                        state->tcon,
     246             :                                        flags,
     247             :                                        unc);
     248       40992 :         if (tevent_req_nomem(subreq, req)) {
     249           0 :                 return tevent_req_post(req, ev);
     250             :         }
     251       40992 :         tevent_req_set_callback(subreq, smb2cli_tcon_done, req);
     252             : 
     253       40992 :         return req;
     254             : }
     255             : 
     256             : static void smb2cli_tcon_validate(struct tevent_req *subreq);
     257             : 
     258       40992 : static void smb2cli_tcon_done(struct tevent_req *subreq)
     259             : {
     260       40992 :         struct tevent_req *req = tevent_req_callback_data(
     261             :                 subreq, struct tevent_req);
     262       40992 :         struct smb2cli_tcon_state *state = tevent_req_data(
     263             :                 req, struct smb2cli_tcon_state);
     264         623 :         NTSTATUS status;
     265             : 
     266       40992 :         status = smb2cli_raw_tcon_recv(subreq);
     267       40992 :         TALLOC_FREE(subreq);
     268       40992 :         if (tevent_req_nterror(req, status)) {
     269       36732 :                 return;
     270             :         }
     271             : 
     272       40876 :         if (!smbXcli_session_is_authenticated(state->session)) {
     273        1103 :                 tevent_req_done(req);
     274        1103 :                 return;
     275             :         }
     276             : 
     277       39773 :         if (smbXcli_conn_protocol(state->conn) >= PROTOCOL_SMB3_11) {
     278       35513 :                 tevent_req_done(req);
     279       35513 :                 return;
     280             :         }
     281             : 
     282        4260 :         subreq = smb2cli_validate_negotiate_info_send(state, state->ev,
     283             :                                                       state->conn,
     284             :                                                       state->timeout_msec,
     285             :                                                       state->session,
     286             :                                                       state->tcon);
     287        4260 :         if (tevent_req_nomem(subreq, req)) {
     288           0 :                 return;
     289             :         }
     290        4260 :         tevent_req_set_callback(subreq, smb2cli_tcon_validate, req);
     291             : }
     292             : 
     293        4260 : static void smb2cli_tcon_validate(struct tevent_req *subreq)
     294             : {
     295        4260 :         struct tevent_req *req = tevent_req_callback_data(
     296             :                 subreq, struct tevent_req);
     297        4260 :         struct smb2cli_tcon_state *state = tevent_req_data(
     298             :                 req, struct smb2cli_tcon_state);
     299          22 :         NTSTATUS status;
     300             : 
     301        4260 :         status = smb2cli_validate_negotiate_info_recv(subreq);
     302        4260 :         TALLOC_FREE(subreq);
     303        4260 :         if (!NT_STATUS_IS_OK(status)) {
     304           0 :                 smb2cli_tcon_set_values(state->tcon, NULL,
     305             :                                         UINT32_MAX, 0, 0, 0, 0);
     306           0 :                 tevent_req_nterror(req, status);
     307           0 :                 return;
     308             :         }
     309             : 
     310        4260 :         tevent_req_done(req);
     311             : }
     312             : 
     313       40992 : NTSTATUS smb2cli_tcon_recv(struct tevent_req *req)
     314             : {
     315       40992 :         return tevent_req_simple_recv_ntstatus(req);
     316             : }
     317             : 
     318           0 : NTSTATUS smb2cli_tcon(struct smbXcli_conn *conn,
     319             :                       uint32_t timeout_msec,
     320             :                       struct smbXcli_session *session,
     321             :                       struct smbXcli_tcon *tcon,
     322             :                       uint16_t flags,
     323             :                       const char *unc)
     324             : {
     325           0 :         TALLOC_CTX *frame = talloc_stackframe();
     326           0 :         struct tevent_context *ev;
     327           0 :         struct tevent_req *req;
     328           0 :         NTSTATUS status = NT_STATUS_NO_MEMORY;
     329             : 
     330           0 :         if (smbXcli_conn_has_async_calls(conn)) {
     331             :                 /*
     332             :                  * Can't use sync call while an async call is in flight
     333             :                  */
     334           0 :                 status = NT_STATUS_INVALID_PARAMETER;
     335           0 :                 goto fail;
     336             :         }
     337           0 :         ev = samba_tevent_context_init(frame);
     338           0 :         if (ev == NULL) {
     339           0 :                 goto fail;
     340             :         }
     341           0 :         req = smb2cli_tcon_send(frame, ev, conn,
     342             :                                 timeout_msec, session, tcon,
     343             :                                 flags, unc);
     344           0 :         if (req == NULL) {
     345           0 :                 goto fail;
     346             :         }
     347           0 :         if (!tevent_req_poll_ntstatus(req, ev, &status)) {
     348           0 :                 goto fail;
     349             :         }
     350           0 :         status = smb2cli_tcon_recv(req);
     351           0 :  fail:
     352           0 :         TALLOC_FREE(frame);
     353           0 :         return status;
     354             : }
     355             : 
     356             : struct smb2cli_tdis_state {
     357             :         struct smbXcli_tcon *tcon;
     358             :         uint8_t fixed[4];
     359             : };
     360             : 
     361             : static void smb2cli_tdis_done(struct tevent_req *subreq);
     362             : 
     363       26200 : struct tevent_req *smb2cli_tdis_send(TALLOC_CTX *mem_ctx,
     364             :                                      struct tevent_context *ev,
     365             :                                      struct smbXcli_conn *conn,
     366             :                                      uint32_t timeout_msec,
     367             :                                      struct smbXcli_session *session,
     368             :                                      struct smbXcli_tcon *tcon)
     369             : {
     370           0 :         struct tevent_req *req, *subreq;
     371           0 :         struct smb2cli_tdis_state *state;
     372             : 
     373       26200 :         req = tevent_req_create(mem_ctx, &state,
     374             :                                 struct smb2cli_tdis_state);
     375       26200 :         if (req == NULL) {
     376           0 :                 return NULL;
     377             :         }
     378       26200 :         state->tcon = tcon;
     379             : 
     380       26200 :         SSVAL(state->fixed, 0, 4);
     381             : 
     382       26200 :         subreq = smb2cli_req_send(state, ev, conn, SMB2_OP_TDIS,
     383             :                                   0, 0, /* flags */
     384             :                                   timeout_msec,
     385             :                                   tcon, session,
     386       26200 :                                   state->fixed, sizeof(state->fixed),
     387             :                                   NULL, 0, /* dyn* */
     388             :                                   0); /* max_dyn_len */
     389       26200 :         if (tevent_req_nomem(subreq, req)) {
     390           0 :                 return tevent_req_post(req, ev);
     391             :         }
     392       26200 :         tevent_req_set_callback(subreq, smb2cli_tdis_done, req);
     393       26200 :         return req;
     394             : }
     395             : 
     396       26200 : static void smb2cli_tdis_done(struct tevent_req *subreq)
     397             : {
     398           0 :         struct tevent_req *req =
     399       26200 :                 tevent_req_callback_data(subreq,
     400             :                 struct tevent_req);
     401           0 :         struct smb2cli_tdis_state *state =
     402       26200 :                 tevent_req_data(req,
     403             :                 struct smb2cli_tdis_state);
     404           0 :         NTSTATUS status;
     405           0 :         static const struct smb2cli_req_expected_response expected[] = {
     406             :         {
     407             :                 .status = NT_STATUS_OK,
     408             :                 .body_size = 0x04
     409             :         }
     410             :         };
     411             : 
     412       26200 :         status = smb2cli_req_recv(subreq, NULL, NULL,
     413             :                                   expected, ARRAY_SIZE(expected));
     414       26200 :         TALLOC_FREE(subreq);
     415       26200 :         if (tevent_req_nterror(req, status)) {
     416         115 :                 return;
     417             :         }
     418       26085 :         smb2cli_tcon_set_values(state->tcon, NULL,
     419             :                                 UINT32_MAX, 0, 0, 0, 0);
     420       26085 :         tevent_req_done(req);
     421             : }
     422             : 
     423       26200 : NTSTATUS smb2cli_tdis_recv(struct tevent_req *req)
     424             : {
     425       26200 :         return tevent_req_simple_recv_ntstatus(req);
     426             : }
     427             : 
     428       26200 : NTSTATUS smb2cli_tdis(struct smbXcli_conn *conn,
     429             :                       uint32_t timeout_msec,
     430             :                       struct smbXcli_session *session,
     431             :                       struct smbXcli_tcon *tcon)
     432             : {
     433       26200 :         TALLOC_CTX *frame = talloc_stackframe();
     434           0 :         struct tevent_context *ev;
     435           0 :         struct tevent_req *req;
     436       26200 :         NTSTATUS status = NT_STATUS_NO_MEMORY;
     437             : 
     438       26200 :         if (smbXcli_conn_has_async_calls(conn)) {
     439             :                 /*
     440             :                  * Can't use sync call while an async call is in flight
     441             :                  */
     442           0 :                 status = NT_STATUS_INVALID_PARAMETER;
     443           0 :                 goto fail;
     444             :         }
     445       26200 :         ev = samba_tevent_context_init(frame);
     446       26200 :         if (ev == NULL) {
     447           0 :                 goto fail;
     448             :         }
     449       26200 :         req = smb2cli_tdis_send(frame, ev, conn,
     450             :                                 timeout_msec, session, tcon);
     451       26200 :         if (req == NULL) {
     452           0 :                 goto fail;
     453             :         }
     454       26200 :         if (!tevent_req_poll_ntstatus(req, ev, &status)) {
     455           0 :                 goto fail;
     456             :         }
     457       26200 :         status = smb2cli_tdis_recv(req);
     458       26200 :  fail:
     459       26200 :         TALLOC_FREE(frame);
     460       26200 :         return status;
     461             : }

Generated by: LCOV version 1.14