diff --git a/frameworks/common/include/permission_map.h b/frameworks/common/include/permission_map.h index 0dadaba12ef4363b85beb15f97c9be4cc43714b0..73a3b415c0d9849e6b6d973aa07dbb5cd6010521 100644 --- a/frameworks/common/include/permission_map.h +++ b/frameworks/common/include/permission_map.h @@ -40,6 +40,7 @@ struct PermissionBriefDef { bool TransferPermissionToOpcode(const std::string& permissionName, uint32_t& opCode); bool TransferOpcodeToPermission(uint32_t opCode, std::string& permissionName); bool IsUserGrantPermission(const std::string& permission); +bool IsUserSettingPermission(const std::string& permission); bool IsDefinedPermission(const std::string& permission); bool GetPermissionBriefDef(const std::string& permission, PermissionBriefDef &permissionBriefDef); void GetPermissionBriefDef(uint32_t code, PermissionBriefDef &permissionBriefDef); diff --git a/frameworks/common/permission_definition_parser.py b/frameworks/common/permission_definition_parser.py index abc9f75d3bf2538dfbff9233678112d8e62abc34..abbca23b97763fd54d049b7cfbd8fed987a20166 100755 --- a/frameworks/common/permission_definition_parser.py +++ b/frameworks/common/permission_definition_parser.py @@ -82,6 +82,7 @@ PERMISSION_BRIEF_DEFINE_PATTERN = ''' JSON_VALUE_CONVERT_TO_CPP_DICT = { "user_grant": "USER_GRANT", "system_grant": "SYSTEM_GRANT", + "manual_setting": "MANUAL_SETTING", "normal": "APL_NORMAL", "system_basic": "APL_SYSTEM_BASIC", "system_core": "APL_SYSTEM_CORE", @@ -177,6 +178,19 @@ def parse_json(path, platform): 'hasValue' : True } + manual_perm = { + 'name' : 'ohos.permission.MANUAL_ATM_SELF_USE', + 'grantMode' : 'manual_setting', + 'availableLevel' : 'normal', + 'availableType' : 'NORMAL', + 'since' : 19, + 'deprecated' : '', + 'provisionEnable' : True, + 'distributedSceneEnable' : False, + 'isKernelEffect' : False, + 'hasValue' : False + } + def_list = [] with open(path, "r", encoding="utf-8") as f: data = json.load(f) @@ -188,6 +202,8 @@ def parse_json(path, platform): def_list.append(perm_def) index += 1 def_list.append(PermissionDef(extend_perm, index)) + index += 1 + def_list.append(PermissionDef(manual_perm, index)) return def_list diff --git a/frameworks/common/src/permission_map.cpp b/frameworks/common/src/permission_map.cpp index 9adb6fcdf12a22289a950e185f4a34ddcf95b293..cb0fdcd8405cca7f04985949c26157c465fe321a 100644 --- a/frameworks/common/src/permission_map.cpp +++ b/frameworks/common/src/permission_map.cpp @@ -84,6 +84,15 @@ bool IsUserGrantPermission(const std::string& permission) return g_permList[opCode].grantMode == USER_GRANT; } +bool IsUserSettingPermission(const std::string& permission) +{ + uint32_t opCode; + if (!TransferPermissionToOpcode(permission, opCode)) { + return false; // default is false + } + return g_permList[opCode].grantMode == USER_GRANT || g_permList[opCode].grantMode == MANUAL_SETTING; +} + bool IsDefinedPermission(const std::string& permission) { if (!g_initedPermMap) { diff --git a/frameworks/ets/ani/accesstoken/ets/@ohos.abilityAccessCtrl.ets b/frameworks/ets/ani/accesstoken/ets/@ohos.abilityAccessCtrl.ets index 8de915f7f79685ded72ccbf7e8844c65a78bb6e7..db4aa4d22ea8927f997f97b557c4ae00a8828de4 100644 --- a/frameworks/ets/ani/accesstoken/ets/@ohos.abilityAccessCtrl.ets +++ b/frameworks/ets/ani/accesstoken/ets/@ohos.abilityAccessCtrl.ets @@ -151,6 +151,10 @@ export default namespace abilityAccessCtrl { revokeUserGrantedPermission(tokenID: int, permissionName: Permissions, permissionFlags: int): Promise; revokeUserGrantedPermission( tokenID: int, permissionName: Permissions, permissionFlags: int, callback: AsyncCallback): void; + + grantPermission(tokenID: int, permissionName: Permissions, permissionFlags: int): Promise; + revokePermission(tokenID: int, permissionName: Permissions, permissionFlags: int): Promise; + getVersion(): Promise; getPermissionsStatus(tokenID: int, permissionList: Array): Promise>; getPermissionFlags(tokenID: int, permissionName: Permissions): Promise; @@ -179,6 +183,9 @@ export default namespace abilityAccessCtrl { native grantUserGrantedPermissionExecute(tokenID: int, permissionName: Permissions, permissionFlags: int): void; native revokeUserGrantedPermissionExecute( tokenID: int, permissionName: Permissions, permissionFlags: int): void; + native grantPermissionWithManualExecute(tokenID: int, permissionName: Permissions, permissionFlags: int): void; + native revokePermissionWithManualExecute( + tokenID: int, permissionName: Permissions, permissionFlags: int): void; native getPermissionsStatusExecute(tokenID: int, permissionList: Array): Array; native getVersionExecute(): int; native getPermissionFlagsExecute(tokenID: int, permissionName: Permissions): int; @@ -360,6 +367,34 @@ export default namespace abilityAccessCtrl { }); } + grantPermission(tokenID: int, permissionName: Permissions, permissionFlags: int): Promise { + return new Promise( + (resolve: (v: undefined) => void, reject: (error: BusinessError) => void) : void => { + let p = taskpool.execute(() : void => { + new AtManagerInner().grantPermissionWithManualExecute(tokenID, permissionName, permissionFlags); + }); + p.then((e: NullishType) : void => { + resolve(undefined); + }).catch((err: Error) : void => { + reject(err as BusinessError); + }); + }); + } + + revokePermission(tokenID: int, permissionName: Permissions, permissionFlags: int): Promise { + return new Promise( + (resolve: (v: undefined) => void, reject: (error: BusinessError) => void): void => { + let p = taskpool.execute((): void => { + new AtManagerInner().revokePermissionWithManualExecute(tokenID, permissionName, permissionFlags); + }); + p.then((e: NullishType): void => { + resolve(undefined); + }).catch((err: Error): void => { + reject(err as BusinessError); + }); + }); + } + getVersion(): Promise { let p = new Promise(( resolve: (v: int) => void, reject: (error: BusinessError) => void) => { diff --git a/frameworks/ets/ani/accesstoken/src/ani_ability_access_ctrl.cpp b/frameworks/ets/ani/accesstoken/src/ani_ability_access_ctrl.cpp index 870f6c7e0792f503e8ed6ee7d2e6e4c4730ae725..27cb58bcc5235072a3653724411d596e02e195e7 100644 --- a/frameworks/ets/ani/accesstoken/src/ani_ability_access_ctrl.cpp +++ b/frameworks/ets/ani/accesstoken/src/ani_ability_access_ctrl.cpp @@ -359,6 +359,75 @@ static void RevokeUserGrantedPermissionExecute([[maybe_unused]] ani_env* env, } } +static void GrantPermissionWithManualExecute([[maybe_unused]] ani_env *env, [[maybe_unused]] ani_object object, + ani_int aniTokenID, ani_string aniPermission, ani_int aniFlags) +{ + if (env == nullptr) { + LOGE(ATM_DOMAIN, ATM_TAG, "Env is null."); + return; + } + AccessTokenID tokenID = static_cast(aniTokenID); + std::string permissionName = ParseAniString(env, static_cast(aniPermission)); + uint32_t permissionFlags = static_cast(aniFlags); + if ((!BusinessErrorAni::ValidateTokenIDdWithThrowError(env, tokenID)) || + (!BusinessErrorAni::ValidatePermissionWithThrowError(env, permissionName)) || + (!BusinessErrorAni::ValidatePermissionFlagWithThrowError(env, permissionFlags))) { + LOGE(ATM_DOMAIN, ATM_TAG, "TokenId(%{public}u) or Permission(%{public}s) or flags(%{public}u)is invalid.", + tokenID, permissionName.c_str(), permissionFlags); + return; + } + + PermissionBriefDef def; + if (!GetPermissionBriefDef(permissionName, def) || + (def.grantMode != USER_GRANT && def.grantMode != MANUAL_SETTING)) { + std::string errMsg = GetErrorMessage(STS_ERROR_PERMISSION_NOT_USER_GRANT_OR_MANUAL_SETTING, + "The specified permission is not a user_grant or manual_setting permission."); + BusinessErrorAni::ThrowError(env, STS_ERROR_PERMISSION_NOT_USER_GRANT_OR_MANUAL_SETTING, errMsg); + return; + } + + int32_t res = AccessTokenKit::GrantPermission(tokenID, permissionName, permissionFlags, true); + if (res != RET_SUCCESS) { + int32_t stsCode = BusinessErrorAni::GetStsErrorCode(res); + BusinessErrorAni::ThrowError(env, stsCode, GetErrorMessage(stsCode)); + } +} + +static void RevokePermissionWithManualExecute([[maybe_unused]] ani_env* env, + [[maybe_unused]] ani_object object, ani_int aniTokenID, ani_string aniPermission, ani_int aniFlags) +{ + LOGI(ATM_DOMAIN, ATM_TAG, "RevokeUserGrantedPermission begin."); + if (env == nullptr) { + LOGE(ATM_DOMAIN, ATM_TAG, "Env is null."); + return; + } + AccessTokenID tokenID = static_cast(aniTokenID); + std::string permissionName = ParseAniString(env, static_cast(aniPermission)); + uint32_t permissionFlags = static_cast(aniFlags); + if ((!BusinessErrorAni::ValidateTokenIDdWithThrowError(env, tokenID)) || + (!BusinessErrorAni::ValidatePermissionWithThrowError(env, permissionName)) || + (!BusinessErrorAni::ValidatePermissionFlagWithThrowError(env, permissionFlags))) { + LOGE(ATM_DOMAIN, ATM_TAG, "TokenId(%{public}u) or Permission(%{public}s) or flags(%{public}u)is invalid.", + tokenID, permissionName.c_str(), permissionFlags); + return; + } + + PermissionBriefDef def; + if (!GetPermissionBriefDef(permissionName, def) || + (def.grantMode != USER_GRANT && def.grantMode != MANUAL_SETTING)) { + std::string errMsg = GetErrorMessage(STS_ERROR_PERMISSION_NOT_USER_GRANT_OR_MANUAL_SETTING, + "The specified permission is not a user_grant or manual_setting permission."); + BusinessErrorAni::ThrowError(env, STS_ERROR_PERMISSION_NOT_USER_GRANT_OR_MANUAL_SETTING, errMsg); + return; + } + + int32_t ret = AccessTokenKit::RevokePermission(tokenID, permissionName, permissionFlags, true); + if (ret != RET_SUCCESS) { + int32_t stsCode = BusinessErrorAni::GetStsErrorCode(ret); + BusinessErrorAni::ThrowError(env, stsCode, GetErrorMessage(stsCode)); + } +} + static ani_int GetVersionExecute([[maybe_unused]] ani_env* env, [[maybe_unused]] ani_object object) { LOGI(ATM_DOMAIN, ATM_TAG, "GetVersionExecute begin."); @@ -847,6 +916,10 @@ void InitAbilityCtrlFunction(ani_env *env) reinterpret_cast(GrantUserGrantedPermissionExecute) }, ani_native_function { "revokeUserGrantedPermissionExecute", nullptr, reinterpret_cast(RevokeUserGrantedPermissionExecute) }, + ani_native_function { "grantPermissionWithManualExecute", nullptr, + reinterpret_cast(GrantPermissionWithManualExecute) }, + ani_native_function { "revokePermissionWithManualExecute", + nullptr, reinterpret_cast(RevokePermissionWithManualExecute) }, ani_native_function { "getVersionExecute", nullptr, reinterpret_cast(GetVersionExecute) }, ani_native_function { "getPermissionsStatusExecute", nullptr, reinterpret_cast(GetPermissionsStatusExecute) }, diff --git a/frameworks/ets/ani/accesstoken/src/ani_request_permission_on_setting.cpp b/frameworks/ets/ani/accesstoken/src/ani_request_permission_on_setting.cpp index d10008ac038ab3701c41d375cd8c7b483261acc1..5968bd2c5c10f2c05646bec9f041dc40aec607a9 100644 --- a/frameworks/ets/ani/accesstoken/src/ani_request_permission_on_setting.cpp +++ b/frameworks/ets/ani/accesstoken/src/ani_request_permission_on_setting.cpp @@ -15,6 +15,7 @@ #include "ani_request_permission_on_setting.h" #include "accesstoken_kit.h" #include "accesstoken_common_log.h" +#include "permission_map.h" #include "token_setproc.h" #include "want.h" @@ -556,6 +557,24 @@ void RequestOnSettingAsyncInstanceControl::CheckDynamicRequest( } } +bool CheckManualSettingPerm(const std::vector& permissionList) +{ + bool result = false; + bool isAllManual = true; + for (const auto& perm : permissionList) { + PermissionBriefDef permissionBriefDef; + if (GetPermissionBriefDef(perm, permissionBriefDef)) { + if (permissionBriefDef.grantMode == MANUAL_SETTING) { + result = true; + } else { + isAllManual = false; + break; + } + } + } + return result && isAllManual; +} + void RequestPermissionOnSettingExecute([[maybe_unused]] ani_env* env, [[maybe_unused]] ani_object object, ani_object aniContext, ani_array_ref permissionList, ani_object callback) { @@ -573,6 +592,15 @@ void RequestPermissionOnSettingExecute([[maybe_unused]] ani_env* env, ani_ref nullRef = nullptr; env->GetNull(&nullRef); ani_object result = reinterpret_cast(nullRef); + + if (CheckManualSettingPerm(asyncContext->permissionList)) { + ani_object error = BusinessErrorAni::CreateError(env, STS_ERROR_PERMISSION_NOT_USER_GRANT_OR_MANUAL_SETTING, + GetErrorMessage(STS_ERROR_PERMISSION_NOT_USER_GRANT_OR_MANUAL_SETTING, + "The specified permission cannot be requested from the user.")); + ExecuteAsyncCallback(env, callback, error, result); + return; + } + static AccessTokenID selfTokenID = static_cast(GetSelfTokenID()); if (selfTokenID != asyncContext->tokenId) { LOGE(ATM_DOMAIN, ATM_TAG, "The context tokenID %{public}d is not same with selfTokenID %{public}d.", diff --git a/frameworks/ets/ani/common/include/ani_error.h b/frameworks/ets/ani/common/include/ani_error.h index e47fe113372111c792d696a2f5c4493d246eada9..3cb11b70631faf182a6a67ccfbf69862953e7a01 100644 --- a/frameworks/ets/ani/common/include/ani_error.h +++ b/frameworks/ets/ani/common/include/ani_error.h @@ -45,6 +45,7 @@ typedef enum { STS_ERROR_ALL_PERM_GRANTED = 12100011, STS_ERROR_PERM_NOT_REVOKE_BY_USER = 12100012, STS_ERROR_GLOBAL_SWITCH_IS_ALREADY_OPEN = 12100013, + STS_ERROR_PERMISSION_NOT_USER_GRANT_OR_MANUAL_SETTING = 12100014, } STSErrorCode; struct AtmResult { diff --git a/frameworks/ets/ani/common/src/ani_error.cpp b/frameworks/ets/ani/common/src/ani_error.cpp index f2433f1eebf76f1e551deec86596c037a2610af8..7ace372261eb59ba17a70a4ba8b33197e4ebacf2 100644 --- a/frameworks/ets/ani/common/src/ani_error.cpp +++ b/frameworks/ets/ani/common/src/ani_error.cpp @@ -45,6 +45,7 @@ static const std::unordered_map g_errorStringMap = { { STS_ERROR_PERM_NOT_REVOKE_BY_USER, "The permission list contains the permission that has not been revoked by the user." }, { STS_ERROR_GLOBAL_SWITCH_IS_ALREADY_OPEN, "The specific global switch is already open." }, + { STS_ERROR_PERMISSION_NOT_USER_GRANT_OR_MANUAL_SETTING, "Unexpected permission."}, }; void BusinessErrorAni::ThrowError(ani_env* env, int32_t err, const std::string& errMsg) diff --git a/frameworks/js/napi/accesstoken/BUILD.gn b/frameworks/js/napi/accesstoken/BUILD.gn index 6cebe5c4c58380e6392910cf5b676301cad5ec80..3c484cffceed988cecd9c68c64b4a9d2a4452f8b 100644 --- a/frameworks/js/napi/accesstoken/BUILD.gn +++ b/frameworks/js/napi/accesstoken/BUILD.gn @@ -39,6 +39,7 @@ ohos_shared_library("libabilityaccessctrl") { ] deps = [ + "${access_token_path}/frameworks/common:accesstoken_common_cxx", "${access_token_path}/interfaces/innerkits/accesstoken:libaccesstoken_sdk", "${access_token_path}/interfaces/innerkits/token_callback:libtoken_callback_sdk", "${access_token_path}/interfaces/innerkits/token_setproc:libtokensetproc_shared", diff --git a/frameworks/js/napi/accesstoken/src/napi_atmanager.cpp b/frameworks/js/napi/accesstoken/src/napi_atmanager.cpp index d0279afb67294895798f604e0050f631f6583238..e2b089b22e31dc17319e8a7ed85ba1c4f07158a6 100644 --- a/frameworks/js/napi/accesstoken/src/napi_atmanager.cpp +++ b/frameworks/js/napi/accesstoken/src/napi_atmanager.cpp @@ -21,6 +21,7 @@ #include "napi_request_permission.h" #include "napi_request_permission_on_setting.h" #include "parameter.h" +#include "permission_map.h" #include "token_setproc.h" #include "want.h" #include "accesstoken_common_log.h" @@ -229,6 +230,8 @@ napi_value NapiAtManager::Init(napi_env env, napi_value exports) DECLARE_NAPI_FUNCTION("verifyAccessTokenSync", VerifyAccessTokenSync), DECLARE_NAPI_FUNCTION("grantUserGrantedPermission", GrantUserGrantedPermission), DECLARE_NAPI_FUNCTION("revokeUserGrantedPermission", RevokeUserGrantedPermission), + DECLARE_NAPI_FUNCTION("grantPermission", GrantPermissionWithManual), + DECLARE_NAPI_FUNCTION("revokePermission", RevokePermissionWithManual), DECLARE_NAPI_FUNCTION("checkAccessToken", CheckAccessToken), DECLARE_NAPI_FUNCTION("checkAccessTokenSync", VerifyAccessTokenSync), DECLARE_NAPI_FUNCTION("getPermissionFlags", GetPermissionFlags), @@ -650,7 +653,7 @@ napi_value NapiAtManager::VerifyAccessTokenSync(napi_env env, napi_callback_info } bool NapiAtManager::ParseInputGrantOrRevokePermission(const napi_env env, const napi_callback_info info, - AtManagerAsyncContext& asyncContext) + AtManagerAsyncContext& asyncContext, bool isManual) { size_t argc = NapiContextCommon::MAX_PARAMS_FOUR; napi_value argv[NapiContextCommon::MAX_PARAMS_FOUR] = {nullptr}; @@ -690,7 +693,7 @@ bool NapiAtManager::ParseInputGrantOrRevokePermission(const napi_env env, const return false; } - if (argc == NapiContextCommon::MAX_PARAMS_FOUR) { + if (!isManual && argc == NapiContextCommon::MAX_PARAMS_FOUR) { // 3: the fourth parameter of argv if ((!IsUndefinedOrNull(env, argv[3])) && (!ParseCallback(env, argv[3], asyncContext.callbackRef))) { NAPI_CALL_BASE(env, napi_throw(env, GenerateBusinessError(env, JsErrorCode::JS_ERROR_PARAM_ILLEGAL, @@ -731,7 +734,8 @@ void NapiAtManager::GrantUserGrantedPermissionExecute(napi_env env, void *data) if (!IsPermissionFlagValid(asyncContext->flag)) { asyncContext->errorCode = ERR_PARAM_INVALID; } - // only user_grant permission can use innerkit class method to grant permission, system_grant return failed + // only user_grant permission can use innerkit class method to grant permission + // system_grant or manual_setting return failed if (permissionDef.grantMode == USER_GRANT) { asyncContext->errorCode = AccessTokenKit::GrantPermission(asyncContext->tokenId, asyncContext->permissionName, asyncContext->flag); @@ -882,7 +886,8 @@ void NapiAtManager::RevokeUserGrantedPermissionExecute(napi_env env, void *data) if (!IsPermissionFlagValid(asyncContext->flag)) { asyncContext->errorCode = ERR_PARAM_INVALID; } - // only user_grant permission can use innerkit class method to grant permission, system_grant return failed + // only user_grant permission can use innerkit class method to grant permission + // system_grant or manual_setting return failed if (permissionDef.grantMode == USER_GRANT) { asyncContext->errorCode = AccessTokenKit::RevokePermission(asyncContext->tokenId, asyncContext->permissionName, asyncContext->flag); @@ -943,6 +948,160 @@ napi_value NapiAtManager::RevokeUserGrantedPermission(napi_env env, napi_callbac return result; } +void NapiAtManager::GrantPermissionWithManualExecute(napi_env env, void *data) +{ + AtManagerAsyncContext* asyncContext = reinterpret_cast(data); + if (asyncContext == nullptr) { + return; + } + + PermissionBriefDef permissionDef; + if (!GetPermissionBriefDef(asyncContext->permissionName, permissionDef)) { + asyncContext->errorCode = ERR_PERMISSION_NOT_EXIST; + return; + } + + LOGD(ATM_DOMAIN, ATM_TAG, "PermissionName = %{public}s, grantmode = %{public}d.", + asyncContext->permissionName.c_str(), permissionDef.grantMode); + + if (!IsPermissionFlagValid(asyncContext->flag)) { + asyncContext->errorCode = ERR_PARAM_INVALID; + return; + } + // only user_grant or manual_setting permission can use innerkit class method to grant permission + // system_grant return failed + if (permissionDef.grantMode == USER_GRANT || permissionDef.grantMode == MANUAL_SETTING) { + asyncContext->errorCode = AccessTokenKit::GrantPermission( + asyncContext->tokenId, asyncContext->permissionName, asyncContext->flag, true); + } else { + asyncContext->errorCode = ERR_PERMISSION_NOT_USER_GRANT_OR_MANUAL_SETTING; + } + LOGD(ATM_DOMAIN, ATM_TAG, + "tokenId = %{public}d, permissionName = %{public}s, flag = %{public}d, grant result = %{public}d.", + asyncContext->tokenId, asyncContext->permissionName.c_str(), asyncContext->flag, asyncContext->errorCode); +} + +void NapiAtManager::GrantPermissionWithManualComplete(napi_env env, napi_status status, void *data) +{ + AtManagerAsyncContext* context = reinterpret_cast(data); + if (context == nullptr) { + LOGE(ATM_DOMAIN, ATM_TAG, "AsyncContext is null."); + return; + } + std::unique_ptr callbackPtr {context}; + napi_value result = GetNapiNull(env); + + ReturnPromiseResult(env, *context, result); +} + +napi_value NapiAtManager::GrantPermissionWithManual(napi_env env, napi_callback_info info) +{ + LOGD(ATM_DOMAIN, ATM_TAG, "GrantPermissionWithManual begin."); + + auto* context = new (std::nothrow) AtManagerAsyncContext(env); // for async work deliver data + if (context == nullptr) { + LOGE(ATM_DOMAIN, ATM_TAG, "New struct fail."); + return nullptr; + } + + std::unique_ptr contextPtr {context}; + if (!ParseInputGrantOrRevokePermission(env, info, *context, true)) { + return nullptr; + } + + napi_value result = nullptr; + + NAPI_CALL(env, napi_create_promise(env, &(context->deferred), &result)); + + napi_value resource = nullptr; + NAPI_CALL(env, napi_create_string_utf8(env, "GrantPermissionWithManual", NAPI_AUTO_LENGTH, &resource)); + + NAPI_CALL(env, napi_create_async_work( + env, nullptr, resource, + GrantPermissionWithManualExecute, GrantPermissionWithManualComplete, + reinterpret_cast(context), &(context->work))); + + NAPI_CALL(env, napi_queue_async_work_with_qos(env, context->work, napi_qos_default)); + + LOGD(ATM_DOMAIN, ATM_TAG, "GrantPermissionWithManual end."); + contextPtr.release(); + return result; +} + +void NapiAtManager::RevokePermissionWithManualExecute(napi_env env, void *data) +{ + AtManagerAsyncContext* asyncContext = reinterpret_cast(data); + if (asyncContext == nullptr) { + return; + } + + PermissionBriefDef permissionDef; + if (!GetPermissionBriefDef(asyncContext->permissionName, permissionDef)) { + asyncContext->errorCode = ERR_PERMISSION_NOT_EXIST; + return; + } + + LOGD(ATM_DOMAIN, ATM_TAG, "PermissionName = %{public}s, grantmode = %{public}d.", + asyncContext->permissionName.c_str(), permissionDef.grantMode); + + if (!IsPermissionFlagValid(asyncContext->flag)) { + asyncContext->errorCode = ERR_PARAM_INVALID; + return; + } + // only user_grant or manual_setting permission can use innerkit class method to grant permission + // system_grant return failed + if (permissionDef.grantMode == USER_GRANT || permissionDef.grantMode == MANUAL_SETTING) { + asyncContext->errorCode = AccessTokenKit::RevokePermission( + asyncContext->tokenId, asyncContext->permissionName, asyncContext->flag, true); + } else { + asyncContext->errorCode = ERR_PERMISSION_NOT_USER_GRANT_OR_MANUAL_SETTING; + } + LOGD(ATM_DOMAIN, ATM_TAG, + "tokenId = %{public}d, permissionName = %{public}s, flag = %{public}d, revoke errorCode = %{public}d.", + asyncContext->tokenId, asyncContext->permissionName.c_str(), asyncContext->flag, asyncContext->errorCode); +} + +void NapiAtManager::RevokePermissionWithManualComplete(napi_env env, napi_status status, void *data) +{ + AtManagerAsyncContext* asyncContext = reinterpret_cast(data); + std::unique_ptr callbackPtr {asyncContext}; + + napi_value result = GetNapiNull(env); + ReturnPromiseResult(env, *asyncContext, result); +} + +napi_value NapiAtManager::RevokePermissionWithManual(napi_env env, napi_callback_info info) +{ + LOGD(ATM_DOMAIN, ATM_TAG, "RevokePermissionWithManual begin."); + + auto* asyncContext = new (std::nothrow) AtManagerAsyncContext(env); // for async work deliver data + if (asyncContext == nullptr) { + LOGE(ATM_DOMAIN, ATM_TAG, "New struct fail."); + return nullptr; + } + + std::unique_ptr context {asyncContext}; + if (!ParseInputGrantOrRevokePermission(env, info, *asyncContext, true)) { + return nullptr; + } + + napi_value result = nullptr; + NAPI_CALL(env, napi_create_promise(env, &(asyncContext->deferred), &result)); + + napi_value resource = nullptr; + NAPI_CALL(env, napi_create_string_utf8(env, "RevokePermissionWithManual", NAPI_AUTO_LENGTH, &resource)); + + NAPI_CALL(env, napi_create_async_work( + env, nullptr, resource, + RevokePermissionWithManualExecute, RevokePermissionWithManualComplete, + reinterpret_cast(asyncContext), &(asyncContext->work))); + + NAPI_CALL(env, napi_queue_async_work_with_qos(env, asyncContext->work, napi_qos_default)); + LOGD(ATM_DOMAIN, ATM_TAG, "RevokePermissionWithManual end."); + context.release(); + return result; +} + void NapiAtManager::GetPermissionFlagsExecute(napi_env env, void *data) { AtManagerAsyncContext* asyncContext = reinterpret_cast(data); diff --git a/frameworks/js/napi/accesstoken/src/napi_context_common.cpp b/frameworks/js/napi/accesstoken/src/napi_context_common.cpp index ed4e546baa36252b08e95970ee6ea40dd969b571..1989d1aeba0978e6fcfca0e881e17146315c26c2 100644 --- a/frameworks/js/napi/accesstoken/src/napi_context_common.cpp +++ b/frameworks/js/napi/accesstoken/src/napi_context_common.cpp @@ -60,6 +60,9 @@ int32_t NapiContextCommon::GetJsErrorCode(int32_t errCode) case ERR_MALLOC_FAILED: jsCode = JS_ERROR_OUT_OF_MEMORY; break; + case ERR_PERMISSION_NOT_USER_GRANT_OR_MANUAL_SETTING: + jsCode = JS_ERROR_PERMISSION_NOT_USER_GRANT_OR_MANUAL_SETTING; + break; default: jsCode = JS_ERROR_INNER; break; diff --git a/frameworks/js/napi/accesstoken/src/napi_request_permission_on_setting.cpp b/frameworks/js/napi/accesstoken/src/napi_request_permission_on_setting.cpp index e14d167db2625f0e4a2664ae2c721d81935d7bbe..0682505ed386b742cd4a64bc826ccfd164367a35 100644 --- a/frameworks/js/napi/accesstoken/src/napi_request_permission_on_setting.cpp +++ b/frameworks/js/napi/accesstoken/src/napi_request_permission_on_setting.cpp @@ -18,6 +18,7 @@ #include "accesstoken_kit.h" #include "accesstoken_common_log.h" #include "napi_base_context.h" +#include "permission_map.h" #include "token_setproc.h" #include "want.h" @@ -617,6 +618,24 @@ bool NapiRequestPermissionOnSetting::ParseRequestPermissionOnSetting(const napi_ return true; } +bool NapiRequestPermissionOnSetting::CheckManualSettingPerm(const std::vector& permissionList) +{ + bool result = false; + bool isAllManual = true; + for (const auto& perm : permissionList) { + PermissionBriefDef permissionBriefDef; + if (GetPermissionBriefDef(perm, permissionBriefDef)) { + if (permissionBriefDef.grantMode == MANUAL_SETTING) { + result = true; + } else { + isAllManual = false; + break; + } + } + } + return result && isAllManual; +} + void NapiRequestPermissionOnSetting::RequestPermissionOnSettingExecute(napi_env env, void* data) { // asyncContext release in complete @@ -625,6 +644,10 @@ void NapiRequestPermissionOnSetting::RequestPermissionOnSettingExecute(napi_env if ((asyncContextHandle == nullptr) || (asyncContextHandle->asyncContextPtr == nullptr)) { return; } + if (CheckManualSettingPerm(asyncContextHandle->asyncContextPtr->permissionList)) { + asyncContextHandle->asyncContextPtr->result.errorCode = ERR_PERMISSION_NOT_USER_GRANT_OR_MANUAL_SETTING; + return; + } if (asyncContextHandle->asyncContextPtr->uiAbilityFlag) { if ((asyncContextHandle->asyncContextPtr->abilityContext == nullptr) || (asyncContextHandle->asyncContextPtr->abilityContext->GetApplicationInfo() == nullptr)) { diff --git a/frameworks/js/napi/common/src/napi_error.cpp b/frameworks/js/napi/common/src/napi_error.cpp index 6b3ae3d679e20f62be46802c5111ba6d9d08100f..1529162bc9542f4fdbf6dc7600e62b83210d6484 100644 --- a/frameworks/js/napi/common/src/napi_error.cpp +++ b/frameworks/js/napi/common/src/napi_error.cpp @@ -39,6 +39,7 @@ static const std::map g_errorStringMap = { {JS_ERROR_PERM_REVOKE_BY_USER, "The permission list contains the permission that has not been revoked by the user."}, {JS_ERROR_GLOBAL_SWITCH_IS_ALREADY_OPEN, "The specific global switch is already open."}, + {JS_ERROR_PERMISSION_NOT_USER_GRANT_OR_MANUAL_SETTING, "The specified permission is an unexpected permission."}, }; std::string GetParamErrorMsg(const std::string& param, const std::string& type) diff --git a/interfaces/innerkits/accesstoken/include/access_token.h b/interfaces/innerkits/accesstoken/include/access_token.h index e43cceca1ca7f797bc84e5d9d8283a653cf32ab0..12ddcbfc750f40a0379e91ef4469b2361ee24903 100644 --- a/interfaces/innerkits/accesstoken/include/access_token.h +++ b/interfaces/innerkits/accesstoken/include/access_token.h @@ -170,6 +170,11 @@ typedef enum TypeGrantMode { * the permission is decleared and app is installed */ SYSTEM_GRANT = 1, + /** + * manual setting permission + * can only be set by the user in the settings + */ + MANUAL_SETTING = 2, } GrantMode; /** @@ -261,6 +266,8 @@ typedef enum TypePermissionErrorReason { UNABLE_POP_UP = 5, /** The permission is fixed by policy */ FIXED_BY_POLICY = 6, + /* The permission is manual setting */ + MANUAL_SETTING_PERM = 7, /** The service is abnormal */ SERVICE_ABNORMAL = 12, } PermissionErrorReason; diff --git a/interfaces/innerkits/accesstoken/include/access_token_error.h b/interfaces/innerkits/accesstoken/include/access_token_error.h index 69588370360ca5500e614680b3ffca3a0503eb50..3a1e656b9e4098c0deb15b20ba527900573f78c8 100644 --- a/interfaces/innerkits/accesstoken/include/access_token_error.h +++ b/interfaces/innerkits/accesstoken/include/access_token_error.h @@ -80,7 +80,8 @@ enum AccessTokenError { ERR_ADD_DEATH_RECIPIENT_FAILED, ERR_PRASE_RAW_DATA_FAILED, ERR_PERMISSION_WITHOUT_VALUE, - ERR_PERMISSION_RESTRICTED + ERR_PERMISSION_RESTRICTED, + ERR_PERMISSION_NOT_USER_GRANT_OR_MANUAL_SETTING }; } // namespace AccessToken } // namespace Security diff --git a/interfaces/innerkits/accesstoken/include/accesstoken_kit.h b/interfaces/innerkits/accesstoken/include/accesstoken_kit.h index a2a9af9d57e8ddcbae0d1af97ae7b53d93e90464..a559189a042abcb08f3b14f87dd45377aa056859 100644 --- a/interfaces/innerkits/accesstoken/include/accesstoken_kit.h +++ b/interfaces/innerkits/accesstoken/include/accesstoken_kit.h @@ -325,17 +325,21 @@ public: * @param tokenID token id * @param permissionName permission name quote * @param flag enum PermissionFlag, see access_token.h + * @param withManual can MANUAL_SETTING perm be granted * @return error code, see access_token_error.h */ - static int GrantPermission(AccessTokenID tokenID, const std::string& permissionName, uint32_t flag); + static int GrantPermission( + AccessTokenID tokenID, const std::string& permissionName, uint32_t flag, bool withManual = false); /** * @brief Revoke input permission to input tokenID with input flag. * @param tokenID token id * @param permissionName permission name quote * @param flag enum PermissionFlag, see access_token.h + * @param withManual can MANUAL_SETTING perm be revoked * @return error code, see access_token_error.h */ - static int RevokePermission(AccessTokenID tokenID, const std::string& permissionName, uint32_t flag); + static int RevokePermission( + AccessTokenID tokenID, const std::string& permissionName, uint32_t flag, bool withManual = false); /** * @brief Clear all user granted permissions state in input tokenID. * @param tokenID token id diff --git a/interfaces/innerkits/accesstoken/libaccesstoken_sdk.map b/interfaces/innerkits/accesstoken/libaccesstoken_sdk.map index 8c89678b9ce1d6c72ca558694ef29a6bf342f464..19ccbf4f8c5fcddcdf4502b8b67f7f650f9376a5 100644 --- a/interfaces/innerkits/accesstoken/libaccesstoken_sdk.map +++ b/interfaces/innerkits/accesstoken/libaccesstoken_sdk.map @@ -27,9 +27,9 @@ "OHOS::Security::AccessToken::AccessTokenKit::GetTokenIDByUserID(int, std::__h::unordered_set, std::__h::equal_to, std::__h::allocator>&)"; "OHOS::Security::AccessToken::AccessTokenKit::GetNativeTokenInfo(unsigned int, OHOS::Security::AccessToken::NativeTokenInfo&)"; "OHOS::Security::AccessToken::AccessTokenKit::GetPermissionFlag(unsigned int, std::__h::basic_string, std::__h::allocator> const&, unsigned int&)"; - "OHOS::Security::AccessToken::AccessTokenKit::GrantPermission(unsigned int, std::__h::basic_string, std::__h::allocator> const&, unsigned int)"; + "OHOS::Security::AccessToken::AccessTokenKit::GrantPermission(unsigned int, std::__h::basic_string, std::__h::allocator> const&, unsigned int, bool)"; "OHOS::Security::AccessToken::AccessTokenKit::SetPermissionStatusWithPolicy(unsigned int, std::__h::vector, std::__h::allocator>, std::__h::allocator, std::__h::allocator>>> const&, int, unsigned int)"; - "OHOS::Security::AccessToken::AccessTokenKit::RevokePermission(unsigned int, std::__h::basic_string, std::__h::allocator> const&, unsigned int)"; + "OHOS::Security::AccessToken::AccessTokenKit::RevokePermission(unsigned int, std::__h::basic_string, std::__h::allocator> const&, unsigned int, bool)"; "OHOS::Security::AccessToken::AccessTokenKit::ClearUserGrantedPermissionState(unsigned int)"; "OHOS::Security::AccessToken::PermStateChangeCallbackCustomize::PermStateChangeCallbackCustomize(OHOS::Security::AccessToken::PermStateChangeScope const&)"; "OHOS::Security::AccessToken::AccessTokenKit::RegisterPermStateChangeCallback(std::__h::shared_ptr const&)"; diff --git a/interfaces/innerkits/accesstoken/src/accesstoken_kit.cpp b/interfaces/innerkits/accesstoken/src/accesstoken_kit.cpp index 83453a03d3c76cb52b93c622a95217b43b94291f..0df4c401777022ecf01a7154e9318dc5374d62db 100644 --- a/interfaces/innerkits/accesstoken/src/accesstoken_kit.cpp +++ b/interfaces/innerkits/accesstoken/src/accesstoken_kit.cpp @@ -492,7 +492,8 @@ int AccessTokenKit::GetPermissionFlag(AccessTokenID tokenID, const std::string& return AccessTokenManagerClient::GetInstance().GetPermissionFlag(tokenID, permissionName, flag); } -int AccessTokenKit::GrantPermission(AccessTokenID tokenID, const std::string& permissionName, uint32_t flag) +int AccessTokenKit::GrantPermission( + AccessTokenID tokenID, const std::string& permissionName, uint32_t flag, bool withManual) { LOGD(ATM_DOMAIN, ATM_TAG, "TokenID=%{public}d, permissionName=%{public}s, flag=%{public}d.", tokenID, permissionName.c_str(), flag); @@ -512,10 +513,11 @@ int AccessTokenKit::GrantPermission(AccessTokenID tokenID, const std::string& pe LOGE(ATM_DOMAIN, ATM_TAG, "Flag is invalid"); return AccessTokenError::ERR_PARAM_INVALID; } - return AccessTokenManagerClient::GetInstance().GrantPermission(tokenID, permissionName, flag); + return AccessTokenManagerClient::GetInstance().GrantPermission(tokenID, permissionName, flag, withManual); } -int AccessTokenKit::RevokePermission(AccessTokenID tokenID, const std::string& permissionName, uint32_t flag) +int AccessTokenKit::RevokePermission( + AccessTokenID tokenID, const std::string& permissionName, uint32_t flag, bool withManual) { LOGD(ATM_DOMAIN, ATM_TAG, "TokenID=%{public}d, permissionName=%{public}s, flag=%{public}d.", tokenID, permissionName.c_str(), flag); @@ -535,7 +537,7 @@ int AccessTokenKit::RevokePermission(AccessTokenID tokenID, const std::string& p LOGE(ATM_DOMAIN, ATM_TAG, "Invalid flag"); return AccessTokenError::ERR_PARAM_INVALID; } - return AccessTokenManagerClient::GetInstance().RevokePermission(tokenID, permissionName, flag); + return AccessTokenManagerClient::GetInstance().RevokePermission(tokenID, permissionName, flag, withManual); } int AccessTokenKit::ClearUserGrantedPermissionState(AccessTokenID tokenID) @@ -745,7 +747,14 @@ static void FormatAvailableType(ATokenAvailableTypeEnum availableType, std::stri static void PermDefinitionToString(const PermissionBriefDef& briefDef, std::string& dumpInfo) { - std::string grantMode = briefDef.grantMode == GrantMode::USER_GRANT ? "USER_GRANT" : "SYSTEM_GRANT"; + std::string grantMode; + if (briefDef.grantMode == GrantMode::USER_GRANT) { + grantMode = "USER_GRANT"; + } else if (briefDef.grantMode == GrantMode::SYSTEM_GRANT) { + grantMode = "SYSTEM_GRANT"; + } else { + grantMode = "MANUAL_SETTING"; + } std::string apl; FormatApl(briefDef.availableLevel, apl); std::string availableType; diff --git a/interfaces/innerkits/accesstoken/src/accesstoken_manager_client.cpp b/interfaces/innerkits/accesstoken/src/accesstoken_manager_client.cpp index b78a9ec69c5e27157994feef60aece30dd12add2..e37580e20fd1acbacd1db94f9e0158c176aff617 100644 --- a/interfaces/innerkits/accesstoken/src/accesstoken_manager_client.cpp +++ b/interfaces/innerkits/accesstoken/src/accesstoken_manager_client.cpp @@ -328,14 +328,15 @@ int32_t AccessTokenManagerClient::GetPermissionsStatus( return result; } -int AccessTokenManagerClient::GrantPermission(AccessTokenID tokenID, const std::string& permissionName, uint32_t flag) +int AccessTokenManagerClient::GrantPermission( + AccessTokenID tokenID, const std::string& permissionName, uint32_t flag, bool withManual) { auto proxy = GetProxy(); if (proxy == nullptr) { LOGE(ATM_DOMAIN, ATM_TAG, "Proxy is null"); return AccessTokenError::ERR_SERVICE_ABNORMAL; } - int32_t result = proxy->GrantPermission(tokenID, permissionName, flag); + int32_t result = proxy->GrantPermission(tokenID, permissionName, flag, withManual); if (result != RET_SUCCESS) { result = ConvertResult(result); } @@ -343,14 +344,15 @@ int AccessTokenManagerClient::GrantPermission(AccessTokenID tokenID, const std:: return result; } -int AccessTokenManagerClient::RevokePermission(AccessTokenID tokenID, const std::string& permissionName, uint32_t flag) +int AccessTokenManagerClient::RevokePermission( + AccessTokenID tokenID, const std::string& permissionName, uint32_t flag, bool withManual) { auto proxy = GetProxy(); if (proxy == nullptr) { LOGE(ATM_DOMAIN, ATM_TAG, "Proxy is null"); return AccessTokenError::ERR_SERVICE_ABNORMAL; } - int32_t result = proxy->RevokePermission(tokenID, permissionName, flag); + int32_t result = proxy->RevokePermission(tokenID, permissionName, flag, withManual); if (result != RET_SUCCESS) { result = ConvertResult(result); } diff --git a/interfaces/innerkits/accesstoken/src/accesstoken_manager_client.h b/interfaces/innerkits/accesstoken/src/accesstoken_manager_client.h index c3c9efd3411e058f232719a65cc4c5bc71d56518..01ae40f836483077619c167b4da239d39c42a62d 100644 --- a/interfaces/innerkits/accesstoken/src/accesstoken_manager_client.h +++ b/interfaces/innerkits/accesstoken/src/accesstoken_manager_client.h @@ -61,8 +61,8 @@ public: PermissionOper GetSelfPermissionsState(std::vector& permList, PermissionGrantInfo& info); int32_t GetPermissionsStatus(AccessTokenID tokenID, std::vector& permList); - int GrantPermission(AccessTokenID tokenID, const std::string& permissionName, uint32_t flag); - int RevokePermission(AccessTokenID tokenID, const std::string& permissionName, uint32_t flag); + int GrantPermission(AccessTokenID tokenID, const std::string& permissionName, uint32_t flag, bool withManual); + int RevokePermission(AccessTokenID tokenID, const std::string& permissionName, uint32_t flag, bool withManual); int GrantPermissionForSpecifiedTime( AccessTokenID tokenID, const std::string& permissionName, uint32_t onceTime); int ClearUserGrantedPermissionState(AccessTokenID tokenID); diff --git a/interfaces/innerkits/accesstoken/test/unittest/HapTokenTest/init_hap_token_test.cpp b/interfaces/innerkits/accesstoken/test/unittest/HapTokenTest/init_hap_token_test.cpp index 56d10b2bf847ab41f6e30b344333f400e31679fc..f91f0cec760f2af8cc52256f1f46d5afb4e8ec73 100644 --- a/interfaces/innerkits/accesstoken/test/unittest/HapTokenTest/init_hap_token_test.cpp +++ b/interfaces/innerkits/accesstoken/test/unittest/HapTokenTest/init_hap_token_test.cpp @@ -1512,6 +1512,42 @@ HWTEST_F(InitHapTokenTest, InitHapTokenAbnormalTest006, TestSize.Level0) int32_t ret = AccessTokenKit::InitHapToken(infoParams, policyParams, fullTokenId); EXPECT_EQ(ERR_PARAM_INVALID, ret); } + +/** + * @tc.name: InitHapTokenWithManualTest001 + * @tc.desc: InitHapToken with MANUAL_SETTING permission + * @tc.type: FUNC + * @tc.require: + */ +HWTEST_F(InitHapTokenTest, InitHapTokenWithManualTest001, TestSize.Level0) +{ + LOGI(ATM_DOMAIN, ATM_TAG, "InitHapTokenWithManualTest001"); + MockNativeToken mock("foundation"); + + HapInfoParams infoParams; + HapPolicyParams policyParams; + TestCommon::GetHapParams(infoParams, policyParams); + policyParams.apl = APL_NORMAL; + TestCommon::TestPrepareManualPermissionStatus(policyParams); + AccessTokenIDEx fullTokenId; + ASSERT_EQ(RET_SUCCESS, AccessTokenKit::InitHapToken(infoParams, policyParams, fullTokenId)); + AccessTokenID tokenID = fullTokenId.tokenIdExStruct.tokenID; + ASSERT_NE(INVALID_TOKENID, tokenID); + + std::vector reqPermList; + EXPECT_EQ(RET_SUCCESS, AccessTokenKit::GetReqPermissions(tokenID, reqPermList, true)); + EXPECT_EQ(reqPermList.size(), 0); + + std::vector reqPermList2; + EXPECT_EQ(RET_SUCCESS, AccessTokenKit::GetReqPermissions(tokenID, reqPermList2, false)); + EXPECT_EQ(reqPermList2.size(), NUMBER_THREE); + + for (auto permState : reqPermList2) { + EXPECT_EQ(PERMISSION_DENIED, AccessTokenKit::VerifyAccessToken(tokenID, permState.permissionName)); + } + + EXPECT_EQ(RET_SUCCESS, AccessTokenKit::DeleteToken(tokenID)); +} } // namespace AccessToken } // namespace Security } // namespace OHOS \ No newline at end of file diff --git a/interfaces/innerkits/accesstoken/test/unittest/HapTokenTest/update_hap_token_test.cpp b/interfaces/innerkits/accesstoken/test/unittest/HapTokenTest/update_hap_token_test.cpp index 8d4201d3ea6a0806ae77e5a0d2fe5a044280ffb5..55338c7ac2edca8802d35ff23f5795aa6519741d 100644 --- a/interfaces/innerkits/accesstoken/test/unittest/HapTokenTest/update_hap_token_test.cpp +++ b/interfaces/innerkits/accesstoken/test/unittest/HapTokenTest/update_hap_token_test.cpp @@ -43,6 +43,7 @@ static const int THREAD_NUM = 3; static constexpr int32_t CYCLE_TIMES = 100; static const int INVALID_APPIDDESC_LEN = 10244; static const int32_t INDEX_ZERO = 0; +static const int32_t INDEX_THREE = 3; static uint64_t g_selfTokenId = 0; static constexpr int32_t API_VERSION_EIGHT = 8; const std::string APP_DISTRIBUTION_TYPE_ENTERPRISE_MDM = "enterprise_mdm"; @@ -1873,6 +1874,106 @@ HWTEST_F(UpdateHapTokenTest, UpdateHapTokenAbnormalTest006, TestSize.Level0) tokenIdEx, info, g_testPolicyParams); EXPECT_EQ(AccessTokenError::ERR_PARAM_INVALID, ret); } + +/** + * @tc.name: UpdateHapTokenWithManualTest001 + * @tc.desc: UpdateHapToken with MANUAL_SETTING permission + * @tc.type: FUNC + * @tc.require: + */ +HWTEST_F(UpdateHapTokenTest, UpdateHapTokenWithManualTest001, TestSize.Level0) +{ + LOGI(ATM_DOMAIN, ATM_TAG, "UpdateHapTokenWithManualTest001"); + + HapInfoParams infoParams; + HapPolicyParams policyParams; + TestCommon::GetHapParams(infoParams, policyParams); + policyParams.apl = APL_NORMAL; + AccessTokenIDEx fullTokenId; + ASSERT_EQ(RET_SUCCESS, AccessTokenKit::InitHapToken(infoParams, policyParams, fullTokenId)); + AccessTokenID tokenID = fullTokenId.tokenIdExStruct.tokenID; + ASSERT_NE(INVALID_TOKENID, tokenID); + + std::vector reqPermList; + EXPECT_EQ(RET_SUCCESS, AccessTokenKit::GetReqPermissions(tokenID, reqPermList, true)); + EXPECT_EQ(reqPermList.size(), 0); + + std::vector reqPermList2; + EXPECT_EQ(RET_SUCCESS, AccessTokenKit::GetReqPermissions(tokenID, reqPermList2, false)); + EXPECT_EQ(reqPermList2.size(), 0); + + UpdateHapInfoParams updateInfoParams = { + .appIDDesc = infoParams.appIDDesc, + .apiVersion = infoParams.apiVersion, + .isSystemApp = false, + .appDistributionType = "" + }; + TestCommon::TestPrepareManualPermissionStatus(policyParams); + + EXPECT_EQ(RET_SUCCESS, AccessTokenKit::UpdateHapToken(fullTokenId, updateInfoParams, policyParams)); + + std::vector reqPermList3; + EXPECT_EQ(RET_SUCCESS, AccessTokenKit::GetReqPermissions(tokenID, reqPermList3, false)); + EXPECT_EQ(reqPermList3.size(), INDEX_THREE); + + for (auto permState : reqPermList3) { + EXPECT_EQ(PERMISSION_DENIED, AccessTokenKit::VerifyAccessToken(tokenID, permState.permissionName)); + } + + EXPECT_EQ(RET_SUCCESS, AccessTokenKit::DeleteToken(tokenID)); +} + +/** + * @tc.name: UpdateHapTokenWithManualTest002 + * @tc.desc: UpdateHapToken with MANUAL_SETTING permission + * @tc.type: FUNC + * @tc.require: + */ +HWTEST_F(UpdateHapTokenTest, UpdateHapTokenWithManualTest002, TestSize.Level0) +{ + LOGI(ATM_DOMAIN, ATM_TAG, "UpdateHapTokenWithManualTest002"); + + HapInfoParams infoParams; + HapPolicyParams policyParams; + TestCommon::GetHapParams(infoParams, policyParams); + policyParams.apl = APL_NORMAL; + TestCommon::TestPrepareManualPermissionStatus(policyParams); + AccessTokenIDEx fullTokenId; + ASSERT_EQ(RET_SUCCESS, AccessTokenKit::InitHapToken(infoParams, policyParams, fullTokenId)); + AccessTokenID tokenID = fullTokenId.tokenIdExStruct.tokenID; + ASSERT_NE(INVALID_TOKENID, tokenID); + + std::vector reqPermList; + EXPECT_EQ(RET_SUCCESS, AccessTokenKit::GetReqPermissions(tokenID, reqPermList, true)); + EXPECT_EQ(reqPermList.size(), 0); + + std::vector reqPermList2; + EXPECT_EQ(RET_SUCCESS, AccessTokenKit::GetReqPermissions(tokenID, reqPermList2, false)); + EXPECT_EQ(reqPermList2.size(), INDEX_THREE); + + for (auto permState : reqPermList2) { + EXPECT_EQ(PERMISSION_DENIED, AccessTokenKit::VerifyAccessToken(tokenID, permState.permissionName)); + } + + UpdateHapInfoParams updateInfoParams = { + .appIDDesc = infoParams.appIDDesc, + .apiVersion = infoParams.apiVersion, + .isSystemApp = false, + .appDistributionType = "" + }; + + HapPolicyParams policyParams2; + TestCommon::GetHapParams(infoParams, policyParams2); + policyParams2.apl = APL_NORMAL; + + EXPECT_EQ(RET_SUCCESS, AccessTokenKit::UpdateHapToken(fullTokenId, updateInfoParams, policyParams2)); + + std::vector reqPermList3; + EXPECT_EQ(RET_SUCCESS, AccessTokenKit::GetReqPermissions(tokenID, reqPermList3, false)); + EXPECT_EQ(reqPermList3.size(), 0); + + EXPECT_EQ(RET_SUCCESS, AccessTokenKit::DeleteToken(tokenID)); +} } // namespace AccessToken } // namespace Security } // namespace OHOS \ No newline at end of file diff --git a/interfaces/innerkits/accesstoken/test/unittest/PermisionDialogTest/get_self_permission_state_test.cpp b/interfaces/innerkits/accesstoken/test/unittest/PermisionDialogTest/get_self_permission_state_test.cpp index 374e36e69fc20ed726828d97827422d74946b52c..7d5b6e1c313b11466c1b0579055f24300f90573f 100644 --- a/interfaces/innerkits/accesstoken/test/unittest/PermisionDialogTest/get_self_permission_state_test.cpp +++ b/interfaces/innerkits/accesstoken/test/unittest/PermisionDialogTest/get_self_permission_state_test.cpp @@ -553,6 +553,53 @@ HWTEST_F(GetSelfPermissionStateTest, GetSelfPermissionsState009, TestSize.Level0 ASSERT_EQ(RET_SUCCESS, TestCommon::DeleteTestHapToken(tokenIdEx.tokenIdExStruct.tokenID)); EXPECT_EQ(0, SetSelfTokenID(g_selfTokenId)); // set self hap token } + +/** + * @tc.name: GetSelfPermissionsStateWithManualTest001 + * @tc.desc: GetSelfPermissionsState with MANUAL_SETTING permission + * @tc.type: FUNC + * @tc.require: + */ +HWTEST_F(GetSelfPermissionStateTest, GetSelfPermissionsStateWithManualTest001, TestSize.Level0) +{ + AccessTokenIDEx fullTokenId; + AccessTokenID tokenID; + { + MockNativeToken mock("foundation"); + + HapInfoParams infoParams; + HapPolicyParams policyParams; + TestCommon::GetHapParams(infoParams, policyParams); + policyParams.apl = APL_NORMAL; + TestCommon::TestPrepareManualPermissionStatus(policyParams); + + ASSERT_EQ(RET_SUCCESS, AccessTokenKit::InitHapToken(infoParams, policyParams, fullTokenId)); + tokenID = fullTokenId.tokenIdExStruct.tokenID; + ASSERT_NE(INVALID_TOKENID, tokenID); + } + + EXPECT_EQ(0, SetSelfTokenID(tokenID)); + + std::vector permsList; + PermissionListState manualState = { + .permissionName = "ohos.permission.MANUAL_ATM_SELF_USE", + .state = FORBIDDEN_OPER + }; + permsList.emplace_back(manualState); + PermissionGrantInfo info; + EXPECT_NE(DYNAMIC_OPER, AccessTokenKit::GetSelfPermissionsState(permsList, info)); + EXPECT_EQ(permsList[0].state, SETTING_OPER); + EXPECT_EQ(permsList[0].errorReason, MANUAL_SETTING_PERM); + + PermissionListState userState = { + .permissionName = "ohos.permission.CAMERA", + .state = FORBIDDEN_OPER + }; + permsList.emplace_back(userState); + EXPECT_EQ(DYNAMIC_OPER, AccessTokenKit::GetSelfPermissionsState(permsList, info)); + + EXPECT_EQ(RET_SUCCESS, TestCommon::DeleteTestHapToken(tokenID)); +} } // namespace AccessToken } // namespace Security } // namespace OHOS \ No newline at end of file diff --git a/interfaces/innerkits/accesstoken/test/unittest/PermisionDialogTest/get_self_permission_status_test.cpp b/interfaces/innerkits/accesstoken/test/unittest/PermisionDialogTest/get_self_permission_status_test.cpp index f962bcf9781a4fd2550aaa89fd09b5b5286f6d90..935b51799df62bad0a95cc4a60df5a78ccb11481 100644 --- a/interfaces/innerkits/accesstoken/test/unittest/PermisionDialogTest/get_self_permission_status_test.cpp +++ b/interfaces/innerkits/accesstoken/test/unittest/PermisionDialogTest/get_self_permission_status_test.cpp @@ -555,6 +555,54 @@ HWTEST_F(GetSelfPermissionStatusTest, GetSelfPermissionStatus009, TestSize.Level EXPECT_EQ(RET_SUCCESS, ret); EXPECT_EQ(PASS_OPER, status); } + +/** + * @tc.name: GetSelfPermissionStatusWithManualTest001 + * @tc.desc: GetSelfPermissionStatus with MANUAL_SETTING permission + * @tc.type: FUNC + * @tc.require: Issue Number + */ +HWTEST_F(GetSelfPermissionStatusTest, GetSelfPermissionStatusWithManualTest001, TestSize.Level0) +{ + AccessTokenIDEx fullTokenId; + AccessTokenID tokenID; + { + MockNativeToken mock("foundation"); + + HapInfoParams infoParams; + HapPolicyParams policyParams; + TestCommon::GetHapParams(infoParams, policyParams); + policyParams.apl = APL_NORMAL; + TestCommon::TestPrepareManualPermissionStatus(policyParams); + + ASSERT_EQ(RET_SUCCESS, AccessTokenKit::InitHapToken(infoParams, policyParams, fullTokenId)); + tokenID = fullTokenId.tokenIdExStruct.tokenID; + ASSERT_NE(INVALID_TOKENID, tokenID); + } + + EXPECT_EQ(0, SetSelfTokenID(tokenID)); + PermissionOper status; + int32_t ret = AccessTokenKit::GetSelfPermissionStatus("ohos.permission.MANUAL_ATM_SELF_USE", status); + EXPECT_EQ(RET_SUCCESS, ret); + EXPECT_EQ(SETTING_OPER, status); + + { + std::vector reqPerm; + reqPerm.emplace_back("ohos.permission.GRANT_SENSITIVE_PERMISSIONS"); + MockHapToken mock("GetSelfPermissionStatusWithManualTest0012", reqPerm, true); + + // grant MANUAL_SETTING permission + ASSERT_EQ(0, AccessTokenKit::GrantPermission( + tokenID, "ohos.permission.MANUAL_ATM_SELF_USE", PERMISSION_USER_SET, true)); + } + + EXPECT_EQ(0, SetSelfTokenID(tokenID)); + ret = AccessTokenKit::GetSelfPermissionStatus("ohos.permission.MANUAL_ATM_SELF_USE", status); + EXPECT_EQ(RET_SUCCESS, ret); + EXPECT_EQ(PASS_OPER, status); + + EXPECT_EQ(RET_SUCCESS, TestCommon::DeleteTestHapToken(tokenID)); +} } // namespace AccessToken } // namespace Security } // namespace OHOS diff --git a/interfaces/innerkits/accesstoken/test/unittest/PermissionsTest/grant_permission_test.cpp b/interfaces/innerkits/accesstoken/test/unittest/PermissionsTest/grant_permission_test.cpp index b7fea6a43c3ffd3650133c62620d1fd9fc73fc1b..f93c8cc13c719771c81f677452562ba41d9c4b70 100644 --- a/interfaces/innerkits/accesstoken/test/unittest/PermissionsTest/grant_permission_test.cpp +++ b/interfaces/innerkits/accesstoken/test/unittest/PermissionsTest/grant_permission_test.cpp @@ -51,6 +51,7 @@ void GrantPermissionTest::SetUpTestCase() std::vector reqPerm; reqPerm.emplace_back("ohos.permission.GRANT_SENSITIVE_PERMISSIONS"); reqPerm.emplace_back("ohos.permission.REVOKE_SENSITIVE_PERMISSIONS"); + reqPerm.emplace_back("ohos.permission.MANAGE_HAP_TOKENID"); g_mock = new (std::nothrow) MockHapToken("GrantPermissionTest", reqPerm); // clean up test cases @@ -324,6 +325,41 @@ HWTEST_F(GrantPermissionTest, GrantPermissionWithRenderTest001, TestSize.Level0) ASSERT_EQ(RET_SUCCESS, TestCommon::DeleteTestHapToken(tokenID)); } + +/** + * @tc.name: GrantPermissionWithManualTest001 + * @tc.desc: GrantPermission with MANUAL_SETTING permission + * @tc.type: FUNC + * @tc.require: + */ +HWTEST_F(GrantPermissionTest, GrantPermissionWithManualTest001, TestSize.Level0) +{ + LOGI(ATM_DOMAIN, ATM_TAG, "GrantPermissionWithManualTest001"); + MockNativeToken mock("foundation"); + + HapInfoParams infoParams; + HapPolicyParams policyParams; + TestCommon::GetHapParams(infoParams, policyParams); + policyParams.apl = APL_NORMAL; + TestCommon::TestPrepareManualPermissionStatus(policyParams); + AccessTokenIDEx fullTokenId; + ASSERT_EQ(RET_SUCCESS, AccessTokenKit::InitHapToken(infoParams, policyParams, fullTokenId)); + AccessTokenID tokenID = fullTokenId.tokenIdExStruct.tokenID; + ASSERT_NE(INVALID_TOKENID, tokenID); + + EXPECT_EQ(PERMISSION_DENIED, AccessTokenKit::VerifyAccessToken(tokenID, "ohos.permission.MANUAL_ATM_SELF_USE")); + // old grant function can't grant MANUAL_SETTING + EXPECT_EQ(ERR_PERMISSION_NOT_EXIST, + AccessTokenKit::GrantPermission(tokenID, "ohos.permission.MANUAL_ATM_SELF_USE", PERMISSION_USER_FIXED, false)); + EXPECT_EQ(PERMISSION_DENIED, AccessTokenKit::VerifyAccessToken(tokenID, "ohos.permission.MANUAL_ATM_SELF_USE")); + + // new grant function can grant MANUAL_SETTING + EXPECT_EQ(RET_SUCCESS, + AccessTokenKit::GrantPermission(tokenID, "ohos.permission.MANUAL_ATM_SELF_USE", PERMISSION_USER_FIXED, true)); + EXPECT_EQ(PERMISSION_GRANTED, AccessTokenKit::VerifyAccessToken(tokenID, "ohos.permission.MANUAL_ATM_SELF_USE")); + + EXPECT_EQ(RET_SUCCESS, TestCommon::DeleteTestHapToken(tokenID)); +} } // namespace AccessToken } // namespace Security } // namespace OHOS \ No newline at end of file diff --git a/interfaces/innerkits/accesstoken/test/unittest/PermissionsTest/revoke_permission_test.cpp b/interfaces/innerkits/accesstoken/test/unittest/PermissionsTest/revoke_permission_test.cpp index d2512fe43cb2b54503b0cc84500130730fbb8e00..53667eb42d72ce8b6ae18fd53491ec6f2c7b9751 100644 --- a/interfaces/innerkits/accesstoken/test/unittest/PermissionsTest/revoke_permission_test.cpp +++ b/interfaces/innerkits/accesstoken/test/unittest/PermissionsTest/revoke_permission_test.cpp @@ -49,7 +49,9 @@ void RevokePermissionTest::SetUpTestCase() TestCommon::SetTestEvironment(g_selfTokenId); std::vector reqPerm; + reqPerm.emplace_back("ohos.permission.GRANT_SENSITIVE_PERMISSIONS"); reqPerm.emplace_back("ohos.permission.REVOKE_SENSITIVE_PERMISSIONS"); + reqPerm.emplace_back("ohos.permission.MANAGE_HAP_TOKENID"); g_mock = new (std::nothrow) MockHapToken("RevokePermissionTest", reqPerm); // clean up test cases @@ -323,6 +325,44 @@ HWTEST_F(RevokePermissionTest, RevokePermissionWithRenderTest001, TestSize.Level ASSERT_EQ(RET_SUCCESS, TestCommon::DeleteTestHapToken(tokenID)); } + +/** + * @tc.name: RevokePermissionWithManualTest001 + * @tc.desc: RevokePermission with MANUAL_SETTING permission + * @tc.type: FUNC + * @tc.require: + */ +HWTEST_F(RevokePermissionTest, RevokePermissionWithManualTest001, TestSize.Level0) +{ + LOGI(ATM_DOMAIN, ATM_TAG, "RevokePermissionWithManualTest001"); + MockNativeToken mock("foundation"); + + HapInfoParams infoParams; + HapPolicyParams policyParams; + TestCommon::GetHapParams(infoParams, policyParams); + policyParams.apl = APL_NORMAL; + TestCommon::TestPrepareManualPermissionStatus(policyParams); + AccessTokenIDEx fullTokenId; + ASSERT_EQ(RET_SUCCESS, AccessTokenKit::InitHapToken(infoParams, policyParams, fullTokenId)); + AccessTokenID tokenID = fullTokenId.tokenIdExStruct.tokenID; + ASSERT_NE(INVALID_TOKENID, tokenID); + + EXPECT_EQ(RET_SUCCESS, + AccessTokenKit::GrantPermission(tokenID, "ohos.permission.MANUAL_ATM_SELF_USE", PERMISSION_USER_FIXED, true)); + EXPECT_EQ(PERMISSION_GRANTED, AccessTokenKit::VerifyAccessToken(tokenID, "ohos.permission.MANUAL_ATM_SELF_USE")); + + // old revoke function can't revoke MANUAL_SETTING + EXPECT_EQ(ERR_PERMISSION_NOT_EXIST, + AccessTokenKit::RevokePermission(tokenID, "ohos.permission.MANUAL_ATM_SELF_USE", PERMISSION_USER_FIXED, false)); + EXPECT_EQ(PERMISSION_GRANTED, AccessTokenKit::VerifyAccessToken(tokenID, "ohos.permission.MANUAL_ATM_SELF_USE")); + + // new revoke function can revoke MANUAL_SETTING + EXPECT_EQ(RET_SUCCESS, + AccessTokenKit::RevokePermission(tokenID, "ohos.permission.MANUAL_ATM_SELF_USE", PERMISSION_USER_FIXED, true)); + EXPECT_EQ(PERMISSION_DENIED, AccessTokenKit::VerifyAccessToken(tokenID, "ohos.permission.MANUAL_ATM_SELF_USE")); + + EXPECT_EQ(RET_SUCCESS, TestCommon::DeleteTestHapToken(tokenID)); +} } // namespace AccessToken } // namespace Security } // namespace OHOS \ No newline at end of file diff --git a/interfaces/innerkits/accesstoken/test/unittest/SaTest/dump_token_info_test.cpp b/interfaces/innerkits/accesstoken/test/unittest/SaTest/dump_token_info_test.cpp index 5f7ff2fbaf0a428940571cbf811db123431fc7d9..47e9c58bb3b0a1c61ba7c8abbc62acfec228fb7f 100644 --- a/interfaces/innerkits/accesstoken/test/unittest/SaTest/dump_token_info_test.cpp +++ b/interfaces/innerkits/accesstoken/test/unittest/SaTest/dump_token_info_test.cpp @@ -149,6 +149,16 @@ HWTEST_F(DumpTokenInfoTest, DumpPermDef001, TestSize.Level1) info.permissionName = "ohos.permission.INVALID"; AccessTokenKit::DumpTokenInfo(info, dumpInfo3); ASSERT_EQ(true, dumpInfo3.empty()); + + std::string dumpInfo4; + info.permissionName = "ohos.permission.MANAGE_HAP_TOKENID"; + AccessTokenKit::DumpTokenInfo(info, dumpInfo4); + ASSERT_EQ(false, dumpInfo4.empty()); + + std::string dumpInfo5; + info.permissionName = "ohos.permission.MANUAL_ATM_SELF_USE"; + AccessTokenKit::DumpTokenInfo(info, dumpInfo5); + ASSERT_EQ(false, dumpInfo5.empty()); } } // namespace AccessToken } // namespace Security diff --git a/interfaces/innerkits/accesstoken/test/unittest/common/test_common.cpp b/interfaces/innerkits/accesstoken/test/unittest/common/test_common.cpp index 9c22c054a534df174d6dbe458c25ef870ab6af60..28a74949d9e5f854f138d859a785cc962b57a90f 100644 --- a/interfaces/innerkits/accesstoken/test/unittest/common/test_common.cpp +++ b/interfaces/innerkits/accesstoken/test/unittest/common/test_common.cpp @@ -230,6 +230,25 @@ void TestCommon::TestPrepareKernelPermissionStatus(HapPolicyParams& policyParams policyParams.aclExtendedMap["ohos.permission.CAMERA"] = "789"; // filtered } +void TestCommon::TestPrepareManualPermissionStatus(HapPolicyParams& policyParams) +{ + PermissionStateFull permissionStatusBasic = { + .permissionName = "ohos.permission.test_basic", + .isGeneral = false, + .resDeviceID = {"local"}, + .grantStatus = {PERMISSION_DENIED}, + .grantFlags = {PERMISSION_DEFAULT_FLAG} + }; + + PermissionStateFull permissionStateFull001 = permissionStatusBasic; + permissionStateFull001.permissionName = "ohos.permission.MANUAL_ATM_SELF_USE"; + PermissionStateFull permissionStateFull002 = permissionStatusBasic; + permissionStateFull002.permissionName = "ohos.permission.MICROPHONE"; + PermissionStateFull permissionStateFull003 = permissionStatusBasic; + permissionStateFull003.permissionName = "ohos.permission.CAMERA"; + policyParams.permStateList = {permissionStateFull001, permissionStateFull002, permissionStateFull003}; +} + void TestCommon::SetTestEvironment(uint64_t shellTokenId) { std::lock_guard lock(g_lockSetToken); diff --git a/interfaces/innerkits/accesstoken/test/unittest/common/test_common.h b/interfaces/innerkits/accesstoken/test/unittest/common/test_common.h index 3ac03a171ea7a7dc2f36c4cddab1bbf5fc84b7f5..23e78b04fc9bf84d27fef2f135c387e76cb044f4 100644 --- a/interfaces/innerkits/accesstoken/test/unittest/common/test_common.h +++ b/interfaces/innerkits/accesstoken/test/unittest/common/test_common.h @@ -56,6 +56,7 @@ public: static void TestPreparePermStateList(HapPolicyParams &policy); static void TestPreparePermDefList(HapPolicyParams &policy); static void TestPrepareKernelPermissionStatus(HapPolicyParams& policyParams); + static void TestPrepareManualPermissionStatus(HapPolicyParams& policyParams); static HapPolicyParams GetTestPolicyParams(); static HapInfoParams GetInfoManagerTestInfoParms(); static HapInfoParams GetInfoManagerTestNormalInfoParms(); diff --git a/interfaces/kits/js/napi/accesstoken/include/napi_atmanager.h b/interfaces/kits/js/napi/accesstoken/include/napi_atmanager.h index 6e9172cf16ac79d64c533712ef88dff540b4674b..d1aad5a2dba420a60e30ef0361dc4f6ae5ce3bc6 100644 --- a/interfaces/kits/js/napi/accesstoken/include/napi_atmanager.h +++ b/interfaces/kits/js/napi/accesstoken/include/napi_atmanager.h @@ -125,6 +125,8 @@ private: static napi_value VerifyAccessTokenSync(napi_env env, napi_callback_info info); static napi_value GrantUserGrantedPermission(napi_env env, napi_callback_info info); static napi_value RevokeUserGrantedPermission(napi_env env, napi_callback_info info); + static napi_value GrantPermissionWithManual(napi_env env, napi_callback_info info); + static napi_value RevokePermissionWithManual(napi_env env, napi_callback_info info); static napi_value CheckAccessToken(napi_env env, napi_callback_info info); static napi_value GetPermissionFlags(napi_env env, napi_callback_info info); static napi_value GetVersion(napi_env env, napi_callback_info info); @@ -148,11 +150,15 @@ private: static void CheckAccessTokenExecute(napi_env env, void* data); static void CheckAccessTokenComplete(napi_env env, napi_status status, void* data); static bool ParseInputGrantOrRevokePermission(const napi_env env, const napi_callback_info info, - AtManagerAsyncContext& asyncContext); + AtManagerAsyncContext& asyncContext, bool isManual = false); static void GrantUserGrantedPermissionExecute(napi_env env, void *data); static void GrantUserGrantedPermissionComplete(napi_env env, napi_status status, void *data); static void RevokeUserGrantedPermissionExecute(napi_env env, void *data); static void RevokeUserGrantedPermissionComplete(napi_env env, napi_status status, void *data); + static void GrantPermissionWithManualExecute(napi_env env, void *data); + static void GrantPermissionWithManualComplete(napi_env env, napi_status status, void *data); + static void RevokePermissionWithManualExecute(napi_env env, void *data); + static void RevokePermissionWithManualComplete(napi_env env, napi_status status, void *data); static void GetVersionExecute(napi_env env, void *data); static void GetVersionComplete(napi_env env, napi_status status, void *data); static void GetPermissionFlagsExecute(napi_env env, void *data); diff --git a/interfaces/kits/js/napi/accesstoken/include/napi_request_permission_on_setting.h b/interfaces/kits/js/napi/accesstoken/include/napi_request_permission_on_setting.h index 8c0e8dbb1cfd83d3fc3cc4f2fe072c0ee3f08760..5b613c7305057a2a5dc2890d6e951f1e6f377692 100644 --- a/interfaces/kits/js/napi/accesstoken/include/napi_request_permission_on_setting.h +++ b/interfaces/kits/js/napi/accesstoken/include/napi_request_permission_on_setting.h @@ -108,6 +108,7 @@ private: std::shared_ptr& asyncContext); static void RequestPermissionOnSettingExecute(napi_env env, void* data); static void RequestPermissionOnSettingComplete(napi_env env, napi_status status, void* data); + static bool CheckManualSettingPerm(const std::vector& permissionList); }; } // namespace AccessToken } // namespace Security diff --git a/interfaces/kits/js/napi/common/include/napi_error.h b/interfaces/kits/js/napi/common/include/napi_error.h index 4d38988e0d42a89182ed29f2c8b7cb927db96ab9..2ec7e4cb611fa1718076ba0383c508bba16bce42 100644 --- a/interfaces/kits/js/napi/common/include/napi_error.h +++ b/interfaces/kits/js/napi/common/include/napi_error.h @@ -45,6 +45,7 @@ typedef enum { JS_ERROR_ALL_PERM_GRANTED = 12100011, JS_ERROR_PERM_REVOKE_BY_USER = 12100012, JS_ERROR_GLOBAL_SWITCH_IS_ALREADY_OPEN = 12100013, + JS_ERROR_PERMISSION_NOT_USER_GRANT_OR_MANUAL_SETTING = 12100014, } JsErrorCode; struct AtmResult { diff --git a/services/accesstokenmanager/idl/IAccessTokenManager.idl b/services/accesstokenmanager/idl/IAccessTokenManager.idl index 3d8317a4b3f3581db3e266c2027b6326cfab359b..45ddd8a27581c4cfb911624cc08c1f1f4225fac0 100644 --- a/services/accesstokenmanager/idl/IAccessTokenManager.idl +++ b/services/accesstokenmanager/idl/IAccessTokenManager.idl @@ -38,8 +38,8 @@ interface OHOS.Security.AccessToken.IAccessTokenManager{ [ipccode 2] void GetDefPermission([in] String permissionName, [out] PermissionDefParcel permissionDefResult); [ipccode 3] void GetReqPermissions([in] unsigned int tokenID, [out] List reqPermList, [in] boolean isSystemGrant); [ipccode 4] void GetPermissionFlag([in] unsigned int tokenID, [in] String permissionName, [out] unsigned int flag); - [ipccode 5] void GrantPermission([in] unsigned int tokenID, [in] String permissionName, [in] unsigned int flag); - [ipccode 6] void RevokePermission([in] unsigned int tokenID, [in] String permissionName, [in] unsigned int flag); + [ipccode 5] void GrantPermission([in] unsigned int tokenID, [in] String permissionName, [in] unsigned int flag, [in] boolean withManual); + [ipccode 6] void RevokePermission([in] unsigned int tokenID, [in] String permissionName, [in] unsigned int flag, [in] boolean withManual); [ipccode 7] void ClearUserGrantedPermissionState([in] unsigned int tokenID); [ipccode 8] void AllocHapToken([in] HapInfoParcel hapInfo, [in] HapPolicyParcel policyParcel, [out] unsigned long fullTokenId); [ipccode 9] void DeleteToken([in] unsigned int tokenID); diff --git a/services/accesstokenmanager/main/cpp/include/permission/permission_manager.h b/services/accesstokenmanager/main/cpp/include/permission/permission_manager.h index 8c390755dfc0b885ecbbfc690fc6b4016fed27c4..8baab4afafc116beb15f7e6820e66269baae008f 100644 --- a/services/accesstokenmanager/main/cpp/include/permission/permission_manager.h +++ b/services/accesstokenmanager/main/cpp/include/permission/permission_manager.h @@ -79,8 +79,10 @@ public: AccessTokenID tokenID, const std::vector& permissionList, int32_t status, uint32_t flag); int32_t UpdatePermission(AccessTokenID tokenID, const std::string& permissionName, bool isGranted, uint32_t flag, bool needKill); - int32_t GrantPermission(AccessTokenID tokenID, const std::string& permissionName, uint32_t flag); - int32_t RevokePermission(AccessTokenID tokenID, const std::string& permissionName, uint32_t flag); + int32_t GrantPermission(AccessTokenID tokenID, const std::string& permissionName, uint32_t flag, + bool withManual = false); + int32_t RevokePermission(AccessTokenID tokenID, const std::string& permissionName, uint32_t flag, + bool withManual = false); int32_t GrantPermissionForSpecifiedTime( AccessTokenID tokenID, const std::string& permissionName, uint32_t onceTime); int32_t SetPermissionStatusWithPolicy( diff --git a/services/accesstokenmanager/main/cpp/include/service/accesstoken_manager_service.h b/services/accesstokenmanager/main/cpp/include/service/accesstoken_manager_service.h index a9daab95e9730ba4b50dde6d45fb7777df530d5d..280fd7cab796852ff272e1b7aad5ea402e220ca6 100644 --- a/services/accesstokenmanager/main/cpp/include/service/accesstoken_manager_service.h +++ b/services/accesstokenmanager/main/cpp/include/service/accesstoken_manager_service.h @@ -72,8 +72,10 @@ public: int32_t GetPermissionRequestToggleStatus(const std::string& permissionName, uint32_t& status, int32_t userID) override; int32_t RequestAppPermOnSetting(AccessTokenID tokenID) override; - int GrantPermission(AccessTokenID tokenID, const std::string& permissionName, uint32_t flag) override; - int RevokePermission(AccessTokenID tokenID, const std::string& permissionName, uint32_t flag) override; + int GrantPermission( + AccessTokenID tokenID, const std::string& permissionName, uint32_t flag, bool withManual) override; + int RevokePermission( + AccessTokenID tokenID, const std::string& permissionName, uint32_t flag, bool withManual) override; int GrantPermissionForSpecifiedTime( AccessTokenID tokenID, const std::string& permissionName, uint32_t onceTime) override; int ClearUserGrantedPermissionState(AccessTokenID tokenID) override; diff --git a/services/accesstokenmanager/main/cpp/src/permission/permission_manager.cpp b/services/accesstokenmanager/main/cpp/src/permission/permission_manager.cpp index 1e53a593766040ae4ba75c42f52bf36b378a3d8f..f8f069374c4ff836d5532bd0c5bb032126bbf5ff 100644 --- a/services/accesstokenmanager/main/cpp/src/permission/permission_manager.cpp +++ b/services/accesstokenmanager/main/cpp/src/permission/permission_manager.cpp @@ -142,7 +142,6 @@ int PermissionManager::GetReqPermissions( LOGE(ATM_DOMAIN, ATM_TAG, "Token %{public}u is invalid.", tokenID); return AccessTokenError::ERR_TOKENID_NOT_EXIST; } - GrantMode mode = isSystemGrant ? SYSTEM_GRANT : USER_GRANT; std::vector tmpList; int32_t ret = infoPtr->GetPermissionStateList(tmpList); if (ret != RET_SUCCESS) { @@ -155,7 +154,8 @@ int PermissionManager::GetReqPermissions( continue; } - if (briefDef.grantMode == mode) { + if ((isSystemGrant && briefDef.grantMode == SYSTEM_GRANT) || + (!isSystemGrant && briefDef.grantMode != SYSTEM_GRANT)) { reqPermList.emplace_back(perm); } } @@ -213,6 +213,12 @@ static bool IsPermissionRestrictedByRules(const std::string& permission) bool PermissionManager::HandlePermissionDeniedCase(uint32_t goalGrantFlag, PermissionListState& permState) { + PermissionBriefDef briefDef; + if (GetPermissionBriefDef(permState.permissionName, briefDef) && briefDef.grantMode == MANUAL_SETTING) { + permState.state = SETTING_OPER; + permState.errorReason = MANUAL_SETTING_PERM; + return true; + } if ((goalGrantFlag & PERMISSION_FIXED_BY_ADMIN_POLICY) != 0) { permState.state = FORBIDDEN_OPER; permState.errorReason = FIXED_BY_POLICY; @@ -339,7 +345,7 @@ int32_t PermissionManager::RequestAppPermOnSetting(const HapTokenInfo& hapInfo, void PermissionManager::ParamUpdate(const std::string& permissionName, uint32_t flag, bool filtered) { Utils::UniqueWriteGuard infoGuard(this->permParamSetLock_); - if (filtered || (IsUserGrantPermission(permissionName) && + if (filtered || (IsUserSettingPermission(permissionName) && ((flag != PERMISSION_PRE_AUTHORIZED_CANCELABLE) && (flag != PERMISSION_SYSTEM_FIXED)))) { paramValue_++; LOGD(ATM_DOMAIN, ATM_TAG, @@ -728,17 +734,35 @@ int32_t PermissionManager::CheckAndUpdateMultiPermissionStatus( return RET_SUCCESS; } -int32_t PermissionManager::GrantPermission(AccessTokenID tokenID, const std::string& permissionName, uint32_t flag) +int32_t PermissionManager::GrantPermission( + AccessTokenID tokenID, const std::string& permissionName, uint32_t flag, bool withManual) { LOGI(ATM_DOMAIN, ATM_TAG, "TokenID: %{public}u, permissionName: %{public}s, flag: %{public}d", tokenID, permissionName.c_str(), flag); + + if (!withManual) { + PermissionBriefDef briefDef; + if (GetPermissionBriefDef(permissionName, briefDef) && briefDef.grantMode == MANUAL_SETTING) { + LOGE(ATM_DOMAIN, ATM_TAG, "MANUAL_SETTING %{public}s can't be grant.", permissionName.c_str()); + return AccessTokenError::ERR_PERMISSION_NOT_EXIST; + } + } return CheckAndUpdatePermissionInner(tokenID, permissionName, true, flag); } -int32_t PermissionManager::RevokePermission(AccessTokenID tokenID, const std::string& permissionName, uint32_t flag) +int32_t PermissionManager::RevokePermission( + AccessTokenID tokenID, const std::string& permissionName, uint32_t flag, bool withManual) { LOGI(ATM_DOMAIN, ATM_TAG, "TokenID: %{public}u, permissionName: %{public}s, flag: %{public}d", tokenID, permissionName.c_str(), flag); + + if (!withManual) { + PermissionBriefDef briefDef; + if (GetPermissionBriefDef(permissionName, briefDef) && briefDef.grantMode == MANUAL_SETTING) { + LOGE(ATM_DOMAIN, ATM_TAG, "MANUAL_SETTING %{public}s can't be revoke.", permissionName.c_str()); + return AccessTokenError::ERR_PERMISSION_NOT_EXIST; + } + } return CheckAndUpdatePermissionInner(tokenID, permissionName, false, flag); } diff --git a/services/accesstokenmanager/main/cpp/src/permission/permission_validator.cpp b/services/accesstokenmanager/main/cpp/src/permission/permission_validator.cpp index 814f474da24f164a1934c8fb4fa2d125293a719e..cfc460c39e186b35e27984379107aed0a8ec4a6f 100644 --- a/services/accesstokenmanager/main/cpp/src/permission/permission_validator.cpp +++ b/services/accesstokenmanager/main/cpp/src/permission/permission_validator.cpp @@ -27,7 +27,8 @@ namespace AccessToken { bool PermissionValidator::IsGrantModeValid(int grantMode) { - return grantMode == GrantMode::SYSTEM_GRANT || grantMode == GrantMode::USER_GRANT; + return grantMode == GrantMode::SYSTEM_GRANT || grantMode == GrantMode::USER_GRANT || + grantMode == GrantMode::MANUAL_SETTING; } bool PermissionValidator::IsGrantStatusValid(int grantStatus) diff --git a/services/accesstokenmanager/main/cpp/src/service/accesstoken_manager_service.cpp b/services/accesstokenmanager/main/cpp/src/service/accesstoken_manager_service.cpp index 1bd833360c16f0240c65fc80382108166fb223a2..ee4161befeb464d9f0b1619a3927b0dbb945e14b 100644 --- a/services/accesstokenmanager/main/cpp/src/service/accesstoken_manager_service.cpp +++ b/services/accesstokenmanager/main/cpp/src/service/accesstoken_manager_service.cpp @@ -487,7 +487,8 @@ int32_t AccessTokenManagerService::RequestAppPermOnSetting(AccessTokenID tokenID grantBundleName_, applicationSettingAbilityName_); } -int AccessTokenManagerService::GrantPermission(AccessTokenID tokenID, const std::string& permissionName, uint32_t flag) +int AccessTokenManagerService::GrantPermission( + AccessTokenID tokenID, const std::string& permissionName, uint32_t flag, bool withManual) { AccessTokenID callingTokenID = IPCSkeleton::GetCallingTokenID(); if ((this->GetTokenType(callingTokenID) == TOKEN_HAP) && (!IsSystemAppCalling())) { @@ -503,11 +504,12 @@ int AccessTokenManagerService::GrantPermission(AccessTokenID tokenID, const std: return AccessTokenError::ERR_PERMISSION_DENIED; } - int32_t ret = PermissionManager::GetInstance().GrantPermission(tokenID, permissionName, flag); + int32_t ret = PermissionManager::GetInstance().GrantPermission(tokenID, permissionName, flag, withManual); return ret; } -int AccessTokenManagerService::RevokePermission(AccessTokenID tokenID, const std::string& permissionName, uint32_t flag) +int AccessTokenManagerService::RevokePermission( + AccessTokenID tokenID, const std::string& permissionName, uint32_t flag, bool withManual) { AccessTokenID callingTokenID = IPCSkeleton::GetCallingTokenID(); if ((this->GetTokenType(callingTokenID) == TOKEN_HAP) && (!IsSystemAppCalling())) { @@ -522,7 +524,8 @@ int AccessTokenManagerService::RevokePermission(AccessTokenID tokenID, const std LOGE(ATM_DOMAIN, ATM_TAG, "Permission denied(tokenID=%{public}d)", callingTokenID); return AccessTokenError::ERR_PERMISSION_DENIED; } - return PermissionManager::GetInstance().RevokePermission(tokenID, permissionName, flag); + + return PermissionManager::GetInstance().RevokePermission(tokenID, permissionName, flag, withManual); } int AccessTokenManagerService::GrantPermissionForSpecifiedTime( @@ -1500,7 +1503,7 @@ void AccessTokenManagerService::UpdateUndefinedInfoCache(const std::vector validValueList; validValueList.emplace_back(value1); validValueList.emplace_back(value2); + validValueList.emplace_back(value3); PermissionDataBrief::GetInstance().DeleteBriefPermDataByTokenId(RANDOM_TOKENID); std::shared_ptr atManagerService_ = diff --git a/services/accesstokenmanager/test/unittest/accesstoken_info_manager_test.cpp b/services/accesstokenmanager/test/unittest/accesstoken_info_manager_test.cpp index 5522bb9be66463e4e771d959bf452c70abbb603e..c095ceba60802d6d79d5b7c5b2ebb1c52d5589cf 100644 --- a/services/accesstokenmanager/test/unittest/accesstoken_info_manager_test.cpp +++ b/services/accesstokenmanager/test/unittest/accesstoken_info_manager_test.cpp @@ -49,6 +49,7 @@ static constexpr int USER_ID = 100; static constexpr int INST_INDEX = 0; static constexpr int32_t MAX_EXTENDED_MAP_SIZE = 512; static constexpr int32_t MAX_VALUE_LENGTH = 1024; +static constexpr int32_t INVALID_GRANT_MODE = 3; static AccessTokenID g_selfTokenId = 0; static PermissionDef g_infoManagerTestPermDef1 = { .permissionName = "open the door", @@ -1736,7 +1737,7 @@ HWTEST_F(AccessTokenInfoManagerTest, IsPermissionDefValid001, TestSize.Level0) PermissionDef permDef = { .permissionName = "ohos.permission.TEST", .bundleName = "com.ohos.test", - .grantMode = static_cast(2), + .grantMode = static_cast(INVALID_GRANT_MODE), .availableLevel = ATokenAplEnum::APL_NORMAL, .provisionEnable = false, .distributedSceneEnable = false, diff --git a/services/accesstokenmanager/test/unittest/permission_manager_test.cpp b/services/accesstokenmanager/test/unittest/permission_manager_test.cpp index 91e4eea8056febfe72a199cc100689e23e6f879e..6c988e280f31d15a72ae4a475f3d150cf58c5674 100644 --- a/services/accesstokenmanager/test/unittest/permission_manager_test.cpp +++ b/services/accesstokenmanager/test/unittest/permission_manager_test.cpp @@ -1962,6 +1962,55 @@ HWTEST_F(PermissionManagerTest, ContinuousTaskCallbackCall001, TestSize.Level1) ASSERT_EQ(RET_SUCCESS, BackgroundTaskManagerAccessClient::GetInstance().GetContinuousTaskApps(list)); } #endif + +/** + * @tc.name: HandlePermissionDeniedCaseWithInvalidAndManualPermTest001 + * @tc.desc: HandlePermissionDeniedCase invalid and manual permission test. + * @tc.type: FUNC + * @tc.require: + */ +HWTEST_F(PermissionManagerTest, HandlePermissionDeniedCaseWithInvalidAndManualPermTest001, TestSize.Level0) +{ + accessTokenService_->state_ = ServiceRunningState::STATE_RUNNING; + accessTokenService_->Initialize(); + + PermissionListState state; + state.permissionName = "ohos.permission.TEST123"; + state.state = DYNAMIC_OPER; + state.errorReason = REQ_SUCCESS; + + EXPECT_EQ(true, + PermissionManager::GetInstance().HandlePermissionDeniedCase(PERMISSION_ALLOW_THIS_TIME, state)); + + state.permissionName = "ohos.permission.MANUAL_ATM_SELF_USE"; + state.state = DYNAMIC_OPER; + state.errorReason = REQ_SUCCESS; + EXPECT_EQ(true, + PermissionManager::GetInstance().HandlePermissionDeniedCase(PERMISSION_USER_FIXED, state)); +} + +/** + * @tc.name: UpdatePermissionWithInvalidPermTest001 + * @tc.desc: GrantPermission & RevokePermission with withManual & invalid permission test. + * @tc.type: FUNC + * @tc.require: + */ +HWTEST_F(PermissionManagerTest, UpdatePermissionWithInvalidPermTest001, TestSize.Level0) +{ + accessTokenService_->state_ = ServiceRunningState::STATE_RUNNING; + accessTokenService_->Initialize(); + AccessTokenID tokenID = CreateTempHapTokenInfo(); + + EXPECT_NE(RET_SUCCESS, PermissionManager::GetInstance().GrantPermission( + tokenID, "ohos.permission.TEST123", PERMISSION_USER_FIXED, true)); + + EXPECT_NE(RET_SUCCESS, PermissionManager::GetInstance().RevokePermission( + tokenID, "ohos.permission.TEST123", PERMISSION_USER_FIXED, true)); + + PermissionManager::GetInstance().ParamUpdate("ohos.permission.TEST123", 0, false); + + EXPECT_EQ(false, IsUserSettingPermission("ohos.permission.TEST123")); +} } // namespace AccessToken } // namespace Security } // namespace OHOS diff --git a/test/fuzztest/services/accesstoken/grantpermissionstub_fuzzer/grantpermissionstub_fuzzer.cpp b/test/fuzztest/services/accesstoken/grantpermissionstub_fuzzer/grantpermissionstub_fuzzer.cpp index 10a54d423680595077d1af22a8eb94672f2a2f71..b3666475f2ba469b59622d99d58214897530de4c 100644 --- a/test/fuzztest/services/accesstoken/grantpermissionstub_fuzzer/grantpermissionstub_fuzzer.cpp +++ b/test/fuzztest/services/accesstoken/grantpermissionstub_fuzzer/grantpermissionstub_fuzzer.cpp @@ -61,9 +61,12 @@ namespace OHOS { std::string permissionName = provider.ConsumeRandomLengthString(); uint32_t flag = provider.ConsumeIntegralInRange( 0, static_cast(PermissionFlag::PERMISSION_ALLOW_THIS_TIME)); + bool withManual = static_cast(provider.ConsumeIntegralInRange(0, 1)); + MessageParcel datas; datas.WriteInterfaceToken(IAccessTokenManager::GetDescriptor()); - if (!datas.WriteUint32(tokenId) || !datas.WriteString(permissionName) || !datas.WriteInt32(flag)) { + if (!datas.WriteUint32(tokenId) || !datas.WriteString(permissionName) || + !datas.WriteInt32(flag) || !datas.WriteBool(withManual)) { return false; } diff --git a/test/fuzztest/services/accesstoken/revokepermissionstub_fuzzer/revokepermissionstub_fuzzer.cpp b/test/fuzztest/services/accesstoken/revokepermissionstub_fuzzer/revokepermissionstub_fuzzer.cpp index c344df43976955614969190a97a21cb790e462d5..88cf34e9fe6f1af9c461cd873d9ff66c327c5858 100644 --- a/test/fuzztest/services/accesstoken/revokepermissionstub_fuzzer/revokepermissionstub_fuzzer.cpp +++ b/test/fuzztest/services/accesstoken/revokepermissionstub_fuzzer/revokepermissionstub_fuzzer.cpp @@ -43,11 +43,12 @@ namespace OHOS { std::string testName = provider.ConsumeRandomLengthString(); uint32_t flag = static_cast(provider.ConsumeIntegralInRange( 0, static_cast(PermissionFlag::PERMISSION_ALLOW_THIS_TIME))); + bool withManual = static_cast(provider.ConsumeIntegralInRange(0, 1)); MessageParcel datas; datas.WriteInterfaceToken(IAccessTokenManager::GetDescriptor()); if (!datas.WriteUint32(tokenId) || !datas.WriteString(testName) || - !datas.WriteInt32(flag)) { + !datas.WriteInt32(flag) || !datas.WriteBool(withManual)) { return false; } uint32_t code = static_cast(