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