-static BOOL unpack_nt_permissions(SMB_STRUCT_STAT *psbuf, uid_t *puser, gid_t *pgrp, mode_t *pmode,
- uint32 security_info_sent, SEC_DESC *psd, BOOL is_directory)
-{
- extern DOM_SID global_sid_World;
- DOM_SID owner_sid;
- DOM_SID grp_sid;
- DOM_SID file_owner_sid;
- DOM_SID file_grp_sid;
- uint32 owner_rid;
- uint32 grp_rid;
- SEC_ACL *dacl = psd->dacl;
- BOOL all_aces_are_inherit_only = (is_directory ? True : False);
- int i;
-
- *pmode = 0;
- *puser = (uid_t)-1;
- *pgrp = (gid_t)-1;
-
- if(security_info_sent == 0) {
- DEBUG(0,("unpack_nt_permissions: no security info sent !\n"));
- return False;
- }
-
- /*
- * Windows 2000 sends the owner and group SIDs as the logged in
- * user, not the connected user. But it still sends the file
- * owner SIDs on an ACL set. So we need to check for the file
- * owner and group SIDs as well as the owner SIDs. JRA.
- */
-
- create_file_sids(psbuf, &file_owner_sid, &file_grp_sid);
-
- /*
- * Validate the owner and group SID's.
- */
-
- memset(&owner_sid, '\0', sizeof(owner_sid));
- memset(&grp_sid, '\0', sizeof(grp_sid));
-
- DEBUG(5,("unpack_nt_permissions: validating owner_sid.\n"));
-
- /*
- * Don't immediately fail if the owner sid cannot be validated.
- * This may be a group chown only set.
- */
-
- if(!validate_unix_sid( &owner_sid, &owner_rid, psd->owner_sid))
- DEBUG(3,("unpack_nt_permissions: unable to validate owner sid.\n"));
- else if(security_info_sent & OWNER_SECURITY_INFORMATION)
- *puser = pdb_user_rid_to_uid(owner_rid);
-
- /*
- * Don't immediately fail if the group sid cannot be validated.
- * This may be an owner chown only set.
- */
-
- if(!validate_unix_sid( &grp_sid, &grp_rid, psd->grp_sid))
- DEBUG(3,("unpack_nt_permissions: unable to validate group sid.\n"));
- else if(security_info_sent & GROUP_SECURITY_INFORMATION)
- *pgrp = pdb_user_rid_to_gid(grp_rid);
-
- /*
- * If no DACL then this is a chown only security descriptor.
- */
-
- if(!(security_info_sent & DACL_SECURITY_INFORMATION) || !dacl) {
- *pmode = 0;
- return True;
- }
-
- /*
- * Now go through the DACL and ensure that
- * any owner/group sids match.
- */
-
- for(i = 0; i < dacl->num_aces; i++) {
- DOM_SID ace_sid;
- SEC_ACE *psa = &dacl->ace[i];
-
- if((psa->type != SEC_ACE_TYPE_ACCESS_ALLOWED) &&
- (psa->type != SEC_ACE_TYPE_ACCESS_DENIED)) {
- DEBUG(3,("unpack_nt_permissions: unable to set anything but an ALLOW or DENY ACE.\n"));
- return False;
- }
-
- /*
- * Ignore or remove bits we don't care about on a directory ACE.
- */
-
- if(is_directory) {
- if(psa->flags & SEC_ACE_FLAG_INHERIT_ONLY) {
- DEBUG(3,("unpack_nt_permissions: ignoring inherit only ACE.\n"));
- continue;
- }
-
- /*
- * At least one of the ACE entries wasn't inherit only.
- * Flag this so we know the returned mode is valid.
- */
-
- all_aces_are_inherit_only = False;
- }
-
- /*
- * Windows 2000 sets these flags even on *file* ACE's. This is wrong
- * but we can ignore them for now. Revisit this when we go to POSIX
- * ACLs on directories.
- */
-
- psa->flags &= ~(SEC_ACE_FLAG_OBJECT_INHERIT|SEC_ACE_FLAG_CONTAINER_INHERIT);
-
- if(psa->flags != 0) {
- DEBUG(1,("unpack_nt_permissions: unable to set ACE flags (%x).\n",
- (unsigned int)psa->flags));
- return False;
- }
-
- /*
- * The security mask may be UNIX_ACCESS_NONE which should map into
- * no permissions (we overload the WRITE_OWNER bit for this) or it
- * should be one of the ALL/EXECUTE/READ/WRITE bits. Arrange for this
- * to be so. Any other bits override the UNIX_ACCESS_NONE bit.
- */
-
- psa->info.mask &= (GENERIC_ALL_ACCESS|GENERIC_EXECUTE_ACCESS|GENERIC_WRITE_ACCESS|
- GENERIC_READ_ACCESS|UNIX_ACCESS_NONE|FILE_ALL_ATTRIBUTES);
-
- if(psa->info.mask != UNIX_ACCESS_NONE)
- psa->info.mask &= ~UNIX_ACCESS_NONE;
-
- sid_copy(&ace_sid, &psa->sid);
-
- if(sid_equal(&ace_sid, &file_owner_sid)) {
- /*
- * Map the desired permissions into owner perms.
- */
-
- if(psa->type == SEC_ACE_TYPE_ACCESS_ALLOWED)
- *pmode |= map_nt_perms( psa->info, S_IRUSR);
- else
- *pmode &= ~(map_nt_perms( psa->info, S_IRUSR));
-
- } else if( sid_equal(&ace_sid, &file_grp_sid)) {
- /*
- * Map the desired permissions into group perms.
- */
-
- if(psa->type == SEC_ACE_TYPE_ACCESS_ALLOWED)
- *pmode |= map_nt_perms( psa->info, S_IRGRP);
- else
- *pmode &= ~(map_nt_perms( psa->info, S_IRGRP));
-
- } else if( sid_equal(&ace_sid, &global_sid_World)) {
- /*
- * Map the desired permissions into other perms.
- */
-
- if(psa->type == SEC_ACE_TYPE_ACCESS_ALLOWED)
- *pmode |= map_nt_perms( psa->info, S_IROTH);
- else
- *pmode &= ~(map_nt_perms( psa->info, S_IROTH));
-
- } else {
- DEBUG(0,("unpack_nt_permissions: unknown SID used in ACL.\n"));
- return False;
- }
- }
-
- if (is_directory && all_aces_are_inherit_only) {
- /*
- * Windows 2000 is doing one of these weird 'inherit acl'
- * traverses to conserve NTFS ACL resources. Just pretend
- * there was no DACL sent. JRA.
- */
-
- DEBUG(10,("unpack_nt_permissions: Win2k inherit acl traverse. Ignoring DACL.\n"));
- free_sec_acl(&psd->dacl);
- }
-
- return True;