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 
16 #include "security_mode_parser.h"
17 
18 #include <algorithm>
19 #include <chrono>
20 #include <ctime>
21 #include <iomanip>
22 #include <sstream>
23 
24 #include "full_ime_info_manager.h"
25 #include "ime_info_inquirer.h"
26 #include "input_method_utils.h"
27 #include "iservice_registry.h"
28 #include "serializable.h"
29 #include "settings_data_utils.h"
30 #include "sys_cfg_parser.h"
31 #include "system_ability_definition.h"
32 namespace OHOS {
33 namespace MiscServices {
34 std::mutex SecurityModeParser::instanceMutex_;
35 sptr<SecurityModeParser> SecurityModeParser::instance_ = nullptr;
36 constexpr const char *SYSTEM_SPECIAL_IME = "";
~SecurityModeParser()37 SecurityModeParser::~SecurityModeParser()
38 {
39 }
40 
GetInstance()41 sptr<SecurityModeParser> SecurityModeParser::GetInstance()
42 {
43     if (instance_ == nullptr) {
44         std::lock_guard<std::mutex> autoLock(instanceMutex_);
45         if (instance_ == nullptr) {
46             IMSA_HILOGI("need to create SecurityModeParser.");
47             instance_ = new (std::nothrow) SecurityModeParser();
48             if (instance_ == nullptr) {
49                 IMSA_HILOGE("instance is nullptr.");
50                 return instance_;
51             }
52         }
53     }
54     return instance_;
55 }
56 
Initialize(const int32_t userId)57 int32_t SecurityModeParser::Initialize(const int32_t userId)
58 {
59     return UpdateFullModeList(userId);
60 }
61 
UpdateFullModeList(int32_t userId)62 int32_t SecurityModeParser::UpdateFullModeList(int32_t userId)
63 {
64     IMSA_HILOGD("key: %{public}s.", SECURITY_MODE);
65     std::string valueStr;
66     int32_t ret = SettingsDataUtils::GetInstance()->GetStringValue(SETTING_URI_PROXY, SECURITY_MODE, valueStr);
67     if (ret != ErrorCode::NO_ERROR || valueStr.empty()) {
68         IMSA_HILOGW("get value failed, or valueStr is empty");
69         return ErrorCode::ERROR_ENABLE_SECURITY_MODE;
70     }
71 
72     if (!ParseSecurityMode(valueStr, userId)) {
73         IMSA_HILOGE("parse %{public}s failed by %{public}d", valueStr.c_str(), userId);
74         return ErrorCode::ERROR_ENABLE_SECURITY_MODE;
75     }
76     return ErrorCode::NO_ERROR;
77 }
78 
ParseSecurityMode(const std::string & valueStr,const int32_t userId)79 bool SecurityModeParser::ParseSecurityMode(const std::string &valueStr, const int32_t userId)
80 {
81     SecModeCfg secModeCfg;
82     secModeCfg.userImeCfg.userId = std::to_string(userId);
83     auto ret = secModeCfg.Unmarshall(valueStr);
84     if (!ret) {
85         IMSA_HILOGE("unmarshall failed!");
86         return ret;
87     }
88     std::lock_guard<std::mutex> autoLock(listMutex_);
89     fullModeList_ = secModeCfg.userImeCfg.identities;
90     return true;
91 }
92 
GetSecurityMode(const std::string & bundleName,int32_t userId)93 SecurityMode SecurityModeParser::GetSecurityMode(const std::string &bundleName, int32_t userId)
94 {
95     if (bundleName == SYSTEM_SPECIAL_IME) {
96         return SecurityMode::FULL;
97     }
98     if (!initialized_) {
99         std::lock_guard<std::mutex> lock(initLock_);
100         if (!initialized_) {
101             UpdateFullModeList(userId);
102             initialized_ = true;
103         }
104     }
105     if (IsFullMode(bundleName)) {
106         return SecurityMode::FULL;
107     } else {
108         return SecurityMode::BASIC;
109     }
110 }
111 
IsFullMode(std::string bundleName)112 bool SecurityModeParser::IsFullMode(std::string bundleName)
113 {
114     std::lock_guard<std::mutex> autoLock(listMutex_);
115     auto it = std::find_if(fullModeList_.begin(), fullModeList_.end(), [&bundleName](const std::string& bundle) {
116         return bundle == bundleName;
117     });
118     return it != fullModeList_.end();
119 }
120 
IsDefaultFullMode(const std::string & bundleName,int32_t userId)121 bool SecurityModeParser::IsDefaultFullMode(const std::string &bundleName, int32_t userId)
122 {
123     auto defaultIme = ImeInfoInquirer::GetInstance().GetDefaultImeCfgProp();
124     if (defaultIme != nullptr && bundleName == defaultIme->name) {
125         return true;
126     }
127     std::string appId;
128     uint32_t versionCode;
129     if (!ImeInfoInquirer::GetInstance().GetImeAppId(userId, bundleName, appId)
130         || !ImeInfoInquirer::GetInstance().GetImeVersionCode(userId, bundleName, versionCode)) {
131         IMSA_HILOGE("%{public}s failed to get appId and versionCode", bundleName.c_str());
132         return false;
133     }
134     std::vector<DefaultFullImeInfo> defaultFullImeList;
135     if (!SysCfgParser::ParseDefaultFullIme(defaultFullImeList)) {
136         IMSA_HILOGE("failed to parse config");
137         return false;
138     }
139     auto ime = std::find_if(defaultFullImeList.begin(), defaultFullImeList.end(),
140         [&appId](const auto &ime) { return ime.appId == appId; });
141     if (ime == defaultFullImeList.end()) {
142         IMSA_HILOGD("not default FULL");
143         return false;
144     }
145     bool isDefaultFull = false;
146     if (ime->expirationVersionCode > 0) {
147         isDefaultFull = !IsExpired(ime->expirationTime) || versionCode < ime->expirationVersionCode;
148     } else {
149         isDefaultFull = !IsExpired(ime->expirationTime);
150     }
151     IMSA_HILOGI("ime: %{public}s, isDefaultFull: %{public}d", bundleName.c_str(), isDefaultFull);
152     return isDefaultFull;
153 }
154 
IsExpired(const std::string & expirationTime)155 bool SecurityModeParser::IsExpired(const std::string &expirationTime)
156 {
157     std::istringstream expirationTimeStr(expirationTime);
158     std::tm expTime = {};
159     expirationTimeStr >> std::get_time(&expTime, "%Y-%m-%d %H:%M:%S");
160     if (expirationTimeStr.fail()) {
161         IMSA_HILOGE("get time error, expirationTime: %{public}s", expirationTime.c_str());
162         return false;
163     }
164     auto expTimePoint = std::chrono::system_clock::from_time_t(std::mktime(&expTime));
165     auto now = std::chrono::system_clock::now();
166     return expTimePoint < now;
167 }
168 } // namespace MiscServices
169 } // namespace OHOS