diff options
author | Jeremy Allison <jra@samba.org> | 2011-10-21 14:12:41 -0700 |
---|---|---|
committer | Jeremy Allison <jra@samba.org> | 2011-10-22 01:37:41 +0200 |
commit | 662e9c04fbdf8e01036ab98783693051b0eb9c7e (patch) | |
tree | 21ee96debd90ed2abcd81a1cc620c2738e2c1da3 /source3/smbd/trans2.c | |
parent | 950f1218b3b5b85d95190083985632a4e1046f10 (diff) | |
download | samba-662e9c04fbdf8e01036ab98783693051b0eb9c7e.tar.gz samba-662e9c04fbdf8e01036ab98783693051b0eb9c7e.tar.bz2 samba-662e9c04fbdf8e01036ab98783693051b0eb9c7e.zip |
Fix bug #8541 - readlink() on Linux clients fails if the symlink target is outside of the share.
The key is to only allow the lookup to succeed if it's a UNIX level lookup or readlink,
but disallow all other operations.
Autobuild-User: Jeremy Allison <jra@samba.org>
Autobuild-Date: Sat Oct 22 01:37:41 CEST 2011 on sn-devel-104
Diffstat (limited to 'source3/smbd/trans2.c')
-rw-r--r-- | source3/smbd/trans2.c | 18 |
1 files changed, 14 insertions, 4 deletions
diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 1a381950df..6ac95bde68 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -2270,6 +2270,7 @@ static void call_trans2findfirst(connection_struct *conn, TALLOC_CTX *ctx = talloc_tos(); struct dptr_struct *dirptr = NULL; struct smbd_server_connection *sconn = req->sconn; + uint32_t ucf_flags = (UCF_SAVE_LCOMP | UCF_ALWAYS_ALLOW_WCARD_LCOMP); if (total_params < 13) { reply_nterror(req, NT_STATUS_INVALID_PARAMETER); @@ -2313,6 +2314,7 @@ close_if_end = %d requires_resume_key = %d level = 0x%x, max_data_bytes = %d\n", reply_nterror(req, NT_STATUS_INVALID_LEVEL); goto out; } + ucf_flags |= UCF_UNIX_NAME_LOOKUP; break; default: reply_nterror(req, NT_STATUS_INVALID_LEVEL); @@ -5103,6 +5105,7 @@ static void call_trans2qfilepathinfo(connection_struct *conn, } else { uint32_t name_hash; char *fname = NULL; + uint32_t ucf_flags = 0; /* qpathinfo */ if (total_params < 7) { @@ -5114,9 +5117,16 @@ static void call_trans2qfilepathinfo(connection_struct *conn, DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QPATHINFO: level = %d\n", info_level)); - if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) { - reply_nterror(req, NT_STATUS_INVALID_LEVEL); - return; + if (INFO_LEVEL_IS_UNIX(info_level)) { + if (!lp_unix_extensions()) { + reply_nterror(req, NT_STATUS_INVALID_LEVEL); + return; + } + if (info_level == SMB_QUERY_FILE_UNIX_BASIC || + info_level == SMB_QUERY_FILE_UNIX_INFO2 || + info_level == SMB_QUERY_FILE_UNIX_LINK) { + ucf_flags |= UCF_UNIX_NAME_LOOKUP; + } } srvstr_get_path(req, params, req->flags2, &fname, ¶ms[6], @@ -5131,7 +5141,7 @@ static void call_trans2qfilepathinfo(connection_struct *conn, conn, req->flags2 & FLAGS2_DFS_PATHNAMES, fname, - 0, + ucf_flags, NULL, &smb_fname); if (!NT_STATUS_IS_OK(status)) { |