diff --git a/qmac.pro b/qmac.pro new file mode 100644 --- /dev/null +++ b/qmac.pro @@ -0,0 +1,5 @@ +TEMPLATE = subdirs + +SUBDIRS += \ + qmac \ + tests diff --git a/qmac/mac.cpp b/qmac/mac.cpp new file mode 100644 --- /dev/null +++ b/qmac/mac.cpp @@ -0,0 +1,15 @@ +#include "qmac.h" + +//--------------------------------------------------------------------------- +//--------------------------------------------------------------------------- +ProcessMac::ProcessMac() +{ + +} + +//--------------------------------------------------------------------------- +//--------------------------------------------------------------------------- +FileMac::FileMac() +{ + +} diff --git a/qmac/nomac.cpp b/qmac/nomac.cpp new file mode 100644 --- /dev/null +++ b/qmac/nomac.cpp @@ -0,0 +1,119 @@ +#include "qmac.h" + +#include + +//--------------------------------------------------------------------------- +//--------------------------------------------------------------------------- +class ProcessMacData : public QSharedData +{ +public: + ProcessMacData(); + + int level() const { return _level; } + QString levelText() const { return _levelText; } + QString categoryText() const { return _categoryText; } + +private: + int _level; + QString _levelText; + QString _categoryText; +}; + +ProcessMacData::ProcessMacData() + : _level(0) + , _levelText(QStringLiteral("Нет")) +{ +} + +//--------------------------------------------------------------------------- +//--------------------------------------------------------------------------- +ProcessMac::ProcessMac() + : d(new ProcessMacData) +{ +} + +ProcessMac::~ProcessMac() = default; + +//--------------------------------------------------------------------------- +int ProcessMac::level() const +{ + return d->level(); +} + +QString ProcessMac::levelText() const +{ + return d->levelText(); +} + +QString ProcessMac::categoryText() const +{ + return d->categoryText(); +} + +bool ProcessMac::canRead(const FileMac& a_fileMac) +{ + Q_UNUSED(a_fileMac) + return true; +} + +bool ProcessMac::canWrite(const FileMac& a_fileMac) +{ + Q_UNUSED(a_fileMac) + return true; +} + +//--------------------------------------------------------------------------- +//--------------------------------------------------------------------------- +class FileMacData : public QSharedData +{ +public: + FileMacData(const QString& a_fileName); + + int level() const { return _level; } + QString levelText() const { return _levelText; } + QString categoryText() const { return _categoryText; } + QString fileName() const { return _fileName; } + +private: + int _level; + QString _levelText; + QString _categoryText; + QString _fileName; +}; + +FileMacData::FileMacData(const QString& a_fileName) + : _level(0) + , _levelText(QStringLiteral("Нет")) + , _fileName(a_fileName) +{ +} + +//--------------------------------------------------------------------------- +//--------------------------------------------------------------------------- +FileMac::FileMac(const QString& a_fileName) + : d(new FileMacData(a_fileName)) +{ +} + +FileMac::~FileMac() = default; + +//--------------------------------------------------------------------------- +int FileMac::level() const +{ + return d->level(); +} + +QString FileMac::levelText() const +{ + return d->levelText(); +} + +QString FileMac::categoryText() const +{ + return d->categoryText(); +} + +QString FileMac::fileName() const +{ + return d->fileName(); +} diff --git a/qmac/qmac.h b/qmac/qmac.h new file mode 100644 --- /dev/null +++ b/qmac/qmac.h @@ -0,0 +1,47 @@ +#ifndef QMAC_H +#define QMAC_H + +#include +#include + +#if defined(QMAC_LIBRARY) +# define QMAC_EXPORT Q_DECL_EXPORT +#else +# define QMAC_EXPORT Q_DECL_IMPORT +#endif + +class FileMacData; +class QMAC_EXPORT FileMac +{ + friend class ProcessMac; +public: + FileMac(const QString& a_fileName); + ~FileMac(); + + int level() const; + QString levelText() const; + QString categoryText() const; + QString fileName() const; + +private: + QSharedDataPointer d; +}; + +class ProcessMacData; +class QMAC_EXPORT ProcessMac +{ +public: + ProcessMac(); + ~ProcessMac(); + + int level() const; + QString levelText() const; + QString categoryText() const; + bool canRead(const FileMac& a_fileMac); + bool canWrite(const FileMac& a_fileMac); + +private: + QSharedDataPointer d; +}; + +#endif // QMAC_H diff --git a/qmac/qmac.pro b/qmac/qmac.pro new file mode 100644 --- /dev/null +++ b/qmac/qmac.pro @@ -0,0 +1,24 @@ +QT -= gui + +TEMPLATE = lib +DEFINES += QMAC_LIBRARY + +CONFIG += c++11 + +# You can make your code fail to compile if it uses deprecated APIs. +# In order to do so, uncomment the following line. +#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0 + +exists(/etc/astra_version) { + SOURCES += mac.cpp + LIBS += -lparsec-mac +} else { + SOURCES += nomac.cpp +} + +HEADERS += \ + qmac.h + +target.path = /lib # lib/dll install location +headers.path = /include # headers install location +headers.files = $$HEADERS diff --git a/tests/main.cpp b/tests/main.cpp new file mode 100644 --- /dev/null +++ b/tests/main.cpp @@ -0,0 +1,234 @@ +#include "main.h" +#include "qmac.h" + +#include +#include +#include +#include + +//для getpid +#include + +//для типов операции функции mac_file_permit() +#include + +//заголовочный файл подсистемы MAC библиотеки PARSEC (мандатное разграничения доступа) +//#include +//#include + +int main(int argc, char *argv[]) +{ + QCoreApplication a(argc, argv); + QTextStream os(stdout); + + os << "AstraLinux SE security system PARSEC demo application" << '\n' << '\n'; + os << "Process name : " << argv[0] << '\n'; + + //(необязательно) получение идентификатора текущего процесса + pid_t pid = getpid(); + os << "Process ID : " << pid << '\n'; + + // + // Процессы + // + + ProcessMac processMac; + os << "Process MAC level: " << processMac.levelText() << " (" << processMac.level() << ')' << '\n'; + os << "Process category : " << processMac.categoryText() << '\n'; + + // + // Файлы + // + + QCommandLineParser parser; + parser.process(a); + + QStringList fileNames = parser.positionalArguments(); + for (const auto& fileName : fileNames) + { + os << '\n'; + os << "File name: " << fileName << '\n'; + os << "File type: "; + QFileInfo fi(fileName); + if (!fi.exists()) + { + os << "does not exist" << '\n'; + continue; + } + + if (fi.isDir()) + os << "directory" << '\n'; + else if (fi.isFile()) + os << "regular file" << '\n'; + else + { + os << "unsupported" << '\n'; + continue; + } + + FileMac fileMac(fileName); + + os << "MAC level: " << fileMac.levelText() << " (" << fileMac.level() << ')' << '\n'; + os << "MAC categ: " << fileMac.categoryText() << '\n'; + + //проверка возможности чтения и записи файла + bool canRead = processMac.canRead(fileMac); + bool canWrite = processMac.canWrite(fileMac); + + os << "Can read : " << (canRead ? "true" : "false") << '\n'; + os << "Can write: " << (canWrite ? "true" : "false") << '\n'; + + if (fi.isDir()) + continue; + + //проверим, действительно ли невозможно читать и записывать файлы + if (!canRead) + { + QFile f(fileName); + + if (f.open(QIODevice::ReadOnly)) + os << "Can not read, but opened for reading !!!" << '\n'; + else + os << "Open for reading failed" << '\n'; + } + + if (!canWrite) + { + QFile f(fileName); + + if (f.open(QIODevice::ReadWrite)) + os << "Can not write, but opened for writing !!!" << '\n'; + else + os << "Open for writing failed" << '\n'; + } + } +} + +/* + //получение метки текущего процесса, то же, что mac_get_pid(0) или mac_get_pid(pid) + mac_t processMac = mac_get_proc(); + + //текстовое представление метки процесса + ssize_t size; + wchar_t* wtext = mac_to_wtext(processMac, &size, MAC_FMT_TXT | MAC_FMT_LEV); + + os << "Process MAC level: " << QString::fromWCharArray(wtext, size) << " (" << mac_get_lev(processMac) << ')' << '\n'; + + //освободить память, выделенную функцией mac_to_wtext + free(wtext); + + //текстовое представление списка категорий + wtext = mac_to_wtext(processMac, &size, MAC_FMT_TXT | MAC_FMT_CAT); + + os << "Process category : " << QString::fromWCharArray(wtext, size) << '\n'; + + //освободить память, выделенную функцией mac_to_wtext + free(wtext); + + // + // Файлы + // + QCommandLineParser parser; + parser.process(a); + + QStringList fileNames = parser.positionalArguments(); + for (const auto& fileName : fileNames) + { + os << '\n'; + os << "File name: " << fileName << '\n'; + os << "File type: "; + QFileInfo fi(fileName); + if (!fi.exists()) + { + os << "does not exist" << '\n'; + continue; + } + + if (fi.isDir()) + os << "directory" << '\n'; + else if (fi.isFile()) + os << "regular file" << '\n'; + else + { + os << "unsupported" << '\n'; + continue; + } + + //получение метки файла по его имени + mac_t fileMac = mac_get_file(fileName.toLocal8Bit().constData()); + + //текстовое представление метки файла + ssize_t size; + wchar_t* wtext = mac_to_wtext(fileMac, &size, MAC_FMT_TXT | MAC_FMT_LEV); + + os << "MAC level: " << QString::fromWCharArray(wtext, size) << " (" << mac_get_lev(fileMac) << ')' << '\n'; + + //освободить память, выделенную функцией mac_to_wtext + free(wtext); + + //текстовое представление списка категорий + wtext = mac_to_wtext(fileMac, &size, MAC_FMT_TXT | MAC_FMT_CAT); + + os << "MAC categ: " << QString::fromWCharArray(wtext, size) << '\n'; + + //освободить память, выделенную функцией mac_to_wtext + free(wtext); + + //проверка возможности чтения и записи файла + bool canRead = 0 == mac_file_permit(processMac, fileMac, R_OK); + bool canWrite = 0 == mac_file_permit(processMac, fileMac, W_OK); + + os << "Can read : " << (canRead ? "true" : "false") << '\n'; + os << "Can write: " << (canWrite ? "true" : "false") << '\n'; + + //освободить память после использования + mac_free(fileMac); + + if (fi.isDir()) + continue; + + //проверим, действительно ли невозможно читать и записывать файлы + if (!canRead) + { + QFile f(fileName); + + if (f.open(QIODevice::ReadOnly)) + os << "Can not read, but opened for reading !!!" << '\n'; + else + os << "Open for reading failed" << '\n'; + } + + if (!canWrite) + { + QFile f(fileName); + + if (f.open(QIODevice::ReadWrite)) + os << "Can not write, but opened for writing !!!" << '\n'; + else + os << "Open for writing failed" << '\n'; + } + + if (canRead) + { + QFile f(fileName); + + if (f.open(QIODevice::ReadOnly)) + { + //получение метки открытого файла по его дескриптору + mac_t mac = mac_get_fd(f.handle()); + + //получение уровня доступа + mac_lev_t lev = mac_get_lev(mac); + Q_UNUSED(lev) + //os << "MAC level: " << lev << '\n'; + + //освободить память после использования + mac_free(mac); + } + } + } + + //освободить память после использования + mac_free(processMac); +} +*/ diff --git a/tests/main.h b/tests/main.h new file mode 100644 --- /dev/null +++ b/tests/main.h @@ -0,0 +1,10 @@ +#ifndef MAIN_H +#define MAIN_H + +#include + +class TestQMac : public QObject +{ +}; + +#endif // MAIN_H diff --git a/tests/tests.pro b/tests/tests.pro new file mode 100644 --- /dev/null +++ b/tests/tests.pro @@ -0,0 +1,32 @@ +TEMPLATE = app +QT += testlib +QT -= gui + +CONFIG += qt console warn_on depend_includepath testcase no_testcase_installs +CONFIG -= app_bundle + +# The following define makes your compiler emit warnings if you use +# any feature of Qt which as been marked deprecated (the exact warnings +# depend on your compiler). Please consult the documentation of the +# deprecated API in order to know how to port your code away from it. +DEFINES += QT_DEPRECATED_WARNINGS + +isEmpty(INCLUDEPATH): SITE_INCLUDEPATH = $$(HOME)/src/include +else: SITE_INCLUDEPATH = $$INCLUDEPATH +isEmpty(LIBS): SITE_LIBS = -L$$(HOME)/src/lib +else: SITE_LIBS = $$LIBS + +INCLUDEPATH = $$PWD/../qmac $$SITE_INCLUDEPATH +DEPENDPATH = $$PWD/../qmac + +win32:CONFIG(release, debug|release): LIBS = -L$$OUT_PWD/../qmac/release +else:win32:CONFIG(debug, debug|release): LIBS = -L$$OUT_PWD/../qmac/debug +else:unix: LIBS = -L$$OUT_PWD/../qmac + +LIBS += -lqmac + +SOURCES += \ + main.cpp + +HEADERS += \ + main.h