diff options
author | David Disseldorp <ddiss@suse.de> | 2011-03-01 19:17:49 +0100 |
---|---|---|
committer | Jeremy Allison <jra@samba.org> | 2011-03-02 01:16:30 +0100 |
commit | 016a8d214ab23883e9d50c46d3a8cc18f9454368 (patch) | |
tree | 6be73542e65e0e3cc72124dd1123e0aa68aa5eef | |
parent | 09b4acfd81669583a38352550dc61107c72a1d42 (diff) | |
download | samba-016a8d214ab23883e9d50c46d3a8cc18f9454368.tar.gz samba-016a8d214ab23883e9d50c46d3a8cc18f9454368.tar.bz2 samba-016a8d214ab23883e9d50c46d3a8cc18f9454368.zip |
s3-printing: vfs_connect prior to driver/dfs IO
samba3.posix_s3.rpc.spoolss.driver fails with the xattr_tdb vfs module
loaded as a part of make test. The (now checked) create_directory() call
in move_driver_to_download_area() fails, uncovering another bug in the
printer driver upload code path.
move_driver_to_download_area() creates a new conn_struct for
manipulating files in [print$]. The VFS layer is plumbed through with
the call to create_conn_struct(), however SMB_VFS_CONNECT() is never
called. Many vfs modules expect state stored at connect time with
SMB_VFS_HANDLE_SET_DATA() to be available on any IO operation and fail
if this is not the case.
This fix adds a call to SMB_VFS_CONNECT() in create_conn_struct() prior
to IO.
https://bugzilla.samba.org/show_bug.cgi?id=7976
Autobuild-User: Jeremy Allison <jra@samba.org>
Autobuild-Date: Wed Mar 2 01:16:30 CET 2011 on sn-devel-104
-rw-r--r-- | source3/printing/nt_printing.c | 3 | ||||
-rw-r--r-- | source3/rpc_server/srvsvc/srv_srvsvc_nt.c | 2 | ||||
-rw-r--r-- | source3/smbd/msdfs.c | 34 |
3 files changed, 29 insertions, 10 deletions
diff --git a/source3/printing/nt_printing.c b/source3/printing/nt_printing.c index 3b805f4f55..d77320cf02 100644 --- a/source3/printing/nt_printing.c +++ b/source3/printing/nt_printing.c @@ -726,6 +726,7 @@ static uint32 get_correct_cversion(struct pipes_struct *p, } if (conn != NULL) { vfs_ChDir(conn, oldcwd); + SMB_VFS_DISCONNECT(conn); conn_free(conn); } if (!NT_STATUS_IS_OK(*perr)) { @@ -1130,6 +1131,7 @@ WERROR move_driver_to_download_area(struct pipes_struct *p, if (conn != NULL) { vfs_ChDir(conn, oldcwd); + SMB_VFS_DISCONNECT(conn); conn_free(conn); } @@ -1968,6 +1970,7 @@ bool delete_driver_files(const struct auth_serversupplied_info *session_info, err_out: if (conn != NULL) { vfs_ChDir(conn, oldcwd); + SMB_VFS_DISCONNECT(conn); conn_free(conn); } return ret; diff --git a/source3/rpc_server/srvsvc/srv_srvsvc_nt.c b/source3/rpc_server/srvsvc/srv_srvsvc_nt.c index 31df4886bb..40687a0e4e 100644 --- a/source3/rpc_server/srvsvc/srv_srvsvc_nt.c +++ b/source3/rpc_server/srvsvc/srv_srvsvc_nt.c @@ -2231,6 +2231,7 @@ error_exit: } if (conn) { + SMB_VFS_DISCONNECT(conn); conn_free(conn); } @@ -2374,6 +2375,7 @@ error_exit: } if (conn) { + SMB_VFS_DISCONNECT(conn); conn_free(conn); } diff --git a/source3/smbd/msdfs.c b/source3/smbd/msdfs.c index 07b0933031..c11e66e3b8 100644 --- a/source3/smbd/msdfs.c +++ b/source3/smbd/msdfs.c @@ -212,7 +212,7 @@ static NTSTATUS parse_dfs_path(connection_struct *conn, /******************************************************** Fake up a connection struct for the VFS layer. - Note this CHANGES CWD !!!! JRA. + Note: this performs a vfs connect and CHANGES CWD !!!! JRA. *********************************************************/ NTSTATUS create_conn_struct(TALLOC_CTX *ctx, @@ -225,6 +225,7 @@ NTSTATUS create_conn_struct(TALLOC_CTX *ctx, connection_struct *conn; char *connpath; char *oldcwd; + const char *vfs_user; conn = TALLOC_ZERO_P(ctx, connection_struct); if (conn == NULL) { @@ -265,6 +266,10 @@ NTSTATUS create_conn_struct(TALLOC_CTX *ctx, TALLOC_FREE(conn); return NT_STATUS_NO_MEMORY; } + vfs_user = conn->session_info->unix_name; + } else { + /* use current authenticated user in absence of session_info */ + vfs_user = get_current_username(); } set_conn_connectpath(conn, connpath); @@ -276,6 +281,13 @@ NTSTATUS create_conn_struct(TALLOC_CTX *ctx, return status; } + /* this must be the first filesystem operation that we do */ + if (SMB_VFS_CONNECT(conn, lp_servicename(snum), vfs_user) < 0) { + DEBUG(0,("VFS connect failed!\n")); + conn_free(conn); + return NT_STATUS_UNSUCCESSFUL; + } + conn->fs_capabilities = SMB_VFS_FS_CAPABILITIES(conn, &conn->ts_res); /* @@ -937,10 +949,7 @@ NTSTATUS get_referred_path(TALLOC_CTX *ctx, if (!NT_STATUS_EQUAL(status, NT_STATUS_PATH_NOT_COVERED)) { DEBUG(3,("get_referred_path: No valid referrals for path %s\n", dfs_path)); - vfs_ChDir(conn, oldpath); - conn_free(conn); - TALLOC_FREE(pdp); - return status; + goto err_exit; } /* We know this is a valid dfs link. Parse the targetpath. */ @@ -949,16 +958,17 @@ NTSTATUS get_referred_path(TALLOC_CTX *ctx, &jucn->referral_count)) { DEBUG(3,("get_referred_path: failed to parse symlink " "target %s\n", targetpath )); - vfs_ChDir(conn, oldpath); - conn_free(conn); - TALLOC_FREE(pdp); - return NT_STATUS_NOT_FOUND; + status = NT_STATUS_NOT_FOUND; + goto err_exit; } + status = NT_STATUS_OK; + err_exit: vfs_ChDir(conn, oldpath); + SMB_VFS_DISCONNECT(conn); conn_free(conn); TALLOC_FREE(pdp); - return NT_STATUS_OK; + return status; } static int setup_ver2_dfs_referral(const char *pathname, @@ -1373,6 +1383,7 @@ static bool junction_to_local_path(const struct junction_map *jucn, jucn->volume_name); if (!*pp_path_out) { vfs_ChDir(*conn_out, *oldpath); + SMB_VFS_DISCONNECT(*conn_out); conn_free(*conn_out); return False; } @@ -1461,6 +1472,7 @@ bool create_msdfs_link(const struct junction_map *jucn) out: vfs_ChDir(conn, cwd); + SMB_VFS_DISCONNECT(conn); conn_free(conn); return ret; } @@ -1492,6 +1504,7 @@ bool remove_msdfs_link(const struct junction_map *jucn) TALLOC_FREE(smb_fname); vfs_ChDir(conn, cwd); + SMB_VFS_DISCONNECT(conn); conn_free(conn); return ret; } @@ -1556,6 +1569,7 @@ static int count_dfs_links(TALLOC_CTX *ctx, int snum) out: vfs_ChDir(conn, cwd); + SMB_VFS_DISCONNECT(conn); conn_free(conn); return cnt; } |