1 /*
2  * Copyright (c) 2023 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 #include "sec_comp_info_helper.h"
16 
17 #include "accesstoken_kit.h"
18 #include "display.h"
19 #include "display_info.h"
20 #include "display_manager.h"
21 #include "location_button.h"
22 #include "paste_button.h"
23 #include "save_button.h"
24 #include "sec_comp_err.h"
25 #include "sec_comp_log.h"
26 #include "sec_comp_service.h"
27 #include "sec_comp_tool.h"
28 #include "window_info_helper.h"
29 
30 namespace OHOS {
31 namespace Security {
32 namespace SecurityComponent {
33 namespace {
34 constexpr OHOS::HiviewDFX::HiLogLabel LABEL = {LOG_CORE, SECURITY_DOMAIN_SECURITY_COMPONENT, "SecCompInfoHelper"};
35 static constexpr double MAX_RECT_PERCENT = 0.1F; // 10%
36 static constexpr double ZERO_OFFSET = 0.0F;
37 static std::mutex g_renderLock;
38 }
39 
AdjustSecCompRect(SecCompBase * comp,float scale)40 void SecCompInfoHelper::AdjustSecCompRect(SecCompBase* comp, float scale)
41 {
42     comp->rect_.width_ *= scale;
43     comp->rect_.height_ *= scale;
44     comp->rect_.x_ = comp->windowRect_.x_ + (comp->rect_.x_ - comp->windowRect_.x_) * scale;
45     comp->rect_.y_ = comp->windowRect_.y_ + (comp->rect_.y_ - comp->windowRect_.y_) * scale;
46 
47     SC_LOG_DEBUG(LABEL, "After adjust x %{public}f, y %{public}f, width %{public}f, height %{public}f",
48         comp->rect_.x_, comp->rect_.y_, comp->rect_.width_, comp->rect_.height_);
49 }
50 
ParseComponent(SecCompType type,const nlohmann::json & jsonComponent)51 SecCompBase* SecCompInfoHelper::ParseComponent(SecCompType type, const nlohmann::json& jsonComponent)
52 {
53     SecCompBase* comp = nullptr;
54     switch (type) {
55         case LOCATION_COMPONENT:
56             comp = ConstructComponent<LocationButton>(jsonComponent);
57             break;
58         case PASTE_COMPONENT:
59             comp = ConstructComponent<PasteButton>(jsonComponent);
60             break;
61         case SAVE_COMPONENT:
62             comp = ConstructComponent<SaveButton>(jsonComponent);
63             break;
64         default:
65             SC_LOG_ERROR(LABEL, "Parse component type unknown");
66             break;
67     }
68     if (comp == nullptr) {
69         SC_LOG_ERROR(LABEL, "Parse component failed");
70         return comp;
71     }
72 
73     comp->SetValid(CheckComponentValid(comp));
74     return comp;
75 }
76 
GetScreenSize(double & width,double & height)77 static bool GetScreenSize(double& width, double& height)
78 {
79     sptr<OHOS::Rosen::Display> display =
80         OHOS::Rosen::DisplayManager::GetInstance().GetDefaultDisplaySync();
81     if (display == nullptr) {
82         SC_LOG_ERROR(LABEL, "Get display manager failed");
83         return false;
84     }
85 
86     auto info = display->GetDisplayInfo();
87     if (info == nullptr) {
88         SC_LOG_ERROR(LABEL, "Get display info failed");
89         return false;
90     }
91 
92     width = static_cast<double>(info->GetWidth());
93     height = static_cast<double>(info->GetHeight());
94     SC_LOG_DEBUG(LABEL, "display manager Screen width %{public}f height %{public}f",
95         width, height);
96     return true;
97 }
98 
CheckRectValid(const SecCompRect & rect,const SecCompRect & windowRect)99 bool SecCompInfoHelper::CheckRectValid(const SecCompRect& rect, const SecCompRect& windowRect)
100 {
101     double curScreenWidth = 0.0F;
102     double curScreenHeight = 0.0F;
103     if (!GetScreenSize(curScreenWidth, curScreenHeight)) {
104         SC_LOG_ERROR(LABEL, "Get screen size is invalid");
105         return false;
106     }
107 
108     if (GreatOrEqual(0.0, rect.width_) || GreatOrEqual(0.0, rect.height_)) {
109         SC_LOG_ERROR(LABEL, "width or height is <= 0");
110         return false;
111     }
112 
113     if (GreatNotEqual(ZERO_OFFSET, rect.x_) || GreatNotEqual(ZERO_OFFSET, rect.y_) ||
114         GreatNotEqual(rect.x_, curScreenWidth) || GreatNotEqual(rect.y_, curScreenHeight)) {
115         SC_LOG_ERROR(LABEL, "SecurityComponentCheckFail: security component is out of screen");
116         return false;
117     }
118 
119     if (GreatOrEqual((rect.x_ + rect.width_), curScreenWidth) ||
120         GreatOrEqual((rect.y_ + rect.height_), curScreenHeight)) {
121         SC_LOG_ERROR(LABEL, "SecurityComponentCheckFail: security component is out of screen");
122         return false;
123     }
124 
125     if (GreatNotEqual(windowRect.x_, rect.x_) || GreatNotEqual(windowRect.y_, rect.y_) ||
126         GreatNotEqual(rect.x_ + rect.width_, windowRect.x_ + windowRect.width_) ||
127         GreatNotEqual(rect.y_ + rect.height_, windowRect.y_ + windowRect.height_)) {
128         SC_LOG_ERROR(LABEL, "SecurityComponentCheckFail: security component is out of window");
129         return false;
130     }
131 
132     // check rect > 10%
133     if (GreatOrEqual((rect.width_ * rect.height_), (curScreenWidth * curScreenHeight * MAX_RECT_PERCENT))) {
134         SC_LOG_ERROR(LABEL, "SecurityComponentCheckFail: security component is larger than 10 percent of screen");
135         return false;
136     }
137     SC_LOG_DEBUG(LABEL, "check component rect success.");
138     return true;
139 }
140 
CheckSecCompBaseButton(const SecCompBase * comp)141 static bool CheckSecCompBaseButton(const SecCompBase* comp)
142 {
143     if ((comp->text_ < 0) && (comp->icon_ < 0)) {
144         SC_LOG_INFO(LABEL, "both text and icon do not exist.");
145         return false;
146     }
147     if (comp->text_ >= 0) {
148         DimensionT minFontSize;
149         if (comp->icon_ >= 0) {
150             minFontSize = MIN_FONT_SIZE_WITH_ICON;
151         } else {
152             minFontSize = MIN_FONT_SIZE_WITHOUT_ICON;
153         }
154 
155         if (comp->fontSize_ < minFontSize) {
156             SC_LOG_INFO(LABEL, "SecurityComponentCheckFail: fontSize is too small.");
157             return false;
158         }
159     }
160     if ((comp->icon_ >= 0) && comp->iconSize_ < MIN_ICON_SIZE) {
161         SC_LOG_INFO(LABEL, "SecurityComponentCheckFail: iconSize is too small.");
162         return false;
163     }
164 
165     if ((comp->bg_ != SecCompBackground::NO_BG_TYPE) && !IsColorFullTransparent(comp->bgColor_) &&
166         (((comp->text_ != NO_TEXT) && (IsColorSimilar(comp->fontColor_, comp->bgColor_))) ||
167         ((comp->icon_ != NO_ICON) && (IsColorSimilar(comp->iconColor_, comp->bgColor_))))) {
168         SC_LOG_INFO(LABEL, "SecurityComponentCheckFail: fontColor or iconColor is similar with backgroundColor.");
169         return false;
170     }
171 
172     if (comp->bg_ == SecCompBackground::NO_BG_TYPE &&
173         ((comp->padding_.top != MIN_PADDING_WITHOUT_BG) || (comp->padding_.right != MIN_PADDING_WITHOUT_BG) ||
174         (comp->padding_.bottom != MIN_PADDING_WITHOUT_BG) || (comp->padding_.left != MIN_PADDING_WITHOUT_BG))) {
175         SC_LOG_INFO(LABEL, "padding can not change without background.");
176         return false;
177     }
178 
179     return true;
180 }
181 
CheckSecCompBase(const SecCompBase * comp)182 static bool CheckSecCompBase(const SecCompBase* comp)
183 {
184     if (comp->parentEffect_) {
185         SC_LOG_ERROR(LABEL,
186             "SecurityComponentCheckFail: the parents of security component have invalid effect.");
187         return false;
188     }
189 
190     if ((comp->padding_.top < MIN_PADDING_SIZE) || (comp->padding_.right < MIN_PADDING_SIZE) ||
191         (comp->padding_.bottom < MIN_PADDING_SIZE) || (comp->padding_.left < MIN_PADDING_SIZE) ||
192         (comp->textIconSpace_ < MIN_PADDING_SIZE)) {
193         SC_LOG_ERROR(LABEL, "SecurityComponentCheckFail: padding or textIconSpace is too small.");
194         return false;
195     }
196 
197     if (((comp->text_ != NO_TEXT) && (IsColorTransparent(comp->fontColor_))) ||
198         ((comp->icon_ != NO_ICON) && (IsColorTransparent(comp->iconColor_)))) {
199         SC_LOG_ERROR(LABEL, "SecurityComponentCheckFail: fontColor or iconColor is too transparent.");
200         return false;
201     }
202     if (!CheckSecCompBaseButton(comp)) {
203         return false;
204     }
205     return true;
206 }
207 
CheckComponentValid(SecCompBase * comp)208 bool SecCompInfoHelper::CheckComponentValid(SecCompBase* comp)
209 {
210     if ((comp == nullptr) || !IsComponentTypeValid(comp->type_)) {
211         SC_LOG_INFO(LABEL, "comp is null or type is invalid.");
212         return false;
213     }
214 
215     float scale = WindowInfoHelper::GetWindowScale(comp->windowId_);
216     SC_LOG_DEBUG(LABEL, "WindowScale = %{public}f", scale);
217     if (!IsEqual(scale, WindowInfoHelper::FULL_SCREEN_SCALE) && !IsEqual(scale, 0.0)) {
218         AdjustSecCompRect(comp, scale);
219     }
220 
221     if (!CheckSecCompBase(comp)) {
222         SC_LOG_INFO(LABEL, "SecComp base is invalid.");
223         return false;
224     }
225 
226     return true;
227 }
228 
GrantTempPermission(AccessToken::AccessTokenID tokenId,const std::shared_ptr<SecCompBase> & componentInfo)229 int32_t SecCompInfoHelper::GrantTempPermission(AccessToken::AccessTokenID tokenId,
230     const std::shared_ptr<SecCompBase>& componentInfo)
231 {
232     if ((tokenId <= 0) || (componentInfo == nullptr)) {
233         SC_LOG_ERROR(LABEL, "Grant component is null");
234         return SC_SERVICE_ERROR_PERMISSION_OPER_FAIL;
235     }
236 
237     SecCompType type = componentInfo->type_;
238     int32_t res;
239     switch (type) {
240         case LOCATION_COMPONENT:
241             {
242                 res = SecCompPermManager::GetInstance().GrantAppPermission(tokenId,
243                     "ohos.permission.APPROXIMATELY_LOCATION");
244                 if (res != SC_OK) {
245                     return SC_SERVICE_ERROR_PERMISSION_OPER_FAIL;
246                 }
247                 res = SecCompPermManager::GetInstance().GrantAppPermission(tokenId, "ohos.permission.LOCATION");
248                 if (res != SC_OK) {
249                     SecCompPermManager::GetInstance().RevokeAppPermission(
250                         tokenId, "ohos.permission.APPROXIMATELY_LOCATION");
251                     return SC_SERVICE_ERROR_PERMISSION_OPER_FAIL;
252                 }
253                 SC_LOG_INFO(LABEL, "Grant location permission, scid = %{public}d.", componentInfo->nodeId_);
254                 return SC_OK;
255             }
256         case PASTE_COMPONENT:
257             res = SecCompPermManager::GetInstance().GrantAppPermission(tokenId, "ohos.permission.SECURE_PASTE");
258             if (res != SC_OK) {
259                 return SC_SERVICE_ERROR_PERMISSION_OPER_FAIL;
260             }
261             SC_LOG_INFO(LABEL, "Grant paste permission, scid = %{public}d.", componentInfo->nodeId_);
262             return SC_OK;
263         case SAVE_COMPONENT:
264             if (IsDlpSandboxCalling(tokenId)) {
265                 SC_LOG_INFO(LABEL, "Dlp sandbox app are not allowed to use save component.");
266                 return SC_SERVICE_ERROR_PERMISSION_OPER_FAIL;
267             }
268             SC_LOG_INFO(LABEL, "Grant save permission, scid = %{public}d.", componentInfo->nodeId_);
269             return SecCompPermManager::GetInstance().GrantTempSavePermission(tokenId);
270         default:
271             SC_LOG_ERROR(LABEL, "Parse component type unknown");
272             break;
273     }
274     return SC_SERVICE_ERROR_PERMISSION_OPER_FAIL;
275 }
276 
IsDlpSandboxCalling(AccessToken::AccessTokenID tokenId)277 inline bool SecCompInfoHelper::IsDlpSandboxCalling(AccessToken::AccessTokenID tokenId)
278 {
279     return AccessToken::AccessTokenKit::GetHapDlpFlag(tokenId) != 0;
280 }
281 }  // namespace SecurityComponent
282 }  // namespace Security
283 }  // namespace OHOS
284