Attempt to fix the build with dnssd
[bbaumbach/samba-autobuild/.git] / source3 / libsmb / cliquota.c
1 /* 
2    Unix SMB/CIFS implementation.
3    client quota functions
4    Copyright (C) Stefan (metze) Metzmacher      2003
5
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.
10
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.
15
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/>.
18 */
19
20 #include "includes.h"
21
22 bool cli_get_quota_handle(struct cli_state *cli, int *quota_fnum)
23 {
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);
28
29         if (*quota_fnum == (-1)) {
30                 return False;
31         }
32
33         return True;
34 }
35
36 void free_ntquota_list(SMB_NTQUOTA_LIST **qt_list)
37 {
38         if (!qt_list)
39                 return;
40
41         if ((*qt_list)->mem_ctx)
42                 talloc_destroy((*qt_list)->mem_ctx);
43
44         (*qt_list) = NULL;
45
46         return; 
47 }
48
49 static bool parse_user_quota_record(const char *rdata, unsigned int rdata_count, unsigned int *offset, SMB_NTQUOTA_STRUCT *pqt)
50 {
51         int sid_len;
52         SMB_NTQUOTA_STRUCT qt;
53
54         ZERO_STRUCT(qt);
55
56         if (!rdata||!offset||!pqt) {
57                 smb_panic("parse_quota_record: called with NULL POINTER!");
58         }
59
60         if (rdata_count < 40) {
61                 return False;
62         }
63
64         /* offset to next quota record.
65          * 4 bytes IVAL(rdata,0)
66          * unused here...
67          */
68         *offset = IVAL(rdata,0);
69
70         /* sid len */
71         sid_len = IVAL(rdata,4);
72
73         if (rdata_count < 40+sid_len) {
74                 return False;           
75         }
76
77         /* unknown 8 bytes in pdata 
78          * maybe its the change time in NTTIME
79          */
80
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? */
90                 return False;
91         }
92 #endif /* LARGE_SMB_OFF_T */
93
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? */
103                 return False;
104         }
105 #endif /* LARGE_SMB_OFF_T */
106
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? */
116                 return False;
117         }
118 #endif /* LARGE_SMB_OFF_T */
119
120         sid_parse(rdata+40,sid_len,&qt.sid);
121
122         qt.qtype = SMB_USER_QUOTA_TYPE;
123
124         *pqt = qt;
125
126         return True;
127 }
128
129 bool cli_get_user_quota(struct cli_state *cli, int quota_fnum, SMB_NTQUOTA_STRUCT *pqt)
130 {
131         bool ret = False;
132         uint16 setup;
133         char params[16];
134         unsigned int data_len;
135         char data[SID_MAX_SIZE+8];
136         char *rparam=NULL, *rdata=NULL;
137         unsigned int rparam_count=0, rdata_count=0;
138         unsigned int sid_len;
139         unsigned int offset;
140
141         if (!cli||!pqt) {
142                 smb_panic("cli_get_user_quota() called with NULL Pointer!");
143         }
144
145         setup = NT_TRANSACT_GET_USER_QUOTA;
146
147         SSVAL(params, 0,quota_fnum);
148         SSVAL(params, 2,TRANSACT_GET_USER_QUOTA_FOR_SID);
149         SIVAL(params, 4,0x00000024);
150         SIVAL(params, 8,0x00000000);
151         SIVAL(params,12,0x00000024);
152
153         sid_len = ndr_size_dom_sid(&pqt->sid, 0);
154         data_len = sid_len+8;
155         SIVAL(data, 0, 0x00000000);
156         SIVAL(data, 4, sid_len);
157         sid_linearize(data+8, sid_len, &pqt->sid);
158
159         if (!cli_send_nt_trans(cli, 
160                                NT_TRANSACT_GET_USER_QUOTA, 
161                                0, 
162                                &setup, 1, 0,
163                                params, 16, 4,
164                                data, data_len, 112)) {
165                 DEBUG(1,("Failed to send NT_TRANSACT_GET_USER_QUOTA\n"));
166                 goto cleanup;
167         }
168
169
170         if (!cli_receive_nt_trans(cli,
171                                   &rparam, &rparam_count,
172                                   &rdata, &rdata_count)) {
173                 DEBUG(1,("Failed to recv NT_TRANSACT_GET_USER_QUOTA\n"));
174                 goto cleanup;
175         }
176
177         if (cli_is_error(cli)) {
178                 ret = False;
179                 goto cleanup;
180         } else {
181                 ret = True;
182         }
183
184         if ((rparam&&rdata)&&(rparam_count>=4&&rdata_count>=8)) {
185                 ret = parse_user_quota_record(rdata, rdata_count, &offset, pqt);
186         } else {
187                 DEBUG(0,("Got INVALID NT_TRANSACT_GET_USER_QUOTA reply.\n"));
188                 ret = False; 
189         }
190
191  cleanup:
192         SAFE_FREE(rparam);
193         SAFE_FREE(rdata); 
194         return ret;
195 }
196
197 bool cli_set_user_quota(struct cli_state *cli, int quota_fnum, SMB_NTQUOTA_STRUCT *pqt)
198 {
199         bool ret = False;
200         uint16 setup;
201         char params[2];
202         char data[112];
203         char *rparam=NULL, *rdata=NULL;
204         unsigned int rparam_count=0, rdata_count=0;
205         unsigned int sid_len;   
206         memset(data,'\0',112);
207
208         if (!cli||!pqt) {
209                 smb_panic("cli_set_user_quota() called with NULL Pointer!");
210         }
211
212         setup = NT_TRANSACT_SET_USER_QUOTA;
213
214         SSVAL(params,0,quota_fnum);
215
216         sid_len = ndr_size_dom_sid(&pqt->sid, 0);
217         SIVAL(data,0,0);
218         SIVAL(data,4,sid_len);
219         SBIG_UINT(data, 8,(uint64_t)0);
220         SBIG_UINT(data,16,pqt->usedspace);
221         SBIG_UINT(data,24,pqt->softlim);
222         SBIG_UINT(data,32,pqt->hardlim);
223         sid_linearize(data+40, sid_len, &pqt->sid);
224
225         if (!cli_send_nt_trans(cli, 
226                                NT_TRANSACT_SET_USER_QUOTA, 
227                                0, 
228                                &setup, 1, 0,
229                                params, 2, 0,
230                                data, 112, 0)) {
231                 DEBUG(1,("Failed to send NT_TRANSACT_SET_USER_QUOTA\n"));
232                 goto cleanup;
233         }
234
235
236         if (!cli_receive_nt_trans(cli, 
237                                   &rparam, &rparam_count,
238                                   &rdata, &rdata_count)) {
239                 DEBUG(1,("NT_TRANSACT_SET_USER_QUOTA failed\n"));
240                 goto cleanup;
241         }
242
243         if (cli_is_error(cli)) {
244                 ret = False;
245                 goto cleanup;
246         } else {
247                 ret = True;
248         }
249
250   cleanup:
251         SAFE_FREE(rparam);
252         SAFE_FREE(rdata);
253         return ret;
254 }
255
256 bool cli_list_user_quota(struct cli_state *cli, int quota_fnum, SMB_NTQUOTA_LIST **pqt_list)
257 {
258         bool ret = False;
259         uint16 setup;
260         char params[16];
261         char *rparam=NULL, *rdata=NULL;
262         unsigned int rparam_count=0, rdata_count=0;
263         unsigned int offset;
264         const char *curdata = NULL;
265         unsigned int curdata_count = 0;
266         TALLOC_CTX *mem_ctx = NULL;
267         SMB_NTQUOTA_STRUCT qt;
268         SMB_NTQUOTA_LIST *tmp_list_ent;
269
270         if (!cli||!pqt_list) {
271                 smb_panic("cli_list_user_quota() called with NULL Pointer!");
272         }
273
274         setup = NT_TRANSACT_GET_USER_QUOTA;
275
276         SSVAL(params, 0,quota_fnum);
277         SSVAL(params, 2,TRANSACT_GET_USER_QUOTA_LIST_START);
278         SIVAL(params, 4,0x00000000);
279         SIVAL(params, 8,0x00000000);
280         SIVAL(params,12,0x00000000);
281
282         if (!cli_send_nt_trans(cli, 
283                                NT_TRANSACT_GET_USER_QUOTA, 
284                                0, 
285                                &setup, 1, 0,
286                                params, 16, 4,
287                                NULL, 0, 2048)) {
288                 DEBUG(1,("Failed to send NT_TRANSACT_GET_USER_QUOTA\n"));
289                 goto cleanup;
290         }
291
292
293         if (!cli_receive_nt_trans(cli,
294                                   &rparam, &rparam_count,
295                                   &rdata, &rdata_count)) {
296                 DEBUG(1,("Failed to recv NT_TRANSACT_GET_USER_QUOTA\n"));
297                 goto cleanup;
298         }
299
300         if (cli_is_error(cli)) {
301                 ret = False;
302                 goto cleanup;
303         } else {
304                 ret = True;
305         }
306
307         if (rdata_count == 0) {
308                 *pqt_list = NULL;
309                 return True;
310         }
311
312         if ((mem_ctx=talloc_init("SMB_USER_QUOTA_LIST"))==NULL) {
313                 DEBUG(0,("talloc_init() failed\n"));
314                 return (-1);
315         }
316
317         offset = 1;
318         for (curdata=rdata,curdata_count=rdata_count;
319                 ((curdata)&&(curdata_count>=8)&&(offset>0));
320                 curdata +=offset,curdata_count -= offset) {
321                 ZERO_STRUCT(qt);
322                 if (!parse_user_quota_record(curdata, curdata_count, &offset, &qt)) {
323                         DEBUG(1,("Failed to parse the quota record\n"));
324                         goto cleanup;
325                 }
326
327                 if ((tmp_list_ent=TALLOC_ZERO_P(mem_ctx,SMB_NTQUOTA_LIST))==NULL) {
328                         DEBUG(0,("TALLOC_ZERO() failed\n"));
329                         talloc_destroy(mem_ctx);
330                         return (-1);
331                 }
332
333                 if ((tmp_list_ent->quotas=TALLOC_ZERO_P(mem_ctx,SMB_NTQUOTA_STRUCT))==NULL) {
334                         DEBUG(0,("TALLOC_ZERO() failed\n"));
335                         talloc_destroy(mem_ctx);
336                         return (-1);
337                 }
338
339                 memcpy(tmp_list_ent->quotas,&qt,sizeof(qt));
340                 tmp_list_ent->mem_ctx = mem_ctx;                
341
342                 DLIST_ADD((*pqt_list),tmp_list_ent);
343         }
344
345         SSVAL(params, 2,TRANSACT_GET_USER_QUOTA_LIST_CONTINUE); 
346         while(1) {
347                 if (!cli_send_nt_trans(cli, 
348                                        NT_TRANSACT_GET_USER_QUOTA, 
349                                        0, 
350                                        &setup, 1, 0,
351                                        params, 16, 4,
352                                        NULL, 0, 2048)) {
353                         DEBUG(1,("Failed to send NT_TRANSACT_GET_USER_QUOTA\n"));
354                         goto cleanup;
355                 }
356
357                 SAFE_FREE(rparam);
358                 SAFE_FREE(rdata);
359                 if (!cli_receive_nt_trans(cli,
360                                           &rparam, &rparam_count,
361                                           &rdata, &rdata_count)) {
362                         DEBUG(1,("Failed to recv NT_TRANSACT_GET_USER_QUOTA\n"));
363                         goto cleanup;
364                 }
365
366                 if (cli_is_error(cli)) {
367                         ret = False;
368                         goto cleanup;
369                 } else {
370                         ret = True;
371                 }
372
373                 if (rdata_count == 0) {
374                         break;  
375                 }
376
377                 offset = 1;
378                 for (curdata=rdata,curdata_count=rdata_count;
379                         ((curdata)&&(curdata_count>=8)&&(offset>0));
380                         curdata +=offset,curdata_count -= offset) {
381                         ZERO_STRUCT(qt);
382                         if (!parse_user_quota_record(curdata, curdata_count, &offset, &qt)) {
383                                 DEBUG(1,("Failed to parse the quota record\n"));
384                                 goto cleanup;
385                         }
386
387                         if ((tmp_list_ent=TALLOC_ZERO_P(mem_ctx,SMB_NTQUOTA_LIST))==NULL) {
388                                 DEBUG(0,("TALLOC_ZERO() failed\n"));
389                                 talloc_destroy(mem_ctx);
390                                 goto cleanup;
391                         }
392
393                         if ((tmp_list_ent->quotas=TALLOC_ZERO_P(mem_ctx,SMB_NTQUOTA_STRUCT))==NULL) {
394                                 DEBUG(0,("TALLOC_ZERO() failed\n"));
395                                 talloc_destroy(mem_ctx);
396                                 goto cleanup;
397                         }
398
399                         memcpy(tmp_list_ent->quotas,&qt,sizeof(qt));
400                         tmp_list_ent->mem_ctx = mem_ctx;                
401
402                         DLIST_ADD((*pqt_list),tmp_list_ent);
403                 }
404         }
405
406
407         ret = True;
408  cleanup:
409         SAFE_FREE(rparam);
410         SAFE_FREE(rdata);
411
412         return ret;
413 }
414
415 bool cli_get_fs_quota_info(struct cli_state *cli, int quota_fnum, SMB_NTQUOTA_STRUCT *pqt)
416 {
417         bool ret = False;
418         uint16 setup;
419         char param[2];
420         char *rparam=NULL, *rdata=NULL;
421         unsigned int rparam_count=0, rdata_count=0;
422         SMB_NTQUOTA_STRUCT qt;
423         ZERO_STRUCT(qt);
424
425         if (!cli||!pqt) {
426                 smb_panic("cli_get_fs_quota_info() called with NULL Pointer!");
427         }
428
429         setup = TRANSACT2_QFSINFO;
430
431         SSVAL(param,0,SMB_FS_QUOTA_INFORMATION);
432
433         if (!cli_send_trans(cli, SMBtrans2, 
434                     NULL, 
435                     0, 0,
436                     &setup, 1, 0,
437                     param, 2, 0,
438                     NULL, 0, 560)) {
439                 goto cleanup;
440         }
441
442         if (!cli_receive_trans(cli, SMBtrans2,
443                               &rparam, &rparam_count,
444                               &rdata, &rdata_count)) {
445                 goto cleanup;
446         }
447
448         if (cli_is_error(cli)) {
449                 ret = False;
450                 goto cleanup;
451         } else {
452                 ret = True;
453         }
454
455         if (rdata_count < 48) {
456                 goto cleanup;
457         }
458
459         /* unknown_1 24 NULL bytes in pdata*/
460
461         /* the soft quotas 8 bytes (uint64_t)*/
462         qt.softlim = (uint64_t)IVAL(rdata,24);
463 #ifdef LARGE_SMB_OFF_T
464         qt.softlim |= (((uint64_t)IVAL(rdata,28)) << 32);
465 #else /* LARGE_SMB_OFF_T */
466         if ((IVAL(rdata,28) != 0)&&
467                 ((qt.softlim != 0xFFFFFFFF)||
468                  (IVAL(rdata,28)!=0xFFFFFFFF))) {
469                 /* more than 32 bits? */
470                 goto cleanup;
471         }
472 #endif /* LARGE_SMB_OFF_T */
473
474         /* the hard quotas 8 bytes (uint64_t)*/
475         qt.hardlim = (uint64_t)IVAL(rdata,32);
476 #ifdef LARGE_SMB_OFF_T
477         qt.hardlim |= (((uint64_t)IVAL(rdata,36)) << 32);
478 #else /* LARGE_SMB_OFF_T */
479         if ((IVAL(rdata,36) != 0)&&
480                 ((qt.hardlim != 0xFFFFFFFF)||
481                  (IVAL(rdata,36)!=0xFFFFFFFF))) {
482                 /* more than 32 bits? */
483                 goto cleanup;
484         }
485 #endif /* LARGE_SMB_OFF_T */
486
487         /* quota_flags 2 bytes **/
488         qt.qflags = SVAL(rdata,40);
489
490         qt.qtype = SMB_USER_FS_QUOTA_TYPE;
491
492         *pqt = qt;
493
494         ret = True;
495 cleanup:
496         SAFE_FREE(rparam);
497         SAFE_FREE(rdata);
498
499         return ret;     
500 }
501
502 bool cli_set_fs_quota_info(struct cli_state *cli, int quota_fnum, SMB_NTQUOTA_STRUCT *pqt)
503 {
504         bool ret = False;
505         uint16 setup;
506         char param[4];
507         char data[48];
508         char *rparam=NULL, *rdata=NULL;
509         unsigned int rparam_count=0, rdata_count=0;
510         SMB_NTQUOTA_STRUCT qt;
511         ZERO_STRUCT(qt);
512         memset(data,'\0',48);
513
514         if (!cli||!pqt) {
515                 smb_panic("cli_set_fs_quota_info() called with NULL Pointer!");
516         }
517
518         setup = TRANSACT2_SETFSINFO;
519
520         SSVAL(param,0,quota_fnum);
521         SSVAL(param,2,SMB_FS_QUOTA_INFORMATION);
522
523         /* Unknown1 24 NULL bytes*/
524
525         /* Default Soft Quota 8 bytes */
526         SBIG_UINT(data,24,pqt->softlim);
527
528         /* Default Hard Quota 8 bytes */
529         SBIG_UINT(data,32,pqt->hardlim);
530
531         /* Quota flag 2 bytes */
532         SSVAL(data,40,pqt->qflags);
533
534         /* Unknown3 6 NULL bytes */
535
536         if (!cli_send_trans(cli, SMBtrans2, 
537                     NULL, 
538                     0, 0,
539                     &setup, 1, 0,
540                     param, 4, 0,
541                     data, 48, 0)) {
542                 goto cleanup;
543         }
544
545         if (!cli_receive_trans(cli, SMBtrans2,
546                               &rparam, &rparam_count,
547                               &rdata, &rdata_count)) {
548                 goto cleanup;
549         }
550
551         if (cli_is_error(cli)) {
552                 ret = False;
553                 goto cleanup;
554         } else {
555                 ret = True;
556         }
557
558 cleanup:
559         SAFE_FREE(rparam);
560         SAFE_FREE(rdata);
561
562         return ret;     
563 }
564
565 static const char *quota_str_static(uint64_t val, bool special, bool _numeric)
566 {
567         const char *result;
568
569         if (!_numeric&&special&&(val == SMB_NTQUOTAS_NO_LIMIT)) {
570                 return "NO LIMIT";
571         }
572         result = talloc_asprintf(talloc_tos(), "%"PRIu64, val);
573         SMB_ASSERT(result != NULL);
574         return result;
575 }
576
577 void dump_ntquota(SMB_NTQUOTA_STRUCT *qt, bool _verbose, bool _numeric, void (*_sidtostring)(fstring str, DOM_SID *sid, bool _numeric))
578 {
579         TALLOC_CTX *frame = talloc_stackframe();
580
581         if (!qt) {
582                 smb_panic("dump_ntquota() called with NULL pointer");
583         }
584
585         switch (qt->qtype) {
586                 case SMB_USER_FS_QUOTA_TYPE:
587                         {
588                                 d_printf("File System QUOTAS:\n");
589                                 d_printf("Limits:\n");
590                                 d_printf(" Default Soft Limit: %15s\n",quota_str_static(qt->softlim,True,_numeric));
591                                 d_printf(" Default Hard Limit: %15s\n",quota_str_static(qt->hardlim,True,_numeric));
592                                 d_printf("Quota Flags:\n");
593                                 d_printf(" Quotas Enabled: %s\n",
594                                         ((qt->qflags&QUOTAS_ENABLED)||(qt->qflags&QUOTAS_DENY_DISK))?"On":"Off");
595                                 d_printf(" Deny Disk:      %s\n",(qt->qflags&QUOTAS_DENY_DISK)?"On":"Off");
596                                 d_printf(" Log Soft Limit: %s\n",(qt->qflags&QUOTAS_LOG_THRESHOLD)?"On":"Off");
597                                 d_printf(" Log Hard Limit: %s\n",(qt->qflags&QUOTAS_LOG_LIMIT)?"On":"Off");
598                         }
599                         break;
600                 case SMB_USER_QUOTA_TYPE:
601                         {
602                                 fstring username_str = {0};
603
604                                 if (_sidtostring) {
605                                         _sidtostring(username_str,&qt->sid,_numeric);
606                                 } else {
607                                         sid_to_fstring(username_str, &qt->sid);
608                                 }
609
610                                 if (_verbose) { 
611                                         d_printf("Quotas for User: %s\n",username_str);
612                                         d_printf("Used Space: %15s\n",quota_str_static(qt->usedspace,False,_numeric));
613                                         d_printf("Soft Limit: %15s\n",quota_str_static(qt->softlim,True,_numeric));
614                                         d_printf("Hard Limit: %15s\n",quota_str_static(qt->hardlim,True,_numeric));
615                                 } else {
616                                         d_printf("%-30s: ",username_str);
617                                         d_printf("%15s/",quota_str_static(qt->usedspace,False,_numeric));
618                                         d_printf("%15s/",quota_str_static(qt->softlim,True,_numeric));
619                                         d_printf("%15s\n",quota_str_static(qt->hardlim,True,_numeric));
620                                 }
621                         }
622                         break;
623                 default:
624                         d_printf("dump_ntquota() invalid qtype(%d)\n",qt->qtype);
625         }
626         TALLOC_FREE(frame);
627         return;
628 }
629
630 void dump_ntquota_list(SMB_NTQUOTA_LIST **qtl, bool _verbose, bool _numeric, void (*_sidtostring)(fstring str, DOM_SID *sid, bool _numeric))
631 {
632         SMB_NTQUOTA_LIST *cur;
633
634         for (cur = *qtl;cur;cur = cur->next) {
635                 if (cur->quotas)
636                         dump_ntquota(cur->quotas,_verbose,_numeric,_sidtostring);
637         }       
638 }