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 "../librpc/gen_ndr/ndr_security.h"
22 #include "fake_file.h"
23 #include "../libcli/security/security.h"
26 NTSTATUS cli_get_quota_handle(struct cli_state *cli, uint16_t *quota_fnum)
28 return cli_ntcreate(cli, FAKE_FILE_NAME_QUOTA_WIN32,
29 0x00000016, DESIRED_ACCESS_PIPE,
30 0x00000000, FILE_SHARE_READ|FILE_SHARE_WRITE,
31 FILE_OPEN, 0x00000000, 0x03, quota_fnum);
34 void free_ntquota_list(SMB_NTQUOTA_LIST **qt_list)
39 if ((*qt_list)->mem_ctx)
40 talloc_destroy((*qt_list)->mem_ctx);
47 static bool parse_user_quota_record(const uint8_t *rdata,
48 unsigned int rdata_count,
50 SMB_NTQUOTA_STRUCT *pqt)
53 SMB_NTQUOTA_STRUCT qt;
57 if (!rdata||!offset||!pqt) {
58 smb_panic("parse_quota_record: called with NULL POINTER!");
61 if (rdata_count < 40) {
65 /* offset to next quota record.
66 * 4 bytes IVAL(rdata,0)
69 *offset = IVAL(rdata,0);
72 sid_len = IVAL(rdata,4);
74 if (rdata_count < 40+sid_len) {
78 /* unknown 8 bytes in pdata
79 * maybe its the change time in NTTIME
82 /* the used space 8 bytes (uint64_t)*/
83 qt.usedspace = (uint64_t)IVAL(rdata,16);
84 #ifdef LARGE_SMB_OFF_T
85 qt.usedspace |= (((uint64_t)IVAL(rdata,20)) << 32);
86 #else /* LARGE_SMB_OFF_T */
87 if ((IVAL(rdata,20) != 0)&&
88 ((qt.usedspace != 0xFFFFFFFF)||
89 (IVAL(rdata,20)!=0xFFFFFFFF))) {
90 /* more than 32 bits? */
93 #endif /* LARGE_SMB_OFF_T */
95 /* the soft quotas 8 bytes (uint64_t)*/
96 qt.softlim = (uint64_t)IVAL(rdata,24);
97 #ifdef LARGE_SMB_OFF_T
98 qt.softlim |= (((uint64_t)IVAL(rdata,28)) << 32);
99 #else /* LARGE_SMB_OFF_T */
100 if ((IVAL(rdata,28) != 0)&&
101 ((qt.softlim != 0xFFFFFFFF)||
102 (IVAL(rdata,28)!=0xFFFFFFFF))) {
103 /* more than 32 bits? */
106 #endif /* LARGE_SMB_OFF_T */
108 /* the hard quotas 8 bytes (uint64_t)*/
109 qt.hardlim = (uint64_t)IVAL(rdata,32);
110 #ifdef LARGE_SMB_OFF_T
111 qt.hardlim |= (((uint64_t)IVAL(rdata,36)) << 32);
112 #else /* LARGE_SMB_OFF_T */
113 if ((IVAL(rdata,36) != 0)&&
114 ((qt.hardlim != 0xFFFFFFFF)||
115 (IVAL(rdata,36)!=0xFFFFFFFF))) {
116 /* more than 32 bits? */
119 #endif /* LARGE_SMB_OFF_T */
121 if (!sid_parse((char *)rdata+40,sid_len,&qt.sid)) {
125 qt.qtype = SMB_USER_QUOTA_TYPE;
132 NTSTATUS cli_get_user_quota(struct cli_state *cli, int quota_fnum,
133 SMB_NTQUOTA_STRUCT *pqt)
137 unsigned int data_len;
138 uint8_t data[SID_MAX_SIZE+8];
139 uint8_t *rparam, *rdata;
140 uint32_t rparam_count, rdata_count;
141 unsigned int sid_len;
146 smb_panic("cli_get_user_quota() called with NULL Pointer!");
149 SSVAL(setup + 0, 0, NT_TRANSACT_GET_USER_QUOTA);
151 SSVAL(params, 0,quota_fnum);
152 SSVAL(params, 2,TRANSACT_GET_USER_QUOTA_FOR_SID);
153 SIVAL(params, 4,0x00000024);
154 SIVAL(params, 8,0x00000000);
155 SIVAL(params,12,0x00000024);
157 sid_len = ndr_size_dom_sid(&pqt->sid, 0);
158 data_len = sid_len+8;
159 SIVAL(data, 0, 0x00000000);
160 SIVAL(data, 4, sid_len);
161 sid_linearize((char *)data+8, sid_len, &pqt->sid);
163 status = cli_trans(talloc_tos(), cli, SMBnttrans,
164 NULL, -1, /* name, fid */
165 NT_TRANSACT_GET_USER_QUOTA, 0,
166 setup, 1, 0, /* setup */
167 params, 16, 4, /* params */
168 data, data_len, 112, /* data */
169 NULL, /* recv_flags2 */
170 NULL, 0, NULL, /* rsetup */
171 &rparam, 4, &rparam_count,
172 &rdata, 8, &rdata_count);
173 if (!NT_STATUS_IS_OK(status)) {
174 DEBUG(1, ("NT_TRANSACT_GET_USER_QUOTA failed: %s\n",
179 if (!parse_user_quota_record(rdata, rdata_count, &offset, pqt)) {
180 status = NT_STATUS_INVALID_NETWORK_RESPONSE;
181 DEBUG(0,("Got INVALID NT_TRANSACT_GET_USER_QUOTA reply.\n"));
189 NTSTATUS cli_set_user_quota(struct cli_state *cli, int quota_fnum,
190 SMB_NTQUOTA_STRUCT *pqt)
195 unsigned int sid_len;
198 memset(data,'\0',112);
201 smb_panic("cli_set_user_quota() called with NULL Pointer!");
204 SSVAL(setup + 0, 0, NT_TRANSACT_SET_USER_QUOTA);
206 SSVAL(params,0,quota_fnum);
208 sid_len = ndr_size_dom_sid(&pqt->sid, 0);
210 SIVAL(data,4,sid_len);
211 SBIG_UINT(data, 8,(uint64_t)0);
212 SBIG_UINT(data,16,pqt->usedspace);
213 SBIG_UINT(data,24,pqt->softlim);
214 SBIG_UINT(data,32,pqt->hardlim);
215 sid_linearize((char *)data+40, sid_len, &pqt->sid);
217 status = cli_trans(talloc_tos(), cli, SMBnttrans,
218 NULL, -1, /* name, fid */
219 NT_TRANSACT_SET_USER_QUOTA, 0,
220 setup, 1, 0, /* setup */
221 params, 2, 0, /* params */
222 data, 112, 0, /* data */
223 NULL, /* recv_flags2 */
224 NULL, 0, NULL, /* rsetup */
225 NULL, 0, NULL, /* rparams */
226 NULL, 0, NULL); /* rdata */
228 if (!NT_STATUS_IS_OK(status)) {
229 DEBUG(1, ("NT_TRANSACT_SET_USER_QUOTA failed: %s\n",
236 NTSTATUS cli_list_user_quota(struct cli_state *cli, int quota_fnum,
237 SMB_NTQUOTA_LIST **pqt_list)
241 uint8_t *rparam=NULL, *rdata=NULL;
242 uint32_t rparam_count=0, rdata_count=0;
244 const uint8_t *curdata = NULL;
245 unsigned int curdata_count = 0;
246 TALLOC_CTX *mem_ctx = NULL;
247 SMB_NTQUOTA_STRUCT qt;
248 SMB_NTQUOTA_LIST *tmp_list_ent;
251 if (!cli||!pqt_list) {
252 smb_panic("cli_list_user_quota() called with NULL Pointer!");
255 SSVAL(setup + 0, 0, NT_TRANSACT_GET_USER_QUOTA);
257 SSVAL(params, 0,quota_fnum);
258 SSVAL(params, 2,TRANSACT_GET_USER_QUOTA_LIST_START);
259 SIVAL(params, 4,0x00000000);
260 SIVAL(params, 8,0x00000000);
261 SIVAL(params,12,0x00000000);
263 status = cli_trans(talloc_tos(), cli, SMBnttrans,
264 NULL, -1, /* name, fid */
265 NT_TRANSACT_GET_USER_QUOTA, 0,
266 setup, 1, 0, /* setup */
267 params, 16, 4, /* params */
268 NULL, 0, 2048, /* data */
269 NULL, /* recv_flags2 */
270 NULL, 0, NULL, /* rsetup */
271 &rparam, 0, &rparam_count,
272 &rdata, 0, &rdata_count);
274 if (!NT_STATUS_IS_OK(status)) {
275 DEBUG(1, ("NT_TRANSACT_GET_USER_QUOTA failed: %s\n",
280 if (rdata_count == 0) {
285 if ((mem_ctx=talloc_init("SMB_USER_QUOTA_LIST"))==NULL) {
286 DEBUG(0,("talloc_init() failed\n"));
287 return NT_STATUS_NO_MEMORY;
291 for (curdata=rdata,curdata_count=rdata_count;
292 ((curdata)&&(curdata_count>=8)&&(offset>0));
293 curdata +=offset,curdata_count -= offset) {
295 if (!parse_user_quota_record((uint8_t *)curdata, curdata_count,
297 DEBUG(1,("Failed to parse the quota record\n"));
301 if ((tmp_list_ent=TALLOC_ZERO_P(mem_ctx,SMB_NTQUOTA_LIST))==NULL) {
302 DEBUG(0,("TALLOC_ZERO() failed\n"));
303 talloc_destroy(mem_ctx);
304 return NT_STATUS_NO_MEMORY;
307 if ((tmp_list_ent->quotas=TALLOC_ZERO_P(mem_ctx,SMB_NTQUOTA_STRUCT))==NULL) {
308 DEBUG(0,("TALLOC_ZERO() failed\n"));
309 talloc_destroy(mem_ctx);
310 return NT_STATUS_NO_MEMORY;
313 memcpy(tmp_list_ent->quotas,&qt,sizeof(qt));
314 tmp_list_ent->mem_ctx = mem_ctx;
316 DLIST_ADD((*pqt_list),tmp_list_ent);
319 SSVAL(params, 2,TRANSACT_GET_USER_QUOTA_LIST_CONTINUE);
325 status = cli_trans(talloc_tos(), cli, SMBnttrans,
326 NULL, -1, /* name, fid */
327 NT_TRANSACT_GET_USER_QUOTA, 0,
328 setup, 1, 0, /* setup */
329 params, 16, 4, /* params */
330 NULL, 0, 2048, /* data */
331 NULL, /* recv_flags2 */
332 NULL, 0, NULL, /* rsetup */
333 &rparam, 0, &rparam_count,
334 &rdata, 0, &rdata_count);
336 if (!NT_STATUS_IS_OK(status)) {
337 DEBUG(1, ("NT_TRANSACT_GET_USER_QUOTA failed: %s\n",
342 if (rdata_count == 0) {
347 for (curdata=rdata,curdata_count=rdata_count;
348 ((curdata)&&(curdata_count>=8)&&(offset>0));
349 curdata +=offset,curdata_count -= offset) {
351 if (!parse_user_quota_record((uint8_t *)curdata,
352 curdata_count, &offset,
354 DEBUG(1,("Failed to parse the quota record\n"));
358 if ((tmp_list_ent=TALLOC_ZERO_P(mem_ctx,SMB_NTQUOTA_LIST))==NULL) {
359 DEBUG(0,("TALLOC_ZERO() failed\n"));
360 talloc_destroy(mem_ctx);
364 if ((tmp_list_ent->quotas=TALLOC_ZERO_P(mem_ctx,SMB_NTQUOTA_STRUCT))==NULL) {
365 DEBUG(0,("TALLOC_ZERO() failed\n"));
366 talloc_destroy(mem_ctx);
370 memcpy(tmp_list_ent->quotas,&qt,sizeof(qt));
371 tmp_list_ent->mem_ctx = mem_ctx;
373 DLIST_ADD((*pqt_list),tmp_list_ent);
384 NTSTATUS cli_get_fs_quota_info(struct cli_state *cli, int quota_fnum,
385 SMB_NTQUOTA_STRUCT *pqt)
390 uint32_t rdata_count=0;
391 SMB_NTQUOTA_STRUCT qt;
397 smb_panic("cli_get_fs_quota_info() called with NULL Pointer!");
400 SSVAL(setup + 0, 0, TRANSACT2_QFSINFO);
402 SSVAL(param,0,SMB_FS_QUOTA_INFORMATION);
404 status = cli_trans(talloc_tos(), cli, SMBtrans2,
405 NULL, -1, /* name, fid */
406 0, 0, /* function, flags */
407 setup, 1, 0, /* setup */
408 param, 2, 0, /* param */
409 NULL, 0, 560, /* data */
410 NULL, /* recv_flags2 */
411 NULL, 0, NULL, /* rsetup */
412 NULL, 0, NULL, /* rparam */
413 &rdata, 48, &rdata_count);
415 if (!NT_STATUS_IS_OK(status)) {
416 DEBUG(1, ("SMB_FS_QUOTA_INFORMATION failed: %s\n",
421 /* unknown_1 24 NULL bytes in pdata*/
423 /* the soft quotas 8 bytes (uint64_t)*/
424 qt.softlim = (uint64_t)IVAL(rdata,24);
425 #ifdef LARGE_SMB_OFF_T
426 qt.softlim |= (((uint64_t)IVAL(rdata,28)) << 32);
427 #else /* LARGE_SMB_OFF_T */
428 if ((IVAL(rdata,28) != 0)&&
429 ((qt.softlim != 0xFFFFFFFF)||
430 (IVAL(rdata,28)!=0xFFFFFFFF))) {
431 /* more than 32 bits? */
432 status = NT_STATUS_INVALID_NETWORK_RESPONSE;
435 #endif /* LARGE_SMB_OFF_T */
437 /* the hard quotas 8 bytes (uint64_t)*/
438 qt.hardlim = (uint64_t)IVAL(rdata,32);
439 #ifdef LARGE_SMB_OFF_T
440 qt.hardlim |= (((uint64_t)IVAL(rdata,36)) << 32);
441 #else /* LARGE_SMB_OFF_T */
442 if ((IVAL(rdata,36) != 0)&&
443 ((qt.hardlim != 0xFFFFFFFF)||
444 (IVAL(rdata,36)!=0xFFFFFFFF))) {
445 /* more than 32 bits? */
446 status = NT_STATUS_INVALID_NETWORK_RESPONSE;
449 #endif /* LARGE_SMB_OFF_T */
451 /* quota_flags 2 bytes **/
452 qt.qflags = SVAL(rdata,40);
454 qt.qtype = SMB_USER_FS_QUOTA_TYPE;
462 NTSTATUS cli_set_fs_quota_info(struct cli_state *cli, int quota_fnum,
463 SMB_NTQUOTA_STRUCT *pqt)
468 SMB_NTQUOTA_STRUCT qt;
471 memset(data,'\0',48);
474 smb_panic("cli_set_fs_quota_info() called with NULL Pointer!");
477 SSVAL(setup + 0, 0,TRANSACT2_SETFSINFO);
479 SSVAL(param,0,quota_fnum);
480 SSVAL(param,2,SMB_FS_QUOTA_INFORMATION);
482 /* Unknown1 24 NULL bytes*/
484 /* Default Soft Quota 8 bytes */
485 SBIG_UINT(data,24,pqt->softlim);
487 /* Default Hard Quota 8 bytes */
488 SBIG_UINT(data,32,pqt->hardlim);
490 /* Quota flag 2 bytes */
491 SSVAL(data,40,pqt->qflags);
493 /* Unknown3 6 NULL bytes */
495 status = cli_trans(talloc_tos(), cli, SMBtrans2,
496 NULL, -1, /* name, fid */
497 0, 0, /* function, flags */
498 setup, 1, 0, /* setup */
499 param, 8, 0, /* param */
500 data, 48, 0, /* data */
501 NULL, /* recv_flags2 */
502 NULL, 0, NULL, /* rsetup */
503 NULL, 0, NULL, /* rparam */
504 NULL, 0, NULL); /* rdata */
506 if (!NT_STATUS_IS_OK(status)) {
507 DEBUG(1, ("SMB_FS_QUOTA_INFORMATION failed: %s\n",