Wwangyb0625修改fuzz
43ac8416创建于 2022年7月14日历史提交
/*
 * Copyright (c) 2022 Huawei Device Co., Ltd.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "dm_auth_manager.h"

#include <string>

#include "auth_message_processor.h"
#include "dm_ability_manager.h"
#include "dm_anonymous.h"
#include "dm_config_manager.h"
#include "dm_constants.h"
#include "dm_log.h"
#include "dm_random.h"
#include "multiple_user_connector.h"
#include "nlohmann/json.hpp"
#include "parameter.h"
#include "show_confirm.h"

namespace OHOS {
namespace DistributedHardware {
const int32_t AUTHENTICATE_TIMEOUT = 120;
const int32_t CONFIRM_TIMEOUT = 60;
const int32_t NEGOTIATE_TIMEOUT = 10;
const int32_t INPUT_TIMEOUT = 60;
const int32_t ADD_TIMEOUT = 10;
const int32_t WAIT_NEGOTIATE_TIMEOUT = 10;
const int32_t WAIT_REQUEST_TIMEOUT = 10;
const int32_t CANCEL_PIN_CODE_DISPLAY = 1;
const int32_t DEVICE_ID_HALF = 2;
const int32_t MAX_AUTH_TIMES = 3;

DmAuthManager::DmAuthManager(std::shared_ptr<SoftbusConnector> softbusConnector,
                             std::shared_ptr<IDeviceManagerServiceListener> listener,
                             std::shared_ptr<HiChainConnector> hiChainConnector)
    : softbusConnector_(softbusConnector), hiChainConnector_(hiChainConnector), listener_(listener)
{
    LOGI("DmAuthManager constructor");
    DmConfigManager &dmConfigManager = DmConfigManager::GetInstance();
    dmConfigManager.GetAuthAdapter(authenticationMap_);
}

DmAuthManager::~DmAuthManager()
{
    LOGI("DmAuthManager destructor");
}

int32_t DmAuthManager::AuthenticateDevice(const std::string &pkgName, int32_t authType, const std::string &deviceId,
                                          const std::string &extra)
{
    LOGI("DmAuthManager::AuthenticateDevice start auth type %d", authType);
    if (authType < DM_AUTH_TYPE_MIN || authType > DM_AUTH_TYPE_MAX) {
        LOGE("AuthenticateDevice failed, authType is illegal");
        return ERR_DM_AUTH_FAILED;
    }
    if (pkgName.empty() || deviceId.empty() || extra.empty()) {
        LOGE("DmAuthManager::AuthenticateDevice failed, pkgName is %s, deviceId is %s, extra is %s",
            pkgName.c_str(), deviceId.c_str(), extra.c_str());
        return ERR_DM_INPUT_PARAMETER_EMPTY;
    }
    std::shared_ptr<IAuthentication> authentication = authenticationMap_[authType];
    if (listener_ == nullptr) {
        LOGE("DmAuthManager::AuthenticateDevice is empty nullptr");
        return ERR_DM_INPUT_PARAMETER_EMPTY;
    }
    if (authentication == nullptr) {
        LOGE("DmAuthManager::AuthenticateDevice authType %d not support.", authType);
        listener_->OnAuthResult(pkgName, deviceId, "", AuthState::AUTH_REQUEST_INIT, ERR_DM_UNSUPPORTED_AUTH_TYPE);
        return ERR_DM_UNSUPPORTED_AUTH_TYPE;
    }

    if (authRequestState_ != nullptr || authResponseState_ != nullptr) {
        LOGE("DmAuthManager::AuthenticateDevice %s is request authentication.", pkgName.c_str());
        listener_->OnAuthResult(pkgName, deviceId, "", AuthState::AUTH_REQUEST_INIT, ERR_DM_AUTH_BUSINESS_BUSY);
        return ERR_DM_AUTH_BUSINESS_BUSY;
    }

    if (!softbusConnector_->HaveDeviceInMap(deviceId)) {
        LOGE("AuthenticateDevice failed, the discoveryDeviceInfoMap_ not have this device");
        listener_->OnAuthResult(pkgName, deviceId, "", AuthState::AUTH_REQUEST_INIT, ERR_DM_INPUT_PARAMETER_EMPTY);
        return ERR_DM_INPUT_PARAMETER_EMPTY;
    }
    if (extra.empty()) {
        LOGE("AuthenticateDevice failed, extra is empty");
        listener_->OnAuthResult(pkgName, deviceId, "", AuthState::AUTH_REQUEST_INIT, ERR_DM_INPUT_PARAMETER_EMPTY);
        return ERR_DM_INPUT_PARAMETER_EMPTY;
    }

    authPtr_ = authenticationMap_[authType];
    if (timer_ == nullptr) {
        timer_ = std::make_shared<DmTimer>();
    }
    timer_->StartTimer(AUTHENTICATE_TIMEOUT_TASK, AUTHENTICATE_TIMEOUT,
        [this] (std::string name) {
            DmAuthManager::HandleAuthenticateTimeout(name);
        });
    authMessageProcessor_ = std::make_shared<AuthMessageProcessor>(shared_from_this());
    authResponseContext_ = std::make_shared<DmAuthResponseContext>();
    authRequestContext_ = std::make_shared<DmAuthRequestContext>();
    authRequestContext_->hostPkgName = pkgName;
    authRequestContext_->authType = authType;
    authRequestContext_->deviceId = deviceId;
    nlohmann::json jsonObject = nlohmann::json::parse(extra, nullptr, false);
    if (!jsonObject.is_discarded()) {
        if (jsonObject.contains(TARGET_PKG_NAME_KEY)) {
            authRequestContext_->targetPkgName = jsonObject[TARGET_PKG_NAME_KEY];
        }
        if (jsonObject.contains(APP_NAME_KEY)) {
            authRequestContext_->appName = jsonObject[APP_NAME_KEY];
        }
        if (jsonObject.contains(APP_DESCRIPTION_KEY)) {
            authRequestContext_->appDesc = jsonObject[APP_DESCRIPTION_KEY];
        }
        if (jsonObject.contains(APP_THUMBNAIL)) {
            authRequestContext_->appThumbnail = jsonObject[APP_THUMBNAIL];
        }
        if (jsonObject.contains(APP_ICON_KEY)) {
            authRequestContext_->appIcon = jsonObject[APP_ICON_KEY];
        }
    }
    authRequestContext_->token = std::to_string(GenRandInt(MIN_PIN_TOKEN, MAX_PIN_TOKEN));
    authMessageProcessor_->SetRequestContext(authRequestContext_);
    authRequestState_ = std::make_shared<AuthRequestInitState>();
    authRequestState_->SetAuthManager(shared_from_this());
    authRequestState_->SetAuthContext(authRequestContext_);
    authRequestState_->Enter();
    LOGI("DmAuthManager::AuthenticateDevice complete");
    return DM_OK;
}

int32_t DmAuthManager::UnAuthenticateDevice(const std::string &pkgName, const std::string &deviceId)
{
    if (pkgName.empty()) {
        LOGE(" DmAuthManager::UnAuthenticateDevice failed pkgName is null");
        return ERR_DM_FAILED;
    }
    std::string deviceUdid;
    int32_t ret = SoftbusConnector::GetUdidByNetworkId(deviceId.c_str(), deviceUdid);
    if (ret != DM_OK) {
        LOGE("UnAuthenticateDevice GetNodeKeyInfo failed");
        return ERR_DM_FAILED;
    }

    std::string groupId = "";
    std::vector<OHOS::DistributedHardware::GroupInfo> groupList;
    hiChainConnector_->GetRelatedGroups(deviceUdid, groupList);
    if (groupList.size() > 0) {
        groupId = groupList.front().groupId;
        LOGI(" DmAuthManager::UnAuthenticateDevice groupId=%s, deviceId=%s, deviceUdid=%s",
             GetAnonyString(groupId).c_str(), GetAnonyString(deviceId).c_str(), GetAnonyString(deviceUdid).c_str());
        hiChainConnector_->DeleteGroup(groupId);
    } else {
        LOGE("DmAuthManager::UnAuthenticateDevice groupList.size = 0");
        return ERR_DM_FAILED;
    }
    return DM_OK;
}

int32_t DmAuthManager::VerifyAuthentication(const std::string &authParam)
{
    LOGI("DmAuthManager::VerifyAuthentication");
    if (authResponseContext_ == nullptr) {
        LOGE("authResponseContext_ is not init");
        return ERR_DM_AUTH_NOT_START;
    }
    timer_->DeleteTimer(INPUT_TIMEOUT_TASK);
    int32_t ret = authPtr_->VerifyAuthentication(authResponseContext_->authToken, authParam);
    switch (ret) {
        case DM_OK:
            authRequestState_->TransitionTo(std::make_shared<AuthRequestJoinState>());
            break;
        case ERR_DM_INPUT_PARAMETER_EMPTY:
            listener_->OnVerifyAuthResult(authRequestContext_->hostPkgName, authRequestContext_->deviceId,
                                          ERR_DM_INPUT_PARAMETER_EMPTY, "");
            break;
        default:
            authRequestContext_->reason = ERR_DM_INPUT_PARAMETER_EMPTY;
            authResponseContext_->state = authRequestState_->GetStateType();
            authRequestState_->TransitionTo(std::make_shared<AuthRequestFinishState>());
            break;
    }
    LOGI("DmAuthManager::VerifyAuthentication complete");
    return DM_OK;
}

void DmAuthManager::OnSessionOpened(int32_t sessionId, int32_t sessionSide, int32_t result)
{
    LOGI("DmAuthManager::OnSessionOpened sessionId=%d result=%d", sessionId, result);
    if (sessionSide == AUTH_SESSION_SIDE_SERVER) {
        if (authResponseState_ == nullptr && authRequestState_ == nullptr) {
            authMessageProcessor_ = std::make_shared<AuthMessageProcessor>(shared_from_this());
            authResponseState_ = std::make_shared<AuthResponseInitState>();
            authResponseState_->SetAuthManager(shared_from_this());
            authResponseState_->Enter();
            authResponseContext_ = std::make_shared<DmAuthResponseContext>();
            timer_ = std::make_shared<DmTimer>();
            timer_->StartTimer(AUTHENTICATE_TIMEOUT_TASK, AUTHENTICATE_TIMEOUT,
                [this] (std::string name) {
                    DmAuthManager::HandleAuthenticateTimeout(name);
                });
            timer_->StartTimer(WAIT_NEGOTIATE_TIMEOUT_TASK, WAIT_NEGOTIATE_TIMEOUT,
                [this] (std::string name) {
                    DmAuthManager::HandleAuthenticateTimeout(name);
                });
        } else {
            std::shared_ptr<AuthMessageProcessor> authMessageProcessor =
                std::make_shared<AuthMessageProcessor>(shared_from_this());
            std::shared_ptr<DmAuthResponseContext> authResponseContext = std::make_shared<DmAuthResponseContext>();
            authResponseContext->reply = ERR_DM_AUTH_BUSINESS_BUSY;
            authMessageProcessor->SetResponseContext(authResponseContext);
            std::string message = authMessageProcessor->CreateSimpleMessage(MSG_TYPE_REQ_AUTH_TERMINATE);
            softbusConnector_->GetSoftbusSession()->SendData(sessionId, message);
        }
    } else {
        if (authResponseState_ == nullptr && authRequestState_ != nullptr &&
            authRequestState_->GetStateType() == AuthState::AUTH_REQUEST_INIT) {
            authRequestContext_->sessionId = sessionId;
            authRequestState_->SetAuthContext(authRequestContext_);
            authMessageProcessor_->SetRequestContext(authRequestContext_);
            authRequestState_->TransitionTo(std::make_shared<AuthRequestNegotiateState>());
        } else {
            LOGE("DmAuthManager::OnSessionOpened but request state is wrong");
        }
    }
}

void DmAuthManager::OnSessionClosed(const int32_t sessionId)
{
    LOGI("DmAuthManager::OnSessionOpened sessionId=%d", sessionId);
}

void DmAuthManager::OnDataReceived(const int32_t sessionId, const std::string message)
{
    if (authResponseContext_ == nullptr || authMessageProcessor_ == nullptr) {
        LOGE("OnDataReceived failed, authResponseContext or authMessageProcessor_ is nullptr.");
        return;
    }

    authResponseContext_->sessionId = sessionId;
    authMessageProcessor_->SetResponseContext(authResponseContext_);
    int32_t ret = authMessageProcessor_->ParseMessage(message);
    if (ret != DM_OK) {
        LOGE("OnDataReceived failed, parse input message error.");
        return;
    }

    if ((authRequestState_ != nullptr) && (authResponseState_ == nullptr)) {
        // source device auth process
        authRequestContext_ = authMessageProcessor_->GetRequestContext();
        authRequestState_->SetAuthContext(authRequestContext_);
        LOGI("OnDataReceived for source device, authResponseContext msgType=%d, authRequestState stateType=%d",
            authResponseContext_->msgType, authRequestState_->GetStateType());

        switch (authResponseContext_->msgType) {
            case MSG_TYPE_RESP_AUTH:
                if (authRequestState_->GetStateType() == AuthState::AUTH_REQUEST_NEGOTIATE_DONE) {
                    authRequestState_->TransitionTo(std::make_shared<AuthRequestReplyState>());
                }
                break;
            case MSG_TYPE_RESP_NEGOTIATE:
                if (authRequestState_->GetStateType() == AuthState::AUTH_REQUEST_NEGOTIATE) {
                    authRequestState_->TransitionTo(std::make_shared<AuthRequestNegotiateDoneState>());
                }
                break;
            case MSG_TYPE_REQ_AUTH_TERMINATE:
                if (authRequestState_->GetStateType() != AuthState::AUTH_REQUEST_FINISH) {
                    isFinishOfLocal_ = false;
                    authResponseContext_->state = authRequestState_->GetStateType();
                    authRequestState_->TransitionTo(std::make_shared<AuthRequestFinishState>());
                }
                break;
            default:
                break;
        }
    } else if ((authResponseState_ != nullptr) && (authRequestState_ == nullptr)) {
        // sink device auth process
        authResponseState_->SetAuthContext(authResponseContext_);
        LOGI("OnDataReceived for sink device, authResponseContext msgType=%d, authResponseState stateType=%d",
            authResponseContext_->msgType, authResponseState_->GetStateType());

        switch (authResponseContext_->msgType) {
            case MSG_TYPE_NEGOTIATE:
                if (authResponseState_->GetStateType() == AuthState::AUTH_RESPONSE_INIT) {
                    timer_->DeleteTimer(WAIT_NEGOTIATE_TIMEOUT_TASK);
                    authResponseState_->TransitionTo(std::make_shared<AuthResponseNegotiateState>());
                } else {
                    LOGE("Device manager auth state error");
                }
                break;
            case MSG_TYPE_REQ_AUTH:
                if (authResponseState_->GetStateType() == AuthState::AUTH_RESPONSE_NEGOTIATE) {
                    timer_->DeleteTimer(WAIT_REQUEST_TIMEOUT_TASK);
                    authResponseState_->TransitionTo(std::make_shared<AuthResponseConfirmState>());
                } else {
                    LOGE("Device manager auth state error");
                }
                break;
            case MSG_TYPE_REQ_AUTH_TERMINATE:
                if (authResponseState_->GetStateType() != AuthState::AUTH_RESPONSE_FINISH) {
                    isFinishOfLocal_ = false;
                    authResponseState_->TransitionTo(std::make_shared<AuthResponseFinishState>());
                }
                break;
            default:
                break;
        }
    } else {
        LOGE("DmAuthManager::OnDataReceived failed, authRequestState_ or authResponseState_ is invalid.");
    }
}

void DmAuthManager::OnGroupCreated(int64_t requestId, const std::string &groupId)
{
    if (authResponseContext_ == nullptr) {
        LOGE("failed to OnGroupCreated because authResponseContext_ is nullptr");
        return;
    }
    if (authResponseState_ == nullptr) {
        LOGE("DmAuthManager::AuthenticateDevice end");
        return;
    }
    LOGI("DmAuthManager::OnGroupCreated start group id %s", groupId.c_str());
    if (groupId == "{}") {
        authResponseContext_->reply = ERR_DM_CREATE_GROUP_FAILED;
        authMessageProcessor_->SetResponseContext(authResponseContext_);
        std::string message = authMessageProcessor_->CreateSimpleMessage(MSG_TYPE_RESP_AUTH);
        softbusConnector_->GetSoftbusSession()->SendData(authResponseContext_->sessionId, message);
        return;
    }

    int32_t pinCode = GeneratePincode();
    nlohmann::json jsonObj;
    jsonObj[PIN_TOKEN] = authResponseContext_->token;
    jsonObj[QR_CODE_KEY] = GenerateGroupName();
    jsonObj[NFC_CODE_KEY] = GenerateGroupName();
    authResponseContext_->authToken = jsonObj.dump();
    LOGI("DmAuthManager::OnGroupCreated start group id %s", groupId.c_str());
    authResponseContext_->groupId = groupId;
    authResponseContext_->code = pinCode;
    authMessageProcessor_->SetResponseContext(authResponseContext_);
    std::string message = authMessageProcessor_->CreateSimpleMessage(MSG_TYPE_RESP_AUTH);
    softbusConnector_->GetSoftbusSession()->SendData(authResponseContext_->sessionId, message);
    authResponseState_->TransitionTo(std::make_shared<AuthResponseShowState>());
}

void DmAuthManager::OnMemberJoin(int64_t requestId, int32_t status)
{
    if (authResponseContext_ == nullptr) {
        LOGE("failed to OnMemberJoin because authResponseContext_ is nullptr");
        return;
    }
    LOGI("DmAuthManager OnMemberJoin start authTimes %d", authTimes_);
    if (authRequestState_ != nullptr) {
        authTimes_++;
        timer_->DeleteTimer(ADD_TIMEOUT_TASK);
        if (status != DM_OK || authResponseContext_->requestId != requestId) {
            if (authRequestState_ != nullptr && authTimes_ >= MAX_AUTH_TIMES) {
                authResponseContext_->state = AuthState::AUTH_REQUEST_JOIN;
                authRequestContext_->reason = ERR_DM_INPUT_PARAMETER_EMPTY;
                authRequestState_->TransitionTo(std::make_shared<AuthRequestFinishState>());
            } else {
                timer_->StartTimer(INPUT_TIMEOUT_TASK, INPUT_TIMEOUT,
                    [this] (std::string name) {
                        DmAuthManager::HandleAuthenticateTimeout(name);
                    });
                authPtr_->UpdateAuthInfo(authResponseContext_->pageId);
            }
        } else {
            authRequestState_->TransitionTo(std::make_shared<AuthRequestNetworkState>());
        }
    }
}

void DmAuthManager::HandleAuthenticateTimeout(std::string name)
{
    LOGI("DmAuthManager::HandleAuthenticateTimeout start timer name %s", name.c_str());
    if (authRequestState_ != nullptr && authRequestState_->GetStateType() != AuthState::AUTH_REQUEST_FINISH) {
        if (authResponseContext_ == nullptr) {
            authResponseContext_ = std::make_shared<DmAuthResponseContext>();
        }
        authResponseContext_->state = authRequestState_->GetStateType();
        authRequestContext_->reason = ERR_DM_TIME_OUT;
        authRequestState_->TransitionTo(std::make_shared<AuthRequestFinishState>());
    }

    if (authResponseState_ != nullptr && authResponseState_->GetStateType() != AuthState::AUTH_RESPONSE_FINISH) {
        authResponseContext_->state = authResponseState_->GetStateType();
        authResponseContext_->reply = ERR_DM_TIME_OUT;
        authResponseState_->TransitionTo(std::make_shared<AuthResponseFinishState>());
    }
    LOGI("DmAuthManager::HandleAuthenticateTimeout start complete");
}

int32_t DmAuthManager::EstablishAuthChannel(const std::string &deviceId)
{
    int32_t sessionId = softbusConnector_->GetSoftbusSession()->OpenAuthSession(deviceId);
    if (sessionId < 0) {
        LOGE("OpenAuthSession failed, stop the authentication");
        authResponseContext_ = std::make_shared<DmAuthResponseContext>();
        authResponseContext_->state = AuthState::AUTH_REQUEST_NEGOTIATE;
        authRequestContext_->reason = ERR_DM_AUTH_OPEN_SESSION_FAILED;
        if (authRequestState_ != nullptr) {
            authRequestState_->TransitionTo(std::make_shared<AuthRequestFinishState>());
        }
    }
    return DM_OK;
}

void DmAuthManager::StartNegotiate(const int32_t &sessionId)
{
    if (authResponseContext_ == nullptr) {
        LOGE("failed to StartNegotiate because authResponseContext_ is nullptr");
        return;
    }
    LOGI("DmAuthManager::EstablishAuthChannel session id is %d", sessionId);
    char localDeviceId[DEVICE_UUID_LENGTH] = {0};
    GetDevUdid(localDeviceId, DEVICE_UUID_LENGTH);
    authResponseContext_->localDeviceId = localDeviceId;
    authResponseContext_->reply = ERR_DM_AUTH_REJECT;
    authResponseContext_->authType = authRequestContext_->authType;
    authResponseContext_->deviceId = authRequestContext_->deviceId;
    authMessageProcessor_->SetResponseContext(authResponseContext_);
    std::string message = authMessageProcessor_->CreateSimpleMessage(MSG_TYPE_NEGOTIATE);
    softbusConnector_->GetSoftbusSession()->SendData(sessionId, message);
    timer_->StartTimer(NEGOTIATE_TIMEOUT_TASK, NEGOTIATE_TIMEOUT,
        [this] (std::string name) {
            DmAuthManager::HandleAuthenticateTimeout(name);
        });
}

void DmAuthManager::RespNegotiate(const int32_t &sessionId)
{
    if (authResponseContext_ == nullptr) {
        LOGE("failed to RespNegotiate because authResponseContext_ is nullptr");
        return;
    }
    LOGI("DmAuthManager::EstablishAuthChannel session id is %d", sessionId);
    char localDeviceId[DEVICE_UUID_LENGTH] = {0};
    GetDevUdid(localDeviceId, DEVICE_UUID_LENGTH);
    bool ret = hiChainConnector_->IsDevicesInGroup(authResponseContext_->localDeviceId, localDeviceId);
    if (!ret) {
        LOGE("DmAuthManager::EstablishAuthChannel device is in group");
        authResponseContext_->reply = ERR_DM_AUTH_PEER_REJECT;
    } else {
        authResponseContext_->reply = ERR_DM_AUTH_REJECT;
    }

    std::shared_ptr<IAuthentication> authentication = authenticationMap_[authResponseContext_->authType];
    if (authentication == nullptr) {
        LOGE("DmAuthManager::AuthenticateDevice authType %d not support.", authResponseContext_->authType);
        authResponseContext_->reply = ERR_DM_UNSUPPORTED_AUTH_TYPE;
    } else {
        authPtr_ = authenticationMap_[authResponseContext_->authType];
    }

    std::string message = authMessageProcessor_->CreateSimpleMessage(MSG_TYPE_RESP_NEGOTIATE);
    nlohmann::json jsonObject = nlohmann::json::parse(message, nullptr, false);
    if (jsonObject.is_discarded()) {
        softbusConnector_->GetSoftbusSession()->SendData(sessionId, message);
    }
    authResponseContext_ = authResponseState_->GetAuthContext();
    if (jsonObject[TAG_CRYPTO_SUPPORT] == true && authResponseContext_->cryptoSupport) {
        if (jsonObject[TAG_CRYPTO_NAME] == authResponseContext_->cryptoName &&
            jsonObject[TAG_CRYPTO_VERSION] == authResponseContext_->cryptoVer) {
            isCryptoSupport_ = true;
            softbusConnector_->GetSoftbusSession()->SendData(sessionId, message);
            return;
        }
    }
    jsonObject[TAG_CRYPTO_SUPPORT] = false;
    message = jsonObject.dump();
    softbusConnector_->GetSoftbusSession()->SendData(sessionId, message);
    timer_->StartTimer(WAIT_REQUEST_TIMEOUT_TASK, WAIT_REQUEST_TIMEOUT,
        [this] (std::string name) {
            DmAuthManager::HandleAuthenticateTimeout(name);
        });
}

void DmAuthManager::SendAuthRequest(const int32_t &sessionId)
{
    if (authResponseContext_ == nullptr) {
        LOGE("failed to SendAuthRequest because authResponseContext_ is nullptr");
        return;
    }
    LOGI("DmAuthManager::EstablishAuthChannel session id");
    timer_->DeleteTimer(NEGOTIATE_TIMEOUT_TASK);
    if (authResponseContext_->cryptoSupport) {
        isCryptoSupport_ = true;
    }
    if (authResponseContext_->reply == ERR_DM_AUTH_PEER_REJECT) {
        authRequestState_->TransitionTo(std::make_shared<AuthRequestFinishState>());
        return;
    }
    std::vector<std::string> messageList = authMessageProcessor_->CreateAuthRequestMessage();
    for (auto msg : messageList) {
        softbusConnector_->GetSoftbusSession()->SendData(sessionId, msg);
    }
    timer_->StartTimer(CONFIRM_TIMEOUT_TASK, CONFIRM_TIMEOUT,
        [this] (std::string name) {
            DmAuthManager::HandleAuthenticateTimeout(name);
        });
}

int32_t DmAuthManager::StartAuthProcess(const int32_t &action)
{
    if (authResponseContext_ == nullptr) {
        LOGE("failed to StartAuthProcess because authResponseContext_ is nullptr");
        return ERR_DM_AUTH_NOT_START;
    }
    LOGI("DmAuthManager:: StartAuthProcess");
    authResponseContext_->reply = action;
    if (authResponseContext_->reply == USER_OPERATION_TYPE_ALLOW_AUTH &&
        authResponseState_->GetStateType() == AuthState::AUTH_RESPONSE_CONFIRM) {
        authResponseState_->TransitionTo(std::make_shared<AuthResponseGroupState>());
    } else {
        authMessageProcessor_->SetResponseContext(authResponseContext_);
        std::string message = authMessageProcessor_->CreateSimpleMessage(MSG_TYPE_RESP_AUTH);
        softbusConnector_->GetSoftbusSession()->SendData(authResponseContext_->sessionId, message);
    }
    return DM_OK;
}

void DmAuthManager::StartRespAuthProcess()
{
    if (authResponseContext_ == nullptr) {
        LOGE("failed to StartRespAuthProcess because authResponseContext_ is nullptr");
        return;
    }
    LOGI("DmAuthManager::StartRespAuthProcess", authResponseContext_->sessionId);
    timer_->DeleteTimer(CONFIRM_TIMEOUT_TASK);
    if (authResponseContext_->reply == USER_OPERATION_TYPE_ALLOW_AUTH) {
        timer_->StartTimer(INPUT_TIMEOUT_TASK, INPUT_TIMEOUT,
            [this] (std::string name) {
                DmAuthManager::HandleAuthenticateTimeout(name);
            });
        authRequestState_->TransitionTo(std::make_shared<AuthRequestJoinState>());
    } else {
        LOGE("do not accept");
        authResponseContext_->state = AuthState::AUTH_REQUEST_REPLY;
        authRequestContext_->reason = ERR_DM_AUTH_PEER_REJECT;
        authRequestState_->TransitionTo(std::make_shared<AuthRequestFinishState>());
    }
}

int32_t DmAuthManager::CreateGroup()
{
    if (authResponseContext_ == nullptr) {
        LOGE("failed to CreateGroup because authResponseContext_ is nullptr");
        return ERR_DM_FAILED;
    }
    LOGI("DmAuthManager:: CreateGroup start");
    authResponseContext_->groupName = GenerateGroupName();
    authResponseContext_->requestId = GenRandLongLong(MIN_REQUEST_ID, MAX_REQUEST_ID);
    hiChainConnector_->CreateGroup(authResponseContext_->requestId, authResponseContext_->groupName);
    return DM_OK;
}

int32_t DmAuthManager::AddMember(int32_t pinCode)
{
    if (authResponseContext_ == nullptr) {
        LOGE("failed to AddMember because authResponseContext_ is nullptr");
        return ERR_DM_FAILED;
    }
    LOGI("DmAuthManager::AddMember start group id %s", authResponseContext_->groupId.c_str());
    timer_->DeleteTimer(INPUT_TIMEOUT_TASK);
    nlohmann::json jsonObject;
    jsonObject[TAG_GROUP_ID] = authResponseContext_->groupId;
    jsonObject[TAG_GROUP_NAME] = authResponseContext_->groupName;
    jsonObject[PIN_CODE_KEY] = pinCode;
    jsonObject[TAG_REQUEST_ID] = authResponseContext_->requestId;
    jsonObject[TAG_DEVICE_ID] = authResponseContext_->deviceId;
    std::string connectInfo = jsonObject.dump();
    timer_->StartTimer(ADD_TIMEOUT_TASK, ADD_TIMEOUT,
        [this] (std::string name) {
            DmAuthManager::HandleAuthenticateTimeout(name);
        });
    int32_t ret = hiChainConnector_->AddMember(authRequestContext_->deviceId, connectInfo);
    if (ret != 0) {
        return ERR_DM_FAILED;
    }
    return DM_OK;
}

std::string DmAuthManager::GetConnectAddr(std::string deviceId)
{
    LOGI("DmAuthManager::GetConnectAddr");
    std::string connectAddr;
    softbusConnector_->GetConnectAddr(deviceId, connectAddr);
    return connectAddr;
}

int32_t DmAuthManager::JoinNetwork()
{
    if (authResponseContext_ == nullptr) {
        LOGE("failed to JoinNeWork because authResponseContext_ is nullptr");
        return ERR_DM_FAILED;
    }
    LOGI("DmAuthManager JoinNetwork start");
    timer_->DeleteTimer(AUTHENTICATE_TIMEOUT_TASK);
    authResponseContext_->state = AuthState::AUTH_REQUEST_FINISH;
    authRequestContext_->reason = DM_OK;
    authRequestState_->TransitionTo(std::make_shared<AuthRequestFinishState>());
    return DM_OK;
}

void DmAuthManager::AuthenticateFinish()
{
    if (authResponseContext_ == nullptr) {
        LOGE("failed to AuthenticateFinish because authResponseContext_ is nullptr");
        return;
    }
    LOGI("DmAuthManager::AuthenticateFinish start");
    if (authResponseState_ != nullptr) {
        if (authResponseState_->GetStateType() == AuthState::AUTH_RESPONSE_FINISH && authPtr_ != nullptr) {
            authPtr_->CloseAuthInfo(authResponseContext_->pageId, shared_from_this());
        }
        if (isFinishOfLocal_) {
            authMessageProcessor_->SetResponseContext(authResponseContext_);
            std::string message = authMessageProcessor_->CreateSimpleMessage(MSG_TYPE_REQ_AUTH_TERMINATE);
            softbusConnector_->GetSoftbusSession()->SendData(authResponseContext_->sessionId, message);
        }
        timer_->DeleteAll();
        isFinishOfLocal_ = true;
        authResponseContext_ = nullptr;
        authResponseState_ = nullptr;
        authMessageProcessor_ = nullptr;
        authPtr_ = nullptr;
    } else if (authRequestState_ != nullptr) {
        if (isFinishOfLocal_) {
            authMessageProcessor_->SetResponseContext(authResponseContext_);
            std::string message = authMessageProcessor_->CreateSimpleMessage(MSG_TYPE_REQ_AUTH_TERMINATE);
            softbusConnector_->GetSoftbusSession()->SendData(authResponseContext_->sessionId, message);
        } else {
            authRequestContext_->reason = authResponseContext_->reply;
        }
        if ((authResponseContext_->state == AuthState::AUTH_REQUEST_JOIN ||
            authResponseContext_->state == AuthState::AUTH_REQUEST_FINISH) && authPtr_ != nullptr) {
            authPtr_->CloseAuthInfo(authResponseContext_->pageId, shared_from_this());
        }
        listener_->OnAuthResult(authRequestContext_->hostPkgName, authRequestContext_->deviceId,
                                authRequestContext_->token, authResponseContext_->state, authRequestContext_->reason);
        softbusConnector_->GetSoftbusSession()->CloseAuthSession(authRequestContext_->sessionId);
        timer_->DeleteAll();
        isFinishOfLocal_ = true;
        authRequestContext_ = nullptr;
        authResponseContext_ = nullptr;
        authRequestState_ = nullptr;
        authMessageProcessor_ = nullptr;
        authPtr_ = nullptr;
        authTimes_ = 0;
    }
    LOGI("DmAuthManager::AuthenticateFinish complete");
}

void DmAuthManager::CancelDisplay()
{
    LOGI("DmAuthManager::CancelDisplay start");
    nlohmann::json jsonObj;
    jsonObj[CANCEL_DISPLAY_KEY] = CANCEL_PIN_CODE_DISPLAY;
    std::string paramJson = jsonObj.dump();
    std::string pkgName = "com.ohos.devicemanagerui";
    listener_->OnFaCall(pkgName, paramJson);
}

int32_t DmAuthManager::GeneratePincode()
{
    return GenRandInt(MIN_PIN_CODE, MAX_PIN_CODE);
}

std::string DmAuthManager::GenerateGroupName()
{
    if (authResponseContext_ == nullptr) {
        LOGE("failed to GenerateGroupName because authResponseContext_ is nullptr.");
        return "";
    }
    char localDeviceId[DEVICE_UUID_LENGTH] = {0};
    GetDevUdid(localDeviceId, DEVICE_UUID_LENGTH);
    std::string sLocalDeviceId = localDeviceId;
    uint32_t interceptLength = sLocalDeviceId.size() / DEVICE_ID_HALF;
    std::string groupName = authResponseContext_->targetPkgName + sLocalDeviceId.substr(0, interceptLength)
                            + authResponseContext_->localDeviceId.substr(0, interceptLength);
    return groupName;
}

bool DmAuthManager::GetIsCryptoSupport()
{
    LOGI("DmAuthManager::GetIsCryptoSupport start");
    if (authResponseState_ == nullptr) {
        return false;
    }
    if (authRequestState_ == nullptr) {
        if (authResponseState_->GetStateType() == AuthState::AUTH_REQUEST_NEGOTIATE_DONE) {
            return false;
        }
    } else {
        if (authRequestState_->GetStateType() == AuthState::AUTH_REQUEST_NEGOTIATE ||
            authRequestState_->GetStateType() == AuthState::AUTH_REQUEST_NEGOTIATE_DONE) {
            return false;
        }
    }

    return isCryptoSupport_;
}

int32_t DmAuthManager::SetAuthRequestState(std::shared_ptr<AuthRequestState> authRequestState)
{
    authRequestState_ = authRequestState;
    return DM_OK;
}

int32_t DmAuthManager::SetAuthResponseState(std::shared_ptr<AuthResponseState> authResponseState)
{
    authResponseState_ = authResponseState;
    return DM_OK;
}

int32_t DmAuthManager::GetPinCode()
{
    if (authResponseContext_ == nullptr) {
        LOGE("failed to GetPinCode because authResponseContext_ is nullptr");
        return ERR_DM_AUTH_NOT_START;
    }
    LOGI("ShowConfigDialog start add member pin code.");
    return authResponseContext_->code;
}

void DmAuthManager::ShowConfigDialog()
{
    if (authResponseContext_ == nullptr) {
        LOGE("failed to ShowConfigDialog because authResponseContext_ is nullptr");
        return;
    }
    LOGI("ShowConfigDialog start");
    dmAbilityMgr_ = std::make_shared<DmAbilityManager>();
    nlohmann::json jsonObj;
    jsonObj[TAG_AUTH_TYPE] = AUTH_TYPE_PIN;
    jsonObj[TAG_TOKEN] = authResponseContext_->token;
    jsonObj[TARGET_PKG_NAME_KEY] = authResponseContext_->targetPkgName;
    jsonObj.dump();
    const std::string params = jsonObj.dump();
    std::shared_ptr<ShowConfirm> showConfirm_ = std::make_shared<ShowConfirm>();
    showConfirm_->ShowConfirmDialog(params, shared_from_this(), dmAbilityMgr_);
    LOGI("ShowConfigDialog end");
}

void DmAuthManager::ShowAuthInfoDialog()
{
    if (authResponseContext_ == nullptr) {
        LOGE("failed to ShowAuthInfoDialog because authResponseContext_ is nullptr");
        return;
    }
    LOGI("DmAuthManager::ShowAuthInfoDialog start %d", authResponseContext_->code);
    nlohmann::json jsonObj;
    jsonObj[PIN_CODE_KEY] = authResponseContext_->code;
    std::string authParam = jsonObj.dump();
    authPtr_->ShowAuthInfo(authParam, shared_from_this());
}

void DmAuthManager::ShowStartAuthDialog()
{
    if (authResponseContext_ == nullptr) {
        LOGE("failed to ShowStartAuthDialog because authResponseContext_ is nullptr");
        return;
    }
    LOGI("DmAuthManager::ShowStartAuthDialog start because authResponseContext_ is nullptr");
    authPtr_->StartAuth(authResponseContext_->authToken, shared_from_this());
}

int32_t DmAuthManager::GetAuthenticationParam(DmAuthParam &authParam)
{
    if (dmAbilityMgr_ == nullptr) {
        LOGE("dmAbilityMgr_ is nullptr");
        return ERR_DM_POINT_NULL;
    }

    if (authResponseContext_ == nullptr) {
        LOGE("Authenticate is not start");
        return ERR_DM_AUTH_NOT_START;
    }

    dmAbilityMgr_->StartAbilityDone();
    AbilityRole role = dmAbilityMgr_->GetAbilityRole();
    authParam.direction = (int32_t)role;
    authParam.authType = AUTH_TYPE_PIN;
    authParam.authToken = authResponseContext_->token;

    if (role == AbilityRole::ABILITY_ROLE_PASSIVE) {
        authParam.packageName = authResponseContext_->targetPkgName;
        authParam.appName = authResponseContext_->appName;
        authParam.appDescription = authResponseContext_->appDesc;
        authParam.business = BUSINESS_FA_MIRGRATION;
        authParam.pincode = authResponseContext_->code;
    }
    return DM_OK;
}

int32_t DmAuthManager::OnUserOperation(int32_t action)
{
    if (authResponseContext_ == nullptr) {
        LOGE("Authenticate is not start");
        return ERR_DM_AUTH_NOT_START;
    }

    switch (action) {
        case USER_OPERATION_TYPE_ALLOW_AUTH:
        case USER_OPERATION_TYPE_CANCEL_AUTH:
            StartAuthProcess(action);
            break;
        case USER_OPERATION_TYPE_AUTH_CONFIRM_TIMEOUT:
            AuthenticateFinish();
            break;
        case USER_OPERATION_TYPE_CANCEL_PINCODE_DISPLAY:
            CancelDisplay();
            break;
        case USER_OPERATION_TYPE_CANCEL_PINCODE_INPUT:
            authRequestContext_->reason = ERR_DM_AUTH_FAILED;
            authResponseContext_->state = authRequestState_->GetStateType();
            AuthenticateFinish();
            break;
        default:
            LOGE("this action id not support");
            break;
    }
    return DM_OK;
}

void DmAuthManager::UserSwitchEventCallback (int32_t userId)
{
    LOGI("switch user event happen and this user groups will be deleted with userId: %d", userId);
    nlohmann::json jsonObj;
    jsonObj[FIELD_GROUP_TYPE] = GROUP_TYPE_PEER_TO_PEER_GROUP;
    std::string queryParams = jsonObj.dump();
    std::vector<GroupInfo> groupList;

    int32_t oldUserId = MultipleUserConnector::GetSwitchOldUserId();
    MultipleUserConnector::SetSwitchOldUserId(userId);
    if (!hiChainConnector_->GetGroupInfo(oldUserId, queryParams, groupList)) {
        LOGE("failed to get device join groups");
        return;
    }
    for (auto iter = groupList.begin(); iter != groupList.end(); iter++) {
        int32_t ret = hiChainConnector_->DeleteGroup(oldUserId, iter->groupId);
        if (ret != DM_OK) {
            LOGE("fail to delete group");
        }
    }

    if (!hiChainConnector_->GetGroupInfo(userId, queryParams, groupList)) {
        LOGE("failed to get device join groups");
        return;
    }
    for (auto iter = groupList.begin(); iter != groupList.end(); iter++) {
        int32_t ret = hiChainConnector_->DeleteGroup(userId, iter->groupId);
        if (ret != DM_OK) {
            LOGE("fail to delete group");
        }
    }
}

int32_t DmAuthManager::SetPageId(int32_t pageId)
{
    if (authResponseContext_ == nullptr) {
        LOGE("Authenticate is not start");
        return ERR_DM_AUTH_NOT_START;
    }
    authResponseContext_->pageId = pageId;
    return DM_OK;
}

int32_t DmAuthManager::SetReasonAndFinish(int32_t reason, int32_t state)
{
    if (authResponseContext_ == nullptr) {
        LOGE("Authenticate is not start");
        return ERR_DM_AUTH_NOT_START;
    }
    authResponseContext_->state = state;
    authResponseContext_->reply = reason;
    if (authRequestState_ != nullptr && authRequestState_->GetStateType() != AuthState::AUTH_REQUEST_FINISH) {
        authRequestContext_->reason = reason;
        authRequestState_->TransitionTo(std::make_shared<AuthRequestFinishState>());
    } else if (authResponseState_ != nullptr && authResponseState_->GetStateType() != AuthState::AUTH_RESPONSE_FINISH) {
        authResponseState_->TransitionTo(std::make_shared<AuthResponseFinishState>());
    }
    return DM_OK;
}
} // namespace DistributedHardware
} // namespace OHOS