summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--source3/smbd/filename.c82
-rw-r--r--source3/smbd/proto.h11
-rw-r--r--source3/smbd/vfs.c15
3 files changed, 103 insertions, 5 deletions
diff --git a/source3/smbd/filename.c b/source3/smbd/filename.c
index 835f3b40d1..b3e132b7ea 100644
--- a/source3/smbd/filename.c
+++ b/source3/smbd/filename.c
@@ -1021,6 +1021,26 @@ NTSTATUS check_name(connection_struct *conn, const char *name)
}
/****************************************************************************
+ Must be called as root. Creates the struct priv_backup_restore_paths structure
+ attached to the struct smb_request if this call is successful.
+****************************************************************************/
+
+static NTSTATUS check_name_with_privilege(connection_struct *conn,
+ struct smb_request *smbreq,
+ const char *name)
+{
+ NTSTATUS status = check_veto_path(conn, name);
+
+ if (!NT_STATUS_IS_OK(status)) {
+ return status;
+ }
+ return check_reduced_name_with_privilege(conn,
+ name,
+ NULL,
+ NULL);
+}
+
+/****************************************************************************
Check if two filenames are equal.
This needs to be careful about whether we are case sensitive.
****************************************************************************/
@@ -1257,6 +1277,7 @@ static NTSTATUS build_stream_path(TALLOC_CTX *mem_ctx,
* @param ctx talloc_ctx to allocate memory with.
* @param conn connection struct for vfs calls.
* @param dfs_path Whether this path requires dfs resolution.
+ * @param smbreq SMB request if we're using privilages.
* @param name_in The unconverted name.
* @param ucf_flags flags to pass through to unix_convert().
* UCF_ALWAYS_ALLOW_WCARD_LCOMP will be OR'd in if
@@ -1270,9 +1291,10 @@ static NTSTATUS build_stream_path(TALLOC_CTX *mem_ctx,
* @return NT_STATUS_OK if all operations completed succesfully, appropriate
* error otherwise.
*/
-NTSTATUS filename_convert(TALLOC_CTX *ctx,
+static NTSTATUS filename_convert_internal(TALLOC_CTX *ctx,
connection_struct *conn,
bool dfs_path,
+ struct smb_request *smbreq,
const char *name_in,
uint32_t ucf_flags,
bool *ppath_contains_wcard,
@@ -1291,7 +1313,7 @@ NTSTATUS filename_convert(TALLOC_CTX *ctx,
&fname,
ppath_contains_wcard);
if (!NT_STATUS_IS_OK(status)) {
- DEBUG(10,("filename_convert: resolve_dfspath failed "
+ DEBUG(10,("filename_convert_internal: resolve_dfspath failed "
"for name %s with %s\n",
name_in,
nt_errstr(status) ));
@@ -1320,7 +1342,7 @@ NTSTATUS filename_convert(TALLOC_CTX *ctx,
status = unix_convert(ctx, conn, fname, pp_smb_fname, ucf_flags);
if (!NT_STATUS_IS_OK(status)) {
- DEBUG(10,("filename_convert: unix_convert failed "
+ DEBUG(10,("filename_convert_internal: unix_convert failed "
"for name %s with %s\n",
fname,
nt_errstr(status) ));
@@ -1333,9 +1355,13 @@ NTSTATUS filename_convert(TALLOC_CTX *ctx,
return check_veto_path(conn, (*pp_smb_fname)->base_name);
}
- status = check_name(conn, (*pp_smb_fname)->base_name);
+ if (!smbreq) {
+ status = check_name(conn, (*pp_smb_fname)->base_name);
+ } else {
+ status = check_name_with_privilege(conn, smbreq, (*pp_smb_fname)->base_name);
+ }
if (!NT_STATUS_IS_OK(status)) {
- DEBUG(3,("filename_convert: check_name failed "
+ DEBUG(3,("filename_convert_internal: check_name failed "
"for name %s with %s\n",
smb_fname_str_dbg(*pp_smb_fname),
nt_errstr(status) ));
@@ -1345,3 +1371,49 @@ NTSTATUS filename_convert(TALLOC_CTX *ctx,
return status;
}
+
+/*
+ * Go through all the steps to validate a filename.
+ * Non-root version.
+ */
+
+NTSTATUS filename_convert(TALLOC_CTX *ctx,
+ connection_struct *conn,
+ bool dfs_path,
+ const char *name_in,
+ uint32_t ucf_flags,
+ bool *ppath_contains_wcard,
+ struct smb_filename **pp_smb_fname)
+{
+ return filename_convert_internal(ctx,
+ conn,
+ dfs_path,
+ NULL,
+ name_in,
+ ucf_flags,
+ ppath_contains_wcard,
+ pp_smb_fname);
+}
+
+/*
+ * Go through all the steps to validate a filename.
+ * root (privileged) version.
+ */
+
+NTSTATUS filename_convert_with_privilege(TALLOC_CTX *ctx,
+ connection_struct *conn,
+ struct smb_request *smbreq,
+ const char *name_in,
+ uint32_t ucf_flags,
+ bool *ppath_contains_wcard,
+ struct smb_filename **pp_smb_fname)
+{
+ return filename_convert_internal(ctx,
+ conn,
+ smbreq->flags2 & FLAGS2_DFS_PATHNAMES,
+ smbreq,
+ name_in,
+ ucf_flags,
+ ppath_contains_wcard,
+ pp_smb_fname);
+}
diff --git a/source3/smbd/proto.h b/source3/smbd/proto.h
index 4ec91a11db..7101041195 100644
--- a/source3/smbd/proto.h
+++ b/source3/smbd/proto.h
@@ -349,6 +349,13 @@ NTSTATUS filename_convert(TALLOC_CTX *mem_ctx,
uint32_t ucf_flags,
bool *ppath_contains_wcard,
struct smb_filename **pp_smb_fname);
+NTSTATUS filename_convert_with_privilege(TALLOC_CTX *mem_ctx,
+ connection_struct *conn,
+ struct smb_request *smbreq,
+ const char *name_in,
+ uint32_t ucf_flags,
+ bool *ppath_contains_wcard,
+ struct smb_filename **pp_smb_fname);
/* The following definitions come from smbd/files.c */
@@ -1159,6 +1166,10 @@ const char *vfs_readdirname(connection_struct *conn, void *p,
int vfs_ChDir(connection_struct *conn, const char *path);
char *vfs_GetWd(TALLOC_CTX *ctx, connection_struct *conn);
NTSTATUS check_reduced_name(connection_struct *conn, const char *fname);
+NTSTATUS check_reduced_name_with_privilege(connection_struct *conn,
+ const char *fname,
+ struct smb_filename **pp_parent_name,
+ struct smb_filename **pp_file_name);
int vfs_stat_smb_fname(struct connection_struct *conn, const char *fname,
SMB_STRUCT_STAT *psbuf);
int vfs_lstat_smb_fname(struct connection_struct *conn, const char *fname,
diff --git a/source3/smbd/vfs.c b/source3/smbd/vfs.c
index 6239ad4796..65c2535629 100644
--- a/source3/smbd/vfs.c
+++ b/source3/smbd/vfs.c
@@ -895,6 +895,21 @@ char *vfs_GetWd(TALLOC_CTX *ctx, connection_struct *conn)
/*******************************************************************
Reduce a file name, removing .. elements and checking that
it is below dir in the heirachy. This uses realpath.
+ This function must run as root, and will return names
+ and valid stat structs that can be checked on open.
+********************************************************************/
+
+NTSTATUS check_reduced_name_with_privilege(connection_struct *conn,
+ const char *fname,
+ struct smb_filename **pp_parent_name,
+ struct smb_filename **pp_file_name)
+{
+ return NT_STATUS_NOT_IMPLEMENTED;
+}
+
+/*******************************************************************
+ Reduce a file name, removing .. elements and checking that
+ it is below dir in the heirachy. This uses realpath.
********************************************************************/
NTSTATUS check_reduced_name(connection_struct *conn, const char *fname)