LCOV - code coverage report
Current view: top level - source3/smbd - smb2_setinfo.c (source / functions) Hit Total Coverage
Test: coverage report for master 6248eab5 Lines: 185 274 67.5 %
Date: 2021-08-25 13:27:56 Functions: 8 8 100.0 %

          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       10988 : NTSTATUS smbd_smb2_request_process_setinfo(struct smbd_smb2_request *req)
      49             : {
      50       10988 :         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       10988 :         status = smbd_smb2_request_verify_sizes(req, 0x21);
      65       10988 :         if (!NT_STATUS_IS_OK(status)) {
      66           0 :                 return smbd_smb2_request_error(req, status);
      67             :         }
      68       10988 :         inbody = SMBD_SMB2_IN_BODY_PTR(req);
      69             : 
      70       10988 :         in_info_type                    = CVAL(inbody, 0x02);
      71       10988 :         in_file_info_class              = CVAL(inbody, 0x03);
      72       10988 :         in_input_buffer_length          = IVAL(inbody, 0x04);
      73       10988 :         in_input_buffer_offset          = SVAL(inbody, 0x08);
      74             :         /* 0x0A 2 bytes reserved */
      75       10988 :         in_additional_information       = IVAL(inbody, 0x0C);
      76       10988 :         in_file_id_persistent           = BVAL(inbody, 0x10);
      77       10988 :         in_file_id_volatile             = BVAL(inbody, 0x18);
      78             : 
      79       10988 :         if (in_input_buffer_offset == 0 && in_input_buffer_length == 0) {
      80             :                 /* This is ok */
      81       21976 :         } else if (in_input_buffer_offset !=
      82       10988 :                    (SMB2_HDR_BODY + SMBD_SMB2_IN_BODY_LEN(req))) {
      83           0 :                 return smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
      84             :         }
      85             : 
      86       10988 :         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       10988 :         in_input_buffer.data = SMBD_SMB2_IN_DYN_PTR(req);
      91       10988 :         in_input_buffer.length = in_input_buffer_length;
      92             : 
      93       10988 :         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       10988 :         status = smbd_smb2_request_verify_creditcharge(req,
     102       10988 :                                                 in_input_buffer.length);
     103       10988 :         if (!NT_STATUS_IS_OK(status)) {
     104           0 :                 return smbd_smb2_request_error(req, status);
     105             :         }
     106             : 
     107       10988 :         in_fsp = file_fsp_smb2(req, in_file_id_persistent, in_file_id_volatile);
     108       10988 :         if (in_fsp == NULL) {
     109           0 :                 return smbd_smb2_request_error(req, NT_STATUS_FILE_CLOSED);
     110             :         }
     111             : 
     112       10988 :         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       10988 :         if (subreq == NULL) {
     119           0 :                 return smbd_smb2_request_error(req, NT_STATUS_NO_MEMORY);
     120             :         }
     121       10988 :         tevent_req_set_callback(subreq, smbd_smb2_request_setinfo_done, req);
     122             : 
     123       10988 :         return smbd_smb2_request_pending_queue(req, subreq, 500);
     124             : }
     125             : 
     126       10988 : static void smbd_smb2_request_setinfo_done(struct tevent_req *subreq)
     127             : {
     128       10988 :         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       10988 :         status = smbd_smb2_setinfo_recv(subreq);
     135       10988 :         TALLOC_FREE(subreq);
     136       10988 :         if (!NT_STATUS_IS_OK(status)) {
     137          93 :                 error = smbd_smb2_request_error(req, status);
     138          93 :                 if (!NT_STATUS_IS_OK(error)) {
     139           0 :                         smbd_server_connection_terminate(req->xconn,
     140             :                                                          nt_errstr(error));
     141           0 :                         return;
     142             :                 }
     143          93 :                 return;
     144             :         }
     145             : 
     146       10895 :         outbody = smbd_smb2_generate_outbody(req, 0x02);
     147       10895 :         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       10895 :         SSVAL(outbody.data, 0x00, 0x02);        /* struct size */
     158             : 
     159       10895 :         error = smbd_smb2_request_done(req, outbody, NULL);
     160       10895 :         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           4 : static int defer_rename_state_destructor(struct defer_rename_state *rename_state)
     177             : {
     178           4 :         SAFE_FREE(rename_state->data);
     179           4 :         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          18 : static bool delay_rename_lease_break_fn(
     190             :         struct share_mode_entry *e,
     191             :         void *private_data)
     192             : {
     193          18 :         struct delay_rename_lease_break_state *state = private_data;
     194          18 :         struct files_struct *fsp = state->fsp;
     195             :         uint32_t e_lease_type, break_to;
     196             :         bool ours, stale;
     197             : 
     198          18 :         ours = smb2_lease_equal(fsp_client_guid(fsp),
     199          18 :                                 &fsp->lease->lease.lease_key,
     200          18 :                                 &e->client_guid,
     201          18 :                                 &e->lease_key);
     202          18 :         if (ours) {
     203          10 :                 return false;
     204             :         }
     205             : 
     206           8 :         e_lease_type = get_lease_type(e, fsp->file_id);
     207             : 
     208           8 :         if ((e_lease_type & SMB2_LEASE_HANDLE) == 0) {
     209           4 :                 return false;
     210             :         }
     211             : 
     212           4 :         stale = share_entry_stale_pid(e);
     213           4 :         if (stale) {
     214           0 :                 return false;
     215             :         }
     216             : 
     217           4 :         state->delay = true;
     218           4 :         break_to = (e_lease_type & ~SMB2_LEASE_HANDLE);
     219             : 
     220           8 :         send_break_message(
     221           4 :                 fsp->conn->sconn->msg_ctx, &fsp->file_id, e, break_to);
     222             : 
     223           4 :         return false;
     224             : }
     225             : 
     226         285 : 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         285 :         struct delay_rename_lease_break_state state = { .fsp = fsp };
     238             :         struct timeval timeout;
     239             :         bool ok;
     240             : 
     241         285 :         if (fsp->oplock_type != LEASE_OPLOCK) {
     242         275 :                 return NULL;
     243             :         }
     244             : 
     245          10 :         ok = share_mode_forall_leases(
     246             :                 lck, delay_rename_lease_break_fn, &state);
     247          10 :         if (!ok) {
     248           0 :                 return NULL;
     249             :         }
     250             : 
     251          10 :         if (!state.delay) {
     252           6 :                 return NULL;
     253             :         }
     254             : 
     255             :         /* Setup a watch on this record. */
     256           4 :         rename_state = talloc_zero(req, struct defer_rename_state);
     257           4 :         if (rename_state == NULL) {
     258           0 :                 return NULL;
     259             :         }
     260             : 
     261           4 :         rename_state->req = req;
     262           4 :         rename_state->smb2req = smb2req;
     263           4 :         rename_state->ev = ev;
     264           4 :         rename_state->fsp = fsp;
     265           4 :         rename_state->data = data;
     266           4 :         rename_state->data_size = data_size;
     267             : 
     268           4 :         talloc_set_destructor(rename_state, defer_rename_state_destructor);
     269             : 
     270           4 :         subreq = share_mode_watch_send(
     271             :                                 rename_state,
     272             :                                 ev,
     273             :                                 lck,
     274           4 :                                 (struct server_id){0});
     275             : 
     276           4 :         if (subreq == NULL) {
     277           0 :                 exit_server("Could not watch share mode record for rename\n");
     278             :         }
     279             : 
     280           4 :         tevent_req_set_callback(subreq, defer_rename_done, rename_state);
     281             : 
     282           4 :         timeout = timeval_set(OPLOCK_BREAK_TIMEOUT*2, 0);
     283           4 :         if (!tevent_req_set_endtime(subreq,
     284             :                         ev,
     285           4 :                         timeval_sum(&smb2req->request_time, &timeout))) {
     286           0 :                 exit_server("Could not set rename timeout\n");
     287             :         }
     288             : 
     289           4 :         return subreq;
     290             : }
     291             : 
     292           4 : static void defer_rename_done(struct tevent_req *subreq)
     293             : {
     294           4 :         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           4 :         int ret_size = 0;
     299             :         bool ok;
     300             : 
     301           4 :         status = share_mode_watch_recv(subreq, NULL, NULL);
     302           4 :         TALLOC_FREE(subreq);
     303           4 :         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           8 :         ok = change_to_user_and_service(
     314           4 :                 state->smb2req->tcon->compat,
     315           4 :                 state->smb2req->session->global->session_wire_id);
     316           4 :         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           4 :         lck = get_existing_share_mode_lock(state->req, state->fsp->file_id);
     323           4 :         if (lck == NULL) {
     324           0 :                 tevent_req_nterror(state->req, NT_STATUS_UNSUCCESSFUL);
     325           0 :                 return;
     326             :         }
     327           4 :         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           4 :         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          12 :         status = smbd_do_setfilepathinfo(state->fsp->conn,
     344           4 :                                 state->smb2req->smb1req,
     345             :                                 state,
     346             :                                 SMB2_FILE_RENAME_INFORMATION_INTERNAL,
     347           4 :                                 state->fsp,
     348           4 :                                 state->fsp->fsp_name,
     349             :                                 &state->data,
     350             :                                 state->data_size,
     351             :                                 &ret_size);
     352             : 
     353           4 :         TALLOC_FREE(lck);
     354           4 :         SAFE_FREE(state->data);
     355             : 
     356           4 :         if (!NT_STATUS_IS_OK(status)) {
     357           0 :                 tevent_req_nterror(state->req, status);
     358           0 :                 return;
     359             :         }
     360             : 
     361           4 :         tevent_req_done(state->req);
     362             : }
     363             : 
     364             : struct smbd_smb2_setinfo_state {
     365             :         struct smbd_smb2_request *smb2req;
     366             : };
     367             : 
     368       10988 : 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       10988 :         struct tevent_req *req = NULL;
     378       10988 :         struct smbd_smb2_setinfo_state *state = NULL;
     379       10988 :         struct smb_request *smbreq = NULL;
     380       10988 :         connection_struct *conn = smb2req->tcon->compat;
     381       10988 :         struct share_mode_lock *lck = NULL;
     382             :         NTSTATUS status;
     383             :         int ret;
     384             : 
     385       10988 :         req = tevent_req_create(mem_ctx, &state,
     386             :                                 struct smbd_smb2_setinfo_state);
     387       10988 :         if (req == NULL) {
     388           0 :                 return NULL;
     389             :         }
     390       10988 :         state->smb2req = smb2req;
     391             : 
     392       10988 :         DEBUG(10,("smbd_smb2_setinfo_send: %s - %s\n",
     393             :                   fsp_str_dbg(fsp), fsp_fnum_dbg(fsp)));
     394             : 
     395       10988 :         smbreq = smbd_smb2_fake_smb_request(smb2req);
     396       10988 :         if (tevent_req_nomem(smbreq, req)) {
     397           0 :                 return tevent_req_post(req, ev);
     398             :         }
     399             : 
     400       10988 :         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       10988 :         switch (in_info_type) {
     406        4420 :         case SMB2_0_INFO_FILE:
     407             :         {
     408             :                 uint16_t file_info_level;
     409             :                 char *data;
     410             :                 int data_size;
     411        4420 :                 int ret_size = 0;
     412             : 
     413             : 
     414        4420 :                 file_info_level = in_file_info_class + 1000;
     415        4420 :                 if (file_info_level == SMB_FILE_RENAME_INFORMATION) {
     416             :                         /* SMB2_FILE_RENAME_INFORMATION_INTERNAL == 0xFF00 + in_file_info_class */
     417         281 :                         file_info_level = SMB2_FILE_RENAME_INFORMATION_INTERNAL;
     418             :                 }
     419             : 
     420        4420 :                 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          93 :                                 return tevent_req_post(req, ev);
     434             :                         }
     435        4420 :                 } 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 :                                 uint32_t new_private_options =
     443           0 :                                         fh_get_private_options(fsp->fh);
     444           0 :                                 new_private_options |= NTCREATEX_FLAG_DELETE_ON_CLOSE;
     445           0 :                                 fh_set_private_options(fsp->fh, new_private_options);
     446             : 
     447           0 :                                 DEBUG(3,("smbd_smb2_setinfo_send: "
     448             :                                          "Cancelling print job (%s)\n",
     449             :                                          fsp_str_dbg(fsp)));
     450             : 
     451           0 :                                 tevent_req_done(req);
     452           0 :                                 return tevent_req_post(req, ev);
     453             :                         }
     454           0 :                         tevent_req_nterror(req, NT_STATUS_OBJECT_PATH_INVALID);
     455           0 :                         return tevent_req_post(req, ev);
     456             :                 } else {
     457             :                         /*
     458             :                          * Original code - this is an open file.
     459             :                          */
     460             : 
     461        4420 :                         if (SMB_VFS_FSTAT(fsp, &fsp->fsp_name->st) != 0) {
     462           0 :                                 DEBUG(3,("smbd_smb2_setinfo_send: fstat "
     463             :                                          "of %s failed (%s)\n",
     464             :                                          fsp_fnum_dbg(fsp),
     465             :                                          strerror(errno)));
     466           0 :                                 status = map_nt_error_from_unix(errno);
     467           0 :                                 tevent_req_nterror(req, status);
     468           0 :                                 return tevent_req_post(req, ev);
     469             :                         }
     470             :                 }
     471             : 
     472        4420 :                 data = NULL;
     473        4420 :                 data_size = in_input_buffer.length;
     474        4420 :                 if (data_size > 0) {
     475        4420 :                         data = (char *)SMB_MALLOC_ARRAY(char, data_size);
     476        4420 :                         if (tevent_req_nomem(data, req)) {
     477           0 :                                 return tevent_req_post(req, ev);
     478             :                         }
     479        4420 :                         memcpy(data, in_input_buffer.data, data_size);
     480             :                 }
     481             : 
     482        4420 :                 if (file_info_level == SMB2_FILE_RENAME_INFORMATION_INTERNAL) {
     483             :                         struct tevent_req *subreq;
     484             : 
     485         281 :                         lck = get_existing_share_mode_lock(mem_ctx,
     486             :                                                         fsp->file_id);
     487         281 :                         if (lck == NULL) {
     488           0 :                                 SAFE_FREE(data);
     489           0 :                                 tevent_req_nterror(req,
     490             :                                         NT_STATUS_UNSUCCESSFUL);
     491           0 :                                 return tevent_req_post(req, ev);
     492             :                         }
     493             : 
     494         281 :                         subreq = delay_rename_for_lease_break(req,
     495             :                                                         smb2req,
     496             :                                                         ev,
     497             :                                                         fsp,
     498             :                                                         lck,
     499             :                                                         data,
     500             :                                                         data_size);
     501         281 :                         if (subreq) {
     502             :                                 /* Wait for lease break response. */
     503             : 
     504             :                                 /* Ensure we can't be closed in flight. */
     505           4 :                                 if (!aio_add_req_to_fsp(fsp, req)) {
     506           0 :                                         TALLOC_FREE(lck);
     507           0 :                                         tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
     508           0 :                                         return tevent_req_post(req, ev);
     509             :                                 }
     510             : 
     511           4 :                                 TALLOC_FREE(lck);
     512           4 :                                 return req;
     513             :                         }
     514             :                 }
     515             : 
     516        4416 :                 status = smbd_do_setfilepathinfo(conn, smbreq, state,
     517             :                                                  file_info_level,
     518             :                                                  fsp,
     519             :                                                  fsp->fsp_name,
     520             :                                                  &data,
     521             :                                                  data_size,
     522             :                                                  &ret_size);
     523        4416 :                 TALLOC_FREE(lck);
     524        4416 :                 SAFE_FREE(data);
     525        4416 :                 if (!NT_STATUS_IS_OK(status)) {
     526          89 :                         if (NT_STATUS_EQUAL(status, NT_STATUS_INVALID_LEVEL)) {
     527           0 :                                 status = NT_STATUS_INVALID_INFO_CLASS;
     528             :                         }
     529          89 :                         tevent_req_nterror(req, status);
     530          89 :                         return tevent_req_post(req, ev);
     531             :                 }
     532        4327 :                 break;
     533             :         }
     534             : 
     535           0 :         case SMB2_0_INFO_FILESYSTEM:
     536             :         {
     537           0 :                 uint16_t file_info_level = in_file_info_class + 1000;
     538             : 
     539           0 :                 status = smbd_do_setfsinfo(conn, smbreq, state,
     540             :                                         file_info_level,
     541             :                                         fsp,
     542             :                                         &in_input_buffer);
     543           0 :                 if (!NT_STATUS_IS_OK(status)) {
     544           0 :                         if (NT_STATUS_EQUAL(status, NT_STATUS_INVALID_LEVEL)) {
     545           0 :                                 status = NT_STATUS_INVALID_INFO_CLASS;
     546             :                         }
     547           0 :                         tevent_req_nterror(req, status);
     548           0 :                         return tevent_req_post(req, ev);
     549             :                 }
     550           0 :                 break;
     551             :         }
     552             : 
     553        6564 :         case SMB2_0_INFO_SECURITY:
     554             :         {
     555        6564 :                 if (!CAN_WRITE(conn)) {
     556           0 :                         tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
     557           0 :                         return tevent_req_post(req, ev);
     558             :                 }
     559             : 
     560       13128 :                 status = set_sd_blob(fsp,
     561             :                                 in_input_buffer.data,
     562        6564 :                                 in_input_buffer.length,
     563             :                                 in_additional_information &
     564             :                                 SMB_SUPPORTED_SECINFO_FLAGS);
     565        6564 :                 if (!NT_STATUS_IS_OK(status)) {
     566           4 :                         tevent_req_nterror(req, status);
     567           4 :                         return tevent_req_post(req, ev);
     568             :                 }
     569        6560 :                 break;
     570             :         }
     571             : 
     572           4 :         case SMB2_0_INFO_QUOTA:
     573             :         {
     574             : #ifdef HAVE_SYS_QUOTAS
     575           4 :                 struct file_quota_information info = {0};
     576           4 :                 SMB_NTQUOTA_STRUCT qt = {0};
     577             :                 enum ndr_err_code err;
     578             : 
     579           4 :                 if (!fsp->fake_file_handle) {
     580           0 :                         tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
     581           0 :                         return tevent_req_post(req, ev);
     582             :                 }
     583           4 :                 err = ndr_pull_struct_blob(
     584             :                         &in_input_buffer, state, &info,
     585             :                         (ndr_pull_flags_fn_t)ndr_pull_file_quota_information);
     586           4 :                 if (!NDR_ERR_CODE_IS_SUCCESS(err)) {
     587           0 :                         tevent_req_nterror(req, NT_STATUS_UNSUCCESSFUL);
     588           0 :                         return tevent_req_post(req, ev);
     589             :                 }
     590             : 
     591           4 :                 qt.usedspace = info.quota_used;
     592             : 
     593           4 :                 qt.softlim = info.quota_threshold;
     594             : 
     595           4 :                 qt.hardlim = info.quota_limit;
     596             : 
     597           4 :                 qt.sid = info.sid;
     598           4 :                 ret = vfs_set_ntquota(fsp, SMB_USER_QUOTA_TYPE, &qt.sid, &qt);
     599           4 :                 if (ret !=0 ) {
     600           0 :                         status = map_nt_error_from_unix(errno);
     601           0 :                         tevent_req_nterror(req, status);
     602           0 :                         return tevent_req_post(req, ev);
     603             :                 }
     604           4 :                 status = NT_STATUS_OK;
     605           4 :                 break;
     606             : #else
     607             :                 tevent_req_nterror(req, NT_STATUS_NOT_SUPPORTED);
     608             :                 return tevent_req_post(req, ev);
     609             : #endif
     610             :         }
     611           0 :         default:
     612           0 :                 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
     613           0 :                 return tevent_req_post(req, ev);
     614             :         }
     615             : 
     616       10891 :         tevent_req_done(req);
     617       10891 :         return tevent_req_post(req, ev);
     618             : }
     619             : 
     620       10988 : static NTSTATUS smbd_smb2_setinfo_recv(struct tevent_req *req)
     621             : {
     622             :         NTSTATUS status;
     623             : 
     624       10988 :         if (tevent_req_is_nterror(req, &status)) {
     625          93 :                 tevent_req_received(req);
     626          93 :                 return status;
     627             :         }
     628             : 
     629       10895 :         tevent_req_received(req);
     630       10895 :         return NT_STATUS_OK;
     631             : }

Generated by: LCOV version 1.13