1 /*
2 * Copyright (c) 2024-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 #include "cm_napi_get_cert_store_path.h"
17
18 #include "cm_log.h"
19 #include "cm_napi_common.h"
20 #include "cm_type.h"
21
22 #include "bundle_mgr_proxy.h"
23 #include "iservice_registry.h"
24 #include "os_account_manager.h"
25 #include "system_ability_definition.h"
26
27 using namespace std;
28 using namespace OHOS;
29 using namespace OHOS::AppExecFwk;
30
31 namespace CMNapi {
32 namespace {
33 constexpr int CM_NAPI_GET_CERT_STORE_PATH_ARGS = 1;
34 }
35
GetBundleMgrProxy()36 static sptr<BundleMgrProxy> GetBundleMgrProxy()
37 {
38 auto systemAbilityManager = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
39 if (!systemAbilityManager) {
40 CM_LOG_E("Failed to get system ability mgr.");
41 return nullptr;
42 }
43
44 auto remoteObject = systemAbilityManager->GetSystemAbility(BUNDLE_MGR_SERVICE_SYS_ABILITY_ID);
45 if (!remoteObject) {
46 CM_LOG_E("Failed to get bundle manager proxy.");
47 return nullptr;
48 }
49 return iface_cast<BundleMgrProxy>(remoteObject);
50 }
51
GetUserCaStorePath(const enum CmCertScope certScope,string & path)52 static int32_t GetUserCaStorePath(const enum CmCertScope certScope, string &path)
53 {
54 path += CA_STORE_PATH_USER_SANDBOX_BASE;
55 if (certScope == CM_GLOBAL_USER) {
56 path += "0";
57 return CM_SUCCESS;
58 }
59
60 int32_t userId = 0;
61 sptr<BundleMgrProxy> bundleMgrProxy = GetBundleMgrProxy();
62 if (bundleMgrProxy == nullptr) {
63 CM_LOG_E("Failed to get bundle manager proxy.");
64 return CM_FAILURE;
65 }
66
67 BundleInfo bundleInfo;
68 int32_t flags = static_cast<int32_t>(GetBundleInfoFlag::GET_BUNDLE_INFO_DEFAULT) |
69 static_cast<int32_t>(GetBundleInfoFlag::GET_BUNDLE_INFO_WITH_APPLICATION);
70 int32_t ret = bundleMgrProxy->GetBundleInfoForSelf(flags, bundleInfo);
71 if (ret != 0) {
72 CM_LOG_E("Failed to get bundle info for self");
73 return CM_FAILURE;
74 }
75
76 ret = AccountSA::OsAccountManager::GetOsAccountLocalIdFromUid(bundleInfo.applicationInfo.uid, userId);
77 if (ret != 0) {
78 CM_LOG_E("Failed to get userid from uid[%d]", bundleInfo.applicationInfo.uid);
79 return CM_FAILURE;
80 }
81
82 path += to_string(userId);
83 return CM_SUCCESS;
84 }
85
GetCertStorePath(napi_env env,const enum CmCertType certType,const enum CmCertScope certScope)86 static napi_value GetCertStorePath(napi_env env, const enum CmCertType certType, const enum CmCertScope certScope)
87 {
88 string path = "";
89 if (certType == CM_CA_CERT_SYSTEM) {
90 path += CA_STORE_PATH_SYSTEM;
91 } else {
92 int32_t ret = GetUserCaStorePath(certScope, path);
93 if (ret != CM_SUCCESS) {
94 CM_LOG_E("Failed to get user ca path.");
95 ThrowError(env, INNER_FAILURE, "there is an internal error");
96 return nullptr;
97 }
98 }
99
100 napi_value result = nullptr;
101 napi_status status = napi_create_string_utf8(env, path.c_str(), path.length(), &result);
102 if (status != napi_ok) {
103 CM_LOG_E("Failed to creat string out.");
104 ThrowError(env, INNER_FAILURE, "there is an internal error");
105 return nullptr;
106 }
107 return result;
108 }
109
GetCertScope(napi_env env,napi_value arg,uint32_t & scope)110 static int32_t GetCertScope(napi_env env, napi_value arg, uint32_t &scope)
111 {
112 bool hasScope = false;
113 napi_status status = napi_has_named_property(env, arg, CM_CERT_SCOPE_STR.c_str(), &hasScope);
114 if (status != napi_ok || !hasScope) {
115 CM_LOG_D("property certScope not exist");
116 return CM_SUCCESS; /* certScope is optional parameter, can be unset */
117 }
118
119 napi_value obj = nullptr;
120 status = napi_get_named_property(env, arg, CM_CERT_SCOPE_STR.c_str(), &obj);
121 if (status != napi_ok) {
122 CM_LOG_E("Failed to get property certScope");
123 return CM_FAILURE;
124 }
125
126 napi_valuetype valueType;
127 status = napi_typeof(env, obj, &valueType);
128 if (status != napi_ok) {
129 CM_LOG_E("Failed to get property type");
130 return CM_FAILURE;
131 }
132
133 if (valueType == napi_undefined) {
134 CM_LOG_D("property certScope is undefined");
135 return CM_SUCCESS; /* certScope is optional parameter, can be undefined */
136 }
137
138 napi_value result = ParseUint32(env, obj, scope);
139 if (result == nullptr) {
140 CM_LOG_E("Failed to get scope value");
141 return CM_FAILURE;
142 }
143
144 if (!IsValidCertScope(scope)) { /* the scope needs to be checked regardless of the certType type */
145 CM_LOG_E("certScope[%u] is invalid", scope);
146 return CM_FAILURE;
147 }
148
149 return CM_SUCCESS;
150 }
151
GetAndCheckCertType(napi_env env,napi_value arg,uint32_t & type)152 static int32_t GetAndCheckCertType(napi_env env, napi_value arg, uint32_t &type)
153 {
154 napi_value certType = nullptr;
155 napi_status status = napi_get_named_property(env, arg, CM_CERT_TYPE_STR.c_str(), &certType);
156 if (status != napi_ok) {
157 CM_LOG_E("Failed to get certType");
158 return CM_FAILURE;
159 }
160
161 napi_value result = ParseUint32(env, certType, type);
162 if (result == nullptr) {
163 CM_LOG_E("Failed to get certType value");
164 return CM_FAILURE;
165 }
166
167 if (!IsValidCertType(type)) {
168 CM_LOG_E("certType[%u] is invalid", type);
169 return CM_FAILURE;
170 }
171 return CM_SUCCESS;
172 }
173
GetAndCheckCertScope(napi_env env,napi_value arg,const enum CmCertType type,uint32_t & scope)174 static int32_t GetAndCheckCertScope(napi_env env, napi_value arg, const enum CmCertType type, uint32_t &scope)
175 {
176 int32_t ret = GetCertScope(env, arg, scope);
177 if (ret != CM_SUCCESS) {
178 CM_LOG_E("Failed to get certScope");
179 return CM_FAILURE;
180 }
181
182 if ((type == CM_CA_CERT_USER) && (scope == INIT_INVALID_VALUE)) {
183 CM_LOG_E("get user ca cert store path, but scope is not set");
184 return CM_FAILURE;
185 }
186 return CM_SUCCESS;
187 }
188
CMNapiGetCertStorePath(napi_env env,napi_callback_info info)189 napi_value CMNapiGetCertStorePath(napi_env env, napi_callback_info info)
190 {
191 // get params
192 size_t argc = CM_NAPI_GET_CERT_STORE_PATH_ARGS;
193 napi_value argv[CM_NAPI_GET_CERT_STORE_PATH_ARGS] = { nullptr };
194 napi_status status = napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr);
195 if (status != napi_ok) {
196 ThrowError(env, PARAM_ERROR, "Failed to get params");
197 return nullptr;
198 }
199
200 // check param count should be 1.
201 if (argc != CM_NAPI_GET_CERT_STORE_PATH_ARGS) {
202 ThrowError(env, PARAM_ERROR, "param count invalid, should be 1.");
203 CM_LOG_E("args count[%zu] invalid, should be 1.", argc);
204 return nullptr;
205 }
206
207 uint32_t type;
208 int32_t ret = GetAndCheckCertType(env, argv[0], type);
209 if (ret != CM_SUCCESS) {
210 ThrowError(env, PARAM_ERROR, "Failed to get param certType");
211 return nullptr;
212 }
213
214 uint32_t scope = INIT_INVALID_VALUE;
215 ret = GetAndCheckCertScope(env, argv[0], static_cast<CmCertType>(type), scope);
216 if (ret != CM_SUCCESS) {
217 ThrowError(env, PARAM_ERROR, "Failed to get param certScope");
218 return nullptr;
219 }
220
221 return GetCertStorePath(env, static_cast<CmCertType>(type), static_cast<CmCertScope>(scope));
222 }
223 } // namespace CertManagerNapi
224