LCOV - code coverage report
Current view: top level - source3/libsmb - cliquota.c (source / functions) Hit Total Coverage
Test: coverage report for master 2f515e9b Lines: 150 305 49.2 %
Date: 2024-04-21 15:09:00 Functions: 11 15 73.3 %

          Line data    Source code
       1             : /*
       2             :    Unix SMB/CIFS implementation.
       3             :    client quota functions
       4             :    Copyright (C) Stefan (metze) Metzmacher      2003
       5             : 
       6             :    This program is free software; you can redistribute it and/or modify
       7             :    it under the terms of the GNU General Public License as published by
       8             :    the Free Software Foundation; either version 3 of the License, or
       9             :    (at your option) any later version.
      10             : 
      11             :    This program is distributed in the hope that it will be useful,
      12             :    but WITHOUT ANY WARRANTY; without even the implied warranty of
      13             :    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      14             :    GNU General Public License for more details.
      15             : 
      16             :    You should have received a copy of the GNU General Public License
      17             :    along with this program.  If not, see <http://www.gnu.org/licenses/>.
      18             : */
      19             : 
      20             : #include "includes.h"
      21             : #include "libsmb/libsmb.h"
      22             : #include "../librpc/gen_ndr/ndr_security.h"
      23             : #include "fake_file.h"
      24             : #include "../libcli/security/security.h"
      25             : #include "trans2.h"
      26             : #include "../libcli/smb/smbXcli_base.h"
      27             : #include "librpc/gen_ndr/ndr_quota.h"
      28             : 
      29          16 : NTSTATUS cli_get_quota_handle(struct cli_state *cli, uint16_t *quota_fnum)
      30             : {
      31          16 :         return cli_ntcreate(cli, FAKE_FILE_NAME_QUOTA_WIN32,
      32             :                  0x00000016, DESIRED_ACCESS_PIPE,
      33             :                  0x00000000, FILE_SHARE_READ|FILE_SHARE_WRITE,
      34             :                  FILE_OPEN, 0x00000000, 0x03, quota_fnum, NULL);
      35             : }
      36             : 
      37          33 : void free_ntquota_list(SMB_NTQUOTA_LIST **qt_list)
      38             : {
      39          33 :         if (!qt_list || !*qt_list) {
      40           9 :                 return;
      41             :         }
      42             : 
      43          24 :         if ((*qt_list)->mem_ctx)
      44          24 :                 talloc_destroy((*qt_list)->mem_ctx);
      45             : 
      46          24 :         (*qt_list) = NULL;
      47             : 
      48          24 :         return;
      49             : }
      50             : 
      51          76 : bool add_record_to_ntquota_list(TALLOC_CTX *mem_ctx,
      52             :                                 SMB_NTQUOTA_STRUCT *pqt,
      53             :                                 SMB_NTQUOTA_LIST **pqt_list)
      54             : {
      55           0 :         SMB_NTQUOTA_LIST *tmp_list_ent;
      56             : 
      57          76 :         if ((tmp_list_ent = talloc_zero(mem_ctx, SMB_NTQUOTA_LIST)) == NULL) {
      58           0 :                 return false;
      59             :         }
      60             : 
      61          76 :         if ((tmp_list_ent->quotas = talloc_zero(mem_ctx, SMB_NTQUOTA_STRUCT)) ==
      62             :             NULL) {
      63           0 :                 return false;
      64             :         }
      65             : 
      66          76 :         *tmp_list_ent->quotas = *pqt;
      67          76 :         tmp_list_ent->mem_ctx = mem_ctx;
      68             : 
      69          76 :         DLIST_ADD((*pqt_list), tmp_list_ent);
      70             : 
      71          76 :         return true;
      72             : }
      73             : 
      74          84 : bool parse_user_quota_record(const uint8_t *rdata,
      75             :                              unsigned int rdata_count,
      76             :                              unsigned int *offset,
      77             :                              SMB_NTQUOTA_STRUCT *pqt)
      78             : {
      79          84 :         struct file_quota_information info = {0};
      80          84 :         TALLOC_CTX *frame = talloc_stackframe();
      81           0 :         DATA_BLOB blob;
      82           0 :         enum ndr_err_code err;
      83          84 :         bool result = false;
      84             : 
      85          84 :         blob.data = discard_const_p(uint8_t, rdata);
      86          84 :         blob.length = rdata_count;
      87          84 :         err = ndr_pull_struct_blob(
      88             :                         &blob,
      89             :                         frame,
      90             :                         &info,
      91             :                         (ndr_pull_flags_fn_t)ndr_pull_file_quota_information);
      92             : 
      93          84 :         if (!NDR_ERR_CODE_IS_SUCCESS(err)) {
      94           0 :                 goto out;
      95             :         }
      96             : 
      97          84 :         *offset = info.next_entry_offset;
      98             : 
      99          84 :         ZERO_STRUCTP(pqt);
     100          84 :         pqt->usedspace = info.quota_used;
     101             : 
     102          84 :         pqt->softlim = info.quota_threshold;
     103             : 
     104          84 :         pqt->hardlim = info.quota_limit;
     105             : 
     106          84 :         pqt->qtype = SMB_USER_QUOTA_TYPE;
     107          84 :         pqt->sid = info.sid;
     108          84 :         result = true;
     109          84 : out:
     110          84 :         TALLOC_FREE(frame);
     111          84 :         return result;
     112             : }
     113             : 
     114           4 : NTSTATUS parse_user_quota_list(const uint8_t *curdata,
     115             :                                uint32_t curdata_count,
     116             :                                TALLOC_CTX *mem_ctx,
     117             :                                SMB_NTQUOTA_LIST **pqt_list)
     118             : {
     119           4 :         NTSTATUS status = NT_STATUS_OK;
     120           0 :         unsigned offset;
     121           0 :         SMB_NTQUOTA_STRUCT qt;
     122             : 
     123           0 :         while (true) {
     124          72 :                 ZERO_STRUCT(qt);
     125          72 :                 if (!parse_user_quota_record(curdata, curdata_count, &offset,
     126             :                                              &qt)) {
     127           0 :                         DEBUG(1, ("Failed to parse the quota record\n"));
     128           0 :                         status = NT_STATUS_INVALID_NETWORK_RESPONSE;
     129           0 :                         break;
     130             :                 }
     131             : 
     132          72 :                 if (offset > curdata_count) {
     133           0 :                         DEBUG(1, ("out of bounds offset in quota record\n"));
     134           0 :                         status = NT_STATUS_INVALID_NETWORK_RESPONSE;
     135           0 :                         break;
     136             :                 }
     137             : 
     138           0 :                 if (curdata + offset < curdata) {
     139             :                         DEBUG(1, ("Pointer overflow in quota record\n"));
     140             :                         status = NT_STATUS_INVALID_NETWORK_RESPONSE;
     141             :                         break;
     142             :                 }
     143             : 
     144          72 :                 if (!add_record_to_ntquota_list(mem_ctx, &qt, pqt_list)) {
     145           0 :                         status = NT_STATUS_NO_MEMORY;
     146           0 :                         break;
     147             :                 }
     148             : 
     149          72 :                 curdata += offset;
     150          72 :                 curdata_count -= offset;
     151             : 
     152          72 :                 if (offset == 0) {
     153           4 :                         break;
     154             :                 }
     155             :         }
     156             : 
     157           4 :         return status;
     158             : }
     159             : 
     160           0 : NTSTATUS parse_fs_quota_buffer(const uint8_t *rdata,
     161             :                                unsigned int rdata_count,
     162             :                                SMB_NTQUOTA_STRUCT *pqt)
     163             : {
     164           0 :         SMB_NTQUOTA_STRUCT qt;
     165             : 
     166           0 :         ZERO_STRUCT(qt);
     167             : 
     168           0 :         if (rdata_count < 48) {
     169             :                 /* minimum length is not enforced by SMB2 client.
     170             :                  */
     171           0 :                 DEBUG(1, ("small returned fs quota buffer\n"));
     172           0 :                 return NT_STATUS_INVALID_NETWORK_RESPONSE;
     173             :         }
     174             : 
     175             :         /* unknown_1 24 NULL bytes in pdata*/
     176             : 
     177             :         /* the soft quotas 8 bytes (uint64_t)*/
     178           0 :         qt.softlim = BVAL(rdata, 24);
     179             : 
     180             :         /* the hard quotas 8 bytes (uint64_t)*/
     181           0 :         qt.hardlim = BVAL(rdata, 32);
     182             : 
     183             :         /* quota_flags 2 bytes **/
     184           0 :         qt.qflags = SVAL(rdata, 40);
     185             : 
     186           0 :         qt.qtype = SMB_USER_FS_QUOTA_TYPE;
     187             : 
     188           0 :         *pqt = qt;
     189             : 
     190           0 :         return NT_STATUS_OK;
     191             : }
     192             : 
     193           4 : NTSTATUS build_user_quota_buffer(SMB_NTQUOTA_LIST *qt_list,
     194             :                                  uint32_t maxlen,
     195             :                                  TALLOC_CTX *mem_ctx,
     196             :                                  DATA_BLOB *outbuf,
     197             :                                  SMB_NTQUOTA_LIST **end_ptr)
     198             : {
     199           4 :         return fill_quota_buffer(mem_ctx,
     200             :                                  qt_list,
     201             :                                  false,
     202             :                                  maxlen,
     203             :                                  outbuf,
     204             :                                  end_ptr);
     205             : }
     206             : 
     207           0 : NTSTATUS build_fs_quota_buffer(TALLOC_CTX *mem_ctx,
     208             :                                const SMB_NTQUOTA_STRUCT *pqt,
     209             :                                DATA_BLOB *blob,
     210             :                                uint32_t maxlen)
     211             : {
     212           0 :         uint8_t *buf;
     213             : 
     214           0 :         if (maxlen > 0 && maxlen < 48) {
     215           0 :                 return NT_STATUS_BUFFER_TOO_SMALL;
     216             :         }
     217             : 
     218           0 :         *blob = data_blob_talloc_zero(mem_ctx, 48);
     219             : 
     220           0 :         if (!blob->data) {
     221           0 :                 return NT_STATUS_NO_MEMORY;
     222             :         }
     223             : 
     224           0 :         buf = blob->data;
     225             : 
     226             :         /* Unknown1 24 NULL bytes*/
     227           0 :         SBIG_UINT(buf, 0, (uint64_t)0);
     228           0 :         SBIG_UINT(buf, 8, (uint64_t)0);
     229           0 :         SBIG_UINT(buf, 16, (uint64_t)0);
     230             : 
     231             :         /* Default Soft Quota 8 bytes */
     232           0 :         SBIG_UINT(buf, 24, pqt->softlim);
     233             : 
     234             :         /* Default Hard Quota 8 bytes */
     235           0 :         SBIG_UINT(buf, 32, pqt->hardlim);
     236             : 
     237             :         /* Quota flag 4 bytes */
     238           0 :         SIVAL(buf, 40, pqt->qflags);
     239             : 
     240             :         /* 4 padding bytes */
     241           0 :         SIVAL(buf, 44, 0);
     242             : 
     243           0 :         return NT_STATUS_OK;
     244             : }
     245             : 
     246          12 : NTSTATUS cli_get_user_quota(struct cli_state *cli, int quota_fnum,
     247             :                             SMB_NTQUOTA_STRUCT *pqt)
     248             : {
     249           0 :         uint16_t setup[1];
     250          12 :         uint8_t *rparam = NULL, *rdata = NULL;
     251           0 :         uint32_t rparam_count, rdata_count;
     252           0 :         unsigned int sid_len;
     253           0 :         unsigned int offset;
     254          12 :         struct nttrans_query_quota_params get_quota = {0};
     255          12 :         struct file_get_quota_info info =  {0};
     256           0 :         enum ndr_err_code err;
     257           0 :         NTSTATUS status;
     258          12 :         TALLOC_CTX *frame = talloc_stackframe();
     259          12 :         DATA_BLOB data_blob = data_blob_null;
     260          12 :         DATA_BLOB param_blob = data_blob_null;
     261             : 
     262          12 :         if (!cli||!pqt) {
     263           0 :                 smb_panic("cli_get_user_quota() called with NULL Pointer!");
     264             :         }
     265             : 
     266          12 :         if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
     267          10 :                 TALLOC_FREE(frame);
     268          10 :                 return cli_smb2_get_user_quota(cli, quota_fnum, pqt);
     269             :         }
     270             : 
     271           2 :         get_quota.fid = quota_fnum;
     272           2 :         get_quota.return_single_entry = 1;
     273           2 :         get_quota.restart_scan = 0;
     274             : 
     275           2 :         sid_len = ndr_size_dom_sid(&pqt->sid, 0);
     276             : 
     277           2 :         info.next_entry_offset = 0;
     278           2 :         info.sid_length = sid_len;
     279           2 :         info.sid = pqt->sid;
     280             : 
     281           2 :         err = ndr_push_struct_blob(
     282             :                         &data_blob,
     283             :                         frame,
     284             :                         &info,
     285             :                         (ndr_push_flags_fn_t)ndr_push_file_get_quota_info);
     286             : 
     287           2 :         if (!NDR_ERR_CODE_IS_SUCCESS(err)) {
     288           0 :                 status = NT_STATUS_INTERNAL_ERROR;
     289           0 :                 goto out;
     290             :         }
     291             : 
     292           2 :         get_quota.sid_list_length = data_blob.length;
     293           2 :         get_quota.start_sid_offset = data_blob.length;
     294             : 
     295           2 :         err = ndr_push_struct_blob(
     296             :                 &param_blob,
     297             :                 frame,
     298             :                 &get_quota,
     299             :                 (ndr_push_flags_fn_t)ndr_push_nttrans_query_quota_params);
     300             : 
     301           2 :         if (!NDR_ERR_CODE_IS_SUCCESS(err)) {
     302           0 :                 status = NT_STATUS_INTERNAL_ERROR;
     303           0 :                 goto out;
     304             :         }
     305             : 
     306           2 :         status = cli_trans(talloc_tos(), cli, SMBnttrans,
     307             :                            NULL, -1, /* name, fid */
     308             :                            NT_TRANSACT_GET_USER_QUOTA, 0,
     309             :                            setup, 1, 0, /* setup */
     310           2 :                            param_blob.data, param_blob.length, 4, /* params */
     311           2 :                            data_blob.data, data_blob.length, 112, /* data */
     312             :                            NULL,                /* recv_flags2 */
     313             :                            NULL, 0, NULL,       /* rsetup */
     314             :                            &rparam, 4, &rparam_count,
     315             :                            &rdata, 8, &rdata_count);
     316           2 :         if (!NT_STATUS_IS_OK(status)) {
     317           0 :                 DEBUG(1, ("NT_TRANSACT_GET_USER_QUOTA failed: %s\n",
     318             :                           nt_errstr(status)));
     319           0 :                 goto out;
     320             :         }
     321             : 
     322           2 :         if (!parse_user_quota_record(rdata, rdata_count, &offset, pqt)) {
     323           0 :                 status = NT_STATUS_INVALID_NETWORK_RESPONSE;
     324           0 :                 DEBUG(0,("Got INVALID NT_TRANSACT_GET_USER_QUOTA reply.\n"));
     325             :         }
     326             : 
     327           2 : out:
     328           2 :         TALLOC_FREE(rparam);
     329           2 :         TALLOC_FREE(rdata);
     330           2 :         TALLOC_FREE(frame);
     331           2 :         return status;
     332             : }
     333             : 
     334             : NTSTATUS
     335           4 : cli_set_user_quota(struct cli_state *cli, int quota_fnum, SMB_NTQUOTA_LIST *qtl)
     336             : {
     337           0 :         uint16_t setup[1];
     338           0 :         uint8_t params[2];
     339           4 :         DATA_BLOB data = data_blob_null;
     340           0 :         NTSTATUS status;
     341             : 
     342           4 :         if (!cli || !qtl) {
     343           0 :                 smb_panic("cli_set_user_quota() called with NULL Pointer!");
     344             :         }
     345             : 
     346           4 :         if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
     347           4 :                 return cli_smb2_set_user_quota(cli, quota_fnum, qtl);
     348             :         }
     349             : 
     350           0 :         status = build_user_quota_buffer(qtl, 0, talloc_tos(), &data, NULL);
     351           0 :         if (!NT_STATUS_IS_OK(status)) {
     352             :                 /*
     353             :                  * smb1 doesn't send NT_STATUS_NO_MORE_ENTRIES so swallow
     354             :                  * this status.
     355             :                  */
     356           0 :                 if (!NT_STATUS_EQUAL(status, NT_STATUS_NO_MORE_ENTRIES)) {
     357           0 :                         goto cleanup;
     358             :                 }
     359             :         }
     360             : 
     361           0 :         SSVAL(setup + 0, 0, NT_TRANSACT_SET_USER_QUOTA);
     362             : 
     363           0 :         SSVAL(params,0,quota_fnum);
     364             : 
     365           0 :         status = cli_trans(talloc_tos(), cli, SMBnttrans,
     366             :                            NULL, -1, /* name, fid */
     367             :                            NT_TRANSACT_SET_USER_QUOTA, 0,
     368             :                            setup, 1, 0, /* setup */
     369             :                            params, 2, 0, /* params */
     370           0 :                            data.data, data.length, 0, /* data */
     371             :                            NULL,                /* recv_flags2 */
     372             :                            NULL, 0, NULL,       /* rsetup */
     373             :                            NULL, 0, NULL,       /* rparams */
     374             :                            NULL, 0, NULL);      /* rdata */
     375             : 
     376           0 :         if (!NT_STATUS_IS_OK(status)) {
     377           0 :                 DEBUG(1, ("NT_TRANSACT_SET_USER_QUOTA failed: %s\n",
     378             :                           nt_errstr(status)));
     379             :         }
     380             : 
     381           0 : cleanup:
     382           0 :         data_blob_free(&data);
     383           0 :         return status;
     384             : }
     385             : 
     386           8 : static NTSTATUS cli_list_user_quota_step(struct cli_state *cli,
     387             :                                          TALLOC_CTX *mem_ctx,
     388             :                                          int quota_fnum,
     389             :                                          SMB_NTQUOTA_LIST **pqt_list,
     390             :                                          bool first)
     391             : {
     392           0 :         uint16_t setup[1];
     393           8 :         DATA_BLOB params_blob = data_blob_null;
     394           8 :         uint8_t *rparam=NULL, *rdata=NULL;
     395           8 :         uint32_t rparam_count=0, rdata_count=0;
     396           0 :         NTSTATUS status;
     397           8 :         struct nttrans_query_quota_params quota_params = {0};
     398           0 :         enum ndr_err_code err;
     399             : 
     400           8 :         TALLOC_CTX *frame = NULL;
     401           8 :         if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
     402           8 :                 return cli_smb2_list_user_quota_step(cli, mem_ctx, quota_fnum,
     403             :                                                      pqt_list, first);
     404             :         }
     405           0 :         frame = talloc_stackframe();
     406             : 
     407           0 :         SSVAL(setup + 0, 0, NT_TRANSACT_GET_USER_QUOTA);
     408             : 
     409           0 :         quota_params.fid = quota_fnum;
     410           0 :         if (first) {
     411           0 :                 quota_params.restart_scan = 1;
     412             :         }
     413           0 :         err = ndr_push_struct_blob(
     414             :                 &params_blob,
     415             :                 frame,
     416             :                 &quota_params,
     417             :                 (ndr_push_flags_fn_t)ndr_push_nttrans_query_quota_params);
     418             : 
     419           0 :         if (!NDR_ERR_CODE_IS_SUCCESS(err)) {
     420           0 :                 status = NT_STATUS_INVALID_PARAMETER;
     421           0 :                 goto cleanup;
     422             :         }
     423             : 
     424           0 :         status = cli_trans(talloc_tos(), cli, SMBnttrans,
     425             :                            NULL, -1, /* name, fid */
     426             :                            NT_TRANSACT_GET_USER_QUOTA, 0,
     427             :                            setup, 1, 0, /* setup */
     428           0 :                            params_blob.data, params_blob.length, 4, /* params */
     429             :                            NULL, 0, 2048, /* data */
     430             :                            NULL,                /* recv_flags2 */
     431             :                            NULL, 0, NULL,       /* rsetup */
     432             :                            &rparam, 0, &rparam_count,
     433             :                            &rdata, 0, &rdata_count);
     434             : 
     435             :         /* compat. with smbd + safeguard against
     436             :          * endless loop
     437             :          */
     438           0 :         if (NT_STATUS_IS_OK(status) && rdata_count == 0) {
     439           0 :                 status = NT_STATUS_NO_MORE_ENTRIES;
     440             :         }
     441             : 
     442           0 :         if (!NT_STATUS_IS_OK(status)) {
     443           0 :                 goto cleanup;
     444             :         }
     445             : 
     446           0 :         status = parse_user_quota_list(rdata, rdata_count, mem_ctx, pqt_list);
     447             : 
     448           0 : cleanup:
     449           0 :         TALLOC_FREE(rparam);
     450           0 :         TALLOC_FREE(rdata);
     451           0 :         TALLOC_FREE(frame);
     452             : 
     453           0 :         return status;
     454             : }
     455             : 
     456           4 : NTSTATUS cli_list_user_quota(struct cli_state *cli,
     457             :                              int quota_fnum,
     458             :                              SMB_NTQUOTA_LIST **pqt_list)
     459             : {
     460           0 :         NTSTATUS status;
     461           4 :         TALLOC_CTX *mem_ctx = NULL;
     462           4 :         bool first = true;
     463             : 
     464           4 :         if (!cli || !pqt_list) {
     465           0 :                 smb_panic("cli_list_user_quota() called with NULL Pointer!");
     466             :         }
     467             : 
     468           4 :         *pqt_list = NULL;
     469             : 
     470           4 :         if ((mem_ctx = talloc_init("SMB_USER_QUOTA_LIST")) == NULL) {
     471           0 :                 return NT_STATUS_NO_MEMORY;
     472             :         }
     473             : 
     474           0 :         do {
     475           8 :                 status = cli_list_user_quota_step(cli, mem_ctx, quota_fnum,
     476             :                                                   pqt_list, first);
     477           8 :                 first = false;
     478           8 :         } while (NT_STATUS_IS_OK(status));
     479             : 
     480           4 :         if (NT_STATUS_EQUAL(status, NT_STATUS_NO_MORE_ENTRIES)) {
     481           4 :                 status = NT_STATUS_OK;
     482             :         }
     483             : 
     484           4 :         if (!NT_STATUS_IS_OK(status) || *pqt_list == NULL) {
     485           0 :                 TALLOC_FREE(mem_ctx);
     486             :         }
     487             : 
     488           4 :         return status;
     489             : }
     490             : 
     491           0 : NTSTATUS cli_get_fs_quota_info(struct cli_state *cli, int quota_fnum,
     492             :                                SMB_NTQUOTA_STRUCT *pqt)
     493             : {
     494           0 :         uint16_t setup[1];
     495           0 :         uint8_t param[2];
     496           0 :         uint8_t *rdata=NULL;
     497           0 :         uint32_t rdata_count=0;
     498           0 :         NTSTATUS status;
     499             : 
     500           0 :         if (!cli||!pqt) {
     501           0 :                 smb_panic("cli_get_fs_quota_info() called with NULL Pointer!");
     502             :         }
     503             : 
     504           0 :         if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
     505           0 :                 return cli_smb2_get_fs_quota_info(cli, quota_fnum, pqt);
     506             :         }
     507             : 
     508           0 :         SSVAL(setup + 0, 0, TRANSACT2_QFSINFO);
     509             : 
     510           0 :         SSVAL(param,0,SMB_FS_QUOTA_INFORMATION);
     511             : 
     512           0 :         status = cli_trans(talloc_tos(), cli, SMBtrans2,
     513             :                            NULL, -1, /* name, fid */
     514             :                            0, 0,     /* function, flags */
     515             :                            setup, 1, 0, /* setup */
     516             :                            param, 2, 0, /* param */
     517             :                            NULL, 0, 560, /* data */
     518             :                            NULL,         /* recv_flags2 */
     519             :                            NULL, 0, NULL, /* rsetup */
     520             :                            NULL, 0, NULL, /* rparam */
     521             :                            &rdata, 48, &rdata_count);
     522             : 
     523           0 :         if (!NT_STATUS_IS_OK(status)) {
     524           0 :                 DEBUG(1, ("SMB_FS_QUOTA_INFORMATION failed: %s\n",
     525             :                           nt_errstr(status)));
     526           0 :                 return status;
     527             :         }
     528             : 
     529           0 :         status = parse_fs_quota_buffer(rdata, rdata_count, pqt);
     530             : 
     531           0 :         TALLOC_FREE(rdata);
     532           0 :         return status;
     533             : }
     534             : 
     535           0 : NTSTATUS cli_set_fs_quota_info(struct cli_state *cli, int quota_fnum,
     536             :                                SMB_NTQUOTA_STRUCT *pqt)
     537             : {
     538           0 :         uint16_t setup[1];
     539           0 :         uint8_t param[4];
     540           0 :         DATA_BLOB data = data_blob_null;
     541           0 :         NTSTATUS status;
     542             : 
     543           0 :         if (!cli||!pqt) {
     544           0 :                 smb_panic("cli_set_fs_quota_info() called with NULL Pointer!");
     545             :         }
     546             : 
     547           0 :         if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
     548           0 :                 return cli_smb2_set_fs_quota_info(cli, quota_fnum, pqt);
     549             :         }
     550             : 
     551           0 :         status = build_fs_quota_buffer(talloc_tos(), pqt, &data, 0);
     552           0 :         if (!NT_STATUS_IS_OK(status)) {
     553           0 :                 return status;
     554             :         }
     555             : 
     556           0 :         SSVAL(setup + 0, 0,TRANSACT2_SETFSINFO);
     557             : 
     558           0 :         SSVAL(param,0,quota_fnum);
     559           0 :         SSVAL(param,2,SMB_FS_QUOTA_INFORMATION);
     560             : 
     561           0 :         status = cli_trans(talloc_tos(), cli, SMBtrans2,
     562             :                            NULL, -1, /* name, fid */
     563             :                            0, 0,     /* function, flags */
     564             :                            setup, 1, 0, /* setup */
     565             :                            param, 4, 0, /* param */
     566           0 :                            data.data, data.length, 0, /* data */
     567             :                            NULL,         /* recv_flags2 */
     568             :                            NULL, 0, NULL, /* rsetup */
     569             :                            NULL, 0, NULL, /* rparam */
     570             :                            NULL, 0, NULL); /* rdata */
     571             : 
     572           0 :         if (!NT_STATUS_IS_OK(status)) {
     573           0 :                 DEBUG(1, ("SMB_FS_QUOTA_INFORMATION failed: %s\n",
     574             :                           nt_errstr(status)));
     575             :         }
     576             : 
     577           0 :         return status;
     578             : }
     579             : 
     580          24 : NTSTATUS fill_quota_buffer(TALLOC_CTX *mem_ctx,
     581             :                               SMB_NTQUOTA_LIST *qlist,
     582             :                               bool return_single,
     583             :                               uint32_t max_data,
     584             :                               DATA_BLOB *blob,
     585             :                               SMB_NTQUOTA_LIST **end_ptr)
     586             : {
     587          24 :         ndr_flags_type ndr_flags = NDR_SCALARS | NDR_BUFFERS;
     588          24 :         struct ndr_push *qndr = NULL;
     589          24 :         uint32_t start_offset = 0;
     590          24 :         uint32_t padding = 0;
     591          24 :         if (qlist == NULL) {
     592             :                 /* We must push at least one. */
     593           4 :                 return NT_STATUS_NO_MORE_ENTRIES;
     594             :         }
     595             : 
     596          20 :         qndr = ndr_push_init_ctx(mem_ctx);
     597          20 :         if (qndr == NULL) {
     598           0 :                 return NT_STATUS_NO_MEMORY;
     599             :         }
     600             : 
     601          96 :         for (;qlist != NULL; qlist = qlist->next) {
     602          88 :                 struct file_quota_information info = {0};
     603           0 :                 enum ndr_err_code err;
     604          88 :                 uint32_t dsize = sizeof(info.next_entry_offset)
     605             :                         + sizeof(info.sid_length)
     606             :                         + sizeof(info.change_time)
     607             :                         + sizeof(info.quota_used)
     608             :                         + sizeof(info.quota_threshold)
     609             :                         + sizeof(info.quota_limit);
     610             : 
     611             : 
     612          88 :                 info.sid_length = ndr_size_dom_sid(&qlist->quotas->sid, 0);
     613             : 
     614          88 :                 if (max_data) {
     615          84 :                         uint32_t curr_pos_no_padding = qndr->offset - padding;
     616          84 :                         uint32_t payload = dsize + info.sid_length;
     617          84 :                         uint32_t new_pos = (curr_pos_no_padding + payload);
     618          84 :                         if (new_pos < curr_pos_no_padding) {
     619             :                                 /* Detect unlikely integer wrap */
     620           0 :                                 DBG_ERR("Integer wrap while adjusting pos "
     621             :                                         "0x%x by offset 0x%x\n",
     622             :                                         curr_pos_no_padding, payload);
     623           0 :                                 return NT_STATUS_INTERNAL_ERROR;
     624             :                         }
     625          84 :                         if (new_pos > max_data) {
     626           0 :                                 DBG_WARNING("Max data will be exceeded "
     627             :                                             "writing next query info. "
     628             :                                             "cur_pos 0x%x, sid_length 0x%x, "
     629             :                                             "dsize 0x%x, max_data 0x%x\n",
     630             :                                             curr_pos_no_padding,
     631             :                                             info.sid_length,
     632             :                                             dsize,
     633             :                                             max_data);
     634          12 :                                 break;
     635             :                         }
     636             :                 }
     637             : 
     638          88 :                 start_offset = qndr->offset;
     639          88 :                 info.sid = qlist->quotas->sid;
     640          88 :                 info.quota_used = qlist->quotas->usedspace;
     641          88 :                 info.quota_threshold = qlist->quotas->softlim;
     642          88 :                 info.quota_limit = qlist->quotas->hardlim;
     643             : 
     644          88 :                 err = ndr_push_file_quota_information(qndr,
     645             :                                                       ndr_flags,
     646             :                                                       &info);
     647             : 
     648          88 :                 if (!NDR_ERR_CODE_IS_SUCCESS(err)) {
     649           0 :                         DBG_DEBUG("Failed to push the quota sid\n");
     650           0 :                         return NT_STATUS_INTERNAL_ERROR;
     651             :                 }
     652             : 
     653             :                 /* pidl will align to 8 bytes due to 8 byte members*/
     654             :                 /* Remember how much align padding we've used. */
     655          88 :                 padding = qndr->offset;
     656             : 
     657          88 :                 err = ndr_push_align(qndr, 8);
     658          88 :                 if (!NDR_ERR_CODE_IS_SUCCESS(err)) {
     659           0 :                         DBG_DEBUG("ndr_push_align returned %s\n",
     660             :                                   ndr_map_error2string(err));
     661           0 :                         return ndr_map_error2ntstatus(err);
     662             :                 }
     663             : 
     664          88 :                 padding = qndr->offset - padding;
     665             : 
     666             :                 /*
     667             :                  * Overwrite next_entry_offset for this entry now
     668             :                  * we know what it should be. We know we're using
     669             :                  * LIBNDR_FLAG_LITTLE_ENDIAN here so we can use
     670             :                  * SIVAL.
     671             :                  */
     672          88 :                 info.next_entry_offset = qndr->offset - start_offset;
     673          88 :                 SIVAL(qndr->data, start_offset, info.next_entry_offset);
     674             : 
     675          88 :                 if (return_single) {
     676          12 :                         break;
     677             :                 }
     678             :         }
     679             : 
     680          20 :         if (end_ptr != NULL) {
     681          16 :                 *end_ptr = qlist;
     682             :         }
     683             : 
     684             :         /* Remove the padding alignment on the last element pushed. */
     685          20 :         blob->length = qndr->offset - padding;
     686          20 :         blob->data = qndr->data;
     687             : 
     688             :         /*
     689             :          * Terminate the pushed array by setting next_entry_offset
     690             :          * for the last element to zero.
     691             :          */
     692          20 :         if (blob->length >= sizeof(uint32_t)) {
     693          20 :                 SIVAL(qndr->data, start_offset, 0);
     694             :         }
     695          20 :         return NT_STATUS_OK;
     696             : }

Generated by: LCOV version 1.14