已合并
修改controlled存储授权记录逻辑 #481
LinShen创建于 7 天前
修改controlled存储授权记录逻辑 #481
已合并
共 18 个文件变更+494-37
| @@ -350,6 +350,15 @@ pub enum GrantType { | |||
| 350 | /// Remote grant. | 350 | /// Remote grant. |
| 351 | RemoteGrant = 0x02, | 351 | RemoteGrant = 0x02, |
| 352 | } | 352 | } |
| 353 | + | ||
| 354 | +/// Remote grant status enum. | ||
| 355 | + | ||
| 356 | +pub enum RemoteGrantStatus { | ||
| 357 | + /// Enable remote grant. | ||
| 358 | + Enable = 1, | ||
| 359 | + /// Disable remote grant. | ||
| 360 | + Disable = 2, | ||
| 361 | +} | ||
| 353 | // ============================================================================ | 362 | // ============================================================================ |
| 354 | // Basic Structures | 363 | // Basic Structures |
| 355 | // ============================================================================ | 364 | // ============================================================================ |
| @@ -251,6 +251,40 @@ int32_t SafAgentFence::VerifyControllerDevicePackage( | |||
| 251 | return resultCode; | 251 | return resultCode; |
| 252 | } | 252 | } |
| 253 | 253 | ||
| 254 | +int32_t SafAgentFence::GetRemoteGrantStatus(int32_t& remoteGrantStatus) | ||
| 255 | +{ | ||
| 256 | + LOGI("SafAgentFence::GetRemoteGrantStatus enter"); | ||
| 257 | + | ||
| 258 | + auto proxy = GetProxy(g_mutex); | ||
| 259 | + IF_TRUE_LOGE_RETURN_ERR(proxy == nullptr, SAF_ERR_SERVICE_UNAVAILABLE, "load sa fail."); | ||
| 260 | + | ||
| 261 | + int32_t resultCode = SAF_SUCCESS; | ||
| 262 | + int32_t ret = HandleIpcError(proxy, [&]() { | ||
| 263 | + return proxy->GetRemoteGrantStatus(remoteGrantStatus, resultCode); | ||
| 264 | + }); | ||
| 265 | + IF_ERROR_LOGE_RETURN_ERR(ret, SAF_ERR_IPC_PROXY_FAIL, "IPC call failed, ret=%{public}d", ret); | ||
| 266 | + | ||
| 267 | + LOGI("SafAgentFence::GetRemoteGrantStatus finished, resultCode = 0x%{public}x", resultCode); | ||
| 268 | + return resultCode; | ||
| 269 | +} | ||
| 270 | + | ||
| 271 | +int32_t SafAgentFence::UpdateRemoteGrantStatus(int32_t remoteGrantStatus) | ||
| 272 | +{ | ||
| 273 | + LOGI("SafAgentFence::UpdateRemoteGrantStatus enter, remoteGrantStatus=%{public}d", remoteGrantStatus); | ||
| 274 | + | ||
| 275 | + auto proxy = GetProxy(g_mutex); | ||
| 276 | + IF_TRUE_LOGE_RETURN_ERR(proxy == nullptr, SAF_ERR_SERVICE_UNAVAILABLE, "load sa fail."); | ||
| 277 | + | ||
| 278 | + int32_t resultCode = SAF_SUCCESS; | ||
| 279 | + int32_t ret = HandleIpcError(proxy, [&]() { | ||
| 280 | + return proxy->UpdateRemoteGrantStatus(remoteGrantStatus, resultCode); | ||
| 281 | + }); | ||
| 282 | + IF_ERROR_LOGE_RETURN_ERR(ret, SAF_ERR_IPC_PROXY_FAIL, "IPC call failed, ret=%{public}d", ret); | ||
| 283 | + | ||
| 284 | + LOGI("SafAgentFence::UpdateRemoteGrantStatus finished, resultCode = 0x%{public}x", resultCode); | ||
| 285 | + return resultCode; | ||
| 286 | +} | ||
| 287 | + | ||
| 254 | int32_t SafAgentFence::VerifyTicket( | 288 | int32_t SafAgentFence::VerifyTicket( |
| 255 | int32_t osAccountId, | 289 | int32_t osAccountId, |
| 256 | const std::string &callerId, | 290 | const std::string &callerId, |
| @@ -105,6 +105,26 @@ interface OHOS.Security.SAF.ISecureAccessFence { | |||
| 105 | [out] int resultCode | 105 | [out] int resultCode |
| 106 | ); | 106 | ); |
| 107 | 107 | ||
| 108 | + /** | ||
| 109 | + * @brief Get remote grant status. | ||
| 110 | + * @param remoteGrantStatus Output remote grant status. | ||
| 111 | + * @param resultCode Error code output (0 for success). | ||
| 112 | + */ | ||
| 113 | + [ipccode 8] void GetRemoteGrantStatus( | ||
| 114 | + [out] int remoteGrantStatus, | ||
| 115 | + [out] int resultCode | ||
| 116 | + ); | ||
| 117 | + | ||
| 118 | + /** | ||
| 119 | + * @brief Update remote grant status. | ||
| 120 | + * @param remoteGrantStatus Remote grant status to set. | ||
| 121 | + * @param resultCode Error code output (0 for success). | ||
| 122 | + */ | ||
| 123 | + [ipccode 9] void UpdateRemoteGrantStatus( | ||
| 124 | + [in] int remoteGrantStatus, | ||
| 125 | + [out] int resultCode | ||
| 126 | + ); | ||
| 127 | + | ||
| 108 | /** | 128 | /** |
| 109 | * @brief Batch query command permissions. | 129 | * @brief Batch query command permissions. |
| 110 | * @param cmds List of commands to query (input parameter). | 130 | * @param cmds List of commands to query (input parameter). |
| @@ -176,3 +176,13 @@ struct RemoteUserAuthResults { | |||
| 176 | /** Permission query associated with the authentication. */ | 176 | /** Permission query associated with the authentication. */ |
| 177 | PermissionQuery permissionQuery; | 177 | PermissionQuery permissionQuery; |
| 178 | }; | 178 | }; |
| 179 | + | ||
| 180 | +/** | ||
| 181 | + * @brief Remote grant status enum. | ||
| 182 | + */ | ||
| 183 | +enum RemoteGrantStatus { | ||
| 184 | + /** Enable remote grant. */ | ||
| 185 | + ENABLE = 1, | ||
| 186 | + /** Disable remote grant. */ | ||
| 187 | + DISABLE = 2 | ||
| 188 | +}; | ||
| @@ -63,7 +63,11 @@ pub const CMD_VERIFY_CONTROLLED_DEVICE_PACKAGE: u32 = 5; | |||
| 63 | pub const CMD_GENERATE_CONTROLLER_DEVICE_PACKAGE: u32 = 6; | 63 | pub const CMD_GENERATE_CONTROLLER_DEVICE_PACKAGE: u32 = 6; |
| 64 | /// IPC code for VerifyControllerDevicePackage. | 64 | /// IPC code for VerifyControllerDevicePackage. |
| 65 | pub const CMD_VERIFY_CONTROLLER_DEVICE_PACKAGE: u32 = 7; | 65 | pub const CMD_VERIFY_CONTROLLER_DEVICE_PACKAGE: u32 = 7; |
| 66 | - | 66 | +/// IPC code for GetRemoteGrantStatus. |
| 67 | +pub const CMD_GET_REMOTE_GRANT_STATUS: u32 = 8; | ||
| 68 | +/// IPC code for UpdateRemoteGrantStatus. | ||
| 69 | +pub const CMD_UPDATE_REMOTE_GRANT_STATUS: u32 = 9; | ||
| 70 | + | ||
| 67 | const MAX_MAP_CAPACITY: u32 = 64; | 71 | const MAX_MAP_CAPACITY: u32 = 64; |
| 68 | pub(crate) const MAX_VEC_CAPACITY: u32 = 0x10000; | 72 | pub(crate) const MAX_VEC_CAPACITY: u32 = 0x10000; |
| 69 | pub(crate) const MAX_TICKET_CAPACITY: u32 = 99; | 73 | pub(crate) const MAX_TICKET_CAPACITY: u32 = 99; |
| @@ -79,6 +79,16 @@ public: | |||
| 79 | RemoteInfo remoteInfo {}; | 79 | RemoteInfo remoteInfo {}; |
| 80 | std::vector<bool> verifyRes {}; | 80 | std::vector<bool> verifyRes {}; |
| 81 | }; | 81 | }; |
| 82 | + | ||
| 83 | +class GetRemoteGrantStatusContext : public AgentFenceAsyncContext { | ||
| 84 | +public: | ||
| 85 | + int32_t remoteGrantStatus {}; | ||
| 86 | +}; | ||
| 87 | + | ||
| 88 | +class UpdateRemoteGrantStatusContext : public AgentFenceAsyncContext { | ||
| 89 | +public: | ||
| 90 | + int32_t remoteGrantStatus {}; | ||
| 91 | +}; | ||
| 82 | } // namespace SAF | 92 | } // namespace SAF |
| 83 | } // namespace Security | 93 | } // namespace Security |
| 84 | } // namespace OHOS | 94 | } // namespace OHOS |
| @@ -287,6 +287,71 @@ napi_value NapiVerifyControllerDevicePackage(const napi_env env, napi_callback_i | |||
| 287 | return CreateAsyncWork(env, info, std::move(asyncContext), __func__); | 287 | return CreateAsyncWork(env, info, std::move(asyncContext), __func__); |
| 288 | } | 288 | } |
| 289 | 289 | ||
| 290 | +napi_value NapiGetRemoteGrantStatus(const napi_env env, napi_callback_info info) | ||
| 291 | +{ | ||
| 292 | + auto asyncContext = std::unique_ptr<GetRemoteGrantStatusContext>( | ||
| 293 | + new (std::nothrow) GetRemoteGrantStatusContext()); | ||
| 294 | + NAPI_THROW(env, asyncContext == nullptr, COMMON_INTERNAL_ERROR, | ||
| 295 | + "Failed to create GetRemoteGrantStatusContext"); | ||
| 296 | + | ||
| 297 | + asyncContext->parse = [](napi_env env, napi_callback_info info, AgentFenceAsyncContext *context) | ||
| 298 | + -> napi_status { | ||
| 299 | + return napi_ok; | ||
| 300 | + }; | ||
| 301 | + | ||
| 302 | + asyncContext->execute = [](napi_env env, void* data) { | ||
| 303 | + GetRemoteGrantStatusContext *asyncContext = | ||
| 304 | + static_cast<GetRemoteGrantStatusContext *>(data); | ||
| 305 | + asyncContext->result = SafAgentFence::GetRemoteGrantStatus(asyncContext->remoteGrantStatus); | ||
| 306 | + }; | ||
| 307 | + | ||
| 308 | + asyncContext->resolve = [](napi_env env, AgentFenceAsyncContext *context) -> napi_value { | ||
| 309 | + GetRemoteGrantStatusContext *asyncContext = | ||
| 310 | + static_cast<GetRemoteGrantStatusContext *>(context); | ||
| 311 | + napi_value jsResult = nullptr; | ||
| 312 | + NAPI_CALL(env, napi_create_uint32(env, static_cast<uint32_t>(asyncContext->remoteGrantStatus), | ||
| 313 | + &jsResult)); | ||
| 314 | + return jsResult; | ||
| 315 | + }; | ||
| 316 | + | ||
| 317 | + return CreateAsyncWork(env, info, std::move(asyncContext), __func__); | ||
| 318 | +} | ||
| 319 | + | ||
| 320 | +napi_value NapiUpdateRemoteGrantStatus(const napi_env env, napi_callback_info info) | ||
| 321 | +{ | ||
| 322 | + auto asyncContext = std::unique_ptr<UpdateRemoteGrantStatusContext>( | ||
| 323 | + new (std::nothrow) UpdateRemoteGrantStatusContext()); | ||
| 324 | + NAPI_THROW(env, asyncContext == nullptr, COMMON_INTERNAL_ERROR, | ||
| 325 | + "Failed to create UpdateRemoteGrantStatusContext"); | ||
| 326 | + | ||
| 327 | + asyncContext->parse = [](napi_env env, napi_callback_info info, AgentFenceAsyncContext *context) | ||
| 328 | + -> napi_status { | ||
| 329 | + UpdateRemoteGrantStatusContext *asyncContext = | ||
| 330 | + static_cast<UpdateRemoteGrantStatusContext *>(context); | ||
| 331 | + size_t argc = 1; | ||
| 332 | + napi_value argv[1] = { nullptr }; | ||
| 333 | + NAPI_CALL_RETURN_ERR(env, napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr)); | ||
| 334 | + NAPI_THROW_RETURN_ERR(env, argc < 1, GENERAL_PARAMETER_ERROR, "Invalid number of arguments"); | ||
| 335 | + NAPI_CALL_RETURN_ERR(env, napi_get_value_uint32(env, argv[0], | ||
| 336 | + reinterpret_cast<uint32_t*>(&asyncContext->remoteGrantStatus))); | ||
| 337 | + return napi_ok; | ||
| 338 | + }; | ||
| 339 | + | ||
| 340 | + asyncContext->execute = [](napi_env env, void* data) { | ||
| 341 | + UpdateRemoteGrantStatusContext *asyncContext = | ||
| 342 | + static_cast<UpdateRemoteGrantStatusContext *>(data); | ||
| 343 | + asyncContext->result = SafAgentFence::UpdateRemoteGrantStatus(asyncContext->remoteGrantStatus); | ||
| 344 | + }; | ||
| 345 | + | ||
| 346 | + asyncContext->resolve = [](napi_env env, AgentFenceAsyncContext *context) -> napi_value { | ||
| 347 | + napi_value jsResult = nullptr; | ||
| 348 | + NAPI_CALL(env, napi_get_undefined(env, &jsResult)); | ||
| 349 | + return jsResult; | ||
| 350 | + }; | ||
| 351 | + | ||
| 352 | + return CreateAsyncWork(env, info, std::move(asyncContext), __func__); | ||
| 353 | +} | ||
| 354 | + | ||
| 290 | napi_value DeclareOperationType(const napi_env env) | 355 | napi_value DeclareOperationType(const napi_env env) |
| 291 | { | 356 | { |
| 292 | napi_value status = nullptr; | 357 | napi_value status = nullptr; |
| @@ -317,6 +382,15 @@ napi_value DeclareRole(const napi_env env) | |||
| 317 | return role; | 382 | return role; |
| 318 | } | 383 | } |
| 319 | 384 | ||
| 385 | +napi_value DeclareRemoteGrantStatus(const napi_env env) | ||
| 386 | +{ | ||
| 387 | + napi_value status = nullptr; | ||
| 388 | + NAPI_CALL(env, napi_create_object(env, &status)); | ||
| 389 | + AddUint32Property(env, status, "ENABLE", static_cast<uint32_t>(RemoteGrantStatus::ENABLE)); | ||
| 390 | + AddUint32Property(env, status, "DISABLE", static_cast<uint32_t>(RemoteGrantStatus::DISABLE)); | ||
| 391 | + return status; | ||
| 392 | +} | ||
| 393 | + | ||
| 320 | napi_value Register(const napi_env env, napi_value exports) | 394 | napi_value Register(const napi_env env, napi_value exports) |
| 321 | { | 395 | { |
| 322 | napi_property_descriptor desc[] = { | 396 | napi_property_descriptor desc[] = { |
| @@ -326,10 +400,13 @@ napi_value Register(const napi_env env, napi_value exports) | |||
| 326 | DECLARE_NAPI_FUNCTION("verifyControlledDevicePackage", NapiVerifyControlledDevicePackage), | 400 | DECLARE_NAPI_FUNCTION("verifyControlledDevicePackage", NapiVerifyControlledDevicePackage), |
| 327 | DECLARE_NAPI_FUNCTION("generateControllerDevicePackage", NapiGenerateControllerDevicePackage), | 401 | DECLARE_NAPI_FUNCTION("generateControllerDevicePackage", NapiGenerateControllerDevicePackage), |
| 328 | DECLARE_NAPI_FUNCTION("verifyControllerDevicePackage", NapiVerifyControllerDevicePackage), | 402 | DECLARE_NAPI_FUNCTION("verifyControllerDevicePackage", NapiVerifyControllerDevicePackage), |
| 403 | + DECLARE_NAPI_FUNCTION("getRemoteGrantStatus", NapiGetRemoteGrantStatus), | ||
| 404 | + DECLARE_NAPI_FUNCTION("updateRemoteGrantStatus", NapiUpdateRemoteGrantStatus), | ||
| 329 | 405 | ||
| 330 | DECLARE_NAPI_PROPERTY("OperationType", DeclareOperationType(env)), | 406 | DECLARE_NAPI_PROPERTY("OperationType", DeclareOperationType(env)), |
| 331 | DECLARE_NAPI_PROPERTY("AuthStatus", DeclareAuthStatus(env)), | 407 | DECLARE_NAPI_PROPERTY("AuthStatus", DeclareAuthStatus(env)), |
| 332 | DECLARE_NAPI_PROPERTY("Role", DeclareRole(env)), | 408 | DECLARE_NAPI_PROPERTY("Role", DeclareRole(env)), |
| 409 | + DECLARE_NAPI_PROPERTY("RemoteGrantStatus", DeclareRemoteGrantStatus(env)), | ||
| 333 | }; | 410 | }; |
| 334 | 411 | ||
| 335 | NAPI_CALL(env, napi_define_properties(env, exports, sizeof(desc) / sizeof(desc[0]), desc)); | 412 | NAPI_CALL(env, napi_define_properties(env, exports, sizeof(desc) / sizeof(desc[0]), desc)); |
| @@ -152,6 +152,22 @@ public: | |||
| 152 | const std::vector<RemoteAuthPackage> &ticketInfo, | 152 | const std::vector<RemoteAuthPackage> &ticketInfo, |
| 153 | const RemoteInfo &remoteInfo, | 153 | const RemoteInfo &remoteInfo, |
| 154 | std::vector<bool> &verifyRes); | 154 | std::vector<bool> &verifyRes); |
| 155 | + | ||
| 156 | + /** | ||
| 157 | + * @brief Get remote grant status. | ||
| 158 | + * | ||
| 159 | + * @param remoteGrantStatus Output remote grant status. | ||
| 160 | + * @return Returns 0 on success, or error code on failure. | ||
| 161 | + */ | ||
| 162 | + static int32_t GetRemoteGrantStatus(int32_t& remoteGrantStatus); | ||
| 163 | + | ||
| 164 | + /** | ||
| 165 | + * @brief Update remote grant status. | ||
| 166 | + * | ||
| 167 | + * @param remoteGrantStatus Remote grant status to set. | ||
| 168 | + * @return Returns 0 on success, or error code on failure. | ||
| 169 | + */ | ||
| 170 | + static int32_t UpdateRemoteGrantStatus(int32_t remoteGrantStatus); | ||
| 155 | }; | 171 | }; |
| 156 | 172 | ||
| 157 | } | 173 | } |
| @@ -107,6 +107,8 @@ private: | |||
| 107 | void GetValidPermissions(std::vector<std::string> &permissions, const std::vector<PermissionInfo> &permissionInfos); | 107 | void GetValidPermissions(std::vector<std::string> &permissions, const std::vector<PermissionInfo> &permissionInfos); |
| 108 | 108 | ||
| 109 | int32_t GetVerifyTicketInfo(const UserAuthResult &userAuthResult, VerifyTicketInfo &ticketInfo); | 109 | int32_t GetVerifyTicketInfo(const UserAuthResult &userAuthResult, VerifyTicketInfo &ticketInfo); |
| 110 | + | ||
| 111 | + void StoreGrantRecordIfValid(const UserAuthResult &userAuthResult, const TicketMessageInfo &ticketMessageInfo); | ||
| 110 | }; | 112 | }; |
| 111 | 113 | ||
| 112 | } // namespace OHOS::Security::SAF | 114 | } // namespace OHOS::Security::SAF |
| @@ -840,6 +840,56 @@ int32_t PermissionManager::GetVerifyTicketInfo(const UserAuthResult &userAuthRes | |||
| 840 | } | 840 | } |
| 841 | IF_ERROR_LOGE_RETURN(ret, | 841 | IF_ERROR_LOGE_RETURN(ret, |
| 842 | "GetVerifyTicketInfo :: GenerateTicketInfoWithTimeStamp failed, ret=%{public}d", ret); | 842 | "GetVerifyTicketInfo :: GenerateTicketInfoWithTimeStamp failed, ret=%{public}d", ret); |
| 843 | + | ||
| 844 | + StoreGrantRecordIfValid(userAuthResult, ticketMessageInfo); | ||
| 845 | + | ||
| 843 | return SAF_SUCCESS; | 846 | return SAF_SUCCESS; |
| 844 | } | 847 | } |
| 848 | + | ||
| 849 | +void PermissionManager::StoreGrantRecordIfValid(const UserAuthResult &userAuthResult, | ||
| 850 | + const TicketMessageInfo &ticketMessageInfo) | ||
| 851 | +{ | ||
| 852 | + if (IsRemoteInfoEmpty(userAuthResult.permissionQuery.remoteInfo)) { | ||
| 853 | + return; | ||
| 854 | + } | ||
| 855 | + | ||
| 856 | + std::vector<std::string> grantedPermissions; | ||
| 857 | + for (const auto &permInfo : userAuthResult.permissionInfo) { | ||
| 858 | + if (permInfo.permissionStatus == PermissionStatus::GRANTED) { | ||
| 859 | + grantedPermissions.push_back(permInfo.permission); | ||
| 860 | + } | ||
| 861 | + } | ||
| 862 | + | ||
| 863 | + if (grantedPermissions.empty()) { | ||
| 864 | + return; | ||
| 865 | + } | ||
| 866 | + | ||
| 867 | + std::string controlledDeviceName = | ||
| 868 | + userAuthResult.permissionQuery.remoteInfo.remoteControlParams.controlledDeviceName; | ||
| 869 | + std::string controllerDeviceName = | ||
| 870 | + userAuthResult.permissionQuery.remoteInfo.remoteControlParams.controllerDeviceName; | ||
| 871 | + | ||
| 872 | + int32_t osAccountId; | ||
| 873 | + int32_t callerUid = IPCSkeleton::GetCallingUid(); | ||
| 874 | + bool retFlag = GetOsAccountIdFromUid(callerUid, &osAccountId); | ||
| 875 | + if (!retFlag || osAccountId < MIN_OS_ACCOUNT_ID) { | ||
| 876 | + LOGE("invalid uid or osAccountId"); | ||
| 877 | + return; | ||
| 878 | + } | ||
| 879 | + | ||
| 880 | + rust::Vec<rust::String> rustPermissions; | ||
| 881 | + for (const auto &perm : grantedPermissions) { | ||
| 882 | + rustPermissions.push_back(rust::String(perm)); | ||
| 883 | + } | ||
| 884 | + int32_t storeRet = OHOS::Security::SAF::cxx_store_controlled_grant_record( | ||
| 885 | + osAccountId, | ||
| 886 | + rust::String(controlledDeviceName), | ||
| 887 | + rust::String(controllerDeviceName), | ||
| 888 | + rustPermissions, | ||
| 889 | + static_cast<int32_t>(ticketMessageInfo.callerTokenId) | ||
| 890 | + ); | ||
| 891 | + if (storeRet != SAF_SUCCESS) { | ||
| 892 | + LOGE("StoreGrantRecordIfValid :: cxx_store_controlled_grant_record failed, ret=%{public}d", storeRet); | ||
| 893 | + } | ||
| 894 | +} | ||
| 845 | } | 895 | } |
| @@ -39,6 +39,7 @@ use crate::wrapper::{cxx_is_screen_locked, notify_error, notify_performance_metr | |||
| 39 | 39 | ||
| 40 | mod common_event; | 40 | mod common_event; |
| 41 | mod remote_control; | 41 | mod remote_control; |
| 42 | +mod remote_grant_status; | ||
| 42 | mod stub; | 43 | mod stub; |
| 43 | mod ticket_operation; | 44 | mod ticket_operation; |
| 44 | mod wrapper; | 45 | mod wrapper; |
| @@ -17,6 +17,7 @@ | |||
| 17 | 17 | ||
| 18 | use saf_definition::{macros_lib, CommandInfo, ErrCode, Result}; | 18 | use saf_definition::{macros_lib, CommandInfo, ErrCode, Result}; |
| 19 | use saf_log::loge; | 19 | use saf_log::loge; |
| 20 | +use std::collections::HashSet; | ||
| 20 | 21 | ||
| 21 | const MAX_PERMISSION_BUF_SIZE: usize = 4096; | 22 | const MAX_PERMISSION_BUF_SIZE: usize = 4096; |
| 22 | 23 | ||
| @@ -69,6 +70,8 @@ pub fn batch_query_cli_permission( | |||
| 69 | call_cxx_batch_query(&cxx_cmds, &mut out_buf, &mut result)?; | 70 | call_cxx_batch_query(&cxx_cmds, &mut out_buf, &mut result)?; |
| 70 | parse_permissions_from_buffer(&out_buf, result.perm_count, permissions)?; | 71 | parse_permissions_from_buffer(&out_buf, result.perm_count, permissions)?; |
| 71 | 72 | ||
| 73 | + deduplicate_permissions(permissions); | ||
| 74 | + | ||
| 72 | Ok(()) | 75 | Ok(()) |
| 73 | } | 76 | } |
| 74 | 77 | ||
| @@ -111,6 +114,12 @@ fn call_cxx_batch_query( | |||
| 111 | Ok(()) | 114 | Ok(()) |
| 112 | } | 115 | } |
| 113 | 116 | ||
| 117 | +/// Deduplicate permissions while preserving insertion order | ||
| 118 | +fn deduplicate_permissions(permissions: &mut Vec<String>) { | ||
| 119 | + let mut seen = HashSet::new(); | ||
| 120 | + permissions.retain(|p| seen.insert(p.clone())); | ||
| 121 | +} | ||
| 122 | + | ||
| 114 | fn parse_permissions_from_buffer( | 123 | fn parse_permissions_from_buffer( |
| 115 | out_buf: &[u8], | 124 | out_buf: &[u8], |
| 116 | perm_count: i32, | 125 | perm_count: i32, |
| @@ -227,10 +227,6 @@ fn validate_and_verify_single_controller_package( | |||
| 227 | } | 227 | } |
| 228 | }; | 228 | }; |
| 229 | 229 | ||
| 230 | - if verify_result { | ||
| 231 | - store_grant_record_if_success(os_account_id, package, Role::Controlled); | ||
| 232 | - } | ||
| 233 | - | ||
| 234 | Ok(verify_result) | 230 | Ok(verify_result) |
| 235 | } | 231 | } |
| 236 | 232 | ||
| @@ -286,7 +286,8 @@ pub use controller_device::{ | |||
| 286 | verify_controller_device_package, | 286 | verify_controller_device_package, |
| 287 | }; | 287 | }; |
| 288 | 288 | ||
| 289 | -pub use grant_record::{store_grant_record, StoreGrantRecordParams}; | 289 | +pub use grant_record::{get_bundle_name_from_token, |
| 290 | + store_grant_record, StoreGrantRecordParams}; | ||
| 290 | 291 | ||
| 291 | pub use cli_manager::batch_query_cli_permission; | 292 | pub use cli_manager::batch_query_cli_permission; |
| 292 | 293 | ||
| @@ -30,7 +30,7 @@ use saf_definition::{macros_lib, ErrCode, Result, DeviceIdHeader}; | |||
| 30 | 30 | ||
| 31 | use saf_log::{loge, logi}; | 31 | use saf_log::{loge, logi}; |
| 32 | 32 | ||
| 33 | -use saf_utils::{JsonValue, get_compact_json_value}; | 33 | +use saf_utils::{JsonValue, get_compact_json_value, system_time_in_millis}; |
| 34 | 34 | ||
| 35 | use saf_common::JsonBuilder; | 35 | use saf_common::JsonBuilder; |
| 36 | 36 | ||
| @@ -45,6 +45,8 @@ const CACHE_DIR_SUFFIX: &str = "secure_access_fence/agent_plugin"; | |||
| 45 | const CACHE_FILE_NAME: &str = "challenge_cache_list.txt"; | 45 | const CACHE_FILE_NAME: &str = "challenge_cache_list.txt"; |
| 46 | 46 | ||
| 47 | const FILE_MODE: u32 = 0o640; | 47 | const FILE_MODE: u32 = 0o640; |
| 48 | + | ||
| 49 | +const CHALLENGE_EXPIRATION_MILLIS: u64 = 86_400_000; | ||
| 48 | 50 | ||
| 49 | 51 | ||
| 50 | 52 | ||
| @@ -103,12 +105,12 @@ fn ensure_cache_dir_exists(os_account_id: i32) -> Result<()> { | |||
| 103 | if !path.exists() { | 105 | if !path.exists() { |
| 104 | fs::create_dir_all(path).map_err(|e| { | 106 | fs::create_dir_all(path).map_err(|e| { |
| 105 | macros_lib::log_and_into_saf_error!(ErrCode::FileOperationError, | 107 | macros_lib::log_and_into_saf_error!(ErrCode::FileOperationError, |
| 106 | - "Failed to create cache dir {}: {}", dir_path, e) | 108 | + "Failed to create cache dir: {}", e) |
| 107 | })?; | 109 | })?; |
| 108 | 110 | ||
| 109 | fs::set_permissions(path, fs::Permissions::from_mode(0o750)).map_err(|e| { | 111 | fs::set_permissions(path, fs::Permissions::from_mode(0o750)).map_err(|e| { |
| 110 | macros_lib::log_and_into_saf_error!(ErrCode::FileOperationError, | 112 | macros_lib::log_and_into_saf_error!(ErrCode::FileOperationError, |
| 111 | - "Failed to set dir permissions {}: {}", dir_path, e) | 113 | + "Failed to set dir permissions: {}", e) |
| 112 | })?; | 114 | })?; |
| 113 | } | 115 | } |
| 114 | Ok(()) | 116 | Ok(()) |
| @@ -140,12 +142,12 @@ pub fn cache_challenge(os_account_id: i32, challenge: &str, timestamp: u64, devi | |||
| 140 | .open(path) | 142 | .open(path) |
| 141 | .map_err(|e| { | 143 | .map_err(|e| { |
| 142 | macros_lib::log_and_into_saf_error!(ErrCode::FileOperationError, | 144 | macros_lib::log_and_into_saf_error!(ErrCode::FileOperationError, |
| 143 | - "Failed to open cache file {}: {}", file_path, e) | 145 | + "Failed to open cache file: {}", e) |
| 144 | })?; | 146 | })?; |
| 145 | 147 | ||
| 146 | file.write_all(line.as_bytes()).map_err(|e| { | 148 | file.write_all(line.as_bytes()).map_err(|e| { |
| 147 | macros_lib::log_and_into_saf_error!(ErrCode::FileOperationError, | 149 | macros_lib::log_and_into_saf_error!(ErrCode::FileOperationError, |
| 148 | - "Failed to write cache file {}: {}", file_path, e) | 150 | + "Failed to write cache file: {}", e) |
| 149 | })?; | 151 | })?; |
| 150 | 152 | ||
| 151 | logi!("[challenge_cache] Cached challenge for os_account_id={}", os_account_id); | 153 | logi!("[challenge_cache] Cached challenge for os_account_id={}", os_account_id); |
| @@ -159,7 +161,7 @@ pub fn verify_and_remove_challenge( | |||
| 159 | device_id_header: &DeviceIdHeader | 161 | device_id_header: &DeviceIdHeader |
| 160 | ) -> Result<bool> { | 162 | ) -> Result<bool> { |
| 161 | let _lock = CHALLENGE_CACHE_LOCK.lock().unwrap_or_else(|e| e.into_inner()); | 163 | let _lock = CHALLENGE_CACHE_LOCK.lock().unwrap_or_else(|e| e.into_inner()); |
| 162 | - | 164 | + |
| 163 | let file_path = get_cache_file_full_path(os_account_id); | 165 | let file_path = get_cache_file_full_path(os_account_id); |
| 164 | let path = Path::new(&file_path); | 166 | let path = Path::new(&file_path); |
| 165 | 167 | ||
| @@ -179,9 +181,9 @@ pub fn verify_and_remove_challenge( | |||
| 179 | rewrite_cache_file(&file_path, &remaining_lines)?; | 181 | rewrite_cache_file(&file_path, &remaining_lines)?; |
| 180 | logi!("[challenge_cache] Verified and removed challenge for os_account_id={}", os_account_id); | 182 | logi!("[challenge_cache] Verified and removed challenge for os_account_id={}", os_account_id); |
| 181 | } else { | 183 | } else { |
| 182 | - loge!("[challenge_cache] Challenge not found: {}", challenge); | 184 | + loge!("[challenge_cache] Challenge not found"); |
| 183 | return macros_lib::log_throw_error!(ErrCode::ReplayAttackDetected, | 185 | return macros_lib::log_throw_error!(ErrCode::ReplayAttackDetected, |
| 184 | - "Challenge not found: {}", challenge); | 186 | + "Challenge not found"); |
| 185 | } | 187 | } |
| 186 | 188 | ||
| 187 | Ok(found) | 189 | Ok(found) |
| @@ -194,9 +196,15 @@ fn find_and_remove_challenge_in_file( | |||
| 194 | expected_controller_id: &str, | 196 | expected_controller_id: &str, |
| 195 | expected_controlled_id: &str, | 197 | expected_controlled_id: &str, |
| 196 | ) -> Result<(bool, Vec<String>)> { | 198 | ) -> Result<(bool, Vec<String>)> { |
| 199 | + let current_time_millis = system_time_in_millis().map_err(|e| { | ||
| 200 | + loge!("[challenge_cache] Failed to get system time: {:?}", e); | ||
| 201 | + macros_lib::log_and_into_saf_error!(ErrCode::GeneralError, | ||
| 202 | + "Failed to get system time: {:?}", e) | ||
| 203 | + })?; | ||
| 204 | + | ||
| 197 | let file = File::open(file_path).map_err(|e| { | 205 | let file = File::open(file_path).map_err(|e| { |
| 198 | macros_lib::log_and_into_saf_error!(ErrCode::FileOperationError, | 206 | macros_lib::log_and_into_saf_error!(ErrCode::FileOperationError, |
| 199 | - "Failed to open cache file {}: {}", file_path, e) | 207 | + "Failed to open cache file: {}", e) |
| 200 | })?; | 208 | })?; |
| 201 | 209 | ||
| 202 | let reader = BufReader::new(file); | 210 | let reader = BufReader::new(file); |
| @@ -213,31 +221,67 @@ fn find_and_remove_challenge_in_file( | |||
| 213 | continue; | 221 | continue; |
| 214 | } | 222 | } |
| 215 | 223 | ||
| 216 | - if let Some((cached_challenge, cached_entry_json)) = line.split_once('|') { | 224 | + match process_line(&line, challenge, expected_controller_id, expected_controlled_id, current_time_millis) { |
| 217 | - if cached_challenge == challenge { | 225 | + Ok(ProcessResult::Matched) => found = true, |
| 218 | - if let Ok(entry) = deserialize_cache_entry(cached_entry_json) { | 226 | + Ok(ProcessResult::Keep) => remaining_lines.push(line), |
| 219 | - if entry.controller_device_id == expected_controller_id | 227 | + Ok(ProcessResult::Skip) => {} |
| 220 | - && entry.controlled_device_id == expected_controlled_id { | 228 | + Err(e) => return Err(e), |
| 221 | - found = true; | ||
| 222 | - continue; | ||
| 223 | - } else { | ||
| 224 | - loge!("[challenge_cache] DeviceIdHeader mismatch for challenge"); | ||
| 225 | - return macros_lib::log_throw_error!(ErrCode::ReplayAttackDetected, | ||
| 226 | - "DeviceIdHeader mismatch for challenge"); | ||
| 227 | - } | ||
| 228 | - } else { | ||
| 229 | - loge!("[challenge_cache] DeviceIdHeader mismatch for challenge"); | ||
| 230 | - return macros_lib::log_throw_error!(ErrCode::ReplayAttackDetected, | ||
| 231 | - "DeviceIdHeader mismatch for challenge"); | ||
| 232 | - } | ||
| 233 | - } | ||
| 234 | } | 229 | } |
| 235 | - remaining_lines.push(line); | ||
| 236 | } | 230 | } |
| 237 | 231 | ||
| 238 | Ok((found, remaining_lines)) | 232 | Ok((found, remaining_lines)) |
| 239 | } | 233 | } |
| 240 | 234 | ||
| 235 | + | ||
| 236 | +enum ProcessResult { | ||
| 237 | + Matched, | ||
| 238 | + Keep, | ||
| 239 | + Skip, | ||
| 240 | +} | ||
| 241 | + | ||
| 242 | + | ||
| 243 | +fn process_line( | ||
| 244 | + line: &str, | ||
| 245 | + challenge: &str, | ||
| 246 | + expected_controller_id: &str, | ||
| 247 | + expected_controlled_id: &str, | ||
| 248 | + current_time_millis: u64, | ||
| 249 | +) -> Result<ProcessResult> { | ||
| 250 | + let Some((cached_challenge, cached_entry_json)) = line.split_once('|') else { | ||
| 251 | + loge!("[challenge_cache] Invalid line format, skipping..."); | ||
| 252 | + return Ok(ProcessResult::Skip); | ||
| 253 | + }; | ||
| 254 | + | ||
| 255 | + let Ok(entry) = deserialize_cache_entry(cached_entry_json) else { | ||
| 256 | + loge!("[challenge_cache] Failed to parse entry, skipping..."); | ||
| 257 | + return Ok(ProcessResult::Skip); | ||
| 258 | + }; | ||
| 259 | + | ||
| 260 | + let is_expired = current_time_millis > entry.timestamp | ||
| 261 | + && current_time_millis - entry.timestamp > CHALLENGE_EXPIRATION_MILLIS; | ||
| 262 | + | ||
| 263 | + if cached_challenge == challenge { | ||
| 264 | + if is_expired { | ||
| 265 | + loge!("[challenge_cache] Challenge expired"); | ||
| 266 | + return macros_lib::log_throw_error!(ErrCode::ReplayAttackDetected, | ||
| 267 | + "Challenge expired"); | ||
| 268 | + } | ||
| 269 | + if entry.controller_device_id == expected_controller_id | ||
| 270 | + && entry.controlled_device_id == expected_controlled_id { | ||
| 271 | + return Ok(ProcessResult::Matched); | ||
| 272 | + } | ||
| 273 | + loge!("[challenge_cache] DeviceIdHeader mismatch for challenge"); | ||
| 274 | + return macros_lib::log_throw_error!(ErrCode::ReplayAttackDetected, | ||
| 275 | + "DeviceIdHeader mismatch for challenge"); | ||
| 276 | + } | ||
| 277 | + | ||
| 278 | + if is_expired { | ||
| 279 | + Ok(ProcessResult::Skip) | ||
| 280 | + } else { | ||
| 281 | + Ok(ProcessResult::Keep) | ||
| 282 | + } | ||
| 283 | +} | ||
| 284 | + | ||
| 241 | 285 | ||
| 242 | fn rewrite_cache_file(file_path: &str, lines: &[String]) -> Result<()> { | 286 | fn rewrite_cache_file(file_path: &str, lines: &[String]) -> Result<()> { |
| 243 | let path = Path::new(file_path); | 287 | let path = Path::new(file_path); |
| @@ -251,7 +295,7 @@ fn rewrite_cache_file(file_path: &str, lines: &[String]) -> Result<()> { | |||
| 251 | .open(tmp_path_ref) | 295 | .open(tmp_path_ref) |
| 252 | .map_err(|e| { | 296 | .map_err(|e| { |
| 253 | macros_lib::log_and_into_saf_error!(ErrCode::FileOperationError, | 297 | macros_lib::log_and_into_saf_error!(ErrCode::FileOperationError, |
| 254 | - "Failed to open tmp cache file for writing {}: {}", file_path, e) | 298 | + "Failed to open tmp cache file for writing: {}", e) |
| 255 | })?; | 299 | })?; |
| 256 | 300 | ||
| 257 | for line in lines { | 301 | for line in lines { |
| @@ -285,6 +329,11 @@ use lazy_static::lazy_static; | |||
| 285 | use std::collections::HashMap; | 329 | use std::collections::HashMap; |
| 286 | 330 | ||
| 287 | use std::sync::Mutex; | 331 | use std::sync::Mutex; |
| 332 | + | ||
| 333 | +use saf_utils::system_time_in_millis; | ||
| 334 | + | ||
| 335 | + | ||
| 336 | +const CHALLENGE_EXPIRATION_MILLIS: u64 = 86_400_000; | ||
| 288 | 337 | ||
| 289 | 338 | ||
| 290 | lazy_static! { | 339 | lazy_static! { |
| @@ -307,10 +356,24 @@ pub fn verify_and_remove_challenge( | |||
| 307 | challenge: &str, | 356 | challenge: &str, |
| 308 | device_id_header: &DeviceIdHeader, | 357 | device_id_header: &DeviceIdHeader, |
| 309 | ) -> Result<bool> { | 358 | ) -> Result<bool> { |
| 359 | + let current_time_millis = system_time_in_millis().unwrap_or(0); | ||
| 310 | let key = format!("{}:{}", os_account_id, challenge); | 360 | let key = format!("{}:{}", os_account_id, challenge); |
| 311 | let mut cache = MOCK_CHALLENGE_CACHE.lock().unwrap(); | 361 | let mut cache = MOCK_CHALLENGE_CACHE.lock().unwrap(); |
| 362 | + | ||
| 363 | + cache.retain(|_, (timestamp, _, _)| { | ||
| 364 | + current_time_millis <= *timestamp || current_time_millis.saturating_sub(*timestamp) <= CHALLENGE_EXPIRATION_MILLIS | ||
| 365 | + }); | ||
| 366 | + | ||
| 312 | match cache.remove(&key) { | 367 | match cache.remove(&key) { |
| 313 | - Some((_, cached_controller, cached_controlled)) => { | 368 | + Some((timestamp, cached_controller, cached_controlled)) => { |
| 369 | + let is_expired = current_time_millis > timestamp | ||
| 370 | + && current_time_millis - timestamp > CHALLENGE_EXPIRATION_MILLIS; | ||
| 371 | + | ||
| 372 | + if is_expired { | ||
| 373 | + return macros_lib::log_throw_error!(ErrCode::ReplayAttackDetected, | ||
| 374 | + "Challenge expired: {}", challenge); | ||
| 375 | + } | ||
| 376 | + | ||
| 314 | if cached_controller == device_id_header.controller_device_id | 377 | if cached_controller == device_id_header.controller_device_id |
| 315 | && cached_controlled == device_id_header.controlled_device_id { | 378 | && cached_controlled == device_id_header.controlled_device_id { |
| 316 | Ok(true) | 379 | Ok(true) |
| @@ -0,0 +1,42 @@ | |||
| 1 | +/* | ||
| 2 | + * Copyright (c) 2026 Huawei Device Co., Ltd. | ||
| 3 | + * Licensed under the Apache License, Version 2.0 (the "License"); | ||
| 4 | + * you may not use this file except in compliance with the License. | ||
| 5 | + * You may obtain a copy of the License at | ||
| 6 | + * | ||
| 7 | + * http://www.apache.org/licenses/LICENSE-2.0 | ||
| 8 | + * | ||
| 9 | + * Unless required by applicable law or agreed to in writing, software | ||
| 10 | + * distributed under the License is distributed on an "AS IS" BASIS, | ||
| 11 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| 12 | + * See the License for the specific language governing permissions and | ||
| 13 | + * limitations under the License. | ||
| 14 | + */ | ||
| 15 | + | ||
| 16 | +//! This module implements remote grant status management. | ||
| 17 | + | ||
| 18 | +use saf_definition::{macros_lib, ErrCode, Result, RemoteGrantStatus}; | ||
| 19 | + | ||
| 20 | +/// Get remote grant status. | ||
| 21 | +pub fn get_remote_grant_status() -> Result<i32> { | ||
| 22 | + macros_lib::log_throw_error!( | ||
| 23 | + ErrCode::PluginNotSupport, | ||
| 24 | + "Plugin not support for get remote grant status" | ||
| 25 | + ) | ||
| 26 | +} | ||
| 27 | + | ||
| 28 | +/// Update remote grant status. | ||
| 29 | +pub fn update_remote_grant_status(status: i32) -> Result<()> { | ||
| 30 | + if status != RemoteGrantStatus::Enable as i32 && status != RemoteGrantStatus::Disable as i32 { | ||
| 31 | + return macros_lib::log_throw_error!( | ||
| 32 | + ErrCode::InvalidArgument, | ||
| 33 | + "Invalid remote grant status: {}", | ||
| 34 | + status | ||
| 35 | + ); | ||
| 36 | + } | ||
| 37 | + | ||
| 38 | + macros_lib::log_throw_error!( | ||
| 39 | + ErrCode::PluginNotSupport, | ||
| 40 | + "Plugin not support for update remote grant status" | ||
| 41 | + ) | ||
| 42 | +} | ||
| @@ -30,6 +30,7 @@ use saf_ipc::{ | |||
| 30 | CMD_BATCH_GENERATE_TICKET, CMD_BATCH_VERIFY_TICKET, CMD_VERIFY_TICKET, | 30 | CMD_BATCH_GENERATE_TICKET, CMD_BATCH_VERIFY_TICKET, CMD_VERIFY_TICKET, |
| 31 | CMD_GENERATE_CONTROLLED_DEVICE_PACKAGE, CMD_VERIFY_CONTROLLED_DEVICE_PACKAGE, | 31 | CMD_GENERATE_CONTROLLED_DEVICE_PACKAGE, CMD_VERIFY_CONTROLLED_DEVICE_PACKAGE, |
| 32 | CMD_GENERATE_CONTROLLER_DEVICE_PACKAGE, CMD_VERIFY_CONTROLLER_DEVICE_PACKAGE, | 32 | CMD_GENERATE_CONTROLLER_DEVICE_PACKAGE, CMD_VERIFY_CONTROLLER_DEVICE_PACKAGE, |
| 33 | + CMD_GET_REMOTE_GRANT_STATUS, CMD_UPDATE_REMOTE_GRANT_STATUS, | ||
| 33 | IPC_SUCCESS, SA_NAME, | 34 | IPC_SUCCESS, SA_NAME, |
| 34 | }; | 35 | }; |
| 35 | use saf_log::{loge, logi}; | 36 | use saf_log::{loge, logi}; |
| @@ -37,6 +38,7 @@ use saf_plugin::saf_plugin::SAFPlugin; | |||
| 37 | use saf_sdk::{ErrCode, Result, SAFError}; | 38 | use saf_sdk::{ErrCode, Result, SAFError}; |
| 38 | 39 | ||
| 39 | use crate::remote_control; | 40 | use crate::remote_control; |
| 41 | +use crate::remote_grant_status; | ||
| 40 | use crate::wrapper; | 42 | use crate::wrapper; |
| 41 | use crate::SAFService; | 43 | use crate::SAFService; |
| 42 | 44 | ||
| @@ -114,7 +116,13 @@ fn on_remote_request(stub: &SAFService, code: u32, data: &mut MsgParcel, reply: | |||
| 114 | }, | 116 | }, |
| 115 | CMD_VERIFY_CONTROLLER_DEVICE_PACKAGE => { | 117 | CMD_VERIFY_CONTROLLER_DEVICE_PACKAGE => { |
| 116 | handle_verify_controller_device_package(data, reply) | 118 | handle_verify_controller_device_package(data, reply) |
| 117 | - }, | 119 | + }, |
| 120 | + CMD_GET_REMOTE_GRANT_STATUS => { | ||
| 121 | + handle_get_remote_grant_status(data, reply) | ||
| 122 | + } | ||
| 123 | + CMD_UPDATE_REMOTE_GRANT_STATUS => { | ||
| 124 | + handle_update_remote_grant_status(data, reply) | ||
| 125 | + } | ||
| 118 | _ => { | 126 | _ => { |
| 119 | if code >= C_REDIRECT_START_CODE { | 127 | if code >= C_REDIRECT_START_CODE { |
| 120 | let res = wrapper::on_remote_request(code, data, reply); | 128 | let res = wrapper::on_remote_request(code, data, reply); |
| @@ -378,6 +386,55 @@ fn handle_verify_controller_device_package( | |||
| 378 | Ok(()) | 386 | Ok(()) |
| 379 | } | 387 | } |
| 380 | 388 | ||
| 389 | +fn handle_get_remote_grant_status(_data: &mut MsgParcel, reply: &mut MsgParcel) -> IpcResult<()> { | ||
| 390 | + logi!("GetRemoteGrantStatus received"); | ||
| 391 | + | ||
| 392 | + let result = remote_grant_status::get_remote_grant_status(); | ||
| 393 | + | ||
| 394 | + reply.write::<i32>(&(IPC_SUCCESS as i32))?; | ||
| 395 | + | ||
| 396 | + match result { | ||
| 397 | + Ok(status) => { | ||
| 398 | + reply.write::<i32>(&status)?; | ||
| 399 | + reply.write::<i32>(&0)?; | ||
| 400 | + logi!("GetRemoteGrantStatus success, status={}", status); | ||
| 401 | + }, | ||
| 402 | + Err(e) => { | ||
| 403 | + reply.write::<i32>(&0)?; | ||
| 404 | + reply.write::<i32>(&(e.code as i32))?; | ||
| 405 | + loge!("GetRemoteGrantStatus failed: {}", e.msg); | ||
| 406 | + }, | ||
| 407 | + } | ||
| 408 | + | ||
| 409 | + Ok(()) | ||
| 410 | +} | ||
| 411 | + | ||
| 412 | +fn handle_update_remote_grant_status(data: &mut MsgParcel, reply: &mut MsgParcel) -> IpcResult<()> { | ||
| 413 | + let status = data.read::<i32>().map_err(|e| { | ||
| 414 | + loge!("[FATAL]Read status failed: {:?}", e); | ||
| 415 | + IpcStatusCode::Failed | ||
| 416 | + })?; | ||
| 417 | + | ||
| 418 | + logi!("UpdateRemoteGrantStatus received, status={}", status); | ||
| 419 | + | ||
| 420 | + let result = remote_grant_status::update_remote_grant_status(status); | ||
| 421 | + | ||
| 422 | + reply.write::<i32>(&(IPC_SUCCESS as i32))?; | ||
| 423 | + | ||
| 424 | + match result { | ||
| 425 | + Ok(()) => { | ||
| 426 | + reply.write::<i32>(&0)?; | ||
| 427 | + logi!("UpdateRemoteGrantStatus success"); | ||
| 428 | + }, | ||
| 429 | + Err(e) => { | ||
| 430 | + reply.write::<i32>(&(e.code as i32))?; | ||
| 431 | + loge!("UpdateRemoteGrantStatus failed: {}", e.msg); | ||
| 432 | + }, | ||
| 433 | + } | ||
| 434 | + | ||
| 435 | + Ok(()) | ||
| 436 | +} | ||
| 437 | + | ||
| 381 | fn on_extension_request(_stub: &SAFService, code: u32, data: &mut MsgParcel, reply: &mut MsgParcel) -> i32 { | 438 | fn on_extension_request(_stub: &SAFService, code: u32, data: &mut MsgParcel, reply: &mut MsgParcel) -> i32 { |
| 382 | if let Ok(load) = SAFPlugin::get_instance().load_plugin() { | 439 | if let Ok(load) = SAFPlugin::get_instance().load_plugin() { |
| 383 | match load.on_remote_request(code, data, reply) { | 440 | match load.on_remote_request(code, data, reply) { |
| @@ -50,6 +50,13 @@ pub mod ffi { | |||
| 50 | fn get_policy_auth_status(permissions: &Vec<String>, auth_statuses: &mut Vec<i32>) -> i32; | 50 | fn get_policy_auth_status(permissions: &Vec<String>, auth_statuses: &mut Vec<i32>) -> i32; |
| 51 | fn verify_remote_ticket(domain_id: String, remote_control_ticket: String, os_account_id: i32) -> i32; | 51 | fn verify_remote_ticket(domain_id: String, remote_control_ticket: String, os_account_id: i32) -> i32; |
| 52 | fn cxx_store_challenge(caller_token_id: &str, challenge: &str, expire_time_ms: u64) -> i32; | 52 | fn cxx_store_challenge(caller_token_id: &str, challenge: &str, expire_time_ms: u64) -> i32; |
| 53 | + fn cxx_store_controlled_grant_record( | ||
| 54 | + os_account_id: i32, | ||
| 55 | + controlled_device_name: String, | ||
| 56 | + controller_device_name: String, | ||
| 57 | + permission_names: Vec<String>, | ||
| 58 | + caller_token_id: i32, | ||
| 59 | + ) -> i32; | ||
| 53 | } | 60 | } |
| 54 | 61 | ||
| 55 | // Rust callable C++ functions | 62 | // Rust callable C++ functions |
| @@ -200,6 +207,55 @@ pub fn cxx_store_challenge(caller_token_id: &str, challenge: &str, expire_time_m | |||
| 200 | } | 207 | } |
| 201 | } | 208 | } |
| 202 | 209 | ||
| 210 | +/// C++ -> Rust bridge for store_controlled_grant_record. | ||
| 211 | +pub fn cxx_store_controlled_grant_record( | ||
| 212 | + os_account_id: i32, | ||
| 213 | + controlled_device_name: String, | ||
| 214 | + controller_device_name: String, | ||
| 215 | + permission_names: Vec<String>, | ||
| 216 | + caller_token_id: i32, | ||
| 217 | +) -> i32 { | ||
| 218 | + logi!("[Wrapper cxx_store_controlled_grant_record] os_account_id={}, caller_token_id={}, permission_count={}", | ||
| 219 | + os_account_id, caller_token_id, permission_names.len()); | ||
| 220 | + | ||
| 221 | + let calling_bundle_name = match crate::remote_control::get_bundle_name_from_token(caller_token_id) { | ||
| 222 | + Ok(name) => name, | ||
| 223 | + Err(e) => { | ||
| 224 | + loge!("[cxx_store_controlled_grant_record] Failed to get bundle name: {:?}", e); | ||
| 225 | + return e.code as i32; | ||
| 226 | + } | ||
| 227 | + }; | ||
| 228 | + | ||
| 229 | + let params = crate::remote_control::StoreGrantRecordParams { | ||
| 230 | + os_account_id, | ||
| 231 | + controlled_device_name, | ||
| 232 | + controller_device_name, | ||
| 233 | + is_self_grant: false, | ||
| 234 | + permission_names, | ||
| 235 | + device_role: saf_definition::Role::Controlled, | ||
| 236 | + calling_bundle_name, | ||
| 237 | + grant_type: saf_definition::GrantType::RemoteGrant, | ||
| 238 | + timestamp: match saf_utils::system_time_in_millis() { | ||
| 239 | + Ok(t) => t, | ||
| 240 | + Err(e) => { | ||
| 241 | + loge!("[cxx_store_controlled_grant_record] Failed to get timestamp: {:?}", e); | ||
| 242 | + return e.code as i32; | ||
| 243 | + } | ||
| 244 | + }, | ||
| 245 | + }; | ||
| 246 | + | ||
| 247 | + match crate::remote_control::store_grant_record(params) { | ||
| 248 | + Ok(()) => { | ||
| 249 | + logi!("[cxx_store_controlled_grant_record] success"); | ||
| 250 | + 0 | ||
| 251 | + }, | ||
| 252 | + Err(e) => { | ||
| 253 | + loge!("[cxx_store_controlled_grant_record] Failed to store grant record: {:?}", e); | ||
| 254 | + e.code as i32 | ||
| 255 | + } | ||
| 256 | + } | ||
| 257 | +} | ||
| 258 | + | ||
| 203 | /// Get Device UDID via plugin process_event | 259 | /// Get Device UDID via plugin process_event |
| 204 | pub fn get_device_udid(os_account_id: i32) -> saf_definition::Result<String> { | 260 | pub fn get_device_udid(os_account_id: i32) -> saf_definition::Result<String> { |
| 205 | if os_account_id < 0 { | 261 | if os_account_id < 0 { |