root/source3/smbd/file_access.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. can_access_file_acl
  2. can_delete_file_in_directory
  3. can_access_file_data
  4. can_write_to_file
  5. directory_has_default_acl

   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 
  23 #undef  DBGC_CLASS
  24 #define DBGC_CLASS DBGC_ACLS
  25 
  26 /**
  27  * Security descriptor / NT Token level access check function.
  28  */
  29 bool can_access_file_acl(struct connection_struct *conn,
     /* [<][>][^][v][top][bottom][index][help] */
  30                                 const char * fname,
  31                                 uint32_t access_mask)
  32 {
  33         NTSTATUS status;
  34         uint32_t access_granted;
  35         struct security_descriptor *secdesc = NULL;
  36 
  37         if (conn->server_info->utok.uid == 0 || conn->admin_user) {
  38                 /* I'm sorry sir, I didn't know you were root... */
  39                 return true;
  40         }
  41 
  42         status = SMB_VFS_GET_NT_ACL(conn, fname,
  43                                     (OWNER_SECURITY_INFORMATION |
  44                                      GROUP_SECURITY_INFORMATION |
  45                                      DACL_SECURITY_INFORMATION),
  46                                     &secdesc);
  47         if (!NT_STATUS_IS_OK(status)) {
  48                 DEBUG(5, ("Could not get acl: %s\n", nt_errstr(status)));
  49                 return false;
  50         }
  51 
  52         status = se_access_check(secdesc, conn->server_info->ptok,
  53                                  access_mask, &access_granted);
  54         TALLOC_FREE(secdesc);
  55         return NT_STATUS_IS_OK(status);
  56 }
  57 
  58 /****************************************************************************
  59  Actually emulate the in-kernel access checking for delete access. We need
  60  this to successfully return ACCESS_DENIED on a file open for delete access.
  61 ****************************************************************************/
  62 
  63 bool can_delete_file_in_directory(connection_struct *conn, const char *fname)
     /* [<][>][^][v][top][bottom][index][help] */
  64 {
  65         SMB_STRUCT_STAT sbuf;
  66         TALLOC_CTX *ctx = talloc_tos();
  67         char *dname = NULL;
  68 
  69         if (!CAN_WRITE(conn)) {
  70                 return False;
  71         }
  72 
  73         /* Get the parent directory permission mask and owners. */
  74         if (!parent_dirname(ctx, fname, &dname, NULL)) {
  75                 return False;
  76         }
  77         if(SMB_VFS_STAT(conn, dname, &sbuf) != 0) {
  78                 return False;
  79         }
  80 
  81         /* fast paths first */
  82 
  83         if (!S_ISDIR(sbuf.st_mode)) {
  84                 return False;
  85         }
  86         if (conn->server_info->utok.uid == 0 || conn->admin_user) {
  87                 /* I'm sorry sir, I didn't know you were root... */
  88                 return True;
  89         }
  90 
  91 #ifdef S_ISVTX
  92         /* sticky bit means delete only by owner of file or by root or
  93          * by owner of directory. */
  94         if (sbuf.st_mode & S_ISVTX) {
  95                 SMB_STRUCT_STAT sbuf_file;
  96                 if(SMB_VFS_STAT(conn, fname, &sbuf_file) != 0) {
  97                         if (errno == ENOENT) {
  98                                 /* If the file doesn't already exist then
  99                                  * yes we'll be able to delete it. */
 100                                 return True;
 101                         }
 102                         DEBUG(10,("can_delete_file_in_directory: can't "
 103                                 "stat file %s (%s)",
 104                                 fname, strerror(errno) ));
 105                         return False;
 106                 }
 107                 /*
 108                  * Patch from SATOH Fumiyasu <fumiyas@miraclelinux.com>
 109                  * for bug #3348. Don't assume owning sticky bit
 110                  * directory means write access allowed.
 111                  * Fail to delete if we're not the owner of the file,
 112                  * or the owner of the directory as we have no possible
 113                  * chance of deleting. Otherwise, go on and check the ACL.
 114                  */
 115                 if ((conn->server_info->utok.uid != sbuf.st_uid) &&
 116                                 (conn->server_info->utok.uid != sbuf_file.st_uid)) {
 117                         DEBUG(10,("can_delete_file_in_directory: not "
 118                                 "owner of file %s or directory %s",
 119                                 fname, dname));
 120                         return False;
 121                 }
 122         }
 123 #endif
 124 
 125         /* now for ACL checks */
 126 
 127         /*
 128          * There's two ways to get the permission to delete a file: First by
 129          * having the DELETE bit on the file itself and second if that does
 130          * not help, by the DELETE_CHILD bit on the containing directory.
 131          *
 132          * Here we only check the directory permissions, we will
 133          * check the file DELETE permission separately.
 134          */
 135 
 136         return can_access_file_acl(conn, dname, FILE_DELETE_CHILD);
 137 }
 138 
 139 /****************************************************************************
 140  Actually emulate the in-kernel access checking for read/write access. We need
 141  this to successfully check for ability to write for dos filetimes.
 142  Note this doesn't take into account share write permissions.
 143 ****************************************************************************/
 144 
 145 bool can_access_file_data(connection_struct *conn, const char *fname, SMB_STRUCT_STAT *psbuf, uint32 access_mask)
     /* [<][>][^][v][top][bottom][index][help] */
 146 {
 147         if (!(access_mask & (FILE_READ_DATA|FILE_WRITE_DATA))) {
 148                 return False;
 149         }
 150         access_mask &= (FILE_READ_DATA|FILE_WRITE_DATA);
 151 
 152         /* some fast paths first */
 153 
 154         DEBUG(10,("can_access_file_data: requesting 0x%x on file %s\n",
 155                 (unsigned int)access_mask, fname ));
 156 
 157         if (conn->server_info->utok.uid == 0 || conn->admin_user) {
 158                 /* I'm sorry sir, I didn't know you were root... */
 159                 return True;
 160         }
 161 
 162         if (!VALID_STAT(*psbuf)) {
 163                 /* Get the file permission mask and owners. */
 164                 if(SMB_VFS_STAT(conn, fname, psbuf) != 0) {
 165                         return False;
 166                 }
 167         }
 168 
 169         /* Check primary owner access. */
 170         if (conn->server_info->utok.uid == psbuf->st_uid) {
 171                 switch (access_mask) {
 172                         case FILE_READ_DATA:
 173                                 return (psbuf->st_mode & S_IRUSR) ? True : False;
 174 
 175                         case FILE_WRITE_DATA:
 176                                 return (psbuf->st_mode & S_IWUSR) ? True : False;
 177 
 178                         default: /* FILE_READ_DATA|FILE_WRITE_DATA */
 179 
 180                                 if ((psbuf->st_mode & (S_IWUSR|S_IRUSR)) == (S_IWUSR|S_IRUSR)) {
 181                                         return True;
 182                                 } else {
 183                                         return False;
 184                                 }
 185                 }
 186         }
 187 
 188         /* now for ACL checks */
 189 
 190         return can_access_file_acl(conn, fname, access_mask);
 191 }
 192 
 193 /****************************************************************************
 194  Userspace check for write access.
 195  Note this doesn't take into account share write permissions.
 196 ****************************************************************************/
 197 
 198 bool can_write_to_file(connection_struct *conn, const char *fname, SMB_STRUCT_STAT *psbuf)
     /* [<][>][^][v][top][bottom][index][help] */
 199 {
 200         return can_access_file_data(conn, fname, psbuf, FILE_WRITE_DATA);
 201 }
 202 
 203 /****************************************************************************
 204  Check for an existing default Windows ACL on a directory.
 205 ****************************************************************************/
 206 
 207 bool directory_has_default_acl(connection_struct *conn, const char *fname)
     /* [<][>][^][v][top][bottom][index][help] */
 208 {
 209         /* returns talloced off tos. */
 210         struct security_descriptor *secdesc = NULL;
 211         unsigned int i;
 212         NTSTATUS status = SMB_VFS_GET_NT_ACL(conn, fname,
 213                                 DACL_SECURITY_INFORMATION, &secdesc);
 214 
 215         if (!NT_STATUS_IS_OK(status) || secdesc == NULL) {
 216                 return false;
 217         }
 218 
 219         for (i = 0; i < secdesc->dacl->num_aces; i++) {
 220                 struct security_ace *psa = &secdesc->dacl->aces[i];
 221                 if (psa->flags & (SEC_ACE_FLAG_OBJECT_INHERIT|
 222                                 SEC_ACE_FLAG_CONTAINER_INHERIT)) {
 223                         TALLOC_FREE(secdesc);
 224                         return true;
 225                 }
 226         }
 227         TALLOC_FREE(secdesc);
 228         return false;
 229 }

/* [<][>][^][v][top][bottom][index][help] */