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 #include <algorithm>
17 #include <cstdint>
18 #include <tuple>
19 #include "app_domain_verify_mgr_client.h"
20 #include "datetime_ex.h"
21 #include "inner_verify_status.h"
22 #include "verify_task.h"
23 #include "domain_verifier.h"
24 #include "app_domain_verify_hilog.h"
25 #include "bundle_verify_status_info.h"
26 #include "agent_constants.h"
27 #include "domain_url_util.h"
28 #include "app_domain_verify_task_mgr.h"
29 #include "verify_http_task.h"
30 
31 namespace OHOS {
32 namespace AppDomainVerify {
33 const std::string HTTPS = "https";
34 const std::set<std::string> SCHEME_WHITE_SET = { HTTPS };
35 const std::string FUZZY_HOST_START = "*.";
36 const static int CLIENT_ERR_MAX_RETRY_COUNTS = 7; // 7 times for max retry count
37 const static int CLIENT_ERR_BASE_RETRY_DURATION_S = 3600; // 1h for base duration
OnPostVerify(const std::string & uri,const OHOS::NetStack::HttpClient::HttpClientResponse & response)38 void VerifyTask::OnPostVerify(const std::string& uri, const OHOS::NetStack::HttpClient::HttpClientResponse& response)
39 {
40     APP_DOMAIN_VERIFY_HILOGI(APP_DOMAIN_VERIFY_AGENT_MODULE_SERVICE, "called");
41     auto status = DomainVerifier::VerifyHost(response.GetResponseCode(), response.GetResult(), appVerifyBaseInfo_);
42     UpdateVerifyResultInfo(uri, status);
43     unVerifiedSet_.erase(uri);
44     if (unVerifiedSet_.empty()) {
45         OnSaveVerifyResult();
46     }
47     VERIFY_RESULT_EVENT(appVerifyBaseInfo_.appIdentifier, appVerifyBaseInfo_.bundleName, type_, status);
48 }
49 
OnSaveVerifyResult()50 void VerifyTask::OnSaveVerifyResult()
51 {
52     APP_DOMAIN_VERIFY_HILOGI(APP_DOMAIN_VERIFY_AGENT_MODULE_SERVICE, "called");
53     if (!SaveDomainVerifyStatus(appVerifyBaseInfo_.bundleName, verifyResultInfo_)) {
54         APP_DOMAIN_VERIFY_HILOGE(APP_DOMAIN_VERIFY_AGENT_MODULE_SERVICE, "SaveVerifyResult failed");
55     }
56     APP_DOMAIN_VERIFY_HILOGI(APP_DOMAIN_VERIFY_AGENT_MODULE_SERVICE, "call end");
57 }
OnPreRequest(OHOS::NetStack::HttpClient::HttpClientRequest & request,const std::string & uri)58 bool VerifyTask::OnPreRequest(OHOS::NetStack::HttpClient::HttpClientRequest& request, const std::string& uri)
59 {
60     APP_DOMAIN_VERIFY_HILOGI(APP_DOMAIN_VERIFY_AGENT_MODULE_SERVICE, "called");
61     request.SetURL(uri + ApplinkingAssetKeys::ASSET_PATH + ApplinkingAssetKeys::ASSET_NAME);
62     request.SetMethod("GET");
63     return true;
64 }
GetType()65 OHOS::AppDomainVerify::TaskType VerifyTask::GetType()
66 {
67     return type_;
68 }
GetUriVerifyMap()69 const HostVerifyStatusMap& VerifyTask::GetUriVerifyMap()
70 {
71     return verifyResultInfo_.hostVerifyStatusMap;
72 }
InitUriUnVerifySetMap(const VerifyResultInfo & verifyResultInfo)73 void VerifyTask::InitUriUnVerifySetMap(const VerifyResultInfo& verifyResultInfo)
74 {
75     APP_DOMAIN_VERIFY_HILOGD(APP_DOMAIN_VERIFY_AGENT_MODULE_SERVICE, "called");
76     for (const auto& hostVerifyStatusInfo : verifyResultInfo.hostVerifyStatusMap) {
77         if (IsNeedRetry(hostVerifyStatusInfo.second)) {
78             unVerifiedSet_.insert(hostVerifyStatusInfo.first);
79         }
80     }
81 
82     APP_DOMAIN_VERIFY_HILOGD(APP_DOMAIN_VERIFY_AGENT_MODULE_SERVICE, "call end");
83 }
84 
VerifyTask(OHOS::AppDomainVerify::TaskType type,const AppVerifyBaseInfo & appVerifyBaseInfo,const VerifyResultInfo & verifyResultInfo)85 VerifyTask::VerifyTask(OHOS::AppDomainVerify::TaskType type, const AppVerifyBaseInfo& appVerifyBaseInfo,
86     const VerifyResultInfo& verifyResultInfo)
87     : type_(type), appVerifyBaseInfo_(appVerifyBaseInfo), verifyResultInfo_(verifyResultInfo)
88 {
89     staHandlerMap[STATE_SUCCESS] = [this](std::string time, int cnt)->bool {
90         return HandleStateSuccess(time, cnt);
91     };
92     staHandlerMap[FAILURE_CLIENT_ERROR] = [this](std::string time, int cnt)->bool {
93         return HandleFailureClientError(time, cnt);
94     };
95     staHandlerMap[FORBIDDEN_FOREVER] = [this](std::string time, int cnt)->bool {
96         return HandleForbiddenForever(time, cnt);
97     };
98     InitUriUnVerifySetMap(verifyResultInfo);
99 }
100 
GetTaskType()101 OHOS::AppDomainVerify::TaskType& VerifyTask::GetTaskType()
102 {
103     return type_;
104 }
GetAppVerifyBaseInfo()105 AppVerifyBaseInfo& VerifyTask::GetAppVerifyBaseInfo()
106 {
107     return appVerifyBaseInfo_;
108 }
109 
SaveDomainVerifyStatus(const std::string & bundleName,const VerifyResultInfo & verifyResultInfo)110 bool VerifyTask::SaveDomainVerifyStatus(const std::string& bundleName, const VerifyResultInfo& verifyResultInfo)
111 {
112     return AppDomainVerifyMgrClient::GetInstance()->SaveDomainVerifyStatus(bundleName, verifyResultInfo);
113 }
114 
Execute()115 void VerifyTask::Execute()
116 {
117     for (auto& hostVerifyStatusInfo : verifyResultInfo_.hostVerifyStatusMap) {
118         if (unVerifiedSet_.count(hostVerifyStatusInfo.first) != 0) {
119             auto verifyHttpTask = std::make_shared<VerifyHttpTask>(hostVerifyStatusInfo.first, shared_from_this());
120             AppDomainVerifyTaskMgr::GetInstance()->AddTask(verifyHttpTask);
121         }
122     }
123 }
124 
IsNeedRetry(const std::tuple<InnerVerifyStatus,std::string,int> & info)125 bool VerifyTask::IsNeedRetry(const std::tuple<InnerVerifyStatus, std::string, int>& info)
126 {
127     auto [status, verifyTime, verifyCnt] = info;
128     auto iter = staHandlerMap.find(status);
129     if (iter != staHandlerMap.end()) {
130         return iter->second(verifyTime, verifyCnt);
131     }
132     return true;
133 }
134 
CalcRetryDuration(int verifyCnt)135 int64_t VerifyTask::CalcRetryDuration(int verifyCnt)
136 {
137     int64_t duration = pow(2, verifyCnt) * CLIENT_ERR_BASE_RETRY_DURATION_S; // base * 2 ^ verifyCnt
138     return duration;
139 }
140 
HandleFailureClientError(std::string verifyTime,int verifyCnt)141 bool VerifyTask::HandleFailureClientError(std::string verifyTime, int verifyCnt)
142 {
143     APP_DOMAIN_VERIFY_HILOGD(APP_DOMAIN_VERIFY_MODULE_EXTENSION, "called");
144     if (!verifyTime.empty()) {
145         int64_t currTs = GetSecondsSince1970ToNow();
146         int64_t lastTs{};
147         try {
148             lastTs = static_cast<int64_t>(std::stoll(verifyTime));
149         } catch (...) {
150             APP_DOMAIN_VERIFY_HILOGE(APP_DOMAIN_VERIFY_MODULE_EXTENSION, "get verifyTime error");
151             return false;
152         }
153         int64_t duration = currTs - lastTs;
154         int64_t currRetryDuration = CalcRetryDuration(verifyCnt);
155         if (duration <= currRetryDuration) {
156             APP_DOMAIN_VERIFY_HILOGI(APP_DOMAIN_VERIFY_MODULE_EXTENSION,
157                 "last time:%{public}s, curr time:%{public}s, "
158                 "duration:%{public}s "
159                 "is less than max retry duration:%{public}s, not retry",
160                 std::to_string(lastTs).c_str(),
161                 std::to_string(currTs).c_str(),
162                 std::to_string(duration).c_str(),
163                 std::to_string(currRetryDuration).c_str());
164             return false;
165         }
166     }
167     return true;
168 }
169 
HandleStateSuccess(std::string verifyTime,int verifyCnt)170 bool VerifyTask::HandleStateSuccess(std::string verifyTime, int verifyCnt)
171 {
172     APP_DOMAIN_VERIFY_HILOGD(APP_DOMAIN_VERIFY_MODULE_EXTENSION, "called");
173     return false;
174 }
175 
HandleForbiddenForever(std::string verifyTime,int verifyCnt)176 bool VerifyTask::HandleForbiddenForever(std::string verifyTime, int verifyCnt)
177 {
178     APP_DOMAIN_VERIFY_HILOGD(APP_DOMAIN_VERIFY_MODULE_EXTENSION, "called");
179     return false;
180 }
181 
UpdateVerifyResultInfo(const std::string & uri,InnerVerifyStatus status)182 void VerifyTask::UpdateVerifyResultInfo(const std::string& uri, InnerVerifyStatus status)
183 {
184     auto verifyStatus = status;
185     auto currTs = GetSecondsSince1970ToNow();
186     std::string verifyTs = std::to_string(currTs);
187     int verifyCnt = 0;
188     auto& hostVerifyStatusMap = verifyResultInfo_.hostVerifyStatusMap;
189     auto iter = hostVerifyStatusMap.find(uri);
190     if (iter == hostVerifyStatusMap.end()) {
191         hostVerifyStatusMap.insert_or_assign(uri, std::make_tuple(verifyStatus, verifyTs, verifyCnt));
192         return;
193     }
194     if (verifyStatus == InnerVerifyStatus::FAILURE_CLIENT_ERROR) {
195         std::tie(std::ignore, std::ignore, verifyCnt) = iter->second;
196         verifyCnt++;
197         if (verifyCnt >= CLIENT_ERR_MAX_RETRY_COUNTS) {
198             verifyStatus = InnerVerifyStatus::FORBIDDEN_FOREVER;
199         }
200     }
201     std::get<0>(iter->second) = verifyStatus;
202     std::get<1>(iter->second) = verifyTs;
203     std::get<2>(iter->second) = verifyCnt; // 2 is cnt
204 }
205 
206 }
207 }