modules/vfs_solarisacl.c

説明を見る。
00001 /*
00002    Unix SMB/Netbios implementation.
00003    VFS module to get and set Solaris ACLs
00004    Copyright (C) Michael Adam 2006
00005 
00006    This program is free software; you can redistribute it and/or modify
00007    it under the terms of the GNU General Public License as published by
00008    the Free Software Foundation; either version 2 of the License, or
00009    (at your option) any later version.
00010 
00011    This program is distributed in the hope that it will be useful,
00012    but WITHOUT ANY WARRANTY; without even the implied warranty of
00013    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014    GNU General Public License for more details.
00015 
00016    You should have received a copy of the GNU General Public License
00017    along with this program; if not, write to the Free Software
00018    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
00019 */
00020 
00021 
00022 #include "includes.h"
00023 
00024 
00025 /* typedef struct acl SOLARIS_ACE_T; */
00026 typedef aclent_t SOLARIS_ACE_T;
00027 typedef aclent_t *SOLARIS_ACL_T;
00028 typedef int SOLARIS_ACL_TAG_T;   /* the type of an ACL entry */
00029 typedef o_mode_t SOLARIS_PERM_T;
00030 
00031 /* for convenience: check if solaris acl entry is a default entry?  */
00032 #define _IS_DEFAULT(ace) ((ace).a_type & ACL_DEFAULT)
00033 #define _IS_OF_TYPE(ace, type) ( \
00034         (((type) == SMB_ACL_TYPE_ACCESS) && !_IS_DEFAULT(ace)) \
00035         || \
00036         (((type) == SMB_ACL_TYPE_DEFAULT) && _IS_DEFAULT(ace)) \
00037 )
00038 
00039 
00040 /* prototypes for private functions */
00041 
00042 static SOLARIS_ACL_T solaris_acl_init(int count);
00043 static BOOL smb_acl_to_solaris_acl(SMB_ACL_T smb_acl, 
00044                 SOLARIS_ACL_T *solariacl, int *count, 
00045                 SMB_ACL_TYPE_T type);
00046 static SMB_ACL_T solaris_acl_to_smb_acl(SOLARIS_ACL_T solarisacl, int count,
00047                 SMB_ACL_TYPE_T type);
00048 static SOLARIS_ACL_TAG_T smb_tag_to_solaris_tag(SMB_ACL_TAG_T smb_tag);
00049 static SMB_ACL_TAG_T solaris_tag_to_smb_tag(SOLARIS_ACL_TAG_T solaris_tag);
00050 static BOOL solaris_add_to_acl(SOLARIS_ACL_T *solaris_acl, int *count,
00051                 SOLARIS_ACL_T add_acl, int add_count, SMB_ACL_TYPE_T type);
00052 static BOOL solaris_acl_get_file(const char *name, SOLARIS_ACL_T *solarisacl, 
00053                 int *count);
00054 static BOOL solaris_acl_get_fd(int fd, SOLARIS_ACL_T *solarisacl, int *count);
00055 static BOOL solaris_acl_sort(SOLARIS_ACL_T acl, int count);
00056 static SMB_ACL_PERM_T solaris_perm_to_smb_perm(const SOLARIS_PERM_T perm);
00057 static SOLARIS_PERM_T smb_perm_to_solaris_perm(const SMB_ACL_PERM_T perm);
00058 static BOOL solaris_acl_check(SOLARIS_ACL_T solaris_acl, int count);
00059 
00060 
00061 /* public functions - the api */
00062 
00063 SMB_ACL_T solarisacl_sys_acl_get_file(vfs_handle_struct *handle,
00064                                       const char *path_p,
00065                                       SMB_ACL_TYPE_T type)
00066 {
00067         SMB_ACL_T result = NULL;
00068         int count;
00069         SOLARIS_ACL_T solaris_acl = NULL;
00070         
00071         DEBUG(10, ("solarisacl_sys_acl_get_file called for file '%s'.\n", 
00072                    path_p));
00073 
00074         if (type != SMB_ACL_TYPE_ACCESS && type != SMB_ACL_TYPE_DEFAULT) {
00075                 DEBUG(10, ("invalid SMB_ACL_TYPE given (%d)\n", type));
00076                 errno = EINVAL;
00077                 goto done;
00078         }
00079 
00080         DEBUGADD(10, ("getting %s acl\n", 
00081                       ((type == SMB_ACL_TYPE_ACCESS) ? "access" : "default")));
00082 
00083         if (!solaris_acl_get_file(path_p, &solaris_acl, &count)) {
00084                 goto done;
00085         }
00086         result = solaris_acl_to_smb_acl(solaris_acl, count, type);
00087         if (result == NULL) {
00088                 DEBUG(10, ("conversion solaris_acl -> smb_acl failed (%s).\n",
00089                            strerror(errno)));
00090         }
00091         
00092  done:
00093         DEBUG(10, ("solarisacl_sys_acl_get_file %s.\n",
00094                    ((result == NULL) ? "failed" : "succeeded" )));
00095         SAFE_FREE(solaris_acl);
00096         return result;
00097 }
00098 
00099 
00100 /*
00101  * get the access ACL of a file referred to by a fd
00102  */
00103 SMB_ACL_T solarisacl_sys_acl_get_fd(vfs_handle_struct *handle,
00104                                     files_struct *fsp,
00105                                     int fd)
00106 {
00107         SMB_ACL_T result = NULL;
00108         int count;
00109         SOLARIS_ACL_T solaris_acl = NULL;
00110 
00111         DEBUG(10, ("entering solarisacl_sys_acl_get_fd.\n"));
00112 
00113         if (!solaris_acl_get_fd(fd, &solaris_acl, &count)) {
00114                 goto done;
00115         }
00116         /* 
00117          * The facl call returns both ACCESS and DEFAULT acls (as present). 
00118          * The posix acl_get_fd function returns only the
00119          * access acl. So we need to filter this out here.  
00120          */
00121         result = solaris_acl_to_smb_acl(solaris_acl, count,
00122                                         SMB_ACL_TYPE_ACCESS);
00123         if (result == NULL) {
00124                 DEBUG(10, ("conversion solaris_acl -> smb_acl failed (%s).\n",
00125                            strerror(errno)));
00126         }
00127         
00128  done:
00129         DEBUG(10, ("solarisacl_sys_acl_get_fd %s.\n", 
00130                    ((result == NULL) ? "failed" : "succeeded")));
00131         SAFE_FREE(solaris_acl);
00132         return result;
00133 }
00134 
00135 int solarisacl_sys_acl_set_file(vfs_handle_struct *handle,
00136                                 const char *name,
00137                                 SMB_ACL_TYPE_T type,
00138                                 SMB_ACL_T theacl)
00139 {
00140         int ret = -1;
00141         struct stat s;
00142         SOLARIS_ACL_T solaris_acl = NULL;
00143         int count;
00144         
00145         DEBUG(10, ("solarisacl_sys_acl_set_file called for file '%s'\n",
00146                    name));
00147 
00148         if ((type != SMB_ACL_TYPE_ACCESS) && (type != SMB_ACL_TYPE_DEFAULT)) {
00149                 errno = EINVAL;
00150                 DEBUG(10, ("invalid smb acl type given (%d).\n", type));
00151                 goto done;
00152         }
00153         DEBUGADD(10, ("setting %s acl\n", 
00154                       ((type == SMB_ACL_TYPE_ACCESS) ? "access" : "default")));
00155 
00156         if(!smb_acl_to_solaris_acl(theacl, &solaris_acl, &count, type)) {
00157                 DEBUG(10, ("conversion smb_acl -> solaris_acl failed (%s).\n",
00158                            strerror(errno)));
00159                 goto done;
00160         }
00161 
00162         /*
00163          * if the file is a directory, there is extra work to do:
00164          * since the solaris acl call stores both the access acl and 
00165          * the default acl as provided, we have to get the acl part 
00166          * that has not been specified in "type" from the file first 
00167          * and concatenate it with the acl provided.
00168          */
00169         if (SMB_VFS_STAT(handle->conn, name, &s) != 0) {
00170                 DEBUG(10, ("Error in stat call: %s\n", strerror(errno)));
00171                 goto done;
00172         }
00173         if (S_ISDIR(s.st_mode)) {
00174                 SOLARIS_ACL_T other_acl; 
00175                 int other_count;
00176                 SMB_ACL_TYPE_T other_type;
00177 
00178                 other_type = (type == SMB_ACL_TYPE_ACCESS) 
00179                         ? SMB_ACL_TYPE_DEFAULT
00180                         : SMB_ACL_TYPE_ACCESS;
00181                 DEBUGADD(10, ("getting acl from filesystem\n"));
00182                 if (!solaris_acl_get_file(name, &other_acl, &other_count)) {
00183                         DEBUG(10, ("error getting acl from directory\n"));
00184                         goto done;
00185                 }
00186                 DEBUG(10, ("adding %s part of fs acl to given acl\n",
00187                            ((other_type == SMB_ACL_TYPE_ACCESS) 
00188                             ? "access"
00189                             : "default")));
00190                 if (!solaris_add_to_acl(&solaris_acl, &count, other_acl,
00191                                         other_count, other_type)) 
00192                 {
00193                         DEBUG(10, ("error adding other acl.\n"));
00194                         SAFE_FREE(other_acl);
00195                         goto done;
00196                 }
00197                 SAFE_FREE(other_acl);
00198         }
00199         else if (type != SMB_ACL_TYPE_ACCESS) {
00200                 errno = EINVAL;
00201                 goto done;
00202         }
00203 
00204         if (!solaris_acl_sort(solaris_acl, count)) {
00205                 DEBUG(10, ("resulting acl is not valid!\n"));
00206                 goto done;
00207         }
00208 
00209         ret = acl(name, SETACL, count, solaris_acl);
00210         
00211  done:
00212         DEBUG(10, ("solarisacl_sys_acl_set_file %s.\n",
00213                    ((ret != 0) ? "failed" : "succeeded")));
00214         SAFE_FREE(solaris_acl);
00215         return ret;
00216 }
00217 
00218 /*
00219  * set the access ACL on the file referred to by a fd 
00220  */
00221 int solarisacl_sys_acl_set_fd(vfs_handle_struct *handle,
00222                               files_struct *fsp,
00223                               int fd, SMB_ACL_T theacl)
00224 {
00225         SOLARIS_ACL_T solaris_acl = NULL;
00226         SOLARIS_ACL_T default_acl = NULL;
00227         int count, default_count;
00228         int ret = -1;
00229 
00230         DEBUG(10, ("entering solarisacl_sys_acl_set_fd\n"));
00231 
00232         /* 
00233          * the posix acl_set_fd call sets the access acl of the
00234          * file referred to by fd. the solaris facl-SETACL call
00235          * sets the access and default acl as provided, so we
00236          * have to retrieve the default acl of the file and 
00237          * concatenate it with the access acl provided.
00238          */
00239         if (!smb_acl_to_solaris_acl(theacl, &solaris_acl, &count, 
00240                                     SMB_ACL_TYPE_ACCESS))
00241         {
00242                 DEBUG(10, ("conversion smb_acl -> solaris_acl failed (%s).\n",
00243                            strerror(errno)));
00244                 goto done;
00245         }
00246         if (!solaris_acl_get_fd(fd, &default_acl, &default_count)) {
00247                 DEBUG(10, ("error getting (default) acl from fd\n"));
00248                 goto done;
00249         }
00250         if (!solaris_add_to_acl(&solaris_acl, &count,
00251                                 default_acl, default_count,
00252                                 SMB_ACL_TYPE_DEFAULT))
00253         {
00254                 DEBUG(10, ("error adding default acl to solaris acl\n"));
00255                 goto done;
00256         }
00257         if (!solaris_acl_sort(solaris_acl, count)) {
00258                 DEBUG(10, ("resulting acl is not valid!\n"));
00259                 goto done;
00260         }
00261 
00262         ret = facl(fd, SETACL, count, solaris_acl);
00263         if (ret != 0) {
00264                 DEBUG(10, ("call of facl failed (%s).\n", strerror(errno)));
00265         }
00266 
00267  done:
00268         DEBUG(10, ("solarisacl_sys_acl_st_fd %s.\n",
00269                    ((ret == 0) ? "succeded" : "failed" )));
00270         SAFE_FREE(solaris_acl);
00271         SAFE_FREE(default_acl);
00272         return ret;
00273 }
00274 
00275 /*
00276  * delete the default ACL of a directory
00277  *
00278  * This is achieved by fetching the access ACL and rewriting it 
00279  * directly, via the solaris system call: the SETACL call on 
00280  * directories writes both the access and the default ACL as provided.
00281  *
00282  * XXX: posix acl_delete_def_file returns an error if
00283  * the file referred to by path is not a directory.
00284  * this function does not complain but the actions 
00285  * have no effect on a file other than a directory.
00286  * But sys_acl_delete_default_file is only called in
00287  * smbd/posixacls.c after having checked that the file
00288  * is a directory, anyways. So implementing the extra
00289  * check is considered unnecessary. --- Agreed? XXX
00290  */
00291 int solarisacl_sys_acl_delete_def_file(vfs_handle_struct *handle,
00292                                        const char *path)
00293 {
00294         SMB_ACL_T smb_acl;
00295         int ret = -1;
00296         SOLARIS_ACL_T solaris_acl = NULL;
00297         int count;
00298 
00299         DEBUG(10, ("entering solarisacl_sys_acl_delete_def_file.\n"));
00300         
00301         smb_acl = solarisacl_sys_acl_get_file(handle, path, 
00302                                               SMB_ACL_TYPE_ACCESS);
00303         if (smb_acl == NULL) {
00304                 DEBUG(10, ("getting file acl failed!\n"));
00305                 goto done;
00306         }
00307         if (!smb_acl_to_solaris_acl(smb_acl, &solaris_acl, &count, 
00308                                     SMB_ACL_TYPE_ACCESS))
00309         {
00310                 DEBUG(10, ("conversion smb_acl -> solaris_acl failed.\n"));
00311                 goto done;
00312         }
00313         if (!solaris_acl_sort(solaris_acl, count)) {
00314                 DEBUG(10, ("resulting acl is not valid!\n"));
00315                 goto done;
00316         }
00317         ret = acl(path, SETACL, count, solaris_acl);
00318         if (ret != 0) {
00319                 DEBUG(10, ("settinge file acl failed!\n"));
00320         }
00321         
00322  done:
00323         DEBUG(10, ("solarisacl_sys_acl_delete_def_file %s.\n",
00324                    ((ret != 0) ? "failed" : "succeeded" )));
00325         SAFE_FREE(smb_acl);
00326         return ret;
00327 }
00328 
00329 
00330 /* private functions */
00331 
00332 static SOLARIS_ACL_T solaris_acl_init(int count)
00333 {
00334         SOLARIS_ACL_T solaris_acl = 
00335                 (SOLARIS_ACL_T)SMB_MALLOC(sizeof(aclent_t) * count);
00336         if (solaris_acl == NULL) {
00337                 errno = ENOMEM;
00338         }
00339         return solaris_acl;
00340 }
00341 
00342 /*
00343  * Convert the SMB acl to the ACCESS or DEFAULT part of a 
00344  * solaris ACL, as desired.
00345  */
00346 static BOOL smb_acl_to_solaris_acl(SMB_ACL_T smb_acl, 
00347                                    SOLARIS_ACL_T *solaris_acl, int *count, 
00348                                    SMB_ACL_TYPE_T type)
00349 {
00350         BOOL ret = False;
00351         int i;
00352         int check_which, check_rc;
00353 
00354         DEBUG(10, ("entering smb_acl_to_solaris_acl\n"));
00355         
00356         *solaris_acl = NULL;
00357         *count = 0;
00358 
00359         for (i = 0; i < smb_acl->count; i++) {
00360                 const struct smb_acl_entry *smb_entry = &(smb_acl->acl[i]);
00361                 SOLARIS_ACE_T solaris_entry;
00362 
00363                 ZERO_STRUCT(solaris_entry);
00364 
00365                 solaris_entry.a_type = smb_tag_to_solaris_tag(smb_entry->a_type);
00366                 if (solaris_entry.a_type == 0) {
00367                         DEBUG(10, ("smb_tag to solaris_tag failed\n"));
00368                         goto fail;
00369                 }
00370                 switch(solaris_entry.a_type) {
00371                 case USER:
00372                         DEBUG(10, ("got tag type USER with uid %d\n", 
00373                                    smb_entry->uid));
00374                         solaris_entry.a_id = (uid_t)smb_entry->uid;
00375                         break;
00376                 case GROUP:
00377                         DEBUG(10, ("got tag type GROUP with gid %d\n", 
00378                                    smb_entry->gid));
00379                         solaris_entry.a_id = (uid_t)smb_entry->gid;
00380                         break;
00381                 default:
00382                         break;
00383                 }
00384                 if (type == SMB_ACL_TYPE_DEFAULT) {
00385                         DEBUG(10, ("adding default bit to solaris ace\n"));
00386                         solaris_entry.a_type |= ACL_DEFAULT;
00387                 }
00388                 
00389                 solaris_entry.a_perm = 
00390                         smb_perm_to_solaris_perm(smb_entry->a_perm);
00391                 DEBUG(10, ("assembled the following solaris ace:\n"));
00392                 DEBUGADD(10, (" - type: 0x%04x\n", solaris_entry.a_type));
00393                 DEBUGADD(10, (" - id: %d\n", solaris_entry.a_id));
00394                 DEBUGADD(10, (" - perm: o%o\n", solaris_entry.a_perm));
00395                 if (!solaris_add_to_acl(solaris_acl, count, &solaris_entry, 
00396                                         1, type))
00397                 {
00398                         DEBUG(10, ("error adding acl entry\n"));
00399                         goto fail;
00400                 }
00401                 DEBUG(10, ("count after adding: %d (i: %d)\n", *count, i));
00402                 DEBUG(10, ("test, if entry has been copied into acl:\n"));
00403                 DEBUGADD(10, (" - type: 0x%04x\n",
00404                               (*solaris_acl)[(*count)-1].a_type));
00405                 DEBUGADD(10, (" - id: %d\n",
00406                               (*solaris_acl)[(*count)-1].a_id));
00407                 DEBUGADD(10, (" - perm: o%o\n",
00408                               (*solaris_acl)[(*count)-1].a_perm));
00409         }
00410 
00411         ret = True;
00412         goto done;
00413         
00414  fail:
00415         SAFE_FREE(*solaris_acl);
00416  done:
00417         DEBUG(10, ("smb_acl_to_solaris_acl %s\n",
00418                    ((ret == True) ? "succeeded" : "failed")));
00419         return ret;
00420 }
00421 
00422 /* 
00423  * convert either the access or the default part of a 
00424  * soaris acl to the SMB_ACL format.
00425  */
00426 static SMB_ACL_T solaris_acl_to_smb_acl(SOLARIS_ACL_T solaris_acl, int count, 
00427                                         SMB_ACL_TYPE_T type)
00428 {
00429         SMB_ACL_T result;
00430         int i;
00431 
00432         if ((result = sys_acl_init(0)) == NULL) {
00433                 DEBUG(10, ("error allocating memory for SMB_ACL\n"));
00434                 goto fail;
00435         }
00436         for (i = 0; i < count; i++) {
00437                 SMB_ACL_ENTRY_T smb_entry;
00438                 SMB_ACL_PERM_T smb_perm;
00439                 
00440                 if (!_IS_OF_TYPE(solaris_acl[i], type)) {
00441                         continue;
00442                 }
00443                 result = SMB_REALLOC(result, 
00444                                      sizeof(struct smb_acl_t) +
00445                                      (sizeof(struct smb_acl_entry) *
00446                                       (result->count + 1)));
00447                 if (result == NULL) {
00448                         DEBUG(10, ("error reallocating memory for SMB_ACL\n"));
00449                         goto fail;
00450                 }
00451                 smb_entry = &result->acl[result->count];
00452                 if (sys_acl_set_tag_type(smb_entry,
00453                                          solaris_tag_to_smb_tag(solaris_acl[i].a_type)) != 0)
00454                 {
00455                         DEBUG(10, ("invalid tag type given: 0x%04x\n",
00456                                    solaris_acl[i].a_type));
00457                         goto fail;
00458                 }
00459                 /* intentionally not checking return code here: */
00460                 sys_acl_set_qualifier(smb_entry, (void *)&solaris_acl[i].a_id);
00461                 smb_perm = solaris_perm_to_smb_perm(solaris_acl[i].a_perm);
00462                 if (sys_acl_set_permset(smb_entry, &smb_perm) != 0) {
00463                         DEBUG(10, ("invalid permset given: %d\n", 
00464                                    solaris_acl[i].a_perm));
00465                         goto fail;
00466                 }
00467                 result->count += 1;
00468         }
00469         goto done;
00470         
00471  fail:
00472         SAFE_FREE(result);
00473  done:
00474         DEBUG(10, ("solaris_acl_to_smb_acl %s\n",
00475                    ((result == NULL) ? "failed" : "succeeded")));
00476         return result;
00477 }
00478 
00479 
00480 
00481 static SOLARIS_ACL_TAG_T smb_tag_to_solaris_tag(SMB_ACL_TAG_T smb_tag)
00482 {
00483         SOLARIS_ACL_TAG_T solaris_tag = 0;
00484 
00485         DEBUG(10, ("smb_tag_to_solaris_tag\n"));
00486         DEBUGADD(10, (" --> got smb tag 0x%04x\n", smb_tag));
00487         
00488         switch (smb_tag) {
00489         case SMB_ACL_USER:
00490                 solaris_tag = USER;
00491                 break;
00492         case SMB_ACL_USER_OBJ:
00493                 solaris_tag = USER_OBJ;
00494                 break;
00495         case SMB_ACL_GROUP:
00496                 solaris_tag = GROUP;
00497                 break;
00498         case SMB_ACL_GROUP_OBJ:
00499                 solaris_tag = GROUP_OBJ;
00500                 break;
00501         case SMB_ACL_OTHER:
00502                 solaris_tag = OTHER_OBJ;
00503                 break;
00504         case SMB_ACL_MASK:
00505                 solaris_tag = CLASS_OBJ;
00506                 break;
00507         default:
00508                 DEBUGADD(10, (" !!! unknown smb tag type 0x%04x\n", smb_tag));
00509                 break;
00510         }
00511         
00512         DEBUGADD(10, (" --> determined solaris tag 0x%04x\n", solaris_tag));
00513 
00514         return solaris_tag;
00515 }
00516 
00517 static SMB_ACL_TAG_T solaris_tag_to_smb_tag(SOLARIS_ACL_TAG_T solaris_tag)
00518 {
00519         SMB_ACL_TAG_T smb_tag = 0;
00520 
00521         DEBUG(10, ("solaris_tag_to_smb_tag:\n"));
00522         DEBUGADD(10, (" --> got solaris tag 0x%04x\n", solaris_tag)); 
00523         
00524         solaris_tag &= ~ACL_DEFAULT; 
00525 
00526         switch (solaris_tag) {
00527         case USER:
00528                 smb_tag = SMB_ACL_USER;
00529                 break;
00530         case USER_OBJ:
00531                 smb_tag = SMB_ACL_USER_OBJ;
00532                 break;
00533         case GROUP:
00534                 smb_tag = SMB_ACL_GROUP;
00535                 break;
00536         case GROUP_OBJ:
00537                 smb_tag = SMB_ACL_GROUP_OBJ;
00538                 break;
00539         case OTHER_OBJ:
00540                 smb_tag = SMB_ACL_OTHER;
00541                 break;
00542         case CLASS_OBJ:
00543                 smb_tag = SMB_ACL_MASK;
00544                 break;
00545         default:
00546                 DEBUGADD(10, (" !!! unknown solaris tag type: 0x%04x\n", 
00547                                         solaris_tag));
00548                 break;
00549         }
00550 
00551         DEBUGADD(10, (" --> determined smb tag 0x%04x\n", smb_tag));
00552         
00553         return smb_tag;
00554 }
00555 
00556 
00557 static SMB_ACL_PERM_T solaris_perm_to_smb_perm(const SOLARIS_PERM_T perm)
00558 {
00559         SMB_ACL_PERM_T smb_perm = 0;
00560         smb_perm |= ((perm & SMB_ACL_READ) ? SMB_ACL_READ : 0);
00561         smb_perm |= ((perm & SMB_ACL_WRITE) ? SMB_ACL_WRITE : 0);
00562         smb_perm |= ((perm & SMB_ACL_EXECUTE) ? SMB_ACL_EXECUTE : 0);
00563         return smb_perm;
00564 }
00565 
00566 
00567 static SOLARIS_PERM_T smb_perm_to_solaris_perm(const SMB_ACL_PERM_T perm)
00568 {
00569         SOLARIS_PERM_T solaris_perm = 0;
00570         solaris_perm |= ((perm & SMB_ACL_READ) ? SMB_ACL_READ : 0);
00571         solaris_perm |= ((perm & SMB_ACL_WRITE) ? SMB_ACL_WRITE : 0);
00572         solaris_perm |= ((perm & SMB_ACL_EXECUTE) ? SMB_ACL_EXECUTE : 0);
00573         return solaris_perm;
00574 }
00575 
00576 
00577 static BOOL solaris_acl_get_file(const char *name, SOLARIS_ACL_T *solaris_acl, 
00578                                  int *count)
00579 {
00580         BOOL result = False;
00581 
00582         DEBUG(10, ("solaris_acl_get_file called for file '%s'\n", name));
00583         
00584         /* 
00585          * The original code tries some INITIAL_ACL_SIZE
00586          * and only did the GETACLCNT call upon failure
00587          * (for performance reasons).
00588          * For the sake of simplicity, I skip this for now. 
00589          */
00590         *count = acl(name, GETACLCNT, 0, NULL);
00591         if (*count < 0) {
00592                 DEBUG(10, ("acl GETACLCNT failed: %s\n", strerror(errno)));
00593                 goto done;
00594         }
00595         *solaris_acl = solaris_acl_init(*count);
00596         if (*solaris_acl == NULL) {
00597                 DEBUG(10, ("error allocating memory for solaris acl...\n"));
00598                 goto done;
00599         }
00600         *count = acl(name, GETACL, *count, *solaris_acl);
00601         if (*count < 0) {
00602                 DEBUG(10, ("acl GETACL failed: %s\n", strerror(errno)));
00603                 goto done;
00604         }
00605         result = True;
00606 
00607  done:
00608         DEBUG(10, ("solaris_acl_get_file %s.\n",
00609                    ((result == True) ? "succeeded" : "failed" )));
00610         return result;
00611 }
00612 
00613 
00614 static BOOL solaris_acl_get_fd(int fd, SOLARIS_ACL_T *solaris_acl, int *count)
00615 {
00616         BOOL ret = False;
00617 
00618         DEBUG(10, ("entering solaris_acl_get_fd\n"));
00619 
00620         /* 
00621          * see solaris_acl_get_file for comment about omission 
00622          * of INITIAL_ACL_SIZE... 
00623          */
00624         *count = facl(fd, GETACLCNT, 0, NULL);
00625         if (*count < 0) {
00626                 DEBUG(10, ("facl GETACLCNT failed: %s\n", strerror(errno)));
00627                 goto done;
00628         }
00629         *solaris_acl = solaris_acl_init(*count);
00630         if (*solaris_acl == NULL) {
00631                 DEBUG(10, ("error allocating memory for solaris acl...\n"));
00632                 goto done;
00633         }
00634         *count = facl(fd, GETACL, *count, *solaris_acl);
00635         if (*count < 0) {
00636                 DEBUG(10, ("facl GETACL failed: %s\n", strerror(errno)));
00637                 goto done;
00638         }
00639         ret = True;
00640 
00641  done:
00642         DEBUG(10, ("solaris_acl_get_fd %s\n",
00643                    ((ret == True) ? "succeeded" : "failed")));
00644         return ret;
00645 }
00646 
00647 
00648 
00649 /*
00650  * Add entries to a solaris ACL.
00651  *
00652  * Entries are directly added to the solarisacl parameter.
00653  * if memory allocation fails, this may result in solarisacl 
00654  * being NULL. if the resulting acl is to be checked and is 
00655  * not valid, it is kept in solarisacl but False is returned.
00656  *
00657  * The type of ACEs (access/default) to be added to the ACL can 
00658  * be selected via the type parameter. 
00659  * I use the SMB_ACL_TYPE_T type here. Since SMB_ACL_TYPE_ACCESS
00660  * is defined as "0", this means that one can only add either
00661  * access or default ACEs, not both at the same time. If it 
00662  * should become necessary to add all of an ACL, one would have
00663  * to replace this parameter by another type.
00664  */
00665 static BOOL solaris_add_to_acl(SOLARIS_ACL_T *solaris_acl, int *count,
00666                                SOLARIS_ACL_T add_acl, int add_count, 
00667                                SMB_ACL_TYPE_T type)
00668 {
00669         int i;
00670         
00671         if ((type != SMB_ACL_TYPE_ACCESS) && (type != SMB_ACL_TYPE_DEFAULT)) 
00672         {
00673                 DEBUG(10, ("invalid acl type given: %d\n", type));
00674                 errno = EINVAL;
00675                 return False;
00676         }
00677         for (i = 0; i < add_count; i++) {
00678                 if (!_IS_OF_TYPE(add_acl[i], type)) {
00679                         continue;
00680                 }
00681                 ADD_TO_ARRAY(NULL, SOLARIS_ACE_T, add_acl[i], 
00682                              solaris_acl, count);
00683                 if (solaris_acl == NULL) {
00684                         DEBUG(10, ("error enlarging acl.\n"));
00685                         errno = ENOMEM;
00686                         return False;
00687                 }
00688         }
00689         return True;
00690 }
00691 
00692 
00693 /* 
00694  * sort the ACL and check it for validity
00695  *
00696  * [original comment from lib/sysacls.c:]
00697  * 
00698  * if it's a minimal ACL with only 4 entries then we
00699  * need to recalculate the mask permissions to make
00700  * sure that they are the same as the GROUP_OBJ
00701  * permissions as required by the UnixWare acl() system call.
00702  *
00703  * (note: since POSIX allows minimal ACLs which only contain
00704  * 3 entries - ie there is no mask entry - we should, in theory,
00705  * check for this and add a mask entry if necessary - however
00706  * we "know" that the caller of this interface always specifies
00707  * a mask, so in practice "this never happens" (tm) - if it *does*
00708  * happen aclsort() will fail and return an error and someone will
00709  * have to fix it...)
00710  */
00711 static BOOL solaris_acl_sort(SOLARIS_ACL_T solaris_acl, int count)
00712 {
00713         int fixmask = (count <= 4);
00714 
00715         if (aclsort(count, fixmask, solaris_acl) != 0) {
00716                 errno = EINVAL;
00717                 return False;
00718         }
00719         return True;
00720 }
00721 
00722 /*
00723  * acl check function:
00724  *   unused at the moment but could be used to get more
00725  *   concrete error messages for debugging...
00726  *   (acl sort just says that the acl is invalid...)
00727  */
00728 static BOOL solaris_acl_check(SOLARIS_ACL_T solaris_acl, int count)
00729 {
00730         int check_rc;
00731         int check_which;
00732         
00733         check_rc = aclcheck(solaris_acl, count, &check_which);
00734         if (check_rc != 0) {
00735                 DEBUG(10, ("acl is not valid:\n"));
00736                 DEBUGADD(10, (" - return code: %d\n", check_rc));
00737                 DEBUGADD(10, (" - which: %d\n", check_which));
00738                 if (check_which != -1) {
00739                         DEBUGADD(10, (" - invalid entry:\n"));
00740                         DEBUGADD(10, ("   * type: %d:\n", 
00741                                       solaris_acl[check_which].a_type));
00742                         DEBUGADD(10, ("   * id: %d\n",
00743                                       solaris_acl[check_which].a_id));
00744                         DEBUGADD(10, ("   * perm: 0o%o\n",
00745                                       solaris_acl[check_which].a_perm));
00746                 }
00747                 return False;
00748         }
00749         return True;
00750 }
00751 
00752 
00753 /* VFS operations structure */
00754 
00755 static vfs_op_tuple solarisacl_op_tuples[] = {
00756         /* Disk operations */
00757         {SMB_VFS_OP(solarisacl_sys_acl_get_file),
00758          SMB_VFS_OP_SYS_ACL_GET_FILE,
00759          SMB_VFS_LAYER_TRANSPARENT},
00760 
00761         {SMB_VFS_OP(solarisacl_sys_acl_get_fd),
00762          SMB_VFS_OP_SYS_ACL_GET_FD,
00763          SMB_VFS_LAYER_TRANSPARENT},
00764 
00765         {SMB_VFS_OP(solarisacl_sys_acl_set_file),
00766          SMB_VFS_OP_SYS_ACL_SET_FILE,
00767          SMB_VFS_LAYER_TRANSPARENT},
00768 
00769         {SMB_VFS_OP(solarisacl_sys_acl_set_fd),
00770          SMB_VFS_OP_SYS_ACL_SET_FD,
00771          SMB_VFS_LAYER_TRANSPARENT},
00772 
00773         {SMB_VFS_OP(solarisacl_sys_acl_delete_def_file),
00774          SMB_VFS_OP_SYS_ACL_DELETE_DEF_FILE,
00775          SMB_VFS_LAYER_TRANSPARENT},
00776 
00777         {SMB_VFS_OP(NULL),
00778          SMB_VFS_OP_NOOP,
00779          SMB_VFS_LAYER_NOOP}
00780 };
00781 
00782 NTSTATUS vfs_solarisacl_init(void);
00783 NTSTATUS vfs_solarisacl_init(void)
00784 {
00785         return smb_register_vfs(SMB_VFS_INTERFACE_VERSION, "solarisacl",
00786                                 solarisacl_op_tuples);
00787 }
00788 
00789 /* ENTE */

Sambaに対してSat Aug 29 21:23:07 2009に生成されました。  doxygen 1.4.7