Fix the smb2_setinfo to handle FS info types and FSQUOTA infolevel
authorPartha Sarathi <partha@exablox.com>
Thu, 14 Apr 2016 12:39:05 +0000 (12:39 +0000)
committerUri Simchoni <uri@samba.org>
Wed, 27 Apr 2016 03:39:01 +0000 (05:39 +0200)
Signed-off-by: Partha Sarathi <partha@exablox.com>
Reviewed-by: Jeremy Allison <jra@samba.org>
Reviewed-by: Uri Simchoni <uri@samba.org>
Autobuild-User(master): Uri Simchoni <uri@samba.org>
Autobuild-Date(master): Wed Apr 27 05:39:01 CEST 2016 on sn-devel-144

source3/smbd/globals.h
source3/smbd/smb2_setinfo.c
source3/smbd/trans2.c

index 4c02083fc46799b785d17877dffca0dc2c2c3687..9e3e95c8904eb0d38bbb5f82844a23afddd08097 100644 (file)
@@ -140,6 +140,13 @@ 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,
+                               const DATA_BLOB *pdata);
+
 NTSTATUS smbd_do_setfilepathinfo(connection_struct *conn,
                                struct smb_request *req,
                                TALLOC_CTX *mem_ctx,
index 9361aeaf9177bebdbf4885086807df3243911644..a9196fea5a2a1542d35b8c27dbe42e06e47b4731 100644 (file)
@@ -530,6 +530,24 @@ static struct tevent_req *smbd_smb2_setinfo_send(TALLOC_CTX *mem_ctx,
                break;
        }
 
+       case 0x02:/* SMB2_SETINFO_FS */
+       {
+               uint16_t file_info_level = in_file_info_class + 1000;
+
+               status = smbd_do_setfsinfo(conn, smbreq, state,
+                                       file_info_level,
+                                       fsp,
+                                       &in_input_buffer);
+               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)) {
index 0e1c6d9eb84230c9dfb490b5bd32101ff2d4f606..9c0660b367488a61ec031d9387d37236d2baf4be 100644 (file)
@@ -3993,6 +3993,86 @@ 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,
+                       const DATA_BLOB *qdata)
+{
+       NTSTATUS status;
+       SMB_NTQUOTA_STRUCT quotas;
+
+       ZERO_STRUCT(quotas);
+
+       /* access check */
+       if ((get_current_uid(conn) != 0) || !CAN_WRITE(conn)) {
+               DEBUG(3, ("set_fsquota: 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;
+       }
+
+       if (!check_fsp_ntquota_handle(conn, req,
+                                     fsp)) {
+               DEBUG(1, ("set_fsquota: no valid QUOTA HANDLE\n"));
+               return NT_STATUS_INVALID_HANDLE;
+       }
+
+       /* note: normally there're 48 bytes,
+        * but we didn't use the last 6 bytes for now
+        * --metze
+        */
+       if (qdata->length < 42) {
+               DEBUG(0,("set_fsquota: requires total_data(%u) >= 42 bytes!\n",
+                       (unsigned int)qdata->length));
+               return NT_STATUS_INVALID_PARAMETER;
+       }
+
+       /* unknown_1 24 NULL bytes in pdata*/
+
+       /* the soft quotas 8 bytes (uint64_t)*/
+       quotas.softlim = BVAL(qdata->data,24);
+
+       /* the hard quotas 8 bytes (uint64_t)*/
+       quotas.hardlim = BVAL(qdata->data,32);
+
+       /* quota_flags 2 bytes **/
+       quotas.qflags = SVAL(qdata->data,40);
+
+       /* unknown_2 6 NULL bytes follow*/
+
+       /* now set the quotas */
+       if (vfs_set_ntquota(fsp, SMB_USER_FS_QUOTA_TYPE, NULL, &quotas)!=0) {
+               DEBUG(1, ("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,
+                               const DATA_BLOB *pdata)
+{
+       switch (info_level) {
+               case SMB_FS_QUOTA_INFORMATION:
+               {
+                       return smb_set_fsquota(conn,
+                                               req,
+                                               fsp,
+                                               pdata);
+               }
+
+               default:
+                       break;
+       }
+       return NT_STATUS_INVALID_LEVEL;
+}
+
 /****************************************************************************
  Reply to a TRANS2_QFSINFO (query filesystem info).
 ****************************************************************************/
@@ -4220,63 +4300,22 @@ static void call_trans2setfsinfo(connection_struct *conn,
 
                case SMB_FS_QUOTA_INFORMATION:
                        {
+                               NTSTATUS status;
+                               DATA_BLOB qdata = {
+                                               .data = (uint8_t *)pdata,
+                                               .length = total_data
+                               };
                                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, &quotas)!=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,
+                                                       &qdata);
+                               if (!NT_STATUS_IS_OK(status)) {
+                                       reply_nterror(req, status);
                                        return;
                                }
-
                                break;
                        }
                default: