2 Unix SMB/CIFS implementation.
3 SMB NT transaction handling
4 Copyright (C) Jeremy Allison 1994-2007
5 Copyright (C) Stefan (metze) Metzmacher 2003
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 3 of the License, or
10 (at your option) any later version.
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program. If not, see <http://www.gnu.org/licenses/>.
22 #include "system/filesys.h"
23 #include "smbd/smbd.h"
24 #include "smbd/globals.h"
25 #include "fake_file.h"
26 #include "../libcli/security/security.h"
27 #include "../librpc/gen_ndr/ndr_security.h"
28 #include "passdb/lookup_sid.h"
30 #include "smbprofile.h"
31 #include "libsmb/libsmb.h"
32 #include "lib/util_ea.h"
33 #include "librpc/gen_ndr/ndr_quota.h"
34 #include "librpc/gen_ndr/ndr_security.h"
36 extern const struct generic_mapping file_generic_mapping
;
38 /*********************************************************************
39 Windows seems to do canonicalization of inheritance bits. Do the
41 *********************************************************************/
43 static void canonicalize_inheritance_bits(struct files_struct
*fsp
,
44 struct security_descriptor
*psd
)
46 bool set_auto_inherited
= false;
49 * We need to filter out the
50 * SEC_DESC_DACL_AUTO_INHERITED|SEC_DESC_DACL_AUTO_INHERIT_REQ
51 * bits. If both are set we store SEC_DESC_DACL_AUTO_INHERITED
52 * as this alters whether SEC_ACE_FLAG_INHERITED_ACE is set
53 * when an ACE is inherited. Otherwise we zero these bits out.
56 * http://social.msdn.microsoft.com/Forums/eu/os_fileservices/thread/11f77b68-731e-407d-b1b3-064750716531
61 if (!lp_acl_flag_inherited_canonicalization(SNUM(fsp
->conn
))) {
62 psd
->type
&= ~SEC_DESC_DACL_AUTO_INHERIT_REQ
;
66 if ((psd
->type
& (SEC_DESC_DACL_AUTO_INHERITED
|SEC_DESC_DACL_AUTO_INHERIT_REQ
))
67 == (SEC_DESC_DACL_AUTO_INHERITED
|SEC_DESC_DACL_AUTO_INHERIT_REQ
)) {
68 set_auto_inherited
= true;
71 psd
->type
&= ~(SEC_DESC_DACL_AUTO_INHERITED
|SEC_DESC_DACL_AUTO_INHERIT_REQ
);
72 if (set_auto_inherited
) {
73 psd
->type
|= SEC_DESC_DACL_AUTO_INHERITED
;
77 /****************************************************************************
78 Internal fn to set security descriptors.
79 ****************************************************************************/
81 NTSTATUS
set_sd(files_struct
*fsp
, struct security_descriptor
*psd
,
82 uint32_t security_info_sent
)
84 files_struct
*sd_fsp
= NULL
;
88 if (!CAN_WRITE(fsp
->conn
)) {
89 return NT_STATUS_ACCESS_DENIED
;
92 if (!lp_nt_acl_support(SNUM(fsp
->conn
))) {
96 refuse
= refuse_symlink_fsp(fsp
);
98 DBG_DEBUG("ACL set on symlink %s denied.\n",
100 return NT_STATUS_ACCESS_DENIED
;
103 if (psd
->owner_sid
== NULL
) {
104 security_info_sent
&= ~SECINFO_OWNER
;
106 if (psd
->group_sid
== NULL
) {
107 security_info_sent
&= ~SECINFO_GROUP
;
110 /* Ensure we have at least one thing set. */
111 if ((security_info_sent
& (SECINFO_OWNER
|SECINFO_GROUP
|SECINFO_DACL
|SECINFO_SACL
)) == 0) {
116 /* Ensure we have the rights to do this. */
117 if (security_info_sent
& SECINFO_OWNER
) {
118 status
= check_any_access_fsp(fsp
, SEC_STD_WRITE_OWNER
);
119 if (!NT_STATUS_IS_OK(status
)) {
124 if (security_info_sent
& SECINFO_GROUP
) {
125 status
= check_any_access_fsp(fsp
, SEC_STD_WRITE_OWNER
);
126 if (!NT_STATUS_IS_OK(status
)) {
131 if (security_info_sent
& SECINFO_DACL
) {
132 status
= check_any_access_fsp(fsp
, SEC_STD_WRITE_DAC
);
133 if (!NT_STATUS_IS_OK(status
)) {
136 /* Convert all the generic bits. */
138 security_acl_map_generic(psd
->dacl
, &file_generic_mapping
);
142 if (security_info_sent
& SECINFO_SACL
) {
143 status
= check_any_access_fsp(fsp
, SEC_FLAG_SYSTEM_SECURITY
);
144 if (!NT_STATUS_IS_OK(status
)) {
148 * Setting a SACL also requires WRITE_DAC.
149 * See the smbtorture3 SMB2-SACL test.
151 status
= check_any_access_fsp(fsp
, SEC_STD_WRITE_DAC
);
152 if (!NT_STATUS_IS_OK(status
)) {
155 /* Convert all the generic bits. */
157 security_acl_map_generic(psd
->sacl
, &file_generic_mapping
);
161 canonicalize_inheritance_bits(fsp
, psd
);
163 if (DEBUGLEVEL
>= 10) {
164 DEBUG(10,("set_sd for file %s\n", fsp_str_dbg(fsp
)));
165 NDR_PRINT_DEBUG(security_descriptor
, psd
);
168 sd_fsp
= metadata_fsp(fsp
);
169 status
= SMB_VFS_FSET_NT_ACL(sd_fsp
, security_info_sent
, psd
);
176 static bool check_smb2_posix_chmod_ace(const struct files_struct
*fsp
,
177 uint32_t security_info_sent
,
178 struct security_descriptor
*psd
,
181 struct security_ace
*ace
= NULL
;
185 * This must be an ACL with one ACE containing an
186 * MS NFS style mode entry coming in on a POSIX
189 if (!conn_using_smb2(fsp
->conn
->sconn
)) {
193 if (!fsp
->fsp_flags
.posix_open
) {
197 if (!(security_info_sent
& SECINFO_DACL
)) {
201 if (psd
->dacl
== NULL
) {
205 if (psd
->dacl
->num_aces
!= 1) {
208 ace
= &psd
->dacl
->aces
[0];
210 if (ace
->trustee
.num_auths
!= 3) {
214 cmp
= dom_sid_compare_domain(&global_sid_Unix_NFS_Mode
, &ace
->trustee
);
219 *pmode
= (mode_t
)ace
->trustee
.sub_auths
[2];
220 *pmode
&= (S_IRWXU
| S_IRWXG
| S_IRWXO
);
225 /****************************************************************************
226 Internal fn to set security descriptors from a data blob.
227 ****************************************************************************/
229 NTSTATUS
set_sd_blob(files_struct
*fsp
, uint8_t *data
, uint32_t sd_len
,
230 uint32_t security_info_sent
)
232 struct security_descriptor
*psd
= NULL
;
234 bool do_chmod
= false;
235 mode_t smb2_posix_mode
= 0;
239 return NT_STATUS_INVALID_PARAMETER
;
242 status
= unmarshall_sec_desc(talloc_tos(), data
, sd_len
, &psd
);
244 if (!NT_STATUS_IS_OK(status
)) {
248 do_chmod
= check_smb2_posix_chmod_ace(fsp
,
253 return set_sd(fsp
, psd
, security_info_sent
);
258 ret
= SMB_VFS_FCHMOD(fsp
, smb2_posix_mode
);
260 status
= map_nt_error_from_unix(errno
);
261 DBG_ERR("smb2_posix_chmod [%s] [%04o] failed: %s\n",
263 (unsigned)smb2_posix_mode
,
271 /****************************************************************************
273 ****************************************************************************/
275 NTSTATUS
copy_internals(TALLOC_CTX
*ctx
,
276 connection_struct
*conn
,
277 struct smb_request
*req
,
278 struct files_struct
*src_dirfsp
,
279 struct smb_filename
*smb_fname_src
,
280 struct files_struct
*dst_dirfsp
,
281 struct smb_filename
*smb_fname_dst
,
284 files_struct
*fsp1
,*fsp2
;
288 NTSTATUS status
= NT_STATUS_OK
;
289 struct smb_filename
*parent
= NULL
;
290 struct smb_filename
*pathref
= NULL
;
292 if (!CAN_WRITE(conn
)) {
293 status
= NT_STATUS_MEDIA_WRITE_PROTECTED
;
297 /* Source must already exist. */
298 if (!VALID_STAT(smb_fname_src
->st
)) {
299 status
= NT_STATUS_OBJECT_NAME_NOT_FOUND
;
303 /* Ensure attributes match. */
304 fattr
= fdos_mode(smb_fname_src
->fsp
);
305 if ((fattr
& ~attrs
) & (FILE_ATTRIBUTE_HIDDEN
| FILE_ATTRIBUTE_SYSTEM
)) {
306 status
= NT_STATUS_NO_SUCH_FILE
;
310 /* Disallow if dst file already exists. */
311 if (VALID_STAT(smb_fname_dst
->st
)) {
312 status
= NT_STATUS_OBJECT_NAME_COLLISION
;
316 /* No links from a directory. */
317 if (S_ISDIR(smb_fname_src
->st
.st_ex_mode
)) {
318 status
= NT_STATUS_FILE_IS_A_DIRECTORY
;
322 DBG_DEBUG("doing file copy %s to %s\n",
323 smb_fname_str_dbg(smb_fname_src
),
324 smb_fname_str_dbg(smb_fname_dst
));
326 status
= SMB_VFS_CREATE_FILE(
329 src_dirfsp
, /* dirfsp */
330 smb_fname_src
, /* fname */
331 FILE_READ_DATA
|FILE_READ_ATTRIBUTES
|
332 FILE_READ_EA
, /* access_mask */
333 (FILE_SHARE_READ
| FILE_SHARE_WRITE
| /* share_access */
335 FILE_OPEN
, /* create_disposition*/
336 0, /* create_options */
337 FILE_ATTRIBUTE_NORMAL
, /* file_attributes */
338 NO_OPLOCK
, /* oplock_request */
340 0, /* allocation_size */
341 0, /* private_flags */
346 NULL
, NULL
); /* create context */
348 if (!NT_STATUS_IS_OK(status
)) {
352 status
= SMB_VFS_CREATE_FILE(
355 dst_dirfsp
, /* dirfsp */
356 smb_fname_dst
, /* fname */
357 FILE_WRITE_DATA
|FILE_WRITE_ATTRIBUTES
|
358 FILE_WRITE_EA
, /* access_mask */
359 (FILE_SHARE_READ
| FILE_SHARE_WRITE
| /* share_access */
361 FILE_CREATE
, /* create_disposition*/
362 0, /* create_options */
363 fattr
, /* file_attributes */
364 NO_OPLOCK
, /* oplock_request */
366 0, /* allocation_size */
367 0, /* private_flags */
372 NULL
, NULL
); /* create context */
374 if (!NT_STATUS_IS_OK(status
)) {
375 close_file_free(NULL
, &fsp1
, ERROR_CLOSE
);
379 if (smb_fname_src
->st
.st_ex_size
) {
380 ret
= vfs_transfer_file(fsp1
, fsp2
, smb_fname_src
->st
.st_ex_size
);
384 * As we are opening fsp1 read-only we only expect
385 * an error on close on fsp2 if we are out of space.
386 * Thus we don't look at the error return from the
389 close_file_free(NULL
, &fsp1
, NORMAL_CLOSE
);
391 /* Ensure the modtime is set correctly on the destination file. */
392 set_close_write_time(fsp2
, smb_fname_src
->st
.st_ex_mtime
);
394 status
= close_file_free(NULL
, &fsp2
, NORMAL_CLOSE
);
395 if (!NT_STATUS_IS_OK(status
)) {
396 DBG_WARNING("close_file_free() failed: %s\n",
399 * We can't do much but leak the fsp
404 /* Grrr. We have to do this as open_file_ntcreate adds FILE_ATTRIBUTE_ARCHIVE when it
405 creates the file. This isn't the correct thing to do in the copy
408 status
= SMB_VFS_PARENT_PATHNAME(conn
,
413 if (!NT_STATUS_IS_OK(status
)) {
416 if (smb_fname_dst
->fsp
== NULL
) {
417 status
= synthetic_pathref(parent
,
419 smb_fname_dst
->base_name
,
420 smb_fname_dst
->stream_name
,
423 smb_fname_dst
->flags
,
426 /* should we handle NT_STATUS_OBJECT_NAME_NOT_FOUND specially here ???? */
427 if (!NT_STATUS_IS_OK(status
)) {
431 file_set_dosmode(conn
, pathref
, fattr
, parent
, false);
432 smb_fname_dst
->st
.st_ex_mode
= pathref
->st
.st_ex_mode
;
434 file_set_dosmode(conn
, smb_fname_dst
, fattr
, parent
, false);
438 if (ret
< (off_t
)smb_fname_src
->st
.st_ex_size
) {
439 status
= NT_STATUS_DISK_FULL
;
443 if (!NT_STATUS_IS_OK(status
)) {
444 DBG_NOTICE("Error %s copy file %s to %s\n",
446 smb_fname_str_dbg(smb_fname_src
),
447 smb_fname_str_dbg(smb_fname_dst
));
453 /******************************************************************************
454 Fake up a completely empty SD.
455 *******************************************************************************/
457 static NTSTATUS
get_null_nt_acl(TALLOC_CTX
*mem_ctx
, struct security_descriptor
**ppsd
)
461 *ppsd
= make_standard_sec_desc( mem_ctx
, &global_sid_World
, &global_sid_World
, NULL
, &sd_size
);
463 DBG_ERR("Unable to malloc space for security descriptor.\n");
464 return NT_STATUS_NO_MEMORY
;
470 /****************************************************************************
471 Get a security descriptor from the file system, normalize for components
473 ****************************************************************************/
475 static NTSTATUS
smbd_fetch_security_desc(connection_struct
*conn
,
478 uint32_t security_info_wanted
,
479 struct security_descriptor
**ppsd
)
482 struct security_descriptor
*psd
= NULL
;
483 bool need_to_read_sd
= false;
487 * Get the permissions to return.
490 if (security_info_wanted
& SECINFO_SACL
) {
491 status
= check_any_access_fsp(fsp
, SEC_FLAG_SYSTEM_SECURITY
);
492 if (!NT_STATUS_IS_OK(status
)) {
493 DBG_DEBUG("Access to SACL denied.\n");
498 if (security_info_wanted
& (SECINFO_DACL
|SECINFO_OWNER
|SECINFO_GROUP
)) {
499 status
= check_any_access_fsp(fsp
, SEC_STD_READ_CONTROL
);
500 if (!NT_STATUS_IS_OK(status
)) {
501 DBG_DEBUG("Access to DACL, OWNER, or GROUP denied.\n");
506 refuse
= refuse_symlink_fsp(fsp
);
508 DBG_DEBUG("ACL get on symlink %s denied.\n",
510 return NT_STATUS_ACCESS_DENIED
;
513 if (security_info_wanted
& (SECINFO_DACL
|SECINFO_OWNER
|
514 SECINFO_GROUP
|SECINFO_SACL
)) {
515 /* Don't return SECINFO_LABEL if anything else was
516 requested. See bug #8458. */
517 security_info_wanted
&= ~SECINFO_LABEL
;
520 * Only query the file system SD if the caller asks
521 * for any bits. This allows a caller to open without
522 * READ_CONTROL but still issue a query sd. See
525 need_to_read_sd
= true;
528 if (lp_nt_acl_support(SNUM(conn
)) &&
529 ((security_info_wanted
& SECINFO_LABEL
) == 0) &&
532 files_struct
*sd_fsp
= metadata_fsp(fsp
);
533 status
= SMB_VFS_FGET_NT_ACL(
534 sd_fsp
, security_info_wanted
, mem_ctx
, &psd
);
536 status
= get_null_nt_acl(mem_ctx
, &psd
);
539 if (!NT_STATUS_IS_OK(status
)) {
543 if (!(security_info_wanted
& SECINFO_OWNER
)) {
544 psd
->owner_sid
= NULL
;
546 if (!(security_info_wanted
& SECINFO_GROUP
)) {
547 psd
->group_sid
= NULL
;
549 if (!(security_info_wanted
& SECINFO_DACL
)) {
550 psd
->type
&= ~SEC_DESC_DACL_PRESENT
;
553 if (!(security_info_wanted
& SECINFO_SACL
)) {
554 psd
->type
&= ~SEC_DESC_SACL_PRESENT
;
558 /* If the SACL/DACL is NULL, but was requested, we mark that it is
559 * present in the reply to match Windows behavior */
560 if (psd
->sacl
== NULL
&&
561 security_info_wanted
& SECINFO_SACL
)
562 psd
->type
|= SEC_DESC_SACL_PRESENT
;
563 if (psd
->dacl
== NULL
&&
564 security_info_wanted
& SECINFO_DACL
)
565 psd
->type
|= SEC_DESC_DACL_PRESENT
;
567 if (security_info_wanted
& SECINFO_LABEL
) {
568 /* Like W2K3 return a null object. */
569 psd
->owner_sid
= NULL
;
570 psd
->group_sid
= NULL
;
573 psd
->type
&= ~(SEC_DESC_DACL_PRESENT
|SEC_DESC_SACL_PRESENT
);
580 /****************************************************************************
581 Write a security descriptor into marshalled format.
582 ****************************************************************************/
584 static NTSTATUS
smbd_marshall_security_desc(TALLOC_CTX
*mem_ctx
,
586 struct security_descriptor
*psd
,
587 uint32_t max_data_count
,
588 uint8_t **ppmarshalled_sd
,
591 *psd_size
= ndr_size_security_descriptor(psd
, 0);
593 DBG_NOTICE("sd_size = %zu.\n", *psd_size
);
595 if (DEBUGLEVEL
>= 10) {
596 DBG_DEBUG("security desc for file %s\n",
598 NDR_PRINT_DEBUG(security_descriptor
, psd
);
601 if (max_data_count
< *psd_size
) {
602 return NT_STATUS_BUFFER_TOO_SMALL
;
605 return marshall_sec_desc(mem_ctx
,
611 /****************************************************************************
612 Reply to query a security descriptor.
613 Callable from SMB1 and SMB2.
614 If it returns NT_STATUS_BUFFER_TOO_SMALL, psd_size is initialized with
616 ****************************************************************************/
618 NTSTATUS
smbd_do_query_security_desc(connection_struct
*conn
,
621 uint32_t security_info_wanted
,
622 uint32_t max_data_count
,
623 uint8_t **ppmarshalled_sd
,
627 struct security_descriptor
*psd
= NULL
;
630 * Get the permissions to return.
633 status
= smbd_fetch_security_desc(conn
,
636 security_info_wanted
,
638 if (!NT_STATUS_IS_OK(status
)) {
642 status
= smbd_marshall_security_desc(mem_ctx
,
652 #ifdef HAVE_SYS_QUOTAS
653 static enum ndr_err_code
fill_qtlist_from_sids(TALLOC_CTX
*mem_ctx
,
654 struct files_struct
*fsp
,
655 SMB_NTQUOTA_HANDLE
*qt_handle
,
656 struct dom_sid
*sids
,
660 TALLOC_CTX
*list_ctx
= NULL
;
662 list_ctx
= talloc_init("quota_sid_list");
664 if (list_ctx
== NULL
) {
665 DBG_ERR("failed to allocate\n");
666 return NDR_ERR_ALLOC
;
669 if (qt_handle
->quota_list
!=NULL
) {
670 free_ntquota_list(&(qt_handle
->quota_list
));
672 for (i
= 0; i
< elems
; i
++) {
673 SMB_NTQUOTA_STRUCT qt
;
674 SMB_NTQUOTA_LIST
*list_item
;
677 if (!NT_STATUS_IS_OK(vfs_get_ntquota(fsp
,
680 /* non fatal error, return empty item in result */
686 list_item
= talloc_zero(list_ctx
, SMB_NTQUOTA_LIST
);
687 if (list_item
== NULL
) {
688 DBG_ERR("failed to allocate\n");
689 return NDR_ERR_ALLOC
;
692 ok
= sid_to_uid(&sids
[i
], &list_item
->uid
);
694 struct dom_sid_buf buf
;
695 DBG_WARNING("Could not convert SID %s to uid\n",
696 dom_sid_str_buf(&sids
[i
], &buf
));
697 /* No idea what to return here... */
698 return NDR_ERR_INVALID_POINTER
;
701 list_item
->quotas
= talloc_zero(list_item
, SMB_NTQUOTA_STRUCT
);
702 if (list_item
->quotas
== NULL
) {
703 DBG_ERR("failed to allocate\n");
704 return NDR_ERR_ALLOC
;
707 *list_item
->quotas
= qt
;
708 list_item
->mem_ctx
= list_ctx
;
709 DLIST_ADD(qt_handle
->quota_list
, list_item
);
711 qt_handle
->tmp_list
= qt_handle
->quota_list
;
712 return NDR_ERR_SUCCESS
;
715 static enum ndr_err_code
extract_sids_from_buf(TALLOC_CTX
*mem_ctx
,
716 uint32_t sidlistlength
,
718 struct dom_sid
**sids
,
723 enum ndr_err_code err
;
725 struct sid_list_elem
{
726 struct sid_list_elem
*prev
, *next
;
730 struct sid_list_elem
*sid_list
= NULL
;
731 struct sid_list_elem
*iter
= NULL
;
732 TALLOC_CTX
*list_ctx
= talloc_init("sid_list");
744 struct ndr_pull
*ndr_pull
= NULL
;
746 if (sidlistlength
> sid_buf
->length
) {
747 DBG_ERR("sid_list_length 0x%x exceeds "
748 "available bytes %zx\n",
751 err
= NDR_ERR_OFFSET
;
755 struct file_get_quota_info info
;
756 struct sid_list_elem
*item
= NULL
;
757 uint32_t new_offset
= 0;
758 blob
.data
= sid_buf
->data
+ offset
;
759 blob
.length
= sidlistlength
- offset
;
760 ndr_pull
= ndr_pull_init_blob(&blob
, list_ctx
);
766 err
= ndr_pull_file_get_quota_info(ndr_pull
,
767 NDR_SCALARS
| NDR_BUFFERS
, &info
);
768 if (!NDR_ERR_CODE_IS_SUCCESS(err
)) {
769 DBG_ERR("Failed to pull file_get_quota_info "
770 "from sidlist buffer\n");
773 item
= talloc_zero(list_ctx
, struct sid_list_elem
);
779 item
->sid
= info
.sid
;
780 DLIST_ADD(sid_list
, item
);
782 if (i
== UINT32_MAX
) {
783 DBG_ERR("Integer overflow\n");
784 err
= NDR_ERR_ARRAY_SIZE
;
787 new_offset
= info
.next_entry_offset
;
789 /* if new_offset == 0 no more sid(s) to read. */
790 if (new_offset
== 0) {
795 if ((offset
+ new_offset
) < offset
) {
796 DBG_ERR("Integer wrap while adding "
797 "new_offset 0x%x to current "
798 "buffer offset 0x%x\n",
800 err
= NDR_ERR_OFFSET
;
804 offset
+= new_offset
;
806 /* check if new offset is outside buffer boundary. */
807 if (offset
>= sidlistlength
) {
808 DBG_ERR("bufsize 0x%x exceeded by "
809 "new offset 0x%x)\n",
812 err
= NDR_ERR_OFFSET
;
816 *sids
= talloc_zero_array(mem_ctx
, struct dom_sid
, i
);
825 for (iter
= sid_list
, i
= 0; iter
; iter
= iter
->next
, i
++) {
826 struct dom_sid_buf buf
;
827 (*sids
)[i
] = iter
->sid
;
828 DBG_DEBUG("quota SID[%u] %s\n",
830 dom_sid_str_buf(&iter
->sid
, &buf
));
833 err
= NDR_ERR_SUCCESS
;
835 TALLOC_FREE(list_ctx
);
839 NTSTATUS
smbd_do_query_getinfo_quota(TALLOC_CTX
*mem_ctx
,
843 uint32_t sid_list_length
,
845 uint32_t max_data_count
,
847 uint32_t *p_data_size
)
850 SMB_NTQUOTA_HANDLE
*qt_handle
= NULL
;
851 SMB_NTQUOTA_LIST
*qt_list
= NULL
;
852 DATA_BLOB blob
= data_blob_null
;
853 enum ndr_err_code err
;
856 (SMB_NTQUOTA_HANDLE
*)fsp
->fake_file_handle
->private_data
;
858 if (sid_list_length
) {
859 struct dom_sid
*sids
;
862 * error check pulled offsets and lengths for wrap and
863 * exceeding available bytes.
865 if (sid_list_length
> sid_buf
->length
) {
866 DBG_ERR("sid_list_length 0x%x exceeds "
867 "available bytes %zx\n",
870 return NT_STATUS_INVALID_PARAMETER
;
873 err
= extract_sids_from_buf(mem_ctx
, sid_list_length
,
874 sid_buf
, &sids
, &elems
);
875 if (!NDR_ERR_CODE_IS_SUCCESS(err
) || elems
== 0) {
876 return NT_STATUS_INVALID_PARAMETER
;
878 err
= fill_qtlist_from_sids(mem_ctx
,
883 if (!NDR_ERR_CODE_IS_SUCCESS(err
)) {
884 return NT_STATUS_INVALID_PARAMETER
;
886 } else if (restart_scan
) {
887 if (vfs_get_user_ntquota_list(fsp
,
888 &(qt_handle
->quota_list
))!=0) {
889 return NT_STATUS_INTERNAL_ERROR
;
892 if (qt_handle
->quota_list
!=NULL
&&
893 qt_handle
->tmp_list
==NULL
) {
894 free_ntquota_list(&(qt_handle
->quota_list
));
898 if (restart_scan
!=0 ) {
899 qt_list
= qt_handle
->quota_list
;
901 qt_list
= qt_handle
->tmp_list
;
903 status
= fill_quota_buffer(mem_ctx
, qt_list
,
907 &qt_handle
->tmp_list
);
908 if (!NT_STATUS_IS_OK(status
)) {
911 if (blob
.length
> max_data_count
) {
912 return NT_STATUS_BUFFER_TOO_SMALL
;
916 *p_data_size
= blob
.length
;
919 #endif /* HAVE_SYS_QUOTAS */