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