root/source3/modules/vfs_solarisacl.c

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

DEFINITIONS

This source file includes following definitions.
  1. solarisacl_sys_acl_get_file
  2. solarisacl_sys_acl_get_fd
  3. solarisacl_sys_acl_set_file
  4. solarisacl_sys_acl_set_fd
  5. solarisacl_sys_acl_delete_def_file
  6. solaris_acl_init
  7. smb_acl_to_solaris_acl
  8. solaris_acl_to_smb_acl
  9. smb_tag_to_solaris_tag
  10. solaris_tag_to_smb_tag
  11. solaris_perm_to_smb_perm
  12. smb_perm_to_solaris_perm
  13. solaris_acl_get_file
  14. solaris_acl_get_fd
  15. solaris_add_to_acl
  16. solaris_acl_sort
  17. solaris_acl_check
  18. vfs_solarisacl_init

   1 /*
   2    Unix SMB/Netbios implementation.
   3    VFS module to get and set Solaris ACLs
   4    Copyright (C) Michael Adam 2006,2008
   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 
  21 #include "includes.h"
  22 
  23 
  24 /* typedef struct acl SOLARIS_ACE_T; */
  25 typedef aclent_t SOLARIS_ACE_T;
  26 typedef aclent_t *SOLARIS_ACL_T;
  27 typedef int SOLARIS_ACL_TAG_T;   /* the type of an ACL entry */
  28 typedef o_mode_t SOLARIS_PERM_T;
  29 
  30 /* for convenience: check if solaris acl entry is a default entry?  */
  31 #define _IS_DEFAULT(ace) ((ace).a_type & ACL_DEFAULT)
  32 #define _IS_OF_TYPE(ace, type) ( \
  33         (((type) == SMB_ACL_TYPE_ACCESS) && !_IS_DEFAULT(ace)) \
  34         || \
  35         (((type) == SMB_ACL_TYPE_DEFAULT) && _IS_DEFAULT(ace)) \
  36 )
  37 
  38 
  39 /* prototypes for private functions */
  40 
  41 static SOLARIS_ACL_T solaris_acl_init(int count);
  42 static bool smb_acl_to_solaris_acl(SMB_ACL_T smb_acl, 
  43                 SOLARIS_ACL_T *solariacl, int *count, 
  44                 SMB_ACL_TYPE_T type);
  45 static SMB_ACL_T solaris_acl_to_smb_acl(SOLARIS_ACL_T solarisacl, int count,
  46                 SMB_ACL_TYPE_T type);
  47 static SOLARIS_ACL_TAG_T smb_tag_to_solaris_tag(SMB_ACL_TAG_T smb_tag);
  48 static SMB_ACL_TAG_T solaris_tag_to_smb_tag(SOLARIS_ACL_TAG_T solaris_tag);
  49 static bool solaris_add_to_acl(SOLARIS_ACL_T *solaris_acl, int *count,
  50                 SOLARIS_ACL_T add_acl, int add_count, SMB_ACL_TYPE_T type);
  51 static bool solaris_acl_get_file(const char *name, SOLARIS_ACL_T *solarisacl, 
  52                 int *count);
  53 static bool solaris_acl_get_fd(int fd, SOLARIS_ACL_T *solarisacl, int *count);
  54 static bool solaris_acl_sort(SOLARIS_ACL_T theacl, int count);
  55 static SMB_ACL_PERM_T solaris_perm_to_smb_perm(const SOLARIS_PERM_T perm);
  56 static SOLARIS_PERM_T smb_perm_to_solaris_perm(const SMB_ACL_PERM_T perm);
  57 #if 0
  58 static bool solaris_acl_check(SOLARIS_ACL_T solaris_acl, int count);
  59 #endif
  60 
  61 /* public functions - the api */
  62 
  63 SMB_ACL_T solarisacl_sys_acl_get_file(vfs_handle_struct *handle,
     /* [<][>][^][v][top][bottom][index][help] */
  64                                       const char *path_p,
  65                                       SMB_ACL_TYPE_T type)
  66 {
  67         SMB_ACL_T result = NULL;
  68         int count;
  69         SOLARIS_ACL_T solaris_acl = NULL;
  70         
  71         DEBUG(10, ("solarisacl_sys_acl_get_file called for file '%s'.\n", 
  72                    path_p));
  73 
  74         if (type != SMB_ACL_TYPE_ACCESS && type != SMB_ACL_TYPE_DEFAULT) {
  75                 DEBUG(10, ("invalid SMB_ACL_TYPE given (%d)\n", type));
  76                 errno = EINVAL;
  77                 goto done;
  78         }
  79 
  80         DEBUGADD(10, ("getting %s acl\n", 
  81                       ((type == SMB_ACL_TYPE_ACCESS) ? "access" : "default")));
  82 
  83         if (!solaris_acl_get_file(path_p, &solaris_acl, &count)) {
  84                 goto done;
  85         }
  86         result = solaris_acl_to_smb_acl(solaris_acl, count, type);
  87         if (result == NULL) {
  88                 DEBUG(10, ("conversion solaris_acl -> smb_acl failed (%s).\n",
  89                            strerror(errno)));
  90         }
  91         
  92  done:
  93         DEBUG(10, ("solarisacl_sys_acl_get_file %s.\n",
  94                    ((result == NULL) ? "failed" : "succeeded" )));
  95         SAFE_FREE(solaris_acl);
  96         return result;
  97 }
  98 
  99 
 100 /*
 101  * get the access ACL of a file referred to by a fd
 102  */
 103 SMB_ACL_T solarisacl_sys_acl_get_fd(vfs_handle_struct *handle,
     /* [<][>][^][v][top][bottom][index][help] */
 104                                     files_struct *fsp)
 105 {
 106         SMB_ACL_T result = NULL;
 107         int count;
 108         SOLARIS_ACL_T solaris_acl = NULL;
 109 
 110         DEBUG(10, ("entering solarisacl_sys_acl_get_fd.\n"));
 111 
 112         if (!solaris_acl_get_fd(fsp->fh->fd, &solaris_acl, &count)) {
 113                 goto done;
 114         }
 115         /* 
 116          * The facl call returns both ACCESS and DEFAULT acls (as present). 
 117          * The posix acl_get_fd function returns only the
 118          * access acl. So we need to filter this out here.  
 119          */
 120         result = solaris_acl_to_smb_acl(solaris_acl, count,
 121                                         SMB_ACL_TYPE_ACCESS);
 122         if (result == NULL) {
 123                 DEBUG(10, ("conversion solaris_acl -> smb_acl failed (%s).\n",
 124                            strerror(errno)));
 125         }
 126         
 127  done:
 128         DEBUG(10, ("solarisacl_sys_acl_get_fd %s.\n", 
 129                    ((result == NULL) ? "failed" : "succeeded")));
 130         SAFE_FREE(solaris_acl);
 131         return result;
 132 }
 133 
 134 int solarisacl_sys_acl_set_file(vfs_handle_struct *handle,
     /* [<][>][^][v][top][bottom][index][help] */
 135                                 const char *name,
 136                                 SMB_ACL_TYPE_T type,
 137                                 SMB_ACL_T theacl)
 138 {
 139         int ret = -1;
 140         struct stat s;
 141         SOLARIS_ACL_T solaris_acl = NULL;
 142         int count;
 143         
 144         DEBUG(10, ("solarisacl_sys_acl_set_file called for file '%s'\n",
 145                    name));
 146 
 147         if ((type != SMB_ACL_TYPE_ACCESS) && (type != SMB_ACL_TYPE_DEFAULT)) {
 148                 errno = EINVAL;
 149                 DEBUG(10, ("invalid smb acl type given (%d).\n", type));
 150                 goto done;
 151         }
 152         DEBUGADD(10, ("setting %s acl\n", 
 153                       ((type == SMB_ACL_TYPE_ACCESS) ? "access" : "default")));
 154 
 155         if(!smb_acl_to_solaris_acl(theacl, &solaris_acl, &count, type)) {
 156                 DEBUG(10, ("conversion smb_acl -> solaris_acl failed (%s).\n",
 157                            strerror(errno)));
 158                 goto done;
 159         }
 160 
 161         /*
 162          * if the file is a directory, there is extra work to do:
 163          * since the solaris acl call stores both the access acl and 
 164          * the default acl as provided, we have to get the acl part 
 165          * that has not been specified in "type" from the file first 
 166          * and concatenate it with the acl provided.
 167          */
 168         if (SMB_VFS_STAT(handle->conn, name, &s) != 0) {
 169                 DEBUG(10, ("Error in stat call: %s\n", strerror(errno)));
 170                 goto done;
 171         }
 172         if (S_ISDIR(s.st_mode)) {
 173                 SOLARIS_ACL_T other_acl; 
 174                 int other_count;
 175                 SMB_ACL_TYPE_T other_type;
 176 
 177                 other_type = (type == SMB_ACL_TYPE_ACCESS) 
 178                         ? SMB_ACL_TYPE_DEFAULT
 179                         : SMB_ACL_TYPE_ACCESS;
 180                 DEBUGADD(10, ("getting acl from filesystem\n"));
 181                 if (!solaris_acl_get_file(name, &other_acl, &other_count)) {
 182                         DEBUG(10, ("error getting acl from directory\n"));
 183                         goto done;
 184                 }
 185                 DEBUG(10, ("adding %s part of fs acl to given acl\n",
 186                            ((other_type == SMB_ACL_TYPE_ACCESS) 
 187                             ? "access"
 188                             : "default")));
 189                 if (!solaris_add_to_acl(&solaris_acl, &count, other_acl,
 190                                         other_count, other_type)) 
 191                 {
 192                         DEBUG(10, ("error adding other acl.\n"));
 193                         SAFE_FREE(other_acl);
 194                         goto done;
 195                 }
 196                 SAFE_FREE(other_acl);
 197         }
 198         else if (type != SMB_ACL_TYPE_ACCESS) {
 199                 errno = EINVAL;
 200                 goto done;
 201         }
 202 
 203         if (!solaris_acl_sort(solaris_acl, count)) {
 204                 DEBUG(10, ("resulting acl is not valid!\n"));
 205                 goto done;
 206         }
 207 
 208         ret = acl(name, SETACL, count, solaris_acl);
 209         
 210  done:
 211         DEBUG(10, ("solarisacl_sys_acl_set_file %s.\n",
 212                    ((ret != 0) ? "failed" : "succeeded")));
 213         SAFE_FREE(solaris_acl);
 214         return ret;
 215 }
 216 
 217 /*
 218  * set the access ACL on the file referred to by a fd 
 219  */
 220 int solarisacl_sys_acl_set_fd(vfs_handle_struct *handle,
     /* [<][>][^][v][top][bottom][index][help] */
 221                               files_struct *fsp,
 222                               SMB_ACL_T theacl)
 223 {
 224         SOLARIS_ACL_T solaris_acl = NULL;
 225         SOLARIS_ACL_T default_acl = NULL;
 226         int count, default_count;
 227         int ret = -1;
 228 
 229         DEBUG(10, ("entering solarisacl_sys_acl_set_fd\n"));
 230 
 231         /* 
 232          * the posix acl_set_fd call sets the access acl of the
 233          * file referred to by fd. the solaris facl-SETACL call
 234          * sets the access and default acl as provided, so we
 235          * have to retrieve the default acl of the file and 
 236          * concatenate it with the access acl provided.
 237          */
 238         if (!smb_acl_to_solaris_acl(theacl, &solaris_acl, &count, 
 239                                     SMB_ACL_TYPE_ACCESS))
 240         {
 241                 DEBUG(10, ("conversion smb_acl -> solaris_acl failed (%s).\n",
 242                            strerror(errno)));
 243                 goto done;
 244         }
 245         if (!solaris_acl_get_fd(fsp->fh->fd, &default_acl, &default_count)) {
 246                 DEBUG(10, ("error getting (default) acl from fd\n"));
 247                 goto done;
 248         }
 249         if (!solaris_add_to_acl(&solaris_acl, &count,
 250                                 default_acl, default_count,
 251                                 SMB_ACL_TYPE_DEFAULT))
 252         {
 253                 DEBUG(10, ("error adding default acl to solaris acl\n"));
 254                 goto done;
 255         }
 256         if (!solaris_acl_sort(solaris_acl, count)) {
 257                 DEBUG(10, ("resulting acl is not valid!\n"));
 258                 goto done;
 259         }
 260 
 261         ret = facl(fsp->fh->fd, SETACL, count, solaris_acl);
 262         if (ret != 0) {
 263                 DEBUG(10, ("call of facl failed (%s).\n", strerror(errno)));
 264         }
 265 
 266  done:
 267         DEBUG(10, ("solarisacl_sys_acl_set_fd %s.\n",
 268                    ((ret == 0) ? "succeeded" : "failed" )));
 269         SAFE_FREE(solaris_acl);
 270         SAFE_FREE(default_acl);
 271         return ret;
 272 }
 273 
 274 /*
 275  * delete the default ACL of a directory
 276  *
 277  * This is achieved by fetching the access ACL and rewriting it 
 278  * directly, via the solaris system call: the SETACL call on 
 279  * directories writes both the access and the default ACL as provided.
 280  *
 281  * XXX: posix acl_delete_def_file returns an error if
 282  * the file referred to by path is not a directory.
 283  * this function does not complain but the actions 
 284  * have no effect on a file other than a directory.
 285  * But sys_acl_delete_default_file is only called in
 286  * smbd/posixacls.c after having checked that the file
 287  * is a directory, anyways. So implementing the extra
 288  * check is considered unnecessary. --- Agreed? XXX
 289  */
 290 int solarisacl_sys_acl_delete_def_file(vfs_handle_struct *handle,
     /* [<][>][^][v][top][bottom][index][help] */
 291                                        const char *path)
 292 {
 293         SMB_ACL_T smb_acl;
 294         int ret = -1;
 295         SOLARIS_ACL_T solaris_acl = NULL;
 296         int count;
 297 
 298         DEBUG(10, ("entering solarisacl_sys_acl_delete_def_file.\n"));
 299         
 300         smb_acl = solarisacl_sys_acl_get_file(handle, path, 
 301                                               SMB_ACL_TYPE_ACCESS);
 302         if (smb_acl == NULL) {
 303                 DEBUG(10, ("getting file acl failed!\n"));
 304                 goto done;
 305         }
 306         if (!smb_acl_to_solaris_acl(smb_acl, &solaris_acl, &count, 
 307                                     SMB_ACL_TYPE_ACCESS))
 308         {
 309                 DEBUG(10, ("conversion smb_acl -> solaris_acl failed.\n"));
 310                 goto done;
 311         }
 312         if (!solaris_acl_sort(solaris_acl, count)) {
 313                 DEBUG(10, ("resulting acl is not valid!\n"));
 314                 goto done;
 315         }
 316         ret = acl(path, SETACL, count, solaris_acl);
 317         if (ret != 0) {
 318                 DEBUG(10, ("settinge file acl failed!\n"));
 319         }
 320         
 321  done:
 322         DEBUG(10, ("solarisacl_sys_acl_delete_def_file %s.\n",
 323                    ((ret != 0) ? "failed" : "succeeded" )));
 324         SAFE_FREE(smb_acl);
 325         return ret;
 326 }
 327 
 328 
 329 /* private functions */
 330 
 331 static SOLARIS_ACL_T solaris_acl_init(int count)
     /* [<][>][^][v][top][bottom][index][help] */
 332 {
 333         SOLARIS_ACL_T solaris_acl = 
 334                 (SOLARIS_ACL_T)SMB_MALLOC(sizeof(aclent_t) * count);
 335         if (solaris_acl == NULL) {
 336                 errno = ENOMEM;
 337         }
 338         return solaris_acl;
 339 }
 340 
 341 /*
 342  * Convert the SMB acl to the ACCESS or DEFAULT part of a 
 343  * solaris ACL, as desired.
 344  */
 345 static bool smb_acl_to_solaris_acl(SMB_ACL_T smb_acl, 
     /* [<][>][^][v][top][bottom][index][help] */
 346                                    SOLARIS_ACL_T *solaris_acl, int *count, 
 347                                    SMB_ACL_TYPE_T type)
 348 {
 349         bool ret = False;
 350         int i;
 351 
 352         DEBUG(10, ("entering smb_acl_to_solaris_acl\n"));
 353         
 354         *solaris_acl = NULL;
 355         *count = 0;
 356 
 357         for (i = 0; i < smb_acl->count; i++) {
 358                 const struct smb_acl_entry *smb_entry = &(smb_acl->acl[i]);
 359                 SOLARIS_ACE_T solaris_entry;
 360 
 361                 ZERO_STRUCT(solaris_entry);
 362 
 363                 solaris_entry.a_type = smb_tag_to_solaris_tag(smb_entry->a_type);
 364                 if (solaris_entry.a_type == 0) {
 365                         DEBUG(10, ("smb_tag to solaris_tag failed\n"));
 366                         goto fail;
 367                 }
 368                 switch(solaris_entry.a_type) {
 369                 case USER:
 370                         DEBUG(10, ("got tag type USER with uid %u\n", 
 371                                    (unsigned int)smb_entry->uid));
 372                         solaris_entry.a_id = (uid_t)smb_entry->uid;
 373                         break;
 374                 case GROUP:
 375                         DEBUG(10, ("got tag type GROUP with gid %u\n", 
 376                                    (unsigned int)smb_entry->gid));
 377                         solaris_entry.a_id = (uid_t)smb_entry->gid;
 378                         break;
 379                 default:
 380                         break;
 381                 }
 382                 if (type == SMB_ACL_TYPE_DEFAULT) {
 383                         DEBUG(10, ("adding default bit to solaris ace\n"));
 384                         solaris_entry.a_type |= ACL_DEFAULT;
 385                 }
 386                 
 387                 solaris_entry.a_perm = 
 388                         smb_perm_to_solaris_perm(smb_entry->a_perm);
 389                 DEBUG(10, ("assembled the following solaris ace:\n"));
 390                 DEBUGADD(10, (" - type: 0x%04x\n", solaris_entry.a_type));
 391                 DEBUGADD(10, (" - id: %u\n", (unsigned int)solaris_entry.a_id));
 392                 DEBUGADD(10, (" - perm: o%o\n", solaris_entry.a_perm));
 393                 if (!solaris_add_to_acl(solaris_acl, count, &solaris_entry, 
 394                                         1, type))
 395                 {
 396                         DEBUG(10, ("error adding acl entry\n"));
 397                         goto fail;
 398                 }
 399                 DEBUG(10, ("count after adding: %d (i: %d)\n", *count, i));
 400                 DEBUG(10, ("test, if entry has been copied into acl:\n"));
 401                 DEBUGADD(10, (" - type: 0x%04x\n",
 402                               (*solaris_acl)[(*count)-1].a_type));
 403                 DEBUGADD(10, (" - id: %u\n",
 404                               (unsigned int)(*solaris_acl)[(*count)-1].a_id));
 405                 DEBUGADD(10, (" - perm: o%o\n",
 406                               (*solaris_acl)[(*count)-1].a_perm));
 407         }
 408 
 409         ret = True;
 410         goto done;
 411         
 412  fail:
 413         SAFE_FREE(*solaris_acl);
 414  done:
 415         DEBUG(10, ("smb_acl_to_solaris_acl %s\n",
 416                    ((ret == True) ? "succeeded" : "failed")));
 417         return ret;
 418 }
 419 
 420 /* 
 421  * convert either the access or the default part of a 
 422  * soaris acl to the SMB_ACL format.
 423  */
 424 static SMB_ACL_T solaris_acl_to_smb_acl(SOLARIS_ACL_T solaris_acl, int count, 
     /* [<][>][^][v][top][bottom][index][help] */
 425                                         SMB_ACL_TYPE_T type)
 426 {
 427         SMB_ACL_T result;
 428         int i;
 429 
 430         if ((result = sys_acl_init(0)) == NULL) {
 431                 DEBUG(10, ("error allocating memory for SMB_ACL\n"));
 432                 goto fail;
 433         }
 434         for (i = 0; i < count; i++) {
 435                 SMB_ACL_ENTRY_T smb_entry;
 436                 SMB_ACL_PERM_T smb_perm;
 437                 
 438                 if (!_IS_OF_TYPE(solaris_acl[i], type)) {
 439                         continue;
 440                 }
 441                 result = SMB_REALLOC(result, 
 442                                      sizeof(struct smb_acl_t) +
 443                                      (sizeof(struct smb_acl_entry) *
 444                                       (result->count + 1)));
 445                 if (result == NULL) {
 446                         DEBUG(10, ("error reallocating memory for SMB_ACL\n"));
 447                         goto fail;
 448                 }
 449                 smb_entry = &result->acl[result->count];
 450                 if (sys_acl_set_tag_type(smb_entry,
 451                                          solaris_tag_to_smb_tag(solaris_acl[i].a_type)) != 0)
 452                 {
 453                         DEBUG(10, ("invalid tag type given: 0x%04x\n",
 454                                    solaris_acl[i].a_type));
 455                         goto fail;
 456                 }
 457                 /* intentionally not checking return code here: */
 458                 sys_acl_set_qualifier(smb_entry, (void *)&solaris_acl[i].a_id);
 459                 smb_perm = solaris_perm_to_smb_perm(solaris_acl[i].a_perm);
 460                 if (sys_acl_set_permset(smb_entry, &smb_perm) != 0) {
 461                         DEBUG(10, ("invalid permset given: %d\n", 
 462                                    solaris_acl[i].a_perm));
 463                         goto fail;
 464                 }
 465                 result->count += 1;
 466         }
 467         goto done;
 468         
 469  fail:
 470         SAFE_FREE(result);
 471  done:
 472         DEBUG(10, ("solaris_acl_to_smb_acl %s\n",
 473                    ((result == NULL) ? "failed" : "succeeded")));
 474         return result;
 475 }
 476 
 477 
 478 
 479 static SOLARIS_ACL_TAG_T smb_tag_to_solaris_tag(SMB_ACL_TAG_T smb_tag)
     /* [<][>][^][v][top][bottom][index][help] */
 480 {
 481         SOLARIS_ACL_TAG_T solaris_tag = 0;
 482 
 483         DEBUG(10, ("smb_tag_to_solaris_tag\n"));
 484         DEBUGADD(10, (" --> got smb tag 0x%04x\n", smb_tag));
 485         
 486         switch (smb_tag) {
 487         case SMB_ACL_USER:
 488                 solaris_tag = USER;
 489                 break;
 490         case SMB_ACL_USER_OBJ:
 491                 solaris_tag = USER_OBJ;
 492                 break;
 493         case SMB_ACL_GROUP:
 494                 solaris_tag = GROUP;
 495                 break;
 496         case SMB_ACL_GROUP_OBJ:
 497                 solaris_tag = GROUP_OBJ;
 498                 break;
 499         case SMB_ACL_OTHER:
 500                 solaris_tag = OTHER_OBJ;
 501                 break;
 502         case SMB_ACL_MASK:
 503                 solaris_tag = CLASS_OBJ;
 504                 break;
 505         default:
 506                 DEBUGADD(10, (" !!! unknown smb tag type 0x%04x\n", smb_tag));
 507                 break;
 508         }
 509         
 510         DEBUGADD(10, (" --> determined solaris tag 0x%04x\n", solaris_tag));
 511 
 512         return solaris_tag;
 513 }
 514 
 515 static SMB_ACL_TAG_T solaris_tag_to_smb_tag(SOLARIS_ACL_TAG_T solaris_tag)
     /* [<][>][^][v][top][bottom][index][help] */
 516 {
 517         SMB_ACL_TAG_T smb_tag = 0;
 518 
 519         DEBUG(10, ("solaris_tag_to_smb_tag:\n"));
 520         DEBUGADD(10, (" --> got solaris tag 0x%04x\n", solaris_tag)); 
 521         
 522         solaris_tag &= ~ACL_DEFAULT; 
 523 
 524         switch (solaris_tag) {
 525         case USER:
 526                 smb_tag = SMB_ACL_USER;
 527                 break;
 528         case USER_OBJ:
 529                 smb_tag = SMB_ACL_USER_OBJ;
 530                 break;
 531         case GROUP:
 532                 smb_tag = SMB_ACL_GROUP;
 533                 break;
 534         case GROUP_OBJ:
 535                 smb_tag = SMB_ACL_GROUP_OBJ;
 536                 break;
 537         case OTHER_OBJ:
 538                 smb_tag = SMB_ACL_OTHER;
 539                 break;
 540         case CLASS_OBJ:
 541                 smb_tag = SMB_ACL_MASK;
 542                 break;
 543         default:
 544                 DEBUGADD(10, (" !!! unknown solaris tag type: 0x%04x\n", 
 545                                         solaris_tag));
 546                 break;
 547         }
 548 
 549         DEBUGADD(10, (" --> determined smb tag 0x%04x\n", smb_tag));
 550         
 551         return smb_tag;
 552 }
 553 
 554 
 555 static SMB_ACL_PERM_T solaris_perm_to_smb_perm(const SOLARIS_PERM_T perm)
     /* [<][>][^][v][top][bottom][index][help] */
 556 {
 557         SMB_ACL_PERM_T smb_perm = 0;
 558         smb_perm |= ((perm & SMB_ACL_READ) ? SMB_ACL_READ : 0);
 559         smb_perm |= ((perm & SMB_ACL_WRITE) ? SMB_ACL_WRITE : 0);
 560         smb_perm |= ((perm & SMB_ACL_EXECUTE) ? SMB_ACL_EXECUTE : 0);
 561         return smb_perm;
 562 }
 563 
 564 
 565 static SOLARIS_PERM_T smb_perm_to_solaris_perm(const SMB_ACL_PERM_T perm)
     /* [<][>][^][v][top][bottom][index][help] */
 566 {
 567         SOLARIS_PERM_T solaris_perm = 0;
 568         solaris_perm |= ((perm & SMB_ACL_READ) ? SMB_ACL_READ : 0);
 569         solaris_perm |= ((perm & SMB_ACL_WRITE) ? SMB_ACL_WRITE : 0);
 570         solaris_perm |= ((perm & SMB_ACL_EXECUTE) ? SMB_ACL_EXECUTE : 0);
 571         return solaris_perm;
 572 }
 573 
 574 
 575 static bool solaris_acl_get_file(const char *name, SOLARIS_ACL_T *solaris_acl, 
     /* [<][>][^][v][top][bottom][index][help] */
 576                                  int *count)
 577 {
 578         bool result = False;
 579 
 580         DEBUG(10, ("solaris_acl_get_file called for file '%s'\n", name));
 581         
 582         /* 
 583          * The original code tries some INITIAL_ACL_SIZE
 584          * and only did the GETACLCNT call upon failure
 585          * (for performance reasons).
 586          * For the sake of simplicity, I skip this for now. 
 587          */
 588         *count = acl(name, GETACLCNT, 0, NULL);
 589         if (*count < 0) {
 590                 DEBUG(10, ("acl GETACLCNT failed: %s\n", strerror(errno)));
 591                 goto done;
 592         }
 593         *solaris_acl = solaris_acl_init(*count);
 594         if (*solaris_acl == NULL) {
 595                 DEBUG(10, ("error allocating memory for solaris acl...\n"));
 596                 goto done;
 597         }
 598         *count = acl(name, GETACL, *count, *solaris_acl);
 599         if (*count < 0) {
 600                 DEBUG(10, ("acl GETACL failed: %s\n", strerror(errno)));
 601                 goto done;
 602         }
 603         result = True;
 604 
 605  done:
 606         DEBUG(10, ("solaris_acl_get_file %s.\n",
 607                    ((result == True) ? "succeeded" : "failed" )));
 608         return result;
 609 }
 610 
 611 
 612 static bool solaris_acl_get_fd(int fd, SOLARIS_ACL_T *solaris_acl, int *count)
     /* [<][>][^][v][top][bottom][index][help] */
 613 {
 614         bool ret = False;
 615 
 616         DEBUG(10, ("entering solaris_acl_get_fd\n"));
 617 
 618         /* 
 619          * see solaris_acl_get_file for comment about omission 
 620          * of INITIAL_ACL_SIZE... 
 621          */
 622         *count = facl(fd, GETACLCNT, 0, NULL);
 623         if (*count < 0) {
 624                 DEBUG(10, ("facl GETACLCNT failed: %s\n", strerror(errno)));
 625                 goto done;
 626         }
 627         *solaris_acl = solaris_acl_init(*count);
 628         if (*solaris_acl == NULL) {
 629                 DEBUG(10, ("error allocating memory for solaris acl...\n"));
 630                 goto done;
 631         }
 632         *count = facl(fd, GETACL, *count, *solaris_acl);
 633         if (*count < 0) {
 634                 DEBUG(10, ("facl GETACL failed: %s\n", strerror(errno)));
 635                 goto done;
 636         }
 637         ret = True;
 638 
 639  done:
 640         DEBUG(10, ("solaris_acl_get_fd %s\n",
 641                    ((ret == True) ? "succeeded" : "failed")));
 642         return ret;
 643 }
 644 
 645 
 646 
 647 /*
 648  * Add entries to a solaris ACL.
 649  *
 650  * Entries are directly added to the solarisacl parameter.
 651  * if memory allocation fails, this may result in solarisacl 
 652  * being NULL. if the resulting acl is to be checked and is 
 653  * not valid, it is kept in solarisacl but False is returned.
 654  *
 655  * The type of ACEs (access/default) to be added to the ACL can 
 656  * be selected via the type parameter. 
 657  * I use the SMB_ACL_TYPE_T type here. Since SMB_ACL_TYPE_ACCESS
 658  * is defined as "0", this means that one can only add either
 659  * access or default ACEs, not both at the same time. If it 
 660  * should become necessary to add all of an ACL, one would have
 661  * to replace this parameter by another type.
 662  */
 663 static bool solaris_add_to_acl(SOLARIS_ACL_T *solaris_acl, int *count,
     /* [<][>][^][v][top][bottom][index][help] */
 664                                SOLARIS_ACL_T add_acl, int add_count, 
 665                                SMB_ACL_TYPE_T type)
 666 {
 667         int i;
 668         
 669         if ((type != SMB_ACL_TYPE_ACCESS) && (type != SMB_ACL_TYPE_DEFAULT)) 
 670         {
 671                 DEBUG(10, ("invalid acl type given: %d\n", type));
 672                 errno = EINVAL;
 673                 return False;
 674         }
 675         for (i = 0; i < add_count; i++) {
 676                 if (!_IS_OF_TYPE(add_acl[i], type)) {
 677                         continue;
 678                 }
 679                 ADD_TO_ARRAY(NULL, SOLARIS_ACE_T, add_acl[i], 
 680                              solaris_acl, count);
 681                 if (solaris_acl == NULL) {
 682                         DEBUG(10, ("error enlarging acl.\n"));
 683                         errno = ENOMEM;
 684                         return False;
 685                 }
 686         }
 687         return True;
 688 }
 689 
 690 
 691 /* 
 692  * sort the ACL and check it for validity
 693  *
 694  * [original comment from lib/sysacls.c:]
 695  * 
 696  * if it's a minimal ACL with only 4 entries then we
 697  * need to recalculate the mask permissions to make
 698  * sure that they are the same as the GROUP_OBJ
 699  * permissions as required by the UnixWare acl() system call.
 700  *
 701  * (note: since POSIX allows minimal ACLs which only contain
 702  * 3 entries - ie there is no mask entry - we should, in theory,
 703  * check for this and add a mask entry if necessary - however
 704  * we "know" that the caller of this interface always specifies
 705  * a mask, so in practice "this never happens" (tm) - if it *does*
 706  * happen aclsort() will fail and return an error and someone will
 707  * have to fix it...)
 708  */
 709 static bool solaris_acl_sort(SOLARIS_ACL_T solaris_acl, int count)
     /* [<][>][^][v][top][bottom][index][help] */
 710 {
 711         int fixmask = (count <= 4);
 712 
 713         if (aclsort(count, fixmask, solaris_acl) != 0) {
 714                 errno = EINVAL;
 715                 return False;
 716         }
 717         return True;
 718 }
 719 
 720 #if 0
 721 /*
 722  * acl check function:
 723  *   unused at the moment but could be used to get more
 724  *   concrete error messages for debugging...
 725  *   (acl sort just says that the acl is invalid...)
 726  */
 727 static bool solaris_acl_check(SOLARIS_ACL_T solaris_acl, int count)
     /* [<][>][^][v][top][bottom][index][help] */
 728 {
 729         int check_rc;
 730         int check_which;
 731         
 732         check_rc = aclcheck(solaris_acl, count, &check_which);
 733         if (check_rc != 0) {
 734                 DEBUG(10, ("acl is not valid:\n"));
 735                 DEBUGADD(10, (" - return code: %d\n", check_rc));
 736                 DEBUGADD(10, (" - which: %d\n", check_which));
 737                 if (check_which != -1) {
 738                         DEBUGADD(10, (" - invalid entry:\n"));
 739                         DEBUGADD(10, ("   * type: %d:\n", 
 740                                       solaris_acl[check_which].a_type));
 741                         DEBUGADD(10, ("   * id: %d\n",
 742                                       solaris_acl[check_which].a_id));
 743                         DEBUGADD(10, ("   * perm: 0o%o\n",
 744                                       solaris_acl[check_which].a_perm));
 745                 }
 746                 return False;
 747         }
 748         return True;
 749 }
 750 #endif
 751 
 752 /* VFS operations structure */
 753 
 754 static vfs_op_tuple solarisacl_op_tuples[] = {
 755         /* Disk operations */
 756         {SMB_VFS_OP(solarisacl_sys_acl_get_file),
 757          SMB_VFS_OP_SYS_ACL_GET_FILE,
 758          SMB_VFS_LAYER_TRANSPARENT},
 759 
 760         {SMB_VFS_OP(solarisacl_sys_acl_get_fd),
 761          SMB_VFS_OP_SYS_ACL_GET_FD,
 762          SMB_VFS_LAYER_TRANSPARENT},
 763 
 764         {SMB_VFS_OP(solarisacl_sys_acl_set_file),
 765          SMB_VFS_OP_SYS_ACL_SET_FILE,
 766          SMB_VFS_LAYER_TRANSPARENT},
 767 
 768         {SMB_VFS_OP(solarisacl_sys_acl_set_fd),
 769          SMB_VFS_OP_SYS_ACL_SET_FD,
 770          SMB_VFS_LAYER_TRANSPARENT},
 771 
 772         {SMB_VFS_OP(solarisacl_sys_acl_delete_def_file),
 773          SMB_VFS_OP_SYS_ACL_DELETE_DEF_FILE,
 774          SMB_VFS_LAYER_TRANSPARENT},
 775 
 776         {SMB_VFS_OP(NULL),
 777          SMB_VFS_OP_NOOP,
 778          SMB_VFS_LAYER_NOOP}
 779 };
 780 
 781 NTSTATUS vfs_solarisacl_init(void);
 782 NTSTATUS vfs_solarisacl_init(void)
     /* [<][>][^][v][top][bottom][index][help] */
 783 {
 784         return smb_register_vfs(SMB_VFS_INTERFACE_VERSION, "solarisacl",
 785                                 solarisacl_op_tuples);
 786 }
 787 
 788 /* ENTE */

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