posix_acls.c
来自「samba-3.0.22.tar.gz 编译smb服务器的源码」· C语言 代码 · 共 2,170 行 · 第 1/5 页
C
2,170 行
mode |= (sec_access.mask & (GENERIC_EXECUTE_ACCESS|FILE_SPECIFIC_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|FILE_SPECIFIC_READ_BITS)) ? S_IRGRP : 0; mode |= (sec_access.mask & (GENERIC_WRITE_ACCESS|FILE_SPECIFIC_WRITE_BITS)) ? S_IWGRP : 0; mode |= (sec_access.mask & (GENERIC_EXECUTE_ACCESS|FILE_SPECIFIC_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|FILE_SPECIFIC_READ_BITS)) ? S_IROTH : 0; mode |= (sec_access.mask & (GENERIC_WRITE_ACCESS|FILE_SPECIFIC_WRITE_BITS)) ? S_IWOTH : 0; mode |= (sec_access.mask & (GENERIC_EXECUTE_ACCESS|FILE_SPECIFIC_EXECUTE_BITS)) ? S_IXOTH : 0; } break; } return mode;}/**************************************************************************** Unpack a SEC_DESC into a UNIX owner and group.****************************************************************************/static BOOL unpack_nt_owners(int snum, SMB_STRUCT_STAT *psbuf, uid_t *puser, gid_t *pgrp, uint32 security_info_sent, SEC_DESC *psd){ DOM_SID owner_sid; DOM_SID grp_sid; *puser = (uid_t)-1; *pgrp = (gid_t)-1; if(security_info_sent == 0) { DEBUG(0,("unpack_nt_owners: no security info sent !\n")); return True; } /* * 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_owners: validating owner_sids.\n")); /* * Don't immediately fail if the owner sid cannot be validated. * This may be a group chown only set. */ if (security_info_sent & OWNER_SECURITY_INFORMATION) { sid_copy(&owner_sid, psd->owner_sid); if (!NT_STATUS_IS_OK(sid_to_uid(&owner_sid, puser))) { if (lp_force_unknown_acl_user(snum)) { /* this allows take ownership to work * reasonably */ *puser = current_user.uid; } else { DEBUG(3,("unpack_nt_owners: unable to validate" " owner sid for %s\n", sid_string_static(&owner_sid))); return False; } } } /* * Don't immediately fail if the group sid cannot be validated. * This may be an owner chown only set. */ if (security_info_sent & GROUP_SECURITY_INFORMATION) { sid_copy(&grp_sid, psd->grp_sid); if (!NT_STATUS_IS_OK(sid_to_gid( &grp_sid, pgrp))) { if (lp_force_unknown_acl_user(snum)) { /* this allows take group ownership to work * reasonably */ *pgrp = current_user.gid; } else { DEBUG(3,("unpack_nt_owners: unable to validate" " group sid.\n")); return False; } } } DEBUG(5,("unpack_nt_owners: owner_sids validated.\n")); return True;}/**************************************************************************** Ensure the enforced permissions for this share apply.****************************************************************************/static void apply_default_perms(files_struct *fsp, canon_ace *pace, mode_t type){ int snum = SNUM(fsp->conn); mode_t and_bits = (mode_t)0; mode_t or_bits = (mode_t)0; /* Get the initial bits to apply. */ if (fsp->is_directory) { and_bits = lp_dir_security_mask(snum); or_bits = lp_force_dir_security_mode(snum); } else { and_bits = lp_security_mask(snum); or_bits = lp_force_security_mode(snum); } /* Now bounce them into the S_USR space. */ switch(type) { case S_IRUSR: /* Ensure owner has read access. */ pace->perms |= S_IRUSR; if (fsp->is_directory) pace->perms |= (S_IWUSR|S_IXUSR); and_bits = unix_perms_to_acl_perms(and_bits, S_IRUSR, S_IWUSR, S_IXUSR); or_bits = unix_perms_to_acl_perms(or_bits, S_IRUSR, S_IWUSR, S_IXUSR); break; case S_IRGRP: and_bits = unix_perms_to_acl_perms(and_bits, S_IRGRP, S_IWGRP, S_IXGRP); or_bits = unix_perms_to_acl_perms(or_bits, S_IRGRP, S_IWGRP, S_IXGRP); break; case S_IROTH: and_bits = unix_perms_to_acl_perms(and_bits, S_IROTH, S_IWOTH, S_IXOTH); or_bits = unix_perms_to_acl_perms(or_bits, S_IROTH, S_IWOTH, S_IXOTH); break; } pace->perms = ((pace->perms & and_bits)|or_bits);}/**************************************************************************** Check if a given uid/SID is in a group gid/SID. This is probably very expensive and will need optimisation. A *lot* of optimisation :-). JRA.****************************************************************************/static BOOL uid_entry_in_group( canon_ace *uid_ace, canon_ace *group_ace ){ fstring u_name; fstring g_name; /* "Everyone" always matches every uid. */ if (sid_equal(&group_ace->trustee, &global_sid_World)) return True; /* Assume that the current user is in the current group (force group) */ if (uid_ace->unix_ug.uid == current_user.uid && group_ace->unix_ug.gid == current_user.gid) return True; fstrcpy(u_name, uidtoname(uid_ace->unix_ug.uid)); fstrcpy(g_name, gidtoname(group_ace->unix_ug.gid)); /* * Due to the winbind interfaces we need to do this via names, * not uids/gids. */ return user_in_group_list(u_name, g_name, NULL, 0);}/**************************************************************************** A well formed POSIX file or default ACL has at least 3 entries, a SMB_ACL_USER_OBJ, SMB_ACL_GROUP_OBJ, SMB_ACL_OTHER_OBJ. In addition, the owner must always have at least read access. When using this call on get_acl, the pst struct is valid and contains the mode of the file. When using this call on set_acl, the pst struct has been modified to have a mode containing the default for this file or directory type.****************************************************************************/static BOOL ensure_canon_entry_valid(canon_ace **pp_ace, files_struct *fsp, const DOM_SID *pfile_owner_sid, const DOM_SID *pfile_grp_sid, SMB_STRUCT_STAT *pst, BOOL setting_acl){ canon_ace *pace; BOOL got_user = False; BOOL got_grp = False; BOOL got_other = False; canon_ace *pace_other = NULL; for (pace = *pp_ace; pace; pace = pace->next) { if (pace->type == SMB_ACL_USER_OBJ) { if (setting_acl) apply_default_perms(fsp, pace, S_IRUSR); got_user = True; } else if (pace->type == SMB_ACL_GROUP_OBJ) { /* * Ensure create mask/force create mode is respected on set. */ if (setting_acl) apply_default_perms(fsp, pace, S_IRGRP); got_grp = True; } else if (pace->type == SMB_ACL_OTHER) { /* * Ensure create mask/force create mode is respected on set. */ if (setting_acl) apply_default_perms(fsp, pace, S_IROTH); got_other = True; pace_other = pace; } } if (!got_user) { if ((pace = SMB_MALLOC_P(canon_ace)) == NULL) { DEBUG(0,("ensure_canon_entry_valid: malloc fail.\n")); return False; } ZERO_STRUCTP(pace); pace->type = SMB_ACL_USER_OBJ; pace->owner_type = UID_ACE; pace->unix_ug.uid = pst->st_uid; pace->trustee = *pfile_owner_sid; pace->attr = ALLOW_ACE; if (setting_acl) { /* See if the owning user is in any of the other groups in the ACE. If so, OR in the permissions from that group. */ BOOL group_matched = False; canon_ace *pace_iter; for (pace_iter = *pp_ace; pace_iter; pace_iter = pace_iter->next) { if (pace_iter->type == SMB_ACL_GROUP_OBJ || pace_iter->type == SMB_ACL_GROUP) { if (uid_entry_in_group(pace, pace_iter)) { pace->perms |= pace_iter->perms; group_matched = True; } } } /* If we only got an "everyone" perm, just use that. */ if (!group_matched) { if (got_other) pace->perms = pace_other->perms; else pace->perms = 0; } apply_default_perms(fsp, pace, S_IRUSR); } else { pace->perms = unix_perms_to_acl_perms(pst->st_mode, S_IRUSR, S_IWUSR, S_IXUSR); } DLIST_ADD(*pp_ace, pace); } if (!got_grp) { if ((pace = SMB_MALLOC_P(canon_ace)) == NULL) { DEBUG(0,("ensure_canon_entry_valid: malloc fail.\n")); return False; } ZERO_STRUCTP(pace); pace->type = SMB_ACL_GROUP_OBJ; pace->owner_type = GID_ACE; pace->unix_ug.uid = pst->st_gid; pace->trustee = *pfile_grp_sid; pace->attr = ALLOW_ACE; if (setting_acl) { /* If we only got an "everyone" perm, just use that. */ if (got_other) pace->perms = pace_other->perms; else pace->perms = 0; apply_default_perms(fsp, pace, S_IRGRP); } else { pace->perms = unix_perms_to_acl_perms(pst->st_mode, S_IRGRP, S_IWGRP, S_IXGRP); } DLIST_ADD(*pp_ace, pace); } if (!got_other) { if ((pace = SMB_MALLOC_P(canon_ace)) == NULL) { DEBUG(0,("ensure_canon_entry_valid: malloc fail.\n")); return False; } ZERO_STRUCTP(pace); pace->type = SMB_ACL_OTHER; pace->owner_type = WORLD_ACE; pace->unix_ug.world = -1; pace->trustee = global_sid_World; pace->attr = ALLOW_ACE; if (setting_acl) { pace->perms = 0; apply_default_perms(fsp, pace, S_IROTH); } else pace->perms = unix_perms_to_acl_perms(pst->st_mode, S_IROTH, S_IWOTH, S_IXOTH); DLIST_ADD(*pp_ace, pace); } return True;}/**************************************************************************** Check if a POSIX ACL has the required SMB_ACL_USER_OBJ and SMB_ACL_GROUP_OBJ entries. If it does not have them, check if there are any entries where the trustee is the file owner or the owning group, and map these to SMB_ACL_USER_OBJ and SMB_ACL_GROUP_OBJ.****************************************************************************/static void check_owning_objs(canon_ace *ace, DOM_SID *pfile_owner_sid, DOM_SID *pfile_grp_sid){ BOOL got_user_obj, got_group_obj; canon_ace *current_ace; int i, entries; entries = count_canon_ace_list(ace); got_user_obj = False; got_group_obj = False; for (i=0, current_ace = ace; i < entries; i++, current_ace = current_ace->next) { if (current_ace->type == SMB_ACL_USER_OBJ) got_user_obj = True; else if (current_ace->type == SMB_ACL_GROUP_OBJ) got_group_obj = True; } if (got_user_obj && got_group_obj) { DEBUG(10,("check_owning_objs: ACL had owning user/group entries.\n")); return; } for (i=0, current_ace = ace; i < entries; i++, current_ace = current_ace->next) { if (!got_user_obj && current_ace->owner_type == UID_ACE && sid_equal(¤t_ace->trustee, pfile_owner_sid)) { current_ace->type = SMB_ACL_USER_OBJ; got_user_obj = True; } if (!got_group_obj && current_ace->owner_type == GID_ACE && sid_equal(¤t_ace->trustee, pfile_grp_sid)) { current_ace->type = SMB_ACL_GROUP_OBJ; got_group_obj = True; } } if (!got_user_obj) DEBUG(10,("check_owning_objs: ACL is missing an owner entry.\n")); if (!got_group_obj) DEBUG(10,("check_owning_objs: ACL is missing an owning group entry.\n"));}/**************************************************************************** Unpack a SEC_DESC into two canonical ace lists.****************************************************************************/static BOOL create_canon_ace_lists(files_struct *fsp, SMB_STRUCT_STAT *pst, DOM_SID *pfile_owner_sid, DOM_SID *pfile_grp_sid, canon_ace **ppfile_ace, canon_ace **ppdir_ace, SEC_ACL *dacl){ BOOL all_aces_are_inherit_only = (fsp->is_directory ? True : False); canon_ace *file_ace = NULL; canon_ace *dir_ace = NULL; canon_ace *tmp_ace = NULL; canon_ace *current_ace = NULL; BOOL got_dir_allow = False; BOOL got_file_allow = False; int i, j; *ppfile_ace = NULL; *ppdir_ace = NULL; /* * Convert the incoming ACL into a more regular form. */ for(i = 0; i < dacl->num_aces; i++) { SEC_ACE *psa = &dacl->ace[i]; if((psa->type != SEC_ACE_TYPE_ACCESS_ALLOWED) && (psa->type != SEC_ACE_TYPE_ACCESS_DENIED)) { DEBUG(3,("create_canon_ace_lists: unable to set anything but an ALLOW or DENY ACE.\n")); return False; } if (nt4_compatible_acls()) { /* * 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. */ /* * Convert GENERIC bits to specific bits. */ se_map_generic(&psa->info.mask, &file_generic_mapping); psa->info.mask &= (UNIX_ACCESS_NONE|FILE_ALL_ACCESS); if(psa->info.mask != UNIX_ACCESS_NONE) psa->info.mask &= ~UNIX_ACCESS_NONE; } } /* * Deal with the fact that NT 4.x re-writes the canonical format * that we return for default ACLs. If a directory ACE is identical * to a inherited directory ACE then NT changes the bits so that the * first ACE is set to OI|IO and the second ACE for this SID is set * to CI. We need to repair this. JRA. */ for(i = 0; i < dacl->num_aces; i++) { SEC_ACE *psa1 = &dacl->ace[i]; for (j = i + 1; j < dacl->num_aces; j++) { SEC_ACE *psa2 = &dacl->ace[j];
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?