LCOV - code coverage report
Current view: top level - libcli/smb - smb2cli_tcon.c (source / functions) Hit Total Coverage
Test: coverage report for v4-17-test 1498b464 Lines: 125 182 68.7 %
Date: 2024-06-13 04:01:37 Functions: 11 13 84.6 %

          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        7158 : 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        7158 :         struct tevent_req *req = NULL;
      47        7158 :         struct smb2cli_raw_tcon_state *state = NULL;
      48        7158 :         struct tevent_req *subreq = NULL;
      49        7158 :         uint8_t *fixed = NULL;
      50        7158 :         uint8_t *dyn = NULL;
      51             :         size_t dyn_len;
      52             : 
      53        7158 :         req = tevent_req_create(mem_ctx, &state,
      54             :                                 struct smb2cli_raw_tcon_state);
      55        7158 :         if (req == NULL) {
      56           0 :                 return NULL;
      57             :         }
      58        7158 :         state->session = session;
      59        7158 :         state->tcon = tcon;
      60             : 
      61        7158 :         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        7158 :         if (strlen(unc) == 0) {
      69           0 :                 TALLOC_FREE(dyn);
      70           0 :                 dyn_len = 0;
      71             :         }
      72             : 
      73        7158 :         fixed = state->fixed;
      74        7158 :         SSVAL(fixed, 0, 9);
      75        7158 :         if (smbXcli_conn_protocol(conn) >= PROTOCOL_SMB3_11) {
      76        3196 :                 SSVAL(fixed, 2, tcon_flags);
      77             :         } else {
      78        3962 :                 SSVAL(fixed, 2, 0); /* Reserved */
      79             :         }
      80        7158 :         SSVAL(fixed, 4, SMB2_HDR_BODY + 8);
      81        7158 :         SSVAL(fixed, 6, dyn_len);
      82             : 
      83        7158 :         if (dyn_len == 0) {
      84           0 :                 dyn = state->dyn_pad;
      85           0 :                 dyn_len = sizeof(state->dyn_pad);
      86             :         }
      87             : 
      88       12226 :         subreq = smb2cli_req_send(state, ev, conn, SMB2_OP_TCON,
      89             :                                   additional_flags, clear_flags,
      90             :                                   timeout_msec,
      91             :                                   NULL, /* tcon */
      92             :                                   session,
      93        7158 :                                   state->fixed, sizeof(state->fixed),
      94             :                                   dyn, dyn_len,
      95             :                                   0); /* max_dyn_len */
      96        7158 :         if (tevent_req_nomem(subreq, req)) {
      97           0 :                 return tevent_req_post(req, ev);
      98             :         }
      99        7158 :         tevent_req_set_callback(subreq, smb2cli_raw_tcon_done, req);
     100             : 
     101        7158 :         return req;
     102             : }
     103             : 
     104        7158 : static void smb2cli_raw_tcon_done(struct tevent_req *subreq)
     105             : {
     106        7158 :         struct tevent_req *req = tevent_req_callback_data(
     107             :                 subreq, struct tevent_req);
     108        7158 :         struct smb2cli_raw_tcon_state *state = tevent_req_data(
     109             :                 req, struct smb2cli_raw_tcon_state);
     110             :         NTSTATUS status;
     111             :         struct iovec *iov;
     112             :         uint8_t *body;
     113             :         uint32_t tcon_id;
     114             :         uint8_t share_type;
     115             :         uint32_t share_flags;
     116             :         uint32_t share_capabilities;
     117             :         uint32_t maximal_access;
     118             :         static const struct smb2cli_req_expected_response expected[] = {
     119             :         {
     120             :                 .status = NT_STATUS_OK,
     121             :                 .body_size = 0x10
     122             :         }
     123             :         };
     124             : 
     125        7158 :         status = smb2cli_req_recv(subreq, state, &iov,
     126             :                                   expected, ARRAY_SIZE(expected));
     127        7158 :         TALLOC_FREE(subreq);
     128        7158 :         if (!NT_STATUS_IS_OK(status)) {
     129          18 :                 tevent_req_nterror(req, status);
     130          18 :                 return;
     131             :         }
     132             : 
     133        7140 :         tcon_id = IVAL(iov[0].iov_base, SMB2_HDR_TID);
     134             : 
     135        7140 :         body = (uint8_t *)iov[1].iov_base;
     136        7140 :         share_type              = CVAL(body, 0x02);
     137        7140 :         share_flags             = IVAL(body, 0x04);
     138        7140 :         share_capabilities      = IVAL(body, 0x08);
     139        7140 :         maximal_access          = IVAL(body, 0x0C);
     140             : 
     141        7140 :         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        7140 :         tevent_req_done(req);
     150             : }
     151             : 
     152        7158 : NTSTATUS smb2cli_raw_tcon_recv(struct tevent_req *req)
     153             : {
     154        7158 :         return tevent_req_simple_recv_ntstatus(req);
     155             : }
     156             : 
     157           0 : 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           0 :         TALLOC_CTX *frame = talloc_stackframe();
     167             :         struct tevent_context *ev;
     168             :         struct tevent_req *req;
     169           0 :         NTSTATUS status = NT_STATUS_NO_MEMORY;
     170             : 
     171           0 :         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           0 :         ev = samba_tevent_context_init(frame);
     179           0 :         if (ev == NULL) {
     180           0 :                 goto fail;
     181             :         }
     182           0 :         req = smb2cli_raw_tcon_send(frame, ev, conn,
     183             :                                     additional_flags, clear_flags,
     184             :                                     timeout_msec, session, tcon,
     185             :                                     tcon_flags, unc);
     186           0 :         if (req == NULL) {
     187           0 :                 goto fail;
     188             :         }
     189           0 :         if (!tevent_req_poll_ntstatus(req, ev, &status)) {
     190           0 :                 goto fail;
     191             :         }
     192           0 :         status = smb2cli_raw_tcon_recv(req);
     193           0 :  fail:
     194           0 :         TALLOC_FREE(frame);
     195           0 :         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        7158 : 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             :         struct tevent_req *req, *subreq;
     220             :         struct smb2cli_tcon_state *state;
     221        7158 :         uint32_t additional_flags = 0;
     222        7158 :         uint32_t clear_flags = 0;
     223             : 
     224        7158 :         req = tevent_req_create(mem_ctx, &state, struct smb2cli_tcon_state);
     225        7158 :         if (req == NULL) {
     226           0 :                 return NULL;
     227             :         }
     228        7158 :         state->ev = ev;
     229        7158 :         state->conn = conn;
     230        7158 :         state->timeout_msec = timeout_msec;
     231        7158 :         state->session = session;
     232        7158 :         state->tcon = tcon;
     233             : 
     234        7158 :         if (smbXcli_session_is_authenticated(state->session)) {
     235        6673 :                 additional_flags |= SMB2_HDR_FLAG_SIGNED;
     236             :         }
     237             : 
     238       32498 :         subreq = smb2cli_raw_tcon_send(state,
     239        7158 :                                        state->ev,
     240        7158 :                                        state->conn,
     241             :                                        additional_flags,
     242             :                                        clear_flags,
     243        7158 :                                        state->timeout_msec,
     244        7158 :                                        state->session,
     245        7158 :                                        state->tcon,
     246             :                                        flags,
     247             :                                        unc);
     248        7158 :         if (tevent_req_nomem(subreq, req)) {
     249           0 :                 return tevent_req_post(req, ev);
     250             :         }
     251        7158 :         tevent_req_set_callback(subreq, smb2cli_tcon_done, req);
     252             : 
     253        7158 :         return req;
     254             : }
     255             : 
     256             : static void smb2cli_tcon_validate(struct tevent_req *subreq);
     257             : 
     258        7158 : static void smb2cli_tcon_done(struct tevent_req *subreq)
     259             : {
     260        7158 :         struct tevent_req *req = tevent_req_callback_data(
     261             :                 subreq, struct tevent_req);
     262        7158 :         struct smb2cli_tcon_state *state = tevent_req_data(
     263             :                 req, struct smb2cli_tcon_state);
     264             :         NTSTATUS status;
     265             : 
     266        7158 :         status = smb2cli_raw_tcon_recv(subreq);
     267        7158 :         TALLOC_FREE(subreq);
     268        7158 :         if (tevent_req_nterror(req, status)) {
     269        3277 :                 return;
     270             :         }
     271             : 
     272        7140 :         if (!smbXcli_session_is_authenticated(state->session)) {
     273         485 :                 tevent_req_done(req);
     274         485 :                 return;
     275             :         }
     276             : 
     277        6655 :         if (smbXcli_conn_protocol(state->conn) >= PROTOCOL_SMB3_11) {
     278        2765 :                 tevent_req_done(req);
     279        2765 :                 return;
     280             :         }
     281             : 
     282        3890 :         subreq = smb2cli_validate_negotiate_info_send(state, state->ev,
     283             :                                                       state->conn,
     284             :                                                       state->timeout_msec,
     285             :                                                       state->session,
     286             :                                                       state->tcon);
     287        3890 :         if (tevent_req_nomem(subreq, req)) {
     288           0 :                 return;
     289             :         }
     290        3890 :         tevent_req_set_callback(subreq, smb2cli_tcon_validate, req);
     291             : }
     292             : 
     293        3890 : static void smb2cli_tcon_validate(struct tevent_req *subreq)
     294             : {
     295        3890 :         struct tevent_req *req = tevent_req_callback_data(
     296             :                 subreq, struct tevent_req);
     297        3890 :         struct smb2cli_tcon_state *state = tevent_req_data(
     298             :                 req, struct smb2cli_tcon_state);
     299             :         NTSTATUS status;
     300             : 
     301        3890 :         status = smb2cli_validate_negotiate_info_recv(subreq);
     302        3890 :         TALLOC_FREE(subreq);
     303        3890 :         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        3890 :         tevent_req_done(req);
     311             : }
     312             : 
     313        7158 : NTSTATUS smb2cli_tcon_recv(struct tevent_req *req)
     314             : {
     315        7158 :         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             :         struct tevent_context *ev;
     327             :         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        2789 : 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             :         struct tevent_req *req, *subreq;
     371             :         struct smb2cli_tdis_state *state;
     372             : 
     373        2789 :         req = tevent_req_create(mem_ctx, &state,
     374             :                                 struct smb2cli_tdis_state);
     375        2789 :         if (req == NULL) {
     376           0 :                 return NULL;
     377             :         }
     378        2789 :         state->tcon = tcon;
     379             : 
     380        2789 :         SSVAL(state->fixed, 0, 4);
     381             : 
     382        2789 :         subreq = smb2cli_req_send(state, ev, conn, SMB2_OP_TDIS,
     383             :                                   0, 0, /* flags */
     384             :                                   timeout_msec,
     385             :                                   tcon, session,
     386        2789 :                                   state->fixed, sizeof(state->fixed),
     387             :                                   NULL, 0, /* dyn* */
     388             :                                   0); /* max_dyn_len */
     389        2789 :         if (tevent_req_nomem(subreq, req)) {
     390           0 :                 return tevent_req_post(req, ev);
     391             :         }
     392        2789 :         tevent_req_set_callback(subreq, smb2cli_tdis_done, req);
     393        2789 :         return req;
     394             : }
     395             : 
     396        2789 : static void smb2cli_tdis_done(struct tevent_req *subreq)
     397             : {
     398        1792 :         struct tevent_req *req =
     399        2789 :                 tevent_req_callback_data(subreq,
     400             :                 struct tevent_req);
     401        1792 :         struct smb2cli_tdis_state *state =
     402        2789 :                 tevent_req_data(req,
     403             :                 struct smb2cli_tdis_state);
     404             :         NTSTATUS status;
     405             :         static const struct smb2cli_req_expected_response expected[] = {
     406             :         {
     407             :                 .status = NT_STATUS_OK,
     408             :                 .body_size = 0x04
     409             :         }
     410             :         };
     411             : 
     412        2789 :         status = smb2cli_req_recv(subreq, NULL, NULL,
     413             :                                   expected, ARRAY_SIZE(expected));
     414        2789 :         TALLOC_FREE(subreq);
     415        2789 :         if (tevent_req_nterror(req, status)) {
     416          23 :                 return;
     417             :         }
     418        2766 :         smb2cli_tcon_set_values(state->tcon, NULL,
     419             :                                 UINT32_MAX, 0, 0, 0, 0);
     420        2766 :         tevent_req_done(req);
     421             : }
     422             : 
     423        2789 : NTSTATUS smb2cli_tdis_recv(struct tevent_req *req)
     424             : {
     425        2789 :         return tevent_req_simple_recv_ntstatus(req);
     426             : }
     427             : 
     428        2789 : NTSTATUS smb2cli_tdis(struct smbXcli_conn *conn,
     429             :                       uint32_t timeout_msec,
     430             :                       struct smbXcli_session *session,
     431             :                       struct smbXcli_tcon *tcon)
     432             : {
     433        2789 :         TALLOC_CTX *frame = talloc_stackframe();
     434             :         struct tevent_context *ev;
     435             :         struct tevent_req *req;
     436        2789 :         NTSTATUS status = NT_STATUS_NO_MEMORY;
     437             : 
     438        2789 :         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        2789 :         ev = samba_tevent_context_init(frame);
     446        2789 :         if (ev == NULL) {
     447           0 :                 goto fail;
     448             :         }
     449        2789 :         req = smb2cli_tdis_send(frame, ev, conn,
     450             :                                 timeout_msec, session, tcon);
     451        2789 :         if (req == NULL) {
     452           0 :                 goto fail;
     453             :         }
     454        2789 :         if (!tevent_req_poll_ntstatus(req, ev, &status)) {
     455           0 :                 goto fail;
     456             :         }
     457        2789 :         status = smb2cli_tdis_recv(req);
     458        2789 :  fail:
     459        2789 :         TALLOC_FREE(frame);
     460        2789 :         return status;
     461             : }

Generated by: LCOV version 1.13