Line data Source code
1 : /* 2 : Unix SMB/CIFS implementation. 3 : Check access to files based on security descriptors. 4 : Copyright (C) Jeremy Allison 2005-2006. 5 : Copyright (C) Michael Adam 2007. 6 : 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. 11 : 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. 16 : 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/>. 19 : */ 20 : 21 : #include "includes.h" 22 : #include "system/filesys.h" 23 : #include "../libcli/security/security.h" 24 : #include "../librpc/gen_ndr/ndr_security.h" 25 : #include "smbd/smbd.h" 26 : 27 : #undef DBGC_CLASS 28 : #define DBGC_CLASS DBGC_ACLS 29 : 30 : /**************************************************************************** 31 : Actually emulate the in-kernel access checking for delete access. We need 32 : this to successfully return ACCESS_DENIED on a file open for delete access. 33 : ****************************************************************************/ 34 : 35 1556 : bool can_delete_file_in_directory(connection_struct *conn, 36 : struct files_struct *dirfsp, 37 : const struct smb_filename *smb_fname) 38 : { 39 1556 : struct smb_filename *smb_fname_parent = NULL; 40 4 : bool ret; 41 4 : NTSTATUS status; 42 : 43 1556 : if (!CAN_WRITE(conn)) { 44 0 : return False; 45 : } 46 : 47 1556 : if (!lp_acl_check_permissions(SNUM(conn))) { 48 : /* This option means don't check. */ 49 0 : return true; 50 : } 51 : 52 1556 : if (get_current_uid(conn) == (uid_t)0) { 53 : /* I'm sorry sir, I didn't know you were root... */ 54 0 : return true; 55 : } 56 : 57 1556 : if (dirfsp != conn->cwd_fsp) { 58 1540 : smb_fname_parent = dirfsp->fsp_name; 59 : } else { 60 16 : struct smb_filename *atname = NULL; 61 : /* 62 : * Get a pathref on the parent. 63 : */ 64 16 : status = parent_pathref(talloc_tos(), 65 : conn->cwd_fsp, 66 : smb_fname, 67 : &smb_fname_parent, 68 : &atname); 69 16 : if (!NT_STATUS_IS_OK(status)) { 70 0 : return false; 71 : } 72 : } 73 : 74 1556 : SMB_ASSERT(VALID_STAT(smb_fname_parent->st)); 75 : 76 : /* fast paths first */ 77 : 78 1556 : if (!S_ISDIR(smb_fname_parent->st.st_ex_mode)) { 79 0 : ret = false; 80 0 : goto out; 81 : } 82 : 83 : #ifdef S_ISVTX 84 : /* sticky bit means delete only by owner of file or by root or 85 : * by owner of directory. */ 86 1556 : if (smb_fname_parent->st.st_ex_mode & S_ISVTX) { 87 0 : if (!VALID_STAT(smb_fname->st)) { 88 : /* If the file doesn't already exist then 89 : * yes we'll be able to delete it. */ 90 0 : ret = true; 91 0 : goto out; 92 : } 93 : 94 : /* 95 : * Patch from SATOH Fumiyasu <fumiyas@miraclelinux.com> 96 : * for bug #3348. Don't assume owning sticky bit 97 : * directory means write access allowed. 98 : * Fail to delete if we're not the owner of the file, 99 : * or the owner of the directory as we have no possible 100 : * chance of deleting. Otherwise, go on and check the ACL. 101 : */ 102 0 : if ((get_current_uid(conn) != 103 0 : smb_fname_parent->st.st_ex_uid) && 104 0 : (get_current_uid(conn) != smb_fname->st.st_ex_uid)) { 105 0 : DEBUG(10,("can_delete_file_in_directory: not " 106 : "owner of file %s or directory %s\n", 107 : smb_fname_str_dbg(smb_fname), 108 : smb_fname_str_dbg(smb_fname_parent))); 109 0 : ret = false; 110 0 : goto out; 111 : } 112 : } 113 : #endif 114 : 115 : /* now for ACL checks */ 116 : 117 : /* 118 : * There's two ways to get the permission to delete a file: First by 119 : * having the DELETE bit on the file itself and second if that does 120 : * not help, by the DELETE_CHILD bit on the containing directory. 121 : * 122 : * Here we only check the directory permissions, we will 123 : * check the file DELETE permission separately. 124 : */ 125 : 126 1556 : ret = NT_STATUS_IS_OK(smbd_check_access_rights_fsp( 127 : conn->cwd_fsp, 128 : smb_fname_parent->fsp, 129 : false, 130 : FILE_DELETE_CHILD)); 131 1556 : out: 132 1556 : if (smb_fname_parent != dirfsp->fsp_name) { 133 16 : TALLOC_FREE(smb_fname_parent); 134 : } 135 1552 : return ret; 136 : } 137 : 138 : /**************************************************************************** 139 : Userspace check for write access to fsp. 140 : ****************************************************************************/ 141 : 142 1251 : bool can_write_to_fsp(struct files_struct *fsp) 143 : { 144 1251 : return NT_STATUS_IS_OK(smbd_check_access_rights_fsp( 145 : fsp->conn->cwd_fsp, 146 : fsp, 147 : false, 148 : FILE_WRITE_DATA)); 149 : } 150 : 151 : /**************************************************************************** 152 : Check for an existing default Windows ACL on a directory fsp. 153 : ****************************************************************************/ 154 : 155 160309 : bool directory_has_default_acl_fsp(struct files_struct *fsp) 156 : { 157 160309 : struct security_descriptor *secdesc = NULL; 158 416 : unsigned int i; 159 416 : NTSTATUS status; 160 : 161 160309 : status = SMB_VFS_FGET_NT_ACL(metadata_fsp(fsp), 162 : SECINFO_DACL, 163 : talloc_tos(), 164 : &secdesc); 165 : 166 160309 : if (!NT_STATUS_IS_OK(status) || 167 160309 : secdesc == NULL || 168 160309 : secdesc->dacl == NULL) 169 : { 170 0 : TALLOC_FREE(secdesc); 171 0 : return false; 172 : } 173 : 174 351061 : for (i = 0; i < secdesc->dacl->num_aces; i++) { 175 350003 : struct security_ace *psa = &secdesc->dacl->aces[i]; 176 : 177 350003 : if (psa->flags & (SEC_ACE_FLAG_OBJECT_INHERIT| 178 : SEC_ACE_FLAG_CONTAINER_INHERIT)) 179 : { 180 159251 : TALLOC_FREE(secdesc); 181 159251 : return true; 182 : } 183 : } 184 1058 : TALLOC_FREE(secdesc); 185 1058 : return false; 186 : } 187 : 188 : /**************************************************************************** 189 : Check if setting delete on close is allowed on this fsp. 190 : ****************************************************************************/ 191 : 192 170588 : NTSTATUS can_set_delete_on_close(files_struct *fsp, uint32_t dosmode) 193 : { 194 : /* 195 : * Only allow delete on close for writable files. 196 : */ 197 : 198 170590 : if ((dosmode & FILE_ATTRIBUTE_READONLY) && 199 58 : !lp_delete_readonly(SNUM(fsp->conn))) { 200 50 : DEBUG(10,("can_set_delete_on_close: file %s delete on close " 201 : "flag set but file attribute is readonly.\n", 202 : fsp_str_dbg(fsp))); 203 50 : return NT_STATUS_CANNOT_DELETE; 204 : } 205 : 206 : /* 207 : * Only allow delete on close for writable shares. 208 : */ 209 : 210 170538 : if (!CAN_WRITE(fsp->conn)) { 211 0 : DEBUG(10,("can_set_delete_on_close: file %s delete on " 212 : "close flag set but write access denied on share.\n", 213 : fsp_str_dbg(fsp))); 214 0 : return NT_STATUS_ACCESS_DENIED; 215 : } 216 : 217 : /* 218 : * Only allow delete on close for files/directories opened with delete 219 : * intent. 220 : */ 221 : 222 170538 : if (!(fsp->access_mask & DELETE_ACCESS)) { 223 18 : DEBUG(10,("can_set_delete_on_close: file %s delete on " 224 : "close flag set but delete access denied.\n", 225 : fsp_str_dbg(fsp))); 226 18 : return NT_STATUS_ACCESS_DENIED; 227 : } 228 : 229 : /* Don't allow delete on close for non-empty directories. */ 230 170520 : if (fsp->fsp_flags.is_directory) { 231 11290 : SMB_ASSERT(!fsp_is_alternate_stream(fsp)); 232 : 233 : /* Or the root of a share. */ 234 11290 : if (ISDOT(fsp->fsp_name->base_name)) { 235 42 : DEBUG(10,("can_set_delete_on_close: can't set delete on " 236 : "close for the root of a share.\n")); 237 42 : return NT_STATUS_ACCESS_DENIED; 238 : } 239 : 240 11248 : return can_delete_directory_fsp(fsp); 241 : } 242 : 243 159230 : return NT_STATUS_OK; 244 : }