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/>.
22
bool cli_get_quota_handle(struct cli_state *cli, int *quota_fnum)
24
*quota_fnum = cli_nt_create_full(cli, FAKE_FILE_NAME_QUOTA_WIN32,
25
0x00000016, DESIRED_ACCESS_PIPE,
26
0x00000000, FILE_SHARE_READ|FILE_SHARE_WRITE,
27
FILE_OPEN, 0x00000000, 0x03);
29
if (*quota_fnum == (-1)) {
36
void free_ntquota_list(SMB_NTQUOTA_LIST **qt_list)
41
if ((*qt_list)->mem_ctx)
42
talloc_destroy((*qt_list)->mem_ctx);
49
static bool parse_user_quota_record(const char *rdata, unsigned int rdata_count, unsigned int *offset, 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(rdata+40,sid_len,&qt.sid)) {
124
qt.qtype = SMB_USER_QUOTA_TYPE;
131
bool cli_get_user_quota(struct cli_state *cli, int quota_fnum, SMB_NTQUOTA_STRUCT *pqt)
136
unsigned int data_len;
137
char data[SID_MAX_SIZE+8];
138
char *rparam=NULL, *rdata=NULL;
139
unsigned int rparam_count=0, rdata_count=0;
140
unsigned int sid_len;
144
smb_panic("cli_get_user_quota() called with NULL Pointer!");
147
setup = NT_TRANSACT_GET_USER_QUOTA;
149
SSVAL(params, 0,quota_fnum);
150
SSVAL(params, 2,TRANSACT_GET_USER_QUOTA_FOR_SID);
151
SIVAL(params, 4,0x00000024);
152
SIVAL(params, 8,0x00000000);
153
SIVAL(params,12,0x00000024);
155
sid_len = ndr_size_dom_sid(&pqt->sid, NULL, 0);
156
data_len = sid_len+8;
157
SIVAL(data, 0, 0x00000000);
158
SIVAL(data, 4, sid_len);
159
sid_linearize(data+8, sid_len, &pqt->sid);
161
if (!cli_send_nt_trans(cli,
162
NT_TRANSACT_GET_USER_QUOTA,
166
data, data_len, 112)) {
167
DEBUG(1,("Failed to send NT_TRANSACT_GET_USER_QUOTA\n"));
172
if (!cli_receive_nt_trans(cli,
173
&rparam, &rparam_count,
174
&rdata, &rdata_count)) {
175
DEBUG(1,("Failed to recv NT_TRANSACT_GET_USER_QUOTA\n"));
179
if (cli_is_error(cli)) {
186
if ((rparam&&rdata)&&(rparam_count>=4&&rdata_count>=8)) {
187
ret = parse_user_quota_record(rdata, rdata_count, &offset, pqt);
189
DEBUG(0,("Got INVALID NT_TRANSACT_GET_USER_QUOTA reply.\n"));
199
bool cli_set_user_quota(struct cli_state *cli, int quota_fnum, SMB_NTQUOTA_STRUCT *pqt)
205
char *rparam=NULL, *rdata=NULL;
206
unsigned int rparam_count=0, rdata_count=0;
207
unsigned int sid_len;
208
memset(data,'\0',112);
211
smb_panic("cli_set_user_quota() called with NULL Pointer!");
214
setup = NT_TRANSACT_SET_USER_QUOTA;
216
SSVAL(params,0,quota_fnum);
218
sid_len = ndr_size_dom_sid(&pqt->sid, NULL, 0);
220
SIVAL(data,4,sid_len);
221
SBIG_UINT(data, 8,(uint64_t)0);
222
SBIG_UINT(data,16,pqt->usedspace);
223
SBIG_UINT(data,24,pqt->softlim);
224
SBIG_UINT(data,32,pqt->hardlim);
225
sid_linearize(data+40, sid_len, &pqt->sid);
227
if (!cli_send_nt_trans(cli,
228
NT_TRANSACT_SET_USER_QUOTA,
233
DEBUG(1,("Failed to send NT_TRANSACT_SET_USER_QUOTA\n"));
238
if (!cli_receive_nt_trans(cli,
239
&rparam, &rparam_count,
240
&rdata, &rdata_count)) {
241
DEBUG(1,("NT_TRANSACT_SET_USER_QUOTA failed\n"));
245
if (cli_is_error(cli)) {
258
bool cli_list_user_quota(struct cli_state *cli, int quota_fnum, SMB_NTQUOTA_LIST **pqt_list)
263
char *rparam=NULL, *rdata=NULL;
264
unsigned int rparam_count=0, rdata_count=0;
266
const char *curdata = NULL;
267
unsigned int curdata_count = 0;
268
TALLOC_CTX *mem_ctx = NULL;
269
SMB_NTQUOTA_STRUCT qt;
270
SMB_NTQUOTA_LIST *tmp_list_ent;
272
if (!cli||!pqt_list) {
273
smb_panic("cli_list_user_quota() called with NULL Pointer!");
276
setup = NT_TRANSACT_GET_USER_QUOTA;
278
SSVAL(params, 0,quota_fnum);
279
SSVAL(params, 2,TRANSACT_GET_USER_QUOTA_LIST_START);
280
SIVAL(params, 4,0x00000000);
281
SIVAL(params, 8,0x00000000);
282
SIVAL(params,12,0x00000000);
284
if (!cli_send_nt_trans(cli,
285
NT_TRANSACT_GET_USER_QUOTA,
290
DEBUG(1,("Failed to send NT_TRANSACT_GET_USER_QUOTA\n"));
295
if (!cli_receive_nt_trans(cli,
296
&rparam, &rparam_count,
297
&rdata, &rdata_count)) {
298
DEBUG(1,("Failed to recv NT_TRANSACT_GET_USER_QUOTA\n"));
302
if (cli_is_error(cli)) {
309
if (rdata_count == 0) {
314
if ((mem_ctx=talloc_init("SMB_USER_QUOTA_LIST"))==NULL) {
315
DEBUG(0,("talloc_init() failed\n"));
320
for (curdata=rdata,curdata_count=rdata_count;
321
((curdata)&&(curdata_count>=8)&&(offset>0));
322
curdata +=offset,curdata_count -= offset) {
324
if (!parse_user_quota_record(curdata, curdata_count, &offset, &qt)) {
325
DEBUG(1,("Failed to parse the quota record\n"));
329
if ((tmp_list_ent=TALLOC_ZERO_P(mem_ctx,SMB_NTQUOTA_LIST))==NULL) {
330
DEBUG(0,("TALLOC_ZERO() failed\n"));
331
talloc_destroy(mem_ctx);
335
if ((tmp_list_ent->quotas=TALLOC_ZERO_P(mem_ctx,SMB_NTQUOTA_STRUCT))==NULL) {
336
DEBUG(0,("TALLOC_ZERO() failed\n"));
337
talloc_destroy(mem_ctx);
341
memcpy(tmp_list_ent->quotas,&qt,sizeof(qt));
342
tmp_list_ent->mem_ctx = mem_ctx;
344
DLIST_ADD((*pqt_list),tmp_list_ent);
347
SSVAL(params, 2,TRANSACT_GET_USER_QUOTA_LIST_CONTINUE);
349
if (!cli_send_nt_trans(cli,
350
NT_TRANSACT_GET_USER_QUOTA,
355
DEBUG(1,("Failed to send NT_TRANSACT_GET_USER_QUOTA\n"));
361
if (!cli_receive_nt_trans(cli,
362
&rparam, &rparam_count,
363
&rdata, &rdata_count)) {
364
DEBUG(1,("Failed to recv NT_TRANSACT_GET_USER_QUOTA\n"));
368
if (cli_is_error(cli)) {
375
if (rdata_count == 0) {
380
for (curdata=rdata,curdata_count=rdata_count;
381
((curdata)&&(curdata_count>=8)&&(offset>0));
382
curdata +=offset,curdata_count -= offset) {
384
if (!parse_user_quota_record(curdata, curdata_count, &offset, &qt)) {
385
DEBUG(1,("Failed to parse the quota record\n"));
389
if ((tmp_list_ent=TALLOC_ZERO_P(mem_ctx,SMB_NTQUOTA_LIST))==NULL) {
390
DEBUG(0,("TALLOC_ZERO() failed\n"));
391
talloc_destroy(mem_ctx);
395
if ((tmp_list_ent->quotas=TALLOC_ZERO_P(mem_ctx,SMB_NTQUOTA_STRUCT))==NULL) {
396
DEBUG(0,("TALLOC_ZERO() failed\n"));
397
talloc_destroy(mem_ctx);
401
memcpy(tmp_list_ent->quotas,&qt,sizeof(qt));
402
tmp_list_ent->mem_ctx = mem_ctx;
404
DLIST_ADD((*pqt_list),tmp_list_ent);
417
bool cli_get_fs_quota_info(struct cli_state *cli, int quota_fnum, SMB_NTQUOTA_STRUCT *pqt)
422
char *rparam=NULL, *rdata=NULL;
423
unsigned int rparam_count=0, rdata_count=0;
424
SMB_NTQUOTA_STRUCT qt;
428
smb_panic("cli_get_fs_quota_info() called with NULL Pointer!");
431
setup = TRANSACT2_QFSINFO;
433
SSVAL(param,0,SMB_FS_QUOTA_INFORMATION);
435
if (!cli_send_trans(cli, SMBtrans2,
444
if (!cli_receive_trans(cli, SMBtrans2,
445
&rparam, &rparam_count,
446
&rdata, &rdata_count)) {
450
if (cli_is_error(cli)) {
457
if (rdata_count < 48) {
461
/* unknown_1 24 NULL bytes in pdata*/
463
/* the soft quotas 8 bytes (uint64_t)*/
464
qt.softlim = (uint64_t)IVAL(rdata,24);
465
#ifdef LARGE_SMB_OFF_T
466
qt.softlim |= (((uint64_t)IVAL(rdata,28)) << 32);
467
#else /* LARGE_SMB_OFF_T */
468
if ((IVAL(rdata,28) != 0)&&
469
((qt.softlim != 0xFFFFFFFF)||
470
(IVAL(rdata,28)!=0xFFFFFFFF))) {
471
/* more than 32 bits? */
474
#endif /* LARGE_SMB_OFF_T */
476
/* the hard quotas 8 bytes (uint64_t)*/
477
qt.hardlim = (uint64_t)IVAL(rdata,32);
478
#ifdef LARGE_SMB_OFF_T
479
qt.hardlim |= (((uint64_t)IVAL(rdata,36)) << 32);
480
#else /* LARGE_SMB_OFF_T */
481
if ((IVAL(rdata,36) != 0)&&
482
((qt.hardlim != 0xFFFFFFFF)||
483
(IVAL(rdata,36)!=0xFFFFFFFF))) {
484
/* more than 32 bits? */
487
#endif /* LARGE_SMB_OFF_T */
489
/* quota_flags 2 bytes **/
490
qt.qflags = SVAL(rdata,40);
492
qt.qtype = SMB_USER_FS_QUOTA_TYPE;
504
bool cli_set_fs_quota_info(struct cli_state *cli, int quota_fnum, SMB_NTQUOTA_STRUCT *pqt)
510
char *rparam=NULL, *rdata=NULL;
511
unsigned int rparam_count=0, rdata_count=0;
512
SMB_NTQUOTA_STRUCT qt;
514
memset(data,'\0',48);
517
smb_panic("cli_set_fs_quota_info() called with NULL Pointer!");
520
setup = TRANSACT2_SETFSINFO;
522
SSVAL(param,0,quota_fnum);
523
SSVAL(param,2,SMB_FS_QUOTA_INFORMATION);
525
/* Unknown1 24 NULL bytes*/
527
/* Default Soft Quota 8 bytes */
528
SBIG_UINT(data,24,pqt->softlim);
530
/* Default Hard Quota 8 bytes */
531
SBIG_UINT(data,32,pqt->hardlim);
533
/* Quota flag 2 bytes */
534
SSVAL(data,40,pqt->qflags);
536
/* Unknown3 6 NULL bytes */
538
if (!cli_send_trans(cli, SMBtrans2,
547
if (!cli_receive_trans(cli, SMBtrans2,
548
&rparam, &rparam_count,
549
&rdata, &rdata_count)) {
553
if (cli_is_error(cli)) {
567
static const char *quota_str_static(uint64_t val, bool special, bool _numeric)
571
if (!_numeric&&special&&(val == SMB_NTQUOTAS_NO_LIMIT)) {
574
result = talloc_asprintf(talloc_tos(), "%"PRIu64, val);
575
SMB_ASSERT(result != NULL);
579
void dump_ntquota(SMB_NTQUOTA_STRUCT *qt, bool _verbose, bool _numeric, void (*_sidtostring)(fstring str, DOM_SID *sid, bool _numeric))
581
TALLOC_CTX *frame = talloc_stackframe();
584
smb_panic("dump_ntquota() called with NULL pointer");
588
case SMB_USER_FS_QUOTA_TYPE:
590
d_printf("File System QUOTAS:\n");
591
d_printf("Limits:\n");
592
d_printf(" Default Soft Limit: %15s\n",quota_str_static(qt->softlim,True,_numeric));
593
d_printf(" Default Hard Limit: %15s\n",quota_str_static(qt->hardlim,True,_numeric));
594
d_printf("Quota Flags:\n");
595
d_printf(" Quotas Enabled: %s\n",
596
((qt->qflags"AS_ENABLED)||(qt->qflags"AS_DENY_DISK))?"On":"Off");
597
d_printf(" Deny Disk: %s\n",(qt->qflags"AS_DENY_DISK)?"On":"Off");
598
d_printf(" Log Soft Limit: %s\n",(qt->qflags"AS_LOG_THRESHOLD)?"On":"Off");
599
d_printf(" Log Hard Limit: %s\n",(qt->qflags"AS_LOG_LIMIT)?"On":"Off");
602
case SMB_USER_QUOTA_TYPE:
604
fstring username_str = {0};
607
_sidtostring(username_str,&qt->sid,_numeric);
609
sid_to_fstring(username_str, &qt->sid);
613
d_printf("Quotas for User: %s\n",username_str);
614
d_printf("Used Space: %15s\n",quota_str_static(qt->usedspace,False,_numeric));
615
d_printf("Soft Limit: %15s\n",quota_str_static(qt->softlim,True,_numeric));
616
d_printf("Hard Limit: %15s\n",quota_str_static(qt->hardlim,True,_numeric));
618
d_printf("%-30s: ",username_str);
619
d_printf("%15s/",quota_str_static(qt->usedspace,False,_numeric));
620
d_printf("%15s/",quota_str_static(qt->softlim,True,_numeric));
621
d_printf("%15s\n",quota_str_static(qt->hardlim,True,_numeric));
626
d_printf("dump_ntquota() invalid qtype(%d)\n",qt->qtype);
632
void dump_ntquota_list(SMB_NTQUOTA_LIST **qtl, bool _verbose, bool _numeric, void (*_sidtostring)(fstring str, DOM_SID *sid, bool _numeric))
634
SMB_NTQUOTA_LIST *cur;
636
for (cur = *qtl;cur;cur = cur->next) {
638
dump_ntquota(cur->quotas,_verbose,_numeric,_sidtostring);