00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #include "includes.h"
00022
00023
00024
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
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
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:
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
00365
00366 static vfs_op_tuple posixacl_op_tuples[] = {
00367
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 }