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
= BVAL(rdata
,16);
85 /* the soft quotas 8 bytes (uint64_t)*/
86 qt
.softlim
= BVAL(rdata
,24);
88 /* the hard quotas 8 bytes (uint64_t)*/
89 qt
.hardlim
= BVAL(rdata
,32);
91 if (!sid_parse((const char *)rdata
+40,sid_len
,&qt
.sid
)) {
95 qt
.qtype
= SMB_USER_QUOTA_TYPE
;
102 NTSTATUS
cli_get_user_quota(struct cli_state
*cli
, int quota_fnum
,
103 SMB_NTQUOTA_STRUCT
*pqt
)
107 unsigned int data_len
;
108 uint8_t data
[SID_MAX_SIZE
+8];
109 uint8_t *rparam
, *rdata
;
110 uint32_t rparam_count
, rdata_count
;
111 unsigned int sid_len
;
116 smb_panic("cli_get_user_quota() called with NULL Pointer!");
119 SSVAL(setup
+ 0, 0, NT_TRANSACT_GET_USER_QUOTA
);
121 SSVAL(params
, 0,quota_fnum
);
122 SSVAL(params
, 2,TRANSACT_GET_USER_QUOTA_FOR_SID
);
123 SIVAL(params
, 4,0x00000024);
124 SIVAL(params
, 8,0x00000000);
125 SIVAL(params
,12,0x00000024);
127 sid_len
= ndr_size_dom_sid(&pqt
->sid
, 0);
128 data_len
= sid_len
+8;
129 SIVAL(data
, 0, 0x00000000);
130 SIVAL(data
, 4, sid_len
);
131 sid_linearize((char *)data
+8, sid_len
, &pqt
->sid
);
133 status
= cli_trans(talloc_tos(), cli
, SMBnttrans
,
134 NULL
, -1, /* name, fid */
135 NT_TRANSACT_GET_USER_QUOTA
, 0,
136 setup
, 1, 0, /* setup */
137 params
, 16, 4, /* params */
138 data
, data_len
, 112, /* data */
139 NULL
, /* recv_flags2 */
140 NULL
, 0, NULL
, /* rsetup */
141 &rparam
, 4, &rparam_count
,
142 &rdata
, 8, &rdata_count
);
143 if (!NT_STATUS_IS_OK(status
)) {
144 DEBUG(1, ("NT_TRANSACT_GET_USER_QUOTA failed: %s\n",
149 if (!parse_user_quota_record(rdata
, rdata_count
, &offset
, pqt
)) {
150 status
= NT_STATUS_INVALID_NETWORK_RESPONSE
;
151 DEBUG(0,("Got INVALID NT_TRANSACT_GET_USER_QUOTA reply.\n"));
159 NTSTATUS
cli_set_user_quota(struct cli_state
*cli
, int quota_fnum
,
160 SMB_NTQUOTA_STRUCT
*pqt
)
165 unsigned int sid_len
;
168 memset(data
,'\0',112);
171 smb_panic("cli_set_user_quota() called with NULL Pointer!");
174 SSVAL(setup
+ 0, 0, NT_TRANSACT_SET_USER_QUOTA
);
176 SSVAL(params
,0,quota_fnum
);
178 sid_len
= ndr_size_dom_sid(&pqt
->sid
, 0);
180 SIVAL(data
,4,sid_len
);
181 SBIG_UINT(data
, 8,(uint64_t)0);
182 SBIG_UINT(data
,16,pqt
->usedspace
);
183 SBIG_UINT(data
,24,pqt
->softlim
);
184 SBIG_UINT(data
,32,pqt
->hardlim
);
185 sid_linearize((char *)data
+40, sid_len
, &pqt
->sid
);
187 status
= cli_trans(talloc_tos(), cli
, SMBnttrans
,
188 NULL
, -1, /* name, fid */
189 NT_TRANSACT_SET_USER_QUOTA
, 0,
190 setup
, 1, 0, /* setup */
191 params
, 2, 0, /* params */
192 data
, 112, 0, /* data */
193 NULL
, /* recv_flags2 */
194 NULL
, 0, NULL
, /* rsetup */
195 NULL
, 0, NULL
, /* rparams */
196 NULL
, 0, NULL
); /* rdata */
198 if (!NT_STATUS_IS_OK(status
)) {
199 DEBUG(1, ("NT_TRANSACT_SET_USER_QUOTA failed: %s\n",
206 NTSTATUS
cli_list_user_quota(struct cli_state
*cli
, int quota_fnum
,
207 SMB_NTQUOTA_LIST
**pqt_list
)
211 uint8_t *rparam
=NULL
, *rdata
=NULL
;
212 uint32_t rparam_count
=0, rdata_count
=0;
214 const uint8_t *curdata
= NULL
;
215 unsigned int curdata_count
= 0;
216 TALLOC_CTX
*mem_ctx
= NULL
;
217 SMB_NTQUOTA_STRUCT qt
;
218 SMB_NTQUOTA_LIST
*tmp_list_ent
;
221 if (!cli
||!pqt_list
) {
222 smb_panic("cli_list_user_quota() called with NULL Pointer!");
225 SSVAL(setup
+ 0, 0, NT_TRANSACT_GET_USER_QUOTA
);
227 SSVAL(params
, 0,quota_fnum
);
228 SSVAL(params
, 2,TRANSACT_GET_USER_QUOTA_LIST_START
);
229 SIVAL(params
, 4,0x00000000);
230 SIVAL(params
, 8,0x00000000);
231 SIVAL(params
,12,0x00000000);
233 status
= cli_trans(talloc_tos(), cli
, SMBnttrans
,
234 NULL
, -1, /* name, fid */
235 NT_TRANSACT_GET_USER_QUOTA
, 0,
236 setup
, 1, 0, /* setup */
237 params
, 16, 4, /* params */
238 NULL
, 0, 2048, /* data */
239 NULL
, /* recv_flags2 */
240 NULL
, 0, NULL
, /* rsetup */
241 &rparam
, 0, &rparam_count
,
242 &rdata
, 0, &rdata_count
);
244 if (!NT_STATUS_IS_OK(status
)) {
245 DEBUG(1, ("NT_TRANSACT_GET_USER_QUOTA failed: %s\n",
250 if (rdata_count
== 0) {
255 if ((mem_ctx
=talloc_init("SMB_USER_QUOTA_LIST"))==NULL
) {
256 DEBUG(0,("talloc_init() failed\n"));
257 return NT_STATUS_NO_MEMORY
;
261 for (curdata
=rdata
,curdata_count
=rdata_count
;
262 ((curdata
)&&(curdata_count
>=8)&&(offset
>0));
263 curdata
+=offset
,curdata_count
-= offset
) {
265 if (!parse_user_quota_record((const uint8_t *)curdata
, curdata_count
,
267 DEBUG(1,("Failed to parse the quota record\n"));
271 if ((tmp_list_ent
=TALLOC_ZERO_P(mem_ctx
,SMB_NTQUOTA_LIST
))==NULL
) {
272 DEBUG(0,("TALLOC_ZERO() failed\n"));
273 talloc_destroy(mem_ctx
);
274 return NT_STATUS_NO_MEMORY
;
277 if ((tmp_list_ent
->quotas
=TALLOC_ZERO_P(mem_ctx
,SMB_NTQUOTA_STRUCT
))==NULL
) {
278 DEBUG(0,("TALLOC_ZERO() failed\n"));
279 talloc_destroy(mem_ctx
);
280 return NT_STATUS_NO_MEMORY
;
283 memcpy(tmp_list_ent
->quotas
,&qt
,sizeof(qt
));
284 tmp_list_ent
->mem_ctx
= mem_ctx
;
286 DLIST_ADD((*pqt_list
),tmp_list_ent
);
289 SSVAL(params
, 2,TRANSACT_GET_USER_QUOTA_LIST_CONTINUE
);
295 status
= cli_trans(talloc_tos(), cli
, SMBnttrans
,
296 NULL
, -1, /* name, fid */
297 NT_TRANSACT_GET_USER_QUOTA
, 0,
298 setup
, 1, 0, /* setup */
299 params
, 16, 4, /* params */
300 NULL
, 0, 2048, /* data */
301 NULL
, /* recv_flags2 */
302 NULL
, 0, NULL
, /* rsetup */
303 &rparam
, 0, &rparam_count
,
304 &rdata
, 0, &rdata_count
);
306 if (!NT_STATUS_IS_OK(status
)) {
307 DEBUG(1, ("NT_TRANSACT_GET_USER_QUOTA failed: %s\n",
312 if (rdata_count
== 0) {
317 for (curdata
=rdata
,curdata_count
=rdata_count
;
318 ((curdata
)&&(curdata_count
>=8)&&(offset
>0));
319 curdata
+=offset
,curdata_count
-= offset
) {
321 if (!parse_user_quota_record((const uint8_t *)curdata
,
322 curdata_count
, &offset
,
324 DEBUG(1,("Failed to parse the quota record\n"));
328 if ((tmp_list_ent
=TALLOC_ZERO_P(mem_ctx
,SMB_NTQUOTA_LIST
))==NULL
) {
329 DEBUG(0,("TALLOC_ZERO() failed\n"));
330 talloc_destroy(mem_ctx
);
334 if ((tmp_list_ent
->quotas
=TALLOC_ZERO_P(mem_ctx
,SMB_NTQUOTA_STRUCT
))==NULL
) {
335 DEBUG(0,("TALLOC_ZERO() failed\n"));
336 talloc_destroy(mem_ctx
);
340 memcpy(tmp_list_ent
->quotas
,&qt
,sizeof(qt
));
341 tmp_list_ent
->mem_ctx
= mem_ctx
;
343 DLIST_ADD((*pqt_list
),tmp_list_ent
);
354 NTSTATUS
cli_get_fs_quota_info(struct cli_state
*cli
, int quota_fnum
,
355 SMB_NTQUOTA_STRUCT
*pqt
)
360 uint32_t rdata_count
=0;
361 SMB_NTQUOTA_STRUCT qt
;
367 smb_panic("cli_get_fs_quota_info() called with NULL Pointer!");
370 SSVAL(setup
+ 0, 0, TRANSACT2_QFSINFO
);
372 SSVAL(param
,0,SMB_FS_QUOTA_INFORMATION
);
374 status
= cli_trans(talloc_tos(), cli
, SMBtrans2
,
375 NULL
, -1, /* name, fid */
376 0, 0, /* function, flags */
377 setup
, 1, 0, /* setup */
378 param
, 2, 0, /* param */
379 NULL
, 0, 560, /* data */
380 NULL
, /* recv_flags2 */
381 NULL
, 0, NULL
, /* rsetup */
382 NULL
, 0, NULL
, /* rparam */
383 &rdata
, 48, &rdata_count
);
385 if (!NT_STATUS_IS_OK(status
)) {
386 DEBUG(1, ("SMB_FS_QUOTA_INFORMATION failed: %s\n",
391 /* unknown_1 24 NULL bytes in pdata*/
393 /* the soft quotas 8 bytes (uint64_t)*/
394 qt
.softlim
= BVAL(rdata
,24);
396 /* the hard quotas 8 bytes (uint64_t)*/
397 qt
.hardlim
= BVAL(rdata
,32);
399 /* quota_flags 2 bytes **/
400 qt
.qflags
= SVAL(rdata
,40);
402 qt
.qtype
= SMB_USER_FS_QUOTA_TYPE
;
410 NTSTATUS
cli_set_fs_quota_info(struct cli_state
*cli
, int quota_fnum
,
411 SMB_NTQUOTA_STRUCT
*pqt
)
416 SMB_NTQUOTA_STRUCT qt
;
419 memset(data
,'\0',48);
422 smb_panic("cli_set_fs_quota_info() called with NULL Pointer!");
425 SSVAL(setup
+ 0, 0,TRANSACT2_SETFSINFO
);
427 SSVAL(param
,0,quota_fnum
);
428 SSVAL(param
,2,SMB_FS_QUOTA_INFORMATION
);
430 /* Unknown1 24 NULL bytes*/
432 /* Default Soft Quota 8 bytes */
433 SBIG_UINT(data
,24,pqt
->softlim
);
435 /* Default Hard Quota 8 bytes */
436 SBIG_UINT(data
,32,pqt
->hardlim
);
438 /* Quota flag 2 bytes */
439 SSVAL(data
,40,pqt
->qflags
);
441 /* Unknown3 6 NULL bytes */
443 status
= cli_trans(talloc_tos(), cli
, SMBtrans2
,
444 NULL
, -1, /* name, fid */
445 0, 0, /* function, flags */
446 setup
, 1, 0, /* setup */
447 param
, 8, 0, /* param */
448 data
, 48, 0, /* data */
449 NULL
, /* recv_flags2 */
450 NULL
, 0, NULL
, /* rsetup */
451 NULL
, 0, NULL
, /* rparam */
452 NULL
, 0, NULL
); /* rdata */
454 if (!NT_STATUS_IS_OK(status
)) {
455 DEBUG(1, ("SMB_FS_QUOTA_INFORMATION failed: %s\n",