1 /*
2 * Copyright (c) 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 "app_account_authenticator_session.h"
17
18 #include <pthread.h>
19 #include <thread>
20 #include "ability_manager_adapter.h"
21 #include "account_info.h"
22 #include "account_log_wrapper.h"
23 #include "app_account_authenticator_callback.h"
24 #include "app_account_authenticator_manager.h"
25 #include "app_account_common.h"
26 #include "bundle_manager_adapter.h"
27 #include "iservice_registry.h"
28
29 namespace OHOS {
30 namespace AccountSA {
31 namespace {
32 const char THREAD_AUTH_SESSION[] = "authSession";
33 }
34
SessionClientDeathRecipient(const std::string & sessionId)35 SessionClientDeathRecipient::SessionClientDeathRecipient(const std::string &sessionId) : sessionId_(sessionId)
36 {}
37
OnRemoteDied(const wptr<IRemoteObject> & remote)38 void SessionClientDeathRecipient::OnRemoteDied(const wptr<IRemoteObject> &remote)
39 {
40 (void)remote;
41 AppAccountAuthenticatorSessionManager::GetInstance().CloseSession(sessionId_);
42 }
43
SessionServerDeathRecipient(const std::string & sessionId)44 SessionServerDeathRecipient::SessionServerDeathRecipient(const std::string &sessionId) : sessionId_(sessionId)
45 {}
46
OnRemoteDied(const wptr<IRemoteObject> & remote)47 void SessionServerDeathRecipient::OnRemoteDied(const wptr<IRemoteObject> &remote)
48 {
49 (void)remote;
50 AppAccountAuthenticatorSessionManager::GetInstance().OnSessionServerDied(sessionId_);
51 }
52
SessionConnection(const std::string & sessionId)53 SessionConnection::SessionConnection(const std::string &sessionId) : sessionId_(sessionId)
54 {}
55
~SessionConnection()56 SessionConnection::~SessionConnection()
57 {}
58
OnAbilityConnectDone(const AppExecFwk::ElementName & element,const sptr<IRemoteObject> & remoteObject,int32_t resultCode)59 void SessionConnection::OnAbilityConnectDone(
60 const AppExecFwk::ElementName &element, const sptr<IRemoteObject> &remoteObject, int32_t resultCode)
61 {
62 AppAccountAuthenticatorSessionManager::GetInstance().OnSessionAbilityConnectDone(
63 sessionId_, element, remoteObject, resultCode);
64 }
65
OnAbilityDisconnectDone(const AppExecFwk::ElementName & element,int resultCode)66 void SessionConnection::OnAbilityDisconnectDone(const AppExecFwk::ElementName &element, int resultCode)
67 {
68 AppAccountAuthenticatorSessionManager::GetInstance().OnSessionAbilityDisconnectDone(
69 sessionId_, element, resultCode);
70 }
71
AppAccountAuthenticatorSession(AuthenticatorAction action,const AuthenticatorSessionRequest & request)72 AppAccountAuthenticatorSession::AppAccountAuthenticatorSession(
73 AuthenticatorAction action, const AuthenticatorSessionRequest &request)
74 : action_(action), request_(request)
75 {
76 Init();
77 }
78
~AppAccountAuthenticatorSession()79 AppAccountAuthenticatorSession::~AppAccountAuthenticatorSession()
80 {
81 if (isOpened_) {
82 Close();
83 }
84 }
85
Init()86 void AppAccountAuthenticatorSession::Init()
87 {
88 if (isInitialized_) {
89 ACCOUNT_LOGE("session has been initialized");
90 return;
91 }
92
93 sessionId_ = std::to_string(reinterpret_cast<int64_t>(this));
94 conn_ = new (std::nothrow) SessionConnection(sessionId_);
95 clientDeathRecipient_ = new (std::nothrow) SessionClientDeathRecipient(sessionId_);
96 serverDeathRecipient_ = new (std::nothrow) SessionServerDeathRecipient(sessionId_);
97 authenticatorCb_ = new (std::nothrow) AppAccountAuthenticatorCallback(sessionId_);
98 if ((conn_ == nullptr) || (clientDeathRecipient_ == nullptr)
99 || (serverDeathRecipient_ == nullptr) || (authenticatorCb_ == nullptr)) {
100 conn_ = nullptr;
101 clientDeathRecipient_ = nullptr;
102 serverDeathRecipient_ = nullptr;
103 authenticatorCb_ = nullptr;
104 return;
105 }
106 userId_ = request_.callerUid / UID_TRANSFORM_DIVISOR;
107 ownerUid_ = BundleManagerAdapter::GetInstance()->GetUidByBundleName(request_.owner, userId_);
108 isInitialized_ = true;
109 }
110
Open()111 ErrCode AppAccountAuthenticatorSession::Open()
112 {
113 if (isOpened_) {
114 ACCOUNT_LOGD("session has been opened");
115 return ERR_APPACCOUNT_SERVICE_OAUTH_SERVICE_EXCEPTION;
116 }
117 if (!isInitialized_) {
118 ACCOUNT_LOGD("session has not been initialized");
119 return ERR_APPACCOUNT_SERVICE_OAUTH_SERVICE_EXCEPTION;
120 }
121 AuthenticatorInfo info;
122 ErrCode errCode = AppAccountAuthenticatorManager::GetAuthenticatorInfo(request_.owner, userId_, info);
123 if (errCode != ERR_OK) {
124 ACCOUNT_LOGE("authenticator not exist, owner: %{public}s, errCode: %{public}d.",
125 request_.owner.c_str(), errCode);
126 return errCode;
127 }
128 AAFwk::Want want;
129 want.SetElementName(request_.owner, info.abilityName);
130 auto task = [want, this] {
131 AbilityManagerAdapter::GetInstance()->ConnectAbility(want, this->conn_, nullptr, this->userId_);
132 };
133 std::thread taskThread(task);
134 pthread_setname_np(taskThread.native_handle(), THREAD_AUTH_SESSION);
135 taskThread.detach();
136 isOpened_ = true;
137 return ERR_OK;
138 }
139
Close()140 void AppAccountAuthenticatorSession::Close()
141 {
142 std::lock_guard<std::mutex> lock(mutex_);
143 if ((authenticatorProxy_ != nullptr) && (authenticatorProxy_->AsObject() != nullptr)) {
144 authenticatorProxy_->AsObject()->RemoveDeathRecipient(serverDeathRecipient_);
145 }
146 if ((request_.callback != nullptr) && (request_.callback->AsObject() != nullptr)) {
147 request_.callback->AsObject()->RemoveDeathRecipient(clientDeathRecipient_);
148 }
149 if (isConnected_) {
150 AbilityManagerAdapter::GetInstance()->DisconnectAbility(conn_);
151 }
152 isOpened_ = false;
153 }
154
CloseSelf() const155 void AppAccountAuthenticatorSession::CloseSelf() const
156 {
157 AppAccountAuthenticatorSessionManager::GetInstance().CloseSession(sessionId_);
158 }
159
AddClientDeathRecipient()160 ErrCode AppAccountAuthenticatorSession::AddClientDeathRecipient()
161 {
162 if (!isOpened_) {
163 return ERR_APPACCOUNT_SERVICE_OAUTH_SERVICE_EXCEPTION;
164 }
165 if ((request_.callback == nullptr) || (request_.callback->AsObject() == nullptr)) {
166 return ERR_OK;
167 }
168 bool result = request_.callback->AsObject()->AddDeathRecipient(clientDeathRecipient_);
169 if (!result) {
170 return ERR_APPACCOUNT_SERVICE_OAUTH_SERVICE_EXCEPTION;
171 }
172 return ERR_OK;
173 }
174
OnAbilityConnectDone(const AppExecFwk::ElementName & element,const sptr<IRemoteObject> & remoteObject,int32_t resultCode)175 void AppAccountAuthenticatorSession::OnAbilityConnectDone(
176 const AppExecFwk::ElementName &element, const sptr<IRemoteObject> &remoteObject, int32_t resultCode)
177 {
178 std::lock_guard<std::mutex> lock(mutex_);
179 isConnected_ = true;
180 AAFwk::Want errResult;
181 authenticatorProxy_ = iface_cast<IAppAccountAuthenticator>(remoteObject);
182 if ((!authenticatorProxy_) || (!authenticatorProxy_->AsObject())) {
183 OnResult(ERR_JS_ACCOUNT_AUTHENTICATOR_SERVICE_EXCEPTION, errResult);
184 return;
185 }
186 authenticatorProxy_->AsObject()->AddDeathRecipient(serverDeathRecipient_);
187 switch (action_) {
188 case ADD_ACCOUNT_IMPLICITLY:
189 resultCode = authenticatorProxy_->AddAccountImplicitly(request_.authType, request_.callerBundleName,
190 request_.options.GetParams(), authenticatorCb_->AsObject());
191 break;
192 case AUTHENTICATE:
193 resultCode = authenticatorProxy_->Authenticate(request_.name, request_.authType, request_.callerBundleName,
194 request_.options.GetParams(), authenticatorCb_->AsObject());
195 break;
196 case CREATE_ACCOUNT_IMPLICITLY:
197 resultCode = authenticatorProxy_->CreateAccountImplicitly(request_.createOptions,
198 authenticatorCb_->AsObject());
199 break;
200 case AUTH:
201 resultCode = authenticatorProxy_->Auth(
202 request_.name, request_.authType, request_.options.GetParams(), authenticatorCb_->AsObject());
203 break;
204 case VERIFY_CREDENTIAL:
205 resultCode = authenticatorProxy_->VerifyCredential(
206 request_.name, request_.verifyCredOptions, authenticatorCb_->AsObject());
207 break;
208 case CHECK_ACCOUNT_LABELS:
209 resultCode = authenticatorProxy_->CheckAccountLabels(
210 request_.name, request_.labels, authenticatorCb_->AsObject());
211 break;
212 case SET_AUTHENTICATOR_PROPERTIES:
213 resultCode = authenticatorProxy_->SetProperties(request_.setPropOptions, authenticatorCb_->AsObject());
214 break;
215 case IS_ACCOUNT_REMOVABLE:
216 resultCode = authenticatorProxy_->IsAccountRemovable(request_.name, authenticatorCb_->AsObject());
217 break;
218 default:
219 ACCOUNT_LOGE("unsupported action: %{public}d", action_);
220 OnResult(ERR_JS_ACCOUNT_AUTHENTICATOR_SERVICE_EXCEPTION, errResult);
221 return;
222 }
223 if (resultCode != ERR_OK) {
224 OnResult(ERR_JS_ACCOUNT_AUTHENTICATOR_SERVICE_EXCEPTION, errResult);
225 }
226 }
227
OnAbilityDisconnectDone(const AppExecFwk::ElementName & element,int resultCode)228 void AppAccountAuthenticatorSession::OnAbilityDisconnectDone(const AppExecFwk::ElementName &element, int resultCode)
229 {
230 isConnected_ = false;
231 }
232
OnServerDied()233 void AppAccountAuthenticatorSession::OnServerDied()
234 {
235 AAFwk::Want result;
236 OnResult(ERR_JS_ACCOUNT_AUTHENTICATOR_SERVICE_EXCEPTION, result);
237 }
238
OnResult(int32_t resultCode,const AAFwk::Want & result) const239 int32_t AppAccountAuthenticatorSession::OnResult(int32_t resultCode, const AAFwk::Want &result) const
240 {
241 if (resultCode == ERR_JS_SUCCESS) {
242 switch (action_) {
243 case ADD_ACCOUNT_IMPLICITLY:
244 resultCode = OnAddAccountImplicitlyDone(result);
245 break;
246 case AUTHENTICATE:
247 resultCode = OnAuthenticateDone(result);
248 break;
249 default:
250 break;
251 }
252 }
253 if ((request_.callback != nullptr) && (request_.callback->AsObject() != nullptr)) {
254 request_.callback->OnResult(resultCode, result);
255 }
256 if (isConnected_) {
257 AbilityManagerAdapter::GetInstance()->DisconnectAbility(conn_);
258 }
259 CloseSelf();
260 return resultCode;
261 }
262
OnRequestRedirected(AAFwk::Want & newRequest) const263 int32_t AppAccountAuthenticatorSession::OnRequestRedirected(AAFwk::Want &newRequest) const
264 {
265 AAFwk::Want errResult;
266 AppExecFwk::ElementName element = newRequest.GetElement();
267 if (element.GetBundleName() != request_.owner) {
268 ACCOUNT_LOGD("invalid response");
269 OnResult(ERR_JS_ACCOUNT_AUTHENTICATOR_SERVICE_EXCEPTION, errResult);
270 return ERR_JS_SUCCESS;
271 }
272 if ((!request_.callback) || (!request_.callback->AsObject())) {
273 ACCOUNT_LOGD("app account callback is nullptr");
274 if (isConnected_) {
275 AbilityManagerAdapter::GetInstance()->DisconnectAbility(conn_);
276 }
277 CloseSelf();
278 return ERR_JS_SUCCESS;
279 }
280 newRequest.SetParam(Constants::KEY_ACTION, action_);
281 newRequest.SetParam(Constants::KEY_NAME, request_.name);
282 newRequest.SetParam(Constants::KEY_SESSION_ID, sessionId_);
283 newRequest.SetParam(Constants::KEY_CALLER_BUNDLE_NAME, request_.callerBundleName);
284 newRequest.SetParam(Constants::KEY_CALLER_PID, request_.callerPid);
285 newRequest.SetParam(Constants::KEY_CALLER_UID, request_.callerUid);
286 if (action_ == AUTHENTICATE || action_ == ADD_ACCOUNT_IMPLICITLY) {
287 newRequest.SetParam(Constants::KEY_AUTH_TYPE, request_.authType);
288 }
289 request_.callback->OnRequestRedirected(newRequest);
290 return ERR_JS_SUCCESS;
291 }
292
OnRequestContinued() const293 int32_t AppAccountAuthenticatorSession::OnRequestContinued() const
294 {
295 if ((!request_.callback) || (!request_.callback->AsObject())) {
296 ACCOUNT_LOGD("app account callback is nullptr");
297 if (isConnected_) {
298 AbilityManagerAdapter::GetInstance()->DisconnectAbility(conn_);
299 }
300 CloseSelf();
301 return ERR_JS_SUCCESS;
302 }
303 request_.callback->OnRequestContinued();
304 return ERR_JS_SUCCESS;
305 }
306
OnAuthenticateDone(const AAFwk::Want & result) const307 int32_t AppAccountAuthenticatorSession::OnAuthenticateDone(const AAFwk::Want &result) const
308 {
309 std::string name = result.GetStringParam(Constants::KEY_NAME);
310 if (name != request_.name) {
311 return ERR_JS_ACCOUNT_AUTHENTICATOR_SERVICE_EXCEPTION;
312 }
313 return ERR_OK;
314 }
315
OnAddAccountImplicitlyDone(const AAFwk::Want & result) const316 int32_t AppAccountAuthenticatorSession::OnAddAccountImplicitlyDone(const AAFwk::Want &result) const
317 {
318 std::string name = result.GetStringParam(Constants::KEY_NAME);
319 if (name.empty()) {
320 return ERR_JS_ACCOUNT_AUTHENTICATOR_SERVICE_EXCEPTION;
321 }
322 AppAccountInfo info(name, request_.owner);
323 info.SetAppIndex(request_.appIndex);
324 AppAccountControlManager::GetInstance().AddAccount(name, "", ownerUid_, request_.owner, info);
325 return ERR_OK;
326 }
327
GetRequest(AuthenticatorSessionRequest & request) const328 void AppAccountAuthenticatorSession::GetRequest(AuthenticatorSessionRequest &request) const
329 {
330 request = request_;
331 }
332
GetAuthenticatorCallback(const AuthenticatorSessionRequest & request,sptr<IRemoteObject> & callback) const333 ErrCode AppAccountAuthenticatorSession::GetAuthenticatorCallback(
334 const AuthenticatorSessionRequest &request, sptr<IRemoteObject> &callback) const
335 {
336 callback = nullptr;
337 if ((request.callerUid != ownerUid_) || (request.callerBundleName != request_.owner)) {
338 ACCOUNT_LOGE("fail to get authenticator callback for permission denied");
339 return ERR_ACCOUNT_COMMON_PERMISSION_DENIED;
340 }
341 if (!authenticatorCb_) {
342 ACCOUNT_LOGE("session has not been initialized");
343 return ERR_APPACCOUNT_SERVICE_OAUTH_AUTHENTICATOR_CALLBACK_NOT_EXIST;
344 }
345 callback = authenticatorCb_->AsObject();
346 return ERR_OK;
347 }
348
GetSessionId() const349 std::string AppAccountAuthenticatorSession::GetSessionId() const
350 {
351 return sessionId_;
352 }
353 } // namespace AccountSA
354 } // namespace OHOS
355