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"
25 NTSTATUS cli_get_quota_handle(struct cli_state *cli, uint16_t *quota_fnum)
27 return cli_ntcreate(cli, FAKE_FILE_NAME_QUOTA_WIN32,
28 0x00000016, DESIRED_ACCESS_PIPE,
29 0x00000000, FILE_SHARE_READ|FILE_SHARE_WRITE,
30 FILE_OPEN, 0x00000000, 0x03, quota_fnum);
33 void free_ntquota_list(SMB_NTQUOTA_LIST **qt_list)
38 if ((*qt_list)->mem_ctx)
39 talloc_destroy((*qt_list)->mem_ctx);
46 static bool parse_user_quota_record(const uint8_t *rdata,
47 unsigned int rdata_count,
49 SMB_NTQUOTA_STRUCT *pqt)
52 SMB_NTQUOTA_STRUCT qt;
56 if (!rdata||!offset||!pqt) {
57 smb_panic("parse_quota_record: called with NULL POINTER!");
60 if (rdata_count < 40) {
64 /* offset to next quota record.
65 * 4 bytes IVAL(rdata,0)
68 *offset = IVAL(rdata,0);
71 sid_len = IVAL(rdata,4);
73 if (rdata_count < 40+sid_len) {
77 /* unknown 8 bytes in pdata
78 * maybe its the change time in NTTIME
81 /* the used space 8 bytes (uint64_t)*/
82 qt.usedspace = (uint64_t)IVAL(rdata,16);
83 #ifdef LARGE_SMB_OFF_T
84 qt.usedspace |= (((uint64_t)IVAL(rdata,20)) << 32);
85 #else /* LARGE_SMB_OFF_T */
86 if ((IVAL(rdata,20) != 0)&&
87 ((qt.usedspace != 0xFFFFFFFF)||
88 (IVAL(rdata,20)!=0xFFFFFFFF))) {
89 /* more than 32 bits? */
92 #endif /* LARGE_SMB_OFF_T */
94 /* the soft quotas 8 bytes (uint64_t)*/
95 qt.softlim = (uint64_t)IVAL(rdata,24);
96 #ifdef LARGE_SMB_OFF_T
97 qt.softlim |= (((uint64_t)IVAL(rdata,28)) << 32);
98 #else /* LARGE_SMB_OFF_T */
99 if ((IVAL(rdata,28) != 0)&&
100 ((qt.softlim != 0xFFFFFFFF)||
101 (IVAL(rdata,28)!=0xFFFFFFFF))) {
102 /* more than 32 bits? */
105 #endif /* LARGE_SMB_OFF_T */
107 /* the hard quotas 8 bytes (uint64_t)*/
108 qt.hardlim = (uint64_t)IVAL(rdata,32);
109 #ifdef LARGE_SMB_OFF_T
110 qt.hardlim |= (((uint64_t)IVAL(rdata,36)) << 32);
111 #else /* LARGE_SMB_OFF_T */
112 if ((IVAL(rdata,36) != 0)&&
113 ((qt.hardlim != 0xFFFFFFFF)||
114 (IVAL(rdata,36)!=0xFFFFFFFF))) {
115 /* more than 32 bits? */
118 #endif /* LARGE_SMB_OFF_T */
120 if (!sid_parse((char *)rdata+40,sid_len,&qt.sid)) {
124 qt.qtype = SMB_USER_QUOTA_TYPE;
131 NTSTATUS cli_get_user_quota(struct cli_state *cli, int quota_fnum,
132 SMB_NTQUOTA_STRUCT *pqt)
136 unsigned int data_len;
137 uint8_t data[SID_MAX_SIZE+8];
138 uint8_t *rparam, *rdata;
139 uint32_t rparam_count, rdata_count;
140 unsigned int sid_len;
145 smb_panic("cli_get_user_quota() called with NULL Pointer!");
148 SSVAL(setup + 0, 0, NT_TRANSACT_GET_USER_QUOTA);
150 SSVAL(params, 0,quota_fnum);
151 SSVAL(params, 2,TRANSACT_GET_USER_QUOTA_FOR_SID);
152 SIVAL(params, 4,0x00000024);
153 SIVAL(params, 8,0x00000000);
154 SIVAL(params,12,0x00000024);
156 sid_len = ndr_size_dom_sid(&pqt->sid, 0);
157 data_len = sid_len+8;
158 SIVAL(data, 0, 0x00000000);
159 SIVAL(data, 4, sid_len);
160 sid_linearize((char *)data+8, sid_len, &pqt->sid);
162 status = cli_trans(talloc_tos(), cli, SMBnttrans,
163 NULL, -1, /* name, fid */
164 NT_TRANSACT_GET_USER_QUOTA, 0,
165 setup, 1, 0, /* setup */
166 params, 16, 4, /* params */
167 data, data_len, 112, /* data */
168 NULL, /* recv_flags2 */
169 NULL, 0, NULL, /* rsetup */
170 &rparam, 4, &rparam_count,
171 &rdata, 8, &rdata_count);
172 if (!NT_STATUS_IS_OK(status)) {
173 DEBUG(1, ("NT_TRANSACT_GET_USER_QUOTA failed: %s\n",
178 if (!parse_user_quota_record(rdata, rdata_count, &offset, pqt)) {
179 status = NT_STATUS_INVALID_NETWORK_RESPONSE;
180 DEBUG(0,("Got INVALID NT_TRANSACT_GET_USER_QUOTA reply.\n"));
188 NTSTATUS cli_set_user_quota(struct cli_state *cli, int quota_fnum,
189 SMB_NTQUOTA_STRUCT *pqt)
194 unsigned int sid_len;
197 memset(data,'\0',112);
200 smb_panic("cli_set_user_quota() called with NULL Pointer!");
203 SSVAL(setup + 0, 0, NT_TRANSACT_SET_USER_QUOTA);
205 SSVAL(params,0,quota_fnum);
207 sid_len = ndr_size_dom_sid(&pqt->sid, 0);
209 SIVAL(data,4,sid_len);
210 SBIG_UINT(data, 8,(uint64_t)0);
211 SBIG_UINT(data,16,pqt->usedspace);
212 SBIG_UINT(data,24,pqt->softlim);
213 SBIG_UINT(data,32,pqt->hardlim);
214 sid_linearize((char *)data+40, sid_len, &pqt->sid);
216 status = cli_trans(talloc_tos(), cli, SMBnttrans,
217 NULL, -1, /* name, fid */
218 NT_TRANSACT_SET_USER_QUOTA, 0,
219 setup, 1, 0, /* setup */
220 params, 2, 0, /* params */
221 data, 112, 0, /* data */
222 NULL, /* recv_flags2 */
223 NULL, 0, NULL, /* rsetup */
224 NULL, 0, NULL, /* rparams */
225 NULL, 0, NULL); /* rdata */
227 if (!NT_STATUS_IS_OK(status)) {
228 DEBUG(1, ("NT_TRANSACT_SET_USER_QUOTA failed: %s\n",
235 NTSTATUS cli_list_user_quota(struct cli_state *cli, int quota_fnum,
236 SMB_NTQUOTA_LIST **pqt_list)
240 uint8_t *rparam=NULL, *rdata=NULL;
241 uint32_t rparam_count=0, rdata_count=0;
243 const uint8_t *curdata = NULL;
244 unsigned int curdata_count = 0;
245 TALLOC_CTX *mem_ctx = NULL;
246 SMB_NTQUOTA_STRUCT qt;
247 SMB_NTQUOTA_LIST *tmp_list_ent;
250 if (!cli||!pqt_list) {
251 smb_panic("cli_list_user_quota() called with NULL Pointer!");
254 SSVAL(setup + 0, 0, NT_TRANSACT_GET_USER_QUOTA);
256 SSVAL(params, 0,quota_fnum);
257 SSVAL(params, 2,TRANSACT_GET_USER_QUOTA_LIST_START);
258 SIVAL(params, 4,0x00000000);
259 SIVAL(params, 8,0x00000000);
260 SIVAL(params,12,0x00000000);
262 status = cli_trans(talloc_tos(), cli, SMBnttrans,
263 NULL, -1, /* name, fid */
264 NT_TRANSACT_GET_USER_QUOTA, 0,
265 setup, 1, 0, /* setup */
266 params, 16, 4, /* params */
267 NULL, 0, 2048, /* data */
268 NULL, /* recv_flags2 */
269 NULL, 0, NULL, /* rsetup */
270 &rparam, 0, &rparam_count,
271 &rdata, 0, &rdata_count);
273 if (!NT_STATUS_IS_OK(status)) {
274 DEBUG(1, ("NT_TRANSACT_GET_USER_QUOTA failed: %s\n",
279 if (rdata_count == 0) {
284 if ((mem_ctx=talloc_init("SMB_USER_QUOTA_LIST"))==NULL) {
285 DEBUG(0,("talloc_init() failed\n"));
286 return NT_STATUS_NO_MEMORY;
290 for (curdata=rdata,curdata_count=rdata_count;
291 ((curdata)&&(curdata_count>=8)&&(offset>0));
292 curdata +=offset,curdata_count -= offset) {
294 if (!parse_user_quota_record((uint8_t *)curdata, curdata_count,
296 DEBUG(1,("Failed to parse the quota record\n"));
300 if ((tmp_list_ent=TALLOC_ZERO_P(mem_ctx,SMB_NTQUOTA_LIST))==NULL) {
301 DEBUG(0,("TALLOC_ZERO() failed\n"));
302 talloc_destroy(mem_ctx);
303 return NT_STATUS_NO_MEMORY;
306 if ((tmp_list_ent->quotas=TALLOC_ZERO_P(mem_ctx,SMB_NTQUOTA_STRUCT))==NULL) {
307 DEBUG(0,("TALLOC_ZERO() failed\n"));
308 talloc_destroy(mem_ctx);
309 return NT_STATUS_NO_MEMORY;
312 memcpy(tmp_list_ent->quotas,&qt,sizeof(qt));
313 tmp_list_ent->mem_ctx = mem_ctx;
315 DLIST_ADD((*pqt_list),tmp_list_ent);
318 SSVAL(params, 2,TRANSACT_GET_USER_QUOTA_LIST_CONTINUE);
324 status = cli_trans(talloc_tos(), cli, SMBnttrans,
325 NULL, -1, /* name, fid */
326 NT_TRANSACT_GET_USER_QUOTA, 0,
327 setup, 1, 0, /* setup */
328 params, 16, 4, /* params */
329 NULL, 0, 2048, /* data */
330 NULL, /* recv_flags2 */
331 NULL, 0, NULL, /* rsetup */
332 &rparam, 0, &rparam_count,
333 &rdata, 0, &rdata_count);
335 if (!NT_STATUS_IS_OK(status)) {
336 DEBUG(1, ("NT_TRANSACT_GET_USER_QUOTA failed: %s\n",
341 if (rdata_count == 0) {
346 for (curdata=rdata,curdata_count=rdata_count;
347 ((curdata)&&(curdata_count>=8)&&(offset>0));
348 curdata +=offset,curdata_count -= offset) {
350 if (!parse_user_quota_record((uint8_t *)curdata,
351 curdata_count, &offset,
353 DEBUG(1,("Failed to parse the quota record\n"));
357 if ((tmp_list_ent=TALLOC_ZERO_P(mem_ctx,SMB_NTQUOTA_LIST))==NULL) {
358 DEBUG(0,("TALLOC_ZERO() failed\n"));
359 talloc_destroy(mem_ctx);
363 if ((tmp_list_ent->quotas=TALLOC_ZERO_P(mem_ctx,SMB_NTQUOTA_STRUCT))==NULL) {
364 DEBUG(0,("TALLOC_ZERO() failed\n"));
365 talloc_destroy(mem_ctx);
369 memcpy(tmp_list_ent->quotas,&qt,sizeof(qt));
370 tmp_list_ent->mem_ctx = mem_ctx;
372 DLIST_ADD((*pqt_list),tmp_list_ent);
383 NTSTATUS cli_get_fs_quota_info(struct cli_state *cli, int quota_fnum,
384 SMB_NTQUOTA_STRUCT *pqt)
389 uint32_t rdata_count=0;
390 SMB_NTQUOTA_STRUCT qt;
396 smb_panic("cli_get_fs_quota_info() called with NULL Pointer!");
399 SSVAL(setup + 0, 0, TRANSACT2_QFSINFO);
401 SSVAL(param,0,SMB_FS_QUOTA_INFORMATION);
403 status = cli_trans(talloc_tos(), cli, SMBtrans2,
404 NULL, -1, /* name, fid */
405 0, 0, /* function, flags */
406 setup, 1, 0, /* setup */
407 param, 2, 0, /* param */
408 NULL, 0, 560, /* data */
409 NULL, /* recv_flags2 */
410 NULL, 0, NULL, /* rsetup */
411 NULL, 0, NULL, /* rparam */
412 &rdata, 48, &rdata_count);
414 if (!NT_STATUS_IS_OK(status)) {
415 DEBUG(1, ("SMB_FS_QUOTA_INFORMATION failed: %s\n",
420 /* unknown_1 24 NULL bytes in pdata*/
422 /* the soft quotas 8 bytes (uint64_t)*/
423 qt.softlim = (uint64_t)IVAL(rdata,24);
424 #ifdef LARGE_SMB_OFF_T
425 qt.softlim |= (((uint64_t)IVAL(rdata,28)) << 32);
426 #else /* LARGE_SMB_OFF_T */
427 if ((IVAL(rdata,28) != 0)&&
428 ((qt.softlim != 0xFFFFFFFF)||
429 (IVAL(rdata,28)!=0xFFFFFFFF))) {
430 /* more than 32 bits? */
431 status = NT_STATUS_INVALID_NETWORK_RESPONSE;
434 #endif /* LARGE_SMB_OFF_T */
436 /* the hard quotas 8 bytes (uint64_t)*/
437 qt.hardlim = (uint64_t)IVAL(rdata,32);
438 #ifdef LARGE_SMB_OFF_T
439 qt.hardlim |= (((uint64_t)IVAL(rdata,36)) << 32);
440 #else /* LARGE_SMB_OFF_T */
441 if ((IVAL(rdata,36) != 0)&&
442 ((qt.hardlim != 0xFFFFFFFF)||
443 (IVAL(rdata,36)!=0xFFFFFFFF))) {
444 /* more than 32 bits? */
445 status = NT_STATUS_INVALID_NETWORK_RESPONSE;
448 #endif /* LARGE_SMB_OFF_T */
450 /* quota_flags 2 bytes **/
451 qt.qflags = SVAL(rdata,40);
453 qt.qtype = SMB_USER_FS_QUOTA_TYPE;
461 NTSTATUS cli_set_fs_quota_info(struct cli_state *cli, int quota_fnum,
462 SMB_NTQUOTA_STRUCT *pqt)
467 SMB_NTQUOTA_STRUCT qt;
470 memset(data,'\0',48);
473 smb_panic("cli_set_fs_quota_info() called with NULL Pointer!");
476 SSVAL(setup + 0, 0,TRANSACT2_SETFSINFO);
478 SSVAL(param,0,quota_fnum);
479 SSVAL(param,2,SMB_FS_QUOTA_INFORMATION);
481 /* Unknown1 24 NULL bytes*/
483 /* Default Soft Quota 8 bytes */
484 SBIG_UINT(data,24,pqt->softlim);
486 /* Default Hard Quota 8 bytes */
487 SBIG_UINT(data,32,pqt->hardlim);
489 /* Quota flag 2 bytes */
490 SSVAL(data,40,pqt->qflags);
492 /* Unknown3 6 NULL bytes */
494 status = cli_trans(talloc_tos(), cli, SMBtrans2,
495 NULL, -1, /* name, fid */
496 0, 0, /* function, flags */
497 setup, 1, 0, /* setup */
498 param, 8, 0, /* param */
499 data, 48, 0, /* data */
500 NULL, /* recv_flags2 */
501 NULL, 0, NULL, /* rsetup */
502 NULL, 0, NULL, /* rparam */
503 NULL, 0, NULL); /* rdata */
505 if (!NT_STATUS_IS_OK(status)) {
506 DEBUG(1, ("SMB_FS_QUOTA_INFORMATION failed: %s\n",
513 static const char *quota_str_static(uint64_t val, bool special, bool _numeric)
517 if (!_numeric&&special&&(val == SMB_NTQUOTAS_NO_LIMIT)) {
520 result = talloc_asprintf(talloc_tos(), "%"PRIu64, val);
521 SMB_ASSERT(result != NULL);
525 void dump_ntquota(SMB_NTQUOTA_STRUCT *qt, bool _verbose, bool _numeric, void (*_sidtostring)(fstring str, struct dom_sid *sid, bool _numeric))
527 TALLOC_CTX *frame = talloc_stackframe();
530 smb_panic("dump_ntquota() called with NULL pointer");
534 case SMB_USER_FS_QUOTA_TYPE:
536 d_printf("File System QUOTAS:\n");
537 d_printf("Limits:\n");
538 d_printf(" Default Soft Limit: %15s\n",quota_str_static(qt->softlim,True,_numeric));
539 d_printf(" Default Hard Limit: %15s\n",quota_str_static(qt->hardlim,True,_numeric));
540 d_printf("Quota Flags:\n");
541 d_printf(" Quotas Enabled: %s\n",
542 ((qt->qflags"AS_ENABLED)||(qt->qflags"AS_DENY_DISK))?"On":"Off");
543 d_printf(" Deny Disk: %s\n",(qt->qflags"AS_DENY_DISK)?"On":"Off");
544 d_printf(" Log Soft Limit: %s\n",(qt->qflags"AS_LOG_THRESHOLD)?"On":"Off");
545 d_printf(" Log Hard Limit: %s\n",(qt->qflags"AS_LOG_LIMIT)?"On":"Off");
548 case SMB_USER_QUOTA_TYPE:
550 fstring username_str = {0};
553 _sidtostring(username_str,&qt->sid,_numeric);
555 sid_to_fstring(username_str, &qt->sid);
559 d_printf("Quotas for User: %s\n",username_str);
560 d_printf("Used Space: %15s\n",quota_str_static(qt->usedspace,False,_numeric));
561 d_printf("Soft Limit: %15s\n",quota_str_static(qt->softlim,True,_numeric));
562 d_printf("Hard Limit: %15s\n",quota_str_static(qt->hardlim,True,_numeric));
564 d_printf("%-30s: ",username_str);
565 d_printf("%15s/",quota_str_static(qt->usedspace,False,_numeric));
566 d_printf("%15s/",quota_str_static(qt->softlim,True,_numeric));
567 d_printf("%15s\n",quota_str_static(qt->hardlim,True,_numeric));
572 d_printf("dump_ntquota() invalid qtype(%d)\n",qt->qtype);
578 void dump_ntquota_list(SMB_NTQUOTA_LIST **qtl, bool _verbose, bool _numeric, void (*_sidtostring)(fstring str, struct dom_sid *sid, bool _numeric))
580 SMB_NTQUOTA_LIST *cur;
582 for (cur = *qtl;cur;cur = cur->next) {
584 dump_ntquota(cur->quotas,_verbose,_numeric,_sidtostring);