summaryrefslogtreecommitdiffstats
path: root/examples
diff options
context:
space:
mode:
authorGerhard Gappmeier <gerhard.gappmeier@ascolab.com>2018-11-13 14:18:17 +0100
committerRainer Keller <Rainer.Keller@qt.io>2019-01-11 13:49:18 +0000
commit04a9a85872c2e54fe69902a308e6d4ed33ac1f19 (patch)
tree7c9ae9b62adc9a13bb06bfc51fda90970bcb2ded /examples
parent05022007770b087b2632568fcf061053f3924dcb (diff)
opcuaviewer: Add certificate dialog and trust functionality
Change-Id: Ibab6725d5047512dc8db7feb2d46f41a75054eb0 Reviewed-by: Frank Meerkoetter <frank.meerkoetter@basyskom.com>
Diffstat (limited to 'examples')
-rw-r--r--examples/opcua/opcuaviewer/certificatedialog.cpp93
-rw-r--r--examples/opcua/opcuaviewer/certificatedialog.h70
-rw-r--r--examples/opcua/opcuaviewer/certificatedialog.ui131
-rw-r--r--examples/opcua/opcuaviewer/mainwindow.cpp29
-rw-r--r--examples/opcua/opcuaviewer/mainwindow.h1
-rw-r--r--examples/opcua/opcuaviewer/opcuaviewer.pro9
6 files changed, 314 insertions, 19 deletions
diff --git a/examples/opcua/opcuaviewer/certificatedialog.cpp b/examples/opcua/opcuaviewer/certificatedialog.cpp
new file mode 100644
index 0000000..61628bc
--- /dev/null
+++ b/examples/opcua/opcuaviewer/certificatedialog.cpp
@@ -0,0 +1,93 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 Unified Automation GmbH
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the QtOpcUa module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL3$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPLv3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or later as published by the Free
+** Software Foundation and appearing in the file LICENSE.GPL included in
+** the packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "certificatedialog.h"
+#include "ui_certificatedialog.h"
+#include <QPushButton>
+
+QT_BEGIN_NAMESPACE
+
+CertificateDialog::CertificateDialog(QWidget *parent) :
+ QDialog(parent),
+ ui(new Ui::CertificateDialog)
+{
+ ui->setupUi(this);
+ connect(ui->btnTrust, &QPushButton::clicked, this, &CertificateDialog::saveCertificate);
+}
+
+CertificateDialog::~CertificateDialog()
+{
+ delete ui;
+}
+
+/** Returns 0 if the connect should be aborted, 1 if it should be resumed. */
+int CertificateDialog::showCertificate(const QString &message, const QByteArray &der, const QString &trustListLocation)
+{
+ QList<QSslCertificate> certs = QSslCertificate::fromData(der, QSsl::Der);
+
+ m_trustListLocation = trustListLocation;
+
+ // if it is a unstrusted self-signed certificate we can allow to trust it
+ if (certs.count() == 1 && certs[0].isSelfSigned()) {
+ m_cert = certs[0];
+ ui->btnTrust->setEnabled(true);
+ } else {
+ ui->btnTrust->setEnabled(false);
+ }
+
+ for (const QSslCertificate &cert : qAsConst(certs))
+ ui->certificate->appendPlainText(cert.toText());
+
+ ui->message->setText(message);
+ ui->certificate->moveCursor(QTextCursor::Start);
+ ui->certificate->ensureCursorVisible();
+
+ return exec();
+}
+
+void CertificateDialog::saveCertificate()
+{
+ const QByteArray digest = m_cert.digest();
+ const QString path = m_trustListLocation + "/" + digest.toHex() + ".der";
+
+ QFile file(path);
+ if (file.open(QIODevice::WriteOnly)) {
+ file.write(m_cert.toDer());
+ file.close();
+ }
+}
+
+QT_END_NAMESPACE
diff --git a/examples/opcua/opcuaviewer/certificatedialog.h b/examples/opcua/opcuaviewer/certificatedialog.h
new file mode 100644
index 0000000..6e82ae1
--- /dev/null
+++ b/examples/opcua/opcuaviewer/certificatedialog.h
@@ -0,0 +1,70 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 Unified Automation GmbH
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the QtOpcUa module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL3$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPLv3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or later as published by the Free
+** Software Foundation and appearing in the file LICENSE.GPL included in
+** the packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef CERTIFICATEDIALOG_H
+#define CERTIFICATEDIALOG_H
+
+#include <QDialog>
+#include <QSslCertificate>
+
+QT_BEGIN_NAMESPACE
+
+namespace Ui {
+class CertificateDialog;
+}
+
+class CertificateDialog : public QDialog
+{
+ Q_OBJECT
+
+public:
+ explicit CertificateDialog(QWidget *parent = nullptr);
+ ~CertificateDialog();
+
+ int showCertificate(const QString &message, const QByteArray &der, const QString &trustListLocation);
+
+private slots:
+ void saveCertificate();
+
+private:
+ Ui::CertificateDialog *ui;
+ QSslCertificate m_cert;
+ QString m_trustListLocation;
+};
+
+QT_END_NAMESPACE
+
+#endif // CERTIFICATEDIALOG_H
diff --git a/examples/opcua/opcuaviewer/certificatedialog.ui b/examples/opcua/opcuaviewer/certificatedialog.ui
new file mode 100644
index 0000000..0a25d2c
--- /dev/null
+++ b/examples/opcua/opcuaviewer/certificatedialog.ui
@@ -0,0 +1,131 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>CertificateDialog</class>
+ <widget class="QDialog" name="CertificateDialog">
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>720</width>
+ <height>423</height>
+ </rect>
+ </property>
+ <property name="windowTitle">
+ <string>Dialog</string>
+ </property>
+ <layout class="QVBoxLayout" name="verticalLayout">
+ <item>
+ <widget class="QLabel" name="message">
+ <property name="text">
+ <string>TextLabel</string>
+ </property>
+ <property name="alignment">
+ <set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set>
+ </property>
+ <property name="wordWrap">
+ <bool>true</bool>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QPlainTextEdit" name="certificate">
+ <property name="readOnly">
+ <bool>true</bool>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <layout class="QHBoxLayout" name="horizontalLayout">
+ <item>
+ <spacer name="horizontalSpacer">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>40</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ <item>
+ <widget class="QPushButton" name="btnIgnore">
+ <property name="text">
+ <string>Ignore Error</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QPushButton" name="btnTrust">
+ <property name="text">
+ <string>Trust Certificate</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QPushButton" name="btnCancel">
+ <property name="text">
+ <string>Cancel</string>
+ </property>
+ <property name="default">
+ <bool>true</bool>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ </layout>
+ </widget>
+ <resources/>
+ <connections>
+ <connection>
+ <sender>btnIgnore</sender>
+ <signal>clicked()</signal>
+ <receiver>CertificateDialog</receiver>
+ <slot>accept()</slot>
+ <hints>
+ <hint type="sourcelabel">
+ <x>475</x>
+ <y>402</y>
+ </hint>
+ <hint type="destinationlabel">
+ <x>374</x>
+ <y>397</y>
+ </hint>
+ </hints>
+ </connection>
+ <connection>
+ <sender>btnTrust</sender>
+ <signal>clicked()</signal>
+ <receiver>CertificateDialog</receiver>
+ <slot>accept()</slot>
+ <hints>
+ <hint type="sourcelabel">
+ <x>563</x>
+ <y>404</y>
+ </hint>
+ <hint type="destinationlabel">
+ <x>287</x>
+ <y>395</y>
+ </hint>
+ </hints>
+ </connection>
+ <connection>
+ <sender>btnCancel</sender>
+ <signal>clicked()</signal>
+ <receiver>CertificateDialog</receiver>
+ <slot>reject()</slot>
+ <hints>
+ <hint type="sourcelabel">
+ <x>670</x>
+ <y>406</y>
+ </hint>
+ <hint type="destinationlabel">
+ <x>717</x>
+ <y>395</y>
+ </hint>
+ </hints>
+ </connection>
+ </connections>
+</ui>
diff --git a/examples/opcua/opcuaviewer/mainwindow.cpp b/examples/opcua/opcuaviewer/mainwindow.cpp
index c6f9d0a..eb91531 100644
--- a/examples/opcua/opcuaviewer/mainwindow.cpp
+++ b/examples/opcua/opcuaviewer/mainwindow.cpp
@@ -50,6 +50,7 @@
#include "mainwindow.h"
#include "opcuamodel.h"
+#include "certificatedialog.h"
#include <QCoreApplication>
#include <QDir>
@@ -155,7 +156,7 @@ MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent)
widget->setLayout(vbox);
setCentralWidget(widget);
- mHost->setText("opc.tcp://localhost");
+ mHost->setText("opc.tcp://localhost:48010");
mEndpoints->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred);
updateUiState();
@@ -314,9 +315,9 @@ void MainWindow::connectToServer()
}
if (mEndpoints->currentIndex() >= 0) {
- QOpcUa::QEndpointDescription endpoint = mEndpointList[mEndpoints->currentIndex()];
+ m_endpoint = mEndpointList[mEndpoints->currentIndex()];
createClient();
- mOpcUaClient->connectToEndpoint(endpoint);
+ mOpcUaClient->connectToEndpoint(m_endpoint);
}
}
@@ -450,8 +451,8 @@ bool MainWindow::createPkiFolders()
void MainWindow::showErrorDialog(QOpcUaErrorState *errorState)
{
QString msg;
- QMessageBox::StandardButtons buttons = QMessageBox::Ok;
- QMessageBox::StandardButton defaultButton = QMessageBox::Ok;
+ CertificateDialog dlg;
+ int result = 0;
const QString statuscode = QOpcUa::statusToString(errorState->errorCode());
@@ -463,29 +464,23 @@ void MainWindow::showErrorDialog(QOpcUaErrorState *errorState)
switch (errorState->connectionStep()) {
case QOpcUaErrorState::ConnectionStep::CertificateValidation:
msg += tr("Server certificate validation failed with error 0x%1 (%2).\nClick 'Abort' to abort the connect, or 'Ignore' to continue connecting.")
- .arg(static_cast<ulong>(errorState->errorCode()), 8, 16, QLatin1Char('0')).arg(statuscode);
- buttons = QMessageBox::Ignore | QMessageBox::Abort;
- defaultButton = QMessageBox::Abort;
+ .arg(static_cast<ulong>(errorState->errorCode()), 8, 16, QLatin1Char('0')).arg(statuscode);
+ result = dlg.showCertificate(msg, m_endpoint.serverCertificate(), m_pkiConfig.trustListLocation());
+ errorState->setIgnoreError(result == 1);
break;
case QOpcUaErrorState::ConnectionStep::OpenSecureChannel:
msg += tr("OpenSecureChannel failed with error 0x%1 (%2).").arg(errorState->errorCode(), 8, 16, QLatin1Char('0')).arg(statuscode);
+ QMessageBox::warning(this, tr("Connection Error"), msg);
break;
case QOpcUaErrorState::ConnectionStep::CreateSession:
msg += tr("CreateSession failed with error 0x%1 (%2).").arg(errorState->errorCode(), 8, 16, QLatin1Char('0')).arg(statuscode);
+ QMessageBox::warning(this, tr("Connection Error"), msg);
break;
case QOpcUaErrorState::ConnectionStep::ActivateSession:
msg += tr("ActivateSession failed with error 0x%1 (%2).").arg(errorState->errorCode(), 8, 16, QLatin1Char('0')).arg(statuscode);
+ QMessageBox::warning(this, tr("Connection Error"), msg);
break;
}
-
- QMessageBox::StandardButton result = QMessageBox::warning(
- this,
- tr("Connect Error"),
- msg,
- buttons,
- defaultButton);
-
- errorState->setIgnoreError(result == QMessageBox::Ignore);
}
QT_END_NAMESPACE
diff --git a/examples/opcua/opcuaviewer/mainwindow.h b/examples/opcua/opcuaviewer/mainwindow.h
index d7056d1..1457e3b 100644
--- a/examples/opcua/opcuaviewer/mainwindow.h
+++ b/examples/opcua/opcuaviewer/mainwindow.h
@@ -109,6 +109,7 @@ private:
bool mClientConnected;
QOpcUaApplicationIdentity m_identity;
QOpcUaPkiConfiguration m_pkiConfig;
+ QOpcUa::QEndpointDescription m_endpoint; // current endpoint used to connect
};
QT_END_NAMESPACE
diff --git a/examples/opcua/opcuaviewer/opcuaviewer.pro b/examples/opcua/opcuaviewer/opcuaviewer.pro
index 15e55ce..ce06229 100644
--- a/examples/opcua/opcuaviewer/opcuaviewer.pro
+++ b/examples/opcua/opcuaviewer/opcuaviewer.pro
@@ -7,7 +7,8 @@ INCLUDEPATH += \
SOURCES += main.cpp \
mainwindow.cpp \
opcuamodel.cpp \
- treeitem.cpp
+ treeitem.cpp \
+ certificatedialog.cpp
#install
target.path = $$[QT_INSTALL_EXAMPLES]/opcua/opcuaviewer
@@ -16,4 +17,8 @@ INSTALLS += target
HEADERS += \
mainwindow.h \
opcuamodel.h \
- treeitem.h
+ treeitem.h \
+ certificatedialog.h
+
+FORMS += \
+ certificatedialog.ui