LCOV - code coverage report
Current view: top level - source4/libcli/smb_composite - smb2.c (source / functions) Hit Total Coverage
Test: coverage report for master 2f515e9b Lines: 176 207 85.0 %
Date: 2024-04-21 15:09:00 Functions: 16 16 100.0 %

          Line data    Source code
       1             : /* 
       2             :    Unix SMB/CIFS implementation.
       3             : 
       4             :    Copyright (C) Andrew Tridgell 2008
       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             :   a composite API for making SMB-like calls using SMB2. This is useful
      21             :   as SMB2 often requires more than one requests where a single SMB
      22             :   request would do. In converting code that uses SMB to use SMB2,
      23             :   these routines make life a lot easier
      24             : */
      25             : 
      26             : 
      27             : #include "includes.h"
      28             : #include <tevent.h>
      29             : #include "lib/util/tevent_ntstatus.h"
      30             : #include "libcli/raw/libcliraw.h"
      31             : #include "libcli/raw/raw_proto.h"
      32             : #include "libcli/composite/composite.h"
      33             : #include "libcli/smb_composite/smb_composite.h"
      34             : #include "libcli/smb2/smb2_calls.h"
      35             : 
      36             : /*
      37             :   continue after a SMB2 close
      38             :  */
      39      200564 : static void continue_close(struct smb2_request *req)
      40             : {
      41      200564 :         struct composite_context *ctx = talloc_get_type(req->async.private_data, 
      42             :                                                         struct composite_context);
      43          25 :         NTSTATUS status;
      44          25 :         struct smb2_close close_parm;
      45             : 
      46      200564 :         status = smb2_close_recv(req, &close_parm);
      47      200564 :         composite_error(ctx, status);   
      48      200564 : }
      49             : 
      50             : /*
      51             :   continue after the create in a composite unlink
      52             :  */
      53      358768 : static void continue_unlink(struct smb2_request *req)
      54             : {
      55      358768 :         struct composite_context *ctx = talloc_get_type(req->async.private_data, 
      56             :                                                         struct composite_context);
      57      358768 :         struct smb2_tree *tree = req->tree;
      58         188 :         struct smb2_create create_parm;
      59         188 :         struct smb2_close close_parm;
      60         188 :         NTSTATUS status;
      61             : 
      62      358768 :         status = smb2_create_recv(req, ctx, &create_parm);
      63      358768 :         if (!NT_STATUS_IS_OK(status)) {
      64      160730 :                 composite_error(ctx, status);
      65      160730 :                 return;
      66             :         }
      67             : 
      68      198038 :         ZERO_STRUCT(close_parm);
      69      198038 :         close_parm.in.file.handle = create_parm.out.file.handle;
      70             :         
      71      198038 :         req = smb2_close_send(tree, &close_parm);
      72      198038 :         composite_continue_smb2(ctx, req, continue_close, ctx);
      73             : }
      74             : 
      75             : /*
      76             :   composite SMB2 unlink call
      77             : */
      78      358783 : struct composite_context *smb2_composite_unlink_send(struct smb2_tree *tree, 
      79             :                                                      union smb_unlink *io)
      80             : {
      81         188 :         struct composite_context *ctx;
      82         188 :         struct smb2_create create_parm;
      83         188 :         struct smb2_request *req;
      84             : 
      85      358783 :         ctx = composite_create(tree, tree->session->transport->ev);
      86      358783 :         if (ctx == NULL) return NULL;
      87             : 
      88             :         /* check for wildcards - we could support these with a
      89             :            search, but for now they aren't necessary */
      90      358783 :         if (strpbrk(io->unlink.in.pattern, "*?<>") != NULL) {
      91           5 :                 composite_error(ctx, NT_STATUS_NOT_SUPPORTED);
      92           5 :                 return ctx;
      93             :         }
      94             : 
      95      358778 :         ZERO_STRUCT(create_parm);
      96      358778 :         create_parm.in.desired_access     = SEC_STD_DELETE;
      97      358778 :         create_parm.in.create_disposition = NTCREATEX_DISP_OPEN;
      98      358778 :         create_parm.in.share_access = 
      99             :                 NTCREATEX_SHARE_ACCESS_DELETE|
     100             :                 NTCREATEX_SHARE_ACCESS_READ|
     101             :                 NTCREATEX_SHARE_ACCESS_WRITE;
     102      358778 :         create_parm.in.create_options = 
     103             :                 NTCREATEX_OPTIONS_DELETE_ON_CLOSE |
     104             :                 NTCREATEX_OPTIONS_NON_DIRECTORY_FILE;
     105      358778 :         create_parm.in.fname = io->unlink.in.pattern;
     106      358778 :         if (create_parm.in.fname[0] == '\\') {
     107          12 :                 create_parm.in.fname++;
     108             :         }
     109             : 
     110      358778 :         req = smb2_create_send(tree, &create_parm);
     111             : 
     112      358778 :         composite_continue_smb2(ctx, req, continue_unlink, ctx);
     113      358778 :         return ctx;
     114             : }
     115             : 
     116             : 
     117             : /*
     118             :   composite unlink call - sync interface
     119             : */
     120      358783 : NTSTATUS smb2_composite_unlink(struct smb2_tree *tree, union smb_unlink *io)
     121             : {
     122      358783 :         struct composite_context *c = smb2_composite_unlink_send(tree, io);
     123      358783 :         return composite_wait_free(c);
     124             : }
     125             : 
     126             : 
     127             : 
     128             : 
     129             : /*
     130             :   continue after the create in a composite mkdir
     131             :  */
     132         391 : static void continue_mkdir(struct smb2_request *req)
     133             : {
     134         391 :         struct composite_context *ctx = talloc_get_type(req->async.private_data, 
     135             :                                                         struct composite_context);
     136         391 :         struct smb2_tree *tree = req->tree;
     137           2 :         struct smb2_create create_parm;
     138           2 :         struct smb2_close close_parm;
     139           2 :         NTSTATUS status;
     140             : 
     141         391 :         status = smb2_create_recv(req, ctx, &create_parm);
     142         391 :         if (!NT_STATUS_IS_OK(status)) {
     143          80 :                 composite_error(ctx, status);
     144          80 :                 return;
     145             :         }
     146             : 
     147         311 :         ZERO_STRUCT(close_parm);
     148         311 :         close_parm.in.file.handle = create_parm.out.file.handle;
     149             :         
     150         311 :         req = smb2_close_send(tree, &close_parm);
     151         311 :         composite_continue_smb2(ctx, req, continue_close, ctx);
     152             : }
     153             : 
     154             : /*
     155             :   composite SMB2 mkdir call
     156             : */
     157         391 : struct composite_context *smb2_composite_mkdir_send(struct smb2_tree *tree, 
     158             :                                                      union smb_mkdir *io)
     159             : {
     160           2 :         struct composite_context *ctx;
     161           2 :         struct smb2_create create_parm;
     162           2 :         struct smb2_request *req;
     163             : 
     164         391 :         ctx = composite_create(tree, tree->session->transport->ev);
     165         391 :         if (ctx == NULL) return NULL;
     166             : 
     167         391 :         ZERO_STRUCT(create_parm);
     168             : 
     169         391 :         create_parm.in.desired_access = SEC_FLAG_MAXIMUM_ALLOWED;
     170         391 :         create_parm.in.share_access = 
     171             :                 NTCREATEX_SHARE_ACCESS_READ|
     172             :                 NTCREATEX_SHARE_ACCESS_WRITE;
     173         391 :         create_parm.in.create_options = NTCREATEX_OPTIONS_DIRECTORY;
     174         391 :         create_parm.in.file_attributes   = FILE_ATTRIBUTE_DIRECTORY;
     175         391 :         create_parm.in.create_disposition = NTCREATEX_DISP_CREATE;
     176         391 :         create_parm.in.fname = io->mkdir.in.path;
     177         391 :         if (create_parm.in.fname[0] == '\\') {
     178           0 :                 create_parm.in.fname++;
     179             :         }
     180             : 
     181         391 :         req = smb2_create_send(tree, &create_parm);
     182             : 
     183         391 :         composite_continue_smb2(ctx, req, continue_mkdir, ctx);
     184             : 
     185         391 :         return ctx;
     186             : }
     187             : 
     188             : 
     189             : /*
     190             :   composite mkdir call - sync interface
     191             : */
     192         391 : NTSTATUS smb2_composite_mkdir(struct smb2_tree *tree, union smb_mkdir *io)
     193             : {
     194         391 :         struct composite_context *c = smb2_composite_mkdir_send(tree, io);
     195         391 :         return composite_wait_free(c);
     196             : }
     197             : 
     198             : 
     199             : 
     200             : /*
     201             :   continue after the create in a composite rmdir
     202             :  */
     203        2492 : static void continue_rmdir(struct smb2_request *req)
     204             : {
     205        2492 :         struct composite_context *ctx = talloc_get_type(req->async.private_data, 
     206             :                                                         struct composite_context);
     207        2492 :         struct smb2_tree *tree = req->tree;
     208           2 :         struct smb2_create create_parm;
     209           2 :         struct smb2_close close_parm;
     210           2 :         NTSTATUS status;
     211             : 
     212        2492 :         status = smb2_create_recv(req, ctx, &create_parm);
     213        2492 :         if (!NT_STATUS_IS_OK(status)) {
     214         277 :                 composite_error(ctx, status);
     215         277 :                 return;
     216             :         }
     217             : 
     218        2215 :         ZERO_STRUCT(close_parm);
     219        2215 :         close_parm.in.file.handle = create_parm.out.file.handle;
     220             :         
     221        2215 :         req = smb2_close_send(tree, &close_parm);
     222        2215 :         composite_continue_smb2(ctx, req, continue_close, ctx);
     223             : }
     224             : 
     225             : /*
     226             :   composite SMB2 rmdir call
     227             : */
     228        2492 : struct composite_context *smb2_composite_rmdir_send(struct smb2_tree *tree, 
     229             :                                                     struct smb_rmdir *io)
     230             : {
     231           2 :         struct composite_context *ctx;
     232           2 :         struct smb2_create create_parm;
     233           2 :         struct smb2_request *req;
     234             : 
     235        2492 :         ctx = composite_create(tree, tree->session->transport->ev);
     236        2492 :         if (ctx == NULL) return NULL;
     237             : 
     238        2492 :         ZERO_STRUCT(create_parm);
     239        2492 :         create_parm.in.desired_access     = SEC_STD_DELETE;
     240        2492 :         create_parm.in.create_disposition = NTCREATEX_DISP_OPEN;
     241        2492 :         create_parm.in.share_access = 
     242             :                 NTCREATEX_SHARE_ACCESS_DELETE|
     243             :                 NTCREATEX_SHARE_ACCESS_READ|
     244             :                 NTCREATEX_SHARE_ACCESS_WRITE;
     245        2492 :         create_parm.in.create_options = 
     246             :                 NTCREATEX_OPTIONS_DIRECTORY |
     247             :                 NTCREATEX_OPTIONS_DELETE_ON_CLOSE;
     248        2492 :         create_parm.in.fname = io->in.path;
     249        2492 :         if (create_parm.in.fname[0] == '\\') {
     250           0 :                 create_parm.in.fname++;
     251             :         }
     252             : 
     253        2492 :         req = smb2_create_send(tree, &create_parm);
     254             : 
     255        2492 :         composite_continue_smb2(ctx, req, continue_rmdir, ctx);
     256        2492 :         return ctx;
     257             : }
     258             : 
     259             : 
     260             : /*
     261             :   composite rmdir call - sync interface
     262             : */
     263        2492 : NTSTATUS smb2_composite_rmdir(struct smb2_tree *tree, struct smb_rmdir *io)
     264             : {
     265        2492 :         struct composite_context *c = smb2_composite_rmdir_send(tree, io);
     266        2492 :         return composite_wait_free(c);
     267             : }
     268             : 
     269             : struct smb2_composite_setpathinfo_state {
     270             :         struct smb2_tree *tree;
     271             :         union smb_setfileinfo io;
     272             :         NTSTATUS set_status;
     273             :         struct smb2_create cr;
     274             :         struct smb2_close cl;
     275             : };
     276             : 
     277             : static void smb2_composite_setpathinfo_create_done(struct smb2_request *smb2req);
     278             : 
     279             : /*
     280             :   composite SMB2 setpathinfo call
     281             : */
     282           9 : struct tevent_req *smb2_composite_setpathinfo_send(TALLOC_CTX *mem_ctx,
     283             :                                                    struct tevent_context *ev,
     284             :                                                    struct smb2_tree *tree,
     285             :                                                    const union smb_setfileinfo *io)
     286             : {
     287           0 :         struct tevent_req *req;
     288           0 :         struct smb2_composite_setpathinfo_state *state;
     289           0 :         struct smb2_request *smb2req;
     290             : 
     291           9 :         req = tevent_req_create(mem_ctx, &state,
     292             :                                 struct smb2_composite_setpathinfo_state);
     293           9 :         if (req == NULL) {
     294           0 :                 return NULL;
     295             :         }
     296             : 
     297           9 :         state->tree = tree;
     298           9 :         state->io = *io;
     299             : 
     300           9 :         state->cr.in.desired_access     = SEC_FLAG_MAXIMUM_ALLOWED;
     301           9 :         state->cr.in.create_disposition = NTCREATEX_DISP_OPEN;
     302           9 :         state->cr.in.share_access =
     303             :                 NTCREATEX_SHARE_ACCESS_DELETE|
     304             :                 NTCREATEX_SHARE_ACCESS_READ|
     305             :                 NTCREATEX_SHARE_ACCESS_WRITE;
     306           9 :         state->cr.in.create_options = 0;
     307           9 :         state->cr.in.fname = state->io.generic.in.file.path;
     308           9 :         if (state->cr.in.fname[0] == '\\') {
     309           0 :                 state->cr.in.fname++;
     310             :         }
     311             : 
     312           9 :         smb2req = smb2_create_send(tree, &state->cr);
     313           9 :         if (tevent_req_nomem(smb2req, req)) {
     314           0 :                 return tevent_req_post(req, ev);
     315             :         }
     316           9 :         smb2req->async.fn = smb2_composite_setpathinfo_create_done;
     317           9 :         smb2req->async.private_data = req;
     318             : 
     319           9 :         return req;
     320             : }
     321             : 
     322             : static void smb2_composite_setpathinfo_setinfo_done(struct smb2_request *smb2req);
     323             : 
     324           9 : static void smb2_composite_setpathinfo_create_done(struct smb2_request *smb2req)
     325             : {
     326           0 :         struct tevent_req *req =
     327           9 :                 talloc_get_type_abort(smb2req->async.private_data,
     328             :                 struct tevent_req);
     329           0 :         struct smb2_composite_setpathinfo_state *state =
     330           9 :                 tevent_req_data(req,
     331             :                 struct smb2_composite_setpathinfo_state);
     332           0 :         NTSTATUS status;
     333             : 
     334           9 :         status = smb2_create_recv(smb2req, state, &state->cr);
     335           9 :         if (tevent_req_nterror(req, status)) {
     336           3 :                 return;
     337             :         }
     338             : 
     339           6 :         state->io.generic.in.file.handle = state->cr.out.file.handle;
     340             : 
     341           6 :         smb2req = smb2_setinfo_file_send(state->tree, &state->io);
     342           6 :         if (tevent_req_nomem(smb2req, req)) {
     343           0 :                 return;
     344             :         }
     345           6 :         smb2req->async.fn = smb2_composite_setpathinfo_setinfo_done;
     346           6 :         smb2req->async.private_data = req;
     347             : }
     348             : 
     349             : static void smb2_composite_setpathinfo_close_done(struct smb2_request *smb2req);
     350             : 
     351           6 : static void smb2_composite_setpathinfo_setinfo_done(struct smb2_request *smb2req)
     352             : {
     353           0 :         struct tevent_req *req =
     354           6 :                 talloc_get_type_abort(smb2req->async.private_data,
     355             :                 struct tevent_req);
     356           0 :         struct smb2_composite_setpathinfo_state *state =
     357           6 :                 tevent_req_data(req,
     358             :                 struct smb2_composite_setpathinfo_state);
     359           0 :         NTSTATUS status;
     360             : 
     361           6 :         status = smb2_setinfo_recv(smb2req);
     362           6 :         state->set_status = status;
     363             : 
     364           6 :         state->cl.in.file.handle = state->io.generic.in.file.handle;
     365             : 
     366           6 :         smb2req = smb2_close_send(state->tree, &state->cl);
     367           6 :         if (tevent_req_nomem(smb2req, req)) {
     368           0 :                 return;
     369             :         }
     370           6 :         smb2req->async.fn = smb2_composite_setpathinfo_close_done;
     371           6 :         smb2req->async.private_data = req;
     372             : }
     373             : 
     374           6 : static void smb2_composite_setpathinfo_close_done(struct smb2_request *smb2req)
     375             : {
     376           0 :         struct tevent_req *req =
     377           6 :                 talloc_get_type_abort(smb2req->async.private_data,
     378             :                 struct tevent_req);
     379           0 :         struct smb2_composite_setpathinfo_state *state =
     380           6 :                 tevent_req_data(req,
     381             :                 struct smb2_composite_setpathinfo_state);
     382           0 :         NTSTATUS status;
     383             : 
     384           6 :         status = smb2_close_recv(smb2req, &state->cl);
     385             : 
     386           6 :         if (tevent_req_nterror(req, state->set_status)) {
     387           0 :                 return;
     388             :         }
     389             : 
     390           6 :         if (tevent_req_nterror(req, status)) {
     391           0 :                 return;
     392             :         }
     393             : 
     394           6 :         tevent_req_done(req);
     395             : }
     396             : 
     397           9 : NTSTATUS smb2_composite_setpathinfo_recv(struct tevent_req *req)
     398             : {
     399           0 :         NTSTATUS status;
     400             : 
     401           9 :         if (tevent_req_is_nterror(req, &status)) {
     402           3 :                 tevent_req_received(req);
     403           3 :                 return status;
     404             :         }
     405             : 
     406           6 :         tevent_req_received(req);
     407           6 :         return NT_STATUS_OK;
     408             : }
     409             : 
     410             : /*
     411             :   composite setpathinfo call
     412             :  */
     413           9 : NTSTATUS smb2_composite_setpathinfo(struct smb2_tree *tree, union smb_setfileinfo *io)
     414             : {
     415           0 :         struct tevent_req *subreq;
     416           0 :         NTSTATUS status;
     417           0 :         bool ok;
     418           9 :         TALLOC_CTX *frame = talloc_stackframe();
     419           9 :         struct tevent_context *ev = tree->session->transport->ev;
     420             : 
     421           9 :         if (frame == NULL) {
     422           0 :                 return NT_STATUS_NO_MEMORY;
     423             :         }
     424             : 
     425           9 :         subreq = smb2_composite_setpathinfo_send(frame, ev, tree, io);
     426           9 :         if (subreq == NULL) {
     427           0 :                 TALLOC_FREE(frame);
     428           0 :                 return NT_STATUS_NO_MEMORY;
     429             :         }
     430             : 
     431           9 :         ok = tevent_req_poll(subreq, ev);
     432           9 :         if (!ok) {
     433           0 :                 status = map_nt_error_from_unix_common(errno);
     434           0 :                 TALLOC_FREE(frame);
     435           0 :                 return status;
     436             :         }
     437             : 
     438           9 :         status = smb2_composite_setpathinfo_recv(subreq);
     439           9 :         TALLOC_FREE(subreq);
     440           9 :         if (!NT_STATUS_IS_OK(status)) {
     441           3 :                 TALLOC_FREE(frame);
     442           3 :                 return status;
     443             :         }
     444             : 
     445           6 :         TALLOC_FREE(frame);
     446           6 :         return NT_STATUS_OK;
     447             : }

Generated by: LCOV version 1.14