root/source3/modules/vfs_posixacl.c

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

DEFINITIONS

This source file includes following definitions.
  1. posixacl_sys_acl_get_file
  2. posixacl_sys_acl_get_fd
  3. posixacl_sys_acl_set_file
  4. posixacl_sys_acl_set_fd
  5. posixacl_sys_acl_delete_def_file
  6. smb_ace_to_internal
  7. smb_acl_to_internal
  8. smb_acl_set_mode
  9. smb_acl_to_posix
  10. vfs_posixacl_init

   1 /*
   2    Unix SMB/Netbios implementation.
   3    VFS module to get and set posix acls
   4    Copyright (C) Volker Lendecke 2006
   5 
   6    This program is free software; you can redistribute it and/or modify
   7    it under the terms of the GNU General Public License as published by
   8    the Free Software Foundation; either version 3 of the License, or
   9    (at your option) any later version.
  10 
  11    This program is distributed in the hope that it will be useful,
  12    but WITHOUT ANY WARRANTY; without even the implied warranty of
  13    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14    GNU General Public License for more details.
  15 
  16    You should have received a copy of the GNU General Public License
  17    along with this program.  If not, see <http://www.gnu.org/licenses/>.
  18 */
  19 
  20 #include "includes.h"
  21 
  22 
  23 /* prototypes for static functions first - for clarity */
  24 
  25 static bool smb_ace_to_internal(acl_entry_t posix_ace,
  26                                 struct smb_acl_entry *ace);
  27 static struct smb_acl_t *smb_acl_to_internal(acl_t acl);
  28 static int smb_acl_set_mode(acl_entry_t entry, SMB_ACL_PERM_T perm);
  29 static acl_t smb_acl_to_posix(const struct smb_acl_t *acl);
  30 
  31 
  32 /* public functions - the api */
  33 
  34 SMB_ACL_T posixacl_sys_acl_get_file(vfs_handle_struct *handle,
     /* [<][>][^][v][top][bottom][index][help] */
  35                                     const char *path_p,
  36                                     SMB_ACL_TYPE_T type)
  37 {
  38         struct smb_acl_t *result;
  39         acl_type_t acl_type;
  40         acl_t acl;
  41 
  42         switch(type) {
  43         case SMB_ACL_TYPE_ACCESS:
  44                 acl_type = ACL_TYPE_ACCESS;
  45                 break;
  46         case SMB_ACL_TYPE_DEFAULT:
  47                 acl_type = ACL_TYPE_DEFAULT;
  48                 break;
  49         default:
  50                 errno = EINVAL;
  51                 return NULL;
  52         }
  53 
  54         acl = acl_get_file(path_p, acl_type);
  55 
  56         if (acl == NULL) {
  57                 return NULL;
  58         }
  59 
  60         result = smb_acl_to_internal(acl);
  61         acl_free(acl);
  62         return result;
  63 }
  64 
  65 SMB_ACL_T posixacl_sys_acl_get_fd(vfs_handle_struct *handle,
     /* [<][>][^][v][top][bottom][index][help] */
  66                                   files_struct *fsp)
  67 {
  68         struct smb_acl_t *result;
  69         acl_t acl = acl_get_fd(fsp->fh->fd);
  70 
  71         if (acl == NULL) {
  72                 return NULL;
  73         }
  74 
  75         result = smb_acl_to_internal(acl);
  76         acl_free(acl);
  77         return result;
  78 }
  79 
  80 int posixacl_sys_acl_set_file(vfs_handle_struct *handle,
     /* [<][>][^][v][top][bottom][index][help] */
  81                               const char *name,
  82                               SMB_ACL_TYPE_T type,
  83                               SMB_ACL_T theacl)
  84 {
  85         int res;
  86         acl_type_t acl_type;
  87         acl_t acl;
  88 
  89         DEBUG(10, ("Calling acl_set_file: %s, %d\n", name, type));
  90 
  91         switch(type) {
  92         case SMB_ACL_TYPE_ACCESS:
  93                 acl_type = ACL_TYPE_ACCESS;
  94                 break;
  95         case SMB_ACL_TYPE_DEFAULT:
  96                 acl_type = ACL_TYPE_DEFAULT;
  97                 break;
  98         default:
  99                 errno = EINVAL;
 100                 return -1;
 101         }
 102 
 103         if ((acl = smb_acl_to_posix(theacl)) == NULL) {
 104                 return -1;
 105         }
 106         res = acl_set_file(name, acl_type, acl);
 107         if (res != 0) {
 108                 DEBUG(10, ("acl_set_file failed: %s\n", strerror(errno)));
 109         }
 110         acl_free(acl);
 111         return res;
 112 }
 113 
 114 int posixacl_sys_acl_set_fd(vfs_handle_struct *handle,
     /* [<][>][^][v][top][bottom][index][help] */
 115                             files_struct *fsp,
 116                             SMB_ACL_T theacl)
 117 {
 118         int res;
 119         acl_t acl = smb_acl_to_posix(theacl);
 120         if (acl == NULL) {
 121                 return -1;
 122         }
 123         res =  acl_set_fd(fsp->fh->fd, acl);
 124         acl_free(acl);
 125         return res;
 126 }
 127 
 128 int posixacl_sys_acl_delete_def_file(vfs_handle_struct *handle,
     /* [<][>][^][v][top][bottom][index][help] */
 129                                      const char *path)
 130 {
 131         return acl_delete_def_file(path);
 132 }
 133 
 134 
 135 /* private functions */
 136 
 137 static bool smb_ace_to_internal(acl_entry_t posix_ace,
     /* [<][>][^][v][top][bottom][index][help] */
 138                                 struct smb_acl_entry *ace)
 139 {
 140         acl_tag_t tag;
 141         acl_permset_t permset;
 142 
 143         if (acl_get_tag_type(posix_ace, &tag) != 0) {
 144                 DEBUG(0, ("smb_acl_get_tag_type failed\n"));
 145                 return False;
 146         }
 147 
 148         switch(tag) {
 149         case ACL_USER:
 150                 ace->a_type = SMB_ACL_USER;
 151                 break;
 152         case ACL_USER_OBJ:
 153                 ace->a_type = SMB_ACL_USER_OBJ;
 154                 break;
 155         case ACL_GROUP:
 156                 ace->a_type = SMB_ACL_GROUP;
 157                 break;
 158         case ACL_GROUP_OBJ:
 159                 ace->a_type = SMB_ACL_GROUP_OBJ;
 160                 break;
 161         case ACL_OTHER:
 162                 ace->a_type = SMB_ACL_OTHER;
 163                 break;
 164         case ACL_MASK:
 165                 ace->a_type = SMB_ACL_MASK;
 166                 break;
 167         default:
 168                 DEBUG(0, ("unknown tag type %d\n", (unsigned int)tag));
 169                 return False;
 170         }
 171         switch(ace->a_type) {
 172         case SMB_ACL_USER: {
 173                 uid_t *puid = (uid_t *)acl_get_qualifier(posix_ace);
 174                 if (puid == NULL) {
 175                         DEBUG(0, ("smb_acl_get_qualifier failed\n"));
 176                         return False;
 177                 }
 178                 ace->uid = *puid;
 179                 acl_free(puid);
 180                 break;
 181         }
 182                 
 183         case SMB_ACL_GROUP: {
 184                 gid_t *pgid = (uid_t *)acl_get_qualifier(posix_ace);
 185                 if (pgid == NULL) {
 186                         DEBUG(0, ("smb_acl_get_qualifier failed\n"));
 187                         return False;
 188                 }
 189                 ace->gid = *pgid;
 190                 acl_free(pgid);
 191                 break;
 192         }
 193         default:
 194                 break;
 195         }
 196         if (acl_get_permset(posix_ace, &permset) != 0) {
 197                 DEBUG(0, ("smb_acl_get_mode failed\n"));
 198                 return False;
 199         }
 200         ace->a_perm = 0;
 201 #ifdef HAVE_ACL_GET_PERM_NP
 202         ace->a_perm |= (acl_get_perm_np(permset, ACL_READ) ? SMB_ACL_READ : 0);
 203         ace->a_perm |= (acl_get_perm_np(permset, ACL_WRITE) ? SMB_ACL_WRITE : 0);
 204         ace->a_perm |= (acl_get_perm_np(permset, ACL_EXECUTE) ? SMB_ACL_EXECUTE : 0);
 205 #else
 206         ace->a_perm |= (acl_get_perm(permset, ACL_READ) ? SMB_ACL_READ : 0);
 207         ace->a_perm |= (acl_get_perm(permset, ACL_WRITE) ? SMB_ACL_WRITE : 0);
 208         ace->a_perm |= (acl_get_perm(permset, ACL_EXECUTE) ? SMB_ACL_EXECUTE : 0);
 209 #endif
 210         return True;
 211 }
 212 
 213 static struct smb_acl_t *smb_acl_to_internal(acl_t acl)
     /* [<][>][^][v][top][bottom][index][help] */
 214 {
 215         struct smb_acl_t *result = SMB_MALLOC_P(struct smb_acl_t);
 216         int entry_id = ACL_FIRST_ENTRY;
 217         acl_entry_t e;
 218         if (result == NULL) {
 219                 return NULL;
 220         }
 221         ZERO_STRUCTP(result);
 222         while (acl_get_entry(acl, entry_id, &e) == 1) {
 223 
 224                 entry_id = ACL_NEXT_ENTRY;
 225 
 226                 result = (struct smb_acl_t *)SMB_REALLOC(
 227                         result, sizeof(struct smb_acl_t) +
 228                         (sizeof(struct smb_acl_entry) * (result->count+1)));
 229                 if (result == NULL) {
 230                         DEBUG(0, ("SMB_REALLOC failed\n"));
 231                         errno = ENOMEM;
 232                         return NULL;
 233                 }
 234 
 235                 if (!smb_ace_to_internal(e, &result->acl[result->count])) {
 236                         SAFE_FREE(result);
 237                         return NULL;
 238                 }
 239 
 240                 result->count += 1;
 241         }
 242         return result;
 243 }
 244 
 245 static int smb_acl_set_mode(acl_entry_t entry, SMB_ACL_PERM_T perm)
     /* [<][>][^][v][top][bottom][index][help] */
 246 {
 247         int ret;
 248         acl_permset_t permset;
 249 
 250         if ((ret = acl_get_permset(entry, &permset)) != 0) {
 251                 return ret;
 252         }
 253         if ((ret = acl_clear_perms(permset)) != 0) {
 254                 return ret;
 255         }
 256         if ((perm & SMB_ACL_READ) &&
 257             ((ret = acl_add_perm(permset, ACL_READ)) != 0)) {
 258                 return ret;
 259         }
 260         if ((perm & SMB_ACL_WRITE) &&
 261             ((ret = acl_add_perm(permset, ACL_WRITE)) != 0)) {
 262                 return ret;
 263         }
 264         if ((perm & SMB_ACL_EXECUTE) &&
 265             ((ret = acl_add_perm(permset, ACL_EXECUTE)) != 0)) {
 266                 return ret;
 267         }
 268         return acl_set_permset(entry, permset);
 269 }
 270 
 271 static acl_t smb_acl_to_posix(const struct smb_acl_t *acl)
     /* [<][>][^][v][top][bottom][index][help] */
 272 {
 273         acl_t result;
 274         int i;
 275 
 276         result = acl_init(acl->count);
 277         if (result == NULL) {
 278                 DEBUG(10, ("acl_init failed\n"));
 279                 return NULL;
 280         }
 281 
 282         for (i=0; i<acl->count; i++) {
 283                 const struct smb_acl_entry *entry = &acl->acl[i];
 284                 acl_entry_t e;
 285                 acl_tag_t tag;
 286 
 287                 if (acl_create_entry(&result, &e) != 0) {
 288                         DEBUG(1, ("acl_create_entry failed: %s\n",
 289                                   strerror(errno)));
 290                         goto fail;
 291                 }
 292 
 293                 switch (entry->a_type) {
 294                 case SMB_ACL_USER:
 295                         tag = ACL_USER;
 296                         break;
 297                 case SMB_ACL_USER_OBJ:
 298                         tag = ACL_USER_OBJ;
 299                         break;
 300                 case SMB_ACL_GROUP:
 301                         tag = ACL_GROUP;
 302                         break;
 303                 case SMB_ACL_GROUP_OBJ:
 304                         tag = ACL_GROUP_OBJ;
 305                         break;
 306                 case SMB_ACL_OTHER:
 307                         tag = ACL_OTHER;
 308                         break;
 309                 case SMB_ACL_MASK:
 310                         tag = ACL_MASK;
 311                         break;
 312                 default:
 313                         DEBUG(1, ("Unknown tag value %d\n", entry->a_type));
 314                         goto fail;
 315                 }
 316 
 317                 if (acl_set_tag_type(e, tag) != 0) {
 318                         DEBUG(10, ("acl_set_tag_type(%d) failed: %s\n",
 319                                    tag, strerror(errno)));
 320                         goto fail;
 321                 }
 322 
 323                 switch (entry->a_type) {
 324                 case SMB_ACL_USER:
 325                         if (acl_set_qualifier(e, &entry->uid) != 0) {
 326                                 DEBUG(1, ("acl_set_qualifiier failed: %s\n",
 327                                           strerror(errno)));
 328                                 goto fail;
 329                         }
 330                         break;
 331                 case SMB_ACL_GROUP:
 332                         if (acl_set_qualifier(e, &entry->gid) != 0) {
 333                                 DEBUG(1, ("acl_set_qualifiier failed: %s\n",
 334                                           strerror(errno)));
 335                                 goto fail;
 336                         }
 337                         break;
 338                 default:        /* Shut up, compiler! :-) */
 339                         break;
 340                 }
 341 
 342                 if (smb_acl_set_mode(e, entry->a_perm) != 0) {
 343                         goto fail;
 344                 }
 345         }
 346 
 347         if (acl_valid(result) != 0) {
 348                 DEBUG(0, ("smb_acl_to_posix: ACL is invalid for set (%s)\n",
 349                           strerror(errno)));
 350                 goto fail;
 351         }
 352 
 353         return result;
 354 
 355  fail:
 356         if (result != NULL) {
 357                 acl_free(result);
 358         }
 359         return NULL;
 360 }
 361 
 362 /* VFS operations structure */
 363 
 364 static vfs_op_tuple posixacl_op_tuples[] = {
 365         /* Disk operations */
 366   {SMB_VFS_OP(posixacl_sys_acl_get_file),
 367    SMB_VFS_OP_SYS_ACL_GET_FILE,
 368    SMB_VFS_LAYER_TRANSPARENT},
 369 
 370   {SMB_VFS_OP(posixacl_sys_acl_get_fd),
 371    SMB_VFS_OP_SYS_ACL_GET_FD,
 372    SMB_VFS_LAYER_TRANSPARENT},
 373 
 374   {SMB_VFS_OP(posixacl_sys_acl_set_file),
 375    SMB_VFS_OP_SYS_ACL_SET_FILE,
 376    SMB_VFS_LAYER_TRANSPARENT},
 377 
 378   {SMB_VFS_OP(posixacl_sys_acl_set_fd),
 379    SMB_VFS_OP_SYS_ACL_SET_FD,
 380    SMB_VFS_LAYER_TRANSPARENT},
 381 
 382   {SMB_VFS_OP(posixacl_sys_acl_delete_def_file),
 383    SMB_VFS_OP_SYS_ACL_DELETE_DEF_FILE,
 384    SMB_VFS_LAYER_TRANSPARENT},
 385 
 386   {SMB_VFS_OP(NULL),
 387    SMB_VFS_OP_NOOP,
 388    SMB_VFS_LAYER_NOOP}
 389 };
 390 
 391 NTSTATUS vfs_posixacl_init(void);
 392 NTSTATUS vfs_posixacl_init(void)
     /* [<][>][^][v][top][bottom][index][help] */
 393 {
 394         return smb_register_vfs(SMB_VFS_INTERFACE_VERSION, "posixacl",
 395                                 posixacl_op_tuples);
 396 }

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