From 4b21ad9db7babb1e278fa2e3b81737b6df36e2d2 Mon Sep 17 00:00:00 2001 From: Sam Liddicott Date: Thu, 14 May 2009 08:58:50 +0100 Subject: Have ntvfs_connect() accept union smb_tcon *tcon instead of char* sharename This change brings ntvfs_connect into compliance with other ntvfs functions which take an ntvfs module, an ntvfs request and an smb io union. It now becomes the responsibility of ntvfs modules to examine tcon->generic.level themselves and derive the share name and any other options directly; e.g. const char *sharename; switch (tcon->generic.level) { case RAW_TCON_TCON: sharename = tcon->tcon.in.service; break; case RAW_TCON_TCONX: sharename = tcon->tconx.in.path; break; case RAW_TCON_SMB2: default: return NT_STATUS_INVALID_LEVEL; } if (strncmp(sharename, "\\\\", 2) == 0) { char *p = strchr(sharename+2, '\\'); if (p) { sharename = p + 1; } } service.c smbsrv_tcon_backend() is called before ntvfs_connect and fills in some of the tcon->..out values. For the case of RAW_TCON_TCONX, it filles out tcon->tconx.out.tid and tcon->tconx.out.options For the case of RAW_TCON_TCON it fills out tcon->tcon.out.tid and tcon->tcon.out.max_xmit Thus the ntvfs_connect function for vfs modules may override these values if desired, but are not required to. ntvfs_connect functions are required to fill in the tcon->tconx.out.*_type fields, for RAW_TCON_TCONX, perhaps something like: if (tcon->generic.level == RAW_TCON_TCONX) { tcon->tconx.out.fs_type = ntvfs->ctx->fs_type; tcon->tconx.out.dev_type = ntvfs->ctx->dev_type; } Signed-off-by: Sam Liddicott (I fixed the ntvfs_connect() in the smb_server/smb2/ and the RAW_TCON_SMB2 switch case in the modules) Signed-off-by: Stefan Metzmacher --- source4/ntvfs/cifs/vfs_cifs.c | 30 +++++++++++++++++++++++++- source4/ntvfs/cifs_posix_cli/vfs_cifs_posix.c | 30 +++++++++++++++++++++++++- source4/ntvfs/ipc/vfs_ipc.c | 30 +++++++++++++++++++++++++- source4/ntvfs/nbench/vfs_nbench.c | 5 +++-- source4/ntvfs/ntvfs.h | 2 +- source4/ntvfs/ntvfs_interface.c | 9 ++++---- source4/ntvfs/posix/vfs_posix.c | 30 +++++++++++++++++++++++++- source4/ntvfs/print/vfs_print.c | 7 +++++- source4/ntvfs/simple/vfs_simple.c | 30 +++++++++++++++++++++++++- source4/ntvfs/smb2/vfs_smb2.c | 31 +++++++++++++++++++++++++-- source4/ntvfs/unixuid/vfs_unixuid.c | 4 ++-- 11 files changed, 191 insertions(+), 17 deletions(-) (limited to 'source4/ntvfs') diff --git a/source4/ntvfs/cifs/vfs_cifs.c b/source4/ntvfs/cifs/vfs_cifs.c index be9096b01f..1cb6a46615 100644 --- a/source4/ntvfs/cifs/vfs_cifs.c +++ b/source4/ntvfs/cifs/vfs_cifs.c @@ -136,7 +136,8 @@ static bool oplock_handler(struct smbcli_transport *transport, uint16_t tid, uin connect to a share - used when a tree_connect operation comes in. */ static NTSTATUS cvfs_connect(struct ntvfs_module_context *ntvfs, - struct ntvfs_request *req, const char *sharename) + struct ntvfs_request *req, + union smb_tcon *tcon) { NTSTATUS status; struct cvfs_private *p; @@ -147,6 +148,28 @@ static NTSTATUS cvfs_connect(struct ntvfs_module_context *ntvfs, struct cli_credentials *credentials; bool machine_account; + const char* sharename; + + switch (tcon->generic.level) { + case RAW_TCON_TCON: + sharename = tcon->tcon.in.service; + break; + case RAW_TCON_TCONX: + sharename = tcon->tconx.in.path; + break; + case RAW_TCON_SMB2: + sharename = tcon->smb2.in.path; + break; + default: + return NT_STATUS_INVALID_LEVEL; + } + + if (strncmp(sharename, "\\\\", 2) == 0) { + char *p = strchr(sharename+2, '\\'); + if (p) { + sharename = p + 1; + } + } /* Here we need to determine which server to connect to. * For now we use parametric options, type cifs. @@ -242,6 +265,11 @@ static NTSTATUS cvfs_connect(struct ntvfs_module_context *ntvfs, ntvfs->ctx->dev_type = talloc_strdup(ntvfs->ctx, "A:"); NT_STATUS_HAVE_NO_MEMORY(ntvfs->ctx->dev_type); + if (tcon->generic.level == RAW_TCON_TCONX) { + tcon->tconx.out.fs_type = ntvfs->ctx->fs_type; + tcon->tconx.out.dev_type = ntvfs->ctx->dev_type; + } + /* we need to receive oplock break requests from the server */ smbcli_oplock_handler(p->transport, oplock_handler, p); diff --git a/source4/ntvfs/cifs_posix_cli/vfs_cifs_posix.c b/source4/ntvfs/cifs_posix_cli/vfs_cifs_posix.c index 02fe9f2264..7b7c17a9be 100644 --- a/source4/ntvfs/cifs_posix_cli/vfs_cifs_posix.c +++ b/source4/ntvfs/cifs_posix_cli/vfs_cifs_posix.c @@ -48,11 +48,34 @@ that comes later) */ static NTSTATUS cifspsx_connect(struct ntvfs_module_context *ntvfs, - struct ntvfs_request *req, const char *sharename) + struct ntvfs_request *req, + union smb_tcon* tcon) { struct stat st; struct cifspsx_private *p; struct share_config *scfg = ntvfs->ctx->config; + const char *sharename; + + switch (tcon->generic.level) { + case RAW_TCON_TCON: + sharename = tcon->tcon.in.service; + break; + case RAW_TCON_TCONX: + sharename = tcon->tconx.in.path; + break; + case RAW_TCON_SMB2: + sharename = tcon->smb2.in.path; + break; + default: + return NT_STATUS_INVALID_LEVEL; + } + + if (strncmp(sharename, "\\\\", 2) == 0) { + char *p = strchr(sharename+2, '\\'); + if (p) { + sharename = p + 1; + } + } p = talloc(ntvfs, struct cifspsx_private); NT_STATUS_HAVE_NO_MEMORY(p); @@ -74,6 +97,11 @@ static NTSTATUS cifspsx_connect(struct ntvfs_module_context *ntvfs, ntvfs->ctx->dev_type = talloc_strdup(ntvfs->ctx, "A:"); NT_STATUS_HAVE_NO_MEMORY(ntvfs->ctx->dev_type); + if (tcon->generic.level == RAW_TCON_TCONX) { + tcon->tconx.out.fs_type = ntvfs->ctx->fs_type; + tcon->tconx.out.dev_type = ntvfs->ctx->dev_type; + } + ntvfs->private_data = p; DEBUG(0,("WARNING: ntvfs cifs posix: connect to share [%s] with ROOT privileges!!!\n",sharename)); diff --git a/source4/ntvfs/ipc/vfs_ipc.c b/source4/ntvfs/ipc/vfs_ipc.c index 2f05a86dfa..20b00f24e3 100644 --- a/source4/ntvfs/ipc/vfs_ipc.c +++ b/source4/ntvfs/ipc/vfs_ipc.c @@ -88,10 +88,33 @@ static struct pipe_state *pipe_state_find_key(struct ipc_private *ipriv, struct connect to a share - always works */ static NTSTATUS ipc_connect(struct ntvfs_module_context *ntvfs, - struct ntvfs_request *req, const char *sharename) + struct ntvfs_request *req, + union smb_tcon* tcon) { NTSTATUS status; struct ipc_private *ipriv; + const char *sharename; + + switch (tcon->generic.level) { + case RAW_TCON_TCON: + sharename = tcon->tcon.in.service; + break; + case RAW_TCON_TCONX: + sharename = tcon->tconx.in.path; + break; + case RAW_TCON_SMB2: + sharename = tcon->smb2.in.path; + break; + default: + return NT_STATUS_INVALID_LEVEL; + } + + if (strncmp(sharename, "\\\\", 2) == 0) { + char *p = strchr(sharename+2, '\\'); + if (p) { + sharename = p + 1; + } + } ntvfs->ctx->fs_type = talloc_strdup(ntvfs->ctx, "IPC"); NT_STATUS_HAVE_NO_MEMORY(ntvfs->ctx->fs_type); @@ -99,6 +122,11 @@ static NTSTATUS ipc_connect(struct ntvfs_module_context *ntvfs, ntvfs->ctx->dev_type = talloc_strdup(ntvfs->ctx, "IPC"); NT_STATUS_HAVE_NO_MEMORY(ntvfs->ctx->dev_type); + if (tcon->generic.level == RAW_TCON_TCONX) { + tcon->tconx.out.fs_type = ntvfs->ctx->fs_type; + tcon->tconx.out.dev_type = ntvfs->ctx->dev_type; + } + /* prepare the private state for this connection */ ipriv = talloc(ntvfs, struct ipc_private); NT_STATUS_HAVE_NO_MEMORY(ipriv); diff --git a/source4/ntvfs/nbench/vfs_nbench.c b/source4/ntvfs/nbench/vfs_nbench.c index 7ba2e7c649..2500140762 100644 --- a/source4/ntvfs/nbench/vfs_nbench.c +++ b/source4/ntvfs/nbench/vfs_nbench.c @@ -111,7 +111,8 @@ static char *nbench_ntvfs_handle_string(struct ntvfs_request *req, struct ntvfs_ connect to a share - used when a tree_connect operation comes in. */ static NTSTATUS nbench_connect(struct ntvfs_module_context *ntvfs, - struct ntvfs_request *req, const char *sharename) + struct ntvfs_request *req, + union smb_tcon* con) { struct nbench_private *nprivates; NTSTATUS status; @@ -133,7 +134,7 @@ static NTSTATUS nbench_connect(struct ntvfs_module_context *ntvfs, ntvfs->private_data = nprivates; - status = ntvfs_next_connect(ntvfs, req, sharename); + status = ntvfs_next_connect(ntvfs, req, con); return status; } diff --git a/source4/ntvfs/ntvfs.h b/source4/ntvfs/ntvfs.h index b62595967f..5e9c657737 100644 --- a/source4/ntvfs/ntvfs.h +++ b/source4/ntvfs/ntvfs.h @@ -49,7 +49,7 @@ struct ntvfs_ops { /* initial setup */ NTSTATUS (*connect)(struct ntvfs_module_context *ntvfs, struct ntvfs_request *req, - const char *sharename); + union smb_tcon *tcon); NTSTATUS (*disconnect)(struct ntvfs_module_context *ntvfs); /* async_setup - called when a backend is processing a async request */ diff --git a/source4/ntvfs/ntvfs_interface.c b/source4/ntvfs/ntvfs_interface.c index 6d3fe55c06..808bd97e61 100644 --- a/source4/ntvfs/ntvfs_interface.c +++ b/source4/ntvfs/ntvfs_interface.c @@ -22,13 +22,13 @@ #include "ntvfs/ntvfs.h" /* connect/disconnect */ -NTSTATUS ntvfs_connect(struct ntvfs_request *req, const char *sharename) +NTSTATUS ntvfs_connect(struct ntvfs_request *req, union smb_tcon *tcon) { struct ntvfs_module_context *ntvfs = req->ctx->modules; if (!ntvfs->ops->connect) { return NT_STATUS_NOT_IMPLEMENTED; } - return ntvfs->ops->connect(ntvfs, req, sharename); + return ntvfs->ops->connect(ntvfs, req, tcon); } NTSTATUS ntvfs_disconnect(struct ntvfs_context *ntvfs_ctx) @@ -335,12 +335,13 @@ NTSTATUS ntvfs_cancel(struct ntvfs_request *req) /* initial setup */ NTSTATUS ntvfs_next_connect(struct ntvfs_module_context *ntvfs, - struct ntvfs_request *req, const char *sharename) + struct ntvfs_request *req, + union smb_tcon *tcon) { if (!ntvfs->next || !ntvfs->next->ops->connect) { return NT_STATUS_NOT_IMPLEMENTED; } - return ntvfs->next->ops->connect(ntvfs->next, req, sharename); + return ntvfs->next->ops->connect(ntvfs->next, req, tcon); } NTSTATUS ntvfs_next_disconnect(struct ntvfs_module_context *ntvfs) diff --git a/source4/ntvfs/posix/vfs_posix.c b/source4/ntvfs/posix/vfs_posix.c index 29ef701dee..5134c0a608 100644 --- a/source4/ntvfs/posix/vfs_posix.c +++ b/source4/ntvfs/posix/vfs_posix.c @@ -168,12 +168,35 @@ static int pvfs_state_destructor(struct pvfs_state *pvfs) that comes later) */ static NTSTATUS pvfs_connect(struct ntvfs_module_context *ntvfs, - struct ntvfs_request *req, const char *sharename) + struct ntvfs_request *req, + union smb_tcon* tcon) { struct pvfs_state *pvfs; struct stat st; char *base_directory; NTSTATUS status; + const char *sharename; + + switch (tcon->generic.level) { + case RAW_TCON_TCON: + sharename = tcon->tcon.in.service; + break; + case RAW_TCON_TCONX: + sharename = tcon->tconx.in.path; + break; + case RAW_TCON_SMB2: + sharename = tcon->smb2.in.path; + break; + default: + return NT_STATUS_INVALID_LEVEL; + } + + if (strncmp(sharename, "\\\\", 2) == 0) { + char *p = strchr(sharename+2, '\\'); + if (p) { + sharename = p + 1; + } + } /* * TODO: call this from ntvfs_posix_init() @@ -209,6 +232,11 @@ static NTSTATUS pvfs_connect(struct ntvfs_module_context *ntvfs, ntvfs->ctx->dev_type = talloc_strdup(ntvfs->ctx, "A:"); NT_STATUS_HAVE_NO_MEMORY(ntvfs->ctx->dev_type); + if (tcon->generic.level == RAW_TCON_TCONX) { + tcon->tconx.out.fs_type = ntvfs->ctx->fs_type; + tcon->tconx.out.dev_type = ntvfs->ctx->dev_type; + } + ntvfs->private_data = pvfs; pvfs->brl_context = brl_init(pvfs, diff --git a/source4/ntvfs/print/vfs_print.c b/source4/ntvfs/print/vfs_print.c index 540e51a43b..0530e04f6d 100644 --- a/source4/ntvfs/print/vfs_print.c +++ b/source4/ntvfs/print/vfs_print.c @@ -32,7 +32,7 @@ is available */ static NTSTATUS print_connect(struct ntvfs_module_context *ntvfs, - struct ntvfs_request *req, const char *sharename) + struct ntvfs_request *req, union smb_tcon* tcon) { ntvfs->ctx->fs_type = talloc_strdup(ntvfs->ctx, "NTFS"); NT_STATUS_HAVE_NO_MEMORY(ntvfs->ctx->fs_type); @@ -40,6 +40,11 @@ static NTSTATUS print_connect(struct ntvfs_module_context *ntvfs, ntvfs->ctx->dev_type = talloc_strdup(ntvfs->ctx, "LPT1:"); NT_STATUS_HAVE_NO_MEMORY(ntvfs->ctx->dev_type); + if (tcon->generic.level == RAW_TCON_TCONX) { + tcon->tconx.out.fs_type = ntvfs->ctx->fs_type; + tcon->tconx.out.dev_type = ntvfs->ctx->dev_type; + } + return NT_STATUS_OK; } diff --git a/source4/ntvfs/simple/vfs_simple.c b/source4/ntvfs/simple/vfs_simple.c index bf0afcec0a..aabaa3c47f 100644 --- a/source4/ntvfs/simple/vfs_simple.c +++ b/source4/ntvfs/simple/vfs_simple.c @@ -47,11 +47,34 @@ that comes later) */ static NTSTATUS svfs_connect(struct ntvfs_module_context *ntvfs, - struct ntvfs_request *req, const char *sharename) + struct ntvfs_request *req, + union smb_tcon* tcon) { struct stat st; struct svfs_private *p; struct share_config *scfg = ntvfs->ctx->config; + const char *sharename; + + switch (tcon->generic.level) { + case RAW_TCON_TCON: + sharename = tcon->tcon.in.service; + break; + case RAW_TCON_TCONX: + sharename = tcon->tconx.in.path; + break; + case RAW_TCON_SMB2: + sharename = tcon->smb2.in.path; + break; + default: + return NT_STATUS_INVALID_LEVEL; + } + + if (strncmp(sharename, "\\\\", 2) == 0) { + char *p = strchr(sharename+2, '\\'); + if (p) { + sharename = p + 1; + } + } p = talloc(ntvfs, struct svfs_private); NT_STATUS_HAVE_NO_MEMORY(p); @@ -73,6 +96,11 @@ static NTSTATUS svfs_connect(struct ntvfs_module_context *ntvfs, ntvfs->ctx->dev_type = talloc_strdup(ntvfs->ctx, "A:"); NT_STATUS_HAVE_NO_MEMORY(ntvfs->ctx->dev_type); + if (tcon->generic.level == RAW_TCON_TCONX) { + tcon->tconx.out.fs_type = ntvfs->ctx->fs_type; + tcon->tconx.out.dev_type = ntvfs->ctx->dev_type; + } + ntvfs->private_data = p; return NT_STATUS_OK; diff --git a/source4/ntvfs/smb2/vfs_smb2.c b/source4/ntvfs/smb2/vfs_smb2.c index d1e194f638..6fc0d42b02 100644 --- a/source4/ntvfs/smb2/vfs_smb2.c +++ b/source4/ntvfs/smb2/vfs_smb2.c @@ -154,11 +154,12 @@ static NTSTATUS smb2_get_roothandle(struct smb2_tree *tree, struct smb2_handle * connect to a share - used when a tree_connect operation comes in. */ static NTSTATUS cvfs_connect(struct ntvfs_module_context *ntvfs, - struct ntvfs_request *req, const char *sharename) + struct ntvfs_request *req, + union smb_tcon* tcon) { NTSTATUS status; struct cvfs_private *p; - const char *host, *user, *pass, *domain, *remote_share; + const char *host, *user, *pass, *domain, *remote_share, *sharename; struct composite_context *creq; struct share_config *scfg = ntvfs->ctx->config; struct smb2_tree *tree; @@ -166,6 +167,27 @@ static NTSTATUS cvfs_connect(struct ntvfs_module_context *ntvfs, bool machine_account; struct smbcli_options options; + switch (tcon->generic.level) { + case RAW_TCON_TCON: + sharename = tcon->tcon.in.service; + break; + case RAW_TCON_TCONX: + sharename = tcon->tconx.in.path; + break; + case RAW_TCON_SMB2: + sharename = tcon->smb2.in.path; + break; + default: + return NT_STATUS_INVALID_LEVEL; + } + + if (strncmp(sharename, "\\\\", 2) == 0) { + char *p = strchr(sharename+2, '\\'); + if (p) { + sharename = p + 1; + } + } + /* Here we need to determine which server to connect to. * For now we use parametric options, type cifs. * Later we will use security=server and auth_server.c. @@ -251,6 +273,11 @@ static NTSTATUS cvfs_connect(struct ntvfs_module_context *ntvfs, ntvfs->ctx->dev_type = talloc_strdup(ntvfs->ctx, "A:"); NT_STATUS_HAVE_NO_MEMORY(ntvfs->ctx->dev_type); + if (tcon->generic.level == RAW_TCON_TCONX) { + tcon->tconx.out.fs_type = ntvfs->ctx->fs_type; + tcon->tconx.out.dev_type = ntvfs->ctx->dev_type; + } + /* we need to receive oplock break requests from the server */ /* TODO: enable oplocks smbcli_oplock_handler(p->transport, oplock_handler, p); diff --git a/source4/ntvfs/unixuid/vfs_unixuid.c b/source4/ntvfs/unixuid/vfs_unixuid.c index 062fa41889..3ef341d61a 100644 --- a/source4/ntvfs/unixuid/vfs_unixuid.c +++ b/source4/ntvfs/unixuid/vfs_unixuid.c @@ -293,7 +293,7 @@ static NTSTATUS unixuid_setup_security(struct ntvfs_module_context *ntvfs, connect to a share - used when a tree_connect operation comes in. */ static NTSTATUS unixuid_connect(struct ntvfs_module_context *ntvfs, - struct ntvfs_request *req, const char *sharename) + struct ntvfs_request *req, union smb_tcon *tcon) { struct unixuid_private *priv; NTSTATUS status; @@ -321,7 +321,7 @@ static NTSTATUS unixuid_connect(struct ntvfs_module_context *ntvfs, /* we don't use PASS_THRU_REQ here, as the connect operation runs with root privileges. This allows the backends to setup any database links they might need during the connect. */ - status = ntvfs_next_connect(ntvfs, req, sharename); + status = ntvfs_next_connect(ntvfs, req, tcon); return status; } -- cgit