summaryrefslogtreecommitdiffstats
path: root/source3/smbd/vfs.c
diff options
context:
space:
mode:
Diffstat (limited to 'source3/smbd/vfs.c')
-rw-r--r--source3/smbd/vfs.c87
1 files changed, 49 insertions, 38 deletions
diff --git a/source3/smbd/vfs.c b/source3/smbd/vfs.c
index 3b482e7f0cd..7be38672678 100644
--- a/source3/smbd/vfs.c
+++ b/source3/smbd/vfs.c
@@ -183,7 +183,7 @@ bool vfs_init_custom(connection_struct *conn, const char *vfs_object)
DEBUGADD(5,("Successfully loaded vfs module [%s] with the new modules system\n", vfs_object));
- handle = TALLOC_ZERO_P(conn, vfs_handle_struct);
+ handle = talloc_zero(conn, vfs_handle_struct);
if (!handle) {
DEBUG(0,("TALLOC_ZERO() failed!\n"));
goto fail;
@@ -795,7 +795,7 @@ int vfs_ChDir(connection_struct *conn, const char *path)
char *vfs_GetWd(TALLOC_CTX *ctx, connection_struct *conn)
{
- char s[PATH_MAX+1];
+ char *current_dir = NULL;
char *result = NULL;
DATA_BLOB cache_value;
struct file_id key;
@@ -803,8 +803,6 @@ char *vfs_GetWd(TALLOC_CTX *ctx, connection_struct *conn)
struct smb_filename *smb_fname_full = NULL;
NTSTATUS status;
- *s = 0;
-
if (!lp_getwd_cache()) {
goto nocache;
}
@@ -866,7 +864,8 @@ char *vfs_GetWd(TALLOC_CTX *ctx, connection_struct *conn)
* systems, or the not quite so bad getwd.
*/
- if (!SMB_VFS_GETWD(conn,s)) {
+ current_dir = SMB_VFS_GETWD(conn);
+ if (current_dir == NULL) {
DEBUG(0, ("vfs_GetWd: SMB_VFS_GETWD call failed: %s\n",
strerror(errno)));
goto out;
@@ -877,10 +876,11 @@ char *vfs_GetWd(TALLOC_CTX *ctx, connection_struct *conn)
memcache_add(smbd_memcache(), GETWD_CACHE,
data_blob_const(&key, sizeof(key)),
- data_blob_const(s, strlen(s)+1));
+ data_blob_const(current_dir,
+ strlen(current_dir)+1));
}
- result = talloc_strdup(ctx, s);
+ result = talloc_strdup(ctx, current_dir);
if (result == NULL) {
errno = ENOMEM;
}
@@ -888,6 +888,7 @@ char *vfs_GetWd(TALLOC_CTX *ctx, connection_struct *conn)
out:
TALLOC_FREE(smb_fname_dot);
TALLOC_FREE(smb_fname_full);
+ SAFE_FREE(current_dir);
return result;
}
@@ -899,6 +900,8 @@ char *vfs_GetWd(TALLOC_CTX *ctx, connection_struct *conn)
NTSTATUS check_reduced_name(connection_struct *conn, const char *fname)
{
char *resolved_name = NULL;
+ bool allow_symlinks = true;
+ bool allow_widelinks = false;
DEBUG(3,("check_reduced_name [%s] [%s]\n", fname, conn->connectpath));
@@ -973,9 +976,13 @@ NTSTATUS check_reduced_name(connection_struct *conn, const char *fname)
return NT_STATUS_OBJECT_NAME_INVALID;
}
- /* Check for widelinks allowed. */
- if (!lp_widelinks(SNUM(conn))) {
+ allow_widelinks = lp_widelinks(SNUM(conn));
+ allow_symlinks = lp_symlinks(SNUM(conn));
+
+ /* Common widelinks and symlinks checks. */
+ if (!allow_widelinks || !allow_symlinks) {
const char *conn_rootdir;
+ size_t rootdir_len;
conn_rootdir = SMB_VFS_CONNECTPATH(conn, fname);
if (conn_rootdir == NULL) {
@@ -985,8 +992,9 @@ NTSTATUS check_reduced_name(connection_struct *conn, const char *fname)
return NT_STATUS_ACCESS_DENIED;
}
+ rootdir_len = strlen(conn_rootdir);
if (strncmp(conn_rootdir, resolved_name,
- strlen(conn_rootdir)) != 0) {
+ rootdir_len) != 0) {
DEBUG(2, ("check_reduced_name: Bad access "
"attempt: %s is a symlink outside the "
"share path\n", fname));
@@ -995,35 +1003,38 @@ NTSTATUS check_reduced_name(connection_struct *conn, const char *fname)
SAFE_FREE(resolved_name);
return NT_STATUS_ACCESS_DENIED;
}
- }
- /* Check if we are allowing users to follow symlinks */
- /* Patch from David Clerc <David.Clerc@cui.unige.ch>
- University of Geneva */
+ /* Extra checks if all symlinks are disallowed. */
+ if (!allow_symlinks) {
+ /* fname can't have changed in resolved_path. */
+ const char *p = &resolved_name[rootdir_len];
-#ifdef S_ISLNK
- if (!lp_symlinks(SNUM(conn))) {
- struct smb_filename *smb_fname = NULL;
- NTSTATUS status;
+ /* *p can be '\0' if fname was "." */
+ if (*p == '\0' && ISDOT(fname)) {
+ goto out;
+ }
- status = create_synthetic_smb_fname(talloc_tos(), fname, NULL,
- NULL, &smb_fname);
- if (!NT_STATUS_IS_OK(status)) {
- SAFE_FREE(resolved_name);
- return status;
+ if (*p != '/') {
+ DEBUG(2, ("check_reduced_name: logic error (%c) "
+ "in resolved_name: %s\n",
+ *p,
+ fname));
+ SAFE_FREE(resolved_name);
+ return NT_STATUS_ACCESS_DENIED;
+ }
+
+ p++;
+ if (strcmp(fname, p)!=0) {
+ DEBUG(2, ("check_reduced_name: Bad access "
+ "attempt: %s is a symlink\n",
+ fname));
+ SAFE_FREE(resolved_name);
+ return NT_STATUS_ACCESS_DENIED;
+ }
}
+ }
- if ( (SMB_VFS_LSTAT(conn, smb_fname) != -1) &&
- (S_ISLNK(smb_fname->st.st_ex_mode)) ) {
- SAFE_FREE(resolved_name);
- DEBUG(3,("check_reduced_name: denied: file path name "
- "%s is a symlink\n",resolved_name));
- TALLOC_FREE(smb_fname);
- return NT_STATUS_ACCESS_DENIED;
- }
- TALLOC_FREE(smb_fname);
- }
-#endif
+ out:
DEBUG(3,("check_reduced_name: %s reduced to %s\n", fname,
resolved_name));
@@ -1164,7 +1175,7 @@ int smb_vfs_call_set_quota(struct vfs_handle_struct *handle,
int smb_vfs_call_get_shadow_copy_data(struct vfs_handle_struct *handle,
struct files_struct *fsp,
- SHADOW_COPY_DATA *shadow_copy_data,
+ struct shadow_copy_data *shadow_copy_data,
bool labels)
{
VFS_FIND(get_shadow_copy_data);
@@ -1496,7 +1507,7 @@ NTSTATUS vfs_chown_fsp(files_struct *fsp, uid_t uid, gid_t gid)
}
ZERO_STRUCT(local_fname);
- local_fname.base_name = CONST_DISCARD(char *,final_component);
+ local_fname.base_name = discard_const_p(char, final_component);
/* Must use lstat here. */
ret = SMB_VFS_LSTAT(fsp->conn, &local_fname);
@@ -1543,10 +1554,10 @@ int smb_vfs_call_chdir(struct vfs_handle_struct *handle, const char *path)
return handle->fns->chdir(handle, path);
}
-char *smb_vfs_call_getwd(struct vfs_handle_struct *handle, char *buf)
+char *smb_vfs_call_getwd(struct vfs_handle_struct *handle)
{
VFS_FIND(getwd);
- return handle->fns->getwd(handle, buf);
+ return handle->fns->getwd(handle);
}
int smb_vfs_call_ntimes(struct vfs_handle_struct *handle,