From 5f91f23b593ea66c96b49cf594d27c2d6f3e8f67 Mon Sep 17 00:00:00 2001 From: Partha Sarathi Date: Thu, 14 Apr 2016 12:39:05 +0000 Subject: [PATCH] Fix the smb2_setinfo to handle FS info types and FSQUOTA infolevel Signed-off-by: Partha Sarathi Reviewed-by: Jeremy Allison --- source3/smbd/globals.h | 9 +++ source3/smbd/smb2_setinfo.c | 35 ++++++++++ source3/smbd/trans2.c | 155 +++++++++++++++++++++++++++++--------------- 3 files changed, 147 insertions(+), 52 deletions(-) diff --git a/source3/smbd/globals.h b/source3/smbd/globals.h index 4c02083..4f02a10 100644 --- a/source3/smbd/globals.h +++ b/source3/smbd/globals.h @@ -140,6 +140,15 @@ NTSTATUS smbd_do_qfilepathinfo(connection_struct *conn, char **ppdata, unsigned int *pdata_size); +NTSTATUS smbd_do_setfsinfo(connection_struct *conn, + struct smb_request *req, + TALLOC_CTX *mem_ctx, + uint16_t info_level, + files_struct *fsp, + struct smb_filename *smb_fname, + char **ppdata, size_t total_data, + size_t *ret_data_size); + NTSTATUS smbd_do_setfilepathinfo(connection_struct *conn, struct smb_request *req, TALLOC_CTX *mem_ctx, diff --git a/source3/smbd/smb2_setinfo.c b/source3/smbd/smb2_setinfo.c index 9361aea..fcb98de 100644 --- a/source3/smbd/smb2_setinfo.c +++ b/source3/smbd/smb2_setinfo.c @@ -530,6 +530,41 @@ static struct tevent_req *smbd_smb2_setinfo_send(TALLOC_CTX *mem_ctx, break; } + case 0x02:/* SMB2_SETINFO_FS */ + { + uint16_t file_info_level; + char *data; + size_t data_size; + size_t ret_size = 0; + + file_info_level = in_file_info_class + 1000; + data = NULL; + data_size = in_input_buffer.length; + if (data_size > 0) { + data = (char *)SMB_MALLOC_ARRAY(char, data_size); + if (tevent_req_nomem(data, req)) { + return tevent_req_post(req, ev); + } + memcpy(data, in_input_buffer.data, data_size); + } + status = smbd_do_setfsinfo(conn, smbreq, state, + file_info_level, + fsp, + fsp->fsp_name, + &data, + data_size, + &ret_size); + SAFE_FREE(data); + if (!NT_STATUS_IS_OK(status)) { + if (NT_STATUS_EQUAL(status, NT_STATUS_INVALID_LEVEL)) { + status = NT_STATUS_INVALID_INFO_CLASS; + } + tevent_req_nterror(req, status); + return tevent_req_post(req, ev); + } + break; + } + case 0x03:/* SMB2_SETINFO_SECURITY */ { if (!CAN_WRITE(conn)) { diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 0e1c6d9..fb268ce 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -3993,6 +3993,101 @@ cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned return status; } +static NTSTATUS smb_set_fsquota(connection_struct *conn, + struct smb_request *req, + files_struct *fsp, + char **ppdata, + size_t total_data) +{ + NTSTATUS status; + char *pdata = *ppdata; + SMB_NTQUOTA_STRUCT quotas; + ZERO_STRUCT(quotas); + + /* access check */ + if ((get_current_uid(conn) != 0) || !CAN_WRITE(conn)) { + DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n", + lp_servicename(talloc_tos(), SNUM(conn)), + conn->session_info->unix_info->unix_name)); + return NT_STATUS_ACCESS_DENIED; + } + + /* note: normally there're 48 bytes, + * but we didn't use the last 6 bytes for now + * --metze + */ + if (!check_fsp_ntquota_handle(conn, req, + fsp)) { + DEBUG(3,("TRANSACT_GET_USER_QUOTA: no valid QUOTA HANDLE\n")); + return NT_STATUS_INVALID_HANDLE; + } + + if (total_data < 42) { + DEBUG(0,("set_fsquota: requires total_data(%u) >= 42 bytes!\n", + (unsigned int)total_data)); + return NT_STATUS_INVALID_PARAMETER; + } + + /* unknown_1 24 NULL bytes in pdata*/ + + /* the soft quotas 8 bytes (uint64_t)*/ + quotas.softlim = BVAL(pdata,24); + + /* the hard quotas 8 bytes (uint64_t)*/ + quotas.hardlim = BVAL(pdata,32); + + /* quota_flags 2 bytes **/ + quotas.qflags = SVAL(pdata,40); + + /* unknown_2 6 NULL bytes follow*/ + + /* now set the quotas */ + if (vfs_set_ntquota(fsp, SMB_USER_FS_QUOTA_TYPE, NULL, "as)!=0) { + DEBUG(0,("vfs_set_ntquota() failed for service [%s]\n",lp_servicename(talloc_tos(), SNUM(conn)))); + status = map_nt_error_from_unix(errno); + } else { + status = NT_STATUS_OK; + } + return status; +} + +NTSTATUS smbd_do_setfsinfo(connection_struct *conn, + struct smb_request *req, + TALLOC_CTX *mem_ctx, + uint16_t info_level, + files_struct *fsp, + struct smb_filename *smb_fname, + char **ppdata, size_t total_data, + size_t *ret_data_size) +{ + NTSTATUS status = NT_STATUS_OK; + size_t data_return_size = 0; + + *ret_data_size = 0; + + switch (info_level) { + case SMB_FS_QUOTA_INFORMATION: + { + status = smb_set_fsquota(conn, + req, + fsp, + ppdata, + total_data); + break; + } + + default: + return NT_STATUS_INVALID_LEVEL; + } + + if (!NT_STATUS_IS_OK(status)) { + return status; + } + + *ret_data_size = data_return_size; + return NT_STATUS_OK; +} + /**************************************************************************** Reply to a TRANS2_QFSINFO (query filesystem info). ****************************************************************************/ @@ -4220,63 +4315,19 @@ static void call_trans2setfsinfo(connection_struct *conn, case SMB_FS_QUOTA_INFORMATION: { + NTSTATUS status; files_struct *fsp = NULL; - SMB_NTQUOTA_STRUCT quotas; - - ZERO_STRUCT(quotas); - - /* access check */ - if ((get_current_uid(conn) != 0) || !CAN_WRITE(conn)) { - DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n", - lp_servicename(talloc_tos(), SNUM(conn)), - conn->session_info->unix_info->unix_name)); - reply_nterror(req, NT_STATUS_ACCESS_DENIED); - return; - } - - /* note: normally there're 48 bytes, - * but we didn't use the last 6 bytes for now - * --metze - */ fsp = file_fsp(req, SVAL(params,0)); - if (!check_fsp_ntquota_handle(conn, req, - fsp)) { - DEBUG(3,("TRANSACT_GET_USER_QUOTA: no valid QUOTA HANDLE\n")); - reply_nterror( - req, NT_STATUS_INVALID_HANDLE); - return; - } - - if (total_data < 42) { - DEBUG(0,("call_trans2setfsinfo: SET_FS_QUOTA: requires total_data(%d) >= 42 bytes!\n", - total_data)); - reply_nterror( - req, - NT_STATUS_INVALID_PARAMETER); - return; - } - - /* unknown_1 24 NULL bytes in pdata*/ - - /* the soft quotas 8 bytes (uint64_t)*/ - quotas.softlim = BVAL(pdata,24); - - /* the hard quotas 8 bytes (uint64_t)*/ - quotas.hardlim = BVAL(pdata,32); - - /* quota_flags 2 bytes **/ - quotas.qflags = SVAL(pdata,40); - - /* unknown_2 6 NULL bytes follow*/ - - /* now set the quotas */ - if (vfs_set_ntquota(fsp, SMB_USER_FS_QUOTA_TYPE, NULL, "as)!=0) { - DEBUG(0,("vfs_set_ntquota() failed for service [%s]\n",lp_servicename(talloc_tos(), SNUM(conn)))); - reply_nterror(req, map_nt_error_from_unix(errno)); + status = smb_set_fsquota(conn, + req, + fsp, + ppdata, + total_data); + if (!NT_STATUS_IS_OK(status)) { + reply_nterror(req, status); return; } - break; } default: -- 2.8.0.rc3.226.g39d4020