LCOV - code coverage report
Current view: top level - source3/smbd - smb2_setinfo.c (source / functions) Hit Total Coverage
Test: coverage report for v4-17-test 1498b464 Lines: 103 271 38.0 %
Date: 2024-06-13 04:01:37 Functions: 5 8 62.5 %

          Line data    Source code
       1             : /*
       2             :    Unix SMB/CIFS implementation.
       3             :    Core SMB2 server
       4             : 
       5             :    Copyright (C) Stefan Metzmacher 2009
       6             :    Copyright (C) Jeremy Allison 2010
       7             : 
       8             :    This program is free software; you can redistribute it and/or modify
       9             :    it under the terms of the GNU General Public License as published by
      10             :    the Free Software Foundation; either version 3 of the License, or
      11             :    (at your option) any later version.
      12             : 
      13             :    This program is distributed in the hope that it will be useful,
      14             :    but WITHOUT ANY WARRANTY; without even the implied warranty of
      15             :    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      16             :    GNU General Public License for more details.
      17             : 
      18             :    You should have received a copy of the GNU General Public License
      19             :    along with this program.  If not, see <http://www.gnu.org/licenses/>.
      20             : */
      21             : 
      22             : #include "includes.h"
      23             : #include "locking/share_mode_lock.h"
      24             : #include "smbd/smbd.h"
      25             : #include "smbd/globals.h"
      26             : #include "../libcli/smb/smb_common.h"
      27             : #include "trans2.h"
      28             : #include "../lib/util/tevent_ntstatus.h"
      29             : #include "../librpc/gen_ndr/open_files.h"
      30             : #include "source3/lib/dbwrap/dbwrap_watch.h"
      31             : #include "messages.h"
      32             : #include "librpc/gen_ndr/ndr_quota.h"
      33             : 
      34             : #undef DBGC_CLASS
      35             : #define DBGC_CLASS DBGC_SMB2
      36             : 
      37             : static struct tevent_req *smbd_smb2_setinfo_send(TALLOC_CTX *mem_ctx,
      38             :                                                  struct tevent_context *ev,
      39             :                                                  struct smbd_smb2_request *smb2req,
      40             :                                                  struct files_struct *in_fsp,
      41             :                                                  uint8_t in_info_type,
      42             :                                                  uint8_t in_file_info_class,
      43             :                                                  DATA_BLOB in_input_buffer,
      44             :                                                  uint32_t in_additional_information);
      45             : static NTSTATUS smbd_smb2_setinfo_recv(struct tevent_req *req);
      46             : 
      47             : static void smbd_smb2_request_setinfo_done(struct tevent_req *subreq);
      48        1020 : NTSTATUS smbd_smb2_request_process_setinfo(struct smbd_smb2_request *req)
      49             : {
      50        1020 :         struct smbXsrv_connection *xconn = req->xconn;
      51             :         NTSTATUS status;
      52             :         const uint8_t *inbody;
      53             :         uint8_t in_info_type;
      54             :         uint8_t in_file_info_class;
      55             :         uint16_t in_input_buffer_offset;
      56             :         uint32_t in_input_buffer_length;
      57             :         DATA_BLOB in_input_buffer;
      58             :         uint32_t in_additional_information;
      59             :         uint64_t in_file_id_persistent;
      60             :         uint64_t in_file_id_volatile;
      61             :         struct files_struct *in_fsp;
      62             :         struct tevent_req *subreq;
      63             : 
      64        1020 :         status = smbd_smb2_request_verify_sizes(req, 0x21);
      65        1020 :         if (!NT_STATUS_IS_OK(status)) {
      66           0 :                 return smbd_smb2_request_error(req, status);
      67             :         }
      68        1020 :         inbody = SMBD_SMB2_IN_BODY_PTR(req);
      69             : 
      70        1020 :         in_info_type                    = CVAL(inbody, 0x02);
      71        1020 :         in_file_info_class              = CVAL(inbody, 0x03);
      72        1020 :         in_input_buffer_length          = IVAL(inbody, 0x04);
      73        1020 :         in_input_buffer_offset          = SVAL(inbody, 0x08);
      74             :         /* 0x0A 2 bytes reserved */
      75        1020 :         in_additional_information       = IVAL(inbody, 0x0C);
      76        1020 :         in_file_id_persistent           = BVAL(inbody, 0x10);
      77        1020 :         in_file_id_volatile             = BVAL(inbody, 0x18);
      78             : 
      79        1020 :         if (in_input_buffer_offset == 0 && in_input_buffer_length == 0) {
      80             :                 /* This is ok */
      81        1946 :         } else if (in_input_buffer_offset !=
      82        1020 :                    (SMB2_HDR_BODY + SMBD_SMB2_IN_BODY_LEN(req))) {
      83           0 :                 return smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
      84             :         }
      85             : 
      86        1020 :         if (in_input_buffer_length > SMBD_SMB2_IN_DYN_LEN(req)) {
      87           0 :                 return smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
      88             :         }
      89             : 
      90        1020 :         in_input_buffer.data = SMBD_SMB2_IN_DYN_PTR(req);
      91        1020 :         in_input_buffer.length = in_input_buffer_length;
      92             : 
      93        1020 :         if (in_input_buffer.length > xconn->smb2.server.max_trans) {
      94           0 :                 DEBUG(2,("smbd_smb2_request_process_setinfo: "
      95             :                          "client ignored max trans: %s: 0x%08X: 0x%08X\n",
      96             :                          __location__, (unsigned)in_input_buffer.length,
      97             :                          (unsigned)xconn->smb2.server.max_trans));
      98           0 :                 return smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
      99             :         }
     100             : 
     101        1020 :         status = smbd_smb2_request_verify_creditcharge(req,
     102        1020 :                                                 in_input_buffer.length);
     103        1020 :         if (!NT_STATUS_IS_OK(status)) {
     104           0 :                 return smbd_smb2_request_error(req, status);
     105             :         }
     106             : 
     107        1020 :         in_fsp = file_fsp_smb2(req, in_file_id_persistent, in_file_id_volatile);
     108        1020 :         if (in_fsp == NULL) {
     109           0 :                 return smbd_smb2_request_error(req, NT_STATUS_FILE_CLOSED);
     110             :         }
     111             : 
     112        1020 :         subreq = smbd_smb2_setinfo_send(req, req->sconn->ev_ctx,
     113             :                                         req, in_fsp,
     114             :                                         in_info_type,
     115             :                                         in_file_info_class,
     116             :                                         in_input_buffer,
     117             :                                         in_additional_information);
     118        1020 :         if (subreq == NULL) {
     119           0 :                 return smbd_smb2_request_error(req, NT_STATUS_NO_MEMORY);
     120             :         }
     121        1020 :         tevent_req_set_callback(subreq, smbd_smb2_request_setinfo_done, req);
     122             : 
     123        1020 :         return smbd_smb2_request_pending_queue(req, subreq, 500);
     124             : }
     125             : 
     126        1020 : static void smbd_smb2_request_setinfo_done(struct tevent_req *subreq)
     127             : {
     128        1020 :         struct smbd_smb2_request *req = tevent_req_callback_data(subreq,
     129             :                                         struct smbd_smb2_request);
     130             :         DATA_BLOB outbody;
     131             :         NTSTATUS status;
     132             :         NTSTATUS error; /* transport error */
     133             : 
     134        1020 :         status = smbd_smb2_setinfo_recv(subreq);
     135        1020 :         TALLOC_FREE(subreq);
     136        1020 :         if (!NT_STATUS_IS_OK(status)) {
     137           6 :                 error = smbd_smb2_request_error(req, status);
     138           6 :                 if (!NT_STATUS_IS_OK(error)) {
     139           0 :                         smbd_server_connection_terminate(req->xconn,
     140             :                                                          nt_errstr(error));
     141           2 :                         return;
     142             :                 }
     143           6 :                 return;
     144             :         }
     145             : 
     146        1014 :         outbody = smbd_smb2_generate_outbody(req, 0x02);
     147        1014 :         if (outbody.data == NULL) {
     148           0 :                 error = smbd_smb2_request_error(req, NT_STATUS_NO_MEMORY);
     149           0 :                 if (!NT_STATUS_IS_OK(error)) {
     150           0 :                         smbd_server_connection_terminate(req->xconn,
     151             :                                                          nt_errstr(error));
     152           0 :                         return;
     153             :                 }
     154           0 :                 return;
     155             :         }
     156             : 
     157        1014 :         SSVAL(outbody.data, 0x00, 0x02);        /* struct size */
     158             : 
     159        1014 :         error = smbd_smb2_request_done(req, outbody, NULL);
     160        1014 :         if (!NT_STATUS_IS_OK(error)) {
     161           0 :                 smbd_server_connection_terminate(req->xconn,
     162             :                                                  nt_errstr(error));
     163           0 :                 return;
     164             :         }
     165             : }
     166             : 
     167             : struct defer_rename_state {
     168             :         struct tevent_req *req;
     169             :         struct smbd_smb2_request *smb2req;
     170             :         struct tevent_context *ev;
     171             :         struct files_struct *fsp;
     172             :         char *data;
     173             :         int data_size;
     174             : };
     175             : 
     176           0 : static int defer_rename_state_destructor(struct defer_rename_state *rename_state)
     177             : {
     178           0 :         SAFE_FREE(rename_state->data);
     179           0 :         return 0;
     180             : }
     181             : 
     182             : static void defer_rename_done(struct tevent_req *subreq);
     183             : 
     184             : struct delay_rename_lease_break_state {
     185             :         struct files_struct *fsp;
     186             :         bool delay;
     187             : };
     188             : 
     189           0 : static bool delay_rename_lease_break_fn(
     190             :         struct share_mode_entry *e,
     191             :         void *private_data)
     192             : {
     193           0 :         struct delay_rename_lease_break_state *state = private_data;
     194           0 :         struct files_struct *fsp = state->fsp;
     195             :         uint32_t e_lease_type, break_to;
     196             :         bool ours, stale;
     197             : 
     198           0 :         ours = smb2_lease_equal(fsp_client_guid(fsp),
     199           0 :                                 &fsp->lease->lease.lease_key,
     200           0 :                                 &e->client_guid,
     201           0 :                                 &e->lease_key);
     202           0 :         if (ours) {
     203           0 :                 return false;
     204             :         }
     205             : 
     206           0 :         e_lease_type = get_lease_type(e, fsp->file_id);
     207             : 
     208           0 :         if ((e_lease_type & SMB2_LEASE_HANDLE) == 0) {
     209           0 :                 return false;
     210             :         }
     211             : 
     212           0 :         stale = share_entry_stale_pid(e);
     213           0 :         if (stale) {
     214           0 :                 return false;
     215             :         }
     216             : 
     217           0 :         state->delay = true;
     218           0 :         break_to = (e_lease_type & ~SMB2_LEASE_HANDLE);
     219             : 
     220           0 :         send_break_message(
     221           0 :                 fsp->conn->sconn->msg_ctx, &fsp->file_id, e, break_to);
     222             : 
     223           0 :         return false;
     224             : }
     225             : 
     226          21 : static struct tevent_req *delay_rename_for_lease_break(struct tevent_req *req,
     227             :                                 struct smbd_smb2_request *smb2req,
     228             :                                 struct tevent_context *ev,
     229             :                                 struct files_struct *fsp,
     230             :                                 struct share_mode_lock *lck,
     231             :                                 char *data,
     232             :                                 int data_size)
     233             : 
     234             : {
     235             :         struct tevent_req *subreq;
     236             :         struct defer_rename_state *rename_state;
     237          21 :         struct delay_rename_lease_break_state state = { .fsp = fsp };
     238             :         struct timeval timeout;
     239             :         bool ok;
     240             : 
     241          21 :         if (fsp->oplock_type != LEASE_OPLOCK) {
     242          21 :                 return NULL;
     243             :         }
     244             : 
     245           0 :         ok = share_mode_forall_leases(
     246             :                 lck, delay_rename_lease_break_fn, &state);
     247           0 :         if (!ok) {
     248           0 :                 return NULL;
     249             :         }
     250             : 
     251           0 :         if (!state.delay) {
     252           0 :                 return NULL;
     253             :         }
     254             : 
     255             :         /* Setup a watch on this record. */
     256           0 :         rename_state = talloc_zero(req, struct defer_rename_state);
     257           0 :         if (rename_state == NULL) {
     258           0 :                 return NULL;
     259             :         }
     260             : 
     261           0 :         rename_state->req = req;
     262           0 :         rename_state->smb2req = smb2req;
     263           0 :         rename_state->ev = ev;
     264           0 :         rename_state->fsp = fsp;
     265           0 :         rename_state->data = data;
     266           0 :         rename_state->data_size = data_size;
     267             : 
     268           0 :         talloc_set_destructor(rename_state, defer_rename_state_destructor);
     269             : 
     270           0 :         subreq = share_mode_watch_send(
     271             :                                 rename_state,
     272             :                                 ev,
     273             :                                 lck,
     274           0 :                                 (struct server_id){0});
     275             : 
     276           0 :         if (subreq == NULL) {
     277           0 :                 exit_server("Could not watch share mode record for rename\n");
     278             :         }
     279             : 
     280           0 :         tevent_req_set_callback(subreq, defer_rename_done, rename_state);
     281             : 
     282           0 :         timeout = timeval_set(OPLOCK_BREAK_TIMEOUT*2, 0);
     283           0 :         if (!tevent_req_set_endtime(subreq,
     284             :                         ev,
     285           0 :                         timeval_sum(&smb2req->request_time, &timeout))) {
     286           0 :                 exit_server("Could not set rename timeout\n");
     287             :         }
     288             : 
     289           0 :         return subreq;
     290             : }
     291             : 
     292           0 : static void defer_rename_done(struct tevent_req *subreq)
     293             : {
     294           0 :         struct defer_rename_state *state = tevent_req_callback_data(
     295             :                 subreq, struct defer_rename_state);
     296             :         NTSTATUS status;
     297             :         struct share_mode_lock *lck;
     298           0 :         int ret_size = 0;
     299             :         bool ok;
     300             : 
     301           0 :         status = share_mode_watch_recv(subreq, NULL, NULL);
     302           0 :         TALLOC_FREE(subreq);
     303           0 :         if (!NT_STATUS_IS_OK(status)) {
     304           0 :                 DEBUG(5, ("dbwrap_record_watch_recv returned %s\n",
     305             :                         nt_errstr(status)));
     306           0 :                 tevent_req_nterror(state->req, status);
     307           0 :                 return;
     308             :         }
     309             : 
     310             :         /*
     311             :          * Make sure we run as the user again
     312             :          */
     313           0 :         ok = change_to_user_and_service(
     314           0 :                 state->smb2req->tcon->compat,
     315           0 :                 state->smb2req->session->global->session_wire_id);
     316           0 :         if (!ok) {
     317           0 :                 tevent_req_nterror(state->req, NT_STATUS_ACCESS_DENIED);
     318           0 :                 return;
     319             :         }
     320             : 
     321             :         /* Do we still need to wait ? */
     322           0 :         lck = get_existing_share_mode_lock(state->req, state->fsp->file_id);
     323           0 :         if (lck == NULL) {
     324           0 :                 tevent_req_nterror(state->req, NT_STATUS_UNSUCCESSFUL);
     325           0 :                 return;
     326             :         }
     327           0 :         subreq = delay_rename_for_lease_break(state->req,
     328             :                                 state->smb2req,
     329             :                                 state->ev,
     330             :                                 state->fsp,
     331             :                                 lck,
     332             :                                 state->data,
     333             :                                 state->data_size);
     334           0 :         if (subreq) {
     335             :                 /* Yep - keep waiting. */
     336           0 :                 state->data = NULL;
     337           0 :                 TALLOC_FREE(state);
     338           0 :                 TALLOC_FREE(lck);
     339           0 :                 return;
     340             :         }
     341             : 
     342             :         /* Do the rename under the lock. */
     343           0 :         status = smbd_do_setfilepathinfo(state->fsp->conn,
     344           0 :                                 state->smb2req->smb1req,
     345             :                                 state,
     346             :                                 SMB2_FILE_RENAME_INFORMATION_INTERNAL,
     347           0 :                                 state->fsp,
     348           0 :                                 state->fsp->fsp_name,
     349             :                                 &state->data,
     350             :                                 state->data_size,
     351             :                                 &ret_size);
     352             : 
     353           0 :         TALLOC_FREE(lck);
     354           0 :         SAFE_FREE(state->data);
     355             : 
     356           0 :         if (!NT_STATUS_IS_OK(status)) {
     357           0 :                 tevent_req_nterror(state->req, status);
     358           0 :                 return;
     359             :         }
     360             : 
     361           0 :         tevent_req_done(state->req);
     362             : }
     363             : 
     364             : struct smbd_smb2_setinfo_state {
     365             :         struct smbd_smb2_request *smb2req;
     366             : };
     367             : 
     368        1020 : static struct tevent_req *smbd_smb2_setinfo_send(TALLOC_CTX *mem_ctx,
     369             :                                                  struct tevent_context *ev,
     370             :                                                  struct smbd_smb2_request *smb2req,
     371             :                                                  struct files_struct *fsp,
     372             :                                                  uint8_t in_info_type,
     373             :                                                  uint8_t in_file_info_class,
     374             :                                                  DATA_BLOB in_input_buffer,
     375             :                                                  uint32_t in_additional_information)
     376             : {
     377        1020 :         struct tevent_req *req = NULL;
     378        1020 :         struct smbd_smb2_setinfo_state *state = NULL;
     379        1020 :         struct smb_request *smbreq = NULL;
     380        1020 :         connection_struct *conn = smb2req->tcon->compat;
     381        1020 :         struct share_mode_lock *lck = NULL;
     382             :         NTSTATUS status;
     383             :         int ret;
     384             : 
     385        1020 :         req = tevent_req_create(mem_ctx, &state,
     386             :                                 struct smbd_smb2_setinfo_state);
     387        1020 :         if (req == NULL) {
     388           0 :                 return NULL;
     389             :         }
     390        1020 :         state->smb2req = smb2req;
     391             : 
     392        1020 :         DEBUG(10,("smbd_smb2_setinfo_send: %s - %s\n",
     393             :                   fsp_str_dbg(fsp), fsp_fnum_dbg(fsp)));
     394             : 
     395        1020 :         smbreq = smbd_smb2_fake_smb_request(smb2req);
     396        1020 :         if (tevent_req_nomem(smbreq, req)) {
     397           0 :                 return tevent_req_post(req, ev);
     398             :         }
     399             : 
     400        1020 :         if (IS_IPC(conn)) {
     401           0 :                 tevent_req_nterror(req, NT_STATUS_NOT_SUPPORTED);
     402           0 :                 return tevent_req_post(req, ev);
     403             :         }
     404             : 
     405        1020 :         switch (in_info_type) {
     406         894 :         case SMB2_0_INFO_FILE:
     407             :         {
     408             :                 uint16_t file_info_level;
     409             :                 char *data;
     410             :                 int data_size;
     411         894 :                 int ret_size = 0;
     412             : 
     413             : 
     414         894 :                 file_info_level = in_file_info_class + 1000;
     415         894 :                 if (file_info_level == SMB_FILE_RENAME_INFORMATION) {
     416             :                         /* SMB2_FILE_RENAME_INFORMATION_INTERNAL == 0xFF00 + in_file_info_class */
     417          21 :                         file_info_level = SMB2_FILE_RENAME_INFORMATION_INTERNAL;
     418             :                 }
     419             : 
     420         894 :                 if (fsp_get_pathref_fd(fsp) == -1) {
     421             :                         /*
     422             :                          * This is actually a SETFILEINFO on a directory
     423             :                          * handle (returned from an NT SMB). NT5.0 seems
     424             :                          * to do this call. JRA.
     425             :                          */
     426           0 :                         ret = vfs_stat(fsp->conn, fsp->fsp_name);
     427           0 :                         if (ret != 0) {
     428           0 :                                 DBG_WARNING("vfs_stat() of %s failed (%s)\n",
     429             :                                             fsp_str_dbg(fsp),
     430             :                                             strerror(errno));
     431           0 :                                 status = map_nt_error_from_unix(errno);
     432           0 :                                 tevent_req_nterror(req, status);
     433           6 :                                 return tevent_req_post(req, ev);
     434             :                         }
     435         894 :                 } else if (fsp->print_file) {
     436             :                         /*
     437             :                          * Doing a DELETE_ON_CLOSE should cancel a print job.
     438             :                          */
     439           0 :                         if ((file_info_level == SMB_SET_FILE_DISPOSITION_INFO)
     440           0 :                             && in_input_buffer.length >= 1
     441           0 :                             && CVAL(in_input_buffer.data,0)) {
     442           0 :                                 fsp->fsp_flags.delete_on_close = true;
     443             : 
     444           0 :                                 DEBUG(3,("smbd_smb2_setinfo_send: "
     445             :                                          "Cancelling print job (%s)\n",
     446             :                                          fsp_str_dbg(fsp)));
     447             : 
     448           0 :                                 tevent_req_done(req);
     449           0 :                                 return tevent_req_post(req, ev);
     450             :                         }
     451           0 :                         tevent_req_nterror(req, NT_STATUS_OBJECT_PATH_INVALID);
     452           0 :                         return tevent_req_post(req, ev);
     453             :                 } else {
     454             :                         /*
     455             :                          * Original code - this is an open file.
     456             :                          */
     457             : 
     458         894 :                         status = vfs_stat_fsp(fsp);
     459         894 :                         if (!NT_STATUS_IS_OK(status)) {
     460           0 :                                 DEBUG(3,("smbd_smb2_setinfo_send: fstat "
     461             :                                          "of %s failed (%s)\n",
     462             :                                          fsp_fnum_dbg(fsp),
     463             :                                          nt_errstr(status)));
     464           0 :                                 tevent_req_nterror(req, status);
     465           0 :                                 return tevent_req_post(req, ev);
     466             :                         }
     467             :                 }
     468             : 
     469         894 :                 data = NULL;
     470         894 :                 data_size = in_input_buffer.length;
     471         894 :                 if (data_size > 0) {
     472         894 :                         data = (char *)SMB_MALLOC_ARRAY(char, data_size);
     473         894 :                         if (tevent_req_nomem(data, req)) {
     474           0 :                                 return tevent_req_post(req, ev);
     475             :                         }
     476         894 :                         memcpy(data, in_input_buffer.data, data_size);
     477             :                 }
     478             : 
     479         894 :                 if (file_info_level == SMB2_FILE_RENAME_INFORMATION_INTERNAL) {
     480             :                         struct tevent_req *subreq;
     481             : 
     482          21 :                         lck = get_existing_share_mode_lock(mem_ctx,
     483             :                                                         fsp->file_id);
     484          21 :                         if (lck == NULL) {
     485           0 :                                 SAFE_FREE(data);
     486           0 :                                 tevent_req_nterror(req,
     487             :                                         NT_STATUS_UNSUCCESSFUL);
     488           0 :                                 return tevent_req_post(req, ev);
     489             :                         }
     490             : 
     491          21 :                         subreq = delay_rename_for_lease_break(req,
     492             :                                                         smb2req,
     493             :                                                         ev,
     494             :                                                         fsp,
     495             :                                                         lck,
     496             :                                                         data,
     497             :                                                         data_size);
     498          21 :                         if (subreq) {
     499             :                                 /* Wait for lease break response. */
     500             : 
     501             :                                 /* Ensure we can't be closed in flight. */
     502           0 :                                 if (!aio_add_req_to_fsp(fsp, req)) {
     503           0 :                                         TALLOC_FREE(lck);
     504           0 :                                         tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
     505           0 :                                         return tevent_req_post(req, ev);
     506             :                                 }
     507             : 
     508           0 :                                 TALLOC_FREE(lck);
     509           0 :                                 return req;
     510             :                         }
     511             :                 }
     512             : 
     513         894 :                 status = smbd_do_setfilepathinfo(conn, smbreq, state,
     514             :                                                  file_info_level,
     515             :                                                  fsp,
     516             :                                                  fsp->fsp_name,
     517             :                                                  &data,
     518             :                                                  data_size,
     519             :                                                  &ret_size);
     520         894 :                 TALLOC_FREE(lck);
     521         894 :                 SAFE_FREE(data);
     522         894 :                 if (!NT_STATUS_IS_OK(status)) {
     523           6 :                         if (NT_STATUS_EQUAL(status, NT_STATUS_INVALID_LEVEL)) {
     524           0 :                                 status = NT_STATUS_INVALID_INFO_CLASS;
     525             :                         }
     526           6 :                         tevent_req_nterror(req, status);
     527           6 :                         return tevent_req_post(req, ev);
     528             :                 }
     529         888 :                 break;
     530             :         }
     531             : 
     532           0 :         case SMB2_0_INFO_FILESYSTEM:
     533             :         {
     534           0 :                 uint16_t file_info_level = in_file_info_class + 1000;
     535             : 
     536           0 :                 status = smbd_do_setfsinfo(conn, smbreq, state,
     537             :                                         file_info_level,
     538             :                                         fsp,
     539             :                                         &in_input_buffer);
     540           0 :                 if (!NT_STATUS_IS_OK(status)) {
     541           0 :                         if (NT_STATUS_EQUAL(status, NT_STATUS_INVALID_LEVEL)) {
     542           0 :                                 status = NT_STATUS_INVALID_INFO_CLASS;
     543             :                         }
     544           0 :                         tevent_req_nterror(req, status);
     545           0 :                         return tevent_req_post(req, ev);
     546             :                 }
     547           0 :                 break;
     548             :         }
     549             : 
     550         126 :         case SMB2_0_INFO_SECURITY:
     551             :         {
     552         126 :                 if (!CAN_WRITE(conn)) {
     553           0 :                         tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
     554           0 :                         return tevent_req_post(req, ev);
     555             :                 }
     556             : 
     557         249 :                 status = set_sd_blob(fsp,
     558             :                                 in_input_buffer.data,
     559         126 :                                 in_input_buffer.length,
     560             :                                 in_additional_information &
     561             :                                 SMB_SUPPORTED_SECINFO_FLAGS);
     562         126 :                 if (!NT_STATUS_IS_OK(status)) {
     563           0 :                         tevent_req_nterror(req, status);
     564           0 :                         return tevent_req_post(req, ev);
     565             :                 }
     566         126 :                 break;
     567             :         }
     568             : 
     569           0 :         case SMB2_0_INFO_QUOTA:
     570             :         {
     571             : #ifdef HAVE_SYS_QUOTAS
     572           0 :                 struct file_quota_information info = {0};
     573           0 :                 SMB_NTQUOTA_STRUCT qt = {0};
     574             :                 enum ndr_err_code err;
     575             : 
     576           0 :                 if (!fsp->fake_file_handle) {
     577           0 :                         tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
     578           0 :                         return tevent_req_post(req, ev);
     579             :                 }
     580           0 :                 err = ndr_pull_struct_blob(
     581             :                         &in_input_buffer, state, &info,
     582             :                         (ndr_pull_flags_fn_t)ndr_pull_file_quota_information);
     583           0 :                 if (!NDR_ERR_CODE_IS_SUCCESS(err)) {
     584           0 :                         tevent_req_nterror(req, NT_STATUS_UNSUCCESSFUL);
     585           0 :                         return tevent_req_post(req, ev);
     586             :                 }
     587             : 
     588           0 :                 qt.usedspace = info.quota_used;
     589             : 
     590           0 :                 qt.softlim = info.quota_threshold;
     591             : 
     592           0 :                 qt.hardlim = info.quota_limit;
     593             : 
     594           0 :                 qt.sid = info.sid;
     595           0 :                 ret = vfs_set_ntquota(fsp, SMB_USER_QUOTA_TYPE, &qt.sid, &qt);
     596           0 :                 if (ret !=0 ) {
     597           0 :                         status = map_nt_error_from_unix(errno);
     598           0 :                         tevent_req_nterror(req, status);
     599           0 :                         return tevent_req_post(req, ev);
     600             :                 }
     601           0 :                 status = NT_STATUS_OK;
     602           0 :                 break;
     603             : #else
     604             :                 tevent_req_nterror(req, NT_STATUS_NOT_SUPPORTED);
     605             :                 return tevent_req_post(req, ev);
     606             : #endif
     607             :         }
     608           0 :         default:
     609           0 :                 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
     610           0 :                 return tevent_req_post(req, ev);
     611             :         }
     612             : 
     613        1014 :         tevent_req_done(req);
     614        1014 :         return tevent_req_post(req, ev);
     615             : }
     616             : 
     617        1020 : static NTSTATUS smbd_smb2_setinfo_recv(struct tevent_req *req)
     618             : {
     619             :         NTSTATUS status;
     620             : 
     621        1020 :         if (tevent_req_is_nterror(req, &status)) {
     622           6 :                 tevent_req_received(req);
     623           6 :                 return status;
     624             :         }
     625             : 
     626        1014 :         tevent_req_received(req);
     627        1014 :         return NT_STATUS_OK;
     628             : }

Generated by: LCOV version 1.13