From 383bdfecc3f5759e29c80646958a84c4243ee0cc Mon Sep 17 00:00:00 2001 From: chenbotong Date: Thu, 8 May 2025 15:27:30 +0800 Subject: [PATCH] fix : add auth info verification Signed-off-by: chenbotong --- .../include/auth_deviceprofile.h | 1 + .../authentication/src/auth_deviceprofile.cpp | 103 +++++++++++++++++- .../src/auth_deviceprofile_virtual.cpp | 9 ++ core/authentication/src/auth_session_json.c | 73 +++++++++++-- .../unittest/auth_hichain_deps_mock.cpp | 6 + .../unittest/auth_hichain_deps_mock.h | 3 + .../unittest/auth_session_json_mock.cpp | 6 + .../unittest/auth_session_json_mock.h | 3 + 8 files changed, 189 insertions(+), 15 deletions(-) diff --git a/core/authentication/include/auth_deviceprofile.h b/core/authentication/include/auth_deviceprofile.h index 9e14afb632..2166350fa5 100644 --- a/core/authentication/include/auth_deviceprofile.h +++ b/core/authentication/include/auth_deviceprofile.h @@ -49,6 +49,7 @@ int32_t GetAccessUkIdDiffAccount(const AuthACLInfo *acl, int32_t *ukId, uint64_t int32_t GetAccessUkByUkId(int32_t sessionKeyId, uint8_t *uk, uint32_t ukLen); void UpdateAssetSessionKeyByAcl( AuthACLInfo *info, const uint8_t *sessionKey, uint32_t sessionKeyLen, int32_t *sessionKeyId, bool isSameAccount); +bool IsSKIdInvalid(int32_t sessionKeyId, const char *accountHash, const char *udidShortHash, int32_t userId); #ifdef __cplusplus #if __cplusplus diff --git a/core/authentication/src/auth_deviceprofile.cpp b/core/authentication/src/auth_deviceprofile.cpp index a291f41c94..25c906b840 100644 --- a/core/authentication/src/auth_deviceprofile.cpp +++ b/core/authentication/src/auth_deviceprofile.cpp @@ -29,10 +29,11 @@ #include "softbus_adapter_mem.h" #include "softbus_utils.h" -#define DEFAULT_ACCOUNT_UID "ohosAnonymousUid" -#define DEFAULT_USER_KEY_INDEX (-1) -#define DEFAULT_UKID_TIME (-1) -#define DEFAULT_USERID (-1) +#define DEFAULT_ACCOUNT_UID "ohosAnonymousUid" +#define DEFAULT_ACCOUNT_VALUE "0" +#define DEFAULT_USER_KEY_INDEX (-1) +#define DEFAULT_UKID_TIME (-1) +#define DEFAULT_USERID (-1) using DpClient = OHOS::DistributedDeviceProfile::DistributedDeviceProfileClient; static std::set g_notTrustedDevices; @@ -917,4 +918,98 @@ void UpdateAssetSessionKeyByAcl( ret = UpdateDpAclByAuthAcl(info, *sessionKeyId, currentTime, isSameAccount); LNN_LOGW(LNN_STATE, "UpdateDpAclByAuthAcl result ret=%{public}d", ret); return; +} + +static int32_t GetStringHash(std::string str, char *hashStrBuf, int32_t len) +{ + uint8_t hash[SHA_256_HASH_LEN] = { 0 }; + if (SoftBusGenerateStrHash((const unsigned char *)str.c_str(), str.length(), hash) != SOFTBUS_OK) { + LNN_LOGE(LNN_STATE, "generate hash fail"); + return SOFTBUS_NETWORK_GENERATE_STR_HASH_ERR; + } + if (ConvertBytesToHexString(hashStrBuf, len + 1, hash, len / HEXIFY_UNIT_LEN) != SOFTBUS_OK) { + LNN_LOGE(LNN_STATE, "convert hash hex string fail"); + return SOFTBUS_NETWORK_BYTES_TO_HEX_STR_ERR; + } + return SOFTBUS_OK; +} + +static bool IsSKIdInvalidInner(int32_t sessionKeyId, const char *accountHash, const char *udidShortHash, + int32_t userId, OHOS::DistributedDeviceProfile::AccessControlProfile &aclProfile) +{ + std::string sourceDeviceId = aclProfile.GetAccesser().GetAccesserDeviceId(); + std::string sourceAccountId = aclProfile.GetAccesser().GetAccesserAccountId(); + std::string sinkDeviceId = aclProfile.GetAccessee().GetAccesseeDeviceId(); + std::string sinkAccountId = aclProfile.GetAccessee().GetAccesseeAccountId(); + char aclUdidShortHash[SHA_256_HEX_HASH_LEN] = { 0 }; + char aclAccountHash[SHA_256_HEX_HASH_LEN] = { 0 }; + if (strcmp(DEFAULT_ACCOUNT_UID, sourceAccountId.c_str()) == 0) { + (void)GetStringHash(DEFAULT_ACCOUNT_VALUE, aclAccountHash, SHA_256_HEX_HASH_LEN - 1); + sourceAccountId = aclAccountHash; + } + if (strcmp(DEFAULT_ACCOUNT_UID, sinkAccountId.c_str()) == 0) { + (void)GetStringHash(DEFAULT_ACCOUNT_VALUE, aclAccountHash, SHA_256_HEX_HASH_LEN - 1); + sinkAccountId = aclAccountHash; + } + if (aclProfile.GetAccesser().GetAccesserSessionKeyId() == sessionKeyId) { + if (GetStringHash(sinkDeviceId, aclUdidShortHash, CUST_UDID_LEN) != SOFTBUS_OK) { + LNN_LOGE(LNN_STATE, "GetStringHash fail"); + return false; + } + if (StrCmpIgnoreCase(aclUdidShortHash, udidShortHash) != 0 || + StrCmpIgnoreCase(sinkAccountId.c_str(), accountHash) != 0 || + userId != aclProfile.GetAccessee().GetAccesseeUserId()) { + LNN_LOGE(LNN_STATE, "accountId/udid/userId error"); + return true; + } + return false; + } else if (aclProfile.GetAccessee().GetAccesseeSessionKeyId() == sessionKeyId) { + if (GetStringHash(sourceDeviceId, aclUdidShortHash, CUST_UDID_LEN) != SOFTBUS_OK) { + LNN_LOGE(LNN_STATE, "GetStringHash fail"); + return false; + } + if (StrCmpIgnoreCase(aclUdidShortHash, udidShortHash) != 0 || + StrCmpIgnoreCase(sourceAccountId.c_str(), accountHash) != 0 || + userId != aclProfile.GetAccesser().GetAccesserUserId()) { + LNN_LOGE(LNN_STATE, "accountId/udid/userId error"); + return true; + } + return false; + } + LNN_LOGE(LNN_STATE, "skId not match!"); + return true; +} + +bool IsSKIdInvalid(int32_t sessionKeyId, const char *accountHash, const char *udidShortHash, int32_t userId) +{ + if (accountHash == nullptr || udidShortHash == nullptr || strlen(udidShortHash) < CUST_UDID_LEN || + strlen(accountHash) < SHA_256_HEX_HASH_LEN - 1) { + LNN_LOGE(LNN_STATE, "param error"); + return false; + } + + std::vector aclProfiles; + int32_t ret = DpClient::GetInstance().GetAllAccessControlProfile(aclProfiles); + if (ret != OHOS::DistributedDeviceProfile::DP_SUCCESS) { + LNN_LOGE(LNN_STATE, "GetAllAccessControlProfile ret=%{public}d", ret); + return false; + } + if (aclProfiles.empty()) { + LNN_LOGE(LNN_STATE, "aclProfiles is empty"); + return true; + } + int32_t accesserSessionKeyId = 0; + int32_t accesseeSessionKeyId = 0; + for (auto &aclProfile : aclProfiles) { + LNN_LOGI(LNN_STATE, "GetAccesser=%{public}s, GetAccessee=%{public}s", + aclProfile.GetAccesser().dump().c_str(), aclProfile.GetAccessee().dump().c_str()); + accesserSessionKeyId = aclProfile.GetAccesser().GetAccesserSessionKeyId(); + accesseeSessionKeyId = aclProfile.GetAccessee().GetAccesseeSessionKeyId(); + if (accesserSessionKeyId != sessionKeyId && accesseeSessionKeyId != sessionKeyId) { + continue; + } + return IsSKIdInvalidInner(sessionKeyId, accountHash, udidShortHash, userId, aclProfile); + } + LNN_LOGE(LNN_STATE, "key not found"); + return true; } \ No newline at end of file diff --git a/core/authentication/src/auth_deviceprofile_virtual.cpp b/core/authentication/src/auth_deviceprofile_virtual.cpp index 34bdc84feb..4e4057ddf7 100644 --- a/core/authentication/src/auth_deviceprofile_virtual.cpp +++ b/core/authentication/src/auth_deviceprofile_virtual.cpp @@ -98,4 +98,13 @@ void UpdateAssetSessionKeyByAcl( (void)sessionKeyLen; (void)sessionKeyId; (void)isSameAccount; +} + +bool IsSKIdInvalid(int32_t sessionKeyId, const char *accountHash, const char *udidShortHash, int32_t userId) +{ + (void)sessionKeyId; + (void)accountHash; + (void)udidShortHash; + (void)userId; + return false; } \ No newline at end of file diff --git a/core/authentication/src/auth_session_json.c b/core/authentication/src/auth_session_json.c index 97f8e23281..87a97d3b8b 100644 --- a/core/authentication/src/auth_session_json.c +++ b/core/authentication/src/auth_session_json.c @@ -167,6 +167,7 @@ #define HAS_SUPPRESS_STRATEGY (0x08L) #define HAS_WAIT_TCP_TX_DONE (0x10L) #define LOCAL_FLAGS (HAS_CTRL_CHANNEL | HAS_P2P_AUTH_V2 | HAS_SUPPRESS_STRATEGY | HAS_WAIT_TCP_TX_DONE) +#define LONG_TO_STRING_MAX_LEN 21 #define DEFAULT_BATTERY_LEVEL 100 #define DEFAULT_NODE_WEIGHT 100 #define BASE64_OFFLINE_CODE_LEN 16 @@ -297,6 +298,30 @@ static bool GenerateUdidShortHash(const char *udid, char *udidHashBuf, uint32_t return true; } +static int32_t GenerateAccountHash(int64_t accountId, char *accountHashBuf, uint32_t bufLen) +{ + char accountString[LONG_TO_STRING_MAX_LEN] = { 0 }; + uint8_t accountHash[SHA_256_HASH_LEN] = { 0 }; + if (sprintf_s(accountString, LONG_TO_STRING_MAX_LEN, "%" PRId64, accountId) == -1) { + AUTH_LOGE(AUTH_FSM, "long to string fail"); + return SOFTBUS_SPRINTF_ERR; + } + char *anonyAccountId = NULL; + Anonymize(accountString, &anonyAccountId); + AUTH_LOGI(AUTH_FSM, "accountString=%{public}s", AnonymizeWrapper(anonyAccountId)); + AnonymizeFree(anonyAccountId); + int32_t ret = SoftBusGenerateStrHash((uint8_t *)accountString, strlen(accountString), accountHash); + if (ret != SOFTBUS_OK) { + AUTH_LOGE(AUTH_FSM, "accountId hash fail, ret=%{public}d", ret); + return SOFTBUS_NETWORK_GENERATE_STR_HASH_ERR; + } + if (ConvertBytesToHexString(accountHashBuf, bufLen, accountHash, SHA_256_HASH_LEN) != SOFTBUS_OK) { + AUTH_LOGE(AUTH_FSM, "convert bytes to string fail"); + return SOFTBUS_NETWORK_BYTES_TO_HEX_STR_ERR; + } + return SOFTBUS_OK; +} + static bool GetUdidOrShortHash(const AuthSessionInfo *info, char *udidBuf, uint32_t bufLen) { if (!info->isServer) { @@ -725,7 +750,7 @@ static int32_t ParseNormalizeData(AuthSessionInfo *info, char *encNormalizedKey, return SOFTBUS_OK; } -static void CheckDeviceKeyValid(JsonObj *obj, AuthSessionInfo *info) +static void UnpackSKId(JsonObj *obj, AuthSessionInfo *info) { int32_t localDeviceKeyId = AUTH_INVALID_DEVICEKEY_ID; int32_t remoteDeviceKeyId = AUTH_INVALID_DEVICEKEY_ID; @@ -873,21 +898,27 @@ static int32_t GetLocalUdidShortHash(char *localUdidHash) static void UnpackExternalAuthInfo(JsonObj *obj, AuthSessionInfo *info) { + OptInt(obj, USERID, &info->userId, 0); + UnpackSKId(obj, info); if (info->authVersion < AUTH_VERSION_V2) { AUTH_LOGD(AUTH_FSM, "lower version dont need unpack auth info"); return; } - if (!JSON_GetStringFromObject(obj, UDID_SHORT_HASH, info->udidShortHash, SHA_256_HEX_HASH_LEN)) { AUTH_LOGE(AUTH_FSM, "udid short hash not found"); return; } - if (!JSON_GetStringFromObject(obj, ACCOUNT_HASH, info->accountHash, SHA_256_HEX_HASH_LEN)) { AUTH_LOGE(AUTH_FSM, "account hash not found"); return; } - + if (info->deviceKeyId.hasDeviceKeyId && + IsSKIdInvalid(info->deviceKeyId.localDeviceKeyId, info->accountHash, info->udidShortHash, info->userId)) { + info->deviceKeyId.hasDeviceKeyId = false; + info->deviceKeyId.localDeviceKeyId = AUTH_INVALID_DEVICEKEY_ID; + info->deviceKeyId.remoteDeviceKeyId = AUTH_INVALID_DEVICEKEY_ID; + AUTH_LOGE(AUTH_FSM, "SKId invalid, hasDeviceKeyId=false"); + } NodeInfo nodeInfo; (void)memset_s(&nodeInfo, sizeof(NodeInfo), 0, sizeof(NodeInfo)); int32_t ret = LnnGetLocalNodeInfoSafe(&nodeInfo); @@ -895,15 +926,12 @@ static void UnpackExternalAuthInfo(JsonObj *obj, AuthSessionInfo *info) AUTH_LOGE(AUTH_FSM, "get node info fail"); return; } - info->isSameAccount = JudgeIsSameAccount(info->accountHash); - char localUdidHash[SHA_256_HEX_HASH_LEN] = { 0 }; if (GetLocalUdidShortHash(localUdidHash) != SOFTBUS_OK) { AUTH_LOGE(AUTH_FSM, "get local udid short hash fail"); return; } - char *udidShortHash = info->isSameAccount ? localUdidHash : info->udidShortHash; char *credList = NULL; ret = IdServiceQueryCredential(nodeInfo.userId, udidShortHash, info->accountHash, info->isSameAccount, &credList); @@ -911,12 +939,10 @@ static void UnpackExternalAuthInfo(JsonObj *obj, AuthSessionInfo *info) AUTH_LOGE(AUTH_FSM, "query credential fail"); return; } - info->credId = IdServiceGetCredIdFromCredList(nodeInfo.userId, credList); if (info->credId == NULL) { AUTH_LOGE(AUTH_FSM, "get cred id fail"); } - IdServiceDestroyCredentialList(&credList); } @@ -1378,14 +1404,12 @@ int32_t UnpackDeviceIdJson(const char *msg, uint32_t len, AuthSessionInfo *info, SetCompressFlag(compressParse, &info->isSupportCompress); } UnPackAuthPreLinkNode(obj, info); - CheckDeviceKeyValid(obj, info); OptInt(obj, AUTH_MODULE, (int32_t *)&info->module, AUTH_MODULE_LNN); bool isSupportNormalizedKey = false; OptBool(obj, IS_NORMALIZED, &isSupportNormalizedKey, false); UnpackFastAuth(obj, info); UnpackNormalizedKey(obj, info, isSupportNormalizedKey, authSeq); OptBool(obj, IS_NEED_PACK_CERT, &info->isNeedPackCert, false); - OptInt(obj, USERID, &info->userId, 0); UnpackExternalAuthInfo(obj, info); JSON_Delete(obj); return SOFTBUS_OK; @@ -2485,6 +2509,29 @@ static int32_t UnpackDeviceInfoMsgInner( return ret; } +static bool IsInvalidExternalAuthInfo(JsonObj *obj, NodeInfo *nodeInfo, const AuthSessionInfo *info) +{ + char udidHash[SHA_256_HEX_HASH_LEN] = { 0 }; + char accountHash[SHA_256_HEX_HASH_LEN] = { 0 }; + if (!GenerateUdidShortHash(nodeInfo->deviceInfo.deviceUdid, udidHash, SHA_256_HEX_HASH_LEN)) { + AUTH_LOGE(AUTH_FSM, "get local udid hash fail"); + return false; + } + if (strcmp(udidHash, info->udidShortHash) != 0) { + AUTH_LOGE(AUTH_FSM, "udidHash change!"); + return true; + } + if (GenerateAccountHash(nodeInfo->accountId, accountHash, SHA_256_HEX_HASH_LEN) != SOFTBUS_OK) { + AUTH_LOGE(AUTH_FSM, "gen accountHash fail"); + return false; + } + if (strcmp(accountHash, info->accountHash) != 0) { + AUTH_LOGE(AUTH_FSM, "accountHash change!"); + return true; + } + return false; +} + static bool IsInvalidDeviceInfo(JsonObj *obj, NodeInfo *nodeInfo, const AuthSessionInfo *info) { if (obj == NULL || nodeInfo == NULL || info == NULL) { @@ -2505,6 +2552,10 @@ static bool IsInvalidDeviceInfo(JsonObj *obj, NodeInfo *nodeInfo, const AuthSess AUTH_LOGE(AUTH_FSM, "authVersion change!"); return true; } + if (authVersion >= AUTH_VERSION_V2 && IsInvalidExternalAuthInfo(obj, nodeInfo, info)) { + AUTH_LOGE(AUTH_FSM, "is invalid ExternalAuthInfo!"); + return true; + } return false; } diff --git a/tests/core/authentication/unittest/auth_hichain_deps_mock.cpp b/tests/core/authentication/unittest/auth_hichain_deps_mock.cpp index 07445008ce..0df5d01e2d 100644 --- a/tests/core/authentication/unittest/auth_hichain_deps_mock.cpp +++ b/tests/core/authentication/unittest/auth_hichain_deps_mock.cpp @@ -259,5 +259,11 @@ int32_t GetActiveOsAccountIds(void) { return GetAuthHichainMockInterface()->GetActiveOsAccountIds(); } + +bool IsSKIdInvalid(int32_t sessionKeyId, const char *accountHash, const char *udidShortHash, + int32_t userId) +{ + return GetAuthHichainMockInterface()->IsSKIdInvalid(sessionKeyId, accountHash, udidShortHash, userId); +} } // extern "C" } // namespace OHOS diff --git a/tests/core/authentication/unittest/auth_hichain_deps_mock.h b/tests/core/authentication/unittest/auth_hichain_deps_mock.h index 325420eb68..c011a2e97e 100644 --- a/tests/core/authentication/unittest/auth_hichain_deps_mock.h +++ b/tests/core/authentication/unittest/auth_hichain_deps_mock.h @@ -86,6 +86,8 @@ public: DeviceAuthCallback *cb) = 0; virtual void IdServiceDestroyCredentialList(char **returnData) = 0; virtual int32_t GetActiveOsAccountIds(void) = 0; + virtual bool IsSKIdInvalid(int32_t sessionKeyId, const char *accountHash, const char *udidShortHash, + int32_t userId) = 0; }; class AuthHichainInterfaceMock : public AuthHichainInterface { @@ -134,6 +136,7 @@ public: MOCK_METHOD4(IdServiceProcessCredData, int32_t (int64_t, const uint8_t *, uint32_t, DeviceAuthCallback *)); MOCK_METHOD1(IdServiceDestroyCredentialList, void (char **)); MOCK_METHOD0(GetActiveOsAccountIds, int32_t(void)); + MOCK_METHOD4(IsSKIdInvalid, bool (int32_t, const char *, const char *, int32_t)); }; } // namespace OHOS #endif // AUTH_COMMON_MOCK_H diff --git a/tests/core/authentication/unittest/auth_session_json_mock.cpp b/tests/core/authentication/unittest/auth_session_json_mock.cpp index 20ea5bf30a..63778df614 100755 --- a/tests/core/authentication/unittest/auth_session_json_mock.cpp +++ b/tests/core/authentication/unittest/auth_session_json_mock.cpp @@ -437,5 +437,11 @@ int32_t GetActiveOsAccountIds(void) { return GetInterface()->GetActiveOsAccountIds(); } + +bool IsSKIdInvalid(int32_t sessionKeyId, const char *accountHash, const char *udidShortHash, + int32_t userId) +{ + return GetInterface()->IsSKIdInvalid(sessionKeyId, accountHash, udidShortHash, userId); +} } } \ No newline at end of file diff --git a/tests/core/authentication/unittest/auth_session_json_mock.h b/tests/core/authentication/unittest/auth_session_json_mock.h index aed6d5e127..5daa5564a3 100755 --- a/tests/core/authentication/unittest/auth_session_json_mock.h +++ b/tests/core/authentication/unittest/auth_session_json_mock.h @@ -119,6 +119,8 @@ public: bool isSameAccount, char **credList) = 0; virtual void IdServiceDestroyCredentialList(char **returnData) = 0; virtual int32_t GetActiveOsAccountIds(void) = 0; + virtual bool IsSKIdInvalid(int32_t sessionKeyId, const char *accountHash, const char *udidShortHash, + int32_t userId) = 0; }; class AuthSessionJsonInterfaceMock : public AuthSessionJsonInterface { @@ -195,6 +197,7 @@ public: bool isSameAccount, char **credList)); MOCK_METHOD1(IdServiceDestroyCredentialList, void (char **returnData)); MOCK_METHOD0(GetActiveOsAccountIds, int32_t(void)); + MOCK_METHOD4(IsSKIdInvalid, bool (int32_t, const char *, const char *, int32_t)); }; extern "C" { -- Gitee