diff options
Diffstat (limited to 'source3/lib/util_unixsd.c')
-rw-r--r-- | source3/lib/util_unixsd.c | 679 |
1 files changed, 0 insertions, 679 deletions
diff --git a/source3/lib/util_unixsd.c b/source3/lib/util_unixsd.c deleted file mode 100644 index bee9f69641..0000000000 --- a/source3/lib/util_unixsd.c +++ /dev/null @@ -1,679 +0,0 @@ -/* - Unix SMB/Netbios implementation. - Version 1.9. - SMB NT Security Descriptor / Unix permission conversion. - Copyright (C) Jeremy Allison 1994-2000 - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -*/ - -#include "includes.h" -#include "rpc_parse.h" -#include "sids.h" - -#ifndef WITH_SURS -extern DOM_SID global_sid_World; -#define global_sid_everyone &global_sid_World -#endif - - -/**************************************************************************** - Map unix perms to NT. -****************************************************************************/ - -static SEC_ACCESS map_unix_perms(int *pacl_type, mode_t perm, int r_mask, - int w_mask, int x_mask, BOOL is_directory) -{ - SEC_ACCESS sa; - uint32 nt_mask = 0; - - *pacl_type = SEC_ACE_TYPE_ACCESS_ALLOWED; - - if ((perm & (r_mask | w_mask | x_mask)) == (r_mask | w_mask | x_mask)) - { - nt_mask = UNIX_ACCESS_RWX; - } - else if ((perm & (r_mask | w_mask | x_mask)) == 0) - { - nt_mask = UNIX_ACCESS_NONE; - } - else - { - nt_mask |= (perm & r_mask) ? UNIX_ACCESS_R : 0; - if (is_directory) - nt_mask |= (perm & w_mask) ? UNIX_ACCESS_W : 0; - else - nt_mask |= (perm & w_mask) ? UNIX_ACCESS_W : 0; - nt_mask |= (perm & x_mask) ? UNIX_ACCESS_X : 0; - } - make_sec_access(&sa, nt_mask); - return sa; -} - -/**************************************************************************** - Function to create owner and group SIDs from a SMB_STRUCT_STAT. -****************************************************************************/ - -static BOOL create_file_sids(const SMB_STRUCT_STAT * psbuf, - DOM_SID *powner_sid, DOM_SID *pgroup_sid) -{ - extern DOM_SID global_sam_sid; - - sid_copy(powner_sid, &global_sam_sid); - sid_copy(pgroup_sid, &global_sam_sid); - sid_append_rid(powner_sid, pdb_uid_to_user_rid(psbuf->st_uid)); - sid_append_rid(pgroup_sid, pdb_gid_to_group_rid(psbuf->st_gid)); - return True; -} - -#ifdef WITH_SURS -static BOOL create_file_sids(const SMB_STRUCT_STAT * psbuf, - DOM_SID *powner_sid, DOM_SID *pgroup_sid) -{ - SURS_POSIX_ID id; - - ZERO_STRUCTP(powner_sid); - ZERO_STRUCTP(pgroup_sid); - DEBUG(0, ("TODO: create_file_sids: not ok " - "to assume gid is NT group\n")); - - id.type = SURS_POSIX_UID; - id.id = (uint32)psbuf->st_uid; - - if (!surs_unixid_to_sam_sid(&id, powner_sid, False)) - { - DEBUG(3, ("create_file_sids: map uid %d failed\n", - (int)psbuf->st_uid)); - return False; - } - - id.type = SURS_POSIX_GID; - id.id = (uint32)psbuf->st_gid; - - if (!surs_unixid_to_sam_sid(&id, pgroup_sid, False)) - { - DEBUG(3, ("create_file_sids: map gid %d failed\n", - (int)psbuf->st_gid)); - return False; - } - return True; -} -#endif - -/**************************************************************************** - Reply to query a security descriptor from an fsp. If it succeeds it allocates - the space for the return elements and returns True. -****************************************************************************/ - -size_t convertperms_unix_to_sd(const SMB_STRUCT_STAT * sbuf, - BOOL is_directory, mode_t mode, - SEC_DESC ** ppdesc) -{ - SEC_ACE *ace_list = NULL; - DOM_SID owner_sid; - DOM_SID group_sid; - size_t sec_desc_size; - SEC_ACL *psa = NULL; - SEC_ACCESS owner_access; - int owner_acl_type; - SEC_ACCESS group_access; - int grp_acl_type; - SEC_ACCESS other_access; - int other_acl_type; - int num_acls = 0; - - (*ppdesc) = NULL; - - if (!lp_nt_acl_support() || sbuf == NULL) - { - sid_copy(&owner_sid, global_sid_everyone); - sid_copy(&group_sid, global_sid_everyone); - } - else - { - if (!create_file_sids(sbuf, &owner_sid, &group_sid)) - { - DEBUG(3, ("create_file_sids: uid or gid " - "not mapped to SIDS\n")); - return 0; - } - - /* - * Create the generic 3 element UNIX acl. - */ - - owner_access = map_unix_perms(&owner_acl_type, sbuf->st_mode, - S_IRUSR, S_IWUSR, S_IXUSR, - is_directory); - group_access = map_unix_perms(&grp_acl_type, sbuf->st_mode, - S_IRGRP, S_IWGRP, S_IXGRP, - is_directory); - other_access = map_unix_perms(&other_acl_type, sbuf->st_mode, - S_IROTH, S_IWOTH, S_IXOTH, - is_directory); - - if (owner_access.mask) - { - ace_list = g_renew(SEC_ACE, ace_list, num_acls + 1); - if (ace_list == NULL) - { - return 0; - } - make_sec_ace(&ace_list[num_acls++], &owner_sid, - owner_acl_type, owner_access, 0); - } - - if (group_access.mask) - { - ace_list = g_renew(SEC_ACE, ace_list, num_acls + 1); - if (ace_list == NULL) - { - return 0; - } - - make_sec_ace(&ace_list[num_acls++], &group_sid, - grp_acl_type, group_access, 0); - } - - if (other_access.mask) - { - ace_list = g_renew(SEC_ACE, ace_list, num_acls + 1); - if (ace_list == NULL) - { - return 0; - } - - make_sec_ace(&ace_list[num_acls++], - global_sid_everyone, other_acl_type, - other_access, 0); - } - - if (is_directory) - { - /* - * For directory ACLs we also add in the - * inherited permissions ACE entries. These - * are the permissions a file would get when - * being created in the directory. - */ - - owner_access = map_unix_perms(&owner_acl_type, mode, - S_IRUSR, S_IWUSR, - S_IXUSR, is_directory); - group_access = map_unix_perms(&grp_acl_type, - mode, S_IRGRP, - S_IWGRP, S_IXGRP, - is_directory); - other_access = map_unix_perms(&other_acl_type, - mode, S_IROTH, - S_IWOTH, S_IXOTH, - is_directory); - - if (owner_access.mask) - { - ace_list = g_renew(SEC_ACE, ace_list, - num_acls + 1); - if (ace_list == NULL) - { - return 0; - } - - make_sec_ace(&ace_list[num_acls++], - &owner_sid, owner_acl_type, - owner_access, - SEC_ACE_FLAG_OBJECT_INHERIT | - SEC_ACE_FLAG_INHERIT_ONLY); - } - - if (group_access.mask) - { - ace_list = g_renew(SEC_ACE, ace_list, - num_acls + 1); - if (ace_list == NULL) - { - return 0; - } - - make_sec_ace(&ace_list[num_acls++], - &group_sid, grp_acl_type, - group_access, - SEC_ACE_FLAG_OBJECT_INHERIT | - SEC_ACE_FLAG_INHERIT_ONLY); - } - - if (other_access.mask) - { - ace_list = g_renew(SEC_ACE, ace_list, - num_acls + 1); - if (ace_list == NULL) - { - return 0; - } - - make_sec_ace(&ace_list[num_acls++], - global_sid_everyone, - other_acl_type, other_access, - SEC_ACE_FLAG_OBJECT_INHERIT | - SEC_ACE_FLAG_INHERIT_ONLY); - } - } - - if (num_acls) - { - psa = g_new(SEC_ACL, 1); - if (psa == NULL) - { - safe_free(ace_list); - } - if (!make_sec_acl(psa, 2, num_acls, ace_list)) - { - DEBUG(0, ("get_nt_acl: Unable to malloc " - "space for acl.\n")); - safe_free(ace_list); - safe_free(psa); - return 0; - } - } - } - - (*ppdesc) = g_new(SEC_DESC, 1); - - if ((*ppdesc) == NULL) - { - DEBUG(0, ("get_nt_acl: Unable to malloc space " - "for security descriptor.\n")); - sec_desc_size = 0; - free_sec_acl(psa); - safe_free(psa); - return 0; - } - - sec_desc_size = make_sec_desc((*ppdesc), 1, - SEC_DESC_SELF_RELATIVE | - (sbuf?SEC_DESC_DACL_PRESENT:0), - sid_dup(&owner_sid), - sid_dup(&group_sid), NULL, psa); - - return sec_desc_size; -} - -/**************************************************************************** - Map NT perms to UNIX. -****************************************************************************/ - -#define FILE_SPECIFIC_READ_BITS \ - (FILE_READ_DATA|FILE_READ_EA|FILE_READ_ATTRIBUTES) -#define FILE_SPECIFIC_WRITE_BITS \ - (FILE_WRITE_DATA|FILE_APPEND_DATA|FILE_WRITE_EA|FILE_WRITE_ATTRIBUTES) -#define FILE_SPECIFIC_EXECUTE_BITS (FILE_EXECUTE) - -#define PRINT_SPECIFIC_READ_BITS (PRINTER_READ) -#define PRINT_SPECIFIC_WRITE_BITS (PRINTER_READ) -#define PRINT_SPECIFIC_EXECUTE_BITS (PRINTER_ALL_ACCESS) - -static mode_t map_nt_perms(SEC_ACCESS sec_access, int type) -{ - uint32 write_bits; - uint32 read_bits; - uint32 execute_bits; - mode_t mode = 0; - - write_bits = FILE_SPECIFIC_WRITE_BITS; - read_bits = FILE_SPECIFIC_READ_BITS; - execute_bits = FILE_SPECIFIC_EXECUTE_BITS; - - switch (type) - { - case S_IRUSR: - if (sec_access.mask & GENERIC_ALL_ACCESS) - mode = S_IRUSR | S_IWUSR | S_IXUSR; - else - { - mode |= - (sec_access.mask & - (GENERIC_READ_ACCESS | - read_bits)) ? S_IRUSR : 0; - mode |= - (sec_access.mask & - (GENERIC_WRITE_ACCESS | - write_bits)) ? S_IWUSR : 0; - mode |= - (sec_access.mask & - (GENERIC_EXECUTE_ACCESS | - execute_bits)) ? S_IXUSR : 0; - } - break; - case S_IRGRP: - if (sec_access.mask & GENERIC_ALL_ACCESS) - mode = S_IRGRP | S_IWGRP | S_IXGRP; - else - { - mode |= - (sec_access.mask & - (GENERIC_READ_ACCESS | - read_bits)) ? S_IRGRP : 0; - mode |= - (sec_access.mask & - (GENERIC_WRITE_ACCESS | - write_bits)) ? S_IWGRP : 0; - mode |= - (sec_access.mask & - (GENERIC_EXECUTE_ACCESS | - execute_bits)) ? S_IXGRP : 0; - } - break; - case S_IROTH: - if (sec_access.mask & GENERIC_ALL_ACCESS) - mode = S_IROTH | S_IWOTH | S_IXOTH; - else - { - mode |= - (sec_access.mask & - (GENERIC_READ_ACCESS | - read_bits)) ? S_IROTH : 0; - mode |= - (sec_access.mask & - (GENERIC_WRITE_ACCESS | - write_bits)) ? S_IWOTH : 0; - mode |= - (sec_access.mask & - (GENERIC_EXECUTE_ACCESS | - execute_bits)) ? S_IXOTH : 0; - } - break; - } - - return mode; -} - -#ifndef WITH_SURS -/**************************************************************************** - Validate a SID. -****************************************************************************/ -static BOOL validate_unix_sid(DOM_SID *psid, uint32 *prid, DOM_SID *sd_sid) -{ - extern DOM_SID global_sam_sid; - DOM_SID sid; - - if (!sd_sid) - { - DEBUG(5, ("validate_unix_sid: sid missing.\n")); - return False; - } - - sid_copy(psid, sd_sid); - sid_copy(&sid, sd_sid); - - if (!sid_split_rid(&sid, prid)) - { - DEBUG(5, ("validate_unix_sid: cannot get RID from sid.\n")); - return False; - } - - if (!sid_equal(&sid, &global_sam_sid)) - { - DEBUG(5, ("validate_unix_sid: sid is not ours.\n")); - return False; - } - - return True; -} -#endif - -/**************************************************************************** - Unpack a SEC_DESC into a owner, group and set of UNIX permissions. -****************************************************************************/ - -BOOL convertperms_sd_to_unix(SMB_STRUCT_STAT * psbuf, uid_t * puser, - gid_t * pgrp, mode_t * pmode, - uint32 security_info_sent, SEC_DESC * psd, - BOOL is_directory) -{ - DOM_SID file_owner_sid; - DOM_SID file_grp_sid; - SEC_ACL *dacl = psd->dacl; - BOOL all_aces_are_inherit_only = (is_directory ? True : False); - int i; -#ifdef WITH_SURS - SURS_POSIX_ID id; -#else - DOM_SID owner_sid; - DOM_SID grp_sid; - uint32 owner_rid; - uint32 grp_rid; -#endif - - *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. - */ - - if (!create_file_sids(psbuf, &file_owner_sid, &file_grp_sid)) - { - DEBUG(3, ("create_file_sids: uid or gid " - "not mapped to SIDS\n")); - return 0; - } - - /* - * Don't immediately fail if the owner sid cannot be validated. - * This may be a group chown only set. - */ - - DEBUG(0, ("TODO: LsaLookupSids to find type of owner_sid\n")); - -#ifdef WITH_SURS - if (security_info_sent & OWNER_SECURITY_INFORMATION && - surs_sam_sid_to_unixid(psd->owner_sid, &id, False) && - id.type == SURS_POSIX_UID) - { - *puser = (uid_t) id.id; - } - -#else - 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); - - if (security_info_sent & OWNER_SECURITY_INFORMATION) - { - *puser = pdb_user_rid_to_uid(owner_rid); - } - -#endif - /* - * Don't immediately fail if the group sid cannot be validated. - * This may be an owner chown only set. - */ - -#ifdef WITH_SURS - if (security_info_sent & GROUP_SECURITY_INFORMATION && - surs_sam_sid_to_unixid(psd->grp_sid, &id, False) && - (id.type == SURS_POSIX_GID)) - { - *pgrp = (gid_t) id.id; - } -#else - 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); - -#endif - /* - * 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_everyone)) - { - /* - * 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); - safe_free(psd->dacl); - psd->dacl = NULL; - } - - return True; -} |