diff --git a/interfaces/common/src/common_func.cpp b/interfaces/common/src/common_func.cpp index 01307b9ca6fb9db416e5581932d35a90df6a7e01..8850178f63da956d8b4630c3d4c9c15fedfd37b4 100644 --- a/interfaces/common/src/common_func.cpp +++ b/interfaces/common/src/common_func.cpp @@ -110,6 +110,10 @@ static void NormalizePath(string &path) string CommonFunc::GetUriFromPath(const string &path) { + if (!SandboxHelper::IsValidPath(path)) { + LOGE("path is ValidPath, The path contains '/./' or '../'characters"); + return ""; + } if (path.find(FILE_SCHEME_PREFIX) == 0) { return path; } diff --git a/interfaces/common/src/sandbox_helper.cpp b/interfaces/common/src/sandbox_helper.cpp index 863884aa02dbe43c97f73c9a4cc32ba784b26b9a..3ec9256e44b6c799d3a62f6632146af1a3bd4e15 100644 --- a/interfaces/common/src/sandbox_helper.cpp +++ b/interfaces/common/src/sandbox_helper.cpp @@ -19,7 +19,6 @@ #include #include #include - #include "log.h" #include "json_utils.h" #include "uri.h" @@ -42,13 +41,16 @@ namespace { const string FILE_MANAGER_AUTHORITY = "docs"; const string DLP_MANAGER_BUNDLE_NAME = "com.ohos.dlpmanager"; const string FUSE_URI_HEAD = "/mnt/data/fuse"; - const string BACKFLASH = "/"; + const char BACKSLASH = '/'; const string MEDIA = "media"; const string NETWORK_ID_FLAG = ""; const string LOCAL = "local"; const int ASSET_IN_BUCKET_NUM_MAX = 1000; const int ASSET_DIR_START_NUM = 16; const int DECODE_FORMAT_NUM = 16; + const std::string PATH_INVALID_FLAG1 = "../"; + const std::string PATH_INVALID_FLAG2 = "/.."; + const uint32_t PATH_INVALID_FLAG_LEN = 3; } struct MediaUriInfo { @@ -302,7 +304,7 @@ static int32_t GetMediaPhysicalPath(const std::string &sandboxPath, const std::s } physicalPath = SHAER_PATH_HEAD + userId + SHAER_PATH_MID + mediaUriInfo.mediaType + - BACKFLASH + to_string(bucketNum) + BACKFLASH + mediaUriInfo.realName + mediaSuffix; + BACKSLASH + to_string(bucketNum) + BACKSLASH + mediaUriInfo.realName + mediaSuffix; return 0; } @@ -342,6 +344,10 @@ static void DoGetPhysicalPath(string &lowerPathTail, string &lowerPathHead, cons int32_t SandboxHelper::GetPhysicalPath(const std::string &fileUri, const std::string &userId, std::string &physicalPath) { + if (!IsValidPath(fileUri)) { + LOGE("fileUri is ValidUri, The fileUri contains '/./' or '../'characters"); + return -EINVAL; + } Uri uri(fileUri); string bundleName = uri.GetAuthority(); if (bundleName == MEDIA) { @@ -378,6 +384,10 @@ int32_t SandboxHelper::GetPhysicalPath(const std::string &fileUri, const std::st int32_t SandboxHelper::GetBackupPhysicalPath(const std::string &fileUri, const std::string &userId, std::string &physicalPath) { + if (!IsValidPath(fileUri)) { + LOGE("fileUri is ValidUri, The fileUri contains '/./' or '../'characters"); + return -EINVAL; + } Uri uri(fileUri); string bundleName = uri.GetAuthority(); if (bundleName == MEDIA) { @@ -411,10 +421,22 @@ int32_t SandboxHelper::GetBackupPhysicalPath(const std::string &fileUri, const s return 0; } -bool SandboxHelper::IsValidPath(const std::string &path) +bool SandboxHelper::IsValidPath(const std::string &filePath) { - if (path.find("/./") != std::string::npos || - path.find("/../") != std::string::npos) { + if (filePath.find("/./") != std::string::npos) { + return false; + } + size_t pos = filePath.find(PATH_INVALID_FLAG1); + while (pos != string::npos) { + if (pos == 0 || filePath[pos - 1] == BACKSLASH) { + LOGE("Relative path is not allowed, path contain ../"); + return false; + } + pos = filePath.find(PATH_INVALID_FLAG1, pos + PATH_INVALID_FLAG_LEN); + } + pos = filePath.rfind(PATH_INVALID_FLAG2); + if ((pos != string::npos) && (filePath.size() - pos == PATH_INVALID_FLAG_LEN)) { + LOGE("Relative path is not allowed, path tail is /.."); return false; } return true; diff --git a/interfaces/innerkits/native/file_uri/src/file_uri.cpp b/interfaces/innerkits/native/file_uri/src/file_uri.cpp index f2af06226bd36679c74b318409e3cd9e0b36ca15..5e58b6000d54d86a49a5ad1154eead3aa5e880e7 100644 --- a/interfaces/innerkits/native/file_uri/src/file_uri.cpp +++ b/interfaces/innerkits/native/file_uri/src/file_uri.cpp @@ -143,7 +143,8 @@ string FileUri::GetRealPath() string FileUri::GetRealPathBySA(const std::string &targetBundleName) { string sandboxPath = DecodeBySA(uri_.GetPath()); - if (sandboxPath.empty()) { + if (sandboxPath.empty() || !SandboxHelper::IsValidPath(sandboxPath)) { + LOGE("path is ValidPath, The path contains '/./' or '../'characters"); return ""; } string realPath = sandboxPath; @@ -165,6 +166,10 @@ string FileUri::ToString() string FileUri::GetFullDirectoryUri() { string uri = uri_.ToString(); + if (!SandboxHelper::IsValidPath(uri)) { + LOGE("uri is ValidUri, The uri contains '/./' or '../'characters"); + return ""; + } struct stat fileInfo; if (stat(GetRealPath().c_str(), &fileInfo) != 0) { LOGE("fileInfo is error,%{public}s", strerror(errno)); @@ -200,6 +205,10 @@ bool FileUri::CheckUriFormat(const std::string &uri) LOGE("URI is missing file://"); return false; } + if (!SandboxHelper::IsValidPath(uri)) { + LOGE("uri is ValidPath, The uri contains '/./' or '../'characters"); + return false; + } return true; } diff --git a/test/unittest/file_share_native/file_share_test.cpp b/test/unittest/file_share_native/file_share_test.cpp index 2a0b3c27918ccad7fc66c328583813f89e89f1ea..d87c28f6057a08ee73581177d9166f8180572474 100644 --- a/test/unittest/file_share_native/file_share_test.cpp +++ b/test/unittest/file_share_native/file_share_test.cpp @@ -421,6 +421,45 @@ HWTEST_F(FileShareTest, File_share_GetPhysicalPath_0006, testing::ext::TestSize. GTEST_LOG_(INFO) << "FileShareTest-end File_share_GetPhysicalPath_0006"; } +/** + * @tc.name: File_share_GetPhysicalPath_0007 + * @tc.desc: Test function of GetPhysicalPath() interface for SUCCESS. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + * @tc.require: I7PDZL + */ +HWTEST_F(FileShareTest, File_share_GetPhysicalPath_0007, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "FileShareTest-begin File_share_GetPhysicalPath_0007"; + std::string fileUri0 = "file://docs/storage/Users/currentUser/../test../test1"; + std::string fileUri1 = "file://docs/storage/Users/currentUser/test../../test"; + std::string fileUri2 = "file://docs/storage/Users/currentUser/test../../"; + std::string fileUri3 = "file://docs/storage/Users/currentUser/test../test../.."; + std::string fileUri4 = "file://docs/storage/Users/currentUser/test/..test/.."; + std::string fileUri5 = "file://docs/storage/Users/currentUser/test/test../test"; + std::string fileUri6 = "file://docs/storage/Users/currentUser/test../test../test"; + std::string fileUri7 = "file://docs/storage/Users/currentUser/test../test../test../..test"; + std::string physicalPath; + int32_t ret = SandboxHelper::GetPhysicalPath(fileUri0, "100", physicalPath); + EXPECT_EQ(ret, -EINVAL); + ret = SandboxHelper::GetPhysicalPath(fileUri1, "100", physicalPath); + EXPECT_EQ(ret, -EINVAL); + ret = SandboxHelper::GetPhysicalPath(fileUri2, "100", physicalPath); + EXPECT_EQ(ret, -EINVAL); + ret = SandboxHelper::GetPhysicalPath(fileUri3, "100", physicalPath); + EXPECT_EQ(ret, -EINVAL); + ret = SandboxHelper::GetPhysicalPath(fileUri4, "100", physicalPath); + EXPECT_EQ(ret, -EINVAL); + ret = SandboxHelper::GetPhysicalPath(fileUri5, "100", physicalPath); + EXPECT_EQ(ret, E_OK); + ret = SandboxHelper::GetPhysicalPath(fileUri6, "100", physicalPath); + EXPECT_EQ(ret, E_OK); + ret = SandboxHelper::GetPhysicalPath(fileUri7, "100", physicalPath); + EXPECT_EQ(ret, E_OK); + GTEST_LOG_(INFO) << "FileShareTest-end File_share_GetPhysicalPath_0007"; +} + /** * @tc.name: File_share_CheckValidPath_0001 * @tc.desc: Test function of CheckValidPath() interface for FAILURE. @@ -442,6 +481,43 @@ HWTEST_F(FileShareTest, File_share_CheckValidPath_0001, testing::ext::TestSize.L GTEST_LOG_(INFO) << "FileShareTest-end File_share_CheckValidPath_0001"; } +/** + * @tc.name: File_share_IsValidPath_0002 + * @tc.desc: Test function of CheckValidPath() interface for FAILURE. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + * @tc.require: I7PDZL + */ +HWTEST_F(FileShareTest, File_share_IsValidPath_0002, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "FileShareTest-begin File_share_IsValidPath_0002"; + bool result = SandboxHelper::IsValidPath("../test../test1"); + EXPECT_FALSE(result); + result = SandboxHelper::IsValidPath("/../test../test1"); + EXPECT_FALSE(result); + result = SandboxHelper::IsValidPath("test../../test"); + EXPECT_FALSE(result); + result = SandboxHelper::IsValidPath("test../../"); + EXPECT_FALSE(result); + result = SandboxHelper::IsValidPath("test../test../.."); + EXPECT_FALSE(result); + result = SandboxHelper::IsValidPath("/test/..test/.."); + EXPECT_FALSE(result); + + result = SandboxHelper::IsValidPath("test"); + EXPECT_TRUE(result); + result = SandboxHelper::IsValidPath("/test/test../test"); + EXPECT_TRUE(result); + result = SandboxHelper::IsValidPath("/test../test../test"); + EXPECT_TRUE(result); + result = SandboxHelper::IsValidPath("/test../test../test../"); + EXPECT_TRUE(result); + result = SandboxHelper::IsValidPath("/test../test../test../..test"); + EXPECT_TRUE(result); + GTEST_LOG_(INFO) << "FileShareTest-end File_share_IsValidPath_0002"; +} + /** * @tc.name: File_share_GetBackupPhysicalPath_0001 * @tc.desc: Test function of GetBackupPhysicalPath() interface for SUCCESS. @@ -558,4 +634,44 @@ HWTEST_F(FileShareTest, File_share_GetBackupPhysicalPath_0006, testing::ext::Tes EXPECT_EQ(ret, -EINVAL); GTEST_LOG_(INFO) << "FileShareTest-end File_share_GetBackupPhysicalPath_0006"; } + +/** + * @tc.name: File_share_GetBackupPhysicalPath_0007 + * @tc.desc: Test function of GetBackupPhysicalPath() interface for FAILURE. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + * @tc.require: I7PDZL + */ +HWTEST_F(FileShareTest, File_share_GetBackupPhysicalPath_0007, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "FileShareTest-begin File_share_GetPhysicalPath_0007"; + std::string fileUri0 = "file://docs/storage/Users/currentUser/../test../test1"; + std::string fileUri1 = "file://docs/storage/Users/currentUser/test../../test"; + std::string fileUri2 = "file://docs/storage/Users/currentUser/test../../"; + std::string fileUri3 = "file://docs/storage/Users/currentUser/test../test../.."; + std::string fileUri4 = "file://docs/storage/Users/currentUser/test/..test/.."; + std::string fileUri5 = "file://docs/storage/Users/currentUser/test/test../test"; + std::string fileUri6 = "file://docs/storage/Users/currentUser/test../test../test"; + std::string fileUri7 = "file://docs/storage/Users/currentUser/test../test../test../..test"; + std::string physicalPath; + int32_t ret = SandboxHelper::GetBackupPhysicalPath(fileUri0, "100", physicalPath); + EXPECT_EQ(ret, -EINVAL); + ret = SandboxHelper::GetBackupPhysicalPath(fileUri1, "100", physicalPath); + EXPECT_EQ(ret, -EINVAL); + ret = SandboxHelper::GetBackupPhysicalPath(fileUri2, "100", physicalPath); + EXPECT_EQ(ret, -EINVAL); + ret = SandboxHelper::GetBackupPhysicalPath(fileUri3, "100", physicalPath); + EXPECT_EQ(ret, -EINVAL); + ret = SandboxHelper::GetBackupPhysicalPath(fileUri4, "100", physicalPath); + EXPECT_EQ(ret, -EINVAL); + ret = SandboxHelper::GetBackupPhysicalPath(fileUri5, "100", physicalPath); + EXPECT_EQ(ret, E_OK); + ret = SandboxHelper::GetBackupPhysicalPath(fileUri6, "100", physicalPath); + EXPECT_EQ(ret, E_OK); + ret = SandboxHelper::GetBackupPhysicalPath(fileUri7, "100", physicalPath); + EXPECT_EQ(ret, E_OK); + GTEST_LOG_(INFO) << "FileShareTest-end File_share_GetBackupPhysicalPath_0007"; +} + } // namespace \ No newline at end of file diff --git a/test/unittest/file_uri_native/file_uri_test.cpp b/test/unittest/file_uri_native/file_uri_test.cpp index bb5fce798f4e058cb0bb06d68f8663a562c9e32d..468865cb2ce06090438a413ac7b85f1cbef7abe9 100644 --- a/test/unittest/file_uri_native/file_uri_test.cpp +++ b/test/unittest/file_uri_native/file_uri_test.cpp @@ -368,6 +368,110 @@ namespace OHOS::AppFileService::ModuleFileUri { GTEST_LOG_(INFO) << "FileUriTest-end File_uri_GetPath_0000"; } + /** + * @tc.name: file_uri_test_0008 + * @tc.desc: Test function of GetFullDirectoryUri() interface for SUCCESS. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + * @tc.require: + */ + HWTEST_F(FileUriTest, File_uri_GetFullDirectoryUri_0001, testing::ext::TestSize.Level1) + { + GTEST_LOG_(INFO) << "FileUriTest-begin File_uri_GetFullDirectoryUri_0001"; + std::string fileUri0 = "file://docs/storage/Users/currentUser/../test../test1"; + std::string fileUri1 = "file://docs/storage/Users/currentUser/test../../test"; + std::string fileUri2 = "file://docs/storage/Users/currentUser/test../../"; + std::string fileUri3 = "file://docs/storage/Users/currentUser/test../test../.."; + std::string fileUri4 = "file://docs/storage/Users/currentUser/test/..test/.."; + FileUri fileUriObject0(fileUri0); + EXPECT_EQ(fileUriObject0.GetFullDirectoryUri(), ""); + FileUri fileUriObject1(fileUri1); + EXPECT_EQ(fileUriObject1.GetFullDirectoryUri(), ""); + FileUri fileUriObject2(fileUri2); + EXPECT_EQ(fileUriObject2.GetFullDirectoryUri(), ""); + FileUri fileUriObject3(fileUri3); + EXPECT_EQ(fileUriObject3.GetFullDirectoryUri(), ""); + FileUri fileUriObject4(fileUri4); + EXPECT_EQ(fileUriObject4.GetFullDirectoryUri(), ""); + GTEST_LOG_(INFO) << "FileUriTest-end File_uri_GetPath_0001"; + } + + /** + * @tc.name: file_uri_test_0009 + * @tc.desc: Test function of CheckUriFormat() interface for SUCCESS. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + * @tc.require: + */ + HWTEST_F(FileUriTest, File_uri_CheckUriFormat_0000, testing::ext::TestSize.Level1) + { + GTEST_LOG_(INFO) << "FileUriTest-begin File_uri_CheckUriFormat_0000"; + std::string fileUri0 = "file://docs/storage/Users/currentUser/../test../test1"; + std::string fileUri1 = "file://docs/storage/Users/currentUser/test../../test"; + std::string fileUri2 = "file://docs/storage/Users/currentUser/test../../"; + std::string fileUri3 = "file://docs/storage/Users/currentUser/test../test../.."; + std::string fileUri4 = "file://docs/storage/Users/currentUser/test/..test/.."; + std::string fileUri5 = "file://docs/storage/Users/currentUser/test/test../test"; + std::string fileUri6 = "file://docs/storage/Users/currentUser/test../test../test"; + std::string fileUri7 = "file://docs/storage/Users/currentUser/test../test../test../..test"; + FileUri fileUriObject0(fileUri0); + EXPECT_FALSE(fileUriObject0.CheckUriFormat(fileUri0)); + FileUri fileUriObject1(fileUri1); + EXPECT_FALSE(fileUriObject1.CheckUriFormat(fileUri1)); + FileUri fileUriObject2(fileUri2); + EXPECT_FALSE(fileUriObject2.CheckUriFormat(fileUri2)); + FileUri fileUriObject3(fileUri3); + EXPECT_FALSE(fileUriObject3.CheckUriFormat(fileUri3)); + FileUri fileUriObject4(fileUri4); + EXPECT_FALSE(fileUriObject4.CheckUriFormat(fileUri4)); + FileUri fileUriObject5(fileUri5); + EXPECT_TRUE(fileUriObject5.CheckUriFormat(fileUri5)); + FileUri fileUriObject6(fileUri6); + EXPECT_TRUE(fileUriObject6.CheckUriFormat(fileUri6)); + FileUri fileUriObject7(fileUri7); + EXPECT_TRUE(fileUriObject7.CheckUriFormat(fileUri7)); + GTEST_LOG_(INFO) << "FileUriTest-end File_uri_CheckUriFormat_0000"; + } + + /** + * @tc.name: file_uri_test_0010 + * @tc.desc: Test function of GetUriFromPath() interface for SUCCESS. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + * @tc.require: + */ + HWTEST_F(FileUriTest, File_uri_GetUriFromPath_0010, testing::ext::TestSize.Level1) + { + GTEST_LOG_(INFO) << "FileUriTest-begin File_uri_GetUriFromPath_0010"; + std::string fileUri0 = "/storage/Users/currentUser/../test../test1"; + std::string fileUri1 = "/storage/Users/currentUser/test../../test"; + std::string fileUri2 = "/storage/Users/currentUser/test../../"; + std::string fileUri3 = "/storage/Users/currentUser/test../test../.."; + std::string fileUri4 = "/storage/Users/currentUser/test/..test/.."; + std::string fileUri5 = "/storage/Users/currentUser/test/test../test"; + std::string fileUri6 = "/storage/Users/currentUser/test../test../test"; + std::string fileUri7 = "/storage/Users/currentUser/test../test../test../..test"; + FileUri fileUriObject0(fileUri0); + EXPECT_EQ(fileUriObject0.ToString(), ""); + FileUri fileUriObject1(fileUri1); + EXPECT_EQ(fileUriObject1.ToString(), ""); + FileUri fileUriObject2(fileUri2); + EXPECT_EQ(fileUriObject2.ToString(), ""); + FileUri fileUriObject3(fileUri3); + EXPECT_EQ(fileUriObject3.ToString(), ""); + FileUri fileUriObject4(fileUri4); + EXPECT_EQ(fileUriObject4.ToString(), ""); + FileUri fileUriObject5(fileUri5); + EXPECT_EQ(fileUriObject5.ToString(), "file://docs/storage/Users/currentUser/test/test../test"); + FileUri fileUriObject6(fileUri6); + EXPECT_EQ(fileUriObject6.ToString(), "file://docs/storage/Users/currentUser/test../test../test"); + FileUri fileUriObject7(fileUri7); + EXPECT_EQ(fileUriObject7.ToString(), "file://docs/storage/Users/currentUser/test../test../test../..test"); + GTEST_LOG_(INFO) << "FileUriTest-end File_uri_GetUriFromPath_0010"; + } /** * @tc.name: File_uri_IsRemoteUri_0000 * @tc.desc: Test function of IsRemoteUri() interface for SUCCESS. diff --git a/tests/unittests/backup_utils/BUILD.gn b/tests/unittests/backup_utils/BUILD.gn index f982532bc8286ec5fa7c1708107f3ef21baa43fe..79370309e30a1fe4f56e7857879abe0087ee21bf 100644 --- a/tests/unittests/backup_utils/BUILD.gn +++ b/tests/unittests/backup_utils/BUILD.gn @@ -84,6 +84,7 @@ ohos_unittest("b_file_test") { include_dirs = [ "${path_backup}/utils/src/b_filesystem" ] deps = [ + "${path_backup}/interfaces/innerkits/native:sandbox_helper_native", "${path_backup}/tests/utils:backup_test_utils", "${path_backup}/utils/:backup_utils", ] diff --git a/utils/src/b_filesystem/b_dir.cpp b/utils/src/b_filesystem/b_dir.cpp index 2845338e4d6086644a0961141591cab2e3846212..629da52d4593f3e3d6aa39b1774f8b58d7d3a915 100644 --- a/utils/src/b_filesystem/b_dir.cpp +++ b/utils/src/b_filesystem/b_dir.cpp @@ -34,6 +34,7 @@ #include "directory_ex.h" #include "errors.h" #include "filemgmt_libhilog.h" +#include "sandbox_helper.h" namespace OHOS::FileManagement::Backup { using namespace std; @@ -41,9 +42,6 @@ const int32_t PATH_MAX_LEN = 4096; const size_t TOP_ELE = 0; const std::string APP_DATA_DIR = BConstants::PATH_PUBLIC_HOME + BConstants::PATH_APP_DATA + BConstants::FILE_SEPARATOR_CHAR; -const std::string PATH_INVALID_FLAG1 = "../"; -const std::string PATH_INVALID_FLAG2 = "/.."; -const uint32_t PATH_INVALID_FLAG_LEN = 3; static bool IsEmptyDirectory(const string &path) { @@ -516,22 +514,7 @@ vector BDir::GetDirs(const vector &paths) bool BDir::IsFilePathValid(const std::string &filePath) { - size_t pos = filePath.find(PATH_INVALID_FLAG1); - while (pos != string::npos) { - if (pos == 0 || filePath[pos - 1] == BConstants::FILE_SEPARATOR_CHAR) { - HILOGE("Relative path is not allowed, path contain ../, path = %{private}s", - GetAnonyString(filePath).c_str()); - return false; - } - pos = filePath.find(PATH_INVALID_FLAG1, pos + PATH_INVALID_FLAG_LEN); - } - pos = filePath.rfind(PATH_INVALID_FLAG2); - if ((pos != string::npos) && (filePath.size() - pos == PATH_INVALID_FLAG_LEN)) { - HILOGE("Relative path is not allowed, path tail is /.., path = %{private}s", - GetAnonyString(filePath).c_str()); - return false; - } - return true; + return AppFileService::SandboxHelper::IsValidPath(filePath); } bool BDir::CheckAndRmSoftLink(const std::string &filePath)