diff options
-rw-r--r-- | source3/smbd/filename.c | 82 | ||||
-rw-r--r-- | source3/smbd/proto.h | 11 | ||||
-rw-r--r-- | source3/smbd/vfs.c | 15 |
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) |