1/*
2 * Copyright (c) 2024 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 the capability of processing the identity information of the Asset caller.
17
18use ipc::Skeleton;
19
20use asset_definition::{log_throw_error, ErrCode, Result};
21
22use crate::{get_user_id, OwnerType, SUCCESS};
23
24#[repr(C)]
25struct HapInfoFfi {
26    app_id: *mut u8,
27    app_id_len: u32,
28    app_index: i32,
29}
30
31#[repr(C)]
32struct NativeInfoFfi {
33    uid: u32,
34}
35
36#[repr(C)]
37struct ProcessInfoFfi {
38    user_id: u32,
39    owner_type: u32,
40
41    process_name: *mut u8,
42    process_name_len: u32,
43
44    hap_info: HapInfoFfi,
45    native_info: NativeInfoFfi,
46}
47
48impl ProcessInfoFfi {
49    fn init(user_id: u32, uid: u32, process_name: &mut Vec<u8>, app_id: &mut Vec<u8>) -> Self {
50        ProcessInfoFfi {
51            user_id,
52            owner_type: 0,
53            process_name: process_name.as_mut_ptr(),
54            process_name_len: process_name.len() as u32,
55            hap_info: HapInfoFfi { app_id: app_id.as_mut_ptr(), app_id_len: app_id.len() as u32, app_index: 0 },
56            native_info: NativeInfoFfi { uid },
57        }
58    }
59}
60
61extern "C" {
62    fn GetCallingProcessInfo(userId: u32, uid: u64, ownerInfo: *mut ProcessInfoFfi) -> i32;
63}
64
65/// hap-relative information
66#[derive(Clone)]
67#[derive(PartialEq, Eq)]
68pub struct HapInfo {
69    /// app id for a hap
70    pub app_id: Vec<u8>,
71
72    /// app index
73    pub app_index: i32,
74}
75
76/// native-relative information
77#[derive(Clone)]
78#[derive(PartialEq, Eq)]
79pub struct NativeInfo {
80    /// uid
81    pub uid: u32,
82}
83
84/// process detail information
85#[derive(Clone)]
86#[derive(PartialEq, Eq)]
87pub enum ProcessInfoDetail {
88    /// hap-relative information
89    Hap(HapInfo),
90
91    /// native-relative information
92    Native(NativeInfo),
93}
94
95/// The identity of calling process.
96#[derive(Clone)]
97#[derive(PartialEq, Eq)]
98pub struct ProcessInfo {
99    /// user id of the process
100    pub user_id: u32,
101
102    /// the owner type of the process
103    pub owner_type: OwnerType,
104
105    /// process name
106    pub process_name: Vec<u8>,
107
108    /// process information
109    pub process_info_detail: ProcessInfoDetail,
110}
111
112impl ProcessInfo {
113    /// Build process info.
114    pub fn build() -> Result<Self> {
115        let uid = Skeleton::calling_uid();
116        let user_id = get_user_id(uid)?;
117        let mut process_name = vec![0u8; 256];
118        let mut app_id: Vec<u8> = vec![0u8; 256];
119        let mut process_info_ffi = ProcessInfoFfi::init(user_id, uid as u32, &mut process_name, &mut app_id);
120        match unsafe { GetCallingProcessInfo(user_id, uid, &mut process_info_ffi) } {
121            SUCCESS => {
122                process_name.truncate(process_info_ffi.process_name_len as usize);
123                app_id.truncate(process_info_ffi.hap_info.app_id_len as usize);
124            },
125            error => {
126                let error = ErrCode::try_from(error as u32)?;
127                return log_throw_error!(error, "[FATAL]Get calling package name failed, res is {}.", error);
128            },
129        }
130
131        let process_info_detail = match OwnerType::try_from(process_info_ffi.owner_type)? {
132            OwnerType::Hap => {
133                ProcessInfoDetail::Hap(HapInfo { app_id, app_index: process_info_ffi.hap_info.app_index })
134            },
135            OwnerType::Native => ProcessInfoDetail::Native(NativeInfo { uid: process_info_ffi.native_info.uid }),
136        };
137
138        Ok(Self {
139            user_id,
140            owner_type: OwnerType::try_from(process_info_ffi.owner_type)?,
141            process_name,
142            process_info_detail,
143        })
144    }
145}
146