1 /*
2  * Copyright (c) 2020-2022 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 "ipc_auth.h"
17 
18 #include <securec.h>
19 #include <stdbool.h>
20 #include <string.h>
21 
22 #ifdef OHOS_APPFWK_ENABLE
23 #include "bundle_manager.h"
24 #endif
25 #include "log.h"
26 
27 #include "ipc_auth_err.h"
28 #include "policy_preset.h"
29 #include "policy_preset_product.h"
30 #include "policy_registry.h"
31 
32 static unsigned int g_systemSvcUids[] = {1, 2, 0, 6, 7, 8, 9, 10, 11, 12, 19, 20, 3046};
33 
34 static unsigned int g_systemSvcUidSize = sizeof(g_systemSvcUids) / sizeof(unsigned int);
35 
IsUidValid(unsigned int uid)36 static int IsUidValid(unsigned int uid)
37 {
38     for (int i = 0; i < g_systemSvcUidSize; i++) {
39         if (g_systemSvcUids[i] == uid) {
40             return AUTH_ERRORCODE_SUCCESS;
41         }
42     }
43     return AUTH_ERRORCODE_INVALID_UID;
44 }
45 
46 #ifdef OHOS_APPFWK_ENABLE
GetUidByBundleName(const char * bundleName,unsigned int * uid)47 static int GetUidByBundleName(const char *bundleName, unsigned int *uid)
48 {
49     BundleInfo bundleInfo = {0};
50     if (GetBundleInfo(bundleName, 0, &bundleInfo) != 0) {
51         HILOG_ERROR(HILOG_MODULE_APP, "Invalid bundleName, [name: %s][line: %d]", bundleName, __LINE__);
52         return AUTH_ERRORCODE_INVALID_BUNDLENAME;
53     }
54     *uid = bundleInfo.uid;
55     return AUTH_ERRORCODE_SUCCESS;
56 }
57 #endif
58 
StrcmpWithNull(const char * s1,const char * s2)59 static int StrcmpWithNull(const char *s1, const char *s2)
60 {
61     if ((s1 == NULL) && (s2 == NULL)) {
62         return 0;
63     }
64     if ((s1 == NULL) || (s2 == NULL)) {
65         return -1;
66     }
67     return strcmp(s1, s2);
68 }
69 
SetPolicy(const IpcPolicy * policy,PolicyTrans * policyTrans)70 static void SetPolicy(const IpcPolicy *policy, PolicyTrans *policyTrans)
71 {
72     switch (policy->type) {
73         case RANGE:
74             policyTrans->type = RANGE;
75             policyTrans->uidMax = policy->uidMax;
76             policyTrans->uidMin = policy->uidMin;
77             break;
78         case FIXED:
79             policyTrans->type = FIXED;
80             for (int m = 0; m < UID_SIZE; m++) {
81                 policyTrans->fixedUid[m] = policy->fixedUid[m];
82             }
83             break;
84 #ifdef OHOS_APPFWK_ENABLE
85         case BUNDLENAME: {
86             policyTrans->type = BUNDLENAME;
87             unsigned int uid = 0;
88             int ret = GetUidByBundleName(policy->bundleName, &uid);
89             if (ret != AUTH_ERRORCODE_SUCCESS) {
90                 break;
91             }
92             policyTrans->fixedUid[0] = uid;
93             break;
94         }
95 #endif
96         default:
97             break;
98     }
99 }
100 
IsPolicyValid(enum PolicyType type)101 static bool IsPolicyValid(enum PolicyType type)
102 {
103     if ((type == RANGE) || (type == FIXED)) {
104         return true;
105     }
106 #ifdef OHOS_APPFWK_ENABLE
107     if (type == BUNDLENAME) {
108         return true;
109     }
110 #endif
111     return false;
112 }
113 
SetPolicies(const FeaturePolicy * featurePolicy,PolicyTrans ** policies,unsigned int * policyNum)114 static int SetPolicies(const FeaturePolicy *featurePolicy, PolicyTrans **policies, unsigned int *policyNum)
115 {
116     int num = 0;
117     for (int k = 0; k < POLICY_SIZE; k++) {
118         if (IsPolicyValid(featurePolicy->policies[k].type)) {
119             num++;
120         }
121     }
122     int allocSize = sizeof(PolicyTrans) * num;
123     if (allocSize == 0) {
124         return AUTH_ERRORCODE_NO_POLICY_SET;
125     }
126     *policies = (PolicyTrans *)malloc(allocSize);
127     if (*policies == NULL) {
128         HILOG_ERROR(HILOG_MODULE_APP, "Malloc failed, [line: %d]", __LINE__);
129         return AUTH_ERRORCODE_MALLOC_FAIL;
130     }
131     if (memset_s(*policies, allocSize, 0x0, allocSize) != EOK) {
132         HILOG_ERROR(HILOG_MODULE_APP, "Memset failed, [line: %d]", __LINE__);
133         free(*policies);
134         *policies = NULL;
135         return AUTH_ERRORCODE_MEMSET_FAIL;
136     }
137     int index = 0;
138     for (int k = 0; k < POLICY_SIZE; k++) {
139         IpcPolicy policy = featurePolicy->policies[k];
140         if (IsPolicyValid(policy.type)) {
141             SetPolicy(&policy, *policies + index);
142             index++;
143         }
144     }
145     *policyNum = num;
146     return AUTH_ERRORCODE_SUCCESS;
147 }
148 
SetPresetPolicies(const PolicySetting presetPolicy[],int policySize,RegParams params,PolicyTrans ** policies,unsigned int * policyNum)149 static int SetPresetPolicies(const PolicySetting presetPolicy[], int policySize, RegParams params,
150     PolicyTrans **policies, unsigned int *policyNum)
151 {
152     for (int i = 0; i < policySize; i++) {
153         if (strcmp(presetPolicy[i].service, params.service) != 0) {
154             continue;
155         }
156         for (int j = 0; j < presetPolicy[i].featureNum; j++) {
157             FeaturePolicy *featurePolicy = (FeaturePolicy *) presetPolicy[i].features + j;
158             if (StrcmpWithNull(featurePolicy->feature, params.feature) != 0) {
159                 continue;
160             }
161             if (SetPolicies(featurePolicy, policies, policyNum) == AUTH_ERRORCODE_SUCCESS) {
162                 return AUTH_ERRORCODE_SUCCESS;
163             }
164             return AUTH_ERRORCODE_NO_POLICY_SET;
165         }
166         return AUTH_ERRORCODE_NO_POLICY_SET;
167     }
168     return AUTH_ERRORCODE_POLICY_NOT_FOUND;
169 }
170 
GetCommunicationStrategy(RegParams params,PolicyTrans ** policies,unsigned int * policyNum)171 int GetCommunicationStrategy(RegParams params, PolicyTrans **policies, unsigned int *policyNum)
172 {
173     if (IsUidValid(params.uid) == AUTH_ERRORCODE_INVALID_UID) {
174         HILOG_ERROR(HILOG_MODULE_APP, "Invalid uid, [svc: %s][ft: %s][uid:%u][pid: %u][line: %d]",
175                     params.service, params.feature, params.uid, params.pid, __LINE__);
176         return AUTH_ERRORCODE_INVALID_UID;
177     }
178 
179     int res = SetPresetPolicies(g_presetPolicies, g_presetPolicySize, params, policies, policyNum);
180     if (res != AUTH_ERRORCODE_POLICY_NOT_FOUND) {
181         return res;
182     }
183 #if  POLICY_PRODUCT
184     res = SetPresetPolicies(g_productPolicies, g_productPolicySize, params, policies, policyNum);
185     if (res != AUTH_ERRORCODE_POLICY_NOT_FOUND) {
186         return res;
187     }
188 #endif
189     res = SetPresetPolicies(g_registryPolicies, g_regPoliciesSize, params, policies, policyNum);
190     if (res != AUTH_ERRORCODE_POLICY_NOT_FOUND) {
191         return res;
192     }
193     return AUTH_ERRORCODE_NO_POLICY_SET;
194 }
195 
IsUidFixed(const int fixedUid[],unsigned int consumerUid)196 static int IsUidFixed(const int fixedUid[], unsigned int consumerUid)
197 {
198     for (int m = 0; m < UID_SIZE; m++) {
199         if (fixedUid[m] == consumerUid) {
200             return AUTH_ERRORCODE_SUCCESS;
201         }
202     }
203     return AUTH_ERRORCODE_ACCESS_DENIED;
204 }
205 
CheckPolicy(const IpcPolicy * policy,unsigned int consumerUid)206 static int CheckPolicy(const IpcPolicy *policy, unsigned int consumerUid)
207 {
208     switch (policy->type) {
209         case RANGE:
210             if (consumerUid >= policy->uidMin && consumerUid <= policy->uidMax) {
211                 return AUTH_ERRORCODE_SUCCESS;
212             }
213             break;
214         case FIXED:
215             if (IsUidFixed(policy->fixedUid, consumerUid) == AUTH_ERRORCODE_SUCCESS) {
216                 return AUTH_ERRORCODE_SUCCESS;
217             }
218             break;
219 #ifdef OHOS_APPFWK_ENABLE
220         case BUNDLENAME: {
221             unsigned int uid = 0;
222             int ret = GetUidByBundleName(policy->bundleName, &uid);
223             if (ret != AUTH_ERRORCODE_SUCCESS) {
224                 return ret;
225             }
226             if (uid == consumerUid) {
227                 return AUTH_ERRORCODE_SUCCESS;
228             }
229             break;
230         }
231 #endif
232         default:
233             break;
234     }
235     return AUTH_ERRORCODE_ACCESS_DENIED;
236 }
237 
CheckFeaturePolicies(const FeaturePolicy * featurePolicy,unsigned int consumerUid)238 static int CheckFeaturePolicies(const FeaturePolicy *featurePolicy, unsigned int consumerUid)
239 {
240     for (int k = 0; k < POLICY_SIZE; k++) {
241         IpcPolicy policy = featurePolicy->policies[k];
242         int ret = CheckPolicy(&policy, consumerUid);
243         if (ret == AUTH_ERRORCODE_SUCCESS) {
244             return ret;
245         }
246     }
247     return AUTH_ERRORCODE_ACCESS_DENIED;
248 }
249 
CheckSvcPolicies(const PolicySetting policySetting[],int policySize,const AuthParams * params)250 static int CheckSvcPolicies(const PolicySetting policySetting[], int policySize, const AuthParams *params)
251 {
252     for (int i = 0; i < policySize; i++) {
253         if (strcmp(policySetting[i].service, params->providerService) != 0) {
254             continue;
255         }
256         for (int j = 0; j < policySetting[i].featureNum; j++) {
257             FeaturePolicy *featurePolicy = (FeaturePolicy *)policySetting[i].features + j;
258             char *s1 = featurePolicy->feature;
259             char *s2 = params->providerfeature;
260             if (StrcmpWithNull(s1, s2) != 0) {
261                 continue;
262             }
263             int ret = CheckFeaturePolicies(featurePolicy, params->consumerUid);
264             if (ret == AUTH_ERRORCODE_SUCCESS) {
265                 return ret;
266             }
267             break;
268         }
269         break;
270     }
271     return AUTH_ERRORCODE_ACCESS_DENIED;
272 }
273 
IsCommunicationAllowed(AuthParams params)274 int IsCommunicationAllowed(AuthParams params)
275 {
276     if (CheckSvcPolicies(g_presetPolicies, g_presetPolicySize, &params) == AUTH_ERRORCODE_SUCCESS) {
277         return AUTH_ERRORCODE_SUCCESS;
278     }
279 #if  POLICY_PRODUCT
280     if (CheckSvcPolicies(g_productPolicies, g_productPolicySize, &params) == AUTH_ERRORCODE_SUCCESS) {
281         return AUTH_ERRORCODE_SUCCESS;
282     }
283 #endif
284     if (CheckSvcPolicies(g_registryPolicies, g_regPoliciesSize, &params) == AUTH_ERRORCODE_SUCCESS) {
285         return AUTH_ERRORCODE_SUCCESS;
286     }
287 
288     HILOG_ERROR(HILOG_MODULE_APP,
289         "Access denied, [consumerUid: %u][consumerPid: %u][providerUid:%u][providerPid: %u][line: %d]",
290         params.consumerUid, params.consumerPid, params.providerUid, params.providerPid, __LINE__);
291     return AUTH_ERRORCODE_ACCESS_DENIED;
292 }
293