2 Unix SMB/CIFS implementation.
4 Copyright (C) Stefan (metze) Metzmacher 2003
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.
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.
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/>.
21 #include "libsmb/libsmb.h"
22 #include "../librpc/gen_ndr/ndr_security.h"
23 #include "fake_file.h"
24 #include "../libcli/security/security.h"
27 NTSTATUS cli_get_quota_handle(struct cli_state *cli, uint16_t *quota_fnum)
29 return cli_ntcreate(cli, FAKE_FILE_NAME_QUOTA_WIN32,
30 0x00000016, DESIRED_ACCESS_PIPE,
31 0x00000000, FILE_SHARE_READ|FILE_SHARE_WRITE,
32 FILE_OPEN, 0x00000000, 0x03, quota_fnum, NULL);
35 void free_ntquota_list(SMB_NTQUOTA_LIST **qt_list)
37 if (!qt_list || !*qt_list) {
41 if ((*qt_list)->mem_ctx)
42 talloc_destroy((*qt_list)->mem_ctx);
49 static bool parse_user_quota_record(const uint8_t *rdata,
50 unsigned int rdata_count,
52 SMB_NTQUOTA_STRUCT *pqt)
55 SMB_NTQUOTA_STRUCT qt;
59 if (!rdata||!offset||!pqt) {
60 smb_panic("parse_quota_record: called with NULL POINTER!");
63 if (rdata_count < 40) {
67 /* offset to next quota record.
68 * 4 bytes IVAL(rdata,0)
71 *offset = IVAL(rdata,0);
74 sid_len = IVAL(rdata,4);
76 if (rdata_count < 40+sid_len) {
80 /* unknown 8 bytes in pdata
81 * maybe its the change time in NTTIME
84 /* the used space 8 bytes (uint64_t)*/
85 qt.usedspace = BVAL(rdata,16);
87 /* the soft quotas 8 bytes (uint64_t)*/
88 qt.softlim = BVAL(rdata,24);
90 /* the hard quotas 8 bytes (uint64_t)*/
91 qt.hardlim = BVAL(rdata,32);
93 if (!sid_parse(rdata+40,sid_len,&qt.sid)) {
97 qt.qtype = SMB_USER_QUOTA_TYPE;
104 NTSTATUS cli_get_user_quota(struct cli_state *cli, int quota_fnum,
105 SMB_NTQUOTA_STRUCT *pqt)
109 unsigned int data_len;
110 uint8_t data[SID_MAX_SIZE+8];
111 uint8_t *rparam, *rdata;
112 uint32_t rparam_count, rdata_count;
113 unsigned int sid_len;
118 smb_panic("cli_get_user_quota() called with NULL Pointer!");
121 SSVAL(setup + 0, 0, NT_TRANSACT_GET_USER_QUOTA);
123 SSVAL(params, 0,quota_fnum);
124 SSVAL(params, 2,TRANSACT_GET_USER_QUOTA_FOR_SID);
125 SIVAL(params, 4,0x00000024);
126 SIVAL(params, 8,0x00000000);
127 SIVAL(params,12,0x00000024);
129 sid_len = ndr_size_dom_sid(&pqt->sid, 0);
130 data_len = sid_len+8;
131 SIVAL(data, 0, 0x00000000);
132 SIVAL(data, 4, sid_len);
133 sid_linearize(data+8, sid_len, &pqt->sid);
135 status = cli_trans(talloc_tos(), cli, SMBnttrans,
136 NULL, -1, /* name, fid */
137 NT_TRANSACT_GET_USER_QUOTA, 0,
138 setup, 1, 0, /* setup */
139 params, 16, 4, /* params */
140 data, data_len, 112, /* data */
141 NULL, /* recv_flags2 */
142 NULL, 0, NULL, /* rsetup */
143 &rparam, 4, &rparam_count,
144 &rdata, 8, &rdata_count);
145 if (!NT_STATUS_IS_OK(status)) {
146 DEBUG(1, ("NT_TRANSACT_GET_USER_QUOTA failed: %s\n",
151 if (!parse_user_quota_record(rdata, rdata_count, &offset, pqt)) {
152 status = NT_STATUS_INVALID_NETWORK_RESPONSE;
153 DEBUG(0,("Got INVALID NT_TRANSACT_GET_USER_QUOTA reply.\n"));
161 NTSTATUS cli_set_user_quota(struct cli_state *cli, int quota_fnum,
162 SMB_NTQUOTA_STRUCT *pqt)
167 unsigned int sid_len;
170 memset(data,'\0',112);
173 smb_panic("cli_set_user_quota() called with NULL Pointer!");
176 SSVAL(setup + 0, 0, NT_TRANSACT_SET_USER_QUOTA);
178 SSVAL(params,0,quota_fnum);
180 sid_len = ndr_size_dom_sid(&pqt->sid, 0);
182 SIVAL(data,4,sid_len);
183 SBIG_UINT(data, 8,(uint64_t)0);
184 SBIG_UINT(data,16,pqt->usedspace);
185 SBIG_UINT(data,24,pqt->softlim);
186 SBIG_UINT(data,32,pqt->hardlim);
187 sid_linearize(data+40, sid_len, &pqt->sid);
189 status = cli_trans(talloc_tos(), cli, SMBnttrans,
190 NULL, -1, /* name, fid */
191 NT_TRANSACT_SET_USER_QUOTA, 0,
192 setup, 1, 0, /* setup */
193 params, 2, 0, /* params */
194 data, 112, 0, /* data */
195 NULL, /* recv_flags2 */
196 NULL, 0, NULL, /* rsetup */
197 NULL, 0, NULL, /* rparams */
198 NULL, 0, NULL); /* rdata */
200 if (!NT_STATUS_IS_OK(status)) {
201 DEBUG(1, ("NT_TRANSACT_SET_USER_QUOTA failed: %s\n",
208 NTSTATUS cli_list_user_quota(struct cli_state *cli, int quota_fnum,
209 SMB_NTQUOTA_LIST **pqt_list)
213 uint8_t *rparam=NULL, *rdata=NULL;
214 uint32_t rparam_count=0, rdata_count=0;
216 const uint8_t *curdata = NULL;
217 unsigned int curdata_count = 0;
218 TALLOC_CTX *mem_ctx = NULL;
219 SMB_NTQUOTA_STRUCT qt;
220 SMB_NTQUOTA_LIST *tmp_list_ent;
223 if (!cli||!pqt_list) {
224 smb_panic("cli_list_user_quota() called with NULL Pointer!");
227 SSVAL(setup + 0, 0, NT_TRANSACT_GET_USER_QUOTA);
229 SSVAL(params, 0,quota_fnum);
230 SSVAL(params, 2,TRANSACT_GET_USER_QUOTA_LIST_START);
231 SIVAL(params, 4,0x00000000);
232 SIVAL(params, 8,0x00000000);
233 SIVAL(params,12,0x00000000);
235 status = cli_trans(talloc_tos(), cli, SMBnttrans,
236 NULL, -1, /* name, fid */
237 NT_TRANSACT_GET_USER_QUOTA, 0,
238 setup, 1, 0, /* setup */
239 params, 16, 4, /* params */
240 NULL, 0, 2048, /* data */
241 NULL, /* recv_flags2 */
242 NULL, 0, NULL, /* rsetup */
243 &rparam, 0, &rparam_count,
244 &rdata, 0, &rdata_count);
246 if (!NT_STATUS_IS_OK(status) &&
247 !NT_STATUS_EQUAL(status, NT_STATUS_NO_MORE_ENTRIES)) {
248 DEBUG(1, ("NT_TRANSACT_GET_USER_QUOTA failed: %s\n",
253 if (NT_STATUS_EQUAL(status, NT_STATUS_NO_MORE_ENTRIES) ||
259 if ((mem_ctx=talloc_init("SMB_USER_QUOTA_LIST"))==NULL) {
260 DEBUG(0,("talloc_init() failed\n"));
261 return NT_STATUS_NO_MEMORY;
265 for (curdata=rdata,curdata_count=rdata_count;
266 ((curdata)&&(curdata_count>=8)&&(offset>0));
267 curdata +=offset,curdata_count -= offset) {
269 if (!parse_user_quota_record((const uint8_t *)curdata, curdata_count,
271 DEBUG(1,("Failed to parse the quota record\n"));
275 if ((tmp_list_ent=talloc_zero(mem_ctx,SMB_NTQUOTA_LIST))==NULL) {
276 DEBUG(0,("TALLOC_ZERO() failed\n"));
277 talloc_destroy(mem_ctx);
278 return NT_STATUS_NO_MEMORY;
281 if ((tmp_list_ent->quotas=talloc_zero(mem_ctx,SMB_NTQUOTA_STRUCT))==NULL) {
282 DEBUG(0,("TALLOC_ZERO() failed\n"));
283 talloc_destroy(mem_ctx);
284 return NT_STATUS_NO_MEMORY;
287 memcpy(tmp_list_ent->quotas,&qt,sizeof(qt));
288 tmp_list_ent->mem_ctx = mem_ctx;
290 DLIST_ADD((*pqt_list),tmp_list_ent);
293 SSVAL(params, 2,TRANSACT_GET_USER_QUOTA_LIST_CONTINUE);
299 status = cli_trans(talloc_tos(), cli, SMBnttrans,
300 NULL, -1, /* name, fid */
301 NT_TRANSACT_GET_USER_QUOTA, 0,
302 setup, 1, 0, /* setup */
303 params, 16, 4, /* params */
304 NULL, 0, 2048, /* data */
305 NULL, /* recv_flags2 */
306 NULL, 0, NULL, /* rsetup */
307 &rparam, 0, &rparam_count,
308 &rdata, 0, &rdata_count);
310 if (!NT_STATUS_IS_OK(status) &&
311 !NT_STATUS_EQUAL(status, NT_STATUS_NO_MORE_ENTRIES)) {
312 DEBUG(1, ("NT_TRANSACT_GET_USER_QUOTA failed: %s\n",
317 if (NT_STATUS_EQUAL(status, NT_STATUS_NO_MORE_ENTRIES) ||
319 status = NT_STATUS_OK;
324 for (curdata=rdata,curdata_count=rdata_count;
325 ((curdata)&&(curdata_count>=8)&&(offset>0));
326 curdata +=offset,curdata_count -= offset) {
328 if (!parse_user_quota_record((const uint8_t *)curdata,
329 curdata_count, &offset,
331 DEBUG(1,("Failed to parse the quota record\n"));
335 if ((tmp_list_ent=talloc_zero(mem_ctx,SMB_NTQUOTA_LIST))==NULL) {
336 DEBUG(0,("TALLOC_ZERO() failed\n"));
337 talloc_destroy(mem_ctx);
341 if ((tmp_list_ent->quotas=talloc_zero(mem_ctx,SMB_NTQUOTA_STRUCT))==NULL) {
342 DEBUG(0,("TALLOC_ZERO() failed\n"));
343 talloc_destroy(mem_ctx);
347 memcpy(tmp_list_ent->quotas,&qt,sizeof(qt));
348 tmp_list_ent->mem_ctx = mem_ctx;
350 DLIST_ADD((*pqt_list),tmp_list_ent);
361 NTSTATUS cli_get_fs_quota_info(struct cli_state *cli, int quota_fnum,
362 SMB_NTQUOTA_STRUCT *pqt)
367 uint32_t rdata_count=0;
368 SMB_NTQUOTA_STRUCT qt;
374 smb_panic("cli_get_fs_quota_info() called with NULL Pointer!");
377 SSVAL(setup + 0, 0, TRANSACT2_QFSINFO);
379 SSVAL(param,0,SMB_FS_QUOTA_INFORMATION);
381 status = cli_trans(talloc_tos(), cli, SMBtrans2,
382 NULL, -1, /* name, fid */
383 0, 0, /* function, flags */
384 setup, 1, 0, /* setup */
385 param, 2, 0, /* param */
386 NULL, 0, 560, /* data */
387 NULL, /* recv_flags2 */
388 NULL, 0, NULL, /* rsetup */
389 NULL, 0, NULL, /* rparam */
390 &rdata, 48, &rdata_count);
392 if (!NT_STATUS_IS_OK(status)) {
393 DEBUG(1, ("SMB_FS_QUOTA_INFORMATION failed: %s\n",
398 /* unknown_1 24 NULL bytes in pdata*/
400 /* the soft quotas 8 bytes (uint64_t)*/
401 qt.softlim = BVAL(rdata,24);
403 /* the hard quotas 8 bytes (uint64_t)*/
404 qt.hardlim = BVAL(rdata,32);
406 /* quota_flags 2 bytes **/
407 qt.qflags = SVAL(rdata,40);
409 qt.qtype = SMB_USER_FS_QUOTA_TYPE;
417 NTSTATUS cli_set_fs_quota_info(struct cli_state *cli, int quota_fnum,
418 SMB_NTQUOTA_STRUCT *pqt)
423 SMB_NTQUOTA_STRUCT qt;
426 memset(data,'\0',48);
429 smb_panic("cli_set_fs_quota_info() called with NULL Pointer!");
432 SSVAL(setup + 0, 0,TRANSACT2_SETFSINFO);
434 SSVAL(param,0,quota_fnum);
435 SSVAL(param,2,SMB_FS_QUOTA_INFORMATION);
437 /* Unknown1 24 NULL bytes*/
439 /* Default Soft Quota 8 bytes */
440 SBIG_UINT(data,24,pqt->softlim);
442 /* Default Hard Quota 8 bytes */
443 SBIG_UINT(data,32,pqt->hardlim);
445 /* Quota flag 2 bytes */
446 SSVAL(data,40,pqt->qflags);
448 /* Unknown3 6 NULL bytes */
450 status = cli_trans(talloc_tos(), cli, SMBtrans2,
451 NULL, -1, /* name, fid */
452 0, 0, /* function, flags */
453 setup, 1, 0, /* setup */
454 param, 8, 0, /* param */
455 data, 48, 0, /* data */
456 NULL, /* recv_flags2 */
457 NULL, 0, NULL, /* rsetup */
458 NULL, 0, NULL, /* rparam */
459 NULL, 0, NULL); /* rdata */
461 if (!NT_STATUS_IS_OK(status)) {
462 DEBUG(1, ("SMB_FS_QUOTA_INFORMATION failed: %s\n",