if (ret == 0) {
TALLOC_CTX *frame = talloc_stackframe();
char *path;
+ struct smb_filename smb_fname_base = {
+ .base_name = smb_fname->base_name
+ };
NTSTATUS status;
- status = get_full_smb_filename(frame, smb_fname, &path);
+ /*
+ * As we're calling getxattr directly here
+ * we need to use only the base_name, not
+ * the full name containing any stream name.
+ */
+ status = get_full_smb_filename(frame, &smb_fname_base, &path);
if (!NT_STATUS_IS_OK(status)) {
errno = map_errno_from_nt_status(status);
TALLOC_FREE(frame);
return ret;
}
+static int fake_acls_lstat(vfs_handle_struct *handle,
+ struct smb_filename *smb_fname)
+{
+ int ret = -1;
+
+ ret = SMB_VFS_NEXT_LSTAT(handle, smb_fname);
+ if (ret == 0) {
+ TALLOC_CTX *frame = talloc_stackframe();
+ char *path;
+ struct smb_filename smb_fname_base = {
+ .base_name = smb_fname->base_name
+ };
+ NTSTATUS status;
+ /*
+ * As we're calling getxattr directly here
+ * we need to use only the base_name, not
+ * the full name containing any stream name.
+ */
+ status = get_full_smb_filename(frame, &smb_fname_base, &path);
+ if (!NT_STATUS_IS_OK(status)) {
+ errno = map_errno_from_nt_status(status);
+ TALLOC_FREE(frame);
+ return -1;
+ }
+
+ /* This isn't quite right (calling getxattr not
+ * lgetxattr), but for the test purposes of this
+ * module (fake NT ACLs from windows clients), it is
+ * close enough. We removed the l*xattr functions
+ * because linux doesn't support using them, but we
+ * could fake them in xattr_tdb if we really wanted
+ * to. We ignore errors because the link might not point anywhere */
+ fake_acls_uid(handle, path, &smb_fname->st.st_ex_uid);
+ fake_acls_gid(handle, path, &smb_fname->st.st_ex_gid);
+ TALLOC_FREE(frame);
+ }
+
+ return ret;
+}
+
static int fake_acls_fstat(vfs_handle_struct *handle, files_struct *fsp, SMB_STRUCT_STAT *sbuf)
{
int ret = -1;
return ret;
}
-static SMB_ACL_T fake_acls_blob2acl(DATA_BLOB *blob)
+static SMB_ACL_T fake_acls_blob2acl(DATA_BLOB *blob, TALLOC_CTX *mem_ctx)
{
enum ndr_err_code ndr_err;
- /* For now, ACLs are allocated on NULL */
- struct smb_acl_t *acl = talloc(NULL, struct smb_acl_t);
+ struct smb_acl_t *acl = talloc(mem_ctx, struct smb_acl_t);
if (!acl) {
errno = ENOMEM;
return NULL;
return blob;
}
-static SMB_ACL_T fake_acls_sys_acl_get_file(struct vfs_handle_struct *handle, const char *path, SMB_ACL_TYPE_T type)
+static SMB_ACL_T fake_acls_sys_acl_get_file(struct vfs_handle_struct *handle,
+ const char *path,
+ SMB_ACL_TYPE_T type,
+ TALLOC_CTX *mem_ctx)
{
DATA_BLOB blob = data_blob_null;
ssize_t length;
return NULL;
}
if (length != -1) {
- acl = fake_acls_blob2acl(&blob);
+ acl = fake_acls_blob2acl(&blob, mem_ctx);
}
TALLOC_FREE(frame);
return acl;
}
-static SMB_ACL_T fake_acls_sys_acl_get_fd(struct vfs_handle_struct *handle, files_struct *fsp)
+static SMB_ACL_T fake_acls_sys_acl_get_fd(struct vfs_handle_struct *handle,
+ files_struct *fsp,
+ TALLOC_CTX *mem_ctx)
{
DATA_BLOB blob = data_blob_null;
ssize_t length;
const char *name = FAKE_ACL_ACCESS_XATTR;
- struct smb_acl_t *acl;
+ struct smb_acl_t *acl = NULL;
TALLOC_CTX *frame = talloc_stackframe();
do {
return NULL;
}
if (length != -1) {
- acl = fake_acls_blob2acl(&blob);
+ acl = fake_acls_blob2acl(&blob, mem_ctx);
}
TALLOC_FREE(frame);
return acl;
}
+
static int fake_acls_sys_acl_set_file(vfs_handle_struct *handle, const char *path, SMB_ACL_TYPE_T acltype, SMB_ACL_T theacl)
{
int ret;
static int fake_acls_sys_acl_delete_def_file(vfs_handle_struct *handle, const char *path)
{
+ int ret;
const char *name = FAKE_ACL_DEFAULT_XATTR;
- return SMB_VFS_NEXT_REMOVEXATTR(handle, path, name);
+ TALLOC_CTX *frame = talloc_stackframe();
+ struct smb_filename *smb_fname;
+
+ smb_fname = synthetic_smb_fname(frame, path, NULL, NULL);
+ if (smb_fname == NULL) {
+ TALLOC_FREE(frame);
+ errno = ENOMEM;
+ return -1;
+ }
+
+ ret = SMB_VFS_NEXT_STAT(handle, smb_fname);
+ if (ret == -1) {
+ TALLOC_FREE(frame);
+ return -1;
+ }
+
+ if (!S_ISDIR(smb_fname->st.st_ex_mode)) {
+ errno = EINVAL;
+ TALLOC_FREE(frame);
+ return -1;
+ }
+
+ ret = SMB_VFS_NEXT_REMOVEXATTR(handle, path, name);
+ if (ret == -1 && errno == ENOATTR) {
+ ret = 0;
+ errno = 0;
+ }
+
+ TALLOC_FREE(frame);
+ return ret;
+}
+
+static int fake_acls_chown(vfs_handle_struct *handle,
+ const struct smb_filename *smb_fname,
+ uid_t uid,
+ gid_t gid)
+{
+ int ret;
+ uint8_t id_buf[4];
+ if (uid != -1) {
+ SIVAL(id_buf, 0, uid);
+ ret = SMB_VFS_NEXT_SETXATTR(handle,
+ smb_fname->base_name,
+ FAKE_UID,
+ id_buf,
+ sizeof(id_buf),
+ 0);
+ if (ret != 0) {
+ return ret;
+ }
+ }
+ if (gid != -1) {
+ SIVAL(id_buf, 0, gid);
+ ret = SMB_VFS_NEXT_SETXATTR(handle,
+ smb_fname->base_name,
+ FAKE_GID,
+ id_buf,
+ sizeof(id_buf),
+ 0);
+ if (ret != 0) {
+ return ret;
+ }
+ }
+ return 0;
}
-static int fake_acls_chown(vfs_handle_struct *handle, const char *path, uid_t uid, gid_t gid)
+static int fake_acls_lchown(vfs_handle_struct *handle, const char *path, uid_t uid, gid_t gid)
{
int ret;
uint8_t id_buf[4];
if (uid != -1) {
+ /* This isn't quite right (calling setxattr not
+ * lsetxattr), but for the test purposes of this
+ * module (fake NT ACLs from windows clients), it is
+ * close enough. We removed the l*xattr functions
+ * because linux doesn't support using them, but we
+ * could fake them in xattr_tdb if we really wanted
+ * to.
+ */
SIVAL(id_buf, 0, uid);
ret = SMB_VFS_NEXT_SETXATTR(handle, path, FAKE_UID, id_buf, sizeof(id_buf), 0);
if (ret != 0) {
static struct vfs_fn_pointers vfs_fake_acls_fns = {
.stat_fn = fake_acls_stat,
+ .lstat_fn = fake_acls_lstat,
.fstat_fn = fake_acls_fstat,
.sys_acl_get_file_fn = fake_acls_sys_acl_get_file,
.sys_acl_get_fd_fn = fake_acls_sys_acl_get_fd,
+ .sys_acl_blob_get_file_fn = posix_sys_acl_blob_get_file,
+ .sys_acl_blob_get_fd_fn = posix_sys_acl_blob_get_fd,
.sys_acl_set_file_fn = fake_acls_sys_acl_set_file,
.sys_acl_set_fd_fn = fake_acls_sys_acl_set_fd,
.sys_acl_delete_def_file_fn = fake_acls_sys_acl_delete_def_file,
.chown_fn = fake_acls_chown,
+ .lchown_fn = fake_acls_lchown,
.fchown_fn = fake_acls_fchown,
};