summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKai Köhne <kai.koehne@qt.io>2022-12-13 13:48:20 +0100
committerKai Köhne <kai.koehne@qt.io>2023-02-24 12:16:42 +0100
commitddfe3639386c235d50a54c46071983525ed3a645 (patch)
tree5dcb73a2b58bec5f6af40f17a2421cd182b78664
parent6576521204775bda0e157fc5287df786628d1513 (diff)
OpcuaViewer: Don't locate files relative to binary
The logic to locate files relative to the binary is fragile. It is currently broken for CMake on Windows, and not actually implemented in qmake. Furthermore, it requires the binary directory to be writable at runtime, because additional folders will be created there. Instead, embed the files via qrc, and extract them at runtime into AppLocalDataLocation, which we know we can read/write to. Pick-to: 6.4 6.5 Fixes: QTBUG-109097 Change-Id: Ia6994339f4eba94ee6ef0cd82eadcc72563b7d47 Reviewed-by: Ivan Solovev <ivan.solovev@qt.io>
-rw-r--r--examples/opcua/opcuaviewer/CMakeLists.txt14
-rw-r--r--examples/opcua/opcuaviewer/mainwindow.cpp92
-rw-r--r--examples/opcua/opcuaviewer/mainwindow.h2
-rw-r--r--examples/opcua/opcuaviewer/opcuaviewer.pro12
-rw-r--r--src/opcua/doc/src/security.qdoc7
5 files changed, 73 insertions, 54 deletions
diff --git a/examples/opcua/opcuaviewer/CMakeLists.txt b/examples/opcua/opcuaviewer/CMakeLists.txt
index 08776be..1445a85 100644
--- a/examples/opcua/opcuaviewer/CMakeLists.txt
+++ b/examples/opcua/opcuaviewer/CMakeLists.txt
@@ -14,9 +14,6 @@ find_package(Qt6 REQUIRED COMPONENTS Core Gui OpcUa Widgets)
qt_standard_project_setup()
-file(COPY "${CMAKE_CURRENT_SOURCE_DIR}/pki"
- DESTINATION "${CMAKE_CURRENT_BINARY_DIR}")
-
qt_add_executable(opcuaviewer
certificatedialog.cpp certificatedialog.h certificatedialog.ui
main.cpp
@@ -25,6 +22,17 @@ qt_add_executable(opcuaviewer
treeitem.cpp treeitem.h
)
+qt_add_resources(opcuaviewer "pki"
+ PREFIX /
+ FILES
+ pki/own/certs/opcuaviewer.der
+ pki/own/private/opcuaviewer.pem
+ pki/trusted/certs/3d8ec65c47524d6ad67bed912c19a895.der
+ pki/trusted/certs/ca.der
+ pki/trusted/certs/open62541-testserver.der
+ pki/trusted/crl/ca.crl.pem
+)
+
set_target_properties(opcuaviewer PROPERTIES
WIN32_EXECUTABLE TRUE
MACOSX_BUNDLE TRUE
diff --git a/examples/opcua/opcuaviewer/mainwindow.cpp b/examples/opcua/opcuaviewer/mainwindow.cpp
index b05605f..00d6e55 100644
--- a/examples/opcua/opcuaviewer/mainwindow.cpp
+++ b/examples/opcua/opcuaviewer/mainwindow.cpp
@@ -9,6 +9,7 @@
#include <QApplication>
#include <QDir>
#include <QMessageBox>
+#include <QStandardPaths>
#include <QTextCharFormat>
#include <QTextBlock>
#include <QOpcUaProvider>
@@ -117,23 +118,51 @@ MainWindow::~MainWindow()
delete ui;
}
+static bool copyDirRecursively(const QString &from, const QString &to)
+{
+ const QDir srcDir(from);
+ const QDir targetDir(to);
+ if (!QDir().mkpath(to))
+ return false;
+
+ const QFileInfoList infos =
+ srcDir.entryInfoList(QDir::Dirs | QDir::Files | QDir::NoDotAndDotDot);
+ for (const QFileInfo &info : infos) {
+ const QString srcItemPath = info.absoluteFilePath();
+ const QString dstItemPath = targetDir.absoluteFilePath(info.fileName());
+ if (info.isDir()) {
+ if (!copyDirRecursively(srcItemPath, dstItemPath))
+ return false;
+ } else if (info.isFile()) {
+ if (!QFile::copy(srcItemPath, dstItemPath))
+ return false;
+ }
+ }
+ return true;
+}
+
//! [PKI Configuration]
void MainWindow::setupPkiConfiguration()
{
- QString pkidir = QCoreApplication::applicationDirPath();
-#ifdef Q_OS_WIN
- pkidir += "../";
-#endif
- pkidir += "/pki";
- m_pkiConfig.setClientCertificateFile(pkidir + "/own/certs/opcuaviewer.der");
- m_pkiConfig.setPrivateKeyFile(pkidir + "/own/private/opcuaviewer.pem");
- m_pkiConfig.setTrustListDirectory(pkidir + "/trusted/certs");
- m_pkiConfig.setRevocationListDirectory(pkidir + "/trusted/crl");
- m_pkiConfig.setIssuerListDirectory(pkidir + "/issuers/certs");
- m_pkiConfig.setIssuerRevocationListDirectory(pkidir + "/issuers/crl");
-
- // create the folders if they don't exist yet
- createPkiFolders();
+ const QDir pkidir =
+ QDir(QStandardPaths::writableLocation(QStandardPaths::AppLocalDataLocation) + "/pki");
+
+ if (!pkidir.exists() && !copyDirRecursively(":/pki", pkidir.path()))
+ qFatal("Could not set up directory %s!", qUtf8Printable(pkidir.path()));
+
+ m_pkiConfig.setClientCertificateFile(pkidir.absoluteFilePath("own/certs/opcuaviewer.der"));
+ m_pkiConfig.setPrivateKeyFile(pkidir.absoluteFilePath("own/private/opcuaviewer.pem"));
+ m_pkiConfig.setTrustListDirectory(pkidir.absoluteFilePath("trusted/certs"));
+ m_pkiConfig.setRevocationListDirectory(pkidir.absoluteFilePath("trusted/crl"));
+ m_pkiConfig.setIssuerListDirectory(pkidir.absoluteFilePath("issuers/certs"));
+ m_pkiConfig.setIssuerRevocationListDirectory(pkidir.absoluteFilePath("issuers/crl"));
+
+ const QStringList toCreate = { m_pkiConfig.issuerListDirectory(),
+ m_pkiConfig.issuerRevocationListDirectory() };
+ for (const QString &dir : toCreate) {
+ if (!QDir().mkpath(dir))
+ qFatal("Could not create directory %s!", qUtf8Printable(dir));
+ }
}
//! [PKI Configuration]
@@ -343,41 +372,6 @@ void MainWindow::log(const QString &text, const QColor &color)
log(text, QString(), color);
}
-bool MainWindow::createPkiPath(const QString &path)
-{
- const QString msg = tr("Creating PKI path '%1': %2");
-
- QDir dir;
- const bool ret = dir.mkpath(path);
- if (ret)
- qDebug() << msg.arg(path, "SUCCESS.");
- else
- qCritical("%s", qPrintable(msg.arg(path, "FAILED.")));
-
- return ret;
-}
-
-bool MainWindow::createPkiFolders()
-{
- bool result = createPkiPath(m_pkiConfig.trustListDirectory());
- if (!result)
- return result;
-
- result = createPkiPath(m_pkiConfig.revocationListDirectory());
- if (!result)
- return result;
-
- result = createPkiPath(m_pkiConfig.issuerListDirectory());
- if (!result)
- return result;
-
- result = createPkiPath(m_pkiConfig.issuerRevocationListDirectory());
- if (!result)
- return result;
-
- return result;
-}
-
void MainWindow::showErrorDialog(QOpcUaErrorState *errorState)
{
int result = 0;
diff --git a/examples/opcua/opcuaviewer/mainwindow.h b/examples/opcua/opcuaviewer/mainwindow.h
index 1f59048..5f08f50 100644
--- a/examples/opcua/opcuaviewer/mainwindow.h
+++ b/examples/opcua/opcuaviewer/mainwindow.h
@@ -48,8 +48,6 @@ private:
void createClient();
void updateUiState();
void setupPkiConfiguration();
- bool createPkiFolders();
- bool createPkiPath(const QString &path);
private:
Ui::MainWindow *ui;
diff --git a/examples/opcua/opcuaviewer/opcuaviewer.pro b/examples/opcua/opcuaviewer/opcuaviewer.pro
index cbe8057..ca0a31a 100644
--- a/examples/opcua/opcuaviewer/opcuaviewer.pro
+++ b/examples/opcua/opcuaviewer/opcuaviewer.pro
@@ -21,3 +21,15 @@ HEADERS += \
FORMS += \
certificatedialog.ui \
mainwindow.ui \
+
+pki.files = \
+ pki/own/certs/opcuaviewer.der \
+ pki/own/private/opcuaviewer.pem \
+ pki/trusted/certs/3d8ec65c47524d6ad67bed912c19a895.der \
+ pki/trusted/certs/ca.der \
+ pki/trusted/certs/open62541-testserver.der \
+ pki/trusted/crl/ca.crl.pem
+
+pki.prefix = /
+
+RESOURCES += pki
diff --git a/src/opcua/doc/src/security.qdoc b/src/opcua/doc/src/security.qdoc
index 62656c7..cdcff38 100644
--- a/src/opcua/doc/src/security.qdoc
+++ b/src/opcua/doc/src/security.qdoc
@@ -129,7 +129,14 @@ Certificate:
\li Configure the correct Application Identity
\snippet ../../examples/opcua/opcuaviewer/mainwindow.cpp Application Identity
\li Configure PKI locations so that the SDK can find the certificate, private key, trust list etc.
+
+ See for instance the code from the \l{Qt OPC UA Viewer Example}:
\snippet ../../examples/opcua/opcuaviewer/mainwindow.cpp PKI Configuration
+
+ In the example, we extract pre-configured own and trusted certificates
+ from the Qt resource system to a writable location in the file system.
+ The remaining directories for issuer (revocation) lists are created
+ manually.
\endlist
\section2 PKI Folder Layout