modules/vfs_posixacl.c

説明を見る。
00001 /*
00002    Unix SMB/Netbios implementation.
00003    VFS module to get and set posix acls
00004    Copyright (C) Volker Lendecke 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 #include "includes.h"
00022 
00023 
00024 /* prototypes for static functions first - for clarity */
00025 
00026 static BOOL smb_ace_to_internal(acl_entry_t posix_ace,
00027                                 struct smb_acl_entry *ace);
00028 static struct smb_acl_t *smb_acl_to_internal(acl_t acl);
00029 static int smb_acl_set_mode(acl_entry_t entry, SMB_ACL_PERM_T perm);
00030 static acl_t smb_acl_to_posix(const struct smb_acl_t *acl);
00031 
00032 
00033 /* public functions - the api */
00034 
00035 SMB_ACL_T posixacl_sys_acl_get_file(vfs_handle_struct *handle,
00036                                     const char *path_p,
00037                                     SMB_ACL_TYPE_T type)
00038 {
00039         struct smb_acl_t *result;
00040         acl_type_t acl_type;
00041         acl_t acl;
00042 
00043         switch(type) {
00044         case SMB_ACL_TYPE_ACCESS:
00045                 acl_type = ACL_TYPE_ACCESS;
00046                 break;
00047         case SMB_ACL_TYPE_DEFAULT:
00048                 acl_type = ACL_TYPE_DEFAULT;
00049                 break;
00050         default:
00051                 errno = EINVAL;
00052                 return NULL;
00053         }
00054 
00055         acl = acl_get_file(path_p, acl_type);
00056 
00057         if (acl == NULL) {
00058                 return NULL;
00059         }
00060 
00061         result = smb_acl_to_internal(acl);
00062         acl_free(acl);
00063         return result;
00064 }
00065 
00066 SMB_ACL_T posixacl_sys_acl_get_fd(vfs_handle_struct *handle,
00067                                   files_struct *fsp,
00068                                   int fd)
00069 {
00070         struct smb_acl_t *result;
00071         acl_t acl = acl_get_fd(fd);
00072 
00073         if (acl == NULL) {
00074                 return NULL;
00075         }
00076 
00077         result = smb_acl_to_internal(acl);
00078         acl_free(acl);
00079         return result;
00080 }
00081 
00082 int posixacl_sys_acl_set_file(vfs_handle_struct *handle,
00083                               const char *name,
00084                               SMB_ACL_TYPE_T type,
00085                               SMB_ACL_T theacl)
00086 {
00087         int res;
00088         acl_type_t acl_type;
00089         acl_t acl;
00090 
00091         DEBUG(10, ("Calling acl_set_file: %s, %d\n", name, type));
00092 
00093         switch(type) {
00094         case SMB_ACL_TYPE_ACCESS:
00095                 acl_type = ACL_TYPE_ACCESS;
00096                 break;
00097         case SMB_ACL_TYPE_DEFAULT:
00098                 acl_type = ACL_TYPE_DEFAULT;
00099                 break;
00100         default:
00101                 errno = EINVAL;
00102                 return -1;
00103         }
00104 
00105         if ((acl = smb_acl_to_posix(theacl)) == NULL) {
00106                 return -1;
00107         }
00108         res = acl_set_file(name, acl_type, acl);
00109         if (res != 0) {
00110                 DEBUG(10, ("acl_set_file failed: %s\n", strerror(errno)));
00111         }
00112         acl_free(acl);
00113         return res;
00114 }
00115 
00116 int posixacl_sys_acl_set_fd(vfs_handle_struct *handle,
00117                             files_struct *fsp,
00118                             int fd, SMB_ACL_T theacl)
00119 {
00120         int res;
00121         acl_t acl = smb_acl_to_posix(theacl);
00122         if (acl == NULL) {
00123                 return -1;
00124         }
00125         res =  acl_set_fd(fd, acl);
00126         acl_free(acl);
00127         return res;
00128 }
00129 
00130 int posixacl_sys_acl_delete_def_file(vfs_handle_struct *handle,
00131                                      const char *path)
00132 {
00133         return acl_delete_def_file(path);
00134 }
00135 
00136 
00137 /* private functions */
00138 
00139 static BOOL smb_ace_to_internal(acl_entry_t posix_ace,
00140                                 struct smb_acl_entry *ace)
00141 {
00142         acl_tag_t tag;
00143         acl_permset_t permset;
00144 
00145         if (acl_get_tag_type(posix_ace, &tag) != 0) {
00146                 DEBUG(0, ("smb_acl_get_tag_type failed\n"));
00147                 return False;
00148         }
00149 
00150         switch(tag) {
00151         case ACL_USER:
00152                 ace->a_type = SMB_ACL_USER;
00153                 break;
00154         case ACL_USER_OBJ:
00155                 ace->a_type = SMB_ACL_USER_OBJ;
00156                 break;
00157         case ACL_GROUP:
00158                 ace->a_type = SMB_ACL_GROUP;
00159                 break;
00160         case ACL_GROUP_OBJ:
00161                 ace->a_type = SMB_ACL_GROUP_OBJ;
00162                 break;
00163         case ACL_OTHER:
00164                 ace->a_type = SMB_ACL_OTHER;
00165                 break;
00166         case ACL_MASK:
00167                 ace->a_type = SMB_ACL_MASK;
00168                 break;
00169         default:
00170                 DEBUG(0, ("unknown tag type %d\n", (unsigned int)tag));
00171                 return False;
00172         }
00173         switch(ace->a_type) {
00174         case SMB_ACL_USER: {
00175                 uid_t *puid = (uid_t *)acl_get_qualifier(posix_ace);
00176                 if (puid == NULL) {
00177                         DEBUG(0, ("smb_acl_get_qualifier failed\n"));
00178                         return False;
00179                 }
00180                 ace->uid = *puid;
00181                 acl_free(puid);
00182                 break;
00183         }
00184                 
00185         case SMB_ACL_GROUP: {
00186                 gid_t *pgid = (uid_t *)acl_get_qualifier(posix_ace);
00187                 if (pgid == NULL) {
00188                         DEBUG(0, ("smb_acl_get_qualifier failed\n"));
00189                         return False;
00190                 }
00191                 ace->gid = *pgid;
00192                 acl_free(pgid);
00193                 break;
00194         }
00195         default:
00196                 break;
00197         }
00198         if (acl_get_permset(posix_ace, &permset) != 0) {
00199                 DEBUG(0, ("smb_acl_get_mode failed\n"));
00200                 return False;
00201         }
00202         ace->a_perm = 0;
00203 #ifdef HAVE_ACL_GET_PERM_NP
00204         ace->a_perm |= (acl_get_perm_np(permset, ACL_READ) ? SMB_ACL_READ : 0);
00205         ace->a_perm |= (acl_get_perm_np(permset, ACL_WRITE) ? SMB_ACL_WRITE : 0);
00206         ace->a_perm |= (acl_get_perm_np(permset, ACL_EXECUTE) ? SMB_ACL_EXECUTE : 0);
00207 #else
00208         ace->a_perm |= (acl_get_perm(permset, ACL_READ) ? SMB_ACL_READ : 0);
00209         ace->a_perm |= (acl_get_perm(permset, ACL_WRITE) ? SMB_ACL_WRITE : 0);
00210         ace->a_perm |= (acl_get_perm(permset, ACL_EXECUTE) ? SMB_ACL_EXECUTE : 0);
00211 #endif
00212         return True;
00213 }
00214 
00215 static struct smb_acl_t *smb_acl_to_internal(acl_t acl)
00216 {
00217         struct smb_acl_t *result = SMB_MALLOC_P(struct smb_acl_t);
00218         int entry_id = ACL_FIRST_ENTRY;
00219         acl_entry_t e;
00220         if (result == NULL) {
00221                 return NULL;
00222         }
00223         ZERO_STRUCTP(result);
00224         while (acl_get_entry(acl, entry_id, &e) == 1) {
00225 
00226                 entry_id = ACL_NEXT_ENTRY;
00227 
00228                 result = (struct smb_acl_t *)SMB_REALLOC(
00229                         result, sizeof(struct smb_acl_t) +
00230                         (sizeof(struct smb_acl_entry) * (result->count+1)));
00231                 if (result == NULL) {
00232                         DEBUG(0, ("SMB_REALLOC failed\n"));
00233                         errno = ENOMEM;
00234                         return NULL;
00235                 }
00236 
00237                 if (!smb_ace_to_internal(e, &result->acl[result->count])) {
00238                         SAFE_FREE(result);
00239                         return NULL;
00240                 }
00241 
00242                 result->count += 1;
00243         }
00244         return result;
00245 }
00246 
00247 static int smb_acl_set_mode(acl_entry_t entry, SMB_ACL_PERM_T perm)
00248 {
00249         int ret;
00250         acl_permset_t permset;
00251 
00252         if ((ret = acl_get_permset(entry, &permset)) != 0) {
00253                 return ret;
00254         }
00255         if ((ret = acl_clear_perms(permset)) != 0) {
00256                 return ret;
00257         }
00258         if ((perm & SMB_ACL_READ) &&
00259             ((ret = acl_add_perm(permset, ACL_READ)) != 0)) {
00260                 return ret;
00261         }
00262         if ((perm & SMB_ACL_WRITE) &&
00263             ((ret = acl_add_perm(permset, ACL_WRITE)) != 0)) {
00264                 return ret;
00265         }
00266         if ((perm & SMB_ACL_EXECUTE) &&
00267             ((ret = acl_add_perm(permset, ACL_EXECUTE)) != 0)) {
00268                 return ret;
00269         }
00270         return acl_set_permset(entry, permset);
00271 }
00272 
00273 static acl_t smb_acl_to_posix(const struct smb_acl_t *acl)
00274 {
00275         acl_t result;
00276         int i;
00277 
00278         result = acl_init(acl->count);
00279         if (result == NULL) {
00280                 DEBUG(10, ("acl_init failed\n"));
00281                 return NULL;
00282         }
00283 
00284         for (i=0; i<acl->count; i++) {
00285                 const struct smb_acl_entry *entry = &acl->acl[i];
00286                 acl_entry_t e;
00287                 acl_tag_t tag;
00288 
00289                 if (acl_create_entry(&result, &e) != 0) {
00290                         DEBUG(1, ("acl_create_entry failed: %s\n",
00291                                   strerror(errno)));
00292                         goto fail;
00293                 }
00294 
00295                 switch (entry->a_type) {
00296                 case SMB_ACL_USER:
00297                         tag = ACL_USER;
00298                         break;
00299                 case SMB_ACL_USER_OBJ:
00300                         tag = ACL_USER_OBJ;
00301                         break;
00302                 case SMB_ACL_GROUP:
00303                         tag = ACL_GROUP;
00304                         break;
00305                 case SMB_ACL_GROUP_OBJ:
00306                         tag = ACL_GROUP_OBJ;
00307                         break;
00308                 case SMB_ACL_OTHER:
00309                         tag = ACL_OTHER;
00310                         break;
00311                 case SMB_ACL_MASK:
00312                         tag = ACL_MASK;
00313                         break;
00314                 default:
00315                         DEBUG(1, ("Unknown tag value %d\n", entry->a_type));
00316                         goto fail;
00317                 }
00318 
00319                 if (acl_set_tag_type(e, tag) != 0) {
00320                         DEBUG(10, ("acl_set_tag_type(%d) failed: %s\n",
00321                                    tag, strerror(errno)));
00322                         goto fail;
00323                 }
00324 
00325                 switch (entry->a_type) {
00326                 case SMB_ACL_USER:
00327                         if (acl_set_qualifier(e, &entry->uid) != 0) {
00328                                 DEBUG(1, ("acl_set_qualifiier failed: %s\n",
00329                                           strerror(errno)));
00330                                 goto fail;
00331                         }
00332                         break;
00333                 case SMB_ACL_GROUP:
00334                         if (acl_set_qualifier(e, &entry->gid) != 0) {
00335                                 DEBUG(1, ("acl_set_qualifiier failed: %s\n",
00336                                           strerror(errno)));
00337                                 goto fail;
00338                         }
00339                         break;
00340                 default:        /* Shut up, compiler! :-) */
00341                         break;
00342                 }
00343 
00344                 if (smb_acl_set_mode(e, entry->a_perm) != 0) {
00345                         goto fail;
00346                 }
00347         }
00348 
00349         if (acl_valid(result) != 0) {
00350                 DEBUG(0, ("smb_acl_to_posix: ACL is invalid for set (%s)\n",
00351                           strerror(errno)));
00352                 goto fail;
00353         }
00354 
00355         return result;
00356 
00357  fail:
00358         if (result != NULL) {
00359                 acl_free(result);
00360         }
00361         return NULL;
00362 }
00363 
00364 /* VFS operations structure */
00365 
00366 static vfs_op_tuple posixacl_op_tuples[] = {
00367         /* Disk operations */
00368   {SMB_VFS_OP(posixacl_sys_acl_get_file),
00369    SMB_VFS_OP_SYS_ACL_GET_FILE,
00370    SMB_VFS_LAYER_TRANSPARENT},
00371 
00372   {SMB_VFS_OP(posixacl_sys_acl_get_fd),
00373    SMB_VFS_OP_SYS_ACL_GET_FD,
00374    SMB_VFS_LAYER_TRANSPARENT},
00375 
00376   {SMB_VFS_OP(posixacl_sys_acl_set_file),
00377    SMB_VFS_OP_SYS_ACL_SET_FILE,
00378    SMB_VFS_LAYER_TRANSPARENT},
00379 
00380   {SMB_VFS_OP(posixacl_sys_acl_set_fd),
00381    SMB_VFS_OP_SYS_ACL_SET_FD,
00382    SMB_VFS_LAYER_TRANSPARENT},
00383 
00384   {SMB_VFS_OP(posixacl_sys_acl_delete_def_file),
00385    SMB_VFS_OP_SYS_ACL_DELETE_DEF_FILE,
00386    SMB_VFS_LAYER_TRANSPARENT},
00387 
00388   {SMB_VFS_OP(NULL),
00389    SMB_VFS_OP_NOOP,
00390    SMB_VFS_LAYER_NOOP}
00391 };
00392 
00393 NTSTATUS vfs_posixacl_init(void);
00394 NTSTATUS vfs_posixacl_init(void)
00395 {
00396         return smb_register_vfs(SMB_VFS_INTERFACE_VERSION, "posixacl",
00397                                 posixacl_op_tuples);
00398 }

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