root/source3/modules/onefs_acl.c

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

DEFINITIONS

This source file includes following definitions.
  1. onefs_sid_to_identity
  2. onefs_identity_to_sid
  3. onefs_og_to_identity
  4. sid_in_ignore_list
  5. onefs_samba_ace_to_ace
  6. onefs_samba_acl_to_acl
  7. onefs_acl_to_samba_acl
  8. onefs_canon_acl
  9. onefs_init_ace
  10. add_sfs_aces
  11. onefs_fget_nt_acl
  12. onefs_get_nt_acl
  13. onefs_samba_sd_to_sd
  14. onefs_fset_nt_acl

   1 /*
   2  * Unix SMB/CIFS implementation.
   3  *
   4  * Support for OneFS native NTFS ACLs
   5  *
   6  * Copyright (C) Steven Danneman, 2008
   7  *
   8  * This program is free software; you can redistribute it and/or modify
   9  * it under the terms of the GNU General Public License as published by
  10  * the Free Software Foundation; either version 3 of the License, or
  11  * (at your option) any later version.
  12  *
  13  * This program is distributed in the hope that it will be useful,
  14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  16  * GNU General Public License for more details.
  17  *
  18  * You should have received a copy of the GNU General Public License
  19  * along with this program; if not, see <http://www.gnu.org/licenses/>.
  20  */
  21 
  22 #include "includes.h"
  23 #include "onefs.h"
  24 #include "onefs_config.h"
  25 
  26 #include <isi_acl/isi_acl_util.h>
  27 #include <ifs/ifs_syscalls.h>
  28 #include <sys/isi_acl.h>
  29 
  30 const struct enum_list enum_onefs_acl_wire_format[] = {
  31         {ACL_FORMAT_RAW,  "No Format"},
  32         {ACL_FORMAT_WINDOWS_SD, "Format Windows SD"},
  33         {ACL_FORMAT_ALWAYS, "Always Format SD"},
  34         {-1, NULL}
  35 };
  36 
  37 /**
  38  * Turn SID into UID/GID and setup a struct ifs_identity
  39  */
  40 static bool
  41 onefs_sid_to_identity(const DOM_SID *sid, struct ifs_identity *id,
     /* [<][>][^][v][top][bottom][index][help] */
  42     bool is_group)
  43 {
  44         enum ifs_identity_type type = IFS_ID_TYPE_LAST+1;
  45         uid_t uid = 0;
  46         gid_t gid = 0;
  47 
  48         if (!sid || sid_equal(sid, &global_sid_NULL))
  49                 type = IFS_ID_TYPE_NULL;
  50         else if (sid_equal(sid, &global_sid_World))
  51                 type = IFS_ID_TYPE_EVERYONE;
  52         else if (sid_equal(sid, &global_sid_Creator_Owner))
  53                 type = IFS_ID_TYPE_CREATOR_OWNER;
  54         else if (sid_equal(sid, &global_sid_Creator_Group))
  55                 type = IFS_ID_TYPE_CREATOR_GROUP;
  56         else if (is_group) {
  57                 if (!sid_to_gid(sid, &gid))
  58                         return false;
  59                 type = IFS_ID_TYPE_GID;
  60         } else {
  61                 if (sid_to_uid(sid, &uid))
  62                         type = IFS_ID_TYPE_UID;
  63                 else if (sid_to_gid(sid, &gid))
  64                         type = IFS_ID_TYPE_GID;
  65                 else
  66                         return false;
  67         }
  68 
  69         if (aclu_initialize_identity(id, type, uid, gid, is_group)) {
  70                 DEBUG(3, ("Call to aclu_initialize_identity failed! id=%x, "
  71                     "type=%d, uid=%u, gid=%u, is_group=%d\n",
  72                     (unsigned int)id, type, uid, gid, is_group));
  73                 return false;
  74         }
  75 
  76         return true;
  77 }
  78 
  79 /**
  80  * Turn struct ifs_identity into SID
  81  */
  82 static bool
  83 onefs_identity_to_sid(struct ifs_identity *id, DOM_SID *sid)
     /* [<][>][^][v][top][bottom][index][help] */
  84 {
  85         if (!id || !sid)
  86                 return false;
  87 
  88         if (id->type >= IFS_ID_TYPE_LAST)
  89                 return false;
  90 
  91         switch (id->type) {
  92             case IFS_ID_TYPE_UID:
  93                 uid_to_sid(sid, id->id.uid);
  94                 break;
  95             case IFS_ID_TYPE_GID:
  96                 gid_to_sid(sid, id->id.gid);
  97                 break;
  98             case IFS_ID_TYPE_EVERYONE:
  99                 sid_copy(sid, &global_sid_World);
 100                 break;
 101             case IFS_ID_TYPE_NULL:
 102                 sid_copy(sid, &global_sid_NULL);
 103                 break;
 104             case IFS_ID_TYPE_CREATOR_OWNER:
 105                 sid_copy(sid, &global_sid_Creator_Owner);
 106                 break;
 107             case IFS_ID_TYPE_CREATOR_GROUP:
 108                 sid_copy(sid, &global_sid_Creator_Group);
 109                 break;
 110             default:
 111                 DEBUG(0, ("Unknown identity type: %d\n", id->type));
 112                 return false;
 113         }
 114 
 115         return true;
 116 }
 117 
 118 static bool
 119 onefs_og_to_identity(DOM_SID *sid, struct ifs_identity * ident,
     /* [<][>][^][v][top][bottom][index][help] */
 120     bool is_group, int snum)
 121 {
 122         const DOM_SID *b_admin_sid = &global_sid_Builtin_Administrators;
 123 
 124         if (!onefs_sid_to_identity(sid, ident, is_group)) {
 125                 if (!lp_parm_bool(snum, PARM_ONEFS_TYPE,
 126                      PARM_UNMAPPABLE_SIDS_IGNORE,
 127                      PARM_UNMAPPABLE_SIDS_IGNORE_DEFAULT)) {
 128                         DEBUG(3, ("Unresolvable SID (%s) found.\n",
 129                                 sid_string_dbg(sid)));
 130                         return false;
 131                 }
 132                 if (!onefs_sid_to_identity(b_admin_sid, ident, is_group)) {
 133                         return false;
 134                 }
 135                 DEBUG(3, ("Mapping unresolvable owner SID (%s) to Builtin "
 136                         "Administrators group.\n",
 137                         sid_string_dbg(sid)));
 138         }
 139         return true;
 140 }
 141 
 142 static bool
 143 sid_in_ignore_list(DOM_SID * sid, int snum)
     /* [<][>][^][v][top][bottom][index][help] */
 144 {
 145         const char ** sid_list = NULL;
 146         DOM_SID match;
 147 
 148         sid_list = lp_parm_string_list(snum, PARM_ONEFS_TYPE,
 149             PARM_UNMAPPABLE_SIDS_IGNORE_LIST,
 150             PARM_UNMAPPABLE_SIDS_IGNORE_LIST_DEFAULT);
 151 
 152         /* Fast path a NULL list */
 153         if (!sid_list || *sid_list == NULL)
 154                 return false;
 155 
 156         while (*sid_list) {
 157                 if (string_to_sid(&match, *sid_list))
 158                         if (sid_equal(sid, &match))
 159                                 return true;
 160                 sid_list++;
 161         }
 162 
 163         return false;
 164 }
 165 
 166 /**
 167  * Convert a trustee to a struct identity
 168  */
 169 static bool
 170 onefs_samba_ace_to_ace(SEC_ACE * samba_ace, struct ifs_ace * ace,
     /* [<][>][^][v][top][bottom][index][help] */
 171     bool *mapped, int snum)
 172 {
 173         struct ifs_identity ident = {.type=IFS_ID_TYPE_LAST, .id.uid=0};
 174 
 175         SMB_ASSERT(ace);
 176         SMB_ASSERT(mapped);
 177         SMB_ASSERT(samba_ace);
 178 
 179         if (onefs_sid_to_identity(&samba_ace->trustee, &ident, false)) {
 180                 *mapped = true;
 181         } else {
 182 
 183                 SMB_ASSERT(ident.id.uid >= 0);
 184 
 185                 /* Ignore the sid if it's in the list */
 186                 if (sid_in_ignore_list(&samba_ace->trustee, snum)) {
 187                         DEBUG(3, ("Silently failing to set ACE for SID (%s) "
 188                                 "because it is in the ignore sids list\n",
 189                                 sid_string_dbg(&samba_ace->trustee)));
 190                         *mapped = false;
 191                 } else if ((samba_ace->type == SEC_ACE_TYPE_ACCESS_DENIED) &&
 192                     lp_parm_bool(snum, PARM_ONEFS_TYPE,
 193                     PARM_UNMAPPABLE_SIDS_DENY_EVERYONE,
 194                     PARM_UNMAPPABLE_SIDS_DENY_EVERYONE_DEFAULT)) {
 195                         /* If the ace is deny translated to Everyone */
 196                         DEBUG(3, ("Mapping unresolvable deny ACE SID (%s) "
 197                                 "to Everyone.\n",
 198                                 sid_string_dbg(&samba_ace->trustee)));
 199                         if (aclu_initialize_identity(&ident,
 200                                 IFS_ID_TYPE_EVERYONE, 0, 0, False) != 0) {
 201                                 DEBUG(2, ("aclu_initialize_identity() "
 202                                         "failed making Everyone\n"));
 203                                 return false;
 204                         }
 205                         *mapped = true;
 206                 } else if (lp_parm_bool(snum, PARM_ONEFS_TYPE,
 207                            PARM_UNMAPPABLE_SIDS_IGNORE,
 208                            PARM_UNMAPPABLE_SIDS_IGNORE_DEFAULT)) {
 209                         DEBUG(3, ("Silently failing to set ACE for SID (%s) "
 210                                 "because it is unresolvable\n",
 211                                 sid_string_dbg(&samba_ace->trustee)));
 212                         *mapped = false;
 213                 } else {
 214                         /* Fail for lack of a better option */
 215                         return false;
 216                 }
 217         }
 218 
 219         if (*mapped) {
 220                 if (aclu_initialize_ace(ace, samba_ace->type,
 221                         samba_ace->access_mask, samba_ace->flags, 0,
 222                         &ident))
 223                         return false;
 224 
 225                 if ((ace->trustee.type == IFS_ID_TYPE_CREATOR_OWNER ||
 226                         ace->trustee.type == IFS_ID_TYPE_CREATOR_GROUP) &&
 227                     nt4_compatible_acls())
 228                         ace->flags |= SEC_ACE_FLAG_INHERIT_ONLY;
 229         }
 230 
 231         return true;
 232 }
 233 
 234 /**
 235  * Convert a SEC_ACL to a struct ifs_security_acl
 236  */
 237 static bool
 238 onefs_samba_acl_to_acl(SEC_ACL *samba_acl, struct ifs_security_acl **acl,
     /* [<][>][^][v][top][bottom][index][help] */
 239     bool * ignore_aces, int snum)
 240 {
 241         int num_aces = 0;
 242         struct ifs_ace *aces = NULL;
 243         SEC_ACE *samba_aces;
 244         bool mapped;
 245         int i, j;
 246 
 247         SMB_ASSERT(ignore_aces);
 248 
 249         if ((!acl) || (!samba_acl))
 250                 return false;
 251 
 252         samba_aces = samba_acl->aces;
 253 
 254         if (samba_acl->num_aces > 0 && samba_aces) {
 255                 /* Setup ACES */
 256                 num_aces = samba_acl->num_aces;
 257                 aces = SMB_MALLOC_ARRAY(struct ifs_ace, num_aces);
 258 
 259                 for (i = 0, j = 0; j < num_aces; i++, j++) {
 260                         if (!onefs_samba_ace_to_ace(&samba_aces[j],
 261                                 &aces[i], &mapped, snum))
 262                                 goto err_free;
 263 
 264                         if (!mapped)
 265                                 i--;
 266                 }
 267                 num_aces = i;
 268         }
 269 
 270         /* If aces are given but we cannot apply them due to the reasons
 271          * above we do not change the SD.  However, if we are told to
 272          * explicitly set an SD with 0 aces we honor this operation */
 273         *ignore_aces = samba_acl->num_aces > 0 && num_aces < 1;
 274 
 275         if (*ignore_aces == false)
 276                 if (aclu_initialize_acl(acl, aces, num_aces))
 277                         goto err_free;
 278 
 279         /* Currently aclu_initialize_acl should copy the aces over, allowing
 280          * us to immediately free */
 281         free(aces);
 282         return true;
 283 
 284 err_free:
 285         free(aces);
 286         return false;
 287 }
 288 
 289 /**
 290  * Convert a struct ifs_security_acl to a SEC_ACL
 291  */
 292 static bool
 293 onefs_acl_to_samba_acl(struct ifs_security_acl *acl, SEC_ACL **samba_acl)
     /* [<][>][^][v][top][bottom][index][help] */
 294 {
 295         SEC_ACE *samba_aces = NULL;
 296         SEC_ACL *tmp_samba_acl = NULL;
 297         int i, num_aces = 0;
 298 
 299         if (!samba_acl)
 300                 return false;
 301 
 302         /* NULL ACL */
 303         if (!acl) {
 304                 *samba_acl = NULL;
 305                 return true;
 306         }
 307 
 308         /* Determine number of aces in ACL */
 309         if (!acl->aces)
 310                 num_aces = 0;
 311         else
 312                 num_aces = acl->num_aces;
 313 
 314         /* Allocate the ace list. */
 315         if (num_aces > 0) {
 316                 if ((samba_aces = SMB_MALLOC_ARRAY(SEC_ACE, num_aces)) == NULL)
 317                 {
 318                         DEBUG(0, ("Unable to malloc space for %d aces.\n",
 319                             num_aces));
 320                         return false;
 321                 }
 322                 memset(samba_aces, '\0', (num_aces) * sizeof(SEC_ACE));
 323         }
 324 
 325         for (i = 0; i < num_aces; i++) {
 326                 DOM_SID sid;
 327 
 328                 if (!onefs_identity_to_sid(&acl->aces[i].trustee, &sid))
 329                         goto err_free;
 330 
 331                 init_sec_ace(&samba_aces[i], &sid, acl->aces[i].type,
 332                     acl->aces[i].access_mask, acl->aces[i].flags);
 333         }
 334 
 335         if ((tmp_samba_acl = make_sec_acl(talloc_tos(), acl->revision, num_aces,
 336             samba_aces)) == NULL) {
 337                DEBUG(0, ("Unable to malloc space for acl.\n"));
 338                goto err_free;
 339         }
 340 
 341         *samba_acl = tmp_samba_acl;
 342         SAFE_FREE(samba_aces);
 343         return true;
 344 err_free:
 345         SAFE_FREE(samba_aces);
 346         return false;
 347 }
 348 
 349 /**
 350  * @brief Reorder ACLs into the "correct" order for Windows Explorer.
 351  *
 352  * Windows Explorer expects ACLs to be in a standard order (inherited first,
 353  * then deny, then permit.)  When ACLs are composed from POSIX file permissions
 354  * bits, they may not match these expectations, generating an annoying warning
 355  * dialog for the user.  This function will, if configured appropriately,
 356  * reorder the ACLs for these "synthetic" (POSIX-derived) descriptors to prevent
 357  * this.  The list is changed within the security descriptor passed in.
 358  *
 359  * @param fsp files_struct with service configs; must not be NULL
 360  * @param sd security descriptor being normalized;
 361  *           sd->dacl->aces is rewritten in-place, so must not be NULL
 362  * @return true on success, errno will be set on error
 363  *
 364  * @bug Although Windows Explorer likes the reordering, they seem to cause
 365  *  problems with Excel and Word sending back the reordered ACLs to us and
 366  *  changing policy; see Isilon bug 30165.
 367  */
 368 static bool
 369 onefs_canon_acl(files_struct *fsp, struct ifs_security_descriptor *sd)
     /* [<][>][^][v][top][bottom][index][help] */
 370 {
 371         int error = 0;
 372         int cur;
 373         struct ifs_ace *new_aces = NULL;
 374         int new_aces_count = 0;
 375         SMB_STRUCT_STAT sbuf;
 376 
 377         if (sd == NULL || sd->dacl == NULL || sd->dacl->num_aces == 0)
 378                 return true;
 379 
 380         /*
 381          * Find out if this is a windows bit, and if the smb policy wants us to
 382          * lie about the sd.
 383          */
 384         SMB_ASSERT(fsp != NULL);
 385         switch (lp_parm_enum(SNUM(fsp->conn), PARM_ONEFS_TYPE,
 386                 PARM_ACL_WIRE_FORMAT, enum_onefs_acl_wire_format,
 387                 PARM_ACL_WIRE_FORMAT_DEFAULT))  {
 388         case ACL_FORMAT_RAW:
 389                 return true;
 390 
 391         case ACL_FORMAT_WINDOWS_SD:
 392                 error = SMB_VFS_FSTAT(fsp, &sbuf);
 393                 if (error)
 394                         return false;
 395 
 396                 if ((sbuf.st_flags & SF_HASNTFSACL) != 0) {
 397                         DEBUG(10, ("Did not canonicalize ACLs because a "
 398                             "Windows ACL set was found for file %s\n",
 399                             fsp->fsp_name));
 400                         return true;
 401                 }
 402                 break;
 403 
 404         case ACL_FORMAT_ALWAYS:
 405                 break;
 406 
 407         default:
 408                 SMB_ASSERT(false);
 409                 return false;
 410         }
 411 
 412         new_aces = SMB_MALLOC_ARRAY(struct ifs_ace, sd->dacl->num_aces);
 413         if (new_aces == NULL)
 414                 return false;
 415 
 416         /*
 417          * By walking down the list 3 separate times, we can avoid the need
 418          * to create multiple temp buffers and extra copies.
 419          */
 420         for (cur = 0; cur < sd->dacl->num_aces; cur++)  {
 421                 if (sd->dacl->aces[cur].flags & IFS_ACE_FLAG_INHERITED_ACE)
 422                         new_aces[new_aces_count++] = sd->dacl->aces[cur];
 423         }
 424 
 425         for (cur = 0; cur < sd->dacl->num_aces; cur++)  {
 426                 if (!(sd->dacl->aces[cur].flags & IFS_ACE_FLAG_INHERITED_ACE) &&
 427                     (sd->dacl->aces[cur].type == IFS_ACE_TYPE_ACCESS_DENIED))
 428                         new_aces[new_aces_count++] = sd->dacl->aces[cur];
 429         }
 430 
 431         for (cur = 0; cur < sd->dacl->num_aces; cur++)  {
 432                 if (!(sd->dacl->aces[cur].flags & IFS_ACE_FLAG_INHERITED_ACE) &&
 433                     !(sd->dacl->aces[cur].type == IFS_ACE_TYPE_ACCESS_DENIED))
 434                         new_aces[new_aces_count++] = sd->dacl->aces[cur];
 435         }
 436 
 437         SMB_ASSERT(new_aces_count == sd->dacl->num_aces);
 438         DEBUG(10, ("Performed canonicalization of ACLs for file %s\n",
 439             fsp->fsp_name));
 440 
 441         /*
 442          * At this point you would think we could just do this:
 443          *   SAFE_FREE(sd->dacl->aces);
 444          *   sd->dacl->aces = new_aces;
 445          * However, in some cases the existing aces pointer does not point
 446          * to the beginning of an allocated block.  So we have to do a more
 447          * expensive memcpy()
 448          */
 449         memcpy(sd->dacl->aces, new_aces,
 450             sizeof(struct ifs_ace) * new_aces_count);
 451 
 452         SAFE_FREE(new_aces);
 453         return true;
 454 }
 455 
 456 
 457 /**
 458  * This enum is a helper for onefs_fget_nt_acl() to communicate with
 459  * onefs_init_ace().
 460  */
 461 enum mode_ident { USR, GRP, OTH };
 462 
 463 /**
 464  * Initializes an ACE for addition to a synthetic ACL.
 465  */
 466 static struct ifs_ace onefs_init_ace(struct connection_struct *conn,
     /* [<][>][^][v][top][bottom][index][help] */
 467                                      mode_t mode,
 468                                      bool isdir,
 469                                      enum mode_ident ident)
 470 {
 471         struct ifs_ace result;
 472         enum ifs_ace_rights r,w,x;
 473 
 474         r = isdir ? UNIX_DIRECTORY_ACCESS_R : UNIX_ACCESS_R;
 475         w = isdir ? UNIX_DIRECTORY_ACCESS_W : UNIX_ACCESS_W;
 476         x = isdir ? UNIX_DIRECTORY_ACCESS_X : UNIX_ACCESS_X;
 477 
 478         result.type = IFS_ACE_TYPE_ACCESS_ALLOWED;
 479         result.ifs_flags = 0;
 480         result.flags = isdir ? IFS_ACE_FLAG_CONTAINER_INHERIT :
 481             IFS_ACE_FLAG_OBJECT_INHERIT;
 482         result.flags |= IFS_ACE_FLAG_INHERIT_ONLY;
 483 
 484         switch (ident) {
 485         case USR:
 486                 result.access_mask =
 487                     ((mode & S_IRUSR) ? r : 0 ) |
 488                     ((mode & S_IWUSR) ? w : 0 ) |
 489                     ((mode & S_IXUSR) ? x : 0 );
 490                 if (lp_parm_bool(SNUM(conn), PARM_ONEFS_TYPE,
 491                     PARM_CREATOR_OWNER_GETS_FULL_CONTROL,
 492                     PARM_CREATOR_OWNER_GETS_FULL_CONTROL_DEFAULT))
 493                         result.access_mask |= GENERIC_ALL_ACCESS;
 494                 result.trustee.type = IFS_ID_TYPE_CREATOR_OWNER;
 495                 break;
 496         case GRP:
 497                 result.access_mask =
 498                     ((mode & S_IRGRP) ? r : 0 ) |
 499                     ((mode & S_IWGRP) ? w : 0 ) |
 500                     ((mode & S_IXGRP) ? x : 0 );
 501                 result.trustee.type = IFS_ID_TYPE_CREATOR_GROUP;
 502                 break;
 503         case OTH:
 504                 result.access_mask =
 505                     ((mode & S_IROTH) ? r : 0 ) |
 506                     ((mode & S_IWOTH) ? w : 0 ) |
 507                     ((mode & S_IXOTH) ? x : 0 );
 508                 result.trustee.type = IFS_ID_TYPE_EVERYONE;
 509                 break;
 510         }
 511 
 512         return result;
 513 }
 514 
 515 /**
 516  * This adds inheritable ACEs to the end of the DACL, with the ACEs
 517  * being derived from the mode bits.  This is useful for clients that have the
 518  * MoveSecurityAttributes regkey set to 0 or are in Simple File Sharing Mode.
 519  *
 520  * On these clients, when copying files from one folder to another inside the
 521  * same volume/share, the DACL is explicitely cleared.  Without inheritable
 522  * aces on the target folder the mode bits of the copied file are set to 000.
 523  *
 524  * See Isilon Bug 27990
 525  *
 526  * Note: This function allocates additional memory onto sd->dacl->aces, that
 527  * must be freed by the caller.
 528  */
 529 static bool add_sfs_aces(files_struct *fsp, struct ifs_security_descriptor *sd)
     /* [<][>][^][v][top][bottom][index][help] */
 530 {
 531         int error;
 532         SMB_STRUCT_STAT sbuf;
 533 
 534         error = SMB_VFS_FSTAT(fsp, &sbuf);
 535         if (error) {
 536                 DEBUG(0, ("Failed to stat %s in simple files sharing "
 537                           "compatibility mode. errno=%d\n",
 538                           fsp->fsp_name, errno));
 539                 return false;
 540         }
 541 
 542         /* Only continue if this is a synthetic ACL and a directory. */
 543         if (S_ISDIR(sbuf.st_mode) && (sbuf.st_flags & SF_HASNTFSACL) == 0) {
 544                 struct ifs_ace new_aces[6];
 545                 struct ifs_ace *old_aces;
 546                 int i, num_aces_to_add = 0;
 547                 mode_t file_mode = 0, dir_mode = 0;
 548 
 549                 /* Use existing samba logic to derive the mode bits. */
 550                 file_mode = unix_mode(fsp->conn, 0, fsp->fsp_name, false);
 551                 dir_mode = unix_mode(fsp->conn, aDIR, fsp->fsp_name, false);
 552 
 553                 /* Initialize ACEs. */
 554                 new_aces[0] = onefs_init_ace(fsp->conn, file_mode, false, USR);
 555                 new_aces[1] = onefs_init_ace(fsp->conn, file_mode, false, GRP);
 556                 new_aces[2] = onefs_init_ace(fsp->conn, file_mode, false, OTH);
 557                 new_aces[3] = onefs_init_ace(fsp->conn, dir_mode, true, USR);
 558                 new_aces[4] = onefs_init_ace(fsp->conn, dir_mode, true, GRP);
 559                 new_aces[5] = onefs_init_ace(fsp->conn, dir_mode, true, OTH);
 560 
 561                 for (i = 0; i < 6; i++)
 562                         if (new_aces[i].access_mask != 0)
 563                                 num_aces_to_add++;
 564 
 565                 /* Expand the ACEs array */
 566                 if (num_aces_to_add != 0) {
 567                         old_aces = sd->dacl->aces;
 568 
 569                         sd->dacl->aces = SMB_MALLOC_ARRAY(struct ifs_ace,
 570                             sd->dacl->num_aces + num_aces_to_add);
 571                         if (!sd->dacl->aces) {
 572                                 DEBUG(0, ("Unable to malloc space for "
 573                                     "new_aces: %d.\n",
 574                                      sd->dacl->num_aces + num_aces_to_add));
 575                                 return false;
 576                         }
 577                         memcpy(sd->dacl->aces, old_aces,
 578                             sizeof(struct ifs_ace) * sd->dacl->num_aces);
 579 
 580                         /* Add the new ACEs to the DACL. */
 581                         for (i = 0; i < 6; i++) {
 582                                 if (new_aces[i].access_mask != 0) {
 583                                         sd->dacl->aces[sd->dacl->num_aces] =
 584                                             new_aces[i];
 585                                         sd->dacl->num_aces++;
 586                                 }
 587                         }
 588                 }
 589         }
 590         return true;
 591 }
 592 
 593 /**
 594  * Isilon-specific function for getting an NTFS ACL from an open file.
 595  *
 596  * @param[out] ppdesc SecDesc to allocate and fill in
 597  *
 598  * @return NTSTATUS based off errno on error
 599  */
 600 NTSTATUS
 601 onefs_fget_nt_acl(vfs_handle_struct *handle, files_struct *fsp,
     /* [<][>][^][v][top][bottom][index][help] */
 602                   uint32 security_info, SEC_DESC **ppdesc)
 603 {
 604         int error;
 605         uint32_t sd_size = 0;
 606         size_t size = 0;
 607         struct ifs_security_descriptor *sd = NULL;
 608         DOM_SID owner_sid, group_sid;
 609         DOM_SID *ownerp, *groupp;
 610         SEC_ACL *dacl, *sacl;
 611         SEC_DESC *pdesc;
 612         bool alloced = false;
 613         bool new_aces_alloced = false;
 614         bool fopened = false;
 615         NTSTATUS status = NT_STATUS_OK;
 616 
 617         START_PROFILE(syscall_get_sd);
 618 
 619         *ppdesc = NULL;
 620 
 621         DEBUG(5, ("Getting sd for file %s. security_info=%u\n",
 622             fsp->fsp_name, security_info));
 623 
 624         if (lp_parm_bool(SNUM(fsp->conn), PARM_ONEFS_TYPE,
 625                 PARM_IGNORE_SACLS, PARM_IGNORE_SACLS_DEFAULT)) {
 626                 DEBUG(5, ("Ignoring SACL on %s.\n", fsp->fsp_name));
 627                 security_info &= ~SACL_SECURITY_INFORMATION;
 628         }
 629 
 630         if (fsp->fh->fd == -1) {
 631                 if ((fsp->fh->fd = onefs_sys_create_file(handle->conn,
 632                                                          -1,
 633                                                          fsp->fsp_name,
 634                                                          0,
 635                                                          0,
 636                                                          0,
 637                                                          0,
 638                                                          0,
 639                                                          0,
 640                                                          INTERNAL_OPEN_ONLY,
 641                                                          0,
 642                                                          NULL,
 643                                                          0,
 644                                                          NULL)) == -1) {
 645                         DEBUG(0, ("Error opening file %s. errno=%d (%s)\n",
 646                                   fsp->fsp_name, errno, strerror(errno)));
 647                         status = map_nt_error_from_unix(errno);
 648                         goto out;
 649                 }
 650                 fopened = true;
 651         }
 652 
 653         /* Get security descriptor */
 654         sd_size = 0;
 655         do {
 656                 /* Allocate memory for get_security_descriptor */
 657                 if (sd_size > 0) {
 658                         sd = SMB_REALLOC(sd, sd_size);
 659                         if (!sd) {
 660                                 DEBUG(0, ("Unable to malloc %u bytes of space "
 661                                     "for security descriptor.\n", sd_size));
 662                                 status = map_nt_error_from_unix(errno);
 663                                 goto out;
 664                         }
 665 
 666                         alloced = true;
 667                 }
 668 
 669                 error = ifs_get_security_descriptor(fsp->fh->fd, security_info,
 670                     sd_size, &sd_size, sd);
 671                 if (error && (errno != EMSGSIZE)) {
 672                         DEBUG(0, ("Failed getting size of security descriptor! "
 673                             "errno=%d\n", errno));
 674                         status = map_nt_error_from_unix(errno);
 675                         goto out;
 676                 }
 677         } while (error);
 678 
 679         DEBUG(5, ("Got sd, size=%u:\n", sd_size));
 680 
 681         if (lp_parm_bool(SNUM(fsp->conn),
 682             PARM_ONEFS_TYPE,
 683             PARM_SIMPLE_FILE_SHARING_COMPATIBILITY_MODE,
 684             PARM_SIMPLE_FILE_SHARING_COMPATIBILITY_MODE_DEFAULT) &&
 685             sd->dacl) {
 686                 if(!(new_aces_alloced = add_sfs_aces(fsp, sd)))
 687                         goto out;
 688         }
 689 
 690         if (!(onefs_canon_acl(fsp, sd))) {
 691                 status = map_nt_error_from_unix(errno);
 692                 goto out;
 693         }
 694 
 695         DEBUG(5, ("Finished canonicalizing ACL\n"));
 696 
 697         ownerp = NULL;
 698         groupp = NULL;
 699         dacl = NULL;
 700         sacl = NULL;
 701 
 702         /* Copy owner into ppdesc */
 703         if (security_info & OWNER_SECURITY_INFORMATION) {
 704                 if (!onefs_identity_to_sid(sd->owner, &owner_sid)) {
 705                         status = NT_STATUS_INVALID_PARAMETER;
 706                         goto out;
 707                 }
 708 
 709                 ownerp = &owner_sid;
 710         }
 711 
 712         /* Copy group into ppdesc */
 713         if (security_info & GROUP_SECURITY_INFORMATION) {
 714                 if (!onefs_identity_to_sid(sd->group, &group_sid)) {
 715                         status = NT_STATUS_INVALID_PARAMETER;
 716                         goto out;
 717                 }
 718 
 719                 groupp = &group_sid;
 720         }
 721 
 722         /* Copy DACL into ppdesc */
 723         if (security_info & DACL_SECURITY_INFORMATION) {
 724                 if (!onefs_acl_to_samba_acl(sd->dacl, &dacl)) {
 725                         status = NT_STATUS_INVALID_PARAMETER;
 726                         goto out;
 727                 }
 728         }
 729 
 730         /* Copy SACL into ppdesc */
 731         if (security_info & SACL_SECURITY_INFORMATION) {
 732                 if (!onefs_acl_to_samba_acl(sd->sacl, &sacl)) {
 733                         status = NT_STATUS_INVALID_PARAMETER;
 734                         goto out;
 735                 }
 736         }
 737 
 738         /* AUTO_INHERIT_REQ bits are not returned over the wire so strip them
 739          * off.  Eventually we should stop storing these in the kernel
 740          * all together. See Isilon bug 40364 */
 741         sd->control &= ~(IFS_SD_CTRL_DACL_AUTO_INHERIT_REQ |
 742                          IFS_SD_CTRL_SACL_AUTO_INHERIT_REQ);
 743 
 744         pdesc = make_sec_desc(talloc_tos(), sd->revision, sd->control,
 745             ownerp, groupp, sacl, dacl, &size);
 746 
 747         if (!pdesc) {
 748                 DEBUG(0, ("Problem with make_sec_desc. Memory?\n"));
 749                 status = map_nt_error_from_unix(errno);
 750                 goto out;
 751         }
 752 
 753         *ppdesc = pdesc;
 754 
 755         DEBUG(5, ("Finished retrieving/canonicalizing SD!\n"));
 756         /* FALLTHROUGH */
 757 out:
 758 
 759         END_PROFILE(syscall_get_sd);
 760 
 761         if (alloced && sd) {
 762                 if (new_aces_alloced && sd->dacl->aces)
 763                         SAFE_FREE(sd->dacl->aces);
 764 
 765                 SAFE_FREE(sd);
 766         }
 767 
 768         if (fopened) {
 769                 close(fsp->fh->fd);
 770                 fsp->fh->fd = -1;
 771         }
 772 
 773         return status;
 774 }
 775 
 776 /**
 777  * Isilon-specific function for getting an NTFS ACL from a file path.
 778  *
 779  * Since onefs_fget_nt_acl() needs to open a filepath if the fd is invalid,
 780  * we just mock up a files_struct with the path and bad fd and call into it.
 781  *
 782  * @param[out] ppdesc SecDesc to allocate and fill in
 783  *
 784  * @return NTSTATUS based off errno on error
 785  */
 786 NTSTATUS
 787 onefs_get_nt_acl(vfs_handle_struct *handle, const char* name,
     /* [<][>][^][v][top][bottom][index][help] */
 788                  uint32 security_info, SEC_DESC **ppdesc)
 789 {
 790         files_struct finfo;
 791         struct fd_handle fh;
 792 
 793         ZERO_STRUCT(finfo);
 794         ZERO_STRUCT(fh);
 795 
 796         finfo.fnum = -1;
 797         finfo.conn = handle->conn;
 798         finfo.fh = &fh;
 799         finfo.fh->fd = -1;
 800         finfo.fsp_name = CONST_DISCARD(char *, name);
 801 
 802         return onefs_fget_nt_acl(handle, &finfo, security_info, ppdesc);
 803 }
 804 
 805 /**
 806  * Isilon-specific function for setting up an ifs_security_descriptor, given a
 807  * samba SEC_DESC.
 808  *
 809  * @param[out] sd ifs_security_descriptor to fill in
 810  *
 811  * @return NTSTATUS_OK if successful
 812  */
 813 NTSTATUS onefs_samba_sd_to_sd(uint32_t security_info_sent, SEC_DESC *psd,
     /* [<][>][^][v][top][bottom][index][help] */
 814                               struct ifs_security_descriptor *sd, int snum,
 815                               uint32_t *security_info_effective)
 816 {
 817         struct ifs_security_acl *daclp, *saclp;
 818         struct ifs_identity owner, group, *ownerp, *groupp;
 819         bool ignore_aces;
 820 
 821         ownerp = NULL;
 822         groupp = NULL;
 823         daclp = NULL;
 824         saclp = NULL;
 825 
 826         *security_info_effective = security_info_sent;
 827 
 828         /* Setup owner */
 829         if (security_info_sent & OWNER_SECURITY_INFORMATION) {
 830                 if (!onefs_og_to_identity(psd->owner_sid, &owner, false, snum))
 831                         return NT_STATUS_ACCESS_DENIED;
 832 
 833                 SMB_ASSERT(owner.id.uid >= 0);
 834 
 835                 ownerp = &owner;
 836         }
 837 
 838         /* Setup group */
 839         if (security_info_sent & GROUP_SECURITY_INFORMATION) {
 840                 if (!onefs_og_to_identity(psd->group_sid, &group, true, snum))
 841                         return NT_STATUS_ACCESS_DENIED;
 842 
 843                 SMB_ASSERT(group.id.gid >= 0);
 844 
 845                 groupp = &group;
 846         }
 847 
 848         /* Setup DACL */
 849         if ((security_info_sent & DACL_SECURITY_INFORMATION) && (psd->dacl)) {
 850                 if (!onefs_samba_acl_to_acl(psd->dacl, &daclp, &ignore_aces,
 851                         snum))
 852                         return NT_STATUS_ACCESS_DENIED;
 853 
 854                 if (ignore_aces == true)
 855                         *security_info_effective &= ~DACL_SECURITY_INFORMATION;
 856         }
 857 
 858         /* Setup SACL */
 859         if (security_info_sent & SACL_SECURITY_INFORMATION) {
 860 
 861                 if (lp_parm_bool(snum, PARM_ONEFS_TYPE,
 862                             PARM_IGNORE_SACLS, PARM_IGNORE_SACLS_DEFAULT)) {
 863                         DEBUG(5, ("Ignoring SACL.\n"));
 864                         *security_info_effective &= ~SACL_SECURITY_INFORMATION;
 865                 } else {
 866                         if (psd->sacl) {
 867                                 if (!onefs_samba_acl_to_acl(psd->sacl,
 868                                         &saclp, &ignore_aces, snum))
 869                                         return NT_STATUS_ACCESS_DENIED;
 870 
 871                                 if (ignore_aces == true) {
 872                                         *security_info_effective &=
 873                                             ~SACL_SECURITY_INFORMATION;
 874                                 }
 875                         }
 876                 }
 877         }
 878 
 879         /* Setup ifs_security_descriptor */
 880         DEBUG(5,("Setting up SD\n"));
 881         if (aclu_initialize_sd(sd, psd->type, ownerp, groupp,
 882                 (daclp ? &daclp : NULL), (saclp ? &saclp : NULL), false))
 883                 return NT_STATUS_ACCESS_DENIED;
 884 
 885         DEBUG(10, ("sec_info_sent: 0x%x, sec_info_effective: 0x%x.\n",
 886                    security_info_sent, *security_info_effective));
 887 
 888         return NT_STATUS_OK;
 889 }
 890 
 891 /**
 892  * Isilon-specific function for setting an NTFS ACL on an open file.
 893  *
 894  * @return NT_STATUS_UNSUCCESSFUL for userspace errors, NTSTATUS based off
 895  * errno on syscall errors
 896  */
 897 NTSTATUS
 898 onefs_fset_nt_acl(vfs_handle_struct *handle, files_struct *fsp,
     /* [<][>][^][v][top][bottom][index][help] */
 899                   uint32_t sec_info_sent, SEC_DESC *psd)
 900 {
 901         struct ifs_security_descriptor sd = {};
 902         int fd = -1;
 903         bool fopened = false;
 904         NTSTATUS status;
 905         uint32_t sec_info_effective = 0;
 906 
 907         START_PROFILE(syscall_set_sd);
 908 
 909         DEBUG(5,("Setting SD on file %s.\n", fsp->fsp_name ));
 910 
 911         status = onefs_samba_sd_to_sd(sec_info_sent, psd, &sd,
 912                                       SNUM(handle->conn), &sec_info_effective);
 913 
 914         if (!NT_STATUS_IS_OK(status)) {
 915                 DEBUG(3, ("SD initialization failure: %s\n", nt_errstr(status)));
 916                 goto out;
 917         }
 918 
 919         fd = fsp->fh->fd;
 920         if (fd == -1) {
 921                 DEBUG(10,("Reopening file %s.\n", fsp->fsp_name));
 922                 if ((fd = onefs_sys_create_file(handle->conn,
 923                                                 -1,
 924                                                 fsp->fsp_name,
 925                                                 0,
 926                                                 0,
 927                                                 0,
 928                                                 0,
 929                                                 0,
 930                                                 0,
 931                                                 INTERNAL_OPEN_ONLY,
 932                                                 0,
 933                                                 NULL,
 934                                                 0,
 935                                                 NULL)) == -1) {
 936                         DEBUG(0, ("Error opening file %s. errno=%d (%s)\n",
 937                                   fsp->fsp_name, errno, strerror(errno)));
 938                         status = map_nt_error_from_unix(errno);
 939                         goto out;
 940                 }
 941                 fopened = true;
 942         }
 943 
 944         errno = 0;
 945         if (ifs_set_security_descriptor(fd, sec_info_effective, &sd)) {
 946                 DEBUG(0, ("Error setting security descriptor = %s\n",
 947                           strerror(errno)));
 948                 status = map_nt_error_from_unix(errno);
 949                 goto out;
 950         }
 951 
 952         DEBUG(5, ("Security descriptor set correctly!\n"));
 953         status = NT_STATUS_OK;
 954 
 955         /* FALLTHROUGH */
 956 out:
 957         END_PROFILE(syscall_set_sd);
 958 
 959         if (fopened)
 960                 close(fd);
 961 
 962         aclu_free_sd(&sd, false);
 963         return status;
 964 }

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