s4:kdc: Implement KDC plugin hardware authentication policy
[samba.git] / source3 / modules / vfs_streams_xattr.c
index 682d492fee3dc7bd853a182efaab3a2c20441fa0..03ff6147cb030bd56829670bbdc72f8c22fd5ba4 100644 (file)
@@ -74,17 +74,15 @@ static NTSTATUS streams_xattr_get_name(vfs_handle_struct *handle,
                                       const char *stream_name,
                                       char **xattr_name)
 {
-       char *sname;
+       size_t stream_name_len = strlen(stream_name);
        char *stype;
        struct streams_xattr_config *config;
 
        SMB_VFS_HANDLE_GET_DATA(handle, config, struct streams_xattr_config,
                                return NT_STATUS_UNSUCCESSFUL);
 
-       sname = talloc_strdup(ctx, stream_name + 1);
-       if (sname == NULL) {
-               return NT_STATUS_NO_MEMORY;
-       }
+       SMB_ASSERT(stream_name[0] == ':');
+       stream_name += 1;
 
        /*
         * With vfs_fruit option "fruit:encoding = native" we're
@@ -100,34 +98,32 @@ static NTSTATUS streams_xattr_get_name(vfs_handle_struct *handle,
         * In check_path_syntax() we've already ensured the streamname
         * we got from the client is valid.
         */
-       stype = strrchr_m(sname, ':');
+       stype = strrchr_m(stream_name, ':');
 
        if (stype) {
                /*
                 * We only support one stream type: "$DATA"
                 */
                if (strcasecmp_m(stype, ":$DATA") != 0) {
-                       talloc_free(sname);
                        return NT_STATUS_INVALID_PARAMETER;
                }
 
                /* Split name and type */
-               stype[0] = '\0';
+               stream_name_len = (stype - stream_name);
        }
 
-       *xattr_name = talloc_asprintf(ctx, "%s%s%s",
+       *xattr_name = talloc_asprintf(ctx, "%s%.*s%s",
                                      config->prefix,
-                                     sname,
+                                     (int)stream_name_len,
+                                     stream_name,
                                      config->store_stream_type ? ":$DATA" : "");
        if (*xattr_name == NULL) {
-               talloc_free(sname);
                return NT_STATUS_NO_MEMORY;
        }
 
        DEBUG(10, ("xattr_name: %s, stream_name: %s\n", *xattr_name,
                   stream_name));
 
-       talloc_free(sname);
        return NT_STATUS_OK;
 }
 
@@ -182,7 +178,7 @@ static int streams_xattr_fstat(vfs_handle_struct *handle, files_struct *fsp,
        struct stream_io *io = (struct stream_io *)
                VFS_FETCH_FSP_EXTENSION(handle, fsp);
 
-       if (io == NULL || fsp->base_fsp == NULL) {
+       if (io == NULL || !fsp_is_alternate_stream(fsp)) {
                return SMB_VFS_NEXT_FSTAT(handle, fsp, sbuf);
        }
 
@@ -315,8 +311,7 @@ static int streams_xattr_openat(struct vfs_handle_struct *handle,
                                const struct files_struct *dirfsp,
                                const struct smb_filename *smb_fname,
                                files_struct *fsp,
-                               int flags,
-                               mode_t mode)
+                               const struct vfs_open_how *how)
 {
        NTSTATUS status;
        struct streams_xattr_config *config = NULL;
@@ -332,21 +327,23 @@ static int streams_xattr_openat(struct vfs_handle_struct *handle,
 
        DBG_DEBUG("called for %s with flags 0x%x\n",
                  smb_fname_str_dbg(smb_fname),
-                 flags);
+                 how->flags);
 
        if (!is_named_stream(smb_fname)) {
                return SMB_VFS_NEXT_OPENAT(handle,
                                           dirfsp,
                                           smb_fname,
                                           fsp,
-                                          flags,
-                                          mode);
+                                          how);
        }
 
-       /*
-        * For now assert this, so the below SMB_VFS_SETXATTR() works.
-        */
-       SMB_ASSERT(fsp_get_pathref_fd(dirfsp) == AT_FDCWD);
+       if (how->resolve != 0) {
+               errno = ENOSYS;
+               return -1;
+       }
+
+       SMB_ASSERT(fsp_is_alternate_stream(fsp));
+       SMB_ASSERT(dirfsp == NULL);
 
        status = streams_xattr_get_name(handle, talloc_tos(),
                                        smb_fname->stream_name, &xattr_name);
@@ -375,7 +372,7 @@ static int streams_xattr_openat(struct vfs_handle_struct *handle,
                        goto fail;
                }
 
-               if (!(flags & O_CREAT)) {
+               if (!(how->flags & O_CREAT)) {
                        errno = ENOATTR;
                        goto fail;
                }
@@ -383,7 +380,7 @@ static int streams_xattr_openat(struct vfs_handle_struct *handle,
                set_empty_xattr = true;
        }
 
-       if (flags & O_TRUNC) {
+       if (how->flags & O_TRUNC) {
                set_empty_xattr = true;
        }
 
@@ -403,7 +400,7 @@ static int streams_xattr_openat(struct vfs_handle_struct *handle,
                ret = SMB_VFS_FSETXATTR(fsp->base_fsp,
                                       xattr_name,
                                       &null, sizeof(null),
-                                      flags & O_EXCL ? XATTR_CREATE : 0);
+                                      how->flags & O_EXCL ? XATTR_CREATE : 0);
                if (ret != 0) {
                        goto fail;
                }
@@ -464,7 +461,7 @@ static int streams_xattr_close(vfs_handle_struct *handle,
        DBG_DEBUG("streams_xattr_close called [%s] fd [%d]\n",
                        smb_fname_str_dbg(fsp->fsp_name), fd);
 
-       if (!is_named_stream(fsp->fsp_name)) {
+       if (!fsp_is_alternate_stream(fsp)) {
                return SMB_VFS_NEXT_CLOSE(handle, fsp);
        }
 
@@ -474,7 +471,7 @@ static int streams_xattr_close(vfs_handle_struct *handle,
        return ret;
 }
 
-static int streams_xattr_unlink_internal(vfs_handle_struct *handle,
+static int streams_xattr_unlinkat(vfs_handle_struct *handle,
                        struct files_struct *dirfsp,
                        const struct smb_filename *smb_fname,
                        int flags)
@@ -482,6 +479,8 @@ static int streams_xattr_unlink_internal(vfs_handle_struct *handle,
        NTSTATUS status;
        int ret = -1;
        char *xattr_name = NULL;
+       struct smb_filename *pathref = NULL;
+       struct files_struct *fsp = smb_fname->fsp;
 
        if (!is_named_stream(smb_fname)) {
                return SMB_VFS_NEXT_UNLINKAT(handle,
@@ -490,6 +489,9 @@ static int streams_xattr_unlink_internal(vfs_handle_struct *handle,
                                        flags);
        }
 
+       /* A stream can never be rmdir'ed */
+       SMB_ASSERT((flags & AT_REMOVEDIR) == 0);
+
        status = streams_xattr_get_name(handle, talloc_tos(),
                                        smb_fname->stream_name, &xattr_name);
        if (!NT_STATUS_IS_OK(status)) {
@@ -497,10 +499,26 @@ static int streams_xattr_unlink_internal(vfs_handle_struct *handle,
                goto fail;
        }
 
-       SMB_ASSERT(smb_fname->fsp != NULL);
-       SMB_ASSERT(smb_fname->fsp->base_fsp != NULL);
+       if (fsp == NULL) {
+               status = synthetic_pathref(talloc_tos(),
+                                       handle->conn->cwd_fsp,
+                                       smb_fname->base_name,
+                                       NULL,
+                                       NULL,
+                                       smb_fname->twrp,
+                                       smb_fname->flags,
+                                       &pathref);
+               if (!NT_STATUS_IS_OK(status)) {
+                       errno = ENOENT;
+                       goto fail;
+               }
+               fsp = pathref->fsp;
+       } else {
+               SMB_ASSERT(fsp_is_alternate_stream(smb_fname->fsp));
+               fsp = fsp->base_fsp;
+       }
 
-       ret = SMB_VFS_FREMOVEXATTR(smb_fname->fsp->base_fsp, xattr_name);
+       ret = SMB_VFS_FREMOVEXATTR(fsp, xattr_name);
 
        if ((ret == -1) && (errno == ENOATTR)) {
                errno = ENOENT;
@@ -511,26 +529,7 @@ static int streams_xattr_unlink_internal(vfs_handle_struct *handle,
 
  fail:
        TALLOC_FREE(xattr_name);
-       return ret;
-}
-
-static int streams_xattr_unlinkat(vfs_handle_struct *handle,
-                       struct files_struct *dirfsp,
-                       const struct smb_filename *smb_fname,
-                       int flags)
-{
-       int ret;
-       if (flags & AT_REMOVEDIR) {
-               ret = SMB_VFS_NEXT_UNLINKAT(handle,
-                               dirfsp,
-                               smb_fname,
-                               flags);
-       } else {
-               ret = streams_xattr_unlink_internal(handle,
-                               dirfsp,
-                               smb_fname,
-                               flags);
-       }
+       TALLOC_FREE(pathref);
        return ret;
 }
 
@@ -1536,6 +1535,38 @@ static bool streams_xattr_strict_lock_check(struct vfs_handle_struct *handle,
        return true;
 }
 
+static int streams_xattr_fcntl(vfs_handle_struct *handle,
+                              files_struct *fsp,
+                              int cmd,
+                              va_list cmd_arg)
+{
+       va_list dup_cmd_arg;
+       void *arg;
+       int ret;
+
+       if (fsp_is_alternate_stream(fsp)) {
+               switch (cmd) {
+               case F_GETFL:
+               case F_SETFL:
+                       break;
+               default:
+                       DBG_ERR("Unsupported fcntl() cmd [%d] on [%s]\n",
+                               cmd, fsp_str_dbg(fsp));
+                       errno = EINVAL;
+                       return -1;
+               }
+       }
+
+       va_copy(dup_cmd_arg, cmd_arg);
+       arg = va_arg(dup_cmd_arg, void *);
+
+       ret = SMB_VFS_NEXT_FCNTL(handle, fsp, cmd, arg);
+
+       va_end(dup_cmd_arg);
+
+       return ret;
+}
+
 static struct vfs_fn_pointers vfs_streams_xattr_fns = {
        .fs_capabilities_fn = streams_xattr_fs_capabilities,
        .connect_fn = streams_xattr_connect,
@@ -1564,6 +1595,7 @@ static struct vfs_fn_pointers vfs_streams_xattr_fns = {
        .filesystem_sharemode_fn = streams_xattr_filesystem_sharemode,
        .linux_setlease_fn = streams_xattr_linux_setlease,
        .strict_lock_check_fn = streams_xattr_strict_lock_check,
+       .fcntl_fn = streams_xattr_fcntl,
 
        .fchown_fn = streams_xattr_fchown,
        .fchmod_fn = streams_xattr_fchmod,