summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRalph Boehme <rb@sernet.de>2014-05-20 15:17:01 +0200
committerMichael Adam <obnox@samba.org>2014-06-13 13:22:18 +0200
commit634bcb09a08b927fd79ae0e16aeee2a123605f94 (patch)
tree55104edb9c53a51e0a95613cb1950c1144e61fca
parentf03e8b12c6959fb8213fbfcd3792b70094bd9a71 (diff)
downloadsamba-634bcb09a08b927fd79ae0e16aeee2a123605f94.tar.gz
samba-634bcb09a08b927fd79ae0e16aeee2a123605f94.tar.xz
samba-634bcb09a08b927fd79ae0e16aeee2a123605f94.zip
vfs_streams_xattr: add options "prefix" and "store_stream_type"
Add module options that can be used to configure the stream prefix the module uses (option "prefix", a string) and whether the stream type "$DATA" is appended to the xattr name on disk (option "store_stream_type", a boolean). The default "prefix" is "user.DosStream" and the default for "store_stream_type" is true, this gives unchanged default behaviour when not specifying this option. OS X SMB clients will send xattrs as named streams over the wire, by setting the options to the following values streams_xattr:prefix = user. streams_xattr:store_stream_type = no OS X xattrs will be stored on disk on the server with their unmodified names and as such provide interoperability with other protocols like AFP. In order to prevent access to our internal Samba xattrs, check the xattr name with the function samba_private_attr_name() made public by the previous commit. Signed-off-by: Ralph Boehme <rb@sernet.de> Reviewed-by: Christof Schmitt <cs@samba.org> Reviewed-by: Michael Adam <obnox@samba.org>
-rw-r--r--source3/modules/vfs_streams_xattr.c122
1 files changed, 92 insertions, 30 deletions
diff --git a/source3/modules/vfs_streams_xattr.c b/source3/modules/vfs_streams_xattr.c
index 5e9bd3e864c..735db2b9204 100644
--- a/source3/modules/vfs_streams_xattr.c
+++ b/source3/modules/vfs_streams_xattr.c
@@ -29,6 +29,12 @@
#undef DBGC_CLASS
#define DBGC_CLASS DBGC_VFS
+struct streams_xattr_config {
+ const char *prefix;
+ size_t prefix_len;
+ bool store_stream_type;
+};
+
struct stream_io {
char *base;
char *xattr_name;
@@ -95,33 +101,41 @@ static ssize_t get_xattr_size(connection_struct *conn,
* Given a stream name, populate xattr_name with the xattr name to use for
* accessing the stream.
*/
-static NTSTATUS streams_xattr_get_name(TALLOC_CTX *ctx,
+static NTSTATUS streams_xattr_get_name(vfs_handle_struct *handle,
+ TALLOC_CTX *ctx,
const char *stream_name,
char **xattr_name)
{
char *stype;
+ struct streams_xattr_config *config;
+
+ SMB_VFS_HANDLE_GET_DATA(handle, config, struct streams_xattr_config,
+ return NT_STATUS_UNSUCCESSFUL);
stype = strchr_m(stream_name + 1, ':');
*xattr_name = talloc_asprintf(ctx, "%s%s",
- SAMBA_XATTR_DOSSTREAM_PREFIX,
+ config->prefix,
stream_name + 1);
if (*xattr_name == NULL) {
return NT_STATUS_NO_MEMORY;
}
- if (stype == NULL) {
- /* Append an explicit stream type if one wasn't specified. */
- *xattr_name = talloc_asprintf(ctx, "%s:$DATA",
- *xattr_name);
- if (*xattr_name == NULL) {
- return NT_STATUS_NO_MEMORY;
- }
- } else {
+ if (stype != NULL) {
/* Normalize the stream type to upercase. */
if (!strupper_m(strrchr_m(*xattr_name, ':') + 1)) {
return NT_STATUS_INVALID_PARAMETER;
}
+ } else if (config->store_stream_type) {
+ /*
+ * Append an explicit stream type if one wasn't
+ * specified.
+ */
+ *xattr_name = talloc_asprintf(ctx, "%s%s",
+ *xattr_name, ":$DATA");
+ if (*xattr_name == NULL) {
+ return NT_STATUS_NO_MEMORY;
+ }
}
DEBUG(10, ("xattr_name: %s, stream_name: %s\n", *xattr_name,
@@ -145,7 +159,7 @@ static bool streams_xattr_recheck(struct stream_io *sio)
return false;
}
- status = streams_xattr_get_name(talloc_tos(),
+ status = streams_xattr_get_name(sio->handle, talloc_tos(),
sio->fsp->fsp_name->stream_name,
&xattr_name);
if (!NT_STATUS_IS_OK(status)) {
@@ -271,8 +285,8 @@ static int streams_xattr_stat(vfs_handle_struct *handle,
}
/* Derive the xattr name to lookup. */
- status = streams_xattr_get_name(talloc_tos(), smb_fname->stream_name,
- &xattr_name);
+ status = streams_xattr_get_name(handle, talloc_tos(),
+ smb_fname->stream_name, &xattr_name);
if (!NT_STATUS_IS_OK(status)) {
errno = map_errno_from_nt_status(status);
return -1;
@@ -322,8 +336,8 @@ static int streams_xattr_lstat(vfs_handle_struct *handle,
}
/* Derive the xattr name to lookup. */
- status = streams_xattr_get_name(talloc_tos(), smb_fname->stream_name,
- &xattr_name);
+ status = streams_xattr_get_name(handle, talloc_tos(),
+ smb_fname->stream_name, &xattr_name);
if (!NT_STATUS_IS_OK(status)) {
errno = map_errno_from_nt_status(status);
return -1;
@@ -386,8 +400,8 @@ static int streams_xattr_open(vfs_handle_struct *handle,
return ret;
}
- status = streams_xattr_get_name(talloc_tos(), smb_fname->stream_name,
- &xattr_name);
+ status = streams_xattr_get_name(handle, talloc_tos(),
+ smb_fname->stream_name, &xattr_name);
if (!NT_STATUS_IS_OK(status)) {
errno = map_errno_from_nt_status(status);
goto fail;
@@ -541,8 +555,8 @@ static int streams_xattr_unlink(vfs_handle_struct *handle,
return ret;
}
- status = streams_xattr_get_name(talloc_tos(), smb_fname->stream_name,
- &xattr_name);
+ status = streams_xattr_get_name(handle, talloc_tos(),
+ smb_fname->stream_name, &xattr_name);
if (!NT_STATUS_IS_OK(status)) {
errno = map_errno_from_nt_status(status);
goto fail;
@@ -597,14 +611,14 @@ static int streams_xattr_rename(vfs_handle_struct *handle,
}
/* Get the xattr names. */
- status = streams_xattr_get_name(talloc_tos(),
+ status = streams_xattr_get_name(handle, talloc_tos(),
smb_fname_src->stream_name,
&src_xattr_name);
if (!NT_STATUS_IS_OK(status)) {
errno = map_errno_from_nt_status(status);
goto fail;
}
- status = streams_xattr_get_name(talloc_tos(),
+ status = streams_xattr_get_name(handle, talloc_tos(),
smb_fname_dst->stream_name,
&dst_xattr_name);
if (!NT_STATUS_IS_OK(status)) {
@@ -650,7 +664,7 @@ static int streams_xattr_rename(vfs_handle_struct *handle,
return ret;
}
-static NTSTATUS walk_xattr_streams(connection_struct *conn, files_struct *fsp,
+static NTSTATUS walk_xattr_streams(vfs_handle_struct *handle, files_struct *fsp,
const char *fname,
bool (*fn)(struct ea_struct *ea,
void *private_data),
@@ -659,9 +673,12 @@ static NTSTATUS walk_xattr_streams(connection_struct *conn, files_struct *fsp,
NTSTATUS status;
char **names;
size_t i, num_names;
- size_t prefix_len = strlen(SAMBA_XATTR_DOSSTREAM_PREFIX);
+ struct streams_xattr_config *config;
+
+ SMB_VFS_HANDLE_GET_DATA(handle, config, struct streams_xattr_config,
+ return NT_STATUS_UNSUCCESSFUL);
- status = get_ea_names_from_file(talloc_tos(), conn, fsp, fname,
+ status = get_ea_names_from_file(talloc_tos(), handle->conn, fsp, fname,
&names, &num_names);
if (!NT_STATUS_IS_OK(status)) {
return status;
@@ -670,20 +687,26 @@ static NTSTATUS walk_xattr_streams(connection_struct *conn, files_struct *fsp,
for (i=0; i<num_names; i++) {
struct ea_struct ea;
- if (strncmp(names[i], SAMBA_XATTR_DOSSTREAM_PREFIX,
- prefix_len) != 0) {
+ if (strncmp(names[i], config->prefix,
+ config->prefix_len) != 0) {
+ continue;
+ }
+ if (samba_private_attr_name(names[i])) {
continue;
}
- status = get_ea_value(names, conn, fsp, fname, names[i], &ea);
+ status = get_ea_value(names, handle->conn, fsp, fname,
+ names[i], &ea);
if (!NT_STATUS_IS_OK(status)) {
DEBUG(10, ("Could not get ea %s for file %s: %s\n",
names[i], fname, nt_errstr(status)));
continue;
}
- ea.name = talloc_asprintf(ea.value.data, ":%s",
- names[i] + prefix_len);
+ ea.name = talloc_asprintf(
+ ea.value.data, ":%s%s",
+ names[i] + config->prefix_len,
+ config->store_stream_type ? "" : ":$DATA");
if (ea.name == NULL) {
DEBUG(0, ("talloc failed\n"));
continue;
@@ -803,7 +826,7 @@ static NTSTATUS streams_xattr_streaminfo(vfs_handle_struct *handle,
*/
status = NT_STATUS_OK;
} else {
- status = walk_xattr_streams(handle->conn, fsp, fname,
+ status = walk_xattr_streams(handle, fsp, fname,
collect_one_stream, &state);
}
@@ -829,6 +852,44 @@ static uint32_t streams_xattr_fs_capabilities(struct vfs_handle_struct *handle,
return SMB_VFS_NEXT_FS_CAPABILITIES(handle, p_ts_res) | FILE_NAMED_STREAMS;
}
+static int streams_xattr_connect(vfs_handle_struct *handle,
+ const char *service, const char *user)
+{
+ struct streams_xattr_config *config;
+ const char *default_prefix = SAMBA_XATTR_DOSSTREAM_PREFIX;
+ const char *prefix;
+
+ config = talloc_zero(handle->conn, struct streams_xattr_config);
+ if (config == NULL) {
+ DEBUG(1, ("talloc_zero() failed\n"));
+ errno = ENOMEM;
+ return -1;
+ }
+
+ prefix = lp_parm_const_string(SNUM(handle->conn),
+ "streams_xattr", "prefix",
+ default_prefix);
+ config->prefix = talloc_strdup(config, prefix);
+ if (config->prefix == NULL) {
+ DEBUG(1, ("talloc_strdup() failed\n"));
+ errno = ENOMEM;
+ return -1;
+ }
+ config->prefix_len = strlen(config->prefix);
+ DEBUG(10, ("streams_xattr using stream prefix: %s\n", config->prefix));
+
+ config->store_stream_type = lp_parm_bool(SNUM(handle->conn),
+ "streams_xattr",
+ "store_stream_type",
+ true);
+
+ SMB_VFS_HANDLE_SET_DATA(handle, config,
+ NULL, struct stream_xattr_config,
+ return -1);
+
+ return 0;
+}
+
static ssize_t streams_xattr_pwrite(vfs_handle_struct *handle,
files_struct *fsp, const void *data,
size_t n, off_t offset)
@@ -1031,6 +1092,7 @@ static int streams_xattr_fallocate(struct vfs_handle_struct *handle,
static struct vfs_fn_pointers vfs_streams_xattr_fns = {
.fs_capabilities_fn = streams_xattr_fs_capabilities,
+ .connect_fn = streams_xattr_connect,
.open_fn = streams_xattr_open,
.stat_fn = streams_xattr_stat,
.fstat_fn = streams_xattr_fstat,