parent
0a9d408a78
commit
9c88f3c1ca
@ -0,0 +1,8 @@ |
|||||||
|
cmake_minimum_required(VERSION 3.7) |
||||||
|
|
||||||
|
project(dp4-uos) |
||||||
|
|
||||||
|
add_subdirectory(dp4-login-plugin) |
||||||
|
add_subdirectory(dp4-pam) |
||||||
|
add_subdirectory(dp4-dbus-service) |
||||||
|
add_subdirectory(example) |
||||||
@ -0,0 +1,97 @@ |
|||||||
|
# - Try to find the PAM libraries |
||||||
|
# Once done this will define |
||||||
|
# |
||||||
|
# PAM_FOUND - system has pam |
||||||
|
# PAM_INCLUDE_DIR - the pam include directory |
||||||
|
# PAM_LIBRARIES - libpam library |
||||||
|
# |
||||||
|
# Redistribution and use in source and binary forms, with or without |
||||||
|
# modification, are permitted provided that the following conditions |
||||||
|
# are met: |
||||||
|
# |
||||||
|
# 1. Redistributions of source code must retain the copyright |
||||||
|
# notice, this list of conditions and the following disclaimer. |
||||||
|
# 2. Redistributions in binary form must reproduce the copyright |
||||||
|
# notice, this list of conditions and the following disclaimer in the |
||||||
|
# documentation and/or other materials provided with the distribution. |
||||||
|
# 3. The name of the author may not be used to endorse or promote products |
||||||
|
# derived from this software without specific prior written permission. |
||||||
|
# |
||||||
|
# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
||||||
|
# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
||||||
|
# OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
||||||
|
# IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
||||||
|
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
||||||
|
# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
||||||
|
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
||||||
|
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
||||||
|
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
||||||
|
# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
||||||
|
|
||||||
|
if (PAM_INCLUDE_DIR AND PAM_LIBRARY) |
||||||
|
# Already in cache, be silent |
||||||
|
set(PAM_FIND_QUIETLY TRUE) |
||||||
|
endif (PAM_INCLUDE_DIR AND PAM_LIBRARY) |
||||||
|
|
||||||
|
find_path(PAM_INCLUDE_DIR NAMES security/pam_appl.h pam/pam_appl.h) |
||||||
|
find_library(PAM_LIBRARY pam) |
||||||
|
find_library(DL_LIBRARY dl) |
||||||
|
|
||||||
|
if (PAM_INCLUDE_DIR AND PAM_LIBRARY) |
||||||
|
set(PAM_FOUND TRUE) |
||||||
|
if (DL_LIBRARY) |
||||||
|
set(PAM_LIBRARIES ${PAM_LIBRARY} ${DL_LIBRARY}) |
||||||
|
else (DL_LIBRARY) |
||||||
|
set(PAM_LIBRARIES ${PAM_LIBRARY}) |
||||||
|
endif (DL_LIBRARY) |
||||||
|
|
||||||
|
if (EXISTS ${PAM_INCLUDE_DIR}/pam/pam_appl.h) |
||||||
|
# darwin claims to be something special |
||||||
|
set(HAVE_PAM_PAM_APPL_H 1) |
||||||
|
endif (EXISTS ${PAM_INCLUDE_DIR}/pam/pam_appl.h) |
||||||
|
|
||||||
|
if (NOT DEFINED PAM_MESSAGE_CONST) |
||||||
|
include(CheckCXXSourceCompiles) |
||||||
|
# XXX does this work with plain c? |
||||||
|
check_cxx_source_compiles(" |
||||||
|
#if ${HAVE_PAM_PAM_APPL_H}+0 |
||||||
|
# include <pam/pam_appl.h> |
||||||
|
#else |
||||||
|
# include <security/pam_appl.h> |
||||||
|
#endif |
||||||
|
|
||||||
|
static int PAM_conv( |
||||||
|
int num_msg, |
||||||
|
const struct pam_message **msg, /* this is the culprit */ |
||||||
|
struct pam_response **resp, |
||||||
|
void *ctx) |
||||||
|
{ |
||||||
|
return 0; |
||||||
|
} |
||||||
|
|
||||||
|
int main(void) |
||||||
|
{ |
||||||
|
struct pam_conv PAM_conversation = { |
||||||
|
&PAM_conv, /* this bombs out if the above does not match */ |
||||||
|
0 |
||||||
|
}; |
||||||
|
|
||||||
|
return 0; |
||||||
|
} |
||||||
|
" PAM_MESSAGE_CONST) |
||||||
|
endif (NOT DEFINED PAM_MESSAGE_CONST) |
||||||
|
set(PAM_MESSAGE_CONST ${PAM_MESSAGE_CONST} CACHE BOOL "PAM expects a conversation function with const pam_message") |
||||||
|
|
||||||
|
endif (PAM_INCLUDE_DIR AND PAM_LIBRARY) |
||||||
|
|
||||||
|
if (PAM_FOUND) |
||||||
|
if (NOT PAM_FIND_QUIETLY) |
||||||
|
message(STATUS "Found PAM: ${PAM_LIBRARIES}") |
||||||
|
endif (NOT PAM_FIND_QUIETLY) |
||||||
|
else (PAM_FOUND) |
||||||
|
if (PAM_FIND_REQUIRED) |
||||||
|
message(FATAL_ERROR "PAM was not found") |
||||||
|
endif(PAM_FIND_REQUIRED) |
||||||
|
endif (PAM_FOUND) |
||||||
|
|
||||||
|
mark_as_advanced(PAM_INCLUDE_DIR PAM_LIBRARY DL_LIBRARY PAM_MESSAGE_CONST) |
||||||
@ -0,0 +1,5 @@ |
|||||||
|
dp4-uos (1.0.0) unstable; urgency=medium |
||||||
|
|
||||||
|
* support single sign-on |
||||||
|
|
||||||
|
-- donghualin <donghualin@uniontech.com> Thu, 16 May 2024 11:07:48 +0800 |
||||||
@ -0,0 +1 @@ |
|||||||
|
9 |
||||||
@ -0,0 +1,30 @@ |
|||||||
|
Source: dp4-uos |
||||||
|
Section: libs |
||||||
|
Priority: optional |
||||||
|
Maintainer: Deepin Packages Builder <packages@deepin.com> |
||||||
|
Build-Depends: debhelper (>= 8.0.0), |
||||||
|
cmake, |
||||||
|
qt5-default, |
||||||
|
pkg-config, |
||||||
|
dde-session-shell-dev, |
||||||
|
qtbase5-dev, |
||||||
|
qtbase5-private-dev, |
||||||
|
qttools5-dev, |
||||||
|
libpam0g-dev |
||||||
|
Standards-Version: 4.5.1 |
||||||
|
Homepage: https://www.deepin.org |
||||||
|
|
||||||
|
Package: deepin-service-plugin-dp4 |
||||||
|
Architecture: any |
||||||
|
Depends: ${shlibs:Depends}, ${misc:Depends} |
||||||
|
Description: the service of dp4. |
||||||
|
|
||||||
|
Package: login-dp4-plugin |
||||||
|
Architecture: any |
||||||
|
Depends: ${shlibs:Depends}, ${misc:Depends} |
||||||
|
Description: the plugin of login by dp4. |
||||||
|
|
||||||
|
Package: pam-dp4 |
||||||
|
Architecture: any |
||||||
|
Depends: ${shlibs:Depends}, ${misc:Depends} |
||||||
|
Description: the package of dp4 for login by pam. |
||||||
@ -0,0 +1,20 @@ |
|||||||
|
Format: http://www.debian.org/doc/packaging-manuals/copyright-format/1.0/ |
||||||
|
Upstream-Name: deepin-passkey |
||||||
|
Files: * |
||||||
|
Copyright: 2023 Deepin Technology Co., Ltd. |
||||||
|
License: GPL-3+ |
||||||
|
This package is free software; you can redistribute it and/or modify |
||||||
|
it under the terms of the GNU General Public License as published by |
||||||
|
the Free Software Foundation; either version 3 of the License, or |
||||||
|
(at your option) any later version. |
||||||
|
. |
||||||
|
This package is distributed in the hope that it will be useful, |
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of |
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
||||||
|
GNU General Public License for more details. |
||||||
|
. |
||||||
|
You should have received a copy of the GNU General Public License |
||||||
|
along with this program. If not, see <http://www.gnu.org/licenses/> |
||||||
|
. |
||||||
|
On Debian systems, the complete text of the GNU General |
||||||
|
Public License version 3 can be found in "/usr/share/common-licenses/GPL-3". |
||||||
@ -0,0 +1,4 @@ |
|||||||
|
usr/lib/*/deepin-service-manager/libdp4-service.so |
||||||
|
usr/share/deepin-service-manager/user/plugin-dp4-service.json |
||||||
|
usr/share/dbus-1/system.d/org.deepin.service.dp4.conf |
||||||
|
usr/share/dp4-service/translations |
||||||
@ -0,0 +1,2 @@ |
|||||||
|
usr/lib/dde-session-shell/modules/libdp4-login-plugin.so |
||||||
|
usr/share/dp4-login-plugin/translations |
||||||
@ -0,0 +1 @@ |
|||||||
|
usr/lib/*/security |
||||||
@ -0,0 +1,6 @@ |
|||||||
|
#!/usr/bin/make -f |
||||||
|
|
||||||
|
include /usr/share/dpkg/default.mk |
||||||
|
|
||||||
|
%: |
||||||
|
dh $@ --buildsystem=cmake |
||||||
@ -0,0 +1 @@ |
|||||||
|
3.0 (native) |
||||||
@ -0,0 +1,57 @@ |
|||||||
|
cmake_minimum_required(VERSION 3.7) |
||||||
|
|
||||||
|
set(PLUGIN_NAME "dp4-service") |
||||||
|
|
||||||
|
project(${PLUGIN_NAME}) |
||||||
|
|
||||||
|
set(CMAKE_AUTOMOC ON) |
||||||
|
set(CMAKE_AUTORCC ON) |
||||||
|
|
||||||
|
include(GNUInstallDirs) |
||||||
|
|
||||||
|
if (CMAKE_BUILD_TYPE STREQUAL "Debug") |
||||||
|
ADD_DEFINITIONS(-DQM_FILES_DIR="${CMAKE_BINARY_DIR}/dp4-service-plugin") |
||||||
|
else() |
||||||
|
ADD_DEFINITIONS(-DQM_FILES_DIR="/usr/share/deepin-service-manager/dp4-service-plugin/translations") |
||||||
|
endif() |
||||||
|
|
||||||
|
find_package(Qt5 COMPONENTS Core Widgets DBus Network LinguistTools REQUIRED) |
||||||
|
|
||||||
|
file(GLOB TS_FILES "translations/*.ts") |
||||||
|
qt5_add_translation(QM_FILES ${TS_FILES}) |
||||||
|
add_custom_target(${PLUGIN_NAME}_language ALL DEPENDS ${QM_FILES}) |
||||||
|
|
||||||
|
file(GLOB_RECURSE SRCS "*.h" "*.cpp") |
||||||
|
|
||||||
|
add_library(${PLUGIN_NAME} MODULE |
||||||
|
${SRCS} |
||||||
|
) |
||||||
|
|
||||||
|
target_include_directories(${PLUGIN_NAME} PUBLIC |
||||||
|
Qt5::Core |
||||||
|
Qt5::DBus |
||||||
|
${Qt5Widget_INCLUDE_DIRS} |
||||||
|
${Qt5Network_INCLUDE_DIRS} |
||||||
|
${DtkCore_INCLUDE_DIRS} |
||||||
|
. |
||||||
|
) |
||||||
|
|
||||||
|
target_link_libraries(${PLUGIN_NAME} PRIVATE |
||||||
|
Qt5::Core |
||||||
|
Qt5::DBus |
||||||
|
${Qt5Network_LIBRARIES} |
||||||
|
${Qt5Widgets_LIBRARIES} |
||||||
|
) |
||||||
|
|
||||||
|
if (CMAKE_BUILD_TYPE STREQUAL "Debug") |
||||||
|
EXECUTE_PROCESS(COMMAND mkdir -p ${CMAKE_BINARY_DIR}/share/system/) |
||||||
|
EXECUTE_PROCESS(COMMAND mkdir -p ${CMAKE_BINARY_DIR}/share/user/) |
||||||
|
EXECUTE_PROCESS(COMMAND cp -f ${CMAKE_CURRENT_SOURCE_DIR}/plugin-dp4-service.json ${CMAKE_BINARY_DIR}/share/user/) |
||||||
|
else() |
||||||
|
# just need this in your project |
||||||
|
install(TARGETS ${PLUGIN_NAME} DESTINATION ${CMAKE_INSTALL_LIBDIR}/deepin-service-manager/) |
||||||
|
install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/plugin-dp4-service.json DESTINATION share/deepin-service-manager/user/) |
||||||
|
endif() |
||||||
|
|
||||||
|
install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/org.deepin.service.dp4.conf DESTINATION share/dbus-1/system.d/) |
||||||
|
install(FILES ${QM_FILES} DESTINATION ${CMAKE_INSTALL_DATADIR}/${PLUGIN_NAME}/translations) |
||||||
@ -0,0 +1,23 @@ |
|||||||
|
// SPDX-FileCopyrightText: 2024 UnionTech Software Technology Co., Ltd.
|
||||||
|
//
|
||||||
|
// SPDX-License-Identifier: LGPL-3.0-or-later
|
||||||
|
|
||||||
|
#include "dp4service.h" |
||||||
|
|
||||||
|
using namespace dp4::service; |
||||||
|
|
||||||
|
Dp4Service::Dp4Service(QObject *parent) |
||||||
|
: QObject(parent) |
||||||
|
{ |
||||||
|
QString test = tr("test"); |
||||||
|
} |
||||||
|
|
||||||
|
QString Dp4Service::getToken() |
||||||
|
{ |
||||||
|
return m_token; |
||||||
|
} |
||||||
|
|
||||||
|
void Dp4Service::setToken(const QString &token) |
||||||
|
{ |
||||||
|
m_token = token; |
||||||
|
} |
||||||
@ -0,0 +1,34 @@ |
|||||||
|
// SPDX-FileCopyrightText: 2024 UnionTech Software Technology Co., Ltd.
|
||||||
|
//
|
||||||
|
// SPDX-License-Identifier: LGPL-3.0-or-later
|
||||||
|
|
||||||
|
#ifndef SESSIONSERVICE_H |
||||||
|
#define SESSIONSERVICE_H |
||||||
|
|
||||||
|
#include <QObject> |
||||||
|
|
||||||
|
namespace dp4 { |
||||||
|
namespace service { |
||||||
|
|
||||||
|
class Dp4Service : public QObject |
||||||
|
{ |
||||||
|
Q_OBJECT |
||||||
|
Q_CLASSINFO("D-Bus Interface", "org.deepin.service.dp4") |
||||||
|
|
||||||
|
Q_PROPERTY(QString token READ getToken WRITE setToken) |
||||||
|
|
||||||
|
public: |
||||||
|
explicit Dp4Service(QObject *parent = nullptr); |
||||||
|
|
||||||
|
private: |
||||||
|
QString getToken(); |
||||||
|
void setToken(const QString &token); |
||||||
|
|
||||||
|
private: |
||||||
|
QString m_token; |
||||||
|
}; |
||||||
|
|
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
#endif // SERVICE_H
|
||||||
@ -0,0 +1,8 @@ |
|||||||
|
#!/bin/bash |
||||||
|
if [ ! -d "translations/" ];then |
||||||
|
mkdir translations |
||||||
|
fi |
||||||
|
cd ./translations |
||||||
|
rm -f dp4-dbus-service.ts |
||||||
|
lupdate ../ -ts -no-ui-lines -locations none -no-obsolete dp4-dbus-service.ts |
||||||
|
cd ../ |
||||||
@ -0,0 +1,19 @@ |
|||||||
|
<?xml version="1.0" encoding="UTF-8"?> <!-- -*- XML -*- --> |
||||||
|
|
||||||
|
<!DOCTYPE busconfig PUBLIC |
||||||
|
"-//freedesktop//DTD D-BUS Bus Configuration 1.0//EN" |
||||||
|
"http://www.freedesktop.org/standards/dbus/1.0/busconfig.dtd"> |
||||||
|
<busconfig> |
||||||
|
|
||||||
|
<!-- Only root can own the service --> |
||||||
|
<policy user="root"> |
||||||
|
<allow own="org.deepin.service.dp4"/> |
||||||
|
<allow send_destination="org.deepin.service.dp4"/> |
||||||
|
</policy> |
||||||
|
|
||||||
|
<!-- Allow anyone to invoke methods on the interfaces --> |
||||||
|
<policy context="default"> |
||||||
|
<allow send_destination="org.deepin.service.dp4"/> |
||||||
|
</policy> |
||||||
|
|
||||||
|
</busconfig> |
||||||
@ -0,0 +1,13 @@ |
|||||||
|
{ |
||||||
|
"name": "org.deepin.service.dp4", |
||||||
|
"libPath": "libdp4-service.so", |
||||||
|
"group": "core", |
||||||
|
"policyStartType": "Resident", |
||||||
|
"pluginType": "qt", |
||||||
|
"startDelay": 0, |
||||||
|
"policy": [ |
||||||
|
{ |
||||||
|
"path": "/org/deepin/service/dp4" |
||||||
|
} |
||||||
|
] |
||||||
|
} |
||||||
@ -0,0 +1,34 @@ |
|||||||
|
// SPDX-FileCopyrightText: 2023 UnionTech Software Technology Co., Ltd.
|
||||||
|
//
|
||||||
|
// SPDX-License-Identifier: LGPL-3.0-or-later
|
||||||
|
#include "dp4service.h" |
||||||
|
|
||||||
|
#include <QDBusConnection> |
||||||
|
#include <QDebug> |
||||||
|
|
||||||
|
#include <unistd.h> |
||||||
|
|
||||||
|
static dp4::service::Dp4Service *serviceObject = nullptr; |
||||||
|
|
||||||
|
extern "C" int DSMRegister(const char *name, void *data) |
||||||
|
{ |
||||||
|
QDBusConnection::RegisterOptions opts = QDBusConnection::ExportAllSlots |
||||||
|
| QDBusConnection::ExportAllSignals | QDBusConnection::ExportAllProperties; |
||||||
|
|
||||||
|
QString path = name; |
||||||
|
path = QString("/%1").arg(path.replace(".", "/")); |
||||||
|
auto connection = reinterpret_cast<QDBusConnection *>(data); |
||||||
|
serviceObject = new dp4::service::Dp4Service; |
||||||
|
connection->registerObject(path, serviceObject, opts); |
||||||
|
return 0; |
||||||
|
} |
||||||
|
|
||||||
|
// 该函数用于资源释放
|
||||||
|
// 非常驻插件必须实现该函数,以防内存泄漏
|
||||||
|
extern "C" int DSMUnRegister(const char *name, void *data) |
||||||
|
{ |
||||||
|
(void)name; |
||||||
|
(void)data; |
||||||
|
serviceObject->deleteLater(); |
||||||
|
return 0; |
||||||
|
} |
||||||
@ -0,0 +1,37 @@ |
|||||||
|
cmake_minimum_required(VERSION 3.7) |
||||||
|
|
||||||
|
set(LIB_NAME "dp4-login-plugin") |
||||||
|
|
||||||
|
project(${LIB_NAME}) |
||||||
|
|
||||||
|
include(GNUInstallDirs) |
||||||
|
|
||||||
|
# 启用 qt moc 的支持 |
||||||
|
set(CMAKE_AUTOMOC ON) |
||||||
|
|
||||||
|
find_package(Qt5 COMPONENTS Core Widgets DBus Network LinguistTools REQUIRED) |
||||||
|
find_package(PkgConfig REQUIRED) |
||||||
|
find_package(DdeSessionShell REQUIRED) |
||||||
|
|
||||||
|
pkg_check_modules(SSL REQUIRED IMPORTED_TARGET libcrypto libssl openssl) |
||||||
|
|
||||||
|
file(GLOB TS_FILES "translations/*.ts") |
||||||
|
qt5_add_translation(QM_FILES ${TS_FILES}) |
||||||
|
add_custom_target(${BIN_NAME}_language ALL DEPENDS ${QM_FILES}) |
||||||
|
|
||||||
|
file(GLOB_RECURSE SRCS "*.h" "*.cpp") |
||||||
|
|
||||||
|
add_library(${LIB_NAME} SHARED ${SRCS}) |
||||||
|
|
||||||
|
target_include_directories(${LIB_NAME} PUBLIC |
||||||
|
${Qt5DBus_INCLUDE_DIRS} |
||||||
|
${DDESESSIONSHELL_INCLUDE_DIR} |
||||||
|
) |
||||||
|
|
||||||
|
target_link_libraries(${LIB_NAME} PRIVATE |
||||||
|
${Qt5Widgets_LIBRARIES} |
||||||
|
${Qt5DBus_LIBRARIES} |
||||||
|
) |
||||||
|
|
||||||
|
install(TARGETS ${LIB_NAME} LIBRARY DESTINATION lib/dde-session-shell/modules)# 安装.qm文件 |
||||||
|
install(FILES ${QM_FILES} DESTINATION ${CMAKE_INSTALL_DATADIR}/${LIB_NAME}/translations/) |
||||||
@ -0,0 +1,97 @@ |
|||||||
|
// SPDX-FileCopyrightText: 2015 - 2022 UnionTech Software Technology Co., Ltd.
|
||||||
|
//
|
||||||
|
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
#include "dp4_login_module.h" |
||||||
|
|
||||||
|
namespace dss |
||||||
|
{ |
||||||
|
namespace module |
||||||
|
{ |
||||||
|
|
||||||
|
Dp4LoginModule::Dp4LoginModule(QObject *parent) |
||||||
|
: QObject(parent) |
||||||
|
, m_callbackFun(nullptr) |
||||||
|
, m_callbackData(new AuthCallbackData) |
||||||
|
, m_messageCallbackFunc(nullptr) |
||||||
|
{ |
||||||
|
setObjectName(QStringLiteral("AssistLoginModule")); |
||||||
|
|
||||||
|
QString testText = tr("test"); |
||||||
|
// 以下部分爲測試代碼,具體如何寫請根據實際的業務來處理即可
|
||||||
|
/*m_callbackData->account = "uos";
|
||||||
|
m_callbackData->token = "1"; |
||||||
|
m_callbackData->result = 0; |
||||||
|
*/ |
||||||
|
} |
||||||
|
|
||||||
|
Dp4LoginModule::~Dp4LoginModule() |
||||||
|
{ |
||||||
|
if (m_callbackData) { |
||||||
|
delete m_callbackData; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
void Dp4LoginModule::init() |
||||||
|
{ |
||||||
|
} |
||||||
|
|
||||||
|
QWidget *Dp4LoginModule::content() |
||||||
|
{ |
||||||
|
return nullptr; |
||||||
|
} |
||||||
|
|
||||||
|
void Dp4LoginModule::reset() |
||||||
|
{ |
||||||
|
init(); |
||||||
|
} |
||||||
|
|
||||||
|
void Dp4LoginModule::setCallback(LoginCallBack *callback) |
||||||
|
{ |
||||||
|
m_callback = callback; |
||||||
|
m_callbackFun = callback->authCallbackFun; |
||||||
|
} |
||||||
|
|
||||||
|
std::string Dp4LoginModule::onMessage(const std::string &message) |
||||||
|
{ |
||||||
|
qInfo() << Q_FUNC_INFO; |
||||||
|
QJsonParseError jsonParseError; |
||||||
|
const QJsonDocument messageDoc = QJsonDocument::fromJson(QByteArray::fromStdString(message), &jsonParseError); |
||||||
|
if (jsonParseError.error != QJsonParseError::NoError || messageDoc.isEmpty()) { |
||||||
|
qWarning() << Q_FUNC_INFO << "Failed to obtain message from shell!: " << QString::fromStdString(message); |
||||||
|
return ""; |
||||||
|
} |
||||||
|
|
||||||
|
QJsonObject retObj; |
||||||
|
retObj["Code"] = 0; |
||||||
|
retObj["Message"] = "Success"; |
||||||
|
|
||||||
|
QJsonObject msgObj = messageDoc.object(); |
||||||
|
QString cmdType = msgObj.value("CmdType").toString(); |
||||||
|
QJsonObject data = msgObj.value("Data").toObject(); |
||||||
|
qInfo() << "Cmd type: " << cmdType; |
||||||
|
if (cmdType == "CurrentUserChanged") { |
||||||
|
|
||||||
|
} else if (cmdType == "GetConfigs") { |
||||||
|
QJsonObject retDataObj; |
||||||
|
retDataObj["ShowAvatar"] = false; |
||||||
|
retDataObj["ShowUserName"] = false; |
||||||
|
retDataObj["ShowSwitchButton"] = false; |
||||||
|
retDataObj["ShowLockButton"] = false; |
||||||
|
retDataObj["DefaultAuthLevel"] = DefaultAuthLevel::StrongDefault; |
||||||
|
retDataObj["AuthType"] = AuthType::AT_Custom; |
||||||
|
|
||||||
|
retObj["Data"] = retDataObj; |
||||||
|
} else if (cmdType == "StartAuth") { |
||||||
|
|
||||||
|
} else if (cmdType == "AuthState") { |
||||||
|
|
||||||
|
} else if (cmdType == "LimitsInfo") { |
||||||
|
} |
||||||
|
|
||||||
|
QJsonDocument doc; |
||||||
|
doc.setObject(retObj); |
||||||
|
return doc.toJson().toStdString(); |
||||||
|
} |
||||||
|
|
||||||
|
} |
||||||
|
} |
||||||
@ -0,0 +1,44 @@ |
|||||||
|
// SPDX-FileCopyrightText: 2015 - 2022 UnionTech Software Technology Co., Ltd.
|
||||||
|
//
|
||||||
|
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
|
||||||
|
#ifndef ASSIST_LOGIN_MODULE_H |
||||||
|
#define ASSIST_LOGIN_MODULE_H |
||||||
|
|
||||||
|
#include "login_module_interface.h" |
||||||
|
|
||||||
|
namespace dss |
||||||
|
{ |
||||||
|
namespace module |
||||||
|
{ |
||||||
|
class Dp4LoginModule: public QObject, public LoginModuleInterface |
||||||
|
{ |
||||||
|
Q_OBJECT |
||||||
|
|
||||||
|
Q_PLUGIN_METADATA(IID "com.deepin.dde.shell.Modules.Login" FILE "login.json") |
||||||
|
Q_INTERFACES(dss::module::LoginModuleInterface) |
||||||
|
|
||||||
|
public: |
||||||
|
explicit Dp4LoginModule(QObject *parent = nullptr); |
||||||
|
~Dp4LoginModule() override; |
||||||
|
|
||||||
|
void init() override; |
||||||
|
ModuleType type() const override |
||||||
|
{ return IpcAssistLoginType; } |
||||||
|
inline QString key() const override |
||||||
|
{ return "dp4-login"; } |
||||||
|
QWidget *content() override; |
||||||
|
void setCallback(LoginCallBack *callback) override; |
||||||
|
std::string onMessage(const std::string &) override; |
||||||
|
void reset() override; |
||||||
|
|
||||||
|
private: |
||||||
|
LoginCallBack *m_callback; |
||||||
|
AuthCallbackFun m_callbackFun; |
||||||
|
AuthCallbackData *m_callbackData; |
||||||
|
MessageCallbackFun m_messageCallbackFunc; |
||||||
|
}; |
||||||
|
|
||||||
|
} |
||||||
|
} |
||||||
|
#endif //ASSIST_LOGIN_MODULE_H
|
||||||
@ -0,0 +1,4 @@ |
|||||||
|
{ |
||||||
|
"api": "1.2.0", |
||||||
|
"pluginType": "Login" |
||||||
|
} |
||||||
@ -0,0 +1,8 @@ |
|||||||
|
#!/bin/bash |
||||||
|
if [ ! -d "translations/" ];then |
||||||
|
mkdir translations |
||||||
|
fi |
||||||
|
cd ./translations |
||||||
|
rm -f dp4-login-plugin.ts |
||||||
|
lupdate ../ -ts -no-ui-lines -locations none -no-obsolete dp4-login-plugin.ts |
||||||
|
cd ../ |
||||||
@ -0,0 +1,20 @@ |
|||||||
|
cmake_minimum_required(VERSION 3.7) |
||||||
|
|
||||||
|
set(PAM_LIB_NAME "dp4-login-pam") |
||||||
|
|
||||||
|
file(GLOB_RECURSE LIB_SRCS |
||||||
|
"*.h" |
||||||
|
"*.c" |
||||||
|
) |
||||||
|
|
||||||
|
add_library(${PAM_LIB_NAME} MODULE |
||||||
|
${LIB_SRCS} |
||||||
|
) |
||||||
|
|
||||||
|
set_target_properties(${PAM_LIB_NAME} PROPERTIES PREFIX "") |
||||||
|
|
||||||
|
target_link_libraries(${PAM_LIB_NAME} PRIVATE |
||||||
|
-lpam |
||||||
|
) |
||||||
|
|
||||||
|
install(TARGETS ${PAM_LIB_NAME} DESTINATION ${CMAKE_INSTALL_LIBDIR}/security) |
||||||
@ -0,0 +1,41 @@ |
|||||||
|
#include <stdio.h> |
||||||
|
#include <security/_pam_types.h> |
||||||
|
#include <security/pam_modules.h> |
||||||
|
#include <security/pam_ext.h> |
||||||
|
#include <sys/syslog.h> |
||||||
|
|
||||||
|
// PAM 认证函数
|
||||||
|
PAM_EXTERN int pam_sm_authenticate(pam_handle_t *pamh, int flags, int argc, const char **argv) |
||||||
|
{ |
||||||
|
// 获取用户名
|
||||||
|
const char *username = NULL; |
||||||
|
int nret = pam_get_item(pamh, PAM_USER, (const void **)&username); |
||||||
|
pam_syslog(pamh, LOG_WARNING, "in test login,get username..%s..ret:%d.....", username, nret); |
||||||
|
if (nret != PAM_SUCCESS) { |
||||||
|
return PAM_AUTH_ERR; |
||||||
|
} |
||||||
|
|
||||||
|
// 获取密码
|
||||||
|
const char *password = NULL; |
||||||
|
int retpwd = pam_get_item(pamh, PAM_AUTHTOK, (const void **)&password); |
||||||
|
if (retpwd == PAM_SUCCESS) { |
||||||
|
pam_syslog(pamh, LOG_WARNING, "password: %s", password); |
||||||
|
} else { |
||||||
|
pam_syslog(pamh, LOG_WARNING, "get password failed: %d", retpwd); |
||||||
|
} |
||||||
|
|
||||||
|
for (int i = 0; i < argc; i++) { |
||||||
|
pam_syslog(pamh, LOG_WARNING, "input parameter: %s", argv[i]); |
||||||
|
} |
||||||
|
return PAM_SUCCESS; |
||||||
|
} |
||||||
|
|
||||||
|
PAM_EXTERN int pam_sm_setcred(pam_handle_t *pamh, int flags, int argc, const char **argv) |
||||||
|
{ |
||||||
|
pam_syslog(pamh, LOG_WARNING, "in test login,pam_sm_setcred...., flags:%d, argc:%d", flags, argc); |
||||||
|
for (int i = 0; i < argc; i++) { |
||||||
|
pam_syslog(pamh, LOG_WARNING, "input parameter: %s", argv[i]); |
||||||
|
} |
||||||
|
|
||||||
|
return PAM_SUCCESS; |
||||||
|
} |
||||||
@ -0,0 +1,61 @@ |
|||||||
|
cmake_minimum_required(VERSION 3.7) |
||||||
|
|
||||||
|
project(example) |
||||||
|
|
||||||
|
include(GNUInstallDirs) |
||||||
|
if (CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT) |
||||||
|
set(CMAKE_INSTALL_PREFIX /usr) |
||||||
|
endif () |
||||||
|
|
||||||
|
set(CMAKE_CXX_STANDARD 11) |
||||||
|
set(CMAKE_INCLUDE_CURRENT_DIR ON) |
||||||
|
set(CMAKE_PREFIX_PATH $ENV{Qt5_DIR}) |
||||||
|
set(CMAKE_AUTOMOC ON) |
||||||
|
set(CMAKE_AUTORCC ON) |
||||||
|
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -g -Wall") |
||||||
|
set(CMAKE_MODULE_PATH ${CMAKE_SOURCE_DIR}/cmake/modules) |
||||||
|
|
||||||
|
if (CMAKE_BUILD_TYPE STREQUAL "Debug") |
||||||
|
ADD_DEFINITIONS(-DSERVICE_CONFIG_DIR="${CMAKE_BINARY_DIR}/share/") |
||||||
|
ADD_DEFINITIONS(-DSERVICE_LIB_DIR="${CMAKE_BINARY_DIR}/network-service-plugin/") |
||||||
|
else() |
||||||
|
ADD_DEFINITIONS(-DSERVICE_CONFIG_DIR="${CMAKE_INSTALL_PREFIX}/share/deepin-service-manager/") |
||||||
|
ADD_DEFINITIONS(-DSERVICE_LIB_DIR="${CMAKE_INSTALL_FULL_LIBDIR}/deepin-service-manager/") |
||||||
|
endif() |
||||||
|
|
||||||
|
file(GLOB_RECURSE COMPILEFILES *.h *.cpp ../dp4-login-plugin/*.h ../dp4-login-plugin/*.cpp) |
||||||
|
|
||||||
|
if (CMAKE_BUILD_TYPE STREQUAL "Debug") |
||||||
|
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -g -fsanitize=address -O0") |
||||||
|
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -g -fsanitize=address -O0") |
||||||
|
endif() |
||||||
|
|
||||||
|
add_executable(${PROJECT_NAME} ${COMPILEFILES}) |
||||||
|
|
||||||
|
find_package(PAM REQUIRED) |
||||||
|
find_package(Qt5 COMPONENTS Core Widgets DBus Network REQUIRED) |
||||||
|
find_package(DdeSessionShell REQUIRED) |
||||||
|
|
||||||
|
set(TRY_KF5_LIBRARIES |
||||||
|
IMPORTED_LOCATION_DEBIAN |
||||||
|
IMPORTED_LOCATION_NOCONFIG |
||||||
|
) |
||||||
|
|
||||||
|
target_include_directories(${PROJECT_NAME} PUBLIC |
||||||
|
./service |
||||||
|
../dp4-login-plugin/ |
||||||
|
${PAM_INCLUDE_DIR} |
||||||
|
${Qt5Widget_INCLUDE_DIRS} |
||||||
|
${Qt5Core_INCLUDE_DIRS} |
||||||
|
${Qt5DBus_INCLUDE_DIRS} |
||||||
|
${Qt5Network_INCLUDE_DIRS} |
||||||
|
${DDESESSIONSHELL_INCLUDE_DIR} |
||||||
|
) |
||||||
|
|
||||||
|
target_link_libraries(${PROJECT_NAME} PRIVATE |
||||||
|
${PAM_LIBRARIES} |
||||||
|
${Qt5Widgets_LIBRARIES} |
||||||
|
${Qt5Core_LIBRARIES} |
||||||
|
${Qt5DBus_LIBRARIES} |
||||||
|
${Qt5Network_LIBRARIES} |
||||||
|
) |
||||||
@ -0,0 +1,18 @@ |
|||||||
|
#include "loginwidget.h" |
||||||
|
#include "dp4_login_module.h" |
||||||
|
|
||||||
|
#include <QHBoxLayout> |
||||||
|
|
||||||
|
LoginWidget::LoginWidget(QWidget *parent) |
||||||
|
: QWidget (parent) |
||||||
|
, m_dp4module(new dss::module::Dp4LoginModule(this)) |
||||||
|
{ |
||||||
|
QHBoxLayout *layout = new QHBoxLayout(this); |
||||||
|
layout->setContentsMargins(0, 0, 0, 0); |
||||||
|
layout->setSpacing(0); |
||||||
|
layout->addWidget(m_dp4module->content()); |
||||||
|
} |
||||||
|
|
||||||
|
LoginWidget::~LoginWidget() |
||||||
|
{ |
||||||
|
} |
||||||
@ -0,0 +1,24 @@ |
|||||||
|
#ifndef LOGINWIDGET_H |
||||||
|
#define LOGINWIDGET_H |
||||||
|
|
||||||
|
#include <QWidget> |
||||||
|
|
||||||
|
namespace dss { |
||||||
|
namespace module { |
||||||
|
class Dp4LoginModule; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
class LoginWidget : public QWidget |
||||||
|
{ |
||||||
|
Q_OBJECT |
||||||
|
|
||||||
|
public: |
||||||
|
LoginWidget(QWidget *parent = nullptr); |
||||||
|
~LoginWidget(); |
||||||
|
|
||||||
|
private: |
||||||
|
dss::module::Dp4LoginModule *m_dp4module; |
||||||
|
}; |
||||||
|
|
||||||
|
#endif |
||||||
@ -0,0 +1,47 @@ |
|||||||
|
// SPDX-FileCopyrightText: 2022 UnionTech Software Technology Co., Ltd.
|
||||||
|
//
|
||||||
|
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
|
||||||
|
#include "serviceqtdbus.h" |
||||||
|
#include "loginwidget.h" |
||||||
|
#include "pamtest.h" |
||||||
|
|
||||||
|
#include <QApplication> |
||||||
|
#include <QDesktopWidget> |
||||||
|
#include <QTranslator> |
||||||
|
|
||||||
|
#include <unistd.h> |
||||||
|
|
||||||
|
using namespace std; |
||||||
|
|
||||||
|
int main(int argc, char *argv[]) |
||||||
|
{ |
||||||
|
QApplication app(argc, argv); |
||||||
|
|
||||||
|
if (QString(argv[1]) == "service") { |
||||||
|
// 新建deepinServiceManager的服务
|
||||||
|
QString fileName = QString("%1user/plugin-dp4-service.json").arg(SERVICE_CONFIG_DIR); |
||||||
|
Policy policy(nullptr); |
||||||
|
policy.parseConfig(fileName); |
||||||
|
ServiceQtDBus service; |
||||||
|
service.init(QDBusConnection::BusType::SessionBus, &policy); |
||||||
|
return app.exec(); |
||||||
|
} |
||||||
|
|
||||||
|
if (QString(argv[1]) == "login") { |
||||||
|
// 登錄插件的demo
|
||||||
|
LoginWidget widget; |
||||||
|
widget.show(); |
||||||
|
widget.resize(500, 500); |
||||||
|
return app.exec(); |
||||||
|
} |
||||||
|
|
||||||
|
if (QString(argv[1]) == "pam") { |
||||||
|
// 測試pam
|
||||||
|
PamTest test; |
||||||
|
test.startPam(); |
||||||
|
return app.exec(); |
||||||
|
} |
||||||
|
|
||||||
|
return app.exec(); |
||||||
|
} |
||||||
@ -0,0 +1,57 @@ |
|||||||
|
#include "pamtest.h" |
||||||
|
|
||||||
|
#include <QDebug> |
||||||
|
|
||||||
|
#include <security/pam_appl.h> |
||||||
|
|
||||||
|
PamTest::PamTest(QObject *parent) |
||||||
|
: QObject (parent) |
||||||
|
{ |
||||||
|
} |
||||||
|
|
||||||
|
PamTest::~PamTest() |
||||||
|
{ |
||||||
|
} |
||||||
|
|
||||||
|
void PamTest::startPam() |
||||||
|
{ |
||||||
|
pam_handle_t *pamHandle = nullptr; |
||||||
|
pam_conv conv = {PAMConversation, static_cast<void *>(this)}; |
||||||
|
// pam_start第一個參數對應於/etc/pam.d下面的指定的PAM文件,第二個參數對應於登錄的賬戶名
|
||||||
|
int ret = pam_start("test_pam", "uos", &conv, &pamHandle); |
||||||
|
if (ret != PAM_SUCCESS) { |
||||||
|
//qCritical() << "ERROR: PAM start failed, error: " << pam_strerror(pamHandle, ret) << ", start infomation: " << ret;
|
||||||
|
} else { |
||||||
|
qDebug() << "PAM start..."; |
||||||
|
} |
||||||
|
|
||||||
|
// 可以在此處設置密碼
|
||||||
|
//const char *password = "testpassword";
|
||||||
|
//pam_set_item(pamHandle, PAM_AUTHTOK, password);
|
||||||
|
|
||||||
|
int rc = pam_authenticate(pamHandle, 0); |
||||||
|
if (rc != PAM_SUCCESS) { |
||||||
|
//qWarning() << "PAM authenticate failed, error: " << pam_strerror(pamHandle, rc) << ", PAM authenticate: " << rc;
|
||||||
|
} else { |
||||||
|
qDebug() << "PAM authenticate finished."; |
||||||
|
} |
||||||
|
|
||||||
|
int tmpRt = pam_acct_mgmt(pamHandle, 1); |
||||||
|
if (tmpRt != PAM_SUCCESS) { |
||||||
|
//qCritical() << "PAM acct failed:" << pam_strerror(pamHandle, tmpRt) << "PAM end infomation: " << tmpRt;
|
||||||
|
} else { |
||||||
|
qDebug() << "PAM acct finished."; |
||||||
|
} |
||||||
|
|
||||||
|
int re = pam_end(pamHandle, rc); |
||||||
|
if (re != PAM_SUCCESS) { |
||||||
|
//qCritical() << "PAM end failed:" << pam_strerror(pamHandle, re) << "PAM end infomation: " << re;
|
||||||
|
} else { |
||||||
|
qDebug() << "PAM end..."; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
int PamTest::PAMConversation(int num_msg, const pam_message **msg, pam_response **resp, void *app_data) |
||||||
|
{ |
||||||
|
return PAM_SUCCESS; |
||||||
|
} |
||||||
@ -0,0 +1,23 @@ |
|||||||
|
#ifndef PAMTEST_H |
||||||
|
#define PAMTEST_H |
||||||
|
|
||||||
|
#include <QObject> |
||||||
|
|
||||||
|
#include <security/_pam_types.h> |
||||||
|
|
||||||
|
class PamTest : public QObject |
||||||
|
{ |
||||||
|
Q_OBJECT |
||||||
|
|
||||||
|
public: |
||||||
|
PamTest(QObject *parent = nullptr); |
||||||
|
~PamTest(); |
||||||
|
|
||||||
|
void startPam(); |
||||||
|
|
||||||
|
private: |
||||||
|
static int PAMConversation(int num_msg, const pam_message **msg, pam_response **resp, void *app_data); |
||||||
|
|
||||||
|
}; |
||||||
|
|
||||||
|
#endif |
||||||
@ -0,0 +1,542 @@ |
|||||||
|
// SPDX-FileCopyrightText: 2023 UnionTech Software Technology Co., Ltd.
|
||||||
|
//
|
||||||
|
// SPDX-License-Identifier: LGPL-3.0-or-later
|
||||||
|
|
||||||
|
#include "policy.h" |
||||||
|
|
||||||
|
#include <QDebug> |
||||||
|
#include <QFile> |
||||||
|
#include <QJsonArray> |
||||||
|
#include <QJsonDocument> |
||||||
|
#include <QJsonObject> |
||||||
|
#include <QLoggingCategory> |
||||||
|
|
||||||
|
Q_LOGGING_CATEGORY(dsm_policy, "[Policy]") |
||||||
|
|
||||||
|
Policy::Policy(QObject *parent) |
||||||
|
: QObject(parent) |
||||||
|
{ |
||||||
|
} |
||||||
|
|
||||||
|
bool Policy::checkPathHide(const QString &path) |
||||||
|
{ |
||||||
|
QMapPathHide::iterator iter = mapPathHide.find(path); |
||||||
|
if (iter == mapPathHide.end()) { |
||||||
|
return false; |
||||||
|
} |
||||||
|
return iter.value(); |
||||||
|
} |
||||||
|
|
||||||
|
bool Policy::checkMethodPermission(const QString &process, |
||||||
|
const QString &path, |
||||||
|
const QString &interface, |
||||||
|
const QString &method) |
||||||
|
{ |
||||||
|
return checkPermission(process, path, interface, method, CallDestType::Method); |
||||||
|
} |
||||||
|
|
||||||
|
bool Policy::checkPropertyPermission(const QString &process, |
||||||
|
const QString &path, |
||||||
|
const QString &interface, |
||||||
|
const QString &property) |
||||||
|
{ |
||||||
|
return checkPermission(process, path, interface, property, CallDestType::Property); |
||||||
|
} |
||||||
|
|
||||||
|
bool Policy::checkPermission(const QString &process, |
||||||
|
const QString &path, |
||||||
|
const QString &interface, |
||||||
|
const QString &dest, |
||||||
|
const CallDestType &type) |
||||||
|
{ |
||||||
|
qCInfo(dsm_policy) << "check permission:" |
||||||
|
<< QString("process=%1, path=%2, interface=%3, dest=%4") |
||||||
|
.arg(process, path, interface, dest); |
||||||
|
// 时间复杂度跟权限配置复杂度正相关,简单的配置就会校验很快
|
||||||
|
QMapPath::const_iterator iterPath = mapPath.find(path); |
||||||
|
if (iterPath == mapPath.end()) { |
||||||
|
// 默认不校验,即有权限
|
||||||
|
return true; |
||||||
|
} |
||||||
|
|
||||||
|
// PATH权限
|
||||||
|
const PolicyPath &policyPath = iterPath.value(); |
||||||
|
QMapInterface::const_iterator iterInterface = policyPath.interfaces.find(interface); |
||||||
|
if (iterInterface == policyPath.interfaces.end()) { |
||||||
|
// 没有配置interface权限,则用path权限
|
||||||
|
if (!policyPath.needPermission) { |
||||||
|
return true; |
||||||
|
} |
||||||
|
return policyPath.processes.contains(process); |
||||||
|
} |
||||||
|
|
||||||
|
if (type == CallDestType::Method) { |
||||||
|
// INTERFACE权限
|
||||||
|
const PolicyInterface &policyInterface = iterInterface.value(); |
||||||
|
QMapMethod::const_iterator iterMethod = policyInterface.methods.find(dest); |
||||||
|
if (iterMethod == policyInterface.methods.end()) { |
||||||
|
if (!policyInterface.needPermission) { |
||||||
|
return true; |
||||||
|
} |
||||||
|
return policyInterface.processes.contains(process); |
||||||
|
} |
||||||
|
// METHOD权限
|
||||||
|
const PolicyMethod &policyMethod = iterMethod.value(); |
||||||
|
if (!policyMethod.needPermission) { |
||||||
|
return true; |
||||||
|
} |
||||||
|
return policyMethod.processes.contains(process); |
||||||
|
|
||||||
|
} else if (type == CallDestType::Property) { |
||||||
|
// INTERFACE权限
|
||||||
|
const PolicyInterface &policyInterface = iterInterface.value(); |
||||||
|
QMapProperty::const_iterator iterProp = policyInterface.properties.find(dest); |
||||||
|
if (iterProp == policyInterface.properties.end()) { |
||||||
|
if (!policyInterface.needPermission) { |
||||||
|
return true; |
||||||
|
} |
||||||
|
return policyInterface.processes.contains(process); |
||||||
|
} |
||||||
|
// PROPERTY权限
|
||||||
|
const PolicyProperty &policyProp = iterProp.value(); |
||||||
|
if (!policyProp.needPermission) { |
||||||
|
return true; |
||||||
|
} |
||||||
|
return policyProp.processes.contains(process); |
||||||
|
} |
||||||
|
|
||||||
|
qCWarning(dsm_policy) << "check permission error!"; |
||||||
|
return false; |
||||||
|
} |
||||||
|
|
||||||
|
QStringList Policy::paths() const |
||||||
|
{ |
||||||
|
return mapSubPath.keys(); |
||||||
|
} |
||||||
|
|
||||||
|
bool Policy::allowSubPath(const QString &path) const |
||||||
|
{ |
||||||
|
auto iter = mapSubPath.find(path); |
||||||
|
if (iter != mapSubPath.end()) { |
||||||
|
return iter.value(); |
||||||
|
} |
||||||
|
return false; |
||||||
|
} |
||||||
|
|
||||||
|
bool Policy::isResident() const |
||||||
|
{ |
||||||
|
return startType == "Resident"; |
||||||
|
} |
||||||
|
|
||||||
|
void Policy::print() |
||||||
|
{ |
||||||
|
qInfo() << "-------------------------------------"; |
||||||
|
qInfo() << "DBUS POLICY CONFIG"; |
||||||
|
qInfo() << "- name:" << name; |
||||||
|
qInfo() << "- path hide"; |
||||||
|
for (QMapPathHide::iterator iter = mapPathHide.begin(); iter != mapPathHide.end(); iter++) { |
||||||
|
qInfo() << "-- path hide:" << iter.key() << iter.value(); |
||||||
|
} |
||||||
|
qInfo() << "- whitelist"; |
||||||
|
for (QMapWhitelists::iterator iter = mapWhitelist.begin(); iter != mapWhitelist.end(); iter++) { |
||||||
|
qInfo() << "-- whitelist:" << iter.key() << iter.value().name << iter.value().process; |
||||||
|
} |
||||||
|
qInfo() << "- policy"; |
||||||
|
for (QMapPath::iterator iter = mapPath.begin(); iter != mapPath.end(); iter++) { |
||||||
|
qInfo() << "-- path:" << iter.key() << iter.value().path; |
||||||
|
qInfo() << "-- permission:" << iter.value().needPermission; |
||||||
|
qInfo() << "-- whitelist:" << iter.value().processes; |
||||||
|
for (QMapInterface::iterator iterInterface = iter.value().interfaces.begin(); |
||||||
|
iterInterface != iter.value().interfaces.end(); |
||||||
|
iterInterface++) { |
||||||
|
qInfo() << "---- interface:" << iterInterface.key() << iterInterface.value().interface; |
||||||
|
qInfo() << "---- permission:" << iterInterface.value().needPermission; |
||||||
|
qInfo() << "---- whitelist:" << iterInterface.value().processes; |
||||||
|
for (QMapMethod::iterator iterMethod = iterInterface.value().methods.begin(); |
||||||
|
iterMethod != iterInterface.value().methods.end(); |
||||||
|
iterMethod++) { |
||||||
|
qInfo() << "------ method:" << iterMethod.key() << iterMethod.value().method; |
||||||
|
qInfo() << "------ permission:" << iterMethod.value().needPermission; |
||||||
|
qInfo() << "------ whitelist:" << iterMethod.value().processes; |
||||||
|
} |
||||||
|
for (QMapProperty::iterator iterProp = iterInterface.value().properties.begin(); |
||||||
|
iterProp != iterInterface.value().properties.end(); |
||||||
|
iterProp++) { |
||||||
|
qInfo() << "------ property:" << iterProp.key() << iterProp.value().property; |
||||||
|
qInfo() << "------ permission:" << iterProp.value().needPermission; |
||||||
|
qInfo() << "------ whitelist:" << iterProp.value().processes; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
qInfo() << "-------------------------------------"; |
||||||
|
} |
||||||
|
|
||||||
|
void Policy::parseConfig(const QString &path) |
||||||
|
{ |
||||||
|
qCInfo(dsm_policy) << "parse config:" << path; |
||||||
|
if (path.isEmpty()) { |
||||||
|
qCWarning(dsm_policy) << "path is empty!"; |
||||||
|
return; |
||||||
|
} |
||||||
|
QJsonDocument jsonDoc; |
||||||
|
if (!readJsonFile(jsonDoc, path)) { |
||||||
|
qCWarning(dsm_policy) << "read json file failed!"; |
||||||
|
return; |
||||||
|
} |
||||||
|
QJsonObject rootObj = jsonDoc.object(); |
||||||
|
jsonGetString(rootObj, "name", name); |
||||||
|
jsonGetString(rootObj, "group", group, "app"); |
||||||
|
jsonGetString(rootObj, "libPath", pluginPath); // 兼容
|
||||||
|
jsonGetString(rootObj, "pluginPath", pluginPath, pluginPath); |
||||||
|
jsonGetString(rootObj, "policyVersion", version, "1.0"); // 兼容
|
||||||
|
jsonGetString(rootObj, "version", version, version); |
||||||
|
jsonGetString(rootObj, "policyStartType", startType, "Resident"); // 兼容
|
||||||
|
jsonGetString(rootObj, "startType", startType, startType); |
||||||
|
jsonGetStringList(rootObj, "dependencies", dependencies); |
||||||
|
jsonGetInt(rootObj, "startDelay", startDelay, 0); |
||||||
|
jsonGetInt(rootObj, "idleTime", idleTime, 10); |
||||||
|
// get SDKType
|
||||||
|
QString sdkTypeString; |
||||||
|
jsonGetString(rootObj, "pluginType", sdkTypeString, "qt"); |
||||||
|
if (sdkTypeString == "qt") |
||||||
|
sdkType = SDKType::QT; |
||||||
|
if (sdkTypeString == "sd") |
||||||
|
sdkType = SDKType::SD; |
||||||
|
|
||||||
|
if (name.isEmpty()) { |
||||||
|
qCWarning(dsm_policy) << "json error, name is empty."; |
||||||
|
return; |
||||||
|
} |
||||||
|
if (!parseWhitelist(rootObj)) { |
||||||
|
qCWarning(dsm_policy) << "json error, parse whitelist error."; |
||||||
|
return; |
||||||
|
} |
||||||
|
|
||||||
|
if (!parsePolicy(rootObj)) { |
||||||
|
qCWarning(dsm_policy) << "json error, parse policy error."; |
||||||
|
return; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
bool Policy::readJsonFile(QJsonDocument &outDoc, const QString &fileName) |
||||||
|
{ |
||||||
|
QFile jsonFIle(fileName); |
||||||
|
if (!jsonFIle.open(QIODevice::ReadOnly)) { |
||||||
|
qCWarning(dsm_policy) << QString("open file: %1 error!").arg(fileName); |
||||||
|
return false; |
||||||
|
} |
||||||
|
|
||||||
|
QJsonParseError jsonParserError; |
||||||
|
outDoc = QJsonDocument::fromJson(jsonFIle.readAll(), &jsonParserError); |
||||||
|
jsonFIle.close(); |
||||||
|
if (jsonParserError.error != QJsonParseError::NoError) { |
||||||
|
qCWarning(dsm_policy) << "to json document error: " << jsonParserError.errorString(); |
||||||
|
return false; |
||||||
|
} |
||||||
|
if (outDoc.isNull()) { |
||||||
|
qCWarning(dsm_policy) << "json document is null!"; |
||||||
|
return false; |
||||||
|
} |
||||||
|
return true; |
||||||
|
} |
||||||
|
|
||||||
|
// typedef QMap<QString, PolicyWhitelist> QMapWhitelists;
|
||||||
|
bool Policy::parseWhitelist(const QJsonObject &obj) |
||||||
|
{ |
||||||
|
mapWhitelist.clear(); |
||||||
|
if (!obj.contains("whitelists")) { |
||||||
|
// 为空,不是出错
|
||||||
|
return true; |
||||||
|
} |
||||||
|
QJsonValue listsValue = obj.value("whitelists"); |
||||||
|
if (!listsValue.isArray()) { |
||||||
|
qCWarning(dsm_policy) << "parse whitelist error, must be json array!"; |
||||||
|
return false; |
||||||
|
} |
||||||
|
QJsonArray lists = listsValue.toArray(); |
||||||
|
for (int i = 0; i < lists.size(); ++i) { |
||||||
|
QJsonValue whitelistValue = lists.at(i); |
||||||
|
if (whitelistValue.isObject()) { |
||||||
|
PolicyWhitelist whitelist; |
||||||
|
QJsonObject whitelistObj = whitelistValue.toObject(); |
||||||
|
QString name; |
||||||
|
jsonGetString(whitelistObj, "name", name); |
||||||
|
if (name.isEmpty()) { |
||||||
|
continue; |
||||||
|
} |
||||||
|
if (!whitelistObj.contains("process")) { |
||||||
|
continue; |
||||||
|
} |
||||||
|
QJsonArray processes = whitelistObj.value("process").toArray(); |
||||||
|
if (processes.size() <= 0) { |
||||||
|
continue; |
||||||
|
} |
||||||
|
whitelist.name = name; |
||||||
|
for (int j = 0; j < processes.size(); ++j) { |
||||||
|
if (processes.at(j).isString()) { |
||||||
|
whitelist.process.append(processes.at(j).toString()); |
||||||
|
} |
||||||
|
} |
||||||
|
mapWhitelist.insert(name, whitelist); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
return true; |
||||||
|
} |
||||||
|
|
||||||
|
bool Policy::parsePolicy(const QJsonObject &obj) |
||||||
|
{ |
||||||
|
mapPathHide.clear(); |
||||||
|
mapPath.clear(); |
||||||
|
if (!obj.contains("policy")) { |
||||||
|
// 为空,不是出错
|
||||||
|
return true; |
||||||
|
} |
||||||
|
QJsonValue policyValue = obj.value("policy"); |
||||||
|
if (!policyValue.isArray()) { |
||||||
|
qCWarning(dsm_policy) << "parse policy error, must be json array!"; |
||||||
|
return false; |
||||||
|
} |
||||||
|
QJsonArray policyList = policyValue.toArray(); |
||||||
|
for (int i = 0; i < policyList.size(); ++i) { |
||||||
|
QJsonValue policy = policyList.at(i); |
||||||
|
if (!policy.isObject()) |
||||||
|
continue; |
||||||
|
if (!parsePolicyPath(policy.toObject())) { |
||||||
|
return false; |
||||||
|
} |
||||||
|
} |
||||||
|
return true; |
||||||
|
} |
||||||
|
|
||||||
|
bool Policy::parsePolicyPath(const QJsonObject &obj) |
||||||
|
{ |
||||||
|
QString path; |
||||||
|
jsonGetString(obj, "path", path); |
||||||
|
if (path.isEmpty()) { |
||||||
|
qCWarning(dsm_policy) << "parse policy-path error, must be a string!"; |
||||||
|
return false; |
||||||
|
} |
||||||
|
|
||||||
|
bool pathHide; |
||||||
|
jsonGetBool(obj, "pathhide", pathHide, false); |
||||||
|
mapPathHide.insert(path, pathHide); |
||||||
|
|
||||||
|
bool subpath; |
||||||
|
jsonGetBool(obj, "subpath", subpath, false); |
||||||
|
mapSubPath.insert(path, pathHide); |
||||||
|
|
||||||
|
PolicyPath policyPath; |
||||||
|
policyPath.path = path; |
||||||
|
jsonGetBool(obj, "permission", policyPath.needPermission, false); |
||||||
|
QString whitelist; |
||||||
|
jsonGetString(obj, "whitelist", whitelist); |
||||||
|
if (!whitelist.isEmpty()) { |
||||||
|
QMapWhitelists::const_iterator iterWhitelist = mapWhitelist.find(whitelist); |
||||||
|
if (iterWhitelist != mapWhitelist.end() && iterWhitelist.value().name == whitelist) { |
||||||
|
policyPath.processes = iterWhitelist.value().process; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
if (obj.contains("interfaces")) { |
||||||
|
QJsonValue interfaces = obj.value("interfaces"); |
||||||
|
if (interfaces.isArray()) { |
||||||
|
QJsonArray interfaceList = interfaces.toArray(); |
||||||
|
for (int i = 0; i < interfaceList.size(); ++i) { |
||||||
|
QJsonValue interface = interfaceList.at(i); |
||||||
|
if (interface.isObject()) { |
||||||
|
bool ret = parsePolicyInterface(interface.toObject(), policyPath); |
||||||
|
if (!ret) { |
||||||
|
return false; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
mapPath.insert(path, policyPath); |
||||||
|
|
||||||
|
return true; |
||||||
|
} |
||||||
|
|
||||||
|
bool Policy::parsePolicyInterface(const QJsonObject &obj, PolicyPath &policyPath) |
||||||
|
{ |
||||||
|
QString interface; |
||||||
|
jsonGetString(obj, "interface", interface); |
||||||
|
if (interface.isEmpty()) { |
||||||
|
qCWarning(dsm_policy) << "parse policy-interface error, must be a string!"; |
||||||
|
return false; |
||||||
|
} |
||||||
|
|
||||||
|
PolicyInterface policyInterface; |
||||||
|
policyInterface.interface = interface; |
||||||
|
// interface没有指定permission,则使用上级path的permission
|
||||||
|
jsonGetBool(obj, "permission", policyInterface.needPermission, policyPath.needPermission); |
||||||
|
QString whitelist; |
||||||
|
jsonGetString(obj, "whitelist", whitelist); |
||||||
|
if (!whitelist.isEmpty()) { |
||||||
|
QMapWhitelists::const_iterator iterWhitelist = mapWhitelist.find(whitelist); |
||||||
|
if (iterWhitelist != mapWhitelist.end() && iterWhitelist.value().name == whitelist) { |
||||||
|
policyInterface.processes = iterWhitelist.value().process; |
||||||
|
} // esle 错误的whitelist认为是空值
|
||||||
|
} else { |
||||||
|
// interface没有指定whitelist,则使用上级path的whitelist
|
||||||
|
policyInterface.processes = policyPath.processes; |
||||||
|
} |
||||||
|
|
||||||
|
if (obj.contains("methods")) { |
||||||
|
QJsonValue methods = obj.value("methods"); |
||||||
|
if (methods.isArray()) { |
||||||
|
QJsonArray methodList = methods.toArray(); |
||||||
|
for (int i = 0; i < methodList.size(); ++i) { |
||||||
|
QJsonValue method = methodList.at(i); |
||||||
|
if (method.isObject()) { |
||||||
|
bool ret = parsePolicyMethod(method.toObject(), policyInterface); |
||||||
|
if (!ret) { |
||||||
|
return false; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
if (obj.contains("properties")) { |
||||||
|
QJsonValue properties = obj.value("properties"); |
||||||
|
if (properties.isArray()) { |
||||||
|
QJsonArray propertiesList = properties.toArray(); |
||||||
|
for (int i = 0; i < propertiesList.size(); ++i) { |
||||||
|
QJsonValue property = propertiesList.at(i); |
||||||
|
if (property.isObject()) { |
||||||
|
bool ret = parsePolicyProperties(property.toObject(), policyInterface); |
||||||
|
if (!ret) { |
||||||
|
return false; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
policyPath.interfaces.insert(interface, policyInterface); |
||||||
|
return true; |
||||||
|
} |
||||||
|
|
||||||
|
bool Policy::parsePolicyMethod(const QJsonObject &obj, PolicyInterface &policyInterface) |
||||||
|
{ |
||||||
|
QString method; |
||||||
|
jsonGetString(obj, "method", method); |
||||||
|
if (method.isEmpty()) { |
||||||
|
qCWarning(dsm_policy) << "parse policy-method error, must be a string!"; |
||||||
|
return false; |
||||||
|
} |
||||||
|
|
||||||
|
PolicyMethod policyMethod; |
||||||
|
policyMethod.method = method; |
||||||
|
// method没有指定permission,则使用上级interface的permission
|
||||||
|
jsonGetBool(obj, "permission", policyMethod.needPermission, policyInterface.needPermission); |
||||||
|
QString whitelist; |
||||||
|
jsonGetString(obj, "whitelist", whitelist); |
||||||
|
if (!whitelist.isEmpty()) { |
||||||
|
QMapWhitelists::const_iterator iterWhitelist = mapWhitelist.find(whitelist); |
||||||
|
if (iterWhitelist != mapWhitelist.end() && iterWhitelist.value().name == whitelist) { |
||||||
|
policyMethod.processes = iterWhitelist.value().process; |
||||||
|
} |
||||||
|
} else { |
||||||
|
// method没有指定whitelist,则使用上级interface的whitelist
|
||||||
|
policyMethod.processes = policyInterface.processes; |
||||||
|
} |
||||||
|
|
||||||
|
policyInterface.methods.insert(method, policyMethod); |
||||||
|
return true; |
||||||
|
} |
||||||
|
|
||||||
|
bool Policy::parsePolicyProperties(const QJsonObject &obj, PolicyInterface &policyInterface) |
||||||
|
{ |
||||||
|
QString property; |
||||||
|
jsonGetString(obj, "property", property); |
||||||
|
if (property.isEmpty()) { |
||||||
|
qCWarning(dsm_policy) << "parse policy-property error, must be a string!"; |
||||||
|
return false; |
||||||
|
} |
||||||
|
|
||||||
|
PolicyProperty policyproperty; |
||||||
|
policyproperty.property = property; |
||||||
|
jsonGetBool(obj, "permission", policyproperty.needPermission, policyInterface.needPermission); |
||||||
|
QString whitelist; |
||||||
|
jsonGetString(obj, "whitelist", whitelist); |
||||||
|
if (!whitelist.isEmpty()) { |
||||||
|
QMapWhitelists::const_iterator iterWhitelist = mapWhitelist.find(whitelist); |
||||||
|
if (iterWhitelist != mapWhitelist.end() && iterWhitelist.value().name == whitelist) { |
||||||
|
policyproperty.processes = iterWhitelist.value().process; |
||||||
|
} |
||||||
|
} else { |
||||||
|
policyproperty.processes = policyInterface.processes; |
||||||
|
} |
||||||
|
|
||||||
|
policyInterface.properties.insert(property, policyproperty); |
||||||
|
return true; |
||||||
|
} |
||||||
|
|
||||||
|
bool Policy::jsonGetString(const QJsonObject &obj, |
||||||
|
const QString &key, |
||||||
|
QString &value, |
||||||
|
QString defaultValue) |
||||||
|
{ |
||||||
|
if (obj.contains(key)) { |
||||||
|
const QJsonValue &v = obj.value(key); |
||||||
|
if (v.isString()) { |
||||||
|
value = v.toString(); |
||||||
|
return true; |
||||||
|
} |
||||||
|
} |
||||||
|
value = defaultValue; |
||||||
|
return false; |
||||||
|
} |
||||||
|
|
||||||
|
bool Policy::jsonGetStringList(const QJsonObject &obj, |
||||||
|
const QString &key, |
||||||
|
QStringList &value, |
||||||
|
QStringList defaultValue) |
||||||
|
{ |
||||||
|
value = defaultValue; |
||||||
|
if (!obj.contains(key)) |
||||||
|
return false; |
||||||
|
const QJsonValue &v = obj.value(key); |
||||||
|
if (v.isString()) { |
||||||
|
value.append(v.toString()); |
||||||
|
return true; |
||||||
|
} |
||||||
|
if (v.isArray()) { |
||||||
|
const QJsonArray &array = v.toArray(); |
||||||
|
for (auto &&a : array) { |
||||||
|
if (a.isString()) |
||||||
|
value.append(a.toString()); |
||||||
|
} |
||||||
|
} |
||||||
|
return true; |
||||||
|
} |
||||||
|
|
||||||
|
bool Policy::jsonGetBool(const QJsonObject &obj, const QString &key, bool &value, bool defaultValue) |
||||||
|
{ |
||||||
|
if (obj.contains(key)) { |
||||||
|
const QJsonValue &v = obj.value(key); |
||||||
|
if (v.isBool()) { |
||||||
|
value = v.toBool(); |
||||||
|
return true; |
||||||
|
} |
||||||
|
} |
||||||
|
value = defaultValue; |
||||||
|
return false; |
||||||
|
} |
||||||
|
|
||||||
|
bool Policy::jsonGetInt(const QJsonObject &obj, const QString &key, int &value, int defaultValue) |
||||||
|
{ |
||||||
|
if (obj.contains(key)) { |
||||||
|
const QJsonValue &v = obj.value(key); |
||||||
|
if (v.isDouble()) { |
||||||
|
value = v.toInt(); |
||||||
|
return true; |
||||||
|
} |
||||||
|
} |
||||||
|
value = defaultValue; |
||||||
|
return false; |
||||||
|
} |
||||||
@ -0,0 +1,145 @@ |
|||||||
|
// SPDX-FileCopyrightText: 2023 UnionTech Software Technology Co., Ltd.
|
||||||
|
//
|
||||||
|
// SPDX-License-Identifier: LGPL-3.0-or-later
|
||||||
|
|
||||||
|
#ifndef POLICY_H |
||||||
|
#define POLICY_H |
||||||
|
|
||||||
|
#include <QMap> |
||||||
|
#include <QObject> |
||||||
|
|
||||||
|
enum class SDKType { QT, SD }; |
||||||
|
|
||||||
|
struct PolicyWhitelist |
||||||
|
{ |
||||||
|
QString name; |
||||||
|
QStringList process; |
||||||
|
}; |
||||||
|
|
||||||
|
typedef QMap<QString, PolicyWhitelist> QMapWhitelists; |
||||||
|
// hide, default:false
|
||||||
|
typedef QMap<QString, bool> QMapPathHide; |
||||||
|
// subpath, default:false
|
||||||
|
typedef QMap<QString, bool> QMapSubPath; |
||||||
|
|
||||||
|
// typedef QMap<QString, bool> QMapProcess;
|
||||||
|
struct PolicyMethod |
||||||
|
{ |
||||||
|
QString method; |
||||||
|
bool needPermission; |
||||||
|
QStringList processes; |
||||||
|
}; |
||||||
|
|
||||||
|
typedef QMap<QString, PolicyMethod> QMapMethod; |
||||||
|
|
||||||
|
struct PolicyProperty |
||||||
|
{ |
||||||
|
QString property; |
||||||
|
bool needPermission; |
||||||
|
QStringList processes; |
||||||
|
}; |
||||||
|
|
||||||
|
typedef QMap<QString, PolicyProperty> QMapProperty; |
||||||
|
|
||||||
|
struct PolicyInterface |
||||||
|
{ |
||||||
|
QString interface; |
||||||
|
bool needPermission; |
||||||
|
QStringList processes; |
||||||
|
QMapMethod methods; |
||||||
|
QMapProperty properties; |
||||||
|
}; |
||||||
|
|
||||||
|
typedef QMap<QString, PolicyInterface> QMapInterface; |
||||||
|
|
||||||
|
struct PolicyPath |
||||||
|
{ |
||||||
|
QString path; |
||||||
|
bool needPermission; |
||||||
|
QStringList processes; |
||||||
|
QMapInterface interfaces; |
||||||
|
}; |
||||||
|
|
||||||
|
typedef QMap<QString, PolicyPath> QMapPath; |
||||||
|
|
||||||
|
enum CallDestType { Method, Property }; |
||||||
|
|
||||||
|
class Policy : public QObject |
||||||
|
{ |
||||||
|
Q_OBJECT |
||||||
|
public: |
||||||
|
explicit Policy(QObject *parent = nullptr); |
||||||
|
|
||||||
|
void parseConfig(const QString &path); |
||||||
|
|
||||||
|
bool checkPathHide(const QString &path); |
||||||
|
bool checkMethodPermission(const QString &process, |
||||||
|
const QString &path, |
||||||
|
const QString &interface, |
||||||
|
const QString &method); |
||||||
|
bool checkPropertyPermission(const QString &process, |
||||||
|
const QString &path, |
||||||
|
const QString &interface, |
||||||
|
const QString &property); |
||||||
|
bool checkPermission(const QString &process, |
||||||
|
const QString &path, |
||||||
|
const QString &interface, |
||||||
|
const QString &dest, |
||||||
|
const CallDestType &type); |
||||||
|
QStringList paths() const; |
||||||
|
bool allowSubPath(const QString &path) const; |
||||||
|
bool isResident() const; |
||||||
|
|
||||||
|
// void Check(); // TODO
|
||||||
|
void print(); |
||||||
|
|
||||||
|
private: |
||||||
|
bool readJsonFile(QJsonDocument &outDoc, const QString &fileName); |
||||||
|
bool parseWhitelist(const QJsonObject &obj); |
||||||
|
bool parsePolicy(const QJsonObject &obj); |
||||||
|
bool parsePolicyPath(const QJsonObject &obj); |
||||||
|
bool parsePolicyInterface(const QJsonObject &obj, PolicyPath &policyPath); |
||||||
|
bool parsePolicyMethod(const QJsonObject &obj, PolicyInterface &policyInterface); |
||||||
|
bool parsePolicyProperties(const QJsonObject &obj, PolicyInterface &policyInterface); |
||||||
|
|
||||||
|
bool jsonGetString(const QJsonObject &obj, |
||||||
|
const QString &key, |
||||||
|
QString &value, |
||||||
|
QString defaultValue = ""); |
||||||
|
bool jsonGetStringList(const QJsonObject &obj, |
||||||
|
const QString &key, |
||||||
|
QStringList &value, |
||||||
|
QStringList defaultValue = {}); |
||||||
|
bool |
||||||
|
jsonGetBool(const QJsonObject &obj, const QString &key, bool &value, bool defaultValue = false); |
||||||
|
bool jsonGetInt(const QJsonObject &obj, const QString &key, int &value, int defaultValue = 0); |
||||||
|
|
||||||
|
public: |
||||||
|
// 数据定义
|
||||||
|
// 插入速度要求不高,查询速度要求很高,因此解析json的结果会通过冗余、预处理来提高查询速度,即以查询的速度角度来定义结构
|
||||||
|
// 配置文件和此处数据没有一一对应,解析文件时,需要为此处数据服务,填充相关数据
|
||||||
|
// 如果文件没有配置某参数,那也不允许空值,根据数据向下继承,比如某个参数interface没有设置,则interface的这个参数继承path
|
||||||
|
// 不允许空值的作用是减少查询时的逻辑判断,把这些逻辑处理转移到解析文件阶段
|
||||||
|
// 隐藏 - In:path,Out:pathhide
|
||||||
|
// 权限PATH - In:process、path,Out:bool
|
||||||
|
// 权限INTERFACE - In:process、path、interface,Out:bool
|
||||||
|
// 权限METHOD - In:process、path、interface、method,Out:bool
|
||||||
|
// 权限PROPERTIES - In:process、path、interface,Out:bool
|
||||||
|
QMapWhitelists mapWhitelist; |
||||||
|
QMapPathHide mapPathHide; |
||||||
|
QMapSubPath mapSubPath; |
||||||
|
QMapPath mapPath; |
||||||
|
|
||||||
|
public: |
||||||
|
QString name; |
||||||
|
QString group; |
||||||
|
QString pluginPath; |
||||||
|
QString version; |
||||||
|
QString startType; |
||||||
|
QStringList dependencies; |
||||||
|
SDKType sdkType; |
||||||
|
int startDelay; |
||||||
|
int idleTime; |
||||||
|
}; |
||||||
|
|
||||||
|
#endif // POLICY_H
|
||||||
@ -0,0 +1,276 @@ |
|||||||
|
// SPDX-FileCopyrightText: 2023 UnionTech Software Technology Co., Ltd.
|
||||||
|
//
|
||||||
|
// SPDX-License-Identifier: LGPL-3.0-or-later
|
||||||
|
|
||||||
|
#include "qtdbushook.h" |
||||||
|
|
||||||
|
#include "policy.h" |
||||||
|
#include "serviceqtdbus.h" |
||||||
|
|
||||||
|
#include <QDBusConnectionInterface> |
||||||
|
#include <QDBusMessage> |
||||||
|
#include <QDebug> |
||||||
|
#include <QFile> |
||||||
|
#include <QLoggingCategory> |
||||||
|
#include <QTimer> |
||||||
|
|
||||||
|
#ifdef Q_DBUS_EXPORT |
||||||
|
extern Q_DBUS_EXPORT void qDBusAddSpyHook(void (*)(const QDBusMessage &)); |
||||||
|
extern Q_DBUS_EXPORT void qDBusAddFilterHook(int (*)(const QString &, const QDBusMessage &)); |
||||||
|
#else |
||||||
|
extern QDBUS_EXPORT void qDBusAddSpyHook(void (*)(const QDBusMessage &)); |
||||||
|
extern QDBUS_EXPORT void qDBusAddFilterHook(int (*)(const QString &, const QDBusMessage &)); |
||||||
|
#endif |
||||||
|
|
||||||
|
#ifdef Q_DBUS_HOOK_FILTER |
||||||
|
# define HOOK_RESULT_TYPE int |
||||||
|
# define HOOK_RESULT_SUCCESS 0 |
||||||
|
# define HOOK_RESULT_FAILED -1 |
||||||
|
#else |
||||||
|
# define HOOK_RESULT_TYPE void |
||||||
|
# define HOOK_RESULT_SUCCESS |
||||||
|
# define HOOK_RESULT_FAILED |
||||||
|
#endif |
||||||
|
|
||||||
|
Q_LOGGING_CATEGORY(dsm_hook_qt, "[QDBusHook]") |
||||||
|
|
||||||
|
QString getCMD(ServiceBase *obj, QString dbusService) |
||||||
|
{ |
||||||
|
ServiceQtDBus *srv = qobject_cast<ServiceQtDBus *>(obj); |
||||||
|
if (!srv) { |
||||||
|
return ""; |
||||||
|
} |
||||||
|
const unsigned int &pid = srv->qDbusConnection().interface()->servicePid(dbusService).value(); |
||||||
|
qCDebug(dsm_hook_qt) << "--pid:" << pid; |
||||||
|
QFile procCmd("/proc/" + QString::number(pid) + "/cmdline"); |
||||||
|
QString cmd; |
||||||
|
if (procCmd.open(QIODevice::ReadOnly)) { |
||||||
|
QList<QByteArray> cmds = procCmd.readAll().split('\0'); |
||||||
|
cmd = QString(cmds.first()); |
||||||
|
qCDebug(dsm_hook_qt) << "--cmd:" << cmd; |
||||||
|
} |
||||||
|
return cmd; |
||||||
|
} |
||||||
|
|
||||||
|
// if it is not a local message, hook exec at main thread
|
||||||
|
void QTDBusSpyHook(const QDBusMessage &msg) |
||||||
|
{ |
||||||
|
qCInfo(dsm_hook_qt) << "--msg=" << msg; |
||||||
|
// qInfo() << "--Handler ThreadID:" << QThread::currentThreadId();
|
||||||
|
|
||||||
|
ServiceBase *serviceObj = nullptr; |
||||||
|
bool isSubPath; |
||||||
|
QString realPath; // 子PATH可能没有配置,使用父PATH的配置
|
||||||
|
bool findRet = QTDbusHook::instance()->getServiceObject("", |
||||||
|
msg.path(), |
||||||
|
&serviceObj, |
||||||
|
isSubPath, |
||||||
|
realPath); |
||||||
|
if (!findRet) { |
||||||
|
qCWarning(dsm_hook_qt) << "--can not find hook object: " << msg.path(); |
||||||
|
return; |
||||||
|
} |
||||||
|
if (!serviceObj->isRegister()) { |
||||||
|
qCInfo(dsm_hook_qt) << "--to register dbus object: " << msg.path(); |
||||||
|
serviceObj->registerService(); |
||||||
|
} |
||||||
|
|
||||||
|
if (!serviceObj->policy->isResident() && !serviceObj->isLockTimer()) { |
||||||
|
qCInfo(dsm_hook_qt) << QString("--service: %1 will unregister in %2 minutes!") |
||||||
|
.arg(serviceObj->policy->name) |
||||||
|
.arg(serviceObj->policy->idleTime); |
||||||
|
QTimer::singleShot(0, serviceObj, SLOT(restartTimer())); |
||||||
|
} |
||||||
|
if (msg.member() == "Introspect" && msg.interface() == "org.freedesktop.DBus.Introspectable") { |
||||||
|
if (serviceObj->policy->checkPathHide(realPath)) { |
||||||
|
qCDebug(dsm_hook_qt) << "--call Introspect" << msg.path() << " ,is hided!"; |
||||||
|
QList<QVariant> arguments; |
||||||
|
arguments << ""; |
||||||
|
QDBusMessage reply = msg.createReply(arguments); |
||||||
|
ServiceQtDBus *srv = qobject_cast<ServiceQtDBus *>(serviceObj); |
||||||
|
if (srv) { |
||||||
|
srv->qDbusConnection().send(reply); |
||||||
|
} |
||||||
|
// ((ServiceQtDBus*)serviceObj)->qDbusConnection().send(reply);
|
||||||
|
} |
||||||
|
} else if (msg.member() == "Set" && msg.interface() == "org.freedesktop.DBus.Properties") { |
||||||
|
const QList<QVariant> &args = msg.arguments(); |
||||||
|
if (args.size() >= 2) { |
||||||
|
if (!serviceObj->policy->checkPropertyPermission(getCMD(serviceObj, msg.service()), |
||||||
|
realPath, |
||||||
|
args.at(0).toString(), |
||||||
|
args.at(1).toString())) { |
||||||
|
QDBusMessage reply = msg.createErrorReply("com.deepin.service.Permission.Deny", |
||||||
|
"The call is deny"); |
||||||
|
ServiceQtDBus *srv = qobject_cast<ServiceQtDBus *>(serviceObj); |
||||||
|
if (srv) { |
||||||
|
srv->qDbusConnection().send(reply); |
||||||
|
return; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} else if (msg.interface() != "org.freedesktop.DBus.Properties" |
||||||
|
&& msg.interface() != "org.freedesktop.DBus.Introspectable" |
||||||
|
&& msg.interface() != "org.freedesktop.DBus.Peer") { |
||||||
|
if (!serviceObj->policy->checkMethodPermission(getCMD(serviceObj, msg.service()), |
||||||
|
realPath, |
||||||
|
msg.interface(), |
||||||
|
msg.member())) { |
||||||
|
QDBusMessage reply = |
||||||
|
msg.createErrorReply("com.deepin.service.Permission.Deny", "The call is deny2"); |
||||||
|
ServiceQtDBus *srv = qobject_cast<ServiceQtDBus *>(serviceObj); |
||||||
|
if (srv) { |
||||||
|
// srv->qDbusConnection().send(reply);
|
||||||
|
// QDBusConnection::sessionBus().send(reply);
|
||||||
|
QDBusConnection::connectToBus(QDBusConnection::SessionBus, |
||||||
|
QString("org.dsdsf.dsfsdf")) |
||||||
|
.send(reply); |
||||||
|
return; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
return; |
||||||
|
} |
||||||
|
|
||||||
|
// if it is not a local message, hook exec at main thread
|
||||||
|
int QTDBusHook(const QString &baseService, const QDBusMessage &msg) |
||||||
|
{ |
||||||
|
qCInfo(dsm_hook_qt) << "--baseService=" << baseService; |
||||||
|
qCInfo(dsm_hook_qt) << "--msg=" << msg; |
||||||
|
// qInfo() << "--Handler ThreadID:" << QThread::currentThreadId();
|
||||||
|
|
||||||
|
ServiceBase *serviceObj = nullptr; |
||||||
|
bool isSubPath; |
||||||
|
QString realPath; // 子PATH可能没有配置,使用父PATH的配置
|
||||||
|
bool findRet = QTDbusHook::instance()->getServiceObject("", |
||||||
|
msg.path(), |
||||||
|
&serviceObj, |
||||||
|
isSubPath, |
||||||
|
realPath); |
||||||
|
if (!findRet) { |
||||||
|
qCWarning(dsm_hook_qt) << "--can not find hook object:" << msg.path(); |
||||||
|
return 0; |
||||||
|
} |
||||||
|
if (!serviceObj->isRegister()) { |
||||||
|
qCInfo(dsm_hook_qt) << "--to register dbus object: " << msg.path(); |
||||||
|
serviceObj->registerService(); |
||||||
|
} |
||||||
|
|
||||||
|
if (!serviceObj->policy->isResident() && !serviceObj->isLockTimer()) { |
||||||
|
qCInfo(dsm_hook_qt) << QString("--service: %1 will unregister in 10 minutes!") |
||||||
|
.arg(serviceObj->policy->name); |
||||||
|
QTimer::singleShot(0, serviceObj, SLOT(restartTimer())); |
||||||
|
} |
||||||
|
if (msg.member() == "Introspect" && msg.interface() == "org.freedesktop.DBus.Introspectable") { |
||||||
|
if (serviceObj->policy->checkPathHide(realPath)) { |
||||||
|
qCDebug(dsm_hook_qt) << "--call Introspect" << msg.path() << " ,is hided!"; |
||||||
|
QList<QVariant> arguments; |
||||||
|
arguments << ""; |
||||||
|
QDBusMessage reply = msg.createReply(arguments); |
||||||
|
ServiceQtDBus *srv = qobject_cast<ServiceQtDBus *>(serviceObj); |
||||||
|
if (srv) { |
||||||
|
srv->qDbusConnection().send(reply); |
||||||
|
} |
||||||
|
// ((ServiceQtDBus*)serviceObj)->qDbusConnection().send(reply);
|
||||||
|
} |
||||||
|
} else if (msg.member() == "Set" && msg.interface() == "org.freedesktop.DBus.Properties") { |
||||||
|
const QList<QVariant> &args = msg.arguments(); |
||||||
|
if (args.size() >= 2) { |
||||||
|
if (!serviceObj->policy->checkPropertyPermission(getCMD(serviceObj, msg.service()), |
||||||
|
realPath, |
||||||
|
args.at(0).toString(), |
||||||
|
args.at(1).toString())) { |
||||||
|
QDBusMessage reply = msg.createErrorReply("com.deepin.service.Permission.Deny", |
||||||
|
"The call is deny"); |
||||||
|
ServiceQtDBus *srv = qobject_cast<ServiceQtDBus *>(serviceObj); |
||||||
|
if (srv) { |
||||||
|
srv->qDbusConnection().send(reply); |
||||||
|
return -1; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} else if (msg.interface() != "org.freedesktop.DBus.Properties" |
||||||
|
&& msg.interface() != "org.freedesktop.DBus.Introspectable" |
||||||
|
&& msg.interface() != "org.freedesktop.DBus.Peer") { |
||||||
|
if (!serviceObj->policy->checkMethodPermission(getCMD(serviceObj, msg.service()), |
||||||
|
realPath, |
||||||
|
msg.interface(), |
||||||
|
msg.member())) { |
||||||
|
QDBusMessage reply = |
||||||
|
msg.createErrorReply("com.deepin.service.Permission.Deny", "The call is deny2"); |
||||||
|
ServiceQtDBus *srv = qobject_cast<ServiceQtDBus *>(serviceObj); |
||||||
|
if (srv) { |
||||||
|
srv->qDbusConnection().send(reply); |
||||||
|
return -1; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
return 0; |
||||||
|
|
||||||
|
// test TODO
|
||||||
|
// if (msg.member() == "Register") {
|
||||||
|
// Policy ppp;
|
||||||
|
// ppp.Test();
|
||||||
|
// QList<QVariant> arguments;
|
||||||
|
// arguments << true << "sdvvv";
|
||||||
|
|
||||||
|
// QDBusMessage reply =
|
||||||
|
// msg.createErrorReply("com.deepin.services.Nooooooo", "The method
|
||||||
|
// call 'Register()' is not supported");
|
||||||
|
// QDBusConnection::connectToBus(QDBusConnection::SessionBus,
|
||||||
|
// "org.deepin.services.demo2").send(reply);
|
||||||
|
// }
|
||||||
|
} |
||||||
|
|
||||||
|
Q_GLOBAL_STATIC(QTDbusHook, qtDBusHook) |
||||||
|
|
||||||
|
QTDbusHook::QTDbusHook() |
||||||
|
{ |
||||||
|
qCDebug(dsm_hook_qt) << "qt hook register."; |
||||||
|
#ifdef Q_DBUS_HOOK_FILTER |
||||||
|
qDBusAddFilterHook(QTDBusHook); |
||||||
|
#else |
||||||
|
qDBusAddSpyHook(QTDBusSpyHook); |
||||||
|
#endif |
||||||
|
} |
||||||
|
|
||||||
|
QTDbusHook *QTDbusHook::instance() |
||||||
|
{ |
||||||
|
return qtDBusHook; |
||||||
|
} |
||||||
|
|
||||||
|
bool QTDbusHook::getServiceObject( |
||||||
|
QString name, QString path, ServiceBase **service, bool &isSubPath, QString &realPath) |
||||||
|
{ |
||||||
|
Q_UNUSED(name) // TODO:QtDBus Hook 无法获取到name
|
||||||
|
ServiceObjectMap::iterator iterService = m_serviceMap.find(path); |
||||||
|
if (iterService != m_serviceMap.end()) { |
||||||
|
*service = iterService.value(); |
||||||
|
isSubPath = true; |
||||||
|
realPath = iterService.key(); |
||||||
|
return true; |
||||||
|
} |
||||||
|
for (auto iter = m_serviceMap.begin(); iter != m_serviceMap.end(); ++iter) { |
||||||
|
if (path.startsWith(iter.key()) && iter.value()->policy->allowSubPath(iter.key())) { |
||||||
|
*service = iter.value(); |
||||||
|
isSubPath = false; |
||||||
|
realPath = iter.key(); |
||||||
|
return true; |
||||||
|
} |
||||||
|
} |
||||||
|
return false; |
||||||
|
} |
||||||
|
|
||||||
|
bool QTDbusHook::setServiceObject(ServiceBase *obj) |
||||||
|
{ |
||||||
|
QStringList paths = obj->policy->paths(); |
||||||
|
for (auto path : paths) { |
||||||
|
ServiceObjectMap::iterator iterService = m_serviceMap.find(path); |
||||||
|
if (iterService != m_serviceMap.end()) { |
||||||
|
qCWarning(dsm_hook_qt) << "set service path failed, the object is existed: " << path; |
||||||
|
continue; |
||||||
|
} |
||||||
|
m_serviceMap[path] = obj; |
||||||
|
} |
||||||
|
return true; |
||||||
|
} |
||||||
@ -0,0 +1,28 @@ |
|||||||
|
// SPDX-FileCopyrightText: 2023 UnionTech Software Technology Co., Ltd.
|
||||||
|
//
|
||||||
|
// SPDX-License-Identifier: LGPL-3.0-or-later
|
||||||
|
|
||||||
|
#ifndef QTDBUSHOOK_H |
||||||
|
#define QTDBUSHOOK_H |
||||||
|
|
||||||
|
#include "servicebase.h" |
||||||
|
|
||||||
|
typedef QMap<QString, ServiceBase *> ServiceObjectMap; |
||||||
|
|
||||||
|
class QTDbusHook |
||||||
|
{ |
||||||
|
public: |
||||||
|
explicit QTDbusHook(); |
||||||
|
|
||||||
|
bool getServiceObject( |
||||||
|
QString name, QString path, ServiceBase **service, bool &isSubPath, QString &realPath); |
||||||
|
|
||||||
|
bool setServiceObject(ServiceBase *obj); |
||||||
|
|
||||||
|
static QTDbusHook *instance(); |
||||||
|
|
||||||
|
private: |
||||||
|
ServiceObjectMap m_serviceMap; |
||||||
|
}; |
||||||
|
|
||||||
|
#endif // QTDBUSHOOK_H
|
||||||
@ -0,0 +1,77 @@ |
|||||||
|
// SPDX-FileCopyrightText: 2023 UnionTech Software Technology Co., Ltd.
|
||||||
|
//
|
||||||
|
// SPDX-License-Identifier: LGPL-3.0-or-later
|
||||||
|
|
||||||
|
#include "servicebase.h" |
||||||
|
|
||||||
|
#include "policy.h" |
||||||
|
|
||||||
|
#include <QDBusConnection> |
||||||
|
#include <QDBusMessage> |
||||||
|
#include <QDebug> |
||||||
|
#include <QThread> |
||||||
|
#include <QTimer> |
||||||
|
|
||||||
|
ServiceBase::ServiceBase(QObject *parent) |
||||||
|
: QObject(parent) |
||||||
|
, policy(nullptr) |
||||||
|
, m_isRegister(false) |
||||||
|
, m_isLockTimer(false) |
||||||
|
, m_timer(new QTimer(this)) |
||||||
|
{ |
||||||
|
m_timer->setSingleShot(true); |
||||||
|
m_timer->setInterval(10 * 60 * 1000); // 设置超时时间, 默认10分钟
|
||||||
|
connect(m_timer, &QTimer::timeout, this, &ServiceBase::idleSignal); |
||||||
|
} |
||||||
|
|
||||||
|
ServiceBase::~ServiceBase() { } |
||||||
|
|
||||||
|
void ServiceBase::init(const QDBusConnection::BusType &busType, Policy *p) |
||||||
|
{ |
||||||
|
m_sessionType = busType; |
||||||
|
policy = p; |
||||||
|
p->setParent(this); |
||||||
|
// p->Print();
|
||||||
|
|
||||||
|
m_timer->setInterval(policy->idleTime * 60 * 1000); // 设置超时时间
|
||||||
|
connect(this, &ServiceBase::idleSignal, this, &ServiceBase::unregisterService); |
||||||
|
initService(); |
||||||
|
} |
||||||
|
|
||||||
|
void ServiceBase::initService() |
||||||
|
{ |
||||||
|
QThread *th = new QThread(); |
||||||
|
setParent(nullptr); |
||||||
|
moveToThread(th); |
||||||
|
connect(th, &QThread::started, this, &ServiceBase::initThread); |
||||||
|
th->start(); |
||||||
|
} |
||||||
|
|
||||||
|
void ServiceBase::initThread() { } |
||||||
|
|
||||||
|
bool ServiceBase::isRegister() const |
||||||
|
{ |
||||||
|
return m_isRegister; |
||||||
|
} |
||||||
|
|
||||||
|
bool ServiceBase::isLockTimer() const |
||||||
|
{ |
||||||
|
return m_isLockTimer; |
||||||
|
} |
||||||
|
|
||||||
|
void ServiceBase::restartTimer() |
||||||
|
{ |
||||||
|
m_timer->start(); |
||||||
|
} |
||||||
|
|
||||||
|
bool ServiceBase::registerService() |
||||||
|
{ |
||||||
|
m_isRegister = true; |
||||||
|
return true; |
||||||
|
} |
||||||
|
|
||||||
|
bool ServiceBase::unregisterService() |
||||||
|
{ |
||||||
|
m_isRegister = false; |
||||||
|
return true; |
||||||
|
} |
||||||
@ -0,0 +1,54 @@ |
|||||||
|
// SPDX-FileCopyrightText: 2023 UnionTech Software Technology Co., Ltd.
|
||||||
|
//
|
||||||
|
// SPDX-License-Identifier: LGPL-3.0-or-later
|
||||||
|
|
||||||
|
#ifndef SERVICEBASE_H |
||||||
|
#define SERVICEBASE_H |
||||||
|
|
||||||
|
#include "policy.h" |
||||||
|
|
||||||
|
#include <QDBusConnection> |
||||||
|
#include <QObject> |
||||||
|
|
||||||
|
typedef void *(*ServiceObject)(const char *path, const int len); |
||||||
|
typedef int (*DSMRegister)(const char *name, void *data); |
||||||
|
typedef int (*DSMUnRegister)(const char *name, void *data); |
||||||
|
|
||||||
|
class QTimer; |
||||||
|
|
||||||
|
class ServiceBase : public QObject |
||||||
|
{ |
||||||
|
Q_OBJECT |
||||||
|
public: |
||||||
|
explicit ServiceBase(QObject *parent = nullptr); |
||||||
|
virtual ~ServiceBase(); |
||||||
|
|
||||||
|
bool isRegister() const; |
||||||
|
bool isLockTimer() const; |
||||||
|
virtual bool registerService(); |
||||||
|
virtual bool unregisterService(); |
||||||
|
|
||||||
|
Q_SIGNALS: |
||||||
|
void idleSignal(); |
||||||
|
|
||||||
|
public Q_SLOTS: |
||||||
|
void init(const QDBusConnection::BusType &busType, Policy *p); |
||||||
|
void restartTimer(); |
||||||
|
|
||||||
|
protected: |
||||||
|
virtual void initService(); |
||||||
|
virtual void initThread(); |
||||||
|
|
||||||
|
public: |
||||||
|
Policy *policy; |
||||||
|
|
||||||
|
protected: |
||||||
|
bool m_isRegister; |
||||||
|
bool m_isLockTimer; |
||||||
|
|
||||||
|
QDBusConnection::BusType m_sessionType; |
||||||
|
SDKType m_SDKType; // qdbus、sdbus
|
||||||
|
QTimer *m_timer; |
||||||
|
}; |
||||||
|
|
||||||
|
#endif // SERVICEBASE_H
|
||||||
@ -0,0 +1,106 @@ |
|||||||
|
// SPDX-FileCopyrightText: 2023 UnionTech Software Technology Co., Ltd.
|
||||||
|
//
|
||||||
|
// SPDX-License-Identifier: LGPL-3.0-or-later
|
||||||
|
|
||||||
|
#include "serviceqtdbus.h" |
||||||
|
|
||||||
|
#include "policy.h" |
||||||
|
#include "qtdbushook.h" |
||||||
|
|
||||||
|
#include <QDBusAbstractAdaptor> |
||||||
|
#include <QDebug> |
||||||
|
#include <QFileInfo> |
||||||
|
#include <QLibrary> |
||||||
|
#include <QLoggingCategory> |
||||||
|
#include <QMetaClassInfo> |
||||||
|
#include <QThread> |
||||||
|
|
||||||
|
Q_LOGGING_CATEGORY(dsm_service_qt, "[QDBusService]") |
||||||
|
|
||||||
|
ServiceQtDBus::ServiceQtDBus(QObject *parent) |
||||||
|
: ServiceBase(parent) |
||||||
|
, m_library(nullptr) |
||||||
|
{ |
||||||
|
m_SDKType = SDKType::QT; |
||||||
|
} |
||||||
|
|
||||||
|
QDBusConnection ServiceQtDBus::qDbusConnection() |
||||||
|
{ |
||||||
|
if (policy->name.isEmpty()) { |
||||||
|
return m_sessionType == QDBusConnection::SystemBus ? QDBusConnection::systemBus() : QDBusConnection::sessionBus(); |
||||||
|
} |
||||||
|
|
||||||
|
return m_sessionType == QDBusConnection::SystemBus ? QDBusConnection::connectToBus(QDBusConnection::SystemBus, policy->name) |
||||||
|
: QDBusConnection::connectToBus(QDBusConnection::SessionBus, policy->name); |
||||||
|
} |
||||||
|
|
||||||
|
void ServiceQtDBus::initThread() |
||||||
|
{ |
||||||
|
qCInfo(dsm_service_qt) << "init service: " << policy->name << "paths: " << policy->paths(); |
||||||
|
qDbusConnection().registerService(policy->name); |
||||||
|
|
||||||
|
// TODO: 无权限、隐藏、按需启动需求的service,不应该注册,避免触发hook,提高效率
|
||||||
|
QTDbusHook::instance()->setServiceObject(this); |
||||||
|
|
||||||
|
QFileInfo fileInfo(QString(SERVICE_LIB_DIR) + policy->pluginPath); |
||||||
|
if (QLibrary::isLibrary(fileInfo.absoluteFilePath())) { |
||||||
|
qCInfo(dsm_service_qt) << "init library: " << fileInfo.absoluteFilePath(); |
||||||
|
m_library = new QLibrary(fileInfo.absoluteFilePath()); |
||||||
|
} |
||||||
|
|
||||||
|
if (!registerService()) { |
||||||
|
qCWarning(dsm_service_qt) << "register service failed: " << policy->name; |
||||||
|
} |
||||||
|
ServiceBase::initThread(); |
||||||
|
} |
||||||
|
|
||||||
|
bool ServiceQtDBus::registerService() |
||||||
|
{ |
||||||
|
qCInfo(dsm_service_qt) << "service register: " << policy->name; |
||||||
|
|
||||||
|
if (libFuncCall("DSMRegister", true)) { |
||||||
|
ServiceBase::registerService(); |
||||||
|
return true; |
||||||
|
} |
||||||
|
|
||||||
|
return false; |
||||||
|
} |
||||||
|
|
||||||
|
bool ServiceQtDBus::unregisterService() |
||||||
|
{ |
||||||
|
qCInfo(dsm_service_qt) << "service unregister: " << policy->name; |
||||||
|
|
||||||
|
if (libFuncCall("DSMUnRegister", false)) { |
||||||
|
ServiceBase::unregisterService(); |
||||||
|
return true; |
||||||
|
} |
||||||
|
|
||||||
|
return false; |
||||||
|
} |
||||||
|
|
||||||
|
bool ServiceQtDBus::libFuncCall(const QString &funcName, bool isRegister) |
||||||
|
{ |
||||||
|
if (m_library == nullptr) { |
||||||
|
return false; |
||||||
|
} |
||||||
|
auto objFunc = isRegister ? DSMRegister(m_library->resolve(funcName.toStdString().c_str())) |
||||||
|
: DSMUnRegister(m_library->resolve(funcName.toStdString().c_str())); |
||||||
|
if (!objFunc) { |
||||||
|
qCWarning(dsm_service_qt) |
||||||
|
<< QString("failed to resolve the method: %1\n file: %2\n error message: %3") |
||||||
|
.arg(funcName) |
||||||
|
.arg(m_library->fileName()) |
||||||
|
.arg(m_library->errorString()); |
||||||
|
if (m_library->isLoaded()) |
||||||
|
m_library->unload(); |
||||||
|
m_library->deleteLater(); |
||||||
|
return false; |
||||||
|
} |
||||||
|
auto connection = qDbusConnection(); |
||||||
|
int ret = objFunc(policy->name.toStdString().c_str(), (void *)&connection); |
||||||
|
if (ret) { |
||||||
|
return false; |
||||||
|
} |
||||||
|
|
||||||
|
return true; |
||||||
|
} |
||||||
@ -0,0 +1,33 @@ |
|||||||
|
// SPDX-FileCopyrightText: 2023 UnionTech Software Technology Co., Ltd.
|
||||||
|
//
|
||||||
|
// SPDX-License-Identifier: LGPL-3.0-or-later
|
||||||
|
|
||||||
|
#ifndef SERVICEQTDBUS_H |
||||||
|
#define SERVICEQTDBUS_H |
||||||
|
|
||||||
|
#include "servicebase.h" |
||||||
|
|
||||||
|
class QLibrary; |
||||||
|
|
||||||
|
class ServiceQtDBus : public ServiceBase |
||||||
|
{ |
||||||
|
Q_OBJECT |
||||||
|
public: |
||||||
|
explicit ServiceQtDBus(QObject *parent = nullptr); |
||||||
|
|
||||||
|
QDBusConnection qDbusConnection(); |
||||||
|
|
||||||
|
virtual bool registerService() override; |
||||||
|
virtual bool unregisterService() override; |
||||||
|
|
||||||
|
protected: |
||||||
|
virtual void initThread() override; |
||||||
|
|
||||||
|
private: |
||||||
|
bool libFuncCall(const QString &funcName, bool isRegister); |
||||||
|
|
||||||
|
private: |
||||||
|
QLibrary *m_library; |
||||||
|
}; |
||||||
|
|
||||||
|
#endif // SERVICEQTDBUS_H
|
||||||
@ -0,0 +1,6 @@ |
|||||||
|
cd dp4-dbus-service |
||||||
|
sh ./lupdate.sh |
||||||
|
cd .. |
||||||
|
cd dp4-login-plugin |
||||||
|
sh ./lupdate.sh |
||||||
|
cd .. |
||||||
Loading…
Reference in new issue